X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FTransforms%2FIPO%2FExtractGV.cpp;h=6716deb9e47b8b4216a289499399f9dedde3cb2c;hb=c2a08d28eb1199d67dff5b66061cf7f6a25d2527;hp=7f67e48ade839a890a4995f2b3d9c64320dfa77b;hpb=1f74590e9d1b9cf0f1f81a156efea73f76546e05;p=oota-llvm.git diff --git a/lib/Transforms/IPO/ExtractGV.cpp b/lib/Transforms/IPO/ExtractGV.cpp index 7f67e48ade8..6716deb9e47 100644 --- a/lib/Transforms/IPO/ExtractGV.cpp +++ b/lib/Transforms/IPO/ExtractGV.cpp @@ -17,15 +17,15 @@ #include "llvm/Pass.h" #include "llvm/Constants.h" #include "llvm/Transforms/IPO.h" +#include "llvm/ADT/SetVector.h" #include using namespace llvm; namespace { /// @brief A pass to extract specific functions and their dependencies. class GVExtractorPass : public ModulePass { - std::vector Named; + SetVector Named; bool deleteStuff; - bool reLink; public: static char ID; // Pass identification, replacement for typeid @@ -33,133 +33,93 @@ namespace { /// specified function. Otherwise, it deletes as much of the module as /// possible, except for the function specified. /// - explicit GVExtractorPass(std::vector& GVs, bool deleteS = true, - bool relinkCallees = false) - : ModulePass(&ID), Named(GVs), deleteStuff(deleteS), - reLink(relinkCallees) {} + explicit GVExtractorPass(std::vector& GVs, bool deleteS = true) + : ModulePass(ID), Named(GVs.begin(), GVs.end()), deleteStuff(deleteS) {} bool runOnModule(Module &M) { - if (Named.size() == 0) { - return false; // Nothing to extract - } - - - if (deleteStuff) - return deleteGV(); - M.setModuleInlineAsm(""); - return isolateGV(M); - } - - bool deleteGV() { - for (std::vector::iterator GI = Named.begin(), - GE = Named.end(); GI != GE; ++GI) { - if (Function* NamedFunc = dyn_cast(*GI)) { - // If we're in relinking mode, set linkage of all internal callees to - // external. This will allow us extract function, and then - link - // everything together - if (reLink) { - for (Function::iterator B = NamedFunc->begin(), BE = NamedFunc->end(); - B != BE; ++B) { - for (BasicBlock::iterator I = B->begin(), E = B->end(); - I != E; ++I) { - if (CallInst* callInst = dyn_cast(&*I)) { - Function* Callee = callInst->getCalledFunction(); - if (Callee && Callee->hasLocalLinkage()) - Callee->setLinkage(GlobalValue::ExternalLinkage); - } - } - } - } - - NamedFunc->setLinkage(GlobalValue::ExternalLinkage); - NamedFunc->deleteBody(); - assert(NamedFunc->isDeclaration() && "This didn't make the function external!"); - } else { - if (!(*GI)->isDeclaration()) { - cast(*GI)->setInitializer(0); //clear the initializer - (*GI)->setLinkage(GlobalValue::ExternalLinkage); - } + // Visit the global inline asm. + if (!deleteStuff) + M.setModuleInlineAsm(""); + + // For simplicity, just give all GlobalValues ExternalLinkage. A trickier + // implementation could figure out which GlobalValues are actually + // referenced by the Named set, and which GlobalValues in the rest of + // the module are referenced by the NamedSet, and get away with leaving + // more internal and private things internal and private. But for now, + // be conservative and simple. + + // Visit the GlobalVariables. + for (Module::global_iterator I = M.global_begin(), E = M.global_end(); + I != E; ++I) { + bool Delete = + deleteStuff == (bool)Named.count(I) && !I->isDeclaration(); + if (!Delete) { + if (I->hasAvailableExternallyLinkage()) + continue; + if (I->getName() == "llvm.global_ctors") + continue; } - } - return true; - } - bool isolateGV(Module &M) { - // Mark all globals internal - // FIXME: what should we do with private linkage? - for (Module::global_iterator I = M.global_begin(), E = M.global_end(); I != E; ++I) - if (!I->isDeclaration()) { - I->setLinkage(GlobalValue::InternalLinkage); - } - for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) - if (!I->isDeclaration()) { - I->setLinkage(GlobalValue::InternalLinkage); - } + bool Local = I->hasLocalLinkage(); + if (Local) + I->setVisibility(GlobalValue::HiddenVisibility); - // Make sure our result is globally accessible... - // by putting them in the used array - { - std::vector AUGs; - const Type *SBP= - Type::getInt8PtrTy(M.getContext()); - for (std::vector::iterator GI = Named.begin(), - GE = Named.end(); GI != GE; ++GI) { - (*GI)->setLinkage(GlobalValue::ExternalLinkage); - AUGs.push_back(ConstantExpr::getBitCast(*GI, SBP)); - } - ArrayType *AT = ArrayType::get(SBP, AUGs.size()); - Constant *Init = ConstantArray::get(AT, AUGs); - GlobalValue *gv = new GlobalVariable(M, AT, false, - GlobalValue::AppendingLinkage, - Init, "llvm.used"); - gv->setSection("llvm.metadata"); - } - - // All of the functions may be used by global variables or the named - // globals. Loop through them and create a new, external functions that - // can be "used", instead of ones with bodies. - std::vector NewFunctions; + if (Local || Delete) + I->setLinkage(GlobalValue::ExternalLinkage); - Function *Last = --M.end(); // Figure out where the last real fn is. + if (Delete) + I->setInitializer(0); + } - for (Module::iterator I = M.begin(); ; ++I) { - if (std::find(Named.begin(), Named.end(), &*I) == Named.end()) { - Function *New = Function::Create(I->getFunctionType(), - GlobalValue::ExternalLinkage); - New->copyAttributesFrom(I); + // Visit the Functions. + for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) { + bool Delete = + deleteStuff == (bool)Named.count(I) && !I->isDeclaration(); + if (!Delete) { + if (I->hasAvailableExternallyLinkage()) + continue; + } - // If it's not the named function, delete the body of the function - I->dropAllReferences(); + bool Local = I->hasLocalLinkage(); + if (Local) + I->setVisibility(GlobalValue::HiddenVisibility); - M.getFunctionList().push_back(New); - NewFunctions.push_back(New); - New->takeName(I); - } + if (Local || Delete) + I->setLinkage(GlobalValue::ExternalLinkage); - if (&*I == Last) break; // Stop after processing the last function + if (Delete) + I->deleteBody(); } - // Now that we have replacements all set up, loop through the module, - // deleting the old functions, replacing them with the newly created - // functions. - if (!NewFunctions.empty()) { - unsigned FuncNum = 0; - Module::iterator I = M.begin(); - do { - if (std::find(Named.begin(), Named.end(), &*I) == Named.end()) { - // Make everything that uses the old function use the new dummy fn - I->replaceAllUsesWith(NewFunctions[FuncNum++]); + // Visit the Aliases. + for (Module::alias_iterator I = M.alias_begin(), E = M.alias_end(); + I != E;) { + Module::alias_iterator CurI = I; + ++I; - Function *Old = I; - ++I; // Move the iterator to the new function + if (CurI->hasLocalLinkage()) { + CurI->setVisibility(GlobalValue::HiddenVisibility); + CurI->setLinkage(GlobalValue::ExternalLinkage); + } + + if (deleteStuff == (bool)Named.count(CurI)) { + Type *Ty = CurI->getType()->getElementType(); - // Delete the old function! - M.getFunctionList().erase(Old); + CurI->removeFromParent(); + llvm::Value *Declaration; + if (FunctionType *FTy = dyn_cast(Ty)) { + Declaration = Function::Create(FTy, GlobalValue::ExternalLinkage, + CurI->getName(), &M); } else { - ++I; // Skip the function we are extracting + Declaration = + new GlobalVariable(M, Ty, false, GlobalValue::ExternalLinkage, + 0, CurI->getName()); + } - } while (&*I != NewFunctions[0]); + CurI->replaceAllUsesWith(Declaration); + delete CurI; + } } return true; @@ -170,6 +130,6 @@ namespace { } ModulePass *llvm::createGVExtractionPass(std::vector& GVs, - bool deleteFn, bool relinkCallees) { - return new GVExtractorPass(GVs, deleteFn, relinkCallees); + bool deleteFn) { + return new GVExtractorPass(GVs, deleteFn); }