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 @@ -118,6 +118,10 @@ /// the current PC. Defaults to false. bool DollarIsPC = false; + /// Allow '.' token, when not referencing an identifier or constant, to refer + /// to the current PC. Defaults to false. + bool DotIsPC = true; + /// This string, if specified, is used to separate instructions from each /// other when on the same line. Defaults to ';' const char *SeparatorString; @@ -589,6 +593,7 @@ unsigned getMinInstAlignment() const { return MinInstAlignment; } bool getDollarIsPC() const { return DollarIsPC; } + bool getDotIsPC() const { return DotIsPC; } 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 @@ -1245,6 +1245,9 @@ return false; } case AsmToken::Dot: { + if (!MAI.getDotIsPC()) + return TokError("cannot use . as current PC"); + // This is a '.' reference, which references the current PC. Emit a // temporary label to the streamer and refer to it. MCSymbol *Sym = Ctx.createTempSymbol(); 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 @@ -27,6 +27,7 @@ AllowAtAtStartOfIdentifier = (AssemblerDialect == AD_HLASM); AllowDollarAtStartOfIdentifier = (AssemblerDialect == AD_HLASM); AllowHashAtStartOfIdentifier = (AssemblerDialect == AD_HLASM); + DotIsPC = (AssemblerDialect == AD_ATT); ZeroDirective = "\t.space\t"; Data64bitsDirective = "\t.quad\t"; 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 @@ -47,6 +47,7 @@ void setAllowHashAtStartOfIdentifier(bool Value) { AllowHashAtStartOfIdentifier = Value; } + void setAllowDotIsPC(bool Value) { DotIsPC = Value; } }; // Setup a testing class that the GTest framework can call. @@ -55,6 +56,7 @@ static void SetUpTestCase() { LLVMInitializeSystemZTargetInfo(); LLVMInitializeSystemZTargetMC(); + LLVMInitializeSystemZAsmParser(); } std::unique_ptr MRI; @@ -63,6 +65,8 @@ std::unique_ptr Str; std::unique_ptr Parser; std::unique_ptr Ctx; + std::unique_ptr STI; + std::unique_ptr TargetAsmParser; SourceMgr SrcMgr; std::string TripleName; @@ -85,6 +89,12 @@ MRI.reset(TheTarget->createMCRegInfo(TripleName)); EXPECT_NE(MRI, nullptr); + MII.reset(TheTarget->createMCInstrInfo()); + EXPECT_NE(MII, nullptr); + + STI.reset(TheTarget->createMCSubtargetInfo(TripleName, "z10", "")); + EXPECT_NE(STI, nullptr); + std::unique_ptr MAI; MAI.reset(TheTarget->createMCAsmInfo(*MRI, TripleName, MCOptions)); EXPECT_NE(MAI, nullptr); @@ -109,6 +119,10 @@ Str.reset(TheTarget->createNullStreamer(*Ctx)); Parser.reset(createMCAsmParser(SrcMgr, *Ctx, *Str, *MUPMAI)); + + TargetAsmParser.reset( + TheTarget->createMCAsmParser(*STI, *Parser, *MII, MCOptions)); + Parser->setTargetParser(*TargetAsmParser); } void lexAndCheckTokens(StringRef AsmStr, @@ -592,4 +606,20 @@ {AsmToken::Identifier, AsmToken::EndOfStatement, AsmToken::Eof}); lexAndCheckTokens(AsmStr, ExpectedTokens); } + +TEST_F(SystemZAsmLexerTest, CheckRejectDotAsCurrentPC) { + StringRef AsmStr = ".-4"; + + // Setup. + MUPMAI->setAllowDotIsPC(false); + 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