1/*
2 * Copyright (C) 2012 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_LLVM_INTRINSIC_HELPER_H_
18#define ART_COMPILER_LLVM_INTRINSIC_HELPER_H_
19
20#include "base/logging.h"
21
22#include <llvm/ADT/DenseMap.h>
23
24namespace llvm {
25  class Function;
26  class FunctionType;
27  class LLVMContext;
28  class Module;
29}  // namespace llvm
30
31namespace art {
32namespace llvm {
33
34class IRBuilder;
35
36class IntrinsicHelper {
37 public:
38  enum IntrinsicId {
39#define DEF_INTRINSICS_FUNC(ID, ...) ID,
40#include "intrinsic_func_list.def"
41    MaxIntrinsicId,
42
43    // Pseudo-intrinsics Id
44    UnknownId
45  };
46
47  enum IntrinsicAttribute {
48    kAttrNone     = 0,
49
50    // Intrinsic that neither modified the memory state nor refer to the global
51    // state
52    kAttrReadNone = 1 << 0,
53
54    // Intrinsic that doesn't modify the memory state. Note that one should set
55    // this flag carefully when the intrinsic may throw exception. Since the
56    // thread state is implicitly modified when an exception is thrown.
57    kAttrReadOnly = 1 << 1,
58
59    // Note that intrinsic without kAttrNoThrow and kAttrDoThrow set means that
60    // intrinsic generates exception in some cases
61
62    // Intrinsic that never generates exception
63    kAttrNoThrow  = 1 << 2,
64    // Intrinsic that always generate exception
65    kAttrDoThrow  = 1 << 3,
66  };
67
68  enum IntrinsicValType {
69    kNone,
70
71    kVoidTy,
72
73    kJavaObjectTy,
74    kJavaMethodTy,
75    kJavaThreadTy,
76
77    kInt1Ty,
78    kInt8Ty,
79    kInt16Ty,
80    kInt32Ty,
81    kInt64Ty,
82    kFloatTy,
83    kDoubleTy,
84
85    kInt1ConstantTy,
86    kInt8ConstantTy,
87    kInt16ConstantTy,
88    kInt32ConstantTy,
89    kInt64ConstantTy,
90    kFloatConstantTy,
91    kDoubleConstantTy,
92
93    kVarArgTy,
94  };
95
96  enum {
97    kIntrinsicMaxArgc = 5
98  };
99
100  typedef struct IntrinsicInfo {
101    const char* name_;
102    unsigned attr_;
103    IntrinsicValType ret_val_type_;
104    IntrinsicValType arg_type_[kIntrinsicMaxArgc];
105  } IntrinsicInfo;
106
107 private:
108  static const IntrinsicInfo Info[];
109
110 public:
111  static const IntrinsicInfo& GetInfo(IntrinsicId id) {
112    DCHECK(id >= 0 && id < MaxIntrinsicId) << "Unknown ART intrinsics ID: "
113                                           << id;
114    return Info[id];
115  }
116
117  static const char* GetName(IntrinsicId id) {
118    return (id <= MaxIntrinsicId) ? GetInfo(id).name_ : "InvalidIntrinsic";
119  }
120
121  static unsigned GetAttr(IntrinsicId id) {
122    return GetInfo(id).attr_;
123  }
124
125 public:
126  IntrinsicHelper(::llvm::LLVMContext& context, ::llvm::Module& module);
127
128  ::llvm::Function* GetIntrinsicFunction(IntrinsicId id) {
129    DCHECK(id >= 0 && id < MaxIntrinsicId) << "Unknown ART intrinsics ID: "
130                                           << id;
131    return intrinsic_funcs_[id];
132  }
133
134  IntrinsicId GetIntrinsicId(const ::llvm::Function* func) const {
135    ::llvm::DenseMap<const ::llvm::Function*, IntrinsicId>::const_iterator
136        i = intrinsic_funcs_map_.find(func);
137    if (i == intrinsic_funcs_map_.end()) {
138      return UnknownId;
139    } else {
140      return i->second;
141    }
142  }
143
144 private:
145  // FIXME: "+1" is to workaround the GCC bugs:
146  // http://gcc.gnu.org/bugzilla/show_bug.cgi?id=43949
147  // Remove this when uses newer GCC (> 4.4.3)
148  ::llvm::Function* intrinsic_funcs_[MaxIntrinsicId + 1];
149
150  // Map a llvm::Function to its intrinsic id
151  ::llvm::DenseMap<const ::llvm::Function*, IntrinsicId> intrinsic_funcs_map_;
152};
153
154}  // namespace llvm
155}  // namespace art
156
157#endif  // ART_COMPILER_LLVM_INTRINSIC_HELPER_H_
158