#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCInstrInfo.h"
#include "llvm/MC/MCObjectFileInfo.h"
#include "llvm/MC/MCParser/MCAsmLexer.h"
#include "llvm/MC/MCParser/MCTargetAsmParser.h"
#include "llvm/MC/MCRegisterInfo.h"
#include "llvm/MC/MCStreamer.h"
#include "llvm/MC/MCSubtargetInfo.h"
#include "llvm/MC/MCSymbol.h"
#include "llvm/MC/TargetRegistry.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/SourceMgr.h"
#include "llvm/Support/TargetSelect.h"
#include "gtest/gtest.h"
using namespace llvm;
namespace {
class SystemZAsmLexerTest : public ::testing::Test {
protected:
static void SetUpTestCase() {
LLVMInitializeSystemZTargetInfo();
LLVMInitializeSystemZTargetMC();
LLVMInitializeSystemZAsmParser();
}
std::unique_ptr<MCRegisterInfo> MRI;
std::unique_ptr<MCAsmInfo> MAI;
std::unique_ptr<const MCInstrInfo> MII;
std::unique_ptr<MCObjectFileInfo> MOFI;
std::unique_ptr<MCStreamer> Str;
std::unique_ptr<MCAsmParser> Parser;
std::unique_ptr<MCContext> Ctx;
std::unique_ptr<MCSubtargetInfo> STI;
std::unique_ptr<MCTargetAsmParser> TargetAsmParser;
SourceMgr SrcMgr;
std::string TripleName;
llvm::Triple Triple;
const Target *TheTarget;
const MCTargetOptions MCOptions;
SystemZAsmLexerTest() = delete;
SystemZAsmLexerTest(std::string SystemZTriple) {
TripleName = SystemZTriple;
Triple = llvm::Triple(TripleName);
std::string Error;
TheTarget = TargetRegistry::lookupTarget(TripleName, Error);
EXPECT_NE(TheTarget, nullptr);
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);
MAI.reset(TheTarget->createMCAsmInfo(*MRI, TripleName, MCOptions));
EXPECT_NE(MAI, nullptr);
}
void setupCallToAsmParser(StringRef AsmStr) {
std::unique_ptr<MemoryBuffer> Buffer(MemoryBuffer::getMemBuffer(AsmStr));
SrcMgr.AddNewSourceBuffer(std::move(Buffer), SMLoc());
EXPECT_EQ(Buffer, nullptr);
Ctx.reset(new MCContext(Triple, MAI.get(), MRI.get(), STI.get(), &SrcMgr,
&MCOptions));
MOFI.reset(TheTarget->createMCObjectFileInfo(*Ctx, false,
false));
Ctx->setObjectFileInfo(MOFI.get());
Str.reset(TheTarget->createNullStreamer(*Ctx));
Parser.reset(createMCAsmParser(SrcMgr, *Ctx, *Str, *MAI));
TargetAsmParser.reset(
TheTarget->createMCAsmParser(*STI, *Parser, *MII, MCOptions));
Parser->setTargetParser(*TargetAsmParser);
}
void lexAndCheckTokens(StringRef AsmStr,
SmallVector<AsmToken::TokenKind> ExpectedTokens) {
MCAsmLexer &Lexer = Parser->getLexer();
for (size_t I = 0; I < ExpectedTokens.size(); ++I) {
EXPECT_EQ(Lexer.getTok().getKind(), ExpectedTokens[I]);
Lexer.Lex();
}
}
void lexAndCheckIntegerTokensAndValues(StringRef AsmStr,
SmallVector<int64_t> ExpectedValues) {
MCAsmLexer &Lexer = Parser->getLexer();
for (size_t I = 0; I < ExpectedValues.size(); ++I) {
if (Lexer.getTok().getKind() == AsmToken::EndOfStatement)
continue;
EXPECT_EQ(Lexer.getTok().getKind(), AsmToken::Integer);
EXPECT_EQ(Lexer.getTok().getIntVal(), ExpectedValues[I]);
Lexer.Lex();
}
}
};
class SystemZAsmLexerLinux : public SystemZAsmLexerTest {
protected:
SystemZAsmLexerLinux() : SystemZAsmLexerTest("s390x-ibm-linux") {}
};
class SystemZAsmLexerZOS : public SystemZAsmLexerTest {
protected:
SystemZAsmLexerZOS() : SystemZAsmLexerTest("s390x-ibm-zos") {}
};
TEST_F(SystemZAsmLexerLinux, CheckDontRestrictCommentStringToStartOfStatement) {
StringRef AsmStr = "jne #-4";
setupCallToAsmParser(AsmStr);
Parser->getLexer().Lex();
SmallVector<AsmToken::TokenKind> ExpectedTokens(
{AsmToken::Identifier, AsmToken::EndOfStatement});
lexAndCheckTokens(AsmStr , ExpectedTokens);
}
TEST_F(SystemZAsmLexerZOS, CheckRestrictCommentStringToStartOfStatement) {
StringRef AsmStr = "jne #-4";
setupCallToAsmParser(AsmStr);
Parser->getLexer().Lex();
SmallVector<AsmToken::TokenKind> ExpectedTokens(
{AsmToken::Identifier, AsmToken::Space, AsmToken::Identifier});
lexAndCheckTokens(AsmStr , ExpectedTokens);
}
TEST_F(SystemZAsmLexerZOS, CheckHLASMComment) {
StringRef AsmStr = "* lhi 1,10";
setupCallToAsmParser(AsmStr);
Parser->getLexer().Lex();
SmallVector<AsmToken::TokenKind> ExpectedTokens(
{AsmToken::EndOfStatement, AsmToken::Eof});
lexAndCheckTokens(AsmStr , ExpectedTokens);
}
TEST_F(SystemZAsmLexerLinux, CheckHashDefault) {
StringRef AsmStr = "lh#123";
setupCallToAsmParser(AsmStr);
Parser->getLexer().Lex();
SmallVector<AsmToken::TokenKind> ExpectedTokens(
{AsmToken::Identifier, AsmToken::EndOfStatement, AsmToken::Eof});
lexAndCheckTokens(AsmStr, ExpectedTokens);
}
TEST_F(SystemZAsmLexerZOS, CheckAllowHashInIdentifier) {
StringRef AsmStr = "lh#123";
setupCallToAsmParser(AsmStr);
Parser->getLexer().Lex();
SmallVector<AsmToken::TokenKind> ExpectedTokens(
{AsmToken::Identifier, AsmToken::EndOfStatement, AsmToken::Eof});
lexAndCheckTokens(AsmStr, ExpectedTokens);
}
TEST_F(SystemZAsmLexerZOS, CheckAllowHashInIdentifier2) {
StringRef AsmStr = "lh#12*3";
setupCallToAsmParser(AsmStr);
Parser->getLexer().Lex();
SmallVector<AsmToken::TokenKind> ExpectedTokens(
{AsmToken::Identifier, AsmToken::Star, AsmToken::Integer,
AsmToken::EndOfStatement, AsmToken::Eof});
lexAndCheckTokens(AsmStr, ExpectedTokens);
}
TEST_F(SystemZAsmLexerLinux, DontCheckStrictCommentString) {
StringRef AsmStr = "# abc\n/* def */// xyz";
setupCallToAsmParser(AsmStr);
Parser->getLexer().Lex();
SmallVector<AsmToken::TokenKind> ExpectedTokens(
{AsmToken::EndOfStatement, AsmToken::Comment, AsmToken::EndOfStatement,
AsmToken::Eof});
lexAndCheckTokens(AsmStr, ExpectedTokens);
}
TEST_F(SystemZAsmLexerZOS, CheckStrictCommentString) {
StringRef AsmStr = "# abc\n/* def */// xyz";
setupCallToAsmParser(AsmStr);
Parser->getLexer().Lex();
SmallVector<AsmToken::TokenKind> ExpectedTokens;
ExpectedTokens.push_back(AsmToken::Identifier); ExpectedTokens.push_back(AsmToken::Space); ExpectedTokens.push_back(AsmToken::Identifier); ExpectedTokens.push_back(AsmToken::EndOfStatement); ExpectedTokens.push_back(AsmToken::Slash); ExpectedTokens.push_back(AsmToken::Star); ExpectedTokens.push_back(AsmToken::Space); ExpectedTokens.push_back(AsmToken::Identifier); ExpectedTokens.push_back(AsmToken::Space); ExpectedTokens.push_back(AsmToken::Star); ExpectedTokens.push_back(AsmToken::Slash); ExpectedTokens.push_back(AsmToken::Slash); ExpectedTokens.push_back(AsmToken::Slash); ExpectedTokens.push_back(AsmToken::Space); ExpectedTokens.push_back(AsmToken::Identifier); ExpectedTokens.push_back(AsmToken::EndOfStatement);
ExpectedTokens.push_back(AsmToken::Eof);
lexAndCheckTokens(AsmStr, ExpectedTokens);
}
TEST_F(SystemZAsmLexerZOS, CheckValidHLASMIntegers) {
StringRef AsmStr = "123\n000123\n1999\n007\n12300\n12021\n";
setupCallToAsmParser(AsmStr);
Parser->getLexer().Lex();
SmallVector<int64_t> ExpectedValues({123, 123, 1999, 7, 12300, 12021});
lexAndCheckIntegerTokensAndValues(AsmStr, ExpectedValues);
}
TEST_F(SystemZAsmLexerZOS, CheckInvalidHLASMIntegers) {
StringRef AsmStr = "0b0101\n0xDEADBEEF\nfffh\n.133\n";
setupCallToAsmParser(AsmStr);
Parser->getLexer().Lex();
SmallVector<AsmToken::TokenKind> ExpectedTokens;
ExpectedTokens.push_back(AsmToken::Integer); ExpectedTokens.push_back(AsmToken::Identifier); ExpectedTokens.push_back(AsmToken::EndOfStatement); ExpectedTokens.push_back(AsmToken::Integer); ExpectedTokens.push_back(AsmToken::Identifier); ExpectedTokens.push_back(AsmToken::EndOfStatement); ExpectedTokens.push_back(AsmToken::Identifier); ExpectedTokens.push_back(AsmToken::EndOfStatement); ExpectedTokens.push_back(AsmToken::Real); ExpectedTokens.push_back(AsmToken::EndOfStatement); ExpectedTokens.push_back(AsmToken::Eof);
lexAndCheckTokens(AsmStr, ExpectedTokens);
}
TEST_F(SystemZAsmLexerLinux, CheckDefaultIntegers) {
StringRef AsmStr = "0b0101\n0xDEADBEEF\nfffh\n";
setupCallToAsmParser(AsmStr);
Parser->getLexer().Lex();
SmallVector<int64_t> ExpectedValues({5, 0xDEADBEEF, 0xFFF});
lexAndCheckIntegerTokensAndValues(AsmStr, ExpectedValues);
}
TEST_F(SystemZAsmLexerLinux, CheckDefaultFloats) {
StringRef AsmStr = "0.333\n1.3\n2.5\n3.0\n";
setupCallToAsmParser(AsmStr);
Parser->getLexer().Lex();
SmallVector<AsmToken::TokenKind> ExpectedTokens;
for (int I = 0; I < 4; ++I)
ExpectedTokens.insert(ExpectedTokens.begin(),
{AsmToken::Real, AsmToken::EndOfStatement});
ExpectedTokens.push_back(AsmToken::Eof);
lexAndCheckTokens(AsmStr, ExpectedTokens);
}
TEST_F(SystemZAsmLexerLinux, CheckDefaultQuestionAtStartOfIdentifier) {
StringRef AsmStr = "?lh1?23";
setupCallToAsmParser(AsmStr);
Parser->getLexer().Lex();
SmallVector<AsmToken::TokenKind> ExpectedTokens(
{AsmToken::Error, AsmToken::Identifier, AsmToken::EndOfStatement,
AsmToken::Eof});
lexAndCheckTokens(AsmStr, ExpectedTokens);
}
TEST_F(SystemZAsmLexerLinux, CheckDefaultAtAtStartOfIdentifier) {
StringRef AsmStr = "@@lh1?23";
setupCallToAsmParser(AsmStr);
Parser->getLexer().Lex();
SmallVector<AsmToken::TokenKind> ExpectedTokens(
{AsmToken::At, AsmToken::At, AsmToken::Identifier,
AsmToken::EndOfStatement, AsmToken::Eof});
lexAndCheckTokens(AsmStr, ExpectedTokens);
}
TEST_F(SystemZAsmLexerZOS, CheckAcceptAtAtStartOfIdentifier) {
StringRef AsmStr = "@@lh1?23";
setupCallToAsmParser(AsmStr);
Parser->getLexer().Lex();
SmallVector<AsmToken::TokenKind> ExpectedTokens(
{AsmToken::Identifier, AsmToken::EndOfStatement, AsmToken::Eof});
lexAndCheckTokens(AsmStr, ExpectedTokens);
}
TEST_F(SystemZAsmLexerLinux, CheckDefaultDollarAtStartOfIdentifier) {
StringRef AsmStr = "$$ac$c";
setupCallToAsmParser(AsmStr);
Parser->getLexer().Lex();
SmallVector<AsmToken::TokenKind> ExpectedTokens(
{AsmToken::Dollar, AsmToken::Dollar, AsmToken::Identifier,
AsmToken::EndOfStatement, AsmToken::Eof});
lexAndCheckTokens(AsmStr, ExpectedTokens);
}
TEST_F(SystemZAsmLexerZOS, CheckAcceptDollarAtStartOfIdentifier) {
StringRef AsmStr = "$$ab$c";
setupCallToAsmParser(AsmStr);
Parser->getLexer().Lex();
SmallVector<AsmToken::TokenKind> ExpectedTokens(
{AsmToken::Identifier, AsmToken::EndOfStatement, AsmToken::Eof});
lexAndCheckTokens(AsmStr, ExpectedTokens);
}
TEST_F(SystemZAsmLexerZOS, CheckAcceptHashAtStartOfIdentifier) {
StringRef AsmStr = "##a#b$c";
setupCallToAsmParser(AsmStr);
Parser->getLexer().Lex();
SmallVector<AsmToken::TokenKind> ExpectedTokens(
{AsmToken::Identifier, AsmToken::EndOfStatement, AsmToken::Eof});
lexAndCheckTokens(AsmStr, ExpectedTokens);
}
TEST_F(SystemZAsmLexerLinux, CheckAcceptHashAtStartOfIdentifier2) {
StringRef AsmStr = "##a#b$c";
setupCallToAsmParser(AsmStr);
Parser->getLexer().Lex();
SmallVector<AsmToken::TokenKind> ExpectedTokens(
{AsmToken::EndOfStatement, AsmToken::Eof});
lexAndCheckTokens(AsmStr, ExpectedTokens);
}
TEST_F(SystemZAsmLexerZOS, CheckAcceptHashAtStartOfIdentifier3) {
StringRef AsmStr = "##a#b$c";
setupCallToAsmParser(AsmStr);
Parser->getLexer().Lex();
SmallVector<AsmToken::TokenKind> ExpectedTokens(
{AsmToken::Identifier, AsmToken::EndOfStatement, AsmToken::Eof});
lexAndCheckTokens(AsmStr, ExpectedTokens);
}
TEST_F(SystemZAsmLexerZOS, CheckAcceptHashAtStartOfIdentifier4) {
StringRef AsmStr = "##a#b$c";
setupCallToAsmParser(AsmStr);
Parser->getLexer().Lex();
SmallVector<AsmToken::TokenKind> ExpectedTokens(
{AsmToken::Identifier, AsmToken::EndOfStatement, AsmToken::Eof});
lexAndCheckTokens(AsmStr, ExpectedTokens);
}
TEST_F(SystemZAsmLexerZOS, CheckRejectDotAsCurrentPC) {
StringRef AsmStr = ".-4";
setupCallToAsmParser(AsmStr);
Parser->getLexer().Lex();
const MCExpr *Expr;
bool ParsePrimaryExpr = Parser->parseExpression(Expr);
EXPECT_EQ(ParsePrimaryExpr, true);
EXPECT_EQ(Parser->hasPendingError(), true);
}
TEST_F(SystemZAsmLexerLinux, CheckRejectStarAsCurrentPC) {
StringRef AsmStr = "*-4";
setupCallToAsmParser(AsmStr);
Parser->getLexer().Lex();
const MCExpr *Expr;
bool ParsePrimaryExpr = Parser->parseExpression(Expr);
EXPECT_EQ(ParsePrimaryExpr, true);
EXPECT_EQ(Parser->hasPendingError(), true);
}
TEST_F(SystemZAsmLexerZOS, CheckRejectCharLiterals) {
StringRef AsmStr = "abc 'd'";
setupCallToAsmParser(AsmStr);
Parser->getLexer().Lex();
SmallVector<AsmToken::TokenKind> ExpectedTokens(
{AsmToken::Identifier, AsmToken::Space, AsmToken::Error, AsmToken::Error,
AsmToken::EndOfStatement, AsmToken::Eof});
lexAndCheckTokens(AsmStr, ExpectedTokens);
}
TEST_F(SystemZAsmLexerZOS, CheckRejectStringLiterals) {
StringRef AsmStr = "abc \"ef\"";
setupCallToAsmParser(AsmStr);
Parser->getLexer().Lex();
SmallVector<AsmToken::TokenKind> ExpectedTokens(
{AsmToken::Identifier, AsmToken::Space, AsmToken::Error,
AsmToken::Identifier, AsmToken::Error, AsmToken::EndOfStatement,
AsmToken::Eof});
lexAndCheckTokens(AsmStr, ExpectedTokens);
}
TEST_F(SystemZAsmLexerZOS, CheckPrintAcceptableSymbol) {
std::string AsmStr = "ab13_$.@";
EXPECT_EQ(true, MAI->isValidUnquotedName(AsmStr));
AsmStr += "#";
EXPECT_EQ(true, MAI->isValidUnquotedName(AsmStr));
}
TEST_F(SystemZAsmLexerLinux, CheckPrintAcceptableSymbol) {
std::string AsmStr = "ab13_$.";
EXPECT_EQ(true, MAI->isValidUnquotedName(AsmStr));
AsmStr = "ab13_$.@";
EXPECT_EQ(false, MAI->isValidUnquotedName(AsmStr));
AsmStr = "ab13_$.#";
EXPECT_EQ(false, MAI->isValidUnquotedName(AsmStr));
}
TEST_F(SystemZAsmLexerZOS, CheckLabelCaseUpperCase) {
StringRef AsmStr = "label";
setupCallToAsmParser(AsmStr);
Parser->getLexer().Lex();
const MCExpr *Expr;
bool ParsePrimaryExpr = Parser->parseExpression(Expr);
EXPECT_EQ(ParsePrimaryExpr, false);
const MCSymbolRefExpr *SymbolExpr = dyn_cast<MCSymbolRefExpr>(Expr);
EXPECT_NE(SymbolExpr, nullptr);
EXPECT_NE(&SymbolExpr->getSymbol(), nullptr);
EXPECT_EQ((&SymbolExpr->getSymbol())->getName(), StringRef("LABEL"));
}
TEST_F(SystemZAsmLexerLinux, CheckLabelUpperCase2) {
StringRef AsmStr = "label";
setupCallToAsmParser(AsmStr);
Parser->getLexer().Lex();
const MCExpr *Expr;
bool ParsePrimaryExpr = Parser->parseExpression(Expr);
EXPECT_EQ(ParsePrimaryExpr, false);
const MCSymbolRefExpr *SymbolExpr = dyn_cast<MCSymbolRefExpr>(Expr);
EXPECT_NE(SymbolExpr, nullptr);
EXPECT_NE(&SymbolExpr->getSymbol(), nullptr);
EXPECT_EQ((&SymbolExpr->getSymbol())->getName(), StringRef("label"));
}
}