Path: blob/main/contrib/llvm-project/llvm/lib/Transforms/IPO/ExtractGV.cpp
35266 views
//===-- ExtractGV.cpp - Global Value extraction pass ----------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// This pass extracts global values9//10//===----------------------------------------------------------------------===//1112#include "llvm/Transforms/IPO/ExtractGV.h"13#include "llvm/IR/Module.h"14#include "llvm/IR/PassManager.h"15#include <algorithm>1617using namespace llvm;1819/// 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) {24bool Local = GV.hasLocalLinkage();25if (Local || Delete) {26GV.setLinkage(GlobalValue::ExternalLinkage);27if (Local)28GV.setVisibility(GlobalValue::HiddenVisibility);29return;30}3132if (!GV.hasLinkOnceLinkage()) {33assert(!GV.isDiscardableIfUnused());34return;35}3637// Map linkonce* to weak* so that llvm doesn't drop this GV.38switch (GV.getLinkage()) {39default:40llvm_unreachable("Unexpected linkage");41case GlobalValue::LinkOnceAnyLinkage:42GV.setLinkage(GlobalValue::WeakAnyLinkage);43return;44case GlobalValue::LinkOnceODRLinkage:45GV.setLinkage(GlobalValue::WeakODRLinkage);46return;47}48}4950/// 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,54bool keepConstInit)55: Named(GVs.begin(), GVs.end()), deleteStuff(deleteS),56keepConstInit(keepConstInit) {}5758PreservedAnalyses ExtractGVPass::run(Module &M, ModuleAnalysisManager &) {59// Visit the global inline asm.60if (!deleteStuff)61M.setModuleInlineAsm("");6263// 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.6970// Visit the GlobalVariables.71for (GlobalVariable &GV : M.globals()) {72bool Delete = deleteStuff == (bool)Named.count(&GV) &&73!GV.isDeclaration() && (!GV.isConstant() || !keepConstInit);74if (!Delete) {75if (GV.hasAvailableExternallyLinkage())76continue;77if (GV.getName() == "llvm.global_ctors")78continue;79}8081makeVisible(GV, Delete);8283if (Delete) {84// Make this a declaration and drop it's comdat.85GV.setInitializer(nullptr);86GV.setComdat(nullptr);87}88}8990// Visit the Functions.91for (Function &F : M) {92bool Delete = deleteStuff == (bool)Named.count(&F) && !F.isDeclaration();93if (!Delete) {94if (F.hasAvailableExternallyLinkage())95continue;96}9798makeVisible(F, Delete);99100if (Delete) {101// Make this a declaration and drop it's comdat.102F.deleteBody();103F.setComdat(nullptr);104}105}106107// Visit the Aliases.108for (GlobalAlias &GA : llvm::make_early_inc_range(M.aliases())) {109bool Delete = deleteStuff == (bool)Named.count(&GA);110makeVisible(GA, Delete);111112if (Delete) {113Type *Ty = GA.getValueType();114115GA.removeFromParent();116llvm::Value *Declaration;117if (FunctionType *FTy = dyn_cast<FunctionType>(Ty)) {118Declaration = Function::Create(FTy, GlobalValue::ExternalLinkage,119GA.getAddressSpace(), GA.getName(), &M);120121} else {122Declaration = new GlobalVariable(123M, Ty, false, GlobalValue::ExternalLinkage, nullptr, GA.getName());124}125GA.replaceAllUsesWith(Declaration);126delete &GA;127}128}129130// Visit the IFuncs.131for (GlobalIFunc &IF : llvm::make_early_inc_range(M.ifuncs())) {132bool Delete = deleteStuff == (bool)Named.count(&IF);133makeVisible(IF, Delete);134135if (!Delete)136continue;137138auto *FuncType = dyn_cast<FunctionType>(IF.getValueType());139IF.removeFromParent();140llvm::Value *Declaration =141Function::Create(FuncType, GlobalValue::ExternalLinkage,142IF.getAddressSpace(), IF.getName(), &M);143IF.replaceAllUsesWith(Declaration);144delete &IF;145}146147return PreservedAnalyses::none();148}149150151