GenerateStubsWhiteList.cpp revision 12398d81f32e5e0479d02b8608a83c75cd991bb3
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 */ 9612398d81f32e5e0479d02b8608a83c75cd991bb3Yang Nilist<string> expandTypedefs(const string type, unsigned int apiLevel, int intSize) { 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); 10936090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet list<string> newTokens{istream_iterator<string>{stream}, istream_iterator<string>{}}; 11036090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet // Replace the token with the substitution. Don't advance, as the new substitution 11136090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet // might itself be replaced. 11236090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet auto prev = i; 11336090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet --prev; 11436090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet tokens.insert(i, newTokens.begin(), newTokens.end()); 11536090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet tokens.erase(i); 11636090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet advance(i, -newTokens.size()); 11736090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet } 11836090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet } 11936090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet return tokens; 12036090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet} 12136090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet 12236090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet// Remove the first element of the list if it equals 'prefix'. Return true in that case. 12336090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouilletstatic bool eatFront(list<string>* tokens, const char* prefix) { 12436090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet if (tokens->front() == prefix) { 12536090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet tokens->pop_front(); 12636090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet return true; 12736090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet } 12836090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet return false; 12936090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet} 13036090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet 13136090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet/* Search the table of translations for the built-ins for the mangling that 13236090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet * corresponds to this list of tokens. If a match is found, consume these tokens 13336090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet * and return a pointer to the string. If not, return nullptr. 13436090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet */ 13536090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouilletstatic const char* findManglingOfBuiltInType(list<string>* tokens) { 13636090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet for (const BuiltInMangling& a : builtInMangling) { 13736090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet auto t = tokens->begin(); 13836090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet auto end = tokens->end(); 13936090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet bool match = true; 14036090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet // We match up to three tokens. 14136090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet for (int i = 0; i < 3; i++) { 14236090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet if (!a.token[i]) { 14336090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet // No more tokens 14436090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet break; 14536090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet } 14636090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet if (t == end || *t++ != a.token[i]) { 14736090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet match = false; 14836090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet } 14936090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet } 15036090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet if (match) { 15136090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet tokens->erase(tokens->begin(), t); 15236090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet return a.equivalence; 15336090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet } 15436090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet } 15536090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet return nullptr; 15636090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet} 15736090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet 15836090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet// Mangle a long name by prefixing it with its length, e.g. "13rs_allocation". 15936090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouilletstatic inline string mangleLongName(const string& name) { 16036090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet return to_string(name.size()) + name; 16136090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet} 16236090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet 16336090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet/* Mangle the type name that's represented by the vector size and list of tokens. 16436090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet * The mangling will be returned in full form in 'mangling'. 'compressedMangling' 16536090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet * will have the compressed equivalent. This is built using the 'previousManglings' 16636090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet * list. false is returned if an error is encountered. 16736090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet * 16836090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet * This function is recursive because compression is possible at each level of the definition. 16936090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet * See http://mentorembedded.github.io/cxx-abi/abi.html#mangle.type for a description 17036090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet * of the Itanium mangling used by llvm. 17136090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet * 17236090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet * This function mangles correctly the types currently used by RenderScript. It does 17336090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet * not currently mangle more complicated types like function pointers, namespaces, 17436090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet * or other C++ types. In particular, we don't deal correctly with parenthesis. 17536090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet */ 17636090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouilletstatic bool mangleType(string vectorSize, list<string>* tokens, vector<string>* previousManglings, 17736090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet string* mangling, string* compressedMangling) { 17836090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet string delta; // The part of the mangling we're generating for this recursion. 17936090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet bool isTerminal = false; // True if this iteration parses a terminal node in the production. 18036090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet bool canBeCompressed = true; // Will be false for manglings of builtins. 18136090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet 18236090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet if (tokens->back() == "*") { 18336090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet delta = "P"; 18436090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet tokens->pop_back(); 18536090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet } else if (eatFront(tokens, "const")) { 18636090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet delta = "K"; 18736090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet } else if (eatFront(tokens, "volatile")) { 18836090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet delta = "V"; 18936090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet } else if (vectorSize != "1" && vectorSize != "") { 19036090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet // For vector, prefix with the abbreviation for a vector, including the size. 19136090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet delta = "Dv" + vectorSize + "_"; 19236090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet vectorSize.clear(); // Reset to mark the size as consumed. 19336090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet } else if (eatFront(tokens, "struct")) { 19436090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet // For a structure, we just use the structure name 19536090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet if (tokens->size() == 0) { 19636090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet cerr << "Expected a name after struct\n"; 19736090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet return false; 19836090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet } 19936090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet delta = mangleLongName(tokens->front()); 20036090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet isTerminal = true; 20136090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet tokens->pop_front(); 20236090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet } else { 20336090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet const char* c = findManglingOfBuiltInType(tokens); 20436090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet if (c) { 20536090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet // It's a basic type. We don't use those directly for compression. 20636090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet delta = c; 20736090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet isTerminal = true; 20836090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet canBeCompressed = false; 20936090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet } else if (tokens->size() > 0) { 21036090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet // It's a complex type name. 21136090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet delta = mangleLongName(tokens->front()); 21236090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet isTerminal = true; 21336090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet tokens->pop_front(); 21436090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet } 21536090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet } 21636090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet 21736090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet if (isTerminal) { 21836090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet // If we're the terminal node, there should be nothing left to mangle. 21936090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet if (tokens->size() > 0) { 22036090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet cerr << "Expected nothing else but found"; 22136090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet for (const auto& t : *tokens) { 22236090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet cerr << " " << t; 22336090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet } 22436090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet cerr << "\n"; 22536090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet return false; 22636090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet } 22736090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet *mangling = delta; 22836090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet *compressedMangling = delta; 22936090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet } else { 23036090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet // We're not terminal. Recurse and prefix what we've translated this pass. 23136090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet if (tokens->size() == 0) { 23236090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet cerr << "Expected a more complete type\n"; 23336090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet return false; 23436090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet } 23536090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet string rest, compressedRest; 23636090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet if (!mangleType(vectorSize, tokens, previousManglings, &rest, &compressedRest)) { 23736090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet return false; 23836090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet } 23936090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet *mangling = delta + rest; 24036090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet *compressedMangling = delta + compressedRest; 24136090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet } 24236090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet 24336090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet /* If it's a built-in type, we don't look at previously emitted ones and we 24436090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet * don't keep track of it. 24536090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet */ 24636090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet if (!canBeCompressed) { 24736090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet return true; 24836090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet } 24936090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet 25036090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet // See if we've encountered this mangling before. 25136090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet for (size_t i = 0; i < previousManglings->size(); ++i) { 25236090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet if ((*previousManglings)[i] == *mangling) { 25336090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet // We have a match, construct an index reference to that previously emitted mangling. 25436090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet ostringstream stream2; 25536090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet stream2 << 'S'; 25636090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet if (i > 0) { 25736090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet stream2 << (char)('0' + i - 1); 25836090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet } 25936090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet stream2 << '_'; 26036090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet *compressedMangling = stream2.str(); 26136090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet return true; 26236090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet } 26336090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet } 26436090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet 26536090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet // We have not encountered this before. Add it to the list. 26636090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet previousManglings->push_back(*mangling); 26736090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet return true; 26836090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet} 26936090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet 27036090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet// Write to the stream the mangled representation of each parameter. 27136090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouilletstatic bool writeParameters(ostringstream* stream, const std::vector<ParameterDefinition*>& params, 27212398d81f32e5e0479d02b8608a83c75cd991bb3Yang Ni unsigned int apiLevel, int intSize) { 27336090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet if (params.empty()) { 27436090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet *stream << "v"; 27536090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet return true; 27636090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet } 27736090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet /* We keep track of the previously generated parameter types, as type mangling 27836090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet * is compressed by reusing previous manglings. 27936090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet */ 28036090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet vector<string> previousManglings; 28136090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet for (ParameterDefinition* p : params) { 28236090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet // Expand the typedefs and create a tokenized list. 28336090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet list<string> tokens = expandTypedefs(p->rsType, apiLevel, intSize); 28436090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet if (p->isOutParameter) { 28536090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet tokens.push_back("*"); 28636090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet } 28736090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet string mangling, compressedMangling; 28836090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet if (!mangleType(p->mVectorSize, &tokens, &previousManglings, &mangling, 28936090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet &compressedMangling)) { 29036090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet return false; 29136090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet } 29236090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet *stream << compressedMangling; 29336090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet } 29436090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet return true; 29536090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet} 29636090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet 29736090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet/* Add the mangling for this permutation of the function. apiLevel and intSize is used 29836090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet * to select the correct type when expanding complex type. 29936090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet */ 30036090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouilletstatic bool addFunctionManglingToSet(const Function& function, 30136090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet const FunctionPermutation& permutation, bool overloadable, 30212398d81f32e5e0479d02b8608a83c75cd991bb3Yang Ni unsigned int apiLevel, int intSize, set<string>* allManglings) { 30336090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet const string& functionName = permutation.getName(); 30436090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet string mangling; 30536090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet if (overloadable) { 30636090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet ostringstream stream; 30736090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet stream << "_Z" << mangleLongName(functionName); 30836090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet if (!writeParameters(&stream, permutation.getParams(), apiLevel, intSize)) { 30936090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet cerr << "Error mangling " << functionName << ". See above message.\n"; 31036090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet return false; 31136090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet } 31236090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet mangling = stream.str(); 31336090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet } else { 31436090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet mangling = functionName; 31536090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet } 31636090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet allManglings->insert(mangling); 31736090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet return true; 31836090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet} 31936090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet 32036090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet/* Add to the set the mangling of each function prototype that can be generated from this 32136090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet * specification, i.e. for all the versions covered and for 32/64 bits. We call this 32236090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet * for each API level because the implementation of a type may have changed in the range 32336090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet * of API levels covered. 32436090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet */ 32536090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouilletstatic bool addManglingsForSpecification(const Function& function, 32612398d81f32e5e0479d02b8608a83c75cd991bb3Yang Ni const FunctionSpecification& spec, unsigned int lastApiLevel, 32736090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet set<string>* allManglings) { 32836090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet // If the function is inlined, we won't generate an unresolved external for that. 32936090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet if (spec.hasInline()) { 33036090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet return true; 33136090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet } 33236090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet const VersionInfo info = spec.getVersionInfo(); 33312398d81f32e5e0479d02b8608a83c75cd991bb3Yang Ni unsigned int minApiLevel, maxApiLevel; 33412398d81f32e5e0479d02b8608a83c75cd991bb3Yang Ni minApiLevel = info.minVersion ? info.minVersion : kMinimumApiLevelForTests; 33512398d81f32e5e0479d02b8608a83c75cd991bb3Yang Ni maxApiLevel = info.maxVersion ? info.maxVersion : lastApiLevel; 33636090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet const bool overloadable = spec.isOverloadable(); 33736090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet 33836090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet /* We track success rather than aborting early in case of failure so that we 33936090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet * generate all the error messages. 34036090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet */ 34136090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet bool success = true; 34212398d81f32e5e0479d02b8608a83c75cd991bb3Yang Ni // Use 64-bit integer here for the loop count to avoid overflow 34312398d81f32e5e0479d02b8608a83c75cd991bb3Yang Ni // (minApiLevel == maxApiLevel == UINT_MAX for unreleased API) 34412398d81f32e5e0479d02b8608a83c75cd991bb3Yang Ni for (int64_t apiLevel = minApiLevel; apiLevel <= maxApiLevel; ++apiLevel) { 34536090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet for (auto permutation : spec.getPermutations()) { 34636090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet if (info.intSize == 0 || info.intSize == 32) { 34736090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet if (!addFunctionManglingToSet(function, *permutation, overloadable, apiLevel, 32, 34836090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet allManglings)) { 34936090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet success = false; 35036090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet } 35136090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet } 35236090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet if (apiLevel >= kApiLevelWithFirst64Bit && (info.intSize == 0 || info.intSize == 64)) { 35336090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet if (!addFunctionManglingToSet(function, *permutation, overloadable, apiLevel, 64, 35436090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet allManglings)) { 35536090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet success = false; 35636090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet } 35736090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet } 35836090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet } 35936090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet } 36036090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet return success; 36136090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet} 36236090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet 36336090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet/* Generate the white list file of the mangled function prototypes. This generated list is used 36436090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet * to validate unresolved external references. 'lastApiLevel' is the largest api level found in 36536090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet * all spec files. 36636090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet */ 36712398d81f32e5e0479d02b8608a83c75cd991bb3Yang Nistatic bool generateWhiteListFile(unsigned int lastApiLevel) { 36836090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet bool success = true; 36936090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet // We generate all the manglings in a set to remove duplicates and to order them. 37036090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet set<string> allManglings; 37136090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet for (auto f : systemSpecification.getFunctions()) { 37236090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet const Function* function = f.second; 37336090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet for (auto spec : function->getSpecifications()) { 37412398d81f32e5e0479d02b8608a83c75cd991bb3Yang Ni // Compiler intrinsics are not runtime APIs. Do not include them in the whitelist. 37512398d81f32e5e0479d02b8608a83c75cd991bb3Yang Ni if (spec->isIntrinsic()) { 37612398d81f32e5e0479d02b8608a83c75cd991bb3Yang Ni continue; 37712398d81f32e5e0479d02b8608a83c75cd991bb3Yang Ni } 37836090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet if (!addManglingsForSpecification(*function, *spec, lastApiLevel, &allManglings)) { 37936090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet success = false; // We continue so we can generate all errors. 38036090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet } 38136090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet } 38236090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet } 38336090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet 38436090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet if (success) { 38536090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet GeneratedFile file; 38636090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet if (!file.start(".", "RSStubsWhiteList.cpp")) { 38736090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet return false; 38836090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet } 38936090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet 39036090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet file.writeNotices(); 39136090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet file << "#include \"RSStubsWhiteList.h\"\n\n"; 39236090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet file << "std::vector<std::string> stubList = {\n"; 39336090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet for (const auto& e : allManglings) { 39436090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet file << "\"" << e << "\",\n"; 39536090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet } 39636090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet file << "};\n"; 39736090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet } 39836090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet return success; 39936090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet} 40036090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet 40136090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet// Add a uniquely named variable definition to the file and return its name. 40236090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouilletstatic const string addVariable(GeneratedFile* file, unsigned int* variableNumber) { 40336090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet const string name = "buf" + to_string((*variableNumber)++); 40436090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet /* Some data structures like rs_tm can't be exported. We'll just use a dumb buffer 40536090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet * and cast its address later on. 40636090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet */ 40736090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet *file << "char " << name << "[200];\n"; 40836090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet return name; 40936090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet} 41036090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet 41136090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet/* Write to the file the globals needed to make the call for this permutation. The actual 41236090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet * call is stored in 'calls', as we'll need to generate all the global variable declarations 41336090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet * before the function definition. 41436090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet */ 41536090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouilletstatic void generateTestCall(GeneratedFile* file, ostringstream* calls, 41636090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet unsigned int* variableNumber, const Function& function, 41736090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet const FunctionPermutation& permutation) { 41836090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet *calls << " "; 41936090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet 42036090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet // Handle the return type. 42136090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet const auto ret = permutation.getReturn(); 42236090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet if (ret && ret->rsType != "void" && ret->rsType != "const void") { 42336090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet *calls << "*(" << ret->rsType << "*)" << addVariable(file, variableNumber) << " = "; 42436090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet } 42536090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet 42636090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet *calls << permutation.getName() << "("; 42736090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet 42836090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet // Generate the arguments. 42936090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet const char* separator = ""; 43036090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet for (auto p : permutation.getParams()) { 43136090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet *calls << separator; 43236090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet // Special case for the kernel context, as it has a special existence. 43336090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet if (p->rsType == "rs_kernel_context") { 4344324eec445c6882dce89a24765482293ed31914eJean-Luc Brouillet *calls << "context"; 43536090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet } else if (p->isOutParameter) { 43636090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet *calls << "(" << p->rsType << "*) " << addVariable(file, variableNumber); 43736090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet } else { 43836090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet *calls << "*(" << p->rsType << "*)" << addVariable(file, variableNumber); 43936090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet } 44036090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet separator = ", "; 44136090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet } 44236090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet *calls << ");\n"; 44336090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet} 44436090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet 44536090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet/* Generate a test file that will be used in the frameworks/compile/slang/tests unit tests. 44636090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet * This file tests that all RenderScript APIs can be called for the specified API level. 44736090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet * To avoid the compiler agressively pruning out our calls, we use globals as inputs and outputs. 44836090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet * 44936090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet * Since some structures can't be defined at the global level, we use casts of simple byte 45036090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet * buffers to get around that restriction. 45136090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet * 45236090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet * This file can be used to verify the white list that's also generated in this file. To do so, 45336090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet * run "llvm-nm -undefined-only -just-symbol-name" on the resulting bit code. 45436090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet */ 45512398d81f32e5e0479d02b8608a83c75cd991bb3Yang Nistatic bool generateApiTesterFile(const string& slangTestDirectory, unsigned int apiLevel) { 45636090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet GeneratedFile file; 45736090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet if (!file.start(slangTestDirectory, "all" + to_string(apiLevel) + ".rs")) { 45836090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet return false; 45936090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet } 46036090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet 46136090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet /* This unusual comment is used by slang/tests/test.py to know which parameter to pass 46236090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet * to llvm-rs-cc when compiling the test. 46336090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet */ 46436090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet file << "// -target-api " << apiLevel << " -Wno-deprecated-declarations\n"; 46536090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet 46636090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet file.writeNotices(); 46736090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet file << "#pragma version(1)\n"; 46836090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet file << "#pragma rs java_package_name(com.example.renderscript.testallapi)\n\n"; 46936090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet if (apiLevel < 23) { // All rs_graphics APIs were deprecated in api level 23. 47036090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet file << "#include \"rs_graphics.rsh\"\n\n"; 47136090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet } 47236090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet 47336090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet /* The code below emits globals and calls to functions in parallel. We store 47436090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet * the calls in a stream so that we can emit them in the file in the proper order. 47536090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet */ 47636090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet ostringstream calls; 47736090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet unsigned int variableNumber = 0; // Used to generate unique names. 47836090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet for (auto f : systemSpecification.getFunctions()) { 47936090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet const Function* function = f.second; 48036090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet for (auto spec : function->getSpecifications()) { 48112398d81f32e5e0479d02b8608a83c75cd991bb3Yang Ni // Do not include internal APIs in the API tests. 48212398d81f32e5e0479d02b8608a83c75cd991bb3Yang Ni if (spec->isInternal()) { 48312398d81f32e5e0479d02b8608a83c75cd991bb3Yang Ni continue; 48412398d81f32e5e0479d02b8608a83c75cd991bb3Yang Ni } 48536090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet VersionInfo info = spec->getVersionInfo(); 48636090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet if (!info.includesVersion(apiLevel)) { 48736090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet continue; 48836090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet } 48936090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet if (info.intSize == 32) { 49036090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet calls << "#ifndef __LP64__\n"; 49136090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet } else if (info.intSize == 64) { 49236090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet calls << "#ifdef __LP64__\n"; 49336090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet } 49436090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet for (auto permutation : spec->getPermutations()) { 49536090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet generateTestCall(&file, &calls, &variableNumber, *function, *permutation); 49636090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet } 49736090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet if (info.intSize != 0) { 49836090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet calls << "#endif\n"; 49936090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet } 50036090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet } 50136090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet } 50236090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet file << "\n"; 50336090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet 50436090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet // Modify the style of kernel as required by the API level. 50536090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet if (apiLevel >= 23) { 5064324eec445c6882dce89a24765482293ed31914eJean-Luc Brouillet file << "void RS_KERNEL test(int in, rs_kernel_context context) {\n"; 50736090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet } else if (apiLevel >= 17) { 50836090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet file << "void RS_KERNEL test(int in) {\n"; 50936090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet } else { 51036090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet file << "void root(const int* in) {\n"; 51136090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet } 51236090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet file << calls.str(); 51336090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet file << "}\n"; 51436090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet 51536090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet return true; 51636090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet} 51736090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet 51812398d81f32e5e0479d02b8608a83c75cd991bb3Yang Nibool generateStubsWhiteList(const string& slangTestDirectory, unsigned int maxApiLevel) { 51912398d81f32e5e0479d02b8608a83c75cd991bb3Yang Ni unsigned int lastApiLevel = min(systemSpecification.getMaximumApiLevel(), maxApiLevel); 52036090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet if (!generateWhiteListFile(lastApiLevel)) { 52136090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet return false; 52236090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet } 52336090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet // Generate a test file for each apiLevel. 52412398d81f32e5e0479d02b8608a83c75cd991bb3Yang Ni for (unsigned int i = kMinimumApiLevelForTests; i <= lastApiLevel; ++i) { 52536090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet if (!generateApiTesterFile(slangTestDirectory, i)) { 52636090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet return false; 52736090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet } 52836090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet } 52936090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet return true; 53036090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet} 531