brintos

brintos / llvm-project-archived public Read only

0
0
Text · 4.6 KiB · 16fdb93 Raw
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