blob: 39c4a586e2fe1b4baebc8d88e33bc408cca96c0f [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
Ian Rogers4c1c2832013-03-04 18:30:13 -080026namespace art {
27namespace llvm {
Shih-wei Liaoe94d9b22012-05-22 09:01:24 -070028
Ian Rogers4c1c2832013-03-04 18:30:13 -080029const IntrinsicHelper::IntrinsicInfo IntrinsicHelper::Info[] = {
30#define DEF_INTRINSICS_FUNC(_, NAME, ATTR, RET_TYPE, ARG1_TYPE, ARG2_TYPE, \
31 ARG3_TYPE, ARG4_TYPE, \
32 ARG5_TYPE) \
33 { #NAME, ATTR, RET_TYPE, { ARG1_TYPE, ARG2_TYPE, \
34 ARG3_TYPE, ARG4_TYPE, \
35 ARG5_TYPE} },
36#include "intrinsic_func_list.def"
37};
Shih-wei Liaoe94d9b22012-05-22 09:01:24 -070038
Ian Rogers4c1c2832013-03-04 18:30:13 -080039static ::llvm::Type* GetLLVMTypeOfIntrinsicValType(IRBuilder& irb,
40 IntrinsicHelper::IntrinsicValType type) {
Shih-wei Liaoe94d9b22012-05-22 09:01:24 -070041 switch (type) {
42 case IntrinsicHelper::kVoidTy: {
43 return irb.getVoidTy();
44 }
45 case IntrinsicHelper::kJavaObjectTy: {
Ian Rogers76ae4fe2013-02-27 16:03:41 -080046 return irb.getJObjectTy();
Shih-wei Liaoe94d9b22012-05-22 09:01:24 -070047 }
48 case IntrinsicHelper::kJavaMethodTy: {
Ian Rogers76ae4fe2013-02-27 16:03:41 -080049 return irb.getJMethodTy();
Shih-wei Liaoe94d9b22012-05-22 09:01:24 -070050 }
51 case IntrinsicHelper::kJavaThreadTy: {
Ian Rogers76ae4fe2013-02-27 16:03:41 -080052 return irb.getJThreadTy();
Shih-wei Liaoe94d9b22012-05-22 09:01:24 -070053 }
54 case IntrinsicHelper::kInt1Ty:
55 case IntrinsicHelper::kInt1ConstantTy: {
56 return irb.getInt1Ty();
57 }
58 case IntrinsicHelper::kInt8Ty:
59 case IntrinsicHelper::kInt8ConstantTy: {
60 return irb.getInt8Ty();
61 }
62 case IntrinsicHelper::kInt16Ty:
63 case IntrinsicHelper::kInt16ConstantTy: {
64 return irb.getInt16Ty();
65 }
66 case IntrinsicHelper::kInt32Ty:
67 case IntrinsicHelper::kInt32ConstantTy: {
68 return irb.getInt32Ty();
69 }
70 case IntrinsicHelper::kInt64Ty:
71 case IntrinsicHelper::kInt64ConstantTy: {
72 return irb.getInt64Ty();
73 }
Shih-wei Liao21d28f52012-06-12 05:55:00 -070074 case IntrinsicHelper::kFloatTy:
75 case IntrinsicHelper::kFloatConstantTy: {
buzbee2cfc6392012-05-07 14:51:40 -070076 return irb.getFloatTy();
77 }
Shih-wei Liao21d28f52012-06-12 05:55:00 -070078 case IntrinsicHelper::kDoubleTy:
79 case IntrinsicHelper::kDoubleConstantTy: {
buzbee2cfc6392012-05-07 14:51:40 -070080 return irb.getDoubleTy();
81 }
Shih-wei Liaoe94d9b22012-05-22 09:01:24 -070082 case IntrinsicHelper::kNone:
83 case IntrinsicHelper::kVarArgTy:
84 default: {
85 LOG(FATAL) << "Invalid intrinsic type " << type << "to get LLVM type!";
86 return NULL;
87 }
88 }
89 // unreachable
90}
91
Ian Rogers4c1c2832013-03-04 18:30:13 -080092IntrinsicHelper::IntrinsicHelper(::llvm::LLVMContext& context,
93 ::llvm::Module& module) {
Shih-wei Liaoe94d9b22012-05-22 09:01:24 -070094 IRBuilder irb(context, module, *this);
95
96 ::memset(intrinsic_funcs_, 0, sizeof(intrinsic_funcs_));
97
98 // This loop does the following things:
99 // 1. Introduce the intrinsic function into the module
100 // 2. Add "nocapture" and "noalias" attribute to the arguments in all
101 // intrinsics functions.
102 // 3. Initialize intrinsic_funcs_map_.
103 for (unsigned i = 0; i < MaxIntrinsicId; i++) {
104 IntrinsicId id = static_cast<IntrinsicId>(i);
105 const IntrinsicInfo& info = Info[i];
106
107 // Parse and construct the argument type from IntrinsicInfo
Ian Rogers4c1c2832013-03-04 18:30:13 -0800108 ::llvm::Type* arg_type[kIntrinsicMaxArgc];
Shih-wei Liaoe94d9b22012-05-22 09:01:24 -0700109 unsigned num_args = 0;
110 bool is_var_arg = false;
111 for (unsigned arg_iter = 0; arg_iter < kIntrinsicMaxArgc; arg_iter++) {
112 IntrinsicValType type = info.arg_type_[arg_iter];
113
114 if (type == kNone) {
115 break;
116 } else if (type == kVarArgTy) {
117 // Variable argument type must be the last argument
118 is_var_arg = true;
119 break;
120 }
121
122 arg_type[num_args++] = GetLLVMTypeOfIntrinsicValType(irb, type);
123 }
124
125 // Construct the function type
Ian Rogers4c1c2832013-03-04 18:30:13 -0800126 ::llvm::Type* ret_type =
Shih-wei Liaoe94d9b22012-05-22 09:01:24 -0700127 GetLLVMTypeOfIntrinsicValType(irb, info.ret_val_type_);
128
Ian Rogers4c1c2832013-03-04 18:30:13 -0800129 ::llvm::FunctionType* type =
130 ::llvm::FunctionType::get(ret_type,
131 ::llvm::ArrayRef< ::llvm::Type*>(arg_type, num_args),
132 is_var_arg);
Shih-wei Liaoe94d9b22012-05-22 09:01:24 -0700133
134 // Declare the function
Ian Rogers4c1c2832013-03-04 18:30:13 -0800135 ::llvm::Function *fn = ::llvm::Function::Create(type,
136 ::llvm::Function::ExternalLinkage,
137 info.name_, &module);
Shih-wei Liaoe94d9b22012-05-22 09:01:24 -0700138
139 fn->setOnlyReadsMemory(info.attr_ & kAttrReadOnly);
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700140 fn->setDoesNotAccessMemory(info.attr_ & kAttrReadNone);
Shih-wei Liaoe94d9b22012-05-22 09:01:24 -0700141 // None of the intrinsics throws exception
142 fn->setDoesNotThrow(true);
143
144 intrinsic_funcs_[id] = fn;
145
Ian Rogers4c1c2832013-03-04 18:30:13 -0800146 DCHECK_NE(fn, static_cast< ::llvm::Function*>(NULL)) << "Intrinsic `"
Shih-wei Liaoe94d9b22012-05-22 09:01:24 -0700147 << GetName(id) << "' was not defined!";
148
149 // Add "noalias" and "nocapture" attribute to all arguments of pointer type
Ian Rogers4c1c2832013-03-04 18:30:13 -0800150 for (::llvm::Function::arg_iterator arg_iter = fn->arg_begin(),
Shih-wei Liaoe94d9b22012-05-22 09:01:24 -0700151 arg_end = fn->arg_end(); arg_iter != arg_end; arg_iter++) {
152 if (arg_iter->getType()->isPointerTy()) {
Ian Rogers4c1c2832013-03-04 18:30:13 -0800153 arg_iter->addAttr(::llvm::Attribute::NoCapture);
154 arg_iter->addAttr(::llvm::Attribute::NoAlias);
Shih-wei Liaoe94d9b22012-05-22 09:01:24 -0700155 }
156 }
157
158 // Insert the newly created intrinsic to intrinsic_funcs_map_
159 if (!intrinsic_funcs_map_.insert(std::make_pair(fn, id)).second) {
160 LOG(FATAL) << "Duplicate entry in intrinsic functions map?";
161 }
162 }
163
164 return;
165}
166
Ian Rogers4c1c2832013-03-04 18:30:13 -0800167} // namespace llvm
Shih-wei Liaoe94d9b22012-05-22 09:01:24 -0700168} // namespace art