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 52 /// If deleteS is true, this pass deletes the specified global values. 53 /// Otherwise, it deletes as much of the module as possible, except for the 54 /// global values specified. 55 ExtractGVPass::ExtractGVPass(std::vector<GlobalValue *> &GVs, bool deleteS, 56 bool keepConstInit) 57 : Named(GVs.begin(), GVs.end()), deleteStuff(deleteS), 58 keepConstInit(keepConstInit) {} 59 60 PreservedAnalyses ExtractGVPass::run(Module &M, ModuleAnalysisManager &) { 61 // Visit the global inline asm. 62 if (!deleteStuff) 63 M.setModuleInlineAsm(""); 64 65 // For simplicity, just give all GlobalValues ExternalLinkage. A trickier 66 // implementation could figure out which GlobalValues are actually 67 // referenced by the Named set, and which GlobalValues in the rest of 68 // the module are referenced by the NamedSet, and get away with leaving 69 // more internal and private things internal and private. But for now, 70 // be conservative and simple. 71 72 // Visit the GlobalVariables. 73 for (GlobalVariable &GV : M.globals()) { 74 bool Delete = deleteStuff == (bool)Named.count(&GV) && 75 !GV.isDeclaration() && (!GV.isConstant() || !keepConstInit); 76 if (!Delete) { 77 if (GV.hasAvailableExternallyLinkage()) 78 continue; 79 if (GV.getName() == "llvm.global_ctors") 80 continue; 81 } 82 83 makeVisible(GV, Delete); 84 85 if (Delete) { 86 // Make this a declaration and drop it's comdat. 87 GV.setInitializer(nullptr); 88 GV.setComdat(nullptr); 89 } 90 } 91 92 // Visit the Functions. 93 for (Function &F : M) { 94 bool Delete = deleteStuff == (bool)Named.count(&F) && !F.isDeclaration(); 95 if (!Delete) { 96 if (F.hasAvailableExternallyLinkage()) 97 continue; 98 } 99 100 makeVisible(F, Delete); 101 102 if (Delete) { 103 // Make this a declaration and drop it's comdat. 104 F.deleteBody(); 105 F.setComdat(nullptr); 106 } 107 } 108 109 // Visit the Aliases. 110 for (GlobalAlias &GA : llvm::make_early_inc_range(M.aliases())) { 111 bool Delete = deleteStuff == (bool)Named.count(&GA); 112 makeVisible(GA, Delete); 113 114 if (Delete) { 115 Type *Ty = GA.getValueType(); 116 117 GA.removeFromParent(); 118 llvm::Value *Declaration; 119 if (FunctionType *FTy = dyn_cast<FunctionType>(Ty)) { 120 Declaration = Function::Create(FTy, GlobalValue::ExternalLinkage, 121 GA.getAddressSpace(), GA.getName(), &M); 122 123 } else { 124 Declaration = new GlobalVariable( 125 M, Ty, false, GlobalValue::ExternalLinkage, nullptr, GA.getName()); 126 } 127 GA.replaceAllUsesWith(Declaration); 128 delete &GA; 129 } 130 } 131 132 return PreservedAnalyses::none(); 133 } 134