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