1 /*
2  * Copyright (C) 2015 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 <memory>
18 #include <vector>
19 
20 #include "arch/instruction_set.h"
21 #include "cfi_test.h"
22 #include "gtest/gtest.h"
23 #include "optimizing/code_generator.h"
24 #include "optimizing/optimizing_unit_test.h"
25 #include "utils/assembler.h"
26 
27 #include "optimizing/optimizing_cfi_test_expected.inc"
28 
29 namespace art {
30 
31 // Run the tests only on host.
32 #ifndef HAVE_ANDROID_OS
33 
34 class OptimizingCFITest : public CFITest {
35  public:
36   // Enable this flag to generate the expected outputs.
37   static constexpr bool kGenerateExpected = false;
38 
TestImpl(InstructionSet isa,const char * isa_str,const std::vector<uint8_t> & expected_asm,const std::vector<uint8_t> & expected_cfi)39   void TestImpl(InstructionSet isa, const char* isa_str,
40                 const std::vector<uint8_t>& expected_asm,
41                 const std::vector<uint8_t>& expected_cfi) {
42     // Setup simple context.
43     ArenaPool pool;
44     ArenaAllocator allocator(&pool);
45     CompilerOptions opts;
46     std::unique_ptr<const InstructionSetFeatures> isa_features;
47     std::string error;
48     isa_features.reset(InstructionSetFeatures::FromVariant(isa, "default", &error));
49     HGraph* graph = CreateGraph(&allocator);
50     // Generate simple frame with some spills.
51     std::unique_ptr<CodeGenerator> code_gen(
52         CodeGenerator::Create(graph, isa, *isa_features.get(), opts));
53     const int frame_size = 64;
54     int core_reg = 0;
55     int fp_reg = 0;
56     for (int i = 0; i < 2; i++) {  // Two registers of each kind.
57       for (; core_reg < 32; core_reg++) {
58         if (code_gen->IsCoreCalleeSaveRegister(core_reg)) {
59           auto location = Location::RegisterLocation(core_reg);
60           code_gen->AddAllocatedRegister(location);
61           core_reg++;
62           break;
63         }
64       }
65       for (; fp_reg < 32; fp_reg++) {
66         if (code_gen->IsFloatingPointCalleeSaveRegister(fp_reg)) {
67           auto location = Location::FpuRegisterLocation(fp_reg);
68           code_gen->AddAllocatedRegister(location);
69           fp_reg++;
70           break;
71         }
72       }
73     }
74     code_gen->ComputeSpillMask();
75     code_gen->SetFrameSize(frame_size);
76     code_gen->GenerateFrameEntry();
77     code_gen->GenerateFrameExit();
78     // Get the outputs.
79     InternalCodeAllocator code_allocator;
80     code_gen->Finalize(&code_allocator);
81     const std::vector<uint8_t>& actual_asm = code_allocator.GetMemory();
82     Assembler* opt_asm = code_gen->GetAssembler();
83     const std::vector<uint8_t>& actual_cfi = *(opt_asm->cfi().data());
84 
85     if (kGenerateExpected) {
86       GenerateExpected(stdout, isa, isa_str, actual_asm, actual_cfi);
87     } else {
88       EXPECT_EQ(expected_asm, actual_asm);
89       EXPECT_EQ(expected_cfi, actual_cfi);
90     }
91   }
92 
93  private:
94   class InternalCodeAllocator : public CodeAllocator {
95    public:
InternalCodeAllocator()96     InternalCodeAllocator() {}
97 
Allocate(size_t size)98     virtual uint8_t* Allocate(size_t size) {
99       memory_.resize(size);
100       return memory_.data();
101     }
102 
GetMemory()103     const std::vector<uint8_t>& GetMemory() { return memory_; }
104 
105    private:
106     std::vector<uint8_t> memory_;
107 
108     DISALLOW_COPY_AND_ASSIGN(InternalCodeAllocator);
109   };
110 };
111 
112 #define TEST_ISA(isa) \
113   TEST_F(OptimizingCFITest, isa) { \
114     std::vector<uint8_t> expected_asm(expected_asm_##isa, \
115         expected_asm_##isa + arraysize(expected_asm_##isa)); \
116     std::vector<uint8_t> expected_cfi(expected_cfi_##isa, \
117         expected_cfi_##isa + arraysize(expected_cfi_##isa)); \
118     TestImpl(isa, #isa, expected_asm, expected_cfi); \
119   }
120 
121 TEST_ISA(kThumb2)
122 TEST_ISA(kArm64)
123 TEST_ISA(kX86)
124 TEST_ISA(kX86_64)
125 
126 #endif  // HAVE_ANDROID_OS
127 
128 }  // namespace art
129