wgsl: Replace [[decoration]] with @decoration

Deprecate the old syntax. Migrate everything to the new syntax.

Bug: tint:1382
Change-Id: Ide12b2e927b17dc93b9714c7049090864cc568d3
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/77260
Reviewed-by: James Price <jrprice@google.com>
Kokoro: Kokoro <noreply+kokoro@google.com>
Reviewed-by: David Neto <dneto@google.com>
Commit-Queue: David Neto <dneto@google.com>
diff --git a/src/transform/add_empty_entry_point_test.cc b/src/transform/add_empty_entry_point_test.cc
index 722af1a..4cee0bc 100644
--- a/src/transform/add_empty_entry_point_test.cc
+++ b/src/transform/add_empty_entry_point_test.cc
@@ -28,7 +28,7 @@
   auto* src = R"()";
 
   auto* expect = R"(
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn unused_entry_point() {
 }
 )";
@@ -40,7 +40,7 @@
 
 TEST_F(AddEmptyEntryPointTest, ExistingEntryPoint) {
   auto* src = R"(
-[[stage(fragment)]]
+@stage(fragment)
 fn main() {
 }
 )";
@@ -56,7 +56,7 @@
   auto* src = R"(var<private> unused_entry_point : f32;)";
 
   auto* expect = R"(
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn unused_entry_point_1() {
 }
 
diff --git a/src/transform/add_spirv_block_decoration.h b/src/transform/add_spirv_block_decoration.h
index c5e67bb..2f23fb9 100644
--- a/src/transform/add_spirv_block_decoration.h
+++ b/src/transform/add_spirv_block_decoration.h
@@ -24,10 +24,10 @@
 namespace transform {
 
 /// AddSpirvBlockDecoration is a transform that adds an
-/// [[internal(spirv_block)]] attribute to any structure that is used as the
+/// `@internal(spirv_block)` attribute to any structure that is used as the
 /// store type of a buffer. If that structure is nested inside another structure
 /// or an array, then it is wrapped inside another structure which gets the
-/// [[internal(spirv_block)]] attribute instead.
+/// `@internal(spirv_block)` attribute instead.
 class AddSpirvBlockDecoration
     : public Castable<AddSpirvBlockDecoration, Transform> {
  public:
@@ -43,7 +43,7 @@
     ~SpirvBlockDecoration() override;
 
     /// @return a short description of the internal decoration which will be
-    /// displayed as `[[internal(<name>)]]`
+    /// displayed as `@internal(<name>)`
     std::string InternalName() const override;
 
     /// Performs a deep clone of this object using the CloneContext `ctx`.
diff --git a/src/transform/add_spirv_block_decoration_test.cc b/src/transform/add_spirv_block_decoration_test.cc
index e504c50..3a8455f 100644
--- a/src/transform/add_spirv_block_decoration_test.cc
+++ b/src/transform/add_spirv_block_decoration_test.cc
@@ -42,7 +42,7 @@
 
 var<private> p : S;
 
-[[stage(fragment)]]
+@stage(fragment)
 fn main() {
   p.f = 1.0;
 }
@@ -57,11 +57,11 @@
 TEST_F(AddSpirvBlockDecorationTest, Noop_UsedForShaderIO) {
   auto* src = R"(
 struct S {
-  [[location(0)]]
+  @location(0)
   f : f32;
 }
 
-[[stage(fragment)]]
+@stage(fragment)
 fn main() -> S {
   return S();
 }
@@ -75,23 +75,23 @@
 
 TEST_F(AddSpirvBlockDecorationTest, BasicScalar) {
   auto* src = R"(
-[[group(0), binding(0)]]
+@group(0) @binding(0)
 var<uniform> u : f32;
 
-[[stage(fragment)]]
+@stage(fragment)
 fn main() {
   let f = u;
 }
 )";
   auto* expect = R"(
-[[internal(spirv_block)]]
+@internal(spirv_block)
 struct u_block {
   inner : f32;
 }
 
-[[group(0), binding(0)]] var<uniform> u : u_block;
+@group(0) @binding(0) var<uniform> u : u_block;
 
-[[stage(fragment)]]
+@stage(fragment)
 fn main() {
   let f = u.inner;
 }
@@ -104,23 +104,23 @@
 
 TEST_F(AddSpirvBlockDecorationTest, BasicArray) {
   auto* src = R"(
-[[group(0), binding(0)]]
+@group(0) @binding(0)
 var<uniform> u : array<vec4<f32>, 4u>;
 
-[[stage(fragment)]]
+@stage(fragment)
 fn main() {
   let a = u;
 }
 )";
   auto* expect = R"(
-[[internal(spirv_block)]]
+@internal(spirv_block)
 struct u_block {
   inner : array<vec4<f32>, 4u>;
 }
 
-[[group(0), binding(0)]] var<uniform> u : u_block;
+@group(0) @binding(0) var<uniform> u : u_block;
 
-[[stage(fragment)]]
+@stage(fragment)
 fn main() {
   let a = u.inner;
 }
@@ -135,10 +135,10 @@
   auto* src = R"(
 type Numbers = array<vec4<f32>, 4u>;
 
-[[group(0), binding(0)]]
+@group(0) @binding(0)
 var<uniform> u : Numbers;
 
-[[stage(fragment)]]
+@stage(fragment)
 fn main() {
   let a = u;
 }
@@ -146,14 +146,14 @@
   auto* expect = R"(
 type Numbers = array<vec4<f32>, 4u>;
 
-[[internal(spirv_block)]]
+@internal(spirv_block)
 struct u_block {
   inner : array<vec4<f32>, 4u>;
 }
 
-[[group(0), binding(0)]] var<uniform> u : u_block;
+@group(0) @binding(0) var<uniform> u : u_block;
 
-[[stage(fragment)]]
+@stage(fragment)
 fn main() {
   let a = u.inner;
 }
@@ -170,23 +170,23 @@
   f : f32;
 };
 
-[[group(0), binding(0)]]
+@group(0) @binding(0)
 var<uniform> u : S;
 
-[[stage(fragment)]]
+@stage(fragment)
 fn main() {
   let f = u.f;
 }
 )";
   auto* expect = R"(
-[[internal(spirv_block)]]
+@internal(spirv_block)
 struct S {
   f : f32;
 }
 
-[[group(0), binding(0)]] var<uniform> u : S;
+@group(0) @binding(0) var<uniform> u : S;
 
-[[stage(fragment)]]
+@stage(fragment)
 fn main() {
   let f = u.f;
 }
@@ -207,10 +207,10 @@
   i : Inner;
 };
 
-[[group(0), binding(0)]]
+@group(0) @binding(0)
 var<uniform> u : Outer;
 
-[[stage(fragment)]]
+@stage(fragment)
 fn main() {
   let f = u.i.f;
 }
@@ -220,14 +220,14 @@
   f : f32;
 }
 
-[[internal(spirv_block)]]
+@internal(spirv_block)
 struct Outer {
   i : Inner;
 }
 
-[[group(0), binding(0)]] var<uniform> u : Outer;
+@group(0) @binding(0) var<uniform> u : Outer;
 
-[[stage(fragment)]]
+@stage(fragment)
 fn main() {
   let f = u.i.f;
 }
@@ -248,13 +248,13 @@
   i : Inner;
 };
 
-[[group(0), binding(0)]]
+@group(0) @binding(0)
 var<uniform> u0 : Outer;
 
-[[group(0), binding(1)]]
+@group(0) @binding(1)
 var<uniform> u1 : Inner;
 
-[[stage(fragment)]]
+@stage(fragment)
 fn main() {
   let f0 = u0.i.f;
   let f1 = u1.f;
@@ -265,21 +265,21 @@
   f : f32;
 }
 
-[[internal(spirv_block)]]
+@internal(spirv_block)
 struct Outer {
   i : Inner;
 }
 
-[[group(0), binding(0)]] var<uniform> u0 : Outer;
+@group(0) @binding(0) var<uniform> u0 : Outer;
 
-[[internal(spirv_block)]]
+@internal(spirv_block)
 struct u1_block {
   inner : Inner;
 }
 
-[[group(0), binding(1)]] var<uniform> u1 : u1_block;
+@group(0) @binding(1) var<uniform> u1 : u1_block;
 
-[[stage(fragment)]]
+@stage(fragment)
 fn main() {
   let f0 = u0.i.f;
   let f1 = u1.inner.f;
@@ -303,10 +303,10 @@
 
 var<private> p : Outer;
 
-[[group(0), binding(1)]]
+@group(0) @binding(1)
 var<uniform> u : Inner;
 
-[[stage(fragment)]]
+@stage(fragment)
 fn main() {
   let f0 = p.i.f;
   let f1 = u.f;
@@ -323,14 +323,14 @@
 
 var<private> p : Outer;
 
-[[internal(spirv_block)]]
+@internal(spirv_block)
 struct u_block {
   inner : Inner;
 }
 
-[[group(0), binding(1)]] var<uniform> u : u_block;
+@group(0) @binding(1) var<uniform> u : u_block;
 
-[[stage(fragment)]]
+@stage(fragment)
 fn main() {
   let f0 = p.i.f;
   let f1 = u.inner.f;
@@ -352,16 +352,16 @@
   i : Inner;
 };
 
-[[group(0), binding(0)]]
+@group(0) @binding(0)
 var<uniform> u0 : S;
 
-[[group(0), binding(1)]]
+@group(0) @binding(1)
 var<uniform> u1 : Inner;
 
-[[group(0), binding(2)]]
+@group(0) @binding(2)
 var<uniform> u2 : Inner;
 
-[[stage(fragment)]]
+@stage(fragment)
 fn main() {
   let f0 = u0.i.f;
   let f1 = u1.f;
@@ -373,23 +373,23 @@
   f : f32;
 }
 
-[[internal(spirv_block)]]
+@internal(spirv_block)
 struct S {
   i : Inner;
 }
 
-[[group(0), binding(0)]] var<uniform> u0 : S;
+@group(0) @binding(0) var<uniform> u0 : S;
 
-[[internal(spirv_block)]]
+@internal(spirv_block)
 struct u1_block {
   inner : Inner;
 }
 
-[[group(0), binding(1)]] var<uniform> u1 : u1_block;
+@group(0) @binding(1) var<uniform> u1 : u1_block;
 
-[[group(0), binding(2)]] var<uniform> u2 : u1_block;
+@group(0) @binding(2) var<uniform> u2 : u1_block;
 
-[[stage(fragment)]]
+@stage(fragment)
 fn main() {
   let f0 = u0.i.f;
   let f1 = u1.inner.f;
@@ -408,10 +408,10 @@
   f : f32;
 };
 
-[[group(0), binding(0)]]
+@group(0) @binding(0)
 var<uniform> u : S;
 
-[[stage(fragment)]]
+@stage(fragment)
 fn main() {
   let f = u.f;
   let a = array<S, 4>();
@@ -422,14 +422,14 @@
   f : f32;
 }
 
-[[internal(spirv_block)]]
+@internal(spirv_block)
 struct u_block {
   inner : S;
 }
 
-[[group(0), binding(0)]] var<uniform> u : u_block;
+@group(0) @binding(0) var<uniform> u : u_block;
 
-[[stage(fragment)]]
+@stage(fragment)
 fn main() {
   let f = u.inner.f;
   let a = array<S, 4>();
@@ -447,13 +447,13 @@
   f : f32;
 };
 
-[[group(0), binding(0)]]
+@group(0) @binding(0)
 var<uniform> u0 : S;
 
-[[group(0), binding(1)]]
+@group(0) @binding(1)
 var<uniform> u1 : S;
 
-[[stage(fragment)]]
+@stage(fragment)
 fn main() {
   let f0 = u0.f;
   let f1 = u1.f;
@@ -465,16 +465,16 @@
   f : f32;
 }
 
-[[internal(spirv_block)]]
+@internal(spirv_block)
 struct u0_block {
   inner : S;
 }
 
-[[group(0), binding(0)]] var<uniform> u0 : u0_block;
+@group(0) @binding(0) var<uniform> u0 : u0_block;
 
-[[group(0), binding(1)]] var<uniform> u1 : u0_block;
+@group(0) @binding(1) var<uniform> u1 : u0_block;
 
-[[stage(fragment)]]
+@stage(fragment)
 fn main() {
   let f0 = u0.inner.f;
   let f1 = u1.inner.f;
@@ -501,13 +501,13 @@
 
 type MyOuter = Outer;
 
-[[group(0), binding(0)]]
+@group(0) @binding(0)
 var<uniform> u0 : MyOuter;
 
-[[group(0), binding(1)]]
+@group(0) @binding(1)
 var<uniform> u1 : MyInner;
 
-[[stage(fragment)]]
+@stage(fragment)
 fn main() {
   let f0 = u0.i.f;
   let f1 = u1.f;
@@ -520,23 +520,23 @@
 
 type MyInner = Inner;
 
-[[internal(spirv_block)]]
+@internal(spirv_block)
 struct Outer {
   i : MyInner;
 }
 
 type MyOuter = Outer;
 
-[[group(0), binding(0)]] var<uniform> u0 : MyOuter;
+@group(0) @binding(0) var<uniform> u0 : MyOuter;
 
-[[internal(spirv_block)]]
+@internal(spirv_block)
 struct u1_block {
   inner : Inner;
 }
 
-[[group(0), binding(1)]] var<uniform> u1 : u1_block;
+@group(0) @binding(1) var<uniform> u1 : u1_block;
 
-[[stage(fragment)]]
+@stage(fragment)
 fn main() {
   let f0 = u0.i.f;
   let f1 = u1.inner.f;
diff --git a/src/transform/array_length_from_uniform.h b/src/transform/array_length_from_uniform.h
index 6ab1598..bd7a461 100644
--- a/src/transform/array_length_from_uniform.h
+++ b/src/transform/array_length_from_uniform.h
@@ -38,7 +38,7 @@
 ///  buffer_size : array<u32, 8>;
 /// };
 ///
-/// [[group(0), binding(30)]]
+/// @group(0) @binding(30)
 /// var<uniform> buffer_size_ubo : buffer_size_struct;
 /// ```
 /// The binding group and number used for this uniform buffer is provided via
diff --git a/src/transform/array_length_from_uniform_test.cc b/src/transform/array_length_from_uniform_test.cc
index b9139a9..944fc6a 100644
--- a/src/transform/array_length_from_uniform_test.cc
+++ b/src/transform/array_length_from_uniform_test.cc
@@ -52,9 +52,9 @@
 
 TEST_F(ArrayLengthFromUniformTest, Basic) {
   auto* src = R"(
-[[group(0), binding(0)]] var<storage, read> sb : array<i32>;
+@group(0) @binding(0) var<storage, read> sb : array<i32>;
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn main() {
   var len : u32 = arrayLength(&sb);
 }
@@ -65,11 +65,11 @@
   buffer_size : array<vec4<u32>, 1u>;
 }
 
-[[group(0), binding(30)]] var<uniform> tint_symbol_1 : tint_symbol;
+@group(0) @binding(30) var<uniform> tint_symbol_1 : tint_symbol;
 
-[[group(0), binding(0)]] var<storage, read> sb : array<i32>;
+@group(0) @binding(0) var<storage, read> sb : array<i32>;
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn main() {
   var len : u32 = (tint_symbol_1.buffer_size[0u][0u] / 4u);
 }
@@ -95,9 +95,9 @@
   arr : array<i32>;
 };
 
-[[group(0), binding(0)]] var<storage, read> sb : SB;
+@group(0) @binding(0) var<storage, read> sb : SB;
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn main() {
   var len : u32 = arrayLength(&sb.arr);
 }
@@ -108,16 +108,16 @@
   buffer_size : array<vec4<u32>, 1u>;
 }
 
-[[group(0), binding(30)]] var<uniform> tint_symbol_1 : tint_symbol;
+@group(0) @binding(30) var<uniform> tint_symbol_1 : tint_symbol;
 
 struct SB {
   x : i32;
   arr : array<i32>;
 }
 
-[[group(0), binding(0)]] var<storage, read> sb : SB;
+@group(0) @binding(0) var<storage, read> sb : SB;
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn main() {
   var len : u32 = ((tint_symbol_1.buffer_size[0u][0u] - 4u) / 4u);
 }
@@ -138,9 +138,9 @@
 
 TEST_F(ArrayLengthFromUniformTest, WithStride) {
   auto* src = R"(
-[[group(0), binding(0)]] var<storage, read> sb : [[stride(64)]] array<i32>;
+@group(0) @binding(0) var<storage, read> sb : @stride(64) array<i32>;
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn main() {
   var len : u32 = arrayLength(&sb);
 }
@@ -151,11 +151,11 @@
   buffer_size : array<vec4<u32>, 1u>;
 }
 
-[[group(0), binding(30)]] var<uniform> tint_symbol_1 : tint_symbol;
+@group(0) @binding(30) var<uniform> tint_symbol_1 : tint_symbol;
 
-[[group(0), binding(0)]] var<storage, read> sb : [[stride(64)]] array<i32>;
+@group(0) @binding(0) var<storage, read> sb : @stride(64) array<i32>;
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn main() {
   var len : u32 = (tint_symbol_1.buffer_size[0u][0u] / 64u);
 }
@@ -179,12 +179,12 @@
 struct SB {
   x : i32;
   y : f32;
-  arr : [[stride(64)]] array<i32>;
+  arr : @stride(64) array<i32>;
 };
 
-[[group(0), binding(0)]] var<storage, read> sb : SB;
+@group(0) @binding(0) var<storage, read> sb : SB;
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn main() {
   var len : u32 = arrayLength(&sb.arr);
 }
@@ -195,17 +195,17 @@
   buffer_size : array<vec4<u32>, 1u>;
 }
 
-[[group(0), binding(30)]] var<uniform> tint_symbol_1 : tint_symbol;
+@group(0) @binding(30) var<uniform> tint_symbol_1 : tint_symbol;
 
 struct SB {
   x : i32;
   y : f32;
-  arr : [[stride(64)]] array<i32>;
+  arr : @stride(64) array<i32>;
 }
 
-[[group(0), binding(0)]] var<storage, read> sb : SB;
+@group(0) @binding(0) var<storage, read> sb : SB;
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn main() {
   var len : u32 = ((tint_symbol_1.buffer_size[0u][0u] - 8u) / 64u);
 }
@@ -239,13 +239,13 @@
   arr4 : array<vec4<f32>>;
 };
 
-[[group(0), binding(2)]] var<storage, read> sb1 : SB1;
-[[group(1), binding(2)]] var<storage, read> sb2 : SB2;
-[[group(2), binding(2)]] var<storage, read> sb3 : array<vec4<f32>>;
-[[group(3), binding(2)]] var<storage, read> sb4 : SB4;
-[[group(4), binding(2)]] var<storage, read> sb5 : array<vec4<f32>>;
+@group(0) @binding(2) var<storage, read> sb1 : SB1;
+@group(1) @binding(2) var<storage, read> sb2 : SB2;
+@group(2) @binding(2) var<storage, read> sb3 : array<vec4<f32>>;
+@group(3) @binding(2) var<storage, read> sb4 : SB4;
+@group(4) @binding(2) var<storage, read> sb5 : array<vec4<f32>>;
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn main() {
   var len1 : u32 = arrayLength(&(sb1.arr1));
   var len2 : u32 = arrayLength(&(sb2.arr2));
@@ -261,7 +261,7 @@
   buffer_size : array<vec4<u32>, 2u>;
 }
 
-[[group(0), binding(30)]] var<uniform> tint_symbol_1 : tint_symbol;
+@group(0) @binding(30) var<uniform> tint_symbol_1 : tint_symbol;
 
 struct SB1 {
   x : i32;
@@ -278,17 +278,17 @@
   arr4 : array<vec4<f32>>;
 }
 
-[[group(0), binding(2)]] var<storage, read> sb1 : SB1;
+@group(0) @binding(2) var<storage, read> sb1 : SB1;
 
-[[group(1), binding(2)]] var<storage, read> sb2 : SB2;
+@group(1) @binding(2) var<storage, read> sb2 : SB2;
 
-[[group(2), binding(2)]] var<storage, read> sb3 : array<vec4<f32>>;
+@group(2) @binding(2) var<storage, read> sb3 : array<vec4<f32>>;
 
-[[group(3), binding(2)]] var<storage, read> sb4 : SB4;
+@group(3) @binding(2) var<storage, read> sb4 : SB4;
 
-[[group(4), binding(2)]] var<storage, read> sb5 : array<vec4<f32>>;
+@group(4) @binding(2) var<storage, read> sb5 : array<vec4<f32>>;
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn main() {
   var len1 : u32 = ((tint_symbol_1.buffer_size[0u][0u] - 4u) / 4u);
   var len2 : u32 = ((tint_symbol_1.buffer_size[0u][1u] - 16u) / 16u);
@@ -331,13 +331,13 @@
   arr4 : array<vec4<f32>>;
 };
 
-[[group(0), binding(2)]] var<storage, read> sb1 : SB1;
-[[group(1), binding(2)]] var<storage, read> sb2 : SB2;
-[[group(2), binding(2)]] var<storage, read> sb3 : array<vec4<f32>>;
-[[group(3), binding(2)]] var<storage, read> sb4 : SB4;
-[[group(4), binding(2)]] var<storage, read> sb5 : array<vec4<f32>>;
+@group(0) @binding(2) var<storage, read> sb1 : SB1;
+@group(1) @binding(2) var<storage, read> sb2 : SB2;
+@group(2) @binding(2) var<storage, read> sb3 : array<vec4<f32>>;
+@group(3) @binding(2) var<storage, read> sb4 : SB4;
+@group(4) @binding(2) var<storage, read> sb5 : array<vec4<f32>>;
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn main() {
   var len1 : u32 = arrayLength(&(sb1.arr1));
   var len3 : u32 = arrayLength(&sb3);
@@ -350,7 +350,7 @@
   buffer_size : array<vec4<u32>, 1u>;
 }
 
-[[group(0), binding(30)]] var<uniform> tint_symbol_1 : tint_symbol;
+@group(0) @binding(30) var<uniform> tint_symbol_1 : tint_symbol;
 
 struct SB1 {
   x : i32;
@@ -367,17 +367,17 @@
   arr4 : array<vec4<f32>>;
 }
 
-[[group(0), binding(2)]] var<storage, read> sb1 : SB1;
+@group(0) @binding(2) var<storage, read> sb1 : SB1;
 
-[[group(1), binding(2)]] var<storage, read> sb2 : SB2;
+@group(1) @binding(2) var<storage, read> sb2 : SB2;
 
-[[group(2), binding(2)]] var<storage, read> sb3 : array<vec4<f32>>;
+@group(2) @binding(2) var<storage, read> sb3 : array<vec4<f32>>;
 
-[[group(3), binding(2)]] var<storage, read> sb4 : SB4;
+@group(3) @binding(2) var<storage, read> sb4 : SB4;
 
-[[group(4), binding(2)]] var<storage, read> sb5 : array<vec4<f32>>;
+@group(4) @binding(2) var<storage, read> sb5 : array<vec4<f32>>;
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn main() {
   var len1 : u32 = ((tint_symbol_1.buffer_size[0u][0u] - 4u) / 4u);
   var len3 : u32 = (tint_symbol_1.buffer_size[0u][2u] / 16u);
@@ -409,9 +409,9 @@
   arr : array<i32>;
 }
 
-[[group(0), binding(0)]] var<storage, read> sb : SB;
+@group(0) @binding(0) var<storage, read> sb : SB;
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn main() {
   ignore(&(sb.arr));
 }
@@ -442,11 +442,11 @@
   arr2 : array<vec4<f32>>;
 };
 
-[[group(0), binding(2)]] var<storage, read> sb1 : SB1;
+@group(0) @binding(2) var<storage, read> sb1 : SB1;
 
-[[group(1), binding(2)]] var<storage, read> sb2 : SB2;
+@group(1) @binding(2) var<storage, read> sb2 : SB2;
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn main() {
   var len1 : u32 = arrayLength(&(sb1.arr1));
   var len2 : u32 = arrayLength(&(sb2.arr2));
@@ -459,7 +459,7 @@
   buffer_size : array<vec4<u32>, 1u>;
 }
 
-[[group(0), binding(30)]] var<uniform> tint_symbol_1 : tint_symbol;
+@group(0) @binding(30) var<uniform> tint_symbol_1 : tint_symbol;
 
 struct SB1 {
   x : i32;
@@ -471,11 +471,11 @@
   arr2 : array<vec4<f32>>;
 }
 
-[[group(0), binding(2)]] var<storage, read> sb1 : SB1;
+@group(0) @binding(2) var<storage, read> sb1 : SB1;
 
-[[group(1), binding(2)]] var<storage, read> sb2 : SB2;
+@group(1) @binding(2) var<storage, read> sb2 : SB2;
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn main() {
   var len1 : u32 = ((tint_symbol_1.buffer_size[0u][0u] - 4u) / 4u);
   var len2 : u32 = arrayLength(&(sb2.arr2));
diff --git a/src/transform/binding_remapper_test.cc b/src/transform/binding_remapper_test.cc
index de85cb0..5827cb2 100644
--- a/src/transform/binding_remapper_test.cc
+++ b/src/transform/binding_remapper_test.cc
@@ -30,11 +30,11 @@
   a : f32;
 }
 
-[[group(2), binding(1)]] var<storage, read> a : S;
+@group(2) @binding(1) var<storage, read> a : S;
 
-[[group(3), binding(2)]] var<storage, read> b : S;
+@group(3) @binding(2) var<storage, read> b : S;
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn f() {
 }
 )";
@@ -55,11 +55,11 @@
   a : f32;
 };
 
-[[group(2), binding(1)]] var<storage, read> a : S;
+@group(2) @binding(1) var<storage, read> a : S;
 
-[[group(3), binding(2)]] var<storage, read> b : S;
+@group(3) @binding(2) var<storage, read> b : S;
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn f() {
 }
 )";
@@ -69,11 +69,11 @@
   a : f32;
 }
 
-[[group(1), binding(2)]] var<storage, read> a : S;
+@group(1) @binding(2) var<storage, read> a : S;
 
-[[group(3), binding(2)]] var<storage, read> b : S;
+@group(3) @binding(2) var<storage, read> b : S;
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn f() {
 }
 )";
@@ -83,7 +83,7 @@
       BindingRemapper::BindingPoints{
           {{2, 1}, {1, 2}},  // Remap
           {{4, 5}, {6, 7}},  // Not found
-                             // Keep [[group(3), binding(2)]] as is
+                             // Keep @group(3) @binding(2) as is
       },
       BindingRemapper::AccessControls{});
   auto got = Run<BindingRemapper>(src, data);
@@ -97,13 +97,13 @@
   a : f32;
 };
 
-[[group(2), binding(1)]] var<storage, read> a : S;
+@group(2) @binding(1) var<storage, read> a : S;
 
-[[group(3), binding(2)]] var<storage, write> b : S;
+@group(3) @binding(2) var<storage, write> b : S;
 
-[[group(4), binding(3)]] var<storage, read> c : S;
+@group(4) @binding(3) var<storage, read> c : S;
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn f() {
 }
 )";
@@ -113,13 +113,13 @@
   a : f32;
 }
 
-[[group(2), binding(1)]] var<storage, write> a : S;
+@group(2) @binding(1) var<storage, write> a : S;
 
-[[group(3), binding(2)]] var<storage, write> b : S;
+@group(3) @binding(2) var<storage, write> b : S;
 
-[[group(4), binding(3)]] var<storage, read> c : S;
+@group(4) @binding(3) var<storage, read> c : S;
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn f() {
 }
 )";
@@ -129,7 +129,7 @@
       BindingRemapper::BindingPoints{},
       BindingRemapper::AccessControls{
           {{2, 1}, ast::Access::kWrite},  // Modify access control
-          // Keep [[group(3), binding(2)]] as is
+          // Keep @group(3) @binding(2) as is
           {{4, 3}, ast::Access::kRead},  // Add access control
       });
   auto got = Run<BindingRemapper>(src, data);
@@ -151,13 +151,13 @@
 
 type A = S;
 
-[[group(2), binding(1)]] var<storage> a : ReadOnlyS;
+@group(2) @binding(1) var<storage> a : ReadOnlyS;
 
-[[group(3), binding(2)]] var<storage> b : WriteOnlyS;
+@group(3) @binding(2) var<storage> b : WriteOnlyS;
 
-[[group(4), binding(3)]] var<storage> c : A;
+@group(4) @binding(3) var<storage> c : A;
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn f() {
 }
 )";
@@ -173,13 +173,13 @@
 
 type A = S;
 
-[[group(2), binding(1)]] var<storage, write> a : S;
+@group(2) @binding(1) var<storage, write> a : S;
 
-[[group(3), binding(2)]] var<storage> b : WriteOnlyS;
+@group(3) @binding(2) var<storage> b : WriteOnlyS;
 
-[[group(4), binding(3)]] var<storage, write> c : S;
+@group(4) @binding(3) var<storage, write> c : S;
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn f() {
 }
 )";
@@ -189,7 +189,7 @@
       BindingRemapper::BindingPoints{},
       BindingRemapper::AccessControls{
           {{2, 1}, ast::Access::kWrite},  // Modify access control
-          // Keep [[group(3), binding(2)]] as is
+          // Keep @group(3) @binding(2) as is
           {{4, 3}, ast::Access::kRead},  // Add access control
       });
   auto got = Run<BindingRemapper>(src, data);
@@ -203,11 +203,11 @@
   a : f32;
 };
 
-[[group(2), binding(1)]] var<storage, read> a : S;
+@group(2) @binding(1) var<storage, read> a : S;
 
-[[group(3), binding(2)]] var<storage, read> b : S;
+@group(3) @binding(2) var<storage, read> b : S;
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn f() {
 }
 )";
@@ -217,11 +217,11 @@
   a : f32;
 }
 
-[[group(4), binding(5)]] var<storage, write> a : S;
+@group(4) @binding(5) var<storage, write> a : S;
 
-[[group(6), binding(7)]] var<storage, write> b : S;
+@group(6) @binding(7) var<storage, write> b : S;
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn f() {
 }
 )";
@@ -247,15 +247,15 @@
   i : i32;
 };
 
-[[group(2), binding(1)]] var<storage, read> a : S;
+@group(2) @binding(1) var<storage, read> a : S;
 
-[[group(3), binding(2)]] var<storage, read> b : S;
+@group(3) @binding(2) var<storage, read> b : S;
 
-[[group(4), binding(3)]] var<storage, read> c : S;
+@group(4) @binding(3) var<storage, read> c : S;
 
-[[group(5), binding(4)]] var<storage, read> d : S;
+@group(5) @binding(4) var<storage, read> d : S;
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn f() {
   let x : i32 = (((a.i + b.i) + c.i) + d.i);
 }
@@ -266,15 +266,15 @@
   i : i32;
 }
 
-[[internal(disable_validation__binding_point_collision), group(1), binding(1)]] var<storage, read> a : S;
+@internal(disable_validation__binding_point_collision) @group(1) @binding(1) var<storage, read> a : S;
 
-[[internal(disable_validation__binding_point_collision), group(1), binding(1)]] var<storage, read> b : S;
+@internal(disable_validation__binding_point_collision) @group(1) @binding(1) var<storage, read> b : S;
 
-[[internal(disable_validation__binding_point_collision), group(5), binding(4)]] var<storage, read> c : S;
+@internal(disable_validation__binding_point_collision) @group(5) @binding(4) var<storage, read> c : S;
 
-[[internal(disable_validation__binding_point_collision), group(5), binding(4)]] var<storage, read> d : S;
+@internal(disable_validation__binding_point_collision) @group(5) @binding(4) var<storage, read> d : S;
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn f() {
   let x : i32 = (((a.i + b.i) + c.i) + d.i);
 }
@@ -299,20 +299,20 @@
   i : i32;
 };
 
-[[group(2), binding(1)]] var<storage, read> a : S;
+@group(2) @binding(1) var<storage, read> a : S;
 
-[[group(3), binding(2)]] var<storage, read> b : S;
+@group(3) @binding(2) var<storage, read> b : S;
 
-[[group(4), binding(3)]] var<storage, read> c : S;
+@group(4) @binding(3) var<storage, read> c : S;
 
-[[group(5), binding(4)]] var<storage, read> d : S;
+@group(5) @binding(4) var<storage, read> d : S;
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn f1() {
   let x : i32 = (a.i + c.i);
 }
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn f2() {
   let x : i32 = (b.i + d.i);
 }
@@ -323,20 +323,20 @@
   i : i32;
 }
 
-[[group(1), binding(1)]] var<storage, read> a : S;
+@group(1) @binding(1) var<storage, read> a : S;
 
-[[group(1), binding(1)]] var<storage, read> b : S;
+@group(1) @binding(1) var<storage, read> b : S;
 
-[[group(5), binding(4)]] var<storage, read> c : S;
+@group(5) @binding(4) var<storage, read> c : S;
 
-[[group(5), binding(4)]] var<storage, read> d : S;
+@group(5) @binding(4) var<storage, read> d : S;
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn f1() {
   let x : i32 = (a.i + c.i);
 }
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn f2() {
   let x : i32 = (b.i + d.i);
 }
@@ -361,10 +361,10 @@
   a : f32;
 };
 
-[[group(2), binding(1)]] var<storage, read> a : S;
-[[group(3), binding(2)]] var<storage, read> b : S;
+@group(2) @binding(1) var<storage, read> a : S;
+@group(3) @binding(2) var<storage, read> b : S;
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn f() {}
 )";
 
diff --git a/src/transform/calculate_array_length_test.cc b/src/transform/calculate_array_length_test.cc
index 83e0ac7..88643ae 100644
--- a/src/transform/calculate_array_length_test.cc
+++ b/src/transform/calculate_array_length_test.cc
@@ -38,21 +38,21 @@
 
 TEST_F(CalculateArrayLengthTest, Basic) {
   auto* src = R"(
-[[group(0), binding(0)]] var<storage, read> sb : array<i32>;
+@group(0) @binding(0) var<storage, read> sb : array<i32>;
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn main() {
   var len : u32 = arrayLength(&sb);
 }
 )";
 
   auto* expect = R"(
-[[internal(intrinsic_buffer_size)]]
-fn tint_symbol([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : array<i32>, result : ptr<function, u32>)
+@internal(intrinsic_buffer_size)
+fn tint_symbol(@internal(disable_validation__ignore_constructible_function_parameter) buffer : array<i32>, result : ptr<function, u32>)
 
-[[group(0), binding(0)]] var<storage, read> sb : array<i32>;
+@group(0) @binding(0) var<storage, read> sb : array<i32>;
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn main() {
   var tint_symbol_1 : u32 = 0u;
   tint_symbol(sb, &(tint_symbol_1));
@@ -73,9 +73,9 @@
   arr : array<i32>;
 };
 
-[[group(0), binding(0)]] var<storage, read> sb : SB;
+@group(0) @binding(0) var<storage, read> sb : SB;
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn main() {
   var len : u32 = arrayLength(&sb.arr);
 }
@@ -87,12 +87,12 @@
   arr : array<i32>;
 }
 
-[[internal(intrinsic_buffer_size)]]
-fn tint_symbol([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : SB, result : ptr<function, u32>)
+@internal(intrinsic_buffer_size)
+fn tint_symbol(@internal(disable_validation__ignore_constructible_function_parameter) buffer : SB, result : ptr<function, u32>)
 
-[[group(0), binding(0)]] var<storage, read> sb : SB;
+@group(0) @binding(0) var<storage, read> sb : SB;
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn main() {
   var tint_symbol_1 : u32 = 0u;
   tint_symbol(sb, &(tint_symbol_1));
@@ -108,9 +108,9 @@
 
 TEST_F(CalculateArrayLengthTest, InSameBlock) {
   auto* src = R"(
-[[group(0), binding(0)]] var<storage, read> sb : array<i32>;;
+@group(0) @binding(0) var<storage, read> sb : array<i32>;;
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn main() {
   var a : u32 = arrayLength(&sb);
   var b : u32 = arrayLength(&sb);
@@ -119,12 +119,12 @@
 )";
 
   auto* expect = R"(
-[[internal(intrinsic_buffer_size)]]
-fn tint_symbol([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : array<i32>, result : ptr<function, u32>)
+@internal(intrinsic_buffer_size)
+fn tint_symbol(@internal(disable_validation__ignore_constructible_function_parameter) buffer : array<i32>, result : ptr<function, u32>)
 
-[[group(0), binding(0)]] var<storage, read> sb : array<i32>;
+@group(0) @binding(0) var<storage, read> sb : array<i32>;
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn main() {
   var tint_symbol_1 : u32 = 0u;
   tint_symbol(sb, &(tint_symbol_1));
@@ -147,9 +147,9 @@
   arr : array<i32>;
 };
 
-[[group(0), binding(0)]] var<storage, read> sb : SB;
+@group(0) @binding(0) var<storage, read> sb : SB;
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn main() {
   var a : u32 = arrayLength(&sb.arr);
   var b : u32 = arrayLength(&sb.arr);
@@ -163,12 +163,12 @@
   arr : array<i32>;
 }
 
-[[internal(intrinsic_buffer_size)]]
-fn tint_symbol([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : SB, result : ptr<function, u32>)
+@internal(intrinsic_buffer_size)
+fn tint_symbol(@internal(disable_validation__ignore_constructible_function_parameter) buffer : SB, result : ptr<function, u32>)
 
-[[group(0), binding(0)]] var<storage, read> sb : SB;
+@group(0) @binding(0) var<storage, read> sb : SB;
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn main() {
   var tint_symbol_1 : u32 = 0u;
   tint_symbol(sb, &(tint_symbol_1));
@@ -186,21 +186,21 @@
 
 TEST_F(CalculateArrayLengthTest, WithStride) {
   auto* src = R"(
-[[group(0), binding(0)]] var<storage, read> sb : [[stride(64)]] array<i32>;
+@group(0) @binding(0) var<storage, read> sb : @stride(64) array<i32>;
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn main() {
   var len : u32 = arrayLength(&sb);
 }
 )";
 
   auto* expect = R"(
-[[internal(intrinsic_buffer_size)]]
-fn tint_symbol([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : [[stride(64)]] array<i32>, result : ptr<function, u32>)
+@internal(intrinsic_buffer_size)
+fn tint_symbol(@internal(disable_validation__ignore_constructible_function_parameter) buffer : @stride(64) array<i32>, result : ptr<function, u32>)
 
-[[group(0), binding(0)]] var<storage, read> sb : [[stride(64)]] array<i32>;
+@group(0) @binding(0) var<storage, read> sb : @stride(64) array<i32>;
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn main() {
   var tint_symbol_1 : u32 = 0u;
   tint_symbol(sb, &(tint_symbol_1));
@@ -219,12 +219,12 @@
 struct SB {
   x : i32;
   y : f32;
-  arr : [[stride(64)]] array<i32>;
+  arr : @stride(64) array<i32>;
 };
 
-[[group(0), binding(0)]] var<storage, read> sb : SB;
+@group(0) @binding(0) var<storage, read> sb : SB;
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn main() {
   var len : u32 = arrayLength(&sb.arr);
 }
@@ -234,15 +234,15 @@
 struct SB {
   x : i32;
   y : f32;
-  arr : [[stride(64)]] array<i32>;
+  arr : @stride(64) array<i32>;
 }
 
-[[internal(intrinsic_buffer_size)]]
-fn tint_symbol([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : SB, result : ptr<function, u32>)
+@internal(intrinsic_buffer_size)
+fn tint_symbol(@internal(disable_validation__ignore_constructible_function_parameter) buffer : SB, result : ptr<function, u32>)
 
-[[group(0), binding(0)]] var<storage, read> sb : SB;
+@group(0) @binding(0) var<storage, read> sb : SB;
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn main() {
   var tint_symbol_1 : u32 = 0u;
   tint_symbol(sb, &(tint_symbol_1));
@@ -263,9 +263,9 @@
   arr : array<i32>;
 };
 
-[[group(0), binding(0)]] var<storage, read> sb : SB;
+@group(0) @binding(0) var<storage, read> sb : SB;
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn main() {
   if (true) {
     var len : u32 = arrayLength(&sb.arr);
@@ -283,12 +283,12 @@
   arr : array<i32>;
 }
 
-[[internal(intrinsic_buffer_size)]]
-fn tint_symbol([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : SB, result : ptr<function, u32>)
+@internal(intrinsic_buffer_size)
+fn tint_symbol(@internal(disable_validation__ignore_constructible_function_parameter) buffer : SB, result : ptr<function, u32>)
 
-[[group(0), binding(0)]] var<storage, read> sb : SB;
+@group(0) @binding(0) var<storage, read> sb : SB;
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn main() {
   if (true) {
     var tint_symbol_1 : u32 = 0u;
@@ -323,13 +323,13 @@
   arr2 : array<vec4<f32>>;
 };
 
-[[group(0), binding(0)]] var<storage, read> sb1 : SB1;
+@group(0) @binding(0) var<storage, read> sb1 : SB1;
 
-[[group(0), binding(1)]] var<storage, read> sb2 : SB2;
+@group(0) @binding(1) var<storage, read> sb2 : SB2;
 
-[[group(0), binding(2)]] var<storage, read> sb3 : array<i32>;
+@group(0) @binding(2) var<storage, read> sb3 : array<i32>;
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn main() {
   var len1 : u32 = arrayLength(&(sb1.arr1));
   var len2 : u32 = arrayLength(&(sb2.arr2));
@@ -339,32 +339,32 @@
 )";
 
   auto* expect = R"(
-[[internal(intrinsic_buffer_size)]]
-fn tint_symbol_6([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : array<i32>, result : ptr<function, u32>)
+@internal(intrinsic_buffer_size)
+fn tint_symbol_6(@internal(disable_validation__ignore_constructible_function_parameter) buffer : array<i32>, result : ptr<function, u32>)
 
 struct SB1 {
   x : i32;
   arr1 : array<i32>;
 }
 
-[[internal(intrinsic_buffer_size)]]
-fn tint_symbol([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : SB1, result : ptr<function, u32>)
+@internal(intrinsic_buffer_size)
+fn tint_symbol(@internal(disable_validation__ignore_constructible_function_parameter) buffer : SB1, result : ptr<function, u32>)
 
 struct SB2 {
   x : i32;
   arr2 : array<vec4<f32>>;
 }
 
-[[internal(intrinsic_buffer_size)]]
-fn tint_symbol_3([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : SB2, result : ptr<function, u32>)
+@internal(intrinsic_buffer_size)
+fn tint_symbol_3(@internal(disable_validation__ignore_constructible_function_parameter) buffer : SB2, result : ptr<function, u32>)
 
-[[group(0), binding(0)]] var<storage, read> sb1 : SB1;
+@group(0) @binding(0) var<storage, read> sb1 : SB1;
 
-[[group(0), binding(1)]] var<storage, read> sb2 : SB2;
+@group(0) @binding(1) var<storage, read> sb2 : SB2;
 
-[[group(0), binding(2)]] var<storage, read> sb3 : array<i32>;
+@group(0) @binding(2) var<storage, read> sb3 : array<i32>;
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn main() {
   var tint_symbol_1 : u32 = 0u;
   tint_symbol(sb1, &(tint_symbol_1));
@@ -394,10 +394,10 @@
   arr : array<i32>;
 };
 
-[[group(0), binding(0)]] var<storage, read> a : SB;
-[[group(0), binding(1)]] var<storage, read> b : SB;
+@group(0) @binding(0) var<storage, read> a : SB;
+@group(0) @binding(1) var<storage, read> b : SB;
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn main() {
   let x = &a;
   var a : u32 = arrayLength(&a.arr);
@@ -414,14 +414,14 @@
   arr : array<i32>;
 }
 
-[[internal(intrinsic_buffer_size)]]
-fn tint_symbol([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : SB, result : ptr<function, u32>)
+@internal(intrinsic_buffer_size)
+fn tint_symbol(@internal(disable_validation__ignore_constructible_function_parameter) buffer : SB, result : ptr<function, u32>)
 
-[[group(0), binding(0)]] var<storage, read> a : SB;
+@group(0) @binding(0) var<storage, read> a : SB;
 
-[[group(0), binding(1)]] var<storage, read> b : SB;
+@group(0) @binding(1) var<storage, read> b : SB;
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn main() {
   var tint_symbol_1 : u32 = 0u;
   tint_symbol(a, &(tint_symbol_1));
diff --git a/src/transform/canonicalize_entry_point_io.h b/src/transform/canonicalize_entry_point_io.h
index baaa65a..0bf16ba 100644
--- a/src/transform/canonicalize_entry_point_io.h
+++ b/src/transform/canonicalize_entry_point_io.h
@@ -31,13 +31,13 @@
 /// Before:
 /// ```
 /// struct Locations{
-///   [[location(1)]] loc1 : f32;
-///   [[location(2)]] loc2 : vec4<u32>;
+///   @location(1) loc1 : f32;
+///   @location(2) loc2 : vec4<u32>;
 /// };
 ///
-/// [[stage(fragment)]]
-/// fn frag_main([[builtin(position)]] coord : vec4<f32>,
-///              locations : Locations) -> [[location(0)]] f32 {
+/// @stage(fragment)
+/// fn frag_main(@builtin(position) coord : vec4<f32>,
+///              locations : Locations) -> @location(0) f32 {
 ///   if (coord.w > 1.0) {
 ///     return 0.0;
 ///   }
@@ -54,13 +54,13 @@
 /// };
 ///
 /// struct frag_main_in {
-///   [[builtin(position)]] coord : vec4<f32>;
-///   [[location(1)]] loc1 : f32;
-///   [[location(2)]] loc2 : vec4<u32>
+///   @builtin(position) coord : vec4<f32>;
+///   @location(1) loc1 : f32;
+///   @location(2) loc2 : vec4<u32>
 /// };
 ///
 /// struct frag_main_out {
-///   [[location(0)]] loc0 : f32;
+///   @location(0) loc0 : f32;
 /// };
 ///
 /// fn frag_main_inner(coord : vec4<f32>,
@@ -72,7 +72,7 @@
 ///   return col;
 /// }
 ///
-/// [[stage(fragment)]]
+/// @stage(fragment)
 /// fn frag_main(in : frag_main_in) -> frag_main_out {
 ///   let inner_retval = frag_main_inner(in.coord, Locations(in.loc1, in.loc2));
 ///   var wrapper_result : frag_main_out;
diff --git a/src/transform/canonicalize_entry_point_io_test.cc b/src/transform/canonicalize_entry_point_io_test.cc
index 3c16ee5..0219ff2 100644
--- a/src/transform/canonicalize_entry_point_io_test.cc
+++ b/src/transform/canonicalize_entry_point_io_test.cc
@@ -51,11 +51,11 @@
   // Test that we do not introduce wrapper functions when there is no shader IO
   // to process.
   auto* src = R"(
-[[stage(fragment)]]
+@stage(fragment)
 fn frag_main() {
 }
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn comp_main() {
 }
 )";
@@ -72,26 +72,26 @@
 
 TEST_F(CanonicalizeEntryPointIOTest, Parameters_Spirv) {
   auto* src = R"(
-[[stage(fragment)]]
-fn frag_main([[location(1)]] loc1 : f32,
-             [[location(2)]] loc2 : vec4<u32>,
-             [[builtin(position)]] coord : vec4<f32>) {
+@stage(fragment)
+fn frag_main(@location(1) loc1 : f32,
+             @location(2) loc2 : vec4<u32>,
+             @builtin(position) coord : vec4<f32>) {
   var col : f32 = (coord.x * loc1);
 }
 )";
 
   auto* expect = R"(
-[[location(1), internal(disable_validation__ignore_storage_class)]] var<in> loc1_1 : f32;
+@location(1) @internal(disable_validation__ignore_storage_class) var<in> loc1_1 : f32;
 
-[[location(2), interpolate(flat), internal(disable_validation__ignore_storage_class)]] var<in> loc2_1 : vec4<u32>;
+@location(2) @interpolate(flat) @internal(disable_validation__ignore_storage_class) var<in> loc2_1 : vec4<u32>;
 
-[[builtin(position), internal(disable_validation__ignore_storage_class)]] var<in> coord_1 : vec4<f32>;
+@builtin(position) @internal(disable_validation__ignore_storage_class) var<in> coord_1 : vec4<f32>;
 
 fn frag_main_inner(loc1 : f32, loc2 : vec4<u32>, coord : vec4<f32>) {
   var col : f32 = (coord.x * loc1);
 }
 
-[[stage(fragment)]]
+@stage(fragment)
 fn frag_main() {
   frag_main_inner(loc1_1, loc2_1, coord_1);
 }
@@ -107,19 +107,19 @@
 
 TEST_F(CanonicalizeEntryPointIOTest, Parameters_Msl) {
   auto* src = R"(
-[[stage(fragment)]]
-fn frag_main([[location(1)]] loc1 : f32,
-             [[location(2)]] loc2 : vec4<u32>,
-             [[builtin(position)]] coord : vec4<f32>) {
+@stage(fragment)
+fn frag_main(@location(1) loc1 : f32,
+             @location(2) loc2 : vec4<u32>,
+             @builtin(position) coord : vec4<f32>) {
   var col : f32 = (coord.x * loc1);
 }
 )";
 
   auto* expect = R"(
 struct tint_symbol_1 {
-  [[location(1)]]
+  @location(1)
   loc1 : f32;
-  [[location(2)]]
+  @location(2)
   loc2 : vec4<u32>;
 }
 
@@ -127,8 +127,8 @@
   var col : f32 = (coord.x * loc1);
 }
 
-[[stage(fragment)]]
-fn frag_main([[builtin(position)]] coord : vec4<f32>, tint_symbol : tint_symbol_1) {
+@stage(fragment)
+fn frag_main(@builtin(position) coord : vec4<f32>, tint_symbol : tint_symbol_1) {
   frag_main_inner(tint_symbol.loc1, tint_symbol.loc2, coord);
 }
 )";
@@ -143,21 +143,21 @@
 
 TEST_F(CanonicalizeEntryPointIOTest, Parameters_Hlsl) {
   auto* src = R"(
-[[stage(fragment)]]
-fn frag_main([[location(1)]] loc1 : f32,
-             [[location(2)]] loc2 : vec4<u32>,
-             [[builtin(position)]] coord : vec4<f32>) {
+@stage(fragment)
+fn frag_main(@location(1) loc1 : f32,
+             @location(2) loc2 : vec4<u32>,
+             @builtin(position) coord : vec4<f32>) {
   var col : f32 = (coord.x * loc1);
 }
 )";
 
   auto* expect = R"(
 struct tint_symbol_1 {
-  [[location(1)]]
+  @location(1)
   loc1 : f32;
-  [[location(2)]]
+  @location(2)
   loc2 : vec4<u32>;
-  [[builtin(position)]]
+  @builtin(position)
   coord : vec4<f32>;
 }
 
@@ -165,7 +165,7 @@
   var col : f32 = (coord.x * loc1);
 }
 
-[[stage(fragment)]]
+@stage(fragment)
 fn frag_main(tint_symbol : tint_symbol_1) {
   frag_main_inner(tint_symbol.loc1, tint_symbol.loc2, tint_symbol.coord);
 }
@@ -183,8 +183,8 @@
   auto* src = R"(
 type myf32 = f32;
 
-[[stage(fragment)]]
-fn frag_main([[location(1)]] loc1 : myf32) {
+@stage(fragment)
+fn frag_main(@location(1) loc1 : myf32) {
   var x : myf32 = loc1;
 }
 )";
@@ -193,7 +193,7 @@
 type myf32 = f32;
 
 struct tint_symbol_1 {
-  [[location(1)]]
+  @location(1)
   loc1 : f32;
 }
 
@@ -201,7 +201,7 @@
   var x : myf32 = loc1;
 }
 
-[[stage(fragment)]]
+@stage(fragment)
 fn frag_main(tint_symbol : tint_symbol_1) {
   frag_main_inner(tint_symbol.loc1);
 }
@@ -218,15 +218,15 @@
 TEST_F(CanonicalizeEntryPointIOTest, StructParameters_Spirv) {
   auto* src = R"(
 struct FragBuiltins {
-  [[builtin(position)]] coord : vec4<f32>;
+  @builtin(position) coord : vec4<f32>;
 };
 struct FragLocations {
-  [[location(1)]] loc1 : f32;
-  [[location(2)]] loc2 : vec4<u32>;
+  @location(1) loc1 : f32;
+  @location(2) loc2 : vec4<u32>;
 };
 
-[[stage(fragment)]]
-fn frag_main([[location(0)]] loc0 : f32,
+@stage(fragment)
+fn frag_main(@location(0) loc0 : f32,
              locations : FragLocations,
              builtins : FragBuiltins) {
   var col : f32 = ((builtins.coord.x * locations.loc1) + loc0);
@@ -234,13 +234,13 @@
 )";
 
   auto* expect = R"(
-[[location(0), internal(disable_validation__ignore_storage_class)]] var<in> loc0_1 : f32;
+@location(0) @internal(disable_validation__ignore_storage_class) var<in> loc0_1 : f32;
 
-[[location(1), internal(disable_validation__ignore_storage_class)]] var<in> loc1_1 : f32;
+@location(1) @internal(disable_validation__ignore_storage_class) var<in> loc1_1 : f32;
 
-[[location(2), interpolate(flat), internal(disable_validation__ignore_storage_class)]] var<in> loc2_1 : vec4<u32>;
+@location(2) @interpolate(flat) @internal(disable_validation__ignore_storage_class) var<in> loc2_1 : vec4<u32>;
 
-[[builtin(position), internal(disable_validation__ignore_storage_class)]] var<in> coord_1 : vec4<f32>;
+@builtin(position) @internal(disable_validation__ignore_storage_class) var<in> coord_1 : vec4<f32>;
 
 struct FragBuiltins {
   coord : vec4<f32>;
@@ -255,7 +255,7 @@
   var col : f32 = ((builtins.coord.x * locations.loc1) + loc0);
 }
 
-[[stage(fragment)]]
+@stage(fragment)
 fn frag_main() {
   frag_main_inner(loc0_1, FragLocations(loc1_1, loc2_1), FragBuiltins(coord_1));
 }
@@ -272,15 +272,15 @@
 TEST_F(CanonicalizeEntryPointIOTest, StructParameters_kMsl) {
   auto* src = R"(
 struct FragBuiltins {
-  [[builtin(position)]] coord : vec4<f32>;
+  @builtin(position) coord : vec4<f32>;
 };
 struct FragLocations {
-  [[location(1)]] loc1 : f32;
-  [[location(2)]] loc2 : vec4<u32>;
+  @location(1) loc1 : f32;
+  @location(2) loc2 : vec4<u32>;
 };
 
-[[stage(fragment)]]
-fn frag_main([[location(0)]] loc0 : f32,
+@stage(fragment)
+fn frag_main(@location(0) loc0 : f32,
              locations : FragLocations,
              builtins : FragBuiltins) {
   var col : f32 = ((builtins.coord.x * locations.loc1) + loc0);
@@ -298,11 +298,11 @@
 }
 
 struct tint_symbol_1 {
-  [[location(0)]]
+  @location(0)
   loc0 : f32;
-  [[location(1)]]
+  @location(1)
   loc1 : f32;
-  [[location(2)]]
+  @location(2)
   loc2 : vec4<u32>;
 }
 
@@ -310,8 +310,8 @@
   var col : f32 = ((builtins.coord.x * locations.loc1) + loc0);
 }
 
-[[stage(fragment)]]
-fn frag_main([[builtin(position)]] coord : vec4<f32>, tint_symbol : tint_symbol_1) {
+@stage(fragment)
+fn frag_main(@builtin(position) coord : vec4<f32>, tint_symbol : tint_symbol_1) {
   frag_main_inner(tint_symbol.loc0, FragLocations(tint_symbol.loc1, tint_symbol.loc2), FragBuiltins(coord));
 }
 )";
@@ -327,15 +327,15 @@
 TEST_F(CanonicalizeEntryPointIOTest, StructParameters_Hlsl) {
   auto* src = R"(
 struct FragBuiltins {
-  [[builtin(position)]] coord : vec4<f32>;
+  @builtin(position) coord : vec4<f32>;
 };
 struct FragLocations {
-  [[location(1)]] loc1 : f32;
-  [[location(2)]] loc2 : vec4<u32>;
+  @location(1) loc1 : f32;
+  @location(2) loc2 : vec4<u32>;
 };
 
-[[stage(fragment)]]
-fn frag_main([[location(0)]] loc0 : f32,
+@stage(fragment)
+fn frag_main(@location(0) loc0 : f32,
              locations : FragLocations,
              builtins : FragBuiltins) {
   var col : f32 = ((builtins.coord.x * locations.loc1) + loc0);
@@ -353,13 +353,13 @@
 }
 
 struct tint_symbol_1 {
-  [[location(0)]]
+  @location(0)
   loc0 : f32;
-  [[location(1)]]
+  @location(1)
   loc1 : f32;
-  [[location(2)]]
+  @location(2)
   loc2 : vec4<u32>;
-  [[builtin(position)]]
+  @builtin(position)
   coord : vec4<f32>;
 }
 
@@ -367,7 +367,7 @@
   var col : f32 = ((builtins.coord.x * locations.loc1) + loc0);
 }
 
-[[stage(fragment)]]
+@stage(fragment)
 fn frag_main(tint_symbol : tint_symbol_1) {
   frag_main_inner(tint_symbol.loc0, FragLocations(tint_symbol.loc1, tint_symbol.loc2), FragBuiltins(tint_symbol.coord));
 }
@@ -383,20 +383,20 @@
 
 TEST_F(CanonicalizeEntryPointIOTest, Return_NonStruct_Spirv) {
   auto* src = R"(
-[[stage(fragment)]]
-fn frag_main() -> [[builtin(frag_depth)]] f32 {
+@stage(fragment)
+fn frag_main() -> @builtin(frag_depth) f32 {
   return 1.0;
 }
 )";
 
   auto* expect = R"(
-[[builtin(frag_depth), internal(disable_validation__ignore_storage_class)]] var<out> value : f32;
+@builtin(frag_depth) @internal(disable_validation__ignore_storage_class) var<out> value : f32;
 
 fn frag_main_inner() -> f32 {
   return 1.0;
 }
 
-[[stage(fragment)]]
+@stage(fragment)
 fn frag_main() {
   let inner_result = frag_main_inner();
   value = inner_result;
@@ -413,15 +413,15 @@
 
 TEST_F(CanonicalizeEntryPointIOTest, Return_NonStruct_Msl) {
   auto* src = R"(
-[[stage(fragment)]]
-fn frag_main() -> [[builtin(frag_depth)]] f32 {
+@stage(fragment)
+fn frag_main() -> @builtin(frag_depth) f32 {
   return 1.0;
 }
 )";
 
   auto* expect = R"(
 struct tint_symbol {
-  [[builtin(frag_depth)]]
+  @builtin(frag_depth)
   value : f32;
 }
 
@@ -429,7 +429,7 @@
   return 1.0;
 }
 
-[[stage(fragment)]]
+@stage(fragment)
 fn frag_main() -> tint_symbol {
   let inner_result = frag_main_inner();
   var wrapper_result : tint_symbol;
@@ -448,15 +448,15 @@
 
 TEST_F(CanonicalizeEntryPointIOTest, Return_NonStruct_Hlsl) {
   auto* src = R"(
-[[stage(fragment)]]
-fn frag_main() -> [[builtin(frag_depth)]] f32 {
+@stage(fragment)
+fn frag_main() -> @builtin(frag_depth) f32 {
   return 1.0;
 }
 )";
 
   auto* expect = R"(
 struct tint_symbol {
-  [[builtin(frag_depth)]]
+  @builtin(frag_depth)
   value : f32;
 }
 
@@ -464,7 +464,7 @@
   return 1.0;
 }
 
-[[stage(fragment)]]
+@stage(fragment)
 fn frag_main() -> tint_symbol {
   let inner_result = frag_main_inner();
   var wrapper_result : tint_symbol;
@@ -484,12 +484,12 @@
 TEST_F(CanonicalizeEntryPointIOTest, Return_Struct_Spirv) {
   auto* src = R"(
 struct FragOutput {
-  [[location(0)]] color : vec4<f32>;
-  [[builtin(frag_depth)]] depth : f32;
-  [[builtin(sample_mask)]] mask : u32;
+  @location(0) color : vec4<f32>;
+  @builtin(frag_depth) depth : f32;
+  @builtin(sample_mask) mask : u32;
 };
 
-[[stage(fragment)]]
+@stage(fragment)
 fn frag_main() -> FragOutput {
   var output : FragOutput;
   output.depth = 1.0;
@@ -500,11 +500,11 @@
 )";
 
   auto* expect = R"(
-[[location(0), internal(disable_validation__ignore_storage_class)]] var<out> color_1 : vec4<f32>;
+@location(0) @internal(disable_validation__ignore_storage_class) var<out> color_1 : vec4<f32>;
 
-[[builtin(frag_depth), internal(disable_validation__ignore_storage_class)]] var<out> depth_1 : f32;
+@builtin(frag_depth) @internal(disable_validation__ignore_storage_class) var<out> depth_1 : f32;
 
-[[builtin(sample_mask), internal(disable_validation__ignore_storage_class)]] var<out> mask_1 : array<u32, 1>;
+@builtin(sample_mask) @internal(disable_validation__ignore_storage_class) var<out> mask_1 : array<u32, 1>;
 
 struct FragOutput {
   color : vec4<f32>;
@@ -520,7 +520,7 @@
   return output;
 }
 
-[[stage(fragment)]]
+@stage(fragment)
 fn frag_main() {
   let inner_result = frag_main_inner();
   color_1 = inner_result.color;
@@ -540,12 +540,12 @@
 TEST_F(CanonicalizeEntryPointIOTest, Return_Struct_Msl) {
   auto* src = R"(
 struct FragOutput {
-  [[location(0)]] color : vec4<f32>;
-  [[builtin(frag_depth)]] depth : f32;
-  [[builtin(sample_mask)]] mask : u32;
+  @location(0) color : vec4<f32>;
+  @builtin(frag_depth) depth : f32;
+  @builtin(sample_mask) mask : u32;
 };
 
-[[stage(fragment)]]
+@stage(fragment)
 fn frag_main() -> FragOutput {
   var output : FragOutput;
   output.depth = 1.0;
@@ -563,11 +563,11 @@
 }
 
 struct tint_symbol {
-  [[location(0)]]
+  @location(0)
   color : vec4<f32>;
-  [[builtin(frag_depth)]]
+  @builtin(frag_depth)
   depth : f32;
-  [[builtin(sample_mask)]]
+  @builtin(sample_mask)
   mask : u32;
 }
 
@@ -579,7 +579,7 @@
   return output;
 }
 
-[[stage(fragment)]]
+@stage(fragment)
 fn frag_main() -> tint_symbol {
   let inner_result = frag_main_inner();
   var wrapper_result : tint_symbol;
@@ -601,12 +601,12 @@
 TEST_F(CanonicalizeEntryPointIOTest, Return_Struct_Hlsl) {
   auto* src = R"(
 struct FragOutput {
-  [[location(0)]] color : vec4<f32>;
-  [[builtin(frag_depth)]] depth : f32;
-  [[builtin(sample_mask)]] mask : u32;
+  @location(0) color : vec4<f32>;
+  @builtin(frag_depth) depth : f32;
+  @builtin(sample_mask) mask : u32;
 };
 
-[[stage(fragment)]]
+@stage(fragment)
 fn frag_main() -> FragOutput {
   var output : FragOutput;
   output.depth = 1.0;
@@ -624,11 +624,11 @@
 }
 
 struct tint_symbol {
-  [[location(0)]]
+  @location(0)
   color : vec4<f32>;
-  [[builtin(frag_depth)]]
+  @builtin(frag_depth)
   depth : f32;
-  [[builtin(sample_mask)]]
+  @builtin(sample_mask)
   mask : u32;
 }
 
@@ -640,7 +640,7 @@
   return output;
 }
 
-[[stage(fragment)]]
+@stage(fragment)
 fn frag_main() -> tint_symbol {
   let inner_result = frag_main_inner();
   var wrapper_result : tint_symbol;
@@ -663,33 +663,33 @@
        StructParameters_SharedDeviceFunction_Spirv) {
   auto* src = R"(
 struct FragmentInput {
-  [[location(0)]] value : f32;
-  [[location(1)]] mul : f32;
+  @location(0) value : f32;
+  @location(1) mul : f32;
 };
 
 fn foo(x : FragmentInput) -> f32 {
   return x.value * x.mul;
 }
 
-[[stage(fragment)]]
+@stage(fragment)
 fn frag_main1(inputs : FragmentInput) {
   var x : f32 = foo(inputs);
 }
 
-[[stage(fragment)]]
+@stage(fragment)
 fn frag_main2(inputs : FragmentInput) {
   var x : f32 = foo(inputs);
 }
 )";
 
   auto* expect = R"(
-[[location(0), internal(disable_validation__ignore_storage_class)]] var<in> value_1 : f32;
+@location(0) @internal(disable_validation__ignore_storage_class) var<in> value_1 : f32;
 
-[[location(1), internal(disable_validation__ignore_storage_class)]] var<in> mul_1 : f32;
+@location(1) @internal(disable_validation__ignore_storage_class) var<in> mul_1 : f32;
 
-[[location(0), internal(disable_validation__ignore_storage_class)]] var<in> value_2 : f32;
+@location(0) @internal(disable_validation__ignore_storage_class) var<in> value_2 : f32;
 
-[[location(1), internal(disable_validation__ignore_storage_class)]] var<in> mul_2 : f32;
+@location(1) @internal(disable_validation__ignore_storage_class) var<in> mul_2 : f32;
 
 struct FragmentInput {
   value : f32;
@@ -704,7 +704,7 @@
   var x : f32 = foo(inputs);
 }
 
-[[stage(fragment)]]
+@stage(fragment)
 fn frag_main1() {
   frag_main1_inner(FragmentInput(value_1, mul_1));
 }
@@ -713,7 +713,7 @@
   var x : f32 = foo(inputs);
 }
 
-[[stage(fragment)]]
+@stage(fragment)
 fn frag_main2() {
   frag_main2_inner(FragmentInput(value_2, mul_2));
 }
@@ -731,20 +731,20 @@
        StructParameters_SharedDeviceFunction_Msl) {
   auto* src = R"(
 struct FragmentInput {
-  [[location(0)]] value : f32;
-  [[location(1)]] mul : f32;
+  @location(0) value : f32;
+  @location(1) mul : f32;
 };
 
 fn foo(x : FragmentInput) -> f32 {
   return x.value * x.mul;
 }
 
-[[stage(fragment)]]
+@stage(fragment)
 fn frag_main1(inputs : FragmentInput) {
   var x : f32 = foo(inputs);
 }
 
-[[stage(fragment)]]
+@stage(fragment)
 fn frag_main2(inputs : FragmentInput) {
   var x : f32 = foo(inputs);
 }
@@ -761,9 +761,9 @@
 }
 
 struct tint_symbol_1 {
-  [[location(0)]]
+  @location(0)
   value : f32;
-  [[location(1)]]
+  @location(1)
   mul : f32;
 }
 
@@ -771,15 +771,15 @@
   var x : f32 = foo(inputs);
 }
 
-[[stage(fragment)]]
+@stage(fragment)
 fn frag_main1(tint_symbol : tint_symbol_1) {
   frag_main1_inner(FragmentInput(tint_symbol.value, tint_symbol.mul));
 }
 
 struct tint_symbol_3 {
-  [[location(0)]]
+  @location(0)
   value : f32;
-  [[location(1)]]
+  @location(1)
   mul : f32;
 }
 
@@ -787,7 +787,7 @@
   var x : f32 = foo(inputs);
 }
 
-[[stage(fragment)]]
+@stage(fragment)
 fn frag_main2(tint_symbol_2 : tint_symbol_3) {
   frag_main2_inner(FragmentInput(tint_symbol_2.value, tint_symbol_2.mul));
 }
@@ -805,20 +805,20 @@
        StructParameters_SharedDeviceFunction_Hlsl) {
   auto* src = R"(
 struct FragmentInput {
-  [[location(0)]] value : f32;
-  [[location(1)]] mul : f32;
+  @location(0) value : f32;
+  @location(1) mul : f32;
 };
 
 fn foo(x : FragmentInput) -> f32 {
   return x.value * x.mul;
 }
 
-[[stage(fragment)]]
+@stage(fragment)
 fn frag_main1(inputs : FragmentInput) {
   var x : f32 = foo(inputs);
 }
 
-[[stage(fragment)]]
+@stage(fragment)
 fn frag_main2(inputs : FragmentInput) {
   var x : f32 = foo(inputs);
 }
@@ -835,9 +835,9 @@
 }
 
 struct tint_symbol_1 {
-  [[location(0)]]
+  @location(0)
   value : f32;
-  [[location(1)]]
+  @location(1)
   mul : f32;
 }
 
@@ -845,15 +845,15 @@
   var x : f32 = foo(inputs);
 }
 
-[[stage(fragment)]]
+@stage(fragment)
 fn frag_main1(tint_symbol : tint_symbol_1) {
   frag_main1_inner(FragmentInput(tint_symbol.value, tint_symbol.mul));
 }
 
 struct tint_symbol_3 {
-  [[location(0)]]
+  @location(0)
   value : f32;
-  [[location(1)]]
+  @location(1)
   mul : f32;
 }
 
@@ -861,7 +861,7 @@
   var x : f32 = foo(inputs);
 }
 
-[[stage(fragment)]]
+@stage(fragment)
 fn frag_main2(tint_symbol_2 : tint_symbol_3) {
   frag_main2_inner(FragmentInput(tint_symbol_2.value, tint_symbol_2.mul));
 }
@@ -878,8 +878,8 @@
 TEST_F(CanonicalizeEntryPointIOTest, Struct_ModuleScopeVariable) {
   auto* src = R"(
 struct FragmentInput {
-  [[location(0)]] col1 : f32;
-  [[location(1)]] col2 : f32;
+  @location(0) col1 : f32;
+  @location(1) col2 : f32;
 };
 
 var<private> global_inputs : FragmentInput;
@@ -892,7 +892,7 @@
   return global_inputs.col2 * 2.0;
 }
 
-[[stage(fragment)]]
+@stage(fragment)
 fn frag_main1(inputs : FragmentInput) {
  global_inputs = inputs;
  var r : f32 = foo();
@@ -917,9 +917,9 @@
 }
 
 struct tint_symbol_1 {
-  [[location(0)]]
+  @location(0)
   col1 : f32;
-  [[location(1)]]
+  @location(1)
   col2 : f32;
 }
 
@@ -929,7 +929,7 @@
   var g : f32 = bar();
 }
 
-[[stage(fragment)]]
+@stage(fragment)
 fn frag_main1(tint_symbol : tint_symbol_1) {
   frag_main1_inner(FragmentInput(tint_symbol.col1, tint_symbol.col2));
 }
@@ -948,13 +948,13 @@
 type myf32 = f32;
 
 struct FragmentInput {
-  [[location(0)]] col1 : myf32;
-  [[location(1)]] col2 : myf32;
+  @location(0) col1 : myf32;
+  @location(1) col2 : myf32;
 };
 
 struct FragmentOutput {
-  [[location(0)]] col1 : myf32;
-  [[location(1)]] col2 : myf32;
+  @location(0) col1 : myf32;
+  @location(1) col2 : myf32;
 };
 
 type MyFragmentInput = FragmentInput;
@@ -965,7 +965,7 @@
   return x.col1;
 }
 
-[[stage(fragment)]]
+@stage(fragment)
 fn frag_main(inputs : MyFragmentInput) -> MyFragmentOutput {
   var x : myf32 = foo(inputs);
   return MyFragmentOutput(x, inputs.col2);
@@ -994,16 +994,16 @@
 }
 
 struct tint_symbol_1 {
-  [[location(0)]]
+  @location(0)
   col1 : f32;
-  [[location(1)]]
+  @location(1)
   col2 : f32;
 }
 
 struct tint_symbol_2 {
-  [[location(0)]]
+  @location(0)
   col1 : f32;
-  [[location(1)]]
+  @location(1)
   col2 : f32;
 }
 
@@ -1012,7 +1012,7 @@
   return MyFragmentOutput(x, inputs.col2);
 }
 
-[[stage(fragment)]]
+@stage(fragment)
 fn frag_main(tint_symbol : tint_symbol_1) -> tint_symbol_2 {
   let inner_result = frag_main_inner(MyFragmentInput(tint_symbol.col1, tint_symbol.col2));
   var wrapper_result : tint_symbol_2;
@@ -1033,25 +1033,25 @@
 TEST_F(CanonicalizeEntryPointIOTest, InterpolateAttributes) {
   auto* src = R"(
 struct VertexOut {
-  [[builtin(position)]] pos : vec4<f32>;
-  [[location(1), interpolate(flat)]] loc1: f32;
-  [[location(2), interpolate(linear, sample)]] loc2 : f32;
-  [[location(3), interpolate(perspective, centroid)]] loc3 : f32;
+  @builtin(position) pos : vec4<f32>;
+  @location(1) @interpolate(flat) loc1: f32;
+  @location(2) @interpolate(linear, sample) loc2 : f32;
+  @location(3) @interpolate(perspective, centroid) loc3 : f32;
 };
 
 struct FragmentIn {
-  [[location(1), interpolate(flat)]] loc1: f32;
-  [[location(2), interpolate(linear, sample)]] loc2 : f32;
+  @location(1) @interpolate(flat) loc1: f32;
+  @location(2) @interpolate(linear, sample) loc2 : f32;
 };
 
-[[stage(vertex)]]
+@stage(vertex)
 fn vert_main() -> VertexOut {
   return VertexOut();
 }
 
-[[stage(fragment)]]
+@stage(fragment)
 fn frag_main(inputs : FragmentIn,
-             [[location(3), interpolate(perspective, centroid)]] loc3 : f32) {
+             @location(3) @interpolate(perspective, centroid) loc3 : f32) {
   let x = inputs.loc1 + inputs.loc2 + loc3;
 }
 )";
@@ -1070,13 +1070,13 @@
 }
 
 struct tint_symbol {
-  [[location(1), interpolate(flat)]]
+  @location(1) @interpolate(flat)
   loc1 : f32;
-  [[location(2), interpolate(linear, sample)]]
+  @location(2) @interpolate(linear, sample)
   loc2 : f32;
-  [[location(3), interpolate(perspective, centroid)]]
+  @location(3) @interpolate(perspective, centroid)
   loc3 : f32;
-  [[builtin(position)]]
+  @builtin(position)
   pos : vec4<f32>;
 }
 
@@ -1084,7 +1084,7 @@
   return VertexOut();
 }
 
-[[stage(vertex)]]
+@stage(vertex)
 fn vert_main() -> tint_symbol {
   let inner_result = vert_main_inner();
   var wrapper_result : tint_symbol;
@@ -1096,11 +1096,11 @@
 }
 
 struct tint_symbol_2 {
-  [[location(1), interpolate(flat)]]
+  @location(1) @interpolate(flat)
   loc1 : f32;
-  [[location(2), interpolate(linear, sample)]]
+  @location(2) @interpolate(linear, sample)
   loc2 : f32;
-  [[location(3), interpolate(perspective, centroid)]]
+  @location(3) @interpolate(perspective, centroid)
   loc3 : f32;
 }
 
@@ -1108,7 +1108,7 @@
   let x = ((inputs.loc1 + inputs.loc2) + loc3);
 }
 
-[[stage(fragment)]]
+@stage(fragment)
 fn frag_main(tint_symbol_1 : tint_symbol_2) {
   frag_main_inner(FragmentIn(tint_symbol_1.loc1, tint_symbol_1.loc2), tint_symbol_1.loc3);
 }
@@ -1127,33 +1127,33 @@
   // fragment inputs, but not vertex inputs or fragment outputs.
   auto* src = R"(
 struct VertexIn {
-  [[location(0)]] i : i32;
-  [[location(1)]] u : u32;
-  [[location(2)]] vi : vec4<i32>;
-  [[location(3)]] vu : vec4<u32>;
+  @location(0) i : i32;
+  @location(1) u : u32;
+  @location(2) vi : vec4<i32>;
+  @location(3) vu : vec4<u32>;
 };
 
 struct VertexOut {
-  [[location(0)]] i : i32;
-  [[location(1)]] u : u32;
-  [[location(2)]] vi : vec4<i32>;
-  [[location(3)]] vu : vec4<u32>;
-  [[builtin(position)]] pos : vec4<f32>;
+  @location(0) i : i32;
+  @location(1) u : u32;
+  @location(2) vi : vec4<i32>;
+  @location(3) vu : vec4<u32>;
+  @builtin(position) pos : vec4<f32>;
 };
 
 struct FragmentInterface {
-  [[location(0)]] i : i32;
-  [[location(1)]] u : u32;
-  [[location(2)]] vi : vec4<i32>;
-  [[location(3)]] vu : vec4<u32>;
+  @location(0) i : i32;
+  @location(1) u : u32;
+  @location(2) vi : vec4<i32>;
+  @location(3) vu : vec4<u32>;
 };
 
-[[stage(vertex)]]
+@stage(vertex)
 fn vert_main(in : VertexIn) -> VertexOut {
   return VertexOut(in.i, in.u, in.vi, in.vu, vec4<f32>());
 }
 
-[[stage(fragment)]]
+@stage(fragment)
 fn frag_main(inputs : FragmentInterface) -> FragmentInterface {
   return inputs;
 }
@@ -1161,39 +1161,39 @@
 
   auto* expect =
       R"(
-[[location(0), internal(disable_validation__ignore_storage_class)]] var<in> i_1 : i32;
+@location(0) @internal(disable_validation__ignore_storage_class) var<in> i_1 : i32;
 
-[[location(1), internal(disable_validation__ignore_storage_class)]] var<in> u_1 : u32;
+@location(1) @internal(disable_validation__ignore_storage_class) var<in> u_1 : u32;
 
-[[location(2), internal(disable_validation__ignore_storage_class)]] var<in> vi_1 : vec4<i32>;
+@location(2) @internal(disable_validation__ignore_storage_class) var<in> vi_1 : vec4<i32>;
 
-[[location(3), internal(disable_validation__ignore_storage_class)]] var<in> vu_1 : vec4<u32>;
+@location(3) @internal(disable_validation__ignore_storage_class) var<in> vu_1 : vec4<u32>;
 
-[[location(0), interpolate(flat), internal(disable_validation__ignore_storage_class)]] var<out> i_2 : i32;
+@location(0) @interpolate(flat) @internal(disable_validation__ignore_storage_class) var<out> i_2 : i32;
 
-[[location(1), interpolate(flat), internal(disable_validation__ignore_storage_class)]] var<out> u_2 : u32;
+@location(1) @interpolate(flat) @internal(disable_validation__ignore_storage_class) var<out> u_2 : u32;
 
-[[location(2), interpolate(flat), internal(disable_validation__ignore_storage_class)]] var<out> vi_2 : vec4<i32>;
+@location(2) @interpolate(flat) @internal(disable_validation__ignore_storage_class) var<out> vi_2 : vec4<i32>;
 
-[[location(3), interpolate(flat), internal(disable_validation__ignore_storage_class)]] var<out> vu_2 : vec4<u32>;
+@location(3) @interpolate(flat) @internal(disable_validation__ignore_storage_class) var<out> vu_2 : vec4<u32>;
 
-[[builtin(position), internal(disable_validation__ignore_storage_class)]] var<out> pos_1 : vec4<f32>;
+@builtin(position) @internal(disable_validation__ignore_storage_class) var<out> pos_1 : vec4<f32>;
 
-[[location(0), interpolate(flat), internal(disable_validation__ignore_storage_class)]] var<in> i_3 : i32;
+@location(0) @interpolate(flat) @internal(disable_validation__ignore_storage_class) var<in> i_3 : i32;
 
-[[location(1), interpolate(flat), internal(disable_validation__ignore_storage_class)]] var<in> u_3 : u32;
+@location(1) @interpolate(flat) @internal(disable_validation__ignore_storage_class) var<in> u_3 : u32;
 
-[[location(2), interpolate(flat), internal(disable_validation__ignore_storage_class)]] var<in> vi_3 : vec4<i32>;
+@location(2) @interpolate(flat) @internal(disable_validation__ignore_storage_class) var<in> vi_3 : vec4<i32>;
 
-[[location(3), interpolate(flat), internal(disable_validation__ignore_storage_class)]] var<in> vu_3 : vec4<u32>;
+@location(3) @interpolate(flat) @internal(disable_validation__ignore_storage_class) var<in> vu_3 : vec4<u32>;
 
-[[location(0), internal(disable_validation__ignore_storage_class)]] var<out> i_4 : i32;
+@location(0) @internal(disable_validation__ignore_storage_class) var<out> i_4 : i32;
 
-[[location(1), internal(disable_validation__ignore_storage_class)]] var<out> u_4 : u32;
+@location(1) @internal(disable_validation__ignore_storage_class) var<out> u_4 : u32;
 
-[[location(2), internal(disable_validation__ignore_storage_class)]] var<out> vi_4 : vec4<i32>;
+@location(2) @internal(disable_validation__ignore_storage_class) var<out> vi_4 : vec4<i32>;
 
-[[location(3), internal(disable_validation__ignore_storage_class)]] var<out> vu_4 : vec4<u32>;
+@location(3) @internal(disable_validation__ignore_storage_class) var<out> vu_4 : vec4<u32>;
 
 struct VertexIn {
   i : i32;
@@ -1221,7 +1221,7 @@
   return VertexOut(in.i, in.u, in.vi, in.vu, vec4<f32>());
 }
 
-[[stage(vertex)]]
+@stage(vertex)
 fn vert_main() {
   let inner_result = vert_main_inner(VertexIn(i_1, u_1, vi_1, vu_1));
   i_2 = inner_result.i;
@@ -1235,7 +1235,7 @@
   return inputs;
 }
 
-[[stage(fragment)]]
+@stage(fragment)
 fn frag_main() {
   let inner_result_1 = frag_main_inner(FragmentInterface(i_3, u_3, vi_3, vu_3));
   i_4 = inner_result_1.i;
@@ -1259,12 +1259,12 @@
   [[builtin(position), invariant]] pos : vec4<f32>;
 };
 
-[[stage(vertex)]]
+@stage(vertex)
 fn main1() -> VertexOut {
   return VertexOut();
 }
 
-[[stage(vertex)]]
+@stage(vertex)
 fn main2() -> [[builtin(position), invariant]] vec4<f32> {
   return vec4<f32>();
 }
@@ -1276,7 +1276,7 @@
 }
 
 struct tint_symbol {
-  [[builtin(position), invariant]]
+  @builtin(position) @invariant
   pos : vec4<f32>;
 }
 
@@ -1284,7 +1284,7 @@
   return VertexOut();
 }
 
-[[stage(vertex)]]
+@stage(vertex)
 fn main1() -> tint_symbol {
   let inner_result = main1_inner();
   var wrapper_result : tint_symbol;
@@ -1293,7 +1293,7 @@
 }
 
 struct tint_symbol_1 {
-  [[builtin(position), invariant]]
+  @builtin(position) @invariant
   value : vec4<f32>;
 }
 
@@ -1301,7 +1301,7 @@
   return vec4<f32>();
 }
 
-[[stage(vertex)]]
+@stage(vertex)
 fn main2() -> tint_symbol_1 {
   let inner_result_1 = main2_inner();
   var wrapper_result_1 : tint_symbol_1;
@@ -1321,16 +1321,16 @@
 TEST_F(CanonicalizeEntryPointIOTest, Struct_LayoutDecorations) {
   auto* src = R"(
 struct FragmentInput {
-  [[size(16), location(1)]] value : f32;
-  [[builtin(position)]] [[align(32)]] coord : vec4<f32>;
-  [[location(0), interpolate(linear, sample)]] [[align(128)]] loc0 : f32;
+  @size(16) @location(1) value : f32;
+  @builtin(position) @align(32) coord : vec4<f32>;
+  @location(0) @interpolate(linear, sample) @align(128) loc0 : f32;
 };
 
 struct FragmentOutput {
-  [[size(16), location(1), interpolate(flat)]] value : f32;
+  @size(16) @location(1) @interpolate(flat) value : f32;
 };
 
-[[stage(fragment)]]
+@stage(fragment)
 fn frag_main(inputs : FragmentInput) -> FragmentOutput {
   return FragmentOutput(inputs.coord.x * inputs.value + inputs.loc0);
 }
@@ -1338,30 +1338,30 @@
 
   auto* expect = R"(
 struct FragmentInput {
-  [[size(16)]]
+  @size(16)
   value : f32;
-  [[align(32)]]
+  @align(32)
   coord : vec4<f32>;
-  [[align(128)]]
+  @align(128)
   loc0 : f32;
 }
 
 struct FragmentOutput {
-  [[size(16)]]
+  @size(16)
   value : f32;
 }
 
 struct tint_symbol_1 {
-  [[location(0), interpolate(linear, sample)]]
+  @location(0) @interpolate(linear, sample)
   loc0 : f32;
-  [[location(1)]]
+  @location(1)
   value : f32;
-  [[builtin(position)]]
+  @builtin(position)
   coord : vec4<f32>;
 }
 
 struct tint_symbol_2 {
-  [[location(1), interpolate(flat)]]
+  @location(1) @interpolate(flat)
   value : f32;
 }
 
@@ -1369,7 +1369,7 @@
   return FragmentOutput(((inputs.coord.x * inputs.value) + inputs.loc0));
 }
 
-[[stage(fragment)]]
+@stage(fragment)
 fn frag_main(tint_symbol : tint_symbol_1) -> tint_symbol_2 {
   let inner_result = frag_main_inner(FragmentInput(tint_symbol.value, tint_symbol.coord, tint_symbol.loc0));
   var wrapper_result : tint_symbol_2;
@@ -1389,29 +1389,29 @@
 TEST_F(CanonicalizeEntryPointIOTest, SortedMembers) {
   auto* src = R"(
 struct VertexOutput {
-  [[location(1)]] b : u32;
-  [[builtin(position)]] pos : vec4<f32>;
-  [[location(3)]] d : u32;
-  [[location(0)]] a : f32;
-  [[location(2)]] c : i32;
+  @location(1) b : u32;
+  @builtin(position) pos : vec4<f32>;
+  @location(3) d : u32;
+  @location(0) a : f32;
+  @location(2) c : i32;
 };
 
 struct FragmentInputExtra {
-  [[location(3)]] d : u32;
-  [[builtin(position)]] pos : vec4<f32>;
-  [[location(0)]] a : f32;
+  @location(3) d : u32;
+  @builtin(position) pos : vec4<f32>;
+  @location(0) a : f32;
 };
 
-[[stage(vertex)]]
+@stage(vertex)
 fn vert_main() -> VertexOutput {
   return VertexOutput();
 }
 
-[[stage(fragment)]]
-fn frag_main([[builtin(front_facing)]] ff : bool,
-             [[location(2)]] c : i32,
+@stage(fragment)
+fn frag_main(@builtin(front_facing) ff : bool,
+             @location(2) c : i32,
              inputs : FragmentInputExtra,
-             [[location(1)]] b : u32) {
+             @location(1) b : u32) {
 }
 )";
 
@@ -1431,15 +1431,15 @@
 }
 
 struct tint_symbol {
-  [[location(0)]]
+  @location(0)
   a : f32;
-  [[location(1)]]
+  @location(1)
   b : u32;
-  [[location(2)]]
+  @location(2)
   c : i32;
-  [[location(3)]]
+  @location(3)
   d : u32;
-  [[builtin(position)]]
+  @builtin(position)
   pos : vec4<f32>;
 }
 
@@ -1447,7 +1447,7 @@
   return VertexOutput();
 }
 
-[[stage(vertex)]]
+@stage(vertex)
 fn vert_main() -> tint_symbol {
   let inner_result = vert_main_inner();
   var wrapper_result : tint_symbol;
@@ -1460,24 +1460,24 @@
 }
 
 struct tint_symbol_2 {
-  [[location(0)]]
+  @location(0)
   a : f32;
-  [[location(1)]]
+  @location(1)
   b : u32;
-  [[location(2)]]
+  @location(2)
   c : i32;
-  [[location(3)]]
+  @location(3)
   d : u32;
-  [[builtin(position)]]
+  @builtin(position)
   pos : vec4<f32>;
-  [[builtin(front_facing)]]
+  @builtin(front_facing)
   ff : bool;
 }
 
 fn frag_main_inner(ff : bool, c : i32, inputs : FragmentInputExtra, b : u32) {
 }
 
-[[stage(fragment)]]
+@stage(fragment)
 fn frag_main(tint_symbol_1 : tint_symbol_2) {
   frag_main_inner(tint_symbol_1.ff, tint_symbol_1.c, FragmentInputExtra(tint_symbol_1.d, tint_symbol_1.pos, tint_symbol_1.a), tint_symbol_1.b);
 }
@@ -1493,21 +1493,21 @@
 
 TEST_F(CanonicalizeEntryPointIOTest, DontRenameSymbols) {
   auto* src = R"(
-[[stage(fragment)]]
-fn tint_symbol_1([[location(0)]] col : f32) {
+@stage(fragment)
+fn tint_symbol_1(@location(0) col : f32) {
 }
 )";
 
   auto* expect = R"(
 struct tint_symbol_2 {
-  [[location(0)]]
+  @location(0)
   col : f32;
 }
 
 fn tint_symbol_1_inner(col : f32) {
 }
 
-[[stage(fragment)]]
+@stage(fragment)
 fn tint_symbol_1(tint_symbol : tint_symbol_2) {
   tint_symbol_1_inner(tint_symbol.col);
 }
@@ -1523,21 +1523,21 @@
 
 TEST_F(CanonicalizeEntryPointIOTest, FixedSampleMask_VoidNoReturn) {
   auto* src = R"(
-[[stage(fragment)]]
+@stage(fragment)
 fn frag_main() {
 }
 )";
 
   auto* expect = R"(
 struct tint_symbol {
-  [[builtin(sample_mask)]]
+  @builtin(sample_mask)
   fixed_sample_mask : u32;
 }
 
 fn frag_main_inner() {
 }
 
-[[stage(fragment)]]
+@stage(fragment)
 fn frag_main() -> tint_symbol {
   frag_main_inner();
   var wrapper_result : tint_symbol;
@@ -1556,7 +1556,7 @@
 
 TEST_F(CanonicalizeEntryPointIOTest, FixedSampleMask_VoidWithReturn) {
   auto* src = R"(
-[[stage(fragment)]]
+@stage(fragment)
 fn frag_main() {
   return;
 }
@@ -1564,7 +1564,7 @@
 
   auto* expect = R"(
 struct tint_symbol {
-  [[builtin(sample_mask)]]
+  @builtin(sample_mask)
   fixed_sample_mask : u32;
 }
 
@@ -1572,7 +1572,7 @@
   return;
 }
 
-[[stage(fragment)]]
+@stage(fragment)
 fn frag_main() -> tint_symbol {
   frag_main_inner();
   var wrapper_result : tint_symbol;
@@ -1591,15 +1591,15 @@
 
 TEST_F(CanonicalizeEntryPointIOTest, FixedSampleMask_WithAuthoredMask) {
   auto* src = R"(
-[[stage(fragment)]]
-fn frag_main() -> [[builtin(sample_mask)]] u32 {
+@stage(fragment)
+fn frag_main() -> @builtin(sample_mask) u32 {
   return 7u;
 }
 )";
 
   auto* expect = R"(
 struct tint_symbol {
-  [[builtin(sample_mask)]]
+  @builtin(sample_mask)
   value : u32;
 }
 
@@ -1607,7 +1607,7 @@
   return 7u;
 }
 
-[[stage(fragment)]]
+@stage(fragment)
 fn frag_main() -> tint_symbol {
   let inner_result = frag_main_inner();
   var wrapper_result : tint_symbol;
@@ -1626,17 +1626,17 @@
 
 TEST_F(CanonicalizeEntryPointIOTest, FixedSampleMask_WithoutAuthoredMask) {
   auto* src = R"(
-[[stage(fragment)]]
-fn frag_main() -> [[location(0)]] f32 {
+@stage(fragment)
+fn frag_main() -> @location(0) f32 {
   return 1.0;
 }
 )";
 
   auto* expect = R"(
 struct tint_symbol {
-  [[location(0)]]
+  @location(0)
   value : f32;
-  [[builtin(sample_mask)]]
+  @builtin(sample_mask)
   fixed_sample_mask : u32;
 }
 
@@ -1644,7 +1644,7 @@
   return 1.0;
 }
 
-[[stage(fragment)]]
+@stage(fragment)
 fn frag_main() -> tint_symbol {
   let inner_result = frag_main_inner();
   var wrapper_result : tint_symbol;
@@ -1665,12 +1665,12 @@
 TEST_F(CanonicalizeEntryPointIOTest, FixedSampleMask_StructWithAuthoredMask) {
   auto* src = R"(
 struct Output {
-  [[builtin(frag_depth)]] depth : f32;
-  [[builtin(sample_mask)]] mask : u32;
-  [[location(0)]] value : f32;
+  @builtin(frag_depth) depth : f32;
+  @builtin(sample_mask) mask : u32;
+  @location(0) value : f32;
 };
 
-[[stage(fragment)]]
+@stage(fragment)
 fn frag_main() -> Output {
   return Output(0.5, 7u, 1.0);
 }
@@ -1684,11 +1684,11 @@
 }
 
 struct tint_symbol {
-  [[location(0)]]
+  @location(0)
   value : f32;
-  [[builtin(frag_depth)]]
+  @builtin(frag_depth)
   depth : f32;
-  [[builtin(sample_mask)]]
+  @builtin(sample_mask)
   mask : u32;
 }
 
@@ -1696,7 +1696,7 @@
   return Output(0.5, 7u, 1.0);
 }
 
-[[stage(fragment)]]
+@stage(fragment)
 fn frag_main() -> tint_symbol {
   let inner_result = frag_main_inner();
   var wrapper_result : tint_symbol;
@@ -1719,11 +1719,11 @@
        FixedSampleMask_StructWithoutAuthoredMask) {
   auto* src = R"(
 struct Output {
-  [[builtin(frag_depth)]] depth : f32;
-  [[location(0)]] value : f32;
+  @builtin(frag_depth) depth : f32;
+  @location(0) value : f32;
 };
 
-[[stage(fragment)]]
+@stage(fragment)
 fn frag_main() -> Output {
   return Output(0.5, 1.0);
 }
@@ -1736,11 +1736,11 @@
 }
 
 struct tint_symbol {
-  [[location(0)]]
+  @location(0)
   value : f32;
-  [[builtin(frag_depth)]]
+  @builtin(frag_depth)
   depth : f32;
-  [[builtin(sample_mask)]]
+  @builtin(sample_mask)
   fixed_sample_mask : u32;
 }
 
@@ -1748,7 +1748,7 @@
   return Output(0.5, 1.0);
 }
 
-[[stage(fragment)]]
+@stage(fragment)
 fn frag_main() -> tint_symbol {
   let inner_result = frag_main_inner();
   var wrapper_result : tint_symbol;
@@ -1769,29 +1769,29 @@
 
 TEST_F(CanonicalizeEntryPointIOTest, FixedSampleMask_MultipleShaders) {
   auto* src = R"(
-[[stage(fragment)]]
-fn frag_main1() -> [[builtin(sample_mask)]] u32 {
+@stage(fragment)
+fn frag_main1() -> @builtin(sample_mask) u32 {
   return 7u;
 }
 
-[[stage(fragment)]]
-fn frag_main2() -> [[location(0)]] f32 {
+@stage(fragment)
+fn frag_main2() -> @location(0) f32 {
   return 1.0;
 }
 
-[[stage(vertex)]]
-fn vert_main1() -> [[builtin(position)]] vec4<f32> {
+@stage(vertex)
+fn vert_main1() -> @builtin(position) vec4<f32> {
   return vec4<f32>();
 }
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn comp_main1() {
 }
 )";
 
   auto* expect = R"(
 struct tint_symbol {
-  [[builtin(sample_mask)]]
+  @builtin(sample_mask)
   value : u32;
 }
 
@@ -1799,7 +1799,7 @@
   return 7u;
 }
 
-[[stage(fragment)]]
+@stage(fragment)
 fn frag_main1() -> tint_symbol {
   let inner_result = frag_main1_inner();
   var wrapper_result : tint_symbol;
@@ -1808,9 +1808,9 @@
 }
 
 struct tint_symbol_1 {
-  [[location(0)]]
+  @location(0)
   value : f32;
-  [[builtin(sample_mask)]]
+  @builtin(sample_mask)
   fixed_sample_mask : u32;
 }
 
@@ -1818,7 +1818,7 @@
   return 1.0;
 }
 
-[[stage(fragment)]]
+@stage(fragment)
 fn frag_main2() -> tint_symbol_1 {
   let inner_result_1 = frag_main2_inner();
   var wrapper_result_1 : tint_symbol_1;
@@ -1828,7 +1828,7 @@
 }
 
 struct tint_symbol_2 {
-  [[builtin(position)]]
+  @builtin(position)
   value : vec4<f32>;
 }
 
@@ -1836,7 +1836,7 @@
   return vec4<f32>();
 }
 
-[[stage(vertex)]]
+@stage(vertex)
 fn vert_main1() -> tint_symbol_2 {
   let inner_result_2 = vert_main1_inner();
   var wrapper_result_2 : tint_symbol_2;
@@ -1844,7 +1844,7 @@
   return wrapper_result_2;
 }
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn comp_main1() {
 }
 )";
@@ -1860,11 +1860,11 @@
 TEST_F(CanonicalizeEntryPointIOTest, FixedSampleMask_AvoidNameClash) {
   auto* src = R"(
 struct FragOut {
-  [[location(0)]] fixed_sample_mask : vec4<f32>;
-  [[location(1)]] fixed_sample_mask_1 : vec4<f32>;
+  @location(0) fixed_sample_mask : vec4<f32>;
+  @location(1) fixed_sample_mask_1 : vec4<f32>;
 };
 
-[[stage(fragment)]]
+@stage(fragment)
 fn frag_main() -> FragOut {
   return FragOut();
 }
@@ -1877,11 +1877,11 @@
 }
 
 struct tint_symbol {
-  [[location(0)]]
+  @location(0)
   fixed_sample_mask : vec4<f32>;
-  [[location(1)]]
+  @location(1)
   fixed_sample_mask_1 : vec4<f32>;
-  [[builtin(sample_mask)]]
+  @builtin(sample_mask)
   fixed_sample_mask_2 : u32;
 }
 
@@ -1889,7 +1889,7 @@
   return FragOut();
 }
 
-[[stage(fragment)]]
+@stage(fragment)
 fn frag_main() -> tint_symbol {
   let inner_result = frag_main_inner();
   var wrapper_result : tint_symbol;
@@ -1911,22 +1911,22 @@
 TEST_F(CanonicalizeEntryPointIOTest,
        EmitVertexPointSize_ReturnNonStruct_Spirv) {
   auto* src = R"(
-[[stage(vertex)]]
-fn vert_main() -> [[builtin(position)]] vec4<f32> {
+@stage(vertex)
+fn vert_main() -> @builtin(position) vec4<f32> {
   return vec4<f32>();
 }
 )";
 
   auto* expect = R"(
-[[builtin(position), internal(disable_validation__ignore_storage_class)]] var<out> value : vec4<f32>;
+@builtin(position) @internal(disable_validation__ignore_storage_class) var<out> value : vec4<f32>;
 
-[[builtin(pointsize), internal(disable_validation__ignore_storage_class)]] var<out> vertex_point_size : f32;
+@builtin(pointsize) @internal(disable_validation__ignore_storage_class) var<out> vertex_point_size : f32;
 
 fn vert_main_inner() -> vec4<f32> {
   return vec4<f32>();
 }
 
-[[stage(vertex)]]
+@stage(vertex)
 fn vert_main() {
   let inner_result = vert_main_inner();
   value = inner_result;
@@ -1944,17 +1944,17 @@
 
 TEST_F(CanonicalizeEntryPointIOTest, EmitVertexPointSize_ReturnNonStruct_Msl) {
   auto* src = R"(
-[[stage(vertex)]]
-fn vert_main() -> [[builtin(position)]] vec4<f32> {
+@stage(vertex)
+fn vert_main() -> @builtin(position) vec4<f32> {
   return vec4<f32>();
 }
 )";
 
   auto* expect = R"(
 struct tint_symbol {
-  [[builtin(position)]]
+  @builtin(position)
   value : vec4<f32>;
-  [[builtin(pointsize)]]
+  @builtin(pointsize)
   vertex_point_size : f32;
 }
 
@@ -1962,7 +1962,7 @@
   return vec4<f32>();
 }
 
-[[stage(vertex)]]
+@stage(vertex)
 fn vert_main() -> tint_symbol {
   let inner_result = vert_main_inner();
   var wrapper_result : tint_symbol;
@@ -1983,19 +1983,19 @@
 TEST_F(CanonicalizeEntryPointIOTest, EmitVertexPointSize_ReturnStruct_Spirv) {
   auto* src = R"(
 struct VertOut {
-  [[builtin(position)]] pos : vec4<f32>;
+  @builtin(position) pos : vec4<f32>;
 };
 
-[[stage(vertex)]]
+@stage(vertex)
 fn vert_main() -> VertOut {
   return VertOut();
 }
 )";
 
   auto* expect = R"(
-[[builtin(position), internal(disable_validation__ignore_storage_class)]] var<out> pos_1 : vec4<f32>;
+@builtin(position) @internal(disable_validation__ignore_storage_class) var<out> pos_1 : vec4<f32>;
 
-[[builtin(pointsize), internal(disable_validation__ignore_storage_class)]] var<out> vertex_point_size : f32;
+@builtin(pointsize) @internal(disable_validation__ignore_storage_class) var<out> vertex_point_size : f32;
 
 struct VertOut {
   pos : vec4<f32>;
@@ -2005,7 +2005,7 @@
   return VertOut();
 }
 
-[[stage(vertex)]]
+@stage(vertex)
 fn vert_main() {
   let inner_result = vert_main_inner();
   pos_1 = inner_result.pos;
@@ -2024,10 +2024,10 @@
 TEST_F(CanonicalizeEntryPointIOTest, EmitVertexPointSize_ReturnStruct_Msl) {
   auto* src = R"(
 struct VertOut {
-  [[builtin(position)]] pos : vec4<f32>;
+  @builtin(position) pos : vec4<f32>;
 };
 
-[[stage(vertex)]]
+@stage(vertex)
 fn vert_main() -> VertOut {
   return VertOut();
 }
@@ -2039,9 +2039,9 @@
 }
 
 struct tint_symbol {
-  [[builtin(position)]]
+  @builtin(position)
   pos : vec4<f32>;
-  [[builtin(pointsize)]]
+  @builtin(pointsize)
   vertex_point_size : f32;
 }
 
@@ -2049,7 +2049,7 @@
   return VertOut();
 }
 
-[[stage(vertex)]]
+@stage(vertex)
 fn vert_main() -> tint_symbol {
   let inner_result = vert_main_inner();
   var wrapper_result : tint_symbol;
@@ -2074,19 +2074,19 @@
 var<private> vertex_point_size_2 : f32;
 
 struct VertIn1 {
-  [[location(0)]] collide : f32;
+  @location(0) collide : f32;
 };
 
 struct VertIn2 {
-  [[location(1)]] collide : f32;
+  @location(1) collide : f32;
 };
 
 struct VertOut {
-  [[location(0)]] vertex_point_size : f32;
-  [[builtin(position)]] vertex_point_size_1 : vec4<f32>;
+  @location(0) vertex_point_size : f32;
+  @builtin(position) vertex_point_size_1 : vec4<f32>;
 };
 
-[[stage(vertex)]]
+@stage(vertex)
 fn vert_main(collide : VertIn1, collide_1 : VertIn2) -> VertOut {
   let x = collide.collide + collide_1.collide;
   return VertOut();
@@ -2094,15 +2094,15 @@
 )";
 
   auto* expect = R"(
-[[location(0), internal(disable_validation__ignore_storage_class)]] var<in> collide_2 : f32;
+@location(0) @internal(disable_validation__ignore_storage_class) var<in> collide_2 : f32;
 
-[[location(1), internal(disable_validation__ignore_storage_class)]] var<in> collide_3 : f32;
+@location(1) @internal(disable_validation__ignore_storage_class) var<in> collide_3 : f32;
 
-[[location(0), internal(disable_validation__ignore_storage_class)]] var<out> vertex_point_size_3 : f32;
+@location(0) @internal(disable_validation__ignore_storage_class) var<out> vertex_point_size_3 : f32;
 
-[[builtin(position), internal(disable_validation__ignore_storage_class)]] var<out> vertex_point_size_1_1 : vec4<f32>;
+@builtin(position) @internal(disable_validation__ignore_storage_class) var<out> vertex_point_size_1_1 : vec4<f32>;
 
-[[builtin(pointsize), internal(disable_validation__ignore_storage_class)]] var<out> vertex_point_size_4 : f32;
+@builtin(pointsize) @internal(disable_validation__ignore_storage_class) var<out> vertex_point_size_4 : f32;
 
 var<private> vertex_point_size : f32;
 
@@ -2128,7 +2128,7 @@
   return VertOut();
 }
 
-[[stage(vertex)]]
+@stage(vertex)
 fn vert_main() {
   let inner_result = vert_main_inner(VertIn1(collide_2), VertIn2(collide_3));
   vertex_point_size_3 = inner_result.vertex_point_size;
@@ -2148,19 +2148,19 @@
 TEST_F(CanonicalizeEntryPointIOTest, EmitVertexPointSize_AvoidNameClash_Msl) {
   auto* src = R"(
 struct VertIn1 {
-  [[location(0)]] collide : f32;
+  @location(0) collide : f32;
 };
 
 struct VertIn2 {
-  [[location(1)]] collide : f32;
+  @location(1) collide : f32;
 };
 
 struct VertOut {
-  [[location(0)]] vertex_point_size : vec4<f32>;
-  [[builtin(position)]] vertex_point_size_1 : vec4<f32>;
+  @location(0) vertex_point_size : vec4<f32>;
+  @builtin(position) vertex_point_size_1 : vec4<f32>;
 };
 
-[[stage(vertex)]]
+@stage(vertex)
 fn vert_main(collide : VertIn1, collide_1 : VertIn2) -> VertOut {
   let x = collide.collide + collide_1.collide;
   return VertOut();
@@ -2182,18 +2182,18 @@
 }
 
 struct tint_symbol_1 {
-  [[location(0)]]
+  @location(0)
   collide : f32;
-  [[location(1)]]
+  @location(1)
   collide_2 : f32;
 }
 
 struct tint_symbol_2 {
-  [[location(0)]]
+  @location(0)
   vertex_point_size : vec4<f32>;
-  [[builtin(position)]]
+  @builtin(position)
   vertex_point_size_1 : vec4<f32>;
-  [[builtin(pointsize)]]
+  @builtin(pointsize)
   vertex_point_size_2 : f32;
 }
 
@@ -2202,7 +2202,7 @@
   return VertOut();
 }
 
-[[stage(vertex)]]
+@stage(vertex)
 fn vert_main(tint_symbol : tint_symbol_1) -> tint_symbol_2 {
   let inner_result = vert_main_inner(VertIn1(tint_symbol.collide), VertIn2(tint_symbol.collide_2));
   var wrapper_result : tint_symbol_2;
@@ -2224,19 +2224,19 @@
 TEST_F(CanonicalizeEntryPointIOTest, EmitVertexPointSize_AvoidNameClash_Hlsl) {
   auto* src = R"(
 struct VertIn1 {
-  [[location(0)]] collide : f32;
+  @location(0) collide : f32;
 };
 
 struct VertIn2 {
-  [[location(1)]] collide : f32;
+  @location(1) collide : f32;
 };
 
 struct VertOut {
-  [[location(0)]] vertex_point_size : vec4<f32>;
-  [[builtin(position)]] vertex_point_size_1 : vec4<f32>;
+  @location(0) vertex_point_size : vec4<f32>;
+  @builtin(position) vertex_point_size_1 : vec4<f32>;
 };
 
-[[stage(vertex)]]
+@stage(vertex)
 fn vert_main(collide : VertIn1, collide_1 : VertIn2) -> VertOut {
   let x = collide.collide + collide_1.collide;
   return VertOut();
@@ -2258,18 +2258,18 @@
 }
 
 struct tint_symbol_1 {
-  [[location(0)]]
+  @location(0)
   collide : f32;
-  [[location(1)]]
+  @location(1)
   collide_2 : f32;
 }
 
 struct tint_symbol_2 {
-  [[location(0)]]
+  @location(0)
   vertex_point_size : vec4<f32>;
-  [[builtin(position)]]
+  @builtin(position)
   vertex_point_size_1 : vec4<f32>;
-  [[builtin(pointsize)]]
+  @builtin(pointsize)
   vertex_point_size_2 : f32;
 }
 
@@ -2278,7 +2278,7 @@
   return VertOut();
 }
 
-[[stage(vertex)]]
+@stage(vertex)
 fn vert_main(tint_symbol : tint_symbol_1) -> tint_symbol_2 {
   let inner_result = vert_main_inner(VertIn1(tint_symbol.collide), VertIn2(tint_symbol.collide_2));
   var wrapper_result : tint_symbol_2;
@@ -2299,26 +2299,26 @@
 
 TEST_F(CanonicalizeEntryPointIOTest, SpirvSampleMaskBuiltins) {
   auto* src = R"(
-[[stage(fragment)]]
-fn main([[builtin(sample_index)]] sample_index : u32,
-        [[builtin(sample_mask)]] mask_in : u32
-        ) -> [[builtin(sample_mask)]] u32 {
+@stage(fragment)
+fn main(@builtin(sample_index) sample_index : u32,
+        @builtin(sample_mask) mask_in : u32
+        ) -> @builtin(sample_mask) u32 {
   return mask_in;
 }
 )";
 
   auto* expect = R"(
-[[builtin(sample_index), internal(disable_validation__ignore_storage_class)]] var<in> sample_index_1 : u32;
+@builtin(sample_index) @internal(disable_validation__ignore_storage_class) var<in> sample_index_1 : u32;
 
-[[builtin(sample_mask), internal(disable_validation__ignore_storage_class)]] var<in> mask_in_1 : array<u32, 1>;
+@builtin(sample_mask) @internal(disable_validation__ignore_storage_class) var<in> mask_in_1 : array<u32, 1>;
 
-[[builtin(sample_mask), internal(disable_validation__ignore_storage_class)]] var<out> value : array<u32, 1>;
+@builtin(sample_mask) @internal(disable_validation__ignore_storage_class) var<out> value : array<u32, 1>;
 
 fn main_inner(sample_index : u32, mask_in : u32) -> u32 {
   return mask_in;
 }
 
-[[stage(fragment)]]
+@stage(fragment)
 fn main() {
   let inner_result = main_inner(sample_index_1, mask_in_1[0]);
   value[0] = inner_result;
diff --git a/src/transform/decompose_memory_access.h b/src/transform/decompose_memory_access.h
index 67f3eb9..9fb1b0f 100644
--- a/src/transform/decompose_memory_access.h
+++ b/src/transform/decompose_memory_access.h
@@ -82,7 +82,7 @@
     ~Intrinsic() override;
 
     /// @return a short description of the internal decoration which will be
-    /// displayed as `[[internal(<name>)]]`
+    /// displayed as `@internal(<name>)`
     std::string InternalName() const override;
 
     /// Performs a deep clone of this object using the CloneContext `ctx`.
diff --git a/src/transform/decompose_memory_access_test.cc b/src/transform/decompose_memory_access_test.cc
index c28f48e..2fd6e10 100644
--- a/src/transform/decompose_memory_access_test.cc
+++ b/src/transform/decompose_memory_access_test.cc
@@ -49,9 +49,9 @@
   v : array<vec3<f32>, 2>;
 };
 
-[[group(0), binding(0)]] var<storage, read_write> sb : SB;
+@group(0) @binding(0) var<storage, read_write> sb : SB;
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn main() {
   var a : i32 = sb.a;
   var b : u32 = sb.b;
@@ -104,81 +104,81 @@
   v : array<vec3<f32>, 2>;
 }
 
-[[group(0), binding(0)]] var<storage, read_write> sb : SB;
+@group(0) @binding(0) var<storage, read_write> sb : SB;
 
-[[internal(intrinsic_load_storage_i32), internal(disable_validation__function_has_no_body)]]
-fn tint_symbol([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : SB, offset : u32) -> i32
+@internal(intrinsic_load_storage_i32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol(@internal(disable_validation__ignore_constructible_function_parameter) buffer : SB, offset : u32) -> i32
 
-[[internal(intrinsic_load_storage_u32), internal(disable_validation__function_has_no_body)]]
-fn tint_symbol_1([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : SB, offset : u32) -> u32
+@internal(intrinsic_load_storage_u32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_1(@internal(disable_validation__ignore_constructible_function_parameter) buffer : SB, offset : u32) -> u32
 
-[[internal(intrinsic_load_storage_f32), internal(disable_validation__function_has_no_body)]]
-fn tint_symbol_2([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : SB, offset : u32) -> f32
+@internal(intrinsic_load_storage_f32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_2(@internal(disable_validation__ignore_constructible_function_parameter) buffer : SB, offset : u32) -> f32
 
-[[internal(intrinsic_load_storage_vec2_i32), internal(disable_validation__function_has_no_body)]]
-fn tint_symbol_3([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : SB, offset : u32) -> vec2<i32>
+@internal(intrinsic_load_storage_vec2_i32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_3(@internal(disable_validation__ignore_constructible_function_parameter) buffer : SB, offset : u32) -> vec2<i32>
 
-[[internal(intrinsic_load_storage_vec2_u32), internal(disable_validation__function_has_no_body)]]
-fn tint_symbol_4([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : SB, offset : u32) -> vec2<u32>
+@internal(intrinsic_load_storage_vec2_u32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_4(@internal(disable_validation__ignore_constructible_function_parameter) buffer : SB, offset : u32) -> vec2<u32>
 
-[[internal(intrinsic_load_storage_vec2_f32), internal(disable_validation__function_has_no_body)]]
-fn tint_symbol_5([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : SB, offset : u32) -> vec2<f32>
+@internal(intrinsic_load_storage_vec2_f32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_5(@internal(disable_validation__ignore_constructible_function_parameter) buffer : SB, offset : u32) -> vec2<f32>
 
-[[internal(intrinsic_load_storage_vec3_i32), internal(disable_validation__function_has_no_body)]]
-fn tint_symbol_6([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : SB, offset : u32) -> vec3<i32>
+@internal(intrinsic_load_storage_vec3_i32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_6(@internal(disable_validation__ignore_constructible_function_parameter) buffer : SB, offset : u32) -> vec3<i32>
 
-[[internal(intrinsic_load_storage_vec3_u32), internal(disable_validation__function_has_no_body)]]
-fn tint_symbol_7([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : SB, offset : u32) -> vec3<u32>
+@internal(intrinsic_load_storage_vec3_u32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_7(@internal(disable_validation__ignore_constructible_function_parameter) buffer : SB, offset : u32) -> vec3<u32>
 
-[[internal(intrinsic_load_storage_vec3_f32), internal(disable_validation__function_has_no_body)]]
-fn tint_symbol_8([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : SB, offset : u32) -> vec3<f32>
+@internal(intrinsic_load_storage_vec3_f32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_8(@internal(disable_validation__ignore_constructible_function_parameter) buffer : SB, offset : u32) -> vec3<f32>
 
-[[internal(intrinsic_load_storage_vec4_i32), internal(disable_validation__function_has_no_body)]]
-fn tint_symbol_9([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : SB, offset : u32) -> vec4<i32>
+@internal(intrinsic_load_storage_vec4_i32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_9(@internal(disable_validation__ignore_constructible_function_parameter) buffer : SB, offset : u32) -> vec4<i32>
 
-[[internal(intrinsic_load_storage_vec4_u32), internal(disable_validation__function_has_no_body)]]
-fn tint_symbol_10([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : SB, offset : u32) -> vec4<u32>
+@internal(intrinsic_load_storage_vec4_u32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_10(@internal(disable_validation__ignore_constructible_function_parameter) buffer : SB, offset : u32) -> vec4<u32>
 
-[[internal(intrinsic_load_storage_vec4_f32), internal(disable_validation__function_has_no_body)]]
-fn tint_symbol_11([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : SB, offset : u32) -> vec4<f32>
+@internal(intrinsic_load_storage_vec4_f32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_11(@internal(disable_validation__ignore_constructible_function_parameter) buffer : SB, offset : u32) -> vec4<f32>
 
-fn tint_symbol_12([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : SB, offset : u32) -> mat2x2<f32> {
+fn tint_symbol_12(@internal(disable_validation__ignore_constructible_function_parameter) buffer : SB, offset : u32) -> mat2x2<f32> {
   return mat2x2<f32>(tint_symbol_5(buffer, (offset + 0u)), tint_symbol_5(buffer, (offset + 8u)));
 }
 
-fn tint_symbol_13([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : SB, offset : u32) -> mat2x3<f32> {
+fn tint_symbol_13(@internal(disable_validation__ignore_constructible_function_parameter) buffer : SB, offset : u32) -> mat2x3<f32> {
   return mat2x3<f32>(tint_symbol_8(buffer, (offset + 0u)), tint_symbol_8(buffer, (offset + 16u)));
 }
 
-fn tint_symbol_14([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : SB, offset : u32) -> mat2x4<f32> {
+fn tint_symbol_14(@internal(disable_validation__ignore_constructible_function_parameter) buffer : SB, offset : u32) -> mat2x4<f32> {
   return mat2x4<f32>(tint_symbol_11(buffer, (offset + 0u)), tint_symbol_11(buffer, (offset + 16u)));
 }
 
-fn tint_symbol_15([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : SB, offset : u32) -> mat3x2<f32> {
+fn tint_symbol_15(@internal(disable_validation__ignore_constructible_function_parameter) buffer : SB, offset : u32) -> mat3x2<f32> {
   return mat3x2<f32>(tint_symbol_5(buffer, (offset + 0u)), tint_symbol_5(buffer, (offset + 8u)), tint_symbol_5(buffer, (offset + 16u)));
 }
 
-fn tint_symbol_16([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : SB, offset : u32) -> mat3x3<f32> {
+fn tint_symbol_16(@internal(disable_validation__ignore_constructible_function_parameter) buffer : SB, offset : u32) -> mat3x3<f32> {
   return mat3x3<f32>(tint_symbol_8(buffer, (offset + 0u)), tint_symbol_8(buffer, (offset + 16u)), tint_symbol_8(buffer, (offset + 32u)));
 }
 
-fn tint_symbol_17([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : SB, offset : u32) -> mat3x4<f32> {
+fn tint_symbol_17(@internal(disable_validation__ignore_constructible_function_parameter) buffer : SB, offset : u32) -> mat3x4<f32> {
   return mat3x4<f32>(tint_symbol_11(buffer, (offset + 0u)), tint_symbol_11(buffer, (offset + 16u)), tint_symbol_11(buffer, (offset + 32u)));
 }
 
-fn tint_symbol_18([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : SB, offset : u32) -> mat4x2<f32> {
+fn tint_symbol_18(@internal(disable_validation__ignore_constructible_function_parameter) buffer : SB, offset : u32) -> mat4x2<f32> {
   return mat4x2<f32>(tint_symbol_5(buffer, (offset + 0u)), tint_symbol_5(buffer, (offset + 8u)), tint_symbol_5(buffer, (offset + 16u)), tint_symbol_5(buffer, (offset + 24u)));
 }
 
-fn tint_symbol_19([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : SB, offset : u32) -> mat4x3<f32> {
+fn tint_symbol_19(@internal(disable_validation__ignore_constructible_function_parameter) buffer : SB, offset : u32) -> mat4x3<f32> {
   return mat4x3<f32>(tint_symbol_8(buffer, (offset + 0u)), tint_symbol_8(buffer, (offset + 16u)), tint_symbol_8(buffer, (offset + 32u)), tint_symbol_8(buffer, (offset + 48u)));
 }
 
-fn tint_symbol_20([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : SB, offset : u32) -> mat4x4<f32> {
+fn tint_symbol_20(@internal(disable_validation__ignore_constructible_function_parameter) buffer : SB, offset : u32) -> mat4x4<f32> {
   return mat4x4<f32>(tint_symbol_11(buffer, (offset + 0u)), tint_symbol_11(buffer, (offset + 16u)), tint_symbol_11(buffer, (offset + 32u)), tint_symbol_11(buffer, (offset + 48u)));
 }
 
-fn tint_symbol_21([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : SB, offset : u32) -> array<vec3<f32>, 2u> {
+fn tint_symbol_21(@internal(disable_validation__ignore_constructible_function_parameter) buffer : SB, offset : u32) -> array<vec3<f32>, 2u> {
   var arr : array<vec3<f32>, 2u>;
   for(var i_1 = 0u; (i_1 < 2u); i_1 = (i_1 + 1u)) {
     arr[i_1] = tint_symbol_8(buffer, (offset + (i_1 * 16u)));
@@ -186,7 +186,7 @@
   return arr;
 }
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn main() {
   var a : i32 = tint_symbol(sb, 0u);
   var b : u32 = tint_symbol_1(sb, 4u);
@@ -245,9 +245,9 @@
   v : array<vec3<f32>, 2>;
 };
 
-[[group(0), binding(0)]] var<uniform> ub : UB;
+@group(0) @binding(0) var<uniform> ub : UB;
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn main() {
   var a : i32 = ub.a;
   var b : u32 = ub.b;
@@ -300,81 +300,81 @@
   v : array<vec3<f32>, 2>;
 }
 
-[[group(0), binding(0)]] var<uniform> ub : UB;
+@group(0) @binding(0) var<uniform> ub : UB;
 
-[[internal(intrinsic_load_uniform_i32), internal(disable_validation__function_has_no_body)]]
-fn tint_symbol([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : UB, offset : u32) -> i32
+@internal(intrinsic_load_uniform_i32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol(@internal(disable_validation__ignore_constructible_function_parameter) buffer : UB, offset : u32) -> i32
 
-[[internal(intrinsic_load_uniform_u32), internal(disable_validation__function_has_no_body)]]
-fn tint_symbol_1([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : UB, offset : u32) -> u32
+@internal(intrinsic_load_uniform_u32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_1(@internal(disable_validation__ignore_constructible_function_parameter) buffer : UB, offset : u32) -> u32
 
-[[internal(intrinsic_load_uniform_f32), internal(disable_validation__function_has_no_body)]]
-fn tint_symbol_2([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : UB, offset : u32) -> f32
+@internal(intrinsic_load_uniform_f32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_2(@internal(disable_validation__ignore_constructible_function_parameter) buffer : UB, offset : u32) -> f32
 
-[[internal(intrinsic_load_uniform_vec2_i32), internal(disable_validation__function_has_no_body)]]
-fn tint_symbol_3([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : UB, offset : u32) -> vec2<i32>
+@internal(intrinsic_load_uniform_vec2_i32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_3(@internal(disable_validation__ignore_constructible_function_parameter) buffer : UB, offset : u32) -> vec2<i32>
 
-[[internal(intrinsic_load_uniform_vec2_u32), internal(disable_validation__function_has_no_body)]]
-fn tint_symbol_4([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : UB, offset : u32) -> vec2<u32>
+@internal(intrinsic_load_uniform_vec2_u32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_4(@internal(disable_validation__ignore_constructible_function_parameter) buffer : UB, offset : u32) -> vec2<u32>
 
-[[internal(intrinsic_load_uniform_vec2_f32), internal(disable_validation__function_has_no_body)]]
-fn tint_symbol_5([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : UB, offset : u32) -> vec2<f32>
+@internal(intrinsic_load_uniform_vec2_f32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_5(@internal(disable_validation__ignore_constructible_function_parameter) buffer : UB, offset : u32) -> vec2<f32>
 
-[[internal(intrinsic_load_uniform_vec3_i32), internal(disable_validation__function_has_no_body)]]
-fn tint_symbol_6([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : UB, offset : u32) -> vec3<i32>
+@internal(intrinsic_load_uniform_vec3_i32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_6(@internal(disable_validation__ignore_constructible_function_parameter) buffer : UB, offset : u32) -> vec3<i32>
 
-[[internal(intrinsic_load_uniform_vec3_u32), internal(disable_validation__function_has_no_body)]]
-fn tint_symbol_7([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : UB, offset : u32) -> vec3<u32>
+@internal(intrinsic_load_uniform_vec3_u32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_7(@internal(disable_validation__ignore_constructible_function_parameter) buffer : UB, offset : u32) -> vec3<u32>
 
-[[internal(intrinsic_load_uniform_vec3_f32), internal(disable_validation__function_has_no_body)]]
-fn tint_symbol_8([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : UB, offset : u32) -> vec3<f32>
+@internal(intrinsic_load_uniform_vec3_f32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_8(@internal(disable_validation__ignore_constructible_function_parameter) buffer : UB, offset : u32) -> vec3<f32>
 
-[[internal(intrinsic_load_uniform_vec4_i32), internal(disable_validation__function_has_no_body)]]
-fn tint_symbol_9([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : UB, offset : u32) -> vec4<i32>
+@internal(intrinsic_load_uniform_vec4_i32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_9(@internal(disable_validation__ignore_constructible_function_parameter) buffer : UB, offset : u32) -> vec4<i32>
 
-[[internal(intrinsic_load_uniform_vec4_u32), internal(disable_validation__function_has_no_body)]]
-fn tint_symbol_10([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : UB, offset : u32) -> vec4<u32>
+@internal(intrinsic_load_uniform_vec4_u32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_10(@internal(disable_validation__ignore_constructible_function_parameter) buffer : UB, offset : u32) -> vec4<u32>
 
-[[internal(intrinsic_load_uniform_vec4_f32), internal(disable_validation__function_has_no_body)]]
-fn tint_symbol_11([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : UB, offset : u32) -> vec4<f32>
+@internal(intrinsic_load_uniform_vec4_f32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_11(@internal(disable_validation__ignore_constructible_function_parameter) buffer : UB, offset : u32) -> vec4<f32>
 
-fn tint_symbol_12([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : UB, offset : u32) -> mat2x2<f32> {
+fn tint_symbol_12(@internal(disable_validation__ignore_constructible_function_parameter) buffer : UB, offset : u32) -> mat2x2<f32> {
   return mat2x2<f32>(tint_symbol_5(buffer, (offset + 0u)), tint_symbol_5(buffer, (offset + 8u)));
 }
 
-fn tint_symbol_13([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : UB, offset : u32) -> mat2x3<f32> {
+fn tint_symbol_13(@internal(disable_validation__ignore_constructible_function_parameter) buffer : UB, offset : u32) -> mat2x3<f32> {
   return mat2x3<f32>(tint_symbol_8(buffer, (offset + 0u)), tint_symbol_8(buffer, (offset + 16u)));
 }
 
-fn tint_symbol_14([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : UB, offset : u32) -> mat2x4<f32> {
+fn tint_symbol_14(@internal(disable_validation__ignore_constructible_function_parameter) buffer : UB, offset : u32) -> mat2x4<f32> {
   return mat2x4<f32>(tint_symbol_11(buffer, (offset + 0u)), tint_symbol_11(buffer, (offset + 16u)));
 }
 
-fn tint_symbol_15([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : UB, offset : u32) -> mat3x2<f32> {
+fn tint_symbol_15(@internal(disable_validation__ignore_constructible_function_parameter) buffer : UB, offset : u32) -> mat3x2<f32> {
   return mat3x2<f32>(tint_symbol_5(buffer, (offset + 0u)), tint_symbol_5(buffer, (offset + 8u)), tint_symbol_5(buffer, (offset + 16u)));
 }
 
-fn tint_symbol_16([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : UB, offset : u32) -> mat3x3<f32> {
+fn tint_symbol_16(@internal(disable_validation__ignore_constructible_function_parameter) buffer : UB, offset : u32) -> mat3x3<f32> {
   return mat3x3<f32>(tint_symbol_8(buffer, (offset + 0u)), tint_symbol_8(buffer, (offset + 16u)), tint_symbol_8(buffer, (offset + 32u)));
 }
 
-fn tint_symbol_17([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : UB, offset : u32) -> mat3x4<f32> {
+fn tint_symbol_17(@internal(disable_validation__ignore_constructible_function_parameter) buffer : UB, offset : u32) -> mat3x4<f32> {
   return mat3x4<f32>(tint_symbol_11(buffer, (offset + 0u)), tint_symbol_11(buffer, (offset + 16u)), tint_symbol_11(buffer, (offset + 32u)));
 }
 
-fn tint_symbol_18([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : UB, offset : u32) -> mat4x2<f32> {
+fn tint_symbol_18(@internal(disable_validation__ignore_constructible_function_parameter) buffer : UB, offset : u32) -> mat4x2<f32> {
   return mat4x2<f32>(tint_symbol_5(buffer, (offset + 0u)), tint_symbol_5(buffer, (offset + 8u)), tint_symbol_5(buffer, (offset + 16u)), tint_symbol_5(buffer, (offset + 24u)));
 }
 
-fn tint_symbol_19([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : UB, offset : u32) -> mat4x3<f32> {
+fn tint_symbol_19(@internal(disable_validation__ignore_constructible_function_parameter) buffer : UB, offset : u32) -> mat4x3<f32> {
   return mat4x3<f32>(tint_symbol_8(buffer, (offset + 0u)), tint_symbol_8(buffer, (offset + 16u)), tint_symbol_8(buffer, (offset + 32u)), tint_symbol_8(buffer, (offset + 48u)));
 }
 
-fn tint_symbol_20([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : UB, offset : u32) -> mat4x4<f32> {
+fn tint_symbol_20(@internal(disable_validation__ignore_constructible_function_parameter) buffer : UB, offset : u32) -> mat4x4<f32> {
   return mat4x4<f32>(tint_symbol_11(buffer, (offset + 0u)), tint_symbol_11(buffer, (offset + 16u)), tint_symbol_11(buffer, (offset + 32u)), tint_symbol_11(buffer, (offset + 48u)));
 }
 
-fn tint_symbol_21([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : UB, offset : u32) -> array<vec3<f32>, 2u> {
+fn tint_symbol_21(@internal(disable_validation__ignore_constructible_function_parameter) buffer : UB, offset : u32) -> array<vec3<f32>, 2u> {
   var arr : array<vec3<f32>, 2u>;
   for(var i_1 = 0u; (i_1 < 2u); i_1 = (i_1 + 1u)) {
     arr[i_1] = tint_symbol_8(buffer, (offset + (i_1 * 16u)));
@@ -382,7 +382,7 @@
   return arr;
 }
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn main() {
   var a : i32 = tint_symbol(ub, 0u);
   var b : u32 = tint_symbol_1(ub, 4u);
@@ -441,9 +441,9 @@
   v : array<vec3<f32>, 2>;
 };
 
-[[group(0), binding(0)]] var<storage, read_write> sb : SB;
+@group(0) @binding(0) var<storage, read_write> sb : SB;
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn main() {
   sb.a = i32();
   sb.b = u32();
@@ -496,106 +496,106 @@
   v : array<vec3<f32>, 2>;
 }
 
-[[group(0), binding(0)]] var<storage, read_write> sb : SB;
+@group(0) @binding(0) var<storage, read_write> sb : SB;
 
-[[internal(intrinsic_store_storage_i32), internal(disable_validation__function_has_no_body)]]
-fn tint_symbol([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : SB, offset : u32, value : i32)
+@internal(intrinsic_store_storage_i32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol(@internal(disable_validation__ignore_constructible_function_parameter) buffer : SB, offset : u32, value : i32)
 
-[[internal(intrinsic_store_storage_u32), internal(disable_validation__function_has_no_body)]]
-fn tint_symbol_1([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : SB, offset : u32, value : u32)
+@internal(intrinsic_store_storage_u32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_1(@internal(disable_validation__ignore_constructible_function_parameter) buffer : SB, offset : u32, value : u32)
 
-[[internal(intrinsic_store_storage_f32), internal(disable_validation__function_has_no_body)]]
-fn tint_symbol_2([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : SB, offset : u32, value : f32)
+@internal(intrinsic_store_storage_f32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_2(@internal(disable_validation__ignore_constructible_function_parameter) buffer : SB, offset : u32, value : f32)
 
-[[internal(intrinsic_store_storage_vec2_i32), internal(disable_validation__function_has_no_body)]]
-fn tint_symbol_3([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : SB, offset : u32, value : vec2<i32>)
+@internal(intrinsic_store_storage_vec2_i32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_3(@internal(disable_validation__ignore_constructible_function_parameter) buffer : SB, offset : u32, value : vec2<i32>)
 
-[[internal(intrinsic_store_storage_vec2_u32), internal(disable_validation__function_has_no_body)]]
-fn tint_symbol_4([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : SB, offset : u32, value : vec2<u32>)
+@internal(intrinsic_store_storage_vec2_u32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_4(@internal(disable_validation__ignore_constructible_function_parameter) buffer : SB, offset : u32, value : vec2<u32>)
 
-[[internal(intrinsic_store_storage_vec2_f32), internal(disable_validation__function_has_no_body)]]
-fn tint_symbol_5([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : SB, offset : u32, value : vec2<f32>)
+@internal(intrinsic_store_storage_vec2_f32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_5(@internal(disable_validation__ignore_constructible_function_parameter) buffer : SB, offset : u32, value : vec2<f32>)
 
-[[internal(intrinsic_store_storage_vec3_i32), internal(disable_validation__function_has_no_body)]]
-fn tint_symbol_6([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : SB, offset : u32, value : vec3<i32>)
+@internal(intrinsic_store_storage_vec3_i32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_6(@internal(disable_validation__ignore_constructible_function_parameter) buffer : SB, offset : u32, value : vec3<i32>)
 
-[[internal(intrinsic_store_storage_vec3_u32), internal(disable_validation__function_has_no_body)]]
-fn tint_symbol_7([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : SB, offset : u32, value : vec3<u32>)
+@internal(intrinsic_store_storage_vec3_u32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_7(@internal(disable_validation__ignore_constructible_function_parameter) buffer : SB, offset : u32, value : vec3<u32>)
 
-[[internal(intrinsic_store_storage_vec3_f32), internal(disable_validation__function_has_no_body)]]
-fn tint_symbol_8([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : SB, offset : u32, value : vec3<f32>)
+@internal(intrinsic_store_storage_vec3_f32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_8(@internal(disable_validation__ignore_constructible_function_parameter) buffer : SB, offset : u32, value : vec3<f32>)
 
-[[internal(intrinsic_store_storage_vec4_i32), internal(disable_validation__function_has_no_body)]]
-fn tint_symbol_9([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : SB, offset : u32, value : vec4<i32>)
+@internal(intrinsic_store_storage_vec4_i32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_9(@internal(disable_validation__ignore_constructible_function_parameter) buffer : SB, offset : u32, value : vec4<i32>)
 
-[[internal(intrinsic_store_storage_vec4_u32), internal(disable_validation__function_has_no_body)]]
-fn tint_symbol_10([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : SB, offset : u32, value : vec4<u32>)
+@internal(intrinsic_store_storage_vec4_u32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_10(@internal(disable_validation__ignore_constructible_function_parameter) buffer : SB, offset : u32, value : vec4<u32>)
 
-[[internal(intrinsic_store_storage_vec4_f32), internal(disable_validation__function_has_no_body)]]
-fn tint_symbol_11([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : SB, offset : u32, value : vec4<f32>)
+@internal(intrinsic_store_storage_vec4_f32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_11(@internal(disable_validation__ignore_constructible_function_parameter) buffer : SB, offset : u32, value : vec4<f32>)
 
-fn tint_symbol_12([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : SB, offset : u32, value : mat2x2<f32>) {
+fn tint_symbol_12(@internal(disable_validation__ignore_constructible_function_parameter) buffer : SB, offset : u32, value : mat2x2<f32>) {
   tint_symbol_5(buffer, (offset + 0u), value[0u]);
   tint_symbol_5(buffer, (offset + 8u), value[1u]);
 }
 
-fn tint_symbol_13([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : SB, offset : u32, value : mat2x3<f32>) {
+fn tint_symbol_13(@internal(disable_validation__ignore_constructible_function_parameter) buffer : SB, offset : u32, value : mat2x3<f32>) {
   tint_symbol_8(buffer, (offset + 0u), value[0u]);
   tint_symbol_8(buffer, (offset + 16u), value[1u]);
 }
 
-fn tint_symbol_14([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : SB, offset : u32, value : mat2x4<f32>) {
+fn tint_symbol_14(@internal(disable_validation__ignore_constructible_function_parameter) buffer : SB, offset : u32, value : mat2x4<f32>) {
   tint_symbol_11(buffer, (offset + 0u), value[0u]);
   tint_symbol_11(buffer, (offset + 16u), value[1u]);
 }
 
-fn tint_symbol_15([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : SB, offset : u32, value : mat3x2<f32>) {
+fn tint_symbol_15(@internal(disable_validation__ignore_constructible_function_parameter) buffer : SB, offset : u32, value : mat3x2<f32>) {
   tint_symbol_5(buffer, (offset + 0u), value[0u]);
   tint_symbol_5(buffer, (offset + 8u), value[1u]);
   tint_symbol_5(buffer, (offset + 16u), value[2u]);
 }
 
-fn tint_symbol_16([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : SB, offset : u32, value : mat3x3<f32>) {
+fn tint_symbol_16(@internal(disable_validation__ignore_constructible_function_parameter) buffer : SB, offset : u32, value : mat3x3<f32>) {
   tint_symbol_8(buffer, (offset + 0u), value[0u]);
   tint_symbol_8(buffer, (offset + 16u), value[1u]);
   tint_symbol_8(buffer, (offset + 32u), value[2u]);
 }
 
-fn tint_symbol_17([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : SB, offset : u32, value : mat3x4<f32>) {
+fn tint_symbol_17(@internal(disable_validation__ignore_constructible_function_parameter) buffer : SB, offset : u32, value : mat3x4<f32>) {
   tint_symbol_11(buffer, (offset + 0u), value[0u]);
   tint_symbol_11(buffer, (offset + 16u), value[1u]);
   tint_symbol_11(buffer, (offset + 32u), value[2u]);
 }
 
-fn tint_symbol_18([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : SB, offset : u32, value : mat4x2<f32>) {
+fn tint_symbol_18(@internal(disable_validation__ignore_constructible_function_parameter) buffer : SB, offset : u32, value : mat4x2<f32>) {
   tint_symbol_5(buffer, (offset + 0u), value[0u]);
   tint_symbol_5(buffer, (offset + 8u), value[1u]);
   tint_symbol_5(buffer, (offset + 16u), value[2u]);
   tint_symbol_5(buffer, (offset + 24u), value[3u]);
 }
 
-fn tint_symbol_19([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : SB, offset : u32, value : mat4x3<f32>) {
+fn tint_symbol_19(@internal(disable_validation__ignore_constructible_function_parameter) buffer : SB, offset : u32, value : mat4x3<f32>) {
   tint_symbol_8(buffer, (offset + 0u), value[0u]);
   tint_symbol_8(buffer, (offset + 16u), value[1u]);
   tint_symbol_8(buffer, (offset + 32u), value[2u]);
   tint_symbol_8(buffer, (offset + 48u), value[3u]);
 }
 
-fn tint_symbol_20([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : SB, offset : u32, value : mat4x4<f32>) {
+fn tint_symbol_20(@internal(disable_validation__ignore_constructible_function_parameter) buffer : SB, offset : u32, value : mat4x4<f32>) {
   tint_symbol_11(buffer, (offset + 0u), value[0u]);
   tint_symbol_11(buffer, (offset + 16u), value[1u]);
   tint_symbol_11(buffer, (offset + 32u), value[2u]);
   tint_symbol_11(buffer, (offset + 48u), value[3u]);
 }
 
-fn tint_symbol_21([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : SB, offset : u32, value : array<vec3<f32>, 2u>) {
+fn tint_symbol_21(@internal(disable_validation__ignore_constructible_function_parameter) buffer : SB, offset : u32, value : array<vec3<f32>, 2u>) {
   var array = value;
   for(var i_1 = 0u; (i_1 < 2u); i_1 = (i_1 + 1u)) {
     tint_symbol_8(buffer, (offset + (i_1 * 16u)), array[i_1]);
   }
 }
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn main() {
   tint_symbol(sb, 0u, i32());
   tint_symbol_1(sb, 4u, u32());
@@ -654,9 +654,9 @@
   v : array<vec3<f32>, 2>;
 };
 
-[[group(0), binding(0)]] var<storage, read_write> sb : SB;
+@group(0) @binding(0) var<storage, read_write> sb : SB;
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn main() {
   var x : SB = sb;
 }
@@ -688,81 +688,81 @@
   v : array<vec3<f32>, 2>;
 }
 
-[[group(0), binding(0)]] var<storage, read_write> sb : SB;
+@group(0) @binding(0) var<storage, read_write> sb : SB;
 
-[[internal(intrinsic_load_storage_i32), internal(disable_validation__function_has_no_body)]]
-fn tint_symbol_1([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : SB, offset : u32) -> i32
+@internal(intrinsic_load_storage_i32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_1(@internal(disable_validation__ignore_constructible_function_parameter) buffer : SB, offset : u32) -> i32
 
-[[internal(intrinsic_load_storage_u32), internal(disable_validation__function_has_no_body)]]
-fn tint_symbol_2([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : SB, offset : u32) -> u32
+@internal(intrinsic_load_storage_u32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_2(@internal(disable_validation__ignore_constructible_function_parameter) buffer : SB, offset : u32) -> u32
 
-[[internal(intrinsic_load_storage_f32), internal(disable_validation__function_has_no_body)]]
-fn tint_symbol_3([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : SB, offset : u32) -> f32
+@internal(intrinsic_load_storage_f32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_3(@internal(disable_validation__ignore_constructible_function_parameter) buffer : SB, offset : u32) -> f32
 
-[[internal(intrinsic_load_storage_vec2_i32), internal(disable_validation__function_has_no_body)]]
-fn tint_symbol_4([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : SB, offset : u32) -> vec2<i32>
+@internal(intrinsic_load_storage_vec2_i32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_4(@internal(disable_validation__ignore_constructible_function_parameter) buffer : SB, offset : u32) -> vec2<i32>
 
-[[internal(intrinsic_load_storage_vec2_u32), internal(disable_validation__function_has_no_body)]]
-fn tint_symbol_5([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : SB, offset : u32) -> vec2<u32>
+@internal(intrinsic_load_storage_vec2_u32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_5(@internal(disable_validation__ignore_constructible_function_parameter) buffer : SB, offset : u32) -> vec2<u32>
 
-[[internal(intrinsic_load_storage_vec2_f32), internal(disable_validation__function_has_no_body)]]
-fn tint_symbol_6([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : SB, offset : u32) -> vec2<f32>
+@internal(intrinsic_load_storage_vec2_f32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_6(@internal(disable_validation__ignore_constructible_function_parameter) buffer : SB, offset : u32) -> vec2<f32>
 
-[[internal(intrinsic_load_storage_vec3_i32), internal(disable_validation__function_has_no_body)]]
-fn tint_symbol_7([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : SB, offset : u32) -> vec3<i32>
+@internal(intrinsic_load_storage_vec3_i32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_7(@internal(disable_validation__ignore_constructible_function_parameter) buffer : SB, offset : u32) -> vec3<i32>
 
-[[internal(intrinsic_load_storage_vec3_u32), internal(disable_validation__function_has_no_body)]]
-fn tint_symbol_8([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : SB, offset : u32) -> vec3<u32>
+@internal(intrinsic_load_storage_vec3_u32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_8(@internal(disable_validation__ignore_constructible_function_parameter) buffer : SB, offset : u32) -> vec3<u32>
 
-[[internal(intrinsic_load_storage_vec3_f32), internal(disable_validation__function_has_no_body)]]
-fn tint_symbol_9([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : SB, offset : u32) -> vec3<f32>
+@internal(intrinsic_load_storage_vec3_f32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_9(@internal(disable_validation__ignore_constructible_function_parameter) buffer : SB, offset : u32) -> vec3<f32>
 
-[[internal(intrinsic_load_storage_vec4_i32), internal(disable_validation__function_has_no_body)]]
-fn tint_symbol_10([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : SB, offset : u32) -> vec4<i32>
+@internal(intrinsic_load_storage_vec4_i32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_10(@internal(disable_validation__ignore_constructible_function_parameter) buffer : SB, offset : u32) -> vec4<i32>
 
-[[internal(intrinsic_load_storage_vec4_u32), internal(disable_validation__function_has_no_body)]]
-fn tint_symbol_11([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : SB, offset : u32) -> vec4<u32>
+@internal(intrinsic_load_storage_vec4_u32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_11(@internal(disable_validation__ignore_constructible_function_parameter) buffer : SB, offset : u32) -> vec4<u32>
 
-[[internal(intrinsic_load_storage_vec4_f32), internal(disable_validation__function_has_no_body)]]
-fn tint_symbol_12([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : SB, offset : u32) -> vec4<f32>
+@internal(intrinsic_load_storage_vec4_f32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_12(@internal(disable_validation__ignore_constructible_function_parameter) buffer : SB, offset : u32) -> vec4<f32>
 
-fn tint_symbol_13([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : SB, offset : u32) -> mat2x2<f32> {
+fn tint_symbol_13(@internal(disable_validation__ignore_constructible_function_parameter) buffer : SB, offset : u32) -> mat2x2<f32> {
   return mat2x2<f32>(tint_symbol_6(buffer, (offset + 0u)), tint_symbol_6(buffer, (offset + 8u)));
 }
 
-fn tint_symbol_14([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : SB, offset : u32) -> mat2x3<f32> {
+fn tint_symbol_14(@internal(disable_validation__ignore_constructible_function_parameter) buffer : SB, offset : u32) -> mat2x3<f32> {
   return mat2x3<f32>(tint_symbol_9(buffer, (offset + 0u)), tint_symbol_9(buffer, (offset + 16u)));
 }
 
-fn tint_symbol_15([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : SB, offset : u32) -> mat2x4<f32> {
+fn tint_symbol_15(@internal(disable_validation__ignore_constructible_function_parameter) buffer : SB, offset : u32) -> mat2x4<f32> {
   return mat2x4<f32>(tint_symbol_12(buffer, (offset + 0u)), tint_symbol_12(buffer, (offset + 16u)));
 }
 
-fn tint_symbol_16([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : SB, offset : u32) -> mat3x2<f32> {
+fn tint_symbol_16(@internal(disable_validation__ignore_constructible_function_parameter) buffer : SB, offset : u32) -> mat3x2<f32> {
   return mat3x2<f32>(tint_symbol_6(buffer, (offset + 0u)), tint_symbol_6(buffer, (offset + 8u)), tint_symbol_6(buffer, (offset + 16u)));
 }
 
-fn tint_symbol_17([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : SB, offset : u32) -> mat3x3<f32> {
+fn tint_symbol_17(@internal(disable_validation__ignore_constructible_function_parameter) buffer : SB, offset : u32) -> mat3x3<f32> {
   return mat3x3<f32>(tint_symbol_9(buffer, (offset + 0u)), tint_symbol_9(buffer, (offset + 16u)), tint_symbol_9(buffer, (offset + 32u)));
 }
 
-fn tint_symbol_18([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : SB, offset : u32) -> mat3x4<f32> {
+fn tint_symbol_18(@internal(disable_validation__ignore_constructible_function_parameter) buffer : SB, offset : u32) -> mat3x4<f32> {
   return mat3x4<f32>(tint_symbol_12(buffer, (offset + 0u)), tint_symbol_12(buffer, (offset + 16u)), tint_symbol_12(buffer, (offset + 32u)));
 }
 
-fn tint_symbol_19([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : SB, offset : u32) -> mat4x2<f32> {
+fn tint_symbol_19(@internal(disable_validation__ignore_constructible_function_parameter) buffer : SB, offset : u32) -> mat4x2<f32> {
   return mat4x2<f32>(tint_symbol_6(buffer, (offset + 0u)), tint_symbol_6(buffer, (offset + 8u)), tint_symbol_6(buffer, (offset + 16u)), tint_symbol_6(buffer, (offset + 24u)));
 }
 
-fn tint_symbol_20([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : SB, offset : u32) -> mat4x3<f32> {
+fn tint_symbol_20(@internal(disable_validation__ignore_constructible_function_parameter) buffer : SB, offset : u32) -> mat4x3<f32> {
   return mat4x3<f32>(tint_symbol_9(buffer, (offset + 0u)), tint_symbol_9(buffer, (offset + 16u)), tint_symbol_9(buffer, (offset + 32u)), tint_symbol_9(buffer, (offset + 48u)));
 }
 
-fn tint_symbol_21([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : SB, offset : u32) -> mat4x4<f32> {
+fn tint_symbol_21(@internal(disable_validation__ignore_constructible_function_parameter) buffer : SB, offset : u32) -> mat4x4<f32> {
   return mat4x4<f32>(tint_symbol_12(buffer, (offset + 0u)), tint_symbol_12(buffer, (offset + 16u)), tint_symbol_12(buffer, (offset + 32u)), tint_symbol_12(buffer, (offset + 48u)));
 }
 
-fn tint_symbol_22([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : SB, offset : u32) -> array<vec3<f32>, 2u> {
+fn tint_symbol_22(@internal(disable_validation__ignore_constructible_function_parameter) buffer : SB, offset : u32) -> array<vec3<f32>, 2u> {
   var arr : array<vec3<f32>, 2u>;
   for(var i_1 = 0u; (i_1 < 2u); i_1 = (i_1 + 1u)) {
     arr[i_1] = tint_symbol_9(buffer, (offset + (i_1 * 16u)));
@@ -770,11 +770,11 @@
   return arr;
 }
 
-fn tint_symbol([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : SB, offset : u32) -> SB {
+fn tint_symbol(@internal(disable_validation__ignore_constructible_function_parameter) buffer : SB, offset : u32) -> SB {
   return SB(tint_symbol_1(buffer, (offset + 0u)), tint_symbol_2(buffer, (offset + 4u)), tint_symbol_3(buffer, (offset + 8u)), tint_symbol_4(buffer, (offset + 16u)), tint_symbol_5(buffer, (offset + 24u)), tint_symbol_6(buffer, (offset + 32u)), tint_symbol_7(buffer, (offset + 48u)), tint_symbol_8(buffer, (offset + 64u)), tint_symbol_9(buffer, (offset + 80u)), tint_symbol_10(buffer, (offset + 96u)), tint_symbol_11(buffer, (offset + 112u)), tint_symbol_12(buffer, (offset + 128u)), tint_symbol_13(buffer, (offset + 144u)), tint_symbol_14(buffer, (offset + 160u)), tint_symbol_15(buffer, (offset + 192u)), tint_symbol_16(buffer, (offset + 224u)), tint_symbol_17(buffer, (offset + 256u)), tint_symbol_18(buffer, (offset + 304u)), tint_symbol_19(buffer, (offset + 352u)), tint_symbol_20(buffer, (offset + 384u)), tint_symbol_21(buffer, (offset + 448u)), tint_symbol_22(buffer, (offset + 512u)));
 }
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn main() {
   var x : SB = tint_symbol(sb, 0u);
 }
@@ -812,9 +812,9 @@
   v : array<vec3<f32>, 2>;
 };
 
-[[group(0), binding(0)]] var<storage, read_write> sb : SB;
+@group(0) @binding(0) var<storage, read_write> sb : SB;
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn main() {
   sb = SB();
 }
@@ -846,106 +846,106 @@
   v : array<vec3<f32>, 2>;
 }
 
-[[group(0), binding(0)]] var<storage, read_write> sb : SB;
+@group(0) @binding(0) var<storage, read_write> sb : SB;
 
-[[internal(intrinsic_store_storage_i32), internal(disable_validation__function_has_no_body)]]
-fn tint_symbol_1([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : SB, offset : u32, value : i32)
+@internal(intrinsic_store_storage_i32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_1(@internal(disable_validation__ignore_constructible_function_parameter) buffer : SB, offset : u32, value : i32)
 
-[[internal(intrinsic_store_storage_u32), internal(disable_validation__function_has_no_body)]]
-fn tint_symbol_2([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : SB, offset : u32, value : u32)
+@internal(intrinsic_store_storage_u32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_2(@internal(disable_validation__ignore_constructible_function_parameter) buffer : SB, offset : u32, value : u32)
 
-[[internal(intrinsic_store_storage_f32), internal(disable_validation__function_has_no_body)]]
-fn tint_symbol_3([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : SB, offset : u32, value : f32)
+@internal(intrinsic_store_storage_f32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_3(@internal(disable_validation__ignore_constructible_function_parameter) buffer : SB, offset : u32, value : f32)
 
-[[internal(intrinsic_store_storage_vec2_i32), internal(disable_validation__function_has_no_body)]]
-fn tint_symbol_4([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : SB, offset : u32, value : vec2<i32>)
+@internal(intrinsic_store_storage_vec2_i32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_4(@internal(disable_validation__ignore_constructible_function_parameter) buffer : SB, offset : u32, value : vec2<i32>)
 
-[[internal(intrinsic_store_storage_vec2_u32), internal(disable_validation__function_has_no_body)]]
-fn tint_symbol_5([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : SB, offset : u32, value : vec2<u32>)
+@internal(intrinsic_store_storage_vec2_u32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_5(@internal(disable_validation__ignore_constructible_function_parameter) buffer : SB, offset : u32, value : vec2<u32>)
 
-[[internal(intrinsic_store_storage_vec2_f32), internal(disable_validation__function_has_no_body)]]
-fn tint_symbol_6([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : SB, offset : u32, value : vec2<f32>)
+@internal(intrinsic_store_storage_vec2_f32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_6(@internal(disable_validation__ignore_constructible_function_parameter) buffer : SB, offset : u32, value : vec2<f32>)
 
-[[internal(intrinsic_store_storage_vec3_i32), internal(disable_validation__function_has_no_body)]]
-fn tint_symbol_7([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : SB, offset : u32, value : vec3<i32>)
+@internal(intrinsic_store_storage_vec3_i32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_7(@internal(disable_validation__ignore_constructible_function_parameter) buffer : SB, offset : u32, value : vec3<i32>)
 
-[[internal(intrinsic_store_storage_vec3_u32), internal(disable_validation__function_has_no_body)]]
-fn tint_symbol_8([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : SB, offset : u32, value : vec3<u32>)
+@internal(intrinsic_store_storage_vec3_u32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_8(@internal(disable_validation__ignore_constructible_function_parameter) buffer : SB, offset : u32, value : vec3<u32>)
 
-[[internal(intrinsic_store_storage_vec3_f32), internal(disable_validation__function_has_no_body)]]
-fn tint_symbol_9([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : SB, offset : u32, value : vec3<f32>)
+@internal(intrinsic_store_storage_vec3_f32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_9(@internal(disable_validation__ignore_constructible_function_parameter) buffer : SB, offset : u32, value : vec3<f32>)
 
-[[internal(intrinsic_store_storage_vec4_i32), internal(disable_validation__function_has_no_body)]]
-fn tint_symbol_10([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : SB, offset : u32, value : vec4<i32>)
+@internal(intrinsic_store_storage_vec4_i32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_10(@internal(disable_validation__ignore_constructible_function_parameter) buffer : SB, offset : u32, value : vec4<i32>)
 
-[[internal(intrinsic_store_storage_vec4_u32), internal(disable_validation__function_has_no_body)]]
-fn tint_symbol_11([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : SB, offset : u32, value : vec4<u32>)
+@internal(intrinsic_store_storage_vec4_u32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_11(@internal(disable_validation__ignore_constructible_function_parameter) buffer : SB, offset : u32, value : vec4<u32>)
 
-[[internal(intrinsic_store_storage_vec4_f32), internal(disable_validation__function_has_no_body)]]
-fn tint_symbol_12([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : SB, offset : u32, value : vec4<f32>)
+@internal(intrinsic_store_storage_vec4_f32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_12(@internal(disable_validation__ignore_constructible_function_parameter) buffer : SB, offset : u32, value : vec4<f32>)
 
-fn tint_symbol_13([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : SB, offset : u32, value : mat2x2<f32>) {
+fn tint_symbol_13(@internal(disable_validation__ignore_constructible_function_parameter) buffer : SB, offset : u32, value : mat2x2<f32>) {
   tint_symbol_6(buffer, (offset + 0u), value[0u]);
   tint_symbol_6(buffer, (offset + 8u), value[1u]);
 }
 
-fn tint_symbol_14([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : SB, offset : u32, value : mat2x3<f32>) {
+fn tint_symbol_14(@internal(disable_validation__ignore_constructible_function_parameter) buffer : SB, offset : u32, value : mat2x3<f32>) {
   tint_symbol_9(buffer, (offset + 0u), value[0u]);
   tint_symbol_9(buffer, (offset + 16u), value[1u]);
 }
 
-fn tint_symbol_15([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : SB, offset : u32, value : mat2x4<f32>) {
+fn tint_symbol_15(@internal(disable_validation__ignore_constructible_function_parameter) buffer : SB, offset : u32, value : mat2x4<f32>) {
   tint_symbol_12(buffer, (offset + 0u), value[0u]);
   tint_symbol_12(buffer, (offset + 16u), value[1u]);
 }
 
-fn tint_symbol_16([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : SB, offset : u32, value : mat3x2<f32>) {
+fn tint_symbol_16(@internal(disable_validation__ignore_constructible_function_parameter) buffer : SB, offset : u32, value : mat3x2<f32>) {
   tint_symbol_6(buffer, (offset + 0u), value[0u]);
   tint_symbol_6(buffer, (offset + 8u), value[1u]);
   tint_symbol_6(buffer, (offset + 16u), value[2u]);
 }
 
-fn tint_symbol_17([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : SB, offset : u32, value : mat3x3<f32>) {
+fn tint_symbol_17(@internal(disable_validation__ignore_constructible_function_parameter) buffer : SB, offset : u32, value : mat3x3<f32>) {
   tint_symbol_9(buffer, (offset + 0u), value[0u]);
   tint_symbol_9(buffer, (offset + 16u), value[1u]);
   tint_symbol_9(buffer, (offset + 32u), value[2u]);
 }
 
-fn tint_symbol_18([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : SB, offset : u32, value : mat3x4<f32>) {
+fn tint_symbol_18(@internal(disable_validation__ignore_constructible_function_parameter) buffer : SB, offset : u32, value : mat3x4<f32>) {
   tint_symbol_12(buffer, (offset + 0u), value[0u]);
   tint_symbol_12(buffer, (offset + 16u), value[1u]);
   tint_symbol_12(buffer, (offset + 32u), value[2u]);
 }
 
-fn tint_symbol_19([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : SB, offset : u32, value : mat4x2<f32>) {
+fn tint_symbol_19(@internal(disable_validation__ignore_constructible_function_parameter) buffer : SB, offset : u32, value : mat4x2<f32>) {
   tint_symbol_6(buffer, (offset + 0u), value[0u]);
   tint_symbol_6(buffer, (offset + 8u), value[1u]);
   tint_symbol_6(buffer, (offset + 16u), value[2u]);
   tint_symbol_6(buffer, (offset + 24u), value[3u]);
 }
 
-fn tint_symbol_20([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : SB, offset : u32, value : mat4x3<f32>) {
+fn tint_symbol_20(@internal(disable_validation__ignore_constructible_function_parameter) buffer : SB, offset : u32, value : mat4x3<f32>) {
   tint_symbol_9(buffer, (offset + 0u), value[0u]);
   tint_symbol_9(buffer, (offset + 16u), value[1u]);
   tint_symbol_9(buffer, (offset + 32u), value[2u]);
   tint_symbol_9(buffer, (offset + 48u), value[3u]);
 }
 
-fn tint_symbol_21([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : SB, offset : u32, value : mat4x4<f32>) {
+fn tint_symbol_21(@internal(disable_validation__ignore_constructible_function_parameter) buffer : SB, offset : u32, value : mat4x4<f32>) {
   tint_symbol_12(buffer, (offset + 0u), value[0u]);
   tint_symbol_12(buffer, (offset + 16u), value[1u]);
   tint_symbol_12(buffer, (offset + 32u), value[2u]);
   tint_symbol_12(buffer, (offset + 48u), value[3u]);
 }
 
-fn tint_symbol_22([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : SB, offset : u32, value : array<vec3<f32>, 2u>) {
+fn tint_symbol_22(@internal(disable_validation__ignore_constructible_function_parameter) buffer : SB, offset : u32, value : array<vec3<f32>, 2u>) {
   var array = value;
   for(var i_1 = 0u; (i_1 < 2u); i_1 = (i_1 + 1u)) {
     tint_symbol_9(buffer, (offset + (i_1 * 16u)), array[i_1]);
   }
 }
 
-fn tint_symbol([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : SB, offset : u32, value : SB) {
+fn tint_symbol(@internal(disable_validation__ignore_constructible_function_parameter) buffer : SB, offset : u32, value : SB) {
   tint_symbol_1(buffer, (offset + 0u), value.a);
   tint_symbol_2(buffer, (offset + 4u), value.b);
   tint_symbol_3(buffer, (offset + 8u), value.c);
@@ -970,7 +970,7 @@
   tint_symbol_22(buffer, (offset + 512u), value.v);
 }
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn main() {
   tint_symbol(sb, 0u, SB());
 }
@@ -991,19 +991,19 @@
 
 struct S2 {
   a : i32;
-  b : [[stride(32)]] array<S1, 3>;
+  b : @stride(32) array<S1, 3>;
   c : i32;
 };
 
 struct SB {
-  [[size(128)]]
+  @size(128)
   a : i32;
-  b : [[stride(256)]] array<S2>;
+  b : @stride(256) array<S2>;
 };
 
-[[group(0), binding(0)]] var<storage, read_write> sb : SB;
+@group(0) @binding(0) var<storage, read_write> sb : SB;
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn main() {
   var x : f32 = sb.b[4].b[1].b.z;
 }
@@ -1025,22 +1025,22 @@
 
 struct S2 {
   a : i32;
-  b : [[stride(32)]] array<S1, 3>;
+  b : @stride(32) array<S1, 3>;
   c : i32;
 }
 
 struct SB {
-  [[size(128)]]
+  @size(128)
   a : i32;
-  b : [[stride(256)]] array<S2>;
+  b : @stride(256) array<S2>;
 }
 
-[[group(0), binding(0)]] var<storage, read_write> sb : SB;
+@group(0) @binding(0) var<storage, read_write> sb : SB;
 
-[[internal(intrinsic_load_storage_f32), internal(disable_validation__function_has_no_body)]]
-fn tint_symbol([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : SB, offset : u32) -> f32
+@internal(intrinsic_load_storage_f32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol(@internal(disable_validation__ignore_constructible_function_parameter) buffer : SB, offset : u32) -> f32
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn main() {
   var x : f32 = tint_symbol(sb, 1224u);
 }
@@ -1061,19 +1061,19 @@
 
 struct S2 {
   a : i32;
-  b : [[stride(32)]] array<S1, 3>;
+  b : @stride(32) array<S1, 3>;
   c : i32;
 };
 
 struct SB {
-  [[size(128)]]
+  @size(128)
   a : i32;
-  b : [[stride(256)]] array<S2>;
+  b : @stride(256) array<S2>;
 };
 
-[[group(0), binding(0)]] var<storage, read_write> sb : SB;
+@group(0) @binding(0) var<storage, read_write> sb : SB;
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn main() {
   var i : i32 = 4;
   var j : u32 = 1u;
@@ -1091,22 +1091,22 @@
 
 struct S2 {
   a : i32;
-  b : [[stride(32)]] array<S1, 3>;
+  b : @stride(32) array<S1, 3>;
   c : i32;
 }
 
 struct SB {
-  [[size(128)]]
+  @size(128)
   a : i32;
-  b : [[stride(256)]] array<S2>;
+  b : @stride(256) array<S2>;
 }
 
-[[group(0), binding(0)]] var<storage, read_write> sb : SB;
+@group(0) @binding(0) var<storage, read_write> sb : SB;
 
-[[internal(intrinsic_load_storage_f32), internal(disable_validation__function_has_no_body)]]
-fn tint_symbol([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : SB, offset : u32) -> f32
+@internal(intrinsic_load_storage_f32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol(@internal(disable_validation__ignore_constructible_function_parameter) buffer : SB, offset : u32) -> f32
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn main() {
   var i : i32 = 4;
   var j : u32 = 1u;
@@ -1130,7 +1130,7 @@
 
 type A1 = S1;
 
-type A1_Array = [[stride(32)]] array<S1, 3>;
+type A1_Array = @stride(32) array<S1, 3>;
 
 struct S2 {
   a : i32;
@@ -1140,17 +1140,17 @@
 
 type A2 = S2;
 
-type A2_Array = [[stride(256)]] array<S2>;
+type A2_Array = @stride(256) array<S2>;
 
 struct SB {
-  [[size(128)]]
+  @size(128)
   a : i32;
   b : A2_Array;
 };
 
-[[group(0), binding(0)]] var<storage, read_write> sb : SB;
+@group(0) @binding(0) var<storage, read_write> sb : SB;
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn main() {
   var i : i32 = 4;
   var j : u32 = 1u;
@@ -1168,7 +1168,7 @@
 
 type A1 = S1;
 
-type A1_Array = [[stride(32)]] array<S1, 3>;
+type A1_Array = @stride(32) array<S1, 3>;
 
 struct S2 {
   a : i32;
@@ -1178,20 +1178,20 @@
 
 type A2 = S2;
 
-type A2_Array = [[stride(256)]] array<S2>;
+type A2_Array = @stride(256) array<S2>;
 
 struct SB {
-  [[size(128)]]
+  @size(128)
   a : i32;
   b : A2_Array;
 }
 
-[[group(0), binding(0)]] var<storage, read_write> sb : SB;
+@group(0) @binding(0) var<storage, read_write> sb : SB;
 
-[[internal(intrinsic_load_storage_f32), internal(disable_validation__function_has_no_body)]]
-fn tint_symbol([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : SB, offset : u32) -> f32
+@internal(intrinsic_load_storage_f32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol(@internal(disable_validation__ignore_constructible_function_parameter) buffer : SB, offset : u32) -> f32
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn main() {
   var i : i32 = 4;
   var j : u32 = 1u;
@@ -1213,9 +1213,9 @@
   b : atomic<u32>;
 };
 
-[[group(0), binding(0)]] var<storage, read_write> sb : SB;
+@group(0) @binding(0) var<storage, read_write> sb : SB;
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn main() {
   atomicStore(&sb.a, 123);
   atomicLoad(&sb.a);
@@ -1250,75 +1250,75 @@
   b : atomic<u32>;
 }
 
-[[group(0), binding(0)]] var<storage, read_write> sb : SB;
+@group(0) @binding(0) var<storage, read_write> sb : SB;
 
-[[internal(intrinsic_atomic_store_storage_i32), internal(disable_validation__function_has_no_body)]]
-fn tint_symbol([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : SB, offset : u32, param_1 : i32)
+@internal(intrinsic_atomic_store_storage_i32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol(@internal(disable_validation__ignore_constructible_function_parameter) buffer : SB, offset : u32, param_1 : i32)
 
-[[internal(intrinsic_atomic_load_storage_i32), internal(disable_validation__function_has_no_body)]]
-fn tint_symbol_1([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : SB, offset : u32) -> i32
+@internal(intrinsic_atomic_load_storage_i32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_1(@internal(disable_validation__ignore_constructible_function_parameter) buffer : SB, offset : u32) -> i32
 
-[[internal(intrinsic_atomic_add_storage_i32), internal(disable_validation__function_has_no_body)]]
-fn tint_symbol_2([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : SB, offset : u32, param_1 : i32) -> i32
+@internal(intrinsic_atomic_add_storage_i32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_2(@internal(disable_validation__ignore_constructible_function_parameter) buffer : SB, offset : u32, param_1 : i32) -> i32
 
-[[internal(intrinsic_atomic_sub_storage_i32), internal(disable_validation__function_has_no_body)]]
-fn tint_symbol_3([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : SB, offset : u32, param_1 : i32) -> i32
+@internal(intrinsic_atomic_sub_storage_i32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_3(@internal(disable_validation__ignore_constructible_function_parameter) buffer : SB, offset : u32, param_1 : i32) -> i32
 
-[[internal(intrinsic_atomic_max_storage_i32), internal(disable_validation__function_has_no_body)]]
-fn tint_symbol_4([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : SB, offset : u32, param_1 : i32) -> i32
+@internal(intrinsic_atomic_max_storage_i32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_4(@internal(disable_validation__ignore_constructible_function_parameter) buffer : SB, offset : u32, param_1 : i32) -> i32
 
-[[internal(intrinsic_atomic_min_storage_i32), internal(disable_validation__function_has_no_body)]]
-fn tint_symbol_5([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : SB, offset : u32, param_1 : i32) -> i32
+@internal(intrinsic_atomic_min_storage_i32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_5(@internal(disable_validation__ignore_constructible_function_parameter) buffer : SB, offset : u32, param_1 : i32) -> i32
 
-[[internal(intrinsic_atomic_and_storage_i32), internal(disable_validation__function_has_no_body)]]
-fn tint_symbol_6([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : SB, offset : u32, param_1 : i32) -> i32
+@internal(intrinsic_atomic_and_storage_i32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_6(@internal(disable_validation__ignore_constructible_function_parameter) buffer : SB, offset : u32, param_1 : i32) -> i32
 
-[[internal(intrinsic_atomic_or_storage_i32), internal(disable_validation__function_has_no_body)]]
-fn tint_symbol_7([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : SB, offset : u32, param_1 : i32) -> i32
+@internal(intrinsic_atomic_or_storage_i32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_7(@internal(disable_validation__ignore_constructible_function_parameter) buffer : SB, offset : u32, param_1 : i32) -> i32
 
-[[internal(intrinsic_atomic_xor_storage_i32), internal(disable_validation__function_has_no_body)]]
-fn tint_symbol_8([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : SB, offset : u32, param_1 : i32) -> i32
+@internal(intrinsic_atomic_xor_storage_i32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_8(@internal(disable_validation__ignore_constructible_function_parameter) buffer : SB, offset : u32, param_1 : i32) -> i32
 
-[[internal(intrinsic_atomic_exchange_storage_i32), internal(disable_validation__function_has_no_body)]]
-fn tint_symbol_9([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : SB, offset : u32, param_1 : i32) -> i32
+@internal(intrinsic_atomic_exchange_storage_i32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_9(@internal(disable_validation__ignore_constructible_function_parameter) buffer : SB, offset : u32, param_1 : i32) -> i32
 
-[[internal(intrinsic_atomic_compare_exchange_weak_storage_i32), internal(disable_validation__function_has_no_body)]]
-fn tint_symbol_10([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : SB, offset : u32, param_1 : i32, param_2 : i32) -> vec2<i32>
+@internal(intrinsic_atomic_compare_exchange_weak_storage_i32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_10(@internal(disable_validation__ignore_constructible_function_parameter) buffer : SB, offset : u32, param_1 : i32, param_2 : i32) -> vec2<i32>
 
-[[internal(intrinsic_atomic_store_storage_u32), internal(disable_validation__function_has_no_body)]]
-fn tint_symbol_11([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : SB, offset : u32, param_1 : u32)
+@internal(intrinsic_atomic_store_storage_u32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_11(@internal(disable_validation__ignore_constructible_function_parameter) buffer : SB, offset : u32, param_1 : u32)
 
-[[internal(intrinsic_atomic_load_storage_u32), internal(disable_validation__function_has_no_body)]]
-fn tint_symbol_12([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : SB, offset : u32) -> u32
+@internal(intrinsic_atomic_load_storage_u32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_12(@internal(disable_validation__ignore_constructible_function_parameter) buffer : SB, offset : u32) -> u32
 
-[[internal(intrinsic_atomic_add_storage_u32), internal(disable_validation__function_has_no_body)]]
-fn tint_symbol_13([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : SB, offset : u32, param_1 : u32) -> u32
+@internal(intrinsic_atomic_add_storage_u32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_13(@internal(disable_validation__ignore_constructible_function_parameter) buffer : SB, offset : u32, param_1 : u32) -> u32
 
-[[internal(intrinsic_atomic_sub_storage_u32), internal(disable_validation__function_has_no_body)]]
-fn tint_symbol_14([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : SB, offset : u32, param_1 : u32) -> u32
+@internal(intrinsic_atomic_sub_storage_u32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_14(@internal(disable_validation__ignore_constructible_function_parameter) buffer : SB, offset : u32, param_1 : u32) -> u32
 
-[[internal(intrinsic_atomic_max_storage_u32), internal(disable_validation__function_has_no_body)]]
-fn tint_symbol_15([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : SB, offset : u32, param_1 : u32) -> u32
+@internal(intrinsic_atomic_max_storage_u32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_15(@internal(disable_validation__ignore_constructible_function_parameter) buffer : SB, offset : u32, param_1 : u32) -> u32
 
-[[internal(intrinsic_atomic_min_storage_u32), internal(disable_validation__function_has_no_body)]]
-fn tint_symbol_16([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : SB, offset : u32, param_1 : u32) -> u32
+@internal(intrinsic_atomic_min_storage_u32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_16(@internal(disable_validation__ignore_constructible_function_parameter) buffer : SB, offset : u32, param_1 : u32) -> u32
 
-[[internal(intrinsic_atomic_and_storage_u32), internal(disable_validation__function_has_no_body)]]
-fn tint_symbol_17([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : SB, offset : u32, param_1 : u32) -> u32
+@internal(intrinsic_atomic_and_storage_u32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_17(@internal(disable_validation__ignore_constructible_function_parameter) buffer : SB, offset : u32, param_1 : u32) -> u32
 
-[[internal(intrinsic_atomic_or_storage_u32), internal(disable_validation__function_has_no_body)]]
-fn tint_symbol_18([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : SB, offset : u32, param_1 : u32) -> u32
+@internal(intrinsic_atomic_or_storage_u32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_18(@internal(disable_validation__ignore_constructible_function_parameter) buffer : SB, offset : u32, param_1 : u32) -> u32
 
-[[internal(intrinsic_atomic_xor_storage_u32), internal(disable_validation__function_has_no_body)]]
-fn tint_symbol_19([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : SB, offset : u32, param_1 : u32) -> u32
+@internal(intrinsic_atomic_xor_storage_u32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_19(@internal(disable_validation__ignore_constructible_function_parameter) buffer : SB, offset : u32, param_1 : u32) -> u32
 
-[[internal(intrinsic_atomic_exchange_storage_u32), internal(disable_validation__function_has_no_body)]]
-fn tint_symbol_20([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : SB, offset : u32, param_1 : u32) -> u32
+@internal(intrinsic_atomic_exchange_storage_u32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_20(@internal(disable_validation__ignore_constructible_function_parameter) buffer : SB, offset : u32, param_1 : u32) -> u32
 
-[[internal(intrinsic_atomic_compare_exchange_weak_storage_u32), internal(disable_validation__function_has_no_body)]]
-fn tint_symbol_21([[internal(disable_validation__ignore_constructible_function_parameter)]] buffer : SB, offset : u32, param_1 : u32, param_2 : u32) -> vec2<u32>
+@internal(intrinsic_atomic_compare_exchange_weak_storage_u32) @internal(disable_validation__function_has_no_body)
+fn tint_symbol_21(@internal(disable_validation__ignore_constructible_function_parameter) buffer : SB, offset : u32, param_1 : u32, param_2 : u32) -> vec2<u32>
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn main() {
   tint_symbol(sb, 16u, 123);
   tint_symbol_1(sb, 16u);
@@ -1360,7 +1360,7 @@
 
 var<workgroup> w : S;
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn main() {
   atomicStore(&(w.a), 123);
   atomicLoad(&(w.a));
diff --git a/src/transform/decompose_strided_matrix_test.cc b/src/transform/decompose_strided_matrix_test.cc
index db31c62..8561ccf 100644
--- a/src/transform/decompose_strided_matrix_test.cc
+++ b/src/transform/decompose_strided_matrix_test.cc
@@ -52,13 +52,13 @@
 
 TEST_F(DecomposeStridedMatrixTest, ReadUniformMatrix) {
   // struct S {
-  //   [[offset(16), stride(32)]]
-  //   [[internal(ignore_stride_decoration)]]
+  //   @offset(16) @stride(32)
+  //   @internal(ignore_stride_decoration)
   //   m : mat2x2<f32>;
   // };
-  // [[group(0), binding(0)]] var<uniform> s : S;
+  // @group(0) @binding(0) var<uniform> s : S;
   //
-  // [[stage(compute), workgroup_size(1)]]
+  // @stage(compute) @workgroup_size(1)
   // fn f() {
   //   let x : mat2x2<f32> = s.m;
   // }
@@ -88,18 +88,18 @@
 
   auto* expect = R"(
 struct S {
-  [[size(16)]]
+  @size(16)
   padding : u32;
-  m : [[stride(32)]] array<vec2<f32>, 2u>;
+  m : @stride(32) array<vec2<f32>, 2u>;
 }
 
-[[group(0), binding(0)]] var<uniform> s : S;
+@group(0) @binding(0) var<uniform> s : S;
 
-fn arr_to_mat2x2_stride_32(arr : [[stride(32)]] array<vec2<f32>, 2u>) -> mat2x2<f32> {
+fn arr_to_mat2x2_stride_32(arr : @stride(32) array<vec2<f32>, 2u>) -> mat2x2<f32> {
   return mat2x2<f32>(arr[0u], arr[1u]);
 }
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn f() {
   let x : mat2x2<f32> = arr_to_mat2x2_stride_32(s.m);
 }
@@ -113,13 +113,13 @@
 
 TEST_F(DecomposeStridedMatrixTest, ReadUniformColumn) {
   // struct S {
-  //   [[offset(16), stride(32)]]
-  //   [[internal(ignore_stride_decoration)]]
+  //   @offset(16) @stride(32)
+  //   @internal(ignore_stride_decoration)
   //   m : mat2x2<f32>;
   // };
-  // [[group(0), binding(0)]] var<uniform> s : S;
+  // @group(0) @binding(0) var<uniform> s : S;
   //
-  // [[stage(compute), workgroup_size(1)]]
+  // @stage(compute) @workgroup_size(1)
   // fn f() {
   //   let x : vec2<f32> = s.m[1];
   // }
@@ -149,14 +149,14 @@
 
   auto* expect = R"(
 struct S {
-  [[size(16)]]
+  @size(16)
   padding : u32;
-  m : [[stride(32)]] array<vec2<f32>, 2u>;
+  m : @stride(32) array<vec2<f32>, 2u>;
 }
 
-[[group(0), binding(0)]] var<uniform> s : S;
+@group(0) @binding(0) var<uniform> s : S;
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn f() {
   let x : vec2<f32> = s.m[1];
 }
@@ -170,13 +170,13 @@
 
 TEST_F(DecomposeStridedMatrixTest, ReadUniformMatrix_DefaultStride) {
   // struct S {
-  //   [[offset(16), stride(8)]]
-  //   [[internal(ignore_stride_decoration)]]
+  //   @offset(16) @stride(8)
+  //   @internal(ignore_stride_decoration)
   //   m : mat2x2<f32>;
   // };
-  // [[group(0), binding(0)]] var<uniform> s : S;
+  // @group(0) @binding(0) var<uniform> s : S;
   //
-  // [[stage(compute), workgroup_size(1)]]
+  // @stage(compute) @workgroup_size(1)
   // fn f() {
   //   let x : mat2x2<f32> = s.m;
   // }
@@ -206,15 +206,15 @@
 
   auto* expect = R"(
 struct S {
-  [[size(16)]]
+  @size(16)
   padding : u32;
-  [[stride(8), internal(disable_validation__ignore_stride)]]
+  @stride(8) @internal(disable_validation__ignore_stride)
   m : mat2x2<f32>;
 }
 
-[[group(0), binding(0)]] var<uniform> s : S;
+@group(0) @binding(0) var<uniform> s : S;
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn f() {
   let x : mat2x2<f32> = s.m;
 }
@@ -228,13 +228,13 @@
 
 TEST_F(DecomposeStridedMatrixTest, ReadStorageMatrix) {
   // struct S {
-  //   [[offset(8), stride(32)]]
-  //   [[internal(ignore_stride_decoration)]]
+  //   @offset(8) @stride(32)
+  //   @internal(ignore_stride_decoration)
   //   m : mat2x2<f32>;
   // };
-  // [[group(0), binding(0)]] var<storage, read_write> s : S;
+  // @group(0) @binding(0) var<storage, read_write> s : S;
   //
-  // [[stage(compute), workgroup_size(1)]]
+  // @stage(compute) @workgroup_size(1)
   // fn f() {
   //   let x : mat2x2<f32> = s.m;
   // }
@@ -264,18 +264,18 @@
 
   auto* expect = R"(
 struct S {
-  [[size(8)]]
+  @size(8)
   padding : u32;
-  m : [[stride(32)]] array<vec2<f32>, 2u>;
+  m : @stride(32) array<vec2<f32>, 2u>;
 }
 
-[[group(0), binding(0)]] var<storage, read_write> s : S;
+@group(0) @binding(0) var<storage, read_write> s : S;
 
-fn arr_to_mat2x2_stride_32(arr : [[stride(32)]] array<vec2<f32>, 2u>) -> mat2x2<f32> {
+fn arr_to_mat2x2_stride_32(arr : @stride(32) array<vec2<f32>, 2u>) -> mat2x2<f32> {
   return mat2x2<f32>(arr[0u], arr[1u]);
 }
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn f() {
   let x : mat2x2<f32> = arr_to_mat2x2_stride_32(s.m);
 }
@@ -289,13 +289,13 @@
 
 TEST_F(DecomposeStridedMatrixTest, ReadStorageColumn) {
   // struct S {
-  //   [[offset(16), stride(32)]]
-  //   [[internal(ignore_stride_decoration)]]
+  //   @offset(16) @stride(32)
+  //   @internal(ignore_stride_decoration)
   //   m : mat2x2<f32>;
   // };
-  // [[group(0), binding(0)]] var<storage, read_write> s : S;
+  // @group(0) @binding(0) var<storage, read_write> s : S;
   //
-  // [[stage(compute), workgroup_size(1)]]
+  // @stage(compute) @workgroup_size(1)
   // fn f() {
   //   let x : vec2<f32> = s.m[1];
   // }
@@ -325,14 +325,14 @@
 
   auto* expect = R"(
 struct S {
-  [[size(16)]]
+  @size(16)
   padding : u32;
-  m : [[stride(32)]] array<vec2<f32>, 2u>;
+  m : @stride(32) array<vec2<f32>, 2u>;
 }
 
-[[group(0), binding(0)]] var<storage, read_write> s : S;
+@group(0) @binding(0) var<storage, read_write> s : S;
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn f() {
   let x : vec2<f32> = s.m[1];
 }
@@ -346,13 +346,13 @@
 
 TEST_F(DecomposeStridedMatrixTest, WriteStorageMatrix) {
   // struct S {
-  //   [[offset(8), stride(32)]]
-  //   [[internal(ignore_stride_decoration)]]
+  //   @offset(8) @stride(32)
+  //   @internal(ignore_stride_decoration)
   //   m : mat2x2<f32>;
   // };
-  // [[group(0), binding(0)]] var<storage, read_write> s : S;
+  // @group(0) @binding(0) var<storage, read_write> s : S;
   //
-  // [[stage(compute), workgroup_size(1)]]
+  // @stage(compute) @workgroup_size(1)
   // fn f() {
   //   s.m = mat2x2<f32>(vec2<f32>(1.0, 2.0), vec2<f32>(3.0, 4.0));
   // }
@@ -383,18 +383,18 @@
 
   auto* expect = R"(
 struct S {
-  [[size(8)]]
+  @size(8)
   padding : u32;
-  m : [[stride(32)]] array<vec2<f32>, 2u>;
+  m : @stride(32) array<vec2<f32>, 2u>;
 }
 
-[[group(0), binding(0)]] var<storage, read_write> s : S;
+@group(0) @binding(0) var<storage, read_write> s : S;
 
-fn mat2x2_stride_32_to_arr(mat : mat2x2<f32>) -> [[stride(32)]] array<vec2<f32>, 2u> {
-  return [[stride(32)]] array<vec2<f32>, 2u>(mat[0u], mat[1u]);
+fn mat2x2_stride_32_to_arr(mat : mat2x2<f32>) -> @stride(32) array<vec2<f32>, 2u> {
+  return @stride(32) array<vec2<f32>, 2u>(mat[0u], mat[1u]);
 }
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn f() {
   s.m = mat2x2_stride_32_to_arr(mat2x2<f32>(vec2<f32>(1.0, 2.0), vec2<f32>(3.0, 4.0)));
 }
@@ -408,13 +408,13 @@
 
 TEST_F(DecomposeStridedMatrixTest, WriteStorageColumn) {
   // struct S {
-  //   [[offset(8), stride(32)]]
-  //   [[internal(ignore_stride_decoration)]]
+  //   @offset(8) @stride(32)
+  //   @internal(ignore_stride_decoration)
   //   m : mat2x2<f32>;
   // };
-  // [[group(0), binding(0)]] var<storage, read_write> s : S;
+  // @group(0) @binding(0) var<storage, read_write> s : S;
   //
-  // [[stage(compute), workgroup_size(1)]]
+  // @stage(compute) @workgroup_size(1)
   // fn f() {
   //   s.m[1] = vec2<f32>(1.0, 2.0);
   // }
@@ -444,14 +444,14 @@
 
   auto* expect = R"(
 struct S {
-  [[size(8)]]
+  @size(8)
   padding : u32;
-  m : [[stride(32)]] array<vec2<f32>, 2u>;
+  m : @stride(32) array<vec2<f32>, 2u>;
 }
 
-[[group(0), binding(0)]] var<storage, read_write> s : S;
+@group(0) @binding(0) var<storage, read_write> s : S;
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn f() {
   s.m[1] = vec2<f32>(1.0, 2.0);
 }
@@ -465,13 +465,13 @@
 
 TEST_F(DecomposeStridedMatrixTest, ReadWriteViaPointerLets) {
   // struct S {
-  //   [[offset(8), stride(32)]]
-  //   [[internal(ignore_stride_decoration)]]
+  //   @offset(8) @stride(32)
+  //   @internal(ignore_stride_decoration)
   //   m : mat2x2<f32>;
   // };
-  // [[group(0), binding(0)]] var<storage, read_write> s : S;
+  // @group(0) @binding(0) var<storage, read_write> s : S;
   //
-  // [[stage(compute), workgroup_size(1)]]
+  // @stage(compute) @workgroup_size(1)
   // fn f() {
   //   let a = &s.m;
   //   let b = &*&*(a);
@@ -516,22 +516,22 @@
 
   auto* expect = R"(
 struct S {
-  [[size(8)]]
+  @size(8)
   padding : u32;
-  m : [[stride(32)]] array<vec2<f32>, 2u>;
+  m : @stride(32) array<vec2<f32>, 2u>;
 }
 
-[[group(0), binding(0)]] var<storage, read_write> s : S;
+@group(0) @binding(0) var<storage, read_write> s : S;
 
-fn arr_to_mat2x2_stride_32(arr : [[stride(32)]] array<vec2<f32>, 2u>) -> mat2x2<f32> {
+fn arr_to_mat2x2_stride_32(arr : @stride(32) array<vec2<f32>, 2u>) -> mat2x2<f32> {
   return mat2x2<f32>(arr[0u], arr[1u]);
 }
 
-fn mat2x2_stride_32_to_arr(mat : mat2x2<f32>) -> [[stride(32)]] array<vec2<f32>, 2u> {
-  return [[stride(32)]] array<vec2<f32>, 2u>(mat[0u], mat[1u]);
+fn mat2x2_stride_32_to_arr(mat : mat2x2<f32>) -> @stride(32) array<vec2<f32>, 2u> {
+  return @stride(32) array<vec2<f32>, 2u>(mat[0u], mat[1u]);
 }
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn f() {
   let x = arr_to_mat2x2_stride_32(s.m);
   let y = s.m[1];
@@ -549,13 +549,13 @@
 
 TEST_F(DecomposeStridedMatrixTest, ReadPrivateMatrix) {
   // struct S {
-  //   [[offset(8), stride(32)]]
-  //   [[internal(ignore_stride_decoration)]]
+  //   @offset(8) @stride(32)
+  //   @internal(ignore_stride_decoration)
   //   m : mat2x2<f32>;
   // };
   // var<private> s : S;
   //
-  // [[stage(compute), workgroup_size(1)]]
+  // @stage(compute) @workgroup_size(1)
   // fn f() {
   //   let x : mat2x2<f32> = s.m;
   // }
@@ -584,15 +584,15 @@
 
   auto* expect = R"(
 struct S {
-  [[size(8)]]
+  @size(8)
   padding : u32;
-  [[stride(32), internal(disable_validation__ignore_stride)]]
+  @stride(32) @internal(disable_validation__ignore_stride)
   m : mat2x2<f32>;
 }
 
 var<private> s : S;
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn f() {
   let x : mat2x2<f32> = s.m;
 }
@@ -606,13 +606,13 @@
 
 TEST_F(DecomposeStridedMatrixTest, WritePrivateMatrix) {
   // struct S {
-  //   [[offset(8), stride(32)]]
-  //   [[internal(ignore_stride_decoration)]]
+  //   @offset(8) @stride(32)
+  //   @internal(ignore_stride_decoration)
   //   m : mat2x2<f32>;
   // };
   // var<private> s : S;
   //
-  // [[stage(compute), workgroup_size(1)]]
+  // @stage(compute) @workgroup_size(1)
   // fn f() {
   //   s.m = mat2x2<f32>(vec2<f32>(1.0, 2.0), vec2<f32>(3.0, 4.0));
   // }
@@ -642,15 +642,15 @@
 
   auto* expect = R"(
 struct S {
-  [[size(8)]]
+  @size(8)
   padding : u32;
-  [[stride(32), internal(disable_validation__ignore_stride)]]
+  @stride(32) @internal(disable_validation__ignore_stride)
   m : mat2x2<f32>;
 }
 
 var<private> s : S;
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn f() {
   s.m = mat2x2<f32>(vec2<f32>(1.0, 2.0), vec2<f32>(3.0, 4.0));
 }
diff --git a/src/transform/external_texture_transform_test.cc b/src/transform/external_texture_transform_test.cc
index d9fef8f..28baadf 100644
--- a/src/transform/external_texture_transform_test.cc
+++ b/src/transform/external_texture_transform_test.cc
@@ -24,23 +24,23 @@
 
 TEST_F(ExternalTextureTransformTest, SampleLevelSinglePlane) {
   auto* src = R"(
-[[group(0), binding(0)]] var s : sampler;
+@group(0) @binding(0) var s : sampler;
 
-[[group(0), binding(1)]] var t : texture_external;
+@group(0) @binding(1) var t : texture_external;
 
-[[stage(fragment)]]
-fn main([[builtin(position)]] coord : vec4<f32>) -> [[location(0)]] vec4<f32> {
+@stage(fragment)
+fn main(@builtin(position) coord : vec4<f32>) -> @location(0) vec4<f32> {
   return textureSampleLevel(t, s, (coord.xy / vec2<f32>(4.0, 4.0)));
 }
 )";
 
   auto* expect = R"(
-[[group(0), binding(0)]] var s : sampler;
+@group(0) @binding(0) var s : sampler;
 
-[[group(0), binding(1)]] var t : texture_2d<f32>;
+@group(0) @binding(1) var t : texture_2d<f32>;
 
-[[stage(fragment)]]
-fn main([[builtin(position)]] coord : vec4<f32>) -> [[location(0)]] vec4<f32> {
+@stage(fragment)
+fn main(@builtin(position) coord : vec4<f32>) -> @location(0) vec4<f32> {
   return textureSampleLevel(t, s, (coord.xy / vec2<f32>(4.0, 4.0)), 0.0);
 }
 )";
@@ -52,19 +52,19 @@
 
 TEST_F(ExternalTextureTransformTest, LoadSinglePlane) {
   auto* src = R"(
-[[group(0), binding(0)]] var t : texture_external;
+@group(0) @binding(0) var t : texture_external;
 
-[[stage(fragment)]]
-fn main([[builtin(position)]] coord : vec4<f32>) -> [[location(0)]] vec4<f32> {
+@stage(fragment)
+fn main(@builtin(position) coord : vec4<f32>) -> @location(0) vec4<f32> {
   return textureLoad(t, vec2<i32>(1, 1));
 }
 )";
 
   auto* expect = R"(
-[[group(0), binding(0)]] var t : texture_2d<f32>;
+@group(0) @binding(0) var t : texture_2d<f32>;
 
-[[stage(fragment)]]
-fn main([[builtin(position)]] coord : vec4<f32>) -> [[location(0)]] vec4<f32> {
+@stage(fragment)
+fn main(@builtin(position) coord : vec4<f32>) -> @location(0) vec4<f32> {
   return textureLoad(t, vec2<i32>(1, 1), 0);
 }
 )";
@@ -76,10 +76,10 @@
 
 TEST_F(ExternalTextureTransformTest, DimensionsSinglePlane) {
   auto* src = R"(
-[[group(0), binding(0)]] var t : texture_external;
+@group(0) @binding(0) var t : texture_external;
 
-[[stage(fragment)]]
-fn main([[builtin(position)]] coord : vec4<f32>) -> [[location(0)]] vec4<f32> {
+@stage(fragment)
+fn main(@builtin(position) coord : vec4<f32>) -> @location(0) vec4<f32> {
   var dim : vec2<i32>;
   dim = textureDimensions(t);
   return vec4<f32>(0.0, 0.0, 0.0, 0.0);
@@ -87,10 +87,10 @@
 )";
 
   auto* expect = R"(
-[[group(0), binding(0)]] var t : texture_2d<f32>;
+@group(0) @binding(0) var t : texture_2d<f32>;
 
-[[stage(fragment)]]
-fn main([[builtin(position)]] coord : vec4<f32>) -> [[location(0)]] vec4<f32> {
+@stage(fragment)
+fn main(@builtin(position) coord : vec4<f32>) -> @location(0) vec4<f32> {
   var dim : vec2<i32>;
   dim = textureDimensions(t);
   return vec4<f32>(0.0, 0.0, 0.0, 0.0);
diff --git a/src/transform/first_index_offset.h b/src/transform/first_index_offset.h
index ffbb138..a885581 100644
--- a/src/transform/first_index_offset.h
+++ b/src/transform/first_index_offset.h
@@ -35,24 +35,28 @@
 /// Therefore, these values must by passed to the shader.
 ///
 /// Before:
-///   [[builtin(vertex_index)]] var<in> vert_idx : u32;
+/// ```
+///   @builtin(vertex_index) var<in> vert_idx : u32;
 ///   fn func() -> u32 {
 ///     return vert_idx;
 ///   }
+/// ```
 ///
 /// After:
+/// ```
 ///   struct TintFirstIndexOffsetData {
 ///     tint_first_vertex_index : u32;
 ///     tint_first_instance_index : u32;
 ///   };
-///   [[builtin(vertex_index)]] var<in> tint_first_index_offset_vert_idx : u32;
-///   [[binding(N), group(M)]] var<uniform> tint_first_index_data :
+///   @builtin(vertex_index) var<in> tint_first_index_offset_vert_idx : u32;
+///   @binding(N) @group(M) var<uniform> tint_first_index_data :
 ///                                                    TintFirstIndexOffsetData;
 ///   fn func() -> u32 {
 ///     const vert_idx = (tint_first_index_offset_vert_idx +
 ///                       tint_first_index_data.tint_first_vertex_index);
 ///     return vert_idx;
 ///   }
+/// ```
 ///
 class FirstIndexOffset : public Castable<FirstIndexOffset, Transform> {
  public:
@@ -71,9 +75,9 @@
     /// Destructor
     ~BindingPoint() override;
 
-    /// [[binding()]] for the first vertex / first instance uniform buffer
+    /// `@binding()` for the first vertex / first instance uniform buffer
     uint32_t binding = 0;
-    /// [[group()]] for the first vertex / first instance uniform buffer
+    /// `@group()` for the first vertex / first instance uniform buffer
     uint32_t group = 0;
   };
 
diff --git a/src/transform/first_index_offset_test.cc b/src/transform/first_index_offset_test.cc
index 6368d29..c0c95f6 100644
--- a/src/transform/first_index_offset_test.cc
+++ b/src/transform/first_index_offset_test.cc
@@ -51,8 +51,8 @@
   return vert_idx;
 }
 
-[[stage(vertex)]]
-fn entry([[builtin(vertex_index)]] vert_idx : u32) -> [[builtin(position)]] vec4<f32> {
+@stage(vertex)
+fn entry(@builtin(vertex_index) vert_idx : u32) -> @builtin(position) vec4<f32> {
   test(vert_idx);
   return vec4<f32>();
 }
@@ -63,14 +63,14 @@
   first_vertex_index : u32;
 }
 
-[[binding(1), group(2)]] var<uniform> tint_symbol_1 : tint_symbol;
+@binding(1) @group(2) var<uniform> tint_symbol_1 : tint_symbol;
 
 fn test(vert_idx : u32) -> u32 {
   return vert_idx;
 }
 
-[[stage(vertex)]]
-fn entry([[builtin(vertex_index)]] vert_idx : u32) -> [[builtin(position)]] vec4<f32> {
+@stage(vertex)
+fn entry(@builtin(vertex_index) vert_idx : u32) -> @builtin(position) vec4<f32> {
   test((vert_idx + tint_symbol_1.first_vertex_index));
   return vec4<f32>();
 }
@@ -97,8 +97,8 @@
   return inst_idx;
 }
 
-[[stage(vertex)]]
-fn entry([[builtin(instance_index)]] inst_idx : u32) -> [[builtin(position)]] vec4<f32> {
+@stage(vertex)
+fn entry(@builtin(instance_index) inst_idx : u32) -> @builtin(position) vec4<f32> {
   test(inst_idx);
   return vec4<f32>();
 }
@@ -109,14 +109,14 @@
   first_instance_index : u32;
 }
 
-[[binding(1), group(7)]] var<uniform> tint_symbol_1 : tint_symbol;
+@binding(1) @group(7) var<uniform> tint_symbol_1 : tint_symbol;
 
 fn test(inst_idx : u32) -> u32 {
   return inst_idx;
 }
 
-[[stage(vertex)]]
-fn entry([[builtin(instance_index)]] inst_idx : u32) -> [[builtin(position)]] vec4<f32> {
+@stage(vertex)
+fn entry(@builtin(instance_index) inst_idx : u32) -> @builtin(position) vec4<f32> {
   test((inst_idx + tint_symbol_1.first_instance_index));
   return vec4<f32>();
 }
@@ -144,12 +144,12 @@
 }
 
 struct Inputs {
-  [[builtin(instance_index)]] instance_idx : u32;
-  [[builtin(vertex_index)]] vert_idx : u32;
+  @builtin(instance_index) instance_idx : u32;
+  @builtin(vertex_index) vert_idx : u32;
 };
 
-[[stage(vertex)]]
-fn entry(inputs : Inputs) -> [[builtin(position)]] vec4<f32> {
+@stage(vertex)
+fn entry(inputs : Inputs) -> @builtin(position) vec4<f32> {
   test(inputs.instance_idx, inputs.vert_idx);
   return vec4<f32>();
 }
@@ -161,21 +161,21 @@
   first_instance_index : u32;
 }
 
-[[binding(1), group(2)]] var<uniform> tint_symbol_1 : tint_symbol;
+@binding(1) @group(2) var<uniform> tint_symbol_1 : tint_symbol;
 
 fn test(instance_idx : u32, vert_idx : u32) -> u32 {
   return (instance_idx + vert_idx);
 }
 
 struct Inputs {
-  [[builtin(instance_index)]]
+  @builtin(instance_index)
   instance_idx : u32;
-  [[builtin(vertex_index)]]
+  @builtin(vertex_index)
   vert_idx : u32;
 }
 
-[[stage(vertex)]]
-fn entry(inputs : Inputs) -> [[builtin(position)]] vec4<f32> {
+@stage(vertex)
+fn entry(inputs : Inputs) -> @builtin(position) vec4<f32> {
   test((inputs.instance_idx + tint_symbol_1.first_instance_index), (inputs.vert_idx + tint_symbol_1.first_vertex_index));
   return vec4<f32>();
 }
@@ -206,8 +206,8 @@
   return func1(vert_idx);
 }
 
-[[stage(vertex)]]
-fn entry([[builtin(vertex_index)]] vert_idx : u32) -> [[builtin(position)]] vec4<f32> {
+@stage(vertex)
+fn entry(@builtin(vertex_index) vert_idx : u32) -> @builtin(position) vec4<f32> {
   func2(vert_idx);
   return vec4<f32>();
 }
@@ -218,7 +218,7 @@
   first_vertex_index : u32;
 }
 
-[[binding(1), group(2)]] var<uniform> tint_symbol_1 : tint_symbol;
+@binding(1) @group(2) var<uniform> tint_symbol_1 : tint_symbol;
 
 fn func1(vert_idx : u32) -> u32 {
   return vert_idx;
@@ -228,8 +228,8 @@
   return func1(vert_idx);
 }
 
-[[stage(vertex)]]
-fn entry([[builtin(vertex_index)]] vert_idx : u32) -> [[builtin(position)]] vec4<f32> {
+@stage(vertex)
+fn entry(@builtin(vertex_index) vert_idx : u32) -> @builtin(position) vec4<f32> {
   func2((vert_idx + tint_symbol_1.first_vertex_index));
   return vec4<f32>();
 }
@@ -256,20 +256,20 @@
   return i;
 }
 
-[[stage(vertex)]]
-fn entry_a([[builtin(vertex_index)]] vert_idx : u32) -> [[builtin(position)]] vec4<f32> {
+@stage(vertex)
+fn entry_a(@builtin(vertex_index) vert_idx : u32) -> @builtin(position) vec4<f32> {
   func(vert_idx);
   return vec4<f32>();
 }
 
-[[stage(vertex)]]
-fn entry_b([[builtin(vertex_index)]] vert_idx : u32, [[builtin(instance_index)]] inst_idx : u32) -> [[builtin(position)]] vec4<f32> {
+@stage(vertex)
+fn entry_b(@builtin(vertex_index) vert_idx : u32, @builtin(instance_index) inst_idx : u32) -> @builtin(position) vec4<f32> {
   func(vert_idx + inst_idx);
   return vec4<f32>();
 }
 
-[[stage(vertex)]]
-fn entry_c([[builtin(instance_index)]] inst_idx : u32) -> [[builtin(position)]] vec4<f32> {
+@stage(vertex)
+fn entry_c(@builtin(instance_index) inst_idx : u32) -> @builtin(position) vec4<f32> {
   func(inst_idx);
   return vec4<f32>();
 }
@@ -281,26 +281,26 @@
   first_instance_index : u32;
 }
 
-[[binding(1), group(2)]] var<uniform> tint_symbol_1 : tint_symbol;
+@binding(1) @group(2) var<uniform> tint_symbol_1 : tint_symbol;
 
 fn func(i : u32) -> u32 {
   return i;
 }
 
-[[stage(vertex)]]
-fn entry_a([[builtin(vertex_index)]] vert_idx : u32) -> [[builtin(position)]] vec4<f32> {
+@stage(vertex)
+fn entry_a(@builtin(vertex_index) vert_idx : u32) -> @builtin(position) vec4<f32> {
   func((vert_idx + tint_symbol_1.first_vertex_index));
   return vec4<f32>();
 }
 
-[[stage(vertex)]]
-fn entry_b([[builtin(vertex_index)]] vert_idx : u32, [[builtin(instance_index)]] inst_idx : u32) -> [[builtin(position)]] vec4<f32> {
+@stage(vertex)
+fn entry_b(@builtin(vertex_index) vert_idx : u32, @builtin(instance_index) inst_idx : u32) -> @builtin(position) vec4<f32> {
   func(((vert_idx + tint_symbol_1.first_vertex_index) + (inst_idx + tint_symbol_1.first_instance_index)));
   return vec4<f32>();
 }
 
-[[stage(vertex)]]
-fn entry_c([[builtin(instance_index)]] inst_idx : u32) -> [[builtin(position)]] vec4<f32> {
+@stage(vertex)
+fn entry_c(@builtin(instance_index) inst_idx : u32) -> @builtin(position) vec4<f32> {
   func((inst_idx + tint_symbol_1.first_instance_index));
   return vec4<f32>();
 }
diff --git a/src/transform/glsl_test.cc b/src/transform/glsl_test.cc
index b280e33..49b0dfd 100644
--- a/src/transform/glsl_test.cc
+++ b/src/transform/glsl_test.cc
@@ -26,7 +26,7 @@
   auto* src = R"()";
 
   auto* expect = R"(
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn unused_entry_point() {
 }
 )";
diff --git a/src/transform/localize_struct_array_assignment_test.cc b/src/transform/localize_struct_array_assignment_test.cc
index 2b3b0c9..878a89c 100644
--- a/src/transform/localize_struct_array_assignment_test.cc
+++ b/src/transform/localize_struct_array_assignment_test.cc
@@ -44,7 +44,7 @@
 
 TEST_F(LocalizeStructArrayAssignmentTest, StructArray) {
   auto* src = R"(
-[[block]] struct Uniforms {
+@block struct Uniforms {
   i : u32;
 };
 
@@ -56,9 +56,9 @@
   a1 : array<InnerS, 8>;
 };
 
-[[group(1), binding(4)]] var<uniform> uniforms : Uniforms;
+@group(1) @binding(4) var<uniform> uniforms : Uniforms;
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn main() {
   var v : InnerS;
   var s1 : OuterS;
@@ -67,7 +67,7 @@
 )";
 
   auto* expect = R"(
-[[block]]
+@block
 struct Uniforms {
   i : u32;
 }
@@ -80,9 +80,9 @@
   a1 : array<InnerS, 8>;
 }
 
-[[group(1), binding(4)]] var<uniform> uniforms : Uniforms;
+@group(1) @binding(4) var<uniform> uniforms : Uniforms;
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn main() {
   var v : InnerS;
   var s1 : OuterS;
@@ -102,7 +102,7 @@
 
 TEST_F(LocalizeStructArrayAssignmentTest, StructStructArray) {
   auto* src = R"(
-[[block]] struct Uniforms {
+@block struct Uniforms {
   i : u32;
 };
 
@@ -118,9 +118,9 @@
   s2 : S1;
 };
 
-[[group(1), binding(4)]] var<uniform> uniforms : Uniforms;
+@group(1) @binding(4) var<uniform> uniforms : Uniforms;
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn main() {
   var v : InnerS;
   var s1 : OuterS;
@@ -129,7 +129,7 @@
 )";
 
   auto* expect = R"(
-[[block]]
+@block
 struct Uniforms {
   i : u32;
 }
@@ -146,9 +146,9 @@
   s2 : S1;
 }
 
-[[group(1), binding(4)]] var<uniform> uniforms : Uniforms;
+@group(1) @binding(4) var<uniform> uniforms : Uniforms;
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn main() {
   var v : InnerS;
   var s1 : OuterS;
@@ -168,7 +168,7 @@
 
 TEST_F(LocalizeStructArrayAssignmentTest, StructArrayArray) {
   auto* src = R"(
-[[block]] struct Uniforms {
+@block struct Uniforms {
   i : u32;
   j : u32;
 };
@@ -181,9 +181,9 @@
   a1 : array<array<InnerS, 8>, 8>;
 };
 
-[[group(1), binding(4)]] var<uniform> uniforms : Uniforms;
+@group(1) @binding(4) var<uniform> uniforms : Uniforms;
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn main() {
   var v : InnerS;
   var s1 : OuterS;
@@ -192,7 +192,7 @@
 )";
 
   auto* expect = R"(
-[[block]]
+@block
 struct Uniforms {
   i : u32;
   j : u32;
@@ -206,9 +206,9 @@
   a1 : array<array<InnerS, 8>, 8>;
 }
 
-[[group(1), binding(4)]] var<uniform> uniforms : Uniforms;
+@group(1) @binding(4) var<uniform> uniforms : Uniforms;
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn main() {
   var v : InnerS;
   var s1 : OuterS;
@@ -228,7 +228,7 @@
 
 TEST_F(LocalizeStructArrayAssignmentTest, StructArrayStruct) {
   auto* src = R"(
-[[block]] struct Uniforms {
+@block struct Uniforms {
   i : u32;
 };
 
@@ -244,9 +244,9 @@
   a1 : array<S1, 8>;
 };
 
-[[group(1), binding(4)]] var<uniform> uniforms : Uniforms;
+@group(1) @binding(4) var<uniform> uniforms : Uniforms;
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn main() {
   var v : InnerS;
   var s1 : OuterS;
@@ -255,7 +255,7 @@
 )";
 
   auto* expect = R"(
-[[block]]
+@block
 struct Uniforms {
   i : u32;
 }
@@ -272,9 +272,9 @@
   a1 : array<S1, 8>;
 }
 
-[[group(1), binding(4)]] var<uniform> uniforms : Uniforms;
+@group(1) @binding(4) var<uniform> uniforms : Uniforms;
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn main() {
   var v : InnerS;
   var s1 : OuterS;
@@ -294,7 +294,7 @@
 
 TEST_F(LocalizeStructArrayAssignmentTest, StructArrayStructArray) {
   auto* src = R"(
-[[block]] struct Uniforms {
+@block struct Uniforms {
   i : u32;
   j : u32;
 };
@@ -311,9 +311,9 @@
   a1 : array<S1, 8>;
 };
 
-[[group(1), binding(4)]] var<uniform> uniforms : Uniforms;
+@group(1) @binding(4) var<uniform> uniforms : Uniforms;
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn main() {
   var v : InnerS;
   var s : OuterS;
@@ -322,7 +322,7 @@
 )";
 
   auto* expect = R"(
-[[block]]
+@block
 struct Uniforms {
   i : u32;
   j : u32;
@@ -340,9 +340,9 @@
   a1 : array<S1, 8>;
 }
 
-[[group(1), binding(4)]] var<uniform> uniforms : Uniforms;
+@group(1) @binding(4) var<uniform> uniforms : Uniforms;
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn main() {
   var v : InnerS;
   var s : OuterS;
@@ -365,7 +365,7 @@
 
 TEST_F(LocalizeStructArrayAssignmentTest, IndexingWithSideEffectFunc) {
   auto* src = R"(
-[[block]] struct Uniforms {
+@block struct Uniforms {
   i : u32;
   j : u32;
 };
@@ -388,9 +388,9 @@
   return nextIndex;
 }
 
-[[group(1), binding(4)]] var<uniform> uniforms : Uniforms;
+@group(1) @binding(4) var<uniform> uniforms : Uniforms;
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn main() {
   var v : InnerS;
   var s : OuterS;
@@ -399,7 +399,7 @@
 )";
 
   auto* expect = R"(
-[[block]]
+@block
 struct Uniforms {
   i : u32;
   j : u32;
@@ -424,9 +424,9 @@
   return nextIndex;
 }
 
-[[group(1), binding(4)]] var<uniform> uniforms : Uniforms;
+@group(1) @binding(4) var<uniform> uniforms : Uniforms;
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn main() {
   var v : InnerS;
   var s : OuterS;
@@ -449,7 +449,7 @@
 
 TEST_F(LocalizeStructArrayAssignmentTest, ViaPointerArg) {
   auto* src = R"(
-[[block]] struct Uniforms {
+@block struct Uniforms {
   i : u32;
 };
 struct InnerS {
@@ -458,14 +458,14 @@
 struct OuterS {
   a1 : array<InnerS, 8>;
 };
-[[group(1), binding(4)]] var<uniform> uniforms : Uniforms;
+@group(1) @binding(4) var<uniform> uniforms : Uniforms;
 
 fn f(p : ptr<function, OuterS>) {
   var v : InnerS;
   (*p).a1[uniforms.i] = v;
 }
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn main() {
   var s1 : OuterS;
   f(&s1);
@@ -473,7 +473,7 @@
 )";
 
   auto* expect = R"(
-[[block]]
+@block
 struct Uniforms {
   i : u32;
 }
@@ -486,7 +486,7 @@
   a1 : array<InnerS, 8>;
 }
 
-[[group(1), binding(4)]] var<uniform> uniforms : Uniforms;
+@group(1) @binding(4) var<uniform> uniforms : Uniforms;
 
 fn f(p : ptr<function, OuterS>) {
   var v : InnerS;
@@ -498,7 +498,7 @@
   }
 }
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn main() {
   var s1 : OuterS;
   f(&(s1));
@@ -512,7 +512,7 @@
 
 TEST_F(LocalizeStructArrayAssignmentTest, ViaPointerVar) {
   auto* src = R"(
-[[block]]
+@block
 struct Uniforms {
   i : u32;
 };
@@ -525,13 +525,13 @@
   a1 : array<InnerS, 8>;
 };
 
-[[group(1), binding(4)]] var<uniform> uniforms : Uniforms;
+@group(1) @binding(4) var<uniform> uniforms : Uniforms;
 
 fn f(p : ptr<function, InnerS>, v : InnerS) {
   *(p) = v;
 }
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn main() {
   var v : InnerS;
   var s1 : OuterS;
@@ -541,7 +541,7 @@
 )";
 
   auto* expect = R"(
-[[block]]
+@block
 struct Uniforms {
   i : u32;
 }
@@ -554,13 +554,13 @@
   a1 : array<InnerS, 8>;
 }
 
-[[group(1), binding(4)]] var<uniform> uniforms : Uniforms;
+@group(1) @binding(4) var<uniform> uniforms : Uniforms;
 
 fn f(p : ptr<function, InnerS>, v : InnerS) {
   *(p) = v;
 }
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn main() {
   var v : InnerS;
   var s1 : OuterS;
@@ -581,23 +581,23 @@
 
 TEST_F(LocalizeStructArrayAssignmentTest, VectorAssignment) {
   auto* src = R"(
-[[block]]
+@block
 struct Uniforms {
   i : u32;
 }
 
-[[block]]
+@block
 struct OuterS {
   a1 : array<u32, 8>;
 }
 
-[[group(1), binding(4)]] var<uniform> uniforms : Uniforms;
+@group(1) @binding(4) var<uniform> uniforms : Uniforms;
 
 fn f(i : u32) -> u32 {
   return (i + 1u);
 }
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn main() {
   var s1 : OuterS;
   var v : vec3<f32>;
diff --git a/src/transform/module_scope_var_to_entry_point_param.h b/src/transform/module_scope_var_to_entry_point_param.h
index 34db3e6..29132c8 100644
--- a/src/transform/module_scope_var_to_entry_point_param.h
+++ b/src/transform/module_scope_var_to_entry_point_param.h
@@ -36,7 +36,7 @@
 /// struct S {
 ///   f : f32;
 /// };
-/// [[binding(0), group(0)]]
+/// @binding(0) @group(0)
 /// var<storage, read> s : S;
 /// var<private> p : f32 = 2.0;
 ///
@@ -44,7 +44,7 @@
 ///   p = p + f;
 /// }
 ///
-/// [[stage(compute), workgroup_size(1)]]
+/// @stage(compute) @workgroup_size(1)
 /// fn main() {
 ///   foo();
 /// }
@@ -56,7 +56,7 @@
 ///   *p = *p + (*sptr).f;
 /// }
 ///
-/// [[stage(compute), workgroup_size(1)]]
+/// @stage(compute) @workgroup_size(1)
 /// fn main(sptr : ptr<storage, S, read>) {
 ///   var<private> p : f32 = 2.0;
 ///   foo(&p, sptr);
diff --git a/src/transform/module_scope_var_to_entry_point_param_test.cc b/src/transform/module_scope_var_to_entry_point_param_test.cc
index ffbd635..d8b0f63 100644
--- a/src/transform/module_scope_var_to_entry_point_param_test.cc
+++ b/src/transform/module_scope_var_to_entry_point_param_test.cc
@@ -29,17 +29,17 @@
 var<private> p : f32;
 var<workgroup> w : f32;
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn main() {
   w = p;
 }
 )";
 
   auto* expect = R"(
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn main() {
-  [[internal(disable_validation__ignore_storage_class)]] var<workgroup> tint_symbol : f32;
-  [[internal(disable_validation__ignore_storage_class)]] var<private> tint_symbol_1 : f32;
+  @internal(disable_validation__ignore_storage_class) var<workgroup> tint_symbol : f32;
+  @internal(disable_validation__ignore_storage_class) var<private> tint_symbol_1 : f32;
   tint_symbol = tint_symbol_1;
 }
 )";
@@ -68,7 +68,7 @@
   no_uses();
 }
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn main() {
   foo(1.0);
 }
@@ -78,21 +78,21 @@
 fn no_uses() {
 }
 
-fn bar(a : f32, b : f32, [[internal(disable_validation__ignore_storage_class), internal(disable_validation__ignore_invalid_pointer_argument)]] tint_symbol : ptr<private, f32>, [[internal(disable_validation__ignore_storage_class), internal(disable_validation__ignore_invalid_pointer_argument)]] tint_symbol_1 : ptr<workgroup, f32>) {
+fn bar(a : f32, b : f32, @internal(disable_validation__ignore_storage_class) @internal(disable_validation__ignore_invalid_pointer_argument) tint_symbol : ptr<private, f32>, @internal(disable_validation__ignore_storage_class) @internal(disable_validation__ignore_invalid_pointer_argument) tint_symbol_1 : ptr<workgroup, f32>) {
   *(tint_symbol) = a;
   *(tint_symbol_1) = b;
 }
 
-fn foo(a : f32, [[internal(disable_validation__ignore_storage_class), internal(disable_validation__ignore_invalid_pointer_argument)]] tint_symbol_2 : ptr<private, f32>, [[internal(disable_validation__ignore_storage_class), internal(disable_validation__ignore_invalid_pointer_argument)]] tint_symbol_3 : ptr<workgroup, f32>) {
+fn foo(a : f32, @internal(disable_validation__ignore_storage_class) @internal(disable_validation__ignore_invalid_pointer_argument) tint_symbol_2 : ptr<private, f32>, @internal(disable_validation__ignore_storage_class) @internal(disable_validation__ignore_invalid_pointer_argument) tint_symbol_3 : ptr<workgroup, f32>) {
   let b : f32 = 2.0;
   bar(a, b, tint_symbol_2, tint_symbol_3);
   no_uses();
 }
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn main() {
-  [[internal(disable_validation__ignore_storage_class)]] var<private> tint_symbol_4 : f32;
-  [[internal(disable_validation__ignore_storage_class)]] var<workgroup> tint_symbol_5 : f32;
+  @internal(disable_validation__ignore_storage_class) var<private> tint_symbol_4 : f32;
+  @internal(disable_validation__ignore_storage_class) var<workgroup> tint_symbol_5 : f32;
   foo(1.0, &(tint_symbol_4), &(tint_symbol_5));
 }
 )";
@@ -107,17 +107,17 @@
 var<private> a : f32 = 1.0;
 var<private> b : f32 = f32();
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn main() {
   let x : f32 = a + b;
 }
 )";
 
   auto* expect = R"(
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn main() {
-  [[internal(disable_validation__ignore_storage_class)]] var<private> tint_symbol : f32 = 1.0;
-  [[internal(disable_validation__ignore_storage_class)]] var<private> tint_symbol_1 : f32 = f32();
+  @internal(disable_validation__ignore_storage_class) var<private> tint_symbol : f32 = 1.0;
+  @internal(disable_validation__ignore_storage_class) var<private> tint_symbol_1 : f32 = f32();
   let x : f32 = (tint_symbol + tint_symbol_1);
 }
 )";
@@ -132,7 +132,7 @@
 var<private> p : f32;
 var<workgroup> w : f32;
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn main() {
   let p_ptr : ptr<private, f32> = &p;
   let w_ptr : ptr<workgroup, f32> = &w;
@@ -142,10 +142,10 @@
 )";
 
   auto* expect = R"(
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn main() {
-  [[internal(disable_validation__ignore_storage_class)]] var<private> tint_symbol : f32;
-  [[internal(disable_validation__ignore_storage_class)]] var<workgroup> tint_symbol_1 : f32;
+  @internal(disable_validation__ignore_storage_class) var<private> tint_symbol : f32;
+  @internal(disable_validation__ignore_storage_class) var<workgroup> tint_symbol_1 : f32;
   let p_ptr : ptr<private, f32> = &(tint_symbol);
   let w_ptr : ptr<workgroup, f32> = &(tint_symbol_1);
   let x : f32 = (*(p_ptr) + *(w_ptr));
@@ -170,7 +170,7 @@
   bar(&v);
 }
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn main() {
   foo();
 }
@@ -181,13 +181,13 @@
   *(p) = 0.0;
 }
 
-fn foo([[internal(disable_validation__ignore_storage_class), internal(disable_validation__ignore_invalid_pointer_argument)]] tint_symbol : ptr<private, f32>) {
+fn foo(@internal(disable_validation__ignore_storage_class) @internal(disable_validation__ignore_invalid_pointer_argument) tint_symbol : ptr<private, f32>) {
   bar(tint_symbol);
 }
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn main() {
-  [[internal(disable_validation__ignore_storage_class)]] var<private> tint_symbol_1 : f32;
+  @internal(disable_validation__ignore_storage_class) var<private> tint_symbol_1 : f32;
   foo(&(tint_symbol_1));
 }
 )";
@@ -203,12 +203,12 @@
   a : f32;
 };
 
-[[group(0), binding(0)]]
+@group(0) @binding(0)
 var<uniform> u : S;
-[[group(0), binding(1)]]
+@group(0) @binding(1)
 var<storage> s : S;
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn main() {
   _ = u;
   _ = s;
@@ -220,8 +220,8 @@
   a : f32;
 }
 
-[[stage(compute), workgroup_size(1)]]
-fn main([[group(0), binding(0), internal(disable_validation__entry_point_parameter), internal(disable_validation__ignore_storage_class)]] tint_symbol : ptr<uniform, S>, [[group(0), binding(1), internal(disable_validation__entry_point_parameter), internal(disable_validation__ignore_storage_class)]] tint_symbol_1 : ptr<storage, S>) {
+@stage(compute) @workgroup_size(1)
+fn main(@group(0) @binding(0) @internal(disable_validation__entry_point_parameter) @internal(disable_validation__ignore_storage_class) tint_symbol : ptr<uniform, S>, @group(0) @binding(1) @internal(disable_validation__entry_point_parameter) @internal(disable_validation__ignore_storage_class) tint_symbol_1 : ptr<storage, S>) {
   _ = *(tint_symbol);
   _ = *(tint_symbol_1);
 }
@@ -234,10 +234,10 @@
 
 TEST_F(ModuleScopeVarToEntryPointParamTest, Buffer_RuntimeArray) {
   auto* src = R"(
-[[group(0), binding(0)]]
+@group(0) @binding(0)
 var<storage> buffer : array<f32>;
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn main() {
   _ = buffer[0];
 }
@@ -248,8 +248,8 @@
   arr : array<f32>;
 }
 
-[[stage(compute), workgroup_size(1)]]
-fn main([[group(0), binding(0), internal(disable_validation__entry_point_parameter), internal(disable_validation__ignore_storage_class)]] tint_symbol : ptr<storage, tint_symbol_1>) {
+@stage(compute) @workgroup_size(1)
+fn main(@group(0) @binding(0) @internal(disable_validation__entry_point_parameter) @internal(disable_validation__ignore_storage_class) tint_symbol : ptr<storage, tint_symbol_1>) {
   _ = (*(tint_symbol)).arr[0];
 }
 )";
@@ -261,14 +261,14 @@
 
 TEST_F(ModuleScopeVarToEntryPointParamTest, Buffer_RuntimeArrayInsideFunction) {
   auto* src = R"(
-[[group(0), binding(0)]]
+@group(0) @binding(0)
 var<storage> buffer : array<f32>;
 
 fn foo() {
   _ = buffer[0];
 }
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn main() {
   foo();
 }
@@ -279,12 +279,12 @@
   arr : array<f32>;
 }
 
-fn foo([[internal(disable_validation__ignore_storage_class), internal(disable_validation__ignore_invalid_pointer_argument)]] tint_symbol : ptr<storage, array<f32>>) {
+fn foo(@internal(disable_validation__ignore_storage_class) @internal(disable_validation__ignore_invalid_pointer_argument) tint_symbol : ptr<storage, array<f32>>) {
   _ = (*(tint_symbol))[0];
 }
 
-[[stage(compute), workgroup_size(1)]]
-fn main([[group(0), binding(0), internal(disable_validation__entry_point_parameter), internal(disable_validation__ignore_storage_class)]] tint_symbol_1 : ptr<storage, tint_symbol_2>) {
+@stage(compute) @workgroup_size(1)
+fn main(@group(0) @binding(0) @internal(disable_validation__entry_point_parameter) @internal(disable_validation__ignore_storage_class) tint_symbol_1 : ptr<storage, tint_symbol_2>) {
   foo(&((*(tint_symbol_1)).arr));
 }
 )";
@@ -298,10 +298,10 @@
   auto* src = R"(
 type myarray = array<f32>;
 
-[[group(0), binding(0)]]
+@group(0) @binding(0)
 var<storage> buffer : myarray;
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn main() {
   _ = buffer[0];
 }
@@ -314,8 +314,8 @@
 
 type myarray = array<f32>;
 
-[[stage(compute), workgroup_size(1)]]
-fn main([[group(0), binding(0), internal(disable_validation__entry_point_parameter), internal(disable_validation__ignore_storage_class)]] tint_symbol : ptr<storage, tint_symbol_1>) {
+@stage(compute) @workgroup_size(1)
+fn main(@group(0) @binding(0) @internal(disable_validation__entry_point_parameter) @internal(disable_validation__ignore_storage_class) tint_symbol : ptr<storage, tint_symbol_1>) {
   _ = (*(tint_symbol)).arr[0];
 }
 )";
@@ -331,10 +331,10 @@
   f : f32;
 };
 
-[[group(0), binding(0)]]
+@group(0) @binding(0)
 var<storage> buffer : array<S>;
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn main() {
   _ = buffer[0];
 }
@@ -349,8 +349,8 @@
   arr : array<S>;
 }
 
-[[stage(compute), workgroup_size(1)]]
-fn main([[group(0), binding(0), internal(disable_validation__entry_point_parameter), internal(disable_validation__ignore_storage_class)]] tint_symbol : ptr<storage, tint_symbol_1>) {
+@stage(compute) @workgroup_size(1)
+fn main(@group(0) @binding(0) @internal(disable_validation__entry_point_parameter) @internal(disable_validation__ignore_storage_class) tint_symbol : ptr<storage, tint_symbol_1>) {
   _ = (*(tint_symbol)).arr[0];
 }
 )";
@@ -366,9 +366,9 @@
   a : f32;
 };
 
-[[group(0), binding(0)]]
+@group(0) @binding(0)
 var<uniform> u : S;
-[[group(0), binding(1)]]
+@group(0) @binding(1)
 var<storage> s : S;
 
 fn no_uses() {
@@ -386,7 +386,7 @@
   no_uses();
 }
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn main() {
   foo(1.0);
 }
@@ -400,20 +400,20 @@
 fn no_uses() {
 }
 
-fn bar(a : f32, b : f32, [[internal(disable_validation__ignore_storage_class), internal(disable_validation__ignore_invalid_pointer_argument)]] tint_symbol : ptr<uniform, S>, [[internal(disable_validation__ignore_storage_class), internal(disable_validation__ignore_invalid_pointer_argument)]] tint_symbol_1 : ptr<storage, S>) {
+fn bar(a : f32, b : f32, @internal(disable_validation__ignore_storage_class) @internal(disable_validation__ignore_invalid_pointer_argument) tint_symbol : ptr<uniform, S>, @internal(disable_validation__ignore_storage_class) @internal(disable_validation__ignore_invalid_pointer_argument) tint_symbol_1 : ptr<storage, S>) {
   _ = *(tint_symbol);
   _ = *(tint_symbol_1);
 }
 
-fn foo(a : f32, [[internal(disable_validation__ignore_storage_class), internal(disable_validation__ignore_invalid_pointer_argument)]] tint_symbol_2 : ptr<uniform, S>, [[internal(disable_validation__ignore_storage_class), internal(disable_validation__ignore_invalid_pointer_argument)]] tint_symbol_3 : ptr<storage, S>) {
+fn foo(a : f32, @internal(disable_validation__ignore_storage_class) @internal(disable_validation__ignore_invalid_pointer_argument) tint_symbol_2 : ptr<uniform, S>, @internal(disable_validation__ignore_storage_class) @internal(disable_validation__ignore_invalid_pointer_argument) tint_symbol_3 : ptr<storage, S>) {
   let b : f32 = 2.0;
   _ = *(tint_symbol_2);
   bar(a, b, tint_symbol_2, tint_symbol_3);
   no_uses();
 }
 
-[[stage(compute), workgroup_size(1)]]
-fn main([[group(0), binding(0), internal(disable_validation__entry_point_parameter), internal(disable_validation__ignore_storage_class)]] tint_symbol_4 : ptr<uniform, S>, [[group(0), binding(1), internal(disable_validation__entry_point_parameter), internal(disable_validation__ignore_storage_class)]] tint_symbol_5 : ptr<storage, S>) {
+@stage(compute) @workgroup_size(1)
+fn main(@group(0) @binding(0) @internal(disable_validation__entry_point_parameter) @internal(disable_validation__ignore_storage_class) tint_symbol_4 : ptr<uniform, S>, @group(0) @binding(1) @internal(disable_validation__entry_point_parameter) @internal(disable_validation__ignore_storage_class) tint_symbol_5 : ptr<storage, S>) {
   foo(1.0, tint_symbol_4, tint_symbol_5);
 }
 )";
@@ -425,10 +425,10 @@
 
 TEST_F(ModuleScopeVarToEntryPointParamTest, HandleTypes_Basic) {
   auto* src = R"(
-[[group(0), binding(0)]] var t : texture_2d<f32>;
-[[group(0), binding(1)]] var s : sampler;
+@group(0) @binding(0) var t : texture_2d<f32>;
+@group(0) @binding(1) var s : sampler;
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn main() {
   _ = t;
   _ = s;
@@ -436,8 +436,8 @@
 )";
 
   auto* expect = R"(
-[[stage(compute), workgroup_size(1)]]
-fn main([[group(0), binding(0), internal(disable_validation__entry_point_parameter)]] tint_symbol : texture_2d<f32>, [[group(0), binding(1), internal(disable_validation__entry_point_parameter)]] tint_symbol_1 : sampler) {
+@stage(compute) @workgroup_size(1)
+fn main(@group(0) @binding(0) @internal(disable_validation__entry_point_parameter) tint_symbol : texture_2d<f32>, @group(0) @binding(1) @internal(disable_validation__entry_point_parameter) tint_symbol_1 : sampler) {
   _ = tint_symbol;
   _ = tint_symbol_1;
 }
@@ -450,8 +450,8 @@
 
 TEST_F(ModuleScopeVarToEntryPointParamTest, HandleTypes_FunctionCalls) {
   auto* src = R"(
-[[group(0), binding(0)]] var t : texture_2d<f32>;
-[[group(0), binding(1)]] var s : sampler;
+@group(0) @binding(0) var t : texture_2d<f32>;
+@group(0) @binding(1) var s : sampler;
 
 fn no_uses() {
 }
@@ -468,7 +468,7 @@
   no_uses();
 }
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn main() {
   foo(1.0);
 }
@@ -490,8 +490,8 @@
   no_uses();
 }
 
-[[stage(compute), workgroup_size(1)]]
-fn main([[group(0), binding(0), internal(disable_validation__entry_point_parameter)]] tint_symbol_4 : texture_2d<f32>, [[group(0), binding(1), internal(disable_validation__entry_point_parameter)]] tint_symbol_5 : sampler) {
+@stage(compute) @workgroup_size(1)
+fn main(@group(0) @binding(0) @internal(disable_validation__entry_point_parameter) tint_symbol_4 : texture_2d<f32>, @group(0) @binding(1) @internal(disable_validation__entry_point_parameter) tint_symbol_5 : sampler) {
   foo(1.0, tint_symbol_4, tint_symbol_5);
 }
 )";
@@ -505,7 +505,7 @@
   auto* src = R"(
 var<workgroup> m : mat2x2<f32>;
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn main() {
   let x = m;
 }
@@ -516,8 +516,8 @@
   m : mat2x2<f32>;
 }
 
-[[stage(compute), workgroup_size(1)]]
-fn main([[internal(disable_validation__entry_point_parameter)]] tint_symbol_1 : ptr<workgroup, tint_symbol_2>) {
+@stage(compute) @workgroup_size(1)
+fn main(@internal(disable_validation__entry_point_parameter) tint_symbol_1 : ptr<workgroup, tint_symbol_2>) {
   let tint_symbol : ptr<workgroup, mat2x2<f32>> = &((*(tint_symbol_1)).m);
   let x = *(tint_symbol);
 }
@@ -538,7 +538,7 @@
 };
 var<workgroup> m : array<S2, 4>;
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn main() {
   let x = m;
 }
@@ -557,8 +557,8 @@
   m : array<S2, 4u>;
 }
 
-[[stage(compute), workgroup_size(1)]]
-fn main([[internal(disable_validation__entry_point_parameter)]] tint_symbol_1 : ptr<workgroup, tint_symbol_2>) {
+@stage(compute) @workgroup_size(1)
+fn main(@internal(disable_validation__entry_point_parameter) tint_symbol_1 : ptr<workgroup, tint_symbol_2>) {
   let tint_symbol : ptr<workgroup, array<S2, 4u>> = &((*(tint_symbol_1)).m);
   let x = *(tint_symbol);
 }
@@ -581,7 +581,7 @@
 
 var<workgroup> b : S;
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn main() {
   let x = a;
   let y = b;
@@ -598,8 +598,8 @@
   b : S;
 }
 
-[[stage(compute), workgroup_size(1)]]
-fn main([[internal(disable_validation__entry_point_parameter)]] tint_symbol_1 : ptr<workgroup, tint_symbol_3>) {
+@stage(compute) @workgroup_size(1)
+fn main(@internal(disable_validation__entry_point_parameter) tint_symbol_1 : ptr<workgroup, tint_symbol_3>) {
   let tint_symbol : ptr<workgroup, S> = &((*(tint_symbol_1)).a);
   let tint_symbol_2 : ptr<workgroup, S> = &((*(tint_symbol_1)).b);
   let x = *(tint_symbol);
@@ -621,15 +621,15 @@
 var<private> p : f32;
 var<workgroup> w : f32;
 
-[[group(0), binding(0)]]
+@group(0) @binding(0)
 var<uniform> ub : S;
-[[group(0), binding(1)]]
+@group(0) @binding(1)
 var<storage> sb : S;
 
-[[group(0), binding(2)]] var t : texture_2d<f32>;
-[[group(0), binding(3)]] var s : sampler;
+@group(0) @binding(2) var t : texture_2d<f32>;
+@group(0) @binding(3) var s : sampler;
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn main() {
 }
 )";
@@ -639,7 +639,7 @@
   a : f32;
 }
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn main() {
 }
 )";
diff --git a/src/transform/multiplanar_external_texture_test.cc b/src/transform/multiplanar_external_texture_test.cc
index e4c1d55..be8137a 100644
--- a/src/transform/multiplanar_external_texture_test.cc
+++ b/src/transform/multiplanar_external_texture_test.cc
@@ -25,11 +25,11 @@
 // result in an error.
 TEST_F(MultiplanarExternalTextureTest, ErrorNoPassedData) {
   auto* src = R"(
-[[group(0), binding(0)]] var s : sampler;
-[[group(0), binding(1)]] var ext_tex : texture_external;
+@group(0) @binding(0) var s : sampler;
+@group(0) @binding(1) var ext_tex : texture_external;
 
-[[stage(fragment)]]
-fn main([[builtin(position)]] coord : vec4<f32>) -> [[location(0)]] vec4<f32> {
+@stage(fragment)
+fn main(@builtin(position) coord : vec4<f32>) -> @location(0) vec4<f32> {
   return textureSampleLevel(ext_tex, s, coord.xy);
 }
 )";
@@ -43,11 +43,11 @@
 // Running the transform with incorrect binding data should result in an error.
 TEST_F(MultiplanarExternalTextureTest, ErrorIncorrectBindingPont) {
   auto* src = R"(
-[[group(0), binding(0)]] var s : sampler;
-[[group(0), binding(1)]] var ext_tex : texture_external;
+@group(0) @binding(0) var s : sampler;
+@group(0) @binding(1) var ext_tex : texture_external;
 
-[[stage(fragment)]]
-fn main([[builtin(position)]] coord : vec4<f32>) -> [[location(0)]] vec4<f32> {
+@stage(fragment)
+fn main(@builtin(position) coord : vec4<f32>) -> @location(0) vec4<f32> {
   return textureSampleLevel(ext_tex, s, coord.xy);
 }
 )";
@@ -67,10 +67,10 @@
 // Tests that the transform works with a textureDimensions call.
 TEST_F(MultiplanarExternalTextureTest, Dimensions) {
   auto* src = R"(
-[[group(0), binding(0)]] var ext_tex : texture_external;
+@group(0) @binding(0) var ext_tex : texture_external;
 
-[[stage(fragment)]]
-fn main([[builtin(position)]] coord : vec4<f32>) -> [[location(0)]] vec4<f32> {
+@stage(fragment)
+fn main(@builtin(position) coord : vec4<f32>) -> @location(0) vec4<f32> {
   var dim : vec2<i32>;
   dim = textureDimensions(ext_tex);
   return vec4<f32>(0.0, 0.0, 0.0, 0.0);
@@ -86,14 +86,14 @@
   ub : f32;
 }
 
-[[group(0), binding(1)]] var ext_tex_plane_1 : texture_2d<f32>;
+@group(0) @binding(1) var ext_tex_plane_1 : texture_2d<f32>;
 
-[[group(0), binding(2)]] var<uniform> ext_tex_params : ExternalTextureParams;
+@group(0) @binding(2) var<uniform> ext_tex_params : ExternalTextureParams;
 
-[[group(0), binding(0)]] var ext_tex : texture_2d<f32>;
+@group(0) @binding(0) var ext_tex : texture_2d<f32>;
 
-[[stage(fragment)]]
-fn main([[builtin(position)]] coord : vec4<f32>) -> [[location(0)]] vec4<f32> {
+@stage(fragment)
+fn main(@builtin(position) coord : vec4<f32>) -> @location(0) vec4<f32> {
   var dim : vec2<i32>;
   dim = textureDimensions(ext_tex);
   return vec4<f32>(0.0, 0.0, 0.0, 0.0);
@@ -110,17 +110,17 @@
 // Test that the transform works with a textureSampleLevel call.
 TEST_F(MultiplanarExternalTextureTest, BasicTextureSampleLevel) {
   auto* src = R"(
-[[group(0), binding(0)]] var s : sampler;
-[[group(0), binding(1)]] var ext_tex : texture_external;
+@group(0) @binding(0) var s : sampler;
+@group(0) @binding(1) var ext_tex : texture_external;
 
-[[stage(fragment)]]
-fn main([[builtin(position)]] coord : vec4<f32>) -> [[location(0)]] vec4<f32> {
+@stage(fragment)
+fn main(@builtin(position) coord : vec4<f32>) -> @location(0) vec4<f32> {
   return textureSampleLevel(ext_tex, s, coord.xy);
 }
 )";
 
   auto* expect = R"(
-[[group(0), binding(0)]] var s : sampler;
+@group(0) @binding(0) var s : sampler;
 
 struct ExternalTextureParams {
   numPlanes : u32;
@@ -130,11 +130,11 @@
   ub : f32;
 }
 
-[[group(0), binding(2)]] var ext_tex_plane_1 : texture_2d<f32>;
+@group(0) @binding(2) var ext_tex_plane_1 : texture_2d<f32>;
 
-[[group(0), binding(3)]] var<uniform> ext_tex_params : ExternalTextureParams;
+@group(0) @binding(3) var<uniform> ext_tex_params : ExternalTextureParams;
 
-[[group(0), binding(1)]] var ext_tex : texture_2d<f32>;
+@group(0) @binding(1) var ext_tex : texture_2d<f32>;
 
 fn textureSampleExternal(plane0 : texture_2d<f32>, plane1 : texture_2d<f32>, smp : sampler, coord : vec2<f32>, params : ExternalTextureParams) -> vec4<f32> {
   if ((params.numPlanes == 1u)) {
@@ -150,8 +150,8 @@
   return vec4<f32>(r, g, b, 1.0);
 }
 
-[[stage(fragment)]]
-fn main([[builtin(position)]] coord : vec4<f32>) -> [[location(0)]] vec4<f32> {
+@stage(fragment)
+fn main(@builtin(position) coord : vec4<f32>) -> @location(0) vec4<f32> {
   return textureSampleExternal(ext_tex, ext_tex_plane_1, s, coord.xy, ext_tex_params);
 }
 )";
@@ -166,10 +166,10 @@
 // Tests that the transform works with a textureLoad call.
 TEST_F(MultiplanarExternalTextureTest, BasicTextureLoad) {
   auto* src = R"(
-[[group(0), binding(0)]] var ext_tex : texture_external;
+@group(0) @binding(0) var ext_tex : texture_external;
 
-[[stage(fragment)]]
-fn main([[builtin(position)]] coord : vec4<f32>) -> [[location(0)]] vec4<f32> {
+@stage(fragment)
+fn main(@builtin(position) coord : vec4<f32>) -> @location(0) vec4<f32> {
   return textureLoad(ext_tex, vec2<i32>(1, 1));
 }
 )";
@@ -183,11 +183,11 @@
   ub : f32;
 }
 
-[[group(0), binding(1)]] var ext_tex_plane_1 : texture_2d<f32>;
+@group(0) @binding(1) var ext_tex_plane_1 : texture_2d<f32>;
 
-[[group(0), binding(2)]] var<uniform> ext_tex_params : ExternalTextureParams;
+@group(0) @binding(2) var<uniform> ext_tex_params : ExternalTextureParams;
 
-[[group(0), binding(0)]] var ext_tex : texture_2d<f32>;
+@group(0) @binding(0) var ext_tex : texture_2d<f32>;
 
 fn textureLoadExternal(plane0 : texture_2d<f32>, plane1 : texture_2d<f32>, coord : vec2<i32>, params : ExternalTextureParams) -> vec4<f32> {
   if ((params.numPlanes == 1u)) {
@@ -203,8 +203,8 @@
   return vec4<f32>(r, g, b, 1.0);
 }
 
-[[stage(fragment)]]
-fn main([[builtin(position)]] coord : vec4<f32>) -> [[location(0)]] vec4<f32> {
+@stage(fragment)
+fn main(@builtin(position) coord : vec4<f32>) -> @location(0) vec4<f32> {
   return textureLoadExternal(ext_tex, ext_tex_plane_1, vec2<i32>(1, 1), ext_tex_params);
 }
 )";
@@ -220,17 +220,17 @@
 // call.
 TEST_F(MultiplanarExternalTextureTest, TextureSampleAndTextureLoad) {
   auto* src = R"(
-[[group(0), binding(0)]] var s : sampler;
-[[group(0), binding(1)]] var ext_tex : texture_external;
+@group(0) @binding(0) var s : sampler;
+@group(0) @binding(1) var ext_tex : texture_external;
 
-[[stage(fragment)]]
-fn main([[builtin(position)]] coord : vec4<f32>) -> [[location(0)]] vec4<f32> {
+@stage(fragment)
+fn main(@builtin(position) coord : vec4<f32>) -> @location(0) vec4<f32> {
   return textureSampleLevel(ext_tex, s, coord.xy) + textureLoad(ext_tex, vec2<i32>(1, 1));
 }
 )";
 
   auto* expect = R"(
-[[group(0), binding(0)]] var s : sampler;
+@group(0) @binding(0) var s : sampler;
 
 struct ExternalTextureParams {
   numPlanes : u32;
@@ -240,11 +240,11 @@
   ub : f32;
 }
 
-[[group(0), binding(2)]] var ext_tex_plane_1 : texture_2d<f32>;
+@group(0) @binding(2) var ext_tex_plane_1 : texture_2d<f32>;
 
-[[group(0), binding(3)]] var<uniform> ext_tex_params : ExternalTextureParams;
+@group(0) @binding(3) var<uniform> ext_tex_params : ExternalTextureParams;
 
-[[group(0), binding(1)]] var ext_tex : texture_2d<f32>;
+@group(0) @binding(1) var ext_tex : texture_2d<f32>;
 
 fn textureSampleExternal(plane0 : texture_2d<f32>, plane1 : texture_2d<f32>, smp : sampler, coord : vec2<f32>, params : ExternalTextureParams) -> vec4<f32> {
   if ((params.numPlanes == 1u)) {
@@ -274,8 +274,8 @@
   return vec4<f32>(r, g, b, 1.0);
 }
 
-[[stage(fragment)]]
-fn main([[builtin(position)]] coord : vec4<f32>) -> [[location(0)]] vec4<f32> {
+@stage(fragment)
+fn main(@builtin(position) coord : vec4<f32>) -> @location(0) vec4<f32> {
   return (textureSampleExternal(ext_tex, ext_tex_plane_1, s, coord.xy, ext_tex_params) + textureLoadExternal(ext_tex, ext_tex_plane_1, vec2<i32>(1, 1), ext_tex_params));
 }
 )";
@@ -290,20 +290,20 @@
 // Tests that the transform works with many instances of texture_external.
 TEST_F(MultiplanarExternalTextureTest, ManyTextureSampleLevel) {
   auto* src = R"(
-[[group(0), binding(0)]] var s : sampler;
-[[group(0), binding(1)]] var ext_tex : texture_external;
-[[group(0), binding(2)]] var ext_tex_1 : texture_external;
-[[group(0), binding(3)]] var ext_tex_2 : texture_external;
-[[group(1), binding(0)]] var ext_tex_3 : texture_external;
+@group(0) @binding(0) var s : sampler;
+@group(0) @binding(1) var ext_tex : texture_external;
+@group(0) @binding(2) var ext_tex_1 : texture_external;
+@group(0) @binding(3) var ext_tex_2 : texture_external;
+@group(1) @binding(0) var ext_tex_3 : texture_external;
 
-[[stage(fragment)]]
-fn main([[builtin(position)]] coord : vec4<f32>) -> [[location(0)]] vec4<f32> {
+@stage(fragment)
+fn main(@builtin(position) coord : vec4<f32>) -> @location(0) vec4<f32> {
   return textureSampleLevel(ext_tex, s, coord.xy) + textureSampleLevel(ext_tex_1, s, coord.xy) + textureSampleLevel(ext_tex_2, s, coord.xy) + textureSampleLevel(ext_tex_3, s, coord.xy);
 }
 )";
 
   auto* expect = R"(
-[[group(0), binding(0)]] var s : sampler;
+@group(0) @binding(0) var s : sampler;
 
 struct ExternalTextureParams {
   numPlanes : u32;
@@ -313,29 +313,29 @@
   ub : f32;
 }
 
-[[group(0), binding(4)]] var ext_tex_plane_1 : texture_2d<f32>;
+@group(0) @binding(4) var ext_tex_plane_1 : texture_2d<f32>;
 
-[[group(0), binding(5)]] var<uniform> ext_tex_params : ExternalTextureParams;
+@group(0) @binding(5) var<uniform> ext_tex_params : ExternalTextureParams;
 
-[[group(0), binding(1)]] var ext_tex : texture_2d<f32>;
+@group(0) @binding(1) var ext_tex : texture_2d<f32>;
 
-[[group(0), binding(6)]] var ext_tex_plane_1_1 : texture_2d<f32>;
+@group(0) @binding(6) var ext_tex_plane_1_1 : texture_2d<f32>;
 
-[[group(0), binding(7)]] var<uniform> ext_tex_params_1 : ExternalTextureParams;
+@group(0) @binding(7) var<uniform> ext_tex_params_1 : ExternalTextureParams;
 
-[[group(0), binding(2)]] var ext_tex_1 : texture_2d<f32>;
+@group(0) @binding(2) var ext_tex_1 : texture_2d<f32>;
 
-[[group(0), binding(8)]] var ext_tex_plane_1_2 : texture_2d<f32>;
+@group(0) @binding(8) var ext_tex_plane_1_2 : texture_2d<f32>;
 
-[[group(0), binding(9)]] var<uniform> ext_tex_params_2 : ExternalTextureParams;
+@group(0) @binding(9) var<uniform> ext_tex_params_2 : ExternalTextureParams;
 
-[[group(0), binding(3)]] var ext_tex_2 : texture_2d<f32>;
+@group(0) @binding(3) var ext_tex_2 : texture_2d<f32>;
 
-[[group(1), binding(1)]] var ext_tex_plane_1_3 : texture_2d<f32>;
+@group(1) @binding(1) var ext_tex_plane_1_3 : texture_2d<f32>;
 
-[[group(1), binding(2)]] var<uniform> ext_tex_params_3 : ExternalTextureParams;
+@group(1) @binding(2) var<uniform> ext_tex_params_3 : ExternalTextureParams;
 
-[[group(1), binding(0)]] var ext_tex_3 : texture_2d<f32>;
+@group(1) @binding(0) var ext_tex_3 : texture_2d<f32>;
 
 fn textureSampleExternal(plane0 : texture_2d<f32>, plane1 : texture_2d<f32>, smp : sampler, coord : vec2<f32>, params : ExternalTextureParams) -> vec4<f32> {
   if ((params.numPlanes == 1u)) {
@@ -351,8 +351,8 @@
   return vec4<f32>(r, g, b, 1.0);
 }
 
-[[stage(fragment)]]
-fn main([[builtin(position)]] coord : vec4<f32>) -> [[location(0)]] vec4<f32> {
+@stage(fragment)
+fn main(@builtin(position) coord : vec4<f32>) -> @location(0) vec4<f32> {
   return (((textureSampleExternal(ext_tex, ext_tex_plane_1, s, coord.xy, ext_tex_params) + textureSampleExternal(ext_tex_1, ext_tex_plane_1_1, s, coord.xy, ext_tex_params_1)) + textureSampleExternal(ext_tex_2, ext_tex_plane_1_2, s, coord.xy, ext_tex_params_2)) + textureSampleExternal(ext_tex_3, ext_tex_plane_1_3, s, coord.xy, ext_tex_params_3));
 }
 )";
@@ -377,10 +377,10 @@
   textureSampleLevel(t, s, vec2<f32>(1.0, 2.0));
 }
 
-[[group(0), binding(0)]] var ext_tex : texture_external;
-[[group(0), binding(1)]] var smp : sampler;
+@group(0) @binding(0) var ext_tex : texture_external;
+@group(0) @binding(1) var smp : sampler;
 
-[[stage(fragment)]]
+@stage(fragment)
 fn main() {
   f(ext_tex, smp);
 }
@@ -413,15 +413,15 @@
   textureSampleExternal(t, ext_tex_plane_1, s, vec2<f32>(1.0, 2.0), ext_tex_params);
 }
 
-[[group(0), binding(2)]] var ext_tex_plane_1_1 : texture_2d<f32>;
+@group(0) @binding(2) var ext_tex_plane_1_1 : texture_2d<f32>;
 
-[[group(0), binding(3)]] var<uniform> ext_tex_params_1 : ExternalTextureParams;
+@group(0) @binding(3) var<uniform> ext_tex_params_1 : ExternalTextureParams;
 
-[[group(0), binding(0)]] var ext_tex : texture_2d<f32>;
+@group(0) @binding(0) var ext_tex : texture_2d<f32>;
 
-[[group(0), binding(1)]] var smp : sampler;
+@group(0) @binding(1) var smp : sampler;
 
-[[stage(fragment)]]
+@stage(fragment)
 fn main() {
   f(ext_tex, ext_tex_plane_1_1, ext_tex_params_1, smp);
 }
@@ -443,10 +443,10 @@
   textureSampleLevel(t, s, vec2<f32>(1.0, 2.0));
 }
 
-[[group(0), binding(0)]] var ext_tex : texture_external;
-[[group(0), binding(1)]] var smp : sampler;
+@group(0) @binding(0) var ext_tex : texture_external;
+@group(0) @binding(1) var smp : sampler;
 
-[[stage(fragment)]]
+@stage(fragment)
 fn main() {
   f(smp, ext_tex);
 }
@@ -479,15 +479,15 @@
   textureSampleExternal(t, ext_tex_plane_1, s, vec2<f32>(1.0, 2.0), ext_tex_params);
 }
 
-[[group(0), binding(2)]] var ext_tex_plane_1_1 : texture_2d<f32>;
+@group(0) @binding(2) var ext_tex_plane_1_1 : texture_2d<f32>;
 
-[[group(0), binding(3)]] var<uniform> ext_tex_params_1 : ExternalTextureParams;
+@group(0) @binding(3) var<uniform> ext_tex_params_1 : ExternalTextureParams;
 
-[[group(0), binding(0)]] var ext_tex : texture_2d<f32>;
+@group(0) @binding(0) var ext_tex : texture_2d<f32>;
 
-[[group(0), binding(1)]] var smp : sampler;
+@group(0) @binding(1) var smp : sampler;
 
-[[stage(fragment)]]
+@stage(fragment)
 fn main() {
   f(smp, ext_tex, ext_tex_plane_1_1, ext_tex_params_1);
 }
@@ -510,11 +510,11 @@
   textureSampleLevel(t2, s, vec2<f32>(1.0, 2.0));
 }
 
-[[group(0), binding(0)]] var ext_tex : texture_external;
-[[group(0), binding(1)]] var smp : sampler;
-[[group(0), binding(2)]] var ext_tex2 : texture_external;
+@group(0) @binding(0) var ext_tex : texture_external;
+@group(0) @binding(1) var smp : sampler;
+@group(0) @binding(2) var ext_tex2 : texture_external;
 
-[[stage(fragment)]]
+@stage(fragment)
 fn main() {
   f(ext_tex, smp, ext_tex2);
 }
@@ -548,21 +548,21 @@
   textureSampleExternal(t2, ext_tex_plane_1_1, s, vec2<f32>(1.0, 2.0), ext_tex_params_1);
 }
 
-[[group(0), binding(3)]] var ext_tex_plane_1_2 : texture_2d<f32>;
+@group(0) @binding(3) var ext_tex_plane_1_2 : texture_2d<f32>;
 
-[[group(0), binding(4)]] var<uniform> ext_tex_params_2 : ExternalTextureParams;
+@group(0) @binding(4) var<uniform> ext_tex_params_2 : ExternalTextureParams;
 
-[[group(0), binding(0)]] var ext_tex : texture_2d<f32>;
+@group(0) @binding(0) var ext_tex : texture_2d<f32>;
 
-[[group(0), binding(1)]] var smp : sampler;
+@group(0) @binding(1) var smp : sampler;
 
-[[group(0), binding(5)]] var ext_tex_plane_1_3 : texture_2d<f32>;
+@group(0) @binding(5) var ext_tex_plane_1_3 : texture_2d<f32>;
 
-[[group(0), binding(6)]] var<uniform> ext_tex_params_3 : ExternalTextureParams;
+@group(0) @binding(6) var<uniform> ext_tex_params_3 : ExternalTextureParams;
 
-[[group(0), binding(2)]] var ext_tex2 : texture_2d<f32>;
+@group(0) @binding(2) var ext_tex2 : texture_2d<f32>;
 
-[[stage(fragment)]]
+@stage(fragment)
 fn main() {
   f(ext_tex, ext_tex_plane_1_2, ext_tex_params_2, smp, ext_tex2, ext_tex_plane_1_3, ext_tex_params_3);
 }
@@ -589,10 +589,10 @@
   nested(t, s);
 }
 
-[[group(0), binding(0)]] var ext_tex : texture_external;
-[[group(0), binding(1)]] var smp : sampler;
+@group(0) @binding(0) var ext_tex : texture_external;
+@group(0) @binding(1) var smp : sampler;
 
-[[stage(fragment)]]
+@stage(fragment)
 fn main() {
   f(ext_tex, smp);
 }
@@ -629,15 +629,15 @@
   nested(t, ext_tex_plane_1_1, ext_tex_params_1, s);
 }
 
-[[group(0), binding(2)]] var ext_tex_plane_1_2 : texture_2d<f32>;
+@group(0) @binding(2) var ext_tex_plane_1_2 : texture_2d<f32>;
 
-[[group(0), binding(3)]] var<uniform> ext_tex_params_2 : ExternalTextureParams;
+@group(0) @binding(3) var<uniform> ext_tex_params_2 : ExternalTextureParams;
 
-[[group(0), binding(0)]] var ext_tex : texture_2d<f32>;
+@group(0) @binding(0) var ext_tex : texture_2d<f32>;
 
-[[group(0), binding(1)]] var smp : sampler;
+@group(0) @binding(1) var smp : sampler;
 
-[[stage(fragment)]]
+@stage(fragment)
 fn main() {
   f(ext_tex, ext_tex_plane_1_2, ext_tex_params_2, smp);
 }
diff --git a/src/transform/num_workgroups_from_uniform.h b/src/transform/num_workgroups_from_uniform.h
index af922c2..ab8daa6 100644
--- a/src/transform/num_workgroups_from_uniform.h
+++ b/src/transform/num_workgroups_from_uniform.h
@@ -34,7 +34,7 @@
 ///  num_workgroups : vec3<u32>;
 /// };
 ///
-/// [[group(0), binding(0)]]
+/// @group(0) @binding(0)
 /// var<uniform> num_workgroups_ubo : num_workgroups_struct;
 /// ```
 /// The binding group and number used for this uniform buffer is provided via
diff --git a/src/transform/num_workgroups_from_uniform_test.cc b/src/transform/num_workgroups_from_uniform_test.cc
index ecb221a..bea5222 100644
--- a/src/transform/num_workgroups_from_uniform_test.cc
+++ b/src/transform/num_workgroups_from_uniform_test.cc
@@ -57,8 +57,8 @@
 
 TEST_F(NumWorkgroupsFromUniformTest, Basic) {
   auto* src = R"(
-[[stage(compute), workgroup_size(1)]]
-fn main([[builtin(num_workgroups)]] num_wgs : vec3<u32>) {
+@stage(compute) @workgroup_size(1)
+fn main(@builtin(num_workgroups) num_wgs : vec3<u32>) {
   let groups_x = num_wgs.x;
   let groups_y = num_wgs.y;
   let groups_z = num_wgs.z;
@@ -70,7 +70,7 @@
   num_workgroups : vec3<u32>;
 }
 
-[[group(0), binding(30)]] var<uniform> tint_symbol_3 : tint_symbol_2;
+@group(0) @binding(30) var<uniform> tint_symbol_3 : tint_symbol_2;
 
 fn main_inner(num_wgs : vec3<u32>) {
   let groups_x = num_wgs.x;
@@ -78,7 +78,7 @@
   let groups_z = num_wgs.z;
 }
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn main() {
   main_inner(tint_symbol_3.num_workgroups);
 }
@@ -96,10 +96,10 @@
 TEST_F(NumWorkgroupsFromUniformTest, StructOnlyMember) {
   auto* src = R"(
 struct Builtins {
-  [[builtin(num_workgroups)]] num_wgs : vec3<u32>;
+  @builtin(num_workgroups) num_wgs : vec3<u32>;
 };
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn main(in : Builtins) {
   let groups_x = in.num_wgs.x;
   let groups_y = in.num_wgs.y;
@@ -112,7 +112,7 @@
   num_workgroups : vec3<u32>;
 }
 
-[[group(0), binding(30)]] var<uniform> tint_symbol_3 : tint_symbol_2;
+@group(0) @binding(30) var<uniform> tint_symbol_3 : tint_symbol_2;
 
 struct Builtins {
   num_wgs : vec3<u32>;
@@ -124,7 +124,7 @@
   let groups_z = in.num_wgs.z;
 }
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn main() {
   main_inner(Builtins(tint_symbol_3.num_workgroups));
 }
@@ -142,12 +142,12 @@
 TEST_F(NumWorkgroupsFromUniformTest, StructMultipleMembers) {
   auto* src = R"(
 struct Builtins {
-  [[builtin(global_invocation_id)]] gid : vec3<u32>;
-  [[builtin(num_workgroups)]] num_wgs : vec3<u32>;
-  [[builtin(workgroup_id)]] wgid : vec3<u32>;
+  @builtin(global_invocation_id) gid : vec3<u32>;
+  @builtin(num_workgroups) num_wgs : vec3<u32>;
+  @builtin(workgroup_id) wgid : vec3<u32>;
 };
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn main(in : Builtins) {
   let groups_x = in.num_wgs.x;
   let groups_y = in.num_wgs.y;
@@ -160,7 +160,7 @@
   num_workgroups : vec3<u32>;
 }
 
-[[group(0), binding(30)]] var<uniform> tint_symbol_3 : tint_symbol_2;
+@group(0) @binding(30) var<uniform> tint_symbol_3 : tint_symbol_2;
 
 struct Builtins {
   gid : vec3<u32>;
@@ -169,9 +169,9 @@
 }
 
 struct tint_symbol_1 {
-  [[builtin(global_invocation_id)]]
+  @builtin(global_invocation_id)
   gid : vec3<u32>;
-  [[builtin(workgroup_id)]]
+  @builtin(workgroup_id)
   wgid : vec3<u32>;
 }
 
@@ -181,7 +181,7 @@
   let groups_z = in.num_wgs.z;
 }
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn main(tint_symbol : tint_symbol_1) {
   main_inner(Builtins(tint_symbol.gid, tint_symbol_3.num_workgroups, tint_symbol.wgid));
 }
@@ -199,31 +199,31 @@
 TEST_F(NumWorkgroupsFromUniformTest, MultipleEntryPoints) {
   auto* src = R"(
 struct Builtins1 {
-  [[builtin(num_workgroups)]] num_wgs : vec3<u32>;
+  @builtin(num_workgroups) num_wgs : vec3<u32>;
 };
 
 struct Builtins2 {
-  [[builtin(global_invocation_id)]] gid : vec3<u32>;
-  [[builtin(num_workgroups)]] num_wgs : vec3<u32>;
-  [[builtin(workgroup_id)]] wgid : vec3<u32>;
+  @builtin(global_invocation_id) gid : vec3<u32>;
+  @builtin(num_workgroups) num_wgs : vec3<u32>;
+  @builtin(workgroup_id) wgid : vec3<u32>;
 };
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn main1(in : Builtins1) {
   let groups_x = in.num_wgs.x;
   let groups_y = in.num_wgs.y;
   let groups_z = in.num_wgs.z;
 }
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn main2(in : Builtins2) {
   let groups_x = in.num_wgs.x;
   let groups_y = in.num_wgs.y;
   let groups_z = in.num_wgs.z;
 }
 
-[[stage(compute), workgroup_size(1)]]
-fn main3([[builtin(num_workgroups)]] num_wgs : vec3<u32>) {
+@stage(compute) @workgroup_size(1)
+fn main3(@builtin(num_workgroups) num_wgs : vec3<u32>) {
   let groups_x = num_wgs.x;
   let groups_y = num_wgs.y;
   let groups_z = num_wgs.z;
@@ -235,7 +235,7 @@
   num_workgroups : vec3<u32>;
 }
 
-[[group(0), binding(30)]] var<uniform> tint_symbol_7 : tint_symbol_6;
+@group(0) @binding(30) var<uniform> tint_symbol_7 : tint_symbol_6;
 
 struct Builtins1 {
   num_wgs : vec3<u32>;
@@ -253,15 +253,15 @@
   let groups_z = in.num_wgs.z;
 }
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn main1() {
   main1_inner(Builtins1(tint_symbol_7.num_workgroups));
 }
 
 struct tint_symbol_3 {
-  [[builtin(global_invocation_id)]]
+  @builtin(global_invocation_id)
   gid : vec3<u32>;
-  [[builtin(workgroup_id)]]
+  @builtin(workgroup_id)
   wgid : vec3<u32>;
 }
 
@@ -271,7 +271,7 @@
   let groups_z = in.num_wgs.z;
 }
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn main2(tint_symbol_2 : tint_symbol_3) {
   main2_inner(Builtins2(tint_symbol_2.gid, tint_symbol_7.num_workgroups, tint_symbol_2.wgid));
 }
@@ -282,7 +282,7 @@
   let groups_z = num_wgs.z;
 }
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn main3() {
   main3_inner(tint_symbol_7.num_workgroups);
 }
@@ -300,11 +300,11 @@
 TEST_F(NumWorkgroupsFromUniformTest, NoUsages) {
   auto* src = R"(
 struct Builtins {
-  [[builtin(global_invocation_id)]] gid : vec3<u32>;
-  [[builtin(workgroup_id)]] wgid : vec3<u32>;
+  @builtin(global_invocation_id) gid : vec3<u32>;
+  @builtin(workgroup_id) wgid : vec3<u32>;
 };
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn main(in : Builtins) {
 }
 )";
@@ -316,16 +316,16 @@
 }
 
 struct tint_symbol_1 {
-  [[builtin(global_invocation_id)]]
+  @builtin(global_invocation_id)
   gid : vec3<u32>;
-  [[builtin(workgroup_id)]]
+  @builtin(workgroup_id)
   wgid : vec3<u32>;
 }
 
 fn main_inner(in : Builtins) {
 }
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn main(tint_symbol : tint_symbol_1) {
   main_inner(Builtins(tint_symbol.gid, tint_symbol.wgid));
 }
diff --git a/src/transform/pad_array_elements_test.cc b/src/transform/pad_array_elements_test.cc
index 05ca2da..441eadc 100644
--- a/src/transform/pad_array_elements_test.cc
+++ b/src/transform/pad_array_elements_test.cc
@@ -46,11 +46,11 @@
 
 TEST_F(PadArrayElementsTest, ArrayAsGlobal) {
   auto* src = R"(
-var<private> arr : [[stride(8)]] array<i32, 4>;
+var<private> arr : @stride(8) array<i32, 4>;
 )";
   auto* expect = R"(
 struct tint_padded_array_element {
-  [[size(8)]]
+  @size(8)
   el : i32;
 }
 
@@ -65,12 +65,12 @@
 TEST_F(PadArrayElementsTest, RuntimeArray) {
   auto* src = R"(
 struct S {
-  rta : [[stride(8)]] array<i32>;
+  rta : @stride(8) array<i32>;
 };
 )";
   auto* expect = R"(
 struct tint_padded_array_element {
-  [[size(8)]]
+  @size(8)
   el : i32;
 }
 
@@ -87,15 +87,15 @@
 TEST_F(PadArrayElementsTest, ArrayFunctionVar) {
   auto* src = R"(
 fn f() {
-  var arr : [[stride(16)]] array<i32, 4>;
-  arr = [[stride(16)]] array<i32, 4>();
-  arr = [[stride(16)]] array<i32, 4>(1, 2, 3, 4);
+  var arr : @stride(16) array<i32, 4>;
+  arr = @stride(16) array<i32, 4>();
+  arr = @stride(16) array<i32, 4>(1, 2, 3, 4);
   let x = arr[3];
 }
 )";
   auto* expect = R"(
 struct tint_padded_array_element {
-  [[size(16)]]
+  @size(16)
   el : i32;
 }
 
@@ -114,13 +114,13 @@
 
 TEST_F(PadArrayElementsTest, ArrayAsParam) {
   auto* src = R"(
-fn f(a : [[stride(12)]] array<i32, 4>) -> i32 {
+fn f(a : @stride(12) array<i32, 4>) -> i32 {
   return a[2];
 }
 )";
   auto* expect = R"(
 struct tint_padded_array_element {
-  [[size(12)]]
+  @size(12)
   el : i32;
 }
 
@@ -137,14 +137,14 @@
 // TODO(crbug.com/tint/781): Cannot parse the stride on the return array type.
 TEST_F(PadArrayElementsTest, DISABLED_ArrayAsReturn) {
   auto* src = R"(
-fn f() -> [[stride(8)]] array<i32, 4> {
+fn f() -> @stride(8) array<i32, 4> {
   return array<i32, 4>(1, 2, 3, 4);
 }
 )";
   auto* expect = R"(
 struct tint_padded_array_element {
   el : i32;
-  [[size(4)]]
+  @size(4)
   padding : u32;
 };
 
@@ -160,7 +160,7 @@
 
 TEST_F(PadArrayElementsTest, ArrayAlias) {
   auto* src = R"(
-type Array = [[stride(16)]] array<i32, 4>;
+type Array = @stride(16) array<i32, 4>;
 
 fn f() {
   var arr : Array;
@@ -173,7 +173,7 @@
 )";
   auto* expect = R"(
 struct tint_padded_array_element {
-  [[size(16)]]
+  @size(16)
   el : i32;
 }
 
@@ -197,25 +197,25 @@
 TEST_F(PadArrayElementsTest, ArraysInStruct) {
   auto* src = R"(
 struct S {
-  a : [[stride(8)]] array<i32, 4>;
-  b : [[stride(8)]] array<i32, 8>;
-  c : [[stride(8)]] array<i32, 4>;
-  d : [[stride(12)]] array<i32, 8>;
+  a : @stride(8) array<i32, 4>;
+  b : @stride(8) array<i32, 8>;
+  c : @stride(8) array<i32, 4>;
+  d : @stride(12) array<i32, 8>;
 };
 )";
   auto* expect = R"(
 struct tint_padded_array_element {
-  [[size(8)]]
+  @size(8)
   el : i32;
 }
 
 struct tint_padded_array_element_1 {
-  [[size(8)]]
+  @size(8)
   el : i32;
 }
 
 struct tint_padded_array_element_2 {
-  [[size(12)]]
+  @size(12)
   el : i32;
 }
 
@@ -235,39 +235,39 @@
 TEST_F(PadArrayElementsTest, ArraysOfArraysInStruct) {
   auto* src = R"(
 struct S {
-  a : [[stride(512)]] array<i32, 4>;
-  b : [[stride(512)]] array<[[stride(32)]] array<i32, 4>, 4>;
-  c : [[stride(512)]] array<[[stride(64)]] array<[[stride(8)]] array<i32, 4>, 4>, 4>;
+  a : @stride(512) array<i32, 4>;
+  b : @stride(512) array<@stride(32) array<i32, 4>, 4>;
+  c : @stride(512) array<@stride(64) array<@stride(8) array<i32, 4>, 4>, 4>;
 };
 )";
   auto* expect = R"(
 struct tint_padded_array_element {
-  [[size(512)]]
+  @size(512)
   el : i32;
 }
 
 struct tint_padded_array_element_2 {
-  [[size(32)]]
+  @size(32)
   el : i32;
 }
 
 struct tint_padded_array_element_1 {
-  [[size(512)]]
+  @size(512)
   el : array<tint_padded_array_element_2, 4u>;
 }
 
 struct tint_padded_array_element_5 {
-  [[size(8)]]
+  @size(8)
   el : i32;
 }
 
 struct tint_padded_array_element_4 {
-  [[size(64)]]
+  @size(64)
   el : array<tint_padded_array_element_5, 4u>;
 }
 
 struct tint_padded_array_element_3 {
-  [[size(512)]]
+  @size(512)
   el : array<tint_padded_array_element_4, 4u>;
 }
 
@@ -286,9 +286,9 @@
 TEST_F(PadArrayElementsTest, AccessArraysOfArraysInStruct) {
   auto* src = R"(
 struct S {
-  a : [[stride(512)]] array<i32, 4>;
-  b : [[stride(512)]] array<[[stride(32)]] array<i32, 4>, 4>;
-  c : [[stride(512)]] array<[[stride(64)]] array<[[stride(8)]] array<i32, 4>, 4>, 4>;
+  a : @stride(512) array<i32, 4>;
+  b : @stride(512) array<@stride(32) array<i32, 4>, 4>;
+  c : @stride(512) array<@stride(64) array<@stride(8) array<i32, 4>, 4>, 4>;
 };
 
 fn f(s : S) -> i32 {
@@ -297,32 +297,32 @@
 )";
   auto* expect = R"(
 struct tint_padded_array_element {
-  [[size(512)]]
+  @size(512)
   el : i32;
 }
 
 struct tint_padded_array_element_2 {
-  [[size(32)]]
+  @size(32)
   el : i32;
 }
 
 struct tint_padded_array_element_1 {
-  [[size(512)]]
+  @size(512)
   el : array<tint_padded_array_element_2, 4u>;
 }
 
 struct tint_padded_array_element_5 {
-  [[size(8)]]
+  @size(8)
   el : i32;
 }
 
 struct tint_padded_array_element_4 {
-  [[size(64)]]
+  @size(64)
   el : array<tint_padded_array_element_5, 4u>;
 }
 
 struct tint_padded_array_element_3 {
-  [[size(512)]]
+  @size(512)
   el : array<tint_padded_array_element_4, 4u>;
 }
 
@@ -346,24 +346,24 @@
   auto* src = R"(
 type T0 = i32;
 
-type T1 = [[stride(8)]] array<i32, 1>;
+type T1 = @stride(8) array<i32, 1>;
 
 type T2 = i32;
 
-fn f1(a : [[stride(8)]] array<i32, 2>) {
+fn f1(a : @stride(8) array<i32, 2>) {
 }
 
 type T3 = i32;
 
 fn f2() {
-  var v : [[stride(8)]] array<i32, 3>;
+  var v : @stride(8) array<i32, 3>;
 }
 )";
   auto* expect = R"(
 type T0 = i32;
 
 struct tint_padded_array_element {
-  [[size(8)]]
+  @size(8)
   el : i32;
 }
 
@@ -372,7 +372,7 @@
 type T2 = i32;
 
 struct tint_padded_array_element_1 {
-  [[size(8)]]
+  @size(8)
   el : i32;
 }
 
@@ -382,7 +382,7 @@
 type T3 = i32;
 
 struct tint_padded_array_element_2 {
-  [[size(8)]]
+  @size(8)
   el : i32;
 }
 
diff --git a/src/transform/remove_phonies_test.cc b/src/transform/remove_phonies_test.cc
index 6d6c86d..6e8a1f1 100644
--- a/src/transform/remove_phonies_test.cc
+++ b/src/transform/remove_phonies_test.cc
@@ -37,7 +37,7 @@
 
 TEST_F(RemovePhoniesTest, NoSideEffects) {
   auto* src = R"(
-[[group(0), binding(0)]] var t : texture_2d<f32>;
+@group(0) @binding(0) var t : texture_2d<f32>;
 
 fn f() {
   var v : i32;
@@ -54,7 +54,7 @@
 )";
 
   auto* expect = R"(
-[[group(0), binding(0)]] var t : texture_2d<f32>;
+@group(0) @binding(0) var t : texture_2d<f32>;
 
 fn f() {
   var v : i32;
@@ -177,7 +177,7 @@
   arr : array<i32>;
 };
 
-[[group(0), binding(0)]] var<storage, read_write> s : S;
+@group(0) @binding(0) var<storage, read_write> s : S;
 
 fn x() -> i32 {
   return 0;
@@ -206,7 +206,7 @@
   arr : array<i32>;
 }
 
-[[group(0), binding(0)]] var<storage, read_write> s : S;
+@group(0) @binding(0) var<storage, read_write> s : S;
 
 fn x() -> i32 {
   return 0;
diff --git a/src/transform/renamer_test.cc b/src/transform/renamer_test.cc
index 7f83043..5ef8ee5 100644
--- a/src/transform/renamer_test.cc
+++ b/src/transform/renamer_test.cc
@@ -46,9 +46,9 @@
   return vert_idx;
 }
 
-[[stage(vertex)]]
-fn entry([[builtin(vertex_index)]] vert_idx : u32
-        ) -> [[builtin(position)]] vec4<f32>  {
+@stage(vertex)
+fn entry(@builtin(vertex_index) vert_idx : u32
+        ) -> @builtin(position) vec4<f32>  {
   ignore(test(vert_idx));
   return vec4<f32>();
 }
@@ -59,8 +59,8 @@
   return tint_symbol_1;
 }
 
-[[stage(vertex)]]
-fn tint_symbol_2([[builtin(vertex_index)]] tint_symbol_1 : u32) -> [[builtin(position)]] vec4<f32> {
+@stage(vertex)
+fn tint_symbol_2(@builtin(vertex_index) tint_symbol_1 : u32) -> @builtin(position) vec4<f32> {
   ignore(tint_symbol(tint_symbol_1));
   return vec4<f32>();
 }
@@ -83,8 +83,8 @@
 
 TEST_F(RenamerTest, PreserveSwizzles) {
   auto* src = R"(
-[[stage(vertex)]]
-fn entry() -> [[builtin(position)]] vec4<f32> {
+@stage(vertex)
+fn entry() -> @builtin(position) vec4<f32> {
   var v : vec4<f32>;
   var rgba : f32;
   var xyzw : f32;
@@ -93,8 +93,8 @@
 )";
 
   auto* expect = R"(
-[[stage(vertex)]]
-fn tint_symbol() -> [[builtin(position)]] vec4<f32> {
+@stage(vertex)
+fn tint_symbol() -> @builtin(position) vec4<f32> {
   var tint_symbol_1 : vec4<f32>;
   var tint_symbol_2 : f32;
   var tint_symbol_3 : f32;
@@ -120,16 +120,16 @@
 
 TEST_F(RenamerTest, PreserveIntrinsics) {
   auto* src = R"(
-[[stage(vertex)]]
-fn entry() -> [[builtin(position)]] vec4<f32> {
+@stage(vertex)
+fn entry() -> @builtin(position) vec4<f32> {
   var blah : vec4<f32>;
   return abs(blah);
 }
 )";
 
   auto* expect = R"(
-[[stage(vertex)]]
-fn tint_symbol() -> [[builtin(position)]] vec4<f32> {
+@stage(vertex)
+fn tint_symbol() -> @builtin(position) vec4<f32> {
   var tint_symbol_1 : vec4<f32>;
   return abs(tint_symbol_1);
 }
@@ -151,7 +151,7 @@
 
 TEST_F(RenamerTest, PreserveBuiltinTypes) {
   auto* src = R"(
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn entry() {
   var a = modf(1.0).whole;
   var b = modf(1.0).fract;
@@ -161,7 +161,7 @@
 )";
 
   auto* expect = R"(
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn tint_symbol() {
   var tint_symbol_1 = modf(1.0).whole;
   var tint_symbol_2 = modf(1.0).fract;
@@ -186,8 +186,8 @@
 
 TEST_F(RenamerTest, AttemptSymbolCollision) {
   auto* src = R"(
-[[stage(vertex)]]
-fn entry() -> [[builtin(position)]] vec4<f32> {
+@stage(vertex)
+fn entry() -> @builtin(position) vec4<f32> {
   var tint_symbol : vec4<f32>;
   var tint_symbol_2 : vec4<f32>;
   var tint_symbol_4 : vec4<f32>;
@@ -196,8 +196,8 @@
 )";
 
   auto* expect = R"(
-[[stage(vertex)]]
-fn tint_symbol() -> [[builtin(position)]] vec4<f32> {
+@stage(vertex)
+fn tint_symbol() -> @builtin(position) vec4<f32> {
   var tint_symbol_1 : vec4<f32>;
   var tint_symbol_2 : vec4<f32>;
   var tint_symbol_3 : vec4<f32>;
@@ -229,7 +229,7 @@
   auto keyword = GetParam();
 
   auto src = R"(
-[[stage(fragment)]]
+@stage(fragment)
 fn frag_main() {
   var )" + keyword +
              R"( : i32;
@@ -237,7 +237,7 @@
 )";
 
   auto* expect = R"(
-[[stage(fragment)]]
+@stage(fragment)
 fn frag_main() {
   var tint_symbol : i32;
 }
@@ -254,7 +254,7 @@
   auto keyword = GetParam();
 
   auto src = R"(
-[[stage(fragment)]]
+@stage(fragment)
 fn frag_main() {
   var )" + keyword +
              R"( : i32;
@@ -262,7 +262,7 @@
 )";
 
   auto* expect = R"(
-[[stage(fragment)]]
+@stage(fragment)
 fn frag_main() {
   var tint_symbol : i32;
 }
@@ -279,7 +279,7 @@
   auto keyword = GetParam();
 
   auto src = R"(
-[[stage(fragment)]]
+@stage(fragment)
 fn frag_main() {
   var )" + keyword +
              R"( : i32;
@@ -287,7 +287,7 @@
 )";
 
   auto* expect = R"(
-[[stage(fragment)]]
+@stage(fragment)
 fn frag_main() {
   var tint_symbol : i32;
 }
diff --git a/src/transform/robustness_test.cc b/src/transform/robustness_test.cc
index a471381..8af6cce 100644
--- a/src/transform/robustness_test.cc
+++ b/src/transform/robustness_test.cc
@@ -178,7 +178,7 @@
   a : array<f32, 0x7fffffff>;
   b : array<f32>;
 };
-[[group(0), binding(0)]] var<storage, read> s : S;
+@group(0) @binding(0) var<storage, read> s : S;
 
 fn f() {
   // Signed
@@ -217,7 +217,7 @@
   b : array<f32>;
 };
 
-[[group(0), binding(0)]] var<storage, read> s : S;
+@group(0) @binding(0) var<storage, read> s : S;
 
 fn f() {
   var i32_a1 : f32 = s.a[2147483646];
@@ -579,7 +579,7 @@
 
 // TODO(dsinclair): Implement when constant_id exists
 TEST_F(RobustnessTest, DISABLED_Vector_Constant_Id_Clamps) {
-  // [[override(1300)]] let idx : i32;
+  // @override(1300) let idx : i32;
   // var a : vec3<f32>
   // var b : f32 = a[idx]
   //
@@ -588,7 +588,7 @@
 
 // TODO(dsinclair): Implement when constant_id exists
 TEST_F(RobustnessTest, DISABLED_Array_Constant_Id_Clamps) {
-  // [[override(1300)]] let idx : i32;
+  // @override(1300) let idx : i32;
   // var a : array<f32, 4>
   // var b : f32 = a[idx]
   //
@@ -597,7 +597,7 @@
 
 // TODO(dsinclair): Implement when constant_id exists
 TEST_F(RobustnessTest, DISABLED_Matrix_Column_Constant_Id_Clamps) {
-  // [[override(1300)]] let idx : i32;
+  // @override(1300) let idx : i32;
   // var a : mat3x2<f32>
   // var b : f32 = a[idx][1]
   //
@@ -606,7 +606,7 @@
 
 // TODO(dsinclair): Implement when constant_id exists
 TEST_F(RobustnessTest, DISABLED_Matrix_Row_Constant_Id_Clamps) {
-  // [[override(1300)]] let idx : i32;
+  // @override(1300) let idx : i32;
   // var a : mat3x2<f32>
   // var b : f32 = a[1][idx]
   //
@@ -619,7 +619,7 @@
   a : f32;
   b : array<f32>;
 };
-[[group(0), binding(0)]] var<storage, read> s : S;
+@group(0) @binding(0) var<storage, read> s : S;
 
 fn f() {
   var d : f32 = s.b[25];
@@ -632,7 +632,7 @@
   b : array<f32>;
 }
 
-[[group(0), binding(0)]] var<storage, read> s : S;
+@group(0) @binding(0) var<storage, read> s : S;
 
 fn f() {
   var d : f32 = s.b[min(25u, (arrayLength(&(s.b)) - 1u))];
@@ -652,14 +652,14 @@
 // Clamp textureLoad() coord, array_index and level values
 TEST_F(RobustnessTest, TextureLoad_Clamp) {
   auto* src = R"(
-[[group(0), binding(0)]] var tex_1d : texture_1d<f32>;
-[[group(0), binding(0)]] var tex_2d : texture_2d<f32>;
-[[group(0), binding(0)]] var tex_2d_arr : texture_2d_array<f32>;
-[[group(0), binding(0)]] var tex_3d : texture_3d<f32>;
-[[group(0), binding(0)]] var tex_ms_2d : texture_multisampled_2d<f32>;
-[[group(0), binding(0)]] var tex_depth_2d : texture_depth_2d;
-[[group(0), binding(0)]] var tex_depth_2d_arr : texture_depth_2d_array;
-[[group(0), binding(0)]] var tex_external : texture_external;
+@group(0) @binding(0) var tex_1d : texture_1d<f32>;
+@group(0) @binding(0) var tex_2d : texture_2d<f32>;
+@group(0) @binding(0) var tex_2d_arr : texture_2d_array<f32>;
+@group(0) @binding(0) var tex_3d : texture_3d<f32>;
+@group(0) @binding(0) var tex_ms_2d : texture_multisampled_2d<f32>;
+@group(0) @binding(0) var tex_depth_2d : texture_depth_2d;
+@group(0) @binding(0) var tex_depth_2d_arr : texture_depth_2d_array;
+@group(0) @binding(0) var tex_external : texture_external;
 
 fn f() {
   var array_idx : i32;
@@ -679,21 +679,21 @@
 
   auto* expect =
       R"(
-[[group(0), binding(0)]] var tex_1d : texture_1d<f32>;
+@group(0) @binding(0) var tex_1d : texture_1d<f32>;
 
-[[group(0), binding(0)]] var tex_2d : texture_2d<f32>;
+@group(0) @binding(0) var tex_2d : texture_2d<f32>;
 
-[[group(0), binding(0)]] var tex_2d_arr : texture_2d_array<f32>;
+@group(0) @binding(0) var tex_2d_arr : texture_2d_array<f32>;
 
-[[group(0), binding(0)]] var tex_3d : texture_3d<f32>;
+@group(0) @binding(0) var tex_3d : texture_3d<f32>;
 
-[[group(0), binding(0)]] var tex_ms_2d : texture_multisampled_2d<f32>;
+@group(0) @binding(0) var tex_ms_2d : texture_multisampled_2d<f32>;
 
-[[group(0), binding(0)]] var tex_depth_2d : texture_depth_2d;
+@group(0) @binding(0) var tex_depth_2d : texture_depth_2d;
 
-[[group(0), binding(0)]] var tex_depth_2d_arr : texture_depth_2d_array;
+@group(0) @binding(0) var tex_depth_2d_arr : texture_depth_2d_array;
 
-[[group(0), binding(0)]] var tex_external : texture_external;
+@group(0) @binding(0) var tex_external : texture_external;
 
 fn f() {
   var array_idx : i32;
@@ -718,13 +718,13 @@
 // Clamp textureStore() coord, array_index and level values
 TEST_F(RobustnessTest, TextureStore_Clamp) {
   auto* src = R"(
-[[group(0), binding(0)]] var tex1d : texture_storage_1d<rgba8sint, write>;
+@group(0) @binding(0) var tex1d : texture_storage_1d<rgba8sint, write>;
 
-[[group(0), binding(1)]] var tex2d : texture_storage_2d<rgba8sint, write>;
+@group(0) @binding(1) var tex2d : texture_storage_2d<rgba8sint, write>;
 
-[[group(0), binding(2)]] var tex2d_arr : texture_storage_2d_array<rgba8sint, write>;
+@group(0) @binding(2) var tex2d_arr : texture_storage_2d_array<rgba8sint, write>;
 
-[[group(0), binding(3)]] var tex3d : texture_storage_3d<rgba8sint, write>;
+@group(0) @binding(3) var tex3d : texture_storage_3d<rgba8sint, write>;
 
 fn f() {
   textureStore(tex1d, 10, vec4<i32>());
@@ -735,13 +735,13 @@
 )";
 
   auto* expect = R"(
-[[group(0), binding(0)]] var tex1d : texture_storage_1d<rgba8sint, write>;
+@group(0) @binding(0) var tex1d : texture_storage_1d<rgba8sint, write>;
 
-[[group(0), binding(1)]] var tex2d : texture_storage_2d<rgba8sint, write>;
+@group(0) @binding(1) var tex2d : texture_storage_2d<rgba8sint, write>;
 
-[[group(0), binding(2)]] var tex2d_arr : texture_storage_2d_array<rgba8sint, write>;
+@group(0) @binding(2) var tex2d_arr : texture_storage_2d_array<rgba8sint, write>;
 
-[[group(0), binding(3)]] var tex3d : texture_storage_3d<rgba8sint, write>;
+@group(0) @binding(3) var tex3d : texture_storage_3d<rgba8sint, write>;
 
 fn f() {
   textureStore(tex1d, clamp(10, i32(), (textureDimensions(tex1d) - i32(1))), vec4<i32>());
@@ -779,7 +779,7 @@
   b : array<f32>;
 };
 
-[[group(0), binding(0)]] var<storage, read> s : S;
+@group(0) @binding(0) var<storage, read> s : S;
 
 let c : u32 = 1u;
 
@@ -796,7 +796,7 @@
   b : array<f32>;
 }
 
-[[group(0), binding(0)]] var<storage, read> s : S;
+@group(0) @binding(0) var<storage, read> s : S;
 
 let c : u32 = 1u;
 
@@ -817,13 +817,13 @@
   a : array<f32, 4>;
   b : array<f32>;
 };
-[[group(0), binding(0)]] var<storage, read> s : S;
+@group(0) @binding(0) var<storage, read> s : S;
 
-type UArr = [[stride(16)]] array<f32, 4>;
+type UArr = @stride(16) array<f32, 4>;
 struct U {
   a : UArr;
 };
-[[group(1), binding(0)]] var<uniform> u : U;
+@group(1) @binding(0) var<uniform> u : U;
 
 fn f() {
   // Signed
@@ -876,15 +876,15 @@
   b : array<f32>;
 }
 
-[[group(0), binding(0)]] var<storage, read> s : S;
+@group(0) @binding(0) var<storage, read> s : S;
 
-type UArr = [[stride(16)]] array<f32, 4>;
+type UArr = @stride(16) array<f32, 4>;
 
 struct U {
   a : UArr;
 }
 
-[[group(1), binding(0)]] var<uniform> u : U;
+@group(1) @binding(0) var<uniform> u : U;
 
 fn f() {
   var i32_sa1 : f32 = s.a[3];
@@ -939,15 +939,15 @@
   b : array<f32>;
 }
 
-[[group(0), binding(0)]] var<storage, read> s : S;
+@group(0) @binding(0) var<storage, read> s : S;
 
-type UArr = [[stride(16)]] array<f32, 4>;
+type UArr = @stride(16) array<f32, 4>;
 
 struct U {
   a : UArr;
 }
 
-[[group(1), binding(0)]] var<uniform> u : U;
+@group(1) @binding(0) var<uniform> u : U;
 
 fn f() {
   var i32_sa1 : f32 = s.a[4];
@@ -1004,15 +1004,15 @@
   b : array<f32>;
 }
 
-[[group(0), binding(0)]] var<storage, read> s : S;
+@group(0) @binding(0) var<storage, read> s : S;
 
-type UArr = [[stride(16)]] array<f32, 4>;
+type UArr = @stride(16) array<f32, 4>;
 
 struct U {
   a : UArr;
 }
 
-[[group(1), binding(0)]] var<uniform> u : U;
+@group(1) @binding(0) var<uniform> u : U;
 
 fn f() {
   var i32_sa1 : f32 = s.a[3];
@@ -1069,15 +1069,15 @@
   b : array<f32>;
 }
 
-[[group(0), binding(0)]] var<storage, read> s : S;
+@group(0) @binding(0) var<storage, read> s : S;
 
-type UArr = [[stride(16)]] array<f32, 4>;
+type UArr = @stride(16) array<f32, 4>;
 
 struct U {
   a : UArr;
 }
 
-[[group(1), binding(0)]] var<uniform> u : U;
+@group(1) @binding(0) var<uniform> u : U;
 
 fn f() {
   var i32_sa1 : f32 = s.a[4];
diff --git a/src/transform/simplify_pointers_test.cc b/src/transform/simplify_pointers_test.cc
index 6b55d32..a9cce89 100644
--- a/src/transform/simplify_pointers_test.cc
+++ b/src/transform/simplify_pointers_test.cc
@@ -249,7 +249,7 @@
   return 1;
 }
 
-[[stage(fragment)]]
+@stage(fragment)
 fn main() {
   var arr = array<f32, 4>();
   for (let a = &arr[foo()]; ;) {
@@ -264,7 +264,7 @@
   return 1;
 }
 
-[[stage(fragment)]]
+@stage(fragment)
 fn main() {
   var arr = array<f32, 4>();
   let a_save = foo();
@@ -350,7 +350,7 @@
   auto* src = R"(
 var<private> a : array<i32, 2>;
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn main() {
   let x = &a;
   var a : i32 = (*x)[0];
@@ -363,7 +363,7 @@
   auto* expect = R"(
 var<private> a : array<i32, 2>;
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn main() {
   var a_1 : i32 = a[0];
   {
diff --git a/src/transform/single_entry_point_test.cc b/src/transform/single_entry_point_test.cc
index b2193b1..6b950fe 100644
--- a/src/transform/single_entry_point_test.cc
+++ b/src/transform/single_entry_point_test.cc
@@ -49,8 +49,8 @@
 
 TEST_F(SingleEntryPointTest, Error_InvalidEntryPoint) {
   auto* src = R"(
-[[stage(vertex)]]
-fn main() -> [[builtin(position)]] vec4<f32> {
+@stage(vertex)
+fn main() -> @builtin(position) vec4<f32> {
   return vec4<f32>();
 }
 )";
@@ -70,7 +70,7 @@
   auto* src = R"(
 fn foo() {}
 
-[[stage(fragment)]]
+@stage(fragment)
 fn main() {}
 )";
 
@@ -87,7 +87,7 @@
 
 TEST_F(SingleEntryPointTest, SingleEntryPoint) {
   auto* src = R"(
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn main() {
 }
 )";
@@ -103,26 +103,26 @@
 
 TEST_F(SingleEntryPointTest, MultipleEntryPoints) {
   auto* src = R"(
-[[stage(vertex)]]
-fn vert_main() -> [[builtin(position)]] vec4<f32> {
+@stage(vertex)
+fn vert_main() -> @builtin(position) vec4<f32> {
   return vec4<f32>();
 }
 
-[[stage(fragment)]]
+@stage(fragment)
 fn frag_main() {
 }
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn comp_main1() {
 }
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn comp_main2() {
 }
 )";
 
   auto* expect = R"(
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn comp_main1() {
 }
 )";
@@ -146,23 +146,23 @@
 
 var<private> d : f32;
 
-[[stage(vertex)]]
-fn vert_main() -> [[builtin(position)]] vec4<f32> {
+@stage(vertex)
+fn vert_main() -> @builtin(position) vec4<f32> {
   a = 0.0;
   return vec4<f32>();
 }
 
-[[stage(fragment)]]
+@stage(fragment)
 fn frag_main() {
   b = 0.0;
 }
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn comp_main1() {
   c = 0.0;
 }
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn comp_main2() {
   d = 0.0;
 }
@@ -171,7 +171,7 @@
   auto* expect = R"(
 var<private> c : f32;
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn comp_main1() {
   c = 0.0;
 }
@@ -196,23 +196,23 @@
 
 let d : f32 = 1.0;
 
-[[stage(vertex)]]
-fn vert_main() -> [[builtin(position)]] vec4<f32> {
+@stage(vertex)
+fn vert_main() -> @builtin(position) vec4<f32> {
   let local_a : f32 = a;
   return vec4<f32>();
 }
 
-[[stage(fragment)]]
+@stage(fragment)
 fn frag_main() {
   let local_b : f32 = b;
 }
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn comp_main1() {
   let local_c : f32 = c;
 }
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn comp_main2() {
   let local_d : f32 = d;
 }
@@ -221,7 +221,7 @@
   auto* expect = R"(
 let c : f32 = 1.0;
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn comp_main1() {
   let local_c : f32 = c;
 }
@@ -240,7 +240,7 @@
   auto* src = R"(
 let size : i32 = 1;
 
-[[stage(compute), workgroup_size(size)]]
+@stage(compute) @workgroup_size(size)
 fn main() {
 }
 )";
@@ -258,32 +258,32 @@
 
 TEST_F(SingleEntryPointTest, OverridableConstants) {
   auto* src = R"(
-[[override(1001)]] let c1 : u32 = 1u;
+@override(1001) let c1 : u32 = 1u;
 [[override]] let c2 : u32 = 1u;
-[[override(0)]] let c3 : u32 = 1u;
-[[override(9999)]] let c4 : u32 = 1u;
+@override(0) let c3 : u32 = 1u;
+@override(9999) let c4 : u32 = 1u;
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn comp_main1() {
     let local_d = c1;
 }
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn comp_main2() {
     let local_d = c2;
 }
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn comp_main3() {
     let local_d = c3;
 }
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn comp_main4() {
     let local_d = c4;
 }
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn comp_main5() {
     let local_d = 1u;
 }
@@ -292,9 +292,9 @@
   {
     SingleEntryPoint::Config cfg("comp_main1");
     auto* expect = R"(
-[[override(1001)]] let c1 : u32 = 1u;
+@override(1001) let c1 : u32 = 1u;
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn comp_main1() {
   let local_d = c1;
 }
@@ -310,9 +310,9 @@
     // The decorator is replaced with the one with explicit id
     // And should not be affected by other constants stripped away
     auto* expect = R"(
-[[override(1)]] let c2 : u32 = 1u;
+@override(1) let c2 : u32 = 1u;
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn comp_main2() {
   let local_d = c2;
 }
@@ -326,9 +326,9 @@
   {
     SingleEntryPoint::Config cfg("comp_main3");
     auto* expect = R"(
-[[override(0)]] let c3 : u32 = 1u;
+@override(0) let c3 : u32 = 1u;
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn comp_main3() {
   let local_d = c3;
 }
@@ -342,9 +342,9 @@
   {
     SingleEntryPoint::Config cfg("comp_main4");
     auto* expect = R"(
-[[override(9999)]] let c4 : u32 = 1u;
+@override(9999) let c4 : u32 = 1u;
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn comp_main4() {
   let local_d = c4;
 }
@@ -358,7 +358,7 @@
   {
     SingleEntryPoint::Config cfg("comp_main5");
     auto* expect = R"(
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn comp_main5() {
   let local_d = 1u;
 }
@@ -391,12 +391,12 @@
   inner_shared();
 }
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn comp_main1() {
   outer1();
 }
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn comp_main2() {
   outer2();
 }
@@ -414,7 +414,7 @@
   inner_shared();
 }
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn comp_main1() {
   outer1();
 }
@@ -465,12 +465,12 @@
   outer2_var = 0.0;
 }
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn comp_main1() {
   outer1();
 }
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn comp_main2() {
   outer2();
 }
@@ -497,7 +497,7 @@
   outer1_var = 0.0;
 }
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn comp_main1() {
   outer1();
 }
diff --git a/src/transform/vectorize_scalar_matrix_constructors_test.cc b/src/transform/vectorize_scalar_matrix_constructors_test.cc
index c603ee2..7e72e4c 100644
--- a/src/transform/vectorize_scalar_matrix_constructors_test.cc
+++ b/src/transform/vectorize_scalar_matrix_constructors_test.cc
@@ -54,7 +54,7 @@
   }
 
   std::string tmpl = R"(
-[[stage(fragment)]]
+@stage(fragment)
 fn main() {
   let m = ${matrix}(${values});
 }
@@ -83,7 +83,7 @@
   }
 
   std::string tmpl = R"(
-[[stage(fragment)]]
+@stage(fragment)
 fn main() {
   let m = ${matrix}(${columns});
 }
diff --git a/src/transform/vertex_pulling_test.cc b/src/transform/vertex_pulling_test.cc
index 10b8ee8..b2482af 100644
--- a/src/transform/vertex_pulling_test.cc
+++ b/src/transform/vertex_pulling_test.cc
@@ -38,8 +38,8 @@
 
 TEST_F(VertexPullingTest, Error_InvalidEntryPoint) {
   auto* src = R"(
-[[stage(vertex)]]
-fn main() -> [[builtin(position)]] vec4<f32> {
+@stage(vertex)
+fn main() -> @builtin(position) vec4<f32> {
   return vec4<f32>();
 }
 )";
@@ -58,7 +58,7 @@
 
 TEST_F(VertexPullingTest, Error_EntryPointWrongStage) {
   auto* src = R"(
-[[stage(fragment)]]
+@stage(fragment)
 fn main() {}
 )";
 
@@ -76,8 +76,8 @@
 
 TEST_F(VertexPullingTest, Error_BadStride) {
   auto* src = R"(
-[[stage(vertex)]]
-fn main([[location(0)]] var_a : f32) -> [[builtin(position)]] vec4<f32> {
+@stage(vertex)
+fn main(@location(0) var_a : f32) -> @builtin(position) vec4<f32> {
   return vec4<f32>(var_a, 0.0, 0.0, 1.0);
 }
 )";
@@ -100,19 +100,19 @@
 
 TEST_F(VertexPullingTest, BasicModule) {
   auto* src = R"(
-[[stage(vertex)]]
-fn main() -> [[builtin(position)]] vec4<f32> {
+@stage(vertex)
+fn main() -> @builtin(position) vec4<f32> {
   return vec4<f32>();
 }
 )";
 
   auto* expect = R"(
 struct TintVertexData {
-  tint_vertex_data : [[stride(4)]] array<u32>;
+  tint_vertex_data : @stride(4) array<u32>;
 }
 
-[[stage(vertex)]]
-fn main() -> [[builtin(position)]] vec4<f32> {
+@stage(vertex)
+fn main() -> @builtin(position) vec4<f32> {
   return vec4<f32>();
 }
 )";
@@ -129,21 +129,21 @@
 
 TEST_F(VertexPullingTest, OneAttribute) {
   auto* src = R"(
-[[stage(vertex)]]
-fn main([[location(0)]] var_a : f32) -> [[builtin(position)]] vec4<f32> {
+@stage(vertex)
+fn main(@location(0) var_a : f32) -> @builtin(position) vec4<f32> {
   return vec4<f32>(var_a, 0.0, 0.0, 1.0);
 }
 )";
 
   auto* expect = R"(
 struct TintVertexData {
-  tint_vertex_data : [[stride(4)]] array<u32>;
+  tint_vertex_data : @stride(4) array<u32>;
 }
 
-[[binding(0), group(4)]] var<storage, read> tint_pulling_vertex_buffer_0 : TintVertexData;
+@binding(0) @group(4) var<storage, read> tint_pulling_vertex_buffer_0 : TintVertexData;
 
-[[stage(vertex)]]
-fn main([[builtin(vertex_index)]] tint_pulling_vertex_index : u32) -> [[builtin(position)]] vec4<f32> {
+@stage(vertex)
+fn main(@builtin(vertex_index) tint_pulling_vertex_index : u32) -> @builtin(position) vec4<f32> {
   var var_a : f32;
   {
     let buffer_array_base_0 = tint_pulling_vertex_index;
@@ -167,21 +167,21 @@
 
 TEST_F(VertexPullingTest, OneInstancedAttribute) {
   auto* src = R"(
-[[stage(vertex)]]
-fn main([[location(0)]] var_a : f32) -> [[builtin(position)]] vec4<f32> {
+@stage(vertex)
+fn main(@location(0) var_a : f32) -> @builtin(position) vec4<f32> {
   return vec4<f32>(var_a, 0.0, 0.0, 1.0);
 }
 )";
 
   auto* expect = R"(
 struct TintVertexData {
-  tint_vertex_data : [[stride(4)]] array<u32>;
+  tint_vertex_data : @stride(4) array<u32>;
 }
 
-[[binding(0), group(4)]] var<storage, read> tint_pulling_vertex_buffer_0 : TintVertexData;
+@binding(0) @group(4) var<storage, read> tint_pulling_vertex_buffer_0 : TintVertexData;
 
-[[stage(vertex)]]
-fn main([[builtin(instance_index)]] tint_pulling_instance_index : u32) -> [[builtin(position)]] vec4<f32> {
+@stage(vertex)
+fn main(@builtin(instance_index) tint_pulling_instance_index : u32) -> @builtin(position) vec4<f32> {
   var var_a : f32;
   {
     let buffer_array_base_0 = tint_pulling_instance_index;
@@ -205,21 +205,21 @@
 
 TEST_F(VertexPullingTest, OneAttributeDifferentOutputSet) {
   auto* src = R"(
-[[stage(vertex)]]
-fn main([[location(0)]] var_a : f32) -> [[builtin(position)]] vec4<f32> {
+@stage(vertex)
+fn main(@location(0) var_a : f32) -> @builtin(position) vec4<f32> {
   return vec4<f32>(var_a, 0.0, 0.0, 1.0);
 }
 )";
 
   auto* expect = R"(
 struct TintVertexData {
-  tint_vertex_data : [[stride(4)]] array<u32>;
+  tint_vertex_data : @stride(4) array<u32>;
 }
 
-[[binding(0), group(5)]] var<storage, read> tint_pulling_vertex_buffer_0 : TintVertexData;
+@binding(0) @group(5) var<storage, read> tint_pulling_vertex_buffer_0 : TintVertexData;
 
-[[stage(vertex)]]
-fn main([[builtin(vertex_index)]] tint_pulling_vertex_index : u32) -> [[builtin(position)]] vec4<f32> {
+@stage(vertex)
+fn main(@builtin(vertex_index) tint_pulling_vertex_index : u32) -> @builtin(position) vec4<f32> {
   var var_a : f32;
   {
     let buffer_array_base_0 = tint_pulling_vertex_index;
@@ -245,29 +245,29 @@
 TEST_F(VertexPullingTest, OneAttribute_Struct) {
   auto* src = R"(
 struct Inputs {
-  [[location(0)]] var_a : f32;
+  @location(0) var_a : f32;
 };
 
-[[stage(vertex)]]
-fn main(inputs : Inputs) -> [[builtin(position)]] vec4<f32> {
+@stage(vertex)
+fn main(inputs : Inputs) -> @builtin(position) vec4<f32> {
   return vec4<f32>(inputs.var_a, 0.0, 0.0, 1.0);
 }
 )";
 
   auto* expect = R"(
 struct TintVertexData {
-  tint_vertex_data : [[stride(4)]] array<u32>;
+  tint_vertex_data : @stride(4) array<u32>;
 }
 
-[[binding(0), group(4)]] var<storage, read> tint_pulling_vertex_buffer_0 : TintVertexData;
+@binding(0) @group(4) var<storage, read> tint_pulling_vertex_buffer_0 : TintVertexData;
 
 struct Inputs {
-  [[location(0)]]
+  @location(0)
   var_a : f32;
 }
 
-[[stage(vertex)]]
-fn main([[builtin(vertex_index)]] tint_pulling_vertex_index : u32) -> [[builtin(position)]] vec4<f32> {
+@stage(vertex)
+fn main(@builtin(vertex_index) tint_pulling_vertex_index : u32) -> @builtin(position) vec4<f32> {
   var inputs : Inputs;
   {
     let buffer_array_base_0 = tint_pulling_vertex_index;
@@ -292,27 +292,27 @@
 // We expect the transform to use an existing builtin variables if it finds them
 TEST_F(VertexPullingTest, ExistingVertexIndexAndInstanceIndex) {
   auto* src = R"(
-[[stage(vertex)]]
-fn main([[location(0)]] var_a : f32,
-        [[location(1)]] var_b : f32,
-        [[builtin(vertex_index)]] custom_vertex_index : u32,
-        [[builtin(instance_index)]] custom_instance_index : u32
-        ) -> [[builtin(position)]] vec4<f32> {
+@stage(vertex)
+fn main(@location(0) var_a : f32,
+        @location(1) var_b : f32,
+        @builtin(vertex_index) custom_vertex_index : u32,
+        @builtin(instance_index) custom_instance_index : u32
+        ) -> @builtin(position) vec4<f32> {
   return vec4<f32>(var_a, var_b, 0.0, 1.0);
 }
 )";
 
   auto* expect = R"(
 struct TintVertexData {
-  tint_vertex_data : [[stride(4)]] array<u32>;
+  tint_vertex_data : @stride(4) array<u32>;
 }
 
-[[binding(0), group(4)]] var<storage, read> tint_pulling_vertex_buffer_0 : TintVertexData;
+@binding(0) @group(4) var<storage, read> tint_pulling_vertex_buffer_0 : TintVertexData;
 
-[[binding(1), group(4)]] var<storage, read> tint_pulling_vertex_buffer_1 : TintVertexData;
+@binding(1) @group(4) var<storage, read> tint_pulling_vertex_buffer_1 : TintVertexData;
 
-[[stage(vertex)]]
-fn main([[builtin(vertex_index)]] custom_vertex_index : u32, [[builtin(instance_index)]] custom_instance_index : u32) -> [[builtin(position)]] vec4<f32> {
+@stage(vertex)
+fn main(@builtin(vertex_index) custom_vertex_index : u32, @builtin(instance_index) custom_instance_index : u32) -> @builtin(position) vec4<f32> {
   var var_a : f32;
   var var_b : f32;
   {
@@ -350,47 +350,47 @@
 TEST_F(VertexPullingTest, ExistingVertexIndexAndInstanceIndex_Struct) {
   auto* src = R"(
 struct Inputs {
-  [[location(0)]] var_a : f32;
-  [[location(1)]] var_b : f32;
-  [[builtin(vertex_index)]] custom_vertex_index : u32;
-  [[builtin(instance_index)]] custom_instance_index : u32;
+  @location(0) var_a : f32;
+  @location(1) var_b : f32;
+  @builtin(vertex_index) custom_vertex_index : u32;
+  @builtin(instance_index) custom_instance_index : u32;
 };
 
-[[stage(vertex)]]
-fn main(inputs : Inputs) -> [[builtin(position)]] vec4<f32> {
+@stage(vertex)
+fn main(inputs : Inputs) -> @builtin(position) vec4<f32> {
   return vec4<f32>(inputs.var_a, inputs.var_b, 0.0, 1.0);
 }
 )";
 
   auto* expect = R"(
 struct TintVertexData {
-  tint_vertex_data : [[stride(4)]] array<u32>;
+  tint_vertex_data : @stride(4) array<u32>;
 }
 
-[[binding(0), group(4)]] var<storage, read> tint_pulling_vertex_buffer_0 : TintVertexData;
+@binding(0) @group(4) var<storage, read> tint_pulling_vertex_buffer_0 : TintVertexData;
 
-[[binding(1), group(4)]] var<storage, read> tint_pulling_vertex_buffer_1 : TintVertexData;
+@binding(1) @group(4) var<storage, read> tint_pulling_vertex_buffer_1 : TintVertexData;
 
 struct tint_symbol {
-  [[builtin(vertex_index)]]
+  @builtin(vertex_index)
   custom_vertex_index : u32;
-  [[builtin(instance_index)]]
+  @builtin(instance_index)
   custom_instance_index : u32;
 }
 
 struct Inputs {
-  [[location(0)]]
+  @location(0)
   var_a : f32;
-  [[location(1)]]
+  @location(1)
   var_b : f32;
-  [[builtin(vertex_index)]]
+  @builtin(vertex_index)
   custom_vertex_index : u32;
-  [[builtin(instance_index)]]
+  @builtin(instance_index)
   custom_instance_index : u32;
 }
 
-[[stage(vertex)]]
-fn main(tint_symbol_1 : tint_symbol) -> [[builtin(position)]] vec4<f32> {
+@stage(vertex)
+fn main(tint_symbol_1 : tint_symbol) -> @builtin(position) vec4<f32> {
   var inputs : Inputs;
   inputs.custom_vertex_index = tint_symbol_1.custom_vertex_index;
   inputs.custom_instance_index = tint_symbol_1.custom_instance_index;
@@ -429,46 +429,46 @@
 TEST_F(VertexPullingTest, ExistingVertexIndexAndInstanceIndex_SeparateStruct) {
   auto* src = R"(
 struct Inputs {
-  [[location(0)]] var_a : f32;
-  [[location(1)]] var_b : f32;
+  @location(0) var_a : f32;
+  @location(1) var_b : f32;
 };
 
 struct Indices {
-  [[builtin(vertex_index)]] custom_vertex_index : u32;
-  [[builtin(instance_index)]] custom_instance_index : u32;
+  @builtin(vertex_index) custom_vertex_index : u32;
+  @builtin(instance_index) custom_instance_index : u32;
 };
 
-[[stage(vertex)]]
-fn main(inputs : Inputs, indices : Indices) -> [[builtin(position)]] vec4<f32> {
+@stage(vertex)
+fn main(inputs : Inputs, indices : Indices) -> @builtin(position) vec4<f32> {
   return vec4<f32>(inputs.var_a, inputs.var_b, 0.0, 1.0);
 }
 )";
 
   auto* expect = R"(
 struct TintVertexData {
-  tint_vertex_data : [[stride(4)]] array<u32>;
+  tint_vertex_data : @stride(4) array<u32>;
 }
 
-[[binding(0), group(4)]] var<storage, read> tint_pulling_vertex_buffer_0 : TintVertexData;
+@binding(0) @group(4) var<storage, read> tint_pulling_vertex_buffer_0 : TintVertexData;
 
-[[binding(1), group(4)]] var<storage, read> tint_pulling_vertex_buffer_1 : TintVertexData;
+@binding(1) @group(4) var<storage, read> tint_pulling_vertex_buffer_1 : TintVertexData;
 
 struct Inputs {
-  [[location(0)]]
+  @location(0)
   var_a : f32;
-  [[location(1)]]
+  @location(1)
   var_b : f32;
 }
 
 struct Indices {
-  [[builtin(vertex_index)]]
+  @builtin(vertex_index)
   custom_vertex_index : u32;
-  [[builtin(instance_index)]]
+  @builtin(instance_index)
   custom_instance_index : u32;
 }
 
-[[stage(vertex)]]
-fn main(indices : Indices) -> [[builtin(position)]] vec4<f32> {
+@stage(vertex)
+fn main(indices : Indices) -> @builtin(position) vec4<f32> {
   var inputs : Inputs;
   {
     let buffer_array_base_0 = indices.custom_vertex_index;
@@ -504,22 +504,22 @@
 
 TEST_F(VertexPullingTest, TwoAttributesSameBuffer) {
   auto* src = R"(
-[[stage(vertex)]]
-fn main([[location(0)]] var_a : f32,
-        [[location(1)]] var_b : vec4<f32>) -> [[builtin(position)]] vec4<f32> {
+@stage(vertex)
+fn main(@location(0) var_a : f32,
+        @location(1) var_b : vec4<f32>) -> @builtin(position) vec4<f32> {
   return vec4<f32>();
 }
 )";
 
   auto* expect = R"(
 struct TintVertexData {
-  tint_vertex_data : [[stride(4)]] array<u32>;
+  tint_vertex_data : @stride(4) array<u32>;
 }
 
-[[binding(0), group(4)]] var<storage, read> tint_pulling_vertex_buffer_0 : TintVertexData;
+@binding(0) @group(4) var<storage, read> tint_pulling_vertex_buffer_0 : TintVertexData;
 
-[[stage(vertex)]]
-fn main([[builtin(vertex_index)]] tint_pulling_vertex_index : u32) -> [[builtin(position)]] vec4<f32> {
+@stage(vertex)
+fn main(@builtin(vertex_index) tint_pulling_vertex_index : u32) -> @builtin(position) vec4<f32> {
   var var_a : f32;
   var var_b : vec4<f32>;
   {
@@ -547,28 +547,28 @@
 
 TEST_F(VertexPullingTest, FloatVectorAttributes) {
   auto* src = R"(
-[[stage(vertex)]]
-fn main([[location(0)]] var_a : vec2<f32>,
-        [[location(1)]] var_b : vec3<f32>,
-        [[location(2)]] var_c : vec4<f32>
-        ) -> [[builtin(position)]] vec4<f32> {
+@stage(vertex)
+fn main(@location(0) var_a : vec2<f32>,
+        @location(1) var_b : vec3<f32>,
+        @location(2) var_c : vec4<f32>
+        ) -> @builtin(position) vec4<f32> {
   return vec4<f32>();
 }
 )";
 
   auto* expect = R"(
 struct TintVertexData {
-  tint_vertex_data : [[stride(4)]] array<u32>;
+  tint_vertex_data : @stride(4) array<u32>;
 }
 
-[[binding(0), group(4)]] var<storage, read> tint_pulling_vertex_buffer_0 : TintVertexData;
+@binding(0) @group(4) var<storage, read> tint_pulling_vertex_buffer_0 : TintVertexData;
 
-[[binding(1), group(4)]] var<storage, read> tint_pulling_vertex_buffer_1 : TintVertexData;
+@binding(1) @group(4) var<storage, read> tint_pulling_vertex_buffer_1 : TintVertexData;
 
-[[binding(2), group(4)]] var<storage, read> tint_pulling_vertex_buffer_2 : TintVertexData;
+@binding(2) @group(4) var<storage, read> tint_pulling_vertex_buffer_2 : TintVertexData;
 
-[[stage(vertex)]]
-fn main([[builtin(vertex_index)]] tint_pulling_vertex_index : u32) -> [[builtin(position)]] vec4<f32> {
+@stage(vertex)
+fn main(@builtin(vertex_index) tint_pulling_vertex_index : u32) -> @builtin(position) vec4<f32> {
   var var_a : vec2<f32>;
   var var_b : vec3<f32>;
   var var_c : vec4<f32>;
@@ -601,9 +601,9 @@
 
 TEST_F(VertexPullingTest, AttemptSymbolCollision) {
   auto* src = R"(
-[[stage(vertex)]]
-fn main([[location(0)]] var_a : f32,
-        [[location(1)]] var_b : vec4<f32>) -> [[builtin(position)]] vec4<f32> {
+@stage(vertex)
+fn main(@location(0) var_a : f32,
+        @location(1) var_b : vec4<f32>) -> @builtin(position) vec4<f32> {
   var tint_pulling_vertex_index : i32;
   var tint_pulling_vertex_buffer_0 : i32;
   var tint_vertex_data : i32;
@@ -614,13 +614,13 @@
 
   auto* expect = R"(
 struct TintVertexData {
-  tint_vertex_data_1 : [[stride(4)]] array<u32>;
+  tint_vertex_data_1 : @stride(4) array<u32>;
 }
 
-[[binding(0), group(4)]] var<storage, read> tint_pulling_vertex_buffer_0_1 : TintVertexData;
+@binding(0) @group(4) var<storage, read> tint_pulling_vertex_buffer_0_1 : TintVertexData;
 
-[[stage(vertex)]]
-fn main([[builtin(vertex_index)]] tint_pulling_vertex_index_1 : u32) -> [[builtin(position)]] vec4<f32> {
+@stage(vertex)
+fn main(@builtin(vertex_index) tint_pulling_vertex_index_1 : u32) -> @builtin(position) vec4<f32> {
   var var_a : f32;
   var var_b : vec4<f32>;
   {
@@ -652,52 +652,52 @@
 
 TEST_F(VertexPullingTest, FormatsAligned) {
   auto* src = R"(
-[[stage(vertex)]]
+@stage(vertex)
 fn main(
-    [[location(0)]] uint8x2 : vec2<u32>,
-    [[location(1)]] uint8x4 : vec4<u32>,
-    [[location(2)]] sint8x2 : vec2<i32>,
-    [[location(3)]] sint8x4 : vec4<i32>,
-    [[location(4)]] unorm8x2 : vec2<f32>,
-    [[location(5)]] unorm8x4 : vec4<f32>,
-    [[location(6)]] snorm8x2 : vec2<f32>,
-    [[location(7)]] snorm8x4 : vec4<f32>,
-    [[location(8)]] uint16x2 : vec2<u32>,
-    [[location(9)]] uint16x4 : vec4<u32>,
-    [[location(10)]] sint16x2 : vec2<i32>,
-    [[location(11)]] sint16x4 : vec4<i32>,
-    [[location(12)]] unorm16x2 : vec2<f32>,
-    [[location(13)]] unorm16x4 : vec4<f32>,
-    [[location(14)]] snorm16x2 : vec2<f32>,
-    [[location(15)]] snorm16x4 : vec4<f32>,
-    [[location(16)]] float16x2 : vec2<f32>,
-    [[location(17)]] float16x4 : vec4<f32>,
-    [[location(18)]] float32 : f32,
-    [[location(19)]] float32x2 : vec2<f32>,
-    [[location(20)]] float32x3 : vec3<f32>,
-    [[location(21)]] float32x4 : vec4<f32>,
-    [[location(22)]] uint32 : u32,
-    [[location(23)]] uint32x2 : vec2<u32>,
-    [[location(24)]] uint32x3 : vec3<u32>,
-    [[location(25)]] uint32x4 : vec4<u32>,
-    [[location(26)]] sint32 : i32,
-    [[location(27)]] sint32x2 : vec2<i32>,
-    [[location(28)]] sint32x3 : vec3<i32>,
-    [[location(29)]] sint32x4 : vec4<i32>
-  ) -> [[builtin(position)]] vec4<f32> {
+    @location(0) uint8x2 : vec2<u32>,
+    @location(1) uint8x4 : vec4<u32>,
+    @location(2) sint8x2 : vec2<i32>,
+    @location(3) sint8x4 : vec4<i32>,
+    @location(4) unorm8x2 : vec2<f32>,
+    @location(5) unorm8x4 : vec4<f32>,
+    @location(6) snorm8x2 : vec2<f32>,
+    @location(7) snorm8x4 : vec4<f32>,
+    @location(8) uint16x2 : vec2<u32>,
+    @location(9) uint16x4 : vec4<u32>,
+    @location(10) sint16x2 : vec2<i32>,
+    @location(11) sint16x4 : vec4<i32>,
+    @location(12) unorm16x2 : vec2<f32>,
+    @location(13) unorm16x4 : vec4<f32>,
+    @location(14) snorm16x2 : vec2<f32>,
+    @location(15) snorm16x4 : vec4<f32>,
+    @location(16) float16x2 : vec2<f32>,
+    @location(17) float16x4 : vec4<f32>,
+    @location(18) float32 : f32,
+    @location(19) float32x2 : vec2<f32>,
+    @location(20) float32x3 : vec3<f32>,
+    @location(21) float32x4 : vec4<f32>,
+    @location(22) uint32 : u32,
+    @location(23) uint32x2 : vec2<u32>,
+    @location(24) uint32x3 : vec3<u32>,
+    @location(25) uint32x4 : vec4<u32>,
+    @location(26) sint32 : i32,
+    @location(27) sint32x2 : vec2<i32>,
+    @location(28) sint32x3 : vec3<i32>,
+    @location(29) sint32x4 : vec4<i32>
+  ) -> @builtin(position) vec4<f32> {
   return vec4<f32>(0.0, 0.0, 0.0, 1.0);
 }
 )";
 
   auto* expect = R"(
 struct TintVertexData {
-  tint_vertex_data : [[stride(4)]] array<u32>;
+  tint_vertex_data : @stride(4) array<u32>;
 }
 
-[[binding(0), group(4)]] var<storage, read> tint_pulling_vertex_buffer_0 : TintVertexData;
+@binding(0) @group(4) var<storage, read> tint_pulling_vertex_buffer_0 : TintVertexData;
 
-[[stage(vertex)]]
-fn main([[builtin(vertex_index)]] tint_pulling_vertex_index : u32) -> [[builtin(position)]] vec4<f32> {
+@stage(vertex)
+fn main(@builtin(vertex_index) tint_pulling_vertex_index : u32) -> @builtin(position) vec4<f32> {
   var uint8x2 : vec2<u32>;
   var uint8x4 : vec4<u32>;
   var sint8x2 : vec2<i32>;
@@ -811,39 +811,39 @@
 
 TEST_F(VertexPullingTest, FormatsStrideUnaligned) {
   auto* src = R"(
-[[stage(vertex)]]
+@stage(vertex)
 fn main(
-    [[location(0)]] uint8x2 : vec2<u32>,
-    [[location(1)]] uint8x4 : vec4<u32>,
-    [[location(2)]] sint8x2 : vec2<i32>,
-    [[location(3)]] sint8x4 : vec4<i32>,
-    [[location(4)]] unorm8x2 : vec2<f32>,
-    [[location(5)]] unorm8x4 : vec4<f32>,
-    [[location(6)]] snorm8x2 : vec2<f32>,
-    [[location(7)]] snorm8x4 : vec4<f32>,
-    [[location(8)]] uint16x2 : vec2<u32>,
-    [[location(9)]] uint16x4 : vec4<u32>,
-    [[location(10)]] sint16x2 : vec2<i32>,
-    [[location(11)]] sint16x4 : vec4<i32>,
-    [[location(12)]] unorm16x2 : vec2<f32>,
-    [[location(13)]] unorm16x4 : vec4<f32>,
-    [[location(14)]] snorm16x2 : vec2<f32>,
-    [[location(15)]] snorm16x4 : vec4<f32>,
-    [[location(16)]] float16x2 : vec2<f32>,
-    [[location(17)]] float16x4 : vec4<f32>,
-    [[location(18)]] float32 : f32,
-    [[location(19)]] float32x2 : vec2<f32>,
-    [[location(20)]] float32x3 : vec3<f32>,
-    [[location(21)]] float32x4 : vec4<f32>,
-    [[location(22)]] uint32 : u32,
-    [[location(23)]] uint32x2 : vec2<u32>,
-    [[location(24)]] uint32x3 : vec3<u32>,
-    [[location(25)]] uint32x4 : vec4<u32>,
-    [[location(26)]] sint32 : i32,
-    [[location(27)]] sint32x2 : vec2<i32>,
-    [[location(28)]] sint32x3 : vec3<i32>,
-    [[location(29)]] sint32x4 : vec4<i32>
-  ) -> [[builtin(position)]] vec4<f32> {
+    @location(0) uint8x2 : vec2<u32>,
+    @location(1) uint8x4 : vec4<u32>,
+    @location(2) sint8x2 : vec2<i32>,
+    @location(3) sint8x4 : vec4<i32>,
+    @location(4) unorm8x2 : vec2<f32>,
+    @location(5) unorm8x4 : vec4<f32>,
+    @location(6) snorm8x2 : vec2<f32>,
+    @location(7) snorm8x4 : vec4<f32>,
+    @location(8) uint16x2 : vec2<u32>,
+    @location(9) uint16x4 : vec4<u32>,
+    @location(10) sint16x2 : vec2<i32>,
+    @location(11) sint16x4 : vec4<i32>,
+    @location(12) unorm16x2 : vec2<f32>,
+    @location(13) unorm16x4 : vec4<f32>,
+    @location(14) snorm16x2 : vec2<f32>,
+    @location(15) snorm16x4 : vec4<f32>,
+    @location(16) float16x2 : vec2<f32>,
+    @location(17) float16x4 : vec4<f32>,
+    @location(18) float32 : f32,
+    @location(19) float32x2 : vec2<f32>,
+    @location(20) float32x3 : vec3<f32>,
+    @location(21) float32x4 : vec4<f32>,
+    @location(22) uint32 : u32,
+    @location(23) uint32x2 : vec2<u32>,
+    @location(24) uint32x3 : vec3<u32>,
+    @location(25) uint32x4 : vec4<u32>,
+    @location(26) sint32 : i32,
+    @location(27) sint32x2 : vec2<i32>,
+    @location(28) sint32x3 : vec3<i32>,
+    @location(29) sint32x4 : vec4<i32>
+  ) -> @builtin(position) vec4<f32> {
   return vec4<f32>(0.0, 0.0, 0.0, 1.0);
 }
 )";
@@ -851,13 +851,13 @@
   auto* expect =
       R"(
 struct TintVertexData {
-  tint_vertex_data : [[stride(4)]] array<u32>;
+  tint_vertex_data : @stride(4) array<u32>;
 }
 
-[[binding(0), group(4)]] var<storage, read> tint_pulling_vertex_buffer_0 : TintVertexData;
+@binding(0) @group(4) var<storage, read> tint_pulling_vertex_buffer_0 : TintVertexData;
 
-[[stage(vertex)]]
-fn main([[builtin(vertex_index)]] tint_pulling_vertex_index : u32) -> [[builtin(position)]] vec4<f32> {
+@stage(vertex)
+fn main(@builtin(vertex_index) tint_pulling_vertex_index : u32) -> @builtin(position) vec4<f32> {
   var uint8x2 : vec2<u32>;
   var uint8x4 : vec4<u32>;
   var sint8x2 : vec2<i32>;
@@ -971,52 +971,52 @@
 
 TEST_F(VertexPullingTest, FormatsWithVectorsResized) {
   auto* src = R"(
-[[stage(vertex)]]
+@stage(vertex)
 fn main(
-    [[location(0)]] uint8x2 : vec3<u32>,
-    [[location(1)]] uint8x4 : vec2<u32>,
-    [[location(2)]] sint8x2 : i32,
-    [[location(3)]] sint8x4 : vec2<i32>,
-    [[location(4)]] unorm8x2 : vec4<f32>,
-    [[location(5)]] unorm8x4 : f32,
-    [[location(6)]] snorm8x2 : vec3<f32>,
-    [[location(7)]] snorm8x4 : f32,
-    [[location(8)]] uint16x2 : vec3<u32>,
-    [[location(9)]] uint16x4 : vec2<u32>,
-    [[location(10)]] sint16x2 : vec4<i32>,
-    [[location(11)]] sint16x4 : i32,
-    [[location(12)]] unorm16x2 : vec3<f32>,
-    [[location(13)]] unorm16x4 : f32,
-    [[location(14)]] snorm16x2 : vec4<f32>,
-    [[location(15)]] snorm16x4 : vec3<f32>,
-    [[location(16)]] float16x2 : vec4<f32>,
-    [[location(17)]] float16x4 : f32,
-    [[location(18)]] float32 : vec4<f32>,
-    [[location(19)]] float32x2 : vec4<f32>,
-    [[location(20)]] float32x3 : vec2<f32>,
-    [[location(21)]] float32x4 : vec3<f32>,
-    [[location(22)]] uint32 : vec3<u32>,
-    [[location(23)]] uint32x2 : vec4<u32>,
-    [[location(24)]] uint32x3 : vec4<u32>,
-    [[location(25)]] uint32x4 : vec2<u32>,
-    [[location(26)]] sint32 : vec4<i32>,
-    [[location(27)]] sint32x2 : vec3<i32>,
-    [[location(28)]] sint32x3 : i32,
-    [[location(29)]] sint32x4 : vec2<i32>
-  ) -> [[builtin(position)]] vec4<f32> {
+    @location(0) uint8x2 : vec3<u32>,
+    @location(1) uint8x4 : vec2<u32>,
+    @location(2) sint8x2 : i32,
+    @location(3) sint8x4 : vec2<i32>,
+    @location(4) unorm8x2 : vec4<f32>,
+    @location(5) unorm8x4 : f32,
+    @location(6) snorm8x2 : vec3<f32>,
+    @location(7) snorm8x4 : f32,
+    @location(8) uint16x2 : vec3<u32>,
+    @location(9) uint16x4 : vec2<u32>,
+    @location(10) sint16x2 : vec4<i32>,
+    @location(11) sint16x4 : i32,
+    @location(12) unorm16x2 : vec3<f32>,
+    @location(13) unorm16x4 : f32,
+    @location(14) snorm16x2 : vec4<f32>,
+    @location(15) snorm16x4 : vec3<f32>,
+    @location(16) float16x2 : vec4<f32>,
+    @location(17) float16x4 : f32,
+    @location(18) float32 : vec4<f32>,
+    @location(19) float32x2 : vec4<f32>,
+    @location(20) float32x3 : vec2<f32>,
+    @location(21) float32x4 : vec3<f32>,
+    @location(22) uint32 : vec3<u32>,
+    @location(23) uint32x2 : vec4<u32>,
+    @location(24) uint32x3 : vec4<u32>,
+    @location(25) uint32x4 : vec2<u32>,
+    @location(26) sint32 : vec4<i32>,
+    @location(27) sint32x2 : vec3<i32>,
+    @location(28) sint32x3 : i32,
+    @location(29) sint32x4 : vec2<i32>
+  ) -> @builtin(position) vec4<f32> {
   return vec4<f32>(0.0, 0.0, 0.0, 1.0);
 }
 )";
 
   auto* expect = R"(
 struct TintVertexData {
-  tint_vertex_data : [[stride(4)]] array<u32>;
+  tint_vertex_data : @stride(4) array<u32>;
 }
 
-[[binding(0), group(4)]] var<storage, read> tint_pulling_vertex_buffer_0 : TintVertexData;
+@binding(0) @group(4) var<storage, read> tint_pulling_vertex_buffer_0 : TintVertexData;
 
-[[stage(vertex)]]
-fn main([[builtin(vertex_index)]] tint_pulling_vertex_index : u32) -> [[builtin(position)]] vec4<f32> {
+@stage(vertex)
+fn main(@builtin(vertex_index) tint_pulling_vertex_index : u32) -> @builtin(position) vec4<f32> {
   var uint8x2 : vec3<u32>;
   var uint8x4 : vec2<u32>;
   var sint8x2 : i32;
diff --git a/src/transform/zero_init_workgroup_memory_test.cc b/src/transform/zero_init_workgroup_memory_test.cc
index 166036e..d23e0af 100644
--- a/src/transform/zero_init_workgroup_memory_test.cc
+++ b/src/transform/zero_init_workgroup_memory_test.cc
@@ -60,7 +60,7 @@
   b = c;
 }
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn f() {
 }
 )";
@@ -75,16 +75,16 @@
   auto* src = R"(
 var<workgroup> v : i32;
 
-[[stage(compute), workgroup_size(1)]]
-fn f([[builtin(local_invocation_index)]] local_idx : u32) {
+@stage(compute) @workgroup_size(1)
+fn f(@builtin(local_invocation_index) local_idx : u32) {
   ignore(v); // Initialization should be inserted above this statement
 }
 )";
   auto* expect = R"(
 var<workgroup> v : i32;
 
-[[stage(compute), workgroup_size(1)]]
-fn f([[builtin(local_invocation_index)]] local_idx : u32) {
+@stage(compute) @workgroup_size(1)
+fn f(@builtin(local_invocation_index) local_idx : u32) {
   {
     v = i32();
   }
@@ -104,10 +104,10 @@
 var<workgroup> v : i32;
 
 struct Params {
-  [[builtin(local_invocation_index)]] local_idx : u32;
+  @builtin(local_invocation_index) local_idx : u32;
 };
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn f(params : Params) {
   ignore(v); // Initialization should be inserted above this statement
 }
@@ -116,11 +116,11 @@
 var<workgroup> v : i32;
 
 struct Params {
-  [[builtin(local_invocation_index)]]
+  @builtin(local_invocation_index)
   local_idx : u32;
 }
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn f(params : Params) {
   {
     v = i32();
@@ -139,7 +139,7 @@
   auto* src = R"(
 var<workgroup> v : i32;
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn f() {
   ignore(v); // Initialization should be inserted above this statement
 }
@@ -147,8 +147,8 @@
   auto* expect = R"(
 var<workgroup> v : i32;
 
-[[stage(compute), workgroup_size(1)]]
-fn f([[builtin(local_invocation_index)]] local_invocation_index : u32) {
+@stage(compute) @workgroup_size(1)
+fn f(@builtin(local_invocation_index) local_invocation_index : u32) {
   {
     v = i32();
   }
@@ -176,8 +176,8 @@
 
 var<workgroup> c : array<S, 32>;
 
-[[stage(compute), workgroup_size(1)]]
-fn f([[builtin(local_invocation_index)]] local_idx : u32) {
+@stage(compute) @workgroup_size(1)
+fn f(@builtin(local_invocation_index) local_idx : u32) {
   ignore(a); // Initialization should be inserted above this statement
   ignore(b);
   ignore(c);
@@ -195,8 +195,8 @@
 
 var<workgroup> c : array<S, 32>;
 
-[[stage(compute), workgroup_size(1)]]
-fn f([[builtin(local_invocation_index)]] local_idx : u32) {
+@stage(compute) @workgroup_size(1)
+fn f(@builtin(local_invocation_index) local_idx : u32) {
   {
     a = i32();
     b.x = i32();
@@ -240,8 +240,8 @@
 
 var<workgroup> c : array<S, 32>;
 
-[[stage(compute), workgroup_size(2, 3)]]
-fn f([[builtin(local_invocation_index)]] local_idx : u32) {
+@stage(compute) @workgroup_size(2, 3)
+fn f(@builtin(local_invocation_index) local_idx : u32) {
   ignore(a); // Initialization should be inserted above this statement
   ignore(b);
   ignore(c);
@@ -259,8 +259,8 @@
 
 var<workgroup> c : array<S, 32>;
 
-[[stage(compute), workgroup_size(2, 3)]]
-fn f([[builtin(local_invocation_index)]] local_idx : u32) {
+@stage(compute) @workgroup_size(2, 3)
+fn f(@builtin(local_invocation_index) local_idx : u32) {
   if ((local_idx < 1u)) {
     a = i32();
     b.x = i32();
@@ -304,10 +304,10 @@
 
 var<workgroup> c : array<S, 32>;
 
-[[override(1)]] let X : i32;
+@override(1) let X : i32;
 
-[[stage(compute), workgroup_size(2, 3, X)]]
-fn f([[builtin(local_invocation_index)]] local_idx : u32) {
+@stage(compute) @workgroup_size(2, 3, X)
+fn f(@builtin(local_invocation_index) local_idx : u32) {
   ignore(a); // Initialization should be inserted above this statement
   ignore(b);
   ignore(c);
@@ -326,10 +326,10 @@
 
 var<workgroup> c : array<S, 32>;
 
-[[override(1)]] let X : i32;
+@override(1) let X : i32;
 
-[[stage(compute), workgroup_size(2, 3, X)]]
-fn f([[builtin(local_invocation_index)]] local_idx : u32) {
+@stage(compute) @workgroup_size(2, 3, X)
+fn f(@builtin(local_invocation_index) local_idx : u32) {
   for(var idx : u32 = local_idx; (idx < 1u); idx = (idx + (u32(X) * 6u))) {
     a = i32();
     b.x = i32();
@@ -374,10 +374,10 @@
 
 var<workgroup> c : array<S, 32>;
 
-[[override(1)]] let X : u32;
+@override(1) let X : u32;
 
-[[stage(compute), workgroup_size(5u, X, 10u)]]
-fn f([[builtin(local_invocation_index)]] local_idx : u32) {
+@stage(compute) @workgroup_size(5u, X, 10u)
+fn f(@builtin(local_invocation_index) local_idx : u32) {
   ignore(a); // Initialization should be inserted above this statement
   ignore(b);
   ignore(c);
@@ -397,10 +397,10 @@
 
 var<workgroup> c : array<S, 32>;
 
-[[override(1)]] let X : u32;
+@override(1) let X : u32;
 
-[[stage(compute), workgroup_size(5u, X, 10u)]]
-fn f([[builtin(local_invocation_index)]] local_idx : u32) {
+@stage(compute) @workgroup_size(5u, X, 10u)
+fn f(@builtin(local_invocation_index) local_idx : u32) {
   for(var idx : u32 = local_idx; (idx < 1u); idx = (idx + (X * 50u))) {
     a = i32();
   }
@@ -462,8 +462,8 @@
 
 var<workgroup> c : array<S, 32>;
 
-[[stage(compute), workgroup_size(1)]]
-fn f([[builtin(local_invocation_id)]] local_invocation_id : vec3<u32>) {
+@stage(compute) @workgroup_size(1)
+fn f(@builtin(local_invocation_id) local_invocation_id : vec3<u32>) {
   ignore(a); // Initialization should be inserted above this statement
   ignore(b);
   ignore(c);
@@ -481,8 +481,8 @@
 
 var<workgroup> c : array<S, 32>;
 
-[[stage(compute), workgroup_size(1)]]
-fn f([[builtin(local_invocation_id)]] local_invocation_id : vec3<u32>, [[builtin(local_invocation_index)]] local_invocation_index : u32) {
+@stage(compute) @workgroup_size(1)
+fn f(@builtin(local_invocation_id) local_invocation_id : vec3<u32>, @builtin(local_invocation_index) local_invocation_index : u32) {
   {
     a = i32();
     b.x = i32();
@@ -525,18 +525,18 @@
 
 var<workgroup> c : array<S, 32>;
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn f1() {
   ignore(a); // Initialization should be inserted above this statement
   ignore(c);
 }
 
-[[stage(compute), workgroup_size(1, 2, 3)]]
-fn f2([[builtin(local_invocation_id)]] local_invocation_id : vec3<u32>) {
+@stage(compute) @workgroup_size(1, 2, 3)
+fn f2(@builtin(local_invocation_id) local_invocation_id : vec3<u32>) {
   ignore(b); // Initialization should be inserted above this statement
 }
 
-[[stage(compute), workgroup_size(4, 5, 6)]]
+@stage(compute) @workgroup_size(4, 5, 6)
 fn f3() {
   ignore(c); // Initialization should be inserted above this statement
   ignore(a);
@@ -554,8 +554,8 @@
 
 var<workgroup> c : array<S, 32>;
 
-[[stage(compute), workgroup_size(1)]]
-fn f1([[builtin(local_invocation_index)]] local_invocation_index : u32) {
+@stage(compute) @workgroup_size(1)
+fn f1(@builtin(local_invocation_index) local_invocation_index : u32) {
   {
     a = i32();
   }
@@ -573,8 +573,8 @@
   ignore(c);
 }
 
-[[stage(compute), workgroup_size(1, 2, 3)]]
-fn f2([[builtin(local_invocation_id)]] local_invocation_id : vec3<u32>, [[builtin(local_invocation_index)]] local_invocation_index_1 : u32) {
+@stage(compute) @workgroup_size(1, 2, 3)
+fn f2(@builtin(local_invocation_id) local_invocation_id : vec3<u32>, @builtin(local_invocation_index) local_invocation_index_1 : u32) {
   if ((local_invocation_index_1 < 1u)) {
     b.x = i32();
   }
@@ -586,8 +586,8 @@
   ignore(b);
 }
 
-[[stage(compute), workgroup_size(4, 5, 6)]]
-fn f3([[builtin(local_invocation_index)]] local_invocation_index_2 : u32) {
+@stage(compute) @workgroup_size(4, 5, 6)
+fn f3(@builtin(local_invocation_index) local_invocation_index_2 : u32) {
   if ((local_invocation_index_2 < 1u)) {
     a = i32();
   }
@@ -623,8 +623,8 @@
   use_v();
 }
 
-[[stage(compute), workgroup_size(1)]]
-fn f([[builtin(local_invocation_index)]] local_idx : u32) {
+@stage(compute) @workgroup_size(1)
+fn f(@builtin(local_invocation_index) local_idx : u32) {
   call_use_v(); // Initialization should be inserted above this statement
 }
 )";
@@ -639,8 +639,8 @@
   use_v();
 }
 
-[[stage(compute), workgroup_size(1)]]
-fn f([[builtin(local_invocation_index)]] local_idx : u32) {
+@stage(compute) @workgroup_size(1)
+fn f(@builtin(local_invocation_index) local_idx : u32) {
   {
     v = i32();
   }
@@ -659,7 +659,7 @@
 var<workgroup> i : atomic<i32>;
 var<workgroup> u : atomic<u32>;
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn f() {
   ignore(i); // Initialization should be inserted above this statement
   ignore(u);
@@ -670,8 +670,8 @@
 
 var<workgroup> u : atomic<u32>;
 
-[[stage(compute), workgroup_size(1)]]
-fn f([[builtin(local_invocation_index)]] local_invocation_index : u32) {
+@stage(compute) @workgroup_size(1)
+fn f(@builtin(local_invocation_index) local_invocation_index : u32) {
   {
     atomicStore(&(i), i32());
     atomicStore(&(u), u32());
@@ -699,7 +699,7 @@
 
 var<workgroup> w : S;
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn f() {
   ignore(w); // Initialization should be inserted above this statement
 }
@@ -715,8 +715,8 @@
 
 var<workgroup> w : S;
 
-[[stage(compute), workgroup_size(1)]]
-fn f([[builtin(local_invocation_index)]] local_invocation_index : u32) {
+@stage(compute) @workgroup_size(1)
+fn f(@builtin(local_invocation_index) local_invocation_index : u32) {
   {
     w.a = i32();
     atomicStore(&(w.i), i32());
@@ -738,7 +738,7 @@
   auto* src = R"(
 var<workgroup> w : array<atomic<u32>, 4>;
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn f() {
   ignore(w); // Initialization should be inserted above this statement
 }
@@ -746,8 +746,8 @@
   auto* expect = R"(
 var<workgroup> w : array<atomic<u32>, 4>;
 
-[[stage(compute), workgroup_size(1)]]
-fn f([[builtin(local_invocation_index)]] local_invocation_index : u32) {
+@stage(compute) @workgroup_size(1)
+fn f(@builtin(local_invocation_index) local_invocation_index : u32) {
   for(var idx : u32 = local_invocation_index; (idx < 4u); idx = (idx + 1u)) {
     let i : u32 = idx;
     atomicStore(&(w[i]), u32());
@@ -774,7 +774,7 @@
 
 var<workgroup> w : array<S, 4>;
 
-[[stage(compute), workgroup_size(1)]]
+@stage(compute) @workgroup_size(1)
 fn f() {
   ignore(w); // Initialization should be inserted above this statement
 }
@@ -790,8 +790,8 @@
 
 var<workgroup> w : array<S, 4>;
 
-[[stage(compute), workgroup_size(1)]]
-fn f([[builtin(local_invocation_index)]] local_invocation_index : u32) {
+@stage(compute) @workgroup_size(1)
+fn f(@builtin(local_invocation_index) local_invocation_index : u32) {
   for(var idx : u32 = local_invocation_index; (idx < 4u); idx = (idx + 1u)) {
     let i_1 : u32 = idx;
     w[i_1].a = i32();