summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/llvm/Intrinsics.h13
-rw-r--r--include/llvm/Intrinsics.td24
-rw-r--r--lib/VMCore/Function.cpp19
-rw-r--r--utils/TableGen/IntrinsicEmitter.cpp71
-rw-r--r--utils/TableGen/IntrinsicEmitter.h2
5 files changed, 122 insertions, 7 deletions
diff --git a/include/llvm/Intrinsics.h b/include/llvm/Intrinsics.h
index e439476914..8275b72676 100644
--- a/include/llvm/Intrinsics.h
+++ b/include/llvm/Intrinsics.h
@@ -18,6 +18,10 @@
namespace llvm {
+class FunctionType;
+class Function;
+class Module;
+
/// Intrinsic Namespace - This namespace contains an enum with a value for
/// every intrinsic/builtin function known by LLVM. These enum values are
/// returned by Function::getIntrinsicID().
@@ -36,6 +40,15 @@ namespace Intrinsic {
/// Intrinsic::getName(ID) - Return the LLVM name for an intrinsic, such as
/// "llvm.ppc.altivec.lvx".
const char *getName(ID id);
+
+ /// Intrinsic::getType(ID) - Return the function type for an intrinsic.
+ ///
+ const FunctionType *getType(ID id);
+
+ /// Intrinsic::getDeclaration(M, ID) - Create or insert an LLVM Function
+ /// declaration for an intrinsic, and return it.
+ Function *getDeclaration(Module *M, ID id);
+
} // End Intrinsic namespace
} // End llvm namespace
diff --git a/include/llvm/Intrinsics.td b/include/llvm/Intrinsics.td
index 126205a5b5..b00eec4663 100644
--- a/include/llvm/Intrinsics.td
+++ b/include/llvm/Intrinsics.td
@@ -68,6 +68,15 @@ class LLVMPackedType<ValueType VT, int numelts, LLVMType elty>
LLVMType ElTy = elty;
}
+class LLVMPointerType<LLVMType elty>
+ : LLVMType<iPTR, "Type::PointerTyID">{
+ LLVMType ElTy = elty;
+}
+
+class LLVMEmptyStructType
+ : LLVMType<OtherVT, "Type::StructTyID">{
+}
+
def llvm_void_ty : LLVMType<isVoid, "Type::VoidTyID">;
def llvm_bool_ty : LLVMIntegerType<i1, 1>;
def llvm_i8_ty : LLVMIntegerType<i8 , 8>;
@@ -76,9 +85,10 @@ def llvm_i32_ty : LLVMIntegerType<i32, 32>;
def llvm_i64_ty : LLVMIntegerType<i64, 64>;
def llvm_float_ty : LLVMType<f32, "Type::FloatTyID">;
def llvm_double_ty : LLVMType<f64, "Type::DoubleTyID">;
-def llvm_ptr_ty : LLVMType<iPTR, "Type::PointerTyID">; // i8*
-def llvm_ptrptr_ty : LLVMType<iPTR, "Type::PointerTyID">; // i8**
-def llvm_descriptor_ty : LLVMType<iPTR, "Type::PointerTyID">; // global*
+def llvm_ptr_ty : LLVMPointerType<llvm_i8_ty>; // i8*
+def llvm_ptrptr_ty : LLVMPointerType<llvm_ptr_ty>; // i8**
+def llvm_empty_ty : LLVMEmptyStructType; // { }
+def llvm_descriptor_ty : LLVMPointerType<llvm_empty_ty>; // { }*
def llvm_v16i8_ty : LLVMPackedType<v16i8,16, llvm_i8_ty>; // 16 x i8
def llvm_v8i16_ty : LLVMPackedType<v8i16, 8, llvm_i16_ty>; // 8 x i16
@@ -123,10 +133,10 @@ class GCCBuiltin<string name> {
//===--------------- Variable Argument Handling Intrinsics ----------------===//
//
-def int_vastart : Intrinsic<[llvm_void_ty, llvm_ptrptr_ty], [], "llvm.va_start">;
-def int_vacopy : Intrinsic<[llvm_void_ty, llvm_ptrptr_ty, llvm_ptrptr_ty], [],
+def int_vastart : Intrinsic<[llvm_void_ty, llvm_ptr_ty], [], "llvm.va_start">;
+def int_vacopy : Intrinsic<[llvm_void_ty, llvm_ptr_ty, llvm_ptr_ty], [],
"llvm.va_copy">;
-def int_vaend : Intrinsic<[llvm_void_ty, llvm_ptrptr_ty], [], "llvm.va_end">;
+def int_vaend : Intrinsic<[llvm_void_ty, llvm_ptr_ty], [], "llvm.va_end">;
//===------------------- Garbage Collection Intrinsics --------------------===//
//
@@ -216,7 +226,7 @@ def int_dbg_stoppoint : Intrinsic<[llvm_void_ty,
def int_dbg_region_start : Intrinsic<[llvm_void_ty, llvm_descriptor_ty]>;
def int_dbg_region_end : Intrinsic<[llvm_void_ty, llvm_descriptor_ty]>;
def int_dbg_func_start : Intrinsic<[llvm_void_ty, llvm_descriptor_ty]>;
-def int_dbg_declare : Intrinsic<[llvm_void_ty, llvm_ptr_ty,
+def int_dbg_declare : Intrinsic<[llvm_void_ty, llvm_descriptor_ty,
llvm_descriptor_ty]>;
//===------------------ Exception Handling Intrinsics----------------------===//
diff --git a/lib/VMCore/Function.cpp b/lib/VMCore/Function.cpp
index cc0cefad66..72237eb440 100644
--- a/lib/VMCore/Function.cpp
+++ b/lib/VMCore/Function.cpp
@@ -183,6 +183,25 @@ const char *Intrinsic::getName(ID id) {
return Table[id];
}
+const FunctionType *Intrinsic::getType(ID id) {
+ const Type *ResultTy = NULL;
+ std::vector<const Type*> ArgTys;
+ std::vector<FunctionType::ParameterAttributes> Attrs;
+ bool IsVarArg = false;
+
+#define GET_INTRINSIC_GENERATOR
+#include "llvm/Intrinsics.gen"
+#undef GET_INTRINSIC_GENERATOR
+
+ return FunctionType::get(ResultTy, ArgTys, IsVarArg, Attrs);
+}
+
+Function *Intrinsic::getDeclaration(Module *M, ID id) {
+// There can never be multiple globals with the same name of different types,
+// because intrinsics must be a specific type.
+ return cast<Function>(M->getOrInsertFunction(getName(id), getType(id)));
+}
+
Value *IntrinsicInst::StripPointerCasts(Value *Ptr) {
if (ConstantExpr *CE = dyn_cast<ConstantExpr>(Ptr)) {
if (CE->getOpcode() == Instruction::BitCast) {
diff --git a/utils/TableGen/IntrinsicEmitter.cpp b/utils/TableGen/IntrinsicEmitter.cpp
index ab527521dc..1a70b257f1 100644
--- a/utils/TableGen/IntrinsicEmitter.cpp
+++ b/utils/TableGen/IntrinsicEmitter.cpp
@@ -38,6 +38,9 @@ void IntrinsicEmitter::run(std::ostream &OS) {
// Emit the intrinsic verifier.
EmitVerifier(Ints, OS);
+ // Emit the intrinsic declaration generator.
+ EmitGenerator(Ints, OS);
+
// Emit mod/ref info for each function.
EmitModRefInfo(Ints, OS);
@@ -125,6 +128,25 @@ static bool EmitTypeVerify(std::ostream &OS, Record *ArgType) {
return false;
}
+static void EmitTypeGenerate(std::ostream &OS, Record *ArgType) {
+ if (ArgType->isSubClassOf("LLVMIntegerType")) {
+ OS << "IntegerType::get(" << ArgType->getValueAsInt("Width") << ")";
+ } else if (ArgType->isSubClassOf("LLVMPackedType")) {
+ OS << "PackedType::get(";
+ EmitTypeGenerate(OS, ArgType->getValueAsDef("ElTy"));
+ OS << ", " << ArgType->getValueAsInt("NumElts") << ")";
+ } else if (ArgType->isSubClassOf("LLVMPointerType")) {
+ OS << "PointerType::get(";
+ EmitTypeGenerate(OS, ArgType->getValueAsDef("ElTy"));
+ OS << ")";
+ } else if (ArgType->isSubClassOf("LLVMEmptyStructType")) {
+ OS << "StructType::get(std::vector<const Type *>())";
+ } else {
+ OS << "Type::getPrimitiveType(";
+ OS << ArgType->getValueAsString("TypeVal") << ")";
+ }
+}
+
/// RecordListComparator - Provide a determinstic comparator for lists of
/// records.
namespace {
@@ -188,6 +210,55 @@ void IntrinsicEmitter::EmitVerifier(const std::vector<CodeGenIntrinsic> &Ints,
OS << "#endif\n\n";
}
+void IntrinsicEmitter::EmitGenerator(const std::vector<CodeGenIntrinsic> &Ints,
+ std::ostream &OS) {
+ OS << "// Code for generating Intrinsic function declarations.\n";
+ OS << "#ifdef GET_INTRINSIC_GENERATOR\n";
+ OS << " switch (id) {\n";
+ OS << " default: assert(0 && \"Invalid intrinsic!\");\n";
+
+ // Similar to GET_INTRINSIC_VERIFIER, batch up cases that have identical
+ // types.
+ typedef std::map<std::vector<Record*>, std::vector<unsigned>,
+ RecordListComparator> MapTy;
+ MapTy UniqueArgInfos;
+
+ // Compute the unique argument type info.
+ for (unsigned i = 0, e = Ints.size(); i != e; ++i)
+ UniqueArgInfos[Ints[i].ArgTypeDefs].push_back(i);
+
+ // Loop through the array, emitting one generator for each batch.
+ for (MapTy::iterator I = UniqueArgInfos.begin(),
+ E = UniqueArgInfos.end(); I != E; ++I) {
+ for (unsigned i = 0, e = I->second.size(); i != e; ++i) {
+ OS << " case Intrinsic::" << Ints[I->second[i]].EnumName << ":\t\t// "
+ << Ints[I->second[i]].Name << "\n";
+ }
+
+ const std::vector<Record*> &ArgTypes = I->first;
+ unsigned N = ArgTypes.size();
+
+ if (ArgTypes[N-1]->getValueAsString("TypeVal") == "...") {
+ OS << " IsVarArg = true;\n";
+ --N;
+ }
+
+ OS << " ResultTy = ";
+ EmitTypeGenerate(OS, ArgTypes[0]);
+ OS << ";\n";
+
+ for (unsigned j = 1; j != N; ++j) {
+ OS << " ArgTys.push_back(";
+ EmitTypeGenerate(OS, ArgTypes[j]);
+ OS << ");\n";
+ }
+
+ OS << " break;\n";
+ }
+ OS << " }\n";
+ OS << "#endif\n\n";
+}
+
void IntrinsicEmitter::EmitModRefInfo(const std::vector<CodeGenIntrinsic> &Ints,
std::ostream &OS) {
OS << "// BasicAliasAnalysis code.\n";
diff --git a/utils/TableGen/IntrinsicEmitter.h b/utils/TableGen/IntrinsicEmitter.h
index ff97b4fe11..fa483ce674 100644
--- a/utils/TableGen/IntrinsicEmitter.h
+++ b/utils/TableGen/IntrinsicEmitter.h
@@ -35,6 +35,8 @@ namespace llvm {
std::ostream &OS);
void EmitVerifier(const std::vector<CodeGenIntrinsic> &Ints,
std::ostream &OS);
+ void EmitGenerator(const std::vector<CodeGenIntrinsic> &Ints,
+ std::ostream &OS);
void EmitModRefInfo(const std::vector<CodeGenIntrinsic> &Ints,
std::ostream &OS);
void EmitNoMemoryInfo(const std::vector<CodeGenIntrinsic> &Ints,