blob: 39f8fb1f622f3fbe383e3248aebb9a54ba995036 [file] [log] [blame]
Ian Rogers4c1c2832013-03-04 18:30:13 -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"
21#include "compiler/dex/compiler_enums.h"
22#include "intrinsic_helper.h"
23#include "md_builder.h"
24#include "runtime_support_builder.h"
25#include "runtime_support_func.h"
26
Brian Carlstrom37d48792013-03-22 14:14:45 -070027#include <llvm/IR/Constants.h>
28#include <llvm/IR/DerivedTypes.h>
29#include <llvm/IR/IRBuilder.h>
30#include <llvm/IR/LLVMContext.h>
31#include <llvm/IR/Type.h>
Ian Rogers4c1c2832013-03-04 18:30:13 -080032#include <llvm/Support/NoFolder.h>
Ian Rogers4c1c2832013-03-04 18:30:13 -080033
34#include <stdint.h>
35
36
37namespace art {
38namespace llvm {
39
40class InserterWithDexOffset : public ::llvm::IRBuilderDefaultInserter<true> {
41 public:
42 InserterWithDexOffset() : node_(NULL) {}
43
44 void InsertHelper(::llvm::Instruction *I, const ::llvm::Twine &Name,
45 ::llvm::BasicBlock *BB,
46 ::llvm::BasicBlock::iterator InsertPt) const {
47 ::llvm::IRBuilderDefaultInserter<true>::InsertHelper(I, Name, BB, InsertPt);
48 if (node_ != NULL) {
49 I->setMetadata("DexOff", node_);
50 }
51 }
52
53 void SetDexOffset(::llvm::MDNode* node) {
54 node_ = node;
55 }
56 private:
57 ::llvm::MDNode* node_;
58};
59
60typedef ::llvm::IRBuilder<true, ::llvm::ConstantFolder, InserterWithDexOffset> LLVMIRBuilder;
61// NOTE: Here we define our own LLVMIRBuilder type alias, so that we can
62// switch "preserveNames" template parameter easily.
63
64
65class IRBuilder : public LLVMIRBuilder {
66 public:
67 //--------------------------------------------------------------------------
68 // General
69 //--------------------------------------------------------------------------
70
71 IRBuilder(::llvm::LLVMContext& context, ::llvm::Module& module,
72 IntrinsicHelper& intrinsic_helper);
73
74
75 //--------------------------------------------------------------------------
76 // Extend load & store for TBAA
77 //--------------------------------------------------------------------------
78
79 ::llvm::LoadInst* CreateLoad(::llvm::Value* ptr, ::llvm::MDNode* tbaa_info) {
80 ::llvm::LoadInst* inst = LLVMIRBuilder::CreateLoad(ptr);
81 inst->setMetadata(::llvm::LLVMContext::MD_tbaa, tbaa_info);
82 return inst;
83 }
84
85 ::llvm::StoreInst* CreateStore(::llvm::Value* val, ::llvm::Value* ptr, ::llvm::MDNode* tbaa_info) {
86 ::llvm::StoreInst* inst = LLVMIRBuilder::CreateStore(val, ptr);
87 inst->setMetadata(::llvm::LLVMContext::MD_tbaa, tbaa_info);
88 return inst;
89 }
90
91 ::llvm::AtomicCmpXchgInst*
92 CreateAtomicCmpXchgInst(::llvm::Value* ptr, ::llvm::Value* cmp, ::llvm::Value* val,
93 ::llvm::MDNode* tbaa_info) {
94 ::llvm::AtomicCmpXchgInst* inst =
95 LLVMIRBuilder::CreateAtomicCmpXchg(ptr, cmp, val, ::llvm::Acquire);
96 inst->setMetadata(::llvm::LLVMContext::MD_tbaa, tbaa_info);
97 return inst;
98 }
99
100 //--------------------------------------------------------------------------
101 // Extend memory barrier
102 //--------------------------------------------------------------------------
103 void CreateMemoryBarrier(MemBarrierKind barrier_kind) {
104#if ANDROID_SMP
105 // TODO: select atomic ordering according to given barrier kind.
106 CreateFence(::llvm::SequentiallyConsistent);
107#endif
108 }
109
110 //--------------------------------------------------------------------------
111 // TBAA
112 //--------------------------------------------------------------------------
113
114 // TODO: After we design the non-special TBAA info, re-design the TBAA interface.
115 ::llvm::LoadInst* CreateLoad(::llvm::Value* ptr, TBAASpecialType special_ty) {
116 return CreateLoad(ptr, mdb_.GetTBAASpecialType(special_ty));
117 }
118
119 ::llvm::StoreInst* CreateStore(::llvm::Value* val, ::llvm::Value* ptr, TBAASpecialType special_ty) {
120 DCHECK_NE(special_ty, kTBAAConstJObject) << "ConstJObject is read only!";
121 return CreateStore(val, ptr, mdb_.GetTBAASpecialType(special_ty));
122 }
123
124 ::llvm::LoadInst* CreateLoad(::llvm::Value* ptr, TBAASpecialType special_ty, JType j_ty) {
125 return CreateLoad(ptr, mdb_.GetTBAAMemoryJType(special_ty, j_ty));
126 }
127
128 ::llvm::StoreInst* CreateStore(::llvm::Value* val, ::llvm::Value* ptr,
129 TBAASpecialType special_ty, JType j_ty) {
130 DCHECK_NE(special_ty, kTBAAConstJObject) << "ConstJObject is read only!";
131 return CreateStore(val, ptr, mdb_.GetTBAAMemoryJType(special_ty, j_ty));
132 }
133
134 ::llvm::LoadInst* LoadFromObjectOffset(::llvm::Value* object_addr,
135 int64_t offset,
136 ::llvm::Type* type,
137 TBAASpecialType special_ty) {
138 return LoadFromObjectOffset(object_addr, offset, type, mdb_.GetTBAASpecialType(special_ty));
139 }
140
141 void StoreToObjectOffset(::llvm::Value* object_addr,
142 int64_t offset,
143 ::llvm::Value* new_value,
144 TBAASpecialType special_ty) {
145 DCHECK_NE(special_ty, kTBAAConstJObject) << "ConstJObject is read only!";
146 StoreToObjectOffset(object_addr, offset, new_value, mdb_.GetTBAASpecialType(special_ty));
147 }
148
149 ::llvm::LoadInst* LoadFromObjectOffset(::llvm::Value* object_addr,
150 int64_t offset,
151 ::llvm::Type* type,
152 TBAASpecialType special_ty, JType j_ty) {
153 return LoadFromObjectOffset(object_addr, offset, type, mdb_.GetTBAAMemoryJType(special_ty, j_ty));
154 }
155
156 void StoreToObjectOffset(::llvm::Value* object_addr,
157 int64_t offset,
158 ::llvm::Value* new_value,
159 TBAASpecialType special_ty, JType j_ty) {
160 DCHECK_NE(special_ty, kTBAAConstJObject) << "ConstJObject is read only!";
161 StoreToObjectOffset(object_addr, offset, new_value, mdb_.GetTBAAMemoryJType(special_ty, j_ty));
162 }
163
164 ::llvm::AtomicCmpXchgInst*
165 CompareExchangeObjectOffset(::llvm::Value* object_addr,
166 int64_t offset,
167 ::llvm::Value* cmp_value,
168 ::llvm::Value* new_value,
169 TBAASpecialType special_ty) {
170 DCHECK_NE(special_ty, kTBAAConstJObject) << "ConstJObject is read only!";
171 return CompareExchangeObjectOffset(object_addr, offset, cmp_value, new_value,
172 mdb_.GetTBAASpecialType(special_ty));
173 }
174
175 void SetTBAA(::llvm::Instruction* inst, TBAASpecialType special_ty) {
176 inst->setMetadata(::llvm::LLVMContext::MD_tbaa, mdb_.GetTBAASpecialType(special_ty));
177 }
178
179
180 //--------------------------------------------------------------------------
181 // Static Branch Prediction
182 //--------------------------------------------------------------------------
183
184 // Import the orignal conditional branch
185 using LLVMIRBuilder::CreateCondBr;
186 ::llvm::BranchInst* CreateCondBr(::llvm::Value *cond,
187 ::llvm::BasicBlock* true_bb,
188 ::llvm::BasicBlock* false_bb,
189 ExpectCond expect) {
190 ::llvm::BranchInst* branch_inst = CreateCondBr(cond, true_bb, false_bb);
191 branch_inst->setMetadata(::llvm::LLVMContext::MD_prof, mdb_.GetBranchWeights(expect));
192 return branch_inst;
193 }
194
195
196 //--------------------------------------------------------------------------
197 // Pointer Arithmetic Helper Function
198 //--------------------------------------------------------------------------
199
200 ::llvm::IntegerType* getPtrEquivIntTy() {
201 return getInt32Ty();
202 }
203
204 size_t getSizeOfPtrEquivInt() {
205 return 4;
206 }
207
208 ::llvm::ConstantInt* getSizeOfPtrEquivIntValue() {
209 return getPtrEquivInt(getSizeOfPtrEquivInt());
210 }
211
212 ::llvm::ConstantInt* getPtrEquivInt(int64_t i) {
213 return ::llvm::ConstantInt::get(getPtrEquivIntTy(), i);
214 }
215
216 ::llvm::Value* CreatePtrDisp(::llvm::Value* base,
217 ::llvm::Value* offset,
218 ::llvm::PointerType* ret_ty) {
219
220 ::llvm::Value* base_int = CreatePtrToInt(base, getPtrEquivIntTy());
221 ::llvm::Value* result_int = CreateAdd(base_int, offset);
222 ::llvm::Value* result = CreateIntToPtr(result_int, ret_ty);
223
224 return result;
225 }
226
227 ::llvm::Value* CreatePtrDisp(::llvm::Value* base,
228 ::llvm::Value* bs,
229 ::llvm::Value* count,
230 ::llvm::Value* offset,
231 ::llvm::PointerType* ret_ty) {
232
233 ::llvm::Value* block_offset = CreateMul(bs, count);
234 ::llvm::Value* total_offset = CreateAdd(block_offset, offset);
235
236 return CreatePtrDisp(base, total_offset, ret_ty);
237 }
238
239 ::llvm::LoadInst* LoadFromObjectOffset(::llvm::Value* object_addr,
240 int64_t offset,
241 ::llvm::Type* type,
242 ::llvm::MDNode* tbaa_info) {
243 // Convert offset to ::llvm::value
244 ::llvm::Value* llvm_offset = getPtrEquivInt(offset);
245 // Calculate the value's address
246 ::llvm::Value* value_addr = CreatePtrDisp(object_addr, llvm_offset, type->getPointerTo());
247 // Load
248 return CreateLoad(value_addr, tbaa_info);
249 }
250
251 void StoreToObjectOffset(::llvm::Value* object_addr,
252 int64_t offset,
253 ::llvm::Value* new_value,
254 ::llvm::MDNode* tbaa_info) {
255 // Convert offset to ::llvm::value
256 ::llvm::Value* llvm_offset = getPtrEquivInt(offset);
257 // Calculate the value's address
258 ::llvm::Value* value_addr = CreatePtrDisp(object_addr,
259 llvm_offset,
260 new_value->getType()->getPointerTo());
261 // Store
262 CreateStore(new_value, value_addr, tbaa_info);
263 }
264
265 ::llvm::AtomicCmpXchgInst* CompareExchangeObjectOffset(::llvm::Value* object_addr,
266 int64_t offset,
267 ::llvm::Value* cmp_value,
268 ::llvm::Value* new_value,
269 ::llvm::MDNode* tbaa_info) {
270 // Convert offset to ::llvm::value
271 ::llvm::Value* llvm_offset = getPtrEquivInt(offset);
272 // Calculate the value's address
273 ::llvm::Value* value_addr = CreatePtrDisp(object_addr,
274 llvm_offset,
275 new_value->getType()->getPointerTo());
276 // Atomic compare and exchange
277 return CreateAtomicCmpXchgInst(value_addr, cmp_value, new_value, tbaa_info);
278 }
279
280
281 //--------------------------------------------------------------------------
282 // Runtime Helper Function
283 //--------------------------------------------------------------------------
284
285 RuntimeSupportBuilder& Runtime() {
286 return *runtime_support_;
287 }
288
289 // TODO: Deprecate
290 ::llvm::Function* GetRuntime(runtime_support::RuntimeId rt) {
291 return runtime_support_->GetRuntimeSupportFunction(rt);
292 }
293
294 // TODO: Deprecate
295 void SetRuntimeSupport(RuntimeSupportBuilder* runtime_support) {
296 // Can only set once. We can't do this on constructor, because RuntimeSupportBuilder needs
297 // IRBuilder.
298 if (runtime_support_ == NULL && runtime_support != NULL) {
299 runtime_support_ = runtime_support;
300 }
301 }
302
303
304 //--------------------------------------------------------------------------
305 // Type Helper Function
306 //--------------------------------------------------------------------------
307
308 ::llvm::Type* getJType(char shorty_jty) {
309 return getJType(GetJTypeFromShorty(shorty_jty));
310 }
311
312 ::llvm::Type* getJType(JType jty);
313
314 ::llvm::Type* getJVoidTy() {
315 return getVoidTy();
316 }
317
318 ::llvm::IntegerType* getJBooleanTy() {
319 return getInt8Ty();
320 }
321
322 ::llvm::IntegerType* getJByteTy() {
323 return getInt8Ty();
324 }
325
326 ::llvm::IntegerType* getJCharTy() {
327 return getInt16Ty();
328 }
329
330 ::llvm::IntegerType* getJShortTy() {
331 return getInt16Ty();
332 }
333
334 ::llvm::IntegerType* getJIntTy() {
335 return getInt32Ty();
336 }
337
338 ::llvm::IntegerType* getJLongTy() {
339 return getInt64Ty();
340 }
341
342 ::llvm::Type* getJFloatTy() {
343 return getFloatTy();
344 }
345
346 ::llvm::Type* getJDoubleTy() {
347 return getDoubleTy();
348 }
349
350 ::llvm::PointerType* getJObjectTy() {
351 return java_object_type_;
352 }
353
354 ::llvm::PointerType* getJMethodTy() {
355 return java_method_type_;
356 }
357
358 ::llvm::PointerType* getJThreadTy() {
359 return java_thread_type_;
360 }
361
362 ::llvm::Type* getArtFrameTy() {
363 return art_frame_type_;
364 }
365
366 ::llvm::PointerType* getJEnvTy() {
367 return jenv_type_;
368 }
369
370 ::llvm::Type* getJValueTy() {
371 // NOTE: JValue is an union type, which may contains boolean, byte, char,
372 // short, int, long, float, double, Object. However, LLVM itself does
373 // not support union type, so we have to return a type with biggest size,
374 // then bitcast it before we use it.
375 return getJLongTy();
376 }
377
378 ::llvm::StructType* getShadowFrameTy(uint32_t vreg_size);
379
380
381 //--------------------------------------------------------------------------
382 // Constant Value Helper Function
383 //--------------------------------------------------------------------------
384
385 ::llvm::ConstantInt* getJBoolean(bool is_true) {
386 return (is_true) ? getTrue() : getFalse();
387 }
388
389 ::llvm::ConstantInt* getJByte(int8_t i) {
390 return ::llvm::ConstantInt::getSigned(getJByteTy(), i);
391 }
392
393 ::llvm::ConstantInt* getJChar(int16_t i) {
394 return ::llvm::ConstantInt::getSigned(getJCharTy(), i);
395 }
396
397 ::llvm::ConstantInt* getJShort(int16_t i) {
398 return ::llvm::ConstantInt::getSigned(getJShortTy(), i);
399 }
400
401 ::llvm::ConstantInt* getJInt(int32_t i) {
402 return ::llvm::ConstantInt::getSigned(getJIntTy(), i);
403 }
404
405 ::llvm::ConstantInt* getJLong(int64_t i) {
406 return ::llvm::ConstantInt::getSigned(getJLongTy(), i);
407 }
408
409 ::llvm::Constant* getJFloat(float f) {
410 return ::llvm::ConstantFP::get(getJFloatTy(), f);
411 }
412
413 ::llvm::Constant* getJDouble(double d) {
414 return ::llvm::ConstantFP::get(getJDoubleTy(), d);
415 }
416
417 ::llvm::ConstantPointerNull* getJNull() {
418 return ::llvm::ConstantPointerNull::get(getJObjectTy());
419 }
420
421 ::llvm::Constant* getJZero(char shorty_jty) {
422 return getJZero(GetJTypeFromShorty(shorty_jty));
423 }
424
425 ::llvm::Constant* getJZero(JType jty) {
426 switch (jty) {
427 case kVoid:
428 LOG(FATAL) << "Zero is not a value of void type";
429 return NULL;
430
431 case kBoolean:
432 return getJBoolean(false);
433
434 case kByte:
435 return getJByte(0);
436
437 case kChar:
438 return getJChar(0);
439
440 case kShort:
441 return getJShort(0);
442
443 case kInt:
444 return getJInt(0);
445
446 case kLong:
447 return getJLong(0);
448
449 case kFloat:
450 return getJFloat(0.0f);
451
452 case kDouble:
453 return getJDouble(0.0);
454
455 case kObject:
456 return getJNull();
457
458 default:
459 LOG(FATAL) << "Unknown java type: " << jty;
460 return NULL;
461 }
462 }
463
464
465 private:
466 ::llvm::Module* module_;
467
468 MDBuilder mdb_;
469
470 ::llvm::PointerType* java_object_type_;
471 ::llvm::PointerType* java_method_type_;
472 ::llvm::PointerType* java_thread_type_;
473
474 ::llvm::PointerType* jenv_type_;
475
476 ::llvm::StructType* art_frame_type_;
477
478 RuntimeSupportBuilder* runtime_support_;
479
480 IntrinsicHelper& intrinsic_helper_;
481};
482
483
484} // namespace llvm
485} // namespace art
486
487#endif // ART_SRC_COMPILER_LLVM_IR_BUILDER_H_