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 // Lex initially to get the string. 98 Parser->getLexer().Lex(); 99 } 100 101 void lexAndCheckTokens(StringRef AsmStr, 102 SmallVector<AsmToken::TokenKind> ExpectedTokens) { 103 // Get reference to AsmLexer. 104 MCAsmLexer &Lexer = Parser->getLexer(); 105 // Loop through all expected tokens checking one by one. 106 for (size_t I = 0; I < ExpectedTokens.size(); ++I) { 107 EXPECT_EQ(Lexer.getTok().getKind(), ExpectedTokens[I]); 108 Lexer.Lex(); 109 } 110 } 111 }; 112 113 TEST_F(SystemZAsmLexerTest, CheckDontRestrictCommentStringToStartOfStatement) { 114 StringRef AsmStr = "jne #-4"; 115 116 // Setup. 117 setupCallToAsmParser(AsmStr); 118 119 SmallVector<AsmToken::TokenKind> ExpectedTokens( 120 {AsmToken::Identifier, AsmToken::EndOfStatement}); 121 lexAndCheckTokens(AsmStr /* "jne #-4" */, ExpectedTokens); 122 } 123 124 // Testing MCAsmInfo's RestrictCommentStringToStartOfStatement attribute. 125 TEST_F(SystemZAsmLexerTest, CheckRestrictCommentStringToStartOfStatement) { 126 StringRef AsmStr = "jne #-4"; 127 128 // Setup. 129 MUPMAI->setRestrictCommentStringToStartOfStatement(true); 130 setupCallToAsmParser(AsmStr); 131 132 // When we are restricting the comment string to only the start of the 133 // statement, The sequence of tokens we are expecting are: Identifier - "jne" 134 // Hash - '#' 135 // Minus - '-' 136 // Integer - '4' 137 SmallVector<AsmToken::TokenKind> ExpectedTokens( 138 {AsmToken::Identifier, AsmToken::Hash, AsmToken::Minus, 139 AsmToken::Integer}); 140 lexAndCheckTokens(AsmStr /* "jne #-4" */, ExpectedTokens); 141 } 142 143 // Test HLASM Comment Syntax ('*') 144 TEST_F(SystemZAsmLexerTest, CheckHLASMComment) { 145 StringRef AsmStr = "* lhi 1,10"; 146 147 // Setup. 148 MUPMAI->setCommentString("*"); 149 setupCallToAsmParser(AsmStr); 150 151 SmallVector<AsmToken::TokenKind> ExpectedTokens( 152 {AsmToken::EndOfStatement, AsmToken::Eof}); 153 lexAndCheckTokens(AsmStr /* "* lhi 1,10" */, ExpectedTokens); 154 } 155 } // end anonymous namespace 156