mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-06-23 01:24:30 +00:00
Enable variable arguments support for intrinsics.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@193766 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@ -77,7 +77,7 @@ namespace Intrinsic {
|
|||||||
/// getIntrinsicInfoTableEntries.
|
/// getIntrinsicInfoTableEntries.
|
||||||
struct IITDescriptor {
|
struct IITDescriptor {
|
||||||
enum IITDescriptorKind {
|
enum IITDescriptorKind {
|
||||||
Void, MMX, Metadata, Half, Float, Double,
|
Void, VarArg, MMX, Metadata, Half, Float, Double,
|
||||||
Integer, Vector, Pointer, Struct,
|
Integer, Vector, Pointer, Struct,
|
||||||
Argument, ExtendVecArgument, TruncVecArgument
|
Argument, ExtendVecArgument, TruncVecArgument
|
||||||
} Kind;
|
} Kind;
|
||||||
|
@ -454,7 +454,8 @@ enum IIT_Info {
|
|||||||
IIT_EXTEND_VEC_ARG = 23,
|
IIT_EXTEND_VEC_ARG = 23,
|
||||||
IIT_TRUNC_VEC_ARG = 24,
|
IIT_TRUNC_VEC_ARG = 24,
|
||||||
IIT_ANYPTR = 25,
|
IIT_ANYPTR = 25,
|
||||||
IIT_V1 = 26
|
IIT_V1 = 26,
|
||||||
|
IIT_VARARG = 27
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -468,6 +469,9 @@ static void DecodeIITType(unsigned &NextElt, ArrayRef<unsigned char> Infos,
|
|||||||
case IIT_Done:
|
case IIT_Done:
|
||||||
OutputTable.push_back(IITDescriptor::get(IITDescriptor::Void, 0));
|
OutputTable.push_back(IITDescriptor::get(IITDescriptor::Void, 0));
|
||||||
return;
|
return;
|
||||||
|
case IIT_VARARG:
|
||||||
|
OutputTable.push_back(IITDescriptor::get(IITDescriptor::VarArg, 0));
|
||||||
|
return;
|
||||||
case IIT_MMX:
|
case IIT_MMX:
|
||||||
OutputTable.push_back(IITDescriptor::get(IITDescriptor::MMX, 0));
|
OutputTable.push_back(IITDescriptor::get(IITDescriptor::MMX, 0));
|
||||||
return;
|
return;
|
||||||
@ -613,6 +617,7 @@ static Type *DecodeFixedType(ArrayRef<Intrinsic::IITDescriptor> &Infos,
|
|||||||
|
|
||||||
switch (D.Kind) {
|
switch (D.Kind) {
|
||||||
case IITDescriptor::Void: return Type::getVoidTy(Context);
|
case IITDescriptor::Void: return Type::getVoidTy(Context);
|
||||||
|
case IITDescriptor::VarArg: return Type::getVoidTy(Context);
|
||||||
case IITDescriptor::MMX: return Type::getX86_MMXTy(Context);
|
case IITDescriptor::MMX: return Type::getX86_MMXTy(Context);
|
||||||
case IITDescriptor::Metadata: return Type::getMetadataTy(Context);
|
case IITDescriptor::Metadata: return Type::getMetadataTy(Context);
|
||||||
case IITDescriptor::Half: return Type::getHalfTy(Context);
|
case IITDescriptor::Half: return Type::getHalfTy(Context);
|
||||||
|
@ -321,6 +321,8 @@ namespace {
|
|||||||
bool VerifyIntrinsicType(Type *Ty,
|
bool VerifyIntrinsicType(Type *Ty,
|
||||||
ArrayRef<Intrinsic::IITDescriptor> &Infos,
|
ArrayRef<Intrinsic::IITDescriptor> &Infos,
|
||||||
SmallVectorImpl<Type*> &ArgTys);
|
SmallVectorImpl<Type*> &ArgTys);
|
||||||
|
bool VerifyIntrinsicIsVarArg(bool isVarArg,
|
||||||
|
ArrayRef<Intrinsic::IITDescriptor> &Infos);
|
||||||
bool VerifyAttributeCount(AttributeSet Attrs, unsigned Params);
|
bool VerifyAttributeCount(AttributeSet Attrs, unsigned Params);
|
||||||
void VerifyAttributeTypes(AttributeSet Attrs, unsigned Idx,
|
void VerifyAttributeTypes(AttributeSet Attrs, unsigned Idx,
|
||||||
bool isFunction, const Value *V);
|
bool isFunction, const Value *V);
|
||||||
@ -2135,6 +2137,7 @@ bool Verifier::VerifyIntrinsicType(Type *Ty,
|
|||||||
|
|
||||||
switch (D.Kind) {
|
switch (D.Kind) {
|
||||||
case IITDescriptor::Void: return !Ty->isVoidTy();
|
case IITDescriptor::Void: return !Ty->isVoidTy();
|
||||||
|
case IITDescriptor::VarArg: return true;
|
||||||
case IITDescriptor::MMX: return !Ty->isX86_MMXTy();
|
case IITDescriptor::MMX: return !Ty->isX86_MMXTy();
|
||||||
case IITDescriptor::Metadata: return !Ty->isMetadataTy();
|
case IITDescriptor::Metadata: return !Ty->isMetadataTy();
|
||||||
case IITDescriptor::Half: return !Ty->isHalfTy();
|
case IITDescriptor::Half: return !Ty->isHalfTy();
|
||||||
@ -2199,6 +2202,33 @@ bool Verifier::VerifyIntrinsicType(Type *Ty,
|
|||||||
llvm_unreachable("unhandled");
|
llvm_unreachable("unhandled");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// \brief Verify if the intrinsic has variable arguments.
|
||||||
|
/// This method is intended to be called after all the fixed arguments have been
|
||||||
|
/// verified first.
|
||||||
|
///
|
||||||
|
/// This method returns true on error and does not print an error message.
|
||||||
|
bool
|
||||||
|
Verifier::VerifyIntrinsicIsVarArg(bool isVarArg,
|
||||||
|
ArrayRef<Intrinsic::IITDescriptor> &Infos) {
|
||||||
|
using namespace Intrinsic;
|
||||||
|
|
||||||
|
// If there are no descriptors left, then it can't be a vararg.
|
||||||
|
if (Infos.empty())
|
||||||
|
return isVarArg ? true : false;
|
||||||
|
|
||||||
|
// There should be only one descriptor remaining at this point.
|
||||||
|
if (Infos.size() != 1)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// Check and verify the descriptor.
|
||||||
|
IITDescriptor D = Infos.front();
|
||||||
|
Infos = Infos.slice(1);
|
||||||
|
if (D.Kind == IITDescriptor::VarArg)
|
||||||
|
return isVarArg ? false : true;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/// visitIntrinsicFunction - Allow intrinsics to be verified in different ways.
|
/// visitIntrinsicFunction - Allow intrinsics to be verified in different ways.
|
||||||
///
|
///
|
||||||
void Verifier::visitIntrinsicFunctionCall(Intrinsic::ID ID, CallInst &CI) {
|
void Verifier::visitIntrinsicFunctionCall(Intrinsic::ID ID, CallInst &CI) {
|
||||||
@ -2209,7 +2239,7 @@ void Verifier::visitIntrinsicFunctionCall(Intrinsic::ID ID, CallInst &CI) {
|
|||||||
// Verify that the intrinsic prototype lines up with what the .td files
|
// Verify that the intrinsic prototype lines up with what the .td files
|
||||||
// describe.
|
// describe.
|
||||||
FunctionType *IFTy = IF->getFunctionType();
|
FunctionType *IFTy = IF->getFunctionType();
|
||||||
Assert1(!IFTy->isVarArg(), "Intrinsic prototypes are not varargs", IF);
|
bool IsVarArg = IFTy->isVarArg();
|
||||||
|
|
||||||
SmallVector<Intrinsic::IITDescriptor, 8> Table;
|
SmallVector<Intrinsic::IITDescriptor, 8> Table;
|
||||||
getIntrinsicInfoTableEntries(ID, Table);
|
getIntrinsicInfoTableEntries(ID, Table);
|
||||||
@ -2221,6 +2251,16 @@ void Verifier::visitIntrinsicFunctionCall(Intrinsic::ID ID, CallInst &CI) {
|
|||||||
for (unsigned i = 0, e = IFTy->getNumParams(); i != e; ++i)
|
for (unsigned i = 0, e = IFTy->getNumParams(); i != e; ++i)
|
||||||
Assert1(!VerifyIntrinsicType(IFTy->getParamType(i), TableRef, ArgTys),
|
Assert1(!VerifyIntrinsicType(IFTy->getParamType(i), TableRef, ArgTys),
|
||||||
"Intrinsic has incorrect argument type!", IF);
|
"Intrinsic has incorrect argument type!", IF);
|
||||||
|
|
||||||
|
// Verify if the intrinsic call matches the vararg property.
|
||||||
|
if (IsVarArg)
|
||||||
|
Assert1(!VerifyIntrinsicIsVarArg(IsVarArg, TableRef),
|
||||||
|
"Intrinsic was not defined with variable arguments!", IF);
|
||||||
|
else
|
||||||
|
Assert1(!VerifyIntrinsicIsVarArg(IsVarArg, TableRef),
|
||||||
|
"Callsite was not defined with variable arguments!", IF);
|
||||||
|
|
||||||
|
// All descriptors should be absorbed by now.
|
||||||
Assert1(TableRef.empty(), "Intrinsic has too few arguments!", IF);
|
Assert1(TableRef.empty(), "Intrinsic has too few arguments!", IF);
|
||||||
|
|
||||||
// Now that we have the intrinsic ID and the actual argument types (and we
|
// Now that we have the intrinsic ID and the actual argument types (and we
|
||||||
|
29
test/TableGen/intrinsic-varargs.td
Normal file
29
test/TableGen/intrinsic-varargs.td
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
// RUN: llvm-tblgen -gen-intrinsic %s | FileCheck %s
|
||||||
|
|
||||||
|
class IntrinsicProperty;
|
||||||
|
|
||||||
|
class ValueType<int size, int value> {
|
||||||
|
string Namespace = "MVT";
|
||||||
|
int Size = size;
|
||||||
|
int Value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
class LLVMType<ValueType vt> {
|
||||||
|
ValueType VT = vt;
|
||||||
|
}
|
||||||
|
|
||||||
|
class Intrinsic<string name, list<LLVMType> param_types = []> {
|
||||||
|
string LLVMName = name;
|
||||||
|
bit isTarget = 0;
|
||||||
|
string TargetPrefix = "";
|
||||||
|
list<LLVMType> RetTypes = [];
|
||||||
|
list<LLVMType> ParamTypes = param_types;
|
||||||
|
list<IntrinsicProperty> Properties = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
// isVoid needs to match the definition in ValueTypes.td
|
||||||
|
def isVoid : ValueType<0, 56>; // Produces no value
|
||||||
|
def llvm_vararg_ty : LLVMType<isVoid>; // this means vararg here
|
||||||
|
|
||||||
|
// CHECK: /* 0 */ 0, 27, 0,
|
||||||
|
def int_foo : Intrinsic<"llvm.foo", [llvm_vararg_ty]>;
|
@ -261,7 +261,8 @@ enum IIT_Info {
|
|||||||
IIT_EXTEND_VEC_ARG = 23,
|
IIT_EXTEND_VEC_ARG = 23,
|
||||||
IIT_TRUNC_VEC_ARG = 24,
|
IIT_TRUNC_VEC_ARG = 24,
|
||||||
IIT_ANYPTR = 25,
|
IIT_ANYPTR = 25,
|
||||||
IIT_V1 = 26
|
IIT_V1 = 26,
|
||||||
|
IIT_VARARG = 27
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -288,6 +289,8 @@ static void EncodeFixedValueType(MVT::SimpleValueType VT,
|
|||||||
case MVT::x86mmx: return Sig.push_back(IIT_MMX);
|
case MVT::x86mmx: return Sig.push_back(IIT_MMX);
|
||||||
// MVT::OtherVT is used to mean the empty struct type here.
|
// MVT::OtherVT is used to mean the empty struct type here.
|
||||||
case MVT::Other: return Sig.push_back(IIT_EMPTYSTRUCT);
|
case MVT::Other: return Sig.push_back(IIT_EMPTYSTRUCT);
|
||||||
|
// MVT::isVoid is used to represent varargs here.
|
||||||
|
case MVT::isVoid: return Sig.push_back(IIT_VARARG);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user