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 bool keepConstInit; 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, bool keepConstInit = false) 66 : ModulePass(ID), Named(GVs.begin(), GVs.end()), deleteStuff(deleteS), 67 keepConstInit(keepConstInit) {} 68 69 bool runOnModule(Module &M) override { 70 if (skipModule(M)) 71 return false; 72 73 // Visit the global inline asm. 74 if (!deleteStuff) 75 M.setModuleInlineAsm(""); 76 77 // For simplicity, just give all GlobalValues ExternalLinkage. A trickier 78 // implementation could figure out which GlobalValues are actually 79 // referenced by the Named set, and which GlobalValues in the rest of 80 // the module are referenced by the NamedSet, and get away with leaving 81 // more internal and private things internal and private. But for now, 82 // be conservative and simple. 83 84 // Visit the GlobalVariables. 85 for (Module::global_iterator I = M.global_begin(), E = M.global_end(); 86 I != E; ++I) { 87 bool Delete = 88 deleteStuff == (bool)Named.count(&*I) && !I->isDeclaration() && 89 (!I->isConstant() || !keepConstInit); 90 if (!Delete) { 91 if (I->hasAvailableExternallyLinkage()) 92 continue; 93 if (I->getName() == "llvm.global_ctors") 94 continue; 95 } 96 97 makeVisible(*I, Delete); 98 99 if (Delete) { 100 // Make this a declaration and drop it's comdat. 101 I->setInitializer(nullptr); 102 I->setComdat(nullptr); 103 } 104 } 105 106 // Visit the Functions. 107 for (Function &F : M) { 108 bool Delete = 109 deleteStuff == (bool)Named.count(&F) && !F.isDeclaration(); 110 if (!Delete) { 111 if (F.hasAvailableExternallyLinkage()) 112 continue; 113 } 114 115 makeVisible(F, Delete); 116 117 if (Delete) { 118 // Make this a declaration and drop it's comdat. 119 F.deleteBody(); 120 F.setComdat(nullptr); 121 } 122 } 123 124 // Visit the Aliases. 125 for (Module::alias_iterator I = M.alias_begin(), E = M.alias_end(); 126 I != E;) { 127 Module::alias_iterator CurI = I; 128 ++I; 129 130 bool Delete = deleteStuff == (bool)Named.count(&*CurI); 131 makeVisible(*CurI, Delete); 132 133 if (Delete) { 134 Type *Ty = CurI->getValueType(); 135 136 CurI->removeFromParent(); 137 llvm::Value *Declaration; 138 if (FunctionType *FTy = dyn_cast<FunctionType>(Ty)) { 139 Declaration = Function::Create(FTy, GlobalValue::ExternalLinkage, 140 CurI->getAddressSpace(), 141 CurI->getName(), &M); 142 143 } else { 144 Declaration = 145 new GlobalVariable(M, Ty, false, GlobalValue::ExternalLinkage, 146 nullptr, CurI->getName()); 147 148 } 149 CurI->replaceAllUsesWith(Declaration); 150 delete &*CurI; 151 } 152 } 153 154 return true; 155 } 156 }; 157 158 char GVExtractorPass::ID = 0; 159 } 160 161 ModulePass *llvm::createGVExtractionPass(std::vector<GlobalValue *> &GVs, 162 bool deleteFn, bool keepConstInit) { 163 return new GVExtractorPass(GVs, deleteFn, keepConstInit); 164 } 165