diff --git a/lib/HLSL/HLLegalizeParameter.cpp b/lib/HLSL/HLLegalizeParameter.cpp index 141f163e15..22fc05d6b6 100644 --- a/lib/HLSL/HLLegalizeParameter.cpp +++ b/lib/HLSL/HLLegalizeParameter.cpp @@ -256,7 +256,8 @@ bool HLLegalizeParameter::runOnModule(Module &M) { continue; for (Argument &Arg : F.args()) { - if (!Arg.getType()->isPointerTy()) + Type *PtrTy = dyn_cast(Arg.getType()); + if (!PtrTy || 0 != PtrTy->getPointerAddressSpace()) continue; Type *EltTy = dxilutil::GetArrayEltTy(Arg.getType()); if (dxilutil::IsHLSLObjectType(EltTy) || diff --git a/tools/clang/include/clang/AST/Decl.h b/tools/clang/include/clang/AST/Decl.h index 985ad895ab..917eae3299 100644 --- a/tools/clang/include/clang/AST/Decl.h +++ b/tools/clang/include/clang/AST/Decl.h @@ -1458,6 +1458,8 @@ class ParmVarDecl : public VarDecl { void setModifierOut(bool value) { ParmVarDeclBits.IsModifierOut = value; } /// Synthesize a ParameterModifier value for this parameter. hlsl::ParameterModifier getParamModifiers() const { + if (!isModifierIn() && !isModifierOut()) + return hlsl::ParameterModifier(hlsl::ParameterModifier::Kind::Ref); if (isModifierIn() && !isModifierOut()) return hlsl::ParameterModifier(hlsl::ParameterModifier::Kind::In); if (isModifierIn() && isModifierOut()) diff --git a/tools/clang/include/clang/Basic/DiagnosticSemaKinds.td b/tools/clang/include/clang/Basic/DiagnosticSemaKinds.td index 34a2195cbc..be12208111 100644 --- a/tools/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/tools/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -1597,6 +1597,13 @@ def warn_hlsl_sometimes_uninit_out_param : Warning< "its declaration is reached|" "%3 is called}2">, InGroup; +def warn_hlsl_groupshared_202x: Warning< + "Support for groupshared parameter annotation not added until HLSL 202x">, + InGroup; +def warn_hlsl_groupshared_inout: Warning< + "Passing groupshared variable to a parameter annotated with inout. See" + "'groupshared' parameter annotation added in 202x.">, + InGroup; // HLSL Change End - Add warning for uninitialized out param def warn_maybe_uninit_var : Warning< "variable %0 may be uninitialized when " diff --git a/tools/clang/lib/AST/HlslTypes.cpp b/tools/clang/lib/AST/HlslTypes.cpp index 00c18a81a9..530fd79019 100644 --- a/tools/clang/lib/AST/HlslTypes.cpp +++ b/tools/clang/lib/AST/HlslTypes.cpp @@ -292,6 +292,9 @@ bool HasHLSLReorderCoherent(clang::QualType type) { return false; } +/// Checks whether the pAttributes indicate a parameter is groupshared +bool IsParamAttributedAsGroupShared(clang::AttributeList *pAttributes); + /// Checks whether the pAttributes indicate a parameter is inout or out; if /// inout, pIsIn will be set to true. bool IsParamAttributedAsOut(clang::AttributeList *pAttributes, bool *pIsIn); @@ -934,6 +937,19 @@ unsigned GetHLSLOutputPatchCount(QualType type) { return argList[1].getAsIntegral().getLimitedValue(); } +bool IsParamAttributedAsGroupShared(clang::AttributeList *pAttributes) { + while (pAttributes != nullptr) { + switch (pAttributes->getKind()) { + case AttributeList::AT_HLSLGroupShared: + return true; + default: + break; + } + pAttributes = pAttributes->getNext(); + } + return false; +} + bool IsParamAttributedAsOut(clang::AttributeList *pAttributes, bool *pIsIn) { bool anyFound = false; bool inFound = false; @@ -967,6 +983,8 @@ bool IsParamAttributedAsOut(clang::AttributeList *pAttributes, bool *pIsIn) { hlsl::ParameterModifier ParamModFromAttributeList(clang::AttributeList *pAttributes) { + if (IsParamAttributedAsGroupShared(pAttributes)) + return ParameterModifier(hlsl::ParameterModifier::Kind::Ref); bool isIn, isOut; isOut = IsParamAttributedAsOut(pAttributes, &isIn); return ParameterModifier::FromInOut(isIn, isOut); diff --git a/tools/clang/lib/AST/MicrosoftMangle.cpp b/tools/clang/lib/AST/MicrosoftMangle.cpp index ae9f1cd7f8..66f4c9113a 100644 --- a/tools/clang/lib/AST/MicrosoftMangle.cpp +++ b/tools/clang/lib/AST/MicrosoftMangle.cpp @@ -2033,6 +2033,8 @@ void MicrosoftCXXNameMangler::mangleType(const LValueReferenceType *T, Qualifiers Quals, SourceRange Range) { QualType PointeeType = T->getPointeeType(); Out << (Quals.hasVolatile() ? 'B' : 'A'); + if (PointeeType.getQualifiers().getAddressSpace() == 3) + Out << 'G'; manglePointerExtQualifiers(Quals, PointeeType); mangleType(PointeeType, Range); } diff --git a/tools/clang/lib/CodeGen/CGHLSLMS.cpp b/tools/clang/lib/CodeGen/CGHLSLMS.cpp index 6c68381a20..1e8bd32702 100644 --- a/tools/clang/lib/CodeGen/CGHLSLMS.cpp +++ b/tools/clang/lib/CodeGen/CGHLSLMS.cpp @@ -1309,6 +1309,14 @@ unsigned CGMSHLSLRuntime::AddTypeAnnotation(QualType Ty, const IncompleteArrayType *arrayTy = CGM.getContext().getAsIncompleteArrayType(Ty); arrayElementTy = arrayTy->getElementType(); + } else if (paramTy->isConstantArrayType()) { + // hacky because unclear proper usage of paramTy vs Ty... + const ConstantArrayType *arrayTy = + CGM.getContext().getAsConstantArrayType(paramTy); + DXASSERT(arrayTy != nullptr, "Must be array type here"); + + arraySize = arrayTy->getSize().getLimitedValue(); + arrayElementTy = arrayTy->getElementType(); } else { DXASSERT(0, "Must array type here"); } @@ -6232,7 +6240,8 @@ void CGMSHLSLRuntime::EmitHLSLOutParamConversionInit( } } else if (isAggregateType) { // aggregate in-only - emit RValue, unless LValueToRValue cast - EmitRValueAgg = true; + if (Param->isModifierIn()) + EmitRValueAgg = true; if (const ImplicitCastExpr *cast = dyn_cast(Arg)) { if (cast->getCastKind() == CastKind::CK_LValueToRValue) { EmitRValueAgg = false; diff --git a/tools/clang/lib/Sema/SemaDeclAttr.cpp b/tools/clang/lib/Sema/SemaDeclAttr.cpp index 085874a0ed..8a45e56c2b 100644 --- a/tools/clang/lib/Sema/SemaDeclAttr.cpp +++ b/tools/clang/lib/Sema/SemaDeclAttr.cpp @@ -4945,6 +4945,12 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, handleSimpleAttribute(S, D, Attr); break; case AttributeList::AT_NoInline: + if (S.LangOpts.HLSL) { + bool Handled = false; + hlsl::HandleDeclAttributeForHLSL(S, D, Attr, Handled); + if (Handled) + break; + } handleSimpleAttribute(S, D, Attr); break; case AttributeList::AT_NoInstrumentFunction: // Interacts with -pg. diff --git a/tools/clang/lib/Sema/SemaHLSL.cpp b/tools/clang/lib/Sema/SemaHLSL.cpp index e9c8c90a2d..bb00635c1d 100644 --- a/tools/clang/lib/Sema/SemaHLSL.cpp +++ b/tools/clang/lib/Sema/SemaHLSL.cpp @@ -14474,6 +14474,27 @@ void Sema::DiagnoseHLSLDeclAttr(const Decl *D, const Attr *A) { HLSLExternalSource *ExtSource = HLSLExternalSource::FromSema(this); const bool IsGCAttr = isa(A); const bool IsRCAttr = isa(A); + const bool IsExportAttr = isa(A); + const bool IsNoInlineAttr = isa(A); + if (IsExportAttr || IsNoInlineAttr) { + if (const FunctionDecl *FD = dyn_cast(D)) { + for (ParmVarDecl *PVD : FD->parameters()) { + if (!PVD->hasAttrs()) + continue; + for (Attr *A : PVD->getAttrs()) { + switch (A->getKind()) { + case clang::attr::HLSLGroupShared: { // todo improve this error msg + Diag(A->getLocation(), diag::err_hlsl_varmodifiersna) + << "groupshared" << "export/noinline" << "parameter"; + return; + break; + } + } + } + } + return; + } + } if (IsGCAttr || IsRCAttr) { const ValueDecl *TD = cast(D); if (TD->getType()->isDependentType()) @@ -14655,6 +14676,8 @@ void hlsl::HandleDeclAttributeForHLSL(Sema &S, Decl *D, const AttributeList &A, VD->setType( S.Context.getAddrSpaceQualType(VD->getType(), DXIL::kTGSMAddrSpace)); } + if (ParmVarDecl *VD = dyn_cast(D)) + VD->setType(S.Context.getLValueReferenceType(VD->getType())); break; case AttributeList::AT_HLSLUniform: declAttr = ::new (S.Context) HLSLUniformAttr( @@ -14996,6 +15019,7 @@ void hlsl::HandleDeclAttributeForHLSL(Sema &S, Decl *D, const AttributeList &A, } if (declAttr != nullptr) { + S.DiagnoseHLSLDeclAttr(D, declAttr); DXASSERT_NOMSG(Handled); D->addAttr(declAttr); @@ -15749,7 +15773,14 @@ bool Sema::DiagnoseHLSLDecl(Declarator &D, DeclContext *DC, Expr *BitWidth, break; case AttributeList::AT_HLSLGroupShared: isGroupShared = true; - if (!isGlobal) { + if (isParameter && getLangOpts().HLSLVersion < hlsl::LangStd::v202x) + Diag(pAttr->getLoc(), diag::warn_hlsl_groupshared_202x); + if (isParameter && (usageIn || usageOut)) { + Diag(pAttr->getLoc(), diag::err_hlsl_varmodifiersna) + << pAttr->getName() << "in/out/inout modifiers" << declarationType; + result = false; + } + if (!(isGlobal || isParameter)) { Diag(pAttr->getLoc(), diag::err_hlsl_varmodifierna) << pAttr->getName() << declarationType << pAttr->getRange(); result = false; @@ -15786,6 +15817,10 @@ bool Sema::DiagnoseHLSLDecl(Declarator &D, DeclContext *DC, Expr *BitWidth, Diag(pAttr->getLoc(), diag::err_hlsl_usage_not_on_parameter) << pAttr->getName() << pAttr->getRange(); result = false; + } else if (isGroupShared) { + Diag(pAttr->getLoc(), diag::err_hlsl_varmodifiersna) + << pAttr->getName() << "groupshared" << declarationType; + result = false; } if (!IsUsageAttributeCompatible(pAttr->getKind(), usageIn, usageOut)) { Diag(pAttr->getLoc(), diag::err_hlsl_duplicate_parameter_usages) diff --git a/tools/clang/lib/Sema/SemaOverload.cpp b/tools/clang/lib/Sema/SemaOverload.cpp index 274b66646b..210109396c 100644 --- a/tools/clang/lib/Sema/SemaOverload.cpp +++ b/tools/clang/lib/Sema/SemaOverload.cpp @@ -4953,6 +4953,26 @@ InitCallParamConversions(Sema &S, const FunctionProtoType *Proto, ImplicitConversionSequence &OutConversion) { hlsl::ParameterModifier paramMods = Proto->getParamMods()[ArgIdx]; QualType ParamType = Proto->getParamType(ArgIdx); + + // must be a Ref; don't allow any conversions + if (!(paramMods.isAnyIn() || paramMods.isAnyOut())) { + if (!S.getASTContext().hasSameUnqualifiedType( + ParamType.getNonReferenceType(), Arg->getType()) || + Arg->getType().getQualifiers().getAddressSpace() != + hlsl::DXIL::kTGSMAddrSpace) { + InConversion.setBad(BadConversionSequence::no_conversion, Arg->getType(), + ParamType); + InConversion.Bad.FromExpr = Arg; // hack for now + return; + } + } + + if (S.getLangOpts().HLSLVersion >= hlsl::LangStd::v202x && + paramMods.isAnyIn() && paramMods.isAnyOut() && + Arg->getType().getQualifiers().getAddressSpace() == + hlsl::DXIL::kTGSMAddrSpace) + S.Diag(Arg->getLocStart(), diag::warn_hlsl_groupshared_inout); + if (paramMods.isAnyIn()) { InConversion = TryCopyInitialization(S, Arg, ParamType, SuppressUserConversions, diff --git a/tools/clang/test/CodeGenHLSL/groupsharedArgs/ArrTest.hlsl b/tools/clang/test/CodeGenHLSL/groupsharedArgs/ArrTest.hlsl new file mode 100644 index 0000000000..f4bfd02570 --- /dev/null +++ b/tools/clang/test/CodeGenHLSL/groupsharedArgs/ArrTest.hlsl @@ -0,0 +1,16 @@ +// RUN: %dxc -E main -T cs_6_0 -HV 202x -fcgl %s | FileCheck %s + +groupshared float4 SharedArr[64]; + +// CHECK-LABEL: define internal void @"\01?fn@@YAXAGAY0EA@$$CAV?$vector@M$03@@M@Z"([64 x <4 x float>] addrspace(3)* dereferenceable(1024) %Arr, float %F) +// CHECK: [[ArrIdx:%.*]] = getelementptr inbounds [64 x <4 x float>], [64 x <4 x float>] addrspace(3)* %Arr, i32 0, i32 5 +// CHECK-NEXT: store <4 x float> {{.*}}, <4 x float> addrspace(3)* [[ArrIdx]], align 4 +void fn(groupshared float4 Arr[64], float F) { + float4 tmp = F.xxxx; + Arr[5] = tmp; +} + +[numthreads(4,1,1)] +void main() { + fn(SharedArr, 6.0); +} diff --git a/tools/clang/test/CodeGenHLSL/groupsharedArgs/Overloads.hlsl b/tools/clang/test/CodeGenHLSL/groupsharedArgs/Overloads.hlsl new file mode 100644 index 0000000000..dcb06762d6 --- /dev/null +++ b/tools/clang/test/CodeGenHLSL/groupsharedArgs/Overloads.hlsl @@ -0,0 +1,37 @@ +// RUN: %dxc -E main -T cs_6_0 -HV 202x -fcgl %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); + +// CHECK-LABEL: define void @main() +[numthreads(4,1,1)] +void main() { + float4 Local[2] = {1.0.xxxx, 2.0.xxxx}; +// CHECK-DAG: call void @"\01?fn@@YAXY01$$CAV?$vector@M$03@@@Z"([2 x <4 x float>]* %Local) + fn(Local); + +// CHECK-DAG: call void @"\01?fn2@@YAXV?$vector@H$03@@@Z"(<4 x i32> + fn2(11.xxxx); +} + +void fn(groupshared float4 Arr[2]) { + Arr[1] = 7.0.xxxx; +} + +// CHECK-LABEL: define internal void @"\01?fn@@YAXY01$$CAV?$vector@M$03@@@Z"([2 x <4 x float>]* noalias %Arr) +void fn(inout float4 Arr[2]) { + Arr[1] = 5.0.xxxx; +} + +void fn2(groupshared int4 Shared) { + Shared.x = 10; +} + +// CHECK-DAG: define internal void @"\01?fn2@@YAXV?$vector@H$03@@@Z"(<4 x i32> %Local) +void fn2(int4 Local) { + int X = Local.y; +} diff --git a/tools/clang/test/CodeGenHLSL/groupsharedArgs/ScalarTest.hlsl b/tools/clang/test/CodeGenHLSL/groupsharedArgs/ScalarTest.hlsl new file mode 100644 index 0000000000..5fb170a15e --- /dev/null +++ b/tools/clang/test/CodeGenHLSL/groupsharedArgs/ScalarTest.hlsl @@ -0,0 +1,15 @@ +// RUN: %dxc -E main -T cs_6_2 -enable-16bit-types -HV 202x -fcgl %s | FileCheck %s + +groupshared uint16_t SharedData; + +// mangling changes added the first G +// CHECK-LABEL: @"\01?fn1@@YAXAGAG@Z" +// CHECK: store i16 5, i16 addrspace(3)* %Sh, align 4 +void fn1(groupshared uint16_t Sh) { + Sh = 5; +} + +[numthreads(4, 1, 1)] +void main(uint3 TID : SV_GroupThreadID) { + fn1(SharedData); +} diff --git a/tools/clang/test/CodeGenHLSL/groupsharedArgs/StructTest.hlsl b/tools/clang/test/CodeGenHLSL/groupsharedArgs/StructTest.hlsl new file mode 100644 index 0000000000..d5ec94bed6 --- /dev/null +++ b/tools/clang/test/CodeGenHLSL/groupsharedArgs/StructTest.hlsl @@ -0,0 +1,32 @@ +// RUN: %dxc -E main -T cs_6_3 -HV 202x -fcgl %s | FileCheck %s + +struct Shared { + int A; + float F; + double Arr[4]; +}; + +groupshared Shared SharedData; + +// CHECK-LABEL: @"\01?fn1@@YAXAGAUShared@@@Z" +// CHECK: [[D:%.*]] = alloca double, align 8 +// CHECK: [[A:%.*]] = getelementptr inbounds %struct.Shared, %struct.Shared addrspace(3)* %Sh, i32 0, i32 0 +// CHECK: store i32 10, i32 addrspace(3)* [[A]], align 4 +// CHECK: [[F:%.*]] = getelementptr inbounds %struct.Shared, %struct.Shared addrspace(3)* %Sh, i32 0, i32 1 +// CHECK: store float 0x40263851E0000000, float addrspace(3)* %F, align 4 +// CHECK: store double 1.000000e+01, double* [[D]], align 8 +// CHECK: [[Z:%.*]] = load double, double* [[D]], align 8 +// CHECK: [[Arr:%.*]] = getelementptr inbounds %struct.Shared, %struct.Shared addrspace(3)* %Sh, i32 0, i32 2 +// CHECK: [[ArrIdx:%.*]] = getelementptr inbounds [4 x double], [4 x double] addrspace(3)* [[Arr]], i32 0, i32 1 +// CHECK: store double [[Z]], double addrspace(3)* [[ArrIdx]], align 4 +void fn1(groupshared Shared Sh) { + Sh.A = 10; + Sh.F = 11.11; + double D = 10.0; + Sh.Arr[1] = D; +} + +[numthreads(4, 1, 1)] +void main(uint3 TID : SV_GroupThreadID) { + fn1(SharedData); +} diff --git a/tools/clang/test/CodeGenHLSL/groupsharedArgs/TemplateTest.hlsl b/tools/clang/test/CodeGenHLSL/groupsharedArgs/TemplateTest.hlsl new file mode 100644 index 0000000000..48a615a196 --- /dev/null +++ b/tools/clang/test/CodeGenHLSL/groupsharedArgs/TemplateTest.hlsl @@ -0,0 +1,32 @@ +// RUN: %dxc -E main -T cs_6_3 -HV 202x -fcgl %s | FileCheck %s + +template struct Shared { + T A; + float F; + double Arr[4]; +}; + +groupshared Shared SharedData; + +// CHECK-LABEL: @"\01?fn1@@YAXAGAU?$Shared@H@@@Z" +// CHECK: [[D:%.*]] = alloca double, align 8 +// CHECK: [[A:%.*]] = getelementptr inbounds %"struct.Shared", %"struct.Shared" addrspace(3)* %Sh, i32 0, i32 0 +// CHECK: store i32 10, i32 addrspace(3)* [[A]], align 4 +// CHECK: [[F:%.*]] = getelementptr inbounds %"struct.Shared", %"struct.Shared" addrspace(3)* %Sh, i32 0, i32 1 +// CHECK: store float 0x40263851E0000000, float addrspace(3)* %F, align 4 +// CHECK: store double 1.000000e+01, double* [[D]], align 8 +// CHECK: [[Z:%.*]] = load double, double* [[D]], align 8 +// CHECK: [[Arr:%.*]] = getelementptr inbounds %"struct.Shared", %"struct.Shared" addrspace(3)* %Sh, i32 0, i32 2 +// CHECK: [[ArrIdx:%.*]] = getelementptr inbounds [4 x double], [4 x double] addrspace(3)* [[Arr]], i32 0, i32 1 +// CHECK: store double [[Z]], double addrspace(3)* [[ArrIdx]], align 4 +void fn1(groupshared Shared Sh) { + Sh.A = 10; + Sh.F = 11.11; + double D = 10.0; + Sh.Arr[1] = D; +} + +[numthreads(4, 1, 1)] +void main(uint3 TID : SV_GroupThreadID) { + fn1(SharedData); +} diff --git a/tools/clang/test/CodeGenHLSL/groupsharedArgs/VectorTest.hlsl b/tools/clang/test/CodeGenHLSL/groupsharedArgs/VectorTest.hlsl new file mode 100644 index 0000000000..d34d4aa421 --- /dev/null +++ b/tools/clang/test/CodeGenHLSL/groupsharedArgs/VectorTest.hlsl @@ -0,0 +1,18 @@ +// RUN: %dxc -E main -T cs_6_3 -HV 202x -fcgl %s | FileCheck %s + +groupshared float4 SharedData; + +// CHECK-LABEL: @"\01?fn1@@YAXAGAV?$vector@M$03@@@Z" +// CHECK: [[Tmp:%.*]] = alloca <1 x float>, align 4 +// CHECK: store <1 x float> , <1 x float>* [[Tmp]] +// CHECK: [[Z:%.*]] = load <1 x float>, <1 x float>* [[Tmp]] +// CHECK: [[Y:%.*]] = shufflevector <1 x float> [[Z]], <1 x float> undef, <4 x i32> zeroinitializer +// CHECK: store <4 x float> [[Y]], <4 x float> addrspace(3)* %Sh, align 4 +void fn1(groupshared float4 Sh) { + Sh = 5.0.xxxx; +} + +[numthreads(4, 1, 1)] +void main(uint3 TID : SV_GroupThreadID) { + fn1(SharedData); +} diff --git a/tools/clang/test/SemaHLSL/v202x/groupshared/ExplicitCast.hlsl b/tools/clang/test/SemaHLSL/v202x/groupshared/ExplicitCast.hlsl new file mode 100644 index 0000000000..55652e1866 --- /dev/null +++ b/tools/clang/test/SemaHLSL/v202x/groupshared/ExplicitCast.hlsl @@ -0,0 +1,13 @@ +// RUN: %dxc -T lib_6_3 -enable-16bit-types -HV 202x -verify %s + +groupshared uint16_t SharedData; + +void fn1(groupshared half Sh) { +// expected-note@-1{{candidate function not viable: 1st argument ('half') is in address space 0, but parameter must be in address space 3}} + Sh = 5; +} + +void fn2() { + fn1((half)SharedData); + // expected-error@-1{{no matching function for call to 'fn1'}} +} diff --git a/tools/clang/test/SemaHLSL/v202x/groupshared/ExportNoInlineTest.hlsl b/tools/clang/test/SemaHLSL/v202x/groupshared/ExportNoInlineTest.hlsl new file mode 100644 index 0000000000..56f8042491 --- /dev/null +++ b/tools/clang/test/SemaHLSL/v202x/groupshared/ExportNoInlineTest.hlsl @@ -0,0 +1,11 @@ +// RUN: %dxc -T lib_6_3 -HV 202x -verify %s + +export void fn1(groupshared uint Sh) { +// expected-error@-1{{groupshared and export/noinline cannot be used together for a parameter}} + Sh = 5; +} + +[noinline] void fn2(groupshared uint Sh) { +// expected-error@-1{{groupshared and export/noinline cannot be used together for a parameter}} + Sh = 6; +} diff --git a/tools/clang/test/SemaHLSL/v202x/groupshared/InOutWarning.hlsl b/tools/clang/test/SemaHLSL/v202x/groupshared/InOutWarning.hlsl new file mode 100644 index 0000000000..9df686e643 --- /dev/null +++ b/tools/clang/test/SemaHLSL/v202x/groupshared/InOutWarning.hlsl @@ -0,0 +1,12 @@ +// RUN: %dxc -T lib_6_3 -HV 202x -verify %s + +groupshared uint SharedData; + +void fn1(inout uint Sh) { + Sh = 5; +} + +void fn2() { + fn1(SharedData); +// expected-warning@-1{{assing groupshared variable to a parameter annotated with inout. See'groupshared' parameter annotation added in 202x}} +} diff --git a/tools/clang/test/SemaHLSL/v202x/groupshared/NotGroupSharedTest.hlsl b/tools/clang/test/SemaHLSL/v202x/groupshared/NotGroupSharedTest.hlsl new file mode 100644 index 0000000000..229141eb0c --- /dev/null +++ b/tools/clang/test/SemaHLSL/v202x/groupshared/NotGroupSharedTest.hlsl @@ -0,0 +1,18 @@ +// RUN: %dxc -T cs_6_3 -enable-16bit-types -HV 202x -verify %s + +RWStructuredBuffer Out : register(u0); + +groupshared uint16_t SharedData; + +void fn1(groupshared half Sh) { +// expected-note@-1{{candidate function not viable: 1st argument ('half') is in address space 0, but parameter must be in address space}} + 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'}} + Out[TID.x] = (uint4) SharedData.xxxx; +} diff --git a/tools/clang/test/SemaHLSL/v202x/groupshared/Pre202xWarning.hlsl b/tools/clang/test/SemaHLSL/v202x/groupshared/Pre202xWarning.hlsl new file mode 100644 index 0000000000..1382be09a5 --- /dev/null +++ b/tools/clang/test/SemaHLSL/v202x/groupshared/Pre202xWarning.hlsl @@ -0,0 +1,12 @@ +// RUN: %dxc -T lib_6_3 -HV 2021 -verify %s + +groupshared uint SharedData; + +void fn1(groupshared uint Sh) { +// expected-warning@-1{{Support for groupshared parameter annotation not added until HLSL 202x}} + Sh = 5; +} + +void fn2() { + fn1(SharedData); +} diff --git a/tools/clang/test/SemaHLSL/v202x/groupshared/ScalarTest.hlsl b/tools/clang/test/SemaHLSL/v202x/groupshared/ScalarTest.hlsl new file mode 100644 index 0000000000..9d3703ea22 --- /dev/null +++ b/tools/clang/test/SemaHLSL/v202x/groupshared/ScalarTest.hlsl @@ -0,0 +1,13 @@ +// RUN: %dxc -T lib_6_3 -enable-16bit-types -HV 202x -verify %s + +groupshared uint16_t SharedData; + +void fn1(groupshared half Sh) { +// expected-note@-1{{candidate function not viable: no known conversion from '__attribute__((address_space(3))) uint16_t' to '__attribute__((address_space(3))) half &' for 1st argument}} + Sh = 5; +} + +void fn2() { + fn1(SharedData); + // expected-error@-1{{no matching function for call to 'fn1'}} +} diff --git a/tools/clang/test/SemaHLSL/varmods-syntax.hlsl b/tools/clang/test/SemaHLSL/varmods-syntax.hlsl index 8bb5bb2fc5..17fa7cd810 100644 --- a/tools/clang/test/SemaHLSL/varmods-syntax.hlsl +++ b/tools/clang/test/SemaHLSL/varmods-syntax.hlsl @@ -1,4 +1,4 @@ -// RUN: %dxc -Tlib_6_3 -verify %s +// RUN: %dxc -Tlib_6_3 -HV 202x -verify %s // The following is meant to be processed by the CodeTags extension in the "VS For Everything" Visual Studio extension: /* @@ -497,33 +497,33 @@ struct s_inout { // Parameters // modify(lines, gen_code('float4 foo_%(id)s(%(mods)s float4 val) { return val; }', storage_combos)) // GENERATED_CODE:BEGIN -float4 foo_gro_ext(groupshared extern float4 val) { return val; } /* expected-error {{'groupshared' is not a valid modifier for a parameter}} expected-error {{invalid storage class specifier in function declarator}} fxc-error {{X3000: syntax error: unexpected token 'groupshared'}} fxc-error {{X3004: undeclared identifier 'val'}} fxc-error {{X3080: 'foo_gro_ext': function must return a value}} */ +float4 foo_gro_ext(groupshared extern float4 val) { return val; } /* expected-error {{invalid storage class specifier in function declarator}} fxc-error {{X3000: syntax error: unexpected token 'groupshared'}} fxc-error {{X3004: undeclared identifier 'val'}} fxc-error {{X3080: 'foo_gro_ext': function must return a value}} */ float4 foo_ext_sta(extern static float4 val) { return val; } /* expected-error {{cannot combine with previous 'extern' declaration specifier}} expected-error {{invalid storage class specifier in function declarator}} fxc-error {{X3000: syntax error: unexpected token 'extern'}} fxc-error {{X3004: undeclared identifier 'val'}} fxc-error {{X3080: 'foo_ext_sta': function must return a value}} */ float4 foo_sta_uni(static uniform float4 val) { return val; } /* expected-error {{invalid storage class specifier in function declarator}} fxc-error {{X3000: syntax error: unexpected token 'static'}} fxc-error {{X3004: undeclared identifier 'val'}} fxc-error {{X3080: 'foo_sta_uni': function must return a value}} */ -float4 foo_gro(groupshared float4 val) { return val; } /* expected-error {{'groupshared' is not a valid modifier for a parameter}} fxc-error {{X3000: syntax error: unexpected token 'groupshared'}} fxc-error {{X3004: undeclared identifier 'val'}} fxc-error {{X3080: 'foo_gro': function must return a value}} */ -float4 foo_gro_pre(groupshared precise float4 val) { return val; } /* expected-error {{'groupshared' is not a valid modifier for a parameter}} fxc-error {{X3000: syntax error: unexpected token 'groupshared'}} fxc-error {{X3004: undeclared identifier 'val'}} fxc-error {{X3080: 'foo_gro_pre': function must return a value}} */ -float4 foo_gro_pre_sta(groupshared precise static float4 val) { return val; } /* expected-error {{'groupshared' is not a valid modifier for a parameter}} expected-error {{invalid storage class specifier in function declarator}} fxc-error {{X3000: syntax error: unexpected token 'groupshared'}} fxc-error {{X3004: undeclared identifier 'val'}} fxc-error {{X3080: 'foo_gro_pre_sta': function must return a value}} */ -float4 foo_gro_pre_sta_vol(groupshared precise static volatile float4 val) { return val; } /* expected-error {{'groupshared' is not a valid modifier for a parameter}} expected-error {{'volatile' is not a valid modifier for a parameter}} expected-error {{invalid storage class specifier in function declarator}} fxc-error {{X3000: syntax error: unexpected token 'groupshared'}} fxc-error {{X3004: undeclared identifier 'val'}} fxc-error {{X3080: 'foo_gro_pre_sta_vol': function must return a value}} */ -float4 foo_gro_pre_sta_vol_con(groupshared precise static volatile const float4 val) { return val; } /* expected-error {{'groupshared' is not a valid modifier for a parameter}} expected-error {{'volatile' is not a valid modifier for a parameter}} expected-error {{invalid storage class specifier in function declarator}} fxc-error {{X3000: syntax error: unexpected token 'groupshared'}} fxc-error {{X3004: undeclared identifier 'val'}} fxc-error {{X3080: 'foo_gro_pre_sta_vol_con': function must return a value}} */ -float4 foo_gro_pre_sta_con(groupshared precise static const float4 val) { return val; } /* expected-error {{'groupshared' is not a valid modifier for a parameter}} expected-error {{invalid storage class specifier in function declarator}} fxc-error {{X3000: syntax error: unexpected token 'groupshared'}} fxc-error {{X3004: undeclared identifier 'val'}} fxc-error {{X3080: 'foo_gro_pre_sta_con': function must return a value}} */ -float4 foo_gro_pre_uni(groupshared precise uniform float4 val) { return val; } /* expected-error {{'groupshared' is not a valid modifier for a parameter}} fxc-error {{X3000: syntax error: unexpected token 'groupshared'}} fxc-error {{X3004: undeclared identifier 'val'}} fxc-error {{X3080: 'foo_gro_pre_uni': function must return a value}} */ -float4 foo_gro_pre_uni_vol(groupshared precise uniform volatile float4 val) { return val; } /* expected-error {{'groupshared' is not a valid modifier for a parameter}} expected-error {{'volatile' is not a valid modifier for a parameter}} fxc-error {{X3000: syntax error: unexpected token 'groupshared'}} fxc-error {{X3004: undeclared identifier 'val'}} fxc-error {{X3080: 'foo_gro_pre_uni_vol': function must return a value}} */ -float4 foo_gro_pre_uni_vol_con(groupshared precise uniform volatile const float4 val) { return val; } /* expected-error {{'groupshared' is not a valid modifier for a parameter}} expected-error {{'volatile' is not a valid modifier for a parameter}} fxc-error {{X3000: syntax error: unexpected token 'groupshared'}} fxc-error {{X3004: undeclared identifier 'val'}} fxc-error {{X3080: 'foo_gro_pre_uni_vol_con': function must return a value}} */ -float4 foo_gro_pre_uni_con(groupshared precise uniform const float4 val) { return val; } /* expected-error {{'groupshared' is not a valid modifier for a parameter}} fxc-error {{X3000: syntax error: unexpected token 'groupshared'}} fxc-error {{X3004: undeclared identifier 'val'}} fxc-error {{X3080: 'foo_gro_pre_uni_con': function must return a value}} */ -float4 foo_gro_pre_vol(groupshared precise volatile float4 val) { return val; } /* expected-error {{'groupshared' is not a valid modifier for a parameter}} expected-error {{'volatile' is not a valid modifier for a parameter}} fxc-error {{X3000: syntax error: unexpected token 'groupshared'}} fxc-error {{X3004: undeclared identifier 'val'}} fxc-error {{X3080: 'foo_gro_pre_vol': function must return a value}} */ -float4 foo_gro_pre_vol_con(groupshared precise volatile const float4 val) { return val; } /* expected-error {{'groupshared' is not a valid modifier for a parameter}} expected-error {{'volatile' is not a valid modifier for a parameter}} fxc-error {{X3000: syntax error: unexpected token 'groupshared'}} fxc-error {{X3004: undeclared identifier 'val'}} fxc-error {{X3080: 'foo_gro_pre_vol_con': function must return a value}} */ -float4 foo_gro_pre_con(groupshared precise const float4 val) { return val; } /* expected-error {{'groupshared' is not a valid modifier for a parameter}} fxc-error {{X3000: syntax error: unexpected token 'groupshared'}} fxc-error {{X3004: undeclared identifier 'val'}} fxc-error {{X3080: 'foo_gro_pre_con': function must return a value}} */ -float4 foo_gro_sta(groupshared static float4 val) { return val; } /* expected-error {{'groupshared' is not a valid modifier for a parameter}} expected-error {{invalid storage class specifier in function declarator}} fxc-error {{X3000: syntax error: unexpected token 'groupshared'}} fxc-error {{X3004: undeclared identifier 'val'}} fxc-error {{X3080: 'foo_gro_sta': function must return a value}} */ -float4 foo_gro_sta_vol(groupshared static volatile float4 val) { return val; } /* expected-error {{'groupshared' is not a valid modifier for a parameter}} expected-error {{'volatile' is not a valid modifier for a parameter}} expected-error {{invalid storage class specifier in function declarator}} fxc-error {{X3000: syntax error: unexpected token 'groupshared'}} fxc-error {{X3004: undeclared identifier 'val'}} fxc-error {{X3080: 'foo_gro_sta_vol': function must return a value}} */ -float4 foo_gro_sta_vol_con(groupshared static volatile const float4 val) { return val; } /* expected-error {{'groupshared' is not a valid modifier for a parameter}} expected-error {{'volatile' is not a valid modifier for a parameter}} expected-error {{invalid storage class specifier in function declarator}} fxc-error {{X3000: syntax error: unexpected token 'groupshared'}} fxc-error {{X3004: undeclared identifier 'val'}} fxc-error {{X3080: 'foo_gro_sta_vol_con': function must return a value}} */ -float4 foo_gro_sta_con(groupshared static const float4 val) { return val; } /* expected-error {{'groupshared' is not a valid modifier for a parameter}} expected-error {{invalid storage class specifier in function declarator}} fxc-error {{X3000: syntax error: unexpected token 'groupshared'}} fxc-error {{X3004: undeclared identifier 'val'}} fxc-error {{X3080: 'foo_gro_sta_con': function must return a value}} */ -float4 foo_gro_uni(groupshared uniform float4 val) { return val; } /* expected-error {{'groupshared' is not a valid modifier for a parameter}} fxc-error {{X3000: syntax error: unexpected token 'groupshared'}} fxc-error {{X3004: undeclared identifier 'val'}} fxc-error {{X3080: 'foo_gro_uni': function must return a value}} */ -float4 foo_gro_uni_vol(groupshared uniform volatile float4 val) { return val; } /* expected-error {{'groupshared' is not a valid modifier for a parameter}} expected-error {{'volatile' is not a valid modifier for a parameter}} fxc-error {{X3000: syntax error: unexpected token 'groupshared'}} fxc-error {{X3004: undeclared identifier 'val'}} fxc-error {{X3080: 'foo_gro_uni_vol': function must return a value}} */ -float4 foo_gro_uni_vol_con(groupshared uniform volatile const float4 val) { return val; } /* expected-error {{'groupshared' is not a valid modifier for a parameter}} expected-error {{'volatile' is not a valid modifier for a parameter}} fxc-error {{X3000: syntax error: unexpected token 'groupshared'}} fxc-error {{X3004: undeclared identifier 'val'}} fxc-error {{X3080: 'foo_gro_uni_vol_con': function must return a value}} */ -float4 foo_gro_uni_con(groupshared uniform const float4 val) { return val; } /* expected-error {{'groupshared' is not a valid modifier for a parameter}} fxc-error {{X3000: syntax error: unexpected token 'groupshared'}} fxc-error {{X3004: undeclared identifier 'val'}} fxc-error {{X3080: 'foo_gro_uni_con': function must return a value}} */ -float4 foo_gro_vol(groupshared volatile float4 val) { return val; } /* expected-error {{'groupshared' is not a valid modifier for a parameter}} expected-error {{'volatile' is not a valid modifier for a parameter}} fxc-error {{X3000: syntax error: unexpected token 'groupshared'}} fxc-error {{X3004: undeclared identifier 'val'}} fxc-error {{X3080: 'foo_gro_vol': function must return a value}} */ -float4 foo_gro_vol_con(groupshared volatile const float4 val) { return val; } /* expected-error {{'groupshared' is not a valid modifier for a parameter}} expected-error {{'volatile' is not a valid modifier for a parameter}} fxc-error {{X3000: syntax error: unexpected token 'groupshared'}} fxc-error {{X3004: undeclared identifier 'val'}} fxc-error {{X3080: 'foo_gro_vol_con': function must return a value}} */ -float4 foo_gro_con(groupshared const float4 val) { return val; } /* expected-error {{'groupshared' is not a valid modifier for a parameter}} fxc-error {{X3000: syntax error: unexpected token 'groupshared'}} fxc-error {{X3004: undeclared identifier 'val'}} fxc-error {{X3080: 'foo_gro_con': function must return a value}} */ +float4 foo_gro(groupshared float4 val) { return val; } /* fxc-error {{X3000: syntax error: unexpected token 'groupshared'}} fxc-error {{X3004: undeclared identifier 'val'}} fxc-error {{X3080: 'foo_gro': function must return a value}} */ +float4 foo_gro_pre(groupshared precise float4 val) { return val; } /* fxc-error {{X3000: syntax error: unexpected token 'groupshared'}} fxc-error {{X3004: undeclared identifier 'val'}} fxc-error {{X3080: 'foo_gro_pre': function must return a value}} */ +float4 foo_gro_pre_sta(groupshared precise static float4 val) { return val; } /* expected-error {{invalid storage class specifier in function declarator}} fxc-error {{X3000: syntax error: unexpected token 'groupshared'}} fxc-error {{X3004: undeclared identifier 'val'}} fxc-error {{X3080: 'foo_gro_pre_sta': function must return a value}} */ +float4 foo_gro_pre_sta_vol(groupshared precise static volatile float4 val) { return val; } /* expected-error {{'volatile' is not a valid modifier for a parameter}} expected-error {{invalid storage class specifier in function declarator}} fxc-error {{X3000: syntax error: unexpected token 'groupshared'}} fxc-error {{X3004: undeclared identifier 'val'}} fxc-error {{X3080: 'foo_gro_pre_sta_vol': function must return a value}} */ +float4 foo_gro_pre_sta_vol_con(groupshared precise static volatile const float4 val) { return val; } /* expected-error {{'volatile' is not a valid modifier for a parameter}} expected-error {{invalid storage class specifier in function declarator}} fxc-error {{X3000: syntax error: unexpected token 'groupshared'}} fxc-error {{X3004: undeclared identifier 'val'}} fxc-error {{X3080: 'foo_gro_pre_sta_vol_con': function must return a value}} */ +float4 foo_gro_pre_sta_con(groupshared precise static const float4 val) { return val; } /* expected-error {{invalid storage class specifier in function declarator}} fxc-error {{X3000: syntax error: unexpected token 'groupshared'}} fxc-error {{X3004: undeclared identifier 'val'}} fxc-error {{X3080: 'foo_gro_pre_sta_con': function must return a value}} */ +float4 foo_gro_pre_uni(groupshared precise uniform float4 val) { return val; } /* fxc-error {{X3000: syntax error: unexpected token 'groupshared'}} fxc-error {{X3004: undeclared identifier 'val'}} fxc-error {{X3080: 'foo_gro_pre_uni': function must return a value}} */ +float4 foo_gro_pre_uni_vol(groupshared precise uniform volatile float4 val) { return val; } /* expected-error {{'volatile' is not a valid modifier for a parameter}} fxc-error {{X3000: syntax error: unexpected token 'groupshared'}} fxc-error {{X3004: undeclared identifier 'val'}} fxc-error {{X3080: 'foo_gro_pre_uni_vol': function must return a value}} */ +float4 foo_gro_pre_uni_vol_con(groupshared precise uniform volatile const float4 val) { return val; } /* expected-error {{'volatile' is not a valid modifier for a parameter}} fxc-error {{X3000: syntax error: unexpected token 'groupshared'}} fxc-error {{X3004: undeclared identifier 'val'}} fxc-error {{X3080: 'foo_gro_pre_uni_vol_con': function must return a value}} */ +float4 foo_gro_pre_uni_con(groupshared precise uniform const float4 val) { return val; } /* fxc-error {{X3000: syntax error: unexpected token 'groupshared'}} fxc-error {{X3004: undeclared identifier 'val'}} fxc-error {{X3080: 'foo_gro_pre_uni_con': function must return a value}} */ +float4 foo_gro_pre_vol(groupshared precise volatile float4 val) { return val; } /* expected-error {{'volatile' is not a valid modifier for a parameter}} fxc-error {{X3000: syntax error: unexpected token 'groupshared'}} fxc-error {{X3004: undeclared identifier 'val'}} fxc-error {{X3080: 'foo_gro_pre_vol': function must return a value}} */ +float4 foo_gro_pre_vol_con(groupshared precise volatile const float4 val) { return val; } /* expected-error {{'volatile' is not a valid modifier for a parameter}} fxc-error {{X3000: syntax error: unexpected token 'groupshared'}} fxc-error {{X3004: undeclared identifier 'val'}} fxc-error {{X3080: 'foo_gro_pre_vol_con': function must return a value}} */ +float4 foo_gro_pre_con(groupshared precise const float4 val) { return val; } /* fxc-error {{X3000: syntax error: unexpected token 'groupshared'}} fxc-error {{X3004: undeclared identifier 'val'}} fxc-error {{X3080: 'foo_gro_pre_con': function must return a value}} */ +float4 foo_gro_sta(groupshared static float4 val) { return val; } /* expected-error {{invalid storage class specifier in function declarator}} fxc-error {{X3000: syntax error: unexpected token 'groupshared'}} fxc-error {{X3004: undeclared identifier 'val'}} fxc-error {{X3080: 'foo_gro_sta': function must return a value}} */ +float4 foo_gro_sta_vol(groupshared static volatile float4 val) { return val; } /* expected-error {{'volatile' is not a valid modifier for a parameter}} expected-error {{invalid storage class specifier in function declarator}} fxc-error {{X3000: syntax error: unexpected token 'groupshared'}} fxc-error {{X3004: undeclared identifier 'val'}} fxc-error {{X3080: 'foo_gro_sta_vol': function must return a value}} */ +float4 foo_gro_sta_vol_con(groupshared static volatile const float4 val) { return val; } /* expected-error {{'volatile' is not a valid modifier for a parameter}} expected-error {{invalid storage class specifier in function declarator}} fxc-error {{X3000: syntax error: unexpected token 'groupshared'}} fxc-error {{X3004: undeclared identifier 'val'}} fxc-error {{X3080: 'foo_gro_sta_vol_con': function must return a value}} */ +float4 foo_gro_sta_con(groupshared static const float4 val) { return val; } /* expected-error {{invalid storage class specifier in function declarator}} fxc-error {{X3000: syntax error: unexpected token 'groupshared'}} fxc-error {{X3004: undeclared identifier 'val'}} fxc-error {{X3080: 'foo_gro_sta_con': function must return a value}} */ +float4 foo_gro_uni(groupshared uniform float4 val) { return val; } /* fxc-error {{X3000: syntax error: unexpected token 'groupshared'}} fxc-error {{X3004: undeclared identifier 'val'}} fxc-error {{X3080: 'foo_gro_uni': function must return a value}} */ +float4 foo_gro_uni_vol(groupshared uniform volatile float4 val) { return val; } /* expected-error {{'volatile' is not a valid modifier for a parameter}} fxc-error {{X3000: syntax error: unexpected token 'groupshared'}} fxc-error {{X3004: undeclared identifier 'val'}} fxc-error {{X3080: 'foo_gro_uni_vol': function must return a value}} */ +float4 foo_gro_uni_vol_con(groupshared uniform volatile const float4 val) { return val; } /* expected-error {{'volatile' is not a valid modifier for a parameter}} fxc-error {{X3000: syntax error: unexpected token 'groupshared'}} fxc-error {{X3004: undeclared identifier 'val'}} fxc-error {{X3080: 'foo_gro_uni_vol_con': function must return a value}} */ +float4 foo_gro_uni_con(groupshared uniform const float4 val) { return val; } /* fxc-error {{X3000: syntax error: unexpected token 'groupshared'}} fxc-error {{X3004: undeclared identifier 'val'}} fxc-error {{X3080: 'foo_gro_uni_con': function must return a value}} */ +float4 foo_gro_vol(groupshared volatile float4 val) { return val; } /* expected-error {{'volatile' is not a valid modifier for a parameter}} fxc-error {{X3000: syntax error: unexpected token 'groupshared'}} fxc-error {{X3004: undeclared identifier 'val'}} fxc-error {{X3080: 'foo_gro_vol': function must return a value}} */ +float4 foo_gro_vol_con(groupshared volatile const float4 val) { return val; } /* expected-error {{'volatile' is not a valid modifier for a parameter}} fxc-error {{X3000: syntax error: unexpected token 'groupshared'}} fxc-error {{X3004: undeclared identifier 'val'}} fxc-error {{X3080: 'foo_gro_vol_con': function must return a value}} */ +float4 foo_gro_con(groupshared const float4 val) { return val; } /* fxc-error {{X3000: syntax error: unexpected token 'groupshared'}} fxc-error {{X3004: undeclared identifier 'val'}} fxc-error {{X3080: 'foo_gro_con': function must return a value}} */ float4 foo_ext(extern float4 val) { return val; } /* expected-error {{invalid storage class specifier in function declarator}} fxc-error {{X3000: syntax error: unexpected token 'extern'}} fxc-error {{X3004: undeclared identifier 'val'}} fxc-error {{X3080: 'foo_ext': function must return a value}} */ float4 foo_ext_pre(extern precise float4 val) { return val; } /* expected-error {{invalid storage class specifier in function declarator}} fxc-error {{X3000: syntax error: unexpected token 'extern'}} fxc-error {{X3004: undeclared identifier 'val'}} fxc-error {{X3080: 'foo_ext_pre': function must return a value}} */ float4 foo_ext_pre_uni(extern precise uniform float4 val) { return val; } /* expected-error {{invalid storage class specifier in function declarator}} fxc-error {{X3000: syntax error: unexpected token 'extern'}} fxc-error {{X3004: undeclared identifier 'val'}} fxc-error {{X3080: 'foo_ext_pre_uni': function must return a value}} */