codegen_test.cc revision 20dfc797dc631bf8d655dcf123f46f13332d3074
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 fptr f = reinterpret_cast<fptr>(allocator.GetMemory()); 55#if defined(__arm__) 56 // For thumb we need the bottom bit set. 57 f = reinterpret_cast<fptr>(reinterpret_cast<uintptr_t>(f) + 1); 58#endif 59 int32_t result = f(); 60 if (has_result) { 61 CHECK_EQ(result, expected); 62 } 63} 64#endif 65 66static void TestCode(const uint16_t* data, bool has_result = false, int32_t expected = 0) { 67 ArenaPool pool; 68 ArenaAllocator arena(&pool); 69 HGraphBuilder builder(&arena); 70 const DexFile::CodeItem* item = reinterpret_cast<const DexFile::CodeItem*>(data); 71 HGraph* graph = builder.BuildGraph(*item); 72 ASSERT_NE(graph, nullptr); 73 InternalCodeAllocator allocator; 74 75 CodeGenerator* codegen = CodeGenerator::Create(&arena, graph, kX86); 76 codegen->CompileBaseline(&allocator); 77#if defined(__i386__) 78 Run(allocator, has_result, expected); 79#endif 80 81 codegen = CodeGenerator::Create(&arena, graph, kArm); 82 codegen->CompileBaseline(&allocator); 83#if defined(__arm__) 84 Run(allocator, has_result, expected); 85#endif 86 87 codegen = CodeGenerator::Create(&arena, graph, kX86_64); 88 codegen->CompileBaseline(&allocator); 89#if defined(__x86_64__) 90 Run(allocator, has_result, expected); 91#endif 92} 93 94TEST(CodegenTest, ReturnVoid) { 95 const uint16_t data[] = ZERO_REGISTER_CODE_ITEM(Instruction::RETURN_VOID); 96 TestCode(data); 97} 98 99TEST(CodegenTest, CFG1) { 100 const uint16_t data[] = ZERO_REGISTER_CODE_ITEM( 101 Instruction::GOTO | 0x100, 102 Instruction::RETURN_VOID); 103 104 TestCode(data); 105} 106 107TEST(CodegenTest, CFG2) { 108 const uint16_t data[] = ZERO_REGISTER_CODE_ITEM( 109 Instruction::GOTO | 0x100, 110 Instruction::GOTO | 0x100, 111 Instruction::RETURN_VOID); 112 113 TestCode(data); 114} 115 116TEST(CodegenTest, CFG3) { 117 const uint16_t data1[] = ZERO_REGISTER_CODE_ITEM( 118 Instruction::GOTO | 0x200, 119 Instruction::RETURN_VOID, 120 Instruction::GOTO | 0xFF00); 121 122 TestCode(data1); 123 124 const uint16_t data2[] = ZERO_REGISTER_CODE_ITEM( 125 Instruction::GOTO_16, 3, 126 Instruction::RETURN_VOID, 127 Instruction::GOTO_16, 0xFFFF); 128 129 TestCode(data2); 130 131 const uint16_t data3[] = ZERO_REGISTER_CODE_ITEM( 132 Instruction::GOTO_32, 4, 0, 133 Instruction::RETURN_VOID, 134 Instruction::GOTO_32, 0xFFFF, 0xFFFF); 135 136 TestCode(data3); 137} 138 139TEST(CodegenTest, CFG4) { 140 const uint16_t data[] = ZERO_REGISTER_CODE_ITEM( 141 Instruction::RETURN_VOID, 142 Instruction::GOTO | 0x100, 143 Instruction::GOTO | 0xFE00); 144 145 TestCode(data); 146} 147 148TEST(CodegenTest, CFG5) { 149 const uint16_t data[] = ONE_REGISTER_CODE_ITEM( 150 Instruction::CONST_4 | 0 | 0, 151 Instruction::IF_EQ, 3, 152 Instruction::GOTO | 0x100, 153 Instruction::RETURN_VOID); 154 155 TestCode(data); 156} 157 158TEST(CodegenTest, IntConstant) { 159 const uint16_t data[] = ONE_REGISTER_CODE_ITEM( 160 Instruction::CONST_4 | 0 | 0, 161 Instruction::RETURN_VOID); 162 163 TestCode(data); 164} 165 166TEST(CodegenTest, Return1) { 167 const uint16_t data[] = ONE_REGISTER_CODE_ITEM( 168 Instruction::CONST_4 | 0 | 0, 169 Instruction::RETURN | 0); 170 171 TestCode(data, true, 0); 172} 173 174TEST(CodegenTest, Return2) { 175 const uint16_t data[] = TWO_REGISTERS_CODE_ITEM( 176 Instruction::CONST_4 | 0 | 0, 177 Instruction::CONST_4 | 0 | 1 << 8, 178 Instruction::RETURN | 1 << 8); 179 180 TestCode(data, true, 0); 181} 182 183TEST(CodegenTest, Return3) { 184 const uint16_t data[] = TWO_REGISTERS_CODE_ITEM( 185 Instruction::CONST_4 | 0 | 0, 186 Instruction::CONST_4 | 1 << 8 | 1 << 12, 187 Instruction::RETURN | 1 << 8); 188 189 TestCode(data, true, 1); 190} 191 192TEST(CodegenTest, ReturnIf1) { 193 const uint16_t data[] = TWO_REGISTERS_CODE_ITEM( 194 Instruction::CONST_4 | 0 | 0, 195 Instruction::CONST_4 | 1 << 8 | 1 << 12, 196 Instruction::IF_EQ, 3, 197 Instruction::RETURN | 0 << 8, 198 Instruction::RETURN | 1 << 8); 199 200 TestCode(data, true, 1); 201} 202 203TEST(CodegenTest, ReturnIf2) { 204 const uint16_t data[] = TWO_REGISTERS_CODE_ITEM( 205 Instruction::CONST_4 | 0 | 0, 206 Instruction::CONST_4 | 1 << 8 | 1 << 12, 207 Instruction::IF_EQ | 0 << 4 | 1 << 8, 3, 208 Instruction::RETURN | 0 << 8, 209 Instruction::RETURN | 1 << 8); 210 211 TestCode(data, true, 0); 212} 213 214TEST(CodegenTest, ReturnAdd1) { 215 const uint16_t data[] = TWO_REGISTERS_CODE_ITEM( 216 Instruction::CONST_4 | 3 << 12 | 0, 217 Instruction::CONST_4 | 4 << 12 | 1 << 8, 218 Instruction::ADD_INT, 1 << 8 | 0, 219 Instruction::RETURN); 220 221 TestCode(data, true, 7); 222} 223 224TEST(CodegenTest, ReturnAdd2) { 225 const uint16_t data[] = TWO_REGISTERS_CODE_ITEM( 226 Instruction::CONST_4 | 3 << 12 | 0, 227 Instruction::CONST_4 | 4 << 12 | 1 << 8, 228 Instruction::ADD_INT_2ADDR | 1 << 12, 229 Instruction::RETURN); 230 231 TestCode(data, true, 7); 232} 233 234TEST(CodegenTest, ReturnAdd3) { 235 const uint16_t data[] = ONE_REGISTER_CODE_ITEM( 236 Instruction::CONST_4 | 4 << 12 | 0 << 8, 237 Instruction::ADD_INT_LIT8, 3 << 8 | 0, 238 Instruction::RETURN); 239 240 TestCode(data, true, 7); 241} 242 243TEST(CodegenTest, ReturnAdd4) { 244 const uint16_t data[] = ONE_REGISTER_CODE_ITEM( 245 Instruction::CONST_4 | 4 << 12 | 0 << 8, 246 Instruction::ADD_INT_LIT16, 3, 247 Instruction::RETURN); 248 249 TestCode(data, true, 7); 250} 251 252} // namespace art 253