[ORC] Add optional context string to duplicate symbol definition errors.

The context string can be added to indicate the source of the duplicate
definition. E.g. if the context is set to "foo2.o", then:

"Duplicate definition of symbol 'foo'"

becomes

"In foo2.o, duplicate definition of symbol 'foo'".

The JITDylib::defineImpl method is updated to use the name of the
MaterializationUnit being added as the context string for duplicate definition
errors. The JITDylib::defineMaterializing method is updated to use
"defineMaterializing operation" as the conext string.
This commit is contained in:
Lang Hames
2025-05-09 17:06:36 +10:00
parent 60b62c65bd
commit b0979b8c65
5 changed files with 32 additions and 6 deletions

View File

@@ -48,12 +48,16 @@ class DuplicateDefinition : public ErrorInfo<DuplicateDefinition> {
public:
static char ID;
DuplicateDefinition(std::string SymbolName);
DuplicateDefinition(std::string SymbolName,
std::optional<std::string> Context = {});
std::error_code convertToErrorCode() const override;
void log(raw_ostream &OS) const override;
const std::string &getSymbolName() const;
const std::optional<std::string> &getContext() const;
private:
std::string SymbolName;
std::optional<std::string> Context;
};
class JITSymbolNotFound : public ErrorInfo<JITSymbolNotFound> {

View File

@@ -731,7 +731,8 @@ JITDylib::defineMaterializing(MaterializationResponsibility &FromMR,
Symbols.erase(Symbols.find_as(S));
// FIXME: Return all duplicates.
return make_error<DuplicateDefinition>(std::string(*Name));
return make_error<DuplicateDefinition>(
std::string(*Name), "defineMaterializing operation");
}
// Otherwise just make a note to discard this symbol after the loop.
@@ -1424,7 +1425,8 @@ Error JITDylib::defineImpl(MaterializationUnit &MU) {
if (!Duplicates.empty()) {
LLVM_DEBUG(
{ dbgs() << " Error: Duplicate symbols " << Duplicates << "\n"; });
return make_error<DuplicateDefinition>(std::string(**Duplicates.begin()));
return make_error<DuplicateDefinition>(std::string(**Duplicates.begin()),
MU.getName().str());
}
// Discard any overridden defs in this MU.

View File

@@ -86,21 +86,28 @@ std::error_code orcError(OrcErrorCode ErrCode) {
return std::error_code(static_cast<UT>(ErrCode), getOrcErrCat());
}
DuplicateDefinition::DuplicateDefinition(std::string SymbolName)
: SymbolName(std::move(SymbolName)) {}
DuplicateDefinition::DuplicateDefinition(std::string SymbolName,
std::optional<std::string> Context)
: SymbolName(std::move(SymbolName)), Context(std::move(Context)) {}
std::error_code DuplicateDefinition::convertToErrorCode() const {
return orcError(OrcErrorCode::DuplicateDefinition);
}
void DuplicateDefinition::log(raw_ostream &OS) const {
OS << "Duplicate definition of symbol '" << SymbolName << "'";
if (Context)
OS << "In " << *Context << ", ";
OS << "duplicate definition of symbol '" << SymbolName << "'";
}
const std::string &DuplicateDefinition::getSymbolName() const {
return SymbolName;
}
const std::optional<std::string> &DuplicateDefinition::getContext() const {
return Context;
}
JITSymbolNotFound::JITSymbolNotFound(std::string SymbolName)
: SymbolName(std::move(SymbolName)) {}

View File

@@ -0,0 +1,4 @@
define i32 @main(i32 %argc, i8** %argv) {
entry:
ret i32 42
}

View File

@@ -0,0 +1,9 @@
# RUN: rm -rf %t && mkdir %t
# RUN: llc -filetype=obj -o %t/main-ret-0.o %S/Inputs/main-ret-0.ll
# RUN: llc -filetype=obj -o %T/main-ret-42.o %S/Inputs/main-ret-42.ll
# RUN: not llvm-jitlink -noexec %T/main-ret-0.o %T/main-ret-42.o 2>&1 | FileCheck %s
#
# Trigger a duplicate definition error by trying to link two main functions,
# check that the error message includes the file that introduced the duplicate.
#
# CHECK: In {{.*}}main-ret-42.o, duplicate definition of {{.*}}main