diff --git a/include/llvm/Intrinsics.h b/include/llvm/Intrinsics.h index 37038256033..09a79c2e679 100644 --- a/include/llvm/Intrinsics.h +++ b/include/llvm/Intrinsics.h @@ -74,6 +74,51 @@ namespace Intrinsic { /// Map a GCC builtin name to an intrinsic ID. ID getIntrinsicForGCCBuiltin(const char *Prefix, const char *BuiltinName); + /// IITDescriptor - This is a type descriptor which explains the type + /// requirements of an intrinsic. This is returned by + /// getIntrinsicInfoTableEntries. + struct IITDescriptor { + enum IITDescriptorKind { + Void, MMX, Metadata, Float, Double, + Integer, Vector, Pointer, Struct, + Argument, ExtendVecArgument, TruncVecArgument + } Kind; + + union { + unsigned Integer_Width; + unsigned Float_Width; + unsigned Vector_Width; + unsigned Pointer_AddressSpace; + unsigned Struct_NumElements; + unsigned Argument_Info; + }; + + enum ArgKind { + AK_AnyInteger, + AK_AnyFloat, + AK_AnyVector, + AK_AnyPointer + }; + unsigned getArgumentNumber() const { + assert(Kind == Argument); + return Argument_Info >> 2; + } + ArgKind getArgumentKind() const { + assert(Kind == Argument); + return (ArgKind)(Argument_Info&3); + } + + static IITDescriptor get(IITDescriptorKind K, unsigned Field) { + IITDescriptor Result = { K, { Field } }; + return Result; + } + }; + + /// getIntrinsicInfoTableEntries - Return the IIT table descriptor for the + /// specified intrinsic into an array of IITDescriptors. + /// + void getIntrinsicInfoTableEntries(ID id, SmallVectorImpl &T); + } // End Intrinsic namespace } // End llvm namespace diff --git a/lib/VMCore/Function.cpp b/lib/VMCore/Function.cpp index 32e1a2e7529..2e0b3168c95 100644 --- a/lib/VMCore/Function.cpp +++ b/lib/VMCore/Function.cpp @@ -357,73 +357,151 @@ std::string Intrinsic::getName(ID id, ArrayRef Tys) { return Result; } -#define GET_INTRINSIC_GENERATOR_GLOBAL -#include "llvm/Intrinsics.gen" -#undef GET_INTRINSIC_GENERATOR_GLOBAL -static Type *DecodeFixedType(unsigned &NextElt, ArrayRef Infos, - ArrayRef Tys, LLVMContext &Context) { +/// IIT_Info - These are enumerators that describe the entries returned by the +/// getIntrinsicInfoTableEntries function. +/// +/// NOTE: This must be kept in synch with the copy in TblGen/IntrinsicEmitter! +enum IIT_Info { + // Common values should be encoded with 0-15. + IIT_Done = 0, + IIT_I1 = 1, + IIT_I8 = 2, + IIT_I16 = 3, + IIT_I32 = 4, + IIT_I64 = 5, + IIT_F32 = 6, + IIT_F64 = 7, + IIT_V2 = 8, + IIT_V4 = 9, + IIT_V8 = 10, + IIT_V16 = 11, + IIT_V32 = 12, + IIT_MMX = 13, + IIT_PTR = 14, + IIT_ARG = 15, + + // Values from 16+ are only encodable with the inefficient encoding. + IIT_METADATA = 16, + IIT_EMPTYSTRUCT = 17, + IIT_STRUCT2 = 18, + IIT_STRUCT3 = 19, + IIT_STRUCT4 = 20, + IIT_STRUCT5 = 21, + IIT_EXTEND_VEC_ARG = 22, + IIT_TRUNC_VEC_ARG = 23, + IIT_ANYPTR = 24 +}; + + +static void DecodeIITType(unsigned &NextElt, ArrayRef Infos, + SmallVectorImpl &OutputTable) { IIT_Info Info = IIT_Info(Infos[NextElt++]); unsigned StructElts = 2; + using namespace Intrinsic; switch (Info) { - case IIT_Done: return Type::getVoidTy(Context); - case IIT_I1: return Type::getInt1Ty(Context); - case IIT_I8: return Type::getInt8Ty(Context); - case IIT_I16: return Type::getInt16Ty(Context); - case IIT_I32: return Type::getInt32Ty(Context); - case IIT_I64: return Type::getInt64Ty(Context); - case IIT_F32: return Type::getFloatTy(Context); - case IIT_F64: return Type::getDoubleTy(Context); - case IIT_MMX: return Type::getX86_MMXTy(Context); - case IIT_METADATA: return Type::getMetadataTy(Context); - case IIT_EMPTYSTRUCT: return StructType::get(Context); + case IIT_Done: + OutputTable.push_back(IITDescriptor::get(IITDescriptor::Void, 0)); + return; + case IIT_MMX: + OutputTable.push_back(IITDescriptor::get(IITDescriptor::MMX, 0)); + return; + case IIT_METADATA: + OutputTable.push_back(IITDescriptor::get(IITDescriptor::Metadata, 0)); + return; + case IIT_F32: + OutputTable.push_back(IITDescriptor::get(IITDescriptor::Float, 0)); + return; + case IIT_F64: + OutputTable.push_back(IITDescriptor::get(IITDescriptor::Double, 0)); + return; + case IIT_I1: + OutputTable.push_back(IITDescriptor::get(IITDescriptor::Integer, 1)); + return; + case IIT_I8: + OutputTable.push_back(IITDescriptor::get(IITDescriptor::Integer, 8)); + return; + case IIT_I16: + OutputTable.push_back(IITDescriptor::get(IITDescriptor::Integer,16)); + return; + case IIT_I32: + OutputTable.push_back(IITDescriptor::get(IITDescriptor::Integer, 32)); + return; + case IIT_I64: + OutputTable.push_back(IITDescriptor::get(IITDescriptor::Integer, 64)); + return; case IIT_V2: - return VectorType::get(DecodeFixedType(NextElt, Infos, Tys, Context), 2); + OutputTable.push_back(IITDescriptor::get(IITDescriptor::Vector, 2)); + DecodeIITType(NextElt, Infos, OutputTable); + return; case IIT_V4: - return VectorType::get(DecodeFixedType(NextElt, Infos, Tys, Context), 4); + OutputTable.push_back(IITDescriptor::get(IITDescriptor::Vector, 4)); + DecodeIITType(NextElt, Infos, OutputTable); + return; case IIT_V8: - return VectorType::get(DecodeFixedType(NextElt, Infos, Tys, Context), 8); + OutputTable.push_back(IITDescriptor::get(IITDescriptor::Vector, 8)); + DecodeIITType(NextElt, Infos, OutputTable); + return; case IIT_V16: - return VectorType::get(DecodeFixedType(NextElt, Infos, Tys, Context), 16); + OutputTable.push_back(IITDescriptor::get(IITDescriptor::Vector, 16)); + DecodeIITType(NextElt, Infos, OutputTable); + return; case IIT_V32: - return VectorType::get(DecodeFixedType(NextElt, Infos, Tys, Context), 32); + OutputTable.push_back(IITDescriptor::get(IITDescriptor::Vector, 32)); + DecodeIITType(NextElt, Infos, OutputTable); + return; case IIT_PTR: - return PointerType::getUnqual(DecodeFixedType(NextElt, Infos, Tys,Context)); + OutputTable.push_back(IITDescriptor::get(IITDescriptor::Pointer, 0)); + DecodeIITType(NextElt, Infos, OutputTable); + return; case IIT_ANYPTR: { // [ANYPTR addrspace, subtype] - unsigned AddrSpace = Infos[NextElt++]; - Type *PtrTy = DecodeFixedType(NextElt, Infos, Tys,Context); - return PointerType::get(PtrTy, AddrSpace); + OutputTable.push_back(IITDescriptor::get(IITDescriptor::Pointer, + Infos[NextElt++])); + DecodeIITType(NextElt, Infos, OutputTable); + return; + } + case IIT_ARG: { + unsigned ArgInfo = (NextElt == Infos.size() ? 0 : Infos[NextElt++]); + OutputTable.push_back(IITDescriptor::get(IITDescriptor::Argument, ArgInfo)); + return; + } + case IIT_EXTEND_VEC_ARG: { + unsigned ArgInfo = (NextElt == Infos.size() ? 0 : Infos[NextElt++]); + OutputTable.push_back(IITDescriptor::get(IITDescriptor::ExtendVecArgument, + ArgInfo)); + return; } - case IIT_ARG: - case IIT_EXTEND_VEC_ARG: case IIT_TRUNC_VEC_ARG: { - unsigned ArgNo = (NextElt == Infos.size() ? 0 : Infos[NextElt++]) >> 2; - assert(ArgNo < Tys.size() && "Not enough types specified!"); - Type *T = Tys[ArgNo]; - - if (Info == IIT_EXTEND_VEC_ARG) - T = VectorType::getExtendedElementVectorType(cast(T)); - if (Info == IIT_TRUNC_VEC_ARG) - T = VectorType::getTruncatedElementVectorType(cast(T)); - return T; + unsigned ArgInfo = (NextElt == Infos.size() ? 0 : Infos[NextElt++]); + OutputTable.push_back(IITDescriptor::get(IITDescriptor::TruncVecArgument, + ArgInfo)); + return; } + case IIT_EMPTYSTRUCT: + OutputTable.push_back(IITDescriptor::get(IITDescriptor::Struct, 0)); + return; case IIT_STRUCT5: ++StructElts; // FALL THROUGH. case IIT_STRUCT4: ++StructElts; // FALL THROUGH. case IIT_STRUCT3: ++StructElts; // FALL THROUGH. case IIT_STRUCT2: { - Type *Elts[5]; + OutputTable.push_back(IITDescriptor::get(IITDescriptor::Struct,StructElts)); + for (unsigned i = 0; i != StructElts; ++i) - Elts[i] = DecodeFixedType(NextElt, Infos, Tys, Context); - return StructType::get(Context, ArrayRef(Elts, StructElts)); + DecodeIITType(NextElt, Infos, OutputTable); + return; } } llvm_unreachable("unhandled"); } - -FunctionType *Intrinsic::getType(LLVMContext &Context, - ID id, ArrayRef Tys) { + +#define GET_INTRINSIC_GENERATOR_GLOBAL +#include "llvm/Intrinsics.gen" +#undef GET_INTRINSIC_GENERATOR_GLOBAL + +void Intrinsic::getIntrinsicInfoTableEntries(ID id, + SmallVectorImpl &T){ // Check to see if the intrinsic's type was expressible by the table. unsigned TableVal = IIT_Table[id-1]; @@ -438,6 +516,8 @@ FunctionType *Intrinsic::getType(LLVMContext &Context, // Strip sentinel bit. NextElt = (TableVal << 1) >> 1; } else { + // Decode the TableVal into an array of IITValues. If the entry was encoded + // into a single word in the table itself, decode it now. do { IITValues.push_back(TableVal & 0xF); TableVal >>= 4; @@ -446,12 +526,68 @@ FunctionType *Intrinsic::getType(LLVMContext &Context, IITEntries = IITValues; NextElt = 0; } - - Type *ResultTy = DecodeFixedType(NextElt, IITEntries, Tys, Context); + + // Okay, decode the table into the output vector of IITDescriptors. + DecodeIITType(NextElt, IITEntries, T); + while (NextElt != IITEntries.size() && IITEntries[NextElt] != 0) + DecodeIITType(NextElt, IITEntries, T); +} + + +static Type *DecodeFixedType(ArrayRef &Infos, + ArrayRef Tys, LLVMContext &Context) { + using namespace Intrinsic; + IITDescriptor D = Infos.front(); + Infos = Infos.slice(1); + + switch (D.Kind) { + case IITDescriptor::Void: return Type::getVoidTy(Context); + case IITDescriptor::MMX: return Type::getX86_MMXTy(Context); + case IITDescriptor::Metadata: return Type::getMetadataTy(Context); + case IITDescriptor::Float: return Type::getFloatTy(Context); + case IITDescriptor::Double: return Type::getDoubleTy(Context); + + case IITDescriptor::Integer: + return IntegerType::get(Context, D.Integer_Width); + case IITDescriptor::Vector: + return VectorType::get(DecodeFixedType(Infos, Tys, Context),D.Vector_Width); + case IITDescriptor::Pointer: + return PointerType::get(DecodeFixedType(Infos, Tys, Context), + D.Pointer_AddressSpace); + case IITDescriptor::Struct: { + Type *Elts[5]; + assert(D.Struct_NumElements <= 5 && "Can't handle this yet"); + for (unsigned i = 0, e = D.Struct_NumElements; i != e; ++i) + Elts[i] = DecodeFixedType(Infos, Tys, Context); + return StructType::get(Context, ArrayRef(Elts,D.Struct_NumElements)); + } + + case IITDescriptor::Argument: + return Tys[D.getArgumentNumber()]; + case IITDescriptor::ExtendVecArgument: + return VectorType::getExtendedElementVectorType(cast( + Tys[D.getArgumentNumber()])); + + case IITDescriptor::TruncVecArgument: + return VectorType::getTruncatedElementVectorType(cast( + Tys[D.getArgumentNumber()])); + } + llvm_unreachable("unhandled"); +} + + + +FunctionType *Intrinsic::getType(LLVMContext &Context, + ID id, ArrayRef Tys) { + SmallVector Table; + getIntrinsicInfoTableEntries(id, Table); + + ArrayRef TableRef = Table; + Type *ResultTy = DecodeFixedType(TableRef, Tys, Context); SmallVector ArgTys; - while (NextElt != IITEntries.size() && IITEntries[NextElt] != 0) - ArgTys.push_back(DecodeFixedType(NextElt, IITEntries, Tys, Context)); + while (!TableRef.empty()) + ArgTys.push_back(DecodeFixedType(TableRef, Tys, Context)); return FunctionType::get(ResultTy, ArgTys, false); } diff --git a/utils/TableGen/IntrinsicEmitter.cpp b/utils/TableGen/IntrinsicEmitter.cpp index 6578a5b8be3..9c024a4981a 100644 --- a/utils/TableGen/IntrinsicEmitter.cpp +++ b/utils/TableGen/IntrinsicEmitter.cpp @@ -310,7 +310,7 @@ void IntrinsicEmitter::EmitVerifier(const std::vector &Ints, } -// NOTE: This must be kept in synch with the version emitted to the .gen file! +// NOTE: This must be kept in synch with the copy in lib/VMCore/Function.cpp! enum IIT_Info { // Common values should be encoded with 0-15. IIT_Done = 0, @@ -481,38 +481,6 @@ void printIITEntry(raw_ostream &OS, unsigned char X) { void IntrinsicEmitter::EmitGenerator(const std::vector &Ints, raw_ostream &OS) { - OS << "// Global intrinsic function declaration type table.\n"; - OS << "#ifdef GET_INTRINSIC_GENERATOR_GLOBAL\n"; - // NOTE: These enums must be kept in sync with the ones above! - OS << "enum IIT_Info {\n"; - OS << " IIT_Done = 0,\n"; - OS << " IIT_I1 = 1,\n"; - OS << " IIT_I8 = 2,\n"; - OS << " IIT_I16 = 3,\n"; - OS << " IIT_I32 = 4,\n"; - OS << " IIT_I64 = 5,\n"; - OS << " IIT_F32 = 6,\n"; - OS << " IIT_F64 = 7,\n"; - OS << " IIT_V2 = 8,\n"; - OS << " IIT_V4 = 9,\n"; - OS << " IIT_V8 = 10,\n"; - OS << " IIT_V16 = 11,\n"; - OS << " IIT_V32 = 12,\n"; - OS << " IIT_MMX = 13,\n"; - OS << " IIT_PTR = 14,\n"; - OS << " IIT_ARG = 15,\n"; - OS << " IIT_METADATA = 16,\n"; - OS << " IIT_EMPTYSTRUCT = 17,\n"; - OS << " IIT_STRUCT2 = 18,\n"; - OS << " IIT_STRUCT3 = 19,\n"; - OS << " IIT_STRUCT4 = 20,\n"; - OS << " IIT_STRUCT5 = 21,\n"; - OS << " IIT_EXTEND_VEC_ARG = 22,\n"; - OS << " IIT_TRUNC_VEC_ARG = 23,\n"; - OS << " IIT_ANYPTR = 24\n"; - OS << "};\n\n"; - - // If we can compute a 32-bit fixed encoding for this intrinsic, do so and // capture it in this vector, otherwise store a ~0U. std::vector FixedEncodings; @@ -558,6 +526,9 @@ void IntrinsicEmitter::EmitGenerator(const std::vector &Ints, LongEncodingTable.layout(); + OS << "// Global intrinsic function declaration type table.\n"; + OS << "#ifdef GET_INTRINSIC_GENERATOR_GLOBAL\n"; + OS << "static const unsigned IIT_Table[] = {\n "; for (unsigned i = 0, e = FixedEncodings.size(); i != e; ++i) {