[hlsl-writer] Update all expressions to take a pre stream.

This Cl updates all of the expression methods to accept a pre stream.
The prestream is used to output code _before_ the statement which is
executing the expression. This will allow for unwrapping logical and and
or expressions and emitting them prior to their expression.

Bug: tint:192
Change-Id: Ifb24e7b8964948a3893185710f17177aaec2a2c9
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/27780
Commit-Queue: David Neto <dneto@google.com>
Reviewed-by: David Neto <dneto@google.com>
diff --git a/src/writer/hlsl/generator_impl.cc b/src/writer/hlsl/generator_impl.cc
index a6f454d..5f620c9 100644
--- a/src/writer/hlsl/generator_impl.cc
+++ b/src/writer/hlsl/generator_impl.cc
@@ -210,19 +210,20 @@
   return true;
 }
 
-bool GeneratorImpl::EmitArrayAccessor(std::ostream& out,
+bool GeneratorImpl::EmitArrayAccessor(std::ostream& pre,
+                                      std::ostream& out,
                                       ast::ArrayAccessorExpression* expr) {
   // Handle writing into a storage buffer array
   if (is_storage_buffer_access(expr)) {
-    return EmitStorageBufferAccessor(out, expr, nullptr);
+    return EmitStorageBufferAccessor(pre, out, expr, nullptr);
   }
 
-  if (!EmitExpression(out, expr->array())) {
+  if (!EmitExpression(pre, out, expr->array())) {
     return false;
   }
   out << "[";
 
-  if (!EmitExpression(out, expr->idx_expr())) {
+  if (!EmitExpression(pre, out, expr->idx_expr())) {
     return false;
   }
   out << "]";
@@ -230,7 +231,9 @@
   return true;
 }
 
-bool GeneratorImpl::EmitAs(std::ostream& out, ast::AsExpression* expr) {
+bool GeneratorImpl::EmitAs(std::ostream& pre,
+                           std::ostream& out,
+                           ast::AsExpression* expr) {
   if (!expr->type()->IsF32() && !expr->type()->IsI32() &&
       !expr->type()->IsU32()) {
     error_ = "Unable to do as cast to type " + expr->type()->type_name();
@@ -242,7 +245,7 @@
     return false;
   }
   out << "(";
-  if (!EmitExpression(out, expr->expr())) {
+  if (!EmitExpression(pre, out, expr->expr())) {
     return false;
   }
   out << ")";
@@ -253,12 +256,14 @@
                                ast::AssignmentStatement* stmt) {
   make_indent(out);
 
+  std::ostringstream pre;
+
   // If the LHS is an accessor into a storage buffer then we have to
   // emit a Store operation instead of an ='s.
   if (stmt->lhs()->IsMemberAccessor()) {
     auto* mem = stmt->lhs()->AsMemberAccessor();
     if (is_storage_buffer_access(mem)) {
-      if (!EmitStorageBufferAccessor(out, mem, stmt->rhs())) {
+      if (!EmitStorageBufferAccessor(pre, out, mem, stmt->rhs())) {
         return false;
       }
       out << ";" << std::endl;
@@ -267,7 +272,7 @@
   } else if (stmt->lhs()->IsArrayAccessor()) {
     auto* ary = stmt->lhs()->AsArrayAccessor();
     if (is_storage_buffer_access(ary)) {
-      if (!EmitStorageBufferAccessor(out, ary, stmt->rhs())) {
+      if (!EmitStorageBufferAccessor(pre, out, ary, stmt->rhs())) {
         return false;
       }
       out << ";" << std::endl;
@@ -275,13 +280,13 @@
     }
   }
 
-  if (!EmitExpression(out, stmt->lhs())) {
+  if (!EmitExpression(pre, out, stmt->lhs())) {
     return false;
   }
 
   out << " = ";
 
-  if (!EmitExpression(out, stmt->rhs())) {
+  if (!EmitExpression(pre, out, stmt->rhs())) {
     return false;
   }
 
@@ -290,10 +295,12 @@
   return true;
 }
 
-bool GeneratorImpl::EmitBinary(std::ostream& out, ast::BinaryExpression* expr) {
+bool GeneratorImpl::EmitBinary(std::ostream& pre,
+                               std::ostream& out,
+                               ast::BinaryExpression* expr) {
   out << "(";
 
-  if (!EmitExpression(out, expr->lhs())) {
+  if (!EmitExpression(pre, out, expr->lhs())) {
     return false;
   }
   out << " ";
@@ -366,7 +373,7 @@
   }
   out << " ";
 
-  if (!EmitExpression(out, expr->rhs())) {
+  if (!EmitExpression(pre, out, expr->rhs())) {
     return false;
   }
 
@@ -460,7 +467,9 @@
   return "";
 }
 
-bool GeneratorImpl::EmitCall(std::ostream& out, ast::CallExpression* expr) {
+bool GeneratorImpl::EmitCall(std::ostream& pre,
+                             std::ostream& out,
+                             ast::CallExpression* expr) {
   if (!expr->func()->IsIdentifier()) {
     error_ = "invalid function name";
     return 0;
@@ -515,12 +524,12 @@
       //     out << ", ";
       //   }
 
-      //   if (!EmitExpression(out, params[0].get())) {
+      //   if (!EmitExpression(pre, out, params[0].get())) {
       //     return false;
       //   }
       //   out << " * ";
 
-      //   if (!EmitExpression(out, params[1].get())) {
+      //   if (!EmitExpression(pre, out, params[1].get())) {
       //     return false;
       //   }
       //   out << "[" << i << "]";
@@ -545,7 +554,7 @@
         }
         first = false;
 
-        if (!EmitExpression(out, param.get())) {
+        if (!EmitExpression(pre, out, param.get())) {
           return false;
         }
       }
@@ -596,19 +605,20 @@
       }
       first = false;
 
-      if (!EmitExpression(out, param.get())) {
+      if (!EmitExpression(pre, out, param.get())) {
         return false;
       }
     }
 
     out << ")";
   } else {
-    return EmitImportFunction(out, expr);
+    return EmitImportFunction(pre, out, expr);
   }
   return true;
 }
 
-bool GeneratorImpl::EmitImportFunction(std::ostream& out,
+bool GeneratorImpl::EmitImportFunction(std::ostream& pre,
+                                       std::ostream& out,
                                        ast::CallExpression* expr) {
   auto* ident = expr->func()->AsIdentifier();
 
@@ -717,7 +727,7 @@
     }
     first = false;
 
-    if (!EmitExpression(out, param.get())) {
+    if (!EmitExpression(pre, out, param.get())) {
       return false;
     }
   }
@@ -726,13 +736,15 @@
   return true;
 }
 
-bool GeneratorImpl::EmitCast(std::ostream& out, ast::CastExpression* expr) {
+bool GeneratorImpl::EmitCast(std::ostream& pre,
+                             std::ostream& out,
+                             ast::CastExpression* expr) {
   if (!EmitType(out, expr->type(), "")) {
     return false;
   }
 
   out << "(";
-  if (!EmitExpression(out, expr->expr())) {
+  if (!EmitExpression(pre, out, expr->expr())) {
     return false;
   }
   out << ")";
@@ -783,21 +795,24 @@
   return true;
 }
 
-bool GeneratorImpl::EmitConstructor(std::ostream& out,
+bool GeneratorImpl::EmitConstructor(std::ostream& pre,
+                                    std::ostream& out,
                                     ast::ConstructorExpression* expr) {
   if (expr->IsScalarConstructor()) {
-    return EmitScalarConstructor(out, expr->AsScalarConstructor());
+    return EmitScalarConstructor(pre, out, expr->AsScalarConstructor());
   }
-  return EmitTypeConstructor(out, expr->AsTypeConstructor());
+  return EmitTypeConstructor(pre, out, expr->AsTypeConstructor());
 }
 
 bool GeneratorImpl::EmitScalarConstructor(
+    std::ostream&,
     std::ostream& out,
     ast::ScalarConstructorExpression* expr) {
   return EmitLiteral(out, expr->literal());
 }
 
-bool GeneratorImpl::EmitTypeConstructor(std::ostream& out,
+bool GeneratorImpl::EmitTypeConstructor(std::ostream& pre,
+                                        std::ostream& out,
                                         ast::TypeConstructorExpression* expr) {
   if (expr->type()->IsArray()) {
     out << "{";
@@ -822,7 +837,7 @@
       }
       first = false;
 
-      if (!EmitExpression(out, e.get())) {
+      if (!EmitExpression(pre, out, e.get())) {
         return false;
       }
     }
@@ -850,33 +865,35 @@
   return true;
 }
 
-bool GeneratorImpl::EmitExpression(std::ostream& out, ast::Expression* expr) {
+bool GeneratorImpl::EmitExpression(std::ostream& pre,
+                                   std::ostream& out,
+                                   ast::Expression* expr) {
   if (expr->IsAs()) {
-    return EmitAs(out, expr->AsAs());
+    return EmitAs(pre, out, expr->AsAs());
   }
   if (expr->IsArrayAccessor()) {
-    return EmitArrayAccessor(out, expr->AsArrayAccessor());
+    return EmitArrayAccessor(pre, out, expr->AsArrayAccessor());
   }
   if (expr->IsBinary()) {
-    return EmitBinary(out, expr->AsBinary());
+    return EmitBinary(pre, out, expr->AsBinary());
   }
   if (expr->IsCall()) {
-    return EmitCall(out, expr->AsCall());
+    return EmitCall(pre, out, expr->AsCall());
   }
   if (expr->IsCast()) {
-    return EmitCast(out, expr->AsCast());
+    return EmitCast(pre, out, expr->AsCast());
   }
   if (expr->IsConstructor()) {
-    return EmitConstructor(out, expr->AsConstructor());
+    return EmitConstructor(pre, out, expr->AsConstructor());
   }
   if (expr->IsIdentifier()) {
-    return EmitIdentifier(out, expr->AsIdentifier());
+    return EmitIdentifier(pre, out, expr->AsIdentifier());
   }
   if (expr->IsMemberAccessor()) {
-    return EmitMemberAccessor(out, expr->AsMemberAccessor());
+    return EmitMemberAccessor(pre, out, expr->AsMemberAccessor());
   }
   if (expr->IsUnaryOp()) {
-    return EmitUnaryOp(out, expr->AsUnaryOp());
+    return EmitUnaryOp(pre, out, expr->AsUnaryOp());
   }
 
   error_ = "unknown expression type: " + expr->str();
@@ -891,7 +908,8 @@
           var->storage_class() == ast::StorageClass::kOutput);
 }
 
-bool GeneratorImpl::EmitIdentifier(std::ostream& out,
+bool GeneratorImpl::EmitIdentifier(std::ostream&,
+                                   std::ostream& out,
                                    ast::IdentifierExpression* expr) {
   auto* ident = expr->AsIdentifier();
   if (ident->has_path()) {
@@ -922,8 +940,9 @@
 bool GeneratorImpl::EmitIf(std::ostream& out, ast::IfStatement* stmt) {
   make_indent(out);
 
+  std::ostringstream pre;
   out << "if (";
-  if (!EmitExpression(out, stmt->condition())) {
+  if (!EmitExpression(pre, out, stmt->condition())) {
     return false;
   }
   out << ") ";
@@ -943,9 +962,10 @@
 }
 
 bool GeneratorImpl::EmitElse(std::ostream& out, ast::ElseStatement* stmt) {
+  std::ostringstream pre;
   if (stmt->HasCondition()) {
     out << " else if (";
-    if (!EmitExpression(out, stmt->condition())) {
+    if (!EmitExpression(pre, out, stmt->condition())) {
       return false;
     }
     out << ") ";
@@ -1511,7 +1531,8 @@
       auto* var = s->AsVariableDecl()->variable();
       out << var->name() << " = ";
       if (var->constructor() != nullptr) {
-        if (!EmitExpression(out, var->constructor())) {
+        std::ostringstream pre;
+        if (!EmitExpression(pre, out, var->constructor())) {
           return false;
         }
       } else {
@@ -1614,7 +1635,8 @@
         return "";
       }
       out << " * ";
-      if (!EmitExpression(out, ary->idx_expr())) {
+      std::ostringstream pre;
+      if (!EmitExpression(pre, out, ary->idx_expr())) {
         return "";
       }
       out << ")";
@@ -1636,7 +1658,8 @@
 // TODO(dsinclair): Need to support loading through a pointer. The pointer is
 // just a memory address in the storage buffer, so need to do the correct
 // calculation.
-bool GeneratorImpl::EmitStorageBufferAccessor(std::ostream& out,
+bool GeneratorImpl::EmitStorageBufferAccessor(std::ostream& pre,
+                                              std::ostream& out,
                                               ast::Expression* expr,
                                               ast::Expression* rhs) {
   auto* result_type = expr->result_type()->UnwrapAliasPtrAlias();
@@ -1685,7 +1708,7 @@
 
       auto name = generate_name(kTempNamePrefix);
       out << " " << name << " = ";
-      if (!EmitExpression(out, rhs)) {
+      if (!EmitExpression(pre, out, rhs)) {
         return false;
       }
       out << ";" << std::endl;
@@ -1723,7 +1746,7 @@
   out << buffer_name << "." << access_method << "(" << idx;
   if (is_store) {
     out << ", asuint(";
-    if (!EmitExpression(out, rhs)) {
+    if (!EmitExpression(pre, out, rhs)) {
       return false;
     }
     out << ")";
@@ -1786,20 +1809,21 @@
   return false;
 }
 
-bool GeneratorImpl::EmitMemberAccessor(std::ostream& out,
+bool GeneratorImpl::EmitMemberAccessor(std::ostream& pre,
+                                       std::ostream& out,
                                        ast::MemberAccessorExpression* expr) {
   // Look for storage buffer accesses as we have to convert them into Load
   // expressions. Stores will be identified in the assignment emission and a
   // member accessor store of a storage buffer will not get here.
   if (is_storage_buffer_access(expr)) {
-    return EmitStorageBufferAccessor(out, expr, nullptr);
+    return EmitStorageBufferAccessor(pre, out, expr, nullptr);
   }
 
-  if (!EmitExpression(out, expr->structure())) {
+  if (!EmitExpression(pre, out, expr->structure())) {
     return false;
   }
   out << ".";
-  return EmitExpression(out, expr->member());
+  return EmitExpression(pre, out, expr->member());
 }
 
 bool GeneratorImpl::EmitReturn(std::ostream& out, ast::ReturnStatement* stmt) {
@@ -1814,7 +1838,8 @@
     }
   } else if (stmt->has_value()) {
     out << " ";
-    if (!EmitExpression(out, stmt->value())) {
+    std::ostringstream pre;
+    if (!EmitExpression(pre, out, stmt->value())) {
       return false;
     }
   }
@@ -1834,7 +1859,8 @@
   }
   if (stmt->IsCall()) {
     make_indent(out);
-    if (!EmitCall(out, stmt->AsCall()->expr())) {
+    std::ostringstream pre;
+    if (!EmitCall(pre, out, stmt->AsCall()->expr())) {
       return false;
     }
     out << ";" << std::endl;
@@ -1874,8 +1900,9 @@
 bool GeneratorImpl::EmitSwitch(std::ostream& out, ast::SwitchStatement* stmt) {
   make_indent(out);
 
+  std::ostringstream pre;
   out << "switch(";
-  if (!EmitExpression(out, stmt->condition())) {
+  if (!EmitExpression(pre, out, stmt->condition())) {
     return false;
   }
   out << ") {" << std::endl;
@@ -1994,7 +2021,8 @@
   return true;
 }
 
-bool GeneratorImpl::EmitUnaryOp(std::ostream& out,
+bool GeneratorImpl::EmitUnaryOp(std::ostream& pre,
+                                std::ostream& out,
                                 ast::UnaryOpExpression* expr) {
   switch (expr->op()) {
     case ast::UnaryOp::kNot:
@@ -2006,7 +2034,7 @@
   }
   out << "(";
 
-  if (!EmitExpression(out, expr->expr())) {
+  if (!EmitExpression(pre, out, expr->expr())) {
     return false;
   }
 
@@ -2038,7 +2066,9 @@
 
   if (!skip_constructor && var->constructor() != nullptr) {
     out << " = ";
-    if (!EmitExpression(out, var->constructor())) {
+
+    std::ostringstream pre;
+    if (!EmitExpression(pre, out, var->constructor())) {
       return false;
     }
   }
@@ -2070,7 +2100,9 @@
 
   if (var->constructor() != nullptr) {
     out << " = ";
-    if (!EmitExpression(out, var->constructor())) {
+
+    std::ostringstream pre;
+    if (!EmitExpression(pre, out, var->constructor())) {
       return false;
     }
   }
diff --git a/src/writer/hlsl/generator_impl.h b/src/writer/hlsl/generator_impl.h
index ba3f60b..4c261f5 100644
--- a/src/writer/hlsl/generator_impl.h
+++ b/src/writer/hlsl/generator_impl.h
@@ -62,25 +62,32 @@
   /// @returns true if the alias was emitted
   bool EmitAliasType(std::ostream& out, const ast::type::AliasType* alias);
   /// Handles an array accessor expression
-  /// @param out the output stream
+  /// @param pre the preamble for the expression stream
+  /// @param out the output of the expression stream
   /// @param expr the expression to emit
   /// @returns true if the array accessor was emitted
-  bool EmitArrayAccessor(std::ostream& out, ast::ArrayAccessorExpression* expr);
+  bool EmitArrayAccessor(std::ostream& pre,
+                         std::ostream& out,
+                         ast::ArrayAccessorExpression* expr);
   /// Handles generating an as expression
-  /// @param out the output stream
+  /// @param pre the preamble for the expression stream
+  /// @param out the output of the expression stream
   /// @param expr the as expression
   /// @returns true if the as was emitted
-  bool EmitAs(std::ostream& out, ast::AsExpression* expr);
+  bool EmitAs(std::ostream& pre, std::ostream& out, ast::AsExpression* expr);
   /// Handles an assignment statement
   /// @param out the output stream
   /// @param stmt the statement to emit
   /// @returns true if the statement was emitted successfully
   bool EmitAssign(std::ostream& out, ast::AssignmentStatement* stmt);
   /// Handles generating a binary expression
-  /// @param out the output stream
+  /// @param pre the preamble for the expression stream
+  /// @param out the output of the expression stream
   /// @param expr the binary expression
   /// @returns true if the expression was emitted, false otherwise
-  bool EmitBinary(std::ostream& out, ast::BinaryExpression* expr);
+  bool EmitBinary(std::ostream& pre,
+                  std::ostream& out,
+                  ast::BinaryExpression* expr);
   /// Handles a block statement
   /// @param out the output stream
   /// @param stmt the statement to emit
@@ -103,41 +110,54 @@
   /// @returns true if the statement was emitted successfully
   bool EmitBreak(std::ostream& out, ast::BreakStatement* stmt);
   /// Handles generating a call expression
-  /// @param out the output stream
+  /// @param pre the preamble for the expression stream
+  /// @param out the output of the expression stream
   /// @param expr the call expression
   /// @returns true if the call expression is emitted
-  bool EmitCall(std::ostream& out, ast::CallExpression* expr);
+  bool EmitCall(std::ostream& pre,
+                std::ostream& out,
+                ast::CallExpression* expr);
   /// Handles a case statement
   /// @param out the output stream
   /// @param stmt the statement
   /// @returns true if the statment was emitted successfully
   bool EmitCase(std::ostream& out, ast::CaseStatement* stmt);
   /// Handles generating a cast expression
-  /// @param out the output stream
+  /// @param pre the preamble for the expression stream
+  /// @param out the output of the expression stream
   /// @param expr the cast expression
   /// @returns true if the cast was emitted
-  bool EmitCast(std::ostream& out, ast::CastExpression* expr);
+  bool EmitCast(std::ostream& pre,
+                std::ostream& out,
+                ast::CastExpression* expr);
   /// Handles generating constructor expressions
-  /// @param out the output stream
+  /// @param pre the preamble for the expression stream
+  /// @param out the output of the expression stream
   /// @param expr the constructor expression
   /// @returns true if the expression was emitted
-  bool EmitConstructor(std::ostream& out, ast::ConstructorExpression* expr);
+  bool EmitConstructor(std::ostream& pre,
+                       std::ostream& out,
+                       ast::ConstructorExpression* expr);
   /// Handles generating a discard statement
   /// @param out the output stream
   /// @param stmt the discard statement
   /// @returns true if the statement was successfully emitted
   bool EmitDiscard(std::ostream& out, ast::DiscardStatement* stmt);
   /// Handles generating a scalar constructor
-  /// @param out the output stream
+  /// @param pre the preamble for the expression stream
+  /// @param out the output of the expression stream
   /// @param expr the scalar constructor expression
   /// @returns true if the scalar constructor is emitted
-  bool EmitScalarConstructor(std::ostream& out,
+  bool EmitScalarConstructor(std::ostream& pre,
+                             std::ostream& out,
                              ast::ScalarConstructorExpression* expr);
   /// Handles emitting a type constructor
-  /// @param out the output stream
+  /// @param pre the preamble for the expression stream
+  /// @param out the output of the expression stream
   /// @param expr the type constructor expression
   /// @returns true if the constructor is emitted
-  bool EmitTypeConstructor(std::ostream& out,
+  bool EmitTypeConstructor(std::ostream& pre,
+                           std::ostream& out,
                            ast::TypeConstructorExpression* expr);
   /// Handles a continue statement
   /// @param out the output stream
@@ -150,10 +170,13 @@
   /// @returns true if the statement was emitted
   bool EmitElse(std::ostream& out, ast::ElseStatement* stmt);
   /// Handles generate an Expression
-  /// @param out the output stream
+  /// @param pre the preamble for the expression stream
+  /// @param out the output of the expression stream
   /// @param expr the expression
   /// @returns true if the expression was emitted
-  bool EmitExpression(std::ostream& out, ast::Expression* expr);
+  bool EmitExpression(std::ostream& pre,
+                      std::ostream& out,
+                      ast::Expression* expr);
   /// Handles generating a function
   /// @param out the output stream
   /// @param func the function to generate
@@ -186,10 +209,13 @@
   /// @returns true if the statement was successfully emitted
   bool EmitIf(std::ostream& out, ast::IfStatement* stmt);
   /// Handles genreating an import expression
-  /// @param out the output stream
+  /// @param pre the preamble for the expression stream
+  /// @param out the output of the expression stream
   /// @param expr the expression
   /// @returns true if the expression was successfully emitted.
-  bool EmitImportFunction(std::ostream& out, ast::CallExpression* expr);
+  bool EmitImportFunction(std::ostream& pre,
+                          std::ostream& out,
+                          ast::CallExpression* expr);
   /// Handles a literal
   /// @param out the output stream
   /// @param lit the literal to emit
@@ -201,22 +227,29 @@
   /// @returns true if the statement was emitted
   bool EmitLoop(std::ostream& out, ast::LoopStatement* stmt);
   /// Handles generating an identifier expression
-  /// @param out the output stream
+  /// @param pre the preamble for the expression stream
+  /// @param out the output of the expression stream
   /// @param expr the identifier expression
   /// @returns true if the identifeir was emitted
-  bool EmitIdentifier(std::ostream& out, ast::IdentifierExpression* expr);
+  bool EmitIdentifier(std::ostream& pre,
+                      std::ostream& out,
+                      ast::IdentifierExpression* expr);
   /// Handles a member accessor expression
-  /// @param out the output stream
+  /// @param pre the preamble for the expression stream
+  /// @param out the output of the expression stream
   /// @param expr the member accessor expression
   /// @returns true if the member accessor was emitted
-  bool EmitMemberAccessor(std::ostream& out,
+  bool EmitMemberAccessor(std::ostream& pre,
+                          std::ostream& out,
                           ast::MemberAccessorExpression* expr);
   /// Handles a storage buffer accessor expression
-  /// @param out the output stream
+  /// @param pre the preamble for the expression stream
+  /// @param out the output of the expression stream
   /// @param expr the storage buffer accessor expression
   /// @param rhs the right side of a store expression. Set to nullptr for a load
   /// @returns true if the storage buffer accessor was emitted
-  bool EmitStorageBufferAccessor(std::ostream& out,
+  bool EmitStorageBufferAccessor(std::ostream& pre,
+                                 std::ostream& out,
                                  ast::Expression* expr,
                                  ast::Expression* rhs);
   /// Handles return statements
@@ -243,10 +276,13 @@
                 ast::type::Type* type,
                 const std::string& name);
   /// Handles a unary op expression
-  /// @param out the output stream
+  /// @param pre the preamble for the expression stream
+  /// @param out the output of the expression stream
   /// @param expr the expression to emit
   /// @returns true if the expression was emitted
-  bool EmitUnaryOp(std::ostream& out, ast::UnaryOpExpression* expr);
+  bool EmitUnaryOp(std::ostream& pre,
+                   std::ostream& out,
+                   ast::UnaryOpExpression* expr);
   /// Emits the zero value for the given type
   /// @param out the output stream
   /// @param type the type to emit the value for
diff --git a/src/writer/hlsl/generator_impl_array_accessor_test.cc b/src/writer/hlsl/generator_impl_array_accessor_test.cc
index 0462efe..5b488d4 100644
--- a/src/writer/hlsl/generator_impl_array_accessor_test.cc
+++ b/src/writer/hlsl/generator_impl_array_accessor_test.cc
@@ -37,7 +37,7 @@
 
   ast::ArrayAccessorExpression expr(std::move(ary), std::move(idx));
 
-  ASSERT_TRUE(gen().EmitExpression(out(), &expr)) << gen().error();
+  ASSERT_TRUE(gen().EmitExpression(pre(), out(), &expr)) << gen().error();
   EXPECT_EQ(result(), "ary[5]");
 }
 
@@ -47,7 +47,7 @@
 
   ast::ArrayAccessorExpression expr(std::move(ary), std::move(idx));
 
-  ASSERT_TRUE(gen().EmitExpression(out(), &expr)) << gen().error();
+  ASSERT_TRUE(gen().EmitExpression(pre(), out(), &expr)) << gen().error();
   EXPECT_EQ(result(), "ary[idx]");
 }
 
diff --git a/src/writer/hlsl/generator_impl_as_test.cc b/src/writer/hlsl/generator_impl_as_test.cc
index 7eb334d..663b1db 100644
--- a/src/writer/hlsl/generator_impl_as_test.cc
+++ b/src/writer/hlsl/generator_impl_as_test.cc
@@ -34,7 +34,7 @@
   auto id = std::make_unique<ast::IdentifierExpression>("id");
   ast::AsExpression as(&f32, std::move(id));
 
-  ASSERT_TRUE(gen().EmitExpression(out(), &as)) << gen().error();
+  ASSERT_TRUE(gen().EmitExpression(pre(), out(), &as)) << gen().error();
   EXPECT_EQ(result(), "asfloat(id)");
 }
 
@@ -43,7 +43,7 @@
   auto id = std::make_unique<ast::IdentifierExpression>("id");
   ast::AsExpression as(&i32, std::move(id));
 
-  ASSERT_TRUE(gen().EmitExpression(out(), &as)) << gen().error();
+  ASSERT_TRUE(gen().EmitExpression(pre(), out(), &as)) << gen().error();
   EXPECT_EQ(result(), "asint(id)");
 }
 
@@ -52,7 +52,7 @@
   auto id = std::make_unique<ast::IdentifierExpression>("id");
   ast::AsExpression as(&u32, std::move(id));
 
-  ASSERT_TRUE(gen().EmitExpression(out(), &as)) << gen().error();
+  ASSERT_TRUE(gen().EmitExpression(pre(), out(), &as)) << gen().error();
   EXPECT_EQ(result(), "asuint(id)");
 }
 
diff --git a/src/writer/hlsl/generator_impl_binary_test.cc b/src/writer/hlsl/generator_impl_binary_test.cc
index 2da3ad9..024aa42 100644
--- a/src/writer/hlsl/generator_impl_binary_test.cc
+++ b/src/writer/hlsl/generator_impl_binary_test.cc
@@ -42,7 +42,7 @@
 
   ast::BinaryExpression expr(params.op, std::move(left), std::move(right));
 
-  ASSERT_TRUE(gen().EmitExpression(out(), &expr)) << gen().error();
+  ASSERT_TRUE(gen().EmitExpression(pre(), out(), &expr)) << gen().error();
   EXPECT_EQ(result(), params.result);
 }
 INSTANTIATE_TEST_SUITE_P(
diff --git a/src/writer/hlsl/generator_impl_call_test.cc b/src/writer/hlsl/generator_impl_call_test.cc
index cbff0a8..63070e0 100644
--- a/src/writer/hlsl/generator_impl_call_test.cc
+++ b/src/writer/hlsl/generator_impl_call_test.cc
@@ -39,7 +39,7 @@
                                               &void_type);
   mod()->AddFunction(std::move(func));
 
-  ASSERT_TRUE(gen().EmitExpression(out(), &call)) << gen().error();
+  ASSERT_TRUE(gen().EmitExpression(pre(), out(), &call)) << gen().error();
   EXPECT_EQ(result(), "my_func()");
 }
 
@@ -56,7 +56,7 @@
                                               &void_type);
   mod()->AddFunction(std::move(func));
 
-  ASSERT_TRUE(gen().EmitExpression(out(), &call)) << gen().error();
+  ASSERT_TRUE(gen().EmitExpression(pre(), out(), &call)) << gen().error();
   EXPECT_EQ(result(), "my_func(param1, param2)");
 }
 
diff --git a/src/writer/hlsl/generator_impl_cast_test.cc b/src/writer/hlsl/generator_impl_cast_test.cc
index 723f374..e646e07 100644
--- a/src/writer/hlsl/generator_impl_cast_test.cc
+++ b/src/writer/hlsl/generator_impl_cast_test.cc
@@ -33,7 +33,7 @@
   auto id = std::make_unique<ast::IdentifierExpression>("id");
   ast::CastExpression cast(&f32, std::move(id));
 
-  ASSERT_TRUE(gen().EmitExpression(out(), &cast)) << gen().error();
+  ASSERT_TRUE(gen().EmitExpression(pre(), out(), &cast)) << gen().error();
   EXPECT_EQ(result(), "float(id)");
 }
 
@@ -44,7 +44,7 @@
   auto id = std::make_unique<ast::IdentifierExpression>("id");
   ast::CastExpression cast(&vec3, std::move(id));
 
-  ASSERT_TRUE(gen().EmitExpression(out(), &cast)) << gen().error();
+  ASSERT_TRUE(gen().EmitExpression(pre(), out(), &cast)) << gen().error();
   EXPECT_EQ(result(), "vector<float, 3>(id)");
 }
 
diff --git a/src/writer/hlsl/generator_impl_constructor_test.cc b/src/writer/hlsl/generator_impl_constructor_test.cc
index 6e3ef5e..6f47277 100644
--- a/src/writer/hlsl/generator_impl_constructor_test.cc
+++ b/src/writer/hlsl/generator_impl_constructor_test.cc
@@ -40,7 +40,7 @@
   auto lit = std::make_unique<ast::BoolLiteral>(&bool_type, false);
   ast::ScalarConstructorExpression expr(std::move(lit));
 
-  ASSERT_TRUE(gen().EmitConstructor(out(), &expr)) << gen().error();
+  ASSERT_TRUE(gen().EmitConstructor(pre(), out(), &expr)) << gen().error();
   EXPECT_EQ(result(), "false");
 }
 
@@ -49,7 +49,7 @@
   auto lit = std::make_unique<ast::SintLiteral>(&i32, -12345);
   ast::ScalarConstructorExpression expr(std::move(lit));
 
-  ASSERT_TRUE(gen().EmitConstructor(out(), &expr)) << gen().error();
+  ASSERT_TRUE(gen().EmitConstructor(pre(), out(), &expr)) << gen().error();
   EXPECT_EQ(result(), "-12345");
 }
 
@@ -58,7 +58,7 @@
   auto lit = std::make_unique<ast::UintLiteral>(&u32, 56779);
   ast::ScalarConstructorExpression expr(std::move(lit));
 
-  ASSERT_TRUE(gen().EmitConstructor(out(), &expr)) << gen().error();
+  ASSERT_TRUE(gen().EmitConstructor(pre(), out(), &expr)) << gen().error();
   EXPECT_EQ(result(), "56779u");
 }
 
@@ -68,7 +68,7 @@
   auto lit = std::make_unique<ast::FloatLiteral>(&f32, float((1 << 30) - 4));
   ast::ScalarConstructorExpression expr(std::move(lit));
 
-  ASSERT_TRUE(gen().EmitConstructor(out(), &expr)) << gen().error();
+  ASSERT_TRUE(gen().EmitConstructor(pre(), out(), &expr)) << gen().error();
   EXPECT_EQ(result(), "1.07374182e+09f");
 }
 
@@ -82,7 +82,7 @@
 
   ast::TypeConstructorExpression expr(&f32, std::move(values));
 
-  ASSERT_TRUE(gen().EmitConstructor(out(), &expr)) << gen().error();
+  ASSERT_TRUE(gen().EmitConstructor(pre(), out(), &expr)) << gen().error();
   EXPECT_EQ(result(), "float(-1.20000004e-05f)");
 }
 
@@ -96,7 +96,7 @@
 
   ast::TypeConstructorExpression expr(&b, std::move(values));
 
-  ASSERT_TRUE(gen().EmitConstructor(out(), &expr)) << gen().error();
+  ASSERT_TRUE(gen().EmitConstructor(pre(), out(), &expr)) << gen().error();
   EXPECT_EQ(result(), "bool(true)");
 }
 
@@ -110,7 +110,7 @@
 
   ast::TypeConstructorExpression expr(&i32, std::move(values));
 
-  ASSERT_TRUE(gen().EmitConstructor(out(), &expr)) << gen().error();
+  ASSERT_TRUE(gen().EmitConstructor(pre(), out(), &expr)) << gen().error();
   EXPECT_EQ(result(), "int(-12345)");
 }
 
@@ -124,7 +124,7 @@
 
   ast::TypeConstructorExpression expr(&u32, std::move(values));
 
-  ASSERT_TRUE(gen().EmitConstructor(out(), &expr)) << gen().error();
+  ASSERT_TRUE(gen().EmitConstructor(pre(), out(), &expr)) << gen().error();
   EXPECT_EQ(result(), "uint(12345u)");
 }
 
@@ -145,7 +145,7 @@
 
   ast::TypeConstructorExpression expr(&vec, std::move(values));
 
-  ASSERT_TRUE(gen().EmitConstructor(out(), &expr)) << gen().error();
+  ASSERT_TRUE(gen().EmitConstructor(pre(), out(), &expr)) << gen().error();
   EXPECT_EQ(result(),
             "vector<float, 3>(1.00000000f, 2.00000000f, 3.00000000f)");
 }
@@ -157,7 +157,7 @@
   ast::ExpressionList values;
   ast::TypeConstructorExpression expr(&vec, std::move(values));
 
-  ASSERT_TRUE(gen().EmitConstructor(out(), &expr)) << gen().error();
+  ASSERT_TRUE(gen().EmitConstructor(pre(), out(), &expr)) << gen().error();
   EXPECT_EQ(result(), "vector<float, 3>(0.0f)");
 }
 
@@ -193,7 +193,7 @@
 
   ast::TypeConstructorExpression expr(&mat, std::move(mat_values));
 
-  ASSERT_TRUE(gen().EmitConstructor(out(), &expr)) << gen().error();
+  ASSERT_TRUE(gen().EmitConstructor(pre(), out(), &expr)) << gen().error();
 
   // A matrix of type T with n columns and m rows can also be constructed from
   // n vectors of type T with m components.
@@ -232,7 +232,7 @@
 
   ast::TypeConstructorExpression expr(&ary, std::move(ary_values));
 
-  ASSERT_TRUE(gen().EmitConstructor(out(), &expr)) << gen().error();
+  ASSERT_TRUE(gen().EmitConstructor(pre(), out(), &expr)) << gen().error();
   EXPECT_EQ(result(),
             std::string("{") +
                 "vector<float, 3>(1.00000000f, 2.00000000f, 3.00000000f), " +
diff --git a/src/writer/hlsl/generator_impl_identifier_test.cc b/src/writer/hlsl/generator_impl_identifier_test.cc
index 58b5ed3..56f15bb 100644
--- a/src/writer/hlsl/generator_impl_identifier_test.cc
+++ b/src/writer/hlsl/generator_impl_identifier_test.cc
@@ -25,20 +25,20 @@
 
 TEST_F(HlslGeneratorImplTest_Identifier, DISABLED_EmitExpression_Identifier) {
   ast::IdentifierExpression i(std::vector<std::string>{"std", "glsl"});
-  ASSERT_TRUE(gen().EmitExpression(out(), &i)) << gen().error();
+  ASSERT_TRUE(gen().EmitExpression(pre(), out(), &i)) << gen().error();
   EXPECT_EQ(result(), "std::glsl");
 }
 
 TEST_F(HlslGeneratorImplTest_Identifier, EmitIdentifierExpression_Single) {
   ast::IdentifierExpression i("foo");
-  ASSERT_TRUE(gen().EmitExpression(out(), &i)) << gen().error();
+  ASSERT_TRUE(gen().EmitExpression(pre(), out(), &i)) << gen().error();
   EXPECT_EQ(result(), "foo");
 }
 
 TEST_F(HlslGeneratorImplTest_Identifier,
        EmitIdentifierExpression_Single_WithCollision) {
   ast::IdentifierExpression i("virtual");
-  ASSERT_TRUE(gen().EmitExpression(out(), &i)) << gen().error();
+  ASSERT_TRUE(gen().EmitExpression(pre(), out(), &i)) << gen().error();
   EXPECT_EQ(result(), "virtual_tint_0");
 }
 
@@ -46,7 +46,7 @@
 TEST_F(HlslGeneratorImplTest_Identifier,
        DISABLED_EmitIdentifierExpression_MultipleNames) {
   ast::IdentifierExpression i({"std", "glsl", "init"});
-  ASSERT_TRUE(gen().EmitExpression(out(), &i)) << gen().error();
+  ASSERT_TRUE(gen().EmitExpression(pre(), out(), &i)) << gen().error();
   EXPECT_EQ(result(), "std::glsl::init");
 }
 
diff --git a/src/writer/hlsl/generator_impl_import_test.cc b/src/writer/hlsl/generator_impl_import_test.cc
index b97859d..8bea055 100644
--- a/src/writer/hlsl/generator_impl_import_test.cc
+++ b/src/writer/hlsl/generator_impl_import_test.cc
@@ -65,7 +65,7 @@
   mod()->AddImport(std::make_unique<ast::Import>("GLSL.std.450", "std"));
 
   ASSERT_TRUE(td().DetermineResultType(&expr)) << td().error();
-  ASSERT_TRUE(gen().EmitImportFunction(out(), &expr)) << gen().error();
+  ASSERT_TRUE(gen().EmitImportFunction(pre(), out(), &expr)) << gen().error();
   EXPECT_EQ(result(), std::string(param.hlsl_name) + "(1.00000000f)");
 }
 INSTANTIATE_TEST_SUITE_P(
@@ -130,7 +130,7 @@
   mod()->AddImport(std::make_unique<ast::Import>("GLSL.std.450", "std"));
 
   ASSERT_TRUE(td().DetermineResultType(&expr)) << td().error();
-  ASSERT_TRUE(gen().EmitImportFunction(out(), &expr)) << gen().error();
+  ASSERT_TRUE(gen().EmitImportFunction(pre(), out(), &expr)) << gen().error();
   EXPECT_EQ(result(), std::string(param.hlsl_name) + "(1)");
 }
 INSTANTIATE_TEST_SUITE_P(HlslGeneratorImplTest_Import,
@@ -158,7 +158,7 @@
   mod()->AddImport(std::make_unique<ast::Import>("GLSL.std.450", "std"));
 
   ASSERT_TRUE(td().DetermineResultType(&expr)) << td().error();
-  ASSERT_TRUE(gen().EmitImportFunction(out(), &expr)) << gen().error();
+  ASSERT_TRUE(gen().EmitImportFunction(pre(), out(), &expr)) << gen().error();
   EXPECT_EQ(result(),
             std::string(param.hlsl_name) + "(1.00000000f, 2.00000000f)");
 }
@@ -210,7 +210,7 @@
   mod()->AddImport(std::make_unique<ast::Import>("GLSL.std.450", "std"));
 
   ASSERT_TRUE(td().DetermineResultType(&expr)) << td().error();
-  ASSERT_TRUE(gen().EmitImportFunction(out(), &expr)) << gen().error();
+  ASSERT_TRUE(gen().EmitImportFunction(pre(), out(), &expr)) << gen().error();
   EXPECT_EQ(result(),
             std::string(param.hlsl_name) +
                 "(vector<float, 3>(1.00000000f, 2.00000000f, 3.00000000f), "
@@ -240,7 +240,7 @@
   mod()->AddImport(std::make_unique<ast::Import>("GLSL.std.450", "std"));
 
   ASSERT_TRUE(td().DetermineResultType(&expr)) << td().error();
-  ASSERT_TRUE(gen().EmitImportFunction(out(), &expr)) << gen().error();
+  ASSERT_TRUE(gen().EmitImportFunction(pre(), out(), &expr)) << gen().error();
   EXPECT_EQ(result(), std::string(param.hlsl_name) + "(1, 2)");
 }
 INSTANTIATE_TEST_SUITE_P(HlslGeneratorImplTest_Import,
@@ -272,7 +272,7 @@
   mod()->AddImport(std::make_unique<ast::Import>("GLSL.std.450", "std"));
 
   ASSERT_TRUE(td().DetermineResultType(&expr)) << td().error();
-  ASSERT_TRUE(gen().EmitImportFunction(out(), &expr)) << gen().error();
+  ASSERT_TRUE(gen().EmitImportFunction(pre(), out(), &expr)) << gen().error();
   EXPECT_EQ(result(), std::string(param.hlsl_name) +
                           "(1.00000000f, 2.00000000f, 3.00000000f)");
 }
@@ -311,7 +311,7 @@
   mod()->AddImport(std::make_unique<ast::Import>("GLSL.std.450", "std"));
 
   ASSERT_TRUE(td().DetermineResultType(&expr)) << td().error();
-  ASSERT_TRUE(gen().EmitImportFunction(out(), &expr)) << gen().error();
+  ASSERT_TRUE(gen().EmitImportFunction(pre(), out(), &expr)) << gen().error();
   EXPECT_EQ(result(), std::string(param.hlsl_name) + "(1, 2, 3)");
 }
 INSTANTIATE_TEST_SUITE_P(HlslGeneratorImplTest_Import,
@@ -339,7 +339,7 @@
   // Register the global
   ASSERT_TRUE(td().Determine()) << td().error();
   ASSERT_TRUE(td().DetermineResultType(&expr)) << td().error();
-  ASSERT_TRUE(gen().EmitImportFunction(out(), &expr)) << gen().error();
+  ASSERT_TRUE(gen().EmitImportFunction(pre(), out(), &expr)) << gen().error();
   EXPECT_EQ(result(), std::string("determinant(var)"));
 }
 
diff --git a/src/writer/hlsl/generator_impl_intrinsic_test.cc b/src/writer/hlsl/generator_impl_intrinsic_test.cc
index f862ba7..0455e97 100644
--- a/src/writer/hlsl/generator_impl_intrinsic_test.cc
+++ b/src/writer/hlsl/generator_impl_intrinsic_test.cc
@@ -96,7 +96,7 @@
   ASSERT_TRUE(td().DetermineResultType(&call)) << td().error();
 
   gen().increment_indent();
-  ASSERT_TRUE(gen().EmitExpression(out(), &call)) << gen().error();
+  ASSERT_TRUE(gen().EmitExpression(pre(), out(), &call)) << gen().error();
   EXPECT_EQ(result(), "  float3x2(a * b[0], a * b[1], a * b[2])");
 }
 
@@ -113,7 +113,7 @@
                            std::move(params));
 
   gen().increment_indent();
-  ASSERT_TRUE(gen().EmitExpression(out(), &call)) << gen().error();
+  ASSERT_TRUE(gen().EmitExpression(pre(), out(), &call)) << gen().error();
   EXPECT_EQ(result(), "  dot(param1, param2)");
 }
 
diff --git a/src/writer/hlsl/generator_impl_member_accessor_test.cc b/src/writer/hlsl/generator_impl_member_accessor_test.cc
index ccfe26a..748b783 100644
--- a/src/writer/hlsl/generator_impl_member_accessor_test.cc
+++ b/src/writer/hlsl/generator_impl_member_accessor_test.cc
@@ -73,7 +73,7 @@
   mod()->AddGlobalVariable(std::move(str_var));
 
   ASSERT_TRUE(td().DetermineResultType(&expr)) << td().error();
-  ASSERT_TRUE(gen().EmitExpression(out(), &expr)) << gen().error();
+  ASSERT_TRUE(gen().EmitExpression(pre(), out(), &expr)) << gen().error();
   EXPECT_EQ(result(), "str.mem");
 }
 
@@ -122,7 +122,7 @@
   ASSERT_TRUE(td().Determine()) << td().error();
   ASSERT_TRUE(td().DetermineResultType(&expr));
 
-  ASSERT_TRUE(gen().EmitExpression(out(), &expr)) << gen().error();
+  ASSERT_TRUE(gen().EmitExpression(pre(), out(), &expr)) << gen().error();
   EXPECT_EQ(result(), "asfloat(data.Load(4))");
 }
 
@@ -171,7 +171,7 @@
   ASSERT_TRUE(td().Determine()) << td().error();
   ASSERT_TRUE(td().DetermineResultType(&expr));
 
-  ASSERT_TRUE(gen().EmitExpression(out(), &expr)) << gen().error();
+  ASSERT_TRUE(gen().EmitExpression(pre(), out(), &expr)) << gen().error();
   EXPECT_EQ(result(), "asint(data.Load(0))");
 }
 TEST_F(HlslGeneratorImplTest_MemberAccessor,
@@ -347,7 +347,7 @@
   ASSERT_TRUE(td().Determine()) << td().error();
   ASSERT_TRUE(td().DetermineResultType(&expr));
 
-  ASSERT_TRUE(gen().EmitExpression(out(), &expr)) << gen().error();
+  ASSERT_TRUE(gen().EmitExpression(pre(), out(), &expr)) << gen().error();
   EXPECT_EQ(result(),
             "asfloat(matrix<uint, 2, 3>(data.Load2(4 + 0), data.Load2(4 + 8), "
             "data.Load2(4 + 16)))");
@@ -403,7 +403,7 @@
   ASSERT_TRUE(td().Determine()) << td().error();
   ASSERT_TRUE(td().DetermineResultType(&expr));
 
-  ASSERT_TRUE(gen().EmitExpression(out(), &expr)) << gen().error();
+  ASSERT_TRUE(gen().EmitExpression(pre(), out(), &expr)) << gen().error();
   EXPECT_EQ(
       result(),
       "asfloat(matrix<uint, 3, 2>(data.Load3(4 + 0), data.Load3(4 + 16)))");
@@ -451,7 +451,7 @@
   ASSERT_TRUE(td().Determine()) << td().error();
   ASSERT_TRUE(td().DetermineResultType(&expr));
 
-  ASSERT_TRUE(gen().EmitExpression(out(), &expr)) << gen().error();
+  ASSERT_TRUE(gen().EmitExpression(pre(), out(), &expr)) << gen().error();
   EXPECT_EQ(result(),
             "asfloat(matrix<uint, 3, 3>(data.Load3(0 + 0), data.Load3(0 + 16), "
             "data.Load3(0 + 32)))");
@@ -509,7 +509,7 @@
   ASSERT_TRUE(td().Determine()) << td().error();
   ASSERT_TRUE(td().DetermineResultType(&expr));
 
-  ASSERT_TRUE(gen().EmitExpression(out(), &expr)) << gen().error();
+  ASSERT_TRUE(gen().EmitExpression(pre(), out(), &expr)) << gen().error();
   EXPECT_EQ(result(), "asfloat(data.Load((4 * 1) + (16 * 2) + 16))");
 }
 
@@ -557,7 +557,7 @@
   ASSERT_TRUE(td().Determine()) << td().error();
   ASSERT_TRUE(td().DetermineResultType(&expr)) << td().error();
 
-  ASSERT_TRUE(gen().EmitExpression(out(), &expr)) << gen().error();
+  ASSERT_TRUE(gen().EmitExpression(pre(), out(), &expr)) << gen().error();
   EXPECT_EQ(result(), "asint(data.Load((4 * 2) + 0))");
 }
 
@@ -613,7 +613,7 @@
   ASSERT_TRUE(td().Determine()) << td().error();
   ASSERT_TRUE(td().DetermineResultType(&expr)) << td().error();
 
-  ASSERT_TRUE(gen().EmitExpression(out(), &expr)) << gen().error();
+  ASSERT_TRUE(gen().EmitExpression(pre(), out(), &expr)) << gen().error();
   EXPECT_EQ(result(), "asint(data.Load((4 * ((2 + 4) - 3)) + 0))");
 }
 
@@ -826,7 +826,7 @@
       std::make_unique<ast::IdentifierExpression>("b"));
 
   ASSERT_TRUE(td().DetermineResultType(&expr));
-  ASSERT_TRUE(gen().EmitExpression(out(), &expr)) << gen().error();
+  ASSERT_TRUE(gen().EmitExpression(pre(), out(), &expr)) << gen().error();
   EXPECT_EQ(result(), "asfloat(data.Load3(16))");
 }
 
@@ -946,12 +946,12 @@
   auto pre_str = std::make_unique<ast::Struct>();
   pre_str->set_members(std::move(members));
 
-  ast::type::StructType pre(std::move(pre_str));
-  pre.set_name("Pre");
+  ast::type::StructType pre_struct(std::move(pre_str));
+  pre_struct.set_name("Pre");
 
   auto coord_var =
       std::make_unique<ast::DecoratedVariable>(std::make_unique<ast::Variable>(
-          "data", ast::StorageClass::kStorageBuffer, &pre));
+          "data", ast::StorageClass::kStorageBuffer, &pre_struct));
 
   td().RegisterVariableForTesting(coord_var.get());
   gen().register_global(coord_var.get());
@@ -969,7 +969,7 @@
       std::make_unique<ast::IdentifierExpression>("b"));
 
   ASSERT_TRUE(td().DetermineResultType(&expr));
-  ASSERT_TRUE(gen().EmitExpression(out(), &expr)) << gen().error();
+  ASSERT_TRUE(gen().EmitExpression(pre(), out(), &expr)) << gen().error();
   EXPECT_EQ(result(), "asfloat(data.Load3(16 + (32 * 2) + 0))");
 }
 
@@ -1019,12 +1019,12 @@
   auto pre_str = std::make_unique<ast::Struct>();
   pre_str->set_members(std::move(members));
 
-  ast::type::StructType pre(std::move(pre_str));
-  pre.set_name("Pre");
+  ast::type::StructType pre_struct(std::move(pre_str));
+  pre_struct.set_name("Pre");
 
   auto coord_var =
       std::make_unique<ast::DecoratedVariable>(std::make_unique<ast::Variable>(
-          "data", ast::StorageClass::kStorageBuffer, &pre));
+          "data", ast::StorageClass::kStorageBuffer, &pre_struct));
 
   td().RegisterVariableForTesting(coord_var.get());
   gen().register_global(coord_var.get());
@@ -1044,7 +1044,7 @@
       std::make_unique<ast::IdentifierExpression>("xy"));
 
   ASSERT_TRUE(td().DetermineResultType(&expr));
-  ASSERT_TRUE(gen().EmitExpression(out(), &expr)) << gen().error();
+  ASSERT_TRUE(gen().EmitExpression(pre(), out(), &expr)) << gen().error();
   EXPECT_EQ(result(), "asfloat(data.Load3(16 + (32 * 2) + 0)).xy");
 }
 
@@ -1095,12 +1095,12 @@
   auto pre_str = std::make_unique<ast::Struct>();
   pre_str->set_members(std::move(members));
 
-  ast::type::StructType pre(std::move(pre_str));
-  pre.set_name("Pre");
+  ast::type::StructType pre_struct(std::move(pre_str));
+  pre_struct.set_name("Pre");
 
   auto coord_var =
       std::make_unique<ast::DecoratedVariable>(std::make_unique<ast::Variable>(
-          "data", ast::StorageClass::kStorageBuffer, &pre));
+          "data", ast::StorageClass::kStorageBuffer, &pre_struct));
 
   td().RegisterVariableForTesting(coord_var.get());
   gen().register_global(coord_var.get());
@@ -1120,7 +1120,7 @@
       std::make_unique<ast::IdentifierExpression>("g"));
 
   ASSERT_TRUE(td().DetermineResultType(&expr));
-  ASSERT_TRUE(gen().EmitExpression(out(), &expr)) << gen().error();
+  ASSERT_TRUE(gen().EmitExpression(pre(), out(), &expr)) << gen().error();
   EXPECT_EQ(result(), "asfloat(data.Load((4 * 1) + 16 + (32 * 2) + 0))");
 }
 
@@ -1170,12 +1170,12 @@
   auto pre_str = std::make_unique<ast::Struct>();
   pre_str->set_members(std::move(members));
 
-  ast::type::StructType pre(std::move(pre_str));
-  pre.set_name("Pre");
+  ast::type::StructType pre_struct(std::move(pre_str));
+  pre_struct.set_name("Pre");
 
   auto coord_var =
       std::make_unique<ast::DecoratedVariable>(std::make_unique<ast::Variable>(
-          "data", ast::StorageClass::kStorageBuffer, &pre));
+          "data", ast::StorageClass::kStorageBuffer, &pre_struct));
 
   td().RegisterVariableForTesting(coord_var.get());
   gen().register_global(coord_var.get());
@@ -1196,7 +1196,7 @@
           std::make_unique<ast::SintLiteral>(&i32, 1)));
 
   ASSERT_TRUE(td().DetermineResultType(&expr));
-  ASSERT_TRUE(gen().EmitExpression(out(), &expr)) << gen().error();
+  ASSERT_TRUE(gen().EmitExpression(pre(), out(), &expr)) << gen().error();
   EXPECT_EQ(result(), "asfloat(data.Load((4 * 1) + 16 + (32 * 2) + 0))");
 }
 
@@ -1246,12 +1246,12 @@
   auto pre_str = std::make_unique<ast::Struct>();
   pre_str->set_members(std::move(members));
 
-  ast::type::StructType pre(std::move(pre_str));
-  pre.set_name("Pre");
+  ast::type::StructType pre_struct(std::move(pre_str));
+  pre_struct.set_name("Pre");
 
   auto coord_var =
       std::make_unique<ast::DecoratedVariable>(std::make_unique<ast::Variable>(
-          "data", ast::StorageClass::kStorageBuffer, &pre));
+          "data", ast::StorageClass::kStorageBuffer, &pre_struct));
 
   td().RegisterVariableForTesting(coord_var.get());
   gen().register_global(coord_var.get());
@@ -1338,12 +1338,12 @@
   auto pre_str = std::make_unique<ast::Struct>();
   pre_str->set_members(std::move(members));
 
-  ast::type::StructType pre(std::move(pre_str));
-  pre.set_name("Pre");
+  ast::type::StructType pre_struct(std::move(pre_str));
+  pre_struct.set_name("Pre");
 
   auto coord_var =
       std::make_unique<ast::DecoratedVariable>(std::make_unique<ast::Variable>(
-          "data", ast::StorageClass::kStorageBuffer, &pre));
+          "data", ast::StorageClass::kStorageBuffer, &pre_struct));
 
   td().RegisterVariableForTesting(coord_var.get());
   gen().register_global(coord_var.get());
diff --git a/src/writer/hlsl/generator_impl_test.cc b/src/writer/hlsl/generator_impl_test.cc
index 22fa5d7..6b2324a 100644
--- a/src/writer/hlsl/generator_impl_test.cc
+++ b/src/writer/hlsl/generator_impl_test.cc
@@ -59,7 +59,7 @@
   ASSERT_EQ(gen().generate_name("func_main_in"), "func_main_in");
 
   ast::IdentifierExpression ident("func_main_in");
-  ASSERT_TRUE(gen().EmitIdentifier(out(), &ident));
+  ASSERT_TRUE(gen().EmitIdentifier(pre(), out(), &ident));
   EXPECT_EQ(result(), "func_main_in_0");
 }
 
diff --git a/src/writer/hlsl/generator_impl_unary_op_test.cc b/src/writer/hlsl/generator_impl_unary_op_test.cc
index 6e97786..b723132 100644
--- a/src/writer/hlsl/generator_impl_unary_op_test.cc
+++ b/src/writer/hlsl/generator_impl_unary_op_test.cc
@@ -40,7 +40,7 @@
   auto expr = std::make_unique<ast::IdentifierExpression>("expr");
   ast::UnaryOpExpression op(params.op, std::move(expr));
 
-  ASSERT_TRUE(gen().EmitExpression(out(), &op)) << gen().error();
+  ASSERT_TRUE(gen().EmitExpression(pre(), out(), &op)) << gen().error();
   EXPECT_EQ(result(), std::string(params.name) + "(expr)");
 }
 INSTANTIATE_TEST_SUITE_P(HlslGeneratorImplTest_UnaryOp,
diff --git a/src/writer/hlsl/test_helper.h b/src/writer/hlsl/test_helper.h
index 68fa0e3..99d5f98 100644
--- a/src/writer/hlsl/test_helper.h
+++ b/src/writer/hlsl/test_helper.h
@@ -46,15 +46,22 @@
   /// @returns the output stream
   std::ostream& out() { return out_; }
 
+  /// @returns the pre stream
+  std::ostream& pre() { return pre_; }
+
   /// @returns the result string
   std::string result() const { return out_.str(); }
 
+  /// @returns the pre result string
+  std::string pre_result() const { return pre_.str(); }
+
  private:
   Context ctx_;
   ast::Module mod_;
   TypeDeterminer td_;
   GeneratorImpl impl_;
   std::ostringstream out_;
+  std::ostringstream pre_;
 };
 using TestHelper = TestHelperBase<testing::Test>;