MCParser: diagnose missing directional labels more clearly.

Before, ELF at least managed a diagnostic but it was a completely untraceable
"undefined symbol" error. MachO had a variety of even worse behaviours: crash,
emit corrupt file, or an equally bad message.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@265984 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Tim Northover 2016-04-11 19:50:46 +00:00
parent 09e9ded8a1
commit 77e5760b43
5 changed files with 45 additions and 19 deletions

View File

@ -146,6 +146,9 @@ private:
/// \brief List of bodies of anonymous macros.
std::deque<MCAsmMacro> MacroLikeBodies;
/// \brief List of forward directional labels for diagnosis at the end.
SmallVector<std::pair<SMLoc, MCSymbol *>, 4> DirectionalLabels;
/// Boolean tracking whether macro substitution is enabled.
unsigned MacrosEnabledFlag : 1;
@ -696,18 +699,28 @@ bool AsmParser::Run(bool NoInitialTextSection, bool NoFinalize) {
// Targets that don't do subsections via symbols may not want this, though,
// so conservatively exclude them. Only do this if we're finalizing, though,
// as otherwise we won't necessarilly have seen everything yet.
if (!NoFinalize && MAI.hasSubsectionsViaSymbols()) {
for (const auto &TableEntry : getContext().getSymbols()) {
MCSymbol *Sym = TableEntry.getValue();
// Variable symbols may not be marked as defined, so check those
// explicitly. If we know it's a variable, we have a definition for
// the purposes of this check.
if (Sym->isTemporary() && !Sym->isVariable() && !Sym->isDefined())
// FIXME: We would really like to refer back to where the symbol was
// first referenced for a source location. We need to add something
// to track that. Currently, we just point to the end of the file.
return Error(getLexer().getLoc(), "assembler local symbol '" +
Sym->getName() + "' not defined");
if (!NoFinalize) {
if (MAI.hasSubsectionsViaSymbols()) {
for (const auto &TableEntry : getContext().getSymbols()) {
MCSymbol *Sym = TableEntry.getValue();
// Variable symbols may not be marked as defined, so check those
// explicitly. If we know it's a variable, we have a definition for
// the purposes of this check.
if (Sym->isTemporary() && !Sym->isVariable() && !Sym->isDefined())
// FIXME: We would really like to refer back to where the symbol was
// first referenced for a source location. We need to add something
// to track that. Currently, we just point to the end of the file.
HadError |=
Error(getLexer().getLoc(), "assembler local symbol '" +
Sym->getName() + "' not defined");
}
}
// Temporary symbols like the ones for directional jumps don't go in the
// symbol table. They also need to be diagnosed in all (final) cases.
for (std::pair<SMLoc, MCSymbol *> &LocSym : DirectionalLabels) {
if (LocSym.second->isUndefined())
HadError |= Error(LocSym.first, "directional label undefined");
}
}
@ -917,7 +930,8 @@ bool AsmParser::parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) {
Ctx.getDirectionalLocalSymbol(IntVal, IDVal == "b");
Res = MCSymbolRefExpr::create(Sym, Variant, getContext());
if (IDVal == "b" && Sym->isUndefined())
return Error(Loc, "invalid reference to undefined symbol");
return Error(Loc, "directional label undefined");
DirectionalLabels.push_back(std::make_pair(Loc, Sym));
EndLoc = Lexer.getTok().getEndLoc();
Lex(); // Eat identifier.
}

View File

@ -41,9 +41,6 @@
// CHECK: <unknown>:0: error: Common symbol 'common' cannot be used in assignment expr
.set v3, common
// CHECK: <unknown>:0: error: Undefined temporary symbol
.word 5f
// CHECK: <unknown>:0: error: symbol 'undef' could not be evaluated in a subtraction expression
.set v2, a-undef

View File

@ -23,9 +23,6 @@
@ CHECK: <unknown>:0: error: Common symbol 'common' cannot be used in assignment expr
.set v3, common
@ CHECK: <unknown>:0: error: Undefined temporary symbol
.word 5f
@ CHECK: <unknown>:0: error: symbol 'undef' could not be evaluated in a subtraction expression
.set v2, a-undef

View File

@ -0,0 +1,9 @@
// RUN: not llvm-mc -triple x86_64-linux-gnu -filetype=obj -o /dev/null %s 2>&1 | FileCheck %s
// CHECK: [[@LINE+1]]:{{[0-9]+}}: error: directional label undefined
jmp 1b
// CHECK: [[@LINE+1]]:{{[0-9]+}}: error: directional label undefined
jmp 1f
// CHECK: [[@LINE+1]]:{{[0-9]+}}: error: directional label undefined
jmp 2f

View File

@ -0,0 +1,9 @@
// RUN: not llvm-mc -triple x86_64-apple-macosx -filetype=obj -o /dev/null %s 2>&1 | FileCheck %s
// CHECK: [[@LINE+1]]:{{[0-9]+}}: error: directional label undefined
jmp 1b
// CHECK: [[@LINE+1]]:{{[0-9]+}}: error: directional label undefined
jmp 1f
// CHECK: [[@LINE+1]]:{{[0-9]+}}: error: directional label undefined
jmp 2f