1 //===- llvm/unittests/MC/SystemZ/SystemZAsmLexerTest.cpp ----------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===--------------------------------------------------------------------===// 8 #include "llvm/MC/MCAsmInfo.h" 9 #include "llvm/MC/MCContext.h" 10 #include "llvm/MC/MCObjectFileInfo.h" 11 #include "llvm/MC/MCParser/MCTargetAsmParser.h" 12 #include "llvm/MC/MCRegisterInfo.h" 13 #include "llvm/MC/MCStreamer.h" 14 #include "llvm/Support/MemoryBuffer.h" 15 #include "llvm/Support/SourceMgr.h" 16 #include "llvm/Support/TargetRegistry.h" 17 #include "llvm/Support/TargetSelect.h" 18 19 #include "gtest/gtest.h" 20 21 using namespace llvm; 22 23 namespace { 24 25 // Come up with our hacked version of MCAsmInfo. 26 // This hacked version derives from the main MCAsmInfo instance. 27 // Here, we're free to override whatever we want, without polluting 28 // the main MCAsmInfo interface. 29 class MockedUpMCAsmInfo : public MCAsmInfo { 30 public: 31 void setRestrictCommentStringToStartOfStatement(bool Value) { 32 RestrictCommentStringToStartOfStatement = Value; 33 } 34 void setCommentString(StringRef Value) { CommentString = Value; } 35 void setAllowAdditionalComments(bool Value) { 36 AllowAdditionalComments = Value; 37 } 38 }; 39 40 // Setup a testing class that the GTest framework can call. 41 class SystemZAsmLexerTest : public ::testing::Test { 42 protected: 43 static void SetUpTestCase() { 44 LLVMInitializeSystemZTargetInfo(); 45 LLVMInitializeSystemZTargetMC(); 46 } 47 48 std::unique_ptr<MCRegisterInfo> MRI; 49 std::unique_ptr<MockedUpMCAsmInfo> MUPMAI; 50 std::unique_ptr<const MCInstrInfo> MII; 51 std::unique_ptr<MCStreamer> Str; 52 std::unique_ptr<MCAsmParser> Parser; 53 std::unique_ptr<MCContext> Ctx; 54 55 SourceMgr SrcMgr; 56 std::string TripleName; 57 llvm::Triple Triple; 58 const Target *TheTarget; 59 60 const MCTargetOptions MCOptions; 61 MCObjectFileInfo MOFI; 62 63 SystemZAsmLexerTest() { 64 // We will use the SystemZ triple, because of missing 65 // Object File and Streamer support for the z/OS target. 66 TripleName = "s390x-ibm-linux"; 67 Triple = llvm::Triple(TripleName); 68 69 std::string Error; 70 TheTarget = TargetRegistry::lookupTarget(TripleName, Error); 71 EXPECT_NE(TheTarget, nullptr); 72 73 MRI.reset(TheTarget->createMCRegInfo(TripleName)); 74 EXPECT_NE(MRI, nullptr); 75 76 std::unique_ptr<MCAsmInfo> MAI; 77 MAI.reset(TheTarget->createMCAsmInfo(*MRI, TripleName, MCOptions)); 78 EXPECT_NE(MAI, nullptr); 79 80 // Now we cast to our mocked up version of MCAsmInfo. 81 MUPMAI.reset(static_cast<MockedUpMCAsmInfo *>(MAI.release())); 82 // MUPMAI should "hold" MAI. 83 EXPECT_NE(MUPMAI, nullptr); 84 // After releasing, MAI should now be null. 85 EXPECT_EQ(MAI, nullptr); 86 } 87 88 void setupCallToAsmParser(StringRef AsmStr) { 89 std::unique_ptr<MemoryBuffer> Buffer(MemoryBuffer::getMemBuffer(AsmStr)); 90 SrcMgr.AddNewSourceBuffer(std::move(Buffer), SMLoc()); 91 EXPECT_EQ(Buffer, nullptr); 92 93 Ctx.reset( 94 new MCContext(MUPMAI.get(), MRI.get(), &MOFI, &SrcMgr, &MCOptions)); 95 MOFI.InitMCObjectFileInfo(Triple, false, *Ctx, false); 96 97 Str.reset(TheTarget->createNullStreamer(*Ctx)); 98 99 Parser.reset(createMCAsmParser(SrcMgr, *Ctx, *Str, *MUPMAI)); 100 } 101 102 void lexAndCheckTokens(StringRef AsmStr, 103 SmallVector<AsmToken::TokenKind> ExpectedTokens) { 104 // Get reference to AsmLexer. 105 MCAsmLexer &Lexer = Parser->getLexer(); 106 // Loop through all expected tokens checking one by one. 107 for (size_t I = 0; I < ExpectedTokens.size(); ++I) { 108 EXPECT_EQ(Lexer.getTok().getKind(), ExpectedTokens[I]); 109 Lexer.Lex(); 110 } 111 } 112 113 void lexAndCheckIntegerTokensAndValues(StringRef AsmStr, 114 SmallVector<int64_t> ExpectedValues) { 115 // Get reference to AsmLexer. 116 MCAsmLexer &Lexer = Parser->getLexer(); 117 // Loop through all expected tokens and expected values. 118 for (size_t I = 0; I < ExpectedValues.size(); ++I) { 119 // Skip any EndOfStatement tokens, we're not concerned with them. 120 if (Lexer.getTok().getKind() == AsmToken::EndOfStatement) 121 continue; 122 EXPECT_EQ(Lexer.getTok().getKind(), AsmToken::Integer); 123 EXPECT_EQ(Lexer.getTok().getIntVal(), ExpectedValues[I]); 124 Lexer.Lex(); 125 } 126 } 127 }; 128 129 TEST_F(SystemZAsmLexerTest, CheckDontRestrictCommentStringToStartOfStatement) { 130 StringRef AsmStr = "jne #-4"; 131 132 // Setup. 133 setupCallToAsmParser(AsmStr); 134 135 // Lex initially to get the string. 136 Parser->getLexer().Lex(); 137 138 SmallVector<AsmToken::TokenKind> ExpectedTokens( 139 {AsmToken::Identifier, AsmToken::EndOfStatement}); 140 lexAndCheckTokens(AsmStr /* "jne #-4" */, ExpectedTokens); 141 } 142 143 // Testing MCAsmInfo's RestrictCommentStringToStartOfStatement attribute. 144 TEST_F(SystemZAsmLexerTest, CheckRestrictCommentStringToStartOfStatement) { 145 StringRef AsmStr = "jne #-4"; 146 147 // Setup. 148 MUPMAI->setRestrictCommentStringToStartOfStatement(true); 149 setupCallToAsmParser(AsmStr); 150 151 // Lex initially to get the string. 152 Parser->getLexer().Lex(); 153 154 // When we are restricting the comment string to only the start of the 155 // statement, The sequence of tokens we are expecting are: Identifier - "jne" 156 // Hash - '#' 157 // Minus - '-' 158 // Integer - '4' 159 SmallVector<AsmToken::TokenKind> ExpectedTokens( 160 {AsmToken::Identifier, AsmToken::Hash, AsmToken::Minus, 161 AsmToken::Integer}); 162 lexAndCheckTokens(AsmStr /* "jne #-4" */, ExpectedTokens); 163 } 164 165 // Test HLASM Comment Syntax ('*') 166 TEST_F(SystemZAsmLexerTest, CheckHLASMComment) { 167 StringRef AsmStr = "* lhi 1,10"; 168 169 // Setup. 170 MUPMAI->setCommentString("*"); 171 setupCallToAsmParser(AsmStr); 172 173 // Lex initially to get the string. 174 Parser->getLexer().Lex(); 175 176 SmallVector<AsmToken::TokenKind> ExpectedTokens( 177 {AsmToken::EndOfStatement, AsmToken::Eof}); 178 lexAndCheckTokens(AsmStr /* "* lhi 1,10" */, ExpectedTokens); 179 } 180 181 TEST_F(SystemZAsmLexerTest, CheckHashDefault) { 182 StringRef AsmStr = "lh#123"; 183 184 // Setup. 185 setupCallToAsmParser(AsmStr); 186 187 // Lex initially to get the string. 188 Parser->getLexer().Lex(); 189 190 // "lh" -> Identifier 191 // "#123" -> EndOfStatement (Lexed as a comment since CommentString is "#") 192 SmallVector<AsmToken::TokenKind> ExpectedTokens( 193 {AsmToken::Identifier, AsmToken::EndOfStatement, AsmToken::Eof}); 194 lexAndCheckTokens(AsmStr, ExpectedTokens); 195 } 196 197 // Test if "#" is accepted as an Identifier 198 TEST_F(SystemZAsmLexerTest, CheckAllowHashInIdentifier) { 199 StringRef AsmStr = "lh#123"; 200 201 // Setup. 202 setupCallToAsmParser(AsmStr); 203 Parser->getLexer().setAllowHashInIdentifier(true); 204 205 // Lex initially to get the string. 206 Parser->getLexer().Lex(); 207 208 // "lh123" -> Identifier 209 SmallVector<AsmToken::TokenKind> ExpectedTokens( 210 {AsmToken::Identifier, AsmToken::EndOfStatement, AsmToken::Eof}); 211 lexAndCheckTokens(AsmStr, ExpectedTokens); 212 } 213 214 TEST_F(SystemZAsmLexerTest, CheckAllowHashInIdentifier2) { 215 StringRef AsmStr = "lh#12*3"; 216 217 // Setup. 218 MUPMAI->setCommentString("*"); 219 MUPMAI->setRestrictCommentStringToStartOfStatement(true); 220 setupCallToAsmParser(AsmStr); 221 Parser->getLexer().setAllowHashInIdentifier(true); 222 223 // Lex initially to get the string. 224 Parser->getLexer().Lex(); 225 226 // "lh#12" -> Identifier 227 // "*" -> Star 228 // "3" -> Integer 229 SmallVector<AsmToken::TokenKind> ExpectedTokens( 230 {AsmToken::Identifier, AsmToken::Star, AsmToken::Integer, 231 AsmToken::EndOfStatement, AsmToken::Eof}); 232 lexAndCheckTokens(AsmStr, ExpectedTokens); 233 } 234 235 TEST_F(SystemZAsmLexerTest, DontCheckStrictCommentString) { 236 StringRef AsmStr = "# abc\n/* def */// xyz"; 237 238 // Setup. 239 setupCallToAsmParser(AsmStr); 240 241 // Lex initially to get the string. 242 Parser->getLexer().Lex(); 243 244 SmallVector<AsmToken::TokenKind> ExpectedTokens( 245 {AsmToken::EndOfStatement, AsmToken::Comment, AsmToken::EndOfStatement, 246 AsmToken::Eof}); 247 lexAndCheckTokens(AsmStr, ExpectedTokens); 248 } 249 250 TEST_F(SystemZAsmLexerTest, DontCheckStrictCommentString2) { 251 StringRef AsmStr = "# abc\n/* def */// xyz\n* rst"; 252 253 // Setup. 254 MUPMAI->setCommentString("*"); 255 setupCallToAsmParser(AsmStr); 256 257 // Lex initially to get the string. 258 Parser->getLexer().Lex(); 259 260 SmallVector<AsmToken::TokenKind> ExpectedTokens( 261 {AsmToken::EndOfStatement, AsmToken::Comment, AsmToken::EndOfStatement, 262 AsmToken::EndOfStatement, AsmToken::Eof}); 263 lexAndCheckTokens(AsmStr, ExpectedTokens); 264 } 265 266 TEST_F(SystemZAsmLexerTest, CheckStrictCommentString) { 267 StringRef AsmStr = "# abc\n/* def */// xyz"; 268 269 // Setup. 270 MUPMAI->setAllowAdditionalComments(false); 271 setupCallToAsmParser(AsmStr); 272 273 // Lex initially to get the string. 274 Parser->getLexer().Lex(); 275 276 // "# abc" -> still treated as a comment, since CommentString 277 // is set to "#" 278 SmallVector<AsmToken::TokenKind> ExpectedTokens; 279 ExpectedTokens.push_back(AsmToken::EndOfStatement); // "# abc\n" 280 ExpectedTokens.push_back(AsmToken::Slash); // "/" 281 ExpectedTokens.push_back(AsmToken::Star); // "*" 282 ExpectedTokens.push_back(AsmToken::Identifier); // "def" 283 ExpectedTokens.push_back(AsmToken::Star); // "*" 284 ExpectedTokens.push_back(AsmToken::Slash); // "/" 285 ExpectedTokens.push_back(AsmToken::Slash); // "/" 286 ExpectedTokens.push_back(AsmToken::Slash); // "/" 287 ExpectedTokens.push_back(AsmToken::Identifier); // "xyz" 288 ExpectedTokens.push_back(AsmToken::EndOfStatement); 289 ExpectedTokens.push_back(AsmToken::Eof); 290 291 lexAndCheckTokens(AsmStr, ExpectedTokens); 292 } 293 294 TEST_F(SystemZAsmLexerTest, CheckStrictCommentString2) { 295 StringRef AsmStr = "// abc"; 296 297 // Setup. 298 MUPMAI->setAllowAdditionalComments(false); 299 MUPMAI->setCommentString("//"); 300 setupCallToAsmParser(AsmStr); 301 302 // Lex initially to get the string. 303 Parser->getLexer().Lex(); 304 305 // "// abc" -> will still be treated as a comment because "//" is the 306 // CommentString 307 SmallVector<AsmToken::TokenKind> ExpectedTokens( 308 {AsmToken::EndOfStatement, AsmToken::Eof}); 309 lexAndCheckTokens(AsmStr /* "// abc" */, ExpectedTokens); 310 } 311 312 TEST_F(SystemZAsmLexerTest, CheckStrictCommentString3) { 313 StringRef AsmStr = "/* abc */"; 314 315 // Setup. 316 MUPMAI->setAllowAdditionalComments(false); 317 setupCallToAsmParser(AsmStr); 318 319 // Lex initially to get the string. 320 Parser->getLexer().Lex(); 321 322 SmallVector<AsmToken::TokenKind> ExpectedTokens; 323 ExpectedTokens.push_back(AsmToken::Slash); 324 ExpectedTokens.push_back(AsmToken::Star); 325 ExpectedTokens.push_back(AsmToken::Identifier); 326 ExpectedTokens.push_back(AsmToken::Star); 327 ExpectedTokens.push_back(AsmToken::Slash); 328 ExpectedTokens.push_back(AsmToken::EndOfStatement); 329 ExpectedTokens.push_back(AsmToken::Eof); 330 331 lexAndCheckTokens(AsmStr, ExpectedTokens); 332 } 333 334 TEST_F(SystemZAsmLexerTest, CheckStrictCommentString4) { 335 StringRef AsmStr = "# abc\n/* def */// xyz"; 336 337 // Setup. 338 MUPMAI->setCommentString("*"); 339 MUPMAI->setAllowAdditionalComments(false); 340 MUPMAI->setRestrictCommentStringToStartOfStatement(true); 341 setupCallToAsmParser(AsmStr); 342 343 // Lex initially to get the string. 344 Parser->getLexer().Lex(); 345 346 SmallVector<AsmToken::TokenKind> ExpectedTokens; 347 ExpectedTokens.push_back(AsmToken::Hash); // "#" 348 ExpectedTokens.push_back(AsmToken::Identifier); // "abc" 349 ExpectedTokens.push_back(AsmToken::EndOfStatement); // "\n" 350 ExpectedTokens.push_back(AsmToken::Slash); // "/" 351 ExpectedTokens.push_back(AsmToken::Star); // "*" 352 ExpectedTokens.push_back(AsmToken::Identifier); // "def" 353 ExpectedTokens.push_back(AsmToken::Star); // "*" 354 ExpectedTokens.push_back(AsmToken::Slash); // "/" 355 ExpectedTokens.push_back(AsmToken::Slash); // "/" 356 ExpectedTokens.push_back(AsmToken::Slash); // "/" 357 ExpectedTokens.push_back(AsmToken::Identifier); // "xyz" 358 ExpectedTokens.push_back(AsmToken::EndOfStatement); 359 ExpectedTokens.push_back(AsmToken::Eof); 360 361 lexAndCheckTokens(AsmStr, ExpectedTokens); 362 } 363 364 TEST_F(SystemZAsmLexerTest, CheckStrictCommentString5) { 365 StringRef AsmStr = "#abc\n/* def */// xyz"; 366 367 // Setup. 368 MUPMAI->setCommentString("*"); 369 MUPMAI->setAllowAdditionalComments(false); 370 setupCallToAsmParser(AsmStr); 371 372 // Lex initially to get the string. 373 Parser->getLexer().Lex(); 374 375 SmallVector<AsmToken::TokenKind> ExpectedTokens; 376 ExpectedTokens.push_back(AsmToken::Hash); // "#" 377 ExpectedTokens.push_back(AsmToken::Identifier); // "abc" 378 ExpectedTokens.push_back(AsmToken::EndOfStatement); // "\n" 379 ExpectedTokens.push_back(AsmToken::Slash); // "/" 380 ExpectedTokens.push_back(AsmToken::EndOfStatement); // "* def */// xyz" 381 ExpectedTokens.push_back(AsmToken::Eof); 382 383 lexAndCheckTokens(AsmStr, ExpectedTokens); 384 } 385 386 TEST_F(SystemZAsmLexerTest, CheckValidHLASMIntegers) { 387 StringRef AsmStr = "123\n000123\n1999\n007\n12300\n12021\n"; 388 // StringRef AsmStr = "123"; 389 // Setup. 390 setupCallToAsmParser(AsmStr); 391 Parser->getLexer().setLexHLASMIntegers(true); 392 393 // Lex initially to get the string. 394 Parser->getLexer().Lex(); 395 396 // SmallVector<int64_t> ExpectedValues({123}); 397 SmallVector<int64_t> ExpectedValues({123, 123, 1999, 7, 12300, 12021}); 398 lexAndCheckIntegerTokensAndValues(AsmStr, ExpectedValues); 399 } 400 401 TEST_F(SystemZAsmLexerTest, CheckInvalidHLASMIntegers) { 402 StringRef AsmStr = "0b0101\n0xDEADBEEF\nfffh\n.133\n"; 403 404 // Setup. 405 setupCallToAsmParser(AsmStr); 406 Parser->getLexer().setLexHLASMIntegers(true); 407 408 // Lex initially to get the string. 409 Parser->getLexer().Lex(); 410 411 SmallVector<AsmToken::TokenKind> ExpectedTokens; 412 ExpectedTokens.push_back(AsmToken::Integer); // "0" 413 ExpectedTokens.push_back(AsmToken::Identifier); // "b0101" 414 ExpectedTokens.push_back(AsmToken::EndOfStatement); // "\n" 415 ExpectedTokens.push_back(AsmToken::Integer); // "0" 416 ExpectedTokens.push_back(AsmToken::Identifier); // "xDEADBEEF" 417 ExpectedTokens.push_back(AsmToken::EndOfStatement); // "\n" 418 ExpectedTokens.push_back(AsmToken::Identifier); // "fffh" 419 ExpectedTokens.push_back(AsmToken::EndOfStatement); // "\n" 420 ExpectedTokens.push_back(AsmToken::Real); // ".133" 421 ExpectedTokens.push_back(AsmToken::EndOfStatement); // "\n" 422 ExpectedTokens.push_back(AsmToken::Eof); 423 lexAndCheckTokens(AsmStr, ExpectedTokens); 424 } 425 426 TEST_F(SystemZAsmLexerTest, CheckDefaultIntegers) { 427 StringRef AsmStr = "0b0101\n0xDEADBEEF\nfffh\n"; 428 429 // Setup. 430 setupCallToAsmParser(AsmStr); 431 432 // Lex initially to get the string. 433 Parser->getLexer().Lex(); 434 435 SmallVector<int64_t> ExpectedValues({5, 0xDEADBEEF, 0xFFF}); 436 lexAndCheckIntegerTokensAndValues(AsmStr, ExpectedValues); 437 } 438 439 TEST_F(SystemZAsmLexerTest, CheckDefaultFloats) { 440 StringRef AsmStr = "0.333\n1.3\n2.5\n3.0\n"; 441 442 // Setup. 443 setupCallToAsmParser(AsmStr); 444 445 // Lex initially to get the string. 446 Parser->getLexer().Lex(); 447 448 SmallVector<AsmToken::TokenKind> ExpectedTokens; 449 450 for (int I = 0; I < 4; ++I) 451 ExpectedTokens.insert(ExpectedTokens.begin(), 452 {AsmToken::Real, AsmToken::EndOfStatement}); 453 454 ExpectedTokens.push_back(AsmToken::Eof); 455 lexAndCheckTokens(AsmStr, ExpectedTokens); 456 } 457 } // end anonymous namespace 458