llvm-project/llvm/lib/Frontend/HLSL/HLSLRootSignature.cpp
Finn Plummer dd3d7cfe2e
[HLSL][RootSignature] Define and integrate rootsig clang attr and decl (#137690)
- Defines a new declaration node `HLSLRootSignature` in `DeclNodes.td`
that will consist of a `TrailingObjects` of the in-memory construction
of the root signature, namely an array of `hlsl::rootsig::RootElement`s

- Defines a new clang attr `RootSignature` which simply holds an
identifier to a corresponding root signature declaration as above

- Integrate the `HLSLRootSignatureParser` to construct the decl node in
`ParseMicrosoftAttributes` and then attach the parsed attr with an
identifier to the entry point function declaration.

- Defines the various required declaration methods

- Add testing that the declaration and reference attr are created
correctly, and some syntactical error tests.

It was previously proposed that we could have the root elements
reference be stored directly as an additional member of the attribute
and to not have a separate root signature decl. In contrast, by defining
them separately as this change proposes, we will allow a unique root
signature to have its own declaration in the AST tree. This allows us to
only construct a single root signature for all duplicate root signature
attributes. Having it located directly as a declaration might also prove
advantageous when we consider root signature libraries.

Resolves https://github.com/llvm/llvm-project/issues/119011
2025-05-12 09:59:46 -07:00

166 lines
4.1 KiB
C++

//===- HLSLRootSignature.cpp - HLSL Root Signature helper objects ---------===//
//
// 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
//
//===----------------------------------------------------------------------===//
///
/// \file This file contains helpers for working with HLSL Root Signatures.
///
//===----------------------------------------------------------------------===//
#include "llvm/Frontend/HLSL/HLSLRootSignature.h"
#include "llvm/ADT/bit.h"
namespace llvm {
namespace hlsl {
namespace rootsig {
static raw_ostream &operator<<(raw_ostream &OS, const Register &Reg) {
switch (Reg.ViewType) {
case RegisterType::BReg:
OS << "b";
break;
case RegisterType::TReg:
OS << "t";
break;
case RegisterType::UReg:
OS << "u";
break;
case RegisterType::SReg:
OS << "s";
break;
}
OS << Reg.Number;
return OS;
}
static raw_ostream &operator<<(raw_ostream &OS,
const ShaderVisibility &Visibility) {
switch (Visibility) {
case ShaderVisibility::All:
OS << "All";
break;
case ShaderVisibility::Vertex:
OS << "Vertex";
break;
case ShaderVisibility::Hull:
OS << "Hull";
break;
case ShaderVisibility::Domain:
OS << "Domain";
break;
case ShaderVisibility::Geometry:
OS << "Geometry";
break;
case ShaderVisibility::Pixel:
OS << "Pixel";
break;
case ShaderVisibility::Amplification:
OS << "Amplification";
break;
case ShaderVisibility::Mesh:
OS << "Mesh";
break;
}
return OS;
}
void DescriptorTable::dump(raw_ostream &OS) const {
OS << "DescriptorTable(numClauses = " << NumClauses
<< ", visibility = " << Visibility << ")";
}
static raw_ostream &operator<<(raw_ostream &OS, const ClauseType &Type) {
switch (Type) {
case ClauseType::CBuffer:
OS << "CBV";
break;
case ClauseType::SRV:
OS << "SRV";
break;
case ClauseType::UAV:
OS << "UAV";
break;
case ClauseType::Sampler:
OS << "Sampler";
break;
}
return OS;
}
static raw_ostream &operator<<(raw_ostream &OS,
const DescriptorRangeFlags &Flags) {
bool FlagSet = false;
unsigned Remaining = llvm::to_underlying(Flags);
while (Remaining) {
unsigned Bit = 1u << llvm::countr_zero(Remaining);
if (Remaining & Bit) {
if (FlagSet)
OS << " | ";
switch (static_cast<DescriptorRangeFlags>(Bit)) {
case DescriptorRangeFlags::DescriptorsVolatile:
OS << "DescriptorsVolatile";
break;
case DescriptorRangeFlags::DataVolatile:
OS << "DataVolatile";
break;
case DescriptorRangeFlags::DataStaticWhileSetAtExecute:
OS << "DataStaticWhileSetAtExecute";
break;
case DescriptorRangeFlags::DataStatic:
OS << "DataStatic";
break;
case DescriptorRangeFlags::DescriptorsStaticKeepingBufferBoundsChecks:
OS << "DescriptorsStaticKeepingBufferBoundsChecks";
break;
default:
OS << "invalid: " << Bit;
break;
}
FlagSet = true;
}
Remaining &= ~Bit;
}
if (!FlagSet)
OS << "None";
return OS;
}
void DescriptorTableClause::dump(raw_ostream &OS) const {
OS << Type << "(" << Reg << ", numDescriptors = " << NumDescriptors
<< ", space = " << Space << ", offset = ";
if (Offset == DescriptorTableOffsetAppend)
OS << "DescriptorTableOffsetAppend";
else
OS << Offset;
OS << ", flags = " << Flags << ")";
}
void dumpRootElements(raw_ostream &OS, ArrayRef<RootElement> Elements) {
OS << "RootElements{";
bool First = true;
for (const RootElement &Element : Elements) {
if (!First)
OS << ",";
OS << " ";
First = false;
if (const auto &Clause = std::get_if<DescriptorTableClause>(&Element))
Clause->dump(OS);
if (const auto &Table = std::get_if<DescriptorTable>(&Element))
Table->dump(OS);
}
OS << "}";
}
} // namespace rootsig
} // namespace hlsl
} // namespace llvm