1//===-- ExtractGV.cpp - Global Value extraction pass ----------------------===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9// 10// This pass extracts global values 11// 12//===----------------------------------------------------------------------===// 13 14#include "llvm/Transforms/IPO.h" 15#include "llvm/ADT/SetVector.h" 16#include "llvm/IR/Constants.h" 17#include "llvm/IR/Instructions.h" 18#include "llvm/IR/LLVMContext.h" 19#include "llvm/IR/Module.h" 20#include "llvm/Pass.h" 21#include <algorithm> 22using namespace llvm; 23 24/// Make sure GV is visible from both modules. Delete is true if it is 25/// being deleted from this module. 26/// This also makes sure GV cannot be dropped so that references from 27/// the split module remain valid. 28static void makeVisible(GlobalValue &GV, bool Delete) { 29 bool Local = GV.hasLocalLinkage(); 30 if (Local || Delete) { 31 GV.setLinkage(GlobalValue::ExternalLinkage); 32 if (Local) 33 GV.setVisibility(GlobalValue::HiddenVisibility); 34 return; 35 } 36 37 if (!GV.hasLinkOnceLinkage()) { 38 assert(!GV.isDiscardableIfUnused()); 39 return; 40 } 41 42 // Map linkonce* to weak* so that llvm doesn't drop this GV. 43 switch(GV.getLinkage()) { 44 default: 45 llvm_unreachable("Unexpected linkage"); 46 case GlobalValue::LinkOnceAnyLinkage: 47 GV.setLinkage(GlobalValue::WeakAnyLinkage); 48 return; 49 case GlobalValue::LinkOnceODRLinkage: 50 GV.setLinkage(GlobalValue::WeakODRLinkage); 51 return; 52 } 53} 54 55namespace { 56 /// @brief A pass to extract specific functions and their dependencies. 57 class GVExtractorPass : public ModulePass { 58 SetVector<GlobalValue *> Named; 59 bool deleteStuff; 60 public: 61 static char ID; // Pass identification, replacement for typeid 62 63 /// FunctionExtractorPass - If deleteFn is true, this pass deletes as the 64 /// specified function. Otherwise, it deletes as much of the module as 65 /// possible, except for the function specified. 66 /// 67 explicit GVExtractorPass(std::vector<GlobalValue*>& GVs, bool deleteS = true) 68 : ModulePass(ID), Named(GVs.begin(), GVs.end()), deleteStuff(deleteS) {} 69 70 bool runOnModule(Module &M) override { 71 if (skipModule(M)) 72 return false; 73 74 // Visit the global inline asm. 75 if (!deleteStuff) 76 M.setModuleInlineAsm(""); 77 78 // For simplicity, just give all GlobalValues ExternalLinkage. A trickier 79 // implementation could figure out which GlobalValues are actually 80 // referenced by the Named set, and which GlobalValues in the rest of 81 // the module are referenced by the NamedSet, and get away with leaving 82 // more internal and private things internal and private. But for now, 83 // be conservative and simple. 84 85 // Visit the GlobalVariables. 86 for (Module::global_iterator I = M.global_begin(), E = M.global_end(); 87 I != E; ++I) { 88 bool Delete = 89 deleteStuff == (bool)Named.count(&*I) && !I->isDeclaration(); 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->getName(), &M); 141 142 } else { 143 Declaration = 144 new GlobalVariable(M, Ty, false, GlobalValue::ExternalLinkage, 145 nullptr, CurI->getName()); 146 147 } 148 CurI->replaceAllUsesWith(Declaration); 149 delete &*CurI; 150 } 151 } 152 153 return true; 154 } 155 }; 156 157 char GVExtractorPass::ID = 0; 158} 159 160ModulePass *llvm::createGVExtractionPass(std::vector<GlobalValue *> &GVs, 161 bool deleteFn) { 162 return new GVExtractorPass(GVs, deleteFn); 163} 164