-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
13 changed files
with
527 additions
and
24 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
#pragma once | ||
|
||
#include <vull/container/vector.hh> | ||
#include <vull/shaderc/arena.hh> | ||
#include <vull/shaderc/type.hh> | ||
#include <vull/support/variant.hh> | ||
|
||
#include <stdint.h> | ||
|
||
namespace vull::shaderc::hir { | ||
|
||
enum class NodeKind { | ||
FunctionDecl, | ||
|
||
BinaryExpr, | ||
BuiltinExpr, | ||
PipelineVar, | ||
}; | ||
|
||
class Node { | ||
const NodeKind m_kind; | ||
|
||
public: | ||
explicit Node(NodeKind kind) : m_kind(kind) {} | ||
|
||
NodeKind kind() const { return m_kind; } | ||
}; | ||
|
||
class Aggregate : public Node { | ||
Vector<Node *> m_nodes; | ||
|
||
public: | ||
explicit Aggregate(NodeKind kind) : Node(kind) {} | ||
|
||
void append_node(Node *node) { m_nodes.push(node); } | ||
}; | ||
|
||
class Expr : public Node { | ||
Type m_type; | ||
|
||
public: | ||
explicit Expr(NodeKind kind) : Node(kind) {} | ||
|
||
void set_type(Type type) { m_type = type; } | ||
Type type() const { return m_type; } | ||
}; | ||
|
||
enum class BinaryOp { | ||
Assign, | ||
|
||
ScalarTimesScalar, | ||
VectorTimesScalar, | ||
MatrixTimesScalar, | ||
VectorTimesMatrix, | ||
MatrixTimesVector, | ||
MatrixTimesMatrix, | ||
}; | ||
|
||
class BinaryExpr : public Expr { | ||
Expr *m_lhs; | ||
Expr *m_rhs; | ||
BinaryOp m_op; | ||
|
||
public: | ||
BinaryExpr(Expr *lhs, Expr *rhs) : Expr(NodeKind::BinaryExpr), m_lhs(lhs), m_rhs(rhs) {} | ||
|
||
void set_op(BinaryOp op) { m_op = op; } | ||
BinaryOp op() const { return m_op; } | ||
}; | ||
|
||
enum class BuiltinFunction { | ||
Dot, | ||
Max, | ||
}; | ||
|
||
class BuiltinExpr : public Expr { | ||
BuiltinFunction m_function; | ||
|
||
public: | ||
BuiltinExpr(BuiltinFunction function) : Expr(NodeKind::BuiltinExpr), m_function(function) {} | ||
|
||
BuiltinFunction function() const { return m_function; } | ||
}; | ||
|
||
class FunctionDecl : public Node { | ||
Type m_return_type; | ||
Vector<Type> m_parameter_types; | ||
}; | ||
|
||
class Root { | ||
Arena m_arena; | ||
Vector<Node *> m_top_level_nodes; | ||
|
||
public: | ||
template <typename T, typename... Args> | ||
T *allocate(Args &&...args) { | ||
return m_arena.allocate<T>(vull::forward<Args>(args)...); | ||
} | ||
|
||
void append_top_level(Node *node) { | ||
m_top_level_nodes.push(node); | ||
} | ||
}; | ||
|
||
} // namespace vull::shaderc::hir |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
#pragma once | ||
|
||
#include <vull/container/hash_map.hh> | ||
#include <vull/shaderc/ast.hh> | ||
#include <vull/shaderc/hir.hh> | ||
#include <vull/support/result.hh> | ||
#include <vull/support/tuple.hh> | ||
#include <vull/support/unique_ptr.hh> | ||
|
||
namespace vull::shaderc { | ||
|
||
enum class LegaliseError { | ||
|
||
}; | ||
|
||
class Legaliser { | ||
class Scope; | ||
|
||
private: | ||
hir::Root m_root; | ||
Scope *m_scope{nullptr}; | ||
UniquePtr<Scope> m_root_scope; | ||
HashMap<StringView, Tuple<hir::BuiltinFunction, Type>> m_builtin_functions; | ||
|
||
Result<hir::Expr *, LegaliseError> lower_binary_expr(const ast::BinaryExpr &); | ||
Result<hir::Expr *, LegaliseError> lower_call_expr(const ast::CallExpr &); | ||
Result<hir::Expr *, LegaliseError> lower_symbol(const ast::Symbol &); | ||
Result<hir::Expr *, LegaliseError> lower_expr(const ast::Node &); | ||
|
||
Result<hir::Node *, LegaliseError> lower_function_decl(const ast::FunctionDecl &); | ||
Result<hir::Node *, LegaliseError> lower_pipeline_decl(const ast::PipelineDecl &); | ||
Result<hir::Node *, LegaliseError> lower_top_level(const ast::Node &); | ||
|
||
public: | ||
Legaliser(); | ||
Legaliser(const Legaliser &) = delete; | ||
Legaliser(Legaliser &&) = delete; | ||
~Legaliser(); | ||
|
||
Legaliser &operator=(const Legaliser &) = delete; | ||
Legaliser &operator=(Legaliser &&) = delete; | ||
|
||
Result<hir::Root, LegaliseError> legalise(const ast::Root &); | ||
}; | ||
|
||
} // namespace vull::shaderc |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
#pragma once | ||
|
||
namespace vull::shaderc::hir { | ||
|
||
class Root; | ||
|
||
} // namespace vull::shaderc::hir | ||
|
||
namespace vull::shaderc::spv { | ||
|
||
class Builder; | ||
|
||
void build_spv(Builder &builder, const hir::Root &hir_root); | ||
|
||
} // namespace vull::shaderc::spv |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,134 @@ | ||
#include <vull/shaderc/legaliser.hh> | ||
|
||
#include <vull/container/hash_map.hh> | ||
#include <vull/support/string_view.hh> | ||
|
||
namespace vull::shaderc { | ||
|
||
class Legaliser::Scope { | ||
Scope *&m_current; | ||
Scope *m_parent; | ||
HashMap<StringView, hir::Expr *> m_symbol_map; | ||
|
||
public: | ||
explicit Scope(Scope *¤t); | ||
Scope(const Scope &) = delete; | ||
Scope(Scope &&) = delete; | ||
~Scope(); | ||
|
||
Scope &operator=(const Scope &) = delete; | ||
Scope &operator=(Scope &&) = delete; | ||
|
||
Result<hir::Expr *, LegaliseError> lookup_symbol(StringView name) const; | ||
Result<void, LegaliseError> put_symbol(StringView name, hir::Expr *expr); | ||
}; | ||
|
||
Legaliser::Scope::Scope(Scope *¤t) : m_current(current), m_parent(current) { | ||
current = this; | ||
} | ||
|
||
Legaliser::Scope::~Scope() { | ||
m_current = m_parent; | ||
} | ||
|
||
Result<hir::Expr *, LegaliseError> Legaliser::Scope::lookup_symbol(StringView name) const { | ||
if (auto symbol = m_symbol_map.get(name)) { | ||
return *symbol; | ||
} | ||
if (m_parent == nullptr) { | ||
// TODO: Not found. | ||
VULL_ENSURE_NOT_REACHED(); | ||
} | ||
return m_parent->lookup_symbol(name); | ||
} | ||
|
||
Result<void, LegaliseError> Legaliser::Scope::put_symbol(StringView name, hir::Expr *expr) { | ||
// TODO: Check for redeclaration. | ||
m_symbol_map.set(name, expr); | ||
return {}; | ||
} | ||
|
||
Legaliser::Legaliser() : m_root_scope(new Scope(m_scope)) {} | ||
Legaliser::~Legaliser() = default; | ||
|
||
Result<hir::Expr *, LegaliseError> Legaliser::lower_binary_expr(const ast::BinaryExpr &ast_expr) { | ||
auto *lhs = VULL_TRY(lower_expr(ast_expr.lhs())); | ||
auto *rhs = VULL_TRY(lower_expr(ast_expr.rhs())); | ||
auto *expr = m_root.allocate<hir::BinaryExpr>(lhs, rhs); | ||
|
||
if (ast::is_assign_op(ast_expr.op())) { | ||
// TODO: Handle other assigns. | ||
VULL_ENSURE(ast_expr.op() == ast::BinaryOp::Assign); | ||
expr->set_op(hir::BinaryOp::Assign); | ||
expr->set_type(lhs->type()); | ||
return expr; | ||
} | ||
|
||
const auto &lhs_type = lhs->type(); | ||
const auto &rhs_type = rhs->type(); | ||
if ((lhs_type.is_vector() && rhs_type.is_scalar()) || (lhs_type.is_scalar() && rhs_type.is_vector())) { | ||
expr->set_op(hir::BinaryOp::VectorTimesScalar); | ||
expr->set_type(lhs_type.is_vector() ? lhs_type : rhs_type); | ||
} else if ((lhs_type.is_matrix() && rhs_type.is_scalar()) || (lhs_type.is_scalar() && rhs_type.is_matrix())) { | ||
expr->set_op(hir::BinaryOp::MatrixTimesScalar); | ||
expr->set_type(lhs_type.is_matrix() ? lhs_type : rhs_type); | ||
} else if (lhs_type.is_vector() && rhs_type.is_matrix()) { | ||
expr->set_op(hir::BinaryOp::VectorTimesMatrix); | ||
expr->set_type(Type(lhs_type.scalar_type(), rhs_type.matrix_cols())); | ||
} else if (lhs_type.is_matrix() && rhs_type.is_vector()) { | ||
expr->set_op(hir::BinaryOp::MatrixTimesVector); | ||
expr->set_type(Type(lhs_type.scalar_type(), lhs_type.matrix_rows())); | ||
} else if (lhs_type.is_matrix() && rhs_type.is_matrix()) { | ||
expr->set_op(hir::BinaryOp::MatrixTimesMatrix); | ||
expr->set_type(Type(lhs_type.scalar_type(), rhs_type.matrix_cols(), lhs_type.matrix_rows())); | ||
} else if (lhs_type.is_scalar() && rhs_type.is_scalar()) { | ||
expr->set_op(hir::BinaryOp::ScalarTimesScalar); | ||
expr->set_type(lhs_type.scalar_type()); | ||
} else { | ||
VULL_ENSURE_NOT_REACHED(); | ||
} | ||
return expr; | ||
} | ||
|
||
Result<hir::Expr *, LegaliseError> Legaliser::lower_call_expr(const ast::CallExpr &ast_expr) { | ||
if (auto builtin = m_builtin_functions.get(ast_expr.name())) { | ||
// TODO: Need to check parameter types match. | ||
auto *expr = m_root.allocate<hir::BuiltinExpr>(vull::get<0>(*builtin)); | ||
expr->set_type(vull::get<1>(*builtin)); | ||
return expr; | ||
} | ||
} | ||
|
||
Result<hir::Expr *, LegaliseError> Legaliser::lower_symbol(const ast::Symbol &ast_symbol) { | ||
return VULL_TRY(m_scope->lookup_symbol(ast_symbol.name())); | ||
} | ||
|
||
Result<hir::Expr *, LegaliseError> Legaliser::lower_expr(const ast::Node &) {} | ||
|
||
Result<hir::Node *, LegaliseError> Legaliser::lower_function_decl(const ast::FunctionDecl &ast_decl) { | ||
auto *function = m_root.allocate<hir::FunctionDecl>(); | ||
|
||
return function; | ||
} | ||
|
||
Result<hir::Node *, LegaliseError> Legaliser::lower_pipeline_decl(const ast::PipelineDecl &ast_decl) { | ||
auto *expr = m_root.allocate<hir::Expr>(hir::NodeKind::PipelineVar); | ||
expr->set_type(ast_decl.type()); | ||
VULL_TRY(m_scope->put_symbol(ast_decl.name(), expr)); | ||
return nullptr; | ||
} | ||
|
||
Result<hir::Node *, LegaliseError> Legaliser::lower_top_level(const ast::Node &) { | ||
|
||
} | ||
|
||
Result<hir::Root, LegaliseError> Legaliser::legalise(const ast::Root &ast_root) { | ||
for (const auto *ast_node : ast_root.top_level_nodes()) { | ||
if (auto *node = VULL_TRY(lower_top_level(*ast_node))) { | ||
m_root.append_top_level(node); | ||
} | ||
} | ||
return vull::move(m_root); | ||
} | ||
|
||
} // namespace vull::shaderc |
Oops, something went wrong.