1*795d594fSAndroid Build Coastguard Worker /*
2*795d594fSAndroid Build Coastguard Worker * Copyright (C) 2015 The Android Open Source Project
3*795d594fSAndroid Build Coastguard Worker *
4*795d594fSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*795d594fSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*795d594fSAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*795d594fSAndroid Build Coastguard Worker *
8*795d594fSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*795d594fSAndroid Build Coastguard Worker *
10*795d594fSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*795d594fSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*795d594fSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*795d594fSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*795d594fSAndroid Build Coastguard Worker * limitations under the License.
15*795d594fSAndroid Build Coastguard Worker */
16*795d594fSAndroid Build Coastguard Worker
17*795d594fSAndroid Build Coastguard Worker #include <memory>
18*795d594fSAndroid Build Coastguard Worker #include <vector>
19*795d594fSAndroid Build Coastguard Worker
20*795d594fSAndroid Build Coastguard Worker #include "arch/instruction_set.h"
21*795d594fSAndroid Build Coastguard Worker #include "base/macros.h"
22*795d594fSAndroid Build Coastguard Worker #include "base/runtime_debug.h"
23*795d594fSAndroid Build Coastguard Worker #include "cfi_test.h"
24*795d594fSAndroid Build Coastguard Worker #include "driver/compiler_options.h"
25*795d594fSAndroid Build Coastguard Worker #include "gtest/gtest.h"
26*795d594fSAndroid Build Coastguard Worker #include "optimizing/code_generator.h"
27*795d594fSAndroid Build Coastguard Worker #include "optimizing/optimizing_unit_test.h"
28*795d594fSAndroid Build Coastguard Worker #include "read_barrier_config.h"
29*795d594fSAndroid Build Coastguard Worker #include "utils/arm/assembler_arm_vixl.h"
30*795d594fSAndroid Build Coastguard Worker #include "utils/assembler.h"
31*795d594fSAndroid Build Coastguard Worker
32*795d594fSAndroid Build Coastguard Worker #include "optimizing/optimizing_cfi_test_expected.inc"
33*795d594fSAndroid Build Coastguard Worker
34*795d594fSAndroid Build Coastguard Worker namespace vixl32 = vixl::aarch32;
35*795d594fSAndroid Build Coastguard Worker
36*795d594fSAndroid Build Coastguard Worker namespace art HIDDEN {
37*795d594fSAndroid Build Coastguard Worker
38*795d594fSAndroid Build Coastguard Worker class OptimizingCFITest : public CFITest, public OptimizingUnitTestHelper {
39*795d594fSAndroid Build Coastguard Worker public:
40*795d594fSAndroid Build Coastguard Worker // Enable this flag to generate the expected outputs.
41*795d594fSAndroid Build Coastguard Worker static constexpr bool kGenerateExpected = false;
42*795d594fSAndroid Build Coastguard Worker
OptimizingCFITest()43*795d594fSAndroid Build Coastguard Worker OptimizingCFITest()
44*795d594fSAndroid Build Coastguard Worker : graph_(nullptr),
45*795d594fSAndroid Build Coastguard Worker code_gen_(),
46*795d594fSAndroid Build Coastguard Worker blocks_(GetAllocator()->Adapter()) {}
47*795d594fSAndroid Build Coastguard Worker
SetUpFrame(InstructionSet isa)48*795d594fSAndroid Build Coastguard Worker void SetUpFrame(InstructionSet isa) {
49*795d594fSAndroid Build Coastguard Worker OverrideInstructionSetFeatures(isa, "default");
50*795d594fSAndroid Build Coastguard Worker
51*795d594fSAndroid Build Coastguard Worker // Ensure that slow-debug is off, so that there is no unexpected read-barrier check emitted.
52*795d594fSAndroid Build Coastguard Worker SetRuntimeDebugFlagsEnabled(false);
53*795d594fSAndroid Build Coastguard Worker
54*795d594fSAndroid Build Coastguard Worker // Setup simple context.
55*795d594fSAndroid Build Coastguard Worker graph_ = CreateGraph();
56*795d594fSAndroid Build Coastguard Worker // Generate simple frame with some spills.
57*795d594fSAndroid Build Coastguard Worker code_gen_ = CodeGenerator::Create(graph_, *compiler_options_);
58*795d594fSAndroid Build Coastguard Worker code_gen_->GetAssembler()->cfi().SetEnabled(true);
59*795d594fSAndroid Build Coastguard Worker code_gen_->InitializeCodeGenerationData();
60*795d594fSAndroid Build Coastguard Worker const int frame_size = 64;
61*795d594fSAndroid Build Coastguard Worker int core_reg = 0;
62*795d594fSAndroid Build Coastguard Worker int fp_reg = 0;
63*795d594fSAndroid Build Coastguard Worker for (int i = 0; i < 2; i++) { // Two registers of each kind.
64*795d594fSAndroid Build Coastguard Worker for (; core_reg < 32; core_reg++) {
65*795d594fSAndroid Build Coastguard Worker if (code_gen_->IsCoreCalleeSaveRegister(core_reg)) {
66*795d594fSAndroid Build Coastguard Worker auto location = Location::RegisterLocation(core_reg);
67*795d594fSAndroid Build Coastguard Worker code_gen_->AddAllocatedRegister(location);
68*795d594fSAndroid Build Coastguard Worker core_reg++;
69*795d594fSAndroid Build Coastguard Worker break;
70*795d594fSAndroid Build Coastguard Worker }
71*795d594fSAndroid Build Coastguard Worker }
72*795d594fSAndroid Build Coastguard Worker for (; fp_reg < 32; fp_reg++) {
73*795d594fSAndroid Build Coastguard Worker if (code_gen_->IsFloatingPointCalleeSaveRegister(fp_reg)) {
74*795d594fSAndroid Build Coastguard Worker auto location = Location::FpuRegisterLocation(fp_reg);
75*795d594fSAndroid Build Coastguard Worker code_gen_->AddAllocatedRegister(location);
76*795d594fSAndroid Build Coastguard Worker fp_reg++;
77*795d594fSAndroid Build Coastguard Worker break;
78*795d594fSAndroid Build Coastguard Worker }
79*795d594fSAndroid Build Coastguard Worker }
80*795d594fSAndroid Build Coastguard Worker }
81*795d594fSAndroid Build Coastguard Worker code_gen_->block_order_ = &blocks_;
82*795d594fSAndroid Build Coastguard Worker code_gen_->ComputeSpillMask();
83*795d594fSAndroid Build Coastguard Worker code_gen_->SetFrameSize(frame_size);
84*795d594fSAndroid Build Coastguard Worker code_gen_->GenerateFrameEntry();
85*795d594fSAndroid Build Coastguard Worker }
86*795d594fSAndroid Build Coastguard Worker
Finish()87*795d594fSAndroid Build Coastguard Worker void Finish() {
88*795d594fSAndroid Build Coastguard Worker code_gen_->GenerateFrameExit();
89*795d594fSAndroid Build Coastguard Worker code_gen_->Finalize();
90*795d594fSAndroid Build Coastguard Worker }
91*795d594fSAndroid Build Coastguard Worker
Check(InstructionSet isa,const char * isa_str,const std::vector<uint8_t> & expected_asm,const std::vector<uint8_t> & expected_cfi)92*795d594fSAndroid Build Coastguard Worker void Check(InstructionSet isa,
93*795d594fSAndroid Build Coastguard Worker const char* isa_str,
94*795d594fSAndroid Build Coastguard Worker const std::vector<uint8_t>& expected_asm,
95*795d594fSAndroid Build Coastguard Worker const std::vector<uint8_t>& expected_cfi) {
96*795d594fSAndroid Build Coastguard Worker // Get the outputs.
97*795d594fSAndroid Build Coastguard Worker ArrayRef<const uint8_t> actual_asm = code_gen_->GetCode();
98*795d594fSAndroid Build Coastguard Worker Assembler* opt_asm = code_gen_->GetAssembler();
99*795d594fSAndroid Build Coastguard Worker ArrayRef<const uint8_t> actual_cfi(*(opt_asm->cfi().data()));
100*795d594fSAndroid Build Coastguard Worker
101*795d594fSAndroid Build Coastguard Worker if (kGenerateExpected) {
102*795d594fSAndroid Build Coastguard Worker GenerateExpected(stdout, isa, isa_str, actual_asm, actual_cfi);
103*795d594fSAndroid Build Coastguard Worker } else {
104*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(ArrayRef<const uint8_t>(expected_asm), actual_asm);
105*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(ArrayRef<const uint8_t>(expected_cfi), actual_cfi);
106*795d594fSAndroid Build Coastguard Worker }
107*795d594fSAndroid Build Coastguard Worker }
108*795d594fSAndroid Build Coastguard Worker
TestImpl(InstructionSet isa,const char * isa_str,const std::vector<uint8_t> & expected_asm,const std::vector<uint8_t> & expected_cfi)109*795d594fSAndroid Build Coastguard Worker void TestImpl(InstructionSet isa, const char*
110*795d594fSAndroid Build Coastguard Worker isa_str,
111*795d594fSAndroid Build Coastguard Worker const std::vector<uint8_t>& expected_asm,
112*795d594fSAndroid Build Coastguard Worker const std::vector<uint8_t>& expected_cfi) {
113*795d594fSAndroid Build Coastguard Worker SetUpFrame(isa);
114*795d594fSAndroid Build Coastguard Worker Finish();
115*795d594fSAndroid Build Coastguard Worker Check(isa, isa_str, expected_asm, expected_cfi);
116*795d594fSAndroid Build Coastguard Worker }
117*795d594fSAndroid Build Coastguard Worker
GetCodeGenerator()118*795d594fSAndroid Build Coastguard Worker CodeGenerator* GetCodeGenerator() {
119*795d594fSAndroid Build Coastguard Worker return code_gen_.get();
120*795d594fSAndroid Build Coastguard Worker }
121*795d594fSAndroid Build Coastguard Worker
122*795d594fSAndroid Build Coastguard Worker private:
123*795d594fSAndroid Build Coastguard Worker HGraph* graph_;
124*795d594fSAndroid Build Coastguard Worker std::unique_ptr<CodeGenerator> code_gen_;
125*795d594fSAndroid Build Coastguard Worker ArenaVector<HBasicBlock*> blocks_;
126*795d594fSAndroid Build Coastguard Worker };
127*795d594fSAndroid Build Coastguard Worker
128*795d594fSAndroid Build Coastguard Worker #define TEST_ISA(isa) \
129*795d594fSAndroid Build Coastguard Worker TEST_F(OptimizingCFITest, isa) { \
130*795d594fSAndroid Build Coastguard Worker std::vector<uint8_t> expected_asm( \
131*795d594fSAndroid Build Coastguard Worker expected_asm_##isa, \
132*795d594fSAndroid Build Coastguard Worker expected_asm_##isa + arraysize(expected_asm_##isa)); \
133*795d594fSAndroid Build Coastguard Worker std::vector<uint8_t> expected_cfi( \
134*795d594fSAndroid Build Coastguard Worker expected_cfi_##isa, \
135*795d594fSAndroid Build Coastguard Worker expected_cfi_##isa + arraysize(expected_cfi_##isa)); \
136*795d594fSAndroid Build Coastguard Worker TestImpl(InstructionSet::isa, #isa, expected_asm, expected_cfi); \
137*795d594fSAndroid Build Coastguard Worker }
138*795d594fSAndroid Build Coastguard Worker
139*795d594fSAndroid Build Coastguard Worker #ifdef ART_ENABLE_CODEGEN_arm
140*795d594fSAndroid Build Coastguard Worker TEST_ISA(kThumb2)
141*795d594fSAndroid Build Coastguard Worker #endif
142*795d594fSAndroid Build Coastguard Worker
143*795d594fSAndroid Build Coastguard Worker #ifdef ART_ENABLE_CODEGEN_arm64
144*795d594fSAndroid Build Coastguard Worker // Run the tests for ARM64 only if the Marking Register is reserved as the
145*795d594fSAndroid Build Coastguard Worker // expected generated code saves and restore X21 and X22 (instead of
146*795d594fSAndroid Build Coastguard Worker // X20 and X21), as X20 is used as Marking Register in the Baker read
147*795d594fSAndroid Build Coastguard Worker // barrier configuration, and as such is removed from the set of
148*795d594fSAndroid Build Coastguard Worker // callee-save registers in the ARM64 code generator of the Optimizing
149*795d594fSAndroid Build Coastguard Worker // compiler.
150*795d594fSAndroid Build Coastguard Worker #if defined(RESERVE_MARKING_REGISTER)
TEST_ISA(kArm64)151*795d594fSAndroid Build Coastguard Worker TEST_ISA(kArm64)
152*795d594fSAndroid Build Coastguard Worker #endif
153*795d594fSAndroid Build Coastguard Worker #endif
154*795d594fSAndroid Build Coastguard Worker
155*795d594fSAndroid Build Coastguard Worker #ifdef ART_ENABLE_CODEGEN_x86
156*795d594fSAndroid Build Coastguard Worker TEST_ISA(kX86)
157*795d594fSAndroid Build Coastguard Worker #endif
158*795d594fSAndroid Build Coastguard Worker
159*795d594fSAndroid Build Coastguard Worker #ifdef ART_ENABLE_CODEGEN_x86_64
160*795d594fSAndroid Build Coastguard Worker TEST_ISA(kX86_64)
161*795d594fSAndroid Build Coastguard Worker #endif
162*795d594fSAndroid Build Coastguard Worker
163*795d594fSAndroid Build Coastguard Worker #ifdef ART_ENABLE_CODEGEN_arm
164*795d594fSAndroid Build Coastguard Worker TEST_F(OptimizingCFITest, kThumb2Adjust) {
165*795d594fSAndroid Build Coastguard Worker using vixl32::r0;
166*795d594fSAndroid Build Coastguard Worker std::vector<uint8_t> expected_asm(
167*795d594fSAndroid Build Coastguard Worker expected_asm_kThumb2_adjust,
168*795d594fSAndroid Build Coastguard Worker expected_asm_kThumb2_adjust + arraysize(expected_asm_kThumb2_adjust));
169*795d594fSAndroid Build Coastguard Worker std::vector<uint8_t> expected_cfi(
170*795d594fSAndroid Build Coastguard Worker expected_cfi_kThumb2_adjust,
171*795d594fSAndroid Build Coastguard Worker expected_cfi_kThumb2_adjust + arraysize(expected_cfi_kThumb2_adjust));
172*795d594fSAndroid Build Coastguard Worker SetUpFrame(InstructionSet::kThumb2);
173*795d594fSAndroid Build Coastguard Worker #define __ down_cast<arm::ArmVIXLAssembler*>(GetCodeGenerator() \
174*795d594fSAndroid Build Coastguard Worker ->GetAssembler())->GetVIXLAssembler()->
175*795d594fSAndroid Build Coastguard Worker vixl32::Label target;
176*795d594fSAndroid Build Coastguard Worker __ CompareAndBranchIfZero(r0, &target);
177*795d594fSAndroid Build Coastguard Worker // Push the target out of range of CBZ.
178*795d594fSAndroid Build Coastguard Worker for (size_t i = 0; i != 65; ++i) {
179*795d594fSAndroid Build Coastguard Worker __ Ldr(r0, vixl32::MemOperand(r0));
180*795d594fSAndroid Build Coastguard Worker }
181*795d594fSAndroid Build Coastguard Worker __ Bind(&target);
182*795d594fSAndroid Build Coastguard Worker #undef __
183*795d594fSAndroid Build Coastguard Worker Finish();
184*795d594fSAndroid Build Coastguard Worker Check(InstructionSet::kThumb2, "kThumb2_adjust", expected_asm, expected_cfi);
185*795d594fSAndroid Build Coastguard Worker }
186*795d594fSAndroid Build Coastguard Worker #endif
187*795d594fSAndroid Build Coastguard Worker
188*795d594fSAndroid Build Coastguard Worker } // namespace art
189