blob: 3bb6948ab408cdb8da652d6729671914b3d6486a [file] [log] [blame]
Shih-wei Liaoe94d9b22012-05-22 09:01:24 -07001/*
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#include "intrinsic_helper.h"
18
19#include "ir_builder.h"
20
21#include <llvm/DerivedTypes.h>
22#include <llvm/Function.h>
23#include <llvm/Intrinsics.h>
Shih-wei Liaoe94d9b22012-05-22 09:01:24 -070024#include <llvm/Support/IRBuilder.h>
25
26using namespace art;
Ian Rogers76ae4fe2013-02-27 16:03:41 -080027using namespace compiler_llvm;
Shih-wei Liaoe94d9b22012-05-22 09:01:24 -070028
29namespace {
30
31inline llvm::Type*
32GetLLVMTypeOfIntrinsicValType(IRBuilder& irb,
33 IntrinsicHelper::IntrinsicValType type) {
34 switch (type) {
35 case IntrinsicHelper::kVoidTy: {
36 return irb.getVoidTy();
37 }
38 case IntrinsicHelper::kJavaObjectTy: {
Ian Rogers76ae4fe2013-02-27 16:03:41 -080039 return irb.getJObjectTy();
Shih-wei Liaoe94d9b22012-05-22 09:01:24 -070040 }
41 case IntrinsicHelper::kJavaMethodTy: {
Ian Rogers76ae4fe2013-02-27 16:03:41 -080042 return irb.getJMethodTy();
Shih-wei Liaoe94d9b22012-05-22 09:01:24 -070043 }
44 case IntrinsicHelper::kJavaThreadTy: {
Ian Rogers76ae4fe2013-02-27 16:03:41 -080045 return irb.getJThreadTy();
Shih-wei Liaoe94d9b22012-05-22 09:01:24 -070046 }
47 case IntrinsicHelper::kInt1Ty:
48 case IntrinsicHelper::kInt1ConstantTy: {
49 return irb.getInt1Ty();
50 }
51 case IntrinsicHelper::kInt8Ty:
52 case IntrinsicHelper::kInt8ConstantTy: {
53 return irb.getInt8Ty();
54 }
55 case IntrinsicHelper::kInt16Ty:
56 case IntrinsicHelper::kInt16ConstantTy: {
57 return irb.getInt16Ty();
58 }
59 case IntrinsicHelper::kInt32Ty:
60 case IntrinsicHelper::kInt32ConstantTy: {
61 return irb.getInt32Ty();
62 }
63 case IntrinsicHelper::kInt64Ty:
64 case IntrinsicHelper::kInt64ConstantTy: {
65 return irb.getInt64Ty();
66 }
Shih-wei Liao21d28f52012-06-12 05:55:00 -070067 case IntrinsicHelper::kFloatTy:
68 case IntrinsicHelper::kFloatConstantTy: {
buzbee2cfc6392012-05-07 14:51:40 -070069 return irb.getFloatTy();
70 }
Shih-wei Liao21d28f52012-06-12 05:55:00 -070071 case IntrinsicHelper::kDoubleTy:
72 case IntrinsicHelper::kDoubleConstantTy: {
buzbee2cfc6392012-05-07 14:51:40 -070073 return irb.getDoubleTy();
74 }
Shih-wei Liaoe94d9b22012-05-22 09:01:24 -070075 case IntrinsicHelper::kNone:
76 case IntrinsicHelper::kVarArgTy:
77 default: {
78 LOG(FATAL) << "Invalid intrinsic type " << type << "to get LLVM type!";
79 return NULL;
80 }
81 }
82 // unreachable
83}
84
85} // anonymous namespace
86
87namespace art {
Ian Rogers76ae4fe2013-02-27 16:03:41 -080088namespace compiler_llvm {
Shih-wei Liaoe94d9b22012-05-22 09:01:24 -070089
Shih-wei Liao21d28f52012-06-12 05:55:00 -070090const IntrinsicHelper::IntrinsicInfo IntrinsicHelper::Info[] = {
Shih-wei Liaoe94d9b22012-05-22 09:01:24 -070091#define DEF_INTRINSICS_FUNC(_, NAME, ATTR, RET_TYPE, ARG1_TYPE, ARG2_TYPE, \
92 ARG3_TYPE, ARG4_TYPE, \
93 ARG5_TYPE) \
94 { #NAME, ATTR, RET_TYPE, { ARG1_TYPE, ARG2_TYPE, \
95 ARG3_TYPE, ARG4_TYPE, \
96 ARG5_TYPE} },
97#include "intrinsic_func_list.def"
98};
99
100IntrinsicHelper::IntrinsicHelper(llvm::LLVMContext& context,
101 llvm::Module& module) {
102 IRBuilder irb(context, module, *this);
103
104 ::memset(intrinsic_funcs_, 0, sizeof(intrinsic_funcs_));
105
106 // This loop does the following things:
107 // 1. Introduce the intrinsic function into the module
108 // 2. Add "nocapture" and "noalias" attribute to the arguments in all
109 // intrinsics functions.
110 // 3. Initialize intrinsic_funcs_map_.
111 for (unsigned i = 0; i < MaxIntrinsicId; i++) {
112 IntrinsicId id = static_cast<IntrinsicId>(i);
113 const IntrinsicInfo& info = Info[i];
114
115 // Parse and construct the argument type from IntrinsicInfo
116 llvm::Type* arg_type[kIntrinsicMaxArgc];
117 unsigned num_args = 0;
118 bool is_var_arg = false;
119 for (unsigned arg_iter = 0; arg_iter < kIntrinsicMaxArgc; arg_iter++) {
120 IntrinsicValType type = info.arg_type_[arg_iter];
121
122 if (type == kNone) {
123 break;
124 } else if (type == kVarArgTy) {
125 // Variable argument type must be the last argument
126 is_var_arg = true;
127 break;
128 }
129
130 arg_type[num_args++] = GetLLVMTypeOfIntrinsicValType(irb, type);
131 }
132
133 // Construct the function type
134 llvm::Type* ret_type =
135 GetLLVMTypeOfIntrinsicValType(irb, info.ret_val_type_);
136
137 llvm::FunctionType* type =
138 llvm::FunctionType::get(ret_type,
139 llvm::ArrayRef<llvm::Type*>(arg_type, num_args),
140 is_var_arg);
141
142 // Declare the function
143 llvm::Function *fn = llvm::Function::Create(type,
144 llvm::Function::ExternalLinkage,
145 info.name_, &module);
146
147 fn->setOnlyReadsMemory(info.attr_ & kAttrReadOnly);
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700148 fn->setDoesNotAccessMemory(info.attr_ & kAttrReadNone);
Shih-wei Liaoe94d9b22012-05-22 09:01:24 -0700149 // None of the intrinsics throws exception
150 fn->setDoesNotThrow(true);
151
152 intrinsic_funcs_[id] = fn;
153
154 DCHECK_NE(fn, static_cast<llvm::Function*>(NULL)) << "Intrinsic `"
155 << GetName(id) << "' was not defined!";
156
157 // Add "noalias" and "nocapture" attribute to all arguments of pointer type
158 for (llvm::Function::arg_iterator arg_iter = fn->arg_begin(),
159 arg_end = fn->arg_end(); arg_iter != arg_end; arg_iter++) {
160 if (arg_iter->getType()->isPointerTy()) {
161 arg_iter->addAttr(llvm::Attribute::NoCapture);
162 arg_iter->addAttr(llvm::Attribute::NoAlias);
163 }
164 }
165
166 // Insert the newly created intrinsic to intrinsic_funcs_map_
167 if (!intrinsic_funcs_map_.insert(std::make_pair(fn, id)).second) {
168 LOG(FATAL) << "Duplicate entry in intrinsic functions map?";
169 }
170 }
171
172 return;
173}
174
Ian Rogers76ae4fe2013-02-27 16:03:41 -0800175} // namespace compiler_llvm
Shih-wei Liaoe94d9b22012-05-22 09:01:24 -0700176} // namespace art