diff options
author | Nathan Gauër <brioche@google.com> | 2025-09-09 15:31:26 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2025-09-09 13:31:26 +0000 |
commit | 57e1846c96f0c858f687fe9c66f4e3793b52f497 (patch) | |
tree | ae7e9cd8d12cbfda83b257dd72ec05090f23fe8d /clang/lib/CodeGen/CGHLSLRuntime.cpp | |
parent | 80c2da6372b5b4104cf09411c9fa8cb64df0a8a2 (diff) | |
download | llvm-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.cpp | 72 |
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); |