reader/spirv: Replace std::make_unique<T> -> create<T>

create() is currently just a simple forwarder to std::make_unique<>, but
will be later replaced with a function that returns a raw pointer,
and owned by the context.

Bug: tint:322
Change-Id: I72558482c4b6aff7a655087ee010b3e16b006192
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/32860
Commit-Queue: Ben Clayton <bclayton@google.com>
Reviewed-by: dan sinclair <dsinclair@chromium.org>
This commit is contained in:
Ben Clayton 2020-11-16 15:21:07 +00:00 committed by Commit Bot service account
parent eeac0c5f63
commit 307919dba9
4 changed files with 211 additions and 212 deletions

View File

@ -502,9 +502,8 @@ FunctionEmitter::StatementBlock::~StatementBlock() = default;
void FunctionEmitter::PushNewStatementBlock(const Construct* construct, void FunctionEmitter::PushNewStatementBlock(const Construct* construct,
uint32_t end_id, uint32_t end_id,
CompletionAction action) { CompletionAction action) {
statements_stack_.emplace_back( statements_stack_.emplace_back(StatementBlock{
StatementBlock{construct, end_id, action, construct, end_id, action, create<ast::BlockStatement>(), nullptr});
std::make_unique<ast::BlockStatement>(), nullptr});
} }
void FunctionEmitter::PushGuard(const std::string& guard_name, void FunctionEmitter::PushGuard(const std::string& guard_name,
@ -515,10 +514,10 @@ void FunctionEmitter::PushGuard(const std::string& guard_name,
// if-selection with a then-clause ending at the same block // if-selection with a then-clause ending at the same block
// as the statement block at the top of the stack. // as the statement block at the top of the stack.
const auto& top = statements_stack_.back(); const auto& top = statements_stack_.back();
auto cond = std::make_unique<ast::IdentifierExpression>(guard_name); auto cond = create<ast::IdentifierExpression>(guard_name);
auto body = std::make_unique<ast::BlockStatement>(); auto body = create<ast::BlockStatement>();
auto* const guard_stmt = AddStatement(std::make_unique<ast::IfStatement>( auto* const guard_stmt =
std::move(cond), std::move(body))) AddStatement(create<ast::IfStatement>(std::move(cond), std::move(body)))
->AsIf(); ->AsIf();
PushNewStatementBlock(top.construct_, end_id, PushNewStatementBlock(top.construct_, end_id,
[guard_stmt](StatementBlock* s) { [guard_stmt](StatementBlock* s) {
@ -530,9 +529,9 @@ void FunctionEmitter::PushTrueGuard(uint32_t end_id) {
assert(!statements_stack_.empty()); assert(!statements_stack_.empty());
const auto& top = statements_stack_.back(); const auto& top = statements_stack_.back();
auto cond = MakeTrue(); auto cond = MakeTrue();
auto body = std::make_unique<ast::BlockStatement>(); auto body = create<ast::BlockStatement>();
auto* const guard_stmt = AddStatement(std::make_unique<ast::IfStatement>( auto* const guard_stmt =
std::move(cond), std::move(body))) AddStatement(create<ast::IfStatement>(std::move(cond), std::move(body)))
->AsIf(); ->AsIf();
guard_stmt->set_condition(MakeTrue()); guard_stmt->set_condition(MakeTrue());
PushNewStatementBlock(top.construct_, end_id, PushNewStatementBlock(top.construct_, end_id,
@ -649,13 +648,12 @@ bool FunctionEmitter::EmitFunctionDeclaration() {
return false; return false;
} }
auto ast_fn = auto ast_fn = create<ast::Function>(name, std::move(ast_params), ret_ty,
std::make_unique<ast::Function>(name, std::move(ast_params), ret_ty, create<ast::BlockStatement>());
std::make_unique<ast::BlockStatement>());
if (ep_info_ != nullptr) { if (ep_info_ != nullptr) {
ast_fn->add_decoration( ast_fn->add_decoration(
std::make_unique<ast::StageDecoration>(ep_info_->stage, Source{})); create<ast::StageDecoration>(ep_info_->stage, Source{}));
} }
ast_module_.AddFunction(std::move(ast_fn)); ast_module_.AddFunction(std::move(ast_fn));
@ -1707,8 +1705,7 @@ bool FunctionEmitter::EmitFunctionVariables() {
parser_impl_.MakeConstantExpression(inst.GetSingleWordInOperand(1)) parser_impl_.MakeConstantExpression(inst.GetSingleWordInOperand(1))
.expr); .expr);
} }
auto var_decl_stmt = auto var_decl_stmt = create<ast::VariableDeclStatement>(std::move(var));
std::make_unique<ast::VariableDeclStatement>(std::move(var));
AddStatementForInstruction(std::move(var_decl_stmt), inst); AddStatementForInstruction(std::move(var_decl_stmt), inst);
// Save this as an already-named value. // Save this as an already-named value.
identifier_values_.insert(inst.result_id()); identifier_values_.insert(inst.result_id());
@ -1723,7 +1720,7 @@ TypedExpression FunctionEmitter::MakeExpression(uint32_t id) {
if (identifier_values_.count(id) || parser_impl_.IsScalarSpecConstant(id)) { if (identifier_values_.count(id) || parser_impl_.IsScalarSpecConstant(id)) {
return TypedExpression( return TypedExpression(
parser_impl_.ConvertType(def_use_mgr_->GetDef(id)->type_id()), parser_impl_.ConvertType(def_use_mgr_->GetDef(id)->type_id()),
std::make_unique<ast::IdentifierExpression>(namer_.Name(id))); create<ast::IdentifierExpression>(namer_.Name(id)));
} }
if (singly_used_values_.count(id)) { if (singly_used_values_.count(id)) {
auto expr = std::move(singly_used_values_[id]); auto expr = std::move(singly_used_values_[id]);
@ -1742,9 +1739,9 @@ TypedExpression FunctionEmitter::MakeExpression(uint32_t id) {
switch (inst->opcode()) { switch (inst->opcode()) {
case SpvOpVariable: case SpvOpVariable:
// This occurs for module-scope variables. // This occurs for module-scope variables.
return TypedExpression(parser_impl_.ConvertType(inst->type_id()), return TypedExpression(
std::make_unique<ast::IdentifierExpression>( parser_impl_.ConvertType(inst->type_id()),
namer_.Name(inst->result_id()))); create<ast::IdentifierExpression>(namer_.Name(inst->result_id())));
default: default:
break; break;
} }
@ -1973,20 +1970,19 @@ bool FunctionEmitter::EmitIfStart(const BlockInfo& block_info) {
const std::string guard_name = block_info.flow_guard_name; const std::string guard_name = block_info.flow_guard_name;
if (!guard_name.empty()) { if (!guard_name.empty()) {
// Declare the guard variable just before the "if", initialized to true. // Declare the guard variable just before the "if", initialized to true.
auto guard_var = std::make_unique<ast::Variable>( auto guard_var = create<ast::Variable>(
guard_name, ast::StorageClass::kFunction, parser_impl_.BoolType()); guard_name, ast::StorageClass::kFunction, parser_impl_.BoolType());
guard_var->set_constructor(MakeTrue()); guard_var->set_constructor(MakeTrue());
auto guard_decl = auto guard_decl = create<ast::VariableDeclStatement>(std::move(guard_var));
std::make_unique<ast::VariableDeclStatement>(std::move(guard_var));
AddStatement(std::move(guard_decl)); AddStatement(std::move(guard_decl));
} }
const auto condition_id = const auto condition_id =
block_info.basic_block->terminator()->GetSingleWordInOperand(0); block_info.basic_block->terminator()->GetSingleWordInOperand(0);
auto cond = MakeExpression(condition_id).expr; auto cond = MakeExpression(condition_id).expr;
auto body = std::make_unique<ast::BlockStatement>(); auto body = create<ast::BlockStatement>();
auto* const if_stmt = AddStatement(std::make_unique<ast::IfStatement>( auto* const if_stmt =
std::move(cond), std::move(body))) AddStatement(create<ast::IfStatement>(std::move(cond), std::move(body)))
->AsIf(); ->AsIf();
// Generate the code for the condition. // Generate the code for the condition.
@ -2040,14 +2036,15 @@ bool FunctionEmitter::EmitIfStart(const BlockInfo& block_info) {
auto push_else = [this, if_stmt, else_end, construct]() { auto push_else = [this, if_stmt, else_end, construct]() {
// Push the else clause onto the stack first. // Push the else clause onto the stack first.
PushNewStatementBlock(construct, else_end, [if_stmt](StatementBlock* s) { PushNewStatementBlock(
construct, else_end, [this, if_stmt](StatementBlock* s) {
// Only set the else-clause if there are statements to fill it. // Only set the else-clause if there are statements to fill it.
if (!s->statements_->empty()) { if (!s->statements_->empty()) {
// The "else" consists of the statement list from the top of statments // The "else" consists of the statement list from the top of
// stack, without an elseif condition. // statments stack, without an elseif condition.
ast::ElseStatementList else_stmts; ast::ElseStatementList else_stmts;
else_stmts.emplace_back(std::make_unique<ast::ElseStatement>( else_stmts.emplace_back(
nullptr, std::move(s->statements_))); create<ast::ElseStatement>(nullptr, std::move(s->statements_)));
if_stmt->set_else_statements(std::move(else_stmts)); if_stmt->set_else_statements(std::move(else_stmts));
} }
}); });
@ -2099,7 +2096,7 @@ bool FunctionEmitter::EmitSwitchStart(const BlockInfo& block_info) {
const auto* branch = block_info.basic_block->terminator(); const auto* branch = block_info.basic_block->terminator();
auto* const switch_stmt = auto* const switch_stmt =
AddStatement(std::make_unique<ast::SwitchStatement>())->AsSwitch(); AddStatement(create<ast::SwitchStatement>())->AsSwitch();
const auto selector_id = branch->GetSingleWordInOperand(0); const auto selector_id = branch->GetSingleWordInOperand(0);
// Generate the code for the selector. // Generate the code for the selector.
auto selector = MakeExpression(selector_id); auto selector = MakeExpression(selector_id);
@ -2111,7 +2108,7 @@ bool FunctionEmitter::EmitSwitchStart(const BlockInfo& block_info) {
construct, construct->end_id, [switch_stmt](StatementBlock* s) { construct, construct->end_id, [switch_stmt](StatementBlock* s) {
switch_stmt->set_body(std::move(*std::move(s->cases_))); switch_stmt->set_body(std::move(*std::move(s->cases_)));
}); });
statements_stack_.back().cases_ = std::make_unique<ast::CaseStatementList>(); statements_stack_.back().cases_ = create<ast::CaseStatementList>();
// Grab a pointer to the case list. It will get buried in the statement block // Grab a pointer to the case list. It will get buried in the statement block
// stack. // stack.
auto* cases = statements_stack_.back().cases_.get(); auto* cases = statements_stack_.back().cases_.get();
@ -2157,8 +2154,8 @@ bool FunctionEmitter::EmitSwitchStart(const BlockInfo& block_info) {
for (size_t i = last_clause_index;; --i) { for (size_t i = last_clause_index;; --i) {
// Create the case clause. Temporarily put it in the wrong order // Create the case clause. Temporarily put it in the wrong order
// on the case statement list. // on the case statement list.
cases->emplace_back(std::make_unique<ast::CaseStatement>( cases->emplace_back(
std::make_unique<ast::BlockStatement>())); create<ast::CaseStatement>(create<ast::BlockStatement>()));
auto* clause = cases->back().get(); auto* clause = cases->back().get();
// Create a list of integer literals for the selector values leading to // Create a list of integer literals for the selector values leading to
@ -2175,10 +2172,10 @@ bool FunctionEmitter::EmitSwitchStart(const BlockInfo& block_info) {
const uint32_t value32 = uint32_t(value & 0xFFFFFFFF); const uint32_t value32 = uint32_t(value & 0xFFFFFFFF);
if (selector.type->is_unsigned_scalar_or_vector()) { if (selector.type->is_unsigned_scalar_or_vector()) {
selectors.emplace_back( selectors.emplace_back(
std::make_unique<ast::UintLiteral>(selector.type, value32)); create<ast::UintLiteral>(selector.type, value32));
} else { } else {
selectors.emplace_back( selectors.emplace_back(
std::make_unique<ast::SintLiteral>(selector.type, value32)); create<ast::SintLiteral>(selector.type, value32));
} }
} }
clause->set_selectors(std::move(selectors)); clause->set_selectors(std::move(selectors));
@ -2195,9 +2192,9 @@ bool FunctionEmitter::EmitSwitchStart(const BlockInfo& block_info) {
if ((default_info == clause_heads[i]) && has_selectors && if ((default_info == clause_heads[i]) && has_selectors &&
construct->ContainsPos(default_info->pos)) { construct->ContainsPos(default_info->pos)) {
// Generate a default clause with a just fallthrough. // Generate a default clause with a just fallthrough.
auto stmts = std::make_unique<ast::BlockStatement>(); auto stmts = create<ast::BlockStatement>();
stmts->append(std::make_unique<ast::FallthroughStatement>()); stmts->append(create<ast::FallthroughStatement>());
auto case_stmt = std::make_unique<ast::CaseStatement>(std::move(stmts)); auto case_stmt = create<ast::CaseStatement>(std::move(stmts));
cases->emplace_back(std::move(case_stmt)); cases->emplace_back(std::move(case_stmt));
} }
@ -2214,9 +2211,9 @@ bool FunctionEmitter::EmitSwitchStart(const BlockInfo& block_info) {
} }
bool FunctionEmitter::EmitLoopStart(const Construct* construct) { bool FunctionEmitter::EmitLoopStart(const Construct* construct) {
auto* loop = AddStatement(std::make_unique<ast::LoopStatement>( auto* loop =
std::make_unique<ast::BlockStatement>(), AddStatement(create<ast::LoopStatement>(create<ast::BlockStatement>(),
std::make_unique<ast::BlockStatement>())) create<ast::BlockStatement>()))
->AsLoop(); ->AsLoop();
PushNewStatementBlock( PushNewStatementBlock(
construct, construct->end_id, construct, construct->end_id,
@ -2244,18 +2241,17 @@ bool FunctionEmitter::EmitNormalTerminator(const BlockInfo& block_info) {
const auto& terminator = *(block_info.basic_block->terminator()); const auto& terminator = *(block_info.basic_block->terminator());
switch (terminator.opcode()) { switch (terminator.opcode()) {
case SpvOpReturn: case SpvOpReturn:
AddStatement(std::make_unique<ast::ReturnStatement>()); AddStatement(create<ast::ReturnStatement>());
return true; return true;
case SpvOpReturnValue: { case SpvOpReturnValue: {
auto value = MakeExpression(terminator.GetSingleWordInOperand(0)); auto value = MakeExpression(terminator.GetSingleWordInOperand(0));
AddStatement( AddStatement(create<ast::ReturnStatement>(std::move(value.expr)));
std::make_unique<ast::ReturnStatement>(std::move(value.expr)));
} }
return true; return true;
case SpvOpKill: case SpvOpKill:
// For now, assume SPIR-V OpKill has same semantics as WGSL discard. // For now, assume SPIR-V OpKill has same semantics as WGSL discard.
// TODO(dneto): https://github.com/gpuweb/gpuweb/issues/676 // TODO(dneto): https://github.com/gpuweb/gpuweb/issues/676
AddStatement(std::make_unique<ast::DiscardStatement>()); AddStatement(create<ast::DiscardStatement>());
return true; return true;
case SpvOpUnreachable: case SpvOpUnreachable:
// Translate as if it's a return. This avoids the problem where WGSL // Translate as if it's a return. This avoids the problem where WGSL
@ -2263,10 +2259,10 @@ bool FunctionEmitter::EmitNormalTerminator(const BlockInfo& block_info) {
{ {
const auto* result_type = type_mgr_->GetType(function_.type_id()); const auto* result_type = type_mgr_->GetType(function_.type_id());
if (result_type->AsVoid() != nullptr) { if (result_type->AsVoid() != nullptr) {
AddStatement(std::make_unique<ast::ReturnStatement>()); AddStatement(create<ast::ReturnStatement>());
} else { } else {
auto* ast_type = parser_impl_.ConvertType(function_.type_id()); auto* ast_type = parser_impl_.ConvertType(function_.type_id());
AddStatement(std::make_unique<ast::ReturnStatement>( AddStatement(create<ast::ReturnStatement>(
parser_impl_.MakeNullValue(ast_type))); parser_impl_.MakeNullValue(ast_type)));
} }
} }
@ -2350,7 +2346,7 @@ std::unique_ptr<ast::Statement> FunctionEmitter::MakeBranchDetailed(
break; break;
case EdgeKind::kSwitchBreak: { case EdgeKind::kSwitchBreak: {
if (forced) { if (forced) {
return std::make_unique<ast::BreakStatement>(); return create<ast::BreakStatement>();
} }
// Unless forced, don't bother with a break at the end of a case/default // Unless forced, don't bother with a break at the end of a case/default
// clause. // clause.
@ -2375,10 +2371,10 @@ std::unique_ptr<ast::Statement> FunctionEmitter::MakeBranchDetailed(
} }
} }
// We need a break. // We need a break.
return std::make_unique<ast::BreakStatement>(); return create<ast::BreakStatement>();
} }
case EdgeKind::kLoopBreak: case EdgeKind::kLoopBreak:
return std::make_unique<ast::BreakStatement>(); return create<ast::BreakStatement>();
case EdgeKind::kLoopContinue: case EdgeKind::kLoopContinue:
// An unconditional continue to the next block is redundant and ugly. // An unconditional continue to the next block is redundant and ugly.
// Skip it in that case. // Skip it in that case.
@ -2386,7 +2382,7 @@ std::unique_ptr<ast::Statement> FunctionEmitter::MakeBranchDetailed(
break; break;
} }
// Otherwise, emit a regular continue statement. // Otherwise, emit a regular continue statement.
return std::make_unique<ast::ContinueStatement>(); return create<ast::ContinueStatement>();
case EdgeKind::kIfBreak: { case EdgeKind::kIfBreak: {
const auto& flow_guard = const auto& flow_guard =
GetBlockInfo(dest_info.header_for_merge)->flow_guard_name; GetBlockInfo(dest_info.header_for_merge)->flow_guard_name;
@ -2395,9 +2391,8 @@ std::unique_ptr<ast::Statement> FunctionEmitter::MakeBranchDetailed(
*flow_guard_name_ptr = flow_guard; *flow_guard_name_ptr = flow_guard;
} }
// Signal an exit from the branch. // Signal an exit from the branch.
return std::make_unique<ast::AssignmentStatement>( return create<ast::AssignmentStatement>(
std::make_unique<ast::IdentifierExpression>(flow_guard), create<ast::IdentifierExpression>(flow_guard), MakeFalse());
MakeFalse());
} }
// For an unconditional branch, the break out to an if-selection // For an unconditional branch, the break out to an if-selection
@ -2405,7 +2400,7 @@ std::unique_ptr<ast::Statement> FunctionEmitter::MakeBranchDetailed(
break; break;
} }
case EdgeKind::kCaseFallThrough: case EdgeKind::kCaseFallThrough:
return std::make_unique<ast::FallthroughStatement>(); return create<ast::FallthroughStatement>();
case EdgeKind::kForward: case EdgeKind::kForward:
// Unconditional forward branch is implicit. // Unconditional forward branch is implicit.
break; break;
@ -2420,19 +2415,19 @@ std::unique_ptr<ast::Statement> FunctionEmitter::MakeSimpleIf(
if ((then_stmt == nullptr) && (else_stmt == nullptr)) { if ((then_stmt == nullptr) && (else_stmt == nullptr)) {
return nullptr; return nullptr;
} }
auto if_stmt = std::make_unique<ast::IfStatement>( auto if_stmt = create<ast::IfStatement>(std::move(condition),
std::move(condition), std::make_unique<ast::BlockStatement>()); create<ast::BlockStatement>());
if (then_stmt != nullptr) { if (then_stmt != nullptr) {
auto stmts = std::make_unique<ast::BlockStatement>(); auto stmts = create<ast::BlockStatement>();
stmts->append(std::move(then_stmt)); stmts->append(std::move(then_stmt));
if_stmt->set_body(std::move(stmts)); if_stmt->set_body(std::move(stmts));
} }
if (else_stmt != nullptr) { if (else_stmt != nullptr) {
auto stmts = std::make_unique<ast::BlockStatement>(); auto stmts = create<ast::BlockStatement>();
stmts->append(std::move(else_stmt)); stmts->append(std::move(else_stmt));
ast::ElseStatementList else_stmts; ast::ElseStatementList else_stmts;
else_stmts.emplace_back( else_stmts.emplace_back(
std::make_unique<ast::ElseStatement>(nullptr, std::move(stmts))); create<ast::ElseStatement>(nullptr, std::move(stmts)));
if_stmt->set_else_statements(std::move(else_stmts)); if_stmt->set_else_statements(std::move(else_stmts));
} }
return if_stmt; return if_stmt;
@ -2479,7 +2474,7 @@ bool FunctionEmitter::EmitConditionalCaseFallThrough(
AddStatement( AddStatement(
MakeSimpleIf(std::move(cond), std::move(other_branch), nullptr)); MakeSimpleIf(std::move(cond), std::move(other_branch), nullptr));
} }
AddStatement(std::make_unique<ast::FallthroughStatement>()); AddStatement(create<ast::FallthroughStatement>());
return success(); return success();
} }
@ -2506,7 +2501,7 @@ bool FunctionEmitter::EmitStatementsInBasicBlock(const BlockInfo& block_info,
assert(def_inst); assert(def_inst);
auto* ast_type = auto* ast_type =
RemapStorageClass(parser_impl_.ConvertType(def_inst->type_id()), id); RemapStorageClass(parser_impl_.ConvertType(def_inst->type_id()), id);
AddStatement(std::make_unique<ast::VariableDeclStatement>( AddStatement(create<ast::VariableDeclStatement>(
parser_impl_.MakeVariable(id, ast::StorageClass::kFunction, ast_type))); parser_impl_.MakeVariable(id, ast::StorageClass::kFunction, ast_type)));
// Save this as an already-named value. // Save this as an already-named value.
identifier_values_.insert(id); identifier_values_.insert(id);
@ -2517,10 +2512,10 @@ bool FunctionEmitter::EmitStatementsInBasicBlock(const BlockInfo& block_info,
assert(def_inst); assert(def_inst);
const auto phi_var_name = GetDefInfo(id)->phi_var; const auto phi_var_name = GetDefInfo(id)->phi_var;
assert(!phi_var_name.empty()); assert(!phi_var_name.empty());
auto var = std::make_unique<ast::Variable>( auto var =
phi_var_name, ast::StorageClass::kFunction, create<ast::Variable>(phi_var_name, ast::StorageClass::kFunction,
parser_impl_.ConvertType(def_inst->type_id())); parser_impl_.ConvertType(def_inst->type_id()));
AddStatement(std::make_unique<ast::VariableDeclStatement>(std::move(var))); AddStatement(create<ast::VariableDeclStatement>(std::move(var)));
} }
// Emit regular statements. // Emit regular statements.
@ -2550,9 +2545,8 @@ bool FunctionEmitter::EmitStatementsInBasicBlock(const BlockInfo& block_info,
for (auto assignment : block_info.phi_assignments) { for (auto assignment : block_info.phi_assignments) {
const auto var_name = GetDefInfo(assignment.phi_id)->phi_var; const auto var_name = GetDefInfo(assignment.phi_id)->phi_var;
auto expr = MakeExpression(assignment.value); auto expr = MakeExpression(assignment.value);
AddStatement(std::make_unique<ast::AssignmentStatement>( AddStatement(create<ast::AssignmentStatement>(
std::make_unique<ast::IdentifierExpression>(var_name), create<ast::IdentifierExpression>(var_name), std::move(expr.expr)));
std::move(expr.expr)));
} }
} }
@ -2574,7 +2568,7 @@ bool FunctionEmitter::EmitConstDefinition(
ast_const->set_constructor(std::move(ast_expr.expr)); ast_const->set_constructor(std::move(ast_expr.expr));
ast_const->set_is_const(true); ast_const->set_is_const(true);
AddStatementForInstruction( AddStatementForInstruction(
std::make_unique<ast::VariableDeclStatement>(std::move(ast_const)), inst); create<ast::VariableDeclStatement>(std::move(ast_const)), inst);
// Save this as an already-named value. // Save this as an already-named value.
identifier_values_.insert(inst.result_id()); identifier_values_.insert(inst.result_id());
return success(); return success();
@ -2588,8 +2582,8 @@ bool FunctionEmitter::EmitConstDefOrWriteToHoistedVar(
if (def_info && def_info->requires_hoisted_def) { if (def_info && def_info->requires_hoisted_def) {
// Emit an assignment of the expression to the hoisted variable. // Emit an assignment of the expression to the hoisted variable.
AddStatementForInstruction( AddStatementForInstruction(
std::make_unique<ast::AssignmentStatement>( create<ast::AssignmentStatement>(
std::make_unique<ast::IdentifierExpression>(namer_.Name(result_id)), create<ast::IdentifierExpression>(namer_.Name(result_id)),
std::move(ast_expr.expr)), std::move(ast_expr.expr)),
inst); inst);
return true; return true;
@ -2654,7 +2648,7 @@ bool FunctionEmitter::EmitStatement(const spvtools::opt::Instruction& inst) {
// TODO(dneto): Order of evaluation? // TODO(dneto): Order of evaluation?
auto lhs = MakeExpression(ptr_id); auto lhs = MakeExpression(ptr_id);
auto rhs = MakeExpression(value_id); auto rhs = MakeExpression(value_id);
AddStatementForInstruction(std::make_unique<ast::AssignmentStatement>( AddStatementForInstruction(create<ast::AssignmentStatement>(
std::move(lhs.expr), std::move(rhs.expr)), std::move(lhs.expr), std::move(rhs.expr)),
inst); inst);
return success(); return success();
@ -2678,9 +2672,9 @@ bool FunctionEmitter::EmitStatement(const spvtools::opt::Instruction& inst) {
} }
case SpvOpPhi: { case SpvOpPhi: {
// Emit a read from the associated state variable. // Emit a read from the associated state variable.
auto expr = TypedExpression( auto expr =
parser_impl_.ConvertType(inst.type_id()), TypedExpression(parser_impl_.ConvertType(inst.type_id()),
std::make_unique<ast::IdentifierExpression>(def_info->phi_var)); create<ast::IdentifierExpression>(def_info->phi_var));
return EmitConstDefOrWriteToHoistedVar(inst, std::move(expr)); return EmitConstDefOrWriteToHoistedVar(inst, std::move(expr));
} }
case SpvOpFunctionCall: case SpvOpFunctionCall:
@ -2714,7 +2708,7 @@ TypedExpression FunctionEmitter::MaybeEmitCombinatorialValue(
if (binary_op != ast::BinaryOp::kNone) { if (binary_op != ast::BinaryOp::kNone) {
auto arg0 = MakeOperand(inst, 0); auto arg0 = MakeOperand(inst, 0);
auto arg1 = MakeOperand(inst, 1); auto arg1 = MakeOperand(inst, 1);
auto binary_expr = std::make_unique<ast::BinaryExpression>( auto binary_expr = create<ast::BinaryExpression>(
binary_op, std::move(arg0.expr), std::move(arg1.expr)); binary_op, std::move(arg0.expr), std::move(arg1.expr));
TypedExpression result(ast_type, std::move(binary_expr)); TypedExpression result(ast_type, std::move(binary_expr));
return parser_impl_.RectifyForcedResultType(std::move(result), opcode, return parser_impl_.RectifyForcedResultType(std::move(result), opcode,
@ -2724,8 +2718,8 @@ TypedExpression FunctionEmitter::MaybeEmitCombinatorialValue(
auto unary_op = ast::UnaryOp::kNegation; auto unary_op = ast::UnaryOp::kNegation;
if (GetUnaryOp(opcode, &unary_op)) { if (GetUnaryOp(opcode, &unary_op)) {
auto arg0 = MakeOperand(inst, 0); auto arg0 = MakeOperand(inst, 0);
auto unary_expr = std::make_unique<ast::UnaryOpExpression>( auto unary_expr =
unary_op, std::move(arg0.expr)); create<ast::UnaryOpExpression>(unary_op, std::move(arg0.expr));
TypedExpression result(ast_type, std::move(unary_expr)); TypedExpression result(ast_type, std::move(unary_expr));
return parser_impl_.RectifyForcedResultType(std::move(result), opcode, return parser_impl_.RectifyForcedResultType(std::move(result), opcode,
arg0.type); arg0.type);
@ -2735,9 +2729,8 @@ TypedExpression FunctionEmitter::MaybeEmitCombinatorialValue(
if (unary_builtin_name != nullptr) { if (unary_builtin_name != nullptr) {
ast::ExpressionList params; ast::ExpressionList params;
params.emplace_back(MakeOperand(inst, 0).expr); params.emplace_back(MakeOperand(inst, 0).expr);
return {ast_type, return {ast_type, create<ast::CallExpression>(
std::make_unique<ast::CallExpression>( create<ast::IdentifierExpression>(unary_builtin_name),
std::make_unique<ast::IdentifierExpression>(unary_builtin_name),
std::move(params))}; std::move(params))};
} }
@ -2751,7 +2744,7 @@ TypedExpression FunctionEmitter::MaybeEmitCombinatorialValue(
} }
if (opcode == SpvOpBitcast) { if (opcode == SpvOpBitcast) {
return {ast_type, std::make_unique<ast::BitcastExpression>( return {ast_type, create<ast::BitcastExpression>(
ast_type, MakeOperand(inst, 0).expr)}; ast_type, MakeOperand(inst, 0).expr)};
} }
@ -2759,10 +2752,10 @@ TypedExpression FunctionEmitter::MaybeEmitCombinatorialValue(
if (negated_op != ast::BinaryOp::kNone) { if (negated_op != ast::BinaryOp::kNone) {
auto arg0 = MakeOperand(inst, 0); auto arg0 = MakeOperand(inst, 0);
auto arg1 = MakeOperand(inst, 1); auto arg1 = MakeOperand(inst, 1);
auto binary_expr = std::make_unique<ast::BinaryExpression>( auto binary_expr = create<ast::BinaryExpression>(
negated_op, std::move(arg0.expr), std::move(arg1.expr)); negated_op, std::move(arg0.expr), std::move(arg1.expr));
auto negated_expr = std::make_unique<ast::UnaryOpExpression>( auto negated_expr = create<ast::UnaryOpExpression>(ast::UnaryOp::kNot,
ast::UnaryOp::kNot, std::move(binary_expr)); std::move(binary_expr));
return {ast_type, std::move(negated_expr)}; return {ast_type, std::move(negated_expr)};
} }
@ -2780,7 +2773,7 @@ TypedExpression FunctionEmitter::MaybeEmitCombinatorialValue(
for (uint32_t iarg = 0; iarg < inst.NumInOperands(); ++iarg) { for (uint32_t iarg = 0; iarg < inst.NumInOperands(); ++iarg) {
operands.emplace_back(MakeOperand(inst, iarg).expr); operands.emplace_back(MakeOperand(inst, iarg).expr);
} }
return {ast_type, std::make_unique<ast::TypeConstructorExpression>( return {ast_type, create<ast::TypeConstructorExpression>(
ast_type, std::move(operands))}; ast_type, std::move(operands))};
} }
@ -2838,15 +2831,14 @@ TypedExpression FunctionEmitter::EmitGlslStd450ExtInst(
return {}; return {};
} }
auto func = std::make_unique<ast::IdentifierExpression>(name); auto func = create<ast::IdentifierExpression>(name);
ast::ExpressionList operands; ast::ExpressionList operands;
// All parameters to GLSL.std.450 extended instructions are IDs. // All parameters to GLSL.std.450 extended instructions are IDs.
for (uint32_t iarg = 2; iarg < inst.NumInOperands(); ++iarg) { for (uint32_t iarg = 2; iarg < inst.NumInOperands(); ++iarg) {
operands.emplace_back(MakeOperand(inst, iarg).expr); operands.emplace_back(MakeOperand(inst, iarg).expr);
} }
auto* ast_type = parser_impl_.ConvertType(inst.type_id()); auto* ast_type = parser_impl_.ConvertType(inst.type_id());
auto call = std::make_unique<ast::CallExpression>(std::move(func), auto call = create<ast::CallExpression>(std::move(func), std::move(operands));
std::move(operands));
return {ast_type, std::move(call)}; return {ast_type, std::move(call)};
} }
@ -2913,7 +2905,7 @@ TypedExpression FunctionEmitter::MakeAccessChain(
// Replace the gl_PerVertex reference with the gl_Position reference // Replace the gl_PerVertex reference with the gl_Position reference
ptr_ty_id = builtin_position_info.member_pointer_type_id; ptr_ty_id = builtin_position_info.member_pointer_type_id;
current_expr.expr = current_expr.expr =
std::make_unique<ast::IdentifierExpression>(namer_.Name(base_id)); create<ast::IdentifierExpression>(namer_.Name(base_id));
current_expr.type = parser_impl_.ConvertType(ptr_ty_id); current_expr.type = parser_impl_.ConvertType(ptr_ty_id);
} }
} }
@ -2963,13 +2955,13 @@ TypedExpression FunctionEmitter::MakeAccessChain(
<< " is too big. Max handled index is " << " is too big. Max handled index is "
<< ((sizeof(swizzles) / sizeof(swizzles[0])) - 1); << ((sizeof(swizzles) / sizeof(swizzles[0])) - 1);
} }
auto letter_index = std::make_unique<ast::IdentifierExpression>( auto letter_index =
swizzles[index_const_val]); create<ast::IdentifierExpression>(swizzles[index_const_val]);
next_expr = std::make_unique<ast::MemberAccessorExpression>( next_expr = create<ast::MemberAccessorExpression>(
std::move(current_expr.expr), std::move(letter_index)); std::move(current_expr.expr), std::move(letter_index));
} else { } else {
// Non-constant index. Use array syntax // Non-constant index. Use array syntax
next_expr = std::make_unique<ast::ArrayAccessorExpression>( next_expr = create<ast::ArrayAccessorExpression>(
std::move(current_expr.expr), std::move(current_expr.expr),
std::move(MakeOperand(inst, index).expr)); std::move(MakeOperand(inst, index).expr));
} }
@ -2978,20 +2970,20 @@ TypedExpression FunctionEmitter::MakeAccessChain(
break; break;
case SpvOpTypeMatrix: case SpvOpTypeMatrix:
// Use array syntax. // Use array syntax.
next_expr = std::make_unique<ast::ArrayAccessorExpression>( next_expr = create<ast::ArrayAccessorExpression>(
std::move(current_expr.expr), std::move(current_expr.expr),
std::move(MakeOperand(inst, index).expr)); std::move(MakeOperand(inst, index).expr));
// All matrix components are the same type. // All matrix components are the same type.
pointee_type_id = pointee_type_inst->GetSingleWordInOperand(0); pointee_type_id = pointee_type_inst->GetSingleWordInOperand(0);
break; break;
case SpvOpTypeArray: case SpvOpTypeArray:
next_expr = std::make_unique<ast::ArrayAccessorExpression>( next_expr = create<ast::ArrayAccessorExpression>(
std::move(current_expr.expr), std::move(current_expr.expr),
std::move(MakeOperand(inst, index).expr)); std::move(MakeOperand(inst, index).expr));
pointee_type_id = pointee_type_inst->GetSingleWordInOperand(0); pointee_type_id = pointee_type_inst->GetSingleWordInOperand(0);
break; break;
case SpvOpTypeRuntimeArray: case SpvOpTypeRuntimeArray:
next_expr = std::make_unique<ast::ArrayAccessorExpression>( next_expr = create<ast::ArrayAccessorExpression>(
std::move(current_expr.expr), std::move(current_expr.expr),
std::move(MakeOperand(inst, index).expr)); std::move(MakeOperand(inst, index).expr));
pointee_type_id = pointee_type_inst->GetSingleWordInOperand(0); pointee_type_id = pointee_type_inst->GetSingleWordInOperand(0);
@ -3011,10 +3003,10 @@ TypedExpression FunctionEmitter::MakeAccessChain(
<< pointee_type_id << " having " << num_members << " members"; << pointee_type_id << " having " << num_members << " members";
return {}; return {};
} }
auto member_access = std::make_unique<ast::IdentifierExpression>( auto member_access = create<ast::IdentifierExpression>(
namer_.GetMemberName(pointee_type_id, uint32_t(index_const_val))); namer_.GetMemberName(pointee_type_id, uint32_t(index_const_val)));
next_expr = std::make_unique<ast::MemberAccessorExpression>( next_expr = create<ast::MemberAccessorExpression>(
std::move(current_expr.expr), std::move(member_access)); std::move(current_expr.expr), std::move(member_access));
pointee_type_id = pointee_type_inst->GetSingleWordInOperand( pointee_type_id = pointee_type_inst->GetSingleWordInOperand(
static_cast<uint32_t>(index_const_val)); static_cast<uint32_t>(index_const_val));
@ -3047,10 +3039,10 @@ TypedExpression FunctionEmitter::MakeCompositeExtract(
// expressions. // expressions.
TypedExpression current_expr(MakeOperand(inst, 0)); TypedExpression current_expr(MakeOperand(inst, 0));
auto make_index = [](uint32_t literal) { auto make_index = [this](uint32_t literal) {
ast::type::U32Type u32; ast::type::U32Type u32;
return std::make_unique<ast::ScalarConstructorExpression>( return create<ast::ScalarConstructorExpression>(
std::make_unique<ast::UintLiteral>(&u32, literal)); create<ast::UintLiteral>(&u32, literal));
}; };
static const char* swizzles[] = {"x", "y", "z", "w"}; static const char* swizzles[] = {"x", "y", "z", "w"};
@ -3088,8 +3080,8 @@ TypedExpression FunctionEmitter::MakeCompositeExtract(
<< ((sizeof(swizzles) / sizeof(swizzles[0])) - 1); << ((sizeof(swizzles) / sizeof(swizzles[0])) - 1);
} }
auto letter_index = auto letter_index =
std::make_unique<ast::IdentifierExpression>(swizzles[index_val]); create<ast::IdentifierExpression>(swizzles[index_val]);
next_expr = std::make_unique<ast::MemberAccessorExpression>( next_expr = create<ast::MemberAccessorExpression>(
std::move(current_expr.expr), std::move(letter_index)); std::move(current_expr.expr), std::move(letter_index));
// All vector components are the same type. // All vector components are the same type.
current_type_id = current_type_inst->GetSingleWordInOperand(0); current_type_id = current_type_inst->GetSingleWordInOperand(0);
@ -3110,7 +3102,7 @@ TypedExpression FunctionEmitter::MakeCompositeExtract(
<< ((sizeof(swizzles) / sizeof(swizzles[0])) - 1); << ((sizeof(swizzles) / sizeof(swizzles[0])) - 1);
} }
// Use array syntax. // Use array syntax.
next_expr = std::make_unique<ast::ArrayAccessorExpression>( next_expr = create<ast::ArrayAccessorExpression>(
std::move(current_expr.expr), make_index(index_val)); std::move(current_expr.expr), make_index(index_val));
// All matrix components are the same type. // All matrix components are the same type.
current_type_id = current_type_inst->GetSingleWordInOperand(0); current_type_id = current_type_inst->GetSingleWordInOperand(0);
@ -3120,7 +3112,7 @@ TypedExpression FunctionEmitter::MakeCompositeExtract(
// The array size could be a spec constant, and so it's not always // The array size could be a spec constant, and so it's not always
// statically checkable. Instead, rely on a runtime index clamp // statically checkable. Instead, rely on a runtime index clamp
// or runtime check to keep this safe. // or runtime check to keep this safe.
next_expr = std::make_unique<ast::ArrayAccessorExpression>( next_expr = create<ast::ArrayAccessorExpression>(
std::move(current_expr.expr), make_index(index_val)); std::move(current_expr.expr), make_index(index_val));
current_type_id = current_type_inst->GetSingleWordInOperand(0); current_type_id = current_type_inst->GetSingleWordInOperand(0);
break; break;
@ -3135,10 +3127,10 @@ TypedExpression FunctionEmitter::MakeCompositeExtract(
<< current_type_id << " having " << num_members << " members"; << current_type_id << " having " << num_members << " members";
return {}; return {};
} }
auto member_access = std::make_unique<ast::IdentifierExpression>( auto member_access = create<ast::IdentifierExpression>(
namer_.GetMemberName(current_type_id, uint32_t(index_val))); namer_.GetMemberName(current_type_id, uint32_t(index_val)));
next_expr = std::make_unique<ast::MemberAccessorExpression>( next_expr = create<ast::MemberAccessorExpression>(
std::move(current_expr.expr), std::move(member_access)); std::move(current_expr.expr), std::move(member_access));
current_type_id = current_type_inst->GetSingleWordInOperand(index_val); current_type_id = current_type_inst->GetSingleWordInOperand(index_val);
break; break;
@ -3155,14 +3147,14 @@ TypedExpression FunctionEmitter::MakeCompositeExtract(
} }
std::unique_ptr<ast::Expression> FunctionEmitter::MakeTrue() const { std::unique_ptr<ast::Expression> FunctionEmitter::MakeTrue() const {
return std::make_unique<ast::ScalarConstructorExpression>( return create<ast::ScalarConstructorExpression>(
std::make_unique<ast::BoolLiteral>(parser_impl_.BoolType(), true)); create<ast::BoolLiteral>(parser_impl_.BoolType(), true));
} }
std::unique_ptr<ast::Expression> FunctionEmitter::MakeFalse() const { std::unique_ptr<ast::Expression> FunctionEmitter::MakeFalse() const {
ast::type::BoolType bool_type; ast::type::BoolType bool_type;
return std::make_unique<ast::ScalarConstructorExpression>( return create<ast::ScalarConstructorExpression>(
std::make_unique<ast::BoolLiteral>(parser_impl_.BoolType(), false)); create<ast::BoolLiteral>(parser_impl_.BoolType(), false));
} }
TypedExpression FunctionEmitter::MakeVectorShuffle( TypedExpression FunctionEmitter::MakeVectorShuffle(
@ -3188,15 +3180,15 @@ TypedExpression FunctionEmitter::MakeVectorShuffle(
const auto index = inst.GetSingleWordInOperand(i); const auto index = inst.GetSingleWordInOperand(i);
if (index < vec0_len) { if (index < vec0_len) {
assert(index < sizeof(swizzles) / sizeof(swizzles[0])); assert(index < sizeof(swizzles) / sizeof(swizzles[0]));
values.emplace_back(std::make_unique<ast::MemberAccessorExpression>( values.emplace_back(create<ast::MemberAccessorExpression>(
MakeExpression(vec0_id).expr, MakeExpression(vec0_id).expr,
std::make_unique<ast::IdentifierExpression>(swizzles[index]))); create<ast::IdentifierExpression>(swizzles[index])));
} else if (index < vec0_len + vec1_len) { } else if (index < vec0_len + vec1_len) {
const auto sub_index = index - vec0_len; const auto sub_index = index - vec0_len;
assert(sub_index < sizeof(swizzles) / sizeof(swizzles[0])); assert(sub_index < sizeof(swizzles) / sizeof(swizzles[0]));
values.emplace_back(std::make_unique<ast::MemberAccessorExpression>( values.emplace_back(create<ast::MemberAccessorExpression>(
MakeExpression(vec1_id).expr, MakeExpression(vec1_id).expr,
std::make_unique<ast::IdentifierExpression>(swizzles[sub_index]))); create<ast::IdentifierExpression>(swizzles[sub_index])));
} else if (index == 0xFFFFFFFF) { } else if (index == 0xFFFFFFFF) {
// By rule, this maps to OpUndef. Instead, make it zero. // By rule, this maps to OpUndef. Instead, make it zero.
values.emplace_back(parser_impl_.MakeNullValue(result_type->type())); values.emplace_back(parser_impl_.MakeNullValue(result_type->type()));
@ -3206,7 +3198,7 @@ TypedExpression FunctionEmitter::MakeVectorShuffle(
return {}; return {};
} }
} }
return {result_type, std::make_unique<ast::TypeConstructorExpression>( return {result_type, create<ast::TypeConstructorExpression>(
result_type, std::move(values))}; result_type, std::move(values))};
} }
@ -3497,28 +3489,27 @@ TypedExpression FunctionEmitter::MakeNumericConversion(
ast::ExpressionList params; ast::ExpressionList params;
params.push_back(std::move(arg_expr.expr)); params.push_back(std::move(arg_expr.expr));
TypedExpression result(expr_type, TypedExpression result(expr_type, create<ast::TypeConstructorExpression>(
std::make_unique<ast::TypeConstructorExpression>(
expr_type, std::move(params))); expr_type, std::move(params)));
if (requested_type == expr_type) { if (requested_type == expr_type) {
return result; return result;
} }
return {requested_type, std::make_unique<ast::BitcastExpression>( return {requested_type, create<ast::BitcastExpression>(
requested_type, std::move(result.expr))}; requested_type, std::move(result.expr))};
} }
bool FunctionEmitter::EmitFunctionCall(const spvtools::opt::Instruction& inst) { bool FunctionEmitter::EmitFunctionCall(const spvtools::opt::Instruction& inst) {
// We ignore function attributes such as Inline, DontInline, Pure, Const. // We ignore function attributes such as Inline, DontInline, Pure, Const.
auto function = std::make_unique<ast::IdentifierExpression>( auto function = create<ast::IdentifierExpression>(
namer_.Name(inst.GetSingleWordInOperand(0))); namer_.Name(inst.GetSingleWordInOperand(0)));
ast::ExpressionList params; ast::ExpressionList params;
for (uint32_t iarg = 1; iarg < inst.NumInOperands(); ++iarg) { for (uint32_t iarg = 1; iarg < inst.NumInOperands(); ++iarg) {
params.emplace_back(MakeOperand(inst, iarg).expr); params.emplace_back(MakeOperand(inst, iarg).expr);
} }
auto call_expr = std::make_unique<ast::CallExpression>(std::move(function), auto call_expr =
std::move(params)); create<ast::CallExpression>(std::move(function), std::move(params));
auto* result_type = parser_impl_.ConvertType(inst.type_id()); auto* result_type = parser_impl_.ConvertType(inst.type_id());
if (!result_type) { if (!result_type) {
return Fail() << "internal error: no mapped type result of call: " return Fail() << "internal error: no mapped type result of call: "
@ -3528,8 +3519,7 @@ bool FunctionEmitter::EmitFunctionCall(const spvtools::opt::Instruction& inst) {
if (result_type->IsVoid()) { if (result_type->IsVoid()) {
return nullptr != return nullptr !=
AddStatementForInstruction( AddStatementForInstruction(
std::make_unique<ast::CallStatement>(std::move(call_expr)), create<ast::CallStatement>(std::move(call_expr)), inst);
inst);
} }
return EmitConstDefOrWriteToHoistedVar(inst, return EmitConstDefOrWriteToHoistedVar(inst,
@ -3541,15 +3531,15 @@ TypedExpression FunctionEmitter::MakeIntrinsicCall(
const auto intrinsic = GetIntrinsic(inst.opcode()); const auto intrinsic = GetIntrinsic(inst.opcode());
std::ostringstream ss; std::ostringstream ss;
ss << intrinsic; ss << intrinsic;
auto ident = std::make_unique<ast::IdentifierExpression>(ss.str()); auto ident = create<ast::IdentifierExpression>(ss.str());
ident->set_intrinsic(intrinsic); ident->set_intrinsic(intrinsic);
ast::ExpressionList params; ast::ExpressionList params;
for (uint32_t iarg = 0; iarg < inst.NumInOperands(); ++iarg) { for (uint32_t iarg = 0; iarg < inst.NumInOperands(); ++iarg) {
params.emplace_back(MakeOperand(inst, iarg).expr); params.emplace_back(MakeOperand(inst, iarg).expr);
} }
auto call_expr = std::make_unique<ast::CallExpression>(std::move(ident), auto call_expr =
std::move(params)); create<ast::CallExpression>(std::move(ident), std::move(params));
auto* result_type = parser_impl_.ConvertType(inst.type_id()); auto* result_type = parser_impl_.ConvertType(inst.type_id());
if (!result_type) { if (!result_type) {
Fail() << "internal error: no mapped type result of call: " Fail() << "internal error: no mapped type result of call: "
@ -3578,9 +3568,8 @@ TypedExpression FunctionEmitter::MakeSimpleSelect(
params.push_back(std::move(operand2.expr)); params.push_back(std::move(operand2.expr));
// The condition goes last. // The condition goes last.
params.push_back(std::move(condition.expr)); params.push_back(std::move(condition.expr));
return {operand1.type, return {operand1.type, create<ast::CallExpression>(
std::make_unique<ast::CallExpression>( create<ast::IdentifierExpression>("select"),
std::make_unique<ast::IdentifierExpression>("select"),
std::move(params))}; std::move(params))};
} }
return {}; return {};

View File

@ -21,6 +21,7 @@
#include <string> #include <string>
#include <unordered_map> #include <unordered_map>
#include <unordered_set> #include <unordered_set>
#include <utility>
#include <vector> #include <vector>
#include "source/opt/basic_block.h" #include "source/opt/basic_block.h"
@ -799,6 +800,13 @@ class FunctionEmitter {
/// @returns a boolean false expression. /// @returns a boolean false expression.
std::unique_ptr<ast::Expression> MakeFalse() const; std::unique_ptr<ast::Expression> MakeFalse() const;
/// @return a `std::unique_ptr` to a new `T` constructed with `args`
/// @param args the arguments to forward to the constructor for `T`
template <typename T, typename... ARGS>
std::unique_ptr<T> create(ARGS&&... args) const {
return std::make_unique<T>(std::forward<ARGS>(args)...);
}
ParserImpl& parser_impl_; ParserImpl& parser_impl_;
ast::Module& ast_module_; ast::Module& ast_module_;
spvtools::opt::IRContext& ir_context_; spvtools::opt::IRContext& ir_context_;

View File

@ -392,8 +392,7 @@ ParserImpl::ConvertMemberDecoration(uint32_t struct_type_id,
<< ShowType(struct_type_id); << ShowType(struct_type_id);
return nullptr; return nullptr;
} }
return std::make_unique<ast::StructMemberOffsetDecoration>(decoration[1], return create<ast::StructMemberOffsetDecoration>(decoration[1], Source{});
Source{});
case SpvDecorationNonReadable: case SpvDecorationNonReadable:
// WGSL doesn't have a member decoration for this. Silently drop it. // WGSL doesn't have a member decoration for this. Silently drop it.
return nullptr; return nullptr;
@ -782,8 +781,7 @@ bool ParserImpl::ApplyArrayDecorations(
<< ": multiple ArrayStride decorations"; << ": multiple ArrayStride decorations";
} }
ast::ArrayDecorationList decos; ast::ArrayDecorationList decos;
decos.push_back( decos.push_back(create<ast::StrideDecoration>(stride, Source{}));
std::make_unique<ast::StrideDecoration>(stride, Source{}));
ast_type->set_decorations(std::move(decos)); ast_type->set_decorations(std::move(decos));
} else { } else {
return Fail() << "invalid array type ID " << type_id return Fail() << "invalid array type ID " << type_id
@ -806,10 +804,10 @@ ast::type::Type* ParserImpl::ConvertType(
const auto decoration = struct_decorations[0][0]; const auto decoration = struct_decorations[0][0];
if (decoration == SpvDecorationBlock) { if (decoration == SpvDecorationBlock) {
ast_struct_decorations.push_back( ast_struct_decorations.push_back(
std::make_unique<ast::StructBlockDecoration>(Source{})); create<ast::StructBlockDecoration>(Source{}));
} else if (decoration == SpvDecorationBufferBlock) { } else if (decoration == SpvDecorationBufferBlock) {
ast_struct_decorations.push_back( ast_struct_decorations.push_back(
std::make_unique<ast::StructBlockDecoration>(Source{})); create<ast::StructBlockDecoration>(Source{}));
remap_buffer_block_type_.insert(type_id); remap_buffer_block_type_.insert(type_id);
} else { } else {
Fail() << "struct with ID " << type_id Fail() << "struct with ID " << type_id
@ -879,14 +877,14 @@ ast::type::Type* ParserImpl::ConvertType(
++num_non_writable_members; ++num_non_writable_members;
} }
const auto member_name = namer_.GetMemberName(type_id, member_index); const auto member_name = namer_.GetMemberName(type_id, member_index);
auto ast_struct_member = std::make_unique<ast::StructMember>( auto ast_struct_member = create<ast::StructMember>(
member_name, ast_member_ty, std::move(ast_member_decorations)); member_name, ast_member_ty, std::move(ast_member_decorations));
ast_members.push_back(std::move(ast_struct_member)); ast_members.push_back(std::move(ast_struct_member));
} }
// Now make the struct. // Now make the struct.
auto ast_struct = std::make_unique<ast::Struct>( auto ast_struct = create<ast::Struct>(std::move(ast_struct_decorations),
std::move(ast_struct_decorations), std::move(ast_members)); std::move(ast_members));
namer_.SuggestSanitizedName(type_id, "S"); namer_.SuggestSanitizedName(type_id, "S");
auto ast_struct_type = std::make_unique<ast::type::StructType>( auto ast_struct_type = std::make_unique<ast::type::StructType>(
@ -971,8 +969,8 @@ bool ParserImpl::EmitScalarSpecConstants() {
case SpvOpSpecConstantTrue: case SpvOpSpecConstantTrue:
case SpvOpSpecConstantFalse: { case SpvOpSpecConstantFalse: {
ast_type = ConvertType(inst.type_id()); ast_type = ConvertType(inst.type_id());
ast_expr = std::make_unique<ast::ScalarConstructorExpression>( ast_expr =
std::make_unique<ast::BoolLiteral>( create<ast::ScalarConstructorExpression>(create<ast::BoolLiteral>(
ast_type, inst.opcode() == SpvOpSpecConstantTrue)); ast_type, inst.opcode() == SpvOpSpecConstantTrue));
break; break;
} }
@ -980,19 +978,19 @@ bool ParserImpl::EmitScalarSpecConstants() {
ast_type = ConvertType(inst.type_id()); ast_type = ConvertType(inst.type_id());
const uint32_t literal_value = inst.GetSingleWordInOperand(0); const uint32_t literal_value = inst.GetSingleWordInOperand(0);
if (ast_type->IsI32()) { if (ast_type->IsI32()) {
ast_expr = std::make_unique<ast::ScalarConstructorExpression>( ast_expr =
std::make_unique<ast::SintLiteral>( create<ast::ScalarConstructorExpression>(create<ast::SintLiteral>(
ast_type, static_cast<int32_t>(literal_value))); ast_type, static_cast<int32_t>(literal_value)));
} else if (ast_type->IsU32()) { } else if (ast_type->IsU32()) {
ast_expr = std::make_unique<ast::ScalarConstructorExpression>( ast_expr =
std::make_unique<ast::UintLiteral>( create<ast::ScalarConstructorExpression>(create<ast::UintLiteral>(
ast_type, static_cast<uint32_t>(literal_value))); ast_type, static_cast<uint32_t>(literal_value)));
} else if (ast_type->IsF32()) { } else if (ast_type->IsF32()) {
float float_value; float float_value;
// Copy the bits so we can read them as a float. // Copy the bits so we can read them as a float.
std::memcpy(&float_value, &literal_value, sizeof(float_value)); std::memcpy(&float_value, &literal_value, sizeof(float_value));
ast_expr = std::make_unique<ast::ScalarConstructorExpression>( ast_expr = create<ast::ScalarConstructorExpression>(
std::make_unique<ast::FloatLiteral>(ast_type, float_value)); create<ast::FloatLiteral>(ast_type, float_value));
} else { } else {
return Fail() << " invalid result type for OpSpecConstant " return Fail() << " invalid result type for OpSpecConstant "
<< inst.PrettyPrint(); << inst.PrettyPrint();
@ -1008,8 +1006,7 @@ bool ParserImpl::EmitScalarSpecConstants() {
ast::VariableDecorationList spec_id_decos; ast::VariableDecorationList spec_id_decos;
for (const auto& deco : GetDecorationsFor(inst.result_id())) { for (const auto& deco : GetDecorationsFor(inst.result_id())) {
if ((deco.size() == 2) && (deco[0] == SpvDecorationSpecId)) { if ((deco.size() == 2) && (deco[0] == SpvDecorationSpecId)) {
auto cid = auto cid = create<ast::ConstantIdDecoration>(deco[1], Source{});
std::make_unique<ast::ConstantIdDecoration>(deco[1], Source{});
spec_id_decos.push_back(std::move(cid)); spec_id_decos.push_back(std::move(cid));
break; break;
} }
@ -1020,8 +1017,7 @@ bool ParserImpl::EmitScalarSpecConstants() {
ast_var->set_constructor(std::move(ast_expr)); ast_var->set_constructor(std::move(ast_expr));
ast_module_.AddGlobalVariable(std::move(ast_var)); ast_module_.AddGlobalVariable(std::move(ast_var));
} else { } else {
auto ast_deco_var = auto ast_deco_var = create<ast::DecoratedVariable>(std::move(ast_var));
std::make_unique<ast::DecoratedVariable>(std::move(ast_var));
ast_deco_var->set_is_const(true); ast_deco_var->set_is_const(true);
ast_deco_var->set_constructor(std::move(ast_expr)); ast_deco_var->set_constructor(std::move(ast_expr));
ast_deco_var->set_decorations(std::move(spec_id_decos)); ast_deco_var->set_decorations(std::move(spec_id_decos));
@ -1140,13 +1136,13 @@ bool ParserImpl::EmitModuleScopeVariables() {
// Make sure the variable has a name. // Make sure the variable has a name.
namer_.SuggestSanitizedName(builtin_position_.per_vertex_var_id, namer_.SuggestSanitizedName(builtin_position_.per_vertex_var_id,
"gl_Position"); "gl_Position");
auto var = std::make_unique<ast::DecoratedVariable>(MakeVariable( auto var = create<ast::DecoratedVariable>(MakeVariable(
builtin_position_.per_vertex_var_id, builtin_position_.per_vertex_var_id,
enum_converter_.ToStorageClass(builtin_position_.storage_class), enum_converter_.ToStorageClass(builtin_position_.storage_class),
ConvertType(builtin_position_.member_type_id))); ConvertType(builtin_position_.member_type_id)));
ast::VariableDecorationList decos; ast::VariableDecorationList decos;
decos.push_back(std::make_unique<ast::BuiltinDecoration>( decos.push_back(
ast::Builtin::kPosition, Source{})); create<ast::BuiltinDecoration>(ast::Builtin::kPosition, Source{}));
var->set_decorations(std::move(decos)); var->set_decorations(std::move(decos));
ast_module_.AddGlobalVariable(std::move(var)); ast_module_.AddGlobalVariable(std::move(var));
@ -1171,7 +1167,7 @@ std::unique_ptr<ast::Variable> ParserImpl::MakeVariable(uint32_t id,
std::make_unique<ast::type::AccessControlType>(access, type)); std::make_unique<ast::type::AccessControlType>(access, type));
} }
auto ast_var = std::make_unique<ast::Variable>(namer_.Name(id), sc, type); auto ast_var = create<ast::Variable>(namer_.Name(id), sc, type);
ast::VariableDecorationList ast_decorations; ast::VariableDecorationList ast_decorations;
for (auto& deco : GetDecorationsFor(id)) { for (auto& deco : GetDecorationsFor(id)) {
@ -1191,7 +1187,7 @@ std::unique_ptr<ast::Variable> ParserImpl::MakeVariable(uint32_t id,
return nullptr; return nullptr;
} }
ast_decorations.emplace_back( ast_decorations.emplace_back(
std::make_unique<ast::BuiltinDecoration>(ast_builtin, Source{})); create<ast::BuiltinDecoration>(ast_builtin, Source{}));
} }
if (deco[0] == SpvDecorationLocation) { if (deco[0] == SpvDecorationLocation) {
if (deco.size() != 2) { if (deco.size() != 2) {
@ -1200,7 +1196,7 @@ std::unique_ptr<ast::Variable> ParserImpl::MakeVariable(uint32_t id,
return nullptr; return nullptr;
} }
ast_decorations.emplace_back( ast_decorations.emplace_back(
std::make_unique<ast::LocationDecoration>(deco[1], Source{})); create<ast::LocationDecoration>(deco[1], Source{}));
} }
if (deco[0] == SpvDecorationDescriptorSet) { if (deco[0] == SpvDecorationDescriptorSet) {
if (deco.size() == 1) { if (deco.size() == 1) {
@ -1209,7 +1205,7 @@ std::unique_ptr<ast::Variable> ParserImpl::MakeVariable(uint32_t id,
return nullptr; return nullptr;
} }
ast_decorations.emplace_back( ast_decorations.emplace_back(
std::make_unique<ast::SetDecoration>(deco[1], Source{})); create<ast::SetDecoration>(deco[1], Source{}));
} }
if (deco[0] == SpvDecorationBinding) { if (deco[0] == SpvDecorationBinding) {
if (deco.size() == 1) { if (deco.size() == 1) {
@ -1218,12 +1214,11 @@ std::unique_ptr<ast::Variable> ParserImpl::MakeVariable(uint32_t id,
return nullptr; return nullptr;
} }
ast_decorations.emplace_back( ast_decorations.emplace_back(
std::make_unique<ast::BindingDecoration>(deco[1], Source{})); create<ast::BindingDecoration>(deco[1], Source{}));
} }
} }
if (!ast_decorations.empty()) { if (!ast_decorations.empty()) {
auto decorated_var = auto decorated_var = create<ast::DecoratedVariable>(std::move(ast_var));
std::make_unique<ast::DecoratedVariable>(std::move(ast_var));
decorated_var->set_decorations(std::move(ast_decorations)); decorated_var->set_decorations(std::move(ast_decorations));
ast_var = std::move(decorated_var); ast_var = std::move(decorated_var);
} }
@ -1263,26 +1258,26 @@ TypedExpression ParserImpl::MakeConstantExpression(uint32_t id) {
// Currently "null<type>" is missing from the WGSL parser. // Currently "null<type>" is missing from the WGSL parser.
// See https://bugs.chromium.org/p/tint/issues/detail?id=34 // See https://bugs.chromium.org/p/tint/issues/detail?id=34
if (ast_type->IsU32()) { if (ast_type->IsU32()) {
return {ast_type, std::make_unique<ast::ScalarConstructorExpression>( return {ast_type,
std::make_unique<ast::UintLiteral>( create<ast::ScalarConstructorExpression>(
ast_type, spirv_const->GetU32()))}; create<ast::UintLiteral>(ast_type, spirv_const->GetU32()))};
} }
if (ast_type->IsI32()) { if (ast_type->IsI32()) {
return {ast_type, std::make_unique<ast::ScalarConstructorExpression>( return {ast_type,
std::make_unique<ast::SintLiteral>( create<ast::ScalarConstructorExpression>(
ast_type, spirv_const->GetS32()))}; create<ast::SintLiteral>(ast_type, spirv_const->GetS32()))};
} }
if (ast_type->IsF32()) { if (ast_type->IsF32()) {
return {ast_type, std::make_unique<ast::ScalarConstructorExpression>( return {ast_type,
std::make_unique<ast::FloatLiteral>( create<ast::ScalarConstructorExpression>(
ast_type, spirv_const->GetFloat()))}; create<ast::FloatLiteral>(ast_type, spirv_const->GetFloat()))};
} }
if (ast_type->IsBool()) { if (ast_type->IsBool()) {
const bool value = spirv_const->AsNullConstant() const bool value = spirv_const->AsNullConstant()
? false ? false
: spirv_const->AsBoolConstant()->value(); : spirv_const->AsBoolConstant()->value();
return {ast_type, std::make_unique<ast::ScalarConstructorExpression>( return {ast_type, create<ast::ScalarConstructorExpression>(
std::make_unique<ast::BoolLiteral>(ast_type, value))}; create<ast::BoolLiteral>(ast_type, value))};
} }
auto* spirv_composite_const = spirv_const->AsCompositeConstant(); auto* spirv_composite_const = spirv_const->AsCompositeConstant();
if (spirv_composite_const != nullptr) { if (spirv_composite_const != nullptr) {
@ -1308,8 +1303,8 @@ TypedExpression ParserImpl::MakeConstantExpression(uint32_t id) {
ast_components.emplace_back(std::move(ast_component.expr)); ast_components.emplace_back(std::move(ast_component.expr));
} }
return {original_ast_type, return {original_ast_type,
std::make_unique<ast::TypeConstructorExpression>( create<ast::TypeConstructorExpression>(original_ast_type,
original_ast_type, std::move(ast_components))}; std::move(ast_components))};
} }
auto* spirv_null_const = spirv_const->AsNullConstant(); auto* spirv_null_const = spirv_const->AsNullConstant();
if (spirv_null_const != nullptr) { if (spirv_null_const != nullptr) {
@ -1336,20 +1331,20 @@ std::unique_ptr<ast::Expression> ParserImpl::MakeNullValue(
type = type->UnwrapIfNeeded(); type = type->UnwrapIfNeeded();
if (type->IsBool()) { if (type->IsBool()) {
return std::make_unique<ast::ScalarConstructorExpression>( return create<ast::ScalarConstructorExpression>(
std::make_unique<ast::BoolLiteral>(type, false)); create<ast::BoolLiteral>(type, false));
} }
if (type->IsU32()) { if (type->IsU32()) {
return std::make_unique<ast::ScalarConstructorExpression>( return create<ast::ScalarConstructorExpression>(
std::make_unique<ast::UintLiteral>(type, 0u)); create<ast::UintLiteral>(type, 0u));
} }
if (type->IsI32()) { if (type->IsI32()) {
return std::make_unique<ast::ScalarConstructorExpression>( return create<ast::ScalarConstructorExpression>(
std::make_unique<ast::SintLiteral>(type, 0)); create<ast::SintLiteral>(type, 0));
} }
if (type->IsF32()) { if (type->IsF32()) {
return std::make_unique<ast::ScalarConstructorExpression>( return create<ast::ScalarConstructorExpression>(
std::make_unique<ast::FloatLiteral>(type, 0.0f)); create<ast::FloatLiteral>(type, 0.0f));
} }
if (type->IsVector()) { if (type->IsVector()) {
const auto* vec_ty = type->AsVector(); const auto* vec_ty = type->AsVector();
@ -1357,8 +1352,8 @@ std::unique_ptr<ast::Expression> ParserImpl::MakeNullValue(
for (size_t i = 0; i < vec_ty->size(); ++i) { for (size_t i = 0; i < vec_ty->size(); ++i) {
ast_components.emplace_back(MakeNullValue(vec_ty->type())); ast_components.emplace_back(MakeNullValue(vec_ty->type()));
} }
return std::make_unique<ast::TypeConstructorExpression>( return create<ast::TypeConstructorExpression>(type,
type, std::move(ast_components)); std::move(ast_components));
} }
if (type->IsMatrix()) { if (type->IsMatrix()) {
const auto* mat_ty = type->AsMatrix(); const auto* mat_ty = type->AsMatrix();
@ -1370,8 +1365,8 @@ std::unique_ptr<ast::Expression> ParserImpl::MakeNullValue(
for (size_t i = 0; i < mat_ty->columns(); ++i) { for (size_t i = 0; i < mat_ty->columns(); ++i) {
ast_components.emplace_back(MakeNullValue(column_ty)); ast_components.emplace_back(MakeNullValue(column_ty));
} }
return std::make_unique<ast::TypeConstructorExpression>( return create<ast::TypeConstructorExpression>(type,
type, std::move(ast_components)); std::move(ast_components));
} }
if (type->IsArray()) { if (type->IsArray()) {
auto* arr_ty = type->AsArray(); auto* arr_ty = type->AsArray();
@ -1379,8 +1374,8 @@ std::unique_ptr<ast::Expression> ParserImpl::MakeNullValue(
for (size_t i = 0; i < arr_ty->size(); ++i) { for (size_t i = 0; i < arr_ty->size(); ++i) {
ast_components.emplace_back(MakeNullValue(arr_ty->type())); ast_components.emplace_back(MakeNullValue(arr_ty->type()));
} }
return std::make_unique<ast::TypeConstructorExpression>( return create<ast::TypeConstructorExpression>(original_type,
original_type, std::move(ast_components)); std::move(ast_components));
} }
if (type->IsStruct()) { if (type->IsStruct()) {
auto* struct_ty = type->AsStruct(); auto* struct_ty = type->AsStruct();
@ -1388,8 +1383,8 @@ std::unique_ptr<ast::Expression> ParserImpl::MakeNullValue(
for (auto& member : struct_ty->impl()->members()) { for (auto& member : struct_ty->impl()->members()) {
ast_components.emplace_back(MakeNullValue(member->type())); ast_components.emplace_back(MakeNullValue(member->type()));
} }
return std::make_unique<ast::TypeConstructorExpression>( return create<ast::TypeConstructorExpression>(original_type,
original_type, std::move(ast_components)); std::move(ast_components));
} }
Fail() << "can't make null value for type: " << type->type_name(); Fail() << "can't make null value for type: " << type->type_name();
return nullptr; return nullptr;
@ -1416,15 +1411,15 @@ TypedExpression ParserImpl::RectifyOperandSignedness(SpvOp op,
auto* unsigned_ty = unsigned_type_for_[type]; auto* unsigned_ty = unsigned_type_for_[type];
if (unsigned_ty != nullptr) { if (unsigned_ty != nullptr) {
// Conversion is required. // Conversion is required.
return {unsigned_ty, std::make_unique<ast::BitcastExpression>( return {unsigned_ty, create<ast::BitcastExpression>(
unsigned_ty, std::move(expr.expr))}; unsigned_ty, std::move(expr.expr))};
} }
} else if (requires_signed) { } else if (requires_signed) {
auto* signed_ty = signed_type_for_[type]; auto* signed_ty = signed_type_for_[type];
if (signed_ty != nullptr) { if (signed_ty != nullptr) {
// Conversion is required. // Conversion is required.
return {signed_ty, std::make_unique<ast::BitcastExpression>( return {signed_ty,
signed_ty, std::move(expr.expr))}; create<ast::BitcastExpression>(signed_ty, std::move(expr.expr))};
} }
} }
// We should not reach here. // We should not reach here.
@ -1487,8 +1482,8 @@ TypedExpression ParserImpl::RectifyForcedResultType(
if ((forced_result_ty == nullptr) || (forced_result_ty == expr.type)) { if ((forced_result_ty == nullptr) || (forced_result_ty == expr.type)) {
return expr; return expr;
} }
return {expr.type, std::make_unique<ast::BitcastExpression>( return {expr.type,
expr.type, std::move(expr.expr))}; create<ast::BitcastExpression>(expr.type, std::move(expr.expr))};
} }
bool ParserImpl::EmitFunctions() { bool ParserImpl::EmitFunctions() {

View File

@ -432,6 +432,13 @@ class ParserImpl : Reader {
bool ApplyArrayDecorations(const spvtools::opt::analysis::Type* spv_type, bool ApplyArrayDecorations(const spvtools::opt::analysis::Type* spv_type,
ast::type::ArrayType* ast_type); ast::type::ArrayType* ast_type);
/// @return a `std::unique_ptr` to a new `T` constructed with `args`
/// @param args the arguments to forward to the constructor for `T`
template <typename T, typename... ARGS>
std::unique_ptr<T> create(ARGS&&... args) const {
return std::make_unique<T>(std::forward<ARGS>(args)...);
}
// The SPIR-V binary we're parsing // The SPIR-V binary we're parsing
std::vector<uint32_t> spv_binary_; std::vector<uint32_t> spv_binary_;