mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-30 17:33:24 +00:00
Significantly reduce the compiled size of Functions.cpp by turning a big blob of tblgen
generated code (for Intrinsic::getType) into a table. This handles common cases right now, but I plan to extend it to handle all cases and merge in type verification logic as well in follow-on patches. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@156905 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
7200c5cd30
commit
a98aa6ad1e
@ -29,7 +29,6 @@
|
|||||||
#include "llvm/ADT/StringExtras.h"
|
#include "llvm/ADT/StringExtras.h"
|
||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
|
|
||||||
|
|
||||||
// Explicit instantiations of SymbolTableListTraits since some of the methods
|
// Explicit instantiations of SymbolTableListTraits since some of the methods
|
||||||
// are not in the public header file...
|
// are not in the public header file...
|
||||||
template class llvm::SymbolTableListTraits<Argument, Function>;
|
template class llvm::SymbolTableListTraits<Argument, Function>;
|
||||||
@ -358,17 +357,57 @@ std::string Intrinsic::getName(ID id, ArrayRef<Type*> Tys) {
|
|||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define GET_INTRINSTIC_GENERATOR_GLOBAL
|
||||||
|
#include "llvm/Intrinsics.gen"
|
||||||
|
#undef GET_INTRINSTIC_GENERATOR_GLOBAL
|
||||||
|
|
||||||
|
static Type *DecodeFixedType(unsigned &TableVal, LLVMContext &Context) {
|
||||||
|
unsigned Nibble = TableVal & 0xF;
|
||||||
|
TableVal >>= 4;
|
||||||
|
|
||||||
|
switch ((IIT_Info)Nibble) {
|
||||||
|
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_V2: return VectorType::get(DecodeFixedType(TableVal, Context), 2);
|
||||||
|
case IIT_V4: return VectorType::get(DecodeFixedType(TableVal, Context), 4);
|
||||||
|
case IIT_V8: return VectorType::get(DecodeFixedType(TableVal, Context), 8);
|
||||||
|
case IIT_V16: return VectorType::get(DecodeFixedType(TableVal, Context), 16);
|
||||||
|
case IIT_MMX: return Type::getX86_MMXTy(Context);
|
||||||
|
case IIT_PTR: return PointerType::get(DecodeFixedType(TableVal, Context),0);
|
||||||
|
case IIT_ARG: assert(0 && "Unimp!");
|
||||||
|
}
|
||||||
|
llvm_unreachable("unhandled");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
FunctionType *Intrinsic::getType(LLVMContext &Context,
|
FunctionType *Intrinsic::getType(LLVMContext &Context,
|
||||||
ID id, ArrayRef<Type*> Tys) {
|
ID id, ArrayRef<Type*> Tys) {
|
||||||
Type *ResultTy = NULL;
|
Type *ResultTy = 0;
|
||||||
SmallVector<Type*, 8> ArgTys;
|
SmallVector<Type*, 8> ArgTys;
|
||||||
bool IsVarArg = false;
|
|
||||||
|
// Check to see if the intrinsic's type was expressible by the table.
|
||||||
|
unsigned TableVal = IIT_Table[id-1];
|
||||||
|
if (TableVal != ~0U) {
|
||||||
|
ResultTy = DecodeFixedType(TableVal, Context);
|
||||||
|
|
||||||
|
while (TableVal)
|
||||||
|
ArgTys.push_back(DecodeFixedType(TableVal, Context));
|
||||||
|
|
||||||
|
return FunctionType::get(ResultTy, ArgTys, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#define GET_INTRINSIC_GENERATOR
|
#define GET_INTRINSIC_GENERATOR
|
||||||
#include "llvm/Intrinsics.gen"
|
#include "llvm/Intrinsics.gen"
|
||||||
#undef GET_INTRINSIC_GENERATOR
|
#undef GET_INTRINSIC_GENERATOR
|
||||||
|
|
||||||
return FunctionType::get(ResultTy, ArgTys, IsVarArg);
|
return FunctionType::get(ResultTy, ArgTys, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Intrinsic::isOverloaded(ID id) {
|
bool Intrinsic::isOverloaded(ID id) {
|
||||||
@ -440,4 +479,3 @@ bool Function::callsFunctionThatReturnsTwice() const {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// vim: sw=2 ai
|
|
||||||
|
@ -174,109 +174,6 @@ EmitIntrinsicToOverloadTable(const std::vector<CodeGenIntrinsic> &Ints,
|
|||||||
OS << "#endif\n\n";
|
OS << "#endif\n\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
static void EmitTypeForValueType(raw_ostream &OS, MVT::SimpleValueType VT) {
|
|
||||||
if (EVT(VT).isInteger()) {
|
|
||||||
unsigned BitWidth = EVT(VT).getSizeInBits();
|
|
||||||
OS << "IntegerType::get(Context, " << BitWidth << ")";
|
|
||||||
} else if (VT == MVT::Other) {
|
|
||||||
// MVT::OtherVT is used to mean the empty struct type here.
|
|
||||||
OS << "StructType::get(Context)";
|
|
||||||
} else if (VT == MVT::f16) {
|
|
||||||
OS << "Type::getHalfTy(Context)";
|
|
||||||
} else if (VT == MVT::f32) {
|
|
||||||
OS << "Type::getFloatTy(Context)";
|
|
||||||
} else if (VT == MVT::f64) {
|
|
||||||
OS << "Type::getDoubleTy(Context)";
|
|
||||||
} else if (VT == MVT::f80) {
|
|
||||||
OS << "Type::getX86_FP80Ty(Context)";
|
|
||||||
} else if (VT == MVT::f128) {
|
|
||||||
OS << "Type::getFP128Ty(Context)";
|
|
||||||
} else if (VT == MVT::ppcf128) {
|
|
||||||
OS << "Type::getPPC_FP128Ty(Context)";
|
|
||||||
} else if (VT == MVT::isVoid) {
|
|
||||||
OS << "Type::getVoidTy(Context)";
|
|
||||||
} else if (VT == MVT::Metadata) {
|
|
||||||
OS << "Type::getMetadataTy(Context)";
|
|
||||||
} else if (VT == MVT::x86mmx) {
|
|
||||||
OS << "Type::getX86_MMXTy(Context)";
|
|
||||||
} else {
|
|
||||||
assert(false && "Unsupported ValueType!");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void EmitTypeGenerate(raw_ostream &OS, const Record *ArgType,
|
|
||||||
unsigned &ArgNo);
|
|
||||||
|
|
||||||
static void EmitTypeGenerate(raw_ostream &OS,
|
|
||||||
const std::vector<Record*> &ArgTypes,
|
|
||||||
unsigned &ArgNo) {
|
|
||||||
if (ArgTypes.empty())
|
|
||||||
return EmitTypeForValueType(OS, MVT::isVoid);
|
|
||||||
|
|
||||||
if (ArgTypes.size() == 1)
|
|
||||||
return EmitTypeGenerate(OS, ArgTypes.front(), ArgNo);
|
|
||||||
|
|
||||||
OS << "StructType::get(";
|
|
||||||
|
|
||||||
for (std::vector<Record*>::const_iterator
|
|
||||||
I = ArgTypes.begin(), E = ArgTypes.end(); I != E; ++I) {
|
|
||||||
EmitTypeGenerate(OS, *I, ArgNo);
|
|
||||||
OS << ", ";
|
|
||||||
}
|
|
||||||
|
|
||||||
OS << " NULL)";
|
|
||||||
}
|
|
||||||
|
|
||||||
static void EmitTypeGenerate(raw_ostream &OS, const Record *ArgType,
|
|
||||||
unsigned &ArgNo) {
|
|
||||||
MVT::SimpleValueType VT = getValueType(ArgType->getValueAsDef("VT"));
|
|
||||||
|
|
||||||
if (ArgType->isSubClassOf("LLVMMatchType")) {
|
|
||||||
unsigned Number = ArgType->getValueAsInt("Number");
|
|
||||||
assert(Number < ArgNo && "Invalid matching number!");
|
|
||||||
if (ArgType->isSubClassOf("LLVMExtendedElementVectorType"))
|
|
||||||
OS << "VectorType::getExtendedElementVectorType"
|
|
||||||
<< "(cast<VectorType>(Tys[" << Number << "]))";
|
|
||||||
else if (ArgType->isSubClassOf("LLVMTruncatedElementVectorType"))
|
|
||||||
OS << "VectorType::getTruncatedElementVectorType"
|
|
||||||
<< "(cast<VectorType>(Tys[" << Number << "]))";
|
|
||||||
else
|
|
||||||
OS << "Tys[" << Number << "]";
|
|
||||||
} else if (VT == MVT::iAny || VT == MVT::fAny || VT == MVT::vAny) {
|
|
||||||
// NOTE: The ArgNo variable here is not the absolute argument number, it is
|
|
||||||
// the index of the "arbitrary" type in the Tys array passed to the
|
|
||||||
// Intrinsic::getDeclaration function. Consequently, we only want to
|
|
||||||
// increment it when we actually hit an overloaded type. Getting this wrong
|
|
||||||
// leads to very subtle bugs!
|
|
||||||
OS << "Tys[" << ArgNo++ << "]";
|
|
||||||
} else if (EVT(VT).isVector()) {
|
|
||||||
EVT VVT = VT;
|
|
||||||
OS << "VectorType::get(";
|
|
||||||
EmitTypeForValueType(OS, VVT.getVectorElementType().getSimpleVT().SimpleTy);
|
|
||||||
OS << ", " << VVT.getVectorNumElements() << ")";
|
|
||||||
} else if (VT == MVT::iPTR) {
|
|
||||||
OS << "PointerType::getUnqual(";
|
|
||||||
EmitTypeGenerate(OS, ArgType->getValueAsDef("ElTy"), ArgNo);
|
|
||||||
OS << ")";
|
|
||||||
} else if (VT == MVT::iPTRAny) {
|
|
||||||
// Make sure the user has passed us an argument type to overload. If not,
|
|
||||||
// treat it as an ordinary (not overloaded) intrinsic.
|
|
||||||
OS << "(" << ArgNo << " < Tys.size()) ? Tys[" << ArgNo
|
|
||||||
<< "] : PointerType::getUnqual(";
|
|
||||||
EmitTypeGenerate(OS, ArgType->getValueAsDef("ElTy"), ArgNo);
|
|
||||||
OS << ")";
|
|
||||||
++ArgNo;
|
|
||||||
} else if (VT == MVT::isVoid) {
|
|
||||||
if (ArgNo == 0)
|
|
||||||
OS << "Type::getVoidTy(Context)";
|
|
||||||
else
|
|
||||||
// MVT::isVoid is used to mean varargs here.
|
|
||||||
OS << "...";
|
|
||||||
} else {
|
|
||||||
EmitTypeForValueType(OS, VT);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// RecordListComparator - Provide a deterministic comparator for lists of
|
/// RecordListComparator - Provide a deterministic comparator for lists of
|
||||||
/// records.
|
/// records.
|
||||||
namespace {
|
namespace {
|
||||||
@ -411,22 +308,322 @@ void IntrinsicEmitter::EmitVerifier(const std::vector<CodeGenIntrinsic> &Ints,
|
|||||||
OS << "#endif\n\n";
|
OS << "#endif\n\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void EmitTypeForValueType(raw_ostream &OS, MVT::SimpleValueType VT) {
|
||||||
|
if (EVT(VT).isInteger()) {
|
||||||
|
unsigned BitWidth = EVT(VT).getSizeInBits();
|
||||||
|
OS << "IntegerType::get(Context, " << BitWidth << ")";
|
||||||
|
} else if (VT == MVT::Other) {
|
||||||
|
// MVT::OtherVT is used to mean the empty struct type here.
|
||||||
|
OS << "StructType::get(Context)";
|
||||||
|
} else if (VT == MVT::f16) {
|
||||||
|
OS << "Type::getHalfTy(Context)";
|
||||||
|
} else if (VT == MVT::f32) {
|
||||||
|
OS << "Type::getFloatTy(Context)";
|
||||||
|
} else if (VT == MVT::f64) {
|
||||||
|
OS << "Type::getDoubleTy(Context)";
|
||||||
|
} else if (VT == MVT::f80) {
|
||||||
|
OS << "Type::getX86_FP80Ty(Context)";
|
||||||
|
} else if (VT == MVT::f128) {
|
||||||
|
OS << "Type::getFP128Ty(Context)";
|
||||||
|
} else if (VT == MVT::ppcf128) {
|
||||||
|
OS << "Type::getPPC_FP128Ty(Context)";
|
||||||
|
} else if (VT == MVT::isVoid) {
|
||||||
|
OS << "Type::getVoidTy(Context)";
|
||||||
|
} else if (VT == MVT::Metadata) {
|
||||||
|
OS << "Type::getMetadataTy(Context)";
|
||||||
|
} else if (VT == MVT::x86mmx) {
|
||||||
|
OS << "Type::getX86_MMXTy(Context)";
|
||||||
|
} else {
|
||||||
|
assert(false && "Unsupported ValueType!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void EmitTypeGenerate(raw_ostream &OS, const Record *ArgType,
|
||||||
|
unsigned &ArgNo);
|
||||||
|
|
||||||
|
static void EmitTypeGenerate(raw_ostream &OS,
|
||||||
|
const std::vector<Record*> &ArgTypes,
|
||||||
|
unsigned &ArgNo) {
|
||||||
|
if (ArgTypes.empty())
|
||||||
|
return EmitTypeForValueType(OS, MVT::isVoid);
|
||||||
|
|
||||||
|
if (ArgTypes.size() == 1)
|
||||||
|
return EmitTypeGenerate(OS, ArgTypes.front(), ArgNo);
|
||||||
|
|
||||||
|
OS << "StructType::get(";
|
||||||
|
|
||||||
|
for (std::vector<Record*>::const_iterator
|
||||||
|
I = ArgTypes.begin(), E = ArgTypes.end(); I != E; ++I) {
|
||||||
|
EmitTypeGenerate(OS, *I, ArgNo);
|
||||||
|
OS << ", ";
|
||||||
|
}
|
||||||
|
|
||||||
|
OS << " NULL)";
|
||||||
|
}
|
||||||
|
|
||||||
|
static void EmitTypeGenerate(raw_ostream &OS, const Record *ArgType,
|
||||||
|
unsigned &ArgNo) {
|
||||||
|
MVT::SimpleValueType VT = getValueType(ArgType->getValueAsDef("VT"));
|
||||||
|
|
||||||
|
if (ArgType->isSubClassOf("LLVMMatchType")) {
|
||||||
|
unsigned Number = ArgType->getValueAsInt("Number");
|
||||||
|
assert(Number < ArgNo && "Invalid matching number!");
|
||||||
|
if (ArgType->isSubClassOf("LLVMExtendedElementVectorType"))
|
||||||
|
OS << "VectorType::getExtendedElementVectorType"
|
||||||
|
<< "(cast<VectorType>(Tys[" << Number << "]))";
|
||||||
|
else if (ArgType->isSubClassOf("LLVMTruncatedElementVectorType"))
|
||||||
|
OS << "VectorType::getTruncatedElementVectorType"
|
||||||
|
<< "(cast<VectorType>(Tys[" << Number << "]))";
|
||||||
|
else
|
||||||
|
OS << "Tys[" << Number << "]";
|
||||||
|
} else if (VT == MVT::iAny || VT == MVT::fAny || VT == MVT::vAny) {
|
||||||
|
// NOTE: The ArgNo variable here is not the absolute argument number, it is
|
||||||
|
// the index of the "arbitrary" type in the Tys array passed to the
|
||||||
|
// Intrinsic::getDeclaration function. Consequently, we only want to
|
||||||
|
// increment it when we actually hit an overloaded type. Getting this wrong
|
||||||
|
// leads to very subtle bugs!
|
||||||
|
OS << "Tys[" << ArgNo++ << "]";
|
||||||
|
} else if (EVT(VT).isVector()) {
|
||||||
|
EVT VVT = VT;
|
||||||
|
OS << "VectorType::get(";
|
||||||
|
EmitTypeForValueType(OS, VVT.getVectorElementType().getSimpleVT().SimpleTy);
|
||||||
|
OS << ", " << VVT.getVectorNumElements() << ")";
|
||||||
|
} else if (VT == MVT::iPTR) {
|
||||||
|
OS << "PointerType::getUnqual(";
|
||||||
|
EmitTypeGenerate(OS, ArgType->getValueAsDef("ElTy"), ArgNo);
|
||||||
|
OS << ")";
|
||||||
|
} else if (VT == MVT::iPTRAny) {
|
||||||
|
// Make sure the user has passed us an argument type to overload. If not,
|
||||||
|
// treat it as an ordinary (not overloaded) intrinsic.
|
||||||
|
OS << "(" << ArgNo << " < Tys.size()) ? Tys[" << ArgNo
|
||||||
|
<< "] : PointerType::getUnqual(";
|
||||||
|
EmitTypeGenerate(OS, ArgType->getValueAsDef("ElTy"), ArgNo);
|
||||||
|
OS << ")";
|
||||||
|
++ArgNo;
|
||||||
|
} else if (VT == MVT::isVoid) {
|
||||||
|
assert(ArgNo == 0);
|
||||||
|
OS << "Type::getVoidTy(Context)";
|
||||||
|
} else {
|
||||||
|
EmitTypeForValueType(OS, VT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// NOTE: This must be kept in synch with the version emitted to the .gen file!
|
||||||
|
enum IIT_Info {
|
||||||
|
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_MMX = 12,
|
||||||
|
IIT_PTR = 13,
|
||||||
|
IIT_ARG = 14
|
||||||
|
};
|
||||||
|
|
||||||
|
static void EncodeFixedValueType(MVT::SimpleValueType VT,
|
||||||
|
SmallVectorImpl<unsigned> &Sig) {
|
||||||
|
if (EVT(VT).isInteger()) {
|
||||||
|
unsigned BitWidth = EVT(VT).getSizeInBits();
|
||||||
|
switch (BitWidth) {
|
||||||
|
default: return Sig.push_back(~0U);
|
||||||
|
case 1: return Sig.push_back(IIT_I1);
|
||||||
|
case 8: return Sig.push_back(IIT_I8);
|
||||||
|
case 16: return Sig.push_back(IIT_I16);
|
||||||
|
case 32: return Sig.push_back(IIT_I32);
|
||||||
|
case 64: return Sig.push_back(IIT_I64);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* } else if (VT == MVT::Other) {
|
||||||
|
// MVT::OtherVT is used to mean the empty struct type here.
|
||||||
|
OS << "StructType::get(Context)";
|
||||||
|
} else if (VT == MVT::f16) {
|
||||||
|
OS << "Type::getHalfTy(Context)";*/
|
||||||
|
if (VT == MVT::f32)
|
||||||
|
return Sig.push_back(IIT_F32);
|
||||||
|
if (VT == MVT::f64)
|
||||||
|
return Sig.push_back(IIT_F64);
|
||||||
|
//if (VT == MVT::f80) {
|
||||||
|
// OS << "Type::getX86_FP80Ty(Context)";
|
||||||
|
//if (VT == MVT::f128) {
|
||||||
|
// OS << "Type::getFP128Ty(Context)";
|
||||||
|
// if (VT == MVT::ppcf128) {
|
||||||
|
// OS << "Type::getPPC_FP128Ty(Context)";
|
||||||
|
//if (VT == MVT::Metadata) {
|
||||||
|
// OS << "Type::getMetadataTy(Context)";
|
||||||
|
if (VT == MVT::x86mmx)
|
||||||
|
return Sig.push_back(IIT_MMX);
|
||||||
|
|
||||||
|
assert(VT != MVT::isVoid);
|
||||||
|
Sig.push_back(~0U);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void EncodeFixedType(Record *R, SmallVectorImpl<unsigned> &Sig) {
|
||||||
|
|
||||||
|
if (R->isSubClassOf("LLVMMatchType")) {
|
||||||
|
return Sig.push_back(~0U);
|
||||||
|
/*
|
||||||
|
unsigned Number = ArgType->getValueAsInt("Number");
|
||||||
|
assert(Number < ArgNo && "Invalid matching number!");
|
||||||
|
if (ArgType->isSubClassOf("LLVMExtendedElementVectorType"))
|
||||||
|
OS << "VectorType::getExtendedElementVectorType"
|
||||||
|
<< "(cast<VectorType>(Tys[" << Number << "]))";
|
||||||
|
else if (ArgType->isSubClassOf("LLVMTruncatedElementVectorType"))
|
||||||
|
OS << "VectorType::getTruncatedElementVectorType"
|
||||||
|
<< "(cast<VectorType>(Tys[" << Number << "]))";
|
||||||
|
else
|
||||||
|
OS << "Tys[" << Number << "]";
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
MVT::SimpleValueType VT = getValueType(R->getValueAsDef("VT"));
|
||||||
|
|
||||||
|
if (VT == MVT::iAny || VT == MVT::fAny || VT == MVT::vAny) {
|
||||||
|
return Sig.push_back(~0U);
|
||||||
|
/*
|
||||||
|
// NOTE: The ArgNo variable here is not the absolute argument number, it is
|
||||||
|
// the index of the "arbitrary" type in the Tys array passed to the
|
||||||
|
// Intrinsic::getDeclaration function. Consequently, we only want to
|
||||||
|
// increment it when we actually hit an overloaded type. Getting this wrong
|
||||||
|
// leads to very subtle bugs!
|
||||||
|
OS << "Tys[" << ArgNo++ << "]";
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
if (EVT(VT).isVector()) {
|
||||||
|
EVT VVT = VT;
|
||||||
|
switch (VVT.getVectorNumElements()) {
|
||||||
|
default: Sig.push_back(~0U); return;
|
||||||
|
case 2: Sig.push_back(IIT_V2); break;
|
||||||
|
case 4: Sig.push_back(IIT_V4); break;
|
||||||
|
case 8: Sig.push_back(IIT_V8); break;
|
||||||
|
case 16: Sig.push_back(IIT_V16); break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return EncodeFixedValueType(VVT.getVectorElementType().
|
||||||
|
getSimpleVT().SimpleTy, Sig);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (VT == MVT::iPTR) {
|
||||||
|
Sig.push_back(IIT_PTR);
|
||||||
|
return EncodeFixedType(R->getValueAsDef("ElTy"), Sig);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*if (VT == MVT::iPTRAny) {
|
||||||
|
// Make sure the user has passed us an argument type to overload. If not,
|
||||||
|
// treat it as an ordinary (not overloaded) intrinsic.
|
||||||
|
OS << "(" << ArgNo << " < Tys.size()) ? Tys[" << ArgNo
|
||||||
|
<< "] : PointerType::getUnqual(";
|
||||||
|
EmitTypeGenerate(OS, ArgType->getValueAsDef("ElTy"), ArgNo);
|
||||||
|
OS << ")";
|
||||||
|
++ArgNo;
|
||||||
|
}*/
|
||||||
|
|
||||||
|
assert(VT != MVT::isVoid);
|
||||||
|
EncodeFixedValueType(VT, Sig);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// ComputeFixedEncoding - If we can encode the type signature for this
|
||||||
|
/// intrinsic into 32 bits, return it. If not, return ~0U.
|
||||||
|
static unsigned ComputeFixedEncoding(const CodeGenIntrinsic &Int) {
|
||||||
|
if (Int.IS.RetVTs.size() >= 2) return ~0U;
|
||||||
|
|
||||||
|
SmallVector<unsigned, 8> TypeSig;
|
||||||
|
if (Int.IS.RetVTs.empty())
|
||||||
|
TypeSig.push_back(IIT_Done);
|
||||||
|
else if (Int.IS.RetVTs.size() == 1 &&
|
||||||
|
Int.IS.RetVTs[0] == MVT::isVoid)
|
||||||
|
TypeSig.push_back(IIT_Done);
|
||||||
|
else
|
||||||
|
EncodeFixedType(Int.IS.RetTypeDefs[0], TypeSig);
|
||||||
|
|
||||||
|
for (unsigned i = 0, e = Int.IS.ParamTypeDefs.size(); i != e; ++i)
|
||||||
|
EncodeFixedType(Int.IS.ParamTypeDefs[i], TypeSig);
|
||||||
|
|
||||||
|
// Can only encode 8 nibbles into a 32-bit word.
|
||||||
|
if (TypeSig.size() > 8) return ~0U;
|
||||||
|
|
||||||
|
unsigned Result = 0;
|
||||||
|
for (unsigned i = 0, e = TypeSig.size(); i != e; ++i) {
|
||||||
|
// If we had an unencodable argument, bail out.
|
||||||
|
if (TypeSig[i] == ~0U)
|
||||||
|
return ~0U;
|
||||||
|
Result = (Result << 4) | TypeSig[e-i-1];
|
||||||
|
}
|
||||||
|
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
void IntrinsicEmitter::EmitGenerator(const std::vector<CodeGenIntrinsic> &Ints,
|
void IntrinsicEmitter::EmitGenerator(const std::vector<CodeGenIntrinsic> &Ints,
|
||||||
raw_ostream &OS) {
|
raw_ostream &OS) {
|
||||||
OS << "// Code for generating Intrinsic function declarations.\n";
|
OS << "// Global intrinsic function declaration type table.\n";
|
||||||
OS << "#ifdef GET_INTRINSIC_GENERATOR\n";
|
OS << "#ifdef GET_INTRINSTIC_GENERATOR_GLOBAL\n";
|
||||||
OS << " switch (id) {\n";
|
// NOTE: These enums must be kept in sync with the ones above!
|
||||||
OS << " default: llvm_unreachable(\"Invalid intrinsic!\");\n";
|
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_MMX = 12,\n";
|
||||||
|
OS << " IIT_PTR = 13,\n";
|
||||||
|
OS << " IIT_ARG = 14\n";
|
||||||
|
// 15 is unassigned so far.
|
||||||
|
OS << "};\n\n";
|
||||||
|
|
||||||
|
|
||||||
// Similar to GET_INTRINSIC_VERIFIER, batch up cases that have identical
|
// Similar to GET_INTRINSIC_VERIFIER, batch up cases that have identical
|
||||||
// types.
|
// types.
|
||||||
typedef std::map<RecPair, std::vector<unsigned>, RecordListComparator> MapTy;
|
typedef std::map<RecPair, std::vector<unsigned>, RecordListComparator> MapTy;
|
||||||
MapTy UniqueArgInfos;
|
MapTy UniqueArgInfos;
|
||||||
|
|
||||||
|
// 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<unsigned> FixedEncodings;
|
||||||
|
|
||||||
// Compute the unique argument type info.
|
// Compute the unique argument type info.
|
||||||
for (unsigned i = 0, e = Ints.size(); i != e; ++i)
|
for (unsigned i = 0, e = Ints.size(); i != e; ++i) {
|
||||||
UniqueArgInfos[make_pair(Ints[i].IS.RetTypeDefs,
|
FixedEncodings.push_back(ComputeFixedEncoding(Ints[i]));
|
||||||
Ints[i].IS.ParamTypeDefs)].push_back(i);
|
|
||||||
|
// If we didn't compute a compact encoding, emit a long-form variant.
|
||||||
|
if (FixedEncodings.back() == ~0U)
|
||||||
|
UniqueArgInfos[make_pair(Ints[i].IS.RetTypeDefs,
|
||||||
|
Ints[i].IS.ParamTypeDefs)].push_back(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
OS << "static const unsigned IIT_Table[] = {\n ";
|
||||||
|
|
||||||
|
for (unsigned i = 0, e = FixedEncodings.size(); i != e; ++i) {
|
||||||
|
if ((i & 7) == 7)
|
||||||
|
OS << "\n ";
|
||||||
|
if (FixedEncodings[i] == ~0U)
|
||||||
|
OS << "~0U, ";
|
||||||
|
else
|
||||||
|
OS << "0x" << utohexstr(FixedEncodings[i]) << ", ";
|
||||||
|
}
|
||||||
|
|
||||||
|
OS << "0\n};\n\n#endif\n\n"; // End of GET_INTRINSTIC_GENERATOR_GLOBAL
|
||||||
|
|
||||||
|
OS << "// Code for generating Intrinsic function declarations.\n";
|
||||||
|
OS << "#ifdef GET_INTRINSIC_GENERATOR\n";
|
||||||
|
OS << " switch (id) {\n";
|
||||||
|
OS << " default: llvm_unreachable(\"Invalid intrinsic!\");\n";
|
||||||
|
|
||||||
// Loop through the array, emitting one generator for each batch.
|
// Loop through the array, emitting one generator for each batch.
|
||||||
std::string IntrinsicStr = TargetPrefix + "Intrinsic::";
|
std::string IntrinsicStr = TargetPrefix + "Intrinsic::";
|
||||||
@ -442,13 +639,6 @@ void IntrinsicEmitter::EmitGenerator(const std::vector<CodeGenIntrinsic> &Ints,
|
|||||||
const std::vector<Record*> &ParamTys = ArgTypes.second;
|
const std::vector<Record*> &ParamTys = ArgTypes.second;
|
||||||
|
|
||||||
unsigned N = ParamTys.size();
|
unsigned N = ParamTys.size();
|
||||||
|
|
||||||
if (N > 1 &&
|
|
||||||
getValueType(ParamTys[N - 1]->getValueAsDef("VT")) == MVT::isVoid) {
|
|
||||||
OS << " IsVarArg = true;\n";
|
|
||||||
--N;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned ArgNo = 0;
|
unsigned ArgNo = 0;
|
||||||
OS << " ResultTy = ";
|
OS << " ResultTy = ";
|
||||||
EmitTypeGenerate(OS, RetTys, ArgNo);
|
EmitTypeGenerate(OS, RetTys, ArgNo);
|
||||||
|
Loading…
Reference in New Issue
Block a user