1 #include "ARMInstrInfo.h" 2 #include "ARMSubtarget.h" 3 #include "ARMTargetMachine.h" 4 #include "llvm/CodeGen/MIRParser/MIRParser.h" 5 #include "llvm/CodeGen/MachineModuleInfo.h" 6 #include "llvm/IR/Module.h" 7 #include "llvm/MC/TargetRegistry.h" 8 #include "llvm/Support/MemoryBuffer.h" 9 #include "llvm/Support/TargetSelect.h" 10 11 #include "gtest/gtest.h" 12 13 using namespace llvm; 14 15 namespace { 16 /// The \p InputIRSnippet is only needed for things that can't be expressed in 17 /// the \p InputMIRSnippet (global variables etc) 18 /// TODO: Some of this might be useful for other architectures as well - extract 19 /// the platform-independent parts somewhere they can be reused. 20 void runChecks( 21 TargetMachine *TM, const ARMBaseInstrInfo *II, 22 const StringRef InputIRSnippet, const StringRef InputMIRSnippet, 23 unsigned Expected, 24 std::function<void(const ARMBaseInstrInfo &, MachineFunction &, unsigned &)> 25 Checks) { 26 LLVMContext Context; 27 28 auto MIRString = "--- |\n" 29 " declare void @sizes()\n" + 30 InputIRSnippet.str() + 31 "...\n" 32 "---\n" 33 "name: sizes\n" 34 "constants:\n" 35 " - id: 0\n" 36 " value: i32 12345678\n" 37 " alignment: 4\n" 38 "jumpTable:\n" 39 " kind: inline\n" 40 " entries:\n" 41 " - id: 0\n" 42 " blocks: [ '%bb.0' ]\n" 43 "body: |\n" 44 " bb.0:\n" + 45 InputMIRSnippet.str(); 46 47 std::unique_ptr<MemoryBuffer> MBuffer = MemoryBuffer::getMemBuffer(MIRString); 48 std::unique_ptr<MIRParser> MParser = 49 createMIRParser(std::move(MBuffer), Context); 50 ASSERT_TRUE(MParser); 51 52 std::unique_ptr<Module> M = MParser->parseIRModule(); 53 ASSERT_TRUE(M); 54 55 M->setTargetTriple(TM->getTargetTriple().getTriple()); 56 M->setDataLayout(TM->createDataLayout()); 57 58 MachineModuleInfo MMI(TM); 59 bool Res = MParser->parseMachineFunctions(*M, MMI); 60 ASSERT_FALSE(Res); 61 62 auto F = M->getFunction("sizes"); 63 ASSERT_TRUE(F != nullptr); 64 auto &MF = MMI.getOrCreateMachineFunction(*F); 65 66 Checks(*II, MF, Expected); 67 } 68 69 } // anonymous namespace 70 71 TEST(InstSizes, PseudoInst) { 72 LLVMInitializeARMTargetInfo(); 73 LLVMInitializeARMTarget(); 74 LLVMInitializeARMTargetMC(); 75 76 auto TT(Triple::normalize("thumbv8.1m.main-none-none-eabi")); 77 std::string Error; 78 const Target *T = TargetRegistry::lookupTarget(TT, Error); 79 if (!T) { 80 dbgs() << Error; 81 GTEST_SKIP(); 82 } 83 84 TargetOptions Options; 85 auto TM = std::unique_ptr<TargetMachine>( 86 T->createTargetMachine(TT, "generic", "", Options, std::nullopt, 87 std::nullopt, CodeGenOptLevel::Default)); 88 ARMSubtarget ST(TM->getTargetTriple(), std::string(TM->getTargetCPU()), 89 std::string(TM->getTargetFeatureString()), 90 *static_cast<const ARMBaseTargetMachine *>(TM.get()), false); 91 const ARMBaseInstrInfo *II = ST.getInstrInfo(); 92 93 auto cmpInstSize = [](const ARMBaseInstrInfo &II, MachineFunction &MF, 94 unsigned &Expected) { 95 auto I = MF.begin()->begin(); 96 EXPECT_EQ(Expected, II.getInstSizeInBytes(*I)); 97 }; 98 99 runChecks(TM.get(), II, "", 100 " $r0 = MOVi16_ga_pcrel" 101 " target-flags(arm-lo16, arm-nonlazy) @sizes, 0\n", 102 4u, cmpInstSize); 103 104 runChecks(TM.get(), II, "", 105 " $r0 = MOVTi16_ga_pcrel $r0," 106 " target-flags(arm-hi16, arm-nonlazy) @sizes, 0\n", 107 4u, cmpInstSize); 108 109 runChecks(TM.get(), II, "", 110 " $r0 = t2MOVi16_ga_pcrel" 111 " target-flags(arm-lo16, arm-nonlazy) @sizes, 0\n", 112 4u, cmpInstSize); 113 114 runChecks(TM.get(), II, "", 115 " $r0 = t2MOVTi16_ga_pcrel $r0," 116 " target-flags(arm-hi16, arm-nonlazy) @sizes, 0\n", 117 4u, cmpInstSize); 118 119 runChecks(TM.get(), II, "", " $r0 = MOVi32imm 2\n", 8u, cmpInstSize); 120 121 runChecks(TM.get(), II, "", " $r0 = t2MOVi32imm 2\n", 8u, cmpInstSize); 122 123 runChecks(TM.get(), II, "", 124 " SpeculationBarrierISBDSBEndBB\n" 125 " tBX_RET 14, $noreg, implicit $r0\n", 126 8u, cmpInstSize); 127 128 runChecks(TM.get(), II, "", 129 " t2SpeculationBarrierISBDSBEndBB\n" 130 " tBX_RET 14, $noreg, implicit $r0\n", 131 8u, cmpInstSize); 132 133 runChecks(TM.get(), II, "", 134 " SpeculationBarrierSBEndBB\n" 135 " tBX_RET 14, $noreg, implicit $r0\n", 136 4u, cmpInstSize); 137 138 runChecks(TM.get(), II, "", 139 " t2SpeculationBarrierSBEndBB\n" 140 " tBX_RET 14, $noreg, implicit $r0\n", 141 4u, cmpInstSize); 142 143 runChecks(TM.get(), II, "", 144 " Int_eh_sjlj_longjmp $r0, $r1, implicit-def $r7," 145 " implicit-def $lr, implicit-def $sp\n", 146 16u, cmpInstSize); 147 148 runChecks(TM.get(), II, "", 149 " tInt_eh_sjlj_longjmp $r0, $r1, implicit-def $r7," 150 " implicit-def $lr, implicit-def $sp\n", 151 10u, cmpInstSize); 152 153 runChecks(TM.get(), II, "", 154 " tInt_WIN_eh_sjlj_longjmp $r0, $r1, implicit-def $r11," 155 " implicit-def $lr, implicit-def $sp\n", 156 12u, cmpInstSize); 157 158 runChecks(TM.get(), II, "", 159 " Int_eh_sjlj_setjmp $r0, $r1, implicit-def $r0," 160 " implicit-def $r1, implicit-def $r2, implicit-def $r3," 161 " implicit-def $r4, implicit-def $r5, implicit-def $r6," 162 " implicit-def $r7, implicit-def $r8, implicit-def $r9," 163 " implicit-def $r10, implicit-def $r11, implicit-def $r12," 164 " implicit-def $lr, implicit-def $cpsr, implicit-def $q0," 165 " implicit-def $q1, implicit-def $q2, implicit-def $q3," 166 " implicit-def $q4, implicit-def $q5, implicit-def $q6," 167 " implicit-def $q7, implicit-def $q8, implicit-def $q9," 168 " implicit-def $q10, implicit-def $q11, implicit-def $q12," 169 " implicit-def $q13, implicit-def $q14, implicit-def $q15\n" 170 " tBX_RET 14, $noreg, implicit $r0\n", 171 20u, cmpInstSize); 172 173 runChecks(TM.get(), II, "", 174 " Int_eh_sjlj_setjmp_nofp $r0, $r1, implicit-def $r0," 175 " implicit-def $r1, implicit-def $r2, implicit-def $r3," 176 " implicit-def $r4, implicit-def $r5, implicit-def $r6," 177 " implicit-def $r7, implicit-def $r8, implicit-def $r9," 178 " implicit-def $r10, implicit-def $r11, implicit-def $r12," 179 " implicit-def $lr, implicit-def $cpsr\n" 180 " tBX_RET 14, $noreg, implicit $r0\n", 181 20u, cmpInstSize); 182 183 runChecks(TM.get(), II, "", 184 " tInt_eh_sjlj_setjmp $r0, $r1, implicit-def $r0," 185 " implicit-def $r1, implicit-def $r2, implicit-def $r3," 186 " implicit-def $r4, implicit-def $r5, implicit-def $r6," 187 " implicit-def $r7, implicit-def $r12, implicit-def $cpsr\n" 188 " tBX_RET 14, $noreg, implicit $r0\n", 189 12u, cmpInstSize); 190 191 runChecks(TM.get(), II, "", 192 " t2Int_eh_sjlj_setjmp $r0, $r1, implicit-def $r0," 193 " implicit-def $r1, implicit-def $r2, implicit-def $r3," 194 " implicit-def $r4, implicit-def $r5, implicit-def $r6," 195 " implicit-def $r7, implicit-def $r8, implicit-def $r9," 196 " implicit-def $r10, implicit-def $r11, implicit-def $r12," 197 " implicit-def $lr, implicit-def $cpsr, implicit-def $q0," 198 " implicit-def $q1, implicit-def $q2, implicit-def $q3," 199 " implicit-def $q8, implicit-def $q9, implicit-def $q10," 200 " implicit-def $q11, implicit-def $q12, implicit-def $q13," 201 " implicit-def $q14, implicit-def $q15\n" 202 " tBX_RET 14, $noreg, implicit $r0\n", 203 12u, cmpInstSize); 204 205 runChecks(TM.get(), II, "", 206 " t2Int_eh_sjlj_setjmp_nofp $r0, $r1, implicit-def $r0," 207 " implicit-def $r1, implicit-def $r2, implicit-def $r3," 208 " implicit-def $r4, implicit-def $r5, implicit-def $r6," 209 " implicit-def $r7, implicit-def $r8, implicit-def $r9," 210 " implicit-def $r10, implicit-def $r11, implicit-def $r12," 211 " implicit-def $lr, implicit-def $cpsr\n" 212 " tBX_RET 14, $noreg, implicit $r0\n", 213 12u, cmpInstSize); 214 215 runChecks(TM.get(), II, "", " CONSTPOOL_ENTRY 3, %const.0, 8\n", 8u, 216 cmpInstSize); 217 218 runChecks(TM.get(), II, "", " JUMPTABLE_ADDRS 0, %jump-table.0, 123\n", 123u, 219 cmpInstSize); 220 221 runChecks(TM.get(), II, "", " JUMPTABLE_INSTS 0, %jump-table.0, 456\n", 456u, 222 cmpInstSize); 223 224 runChecks(TM.get(), II, "", " JUMPTABLE_TBB 0, %jump-table.0, 789\n", 789u, 225 cmpInstSize); 226 227 runChecks(TM.get(), II, "", " JUMPTABLE_TBH 0, %jump-table.0, 188\n", 188u, 228 cmpInstSize); 229 230 runChecks(TM.get(), II, "", " $r0 = SPACE 40, undef $r0\n", 40u, 231 cmpInstSize); 232 233 runChecks(TM.get(), II, "", " INLINEASM &\"movs r0, #42\", 1\n", 6u, 234 cmpInstSize); 235 236 runChecks(TM.get(), II, 237 " define void @foo() {\n" 238 " entry:\n" 239 " ret void\n" 240 " }\n", 241 " INLINEASM_BR &\"b ${0:l}\", 1, 13, blockaddress(@foo, " 242 "%ir-block.entry)\n", 243 6u, cmpInstSize); 244 } 245