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