diff options
author | Andrew Trick <atrick@apple.com> | 2013-10-31 17:18:11 +0000 |
---|---|---|
committer | Andrew Trick <atrick@apple.com> | 2013-10-31 17:18:11 +0000 |
commit | 2e50b8a08d40ce72ae35c73528140d3ee25209e0 (patch) | |
tree | e15491d43320ca7a059db16deb2931bbaa63822a | |
parent | cf940ceff73f567876f1a1f62d3acbf67c43ea90 (diff) | |
download | external_llvm-2e50b8a08d40ce72ae35c73528140d3ee25209e0.zip external_llvm-2e50b8a08d40ce72ae35c73528140d3ee25209e0.tar.gz external_llvm-2e50b8a08d40ce72ae35c73528140d3ee25209e0.tar.bz2 |
Enable variable arguments support for intrinsics.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@193766 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | include/llvm/IR/Intrinsics.h | 2 | ||||
-rw-r--r-- | lib/IR/Function.cpp | 7 | ||||
-rw-r--r-- | lib/IR/Verifier.cpp | 42 | ||||
-rw-r--r-- | test/TableGen/intrinsic-varargs.td | 29 | ||||
-rw-r--r-- | utils/TableGen/IntrinsicEmitter.cpp | 5 |
5 files changed, 81 insertions, 4 deletions
diff --git a/include/llvm/IR/Intrinsics.h b/include/llvm/IR/Intrinsics.h index c81d110..473e525 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 f4bf774..e8a2402 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 de2b672..4b6d0d2 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 0000000..ec1fd35 --- /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 cd4f0e6..6531dcb 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); } } |