Skip to content

Commit

Permalink
scalc llvm codegen
Browse files Browse the repository at this point in the history
  • Loading branch information
lidotcircle committed Aug 1, 2023
1 parent cd22d43 commit 5ab23aa
Show file tree
Hide file tree
Showing 13 changed files with 605 additions and 13 deletions.
48 changes: 48 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
name: Test
on:
push:
branches:
- master
tags:
- v[0-9]+.[0-9]

jobs:
BuildAndTestUbuntu:
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v2
with:
submodules: recursive

- name: release name
id: release
run: |
branch=$(echo ${{github.ref}} | sed 's/refs\/\(heads\|tags\)\///g') && \
release=$([[ "$branch" =~ v[0-9.]+ ]] && echo $branch || echo $branch) && \
echo "release_name=$release" && \
printf "::set-output name=release::%s\n" "$release"
- name: install clang
run: |
wget https://apt.llvm.org/llvm.sh && \
chmod +x llvm.sh && \
sudo ./llvm.sh 17 && \
sudo apt install clang-tidy && \
echo "clang-17: $(which clang-17), clang-tidy: $(which clang-tidy-17)"
- name: Release Build
run: |
export CC=$(which clang-17) && export CXX=$(which clang++-17) && \
mkdir build && cd build && cmake .. -DCMAKE_BUILD_TYPE=Release -DCXX_VERSION=17 && make
- name: Test
run: |
cd build && ctest
- name: release
uses: ncipollo/release-action@v1
with:
allowUpdates: true
artifacts: "./build/example/SimpleCalculator/scalc"
token: ${{ secrets.GITHUB_TOKEN }}
tag: ${{ steps.release.outputs.release }}
8 changes: 8 additions & 0 deletions example/SimpleCalculator/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,8 +1,16 @@
find_package(LLVM REQUIRED CONFIG)
message(STATUS "Found LLVM ${LLVM_PACKAGE_VERSION}")
message(STATUS "Using LLVMConfig.cmake in: ${LLVM_DIR}")

include_directories(${LLVM_INCLUDE_DIRS})
add_definitions(${LLVM_DEFINITIONS})
llvm_map_components_to_libnames(llvm_libs support core irreader)

file(GLOB_RECURSE scalclib_SOURCES CONFIGURE_DEPENDS ./lib/**.cpp)
add_library(scalclib STATIC ${scalclib_SOURCES})
set_property(TARGET scalclib PROPERTY CXX_STANDARD 17)
target_link_libraries(scalclib PUBLIC dcparse)
target_link_libraries(scalclib PUBLIC ${llvm_libs})
target_include_directories(scalclib PUBLIC "${CMAKE_CURRENT_LIST_DIR}/include")

add_executable(scalc ./src/main.cpp)
Expand Down
87 changes: 84 additions & 3 deletions example/SimpleCalculator/include/scalc/ast.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,42 @@
#define _SIMPLE_CALCULATOR_AST_H_

#include "parser/parser.h"
#include "./token.h"
#include <string>
#include <memory>
#include <variant>


using ASTNodeParserContext = std::weak_ptr<DCParser::DCParserContext>;

class ASTNodeExpr;
class ASTNodeExprList;
class ASTNodeBlockStat;
class ASTNodeStat;
class ASTNodeStatList;
class ASTNodeIFStat;
class ASTNodeFunctionDef;
class ASTNodeFunctionDecl;
class ASTNodeCalcUnit;
using UnitItem = std::variant<
std::shared_ptr<ASTNodeFunctionDef>,
std::shared_ptr<ASTNodeFunctionDecl>,
std::shared_ptr<ASTNodeStat>>;


class ASTNodeVisitor {
public:
virtual void visitExpr(const ASTNodeExpr&) = 0;
virtual void visitExprStat(const ASTNodeExprList&) = 0;
virtual void visitBlockStat(const ASTNodeStatList&) = 0;
virtual void visitStatList(const std::vector<std::shared_ptr<ASTNodeStat>>&) = 0;
virtual void visitForStat(const ASTNodeExprList*, const ASTNodeExpr*, const ASTNodeExprList*, const ASTNodeStat&) = 0;
virtual void visitIfStat(const ASTNodeExpr&, const ASTNodeStat&, const ASTNodeStat*) = 0;
virtual void visitReturnStat(const ASTNodeExpr&) = 0;
virtual void visitFuncDef(const std::string&, const std::vector<std::string>&, const ASTNodeBlockStat&) = 0;
virtual void visitFuncDecl(const std::string&, const std::vector<std::string>&) = 0;
virtual void visitCalcUnit(const std::vector<UnitItem>& items) = 0;
};

class ASTNode {
private:
ASTNodeParserContext m_parser_context;
Expand All @@ -17,6 +46,7 @@ class ASTNode {
inline ASTNode(ASTNodeParserContext p): m_parser_context(p) {}
inline ASTNodeParserContext context() { return this->m_parser_context; }
virtual ~ASTNode() = default;
virtual void accept(ASTNodeVisitor& visitor) const = 0;
};


Expand All @@ -26,6 +56,7 @@ class ASTNodeExpr : public ASTNode {

virtual double evaluate() = 0;
virtual bool used() { return false; }
void accept(ASTNodeVisitor& visitor) const override { visitor.visitExpr(*this); }
};

class UnaryOperatorExpr: public ASTNodeExpr {
Expand All @@ -48,6 +79,9 @@ class UnaryOperatorExpr: public ASTNodeExpr {
ASTNodeExpr(c), m_operator(optype),
m_expr(expr) {}

UnaryOperatorType op() const { return m_operator; }
const ASTNodeExpr& cc() const { return *m_expr; }

virtual double evaluate() override;
};

Expand Down Expand Up @@ -76,6 +110,10 @@ class BinaryOperatorExpr: public ASTNodeExpr {
):
ASTNodeExpr(c), m_operator(optype),
m_left(std::move(left)), m_right(std::move(right)) {}

BinaryOperatorType op() const { return m_operator; }
const ASTNodeExpr& left() const { return *m_left; }
const ASTNodeExpr& right() const { return *m_right; }

virtual double evaluate() override;
bool used() override { return m_operator == ASSIGNMENT; }
Expand Down Expand Up @@ -129,6 +167,7 @@ class ASTNodeExprList: public ASTNode, private std::vector<std::shared_ptr<ASTNo
using container_t::size;
using container_t::operator[];
using container_t::push_back;
virtual void accept(ASTNodeVisitor& visitor) const { assert(false); }
};

class FunctionCallExpr: public ASTNodeExpr {
Expand Down Expand Up @@ -180,6 +219,8 @@ class ASTNodeStatList: public ASTNode, private std::vector<std::shared_ptr<ASTNo
using container_t::size;
using container_t::operator[];
using container_t::push_back;

void accept(ASTNodeVisitor& visitor) const override { visitor.visitStatList(*this); }
};

class ASTNodeBlockStat: public ASTNodeStat
Expand All @@ -197,6 +238,7 @@ class ASTNodeBlockStat: public ASTNodeStat
inline const std::shared_ptr<ASTNodeStatList> StatementList() const { return this->_statlist; }

virtual void execute() override;
void accept(ASTNodeVisitor& visitor) const override { visitor.visitBlockStat(*_statlist); }
};

class ASTNodeExprStat: public ASTNodeStat
Expand All @@ -213,6 +255,7 @@ class ASTNodeExprStat: public ASTNodeStat
inline const std::shared_ptr<ASTNodeExprList> exprList() const { return this->_exprlist; }

virtual void execute() override;
void accept(ASTNodeVisitor& visitor) const override { visitor.visitExprStat(*_exprlist); }
};

class ASTNodeReturnStat: public ASTNodeStat
Expand All @@ -229,6 +272,7 @@ class ASTNodeReturnStat: public ASTNodeStat
inline const std::shared_ptr<ASTNodeExpr> expr() const { return this->_expr; }

virtual void execute() override;
void accept(ASTNodeVisitor& visitor) const override { visitor.visitReturnStat(*_expr); }
};

class ASTNodeIFStat: public ASTNodeStat
Expand All @@ -251,6 +295,7 @@ class ASTNodeIFStat: public ASTNodeStat
inline std::shared_ptr<ASTNodeExpr> condition() { return this->_cond; }

virtual void execute() override;
void accept(ASTNodeVisitor& visitor) const override { visitor.visitIfStat(*_cond, *_truestat, _falsestat.get()); }
};

class ASTNodeFORStat: public ASTNodeStat
Expand All @@ -276,6 +321,7 @@ class ASTNodeFORStat: public ASTNodeStat
inline std::shared_ptr<ASTNodeExprList> post() { return this->_post; }

virtual void execute() override;
void accept(ASTNodeVisitor& visitor) const override { visitor.visitForStat(_pre.get(), _cond.get(), _post.get(), *_stat); }
};

/*
Expand Down Expand Up @@ -312,6 +358,8 @@ class ASTNodeArgList: public ASTNode, private std::vector<std::string>
using container_t::size;
using container_t::operator[];
using container_t::push_back;

virtual void accept(ASTNodeVisitor& visitor) const { assert(false); }
};

class ASTNodeFunctionDef: public ASTNode
Expand All @@ -334,19 +382,52 @@ class ASTNodeFunctionDef: public ASTNode
inline std::shared_ptr<ASTNodeBlockStat> blockStat() { return this->blockstat; }

void call(std::vector<double> parameters);
void accept(ASTNodeVisitor& visitor) const override {
std::vector<std::string> args;
for (auto& a: *arglist) args.push_back(a);
visitor.visitFuncDef(static_cast<IDExpr*>(func.get())->id(), args, *blockstat);
}
};

class ASTNodeFunctionDecl: public ASTNode
{
private:
std::shared_ptr<ASTNodeExpr> func;
std::shared_ptr<ASTNodeArgList> arglist;

public:
inline ASTNodeFunctionDecl(
ASTNodeParserContext c,
std::shared_ptr<ASTNodeExpr> func,
std::shared_ptr<ASTNodeArgList> args):
ASTNode(c), func(func), arglist(args) {}

inline std::shared_ptr<ASTNodeExpr> function() { return this->func; }
inline std::shared_ptr<ASTNodeArgList> argList() { return this->arglist; }

void accept(ASTNodeVisitor& visitor) const override {
std::vector<std::string> args;
for (auto& a: *arglist) args.push_back(a);
visitor.visitFuncDecl(static_cast<IDExpr*>(func.get())->id(), args);
}
};

class ASTNodeCalcUnit: public ASTNode
{
private:
std::vector<std::shared_ptr<ASTNodeFunctionDef>> functions;
std::vector<std::shared_ptr<ASTNodeStat>> statements;
std::vector<UnitItem> m_unititem;

public:
inline ASTNodeCalcUnit(ASTNodeParserContext c): ASTNode(c) {}

void push_function(std::shared_ptr<ASTNodeFunctionDef> func) ;
void push_function_decl(std::shared_ptr<ASTNodeFunctionDecl> func) ;
void push_statement(std::shared_ptr<ASTNodeStat> stat);

virtual void accept(ASTNodeVisitor& visitor) const
{
visitor.visitCalcUnit(m_unititem);
}
};

#endif // _SIMPLE_CALCULATOR_AST_H_
2 changes: 2 additions & 0 deletions example/SimpleCalculator/include/scalc/lexer_parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,15 @@ class CalcLexerParser {
private:
CalcParser parser;
CalcLexer lexer;
std::shared_ptr<ASTNode> m_calunit;

public:
CalcLexerParser(bool execute);

void feed(char c);
std::shared_ptr<ASTNode> end();
void reset();
std::string genllvm(const std::string& modulename) const;

std::shared_ptr<SCalcParserContext> getContext();
inline void setDebugStream(std::ostream& out) { this->parser.setDebugStream(out); }
Expand Down
51 changes: 51 additions & 0 deletions example/SimpleCalculator/include/scalc/llvm_visitor.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
#include "ast.h"
#include <map>
#include <string>
#include <memory>
#include <variant>
#include <llvm/IR/IRBuilder.h>
#include <llvm/IR/LLVMContext.h>
#include <llvm/IR/Module.h>
#include <llvm/ADT/APFloat.h>


class ASTNodeVisitorLLVMGen: public ASTNodeVisitor {
private:
std::unique_ptr<llvm::LLVMContext> m_context;
std::unique_ptr<llvm::Module> m_module;
std::unique_ptr<llvm::IRBuilder<>> m_builder;
std::vector<std::map<std::string, std::variant<llvm::AllocaInst*,llvm::GlobalVariable*>>> m_namedValues;
llvm::Value* m_prevValue;
bool m_globalscope;

llvm::Value* lookup_var(const std::string& name)
{
for (size_t i=m_namedValues.size();i>0;i--) {
auto& k = m_namedValues.at(i - 1);
if (k.count(name)) {
if (std::holds_alternative<llvm::AllocaInst*>(k.at(name))) {
return std::get<0>(k.at(name));
} else {
return std::get<1>(k.at(name));
}
}
}
return nullptr;
}

public:
ASTNodeVisitorLLVMGen(const std::string& filename);

void visitExpr(const ASTNodeExpr&) override;
void visitExprStat(const ASTNodeExprList&) override;
void visitBlockStat(const ASTNodeStatList&) override;
void visitStatList(const std::vector<std::shared_ptr<ASTNodeStat>>&) override;
void visitForStat(const ASTNodeExprList*, const ASTNodeExpr*, const ASTNodeExprList*, const ASTNodeStat&) override;
void visitIfStat(const ASTNodeExpr&, const ASTNodeStat&, const ASTNodeStat*) override;
void visitReturnStat(const ASTNodeExpr&) override;
void visitFuncDef(const std::string&, const std::vector<std::string>&, const ASTNodeBlockStat&) override;
void visitFuncDecl(const std::string&, const std::vector<std::string>&) override;
void visitCalcUnit(const std::vector<UnitItem>&) override;

std::string codegen() const;
};
1 change: 1 addition & 0 deletions example/SimpleCalculator/include/scalc/parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
TENTRY(CalcUnit) \
TENTRY(ArgList) \
TENTRY(FunctionDef) \
TENTRY(FunctionDecl) \
\
TENTRY(IfStatement) \
TENTRY(ForStatement) \
Expand Down
9 changes: 7 additions & 2 deletions example/SimpleCalculator/lib/ast.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ class ASTNodeFunctionExec: public SCalcFunction

void ASTNodeCalcUnit::push_function(shared_ptr<ASTNodeFunctionDef> func)
{
this->functions.push_back(func);
this->m_unititem.push_back(func);

auto funcname = func->function();
auto funcnamet = dynamic_pointer_cast<IDExpr>(funcname);
Expand All @@ -52,9 +52,14 @@ void ASTNodeCalcUnit::push_function(shared_ptr<ASTNodeFunctionDef> func)
context->add_function(funcnamet->id(), make_shared<ASTNodeFunctionExec>(func));
}

void ASTNodeCalcUnit::push_function_decl(shared_ptr<ASTNodeFunctionDecl> func)
{
this->m_unititem.push_back(func);
}

void ASTNodeCalcUnit::push_statement(shared_ptr<ASTNodeStat> stat)
{
this->statements.push_back(stat);
this->m_unititem.push_back(stat);

auto context = this->context();
auto ptr = context.lock();
Expand Down
1 change: 0 additions & 1 deletion example/SimpleCalculator/lib/context.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
#include "scalc/context.h"
#include "scalc/ast.h"
#include "scalc/scalc_error.h"
#include "scalc/defer.hpp"
#include <assert.h>
Expand Down
Loading

0 comments on commit 5ab23aa

Please sign in to comment.