xref: /aosp_15_r20/art/compiler/jni/jni_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/arena_allocator.h"
22*795d594fSAndroid Build Coastguard Worker #include "base/macros.h"
23*795d594fSAndroid Build Coastguard Worker #include "base/malloc_arena_pool.h"
24*795d594fSAndroid Build Coastguard Worker #include "base/pointer_size.h"
25*795d594fSAndroid Build Coastguard Worker #include "cfi_test.h"
26*795d594fSAndroid Build Coastguard Worker #include "gtest/gtest.h"
27*795d594fSAndroid Build Coastguard Worker #include "jni/quick/calling_convention.h"
28*795d594fSAndroid Build Coastguard Worker #include "read_barrier_config.h"
29*795d594fSAndroid Build Coastguard Worker #include "utils/assembler.h"
30*795d594fSAndroid Build Coastguard Worker #include "utils/jni_macro_assembler.h"
31*795d594fSAndroid Build Coastguard Worker 
32*795d594fSAndroid Build Coastguard Worker #include "jni/jni_cfi_test_expected.inc"
33*795d594fSAndroid Build Coastguard Worker 
34*795d594fSAndroid Build Coastguard Worker namespace art HIDDEN {
35*795d594fSAndroid Build Coastguard Worker 
36*795d594fSAndroid Build Coastguard Worker class JNICFITest : public CFITest {
37*795d594fSAndroid Build Coastguard Worker  public:
38*795d594fSAndroid Build Coastguard Worker   // Enable this flag to generate the expected outputs.
39*795d594fSAndroid Build Coastguard Worker   static constexpr bool kGenerateExpected = false;
40*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)41*795d594fSAndroid Build Coastguard Worker   void TestImpl(InstructionSet isa,
42*795d594fSAndroid Build Coastguard Worker                 const char* isa_str,
43*795d594fSAndroid Build Coastguard Worker                 const std::vector<uint8_t>& expected_asm,
44*795d594fSAndroid Build Coastguard Worker                 const std::vector<uint8_t>& expected_cfi) {
45*795d594fSAndroid Build Coastguard Worker     if (Is64BitInstructionSet(isa)) {
46*795d594fSAndroid Build Coastguard Worker       TestImplSized<PointerSize::k64>(isa, isa_str, expected_asm, expected_cfi);
47*795d594fSAndroid Build Coastguard Worker     } else {
48*795d594fSAndroid Build Coastguard Worker       TestImplSized<PointerSize::k32>(isa, isa_str, expected_asm, expected_cfi);
49*795d594fSAndroid Build Coastguard Worker     }
50*795d594fSAndroid Build Coastguard Worker   }
51*795d594fSAndroid Build Coastguard Worker 
52*795d594fSAndroid Build Coastguard Worker  private:
53*795d594fSAndroid Build Coastguard Worker   template <PointerSize kPointerSize>
TestImplSized(InstructionSet isa,const char * isa_str,const std::vector<uint8_t> & expected_asm,const std::vector<uint8_t> & expected_cfi)54*795d594fSAndroid Build Coastguard Worker   void TestImplSized(InstructionSet isa,
55*795d594fSAndroid Build Coastguard Worker                      const char* isa_str,
56*795d594fSAndroid Build Coastguard Worker                      const std::vector<uint8_t>& expected_asm,
57*795d594fSAndroid Build Coastguard Worker                      const std::vector<uint8_t>& expected_cfi) {
58*795d594fSAndroid Build Coastguard Worker     // Description of simple method.
59*795d594fSAndroid Build Coastguard Worker     const bool is_static = true;
60*795d594fSAndroid Build Coastguard Worker     const bool is_synchronized = false;
61*795d594fSAndroid Build Coastguard Worker     const char* shorty = "IIFII";
62*795d594fSAndroid Build Coastguard Worker 
63*795d594fSAndroid Build Coastguard Worker     MallocArenaPool pool;
64*795d594fSAndroid Build Coastguard Worker     ArenaAllocator allocator(&pool);
65*795d594fSAndroid Build Coastguard Worker 
66*795d594fSAndroid Build Coastguard Worker     std::unique_ptr<JniCallingConvention> jni_conv(
67*795d594fSAndroid Build Coastguard Worker         JniCallingConvention::Create(&allocator,
68*795d594fSAndroid Build Coastguard Worker                                      is_static,
69*795d594fSAndroid Build Coastguard Worker                                      is_synchronized,
70*795d594fSAndroid Build Coastguard Worker                                      /*is_fast_native=*/ false,
71*795d594fSAndroid Build Coastguard Worker                                      /*is_critical_native=*/ false,
72*795d594fSAndroid Build Coastguard Worker                                      shorty,
73*795d594fSAndroid Build Coastguard Worker                                      isa));
74*795d594fSAndroid Build Coastguard Worker     std::unique_ptr<ManagedRuntimeCallingConvention> mr_conv(
75*795d594fSAndroid Build Coastguard Worker         ManagedRuntimeCallingConvention::Create(
76*795d594fSAndroid Build Coastguard Worker             &allocator, is_static, is_synchronized, shorty, isa));
77*795d594fSAndroid Build Coastguard Worker     const int frame_size(jni_conv->FrameSize());
78*795d594fSAndroid Build Coastguard Worker     ArrayRef<const ManagedRegister> callee_save_regs = jni_conv->CalleeSaveRegisters();
79*795d594fSAndroid Build Coastguard Worker 
80*795d594fSAndroid Build Coastguard Worker     // Assemble the method.
81*795d594fSAndroid Build Coastguard Worker     std::unique_ptr<JNIMacroAssembler<kPointerSize>> jni_asm(
82*795d594fSAndroid Build Coastguard Worker         JNIMacroAssembler<kPointerSize>::Create(&allocator, isa));
83*795d594fSAndroid Build Coastguard Worker     jni_asm->cfi().SetEnabled(true);
84*795d594fSAndroid Build Coastguard Worker     jni_asm->BuildFrame(frame_size, mr_conv->MethodRegister(), callee_save_regs);
85*795d594fSAndroid Build Coastguard Worker     // Spill arguments.
86*795d594fSAndroid Build Coastguard Worker     mr_conv->ResetIterator(FrameOffset(frame_size));
87*795d594fSAndroid Build Coastguard Worker     for (; mr_conv->HasNext(); mr_conv->Next()) {
88*795d594fSAndroid Build Coastguard Worker       if (mr_conv->IsCurrentParamInRegister()) {
89*795d594fSAndroid Build Coastguard Worker         size_t size = mr_conv->IsCurrentParamALongOrDouble() ? 8u : 4u;
90*795d594fSAndroid Build Coastguard Worker         jni_asm->Store(mr_conv->CurrentParamStackOffset(), mr_conv->CurrentParamRegister(), size);
91*795d594fSAndroid Build Coastguard Worker       }
92*795d594fSAndroid Build Coastguard Worker     }
93*795d594fSAndroid Build Coastguard Worker     jni_asm->IncreaseFrameSize(32);
94*795d594fSAndroid Build Coastguard Worker     jni_asm->DecreaseFrameSize(32);
95*795d594fSAndroid Build Coastguard Worker     jni_asm->RemoveFrame(frame_size, callee_save_regs, /* may_suspend= */ true);
96*795d594fSAndroid Build Coastguard Worker     jni_asm->FinalizeCode();
97*795d594fSAndroid Build Coastguard Worker     std::vector<uint8_t> actual_asm(jni_asm->CodeSize());
98*795d594fSAndroid Build Coastguard Worker     MemoryRegion code(&actual_asm[0], actual_asm.size());
99*795d594fSAndroid Build Coastguard Worker     jni_asm->CopyInstructions(code);
100*795d594fSAndroid Build Coastguard Worker     ASSERT_EQ(jni_asm->cfi().GetCurrentCFAOffset(), frame_size);
101*795d594fSAndroid Build Coastguard Worker     const std::vector<uint8_t>& actual_cfi = *(jni_asm->cfi().data());
102*795d594fSAndroid Build Coastguard Worker 
103*795d594fSAndroid Build Coastguard Worker     if (kGenerateExpected) {
104*795d594fSAndroid Build Coastguard Worker       GenerateExpected(stdout,
105*795d594fSAndroid Build Coastguard Worker                        isa,
106*795d594fSAndroid Build Coastguard Worker                        isa_str,
107*795d594fSAndroid Build Coastguard Worker                        ArrayRef<const uint8_t>(actual_asm),
108*795d594fSAndroid Build Coastguard Worker                        ArrayRef<const uint8_t>(actual_cfi));
109*795d594fSAndroid Build Coastguard Worker     } else {
110*795d594fSAndroid Build Coastguard Worker       EXPECT_EQ(expected_asm, actual_asm);
111*795d594fSAndroid Build Coastguard Worker       EXPECT_EQ(expected_cfi, actual_cfi);
112*795d594fSAndroid Build Coastguard Worker     }
113*795d594fSAndroid Build Coastguard Worker   }
114*795d594fSAndroid Build Coastguard Worker };
115*795d594fSAndroid Build Coastguard Worker 
116*795d594fSAndroid Build Coastguard Worker #define TEST_ISA(isa)                                                 \
117*795d594fSAndroid Build Coastguard Worker   TEST_F(JNICFITest, isa) {                                           \
118*795d594fSAndroid Build Coastguard Worker     std::vector<uint8_t> expected_asm(expected_asm_##isa,             \
119*795d594fSAndroid Build Coastguard Worker         expected_asm_##isa + arraysize(expected_asm_##isa));          \
120*795d594fSAndroid Build Coastguard Worker     std::vector<uint8_t> expected_cfi(expected_cfi_##isa,             \
121*795d594fSAndroid Build Coastguard Worker         expected_cfi_##isa + arraysize(expected_cfi_##isa));          \
122*795d594fSAndroid Build Coastguard Worker     TestImpl(InstructionSet::isa, #isa, expected_asm, expected_cfi);  \
123*795d594fSAndroid Build Coastguard Worker   }
124*795d594fSAndroid Build Coastguard Worker 
125*795d594fSAndroid Build Coastguard Worker #ifdef ART_ENABLE_CODEGEN_arm
126*795d594fSAndroid Build Coastguard Worker // Run the tests for ARM only if the Marking Register is reserved as the
127*795d594fSAndroid Build Coastguard Worker // expected generated code contains a Marking Register refresh instruction.
128*795d594fSAndroid Build Coastguard Worker #if defined(RESERVE_MARKING_REGISTER)
129*795d594fSAndroid Build Coastguard Worker TEST_ISA(kThumb2)
130*795d594fSAndroid Build Coastguard Worker #endif
131*795d594fSAndroid Build Coastguard Worker #endif
132*795d594fSAndroid Build Coastguard Worker 
133*795d594fSAndroid Build Coastguard Worker #ifdef ART_ENABLE_CODEGEN_arm64
134*795d594fSAndroid Build Coastguard Worker // Run the tests for ARM64 only if the Marking Register is reserved as the
135*795d594fSAndroid Build Coastguard Worker // expected generated code contains a Marking Register refresh instruction.
136*795d594fSAndroid Build Coastguard Worker #if defined(RESERVE_MARKING_REGISTER)
137*795d594fSAndroid Build Coastguard Worker TEST_ISA(kArm64)
138*795d594fSAndroid Build Coastguard Worker #endif
139*795d594fSAndroid Build Coastguard Worker #endif
140*795d594fSAndroid Build Coastguard Worker 
141*795d594fSAndroid Build Coastguard Worker #ifdef ART_ENABLE_CODEGEN_x86
142*795d594fSAndroid Build Coastguard Worker TEST_ISA(kX86)
143*795d594fSAndroid Build Coastguard Worker #endif
144*795d594fSAndroid Build Coastguard Worker 
145*795d594fSAndroid Build Coastguard Worker #ifdef ART_ENABLE_CODEGEN_x86_64
146*795d594fSAndroid Build Coastguard Worker TEST_ISA(kX86_64)
147*795d594fSAndroid Build Coastguard Worker #endif
148*795d594fSAndroid Build Coastguard Worker 
149*795d594fSAndroid Build Coastguard Worker }  // namespace art
150