[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:
parent
a308ae2a7f
commit
4092f2255c
|
@ -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) {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue