xref: /aosp_15_r20/art/compiler/optimizing/optimizing_cfi_test.cc (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
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