• 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