[spirv-writer] Split the constructor expression method.

This CL splits the TypeConstructor code out of the generic
ConstructorExpression to make the code separation clearer.

Bug: tint:5
Change-Id: I441955c3b09a30b2d02f542f4b7c8e80ff8d9d86
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/20640
Reviewed-by: Ryan Harrison <rharrison@chromium.org>
This commit is contained in:
dan sinclair 2020-04-29 18:53:23 +00:00 committed by dan sinclair
parent a308ae2a7f
commit 4092f2255c
3 changed files with 96 additions and 81 deletions

View File

@ -879,7 +879,8 @@ bool FunctionEmitter::FindSwitchCaseHeaders() {
for (uint32_t case_target_id : case_targets) {
auto* case_block = GetBlockInfo(case_target_id);
case_block->case_values = std::make_unique<std::vector<uint64_t>>(std::move(block_to_values[case_target_id]));
case_block->case_values = std::make_unique<std::vector<uint64_t>>(
std::move(block_to_values[case_target_id]));
// A case target can't be a back-edge.
if (construct->begin_pos >= case_block->pos) {

View File

@ -661,91 +661,97 @@ uint32_t Builder::GenerateConstructorExpression(
return GenerateLiteralIfNeeded(expr->AsScalarConstructor()->literal());
}
if (expr->IsTypeConstructor()) {
auto* init = expr->AsTypeConstructor();
auto type_id = GenerateTypeIfNeeded(init->type());
if (type_id == 0) {
return 0;
}
std::ostringstream out;
out << "__const";
std::vector<Operand> ops;
bool constructor_is_const = true;
for (const auto& e : init->values()) {
if (!e->IsConstructor()) {
if (is_global_init) {
error_ = "constructor must be a constant expression";
return 0;
}
constructor_is_const = false;
}
}
for (const auto& e : init->values()) {
uint32_t id = 0;
if (constructor_is_const) {
id = GenerateConstructorExpression(e->AsConstructor(), is_global_init);
} else {
id = GenerateExpression(e.get());
id = GenerateLoadIfNeeded(e->result_type(), id);
}
if (id == 0) {
return 0;
}
auto* result_type = e->result_type()->UnwrapPtrIfNeeded();
// If we're putting a vector into the constructed composite we need to
// extract each of the values and insert them individually
if (result_type->IsVector()) {
auto* vec = result_type->AsVector();
auto result_type_id = GenerateTypeIfNeeded(vec->type());
if (result_type_id == 0) {
return 0;
}
for (uint32_t i = 0; i < vec->size(); ++i) {
auto extract = result_op();
auto extract_id = extract.to_i();
push_function_inst(spv::Op::OpCompositeExtract,
{Operand::Int(result_type_id), extract,
Operand::Int(id), Operand::Int(i)});
out << "_" << extract_id;
ops.push_back(Operand::Int(extract_id));
}
} else {
out << "_" << id;
ops.push_back(Operand::Int(id));
}
}
auto str = out.str();
auto val = const_to_id_.find(str);
if (val != const_to_id_.end()) {
return val->second;
}
auto result = result_op();
ops.insert(ops.begin(), result);
ops.insert(ops.begin(), Operand::Int(type_id));
const_to_id_[str] = result.to_i();
if (constructor_is_const) {
push_type(spv::Op::OpConstantComposite, ops);
} else {
push_function_inst(spv::Op::OpCompositeConstruct, ops);
}
return result.to_i();
return GenerateTypeConstructorExpression(expr->AsTypeConstructor(),
is_global_init);
}
error_ = "unknown constructor expression";
return 0;
}
uint32_t Builder::GenerateTypeConstructorExpression(
ast::TypeConstructorExpression* init,
bool is_global_init) {
auto type_id = GenerateTypeIfNeeded(init->type());
if (type_id == 0) {
return 0;
}
std::ostringstream out;
out << "__const";
std::vector<Operand> ops;
bool constructor_is_const = true;
for (const auto& e : init->values()) {
if (!e->IsConstructor()) {
if (is_global_init) {
error_ = "constructor must be a constant expression";
return 0;
}
constructor_is_const = false;
}
}
for (const auto& e : init->values()) {
uint32_t id = 0;
if (constructor_is_const) {
id = GenerateConstructorExpression(e->AsConstructor(), is_global_init);
} else {
id = GenerateExpression(e.get());
id = GenerateLoadIfNeeded(e->result_type(), id);
}
if (id == 0) {
return 0;
}
auto* result_type = e->result_type()->UnwrapPtrIfNeeded();
// If we're putting a vector into the constructed composite we need to
// extract each of the values and insert them individually
if (result_type->IsVector()) {
auto* vec = result_type->AsVector();
auto result_type_id = GenerateTypeIfNeeded(vec->type());
if (result_type_id == 0) {
return 0;
}
for (uint32_t i = 0; i < vec->size(); ++i) {
auto extract = result_op();
auto extract_id = extract.to_i();
push_function_inst(spv::Op::OpCompositeExtract,
{Operand::Int(result_type_id), extract,
Operand::Int(id), Operand::Int(i)});
out << "_" << extract_id;
ops.push_back(Operand::Int(extract_id));
}
} else {
out << "_" << id;
ops.push_back(Operand::Int(id));
}
}
auto str = out.str();
auto val = const_to_id_.find(str);
if (val != const_to_id_.end()) {
return val->second;
}
auto result = result_op();
ops.insert(ops.begin(), result);
ops.insert(ops.begin(), Operand::Int(type_id));
const_to_id_[str] = result.to_i();
if (constructor_is_const) {
push_type(spv::Op::OpConstantComposite, ops);
} else {
push_function_inst(spv::Op::OpCompositeConstruct, ops);
}
return result.to_i();
}
uint32_t Builder::GenerateLiteralIfNeeded(ast::Literal* lit) {
auto type_id = GenerateTypeIfNeeded(lit->type());
if (type_id == 0) {

View File

@ -26,6 +26,7 @@
#include "src/ast/literal.h"
#include "src/ast/module.h"
#include "src/ast/struct_member.h"
#include "src/ast/type_constructor_expression.h"
#include "src/scope_stack.h"
#include "src/writer/spirv/function.h"
#include "src/writer/spirv/instruction.h"
@ -200,12 +201,19 @@ class Builder {
/// Generates an import instruction
/// @param imp the import
void GenerateImport(ast::Import* imp);
/// Generates an constructor expression
/// Generates a constructor expression
/// @param expr the expression to generate
/// @param is_global_init set true if this is a global variable constructor
/// @returns the ID of the expression or 0 on failure.
uint32_t GenerateConstructorExpression(ast::ConstructorExpression* expr,
bool is_global_init);
/// Generates a type constructor expression
/// @param init the expression to generate
/// @param is_global_init set true if this is a global variable constructor
/// @returns the ID of the expression or 0 on failure.
uint32_t GenerateTypeConstructorExpression(
ast::TypeConstructorExpression* init,
bool is_global_init);
/// Generates a literal constant if needed
/// @param lit the literal to generate
/// @returns the ID on success or 0 on failure