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