Re-added name/type checking for globals
This commit is contained in:
84
module.cpp
84
module.cpp
@@ -2665,20 +2665,6 @@ lGetExportedFunctions(SymbolTable *symbolTable,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
struct RewriteGlobalInfo {
|
|
||||||
RewriteGlobalInfo(llvm::GlobalVariable *g = NULL, llvm::Constant *i = NULL,
|
|
||||||
SourcePos p = SourcePos()) {
|
|
||||||
gv = g;
|
|
||||||
init = i;
|
|
||||||
pos = p;
|
|
||||||
}
|
|
||||||
|
|
||||||
llvm::GlobalVariable *gv;
|
|
||||||
llvm::Constant *init;
|
|
||||||
SourcePos pos;
|
|
||||||
};
|
|
||||||
|
|
||||||
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);
|
||||||
@@ -2925,25 +2911,48 @@ static void lEmitDispatchModule(llvm::Module *module,
|
|||||||
optPM.run(*module);
|
optPM.run(*module);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Determines if two types are compatible
|
||||||
|
static bool lCompatibleTypes(llvm::Type *Ty1, llvm::Type *Ty2) {
|
||||||
|
while (Ty1->getTypeID() == Ty1->getTypeID())
|
||||||
|
switch (Ty1->getTypeID()) {
|
||||||
|
case llvm::ArrayType::ArrayTyID:
|
||||||
|
if (Ty1->getArrayNumElements() !=
|
||||||
|
Ty2->getArrayNumElements())
|
||||||
|
return false;
|
||||||
|
Ty1 = Ty1->getArrayElementType();
|
||||||
|
Ty2 = Ty2->getArrayElementType();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case llvm::ArrayType::PointerTyID:
|
||||||
|
Ty1 = Ty1->getPointerElementType();
|
||||||
|
Ty2 = Ty2->getPointerElementType();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case llvm::ArrayType::StructTyID:
|
||||||
|
return llvm::dyn_cast<llvm::StructType>(Ty1)->isLayoutIdentical(llvm::dyn_cast<llvm::StructType>(Ty2));
|
||||||
|
|
||||||
|
default:
|
||||||
|
// Pointers for compatible simple types are assumed equal
|
||||||
|
return Ty1 == Ty2;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// Grab all of the global value definitions from the module and change them
|
// 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
|
// 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
|
// 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
|
// multiple definitions of them, one in each of the target-specific output
|
||||||
// files.
|
// files.
|
||||||
static void
|
static void
|
||||||
lExtractGlobals(llvm::Module *module, llvm::Module **mdisp) {
|
lExtractOrCheckGlobals(llvm::Module *msrc, llvm::Module *mdst, bool check) {
|
||||||
llvm::Module::global_iterator iter;
|
llvm::Module::global_iterator iter;
|
||||||
|
|
||||||
if (*mdisp)
|
for (iter = msrc->global_begin(); iter != msrc->global_end(); ++iter) {
|
||||||
return;
|
|
||||||
|
|
||||||
*mdisp = lInitDispatchModule();
|
|
||||||
for (iter = module->global_begin(); iter != module->global_end(); ++iter) {
|
|
||||||
llvm::GlobalVariable *gv = iter;
|
llvm::GlobalVariable *gv = iter;
|
||||||
// Is it a global definition?
|
// Is it a global definition?
|
||||||
if (gv->getLinkage() == llvm::GlobalValue::ExternalLinkage &&
|
if (gv->getLinkage() == llvm::GlobalValue::ExternalLinkage &&
|
||||||
gv->hasInitializer()) {
|
gv->hasInitializer()) {
|
||||||
// Turn this into an 'extern 'declaration by clearing its
|
// Turn this into an 'extern' declaration by clearing its
|
||||||
// initializer.
|
// initializer.
|
||||||
llvm::Constant *init = gv->getInitializer();
|
llvm::Constant *init = gv->getInitializer();
|
||||||
gv->setInitializer(NULL);
|
gv->setInitializer(NULL);
|
||||||
@@ -2953,15 +2962,34 @@ lExtractGlobals(llvm::Module *module, llvm::Module **mdisp) {
|
|||||||
m->symbolTable->LookupVariable(gv->getName().str().c_str());
|
m->symbolTable->LookupVariable(gv->getName().str().c_str());
|
||||||
Assert(sym != NULL);
|
Assert(sym != NULL);
|
||||||
|
|
||||||
// Create a new global in the given model that matches the original
|
// Check presence and compatibility for the current global
|
||||||
// global
|
if (check) {
|
||||||
|
llvm::GlobalVariable *exist =
|
||||||
|
mdst->getGlobalVariable(gv->getName());
|
||||||
|
Assert(exist != NULL);
|
||||||
|
|
||||||
|
// It is possible that the types may not match: for
|
||||||
|
// example, this happens with varying globals if we
|
||||||
|
// compile to different vector widths
|
||||||
|
if (!lCompatibleTypes(exist->getType(), gv->getType())) {
|
||||||
|
Warning(sym->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());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Alternatively, create it anew and make it match the original
|
||||||
|
else {
|
||||||
llvm::GlobalVariable *newGlobal =
|
llvm::GlobalVariable *newGlobal =
|
||||||
new llvm::GlobalVariable(**mdisp, type, gv->isConstant(),
|
new llvm::GlobalVariable(*mdst, type, gv->isConstant(),
|
||||||
llvm::GlobalValue::ExternalLinkage,
|
llvm::GlobalValue::ExternalLinkage,
|
||||||
init, gv->getName());
|
init, gv->getName());
|
||||||
newGlobal->copyAttributesFrom(gv);
|
newGlobal->copyAttributesFrom(gv);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef ISPC_NVPTX_ENABLED
|
#ifdef ISPC_NVPTX_ENABLED
|
||||||
@@ -3169,11 +3197,17 @@ Module::CompileAndOutput(const char *srcFile,
|
|||||||
|
|
||||||
m = new Module(srcFile);
|
m = new Module(srcFile);
|
||||||
if (m->CompileFile() == 0) {
|
if (m->CompileFile() == 0) {
|
||||||
|
// Create the dispatch module, unless already created;
|
||||||
|
// in the latter case, just do the checking
|
||||||
|
bool check = (dispatchModule != NULL);
|
||||||
|
if (!check)
|
||||||
|
dispatchModule = lInitDispatchModule();
|
||||||
|
lExtractOrCheckGlobals(m->module, dispatchModule, check);
|
||||||
|
|
||||||
// Grab pointers to the exported functions from the module we
|
// Grab pointers to the exported functions from the module we
|
||||||
// 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);
|
|
||||||
|
|
||||||
if (outFileName != NULL) {
|
if (outFileName != NULL) {
|
||||||
std::string targetOutFileName;
|
std::string targetOutFileName;
|
||||||
|
|||||||
Reference in New Issue
Block a user