1 #include "AArch64Subtarget.h" 2 #include "AArch64TargetMachine.h" 3 #include "llvm/CodeGen/MIRParser/MIRParser.h" 4 #include "llvm/CodeGen/MachineModuleInfo.h" 5 #include "llvm/MC/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(), std::string(TM->getTargetCPU()), 32 std::string(TM->getTargetCPU()), 33 std::string(TM->getTargetFeatureString()), *TM, 34 /* isLittle */ false); 35 return std::make_unique<AArch64InstrInfo>(ST); 36 } 37 38 /// The \p InputIRSnippet is only needed for things that can't be expressed in 39 /// the \p InputMIRSnippet (global variables etc) 40 /// TODO: Some of this might be useful for other architectures as well - extract 41 /// the platform-independent parts somewhere they can be reused. 42 void runChecks( 43 LLVMTargetMachine *TM, AArch64InstrInfo *II, const StringRef InputIRSnippet, 44 const StringRef InputMIRSnippet, 45 std::function<void(AArch64InstrInfo &, MachineFunction &)> Checks) { 46 LLVMContext Context; 47 48 auto MIRString = 49 "--- |\n" 50 " declare void @sizes()\n" 51 + InputIRSnippet.str() + 52 "...\n" 53 "---\n" 54 "name: sizes\n" 55 "body: |\n" 56 " bb.0:\n" 57 + InputMIRSnippet.str(); 58 59 std::unique_ptr<MemoryBuffer> MBuffer = MemoryBuffer::getMemBuffer(MIRString); 60 std::unique_ptr<MIRParser> MParser = 61 createMIRParser(std::move(MBuffer), Context); 62 ASSERT_TRUE(MParser); 63 64 std::unique_ptr<Module> M = MParser->parseIRModule(); 65 ASSERT_TRUE(M); 66 67 M->setTargetTriple(TM->getTargetTriple().getTriple()); 68 M->setDataLayout(TM->createDataLayout()); 69 70 MachineModuleInfo MMI(TM); 71 bool Res = MParser->parseMachineFunctions(*M, MMI); 72 ASSERT_FALSE(Res); 73 74 auto F = M->getFunction("sizes"); 75 ASSERT_TRUE(F != nullptr); 76 auto &MF = MMI.getOrCreateMachineFunction(*F); 77 78 Checks(*II, MF); 79 } 80 81 } // anonymous namespace 82 83 TEST(InstSizes, Authenticated) { 84 std::unique_ptr<LLVMTargetMachine> TM = createTargetMachine(); 85 ASSERT_TRUE(TM); 86 std::unique_ptr<AArch64InstrInfo> II = createInstrInfo(TM.get()); 87 88 auto isAuthInst = [](AArch64InstrInfo &II, MachineFunction &MF) { 89 auto I = MF.begin()->begin(); 90 EXPECT_EQ(4u, II.getInstSizeInBytes(*I)); 91 EXPECT_TRUE(I->getDesc().isAuthenticated()); 92 }; 93 94 runChecks(TM.get(), II.get(), "", 95 " \n" 96 " BLRAA $x10, $x9\n", 97 isAuthInst); 98 99 runChecks(TM.get(), II.get(), "", 100 " \n" 101 " RETAB implicit $lr, implicit $sp, implicit killed $x0\n", 102 isAuthInst); 103 104 runChecks(TM.get(), II.get(), "", 105 " \n" 106 " frame-destroy AUTIASP implicit-def $lr, implicit killed $lr, implicit $sp\n", 107 isAuthInst); 108 109 runChecks(TM.get(), II.get(), "", 110 " \n" 111 " frame-destroy AUTIBSP implicit-def $lr, implicit killed $lr, implicit $sp\n", 112 isAuthInst); 113 } 114 115 TEST(InstSizes, STACKMAP) { 116 std::unique_ptr<LLVMTargetMachine> TM = createTargetMachine(); 117 ASSERT_TRUE(TM); 118 std::unique_ptr<AArch64InstrInfo> II = createInstrInfo(TM.get()); 119 120 runChecks(TM.get(), II.get(), "", " STACKMAP 0, 16\n" 121 " STACKMAP 1, 32\n", 122 [](AArch64InstrInfo &II, MachineFunction &MF) { 123 auto I = MF.begin()->begin(); 124 EXPECT_EQ(16u, II.getInstSizeInBytes(*I)); 125 ++I; 126 EXPECT_EQ(32u, II.getInstSizeInBytes(*I)); 127 }); 128 } 129 130 TEST(InstSizes, PATCHPOINT) { 131 std::unique_ptr<LLVMTargetMachine> TM = createTargetMachine(); 132 std::unique_ptr<AArch64InstrInfo> II = createInstrInfo(TM.get()); 133 134 runChecks(TM.get(), II.get(), "", 135 " PATCHPOINT 0, 16, 0, 0, 0, csr_aarch64_aapcs\n" 136 " PATCHPOINT 1, 32, 0, 0, 0, csr_aarch64_aapcs\n", 137 [](AArch64InstrInfo &II, MachineFunction &MF) { 138 auto I = MF.begin()->begin(); 139 EXPECT_EQ(16u, II.getInstSizeInBytes(*I)); 140 ++I; 141 EXPECT_EQ(32u, II.getInstSizeInBytes(*I)); 142 }); 143 } 144 145 TEST(InstSizes, TLSDESC_CALLSEQ) { 146 std::unique_ptr<LLVMTargetMachine> TM = createTargetMachine(); 147 std::unique_ptr<AArch64InstrInfo> II = createInstrInfo(TM.get()); 148 149 runChecks( 150 TM.get(), II.get(), 151 " @ThreadLocalGlobal = external thread_local global i32, align 8\n", 152 " TLSDESC_CALLSEQ target-flags(aarch64-tls) @ThreadLocalGlobal\n", 153 [](AArch64InstrInfo &II, MachineFunction &MF) { 154 auto I = MF.begin()->begin(); 155 EXPECT_EQ(16u, II.getInstSizeInBytes(*I)); 156 }); 157 } 158