1 /* 2 * Copyright (C) 2023 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 "critical_native_abi_fixup_riscv64.h" 18 19 #include "arch/riscv64/jni_frame_riscv64.h" 20 #include "intrinsics.h" 21 #include "nodes.h" 22 23 namespace art HIDDEN { 24 namespace riscv64 { 25 26 // Fix up FP arguments passed in core registers for call to @CriticalNative by inserting fake calls 27 // to Float.floatToRawIntBits() or Double.doubleToRawLongBits() to satisfy type consistency checks. FixUpArguments(HInvokeStaticOrDirect * invoke)28static void FixUpArguments(HInvokeStaticOrDirect* invoke) { 29 DCHECK_EQ(invoke->GetCodePtrLocation(), CodePtrLocation::kCallCriticalNative); 30 size_t core_reg = 0u; 31 size_t fp_reg = 0u; 32 for (size_t i = 0, num_args = invoke->GetNumberOfArguments(); i != num_args; ++i) { 33 if (core_reg == kMaxIntLikeArgumentRegisters) { 34 break; // Remaining arguments are passed in FP regs or on the stack. 35 } 36 HInstruction* input = invoke->InputAt(i); 37 DataType::Type input_type = input->GetType(); 38 if (DataType::IsFloatingPointType(input_type)) { 39 if (fp_reg < kMaxFloatOrDoubleArgumentRegisters) { 40 ++fp_reg; 41 } else { 42 DCHECK_LT(core_reg, kMaxIntLikeArgumentRegisters); 43 InsertFpToIntegralIntrinsic(invoke, i); 44 ++core_reg; 45 } 46 } else { 47 ++core_reg; 48 } 49 } 50 } 51 Run()52bool CriticalNativeAbiFixupRiscv64::Run() { 53 if (!graph_->HasDirectCriticalNativeCall()) { 54 return false; 55 } 56 57 for (HBasicBlock* block : graph_->GetReversePostOrder()) { 58 for (HInstructionIterator it(block->GetInstructions()); !it.Done(); it.Advance()) { 59 HInstruction* instruction = it.Current(); 60 if (instruction->IsInvokeStaticOrDirect() && 61 instruction->AsInvokeStaticOrDirect()->GetCodePtrLocation() == 62 CodePtrLocation::kCallCriticalNative) { 63 FixUpArguments(instruction->AsInvokeStaticOrDirect()); 64 } 65 } 66 } 67 return true; 68 } 69 70 } // namespace riscv64 71 } // namespace art 72