Fix bug: FunctionResolve/2003-10-21-GlobalTypeDifference.ll

llvm-svn: 9359
This commit is contained in:
Chris Lattner 2003-10-21 23:17:56 +00:00
parent de20d44b3e
commit af2c00bf14
1 changed files with 19 additions and 55 deletions

View File

@ -109,29 +109,15 @@ static bool ResolveGlobalVariables(Module &M,
std::vector<GlobalValue*> &Globals,
GlobalVariable *Concrete) {
bool Changed = false;
assert(isa<ArrayType>(Concrete->getType()->getElementType()) &&
"Concrete version should be an array type!");
// Get the type of the things that may be resolved to us...
const ArrayType *CATy =cast<ArrayType>(Concrete->getType()->getElementType());
const Type *AETy = CATy->getElementType();
Constant *CCPR = ConstantPointerRef::get(Concrete);
for (unsigned i = 0; i != Globals.size(); ++i)
if (Globals[i] != Concrete) {
GlobalVariable *Old = cast<GlobalVariable>(Globals[i]);
const ArrayType *OATy = cast<ArrayType>(Old->getType()->getElementType());
if (OATy->getElementType() != AETy || OATy->getNumElements() != 0) {
std::cerr << "WARNING: Two global variables exist with the same name "
<< "that cannot be resolved!\n";
return false;
}
Old->replaceAllUsesWith(ConstantExpr::getCast(CCPR, Old->getType()));
Constant *Cast = ConstantExpr::getCast(CCPR, Globals[i]->getType());
Globals[i]->replaceAllUsesWith(Cast);
// Since there are no uses of Old anymore, remove it from the module.
M.getGlobalList().erase(Old);
M.getGlobalList().erase(cast<GlobalVariable>(Globals[i]));
++NumGlobals;
Changed = true;
@ -176,32 +162,15 @@ static bool ProcessGlobalsWithSameName(Module &M,
Concrete = F;
}
} else {
// For global variables, we have to merge C definitions int A[][4] with
// int[6][4]. A[][4] is represented as A[0][4] by the CFE.
GlobalVariable *GV = cast<GlobalVariable>(Globals[i]);
if (!isa<ArrayType>(GV->getType()->getElementType())) {
Concrete = 0;
break; // Non array's cannot be compatible with other types.
} else if (Concrete == 0) {
Concrete = GV;
} else {
// Must have different types... allow merging A[0][4] w/ A[6][4] if
// A[0][4] is external.
const ArrayType *NAT = cast<ArrayType>(GV->getType()->getElementType());
const ArrayType *CAT =
cast<ArrayType>(Concrete->getType()->getElementType());
if (NAT->getElementType() != CAT->getElementType()) {
Concrete = 0; // Non-compatible types
break;
} else if (NAT->getNumElements() == 0 && GV->isExternal()) {
// Concrete remains the same
} else if (CAT->getNumElements() == 0 && Concrete->isExternal()) {
Concrete = GV; // Concrete becomes GV
} else {
Concrete = 0; // Cannot merge these types...
break;
if (!GV->isExternal()) {
if (Concrete) {
std::cerr << "WARNING: Two global variables with external linkage"
<< " exist with the same name: '" << GV->getName()
<< "'!\n";
return false;
}
Concrete = GV;
}
}
++i;
@ -225,21 +194,15 @@ static bool ProcessGlobalsWithSameName(Module &M,
return false; // Nothing to do? Must have multiple internal definitions.
// We should find exactly one concrete function definition, which is
// probably the implementation. Change all of the function definitions and
// uses to use it instead.
//
if (!Concrete) {
std::cerr << "WARNING: Found global types that are not compatible:\n";
for (unsigned i = 0; i < Globals.size(); ++i) {
std::cerr << "\t" << Globals[i]->getType()->getDescription() << " %"
<< Globals[i]->getName() << "\n";
}
std::cerr << " No linkage of globals named '" << Globals[0]->getName()
<< "' performed!\n";
return false;
std::cerr << "WARNING: Found global types that are not compatible:\n";
for (unsigned i = 0; i < Globals.size(); ++i) {
std::cerr << "\t" << *Globals[i]->getType() << " %"
<< Globals[i]->getName() << "\n";
}
if (!Concrete)
Concrete = Globals[0];
if (isFunction)
return ResolveFunctions(M, Globals, cast<Function>(Concrete));
else
@ -266,7 +229,8 @@ bool FunctionResolvingPass::run(Module &M) {
GlobalValue *GV = cast<GlobalValue>(PI->second);
assert(PI->first == GV->getName() &&
"Global name and symbol table do not agree!");
Globals[PI->first].push_back(GV);
if (!GV->hasInternalLinkage())
Globals[PI->first].push_back(GV);
}
}