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