aboutsummaryrefslogtreecommitdiff
path: root/lib/Linker/IRMover.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Linker/IRMover.cpp')
-rw-r--r--lib/Linker/IRMover.cpp74
1 files changed, 62 insertions, 12 deletions
diff --git a/lib/Linker/IRMover.cpp b/lib/Linker/IRMover.cpp
index afbc57abfcc0..37515d93ed50 100644
--- a/lib/Linker/IRMover.cpp
+++ b/lib/Linker/IRMover.cpp
@@ -1,9 +1,8 @@
//===- lib/Linker/IRMover.cpp ---------------------------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
@@ -403,6 +402,7 @@ class IRLinker {
DenseSet<GlobalValue *> ValuesToLink;
std::vector<GlobalValue *> Worklist;
+ std::vector<std::pair<GlobalValue *, Value*>> RAUWWorklist;
void maybeAdd(GlobalValue *GV) {
if (ValuesToLink.insert(GV).second)
@@ -489,12 +489,24 @@ class IRLinker {
void linkAliasBody(GlobalAlias &Dst, GlobalAlias &Src);
Error linkGlobalValueBody(GlobalValue &Dst, GlobalValue &Src);
+ /// Replace all types in the source AttributeList with the
+ /// corresponding destination type.
+ AttributeList mapAttributeTypes(LLVMContext &C, AttributeList Attrs);
+
/// Functions that take care of cloning a specific global value type
/// into the destination module.
GlobalVariable *copyGlobalVariableProto(const GlobalVariable *SGVar);
Function *copyFunctionProto(const Function *SF);
GlobalValue *copyGlobalAliasProto(const GlobalAlias *SGA);
+ /// Perform "replace all uses with" operations. These work items need to be
+ /// performed as part of materialization, but we postpone them to happen after
+ /// materialization is done. The materializer called by ValueMapper is not
+ /// expected to delete constants, as ValueMapper is holding pointers to some
+ /// of them, but constant destruction may be indirectly triggered by RAUW.
+ /// Hence, the need to move this out of the materialization call chain.
+ void flushRAUWWorklist();
+
/// When importing for ThinLTO, prevent importing of types listed on
/// the DICompileUnit that we don't need a copy of in the importing
/// module.
@@ -620,6 +632,21 @@ GlobalVariable *IRLinker::copyGlobalVariableProto(const GlobalVariable *SGVar) {
return NewDGV;
}
+AttributeList IRLinker::mapAttributeTypes(LLVMContext &C, AttributeList Attrs) {
+ for (unsigned i = 0; i < Attrs.getNumAttrSets(); ++i) {
+ if (Attrs.hasAttribute(i, Attribute::ByVal)) {
+ Type *Ty = Attrs.getAttribute(i, Attribute::ByVal).getValueAsType();
+ if (!Ty)
+ continue;
+
+ Attrs = Attrs.removeAttribute(C, i, Attribute::ByVal);
+ Attrs = Attrs.addAttribute(
+ C, i, Attribute::getWithByValType(C, TypeMap.get(Ty)));
+ }
+ }
+ return Attrs;
+}
+
/// Link the function in the source module into the destination module if
/// needed, setting up mapping information.
Function *IRLinker::copyFunctionProto(const Function *SF) {
@@ -629,6 +656,7 @@ Function *IRLinker::copyFunctionProto(const Function *SF) {
Function::Create(TypeMap.get(SF->getFunctionType()),
GlobalValue::ExternalLinkage, SF->getName(), &DstM);
F->copyAttributesFrom(SF);
+ F->setAttributes(mapAttributeTypes(F->getContext(), F->getAttributes()));
return F;
}
@@ -884,8 +912,8 @@ IRLinker::linkAppendingVarProto(GlobalVariable *DstGV,
// Replace any uses of the two global variables with uses of the new
// global.
if (DstGV) {
- DstGV->replaceAllUsesWith(ConstantExpr::getBitCast(NG, DstGV->getType()));
- DstGV->eraseFromParent();
+ RAUWWorklist.push_back(
+ std::make_pair(DstGV, ConstantExpr::getBitCast(NG, DstGV->getType())));
}
return Ret;
@@ -984,9 +1012,12 @@ Expected<Constant *> IRLinker::linkGlobalValueProto(GlobalValue *SGV,
}
if (DGV && NewGV != DGV) {
- DGV->replaceAllUsesWith(
- ConstantExpr::getPointerBitCastOrAddrSpaceCast(NewGV, DGV->getType()));
- DGV->eraseFromParent();
+ // Schedule "replace all uses with" to happen after materializing is
+ // done. It is not safe to do it now, since ValueMapper may be holding
+ // pointers to constants that will get deleted if RAUW runs.
+ RAUWWorklist.push_back(std::make_pair(
+ DGV,
+ ConstantExpr::getPointerBitCastOrAddrSpaceCast(NewGV, DGV->getType())));
}
return C;
@@ -1044,6 +1075,18 @@ Error IRLinker::linkGlobalValueBody(GlobalValue &Dst, GlobalValue &Src) {
return Error::success();
}
+void IRLinker::flushRAUWWorklist() {
+ for (const auto Elem : RAUWWorklist) {
+ GlobalValue *Old;
+ Value *New;
+ std::tie(Old, New) = Elem;
+
+ Old->replaceAllUsesWith(New);
+ Old->eraseFromParent();
+ }
+ RAUWWorklist.clear();
+}
+
void IRLinker::prepareCompileUnitsForImport() {
NamedMDNode *SrcCompileUnits = SrcM->getNamedMetadata("llvm.dbg.cu");
if (!SrcCompileUnits)
@@ -1200,7 +1243,9 @@ Error IRLinker::linkModuleFlagsMetadata() {
if (SrcBehaviorValue == Module::Override &&
SrcOp->getOperand(2) != DstOp->getOperand(2))
return stringErr("linking module flags '" + ID->getString() +
- "': IDs have conflicting override values");
+ "': IDs have conflicting override values in '" +
+ SrcM->getModuleIdentifier() + "' and '" +
+ DstM.getModuleIdentifier() + "'");
continue;
} else if (SrcBehaviorValue == Module::Override) {
// Update the destination flag to that of the source.
@@ -1211,7 +1256,9 @@ Error IRLinker::linkModuleFlagsMetadata() {
// Diagnose inconsistent merge behavior types.
if (SrcBehaviorValue != DstBehaviorValue)
return stringErr("linking module flags '" + ID->getString() +
- "': IDs have conflicting behaviors");
+ "': IDs have conflicting behaviors in '" +
+ SrcM->getModuleIdentifier() + "' and '" +
+ DstM.getModuleIdentifier() + "'");
auto replaceDstValue = [&](MDNode *New) {
Metadata *FlagOps[] = {DstOp->getOperand(0), ID, New};
@@ -1229,7 +1276,9 @@ Error IRLinker::linkModuleFlagsMetadata() {
// Emit an error if the values differ.
if (SrcOp->getOperand(2) != DstOp->getOperand(2))
return stringErr("linking module flags '" + ID->getString() +
- "': IDs have conflicting values");
+ "': IDs have conflicting values in '" +
+ SrcM->getModuleIdentifier() + "' and '" +
+ DstM.getModuleIdentifier() + "'");
continue;
}
case Module::Warning: {
@@ -1369,6 +1418,7 @@ Error IRLinker::run() {
Mapper.mapValue(*GV);
if (FoundError)
return std::move(*FoundError);
+ flushRAUWWorklist();
}
// Note that we are done linking global value bodies. This prevents