mirror of
https://github.com/encounter/dawn-cmake.git
synced 2025-07-15 17:45:58 +00:00
This CL adds the parsing of structs with names. The parsing of type aliased structs remains to allow for migration to the new system. The named struct format is always emitted. Bug: tint:175 Change-Id: Ic0579dedbd2dd0edc7dfd30bc2ec02972091e718 Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/30341 Commit-Queue: dan sinclair <dsinclair@chromium.org> Reviewed-by: David Neto <dneto@google.com>
383 lines
16 KiB
C++
383 lines
16 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_HLSL_GENERATOR_IMPL_H_
|
|
#define SRC_WRITER_HLSL_GENERATOR_IMPL_H_
|
|
|
|
#include "src/ast/intrinsic.h"
|
|
#include "src/ast/literal.h"
|
|
#include "src/ast/module.h"
|
|
#include "src/ast/scalar_constructor_expression.h"
|
|
#include "src/ast/type/struct_type.h"
|
|
#include "src/ast/type_constructor_expression.h"
|
|
#include "src/scope_stack.h"
|
|
#include "src/writer/hlsl/namer.h"
|
|
|
|
namespace tint {
|
|
namespace writer {
|
|
namespace hlsl {
|
|
|
|
/// Implementation class for HLSL generator
|
|
class GeneratorImpl {
|
|
public:
|
|
/// Constructor
|
|
/// @param module the module to generate
|
|
explicit GeneratorImpl(ast::Module* module);
|
|
~GeneratorImpl();
|
|
|
|
/// Increment the emitter indent level
|
|
void increment_indent() { indent_ += 2; }
|
|
/// Decrement the emiter indent level
|
|
void decrement_indent() {
|
|
if (indent_ < 2) {
|
|
indent_ = 0;
|
|
return;
|
|
}
|
|
indent_ -= 2;
|
|
}
|
|
|
|
/// Writes the current indent to the output stream
|
|
/// @param out the output stream
|
|
void make_indent(std::ostream& out);
|
|
|
|
/// @returns the error
|
|
std::string error() const { return error_; }
|
|
|
|
/// Resets the generator
|
|
void Reset();
|
|
|
|
/// @param out the output stream
|
|
/// @returns true on successful generation; false otherwise
|
|
bool Generate(std::ostream& out);
|
|
|
|
/// Handles generating a constructed type
|
|
/// @param out the output stream
|
|
/// @param ty the constructed type to generate
|
|
/// @returns true if the constructed type was emitted
|
|
bool EmitConstructedType(std::ostream& out, const ast::type::Type* ty);
|
|
/// Handles an array accessor expression
|
|
/// @param pre the preamble for the expression stream
|
|
/// @param out the output of the expression stream
|
|
/// @param expr the expression to emit
|
|
/// @returns true if the array accessor was emitted
|
|
bool EmitArrayAccessor(std::ostream& pre,
|
|
std::ostream& out,
|
|
ast::ArrayAccessorExpression* expr);
|
|
/// Handles an assignment statement
|
|
/// @param out the output stream
|
|
/// @param stmt the statement to emit
|
|
/// @returns true if the statement was emitted successfully
|
|
bool EmitAssign(std::ostream& out, ast::AssignmentStatement* stmt);
|
|
/// Handles generating a binary expression
|
|
/// @param pre the preamble for the expression stream
|
|
/// @param out the output of the expression stream
|
|
/// @param expr the binary expression
|
|
/// @returns true if the expression was emitted, false otherwise
|
|
bool EmitBinary(std::ostream& pre,
|
|
std::ostream& out,
|
|
ast::BinaryExpression* expr);
|
|
/// Handles generating a bitcast expression
|
|
/// @param pre the preamble for the expression stream
|
|
/// @param out the output of the expression stream
|
|
/// @param expr the as expression
|
|
/// @returns true if the bitcast was emitted
|
|
bool EmitBitcast(std::ostream& pre,
|
|
std::ostream& out,
|
|
ast::BitcastExpression* expr);
|
|
/// Handles a block statement
|
|
/// @param out the output stream
|
|
/// @param stmt the statement to emit
|
|
/// @returns true if the statement was emitted successfully
|
|
bool EmitBlock(std::ostream& out, const ast::BlockStatement* stmt);
|
|
/// Handles a block statement with a newline at the end
|
|
/// @param out the output stream
|
|
/// @param stmt the statement to emit
|
|
/// @returns true if the statement was emitted successfully
|
|
bool EmitIndentedBlockAndNewline(std::ostream& out,
|
|
ast::BlockStatement* stmt);
|
|
/// Handles a block statement with a newline at the end
|
|
/// @param out the output stream
|
|
/// @param stmt the statement to emit
|
|
/// @returns true if the statement was emitted successfully
|
|
bool EmitBlockAndNewline(std::ostream& out, const ast::BlockStatement* stmt);
|
|
/// Handles a break statement
|
|
/// @param out the output stream
|
|
/// @param stmt the statement to emit
|
|
/// @returns true if the statement was emitted successfully
|
|
bool EmitBreak(std::ostream& out, ast::BreakStatement* stmt);
|
|
/// Handles generating a call expression
|
|
/// @param pre the preamble for the expression stream
|
|
/// @param out the output of the expression stream
|
|
/// @param expr the call expression
|
|
/// @returns true if the call expression is emitted
|
|
bool EmitCall(std::ostream& pre,
|
|
std::ostream& out,
|
|
ast::CallExpression* expr);
|
|
/// Handles a case statement
|
|
/// @param out the output stream
|
|
/// @param stmt the statement
|
|
/// @returns true if the statment was emitted successfully
|
|
bool EmitCase(std::ostream& out, ast::CaseStatement* stmt);
|
|
/// Handles generating constructor expressions
|
|
/// @param pre the preamble for the expression stream
|
|
/// @param out the output of the expression stream
|
|
/// @param expr the constructor expression
|
|
/// @returns true if the expression was emitted
|
|
bool EmitConstructor(std::ostream& pre,
|
|
std::ostream& out,
|
|
ast::ConstructorExpression* expr);
|
|
/// Handles generating a discard statement
|
|
/// @param out the output stream
|
|
/// @param stmt the discard statement
|
|
/// @returns true if the statement was successfully emitted
|
|
bool EmitDiscard(std::ostream& out, ast::DiscardStatement* stmt);
|
|
/// Handles generating a scalar constructor
|
|
/// @param pre the preamble for the expression stream
|
|
/// @param out the output of the expression stream
|
|
/// @param expr the scalar constructor expression
|
|
/// @returns true if the scalar constructor is emitted
|
|
bool EmitScalarConstructor(std::ostream& pre,
|
|
std::ostream& out,
|
|
ast::ScalarConstructorExpression* expr);
|
|
/// Handles emitting a type constructor
|
|
/// @param pre the preamble for the expression stream
|
|
/// @param out the output of the expression stream
|
|
/// @param expr the type constructor expression
|
|
/// @returns true if the constructor is emitted
|
|
bool EmitTypeConstructor(std::ostream& pre,
|
|
std::ostream& out,
|
|
ast::TypeConstructorExpression* expr);
|
|
/// Handles a continue statement
|
|
/// @param out the output stream
|
|
/// @param stmt the statement to emit
|
|
/// @returns true if the statement was emitted successfully
|
|
bool EmitContinue(std::ostream& out, ast::ContinueStatement* stmt);
|
|
/// Handles generate an Expression
|
|
/// @param pre the preamble for the expression stream
|
|
/// @param out the output of the expression stream
|
|
/// @param expr the expression
|
|
/// @returns true if the expression was emitted
|
|
bool EmitExpression(std::ostream& pre,
|
|
std::ostream& out,
|
|
ast::Expression* expr);
|
|
/// Handles generating a function
|
|
/// @param out the output stream
|
|
/// @param func the function to generate
|
|
/// @returns true if the function was emitted
|
|
bool EmitFunction(std::ostream& out, ast::Function* func);
|
|
/// Internal helper for emitting functions
|
|
/// @param out the output stream
|
|
/// @param func the function to emit
|
|
/// @param emit_duplicate_functions set true if we need to duplicate per entry
|
|
/// point
|
|
/// @param ep_name the current entry point or blank if none set
|
|
/// @returns true if the function was emitted.
|
|
bool EmitFunctionInternal(std::ostream& out,
|
|
ast::Function* func,
|
|
bool emit_duplicate_functions,
|
|
const std::string& ep_name);
|
|
/// Handles emitting information for an entry point
|
|
/// @param out the output stream
|
|
/// @param func the entry point
|
|
/// @returns true if the entry point data was emitted
|
|
bool EmitEntryPointData(std::ostream& out, ast::Function* func);
|
|
/// Handles emitting the entry point function
|
|
/// @param out the output stream
|
|
/// @param func the entry point
|
|
/// @returns true if the entry point function was emitted
|
|
bool EmitEntryPointFunction(std::ostream& out, ast::Function* func);
|
|
/// Handles an if statement
|
|
/// @param out the output stream
|
|
/// @param stmt the statement to emit
|
|
/// @returns true if the statement was successfully emitted
|
|
bool EmitIf(std::ostream& out, ast::IfStatement* stmt);
|
|
/// Handles a literal
|
|
/// @param out the output stream
|
|
/// @param lit the literal to emit
|
|
/// @returns true if the literal was successfully emitted
|
|
bool EmitLiteral(std::ostream& out, ast::Literal* lit);
|
|
/// Handles a loop statement
|
|
/// @param out the output stream
|
|
/// @param stmt the statement to emit
|
|
/// @returns true if the statement was emitted
|
|
bool EmitLoop(std::ostream& out, ast::LoopStatement* stmt);
|
|
/// Handles generating an identifier expression
|
|
/// @param pre the preamble for the expression stream
|
|
/// @param out the output of the expression stream
|
|
/// @param expr the identifier expression
|
|
/// @returns true if the identifeir was emitted
|
|
bool EmitIdentifier(std::ostream& pre,
|
|
std::ostream& out,
|
|
ast::IdentifierExpression* expr);
|
|
/// Handles a member accessor expression
|
|
/// @param pre the preamble for the expression stream
|
|
/// @param out the output of the expression stream
|
|
/// @param expr the member accessor expression
|
|
/// @returns true if the member accessor was emitted
|
|
bool EmitMemberAccessor(std::ostream& pre,
|
|
std::ostream& out,
|
|
ast::MemberAccessorExpression* expr);
|
|
/// Handles a storage buffer accessor expression
|
|
/// @param pre the preamble for the expression stream
|
|
/// @param out the output of the expression stream
|
|
/// @param expr the storage buffer accessor expression
|
|
/// @param rhs the right side of a store expression. Set to nullptr for a load
|
|
/// @returns true if the storage buffer accessor was emitted
|
|
bool EmitStorageBufferAccessor(std::ostream& pre,
|
|
std::ostream& out,
|
|
ast::Expression* expr,
|
|
ast::Expression* rhs);
|
|
/// Handles return statements
|
|
/// @param out the output stream
|
|
/// @param stmt the statement to emit
|
|
/// @returns true if the statement was successfully emitted
|
|
bool EmitReturn(std::ostream& out, ast::ReturnStatement* stmt);
|
|
/// Handles statement
|
|
/// @param out the output stream
|
|
/// @param stmt the statement to emit
|
|
/// @returns true if the statement was emitted
|
|
bool EmitStatement(std::ostream& out, ast::Statement* stmt);
|
|
/// Handles generating a switch statement
|
|
/// @param out the output stream
|
|
/// @param stmt the statement to emit
|
|
/// @returns true if the statement was emitted
|
|
bool EmitSwitch(std::ostream& out, ast::SwitchStatement* stmt);
|
|
/// Handles generating type
|
|
/// @param out the output stream
|
|
/// @param type the type to generate
|
|
/// @param name the name of the variable, only used for array emission
|
|
/// @returns true if the type is emitted
|
|
bool EmitType(std::ostream& out,
|
|
ast::type::Type* type,
|
|
const std::string& name);
|
|
/// Handles generating a structure declaration
|
|
/// @param out the output stream
|
|
/// @param ty the struct to generate
|
|
/// @returns true if the struct is emitted
|
|
bool EmitStructType(std::ostream& out, const ast::type::StructType* ty);
|
|
/// Handles a unary op expression
|
|
/// @param pre the preamble for the expression stream
|
|
/// @param out the output of the expression stream
|
|
/// @param expr the expression to emit
|
|
/// @returns true if the expression was emitted
|
|
bool EmitUnaryOp(std::ostream& pre,
|
|
std::ostream& out,
|
|
ast::UnaryOpExpression* expr);
|
|
/// Emits the zero value for the given type
|
|
/// @param out the output stream
|
|
/// @param type the type to emit the value for
|
|
/// @returns true if the zero value was successfully emitted.
|
|
bool EmitZeroValue(std::ostream& out, ast::type::Type* type);
|
|
/// Handles generating a variable
|
|
/// @param out the output stream
|
|
/// @param var the variable to generate
|
|
/// @param skip_constructor set true if the constructor should be skipped
|
|
/// @returns true if the variable was emitted
|
|
bool EmitVariable(std::ostream& out,
|
|
ast::Variable* var,
|
|
bool skip_constructor);
|
|
/// Handles generating a program scope constant variable
|
|
/// @param out the output stream
|
|
/// @param var the variable to emit
|
|
/// @returns true if the variable was emitted
|
|
bool EmitProgramConstVariable(std::ostream& out, const ast::Variable* var);
|
|
|
|
/// Returns true if the accessor is accessing a storage buffer.
|
|
/// @param expr the expression to check
|
|
/// @returns true if the accessor is accessing a storage buffer for which
|
|
/// we need to execute a Load instruction.
|
|
bool is_storage_buffer_access(ast::MemberAccessorExpression* expr);
|
|
/// Returns true if the accessor is accessing a storage buffer.
|
|
/// @param expr the expression to check
|
|
/// @returns true if the accessor is accessing a storage buffer
|
|
bool is_storage_buffer_access(ast::ArrayAccessorExpression* expr);
|
|
/// Registers the given global with the generator
|
|
/// @param global the global to register
|
|
void register_global(ast::Variable* global);
|
|
/// Checks if the global variable is in an input or output struct
|
|
/// @param var the variable to check
|
|
/// @returns true if the global is in an input or output struct
|
|
bool global_is_in_struct(ast::Variable* var) const;
|
|
/// Creates a text string representing the index into a storage buffer
|
|
/// @param pre the pre stream
|
|
/// @param expr the expression to use as the index
|
|
/// @returns the index string, or blank if unable to generate
|
|
std::string generate_storage_buffer_index_expression(std::ostream& pre,
|
|
ast::Expression* expr);
|
|
/// Generates a name for the prefix
|
|
/// @param prefix the prefix of the name to generate
|
|
/// @returns the name
|
|
std::string generate_name(const std::string& prefix);
|
|
/// Generates an intrinsic name from the given name
|
|
/// @param intrinsic the intrinsic to convert to a name
|
|
/// @returns the intrinsic name or blank on error
|
|
std::string generate_intrinsic_name(ast::Intrinsic intrinsic);
|
|
/// Handles generating a builtin method name
|
|
/// @param expr the expression
|
|
/// @returns the name or "" if not valid
|
|
std::string generate_builtin_name(ast::CallExpression* expr);
|
|
/// Converts a builtin to an attribute name
|
|
/// @param builtin the builtin to convert
|
|
/// @returns the string name of the builtin or blank on error
|
|
std::string builtin_to_attribute(ast::Builtin builtin) const;
|
|
/// Determines if the function needs the input struct passed to it.
|
|
/// @param func the function to check
|
|
/// @returns true if there are input struct variables used in the function
|
|
bool has_referenced_in_var_needing_struct(ast::Function* func);
|
|
/// Determines if the function needs the output struct passed to it.
|
|
/// @param func the function to check
|
|
/// @returns true if there are output struct variables used in the function
|
|
bool has_referenced_out_var_needing_struct(ast::Function* func);
|
|
/// Determines if any used module variable requires an input or output struct.
|
|
/// @param func the function to check
|
|
/// @returns true if an input or output struct is required.
|
|
bool has_referenced_var_needing_struct(ast::Function* func);
|
|
|
|
/// @returns the namer for testing
|
|
Namer* namer_for_testing() { return &namer_; }
|
|
|
|
private:
|
|
enum class VarType { kIn, kOut };
|
|
|
|
struct EntryPointData {
|
|
std::string struct_name;
|
|
std::string var_name;
|
|
};
|
|
|
|
std::string current_ep_var_name(VarType type);
|
|
|
|
std::string error_;
|
|
size_t indent_ = 0;
|
|
|
|
Namer namer_;
|
|
ast::Module* module_ = nullptr;
|
|
std::string current_ep_name_;
|
|
bool generating_entry_point_ = false;
|
|
uint32_t loop_emission_counter_ = 0;
|
|
ScopeStack<ast::Variable*> global_variables_;
|
|
std::unordered_map<std::string, EntryPointData> ep_name_to_in_data_;
|
|
std::unordered_map<std::string, EntryPointData> ep_name_to_out_data_;
|
|
|
|
// This maps an input of "<entry_point_name>_<function_name>" to a remapped
|
|
// function name. If there is no entry for a given key then function did
|
|
// not need to be remapped for the entry point and can be emitted directly.
|
|
std::unordered_map<std::string, std::string> ep_func_name_remapped_;
|
|
};
|
|
|
|
} // namespace hlsl
|
|
} // namespace writer
|
|
} // namespace tint
|
|
|
|
#endif // SRC_WRITER_HLSL_GENERATOR_IMPL_H_
|