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