diff --git a/include/dusk/AST/Pattern.h b/include/dusk/AST/Pattern.h index c0ebc47a92ee8ab1ff76cd36936bb32e3e80fa34..4ab8409e9f258f820bb1b5d8175e60d674a31a80 100644 --- a/include/dusk/AST/Pattern.h +++ b/include/dusk/AST/Pattern.h @@ -1,6 +1,4 @@ - - - //===--- Pattern.h - Dusk patterns ------------------------------*- C++ -*-===// +//===--- Pattern.h - Dusk patterns ------------------------------*- C++ -*-===// // // dusk-lang // This source file is part of a dusk-lang project, which is a semestral diff --git a/include/dusk/AST/Stmt.h b/include/dusk/AST/Stmt.h index a811718b10bf5d2317c3aff269fc378eb37fba7d..46b6b6fe228d43e8c9ef36be8a7da56dbfebda78 100644 --- a/include/dusk/AST/Stmt.h +++ b/include/dusk/AST/Stmt.h @@ -26,7 +26,17 @@ class IdentifierExpr; class ASTWalker; /// Describes statement type. -enum struct StmtKind { Break, Return, Range, Block, Func, For, While, If, Subscript }; +enum struct StmtKind { + Break, + Return, + Range, + Block, + Func, + For, + While, + If, + Subscript +}; class Stmt : public ASTNode { /// Statement type @@ -66,26 +76,26 @@ public: }; /// Subscript statement. -class SubscriptStmt: public Stmt { +class SubscriptStmt : public Stmt { /// Subcript value Expr *Value; - + /// Location of left bracket SMLoc LBracket; - + /// Location of right bracket SMLoc RBracket; - + public: SubscriptStmt(Expr *V, SMLoc L, SMLoc R); - + Expr *getValue() const { return Value; } SMLoc getLBracket() const { return LBracket; } SMLoc getRBracket() const { return RBracket; } - + virtual SMRange getSourceRange() const override; }; - + /// Represents a range. class RangeStmt : public Stmt { /// Start of the range @@ -209,4 +219,3 @@ public: #endif /* DUSK_STMT_H */ - diff --git a/include/dusk/IRGen/Context.h b/include/dusk/IRGen/Context.h index c21c347d558117afd5e1f736cc1ebea5ea741a13..85672bcde19d9a529e402276456b2b13f9b7489b 100644 --- a/include/dusk/IRGen/Context.h +++ b/include/dusk/IRGen/Context.h @@ -23,12 +23,14 @@ #include "llvm/IR/Instructions.h" #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/Module.h" +#include "llvm/IR/GlobalVariable.h" #include <memory> namespace dusk { class VarDecl; class ConstDecl; class FuncDecl; +class ParamDecl; namespace irgen { @@ -89,20 +91,18 @@ private: /// Holds declaration of variables, constatnts and functions. class Context { llvm::LLVMContext &Ctx; - llvm::Module *Module; - llvm::IRBuilder<> &Builder; llvm::StringMap<llvm::FunctionType *> Funcs; ContextVals *Vals; - - unsigned Depth; + unsigned Depth = 0; public: + llvm::Module *Module; + llvm::IRBuilder<> &Builder; + Context(llvm::LLVMContext &C, llvm::Module *M, llvm::IRBuilder<> &B); ~Context(); operator llvm::LLVMContext &() { return Ctx; } - - llvm::IRBuilder<> &getBuilder() { return Builder; } /// Returns current depth of the context. unsigned getDepth() const { return Depth; } @@ -112,6 +112,12 @@ public: /// \return \c true on success, \c false if the current scope is already /// a variable, constatnt or function with the same identifier. bool declare(const VarDecl *); + + /// \brief Declares a param in current scope. + /// + /// \return \c true on success, \c false if the current scope is already + /// a variable, constatnt or function with the same identifier. + bool declare(const ParamDecl *); /// \brief Declares a variable in current scope. /// diff --git a/include/dusk/IRGen/IRGenerator.h b/include/dusk/IRGen/IRGenerator.h index 9368eadd99458c4f223875ed4d1ac17469b41ea8..01c50ca251fb5ac911ac4547963bf3e64b8154d2 100644 --- a/include/dusk/IRGen/IRGenerator.h +++ b/include/dusk/IRGen/IRGenerator.h @@ -39,7 +39,7 @@ namespace irgen { class IRGenerator : public ASTWalker { llvm::StringMap<llvm::AllocaInst *> NamedValues; DiagnosticEngine &Diag; - llvm::LLVMContext Context; + llvm::LLVMContext Ctx; llvm::IRBuilder<> Builder; std::unique_ptr<llvm::Module> Module; @@ -49,7 +49,7 @@ public: IRGenerator(DiagnosticEngine &Diag); ~IRGenerator(); - void gen(ModuleDecl *Module) {} + bool gen(ModuleDecl *M); private: diff --git a/lib/IRGen/CMakeLists.txt b/lib/IRGen/CMakeLists.txt index 6b115e3f8579fe89c634904a1fbf6a70c81b6e2d..e54a233f8c7a910682ca83ab572fac6690d74edb 100644 --- a/lib/IRGen/CMakeLists.txt +++ b/lib/IRGen/CMakeLists.txt @@ -1,7 +1,11 @@ set(SOURCE ${CMAKE_CURRENT_SOURCE_DIR}/Context.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/GenDecl.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/GenDecl.h ${CMAKE_CURRENT_SOURCE_DIR}/GenExpr.cpp ${CMAKE_CURRENT_SOURCE_DIR}/GenExpr.h + ${CMAKE_CURRENT_SOURCE_DIR}/GenStmt.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/GenStmt.h ${CMAKE_CURRENT_SOURCE_DIR}/IRGenerator.cpp ${CMAKE_CURRENT_SOURCE_DIR}/TopLevelExpr.cpp ${CMAKE_CURRENT_SOURCE_DIR}/TopLevelExpr.h diff --git a/lib/IRGen/Context.cpp b/lib/IRGen/Context.cpp index 8d0dbd25ae6fd3180e37bf0a01c235aa27209647..7ac61c403b465a8b5461abde42bb1991b3d07d3b 100644 --- a/lib/IRGen/Context.cpp +++ b/lib/IRGen/Context.cpp @@ -1,4 +1,5 @@ + //===--- Context.cpp - Dusck context implementation -----------------------===// // // dusk-lang @@ -17,6 +18,8 @@ #include "dusk/AST/Pattern.h" #include <vector> +#include "GenExpr.h" + using namespace dusk; using namespace irgen; @@ -72,29 +75,57 @@ llvm::Value *ContextVals::get(StringRef Str) const { // MARK: - Context Context::Context(llvm::LLVMContext &C, llvm::Module *M, llvm::IRBuilder<> &B) - : Ctx(C), Module(M), Builder(B), Vals(new ContextVals()) {} + : Ctx(C), Vals(new ContextVals()), Module(M), Builder(B) {} Context::~Context() { delete Vals; } bool Context::declare(const VarDecl *D) { // Check if already declared in current scope - if (!Vals->isDeclared(D->getName()) || Funcs[D->getName()] != nullptr) + if (Vals->isDeclared(D->getName()) || Funcs[D->getName()] != nullptr) + return false; + + // Check if global + if (Depth == 0) { + auto GV = + Module->getOrInsertGlobal(D->getName(), llvm::Type::getInt64Ty(Ctx)); + Vals->Vars[D->getName()] = GV; + return true; + } + + auto Ty = llvm::Type::getInt64Ty(Ctx); + auto Var = Builder.CreateAlloca(Ty, 0, D->getName()); + Vals->Vars[D->getName()] = Var; + return true; +} + +bool Context::declare(const ParamDecl *D) { + assert(Depth != 0 && "Param declaration happen only in functions"); + // Check if already declared in current scope + if (Vals->isDeclared(D->getName()) || Funcs[D->getName()] != nullptr) return false; - auto Ty = llvm::Type::getInt32Ty(Ctx); - auto Val = Builder.CreateAlloca(Ty, 0, D->getName()); - Vals->Vars[D->getName()] = Val; + auto Ty = llvm::Type::getInt64Ty(Ctx); + auto Par = Builder.CreateAlloca(Ty, 0, D->getName()); + Vals->Vars[D->getName()] = Par; return true; } bool Context::declare(const ConstDecl *D) { // Check if already declared in current scope - if (!Vals->isDeclared(D->getName()) || Funcs[D->getName()] != nullptr) + if (Vals->isDeclared(D->getName()) || Funcs[D->getName()] != nullptr) return false; - auto Ty = llvm::Type::getInt32Ty(Ctx); - auto Val = Builder.CreateAlloca(Ty, 0, D->getName()); - Vals->Consts[D->getName()] = Val; + // Check if global + if (Depth == 0) { + auto GV = + Module->getOrInsertGlobal(D->getName(), llvm::Type::getInt64Ty(Ctx)); + Vals->Consts[D->getName()] = GV; + return true; + } + + auto Ty = llvm::Type::getInt64Ty(Ctx); + auto Const = Builder.CreateAlloca(Ty, 0, D->getName()); + Vals->Consts[D->getName()] = Const; return true; } @@ -106,7 +137,7 @@ bool Context::declare(const FuncDecl *Fn) { if (Funcs[Fn->getName()] != nullptr) return false; - auto Ty = llvm::Type::getInt32Ty(Ctx); + auto Ty = llvm::Type::getInt64Ty(Ctx); auto Args = std::vector<llvm::Type *>(Fn->getArgs()->count(), Ty); auto FT = llvm::FunctionType::get(llvm::Type::getVoidTy(Ctx), Args, false); Funcs[Fn->getName()] = FT; diff --git a/lib/IRGen/GenDecl.cpp b/lib/IRGen/GenDecl.cpp new file mode 100644 index 0000000000000000000000000000000000000000..feda6ba09bb0c1a494fa06dcc9d63bda298fe124 --- /dev/null +++ b/lib/IRGen/GenDecl.cpp @@ -0,0 +1,86 @@ +//===--- GenDecl.cpp ------------------------------------------------------===// +// +// dusk-lang +// This source file is part of a dusk-lang project, which is a semestral +// assignement for BI-PJP course at Czech Technical University in Prague. +// The software is provided "AS IS", WITHOUT WARRANTY OF ANY KIND. +// +//===----------------------------------------------------------------------===// + +#include "GenDecl.h" +#include "GenExpr.h" + +using namespace dusk; +using namespace irgen; + +GenDecl::GenDecl(Decl *D, Context &C) : Declaration(D), Ctx(C) {} + +bool GenDecl::gen() { return codegen(Declaration); } + +bool GenDecl::genArgs() { + assert(Declaration->getKind() == DeclKind::Func && + "Invalid declaration type"); + auto FT = static_cast<FuncDecl *>(Declaration); + + for (auto &Arg : FT->getArgs()->getVars()) + if (!codegen(Arg)) + llvm_unreachable("Error argument declaration"); + return true; +} + +bool GenDecl::codegen(VarDecl *D) { + if (!Ctx.declare(D)) + llvm_unreachable("Redefinition"); + + auto Addr = Ctx.getVal(D->getName()); + auto Val = GenExpr(D->getValue(), Ctx).gen(); + Ctx.Builder.CreateStore(Val, Addr); + return true; +} + +bool GenDecl::codegen(ConstDecl *D) { + if (!Ctx.declare(D)) + llvm_unreachable("Redefinition"); + + auto Addr = Ctx.getVal(D->getName()); + auto Val = GenExpr(D->getValue(), Ctx).gen(); + Ctx.Builder.CreateStore(Val, Addr); + return true; +} + +bool GenDecl::codegen(FuncDecl *D) { + if (!Ctx.declare(D)) + llvm_unreachable("Redefinition of function"); + + auto P = Ctx.getFuncProto(D->getName()); + if (!P) + llvm_unreachable("Function not found"); + + auto F = llvm::Function::Create(P, llvm::Function::ExternalLinkage, + D->getName(), Ctx.Module); + unsigned Idx = 0; + auto Args = D->getArgs()->getVars(); + for (auto &Arg : F->args()) + Arg.setName(Args[Idx++]->getName()); + return true; +} + +bool GenDecl::codegen(ParamDecl *D) { + return Ctx.declare(D); +} + +bool GenDecl::codegen(Decl *D) { + switch (D->getKind()) { + case DeclKind::Var: + return codegen(static_cast<VarDecl *>(D)); + case DeclKind::Const: + return codegen(static_cast<ConstDecl *>(D)); + case DeclKind::Func: + return codegen(static_cast<FuncDecl *>(D)); + case DeclKind::Param: + return codegen(static_cast<ParamDecl *>(D)); + default: + llvm_unreachable("Invalid declaration"); + } +} + diff --git a/lib/IRGen/GenDecl.h b/lib/IRGen/GenDecl.h new file mode 100644 index 0000000000000000000000000000000000000000..e63dff4cc5d175543a3f46fc4a0e9dfaf29518db --- /dev/null +++ b/lib/IRGen/GenDecl.h @@ -0,0 +1,49 @@ +//===--- GenDecl.h - Dusk IR declaration generation -------------*- C++ -*-===// +// +// dusk-lang +// This source file is part of a dusk-lang project, which is a semestral +// assignement for BI-PJP course at Czech Technical University in Prague. +// The software is provided "AS IS", WITHOUT WARRANTY OF ANY KIND. +// +//===----------------------------------------------------------------------===// + +#ifndef DUSK_GEN_DECL_H +#define DUSK_GEN_DECL_H + +#include "dusk/AST/Decl.h" +#include "dusk/AST/Expr.h" +#include "dusk/AST/Stmt.h" +#include "dusk/AST/Pattern.h" +#include "dusk/IRGen/Context.h" +#include "llvm/IR/IRBuilder.h" +#include "llvm/IR/Value.h" +#include "llvm/IR/LLVMContext.h" +#include "GenExpr.h" + +namespace dusk { + +namespace irgen { + +class GenDecl { + Decl *Declaration; + Context &Ctx; + +public: + GenDecl(Decl *D, Context &C); + + bool gen(); + bool genArgs(); + +private: + bool codegen(Decl *D); + bool codegen(VarDecl *D); + bool codegen(ConstDecl *D); + bool codegen(FuncDecl *D); + bool codegen(ParamDecl *D); +}; + +} // namespace irgen + +} // namespace dusk + +#endif /* DUSK_GEN_DECL_H */ diff --git a/lib/IRGen/GenExpr.cpp b/lib/IRGen/GenExpr.cpp index 7a12278b254f330f6d9dc367720ffad67bdae2d3..c5ebcedcd95dee2d486b64beed26184979ccff91 100644 --- a/lib/IRGen/GenExpr.cpp +++ b/lib/IRGen/GenExpr.cpp @@ -20,8 +20,6 @@ GenExpr::GenExpr(Expr *R, Context &C) : Root(R), Ctx(C) {} llvm::Value *GenExpr::gen() { return codegen(Root); } -llvm::Value *GenExpr::codegen(Expr *E) { return nullptr; } - llvm::Value *GenExpr::codegen(NumberLiteralExpr *E) { auto Value = llvm::APSInt::get(E->getValue()); return llvm::ConstantInt::get(Ctx, Value); @@ -29,7 +27,7 @@ llvm::Value *GenExpr::codegen(NumberLiteralExpr *E) { llvm::Value *GenExpr::codegen(IdentifierExpr *E) { auto Addr = Ctx.getVal(E->getName()); - return Ctx.getBuilder().CreateLoad(Addr, E->getName()); + return Ctx.Builder.CreateLoad(Addr, E->getName()); } llvm::Value *GenExpr::codegen(InfixExpr *E) { @@ -41,27 +39,27 @@ llvm::Value *GenExpr::codegen(InfixExpr *E) { switch (E->getOp().getKind()) { // Arithemtic operations case tok::plus: - return Ctx.getBuilder().CreateAdd(LHS, RHS, "addtmp"); + return Ctx.Builder.CreateAdd(LHS, RHS, "addtmp"); case tok::minus: - return Ctx.getBuilder().CreateSub(LHS, RHS, "subtmp"); + return Ctx.Builder.CreateSub(LHS, RHS, "subtmp"); case tok::multipy: - return Ctx.getBuilder().CreateMul(LHS, RHS, "multmp"); + return Ctx.Builder.CreateMul(LHS, RHS, "multmp"); case tok::divide: - return Ctx.getBuilder().CreateSDiv(LHS, RHS, "divtmp"); + return Ctx.Builder.CreateSDiv(LHS, RHS, "divtmp"); // Logical operations case tok::equals: - return Ctx.getBuilder().CreateICmpEQ(LHS, RHS, "eqtmp"); + return Ctx.Builder.CreateICmpEQ(LHS, RHS, "eqtmp"); case tok::nequals: - return Ctx.getBuilder().CreateICmpNE(LHS, RHS, "neqtmp"); + return Ctx.Builder.CreateICmpNE(LHS, RHS, "neqtmp"); case tok::greater: - return Ctx.getBuilder().CreateICmpSGT(LHS, RHS, "gttmp"); + return Ctx.Builder.CreateICmpSGT(LHS, RHS, "gttmp"); case tok::greater_eq: - return Ctx.getBuilder().CreateICmpSGE(LHS, RHS, "getmp"); + return Ctx.Builder.CreateICmpSGE(LHS, RHS, "getmp"); case tok::less: - return Ctx.getBuilder().CreateICmpSLT(LHS, RHS, "lttmp"); + return Ctx.Builder.CreateICmpSLT(LHS, RHS, "lttmp"); case tok::less_eq: - return Ctx.getBuilder().CreateICmpSLE(LHS, RHS, "letmp"); + return Ctx.Builder.CreateICmpSLE(LHS, RHS, "letmp"); default: llvm_unreachable("Invalid infix operand"); @@ -72,11 +70,11 @@ llvm::Value *GenExpr::codegen(PrefixExpr *E) { auto Val = codegen(E->getDest()); if (!Val) return nullptr; - + switch (E->getOp().getKind()) { case tok::neg: - return Ctx.getBuilder().CreateNot(Val); - + return Ctx.Builder.CreateNot(Val); + // TODO: fix unary minus case tok::minus: default: @@ -86,23 +84,23 @@ llvm::Value *GenExpr::codegen(PrefixExpr *E) { llvm::Value *GenExpr::codegen(AssignExpr *E) { // Ensure the LHS is a identifier. - auto VarExpr = dynamic_cast<IdentifierExpr *>(E); + auto VarExpr = dynamic_cast<IdentifierExpr *>(E->getDest()); if (!VarExpr) - return nullptr; - + llvm_unreachable("Invalid LHS"); + // Get variable address auto VarAddr = Ctx.getVar(VarExpr->getName()); auto Val = codegen(E->getSource()); if (!VarAddr || !Val) - return nullptr; - - return Ctx.getBuilder().CreateStore(Val, VarAddr, "assign"); + llvm_unreachable("Invalid val or addr"); + + return Ctx.Builder.CreateStore(Val, VarAddr, "assign"); } llvm::Value *GenExpr::codegen(CallExpr *E) { // Ensure the callee is identifier. auto CalleeID = dynamic_cast<IdentifierExpr *>(E->getCalle()); - + // Ensure args is expression pattern auto ArgsPttrn = dynamic_cast<ExprPattern *>(E->getArgs()); if (!CalleeID || !ArgsPttrn) @@ -116,9 +114,33 @@ llvm::Value *GenExpr::codegen(CallExpr *E) { // Invalid number of arguments if (Fn->arg_size() != ArgsPttrn->count()) return nullptr; - + auto Args = std::vector<llvm::Value *>(Fn->arg_size()); for (auto Arg : ArgsPttrn->getValues()) Args.push_back(codegen(Arg)); - return Ctx.getBuilder().CreateCall(Fn, Args); + return Ctx.Builder.CreateCall(Fn, Args); } + + +llvm::Value *GenExpr::codegen(Expr *E) { + switch (E->getKind()) { + case ExprKind::NumberLiteral: + return codegen(static_cast<NumberLiteralExpr *>(E)); + case ExprKind::Identifier: + return codegen(static_cast<IdentifierExpr *>(E)); + case ExprKind::Paren: + return codegen(static_cast<ParenExpr *>(E)->getExpr()); + case ExprKind::Assign: + return codegen(static_cast<AssignExpr *>(E)); + case ExprKind::Infix: + return codegen(static_cast<InfixExpr *>(E)); + case ExprKind::Prefix: + return codegen(static_cast<PrefixExpr *>(E)); + case ExprKind::Call: + return codegen(static_cast<CallExpr *>(E)); + case ExprKind::Subscript: + return codegen(static_cast<SubscriptExpr *>(E)); + } +} + + diff --git a/lib/IRGen/GenStmt.cpp b/lib/IRGen/GenStmt.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e1d0b03610a44e73e5bd6b1e652cb9e51be271da --- /dev/null +++ b/lib/IRGen/GenStmt.cpp @@ -0,0 +1,170 @@ +//===--- GenStmt.cpp ------------------------------------------------------===// +// +// dusk-lang +// This source file is part of a dusk-lang project, which is a semestral +// assignement for BI-PJP course at Czech Technical University in Prague. +// The software is provided "AS IS", WITHOUT WARRANTY OF ANY KIND. +// +//===----------------------------------------------------------------------===// + +#include "GenStmt.h" +#include "GenDecl.h" +#include "GenExpr.h" + +using namespace dusk; +using namespace irgen; + +GenStmt::GenStmt(Stmt *S, Context &C) +: Statement(S), Ctx(C) +{} + +bool GenStmt::gen() { + return codegen(Statement); +} + +bool GenStmt::codegen(BreakStmt *S) { + return false; +} + +bool GenStmt::codegen(ReturnStmt *S) { + return false; +} + +bool GenStmt::codegen(RangeStmt *S) { + return false; +} + +bool GenStmt::codegen(SubscriptStmt *S) { + return false; +} + +bool GenStmt::codegen(BlockStmt *S) { + for (auto &N : S->getNodes()) { + bool R = false; + + if (auto D = dynamic_cast<Decl *>(N)) + R = GenDecl(D, Ctx).gen(); + else if (auto E = dynamic_cast<Expr *>(N)) + R = GenExpr(E, Ctx).gen() != nullptr; + else if (auto S = dynamic_cast<Stmt *>(N)) + R = GenStmt(S, Ctx).gen(); + else + llvm_unreachable("Unexpected node"); + + if (!R) + return false; + } + return true; +} + +bool GenStmt::codegen(ForStmt *S) { + return false; +} + +bool GenStmt::codegen(WhileStmt *S) { + return false; +} + +bool GenStmt::codegen(IfStmt *S) { + auto CondV = GenExpr(S->getCond(), Ctx).gen(); + if (!CondV) + llvm_unreachable("Error generating condition."); + + auto Zero = llvm::ConstantInt::get(llvm::Type::getInt64Ty(Ctx), 0); + // Convert to bool by comparing with 0 + CondV = Ctx.Builder.CreateICmpNE(CondV, Zero, "ifcond"); + auto F = Ctx.Builder.GetInsertBlock()->getParent(); + + auto *ThenBB = llvm::BasicBlock::Create(Ctx, "then", F); + auto *ElseBB = llvm::BasicBlock::Create(Ctx, "else"); + auto *MergeBB = llvm::BasicBlock::Create(Ctx, "endif"); + + Ctx.Builder.CreateCondBr(CondV, ThenBB, ElseBB); + + // Generate then block + Ctx.Builder.SetInsertPoint(ThenBB); + Ctx.push(); + if (!GenStmt(S->getThen(), Ctx).gen()) + llvm_unreachable("Error generating Then"); + Ctx.pop(); + // pop back to point after the condition. + Ctx.Builder.CreateBr(MergeBB); + + + if (!S->hasElseBlock()) { + // Generate merge block + F->getBasicBlockList().push_back(MergeBB); + Ctx.Builder.SetInsertPoint(MergeBB); + return true; + } + + // Generate else block + F->getBasicBlockList().push_back(ElseBB); + Ctx.push(); + Ctx.Builder.SetInsertPoint(ElseBB); + if (!GenStmt(S->getElse(), Ctx).gen()) + llvm_unreachable("Error generating else"); + Ctx.pop(); + // pop back to point after the condition. + Ctx.Builder.CreateBr(MergeBB); + + // Generate merge block + F->getBasicBlockList().push_back(MergeBB); + Ctx.Builder.SetInsertPoint(MergeBB); + return true; +} + +bool GenStmt::codegen(FuncStmt *S) { + GenDecl FD(S->getPrototype(), Ctx); + // Declare + if (!FD.gen()) + return false; + + // Get function + auto F = Ctx.getFunc(S->getPrototype()->getName()); + if (!F) + return false; + + // Create entry block of the function + auto BB = llvm::BasicBlock::Create(Ctx, "entry", F); + Ctx.Builder.SetInsertPoint(BB); + + // Push new context scope + Ctx.push(); + if (!FD.genArgs()) { + Ctx.pop(); + return false; + } + + if (!codegen(S->getBody())) { + Ctx.pop(); + return false; + } + + Ctx.pop(); + return true; +} + +bool GenStmt::codegen(Stmt *S) { + switch (S->getKind()) { + case StmtKind::Break: + return codegen(static_cast<BreakStmt *>(S)); + case StmtKind::Return: + return codegen(static_cast<ReturnStmt *>(S)); + case StmtKind::Range: + return codegen(static_cast<RangeStmt *>(S)); + case StmtKind::Block: + return codegen(static_cast<BlockStmt *>(S)); + case StmtKind::Func: + return codegen(static_cast<FuncStmt *>(S)); + case StmtKind::For: + return codegen(static_cast<ForStmt *>(S)); + case StmtKind::While: + return codegen(static_cast<WhileStmt *>(S)); + case StmtKind::If: + return codegen(static_cast<IfStmt *>(S)); + case StmtKind::Subscript: + llvm_unreachable("Not implemented yet"); + } +} + diff --git a/lib/IRGen/GenStmt.h b/lib/IRGen/GenStmt.h new file mode 100644 index 0000000000000000000000000000000000000000..2db8edae305ec68b624cb60b410832429573dcf4 --- /dev/null +++ b/lib/IRGen/GenStmt.h @@ -0,0 +1,58 @@ +//===--- GenStmt.h - Dusk IR statement generation ---------------*- C++ -*-===// +// +// dusk-lang +// This source file is part of a dusk-lang project, which is a semestral +// assignement for BI-PJP course at Czech Technical University in Prague. +// The software is provided "AS IS", WITHOUT WARRANTY OF ANY KIND. +// +//===----------------------------------------------------------------------===// + +#ifndef DUSK_GEN_STMT_H +#define DUSK_GEN_STMT_H + +#include "dusk/AST/Decl.h" +#include "dusk/AST/Expr.h" +#include "dusk/AST/Stmt.h" +#include "dusk/AST/Pattern.h" +#include "dusk/IRGen/Context.h" +#include "llvm/IR/IRBuilder.h" +#include "llvm/IR/Value.h" +#include "llvm/IR/LLVMContext.h" + + +namespace dusk { + +namespace irgen { + +class GenDel; +class GenExpr; +class GenStmt; + +class GenStmt { + Stmt *Statement; + Context &Ctx; + +public: + GenStmt(Stmt *S, Context &C); + + bool gen(); + +private: + bool codegen(Stmt *S); + bool codegen(BreakStmt *S); + bool codegen(ReturnStmt *S); + bool codegen(RangeStmt *S); + bool codegen(SubscriptStmt *S); + bool codegen(BlockStmt *S); + bool codegen(ForStmt *S); + bool codegen(WhileStmt *S); + bool codegen(IfStmt *S); + bool codegen(FuncStmt *S); +}; + +} // namespace irgen + +} // namespace dusk + +#endif /* DUSK_GEN_STMT_H */ + diff --git a/lib/IRGen/IRGenerator.cpp b/lib/IRGen/IRGenerator.cpp index e9f0529e43c916bb43459dc89987092c8f53c9bb..9862ee6e67840dc7bde1aae634c3070ce8b0fb85 100644 --- a/lib/IRGen/IRGenerator.cpp +++ b/lib/IRGen/IRGenerator.cpp @@ -10,12 +10,36 @@ #include "dusk/IRGen/IRGenerator.h" #include "dusk/IRGen/Context.h" +#include "GenDecl.h" #include "GenExpr.h" +#include "GenStmt.h" using namespace dusk; using namespace irgen; IRGenerator::IRGenerator(DiagnosticEngine &Diag) - : Diag(Diag), Builder({Context}) {} + : Diag(Diag), Builder({Ctx}) {} IRGenerator::~IRGenerator() {} + +bool IRGenerator::gen(ModuleDecl *M) { + Module = std::make_unique<llvm::Module>(M->getName(), Ctx); + Context Ctx(this->Ctx, Module.get(), Builder); + + for (auto &N : M->getContents()) { + bool R = false; + if (auto D = dynamic_cast<Decl *>(N)) + R = GenDecl(D, Ctx).gen(); + else if (auto E = dynamic_cast<Expr *>(N)) + R = GenExpr(E, Ctx).gen() != nullptr; + else if (auto S = dynamic_cast<Stmt *>(N)) + R = GenStmt(S, Ctx).gen(); + else + llvm_unreachable("Unexpected node"); + + if (!R) + return false; + } + Module->print(llvm::errs(), nullptr); + return true; +}