blob: 657db402fadca39270711147427dbfb5d2ea32c8 [file] [log] [blame]
/*
* 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 <llvm/ADT/DenseMap.h>
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 ::llvm::Function*, IntrinsicId>::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<const ::llvm::Function*, IntrinsicId> intrinsic_funcs_map_;
};
} // namespace llvm
} // namespace art
#endif // ART_COMPILER_LLVM_INTRINSIC_HELPER_H_