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 (GlobalVariable &GV : M.globals()) { 86 bool Delete = deleteStuff == (bool)Named.count(&GV) && 87 !GV.isDeclaration() && 88 (!GV.isConstant() || !keepConstInit); 89 if (!Delete) { 90 if (GV.hasAvailableExternallyLinkage()) 91 continue; 92 if (GV.getName() == "llvm.global_ctors") 93 continue; 94 } 95 96 makeVisible(GV, Delete); 97 98 if (Delete) { 99 // Make this a declaration and drop it's comdat. 100 GV.setInitializer(nullptr); 101 GV.setComdat(nullptr); 102 } 103 } 104 105 // Visit the Functions. 106 for (Function &F : M) { 107 bool Delete = 108 deleteStuff == (bool)Named.count(&F) && !F.isDeclaration(); 109 if (!Delete) { 110 if (F.hasAvailableExternallyLinkage()) 111 continue; 112 } 113 114 makeVisible(F, Delete); 115 116 if (Delete) { 117 // Make this a declaration and drop it's comdat. 118 F.deleteBody(); 119 F.setComdat(nullptr); 120 } 121 } 122 123 // Visit the Aliases. 124 for (GlobalAlias &GA : llvm::make_early_inc_range(M.aliases())) { 125 bool Delete = deleteStuff == (bool)Named.count(&GA); 126 makeVisible(GA, Delete); 127 128 if (Delete) { 129 Type *Ty = GA.getValueType(); 130 131 GA.removeFromParent(); 132 llvm::Value *Declaration; 133 if (FunctionType *FTy = dyn_cast<FunctionType>(Ty)) { 134 Declaration = 135 Function::Create(FTy, GlobalValue::ExternalLinkage, 136 GA.getAddressSpace(), GA.getName(), &M); 137 138 } else { 139 Declaration = 140 new GlobalVariable(M, Ty, false, GlobalValue::ExternalLinkage, 141 nullptr, GA.getName()); 142 } 143 GA.replaceAllUsesWith(Declaration); 144 delete &GA; 145 } 146 } 147 148 return true; 149 } 150 }; 151 152 char GVExtractorPass::ID = 0; 153 } 154 155 ModulePass *llvm::createGVExtractionPass(std::vector<GlobalValue *> &GVs, 156 bool deleteFn, bool keepConstInit) { 157 return new GVExtractorPass(GVs, deleteFn, keepConstInit); 158 } 159