tint: Implement pointer alias analysis

Track reads and writes to pointer parameters for each function in the
Resolver, as well as accesses to module-scope variables. At function
call sites, check the root identifiers of each pointer argument to
determine if problematic aliasing occurs.

The MSL backend passes pointers to sub-objects to functions when
handling workgroup storage variables, which triggers the alias
analysis. Add a validation override for this scenario.

Bug: tint:1675

Change-Id: I81a40d1309df65521cc5ad39764d6a09a260f51e
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/110167
Kokoro: Kokoro <noreply+kokoro@google.com>
Reviewed-by: Ben Clayton <bclayton@google.com>
Commit-Queue: James Price <jrprice@google.com>
This commit is contained in:
James Price
2022-11-17 17:27:27 +00:00
committed by Dawn LUCI CQ
parent d6f9a8a253
commit 4d65fc91bb
10 changed files with 1128 additions and 0 deletions

View File

@@ -354,6 +354,7 @@ struct ModuleScopeVarToEntryPointParam::State {
for (auto* func_ast : functions_to_process) {
auto* func_sem = ctx.src->Sem().Get(func_ast);
bool is_entry_point = func_ast->IsEntryPoint();
bool needs_pointer_aliasing = false;
// Map module-scope variables onto their replacement.
struct NewVar {
@@ -424,6 +425,9 @@ struct ModuleScopeVarToEntryPointParam::State {
is_wrapped);
} else {
ProcessVariableInUserFunction(func_ast, var, new_var_symbol, is_pointer);
if (var->AddressSpace() == ast::AddressSpace::kWorkgroup) {
needs_pointer_aliasing = true;
}
}
// Record the replacement symbol.
@@ -434,6 +438,12 @@ struct ModuleScopeVarToEntryPointParam::State {
ReplaceUsesInFunction(func_ast, var, new_var_symbol, is_pointer, is_wrapped);
}
// Allow pointer aliasing if needed.
if (needs_pointer_aliasing) {
ctx.InsertBack(func_ast->attributes,
ctx.dst->Disable(ast::DisabledValidation::kIgnorePointerAliasing));
}
if (!workgroup_parameter_members.IsEmpty()) {
// Create the workgroup memory parameter.
// The parameter is a struct that contains members for each workgroup variable.

View File

@@ -125,12 +125,14 @@ fn zoo(@internal(disable_validation__ignore_address_space) @internal(disable_val
*(tint_symbol) = (*(tint_symbol) * 2.0);
}
@internal(disable_validation__ignore_pointer_aliasing)
fn bar(a : f32, b : f32, @internal(disable_validation__ignore_address_space) @internal(disable_validation__ignore_invalid_pointer_argument) tint_symbol_1 : ptr<private, f32>, @internal(disable_validation__ignore_address_space) @internal(disable_validation__ignore_invalid_pointer_argument) tint_symbol_2 : ptr<workgroup, f32>) {
*(tint_symbol_1) = a;
*(tint_symbol_2) = b;
zoo(tint_symbol_1);
}
@internal(disable_validation__ignore_pointer_aliasing)
fn foo(a : f32, @internal(disable_validation__ignore_address_space) @internal(disable_validation__ignore_invalid_pointer_argument) tint_symbol_3 : ptr<private, f32>, @internal(disable_validation__ignore_address_space) @internal(disable_validation__ignore_invalid_pointer_argument) tint_symbol_4 : ptr<workgroup, f32>) {
let b : f32 = 2.0;
bar(a, b, tint_symbol_3, tint_symbol_4);
@@ -188,6 +190,7 @@ fn main() {
foo(1.0, &(tint_symbol_5), &(tint_symbol_6));
}
@internal(disable_validation__ignore_pointer_aliasing)
fn foo(a : f32, @internal(disable_validation__ignore_address_space) @internal(disable_validation__ignore_invalid_pointer_argument) tint_symbol_3 : ptr<private, f32>, @internal(disable_validation__ignore_address_space) @internal(disable_validation__ignore_invalid_pointer_argument) tint_symbol_4 : ptr<workgroup, f32>) {
let b : f32 = 2.0;
bar(a, b, tint_symbol_3, tint_symbol_4);
@@ -197,6 +200,7 @@ fn foo(a : f32, @internal(disable_validation__ignore_address_space) @internal(di
fn no_uses() {
}
@internal(disable_validation__ignore_pointer_aliasing)
fn bar(a : f32, b : f32, @internal(disable_validation__ignore_address_space) @internal(disable_validation__ignore_invalid_pointer_argument) tint_symbol_1 : ptr<private, f32>, @internal(disable_validation__ignore_address_space) @internal(disable_validation__ignore_invalid_pointer_argument) tint_symbol_2 : ptr<workgroup, f32>) {
*(tint_symbol_1) = a;
*(tint_symbol_2) = b;