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 directional local label references. + if (Identifier.equals_insensitive("@b") || + Identifier.equals_insensitive("@f")) { + bool Before = Identifier.equals_insensitive("@b"); + MCSymbol *Sym = getContext().getDirectionalLocalSymbol(0, 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()) { @@ -1714,34 +1724,10 @@ case AsmToken::BigNum: return TokError("literal value out of range for directive"); case AsmToken::Integer: { - SMLoc Loc = getTok().getLoc(); int64_t IntVal = getTok().getIntVal(); Res = MCConstantExpr::create(IntVal, getContext()); EndLoc = Lexer.getTok().getEndLoc(); Lex(); // Eat token. - // Look for 'b' or 'f' following an Integer as a directional label. - if (Lexer.getKind() == AsmToken::Identifier) { - StringRef IDVal = getTok().getString(); - // Look up the symbol variant if used. - std::pair Split = IDVal.split('@'); - MCSymbolRefExpr::VariantKind Variant = MCSymbolRefExpr::VK_None; - if (Split.first.size() != IDVal.size()) { - Variant = MCSymbolRefExpr::getVariantKindForName(Split.second); - if (Variant == MCSymbolRefExpr::VK_Invalid) - return TokError("invalid variant '" + Split.second + "'"); - IDVal = Split.first; - } - if (IDVal == "f" || IDVal == "b") { - MCSymbol *Sym = - Ctx.getDirectionalLocalSymbol(IntVal, IDVal == "b"); - Res = MCSymbolRefExpr::create(Sym, Variant, getContext()); - if (IDVal == "b" && Sym->isUndefined()) - return Error(Loc, "directional label undefined"); - DirLabels.push_back(std::make_tuple(Loc, CppHashInfo, Sym)); - EndLoc = Lexer.getTok().getEndLoc(); - Lex(); // Eat identifier. - } - } return false; } case AsmToken::String: { @@ -2110,29 +2096,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 +2223,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; + } + // Handle directional local labels + if (IDVal == "@@") { + Sym = Ctx.createDirectionalLocalSymbol(0); + } 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