================ @@ -0,0 +1,586 @@ +//===--- HLSLEmitter.cpp - HLSL intrinsic header generator ----------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This tablegen backend generates hlsl_alias_intrinsics_gen.inc (alias +// overloads) and hlsl_inline_intrinsics_gen.inc (inline/detail overloads) for +// HLSL intrinsic functions. +// +//===----------------------------------------------------------------------===// + +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/StringSwitch.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/TableGen/Record.h" + +using namespace llvm; + +namespace { + +/// Minimum shader model version that supports 16-bit types. +constexpr StringLiteral SM6_2 = "6.2"; + +//===----------------------------------------------------------------------===// +// Type name helpers +//===----------------------------------------------------------------------===// + +static std::string getVectorTypeName(StringRef ElemType, unsigned N) { + return (ElemType + Twine(N)).str(); +} + +static std::string getMatrixTypeName(StringRef ElemType, unsigned Rows, + unsigned Cols) { + return (ElemType + Twine(Rows) + "x" + Twine(Cols)).str(); +} + +/// Get the fixed type name string for a VectorType or HLSLType record. +static std::string getFixedTypeName(const Record *R) { + if (R->isSubClassOf("VectorType")) + return getVectorTypeName( + R->getValueAsDef("ElementType")->getValueAsString("Name"), + R->getValueAsInt("Size")); + assert(R->isSubClassOf("HLSLType")); + return R->getValueAsString("Name").str(); +} + +/// For a VectorType, return its ElementType record; for an HLSLType, return +/// the record itself (it is already a scalar element type). +static const Record *getElementTypeRecord(const Record *R) { + if (R->isSubClassOf("VectorType")) + return R->getValueAsDef("ElementType"); + assert(R->isSubClassOf("HLSLType")); + return R; +} + +//===----------------------------------------------------------------------===// +// Type information +//===----------------------------------------------------------------------===// + +/// Classifies how a type varies across overloads. +enum TypeKindEnum { + TK_Varying = 0, ///< Type matches the full varying type (e.g. float3). + TK_ElemType = 1, ///< Type is the scalar element type (e.g. float). + TK_VaryingShape = 2, ///< Type uses the varying shape with a fixed element. + TK_FixedType = 3, ///< Type is a fixed concrete type (e.g. "half2"). + TK_Void = 4 ///< Type is void (only valid for return types). +}; + +/// Metadata describing how a type (argument or return) varies across overloads. +struct TypeInfo { + /// Classification of how this type varies across overloads. + TypeKindEnum Kind = TK_Varying; + + /// Fixed type name (e.g. "half2") for types with a concrete type that does + /// not vary across overloads. Empty for varying types. + std::string FixedType; + + /// Element type name for TK_VaryingShape types (e.g. "bool" for + /// VaryingShape<BoolTy>). Empty for other type kinds. + StringRef ShapeElemType; + + /// Explicit parameter name (e.g. "eta"). Empty to use the default "p0", + /// "p1", ... naming. Only meaningful for argument types. + StringRef Name; + + /// Construct a TypeInfo from a TableGen record. + static TypeInfo resolve(const Record *Rec) { + TypeInfo TI; + if (Rec->getName() == "VoidTy") { + TI.Kind = TK_Void; + } else if (Rec->getName() == "Varying") { + TI.Kind = TK_Varying; + } else if (Rec->getName() == "VaryingElemType") { + TI.Kind = TK_ElemType; + } else if (Rec->isSubClassOf("VaryingShape")) { + TI.Kind = TK_VaryingShape; + TI.ShapeElemType = + Rec->getValueAsDef("ElementType")->getValueAsString("Name"); + } else if (Rec->isSubClassOf("VectorType") || + Rec->isSubClassOf("HLSLType")) { + TI.Kind = TK_FixedType; + TI.FixedType = getFixedTypeName(Rec); + } else { + llvm_unreachable("unhandled record for type resolution"); + } + return TI; + } + + /// Resolve this type to a concrete type name string. + /// \p ElemType is the scalar element type for the current overload. + /// \p FormatVarying formats a scalar element type into the shaped type name. + std::string + toTypeString(StringRef ElemType, + function_ref<std::string(StringRef)> FormatVarying) const { + switch (Kind) { + case TK_Void: + return "void"; + case TK_Varying: + return FormatVarying(ElemType); + case TK_ElemType: + return ElemType.str(); + case TK_VaryingShape: + return FormatVarying(ShapeElemType); + case TK_FixedType: + assert(!FixedType.empty() && "TK_FixedType requires non-empty FixedType"); + return FixedType; + } + llvm_unreachable("unhandled TypeKindEnum"); + } +}; + +//===----------------------------------------------------------------------===// +// Availability helpers +//===----------------------------------------------------------------------===// + +static void emitAvailability(raw_ostream &OS, StringRef Version, + bool Use16Bit = false) { + if (Use16Bit) { + OS << "_HLSL_16BIT_AVAILABILITY(shadermodel, " << Version << ")\n"; + } else { + OS << "_HLSL_AVAILABILITY(shadermodel, " << Version << ")\n"; + } +} +static std::string getVersionString(const Record *SM) { ---------------- jurahul wrote:
nit: can you add an empty line between functions? https://github.com/llvm/llvm-project/pull/187610 _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
