dawn-cmake/src/writer/wgsl/generator_impl.h
James Price dfd1714174 [wgsl-writer] Emit globals in declared order
Instead of emitting all global variables and then functions, emit
global declarations in the order they were added to the AST.

This fixes issues where the reording might generate an invalid WGSL
program from a valid input (e.g. when declaring a global variable with
the same name as a variable inside a function that precedes it).

This also unifies the implementation of Generate() and
GenerateEntryPoint(), to avoid implementing the same logic twice.

Change-Id: I60a4e5ed4a054562cdcc3d028f8d577434a6d713
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/41303
Reviewed-by: dan sinclair <dsinclair@chromium.org>
Commit-Queue: dan sinclair <dsinclair@chromium.org>
2021-02-10 15:34:37 +00:00

217 lines
8.8 KiB
C++

// Copyright 2020 The Tint Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef SRC_WRITER_WGSL_GENERATOR_IMPL_H_
#define SRC_WRITER_WGSL_GENERATOR_IMPL_H_
#include <sstream>
#include <string>
#include "src/ast/array_accessor_expression.h"
#include "src/ast/assignment_statement.h"
#include "src/ast/binary_expression.h"
#include "src/ast/bitcast_expression.h"
#include "src/ast/break_statement.h"
#include "src/ast/call_expression.h"
#include "src/ast/case_statement.h"
#include "src/ast/constructor_expression.h"
#include "src/ast/continue_statement.h"
#include "src/ast/discard_statement.h"
#include "src/ast/fallthrough_statement.h"
#include "src/ast/identifier_expression.h"
#include "src/ast/if_statement.h"
#include "src/ast/loop_statement.h"
#include "src/ast/member_accessor_expression.h"
#include "src/ast/return_statement.h"
#include "src/ast/scalar_constructor_expression.h"
#include "src/ast/switch_statement.h"
#include "src/ast/type_constructor_expression.h"
#include "src/ast/unary_op_expression.h"
#include "src/ast/variable.h"
#include "src/program.h"
#include "src/type/storage_texture_type.h"
#include "src/type/struct_type.h"
#include "src/type/type.h"
#include "src/writer/text_generator.h"
namespace tint {
namespace writer {
namespace wgsl {
/// Implementation class for WGSL generator
class GeneratorImpl : public TextGenerator {
public:
/// Constructor
/// @param program the program
explicit GeneratorImpl(const Program* program);
~GeneratorImpl();
/// Generates the result data, optionally restricted to a single entry point
/// @param entry entry point to target, or nullptr
/// @returns true on successful generation; false otherwise
bool Generate(const ast::Function* entry);
/// Generates a single entry point
/// @param stage the pipeline stage
/// @param name the entry point name
/// @returns true on successful generation; false otherwise
bool GenerateEntryPoint(ast::PipelineStage stage, const std::string& name);
/// Handles generating a constructed type
/// @param ty the constructed to generate
/// @returns true if the constructed was emitted
bool EmitConstructedType(const type::Type* ty);
/// Handles an array accessor expression
/// @param expr the expression to emit
/// @returns true if the array accessor was emitted
bool EmitArrayAccessor(ast::ArrayAccessorExpression* expr);
/// Handles an assignment statement
/// @param stmt the statement to emit
/// @returns true if the statement was emitted successfully
bool EmitAssign(ast::AssignmentStatement* stmt);
/// Handles generating a binary expression
/// @param expr the binary expression
/// @returns true if the expression was emitted, false otherwise
bool EmitBinary(ast::BinaryExpression* expr);
/// Handles generating a bitcast expression
/// @param expr the bitcast expression
/// @returns true if the bitcast was emitted
bool EmitBitcast(ast::BitcastExpression* expr);
/// Handles a block statement
/// @param stmt the statement to emit
/// @returns true if the statement was emitted successfully
bool EmitBlock(const ast::BlockStatement* stmt);
/// Handles a block statement with a newline at the end
/// @param stmt the statement to emit
/// @returns true if the statement was emitted successfully
bool EmitIndentedBlockAndNewline(const ast::BlockStatement* stmt);
/// Handles a block statement with a newline at the end
/// @param stmt the statement to emit
/// @returns true if the statement was emitted successfully
bool EmitBlockAndNewline(const ast::BlockStatement* stmt);
/// Handles a break statement
/// @param stmt the statement to emit
/// @returns true if the statement was emitted successfully
bool EmitBreak(ast::BreakStatement* stmt);
/// Handles generating a call expression
/// @param expr the call expression
/// @returns true if the call expression is emitted
bool EmitCall(ast::CallExpression* expr);
/// Handles a case statement
/// @param stmt the statement
/// @returns true if the statment was emitted successfully
bool EmitCase(ast::CaseStatement* stmt);
/// Handles generating a scalar constructor
/// @param expr the scalar constructor expression
/// @returns true if the scalar constructor is emitted
bool EmitScalarConstructor(ast::ScalarConstructorExpression* expr);
/// Handles a continue statement
/// @param stmt the statement to emit
/// @returns true if the statement was emitted successfully
bool EmitContinue(ast::ContinueStatement* stmt);
/// Handles generating an else statement
/// @param stmt the statement to emit
/// @returns true if the statement was emitted
bool EmitElse(ast::ElseStatement* stmt);
/// Handles generate an Expression
/// @param expr the expression
/// @returns true if the expression was emitted
bool EmitExpression(ast::Expression* expr);
/// Handles generating a fallthrough statement
/// @param stmt the fallthrough statement
/// @returns true if the statement was successfully emitted
bool EmitFallthrough(ast::FallthroughStatement* stmt);
/// Handles generating a function
/// @param func the function to generate
/// @returns true if the function was emitted
bool EmitFunction(ast::Function* func);
/// Handles generating an identifier expression
/// @param expr the identifier expression
/// @returns true if the identifeir was emitted
bool EmitIdentifier(ast::IdentifierExpression* expr);
/// Handles an if statement
/// @param stmt the statement to emit
/// @returns true if the statement was successfully emitted
bool EmitIf(ast::IfStatement* stmt);
/// Handles generating constructor expressions
/// @param expr the constructor expression
/// @returns true if the expression was emitted
bool EmitConstructor(ast::ConstructorExpression* expr);
/// Handles generating a discard statement
/// @param stmt the discard statement
/// @returns true if the statement was successfully emitted
bool EmitDiscard(ast::DiscardStatement* stmt);
/// Handles a literal
/// @param lit the literal to emit
/// @returns true if the literal was successfully emitted
bool EmitLiteral(ast::Literal* lit);
/// Handles a loop statement
/// @param stmt the statement to emit
/// @returns true if the statement was emtited
bool EmitLoop(ast::LoopStatement* stmt);
/// Handles a member accessor expression
/// @param expr the member accessor expression
/// @returns true if the member accessor was emitted
bool EmitMemberAccessor(ast::MemberAccessorExpression* expr);
/// Handles return statements
/// @param stmt the statement to emit
/// @returns true if the statement was successfully emitted
bool EmitReturn(ast::ReturnStatement* stmt);
/// Handles statement
/// @param stmt the statement to emit
/// @returns true if the statement was emitted
bool EmitStatement(ast::Statement* stmt);
/// Handles generating a switch statement
/// @param stmt the statement to emit
/// @returns true if the statement was emitted
bool EmitSwitch(ast::SwitchStatement* stmt);
/// Handles generating type
/// @param type the type to generate
/// @returns true if the type is emitted
bool EmitType(type::Type* type);
/// Handles generating a struct declaration
/// @param str the struct
/// @returns true if the struct is emitted
bool EmitStructType(const type::Struct* str);
/// Handles emitting an image format
/// @param fmt the format to generate
/// @returns true if the format is emitted
bool EmitImageFormat(const type::ImageFormat fmt);
/// Handles emitting a type constructor
/// @param expr the type constructor expression
/// @returns true if the constructor is emitted
bool EmitTypeConstructor(ast::TypeConstructorExpression* expr);
/// Handles a unary op expression
/// @param expr the expression to emit
/// @returns true if the expression was emitted
bool EmitUnaryOp(ast::UnaryOpExpression* expr);
/// Handles generating a variable
/// @param var the variable to generate
/// @returns true if the variable was emitted
bool EmitVariable(ast::Variable* var);
/// Handles generating variable decorations
/// @param var the decorated variable
/// @returns true if the variable decoration was emitted
bool EmitVariableDecorations(const semantic::Variable* var);
private:
Program const* const program_;
};
} // namespace wgsl
} // namespace writer
} // namespace tint
#endif // SRC_WRITER_WGSL_GENERATOR_IMPL_H_