149 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8//9// This pass extracts global values10//11//===----------------------------------------------------------------------===//12 13#include "llvm/Transforms/IPO/ExtractGV.h"14#include "llvm/IR/Module.h"15#include "llvm/IR/PassManager.h"16 17using namespace llvm;18 19/// Make sure GV is visible from both modules. Delete is true if it is20/// being deleted from this module.21/// This also makes sure GV cannot be dropped so that references from22/// the split module remain valid.23static 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 the52/// global values specified.53ExtractGVPass::ExtractGVPass(std::vector<GlobalValue *> &GVs, bool deleteS,54 bool keepConstInit)55 : Named(llvm::from_range, GVs), deleteStuff(deleteS),56 keepConstInit(keepConstInit) {}57 58PreservedAnalyses 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 trickier64 // implementation could figure out which GlobalValues are actually65 // referenced by the Named set, and which GlobalValues in the rest of66 // the module are referenced by the NamedSet, and get away with leaving67 // 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