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