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