transform/EntryPointIO: Use InsertFront

This removes the need to check for an empty function body and means we
can unconditionally build the function constant initializers, instead
of deferring this work via captured lambdas.

Change-Id: I1571a065fb5885e2b29f0ffb41940a71e5b3f121
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/53281
Auto-Submit: James Price <jrprice@google.com>
Kokoro: Kokoro <noreply+kokoro@google.com>
Reviewed-by: Ben Clayton <bclayton@google.com>
Commit-Queue: James Price <jrprice@google.com>
diff --git a/src/transform/canonicalize_entry_point_io.cc b/src/transform/canonicalize_entry_point_io.cc
index bb1cb71..09bd511 100644
--- a/src/transform/canonicalize_entry_point_io.cc
+++ b/src/transform/canonicalize_entry_point_io.cc
@@ -16,7 +16,6 @@
 
 #include <algorithm>
 #include <utility>
-#include <vector>
 
 #include "src/program_builder.h"
 #include "src/sem/block_statement.h"
@@ -109,11 +108,11 @@
         auto* param_ty = param->Type();
         auto* param_declared_ty = param->Declaration()->type();
 
-        std::function<ast::Expression*()> func_const_initializer;
+        ast::Expression* func_const_initializer = nullptr;
 
         if (auto* str = param_ty->As<sem::Struct>()) {
           // Pull out all struct members and build initializer list.
-          std::vector<Symbol> member_names;
+          ast::ExpressionList init_values;
           for (auto* member : str->Members()) {
             if (member->Type()->Is<sem::Struct>()) {
               TINT_ICE(ctx.dst->Diagnostics()) << "nested pipeline IO struct";
@@ -129,19 +128,12 @@
             auto* member_type = ctx.Clone(member->Declaration()->type());
             new_struct_members.push_back(
                 ctx.dst->Member(member_name, member_type, new_decorations));
-            member_names.emplace_back(member_name);
+            init_values.push_back(
+                ctx.dst->MemberAccessor(new_struct_param_symbol, member_name));
           }
 
-          func_const_initializer = [&ctx, new_struct_param_symbol,
-                                    param_declared_ty, member_names]() {
-            ast::ExpressionList init_values;
-            for (auto name : member_names) {
-              init_values.push_back(
-                  ctx.dst->MemberAccessor(new_struct_param_symbol, name));
-            }
-            return ctx.dst->Construct(ctx.Clone(param_declared_ty),
-                                      init_values);
-          };
+          func_const_initializer =
+              ctx.dst->Construct(ctx.Clone(param_declared_ty), init_values);
         } else {
           ast::DecorationList new_decorations = RemoveDecorations(
               &ctx, param->Declaration()->decorations(),
@@ -151,24 +143,16 @@
               });
           new_struct_members.push_back(ctx.dst->Member(
               param_name, ctx.Clone(param_declared_ty), new_decorations));
-          func_const_initializer = [&ctx, new_struct_param_symbol,
-                                    param_name]() {
-            return ctx.dst->MemberAccessor(new_struct_param_symbol, param_name);
-          };
-        }
-
-        if (func_ast->body()->empty()) {
-          // Don't generate a function-scope const if the function is empty.
-          continue;
+          func_const_initializer =
+              ctx.dst->MemberAccessor(new_struct_param_symbol, param_name);
         }
 
         // Create a function-scope const to replace the parameter.
         // Initialize it with the value extracted from the new struct parameter.
         auto* func_const = ctx.dst->Const(
-            param_name, ctx.Clone(param_declared_ty), func_const_initializer());
-        ctx.InsertBefore(func_ast->body()->statements(),
-                         *func_ast->body()->begin(),
-                         ctx.dst->WrapInStatement(func_const));
+            param_name, ctx.Clone(param_declared_ty), func_const_initializer);
+        ctx.InsertFront(func_ast->body()->statements(),
+                        ctx.dst->WrapInStatement(func_const));
 
         // Replace all uses of the function parameter with the function const.
         for (auto* user : param->Users()) {
diff --git a/src/transform/canonicalize_entry_point_io_test.cc b/src/transform/canonicalize_entry_point_io_test.cc
index 876c21d..e1f32c7 100644
--- a/src/transform/canonicalize_entry_point_io_test.cc
+++ b/src/transform/canonicalize_entry_point_io_test.cc
@@ -107,6 +107,9 @@
 
 [[stage(fragment)]]
 fn frag_main(tint_symbol : tint_symbol_1) {
+  let loc1 : f32 = tint_symbol.loc1;
+  let loc2 : vec4<u32> = tint_symbol.loc2;
+  let coord : vec4<f32> = tint_symbol.coord;
 }
 )";
 
@@ -583,6 +586,10 @@
 
 [[stage(fragment)]]
 fn frag_main(tint_symbol_2 : tint_symbol_3) {
+  let ff : bool = tint_symbol_2.ff;
+  let c : i32 = tint_symbol_2.c;
+  let inputs : FragmentInputExtra = FragmentInputExtra(tint_symbol_2.d, tint_symbol_2.pos, tint_symbol_2.a);
+  let b : u32 = tint_symbol_2.b;
 }
 )";
 
@@ -606,6 +613,7 @@
 
 [[stage(fragment)]]
 fn tint_symbol_1(tint_symbol : tint_symbol_2) {
+  let col : f32 = tint_symbol.col;
 }
 )";