Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions docs/ReleaseNotes.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,12 @@ The included licenses apply to the following files:
- Fixed validator rejecting LinAlgMatrix type in DXIL [#8441](https://github.com/microsoft/DirectXShaderCompiler/pull/8441)
- Fixed float trunc and coord calc errors in ExecTests [#8420](https://github.com/microsoft/DirectXShaderCompiler/pull/8420)
- Convert Bias Vector to match the output type [#8394](https://github.com/microsoft/DirectXShaderCompiler/pull/8394)
- Fixed certain types being disallowed in LinAlg intrinsics [#8465](https://github.com/microsoft/DirectXShaderCompiler/pull/8465)

#### Misc Features
- Support templates with >> instead of > > in 202x [#8453](https://github.com/microsoft/DirectXShaderCompiler/pull/8453)
- Implement `auto` for type deduction [#8452](https://github.com/microsoft/DirectXShaderCompiler/pull/8452)
- Implement `[[nodiscard]]` attribute to warn on unused returns [#8462](https://github.com/microsoft/DirectXShaderCompiler/pull/8462)

#### Bug Fixes
- Fixed build break on certain platforms [#8307](https://github.com/microsoft/DirectXShaderCompiler/pull/8307)
Expand Down
4 changes: 4 additions & 0 deletions tools/clang/include/clang/AST/Decl.h
Original file line number Diff line number Diff line change
Expand Up @@ -2079,6 +2079,10 @@ class FunctionDecl : public DeclaratorDecl, public DeclContext,
/// operators.
bool hasUnusedResultAttr() const;

// HLSL Change Begin - Add support for nodiscard attribute.
Attr *getNoDiscardAttr() const;
// HLSL Change Ends

/// \brief Returns the storage class as written in the source. For the
/// computed linkage of symbol, see getLinkage.
StorageClass getStorageClass() const { return StorageClass(SClass); }
Expand Down
4 changes: 3 additions & 1 deletion tools/clang/include/clang/Basic/Attr.td
Original file line number Diff line number Diff line change
Expand Up @@ -2470,13 +2470,15 @@ def WarnUnused : InheritableAttr {
let Documentation = [Undocumented];
}

// HLSL Change Begin - add C++11 spelling.
def WarnUnusedResult : InheritableAttr {
let Spellings = [GCC<"warn_unused_result">,
let Spellings = [CXX11<"", "nodiscard", 2017>, GCC<"warn_unused_result">,
CXX11<"clang", "warn_unused_result">];
let Subjects = SubjectList<[ObjCMethod, CXXRecord, FunctionLike], WarnDiag,
"ExpectedFunctionMethodOrClass">;
let Documentation = [Undocumented];
}
// HLSL Change End - add C++11 spelling.

def Weak : InheritableAttr {
let Spellings = [GCC<"weak">];
Expand Down
3 changes: 2 additions & 1 deletion tools/clang/include/clang/Basic/DiagnosticParseKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -285,7 +285,8 @@ def warn_cxx98_compat_trailing_return_type : Warning<
"trailing return types are incompatible with C++98">,
InGroup<CXX98Compat>, DefaultIgnore;
def ext_auto_type_specifier : ExtWarn<
"'auto' type specifier is a C++11 extension">, InGroup<CXX11>;
"'auto' type specifier is a %select{C++11|HLSL 202x}0 extension">,
InGroup<CXX11>;
def warn_auto_storage_class : Warning<
"'auto' storage class specifier is redundant and incompatible with C++11">,
InGroup<CXX11Compat>, DefaultIgnore;
Expand Down
8 changes: 5 additions & 3 deletions tools/clang/include/clang/Basic/DiagnosticSemaKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -6368,9 +6368,11 @@ def warn_side_effects_unevaluated_context : Warning<
def warn_side_effects_typeid : Warning<
"expression with side effects will be evaluated despite being used as an "
"operand to 'typeid'">, InGroup<PotentiallyEvaluatedExpression>;
def warn_unused_result : Warning<
"ignoring return value of function declared with warn_unused_result "
"attribute">, InGroup<DiagGroup<"unused-result">>;
// HLSL Change Begin - allow attribute spelling to come in.
def warn_unused_result
: Warning<"ignoring return value of function declared with %0 attribute">,
InGroup<DiagGroup<"unused-result">>;
// HLSL Change End
def warn_unused_volatile : Warning<
"expression result unused; assign into a variable to force a volatile load">,
InGroup<DiagGroup<"unused-volatile-lvalue">>;
Expand Down
2 changes: 1 addition & 1 deletion tools/clang/include/clang/Lex/Token.h
Original file line number Diff line number Diff line change
Expand Up @@ -295,7 +295,7 @@ class Token {
// HLSL Change Starts
bool isHLSLReserved() const {
return is(tok::kw___is_signed) || is(tok::kw___declspec) ||
is(tok::kw___forceinline) || is(tok::kw_auto) || is(tok::kw_catch) ||
is(tok::kw___forceinline) || is(tok::kw_catch) ||
is(tok::kw_const_cast) || is(tok::kw_delete) ||
is(tok::kw_dynamic_cast) || is(tok::kw_enum) ||
is(tok::kw_explicit) || is(tok::kw_friend) || is(tok::kw_goto) ||
Expand Down
22 changes: 19 additions & 3 deletions tools/clang/lib/AST/Decl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2876,14 +2876,30 @@ bool FunctionDecl::hasUnusedResultAttr() const {
QualType RetType = getReturnType();
if (RetType->isRecordType()) {
const CXXRecordDecl *Ret = RetType->getAsCXXRecordDecl();
const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(this);
if (Ret && Ret->hasAttr<WarnUnusedResultAttr>() &&
!(MD && MD->getCorrespondingMethodInClass(Ret, true)))
// HLSL Change Begin - nodiscard on a type should apply to all methods, even
// if they are not marked nodiscard themselves. This is the C++17 behavior.
if (Ret && Ret->hasAttr<WarnUnusedResultAttr>())
return true;
// HLSL Change End
}
return hasAttr<WarnUnusedResultAttr>();
}

// HLSL Change Begin - support nodiscard attr.
Attr *FunctionDecl::getNoDiscardAttr() const {
QualType RetType = getReturnType();
if (RetType->isRecordType()) {
const CXXRecordDecl *Ret = RetType->getAsCXXRecordDecl();
const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(this);
if (Ret && Ret->hasAttr<WarnUnusedResultAttr>() &&
(!hasAttr<WarnUnusedResultAttr>() ||
!(MD && (MD->getCorrespondingMethodInClass(Ret, true)))))
return Ret->getAttr<WarnUnusedResultAttr>();
}
return getAttr<WarnUnusedResultAttr>();
}
// HLSL Change End

/// \brief For an inline function definition in C, or for a gnu_inline function
/// in C++, determine whether the definition will be externally visible.
///
Expand Down
7 changes: 4 additions & 3 deletions tools/clang/lib/Headers/hlsl/dx/linalg.h
Original file line number Diff line number Diff line change
Expand Up @@ -289,8 +289,9 @@ class Matrix {
}

template <typename T>
static typename hlsl::enable_if<hlsl::is_arithmetic<T>::value, Matrix>::type
Splat(T Val) {
[[nodiscard]] static
typename hlsl::enable_if<hlsl::is_arithmetic<T>::value, Matrix>::type
Splat(T Val) {
Matrix Result;
__builtin_LinAlg_FillMatrix(Result.__handle, Val);
return Result;
Expand Down Expand Up @@ -652,7 +653,7 @@ OuterProduct(vector<InputElTy, M> VecA, vector<InputElTy, N> VecB) {

template <typename InputElTy, SIZE_TYPE M>
typename hlsl::enable_if<hlsl::is_arithmetic<InputElTy>::value, void>::type
InterlockedAccumulate(RWByteAddressBuffer Res, vector<InputElTy, M> Vec,
InterlockedAccumulate(vector<InputElTy, M> Vec, RWByteAddressBuffer Res,
uint StartOffset, uint Align = 64) {
__builtin_LinAlg_VectorAccumulateToDescriptor(Vec, Res, StartOffset, Align);
}
Expand Down
8 changes: 6 additions & 2 deletions tools/clang/lib/Parse/ParseDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3918,8 +3918,12 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
break;
// HLSL Change Ends
case tok::kw_auto:
if (getLangOpts().HLSL) { goto HLSLReservedKeyword; } // HLSL Change - auto is reserved for HLSL
if (getLangOpts().CPlusPlus11) {
// HLSL Change Begin - auto is reserved for HLSL 2015 and earlier.
if (getLangOpts().HLSL &&
getLangOpts().HLSLVersion <= hlsl::LangStd::v2015)
goto HLSLReservedKeyword;
// HLSL Change End
if (getLangOpts().CPlusPlus11 || getLangOpts().HLSL) { // HLSL Change
if (isKnownToBeTypeSpecifier(GetLookAheadToken(1))) {
isInvalid = DS.SetStorageClassSpec(Actions, DeclSpec::SCS_auto, Loc,
PrevSpec, DiagID, Policy);
Expand Down
22 changes: 15 additions & 7 deletions tools/clang/lib/Parse/ParseExpr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -254,9 +254,11 @@ static bool isFoldOperator(tok::TokenKind Kind) {
/// precedence of at least \p MinPrec.
ExprResult
Parser::ParseRHSOfBinaryExpression(ExprResult LHS, prec::Level MinPrec) {
prec::Level NextTokPrec = getBinOpPrecedence(Tok.getKind(),
GreaterThanIsOperator,
getLangOpts().CPlusPlus11);
prec::Level NextTokPrec =
getBinOpPrecedence(Tok.getKind(), GreaterThanIsOperator,
getLangOpts().CPlusPlus11 ||
(getLangOpts().HLSL && getLangOpts().HLSLVersion >=
hlsl::LangStd::v202x));
SourceLocation ColonLoc;

while (1) {
Expand Down Expand Up @@ -390,8 +392,11 @@ Parser::ParseRHSOfBinaryExpression(ExprResult LHS, prec::Level MinPrec) {
// Remember the precedence of this operator and get the precedence of the
// operator immediately to the right of the RHS.
prec::Level ThisPrec = NextTokPrec;
NextTokPrec = getBinOpPrecedence(Tok.getKind(), GreaterThanIsOperator,
getLangOpts().CPlusPlus11);
NextTokPrec = getBinOpPrecedence(
Tok.getKind(), GreaterThanIsOperator,
getLangOpts().CPlusPlus11 ||
(getLangOpts().HLSL &&
getLangOpts().HLSLVersion >= hlsl::LangStd::v202x));

// Assignment and conditional expressions are right-associative.
bool isRightAssoc = ThisPrec == prec::Conditional ||
Expand Down Expand Up @@ -424,8 +429,11 @@ Parser::ParseRHSOfBinaryExpression(ExprResult LHS, prec::Level MinPrec) {
LHS = ExprError();
}

NextTokPrec = getBinOpPrecedence(Tok.getKind(), GreaterThanIsOperator,
getLangOpts().CPlusPlus11);
NextTokPrec = getBinOpPrecedence(
Tok.getKind(), GreaterThanIsOperator,
getLangOpts().CPlusPlus11 ||
(getLangOpts().HLSL &&
getLangOpts().HLSLVersion >= hlsl::LangStd::v202x));
}

if (!RHS.isInvalid() && RHSIsInitList) {
Expand Down
4 changes: 3 additions & 1 deletion tools/clang/lib/Parse/ParseTemplate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -840,7 +840,9 @@ bool Parser::ParseGreaterThanInTemplateList(SourceLocation &RAngleLoc,
Hint2 = FixItHint::CreateInsertion(Next.getLocation(), " ");

unsigned DiagId = diag::err_two_right_angle_brackets_need_space;
if (getLangOpts().CPlusPlus11 &&
if ((getLangOpts().CPlusPlus11 ||
(getLangOpts().HLSL &&
getLangOpts().HLSLVersion >= hlsl::LangStd::v202x)) &&
(Tok.is(tok::greatergreater) || Tok.is(tok::greatergreatergreater)))
DiagId = diag::warn_cxx98_compat_two_right_angle_brackets;
else if (Tok.is(tok::greaterequal))
Expand Down
10 changes: 8 additions & 2 deletions tools/clang/lib/Sema/DeclSpec.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1158,8 +1158,14 @@ void DeclSpec::Finish(DiagnosticsEngine &D, Preprocessor &PP, const PrintingPoli
}
// Diagnose if we've recovered from an ill-formed 'auto' storage class
// specifier in a pre-C++11 dialect of C++.
if (!PP.getLangOpts().CPlusPlus11 && TypeSpecType == TST_auto)
Diag(D, TSTLoc, diag::ext_auto_type_specifier);
// HLSL Change Begin - HLSL supports 'auto' as a type specifier in 202x+.
if (!(PP.getLangOpts().CPlusPlus11 ||
(PP.getLangOpts().HLSL &&
PP.getLangOpts().HLSLVersion >= hlsl::LangStd::v202x)) &&
TypeSpecType == TST_auto)
Diag(D, TSTLoc, diag::ext_auto_type_specifier)
<< /* HLSL */ PP.getLangOpts().HLSL;
// HLSL Change End
if (PP.getLangOpts().CPlusPlus && !PP.getLangOpts().CPlusPlus11 &&
StorageClassSpec == SCS_auto)
Diag(D, StorageClassSpecLoc, diag::warn_auto_storage_class)
Expand Down
1 change: 0 additions & 1 deletion tools/clang/lib/Sema/SemaDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9047,7 +9047,6 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init,

// If this is a redeclaration, check that the type we just deduced matches
// the previously declared type.
assert(!getLangOpts().HLSL && "auto types are not supported - merge type below is inconsequential"); // HLSL Change
if (VarDecl *Old = VDecl->getPreviousDecl()) {
// We never need to merge the type, because we cannot form an incomplete
// array of auto, nor deduce such a type.
Expand Down
12 changes: 7 additions & 5 deletions tools/clang/lib/Sema/SemaHLSL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1170,12 +1170,14 @@ static const ArBasicKind g_RayQueryCT[] = {AR_OBJECT_RAY_QUERY,
AR_BASIC_UNKNOWN};

static const ArBasicKind g_LinAlgCT[] = {
AR_BASIC_LITERAL_FLOAT, AR_BASIC_FLOAT16,
AR_BASIC_FLOAT32, AR_BASIC_FLOAT32_PARTIAL_PRECISION,
AR_BASIC_FLOAT16, AR_BASIC_INT32,
AR_BASIC_INT16, AR_BASIC_UINT32,
AR_BASIC_UINT16, AR_BASIC_INT8_4PACKED,
AR_BASIC_UINT8_4PACKED, AR_BASIC_NOCAST,
AR_BASIC_UNKNOWN};
AR_BASIC_FLOAT64, AR_BASIC_LITERAL_INT,
AR_BASIC_UINT16, AR_BASIC_UINT32,
AR_BASIC_UINT64, AR_BASIC_INT16,
AR_BASIC_INT32, AR_BASIC_INT64,
AR_BASIC_UINT8_4PACKED, AR_BASIC_INT8_4PACKED,
AR_BASIC_NOCAST, AR_BASIC_UNKNOWN};

static const ArBasicKind g_AccelerationStructCT[] = {
AR_OBJECT_ACCELERATION_STRUCT, AR_BASIC_UNKNOWN};
Expand Down
11 changes: 9 additions & 2 deletions tools/clang/lib/Sema/SemaStmt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,11 @@ void Sema::DiagnoseUnusedExprResult(const Stmt *S) {
const FunctionDecl *Func = dyn_cast<FunctionDecl>(FD);
if (Func ? Func->hasUnusedResultAttr()
: FD->hasAttr<WarnUnusedResultAttr>()) {
Diag(Loc, diag::warn_unused_result) << R1 << R2;
// HLSL Change Begin - allow attribute spelling to come in.
Attr *NoDiscardAttr = Func ? Func->getNoDiscardAttr()
: FD->getAttr<WarnUnusedResultAttr>();
Diag(Loc, diag::warn_unused_result) << NoDiscardAttr << R1 << R2;
// HLSL Change End
return;
}
if (ShouldSuppress)
Expand All @@ -270,7 +274,10 @@ void Sema::DiagnoseUnusedExprResult(const Stmt *S) {
const ObjCMethodDecl *MD = ME->getMethodDecl();
if (MD) {
if (MD->hasAttr<WarnUnusedResultAttr>()) {
Diag(Loc, diag::warn_unused_result) << R1 << R2;
// HLSL Change Begin - allow attribute spelling to come in.
Diag(Loc, diag::warn_unused_result)
<< MD->getAttr<WarnUnusedResultAttr>() << R1 << R2;
// HLSL Change End
return;
}
}
Expand Down
4 changes: 2 additions & 2 deletions tools/clang/test/CodeGenDXIL/hlsl/linalg/api/vectors.hlsl
Original file line number Diff line number Diff line change
Expand Up @@ -193,9 +193,9 @@ void main(uint ID : SV_GroupID) {
// CHECK: call void @dx.op.linAlgVectorAccumulateToDescriptor.v4f16(i32 -2147483617, <4 x half>
// CHECK-SAME: <half 0xH4926, half 0xH4926, half 0xH4926, half 0xH4926>, %dx.types.Handle %{{[0-9]+}}, i32 0, i32 64)
// CHECK-SAME: ; LinAlgVectorAccumulateToDescriptor(vector,handle,offset,align)
InterlockedAccumulate(RWBAB, vec1, 0);
InterlockedAccumulate(vec1, RWBAB, 0);

// CHECK: call void @dx.op.linAlgVectorAccumulateToDescriptor.v8f16(i32 -2147483617, <8 x half> %{{[0-9]+}},
// CHECK-SAME: %dx.types.Handle %{{[0-9]+}}, i32 8, i32 64) ; LinAlgVectorAccumulateToDescriptor(vector,handle,offset,align)
InterlockedAccumulate(RWBAB, vec2, 8);
InterlockedAccumulate(vec2, RWBAB, 8);
}
Original file line number Diff line number Diff line change
Expand Up @@ -49,4 +49,18 @@ void main() {
// CHECK2-SAME: i1 true, <4 x i64> %{{[0-9]+}}, i32 1, <4 x i64> %{{[0-9]+}}, i32 0)

__builtin_LinAlg_MatrixVectorMultiplyAdd(result3, mat3, true, vec3, 1, result3, 0);

// CHECK: call <8 x i32> @dx.op.linAlgMatVecMulAdd.v8i32.mC17M8N8U0S0.v8i32.v8i32(i32 -2147483622,
// CHECK-SAME: %dx.types.LinAlgMatrixC17M8N8U0S0 {{.*}}, i1 true, <8 x i32> zeroinitializer,
// CHECK-SAME: i32 1, <8 x i32> zeroinitializer, i32 0)
// CHECK-SAME: ; LinAlgMatVecMulAdd(matrix,isOutputSigned,inputVector,inputInterpretation,biasVector,biasInterpretation)

// CHECK2: call void @"dx.hl.op..void (i32, <8 x i32>*, %dx.types.LinAlgMatrixC17M8N8U0S0, i1, <8 x i32>,
// CHECK2-SAME: i32, <8 x i32>, i32)"(i32 419, <8 x i32>* %result4, %dx.types.LinAlgMatrixC17M8N8U0S0 %{{[0-9]+}},
// CHECK2-SAME: i1 true, <8 x i32> %{{[0-9]+}}, i32 1, <8 x i32> %{{[0-9]+}}, i32 0)

__builtin_LinAlgMatrix [[__LinAlgMatrix_Attributes(17, 8, 8, 0, 0)]] mat4;
vector<int8_t4_packed, 8> vec4 = 0;
vector<int8_t4_packed, 8> result4 = 0;
__builtin_LinAlg_MatrixVectorMultiplyAdd(result4, mat4, true, vec4, 1, result4, 0);
}
51 changes: 51 additions & 0 deletions tools/clang/test/CodeGenSPIRV/var.auto.deduction.hlsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
// RUN: %dxc -T cs_6_0 -E main -HV 202x -fcgl %s -spirv | FileCheck %s

// Test that the 'auto' keyword can be used to declare variables with inferred
// types from initialization expressions when targeting SPIR-V.

// CHECK: [[INT:%[a-zA-Z0-9_]+]] = OpTypeInt 32 1
// CHECK: [[INT_1:%[a-zA-Z0-9_]+]] = OpConstant [[INT]] 1
// CHECK: [[FLOAT:%[a-zA-Z0-9_]+]] = OpTypeFloat 32
// CHECK: [[FLOAT_2:%[a-zA-Z0-9_]+]] = OpConstant [[FLOAT]] 2
// CHECK: [[BOOL:%[a-zA-Z0-9_]+]] = OpTypeBool
// CHECK: [[TRUE:%[a-zA-Z0-9_]+]] = OpConstantTrue [[BOOL]]
// CHECK: [[V4FLOAT:%[a-zA-Z0-9_]+]] = OpTypeVector [[FLOAT]] 4
// CHECK: [[VEC_CONST:%[a-zA-Z0-9_]+]] = OpConstantComposite [[V4FLOAT]] {{%[a-zA-Z0-9_]+}} [[FLOAT_2]] {{%[a-zA-Z0-9_]+}} {{%[a-zA-Z0-9_]+}}

// CHECK: [[PTR_INT:%_ptr_Function_int]] = OpTypePointer Function [[INT]]
// CHECK: [[PTR_FLOAT:%_ptr_Function_float]] = OpTypePointer Function [[FLOAT]]
// CHECK: [[PTR_BOOL:%_ptr_Function_bool]] = OpTypePointer Function [[BOOL]]
// CHECK: [[PTR_V4FLOAT:%_ptr_Function_v4float]] = OpTypePointer Function [[V4FLOAT]]

// CHECK: %a = OpVariable [[PTR_INT]] Function
// CHECK: %b = OpVariable [[PTR_FLOAT]] Function
// CHECK: %c = OpVariable [[PTR_BOOL]] Function
// CHECK: %d = OpVariable [[PTR_V4FLOAT]] Function
// CHECK: %sum = OpVariable [[PTR_INT]] Function
// CHECK: %product = OpVariable [[PTR_FLOAT]] Function

// CHECK: OpStore %a [[INT_1]]
// CHECK: OpStore %b [[FLOAT_2]]
// CHECK: OpStore %c [[TRUE]]
// CHECK: OpStore %d [[VEC_CONST]]

RWBuffer<float> output : register(u0);

[numthreads(1,1,1)]
void main() {
// Auto deduces int from integer literal
auto a = 1;
// Auto deduces float from float literal
auto b = 2.0f;
// Auto deduces bool from bool literal
auto c = true;
// Auto deduces float4 from vector type
auto d = float4(1.0f, 2.0f, 3.0f, 4.0f);

// Auto from arithmetic expressions
auto sum = a + a;
auto product = b * b;

// Use the values to prevent dead-code elimination
output[0] = (float)sum + product + d.x + (float)c;
}
Loading
Loading