136090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet/* 236090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet * Copyright (C) 2015 The Android Open Source Project 336090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet * 436090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet * Licensed under the Apache License, Version 2.0 (the "License"); 536090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet * you may not use this file except in compliance with the License. 636090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet * You may obtain a copy of the License at 736090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet * 836090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet * http://www.apache.org/licenses/LICENSE-2.0 936090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet * 1036090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet * Unless required by applicable law or agreed to in writing, software 1136090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet * distributed under the License is distributed on an "AS IS" BASIS, 1236090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1336090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet * See the License for the specific language governing permissions and 1436090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet * limitations under the License. 1536090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet */ 1636090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet 1736090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet#include <algorithm> 1812398d81f32e5e0479d02b8608a83c75cd991bb3Yang Ni#include <climits> 1936090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet#include <iostream> 2036090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet#include <iterator> 2136090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet#include <sstream> 2236090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet 2336090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet#include "Generator.h" 2436090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet#include "Specification.h" 2536090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet#include "Utilities.h" 2636090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet 2736090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouilletusing namespace std; 2836090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet 2912398d81f32e5e0479d02b8608a83c75cd991bb3Yang Niconst unsigned int kMinimumApiLevelForTests = 11; 3012398d81f32e5e0479d02b8608a83c75cd991bb3Yang Niconst unsigned int kApiLevelWithFirst64Bit = 21; 3136090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet 3236090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet// Used to map the built-in types to their mangled representations 3336090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouilletstruct BuiltInMangling { 3436090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet const char* token[3]; // The last two entries can be nullptr 3536090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet const char* equivalence; // The mangled equivalent 3636090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet}; 3736090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet 3836090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc BrouilletBuiltInMangling builtInMangling[] = { 3936090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet {{"long", "long"}, "x"}, 4036090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet {{"unsigned", "long", "long"}, "y"}, 4136090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet {{"long"}, "l"}, 4236090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet {{"unsigned", "long"}, "m"}, 4336090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet {{"int"}, "i"}, 4436090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet {{"unsigned", "int"}, "j"}, 4536090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet {{"short"}, "s"}, 4636090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet {{"unsigned", "short"}, "t"}, 4736090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet {{"char"}, "c"}, 4836090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet {{"unsigned", "char"}, "h"}, 4936090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet {{"signed", "char"}, "a"}, 5036090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet {{"void"}, "v"}, 5136090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet {{"wchar_t"}, "w"}, 5236090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet {{"bool"}, "b"}, 5336090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet {{"__fp16"}, "Dh"}, 5436090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet {{"float"}, "f"}, 5536090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet {{"double"}, "d"}, 5636090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet}; 5736090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet 5836090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet/* For the given API level and bitness (e.g. 32 or 64 bit), try to find a 5936090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet * substitution for the provided type name, as would be done (mostly) by a 6036090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet * preprocessor. Returns empty string if there's no substitution. 6136090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet */ 6212398d81f32e5e0479d02b8608a83c75cd991bb3Yang Nistatic string findSubstitute(const string& typeName, unsigned int apiLevel, int intSize) { 6336090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet const auto& types = systemSpecification.getTypes(); 6436090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet const auto type = types.find(typeName); 6536090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet if (type != types.end()) { 6636090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet for (TypeSpecification* spec : type->second->getSpecifications()) { 6736090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet // Verify this specification applies 6836090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet const VersionInfo info = spec->getVersionInfo(); 6936090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet if (!info.includesVersion(apiLevel) || (info.intSize != 0 && info.intSize != intSize)) { 7036090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet continue; 7136090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet } 7236090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet switch (spec->getKind()) { 7336090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet case SIMPLE: { 74ca51c78b9e3097ee31dd24cdc5982f550ee563d1Stephen Hines return spec->getSimpleType(); 75ca51c78b9e3097ee31dd24cdc5982f550ee563d1Stephen Hines } 76ca51c78b9e3097ee31dd24cdc5982f550ee563d1Stephen Hines case RS_OBJECT: { 77ca51c78b9e3097ee31dd24cdc5982f550ee563d1Stephen Hines // Do nothing for RS object types. 7836090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet break; 7936090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet } 8036090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet case STRUCT: { 81ca51c78b9e3097ee31dd24cdc5982f550ee563d1Stephen Hines return spec->getStructName(); 8236090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet } 8336090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet case ENUM: 8436090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet // Do nothing 8536090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet break; 8636090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet } 8736090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet } 8836090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet } 8936090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet return ""; 9036090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet} 9136090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet 9236090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet/* Expand the typedefs found in 'type' into their equivalents and tokenize 9336090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet * the resulting list. 'apiLevel' and 'intSize' specifies the API level and bitness 9436090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet * we are currently processing. 9536090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet */ 969309a0665a4866f708db9ae67e43b5ea6a27cf27Dean De Leolist<string> expandTypedefs(const string type, unsigned int apiLevel, int intSize, string& vectorSize) { 9736090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet // Split the string in tokens. 9836090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet istringstream stream(type); 9936090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet list<string> tokens{istream_iterator<string>{stream}, istream_iterator<string>{}}; 10036090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet // Try to substitue each token. 10136090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet for (auto i = tokens.begin(); i != tokens.end();) { 10236090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet const string substitute = findSubstitute(*i, apiLevel, intSize); 10336090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet if (substitute.empty()) { 10436090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet // No substitution possible, just go to the next token. 10536090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet i++; 10636090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet } else { 10736090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet // Split the replacement string in tokens. 10836090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet istringstream stream(substitute); 1099309a0665a4866f708db9ae67e43b5ea6a27cf27Dean De Leo 1109309a0665a4866f708db9ae67e43b5ea6a27cf27Dean De Leo /* Get the new vector size. This is for the case of the type being for example 1119309a0665a4866f708db9ae67e43b5ea6a27cf27Dean De Leo * rs_quaternion* == float4*, where we need the vector size to be 4 for the 1129309a0665a4866f708db9ae67e43b5ea6a27cf27Dean De Leo * purposes of mangling, although the parameter itself is not determined to be 1139309a0665a4866f708db9ae67e43b5ea6a27cf27Dean De Leo * a vector. */ 1149309a0665a4866f708db9ae67e43b5ea6a27cf27Dean De Leo string unused; 1159309a0665a4866f708db9ae67e43b5ea6a27cf27Dean De Leo string newVectorSize; 1169309a0665a4866f708db9ae67e43b5ea6a27cf27Dean De Leo getVectorSizeAndBaseType(*i, newVectorSize, unused); 1179309a0665a4866f708db9ae67e43b5ea6a27cf27Dean De Leo 1189309a0665a4866f708db9ae67e43b5ea6a27cf27Dean De Leo istringstream vectorSizeBuf(vectorSize); 1199309a0665a4866f708db9ae67e43b5ea6a27cf27Dean De Leo int vectorSizeVal; 1209309a0665a4866f708db9ae67e43b5ea6a27cf27Dean De Leo vectorSizeBuf >> vectorSizeVal; 1219309a0665a4866f708db9ae67e43b5ea6a27cf27Dean De Leo 1229309a0665a4866f708db9ae67e43b5ea6a27cf27Dean De Leo istringstream newVectorSizeBuf(newVectorSize); 1239309a0665a4866f708db9ae67e43b5ea6a27cf27Dean De Leo int newVectorSizeVal; 1249309a0665a4866f708db9ae67e43b5ea6a27cf27Dean De Leo newVectorSizeBuf >> newVectorSizeVal; 1259309a0665a4866f708db9ae67e43b5ea6a27cf27Dean De Leo 1269309a0665a4866f708db9ae67e43b5ea6a27cf27Dean De Leo if (newVectorSizeVal > vectorSizeVal) 1279309a0665a4866f708db9ae67e43b5ea6a27cf27Dean De Leo vectorSize = newVectorSize; 1289309a0665a4866f708db9ae67e43b5ea6a27cf27Dean De Leo 12936090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet list<string> newTokens{istream_iterator<string>{stream}, istream_iterator<string>{}}; 13036090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet // Replace the token with the substitution. Don't advance, as the new substitution 13136090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet // might itself be replaced. 13236090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet auto prev = i; 13336090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet --prev; 13436090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet tokens.insert(i, newTokens.begin(), newTokens.end()); 13536090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet tokens.erase(i); 13636090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet advance(i, -newTokens.size()); 13736090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet } 13836090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet } 13936090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet return tokens; 14036090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet} 14136090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet 14236090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet// Remove the first element of the list if it equals 'prefix'. Return true in that case. 14336090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouilletstatic bool eatFront(list<string>* tokens, const char* prefix) { 14436090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet if (tokens->front() == prefix) { 14536090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet tokens->pop_front(); 14636090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet return true; 14736090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet } 14836090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet return false; 14936090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet} 15036090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet 15136090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet/* Search the table of translations for the built-ins for the mangling that 15236090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet * corresponds to this list of tokens. If a match is found, consume these tokens 15336090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet * and return a pointer to the string. If not, return nullptr. 15436090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet */ 15536090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouilletstatic const char* findManglingOfBuiltInType(list<string>* tokens) { 15636090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet for (const BuiltInMangling& a : builtInMangling) { 15736090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet auto t = tokens->begin(); 15836090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet auto end = tokens->end(); 15936090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet bool match = true; 16036090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet // We match up to three tokens. 16136090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet for (int i = 0; i < 3; i++) { 16236090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet if (!a.token[i]) { 16336090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet // No more tokens 16436090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet break; 16536090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet } 16636090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet if (t == end || *t++ != a.token[i]) { 16736090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet match = false; 16836090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet } 16936090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet } 17036090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet if (match) { 17136090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet tokens->erase(tokens->begin(), t); 17236090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet return a.equivalence; 17336090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet } 17436090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet } 17536090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet return nullptr; 17636090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet} 17736090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet 17836090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet// Mangle a long name by prefixing it with its length, e.g. "13rs_allocation". 17936090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouilletstatic inline string mangleLongName(const string& name) { 18036090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet return to_string(name.size()) + name; 18136090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet} 18236090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet 18336090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet/* Mangle the type name that's represented by the vector size and list of tokens. 18436090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet * The mangling will be returned in full form in 'mangling'. 'compressedMangling' 18536090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet * will have the compressed equivalent. This is built using the 'previousManglings' 18636090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet * list. false is returned if an error is encountered. 18736090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet * 18836090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet * This function is recursive because compression is possible at each level of the definition. 18936090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet * See http://mentorembedded.github.io/cxx-abi/abi.html#mangle.type for a description 19036090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet * of the Itanium mangling used by llvm. 19136090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet * 19236090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet * This function mangles correctly the types currently used by RenderScript. It does 19336090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet * not currently mangle more complicated types like function pointers, namespaces, 19436090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet * or other C++ types. In particular, we don't deal correctly with parenthesis. 19536090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet */ 19636090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouilletstatic bool mangleType(string vectorSize, list<string>* tokens, vector<string>* previousManglings, 19736090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet string* mangling, string* compressedMangling) { 19836090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet string delta; // The part of the mangling we're generating for this recursion. 19936090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet bool isTerminal = false; // True if this iteration parses a terminal node in the production. 20036090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet bool canBeCompressed = true; // Will be false for manglings of builtins. 20136090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet 20236090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet if (tokens->back() == "*") { 20336090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet delta = "P"; 20436090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet tokens->pop_back(); 20536090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet } else if (eatFront(tokens, "const")) { 20636090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet delta = "K"; 20736090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet } else if (eatFront(tokens, "volatile")) { 20836090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet delta = "V"; 20936090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet } else if (vectorSize != "1" && vectorSize != "") { 21036090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet // For vector, prefix with the abbreviation for a vector, including the size. 21136090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet delta = "Dv" + vectorSize + "_"; 21236090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet vectorSize.clear(); // Reset to mark the size as consumed. 21336090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet } else if (eatFront(tokens, "struct")) { 21436090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet // For a structure, we just use the structure name 21536090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet if (tokens->size() == 0) { 21636090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet cerr << "Expected a name after struct\n"; 21736090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet return false; 21836090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet } 21936090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet delta = mangleLongName(tokens->front()); 22036090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet isTerminal = true; 22136090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet tokens->pop_front(); 222fab6947a18e00964f79e6c802dc70bbaed981730Yang Ni } else if (eatFront(tokens, "...")) { 223fab6947a18e00964f79e6c802dc70bbaed981730Yang Ni delta = "z"; 224fab6947a18e00964f79e6c802dc70bbaed981730Yang Ni isTerminal = true; 22536090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet } else { 22636090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet const char* c = findManglingOfBuiltInType(tokens); 22736090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet if (c) { 22836090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet // It's a basic type. We don't use those directly for compression. 22936090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet delta = c; 23036090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet isTerminal = true; 23136090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet canBeCompressed = false; 23236090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet } else if (tokens->size() > 0) { 23336090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet // It's a complex type name. 23436090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet delta = mangleLongName(tokens->front()); 23536090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet isTerminal = true; 23636090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet tokens->pop_front(); 23736090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet } 23836090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet } 23936090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet 24036090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet if (isTerminal) { 24136090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet // If we're the terminal node, there should be nothing left to mangle. 24236090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet if (tokens->size() > 0) { 24336090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet cerr << "Expected nothing else but found"; 24436090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet for (const auto& t : *tokens) { 24536090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet cerr << " " << t; 24636090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet } 24736090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet cerr << "\n"; 24836090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet return false; 24936090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet } 25036090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet *mangling = delta; 25136090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet *compressedMangling = delta; 25236090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet } else { 25336090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet // We're not terminal. Recurse and prefix what we've translated this pass. 25436090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet if (tokens->size() == 0) { 25536090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet cerr << "Expected a more complete type\n"; 25636090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet return false; 25736090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet } 25836090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet string rest, compressedRest; 25936090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet if (!mangleType(vectorSize, tokens, previousManglings, &rest, &compressedRest)) { 26036090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet return false; 26136090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet } 26236090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet *mangling = delta + rest; 26336090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet *compressedMangling = delta + compressedRest; 26436090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet } 26536090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet 26636090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet /* If it's a built-in type, we don't look at previously emitted ones and we 26736090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet * don't keep track of it. 26836090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet */ 26936090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet if (!canBeCompressed) { 27036090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet return true; 27136090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet } 27236090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet 27336090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet // See if we've encountered this mangling before. 27436090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet for (size_t i = 0; i < previousManglings->size(); ++i) { 27536090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet if ((*previousManglings)[i] == *mangling) { 27636090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet // We have a match, construct an index reference to that previously emitted mangling. 27736090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet ostringstream stream2; 27836090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet stream2 << 'S'; 27936090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet if (i > 0) { 28036090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet stream2 << (char)('0' + i - 1); 28136090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet } 28236090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet stream2 << '_'; 28336090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet *compressedMangling = stream2.str(); 28436090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet return true; 28536090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet } 28636090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet } 28736090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet 28836090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet // We have not encountered this before. Add it to the list. 28936090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet previousManglings->push_back(*mangling); 29036090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet return true; 29136090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet} 29236090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet 29336090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet// Write to the stream the mangled representation of each parameter. 29436090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouilletstatic bool writeParameters(ostringstream* stream, const std::vector<ParameterDefinition*>& params, 29512398d81f32e5e0479d02b8608a83c75cd991bb3Yang Ni unsigned int apiLevel, int intSize) { 29636090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet if (params.empty()) { 29736090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet *stream << "v"; 29836090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet return true; 29936090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet } 30036090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet /* We keep track of the previously generated parameter types, as type mangling 30136090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet * is compressed by reusing previous manglings. 30236090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet */ 30336090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet vector<string> previousManglings; 30436090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet for (ParameterDefinition* p : params) { 30536090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet // Expand the typedefs and create a tokenized list. 3069309a0665a4866f708db9ae67e43b5ea6a27cf27Dean De Leo string vectorSize = p->mVectorSize; 3079309a0665a4866f708db9ae67e43b5ea6a27cf27Dean De Leo list<string> tokens = expandTypedefs(p->rsType, apiLevel, intSize, vectorSize); 30836090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet if (p->isOutParameter) { 30936090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet tokens.push_back("*"); 31036090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet } 31136090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet string mangling, compressedMangling; 3129309a0665a4866f708db9ae67e43b5ea6a27cf27Dean De Leo 3139309a0665a4866f708db9ae67e43b5ea6a27cf27Dean De Leo if (!mangleType(vectorSize, &tokens, &previousManglings, &mangling, 31436090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet &compressedMangling)) { 31536090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet return false; 31636090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet } 31736090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet *stream << compressedMangling; 31836090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet } 31936090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet return true; 32036090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet} 32136090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet 32236090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet/* Add the mangling for this permutation of the function. apiLevel and intSize is used 32336090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet * to select the correct type when expanding complex type. 32436090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet */ 32536090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouilletstatic bool addFunctionManglingToSet(const Function& function, 32636090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet const FunctionPermutation& permutation, bool overloadable, 32712398d81f32e5e0479d02b8608a83c75cd991bb3Yang Ni unsigned int apiLevel, int intSize, set<string>* allManglings) { 32836090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet const string& functionName = permutation.getName(); 32936090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet string mangling; 33036090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet if (overloadable) { 33136090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet ostringstream stream; 33236090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet stream << "_Z" << mangleLongName(functionName); 33336090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet if (!writeParameters(&stream, permutation.getParams(), apiLevel, intSize)) { 33436090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet cerr << "Error mangling " << functionName << ". See above message.\n"; 33536090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet return false; 33636090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet } 33736090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet mangling = stream.str(); 33836090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet } else { 33936090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet mangling = functionName; 34036090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet } 34136090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet allManglings->insert(mangling); 34236090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet return true; 34336090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet} 34436090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet 34536090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet/* Add to the set the mangling of each function prototype that can be generated from this 34636090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet * specification, i.e. for all the versions covered and for 32/64 bits. We call this 34736090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet * for each API level because the implementation of a type may have changed in the range 34836090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet * of API levels covered. 34936090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet */ 35036090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouilletstatic bool addManglingsForSpecification(const Function& function, 35112398d81f32e5e0479d02b8608a83c75cd991bb3Yang Ni const FunctionSpecification& spec, unsigned int lastApiLevel, 35236090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet set<string>* allManglings) { 35336090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet // If the function is inlined, we won't generate an unresolved external for that. 35436090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet if (spec.hasInline()) { 35536090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet return true; 35636090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet } 35736090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet const VersionInfo info = spec.getVersionInfo(); 35812398d81f32e5e0479d02b8608a83c75cd991bb3Yang Ni unsigned int minApiLevel, maxApiLevel; 35912398d81f32e5e0479d02b8608a83c75cd991bb3Yang Ni minApiLevel = info.minVersion ? info.minVersion : kMinimumApiLevelForTests; 36012398d81f32e5e0479d02b8608a83c75cd991bb3Yang Ni maxApiLevel = info.maxVersion ? info.maxVersion : lastApiLevel; 36136090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet const bool overloadable = spec.isOverloadable(); 36236090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet 36336090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet /* We track success rather than aborting early in case of failure so that we 36436090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet * generate all the error messages. 36536090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet */ 36636090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet bool success = true; 36712398d81f32e5e0479d02b8608a83c75cd991bb3Yang Ni // Use 64-bit integer here for the loop count to avoid overflow 36812398d81f32e5e0479d02b8608a83c75cd991bb3Yang Ni // (minApiLevel == maxApiLevel == UINT_MAX for unreleased API) 36912398d81f32e5e0479d02b8608a83c75cd991bb3Yang Ni for (int64_t apiLevel = minApiLevel; apiLevel <= maxApiLevel; ++apiLevel) { 37036090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet for (auto permutation : spec.getPermutations()) { 37136090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet if (info.intSize == 0 || info.intSize == 32) { 37236090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet if (!addFunctionManglingToSet(function, *permutation, overloadable, apiLevel, 32, 37336090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet allManglings)) { 37436090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet success = false; 37536090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet } 37636090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet } 37736090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet if (apiLevel >= kApiLevelWithFirst64Bit && (info.intSize == 0 || info.intSize == 64)) { 37836090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet if (!addFunctionManglingToSet(function, *permutation, overloadable, apiLevel, 64, 37936090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet allManglings)) { 38036090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet success = false; 38136090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet } 38236090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet } 38336090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet } 38436090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet } 38536090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet return success; 38636090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet} 38736090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet 38836090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet/* Generate the white list file of the mangled function prototypes. This generated list is used 38936090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet * to validate unresolved external references. 'lastApiLevel' is the largest api level found in 39036090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet * all spec files. 39136090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet */ 39212398d81f32e5e0479d02b8608a83c75cd991bb3Yang Nistatic bool generateWhiteListFile(unsigned int lastApiLevel) { 39336090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet bool success = true; 39436090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet // We generate all the manglings in a set to remove duplicates and to order them. 39536090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet set<string> allManglings; 39636090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet for (auto f : systemSpecification.getFunctions()) { 39736090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet const Function* function = f.second; 39836090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet for (auto spec : function->getSpecifications()) { 39912398d81f32e5e0479d02b8608a83c75cd991bb3Yang Ni // Compiler intrinsics are not runtime APIs. Do not include them in the whitelist. 40012398d81f32e5e0479d02b8608a83c75cd991bb3Yang Ni if (spec->isIntrinsic()) { 40112398d81f32e5e0479d02b8608a83c75cd991bb3Yang Ni continue; 40212398d81f32e5e0479d02b8608a83c75cd991bb3Yang Ni } 40336090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet if (!addManglingsForSpecification(*function, *spec, lastApiLevel, &allManglings)) { 40436090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet success = false; // We continue so we can generate all errors. 40536090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet } 40636090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet } 40736090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet } 40836090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet 40936090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet if (success) { 41036090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet GeneratedFile file; 41136090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet if (!file.start(".", "RSStubsWhiteList.cpp")) { 41236090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet return false; 41336090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet } 41436090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet 41536090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet file.writeNotices(); 41636090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet file << "#include \"RSStubsWhiteList.h\"\n\n"; 41736090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet file << "std::vector<std::string> stubList = {\n"; 41836090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet for (const auto& e : allManglings) { 41936090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet file << "\"" << e << "\",\n"; 42036090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet } 42136090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet file << "};\n"; 42236090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet } 42336090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet return success; 42436090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet} 42536090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet 42636090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet// Add a uniquely named variable definition to the file and return its name. 42736090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouilletstatic const string addVariable(GeneratedFile* file, unsigned int* variableNumber) { 42836090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet const string name = "buf" + to_string((*variableNumber)++); 42936090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet /* Some data structures like rs_tm can't be exported. We'll just use a dumb buffer 43036090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet * and cast its address later on. 43136090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet */ 43236090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet *file << "char " << name << "[200];\n"; 43336090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet return name; 43436090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet} 43536090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet 43636090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet/* Write to the file the globals needed to make the call for this permutation. The actual 43736090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet * call is stored in 'calls', as we'll need to generate all the global variable declarations 43836090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet * before the function definition. 43936090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet */ 44036090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouilletstatic void generateTestCall(GeneratedFile* file, ostringstream* calls, 44136090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet unsigned int* variableNumber, const Function& function, 44236090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet const FunctionPermutation& permutation) { 44336090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet *calls << " "; 44436090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet 44536090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet // Handle the return type. 44636090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet const auto ret = permutation.getReturn(); 44736090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet if (ret && ret->rsType != "void" && ret->rsType != "const void") { 44836090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet *calls << "*(" << ret->rsType << "*)" << addVariable(file, variableNumber) << " = "; 44936090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet } 45036090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet 45136090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet *calls << permutation.getName() << "("; 45236090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet 45336090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet // Generate the arguments. 45436090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet const char* separator = ""; 45536090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet for (auto p : permutation.getParams()) { 45636090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet *calls << separator; 45736090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet if (p->rsType == "rs_kernel_context") { 4588ba2310e61702f5d2dd6a30eb2f299c282ab55d6Yang Ni // Special case for the kernel context, as it has a special existence. 4594324eec445c6882dce89a24765482293ed31914eJean-Luc Brouillet *calls << "context"; 4608ba2310e61702f5d2dd6a30eb2f299c282ab55d6Yang Ni } else if (p->rsType == "...") { 4618ba2310e61702f5d2dd6a30eb2f299c282ab55d6Yang Ni // Special case for varargs. No need for casting. 4628ba2310e61702f5d2dd6a30eb2f299c282ab55d6Yang Ni *calls << addVariable(file, variableNumber); 46336090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet } else if (p->isOutParameter) { 46436090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet *calls << "(" << p->rsType << "*) " << addVariable(file, variableNumber); 46536090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet } else { 46636090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet *calls << "*(" << p->rsType << "*)" << addVariable(file, variableNumber); 46736090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet } 46836090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet separator = ", "; 46936090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet } 47036090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet *calls << ");\n"; 47136090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet} 47236090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet 47336090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet/* Generate a test file that will be used in the frameworks/compile/slang/tests unit tests. 47436090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet * This file tests that all RenderScript APIs can be called for the specified API level. 47536090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet * To avoid the compiler agressively pruning out our calls, we use globals as inputs and outputs. 47636090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet * 47736090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet * Since some structures can't be defined at the global level, we use casts of simple byte 47836090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet * buffers to get around that restriction. 47936090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet * 48036090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet * This file can be used to verify the white list that's also generated in this file. To do so, 48136090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet * run "llvm-nm -undefined-only -just-symbol-name" on the resulting bit code. 48236090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet */ 48312398d81f32e5e0479d02b8608a83c75cd991bb3Yang Nistatic bool generateApiTesterFile(const string& slangTestDirectory, unsigned int apiLevel) { 48436090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet GeneratedFile file; 48536090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet if (!file.start(slangTestDirectory, "all" + to_string(apiLevel) + ".rs")) { 48636090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet return false; 48736090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet } 48836090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet 48936090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet /* This unusual comment is used by slang/tests/test.py to know which parameter to pass 49036090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet * to llvm-rs-cc when compiling the test. 49136090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet */ 49236090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet file << "// -target-api " << apiLevel << " -Wno-deprecated-declarations\n"; 49336090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet 49436090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet file.writeNotices(); 49536090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet file << "#pragma version(1)\n"; 49636090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet file << "#pragma rs java_package_name(com.example.renderscript.testallapi)\n\n"; 49736090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet if (apiLevel < 23) { // All rs_graphics APIs were deprecated in api level 23. 49836090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet file << "#include \"rs_graphics.rsh\"\n\n"; 49936090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet } 50036090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet 50136090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet /* The code below emits globals and calls to functions in parallel. We store 50236090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet * the calls in a stream so that we can emit them in the file in the proper order. 50336090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet */ 50436090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet ostringstream calls; 50536090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet unsigned int variableNumber = 0; // Used to generate unique names. 50636090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet for (auto f : systemSpecification.getFunctions()) { 50736090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet const Function* function = f.second; 50836090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet for (auto spec : function->getSpecifications()) { 50912398d81f32e5e0479d02b8608a83c75cd991bb3Yang Ni // Do not include internal APIs in the API tests. 51012398d81f32e5e0479d02b8608a83c75cd991bb3Yang Ni if (spec->isInternal()) { 51112398d81f32e5e0479d02b8608a83c75cd991bb3Yang Ni continue; 51212398d81f32e5e0479d02b8608a83c75cd991bb3Yang Ni } 51336090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet VersionInfo info = spec->getVersionInfo(); 51436090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet if (!info.includesVersion(apiLevel)) { 51536090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet continue; 51636090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet } 51736090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet if (info.intSize == 32) { 51836090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet calls << "#ifndef __LP64__\n"; 51936090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet } else if (info.intSize == 64) { 52036090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet calls << "#ifdef __LP64__\n"; 52136090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet } 52236090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet for (auto permutation : spec->getPermutations()) { 5235b93491dbe4637bda19a6a16640e8cb842211e67Pirama Arumuga Nainar // http://b/27358969 Do not test rsForEach in the all-api test. 5245b93491dbe4637bda19a6a16640e8cb842211e67Pirama Arumuga Nainar if (apiLevel >= 24 && permutation->getName().compare(0, 9, "rsForEach") == 0) 5255b93491dbe4637bda19a6a16640e8cb842211e67Pirama Arumuga Nainar continue; 52636090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet generateTestCall(&file, &calls, &variableNumber, *function, *permutation); 52736090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet } 52836090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet if (info.intSize != 0) { 52936090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet calls << "#endif\n"; 53036090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet } 53136090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet } 53236090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet } 53336090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet file << "\n"; 53436090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet 53536090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet // Modify the style of kernel as required by the API level. 53636090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet if (apiLevel >= 23) { 5374324eec445c6882dce89a24765482293ed31914eJean-Luc Brouillet file << "void RS_KERNEL test(int in, rs_kernel_context context) {\n"; 53836090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet } else if (apiLevel >= 17) { 53936090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet file << "void RS_KERNEL test(int in) {\n"; 54036090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet } else { 54136090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet file << "void root(const int* in) {\n"; 54236090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet } 54336090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet file << calls.str(); 54436090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet file << "}\n"; 54536090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet 54636090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet return true; 54736090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet} 54836090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet 54912398d81f32e5e0479d02b8608a83c75cd991bb3Yang Nibool generateStubsWhiteList(const string& slangTestDirectory, unsigned int maxApiLevel) { 55012398d81f32e5e0479d02b8608a83c75cd991bb3Yang Ni unsigned int lastApiLevel = min(systemSpecification.getMaximumApiLevel(), maxApiLevel); 55136090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet if (!generateWhiteListFile(lastApiLevel)) { 55236090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet return false; 55336090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet } 55436090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet // Generate a test file for each apiLevel. 55512398d81f32e5e0479d02b8608a83c75cd991bb3Yang Ni for (unsigned int i = kMinimumApiLevelForTests; i <= lastApiLevel; ++i) { 55636090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet if (!generateApiTesterFile(slangTestDirectory, i)) { 55736090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet return false; 55836090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet } 55936090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet } 56036090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet return true; 56136090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet} 562