1 //===-- ExtractGV.cpp - Global Value extraction pass ----------------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This pass extracts global values 11 // 12 //===----------------------------------------------------------------------===// 13 14 #include "llvm/ADT/SetVector.h" 15 #include "llvm/IR/LLVMContext.h" 16 #include "llvm/IR/Module.h" 17 #include "llvm/Pass.h" 18 #include "llvm/Transforms/IPO.h" 19 #include <algorithm> 20 using namespace llvm; 21 22 /// Make sure GV is visible from both modules. Delete is true if it is 23 /// being deleted from this module. 24 /// This also makes sure GV cannot be dropped so that references from 25 /// the split module remain valid. 26 static void makeVisible(GlobalValue &GV, bool Delete) { 27 bool Local = GV.hasLocalLinkage(); 28 if (Local || Delete) { 29 GV.setLinkage(GlobalValue::ExternalLinkage); 30 if (Local) 31 GV.setVisibility(GlobalValue::HiddenVisibility); 32 return; 33 } 34 35 if (!GV.hasLinkOnceLinkage()) { 36 assert(!GV.isDiscardableIfUnused()); 37 return; 38 } 39 40 // Map linkonce* to weak* so that llvm doesn't drop this GV. 41 switch(GV.getLinkage()) { 42 default: 43 llvm_unreachable("Unexpected linkage"); 44 case GlobalValue::LinkOnceAnyLinkage: 45 GV.setLinkage(GlobalValue::WeakAnyLinkage); 46 return; 47 case GlobalValue::LinkOnceODRLinkage: 48 GV.setLinkage(GlobalValue::WeakODRLinkage); 49 return; 50 } 51 } 52 53 namespace { 54 /// @brief A pass to extract specific global values and their dependencies. 55 class GVExtractorPass : public ModulePass { 56 SetVector<GlobalValue *> Named; 57 bool deleteStuff; 58 public: 59 static char ID; // Pass identification, replacement for typeid 60 61 /// If deleteS is true, this pass deletes the specified global values. 62 /// Otherwise, it deletes as much of the module as possible, except for the 63 /// global values specified. 64 explicit GVExtractorPass(std::vector<GlobalValue*> &GVs, 65 bool deleteS = true) 66 : ModulePass(ID), Named(GVs.begin(), GVs.end()), deleteStuff(deleteS) {} 67 68 bool runOnModule(Module &M) override { 69 if (skipModule(M)) 70 return false; 71 72 // Visit the global inline asm. 73 if (!deleteStuff) 74 M.setModuleInlineAsm(""); 75 76 // For simplicity, just give all GlobalValues ExternalLinkage. A trickier 77 // implementation could figure out which GlobalValues are actually 78 // referenced by the Named set, and which GlobalValues in the rest of 79 // the module are referenced by the NamedSet, and get away with leaving 80 // more internal and private things internal and private. But for now, 81 // be conservative and simple. 82 83 // Visit the GlobalVariables. 84 for (Module::global_iterator I = M.global_begin(), E = M.global_end(); 85 I != E; ++I) { 86 bool Delete = 87 deleteStuff == (bool)Named.count(&*I) && !I->isDeclaration(); 88 if (!Delete) { 89 if (I->hasAvailableExternallyLinkage()) 90 continue; 91 if (I->getName() == "llvm.global_ctors") 92 continue; 93 } 94 95 makeVisible(*I, Delete); 96 97 if (Delete) { 98 // Make this a declaration and drop it's comdat. 99 I->setInitializer(nullptr); 100 I->setComdat(nullptr); 101 } 102 } 103 104 // Visit the Functions. 105 for (Function &F : M) { 106 bool Delete = 107 deleteStuff == (bool)Named.count(&F) && !F.isDeclaration(); 108 if (!Delete) { 109 if (F.hasAvailableExternallyLinkage()) 110 continue; 111 } 112 113 makeVisible(F, Delete); 114 115 if (Delete) { 116 // Make this a declaration and drop it's comdat. 117 F.deleteBody(); 118 F.setComdat(nullptr); 119 } 120 } 121 122 // Visit the Aliases. 123 for (Module::alias_iterator I = M.alias_begin(), E = M.alias_end(); 124 I != E;) { 125 Module::alias_iterator CurI = I; 126 ++I; 127 128 bool Delete = deleteStuff == (bool)Named.count(&*CurI); 129 makeVisible(*CurI, Delete); 130 131 if (Delete) { 132 Type *Ty = CurI->getValueType(); 133 134 CurI->removeFromParent(); 135 llvm::Value *Declaration; 136 if (FunctionType *FTy = dyn_cast<FunctionType>(Ty)) { 137 Declaration = Function::Create(FTy, GlobalValue::ExternalLinkage, 138 CurI->getName(), &M); 139 140 } else { 141 Declaration = 142 new GlobalVariable(M, Ty, false, GlobalValue::ExternalLinkage, 143 nullptr, CurI->getName()); 144 145 } 146 CurI->replaceAllUsesWith(Declaration); 147 delete &*CurI; 148 } 149 } 150 151 return true; 152 } 153 }; 154 155 char GVExtractorPass::ID = 0; 156 } 157 158 ModulePass *llvm::createGVExtractionPass(std::vector<GlobalValue *> &GVs, 159 bool deleteFn) { 160 return new GVExtractorPass(GVs, deleteFn); 161 } 162