123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158 |
- //===-- ExtractGV.cpp - Global Value extraction pass ----------------------===//
- //
- // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
- // See https://llvm.org/LICENSE.txt for license information.
- // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
- //
- //===----------------------------------------------------------------------===//
- //
- // This pass extracts global values
- //
- //===----------------------------------------------------------------------===//
- #include "llvm/ADT/SetVector.h"
- #include "llvm/IR/LLVMContext.h"
- #include "llvm/IR/Module.h"
- #include "llvm/Pass.h"
- #include "llvm/Transforms/IPO.h"
- #include <algorithm>
- using namespace llvm;
- /// Make sure GV is visible from both modules. Delete is true if it is
- /// being deleted from this module.
- /// This also makes sure GV cannot be dropped so that references from
- /// the split module remain valid.
- static void makeVisible(GlobalValue &GV, bool Delete) {
- bool Local = GV.hasLocalLinkage();
- if (Local || Delete) {
- GV.setLinkage(GlobalValue::ExternalLinkage);
- if (Local)
- GV.setVisibility(GlobalValue::HiddenVisibility);
- return;
- }
- if (!GV.hasLinkOnceLinkage()) {
- assert(!GV.isDiscardableIfUnused());
- return;
- }
- // Map linkonce* to weak* so that llvm doesn't drop this GV.
- switch(GV.getLinkage()) {
- default:
- llvm_unreachable("Unexpected linkage");
- case GlobalValue::LinkOnceAnyLinkage:
- GV.setLinkage(GlobalValue::WeakAnyLinkage);
- return;
- case GlobalValue::LinkOnceODRLinkage:
- GV.setLinkage(GlobalValue::WeakODRLinkage);
- return;
- }
- }
- namespace {
- /// A pass to extract specific global values and their dependencies.
- class GVExtractorPass : public ModulePass {
- SetVector<GlobalValue *> Named;
- bool deleteStuff;
- bool keepConstInit;
- public:
- static char ID; // Pass identification, replacement for typeid
- /// If deleteS is true, this pass deletes the specified global values.
- /// Otherwise, it deletes as much of the module as possible, except for the
- /// global values specified.
- explicit GVExtractorPass(std::vector<GlobalValue*> &GVs,
- bool deleteS = true, bool keepConstInit = false)
- : ModulePass(ID), Named(GVs.begin(), GVs.end()), deleteStuff(deleteS),
- keepConstInit(keepConstInit) {}
- bool runOnModule(Module &M) override {
- if (skipModule(M))
- return false;
- // Visit the global inline asm.
- if (!deleteStuff)
- M.setModuleInlineAsm("");
- // For simplicity, just give all GlobalValues ExternalLinkage. A trickier
- // implementation could figure out which GlobalValues are actually
- // referenced by the Named set, and which GlobalValues in the rest of
- // the module are referenced by the NamedSet, and get away with leaving
- // more internal and private things internal and private. But for now,
- // be conservative and simple.
- // Visit the GlobalVariables.
- for (GlobalVariable &GV : M.globals()) {
- bool Delete = deleteStuff == (bool)Named.count(&GV) &&
- !GV.isDeclaration() &&
- (!GV.isConstant() || !keepConstInit);
- if (!Delete) {
- if (GV.hasAvailableExternallyLinkage())
- continue;
- if (GV.getName() == "llvm.global_ctors")
- continue;
- }
- makeVisible(GV, Delete);
- if (Delete) {
- // Make this a declaration and drop it's comdat.
- GV.setInitializer(nullptr);
- GV.setComdat(nullptr);
- }
- }
- // Visit the Functions.
- for (Function &F : M) {
- bool Delete =
- deleteStuff == (bool)Named.count(&F) && !F.isDeclaration();
- if (!Delete) {
- if (F.hasAvailableExternallyLinkage())
- continue;
- }
- makeVisible(F, Delete);
- if (Delete) {
- // Make this a declaration and drop it's comdat.
- F.deleteBody();
- F.setComdat(nullptr);
- }
- }
- // Visit the Aliases.
- for (GlobalAlias &GA : llvm::make_early_inc_range(M.aliases())) {
- bool Delete = deleteStuff == (bool)Named.count(&GA);
- makeVisible(GA, Delete);
- if (Delete) {
- Type *Ty = GA.getValueType();
- GA.removeFromParent();
- llvm::Value *Declaration;
- if (FunctionType *FTy = dyn_cast<FunctionType>(Ty)) {
- Declaration =
- Function::Create(FTy, GlobalValue::ExternalLinkage,
- GA.getAddressSpace(), GA.getName(), &M);
- } else {
- Declaration =
- new GlobalVariable(M, Ty, false, GlobalValue::ExternalLinkage,
- nullptr, GA.getName());
- }
- GA.replaceAllUsesWith(Declaration);
- delete &GA;
- }
- }
- return true;
- }
- };
- char GVExtractorPass::ID = 0;
- }
- ModulePass *llvm::createGVExtractionPass(std::vector<GlobalValue *> &GVs,
- bool deleteFn, bool keepConstInit) {
- return new GVExtractorPass(GVs, deleteFn, keepConstInit);
- }
|