diff --git a/include/IR/IR.h b/include/IR/IR.h new file mode 100644 index 0000000..083308b --- /dev/null +++ b/include/IR/IR.h @@ -0,0 +1,3 @@ +#pragma once +#include "IR_basic.h" +#include "IRBuilder.h" \ No newline at end of file diff --git a/include/IR/IRBuilder.h b/include/IR/IRBuilder.h new file mode 100644 index 0000000..4001b9f --- /dev/null +++ b/include/IR/IRBuilder.h @@ -0,0 +1,54 @@ +#include +#include "IR_basic.h" +#include "ast/astnode_visitor.h" +class IRBuilder : public ASTNodeVirturalVisitor { + std::shared_ptr prog; + + public: + // Structural AST Nodes + void ActuralVisit(FuncDef_ASTNode *node) override; + void ActuralVisit(ClassDef_ASTNode *node) override; + void ActuralVisit(Program_ASTNode *node) override; + + // Statement AST Nodes + void ActuralVisit(EmptyStatement_ASTNode *node) override; + void ActuralVisit(DefinitionStatement_ASTNode *node) override; + void ActuralVisit(ExprStatement_ASTNode *node) override; + void ActuralVisit(IfStatement_ASTNode *node) override; + void ActuralVisit(WhileStatement_ASTNode *node) override; + void ActuralVisit(ForStatement_ASTNode *node) override; + void ActuralVisit(JmpStatement_ASTNode *node) override; + void ActuralVisit(SuiteStatement_ASTNode *node) override; + + // Expression AST Nodes + void ActuralVisit(NewArrayExpr_ASTNode *node) override; + void ActuralVisit(NewConstructExpr_ASTNode *node) override; + void ActuralVisit(NewExpr_ASTNode *node) override; + void ActuralVisit(AccessExpr_ASTNode *node) override; + void ActuralVisit(IndexExpr_ASTNode *node) override; + void ActuralVisit(SuffixExpr_ASTNode *node) override; + void ActuralVisit(PrefixExpr_ASTNode *node) override; + void ActuralVisit(OppositeExpr_ASTNode *node) override; + void ActuralVisit(LNotExpr_ASTNode *node) override; + void ActuralVisit(BNotExpr_ASTNode *node) override; + void ActuralVisit(MDMExpr_ASTNode *node) override; + void ActuralVisit(PMExpr_ASTNode *node) override; + void ActuralVisit(RLExpr_ASTNode *node) override; + void ActuralVisit(GGLLExpr_ASTNode *node) override; + void ActuralVisit(NEExpr_ASTNode *node) override; + void ActuralVisit(BAndExpr_ASTNode *node) override; + void ActuralVisit(BXorExpr_ASTNode *node) override; + void ActuralVisit(BOrExpr_ASTNode *node) override; + void ActuralVisit(LAndExpr_ASTNode *node) override; + void ActuralVisit(LOrExpr_ASTNode *node) override; + void ActuralVisit(TernaryExpr_ASTNode *node) override; + void ActuralVisit(AssignExpr_ASTNode *node) override; + void ActuralVisit(ThisExpr_ASTNode *node) override; + void ActuralVisit(ParenExpr_ASTNode *node) override; + void ActuralVisit(IDExpr_ASTNode *node) override; + void ActuralVisit(FunctionCallExpr_ASTNode *node) override; + void ActuralVisit(FormattedStringExpr_ASTNode *node) override; + void ActuralVisit(ConstantExpr_ASTNode *node) override; +}; + +std::shared_ptr BuildIR(std::shared_ptr src); \ No newline at end of file diff --git a/include/IR/IR_basic.h b/include/IR/IR_basic.h new file mode 100644 index 0000000..d9f6fe5 --- /dev/null +++ b/include/IR/IR_basic.h @@ -0,0 +1,143 @@ +#pragma once +#include +#include +#include +#include +#include +#include "ast/astnode.h" +struct LLVMIRIntType { + size_t bits; +}; +struct LLVMIRPTRType {}; +struct LLVMIRCLASSTYPE {}; +using LLVMType = std::variant; +class LLVMIRItemBase { + public: + LLVMIRItemBase() = default; + virtual ~LLVMIRItemBase() = default; + virtual void RecursivePrint(std::ostream &os) const; +}; + +class TypeDefItem : public LLVMIRItemBase { + public: + void RecursivePrint(std::ostream &os) const { ; } +}; +class GlobalVarDefItem : public LLVMIRItemBase { + LLVMType type; + std::string name; + + public: + void RecursivePrint(std::ostream &os) const { ; } +}; +class ActionItem : public LLVMIRItemBase { + public: + void RecursivePrint(std::ostream &os) const { ; } +}; +class JMPActionItem : public ActionItem { + std::string label; + public: + void RecursivePrint(std::ostream &os) const { ; } +}; +class BRAction: public JMPActionItem { + std::string cond; + std::string true_label; + std::string false_label; + public: + void RecursivePrint(std::ostream &os) const { ; } +}; +class UNConditionJMPAction: public JMPActionItem { + std::string label; + public: + void RecursivePrint(std::ostream &os) const { ; } +}; +class RETAction : public JMPActionItem { + std::string value; + public: + void RecursivePrint(std::ostream &os) const { ; } +}; +class BinaryOperationAction : public ActionItem { + std::string op; + std::string lhs; + std::string rhs; + std::string result; + LLVMType type; + public: + void RecursivePrint(std::ostream &os) const { ; } +}; +class AllocaAction : public ActionItem { + std::string name; + LLVMType type; + size_t num; + public: + void RecursivePrint(std::ostream &os) const { ; } +}; +class LoadAction : public ActionItem { + std::string result; + LLVMType ty; + std::string ptr; + public: + void RecursivePrint(std::ostream &os) const { ; } +}; +class StoreAction : public ActionItem { + LLVMType ty; + std::string value; + std::string ptr; + public: + void RecursivePrint(std::ostream &os) const { ; } +}; +class GetElementPtrAction : public ActionItem { + std::string result; + LLVMType ty; + std::string ptr; + std::vector indices; + public: + void RecursivePrint(std::ostream &os) const { ; } +}; +class ICMPAction : public ActionItem { + std::string op; + std::string lhs; + std::string rhs; + std::string result; + LLVMType ty; + public: + void RecursivePrint(std::ostream &os) const { ; } +}; +class BlockItem : public LLVMIRItemBase { + std::string label; + std::vector> actions; + std::shared_ptr exit_action; + public: + void RecursivePrint(std::ostream &os) const { ; } +}; +class FunctionDefItem : public LLVMIRItemBase { + std::vector> basic_blocks; + + public: + void RecursivePrint(std::ostream &os) const { + for (auto &item : basic_blocks) { + item->RecursivePrint(os); + os << '\n'; + } + } +}; +class ModuleItem : public LLVMIRItemBase { + std::vector> type_defs; + std::vector> global_var_defs; + std::vector> function_defs; + + public: + void RecursivePrint(std::ostream &os) const { + for (auto &item : type_defs) { + item->RecursivePrint(os); + os << '\n'; + } + for (auto &item : global_var_defs) { + item->RecursivePrint(os); + os << '\n'; + } + for (auto &item : function_defs) { + item->RecursivePrint(os); + os << '\n'; + } + } +}; \ No newline at end of file diff --git a/include/ast/ast.h b/include/ast/ast.h index 5997c1a..39f868f 100644 --- a/include/ast/ast.h +++ b/include/ast/ast.h @@ -2,6 +2,7 @@ #define AST_H #include "astnode.h" #include "astnode_visitor.h" +#include "semantic_visitor.h" #include "expr_astnode.h" #include "statement_astnode.h" #include "structural_astnode.h" diff --git a/include/ast/astnode_visitor.h b/include/ast/astnode_visitor.h index 5869d9c..32d37c7 100644 --- a/include/ast/astnode_visitor.h +++ b/include/ast/astnode_visitor.h @@ -54,67 +54,4 @@ class ASTNodeVirturalVisitor : public ASTNodeVisitorBase { virtual void ActuralVisit(ConstantExpr_ASTNode *node) = 0; }; -class ASTSemanticCheckVisitor : public ASTNodeVirturalVisitor { - bool is_in_func_def; - bool has_return; - FunctionSchema cur_func_schema; - std::string cur_class_name; - bool is_in_class_def; - size_t loop_level; - std::shared_ptr global_scope; - friend std::shared_ptr CheckAndDecorate(std::shared_ptr src); - - bool ClassExists(const std::string &name) { - if (name == "int" || name == "bool") return true; - return global_scope->classes.find(name) != global_scope->classes.end(); - } - - public: - ASTSemanticCheckVisitor() : is_in_func_def(false), loop_level(0) {} - // Structural AST Nodes - void ActuralVisit(FuncDef_ASTNode *node) override; - void ActuralVisit(ClassDef_ASTNode *node) override; - void ActuralVisit(Program_ASTNode *node) override; - - // Statement AST Nodes - void ActuralVisit(EmptyStatement_ASTNode *node) override; - void ActuralVisit(DefinitionStatement_ASTNode *node) override; - void ActuralVisit(ExprStatement_ASTNode *node) override; - void ActuralVisit(IfStatement_ASTNode *node) override; - void ActuralVisit(WhileStatement_ASTNode *node) override; - void ActuralVisit(ForStatement_ASTNode *node) override; - void ActuralVisit(JmpStatement_ASTNode *node) override; - void ActuralVisit(SuiteStatement_ASTNode *node) override; - - // Expression AST Nodes - void ActuralVisit(NewArrayExpr_ASTNode *node) override; - void ActuralVisit(NewConstructExpr_ASTNode *node) override; - void ActuralVisit(NewExpr_ASTNode *node) override; - void ActuralVisit(AccessExpr_ASTNode *node) override; - void ActuralVisit(IndexExpr_ASTNode *node) override; - void ActuralVisit(SuffixExpr_ASTNode *node) override; - void ActuralVisit(PrefixExpr_ASTNode *node) override; - void ActuralVisit(OppositeExpr_ASTNode *node) override; - void ActuralVisit(LNotExpr_ASTNode *node) override; - void ActuralVisit(BNotExpr_ASTNode *node) override; - void ActuralVisit(MDMExpr_ASTNode *node) override; - void ActuralVisit(PMExpr_ASTNode *node) override; - void ActuralVisit(RLExpr_ASTNode *node) override; - void ActuralVisit(GGLLExpr_ASTNode *node) override; - void ActuralVisit(NEExpr_ASTNode *node) override; - void ActuralVisit(BAndExpr_ASTNode *node) override; - void ActuralVisit(BXorExpr_ASTNode *node) override; - void ActuralVisit(BOrExpr_ASTNode *node) override; - void ActuralVisit(LAndExpr_ASTNode *node) override; - void ActuralVisit(LOrExpr_ASTNode *node) override; - void ActuralVisit(TernaryExpr_ASTNode *node) override; - void ActuralVisit(AssignExpr_ASTNode *node) override; - void ActuralVisit(ThisExpr_ASTNode *node) override; - void ActuralVisit(ParenExpr_ASTNode *node) override; - void ActuralVisit(IDExpr_ASTNode *node) override; - void ActuralVisit(FunctionCallExpr_ASTNode *node) override; - void ActuralVisit(FormattedStringExpr_ASTNode *node) override; - void ActuralVisit(ConstantExpr_ASTNode *node) override; -}; - #endif // ASTNODE_ActuralVisitOR_H \ No newline at end of file diff --git a/include/ast/scope.hpp b/include/ast/scope.hpp index 6a1cf45..4899078 100644 --- a/include/ast/scope.hpp +++ b/include/ast/scope.hpp @@ -17,6 +17,7 @@ class ScopeBase { protected: ScopeBase *parent; // cannot use std::shared_ptr because of circular dependency + size_t scope_id; virtual bool VariableNameAvailable(const std::string &name, int ttl) = 0; virtual bool add_variable(const std::string &name, const ExprTypeInfo &type) = 0; virtual ExprTypeInfo fetch_varaible(const std::string &name) = 0; @@ -26,6 +27,11 @@ class ScopeBase { "for", "while", "break", "continue", "return"}; return keywords.find(name) != keywords.end(); } + public: + ScopeBase() { + static size_t scope_counter=0; + scope_id = scope_counter++; + } }; class LocalScope : public ScopeBase { friend class Visitor; @@ -104,6 +110,7 @@ class ClassDefScope : public ScopeBase { friend std::shared_ptr CheckAndDecorate(std::shared_ptr src); std::unordered_map member_variables; std::unordered_map> member_functions; + IRClassInfo llvm_class_info; bool add_variable(const std::string &name, const ExprTypeInfo &type) override { if (!VariableNameAvailable(name, 0)) { return false; diff --git a/include/ast/semantic_visitor.h b/include/ast/semantic_visitor.h new file mode 100644 index 0000000..521cc71 --- /dev/null +++ b/include/ast/semantic_visitor.h @@ -0,0 +1,69 @@ +#pragma once +#include "astnode.h" +#include "expr_astnode.h" +#include "statement_astnode.h" +#include "structural_astnode.h" +#include "astnode_visitor.h" + +class ASTSemanticCheckVisitor : public ASTNodeVirturalVisitor { + bool is_in_func_def; + bool has_return; + FunctionSchema cur_func_schema; + std::string cur_class_name; + bool is_in_class_def; + size_t loop_level; + std::shared_ptr global_scope; + friend std::shared_ptr CheckAndDecorate(std::shared_ptr src); + + bool ClassExists(const std::string &name) { + if (name == "int" || name == "bool") return true; + return global_scope->classes.find(name) != global_scope->classes.end(); + } + + public: + ASTSemanticCheckVisitor() : is_in_func_def(false), loop_level(0) {} + // Structural AST Nodes + void ActuralVisit(FuncDef_ASTNode *node) override; + void ActuralVisit(ClassDef_ASTNode *node) override; + void ActuralVisit(Program_ASTNode *node) override; + + // Statement AST Nodes + void ActuralVisit(EmptyStatement_ASTNode *node) override; + void ActuralVisit(DefinitionStatement_ASTNode *node) override; + void ActuralVisit(ExprStatement_ASTNode *node) override; + void ActuralVisit(IfStatement_ASTNode *node) override; + void ActuralVisit(WhileStatement_ASTNode *node) override; + void ActuralVisit(ForStatement_ASTNode *node) override; + void ActuralVisit(JmpStatement_ASTNode *node) override; + void ActuralVisit(SuiteStatement_ASTNode *node) override; + + // Expression AST Nodes + void ActuralVisit(NewArrayExpr_ASTNode *node) override; + void ActuralVisit(NewConstructExpr_ASTNode *node) override; + void ActuralVisit(NewExpr_ASTNode *node) override; + void ActuralVisit(AccessExpr_ASTNode *node) override; + void ActuralVisit(IndexExpr_ASTNode *node) override; + void ActuralVisit(SuffixExpr_ASTNode *node) override; + void ActuralVisit(PrefixExpr_ASTNode *node) override; + void ActuralVisit(OppositeExpr_ASTNode *node) override; + void ActuralVisit(LNotExpr_ASTNode *node) override; + void ActuralVisit(BNotExpr_ASTNode *node) override; + void ActuralVisit(MDMExpr_ASTNode *node) override; + void ActuralVisit(PMExpr_ASTNode *node) override; + void ActuralVisit(RLExpr_ASTNode *node) override; + void ActuralVisit(GGLLExpr_ASTNode *node) override; + void ActuralVisit(NEExpr_ASTNode *node) override; + void ActuralVisit(BAndExpr_ASTNode *node) override; + void ActuralVisit(BXorExpr_ASTNode *node) override; + void ActuralVisit(BOrExpr_ASTNode *node) override; + void ActuralVisit(LAndExpr_ASTNode *node) override; + void ActuralVisit(LOrExpr_ASTNode *node) override; + void ActuralVisit(TernaryExpr_ASTNode *node) override; + void ActuralVisit(AssignExpr_ASTNode *node) override; + void ActuralVisit(ThisExpr_ASTNode *node) override; + void ActuralVisit(ParenExpr_ASTNode *node) override; + void ActuralVisit(IDExpr_ASTNode *node) override; + void ActuralVisit(FunctionCallExpr_ASTNode *node) override; + void ActuralVisit(FormattedStringExpr_ASTNode *node) override; + void ActuralVisit(ConstantExpr_ASTNode *node) override; +}; \ No newline at end of file diff --git a/include/tools.h b/include/tools.h index cbc7b9e..4491ae2 100644 --- a/include/tools.h +++ b/include/tools.h @@ -1,6 +1,8 @@ #pragma once #include +#include #include +#include enum class ASTNodeType { // Expression nodes NewArrayExpr, @@ -98,4 +100,38 @@ inline bool operator==(const ExprTypeInfo &l, const ExprTypeInfo &r) { } throw std::runtime_error("something strange happened"); } -inline bool operator!=(const ExprTypeInfo &l, const ExprTypeInfo &r) { return !(l == r); } \ No newline at end of file +inline bool operator!=(const ExprTypeInfo &l, const ExprTypeInfo &r) { return !(l == r); } + +class IRClassInfo { + public: + std::string class_name; // This data must be provided by user + std::vector member_var_size; // This data must be provided by user. Each of them is the size of a member + // variable, which must be in [1,4] + std::unordered_map member_var_offset; // This data must be provided by user + std::vector member_var_pos_after_align; + size_t class_size_after_align; + void ArrangeSpace() { + size_t cur_pos = 0; + size_t align_size = 1; + for (size_t cur_size : member_var_size) { + if (cur_size != 1 && cur_size != 4) throw std::runtime_error("Invalid member variable size"); + if (cur_pos % cur_size == 0) { + member_var_pos_after_align.push_back(cur_pos); + cur_pos += cur_size; + } else { + cur_pos += cur_size - (cur_pos % cur_size); + member_var_pos_after_align.push_back(cur_pos); + cur_pos += cur_size; + } + if (cur_size > align_size) align_size = cur_size; + if (cur_pos % align_size != 0) cur_pos += align_size - (cur_pos % align_size); + class_size_after_align = cur_pos; + } + } +}; +class IRVariableInfo { + public: + enum class VariableType { global_variable, local_variable, member_variable }; + std::string class_name; + std::string variable_name; +}; \ No newline at end of file diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index dbeb12c..9bee807 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,7 +1,8 @@ add_subdirectory(ast) add_subdirectory(semantic) +add_subdirectory(IR) add_executable(zmxcc main.cpp) -target_link_libraries(zmxcc semantic argparse) +target_link_libraries(zmxcc semantic argparse IR) set_target_properties(zmxcc PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}" ) \ No newline at end of file diff --git a/src/IR/CMakeLists.txt b/src/IR/CMakeLists.txt new file mode 100644 index 0000000..33ea9b2 --- /dev/null +++ b/src/IR/CMakeLists.txt @@ -0,0 +1,5 @@ +include_directories(${CMAKE_SOURCE_DIR}/include/IR) +file(GLOB IR_SOURCES "*.cpp") + +add_library(IR STATIC ${IR_SOURCES}) +target_link_libraries(IR PUBLIC ast) \ No newline at end of file diff --git a/src/IR/IRBuilder.cpp b/src/IR/IRBuilder.cpp new file mode 100644 index 0000000..9f37587 --- /dev/null +++ b/src/IR/IRBuilder.cpp @@ -0,0 +1,167 @@ +#include "IRBuilder.h" +#include + +// Structural AST Nodes +void IRBuilder::ActuralVisit(FuncDef_ASTNode *node) { + // TODO: Implement function body +} + +void IRBuilder::ActuralVisit(ClassDef_ASTNode *node) { + // TODO: Implement function body +} + +void IRBuilder::ActuralVisit(Program_ASTNode *node) { + // TODO: Implement function body + throw std::runtime_error("IRBuilder not implemented"); +} + +// Statement AST Nodes +void IRBuilder::ActuralVisit(EmptyStatement_ASTNode *node) { + // TODO: Implement function body +} + +void IRBuilder::ActuralVisit(DefinitionStatement_ASTNode *node) { + // TODO: Implement function body +} + +void IRBuilder::ActuralVisit(ExprStatement_ASTNode *node) { + // TODO: Implement function body +} + +void IRBuilder::ActuralVisit(IfStatement_ASTNode *node) { + // TODO: Implement function body +} + +void IRBuilder::ActuralVisit(WhileStatement_ASTNode *node) { + // TODO: Implement function body +} + +void IRBuilder::ActuralVisit(ForStatement_ASTNode *node) { + // TODO: Implement function body +} + +void IRBuilder::ActuralVisit(JmpStatement_ASTNode *node) { + // TODO: Implement function body +} + +void IRBuilder::ActuralVisit(SuiteStatement_ASTNode *node) { + // TODO: Implement function body +} + +// Expression AST Nodes +void IRBuilder::ActuralVisit(NewArrayExpr_ASTNode *node) { + // TODO: Implement function body +} + +void IRBuilder::ActuralVisit(NewConstructExpr_ASTNode *node) { + // TODO: Implement function body +} + +void IRBuilder::ActuralVisit(NewExpr_ASTNode *node) { + // TODO: Implement function body +} + +void IRBuilder::ActuralVisit(AccessExpr_ASTNode *node) { + // TODO: Implement function body +} + +void IRBuilder::ActuralVisit(IndexExpr_ASTNode *node) { + // TODO: Implement function body +} + +void IRBuilder::ActuralVisit(SuffixExpr_ASTNode *node) { + // TODO: Implement function body +} + +void IRBuilder::ActuralVisit(PrefixExpr_ASTNode *node) { + // TODO: Implement function body +} + +void IRBuilder::ActuralVisit(OppositeExpr_ASTNode *node) { + // TODO: Implement function body +} + +void IRBuilder::ActuralVisit(LNotExpr_ASTNode *node) { + // TODO: Implement function body +} + +void IRBuilder::ActuralVisit(BNotExpr_ASTNode *node) { + // TODO: Implement function body +} + +void IRBuilder::ActuralVisit(MDMExpr_ASTNode *node) { + // TODO: Implement function body +} + +void IRBuilder::ActuralVisit(PMExpr_ASTNode *node) { + // TODO: Implement function body +} + +void IRBuilder::ActuralVisit(RLExpr_ASTNode *node) { + // TODO: Implement function body +} + +void IRBuilder::ActuralVisit(GGLLExpr_ASTNode *node) { + // TODO: Implement function body +} + +void IRBuilder::ActuralVisit(NEExpr_ASTNode *node) { + // TODO: Implement function body +} + +void IRBuilder::ActuralVisit(BAndExpr_ASTNode *node) { + // TODO: Implement function body +} + +void IRBuilder::ActuralVisit(BXorExpr_ASTNode *node) { + // TODO: Implement function body +} + +void IRBuilder::ActuralVisit(BOrExpr_ASTNode *node) { + // TODO: Implement function body +} + +void IRBuilder::ActuralVisit(LAndExpr_ASTNode *node) { + // TODO: Implement function body +} + +void IRBuilder::ActuralVisit(LOrExpr_ASTNode *node) { + // TODO: Implement function body +} + +void IRBuilder::ActuralVisit(TernaryExpr_ASTNode *node) { + // TODO: Implement function body +} + +void IRBuilder::ActuralVisit(AssignExpr_ASTNode *node) { + // TODO: Implement function body +} + +void IRBuilder::ActuralVisit(ThisExpr_ASTNode *node) { + // TODO: Implement function body +} + +void IRBuilder::ActuralVisit(ParenExpr_ASTNode *node) { + // TODO: Implement function body +} + +void IRBuilder::ActuralVisit(IDExpr_ASTNode *node) { + // TODO: Implement function body +} + +void IRBuilder::ActuralVisit(FunctionCallExpr_ASTNode *node) { + // TODO: Implement function body +} + +void IRBuilder::ActuralVisit(FormattedStringExpr_ASTNode *node) { + // TODO: Implement function body +} + +void IRBuilder::ActuralVisit(ConstantExpr_ASTNode *node) { + // TODO: Implement function body +} + +std::shared_ptr BuildIR(std::shared_ptr src) { + IRBuilder visitor; + visitor.visit(src.get()); +} \ No newline at end of file diff --git a/src/IR/build.sh b/src/IR/build.sh new file mode 100755 index 0000000..e02155f --- /dev/null +++ b/src/IR/build.sh @@ -0,0 +1,10 @@ +#!/bin/bash +# Get the directory of the script +SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )" +# Change to the script directory +cd "$SCRIPT_DIR" +clang-18 -S -emit-llvm --target=riscv32-unknown-elf -O2 -fno-builtin-printf -fno-builtin-memcpy \ + builtin.c -o builtin_intermediate.ll +sed 's/_builtin_/.builtin./g;s/string_/string./g;s/array_/array./g' builtin_intermediate.ll > builtin.ll +rm builtin_intermediate.ll +llc-18 -march=riscv32 builtin.ll -o builtin.s -O2 \ No newline at end of file diff --git a/src/IR/builtin.c b/src/IR/builtin.c new file mode 100644 index 0000000..e8490d3 --- /dev/null +++ b/src/IR/builtin.c @@ -0,0 +1,130 @@ +#include +#define bool _Bool +#define EOF (-1) +// libc function +void* malloc(unsigned int size); +void free(void* ptr); +int printf(const char *pattern, ...); +int scanf(const char *format, ...); +int sprintf(char *str, const char *pattern, ...); +int sscanf(const char *str, const char *pattern, ...); +int string_length(char *self) { + int res=0; + while(self[res]!='\0') { + res++; + } + return res; +} +char* string_substring(char *self,int left, int right) { + int len = right - left; + char *res = (char*)malloc(len+1); + for(int i=0;i>8)&0xff; + ((unsigned char*)res)[2] = (dim_size[0]>>16)&0xff; + ((unsigned char*)res)[3] = (dim_size[0]>>24)&0xff; + void* actual_space=((char*)res)+4; + res=actual_space; + } else { + res=malloc(dim_size[0]*sizeof(void*)+4); + ((unsigned char*)res)[0] = dim_size[0]&0xff; + ((unsigned char*)res)[1] = (dim_size[0]>>8)&0xff; + ((unsigned char*)res)[2] = (dim_size[0]>>16)&0xff; + ((unsigned char*)res)[3] = (dim_size[0]>>24)&0xff; + void* actual_space=((char*)res)+4; + for(int i=0;i=0) dims_with_size++; +// } +// if(dims_with_sizeThis Inner Loop Header: Depth=1 + add a2, a0, a1 + lbu a2, 0(a2) + addi a1, a1, 1 + bnez a2, .LBB0_1 +# %bb.2: + addi a0, a1, -1 + ret +.Lfunc_end0: + .size string.length, .Lfunc_end0-string.length + # -- End function + .option pop + .option push + .option arch, +a, +c, +m + .globl string.substring # -- Begin function string.substring + .p2align 1 + .type string.substring,@function +string.substring: # @string.substring +# %bb.0: + addi sp, sp, -16 + sw ra, 12(sp) # 4-byte Folded Spill + sw s0, 8(sp) # 4-byte Folded Spill + sw s1, 4(sp) # 4-byte Folded Spill + sw s2, 0(sp) # 4-byte Folded Spill + mv s0, a1 + mv s2, a0 + sub s1, a2, a1 + addi a0, s1, 1 + call malloc + add a1, a0, s1 + blez s1, .LBB1_3 +# %bb.1: # %.preheader + add s0, s0, s2 + mv a2, a0 +.LBB1_2: # =>This Inner Loop Header: Depth=1 + lbu a3, 0(s0) + sb a3, 0(a2) + addi a2, a2, 1 + addi s0, s0, 1 + bne a2, a1, .LBB1_2 +.LBB1_3: + sb zero, 0(a1) + lw ra, 12(sp) # 4-byte Folded Reload + lw s0, 8(sp) # 4-byte Folded Reload + lw s1, 4(sp) # 4-byte Folded Reload + lw s2, 0(sp) # 4-byte Folded Reload + addi sp, sp, 16 + ret +.Lfunc_end1: + .size string.substring, .Lfunc_end1-string.substring + # -- End function + .option pop + .option push + .option arch, +a, +c, +m + .globl string.parseInt # -- Begin function string.parseInt + .p2align 1 + .type string.parseInt,@function +string.parseInt: # @string.parseInt +# %bb.0: + addi sp, sp, -16 + sw ra, 12(sp) # 4-byte Folded Spill + lui a1, %hi(.L.str) + addi a1, a1, %lo(.L.str) + addi a2, sp, 8 + call sscanf + lw a0, 8(sp) + lw ra, 12(sp) # 4-byte Folded Reload + addi sp, sp, 16 + ret +.Lfunc_end2: + .size string.parseInt, .Lfunc_end2-string.parseInt + # -- End function + .option pop + .option push + .option arch, +a, +c, +m + .globl string.ord # -- Begin function string.ord + .p2align 1 + .type string.ord,@function +string.ord: # @string.ord +# %bb.0: + add a0, a0, a1 + lbu a0, 0(a0) + ret +.Lfunc_end3: + .size string.ord, .Lfunc_end3-string.ord + # -- End function + .option pop + .option push + .option arch, +a, +c, +m + .globl print # -- Begin function print + .p2align 1 + .type print,@function +print: # @print +# %bb.0: + lui a1, %hi(.L.str.1) + addi a1, a1, %lo(.L.str.1) + mv a2, a0 + mv a0, a1 + mv a1, a2 + tail printf +.Lfunc_end4: + .size print, .Lfunc_end4-print + # -- End function + .option pop + .option push + .option arch, +a, +c, +m + .globl println # -- Begin function println + .p2align 1 + .type println,@function +println: # @println +# %bb.0: + lui a1, %hi(.L.str.2) + addi a1, a1, %lo(.L.str.2) + mv a2, a0 + mv a0, a1 + mv a1, a2 + tail printf +.Lfunc_end5: + .size println, .Lfunc_end5-println + # -- End function + .option pop + .option push + .option arch, +a, +c, +m + .globl printInt # -- Begin function printInt + .p2align 1 + .type printInt,@function +printInt: # @printInt +# %bb.0: + lui a1, %hi(.L.str) + addi a1, a1, %lo(.L.str) + mv a2, a0 + mv a0, a1 + mv a1, a2 + tail printf +.Lfunc_end6: + .size printInt, .Lfunc_end6-printInt + # -- End function + .option pop + .option push + .option arch, +a, +c, +m + .globl printlnInt # -- Begin function printlnInt + .p2align 1 + .type printlnInt,@function +printlnInt: # @printlnInt +# %bb.0: + lui a1, %hi(.L.str.3) + addi a1, a1, %lo(.L.str.3) + mv a2, a0 + mv a0, a1 + mv a1, a2 + tail printf +.Lfunc_end7: + .size printlnInt, .Lfunc_end7-printlnInt + # -- End function + .option pop + .option push + .option arch, +a, +c, +m + .globl toString # -- Begin function toString + .p2align 1 + .type toString,@function +toString: # @toString +# %bb.0: + addi sp, sp, -16 + sw ra, 12(sp) # 4-byte Folded Spill + sw s0, 8(sp) # 4-byte Folded Spill + sw s1, 4(sp) # 4-byte Folded Spill + mv s0, a0 + li a0, 15 + call malloc + mv s1, a0 + lui a0, %hi(.L.str) + addi a1, a0, %lo(.L.str) + mv a0, s1 + mv a2, s0 + call sprintf + mv a0, s1 + lw ra, 12(sp) # 4-byte Folded Reload + lw s0, 8(sp) # 4-byte Folded Reload + lw s1, 4(sp) # 4-byte Folded Reload + addi sp, sp, 16 + ret +.Lfunc_end8: + .size toString, .Lfunc_end8-toString + # -- End function + .option pop + .option push + .option arch, +a, +c, +m + .globl getString # -- Begin function getString + .p2align 1 + .type getString,@function +getString: # @getString +# %bb.0: + addi sp, sp, -48 + sw ra, 44(sp) # 4-byte Folded Spill + sw s0, 40(sp) # 4-byte Folded Spill + sw s1, 36(sp) # 4-byte Folded Spill + sw s2, 32(sp) # 4-byte Folded Spill + sw s3, 28(sp) # 4-byte Folded Spill + sw s4, 24(sp) # 4-byte Folded Spill + sw s5, 20(sp) # 4-byte Folded Spill + sw s6, 16(sp) # 4-byte Folded Spill + sw s7, 12(sp) # 4-byte Folded Spill + sw s8, 8(sp) # 4-byte Folded Spill + li a0, 11 + call malloc + mv s8, a0 + lui a0, %hi(.L.str.4) + addi s2, a0, %lo(.L.str.4) + addi a1, sp, 7 + mv a0, s2 + call scanf + li s3, 1 + bne a0, s3, .LBB9_11 +# %bb.1: # %.preheader1 + li s1, 0 + li s4, 10 + li s5, 13 + mv s6, s8 + li s7, 10 + j .LBB9_4 +.LBB9_2: # in Loop: Header=BB9_4 Depth=1 + mv s8, s6 +.LBB9_3: # in Loop: Header=BB9_4 Depth=1 + addi s0, s1, 1 + add s1, s1, s8 + sb a0, 0(s1) + addi a1, sp, 7 + mv a0, s2 + call scanf + mv s1, s0 + bne a0, s3, .LBB9_13 +.LBB9_4: # =>This Loop Header: Depth=1 + # Child Loop BB9_9 Depth 2 + lbu a0, 7(sp) + beq a0, s4, .LBB9_12 +# %bb.5: # in Loop: Header=BB9_4 Depth=1 + beq a0, s5, .LBB9_12 +# %bb.6: # in Loop: Header=BB9_4 Depth=1 + bne s1, s7, .LBB9_2 +# %bb.7: # in Loop: Header=BB9_4 Depth=1 + slli s7, s1, 1 + addi a0, s7, 1 + call malloc + mv s8, a0 + beqz s1, .LBB9_10 +# %bb.8: # %.preheader + # in Loop: Header=BB9_4 Depth=1 + add a0, s8, s1 + mv a1, s6 + mv a2, s8 +.LBB9_9: # Parent Loop BB9_4 Depth=1 + # => This Inner Loop Header: Depth=2 + lbu a3, 0(a1) + sb a3, 0(a2) + addi a2, a2, 1 + addi a1, a1, 1 + bne a2, a0, .LBB9_9 +.LBB9_10: # in Loop: Header=BB9_4 Depth=1 + mv a0, s6 + call free + lbu a0, 7(sp) + mv s6, s8 + j .LBB9_3 +.LBB9_11: + li s0, 0 + j .LBB9_13 +.LBB9_12: + mv s0, s1 + mv s8, s6 +.LBB9_13: + add s0, s0, s8 + sb zero, 0(s0) + mv a0, s8 + lw ra, 44(sp) # 4-byte Folded Reload + lw s0, 40(sp) # 4-byte Folded Reload + lw s1, 36(sp) # 4-byte Folded Reload + lw s2, 32(sp) # 4-byte Folded Reload + lw s3, 28(sp) # 4-byte Folded Reload + lw s4, 24(sp) # 4-byte Folded Reload + lw s5, 20(sp) # 4-byte Folded Reload + lw s6, 16(sp) # 4-byte Folded Reload + lw s7, 12(sp) # 4-byte Folded Reload + lw s8, 8(sp) # 4-byte Folded Reload + addi sp, sp, 48 + ret +.Lfunc_end9: + .size getString, .Lfunc_end9-getString + # -- End function + .option pop + .option push + .option arch, +a, +c, +m + .globl getInt # -- Begin function getInt + .p2align 1 + .type getInt,@function +getInt: # @getInt +# %bb.0: + addi sp, sp, -16 + sw ra, 12(sp) # 4-byte Folded Spill + lui a0, %hi(.L.str) + addi a0, a0, %lo(.L.str) + addi a1, sp, 8 + call scanf + lw a0, 8(sp) + lw ra, 12(sp) # 4-byte Folded Reload + addi sp, sp, 16 + ret +.Lfunc_end10: + .size getInt, .Lfunc_end10-getInt + # -- End function + .option pop + .option push + .option arch, +a, +c, +m + .globl .builtin.AllocateClassBody # -- Begin function .builtin.AllocateClassBody + .p2align 1 + .type .builtin.AllocateClassBody,@function +.builtin.AllocateClassBody: # @.builtin.AllocateClassBody +# %bb.0: + tail malloc +.Lfunc_end11: + .size .builtin.AllocateClassBody, .Lfunc_end11-.builtin.AllocateClassBody + # -- End function + .option pop + .option push + .option arch, +a, +c, +m + .globl .builtin.GetArrayLength # -- Begin function .builtin.GetArrayLength + .p2align 1 + .type .builtin.GetArrayLength,@function +.builtin.GetArrayLength: # @.builtin.GetArrayLength +# %bb.0: + lbu a1, -3(a0) + lbu a2, -4(a0) + lbu a3, -2(a0) + lbu a0, -1(a0) + slli a1, a1, 8 + or a1, a1, a2 + slli a3, a3, 16 + slli a0, a0, 24 + or a0, a0, a3 + or a0, a0, a1 + ret +.Lfunc_end12: + .size .builtin.GetArrayLength, .Lfunc_end12-.builtin.GetArrayLength + # -- End function + .option pop + .option push + .option arch, +a, +c, +m + .globl .builtin.RecursiveAllocateArray # -- Begin function .builtin.RecursiveAllocateArray + .p2align 1 + .type .builtin.RecursiveAllocateArray,@function +.builtin.RecursiveAllocateArray: # @.builtin.RecursiveAllocateArray +# %bb.0: + addi sp, sp, -48 + sw ra, 44(sp) # 4-byte Folded Spill + sw s0, 40(sp) # 4-byte Folded Spill + sw s1, 36(sp) # 4-byte Folded Spill + sw s2, 32(sp) # 4-byte Folded Spill + sw s3, 28(sp) # 4-byte Folded Spill + sw s4, 24(sp) # 4-byte Folded Spill + sw s5, 20(sp) # 4-byte Folded Spill + sw s6, 16(sp) # 4-byte Folded Spill + sw s7, 12(sp) # 4-byte Folded Spill + lw s0, 0(a2) + mv s3, a1 + mv s2, a0 + srli s5, s0, 8 + srli s4, s0, 16 + li a0, 1 + srli s6, s0, 24 + bne s2, a0, .LBB13_2 +# %bb.1: + mul a0, s0, s3 + addi a0, a0, 4 + call malloc + sb s0, 0(a0) + sb s5, 1(a0) + sb s4, 2(a0) + sb s6, 3(a0) + addi a0, a0, 4 + j .LBB13_6 +.LBB13_2: + mv s7, a2 + slli a0, s0, 2 + addi a0, a0, 4 + call malloc + sb s0, 0(a0) + sb s5, 1(a0) + sb s4, 2(a0) + sb s6, 3(a0) + addi a0, a0, 4 + blez s0, .LBB13_6 +# %bb.3: + li s1, 0 + addi s2, s2, -1 + addi s5, s7, 4 + mv s4, a0 + mv s0, a0 +.LBB13_4: # =>This Inner Loop Header: Depth=1 + mv a0, s2 + mv a1, s3 + mv a2, s5 + call .builtin.RecursiveAllocateArray + lw a1, 0(s7) + sw a0, 0(s0) + addi s1, s1, 1 + addi s0, s0, 4 + blt s1, a1, .LBB13_4 +# %bb.5: + mv a0, s4 +.LBB13_6: + lw ra, 44(sp) # 4-byte Folded Reload + lw s0, 40(sp) # 4-byte Folded Reload + lw s1, 36(sp) # 4-byte Folded Reload + lw s2, 32(sp) # 4-byte Folded Reload + lw s3, 28(sp) # 4-byte Folded Reload + lw s4, 24(sp) # 4-byte Folded Reload + lw s5, 20(sp) # 4-byte Folded Reload + lw s6, 16(sp) # 4-byte Folded Reload + lw s7, 12(sp) # 4-byte Folded Reload + addi sp, sp, 48 + ret +.Lfunc_end13: + .size .builtin.RecursiveAllocateArray, .Lfunc_end13-.builtin.RecursiveAllocateArray + # -- End function + .option pop + .type .L.str,@object # @.str + .section .rodata.str1.1,"aMS",@progbits,1 +.L.str: + .asciz "%d" + .size .L.str, 3 + + .type .L.str.1,@object # @.str.1 +.L.str.1: + .asciz "%s" + .size .L.str.1, 3 + + .type .L.str.2,@object # @.str.2 +.L.str.2: + .asciz "%s\n" + .size .L.str.2, 4 + + .type .L.str.3,@object # @.str.3 +.L.str.3: + .asciz "%d\n" + .size .L.str.3, 4 + + .type .L.str.4,@object # @.str.4 +.L.str.4: + .asciz "%c" + .size .L.str.4, 3 + + .ident "Ubuntu clang version 18.1.8 (++20240731024944+3b5b5c1ec4a3-1~exp1~20240731145000.144)" + .section ".note.GNU-stack","",@progbits diff --git a/src/ast/semanticvisitor.cpp b/src/ast/semanticvisitor.cpp index eb255f3..53b2e0b 100644 --- a/src/ast/semanticvisitor.cpp +++ b/src/ast/semanticvisitor.cpp @@ -1,6 +1,6 @@ #include #include -#include "astnode_visitor.h" +#include "semantic_visitor.h" #include "scope.hpp" #include "tools.h" @@ -444,6 +444,7 @@ void ASTSemanticCheckVisitor::ActuralVisit(AssignExpr_ASTNode *node) { if (node->dest->expr_type_info != node->src->expr_type_info) { throw SemanticError("Type Mismatch", 1); } + node->expr_type_info = node->src->expr_type_info; } void ASTSemanticCheckVisitor::ActuralVisit(ThisExpr_ASTNode *node) { diff --git a/src/main.cpp b/src/main.cpp index 0694b8b..4cd13d6 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,6 +1,7 @@ #include #include #include +#include "IR/IR.h" #include "semantic/semantic.h" int main(int argc, char **argv) { @@ -24,6 +25,7 @@ int main(int argc, char **argv) { std::shared_ptr ast; try { SemanticCheck(fin, ast); + auto IR = BuildIR(ast); } catch (const SemanticError &err) { std::cout << err.what() << std::endl; return err.GetErrorCode();