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