writers: Use the new sem::Module::DependencyOrderedDeclarations

As the resolver currently enforces in-order declarations, this does not
change the declaration order from iterating over the
ast::Module::GlobalDeclarations.

The MSL backend has been changed to use the
sem::Module::DependencyOrderedDeclarations list instead of looping over
different declaration types separately.

Bug: tint:1266
Change-Id: I698d612032285311017bfceab3c42adae1928a0e
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/79767
Reviewed-by: James Price <jrprice@google.com>
Kokoro: Kokoro <noreply+kokoro@google.com>
This commit is contained in:
Ben Clayton
2022-02-09 23:55:51 +00:00
parent a52be6c9ec
commit 8ec32a6ec9
841 changed files with 3258 additions and 2784 deletions

View File

@@ -36,6 +36,7 @@
#include "src/sem/depth_texture_type.h"
#include "src/sem/function.h"
#include "src/sem/member_accessor_expression.h"
#include "src/sem/module.h"
#include "src/sem/multisampled_texture_type.h"
#include "src/sem/sampled_texture_type.h"
#include "src/sem/statement.h"
@@ -147,7 +148,8 @@ bool GeneratorImpl::Generate() {
line();
for (auto* decl : builder_.AST().GlobalDeclarations()) {
auto* mod = builder_.Sem().Module();
for (auto* decl : mod->DependencyOrderedDeclarations()) {
if (decl->Is<ast::Alias>()) {
continue; // Ignore aliases.
}

View File

@@ -37,6 +37,7 @@
#include "src/sem/depth_texture_type.h"
#include "src/sem/function.h"
#include "src/sem/member_accessor_expression.h"
#include "src/sem/module.h"
#include "src/sem/multisampled_texture_type.h"
#include "src/sem/sampled_texture_type.h"
#include "src/sem/statement.h"
@@ -223,7 +224,8 @@ bool GeneratorImpl::Generate() {
const TypeInfo* last_kind = nullptr;
size_t last_padding_line = 0;
for (auto* decl : builder_.AST().GlobalDeclarations()) {
auto* mod = builder_.Sem().Module();
for (auto* decl : mod->DependencyOrderedDeclarations()) {
if (decl->Is<ast::Alias>()) {
continue; // Ignore aliases.
}

View File

@@ -45,6 +45,7 @@
#include "src/sem/i32_type.h"
#include "src/sem/matrix_type.h"
#include "src/sem/member_accessor_expression.h"
#include "src/sem/module.h"
#include "src/sem/multisampled_texture_type.h"
#include "src/sem/pointer_type.h"
#include "src/sem/reference_type.h"
@@ -207,44 +208,46 @@ bool GeneratorImpl::Generate() {
auto helpers_insertion_point = current_buffer_->lines.size();
for (auto* const type_decl : program_->AST().TypeDecls()) {
if (!type_decl->Is<ast::Alias>()) {
if (!EmitTypeDecl(TypeOf(type_decl))) {
return false;
}
auto* mod = builder_.Sem().Module();
for (auto* decl : mod->DependencyOrderedDeclarations()) {
bool ok = Switch(
decl, //
[&](const ast::Struct* str) {
TINT_DEFER(line());
return EmitTypeDecl(TypeOf(str));
},
[&](const ast::Alias*) {
return true; // folded away by the writer
},
[&](const ast::Variable* var) {
if (var->is_const) {
TINT_DEFER(line());
return EmitProgramConstVariable(var);
}
// These are pushed into the entry point by sanitizer transforms.
TINT_ICE(Writer, diagnostics_)
<< "module-scope variables should have been handled by the MSL "
"sanitizer";
return false;
},
[&](const ast::Function* func) {
TINT_DEFER(line());
if (func->IsEntryPoint()) {
return EmitEntryPointFunction(func);
}
return EmitFunction(func);
},
[&](Default) {
// These are pushed into the entry point by sanitizer transforms.
TINT_ICE(Writer, diagnostics_)
<< "unhandled type: " << decl->TypeInfo().name;
return false;
});
if (!ok) {
return false;
}
}
if (!program_->AST().TypeDecls().empty()) {
line();
}
for (auto* var : program_->AST().GlobalVariables()) {
if (var->is_const) {
if (!EmitProgramConstVariable(var)) {
return false;
}
} else {
// These are pushed into the entry point by sanitizer transforms.
TINT_ICE(Writer, diagnostics_) << "module-scope variables should have "
"been handled by the MSL sanitizer";
break;
}
}
for (auto* func : program_->AST().Functions()) {
if (!func->IsEntryPoint()) {
if (!EmitFunction(func)) {
return false;
}
} else {
if (!EmitEntryPointFunction(func)) {
return false;
}
}
line();
}
if (!invariant_define_name_.empty()) {
// 'invariant' attribute requires MSL 2.1 or higher.
// WGSL can ignore the invariant attribute on pre MSL 2.1 devices.
@@ -1555,11 +1558,12 @@ bool GeneratorImpl::EmitLiteral(std::ostream& out,
return true;
},
[&](const ast::SintLiteralExpression* l) {
// MSL (and C++) parse `-2147483648` as a `long` because it parses unary
// minus and `2147483648` as separate tokens, and the latter doesn't
// fit into an (32-bit) `int`. WGSL, OTOH, parses this as an `i32`. To
// avoid issues with `long` to `int` casts, emit `(2147483647 - 1)`
// instead, which ensures the expression type is `int`.
// MSL (and C++) parse `-2147483648` as a `long` because it parses
// unary minus and `2147483648` as separate tokens, and the latter
// doesn't fit into an (32-bit) `int`. WGSL, OTOH, parses this as an
// `i32`. To avoid issues with `long` to `int` casts, emit
// `(2147483647 - 1)` instead, which ensures the expression type is
// `int`.
const auto int_min = std::numeric_limits<int32_t>::min();
if (l->ValueAsI32() == int_min) {
out << "(" << int_min + 1 << " - 1)";
@@ -1741,8 +1745,8 @@ std::string GeneratorImpl::interpolation_to_attribute(
bool GeneratorImpl::EmitEntryPointFunction(const ast::Function* func) {
auto func_name = program_->Symbols().NameFor(func->symbol);
// Returns the binding index of a variable, requiring that the group attribute
// have a value of zero.
// Returns the binding index of a variable, requiring that the group
// attribute have a value of zero.
const uint32_t kInvalidBindingIndex = std::numeric_limits<uint32_t>::max();
auto get_binding_index = [&](const ast::Variable* var) -> uint32_t {
auto bp = var->BindingPoint();
@@ -1923,14 +1927,14 @@ bool GeneratorImpl::EmitForLoop(const ast::ForLoopStatement* stmt) {
}
}
// If the for-loop has a multi-statement conditional and / or continuing, then
// we cannot emit this as a regular for-loop in MSL. Instead we need to
// If the for-loop has a multi-statement conditional and / or continuing,
// then we cannot emit this as a regular for-loop in MSL. Instead we need to
// generate a `while(true)` loop.
bool emit_as_loop = cond_pre.lines.size() > 0 || cont_buf.lines.size() > 1;
// If the for-loop has multi-statement initializer, or is going to be emitted
// as a `while(true)` loop, then declare the initializer statement(s) before
// the loop in a new block.
// If the for-loop has multi-statement initializer, or is going to be
// emitted as a `while(true)` loop, then declare the initializer
// statement(s) before the loop in a new block.
bool nest_in_block =
init_buf.lines.size() > 1 || (stmt->initializer && emit_as_loop);
if (nest_in_block) {

View File

@@ -107,6 +107,7 @@ using namespace metal;
struct tint_symbol_1 {
float foo [[user(locn0)]];
};
struct tint_symbol_2 {
float value [[color(1)]];
};
@@ -207,15 +208,12 @@ struct Interface {
float col2;
float4 pos;
};
struct tint_symbol {
float col1 [[user(locn1)]];
float col2 [[user(locn2)]];
float4 pos [[position]];
};
struct tint_symbol_2 {
float col1 [[user(locn1)]];
float col2 [[user(locn2)]];
};
Interface vert_main_inner() {
Interface const tint_symbol_3 = {.col1=0.5f, .col2=0.25f, .pos=float4()};
@@ -231,6 +229,11 @@ vertex tint_symbol vert_main() {
return wrapper_result;
}
struct tint_symbol_2 {
float col1 [[user(locn1)]];
float col2 [[user(locn2)]];
};
void frag_main_inner(Interface colors) {
float const r = colors.col1;
float const g = colors.col2;
@@ -285,18 +288,16 @@ using namespace metal;
struct VertexOutput {
float4 pos;
};
struct tint_symbol {
float4 pos [[position]];
};
struct tint_symbol_1 {
float4 pos [[position]];
};
VertexOutput foo(float x) {
VertexOutput const tint_symbol_2 = {.pos=float4(x, x, x, 1.0f)};
return tint_symbol_2;
}
struct tint_symbol {
float4 pos [[position]];
};
VertexOutput vert_main1_inner() {
return foo(0.5f);
}
@@ -308,6 +309,10 @@ vertex tint_symbol vert_main1() {
return wrapper_result;
}
struct tint_symbol_1 {
float4 pos [[position]];
};
VertexOutput vert_main2_inner() {
return foo(0.25f);
}

View File

@@ -57,6 +57,7 @@ using namespace metal;
struct tint_symbol {
/* 0x0000 */ uint4 buffer_size[1];
};
struct my_struct {
float a[1];
};
@@ -103,6 +104,7 @@ using namespace metal;
struct tint_symbol {
/* 0x0000 */ uint4 buffer_size[1];
};
struct my_struct {
float z;
float a[1];
@@ -152,6 +154,7 @@ using namespace metal;
struct tint_symbol {
/* 0x0000 */ uint4 buffer_size[1];
};
struct my_struct {
float a[1];
};
@@ -208,6 +211,7 @@ using namespace metal;
struct tint_symbol {
/* 0x0000 */ uint4 buffer_size[2];
};
struct my_struct {
float a[1];
};

View File

@@ -190,6 +190,7 @@ using namespace metal;
struct tint_array_wrapper {
float2x2 arr[4];
};
struct tint_symbol_3 {
tint_array_wrapper m;
};
@@ -240,9 +241,11 @@ struct S1 {
float2x2 m1;
float4x4 m2;
};
struct S2 {
S1 s;
};
struct tint_symbol_4 {
S2 s;
};
@@ -316,11 +319,13 @@ struct tint_symbol_7 {
float2x3 m2;
float2x4 m3;
};
struct tint_symbol_15 {
float3x2 m4;
float3x3 m5;
float3x4 m6;
};
struct tint_symbol_23 {
float4x2 m7;
float4x3 m8;

View File

@@ -31,6 +31,7 @@
#include "src/sem/depth_texture_type.h"
#include "src/sem/function.h"
#include "src/sem/member_accessor_expression.h"
#include "src/sem/module.h"
#include "src/sem/multisampled_texture_type.h"
#include "src/sem/reference_type.h"
#include "src/sem/sampled_texture_type.h"
@@ -308,9 +309,12 @@ bool Builder::Build() {
}
}
for (auto* func : builder_.AST().Functions()) {
if (!GenerateFunction(func)) {
return false;
auto* mod = builder_.Sem().Module();
for (auto* decl : mod->DependencyOrderedDeclarations()) {
if (auto* func = decl->As<ast::Function>()) {
if (!GenerateFunction(func)) {
return false;
}
}
}