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