1 #include "AArch64Subtarget.h" 2 #include "AArch64TargetMachine.h" 3 #include "llvm/CodeGen/MIRParser/MIRParser.h" 4 #include "llvm/CodeGen/MachineModuleInfo.h" 5 #include "llvm/Support/TargetRegistry.h" 6 #include "llvm/Support/TargetSelect.h" 7 8 #include "gtest/gtest.h" 9 10 using namespace llvm; 11 12 namespace { 13 std::unique_ptr<LLVMTargetMachine> createTargetMachine() { 14 auto TT(Triple::normalize("aarch64--")); 15 std::string CPU("generic"); 16 std::string FS(""); 17 18 LLVMInitializeAArch64TargetInfo(); 19 LLVMInitializeAArch64Target(); 20 LLVMInitializeAArch64TargetMC(); 21 22 std::string Error; 23 const Target *TheTarget = TargetRegistry::lookupTarget(TT, Error); 24 25 return std::unique_ptr<LLVMTargetMachine>(static_cast<LLVMTargetMachine*>( 26 TheTarget->createTargetMachine(TT, CPU, FS, TargetOptions(), None, None, 27 CodeGenOpt::Default))); 28 } 29 30 std::unique_ptr<AArch64InstrInfo> createInstrInfo(TargetMachine *TM) { 31 AArch64Subtarget ST(TM->getTargetTriple(), TM->getTargetCPU(), 32 TM->getTargetFeatureString(), *TM, /* isLittle */ false); 33 return std::make_unique<AArch64InstrInfo>(ST); 34 } 35 36 /// The \p InputIRSnippet is only needed for things that can't be expressed in 37 /// the \p InputMIRSnippet (global variables etc) 38 /// TODO: Some of this might be useful for other architectures as well - extract 39 /// the platform-independent parts somewhere they can be reused. 40 void runChecks( 41 LLVMTargetMachine *TM, AArch64InstrInfo *II, const StringRef InputIRSnippet, 42 const StringRef InputMIRSnippet, 43 std::function<void(AArch64InstrInfo &, MachineFunction &)> Checks) { 44 LLVMContext Context; 45 46 auto MIRString = 47 "--- |\n" 48 " declare void @sizes()\n" 49 + InputIRSnippet.str() + 50 "...\n" 51 "---\n" 52 "name: sizes\n" 53 "body: |\n" 54 " bb.0:\n" 55 + InputMIRSnippet.str(); 56 57 std::unique_ptr<MemoryBuffer> MBuffer = MemoryBuffer::getMemBuffer(MIRString); 58 std::unique_ptr<MIRParser> MParser = 59 createMIRParser(std::move(MBuffer), Context); 60 ASSERT_TRUE(MParser); 61 62 std::unique_ptr<Module> M = MParser->parseIRModule(); 63 ASSERT_TRUE(M); 64 65 M->setTargetTriple(TM->getTargetTriple().getTriple()); 66 M->setDataLayout(TM->createDataLayout()); 67 68 MachineModuleInfo MMI(TM); 69 bool Res = MParser->parseMachineFunctions(*M, MMI); 70 ASSERT_FALSE(Res); 71 72 auto F = M->getFunction("sizes"); 73 ASSERT_TRUE(F != nullptr); 74 auto &MF = MMI.getOrCreateMachineFunction(*F); 75 76 Checks(*II, MF); 77 } 78 79 } // anonymous namespace 80 81 TEST(InstSizes, STACKMAP) { 82 std::unique_ptr<LLVMTargetMachine> TM = createTargetMachine(); 83 ASSERT_TRUE(TM); 84 std::unique_ptr<AArch64InstrInfo> II = createInstrInfo(TM.get()); 85 86 runChecks(TM.get(), II.get(), "", " STACKMAP 0, 16\n" 87 " STACKMAP 1, 32\n", 88 [](AArch64InstrInfo &II, MachineFunction &MF) { 89 auto I = MF.begin()->begin(); 90 EXPECT_EQ(16u, II.getInstSizeInBytes(*I)); 91 ++I; 92 EXPECT_EQ(32u, II.getInstSizeInBytes(*I)); 93 }); 94 } 95 96 TEST(InstSizes, PATCHPOINT) { 97 std::unique_ptr<LLVMTargetMachine> TM = createTargetMachine(); 98 std::unique_ptr<AArch64InstrInfo> II = createInstrInfo(TM.get()); 99 100 runChecks(TM.get(), II.get(), "", 101 " PATCHPOINT 0, 16, 0, 0, 0, csr_aarch64_aapcs\n" 102 " PATCHPOINT 1, 32, 0, 0, 0, csr_aarch64_aapcs\n", 103 [](AArch64InstrInfo &II, MachineFunction &MF) { 104 auto I = MF.begin()->begin(); 105 EXPECT_EQ(16u, II.getInstSizeInBytes(*I)); 106 ++I; 107 EXPECT_EQ(32u, II.getInstSizeInBytes(*I)); 108 }); 109 } 110 111 TEST(InstSizes, TLSDESC_CALLSEQ) { 112 std::unique_ptr<LLVMTargetMachine> TM = createTargetMachine(); 113 std::unique_ptr<AArch64InstrInfo> II = createInstrInfo(TM.get()); 114 115 runChecks( 116 TM.get(), II.get(), 117 " @ThreadLocalGlobal = external thread_local global i32, align 8\n", 118 " TLSDESC_CALLSEQ target-flags(aarch64-tls) @ThreadLocalGlobal\n", 119 [](AArch64InstrInfo &II, MachineFunction &MF) { 120 auto I = MF.begin()->begin(); 121 EXPECT_EQ(16u, II.getInstSizeInBytes(*I)); 122 }); 123 } 124