xref: /aosp_15_r20/art/compiler/optimizing/critical_native_abi_fixup_riscv64.cc (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
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)28 static 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()52 bool 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