Cloning: move arguments to create() into temporary locals

In C++ argument evaluation order is undefined. MSVC and Clang evaluate these in different orders, leading to hilarity when writing tests that expect a deterministic ordering.

Pull out all the argument expressions to create() in the clone functions so a cloned program is deterministic in its ordering between compilers.

Change-Id: I8e2de31398960c480ce7ee1dfaac4f67652d2dbc
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/41544
Commit-Queue: Ben Clayton <bclayton@google.com>
Reviewed-by: dan sinclair <dsinclair@chromium.org>
Auto-Submit: Ben Clayton <bclayton@google.com>
This commit is contained in:
Ben Clayton 2021-02-11 20:27:14 +00:00 committed by Commit Bot service account
parent 7b6bcb6e0b
commit 545c9742d5
56 changed files with 237 additions and 108 deletions

View File

@ -35,7 +35,9 @@ void AccessDecoration::to_str(const semantic::Info&,
} }
AccessDecoration* AccessDecoration::Clone(CloneContext* ctx) const { AccessDecoration* AccessDecoration::Clone(CloneContext* ctx) const {
return ctx->dst->create<AccessDecoration>(ctx->Clone(source()), value_); // Clone arguments outside of create() call to have deterministic ordering
auto src = ctx->Clone(source());
return ctx->dst->create<AccessDecoration>(src, value_);
} }
} // namespace ast } // namespace ast

View File

@ -34,8 +34,11 @@ ArrayAccessorExpression::~ArrayAccessorExpression() = default;
ArrayAccessorExpression* ArrayAccessorExpression::Clone( ArrayAccessorExpression* ArrayAccessorExpression::Clone(
CloneContext* ctx) const { CloneContext* ctx) const {
return ctx->dst->create<ArrayAccessorExpression>( // Clone arguments outside of create() call to have deterministic ordering
ctx->Clone(source()), ctx->Clone(array_), ctx->Clone(idx_expr_)); auto src = ctx->Clone(source());
auto* arr = ctx->Clone(array_);
auto* idx = ctx->Clone(idx_expr_);
return ctx->dst->create<ArrayAccessorExpression>(src, arr, idx);
} }
bool ArrayAccessorExpression::IsValid() const { bool ArrayAccessorExpression::IsValid() const {

View File

@ -32,8 +32,11 @@ AssignmentStatement::AssignmentStatement(AssignmentStatement&&) = default;
AssignmentStatement::~AssignmentStatement() = default; AssignmentStatement::~AssignmentStatement() = default;
AssignmentStatement* AssignmentStatement::Clone(CloneContext* ctx) const { AssignmentStatement* AssignmentStatement::Clone(CloneContext* ctx) const {
return ctx->dst->create<AssignmentStatement>( // Clone arguments outside of create() call to have deterministic ordering
ctx->Clone(source()), ctx->Clone(lhs_), ctx->Clone(rhs_)); auto src = ctx->Clone(source());
auto* l = ctx->Clone(lhs_);
auto* r = ctx->Clone(rhs_);
return ctx->dst->create<AssignmentStatement>(src, l, r);
} }
bool AssignmentStatement::IsValid() const { bool AssignmentStatement::IsValid() const {

View File

@ -33,8 +33,11 @@ BinaryExpression::BinaryExpression(BinaryExpression&&) = default;
BinaryExpression::~BinaryExpression() = default; BinaryExpression::~BinaryExpression() = default;
BinaryExpression* BinaryExpression::Clone(CloneContext* ctx) const { BinaryExpression* BinaryExpression::Clone(CloneContext* ctx) const {
return ctx->dst->create<BinaryExpression>(ctx->Clone(source()), op_, // Clone arguments outside of create() call to have deterministic ordering
ctx->Clone(lhs_), ctx->Clone(rhs_)); auto src = ctx->Clone(source());
auto* l = ctx->Clone(lhs_);
auto* r = ctx->Clone(rhs_);
return ctx->dst->create<BinaryExpression>(src, op_, l, r);
} }
bool BinaryExpression::IsValid() const { bool BinaryExpression::IsValid() const {

View File

@ -35,7 +35,9 @@ void BindingDecoration::to_str(const semantic::Info&,
} }
BindingDecoration* BindingDecoration::Clone(CloneContext* ctx) const { BindingDecoration* BindingDecoration::Clone(CloneContext* ctx) const {
return ctx->dst->create<BindingDecoration>(ctx->Clone(source()), value_); // Clone arguments outside of create() call to have deterministic ordering
auto src = ctx->Clone(source());
return ctx->dst->create<BindingDecoration>(src, value_);
} }
} // namespace ast } // namespace ast

View File

@ -31,8 +31,11 @@ BitcastExpression::BitcastExpression(BitcastExpression&&) = default;
BitcastExpression::~BitcastExpression() = default; BitcastExpression::~BitcastExpression() = default;
BitcastExpression* BitcastExpression::Clone(CloneContext* ctx) const { BitcastExpression* BitcastExpression::Clone(CloneContext* ctx) const {
return ctx->dst->create<BitcastExpression>( // Clone arguments outside of create() call to have deterministic ordering
ctx->Clone(source()), ctx->Clone(type_), ctx->Clone(expr_)); auto src = ctx->Clone(source());
auto* ty = ctx->Clone(type_);
auto* e = ctx->Clone(expr_);
return ctx->dst->create<BitcastExpression>(src, ty, e);
} }
bool BitcastExpression::IsValid() const { bool BitcastExpression::IsValid() const {

View File

@ -31,8 +31,10 @@ BlockStatement::BlockStatement(BlockStatement&&) = default;
BlockStatement::~BlockStatement() = default; BlockStatement::~BlockStatement() = default;
BlockStatement* BlockStatement::Clone(CloneContext* ctx) const { BlockStatement* BlockStatement::Clone(CloneContext* ctx) const {
return ctx->dst->create<BlockStatement>(ctx->Clone(source()), // Clone arguments outside of create() call to have deterministic ordering
ctx->Clone(statements_)); auto src = ctx->Clone(source());
auto stmts = ctx->Clone(statements_);
return ctx->dst->create<BlockStatement>(src, stmts);
} }
bool BlockStatement::IsValid() const { bool BlockStatement::IsValid() const {

View File

@ -36,8 +36,10 @@ std::string BoolLiteral::name() const {
} }
BoolLiteral* BoolLiteral::Clone(CloneContext* ctx) const { BoolLiteral* BoolLiteral::Clone(CloneContext* ctx) const {
return ctx->dst->create<BoolLiteral>(ctx->Clone(source()), ctx->Clone(type()), // Clone arguments outside of create() call to have deterministic ordering
value_); auto src = ctx->Clone(source());
auto* ty = ctx->Clone(type());
return ctx->dst->create<BoolLiteral>(src, ty, value_);
} }
} // namespace ast } // namespace ast

View File

@ -29,7 +29,9 @@ BreakStatement::BreakStatement(BreakStatement&&) = default;
BreakStatement::~BreakStatement() = default; BreakStatement::~BreakStatement() = default;
BreakStatement* BreakStatement::Clone(CloneContext* ctx) const { BreakStatement* BreakStatement::Clone(CloneContext* ctx) const {
return ctx->dst->create<BreakStatement>(ctx->Clone(source())); // Clone arguments outside of create() call to have deterministic ordering
auto src = ctx->Clone(source());
return ctx->dst->create<BreakStatement>(src);
} }
bool BreakStatement::IsValid() const { bool BreakStatement::IsValid() const {

View File

@ -35,7 +35,9 @@ void BuiltinDecoration::to_str(const semantic::Info&,
} }
BuiltinDecoration* BuiltinDecoration::Clone(CloneContext* ctx) const { BuiltinDecoration* BuiltinDecoration::Clone(CloneContext* ctx) const {
return ctx->dst->create<BuiltinDecoration>(ctx->Clone(source()), builtin_); // Clone arguments outside of create() call to have deterministic ordering
auto src = ctx->Clone(source());
return ctx->dst->create<BuiltinDecoration>(src, builtin_);
} }
} // namespace ast } // namespace ast

View File

@ -32,8 +32,11 @@ CallExpression::CallExpression(CallExpression&&) = default;
CallExpression::~CallExpression() = default; CallExpression::~CallExpression() = default;
CallExpression* CallExpression::Clone(CloneContext* ctx) const { CallExpression* CallExpression::Clone(CloneContext* ctx) const {
return ctx->dst->create<CallExpression>( // Clone arguments outside of create() call to have deterministic ordering
ctx->Clone(source()), ctx->Clone(func_), ctx->Clone(params_)); auto src = ctx->Clone(source());
auto* fn = ctx->Clone(func_);
auto p = ctx->Clone(params_);
return ctx->dst->create<CallExpression>(src, fn, p);
} }
bool CallExpression::IsValid() const { bool CallExpression::IsValid() const {

View File

@ -31,8 +31,10 @@ CallStatement::CallStatement(CallStatement&&) = default;
CallStatement::~CallStatement() = default; CallStatement::~CallStatement() = default;
CallStatement* CallStatement::Clone(CloneContext* ctx) const { CallStatement* CallStatement::Clone(CloneContext* ctx) const {
return ctx->dst->create<CallStatement>(ctx->Clone(source()), // Clone arguments outside of create() call to have deterministic ordering
ctx->Clone(call_)); auto src = ctx->Clone(source());
auto* call = ctx->Clone(call_);
return ctx->dst->create<CallStatement>(src, call);
} }
bool CallStatement::IsValid() const { bool CallStatement::IsValid() const {

View File

@ -32,8 +32,11 @@ CaseStatement::CaseStatement(CaseStatement&&) = default;
CaseStatement::~CaseStatement() = default; CaseStatement::~CaseStatement() = default;
CaseStatement* CaseStatement::Clone(CloneContext* ctx) const { CaseStatement* CaseStatement::Clone(CloneContext* ctx) const {
return ctx->dst->create<CaseStatement>( // Clone arguments outside of create() call to have deterministic ordering
ctx->Clone(source()), ctx->Clone(selectors_), ctx->Clone(body_)); auto src = ctx->Clone(source());
auto sel = ctx->Clone(selectors_);
auto* b = ctx->Clone(body_);
return ctx->dst->create<CaseStatement>(src, sel, b);
} }
bool CaseStatement::IsValid() const { bool CaseStatement::IsValid() const {

View File

@ -35,7 +35,9 @@ void ConstantIdDecoration::to_str(const semantic::Info&,
} }
ConstantIdDecoration* ConstantIdDecoration::Clone(CloneContext* ctx) const { ConstantIdDecoration* ConstantIdDecoration::Clone(CloneContext* ctx) const {
return ctx->dst->create<ConstantIdDecoration>(ctx->Clone(source()), value_); // Clone arguments outside of create() call to have deterministic ordering
auto src = ctx->Clone(source());
return ctx->dst->create<ConstantIdDecoration>(src, value_);
} }
} // namespace ast } // namespace ast

View File

@ -29,7 +29,9 @@ ContinueStatement::ContinueStatement(ContinueStatement&&) = default;
ContinueStatement::~ContinueStatement() = default; ContinueStatement::~ContinueStatement() = default;
ContinueStatement* ContinueStatement::Clone(CloneContext* ctx) const { ContinueStatement* ContinueStatement::Clone(CloneContext* ctx) const {
return ctx->dst->create<ContinueStatement>(ctx->Clone(source())); // Clone arguments outside of create() call to have deterministic ordering
auto src = ctx->Clone(source());
return ctx->dst->create<ContinueStatement>(src);
} }
bool ContinueStatement::IsValid() const { bool ContinueStatement::IsValid() const {

View File

@ -29,7 +29,9 @@ DiscardStatement::DiscardStatement(DiscardStatement&&) = default;
DiscardStatement::~DiscardStatement() = default; DiscardStatement::~DiscardStatement() = default;
DiscardStatement* DiscardStatement::Clone(CloneContext* ctx) const { DiscardStatement* DiscardStatement::Clone(CloneContext* ctx) const {
return ctx->dst->create<DiscardStatement>(ctx->Clone(source())); // Clone arguments outside of create() call to have deterministic ordering
auto src = ctx->Clone(source());
return ctx->dst->create<DiscardStatement>(src);
} }
bool DiscardStatement::IsValid() const { bool DiscardStatement::IsValid() const {

View File

@ -32,8 +32,11 @@ ElseStatement::ElseStatement(ElseStatement&&) = default;
ElseStatement::~ElseStatement() = default; ElseStatement::~ElseStatement() = default;
ElseStatement* ElseStatement::Clone(CloneContext* ctx) const { ElseStatement* ElseStatement::Clone(CloneContext* ctx) const {
return ctx->dst->create<ElseStatement>( // Clone arguments outside of create() call to have deterministic ordering
ctx->Clone(source()), ctx->Clone(condition_), ctx->Clone(body_)); auto src = ctx->Clone(source());
auto* cond = ctx->Clone(condition_);
auto* b = ctx->Clone(body_);
return ctx->dst->create<ElseStatement>(src, cond, b);
} }
bool ElseStatement::IsValid() const { bool ElseStatement::IsValid() const {

View File

@ -30,7 +30,9 @@ FallthroughStatement::FallthroughStatement(FallthroughStatement&&) = default;
FallthroughStatement::~FallthroughStatement() = default; FallthroughStatement::~FallthroughStatement() = default;
FallthroughStatement* FallthroughStatement::Clone(CloneContext* ctx) const { FallthroughStatement* FallthroughStatement::Clone(CloneContext* ctx) const {
return ctx->dst->create<FallthroughStatement>(ctx->Clone(source())); // Clone arguments outside of create() call to have deterministic ordering
auto src = ctx->Clone(source());
return ctx->dst->create<FallthroughStatement>(src);
} }
bool FallthroughStatement::IsValid() const { bool FallthroughStatement::IsValid() const {

View File

@ -43,8 +43,10 @@ std::string FloatLiteral::name() const {
} }
FloatLiteral* FloatLiteral::Clone(CloneContext* ctx) const { FloatLiteral* FloatLiteral::Clone(CloneContext* ctx) const {
return ctx->dst->create<FloatLiteral>(ctx->Clone(source()), // Clone arguments outside of create() call to have deterministic ordering
ctx->Clone(type()), value_); auto src = ctx->Clone(source());
auto* ty = ctx->Clone(type());
return ctx->dst->create<FloatLiteral>(src, ty, value_);
} }
} // namespace ast } // namespace ast

View File

@ -70,9 +70,14 @@ const Statement* Function::get_last_statement() const {
} }
Function* Function::Clone(CloneContext* ctx) const { Function* Function::Clone(CloneContext* ctx) const {
return ctx->dst->create<Function>( // Clone arguments outside of create() call to have deterministic ordering
ctx->Clone(source()), ctx->Clone(symbol()), ctx->Clone(params_), auto src = ctx->Clone(source());
ctx->Clone(return_type_), ctx->Clone(body_), ctx->Clone(decorations_)); auto sym = ctx->Clone(symbol());
auto p = ctx->Clone(params_);
auto* ret = ctx->Clone(return_type_);
auto* b = ctx->Clone(body_);
auto decos = ctx->Clone(decorations_);
return ctx->dst->create<Function>(src, sym, p, ret, b, decos);
} }
bool Function::IsValid() const { bool Function::IsValid() const {

View File

@ -35,7 +35,9 @@ void GroupDecoration::to_str(const semantic::Info&,
} }
GroupDecoration* GroupDecoration::Clone(CloneContext* ctx) const { GroupDecoration* GroupDecoration::Clone(CloneContext* ctx) const {
return ctx->dst->create<GroupDecoration>(ctx->Clone(source()), value_); // Clone arguments outside of create() call to have deterministic ordering
auto src = ctx->Clone(source());
return ctx->dst->create<GroupDecoration>(src, value_);
} }
} // namespace ast } // namespace ast

View File

@ -30,8 +30,10 @@ IdentifierExpression::IdentifierExpression(IdentifierExpression&&) = default;
IdentifierExpression::~IdentifierExpression() = default; IdentifierExpression::~IdentifierExpression() = default;
IdentifierExpression* IdentifierExpression::Clone(CloneContext* ctx) const { IdentifierExpression* IdentifierExpression::Clone(CloneContext* ctx) const {
return ctx->dst->create<IdentifierExpression>(ctx->Clone(source()), // Clone arguments outside of create() call to have deterministic ordering
ctx->Clone(symbol())); auto src = ctx->Clone(source());
auto sym = ctx->Clone(symbol());
return ctx->dst->create<IdentifierExpression>(src, sym);
} }
bool IdentifierExpression::IsValid() const { bool IdentifierExpression::IsValid() const {

View File

@ -37,10 +37,12 @@ IfStatement::IfStatement(IfStatement&&) = default;
IfStatement::~IfStatement() = default; IfStatement::~IfStatement() = default;
IfStatement* IfStatement::Clone(CloneContext* ctx) const { IfStatement* IfStatement::Clone(CloneContext* ctx) const {
auto* cloned = ctx->dst->create<IfStatement>( // Clone arguments outside of create() call to have deterministic ordering
ctx->Clone(source()), ctx->Clone(condition_), ctx->Clone(body_), auto src = ctx->Clone(source());
ctx->Clone(else_statements_)); auto* cond = ctx->Clone(condition_);
return cloned; auto* b = ctx->Clone(body_);
auto el = ctx->Clone(else_statements_);
return ctx->dst->create<IfStatement>(src, cond, b, el);
} }
bool IfStatement::IsValid() const { bool IfStatement::IsValid() const {

View File

@ -35,7 +35,9 @@ void LocationDecoration::to_str(const semantic::Info&,
} }
LocationDecoration* LocationDecoration::Clone(CloneContext* ctx) const { LocationDecoration* LocationDecoration::Clone(CloneContext* ctx) const {
return ctx->dst->create<LocationDecoration>(ctx->Clone(source()), value_); // Clone arguments outside of create() call to have deterministic ordering
auto src = ctx->Clone(source());
return ctx->dst->create<LocationDecoration>(src, value_);
} }
} // namespace ast } // namespace ast

View File

@ -32,8 +32,11 @@ LoopStatement::LoopStatement(LoopStatement&&) = default;
LoopStatement::~LoopStatement() = default; LoopStatement::~LoopStatement() = default;
LoopStatement* LoopStatement::Clone(CloneContext* ctx) const { LoopStatement* LoopStatement::Clone(CloneContext* ctx) const {
return ctx->dst->create<LoopStatement>( // Clone arguments outside of create() call to have deterministic ordering
ctx->Clone(source()), ctx->Clone(body_), ctx->Clone(continuing_)); auto src = ctx->Clone(source());
auto* b = ctx->Clone(body_);
auto* cont = ctx->Clone(continuing_);
return ctx->dst->create<LoopStatement>(src, b, cont);
} }
bool LoopStatement::IsValid() const { bool LoopStatement::IsValid() const {

View File

@ -34,8 +34,11 @@ MemberAccessorExpression::~MemberAccessorExpression() = default;
MemberAccessorExpression* MemberAccessorExpression::Clone( MemberAccessorExpression* MemberAccessorExpression::Clone(
CloneContext* ctx) const { CloneContext* ctx) const {
return ctx->dst->create<MemberAccessorExpression>( // Clone arguments outside of create() call to have deterministic ordering
ctx->Clone(source()), ctx->Clone(struct_), ctx->Clone(member_)); auto src = ctx->Clone(source());
auto* str = ctx->Clone(structure());
auto* mem = ctx->Clone(member());
return ctx->dst->create<MemberAccessorExpression>(src, str, mem);
} }
bool MemberAccessorExpression::IsValid() const { bool MemberAccessorExpression::IsValid() const {

View File

@ -36,8 +36,10 @@ std::string NullLiteral::name() const {
} }
NullLiteral* NullLiteral::Clone(CloneContext* ctx) const { NullLiteral* NullLiteral::Clone(CloneContext* ctx) const {
return ctx->dst->create<NullLiteral>(ctx->Clone(source()), // Clone arguments outside of create() call to have deterministic ordering
ctx->Clone(type())); auto src = ctx->Clone(source());
auto* ty = ctx->Clone(type());
return ctx->dst->create<NullLiteral>(src, ty);
} }
} // namespace ast } // namespace ast

View File

@ -33,8 +33,10 @@ ReturnStatement::ReturnStatement(ReturnStatement&&) = default;
ReturnStatement::~ReturnStatement() = default; ReturnStatement::~ReturnStatement() = default;
ReturnStatement* ReturnStatement::Clone(CloneContext* ctx) const { ReturnStatement* ReturnStatement::Clone(CloneContext* ctx) const {
return ctx->dst->create<ReturnStatement>(ctx->Clone(source()), // Clone arguments outside of create() call to have deterministic ordering
ctx->Clone(value_)); auto src = ctx->Clone(source());
auto* ret = ctx->Clone(value());
return ctx->dst->create<ReturnStatement>(src, ret);
} }
bool ReturnStatement::IsValid() const { bool ReturnStatement::IsValid() const {

View File

@ -33,8 +33,10 @@ ScalarConstructorExpression::~ScalarConstructorExpression() = default;
ScalarConstructorExpression* ScalarConstructorExpression::Clone( ScalarConstructorExpression* ScalarConstructorExpression::Clone(
CloneContext* ctx) const { CloneContext* ctx) const {
return ctx->dst->create<ScalarConstructorExpression>(ctx->Clone(source()), // Clone arguments outside of create() call to have deterministic ordering
ctx->Clone(literal_)); auto src = ctx->Clone(source());
auto* lit = ctx->Clone(literal());
return ctx->dst->create<ScalarConstructorExpression>(src, lit);
} }
bool ScalarConstructorExpression::IsValid() const { bool ScalarConstructorExpression::IsValid() const {

View File

@ -36,8 +36,10 @@ std::string SintLiteral::name() const {
} }
SintLiteral* SintLiteral::Clone(CloneContext* ctx) const { SintLiteral* SintLiteral::Clone(CloneContext* ctx) const {
return ctx->dst->create<SintLiteral>(ctx->Clone(source()), ctx->Clone(type()), // Clone arguments outside of create() call to have deterministic ordering
value_); auto src = ctx->Clone(source());
auto* ty = ctx->Clone(type());
return ctx->dst->create<SintLiteral>(src, ty, value_);
} }
} // namespace ast } // namespace ast

View File

@ -35,7 +35,9 @@ void StageDecoration::to_str(const semantic::Info&,
} }
StageDecoration* StageDecoration::Clone(CloneContext* ctx) const { StageDecoration* StageDecoration::Clone(CloneContext* ctx) const {
return ctx->dst->create<StageDecoration>(ctx->Clone(source()), stage_); // Clone arguments outside of create() call to have deterministic ordering
auto src = ctx->Clone(source());
return ctx->dst->create<StageDecoration>(src, stage_);
} }
} // namespace ast } // namespace ast

View File

@ -35,7 +35,9 @@ void StrideDecoration::to_str(const semantic::Info&,
} }
StrideDecoration* StrideDecoration::Clone(CloneContext* ctx) const { StrideDecoration* StrideDecoration::Clone(CloneContext* ctx) const {
return ctx->dst->create<StrideDecoration>(ctx->Clone(source()), stride_); // Clone arguments outside of create() call to have deterministic ordering
auto src = ctx->Clone(source());
return ctx->dst->create<StrideDecoration>(src, stride_);
} }
} // namespace ast } // namespace ast

View File

@ -53,8 +53,11 @@ bool Struct::IsBlockDecorated() const {
} }
Struct* Struct::Clone(CloneContext* ctx) const { Struct* Struct::Clone(CloneContext* ctx) const {
return ctx->dst->create<Struct>(ctx->Clone(source()), ctx->Clone(members_), // Clone arguments outside of create() call to have deterministic ordering
ctx->Clone(decorations_)); auto src = ctx->Clone(source());
auto mem = ctx->Clone(members());
auto decos = ctx->Clone(decorations());
return ctx->dst->create<Struct>(src, mem, decos);
} }
bool Struct::IsValid() const { bool Struct::IsValid() const {

View File

@ -35,7 +35,9 @@ void StructBlockDecoration::to_str(const semantic::Info&,
} }
StructBlockDecoration* StructBlockDecoration::Clone(CloneContext* ctx) const { StructBlockDecoration* StructBlockDecoration::Clone(CloneContext* ctx) const {
return ctx->dst->create<StructBlockDecoration>(ctx->Clone(source())); // Clone arguments outside of create() call to have deterministic ordering
auto src = ctx->Clone(source());
return ctx->dst->create<StructBlockDecoration>(src);
} }
} // namespace ast } // namespace ast

View File

@ -55,9 +55,12 @@ uint32_t StructMember::offset() const {
} }
StructMember* StructMember::Clone(CloneContext* ctx) const { StructMember* StructMember::Clone(CloneContext* ctx) const {
return ctx->dst->create<StructMember>(ctx->Clone(source()), // Clone arguments outside of create() call to have deterministic ordering
ctx->Clone(symbol_), ctx->Clone(type_), auto src = ctx->Clone(source());
ctx->Clone(decorations_)); auto sym = ctx->Clone(symbol_);
auto* ty = ctx->Clone(type_);
auto decos = ctx->Clone(decorations_);
return ctx->dst->create<StructMember>(src, sym, ty, decos);
} }
bool StructMember::IsValid() const { bool StructMember::IsValid() const {

View File

@ -37,8 +37,9 @@ void StructMemberOffsetDecoration::to_str(const semantic::Info&,
StructMemberOffsetDecoration* StructMemberOffsetDecoration::Clone( StructMemberOffsetDecoration* StructMemberOffsetDecoration::Clone(
CloneContext* ctx) const { CloneContext* ctx) const {
return ctx->dst->create<StructMemberOffsetDecoration>(ctx->Clone(source()), // Clone arguments outside of create() call to have deterministic ordering
offset_); auto src = ctx->Clone(source());
return ctx->dst->create<StructMemberOffsetDecoration>(src, offset_);
} }
} // namespace ast } // namespace ast

View File

@ -33,8 +33,11 @@ SwitchStatement::SwitchStatement(SwitchStatement&&) = default;
SwitchStatement::~SwitchStatement() = default; SwitchStatement::~SwitchStatement() = default;
SwitchStatement* SwitchStatement::Clone(CloneContext* ctx) const { SwitchStatement* SwitchStatement::Clone(CloneContext* ctx) const {
return ctx->dst->create<SwitchStatement>( // Clone arguments outside of create() call to have deterministic ordering
ctx->Clone(source()), ctx->Clone(condition_), ctx->Clone(body_)); auto src = ctx->Clone(source());
auto* cond = ctx->Clone(condition());
auto b = ctx->Clone(body());
return ctx->dst->create<SwitchStatement>(src, cond, b);
} }
bool SwitchStatement::IsValid() const { bool SwitchStatement::IsValid() const {

View File

@ -34,8 +34,11 @@ TypeConstructorExpression::~TypeConstructorExpression() = default;
TypeConstructorExpression* TypeConstructorExpression::Clone( TypeConstructorExpression* TypeConstructorExpression::Clone(
CloneContext* ctx) const { CloneContext* ctx) const {
return ctx->dst->create<TypeConstructorExpression>( // Clone arguments outside of create() call to have deterministic ordering
ctx->Clone(source()), ctx->Clone(type_), ctx->Clone(values_)); auto src = ctx->Clone(source());
auto* ty = ctx->Clone(type());
auto vals = ctx->Clone(values());
return ctx->dst->create<TypeConstructorExpression>(src, ty, vals);
} }
bool TypeConstructorExpression::IsValid() const { bool TypeConstructorExpression::IsValid() const {

View File

@ -36,8 +36,10 @@ std::string UintLiteral::name() const {
} }
UintLiteral* UintLiteral::Clone(CloneContext* ctx) const { UintLiteral* UintLiteral::Clone(CloneContext* ctx) const {
return ctx->dst->create<UintLiteral>(ctx->Clone(source()), ctx->Clone(type()), // Clone arguments outside of create() call to have deterministic ordering
value_); auto src = ctx->Clone(source());
auto* ty = ctx->Clone(type());
return ctx->dst->create<UintLiteral>(src, ty, value_);
} }
} // namespace ast } // namespace ast

View File

@ -32,8 +32,10 @@ UnaryOpExpression::UnaryOpExpression(UnaryOpExpression&&) = default;
UnaryOpExpression::~UnaryOpExpression() = default; UnaryOpExpression::~UnaryOpExpression() = default;
UnaryOpExpression* UnaryOpExpression::Clone(CloneContext* ctx) const { UnaryOpExpression* UnaryOpExpression::Clone(CloneContext* ctx) const {
return ctx->dst->create<UnaryOpExpression>(ctx->Clone(source()), op_, // Clone arguments outside of create() call to have deterministic ordering
ctx->Clone(expr_)); auto src = ctx->Clone(source());
auto* e = ctx->Clone(expr());
return ctx->dst->create<UnaryOpExpression>(src, op_, e);
} }
bool UnaryOpExpression::IsValid() const { bool UnaryOpExpression::IsValid() const {

View File

@ -92,10 +92,13 @@ uint32_t Variable::constant_id() const {
} }
Variable* Variable::Clone(CloneContext* ctx) const { Variable* Variable::Clone(CloneContext* ctx) const {
return ctx->dst->create<Variable>( auto src = ctx->Clone(source());
ctx->Clone(source()), ctx->Clone(symbol_), declared_storage_class(), auto sym = ctx->Clone(symbol());
ctx->Clone(type()), is_const_, ctx->Clone(constructor()), auto* ty = ctx->Clone(type());
ctx->Clone(decorations_)); auto* ctor = ctx->Clone(constructor());
auto decos = ctx->Clone(decorations());
return ctx->dst->create<Variable>(src, sym, declared_storage_class(), ty,
is_const_, ctor, decos);
} }
bool Variable::IsValid() const { bool Variable::IsValid() const {

View File

@ -31,8 +31,10 @@ VariableDeclStatement::VariableDeclStatement(VariableDeclStatement&&) = default;
VariableDeclStatement::~VariableDeclStatement() = default; VariableDeclStatement::~VariableDeclStatement() = default;
VariableDeclStatement* VariableDeclStatement::Clone(CloneContext* ctx) const { VariableDeclStatement* VariableDeclStatement::Clone(CloneContext* ctx) const {
return ctx->dst->create<VariableDeclStatement>(ctx->Clone(source()), // Clone arguments outside of create() call to have deterministic ordering
ctx->Clone(variable_)); auto src = ctx->Clone(source());
auto* var = ctx->Clone(variable());
return ctx->dst->create<VariableDeclStatement>(src, var);
} }
bool VariableDeclStatement::IsValid() const { bool VariableDeclStatement::IsValid() const {

View File

@ -47,8 +47,9 @@ void WorkgroupDecoration::to_str(const semantic::Info&,
} }
WorkgroupDecoration* WorkgroupDecoration::Clone(CloneContext* ctx) const { WorkgroupDecoration* WorkgroupDecoration::Clone(CloneContext* ctx) const {
return ctx->dst->create<WorkgroupDecoration>(ctx->Clone(source()), x_, y_, // Clone arguments outside of create() call to have deterministic ordering
z_); auto src = ctx->Clone(source());
return ctx->dst->create<WorkgroupDecoration>(src, x_, y_, z_);
} }
} // namespace ast } // namespace ast

View File

@ -120,12 +120,14 @@ ast::ArrayAccessorExpression* BoundArrayAccessors::Transform(
return nullptr; return nullptr;
} }
} else { } else {
new_idx = auto* cloned_idx = ctx->Clone(old_idx);
b.Call("min", b.Construct<u32>(ctx->Clone(old_idx)), b.Expr(size - 1)); new_idx = b.Call("min", b.Construct<u32>(cloned_idx), b.Expr(size - 1));
} }
return b.create<ast::ArrayAccessorExpression>( // Clone arguments outside of create() call to have deterministic ordering
ctx->Clone(expr->source()), ctx->Clone(expr->array()), new_idx); auto src = ctx->Clone(expr->source());
auto* arr = ctx->Clone(expr->array());
return b.create<ast::ArrayAccessorExpression>(src, arr, new_idx);
} }
} // namespace transform } // namespace transform

View File

@ -67,14 +67,15 @@ constexpr char kIndexOffsetPrefix[] = "tint_first_index_offset_";
ast::Variable* clone_variable_with_new_name(CloneContext* ctx, ast::Variable* clone_variable_with_new_name(CloneContext* ctx,
ast::Variable* in, ast::Variable* in,
std::string new_name) { std::string new_name) {
// Clone arguments outside of create() call to have deterministic ordering
auto source = ctx->Clone(in->source());
auto symbol = ctx->dst->Symbols().Register(new_name);
auto* type = ctx->Clone(in->type());
auto* constructor = ctx->Clone(in->constructor());
auto decorations = ctx->Clone(in->decorations());
return ctx->dst->create<ast::Variable>( return ctx->dst->create<ast::Variable>(
ctx->Clone(in->source()), // source source, symbol, in->declared_storage_class(), type, in->is_const(),
ctx->dst->Symbols().Register(new_name), // symbol constructor, decorations);
in->declared_storage_class(), // declared_storage_class
ctx->Clone(in->type()), // type
in->is_const(), // is_const
ctx->Clone(in->constructor()), // constructor
ctx->Clone(in->decorations())); // decorations
} }
} // namespace } // namespace

View File

@ -40,12 +40,16 @@ ast::Function* Transform::CloneWithStatementsAtStart(
for (auto* s : *in->body()) { for (auto* s : *in->body()) {
statements.emplace_back(ctx->Clone(s)); statements.emplace_back(ctx->Clone(s));
} }
return ctx->dst->create<ast::Function>( // Clone arguments outside of create() call to have deterministic ordering
ctx->Clone(in->source()), ctx->Clone(in->symbol()), auto source = ctx->Clone(in->source());
ctx->Clone(in->params()), ctx->Clone(in->return_type()), auto symbol = ctx->Clone(in->symbol());
ctx->dst->create<ast::BlockStatement>(ctx->Clone(in->body()->source()), auto params = ctx->Clone(in->params());
statements), auto* return_type = ctx->Clone(in->return_type());
ctx->Clone(in->decorations())); auto* body = ctx->dst->create<ast::BlockStatement>(
ctx->Clone(in->body()->source()), statements);
auto decos = ctx->Clone(in->decorations());
return ctx->dst->create<ast::Function>(source, symbol, params, return_type,
body, decos);
} }
} // namespace transform } // namespace transform

View File

@ -77,7 +77,9 @@ uint64_t AccessControl::BaseAlignment(MemoryLayout mem_layout) const {
} }
AccessControl* AccessControl::Clone(CloneContext* ctx) const { AccessControl* AccessControl::Clone(CloneContext* ctx) const {
return ctx->dst->create<AccessControl>(access_, ctx->Clone(subtype_)); // Clone arguments outside of create() call to have deterministic ordering
auto* ty = ctx->Clone(type());
return ctx->dst->create<AccessControl>(access_, ty);
} }
} // namespace type } // namespace type

View File

@ -50,7 +50,10 @@ uint64_t Alias::BaseAlignment(MemoryLayout mem_layout) const {
} }
Alias* Alias::Clone(CloneContext* ctx) const { Alias* Alias::Clone(CloneContext* ctx) const {
return ctx->dst->create<Alias>(ctx->Clone(symbol()), ctx->Clone(subtype_)); // Clone arguments outside of create() call to have deterministic ordering
auto sym = ctx->Clone(symbol());
auto* ty = ctx->Clone(type());
return ctx->dst->create<Alias>(sym, ty);
} }
} // namespace type } // namespace type

View File

@ -109,8 +109,10 @@ std::string Array::FriendlyName(const SymbolTable& symbols) const {
} }
Array* Array::Clone(CloneContext* ctx) const { Array* Array::Clone(CloneContext* ctx) const {
return ctx->dst->create<Array>(ctx->Clone(subtype_), size_, // Clone arguments outside of create() call to have deterministic ordering
ctx->Clone(decorations())); auto* ty = ctx->Clone(type());
auto decos = ctx->Clone(decorations());
return ctx->dst->create<Array>(ty, size_, decos);
} }
} // namespace type } // namespace type

View File

@ -63,7 +63,9 @@ uint64_t Matrix::BaseAlignment(MemoryLayout mem_layout) const {
} }
Matrix* Matrix::Clone(CloneContext* ctx) const { Matrix* Matrix::Clone(CloneContext* ctx) const {
return ctx->dst->create<Matrix>(ctx->Clone(subtype_), rows_, columns_); // Clone arguments outside of create() call to have deterministic ordering
auto* ty = ctx->Clone(type());
return ctx->dst->create<Matrix>(ty, rows_, columns_);
} }
} // namespace type } // namespace type

View File

@ -49,7 +49,9 @@ std::string MultisampledTexture::FriendlyName(
} }
MultisampledTexture* MultisampledTexture::Clone(CloneContext* ctx) const { MultisampledTexture* MultisampledTexture::Clone(CloneContext* ctx) const {
return ctx->dst->create<MultisampledTexture>(dim(), ctx->Clone(type_)); // Clone arguments outside of create() call to have deterministic ordering
auto* ty = ctx->Clone(type());
return ctx->dst->create<MultisampledTexture>(dim(), ty);
} }
} // namespace type } // namespace type

View File

@ -46,7 +46,9 @@ Pointer::Pointer(Pointer&&) = default;
Pointer::~Pointer() = default; Pointer::~Pointer() = default;
Pointer* Pointer::Clone(CloneContext* ctx) const { Pointer* Pointer::Clone(CloneContext* ctx) const {
return ctx->dst->create<Pointer>(ctx->Clone(subtype_), storage_class_); // Clone arguments outside of create() call to have deterministic ordering
auto* ty = ctx->Clone(type());
return ctx->dst->create<Pointer>(ty, storage_class_);
} }
} // namespace type } // namespace type

View File

@ -47,7 +47,9 @@ std::string SampledTexture::FriendlyName(const SymbolTable& symbols) const {
} }
SampledTexture* SampledTexture::Clone(CloneContext* ctx) const { SampledTexture* SampledTexture::Clone(CloneContext* ctx) const {
return ctx->dst->create<SampledTexture>(dim(), ctx->Clone(type_)); // Clone arguments outside of create() call to have deterministic ordering
auto* ty = ctx->Clone(type());
return ctx->dst->create<SampledTexture>(dim(), ty);
} }
} // namespace type } // namespace type

View File

@ -163,8 +163,9 @@ std::string StorageTexture::FriendlyName(const SymbolTable&) const {
} }
StorageTexture* StorageTexture::Clone(CloneContext* ctx) const { StorageTexture* StorageTexture::Clone(CloneContext* ctx) const {
return ctx->dst->create<StorageTexture>(dim(), image_format_, // Clone arguments outside of create() call to have deterministic ordering
ctx->Clone(subtype_)); auto* ty = ctx->Clone(type());
return ctx->dst->create<StorageTexture>(dim(), image_format_, ty);
} }
type::Type* StorageTexture::SubtypeFor(type::ImageFormat format, type::Type* StorageTexture::SubtypeFor(type::ImageFormat format,

View File

@ -87,7 +87,10 @@ uint64_t Struct::BaseAlignment(MemoryLayout mem_layout) const {
} }
Struct* Struct::Clone(CloneContext* ctx) const { Struct* Struct::Clone(CloneContext* ctx) const {
return ctx->dst->create<Struct>(ctx->Clone(symbol()), ctx->Clone(struct_)); // Clone arguments outside of create() call to have deterministic ordering
auto sym = ctx->Clone(symbol());
auto* str = ctx->Clone(impl());
return ctx->dst->create<Struct>(sym, str);
} }
} // namespace type } // namespace type

View File

@ -59,7 +59,9 @@ uint64_t Vector::BaseAlignment(MemoryLayout mem_layout) const {
} }
Vector* Vector::Clone(CloneContext* ctx) const { Vector* Vector::Clone(CloneContext* ctx) const {
return ctx->dst->create<Vector>(ctx->Clone(subtype_), size_); // Clone arguments outside of create() call to have deterministic ordering
auto* ty = ctx->Clone(type());
return ctx->dst->create<Vector>(ty, size_);
} }
} // namespace type } // namespace type