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