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