X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FTransforms%2FIPO%2FFunctionResolution.cpp;h=f6e8cf591344129b7810a47a7fcf509ff94fff71;hb=f5da13367f88f06e3b585dc2263ab6e9ca6c4bf8;hp=8361930e94437f6504edcada7213887eab6b6caa;hpb=03fb8b2a424b11e7a035e856fce8e7c583d84863;p=oota-llvm.git diff --git a/lib/Transforms/IPO/FunctionResolution.cpp b/lib/Transforms/IPO/FunctionResolution.cpp index 8361930e944..f6e8cf59134 100644 --- a/lib/Transforms/IPO/FunctionResolution.cpp +++ b/lib/Transforms/IPO/FunctionResolution.cpp @@ -1,10 +1,10 @@ //===- FunctionResolution.cpp - Resolve declarations to implementations ---===// -// +// // The LLVM Compiler Infrastructure // // This file was developed by the LLVM research group and is distributed under // the University of Illinois Open Source License. See LICENSE.TXT for details. -// +// //===----------------------------------------------------------------------===// // // Loop over the functions that are in the module and look for functions that @@ -22,30 +22,30 @@ #include "llvm/Module.h" #include "llvm/DerivedTypes.h" #include "llvm/Pass.h" -#include "llvm/iOther.h" +#include "llvm/Instructions.h" #include "llvm/Constants.h" #include "llvm/Support/CallSite.h" #include "llvm/Target/TargetData.h" #include "llvm/Assembly/Writer.h" -#include "Support/Statistic.h" +#include "llvm/ADT/Statistic.h" #include using namespace llvm; namespace { - Statistic<>NumResolved("funcresolve", "Number of varargs functions resolved"); - Statistic<> NumGlobals("funcresolve", "Number of global variables resolved"); + Statistic NumResolved("funcresolve", "Number of varargs functions resolved"); + Statistic NumGlobals("funcresolve", "Number of global variables resolved"); - struct FunctionResolvingPass : public Pass { + struct FunctionResolvingPass : public ModulePass { virtual void getAnalysisUsage(AnalysisUsage &AU) const { AU.addRequired(); } - bool run(Module &M); + bool runOnModule(Module &M); }; - RegisterOpt X("funcresolve", "Resolve Functions"); + RegisterPass X("funcresolve", "Resolve Functions"); } -Pass *llvm::createFunctionResolvingPass() { +ModulePass *llvm::createFunctionResolvingPass() { return new FunctionResolvingPass(); } @@ -55,41 +55,43 @@ static bool ResolveFunctions(Module &M, std::vector &Globals, for (unsigned i = 0; i != Globals.size(); ++i) if (Globals[i] != Concrete) { Function *Old = cast(Globals[i]); - const FunctionType *OldMT = Old->getFunctionType(); - const FunctionType *ConcreteMT = Concrete->getFunctionType(); - - if (OldMT->getParamTypes().size() > ConcreteMT->getParamTypes().size() && - !ConcreteMT->isVarArg()) + const FunctionType *OldFT = Old->getFunctionType(); + const FunctionType *ConcreteFT = Concrete->getFunctionType(); + + if (OldFT->getNumParams() > ConcreteFT->getNumParams() && + !ConcreteFT->isVarArg()) if (!Old->use_empty()) { - std::cerr << "WARNING: Linking function '" << Old->getName() - << "' is causing arguments to be dropped.\n"; - std::cerr << "WARNING: Prototype: "; - WriteAsOperand(std::cerr, Old); - std::cerr << " resolved to "; - WriteAsOperand(std::cerr, Concrete); - std::cerr << "\n"; + cerr << "WARNING: Linking function '" << Old->getName() + << "' is causing arguments to be dropped.\n"; + cerr << "WARNING: Prototype: "; + WriteAsOperand(*cerr.stream(), Old); + cerr << " resolved to "; + WriteAsOperand(*cerr.stream(), Concrete); + cerr << "\n"; } - + // Check to make sure that if there are specified types, that they // match... // - unsigned NumArguments = std::min(OldMT->getParamTypes().size(), - ConcreteMT->getParamTypes().size()); + unsigned NumArguments = std::min(OldFT->getNumParams(), + ConcreteFT->getNumParams()); if (!Old->use_empty() && !Concrete->use_empty()) for (unsigned i = 0; i < NumArguments; ++i) - if (OldMT->getParamTypes()[i] != ConcreteMT->getParamTypes()[i]) - if (OldMT->getParamTypes()[i]->getPrimitiveID() != - ConcreteMT->getParamTypes()[i]->getPrimitiveID()) { - std::cerr << "WARNING: Function [" << Old->getName() - << "]: Parameter types conflict for: '"; - WriteTypeSymbolic(std::cerr, OldMT, &M); - std::cerr << "' and '"; - WriteTypeSymbolic(std::cerr, ConcreteMT, &M); - std::cerr << "'\n"; + if (OldFT->getParamType(i) != ConcreteFT->getParamType(i)) + if (OldFT->getParamType(i)->getTypeID() != + ConcreteFT->getParamType(i)->getTypeID()) { + cerr << "WARNING: Function [" << Old->getName() + << "]: Parameter types conflict for: '"; + WriteTypeSymbolic(*cerr.stream(), OldFT, &M); + cerr << "' (in " + << Old->getParent()->getModuleIdentifier() << ") and '"; + WriteTypeSymbolic(*cerr.stream(), ConcreteFT, &M); + cerr << "'(in " + << Concrete->getParent()->getModuleIdentifier() << ")\n"; return Changed; } - + // Attempt to convert all of the uses of the old function to the concrete // form of the function. If there is a use of the fn that we don't // understand here we punt to avoid making a bad transformation. @@ -98,12 +100,11 @@ static bool ResolveFunctions(Module &M, std::vector &Globals, // functions and that the Old function has no varargs fns specified. In // otherwords it's just (...) // - if (!Old->use_empty()) { // Avoid making the CPR unless we really need it + if (!Old->use_empty()) { Value *Replacement = Concrete; if (Concrete->getType() != Old->getType()) - Replacement = ConstantExpr::getCast(ConstantPointerRef::get(Concrete), - Old->getType()); - NumResolved += Old->use_size(); + Replacement = ConstantExpr::getCast(Concrete, Old->getType()); + NumResolved += Old->getNumUses(); Old->replaceAllUsesWith(Replacement); } @@ -118,11 +119,10 @@ static bool ResolveGlobalVariables(Module &M, std::vector &Globals, GlobalVariable *Concrete) { bool Changed = false; - Constant *CCPR = ConstantPointerRef::get(Concrete); for (unsigned i = 0; i != Globals.size(); ++i) if (Globals[i] != Concrete) { - Constant *Cast = ConstantExpr::getCast(CCPR, Globals[i]->getType()); + Constant *Cast = ConstantExpr::getCast(Concrete, Globals[i]->getType()); Globals[i]->replaceAllUsesWith(Cast); // Since there are no uses of Old anymore, remove it from the module. @@ -138,8 +138,8 @@ static bool ResolveGlobalVariables(Module &M, static bool CallersAllIgnoreReturnValue(Function &F) { if (F.getReturnType() == Type::VoidTy) return true; for (Value::use_iterator I = F.use_begin(), E = F.use_end(); I != E; ++I) { - if (ConstantPointerRef *CPR = dyn_cast(*I)) { - for (Value::use_iterator I = CPR->use_begin(), E = CPR->use_end(); + if (GlobalValue *GV = dyn_cast(*I)) { + for (Value::use_iterator I = GV->use_begin(), E = GV->use_end(); I != E; ++I) { CallSite CS = CallSite::get(*I); if (!CS.getInstruction() || !CS.getInstruction()->use_empty()) @@ -163,8 +163,8 @@ static bool ProcessGlobalsWithSameName(Module &M, TargetData &TD, for (unsigned i = 0; i != Globals.size(); ) { if (isa(Globals[i]) != isFunction) { - std::cerr << "WARNING: Found function and global variable with the " - << "same name: '" << Globals[i]->getName() << "'.\n"; + cerr << "WARNING: Found function and global variable with the " + << "same name: '" << Globals[i]->getName() << "'.\n"; return false; // Don't know how to handle this, bail out! } @@ -176,11 +176,11 @@ static bool ProcessGlobalsWithSameName(Module &M, TargetData &TD, if (!F->isExternal()) { if (Concrete && !Concrete->isExternal()) return false; // Found two different functions types. Can't choose! - + Concrete = Globals[i]; } else if (Concrete) { if (Concrete->isExternal()) // If we have multiple external symbols... - if (F->getFunctionType()->getNumParams() > + if (F->getFunctionType()->getNumParams() > cast(Concrete)->getFunctionType()->getNumParams()) Concrete = F; // We are more concrete than "Concrete"! @@ -191,9 +191,9 @@ static bool ProcessGlobalsWithSameName(Module &M, TargetData &TD, GlobalVariable *GV = cast(Globals[i]); if (!GV->isExternal()) { if (Concrete) { - std::cerr << "WARNING: Two global variables with external linkage" - << " exist with the same name: '" << GV->getName() - << "'!\n"; + cerr << "WARNING: Two global variables with external linkage" + << " exist with the same name: '" << GV->getName() + << "'!\n"; return false; } Concrete = GV; @@ -215,7 +215,7 @@ static bool ProcessGlobalsWithSameName(Module &M, TargetData &TD, else if (!Globals[i]->hasInternalLinkage()) NumInstancesWithExternalLinkage++; } - + if (!HasExternal && NumInstancesWithExternalLinkage <= 1) return false; // Nothing to do? Must have multiple internal definitions. @@ -231,29 +231,30 @@ static bool ProcessGlobalsWithSameName(Module &M, TargetData &TD, if ((ConcreteF->getReturnType() == OtherF->getReturnType() || CallersAllIgnoreReturnValue(*OtherF)) && OtherF->getFunctionType()->isVarArg() && - OtherF->getFunctionType()->getParamTypes().empty()) + OtherF->getFunctionType()->getNumParams() == 0) DontPrintWarning = true; - + // Otherwise, if the non-concrete global is a global array variable with a // size of 0, and the concrete global is an array with a real size, don't // warn. This occurs due to declaring 'extern int A[];'. if (GlobalVariable *ConcreteGV = dyn_cast(Concrete)) - if (GlobalVariable *OtherGV = dyn_cast(Other)) - if (const ArrayType *OtherAT = - dyn_cast(OtherGV->getType()->getElementType())) - if (const ArrayType *ConcreteAT = - dyn_cast(ConcreteGV->getType()->getElementType())) - if (OtherAT->getElementType() == ConcreteAT->getElementType() && - OtherAT->getNumElements() == 0) - DontPrintWarning = true; + if (GlobalVariable *OtherGV = dyn_cast(Other)) { + const Type *CTy = ConcreteGV->getType(); + const Type *OTy = OtherGV->getType(); + + if (CTy->isSized()) + if (!OTy->isSized() || !TD.getTypeSize(OTy) || + TD.getTypeSize(OTy) == TD.getTypeSize(CTy)) + DontPrintWarning = true; + } } - if (!DontPrintWarning) { - std::cerr << "WARNING: Found global types that are not compatible:\n"; + if (0 && !DontPrintWarning) { + cerr << "WARNING: Found global types that are not compatible:\n"; for (unsigned i = 0; i < Globals.size(); ++i) { - std::cerr << "\t"; - WriteTypeSymbolic(std::cerr, Globals[i]->getType(), &M); - std::cerr << " %" << Globals[i]->getName() << "\n"; + cerr << "\t"; + WriteTypeSymbolic(*cerr.stream(), Globals[i]->getType(), &M); + cerr << " %" << Globals[i]->getName() << "\n"; } } @@ -294,7 +295,7 @@ static bool ProcessGlobalsWithSameName(Module &M, TargetData &TD, return false; } -bool FunctionResolvingPass::run(Module &M) { +bool FunctionResolvingPass::runOnModule(Module &M) { std::map > Globals; // Loop over the globals, adding them to the Globals map. We use a two pass @@ -307,11 +308,13 @@ bool FunctionResolvingPass::run(Module &M) { if (F->use_empty() && F->isExternal()) { M.getFunctionList().erase(F); Changed = true; - } else if (!F->hasInternalLinkage() && !F->getName().empty()) + } else if (!F->hasInternalLinkage() && !F->getName().empty() && + !F->getIntrinsicID()) Globals[F->getName()].push_back(F); } - for (Module::giterator I = M.gbegin(), E = M.gend(); I != E; ) { + for (Module::global_iterator I = M.global_begin(), E = M.global_end(); + I != E; ) { GlobalVariable *GV = I++; if (GV->use_empty() && GV->isExternal()) { M.getGlobalList().erase(GV); @@ -343,7 +346,8 @@ bool FunctionResolvingPass::run(Module &M) { ++I; } - for (Module::giterator I = M.gbegin(), E = M.gend(); I != E; ) + for (Module::global_iterator I = M.global_begin(), E = M.global_end(); + I != E; ) if (I->isExternal() && I->use_empty()) { GlobalVariable *GV = I; ++I;