diff options
author | Yang Ni <yangni@google.com> | 2015-10-23 22:00:42 +0000 |
---|---|---|
committer | Gerrit Code Review <noreply-gerritcodereview@google.com> | 2015-10-23 22:00:42 +0000 |
commit | 4a21e4dc4274dbf7d3ddad62e2cc1a9f25864a5f (patch) | |
tree | bb722c41615b53e21ac5c811fe02819821cde97c | |
parent | 75e9f10b5d26a2feb03dc7bb4ad39514ec3e8660 (diff) | |
parent | 12398d81f32e5e0479d02b8608a83c75cd991bb3 (diff) | |
download | rs-brillo-m7-mr-dev.tar.gz |
Merge "Add rsForEachInternal"brillo-m7-releasebrillo-m7-mr-devbrillo-m7-dev
-rw-r--r-- | api/GenerateHeaderFiles.cpp | 8 | ||||
-rw-r--r-- | api/GenerateStubsWhiteList.cpp | 42 | ||||
-rw-r--r-- | api/GenerateTestFiles.cpp | 6 | ||||
-rw-r--r-- | api/Generator.cpp | 16 | ||||
-rw-r--r-- | api/Generator.h | 4 | ||||
-rw-r--r-- | api/Scanner.cpp | 9 | ||||
-rw-r--r-- | api/Specification.cpp | 62 | ||||
-rw-r--r-- | api/Specification.h | 33 | ||||
-rw-r--r-- | api/Utilities.cpp | 2 | ||||
-rw-r--r-- | api/Utilities.h | 2 | ||||
-rwxr-xr-x | api/generate.sh | 2 | ||||
-rw-r--r-- | api/rs_for_each.spec | 42 | ||||
-rw-r--r-- | driver/rsdRuntimeStubs.cpp | 17 | ||||
-rw-r--r-- | java/tests/RsTest/src/com/android/rs/test/RSTestCore.java | 1 | ||||
-rw-r--r-- | java/tests/RsTest/src/com/android/rs/test/UT_single_source_script.java | 55 | ||||
-rw-r--r-- | java/tests/RsTest/src/com/android/rs/test/single_source_script.rs | 54 | ||||
-rw-r--r-- | rsRuntime.h | 1 | ||||
-rw-r--r-- | rsScriptC_Lib.cpp | 5 | ||||
-rw-r--r-- | scriptc/rs_for_each.rsh | 32 |
19 files changed, 319 insertions, 74 deletions
diff --git a/api/GenerateHeaderFiles.cpp b/api/GenerateHeaderFiles.cpp index aac7ecb8..9d5b49ad 100644 --- a/api/GenerateHeaderFiles.cpp +++ b/api/GenerateHeaderFiles.cpp @@ -42,7 +42,7 @@ static string makeGuardString(const string& filename) { * add a check on a flag that can be set for internal builds. This enables us to keep supporting * old APIs in the runtime code. */ -static void writeVersionGuardStart(GeneratedFile* file, VersionInfo info, int finalVersion) { +static void writeVersionGuardStart(GeneratedFile* file, VersionInfo info, unsigned int finalVersion) { if (info.intSize == 32) { *file << "#ifndef __LP64__\n"; } else if (info.intSize == 64) { @@ -218,7 +218,7 @@ static void writeFunctionPermutation(GeneratedFile* file, const FunctionSpecific *file << "void"; } - *file << makeAttributeTag(spec.getAttribute(), "overloadable", + *file << makeAttributeTag(spec.getAttribute(), spec.isOverloadable() ? "overloadable" : "", function->getDeprecatedApiLevel(), function->getDeprecatedMessage()); *file << "\n"; @@ -364,6 +364,10 @@ static bool writeHeaderFile(const string& directory, const SpecFile& specFile) { set<Function*> documentedFunctions; for (auto spec : specFile.getFunctionSpecifications()) { + // Do not include internal APIs in the header files. + if (spec->isInternal()) { + continue; + } Function* function = spec->getFunction(); if (documentedFunctions.find(function) == documentedFunctions.end()) { documentedFunctions.insert(function); diff --git a/api/GenerateStubsWhiteList.cpp b/api/GenerateStubsWhiteList.cpp index 9b4297d1..69afdbfa 100644 --- a/api/GenerateStubsWhiteList.cpp +++ b/api/GenerateStubsWhiteList.cpp @@ -15,6 +15,7 @@ */ #include <algorithm> +#include <climits> #include <iostream> #include <iterator> #include <sstream> @@ -25,8 +26,8 @@ using namespace std; -const int kMinimumApiLevelForTests = 11; -const int kApiLevelWithFirst64Bit = 21; +const unsigned int kMinimumApiLevelForTests = 11; +const unsigned int kApiLevelWithFirst64Bit = 21; // Used to map the built-in types to their mangled representations struct BuiltInMangling { @@ -58,7 +59,7 @@ BuiltInMangling builtInMangling[] = { * 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) { +static string findSubstitute(const string& typeName, unsigned int apiLevel, int intSize) { const auto& types = systemSpecification.getTypes(); const auto type = types.find(typeName); if (type != types.end()) { @@ -92,7 +93,7 @@ static string findSubstitute(const string& typeName, int apiLevel, int intSize) * the resulting list. 'apiLevel' and 'intSize' specifies the API level and bitness * we are currently processing. */ -list<string> expandTypedefs(const string type, int apiLevel, int intSize) { +list<string> expandTypedefs(const string type, unsigned int apiLevel, int intSize) { // Split the string in tokens. istringstream stream(type); list<string> tokens{istream_iterator<string>{stream}, istream_iterator<string>{}}; @@ -268,7 +269,7 @@ static bool mangleType(string vectorSize, list<string>* tokens, vector<string>* // Write to the stream the mangled representation of each parameter. static bool writeParameters(ostringstream* stream, const std::vector<ParameterDefinition*>& params, - int apiLevel, int intSize) { + unsigned int apiLevel, int intSize) { if (params.empty()) { *stream << "v"; return true; @@ -298,7 +299,7 @@ static bool writeParameters(ostringstream* stream, const std::vector<ParameterDe */ static bool addFunctionManglingToSet(const Function& function, const FunctionPermutation& permutation, bool overloadable, - int apiLevel, int intSize, set<string>* allManglings) { + unsigned int apiLevel, int intSize, set<string>* allManglings) { const string& functionName = permutation.getName(); string mangling; if (overloadable) { @@ -322,22 +323,25 @@ static bool addFunctionManglingToSet(const Function& function, * of API levels covered. */ static bool addManglingsForSpecification(const Function& function, - const FunctionSpecification& spec, int lastApiLevel, + const FunctionSpecification& spec, unsigned int lastApiLevel, set<string>* allManglings) { // If the function is inlined, we won't generate an unresolved external for that. if (spec.hasInline()) { return true; } const VersionInfo info = spec.getVersionInfo(); - const int minApiLevel = info.minVersion ? info.minVersion : kMinimumApiLevelForTests; - const int maxApiLevel = info.maxVersion ? info.maxVersion : lastApiLevel; + unsigned int minApiLevel, maxApiLevel; + minApiLevel = info.minVersion ? info.minVersion : kMinimumApiLevelForTests; + maxApiLevel = info.maxVersion ? info.maxVersion : lastApiLevel; const bool overloadable = spec.isOverloadable(); /* We track success rather than aborting early in case of failure so that we * generate all the error messages. */ bool success = true; - for (int apiLevel = minApiLevel; apiLevel <= maxApiLevel; ++apiLevel) { + // Use 64-bit integer here for the loop count to avoid overflow + // (minApiLevel == maxApiLevel == UINT_MAX for unreleased API) + for (int64_t apiLevel = minApiLevel; apiLevel <= maxApiLevel; ++apiLevel) { for (auto permutation : spec.getPermutations()) { if (info.intSize == 0 || info.intSize == 32) { if (!addFunctionManglingToSet(function, *permutation, overloadable, apiLevel, 32, @@ -360,13 +364,17 @@ static bool addManglingsForSpecification(const Function& function, * to validate unresolved external references. 'lastApiLevel' is the largest api level found in * all spec files. */ -static bool generateWhiteListFile(int lastApiLevel) { +static bool generateWhiteListFile(unsigned int lastApiLevel) { bool success = true; // We generate all the manglings in a set to remove duplicates and to order them. set<string> allManglings; for (auto f : systemSpecification.getFunctions()) { const Function* function = f.second; for (auto spec : function->getSpecifications()) { + // Compiler intrinsics are not runtime APIs. Do not include them in the whitelist. + if (spec->isIntrinsic()) { + continue; + } if (!addManglingsForSpecification(*function, *spec, lastApiLevel, &allManglings)) { success = false; // We continue so we can generate all errors. } @@ -444,7 +452,7 @@ static void generateTestCall(GeneratedFile* file, ostringstream* calls, * 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) { +static bool generateApiTesterFile(const string& slangTestDirectory, unsigned int apiLevel) { GeneratedFile file; if (!file.start(slangTestDirectory, "all" + to_string(apiLevel) + ".rs")) { return false; @@ -470,6 +478,10 @@ static bool generateApiTesterFile(const string& slangTestDirectory, int apiLevel for (auto f : systemSpecification.getFunctions()) { const Function* function = f.second; for (auto spec : function->getSpecifications()) { + // Do not include internal APIs in the API tests. + if (spec->isInternal()) { + continue; + } VersionInfo info = spec->getVersionInfo(); if (!info.includesVersion(apiLevel)) { continue; @@ -503,13 +515,13 @@ static bool generateApiTesterFile(const string& slangTestDirectory, int apiLevel return true; } -bool generateStubsWhiteList(const string& slangTestDirectory, int maxApiLevel) { - int lastApiLevel = min(systemSpecification.getMaximumApiLevel(), maxApiLevel); +bool generateStubsWhiteList(const string& slangTestDirectory, unsigned int maxApiLevel) { + unsigned int lastApiLevel = min(systemSpecification.getMaximumApiLevel(), maxApiLevel); if (!generateWhiteListFile(lastApiLevel)) { return false; } // Generate a test file for each apiLevel. - for (int i = kMinimumApiLevelForTests; i <= lastApiLevel; ++i) { + for (unsigned int i = kMinimumApiLevelForTests; i <= lastApiLevel; ++i) { if (!generateApiTesterFile(slangTestDirectory, i)) { return false; } diff --git a/api/GenerateTestFiles.cpp b/api/GenerateTestFiles.cpp index ddb7c782..45cf1f3c 100644 --- a/api/GenerateTestFiles.cpp +++ b/api/GenerateTestFiles.cpp @@ -46,7 +46,7 @@ static void convertToRsType(const string& name, string* dataType, char* vectorSi } // Returns true if any permutation of the function have tests to b -static bool needTestFiles(const Function& function, int versionOfTestFiles) { +static bool needTestFiles(const Function& function, unsigned int versionOfTestFiles) { for (auto spec : function.getSpecifications()) { if (spec->hasTests(versionOfTestFiles)) { return true; @@ -974,7 +974,7 @@ static bool writeRelaxedRsFile(const Function& function, const string& directory * to test. */ static bool writeTestFilesForFunction(const Function& function, const string& directory, - int versionOfTestFiles) { + unsigned int versionOfTestFiles) { // Avoid creating empty files if we're not testing this function. if (!needTestFiles(function, versionOfTestFiles)) { return true; @@ -1026,7 +1026,7 @@ static bool writeTestFilesForFunction(const Function& function, const string& di return true; } -bool generateTestFiles(const string& directory, int versionOfTestFiles) { +bool generateTestFiles(const string& directory, unsigned int versionOfTestFiles) { bool success = true; for (auto f : systemSpecification.getFunctions()) { if (!writeTestFilesForFunction(*f.second, directory, versionOfTestFiles)) { diff --git a/api/Generator.cpp b/api/Generator.cpp index c44c9958..456f2147 100644 --- a/api/Generator.cpp +++ b/api/Generator.cpp @@ -59,7 +59,7 @@ * Constants are defined as follows: * * constant: {The name of the constant.} - * [version: {Starting API level} [ {Last API level that supports this.}] + * [version: ({Starting API level} [ {Last API level that supports this.}] | UNRELEASED) * [size: {32 or 64. Used if this is available only for 32 or 64 bit code.}] * value: {The value of the constant.} * [hidden:] ...If present, don't document the constant. Omit the following two fields. @@ -73,7 +73,7 @@ * Types can either be simple types, structs, or enums. They have the format: * * type: {The typedef name of the type.} - * [version: {Starting API level} [ {Last API level that supports this.}] + * [version: ({Starting API level} [ {Last API level that supports this.}] | UNRELEASED) * [size: {32 or 64. Used if this is available only for 32 or 64 bit code.}] * simple: {The C declaration that this type is the typedef equivalent.} * [hidden:] ...If present, don't document the type. Omit the following two fields. @@ -85,7 +85,7 @@ * end: * * type: {The typedef name of the type.} - * [version: {Starting API level} [ {Last API level that supports this.}] + * [version: ({Starting API level} [ {Last API level that supports this.}] | UNRELEASED) * [size: {32 or 64. Used if this is available only for 32 or 64 bit code.}] * struct: [{The name that will appear right after the struct keyword}] * field: {Type and name of the field}[, "{One line documentation of the field}"] @@ -99,7 +99,7 @@ * end: * * type: {The typedef name of the type.} - * [version: {Starting API level} [ {Last API level that supports this.}] + * [version: ({Starting API level} [ {Last API level that supports this.}] | UNRELEASED) * [size: {32 or 64. Used if this is available only for 32 or 64 bit code.}] * enum: [{The name that will appear right after the enum keyword}] * value: {Type and name of the field}[, "{One line documentation of the field}"] @@ -114,7 +114,7 @@ * Functions have the following format: * * function: {The name of the function.} - * [version: {Starting API level} [ {Last API level that supports this.}] + * [version: ({Starting API level} [ {Last API level that supports this.}] | UNRELEASED) * [size: {32 or 64. Used if this is available only for 32 or 64 bit code.}] * [attrib: {Attributes of the function.}] * [w: {A comma separated list of width supported. Only 1, 2, 3, 4 are supported. @@ -122,7 +122,7 @@ * ... Up to four w: or t: can be defined. The order matter. These will be replace * ... the #1, #2, #3, #4 that can be found in the rest of the specification. * ret: [{The return type} [, "{One line documentation of the return}"]] - * [arg: {Type}[, {Name}][, {ParameterEntry.testOption}][, "{One line documentation of the field}"]] + * [arg:(({Type}[ {Name})]|{Elipsis})[, {ParameterEntry.testOption}][, "{One line documentation of the field}"]] * [arg: ... Same for all the other arguments of the function.] * [hidden:] ... If present, don't include in the HTML documentation. * [deprecated: [{Deprecation message.}] ... This is deprecated. Compiler will issue a wrning. @@ -153,7 +153,7 @@ using namespace std; -static bool parseCommandLine(int argc, char* argv[], int* maxApiLevel, bool* forVerification, +static bool parseCommandLine(int argc, char* argv[], unsigned int* maxApiLevel, bool* forVerification, vector<string>* specFileNames) { for (int i = 1; i < argc; i++) { if (argv[i][0] == '-') { @@ -189,7 +189,7 @@ static bool parseCommandLine(int argc, char* argv[], int* maxApiLevel, bool* for int main(int argc, char* argv[]) { // If there's no restriction, generated test files for the very highest version. - int maxApiLevel = 999999; + unsigned int maxApiLevel = VersionInfo::kUnreleasedVersion; vector<string> specFileNames; bool forVerification = false; if (!parseCommandLine(argc, argv, &maxApiLevel, &forVerification, &specFileNames)) { diff --git a/api/Generator.h b/api/Generator.h index 7a9dd28d..5d721013 100644 --- a/api/Generator.h +++ b/api/Generator.h @@ -21,7 +21,7 @@ bool generateHeaderFiles(const std::string& directory); // Generates the Java and RenderScript test files. The implementation is in GenerateTestFiles.cpp. -bool generateTestFiles(const std::string& directory, int versionOfTestFiles); +bool generateTestFiles(const std::string& directory, unsigned int versionOfTestFiles); /* Generates the documentation files. The implementation is in GenerateDocumentation.cpp. * If forVerification is false (the default), we generate the .jd files needed by the @@ -33,6 +33,6 @@ bool generateDocumentation(const std::string& director, bool forVerification); * when testing slang and that can be used to manually verify the white list. * The implementation is in GenerateStubsWhiteList.cpp. */ -bool generateStubsWhiteList(const std::string& slangTestDirectory, int maxApiLevel); +bool generateStubsWhiteList(const std::string& slangTestDirectory, unsigned int maxApiLevel); #endif // ANDROID_RS_API_GENERATOR_GENERATOR_H diff --git a/api/Scanner.cpp b/api/Scanner.cpp index 84af5817..1bd4973e 100644 --- a/api/Scanner.cpp +++ b/api/Scanner.cpp @@ -175,7 +175,14 @@ ParameterEntry* Scanner::parseArgString(bool isReturn) { if (!isReturn) { size_t nameStart = s.rfind(' '); if (nameStart == string::npos) { - error() << "Missing variable name\n"; + if (s == "...") { + p->name = s; + p->type = ""; + p->lineNumber = mLineNumber; + return p; + } else { + error() << "Missing variable name\n"; + } } else { p->name = s.substr(nameStart + 1); s.erase(nameStart); diff --git a/api/Specification.cpp b/api/Specification.cpp index f02e4290..28e52314 100644 --- a/api/Specification.cpp +++ b/api/Specification.cpp @@ -32,7 +32,7 @@ using namespace std; // API level when RenderScript was added. -const int MIN_API_LEVEL = 9; +const unsigned int MIN_API_LEVEL = 9; const NumericalType TYPES[] = { {"f16", "FLOAT_16", "half", "float", FLOATING_POINT, 11, 5}, @@ -50,6 +50,8 @@ const NumericalType TYPES[] = { const int NUM_TYPES = sizeof(TYPES) / sizeof(TYPES[0]); +static const char kTagUnreleased[] = "UNRELEASED"; + // The singleton of the collected information of all the spec files. SystemSpecification systemSpecification; @@ -201,26 +203,34 @@ void ParameterDefinition::parseParameterDefinition(const string& type, const str } } -bool VersionInfo::scan(Scanner* scanner, int maxApiLevel) { +bool VersionInfo::scan(Scanner* scanner, unsigned int maxApiLevel) { if (scanner->findOptionalTag("version:")) { const string s = scanner->getValue(); - sscanf(s.c_str(), "%i %i", &minVersion, &maxVersion); - if (minVersion && minVersion < MIN_API_LEVEL) { - scanner->error() << "Minimum version must >= 9\n"; - } - if (minVersion == MIN_API_LEVEL) { - minVersion = 0; - } - if (maxVersion && maxVersion < MIN_API_LEVEL) { - scanner->error() << "Maximum version must >= 9\n"; + if (s.compare(0, sizeof(kTagUnreleased), kTagUnreleased) == 0) { + // The API is still under development and does not have + // an official version number. + minVersion = maxVersion = kUnreleasedVersion; + } else { + sscanf(s.c_str(), "%u %u", &minVersion, &maxVersion); + if (minVersion && minVersion < MIN_API_LEVEL) { + scanner->error() << "Minimum version must >= 9\n"; + } + if (minVersion == MIN_API_LEVEL) { + minVersion = 0; + } + if (maxVersion && maxVersion < MIN_API_LEVEL) { + scanner->error() << "Maximum version must >= 9\n"; + } } } if (scanner->findOptionalTag("size:")) { sscanf(scanner->getValue().c_str(), "%i", &intSize); } + if (maxVersion > maxApiLevel) { maxVersion = maxApiLevel; } + return minVersion == 0 || minVersion <= maxApiLevel; } @@ -331,7 +341,7 @@ void Function::addReturn(ParameterEntry* entry, Scanner* scanner) { } void ConstantSpecification::scanConstantSpecification(Scanner* scanner, SpecFile* specFile, - int maxApiLevel) { + unsigned int maxApiLevel) { string name = scanner->getValue(); VersionInfo info; if (!info.scan(scanner, maxApiLevel)) { @@ -357,7 +367,7 @@ void ConstantSpecification::scanConstantSpecification(Scanner* scanner, SpecFile } void TypeSpecification::scanTypeSpecification(Scanner* scanner, SpecFile* specFile, - int maxApiLevel) { + unsigned int maxApiLevel) { string name = scanner->getValue(); VersionInfo info; if (!info.scan(scanner, maxApiLevel)) { @@ -522,7 +532,7 @@ void FunctionSpecification::parseTest(Scanner* scanner) { } } -bool FunctionSpecification::hasTests(int versionOfTestFiles) const { +bool FunctionSpecification::hasTests(unsigned int versionOfTestFiles) const { if (mVersionInfo.maxVersion != 0 && mVersionInfo.maxVersion < versionOfTestFiles) { return false; } @@ -533,7 +543,7 @@ bool FunctionSpecification::hasTests(int versionOfTestFiles) const { } void FunctionSpecification::scanFunctionSpecification(Scanner* scanner, SpecFile* specFile, - int maxApiLevel) { + unsigned int maxApiLevel) { // Some functions like convert have # part of the name. Truncate at that point. const string& unexpandedName = scanner->getValue(); string name = unexpandedName; @@ -562,6 +572,12 @@ void FunctionSpecification::scanFunctionSpecification(Scanner* scanner, SpecFile spec->mTest = "scalar"; // default spec->mVersionInfo = info; + if (scanner->findOptionalTag("internal:")) { + spec->mInternal = (scanner->getValue() == "true"); + } + if (scanner->findOptionalTag("intrinsic:")) { + spec->mIntrinsic = (scanner->getValue() == "true"); + } if (scanner->findOptionalTag("attrib:")) { spec->mAttribute = scanner->getValue(); } @@ -711,7 +727,7 @@ void SpecFile::addFunctionSpecification(FunctionSpecification* spec, bool hasDoc } // Read the specification, adding the definitions to the global functions map. -bool SpecFile::readSpecFile(int maxApiLevel) { +bool SpecFile::readSpecFile(unsigned int maxApiLevel) { FILE* specFile = fopen(mSpecFileName.c_str(), "rt"); if (!specFile) { cerr << "Error opening input file: " << mSpecFileName << "\n"; @@ -804,7 +820,7 @@ Function* SystemSpecification::findOrCreateFunction(const string& name, bool* cr return findOrCreate<Function>(name, &mFunctions, created); } -bool SystemSpecification::readSpecFile(const string& fileName, int maxApiLevel) { +bool SystemSpecification::readSpecFile(const string& fileName, unsigned int maxApiLevel) { SpecFile* spec = new SpecFile(fileName); if (!spec->readSpecFile(maxApiLevel)) { cerr << fileName << ": Failed to parse.\n"; @@ -815,12 +831,16 @@ bool SystemSpecification::readSpecFile(const string& fileName, int maxApiLevel) } -static void updateMaxApiLevel(const VersionInfo& info, int* maxApiLevel) { +static void updateMaxApiLevel(const VersionInfo& info, unsigned int* maxApiLevel) { + if (info.minVersion == VersionInfo::kUnreleasedVersion) { + // Ignore development API level in consideration of max API level. + return; + } *maxApiLevel = max(*maxApiLevel, max(info.minVersion, info.maxVersion)); } -int SystemSpecification::getMaximumApiLevel() { - int maxApiLevel = 0; +unsigned int SystemSpecification::getMaximumApiLevel() { + unsigned int maxApiLevel = 0; for (auto i : mConstants) { for (auto j: i.second->getSpecifications()) { updateMaxApiLevel(j->getVersionInfo(), &maxApiLevel); @@ -839,7 +859,7 @@ int SystemSpecification::getMaximumApiLevel() { return maxApiLevel; } -bool SystemSpecification::generateFiles(bool forVerification, int maxApiLevel) const { +bool SystemSpecification::generateFiles(bool forVerification, unsigned int maxApiLevel) const { bool success = generateHeaderFiles("scriptc") && generateDocumentation("docs", forVerification) && generateTestFiles("test", maxApiLevel) && diff --git a/api/Specification.h b/api/Specification.h index 87969a63..d3fbad53 100644 --- a/api/Specification.h +++ b/api/Specification.h @@ -19,6 +19,7 @@ // See Generator.cpp for documentation of the .spec file format. +#include <climits> #include <fstream> #include <list> #include <map> @@ -124,8 +125,8 @@ struct VersionInfo { * If non zero, both versions should be at least 9, the API level that introduced * RenderScript. */ - int minVersion; - int maxVersion; + unsigned int minVersion; + unsigned int maxVersion; // Either 0, 32 or 64. If 0, this definition is valid for both 32 and 64 bits. int intSize; @@ -134,12 +135,14 @@ struct VersionInfo { * we are interested in. This may alter maxVersion. This method returns false if the * minVersion is greater than the maxApiLevel. */ - bool scan(Scanner* scanner, int maxApiLevel); + bool scan(Scanner* scanner, unsigned int maxApiLevel); /* Return true if the target can be found whitin the range. */ bool includesVersion(int target) const { return (minVersion == 0 || target >= minVersion) && (maxVersion == 0 || target <= maxVersion); } + + static constexpr unsigned int kUnreleasedVersion = UINT_MAX; }; // We have three type of definitions @@ -266,7 +269,7 @@ public: std::string getValue() const { return mValue; } // Parse a constant specification and add it to specFile. - static void scanConstantSpecification(Scanner* scanner, SpecFile* specFile, int maxApiLevel); + static void scanConstantSpecification(Scanner* scanner, SpecFile* specFile, unsigned int maxApiLevel); }; enum TypeKind { @@ -313,7 +316,7 @@ public: const std::vector<std::string>& getValueComments() const { return mValueComments; } // Parse a type specification and add it to specFile. - static void scanTypeSpecification(Scanner* scanner, SpecFile* specFile, int maxApiLevel); + static void scanTypeSpecification(Scanner* scanner, SpecFile* specFile, unsigned int maxApiLevel); }; // Maximum number of placeholders (like #1, #2) in function specifications. @@ -343,6 +346,9 @@ private: * "": Don't test. This is the default. */ std::string mTest; + bool mInternal; // Internal. Not visible to users. (Default: false) + bool mIntrinsic; // Compiler intrinsic that is lowered to an internal API. + // (Default: false) std::string mAttribute; // Function attributes. std::string mPrecisionLimit; // Maximum precision required when checking output of this // function. @@ -379,10 +385,13 @@ private: void createPermutations(Function* function, Scanner* scanner); public: - FunctionSpecification(Function* function) : mFunction(function), mReturn(nullptr) {} + FunctionSpecification(Function* function) : mFunction(function), mInternal(false), + mIntrinsic(false), mReturn(nullptr) {} ~FunctionSpecification(); Function* getFunction() const { return mFunction; } + bool isInternal() const { return mInternal; } + bool isIntrinsic() const { return mIntrinsic; } std::string getAttribute() const { return mAttribute; } std::string getTest() const { return mTest; } std::string getPrecisionLimit() const { return mPrecisionLimit; } @@ -402,7 +411,7 @@ public: void parseTest(Scanner* scanner); // Return true if we need to generate tests for this function. - bool hasTests(int versionOfTestFiles) const; + bool hasTests(unsigned int versionOfTestFiles) const; bool hasInline() const { return mInline.size() > 0; } @@ -415,7 +424,7 @@ public: } // Parse a function specification and add it to specFile. - static void scanFunctionSpecification(Scanner* scanner, SpecFile* specFile, int maxApiLevel); + static void scanFunctionSpecification(Scanner* scanner, SpecFile* specFile, unsigned int maxApiLevel); }; /* A concrete version of a function specification, where all placeholders have been replaced by @@ -527,7 +536,7 @@ public: !mDocumentedFunctions.empty(); } - bool readSpecFile(int maxApiLevel); + bool readSpecFile(unsigned int maxApiLevel); /* These are called by the parser to keep track of the specifications defined in this file. * hasDocumentation is true if this specification containes the documentation. @@ -562,9 +571,9 @@ public: /* Parse the spec file and create the object hierarchy, adding a pointer to mSpecFiles. * We won't include information passed the specified level. */ - bool readSpecFile(const std::string& fileName, int maxApiLevel); + bool readSpecFile(const std::string& fileName, unsigned int maxApiLevel); // Generate all the files. - bool generateFiles(bool forVerification, int maxApiLevel) const; + bool generateFiles(bool forVerification, unsigned int maxApiLevel) const; const std::vector<SpecFile*>& getSpecFiles() const { return mSpecFiles; } const std::map<std::string, Constant*>& getConstants() const { return mConstants; } @@ -575,7 +584,7 @@ public: std::string getHtmlAnchor(const std::string& name) const; // Returns the maximum API level specified in any spec file. - int getMaximumApiLevel(); + unsigned int getMaximumApiLevel(); }; // Singleton that represents the collection of all the specs we're processing. diff --git a/api/Utilities.cpp b/api/Utilities.cpp index 42682787..841d824f 100644 --- a/api/Utilities.cpp +++ b/api/Utilities.cpp @@ -163,7 +163,7 @@ static void addCommaSeparated(const string& value, ostringstream* stream, bool* } string makeAttributeTag(const string& userAttribute, const string& additionalAttribute, - int deprecatedApiLevel, const string& deprecatedMessage) { + unsigned int deprecatedApiLevel, const string& deprecatedMessage) { ostringstream stream; bool needComma = false; if (userAttribute[0] == '=') { diff --git a/api/Utilities.h b/api/Utilities.h index cd0db728..eced68d2 100644 --- a/api/Utilities.h +++ b/api/Utilities.h @@ -51,7 +51,7 @@ double maxDoubleForInteger(int numberOfIntegerBits, int mantissaSize); * use the additionalAttribute. An empty string will be returned if there are no attributes. */ std::string makeAttributeTag(const std::string& userAttribute, - const std::string& additionalAttribute, int deprecatedApiLevel, + const std::string& additionalAttribute, unsigned int deprecatedApiLevel, const std::string& deprecatedMessage); /* This class is used to generate one source file. There will be one instance diff --git a/api/generate.sh b/api/generate.sh index 3ff882f3..55d3f048 100755 --- a/api/generate.sh +++ b/api/generate.sh @@ -50,7 +50,7 @@ for i in {11..23} do mv slangtest/all$i.rs ../../compile/slang/tests/P_all_api_$i done -rmdir slangtest +rm -rf slangtest mv RSStubsWhiteList.cpp ../../compile/libbcc/lib/Renderscript/ diff --git a/api/rs_for_each.spec b/api/rs_for_each.spec index c0c09b2d..fee1a717 100644 --- a/api/rs_for_each.spec +++ b/api/rs_for_each.spec @@ -156,6 +156,48 @@ arg: rs_allocation output test: none end: +type: rs_kernel +version: UNRELEASED +simple: void* +summary: Handle to a kernel function +description: + An opaque type for a function that is defined with the kernel attribute. A value + of this type can be used in a @rsParallelFor call to launch a kernel. +end: + +function: rsParallelFor +version: UNRELEASED +intrinsic: true +attrib: = +ret: void +arg: rs_kernel kernel, "Function designator to a function that is defined with the kernel attribute." +arg: ..., "Input and output allocations" +summary: Run a kernel defined in the current Script +description: + Runs the kernel over zero or more input allocations. They are passed after the + @rs_kernel argument. If the specified kernel returns a value, an output allocation + must be specified as the last argument. All input allocations, + and the output allocation if it exists, must have the same dimensions. + + This is a synchronous function. A call to this function only returns after all + the work has completed for all cells of the input allocations. If the kernel + function returns any value, the call waits until all results have been written + to the output allocation. +test: none +end: + +function: rsForEachInternal +version: UNRELEASED +internal: true +ret: void +arg: int slot +arg: rs_allocation input +arg: rs_allocation output +summary: (Internal API) Launch a kernel in the current Script (with the slot number) +description: +test: none +end: + function: rsGetArray0 version: 23 ret: uint32_t diff --git a/driver/rsdRuntimeStubs.cpp b/driver/rsdRuntimeStubs.cpp index f28c946b..86c41078 100644 --- a/driver/rsdRuntimeStubs.cpp +++ b/driver/rsdRuntimeStubs.cpp @@ -433,13 +433,20 @@ ELEMENT_AT_OVERLOADS(long, long long) ////////////////////////////////////////////////////////////////////////////// // ForEach routines ////////////////////////////////////////////////////////////////////////////// +void rsForEachInternal(int slot, ::rs_allocation in, ::rs_allocation out) { + Context *rsc = RsdCpuReference::getTlsContext(); + Script *s = const_cast<Script*>(RsdCpuReference::getTlsScript()); + rsrForEach(rsc, s, slot, (Allocation *)in.p, (Allocation *)out.p, + nullptr, 0, nullptr); +} + void __attribute__((overloadable)) rsForEach(::rs_script script, ::rs_allocation in, ::rs_allocation out, const void *usr, const rs_script_call *call) { Context *rsc = RsdCpuReference::getTlsContext(); - rsrForEach(rsc, (Script *)script.p, (Allocation *)in.p, + rsrForEach(rsc, (Script *)script.p, 0, (Allocation *)in.p, (Allocation *)out.p, usr, 0, (RsScriptCall *)call); } @@ -448,7 +455,7 @@ void __attribute__((overloadable)) rsForEach(::rs_script script, ::rs_allocation out, const void *usr) { Context *rsc = RsdCpuReference::getTlsContext(); - rsrForEach(rsc, (Script *)script.p, (Allocation *)in.p, (Allocation *)out.p, + rsrForEach(rsc, (Script *)script.p, 0, (Allocation *)in.p, (Allocation *)out.p, usr, 0, nullptr); } @@ -456,7 +463,7 @@ void __attribute__((overloadable)) rsForEach(::rs_script script, ::rs_allocation in, ::rs_allocation out) { Context *rsc = RsdCpuReference::getTlsContext(); - rsrForEach(rsc, (Script *)script.p, (Allocation *)in.p, (Allocation *)out.p, + rsrForEach(rsc, (Script *)script.p, 0, (Allocation *)in.p, (Allocation *)out.p, nullptr, 0, nullptr); } @@ -468,7 +475,7 @@ void __attribute__((overloadable)) rsForEach(::rs_script script, const void *usr, uint32_t usrLen) { Context *rsc = RsdCpuReference::getTlsContext(); - rsrForEach(rsc, (Script *)script.p, (Allocation *)in.p, (Allocation *)out.p, + rsrForEach(rsc, (Script *)script.p, 0, (Allocation *)in.p, (Allocation *)out.p, usr, usrLen, nullptr); } @@ -479,7 +486,7 @@ void __attribute__((overloadable)) rsForEach(::rs_script script, uint32_t usrLen, const rs_script_call *call) { Context *rsc = RsdCpuReference::getTlsContext(); - rsrForEach(rsc, (Script *)script.p, (Allocation *)in.p, (Allocation *)out.p, + rsrForEach(rsc, (Script *)script.p, 0, (Allocation *)in.p, (Allocation *)out.p, usr, usrLen, (RsScriptCall *)call); } #endif diff --git a/java/tests/RsTest/src/com/android/rs/test/RSTestCore.java b/java/tests/RsTest/src/com/android/rs/test/RSTestCore.java index 3294aed2..ecd661e9 100644 --- a/java/tests/RsTest/src/com/android/rs/test/RSTestCore.java +++ b/java/tests/RsTest/src/com/android/rs/test/RSTestCore.java @@ -85,6 +85,7 @@ public class RSTestCore { unitTests.add(new UT_foreach(this, mRes, mCtx)); unitTests.add(new UT_foreach_bounds(this, mRes, mCtx)); unitTests.add(new UT_noroot(this, mRes, mCtx)); + unitTests.add(new UT_single_source_script(this, mRes, mCtx)); unitTests.add(new UT_script_group2_pointwise(this, mRes, mCtx)); unitTests.add(new UT_script_group2_gatherscatter(this, mRes, mCtx)); unitTests.add(new UT_script_group2_nochain(this, mRes, mCtx)); diff --git a/java/tests/RsTest/src/com/android/rs/test/UT_single_source_script.java b/java/tests/RsTest/src/com/android/rs/test/UT_single_source_script.java new file mode 100644 index 00000000..5765d4e2 --- /dev/null +++ b/java/tests/RsTest/src/com/android/rs/test/UT_single_source_script.java @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.rs.test; + +import android.content.Context; +import android.content.res.Resources; +import android.renderscript.*; + +public class UT_single_source_script extends UnitTest { + private Resources mRes; + private Allocation testAllocation1, testAllocation2; + + protected UT_single_source_script(RSTestCore rstc, Resources res, Context ctx) { + super(rstc, "SingleSourceScript", ctx); + mRes = res; + } + + private void initializeGlobals(RenderScript RS, ScriptC_single_source_script s) { + Type.Builder i32TypeBuilder = new Type.Builder(RS, Element.I32(RS)); + int X = 1024; + int Y = 768; + s.set_dimX(X); + s.set_dimY(Y); + i32TypeBuilder.setX(X).setY(Y); + testAllocation1 = Allocation.createTyped(RS, i32TypeBuilder.create()); + testAllocation2 = Allocation.createTyped(RS, i32TypeBuilder.create()); + } + + public void run() { + RenderScript pRS = RenderScript.create(mCtx); + ScriptC_single_source_script s = new ScriptC_single_source_script(pRS); + pRS.setMessageHandler(mRsMessage); + initializeGlobals(pRS, s); + + s.invoke_entrypoint(testAllocation1, testAllocation2); + + pRS.finish(); + waitForMessage(); + pRS.destroy(); + } +} diff --git a/java/tests/RsTest/src/com/android/rs/test/single_source_script.rs b/java/tests/RsTest/src/com/android/rs/test/single_source_script.rs new file mode 100644 index 00000000..c71b359b --- /dev/null +++ b/java/tests/RsTest/src/com/android/rs/test/single_source_script.rs @@ -0,0 +1,54 @@ +#include "shared.rsh" + +int dimX; +int dimY; + +int __attribute__((kernel)) foo(int a) { + return a * 2; +} + +static void validate(rs_allocation out) { + bool failed = false; + + int i, j; + + for (j = 0; j < dimY; j++) { + for (i = 0; i < dimX; i++) { + const int actual = rsGetElementAt_int(out, i, j); + const int expected = (i + j * dimX) * 4; + if (actual != expected) { + failed = true; + rsDebug("row ", j); + rsDebug("column ", i); + rsDebug("expects ", expected); + rsDebug("got ", actual); + } + } + } + + if (failed) { + rsDebug("FAILED", 0); + } else { + rsDebug("PASSED", 0); + } + + if (failed) { + rsSendToClientBlocking(RS_MSG_TEST_FAILED); + } else { + rsSendToClientBlocking(RS_MSG_TEST_PASSED); + } +} + +void entrypoint(rs_allocation in, rs_allocation out) { + int i, j; + for (i = 0; i < dimX; i++) { + for (j = 0; j < dimY; j++) { + rsSetElementAt_int(in, j * dimX + i, i, j); + } + } + + rsParallelFor(foo, in, out); + rsParallelFor(foo, out, out); + + validate(out); +} diff --git a/rsRuntime.h b/rsRuntime.h index 5a058830..bcaebcdb 100644 --- a/rsRuntime.h +++ b/rsRuntime.h @@ -155,6 +155,7 @@ void rsrAllocationSyncAll(Context *, Allocation *a, RsAllocationUsageType source void rsrForEach(Context *, Script *target, + uint32_t slot, Allocation *in, Allocation *out, const void *usr, diff --git a/rsScriptC_Lib.cpp b/rsScriptC_Lib.cpp index c404bde9..9a9c57fd 100644 --- a/rsScriptC_Lib.cpp +++ b/rsScriptC_Lib.cpp @@ -236,17 +236,18 @@ void rsrAllocationIoReceive(Context *rsc, Allocation *src) { void rsrForEach(Context *rsc, Script *target, + uint32_t slot, Allocation *in, Allocation *out, const void *usr, uint32_t usrBytes, const RsScriptCall *call) { if (in == nullptr) { - target->runForEach(rsc, /* root slot */ 0, nullptr, 0, out, usr, + target->runForEach(rsc, slot, nullptr, 0, out, usr, usrBytes, call); } else { const Allocation *ins[1] = {in}; - target->runForEach(rsc, /* root slot */ 0, ins, + target->runForEach(rsc, slot, ins, sizeof(ins) / sizeof(RsAllocation), out, usr, usrBytes, call); } diff --git a/scriptc/rs_for_each.rsh b/scriptc/rs_for_each.rsh index 9771d094..a105cb22 100644 --- a/scriptc/rs_for_each.rsh +++ b/scriptc/rs_for_each.rsh @@ -91,6 +91,16 @@ typedef struct rs_script_call { } rs_script_call_t; /* + * rs_kernel: Handle to a kernel function + * + * An opaque type for a function that is defined with the kernel attribute. A value + * of this type can be used in a rsParallelFor call to launch a kernel. + */ +#if (defined(RS_VERSION) && (RS_VERSION >= 4294967295) && (defined(RS_DECLARE_EXPIRED_APIS) || RS_VERSION <= 4294967295)) +typedef void* rs_kernel; +#endif + +/* * rsForEach: Invoke the root kernel of a script * * Invoke the kernel named "root" of the specified script. Like other kernels, this root() @@ -149,6 +159,28 @@ extern void __attribute__((overloadable)) #endif /* + * rsParallelFor: Run a kernel defined in the current Script + * + * Runs the kernel over zero or more input allocations. They are passed after the + * rs_kernel argument. If the specified kernel returns a value, an output allocation + * must be specified as the last argument. All input allocations, + * and the output allocation if it exists, must have the same dimensions. + * + * This is a synchronous function. A call to this function only returns after all + * the work has completed for all cells of the input allocations. If the kernel + * function returns any value, the call would also have to wait until all results + * have been written to the output allocation. + * + * Parameters: + * kernel: Function designator to a function that is defined with the kernel attribute. + * ...: Input and output allocations + */ +#if (defined(RS_VERSION) && (RS_VERSION >= 4294967295) && (defined(RS_DECLARE_EXPIRED_APIS) || RS_VERSION <= 4294967295)) +extern void + rsParallelFor(rs_kernel kernel, ...); +#endif + +/* * rsGetArray0: Index in the Array0 dimension for the specified kernel context * * Returns the index in the Array0 dimension of the cell being processed, as specified |