summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYang Ni <yangni@google.com>2015-10-23 22:00:42 +0000
committerGerrit Code Review <noreply-gerritcodereview@google.com>2015-10-23 22:00:42 +0000
commit4a21e4dc4274dbf7d3ddad62e2cc1a9f25864a5f (patch)
treebb722c41615b53e21ac5c811fe02819821cde97c
parent75e9f10b5d26a2feb03dc7bb4ad39514ec3e8660 (diff)
parent12398d81f32e5e0479d02b8608a83c75cd991bb3 (diff)
downloadrs-brillo-m7-mr-dev.tar.gz
-rw-r--r--api/GenerateHeaderFiles.cpp8
-rw-r--r--api/GenerateStubsWhiteList.cpp42
-rw-r--r--api/GenerateTestFiles.cpp6
-rw-r--r--api/Generator.cpp16
-rw-r--r--api/Generator.h4
-rw-r--r--api/Scanner.cpp9
-rw-r--r--api/Specification.cpp62
-rw-r--r--api/Specification.h33
-rw-r--r--api/Utilities.cpp2
-rw-r--r--api/Utilities.h2
-rwxr-xr-xapi/generate.sh2
-rw-r--r--api/rs_for_each.spec42
-rw-r--r--driver/rsdRuntimeStubs.cpp17
-rw-r--r--java/tests/RsTest/src/com/android/rs/test/RSTestCore.java1
-rw-r--r--java/tests/RsTest/src/com/android/rs/test/UT_single_source_script.java55
-rw-r--r--java/tests/RsTest/src/com/android/rs/test/single_source_script.rs54
-rw-r--r--rsRuntime.h1
-rw-r--r--rsScriptC_Lib.cpp5
-rw-r--r--scriptc/rs_for_each.rsh32
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