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_INTRINSIC_HELPER_H_
     18 #define ART_COMPILER_LLVM_INTRINSIC_HELPER_H_
     19 
     20 #include "base/logging.h"
     21 
     22 #include <llvm/ADT/DenseMap.h>
     23 
     24 namespace llvm {
     25   class Function;
     26   class FunctionType;
     27   class LLVMContext;
     28   class Module;
     29 }  // namespace llvm
     30 
     31 namespace art {
     32 namespace llvm {
     33 
     34 class IRBuilder;
     35 
     36 class IntrinsicHelper {
     37  public:
     38   enum IntrinsicId {
     39 #define DEF_INTRINSICS_FUNC(ID, ...) ID,
     40 #include "intrinsic_func_list.def"
     41     MaxIntrinsicId,
     42 
     43     // Pseudo-intrinsics Id
     44     UnknownId
     45   };
     46 
     47   enum IntrinsicAttribute {
     48     kAttrNone     = 0,
     49 
     50     // Intrinsic that neither modified the memory state nor refer to the global
     51     // state
     52     kAttrReadNone = 1 << 0,
     53 
     54     // Intrinsic that doesn't modify the memory state. Note that one should set
     55     // this flag carefully when the intrinsic may throw exception. Since the
     56     // thread state is implicitly modified when an exception is thrown.
     57     kAttrReadOnly = 1 << 1,
     58 
     59     // Note that intrinsic without kAttrNoThrow and kAttrDoThrow set means that
     60     // intrinsic generates exception in some cases
     61 
     62     // Intrinsic that never generates exception
     63     kAttrNoThrow  = 1 << 2,
     64     // Intrinsic that always generate exception
     65     kAttrDoThrow  = 1 << 3,
     66   };
     67 
     68   enum IntrinsicValType {
     69     kNone,
     70 
     71     kVoidTy,
     72 
     73     kJavaObjectTy,
     74     kJavaMethodTy,
     75     kJavaThreadTy,
     76 
     77     kInt1Ty,
     78     kInt8Ty,
     79     kInt16Ty,
     80     kInt32Ty,
     81     kInt64Ty,
     82     kFloatTy,
     83     kDoubleTy,
     84 
     85     kInt1ConstantTy,
     86     kInt8ConstantTy,
     87     kInt16ConstantTy,
     88     kInt32ConstantTy,
     89     kInt64ConstantTy,
     90     kFloatConstantTy,
     91     kDoubleConstantTy,
     92 
     93     kVarArgTy,
     94   };
     95 
     96   enum {
     97     kIntrinsicMaxArgc = 5
     98   };
     99 
    100   typedef struct IntrinsicInfo {
    101     const char* name_;
    102     unsigned attr_;
    103     IntrinsicValType ret_val_type_;
    104     IntrinsicValType arg_type_[kIntrinsicMaxArgc];
    105   } IntrinsicInfo;
    106 
    107  private:
    108   static const IntrinsicInfo Info[];
    109 
    110  public:
    111   static const IntrinsicInfo& GetInfo(IntrinsicId id) {
    112     DCHECK(id >= 0 && id < MaxIntrinsicId) << "Unknown ART intrinsics ID: "
    113                                            << id;
    114     return Info[id];
    115   }
    116 
    117   static const char* GetName(IntrinsicId id) {
    118     return (id <= MaxIntrinsicId) ? GetInfo(id).name_ : "InvalidIntrinsic";
    119   }
    120 
    121   static unsigned GetAttr(IntrinsicId id) {
    122     return GetInfo(id).attr_;
    123   }
    124 
    125  public:
    126   IntrinsicHelper(::llvm::LLVMContext& context, ::llvm::Module& module);
    127 
    128   ::llvm::Function* GetIntrinsicFunction(IntrinsicId id) {
    129     DCHECK(id >= 0 && id < MaxIntrinsicId) << "Unknown ART intrinsics ID: "
    130                                            << id;
    131     return intrinsic_funcs_[id];
    132   }
    133 
    134   IntrinsicId GetIntrinsicId(const ::llvm::Function* func) const {
    135     ::llvm::DenseMap<const ::llvm::Function*, IntrinsicId>::const_iterator
    136         i = intrinsic_funcs_map_.find(func);
    137     if (i == intrinsic_funcs_map_.end()) {
    138       return UnknownId;
    139     } else {
    140       return i->second;
    141     }
    142   }
    143 
    144  private:
    145   // FIXME: "+1" is to workaround the GCC bugs:
    146   // http://gcc.gnu.org/bugzilla/show_bug.cgi?id=43949
    147   // Remove this when uses newer GCC (> 4.4.3)
    148   ::llvm::Function* intrinsic_funcs_[MaxIntrinsicId + 1];
    149 
    150   // Map a llvm::Function to its intrinsic id
    151   ::llvm::DenseMap<const ::llvm::Function*, IntrinsicId> intrinsic_funcs_map_;
    152 };
    153 
    154 }  // namespace llvm
    155 }  // namespace art
    156 
    157 #endif  // ART_COMPILER_LLVM_INTRINSIC_HELPER_H_
    158