https://github.com/spall updated https://github.com/llvm/llvm-project/pull/181886
>From 7ef759df97b3035569c72feb000c4fa18a583041 Mon Sep 17 00:00:00 2001 From: Sarah Spall <[email protected]> Date: Tue, 17 Feb 2026 10:53:18 -0800 Subject: [PATCH 1/2] groupshared arg support mostly --- .../clang/Basic/DiagnosticSemaKinds.td | 7 ++ clang/lib/AST/ASTContext.cpp | 2 + clang/lib/Sema/SemaDecl.cpp | 6 +- clang/lib/Sema/SemaDeclAttr.cpp | 13 ++++ clang/lib/Sema/SemaModule.cpp | 12 +++ clang/lib/Sema/SemaOverload.cpp | 7 +- .../lib/Sema/SemaTemplateInstantiateDecl.cpp | 12 +++ clang/lib/Sema/SemaType.cpp | 21 +++++- .../CodeGenHLSL/groupsharedArgs/ArrTest.hlsl | 24 ++++++ .../groupsharedArgs/MatrixTest.hlsl | 20 +++++ .../groupsharedArgs/Overloads.hlsl | 38 ++++++++++ .../groupsharedArgs/Scalartest.hlsl | 18 +++++ .../groupsharedArgs/TemplateTest.hlsl | 38 ++++++++++ .../groupsharedArgs/VectorTest.hlsl | 22 ++++++ .../groupsharedArgs/ExplicitCast.hlsl | 13 ++++ .../groupsharedArgs/ExportNoInlineTest.hlsl | 19 +++++ .../Language/groupsharedArgs/InOut.hlsl | 74 +++++++++++++++++++ .../groupsharedArgs/NotGroupSharedTest.hlsl | 13 ++++ .../groupsharedArgs/Pre202xWarning.hlsl | 13 ++++ .../Language/groupsharedArgs/ScalarTest.hlsl | 13 ++++ clang/test/SemaHLSL/group_shared.hlsl | 11 +-- clang/test/SemaHLSL/group_shared_202x.hlsl | 3 - 22 files changed, 384 insertions(+), 15 deletions(-) create mode 100644 clang/test/CodeGenHLSL/groupsharedArgs/ArrTest.hlsl create mode 100644 clang/test/CodeGenHLSL/groupsharedArgs/MatrixTest.hlsl create mode 100644 clang/test/CodeGenHLSL/groupsharedArgs/Overloads.hlsl create mode 100644 clang/test/CodeGenHLSL/groupsharedArgs/Scalartest.hlsl create mode 100644 clang/test/CodeGenHLSL/groupsharedArgs/TemplateTest.hlsl create mode 100644 clang/test/CodeGenHLSL/groupsharedArgs/VectorTest.hlsl create mode 100644 clang/test/SemaHLSL/Language/groupsharedArgs/ExplicitCast.hlsl create mode 100644 clang/test/SemaHLSL/Language/groupsharedArgs/ExportNoInlineTest.hlsl create mode 100644 clang/test/SemaHLSL/Language/groupsharedArgs/InOut.hlsl create mode 100644 clang/test/SemaHLSL/Language/groupsharedArgs/NotGroupSharedTest.hlsl create mode 100644 clang/test/SemaHLSL/Language/groupsharedArgs/Pre202xWarning.hlsl create mode 100644 clang/test/SemaHLSL/Language/groupsharedArgs/ScalarTest.hlsl diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 85a023435ba23..377abf8d2c2ae 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -13438,6 +13438,13 @@ def err_hlsl_rootsignature_entry: Error< def err_hlsl_operator_unsupported : Error< "the '%select{&|*|->}0' operator is unsupported in HLSL">; +def warn_hlsl_groupshared_202x : Warning< + "support for groupshared parameter annotation not added until HLSL 202x">, + InGroup<HLSLAvailability>; +def warn_hlsl_groupshared_inout : Warning< + "passing groupshared variable to a parameter annotated with inout. " + "See 'groupshared' parameter annotation added in 202x">, + InGroup<HLSLAvailability>; def err_hlsl_param_qualifier_mismatch : Error<"conflicting parameter qualifier %0 on parameter %1">; def err_hlsl_vector_compound_assignment_truncation : Error< diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index 3f63420cae91e..43f3a4278fc39 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -7949,6 +7949,8 @@ const ArrayType *ASTContext::getAsArrayType(QualType T) const { } QualType ASTContext::getAdjustedParameterType(QualType T) const { + if (getLangOpts().HLSL && T.getAddressSpace() != LangAS::Default) + return getLValueReferenceType(T); if (getLangOpts().HLSL && T->isConstantArrayType()) return getArrayParameterType(T); if (T->isArrayType() || T->isFunctionType()) diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 4dfde4bf8cedf..32adfe393464d 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -15841,7 +15841,11 @@ ParmVarDecl *Sema::CheckParameter(DeclContext *DC, SourceLocation StartLoc, // WebAssembly allows reference types as parameters. Funcref in particular // lives in a different address space. !(T->isFunctionPointerType() && - T.getAddressSpace() == LangAS::wasm_funcref)) { + T.getAddressSpace() == LangAS::wasm_funcref) && + // HLSL allows function arguments to be qualified with an address space + // if the groupshared annotation is used. + !(getLangOpts().HLSL && + T.getAddressSpace() == LangAS::hlsl_groupshared)) { Diag(NameLoc, diag::err_arg_with_address_space); New->setInvalidDecl(); } diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index 5dbff18fff7a9..64fd8811136e8 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -7262,6 +7262,19 @@ ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, const ParsedAttr &AL, return; } + if (S.getLangOpts().HLSL && isa<FunctionDecl>(D) && + AL.getKind() == ParsedAttr::AT_NoInline) { + if (const auto *FD = dyn_cast<FunctionDecl>(D)) { + for (const ParmVarDecl *PVD : FD->parameters()) { + if (PVD->hasAttr<HLSLGroupSharedAddressSpaceAttr>()) { + S.Diag(AL.getLoc(), diag::err_hlsl_attr_incompatible) + << "'noinline'" << "'groupshared' parameter"; + return; + } + } + } + } + // Check if argument population must delayed to after template instantiation. bool MustDelayArgs = MustDelayAttributeArguments(AL); diff --git a/clang/lib/Sema/SemaModule.cpp b/clang/lib/Sema/SemaModule.cpp index 8cb684fd5ae3b..8fc3464ed3e0c 100644 --- a/clang/lib/Sema/SemaModule.cpp +++ b/clang/lib/Sema/SemaModule.cpp @@ -943,6 +943,18 @@ static bool checkExportedDecl(Sema &S, Decl *D, SourceLocation BlockStart) { D->setInvalidDecl(); return false; } + + if (isa<FunctionDecl>(D)) { + FunctionDecl *FD = cast<FunctionDecl>(D); + for (const ParmVarDecl *PVD : FD->parameters()) { + if (PVD->hasAttr<HLSLGroupSharedAddressSpaceAttr>()) { + S.Diag(D->getBeginLoc(), diag::err_hlsl_attr_incompatible) + << "'export'" << "'groupshared' parameter"; + D->setInvalidDecl(); + return false; + } + } + } } // C++20 [module.interface]p3: diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index 81edf966de9e7..a80609d8db119 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -7357,8 +7357,13 @@ void Sema::AddOverloadCandidate( QualType ParamType = Proto->getParamType(ArgIdx); auto ParamABI = Proto->getExtParameterInfo(ArgIdx).getABI(); if (ParamABI == ParameterABI::HLSLOut || - ParamABI == ParameterABI::HLSLInOut) + ParamABI == ParameterABI::HLSLInOut) { ParamType = ParamType.getNonReferenceType(); + if (ParamABI == ParameterABI::HLSLInOut && + Args[ArgIdx]->getType().getAddressSpace() == + LangAS::hlsl_groupshared) + Diag(Args[ArgIdx]->getBeginLoc(), diag::warn_hlsl_groupshared_inout); + } Candidate.Conversions[ConvIdx] = TryCopyInitialization( *this, Args[ArgIdx], ParamType, SuppressUserConversions, /*InOverloadResolution=*/true, diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index e74c41517ecbf..780aa766118fa 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -788,6 +788,18 @@ static void instantiateDependentHLSLParamModifierAttr( ParmVarDecl *NewParm = cast<ParmVarDecl>(New); NewParm->addAttr(Attr->clone(S.getASTContext())); + // we might have already produced an error + // just don't change the type here because it will assert + // also need to produce an error because of all the ways + // templates can be used + if (const auto *RT = NewParm->getType()->getAs<LValueReferenceType>()) { + if (RT->getPointeeType().getAddressSpace() == LangAS::hlsl_groupshared) { + S.Diag(Attr->getLoc(), diag::err_hlsl_attr_incompatible) + << Attr << "'groupshared'"; + return; + } + } + const Type *OldParmTy = cast<ParmVarDecl>(Old)->getType().getTypePtr(); if (OldParmTy->isDependentType() && Attr->isAnyOut()) NewParm->setType(S.HLSL().getInoutParameterType(NewParm->getType())); diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index a6d4b989cae3d..62aab39ab268d 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -8955,11 +8955,24 @@ static void processTypeAttrs(TypeProcessingState &state, QualType &type, case ParsedAttr::AT_OpenCLLocalAddressSpace: case ParsedAttr::AT_OpenCLConstantAddressSpace: case ParsedAttr::AT_OpenCLGenericAddressSpace: - case ParsedAttr::AT_HLSLGroupSharedAddressSpace: case ParsedAttr::AT_AddressSpace: HandleAddressSpaceTypeAttribute(type, attr, state); attr.setUsedAsTypeAttr(); break; + case ParsedAttr::AT_HLSLGroupSharedAddressSpace: + HandleAddressSpaceTypeAttribute(type, attr, state); + if (state.getDeclarator().getContext() == DeclaratorContext::Prototype) { + if (state.getSema().getLangOpts().getHLSLVersion() < + LangOptions::HLSL_202x) + state.getSema().Diag(attr.getLoc(), diag::warn_hlsl_groupshared_202x); + + // Note: we don't check for the usage of HLSLParamModifiers in/out/inout + // here because the check in the AT_HLSLParamModifier case is sufficient + // regardless of the order of groupshared or in/out/inout specified in + // the parameter. And checking there produces a better error message. + } + attr.setUsedAsTypeAttr(); + break; OBJC_POINTER_TYPE_ATTRS_CASELIST: if (!handleObjCPointerTypeAttr(state, attr, type)) distributeObjCPointerTypeAttr(state, attr, type); @@ -9044,6 +9057,12 @@ static void processTypeAttrs(TypeProcessingState &state, QualType &type, case ParsedAttr::AT_HLSLParamModifier: { HandleHLSLParamModifierAttr(state, type, attr, state.getSema()); + if (attrs.hasAttribute(ParsedAttr::AT_HLSLGroupSharedAddressSpace)) { + state.getSema().Diag(attr.getLoc(), diag::err_hlsl_attr_incompatible) + << attr << "'groupshared'"; + attr.setInvalid(); + return; + } attr.setUsedAsTypeAttr(); break; } diff --git a/clang/test/CodeGenHLSL/groupsharedArgs/ArrTest.hlsl b/clang/test/CodeGenHLSL/groupsharedArgs/ArrTest.hlsl new file mode 100644 index 0000000000000..4989275e6ee6d --- /dev/null +++ b/clang/test/CodeGenHLSL/groupsharedArgs/ArrTest.hlsl @@ -0,0 +1,24 @@ +// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.0-compute -std=hlsl202x -emit-llvm -disable-llvm-passes -hlsl-entry main -o - %s | FileCheck %s + +groupshared float4 SharedArr[64]; + +// CHECK-LABEL: define hidden void @_Z2fnRA64_U3AS3Dv4_ff(ptr addrspace(3) noundef align 16 dereferenceable(1024) %Arr, float noundef nofpclass(nan inf) %F) +// CHECK: [[ArrAddr:%.*]] = alloca ptr addrspace(3), align 4 +// CHECK: [[FAddr:%.*]] = alloca float, align 4 +// CHECK: store ptr addrspace(3) %Arr, ptr [[ArrAddr]], align 4 +// CHECK: store float %F, ptr [[FAddr]], align 4 +// CHECK: [[A:%.*]] = load float, ptr [[FAddr]], align 4 +// CHECK: [[Splat:%.*]] = insertelement <1 x float> poison, float [[A]], i64 0 +// CHECK: [[B:%.*]] = shufflevector <1 x float> [[Splat]], <1 x float> poison, <4 x i32> zeroinitializer +// CHECK: [[C:%.*]] = load ptr addrspace(3), ptr [[ArrAddr]], align 4, !align !3 +// CHECK: [[ArrIdx:%.*]] = getelementptr inbounds [64 x <4 x float>], ptr addrspace(3) [[C]], i32 0, i32 5 +// CHECK: store <4 x float> [[B]], ptr addrspace(3) [[ArrIdx]], align 16 +// CHECK: ret void +void fn(groupshared float4 Arr[64], float F) { + Arr[5] = F.xxxx; +} + +[numthreads(4,1,1)] +void main() { + fn(SharedArr, 6.0); +} diff --git a/clang/test/CodeGenHLSL/groupsharedArgs/MatrixTest.hlsl b/clang/test/CodeGenHLSL/groupsharedArgs/MatrixTest.hlsl new file mode 100644 index 0000000000000..b33e2f2d71185 --- /dev/null +++ b/clang/test/CodeGenHLSL/groupsharedArgs/MatrixTest.hlsl @@ -0,0 +1,20 @@ +// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.3-compute -std=hlsl202x -emit-llvm -disable-llvm-passes -hlsl-entry main -o - %s | FileCheck %s + +groupshared float4x4 SharedData; + +// CHECK-LABEL: define hidden void @_Z3fn1RU3AS3u11matrix_typeILm4ELm4EfE(ptr addrspace(3) noundef align 4 dereferenceable(64) %Sh) +// CHECK: [[ShAddr:%.*]] = alloca ptr addrspace(3), align 4 +// CHECK: store ptr addrspace(3) %Sh, ptr [[ShAddr]], align 4 +// CHECK: [[A:%.*]] = load ptr addrspace(3), ptr [[ShAddr]], align 4 +// CHECK: [[B:%.*]] = load <16 x float>, ptr addrspace(3) [[A]], align 4 +// CHECK: [[Matins:%.*]] = insertelement <16 x float> [[B]], float 5.000000e+00, i32 4 +// CHECK: store <16 x float> [[Matins]], ptr addrspace(3) [[A]], align 4 +// CHECK: ret void +void fn1(groupshared float4x4 Sh) { + Sh[0][1] = 5.0; +} + +[numthreads(4,1,1)] +void main(uint3 TID : SV_GroupThreadID) { + fn1(SharedData); +} diff --git a/clang/test/CodeGenHLSL/groupsharedArgs/Overloads.hlsl b/clang/test/CodeGenHLSL/groupsharedArgs/Overloads.hlsl new file mode 100644 index 0000000000000..5576eed5b5043 --- /dev/null +++ b/clang/test/CodeGenHLSL/groupsharedArgs/Overloads.hlsl @@ -0,0 +1,38 @@ +// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.0-compute -std=hlsl202x -emit-llvm -disable-llvm-passes -hlsl-entry main -o - %s | FileCheck %s + +// Verify we are calling the correct overloads +void fn(groupshared float4 Arr[2]); +void fn(inout float4 Arr[2]); + +void fn2(groupshared int4 Shared); +void fn2(int4 Local); + +[numthreads(4,1,1)] +void main() { + float4 Local[2] = {1.0.xxxx, 2.0.xxxx}; +// CHECK: call void @_Z2fnA2_Dv4_f + fn(Local); + +// CHECK: call void @_Z3fn2Dv4_i + fn2(11.xxxx); +} + +// CHECK-LABEL: define hidden void @_Z2fnA2_Dv4_f(ptr noalias noundef align 16 %Arr) +void fn(inout float4 Arr[2]) { + Arr[1] = 5.0.xxxx; +} + +// CHECK-LABEL: define hidden void @_Z3fn2Dv4_i(<4 x i32> noundef %Local) #0 { +void fn2(int4 Local) { + int X = Local.y; +} + +// CHECK-LABEL: define hidden void @_Z2fnRA2_U3AS3Dv4_f(ptr addrspace(3) noundef align 16 dereferenceable(32) %Arr) +void fn(groupshared float4 Arr[2]) { + Arr[1] = 7.0.xxxx; +} + +// CHECK-LABEL: define hidden void @_Z3fn2RU3AS3Dv4_i(ptr addrspace(3) noundef align 16 dereferenceable(16) %Shared) +void fn2(groupshared int4 Shared) { + Shared.x = 10; +} diff --git a/clang/test/CodeGenHLSL/groupsharedArgs/Scalartest.hlsl b/clang/test/CodeGenHLSL/groupsharedArgs/Scalartest.hlsl new file mode 100644 index 0000000000000..02303e449dd76 --- /dev/null +++ b/clang/test/CodeGenHLSL/groupsharedArgs/Scalartest.hlsl @@ -0,0 +1,18 @@ +// RUN: %clang_cc1 -finclude-default-header -fnative-half-type -fnative-int16-type -triple dxil-pc-shadermodel6.2-compute -std=hlsl202x -emit-llvm -disable-llvm-passes -hlsl-entry main -o - %s | FileCheck %s + +groupshared uint16_t SharedData; + +// CHECK-LABEL: define hidden void @_Z3fn1RU3AS3t(ptr addrspace(3) noundef align 2 dereferenceable(2) %Sh) +// CHECK: [[ShAddr:%.*]] = alloca ptr addrspace(3), align 4 +// CHECK: store ptr addrspace(3) %Sh, ptr [[ShAddr]], align 4 +// CHECK: [[A:%.*]] = load ptr addrspace(3), ptr [[ShAddr]], align 4 +// CHECK: store i16 5, ptr addrspace(3) [[A]], align 2 +// CHECK: ret void +void fn1(groupshared uint16_t Sh) { + Sh = 5; +} + +[numthreads(4, 1, 1)] +void main(uint3 TID : SV_GroupThreadID) { + fn1(SharedData); +} diff --git a/clang/test/CodeGenHLSL/groupsharedArgs/TemplateTest.hlsl b/clang/test/CodeGenHLSL/groupsharedArgs/TemplateTest.hlsl new file mode 100644 index 0000000000000..6989abadf4ca9 --- /dev/null +++ b/clang/test/CodeGenHLSL/groupsharedArgs/TemplateTest.hlsl @@ -0,0 +1,38 @@ +// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.3-compute -std=hlsl202x -emit-llvm -disable-llvm-passes -hlsl-entry main -o - %s | FileCheck %s + +// In the case the template type is specified the groupshared attribute is preserved in the type +// CHECK-LABEL: define linkonce_odr hidden void @_Z4tfooIU3AS3Dv4_iEvT_S2_(ptr addrspace(3) noundef align 16 dereferenceable(16) %a, ptr addrspace(3) noundef align 16 dereferenceable(16) %b) +// CHECK: [[AAddr:%.*]] = alloca ptr addrspace(3), align 4 +// CHECK: [[BAddr:%.*]] = alloca ptr addrspace(3), align 4 +// CHECK: store ptr addrspace(3) %a, ptr [[AAddr]], align 4 +// CHECK: store ptr addrspace(3) %b, ptr [[BAddr]], align 4 +// CHECK: [[C:%.*]] = load ptr addrspace(3), ptr [[BAddr]], align 4 +// CHECK: [[D:%.*]] = load <4 x i32>, ptr addrspace(3) [[C]], align 16 +// CHECK: [[E:%.*]] = load ptr addrspace(3), ptr [[AAddr]], align 4 +// CHECK: store <4 x i32> [[D]], ptr addrspace(3) [[E]], align 16 +// CHECK: ret void + +// In the case the template type is deduced the deduction is done on the non cv-qualified type (the address space is removed) +// So the non groupshared version of the function is deduced +// CHECK-LABEL: define linkonce_odr hidden void @_Z4tfooIDv4_iEvT_S1_(<4 x i32> noundef %a, <4 x i32> noundef %b) +// CHECK: [[AAddr:%.*]] = alloca <4 x i32>, align 16 +// CHECK: [[BAddr:%.*]] = alloca <4 x i32>, align 16 +// CHECK: store <4 x i32> %a, ptr [[AAddr]], align 16 +// CHECK: store <4 x i32> %b, ptr [[BAddr]], align 16 +// CHECK: [[C:%.*]] = load <4 x i32>, ptr [[BAddr]], align 16 +// CHECK: store <4 x i32> [[C]], ptr [[AAddr]], align 16 +// CHECK: ret void +template<typename T> +void tfoo(T a, T b) { + a = b; +} + +using ISF = groupshared int4; +ISF SharedData1; +ISF SharedData2; + +[numthreads(4, 1, 1)] +void main(uint3 TID : SV_GroupThreadID) { + tfoo<ISF>(SharedData1, SharedData2); + tfoo(SharedData1, SharedData2); +} diff --git a/clang/test/CodeGenHLSL/groupsharedArgs/VectorTest.hlsl b/clang/test/CodeGenHLSL/groupsharedArgs/VectorTest.hlsl new file mode 100644 index 0000000000000..e61f8d2cdf43b --- /dev/null +++ b/clang/test/CodeGenHLSL/groupsharedArgs/VectorTest.hlsl @@ -0,0 +1,22 @@ +// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.3-compute -std=hlsl202x -emit-llvm -disable-llvm-passes -hlsl-entry main -o - %s | FileCheck %s + +groupshared float4 SharedData; + +// CHECK-LABEL: define hidden void @_Z3fn1RU3AS3Dv4_f(ptr addrspace(3) noundef align 16 dereferenceable(16) %Sh) +// CHECK: [[ShAddr:%.*]] = alloca ptr addrspace(3), align 4 +// CHECK: [[Tmp:%.*]] = alloca <1 x float>, align 4 +// CHECK: store ptr addrspace(3) %Sh, ptr [[ShAddr]], align 4 +// CHECK: store <1 x float> splat (float 5.000000e+00), ptr [[Tmp]], align 4 +// CHECK: [[A:%.*]] = load <1 x float>, ptr [[Tmp]], align 4 +// CHECK: [[B:%.*]] = shufflevector <1 x float> [[A]], <1 x float> poison, <4 x i32> zeroinitializer +// CHECK: [[C:%.*]] = load ptr addrspace(3), ptr [[ShAddr]], align 4 +// CHECK: store <4 x float> [[B]], ptr addrspace(3) [[C]], align 16 +// CHECK: ret void +void fn1(groupshared float4 Sh) { + Sh = 5.0.xxxx; +} + +[numthreads(4, 1, 1)] +void main(uint3 TID : SV_GroupThreadID) { + fn1(SharedData); +} diff --git a/clang/test/SemaHLSL/Language/groupsharedArgs/ExplicitCast.hlsl b/clang/test/SemaHLSL/Language/groupsharedArgs/ExplicitCast.hlsl new file mode 100644 index 0000000000000..86e24f2aee550 --- /dev/null +++ b/clang/test/SemaHLSL/Language/groupsharedArgs/ExplicitCast.hlsl @@ -0,0 +1,13 @@ +// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -finclude-default-header -std=hlsl202x -fnative-half-type -fnative-int16-type -verify -Wconversion %s + +groupshared uint16_t SharedData; + +void fn1(groupshared half Sh) { +// expected-note@-1{{candidate function not viable: cannot bind reference in generic address space to object in address space 'groupshared' in 1st argument}} + Sh = 5; +} + +void fn2() { + fn1((half)SharedData); + // expected-error@-1{{no matching function for call to 'fn1'}} +} diff --git a/clang/test/SemaHLSL/Language/groupsharedArgs/ExportNoInlineTest.hlsl b/clang/test/SemaHLSL/Language/groupsharedArgs/ExportNoInlineTest.hlsl new file mode 100644 index 0000000000000..bdac2dc37ca20 --- /dev/null +++ b/clang/test/SemaHLSL/Language/groupsharedArgs/ExportNoInlineTest.hlsl @@ -0,0 +1,19 @@ +// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -finclude-default-header -std=hlsl202x -verify -Wconversion %s + +export void fn1(groupshared uint Sh) { +// expected-error@-1{{'export' attribute is not compatible with 'groupshared' parameter attribute}} + Sh = 5; +} + +__attribute__((noinline)) void fn2(groupshared uint Sh) { +// expected-error@-1{{'noinline' attribute is not compatible with 'groupshared' parameter attribute}} + Sh = 6; +} + +template<typename T> +void fn3(T A, T B) { + A = B; +} + +//export template void fn3<groupshared uint3>(groupshared uint3 A, groupshared uint3 B); +// //expected-error@-1{{'export' attribute is not compatible with 'groupshared' parameter attribute}} diff --git a/clang/test/SemaHLSL/Language/groupsharedArgs/InOut.hlsl b/clang/test/SemaHLSL/Language/groupsharedArgs/InOut.hlsl new file mode 100644 index 0000000000000..bf57b4b786260 --- /dev/null +++ b/clang/test/SemaHLSL/Language/groupsharedArgs/InOut.hlsl @@ -0,0 +1,74 @@ +// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -finclude-default-header -std=hlsl202x -verify -Wconversion %s + +groupshared uint SharedData; + +void fn1(inout uint Sh) { + Sh = 5; +} + +void fn2(inout groupshared uint Sh); +// expected-error@-1{{'inout' attribute is not compatible with 'groupshared' attribute}} +void fn3(in groupshared uint Sh); +// expected-error@-1{{'in' attribute is not compatible with 'groupshared' attribute}} +void fn4(out groupshared uint Sh); +// expected-error@-1{{'out' attribute is not compatible with 'groupshared' attribute}} +void fn5(groupshared inout uint Sh); +// expected-error@-1{{'inout' attribute is not compatible with 'groupshared' attribute}} +void fn6(groupshared in uint Sh); +// expected-error@-1{{'in' attribute is not compatible with 'groupshared' attribute}} +void fn7(groupshared out uint Sh); +// expected-error@-1{{'out' attribute is not compatible with 'groupshared' attribute}} + + +template<typename T> +void fn8(inout T A); +// expected-note@-1{{candidate template ignored: substitution failure [with T = groupshared uint]: 'inout' attribute is not compatible with 'groupshared' attribute}} + +template void fn8<groupshared uint>(inout groupshared uint A); +// expected-error@-1{{'inout' attribute is not compatible with 'groupshared' attribute}} +// expected-error@-2{{explicit instantiation of 'fn8' does not refer to a function template, variable template, member function, member class, or static data member}} + +template<typename T> +void fn9(out T A); +// expected-note@-1{{candidate template ignored: substitution failure [with T = groupshared uint]: 'out' attribute is not compatible with 'groupshared' attribute}} + +template void fn9<groupshared uint>(out groupshared uint A); +// expected-error@-1{{'out' attribute is not compatible with 'groupshared' attribute}} +// expected-error@-2{{explicit instantiation of 'fn9' does not refer to a function template, variable template, member function, member class, or static data member}} + +template<typename T> +void fn10(in T A); +// expected-note@-1{{candidate template ignored: substitution failure [with T = groupshared uint]: 'in' attribute is not compatible with 'groupshared' attribute}} + +template void fn10<groupshared uint>(in groupshared uint A); +// expected-error@-1{{'in' attribute is not compatible with 'groupshared' attribute}} +// expected-error@-2{{explicit instantiation of 'fn10' does not refer to a function template, variable template, member function, member class, or static data member}} + +// expected-note@+2{{candidate template ignored: substitution failure [with T = groupshared uint]: 'inout' attribute is not compatible with 'groupshared' attribute}} +template<typename T> +void fn11(inout T A, inout T B) { + A = B; +} +// expected-note@+2{{candidate template ignored: substitution failure [with T = groupshared uint]: 'out' attribute is not compatible with 'groupshared' attribute}} +template<typename T> +void fn12(out T A, out T B) { + A = B; +} + +// expected-note@+2{{candidate template ignored: substitution failure [with T = groupshared uint]: 'in' attribute is not compatible with 'groupshared' attribute}} +template<typename T> +void fn13(in T A, in T B) { + A = B; +} + +void fn0() { + fn1(SharedData); +// expected-warning@-1{{passing groupshared variable to a parameter annotated with inout. See 'groupshared' parameter annotation added in 202x}} + + fn11<groupshared uint>(SharedData, SharedData); +// expected-error@-1{{no matching function for call to 'fn11'}} + fn12<groupshared uint>(SharedData, SharedData); +// expected-error@-1{{no matching function for call to 'fn12'}} + fn13<groupshared uint>(SharedData, SharedData); +// expected-error@-1{{no matching function for call to 'fn13'}} +} diff --git a/clang/test/SemaHLSL/Language/groupsharedArgs/NotGroupSharedTest.hlsl b/clang/test/SemaHLSL/Language/groupsharedArgs/NotGroupSharedTest.hlsl new file mode 100644 index 0000000000000..4929f7bdce51a --- /dev/null +++ b/clang/test/SemaHLSL/Language/groupsharedArgs/NotGroupSharedTest.hlsl @@ -0,0 +1,13 @@ +// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-compute -finclude-default-header -std=hlsl202x -fnative-half-type -fnative-int16-type -verify -Wconversion %s + +void fn1(groupshared half Sh) { +// expected-note@-1{{candidate function not viable: cannot bind reference in generic address space to object in address space 'groupshared' in 1st argument}} + Sh = 5; +} + +[numthreads(4, 1, 1)] +void main(uint3 TID : SV_GroupThreadID) { + half tmp = 1.0; + fn1(tmp); + // expected-error@-1{{no matching function for call to 'fn1'}} +} diff --git a/clang/test/SemaHLSL/Language/groupsharedArgs/Pre202xWarning.hlsl b/clang/test/SemaHLSL/Language/groupsharedArgs/Pre202xWarning.hlsl new file mode 100644 index 0000000000000..ba9cee2611dcf --- /dev/null +++ b/clang/test/SemaHLSL/Language/groupsharedArgs/Pre202xWarning.hlsl @@ -0,0 +1,13 @@ +// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -finclude-default-header -std=hlsl2018 -verify -Wconversion %s + +groupshared uint SharedData; + +void fn1(groupshared uint Sh) { +// expected-warning@-1{{support for groupshared parameter annotation not added until HLSL 202x}} +// expected-warning@*{{support for HLSL language version hlsl2018 is incomplete, recommend using hlsl202x instead}} + Sh = 5; +} + +void fn2() { + fn1(SharedData); +} diff --git a/clang/test/SemaHLSL/Language/groupsharedArgs/ScalarTest.hlsl b/clang/test/SemaHLSL/Language/groupsharedArgs/ScalarTest.hlsl new file mode 100644 index 0000000000000..b9f093c7cc825 --- /dev/null +++ b/clang/test/SemaHLSL/Language/groupsharedArgs/ScalarTest.hlsl @@ -0,0 +1,13 @@ +// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -finclude-default-header -std=hlsl202x -fnative-half-type -fnative-int16-type -verify -Wconversion %s + +groupshared uint16_t SharedData; + +void fn1(groupshared half Sh) { +// expected-note@-1{{candidate function not viable: no known conversion from 'groupshared uint16_t' (aka 'groupshared unsigned short') to 'groupshared half &' for 1st argument}} + Sh = 5; +} + +void fn2() { + fn1(SharedData); + // expected-error@-1{{no matching function for call to 'fn1'}} +} diff --git a/clang/test/SemaHLSL/group_shared.hlsl b/clang/test/SemaHLSL/group_shared.hlsl index 0293ddd15eeb9..4df6cf73c4fc0 100644 --- a/clang/test/SemaHLSL/group_shared.hlsl +++ b/clang/test/SemaHLSL/group_shared.hlsl @@ -48,12 +48,7 @@ static groupshared float g; }; - // expected-error@+1 {{parameter may not be qualified with an address space}} - float foo2(groupshared float a) { - return a; - } - -// expected-note@+2 {{parameter may not be qualified with an address space}} +// expected-note@+2 {{candidate template ignored: substitution failure [with T = GSF]}} template<typename T> T tfoo(T t) { return t; @@ -67,8 +62,7 @@ template<typename T> // it is caused by return type check is after pointer check which is acceptable. // expected-error@+1 {{pointers are unsupported in HLSL}} groupshared void (*fp)(); -// expected-error@+2 {{pointers are unsupported in HLSL}} -// expected-error@+1 {{parameter may not be qualified with an address space}} +// expected-error@+1 {{pointers are unsupported in HLSL}} void (*fp2)(groupshared float); // NOTE: HLSL not support trailing return types. // expected-warning@#func{{'auto' type specifier is a HLSL 202y extension}} @@ -102,5 +96,4 @@ _Static_assert(S3<groupshared float>::value, ""); // Can you overload based on the qualifier? void func(float f) {} -// expected-error@+1 {{parameter may not be qualified with an address space}} void func(groupshared float f) {} diff --git a/clang/test/SemaHLSL/group_shared_202x.hlsl b/clang/test/SemaHLSL/group_shared_202x.hlsl index 7ebc717384e94..b9e84202e637e 100644 --- a/clang/test/SemaHLSL/group_shared_202x.hlsl +++ b/clang/test/SemaHLSL/group_shared_202x.hlsl @@ -11,11 +11,8 @@ // expected-error@#func {{return type cannot be qualified with address space}} auto func() -> groupshared void; // #func -// expected-error@#func_gs {{parameter may not be qualified with an address space}} auto func(float groupshared) -> void; // #func_gs - -// expected-error@#l {{parameter may not be qualified with an address space}} // expected-warning@#l {{lambdas are a clang HLSL extension}} auto l = [](groupshared float ) {}; // #l >From b507cd7ee3bdf167d44120c0f44450aa42978e6a Mon Sep 17 00:00:00 2001 From: Sarah Spall <[email protected]> Date: Fri, 20 Feb 2026 08:50:16 -0800 Subject: [PATCH 2/2] self review --- clang/lib/AST/ASTContext.cpp | 2 +- clang/test/CodeGenHLSL/groupsharedArgs/MatrixTest.hlsl | 5 ++--- .../SemaHLSL/Language/groupsharedArgs/ExplicitCast.hlsl | 9 +++++++++ .../Language/groupsharedArgs/ExportNoInlineTest.hlsl | 3 --- .../Language/groupsharedArgs/Pre202xWarning.hlsl | 9 +++++++++ .../SemaHLSL/Language/groupsharedArgs/ScalarTest.hlsl | 9 +++++++++ 6 files changed, 30 insertions(+), 7 deletions(-) diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index 43f3a4278fc39..eb6e028989ad5 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -7949,7 +7949,7 @@ const ArrayType *ASTContext::getAsArrayType(QualType T) const { } QualType ASTContext::getAdjustedParameterType(QualType T) const { - if (getLangOpts().HLSL && T.getAddressSpace() != LangAS::Default) + if (getLangOpts().HLSL && T.getAddressSpace() == LangAS::hlsl_groupshared) return getLValueReferenceType(T); if (getLangOpts().HLSL && T->isConstantArrayType()) return getArrayParameterType(T); diff --git a/clang/test/CodeGenHLSL/groupsharedArgs/MatrixTest.hlsl b/clang/test/CodeGenHLSL/groupsharedArgs/MatrixTest.hlsl index b33e2f2d71185..584ffeeaa646a 100644 --- a/clang/test/CodeGenHLSL/groupsharedArgs/MatrixTest.hlsl +++ b/clang/test/CodeGenHLSL/groupsharedArgs/MatrixTest.hlsl @@ -6,9 +6,8 @@ groupshared float4x4 SharedData; // CHECK: [[ShAddr:%.*]] = alloca ptr addrspace(3), align 4 // CHECK: store ptr addrspace(3) %Sh, ptr [[ShAddr]], align 4 // CHECK: [[A:%.*]] = load ptr addrspace(3), ptr [[ShAddr]], align 4 -// CHECK: [[B:%.*]] = load <16 x float>, ptr addrspace(3) [[A]], align 4 -// CHECK: [[Matins:%.*]] = insertelement <16 x float> [[B]], float 5.000000e+00, i32 4 -// CHECK: store <16 x float> [[Matins]], ptr addrspace(3) [[A]], align 4 +// CHECK: [[B:%.*]] = getelementptr <16 x float>, ptr addrspace(3) [[A]], i32 0, i32 4 +// CHECK: store float 5.000000e+00, ptr addrspace(3) [[B]], align 4 // CHECK: ret void void fn1(groupshared float4x4 Sh) { Sh[0][1] = 5.0; diff --git a/clang/test/SemaHLSL/Language/groupsharedArgs/ExplicitCast.hlsl b/clang/test/SemaHLSL/Language/groupsharedArgs/ExplicitCast.hlsl index 86e24f2aee550..bd125f8eb639b 100644 --- a/clang/test/SemaHLSL/Language/groupsharedArgs/ExplicitCast.hlsl +++ b/clang/test/SemaHLSL/Language/groupsharedArgs/ExplicitCast.hlsl @@ -7,7 +7,16 @@ void fn1(groupshared half Sh) { Sh = 5; } +template<typename T> +void fnT(T A, T B) { +// expected-note@-1{{candidate function template not viable: cannot bind reference in generic address space to object in address space 'groupshared' in 1st argument}} + A = B; +} + void fn2() { fn1((half)SharedData); // expected-error@-1{{no matching function for call to 'fn1'}} + // not sure why someone would do this but want to make sure templates do something sane + fnT<groupshared half>((half)SharedData, (half)SharedData); + // expected-error@-1{{no matching function for call to 'fnT'}} } diff --git a/clang/test/SemaHLSL/Language/groupsharedArgs/ExportNoInlineTest.hlsl b/clang/test/SemaHLSL/Language/groupsharedArgs/ExportNoInlineTest.hlsl index bdac2dc37ca20..d29638b7f3c25 100644 --- a/clang/test/SemaHLSL/Language/groupsharedArgs/ExportNoInlineTest.hlsl +++ b/clang/test/SemaHLSL/Language/groupsharedArgs/ExportNoInlineTest.hlsl @@ -14,6 +14,3 @@ template<typename T> void fn3(T A, T B) { A = B; } - -//export template void fn3<groupshared uint3>(groupshared uint3 A, groupshared uint3 B); -// //expected-error@-1{{'export' attribute is not compatible with 'groupshared' parameter attribute}} diff --git a/clang/test/SemaHLSL/Language/groupsharedArgs/Pre202xWarning.hlsl b/clang/test/SemaHLSL/Language/groupsharedArgs/Pre202xWarning.hlsl index ba9cee2611dcf..24b2bdd3dbe76 100644 --- a/clang/test/SemaHLSL/Language/groupsharedArgs/Pre202xWarning.hlsl +++ b/clang/test/SemaHLSL/Language/groupsharedArgs/Pre202xWarning.hlsl @@ -8,6 +8,15 @@ void fn1(groupshared uint Sh) { Sh = 5; } +template<typename T> +void fnT(T A, T B) { + A = B; +} + +template void fnT<groupshared int>(groupshared int A, groupshared int B); +// expected-warning@-1{{support for groupshared parameter annotation not added until HLSL 202x}} +// expected-warning@-2{{support for groupshared parameter annotation not added until HLSL 202x}} + void fn2() { fn1(SharedData); } diff --git a/clang/test/SemaHLSL/Language/groupsharedArgs/ScalarTest.hlsl b/clang/test/SemaHLSL/Language/groupsharedArgs/ScalarTest.hlsl index b9f093c7cc825..7597004f62eeb 100644 --- a/clang/test/SemaHLSL/Language/groupsharedArgs/ScalarTest.hlsl +++ b/clang/test/SemaHLSL/Language/groupsharedArgs/ScalarTest.hlsl @@ -7,7 +7,16 @@ void fn1(groupshared half Sh) { Sh = 5; } +template<typename T> +void fnT(T A, T B) { +// expected-note@-1{{candidate function template not viable: no known conversion from 'groupshared uint16_t' (aka 'groupshared unsigned short') to 'groupshared half &' for 1st argument}} + A = B; +} + void fn2() { fn1(SharedData); // expected-error@-1{{no matching function for call to 'fn1'}} + // not sure why anyone would do thats but just making sure templates are sane + fnT<groupshared half>(SharedData, SharedData); + // expected-error@-1{{no matching function for call to 'fnT'}} } _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
