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