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_JNI_MACRO_ASSEMBLER_TEST_H_
18 #define ART_COMPILER_UTILS_JNI_MACRO_ASSEMBLER_TEST_H_
19 
20 #include "jni_macro_assembler.h"
21 
22 #include "assembler_test_base.h"
23 #include "common_runtime_test.h"  // For ScratchFile
24 
25 #include <cstdio>
26 #include <cstdlib>
27 #include <fstream>
28 #include <iterator>
29 #include <sys/stat.h>
30 
31 namespace art {
32 
33 template<typename Ass>
34 class JNIMacroAssemblerTest : public testing::Test {
35  public:
GetAssembler()36   Ass* GetAssembler() {
37     return assembler_.get();
38   }
39 
40   typedef std::string (*TestFn)(JNIMacroAssemblerTest* assembler_test, Ass* assembler);
41 
DriverFn(TestFn f,const std::string & test_name)42   void DriverFn(TestFn f, const std::string& test_name) {
43     DriverWrapper(f(this, assembler_.get()), test_name);
44   }
45 
46   // This driver assumes the assembler has already been called.
DriverStr(const std::string & assembly_string,const std::string & test_name)47   void DriverStr(const std::string& assembly_string, const std::string& test_name) {
48     DriverWrapper(assembly_string, test_name);
49   }
50 
51   // This is intended to be run as a test.
CheckTools()52   bool CheckTools() {
53     return test_helper_->CheckTools();
54   }
55 
56  protected:
JNIMacroAssemblerTest()57   explicit JNIMacroAssemblerTest() {}
58 
SetUp()59   void SetUp() OVERRIDE {
60     arena_.reset(new ArenaAllocator(&pool_));
61     assembler_.reset(CreateAssembler(arena_.get()));
62     test_helper_.reset(
63         new AssemblerTestInfrastructure(GetArchitectureString(),
64                                         GetAssemblerCmdName(),
65                                         GetAssemblerParameters(),
66                                         GetObjdumpCmdName(),
67                                         GetObjdumpParameters(),
68                                         GetDisassembleCmdName(),
69                                         GetDisassembleParameters(),
70                                         GetAssemblyHeader()));
71 
72     SetUpHelpers();
73   }
74 
TearDown()75   void TearDown() OVERRIDE {
76     test_helper_.reset();  // Clean up the helper.
77     assembler_.reset();
78     arena_.reset();
79   }
80 
81   // Override this to set up any architecture-specific things, e.g., CPU revision.
CreateAssembler(ArenaAllocator * arena)82   virtual Ass* CreateAssembler(ArenaAllocator* arena) {
83     return new (arena) Ass(arena);
84   }
85 
86   // Override this to set up any architecture-specific things, e.g., register vectors.
SetUpHelpers()87   virtual void SetUpHelpers() {}
88 
89   // Get the typically used name for this architecture, e.g., aarch64, x86_64, ...
90   virtual std::string GetArchitectureString() = 0;
91 
92   // Get the name of the assembler, e.g., "as" by default.
GetAssemblerCmdName()93   virtual std::string GetAssemblerCmdName() {
94     return "as";
95   }
96 
97   // Switches to the assembler command. Default none.
GetAssemblerParameters()98   virtual std::string GetAssemblerParameters() {
99     return "";
100   }
101 
102   // Get the name of the objdump, e.g., "objdump" by default.
GetObjdumpCmdName()103   virtual std::string GetObjdumpCmdName() {
104     return "objdump";
105   }
106 
107   // Switches to the objdump command. Default is " -h".
GetObjdumpParameters()108   virtual std::string GetObjdumpParameters() {
109     return " -h";
110   }
111 
112   // Get the name of the objdump, e.g., "objdump" by default.
GetDisassembleCmdName()113   virtual std::string GetDisassembleCmdName() {
114     return "objdump";
115   }
116 
117   // Switches to the objdump command. As it's a binary, one needs to push the architecture and
118   // such to objdump, so it's architecture-specific and there is no default.
119   virtual std::string GetDisassembleParameters() = 0;
120 
121   // If the assembly file needs a header, return it in a sub-class.
GetAssemblyHeader()122   virtual const char* GetAssemblyHeader() {
123     return nullptr;
124   }
125 
126  private:
127   // Override this to pad the code with NOPs to a certain size if needed.
Pad(std::vector<uint8_t> & data ATTRIBUTE_UNUSED)128   virtual void Pad(std::vector<uint8_t>& data ATTRIBUTE_UNUSED) {
129   }
130 
DriverWrapper(const std::string & assembly_text,const std::string & test_name)131   void DriverWrapper(const std::string& assembly_text, const std::string& test_name) {
132     assembler_->FinalizeCode();
133     size_t cs = assembler_->CodeSize();
134     std::unique_ptr<std::vector<uint8_t>> data(new std::vector<uint8_t>(cs));
135     MemoryRegion code(&(*data)[0], data->size());
136     assembler_->FinalizeInstructions(code);
137     Pad(*data);
138     test_helper_->Driver(*data, assembly_text, test_name);
139   }
140 
141   ArenaPool pool_;
142   std::unique_ptr<ArenaAllocator> arena_;
143   std::unique_ptr<Ass> assembler_;
144   std::unique_ptr<AssemblerTestInfrastructure> test_helper_;
145 
146   DISALLOW_COPY_AND_ASSIGN(JNIMacroAssemblerTest);
147 };
148 
149 }  // namespace art
150 
151 #endif  // ART_COMPILER_UTILS_JNI_MACRO_ASSEMBLER_TEST_H_
152