X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FTransforms%2FIPO%2FExtractGV.cpp;h=8a6bfc6d88568fe429b6c39bb6fb47836a5a940a;hb=0b8c9a80f20772c3793201ab5b251d3520b9cea3;hp=882097cae55dca6b9e0c25735f7b2e4b84fce526;hpb=58d5e051574339106ce4139697ebadd21e34dbc0;p=oota-llvm.git diff --git a/lib/Transforms/IPO/ExtractGV.cpp b/lib/Transforms/IPO/ExtractGV.cpp index 882097cae55..8a6bfc6d885 100644 --- a/lib/Transforms/IPO/ExtractGV.cpp +++ b/lib/Transforms/IPO/ExtractGV.cpp @@ -11,21 +11,21 @@ // //===----------------------------------------------------------------------===// -#include "llvm/Instructions.h" -#include "llvm/Module.h" -#include "llvm/Pass.h" -#include "llvm/Constants.h" #include "llvm/Transforms/IPO.h" -#include "llvm/Support/Compiler.h" +#include "llvm/ADT/SetVector.h" +#include "llvm/IR/Constants.h" +#include "llvm/IR/Instructions.h" +#include "llvm/IR/LLVMContext.h" +#include "llvm/IR/Module.h" +#include "llvm/Pass.h" #include using namespace llvm; namespace { /// @brief A pass to extract specific functions and their dependencies. - class VISIBILITY_HIDDEN GVExtractorPass : public ModulePass { - std::vector Named; + class GVExtractorPass : public ModulePass { + 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((intptr_t)&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->hasInternalLinkage()) - 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 - 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= PointerType::getUnqual(Type::Int8Ty); - 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(AT, false, - GlobalValue::AppendingLinkage, - Init, "llvm.used", &M); - 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 = new Function(I->getFunctionType(), - GlobalValue::ExternalLinkage); - New->setCallingConv(I->getCallingConv()); - New->setParamAttrs(I->getParamAttrs()); - if (I->hasCollector()) - New->setCollector(I->getCollector()); + // 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; + + if (CurI->hasLocalLinkage()) { + CurI->setVisibility(GlobalValue::HiddenVisibility); + CurI->setLinkage(GlobalValue::ExternalLinkage); + } - Function *Old = I; - ++I; // Move the iterator to the new function + 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); }