Merge "Change libbcc so that it compiles as an LLVM loadable module (try 2)."
diff --git a/bcinfo/MetadataExtractor.cpp b/bcinfo/MetadataExtractor.cpp
index 468e940..23d97fe 100644
--- a/bcinfo/MetadataExtractor.cpp
+++ b/bcinfo/MetadataExtractor.cpp
@@ -56,8 +56,75 @@
return false;
}
+const char *createStringFromValue(llvm::Metadata *m) {
+ auto ref = getStringOperand(m);
+ char *c = new char[ref.size() + 1];
+ memcpy(c, ref.data(), ref.size());
+ c[ref.size()] = '\0';
+ return c;
}
+// Collect metadata from NamedMDNodes that contain a list of names
+// (strings).
+//
+// Inputs:
+//
+// NamedMetadata - An LLVM metadata node, each of whose operands have
+// a string as their first entry
+//
+// NameList - A reference that will hold an allocated array of strings
+//
+// Count - A reference that will hold the length of the allocated
+// array of strings
+//
+// Return value:
+//
+// Return true on success, false on error.
+//
+// Upon success, the function sets NameList to an array of strings
+// corresponding the names found in the metadata. The function sets
+// Count to the number of entries in NameList.
+//
+// An error occurs if one of the metadata operands doesn't have a
+// first entry.
+bool populateNameMetadata(const llvm::NamedMDNode *NameMetadata,
+ const char **&NameList, size_t &Count) {
+ if (!NameMetadata) {
+ NameList = nullptr;
+ Count = 0;
+ return true;
+ }
+
+ Count = NameMetadata->getNumOperands();
+ if (!Count) {
+ NameList = nullptr;
+ return true;
+ }
+
+ NameList = new const char *[Count];
+
+ for (size_t i = 0; i < Count; i++) {
+ llvm::MDNode *Name = NameMetadata->getOperand(i);
+ if (Name && Name->getNumOperands() > 0) {
+ NameList[i] = createStringFromValue(Name->getOperand(0));
+ } else {
+ ALOGE("Metadata operand does not contain a name string");
+ for (size_t AllocatedIndex = 0; AllocatedIndex < i; AllocatedIndex++) {
+ delete [] NameList[AllocatedIndex];
+ }
+ delete [] NameList;
+ NameList = nullptr;
+ Count = 0;
+
+ return false;
+ }
+ }
+
+ return true;
+}
+
+} // end anonymous namespace
+
// Name of metadata node where pragma info resides (should be synced with
// slang.cpp)
static const llvm::StringRef PragmaMetadataName = "#pragma";
@@ -79,6 +146,10 @@
// (should be synced with slang_rs_metadata.h)
static const llvm::StringRef ExportForEachMetadataName = "#rs_export_foreach";
+// Name of metadata node where exported reduce name information resides
+// (should be synced with slang_rs_metadata.h)
+static const llvm::StringRef ExportReduceMetadataName = "#rs_export_reduce";
+
// Name of metadata node where RS object slot info resides (should be
// synced with slang_rs_metadata.h)
static const llvm::StringRef ObjectSlotMetadataName = "#rs_object_slots";
@@ -92,28 +163,31 @@
MetadataExtractor::MetadataExtractor(const char *bitcode, size_t bitcodeSize)
: mModule(nullptr), mBitcode(bitcode), mBitcodeSize(bitcodeSize),
mExportVarCount(0), mExportFuncCount(0), mExportForEachSignatureCount(0),
- mExportVarNameList(nullptr), mExportFuncNameList(nullptr),
- mExportForEachNameList(nullptr), mExportForEachSignatureList(nullptr),
- mExportForEachInputCountList(nullptr), mPragmaCount(0),
- mPragmaKeyList(nullptr), mPragmaValueList(nullptr), mObjectSlotCount(0),
- mObjectSlotList(nullptr), mRSFloatPrecision(RS_FP_Full),
- mIsThreadable(true), mBuildChecksum(nullptr) {
+ mExportReduceCount(0), mExportVarNameList(nullptr),
+ mExportFuncNameList(nullptr), mExportForEachNameList(nullptr),
+ mExportForEachSignatureList(nullptr),
+ mExportForEachInputCountList(nullptr), mExportReduceNameList(nullptr),
+ mPragmaCount(0), mPragmaKeyList(nullptr), mPragmaValueList(nullptr),
+ mObjectSlotCount(0), mObjectSlotList(nullptr),
+ mRSFloatPrecision(RS_FP_Full), mIsThreadable(true),
+ mBuildChecksum(nullptr) {
BitcodeWrapper wrapper(bitcode, bitcodeSize);
mTargetAPI = wrapper.getTargetAPI();
mCompilerVersion = wrapper.getCompilerVersion();
mOptimizationLevel = wrapper.getOptimizationLevel();
}
-
MetadataExtractor::MetadataExtractor(const llvm::Module *module)
- : mModule(module), mBitcode(nullptr), mBitcodeSize(0), mExportVarCount(0),
- mExportFuncCount(0), mExportForEachSignatureCount(0),
- mExportVarNameList(nullptr), mExportFuncNameList(nullptr),
- mExportForEachNameList(nullptr), mExportForEachSignatureList(nullptr),
- mExportForEachInputCountList(nullptr), mPragmaCount(0),
- mPragmaKeyList(nullptr), mPragmaValueList(nullptr), mObjectSlotCount(0),
- mObjectSlotList(nullptr), mRSFloatPrecision(RS_FP_Full),
- mIsThreadable(true), mBuildChecksum(nullptr) {
+ : mModule(module), mBitcode(nullptr), mBitcodeSize(0),
+ mExportVarCount(0), mExportFuncCount(0), mExportForEachSignatureCount(0),
+ mExportReduceCount(0), mExportVarNameList(nullptr),
+ mExportFuncNameList(nullptr), mExportForEachNameList(nullptr),
+ mExportForEachSignatureList(nullptr),
+ mExportForEachInputCountList(nullptr), mExportReduceNameList(nullptr),
+ mPragmaCount(0), mPragmaKeyList(nullptr), mPragmaValueList(nullptr),
+ mObjectSlotCount(0), mObjectSlotList(nullptr),
+ mRSFloatPrecision(RS_FP_Full), mIsThreadable(true),
+ mBuildChecksum(nullptr) {
mCompilerVersion = RS_VERSION; // Default to the actual current version.
mOptimizationLevel = 3;
}
@@ -150,6 +224,15 @@
delete [] mExportForEachSignatureList;
mExportForEachSignatureList = nullptr;
+ if (mExportReduceNameList) {
+ for (size_t i = 0; i < mExportReduceCount; i++) {
+ delete [] mExportReduceNameList[i];
+ mExportReduceNameList[i] = nullptr;
+ }
+ }
+ delete [] mExportReduceNameList;
+ mExportReduceNameList = nullptr;
+
for (size_t i = 0; i < mPragmaCount; i++) {
if (mPragmaKeyList) {
delete [] mPragmaKeyList[i];
@@ -208,15 +291,6 @@
}
-static const char *createStringFromValue(llvm::Metadata *m) {
- auto ref = getStringOperand(m);
- char *c = new char[ref.size() + 1];
- memcpy(c, ref.data(), ref.size());
- c[ref.size()] = '\0';
- return c;
-}
-
-
void MetadataExtractor::populatePragmaMetadata(
const llvm::NamedMDNode *PragmaMetadata) {
if (!PragmaMetadata) {
@@ -292,59 +366,6 @@
#endif
}
-
-bool MetadataExtractor::populateVarNameMetadata(
- const llvm::NamedMDNode *VarNameMetadata) {
- if (!VarNameMetadata) {
- return true;
- }
-
- mExportVarCount = VarNameMetadata->getNumOperands();
- if (!mExportVarCount) {
- return true;
- }
-
- const char **TmpNameList = new const char *[mExportVarCount];
-
- for (size_t i = 0; i < mExportVarCount; i++) {
- llvm::MDNode *Name = VarNameMetadata->getOperand(i);
- if (Name != nullptr && Name->getNumOperands() > 1) {
- TmpNameList[i] = createStringFromValue(Name->getOperand(0));
- }
- }
-
- mExportVarNameList = TmpNameList;
-
- return true;
-}
-
-
-bool MetadataExtractor::populateFuncNameMetadata(
- const llvm::NamedMDNode *FuncNameMetadata) {
- if (!FuncNameMetadata) {
- return true;
- }
-
- mExportFuncCount = FuncNameMetadata->getNumOperands();
- if (!mExportFuncCount) {
- return true;
- }
-
- const char **TmpNameList = new const char*[mExportFuncCount];
-
- for (size_t i = 0; i < mExportFuncCount; i++) {
- llvm::MDNode *Name = FuncNameMetadata->getOperand(i);
- if (Name != nullptr && Name->getNumOperands() == 1) {
- TmpNameList[i] = createStringFromValue(Name->getOperand(0));
- }
- }
-
- mExportFuncNameList = TmpNameList;
-
- return true;
-}
-
-
uint32_t MetadataExtractor::calculateNumInputs(const llvm::Function *Function,
uint32_t Signature) {
@@ -521,6 +542,8 @@
mModule->getNamedMetadata(ExportForEachNameMetadataName);
const llvm::NamedMDNode *ExportForEachMetadata =
mModule->getNamedMetadata(ExportForEachMetadataName);
+ const llvm::NamedMDNode *ExportReduceMetadata =
+ mModule->getNamedMetadata(ExportReduceMetadataName);
const llvm::NamedMDNode *PragmaMetadata =
mModule->getNamedMetadata(PragmaMetadataName);
const llvm::NamedMDNode *ObjectSlotMetadata =
@@ -530,17 +553,24 @@
const llvm::NamedMDNode *ChecksumMetadata =
mModule->getNamedMetadata(ChecksumMetadataName);
-
- if (!populateVarNameMetadata(ExportVarMetadata)) {
+ if (!populateNameMetadata(ExportVarMetadata, mExportVarNameList,
+ mExportVarCount)) {
ALOGE("Could not populate export variable metadata");
return false;
}
- if (!populateFuncNameMetadata(ExportFuncMetadata)) {
+ if (!populateNameMetadata(ExportFuncMetadata, mExportFuncNameList,
+ mExportFuncCount)) {
ALOGE("Could not populate export function metadata");
return false;
}
+ if (!populateNameMetadata(ExportReduceMetadata, mExportReduceNameList,
+ mExportReduceCount)) {
+ ALOGE("Could not populate export reduce metadata");
+ return false;
+ }
+
if (!populateForEachMetadata(ExportForEachNameMetadata,
ExportForEachMetadata)) {
ALOGE("Could not populate ForEach signature metadata");
diff --git a/bcinfo/tools/main.cpp b/bcinfo/tools/main.cpp
index 0921151..c4e40f4 100644
--- a/bcinfo/tools/main.cpp
+++ b/bcinfo/tools/main.cpp
@@ -143,6 +143,12 @@
inputCountList[i]);
}
+ fprintf(info, "exportReduceCount: %zu\n", ME->getExportReduceCount());
+ const char **reduceNameList = ME->getExportReduceNameList();
+ for (size_t i = 0; i < ME->getExportReduceCount(); i++) {
+ fprintf(info, "%s\n", reduceNameList[i]);
+ }
+
fprintf(info, "objectSlotCount: %zu\n", ME->getObjectSlotCount());
const uint32_t *slotList = ME->getObjectSlotList();
for (size_t i = 0; i < ME->getObjectSlotCount(); i++) {
@@ -197,6 +203,13 @@
}
printf("\n");
+ printf("exportReduceCount: %zu\n", ME->getExportReduceCount());
+ const char **reduceNameList = ME->getExportReduceNameList();
+ for (size_t i = 0; i < ME->getExportReduceCount(); i++) {
+ printf("func[%zu]: %s\n", i, reduceNameList[i]);
+ }
+ printf("\n");
+
printf("pragmaCount: %zu\n", ME->getPragmaCount());
const char **keyList = ME->getPragmaKeyList();
const char **valueList = ME->getPragmaValueList();
diff --git a/include/bcinfo/MetadataExtractor.h b/include/bcinfo/MetadataExtractor.h
index 99818ca..742346a 100644
--- a/include/bcinfo/MetadataExtractor.h
+++ b/include/bcinfo/MetadataExtractor.h
@@ -54,12 +54,13 @@
size_t mExportVarCount;
size_t mExportFuncCount;
size_t mExportForEachSignatureCount;
+ size_t mExportReduceCount;
const char **mExportVarNameList;
const char **mExportFuncNameList;
const char **mExportForEachNameList;
const uint32_t *mExportForEachSignatureList;
-
const uint32_t *mExportForEachInputCountList;
+ const char **mExportReduceNameList;
size_t mPragmaCount;
const char **mPragmaKeyList;
@@ -80,8 +81,6 @@
const char *mBuildChecksum;
// Helper functions for extraction
- bool populateVarNameMetadata(const llvm::NamedMDNode *VarNameMetadata);
- bool populateFuncNameMetadata(const llvm::NamedMDNode *FuncNameMetadata);
bool populateForEachMetadata(const llvm::NamedMDNode *Names,
const llvm::NamedMDNode *Signatures);
bool populateObjectSlotMetadata(const llvm::NamedMDNode *ObjectSlotMetadata);
@@ -184,6 +183,20 @@
}
/**
+ * \return number of exported reduce kernels (slots) in this script/module.
+ */
+ size_t getExportReduceCount() const {
+ return mExportReduceCount;
+ }
+
+ /**
+ * \return array of exported reduce kernel names.
+ */
+ const char **getExportReduceNameList() const {
+ return mExportReduceNameList;
+ }
+
+ /**
* \return number of pragmas contained in pragmaKeyList and pragmaValueList.
*/
size_t getPragmaCount() const {
diff --git a/tests/libbcc/lit.cfg b/tests/libbcc/lit.cfg
new file mode 100644
index 0000000..5b3c749
--- /dev/null
+++ b/tests/libbcc/lit.cfg
@@ -0,0 +1,46 @@
+# -*- Python -*-
+
+# Configuration file for the 'lit' test runner.
+
+import re
+
+# name: The name of this test suite.
+config.name = 'libbcc'
+
+# suffixes: A list of file extensions to treat as test files.
+config.suffixes = ['.ll']
+
+# testFormat: The test format to use to interpret tests.
+import lit.formats
+config.test_format = lit.formats.ShTest()
+
+ANDROID_HOST_OUT = os.getenv("ANDROID_HOST_OUT")
+ANDROID_PRODUCT_OUT = os.getenv("ANDROID_PRODUCT_OUT")
+
+if not ANDROID_HOST_OUT or not ANDROID_PRODUCT_OUT:
+ import sys
+ sys.exit(1)
+
+# test_source_root: The path where tests are located (default is the test suite
+# root).
+config.test_source_root = None
+config.test_exec_root = os.path.join(ANDROID_HOST_OUT, 'tests', 'bcinfo')
+
+tools_dir = os.path.join(ANDROID_HOST_OUT, 'bin')
+
+# Based on LLVM's lit.cfg: "For each occurrence of an llvm tool name
+# as its own word, replace it with the full path to the build directory
+# holding that tool."
+for pattern in [r"\bFileCheck\b",
+ r"\bllvm-rs-as\b",
+ r"\bbcinfo\b"]:
+ tool_match = re.match(r"^(\\)?((\| )?)\W+b([0-9A-Za-z-_]+)\\b\W*$",
+ pattern)
+ tool_pipe = tool_match.group(2)
+ tool_name = tool_match.group(4)
+ import lit.util
+ tool_path = lit.util.which(tool_name, tools_dir)
+ if not tool_path:
+ lit_config.note("Did not find " + tool_name + " in " + tools_dir)
+ tool_path = os.path.join(tools_dir, tool_name)
+ config.substitutions.append((pattern, tool_pipe + tool_path))
diff --git a/tests/libbcc/test_reduce_metadata.ll b/tests/libbcc/test_reduce_metadata.ll
new file mode 100644
index 0000000..aea8f36
--- /dev/null
+++ b/tests/libbcc/test_reduce_metadata.ll
@@ -0,0 +1,28 @@
+; Check that the #rs_export_reduce node is recognized.
+
+; RUN: llvm-rs-as %s -o %t
+; RUN: bcinfo %t | FileCheck %s
+
+; CHECK: exportReduceCount: 1
+; CHECK: func[0]: add
+
+; ModuleID = 'reduce.bc'
+target datalayout = "e-m:e-i64:64-i128:128-n32:64-S128"
+target triple = "aarch64-none-linux-gnueabi"
+
+; Function Attrs: nounwind readnone
+define i32 @add(i32 %a, i32 %b) #0 {
+ %1 = add nsw i32 %b, %a
+ ret i32 %1
+}
+
+attributes #0 = { nounwind readnone }
+
+!llvm.ident = !{!0}
+!\23pragma = !{!1, !2}
+!\23rs_export_reduce = !{!3}
+
+!0 = !{!"clang version 3.6 "}
+!1 = !{!"version", !"1"}
+!2 = !{!"java_package_name", !"com.android.rs.test"}
+!3 = !{!"add"}
diff --git a/tests/run-lit-tests.sh b/tests/run-lit-tests.sh
new file mode 100755
index 0000000..8976555
--- /dev/null
+++ b/tests/run-lit-tests.sh
@@ -0,0 +1,6 @@
+#!/bin/bash -e
+
+LIT_PATH=$ANDROID_BUILD_TOP/frameworks/compile/libbcc/tests/debuginfo/llvm-lit
+LIBBCC_TESTS=$ANDROID_BUILD_TOP/frameworks/compile/libbcc/tests/libbcc
+
+$LIT_PATH $LIBBCC_TESTS $@