Path: blob/main/contrib/llvm-project/llvm/lib/Transforms/Utils/CloneModule.cpp
35271 views
//===- CloneModule.cpp - Clone an entire module ---------------------------===//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 file implements the CloneModule interface which makes a copy of an9// entire module.10//11//===----------------------------------------------------------------------===//1213#include "llvm/IR/DerivedTypes.h"14#include "llvm/IR/Module.h"15#include "llvm/Transforms/Utils/Cloning.h"16#include "llvm/Transforms/Utils/ValueMapper.h"17using namespace llvm;1819namespace llvm {20class Constant;21}2223static void copyComdat(GlobalObject *Dst, const GlobalObject *Src) {24const Comdat *SC = Src->getComdat();25if (!SC)26return;27Comdat *DC = Dst->getParent()->getOrInsertComdat(SC->getName());28DC->setSelectionKind(SC->getSelectionKind());29Dst->setComdat(DC);30}3132/// This is not as easy as it might seem because we have to worry about making33/// copies of global variables and functions, and making their (initializers and34/// references, respectively) refer to the right globals.35///36/// Cloning un-materialized modules is not currently supported, so any37/// modules initialized via lazy loading should be materialized before cloning38std::unique_ptr<Module> llvm::CloneModule(const Module &M) {39// Create the value map that maps things from the old module over to the new40// module.41ValueToValueMapTy VMap;42return CloneModule(M, VMap);43}4445std::unique_ptr<Module> llvm::CloneModule(const Module &M,46ValueToValueMapTy &VMap) {47return CloneModule(M, VMap, [](const GlobalValue *GV) { return true; });48}4950std::unique_ptr<Module> llvm::CloneModule(51const Module &M, ValueToValueMapTy &VMap,52function_ref<bool(const GlobalValue *)> ShouldCloneDefinition) {5354assert(M.isMaterialized() && "Module must be materialized before cloning!");5556// First off, we need to create the new module.57std::unique_ptr<Module> New =58std::make_unique<Module>(M.getModuleIdentifier(), M.getContext());59New->setSourceFileName(M.getSourceFileName());60New->setDataLayout(M.getDataLayout());61New->setTargetTriple(M.getTargetTriple());62New->setModuleInlineAsm(M.getModuleInlineAsm());63New->IsNewDbgInfoFormat = M.IsNewDbgInfoFormat;6465// Loop over all of the global variables, making corresponding globals in the66// new module. Here we add them to the VMap and to the new Module. We67// don't worry about attributes or initializers, they will come later.68//69for (const GlobalVariable &I : M.globals()) {70GlobalVariable *NewGV = new GlobalVariable(71*New, I.getValueType(), I.isConstant(), I.getLinkage(),72(Constant *)nullptr, I.getName(), (GlobalVariable *)nullptr,73I.getThreadLocalMode(), I.getType()->getAddressSpace());74NewGV->copyAttributesFrom(&I);75VMap[&I] = NewGV;76}7778// Loop over the functions in the module, making external functions as before79for (const Function &I : M) {80Function *NF =81Function::Create(cast<FunctionType>(I.getValueType()), I.getLinkage(),82I.getAddressSpace(), I.getName(), New.get());83NF->copyAttributesFrom(&I);84VMap[&I] = NF;85}8687// Loop over the aliases in the module88for (const GlobalAlias &I : M.aliases()) {89if (!ShouldCloneDefinition(&I)) {90// An alias cannot act as an external reference, so we need to create91// either a function or a global variable depending on the value type.92// FIXME: Once pointee types are gone we can probably pick one or the93// other.94GlobalValue *GV;95if (I.getValueType()->isFunctionTy())96GV = Function::Create(cast<FunctionType>(I.getValueType()),97GlobalValue::ExternalLinkage, I.getAddressSpace(),98I.getName(), New.get());99else100GV = new GlobalVariable(*New, I.getValueType(), false,101GlobalValue::ExternalLinkage, nullptr,102I.getName(), nullptr, I.getThreadLocalMode(),103I.getType()->getAddressSpace());104VMap[&I] = GV;105// We do not copy attributes (mainly because copying between different106// kinds of globals is forbidden), but this is generally not required for107// correctness.108continue;109}110auto *GA = GlobalAlias::create(I.getValueType(),111I.getType()->getPointerAddressSpace(),112I.getLinkage(), I.getName(), New.get());113GA->copyAttributesFrom(&I);114VMap[&I] = GA;115}116117for (const GlobalIFunc &I : M.ifuncs()) {118// Defer setting the resolver function until after functions are cloned.119auto *GI =120GlobalIFunc::create(I.getValueType(), I.getAddressSpace(),121I.getLinkage(), I.getName(), nullptr, New.get());122GI->copyAttributesFrom(&I);123VMap[&I] = GI;124}125126// Now that all of the things that global variable initializer can refer to127// have been created, loop through and copy the global variable referrers128// over... We also set the attributes on the global now.129//130for (const GlobalVariable &G : M.globals()) {131GlobalVariable *GV = cast<GlobalVariable>(VMap[&G]);132133SmallVector<std::pair<unsigned, MDNode *>, 1> MDs;134G.getAllMetadata(MDs);135for (auto MD : MDs)136GV->addMetadata(MD.first, *MapMetadata(MD.second, VMap));137138if (G.isDeclaration())139continue;140141if (!ShouldCloneDefinition(&G)) {142// Skip after setting the correct linkage for an external reference.143GV->setLinkage(GlobalValue::ExternalLinkage);144continue;145}146if (G.hasInitializer())147GV->setInitializer(MapValue(G.getInitializer(), VMap));148149copyComdat(GV, &G);150}151152// Similarly, copy over function bodies now...153//154for (const Function &I : M) {155Function *F = cast<Function>(VMap[&I]);156157if (I.isDeclaration()) {158// Copy over metadata for declarations since we're not doing it below in159// CloneFunctionInto().160SmallVector<std::pair<unsigned, MDNode *>, 1> MDs;161I.getAllMetadata(MDs);162for (auto MD : MDs)163F->addMetadata(MD.first, *MapMetadata(MD.second, VMap));164continue;165}166167if (!ShouldCloneDefinition(&I)) {168// Skip after setting the correct linkage for an external reference.169F->setLinkage(GlobalValue::ExternalLinkage);170// Personality function is not valid on a declaration.171F->setPersonalityFn(nullptr);172continue;173}174175Function::arg_iterator DestI = F->arg_begin();176for (const Argument &J : I.args()) {177DestI->setName(J.getName());178VMap[&J] = &*DestI++;179}180181SmallVector<ReturnInst *, 8> Returns; // Ignore returns cloned.182CloneFunctionInto(F, &I, VMap, CloneFunctionChangeType::ClonedModule,183Returns);184185if (I.hasPersonalityFn())186F->setPersonalityFn(MapValue(I.getPersonalityFn(), VMap));187188copyComdat(F, &I);189}190191// And aliases192for (const GlobalAlias &I : M.aliases()) {193// We already dealt with undefined aliases above.194if (!ShouldCloneDefinition(&I))195continue;196GlobalAlias *GA = cast<GlobalAlias>(VMap[&I]);197if (const Constant *C = I.getAliasee())198GA->setAliasee(MapValue(C, VMap));199}200201for (const GlobalIFunc &I : M.ifuncs()) {202GlobalIFunc *GI = cast<GlobalIFunc>(VMap[&I]);203if (const Constant *Resolver = I.getResolver())204GI->setResolver(MapValue(Resolver, VMap));205}206207// And named metadata....208for (const NamedMDNode &NMD : M.named_metadata()) {209NamedMDNode *NewNMD = New->getOrInsertNamedMetadata(NMD.getName());210for (const MDNode *N : NMD.operands())211NewNMD->addOperand(MapMetadata(N, VMap));212}213214return New;215}216217extern "C" {218219LLVMModuleRef LLVMCloneModule(LLVMModuleRef M) {220return wrap(CloneModule(*unwrap(M)).release());221}222223}224225226