[clang] [HLSL] Implement `SpirvType` and `SpirvOpaqueType` (PR #134034)
Chris B via cfe-commits
cfe-commits at lists.llvm.org
Mon Apr 21 15:27:41 PDT 2025
================
@@ -6330,6 +6331,140 @@ class HLSLAttributedResourceType : public Type, public llvm::FoldingSetNode {
findHandleTypeOnResource(const Type *RT);
};
+/// Instances of this class represent operands to a SPIR-V type instruction.
+class SpirvOperand {
+public:
+ enum SpirvOperandKind : unsigned char {
+ kInvalid, ///< Uninitialized.
+ kConstantId, ///< Integral value to represent as a SPIR-V OpConstant
+ ///< instruction ID.
+ kLiteral, ///< Integral value to represent as an immediate literal.
+ kTypeId, ///< Type to represent as a SPIR-V type ID.
+
+ kMax,
+ };
+
+private:
+ SpirvOperandKind Kind = kInvalid;
+
+ QualType ResultType;
+ llvm::APInt Value; // Signedness of constants is represented by ResultType.
+
+public:
+ SpirvOperand() : Kind(kInvalid), ResultType() {}
+
+ SpirvOperand(SpirvOperandKind Kind, QualType ResultType, llvm::APInt Value)
+ : Kind(Kind), ResultType(ResultType), Value(Value) {}
+
+ SpirvOperand(const SpirvOperand &Other) { *this = Other; }
+ ~SpirvOperand() {}
+
+ SpirvOperand &operator=(const SpirvOperand &Other) {
+ this->Kind = Other.Kind;
+ this->ResultType = Other.ResultType;
+ this->Value = Other.Value;
+ return *this;
+ }
+
+ bool operator==(const SpirvOperand &Other) const {
+ return Kind == Other.Kind && ResultType == Other.ResultType &&
+ Value == Other.Value;
+ }
+
+ bool operator!=(const SpirvOperand &Other) const { return !(*this == Other); }
+
+ SpirvOperandKind getKind() const { return Kind; }
+
+ bool isValid() const { return Kind != kInvalid && Kind < kMax; }
+ bool isConstant() const { return Kind == kConstantId; }
+ bool isLiteral() const { return Kind == kLiteral; }
+ bool isType() const { return Kind == kTypeId; }
+
+ llvm::APInt getValue() const {
+ assert((isConstant() || isLiteral()) &&
+ "This is not an operand with a value!");
+ return Value;
+ }
+
+ QualType getResultType() const {
+ assert((isConstant() || isType()) &&
+ "This is not an operand with a result type!");
+ return ResultType;
+ }
+
+ static SpirvOperand createConstant(QualType ResultType, llvm::APInt Val) {
+ return SpirvOperand(kConstantId, ResultType, Val);
+ }
+
+ static SpirvOperand createLiteral(llvm::APInt Val) {
+ return SpirvOperand(kLiteral, QualType(), Val);
+ }
+
+ static SpirvOperand createType(QualType T) {
+ return SpirvOperand(kTypeId, T, llvm::APSInt());
+ }
+
+ void Profile(llvm::FoldingSetNodeID &ID) const {
+ ID.AddInteger(Kind);
+ ID.AddPointer(ResultType.getAsOpaquePtr());
+ Value.Profile(ID);
+ }
+};
+
+/// Represents an arbitrary, user-specified SPIR-V type instruction.
+class HLSLInlineSpirvType final
+ : public Type,
+ public llvm::FoldingSetNode,
+ private llvm::TrailingObjects<HLSLInlineSpirvType, SpirvOperand> {
+ friend class ASTContext; // ASTContext creates these
+ friend TrailingObjects;
+
+private:
+ uint32_t Opcode;
+ uint32_t Size;
+ uint32_t Alignment;
+ size_t NumOperands;
+
+ HLSLInlineSpirvType(uint32_t Opcode, uint32_t Size, uint32_t Alignment,
+ ArrayRef<SpirvOperand> Operands)
+ : Type(HLSLInlineSpirv, QualType(), TypeDependence::None), Opcode(Opcode),
+ Size(Size), Alignment(Alignment), NumOperands(Operands.size()) {
+ for (size_t I = 0; I < NumOperands; I++) {
+ getTrailingObjects<SpirvOperand>()[I] = Operands[I];
+ }
+ }
+
+public:
+ uint32_t getOpcode() const { return Opcode; }
+ uint32_t getSize() const { return Size; }
+ uint32_t getAlignment() const { return Alignment; }
+ ArrayRef<SpirvOperand> getOperands() const {
+ return {getTrailingObjects<SpirvOperand>(), NumOperands};
+ }
+
+ bool isSugared() const { return false; }
+ QualType desugar() const { return QualType(this, 0); }
+
+ void Profile(llvm::FoldingSetNodeID &ID) {
+ Profile(ID, Opcode, Size, Alignment, getOperands());
+ }
+
+ static void Profile(llvm::FoldingSetNodeID &ID, uint32_t Opcode,
+ uint32_t Size, uint32_t Alignment,
+ ArrayRef<SpirvOperand> Operands) {
+ ID.AddInteger(Opcode);
+ ID.AddInteger(Size);
+ ID.AddInteger(Alignment);
+ for (auto &Operand : Operands) {
+ Operand.Profile(ID);
+ }
----------------
llvm-beanz wrote:
nit: https://llvm.org/docs/CodingStandards.html#don-t-use-braces-on-simple-single-statement-bodies-of-if-else-loop-statements
```suggestion
for (auto &Operand : Operands)
Operand.Profile(ID);
```
https://github.com/llvm/llvm-project/pull/134034
More information about the cfe-commits
mailing list