diff --git a/llvm/lib/Target/DirectX/DXIL.td b/llvm/lib/Target/DirectX/DXIL.td index a66f5b6470934..67015cff78a79 100644 --- a/llvm/lib/Target/DirectX/DXIL.td +++ b/llvm/lib/Target/DirectX/DXIL.td @@ -318,7 +318,7 @@ class DXILOp { def Abs : DXILOp<6, unary> { let Doc = "Returns the absolute value of the input."; let LLVMIntrinsic = int_fabs; - let arguments = [LLVMMatchType<0>]; + let arguments = [overloadTy]; let result = overloadTy; let overloads = [Overloads]; let stages = [Stages]; @@ -338,7 +338,7 @@ def IsInf : DXILOp<9, isSpecialFloat> { def Cos : DXILOp<12, unary> { let Doc = "Returns cosine(theta) for theta in radians."; let LLVMIntrinsic = int_cos; - let arguments = [LLVMMatchType<0>]; + let arguments = [overloadTy]; let result = overloadTy; let overloads = [Overloads]; let stages = [Stages]; @@ -348,7 +348,7 @@ def Cos : DXILOp<12, unary> { def Sin : DXILOp<13, unary> { let Doc = "Returns sine(theta) for theta in radians."; let LLVMIntrinsic = int_sin; - let arguments = [LLVMMatchType<0>]; + let arguments = [overloadTy]; let result = overloadTy; let overloads = [Overloads]; let stages = [Stages]; @@ -358,7 +358,7 @@ def Sin : DXILOp<13, unary> { def Tan : DXILOp<14, unary> { let Doc = "Returns tangent(theta) for theta in radians."; let LLVMIntrinsic = int_tan; - let arguments = [LLVMMatchType<0>]; + let arguments = [overloadTy]; let result = overloadTy; let overloads = [Overloads]; let stages = [Stages]; @@ -368,7 +368,7 @@ def Tan : DXILOp<14, unary> { def ACos : DXILOp<15, unary> { let Doc = "Returns the arccosine of the specified value."; let LLVMIntrinsic = int_acos; - let arguments = [LLVMMatchType<0>]; + let arguments = [overloadTy]; let result = overloadTy; let overloads = [Overloads]; let stages = [Stages]; @@ -378,7 +378,7 @@ def ACos : DXILOp<15, unary> { def ASin : DXILOp<16, unary> { let Doc = "Returns the arcsine of the specified value."; let LLVMIntrinsic = int_asin; - let arguments = [LLVMMatchType<0>]; + let arguments = [overloadTy]; let result = overloadTy; let overloads = [Overloads]; let stages = [Stages]; @@ -388,7 +388,7 @@ def ASin : DXILOp<16, unary> { def ATan : DXILOp<17, unary> { let Doc = "Returns the arctangent of the specified value."; let LLVMIntrinsic = int_atan; - let arguments = [LLVMMatchType<0>]; + let arguments = [overloadTy]; let result = overloadTy; let overloads = [Overloads]; let stages = [Stages]; @@ -398,7 +398,7 @@ def ATan : DXILOp<17, unary> { def HCos : DXILOp<18, unary> { let Doc = "Returns the hyperbolic cosine of the specified value."; let LLVMIntrinsic = int_cosh; - let arguments = [LLVMMatchType<0>]; + let arguments = [overloadTy]; let result = overloadTy; let overloads = [Overloads]; let stages = [Stages]; @@ -408,7 +408,7 @@ def HCos : DXILOp<18, unary> { def HSin : DXILOp<19, unary> { let Doc = "Returns the hyperbolic sine of the specified value."; let LLVMIntrinsic = int_sinh; - let arguments = [LLVMMatchType<0>]; + let arguments = [overloadTy]; let result = overloadTy; let overloads = [Overloads]; let stages = [Stages]; @@ -418,7 +418,7 @@ def HSin : DXILOp<19, unary> { def HTan : DXILOp<20, unary> { let Doc = "Returns the hyperbolic tan of the specified value."; let LLVMIntrinsic = int_tanh; - let arguments = [LLVMMatchType<0>]; + let arguments = [overloadTy]; let result = overloadTy; let overloads = [Overloads]; let stages = [Stages]; @@ -429,7 +429,7 @@ def Exp2 : DXILOp<21, unary> { let Doc = "Returns the base 2 exponential, or 2**x, of the specified value. " "exp2(x) = 2**x."; let LLVMIntrinsic = int_exp2; - let arguments = [LLVMMatchType<0>]; + let arguments = [overloadTy]; let result = overloadTy; let overloads = [Overloads]; let stages = [Stages]; @@ -440,7 +440,7 @@ def Frac : DXILOp<22, unary> { let Doc = "Returns a fraction from 0 to 1 that represents the decimal part " "of the input."; let LLVMIntrinsic = int_dx_frac; - let arguments = [LLVMMatchType<0>]; + let arguments = [overloadTy]; let result = overloadTy; let overloads = [Overloads]; let stages = [Stages]; @@ -450,7 +450,7 @@ def Frac : DXILOp<22, unary> { def Log2 : DXILOp<23, unary> { let Doc = "Returns the base-2 logarithm of the specified value."; let LLVMIntrinsic = int_log2; - let arguments = [LLVMMatchType<0>]; + let arguments = [overloadTy]; let result = overloadTy; let overloads = [Overloads]; let stages = [Stages]; @@ -461,7 +461,7 @@ def Sqrt : DXILOp<24, unary> { let Doc = "Returns the square root of the specified floating-point value, " "per component."; let LLVMIntrinsic = int_sqrt; - let arguments = [LLVMMatchType<0>]; + let arguments = [overloadTy]; let result = overloadTy; let overloads = [Overloads]; let stages = [Stages]; @@ -472,7 +472,7 @@ def RSqrt : DXILOp<25, unary> { let Doc = "Returns the reciprocal of the square root of the specified value. " "rsqrt(x) = 1 / sqrt(x)."; let LLVMIntrinsic = int_dx_rsqrt; - let arguments = [LLVMMatchType<0>]; + let arguments = [overloadTy]; let result = overloadTy; let overloads = [Overloads]; let stages = [Stages]; @@ -483,7 +483,7 @@ def Round : DXILOp<26, unary> { let Doc = "Returns the input rounded to the nearest integer within a " "floating-point type."; let LLVMIntrinsic = int_roundeven; - let arguments = [LLVMMatchType<0>]; + let arguments = [overloadTy]; let result = overloadTy; let overloads = [Overloads]; let stages = [Stages]; @@ -494,7 +494,7 @@ def Floor : DXILOp<27, unary> { let Doc = "Returns the largest integer that is less than or equal to the input."; let LLVMIntrinsic = int_floor; - let arguments = [LLVMMatchType<0>]; + let arguments = [overloadTy]; let result = overloadTy; let overloads = [Overloads]; let stages = [Stages]; @@ -505,7 +505,7 @@ def Ceil : DXILOp<28, unary> { let Doc = "Returns the smallest integer that is greater than or equal to the " "input."; let LLVMIntrinsic = int_ceil; - let arguments = [LLVMMatchType<0>]; + let arguments = [overloadTy]; let result = overloadTy; let overloads = [Overloads]; let stages = [Stages]; @@ -515,7 +515,7 @@ def Ceil : DXILOp<28, unary> { def Trunc : DXILOp<29, unary> { let Doc = "Returns the specified value truncated to the integer component."; let LLVMIntrinsic = int_trunc; - let arguments = [LLVMMatchType<0>]; + let arguments = [overloadTy]; let result = overloadTy; let overloads = [Overloads]; let stages = [Stages]; @@ -525,7 +525,7 @@ def Trunc : DXILOp<29, unary> { def Rbits : DXILOp<30, unary> { let Doc = "Returns the specified value with its bits reversed."; let LLVMIntrinsic = int_bitreverse; - let arguments = [LLVMMatchType<0>]; + let arguments = [overloadTy]; let result = overloadTy; let overloads = [Overloads]; @@ -536,7 +536,7 @@ def Rbits : DXILOp<30, unary> { def FMax : DXILOp<35, binary> { let Doc = "Float maximum. FMax(a,b) = a > b ? a : b"; let LLVMIntrinsic = int_maxnum; - let arguments = [LLVMMatchType<0>, LLVMMatchType<0>]; + let arguments = [overloadTy, overloadTy]; let result = overloadTy; let overloads = [Overloads]; @@ -547,7 +547,7 @@ def FMax : DXILOp<35, binary> { def FMin : DXILOp<36, binary> { let Doc = "Float minimum. FMin(a,b) = a < b ? a : b"; let LLVMIntrinsic = int_minnum; - let arguments = [LLVMMatchType<0>, LLVMMatchType<0>]; + let arguments = [overloadTy, overloadTy]; let result = overloadTy; let overloads = [Overloads]; @@ -558,7 +558,7 @@ def FMin : DXILOp<36, binary> { def SMax : DXILOp<37, binary> { let Doc = "Signed integer maximum. SMax(a,b) = a > b ? a : b"; let LLVMIntrinsic = int_smax; - let arguments = [LLVMMatchType<0>, LLVMMatchType<0>]; + let arguments = [overloadTy, overloadTy]; let result = overloadTy; let overloads = [Overloads]; @@ -569,7 +569,7 @@ def SMax : DXILOp<37, binary> { def SMin : DXILOp<38, binary> { let Doc = "Signed integer minimum. SMin(a,b) = a < b ? a : b"; let LLVMIntrinsic = int_smin; - let arguments = [LLVMMatchType<0>, LLVMMatchType<0>]; + let arguments = [overloadTy, overloadTy]; let result = overloadTy; let overloads = [Overloads]; @@ -580,7 +580,7 @@ def SMin : DXILOp<38, binary> { def UMax : DXILOp<39, binary> { let Doc = "Unsigned integer maximum. UMax(a,b) = a > b ? a : b"; let LLVMIntrinsic = int_umax; - let arguments = [LLVMMatchType<0>, LLVMMatchType<0>]; + let arguments = [overloadTy, overloadTy]; let result = overloadTy; let overloads = [Overloads]; @@ -591,7 +591,7 @@ def UMax : DXILOp<39, binary> { def UMin : DXILOp<40, binary> { let Doc = "Unsigned integer minimum. UMin(a,b) = a < b ? a : b"; let LLVMIntrinsic = int_umin; - let arguments = [LLVMMatchType<0>, LLVMMatchType<0>]; + let arguments = [overloadTy, overloadTy]; let result = overloadTy; let overloads = [Overloads]; @@ -603,7 +603,7 @@ def FMad : DXILOp<46, tertiary> { let Doc = "Floating point arithmetic multiply/add operation. fmad(m,a,b) = m " "* a + b."; let LLVMIntrinsic = int_fmuladd; - let arguments = [LLVMMatchType<0>, LLVMMatchType<0>, LLVMMatchType<0>]; + let arguments = [overloadTy, overloadTy, overloadTy]; let result = overloadTy; let overloads = [Overloads]; @@ -615,7 +615,7 @@ def IMad : DXILOp<48, tertiary> { let Doc = "Signed integer arithmetic multiply/add operation. imad(m,a,b) = m " "* a + b."; let LLVMIntrinsic = int_dx_imad; - let arguments = [LLVMMatchType<0>, LLVMMatchType<0>, LLVMMatchType<0>]; + let arguments = [overloadTy, overloadTy, overloadTy]; let result = overloadTy; let overloads = [Overloads]; @@ -627,7 +627,7 @@ def UMad : DXILOp<49, tertiary> { let Doc = "Unsigned integer arithmetic multiply/add operation. umad(m,a, = m " "* a + b."; let LLVMIntrinsic = int_dx_umad; - let arguments = [LLVMMatchType<0>, LLVMMatchType<0>, LLVMMatchType<0>]; + let arguments = [overloadTy, overloadTy, overloadTy]; let result = overloadTy; let overloads = [Overloads]; diff --git a/llvm/lib/Target/DirectX/DXILOpBuilder.cpp b/llvm/lib/Target/DirectX/DXILOpBuilder.cpp index a03701be743c7..42df7c90cb337 100644 --- a/llvm/lib/Target/DirectX/DXILOpBuilder.cpp +++ b/llvm/lib/Target/DirectX/DXILOpBuilder.cpp @@ -208,8 +208,8 @@ static StructType *getHandleType(LLVMContext &Ctx) { Ctx); } -static Type *getTypeFromParameterKind(ParameterKind Kind, Type *OverloadTy) { - auto &Ctx = OverloadTy->getContext(); +static Type *getTypeFromParameterKind(ParameterKind Kind, LLVMContext &Ctx, + Type *OverloadTy) { switch (Kind) { case ParameterKind::Void: return Type::getVoidTy(Ctx); @@ -285,28 +285,26 @@ static ShaderKind getShaderKindEnum(Triple::EnvironmentType EnvType) { /// the following prototype /// OverloadType dx.op..(int opcode, ) /// are constructed from types in Prop. -/// \param Prop Structure containing DXIL Operation properties based on -/// its specification in DXIL.td. -/// \param OverloadTy Return type to be used to construct DXIL function type. static FunctionType *getDXILOpFunctionType(const OpCodeProperty *Prop, - Type *ReturnTy, Type *OverloadTy) { + LLVMContext &Context, + Type *OverloadTy) { SmallVector ArgTys; const ParameterKind *ParamKinds = getOpCodeParameterKind(*Prop); - // Add ReturnTy as return type of the function - ArgTys.emplace_back(ReturnTy); + assert(Prop->NumOfParameters && "No return type?"); + // Add return type of the function + Type *ReturnTy = getTypeFromParameterKind(ParamKinds[0], Context, OverloadTy); // Add DXIL Opcode value type viz., Int32 as first argument - ArgTys.emplace_back(Type::getInt32Ty(OverloadTy->getContext())); + ArgTys.emplace_back(Type::getInt32Ty(Context)); // Add DXIL Operation parameter types as specified in DXIL properties - for (unsigned I = 0; I < Prop->NumOfParameters; ++I) { + for (unsigned I = 1; I < Prop->NumOfParameters; ++I) { ParameterKind Kind = ParamKinds[I]; - ArgTys.emplace_back(getTypeFromParameterKind(Kind, OverloadTy)); + ArgTys.emplace_back(getTypeFromParameterKind(Kind, Context, OverloadTy)); } - return FunctionType::get( - ArgTys[0], ArrayRef(&ArgTys[1], ArgTys.size() - 1), false); + return FunctionType::get(ReturnTy, ArgTys, /*isVarArg=*/false); } /// Get index of the property from PropList valid for the most recent @@ -347,107 +345,91 @@ DXILOpBuilder::DXILOpBuilder(Module &M, IRBuilderBase &B) : M(M), B(B) { } } -CallInst *DXILOpBuilder::createDXILOpCall(dxil::OpCode OpCode, Type *ReturnTy, - Type *OverloadTy, - SmallVector Args) { +static Error makeOpError(dxil::OpCode OpCode, Twine Msg) { + return make_error( + Twine("Cannot create ") + getOpCodeName(OpCode) + " operation: " + Msg, + inconvertibleErrorCode()); +} +Expected DXILOpBuilder::tryCreateOp(dxil::OpCode OpCode, + ArrayRef Args, + Type *RetTy) { const OpCodeProperty *Prop = getOpCodeProperty(OpCode); + + Type *OverloadTy = nullptr; + if (Prop->OverloadParamIndex == 0) { + if (!RetTy) + return makeOpError(OpCode, "Op overloaded on unknown return type"); + OverloadTy = RetTy; + } else if (Prop->OverloadParamIndex > 0) { + // The index counts including the return type + unsigned ArgIndex = Prop->OverloadParamIndex - 1; + if (static_cast(ArgIndex) >= Args.size()) + return makeOpError(OpCode, "Wrong number of arguments"); + OverloadTy = Args[ArgIndex]->getType(); + } + FunctionType *DXILOpFT = + getDXILOpFunctionType(Prop, M.getContext(), OverloadTy); + std::optional OlIndexOrErr = getPropIndex(ArrayRef(Prop->Overloads), DXILVersion); - if (!OlIndexOrErr.has_value()) { - report_fatal_error(Twine(getOpCodeName(OpCode)) + - ": No valid overloads found for DXIL Version - " + - DXILVersion.getAsString(), - /*gen_crash_diag*/ false); - } + if (!OlIndexOrErr.has_value()) + return makeOpError(OpCode, Twine("No valid overloads for DXIL version ") + + DXILVersion.getAsString()); + uint16_t ValidTyMask = Prop->Overloads[*OlIndexOrErr].ValidTys; - OverloadKind Kind = getOverloadKind(OverloadTy); + // If we don't have an overload type, use the function's return type. This is + // a bit of a hack, but it's necessary to get the type suffix on unoverloaded + // DXIL ops correct, like `dx.op.threadId.i32`. + OverloadKind Kind = + getOverloadKind(OverloadTy ? OverloadTy : DXILOpFT->getReturnType()); // Check if the operation supports overload types and OverloadTy is valid // per the specified types for the operation if ((ValidTyMask != OverloadKind::UNDEFINED) && - (ValidTyMask & (uint16_t)Kind) == 0) { - report_fatal_error(Twine("Invalid Overload Type for DXIL operation - ") + - getOpCodeName(OpCode), - /* gen_crash_diag=*/false); - } + (ValidTyMask & (uint16_t)Kind) == 0) + return makeOpError(OpCode, "Invalid overload type"); // Perform necessary checks to ensure Opcode is valid in the targeted shader // kind std::optional StIndexOrErr = getPropIndex(ArrayRef(Prop->Stages), DXILVersion); - if (!StIndexOrErr.has_value()) { - report_fatal_error(Twine(getOpCodeName(OpCode)) + - ": No valid stages found for DXIL Version - " + - DXILVersion.getAsString(), - /*gen_crash_diag*/ false); - } + if (!StIndexOrErr.has_value()) + return makeOpError(OpCode, Twine("No valid stage for DXIL version ") + + DXILVersion.getAsString()); + uint16_t ValidShaderKindMask = Prop->Stages[*StIndexOrErr].ValidStages; // Ensure valid shader stage properties are specified - if (ValidShaderKindMask == ShaderKind::removed) { - report_fatal_error( - Twine(DXILVersion.getAsString()) + - ": Unsupported Target Shader Stage for DXIL operation - " + - getOpCodeName(OpCode), - /*gen_crash_diag*/ false); - } + if (ValidShaderKindMask == ShaderKind::removed) + return makeOpError(OpCode, "Operation has been removed"); // Shader stage need not be validated since getShaderKindEnum() fails // for unknown shader stage. // Verify the target shader stage is valid for the DXIL operation ShaderKind ModuleStagekind = getShaderKindEnum(ShaderStage); - if (!(ValidShaderKindMask & ModuleStagekind)) { - auto ShaderEnvStr = Triple::getEnvironmentTypeName(ShaderStage); - report_fatal_error(Twine(ShaderEnvStr) + - " : Invalid Shader Stage for DXIL operation - " + - getOpCodeName(OpCode) + " for DXIL Version " + - DXILVersion.getAsString(), - /*gen_crash_diag*/ false); - } + if (!(ValidShaderKindMask & ModuleStagekind)) + return makeOpError(OpCode, "Invalid stage"); std::string DXILFnName = constructOverloadName(Kind, OverloadTy, *Prop); - FunctionCallee DXILFn; - // Get the function with name DXILFnName, if one exists - if (auto *Func = M.getFunction(DXILFnName)) { - DXILFn = FunctionCallee(Func); - } else { - // Construct and add a function with name DXILFnName - FunctionType *DXILOpFT = getDXILOpFunctionType(Prop, ReturnTy, OverloadTy); - DXILFn = M.getOrInsertFunction(DXILFnName, DXILOpFT); - } + FunctionCallee DXILFn = M.getOrInsertFunction(DXILFnName, DXILOpFT); - return B.CreateCall(DXILFn, Args); -} - -Type *DXILOpBuilder::getOverloadTy(dxil::OpCode OpCode, FunctionType *FT) { + // We need to inject the opcode as the first argument. + SmallVector OpArgs; + OpArgs.push_back(B.getInt32(llvm::to_underlying(OpCode))); + OpArgs.append(Args.begin(), Args.end()); - const OpCodeProperty *Prop = getOpCodeProperty(OpCode); - // If DXIL Op has no overload parameter, just return the - // precise return type specified. - if (Prop->OverloadParamIndex < 0) { - return FT->getReturnType(); - } - - // Consider FT->getReturnType() as default overload type, unless - // Prop->OverloadParamIndex != 0. - Type *OverloadType = FT->getReturnType(); - if (Prop->OverloadParamIndex != 0) { - // Skip Return Type. - OverloadType = FT->getParamType(Prop->OverloadParamIndex - 1); - } + return B.CreateCall(DXILFn, OpArgs); +} - const ParameterKind *ParamKinds = getOpCodeParameterKind(*Prop); - auto Kind = ParamKinds[Prop->OverloadParamIndex]; - // For ResRet and CBufferRet, OverloadTy is in field of StructType. - if (Kind == ParameterKind::CBufferRet || - Kind == ParameterKind::ResourceRet) { - auto *ST = cast(OverloadType); - OverloadType = ST->getElementType(0); - } - return OverloadType; +CallInst *DXILOpBuilder::createOp(dxil::OpCode OpCode, ArrayRef &Args, + Type *RetTy) { + Expected Result = tryCreateOp(OpCode, Args, RetTy); + if (Error E = Result.takeError()) + llvm_unreachable("Invalid arguments for operation"); + return *Result; } const char *DXILOpBuilder::getOpCodeName(dxil::OpCode DXILOp) { diff --git a/llvm/lib/Target/DirectX/DXILOpBuilder.h b/llvm/lib/Target/DirectX/DXILOpBuilder.h index abb9a8d2b4cf8..ff66f39a3ceb3 100644 --- a/llvm/lib/Target/DirectX/DXILOpBuilder.h +++ b/llvm/lib/Target/DirectX/DXILOpBuilder.h @@ -15,6 +15,7 @@ #include "DXILConstants.h" #include "llvm/ADT/SmallVector.h" #include "llvm/TargetParser/Triple.h" +#include "llvm/Support/Error.h" namespace llvm { class Module; @@ -23,29 +24,44 @@ class CallInst; class Value; class Type; class FunctionType; -class Use; namespace dxil { class DXILOpBuilder { public: DXILOpBuilder(Module &M, IRBuilderBase &B); - /// Create an instruction that calls DXIL Op with return type, specified - /// opcode, and call arguments. - /// - /// \param OpCode Opcode of the DXIL Op call constructed - /// \param SMVer Shader Model Version of DXIL Module being constructed. - /// \param StageKind Shader Stage for DXIL Module being constructed. - /// \param ReturnTy Return type of the DXIL Op call constructed - /// \param OverloadTy Overload type of the DXIL Op call constructed - /// \param Args Arguments for the DXIL Op call constructed - /// \return DXIL Op call constructed - CallInst *createDXILOpCall(dxil::OpCode OpCode, Type *ReturnTy, - Type *OverloadTy, SmallVector Args); - Type *getOverloadTy(dxil::OpCode OpCode, FunctionType *FT); + + /// Create a call instruction for the given DXIL op. The arguments + /// must be valid for an overload of the operation. + CallInst *createOp(dxil::OpCode Op, ArrayRef &Args, + Type *RetTy = nullptr); + +#define DXIL_OPCODE(Op, Name) \ + CallInst *create##Name##Op(ArrayRef &Args, Type *RetTy = nullptr) { \ + return createOp(dxil::OpCode(Op), Args, RetTy); \ + } +#include "DXILOperation.inc" + + /// Try to create a call instruction for the given DXIL op. Fails if the + /// overload is invalid. + Expected tryCreateOp(dxil::OpCode Op, ArrayRef Args, + Type *RetTy = nullptr); +#define DXIL_OPCODE(Op, Name) \ + Expected tryCreate##Name##Op(ArrayRef &Args, \ + Type *RetTy = nullptr) { \ + return tryCreateOp(dxil::OpCode(Op), Args, RetTy); \ + } +#include "DXILOperation.inc" + + /// Return the name of the given opcode. static const char *getOpCodeName(dxil::OpCode DXILOp); private: + /// Gets a specific overload type of the function for the given DXIL op. If + /// the operation is not overloaded, \c OverloadType may be nullptr. + FunctionType *getOpFunctionType(dxil::OpCode OpCode, + Type *OverloadType = nullptr); + Module &M; IRBuilderBase &B; VersionTuple DXILVersion; diff --git a/llvm/lib/Target/DirectX/DXILOpLowering.cpp b/llvm/lib/Target/DirectX/DXILOpLowering.cpp index 0c0edde43a277..5f84cdcfda6de 100644 --- a/llvm/lib/Target/DirectX/DXILOpLowering.cpp +++ b/llvm/lib/Target/DirectX/DXILOpLowering.cpp @@ -16,6 +16,7 @@ #include "DirectX.h" #include "llvm/ADT/SmallVector.h" #include "llvm/CodeGen/Passes.h" +#include "llvm/IR/DiagnosticInfo.h" #include "llvm/IR/IRBuilder.h" #include "llvm/IR/Instruction.h" #include "llvm/IR/Intrinsics.h" @@ -74,16 +75,13 @@ static SmallVector argVectorFlatten(CallInst *Orig, static void lowerIntrinsic(dxil::OpCode DXILOp, Function &F, Module &M) { IRBuilder<> B(M.getContext()); - DXILOpBuilder DXILB(M, B); - Type *OverloadTy = DXILB.getOverloadTy(DXILOp, F.getFunctionType()); + DXILOpBuilder OpBuilder(M, B); for (User *U : make_early_inc_range(F.users())) { CallInst *CI = dyn_cast(U); if (!CI) continue; SmallVector Args; - Value *DXILOpArg = B.getInt32(static_cast(DXILOp)); - Args.emplace_back(DXILOpArg); B.SetInsertPoint(CI); if (isVectorArgExpansion(F)) { SmallVector NewArgs = argVectorFlatten(CI, B); @@ -91,10 +89,18 @@ static void lowerIntrinsic(dxil::OpCode DXILOp, Function &F, Module &M) { } else Args.append(CI->arg_begin(), CI->arg_end()); - CallInst *DXILCI = - DXILB.createDXILOpCall(DXILOp, F.getReturnType(), OverloadTy, Args); + Expected OpCallOrErr = OpBuilder.tryCreateOp(DXILOp, Args, + F.getReturnType()); + if (Error E = OpCallOrErr.takeError()) { + std::string Message(toString(std::move(E))); + DiagnosticInfoUnsupported Diag(*CI->getFunction(), Message, + CI->getDebugLoc()); + M.getContext().diagnose(Diag); + continue; + } + CallInst *OpCall = *OpCallOrErr; - CI->replaceAllUsesWith(DXILCI); + CI->replaceAllUsesWith(OpCall); CI->eraseFromParent(); } if (F.user_empty()) diff --git a/llvm/test/CodeGen/DirectX/acos_error.ll b/llvm/test/CodeGen/DirectX/acos_error.ll index 4125709a57e7a..cba49cd0c7260 100644 --- a/llvm/test/CodeGen/DirectX/acos_error.ll +++ b/llvm/test/CodeGen/DirectX/acos_error.ll @@ -1,7 +1,8 @@ ; RUN: not opt -S -dxil-op-lower -mtriple=dxil-pc-shadermodel6.3-library %s 2>&1 | FileCheck %s ; DXIL operation acos does not support double overload type -; CHECK: LLVM ERROR: Invalid Overload +; CHECK: in function acos_double +; CHECK-SAME: Cannot create ACos operation: Invalid overload type define noundef double @acos_double(double noundef %a) { entry: diff --git a/llvm/test/CodeGen/DirectX/asin_error.ll b/llvm/test/CodeGen/DirectX/asin_error.ll index de63b0d6be027..78408ea7b64c5 100644 --- a/llvm/test/CodeGen/DirectX/asin_error.ll +++ b/llvm/test/CodeGen/DirectX/asin_error.ll @@ -1,7 +1,8 @@ ; RUN: not opt -S -dxil-op-lower -mtriple=dxil-pc-shadermodel6.3-library %s 2>&1 | FileCheck %s ; DXIL operation asin does not support double overload type -; CHECK: LLVM ERROR: Invalid Overload +; CHECK: in function asin_double +; CHECK-SAME: Cannot create ASin operation: Invalid overload type define noundef double @asin_double(double noundef %a) { entry: diff --git a/llvm/test/CodeGen/DirectX/atan_error.ll b/llvm/test/CodeGen/DirectX/atan_error.ll index c320868ef4e57..b51e2eb5af7d8 100644 --- a/llvm/test/CodeGen/DirectX/atan_error.ll +++ b/llvm/test/CodeGen/DirectX/atan_error.ll @@ -1,7 +1,8 @@ ; RUN: not opt -S -dxil-op-lower -mtriple=dxil-pc-shadermodel6.3-library %s 2>&1 | FileCheck %s ; DXIL operation atan does not support double overload type -; CHECK: LLVM ERROR: Invalid Overload +; CHECK: in function atan_double +; CHECK-SAME: Cannot create ATan operation: Invalid overload type define noundef double @atan_double(double noundef %a) { entry: diff --git a/llvm/test/CodeGen/DirectX/ceil_error.ll b/llvm/test/CodeGen/DirectX/ceil_error.ll index da6f083550186..0188b6d8d5c76 100644 --- a/llvm/test/CodeGen/DirectX/ceil_error.ll +++ b/llvm/test/CodeGen/DirectX/ceil_error.ll @@ -1,7 +1,8 @@ ; RUN: not opt -S -dxil-op-lower -mtriple=dxil-pc-shadermodel6.3-library %s 2>&1 | FileCheck %s ; DXIL operation ceil does not support double overload type -; CHECK: LLVM ERROR: Invalid Overload Type +; CHECK: in function ceil_double +; CHECK-SAME: Cannot create Ceil operation: Invalid overload type define noundef double @ceil_double(double noundef %a) { entry: diff --git a/llvm/test/CodeGen/DirectX/cos_error.ll b/llvm/test/CodeGen/DirectX/cos_error.ll index 6bb85a7cec1e3..6e3513490f781 100644 --- a/llvm/test/CodeGen/DirectX/cos_error.ll +++ b/llvm/test/CodeGen/DirectX/cos_error.ll @@ -1,7 +1,8 @@ ; RUN: not opt -S -dxil-op-lower -mtriple=dxil-pc-shadermodel6.3-library %s 2>&1 | FileCheck %s ; DXIL operation cos does not support double overload type -; CHECK: LLVM ERROR: Invalid Overload Type +; CHECK: in function cos_double +; CHECK-SAME: Cannot create Cos operation: Invalid overload type define noundef double @cos_double(double noundef %a) { entry: diff --git a/llvm/test/CodeGen/DirectX/cosh_error.ll b/llvm/test/CodeGen/DirectX/cosh_error.ll index 4c5f0c7146ab5..604e9686043f8 100644 --- a/llvm/test/CodeGen/DirectX/cosh_error.ll +++ b/llvm/test/CodeGen/DirectX/cosh_error.ll @@ -1,7 +1,8 @@ ; RUN: not opt -S -dxil-op-lower -mtriple=dxil-pc-shadermodel6.3-library %s 2>&1 | FileCheck %s ; DXIL operation cosh does not support double overload type -; CHECK: LLVM ERROR: Invalid Overload +; CHECK: in function cosh_double +; CHECK-SAME: Cannot create HCos operation: Invalid overload type define noundef double @cosh_double(double noundef %a) { entry: diff --git a/llvm/test/CodeGen/DirectX/dot2_error.ll b/llvm/test/CodeGen/DirectX/dot2_error.ll index 54780d18e71fb..97b025d36f018 100644 --- a/llvm/test/CodeGen/DirectX/dot2_error.ll +++ b/llvm/test/CodeGen/DirectX/dot2_error.ll @@ -1,7 +1,8 @@ ; RUN: not opt -S -dxil-op-lower -mtriple=dxil-pc-shadermodel6.3-library %s 2>&1 | FileCheck %s ; DXIL operation dot2 does not support double overload type -; CHECK: LLVM ERROR: Invalid Overload +; CHECK: in function dot_double2 +; CHECK-SAME: Cannot create Dot2 operation: Invalid overload type define noundef double @dot_double2(<2 x double> noundef %a, <2 x double> noundef %b) { entry: diff --git a/llvm/test/CodeGen/DirectX/dot3_error.ll b/llvm/test/CodeGen/DirectX/dot3_error.ll index 242716b0b71ba..3b5dc41ebeb6b 100644 --- a/llvm/test/CodeGen/DirectX/dot3_error.ll +++ b/llvm/test/CodeGen/DirectX/dot3_error.ll @@ -1,7 +1,8 @@ ; RUN: not opt -S -dxil-op-lower -mtriple=dxil-pc-shadermodel6.3-library %s 2>&1 | FileCheck %s ; DXIL operation dot3 does not support double overload type -; CHECK: LLVM ERROR: Invalid Overload +; CHECK: in function dot_double3 +; CHECK-SAME: Cannot create Dot3 operation: Invalid overload type define noundef double @dot_double3(<3 x double> noundef %a, <3 x double> noundef %b) { entry: diff --git a/llvm/test/CodeGen/DirectX/dot4_error.ll b/llvm/test/CodeGen/DirectX/dot4_error.ll index 731adda153def..0a5969616220e 100644 --- a/llvm/test/CodeGen/DirectX/dot4_error.ll +++ b/llvm/test/CodeGen/DirectX/dot4_error.ll @@ -1,7 +1,8 @@ ; RUN: not opt -S -dxil-op-lower -mtriple=dxil-pc-shadermodel6.3-library %s 2>&1 | FileCheck %s ; DXIL operation dot4 does not support double overload type -; CHECK: LLVM ERROR: Invalid Overload +; CHECK: in function dot_double4 +; CHECK-SAME: Cannot create Dot4 operation: Invalid overload type define noundef double @dot_double4(<4 x double> noundef %a, <4 x double> noundef %b) { entry: diff --git a/llvm/test/CodeGen/DirectX/exp2_error.ll b/llvm/test/CodeGen/DirectX/exp2_error.ll index 4d13f936eb6be..94e577932fe98 100644 --- a/llvm/test/CodeGen/DirectX/exp2_error.ll +++ b/llvm/test/CodeGen/DirectX/exp2_error.ll @@ -1,7 +1,8 @@ ; RUN: not opt -S -dxil-op-lower -mtriple=dxil-pc-shadermodel6.3-library %s 2>&1 | FileCheck %s ; DXIL operation exp2 does not support double overload type -; CHECK: LLVM ERROR: Invalid Overload +; CHECK: in function exp2_double +; CHECK-SAME: Cannot create Exp2 operation: Invalid overload type define noundef double @exp2_double(double noundef %a) #0 { entry: diff --git a/llvm/test/CodeGen/DirectX/flattened_thread_id_in_group_error.ll b/llvm/test/CodeGen/DirectX/flattened_thread_id_in_group_error.ll index 9abea5e82868f..b5cc913f3f3dd 100644 --- a/llvm/test/CodeGen/DirectX/flattened_thread_id_in_group_error.ll +++ b/llvm/test/CodeGen/DirectX/flattened_thread_id_in_group_error.ll @@ -1,7 +1,8 @@ ; RUN: not opt -S -dxil-op-lower %s 2>&1 | FileCheck %s ; DXIL operation sin is not valid in library stage -; CHECK: LLVM ERROR: library : Invalid Shader Stage for DXIL operation - FlattenedThreadIdInGroup +; CHECK: in function test_flattened_thread_id_in_group +; CHECK-SAME: Cannot create FlattenedThreadIdInGroup operation: Invalid stage target triple = "dxil-pc-shadermodel6.7-library" diff --git a/llvm/test/CodeGen/DirectX/floor_error.ll b/llvm/test/CodeGen/DirectX/floor_error.ll index e3190e5afb63f..7b4646fc5e103 100644 --- a/llvm/test/CodeGen/DirectX/floor_error.ll +++ b/llvm/test/CodeGen/DirectX/floor_error.ll @@ -1,7 +1,8 @@ ; RUN: not opt -S -dxil-op-lower -mtriple=dxil-pc-shadermodel6.3-library %s 2>&1 | FileCheck %s ; DXIL operation floor does not support double overload type -; CHECK: LLVM ERROR: Invalid Overload Type +; CHECK: in function floor_double +; CHECK-SAME: Cannot create Floor operation: Invalid overload type define noundef double @floor_double(double noundef %a) { entry: diff --git a/llvm/test/CodeGen/DirectX/frac_error.ll b/llvm/test/CodeGen/DirectX/frac_error.ll index 1bc3558ab0c9a..4d997516467b5 100644 --- a/llvm/test/CodeGen/DirectX/frac_error.ll +++ b/llvm/test/CodeGen/DirectX/frac_error.ll @@ -1,7 +1,8 @@ ; RUN: not opt -S -dxil-op-lower -mtriple=dxil-pc-shadermodel6.3-library %s 2>&1 | FileCheck %s ; DXIL operation frac does not support double overload type -; CHECK: LLVM ERROR: Invalid Overload Type +; CHECK: in function frac_double +; CHECK-SAME: Cannot create Frac operation: Invalid overload type ; Function Attrs: noinline nounwind optnone define noundef double @frac_double(double noundef %a) #0 { diff --git a/llvm/test/CodeGen/DirectX/group_id_error.ll b/llvm/test/CodeGen/DirectX/group_id_error.ll index 2a6adcf2a9362..e438984eeb805 100644 --- a/llvm/test/CodeGen/DirectX/group_id_error.ll +++ b/llvm/test/CodeGen/DirectX/group_id_error.ll @@ -1,7 +1,8 @@ ; RUN: not opt -S -dxil-op-lower %s 2>&1 | FileCheck %s ; DXIL operation not valid for pixel stage -; CHECK: LLVM ERROR: pixel : Invalid Shader Stage for DXIL operation - GroupId +; CHECK: in function test_group_id +; CHECK-SAME: Cannot create GroupId operation: Invalid stage target triple = "dxil-pc-shadermodel6.7-pixel" diff --git a/llvm/test/CodeGen/DirectX/isinf_error.ll b/llvm/test/CodeGen/DirectX/isinf_error.ll index 39b83554d74d0..1a9fa653109d3 100644 --- a/llvm/test/CodeGen/DirectX/isinf_error.ll +++ b/llvm/test/CodeGen/DirectX/isinf_error.ll @@ -1,7 +1,8 @@ ; RUN: not opt -S -dxil-op-lower -mtriple=dxil-pc-shadermodel6.3-library %s 2>&1 | FileCheck %s ; DXIL operation isinf does not support double overload type -; CHECK: LLVM ERROR: Invalid Overload Type +; CHECK: in function isinf_double +; CHECK-SAME: Cannot create IsInf operation: Invalid overload type define noundef i1 @isinf_double(double noundef %a) #0 { entry: diff --git a/llvm/test/CodeGen/DirectX/log2_error.ll b/llvm/test/CodeGen/DirectX/log2_error.ll index b8876854d389f..fee8514214851 100644 --- a/llvm/test/CodeGen/DirectX/log2_error.ll +++ b/llvm/test/CodeGen/DirectX/log2_error.ll @@ -1,7 +1,8 @@ ; RUN: not opt -S -dxil-op-lower -mtriple=dxil-pc-shadermodel6.3-library %s 2>&1 | FileCheck %s ; DXIL operation log2 does not support double overload type -; CHECK: LLVM ERROR: Invalid Overload Type +; CHECK: in function log2_double +; CHECK-SAME: Cannot create Log2 operation: Invalid overload type define noundef double @log2_double(double noundef %a) { entry: diff --git a/llvm/test/CodeGen/DirectX/round_error.ll b/llvm/test/CodeGen/DirectX/round_error.ll index 9d2a4e778a924..081a5eb9e1f7f 100644 --- a/llvm/test/CodeGen/DirectX/round_error.ll +++ b/llvm/test/CodeGen/DirectX/round_error.ll @@ -1,7 +1,8 @@ ; RUN: not opt -S -dxil-op-lower -mtriple=dxil-pc-shadermodel6.3-library %s 2>&1 | FileCheck %s ; This test is expected to fail with the following error -; CHECK: LLVM ERROR: Invalid Overload Type +; CHECK: in function round_double +; CHECK-SAME: Cannot create Round operation: Invalid overload type define noundef double @round_double(double noundef %a) #0 { entry: diff --git a/llvm/test/CodeGen/DirectX/rsqrt_error.ll b/llvm/test/CodeGen/DirectX/rsqrt_error.ll index 5e29e37113d19..85d452f436533 100644 --- a/llvm/test/CodeGen/DirectX/rsqrt_error.ll +++ b/llvm/test/CodeGen/DirectX/rsqrt_error.ll @@ -1,7 +1,8 @@ ; RUN: not opt -S -dxil-op-lower -mtriple=dxil-pc-shadermodel6.3-library %s 2>&1 | FileCheck %s ; DXIL operation rsqrt does not support double overload type -; CHECK: LLVM ERROR: Invalid Overload Type +; CHECK: in function rsqrt_double +; CHECK-SAME: Cannot create RSqrt operation: Invalid overload type ; Function Attrs: noinline nounwind optnone define noundef double @rsqrt_double(double noundef %a) #0 { diff --git a/llvm/test/CodeGen/DirectX/sin_error.ll b/llvm/test/CodeGen/DirectX/sin_error.ll index 0e20031501365..f1af604309c48 100644 --- a/llvm/test/CodeGen/DirectX/sin_error.ll +++ b/llvm/test/CodeGen/DirectX/sin_error.ll @@ -1,7 +1,8 @@ ; RUN: not opt -S -dxil-op-lower -mtriple=dxil-pc-shadermodel6.0-library %s 2>&1 | FileCheck %s ; DXIL operation sin does not support double overload type -; CHECK: LLVM ERROR: Invalid Overload +; CHECK: in function sin_double +; CHECK-SAME: Cannot create Sin operation: Invalid overload type define noundef double @sin_double(double noundef %a) #0 { entry: @@ -11,4 +12,3 @@ entry: %1 = call double @llvm.sin.f64(double %0) ret double %1 } - diff --git a/llvm/test/CodeGen/DirectX/sinh_error.ll b/llvm/test/CodeGen/DirectX/sinh_error.ll index 06aeca0339261..01b6e2f168572 100644 --- a/llvm/test/CodeGen/DirectX/sinh_error.ll +++ b/llvm/test/CodeGen/DirectX/sinh_error.ll @@ -1,7 +1,8 @@ ; RUN: not opt -S -dxil-op-lower -mtriple=dxil-pc-shadermodel6.3-library %s 2>&1 | FileCheck %s ; DXIL operation sinh does not support double overload type -; CHECK: LLVM ERROR: Invalid Overload +; CHECK: in function sinh_double +; CHECK-SAME: Cannot create HSin operation: Invalid overload type define noundef double @sinh_double(double noundef %a) { entry: diff --git a/llvm/test/CodeGen/DirectX/sqrt_error.ll b/llvm/test/CodeGen/DirectX/sqrt_error.ll index 1477abc62c13a..af1b0d0cc5144 100644 --- a/llvm/test/CodeGen/DirectX/sqrt_error.ll +++ b/llvm/test/CodeGen/DirectX/sqrt_error.ll @@ -1,7 +1,8 @@ ; RUN: not opt -S -dxil-op-lower -mtriple=dxil-pc-shadermodel6.3-library %s 2>&1 | FileCheck %s ; DXIL operation sqrt does not support double overload type -; CHECK: LLVM ERROR: Invalid Overload Type +; CHECK: in function sqrt_double +; CHECK-SAME: Cannot create Sqrt operation: Invalid overload type define noundef double @sqrt_double(double noundef %a) { entry: diff --git a/llvm/test/CodeGen/DirectX/tan_error.ll b/llvm/test/CodeGen/DirectX/tan_error.ll index fa03e531bd672..3a310e8652a89 100644 --- a/llvm/test/CodeGen/DirectX/tan_error.ll +++ b/llvm/test/CodeGen/DirectX/tan_error.ll @@ -1,7 +1,8 @@ ; RUN: not opt -S -dxil-op-lower -mtriple=dxil-pc-shadermodel6.3-library %s 2>&1 | FileCheck %s ; DXIL operation tan does not support double overload type -; CHECK: LLVM ERROR: Invalid Overload +; CHECK: in function tan_double +; CHECK-SAME: Cannot create Tan operation: Invalid overload type define noundef double @tan_double(double noundef %a) #0 { entry: diff --git a/llvm/test/CodeGen/DirectX/tanh_error.ll b/llvm/test/CodeGen/DirectX/tanh_error.ll index 933ffbc87e23f..b72e590aa78a9 100644 --- a/llvm/test/CodeGen/DirectX/tanh_error.ll +++ b/llvm/test/CodeGen/DirectX/tanh_error.ll @@ -1,7 +1,8 @@ ; RUN: not opt -S -dxil-op-lower -mtriple=dxil-pc-shadermodel6.3-library %s 2>&1 | FileCheck %s ; DXIL operation tanh does not support double overload type -; CHECK: LLVM ERROR: Invalid Overload +; CHECK: in function tanh_double +; CHECK-SAME: Cannot create HTan operation: Invalid overload type define noundef double @tanh_double(double noundef %a) { entry: diff --git a/llvm/test/CodeGen/DirectX/thread_id_error.ll b/llvm/test/CodeGen/DirectX/thread_id_error.ll index 6928932328fbe..f973b5a1bf280 100644 --- a/llvm/test/CodeGen/DirectX/thread_id_error.ll +++ b/llvm/test/CodeGen/DirectX/thread_id_error.ll @@ -1,7 +1,8 @@ ; RUN: not opt -S -dxil-op-lower %s 2>&1 | FileCheck %s ; DXIL operation not valid for library stage -; CHECK: LLVM ERROR: library : Invalid Shader Stage for DXIL operation - ThreadId +; CHECK: in function test_thread_id +; CHECK-SAME: Cannot create ThreadId operation: Invalid stage target triple = "dxil-pc-shadermodel6.7-library" diff --git a/llvm/test/CodeGen/DirectX/thread_id_in_group_error.ll b/llvm/test/CodeGen/DirectX/thread_id_in_group_error.ll index 8b63fd7bae543..74a45ac3285d8 100644 --- a/llvm/test/CodeGen/DirectX/thread_id_in_group_error.ll +++ b/llvm/test/CodeGen/DirectX/thread_id_in_group_error.ll @@ -1,7 +1,8 @@ ; RUN: not opt -S -dxil-op-lower %s 2>&1 | FileCheck %s ; DXIL operation sin is not valid in vertex stage -; CHECK: LLVM ERROR: vertex : Invalid Shader Stage for DXIL operation - ThreadIdInGroup +; CHECK: in function test_thread_id_in_group +; CHECK-SAME: Cannot create ThreadIdInGroup operation: Invalid stage target triple = "dxil-pc-shadermodel6.7-vertex" diff --git a/llvm/test/CodeGen/DirectX/trunc_error.ll b/llvm/test/CodeGen/DirectX/trunc_error.ll index ccc7b1df879ee..a4b48e102758b 100644 --- a/llvm/test/CodeGen/DirectX/trunc_error.ll +++ b/llvm/test/CodeGen/DirectX/trunc_error.ll @@ -1,7 +1,8 @@ ; RUN: not opt -S -dxil-op-lower -mtriple=dxil-pc-shadermodel6.3-library %s 2>&1 | FileCheck %s ; DXIL operation trunc does not support double overload type -; CHECK: LLVM ERROR: Invalid Overload Type +; CHECK: in function trunc_double +; CHECK-SAME: Cannot create Trunc operation: Invalid overload type define noundef double @trunc_double(double noundef %a) { entry: diff --git a/llvm/utils/TableGen/DXILEmitter.cpp b/llvm/utils/TableGen/DXILEmitter.cpp index 8e54ead5ac484..53791618e80fe 100644 --- a/llvm/utils/TableGen/DXILEmitter.cpp +++ b/llvm/utils/TableGen/DXILEmitter.cpp @@ -132,49 +132,25 @@ DXILOperationDesc::DXILOperationDesc(const Record *R) { // resolve an LLVMMatchType in accordance with convention outlined in // the comment before the definition of class LLVMMatchType in // llvm/IR/Intrinsics.td - SmallVector OverloadParamIndices; + OverloadParamIndex = -1; // A sigil meaning none. for (unsigned i = 0; i < ParamTypeRecsSize; i++) { auto TR = ParamTypeRecs[i]; // Track operation parameter indices of any overload types auto isAny = TR->getValueAsInt("isAny"); if (isAny == 1) { - // All overload types in a DXIL Op are required to be of the same type. - if (!OverloadParamIndices.empty()) { - [[maybe_unused]] bool knownType = true; - // Ensure that the same overload type registered earlier is being used - for (auto Idx : OverloadParamIndices) { - if (TR != ParamTypeRecs[Idx]) { - knownType = false; - break; - } - } - assert(knownType && "Specification of multiple differing overload " - "parameter types not yet supported"); - } else { - OverloadParamIndices.push_back(i); + if (OverloadParamIndex != -1) { + assert(TR == ParamTypeRecs[OverloadParamIndex] && + "Specification of multiple differing overload parameter types " + "is not supported"); } + // Keep the earliest parameter index we see, but if it was the return type + // overwrite it with the first overloaded argument. + if (OverloadParamIndex <= 0) + OverloadParamIndex = i; } - // Populate OpTypes array according to the type specification - if (TR->isAnonymous()) { - // Check prior overload types exist - assert(!OverloadParamIndices.empty() && - "No prior overloaded parameter found to match."); - // Get the parameter index of anonymous type, TR, references - auto OLParamIndex = TR->getValueAsInt("Number"); - // Resolve and insert the type to that at OLParamIndex - OpTypes.emplace_back(ParamTypeRecs[OLParamIndex]); - } else { - // A non-anonymous type. Just record it in OpTypes - OpTypes.emplace_back(TR); - } - } - - // Set the index of the overload parameter, if any. - OverloadParamIndex = -1; // default; indicating none - if (!OverloadParamIndices.empty()) { - assert(OverloadParamIndices.size() == 1 && - "Multiple overload type specification not supported"); - OverloadParamIndex = OverloadParamIndices[0]; + if (TR->isAnonymous()) + PrintFatalError(TR, "Only concrete types are allowed here"); + OpTypes.emplace_back(TR); } // Get overload records @@ -490,8 +466,7 @@ static void emitDXILOperationTable(std::vector &Ops, ClassSet.insert(Op.OpClass); OpClassStrings.add(Op.OpClass.data()); SmallVector ParamKindVec; - // ParamKindVec is a vector of parameters. Skip return type at index 0 - for (unsigned i = 1; i < Op.OpTypes.size(); i++) { + for (unsigned i = 0; i < Op.OpTypes.size(); i++) { ParamKindVec.emplace_back(getParameterKind(Op.OpTypes[i])); } ParameterMap[Op.OpClass] = ParamKindVec; @@ -511,23 +486,13 @@ static void emitDXILOperationTable(std::vector &Ops, OS << " static const OpCodeProperty OpCodeProps[] = {\n"; std::string Prefix = ""; for (auto &Op : Ops) { - // Consider Op.OverloadParamIndex as the overload parameter index, by - // default - auto OLParamIdx = Op.OverloadParamIndex; - // If no overload parameter index is set, treat first parameter type as - // overload type - unless the Op has no parameters, in which case treat the - // return type - as overload parameter to emit the appropriate overload kind - // enum. - if (OLParamIdx < 0) { - OLParamIdx = (Op.OpTypes.size() > 1) ? 1 : 0; - } OS << Prefix << " { dxil::OpCode::" << Op.OpName << ", " << OpStrings.get(Op.OpName) << ", OpCodeClass::" << Op.OpClass << ", " << OpClassStrings.get(Op.OpClass.data()) << ", " << getOverloadMaskString(Op.OverloadRecs) << ", " << getStageMaskString(Op.StageRecs) << ", " << getAttributeMaskString(Op.AttrRecs) << ", " << Op.OverloadParamIndex - << ", " << Op.OpTypes.size() - 1 << ", " + << ", " << Op.OpTypes.size() << ", " << Parameters.get(ParameterMap[Op.OpClass]) << " }"; Prefix = ",\n"; }