codegen_test.cc revision 49c105d624e4bf8e56b85caaecfeb80864bd3f59
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#include "builder.h" 18#include "code_generator.h" 19#include "common_compiler_test.h" 20#include "dex_file.h" 21#include "dex_instruction.h" 22#include "instruction_set.h" 23#include "nodes.h" 24#include "optimizing_unit_test.h" 25 26#include "gtest/gtest.h" 27 28namespace art { 29 30class InternalCodeAllocator : public CodeAllocator { 31 public: 32 InternalCodeAllocator() { } 33 34 virtual uint8_t* Allocate(size_t size) { 35 size_ = size; 36 memory_.reset(new uint8_t[size]); 37 return memory_.get(); 38 } 39 40 size_t GetSize() const { return size_; } 41 uint8_t* GetMemory() const { return memory_.get(); } 42 43 private: 44 size_t size_; 45 std::unique_ptr<uint8_t[]> memory_; 46 47 DISALLOW_COPY_AND_ASSIGN(InternalCodeAllocator); 48}; 49 50#if defined(__i386__) || defined(__arm__) || defined(__x86_64__) 51static void Run(const InternalCodeAllocator& allocator, bool has_result, int32_t expected) { 52 typedef int32_t (*fptr)(); 53 CommonCompilerTest::MakeExecutable(allocator.GetMemory(), allocator.GetSize()); 54 int32_t result = reinterpret_cast<fptr>(allocator.GetMemory())(); 55 if (has_result) { 56 CHECK_EQ(result, expected); 57 } 58} 59#endif 60 61static void TestCode(const uint16_t* data, bool has_result = false, int32_t expected = 0) { 62 ArenaPool pool; 63 ArenaAllocator arena(&pool); 64 HGraphBuilder builder(&arena); 65 const DexFile::CodeItem* item = reinterpret_cast<const DexFile::CodeItem*>(data); 66 HGraph* graph = builder.BuildGraph(*item); 67 ASSERT_NE(graph, nullptr); 68 InternalCodeAllocator allocator; 69 70 CodeGenerator* codegen = CodeGenerator::Create(&arena, graph, kX86); 71 codegen->CompileBaseline(&allocator); 72#if defined(__i386__) 73 Run(allocator, has_result, expected); 74#endif 75 76 codegen = CodeGenerator::Create(&arena, graph, kArm); 77 codegen->CompileBaseline(&allocator); 78#if defined(__arm__) 79 Run(allocator, has_result, expected); 80#endif 81 82 codegen = CodeGenerator::Create(&arena, graph, kX86_64); 83 codegen->CompileBaseline(&allocator); 84#if defined(__x86_64__) 85 Run(allocator, has_result, expected); 86#endif 87} 88 89TEST(CodegenTest, ReturnVoid) { 90 const uint16_t data[] = ZERO_REGISTER_CODE_ITEM(Instruction::RETURN_VOID); 91 TestCode(data); 92} 93 94TEST(CodegenTest, CFG1) { 95 const uint16_t data[] = ZERO_REGISTER_CODE_ITEM( 96 Instruction::GOTO | 0x100, 97 Instruction::RETURN_VOID); 98 99 TestCode(data); 100} 101 102TEST(CodegenTest, CFG2) { 103 const uint16_t data[] = ZERO_REGISTER_CODE_ITEM( 104 Instruction::GOTO | 0x100, 105 Instruction::GOTO | 0x100, 106 Instruction::RETURN_VOID); 107 108 TestCode(data); 109} 110 111TEST(CodegenTest, CFG3) { 112 const uint16_t data1[] = ZERO_REGISTER_CODE_ITEM( 113 Instruction::GOTO | 0x200, 114 Instruction::RETURN_VOID, 115 Instruction::GOTO | 0xFF00); 116 117 TestCode(data1); 118 119 const uint16_t data2[] = ZERO_REGISTER_CODE_ITEM( 120 Instruction::GOTO_16, 3, 121 Instruction::RETURN_VOID, 122 Instruction::GOTO_16, 0xFFFF); 123 124 TestCode(data2); 125 126 const uint16_t data3[] = ZERO_REGISTER_CODE_ITEM( 127 Instruction::GOTO_32, 4, 0, 128 Instruction::RETURN_VOID, 129 Instruction::GOTO_32, 0xFFFF, 0xFFFF); 130 131 TestCode(data3); 132} 133 134TEST(CodegenTest, CFG4) { 135 const uint16_t data[] = ZERO_REGISTER_CODE_ITEM( 136 Instruction::RETURN_VOID, 137 Instruction::GOTO | 0x100, 138 Instruction::GOTO | 0xFE00); 139 140 TestCode(data); 141} 142 143TEST(CodegenTest, CFG5) { 144 const uint16_t data[] = ONE_REGISTER_CODE_ITEM( 145 Instruction::CONST_4 | 0 | 0, 146 Instruction::IF_EQ, 3, 147 Instruction::GOTO | 0x100, 148 Instruction::RETURN_VOID); 149 150 TestCode(data); 151} 152 153TEST(CodegenTest, IntConstant) { 154 const uint16_t data[] = ONE_REGISTER_CODE_ITEM( 155 Instruction::CONST_4 | 0 | 0, 156 Instruction::RETURN_VOID); 157 158 TestCode(data); 159} 160 161TEST(CodegenTest, Return1) { 162 const uint16_t data[] = ONE_REGISTER_CODE_ITEM( 163 Instruction::CONST_4 | 0 | 0, 164 Instruction::RETURN | 0); 165 166 TestCode(data, true, 0); 167} 168 169TEST(CodegenTest, Return2) { 170 const uint16_t data[] = TWO_REGISTERS_CODE_ITEM( 171 Instruction::CONST_4 | 0 | 0, 172 Instruction::CONST_4 | 0 | 1 << 8, 173 Instruction::RETURN | 1 << 8); 174 175 TestCode(data, true, 0); 176} 177 178TEST(CodegenTest, Return3) { 179 const uint16_t data[] = TWO_REGISTERS_CODE_ITEM( 180 Instruction::CONST_4 | 0 | 0, 181 Instruction::CONST_4 | 1 << 8 | 1 << 12, 182 Instruction::RETURN | 1 << 8); 183 184 TestCode(data, true, 1); 185} 186 187TEST(CodegenTest, ReturnIf1) { 188 const uint16_t data[] = TWO_REGISTERS_CODE_ITEM( 189 Instruction::CONST_4 | 0 | 0, 190 Instruction::CONST_4 | 1 << 8 | 1 << 12, 191 Instruction::IF_EQ, 3, 192 Instruction::RETURN | 0 << 8, 193 Instruction::RETURN | 1 << 8); 194 195 TestCode(data, true, 1); 196} 197 198TEST(CodegenTest, ReturnIf2) { 199 const uint16_t data[] = TWO_REGISTERS_CODE_ITEM( 200 Instruction::CONST_4 | 0 | 0, 201 Instruction::CONST_4 | 1 << 8 | 1 << 12, 202 Instruction::IF_EQ | 0 << 4 | 1 << 8, 3, 203 Instruction::RETURN | 0 << 8, 204 Instruction::RETURN | 1 << 8); 205 206 TestCode(data, true, 0); 207} 208 209TEST(CodegenTest, ReturnAdd1) { 210 const uint16_t data[] = TWO_REGISTERS_CODE_ITEM( 211 Instruction::CONST_4 | 3 << 12 | 0, 212 Instruction::CONST_4 | 4 << 12 | 1 << 8, 213 Instruction::ADD_INT, 1 << 8 | 0, 214 Instruction::RETURN); 215 216 TestCode(data, true, 7); 217} 218 219TEST(CodegenTest, ReturnAdd2) { 220 const uint16_t data[] = TWO_REGISTERS_CODE_ITEM( 221 Instruction::CONST_4 | 3 << 12 | 0, 222 Instruction::CONST_4 | 4 << 12 | 1 << 8, 223 Instruction::ADD_INT_2ADDR | 1 << 12, 224 Instruction::RETURN); 225 226 TestCode(data, true, 7); 227} 228 229TEST(CodegenTest, ReturnAdd3) { 230 const uint16_t data[] = ONE_REGISTER_CODE_ITEM( 231 Instruction::CONST_4 | 4 << 12 | 0 << 8, 232 Instruction::ADD_INT_LIT8, 3 << 8 | 0, 233 Instruction::RETURN); 234 235 TestCode(data, true, 7); 236} 237 238TEST(CodegenTest, ReturnAdd4) { 239 const uint16_t data[] = ONE_REGISTER_CODE_ITEM( 240 Instruction::CONST_4 | 4 << 12 | 0 << 8, 241 Instruction::ADD_INT_LIT16, 3, 242 Instruction::RETURN); 243 244 TestCode(data, true, 7); 245} 246 247} // namespace art 248