1 /*
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 
22 #include <sys/stat.h>
23 
24 #include <cstdio>
25 #include <cstdlib>
26 #include <fstream>
27 #include <iterator>
28 
29 #include "base/malloc_arena_pool.h"
30 #include "assembler_test_base.h"
31 #include "common_runtime_test.h"  // For ScratchFile
32 
33 namespace art {
34 
35 // Helper for a constexpr string length.
36 constexpr size_t ConstexprStrLen(char const* str, size_t count = 0) {
37   return ('\0' == str[0]) ? count : ConstexprStrLen(str+1, count+1);
38 }
39 
40 enum class RegisterView {  // private
41   kUsePrimaryName,
42   kUseSecondaryName,
43   kUseTertiaryName,
44   kUseQuaternaryName,
45 };
46 
47 // For use in the template as the default type to get a nonvector registers version.
48 struct NoVectorRegs {};
49 
50 template<typename Ass,
51          typename Addr,
52          typename Reg,
53          typename FPReg,
54          typename Imm,
55          typename VecReg = NoVectorRegs>
56 class AssemblerTest : public testing::Test {
57  public:
GetAssembler()58   Ass* GetAssembler() {
59     return assembler_.get();
60   }
61 
62   typedef std::string (*TestFn)(AssemblerTest* assembler_test, Ass* assembler);
63 
DriverFn(TestFn f,const std::string & test_name)64   void DriverFn(TestFn f, const std::string& test_name) {
65     DriverWrapper(f(this, assembler_.get()), test_name);
66   }
67 
68   // This driver assumes the assembler has already been called.
DriverStr(const std::string & assembly_string,const std::string & test_name)69   void DriverStr(const std::string& assembly_string, const std::string& test_name) {
70     DriverWrapper(assembly_string, test_name);
71   }
72 
73   //
74   // Register repeats.
75   //
76 
RepeatR(void (Ass::* f)(Reg),const std::string & fmt)77   std::string RepeatR(void (Ass::*f)(Reg), const std::string& fmt) {
78     return RepeatTemplatedRegister<Reg>(f,
79         GetRegisters(),
80         &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
81         fmt);
82   }
83 
Repeatr(void (Ass::* f)(Reg),const std::string & fmt)84   std::string Repeatr(void (Ass::*f)(Reg), const std::string& fmt) {
85     return RepeatTemplatedRegister<Reg>(f,
86         GetRegisters(),
87         &AssemblerTest::GetRegName<RegisterView::kUseSecondaryName>,
88         fmt);
89   }
90 
RepeatRR(void (Ass::* f)(Reg,Reg),const std::string & fmt)91   std::string RepeatRR(void (Ass::*f)(Reg, Reg), const std::string& fmt) {
92     return RepeatTemplatedRegisters<Reg, Reg>(f,
93         GetRegisters(),
94         GetRegisters(),
95         &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
96         &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
97         fmt);
98   }
99 
RepeatRRNoDupes(void (Ass::* f)(Reg,Reg),const std::string & fmt)100   std::string RepeatRRNoDupes(void (Ass::*f)(Reg, Reg), const std::string& fmt) {
101     return RepeatTemplatedRegistersNoDupes<Reg, Reg>(f,
102         GetRegisters(),
103         GetRegisters(),
104         &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
105         &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
106         fmt);
107   }
108 
Repeatrr(void (Ass::* f)(Reg,Reg),const std::string & fmt)109   std::string Repeatrr(void (Ass::*f)(Reg, Reg), const std::string& fmt) {
110     return RepeatTemplatedRegisters<Reg, Reg>(f,
111         GetRegisters(),
112         GetRegisters(),
113         &AssemblerTest::GetRegName<RegisterView::kUseSecondaryName>,
114         &AssemblerTest::GetRegName<RegisterView::kUseSecondaryName>,
115         fmt);
116   }
117 
Repeatww(void (Ass::* f)(Reg,Reg),const std::string & fmt)118   std::string Repeatww(void (Ass::*f)(Reg, Reg), const std::string& fmt) {
119     return RepeatTemplatedRegisters<Reg, Reg>(f,
120         GetRegisters(),
121         GetRegisters(),
122         &AssemblerTest::GetRegName<RegisterView::kUseTertiaryName>,
123         &AssemblerTest::GetRegName<RegisterView::kUseTertiaryName>,
124         fmt);
125   }
126 
Repeatbb(void (Ass::* f)(Reg,Reg),const std::string & fmt)127   std::string Repeatbb(void (Ass::*f)(Reg, Reg), const std::string& fmt) {
128     return RepeatTemplatedRegisters<Reg, Reg>(f,
129         GetRegisters(),
130         GetRegisters(),
131         &AssemblerTest::GetRegName<RegisterView::kUseQuaternaryName>,
132         &AssemblerTest::GetRegName<RegisterView::kUseQuaternaryName>,
133         fmt);
134   }
135 
RepeatRRR(void (Ass::* f)(Reg,Reg,Reg),const std::string & fmt)136   std::string RepeatRRR(void (Ass::*f)(Reg, Reg, Reg), const std::string& fmt) {
137     return RepeatTemplatedRegisters<Reg, Reg, Reg>(f,
138         GetRegisters(),
139         GetRegisters(),
140         GetRegisters(),
141         &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
142         &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
143         &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
144         fmt);
145   }
146 
Repeatrb(void (Ass::* f)(Reg,Reg),const std::string & fmt)147   std::string Repeatrb(void (Ass::*f)(Reg, Reg), const std::string& fmt) {
148     return RepeatTemplatedRegisters<Reg, Reg>(f,
149         GetRegisters(),
150         GetRegisters(),
151         &AssemblerTest::GetRegName<RegisterView::kUseSecondaryName>,
152         &AssemblerTest::GetRegName<RegisterView::kUseQuaternaryName>,
153         fmt);
154   }
155 
RepeatRr(void (Ass::* f)(Reg,Reg),const std::string & fmt)156   std::string RepeatRr(void (Ass::*f)(Reg, Reg), const std::string& fmt) {
157     return RepeatTemplatedRegisters<Reg, Reg>(f,
158         GetRegisters(),
159         GetRegisters(),
160         &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
161         &AssemblerTest::GetRegName<RegisterView::kUseSecondaryName>,
162         fmt);
163   }
164 
RepeatRI(void (Ass::* f)(Reg,const Imm &),size_t imm_bytes,const std::string & fmt)165   std::string RepeatRI(void (Ass::*f)(Reg, const Imm&), size_t imm_bytes, const std::string& fmt) {
166     return RepeatRegisterImm<RegisterView::kUsePrimaryName>(f, imm_bytes, fmt);
167   }
168 
RepeatrI(void (Ass::* f)(Reg,const Imm &),size_t imm_bytes,const std::string & fmt)169   std::string RepeatrI(void (Ass::*f)(Reg, const Imm&), size_t imm_bytes, const std::string& fmt) {
170     return RepeatRegisterImm<RegisterView::kUseSecondaryName>(f, imm_bytes, fmt);
171   }
172 
RepeatwI(void (Ass::* f)(Reg,const Imm &),size_t imm_bytes,const std::string & fmt)173   std::string RepeatwI(void (Ass::*f)(Reg, const Imm&), size_t imm_bytes, const std::string& fmt) {
174     return RepeatRegisterImm<RegisterView::kUseTertiaryName>(f, imm_bytes, fmt);
175   }
176 
RepeatbI(void (Ass::* f)(Reg,const Imm &),size_t imm_bytes,const std::string & fmt)177   std::string RepeatbI(void (Ass::*f)(Reg, const Imm&), size_t imm_bytes, const std::string& fmt) {
178     return RepeatRegisterImm<RegisterView::kUseQuaternaryName>(f, imm_bytes, fmt);
179   }
180 
181   template <typename Reg1, typename Reg2, typename ImmType>
182   std::string RepeatTemplatedRegistersImmBits(void (Ass::*f)(Reg1, Reg2, ImmType),
183                                               int imm_bits,
184                                               const std::vector<Reg1*> reg1_registers,
185                                               const std::vector<Reg2*> reg2_registers,
186                                               std::string (AssemblerTest::*GetName1)(const Reg1&),
187                                               std::string (AssemblerTest::*GetName2)(const Reg2&),
188                                               const std::string& fmt,
189                                               int bias = 0,
190                                               int multiplier = 1) {
191     std::string str;
192     std::vector<int64_t> imms = CreateImmediateValuesBits(abs(imm_bits), (imm_bits > 0));
193 
194     for (auto reg1 : reg1_registers) {
195       for (auto reg2 : reg2_registers) {
196         for (int64_t imm : imms) {
197           ImmType new_imm = CreateImmediate(imm);
198           if (f != nullptr) {
199             (assembler_.get()->*f)(*reg1, *reg2, new_imm * multiplier + bias);
200           }
201           std::string base = fmt;
202 
203           std::string reg1_string = (this->*GetName1)(*reg1);
204           size_t reg1_index;
205           while ((reg1_index = base.find(REG1_TOKEN)) != std::string::npos) {
206             base.replace(reg1_index, ConstexprStrLen(REG1_TOKEN), reg1_string);
207           }
208 
209           std::string reg2_string = (this->*GetName2)(*reg2);
210           size_t reg2_index;
211           while ((reg2_index = base.find(REG2_TOKEN)) != std::string::npos) {
212             base.replace(reg2_index, ConstexprStrLen(REG2_TOKEN), reg2_string);
213           }
214 
215           size_t imm_index = base.find(IMM_TOKEN);
216           if (imm_index != std::string::npos) {
217             std::ostringstream sreg;
218             sreg << imm * multiplier + bias;
219             std::string imm_string = sreg.str();
220             base.replace(imm_index, ConstexprStrLen(IMM_TOKEN), imm_string);
221           }
222 
223           if (str.size() > 0) {
224             str += "\n";
225           }
226           str += base;
227         }
228       }
229     }
230     // Add a newline at the end.
231     str += "\n";
232     return str;
233   }
234 
235   template <typename Reg1, typename Reg2, typename Reg3, typename ImmType>
RepeatTemplatedRegistersImmBits(void (Ass::* f)(Reg1,Reg2,Reg3,ImmType),int imm_bits,const std::vector<Reg1 * > reg1_registers,const std::vector<Reg2 * > reg2_registers,const std::vector<Reg3 * > reg3_registers,std::string (AssemblerTest::* GetName1)(const Reg1 &),std::string (AssemblerTest::* GetName2)(const Reg2 &),std::string (AssemblerTest::* GetName3)(const Reg3 &),std::string fmt,int bias)236   std::string RepeatTemplatedRegistersImmBits(void (Ass::*f)(Reg1, Reg2, Reg3, ImmType),
237                                               int imm_bits,
238                                               const std::vector<Reg1*> reg1_registers,
239                                               const std::vector<Reg2*> reg2_registers,
240                                               const std::vector<Reg3*> reg3_registers,
241                                               std::string (AssemblerTest::*GetName1)(const Reg1&),
242                                               std::string (AssemblerTest::*GetName2)(const Reg2&),
243                                               std::string (AssemblerTest::*GetName3)(const Reg3&),
244                                               std::string fmt,
245                                               int bias) {
246     std::string str;
247     std::vector<int64_t> imms = CreateImmediateValuesBits(abs(imm_bits), (imm_bits > 0));
248 
249     for (auto reg1 : reg1_registers) {
250       for (auto reg2 : reg2_registers) {
251         for (auto reg3 : reg3_registers) {
252           for (int64_t imm : imms) {
253             ImmType new_imm = CreateImmediate(imm);
254             if (f != nullptr) {
255               (assembler_.get()->*f)(*reg1, *reg2, *reg3, new_imm + bias);
256             }
257             std::string base = fmt;
258 
259             std::string reg1_string = (this->*GetName1)(*reg1);
260             size_t reg1_index;
261             while ((reg1_index = base.find(REG1_TOKEN)) != std::string::npos) {
262               base.replace(reg1_index, ConstexprStrLen(REG1_TOKEN), reg1_string);
263             }
264 
265             std::string reg2_string = (this->*GetName2)(*reg2);
266             size_t reg2_index;
267             while ((reg2_index = base.find(REG2_TOKEN)) != std::string::npos) {
268               base.replace(reg2_index, ConstexprStrLen(REG2_TOKEN), reg2_string);
269             }
270 
271             std::string reg3_string = (this->*GetName3)(*reg3);
272             size_t reg3_index;
273             while ((reg3_index = base.find(REG3_TOKEN)) != std::string::npos) {
274               base.replace(reg3_index, ConstexprStrLen(REG3_TOKEN), reg3_string);
275             }
276 
277             size_t imm_index = base.find(IMM_TOKEN);
278             if (imm_index != std::string::npos) {
279               std::ostringstream sreg;
280               sreg << imm + bias;
281               std::string imm_string = sreg.str();
282               base.replace(imm_index, ConstexprStrLen(IMM_TOKEN), imm_string);
283             }
284 
285             if (str.size() > 0) {
286               str += "\n";
287             }
288             str += base;
289           }
290         }
291       }
292     }
293     // Add a newline at the end.
294     str += "\n";
295     return str;
296   }
297 
298   template <typename ImmType, typename Reg1, typename Reg2>
RepeatTemplatedImmBitsRegisters(void (Ass::* f)(ImmType,Reg1,Reg2),const std::vector<Reg1 * > reg1_registers,const std::vector<Reg2 * > reg2_registers,std::string (AssemblerTest::* GetName1)(const Reg1 &),std::string (AssemblerTest::* GetName2)(const Reg2 &),int imm_bits,const std::string & fmt)299   std::string RepeatTemplatedImmBitsRegisters(void (Ass::*f)(ImmType, Reg1, Reg2),
300                                               const std::vector<Reg1*> reg1_registers,
301                                               const std::vector<Reg2*> reg2_registers,
302                                               std::string (AssemblerTest::*GetName1)(const Reg1&),
303                                               std::string (AssemblerTest::*GetName2)(const Reg2&),
304                                               int imm_bits,
305                                               const std::string& fmt) {
306     std::vector<int64_t> imms = CreateImmediateValuesBits(abs(imm_bits), (imm_bits > 0));
307 
308     WarnOnCombinations(reg1_registers.size() * reg2_registers.size() * imms.size());
309 
310     std::string str;
311     for (auto reg1 : reg1_registers) {
312       for (auto reg2 : reg2_registers) {
313         for (int64_t imm : imms) {
314           ImmType new_imm = CreateImmediate(imm);
315           if (f != nullptr) {
316             (assembler_.get()->*f)(new_imm, *reg1, *reg2);
317           }
318           std::string base = fmt;
319 
320           std::string reg1_string = (this->*GetName1)(*reg1);
321           size_t reg1_index;
322           while ((reg1_index = base.find(REG1_TOKEN)) != std::string::npos) {
323             base.replace(reg1_index, ConstexprStrLen(REG1_TOKEN), reg1_string);
324           }
325 
326           std::string reg2_string = (this->*GetName2)(*reg2);
327           size_t reg2_index;
328           while ((reg2_index = base.find(REG2_TOKEN)) != std::string::npos) {
329             base.replace(reg2_index, ConstexprStrLen(REG2_TOKEN), reg2_string);
330           }
331 
332           size_t imm_index = base.find(IMM_TOKEN);
333           if (imm_index != std::string::npos) {
334             std::ostringstream sreg;
335             sreg << imm;
336             std::string imm_string = sreg.str();
337             base.replace(imm_index, ConstexprStrLen(IMM_TOKEN), imm_string);
338           }
339 
340           if (str.size() > 0) {
341             str += "\n";
342           }
343           str += base;
344         }
345       }
346     }
347     // Add a newline at the end.
348     str += "\n";
349     return str;
350   }
351 
352   template <typename RegType, typename ImmType>
RepeatTemplatedRegisterImmBits(void (Ass::* f)(RegType,ImmType),int imm_bits,const std::vector<RegType * > registers,std::string (AssemblerTest::* GetName)(const RegType &),const std::string & fmt,int bias)353   std::string RepeatTemplatedRegisterImmBits(void (Ass::*f)(RegType, ImmType),
354                                              int imm_bits,
355                                              const std::vector<RegType*> registers,
356                                              std::string (AssemblerTest::*GetName)(const RegType&),
357                                              const std::string& fmt,
358                                              int bias) {
359     std::string str;
360     std::vector<int64_t> imms = CreateImmediateValuesBits(abs(imm_bits), (imm_bits > 0));
361 
362     for (auto reg : registers) {
363       for (int64_t imm : imms) {
364         ImmType new_imm = CreateImmediate(imm);
365         if (f != nullptr) {
366           (assembler_.get()->*f)(*reg, new_imm + bias);
367         }
368         std::string base = fmt;
369 
370         std::string reg_string = (this->*GetName)(*reg);
371         size_t reg_index;
372         while ((reg_index = base.find(REG_TOKEN)) != std::string::npos) {
373           base.replace(reg_index, ConstexprStrLen(REG_TOKEN), reg_string);
374         }
375 
376         size_t imm_index = base.find(IMM_TOKEN);
377         if (imm_index != std::string::npos) {
378           std::ostringstream sreg;
379           sreg << imm + bias;
380           std::string imm_string = sreg.str();
381           base.replace(imm_index, ConstexprStrLen(IMM_TOKEN), imm_string);
382         }
383 
384         if (str.size() > 0) {
385           str += "\n";
386         }
387         str += base;
388       }
389     }
390     // Add a newline at the end.
391     str += "\n";
392     return str;
393   }
394 
395   template <typename ImmType>
396   std::string RepeatRRIb(void (Ass::*f)(Reg, Reg, ImmType),
397                          int imm_bits,
398                          const std::string& fmt,
399                          int bias = 0) {
400     return RepeatTemplatedRegistersImmBits<Reg, Reg, ImmType>(f,
401         imm_bits,
402         GetRegisters(),
403         GetRegisters(),
404         &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
405         &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
406         fmt,
407         bias);
408   }
409 
410   template <typename ImmType>
411   std::string RepeatRRRIb(void (Ass::*f)(Reg, Reg, Reg, ImmType),
412                           int imm_bits,
413                           const std::string& fmt,
414                           int bias = 0) {
415     return RepeatTemplatedRegistersImmBits<Reg, Reg, Reg, ImmType>(f,
416         imm_bits,
417         GetRegisters(),
418         GetRegisters(),
419         GetRegisters(),
420         &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
421         &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
422         &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
423         fmt,
424         bias);
425   }
426 
427   template <typename ImmType>
428   std::string RepeatRIb(void (Ass::*f)(Reg, ImmType), int imm_bits, std::string fmt, int bias = 0) {
429     return RepeatTemplatedRegisterImmBits<Reg, ImmType>(f,
430         imm_bits,
431         GetRegisters(),
432         &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
433         fmt,
434         bias);
435   }
436 
437   template <typename ImmType>
438   std::string RepeatFRIb(void (Ass::*f)(FPReg, Reg, ImmType),
439                          int imm_bits,
440                          const std::string& fmt,
441                          int bias = 0) {
442     return RepeatTemplatedRegistersImmBits<FPReg, Reg, ImmType>(f,
443         imm_bits,
444         GetFPRegisters(),
445         GetRegisters(),
446         &AssemblerTest::GetFPRegName,
447         &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
448         fmt,
449         bias);
450   }
451 
RepeatFF(void (Ass::* f)(FPReg,FPReg),const std::string & fmt)452   std::string RepeatFF(void (Ass::*f)(FPReg, FPReg), const std::string& fmt) {
453     return RepeatTemplatedRegisters<FPReg, FPReg>(f,
454                                                   GetFPRegisters(),
455                                                   GetFPRegisters(),
456                                                   &AssemblerTest::GetFPRegName,
457                                                   &AssemblerTest::GetFPRegName,
458                                                   fmt);
459   }
460 
RepeatFFF(void (Ass::* f)(FPReg,FPReg,FPReg),const std::string & fmt)461   std::string RepeatFFF(void (Ass::*f)(FPReg, FPReg, FPReg), const std::string& fmt) {
462     return RepeatTemplatedRegisters<FPReg, FPReg, FPReg>(f,
463                                                          GetFPRegisters(),
464                                                          GetFPRegisters(),
465                                                          GetFPRegisters(),
466                                                          &AssemblerTest::GetFPRegName,
467                                                          &AssemblerTest::GetFPRegName,
468                                                          &AssemblerTest::GetFPRegName,
469                                                          fmt);
470   }
471 
RepeatFFR(void (Ass::* f)(FPReg,FPReg,Reg),const std::string & fmt)472   std::string RepeatFFR(void (Ass::*f)(FPReg, FPReg, Reg), const std::string& fmt) {
473     return RepeatTemplatedRegisters<FPReg, FPReg, Reg>(
474         f,
475         GetFPRegisters(),
476         GetFPRegisters(),
477         GetRegisters(),
478         &AssemblerTest::GetFPRegName,
479         &AssemblerTest::GetFPRegName,
480         &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
481         fmt);
482   }
483 
RepeatFFI(void (Ass::* f)(FPReg,FPReg,const Imm &),size_t imm_bytes,const std::string & fmt)484   std::string RepeatFFI(void (Ass::*f)(FPReg, FPReg, const Imm&),
485                         size_t imm_bytes,
486                         const std::string& fmt) {
487     return RepeatTemplatedRegistersImm<FPReg, FPReg>(f,
488                                                      GetFPRegisters(),
489                                                      GetFPRegisters(),
490                                                      &AssemblerTest::GetFPRegName,
491                                                      &AssemblerTest::GetFPRegName,
492                                                      imm_bytes,
493                                                      fmt);
494   }
495 
496   template <typename ImmType>
RepeatFFIb(void (Ass::* f)(FPReg,FPReg,ImmType),int imm_bits,const std::string & fmt)497   std::string RepeatFFIb(void (Ass::*f)(FPReg, FPReg, ImmType),
498                          int imm_bits,
499                          const std::string& fmt) {
500     return RepeatTemplatedRegistersImmBits<FPReg, FPReg, ImmType>(f,
501                                                                   imm_bits,
502                                                                   GetFPRegisters(),
503                                                                   GetFPRegisters(),
504                                                                   &AssemblerTest::GetFPRegName,
505                                                                   &AssemblerTest::GetFPRegName,
506                                                                   fmt);
507   }
508 
509   template <typename ImmType>
RepeatIbFF(void (Ass::* f)(ImmType,FPReg,FPReg),int imm_bits,const std::string & fmt)510   std::string RepeatIbFF(void (Ass::*f)(ImmType, FPReg, FPReg),
511                          int imm_bits,
512                          const std::string& fmt) {
513     return RepeatTemplatedImmBitsRegisters<ImmType, FPReg, FPReg>(f,
514                                                                   GetFPRegisters(),
515                                                                   GetFPRegisters(),
516                                                                   &AssemblerTest::GetFPRegName,
517                                                                   &AssemblerTest::GetFPRegName,
518                                                                   imm_bits,
519                                                                   fmt);
520   }
521 
RepeatFR(void (Ass::* f)(FPReg,Reg),const std::string & fmt)522   std::string RepeatFR(void (Ass::*f)(FPReg, Reg), const std::string& fmt) {
523     return RepeatTemplatedRegisters<FPReg, Reg>(f,
524         GetFPRegisters(),
525         GetRegisters(),
526         &AssemblerTest::GetFPRegName,
527         &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
528         fmt);
529   }
530 
RepeatFr(void (Ass::* f)(FPReg,Reg),const std::string & fmt)531   std::string RepeatFr(void (Ass::*f)(FPReg, Reg), const std::string& fmt) {
532     return RepeatTemplatedRegisters<FPReg, Reg>(f,
533         GetFPRegisters(),
534         GetRegisters(),
535         &AssemblerTest::GetFPRegName,
536         &AssemblerTest::GetRegName<RegisterView::kUseSecondaryName>,
537         fmt);
538   }
539 
RepeatRF(void (Ass::* f)(Reg,FPReg),const std::string & fmt)540   std::string RepeatRF(void (Ass::*f)(Reg, FPReg), const std::string& fmt) {
541     return RepeatTemplatedRegisters<Reg, FPReg>(f,
542         GetRegisters(),
543         GetFPRegisters(),
544         &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
545         &AssemblerTest::GetFPRegName,
546         fmt);
547   }
548 
RepeatrF(void (Ass::* f)(Reg,FPReg),const std::string & fmt)549   std::string RepeatrF(void (Ass::*f)(Reg, FPReg), const std::string& fmt) {
550     return RepeatTemplatedRegisters<Reg, FPReg>(f,
551         GetRegisters(),
552         GetFPRegisters(),
553         &AssemblerTest::GetRegName<RegisterView::kUseSecondaryName>,
554         &AssemblerTest::GetFPRegName,
555         fmt);
556   }
557 
558   std::string RepeatI(void (Ass::*f)(const Imm&),
559                       size_t imm_bytes,
560                       const std::string& fmt,
561                       bool as_uint = false) {
562     std::string str;
563     std::vector<int64_t> imms = CreateImmediateValues(imm_bytes, as_uint);
564 
565     WarnOnCombinations(imms.size());
566 
567     for (int64_t imm : imms) {
568       Imm new_imm = CreateImmediate(imm);
569       if (f != nullptr) {
570         (assembler_.get()->*f)(new_imm);
571       }
572       std::string base = fmt;
573 
574       size_t imm_index = base.find(IMM_TOKEN);
575       if (imm_index != std::string::npos) {
576         std::ostringstream sreg;
577         sreg << imm;
578         std::string imm_string = sreg.str();
579         base.replace(imm_index, ConstexprStrLen(IMM_TOKEN), imm_string);
580       }
581 
582       if (str.size() > 0) {
583         str += "\n";
584       }
585       str += base;
586     }
587     // Add a newline at the end.
588     str += "\n";
589     return str;
590   }
591 
RepeatVV(void (Ass::* f)(VecReg,VecReg),const std::string & fmt)592   std::string RepeatVV(void (Ass::*f)(VecReg, VecReg), const std::string& fmt) {
593     return RepeatTemplatedRegisters<VecReg, VecReg>(f,
594                                                     GetVectorRegisters(),
595                                                     GetVectorRegisters(),
596                                                     &AssemblerTest::GetVecRegName,
597                                                     &AssemblerTest::GetVecRegName,
598                                                     fmt);
599   }
600 
RepeatVVV(void (Ass::* f)(VecReg,VecReg,VecReg),const std::string & fmt)601   std::string RepeatVVV(void (Ass::*f)(VecReg, VecReg, VecReg), const std::string& fmt) {
602     return RepeatTemplatedRegisters<VecReg, VecReg, VecReg>(f,
603                                                             GetVectorRegisters(),
604                                                             GetVectorRegisters(),
605                                                             GetVectorRegisters(),
606                                                             &AssemblerTest::GetVecRegName,
607                                                             &AssemblerTest::GetVecRegName,
608                                                             &AssemblerTest::GetVecRegName,
609                                                             fmt);
610   }
611 
RepeatVR(void (Ass::* f)(VecReg,Reg),const std::string & fmt)612   std::string RepeatVR(void (Ass::*f)(VecReg, Reg), const std::string& fmt) {
613     return RepeatTemplatedRegisters<VecReg, Reg>(
614         f,
615         GetVectorRegisters(),
616         GetRegisters(),
617         &AssemblerTest::GetVecRegName,
618         &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
619         fmt);
620   }
621 
622   template <typename ImmType>
623   std::string RepeatVIb(void (Ass::*f)(VecReg, ImmType),
624                         int imm_bits,
625                         std::string fmt,
626                         int bias = 0) {
627     return RepeatTemplatedRegisterImmBits<VecReg, ImmType>(f,
628                                                            imm_bits,
629                                                            GetVectorRegisters(),
630                                                            &AssemblerTest::GetVecRegName,
631                                                            fmt,
632                                                            bias);
633   }
634 
635   template <typename ImmType>
636   std::string RepeatVRIb(void (Ass::*f)(VecReg, Reg, ImmType),
637                          int imm_bits,
638                          const std::string& fmt,
639                          int bias = 0,
640                          int multiplier = 1) {
641     return RepeatTemplatedRegistersImmBits<VecReg, Reg, ImmType>(
642         f,
643         imm_bits,
644         GetVectorRegisters(),
645         GetRegisters(),
646         &AssemblerTest::GetVecRegName,
647         &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
648         fmt,
649         bias,
650         multiplier);
651   }
652 
653   template <typename ImmType>
654   std::string RepeatRVIb(void (Ass::*f)(Reg, VecReg, ImmType),
655                          int imm_bits,
656                          const std::string& fmt,
657                          int bias = 0,
658                          int multiplier = 1) {
659     return RepeatTemplatedRegistersImmBits<Reg, VecReg, ImmType>(
660         f,
661         imm_bits,
662         GetRegisters(),
663         GetVectorRegisters(),
664         &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
665         &AssemblerTest::GetVecRegName,
666         fmt,
667         bias,
668         multiplier);
669   }
670 
671   template <typename ImmType>
672   std::string RepeatVVIb(void (Ass::*f)(VecReg, VecReg, ImmType),
673                          int imm_bits,
674                          const std::string& fmt,
675                          int bias = 0) {
676     return RepeatTemplatedRegistersImmBits<VecReg, VecReg, ImmType>(f,
677                                                                     imm_bits,
678                                                                     GetVectorRegisters(),
679                                                                     GetVectorRegisters(),
680                                                                     &AssemblerTest::GetVecRegName,
681                                                                     &AssemblerTest::GetVecRegName,
682                                                                     fmt,
683                                                                     bias);
684   }
685 
686   // This is intended to be run as a test.
CheckTools()687   bool CheckTools() {
688     return test_helper_->CheckTools();
689   }
690 
691   // The following functions are public so that TestFn can use them...
692 
693   // Returns a vector of address used by any of the repeat methods
694   // involving an "A" (e.g. RepeatA).
695   virtual std::vector<Addr> GetAddresses() = 0;
696 
697   // Returns a vector of registers used by any of the repeat methods
698   // involving an "R" (e.g. RepeatR).
699   virtual std::vector<Reg*> GetRegisters() = 0;
700 
701   // Returns a vector of fp-registers used by any of the repeat methods
702   // involving an "F" (e.g. RepeatFF).
GetFPRegisters()703   virtual std::vector<FPReg*> GetFPRegisters() {
704     UNIMPLEMENTED(FATAL) << "Architecture does not support floating-point registers";
705     UNREACHABLE();
706   }
707 
708   // Returns a vector of dedicated simd-registers used by any of the repeat
709   // methods involving an "V" (e.g. RepeatVV).
GetVectorRegisters()710   virtual std::vector<VecReg*> GetVectorRegisters() {
711     UNIMPLEMENTED(FATAL) << "Architecture does not support vector registers";
712     UNREACHABLE();
713   }
714 
715   // Secondary register names are the secondary view on registers, e.g., 32b on 64b systems.
GetSecondaryRegisterName(const Reg & reg ATTRIBUTE_UNUSED)716   virtual std::string GetSecondaryRegisterName(const Reg& reg ATTRIBUTE_UNUSED) {
717     UNIMPLEMENTED(FATAL) << "Architecture does not support secondary registers";
718     UNREACHABLE();
719   }
720 
721   // Tertiary register names are the tertiary view on registers, e.g., 16b on 64b systems.
GetTertiaryRegisterName(const Reg & reg ATTRIBUTE_UNUSED)722   virtual std::string GetTertiaryRegisterName(const Reg& reg ATTRIBUTE_UNUSED) {
723     UNIMPLEMENTED(FATAL) << "Architecture does not support tertiary registers";
724     UNREACHABLE();
725   }
726 
727   // Quaternary register names are the quaternary view on registers, e.g., 8b on 64b systems.
GetQuaternaryRegisterName(const Reg & reg ATTRIBUTE_UNUSED)728   virtual std::string GetQuaternaryRegisterName(const Reg& reg ATTRIBUTE_UNUSED) {
729     UNIMPLEMENTED(FATAL) << "Architecture does not support quaternary registers";
730     UNREACHABLE();
731   }
732 
GetRegisterName(const Reg & reg)733   std::string GetRegisterName(const Reg& reg) {
734     return GetRegName<RegisterView::kUsePrimaryName>(reg);
735   }
736 
737  protected:
AssemblerTest()738   AssemblerTest() {}
739 
SetUp()740   void SetUp() override {
741     allocator_.reset(new ArenaAllocator(&pool_));
742     assembler_.reset(CreateAssembler(allocator_.get()));
743     test_helper_.reset(
744         new AssemblerTestInfrastructure(GetArchitectureString(),
745                                         GetAssemblerCmdName(),
746                                         GetAssemblerParameters(),
747                                         GetObjdumpCmdName(),
748                                         GetObjdumpParameters(),
749                                         GetDisassembleCmdName(),
750                                         GetDisassembleParameters(),
751                                         GetAssemblyHeader()));
752 
753     SetUpHelpers();
754   }
755 
TearDown()756   void TearDown() override {
757     test_helper_.reset();  // Clean up the helper.
758     assembler_.reset();
759     allocator_.reset();
760   }
761 
762   // Override this to set up any architecture-specific things, e.g., CPU revision.
CreateAssembler(ArenaAllocator * allocator)763   virtual Ass* CreateAssembler(ArenaAllocator* allocator) {
764     return new (allocator) Ass(allocator);
765   }
766 
767   // Override this to set up any architecture-specific things, e.g., register vectors.
SetUpHelpers()768   virtual void SetUpHelpers() {}
769 
770   // Get the typically used name for this architecture, e.g., aarch64, x86_64, ...
771   virtual std::string GetArchitectureString() = 0;
772 
773   // Get the name of the assembler, e.g., "as" by default.
GetAssemblerCmdName()774   virtual std::string GetAssemblerCmdName() {
775     return "as";
776   }
777 
778   // Switches to the assembler command. Default none.
GetAssemblerParameters()779   virtual std::string GetAssemblerParameters() {
780     return "";
781   }
782 
783   // Get the name of the objdump, e.g., "objdump" by default.
GetObjdumpCmdName()784   virtual std::string GetObjdumpCmdName() {
785     return "objdump";
786   }
787 
788   // Switches to the objdump command. Default is " -h".
GetObjdumpParameters()789   virtual std::string GetObjdumpParameters() {
790     return " -h";
791   }
792 
793   // Get the name of the objdump, e.g., "objdump" by default.
GetDisassembleCmdName()794   virtual std::string GetDisassembleCmdName() {
795     return "objdump";
796   }
797 
798   // Switches to the objdump command. As it's a binary, one needs to push the architecture and
799   // such to objdump, so it's architecture-specific and there is no default.
800   virtual std::string GetDisassembleParameters() = 0;
801 
802   // Create a couple of immediate values up to the number of bytes given.
803   virtual std::vector<int64_t> CreateImmediateValues(size_t imm_bytes, bool as_uint = false) {
804     std::vector<int64_t> res;
805     res.push_back(0);
806     if (!as_uint) {
807       res.push_back(-1);
808     } else {
809       res.push_back(0xFF);
810     }
811     res.push_back(0x12);
812     if (imm_bytes >= 2) {
813       res.push_back(0x1234);
814       if (!as_uint) {
815         res.push_back(-0x1234);
816       } else {
817         res.push_back(0xFFFF);
818       }
819       if (imm_bytes >= 4) {
820         res.push_back(0x12345678);
821         if (!as_uint) {
822           res.push_back(-0x12345678);
823         } else {
824           res.push_back(0xFFFFFFFF);
825         }
826         if (imm_bytes >= 6) {
827           res.push_back(0x123456789ABC);
828           if (!as_uint) {
829             res.push_back(-0x123456789ABC);
830           }
831           if (imm_bytes >= 8) {
832             res.push_back(0x123456789ABCDEF0);
833             if (!as_uint) {
834               res.push_back(-0x123456789ABCDEF0);
835             } else {
836               res.push_back(0xFFFFFFFFFFFFFFFF);
837             }
838           }
839         }
840       }
841     }
842     return res;
843   }
844 
845   const int kMaxBitsExhaustiveTest = 8;
846 
847   // Create a couple of immediate values up to the number of bits given.
848   virtual std::vector<int64_t> CreateImmediateValuesBits(const int imm_bits, bool as_uint = false) {
849     CHECK_GT(imm_bits, 0);
850     CHECK_LE(imm_bits, 64);
851     std::vector<int64_t> res;
852 
853     if (imm_bits <= kMaxBitsExhaustiveTest) {
854       if (as_uint) {
855         for (uint64_t i = MinInt<uint64_t>(imm_bits); i <= MaxInt<uint64_t>(imm_bits); i++) {
856           res.push_back(static_cast<int64_t>(i));
857         }
858       } else {
859         for (int64_t i = MinInt<int64_t>(imm_bits); i <= MaxInt<int64_t>(imm_bits); i++) {
860           res.push_back(i);
861         }
862       }
863     } else {
864       if (as_uint) {
865         for (uint64_t i = MinInt<uint64_t>(kMaxBitsExhaustiveTest);
866              i <= MaxInt<uint64_t>(kMaxBitsExhaustiveTest);
867              i++) {
868           res.push_back(static_cast<int64_t>(i));
869         }
870         for (int i = 0; i <= imm_bits; i++) {
871           uint64_t j = (MaxInt<uint64_t>(kMaxBitsExhaustiveTest) + 1) +
872                        ((MaxInt<uint64_t>(imm_bits) -
873                         (MaxInt<uint64_t>(kMaxBitsExhaustiveTest) + 1))
874                         * i / imm_bits);
875           res.push_back(static_cast<int64_t>(j));
876         }
877       } else {
878         for (int i = 0; i <= imm_bits; i++) {
879           int64_t j = MinInt<int64_t>(imm_bits) +
880                       ((((MinInt<int64_t>(kMaxBitsExhaustiveTest) - 1) -
881                          MinInt<int64_t>(imm_bits))
882                         * i) / imm_bits);
883           res.push_back(static_cast<int64_t>(j));
884         }
885         for (int64_t i = MinInt<int64_t>(kMaxBitsExhaustiveTest);
886              i <= MaxInt<int64_t>(kMaxBitsExhaustiveTest);
887              i++) {
888           res.push_back(static_cast<int64_t>(i));
889         }
890         for (int i = 0; i <= imm_bits; i++) {
891           int64_t j = (MaxInt<int64_t>(kMaxBitsExhaustiveTest) + 1) +
892                       ((MaxInt<int64_t>(imm_bits) - (MaxInt<int64_t>(kMaxBitsExhaustiveTest) + 1))
893                        * i / imm_bits);
894           res.push_back(static_cast<int64_t>(j));
895         }
896       }
897     }
898 
899     return res;
900   }
901 
902   // Create an immediate from the specific value.
903   virtual Imm CreateImmediate(int64_t imm_value) = 0;
904 
905   //
906   // Addresses repeats.
907   //
908 
909   // Repeats over addresses provided by fixture.
RepeatA(void (Ass::* f)(const Addr &),const std::string & fmt)910   std::string RepeatA(void (Ass::*f)(const Addr&), const std::string& fmt) {
911     return RepeatA(f, GetAddresses(), fmt);
912   }
913 
914   // Variant that takes explicit vector of addresss
915   // (to test restricted addressing modes set).
RepeatA(void (Ass::* f)(const Addr &),const std::vector<Addr> & a,const std::string & fmt)916   std::string RepeatA(void (Ass::*f)(const Addr&),
917                       const std::vector<Addr>& a,
918                       const std::string& fmt) {
919     return RepeatTemplatedMem<Addr>(f, a, &AssemblerTest::GetAddrName, fmt);
920   }
921 
922   // Repeats over addresses and immediates provided by fixture.
RepeatAI(void (Ass::* f)(const Addr &,const Imm &),size_t imm_bytes,const std::string & fmt)923   std::string RepeatAI(void (Ass::*f)(const Addr&, const Imm&),
924                        size_t imm_bytes,
925                        const std::string& fmt) {
926     return RepeatAI(f, imm_bytes, GetAddresses(), fmt);
927   }
928 
929   // Variant that takes explicit vector of addresss
930   // (to test restricted addressing modes set).
RepeatAI(void (Ass::* f)(const Addr &,const Imm &),size_t imm_bytes,const std::vector<Addr> & a,const std::string & fmt)931   std::string RepeatAI(void (Ass::*f)(const Addr&, const Imm&),
932                        size_t imm_bytes,
933                        const std::vector<Addr>& a,
934                        const std::string& fmt) {
935     return RepeatTemplatedMemImm<Addr>(f, imm_bytes, a, &AssemblerTest::GetAddrName, fmt);
936   }
937 
938   // Repeats over registers and addresses provided by fixture.
RepeatRA(void (Ass::* f)(Reg,const Addr &),const std::string & fmt)939   std::string RepeatRA(void (Ass::*f)(Reg, const Addr&), const std::string& fmt) {
940     return RepeatRA(f, GetAddresses(), fmt);
941   }
942 
943   // Variant that takes explicit vector of addresss
944   // (to test restricted addressing modes set).
RepeatRA(void (Ass::* f)(Reg,const Addr &),const std::vector<Addr> & a,const std::string & fmt)945   std::string RepeatRA(void (Ass::*f)(Reg, const Addr&),
946                        const std::vector<Addr>& a,
947                        const std::string& fmt) {
948     return RepeatTemplatedRegMem<Reg, Addr>(
949         f,
950         GetRegisters(),
951         a,
952         &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
953         &AssemblerTest::GetAddrName,
954         fmt);
955   }
956 
957   // Repeats over secondary registers and addresses provided by fixture.
RepeatrA(void (Ass::* f)(Reg,const Addr &),const std::string & fmt)958   std::string RepeatrA(void (Ass::*f)(Reg, const Addr&), const std::string& fmt) {
959     return RepeatrA(f, GetAddresses(), fmt);
960   }
961 
962   // Variant that takes explicit vector of addresss
963   // (to test restricted addressing modes set).
RepeatrA(void (Ass::* f)(Reg,const Addr &),const std::vector<Addr> & a,const std::string & fmt)964   std::string RepeatrA(void (Ass::*f)(Reg, const Addr&),
965                        const std::vector<Addr>& a,
966                        const std::string& fmt) {
967     return RepeatTemplatedRegMem<Reg, Addr>(
968         f,
969         GetRegisters(),
970         a,
971         &AssemblerTest::GetRegName<RegisterView::kUseSecondaryName>,
972         &AssemblerTest::GetAddrName,
973         fmt);
974   }
975 
976   // Repeats over tertiary registers and addresses provided by fixture.
RepeatwA(void (Ass::* f)(Reg,const Addr &),const std::string & fmt)977   std::string RepeatwA(void (Ass::*f)(Reg, const Addr&), const std::string& fmt) {
978     return RepeatwA(f, GetAddresses(), fmt);
979   }
980 
981   // Variant that takes explicit vector of addresss
982   // (to test restricted addressing modes set).
RepeatwA(void (Ass::* f)(Reg,const Addr &),const std::vector<Addr> & a,const std::string & fmt)983   std::string RepeatwA(void (Ass::*f)(Reg, const Addr&),
984                        const std::vector<Addr>& a,
985                        const std::string& fmt) {
986     return RepeatTemplatedRegMem<Reg, Addr>(
987         f,
988         GetRegisters(),
989         a,
990         &AssemblerTest::GetRegName<RegisterView::kUseTertiaryName>,
991         &AssemblerTest::GetAddrName,
992         fmt);
993   }
994 
995   // Repeats over quaternary registers and addresses provided by fixture.
RepeatbA(void (Ass::* f)(Reg,const Addr &),const std::string & fmt)996   std::string RepeatbA(void (Ass::*f)(Reg, const Addr&), const std::string& fmt) {
997     return RepeatbA(f, GetAddresses(), fmt);
998   }
999 
1000   // Variant that takes explicit vector of addresss
1001   // (to test restricted addressing modes set).
RepeatbA(void (Ass::* f)(Reg,const Addr &),const std::vector<Addr> & a,const std::string & fmt)1002   std::string RepeatbA(void (Ass::*f)(Reg, const Addr&),
1003                        const std::vector<Addr>& a,
1004                        const std::string& fmt) {
1005     return RepeatTemplatedRegMem<Reg, Addr>(
1006         f,
1007         GetRegisters(),
1008         a,
1009         &AssemblerTest::GetRegName<RegisterView::kUseQuaternaryName>,
1010         &AssemblerTest::GetAddrName,
1011         fmt);
1012   }
1013 
1014   // Repeats over fp-registers and addresses provided by fixture.
RepeatFA(void (Ass::* f)(FPReg,const Addr &),const std::string & fmt)1015   std::string RepeatFA(void (Ass::*f)(FPReg, const Addr&), const std::string& fmt) {
1016     return RepeatFA(f, GetAddresses(), fmt);
1017   }
1018 
1019   // Variant that takes explicit vector of addresss
1020   // (to test restricted addressing modes set).
RepeatFA(void (Ass::* f)(FPReg,const Addr &),const std::vector<Addr> & a,const std::string & fmt)1021   std::string RepeatFA(void (Ass::*f)(FPReg, const Addr&),
1022                        const std::vector<Addr>& a,
1023                        const std::string& fmt) {
1024     return RepeatTemplatedRegMem<FPReg, Addr>(
1025         f,
1026         GetFPRegisters(),
1027         a,
1028         &AssemblerTest::GetFPRegName,
1029         &AssemblerTest::GetAddrName,
1030         fmt);
1031   }
1032 
1033   // Repeats over addresses and registers provided by fixture.
RepeatAR(void (Ass::* f)(const Addr &,Reg),const std::string & fmt)1034   std::string RepeatAR(void (Ass::*f)(const Addr&, Reg), const std::string& fmt) {
1035     return RepeatAR(f, GetAddresses(), fmt);
1036   }
1037 
1038   // Variant that takes explicit vector of addresss
1039   // (to test restricted addressing modes set).
RepeatAR(void (Ass::* f)(const Addr &,Reg),const std::vector<Addr> & a,const std::string & fmt)1040   std::string RepeatAR(void (Ass::*f)(const Addr&, Reg),
1041                        const std::vector<Addr>& a,
1042                        const std::string& fmt) {
1043     return RepeatTemplatedMemReg<Addr, Reg>(
1044         f,
1045         a,
1046         GetRegisters(),
1047         &AssemblerTest::GetAddrName,
1048         &AssemblerTest::GetRegName<RegisterView::kUsePrimaryName>,
1049         fmt);
1050   }
1051 
1052   // Repeats over addresses and secondary registers provided by fixture.
RepeatAr(void (Ass::* f)(const Addr &,Reg),const std::string & fmt)1053   std::string RepeatAr(void (Ass::*f)(const Addr&, Reg), const std::string& fmt) {
1054     return RepeatAr(f, GetAddresses(), fmt);
1055   }
1056 
1057   // Variant that takes explicit vector of addresss
1058   // (to test restricted addressing modes set).
RepeatAr(void (Ass::* f)(const Addr &,Reg),const std::vector<Addr> & a,const std::string & fmt)1059   std::string RepeatAr(void (Ass::*f)(const Addr&, Reg),
1060                        const std::vector<Addr>& a,
1061                        const std::string& fmt) {
1062     return RepeatTemplatedMemReg<Addr, Reg>(
1063         f,
1064         a,
1065         GetRegisters(),
1066         &AssemblerTest::GetAddrName,
1067         &AssemblerTest::GetRegName<RegisterView::kUseSecondaryName>,
1068         fmt);
1069   }
1070 
1071   // Repeats over addresses and tertiary registers provided by fixture.
RepeatAw(void (Ass::* f)(const Addr &,Reg),const std::string & fmt)1072   std::string RepeatAw(void (Ass::*f)(const Addr&, Reg), const std::string& fmt) {
1073     return RepeatAw(f, GetAddresses(), fmt);
1074   }
1075 
1076   // Variant that takes explicit vector of addresss
1077   // (to test restricted addressing modes set).
RepeatAw(void (Ass::* f)(const Addr &,Reg),const std::vector<Addr> & a,const std::string & fmt)1078   std::string RepeatAw(void (Ass::*f)(const Addr&, Reg),
1079                        const std::vector<Addr>& a,
1080                        const std::string& fmt) {
1081     return RepeatTemplatedMemReg<Addr, Reg>(
1082         f,
1083         a,
1084         GetRegisters(),
1085         &AssemblerTest::GetAddrName,
1086         &AssemblerTest::GetRegName<RegisterView::kUseTertiaryName>,
1087         fmt);
1088   }
1089 
1090   // Repeats over addresses and quaternary registers provided by fixture.
RepeatAb(void (Ass::* f)(const Addr &,Reg),const std::string & fmt)1091   std::string RepeatAb(void (Ass::*f)(const Addr&, Reg), const std::string& fmt) {
1092     return RepeatAb(f, GetAddresses(), fmt);
1093   }
1094 
1095   // Variant that takes explicit vector of addresss
1096   // (to test restricted addressing modes set).
RepeatAb(void (Ass::* f)(const Addr &,Reg),const std::vector<Addr> & a,const std::string & fmt)1097   std::string RepeatAb(void (Ass::*f)(const Addr&, Reg),
1098                        const std::vector<Addr>& a,
1099                        const std::string& fmt) {
1100     return RepeatTemplatedMemReg<Addr, Reg>(
1101         f,
1102         a,
1103         GetRegisters(),
1104         &AssemblerTest::GetAddrName,
1105         &AssemblerTest::GetRegName<RegisterView::kUseQuaternaryName>,
1106         fmt);
1107   }
1108 
1109   // Repeats over addresses and fp-registers provided by fixture.
RepeatAF(void (Ass::* f)(const Addr &,FPReg),const std::string & fmt)1110   std::string RepeatAF(void (Ass::*f)(const Addr&, FPReg), const std::string& fmt) {
1111     return RepeatAF(f, GetAddresses(), fmt);
1112   }
1113 
1114   // Variant that takes explicit vector of addresss
1115   // (to test restricted addressing modes set).
RepeatAF(void (Ass::* f)(const Addr &,FPReg),const std::vector<Addr> & a,const std::string & fmt)1116   std::string RepeatAF(void (Ass::*f)(const Addr&, FPReg),
1117                        const std::vector<Addr>& a,
1118                        const std::string& fmt) {
1119     return RepeatTemplatedMemReg<Addr, FPReg>(
1120         f,
1121         a,
1122         GetFPRegisters(),
1123         &AssemblerTest::GetAddrName,
1124         &AssemblerTest::GetFPRegName,
1125         fmt);
1126   }
1127 
1128   template <typename AddrType>
RepeatTemplatedMem(void (Ass::* f)(const AddrType &),const std::vector<AddrType> addresses,std::string (AssemblerTest::* GetAName)(const AddrType &),const std::string & fmt)1129   std::string RepeatTemplatedMem(void (Ass::*f)(const AddrType&),
1130                                  const std::vector<AddrType> addresses,
1131                                  std::string (AssemblerTest::*GetAName)(const AddrType&),
1132                                  const std::string& fmt) {
1133     WarnOnCombinations(addresses.size());
1134     std::string str;
1135     for (auto addr : addresses) {
1136       if (f != nullptr) {
1137         (assembler_.get()->*f)(addr);
1138       }
1139       std::string base = fmt;
1140 
1141       std::string addr_string = (this->*GetAName)(addr);
1142       size_t addr_index;
1143       if ((addr_index = base.find(ADDRESS_TOKEN)) != std::string::npos) {
1144         base.replace(addr_index, ConstexprStrLen(ADDRESS_TOKEN), addr_string);
1145       }
1146 
1147       if (str.size() > 0) {
1148         str += "\n";
1149       }
1150       str += base;
1151     }
1152     // Add a newline at the end.
1153     str += "\n";
1154     return str;
1155   }
1156 
1157   template <typename AddrType>
RepeatTemplatedMemImm(void (Ass::* f)(const AddrType &,const Imm &),size_t imm_bytes,const std::vector<AddrType> addresses,std::string (AssemblerTest::* GetAName)(const AddrType &),const std::string & fmt)1158   std::string RepeatTemplatedMemImm(void (Ass::*f)(const AddrType&, const Imm&),
1159                                     size_t imm_bytes,
1160                                     const std::vector<AddrType> addresses,
1161                                     std::string (AssemblerTest::*GetAName)(const AddrType&),
1162                                     const std::string& fmt) {
1163     std::vector<int64_t> imms = CreateImmediateValues(imm_bytes);
1164     WarnOnCombinations(addresses.size() * imms.size());
1165     std::string str;
1166     for (auto addr : addresses) {
1167       for (int64_t imm : imms) {
1168         Imm new_imm = CreateImmediate(imm);
1169         if (f != nullptr) {
1170           (assembler_.get()->*f)(addr, new_imm);
1171         }
1172         std::string base = fmt;
1173 
1174         std::string addr_string = (this->*GetAName)(addr);
1175         size_t addr_index;
1176         if ((addr_index = base.find(ADDRESS_TOKEN)) != std::string::npos) {
1177           base.replace(addr_index, ConstexprStrLen(ADDRESS_TOKEN), addr_string);
1178         }
1179 
1180         size_t imm_index = base.find(IMM_TOKEN);
1181         if (imm_index != std::string::npos) {
1182           std::ostringstream sreg;
1183           sreg << imm;
1184           std::string imm_string = sreg.str();
1185           base.replace(imm_index, ConstexprStrLen(IMM_TOKEN), imm_string);
1186         }
1187 
1188         if (str.size() > 0) {
1189           str += "\n";
1190         }
1191         str += base;
1192       }
1193     }
1194     // Add a newline at the end.
1195     str += "\n";
1196     return str;
1197   }
1198 
1199   template <typename RegType, typename AddrType>
RepeatTemplatedRegMem(void (Ass::* f)(RegType,const AddrType &),const std::vector<RegType * > registers,const std::vector<AddrType> addresses,std::string (AssemblerTest::* GetRName)(const RegType &),std::string (AssemblerTest::* GetAName)(const AddrType &),const std::string & fmt)1200   std::string RepeatTemplatedRegMem(void (Ass::*f)(RegType, const AddrType&),
1201                                     const std::vector<RegType*> registers,
1202                                     const std::vector<AddrType> addresses,
1203                                     std::string (AssemblerTest::*GetRName)(const RegType&),
1204                                     std::string (AssemblerTest::*GetAName)(const AddrType&),
1205                                     const std::string& fmt) {
1206     WarnOnCombinations(addresses.size() * registers.size());
1207     std::string str;
1208     for (auto reg : registers) {
1209       for (auto addr : addresses) {
1210         if (f != nullptr) {
1211           (assembler_.get()->*f)(*reg, addr);
1212         }
1213         std::string base = fmt;
1214 
1215         std::string reg_string = (this->*GetRName)(*reg);
1216         size_t reg_index;
1217         if ((reg_index = base.find(REG_TOKEN)) != std::string::npos) {
1218           base.replace(reg_index, ConstexprStrLen(REG_TOKEN), reg_string);
1219         }
1220 
1221         std::string addr_string = (this->*GetAName)(addr);
1222         size_t addr_index;
1223         if ((addr_index = base.find(ADDRESS_TOKEN)) != std::string::npos) {
1224           base.replace(addr_index, ConstexprStrLen(ADDRESS_TOKEN), addr_string);
1225         }
1226 
1227         if (str.size() > 0) {
1228           str += "\n";
1229         }
1230         str += base;
1231       }
1232     }
1233     // Add a newline at the end.
1234     str += "\n";
1235     return str;
1236   }
1237 
1238   template <typename AddrType, typename RegType>
RepeatTemplatedMemReg(void (Ass::* f)(const AddrType &,RegType),const std::vector<AddrType> addresses,const std::vector<RegType * > registers,std::string (AssemblerTest::* GetAName)(const AddrType &),std::string (AssemblerTest::* GetRName)(const RegType &),const std::string & fmt)1239   std::string RepeatTemplatedMemReg(void (Ass::*f)(const AddrType&, RegType),
1240                                     const std::vector<AddrType> addresses,
1241                                     const std::vector<RegType*> registers,
1242                                     std::string (AssemblerTest::*GetAName)(const AddrType&),
1243                                     std::string (AssemblerTest::*GetRName)(const RegType&),
1244                                     const std::string& fmt) {
1245     WarnOnCombinations(addresses.size() * registers.size());
1246     std::string str;
1247     for (auto addr : addresses) {
1248       for (auto reg : registers) {
1249         if (f != nullptr) {
1250           (assembler_.get()->*f)(addr, *reg);
1251         }
1252         std::string base = fmt;
1253 
1254         std::string addr_string = (this->*GetAName)(addr);
1255         size_t addr_index;
1256         if ((addr_index = base.find(ADDRESS_TOKEN)) != std::string::npos) {
1257           base.replace(addr_index, ConstexprStrLen(ADDRESS_TOKEN), addr_string);
1258         }
1259 
1260         std::string reg_string = (this->*GetRName)(*reg);
1261         size_t reg_index;
1262         if ((reg_index = base.find(REG_TOKEN)) != std::string::npos) {
1263           base.replace(reg_index, ConstexprStrLen(REG_TOKEN), reg_string);
1264         }
1265 
1266         if (str.size() > 0) {
1267           str += "\n";
1268         }
1269         str += base;
1270       }
1271     }
1272     // Add a newline at the end.
1273     str += "\n";
1274     return str;
1275   }
1276 
1277   //
1278   // Register repeats.
1279   //
1280 
1281   template <typename RegType>
RepeatTemplatedRegister(void (Ass::* f)(RegType),const std::vector<RegType * > registers,std::string (AssemblerTest::* GetName)(const RegType &),const std::string & fmt)1282   std::string RepeatTemplatedRegister(void (Ass::*f)(RegType),
1283                                       const std::vector<RegType*> registers,
1284                                       std::string (AssemblerTest::*GetName)(const RegType&),
1285                                       const std::string& fmt) {
1286     std::string str;
1287     for (auto reg : registers) {
1288       if (f != nullptr) {
1289         (assembler_.get()->*f)(*reg);
1290       }
1291       std::string base = fmt;
1292 
1293       std::string reg_string = (this->*GetName)(*reg);
1294       size_t reg_index;
1295       if ((reg_index = base.find(REG_TOKEN)) != std::string::npos) {
1296         base.replace(reg_index, ConstexprStrLen(REG_TOKEN), reg_string);
1297       }
1298 
1299       if (str.size() > 0) {
1300         str += "\n";
1301       }
1302       str += base;
1303     }
1304     // Add a newline at the end.
1305     str += "\n";
1306     return str;
1307   }
1308 
1309   template <typename Reg1, typename Reg2>
RepeatTemplatedRegisters(void (Ass::* f)(Reg1,Reg2),const std::vector<Reg1 * > reg1_registers,const std::vector<Reg2 * > reg2_registers,std::string (AssemblerTest::* GetName1)(const Reg1 &),std::string (AssemblerTest::* GetName2)(const Reg2 &),const std::string & fmt)1310   std::string RepeatTemplatedRegisters(void (Ass::*f)(Reg1, Reg2),
1311                                        const std::vector<Reg1*> reg1_registers,
1312                                        const std::vector<Reg2*> reg2_registers,
1313                                        std::string (AssemblerTest::*GetName1)(const Reg1&),
1314                                        std::string (AssemblerTest::*GetName2)(const Reg2&),
1315                                        const std::string& fmt) {
1316     WarnOnCombinations(reg1_registers.size() * reg2_registers.size());
1317 
1318     std::string str;
1319     for (auto reg1 : reg1_registers) {
1320       for (auto reg2 : reg2_registers) {
1321         if (f != nullptr) {
1322           (assembler_.get()->*f)(*reg1, *reg2);
1323         }
1324         std::string base = fmt;
1325 
1326         std::string reg1_string = (this->*GetName1)(*reg1);
1327         size_t reg1_index;
1328         while ((reg1_index = base.find(REG1_TOKEN)) != std::string::npos) {
1329           base.replace(reg1_index, ConstexprStrLen(REG1_TOKEN), reg1_string);
1330         }
1331 
1332         std::string reg2_string = (this->*GetName2)(*reg2);
1333         size_t reg2_index;
1334         while ((reg2_index = base.find(REG2_TOKEN)) != std::string::npos) {
1335           base.replace(reg2_index, ConstexprStrLen(REG2_TOKEN), reg2_string);
1336         }
1337 
1338         if (str.size() > 0) {
1339           str += "\n";
1340         }
1341         str += base;
1342       }
1343     }
1344     // Add a newline at the end.
1345     str += "\n";
1346     return str;
1347   }
1348 
1349   template <typename Reg1, typename Reg2>
RepeatTemplatedRegistersNoDupes(void (Ass::* f)(Reg1,Reg2),const std::vector<Reg1 * > reg1_registers,const std::vector<Reg2 * > reg2_registers,std::string (AssemblerTest::* GetName1)(const Reg1 &),std::string (AssemblerTest::* GetName2)(const Reg2 &),const std::string & fmt)1350   std::string RepeatTemplatedRegistersNoDupes(void (Ass::*f)(Reg1, Reg2),
1351                                               const std::vector<Reg1*> reg1_registers,
1352                                               const std::vector<Reg2*> reg2_registers,
1353                                               std::string (AssemblerTest::*GetName1)(const Reg1&),
1354                                               std::string (AssemblerTest::*GetName2)(const Reg2&),
1355                                               const std::string& fmt) {
1356     WarnOnCombinations(reg1_registers.size() * reg2_registers.size());
1357 
1358     std::string str;
1359     for (auto reg1 : reg1_registers) {
1360       for (auto reg2 : reg2_registers) {
1361         if (reg1 == reg2) continue;
1362         if (f != nullptr) {
1363           (assembler_.get()->*f)(*reg1, *reg2);
1364         }
1365         std::string base = fmt;
1366 
1367         std::string reg1_string = (this->*GetName1)(*reg1);
1368         size_t reg1_index;
1369         while ((reg1_index = base.find(REG1_TOKEN)) != std::string::npos) {
1370           base.replace(reg1_index, ConstexprStrLen(REG1_TOKEN), reg1_string);
1371         }
1372 
1373         std::string reg2_string = (this->*GetName2)(*reg2);
1374         size_t reg2_index;
1375         while ((reg2_index = base.find(REG2_TOKEN)) != std::string::npos) {
1376           base.replace(reg2_index, ConstexprStrLen(REG2_TOKEN), reg2_string);
1377         }
1378 
1379         if (str.size() > 0) {
1380           str += "\n";
1381         }
1382         str += base;
1383       }
1384     }
1385     // Add a newline at the end.
1386     str += "\n";
1387     return str;
1388   }
1389 
1390   template <typename Reg1, typename Reg2, typename Reg3>
RepeatTemplatedRegisters(void (Ass::* f)(Reg1,Reg2,Reg3),const std::vector<Reg1 * > reg1_registers,const std::vector<Reg2 * > reg2_registers,const std::vector<Reg3 * > reg3_registers,std::string (AssemblerTest::* GetName1)(const Reg1 &),std::string (AssemblerTest::* GetName2)(const Reg2 &),std::string (AssemblerTest::* GetName3)(const Reg3 &),const std::string & fmt)1391   std::string RepeatTemplatedRegisters(void (Ass::*f)(Reg1, Reg2, Reg3),
1392                                        const std::vector<Reg1*> reg1_registers,
1393                                        const std::vector<Reg2*> reg2_registers,
1394                                        const std::vector<Reg3*> reg3_registers,
1395                                        std::string (AssemblerTest::*GetName1)(const Reg1&),
1396                                        std::string (AssemblerTest::*GetName2)(const Reg2&),
1397                                        std::string (AssemblerTest::*GetName3)(const Reg3&),
1398                                        const std::string& fmt) {
1399     std::string str;
1400     for (auto reg1 : reg1_registers) {
1401       for (auto reg2 : reg2_registers) {
1402         for (auto reg3 : reg3_registers) {
1403           if (f != nullptr) {
1404             (assembler_.get()->*f)(*reg1, *reg2, *reg3);
1405           }
1406           std::string base = fmt;
1407 
1408           std::string reg1_string = (this->*GetName1)(*reg1);
1409           size_t reg1_index;
1410           while ((reg1_index = base.find(REG1_TOKEN)) != std::string::npos) {
1411             base.replace(reg1_index, ConstexprStrLen(REG1_TOKEN), reg1_string);
1412           }
1413 
1414           std::string reg2_string = (this->*GetName2)(*reg2);
1415           size_t reg2_index;
1416           while ((reg2_index = base.find(REG2_TOKEN)) != std::string::npos) {
1417             base.replace(reg2_index, ConstexprStrLen(REG2_TOKEN), reg2_string);
1418           }
1419 
1420           std::string reg3_string = (this->*GetName3)(*reg3);
1421           size_t reg3_index;
1422           while ((reg3_index = base.find(REG3_TOKEN)) != std::string::npos) {
1423             base.replace(reg3_index, ConstexprStrLen(REG3_TOKEN), reg3_string);
1424           }
1425 
1426           if (str.size() > 0) {
1427             str += "\n";
1428           }
1429           str += base;
1430         }
1431       }
1432     }
1433     // Add a newline at the end.
1434     str += "\n";
1435     return str;
1436   }
1437 
1438   template <typename Reg1, typename Reg2>
RepeatTemplatedRegistersImm(void (Ass::* f)(Reg1,Reg2,const Imm &),const std::vector<Reg1 * > reg1_registers,const std::vector<Reg2 * > reg2_registers,std::string (AssemblerTest::* GetName1)(const Reg1 &),std::string (AssemblerTest::* GetName2)(const Reg2 &),size_t imm_bytes,const std::string & fmt)1439   std::string RepeatTemplatedRegistersImm(void (Ass::*f)(Reg1, Reg2, const Imm&),
1440                                           const std::vector<Reg1*> reg1_registers,
1441                                           const std::vector<Reg2*> reg2_registers,
1442                                           std::string (AssemblerTest::*GetName1)(const Reg1&),
1443                                           std::string (AssemblerTest::*GetName2)(const Reg2&),
1444                                           size_t imm_bytes,
1445                                           const std::string& fmt) {
1446     std::vector<int64_t> imms = CreateImmediateValues(imm_bytes);
1447     WarnOnCombinations(reg1_registers.size() * reg2_registers.size() * imms.size());
1448 
1449     std::string str;
1450     for (auto reg1 : reg1_registers) {
1451       for (auto reg2 : reg2_registers) {
1452         for (int64_t imm : imms) {
1453           Imm new_imm = CreateImmediate(imm);
1454           if (f != nullptr) {
1455             (assembler_.get()->*f)(*reg1, *reg2, new_imm);
1456           }
1457           std::string base = fmt;
1458 
1459           std::string reg1_string = (this->*GetName1)(*reg1);
1460           size_t reg1_index;
1461           while ((reg1_index = base.find(REG1_TOKEN)) != std::string::npos) {
1462             base.replace(reg1_index, ConstexprStrLen(REG1_TOKEN), reg1_string);
1463           }
1464 
1465           std::string reg2_string = (this->*GetName2)(*reg2);
1466           size_t reg2_index;
1467           while ((reg2_index = base.find(REG2_TOKEN)) != std::string::npos) {
1468             base.replace(reg2_index, ConstexprStrLen(REG2_TOKEN), reg2_string);
1469           }
1470 
1471           size_t imm_index = base.find(IMM_TOKEN);
1472           if (imm_index != std::string::npos) {
1473             std::ostringstream sreg;
1474             sreg << imm;
1475             std::string imm_string = sreg.str();
1476             base.replace(imm_index, ConstexprStrLen(IMM_TOKEN), imm_string);
1477           }
1478 
1479           if (str.size() > 0) {
1480             str += "\n";
1481           }
1482           str += base;
1483         }
1484       }
1485     }
1486     // Add a newline at the end.
1487     str += "\n";
1488     return str;
1489   }
1490 
GetAddrName(const Addr & addr)1491   std::string GetAddrName(const Addr& addr) {
1492     std::ostringstream saddr;
1493     saddr << addr;
1494     return saddr.str();
1495   }
1496 
1497   template <RegisterView kRegView>
GetRegName(const Reg & reg)1498   std::string GetRegName(const Reg& reg) {
1499     std::ostringstream sreg;
1500     switch (kRegView) {
1501       case RegisterView::kUsePrimaryName:
1502         sreg << reg;
1503         break;
1504 
1505       case RegisterView::kUseSecondaryName:
1506         sreg << GetSecondaryRegisterName(reg);
1507         break;
1508 
1509       case RegisterView::kUseTertiaryName:
1510         sreg << GetTertiaryRegisterName(reg);
1511         break;
1512 
1513       case RegisterView::kUseQuaternaryName:
1514         sreg << GetQuaternaryRegisterName(reg);
1515         break;
1516     }
1517     return sreg.str();
1518   }
1519 
GetFPRegName(const FPReg & reg)1520   std::string GetFPRegName(const FPReg& reg) {
1521     std::ostringstream sreg;
1522     sreg << reg;
1523     return sreg.str();
1524   }
1525 
GetVecRegName(const VecReg & reg)1526   std::string GetVecRegName(const VecReg& reg) {
1527     std::ostringstream sreg;
1528     sreg << reg;
1529     return sreg.str();
1530   }
1531 
1532   // If the assembly file needs a header, return it in a sub-class.
GetAssemblyHeader()1533   virtual const char* GetAssemblyHeader() {
1534     return nullptr;
1535   }
1536 
WarnOnCombinations(size_t count)1537   void WarnOnCombinations(size_t count) {
1538     if (count > kWarnManyCombinationsThreshold) {
1539       GTEST_LOG_(WARNING) << "Many combinations (" << count << "), test generation might be slow.";
1540     }
1541   }
1542 
1543   static constexpr const char* ADDRESS_TOKEN = "{mem}";
1544   static constexpr const char* REG_TOKEN = "{reg}";
1545   static constexpr const char* REG1_TOKEN = "{reg1}";
1546   static constexpr const char* REG2_TOKEN = "{reg2}";
1547   static constexpr const char* REG3_TOKEN = "{reg3}";
1548   static constexpr const char* IMM_TOKEN = "{imm}";
1549 
1550  private:
1551   template <RegisterView kRegView>
RepeatRegisterImm(void (Ass::* f)(Reg,const Imm &),size_t imm_bytes,const std::string & fmt)1552   std::string RepeatRegisterImm(void (Ass::*f)(Reg, const Imm&),
1553                                 size_t imm_bytes,
1554                                 const std::string& fmt) {
1555     const std::vector<Reg*> registers = GetRegisters();
1556     std::string str;
1557     std::vector<int64_t> imms = CreateImmediateValues(imm_bytes);
1558 
1559     WarnOnCombinations(registers.size() * imms.size());
1560 
1561     for (auto reg : registers) {
1562       for (int64_t imm : imms) {
1563         Imm new_imm = CreateImmediate(imm);
1564         if (f != nullptr) {
1565           (assembler_.get()->*f)(*reg, new_imm);
1566         }
1567         std::string base = fmt;
1568 
1569         std::string reg_string = GetRegName<kRegView>(*reg);
1570         size_t reg_index;
1571         while ((reg_index = base.find(REG_TOKEN)) != std::string::npos) {
1572           base.replace(reg_index, ConstexprStrLen(REG_TOKEN), reg_string);
1573         }
1574 
1575         size_t imm_index = base.find(IMM_TOKEN);
1576         if (imm_index != std::string::npos) {
1577           std::ostringstream sreg;
1578           sreg << imm;
1579           std::string imm_string = sreg.str();
1580           base.replace(imm_index, ConstexprStrLen(IMM_TOKEN), imm_string);
1581         }
1582 
1583         if (str.size() > 0) {
1584           str += "\n";
1585         }
1586         str += base;
1587       }
1588     }
1589     // Add a newline at the end.
1590     str += "\n";
1591     return str;
1592   }
1593 
1594   // Override this to pad the code with NOPs to a certain size if needed.
Pad(std::vector<uint8_t> & data ATTRIBUTE_UNUSED)1595   virtual void Pad(std::vector<uint8_t>& data ATTRIBUTE_UNUSED) {
1596   }
1597 
DriverWrapper(const std::string & assembly_text,const std::string & test_name)1598   void DriverWrapper(const std::string& assembly_text, const std::string& test_name) {
1599     assembler_->FinalizeCode();
1600     size_t cs = assembler_->CodeSize();
1601     std::unique_ptr<std::vector<uint8_t>> data(new std::vector<uint8_t>(cs));
1602     MemoryRegion code(&(*data)[0], data->size());
1603     assembler_->FinalizeInstructions(code);
1604     Pad(*data);
1605     test_helper_->Driver(*data, assembly_text, test_name);
1606   }
1607 
1608   static constexpr size_t kWarnManyCombinationsThreshold = 500;
1609 
1610   MallocArenaPool pool_;
1611   std::unique_ptr<ArenaAllocator> allocator_;
1612   std::unique_ptr<Ass> assembler_;
1613   std::unique_ptr<AssemblerTestInfrastructure> test_helper_;
1614 
1615   DISALLOW_COPY_AND_ASSIGN(AssemblerTest);
1616 };
1617 
1618 }  // namespace art
1619 
1620 #endif  // ART_COMPILER_UTILS_ASSEMBLER_TEST_H_
1621