Fixed global variable handling
This commit is contained in:
160
module.cpp
160
module.cpp
@@ -2679,95 +2679,6 @@ struct RewriteGlobalInfo {
|
|||||||
SourcePos pos;
|
SourcePos pos;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Grab all of the global value definitions from the module and change them
|
|
||||||
// to be declarations; we'll emit a single definition of each global in the
|
|
||||||
// final module used with the dispatch functions, so that we don't have
|
|
||||||
// multiple definitions of them, one in each of the target-specific output
|
|
||||||
// files.
|
|
||||||
static void
|
|
||||||
lExtractAndRewriteGlobals(llvm::Module *module,
|
|
||||||
std::vector<RewriteGlobalInfo> *globals) {
|
|
||||||
llvm::Module::global_iterator iter;
|
|
||||||
for (iter = module->global_begin(); iter != module->global_end(); ++iter) {
|
|
||||||
llvm::GlobalVariable *gv = iter;
|
|
||||||
// Is it a global definition?
|
|
||||||
if (gv->getLinkage() == llvm::GlobalValue::ExternalLinkage &&
|
|
||||||
gv->hasInitializer()) {
|
|
||||||
// Turn this into an 'extern 'declaration by clearing its
|
|
||||||
// initializer.
|
|
||||||
llvm::Constant *init = gv->getInitializer();
|
|
||||||
gv->setInitializer(NULL);
|
|
||||||
|
|
||||||
Symbol *sym =
|
|
||||||
m->symbolTable->LookupVariable(gv->getName().str().c_str());
|
|
||||||
Assert(sym != NULL);
|
|
||||||
globals->push_back(RewriteGlobalInfo(gv, init, sym->pos));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// This function emits a global variable definition for each global that
|
|
||||||
// was turned into a declaration in the target-specific output file.
|
|
||||||
static void
|
|
||||||
lAddExtractedGlobals(llvm::Module *module,
|
|
||||||
std::vector<RewriteGlobalInfo> globals[Target::NUM_ISAS]) {
|
|
||||||
// Find the first element in the globals[] array that has values stored
|
|
||||||
// in it. All elements of this array should either have empty vectors
|
|
||||||
// (if we didn't compile to the corresponding ISA or if there are no
|
|
||||||
// globals), or should have the same number of vector elements as the
|
|
||||||
// other non-empty vectors.
|
|
||||||
int firstActive = -1;
|
|
||||||
for (int i = 0; i < Target::NUM_ISAS; ++i)
|
|
||||||
if (globals[i].size() > 0) {
|
|
||||||
firstActive = i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (firstActive == -1)
|
|
||||||
// no globals
|
|
||||||
return;
|
|
||||||
|
|
||||||
for (unsigned int i = 0; i < globals[firstActive].size(); ++i) {
|
|
||||||
RewriteGlobalInfo &rgi = globals[firstActive][i];
|
|
||||||
llvm::GlobalVariable *gv = rgi.gv;
|
|
||||||
llvm::Type *type = gv->getType()->getElementType();
|
|
||||||
llvm::Constant *initializer = rgi.init;
|
|
||||||
|
|
||||||
// Create a new global in the given model that matches the original
|
|
||||||
// global
|
|
||||||
llvm::GlobalVariable *newGlobal =
|
|
||||||
new llvm::GlobalVariable(*module, type, gv->isConstant(),
|
|
||||||
llvm::GlobalValue::ExternalLinkage,
|
|
||||||
initializer, gv->getName());
|
|
||||||
newGlobal->copyAttributesFrom(gv);
|
|
||||||
|
|
||||||
// For all of the other targets that we actually generated code
|
|
||||||
// for, make sure the global we just created is compatible with the
|
|
||||||
// global from the module for that target.
|
|
||||||
for (int j = firstActive + 1; j < Target::NUM_ISAS; ++j) {
|
|
||||||
if (globals[j].size() > 0) {
|
|
||||||
// There should be the same number of globals in the other
|
|
||||||
// vectors, in the same order.
|
|
||||||
Assert(globals[firstActive].size() == globals[j].size());
|
|
||||||
llvm::GlobalVariable *gv2 = globals[j][i].gv;
|
|
||||||
Assert(gv2->getName() == gv->getName());
|
|
||||||
|
|
||||||
// It is possible that the types may not match, though--for
|
|
||||||
// example, this happens with varying globals if we compile
|
|
||||||
// to different vector widths.
|
|
||||||
if (gv2->getType() != gv->getType())
|
|
||||||
Warning(rgi.pos, "Mismatch in size/layout of global "
|
|
||||||
"variable \"%s\" with different targets. "
|
|
||||||
"Globals must not include \"varying\" types or arrays "
|
|
||||||
"with size based on programCount when compiling to "
|
|
||||||
"targets with differing vector widths.",
|
|
||||||
gv->getName().str().c_str());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static llvm::FunctionType *
|
static llvm::FunctionType *
|
||||||
lGetVaryingDispatchType(FunctionTargetVariants &funcs) {
|
lGetVaryingDispatchType(FunctionTargetVariants &funcs) {
|
||||||
llvm::Type *ptrToInt8Ty = llvm::Type::getInt8PtrTy(*g->ctx);
|
llvm::Type *ptrToInt8Ty = llvm::Type::getInt8PtrTy(*g->ctx);
|
||||||
@@ -2969,13 +2880,8 @@ lCreateDispatchFunction(llvm::Module *module, llvm::Function *setISAFunc,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Given a map that holds the mapping from each of the 'export'ed functions
|
// Initialize a dispatch module
|
||||||
// in the ispc program to the target-specific variants of the function,
|
static llvm::Module *lInitDispatchModule() {
|
||||||
// create a llvm::Module that has a dispatch function for each exported
|
|
||||||
// function that checks the system's capabilities and picks the most
|
|
||||||
// appropriate compiled variant of the function.
|
|
||||||
static llvm::Module *
|
|
||||||
lCreateDispatchModule(std::map<std::string, FunctionTargetVariants> &functions) {
|
|
||||||
llvm::Module *module = new llvm::Module("dispatch_module", *g->ctx);
|
llvm::Module *module = new llvm::Module("dispatch_module", *g->ctx);
|
||||||
|
|
||||||
// First, link in the definitions from the builtins-dispatch.ll file.
|
// First, link in the definitions from the builtins-dispatch.ll file.
|
||||||
@@ -2983,7 +2889,17 @@ lCreateDispatchModule(std::map<std::string, FunctionTargetVariants> &functions)
|
|||||||
extern int builtins_bitcode_dispatch_length;
|
extern int builtins_bitcode_dispatch_length;
|
||||||
AddBitcodeToModule(builtins_bitcode_dispatch,
|
AddBitcodeToModule(builtins_bitcode_dispatch,
|
||||||
builtins_bitcode_dispatch_length, module);
|
builtins_bitcode_dispatch_length, module);
|
||||||
|
return module;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Complete the creation of a dispatch module.
|
||||||
|
// Given a map that holds the mapping from each of the 'export'ed functions
|
||||||
|
// in the ispc program to the target-specific variants of the function,
|
||||||
|
// create a llvm::Module that has a dispatch function for each exported
|
||||||
|
// function that checks the system's capabilities and picks the most
|
||||||
|
// appropriate compiled variant of the function.
|
||||||
|
static void lEmitDispatchModule(llvm::Module *module,
|
||||||
|
std::map<std::string, FunctionTargetVariants> &functions) {
|
||||||
// Get pointers to things we need below
|
// Get pointers to things we need below
|
||||||
llvm::Function *setFunc = module->getFunction("__set_system_isa");
|
llvm::Function *setFunc = module->getFunction("__set_system_isa");
|
||||||
Assert(setFunc != NULL);
|
Assert(setFunc != NULL);
|
||||||
@@ -2999,7 +2915,6 @@ lCreateDispatchModule(std::map<std::string, FunctionTargetVariants> &functions)
|
|||||||
|
|
||||||
// Do some rudimentary cleanup of the final result and make sure that
|
// Do some rudimentary cleanup of the final result and make sure that
|
||||||
// the module is all ok.
|
// the module is all ok.
|
||||||
|
|
||||||
#if defined(LLVM_3_2) || defined(LLVM_3_3) || defined(LLVM_3_4) || defined(LLVM_3_5) || defined(LLVM_3_6)
|
#if defined(LLVM_3_2) || defined(LLVM_3_3) || defined(LLVM_3_4) || defined(LLVM_3_5) || defined(LLVM_3_6)
|
||||||
llvm::PassManager optPM;
|
llvm::PassManager optPM;
|
||||||
#else // LLVM 3.7+
|
#else // LLVM 3.7+
|
||||||
@@ -3008,10 +2923,46 @@ lCreateDispatchModule(std::map<std::string, FunctionTargetVariants> &functions)
|
|||||||
optPM.add(llvm::createGlobalDCEPass());
|
optPM.add(llvm::createGlobalDCEPass());
|
||||||
optPM.add(llvm::createVerifierPass());
|
optPM.add(llvm::createVerifierPass());
|
||||||
optPM.run(*module);
|
optPM.run(*module);
|
||||||
|
|
||||||
return module;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Grab all of the global value definitions from the module and change them
|
||||||
|
// to be declarations; we'll emit a single definition of each global in the
|
||||||
|
// final module used with the dispatch functions, so that we don't have
|
||||||
|
// multiple definitions of them, one in each of the target-specific output
|
||||||
|
// files.
|
||||||
|
static void
|
||||||
|
lExtractGlobals(llvm::Module *module, llvm::Module **mdisp) {
|
||||||
|
llvm::Module::global_iterator iter;
|
||||||
|
|
||||||
|
if (*mdisp)
|
||||||
|
return;
|
||||||
|
|
||||||
|
*mdisp = lInitDispatchModule();
|
||||||
|
for (iter = module->global_begin(); iter != module->global_end(); ++iter) {
|
||||||
|
llvm::GlobalVariable *gv = iter;
|
||||||
|
// Is it a global definition?
|
||||||
|
if (gv->getLinkage() == llvm::GlobalValue::ExternalLinkage &&
|
||||||
|
gv->hasInitializer()) {
|
||||||
|
// Turn this into an 'extern 'declaration by clearing its
|
||||||
|
// initializer.
|
||||||
|
llvm::Constant *init = gv->getInitializer();
|
||||||
|
gv->setInitializer(NULL);
|
||||||
|
|
||||||
|
llvm::Type *type = gv->getType()->getElementType();
|
||||||
|
Symbol *sym =
|
||||||
|
m->symbolTable->LookupVariable(gv->getName().str().c_str());
|
||||||
|
Assert(sym != NULL);
|
||||||
|
|
||||||
|
// Create a new global in the given model that matches the original
|
||||||
|
// global
|
||||||
|
llvm::GlobalVariable *newGlobal =
|
||||||
|
new llvm::GlobalVariable(**mdisp, type, gv->isConstant(),
|
||||||
|
llvm::GlobalValue::ExternalLinkage,
|
||||||
|
init, gv->getName());
|
||||||
|
newGlobal->copyAttributesFrom(gv);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef ISPC_NVPTX_ENABLED
|
#ifdef ISPC_NVPTX_ENABLED
|
||||||
static std::string lCBEMangle(const std::string &S)
|
static std::string lCBEMangle(const std::string &S)
|
||||||
@@ -3169,8 +3120,9 @@ Module::CompileAndOutput(const char *srcFile,
|
|||||||
for (int i = 0; i < Target::NUM_ISAS; ++i)
|
for (int i = 0; i < Target::NUM_ISAS; ++i)
|
||||||
targetMachines[i] = NULL;
|
targetMachines[i] = NULL;
|
||||||
|
|
||||||
|
llvm::Module *dispatchModule = NULL;
|
||||||
|
|
||||||
std::map<std::string, FunctionTargetVariants> exportedFunctions;
|
std::map<std::string, FunctionTargetVariants> exportedFunctions;
|
||||||
std::vector<RewriteGlobalInfo> globals[Target::NUM_ISAS];
|
|
||||||
int errorCount = 0;
|
int errorCount = 0;
|
||||||
|
|
||||||
// Handle creating a "generic" header file for multiple targets
|
// Handle creating a "generic" header file for multiple targets
|
||||||
@@ -3221,8 +3173,7 @@ Module::CompileAndOutput(const char *srcFile,
|
|||||||
// just compiled, for use in generating the dispatch function
|
// just compiled, for use in generating the dispatch function
|
||||||
// later.
|
// later.
|
||||||
lGetExportedFunctions(m->symbolTable, exportedFunctions);
|
lGetExportedFunctions(m->symbolTable, exportedFunctions);
|
||||||
|
lExtractGlobals(m->module, &dispatchModule);
|
||||||
lExtractAndRewriteGlobals(m->module, &globals[i]);
|
|
||||||
|
|
||||||
if (outFileName != NULL) {
|
if (outFileName != NULL) {
|
||||||
std::string targetOutFileName;
|
std::string targetOutFileName;
|
||||||
@@ -3298,10 +3249,7 @@ Module::CompileAndOutput(const char *srcFile,
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
llvm::Module *dispatchModule =
|
lEmitDispatchModule(dispatchModule, exportedFunctions);
|
||||||
lCreateDispatchModule(exportedFunctions);
|
|
||||||
|
|
||||||
lAddExtractedGlobals(dispatchModule, globals);
|
|
||||||
|
|
||||||
if (outFileName != NULL) {
|
if (outFileName != NULL) {
|
||||||
if (outputType == Bitcode)
|
if (outputType == Bitcode)
|
||||||
|
|||||||
Reference in New Issue
Block a user