Provide additional information about global variables.
Bug: 20306487
This patch extends our global information pass to include details about the
type of a global variable, whether or not it is static, constant, or a
pointer. It also refactors code that deals with conversion between
RenderScript's internal data types and LLVM's type system. A subtle bug
has also been fixed with respect to the RSInvokeHelperPass. The previous
version could ignore an rs_* object that did not have a numeric suffix.
The new helper function properly addresses cases like this.
Change-Id: If9c933a885bf6a9063b7edec3f0873e1b144188d
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);
}
}
}