summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/llvm/IR/Intrinsics.h2
-rw-r--r--lib/IR/Function.cpp7
-rw-r--r--lib/IR/Verifier.cpp42
-rw-r--r--test/TableGen/intrinsic-varargs.td29
-rw-r--r--utils/TableGen/IntrinsicEmitter.cpp5
5 files changed, 81 insertions, 4 deletions
diff --git a/include/llvm/IR/Intrinsics.h b/include/llvm/IR/Intrinsics.h
index c81d110e3b..473e525d9b 100644
--- a/include/llvm/IR/Intrinsics.h
+++ b/include/llvm/IR/Intrinsics.h
@@ -77,7 +77,7 @@ namespace Intrinsic {
/// getIntrinsicInfoTableEntries.
struct IITDescriptor {
enum IITDescriptorKind {
- Void, MMX, Metadata, Half, Float, Double,
+ Void, VarArg, MMX, Metadata, Half, Float, Double,
Integer, Vector, Pointer, Struct,
Argument, ExtendVecArgument, TruncVecArgument
} Kind;
diff --git a/lib/IR/Function.cpp b/lib/IR/Function.cpp
index f4bf774efe..e8a2402b3d 100644
--- a/lib/IR/Function.cpp
+++ b/lib/IR/Function.cpp
@@ -454,7 +454,8 @@ enum IIT_Info {
IIT_EXTEND_VEC_ARG = 23,
IIT_TRUNC_VEC_ARG = 24,
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:
OutputTable.push_back(IITDescriptor::get(IITDescriptor::Void, 0));
return;
+ case IIT_VARARG:
+ OutputTable.push_back(IITDescriptor::get(IITDescriptor::VarArg, 0));
+ return;
case IIT_MMX:
OutputTable.push_back(IITDescriptor::get(IITDescriptor::MMX, 0));
return;
@@ -613,6 +617,7 @@ static Type *DecodeFixedType(ArrayRef<Intrinsic::IITDescriptor> &Infos,
switch (D.Kind) {
case IITDescriptor::Void: return Type::getVoidTy(Context);
+ case IITDescriptor::VarArg: return Type::getVoidTy(Context);
case IITDescriptor::MMX: return Type::getX86_MMXTy(Context);
case IITDescriptor::Metadata: return Type::getMetadataTy(Context);
case IITDescriptor::Half: return Type::getHalfTy(Context);
diff --git a/lib/IR/Verifier.cpp b/lib/IR/Verifier.cpp
index de2b6727d8..4b6d0d2c71 100644
--- a/lib/IR/Verifier.cpp
+++ b/lib/IR/Verifier.cpp
@@ -321,6 +321,8 @@ namespace {
bool VerifyIntrinsicType(Type *Ty,
ArrayRef<Intrinsic::IITDescriptor> &Infos,
SmallVectorImpl<Type*> &ArgTys);
+ bool VerifyIntrinsicIsVarArg(bool isVarArg,
+ ArrayRef<Intrinsic::IITDescriptor> &Infos);
bool VerifyAttributeCount(AttributeSet Attrs, unsigned Params);
void VerifyAttributeTypes(AttributeSet Attrs, unsigned Idx,
bool isFunction, const Value *V);
@@ -2135,6 +2137,7 @@ bool Verifier::VerifyIntrinsicType(Type *Ty,
switch (D.Kind) {
case IITDescriptor::Void: return !Ty->isVoidTy();
+ case IITDescriptor::VarArg: return true;
case IITDescriptor::MMX: return !Ty->isX86_MMXTy();
case IITDescriptor::Metadata: return !Ty->isMetadataTy();
case IITDescriptor::Half: return !Ty->isHalfTy();
@@ -2199,6 +2202,33 @@ bool Verifier::VerifyIntrinsicType(Type *Ty,
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.
///
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
// describe.
FunctionType *IFTy = IF->getFunctionType();
- Assert1(!IFTy->isVarArg(), "Intrinsic prototypes are not varargs", IF);
+ bool IsVarArg = IFTy->isVarArg();
SmallVector<Intrinsic::IITDescriptor, 8> 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)
Assert1(!VerifyIntrinsicType(IFTy->getParamType(i), TableRef, ArgTys),
"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);
// Now that we have the intrinsic ID and the actual argument types (and we
diff --git a/test/TableGen/intrinsic-varargs.td b/test/TableGen/intrinsic-varargs.td
new file mode 100644
index 0000000000..ec1fd35829
--- /dev/null
+++ b/test/TableGen/intrinsic-varargs.td
@@ -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]>;
diff --git a/utils/TableGen/IntrinsicEmitter.cpp b/utils/TableGen/IntrinsicEmitter.cpp
index cd4f0e62d7..6531dcb756 100644
--- a/utils/TableGen/IntrinsicEmitter.cpp
+++ b/utils/TableGen/IntrinsicEmitter.cpp
@@ -261,7 +261,8 @@ enum IIT_Info {
IIT_EXTEND_VEC_ARG = 23,
IIT_TRUNC_VEC_ARG = 24,
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);
// MVT::OtherVT is used to mean the empty struct type here.
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);
}
}