aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/CodeGen/CGHLSLRuntime.cpp
diff options
context:
space:
mode:
authorNathan Gauër <brioche@google.com>2025-09-09 15:31:26 +0200
committerGitHub <noreply@github.com>2025-09-09 13:31:26 +0000
commit57e1846c96f0c858f687fe9c66f4e3793b52f497 (patch)
treeae7e9cd8d12cbfda83b257dd72ec05090f23fe8d /clang/lib/CodeGen/CGHLSLRuntime.cpp
parent80c2da6372b5b4104cf09411c9fa8cb64df0a8a2 (diff)
downloadllvm-57e1846c96f0c858f687fe9c66f4e3793b52f497.zip
llvm-57e1846c96f0c858f687fe9c66f4e3793b52f497.tar.gz
llvm-57e1846c96f0c858f687fe9c66f4e3793b52f497.tar.bz2
[HLSL] Rewrite semantics parsing (#152537)
This is the first PR to implement the semantics proposal: https://github.com/llvm/wg-hlsl/blob/main/proposals/0031-semantics.md This PR focuses on the changes required to handle user semantics, but tried to be almost NFC. What changes is the error messages as the semantics case is not kept when reporting error messages. You might notice the SV_GroupIndex semantic is not properly validated as are others. This is an existing behavior that we'll need to fix, but wanted to keep this separated from this rewrite to stay as-close as an NFC as possible. The next PR will add support on the different kinds of I/O we can have using semantics (input, inout param, structs).
Diffstat (limited to 'clang/lib/CodeGen/CGHLSLRuntime.cpp')
-rw-r--r--clang/lib/CodeGen/CGHLSLRuntime.cpp72
1 files changed, 53 insertions, 19 deletions
diff --git a/clang/lib/CodeGen/CGHLSLRuntime.cpp b/clang/lib/CodeGen/CGHLSLRuntime.cpp
index d27f378..60ad3eb 100644
--- a/clang/lib/CodeGen/CGHLSLRuntime.cpp
+++ b/clang/lib/CodeGen/CGHLSLRuntime.cpp
@@ -23,6 +23,7 @@
#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/AST/Type.h"
#include "clang/Basic/TargetOptions.h"
+#include "clang/Frontend/FrontendDiagnostic.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Frontend/HLSL/RootSignatureMetadata.h"
@@ -552,47 +553,78 @@ static llvm::Value *createSPIRVBuiltinLoad(IRBuilder<> &B, llvm::Module &M,
return B.CreateLoad(Ty, GV);
}
-llvm::Value *CGHLSLRuntime::emitInputSemantic(IRBuilder<> &B,
- const ParmVarDecl &D,
- llvm::Type *Ty) {
- assert(D.hasAttrs() && "Entry parameter missing annotation attribute!");
- if (D.hasAttr<HLSLSV_GroupIndexAttr>()) {
+llvm::Value *
+CGHLSLRuntime::emitSystemSemanticLoad(IRBuilder<> &B, llvm::Type *Type,
+ const clang::DeclaratorDecl *Decl,
+ SemanticInfo &ActiveSemantic) {
+ if (isa<HLSLSV_GroupIndexAttr>(ActiveSemantic.Semantic)) {
llvm::Function *GroupIndex =
CGM.getIntrinsic(getFlattenedThreadIdInGroupIntrinsic());
return B.CreateCall(FunctionCallee(GroupIndex));
}
- if (D.hasAttr<HLSLSV_DispatchThreadIDAttr>()) {
+
+ if (isa<HLSLSV_DispatchThreadIDAttr>(ActiveSemantic.Semantic)) {
llvm::Intrinsic::ID IntrinID = getThreadIdIntrinsic();
llvm::Function *ThreadIDIntrinsic =
llvm::Intrinsic::isOverloaded(IntrinID)
? CGM.getIntrinsic(IntrinID, {CGM.Int32Ty})
: CGM.getIntrinsic(IntrinID);
- return buildVectorInput(B, ThreadIDIntrinsic, Ty);
+ return buildVectorInput(B, ThreadIDIntrinsic, Type);
}
- if (D.hasAttr<HLSLSV_GroupThreadIDAttr>()) {
+
+ if (isa<HLSLSV_GroupThreadIDAttr>(ActiveSemantic.Semantic)) {
llvm::Intrinsic::ID IntrinID = getGroupThreadIdIntrinsic();
llvm::Function *GroupThreadIDIntrinsic =
llvm::Intrinsic::isOverloaded(IntrinID)
? CGM.getIntrinsic(IntrinID, {CGM.Int32Ty})
: CGM.getIntrinsic(IntrinID);
- return buildVectorInput(B, GroupThreadIDIntrinsic, Ty);
+ return buildVectorInput(B, GroupThreadIDIntrinsic, Type);
}
- if (D.hasAttr<HLSLSV_GroupIDAttr>()) {
+
+ if (isa<HLSLSV_GroupIDAttr>(ActiveSemantic.Semantic)) {
llvm::Intrinsic::ID IntrinID = getGroupIdIntrinsic();
llvm::Function *GroupIDIntrinsic =
llvm::Intrinsic::isOverloaded(IntrinID)
? CGM.getIntrinsic(IntrinID, {CGM.Int32Ty})
: CGM.getIntrinsic(IntrinID);
- return buildVectorInput(B, GroupIDIntrinsic, Ty);
+ return buildVectorInput(B, GroupIDIntrinsic, Type);
}
- if (D.hasAttr<HLSLSV_PositionAttr>()) {
- if (getArch() == llvm::Triple::spirv)
- return createSPIRVBuiltinLoad(B, CGM.getModule(), Ty, "sv_position",
- /* BuiltIn::Position */ 0);
- llvm_unreachable("SV_Position semantic not implemented for this target.");
+
+ if (HLSLSV_PositionAttr *S =
+ dyn_cast<HLSLSV_PositionAttr>(ActiveSemantic.Semantic)) {
+ if (CGM.getTriple().getEnvironment() == Triple::EnvironmentType::Pixel)
+ return createSPIRVBuiltinLoad(B, CGM.getModule(), Type,
+ S->getAttrName()->getName(),
+ /* BuiltIn::FragCoord */ 15);
}
- assert(false && "Unhandled parameter attribute");
- return nullptr;
+
+ llvm_unreachable("non-handled system semantic. FIXME.");
+}
+
+llvm::Value *
+CGHLSLRuntime::handleScalarSemanticLoad(IRBuilder<> &B, llvm::Type *Type,
+ const clang::DeclaratorDecl *Decl,
+ SemanticInfo &ActiveSemantic) {
+
+ if (!ActiveSemantic.Semantic) {
+ ActiveSemantic.Semantic = Decl->getAttr<HLSLSemanticAttr>();
+ if (!ActiveSemantic.Semantic) {
+ CGM.getDiags().Report(Decl->getInnerLocStart(),
+ diag::err_hlsl_semantic_missing);
+ return nullptr;
+ }
+ ActiveSemantic.Index = ActiveSemantic.Semantic->getSemanticIndex();
+ }
+
+ return emitSystemSemanticLoad(B, Type, Decl, ActiveSemantic);
+}
+
+llvm::Value *
+CGHLSLRuntime::handleSemanticLoad(IRBuilder<> &B, llvm::Type *Type,
+ const clang::DeclaratorDecl *Decl,
+ SemanticInfo &ActiveSemantic) {
+ assert(!Type->isStructTy());
+ return handleScalarSemanticLoad(B, Type, Decl, ActiveSemantic);
}
void CGHLSLRuntime::emitEntryFunction(const FunctionDecl *FD,
@@ -637,8 +669,10 @@ void CGHLSLRuntime::emitEntryFunction(const FunctionDecl *FD,
Args.emplace_back(PoisonValue::get(Param.getType()));
continue;
}
+
const ParmVarDecl *PD = FD->getParamDecl(Param.getArgNo() - SRetOffset);
- Args.push_back(emitInputSemantic(B, *PD, Param.getType()));
+ SemanticInfo ActiveSemantic = {nullptr, 0};
+ Args.push_back(handleSemanticLoad(B, Param.getType(), PD, ActiveSemantic));
}
CallInst *CI = B.CreateCall(FunctionCallee(Fn), Args, OB);