diff --git a/llvm/lib/ExecutionEngine/Orc/Layer.cpp b/llvm/lib/ExecutionEngine/Orc/Layer.cpp --- a/llvm/lib/ExecutionEngine/Orc/Layer.cpp +++ b/llvm/lib/ExecutionEngine/Orc/Layer.cpp @@ -77,6 +77,9 @@ // Otherwise we just need a normal linker mangling. auto MangledName = Mangle(G.getName()); SymbolFlags[MangledName] = JITSymbolFlags::fromGlobalValue(G); + if (G.getComdat() && + G.getComdat()->getSelectionKind() != Comdat::NoDeduplicate) + SymbolFlags[MangledName] |= JITSymbolFlags::Weak; SymbolToDefinition[MangledName] = &G; } diff --git a/llvm/lib/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.cpp b/llvm/lib/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.cpp --- a/llvm/lib/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.cpp +++ b/llvm/lib/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.cpp @@ -259,6 +259,46 @@ if (COFFSec.Characteristics & COFF::IMAGE_SCN_LNK_COMDAT) I->second.setFlags(I->second.getFlags() | JITSymbolFlags::Weak); } + + // Handle any aliases. + for (auto &Sym : COFFObj->symbols()) { + uint32_t SymFlags = cantFail(Sym.getFlags()); + if (SymFlags & object::BasicSymbolRef::SF_Undefined) + continue; + auto Name = Sym.getName(); + if (!Name) + return Name.takeError(); + auto I = Resolved.find(*Name); + + // Skip already-resolved symbols, and symbols that we're not responsible + // for. + if (I != Resolved.end() || !R.getSymbols().count(ES.intern(*Name))) + continue; + + // Skip anything other than weak externals. + auto COFFSym = COFFObj->getCOFFSymbol(Sym); + if (!COFFSym.isWeakExternal()) + continue; + auto *WeakExternal = COFFSym.getAux(); + if (WeakExternal->Characteristics != COFF::IMAGE_WEAK_EXTERN_SEARCH_ALIAS) + continue; + + // We found an alias. Reuse the resolution of the alias target for the + // alias itself. + Expected TargetSymbol = + COFFObj->getSymbol(WeakExternal->TagIndex); + if (!TargetSymbol) + return TargetSymbol.takeError(); + Expected TargetName = COFFObj->getSymbolName(*TargetSymbol); + if (!TargetName) + return TargetName.takeError(); + auto J = Resolved.find(*TargetName); + if (J == Resolved.end()) + return make_error("Could alias target " + *TargetName + + " not resolved", + inconvertibleErrorCode()); + Resolved[*Name] = J->second; + } } for (auto &KV : Resolved) { diff --git a/llvm/test/ExecutionEngine/OrcLazy/Inputs/comdat-functions.ll b/llvm/test/ExecutionEngine/OrcLazy/Inputs/comdat-functions.ll new file mode 100644 --- /dev/null +++ b/llvm/test/ExecutionEngine/OrcLazy/Inputs/comdat-functions.ll @@ -0,0 +1,6 @@ +$baz = comdat any + +define i32 @baz() comdat { +entry: + ret i32 0 +} diff --git a/llvm/test/ExecutionEngine/OrcLazy/comdat-functions.ll b/llvm/test/ExecutionEngine/OrcLazy/comdat-functions.ll new file mode 100644 --- /dev/null +++ b/llvm/test/ExecutionEngine/OrcLazy/comdat-functions.ll @@ -0,0 +1,16 @@ +; REQUIRES: system-windows +; RUN: lli -jit-kind=orc-lazy -extra-module %p/Inputs/comdat-functions.ll %s +; Check if crashing comdat any functions are not causing duplicate symbol error. + +$baz = comdat any + +define i32 @baz() comdat { +entry: + ret i32 0 +} + +define i32 @main(i32 %argc, i8** %argv) { +entry: + %call = tail call i32 @baz() + ret i32 %call +}