/* Generate a test file that will be used in the frameworks/compile/slang/tests unit tests. * This file tests that all RenderScript APIs can be called for the specified API level. * To avoid the compiler agressively pruning out our calls, we use globals as inputs and outputs. * * Since some structures can't be defined at the global level, we use casts of simple byte * buffers to get around that restriction. * * This file can be used to verify the white list that's also generated in this file. To do so, * run "llvm-nm -undefined-only -just-symbol-name" on the resulting bit code. */ static bool generateApiTesterFile(const string& slangTestDirectory, int apiLevel) { GeneratedFile file; if (!file.start(slangTestDirectory, "all" + to_string(apiLevel) + ".rs")) { return false; } /* This unusual comment is used by slang/tests/test.py to know which parameter to pass * to llvm-rs-cc when compiling the test. */ file << "// -target-api " << apiLevel << " -Wno-deprecated-declarations\n"; file.writeNotices(); file << "#pragma version(1)\n"; file << "#pragma rs java_package_name(com.example.renderscript.testallapi)\n\n"; if (apiLevel < 23) { // All rs_graphics APIs were deprecated in api level 23. file << "#include \"rs_graphics.rsh\"\n\n"; } /* The code below emits globals and calls to functions in parallel. We store * the calls in a stream so that we can emit them in the file in the proper order. */ ostringstream calls; unsigned int variableNumber = 0; // Used to generate unique names. for (auto f : systemSpecification.getFunctions()) { const Function* function = f.second; for (auto spec : function->getSpecifications()) { VersionInfo info = spec->getVersionInfo(); if (!info.includesVersion(apiLevel)) { continue; } if (info.intSize == 32) { calls << "#ifndef __LP64__\n"; } else if (info.intSize == 64) { calls << "#ifdef __LP64__\n"; } for (auto permutation : spec->getPermutations()) { generateTestCall(&file, &calls, &variableNumber, *function, *permutation); } if (info.intSize != 0) { calls << "#endif\n"; } } } file << "\n"; // Modify the style of kernel as required by the API level. if (apiLevel >= 23) { file << "void RS_KERNEL test(int in, rs_kernel_context context) {\n"; } else if (apiLevel >= 17) { file << "void RS_KERNEL test(int in) {\n"; } else { file << "void root(const int* in) {\n"; } file << calls.str(); file << "}\n"; return true; }
/* For the given API level and bitness (e.g. 32 or 64 bit), try to find a * substitution for the provided type name, as would be done (mostly) by a * preprocessor. Returns empty string if there's no substitution. */ static string findSubstitute(const string& typeName, int apiLevel, int intSize) { const auto& types = systemSpecification.getTypes(); const auto type = types.find(typeName); if (type != types.end()) { for (TypeSpecification* spec : type->second->getSpecifications()) { // Verify this specification applies const VersionInfo info = spec->getVersionInfo(); if (!info.includesVersion(apiLevel) || (info.intSize != 0 && info.intSize != intSize)) { continue; } switch (spec->getKind()) { case SIMPLE: { /* For simple typedefs, replace it unless it's the special case of _RS_HANDLE * which is a macro of a struct. */ const string s = spec->getSimpleType(); if (s != "_RS_HANDLE") { return s; } break; } case STRUCT: { const string s = spec->getStructName(); if (!s.empty()) { return s; } break; } case ENUM: // Do nothing break; } } } return ""; }