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/Transforms/IPO/ExtractGV.h" 14 #include "llvm/IR/Module.h" 15 #include "llvm/IR/PassManager.h" 16 17 using namespace llvm; 18 19 /// Make sure GV is visible from both modules. Delete is true if it is 20 /// being deleted from this module. 21 /// This also makes sure GV cannot be dropped so that references from 22 /// the split module remain valid. 23 static void makeVisible(GlobalValue &GV, bool Delete) { 24 bool Local = GV.hasLocalLinkage(); 25 if (Local || Delete) { 26 GV.setLinkage(GlobalValue::ExternalLinkage); 27 if (Local) 28 GV.setVisibility(GlobalValue::HiddenVisibility); 29 return; 30 } 31 32 if (!GV.hasLinkOnceLinkage()) { 33 assert(!GV.isDiscardableIfUnused()); 34 return; 35 } 36 37 // Map linkonce* to weak* so that llvm doesn't drop this GV. 38 switch (GV.getLinkage()) { 39 default: 40 llvm_unreachable("Unexpected linkage"); 41 case GlobalValue::LinkOnceAnyLinkage: 42 GV.setLinkage(GlobalValue::WeakAnyLinkage); 43 return; 44 case GlobalValue::LinkOnceODRLinkage: 45 GV.setLinkage(GlobalValue::WeakODRLinkage); 46 return; 47 } 48 } 49 50 /// If deleteS is true, this pass deletes the specified global values. 51 /// Otherwise, it deletes as much of the module as possible, except for the 52 /// global values specified. 53 ExtractGVPass::ExtractGVPass(std::vector<GlobalValue *> &GVs, bool deleteS, 54 bool keepConstInit) 55 : Named(GVs.begin(), GVs.end()), deleteStuff(deleteS), 56 keepConstInit(keepConstInit) {} 57 58 PreservedAnalyses ExtractGVPass::run(Module &M, ModuleAnalysisManager &) { 59 // Visit the global inline asm. 60 if (!deleteStuff) 61 M.setModuleInlineAsm(""); 62 63 // For simplicity, just give all GlobalValues ExternalLinkage. A trickier 64 // implementation could figure out which GlobalValues are actually 65 // referenced by the Named set, and which GlobalValues in the rest of 66 // the module are referenced by the NamedSet, and get away with leaving 67 // more internal and private things internal and private. But for now, 68 // be conservative and simple. 69 70 // Visit the GlobalVariables. 71 for (GlobalVariable &GV : M.globals()) { 72 bool Delete = deleteStuff == (bool)Named.count(&GV) && 73 !GV.isDeclaration() && (!GV.isConstant() || !keepConstInit); 74 if (!Delete) { 75 if (GV.hasAvailableExternallyLinkage()) 76 continue; 77 if (GV.getName() == "llvm.global_ctors") 78 continue; 79 } 80 81 makeVisible(GV, Delete); 82 83 if (Delete) { 84 // Make this a declaration and drop it's comdat. 85 GV.setInitializer(nullptr); 86 GV.setComdat(nullptr); 87 } 88 } 89 90 // Visit the Functions. 91 for (Function &F : M) { 92 bool Delete = deleteStuff == (bool)Named.count(&F) && !F.isDeclaration(); 93 if (!Delete) { 94 if (F.hasAvailableExternallyLinkage()) 95 continue; 96 } 97 98 makeVisible(F, Delete); 99 100 if (Delete) { 101 // Make this a declaration and drop it's comdat. 102 F.deleteBody(); 103 F.setComdat(nullptr); 104 } 105 } 106 107 // Visit the Aliases. 108 for (GlobalAlias &GA : llvm::make_early_inc_range(M.aliases())) { 109 bool Delete = deleteStuff == (bool)Named.count(&GA); 110 makeVisible(GA, Delete); 111 112 if (Delete) { 113 Type *Ty = GA.getValueType(); 114 115 GA.removeFromParent(); 116 llvm::Value *Declaration; 117 if (FunctionType *FTy = dyn_cast<FunctionType>(Ty)) { 118 Declaration = Function::Create(FTy, GlobalValue::ExternalLinkage, 119 GA.getAddressSpace(), GA.getName(), &M); 120 121 } else { 122 Declaration = new GlobalVariable( 123 M, Ty, false, GlobalValue::ExternalLinkage, nullptr, GA.getName()); 124 } 125 GA.replaceAllUsesWith(Declaration); 126 delete &GA; 127 } 128 } 129 130 // Visit the IFuncs. 131 for (GlobalIFunc &IF : llvm::make_early_inc_range(M.ifuncs())) { 132 bool Delete = deleteStuff == (bool)Named.count(&IF); 133 makeVisible(IF, Delete); 134 135 if (!Delete) 136 continue; 137 138 auto *FuncType = dyn_cast<FunctionType>(IF.getValueType()); 139 IF.removeFromParent(); 140 llvm::Value *Declaration = 141 Function::Create(FuncType, GlobalValue::ExternalLinkage, 142 IF.getAddressSpace(), IF.getName(), &M); 143 IF.replaceAllUsesWith(Declaration); 144 delete &IF; 145 } 146 147 return PreservedAnalyses::none(); 148 } 149