blob: 7161eed9f94501517e458dc135feb9dec2eadfe2 [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"
Nicolas Geoffray8a16d972014-09-11 10:30:02 +010018#include "code_generator_arm.h"
19#include "code_generator_x86.h"
20#include "code_generator_x86_64.h"
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +000021#include "common_compiler_test.h"
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +000022#include "dex_file.h"
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +000023#include "dex_instruction.h"
24#include "instruction_set.h"
25#include "nodes.h"
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +000026#include "optimizing_unit_test.h"
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +000027
28#include "gtest/gtest.h"
29
30namespace art {
31
Nicolas Geoffray787c3072014-03-17 10:20:19 +000032class InternalCodeAllocator : public CodeAllocator {
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +000033 public:
Nicolas Geoffray787c3072014-03-17 10:20:19 +000034 InternalCodeAllocator() { }
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +000035
36 virtual uint8_t* Allocate(size_t size) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +000037 size_ = size;
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +000038 memory_.reset(new uint8_t[size]);
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +000039 return memory_.get();
40 }
41
Nicolas Geoffray787c3072014-03-17 10:20:19 +000042 size_t GetSize() const { return size_; }
43 uint8_t* GetMemory() const { return memory_.get(); }
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +000044
45 private:
Nicolas Geoffray787c3072014-03-17 10:20:19 +000046 size_t size_;
Ian Rogers700a4022014-05-19 16:49:03 -070047 std::unique_ptr<uint8_t[]> memory_;
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +000048
Nicolas Geoffray787c3072014-03-17 10:20:19 +000049 DISALLOW_COPY_AND_ASSIGN(InternalCodeAllocator);
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +000050};
51
Nicolas Geoffray8d486732014-07-16 16:23:40 +010052static void Run(const InternalCodeAllocator& allocator,
53 const CodeGenerator& codegen,
54 bool has_result,
55 int32_t expected) {
Nicolas Geoffray9cf35522014-06-09 18:40:10 +010056 typedef int32_t (*fptr)();
57 CommonCompilerTest::MakeExecutable(allocator.GetMemory(), allocator.GetSize());
Dave Allison20dfc792014-06-16 20:44:29 -070058 fptr f = reinterpret_cast<fptr>(allocator.GetMemory());
Nicolas Geoffray8d486732014-07-16 16:23:40 +010059 if (codegen.GetInstructionSet() == kThumb2) {
60 // For thumb we need the bottom bit set.
61 f = reinterpret_cast<fptr>(reinterpret_cast<uintptr_t>(f) + 1);
62 }
Dave Allison20dfc792014-06-16 20:44:29 -070063 int32_t result = f();
Nicolas Geoffray9cf35522014-06-09 18:40:10 +010064 if (has_result) {
65 CHECK_EQ(result, expected);
66 }
67}
68
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +000069static void TestCode(const uint16_t* data, bool has_result = false, int32_t expected = 0) {
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +000070 ArenaPool pool;
71 ArenaAllocator arena(&pool);
72 HGraphBuilder builder(&arena);
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +000073 const DexFile::CodeItem* item = reinterpret_cast<const DexFile::CodeItem*>(data);
74 HGraph* graph = builder.BuildGraph(*item);
Nicolas Geoffrayfbc695f2014-09-15 15:33:30 +000075 // Remove suspend checks, they cannot be executed in this context.
76 RemoveSuspendChecks(graph);
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +000077 ASSERT_NE(graph, nullptr);
Nicolas Geoffray787c3072014-03-17 10:20:19 +000078 InternalCodeAllocator allocator;
Nicolas Geoffray9cf35522014-06-09 18:40:10 +010079
Nicolas Geoffray8a16d972014-09-11 10:30:02 +010080 x86::CodeGeneratorX86 codegenX86(graph);
Nicolas Geoffray73e80c32014-07-22 17:47:56 +010081 // We avoid doing a stack overflow check that requires the runtime being setup,
82 // by making sure the compiler knows the methods we are running are leaf methods.
Nicolas Geoffray8a16d972014-09-11 10:30:02 +010083 codegenX86.CompileBaseline(&allocator, true);
84 if (kRuntimeISA == kX86) {
85 Run(allocator, codegenX86, has_result, expected);
86 }
Nicolas Geoffray9cf35522014-06-09 18:40:10 +010087
Nicolas Geoffray8a16d972014-09-11 10:30:02 +010088 arm::CodeGeneratorARM codegenARM(graph);
89 codegenARM.CompileBaseline(&allocator, true);
90 if (kRuntimeISA == kArm || kRuntimeISA == kThumb2) {
91 Run(allocator, codegenARM, has_result, expected);
92 }
Nicolas Geoffray9cf35522014-06-09 18:40:10 +010093
Nicolas Geoffray8a16d972014-09-11 10:30:02 +010094 x86_64::CodeGeneratorX86_64 codegenX86_64(graph);
95 codegenX86_64.CompileBaseline(&allocator, true);
96 if (kRuntimeISA == kX86_64) {
97 Run(allocator, codegenX86_64, has_result, expected);
98 }
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +000099}
100
101TEST(CodegenTest, ReturnVoid) {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000102 const uint16_t data[] = ZERO_REGISTER_CODE_ITEM(Instruction::RETURN_VOID);
103 TestCode(data);
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000104}
105
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000106TEST(CodegenTest, CFG1) {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000107 const uint16_t data[] = ZERO_REGISTER_CODE_ITEM(
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000108 Instruction::GOTO | 0x100,
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000109 Instruction::RETURN_VOID);
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000110
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000111 TestCode(data);
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000112}
113
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000114TEST(CodegenTest, CFG2) {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000115 const uint16_t data[] = ZERO_REGISTER_CODE_ITEM(
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000116 Instruction::GOTO | 0x100,
117 Instruction::GOTO | 0x100,
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000118 Instruction::RETURN_VOID);
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000119
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000120 TestCode(data);
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000121}
122
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000123TEST(CodegenTest, CFG3) {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000124 const uint16_t data1[] = ZERO_REGISTER_CODE_ITEM(
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000125 Instruction::GOTO | 0x200,
126 Instruction::RETURN_VOID,
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000127 Instruction::GOTO | 0xFF00);
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000128
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000129 TestCode(data1);
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000130
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000131 const uint16_t data2[] = ZERO_REGISTER_CODE_ITEM(
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000132 Instruction::GOTO_16, 3,
133 Instruction::RETURN_VOID,
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000134 Instruction::GOTO_16, 0xFFFF);
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000135
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000136 TestCode(data2);
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000137
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000138 const uint16_t data3[] = ZERO_REGISTER_CODE_ITEM(
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000139 Instruction::GOTO_32, 4, 0,
140 Instruction::RETURN_VOID,
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000141 Instruction::GOTO_32, 0xFFFF, 0xFFFF);
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000142
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000143 TestCode(data3);
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000144}
145
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000146TEST(CodegenTest, CFG4) {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000147 const uint16_t data[] = ZERO_REGISTER_CODE_ITEM(
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000148 Instruction::RETURN_VOID,
149 Instruction::GOTO | 0x100,
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000150 Instruction::GOTO | 0xFE00);
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000151
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000152 TestCode(data);
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000153}
154
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000155TEST(CodegenTest, CFG5) {
156 const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
157 Instruction::CONST_4 | 0 | 0,
158 Instruction::IF_EQ, 3,
159 Instruction::GOTO | 0x100,
160 Instruction::RETURN_VOID);
161
162 TestCode(data);
163}
164
165TEST(CodegenTest, IntConstant) {
166 const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
167 Instruction::CONST_4 | 0 | 0,
168 Instruction::RETURN_VOID);
169
170 TestCode(data);
171}
172
173TEST(CodegenTest, Return1) {
174 const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
175 Instruction::CONST_4 | 0 | 0,
176 Instruction::RETURN | 0);
177
178 TestCode(data, true, 0);
179}
180
181TEST(CodegenTest, Return2) {
182 const uint16_t data[] = TWO_REGISTERS_CODE_ITEM(
183 Instruction::CONST_4 | 0 | 0,
184 Instruction::CONST_4 | 0 | 1 << 8,
185 Instruction::RETURN | 1 << 8);
186
187 TestCode(data, true, 0);
188}
189
190TEST(CodegenTest, Return3) {
191 const uint16_t data[] = TWO_REGISTERS_CODE_ITEM(
192 Instruction::CONST_4 | 0 | 0,
193 Instruction::CONST_4 | 1 << 8 | 1 << 12,
194 Instruction::RETURN | 1 << 8);
195
196 TestCode(data, true, 1);
197}
198
199TEST(CodegenTest, ReturnIf1) {
200 const uint16_t data[] = TWO_REGISTERS_CODE_ITEM(
201 Instruction::CONST_4 | 0 | 0,
202 Instruction::CONST_4 | 1 << 8 | 1 << 12,
203 Instruction::IF_EQ, 3,
204 Instruction::RETURN | 0 << 8,
205 Instruction::RETURN | 1 << 8);
206
207 TestCode(data, true, 1);
208}
209
210TEST(CodegenTest, ReturnIf2) {
211 const uint16_t data[] = TWO_REGISTERS_CODE_ITEM(
212 Instruction::CONST_4 | 0 | 0,
213 Instruction::CONST_4 | 1 << 8 | 1 << 12,
214 Instruction::IF_EQ | 0 << 4 | 1 << 8, 3,
215 Instruction::RETURN | 0 << 8,
216 Instruction::RETURN | 1 << 8);
217
218 TestCode(data, true, 0);
219}
220
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000221TEST(CodegenTest, ReturnAdd1) {
222 const uint16_t data[] = TWO_REGISTERS_CODE_ITEM(
223 Instruction::CONST_4 | 3 << 12 | 0,
224 Instruction::CONST_4 | 4 << 12 | 1 << 8,
225 Instruction::ADD_INT, 1 << 8 | 0,
226 Instruction::RETURN);
227
228 TestCode(data, true, 7);
229}
230
231TEST(CodegenTest, ReturnAdd2) {
232 const uint16_t data[] = TWO_REGISTERS_CODE_ITEM(
233 Instruction::CONST_4 | 3 << 12 | 0,
234 Instruction::CONST_4 | 4 << 12 | 1 << 8,
235 Instruction::ADD_INT_2ADDR | 1 << 12,
236 Instruction::RETURN);
237
238 TestCode(data, true, 7);
239}
240
241TEST(CodegenTest, ReturnAdd3) {
242 const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
243 Instruction::CONST_4 | 4 << 12 | 0 << 8,
244 Instruction::ADD_INT_LIT8, 3 << 8 | 0,
245 Instruction::RETURN);
246
247 TestCode(data, true, 7);
248}
249
250TEST(CodegenTest, ReturnAdd4) {
251 const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
252 Instruction::CONST_4 | 4 << 12 | 0 << 8,
253 Instruction::ADD_INT_LIT16, 3,
254 Instruction::RETURN);
255
256 TestCode(data, true, 7);
257}
258
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000259} // namespace art