1/*
2 * Copyright (C) 2015 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#ifndef ART_COMPILER_OPTIMIZING_INTRINSICS_H_
18#define ART_COMPILER_OPTIMIZING_INTRINSICS_H_
19
20#include "code_generator.h"
21#include "nodes.h"
22#include "optimization.h"
23#include "parallel_move_resolver.h"
24
25namespace art {
26
27class CompilerDriver;
28class DexFile;
29
30// Recognize intrinsics from HInvoke nodes.
31class IntrinsicsRecognizer : public HOptimization {
32 public:
33  IntrinsicsRecognizer(HGraph* graph, const DexFile* dex_file, CompilerDriver* driver)
34      : HOptimization(graph, true, kIntrinsicsRecognizerPassName),
35        dex_file_(dex_file), driver_(driver) {}
36
37  void Run() OVERRIDE;
38
39  static constexpr const char* kIntrinsicsRecognizerPassName = "intrinsics_recognition";
40
41 private:
42  const DexFile* dex_file_;
43  CompilerDriver* driver_;
44
45  DISALLOW_COPY_AND_ASSIGN(IntrinsicsRecognizer);
46};
47
48class IntrinsicVisitor : public ValueObject {
49 public:
50  virtual ~IntrinsicVisitor() {}
51
52  // Dispatch logic.
53
54  void Dispatch(HInvoke* invoke) {
55    switch (invoke->GetIntrinsic()) {
56      case Intrinsics::kNone:
57        return;
58#define OPTIMIZING_INTRINSICS(Name, IsStatic) \
59      case Intrinsics::k ## Name:             \
60        Visit ## Name(invoke);                \
61        return;
62#include "intrinsics_list.h"
63INTRINSICS_LIST(OPTIMIZING_INTRINSICS)
64#undef INTRINSICS_LIST
65#undef OPTIMIZING_INTRINSICS
66
67      // Do not put a default case. That way the compiler will complain if we missed a case.
68    }
69  }
70
71  // Define visitor methods.
72
73#define OPTIMIZING_INTRINSICS(Name, IsStatic)                    \
74  virtual void Visit ## Name(HInvoke* invoke ATTRIBUTE_UNUSED) { \
75  }
76#include "intrinsics_list.h"
77INTRINSICS_LIST(OPTIMIZING_INTRINSICS)
78#undef INTRINSICS_LIST
79#undef OPTIMIZING_INTRINSICS
80
81  static void MoveArguments(HInvoke* invoke,
82                            CodeGenerator* codegen,
83                            InvokeDexCallingConventionVisitor* calling_convention_visitor) {
84    if (kIsDebugBuild && invoke->IsInvokeStaticOrDirect()) {
85      HInvokeStaticOrDirect* invoke_static_or_direct = invoke->AsInvokeStaticOrDirect();
86      // When we do not run baseline, explicit clinit checks triggered by static
87      // invokes must have been pruned by art::PrepareForRegisterAllocation.
88      DCHECK(codegen->IsBaseline() || !invoke_static_or_direct->IsStaticWithExplicitClinitCheck());
89    }
90
91    if (invoke->GetNumberOfArguments() == 0) {
92      // No argument to move.
93      return;
94    }
95
96    LocationSummary* locations = invoke->GetLocations();
97
98    // We're moving potentially two or more locations to locations that could overlap, so we need
99    // a parallel move resolver.
100    HParallelMove parallel_move(codegen->GetGraph()->GetArena());
101
102    for (size_t i = 0; i < invoke->GetNumberOfArguments(); i++) {
103      HInstruction* input = invoke->InputAt(i);
104      Location cc_loc = calling_convention_visitor->GetNextLocation(input->GetType());
105      Location actual_loc = locations->InAt(i);
106
107      parallel_move.AddMove(actual_loc, cc_loc, input->GetType(), nullptr);
108    }
109
110    codegen->GetMoveResolver()->EmitNativeCode(&parallel_move);
111  }
112
113 protected:
114  IntrinsicVisitor() {}
115
116 private:
117  DISALLOW_COPY_AND_ASSIGN(IntrinsicVisitor);
118};
119
120}  // namespace art
121
122#endif  // ART_COMPILER_OPTIMIZING_INTRINSICS_H_
123