Merge "Provide additional information about global variables."
diff --git a/bcinfo/Android.mk b/bcinfo/Android.mk
index ac9a370..5a55014 100644
--- a/bcinfo/Android.mk
+++ b/bcinfo/Android.mk
@@ -31,6 +31,7 @@
libbcinfo_C_INCLUDES := \
$(LOCAL_PATH)/../include \
+ $(RS_ROOT_PATH) \
$(LOCAL_PATH)/../../slang
libbcinfo_STATIC_LIBRARIES := \
diff --git a/bcinfo/MetadataExtractor.cpp b/bcinfo/MetadataExtractor.cpp
index 0282276..468e940 100644
--- a/bcinfo/MetadataExtractor.cpp
+++ b/bcinfo/MetadataExtractor.cpp
@@ -17,6 +17,7 @@
#include "bcinfo/MetadataExtractor.h"
#include "bcinfo/BitcodeWrapper.h"
+#include "rsDefines.h"
#define LOG_TAG "bcinfo"
#include <cutils/log.h>
@@ -375,8 +376,9 @@
// which means that we need to set the bottom 5 bits in the mask.
mExportForEachSignatureCount = 1;
char **TmpNameList = new char*[mExportForEachSignatureCount];
- TmpNameList[0] = new char[5];
- strncpy(TmpNameList[0], "root", 5);
+ size_t RootLen = strlen(kRoot) + 1;
+ TmpNameList[0] = new char[RootLen];
+ strncpy(TmpNameList[0], kRoot, RootLen);
uint32_t *TmpSigList = new uint32_t[mExportForEachSignatureCount];
TmpSigList[0] = 0x1f;
diff --git a/include/bcc/Renderscript/RSUtils.h b/include/bcc/Renderscript/RSUtils.h
new file mode 100644
index 0000000..d8e3684
--- /dev/null
+++ b/include/bcc/Renderscript/RSUtils.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright 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.
+ */
+
+#ifndef BCC_RS_UTILS_H
+#define BCC_RS_UTILS_H
+
+#include "rsDefines.h"
+
+#include <llvm/IR/Type.h>
+
+namespace {
+
+const char kAllocationTypeName[] = "struct.rs_allocation";
+const char kElementTypeName[] = "struct.rs_element";
+const char kSamplerTypeName[] = "struct.rs_sampler";
+const char kScriptTypeName[] = "struct.rs_script";
+const char kTypeTypeName[] = "struct.rs_type";
+
+// Returns the RsDataType for a given input LLVM type.
+// This is only used to distinguish the associated RS object types (i.e.
+// rs_allocation, rs_element, rs_sampler, rs_script, and rs_type).
+// All other types are reported back as RS_TYPE_NONE, since no special
+// handling would be necessary.
+static inline enum RsDataType getRsDataTypeForType(const llvm::Type *T) {
+ if (T->isStructTy()) {
+ // Get just the object type name with no suffix.
+ size_t LastDot = T->getStructName().rfind('.');
+ if (LastDot == strlen("struct")) {
+ // If we get back to just the "struct" part, we know that we had a
+ // raw typename (i.e. struct.rs_element with no ".[0-9]+" suffix on it.
+ // In that case, we will want to create our slice such that it contains
+ // the entire name.
+ LastDot = T->getStructName().size();
+ }
+ const llvm::StringRef StructName = T->getStructName().slice(0, LastDot);
+ if (StructName.equals(kAllocationTypeName)) {
+ return RS_TYPE_ALLOCATION;
+ } else if (StructName.equals(kElementTypeName)) {
+ return RS_TYPE_ELEMENT;
+ } else if (StructName.equals(kSamplerTypeName)) {
+ return RS_TYPE_SAMPLER;
+ } else if (StructName.equals(kScriptTypeName)) {
+ return RS_TYPE_SCRIPT;
+ } else if (StructName.equals(kTypeTypeName)) {
+ return RS_TYPE_TYPE;
+ }
+ }
+ return RS_TYPE_NONE;
+}
+
+} // end namespace
+
+#endif // BCC_RS_UTILS_H
diff --git a/lib/Core/Compiler.cpp b/lib/Core/Compiler.cpp
index 0c1ecd5..33a085b 100644
--- a/lib/Core/Compiler.cpp
+++ b/lib/Core/Compiler.cpp
@@ -40,6 +40,7 @@
#include "bcc/Support/Log.h"
#include "bcc/Support/OutputFile.h"
#include "bcinfo/MetadataExtractor.h"
+#include "rsDefines.h"
#include <string>
@@ -300,15 +301,16 @@
std::vector<const char *> export_symbols;
const char *sf[] = {
- "root", // Graphics drawing function or compute kernel.
- "init", // Initialization routine called implicitly on startup.
- ".rs.dtor", // Static global destructor for a script instance.
- ".rs.info", // Variable containing string of RS metadata info.
- ".rs.global_entries", // Optional number of global variables.
- ".rs.global_names", // Optional global variable name info.
- ".rs.global_addresses", // Optional global variable address info.
- ".rs.global_sizes", // Optional global variable size info.
- nullptr // Must be nullptr-terminated.
+ kRoot, // Graphics drawing function or compute kernel.
+ kInit, // Initialization routine called implicitly on startup.
+ kRsDtor, // Static global destructor for a script instance.
+ kRsInfo, // Variable containing string of RS metadata info.
+ kRsGlobalEntries, // Optional number of global variables.
+ kRsGlobalNames, // Optional global variable name info.
+ kRsGlobalAddresses, // Optional global variable address info.
+ kRsGlobalSizes, // Optional global variable size info.
+ kRsGlobalProperties, // Optional global variable properties.
+ nullptr // Must be nullptr-terminated.
};
const char **special_functions = sf;
// Special RS functions should always be global symbols.
diff --git a/lib/Renderscript/RSEmbedInfo.cpp b/lib/Renderscript/RSEmbedInfo.cpp
index 65f7ed7..dc1033c 100644
--- a/lib/Renderscript/RSEmbedInfo.cpp
+++ b/lib/Renderscript/RSEmbedInfo.cpp
@@ -15,7 +15,11 @@
*/
#include "bcc/Assert.h"
+#include "bcc/Config/Config.h"
#include "bcc/Renderscript/RSTransforms.h"
+#include "bcc/Support/Log.h"
+#include "bcinfo/MetadataExtractor.h"
+#include "rsDefines.h"
#include <cstdlib>
#include <vector>
@@ -29,10 +33,6 @@
#include <llvm/Support/raw_ostream.h>
#include <llvm/IR/Type.h>
-#include "bcc/Config/Config.h"
-#include "bcc/Support/Log.h"
-#include "bcinfo/MetadataExtractor.h"
-
using namespace bcc;
namespace {
@@ -142,7 +142,7 @@
llvm::GlobalVariable *InfoGV =
new llvm::GlobalVariable(M, Init->getType(), true,
llvm::GlobalValue::ExternalLinkage, Init,
- ".rs.info");
+ kRsInfo);
(void) InfoGV;
return true;
diff --git a/lib/Renderscript/RSGlobalInfoPass.cpp b/lib/Renderscript/RSGlobalInfoPass.cpp
index a4ee386..c6a14a0 100644
--- a/lib/Renderscript/RSGlobalInfoPass.cpp
+++ b/lib/Renderscript/RSGlobalInfoPass.cpp
@@ -15,8 +15,11 @@
*/
#include "bcc/Assert.h"
+#include "bcc/Renderscript/RSUtils.h"
#include "bcc/Support/Log.h"
+#include "rsDefines.h"
+
#include <llvm/IR/Constant.h>
#include <llvm/IR/Constants.h>
#include <llvm/IR/Type.h>
@@ -29,10 +32,10 @@
namespace {
-static const bool kDebugGlobalInfo = false;
+const bool kDebugGlobalInfo = false;
/* RSGlobalInfoPass: Embeds additional information about RenderScript global
- * variables into the Module. The 4 variables added are specified as follows:
+ * variables into the Module. The 5 variables added are specified as follows:
* 1) .rs.global_entries
* i32 - int
* Optional number of global variables.
@@ -48,22 +51,58 @@
* [N * i32] or [N * i64] - size_t[N]
* Optional global variable size info. Each entry corresponds to the size
* of 1 of the N global variables.
+ * 5) .rs.global_properties
+ * [N * i32]
+ * Optional global properties. Each entry corresponds to the properties
+ * for 1 of the N global variables. The 32-bit integer for properties
+ * can be broken down as follows:
+ * bit(s) Encoded value
+ * ------ -------------
+ * 18 Pointer (1 is pointer, 0 is non-pointer)
+ * 17 Static (1 is static, 0 is extern)
+ * 16 Constant (1 is const, 0 is non-const)
+ * 15 - 0 RsDataType (see frameworks/rs/rsDefines.h for more info)
*/
class RSGlobalInfoPass: public llvm::ModulePass {
private:
-
-public:
- static char ID;
-
// If true, we don't include information about immutable global variables
// in our various exported data structures.
bool mSkipConstants;
+ // Encodes properties of the GlobalVariable into a uint32_t.
+ // These values are used to populate the .rs.global_properties array.
+ static uint32_t getEncodedProperties(const llvm::GlobalVariable &GV) {
+ auto GlobalType = GV.getType()->getPointerElementType();
+
+ // We start by getting the RsDataType and placing it into our result.
+ uint32_t result = getRsDataTypeForType(GlobalType);
+ bccAssert(!(result & ~RS_GLOBAL_TYPE)); // Can only alter lower 16-bits.
+
+ if (GlobalType->isPointerTy()) {
+ // Global variables that are pointers can all be used with "bind".
+ result |= RS_GLOBAL_POINTER;
+ }
+
+ if (GV.isConstant()) {
+ result |= RS_GLOBAL_CONSTANT;
+ }
+
+ if (GV.getLinkage() == llvm::GlobalValue::InternalLinkage) {
+ // We only have internal linkage in RS to signify static.
+ result |= RS_GLOBAL_STATIC;
+ }
+
+ return result;
+ }
+
+public:
+ static char ID;
+
RSGlobalInfoPass(bool pSkipConstants = false)
: ModulePass (ID), mSkipConstants(pSkipConstants) {
}
- virtual void getAnalysisUsage(llvm::AnalysisUsage &AU) const override {
+ void getAnalysisUsage(llvm::AnalysisUsage &AU) const override {
// This pass does not use any other analysis passes, but it does
// add new global variables.
}
@@ -73,6 +112,7 @@
std::vector<llvm::Constant *> GVNames;
std::vector<uint32_t> GVSizes32;
std::vector<uint64_t> GVSizes64;
+ std::vector<uint32_t> GVProperties;
const llvm::DataLayout &DL = M.getDataLayout();
const size_t PointerSizeInBits = DL.getPointerSizeInBits();
@@ -94,12 +134,15 @@
// Since these are all global variables, their type is actually a
// pointer to the underlying data. We can extract the total underlying
// storage size by looking at the first contained type.
- auto TypeSize = DL.getTypeAllocSize(GV.getType()->getContainedType(0));
+ auto GlobalType = GV.getType()->getPointerElementType();
+ auto TypeSize = DL.getTypeAllocSize(GlobalType);
if (PointerSizeInBits == 32) {
GVSizes32.push_back(TypeSize);
} else {
GVSizes64.push_back(TypeSize);
}
+
+ GVProperties.push_back(getEncodedProperties(GV));
}
// Create the new strings for storing the names of the global variables.
@@ -122,9 +165,11 @@
if (PointerSizeInBits == 32) {
bccAssert(GVAddresses.size() == GVSizes32.size());
bccAssert(GVSizes64.size() == 0);
+ bccAssert(GVAddresses.size() == GVProperties.size());
} else {
bccAssert(GVSizes32.size() == 0);
bccAssert(GVAddresses.size() == GVSizes64.size());
+ bccAssert(GVAddresses.size() == GVProperties.size());
}
size_t NumGlobals = GVAddresses.size();
@@ -144,8 +189,11 @@
// [NumGlobals * i32] or [NumGlobals * i64]
llvm::ArrayType *SizeArrayTy = llvm::ArrayType::get(SizeTy, NumGlobals);
+ // [NumGlobals * i32]
+ llvm::ArrayType *Int32ArrayTy = llvm::ArrayType::get(Int32Ty, NumGlobals);
+
// 1) @.rs.global_entries = constant i32 NumGlobals
- llvm::Value *V = M.getOrInsertGlobal(".rs.global_entries", Int32Ty);
+ llvm::Value *V = M.getOrInsertGlobal(kRsGlobalEntries, Int32Ty);
llvm::GlobalVariable *GlobalEntries =
llvm::dyn_cast<llvm::GlobalVariable>(V);
llvm::Constant *GlobalEntriesInit =
@@ -154,7 +202,7 @@
GlobalEntries->setConstant(true);
// 2) @.rs.global_names = constant [N * i8*] [...]
- V = M.getOrInsertGlobal(".rs.global_names", VoidPtrArrayTy);
+ V = M.getOrInsertGlobal(kRsGlobalNames, VoidPtrArrayTy);
llvm::GlobalVariable *GlobalNames =
llvm::dyn_cast<llvm::GlobalVariable>(V);
llvm::Constant *GlobalNamesInit =
@@ -163,7 +211,7 @@
GlobalNames->setConstant(true);
// 3) @.rs.global_addresses = constant [N * i8*] [...]
- V = M.getOrInsertGlobal(".rs.global_addresses", VoidPtrArrayTy);
+ V = M.getOrInsertGlobal(kRsGlobalAddresses, VoidPtrArrayTy);
llvm::GlobalVariable *GlobalAddresses =
llvm::dyn_cast<llvm::GlobalVariable>(V);
llvm::Constant *GlobalAddressesInit =
@@ -173,7 +221,7 @@
// 4) @.rs.global_sizes = constant [N * i32 or i64] [...]
- V = M.getOrInsertGlobal(".rs.global_sizes", SizeArrayTy);
+ V = M.getOrInsertGlobal(kRsGlobalSizes, SizeArrayTy);
llvm::GlobalVariable *GlobalSizes =
llvm::dyn_cast<llvm::GlobalVariable>(V);
llvm::Constant *GlobalSizesInit;
@@ -185,11 +233,21 @@
GlobalSizes->setInitializer(GlobalSizesInit);
GlobalSizes->setConstant(true);
+ // 5) @.rs.global_properties = constant i32 NumGlobals
+ V = M.getOrInsertGlobal(kRsGlobalProperties, Int32ArrayTy);
+ llvm::GlobalVariable *GlobalProperties =
+ llvm::dyn_cast<llvm::GlobalVariable>(V);
+ llvm::Constant *GlobalPropertiesInit =
+ llvm::ConstantDataArray::get(M.getContext(), GVProperties);
+ GlobalProperties->setInitializer(GlobalPropertiesInit);
+ GlobalProperties->setConstant(true);
+
if (kDebugGlobalInfo) {
GlobalEntries->dump();
GlobalNames->dump();
GlobalAddresses->dump();
GlobalSizes->dump();
+ GlobalProperties->dump();
}
// Upon completion, this pass has always modified the Module.
diff --git a/lib/Renderscript/RSInvokeHelperPass.cpp b/lib/Renderscript/RSInvokeHelperPass.cpp
index 94213f5..af72ff1 100644
--- a/lib/Renderscript/RSInvokeHelperPass.cpp
+++ b/lib/Renderscript/RSInvokeHelperPass.cpp
@@ -16,6 +16,8 @@
#include "bcc/Assert.h"
#include "bcc/Renderscript/RSTransforms.h"
+#include "bcc/Renderscript/RSUtils.h"
+#include "rsDefines.h"
#include <cstdlib>
@@ -73,11 +75,11 @@
llvm::SmallVector<llvm::Type*, 4> rsBaseObj;
rsBaseObj.append(4, llvm::Type::getInt64PtrTy(M.getContext()));
- rsAllocationType = llvm::StructType::create(rsBaseObj, "struct.rs_allocation");
- rsElementType = llvm::StructType::create(rsBaseObj, "struct.rs_element");
- rsSamplerType = llvm::StructType::create(rsBaseObj, "struct.rs_sampler");
- rsScriptType = llvm::StructType::create(rsBaseObj, "struct.rs_script");
- rsTypeType = llvm::StructType::create(rsBaseObj, "struct.rs_type");
+ rsAllocationType = llvm::StructType::create(rsBaseObj, kAllocationTypeName);
+ rsElementType = llvm::StructType::create(rsBaseObj, kElementTypeName);
+ rsSamplerType = llvm::StructType::create(rsBaseObj, kSamplerTypeName);
+ rsScriptType = llvm::StructType::create(rsBaseObj, kScriptTypeName);
+ rsTypeType = llvm::StructType::create(rsBaseObj, kTypeTypeName);
llvm::SmallVector<llvm::Value*, 1> SetObjParams;
llvm::SmallVector<llvm::Type*, 2> SetObjTypeParams;
@@ -117,25 +119,31 @@
return true;
}
- bool insertSetObjectHelper(llvm::CallInst *Call, llvm::Value *V, llvm::StringRef StructName) {
+ bool insertSetObjectHelper(llvm::CallInst *Call, llvm::Value *V, enum RsDataType DT) {
llvm::Constant *SetObj = nullptr;
llvm::StructType *RSStructType = nullptr;
- if (StructName.equals(rsAllocationType->getName())) {
+ switch (DT) {
+ case RS_TYPE_ALLOCATION:
SetObj = rsAllocationSetObj;
RSStructType = rsAllocationType;
- } else if (StructName.equals(rsElementType->getName())) {
+ break;
+ case RS_TYPE_ELEMENT:
SetObj = rsElementSetObj;
RSStructType = rsElementType;
- } else if (StructName.equals(rsSamplerType->getName())) {
+ break;
+ case RS_TYPE_SAMPLER:
SetObj = rsSamplerSetObj;
RSStructType = rsSamplerType;
- } else if (StructName.equals(rsScriptType->getName())) {
+ break;
+ case RS_TYPE_SCRIPT:
SetObj = rsScriptSetObj;
RSStructType = rsScriptType;
- } else if (StructName.equals(rsTypeType->getName())) {
+ break;
+ case RS_TYPE_TYPE:
SetObj = rsTypeSetObj;
RSStructType = rsTypeType;
- } else {
+ break;
+ default:
return false; // this is for graphics types and matrices; do nothing
}
@@ -191,14 +199,14 @@
if (llvm::CallInst *call = llvm::dyn_cast<llvm::CallInst>(&Inst)) {
for (unsigned int i = 0; i < call->getNumArgOperands(); i++) {
llvm::Value *V = call->getArgOperand(i);
- if (V->getType()->isPointerTy() && V->getType()->getPointerElementType()->isStructTy() &&
- V->getType()->getPointerElementType()->getStructName().startswith("struct.rs_")) {
- // get just the object type name with no prefix or suffix
- size_t LastDot = V->getType()->getPointerElementType()->getStructName().rfind('.');
- llvm::StringRef StructName = V->getType()->getPointerElementType()->getStructName().slice(0, LastDot);
-
+ llvm::Type *T = V->getType();
+ enum RsDataType DT = RS_TYPE_NONE;
+ if (T->isPointerTy() && T->getPointerElementType()->isStructTy()) {
+ DT = getRsDataTypeForType(T->getPointerElementType());
+ }
+ if (DT != RS_TYPE_NONE) {
// generate the new call instruction and insert it
- changed |= insertSetObjectHelper(call, V, StructName);
+ changed |= insertSetObjectHelper(call, V, DT);
}
}
}
diff --git a/libbcc-device-build.mk b/libbcc-device-build.mk
index 0945980..188f2f9 100644
--- a/libbcc-device-build.mk
+++ b/libbcc-device-build.mk
@@ -51,9 +51,8 @@
include frameworks/compile/libbcc/libbcc-targets.mk
LOCAL_C_INCLUDES := \
- bionic \
- external/libcxx/include \
$(LIBBCC_ROOT_PATH)/include \
+ $(RS_ROOT_PATH) \
$(LLVM_ROOT_PATH)/include \
$(LLVM_ROOT_PATH)/device/include \
$(LOCAL_C_INCLUDES)
diff --git a/libbcc-host-build.mk b/libbcc-host-build.mk
index 5ccd657..3a8839f 100644
--- a/libbcc-host-build.mk
+++ b/libbcc-host-build.mk
@@ -42,6 +42,7 @@
LOCAL_C_INCLUDES := \
$(LIBBCC_ROOT_PATH)/include \
+ $(RS_ROOT_PATH) \
$(LLVM_ROOT_PATH)/include \
$(LLVM_ROOT_PATH)/host/include \
$(LOCAL_C_INCLUDES)
diff --git a/libbcc.mk b/libbcc.mk
index 41b0fe7..c3775b2 100644
--- a/libbcc.mk
+++ b/libbcc.mk
@@ -23,6 +23,7 @@
#=====================================================================
LLVM_ROOT_PATH := external/llvm
+RS_ROOT_PATH := frameworks/rs
#=====================================================================
# Related Makefile Paths of libbcc