225 lines · cpp
1//===- CloneModule.cpp - Clone an entire module ---------------------------===//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 file implements the CloneModule interface which makes a copy of an10// entire module.11//12//===----------------------------------------------------------------------===//13 14#include "llvm-c/Core.h"15#include "llvm/IR/DerivedTypes.h"16#include "llvm/IR/Module.h"17#include "llvm/Transforms/Utils/Cloning.h"18#include "llvm/Transforms/Utils/ValueMapper.h"19using namespace llvm;20 21namespace llvm {22class Constant;23}24 25static void copyComdat(GlobalObject *Dst, const GlobalObject *Src) {26 const Comdat *SC = Src->getComdat();27 if (!SC)28 return;29 Comdat *DC = Dst->getParent()->getOrInsertComdat(SC->getName());30 DC->setSelectionKind(SC->getSelectionKind());31 Dst->setComdat(DC);32}33 34/// This is not as easy as it might seem because we have to worry about making35/// copies of global variables and functions, and making their (initializers and36/// references, respectively) refer to the right globals.37///38/// Cloning un-materialized modules is not currently supported, so any39/// modules initialized via lazy loading should be materialized before cloning40std::unique_ptr<Module> llvm::CloneModule(const Module &M) {41 // Create the value map that maps things from the old module over to the new42 // module.43 ValueToValueMapTy VMap;44 return CloneModule(M, VMap);45}46 47std::unique_ptr<Module> llvm::CloneModule(const Module &M,48 ValueToValueMapTy &VMap) {49 return CloneModule(M, VMap, [](const GlobalValue *GV) { return true; });50}51 52std::unique_ptr<Module> llvm::CloneModule(53 const Module &M, ValueToValueMapTy &VMap,54 function_ref<bool(const GlobalValue *)> ShouldCloneDefinition) {55 56 assert(M.isMaterialized() && "Module must be materialized before cloning!");57 58 // First off, we need to create the new module.59 std::unique_ptr<Module> New =60 std::make_unique<Module>(M.getModuleIdentifier(), M.getContext());61 New->setSourceFileName(M.getSourceFileName());62 New->setDataLayout(M.getDataLayout());63 New->setTargetTriple(M.getTargetTriple());64 New->setModuleInlineAsm(M.getModuleInlineAsm());65 66 // Loop over all of the global variables, making corresponding globals in the67 // new module. Here we add them to the VMap and to the new Module. We68 // don't worry about attributes or initializers, they will come later.69 //70 for (const GlobalVariable &I : M.globals()) {71 GlobalVariable *NewGV = new GlobalVariable(72 *New, I.getValueType(), I.isConstant(), I.getLinkage(),73 (Constant *)nullptr, I.getName(), (GlobalVariable *)nullptr,74 I.getThreadLocalMode(), I.getType()->getAddressSpace());75 NewGV->copyAttributesFrom(&I);76 VMap[&I] = NewGV;77 }78 79 // Loop over the functions in the module, making external functions as before80 for (const Function &I : M) {81 Function *NF =82 Function::Create(cast<FunctionType>(I.getValueType()), I.getLinkage(),83 I.getAddressSpace(), I.getName(), New.get());84 NF->copyAttributesFrom(&I);85 VMap[&I] = NF;86 }87 88 // Loop over the aliases in the module89 for (const GlobalAlias &I : M.aliases()) {90 if (!ShouldCloneDefinition(&I)) {91 // An alias cannot act as an external reference, so we need to create92 // either a function or a global variable depending on the value type.93 // FIXME: Once pointee types are gone we can probably pick one or the94 // other.95 GlobalValue *GV;96 if (I.getValueType()->isFunctionTy())97 GV = Function::Create(cast<FunctionType>(I.getValueType()),98 GlobalValue::ExternalLinkage, I.getAddressSpace(),99 I.getName(), New.get());100 else101 GV = new GlobalVariable(*New, I.getValueType(), false,102 GlobalValue::ExternalLinkage, nullptr,103 I.getName(), nullptr, I.getThreadLocalMode(),104 I.getType()->getAddressSpace());105 VMap[&I] = GV;106 // We do not copy attributes (mainly because copying between different107 // kinds of globals is forbidden), but this is generally not required for108 // correctness.109 continue;110 }111 auto *GA = GlobalAlias::create(I.getValueType(),112 I.getType()->getPointerAddressSpace(),113 I.getLinkage(), I.getName(), New.get());114 GA->copyAttributesFrom(&I);115 VMap[&I] = GA;116 }117 118 for (const GlobalIFunc &I : M.ifuncs()) {119 // Defer setting the resolver function until after functions are cloned.120 auto *GI =121 GlobalIFunc::create(I.getValueType(), I.getAddressSpace(),122 I.getLinkage(), I.getName(), nullptr, New.get());123 GI->copyAttributesFrom(&I);124 VMap[&I] = GI;125 }126 127 // Similarly, copy over function bodies now...128 //129 for (const Function &I : M) {130 Function *F = cast<Function>(VMap[&I]);131 132 if (I.isDeclaration()) {133 // Copy over metadata for declarations since we're not doing it below in134 // CloneFunctionInto().135 SmallVector<std::pair<unsigned, MDNode *>, 1> MDs;136 I.getAllMetadata(MDs);137 for (auto MD : MDs)138 F->addMetadata(MD.first, *MapMetadata(MD.second, VMap));139 continue;140 }141 142 if (!ShouldCloneDefinition(&I)) {143 // Skip after setting the correct linkage for an external reference.144 F->setLinkage(GlobalValue::ExternalLinkage);145 // Personality function is not valid on a declaration.146 F->setPersonalityFn(nullptr);147 continue;148 }149 150 Function::arg_iterator DestI = F->arg_begin();151 for (const Argument &J : I.args()) {152 DestI->setName(J.getName());153 VMap[&J] = &*DestI++;154 }155 156 SmallVector<ReturnInst *, 8> Returns; // Ignore returns cloned.157 CloneFunctionInto(F, &I, VMap, CloneFunctionChangeType::ClonedModule,158 Returns);159 160 if (I.hasPersonalityFn())161 F->setPersonalityFn(MapValue(I.getPersonalityFn(), VMap));162 163 copyComdat(F, &I);164 }165 166 // And aliases167 for (const GlobalAlias &I : M.aliases()) {168 // We already dealt with undefined aliases above.169 if (!ShouldCloneDefinition(&I))170 continue;171 GlobalAlias *GA = cast<GlobalAlias>(VMap[&I]);172 if (const Constant *C = I.getAliasee())173 GA->setAliasee(MapValue(C, VMap));174 }175 176 for (const GlobalIFunc &I : M.ifuncs()) {177 GlobalIFunc *GI = cast<GlobalIFunc>(VMap[&I]);178 if (const Constant *Resolver = I.getResolver())179 GI->setResolver(MapValue(Resolver, VMap));180 }181 182 // And named metadata....183 for (const NamedMDNode &NMD : M.named_metadata()) {184 NamedMDNode *NewNMD = New->getOrInsertNamedMetadata(NMD.getName());185 for (const MDNode *N : NMD.operands())186 NewNMD->addOperand(MapMetadata(N, VMap));187 }188 189 // Now that all of the things that global variable initializer can refer to190 // have been created, loop through and copy the global variable referrers191 // over... We also set the attributes on the global now.192 //193 for (const GlobalVariable &G : M.globals()) {194 GlobalVariable *GV = cast<GlobalVariable>(VMap[&G]);195 196 SmallVector<std::pair<unsigned, MDNode *>, 1> MDs;197 G.getAllMetadata(MDs);198 for (auto MD : MDs)199 GV->addMetadata(MD.first, *MapMetadata(MD.second, VMap));200 201 if (G.isDeclaration())202 continue;203 204 if (!ShouldCloneDefinition(&G)) {205 // Skip after setting the correct linkage for an external reference.206 GV->setLinkage(GlobalValue::ExternalLinkage);207 continue;208 }209 if (G.hasInitializer())210 GV->setInitializer(MapValue(G.getInitializer(), VMap));211 212 copyComdat(GV, &G);213 }214 215 return New;216}217 218extern "C" {219 220LLVMModuleRef LLVMCloneModule(LLVMModuleRef M) {221 return wrap(CloneModule(*unwrap(M)).release());222}223 224}225