/* * Copyright (C) 2012 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef ART_COMPILER_LLVM_INTRINSIC_HELPER_H_ #define ART_COMPILER_LLVM_INTRINSIC_HELPER_H_ #include "base/logging.h" #include namespace llvm { class Function; class FunctionType; class LLVMContext; class Module; } // namespace llvm namespace art { namespace llvm { class IRBuilder; class IntrinsicHelper { public: enum IntrinsicId { #define DEF_INTRINSICS_FUNC(ID, ...) ID, #include "intrinsic_func_list.def" MaxIntrinsicId, // Pseudo-intrinsics Id UnknownId }; enum IntrinsicAttribute { kAttrNone = 0, // Intrinsic that neither modified the memory state nor refer to the global // state kAttrReadNone = 1 << 0, // Intrinsic that doesn't modify the memory state. Note that one should set // this flag carefully when the intrinsic may throw exception. Since the // thread state is implicitly modified when an exception is thrown. kAttrReadOnly = 1 << 1, // Note that intrinsic without kAttrNoThrow and kAttrDoThrow set means that // intrinsic generates exception in some cases // Intrinsic that never generates exception kAttrNoThrow = 1 << 2, // Intrinsic that always generate exception kAttrDoThrow = 1 << 3, }; enum IntrinsicValType { kNone, kVoidTy, kJavaObjectTy, kJavaMethodTy, kJavaThreadTy, kInt1Ty, kInt8Ty, kInt16Ty, kInt32Ty, kInt64Ty, kFloatTy, kDoubleTy, kInt1ConstantTy, kInt8ConstantTy, kInt16ConstantTy, kInt32ConstantTy, kInt64ConstantTy, kFloatConstantTy, kDoubleConstantTy, kVarArgTy, }; enum { kIntrinsicMaxArgc = 5 }; typedef struct IntrinsicInfo { const char* name_; unsigned attr_; IntrinsicValType ret_val_type_; IntrinsicValType arg_type_[kIntrinsicMaxArgc]; } IntrinsicInfo; private: static const IntrinsicInfo Info[]; public: static const IntrinsicInfo& GetInfo(IntrinsicId id) { DCHECK(id >= 0 && id < MaxIntrinsicId) << "Unknown ART intrinsics ID: " << id; return Info[id]; } static const char* GetName(IntrinsicId id) { return (id <= MaxIntrinsicId) ? GetInfo(id).name_ : "InvalidIntrinsic"; } static unsigned GetAttr(IntrinsicId id) { return GetInfo(id).attr_; } public: IntrinsicHelper(::llvm::LLVMContext& context, ::llvm::Module& module); ::llvm::Function* GetIntrinsicFunction(IntrinsicId id) { DCHECK(id >= 0 && id < MaxIntrinsicId) << "Unknown ART intrinsics ID: " << id; return intrinsic_funcs_[id]; } IntrinsicId GetIntrinsicId(const ::llvm::Function* func) const { ::llvm::DenseMap::const_iterator i = intrinsic_funcs_map_.find(func); if (i == intrinsic_funcs_map_.end()) { return UnknownId; } else { return i->second; } } private: // FIXME: "+1" is to workaround the GCC bugs: // http://gcc.gnu.org/bugzilla/show_bug.cgi?id=43949 // Remove this when uses newer GCC (> 4.4.3) ::llvm::Function* intrinsic_funcs_[MaxIntrinsicId + 1]; // Map a llvm::Function to its intrinsic id ::llvm::DenseMap intrinsic_funcs_map_; }; } // namespace llvm } // namespace art #endif // ART_COMPILER_LLVM_INTRINSIC_HELPER_H_