• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_IR_BUILDER_H_
18 #define ART_COMPILER_LLVM_IR_BUILDER_H_
19 
20 #include "backend_types.h"
21 #include "dex/compiler_enums.h"
22 #include "intrinsic_helper.h"
23 #include "md_builder.h"
24 #include "runtime_support_builder.h"
25 #include "runtime_support_llvm_func.h"
26 
27 #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>
32 #include <llvm/Support/NoFolder.h>
33 
34 #include <stdint.h>
35 
36 
37 namespace art {
38 namespace llvm {
39 
40 class InserterWithDexOffset : public ::llvm::IRBuilderDefaultInserter<true> {
41   public:
InserterWithDexOffset()42     InserterWithDexOffset() : node_(NULL) {}
43 
InsertHelper(::llvm::Instruction * I,const::llvm::Twine & Name,::llvm::BasicBlock * BB,::llvm::BasicBlock::iterator InsertPt)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 
SetDexOffset(::llvm::MDNode * node)53     void SetDexOffset(::llvm::MDNode* node) {
54       node_ = node;
55     }
56   private:
57     ::llvm::MDNode* node_;
58 };
59 
60 typedef ::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 
65 class 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 
CreateLoad(::llvm::Value * ptr,::llvm::MDNode * tbaa_info)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 
CreateStore(::llvm::Value * val,::llvm::Value * ptr,::llvm::MDNode * tbaa_info)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*
CreateAtomicCmpXchgInst(::llvm::Value * ptr,::llvm::Value * cmp,::llvm::Value * val,::llvm::MDNode * tbaa_info)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   //--------------------------------------------------------------------------
CreateMemoryBarrier(MemBarrierKind barrier_kind)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.
CreateLoad(::llvm::Value * ptr,TBAASpecialType special_ty)115   ::llvm::LoadInst* CreateLoad(::llvm::Value* ptr, TBAASpecialType special_ty) {
116     return CreateLoad(ptr, mdb_.GetTBAASpecialType(special_ty));
117   }
118 
CreateStore(::llvm::Value * val,::llvm::Value * ptr,TBAASpecialType special_ty)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 
CreateLoad(::llvm::Value * ptr,TBAASpecialType special_ty,JType j_ty)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 
CreateStore(::llvm::Value * val,::llvm::Value * ptr,TBAASpecialType special_ty,JType j_ty)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 
LoadFromObjectOffset(::llvm::Value * object_addr,int64_t offset,::llvm::Type * type,TBAASpecialType special_ty)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 
StoreToObjectOffset(::llvm::Value * object_addr,int64_t offset,::llvm::Value * new_value,TBAASpecialType special_ty)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 
LoadFromObjectOffset(::llvm::Value * object_addr,int64_t offset,::llvm::Type * type,TBAASpecialType special_ty,JType j_ty)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 
StoreToObjectOffset(::llvm::Value * object_addr,int64_t offset,::llvm::Value * new_value,TBAASpecialType special_ty,JType j_ty)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*
CompareExchangeObjectOffset(::llvm::Value * object_addr,int64_t offset,::llvm::Value * cmp_value,::llvm::Value * new_value,TBAASpecialType special_ty)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 
SetTBAA(::llvm::Instruction * inst,TBAASpecialType special_ty)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;
CreateCondBr(::llvm::Value * cond,::llvm::BasicBlock * true_bb,::llvm::BasicBlock * false_bb,ExpectCond expect)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     if (false) {
192       // TODO: http://b/8511695 Restore branch weight metadata
193       branch_inst->setMetadata(::llvm::LLVMContext::MD_prof, mdb_.GetBranchWeights(expect));
194     }
195     return branch_inst;
196   }
197 
198 
199   //--------------------------------------------------------------------------
200   // Pointer Arithmetic Helper Function
201   //--------------------------------------------------------------------------
202 
getPtrEquivIntTy()203   ::llvm::IntegerType* getPtrEquivIntTy() {
204     return getInt32Ty();
205   }
206 
getSizeOfPtrEquivInt()207   size_t getSizeOfPtrEquivInt() {
208     return 4;
209   }
210 
getSizeOfPtrEquivIntValue()211   ::llvm::ConstantInt* getSizeOfPtrEquivIntValue() {
212     return getPtrEquivInt(getSizeOfPtrEquivInt());
213   }
214 
getPtrEquivInt(int64_t i)215   ::llvm::ConstantInt* getPtrEquivInt(int64_t i) {
216     return ::llvm::ConstantInt::get(getPtrEquivIntTy(), i);
217   }
218 
CreatePtrDisp(::llvm::Value * base,::llvm::Value * offset,::llvm::PointerType * ret_ty)219   ::llvm::Value* CreatePtrDisp(::llvm::Value* base,
220                              ::llvm::Value* offset,
221                              ::llvm::PointerType* ret_ty) {
222     ::llvm::Value* base_int = CreatePtrToInt(base, getPtrEquivIntTy());
223     ::llvm::Value* result_int = CreateAdd(base_int, offset);
224     ::llvm::Value* result = CreateIntToPtr(result_int, ret_ty);
225 
226     return result;
227   }
228 
CreatePtrDisp(::llvm::Value * base,::llvm::Value * bs,::llvm::Value * count,::llvm::Value * offset,::llvm::PointerType * ret_ty)229   ::llvm::Value* CreatePtrDisp(::llvm::Value* base,
230                              ::llvm::Value* bs,
231                              ::llvm::Value* count,
232                              ::llvm::Value* offset,
233                              ::llvm::PointerType* ret_ty) {
234     ::llvm::Value* block_offset = CreateMul(bs, count);
235     ::llvm::Value* total_offset = CreateAdd(block_offset, offset);
236 
237     return CreatePtrDisp(base, total_offset, ret_ty);
238   }
239 
LoadFromObjectOffset(::llvm::Value * object_addr,int64_t offset,::llvm::Type * type,::llvm::MDNode * tbaa_info)240   ::llvm::LoadInst* LoadFromObjectOffset(::llvm::Value* object_addr,
241                                        int64_t offset,
242                                        ::llvm::Type* type,
243                                        ::llvm::MDNode* tbaa_info) {
244     // Convert offset to ::llvm::value
245     ::llvm::Value* llvm_offset = getPtrEquivInt(offset);
246     // Calculate the value's address
247     ::llvm::Value* value_addr = CreatePtrDisp(object_addr, llvm_offset, type->getPointerTo());
248     // Load
249     return CreateLoad(value_addr, tbaa_info);
250   }
251 
StoreToObjectOffset(::llvm::Value * object_addr,int64_t offset,::llvm::Value * new_value,::llvm::MDNode * tbaa_info)252   void StoreToObjectOffset(::llvm::Value* object_addr,
253                            int64_t offset,
254                            ::llvm::Value* new_value,
255                            ::llvm::MDNode* tbaa_info) {
256     // Convert offset to ::llvm::value
257     ::llvm::Value* llvm_offset = getPtrEquivInt(offset);
258     // Calculate the value's address
259     ::llvm::Value* value_addr = CreatePtrDisp(object_addr,
260                                             llvm_offset,
261                                             new_value->getType()->getPointerTo());
262     // Store
263     CreateStore(new_value, value_addr, tbaa_info);
264   }
265 
CompareExchangeObjectOffset(::llvm::Value * object_addr,int64_t offset,::llvm::Value * cmp_value,::llvm::Value * new_value,::llvm::MDNode * tbaa_info)266   ::llvm::AtomicCmpXchgInst* CompareExchangeObjectOffset(::llvm::Value* object_addr,
267                                                        int64_t offset,
268                                                        ::llvm::Value* cmp_value,
269                                                        ::llvm::Value* new_value,
270                                                        ::llvm::MDNode* tbaa_info) {
271     // Convert offset to ::llvm::value
272     ::llvm::Value* llvm_offset = getPtrEquivInt(offset);
273     // Calculate the value's address
274     ::llvm::Value* value_addr = CreatePtrDisp(object_addr,
275                                             llvm_offset,
276                                             new_value->getType()->getPointerTo());
277     // Atomic compare and exchange
278     return CreateAtomicCmpXchgInst(value_addr, cmp_value, new_value, tbaa_info);
279   }
280 
281 
282   //--------------------------------------------------------------------------
283   // Runtime Helper Function
284   //--------------------------------------------------------------------------
285 
Runtime()286   RuntimeSupportBuilder& Runtime() {
287     return *runtime_support_;
288   }
289 
290   // TODO: Deprecate
GetRuntime(runtime_support::RuntimeId rt)291   ::llvm::Function* GetRuntime(runtime_support::RuntimeId rt) {
292     return runtime_support_->GetRuntimeSupportFunction(rt);
293   }
294 
295   // TODO: Deprecate
SetRuntimeSupport(RuntimeSupportBuilder * runtime_support)296   void SetRuntimeSupport(RuntimeSupportBuilder* runtime_support) {
297     // Can only set once. We can't do this on constructor, because RuntimeSupportBuilder needs
298     // IRBuilder.
299     if (runtime_support_ == NULL && runtime_support != NULL) {
300       runtime_support_ = runtime_support;
301     }
302   }
303 
304 
305   //--------------------------------------------------------------------------
306   // Type Helper Function
307   //--------------------------------------------------------------------------
308 
getJType(char shorty_jty)309   ::llvm::Type* getJType(char shorty_jty) {
310     return getJType(GetJTypeFromShorty(shorty_jty));
311   }
312 
313   ::llvm::Type* getJType(JType jty);
314 
getJVoidTy()315   ::llvm::Type* getJVoidTy() {
316     return getVoidTy();
317   }
318 
getJBooleanTy()319   ::llvm::IntegerType* getJBooleanTy() {
320     return getInt8Ty();
321   }
322 
getJByteTy()323   ::llvm::IntegerType* getJByteTy() {
324     return getInt8Ty();
325   }
326 
getJCharTy()327   ::llvm::IntegerType* getJCharTy() {
328     return getInt16Ty();
329   }
330 
getJShortTy()331   ::llvm::IntegerType* getJShortTy() {
332     return getInt16Ty();
333   }
334 
getJIntTy()335   ::llvm::IntegerType* getJIntTy() {
336     return getInt32Ty();
337   }
338 
getJLongTy()339   ::llvm::IntegerType* getJLongTy() {
340     return getInt64Ty();
341   }
342 
getJFloatTy()343   ::llvm::Type* getJFloatTy() {
344     return getFloatTy();
345   }
346 
getJDoubleTy()347   ::llvm::Type* getJDoubleTy() {
348     return getDoubleTy();
349   }
350 
getJObjectTy()351   ::llvm::PointerType* getJObjectTy() {
352     return java_object_type_;
353   }
354 
getJMethodTy()355   ::llvm::PointerType* getJMethodTy() {
356     return java_method_type_;
357   }
358 
getJThreadTy()359   ::llvm::PointerType* getJThreadTy() {
360     return java_thread_type_;
361   }
362 
getArtFrameTy()363   ::llvm::Type* getArtFrameTy() {
364     return art_frame_type_;
365   }
366 
getJEnvTy()367   ::llvm::PointerType* getJEnvTy() {
368     return jenv_type_;
369   }
370 
getJValueTy()371   ::llvm::Type* getJValueTy() {
372     // NOTE: JValue is an union type, which may contains boolean, byte, char,
373     // short, int, long, float, double, Object.  However, LLVM itself does
374     // not support union type, so we have to return a type with biggest size,
375     // then bitcast it before we use it.
376     return getJLongTy();
377   }
378 
379   ::llvm::StructType* getShadowFrameTy(uint32_t vreg_size);
380 
381 
382   //--------------------------------------------------------------------------
383   // Constant Value Helper Function
384   //--------------------------------------------------------------------------
385 
getJBoolean(bool is_true)386   ::llvm::ConstantInt* getJBoolean(bool is_true) {
387     return (is_true) ? getTrue() : getFalse();
388   }
389 
getJByte(int8_t i)390   ::llvm::ConstantInt* getJByte(int8_t i) {
391     return ::llvm::ConstantInt::getSigned(getJByteTy(), i);
392   }
393 
getJChar(int16_t i)394   ::llvm::ConstantInt* getJChar(int16_t i) {
395     return ::llvm::ConstantInt::getSigned(getJCharTy(), i);
396   }
397 
getJShort(int16_t i)398   ::llvm::ConstantInt* getJShort(int16_t i) {
399     return ::llvm::ConstantInt::getSigned(getJShortTy(), i);
400   }
401 
getJInt(int32_t i)402   ::llvm::ConstantInt* getJInt(int32_t i) {
403     return ::llvm::ConstantInt::getSigned(getJIntTy(), i);
404   }
405 
getJLong(int64_t i)406   ::llvm::ConstantInt* getJLong(int64_t i) {
407     return ::llvm::ConstantInt::getSigned(getJLongTy(), i);
408   }
409 
getJFloat(float f)410   ::llvm::Constant* getJFloat(float f) {
411     return ::llvm::ConstantFP::get(getJFloatTy(), f);
412   }
413 
getJDouble(double d)414   ::llvm::Constant* getJDouble(double d) {
415     return ::llvm::ConstantFP::get(getJDoubleTy(), d);
416   }
417 
getJNull()418   ::llvm::ConstantPointerNull* getJNull() {
419     return ::llvm::ConstantPointerNull::get(getJObjectTy());
420   }
421 
getJZero(char shorty_jty)422   ::llvm::Constant* getJZero(char shorty_jty) {
423     return getJZero(GetJTypeFromShorty(shorty_jty));
424   }
425 
getJZero(JType jty)426   ::llvm::Constant* getJZero(JType jty) {
427     switch (jty) {
428     case kVoid:
429       LOG(FATAL) << "Zero is not a value of void type";
430       return NULL;
431 
432     case kBoolean:
433       return getJBoolean(false);
434 
435     case kByte:
436       return getJByte(0);
437 
438     case kChar:
439       return getJChar(0);
440 
441     case kShort:
442       return getJShort(0);
443 
444     case kInt:
445       return getJInt(0);
446 
447     case kLong:
448       return getJLong(0);
449 
450     case kFloat:
451       return getJFloat(0.0f);
452 
453     case kDouble:
454       return getJDouble(0.0);
455 
456     case kObject:
457       return getJNull();
458 
459     default:
460       LOG(FATAL) << "Unknown java type: " << jty;
461       return NULL;
462     }
463   }
464 
465 
466  private:
467   ::llvm::Module* module_;
468 
469   MDBuilder mdb_;
470 
471   ::llvm::PointerType* java_object_type_;
472   ::llvm::PointerType* java_method_type_;
473   ::llvm::PointerType* java_thread_type_;
474 
475   ::llvm::PointerType* jenv_type_;
476 
477   ::llvm::StructType* art_frame_type_;
478 
479   RuntimeSupportBuilder* runtime_support_;
480 
481   IntrinsicHelper& intrinsic_helper_;
482 };
483 
484 
485 }  // namespace llvm
486 }  // namespace art
487 
488 #endif  // ART_COMPILER_LLVM_IR_BUILDER_H_
489