Skip to content

Commit f7f0fd4

Browse files
lhameszmodem
authored andcommitted
[ORC] Add weak symbol support to defineMaterializing, fix for PR40074.
The MaterializationResponsibility::defineMaterializing method allows clients to add new definitions that are in the process of being materialized to the JIT. This patch adds support to defineMaterializing for symbols with weak linkage where the new definitions may be rejected if another materializer concurrently defines the same symbol. If a weak symbol is rejected it will not be added to the MaterializationResponsibility's responsibility set. Clients can check for membership in the responsibility set via the MaterializationResponsibility::getSymbols() method before resolving any such weak symbols. This patch also adds code to RTDyldObjectLinkingLayer to tag COFF comdat symbols introduced during codegen as weak, on the assumption that these are COFF comdat constants. This fixes http://llvm.org/PR40074. (cherry picked from commit 84217ad)
1 parent 52c1d20 commit f7f0fd4

File tree

4 files changed

+105
-32
lines changed

4 files changed

+105
-32
lines changed

llvm/include/llvm/ExecutionEngine/Orc/Core.h

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -489,13 +489,18 @@ class MaterializationResponsibility {
489489
/// is guaranteed to return Error::success() and can be wrapped with cantFail.
490490
Error notifyEmitted();
491491

492-
/// Adds new symbols to the JITDylib and this responsibility instance.
493-
/// JITDylib entries start out in the materializing state.
492+
/// Attempt to claim responsibility for new definitions. This method can be
493+
/// used to claim responsibility for symbols that are added to a
494+
/// materialization unit during the compilation process (e.g. literal pool
495+
/// symbols). Symbol linkage rules are the same as for symbols that are
496+
/// defined up front: duplicate strong definitions will result in errors.
497+
/// Duplicate weak definitions will be discarded (in which case they will
498+
/// not be added to this responsibility instance).
494499
///
495500
/// This method can be used by materialization units that want to add
496501
/// additional symbols at materialization time (e.g. stubs, compile
497502
/// callbacks, metadata).
498-
Error defineMaterializing(const SymbolFlagsMap &SymbolFlags);
503+
Error defineMaterializing(SymbolFlagsMap SymbolFlags);
499504

500505
/// Notify all not-yet-emitted covered by this MaterializationResponsibility
501506
/// instance that an error has occurred.
@@ -1023,7 +1028,7 @@ class JITDylib {
10231028
const SymbolStringPtr &DependantName,
10241029
MaterializingInfo &EmittedMI);
10251030

1026-
Error defineMaterializing(const SymbolFlagsMap &SymbolFlags);
1031+
Expected<SymbolFlagsMap> defineMaterializing(SymbolFlagsMap SymbolFlags);
10271032

10281033
void replace(std::unique_ptr<MaterializationUnit> MU);
10291034

llvm/lib/ExecutionEngine/Orc/Core.cpp

Lines changed: 51 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -468,15 +468,19 @@ Error MaterializationResponsibility::notifyEmitted() {
468468
}
469469

470470
Error MaterializationResponsibility::defineMaterializing(
471-
const SymbolFlagsMap &NewSymbolFlags) {
472-
// Add the given symbols to this responsibility object.
473-
// It's ok if we hit a duplicate here: In that case the new version will be
474-
// discarded, and the JITDylib::defineMaterializing method will return a
475-
// duplicate symbol error.
476-
for (auto &KV : NewSymbolFlags)
477-
SymbolFlags.insert(KV);
471+
SymbolFlagsMap NewSymbolFlags) {
478472

479-
return JD.defineMaterializing(NewSymbolFlags);
473+
LLVM_DEBUG({
474+
dbgs() << "In " << JD.getName() << " defining materializing symbols "
475+
<< NewSymbolFlags << "\n";
476+
});
477+
if (auto AcceptedDefs = JD.defineMaterializing(std::move(NewSymbolFlags))) {
478+
// Add all newly accepted symbols to this responsibility object.
479+
for (auto &KV : *AcceptedDefs)
480+
SymbolFlags.insert(KV);
481+
return Error::success();
482+
} else
483+
return AcceptedDefs.takeError();
480484
}
481485

482486
void MaterializationResponsibility::failMaterialization() {
@@ -809,31 +813,52 @@ void JITDylib::removeGenerator(DefinitionGenerator &G) {
809813
});
810814
}
811815

812-
Error JITDylib::defineMaterializing(const SymbolFlagsMap &SymbolFlags) {
813-
return ES.runSessionLocked([&]() -> Error {
816+
Expected<SymbolFlagsMap>
817+
JITDylib::defineMaterializing(SymbolFlagsMap SymbolFlags) {
818+
819+
return ES.runSessionLocked([&]() -> Expected<SymbolFlagsMap> {
814820
std::vector<SymbolTable::iterator> AddedSyms;
821+
std::vector<SymbolFlagsMap::iterator> RejectedWeakDefs;
815822

816-
for (auto &KV : SymbolFlags) {
817-
SymbolTable::iterator EntryItr;
818-
bool Added;
823+
for (auto SFItr = SymbolFlags.begin(), SFEnd = SymbolFlags.end();
824+
SFItr != SFEnd; ++SFItr) {
819825

820-
std::tie(EntryItr, Added) =
821-
Symbols.insert(std::make_pair(KV.first, SymbolTableEntry(KV.second)));
826+
auto &Name = SFItr->first;
827+
auto &Flags = SFItr->second;
822828

823-
if (Added) {
824-
AddedSyms.push_back(EntryItr);
825-
EntryItr->second.setState(SymbolState::Materializing);
826-
} else {
827-
// Remove any symbols already added.
828-
for (auto &SI : AddedSyms)
829-
Symbols.erase(SI);
829+
auto EntryItr = Symbols.find(Name);
830830

831-
// FIXME: Return all duplicates.
832-
return make_error<DuplicateDefinition>(*KV.first);
833-
}
831+
// If the entry already exists...
832+
if (EntryItr != Symbols.end()) {
833+
834+
// If this is a strong definition then error out.
835+
if (!Flags.isWeak()) {
836+
// Remove any symbols already added.
837+
for (auto &SI : AddedSyms)
838+
Symbols.erase(SI);
839+
840+
// FIXME: Return all duplicates.
841+
return make_error<DuplicateDefinition>(*Name);
842+
}
843+
844+
// Otherwise just make a note to discard this symbol after the loop.
845+
RejectedWeakDefs.push_back(SFItr);
846+
continue;
847+
} else
848+
EntryItr =
849+
Symbols.insert(std::make_pair(Name, SymbolTableEntry(Flags))).first;
850+
851+
AddedSyms.push_back(EntryItr);
852+
EntryItr->second.setState(SymbolState::Materializing);
834853
}
835854

836-
return Error::success();
855+
// Remove any rejected weak definitions from the SymbolFlags map.
856+
while (!RejectedWeakDefs.empty()) {
857+
SymbolFlags.erase(RejectedWeakDefs.back());
858+
RejectedWeakDefs.pop_back();
859+
}
860+
861+
return SymbolFlags;
837862
});
838863
}
839864

llvm/lib/ExecutionEngine/Orc/LLJIT.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,8 +96,10 @@ LLJIT::createObjectLinkingLayer(LLJITBuilderState &S, ExecutionSession &ES) {
9696
auto ObjLinkingLayer =
9797
std::make_unique<RTDyldObjectLinkingLayer>(ES, std::move(GetMemMgr));
9898

99-
if (S.JTMB->getTargetTriple().isOSBinFormatCOFF())
99+
if (S.JTMB->getTargetTriple().isOSBinFormatCOFF()) {
100100
ObjLinkingLayer->setOverrideObjectFlagsWithResponsibilityFlags(true);
101+
ObjLinkingLayer->setAutoClaimResponsibilityForObjectSymbols(true);
102+
}
101103

102104
// FIXME: Explicit conversion to std::unique_ptr<ObjectLayer> added to silence
103105
// errors from some GCC / libstdc++ bots. Remove this conversion (i.e.

llvm/lib/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.cpp

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
//===----------------------------------------------------------------------===//
88

99
#include "llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h"
10+
#include "llvm/Object/COFF.h"
1011

1112
namespace {
1213

@@ -160,6 +161,39 @@ Error RTDyldObjectLinkingLayer::onObjLoad(
160161
std::set<StringRef> &InternalSymbols) {
161162
SymbolFlagsMap ExtraSymbolsToClaim;
162163
SymbolMap Symbols;
164+
165+
// Hack to support COFF constant pool comdats introduced during compilation:
166+
// (See http://llvm.org/PR40074)
167+
if (auto *COFFObj = dyn_cast<object::COFFObjectFile>(&Obj)) {
168+
auto &ES = getExecutionSession();
169+
170+
// For all resolved symbols that are not already in the responsibilty set:
171+
// check whether the symbol is in a comdat section and if so mark it as
172+
// weak.
173+
for (auto &Sym : COFFObj->symbols()) {
174+
if (Sym.getFlags() & object::BasicSymbolRef::SF_Undefined)
175+
continue;
176+
auto Name = Sym.getName();
177+
if (!Name)
178+
return Name.takeError();
179+
auto I = Resolved.find(*Name);
180+
181+
// Skip unresolved symbols, internal symbols, and symbols that are
182+
// already in the responsibility set.
183+
if (I == Resolved.end() || InternalSymbols.count(*Name) ||
184+
R.getSymbols().count(ES.intern(*Name)))
185+
continue;
186+
auto Sec = Sym.getSection();
187+
if (!Sec)
188+
return Sec.takeError();
189+
if (*Sec == COFFObj->section_end())
190+
continue;
191+
auto &COFFSec = *COFFObj->getCOFFSection(**Sec);
192+
if (COFFSec.Characteristics & COFF::IMAGE_SCN_LNK_COMDAT)
193+
I->second.setFlags(I->second.getFlags() | JITSymbolFlags::Weak);
194+
}
195+
}
196+
163197
for (auto &KV : Resolved) {
164198
// Scan the symbols and add them to the Symbols map for resolution.
165199

@@ -184,10 +218,17 @@ Error RTDyldObjectLinkingLayer::onObjLoad(
184218
Symbols[InternedName] = JITEvaluatedSymbol(KV.second.getAddress(), Flags);
185219
}
186220

187-
if (!ExtraSymbolsToClaim.empty())
221+
if (!ExtraSymbolsToClaim.empty()) {
188222
if (auto Err = R.defineMaterializing(ExtraSymbolsToClaim))
189223
return Err;
190224

225+
// If we claimed responsibility for any weak symbols but were rejected then
226+
// we need to remove them from the resolved set.
227+
for (auto &KV : ExtraSymbolsToClaim)
228+
if (KV.second.isWeak() && !R.getSymbols().count(KV.first))
229+
Symbols.erase(KV.first);
230+
}
231+
191232
if (auto Err = R.notifyResolved(Symbols)) {
192233
R.failMaterialization();
193234
return Err;

0 commit comments

Comments
 (0)