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 // Visit the global inline asm. 72 if (!deleteStuff) 73 M.setModuleInlineAsm(""); 74 75 // For simplicity, just give all GlobalValues ExternalLinkage. A trickier 76 // implementation could figure out which GlobalValues are actually 77 // referenced by the Named set, and which GlobalValues in the rest of 78 // the module are referenced by the NamedSet, and get away with leaving 79 // more internal and private things internal and private. But for now, 80 // be conservative and simple. 81 82 // Visit the GlobalVariables. 83 for (Module::global_iterator I = M.global_begin(), E = M.global_end(); 84 I != E; ++I) { 85 bool Delete = 86 deleteStuff == (bool)Named.count(&*I) && !I->isDeclaration(); 87 if (!Delete) { 88 if (I->hasAvailableExternallyLinkage()) 89 continue; 90 if (I->getName() == "llvm.global_ctors") 91 continue; 92 } 93 94 makeVisible(*I, Delete); 95 96 if (Delete) { 97 // Make this a declaration and drop it's comdat. 98 I->setInitializer(nullptr); 99 I->setComdat(nullptr); 100 } 101 } 102 103 // Visit the Functions. 104 for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) { 105 bool Delete = 106 deleteStuff == (bool)Named.count(&*I) && !I->isDeclaration(); 107 if (!Delete) { 108 if (I->hasAvailableExternallyLinkage()) 109 continue; 110 } 111 112 makeVisible(*I, Delete); 113 114 if (Delete) { 115 // Make this a declaration and drop it's comdat. 116 I->deleteBody(); 117 I->setComdat(nullptr); 118 } 119 } 120 121 // Visit the Aliases. 122 for (Module::alias_iterator I = M.alias_begin(), E = M.alias_end(); 123 I != E;) { 124 Module::alias_iterator CurI = I; 125 ++I; 126 127 bool Delete = deleteStuff == (bool)Named.count(&*CurI); 128 makeVisible(*CurI, Delete); 129 130 if (Delete) { 131 Type *Ty = CurI->getType()->getElementType(); 132 133 CurI->removeFromParent(); 134 llvm::Value *Declaration; 135 if (FunctionType *FTy = dyn_cast<FunctionType>(Ty)) { 136 Declaration = Function::Create(FTy, GlobalValue::ExternalLinkage, 137 CurI->getName(), &M); 138 139 } else { 140 Declaration = 141 new GlobalVariable(M, Ty, false, GlobalValue::ExternalLinkage, 142 nullptr, CurI->getName()); 143 144 } 145 CurI->replaceAllUsesWith(Declaration); 146 delete &*CurI; 147 } 148 } 149 150 return true; 151 } 152 }; 153 154 char GVExtractorPass::ID = 0; 155} 156 157ModulePass *llvm::createGVExtractionPass(std::vector<GlobalValue *> &GVs, 158 bool deleteFn) { 159 return new GVExtractorPass(GVs, deleteFn); 160} 161