Home | History | Annotate | Download | only in llvm
      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:
     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 
     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 
     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     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 
    203   ::llvm::IntegerType* getPtrEquivIntTy() {
    204     return getInt32Ty();
    205   }
    206 
    207   size_t getSizeOfPtrEquivInt() {
    208     return 4;
    209   }
    210 
    211   ::llvm::ConstantInt* getSizeOfPtrEquivIntValue() {
    212     return getPtrEquivInt(getSizeOfPtrEquivInt());
    213   }
    214 
    215   ::llvm::ConstantInt* getPtrEquivInt(int64_t i) {
    216     return ::llvm::ConstantInt::get(getPtrEquivIntTy(), i);
    217   }
    218 
    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 
    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 
    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 
    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 
    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 
    286   RuntimeSupportBuilder& Runtime() {
    287     return *runtime_support_;
    288   }
    289 
    290   // TODO: Deprecate
    291   ::llvm::Function* GetRuntime(runtime_support::RuntimeId rt) {
    292     return runtime_support_->GetRuntimeSupportFunction(rt);
    293   }
    294 
    295   // TODO: Deprecate
    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 
    309   ::llvm::Type* getJType(char shorty_jty) {
    310     return getJType(GetJTypeFromShorty(shorty_jty));
    311   }
    312 
    313   ::llvm::Type* getJType(JType jty);
    314 
    315   ::llvm::Type* getJVoidTy() {
    316     return getVoidTy();
    317   }
    318 
    319   ::llvm::IntegerType* getJBooleanTy() {
    320     return getInt8Ty();
    321   }
    322 
    323   ::llvm::IntegerType* getJByteTy() {
    324     return getInt8Ty();
    325   }
    326 
    327   ::llvm::IntegerType* getJCharTy() {
    328     return getInt16Ty();
    329   }
    330 
    331   ::llvm::IntegerType* getJShortTy() {
    332     return getInt16Ty();
    333   }
    334 
    335   ::llvm::IntegerType* getJIntTy() {
    336     return getInt32Ty();
    337   }
    338 
    339   ::llvm::IntegerType* getJLongTy() {
    340     return getInt64Ty();
    341   }
    342 
    343   ::llvm::Type* getJFloatTy() {
    344     return getFloatTy();
    345   }
    346 
    347   ::llvm::Type* getJDoubleTy() {
    348     return getDoubleTy();
    349   }
    350 
    351   ::llvm::PointerType* getJObjectTy() {
    352     return java_object_type_;
    353   }
    354 
    355   ::llvm::PointerType* getJMethodTy() {
    356     return java_method_type_;
    357   }
    358 
    359   ::llvm::PointerType* getJThreadTy() {
    360     return java_thread_type_;
    361   }
    362 
    363   ::llvm::Type* getArtFrameTy() {
    364     return art_frame_type_;
    365   }
    366 
    367   ::llvm::PointerType* getJEnvTy() {
    368     return jenv_type_;
    369   }
    370 
    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 
    386   ::llvm::ConstantInt* getJBoolean(bool is_true) {
    387     return (is_true) ? getTrue() : getFalse();
    388   }
    389 
    390   ::llvm::ConstantInt* getJByte(int8_t i) {
    391     return ::llvm::ConstantInt::getSigned(getJByteTy(), i);
    392   }
    393 
    394   ::llvm::ConstantInt* getJChar(int16_t i) {
    395     return ::llvm::ConstantInt::getSigned(getJCharTy(), i);
    396   }
    397 
    398   ::llvm::ConstantInt* getJShort(int16_t i) {
    399     return ::llvm::ConstantInt::getSigned(getJShortTy(), i);
    400   }
    401 
    402   ::llvm::ConstantInt* getJInt(int32_t i) {
    403     return ::llvm::ConstantInt::getSigned(getJIntTy(), i);
    404   }
    405 
    406   ::llvm::ConstantInt* getJLong(int64_t i) {
    407     return ::llvm::ConstantInt::getSigned(getJLongTy(), i);
    408   }
    409 
    410   ::llvm::Constant* getJFloat(float f) {
    411     return ::llvm::ConstantFP::get(getJFloatTy(), f);
    412   }
    413 
    414   ::llvm::Constant* getJDouble(double d) {
    415     return ::llvm::ConstantFP::get(getJDoubleTy(), d);
    416   }
    417 
    418   ::llvm::ConstantPointerNull* getJNull() {
    419     return ::llvm::ConstantPointerNull::get(getJObjectTy());
    420   }
    421 
    422   ::llvm::Constant* getJZero(char shorty_jty) {
    423     return getJZero(GetJTypeFromShorty(shorty_jty));
    424   }
    425 
    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