-
Notifications
You must be signed in to change notification settings - Fork 15.2k
[HLSL] Add initial support for output semantics #168095
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
|
@llvm/pr-subscribers-hlsl @llvm/pr-subscribers-backend-directx Author: Nathan Gauër (Keenuts) ChangesThis commits adds the first part of the output semantics. It only considers return values (and sret), but does not handle Patch is 40.45 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/168095.diff 26 Files Affected:
diff --git a/clang/lib/CodeGen/CGHLSLRuntime.cpp b/clang/lib/CodeGen/CGHLSLRuntime.cpp
index ec02096787c7a..741e60e9865cd 100644
--- a/clang/lib/CodeGen/CGHLSLRuntime.cpp
+++ b/clang/lib/CodeGen/CGHLSLRuntime.cpp
@@ -589,6 +589,36 @@ CGHLSLRuntime::emitSPIRVUserSemanticLoad(llvm::IRBuilder<> &B, llvm::Type *Type,
VariableName.str());
}
+static void createSPIRVLocationStore(IRBuilder<> &B, llvm::Module &M,
+ llvm::Value *Source, unsigned Location,
+ StringRef Name) {
+ auto *GV = new llvm::GlobalVariable(
+ M, Source->getType(), /* isConstant= */ false,
+ llvm::GlobalValue::ExternalLinkage,
+ /* Initializer= */ nullptr, /* Name= */ Name, /* insertBefore= */ nullptr,
+ llvm::GlobalVariable::GeneralDynamicTLSModel,
+ /* AddressSpace */ 8, /* isExternallyInitialized= */ false);
+ GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
+ addLocationDecoration(GV, Location);
+ B.CreateStore(Source, GV);
+}
+
+void CGHLSLRuntime::emitSPIRVUserSemanticStore(
+ llvm::IRBuilder<> &B, llvm::Value *Source,
+ HLSLAppliedSemanticAttr *Semantic, std::optional<unsigned> Index) {
+ Twine BaseName = Twine(Semantic->getAttrName()->getName());
+ Twine VariableName = BaseName.concat(Twine(Index.value_or(0)));
+ unsigned Location = SPIRVLastAssignedOutputSemanticLocation;
+
+ // DXC completely ignores the semantic/index pair. Location are assigned from
+ // the first semantic to the last.
+ llvm::ArrayType *AT = dyn_cast<llvm::ArrayType>(Source->getType());
+ unsigned ElementCount = AT ? AT->getNumElements() : 1;
+ SPIRVLastAssignedOutputSemanticLocation += ElementCount;
+ createSPIRVLocationStore(B, CGM.getModule(), Source, Location,
+ VariableName.str());
+}
+
llvm::Value *
CGHLSLRuntime::emitDXILUserSemanticLoad(llvm::IRBuilder<> &B, llvm::Type *Type,
HLSLAppliedSemanticAttr *Semantic,
@@ -609,6 +639,23 @@ CGHLSLRuntime::emitDXILUserSemanticLoad(llvm::IRBuilder<> &B, llvm::Type *Type,
return Value;
}
+void CGHLSLRuntime::emitDXILUserSemanticStore(llvm::IRBuilder<> &B,
+ llvm::Value *Source,
+ HLSLAppliedSemanticAttr *Semantic,
+ std::optional<unsigned> Index) {
+ // DXIL packing rules etc shall be handled here.
+ // FIXME: generate proper sigpoint, index, col, row values.
+ SmallVector<Value *> Args{B.getInt32(4),
+ B.getInt32(0),
+ B.getInt32(0),
+ B.getInt8(0),
+ llvm::PoisonValue::get(B.getInt32Ty()),
+ Source};
+
+ llvm::Intrinsic::ID IntrinsicID = llvm::Intrinsic::dx_store_output;
+ B.CreateIntrinsic(/*ReturnType=*/CGM.VoidTy, IntrinsicID, Args, nullptr);
+}
+
llvm::Value *CGHLSLRuntime::emitUserSemanticLoad(
IRBuilder<> &B, llvm::Type *Type, const clang::DeclaratorDecl *Decl,
HLSLAppliedSemanticAttr *Semantic, std::optional<unsigned> Index) {
@@ -621,6 +668,19 @@ llvm::Value *CGHLSLRuntime::emitUserSemanticLoad(
llvm_unreachable("Unsupported target for user-semantic load.");
}
+void CGHLSLRuntime::emitUserSemanticStore(IRBuilder<> &B, llvm::Value *Source,
+ const clang::DeclaratorDecl *Decl,
+ HLSLAppliedSemanticAttr *Semantic,
+ std::optional<unsigned> Index) {
+ if (CGM.getTarget().getTriple().isSPIRV())
+ return emitSPIRVUserSemanticStore(B, Source, Semantic, Index);
+
+ if (CGM.getTarget().getTriple().isDXIL())
+ return emitDXILUserSemanticStore(B, Source, Semantic, Index);
+
+ llvm_unreachable("Unsupported target for user-semantic load.");
+}
+
llvm::Value *CGHLSLRuntime::emitSystemSemanticLoad(
IRBuilder<> &B, llvm::Type *Type, const clang::DeclaratorDecl *Decl,
HLSLAppliedSemanticAttr *Semantic, std::optional<unsigned> Index) {
@@ -669,6 +729,34 @@ llvm::Value *CGHLSLRuntime::emitSystemSemanticLoad(
llvm_unreachable("non-handled system semantic. FIXME.");
}
+static void createSPIRVBuiltinStore(IRBuilder<> &B, llvm::Module &M,
+ llvm::Value *Source, const Twine &Name,
+ unsigned BuiltInID) {
+ auto *GV = new llvm::GlobalVariable(
+ M, Source->getType(), /* isConstant= */ false,
+ llvm::GlobalValue::ExternalLinkage,
+ /* Initializer= */ nullptr, Name, /* insertBefore= */ nullptr,
+ llvm::GlobalVariable::GeneralDynamicTLSModel,
+ /* AddressSpace */ 8, /* isExternallyInitialized= */ false);
+ addSPIRVBuiltinDecoration(GV, BuiltInID);
+ GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
+ B.CreateStore(Source, GV);
+}
+
+void CGHLSLRuntime::emitSystemSemanticStore(IRBuilder<> &B, llvm::Value *Source,
+ const clang::DeclaratorDecl *Decl,
+ HLSLAppliedSemanticAttr *Semantic,
+ std::optional<unsigned> Index) {
+
+ std::string SemanticName = Semantic->getAttrName()->getName().upper();
+ if (SemanticName == "SV_POSITION")
+ createSPIRVBuiltinStore(B, CGM.getModule(), Source,
+ Semantic->getAttrName()->getName(),
+ /* BuiltIn::Position */ 0);
+ else
+ llvm_unreachable("non-handled system semantic. FIXME.");
+}
+
llvm::Value *CGHLSLRuntime::handleScalarSemanticLoad(
IRBuilder<> &B, const FunctionDecl *FD, llvm::Type *Type,
const clang::DeclaratorDecl *Decl, HLSLAppliedSemanticAttr *Semantic) {
@@ -679,6 +767,16 @@ llvm::Value *CGHLSLRuntime::handleScalarSemanticLoad(
return emitUserSemanticLoad(B, Type, Decl, Semantic, Index);
}
+void CGHLSLRuntime::handleScalarSemanticStore(
+ IRBuilder<> &B, const FunctionDecl *FD, llvm::Value *Source,
+ const clang::DeclaratorDecl *Decl, HLSLAppliedSemanticAttr *Semantic) {
+ std::optional<unsigned> Index = Semantic->getSemanticIndex();
+ if (Semantic->getAttrName()->getName().starts_with_insensitive("SV_"))
+ emitSystemSemanticStore(B, Source, Decl, Semantic, Index);
+ else
+ emitUserSemanticStore(B, Source, Decl, Semantic, Index);
+}
+
std::pair<llvm::Value *, specific_attr_iterator<HLSLAppliedSemanticAttr>>
CGHLSLRuntime::handleStructSemanticLoad(
IRBuilder<> &B, const FunctionDecl *FD, llvm::Type *Type,
@@ -705,6 +803,35 @@ CGHLSLRuntime::handleStructSemanticLoad(
return std::make_pair(Aggregate, AttrBegin);
}
+specific_attr_iterator<HLSLAppliedSemanticAttr>
+CGHLSLRuntime::handleStructSemanticStore(
+ IRBuilder<> &B, const FunctionDecl *FD, llvm::Value *Source,
+ const clang::DeclaratorDecl *Decl,
+ specific_attr_iterator<HLSLAppliedSemanticAttr> AttrBegin,
+ specific_attr_iterator<HLSLAppliedSemanticAttr> AttrEnd) {
+
+ const llvm::StructType *ST = cast<StructType>(Source->getType());
+
+ const clang::RecordDecl *RD = nullptr;
+ if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(Decl))
+ RD = FD->getDeclaredReturnType()->getAsRecordDecl();
+ else
+ RD = Decl->getType()->getAsRecordDecl();
+ assert(RD);
+
+ assert(std::distance(RD->field_begin(), RD->field_end()) ==
+ ST->getNumElements());
+
+ auto FieldDecl = RD->field_begin();
+ for (unsigned I = 0; I < ST->getNumElements(); ++I) {
+ llvm::Value *Extract = B.CreateExtractValue(Source, I);
+ AttrBegin =
+ handleSemanticStore(B, FD, Extract, *FieldDecl, AttrBegin, AttrEnd);
+ }
+
+ return AttrBegin;
+}
+
std::pair<llvm::Value *, specific_attr_iterator<HLSLAppliedSemanticAttr>>
CGHLSLRuntime::handleSemanticLoad(
IRBuilder<> &B, const FunctionDecl *FD, llvm::Type *Type,
@@ -721,6 +848,22 @@ CGHLSLRuntime::handleSemanticLoad(
AttrBegin);
}
+specific_attr_iterator<HLSLAppliedSemanticAttr>
+CGHLSLRuntime::handleSemanticStore(
+ IRBuilder<> &B, const FunctionDecl *FD, llvm::Value *Source,
+ const clang::DeclaratorDecl *Decl,
+ specific_attr_iterator<HLSLAppliedSemanticAttr> AttrBegin,
+ specific_attr_iterator<HLSLAppliedSemanticAttr> AttrEnd) {
+ assert(AttrBegin != AttrEnd);
+ if (Source->getType()->isStructTy())
+ return handleStructSemanticStore(B, FD, Source, Decl, AttrBegin, AttrEnd);
+
+ HLSLAppliedSemanticAttr *Attr = *AttrBegin;
+ ++AttrBegin;
+ handleScalarSemanticStore(B, FD, Source, Decl, Attr);
+ return AttrBegin;
+}
+
void CGHLSLRuntime::emitEntryFunction(const FunctionDecl *FD,
llvm::Function *Fn) {
llvm::Module &M = CGM.getModule();
@@ -752,20 +895,22 @@ void CGHLSLRuntime::emitEntryFunction(const FunctionDecl *FD,
OB.emplace_back("convergencectrl", bundleArgs);
}
- // FIXME: support struct parameters where semantics are on members.
- // See: https://github.com/llvm/llvm-project/issues/57874
+ std::unordered_map<const DeclaratorDecl *, llvm::Value *> OutputSemantic;
+
unsigned SRetOffset = 0;
for (const auto &Param : Fn->args()) {
if (Param.hasStructRetAttr()) {
- // FIXME: support output.
- // See: https://github.com/llvm/llvm-project/issues/57874
SRetOffset = 1;
- Args.emplace_back(PoisonValue::get(Param.getType()));
+ llvm::Type *VarType = Param.getParamStructRetType();
+ llvm::Value *Var = B.CreateAlloca(VarType);
+ OutputSemantic.emplace(FD, Var);
+ Args.push_back(Var);
continue;
}
const ParmVarDecl *PD = FD->getParamDecl(Param.getArgNo() - SRetOffset);
llvm::Value *SemanticValue = nullptr;
+ // FIXME: support inout/out parameters for semantics.
if ([[maybe_unused]] HLSLParamModifierAttr *MA =
PD->getAttr<HLSLParamModifierAttr>()) {
llvm_unreachable("Not handled yet");
@@ -792,8 +937,20 @@ void CGHLSLRuntime::emitEntryFunction(const FunctionDecl *FD,
CallInst *CI = B.CreateCall(FunctionCallee(Fn), Args, OB);
CI->setCallingConv(Fn->getCallingConv());
- // FIXME: Handle codegen for return type semantics.
- // See: https://github.com/llvm/llvm-project/issues/57875
+
+ if (Fn->getReturnType() != CGM.VoidTy)
+ OutputSemantic.emplace(FD, CI);
+
+ for (auto &[Decl, Source] : OutputSemantic) {
+ AllocaInst *AI = dyn_cast<AllocaInst>(Source);
+ llvm::Value *SourceValue =
+ AI ? B.CreateLoad(AI->getAllocatedType(), Source) : Source;
+
+ auto AttrBegin = Decl->specific_attr_begin<HLSLAppliedSemanticAttr>();
+ auto AttrEnd = Decl->specific_attr_end<HLSLAppliedSemanticAttr>();
+ handleSemanticStore(B, FD, SourceValue, Decl, AttrBegin, AttrEnd);
+ }
+
B.CreateRetVoid();
// Add and identify root signature to function, if applicable
diff --git a/clang/lib/CodeGen/CGHLSLRuntime.h b/clang/lib/CodeGen/CGHLSLRuntime.h
index 48935584f28a2..d9f7b3db1bb79 100644
--- a/clang/lib/CodeGen/CGHLSLRuntime.h
+++ b/clang/lib/CodeGen/CGHLSLRuntime.h
@@ -176,12 +176,22 @@ class CGHLSLRuntime {
HLSLAppliedSemanticAttr *Semantic,
std::optional<unsigned> Index);
+ void emitSystemSemanticStore(llvm::IRBuilder<> &B, llvm::Value *Source,
+ const clang::DeclaratorDecl *Decl,
+ HLSLAppliedSemanticAttr *Semantic,
+ std::optional<unsigned> Index);
+
llvm::Value *handleScalarSemanticLoad(llvm::IRBuilder<> &B,
const FunctionDecl *FD,
llvm::Type *Type,
const clang::DeclaratorDecl *Decl,
HLSLAppliedSemanticAttr *Semantic);
+ void handleScalarSemanticStore(llvm::IRBuilder<> &B, const FunctionDecl *FD,
+ llvm::Value *Source,
+ const clang::DeclaratorDecl *Decl,
+ HLSLAppliedSemanticAttr *Semantic);
+
std::pair<llvm::Value *, specific_attr_iterator<HLSLAppliedSemanticAttr>>
handleStructSemanticLoad(
llvm::IRBuilder<> &B, const FunctionDecl *FD, llvm::Type *Type,
@@ -189,12 +199,24 @@ class CGHLSLRuntime {
specific_attr_iterator<HLSLAppliedSemanticAttr> begin,
specific_attr_iterator<HLSLAppliedSemanticAttr> end);
+ specific_attr_iterator<HLSLAppliedSemanticAttr> handleStructSemanticStore(
+ llvm::IRBuilder<> &B, const FunctionDecl *FD, llvm::Value *Source,
+ const clang::DeclaratorDecl *Decl,
+ specific_attr_iterator<HLSLAppliedSemanticAttr> AttrBegin,
+ specific_attr_iterator<HLSLAppliedSemanticAttr> AttrEnd);
+
std::pair<llvm::Value *, specific_attr_iterator<HLSLAppliedSemanticAttr>>
handleSemanticLoad(llvm::IRBuilder<> &B, const FunctionDecl *FD,
llvm::Type *Type, const clang::DeclaratorDecl *Decl,
specific_attr_iterator<HLSLAppliedSemanticAttr> begin,
specific_attr_iterator<HLSLAppliedSemanticAttr> end);
+ specific_attr_iterator<HLSLAppliedSemanticAttr>
+ handleSemanticStore(llvm::IRBuilder<> &B, const FunctionDecl *FD,
+ llvm::Value *Source, const clang::DeclaratorDecl *Decl,
+ specific_attr_iterator<HLSLAppliedSemanticAttr> AttrBegin,
+ specific_attr_iterator<HLSLAppliedSemanticAttr> AttrEnd);
+
public:
CGHLSLRuntime(CodeGenModule &CGM) : CGM(CGM) {}
virtual ~CGHLSLRuntime() {}
@@ -249,10 +271,22 @@ class CGHLSLRuntime {
HLSLAppliedSemanticAttr *Semantic,
std::optional<unsigned> Index);
+ void emitSPIRVUserSemanticStore(llvm::IRBuilder<> &B, llvm::Value *Source,
+ HLSLAppliedSemanticAttr *Semantic,
+ std::optional<unsigned> Index);
+ void emitDXILUserSemanticStore(llvm::IRBuilder<> &B, llvm::Value *Source,
+ HLSLAppliedSemanticAttr *Semantic,
+ std::optional<unsigned> Index);
+ void emitUserSemanticStore(llvm::IRBuilder<> &B, llvm::Value *Source,
+ const clang::DeclaratorDecl *Decl,
+ HLSLAppliedSemanticAttr *Semantic,
+ std::optional<unsigned> Index);
+
llvm::Triple::ArchType getArch();
llvm::DenseMap<const clang::RecordType *, llvm::TargetExtType *> LayoutTypes;
unsigned SPIRVLastAssignedInputSemanticLocation = 0;
+ unsigned SPIRVLastAssignedOutputSemanticLocation = 0;
};
} // namespace CodeGen
diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp
index 2b9b3abbd5360..dd8122c11e696 100644
--- a/clang/lib/Sema/SemaHLSL.cpp
+++ b/clang/lib/Sema/SemaHLSL.cpp
@@ -825,7 +825,9 @@ bool SemaHLSL::determineActiveSemantic(
ActiveSemantic.Index = ActiveSemantic.Semantic->getSemanticIndex();
}
- const Type *T = D->getType()->getUnqualifiedDesugaredType();
+ const Type *T = D == FD ? &*FD->getReturnType() : &*D->getType();
+ T = T->getUnqualifiedDesugaredType();
+
const RecordType *RT = dyn_cast<RecordType>(T);
if (!RT)
return determineActiveSemanticOnScalar(FD, OutputDecl, D, ActiveSemantic,
@@ -915,13 +917,21 @@ void SemaHLSL::CheckEntryPoint(FunctionDecl *FD) {
if (ActiveSemantic.Semantic)
ActiveSemantic.Index = ActiveSemantic.Semantic->getSemanticIndex();
+ // FIXME: Verify output semantics in parameters.
if (!determineActiveSemantic(FD, Param, Param, ActiveSemantic,
ActiveInputSemantics)) {
Diag(Param->getLocation(), diag::note_previous_decl) << Param;
FD->setInvalidDecl();
}
}
- // FIXME: Verify return type semantic annotation.
+
+ SemanticInfo ActiveSemantic;
+ llvm::StringSet<> ActiveOutputSemantics;
+ ActiveSemantic.Semantic = FD->getAttr<HLSLParsedSemanticAttr>();
+ if (ActiveSemantic.Semantic)
+ ActiveSemantic.Index = ActiveSemantic.Semantic->getSemanticIndex();
+ if (!FD->getReturnType()->isVoidType())
+ determineActiveSemantic(FD, FD, FD, ActiveSemantic, ActiveOutputSemantics);
}
void SemaHLSL::checkSemanticAnnotation(
diff --git a/clang/test/CodeGenHLSL/semantics/SV_Position.ps.hlsl b/clang/test/CodeGenHLSL/semantics/SV_Position.ps.hlsl
index 1bba87ea07141..be30e79438831 100644
--- a/clang/test/CodeGenHLSL/semantics/SV_Position.ps.hlsl
+++ b/clang/test/CodeGenHLSL/semantics/SV_Position.ps.hlsl
@@ -3,8 +3,9 @@
// CHECK: @SV_Position = external hidden thread_local addrspace(7) externally_initialized constant <4 x float>, !spirv.Decorations !0
// CHECK: define void @main() {{.*}} {
-float4 main(float4 p : SV_Position) {
+float4 main(float4 p : SV_Position) : A {
// CHECK: %[[#P:]] = load <4 x float>, ptr addrspace(7) @SV_Position, align 16
// CHECK: %[[#R:]] = call spir_func <4 x float> @_Z4mainDv4_f(<4 x float> %[[#P]])
+ // CHECK: store <4 x float> %[[#R]], ptr addrspace(8) @A0, align 16
return p;
}
diff --git a/clang/test/CodeGenHLSL/semantics/missing-vs.hlsl b/clang/test/CodeGenHLSL/semantics/missing-vs.hlsl
new file mode 100644
index 0000000000000..41be9c0ab730c
--- /dev/null
+++ b/clang/test/CodeGenHLSL/semantics/missing-vs.hlsl
@@ -0,0 +1,6 @@
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-vertex -x hlsl -emit-llvm -disable-llvm-passes -o - -hlsl-entry main %s -verify -verify-ignore-unexpected=note
+// RUN: %clang_cc1 -triple spirv-unknown-vulkan-vertex -x hlsl -emit-llvm -disable-llvm-passes -o - -hlsl-entry main %s -verify -verify-ignore-unexpected=note
+
+float main(unsigned GI : A) {
+ // expected-error@-1 {{semantic annotations must be present for all parameters of an entry function or patch constant function}}
+}
diff --git a/clang/test/CodeGenHLSL/semantics/semantic-struct-2-output.hlsl b/clang/test/CodeGenHLSL/semantics/semantic-struct-2-output.hlsl
new file mode 100644
index 0000000000000..2f8dc97ef762e
--- /dev/null
+++ b/clang/test/CodeGenHLSL/semantics/semantic-struct-2-output.hlsl
@@ -0,0 +1,35 @@
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -x hlsl -emit-llvm -finclude-default-header -disable-llvm-passes -o - %s | FileCheck %s --check-prefixes=CHECK-DX,CHECK
+// RUN: %clang_cc1 -triple spirv-linux-vulkan-library -x hlsl -emit-llvm -finclude-default-header -disable-llvm-passes -o - %s | FileCheck %s --check-prefixes=CHECK-VK,CHECK
+
+
+struct Input {
+ float Idx : SV_Position0;
+ float Gid : SV_Position1;
+};
+
+struct Output {
+ float a : A;
+ float b : B;
+};
+
+// Make sure SV_DispatchThreadID translated into dx.thread.id.
+
+// CHECK-DX: define hidden void @_Z3foo5Input(ptr dead_on_unwind noalias writable sret(%struct.Output) align 1 %agg.result, ptr noundef byval(%struct.Input) align 1 %input)
+// CHECK-VK: define hidden spir_func void @_Z3foo5Input(ptr dead_on_unwind noalias writable sret(%struct.Output) align 1 %agg.result, ptr noundef byval(%struct.Input) align 1 %input)
+
+// CHECK: %Idx = getelementptr inbounds nuw %struct.Input, ptr %input, i32 0, i32 0
+// CHECK: %[[#tmp:]] = load float, ptr %Idx, align 1
+// CHECK: %a = getelementptr inbounds nuw %struct.Output, ptr %agg.result, i32 0, i32 0
+// CHECK: store float %[[#tmp]], ptr %a, align 1
+// CHECK: %Gid = getelementptr inbounds nuw %struct.Input, ptr %input, i32 0, i32 1
+// CHECK: %[[#tmp:]] = load float, ptr %Gid, align 1
+// CHECK: %b = getelementptr inbounds nuw %struct.Output, ptr %agg.result, i32 0, i32 1
+// CHECK: store float %[[#tmp]], ptr %b, align 1
+
+Output foo(Input input) {
+ Output o;
+ o.a = input.Idx;
+ o.b = input.Gid;
+ return o;
+}
+
diff --git a/clang/test/CodeGenHLSL/semantics/semantic.array.output.hlsl b/clang/test/CodeGenHLSL/semantics/semantic.array.output.hlsl
new file mode 100644
index 0000000000000..2ff0e3835672c
--- /dev/null
+++ b/clang/test/CodeGenHLSL/semantics/semantic.array.output.hlsl
@@ -0,0 +1,31 @@
+// RUN: %clang_cc1 -triple spirv-linux-vulkan-library -x hlsl -emit-llvm -finclude-default-header -disable-llvm-passes -o - %s | FileCheck %s --check-prefixes=CHECK,CHECK-SPIRV -DTARGET=spv
+// RUN: %clang_cc1 -triple dxil-px-shadermodel6.3-library -x hlsl -emit-llvm -finclude-default-header -disable-llvm-passes ...
[truncated]
|
|
@llvm/pr-subscribers-clang Author: Nathan Gauër (Keenuts) ChangesThis commits adds the first part of the output semantics. It only considers return values (and sret), but does not handle Patch is 40.45 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/168095.diff 26 Files Affected:
diff --git a/clang/lib/CodeGen/CGHLSLRuntime.cpp b/clang/lib/CodeGen/CGHLSLRuntime.cpp
index ec02096787c7a..741e60e9865cd 100644
--- a/clang/lib/CodeGen/CGHLSLRuntime.cpp
+++ b/clang/lib/CodeGen/CGHLSLRuntime.cpp
@@ -589,6 +589,36 @@ CGHLSLRuntime::emitSPIRVUserSemanticLoad(llvm::IRBuilder<> &B, llvm::Type *Type,
VariableName.str());
}
+static void createSPIRVLocationStore(IRBuilder<> &B, llvm::Module &M,
+ llvm::Value *Source, unsigned Location,
+ StringRef Name) {
+ auto *GV = new llvm::GlobalVariable(
+ M, Source->getType(), /* isConstant= */ false,
+ llvm::GlobalValue::ExternalLinkage,
+ /* Initializer= */ nullptr, /* Name= */ Name, /* insertBefore= */ nullptr,
+ llvm::GlobalVariable::GeneralDynamicTLSModel,
+ /* AddressSpace */ 8, /* isExternallyInitialized= */ false);
+ GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
+ addLocationDecoration(GV, Location);
+ B.CreateStore(Source, GV);
+}
+
+void CGHLSLRuntime::emitSPIRVUserSemanticStore(
+ llvm::IRBuilder<> &B, llvm::Value *Source,
+ HLSLAppliedSemanticAttr *Semantic, std::optional<unsigned> Index) {
+ Twine BaseName = Twine(Semantic->getAttrName()->getName());
+ Twine VariableName = BaseName.concat(Twine(Index.value_or(0)));
+ unsigned Location = SPIRVLastAssignedOutputSemanticLocation;
+
+ // DXC completely ignores the semantic/index pair. Location are assigned from
+ // the first semantic to the last.
+ llvm::ArrayType *AT = dyn_cast<llvm::ArrayType>(Source->getType());
+ unsigned ElementCount = AT ? AT->getNumElements() : 1;
+ SPIRVLastAssignedOutputSemanticLocation += ElementCount;
+ createSPIRVLocationStore(B, CGM.getModule(), Source, Location,
+ VariableName.str());
+}
+
llvm::Value *
CGHLSLRuntime::emitDXILUserSemanticLoad(llvm::IRBuilder<> &B, llvm::Type *Type,
HLSLAppliedSemanticAttr *Semantic,
@@ -609,6 +639,23 @@ CGHLSLRuntime::emitDXILUserSemanticLoad(llvm::IRBuilder<> &B, llvm::Type *Type,
return Value;
}
+void CGHLSLRuntime::emitDXILUserSemanticStore(llvm::IRBuilder<> &B,
+ llvm::Value *Source,
+ HLSLAppliedSemanticAttr *Semantic,
+ std::optional<unsigned> Index) {
+ // DXIL packing rules etc shall be handled here.
+ // FIXME: generate proper sigpoint, index, col, row values.
+ SmallVector<Value *> Args{B.getInt32(4),
+ B.getInt32(0),
+ B.getInt32(0),
+ B.getInt8(0),
+ llvm::PoisonValue::get(B.getInt32Ty()),
+ Source};
+
+ llvm::Intrinsic::ID IntrinsicID = llvm::Intrinsic::dx_store_output;
+ B.CreateIntrinsic(/*ReturnType=*/CGM.VoidTy, IntrinsicID, Args, nullptr);
+}
+
llvm::Value *CGHLSLRuntime::emitUserSemanticLoad(
IRBuilder<> &B, llvm::Type *Type, const clang::DeclaratorDecl *Decl,
HLSLAppliedSemanticAttr *Semantic, std::optional<unsigned> Index) {
@@ -621,6 +668,19 @@ llvm::Value *CGHLSLRuntime::emitUserSemanticLoad(
llvm_unreachable("Unsupported target for user-semantic load.");
}
+void CGHLSLRuntime::emitUserSemanticStore(IRBuilder<> &B, llvm::Value *Source,
+ const clang::DeclaratorDecl *Decl,
+ HLSLAppliedSemanticAttr *Semantic,
+ std::optional<unsigned> Index) {
+ if (CGM.getTarget().getTriple().isSPIRV())
+ return emitSPIRVUserSemanticStore(B, Source, Semantic, Index);
+
+ if (CGM.getTarget().getTriple().isDXIL())
+ return emitDXILUserSemanticStore(B, Source, Semantic, Index);
+
+ llvm_unreachable("Unsupported target for user-semantic load.");
+}
+
llvm::Value *CGHLSLRuntime::emitSystemSemanticLoad(
IRBuilder<> &B, llvm::Type *Type, const clang::DeclaratorDecl *Decl,
HLSLAppliedSemanticAttr *Semantic, std::optional<unsigned> Index) {
@@ -669,6 +729,34 @@ llvm::Value *CGHLSLRuntime::emitSystemSemanticLoad(
llvm_unreachable("non-handled system semantic. FIXME.");
}
+static void createSPIRVBuiltinStore(IRBuilder<> &B, llvm::Module &M,
+ llvm::Value *Source, const Twine &Name,
+ unsigned BuiltInID) {
+ auto *GV = new llvm::GlobalVariable(
+ M, Source->getType(), /* isConstant= */ false,
+ llvm::GlobalValue::ExternalLinkage,
+ /* Initializer= */ nullptr, Name, /* insertBefore= */ nullptr,
+ llvm::GlobalVariable::GeneralDynamicTLSModel,
+ /* AddressSpace */ 8, /* isExternallyInitialized= */ false);
+ addSPIRVBuiltinDecoration(GV, BuiltInID);
+ GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
+ B.CreateStore(Source, GV);
+}
+
+void CGHLSLRuntime::emitSystemSemanticStore(IRBuilder<> &B, llvm::Value *Source,
+ const clang::DeclaratorDecl *Decl,
+ HLSLAppliedSemanticAttr *Semantic,
+ std::optional<unsigned> Index) {
+
+ std::string SemanticName = Semantic->getAttrName()->getName().upper();
+ if (SemanticName == "SV_POSITION")
+ createSPIRVBuiltinStore(B, CGM.getModule(), Source,
+ Semantic->getAttrName()->getName(),
+ /* BuiltIn::Position */ 0);
+ else
+ llvm_unreachable("non-handled system semantic. FIXME.");
+}
+
llvm::Value *CGHLSLRuntime::handleScalarSemanticLoad(
IRBuilder<> &B, const FunctionDecl *FD, llvm::Type *Type,
const clang::DeclaratorDecl *Decl, HLSLAppliedSemanticAttr *Semantic) {
@@ -679,6 +767,16 @@ llvm::Value *CGHLSLRuntime::handleScalarSemanticLoad(
return emitUserSemanticLoad(B, Type, Decl, Semantic, Index);
}
+void CGHLSLRuntime::handleScalarSemanticStore(
+ IRBuilder<> &B, const FunctionDecl *FD, llvm::Value *Source,
+ const clang::DeclaratorDecl *Decl, HLSLAppliedSemanticAttr *Semantic) {
+ std::optional<unsigned> Index = Semantic->getSemanticIndex();
+ if (Semantic->getAttrName()->getName().starts_with_insensitive("SV_"))
+ emitSystemSemanticStore(B, Source, Decl, Semantic, Index);
+ else
+ emitUserSemanticStore(B, Source, Decl, Semantic, Index);
+}
+
std::pair<llvm::Value *, specific_attr_iterator<HLSLAppliedSemanticAttr>>
CGHLSLRuntime::handleStructSemanticLoad(
IRBuilder<> &B, const FunctionDecl *FD, llvm::Type *Type,
@@ -705,6 +803,35 @@ CGHLSLRuntime::handleStructSemanticLoad(
return std::make_pair(Aggregate, AttrBegin);
}
+specific_attr_iterator<HLSLAppliedSemanticAttr>
+CGHLSLRuntime::handleStructSemanticStore(
+ IRBuilder<> &B, const FunctionDecl *FD, llvm::Value *Source,
+ const clang::DeclaratorDecl *Decl,
+ specific_attr_iterator<HLSLAppliedSemanticAttr> AttrBegin,
+ specific_attr_iterator<HLSLAppliedSemanticAttr> AttrEnd) {
+
+ const llvm::StructType *ST = cast<StructType>(Source->getType());
+
+ const clang::RecordDecl *RD = nullptr;
+ if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(Decl))
+ RD = FD->getDeclaredReturnType()->getAsRecordDecl();
+ else
+ RD = Decl->getType()->getAsRecordDecl();
+ assert(RD);
+
+ assert(std::distance(RD->field_begin(), RD->field_end()) ==
+ ST->getNumElements());
+
+ auto FieldDecl = RD->field_begin();
+ for (unsigned I = 0; I < ST->getNumElements(); ++I) {
+ llvm::Value *Extract = B.CreateExtractValue(Source, I);
+ AttrBegin =
+ handleSemanticStore(B, FD, Extract, *FieldDecl, AttrBegin, AttrEnd);
+ }
+
+ return AttrBegin;
+}
+
std::pair<llvm::Value *, specific_attr_iterator<HLSLAppliedSemanticAttr>>
CGHLSLRuntime::handleSemanticLoad(
IRBuilder<> &B, const FunctionDecl *FD, llvm::Type *Type,
@@ -721,6 +848,22 @@ CGHLSLRuntime::handleSemanticLoad(
AttrBegin);
}
+specific_attr_iterator<HLSLAppliedSemanticAttr>
+CGHLSLRuntime::handleSemanticStore(
+ IRBuilder<> &B, const FunctionDecl *FD, llvm::Value *Source,
+ const clang::DeclaratorDecl *Decl,
+ specific_attr_iterator<HLSLAppliedSemanticAttr> AttrBegin,
+ specific_attr_iterator<HLSLAppliedSemanticAttr> AttrEnd) {
+ assert(AttrBegin != AttrEnd);
+ if (Source->getType()->isStructTy())
+ return handleStructSemanticStore(B, FD, Source, Decl, AttrBegin, AttrEnd);
+
+ HLSLAppliedSemanticAttr *Attr = *AttrBegin;
+ ++AttrBegin;
+ handleScalarSemanticStore(B, FD, Source, Decl, Attr);
+ return AttrBegin;
+}
+
void CGHLSLRuntime::emitEntryFunction(const FunctionDecl *FD,
llvm::Function *Fn) {
llvm::Module &M = CGM.getModule();
@@ -752,20 +895,22 @@ void CGHLSLRuntime::emitEntryFunction(const FunctionDecl *FD,
OB.emplace_back("convergencectrl", bundleArgs);
}
- // FIXME: support struct parameters where semantics are on members.
- // See: https://github.com/llvm/llvm-project/issues/57874
+ std::unordered_map<const DeclaratorDecl *, llvm::Value *> OutputSemantic;
+
unsigned SRetOffset = 0;
for (const auto &Param : Fn->args()) {
if (Param.hasStructRetAttr()) {
- // FIXME: support output.
- // See: https://github.com/llvm/llvm-project/issues/57874
SRetOffset = 1;
- Args.emplace_back(PoisonValue::get(Param.getType()));
+ llvm::Type *VarType = Param.getParamStructRetType();
+ llvm::Value *Var = B.CreateAlloca(VarType);
+ OutputSemantic.emplace(FD, Var);
+ Args.push_back(Var);
continue;
}
const ParmVarDecl *PD = FD->getParamDecl(Param.getArgNo() - SRetOffset);
llvm::Value *SemanticValue = nullptr;
+ // FIXME: support inout/out parameters for semantics.
if ([[maybe_unused]] HLSLParamModifierAttr *MA =
PD->getAttr<HLSLParamModifierAttr>()) {
llvm_unreachable("Not handled yet");
@@ -792,8 +937,20 @@ void CGHLSLRuntime::emitEntryFunction(const FunctionDecl *FD,
CallInst *CI = B.CreateCall(FunctionCallee(Fn), Args, OB);
CI->setCallingConv(Fn->getCallingConv());
- // FIXME: Handle codegen for return type semantics.
- // See: https://github.com/llvm/llvm-project/issues/57875
+
+ if (Fn->getReturnType() != CGM.VoidTy)
+ OutputSemantic.emplace(FD, CI);
+
+ for (auto &[Decl, Source] : OutputSemantic) {
+ AllocaInst *AI = dyn_cast<AllocaInst>(Source);
+ llvm::Value *SourceValue =
+ AI ? B.CreateLoad(AI->getAllocatedType(), Source) : Source;
+
+ auto AttrBegin = Decl->specific_attr_begin<HLSLAppliedSemanticAttr>();
+ auto AttrEnd = Decl->specific_attr_end<HLSLAppliedSemanticAttr>();
+ handleSemanticStore(B, FD, SourceValue, Decl, AttrBegin, AttrEnd);
+ }
+
B.CreateRetVoid();
// Add and identify root signature to function, if applicable
diff --git a/clang/lib/CodeGen/CGHLSLRuntime.h b/clang/lib/CodeGen/CGHLSLRuntime.h
index 48935584f28a2..d9f7b3db1bb79 100644
--- a/clang/lib/CodeGen/CGHLSLRuntime.h
+++ b/clang/lib/CodeGen/CGHLSLRuntime.h
@@ -176,12 +176,22 @@ class CGHLSLRuntime {
HLSLAppliedSemanticAttr *Semantic,
std::optional<unsigned> Index);
+ void emitSystemSemanticStore(llvm::IRBuilder<> &B, llvm::Value *Source,
+ const clang::DeclaratorDecl *Decl,
+ HLSLAppliedSemanticAttr *Semantic,
+ std::optional<unsigned> Index);
+
llvm::Value *handleScalarSemanticLoad(llvm::IRBuilder<> &B,
const FunctionDecl *FD,
llvm::Type *Type,
const clang::DeclaratorDecl *Decl,
HLSLAppliedSemanticAttr *Semantic);
+ void handleScalarSemanticStore(llvm::IRBuilder<> &B, const FunctionDecl *FD,
+ llvm::Value *Source,
+ const clang::DeclaratorDecl *Decl,
+ HLSLAppliedSemanticAttr *Semantic);
+
std::pair<llvm::Value *, specific_attr_iterator<HLSLAppliedSemanticAttr>>
handleStructSemanticLoad(
llvm::IRBuilder<> &B, const FunctionDecl *FD, llvm::Type *Type,
@@ -189,12 +199,24 @@ class CGHLSLRuntime {
specific_attr_iterator<HLSLAppliedSemanticAttr> begin,
specific_attr_iterator<HLSLAppliedSemanticAttr> end);
+ specific_attr_iterator<HLSLAppliedSemanticAttr> handleStructSemanticStore(
+ llvm::IRBuilder<> &B, const FunctionDecl *FD, llvm::Value *Source,
+ const clang::DeclaratorDecl *Decl,
+ specific_attr_iterator<HLSLAppliedSemanticAttr> AttrBegin,
+ specific_attr_iterator<HLSLAppliedSemanticAttr> AttrEnd);
+
std::pair<llvm::Value *, specific_attr_iterator<HLSLAppliedSemanticAttr>>
handleSemanticLoad(llvm::IRBuilder<> &B, const FunctionDecl *FD,
llvm::Type *Type, const clang::DeclaratorDecl *Decl,
specific_attr_iterator<HLSLAppliedSemanticAttr> begin,
specific_attr_iterator<HLSLAppliedSemanticAttr> end);
+ specific_attr_iterator<HLSLAppliedSemanticAttr>
+ handleSemanticStore(llvm::IRBuilder<> &B, const FunctionDecl *FD,
+ llvm::Value *Source, const clang::DeclaratorDecl *Decl,
+ specific_attr_iterator<HLSLAppliedSemanticAttr> AttrBegin,
+ specific_attr_iterator<HLSLAppliedSemanticAttr> AttrEnd);
+
public:
CGHLSLRuntime(CodeGenModule &CGM) : CGM(CGM) {}
virtual ~CGHLSLRuntime() {}
@@ -249,10 +271,22 @@ class CGHLSLRuntime {
HLSLAppliedSemanticAttr *Semantic,
std::optional<unsigned> Index);
+ void emitSPIRVUserSemanticStore(llvm::IRBuilder<> &B, llvm::Value *Source,
+ HLSLAppliedSemanticAttr *Semantic,
+ std::optional<unsigned> Index);
+ void emitDXILUserSemanticStore(llvm::IRBuilder<> &B, llvm::Value *Source,
+ HLSLAppliedSemanticAttr *Semantic,
+ std::optional<unsigned> Index);
+ void emitUserSemanticStore(llvm::IRBuilder<> &B, llvm::Value *Source,
+ const clang::DeclaratorDecl *Decl,
+ HLSLAppliedSemanticAttr *Semantic,
+ std::optional<unsigned> Index);
+
llvm::Triple::ArchType getArch();
llvm::DenseMap<const clang::RecordType *, llvm::TargetExtType *> LayoutTypes;
unsigned SPIRVLastAssignedInputSemanticLocation = 0;
+ unsigned SPIRVLastAssignedOutputSemanticLocation = 0;
};
} // namespace CodeGen
diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp
index 2b9b3abbd5360..dd8122c11e696 100644
--- a/clang/lib/Sema/SemaHLSL.cpp
+++ b/clang/lib/Sema/SemaHLSL.cpp
@@ -825,7 +825,9 @@ bool SemaHLSL::determineActiveSemantic(
ActiveSemantic.Index = ActiveSemantic.Semantic->getSemanticIndex();
}
- const Type *T = D->getType()->getUnqualifiedDesugaredType();
+ const Type *T = D == FD ? &*FD->getReturnType() : &*D->getType();
+ T = T->getUnqualifiedDesugaredType();
+
const RecordType *RT = dyn_cast<RecordType>(T);
if (!RT)
return determineActiveSemanticOnScalar(FD, OutputDecl, D, ActiveSemantic,
@@ -915,13 +917,21 @@ void SemaHLSL::CheckEntryPoint(FunctionDecl *FD) {
if (ActiveSemantic.Semantic)
ActiveSemantic.Index = ActiveSemantic.Semantic->getSemanticIndex();
+ // FIXME: Verify output semantics in parameters.
if (!determineActiveSemantic(FD, Param, Param, ActiveSemantic,
ActiveInputSemantics)) {
Diag(Param->getLocation(), diag::note_previous_decl) << Param;
FD->setInvalidDecl();
}
}
- // FIXME: Verify return type semantic annotation.
+
+ SemanticInfo ActiveSemantic;
+ llvm::StringSet<> ActiveOutputSemantics;
+ ActiveSemantic.Semantic = FD->getAttr<HLSLParsedSemanticAttr>();
+ if (ActiveSemantic.Semantic)
+ ActiveSemantic.Index = ActiveSemantic.Semantic->getSemanticIndex();
+ if (!FD->getReturnType()->isVoidType())
+ determineActiveSemantic(FD, FD, FD, ActiveSemantic, ActiveOutputSemantics);
}
void SemaHLSL::checkSemanticAnnotation(
diff --git a/clang/test/CodeGenHLSL/semantics/SV_Position.ps.hlsl b/clang/test/CodeGenHLSL/semantics/SV_Position.ps.hlsl
index 1bba87ea07141..be30e79438831 100644
--- a/clang/test/CodeGenHLSL/semantics/SV_Position.ps.hlsl
+++ b/clang/test/CodeGenHLSL/semantics/SV_Position.ps.hlsl
@@ -3,8 +3,9 @@
// CHECK: @SV_Position = external hidden thread_local addrspace(7) externally_initialized constant <4 x float>, !spirv.Decorations !0
// CHECK: define void @main() {{.*}} {
-float4 main(float4 p : SV_Position) {
+float4 main(float4 p : SV_Position) : A {
// CHECK: %[[#P:]] = load <4 x float>, ptr addrspace(7) @SV_Position, align 16
// CHECK: %[[#R:]] = call spir_func <4 x float> @_Z4mainDv4_f(<4 x float> %[[#P]])
+ // CHECK: store <4 x float> %[[#R]], ptr addrspace(8) @A0, align 16
return p;
}
diff --git a/clang/test/CodeGenHLSL/semantics/missing-vs.hlsl b/clang/test/CodeGenHLSL/semantics/missing-vs.hlsl
new file mode 100644
index 0000000000000..41be9c0ab730c
--- /dev/null
+++ b/clang/test/CodeGenHLSL/semantics/missing-vs.hlsl
@@ -0,0 +1,6 @@
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-vertex -x hlsl -emit-llvm -disable-llvm-passes -o - -hlsl-entry main %s -verify -verify-ignore-unexpected=note
+// RUN: %clang_cc1 -triple spirv-unknown-vulkan-vertex -x hlsl -emit-llvm -disable-llvm-passes -o - -hlsl-entry main %s -verify -verify-ignore-unexpected=note
+
+float main(unsigned GI : A) {
+ // expected-error@-1 {{semantic annotations must be present for all parameters of an entry function or patch constant function}}
+}
diff --git a/clang/test/CodeGenHLSL/semantics/semantic-struct-2-output.hlsl b/clang/test/CodeGenHLSL/semantics/semantic-struct-2-output.hlsl
new file mode 100644
index 0000000000000..2f8dc97ef762e
--- /dev/null
+++ b/clang/test/CodeGenHLSL/semantics/semantic-struct-2-output.hlsl
@@ -0,0 +1,35 @@
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -x hlsl -emit-llvm -finclude-default-header -disable-llvm-passes -o - %s | FileCheck %s --check-prefixes=CHECK-DX,CHECK
+// RUN: %clang_cc1 -triple spirv-linux-vulkan-library -x hlsl -emit-llvm -finclude-default-header -disable-llvm-passes -o - %s | FileCheck %s --check-prefixes=CHECK-VK,CHECK
+
+
+struct Input {
+ float Idx : SV_Position0;
+ float Gid : SV_Position1;
+};
+
+struct Output {
+ float a : A;
+ float b : B;
+};
+
+// Make sure SV_DispatchThreadID translated into dx.thread.id.
+
+// CHECK-DX: define hidden void @_Z3foo5Input(ptr dead_on_unwind noalias writable sret(%struct.Output) align 1 %agg.result, ptr noundef byval(%struct.Input) align 1 %input)
+// CHECK-VK: define hidden spir_func void @_Z3foo5Input(ptr dead_on_unwind noalias writable sret(%struct.Output) align 1 %agg.result, ptr noundef byval(%struct.Input) align 1 %input)
+
+// CHECK: %Idx = getelementptr inbounds nuw %struct.Input, ptr %input, i32 0, i32 0
+// CHECK: %[[#tmp:]] = load float, ptr %Idx, align 1
+// CHECK: %a = getelementptr inbounds nuw %struct.Output, ptr %agg.result, i32 0, i32 0
+// CHECK: store float %[[#tmp]], ptr %a, align 1
+// CHECK: %Gid = getelementptr inbounds nuw %struct.Input, ptr %input, i32 0, i32 1
+// CHECK: %[[#tmp:]] = load float, ptr %Gid, align 1
+// CHECK: %b = getelementptr inbounds nuw %struct.Output, ptr %agg.result, i32 0, i32 1
+// CHECK: store float %[[#tmp]], ptr %b, align 1
+
+Output foo(Input input) {
+ Output o;
+ o.a = input.Idx;
+ o.b = input.Gid;
+ return o;
+}
+
diff --git a/clang/test/CodeGenHLSL/semantics/semantic.array.output.hlsl b/clang/test/CodeGenHLSL/semantics/semantic.array.output.hlsl
new file mode 100644
index 0000000000000..2ff0e3835672c
--- /dev/null
+++ b/clang/test/CodeGenHLSL/semantics/semantic.array.output.hlsl
@@ -0,0 +1,31 @@
+// RUN: %clang_cc1 -triple spirv-linux-vulkan-library -x hlsl -emit-llvm -finclude-default-header -disable-llvm-passes -o - %s | FileCheck %s --check-prefixes=CHECK,CHECK-SPIRV -DTARGET=spv
+// RUN: %clang_cc1 -triple dxil-px-shadermodel6.3-library -x hlsl -emit-llvm -finclude-default-header -disable-llvm-passes ...
[truncated]
|
s-perron
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM. Minor issues. The main one is the codegen test could check that the metadata declaring the location decoration is correct.
This commits adds the first part of the output semantics. It only considers return values (and sret), but does not handle `inout` or `out` parameters yet. Those missing bits will reuse the same code, but will require additional testing & some fixups, so planning on adding them separately.
f011a0f to
4b23dc4
Compare
🐧 Linux x64 Test Results
|
|
This PR broke some buildbots, just a missing include. Sending #168739 to fix forward. |
This commits adds the first part of the output semantics. It only considers return values (and sret), but does not handle
inoutoroutparameters yet.Those missing bits will reuse the same code, but will require additional testing & some fixups, so planning on adding them separately.