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 }; 36 37 // Setup a testing class that the GTest framework can call. 38 class SystemZAsmLexerTest : public ::testing::Test { 39 protected: 40 static void SetUpTestCase() { 41 LLVMInitializeSystemZTargetInfo(); 42 LLVMInitializeSystemZTargetMC(); 43 } 44 45 std::unique_ptr<MCRegisterInfo> MRI; 46 std::unique_ptr<MockedUpMCAsmInfo> MUPMAI; 47 std::unique_ptr<const MCInstrInfo> MII; 48 std::unique_ptr<MCStreamer> Str; 49 std::unique_ptr<MCAsmParser> Parser; 50 std::unique_ptr<MCContext> Ctx; 51 52 SourceMgr SrcMgr; 53 std::string TripleName; 54 llvm::Triple Triple; 55 const Target *TheTarget; 56 57 const MCTargetOptions MCOptions; 58 MCObjectFileInfo MOFI; 59 60 SystemZAsmLexerTest() { 61 // We will use the SystemZ triple, because of missing 62 // Object File and Streamer support for the z/OS target. 63 TripleName = "s390x-ibm-linux"; 64 Triple = llvm::Triple(TripleName); 65 66 std::string Error; 67 TheTarget = TargetRegistry::lookupTarget(TripleName, Error); 68 EXPECT_NE(TheTarget, nullptr); 69 70 MRI.reset(TheTarget->createMCRegInfo(TripleName)); 71 EXPECT_NE(MRI, nullptr); 72 73 std::unique_ptr<MCAsmInfo> MAI; 74 MAI.reset(TheTarget->createMCAsmInfo(*MRI, TripleName, MCOptions)); 75 EXPECT_NE(MAI, nullptr); 76 77 // Now we cast to our mocked up version of MCAsmInfo. 78 MUPMAI.reset(static_cast<MockedUpMCAsmInfo *>(MAI.release())); 79 // MUPMAI should "hold" MAI. 80 EXPECT_NE(MUPMAI, nullptr); 81 // After releasing, MAI should now be null. 82 EXPECT_EQ(MAI, nullptr); 83 } 84 85 void setupCallToAsmParser(StringRef AsmStr) { 86 std::unique_ptr<MemoryBuffer> Buffer(MemoryBuffer::getMemBuffer(AsmStr)); 87 SrcMgr.AddNewSourceBuffer(std::move(Buffer), SMLoc()); 88 EXPECT_EQ(Buffer, nullptr); 89 90 Ctx.reset( 91 new MCContext(MUPMAI.get(), MRI.get(), &MOFI, &SrcMgr, &MCOptions)); 92 MOFI.InitMCObjectFileInfo(Triple, false, *Ctx, false); 93 94 Str.reset(TheTarget->createNullStreamer(*Ctx)); 95 96 Parser.reset(createMCAsmParser(SrcMgr, *Ctx, *Str, *MUPMAI)); 97 } 98 99 void lexAndCheckTokens(StringRef AsmStr, 100 SmallVector<AsmToken::TokenKind> ExpectedTokens) { 101 // Get reference to AsmLexer. 102 MCAsmLexer &Lexer = Parser->getLexer(); 103 // Loop through all expected tokens checking one by one. 104 for (size_t I = 0; I < ExpectedTokens.size(); ++I) { 105 EXPECT_EQ(Lexer.getTok().getKind(), ExpectedTokens[I]); 106 Lexer.Lex(); 107 } 108 } 109 }; 110 111 TEST_F(SystemZAsmLexerTest, CheckDontRestrictCommentStringToStartOfStatement) { 112 StringRef AsmStr = "jne #-4"; 113 114 // Setup. 115 setupCallToAsmParser(AsmStr); 116 117 // Lex initially to get the string. 118 Parser->getLexer().Lex(); 119 120 SmallVector<AsmToken::TokenKind> ExpectedTokens( 121 {AsmToken::Identifier, AsmToken::EndOfStatement}); 122 lexAndCheckTokens(AsmStr /* "jne #-4" */, ExpectedTokens); 123 } 124 125 // Testing MCAsmInfo's RestrictCommentStringToStartOfStatement attribute. 126 TEST_F(SystemZAsmLexerTest, CheckRestrictCommentStringToStartOfStatement) { 127 StringRef AsmStr = "jne #-4"; 128 129 // Setup. 130 MUPMAI->setRestrictCommentStringToStartOfStatement(true); 131 setupCallToAsmParser(AsmStr); 132 133 // Lex initially to get the string. 134 Parser->getLexer().Lex(); 135 136 // When we are restricting the comment string to only the start of the 137 // statement, The sequence of tokens we are expecting are: Identifier - "jne" 138 // Hash - '#' 139 // Minus - '-' 140 // Integer - '4' 141 SmallVector<AsmToken::TokenKind> ExpectedTokens( 142 {AsmToken::Identifier, AsmToken::Hash, AsmToken::Minus, 143 AsmToken::Integer}); 144 lexAndCheckTokens(AsmStr /* "jne #-4" */, ExpectedTokens); 145 } 146 147 // Test HLASM Comment Syntax ('*') 148 TEST_F(SystemZAsmLexerTest, CheckHLASMComment) { 149 StringRef AsmStr = "* lhi 1,10"; 150 151 // Setup. 152 MUPMAI->setCommentString("*"); 153 setupCallToAsmParser(AsmStr); 154 155 // Lex initially to get the string. 156 Parser->getLexer().Lex(); 157 158 SmallVector<AsmToken::TokenKind> ExpectedTokens( 159 {AsmToken::EndOfStatement, AsmToken::Eof}); 160 lexAndCheckTokens(AsmStr /* "* lhi 1,10" */, ExpectedTokens); 161 } 162 163 TEST_F(SystemZAsmLexerTest, CheckHashDefault) { 164 StringRef AsmStr = "lh#123"; 165 166 // Setup. 167 setupCallToAsmParser(AsmStr); 168 169 // Lex initially to get the string. 170 Parser->getLexer().Lex(); 171 172 // "lh" -> Identifier 173 // "#123" -> EndOfStatement (Lexed as a comment since CommentString is "#") 174 SmallVector<AsmToken::TokenKind> ExpectedTokens( 175 {AsmToken::Identifier, AsmToken::EndOfStatement, AsmToken::Eof}); 176 lexAndCheckTokens(AsmStr, ExpectedTokens); 177 } 178 179 // Test if "#" is accepted as an Identifier 180 TEST_F(SystemZAsmLexerTest, CheckAllowHashInIdentifier) { 181 StringRef AsmStr = "lh#123"; 182 183 // Setup. 184 setupCallToAsmParser(AsmStr); 185 Parser->getLexer().setAllowHashInIdentifier(true); 186 187 // Lex initially to get the string. 188 Parser->getLexer().Lex(); 189 190 // "lh123" -> Identifier 191 SmallVector<AsmToken::TokenKind> ExpectedTokens( 192 {AsmToken::Identifier, AsmToken::EndOfStatement, AsmToken::Eof}); 193 lexAndCheckTokens(AsmStr, ExpectedTokens); 194 } 195 196 TEST_F(SystemZAsmLexerTest, CheckAllowHashInIdentifier2) { 197 StringRef AsmStr = "lh#12*3"; 198 199 // Setup. 200 MUPMAI->setCommentString("*"); 201 MUPMAI->setRestrictCommentStringToStartOfStatement(true); 202 setupCallToAsmParser(AsmStr); 203 Parser->getLexer().setAllowHashInIdentifier(true); 204 205 // Lex initially to get the string. 206 Parser->getLexer().Lex(); 207 208 // "lh#12" -> Identifier 209 // "*" -> Star 210 // "3" -> Integer 211 SmallVector<AsmToken::TokenKind> ExpectedTokens( 212 {AsmToken::Identifier, AsmToken::Star, AsmToken::Integer, 213 AsmToken::EndOfStatement, AsmToken::Eof}); 214 lexAndCheckTokens(AsmStr, ExpectedTokens); 215 } 216 } // end anonymous namespace 217