blob: c3baf1a7b72491a5e74a4f8266bccf8f3256661f [file] [log] [blame]
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +00001/*
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"
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +000020#include "dex_file.h"
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +000021#include "dex_instruction.h"
22#include "instruction_set.h"
23#include "nodes.h"
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +000024#include "optimizing_unit_test.h"
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +000025
26#include "gtest/gtest.h"
27
28namespace art {
29
Nicolas Geoffray787c3072014-03-17 10:20:19 +000030class InternalCodeAllocator : public CodeAllocator {
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +000031 public:
Nicolas Geoffray787c3072014-03-17 10:20:19 +000032 InternalCodeAllocator() { }
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +000033
34 virtual uint8_t* Allocate(size_t size) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +000035 size_ = size;
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +000036 memory_.reset(new uint8_t[size]);
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +000037 return memory_.get();
38 }
39
Nicolas Geoffray787c3072014-03-17 10:20:19 +000040 size_t GetSize() const { return size_; }
41 uint8_t* GetMemory() const { return memory_.get(); }
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +000042
43 private:
Nicolas Geoffray787c3072014-03-17 10:20:19 +000044 size_t size_;
Ian Rogers700a4022014-05-19 16:49:03 -070045 std::unique_ptr<uint8_t[]> memory_;
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +000046
Nicolas Geoffray787c3072014-03-17 10:20:19 +000047 DISALLOW_COPY_AND_ASSIGN(InternalCodeAllocator);
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +000048};
49
Nicolas Geoffray49c105d2014-06-13 10:29:43 +010050#if defined(__i386__) || defined(__arm__) || defined(__x86_64__)
Nicolas Geoffray9cf35522014-06-09 18:40:10 +010051static 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}
Nicolas Geoffray49c105d2014-06-13 10:29:43 +010059#endif
Nicolas Geoffray9cf35522014-06-09 18:40:10 +010060
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +000061static void TestCode(const uint16_t* data, bool has_result = false, int32_t expected = 0) {
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +000062 ArenaPool pool;
63 ArenaAllocator arena(&pool);
64 HGraphBuilder builder(&arena);
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +000065 const DexFile::CodeItem* item = reinterpret_cast<const DexFile::CodeItem*>(data);
66 HGraph* graph = builder.BuildGraph(*item);
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +000067 ASSERT_NE(graph, nullptr);
Nicolas Geoffray787c3072014-03-17 10:20:19 +000068 InternalCodeAllocator allocator;
Nicolas Geoffray9cf35522014-06-09 18:40:10 +010069
Nicolas Geoffray787c3072014-03-17 10:20:19 +000070 CodeGenerator* codegen = CodeGenerator::Create(&arena, graph, kX86);
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +010071 codegen->CompileBaseline(&allocator);
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +000072#if defined(__i386__)
Nicolas Geoffray9cf35522014-06-09 18:40:10 +010073 Run(allocator, has_result, expected);
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +000074#endif
Nicolas Geoffray9cf35522014-06-09 18:40:10 +010075
Nicolas Geoffray787c3072014-03-17 10:20:19 +000076 codegen = CodeGenerator::Create(&arena, graph, kArm);
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +010077 codegen->CompileBaseline(&allocator);
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +000078#if defined(__arm__)
Nicolas Geoffray9cf35522014-06-09 18:40:10 +010079 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);
Nicolas Geoffray39d57e22014-03-13 10:28:41 +000086#endif
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +000087}
88
89TEST(CodegenTest, ReturnVoid) {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +000090 const uint16_t data[] = ZERO_REGISTER_CODE_ITEM(Instruction::RETURN_VOID);
91 TestCode(data);
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +000092}
93
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +000094TEST(CodegenTest, CFG1) {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +000095 const uint16_t data[] = ZERO_REGISTER_CODE_ITEM(
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +000096 Instruction::GOTO | 0x100,
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +000097 Instruction::RETURN_VOID);
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +000098
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +000099 TestCode(data);
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000100}
101
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000102TEST(CodegenTest, CFG2) {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000103 const uint16_t data[] = ZERO_REGISTER_CODE_ITEM(
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000104 Instruction::GOTO | 0x100,
105 Instruction::GOTO | 0x100,
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000106 Instruction::RETURN_VOID);
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000107
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000108 TestCode(data);
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000109}
110
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000111TEST(CodegenTest, CFG3) {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000112 const uint16_t data1[] = ZERO_REGISTER_CODE_ITEM(
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000113 Instruction::GOTO | 0x200,
114 Instruction::RETURN_VOID,
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000115 Instruction::GOTO | 0xFF00);
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000116
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000117 TestCode(data1);
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000118
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000119 const uint16_t data2[] = ZERO_REGISTER_CODE_ITEM(
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000120 Instruction::GOTO_16, 3,
121 Instruction::RETURN_VOID,
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000122 Instruction::GOTO_16, 0xFFFF);
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000123
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000124 TestCode(data2);
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000125
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000126 const uint16_t data3[] = ZERO_REGISTER_CODE_ITEM(
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000127 Instruction::GOTO_32, 4, 0,
128 Instruction::RETURN_VOID,
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000129 Instruction::GOTO_32, 0xFFFF, 0xFFFF);
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000130
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000131 TestCode(data3);
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000132}
133
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000134TEST(CodegenTest, CFG4) {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000135 const uint16_t data[] = ZERO_REGISTER_CODE_ITEM(
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000136 Instruction::RETURN_VOID,
137 Instruction::GOTO | 0x100,
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000138 Instruction::GOTO | 0xFE00);
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000139
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000140 TestCode(data);
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000141}
142
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000143TEST(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
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000209TEST(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
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000247} // namespace art