diff --git a/llvm/lib/MC/MCParser/MasmParser.cpp b/llvm/lib/MC/MCParser/MasmParser.cpp --- a/llvm/lib/MC/MCParser/MasmParser.cpp +++ b/llvm/lib/MC/MCParser/MasmParser.cpp @@ -1585,6 +1585,16 @@ Res = MCUnaryExpr::createNot(Res, getContext(), FirstTokenLoc); return false; } + // Parse anonymous label references. + if (Identifier.equals_insensitive("@b") || + Identifier.equals_insensitive("@f")) { + bool Before = Identifier.equals_insensitive("@b"); + MCSymbol *Sym = getContext().getDirectionalLocalSymbol(-1, Before); + if (Before && Sym->isUndefined()) + return Error(FirstTokenLoc, "Expected @@ label before @B reference"); + Res = MCSymbolRefExpr::create(Sym, getContext()); + return false; + } // Parse symbol variant. std::pair Split; if (!MAI.useParensForSymbolVariant()) { @@ -2110,29 +2120,9 @@ AsmToken ID = getTok(); SMLoc IDLoc = ID.getLoc(); StringRef IDVal; - int64_t LocalLabelVal = -1; if (Lexer.is(AsmToken::HashDirective)) return parseCppHashLineFilenameComment(IDLoc); - // Allow an integer followed by a ':' as a directional local label. - if (Lexer.is(AsmToken::Integer)) { - LocalLabelVal = getTok().getIntVal(); - if (LocalLabelVal < 0) { - if (!TheCondState.Ignore) { - Lex(); // always eat a token - return Error(IDLoc, "unexpected token at start of statement"); - } - IDVal = ""; - } else { - IDVal = getTok().getString(); - Lex(); // Consume the integer token to be used as an identifier token. - if (Lexer.getKind() != AsmToken::Colon) { - if (!TheCondState.Ignore) { - Lex(); // always eat a token - return Error(IDLoc, "unexpected token at start of statement"); - } - } - } - } else if (Lexer.is(AsmToken::Dot)) { + if (Lexer.is(AsmToken::Dot)) { // Treat '.' as a valid identifier in this context. Lex(); IDVal = "."; @@ -2257,19 +2247,22 @@ // FIXME: This doesn't diagnose assignment to a symbol which has been // implicitly marked as external. MCSymbol *Sym; - if (LocalLabelVal == -1) { - if (ParsingMSInlineAsm && SI) { - StringRef RewrittenLabel = - SI->LookupInlineAsmLabel(IDVal, getSourceManager(), IDLoc, true); - assert(!RewrittenLabel.empty() && - "We should have an internal name here."); - Info.AsmRewrites->emplace_back(AOK_Label, IDLoc, IDVal.size(), - RewrittenLabel); - IDVal = RewrittenLabel; - } + if (ParsingMSInlineAsm && SI) { + StringRef RewrittenLabel = + SI->LookupInlineAsmLabel(IDVal, getSourceManager(), IDLoc, true); + assert(!RewrittenLabel.empty() && + "We should have an internal name here."); + Info.AsmRewrites->emplace_back(AOK_Label, IDLoc, IDVal.size(), + RewrittenLabel); + IDVal = RewrittenLabel; + } + // Rewrite anonymous labels + if (IDVal == "@@") { + Sym = Ctx.createDirectionalLocalSymbol(-1); + } else { Sym = getContext().getOrCreateSymbol(IDVal); - } else - Sym = Ctx.createDirectionalLocalSymbol(LocalLabelVal); + } + // End of Labels should be treated as end of line for lexing // purposes but that information is not available to the Lexer who // does not understand Labels. This may cause us to see a Hash diff --git a/llvm/test/tools/llvm-ml/anonymous_labels.asm b/llvm/test/tools/llvm-ml/anonymous_labels.asm new file mode 100644 --- /dev/null +++ b/llvm/test/tools/llvm-ml/anonymous_labels.asm @@ -0,0 +1,42 @@ +; RUN: llvm-ml -filetype=s %s /Fo - | FileCheck %s + +.code + +t1: + jmp @F + jmp @F +; CHECK-LABEL: t1: +; CHECK-NEXT: jmp [[TEMP1:[[:alpha:][:digit:]]+]] +; CHECK-NEXT: jmp [[TEMP1]] + +@@: + xor eax, eax +; CHECK: [[TEMP1]]: +; CHECK-NEXT: xor eax, eax + +t2: + jmp @B + jmp @B +; CHECK-LABEL: t2: +; CHECK-NEXT: jmp [[TEMP1]] +; CHECK-NEXT: jmp [[TEMP1]] + +t3: + jmp @F +; CHECK-LABEL: t3: +; CHECK-NEXT: jmp [[TEMP2:[[:alpha:][:digit:]]+]] + +@@: + xor eax, eax +; CHECK: [[TEMP2]]: +; CHECK-NEXT: xor eax, eax + +@@: + xor eax, eax +; CHECK: [[TEMP3:[[:alpha:][:digit:]]+]]: +; CHECK-NEXT: xor eax, eax + +t4: + jmp @B +; CHECK-LABEL: t4: +; CHECK-NEXT: jmp [[TEMP3]] diff --git a/llvm/test/tools/llvm-ml/anonymous_labels_errors.asm b/llvm/test/tools/llvm-ml/anonymous_labels_errors.asm new file mode 100644 --- /dev/null +++ b/llvm/test/tools/llvm-ml/anonymous_labels_errors.asm @@ -0,0 +1,16 @@ +; RUN: not llvm-ml -filetype=s %s /Fo - 2>&1 | FileCheck %s --implicit-check-not=error: + +.code + +; CHECK: :[[# @LINE + 2]]:5: error: Expected @@ label before @B reference +; CHECK: :[[# @LINE + 1]]:7: error: Unexpected identifier! +jmp @B + +@@: + jmp @B + jmp @F +@@: + xor eax, eax + +; NOTE: a trailing @F will not fail; fixing this seems to require two passes. +jmp @F