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 assert(TheTarget && "Target not registered"); 25 26 return std::unique_ptr<TargetMachine>( 27 TheTarget->createTargetMachine(TT, CPU, FS, TargetOptions(), None, 28 CodeModel::Default, CodeGenOpt::Default)); 29 } 30 31 std::unique_ptr<AArch64InstrInfo> createInstrInfo(TargetMachine *TM) { 32 AArch64Subtarget ST(TM->getTargetTriple(), TM->getTargetCPU(), 33 TM->getTargetFeatureString(), *TM, /* isLittle */ false); 34 return llvm::make_unique<AArch64InstrInfo>(ST); 35 } 36 37 /// The \p InputIRSnippet is only needed for things that can't be expressed in 38 /// the \p InputMIRSnippet (global variables etc) 39 /// TODO: Some of this might be useful for other architectures as well - extract 40 /// the platform-independent parts somewhere they can be reused. 41 void runChecks( 42 TargetMachine *TM, AArch64InstrInfo *II, const StringRef InputIRSnippet, 43 const StringRef InputMIRSnippet, 44 std::function<void(AArch64InstrInfo &, MachineFunction &)> Checks) { 45 LLVMContext Context; 46 47 auto MIRString = 48 "--- |\n" 49 " declare void @sizes()\n" 50 + InputIRSnippet.str() + 51 "...\n" 52 "---\n" 53 "name: sizes\n" 54 "body: |\n" 55 " bb.0:\n" 56 + InputMIRSnippet.str(); 57 58 std::unique_ptr<MemoryBuffer> MBuffer = MemoryBuffer::getMemBuffer(MIRString); 59 std::unique_ptr<MIRParser> MParser = 60 createMIRParser(std::move(MBuffer), Context); 61 assert(MParser && "Couldn't create MIR parser"); 62 63 std::unique_ptr<Module> M = MParser->parseLLVMModule(); 64 assert(M && "Couldn't parse module"); 65 66 M->setTargetTriple(TM->getTargetTriple().getTriple()); 67 M->setDataLayout(TM->createDataLayout()); 68 69 auto F = M->getFunction("sizes"); 70 assert(F && "Couldn't find intended function"); 71 72 MachineModuleInfo MMI(TM); 73 MMI.setMachineFunctionInitializer(MParser.get()); 74 auto &MF = MMI.getMachineFunction(*F); 75 76 Checks(*II, MF); 77 } 78 79 } // anonymous namespace 80 81 TEST(InstSizes, STACKMAP) { 82 std::unique_ptr<TargetMachine> TM = createTargetMachine(); 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