blob: b34e125866a6a38d7b5b593b2f2f2a77d57ff008 [file] [log] [blame]
Andreas Gampe5a4fa822014-03-31 16:50:12 -07001/*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#ifndef ART_COMPILER_UTILS_ASSEMBLER_TEST_H_
18#define ART_COMPILER_UTILS_ASSEMBLER_TEST_H_
19
20#include "assembler.h"
21
Andreas Gampe03b9ee42015-04-24 21:41:45 -070022#include "assembler_test_base.h"
Andreas Gampeb40c6a72014-05-02 14:25:12 -070023#include "common_runtime_test.h" // For ScratchFile
Andreas Gampe5a4fa822014-03-31 16:50:12 -070024
25#include <cstdio>
26#include <cstdlib>
27#include <fstream>
Andreas Gampe5a4fa822014-03-31 16:50:12 -070028#include <iterator>
29#include <sys/stat.h>
30
31namespace art {
32
Andreas Gampe851df202014-11-12 14:05:46 -080033// Helper for a constexpr string length.
34constexpr size_t ConstexprStrLen(char const* str, size_t count = 0) {
35 return ('\0' == str[0]) ? count : ConstexprStrLen(str+1, count+1);
36}
37
Andreas Gampe849cc5e2014-11-18 13:46:46 -080038enum class RegisterView { // private
39 kUsePrimaryName,
Chao-ying Fud23840d2015-04-07 16:03:04 -070040 kUseSecondaryName,
41 kUseTertiaryName,
42 kUseQuaternaryName,
Andreas Gampe849cc5e2014-11-18 13:46:46 -080043};
44
Andreas Gampe851df202014-11-12 14:05:46 -080045template<typename Ass, typename Reg, typename FPReg, typename Imm>
Andreas Gampe5a4fa822014-03-31 16:50:12 -070046class AssemblerTest : public testing::Test {
47 public:
48 Ass* GetAssembler() {
49 return assembler_.get();
50 }
51
Andreas Gampe851df202014-11-12 14:05:46 -080052 typedef std::string (*TestFn)(AssemblerTest* assembler_test, Ass* assembler);
Andreas Gampe5a4fa822014-03-31 16:50:12 -070053
Andreas Gampe2e965ac2016-11-03 17:24:15 -070054 void DriverFn(TestFn f, const std::string& test_name) {
Andreas Gampe03b9ee42015-04-24 21:41:45 -070055 DriverWrapper(f(this, assembler_.get()), test_name);
Andreas Gampe5a4fa822014-03-31 16:50:12 -070056 }
57
58 // This driver assumes the assembler has already been called.
Andreas Gampe2e965ac2016-11-03 17:24:15 -070059 void DriverStr(const std::string& assembly_string, const std::string& test_name) {
Andreas Gampe03b9ee42015-04-24 21:41:45 -070060 DriverWrapper(assembly_string, test_name);
Andreas Gampe5a4fa822014-03-31 16:50:12 -070061 }
62
Andreas Gampe2e965ac2016-11-03 17:24:15 -070063 std::string RepeatR(void (Ass::*f)(Reg), const std::string& fmt) {
Andreas Gampe851df202014-11-12 14:05:46 -080064 return RepeatTemplatedRegister<Reg>(f,
65 GetRegisters(),
66 &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
67 fmt);
68 }
Andreas Gampe5a4fa822014-03-31 16:50:12 -070069
Andreas Gampe2e965ac2016-11-03 17:24:15 -070070 std::string Repeatr(void (Ass::*f)(Reg), const std::string& fmt) {
Andreas Gampe851df202014-11-12 14:05:46 -080071 return RepeatTemplatedRegister<Reg>(f,
72 GetRegisters(),
73 &AssemblerTest::GetRegName<RegisterView::kUseSecondaryName>,
74 fmt);
Andreas Gampe5a4fa822014-03-31 16:50:12 -070075 }
76
Andreas Gampe2e965ac2016-11-03 17:24:15 -070077 std::string RepeatRR(void (Ass::*f)(Reg, Reg), const std::string& fmt) {
Andreas Gampe851df202014-11-12 14:05:46 -080078 return RepeatTemplatedRegisters<Reg, Reg>(f,
79 GetRegisters(),
80 GetRegisters(),
81 &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
82 &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
83 fmt);
84 }
Andreas Gampe5a4fa822014-03-31 16:50:12 -070085
Andreas Gampe2e965ac2016-11-03 17:24:15 -070086 std::string RepeatRRNoDupes(void (Ass::*f)(Reg, Reg), const std::string& fmt) {
Chris Larsen51417632015-10-02 13:24:25 -070087 return RepeatTemplatedRegistersNoDupes<Reg, Reg>(f,
88 GetRegisters(),
89 GetRegisters(),
90 &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
91 &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
92 fmt);
93 }
94
Andreas Gampe2e965ac2016-11-03 17:24:15 -070095 std::string Repeatrr(void (Ass::*f)(Reg, Reg), const std::string& fmt) {
Andreas Gampe851df202014-11-12 14:05:46 -080096 return RepeatTemplatedRegisters<Reg, Reg>(f,
97 GetRegisters(),
98 GetRegisters(),
99 &AssemblerTest::GetRegName<RegisterView::kUseSecondaryName>,
100 &AssemblerTest::GetRegName<RegisterView::kUseSecondaryName>,
101 fmt);
102 }
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700103
Andreas Gampe2e965ac2016-11-03 17:24:15 -0700104 std::string RepeatRRR(void (Ass::*f)(Reg, Reg, Reg), const std::string& fmt) {
Chris Larsendbce0d72015-09-17 13:34:00 -0700105 return RepeatTemplatedRegisters<Reg, Reg, Reg>(f,
106 GetRegisters(),
107 GetRegisters(),
108 GetRegisters(),
109 &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
110 &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
111 &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
112 fmt);
113 }
114
Andreas Gampe2e965ac2016-11-03 17:24:15 -0700115 std::string Repeatrb(void (Ass::*f)(Reg, Reg), const std::string& fmt) {
Chao-ying Fud23840d2015-04-07 16:03:04 -0700116 return RepeatTemplatedRegisters<Reg, Reg>(f,
117 GetRegisters(),
118 GetRegisters(),
119 &AssemblerTest::GetRegName<RegisterView::kUseSecondaryName>,
120 &AssemblerTest::GetRegName<RegisterView::kUseQuaternaryName>,
121 fmt);
122 }
123
Andreas Gampe2e965ac2016-11-03 17:24:15 -0700124 std::string RepeatRr(void (Ass::*f)(Reg, Reg), const std::string& fmt) {
Andreas Gampe851df202014-11-12 14:05:46 -0800125 return RepeatTemplatedRegisters<Reg, Reg>(f,
126 GetRegisters(),
127 GetRegisters(),
128 &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
129 &AssemblerTest::GetRegName<RegisterView::kUseSecondaryName>,
130 fmt);
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700131 }
132
Andreas Gampe2e965ac2016-11-03 17:24:15 -0700133 std::string RepeatRI(void (Ass::*f)(Reg, const Imm&), size_t imm_bytes, const std::string& fmt) {
Andreas Gampe851df202014-11-12 14:05:46 -0800134 return RepeatRegisterImm<RegisterView::kUsePrimaryName>(f, imm_bytes, fmt);
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700135 }
136
Andreas Gampe2e965ac2016-11-03 17:24:15 -0700137 std::string Repeatri(void (Ass::*f)(Reg, const Imm&), size_t imm_bytes, const std::string& fmt) {
Andreas Gampe851df202014-11-12 14:05:46 -0800138 return RepeatRegisterImm<RegisterView::kUseSecondaryName>(f, imm_bytes, fmt);
139 }
140
Goran Jakovljevic8c434dc2015-08-26 14:39:44 +0200141 template <typename Reg1, typename Reg2, typename ImmType>
142 std::string RepeatTemplatedRegistersImmBits(void (Ass::*f)(Reg1, Reg2, ImmType),
143 int imm_bits,
144 const std::vector<Reg1*> reg1_registers,
145 const std::vector<Reg2*> reg2_registers,
146 std::string (AssemblerTest::*GetName1)(const Reg1&),
147 std::string (AssemblerTest::*GetName2)(const Reg2&),
Andreas Gampe2e965ac2016-11-03 17:24:15 -0700148 const std::string& fmt) {
Chris Larsendbce0d72015-09-17 13:34:00 -0700149 std::string str;
Alexey Frunzecd7b0ee2015-12-03 16:46:38 -0800150 std::vector<int64_t> imms = CreateImmediateValuesBits(abs(imm_bits), (imm_bits > 0));
Chris Larsendbce0d72015-09-17 13:34:00 -0700151
152 for (auto reg1 : reg1_registers) {
153 for (auto reg2 : reg2_registers) {
154 for (int64_t imm : imms) {
155 ImmType new_imm = CreateImmediate(imm);
156 (assembler_.get()->*f)(*reg1, *reg2, new_imm);
157 std::string base = fmt;
158
Goran Jakovljevic8c434dc2015-08-26 14:39:44 +0200159 std::string reg1_string = (this->*GetName1)(*reg1);
Chris Larsendbce0d72015-09-17 13:34:00 -0700160 size_t reg1_index;
161 while ((reg1_index = base.find(REG1_TOKEN)) != std::string::npos) {
162 base.replace(reg1_index, ConstexprStrLen(REG1_TOKEN), reg1_string);
163 }
164
Goran Jakovljevic8c434dc2015-08-26 14:39:44 +0200165 std::string reg2_string = (this->*GetName2)(*reg2);
Chris Larsendbce0d72015-09-17 13:34:00 -0700166 size_t reg2_index;
167 while ((reg2_index = base.find(REG2_TOKEN)) != std::string::npos) {
168 base.replace(reg2_index, ConstexprStrLen(REG2_TOKEN), reg2_string);
169 }
170
171 size_t imm_index = base.find(IMM_TOKEN);
172 if (imm_index != std::string::npos) {
173 std::ostringstream sreg;
174 sreg << imm;
175 std::string imm_string = sreg.str();
176 base.replace(imm_index, ConstexprStrLen(IMM_TOKEN), imm_string);
177 }
178
179 if (str.size() > 0) {
180 str += "\n";
181 }
182 str += base;
183 }
184 }
185 }
186 // Add a newline at the end.
187 str += "\n";
188 return str;
189 }
190
Alexey Frunzecd7b0ee2015-12-03 16:46:38 -0800191 template <typename ImmType, typename Reg1, typename Reg2>
192 std::string RepeatTemplatedImmBitsRegisters(void (Ass::*f)(ImmType, Reg1, Reg2),
193 const std::vector<Reg1*> reg1_registers,
194 const std::vector<Reg2*> reg2_registers,
195 std::string (AssemblerTest::*GetName1)(const Reg1&),
196 std::string (AssemblerTest::*GetName2)(const Reg2&),
197 int imm_bits,
Andreas Gampe2e965ac2016-11-03 17:24:15 -0700198 const std::string& fmt) {
Alexey Frunzecd7b0ee2015-12-03 16:46:38 -0800199 std::vector<int64_t> imms = CreateImmediateValuesBits(abs(imm_bits), (imm_bits > 0));
200
201 WarnOnCombinations(reg1_registers.size() * reg2_registers.size() * imms.size());
202
203 std::string str;
204 for (auto reg1 : reg1_registers) {
205 for (auto reg2 : reg2_registers) {
206 for (int64_t imm : imms) {
207 ImmType new_imm = CreateImmediate(imm);
208 (assembler_.get()->*f)(new_imm, *reg1, *reg2);
209 std::string base = fmt;
210
211 std::string reg1_string = (this->*GetName1)(*reg1);
212 size_t reg1_index;
213 while ((reg1_index = base.find(REG1_TOKEN)) != std::string::npos) {
214 base.replace(reg1_index, ConstexprStrLen(REG1_TOKEN), reg1_string);
215 }
216
217 std::string reg2_string = (this->*GetName2)(*reg2);
218 size_t reg2_index;
219 while ((reg2_index = base.find(REG2_TOKEN)) != std::string::npos) {
220 base.replace(reg2_index, ConstexprStrLen(REG2_TOKEN), reg2_string);
221 }
222
223 size_t imm_index = base.find(IMM_TOKEN);
224 if (imm_index != std::string::npos) {
225 std::ostringstream sreg;
226 sreg << imm;
227 std::string imm_string = sreg.str();
228 base.replace(imm_index, ConstexprStrLen(IMM_TOKEN), imm_string);
229 }
230
231 if (str.size() > 0) {
232 str += "\n";
233 }
234 str += base;
235 }
236 }
237 }
238 // Add a newline at the end.
239 str += "\n";
240 return str;
241 }
242
Goran Jakovljevic8c434dc2015-08-26 14:39:44 +0200243 template <typename RegType, typename ImmType>
244 std::string RepeatTemplatedRegisterImmBits(void (Ass::*f)(RegType, ImmType),
Alexey Frunzecd7b0ee2015-12-03 16:46:38 -0800245 int imm_bits,
246 const std::vector<Reg*> registers,
247 std::string (AssemblerTest::*GetName)(const RegType&),
Andreas Gampe2e965ac2016-11-03 17:24:15 -0700248 const std::string& fmt) {
Goran Jakovljevic8c434dc2015-08-26 14:39:44 +0200249 std::string str;
Alexey Frunzecd7b0ee2015-12-03 16:46:38 -0800250 std::vector<int64_t> imms = CreateImmediateValuesBits(abs(imm_bits), (imm_bits > 0));
Goran Jakovljevic8c434dc2015-08-26 14:39:44 +0200251
252 for (auto reg : registers) {
253 for (int64_t imm : imms) {
254 ImmType new_imm = CreateImmediate(imm);
255 (assembler_.get()->*f)(*reg, new_imm);
256 std::string base = fmt;
257
258 std::string reg_string = (this->*GetName)(*reg);
259 size_t reg_index;
260 while ((reg_index = base.find(REG_TOKEN)) != std::string::npos) {
261 base.replace(reg_index, ConstexprStrLen(REG_TOKEN), reg_string);
262 }
263
264 size_t imm_index = base.find(IMM_TOKEN);
265 if (imm_index != std::string::npos) {
266 std::ostringstream sreg;
267 sreg << imm;
268 std::string imm_string = sreg.str();
269 base.replace(imm_index, ConstexprStrLen(IMM_TOKEN), imm_string);
270 }
271
272 if (str.size() > 0) {
273 str += "\n";
274 }
275 str += base;
276 }
277 }
278 // Add a newline at the end.
279 str += "\n";
280 return str;
281 }
282
283 template <typename ImmType>
Andreas Gampe2e965ac2016-11-03 17:24:15 -0700284 std::string RepeatRRIb(void (Ass::*f)(Reg, Reg, ImmType), int imm_bits, const std::string& fmt) {
Goran Jakovljevic8c434dc2015-08-26 14:39:44 +0200285 return RepeatTemplatedRegistersImmBits<Reg, Reg, ImmType>(f,
286 imm_bits,
287 GetRegisters(),
288 GetRegisters(),
289 &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
290 &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
291 fmt);
292 }
293
294 template <typename ImmType>
Andreas Gampe2e965ac2016-11-03 17:24:15 -0700295 std::string RepeatRIb(void (Ass::*f)(Reg, ImmType), int imm_bits, const std::string& fmt) {
Goran Jakovljevic8c434dc2015-08-26 14:39:44 +0200296 return RepeatTemplatedRegisterImmBits<Reg, ImmType>(f,
297 imm_bits,
298 GetRegisters(),
299 &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
300 fmt);
301 }
302
303 template <typename ImmType>
Andreas Gampe2e965ac2016-11-03 17:24:15 -0700304 std::string RepeatFRIb(void (Ass::*f)(FPReg, Reg, ImmType),
305 int imm_bits,
306 const std::string& fmt) {
Goran Jakovljevic8c434dc2015-08-26 14:39:44 +0200307 return RepeatTemplatedRegistersImmBits<FPReg, Reg, ImmType>(f,
308 imm_bits,
309 GetFPRegisters(),
310 GetRegisters(),
311 &AssemblerTest::GetFPRegName,
312 &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
313 fmt);
Chris Larsendbce0d72015-09-17 13:34:00 -0700314 }
315
Andreas Gampe2e965ac2016-11-03 17:24:15 -0700316 std::string RepeatFF(void (Ass::*f)(FPReg, FPReg), const std::string& fmt) {
Andreas Gampe851df202014-11-12 14:05:46 -0800317 return RepeatTemplatedRegisters<FPReg, FPReg>(f,
318 GetFPRegisters(),
319 GetFPRegisters(),
320 &AssemblerTest::GetFPRegName,
321 &AssemblerTest::GetFPRegName,
322 fmt);
323 }
324
Andreas Gampe2e965ac2016-11-03 17:24:15 -0700325 std::string RepeatFFF(void (Ass::*f)(FPReg, FPReg, FPReg), const std::string& fmt) {
Chris Larsendbce0d72015-09-17 13:34:00 -0700326 return RepeatTemplatedRegisters<FPReg, FPReg, FPReg>(f,
327 GetFPRegisters(),
328 GetFPRegisters(),
329 GetFPRegisters(),
330 &AssemblerTest::GetFPRegName,
331 &AssemblerTest::GetFPRegName,
332 &AssemblerTest::GetFPRegName,
333 fmt);
334 }
335
Andreas Gampe2e965ac2016-11-03 17:24:15 -0700336 std::string RepeatFFR(void (Ass::*f)(FPReg, FPReg, Reg), const std::string& fmt) {
Alexey Frunze674b9ee2016-09-20 14:54:15 -0700337 return RepeatTemplatedRegisters<FPReg, FPReg, Reg>(
338 f,
339 GetFPRegisters(),
340 GetFPRegisters(),
341 GetRegisters(),
342 &AssemblerTest::GetFPRegName,
343 &AssemblerTest::GetFPRegName,
344 &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
345 fmt);
346 }
347
Chris Larsendbce0d72015-09-17 13:34:00 -0700348 std::string RepeatFFI(void (Ass::*f)(FPReg, FPReg, const Imm&),
349 size_t imm_bytes,
Andreas Gampe2e965ac2016-11-03 17:24:15 -0700350 const std::string& fmt) {
Mark Mendellfb8d2792015-03-31 22:16:59 -0400351 return RepeatTemplatedRegistersImm<FPReg, FPReg>(f,
Chris Larsendbce0d72015-09-17 13:34:00 -0700352 GetFPRegisters(),
353 GetFPRegisters(),
354 &AssemblerTest::GetFPRegName,
355 &AssemblerTest::GetFPRegName,
356 imm_bytes,
357 fmt);
Mark Mendellfb8d2792015-03-31 22:16:59 -0400358 }
359
Alexey Frunzecd7b0ee2015-12-03 16:46:38 -0800360 template <typename ImmType>
Andreas Gampe2e965ac2016-11-03 17:24:15 -0700361 std::string RepeatFFIb(void (Ass::*f)(FPReg, FPReg, ImmType),
362 int imm_bits,
363 const std::string& fmt) {
Alexey Frunzea8aaf5a2016-06-27 14:48:20 -0700364 return RepeatTemplatedRegistersImmBits<FPReg, FPReg, ImmType>(f,
365 imm_bits,
366 GetFPRegisters(),
367 GetFPRegisters(),
368 &AssemblerTest::GetFPRegName,
369 &AssemblerTest::GetFPRegName,
370 fmt);
371 }
372
373 template <typename ImmType>
Andreas Gampe2e965ac2016-11-03 17:24:15 -0700374 std::string RepeatIbFF(void (Ass::*f)(ImmType, FPReg, FPReg),
375 int imm_bits,
376 const std::string& fmt) {
Alexey Frunzecd7b0ee2015-12-03 16:46:38 -0800377 return RepeatTemplatedImmBitsRegisters<ImmType, FPReg, FPReg>(f,
378 GetFPRegisters(),
379 GetFPRegisters(),
380 &AssemblerTest::GetFPRegName,
381 &AssemblerTest::GetFPRegName,
382 imm_bits,
383 fmt);
384 }
385
Andreas Gampe2e965ac2016-11-03 17:24:15 -0700386 std::string RepeatFR(void (Ass::*f)(FPReg, Reg), const std::string& fmt) {
Andreas Gampe851df202014-11-12 14:05:46 -0800387 return RepeatTemplatedRegisters<FPReg, Reg>(f,
388 GetFPRegisters(),
389 GetRegisters(),
390 &AssemblerTest::GetFPRegName,
391 &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
392 fmt);
393 }
394
Andreas Gampe2e965ac2016-11-03 17:24:15 -0700395 std::string RepeatFr(void (Ass::*f)(FPReg, Reg), const std::string& fmt) {
Andreas Gampe851df202014-11-12 14:05:46 -0800396 return RepeatTemplatedRegisters<FPReg, Reg>(f,
397 GetFPRegisters(),
398 GetRegisters(),
399 &AssemblerTest::GetFPRegName,
400 &AssemblerTest::GetRegName<RegisterView::kUseSecondaryName>,
401 fmt);
402 }
403
Andreas Gampe2e965ac2016-11-03 17:24:15 -0700404 std::string RepeatRF(void (Ass::*f)(Reg, FPReg), const std::string& fmt) {
Andreas Gampe851df202014-11-12 14:05:46 -0800405 return RepeatTemplatedRegisters<Reg, FPReg>(f,
406 GetRegisters(),
407 GetFPRegisters(),
408 &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
409 &AssemblerTest::GetFPRegName,
410 fmt);
411 }
412
Andreas Gampe2e965ac2016-11-03 17:24:15 -0700413 std::string RepeatrF(void (Ass::*f)(Reg, FPReg), const std::string& fmt) {
Andreas Gampe851df202014-11-12 14:05:46 -0800414 return RepeatTemplatedRegisters<Reg, FPReg>(f,
415 GetRegisters(),
416 GetFPRegisters(),
417 &AssemblerTest::GetRegName<RegisterView::kUseSecondaryName>,
418 &AssemblerTest::GetFPRegName,
419 fmt);
420 }
421
Andreas Gampe2e965ac2016-11-03 17:24:15 -0700422 std::string RepeatI(void (Ass::*f)(const Imm&),
423 size_t imm_bytes,
424 const std::string& fmt,
Andreas Gampe851df202014-11-12 14:05:46 -0800425 bool as_uint = false) {
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700426 std::string str;
Andreas Gampe851df202014-11-12 14:05:46 -0800427 std::vector<int64_t> imms = CreateImmediateValues(imm_bytes, as_uint);
Andreas Gampe849cc5e2014-11-18 13:46:46 -0800428
429 WarnOnCombinations(imms.size());
430
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700431 for (int64_t imm : imms) {
Ian Rogerscf7f1912014-10-22 22:06:39 -0700432 Imm new_imm = CreateImmediate(imm);
433 (assembler_.get()->*f)(new_imm);
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700434 std::string base = fmt;
435
Andreas Gampe851df202014-11-12 14:05:46 -0800436 size_t imm_index = base.find(IMM_TOKEN);
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700437 if (imm_index != std::string::npos) {
438 std::ostringstream sreg;
439 sreg << imm;
440 std::string imm_string = sreg.str();
Andreas Gampe851df202014-11-12 14:05:46 -0800441 base.replace(imm_index, ConstexprStrLen(IMM_TOKEN), imm_string);
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700442 }
443
444 if (str.size() > 0) {
445 str += "\n";
446 }
447 str += base;
448 }
449 // Add a newline at the end.
450 str += "\n";
451 return str;
452 }
453
454 // This is intended to be run as a test.
455 bool CheckTools() {
Andreas Gampe03b9ee42015-04-24 21:41:45 -0700456 return test_helper_->CheckTools();
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700457 }
458
Andreas Gampe851df202014-11-12 14:05:46 -0800459 // The following functions are public so that TestFn can use them...
460
461 virtual std::vector<Reg*> GetRegisters() = 0;
462
463 virtual std::vector<FPReg*> GetFPRegisters() {
464 UNIMPLEMENTED(FATAL) << "Architecture does not support floating-point registers";
465 UNREACHABLE();
466 }
467
468 // Secondary register names are the secondary view on registers, e.g., 32b on 64b systems.
469 virtual std::string GetSecondaryRegisterName(const Reg& reg ATTRIBUTE_UNUSED) {
470 UNIMPLEMENTED(FATAL) << "Architecture does not support secondary registers";
471 UNREACHABLE();
472 }
473
Chao-ying Fud23840d2015-04-07 16:03:04 -0700474 // Tertiary register names are the tertiary view on registers, e.g., 16b on 64b systems.
475 virtual std::string GetTertiaryRegisterName(const Reg& reg ATTRIBUTE_UNUSED) {
476 UNIMPLEMENTED(FATAL) << "Architecture does not support tertiary registers";
477 UNREACHABLE();
478 }
479
480 // Quaternary register names are the quaternary view on registers, e.g., 8b on 64b systems.
481 virtual std::string GetQuaternaryRegisterName(const Reg& reg ATTRIBUTE_UNUSED) {
482 UNIMPLEMENTED(FATAL) << "Architecture does not support quaternary registers";
483 UNREACHABLE();
484 }
485
Calin Juravle9aec02f2014-11-18 23:06:35 +0000486 std::string GetRegisterName(const Reg& reg) {
487 return GetRegName<RegisterView::kUsePrimaryName>(reg);
488 }
489
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700490 protected:
Andreas Gampe851df202014-11-12 14:05:46 -0800491 explicit AssemblerTest() {}
492
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700493 void SetUp() OVERRIDE {
Vladimir Marko93205e32016-04-13 11:59:46 +0100494 arena_.reset(new ArenaAllocator(&pool_));
Chris Larsen3add9cb2016-04-14 14:01:33 -0700495 assembler_.reset(CreateAssembler(arena_.get()));
Andreas Gampe03b9ee42015-04-24 21:41:45 -0700496 test_helper_.reset(
497 new AssemblerTestInfrastructure(GetArchitectureString(),
498 GetAssemblerCmdName(),
499 GetAssemblerParameters(),
500 GetObjdumpCmdName(),
501 GetObjdumpParameters(),
502 GetDisassembleCmdName(),
503 GetDisassembleParameters(),
504 GetAssemblyHeader()));
Andreas Gampeb40c6a72014-05-02 14:25:12 -0700505
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700506 SetUpHelpers();
507 }
508
Andreas Gampe7747c8d2014-08-06 14:53:03 -0700509 void TearDown() OVERRIDE {
Andreas Gampe03b9ee42015-04-24 21:41:45 -0700510 test_helper_.reset(); // Clean up the helper.
Vladimir Marko93205e32016-04-13 11:59:46 +0100511 assembler_.reset();
512 arena_.reset();
Andreas Gampe7747c8d2014-08-06 14:53:03 -0700513 }
514
Chris Larsen3add9cb2016-04-14 14:01:33 -0700515 // Override this to set up any architecture-specific things, e.g., CPU revision.
516 virtual Ass* CreateAssembler(ArenaAllocator* arena) {
517 return new (arena) Ass(arena);
518 }
519
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700520 // Override this to set up any architecture-specific things, e.g., register vectors.
521 virtual void SetUpHelpers() {}
522
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700523 // Get the typically used name for this architecture, e.g., aarch64, x86_64, ...
524 virtual std::string GetArchitectureString() = 0;
525
526 // Get the name of the assembler, e.g., "as" by default.
527 virtual std::string GetAssemblerCmdName() {
528 return "as";
529 }
530
531 // Switches to the assembler command. Default none.
532 virtual std::string GetAssemblerParameters() {
533 return "";
534 }
535
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700536 // Get the name of the objdump, e.g., "objdump" by default.
537 virtual std::string GetObjdumpCmdName() {
538 return "objdump";
539 }
540
541 // Switches to the objdump command. Default is " -h".
542 virtual std::string GetObjdumpParameters() {
543 return " -h";
544 }
545
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700546 // Get the name of the objdump, e.g., "objdump" by default.
547 virtual std::string GetDisassembleCmdName() {
548 return "objdump";
549 }
550
551 // Switches to the objdump command. As it's a binary, one needs to push the architecture and
552 // such to objdump, so it's architecture-specific and there is no default.
553 virtual std::string GetDisassembleParameters() = 0;
554
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700555 // Create a couple of immediate values up to the number of bytes given.
Andreas Gampe851df202014-11-12 14:05:46 -0800556 virtual std::vector<int64_t> CreateImmediateValues(size_t imm_bytes, bool as_uint = false) {
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700557 std::vector<int64_t> res;
558 res.push_back(0);
Andreas Gampe851df202014-11-12 14:05:46 -0800559 if (!as_uint) {
560 res.push_back(-1);
561 } else {
562 res.push_back(0xFF);
563 }
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700564 res.push_back(0x12);
565 if (imm_bytes >= 2) {
566 res.push_back(0x1234);
Andreas Gampe851df202014-11-12 14:05:46 -0800567 if (!as_uint) {
568 res.push_back(-0x1234);
569 } else {
570 res.push_back(0xFFFF);
571 }
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700572 if (imm_bytes >= 4) {
573 res.push_back(0x12345678);
Andreas Gampe851df202014-11-12 14:05:46 -0800574 if (!as_uint) {
575 res.push_back(-0x12345678);
576 } else {
577 res.push_back(0xFFFFFFFF);
578 }
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700579 if (imm_bytes >= 6) {
580 res.push_back(0x123456789ABC);
Andreas Gampe851df202014-11-12 14:05:46 -0800581 if (!as_uint) {
582 res.push_back(-0x123456789ABC);
583 }
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700584 if (imm_bytes >= 8) {
585 res.push_back(0x123456789ABCDEF0);
Andreas Gampe851df202014-11-12 14:05:46 -0800586 if (!as_uint) {
587 res.push_back(-0x123456789ABCDEF0);
588 } else {
589 res.push_back(0xFFFFFFFFFFFFFFFF);
590 }
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700591 }
592 }
593 }
594 }
595 return res;
596 }
597
Chris Larsendbce0d72015-09-17 13:34:00 -0700598 const int kMaxBitsExhaustiveTest = 8;
599
600 // Create a couple of immediate values up to the number of bits given.
601 virtual std::vector<int64_t> CreateImmediateValuesBits(const int imm_bits, bool as_uint = false) {
602 CHECK_GT(imm_bits, 0);
603 CHECK_LE(imm_bits, 64);
604 std::vector<int64_t> res;
605
606 if (imm_bits <= kMaxBitsExhaustiveTest) {
607 if (as_uint) {
608 for (uint64_t i = MinInt<uint64_t>(imm_bits); i <= MaxInt<uint64_t>(imm_bits); i++) {
609 res.push_back(static_cast<int64_t>(i));
610 }
611 } else {
612 for (int64_t i = MinInt<int64_t>(imm_bits); i <= MaxInt<int64_t>(imm_bits); i++) {
613 res.push_back(i);
614 }
615 }
616 } else {
617 if (as_uint) {
618 for (uint64_t i = MinInt<uint64_t>(kMaxBitsExhaustiveTest);
619 i <= MaxInt<uint64_t>(kMaxBitsExhaustiveTest);
620 i++) {
621 res.push_back(static_cast<int64_t>(i));
622 }
623 for (int i = 0; i <= imm_bits; i++) {
624 uint64_t j = (MaxInt<uint64_t>(kMaxBitsExhaustiveTest) + 1) +
625 ((MaxInt<uint64_t>(imm_bits) -
626 (MaxInt<uint64_t>(kMaxBitsExhaustiveTest) + 1))
627 * i / imm_bits);
628 res.push_back(static_cast<int64_t>(j));
629 }
630 } else {
631 for (int i = 0; i <= imm_bits; i++) {
632 int64_t j = MinInt<int64_t>(imm_bits) +
633 ((((MinInt<int64_t>(kMaxBitsExhaustiveTest) - 1) -
634 MinInt<int64_t>(imm_bits))
635 * i) / imm_bits);
636 res.push_back(static_cast<int64_t>(j));
637 }
638 for (int64_t i = MinInt<int64_t>(kMaxBitsExhaustiveTest);
639 i <= MaxInt<int64_t>(kMaxBitsExhaustiveTest);
640 i++) {
641 res.push_back(static_cast<int64_t>(i));
642 }
643 for (int i = 0; i <= imm_bits; i++) {
644 int64_t j = (MaxInt<int64_t>(kMaxBitsExhaustiveTest) + 1) +
645 ((MaxInt<int64_t>(imm_bits) - (MaxInt<int64_t>(kMaxBitsExhaustiveTest) + 1))
646 * i / imm_bits);
647 res.push_back(static_cast<int64_t>(j));
648 }
649 }
650 }
651
652 return res;
653 }
654
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700655 // Create an immediate from the specific value.
Ian Rogerscf7f1912014-10-22 22:06:39 -0700656 virtual Imm CreateImmediate(int64_t imm_value) = 0;
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700657
Andreas Gampe851df202014-11-12 14:05:46 -0800658 template <typename RegType>
659 std::string RepeatTemplatedRegister(void (Ass::*f)(RegType),
660 const std::vector<RegType*> registers,
661 std::string (AssemblerTest::*GetName)(const RegType&),
Andreas Gampe2e965ac2016-11-03 17:24:15 -0700662 const std::string& fmt) {
Andreas Gampe851df202014-11-12 14:05:46 -0800663 std::string str;
664 for (auto reg : registers) {
665 (assembler_.get()->*f)(*reg);
666 std::string base = fmt;
667
668 std::string reg_string = (this->*GetName)(*reg);
669 size_t reg_index;
670 if ((reg_index = base.find(REG_TOKEN)) != std::string::npos) {
671 base.replace(reg_index, ConstexprStrLen(REG_TOKEN), reg_string);
672 }
673
674 if (str.size() > 0) {
675 str += "\n";
676 }
677 str += base;
678 }
679 // Add a newline at the end.
680 str += "\n";
681 return str;
682 }
683
684 template <typename Reg1, typename Reg2>
685 std::string RepeatTemplatedRegisters(void (Ass::*f)(Reg1, Reg2),
686 const std::vector<Reg1*> reg1_registers,
687 const std::vector<Reg2*> reg2_registers,
688 std::string (AssemblerTest::*GetName1)(const Reg1&),
689 std::string (AssemblerTest::*GetName2)(const Reg2&),
Andreas Gampe2e965ac2016-11-03 17:24:15 -0700690 const std::string& fmt) {
Andreas Gampe849cc5e2014-11-18 13:46:46 -0800691 WarnOnCombinations(reg1_registers.size() * reg2_registers.size());
692
Andreas Gampe851df202014-11-12 14:05:46 -0800693 std::string str;
694 for (auto reg1 : reg1_registers) {
695 for (auto reg2 : reg2_registers) {
696 (assembler_.get()->*f)(*reg1, *reg2);
697 std::string base = fmt;
698
699 std::string reg1_string = (this->*GetName1)(*reg1);
700 size_t reg1_index;
701 while ((reg1_index = base.find(REG1_TOKEN)) != std::string::npos) {
702 base.replace(reg1_index, ConstexprStrLen(REG1_TOKEN), reg1_string);
703 }
704
705 std::string reg2_string = (this->*GetName2)(*reg2);
706 size_t reg2_index;
707 while ((reg2_index = base.find(REG2_TOKEN)) != std::string::npos) {
708 base.replace(reg2_index, ConstexprStrLen(REG2_TOKEN), reg2_string);
709 }
710
711 if (str.size() > 0) {
712 str += "\n";
713 }
714 str += base;
715 }
716 }
717 // Add a newline at the end.
718 str += "\n";
719 return str;
720 }
721
Chris Larsen51417632015-10-02 13:24:25 -0700722 template <typename Reg1, typename Reg2>
723 std::string RepeatTemplatedRegistersNoDupes(void (Ass::*f)(Reg1, Reg2),
724 const std::vector<Reg1*> reg1_registers,
725 const std::vector<Reg2*> reg2_registers,
726 std::string (AssemblerTest::*GetName1)(const Reg1&),
727 std::string (AssemblerTest::*GetName2)(const Reg2&),
Andreas Gampe2e965ac2016-11-03 17:24:15 -0700728 const std::string& fmt) {
Chris Larsen51417632015-10-02 13:24:25 -0700729 WarnOnCombinations(reg1_registers.size() * reg2_registers.size());
730
731 std::string str;
732 for (auto reg1 : reg1_registers) {
733 for (auto reg2 : reg2_registers) {
734 if (reg1 == reg2) continue;
735 (assembler_.get()->*f)(*reg1, *reg2);
736 std::string base = fmt;
737
738 std::string reg1_string = (this->*GetName1)(*reg1);
739 size_t reg1_index;
740 while ((reg1_index = base.find(REG1_TOKEN)) != std::string::npos) {
741 base.replace(reg1_index, ConstexprStrLen(REG1_TOKEN), reg1_string);
742 }
743
744 std::string reg2_string = (this->*GetName2)(*reg2);
745 size_t reg2_index;
746 while ((reg2_index = base.find(REG2_TOKEN)) != std::string::npos) {
747 base.replace(reg2_index, ConstexprStrLen(REG2_TOKEN), reg2_string);
748 }
749
750 if (str.size() > 0) {
751 str += "\n";
752 }
753 str += base;
754 }
755 }
756 // Add a newline at the end.
757 str += "\n";
758 return str;
759 }
760
Chris Larsendbce0d72015-09-17 13:34:00 -0700761 template <typename Reg1, typename Reg2, typename Reg3>
762 std::string RepeatTemplatedRegisters(void (Ass::*f)(Reg1, Reg2, Reg3),
763 const std::vector<Reg1*> reg1_registers,
764 const std::vector<Reg2*> reg2_registers,
765 const std::vector<Reg3*> reg3_registers,
766 std::string (AssemblerTest::*GetName1)(const Reg1&),
767 std::string (AssemblerTest::*GetName2)(const Reg2&),
768 std::string (AssemblerTest::*GetName3)(const Reg3&),
Andreas Gampe2e965ac2016-11-03 17:24:15 -0700769 const std::string& fmt) {
Chris Larsendbce0d72015-09-17 13:34:00 -0700770 std::string str;
771 for (auto reg1 : reg1_registers) {
772 for (auto reg2 : reg2_registers) {
773 for (auto reg3 : reg3_registers) {
774 (assembler_.get()->*f)(*reg1, *reg2, *reg3);
775 std::string base = fmt;
776
777 std::string reg1_string = (this->*GetName1)(*reg1);
778 size_t reg1_index;
779 while ((reg1_index = base.find(REG1_TOKEN)) != std::string::npos) {
780 base.replace(reg1_index, ConstexprStrLen(REG1_TOKEN), reg1_string);
781 }
782
783 std::string reg2_string = (this->*GetName2)(*reg2);
784 size_t reg2_index;
785 while ((reg2_index = base.find(REG2_TOKEN)) != std::string::npos) {
786 base.replace(reg2_index, ConstexprStrLen(REG2_TOKEN), reg2_string);
787 }
788
789 std::string reg3_string = (this->*GetName3)(*reg3);
790 size_t reg3_index;
791 while ((reg3_index = base.find(REG3_TOKEN)) != std::string::npos) {
792 base.replace(reg3_index, ConstexprStrLen(REG3_TOKEN), reg3_string);
793 }
794
795 if (str.size() > 0) {
796 str += "\n";
797 }
798 str += base;
799 }
800 }
801 }
802 // Add a newline at the end.
803 str += "\n";
804 return str;
805 }
806
Mark Mendellfb8d2792015-03-31 22:16:59 -0400807 template <typename Reg1, typename Reg2>
808 std::string RepeatTemplatedRegistersImm(void (Ass::*f)(Reg1, Reg2, const Imm&),
809 const std::vector<Reg1*> reg1_registers,
810 const std::vector<Reg2*> reg2_registers,
811 std::string (AssemblerTest::*GetName1)(const Reg1&),
812 std::string (AssemblerTest::*GetName2)(const Reg2&),
813 size_t imm_bytes,
Andreas Gampe2e965ac2016-11-03 17:24:15 -0700814 const std::string& fmt) {
Mark Mendellfb8d2792015-03-31 22:16:59 -0400815 std::vector<int64_t> imms = CreateImmediateValues(imm_bytes);
816 WarnOnCombinations(reg1_registers.size() * reg2_registers.size() * imms.size());
817
818 std::string str;
819 for (auto reg1 : reg1_registers) {
820 for (auto reg2 : reg2_registers) {
821 for (int64_t imm : imms) {
822 Imm new_imm = CreateImmediate(imm);
823 (assembler_.get()->*f)(*reg1, *reg2, new_imm);
824 std::string base = fmt;
825
826 std::string reg1_string = (this->*GetName1)(*reg1);
827 size_t reg1_index;
828 while ((reg1_index = base.find(REG1_TOKEN)) != std::string::npos) {
829 base.replace(reg1_index, ConstexprStrLen(REG1_TOKEN), reg1_string);
830 }
831
832 std::string reg2_string = (this->*GetName2)(*reg2);
833 size_t reg2_index;
834 while ((reg2_index = base.find(REG2_TOKEN)) != std::string::npos) {
835 base.replace(reg2_index, ConstexprStrLen(REG2_TOKEN), reg2_string);
836 }
837
838 size_t imm_index = base.find(IMM_TOKEN);
839 if (imm_index != std::string::npos) {
840 std::ostringstream sreg;
841 sreg << imm;
842 std::string imm_string = sreg.str();
843 base.replace(imm_index, ConstexprStrLen(IMM_TOKEN), imm_string);
844 }
845
846 if (str.size() > 0) {
847 str += "\n";
848 }
849 str += base;
850 }
851 }
852 }
853 // Add a newline at the end.
854 str += "\n";
855 return str;
856 }
857
Andreas Gampe851df202014-11-12 14:05:46 -0800858 template <RegisterView kRegView>
859 std::string GetRegName(const Reg& reg) {
860 std::ostringstream sreg;
861 switch (kRegView) {
862 case RegisterView::kUsePrimaryName:
863 sreg << reg;
864 break;
865
866 case RegisterView::kUseSecondaryName:
867 sreg << GetSecondaryRegisterName(reg);
868 break;
Chao-ying Fud23840d2015-04-07 16:03:04 -0700869
870 case RegisterView::kUseTertiaryName:
871 sreg << GetTertiaryRegisterName(reg);
872 break;
873
874 case RegisterView::kUseQuaternaryName:
875 sreg << GetQuaternaryRegisterName(reg);
876 break;
Andreas Gampe851df202014-11-12 14:05:46 -0800877 }
878 return sreg.str();
879 }
880
881 std::string GetFPRegName(const FPReg& reg) {
882 std::ostringstream sreg;
883 sreg << reg;
884 return sreg.str();
885 }
886
Andreas Gampe849cc5e2014-11-18 13:46:46 -0800887 // If the assembly file needs a header, return it in a sub-class.
888 virtual const char* GetAssemblyHeader() {
889 return nullptr;
890 }
891
892 void WarnOnCombinations(size_t count) {
893 if (count > kWarnManyCombinationsThreshold) {
894 GTEST_LOG_(WARNING) << "Many combinations (" << count << "), test generation might be slow.";
895 }
896 }
897
898 static constexpr const char* REG_TOKEN = "{reg}";
899 static constexpr const char* REG1_TOKEN = "{reg1}";
900 static constexpr const char* REG2_TOKEN = "{reg2}";
Chris Larsendbce0d72015-09-17 13:34:00 -0700901 static constexpr const char* REG3_TOKEN = "{reg3}";
Andreas Gampe849cc5e2014-11-18 13:46:46 -0800902 static constexpr const char* IMM_TOKEN = "{imm}";
903
904 private:
Andreas Gampe851df202014-11-12 14:05:46 -0800905 template <RegisterView kRegView>
Andreas Gampe2e965ac2016-11-03 17:24:15 -0700906 std::string RepeatRegisterImm(void (Ass::*f)(Reg, const Imm&),
907 size_t imm_bytes,
908 const std::string& fmt) {
Andreas Gampe851df202014-11-12 14:05:46 -0800909 const std::vector<Reg*> registers = GetRegisters();
910 std::string str;
911 std::vector<int64_t> imms = CreateImmediateValues(imm_bytes);
Andreas Gampe849cc5e2014-11-18 13:46:46 -0800912
913 WarnOnCombinations(registers.size() * imms.size());
914
Andreas Gampe851df202014-11-12 14:05:46 -0800915 for (auto reg : registers) {
916 for (int64_t imm : imms) {
917 Imm new_imm = CreateImmediate(imm);
918 (assembler_.get()->*f)(*reg, new_imm);
919 std::string base = fmt;
920
921 std::string reg_string = GetRegName<kRegView>(*reg);
922 size_t reg_index;
923 while ((reg_index = base.find(REG_TOKEN)) != std::string::npos) {
924 base.replace(reg_index, ConstexprStrLen(REG_TOKEN), reg_string);
925 }
926
927 size_t imm_index = base.find(IMM_TOKEN);
928 if (imm_index != std::string::npos) {
929 std::ostringstream sreg;
930 sreg << imm;
931 std::string imm_string = sreg.str();
932 base.replace(imm_index, ConstexprStrLen(IMM_TOKEN), imm_string);
933 }
934
935 if (str.size() > 0) {
936 str += "\n";
937 }
938 str += base;
939 }
940 }
941 // Add a newline at the end.
942 str += "\n";
943 return str;
944 }
945
Alexey Frunzea0e87b02015-09-24 22:57:20 -0700946 // Override this to pad the code with NOPs to a certain size if needed.
947 virtual void Pad(std::vector<uint8_t>& data ATTRIBUTE_UNUSED) {
948 }
949
Andreas Gampe2e965ac2016-11-03 17:24:15 -0700950 void DriverWrapper(const std::string& assembly_text, const std::string& test_name) {
Vladimir Markocf93a5c2015-06-16 11:33:24 +0000951 assembler_->FinalizeCode();
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700952 size_t cs = assembler_->CodeSize();
Ian Rogers700a4022014-05-19 16:49:03 -0700953 std::unique_ptr<std::vector<uint8_t>> data(new std::vector<uint8_t>(cs));
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700954 MemoryRegion code(&(*data)[0], data->size());
955 assembler_->FinalizeInstructions(code);
Alexey Frunzea0e87b02015-09-24 22:57:20 -0700956 Pad(*data);
Andreas Gampe03b9ee42015-04-24 21:41:45 -0700957 test_helper_->Driver(*data, assembly_text, test_name);
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700958 }
959
Andreas Gampe849cc5e2014-11-18 13:46:46 -0800960 static constexpr size_t kWarnManyCombinationsThreshold = 500;
Andreas Gampe851df202014-11-12 14:05:46 -0800961
Vladimir Marko93205e32016-04-13 11:59:46 +0100962 ArenaPool pool_;
963 std::unique_ptr<ArenaAllocator> arena_;
Ian Rogers700a4022014-05-19 16:49:03 -0700964 std::unique_ptr<Ass> assembler_;
Andreas Gampe03b9ee42015-04-24 21:41:45 -0700965 std::unique_ptr<AssemblerTestInfrastructure> test_helper_;
Andreas Gampe7747c8d2014-08-06 14:53:03 -0700966
Andreas Gampe851df202014-11-12 14:05:46 -0800967 DISALLOW_COPY_AND_ASSIGN(AssemblerTest);
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700968};
969
970} // namespace art
971
972#endif // ART_COMPILER_UTILS_ASSEMBLER_TEST_H_