mirror of
https://github.com/encounter/dawn-cmake.git
synced 2025-07-07 21:55:53 +00:00
[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) {
|
for (uint32_t case_target_id : case_targets) {
|
||||||
auto* case_block = GetBlockInfo(case_target_id);
|
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.
|
// A case target can't be a back-edge.
|
||||||
if (construct->begin_pos >= case_block->pos) {
|
if (construct->begin_pos >= case_block->pos) {
|
||||||
|
@ -661,91 +661,97 @@ uint32_t Builder::GenerateConstructorExpression(
|
|||||||
return GenerateLiteralIfNeeded(expr->AsScalarConstructor()->literal());
|
return GenerateLiteralIfNeeded(expr->AsScalarConstructor()->literal());
|
||||||
}
|
}
|
||||||
if (expr->IsTypeConstructor()) {
|
if (expr->IsTypeConstructor()) {
|
||||||
auto* init = expr->AsTypeConstructor();
|
return GenerateTypeConstructorExpression(expr->AsTypeConstructor(),
|
||||||
auto type_id = GenerateTypeIfNeeded(init->type());
|
is_global_init);
|
||||||
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();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
error_ = "unknown constructor expression";
|
error_ = "unknown constructor expression";
|
||||||
return 0;
|
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) {
|
uint32_t Builder::GenerateLiteralIfNeeded(ast::Literal* lit) {
|
||||||
auto type_id = GenerateTypeIfNeeded(lit->type());
|
auto type_id = GenerateTypeIfNeeded(lit->type());
|
||||||
if (type_id == 0) {
|
if (type_id == 0) {
|
||||||
|
@ -26,6 +26,7 @@
|
|||||||
#include "src/ast/literal.h"
|
#include "src/ast/literal.h"
|
||||||
#include "src/ast/module.h"
|
#include "src/ast/module.h"
|
||||||
#include "src/ast/struct_member.h"
|
#include "src/ast/struct_member.h"
|
||||||
|
#include "src/ast/type_constructor_expression.h"
|
||||||
#include "src/scope_stack.h"
|
#include "src/scope_stack.h"
|
||||||
#include "src/writer/spirv/function.h"
|
#include "src/writer/spirv/function.h"
|
||||||
#include "src/writer/spirv/instruction.h"
|
#include "src/writer/spirv/instruction.h"
|
||||||
@ -200,12 +201,19 @@ class Builder {
|
|||||||
/// Generates an import instruction
|
/// Generates an import instruction
|
||||||
/// @param imp the import
|
/// @param imp the import
|
||||||
void GenerateImport(ast::Import* imp);
|
void GenerateImport(ast::Import* imp);
|
||||||
/// Generates an constructor expression
|
/// Generates a constructor expression
|
||||||
/// @param expr the expression to generate
|
/// @param expr the expression to generate
|
||||||
/// @param is_global_init set true if this is a global variable constructor
|
/// @param is_global_init set true if this is a global variable constructor
|
||||||
/// @returns the ID of the expression or 0 on failure.
|
/// @returns the ID of the expression or 0 on failure.
|
||||||
uint32_t GenerateConstructorExpression(ast::ConstructorExpression* expr,
|
uint32_t GenerateConstructorExpression(ast::ConstructorExpression* expr,
|
||||||
bool is_global_init);
|
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
|
/// Generates a literal constant if needed
|
||||||
/// @param lit the literal to generate
|
/// @param lit the literal to generate
|
||||||
/// @returns the ID on success or 0 on failure
|
/// @returns the ID on success or 0 on failure
|
||||||
|
Loading…
x
Reference in New Issue
Block a user