|
| 1 | +export const description = ` |
| 2 | +Test statement behavior analysis. |
| 3 | +
|
| 4 | +Functions must have a behavior of {Return}, {Next}, or {Return, Next}. |
| 5 | +Functions with a return type must have a behavior of {Return}. |
| 6 | +
|
| 7 | +Each statement in the function must be valid according to the table. |
| 8 | +`; |
| 9 | + |
| 10 | +import { makeTestGroup } from '../../../../common/framework/test_group.js'; |
| 11 | +import { keysOf } from '../../../../common/util/data_tables.js'; |
| 12 | +import { ShaderValidationTest } from '../shader_validation_test.js'; |
| 13 | + |
| 14 | +export const g = makeTestGroup(ShaderValidationTest); |
| 15 | + |
| 16 | +const kInvalidStatements = { |
| 17 | + break: `break`, |
| 18 | + break_if: `break if true`, |
| 19 | + continue: `continue`, |
| 20 | + loop1: `loop { }`, |
| 21 | + loop2: `loop { continuing { } }`, |
| 22 | + loop3: `loop { continue; continuing { } }`, |
| 23 | + loop4: `loop { continuing { break; } }`, |
| 24 | + loop5: `loop { continuing { continue; } }`, |
| 25 | + loop6: `loop { continuing { return; } }`, |
| 26 | + loop7: `loop { continue; break; }`, |
| 27 | + loop8: `loop { continuing { break if true; return; } }`, |
| 28 | + for1: `for (;;) { }`, |
| 29 | + for2: `for (var i = 0; ; i++) { }`, |
| 30 | + for3: `for (;; break) { }`, |
| 31 | + for4: `for (;; continue ) { }`, |
| 32 | + for5: `for (;; return ) { }`, |
| 33 | + for6: `for (;;) { continue; break; }`, |
| 34 | + // while loops always have break in their behaviors. |
| 35 | + switch1: `switch (1) { case 1 { } }`, |
| 36 | + sequence1: `return; loop { }`, |
| 37 | + compound1: `{ loop { } }`, |
| 38 | +}; |
| 39 | + |
| 40 | +g.test('invalid_statements') |
| 41 | + .desc('Test statements with invalid behaviors') |
| 42 | + .specURL('https://gpuweb.github.io/gpuweb/wgsl/#behaviors-rules') |
| 43 | + .params(u => u.combine('body', keysOf(kInvalidStatements))) |
| 44 | + .fn(t => { |
| 45 | + const body = kInvalidStatements[t.params.body]; |
| 46 | + const code = `fn foo() { |
| 47 | + ${body}; |
| 48 | + }`; |
| 49 | + t.expectCompileResult(false, code); |
| 50 | + }); |
| 51 | + |
| 52 | +const kValidStatements = { |
| 53 | + empty: ``, |
| 54 | + const_assert: `const_assert true`, |
| 55 | + let: `let x = 1`, |
| 56 | + var1: `var x = 1`, |
| 57 | + var2: `var x : i32`, |
| 58 | + assign: `v = 1`, |
| 59 | + phony_assign: `_ = 1`, |
| 60 | + compound_assign: `v += 1`, |
| 61 | + return: `return`, |
| 62 | + discard: `discard`, |
| 63 | + function_call1: `bar()`, |
| 64 | + function_call2: `workgroupBarrier()`, |
| 65 | + |
| 66 | + if1: `if true { } else { }`, |
| 67 | + if2: `if true { }`, |
| 68 | + |
| 69 | + break1: `loop { break; }`, |
| 70 | + break2: `loop { if false { break; } }`, |
| 71 | + break_if: `loop { continuing { break if false; } }`, |
| 72 | + |
| 73 | + continue1: `loop { continue; continuing { break if true; } }`, |
| 74 | + |
| 75 | + loop1: `loop { break; }`, |
| 76 | + loop2: `loop { break; continuing { } }`, |
| 77 | + loop3: `loop { continue; continuing { break if true; } }`, |
| 78 | + loop4: `loop { break; continue; }`, |
| 79 | + |
| 80 | + for1: `for (; true; ) { }`, |
| 81 | + for2: `for (;;) { break; }`, |
| 82 | + for3: `for (;true;) { continue; }`, |
| 83 | + |
| 84 | + while1: `while true { }`, |
| 85 | + while2: `while true { continue; }`, |
| 86 | + while3: `while true { continue; break; }`, |
| 87 | + |
| 88 | + switch1: `switch 1 { default { } }`, |
| 89 | + swtich2: `switch 1 { case 1 { } default { } }`, |
| 90 | + switch3: `switch 1 { default { break; } }`, |
| 91 | + switch4: `switch 1 { default { } case 1 { break; } }`, |
| 92 | + |
| 93 | + sequence1: `return; let x = 1`, |
| 94 | + sequence2: `if true { } let x = 1`, |
| 95 | + sequence3: `switch 1 { default { break; return; } }`, |
| 96 | + |
| 97 | + compound1: `{ }`, |
| 98 | + compound2: `{ loop { break; } if true { return; } }`, |
| 99 | +}; |
| 100 | + |
| 101 | +g.test('valid_statements') |
| 102 | + .desc('Test statements with valid behaviors') |
| 103 | + .specURL('https://gpuweb.github.io/gpuweb/wgsl/#behaviors-rules') |
| 104 | + .params(u => u.combine('body', keysOf(kValidStatements))) |
| 105 | + .fn(t => { |
| 106 | + const body = kValidStatements[t.params.body]; |
| 107 | + const code = ` |
| 108 | + var<private> v : i32; |
| 109 | + fn bar() { } |
| 110 | + fn foo() { |
| 111 | + ${body}; |
| 112 | + }`; |
| 113 | + t.expectCompileResult(true, code); |
| 114 | + }); |
| 115 | + |
| 116 | +const kInvalidFunctions = { |
| 117 | + next_for_type: `fn foo() -> bool { }`, |
| 118 | + next_return_for_type: `fn foo() -> bool { if true { return true; } }`, |
| 119 | +}; |
| 120 | + |
| 121 | +g.test('invalid_functions') |
| 122 | + .desc('Test functions with invalid behaviors') |
| 123 | + .specURL('https://gpuweb.github.io/gpuweb/wgsl/#behaviors-rules') |
| 124 | + .params(u => u.combine('function', keysOf(kInvalidFunctions))) |
| 125 | + .fn(t => { |
| 126 | + const func = kInvalidFunctions[t.params.function]; |
| 127 | + t.expectCompileResult(false, func); |
| 128 | + }); |
| 129 | + |
| 130 | +const kValidFunctions = { |
| 131 | + empty: `fn foo() { }`, |
| 132 | + next_return: `fn foo() { if true { return; } }`, |
| 133 | + no_final_return: `fn foo() -> bool { if true { return true; } else { return false; } }`, |
| 134 | +}; |
| 135 | + |
| 136 | +g.test('valid_functions') |
| 137 | + .desc('Test functions with valid behaviors') |
| 138 | + .specURL('https://gpuweb.github.io/gpuweb/wgsl/#behaviors-rules') |
| 139 | + .params(u => u.combine('function', keysOf(kValidFunctions))) |
| 140 | + .fn(t => { |
| 141 | + const func = kValidFunctions[t.params.function]; |
| 142 | + t.expectCompileResult(true, func); |
| 143 | + }); |
0 commit comments