Index: src/IceConverter.cpp |
diff --git a/src/IceConverter.cpp b/src/IceConverter.cpp |
index 9d59c56980f072b8215de1b0acda4dfcfafce45e..ed9f13aabd87e7ceea8c2ebcf05bc99bd42117e1 100644 |
--- a/src/IceConverter.cpp |
+++ b/src/IceConverter.cpp |
@@ -27,6 +27,7 @@ |
#include "IceConverter.h" |
#include "IceDefs.h" |
#include "IceGlobalContext.h" |
+#include "IceGlobalInits.h" |
#include "IceInst.h" |
#include "IceOperand.h" |
#include "IceTargetLowering.h" |
@@ -45,17 +46,29 @@ template <typename T> static std::string LLVMObjectAsString(const T *O) { |
return Stream.str(); |
} |
-// Converter from LLVM to ICE. The entry point is the convertFunction method. |
+// Base class for converting LLVM to ICE. |
+class LLVM2ICEConverter { |
+public: |
+ LLVM2ICEConverter(Ice::GlobalContext *Ctx, LLVMContext &LLVMContext) |
+ : Ctx(Ctx), TypeConverter(LLVMContext) {} |
+ |
+protected: |
+ // Data |
+ Ice::GlobalContext *Ctx; |
+ Ice::TypeConverter TypeConverter; |
jvoung (off chromium)
2014/10/03 16:15:29
Could disallow copy / assign.
Karl
2014/10/04 16:28:33
Done.
|
+}; |
+ |
+// Converter from LLVM functions to ICE. The entry point is the |
+// convertFunction method. |
// |
-// Note: this currently assumes that the given IR was verified to be valid PNaCl |
-// bitcode: |
+// Note: this currently assumes that the given IR was verified to be |
+// valid PNaCl bitcode: |
// https://developers.google.com/native-client/dev/reference/pnacl-bitcode-abi |
// If not, all kinds of assertions may fire. |
-// |
-class LLVM2ICEConverter { |
+class LLVM2ICEFunctionConverter : LLVM2ICEConverter { |
public: |
- LLVM2ICEConverter(Ice::GlobalContext *Ctx, LLVMContext &LLVMContext) |
- : Ctx(Ctx), Func(NULL), TypeConverter(LLVMContext) {} |
+ LLVM2ICEFunctionConverter(Ice::GlobalContext *Ctx, LLVMContext &LLVMContext) |
+ : LLVM2ICEConverter(Ctx, LLVMContext), Func(NULL) {} |
// Caller is expected to delete the returned Ice::Cfg object. |
Ice::Cfg *convertFunction(const Function *F) { |
@@ -611,13 +624,185 @@ private: |
private: |
// Data |
- Ice::GlobalContext *Ctx; |
Ice::Cfg *Func; |
std::map<const Value *, Ice::Variable *> VarMap; |
std::map<const BasicBlock *, Ice::CfgNode *> NodeMap; |
- Ice::TypeConverter TypeConverter; |
}; |
+// Converter from LLVM global variables to ICE. The entry point is the |
+// convertGlobalsToIce method. |
+// |
+// Note: this currently assumes that the given IR was verified to be |
+// valid PNaCl bitcode: |
+// https://developers.google.com/native-client/dev/reference/pnacl-bitcode-abi |
+// If not, all kinds of assertions may fire. |
+class LLVM2ICEGlobalsConverter : public LLVM2ICEConverter { |
+public: |
+ LLVM2ICEGlobalsConverter(Ice::GlobalContext *Ctx, LLVMContext &LLVMContext) |
+ : LLVM2ICEConverter(Ctx, LLVMContext) {} |
+ |
+ ~LLVM2ICEGlobalsConverter() { |
+ llvm::DeleteContainerSeconds(GlobalVarAddressMap); |
+ } |
+ |
+ /// Converts global variables, and their initializers into ICE global |
+ /// addresses, for module Mod. Puts corresponding converted global |
+ /// addresses into GlobalAddresses. |
+ void convertGlobalsToIce(llvm::Module *Mod, |
+ std::vector<Ice::GlobalAddress *> &GlobalAddresses); |
Jim Stichnoth
2014/10/03 01:28:08
Can you make a typedef for std::vector<Ice::Global
Karl
2014/10/04 16:28:33
Added typedef Translator::GlobalAddressList.
Adde
|
+ |
+private: |
+ // Map from global variables to thier corresponding global address. |
Jim Stichnoth
2014/10/03 01:28:08
their
Karl
2014/10/04 16:28:33
Done.
|
+ std::map<const llvm::GlobalVariable *, Ice::GlobalAddress *> |
+ GlobalVarAddressMap; |
+ |
+ // Adds the Initializer to the list of initializers for Global address. |
+ void AddGlobalInitializer(Ice::GlobalAddress &Global, |
jvoung (off chromium)
2014/10/03 16:15:29
method name consistency: "addGlobalInitializer" in
Karl
2014/10/04 16:28:33
Done.
|
+ const llvm::Constant *Initializer) { |
+ AddGlobalInitializer(Global, Initializer, false, 0); |
jvoung (off chromium)
2014/10/03 16:15:29
nit: For some of the other code in Subzero, there
Karl
2014/10/04 16:28:33
Done.
|
+ } |
+ |
+ // Adds Initializer to the list of initializers for Global |
+ // address. HasOffset is true only if Initializer is a relocation |
+ // initializer and Offset should be added to the relocation. |
+ void AddGlobalInitializer(Ice::GlobalAddress &Global, |
+ const llvm::Constant *Initializer, bool HasOffset, |
+ Ice::GlobalAddress::RelocOffsetType Offset); |
+ |
+ // Returns the global address associated with global variable GV. |
+ Ice::GlobalAddress *getGlobalVarAddress(const llvm::GlobalVariable *GV) { |
+ Ice::GlobalAddress *Addr = GlobalVarAddressMap[GV]; |
Jim Stichnoth
2014/10/03 01:28:08
Maybe better form to do something like this?
if
Karl
2014/10/04 16:28:33
Done.
|
+ if (Addr) |
+ return Addr; |
+ Addr = new Ice::GlobalAddress(); |
+ GlobalVarAddressMap[GV] = Addr; |
+ return Addr; |
+ } |
+ |
+ // Converts the given constant C to the corresponding integer |
+ // literal it contains. |
+ Ice::GlobalAddress::RelocOffsetType |
+ getIntegerLiteralConstant(const llvm::Value *C) { |
+ const llvm::ConstantInt *CI = llvm::dyn_cast<llvm::ConstantInt>(C); |
Jim Stichnoth
2014/10/03 01:28:08
if (auto CI = llvm::dyn_cast<const llvm::ConstantI
Karl
2014/10/04 16:28:33
Fixed all occurrences in file.
|
+ if (CI && CI->getType()->isIntegerTy(32)) |
+ return CI->getSExtValue(); |
+ |
+ std::string Buffer; |
+ raw_string_ostream StrBuf(Buffer); |
+ StrBuf << "Constant not i32 literal: " << *C; |
+ report_fatal_error(StrBuf.str()); |
+ return 0; |
+ } |
+}; |
+ |
+void LLVM2ICEGlobalsConverter::convertGlobalsToIce( |
+ llvm::Module *Mod, std::vector<Ice::GlobalAddress *> &GlobalAddresses) { |
+ for (llvm::Module::const_global_iterator I = Mod->global_begin(), |
+ E = Mod->global_end(); |
+ I != E; ++I) { |
+ if (!I->hasInitializer()) |
+ continue; |
jvoung (off chromium)
2014/10/03 16:15:29
For the PNaCl ABI, should we be stricter? I though
Karl
2014/10/04 16:28:33
I agree. I was being lazy because there is a test
|
+ |
+ const llvm::GlobalVariable *GV = llvm::dyn_cast<GlobalVariable>(I); |
+ assert(GV); |
Jim Stichnoth
2014/10/03 01:28:08
If you're going to assert(GV), might as well use l
Karl
2014/10/04 16:28:33
Not sure what you are asking. Are you asking to pu
|
+ Ice::IceString Name = GV->getName(); |
+ if (!GV->hasInternalLinkage()) { |
+ std::string Buffer; |
+ raw_string_ostream StrBuf(Buffer); |
+ StrBuf << "Can't define external global address: " << Name; |
+ report_fatal_error(StrBuf.str()); |
+ } |
+ |
+ Ice::GlobalAddress *Addr = getGlobalVarAddress(GV); |
+ GlobalAddresses.push_back(Addr); |
+ Addr->setAlignment(GV->getAlignment()); |
+ Addr->setIsConstant(GV->isConstant()); |
+ Addr->setName(Name); |
+ |
+ const llvm::Constant *Initializer = GV->getInitializer(); |
+ if (const llvm::ConstantStruct *CompoundInit = |
+ dyn_cast<llvm::ConstantStruct>(Initializer)) { |
+ for (llvm::ConstantStruct::const_op_iterator i = CompoundInit->op_begin(), |
Jim Stichnoth
2014/10/03 01:28:08
Use I and E instead of i and e for consistency?
Karl
2014/10/04 16:28:33
Done.
|
+ e = CompoundInit->op_end(); |
+ i != e; ++i) { |
+ if (const llvm::Constant *Init = dyn_cast<llvm::Constant>(i)) { |
+ AddGlobalInitializer(*Addr, Init); |
+ } |
jvoung (off chromium)
2014/10/03 16:15:29
What are the possible "else" here, and should it b
Karl
2014/10/04 16:28:33
The format in PNaCl ABI is that the struct is part
|
+ } |
+ } else { |
+ AddGlobalInitializer(*Addr, Initializer); |
+ } |
+ } |
+} |
+ |
+void LLVM2ICEGlobalsConverter::AddGlobalInitializer( |
+ Ice::GlobalAddress &Global, const llvm::Constant *Initializer, |
+ bool HasOffset, Ice::GlobalAddress::RelocOffsetType Offset) { |
+ assert(HasOffset || Offset == 0); |
+ |
+ if (const llvm::ConstantDataArray *CDA = |
+ llvm::dyn_cast<llvm::ConstantDataArray>(Initializer)) { |
+ assert(!HasOffset && llvm::isa<llvm::IntegerType>(CDA->getElementType()) && |
+ (llvm::cast<llvm::IntegerType>(CDA->getElementType()) |
+ ->getBitWidth() == 8)); |
+ Global.AddInitializer(new Ice::GlobalAddress::DataInitializer( |
+ CDA->getRawDataValues().data(), CDA->getNumElements())); |
+ return; |
+ } |
+ |
+ if (llvm::isa<llvm::ConstantAggregateZero>(Initializer)) { |
+ if (const llvm::ArrayType *AT = |
+ llvm::dyn_cast<llvm::ArrayType>(Initializer->getType())) { |
+ assert(!HasOffset && llvm::isa<llvm::IntegerType>(AT->getElementType()) && |
+ (llvm::cast<llvm::IntegerType>(AT->getElementType()) |
+ ->getBitWidth() == 8)); |
+ Global.AddInitializer( |
+ new Ice::GlobalAddress::ZeroInitializer(AT->getNumElements())); |
+ } else { |
+ llvm_unreachable("Unhandled constant aggregate zero type"); |
+ } |
+ return; |
+ } |
+ |
+ if (const ConstantExpr *Exp = |
+ llvm::dyn_cast<llvm::ConstantExpr>(Initializer)) { |
+ switch (Exp->getOpcode()) { |
+ case Instruction::Add: |
+ assert(!HasOffset); |
+ AddGlobalInitializer(Global, Exp->getOperand(0), true, |
+ getIntegerLiteralConstant(Exp->getOperand(1))); |
+ return; |
+ case Instruction::PtrToInt: { |
+ assert(TypeConverter.convertToIceType(Exp->getType()) == |
+ TypeConverter.getIcePointerType()); |
+ llvm::GlobalValue *GV = |
+ llvm::dyn_cast<llvm::GlobalValue>(Exp->getOperand(0)); |
+ assert(GV); |
+ if (llvm::Function *Fcn = llvm::dyn_cast<Function>(GV)) { |
+ Ice::GlobalAddress::RelocationAddress Addr(Fcn); |
+ Global.AddInitializer( |
+ new Ice::GlobalAddress::RelocInitializer(Addr, Offset)); |
+ return; |
+ } else if (llvm::GlobalVariable *Var = |
+ llvm::dyn_cast<llvm::GlobalVariable>(GV)) { |
+ Ice::GlobalAddress::RelocationAddress Addr(getGlobalVarAddress(Var)); |
+ Global.AddInitializer( |
+ new Ice::GlobalAddress::RelocInitializer(Addr, Offset)); |
+ return; |
+ } |
+ break; |
+ } |
+ default: |
+ break; |
+ } |
+ } |
+ |
+ std::string Buffer; |
+ raw_string_ostream StrBuf(Buffer); |
+ StrBuf << "Unhandled global initializer: " << Initializer; |
+ report_fatal_error(StrBuf.str()); |
+} |
+ |
} // end of anonymous namespace |
namespace Ice { |
@@ -626,16 +811,24 @@ void Converter::convertToIce() { |
static TimerIdT IDconvertToIce = GlobalContext::getTimerID("convertToIce"); |
TimerMarker T(IDconvertToIce, Ctx); |
nameUnnamedGlobalAddresses(Mod); |
+ nameUnnamedFunctions(Mod); |
if (!Ctx->getFlags().DisableGlobals) |
convertGlobals(Mod); |
convertFunctions(); |
} |
+void Converter::convertGlobals(llvm::Module *Mod) { |
+ LLVM2ICEGlobalsConverter GlobalsConverter(Ctx, Mod->getContext()); |
+ std::vector<Ice::GlobalAddress *> GlobalAddresses; |
+ GlobalsConverter.convertGlobalsToIce(Mod, GlobalAddresses); |
+ lowerIceGlobals(GlobalAddresses); |
+} |
+ |
void Converter::convertFunctions() { |
for (Module::const_iterator I = Mod->begin(), E = Mod->end(); I != E; ++I) { |
if (I->empty()) |
continue; |
- LLVM2ICEConverter FunctionConverter(Ctx, Mod->getContext()); |
+ LLVM2ICEFunctionConverter FunctionConverter(Ctx, Mod->getContext()); |
Timer TConvert; |
Cfg *Fcn = FunctionConverter.convertFunction(I); |