diff --git a/llvm/include/llvm/MC/MCAsmInfo.h b/llvm/include/llvm/MC/MCAsmInfo.h --- a/llvm/include/llvm/MC/MCAsmInfo.h +++ b/llvm/include/llvm/MC/MCAsmInfo.h @@ -122,6 +122,10 @@ /// to the current PC. Defaults to true. bool DotIsPC = true; + /// Whether the '*' token refers to the current PC. This is used for the + /// HLASM dialect. + bool StarIsPC = false; + /// This string, if specified, is used to separate instructions from each /// other when on the same line. Defaults to ';' const char *SeparatorString; @@ -598,6 +602,7 @@ unsigned getMinInstAlignment() const { return MinInstAlignment; } bool getDollarIsPC() const { return DollarIsPC; } bool getDotIsPC() const { return DotIsPC; } + bool getStarIsPC() const { return StarIsPC; } const char *getSeparatorString() const { return SeparatorString; } /// This indicates the column (zero-based) at which asm comments should be diff --git a/llvm/lib/MC/MCParser/AsmParser.cpp b/llvm/lib/MC/MCParser/AsmParser.cpp --- a/llvm/lib/MC/MCParser/AsmParser.cpp +++ b/llvm/lib/MC/MCParser/AsmParser.cpp @@ -1110,25 +1110,33 @@ Res = MCUnaryExpr::createLNot(Res, getContext(), FirstTokenLoc); return false; case AsmToken::Dollar: + case AsmToken::Star: case AsmToken::At: case AsmToken::String: case AsmToken::Identifier: { StringRef Identifier; if (parseIdentifier(Identifier)) { - // We may have failed but $ may be a valid token. - if (getTok().is(AsmToken::Dollar)) { - if (Lexer.getMAI().getDollarIsPC()) { - Lex(); - // This is a '$' reference, which references the current PC. Emit a - // temporary label to the streamer and refer to it. - MCSymbol *Sym = Ctx.createTempSymbol(); - Out.emitLabel(Sym); - Res = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, - getContext()); - EndLoc = FirstTokenLoc; - return false; - } - return Error(FirstTokenLoc, "invalid token in expression"); + // We may have failed but '$'|'*' may be a valid token in context of + // the current PC. + if (getTok().is(AsmToken::Dollar) || getTok().is(AsmToken::Star)) { + bool ShouldGenerateTempSymbol = false; + if ((getTok().is(AsmToken::Dollar) && MAI.getDollarIsPC()) || + (getTok().is(AsmToken::Star) && MAI.getStarIsPC())) + ShouldGenerateTempSymbol = true; + + if (!ShouldGenerateTempSymbol) + return Error(FirstTokenLoc, "invalid token in expression"); + + // Eat the '$'|'*' token. + Lex(); + // This is either a '$'|'*' reference, which references the current PC. + // Emit a temporary label to the streamer and refer to it. + MCSymbol *Sym = Ctx.createTempSymbol(); + Out.emitLabel(Sym); + Res = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, + getContext()); + EndLoc = FirstTokenLoc; + return false; } } // Parse symbol variant diff --git a/llvm/lib/Target/SystemZ/AsmParser/SystemZAsmParser.cpp b/llvm/lib/Target/SystemZ/AsmParser/SystemZAsmParser.cpp --- a/llvm/lib/Target/SystemZ/AsmParser/SystemZAsmParser.cpp +++ b/llvm/lib/Target/SystemZ/AsmParser/SystemZAsmParser.cpp @@ -1542,6 +1542,10 @@ // For consistency with the GNU assembler, treat immediates as offsets // from ".". if (auto *CE = dyn_cast(Expr)) { + if (isParsingHLASM()) { + Error(StartLoc, "Expected PC-relative expression"); + return MatchOperand_ParseFail; + } if (isOutOfRangeConstant(CE)) { Error(StartLoc, "offset out of range"); return MatchOperand_ParseFail; diff --git a/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZMCAsmInfo.cpp b/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZMCAsmInfo.cpp --- a/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZMCAsmInfo.cpp +++ b/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZMCAsmInfo.cpp @@ -28,6 +28,7 @@ AllowDollarAtStartOfIdentifier = (AssemblerDialect == AD_HLASM); AllowHashAtStartOfIdentifier = (AssemblerDialect == AD_HLASM); DotIsPC = (AssemblerDialect == AD_ATT); + StarIsPC = (AssemblerDialect == AD_HLASM); ZeroDirective = "\t.space\t"; Data64bitsDirective = "\t.quad\t"; diff --git a/llvm/test/MC/AsmParser/directive_rept-diagnostics.s b/llvm/test/MC/AsmParser/directive_rept-diagnostics.s --- a/llvm/test/MC/AsmParser/directive_rept-diagnostics.s +++ b/llvm/test/MC/AsmParser/directive_rept-diagnostics.s @@ -8,7 +8,7 @@ invalid_expression: .rept * -# CHECK: error: unknown token in expression +# CHECK: error: invalid token in expression # CHECK: .rept * # CHECK: ^ diff --git a/llvm/unittests/MC/SystemZ/SystemZAsmLexerTest.cpp b/llvm/unittests/MC/SystemZ/SystemZAsmLexerTest.cpp --- a/llvm/unittests/MC/SystemZ/SystemZAsmLexerTest.cpp +++ b/llvm/unittests/MC/SystemZ/SystemZAsmLexerTest.cpp @@ -685,4 +685,19 @@ EXPECT_EQ(ParsePrimaryExpr, true); EXPECT_EQ(Parser->hasPendingError(), true); } + +TEST_F(SystemZAsmLexerTest, CheckRejectStarAsCurrentPC) { + StringRef AsmStr = "*-4"; + + // Setup. + setupCallToAsmParser(AsmStr); + + // Lex initially to get the string. + Parser->getLexer().Lex(); + + const MCExpr *Expr; + bool ParsePrimaryExpr = Parser->parseExpression(Expr); + EXPECT_EQ(ParsePrimaryExpr, true); + EXPECT_EQ(Parser->hasPendingError(), true); +} } // end anonymous namespace