Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
**bort** is a cross-platform Small-C language cross compiler for RISC-V architecture.

## Global TODOs
- goto
- switch
- compound variable declaration (`int a = 5, b, c = d;`)
- testing
Expand Down
2 changes: 1 addition & 1 deletion dev.sh
Original file line number Diff line number Diff line change
Expand Up @@ -47,5 +47,5 @@ cp -f build/compile_commands.json .
if [ $# -ne 0 ] && [ "$1" == "run" ]; then
echo -e "----------------------------------\n"
set -eux
./build/bort --dump-ast --emit-ir --dump-codegen-info -o - ./tests/corpus/globals.c
./build/bort --dump-ast --emit-ir --dump-codegen-info -o - ./tests/corpus/goto.c
fi
2 changes: 2 additions & 0 deletions include/bort/AST/ASTNode.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ enum class NodeKind {
ReturnStmt,
BreakStmt,
ContinueStmt,
LabelStmt,
GotoStmt,
ASTRoot,
NUM_NODES
};
Expand Down
24 changes: 24 additions & 0 deletions include/bort/AST/GotoStmt.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#pragma once
#include "bort/AST/ASTNode.hpp"

namespace bort::ast {

class GotoStmt final : public Statement {
private:
explicit GotoStmt(std::string targetLabelName)
: Statement{ NodeKind::GotoStmt },
m_TargetLabel{ std::move(targetLabelName) } {
}

public:
[[nodiscard]] auto getTargetLabel() const -> std::string {
return m_TargetLabel;
}

friend class ASTRoot;

private:
std::string m_TargetLabel;
};

} // namespace bort::ast
24 changes: 24 additions & 0 deletions include/bort/AST/LabelStmt.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#pragma once
#include "bort/AST/ASTNode.hpp"

namespace bort::ast {

class LabelStmt final : public Statement {
private:
explicit LabelStmt(std::string labelName)
: Statement{ NodeKind::LabelStmt },
m_LabelName{ std::move(labelName) } {
}

public:
[[nodiscard]] auto getLabelName() const -> std::string {
return m_LabelName;
}

friend class ASTRoot;

private:
std::string m_LabelName;
};

} // namespace bort::ast
6 changes: 5 additions & 1 deletion include/bort/AST/Visitors/ASTPrinter.hpp
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
#pragma once
#include "bort/AST/BreakStmt.hpp"
#include "bort/AST/ContinueStmt.hpp"
#include "bort/AST/GotoStmt.hpp"
#include "bort/AST/IndexationExpr.hpp"
#include "bort/AST/InitializerList.hpp"
#include "bort/AST/LabelStmt.hpp"
#include "bort/AST/UnaryOpExpr.hpp"
#include "bort/AST/Visitors/ASTVisitor.hpp"
#include <concepts>
Expand All @@ -23,6 +25,7 @@ class ASTPrinter : public StructureAwareASTVisitor {
void visit(const Ref<VariableExpr>& varNode) override;
void visit(const Ref<StringExpr>& strNode) override;
void visit(const Ref<CharExpr>& charNode) override;
void visit(const Ref<FunctionCallExpr>& functionCallExpr) override;
void visit(const Ref<VarDecl>& varDeclNode) override;
void visit(const Ref<InitializerList>& initializerListNode) override;
void visit(const Ref<IndexationExpr>& indexationExpr) override;
Expand All @@ -36,7 +39,8 @@ class ASTPrinter : public StructureAwareASTVisitor {
void visit(const Ref<ReturnStmt>& returnStmtNode) override;
void visit(const Ref<BreakStmt>& breakStmtNode) override;
void visit(const Ref<ContinueStmt>& continueStmtNode) override;
void visit(const Ref<FunctionCallExpr>& functionCallExpr) override;
void visit(const Ref<LabelStmt>& labelStmtNode) override;
void visit(const Ref<GotoStmt>& gotoStmtNode) override;

void push();
void pop();
Expand Down
8 changes: 8 additions & 0 deletions include/bort/AST/Visitors/ASTVisitor.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ class WhileStmt;
class ReturnStmt;
class BreakStmt;
class ContinueStmt;
class LabelStmt;
class GotoStmt;

class ASTVisitorBase {
public:
Expand Down Expand Up @@ -88,6 +90,12 @@ class StructureAwareASTVisitor : public ASTVisitorBase {
virtual void visit(const Ref<ContinueStmt>& /* continueNode */) {
// leaf
}
virtual void visit(const Ref<LabelStmt>& /* labelNode */) {
// leaf
}
virtual void visit(const Ref<GotoStmt>& /* gotoNode */) {
// leaf
}
virtual void visit(const Ref<VarDecl>& varDeclNode);
virtual void visit(const Ref<InitializerList>& initializerListNode);
virtual void visit(const Ref<IndexationExpr>& indexationExpr);
Expand Down
5 changes: 5 additions & 0 deletions include/bort/AST/Visitors/SymbolResolutionVisitor.hpp
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
#pragma once
#include "bort/AST/FunctionCallExpr.hpp"
#include "bort/AST/FunctionDecl.hpp"
#include "bort/AST/GotoStmt.hpp"
#include "bort/AST/Visitors/ASTVisitor.hpp"
#include "bort/Basic/Ref.hpp"
#include "bort/Frontend/Symbol.hpp"
#include <optional>
#include <stdexcept>
#include <unordered_map>
#include <unordered_set>

namespace bort::ast {

Expand Down Expand Up @@ -37,11 +39,13 @@ class SymbolResolutionVisitor final : public StructureAwareASTVisitor {
SymbolResolutionVisitor();

protected:
void visit(const Ref<ASTRoot>& astRoot) override;
void visit(const Ref<VariableExpr>& varNode) override;
void visit(const Ref<VarDecl>& varDeclNode) override;
void visit(const Ref<Block>& blockNode) override;
void visit(const Ref<FunctionDecl>& functionDeclNode) override;
void visit(const Ref<FunctionCallExpr>& functionCallExpr) override;
void visit(const Ref<GotoStmt>& gotoStmt) override;

private:
void push();
Expand All @@ -51,5 +55,6 @@ class SymbolResolutionVisitor final : public StructureAwareASTVisitor {
[[nodiscard]] auto resolve(const std::string& name) -> Ref<Symbol>;

Ref<Scope> m_CurrentScope;
std::unordered_set<std::string> m_DefinedLabels;
};
} // namespace bort::ast
80 changes: 29 additions & 51 deletions include/bort/AST/Visitors/Utils.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,11 @@
#include "bort/AST/ExpressionStmt.hpp"
#include "bort/AST/FunctionCallExpr.hpp"
#include "bort/AST/FunctionDecl.hpp"
#include "bort/AST/GotoStmt.hpp"
#include "bort/AST/IfStmt.hpp"
#include "bort/AST/IndexationExpr.hpp"
#include "bort/AST/InitializerList.hpp"
#include "bort/AST/LabelStmt.hpp"
#include "bort/AST/NumberExpr.hpp"
#include "bort/AST/ReturnStmt.hpp"
#include "bort/AST/UnaryOpExpr.hpp"
Expand All @@ -19,6 +21,12 @@
#include "bort/Basic/Casts.hpp"
namespace bort::ast {

template <typename NodeT, typename F>
constexpr static auto castVisit(const Ref<Node>& node, F&& visit) {
bort_assert_nomsg(dynCastRef<NodeT>((node)));
return visit(dynCastRef<NodeT>((node)));
}

/// \brief Driver for all AST walkers
///
/// It is used in StructureAwareASTVisitor which is aimed on more or less
Expand All @@ -30,73 +38,43 @@ template <typename F>
auto callHandler(const Ref<Node>& node, F&& visit) {
switch (node->getKind()) {
case NodeKind::NumberExpr:
bort_assert_nomsg(dynCastRef<NumberExpr>(node));
return visit(dynCastRef<NumberExpr>(node));
break;
return castVisit<NumberExpr>(node, visit);
case NodeKind::VariableExpr:
bort_assert_nomsg(dynCastRef<VariableExpr>(node));
return visit(dynCastRef<VariableExpr>(node));
break;
return castVisit<VariableExpr>(node, visit);
case NodeKind::BinOpExpr:
bort_assert_nomsg(dynCastRef<BinOpExpr>(node));
return visit(dynCastRef<BinOpExpr>(node));
break;
return castVisit<BinOpExpr>(node, visit);
case NodeKind::UnaryOpExpr:
bort_assert_nomsg(dynCastRef<UnaryOpExpr>(node));
return visit(dynCastRef<UnaryOpExpr>(node));
break;
return castVisit<UnaryOpExpr>(node, visit);
case NodeKind::VarDecl:
bort_assert_nomsg(dynCastRef<VarDecl>(node));
return visit(dynCastRef<VarDecl>(node));
break;
return castVisit<VarDecl>(node, visit);
case NodeKind::InitializerList:
bort_assert_nomsg(dynCastRef<InitializerList>(node));
return visit(dynCastRef<InitializerList>(node));
break;
return castVisit<InitializerList>(node, visit);
case NodeKind::IndexationExpr:
bort_assert_nomsg(dynCastRef<IndexationExpr>(node));
return visit(dynCastRef<IndexationExpr>(node));
break;
return castVisit<IndexationExpr>(node, visit);
case NodeKind::FunctionDecl:
bort_assert_nomsg(dynCastRef<FunctionDecl>(node));
return visit(dynCastRef<FunctionDecl>(node));
break;
return castVisit<FunctionDecl>(node, visit);
case NodeKind::FunctionCallExpr:
bort_assert_nomsg(dynCastRef<FunctionCallExpr>(node));
return visit(dynCastRef<FunctionCallExpr>(node));
break;
return castVisit<FunctionCallExpr>(node, visit);
case NodeKind::ExpressionStmt:
bort_assert_nomsg(dynCastRef<ExpressionStmt>(node));
return visit(dynCastRef<ExpressionStmt>(node));
break;
return castVisit<ExpressionStmt>(node, visit);
case NodeKind::Block:
bort_assert_nomsg(dynCastRef<Block>(node));
return visit(dynCastRef<Block>(node));
break;
return castVisit<Block>(node, visit);
case NodeKind::IfStmt:
bort_assert_nomsg(dynCastRef<IfStmt>(node));
return visit(dynCastRef<IfStmt>(node));
break;
return castVisit<IfStmt>(node, visit);
case NodeKind::WhileStmt:
bort_assert_nomsg(dynCastRef<WhileStmt>(node));
return visit(dynCastRef<WhileStmt>(node));
break;
return castVisit<WhileStmt>(node, visit);
case NodeKind::ReturnStmt:
bort_assert_nomsg(dynCastRef<ReturnStmt>(node));
return visit(dynCastRef<ReturnStmt>(node));
break;
return castVisit<ReturnStmt>(node, visit);
case NodeKind::BreakStmt:
bort_assert_nomsg(dynCastRef<BreakStmt>(node));
return visit(dynCastRef<BreakStmt>(node));
break;
return castVisit<BreakStmt>(node, visit);
case NodeKind::ContinueStmt:
bort_assert_nomsg(dynCastRef<ContinueStmt>(node));
return visit(dynCastRef<ContinueStmt>(node));
break;
return castVisit<ContinueStmt>(node, visit);
case NodeKind::LabelStmt:
return castVisit<LabelStmt>(node, visit);
case NodeKind::GotoStmt:
return castVisit<GotoStmt>(node, visit);
case NodeKind::ASTRoot:
bort_assert_nomsg(dynCastRef<ASTRoot>(node));
return visit(dynCastRef<ASTRoot>(node));
break;
return castVisit<ASTRoot>(node, visit);
default:
bort_assert(false, "Generic visit not implemented for node");
// unreachable, casting to root just for fun
Expand Down
10 changes: 9 additions & 1 deletion include/bort/IR/IRCodegen.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@
#include "bort/AST/BreakStmt.hpp"
#include "bort/AST/ContinueStmt.hpp"
#include "bort/AST/FunctionCallExpr.hpp"
#include "bort/AST/GotoStmt.hpp"
#include "bort/AST/IfStmt.hpp"
#include "bort/AST/IndexationExpr.hpp"
#include "bort/AST/InitializerList.hpp"
#include "bort/AST/LabelStmt.hpp"
#include "bort/AST/NumberExpr.hpp"
#include "bort/AST/ReturnStmt.hpp"
#include "bort/AST/UnaryOpExpr.hpp"
Expand All @@ -22,6 +24,8 @@

namespace bort::ir {

struct GotoUnresolvedLabelMD;

class IRCodegen {
public:
[[nodiscard]] auto takeInstructions() -> Module&& {
Expand All @@ -38,6 +42,7 @@ class IRCodegen {
auto visit(const Ref<ast::UnaryOpExpr>& unaryOpExpr) -> ValueRef;
auto visit(const Ref<ast::NumberExpr>& numNode) -> ValueRef;
auto visit(const Ref<ast::VariableExpr>& varNode) -> ValueRef;
auto visit(const Ref<ast::FunctionCallExpr>& funcCallExpr) -> ValueRef;
auto visit(const Ref<ast::VarDecl>& varDeclNode) -> ValueRef;
auto visit(const Ref<ast::InitializerList>& initializerListNode)
-> ValueRef;
Expand All @@ -51,13 +56,16 @@ class IRCodegen {
auto visit(const Ref<ast::ReturnStmt>& returnStmt) -> ValueRef;
auto visit(const Ref<ast::BreakStmt>& breakStmt) -> ValueRef;
auto visit(const Ref<ast::ContinueStmt>& continueStmt) -> ValueRef;
auto visit(const Ref<ast::FunctionCallExpr>& funcCallExpr) -> ValueRef;
auto visit(const Ref<ast::LabelStmt>& labelStmt) -> ValueRef;
auto visit(const Ref<ast::GotoStmt>& gotoStmt) -> ValueRef;

void processGlobalVarDecl(const Ref<ast::VarDecl>& varDeclNode);

auto genBranchFromCondition(const Ref<ast::ExpressionNode>& cond,
bool negate = false) -> Ref<BranchInst>;
auto genArrayPtr(const ValueRef& arr)
-> std::pair<Ref<PointerType>, ValueRef>;
void resolveGotoLabels();

template <typename T>
requires std::is_base_of_v<Instruction, T>
Expand Down
6 changes: 6 additions & 0 deletions include/bort/IR/Module.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,12 @@ class Module : public Value {
return it;
}

[[nodiscard]] auto getLastFunctionIt() {
auto it{ m_Functions.end() };
it--;
return it;
}

[[nodiscard]] auto getLastBBIt() {
auto it{ m_Functions.back().end() };
it--;
Expand Down
2 changes: 2 additions & 0 deletions include/bort/Lex/Tokens.def
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ PUNCT(LBracket, "[")
PUNCT(RBracket, "]")
PUNCT(Comma, ",")
PUNCT(Semicolon, ";")
PUNCT(Colon, ":")
PUNCT(Amp, "&")
PUNCT(Assign, "=")
PUNCT(Equals, "==")
Expand Down Expand Up @@ -73,6 +74,7 @@ KEYWORD(while)
KEYWORD(for)
KEYWORD(return)
KEYWORD(sizeof)
KEYWORD(goto)

// Preprocessor
PPTOK(define)
Expand Down
Loading