blob: aa261c3bb6df6c70fd500a98e697edc93ed01a5c [file] [log] [blame]
Shih-wei Liaod1fec812012-02-13 09:51:10 -08001/*
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_SRC_COMPILER_LLVM_IR_BUILDER_H_
18#define ART_SRC_COMPILER_LLVM_IR_BUILDER_H_
19
20#include "backend_types.h"
TDYa127d668a062012-04-13 12:36:57 -070021#include "runtime_support_builder.h"
Logan Chien42e0e152012-01-13 15:42:36 +080022#include "runtime_support_func.h"
TDYa127aba61122012-05-04 18:28:36 -070023#include "tbaa_info.h"
Shih-wei Liaod1fec812012-02-13 09:51:10 -080024
25#include <llvm/Constants.h>
26#include <llvm/DerivedTypes.h>
TDYa127aba61122012-05-04 18:28:36 -070027#include <llvm/LLVMContext.h>
Shih-wei Liaod1fec812012-02-13 09:51:10 -080028#include <llvm/Support/IRBuilder.h>
29#include <llvm/Type.h>
30
31#include <stdint.h>
32
33
34namespace art {
35namespace compiler_llvm {
36
37
38typedef llvm::IRBuilder<> LLVMIRBuilder;
39// NOTE: Here we define our own LLVMIRBuilder type alias, so that we can
40// switch "preserveNames" template parameter easily.
41
42
43class IRBuilder : public LLVMIRBuilder {
44 public:
45 //--------------------------------------------------------------------------
46 // General
47 //--------------------------------------------------------------------------
48
49 IRBuilder(llvm::LLVMContext& context, llvm::Module& module);
50
51
52 //--------------------------------------------------------------------------
TDYa127aba61122012-05-04 18:28:36 -070053 // Extend load & store for TBAA
54 //--------------------------------------------------------------------------
55
56 llvm::LoadInst* CreateLoad(llvm::Value* ptr, llvm::MDNode* tbaa_info) {
57 llvm::LoadInst* inst = LLVMIRBuilder::CreateLoad(ptr);
58 inst->setMetadata(llvm::LLVMContext::MD_tbaa, tbaa_info);
59 return inst;
60 }
61
62 llvm::StoreInst* CreateStore(llvm::Value* val, llvm::Value* ptr, llvm::MDNode* tbaa_info) {
63 llvm::StoreInst* inst = LLVMIRBuilder::CreateStore(val, ptr);
64 inst->setMetadata(llvm::LLVMContext::MD_tbaa, tbaa_info);
65 return inst;
66 }
67
68
69 //--------------------------------------------------------------------------
70 // TBAA
71 //--------------------------------------------------------------------------
72
73 // TODO: After we design the non-special TBAA info, re-design the TBAA interface.
74 llvm::LoadInst* CreateLoad(llvm::Value* ptr, TBAASpecialType special_ty) {
75 return CreateLoad(ptr, tbaa_.GetSpecialType(special_ty));
76 }
77
78 llvm::StoreInst* CreateStore(llvm::Value* val, llvm::Value* ptr, TBAASpecialType special_ty) {
79 DCHECK_NE(special_ty, kTBAAConstJObject) << "ConstJObject is read only!";
80 return CreateStore(val, ptr, tbaa_.GetSpecialType(special_ty));
81 }
82
TDYa127706e7db2012-05-06 00:05:33 -070083 llvm::LoadInst* CreateLoad(llvm::Value* ptr, TBAASpecialType special_ty, JType j_ty) {
84 return CreateLoad(ptr, tbaa_.GetMemoryJType(special_ty, j_ty));
85 }
86
87 llvm::StoreInst* CreateStore(llvm::Value* val, llvm::Value* ptr,
88 TBAASpecialType special_ty, JType j_ty) {
89 DCHECK_NE(special_ty, kTBAAConstJObject) << "ConstJObject is read only!";
90 return CreateStore(val, ptr, tbaa_.GetMemoryJType(special_ty, j_ty));
91 }
92
TDYa1278fe384d2012-05-06 20:14:17 -070093 llvm::LoadInst* LoadFromObjectOffset(llvm::Value* object_addr,
94 int64_t offset,
95 llvm::Type* type,
96 TBAASpecialType special_ty) {
TDYa127aba61122012-05-04 18:28:36 -070097 return LoadFromObjectOffset(object_addr, offset, type, tbaa_.GetSpecialType(special_ty));
98 }
99
100 void StoreToObjectOffset(llvm::Value* object_addr,
101 int64_t offset,
102 llvm::Value* new_value,
103 TBAASpecialType special_ty) {
104 DCHECK_NE(special_ty, kTBAAConstJObject) << "ConstJObject is read only!";
105 StoreToObjectOffset(object_addr, offset, new_value, tbaa_.GetSpecialType(special_ty));
106 }
107
TDYa127145d4912012-05-06 21:44:45 -0700108 void SetTBAACall(llvm::CallInst* call_inst, TBAASpecialType special_ty) {
109 call_inst->setMetadata(llvm::LLVMContext::MD_tbaa, tbaa_.GetSpecialType(special_ty));
110 }
111
TDYa127aba61122012-05-04 18:28:36 -0700112
113 //--------------------------------------------------------------------------
TDYa127ac7b5bb2012-05-11 13:17:49 -0700114 // Static Branch Prediction
115 //--------------------------------------------------------------------------
116
117 // Import the orignal conditional branch
118 using LLVMIRBuilder::CreateCondBr;
119 llvm::BranchInst* CreateCondBr(llvm::Value *cond,
120 llvm::BasicBlock* true_bb,
121 llvm::BasicBlock* false_bb,
122 ExpectCond expect) {
123 DCHECK_NE(expect, MAX_EXPECT) << "MAX_EXPECT is not for branch weight";
124
125 llvm::BranchInst* branch_inst = LLVMIRBuilder::CreateCondBr(cond, true_bb, false_bb);
126 branch_inst->setMetadata(llvm::LLVMContext::MD_prof, expect_cond_[expect]);
127 return branch_inst;
128 }
129
130
131 //--------------------------------------------------------------------------
Shih-wei Liao4c1f4252012-02-13 09:57:20 -0800132 // Pointer Arithmetic Helper Function
133 //--------------------------------------------------------------------------
134
135 llvm::IntegerType* getPtrEquivIntTy() {
136 return getInt32Ty();
137 }
138
139 size_t getSizeOfPtrEquivInt() {
140 return 4;
141 }
142
143 llvm::ConstantInt* getSizeOfPtrEquivIntValue() {
144 return getPtrEquivInt(getSizeOfPtrEquivInt());
145 }
146
TDYa127ee1f59b2012-04-25 00:56:40 -0700147 llvm::ConstantInt* getPtrEquivInt(int64_t i) {
Shih-wei Liao4c1f4252012-02-13 09:57:20 -0800148 return llvm::ConstantInt::get(getPtrEquivIntTy(), i);
149 }
150
151 llvm::Value* CreatePtrDisp(llvm::Value* base,
152 llvm::Value* offset,
153 llvm::PointerType* ret_ty) {
154
155 llvm::Value* base_int = CreatePtrToInt(base, getPtrEquivIntTy());
156 llvm::Value* result_int = CreateAdd(base_int, offset);
157 llvm::Value* result = CreateIntToPtr(result_int, ret_ty);
158
159 return result;
160 }
161
162 llvm::Value* CreatePtrDisp(llvm::Value* base,
163 llvm::Value* bs,
164 llvm::Value* count,
165 llvm::Value* offset,
166 llvm::PointerType* ret_ty) {
167
168 llvm::Value* block_offset = CreateMul(bs, count);
169 llvm::Value* total_offset = CreateAdd(block_offset, offset);
170
171 return CreatePtrDisp(base, total_offset, ret_ty);
172 }
173
TDYa1278fe384d2012-05-06 20:14:17 -0700174 llvm::LoadInst* LoadFromObjectOffset(llvm::Value* object_addr,
175 int64_t offset,
176 llvm::Type* type,
177 llvm::MDNode* tbaa_info) {
TDYa1275bb86012012-04-11 05:57:28 -0700178 // Convert offset to llvm::value
179 llvm::Value* llvm_offset = getPtrEquivInt(offset);
180 // Calculate the value's address
181 llvm::Value* value_addr = CreatePtrDisp(object_addr, llvm_offset, type->getPointerTo());
182 // Load
TDYa127aba61122012-05-04 18:28:36 -0700183 return CreateLoad(value_addr, tbaa_info);
TDYa1275bb86012012-04-11 05:57:28 -0700184 }
185
TDYa127aba61122012-05-04 18:28:36 -0700186 void StoreToObjectOffset(llvm::Value* object_addr,
187 int64_t offset,
188 llvm::Value* new_value,
189 llvm::MDNode* tbaa_info) {
TDYa1275bb86012012-04-11 05:57:28 -0700190 // Convert offset to llvm::value
191 llvm::Value* llvm_offset = getPtrEquivInt(offset);
192 // Calculate the value's address
193 llvm::Value* value_addr = CreatePtrDisp(object_addr,
194 llvm_offset,
195 new_value->getType()->getPointerTo());
196 // Store
TDYa127aba61122012-05-04 18:28:36 -0700197 CreateStore(new_value, value_addr, tbaa_info);
TDYa1275bb86012012-04-11 05:57:28 -0700198 }
199
Shih-wei Liao4c1f4252012-02-13 09:57:20 -0800200
201 //--------------------------------------------------------------------------
Logan Chien42e0e152012-01-13 15:42:36 +0800202 // Runtime Helper Function
203 //--------------------------------------------------------------------------
204
TDYa127d668a062012-04-13 12:36:57 -0700205 llvm::Function* GetRuntime(runtime_support::RuntimeId rt) {
206 return runtime_support_->GetRuntimeSupportFunction(rt);
207 }
208
209 void SetRuntimeSupport(RuntimeSupportBuilder* runtime_support) {
210 // Can only set once. We can't do this on constructor, because RuntimeSupportBuilder needs
211 // IRBuilder.
212 if (runtime_support_ == NULL && runtime_support != NULL) {
213 runtime_support_ = runtime_support;
214 }
215 }
Logan Chien42e0e152012-01-13 15:42:36 +0800216
217
218 //--------------------------------------------------------------------------
Shih-wei Liaod1fec812012-02-13 09:51:10 -0800219 // Type Helper Function
220 //--------------------------------------------------------------------------
221
222 llvm::Type* getJType(char shorty_jty, JTypeSpace space) {
223 return getJType(GetJTypeFromShorty(shorty_jty), space);
224 }
225
226 llvm::Type* getJType(JType jty, JTypeSpace space) {
227 switch (space) {
228 case kAccurate:
229 return getJTypeInAccurateSpace(jty);
230
231 case kReg:
232 case kField: // Currently field space is equivalent to register space.
233 return getJTypeInRegSpace(jty);
234
235 case kArray:
236 return getJTypeInArraySpace(jty);
237 }
238
Logan Chien83426162011-12-09 09:29:50 +0800239 LOG(FATAL) << "Unknown type space: " << space;
Shih-wei Liaod1fec812012-02-13 09:51:10 -0800240 return NULL;
241 }
242
243 llvm::Type* getJVoidTy() {
244 return getVoidTy();
245 }
246
247 llvm::IntegerType* getJBooleanTy() {
248 return getInt1Ty();
249 }
250
251 llvm::IntegerType* getJByteTy() {
252 return getInt8Ty();
253 }
254
255 llvm::IntegerType* getJCharTy() {
256 return getInt16Ty();
257 }
258
259 llvm::IntegerType* getJShortTy() {
260 return getInt16Ty();
261 }
262
263 llvm::IntegerType* getJIntTy() {
264 return getInt32Ty();
265 }
266
267 llvm::IntegerType* getJLongTy() {
268 return getInt64Ty();
269 }
270
271 llvm::Type* getJFloatTy() {
272 return getFloatTy();
273 }
274
275 llvm::Type* getJDoubleTy() {
276 return getDoubleTy();
277 }
278
279 llvm::PointerType* getJObjectTy() {
280 return jobject_type_;
281 }
282
Logan Chienf04364f2012-02-10 12:01:39 +0800283 llvm::PointerType* getJEnvTy() {
284 return jenv_type_;
285 }
286
287 llvm::Type* getJValueTy() {
288 // NOTE: JValue is an union type, which may contains boolean, byte, char,
289 // short, int, long, float, double, Object. However, LLVM itself does
290 // not support union type, so we have to return a type with biggest size,
291 // then bitcast it before we use it.
292 return getJLongTy();
293 }
294
Logan Chien8dfcbea2012-02-17 18:50:32 +0800295 llvm::StructType* getShadowFrameTy(uint32_t sirt_size);
296
Shih-wei Liaod1fec812012-02-13 09:51:10 -0800297
298 //--------------------------------------------------------------------------
299 // Constant Value Helper Function
300 //--------------------------------------------------------------------------
301
302 llvm::ConstantInt* getJBoolean(bool is_true) {
303 return (is_true) ? getTrue() : getFalse();
304 }
305
306 llvm::ConstantInt* getJByte(int8_t i) {
307 return llvm::ConstantInt::getSigned(getJByteTy(), i);
308 }
309
310 llvm::ConstantInt* getJChar(int16_t i) {
311 return llvm::ConstantInt::getSigned(getJCharTy(), i);
312 }
313
314 llvm::ConstantInt* getJShort(int16_t i) {
315 return llvm::ConstantInt::getSigned(getJShortTy(), i);
316 }
317
318 llvm::ConstantInt* getJInt(int32_t i) {
319 return llvm::ConstantInt::getSigned(getJIntTy(), i);
320 }
321
322 llvm::ConstantInt* getJLong(int64_t i) {
323 return llvm::ConstantInt::getSigned(getJLongTy(), i);
324 }
325
326 llvm::Constant* getJFloat(float f) {
327 return llvm::ConstantFP::get(getJFloatTy(), f);
328 }
329
330 llvm::Constant* getJDouble(double d) {
331 return llvm::ConstantFP::get(getJDoubleTy(), d);
332 }
333
334 llvm::ConstantPointerNull* getJNull() {
335 return llvm::ConstantPointerNull::get(getJObjectTy());
336 }
337
338 llvm::Constant* getJZero(char shorty_jty) {
339 return getJZero(GetJTypeFromShorty(shorty_jty));
340 }
341
342 llvm::Constant* getJZero(JType jty) {
343 switch (jty) {
344 case kVoid:
Logan Chien83426162011-12-09 09:29:50 +0800345 LOG(FATAL) << "Zero is not a value of void type";
Shih-wei Liaod1fec812012-02-13 09:51:10 -0800346 return NULL;
347
348 case kBoolean:
349 return getJBoolean(false);
350
351 case kByte:
352 return getJByte(0);
353
354 case kChar:
355 return getJChar(0);
356
357 case kShort:
358 return getJShort(0);
359
360 case kInt:
361 return getJInt(0);
362
363 case kLong:
364 return getJLong(0);
365
366 case kFloat:
367 return getJFloat(0.0f);
368
369 case kDouble:
370 return getJDouble(0.0);
371
372 case kObject:
373 return getJNull();
Shih-wei Liaod1fec812012-02-13 09:51:10 -0800374
TDYa127706e7db2012-05-06 00:05:33 -0700375 default:
376 LOG(FATAL) << "Unknown java type: " << jty;
377 return NULL;
378 }
Shih-wei Liaod1fec812012-02-13 09:51:10 -0800379 }
380
381
382 private:
383 //--------------------------------------------------------------------------
384 // Type Helper Function (Private)
385 //--------------------------------------------------------------------------
386
387 llvm::Type* getJTypeInAccurateSpace(JType jty);
388 llvm::Type* getJTypeInRegSpace(JType jty);
389 llvm::Type* getJTypeInArraySpace(JType jty);
390
391
392 private:
Logan Chien6a917992012-02-17 18:43:48 +0800393 llvm::Module* module_;
394
Shih-wei Liaod1fec812012-02-13 09:51:10 -0800395 llvm::PointerType* jobject_type_;
396
Logan Chienf04364f2012-02-10 12:01:39 +0800397 llvm::PointerType* jenv_type_;
398
Logan Chien8dfcbea2012-02-17 18:50:32 +0800399 llvm::StructType* art_frame_type_;
400
TDYa127aba61122012-05-04 18:28:36 -0700401 TBAAInfo tbaa_;
402
TDYa127d668a062012-04-13 12:36:57 -0700403 RuntimeSupportBuilder* runtime_support_;
Logan Chien42e0e152012-01-13 15:42:36 +0800404
TDYa127ac7b5bb2012-05-11 13:17:49 -0700405 llvm::MDNode* expect_cond_[MAX_EXPECT];
Shih-wei Liaod1fec812012-02-13 09:51:10 -0800406};
407
408
409} // namespace compiler_llvm
410} // namespace art
411
412#endif // ART_SRC_COMPILER_LLVM_IR_BUILDER_H_