Skip to content

Conversation

@pow2clk
Copy link
Collaborator

@pow2clk pow2clk commented May 12, 2022

This disallows a number of illegal destination parameters to atomic
operations. This includes SRVs and other const values, non-groupshared
and non-resourse variables, members of typed resources, and bitfield
members of any resource.

In addition, this correctly propagates const information so that they
can be properly rejected and also the information is reflected.
This involves the consolidation and earlier detection of a number of
these failures as well as an expansion of that detection.
Also adds validation checks that the targets are not const and either
UAVs or groupshared address space.

Add compilation tests as well as validation tests for all.

Fixes #4319
Fixes #4377
Fixes #4437

This disallows a number of illegal destination parameters to atomic
operations. This includes SRVs and other const values, non-groupshared
and non-resourse variables, members of typed resources, and bitfield
members of any resource.

In addition, this correctly propagates const information so that they
can be properly rejected and also the information is reflected.
This involves the consolidation and earlier detection of a number of
these failures as well as an expansion of that detection.
Also adds validation checks that the targets are not const and either
UAVs or groupshared address space.

Add compilation tests as well as validation tests for all.

Fixes microsoft#4319
Fixes microsoft#4377
Fixes microsoft#4437
dxilutil::EmitErrorOnInstruction(userCall, "Invalid operation on typed buffer.");
return;
break;
}
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All of this was just to generate different errors when atomic ops were performed on typed resources had non-scalar elements. Because this is handled elsewhere, the distinction need not be done here anymore

@AppVeyorBot
Copy link

@AppVeyorBot
Copy link

add test for reviewer commented lib export func test

remove unintended and fairly weird unsubscripted references to resources
in restypes test

add more specific checks for unfound atomics for resources in restypes
@AppVeyorBot
Copy link

Copy link
Collaborator Author

@pow2clk pow2clk left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Respond to feedback

Add location information for overload mismatch notes. Their absence was
preventing verifier tests from working. For note referring to
declaration location, skip if ther is no location due to being builtin

Convert all new error tests to verifier tests

Reword an erorr message

revise test to be valid HLSL
@AppVeyorBot
Copy link

Add drilling through GEP and BC for groupshared atomic validation
Add validation test for const groupshared atomic used through a GEP

Enhance error detection for atomics at lowering time by accounting for
any sequence of GEP and subscript operations that might end with a valid
resource.

Add various new testing for atomic operations performed on destination
values that are attached to a string of GEP and subscripts.
@AppVeyorBot
Copy link

@AppVeyorBot
Copy link

@AppVeyorBot
Copy link

@AppVeyorBot
Copy link

Copy link
Contributor

@tex3d tex3d left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comments about strange/misleading error messages are really just to note, not for fixing in this PR. Makes sense to add new verifier tests to VerifierHelper though.

// Assigning using dest param of atomics
// Distinct because of special handling of atomics dest param
InterlockedAdd(local[0], 1); /* expected-error {{no matching function for call to 'InterlockedAdd'}} expected-note {{candidate function not viable: 1st argument ('const uint') would lose const qualifier}} expected-note {{candidate function not viable: no known conversion from 'const uint' to 'unsigned long long &' for 1st argument}} */
InterlockedAdd(gs_val[0], 1); /* expected-error {{no matching function for call to 'InterlockedAdd'}} expected-note {{candidate function not viable: 1st argument ('const uint') would lose const qualifier}} expected-note {{candidate function not viable: no known conversion from 'const uint' to 'unsigned long long' for 1st argument}} */
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Strange, why does this one (and next two) say to 'unsigned long long' instead of 'unsigned long long &' like the first one?
And why would it be unsigned long long in the first place, since I presume this should take a 32-bit reference?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another "quirk" of how atomics are lowered. The dest param is not made a reference until the candidate function is first added to the used intrinsics. Subsequent candidates are found to match the existing so their params don't get converted. It's only an issue for matching failures. We should talk about why it was designed this way in the first place.

InterlockedOr(str[tid.y].q, 2); /* expected-error {{no matching function for call to 'InterlockedOr'}} expected-note {{candidate function not viable: no known conversion from 'uint' to 'unsigned int' for 1st argument}} expected-note {{candidate function not viable: no known conversion from 'uint' to 'unsigned long long' for 1st argument}} */
InterlockedCompareStore(str[tid.y].q, 3, 1); /* expected-error {{no matching function for call to 'InterlockedCompareStore'}} expected-note {{candidate function not viable: no known conversion from 'uint' to 'unsigned int' for 1st argument}} expected-note {{candidate function not viable: no known conversion from 'uint' to 'unsigned long long' for 1st argument}} */

InterlockedOr(gs.q, 2); /* expected-error {{no matching function for call to 'InterlockedOr'}} expected-note {{candidate function not viable: 1st argument ('__attribute__((address_space(3))) uint') is in address space 3, but parameter must be in address space 0}} expected-note {{candidate function not viable: no known conversion from '__attribute__((address_space(3))) uint' to 'unsigned long long' for 1st argument}} */
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's a shame about the address space error, since it's misleading.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Less so than the previous I'd say. Bitfields just make the compiler do your shifting and casting for you. The result of that operation is a local. Granted, shader authors may not know that. We could consider creating some custom mismatch types at some point. That would be useful in all versions of LLVM unless they've seriously overhauled this system

@AppVeyorBot
Copy link

Change some function signatures and local variables in SemaHLSL to try
to avoid mistakenly comparing matching opcodes from different namespaces
@AppVeyorBot
Copy link

@pow2clk pow2clk merged commit caec6aa into microsoft:main May 17, 2022
@pow2clk pow2clk deleted the disallow_bad_atomics branch May 17, 2022 04:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

4 participants