├── CMakeLists.txt ├── src ├── ast │ ├── ast.cpp │ ├── ast.h │ ├── get_ast_classes.py │ ├── ast_base.cpp │ ├── ast_base.h │ ├── ast_classes.txt │ ├── ast_value.h │ ├── ast_value.cpp │ ├── ast_expr.h │ ├── ast_expr.cpp │ ├── ast_type.cpp │ ├── ast_type.h │ ├── ast_stmt.cpp │ ├── ast_stmt.h │ ├── ast_prog.h │ └── ast_prog.cpp ├── generator │ ├── generator_base.cpp │ ├── generator.cpp │ ├── generator_result.hpp │ ├── gen_sys_func.cpp │ ├── generator_value.cpp │ ├── generator.h │ └── generator_program.cpp ├── CMakeLists.txt ├── type │ ├── type.h │ └── type.cpp ├── main.cpp ├── visitor.h ├── vis │ └── graph_generator.h └── lexer │ └── pascal.l ├── test ├── test.png ├── error.pas ├── cell.pas ├── ten.pas ├── func.pas ├── nested_record.pas ├── myten.pas ├── hanoi.pas ├── p.pas ├── bubble.pas ├── nested_record.pas.ll ├── func.pas.ll ├── cell.pas.ll ├── p.pas.ll ├── cell.pas.dot ├── myten.s ├── nested_record.pas.dot ├── hanoi.s ├── error.pas.dot ├── hanoi.pas.ll ├── ten.pas.ll ├── myten.pas.ll ├── p.pas.dot ├── func.pas.dot ├── bubble.pas.dot └── bubble.pas.ll ├── Our_Pascal_Compiler_Report.pdf ├── line_count.sh ├── .gitignore ├── README.md ├── LICENSE └── playground.txt /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | project(opc) 2 | add_subdirectory(src) -------------------------------------------------------------------------------- /src/ast/ast.cpp: -------------------------------------------------------------------------------- 1 | #include "ast.h" 2 | 3 | ASTNode *ast_root; -------------------------------------------------------------------------------- /test/test.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangyangyi/Our-Pascal-Compiler/HEAD/test/test.png -------------------------------------------------------------------------------- /Our_Pascal_Compiler_Report.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huangyangyi/Our-Pascal-Compiler/HEAD/Our_Pascal_Compiler_Report.pdf -------------------------------------------------------------------------------- /src/ast/ast.h: -------------------------------------------------------------------------------- 1 | #ifndef AST_H 2 | #define AST_H 3 | 4 | #include "ast_base.h" 5 | #include "ast_expr.h" 6 | #include "ast_stmt.h" 7 | #include "ast_prog.h" 8 | #include "ast_type.h" 9 | #include "ast_value.h" 10 | 11 | extern ASTNode *ast_root; 12 | 13 | #endif //AST_H -------------------------------------------------------------------------------- /test/error.pas: -------------------------------------------------------------------------------- 1 | program error; 2 | type t = record 3 | x: real; 4 | y: integer; 5 | end; 6 | var 7 | a,b: real; 8 | c: wrongtype; 9 | d: integer; 10 | e: t; 11 | begin 12 | read(a, b); 13 | d := a + b; 14 | writeln(d); 15 | d := e.x; 16 | d := e.z; 17 | end. -------------------------------------------------------------------------------- /test/cell.pas: -------------------------------------------------------------------------------- 1 | program v233; 2 | var 3 | a,b:array[1..10000] of integer; 4 | m1,m2,n,i,p,t,s:integer; 5 | f:boolean; 6 | begin 7 | t := 0; 8 | for t:= 1 to 150 do 9 | begin 10 | s:=s+1; 11 | end; 12 | writeln(t, s); 13 | end. 14 | 15 | 16 | -------------------------------------------------------------------------------- /src/generator/generator_base.cpp: -------------------------------------------------------------------------------- 1 | #include "generator.h" 2 | #include "generator_result.hpp" 3 | 4 | 5 | std::shared_ptr Generator::VisitASTNode(ASTNode *node) { 6 | return nullptr; 7 | } 8 | 9 | std::shared_ptr Generator::VisitASTNameList(ASTNameList *node) { 10 | return std::make_shared(node->GetIdentifierList()); 11 | } -------------------------------------------------------------------------------- /test/ten.pas: -------------------------------------------------------------------------------- 1 | PROGRAM ten; 2 | VAR 3 | a,s,max,min,avg:real; 4 | i:integer; 5 | BEGIN 6 | write('please input:'); 7 | read(a); 8 | s:=a; 9 | max:=a; 10 | min:=a; 11 | FOR i:=2 TO 10 DO 12 | BEGIN 13 | read(a); 14 | s:=s+a; 15 | IF a>max THEN 16 | max:=a 17 | ELSE 18 | IF a= 6.0 21 | + Please use **cmake** to build this project. 22 | 23 | ## Usage 24 | 25 | + `./opc .pas `: Generate IR code from `.pas` to `.pas.ll`. 26 | + `lli `: Generate an executable file from IR code ``. 27 | 28 | ## Report 29 | 30 | [Click here](https://github.com/huangyangyi/Our-Pascal-Compiler/blob/master/Our_Pascal_Compiler_Report.pdf) -------------------------------------------------------------------------------- /src/ast/ast_base.cpp: -------------------------------------------------------------------------------- 1 | #include "ast_base.h" 2 | #include "../visitor.h" 3 | 4 | #include 5 | 6 | int ASTNode::line() { return this->line_; } 7 | 8 | int ASTNode::col() { return this->col_; } 9 | 10 | std::string ASTNode::get_location() { 11 | return "line " + string(to_string(this->line())) + 12 | " , col " + string(to_string(this->col())) + " : "; 13 | } 14 | 15 | std::pair ASTNode::get_location_pairs(){ 16 | return std::make_pair(this->line(), this->col()); 17 | } 18 | 19 | void ASTNode::set_location(int line, int col) { 20 | this->line_ = line; 21 | this->col_ = col; 22 | } 23 | 24 | std::shared_ptr ASTNode::Accept(Visitor *visitor) { return visitor->VisitASTNode(this); } 25 | 26 | void ASTNameList::AddIdentifier(std::string id) { 27 | this->identifier_list_.push_back(id); 28 | } 29 | 30 | std::shared_ptr ASTNameList::Accept(Visitor *visitor) { return visitor->VisitASTNameList(this); } 31 | 32 | const std::vector &ASTNameList::GetIdentifierList() { return this->identifier_list_; } -------------------------------------------------------------------------------- /src/ast/ast_base.h: -------------------------------------------------------------------------------- 1 | #ifndef OPC_AST_AST_BASE_H 2 | #define OPC_AST_AST_BASE_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | 10 | class VisitorResult; 11 | 12 | class Visitor; 13 | 14 | class ASTNode; 15 | 16 | class ASTNode; 17 | 18 | class ASTNameList; 19 | 20 | class ASTNode { 21 | private: 22 | int line_, col_; 23 | 24 | public: 25 | ASTNode() = default; 26 | 27 | void set_location(int line, int col); 28 | 29 | int line(); 30 | 31 | int col(); 32 | 33 | std::string get_location(); 34 | std::pair get_location_pairs(); 35 | 36 | virtual std::shared_ptr Accept(Visitor *visitor); 37 | }; 38 | 39 | class ASTNameList : public ASTNode { 40 | public: 41 | ASTNameList() = default; 42 | 43 | void AddIdentifier(std::string); 44 | 45 | virtual std::shared_ptr Accept(Visitor *visitor); 46 | 47 | const std::vector &GetIdentifierList(); 48 | 49 | private: 50 | std::vector identifier_list_; 51 | }; 52 | 53 | #endif //OPC_AST_AST_BASE_H -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Yangyi Huang 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /test/nested_record.pas.ll: -------------------------------------------------------------------------------- 1 | ; ModuleID = 'pascal_module' 2 | source_filename = "pascal_module" 3 | 4 | @a = common global { i32, i32, { i32, i32 }, { i32, i32 }, { i32, i32 } } zeroinitializer 5 | @scanf_format = private unnamed_addr constant [5 x i8] c"%d%d\00" 6 | 7 | define i32 @main() { 8 | entry: 9 | %0 = load { i32, i32, { i32, i32 }, { i32, i32 }, { i32, i32 } }, { i32, i32, { i32, i32 }, { i32, i32 }, { i32, i32 } }* @a 10 | %1 = load i32, i32* getelementptr inbounds ({ i32, i32, { i32, i32 }, { i32, i32 }, { i32, i32 } }, { i32, i32, { i32, i32 }, { i32, i32 }, { i32, i32 } }* @a, i32 0, i32 0) 11 | %2 = load { i32, i32, { i32, i32 }, { i32, i32 }, { i32, i32 } }, { i32, i32, { i32, i32 }, { i32, i32 }, { i32, i32 } }* @a 12 | %3 = load i32, i32* getelementptr inbounds ({ i32, i32, { i32, i32 }, { i32, i32 }, { i32, i32 } }, { i32, i32, { i32, i32 }, { i32, i32 }, { i32, i32 } }* @a, i32 0, i32 1) 13 | %call_scanf = call i32 (i8*, ...) @scanf(i8* getelementptr inbounds ([5 x i8], [5 x i8]* @scanf_format, i32 0, i32 0), i32* getelementptr inbounds ({ i32, i32, { i32, i32 }, { i32, i32 }, { i32, i32 } }, { i32, i32, { i32, i32 }, { i32, i32 }, { i32, i32 } }* @a, i32 0, i32 0), i32* getelementptr inbounds ({ i32, i32, { i32, i32 }, { i32, i32 }, { i32, i32 } }, { i32, i32, { i32, i32 }, { i32, i32 }, { i32, i32 } }* @a, i32 0, i32 1)) 14 | ret i32 0 15 | } 16 | 17 | declare i32 @scanf(i8*, ...) 18 | -------------------------------------------------------------------------------- /src/ast/ast_classes.txt: -------------------------------------------------------------------------------- 1 | class ASTNode 2 | class ASTNameList 3 | class ASTExpr 4 | class ASTExpressionList 5 | class ASTBinaryExpr 6 | class ASTUnaryExpr 7 | class ASTPropExpr 8 | class ASTConstValueExpr 9 | class ASTFuncCall 10 | class ASTIDExpr 11 | class ASTArrayExpr 12 | class ASTProgramHead 13 | class ASTRoutineHead 14 | class ASTRoutineBody 15 | class ASTRoutine 16 | class ASTProgram 17 | class ASTRoutinePart 18 | class ASTFuncProcBase 19 | class ASTFunctionDecl 20 | class ASTFunctionHead 21 | class ASTProcedureDecl 22 | class ASTProcedureHead 23 | class ASTParameters 24 | class ASTParaDeclList 25 | class ASTParaTypeList 26 | class ASTParaList 27 | class ASTVarParaList 28 | class ASTValParaList 29 | class ASTNonLabelStmt 30 | class ASTStmt 31 | class ASTStmtList 32 | class ASTAssignStmt 33 | class ASTProcStmt 34 | class ASTIfStmt 35 | class ASTElseClause 36 | class ASTRepeatStmt 37 | class ASTWhileStmt 38 | class ASTForStmt 39 | class ASTCaseStmt 40 | class ASTCaseExprList 41 | class ASTCaseExpr 42 | class ASTGotoStmt 43 | class ASTType 44 | class ASTTypeDecl 45 | class ASTSimpleTypeDecl 46 | class ASTArrayTypeDecl 47 | class ASTFieldDecl 48 | class ASTFieldDeclList 49 | class ASTRecordTypeDecl 50 | class ASTTypeDefinition 51 | class ASTTypeDeclList 52 | class ASTTypePart 53 | class ASTConstValue 54 | class ASTConstExprList 55 | class ASTConstExpr 56 | class ASTConstPart 57 | class ASTVarPart 58 | class ASTVarDeclList 59 | class ASTVarDecl 60 | -------------------------------------------------------------------------------- /src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.10) 2 | project(opc) 3 | 4 | find_package(LLVM REQUIRED CONFIG) 5 | include_directories(.) 6 | include_directories(${CMAKE_CURRENT_BINARY_DIR}) 7 | 8 | # For jsb: specific the address 9 | include_directories(/usr/include/llvm-6.0) 10 | include_directories(/usr/include/llvm-c-6.0) 11 | 12 | execute_process(COMMAND llvm-config --libs OUTPUT_VARIABLE LLVM_LINK_LIBRARIES) 13 | string(STRIP "${LLVM_LINK_LIBRARIES}" LLVM_LINK_LIBRARIES) 14 | 15 | if(APPLE) 16 | include_directories(/usr/local/opt/llvm/include) 17 | string(APPEND CMAKE_CXX_FLAGS " -Wno-c++11-narrowing") 18 | ENDIF(APPLE) 19 | 20 | 21 | set(CMAKE_CXX_STANDARD 14) 22 | 23 | aux_source_directory(ast AST_SOURCE) 24 | aux_source_directory(generator GEN_SOURCE) 25 | aux_source_directory(vis VIS_SOURCE) 26 | 27 | add_custom_command( 28 | OUTPUT pascal.l.cpp 29 | COMMAND lex -o pascal.l.cpp ${CMAKE_CURRENT_LIST_DIR}/lexer/pascal.l 30 | DEPENDS ${CMAKE_CURRENT_LIST_DIR}/lexer/pascal.l pascal.y.cpp 31 | ) 32 | 33 | add_custom_command( 34 | OUTPUT pascal.y.hpp pascal.y.cpp 35 | COMMAND yacc -d -o pascal.y.cpp ${CMAKE_CURRENT_LIST_DIR}/parser/pascal.y 36 | DEPENDS ${CMAKE_CURRENT_LIST_DIR}/parser/pascal.y 37 | ) 38 | 39 | # For jsb: "cannot find -lz", so must quote it 40 | # llvm_map_components_to_libnames(LLVM_LINK_LIBRARIES core) 41 | 42 | add_executable( 43 | opc 44 | main.cpp ${AST_SOURCE} ${GEN_SOURCE} ${VIS_SOURCE} pascal.l.cpp 45 | pascal.y.cpp pascal.y.hpp 46 | type/type.cpp) 47 | 48 | set_target_properties(opc PROPERTIES LINK_LIBRARIES "${LLVM_LINK_LIBRARIES}") 49 | -------------------------------------------------------------------------------- /test/func.pas.ll: -------------------------------------------------------------------------------- 1 | ; ModuleID = 'pascal_module' 2 | source_filename = "pascal_module" 3 | 4 | @a = common global i32 0 5 | @b = common global i32 0 6 | @printf_format = private unnamed_addr constant [8 x i8] c"%d%c%d\0A\00" 7 | @printf_format.1 = private unnamed_addr constant [8 x i8] c"%d%c%d\0A\00" 8 | @printf_format.2 = private unnamed_addr constant [8 x i8] c"%d%c%d\0A\00" 9 | @printf_format.3 = private unnamed_addr constant [8 x i8] c"%d%c%d\0A\00" 10 | 11 | define i32 @main() { 12 | entry: 13 | %0 = load i32, i32* @a 14 | store i32 3, i32* @a 15 | %1 = load i32, i32* @b 16 | store i32 4, i32* @b 17 | %2 = load i32, i32* @a 18 | %3 = load i32, i32* @b 19 | %call_printf = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([8 x i8], [8 x i8]* @printf_format.2, i32 0, i32 0), i32 %2, i8 32, i32 %3) 20 | %4 = load i32, i32* @a 21 | %5 = load i32, i32* @b 22 | call void @f(i32* @a, i32* @b) 23 | %6 = load i32, i32* @a 24 | %7 = load i32, i32* @b 25 | %call_printf1 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([8 x i8], [8 x i8]* @printf_format.3, i32 0, i32 0), i32 %6, i8 32, i32 %7) 26 | ret i32 0 27 | } 28 | 29 | define void @f(i32*, i32*) { 30 | entry: 31 | %2 = load i32, i32* %0 32 | %a = alloca i32 33 | store i32 %2, i32* %a 34 | %3 = load i32, i32* %a 35 | %4 = load i32, i32* %1 36 | %call_printf = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([8 x i8], [8 x i8]* @printf_format, i32 0, i32 0), i32 %3, i8 32, i32 %4) 37 | call void @g(i32* %a, i32* %1) 38 | %5 = load i32, i32* %1 39 | store i32 5, i32* %1 40 | %6 = load i32, i32* %a 41 | %7 = load i32, i32* %1 42 | %call_printf1 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([8 x i8], [8 x i8]* @printf_format.1, i32 0, i32 0), i32 %6, i8 32, i32 %7) 43 | ret void 44 | } 45 | 46 | define void @g(i32*, i32*) { 47 | entry: 48 | %2 = load i32, i32* %0 49 | store i32 2, i32* %0 50 | ret void 51 | } 52 | 53 | declare i32 @printf(i8*, ...) 54 | -------------------------------------------------------------------------------- /test/cell.pas.ll: -------------------------------------------------------------------------------- 1 | ; ModuleID = 'pascal_module' 2 | source_filename = "pascal_module" 3 | 4 | @a = common global [10000 x i32] zeroinitializer 5 | @b = common global [10000 x i32] zeroinitializer 6 | @m1 = common global i32 0 7 | @m2 = common global i32 0 8 | @n = common global i32 0 9 | @i = common global i32 0 10 | @p = common global i32 0 11 | @t = common global i32 0 12 | @s = common global i32 0 13 | @f = common global i1 false 14 | @printf_format = private unnamed_addr constant [6 x i8] c"%d%d\0A\00" 15 | 16 | define i32 @main() { 17 | entry: 18 | %0 = load i32, i32* @t 19 | store i32 0, i32* @t 20 | br label %for_start 21 | 22 | for_start: ; preds = %entry 23 | %1 = load i32, i32* @t 24 | store i32 1, i32* @t 25 | %2 = load i32, i32* @t 26 | %cmptmp = icmp sgt i32 %2, 150 27 | br i1 %cmptmp, label %for_end, label %for_body 28 | 29 | for_body: ; preds = %for_cond, %for_start 30 | %3 = load i32, i32* @s 31 | %4 = load i32, i32* @s 32 | %addtmp = add i32 %4, 1 33 | store i32 %addtmp, i32* @s 34 | br label %for_cond 35 | 36 | for_cond: ; preds = %for_body 37 | %5 = load i32, i32* @t 38 | %6 = load i32, i32* @t 39 | %addtmp1 = add i32 %6, 1 40 | store i32 %addtmp1, i32* @t 41 | %7 = load i32, i32* @t 42 | %cmptmp2 = icmp sgt i32 %7, 150 43 | br i1 %cmptmp2, label %for_step_back, label %for_body 44 | 45 | for_step_back: ; preds = %for_cond 46 | %8 = load i32, i32* @t 47 | %9 = load i32, i32* @t 48 | %subtmp = sub i32 %9, 1 49 | store i32 %subtmp, i32* @t 50 | br label %for_end 51 | 52 | for_end: ; preds = %for_step_back, %for_start 53 | %10 = load i32, i32* @t 54 | %11 = load i32, i32* @s 55 | %call_printf = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([6 x i8], [6 x i8]* @printf_format, i32 0, i32 0), i32 %10, i32 %11) 56 | ret i32 0 57 | } 58 | 59 | declare i32 @printf(i8*, ...) 60 | -------------------------------------------------------------------------------- /playground.txt: -------------------------------------------------------------------------------- 1 | Hello everyone! 2 | 3 | 创建本地变量: ai = IR.CreateAlloca(llvm_type, nullptr, name) AllocInst* (Value*) 4 | 创建全局变量: new llvm::GlobalVariable(llvm_module, llvm_type, false, llvm::GlobalValue::InternalLinkage, 5 | llvm::ConstantAggregateZero::get(llvm_type), id 6 | 获取name的值: IR.CreateLoad(ai, name) - 本地变量 7 | IR.CreateLoad(llvm::GlobalVariable) LoadInst* (Value*) 8 | 9 | Type* -> PointerType* : AllocInst* (CreateAlloca 的结果) 10 | 11 | Type* -> Int32Type* : 传入 CreateLoad的结果 12 | 13 | 声明函数:CreateFunc() 14 | std::vector args_type; 15 | llvm::FunctionType *func_type = llvm::FunctionType::get(get_llvm_type(ret_type), args_type, false); 16 | llvm::Function *func = llvm::Function::Create(func_type, llvm::Function::ExternalLinkage, sign.id, &llvm_module); 17 | 18 | 调用函数:CreateCall(....) 19 | 20 | struct func_sign { 21 | std::string id; 22 | std::vector param_type_vec; 23 | }; 24 | 25 | const std::vector &args_vec 26 | = get_converted_llvm_args(sign.param_type_vec, args); 27 | const sem_type &ret_type = sem::get_ret_type(sign); 28 | if (ret_type == built_in_type::VOID_TYPE) { 29 | return ir_builder.CreateCall(func, args_vec); 30 | } else { 31 | return ir_builder.CreateCall(func, args_vec, "call_" + sign.id); 32 | } 33 | 34 | 35 | AllocInst* : CreateAlloca的结果 36 | 37 | std::vector> layers; (是不是很像我们的CodeBlock::named_values) 38 | Value* 存的就是AllocInst* 39 | 40 | llvm::Value *gen_id_context::get_mem(const std::string &id) const { 41 | for (auto it = layers.rbegin(); it != layers.rend(); it++) { 42 | if ((*it).find(id) != (*it).end()) { 43 | return (*it).at(id); 44 | // == return (*it)[id]; 45 | } 46 | } 47 | throw std::invalid_argument("[gen_id_context::get_llvm_mem] Unknown identifier"); 48 | } 49 | 50 | AllocInst* 本地变量的指针 => 存着这个本地变量指针的一个寄存器 51 | CreateCall 把 AllocInst* 扔进去的时候,会给他安排一个新的寄存器来存放这个指针值 52 | 如果在别的RunningBlock里面访问之前的AllocInst*,你会得到一个寄存器,但现在这个寄存器里放着别的东西 53 | 54 | 所以如果所有的AllocInst* 是用传参一路传下去的,就可以用 55 | -------------------------------------------------------------------------------- /test/p.pas.ll: -------------------------------------------------------------------------------- 1 | ; ModuleID = 'pascal_module' 2 | source_filename = "pascal_module" 3 | 4 | @tcase = common global i32 0 5 | @a = common global i32 0 6 | @b = common global i32 0 7 | @scanf_format = private unnamed_addr constant [3 x i8] c"%d\00" 8 | @scanf_format.1 = private unnamed_addr constant [5 x i8] c"%d%d\00" 9 | @printf_format = private unnamed_addr constant [4 x i8] c"%d\0A\00" 10 | 11 | define i32 @main() { 12 | entry: 13 | %0 = load i32, i32* @tcase 14 | %call_scanf = call i32 (i8*, ...) @scanf(i8* getelementptr inbounds ([3 x i8], [3 x i8]* @scanf_format, i32 0, i32 0), i32* @tcase) 15 | br label %while_cond 16 | 17 | while_cond: ; preds = %while_body, %entry 18 | %1 = load i32, i32* @tcase 19 | %cmptmp = icmp sgt i32 %1, 0 20 | br i1 %cmptmp, label %while_body, label %while_end 21 | 22 | while_body: ; preds = %while_cond 23 | %2 = load i32, i32* @tcase 24 | %3 = load i32, i32* @tcase 25 | %subtmp = sub i32 %3, 1 26 | store i32 %subtmp, i32* @tcase 27 | %4 = load i32, i32* @a 28 | %5 = load i32, i32* @b 29 | %call_scanf1 = call i32 (i8*, ...) @scanf(i8* getelementptr inbounds ([5 x i8], [5 x i8]* @scanf_format.1, i32 0, i32 0), i32* @a, i32* @b) 30 | %6 = load i32, i32* @a 31 | %7 = load i32, i32* @b 32 | %8 = call i32 @gcd(i32* @a, i32* @b) 33 | %call_printf = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @printf_format, i32 0, i32 0), i32 %8) 34 | br label %while_cond 35 | 36 | while_end: ; preds = %while_cond 37 | ret i32 0 38 | } 39 | 40 | define i32 @gcd(i32*, i32*) { 41 | entry: 42 | %2 = load i32, i32* %0 43 | %a = alloca i32 44 | store i32 %2, i32* %a 45 | %3 = load i32, i32* %1 46 | %b = alloca i32 47 | store i32 %3, i32* %b 48 | %gcd = alloca i32 49 | %4 = load i32, i32* %b 50 | %cmptmp = icmp eq i32 %4, 0 51 | br i1 %cmptmp, label %if_then, label %if_else 52 | 53 | if_then: ; preds = %entry 54 | %5 = load i32, i32* %gcd 55 | %6 = load i32, i32* %a 56 | store i32 %6, i32* %gcd 57 | br label %if_cont 58 | 59 | if_else: ; preds = %entry 60 | %7 = load i32, i32* %gcd 61 | %8 = load i32, i32* %b 62 | %9 = load i32, i32* %a 63 | %10 = load i32, i32* %b 64 | %modtmp = srem i32 %9, %10 65 | %"0_1" = alloca i32 66 | store i32 %modtmp, i32* %"0_1" 67 | %11 = call i32 @gcd(i32* %b, i32* %"0_1") 68 | store i32 %11, i32* %gcd 69 | br label %if_cont 70 | 71 | if_cont: ; preds = %if_else, %if_then 72 | %12 = load i32, i32* %gcd 73 | ret i32 %12 74 | } 75 | 76 | declare i32 @scanf(i8*, ...) 77 | 78 | declare i32 @printf(i8*, ...) 79 | -------------------------------------------------------------------------------- /src/type/type.h: -------------------------------------------------------------------------------- 1 | #ifndef OPC_TYPE_H 2 | #define OPC_TYPE_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include "../generator/generator.h" 10 | #include 11 | #include 12 | 13 | namespace OurType { 14 | 15 | bool isEqual(const PascalType *const a, const PascalType *const b); 16 | 17 | class PascalType { 18 | public: 19 | enum class TypeGroup { 20 | BUILT_IN, ENUM, SUBRANGE, ARRAY, STR, RECORD 21 | }; 22 | TypeGroup tg; 23 | 24 | PascalType(TypeGroup tg); 25 | 26 | bool isSimple() const; 27 | 28 | bool isIntegerTy() const; 29 | 30 | bool isCharTy() const; 31 | 32 | bool isFloatingPointTy() const; 33 | 34 | bool isBuiltInTy() const; 35 | 36 | bool isStringTy() const; 37 | 38 | bool isSubRangeTy() const; 39 | 40 | bool isRecordTy() const; 41 | 42 | bool isArrayTy() const; 43 | }; 44 | 45 | class BuiltinType : public PascalType { 46 | public: 47 | enum class BasicTypes { 48 | INT, REAL, CHAR, BOOLEAN, VOID 49 | }; 50 | BasicTypes type; 51 | 52 | BuiltinType(BasicTypes type); 53 | }; 54 | 55 | extern PascalType *const INT_TYPE; 56 | extern PascalType *const REAL_TYPE; 57 | extern PascalType *const CHAR_TYPE; 58 | extern PascalType *const BOOLEAN_TYPE; 59 | extern PascalType *const VOID_TYPE; 60 | 61 | class SubRangeType : public PascalType { 62 | public: 63 | // std::string type_name; 64 | int low; 65 | int high; 66 | 67 | SubRangeType(int low, int high); 68 | }; 69 | 70 | 71 | class ArrayType : public PascalType { 72 | public: 73 | std::pair range; // pair(low, high) 74 | PascalType *element_type; 75 | 76 | llvm::ConstantInt *getLLVMLow(llvm::LLVMContext &context); 77 | 78 | llvm::ConstantInt *getLLVMHigh(llvm::LLVMContext &context); 79 | 80 | ArrayType(std::pair range, PascalType *type); 81 | }; 82 | 83 | class StrType : public PascalType { 84 | public: 85 | int dim; 86 | 87 | StrType(int dim = 256); 88 | }; 89 | 90 | class RecordType : public PascalType { 91 | public: 92 | int size; 93 | std::vector name_vec; 94 | std::vector type_vec; 95 | 96 | RecordType(std::vector name_vec, std::vector type_vec); 97 | }; 98 | 99 | class EnumType : public PascalType { 100 | public: 101 | std::vector names_; 102 | 103 | EnumType(std::vector names, Generator *g); 104 | }; 105 | 106 | llvm::Type *getLLVMType(llvm::LLVMContext &context, PascalType *const p_type); 107 | 108 | }; // namespace Type 109 | 110 | #endif //OPC_TYPE_H -------------------------------------------------------------------------------- /src/ast/ast_value.h: -------------------------------------------------------------------------------- 1 | #ifndef OPC_AST_AST_VALUE_H 2 | #define OPC_AST_AST_VALUE_H 3 | 4 | #include 5 | 6 | #include "ast_base.h" 7 | #include "ast_type.h" 8 | #include "ast_expr.h" 9 | 10 | class Visitor; 11 | 12 | class ASTNode; 13 | 14 | class ASTExpr; 15 | 16 | class ASTConstValue; 17 | 18 | class ASTConstExprList; 19 | 20 | class ASTConstExpr; 21 | 22 | class ASTConstPart; 23 | 24 | class ASTVarPart; 25 | 26 | class ASTVarDeclList; 27 | 28 | class ASTTypeDecl; 29 | 30 | class ASTVarDecl; 31 | 32 | class ASTConstValue : public ASTNode { 33 | public: 34 | enum class ValueType { 35 | INTEGER, FLOAT, CHAR, STRING, BOOL 36 | }; 37 | 38 | ASTConstValue(std::string, ValueType); 39 | 40 | 41 | 42 | virtual std::shared_ptr Accept(Visitor *visitor); 43 | 44 | ValueType getValueType() const; 45 | 46 | const std::string &getContent() const; 47 | std::string getValueTypeName(ValueType value_type); 48 | 49 | private: 50 | ValueType value_type; 51 | std::string content; 52 | 53 | }; 54 | 55 | class ASTConstExprList : public ASTNode { 56 | public: 57 | ASTConstExprList(); 58 | 59 | void add_const_expr(ASTConstExpr *); 60 | 61 | 62 | 63 | virtual std::shared_ptr Accept(Visitor *visitor); 64 | 65 | private: 66 | std::vector const_expr_list; 67 | public: 68 | const std::vector &getConstExprList() const; 69 | }; 70 | 71 | class ASTConstExpr : public ASTNode { 72 | public: 73 | ASTConstExpr(std::string, ASTExpr *); 74 | 75 | 76 | 77 | virtual std::shared_ptr Accept(Visitor *visitor); 78 | 79 | const std::string &getId() const; 80 | 81 | ASTExpr *getValue() const; 82 | 83 | private: 84 | std::string id; 85 | ASTExpr *value; 86 | }; 87 | 88 | class ASTConstPart : public ASTNode { 89 | public: 90 | ASTConstPart(ASTConstExprList *const_expr_list); 91 | 92 | 93 | 94 | virtual std::shared_ptr Accept(Visitor *visitor); 95 | 96 | ASTConstExprList *getConstExprList() const; 97 | 98 | private: 99 | ASTConstExprList *const_expr_list; 100 | }; 101 | 102 | class ASTVarPart : public ASTNode { 103 | public: 104 | ASTVarPart(ASTVarDeclList *); 105 | 106 | 107 | 108 | virtual std::shared_ptr Accept(Visitor *visitor); 109 | 110 | ASTVarDeclList *getVarDeclList() const; 111 | 112 | private: 113 | ASTVarDeclList *var_decl_list; 114 | }; 115 | 116 | class ASTVarDeclList : public ASTNode { 117 | public: 118 | ASTVarDeclList(ASTVarDecl *); 119 | 120 | 121 | 122 | virtual std::shared_ptr Accept(Visitor *visitor); 123 | 124 | void addVarDecl(ASTVarDecl *); 125 | 126 | const std::vector &getVarDeclList() const; 127 | 128 | private: 129 | std::vector var_decl_list; 130 | }; 131 | 132 | class ASTVarDecl : public ASTNode { 133 | public: 134 | ASTVarDecl(ASTNameList *, ASTTypeDecl *); 135 | 136 | 137 | 138 | virtual std::shared_ptr Accept(Visitor *visitor); 139 | 140 | ASTNameList *getNameList() const; 141 | 142 | ASTTypeDecl *getTypeDecl() const; 143 | 144 | private: 145 | ASTNameList *name_list; 146 | ASTTypeDecl *type_decl; 147 | }; 148 | 149 | #endif // OPC_AST_AST_VALUE_H -------------------------------------------------------------------------------- /src/generator/generator.cpp: -------------------------------------------------------------------------------- 1 | #include "generator.h" 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include "type/type.h" 11 | #include 12 | 13 | void Generator::Save(std::string path) { 14 | int fd = open(path.c_str(), O_CREAT | O_WRONLY, 0644); 15 | if (fd < 0) { 16 | std::cerr << "cannot generate output file " << path << ", errno: " << errno << std::endl; 17 | } 18 | if (dup2(fd, 1) < 0) { 19 | std::cerr << "cannot dup output file to stdout, errno: " << errno << std::endl; 20 | } 21 | close(fd); 22 | this->module->print(llvm::outs(), nullptr); 23 | } 24 | 25 | Generator::Generator():builder(this->context) { 26 | this->module = std::make_unique("pascal_module", this->context); 27 | error_message.clear(); 28 | error_position.clear(); 29 | } 30 | 31 | std::shared_ptr Generator::RecordErrorMessage(std::string cur_error_message, std::pair location){ 32 | error_message.push_back(cur_error_message); 33 | error_position.push_back(location); 34 | return nullptr; 35 | } 36 | 37 | bool Generator::hasError(){return error_message.size() > 0;} 38 | void Generator::printError(){ 39 | for (int i = 0; i < error_message.size(); i++){ 40 | std::string location = "[Error] "; 41 | if (error_position[i] != std::make_pair(-1, -1)) 42 | location = "[Error in (" + std::to_string(error_position[i].first) + ", " + std::to_string(error_position[i].second) + ")] "; 43 | std::cout << location + error_message[i] << std::endl; 44 | } 45 | } 46 | 47 | Generator::~Generator() { 48 | for (auto blk: this->block_stack) { 49 | delete blk; 50 | } 51 | delete this->module.release(); 52 | } 53 | CodeBlock* Generator::getCurrentBlock(void) { return *(this->block_stack.rbegin()); } 54 | 55 | std::pair, std::vector > Generator::getAllLocalVarNameType() { 56 | std::vector name_list; 57 | std::vector type_list; 58 | 59 | if (this->block_stack.size() == 1) 60 | return make_pair(name_list, type_list); 61 | 62 | for(auto it : this->getCurrentBlock()->named_values) { 63 | std::string name = it.first; 64 | OurType::PascalType *type = nullptr; 65 | for(int i = this->block_stack.size()-1; i >= 1; i--) { 66 | // do not count global variable 67 | // use the nearest one as it is the currently using type 68 | if (this->block_stack[i]->isType(name, true)) { 69 | type = this->block_stack[i]->named_types[name]; 70 | break; 71 | } 72 | } 73 | 74 | assert(type != nullptr); 75 | 76 | name_list.push_back(name); 77 | type_list.push_back(type); 78 | } 79 | return std::make_pair(name_list, type_list); 80 | } 81 | 82 | OurType::PascalType *Generator::getVarType(std::string id) { 83 | if (!this->getCurrentBlock()->isValue(id) && !this->block_stack[0]->isValue(id)) { 84 | std::cout << "variable not found, return nullptr" << std::endl; 85 | return nullptr; 86 | } 87 | for(int i = this->block_stack.size()-1; i >= 0; i--) { 88 | if (this->block_stack[i]->isType(id, true)) { 89 | return this->block_stack[i]->named_types[id]; 90 | } 91 | } 92 | return nullptr; 93 | } -------------------------------------------------------------------------------- /src/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include "pascal.y.hpp" 8 | #include "vis/graph_generator.h" 9 | #include "generator/generator.h" 10 | 11 | using namespace std; 12 | string input_fname = ""; 13 | string output_dot_fname = ""; 14 | string output_ll_fname = ""; 15 | bool gen_graph = true; 16 | bool gen_ir = true; 17 | 18 | void parse_arg(int argc, char *argv[]) { 19 | for (int i=0;i < argc;i++) { 20 | string arg = argv[i]; 21 | if (arg == "--ir") { 22 | gen_ir = true; 23 | if (i < argc - 1) { 24 | string nxt_arg = argv[i + 1]; 25 | if (nxt_arg[0] != '-') { 26 | output_ll_fname = nxt_arg; 27 | i++; 28 | } 29 | } 30 | } else 31 | if (arg == "--noir") { 32 | gen_ir = false; 33 | } else 34 | if (arg == "--graph") { 35 | gen_graph = true; 36 | if (i < argc - 1) { 37 | string nxt_arg = argv[i + 1]; 38 | if (nxt_arg[0] != '-') { 39 | output_dot_fname = nxt_arg; 40 | i++; 41 | } 42 | } 43 | } 44 | else if (input_fname == "") { 45 | input_fname = arg; 46 | } 47 | } 48 | if (argc == 0) { 49 | printf("Usage: opc input_file [--ir [ir_fname]] [--noir] [--graph [graph_fname]] \n"); 50 | } 51 | } 52 | 53 | int main(int argc, char *argv[]) { 54 | parse_arg(argc - 1, argv + 1); 55 | if (input_fname.substr(input_fname.length() - 4, 4).compare(".pas") != 0) { 56 | cerr << "invalid input file name: " << input_fname << std::endl 57 | << "please use .pas file!" << std::endl; 58 | return 1; 59 | } 60 | int fd = open(input_fname.c_str(), O_RDONLY); 61 | if (fd < 0) { 62 | cerr << "cannot open file " << input_fname << endl; 63 | return 1; 64 | } 65 | if (dup2(fd, 0) < 0) { 66 | cerr << "cannot dup file into stdin " << input_fname << endl; 67 | } 68 | struct stat file_stat; 69 | stat(input_fname.c_str(), &file_stat); 70 | if (!S_ISREG(file_stat.st_mode)) { 71 | std::cerr << input_fname << " is not a regular file" << std::endl; 72 | return 1; 73 | } 74 | std::cout << "parsing..." << endl; 75 | 76 | if (yyparse() != 0) { 77 | std: 78 | cerr << "failed to parse this code!" << std::endl; 79 | return 1; 80 | } 81 | std::cout << "parsed!" << endl; 82 | if (gen_graph) { 83 | GraphGenerator *g = new GraphGenerator(); 84 | 85 | ast_root->Accept(g); 86 | if (output_dot_fname == "") output_dot_fname = input_fname + ".dot"; 87 | g->Save(output_dot_fname); 88 | } 89 | if (gen_ir) { 90 | Generator *gen = new Generator(); 91 | std::cout << "new!" << std::endl; 92 | ast_root->Accept(gen); 93 | std::cout << "accept!" << std::endl; 94 | if (output_ll_fname == "") output_ll_fname = input_fname + ".ll"; 95 | system(("rm "+output_ll_fname).c_str()); 96 | if (gen->hasError()){ 97 | std::cout << "Compiling Error!" << std::endl; 98 | gen->printError(); 99 | } 100 | else 101 | gen->Save(output_ll_fname); 102 | delete gen; 103 | } 104 | return 0; 105 | } -------------------------------------------------------------------------------- /test/cell.pas.dot: -------------------------------------------------------------------------------- 1 | digraph g { 2 | node_0->node_1; 3 | node_1->node_2; 4 | node_0->node_3; 5 | node_3->node_4; 6 | node_4->node_5; 7 | node_5->node_6; 8 | node_6->node_7; 9 | node_7->node_8; 10 | node_8->node_9; 11 | node_8->node_10; 12 | node_7->node_11; 13 | node_11->node_12; 14 | node_12->node_13; 15 | node_11->node_14; 16 | node_14->node_15; 17 | node_6->node_16; 18 | node_16->node_17; 19 | node_17->node_18; 20 | node_17->node_19; 21 | node_17->node_20; 22 | node_17->node_21; 23 | node_17->node_22; 24 | node_17->node_23; 25 | node_17->node_24; 26 | node_16->node_25; 27 | node_25->node_26; 28 | node_6->node_27; 29 | node_27->node_28; 30 | node_28->node_29; 31 | node_27->node_30; 32 | node_30->node_31; 33 | node_3->node_32; 34 | node_32->node_33; 35 | node_33->node_34; 36 | node_34->node_35; 37 | node_35->node_36; 38 | node_34->node_37; 39 | node_33->node_38; 40 | node_38->node_39; 41 | node_38->node_40; 42 | node_38->node_41; 43 | node_38->node_42; 44 | node_42->node_43; 45 | node_43->node_44; 46 | node_44->node_45; 47 | node_43->node_46; 48 | node_46->node_47; 49 | node_47->node_48; 50 | node_46->node_49; 51 | node_33->node_50; 52 | node_50->node_51; 53 | node_50->node_52; 54 | node_52->node_53; 55 | node_53->node_54; 56 | node_52->node_55; 57 | node_55->node_56; 58 | node_0[label="program\n[13, 4]"]; 59 | node_1[label="program_head\n[1, 13]"]; 60 | node_2[label="v233"]; 61 | node_3[label="routine\n[13, 1]"]; 62 | node_4[label="routine_head\n[6, 1]"]; 63 | node_5[label="var_part:\n[6, 1]"]; 64 | node_6[label="var_decl_list:\n[5, 12]"]; 65 | node_7[label="Var_decl:\n[3, 33]"]; 66 | node_8[label="name_list\n[3, 5]"]; 67 | node_9[label="a"]; 68 | node_10[label="b"]; 69 | node_11[label="array_type_decl\n[3, 26]"]; 70 | node_12[label="simple_type_decl\n[3, 16]"]; 71 | node_13[label=""]; 72 | node_14[label="simple_type_decl\n[3, 26]"]; 73 | node_15[label="Integer"]; 74 | node_16[label="Var_decl:\n[4, 26]"]; 75 | node_17[label="name_list\n[4, 17]"]; 76 | node_18[label="m1"]; 77 | node_19[label="m2"]; 78 | node_20[label="n"]; 79 | node_21[label="i"]; 80 | node_22[label="p"]; 81 | node_23[label="t"]; 82 | node_24[label="s"]; 83 | node_25[label="simple_type_decl\n[4, 19]"]; 84 | node_26[label="Integer"]; 85 | node_27[label="Var_decl:\n[5, 12]"]; 86 | node_28[label="name_list\n[5, 3]"]; 87 | node_29[label="f"]; 88 | node_30[label="simple_type_decl\n[5, 5]"]; 89 | node_31[label="Boolean"]; 90 | node_32[label="routine_body\n[13, 1]"]; 91 | node_33[label="stmt_list\n[13, 1]"]; 92 | node_34[label="assign_stmt\n[7, 9]"]; 93 | node_35[label="ID_expr\n[0, 0]"]; 94 | node_36[label="t"]; 95 | node_37[label="0"]; 96 | node_38[label="for_stmt: TO\n[11, 3]"]; 97 | node_39[label="t"]; 98 | node_40[label="1"]; 99 | node_41[label="150"]; 100 | node_42[label="stmt_list\n[11, 3]"]; 101 | node_43[label="assign_stmt\n[10, 8]"]; 102 | node_44[label="ID_expr\n[0, 0]"]; 103 | node_45[label="s"]; 104 | node_46[label="binary_op_expr: PLUS\n[10, 8]"]; 105 | node_47[label="ID_expr\n[10, 6]"]; 106 | node_48[label="s"]; 107 | node_49[label="1"]; 108 | node_50[label="proc_stmt\n[12, 15]"]; 109 | node_51[label="writeln"]; 110 | node_52[label="expression_list\n[12, 15]"]; 111 | node_53[label="ID_expr\n[12, 12]"]; 112 | node_54[label="t"]; 113 | node_55[label="ID_expr\n[12, 15]"]; 114 | node_56[label="s"]; 115 | } -------------------------------------------------------------------------------- /test/myten.s: -------------------------------------------------------------------------------- 1 | .text 2 | .file "pascal_module" 3 | .globl main # -- Begin function main 4 | .p2align 4, 0x90 5 | .type main,@function 6 | main: # @main 7 | .cfi_startproc 8 | # %bb.0: # %for_start 9 | pushq %rax 10 | .cfi_def_cfa_offset 16 11 | movl $.Lprintf_format, %edi 12 | movl $.L__unnamed_1, %esi 13 | xorl %eax, %eax 14 | callq printf 15 | movl $.Lscanf_format, %edi 16 | movl $a, %esi 17 | xorl %eax, %eax 18 | callq scanf 19 | movss a(%rip), %xmm0 # xmm0 = mem[0],zero,zero,zero 20 | movss %xmm0, s(%rip) 21 | movss %xmm0, max(%rip) 22 | movss %xmm0, min(%rip) 23 | movl $2, i(%rip) 24 | .p2align 4, 0x90 25 | .LBB0_2: # %label_10 26 | # =>This Inner Loop Header: Depth=1 27 | movl $.Lscanf_format.1, %edi 28 | movl $a, %esi 29 | xorl %eax, %eax 30 | callq scanf 31 | movss a(%rip), %xmm0 # xmm0 = mem[0],zero,zero,zero 32 | movss s(%rip), %xmm1 # xmm1 = mem[0],zero,zero,zero 33 | addss %xmm0, %xmm1 34 | movss %xmm1, s(%rip) 35 | ucomiss max(%rip), %xmm0 36 | jbe .LBB0_4 37 | # %bb.3: # %label_11 38 | # in Loop: Header=BB0_2 Depth=1 39 | movss a(%rip), %xmm0 # xmm0 = mem[0],zero,zero,zero 40 | movss %xmm0, max(%rip) 41 | jmp .LBB0_1 42 | .p2align 4, 0x90 43 | .LBB0_4: # %label_12 44 | # in Loop: Header=BB0_2 Depth=1 45 | movss min(%rip), %xmm0 # xmm0 = mem[0],zero,zero,zero 46 | ucomiss a(%rip), %xmm0 47 | jbe .LBB0_1 48 | # %bb.5: # %label_17 49 | # in Loop: Header=BB0_2 Depth=1 50 | movss a(%rip), %xmm0 # xmm0 = mem[0],zero,zero,zero 51 | movss %xmm0, min(%rip) 52 | .LBB0_1: # %for_cond 53 | # in Loop: Header=BB0_2 Depth=1 54 | movl i(%rip), %eax 55 | incl %eax 56 | movl %eax, i(%rip) 57 | cmpl $10, %eax 58 | jle .LBB0_2 59 | # %bb.6: # %label_18 60 | movss a(%rip), %xmm0 # xmm0 = mem[0],zero,zero,zero 61 | movl $.Lprintf_format.2, %edi 62 | movb $1, %al 63 | callq printf 64 | xorl %eax, %eax 65 | popq %rcx 66 | retq 67 | .Lfunc_end0: 68 | .size main, .Lfunc_end0-main 69 | .cfi_endproc 70 | # -- End function 71 | .type a,@object # @a 72 | .comm a,4,4 73 | .type s,@object # @s 74 | .comm s,4,4 75 | .type max,@object # @max 76 | .comm max,4,4 77 | .type min,@object # @min 78 | .comm min,4,4 79 | .type avg,@object # @avg 80 | .comm avg,4,4 81 | .type i,@object # @i 82 | .comm i,4,4 83 | .type .L__unnamed_1,@object # @0 84 | .section .rodata.str1.1,"aMS",@progbits,1 85 | .L__unnamed_1: 86 | .asciz "please input:" 87 | .size .L__unnamed_1, 14 88 | 89 | .type .Lprintf_format,@object # @printf_format 90 | .Lprintf_format: 91 | .asciz "%s" 92 | .size .Lprintf_format, 3 93 | 94 | .type .Lscanf_format,@object # @scanf_format 95 | .Lscanf_format: 96 | .asciz "%lf" 97 | .size .Lscanf_format, 4 98 | 99 | .type .Lscanf_format.1,@object # @scanf_format.1 100 | .Lscanf_format.1: 101 | .asciz "%lf" 102 | .size .Lscanf_format.1, 4 103 | 104 | .type .Lprintf_format.2,@object # @printf_format.2 105 | .Lprintf_format.2: 106 | .asciz "%lf\n" 107 | .size .Lprintf_format.2, 5 108 | 109 | 110 | .section ".note.GNU-stack","",@progbits 111 | -------------------------------------------------------------------------------- /src/ast/ast_value.cpp: -------------------------------------------------------------------------------- 1 | #include "ast_value.h" 2 | #include "../visitor.h" 3 | 4 | #include 5 | 6 | ASTConstValue::ASTConstValue(std::string content, 7 | ASTConstValue::ValueType value_type) 8 | : content(content), value_type(value_type) {} 9 | 10 | std::string ASTConstValue::getValueTypeName( 11 | ASTConstValue::ValueType value_type) { 12 | std::string name; 13 | switch (value_type) { 14 | case ValueType::INTEGER: 15 | name = "INTEGER"; 16 | break; 17 | case ValueType::FLOAT: 18 | name = "FLOAT"; 19 | break; 20 | case ValueType::CHAR: 21 | name = "CHAR"; 22 | break; 23 | case ValueType::STRING: 24 | name = "STRING"; 25 | break; 26 | case ValueType::BOOL: 27 | name = "BOOL"; 28 | break; 29 | } 30 | return name; 31 | } 32 | 33 | ASTConstPart::ASTConstPart(ASTConstExprList *const_expr_list) 34 | : const_expr_list(const_expr_list) {} 35 | 36 | ASTConstExprList::ASTConstExprList() = default; 37 | 38 | void ASTConstExprList::add_const_expr(ASTConstExpr *const_expr) { 39 | const_expr_list.push_back(const_expr); 40 | } 41 | 42 | ASTConstExpr::ASTConstExpr(std::string id, ASTExpr *value) : id(id), value(value) {} 43 | 44 | ASTVarPart::ASTVarPart(ASTVarDeclList *var_decl_list) 45 | : var_decl_list(var_decl_list) {} 46 | 47 | ASTVarDeclList::ASTVarDeclList(ASTVarDecl *var_decl) { 48 | var_decl_list.clear(); 49 | var_decl_list.push_back(var_decl); 50 | } 51 | 52 | void ASTVarDeclList::addVarDecl(ASTVarDecl *var_decl) { 53 | var_decl_list.push_back(var_decl); 54 | } 55 | 56 | ASTVarDecl::ASTVarDecl(ASTNameList *name_list, ASTTypeDecl *type_decl) 57 | : name_list(name_list), type_decl(type_decl) {} 58 | 59 | std::shared_ptr ASTConstValue::Accept(Visitor *visitor) { return visitor->VisitASTConstValue(this); } 60 | 61 | ASTConstValue::ValueType ASTConstValue::getValueType() const { 62 | return value_type; 63 | } 64 | 65 | const string &ASTConstValue::getContent() const { 66 | return content; 67 | } 68 | 69 | std::shared_ptr ASTConstExprList::Accept(Visitor *visitor) { 70 | return visitor->VisitASTConstExprList(this); 71 | } 72 | 73 | const vector &ASTConstExprList::getConstExprList() const { 74 | return const_expr_list; 75 | } 76 | 77 | std::shared_ptr ASTConstExpr::Accept(Visitor *visitor) { return visitor->VisitASTConstExpr(this); } 78 | 79 | const string &ASTConstExpr::getId() const { 80 | return id; 81 | } 82 | 83 | ASTExpr *ASTConstExpr::getValue() const { 84 | return value; 85 | } 86 | 87 | std::shared_ptr ASTConstPart::Accept(Visitor *visitor) { return visitor->VisitASTConstPart(this); } 88 | 89 | ASTConstExprList *ASTConstPart::getConstExprList() const { 90 | return const_expr_list; 91 | } 92 | 93 | std::shared_ptr ASTVarPart::Accept(Visitor *visitor) { return visitor->VisitASTVarPart(this); } 94 | 95 | ASTVarDeclList *ASTVarPart::getVarDeclList() const { 96 | return var_decl_list; 97 | } 98 | 99 | std::shared_ptr ASTVarDeclList::Accept(Visitor *visitor) { return visitor->VisitASTVarDeclList(this); } 100 | 101 | const vector &ASTVarDeclList::getVarDeclList() const { 102 | return var_decl_list; 103 | } 104 | 105 | std::shared_ptr ASTVarDecl::Accept(Visitor *visitor) { return visitor->VisitASTVarDecl(this); } 106 | 107 | ASTNameList *ASTVarDecl::getNameList() const { 108 | return name_list; 109 | } 110 | 111 | ASTTypeDecl *ASTVarDecl::getTypeDecl() const { 112 | return type_decl; 113 | } 114 | -------------------------------------------------------------------------------- /test/nested_record.pas.dot: -------------------------------------------------------------------------------- 1 | digraph g { 2 | node_0->node_1; 3 | node_1->node_2; 4 | node_0->node_3; 5 | node_3->node_4; 6 | node_4->node_5; 7 | node_5->node_6; 8 | node_6->node_7; 9 | node_7->node_8; 10 | node_7->node_9; 11 | node_9->node_10; 12 | node_10->node_11; 13 | node_11->node_12; 14 | node_12->node_13; 15 | node_12->node_14; 16 | node_11->node_15; 17 | node_15->node_16; 18 | node_6->node_17; 19 | node_17->node_18; 20 | node_17->node_19; 21 | node_19->node_20; 22 | node_20->node_21; 23 | node_21->node_22; 24 | node_22->node_23; 25 | node_22->node_24; 26 | node_21->node_25; 27 | node_25->node_26; 28 | node_20->node_27; 29 | node_27->node_28; 30 | node_28->node_29; 31 | node_28->node_30; 32 | node_27->node_31; 33 | node_31->node_32; 34 | node_20->node_33; 35 | node_33->node_34; 36 | node_34->node_35; 37 | node_33->node_36; 38 | node_36->node_37; 39 | node_37->node_38; 40 | node_38->node_39; 41 | node_39->node_40; 42 | node_39->node_41; 43 | node_38->node_42; 44 | node_42->node_43; 45 | node_4->node_44; 46 | node_44->node_45; 47 | node_45->node_46; 48 | node_46->node_47; 49 | node_47->node_48; 50 | node_46->node_49; 51 | node_49->node_50; 52 | node_3->node_51; 53 | node_51->node_52; 54 | node_52->node_53; 55 | node_53->node_54; 56 | node_53->node_55; 57 | node_55->node_56; 58 | node_56->node_57; 59 | node_56->node_58; 60 | node_55->node_59; 61 | node_59->node_60; 62 | node_59->node_61; 63 | node_0[label="program\n[17, 4]"]; 64 | node_1[label="program_head\n[1, 27]"]; 65 | node_2[label="test_nested_record"]; 66 | node_3[label="routine\n[17, 1]"]; 67 | node_4[label="routine_head\n[14, 1]"]; 68 | node_5[label="type_part\n[13, 1]"]; 69 | node_6[label="type_decl_list\n[12, 8]"]; 70 | node_7[label="type_definition\n[5, 8]"]; 71 | node_8[label="r1"]; 72 | node_9[label="file_decl_list\n[5, 5]"]; 73 | node_10[label="field_decl_list\n[4, 22]"]; 74 | node_11[label="field_decl\n[4, 22]"]; 75 | node_12[label="name_list\n[4, 12]"]; 76 | node_13[label="a"]; 77 | node_14[label="b"]; 78 | node_15[label="simple_type_decl\n[4, 15]"]; 79 | node_16[label="Integer"]; 80 | node_17[label="type_definition\n[12, 8]"]; 81 | node_18[label="r2"]; 82 | node_19[label="file_decl_list\n[12, 5]"]; 83 | node_20[label="field_decl_list\n[11, 12]"]; 84 | node_21[label="field_decl\n[7, 22]"]; 85 | node_22[label="name_list\n[7, 12]"]; 86 | node_23[label="a"]; 87 | node_24[label="b"]; 88 | node_25[label="simple_type_decl\n[7, 15]"]; 89 | node_26[label="Integer"]; 90 | node_27[label="field_decl\n[8, 17]"]; 91 | node_28[label="name_list\n[8, 12]"]; 92 | node_29[label="c"]; 93 | node_30[label="d"]; 94 | node_31[label="simple_type_decl\n[8, 17]"]; 95 | node_32[label="r1"]; 96 | node_33[label="field_decl\n[11, 12]"]; 97 | node_34[label="name_list\n[9, 9]"]; 98 | node_35[label="e"]; 99 | node_36[label="file_decl_list\n[11, 9]"]; 100 | node_37[label="field_decl_list\n[10, 26]"]; 101 | node_38[label="field_decl\n[10, 26]"]; 102 | node_39[label="name_list\n[10, 16]"]; 103 | node_40[label="a"]; 104 | node_41[label="b"]; 105 | node_42[label="simple_type_decl\n[10, 19]"]; 106 | node_43[label="Integer"]; 107 | node_44[label="var_part:\n[14, 1]"]; 108 | node_45[label="var_decl_list:\n[13, 10]"]; 109 | node_46[label="Var_decl:\n[13, 10]"]; 110 | node_47[label="name_list\n[13, 5]"]; 111 | node_48[label="a"]; 112 | node_49[label="simple_type_decl\n[13, 10]"]; 113 | node_50[label="r2"]; 114 | node_51[label="routine_body\n[17, 1]"]; 115 | node_52[label="stmt_list\n[17, 1]"]; 116 | node_53[label="proc_stmt\n[15, 15]"]; 117 | node_54[label="read"]; 118 | node_55[label="expression_list\n[15, 15]"]; 119 | node_56[label="property_expr:\n[15, 10]"]; 120 | node_57[label="a"]; 121 | node_58[label="a"]; 122 | node_59[label="property_expr:\n[15, 15]"]; 123 | node_60[label="a"]; 124 | node_61[label="b"]; 125 | } -------------------------------------------------------------------------------- /src/ast/ast_expr.h: -------------------------------------------------------------------------------- 1 | #ifndef OPC_AST_AST_EXPR_H 2 | #define OPC_AST_AST_EXPR_H 3 | 4 | #include "ast_base.h" 5 | #include "ast_value.h" 6 | 7 | class Visitor; 8 | 9 | class ASTNode; 10 | 11 | class ASTExpr; 12 | 13 | class ASTExpressionList; 14 | 15 | class ASTBinaryExpr; 16 | 17 | class ASTConstValueExpr; 18 | 19 | class ASTIDExpr; 20 | 21 | class ASTArrayExpr; 22 | 23 | class ASTConstValue; 24 | 25 | class ASTExpr : public ASTNode { 26 | }; 27 | 28 | class ASTExpressionList : public ASTExpr { 29 | public: 30 | ASTExpressionList(ASTExpr *expr); 31 | 32 | void AddExpr(ASTExpr *expr); 33 | 34 | 35 | 36 | virtual std::shared_ptr Accept(Visitor *visitor); 37 | 38 | private: 39 | std::vector expr_list_; 40 | public: 41 | const std::vector &getExprList() const; 42 | }; 43 | 44 | class ASTBinaryExpr : public ASTExpr { 45 | public: 46 | enum class Oper { 47 | GE, 48 | GT, 49 | LE, 50 | LT, 51 | EQUAL, 52 | UNEQUAL, 53 | PLUS, 54 | MINUS, 55 | OR, 56 | MUL, 57 | REALDIV, 58 | DIV, 59 | MOD, 60 | AND 61 | }; 62 | 63 | private: 64 | public: 65 | ASTExpr *getLExpr() const; 66 | 67 | ASTExpr *getRExpr() const; 68 | 69 | public: 70 | Oper getOp() const; 71 | static std::string getOpName(Oper op_); 72 | 73 | private: 74 | Oper op_; 75 | ASTExpr *l_expr_, *r_expr_; 76 | 77 | 78 | public: 79 | ASTBinaryExpr(Oper op, ASTExpr *l_expr, ASTExpr *r_expr); 80 | 81 | 82 | 83 | virtual std::shared_ptr Accept(Visitor *visitor); 84 | }; 85 | 86 | class ASTUnaryExpr : public ASTExpr { 87 | public: 88 | 89 | ASTExpr *getExpr() const; 90 | 91 | enum class Oper { 92 | NOT, SUB 93 | }; 94 | Oper getOp() const; 95 | 96 | private: 97 | Oper op_; 98 | ASTExpr *expr_; 99 | 100 | public: 101 | ASTUnaryExpr(Oper, ASTExpr *); 102 | 103 | 104 | 105 | virtual std::shared_ptr Accept(Visitor *visitor); 106 | }; 107 | 108 | class ASTPropExpr : public ASTExpr { 109 | private: 110 | std::string id_, prop_id_; 111 | public: 112 | const std::string &getId() const; 113 | 114 | const std::string &getPropId() const; 115 | 116 | public: 117 | ASTPropExpr(std::string id, std::string prop_id); 118 | 119 | 120 | 121 | virtual std::shared_ptr Accept(Visitor *visitor); 122 | }; 123 | 124 | class ASTConstValueExpr : public ASTExpr { 125 | private: 126 | ASTConstValue *const_value_; 127 | 128 | public: 129 | ASTConstValueExpr(ASTConstValue *); 130 | 131 | 132 | 133 | ASTConstValue *getConstValue() const; 134 | 135 | virtual std::shared_ptr Accept(Visitor *visitor); 136 | }; 137 | 138 | class ASTFuncCall : public ASTExpr { 139 | private: 140 | public: 141 | const std::string &getFuncId() const; 142 | 143 | ASTExpressionList *getArgList() const; 144 | 145 | private: 146 | std::string func_id_; 147 | ASTExpressionList *arg_list_; 148 | 149 | public: 150 | ASTFuncCall(std::string func_id, ASTExpressionList *arg_list); 151 | 152 | 153 | 154 | virtual std::shared_ptr Accept(Visitor *visitor); 155 | }; 156 | 157 | class ASTIDExpr : public ASTExpr { 158 | private: 159 | std::string id_; 160 | 161 | public: 162 | ASTIDExpr(std::string id); 163 | 164 | 165 | 166 | const std::string &getId() const; 167 | 168 | virtual std::shared_ptr Accept(Visitor *visitor); 169 | }; 170 | 171 | class ASTArrayExpr : public ASTExpr { 172 | private: 173 | std::string id_; 174 | ASTExpr *expr_; 175 | 176 | public: 177 | ASTArrayExpr(std::string id, ASTExpr *expr); 178 | 179 | 180 | 181 | virtual std::shared_ptr Accept(Visitor *visitor); 182 | 183 | const std::string &getId() const; 184 | 185 | ASTExpr *getExpr() const; 186 | }; 187 | 188 | #endif // OPC_AST_AST_EXPR_H -------------------------------------------------------------------------------- /src/generator/generator_result.hpp: -------------------------------------------------------------------------------- 1 | #ifndef OPC_GENERATOR_RESULT_H 2 | #define OPC_GENERATOR_RESULT_H 3 | 4 | #include "../visitor.h" 5 | #include "type/type.h" 6 | #include 7 | #include 8 | 9 | #include 10 | #include 11 | 12 | using namespace OurType; 13 | 14 | class NameList : public VisitorResult { 15 | public: 16 | NameList(const std::vector &list) : list_(list) {}; 17 | 18 | ~NameList() = default; 19 | 20 | const std::vector &getNameList() const { return this->list_; }; 21 | private: 22 | std::vector list_; 23 | }; 24 | 25 | class ValueResult : public VisitorResult { 26 | public: 27 | ValueResult(OurType::PascalType *type, llvm::Value *value, llvm::Value *mem=nullptr) : type_(type), value_(value), mem_(mem) {} 28 | 29 | ~ValueResult() = default; 30 | 31 | llvm::Value *getValue() const { return this->value_; } 32 | llvm::Value *getMem() const { return this->mem_; } 33 | PascalType *getType() const { return this->type_; } 34 | llvm::Type *getllvmType() const {return this->value_->getType();} 35 | private: 36 | llvm::Value *value_; //value 37 | llvm::Value *mem_; //pointer 38 | PascalType *type_; 39 | }; 40 | 41 | /* 42 | template class PairConstant : public VisitorResult { 43 | PairConstantInt(T f, T s): first_(f), second_(s) {} 44 | T first() { return this->first_; } 45 | T second() { return this->second_; } 46 | private: 47 | T first_, second_; // for array, first=low, second=high 48 | } 49 | 50 | class PairResult : public VisitorResult { 51 | public: 52 | PairResult(std::shared_ptr f, std::shared_ptr s): first_(f), second_(s) {} 53 | std::shared_ptr first() { return this->first_; } 54 | std::shared_ptr second() { return this->second_; } 55 | 56 | private: 57 | std::shared_ptr first_, second_; 58 | }; 59 | */ 60 | 61 | class ValueListResult : public VisitorResult { 62 | public: 63 | ValueListResult(std::vector > value_list) : value_list_(value_list){} 64 | 65 | ~ValueListResult() = default; 66 | 67 | const std::vector > &getValueList() const { return this->value_list_; } 68 | private: 69 | std::vector > value_list_; 70 | }; 71 | 72 | class TypeResult : public VisitorResult { 73 | public: 74 | TypeResult(OurType::PascalType *type, bool is_var = false) :type_(type), is_var_(is_var){} 75 | OurType::PascalType *getType() const {return type_;} 76 | bool is_var(){return is_var_;} 77 | 78 | void setIsVar(bool isVar) { 79 | is_var_ = isVar; 80 | } 81 | 82 | private: 83 | OurType::PascalType *type_; 84 | bool is_var_; //use when it is served for function parameters. 85 | }; 86 | 87 | class TypeListResult : public VisitorResult { 88 | public: 89 | TypeListResult(std::vector > type_list, std::vector name_list) 90 | :type_list_(type_list), name_list_(name_list){} 91 | const std::vector> &getTypeList() {return type_list_;} 92 | const std::vector &getNameList(){return name_list_;} 93 | private: 94 | std::vector >type_list_; 95 | std::vector name_list_; 96 | }; 97 | 98 | class TypeDeclResult : public VisitorResult { 99 | public: 100 | TypeDeclResult(std::vector nl, OurType::PascalType *type): 101 | name_list(nl), type_(type) {} 102 | const std::vector &getNameList(void) { return this->name_list; } 103 | OurType::PascalType *getType(void) { return this->type_; } 104 | 105 | private: 106 | std::vector name_list; 107 | OurType::PascalType *type_; 108 | }; 109 | 110 | class TypeDeclListResult : public VisitorResult { 111 | public: 112 | TypeDeclListResult() {} 113 | void addTypeDeclResult(std::shared_ptr tdr) { 114 | this->type_decl_list_.push_back(tdr); 115 | } 116 | std::vector > &getTypeDeclList() { 117 | return this->type_decl_list_; 118 | } 119 | private: 120 | std::vector > type_decl_list_; 121 | }; 122 | 123 | #endif // OPC_GENERATOR_RESULT_H -------------------------------------------------------------------------------- /src/ast/ast_expr.cpp: -------------------------------------------------------------------------------- 1 | #include "ast_expr.h" 2 | #include "../visitor.h" 3 | 4 | 5 | ASTExpressionList::ASTExpressionList(ASTExpr *expr) { 6 | expr_list_.push_back(expr); 7 | } 8 | 9 | void ASTExpressionList::AddExpr(ASTExpr *expr) { expr_list_.push_back(expr); } 10 | 11 | ASTBinaryExpr::ASTBinaryExpr(ASTBinaryExpr::Oper op, ASTExpr *l_expr, 12 | ASTExpr *r_expr) 13 | : op_(op), l_expr_(l_expr), r_expr_(r_expr) {} 14 | 15 | std::string ASTBinaryExpr::getOpName(Oper op_) { 16 | switch (op_) { 17 | case Oper::GE: 18 | return "GE"; 19 | break; 20 | case Oper::GT: 21 | return "GT"; 22 | break; 23 | case Oper::LE: 24 | return "LE"; 25 | break; 26 | case Oper::LT: 27 | return "LT"; 28 | break; 29 | case Oper::EQUAL: 30 | return "EQUAL"; 31 | break; 32 | case Oper::UNEQUAL: 33 | return "UNEQUAL"; 34 | break; 35 | case Oper::PLUS: 36 | return "PLUS"; 37 | break; 38 | case Oper::MINUS: 39 | return "MINUS"; 40 | break; 41 | case Oper::OR: 42 | return "OR"; 43 | break; 44 | case Oper::MUL: 45 | return "MUL"; 46 | break; 47 | case Oper::REALDIV: 48 | return "REALDIV"; 49 | break; 50 | case Oper::DIV: 51 | return "DIV"; 52 | break; 53 | case Oper::MOD: 54 | return "MOD"; 55 | break; 56 | case Oper::AND: 57 | return "AND"; 58 | break; 59 | } 60 | return ""; 61 | } 62 | 63 | ASTUnaryExpr::ASTUnaryExpr(ASTUnaryExpr::Oper op, ASTExpr *expr) 64 | : op_(op), expr_(expr) {} 65 | 66 | ASTPropExpr::ASTPropExpr(std::string id, std::string prop_id) 67 | : id_(id), prop_id_(prop_id) {} 68 | 69 | ASTConstValueExpr::ASTConstValueExpr(ASTConstValue *const_value) 70 | : const_value_(const_value) {} 71 | 72 | ASTFuncCall::ASTFuncCall(std::string func_id, ASTExpressionList *arg_list) 73 | : func_id_(func_id), arg_list_(arg_list) {} 74 | 75 | ASTIDExpr::ASTIDExpr(std::string id) : id_(id) {} 76 | 77 | ASTArrayExpr::ASTArrayExpr(std::string id, ASTExpr *expr) 78 | : id_(id), expr_(expr) {} 79 | 80 | std::shared_ptr ASTExpressionList::Accept(Visitor *visitor) { 81 | return visitor->VisitASTExpressionList(this); 82 | } 83 | 84 | const vector &ASTExpressionList::getExprList() const { 85 | return expr_list_; 86 | } 87 | 88 | std::shared_ptr ASTBinaryExpr::Accept(Visitor *visitor) { return visitor->VisitASTBinaryExpr(this); } 89 | 90 | ASTBinaryExpr::Oper ASTBinaryExpr::getOp() const { 91 | return op_; 92 | } 93 | 94 | ASTExpr *ASTBinaryExpr::getLExpr() const { 95 | return l_expr_; 96 | } 97 | 98 | ASTExpr *ASTBinaryExpr::getRExpr() const { 99 | return r_expr_; 100 | } 101 | 102 | std::shared_ptr ASTUnaryExpr::Accept(Visitor *visitor) { return visitor->VisitASTUnaryExpr(this); } 103 | 104 | ASTUnaryExpr::Oper ASTUnaryExpr::getOp() const { 105 | return op_; 106 | } 107 | 108 | ASTExpr *ASTUnaryExpr::getExpr() const { 109 | return expr_; 110 | } 111 | 112 | std::shared_ptr ASTPropExpr::Accept(Visitor *visitor) { return visitor->VisitASTPropExpr(this); } 113 | 114 | const string &ASTPropExpr::getId() const { 115 | return id_; 116 | } 117 | 118 | const string &ASTPropExpr::getPropId() const { 119 | return prop_id_; 120 | } 121 | 122 | std::shared_ptr ASTConstValueExpr::Accept(Visitor *visitor) { 123 | return visitor->VisitASTConstValueExpr(this); 124 | } 125 | 126 | ASTConstValue *ASTConstValueExpr::getConstValue() const { 127 | return const_value_; 128 | } 129 | 130 | std::shared_ptr ASTFuncCall::Accept(Visitor *visitor) { return visitor->VisitASTFuncCall(this); } 131 | 132 | const string &ASTFuncCall::getFuncId() const { 133 | return func_id_; 134 | } 135 | 136 | ASTExpressionList *ASTFuncCall::getArgList() const { 137 | return arg_list_; 138 | } 139 | 140 | std::shared_ptr ASTIDExpr::Accept(Visitor *visitor) { return visitor->VisitASTIDExpr(this); } 141 | 142 | const string &ASTIDExpr::getId() const { 143 | return id_; 144 | } 145 | 146 | std::shared_ptr ASTArrayExpr::Accept(Visitor *visitor) { return visitor->VisitASTArrayExpr(this); } 147 | 148 | const string &ASTArrayExpr::getId() const { 149 | return id_; 150 | } 151 | 152 | ASTExpr *ASTArrayExpr::getExpr() const { 153 | return expr_; 154 | } 155 | -------------------------------------------------------------------------------- /test/hanoi.s: -------------------------------------------------------------------------------- 1 | .text 2 | .file "pascal_module" 3 | .globl main # -- Begin function main 4 | .p2align 4, 0x90 5 | .type main,@function 6 | main: # @main 7 | .cfi_startproc 8 | # %bb.0: # %entry 9 | pushq %rbp 10 | .cfi_def_cfa_offset 16 11 | .cfi_offset %rbp, -16 12 | movq %rsp, %rbp 13 | .cfi_def_cfa_register %rbp 14 | movl $.Lscanf_format, %edi 15 | movl $N, %esi 16 | xorl %eax, %eax 17 | callq scanf 18 | movq %rsp, %rax 19 | leaq -16(%rax), %rdi 20 | movq %rdi, %rsp 21 | movl $1, -16(%rax) 22 | movq %rsp, %rax 23 | leaq -16(%rax), %rsi 24 | movq %rsi, %rsp 25 | movl $3, -16(%rax) 26 | movq %rsp, %rax 27 | leaq -16(%rax), %rdx 28 | movq %rdx, %rsp 29 | movl $2, -16(%rax) 30 | movl $N, %ecx 31 | callq move 32 | xorl %eax, %eax 33 | movq %rbp, %rsp 34 | popq %rbp 35 | retq 36 | .Lfunc_end0: 37 | .size main, .Lfunc_end0-main 38 | .cfi_endproc 39 | # -- End function 40 | .globl move # -- Begin function move 41 | .p2align 4, 0x90 42 | .type move,@function 43 | move: # @move 44 | .cfi_startproc 45 | # %bb.0: # %label_ 46 | pushq %rbp 47 | .cfi_def_cfa_offset 16 48 | .cfi_offset %rbp, -16 49 | movq %rsp, %rbp 50 | .cfi_def_cfa_register %rbp 51 | pushq %r15 52 | pushq %r14 53 | pushq %rbx 54 | subq $24, %rsp 55 | .cfi_offset %rbx, -40 56 | .cfi_offset %r14, -32 57 | .cfi_offset %r15, -24 58 | movl (%rdi), %eax 59 | movl %eax, -32(%rbp) 60 | movl (%rsi), %eax 61 | movl %eax, -28(%rbp) 62 | movl (%rdx), %eax 63 | movl %eax, -40(%rbp) 64 | movl (%rcx), %eax 65 | movl %eax, -36(%rbp) 66 | cmpl $1, %eax 67 | jne .LBB1_2 68 | # %bb.1: # %label_5 69 | movl -32(%rbp), %esi 70 | movl $.Lprintf_format, %edi 71 | xorl %eax, %eax 72 | callq printf 73 | movl $.Lprintf_format.1, %edi 74 | movl $.L__unnamed_1, %esi 75 | xorl %eax, %eax 76 | callq printf 77 | movl -28(%rbp), %esi 78 | movl $.Lprintf_format.2, %edi 79 | xorl %eax, %eax 80 | callq printf 81 | jmp .LBB1_3 82 | .LBB1_2: # %label_15 83 | movl -36(%rbp), %eax 84 | decl %eax 85 | movq %rsp, %rdx 86 | leaq -16(%rdx), %rcx 87 | movq %rcx, %rsp 88 | movl %eax, -16(%rdx) 89 | leaq -32(%rbp), %r14 90 | leaq -40(%rbp), %rbx 91 | leaq -28(%rbp), %r15 92 | movq %r14, %rdi 93 | movq %rbx, %rsi 94 | movq %r15, %rdx 95 | callq move 96 | movl -32(%rbp), %esi 97 | movl $.Lprintf_format.3, %edi 98 | xorl %eax, %eax 99 | callq printf 100 | movl $.Lprintf_format.4, %edi 101 | movl $.L__unnamed_2, %esi 102 | xorl %eax, %eax 103 | callq printf 104 | movl -28(%rbp), %esi 105 | movl $.Lprintf_format.5, %edi 106 | xorl %eax, %eax 107 | callq printf 108 | movl -36(%rbp), %eax 109 | decl %eax 110 | movq %rsp, %rdx 111 | leaq -16(%rdx), %rcx 112 | movq %rcx, %rsp 113 | movl %eax, -16(%rdx) 114 | movq %rbx, %rdi 115 | movq %r15, %rsi 116 | movq %r14, %rdx 117 | callq move 118 | .LBB1_3: # %if_cont 119 | leaq -24(%rbp), %rsp 120 | popq %rbx 121 | popq %r14 122 | popq %r15 123 | popq %rbp 124 | retq 125 | .Lfunc_end1: 126 | .size move, .Lfunc_end1-move 127 | .cfi_endproc 128 | # -- End function 129 | .type N,@object # @N 130 | .comm N,4,4 131 | .type .Lprintf_format,@object # @printf_format 132 | .section .rodata.str1.1,"aMS",@progbits,1 133 | .Lprintf_format: 134 | .asciz "%d" 135 | .size .Lprintf_format, 3 136 | 137 | .type .L__unnamed_1,@object # @0 138 | .L__unnamed_1: 139 | .asciz "->" 140 | .size .L__unnamed_1, 3 141 | 142 | .type .Lprintf_format.1,@object # @printf_format.1 143 | .Lprintf_format.1: 144 | .asciz "%s" 145 | .size .Lprintf_format.1, 3 146 | 147 | .type .Lprintf_format.2,@object # @printf_format.2 148 | .Lprintf_format.2: 149 | .asciz "%d\n" 150 | .size .Lprintf_format.2, 4 151 | 152 | .type .Lprintf_format.3,@object # @printf_format.3 153 | .Lprintf_format.3: 154 | .asciz "%d" 155 | .size .Lprintf_format.3, 3 156 | 157 | .type .L__unnamed_2,@object # @1 158 | .L__unnamed_2: 159 | .asciz "->" 160 | .size .L__unnamed_2, 3 161 | 162 | .type .Lprintf_format.4,@object # @printf_format.4 163 | .Lprintf_format.4: 164 | .asciz "%s" 165 | .size .Lprintf_format.4, 3 166 | 167 | .type .Lprintf_format.5,@object # @printf_format.5 168 | .Lprintf_format.5: 169 | .asciz "%d\n" 170 | .size .Lprintf_format.5, 4 171 | 172 | .type .Lscanf_format,@object # @scanf_format 173 | .Lscanf_format: 174 | .asciz "%d" 175 | .size .Lscanf_format, 3 176 | 177 | 178 | .section ".note.GNU-stack","",@progbits 179 | -------------------------------------------------------------------------------- /src/ast/ast_type.cpp: -------------------------------------------------------------------------------- 1 | #include "ast_type.h" 2 | #include "../visitor.h" 3 | #include "../generator/generator.h" 4 | 5 | 6 | ASTType::ASTType(TypeName type_name) : type_name(type_name) {} 7 | 8 | ASTSimpleTypeDecl::ASTSimpleTypeDecl(ASTType *type) : type_name(type), my_type(MyType::BUILTIN_TYPE) {} 9 | 10 | ASTSimpleTypeDecl::ASTSimpleTypeDecl(ASTConstValue *low, bool neg_low, ASTConstValue* high, bool neg_high): 11 | my_type(MyType::VALUE_RANGE), low(low), neg_low(neg_low), high(high), neg_high(neg_high) 12 | { } 13 | 14 | ASTSimpleTypeDecl::ASTSimpleTypeDecl(std::string low_name, std::string high_name): 15 | my_type(MyType::ID_RANGE), low_name(low_name), high_name(high_name) 16 | { } 17 | 18 | ASTSimpleTypeDecl::ASTSimpleTypeDecl(std::string defined_id): 19 | my_type(MyType::DEFINED_ID), defined_id(defined_id) {} 20 | 21 | ASTSimpleTypeDecl::ASTSimpleTypeDecl(ASTNameList *name_list): name_list(name_list), my_type{MyType::ENUM} {} 22 | 23 | 24 | ASTArrayTypeDecl::ASTArrayTypeDecl(ASTSimpleTypeDecl *simple_type_decl, 25 | ASTTypeDecl *type_decl) 26 | : simple_type_decl(simple_type_decl), type_decl(type_decl) {} 27 | 28 | ASTFieldDecl::ASTFieldDecl(ASTNameList *name_list, ASTTypeDecl *type_decl) 29 | : name_list(name_list), type_decl(type_decl) { } 30 | 31 | ASTFieldDeclList::ASTFieldDeclList(ASTFieldDecl *field_decl) { 32 | fielddeclList.clear(); 33 | fielddeclList.push_back(field_decl); 34 | } 35 | 36 | void ASTFieldDeclList::addFieldDecl(ASTFieldDecl *field_decl) { 37 | fielddeclList.push_back(field_decl); 38 | } 39 | 40 | ASTRecordTypeDecl::ASTRecordTypeDecl(ASTFieldDeclList *field_decl_list) 41 | : field_decl_list(field_decl_list) {} 42 | 43 | ASTTypePart::ASTTypePart(ASTTypeDeclList *type_decl_list) : type_decl_list_(type_decl_list) {} 44 | 45 | ASTTypeDefinition::ASTTypeDefinition(std::string id, ASTTypeDecl *type_decl) : id_(id), type_decl_(type_decl) {} 46 | 47 | ASTTypeDeclList::ASTTypeDeclList(ASTTypeDefinition *defi) { 48 | this->typeList.push_back(defi); 49 | } 50 | 51 | void ASTTypeDeclList::addASTTypeDefinition(ASTTypeDefinition *defi) { 52 | this->typeList.push_back(defi); 53 | } 54 | 55 | std::shared_ptr ASTType::Accept(Visitor *visitor) { return visitor->VisitASTType(this); } 56 | 57 | ASTType::TypeName ASTType::getTypeName() const { 58 | return type_name; 59 | } 60 | 61 | std::shared_ptr ASTSimpleTypeDecl::Accept(Visitor *visitor) { 62 | return visitor->VisitASTSimpleTypeDecl(this); 63 | } 64 | 65 | ASTType *ASTSimpleTypeDecl::getTypeName() const { 66 | return type_name; 67 | } 68 | 69 | const string &ASTSimpleTypeDecl::getDefinedId() const { 70 | return defined_id; 71 | } 72 | 73 | std::shared_ptr ASTArrayTypeDecl::Accept(Visitor *visitor) { 74 | return visitor->VisitASTArrayTypeDecl(this); 75 | } 76 | 77 | ASTSimpleTypeDecl *ASTArrayTypeDecl::getSimpleTypeDecl() const { 78 | return simple_type_decl; 79 | } 80 | 81 | ASTTypeDecl *ASTArrayTypeDecl::getTypeDecl() const { 82 | return type_decl; 83 | } 84 | 85 | std::shared_ptr ASTFieldDecl::Accept(Visitor *visitor) { return visitor->VisitASTFieldDecl(this); } 86 | 87 | ASTNameList *ASTFieldDecl::getNameList() const { 88 | return name_list; 89 | } 90 | 91 | ASTTypeDecl *ASTFieldDecl::getTypeDecl() const { 92 | return type_decl; 93 | } 94 | 95 | std::shared_ptr ASTFieldDeclList::Accept(Visitor *visitor) { 96 | return visitor->VisitASTFieldDeclList(this); 97 | } 98 | 99 | const vector &ASTFieldDeclList::getFielddeclList() const { 100 | return fielddeclList; 101 | } 102 | 103 | std::shared_ptr ASTRecordTypeDecl::Accept(Visitor *visitor) { 104 | return visitor->VisitASTRecordTypeDecl(this); 105 | } 106 | 107 | ASTFieldDeclList *ASTRecordTypeDecl::getFieldDeclList() const { 108 | return field_decl_list; 109 | } 110 | 111 | std::shared_ptr ASTTypeDefinition::Accept(Visitor *visitor) { 112 | return visitor->VisitASTTypeDefinition(this); 113 | } 114 | 115 | const string &ASTTypeDefinition::getId() const { 116 | return id_; 117 | } 118 | 119 | ASTTypeDecl *ASTTypeDefinition::getTypeDecl() const { 120 | return type_decl_; 121 | } 122 | 123 | std::shared_ptr ASTTypeDeclList::Accept(Visitor *visitor) { return visitor->VisitASTTypeDeclList(this); } 124 | 125 | const vector &ASTTypeDeclList::getTypeList() const { 126 | return typeList; 127 | } 128 | 129 | std::shared_ptr ASTTypePart::Accept(Visitor *visitor) { return visitor->VisitASTTypePart(this); } 130 | 131 | ASTTypeDeclList *ASTTypePart::getTypeDeclList() const { 132 | return type_decl_list_; 133 | } 134 | -------------------------------------------------------------------------------- /test/error.pas.dot: -------------------------------------------------------------------------------- 1 | digraph g { 2 | node_0->node_1; 3 | node_1->node_2; 4 | node_0->node_3; 5 | node_3->node_4; 6 | node_4->node_5; 7 | node_5->node_6; 8 | node_6->node_7; 9 | node_7->node_8; 10 | node_7->node_9; 11 | node_9->node_10; 12 | node_10->node_11; 13 | node_11->node_12; 14 | node_12->node_13; 15 | node_11->node_14; 16 | node_14->node_15; 17 | node_10->node_16; 18 | node_16->node_17; 19 | node_17->node_18; 20 | node_16->node_19; 21 | node_19->node_20; 22 | node_4->node_21; 23 | node_21->node_22; 24 | node_22->node_23; 25 | node_23->node_24; 26 | node_24->node_25; 27 | node_24->node_26; 28 | node_23->node_27; 29 | node_27->node_28; 30 | node_22->node_29; 31 | node_29->node_30; 32 | node_30->node_31; 33 | node_29->node_32; 34 | node_32->node_33; 35 | node_22->node_34; 36 | node_34->node_35; 37 | node_35->node_36; 38 | node_34->node_37; 39 | node_37->node_38; 40 | node_22->node_39; 41 | node_39->node_40; 42 | node_40->node_41; 43 | node_39->node_42; 44 | node_42->node_43; 45 | node_3->node_44; 46 | node_44->node_45; 47 | node_45->node_46; 48 | node_46->node_47; 49 | node_46->node_48; 50 | node_48->node_49; 51 | node_49->node_50; 52 | node_48->node_51; 53 | node_51->node_52; 54 | node_45->node_53; 55 | node_53->node_54; 56 | node_54->node_55; 57 | node_53->node_56; 58 | node_56->node_57; 59 | node_57->node_58; 60 | node_56->node_59; 61 | node_59->node_60; 62 | node_45->node_61; 63 | node_61->node_62; 64 | node_61->node_63; 65 | node_63->node_64; 66 | node_64->node_65; 67 | node_45->node_66; 68 | node_66->node_67; 69 | node_67->node_68; 70 | node_66->node_69; 71 | node_69->node_70; 72 | node_69->node_71; 73 | node_45->node_72; 74 | node_72->node_73; 75 | node_73->node_74; 76 | node_72->node_75; 77 | node_75->node_76; 78 | node_75->node_77; 79 | node_0[label="program\n[17, 4]"]; 80 | node_1[label="program_head\n[1, 14]"]; 81 | node_2[label="error"]; 82 | node_3[label="routine\n[17, 1]"]; 83 | node_4[label="routine_head\n[11, 1]"]; 84 | node_5[label="type_part\n[6, 1]"]; 85 | node_6[label="type_decl_list\n[5, 4]"]; 86 | node_7[label="type_definition\n[5, 4]"]; 87 | node_8[label="t"]; 88 | node_9[label="file_decl_list\n[5, 1]"]; 89 | node_10[label="field_decl_list\n[4, 12]"]; 90 | node_11[label="field_decl\n[3, 9]"]; 91 | node_12[label="name_list\n[3, 2]"]; 92 | node_13[label="x"]; 93 | node_14[label="simple_type_decl\n[3, 5]"]; 94 | node_15[label="Real"]; 95 | node_16[label="field_decl\n[4, 12]"]; 96 | node_17[label="name_list\n[4, 2]"]; 97 | node_18[label="y"]; 98 | node_19[label="simple_type_decl\n[4, 5]"]; 99 | node_20[label="Integer"]; 100 | node_21[label="var_part:\n[11, 1]"]; 101 | node_22[label="var_decl_list:\n[10, 6]"]; 102 | node_23[label="Var_decl:\n[7, 11]"]; 103 | node_24[label="name_list\n[7, 4]"]; 104 | node_25[label="a"]; 105 | node_26[label="b"]; 106 | node_27[label="simple_type_decl\n[7, 7]"]; 107 | node_28[label="Real"]; 108 | node_29[label="Var_decl:\n[8, 14]"]; 109 | node_30[label="name_list\n[8, 2]"]; 110 | node_31[label="c"]; 111 | node_32[label="simple_type_decl\n[8, 14]"]; 112 | node_33[label="wrongtype"]; 113 | node_34[label="Var_decl:\n[9, 12]"]; 114 | node_35[label="name_list\n[9, 2]"]; 115 | node_36[label="d"]; 116 | node_37[label="simple_type_decl\n[9, 5]"]; 117 | node_38[label="Integer"]; 118 | node_39[label="Var_decl:\n[10, 6]"]; 119 | node_40[label="name_list\n[10, 2]"]; 120 | node_41[label="e"]; 121 | node_42[label="simple_type_decl\n[10, 6]"]; 122 | node_43[label="t"]; 123 | node_44[label="routine_body\n[17, 1]"]; 124 | node_45[label="stmt_list\n[17, 1]"]; 125 | node_46[label="proc_stmt\n[12, 11]"]; 126 | node_47[label="read"]; 127 | node_48[label="expression_list\n[12, 11]"]; 128 | node_49[label="ID_expr\n[12, 8]"]; 129 | node_50[label="a"]; 130 | node_51[label="ID_expr\n[12, 11]"]; 131 | node_52[label="b"]; 132 | node_53[label="assign_stmt\n[13, 12]"]; 133 | node_54[label="ID_expr\n[0, 0]"]; 134 | node_55[label="d"]; 135 | node_56[label="binary_op_expr: PLUS\n[13, 12]"]; 136 | node_57[label="ID_expr\n[13, 9]"]; 137 | node_58[label="a"]; 138 | node_59[label="ID_expr\n[13, 12]"]; 139 | node_60[label="b"]; 140 | node_61[label="proc_stmt\n[14, 11]"]; 141 | node_62[label="writeln"]; 142 | node_63[label="expression_list\n[14, 11]"]; 143 | node_64[label="ID_expr\n[14, 11]"]; 144 | node_65[label="d"]; 145 | node_66[label="assign_stmt\n[15, 10]"]; 146 | node_67[label="ID_expr\n[0, 0]"]; 147 | node_68[label="d"]; 148 | node_69[label="property_expr:\n[15, 10]"]; 149 | node_70[label="e"]; 150 | node_71[label="x"]; 151 | node_72[label="assign_stmt\n[16, 10]"]; 152 | node_73[label="ID_expr\n[0, 0]"]; 153 | node_74[label="d"]; 154 | node_75[label="property_expr:\n[16, 10]"]; 155 | node_76[label="e"]; 156 | node_77[label="z"]; 157 | } -------------------------------------------------------------------------------- /src/generator/gen_sys_func.cpp: -------------------------------------------------------------------------------- 1 | #include "generator.h" 2 | #include "generator_result.hpp" 3 | #include 4 | #include 5 | 6 | llvm::Value* GenSysWrite(const std::vector> &args_list, bool new_line, Generator *generator) { 7 | static llvm::Function *llvm_printf = nullptr; 8 | if (llvm_printf == nullptr) { 9 | //register printf 10 | std::vector arg_types = {llvm::Type::getInt8PtrTy(generator->context)}; 11 | llvm::FunctionType *func_type = llvm::FunctionType::get( 12 | llvm::Type::getInt32Ty(generator->context), 13 | arg_types, 14 | true 15 | ); 16 | llvm::Function *func = llvm::Function::Create( 17 | func_type, 18 | llvm::Function::ExternalLinkage, 19 | "printf", 20 | &*(generator->module) 21 | ); 22 | func->setCallingConv(llvm::CallingConv::C); 23 | llvm_printf = func; 24 | } 25 | std::string format; 26 | std::vector printf_args; 27 | printf_args.emplace_back(nullptr); 28 | for (auto arg: args_list) { 29 | OurType::PascalType *tp = arg->getType(); 30 | if (tp->isIntegerTy()) { 31 | format += "%d"; 32 | printf_args.emplace_back(arg->getValue()); 33 | } 34 | else if (tp->isFloatingPointTy()) { 35 | format += "%lf"; 36 | printf_args.emplace_back(arg->getValue()); 37 | } 38 | else if (tp->isCharTy()) { 39 | format += "%c"; 40 | printf_args.emplace_back(arg->getValue()); 41 | } 42 | else if (tp->isStringTy()) { 43 | format += "%s"; 44 | printf_args.emplace_back(arg->getMem()); 45 | } else { 46 | std::cerr << "[write/writeln] Unsupported type" << std::endl; 47 | return nullptr; 48 | } 49 | } 50 | if (new_line) { 51 | format += "\n"; 52 | } 53 | printf_args[0] = generator->builder.CreateGlobalStringPtr(format, "printf_format"); 54 | return generator->builder.CreateCall(llvm_printf, printf_args, "call_printf"); 55 | } 56 | 57 | llvm::Value* GenSysRead(const std::vector> &args_list, bool new_line, Generator *generator) { 58 | static llvm::Function *llvm_scanf = nullptr; 59 | if (llvm_scanf == nullptr) { 60 | //register printf 61 | std::vector arg_types = {llvm::Type::getInt8PtrTy(generator->context)}; 62 | llvm::FunctionType *func_type = llvm::FunctionType::get( 63 | llvm::Type::getInt32Ty(generator->context), 64 | arg_types, 65 | true 66 | ); 67 | llvm::Function *func = llvm::Function::Create( 68 | func_type, 69 | llvm::Function::ExternalLinkage, 70 | "scanf", 71 | &*(generator->module) 72 | ); 73 | func->setCallingConv(llvm::CallingConv::C); 74 | llvm_scanf = func; 75 | } 76 | std::string format; 77 | std::vector scanf_args; 78 | scanf_args.emplace_back(nullptr); 79 | for (auto arg: args_list) { 80 | OurType::PascalType *tp = arg->getType(); 81 | if (tp->isIntegerTy()) { 82 | format += "%d"; 83 | } 84 | else if (tp->isFloatingPointTy()) { 85 | format += "%lf"; 86 | } 87 | else if (tp->isCharTy()) { 88 | format += "%c"; 89 | } 90 | else if (tp->isStringTy()) { 91 | format += "%s"; 92 | } else { 93 | std::cerr << "[read/readln] Unsupported type" << std::endl; 94 | return nullptr; 95 | } 96 | scanf_args.emplace_back(arg->getMem()); 97 | } 98 | if (new_line) { 99 | format += "%*[^\n]"; 100 | } 101 | scanf_args[0] = generator->builder.CreateGlobalStringPtr(format, "scanf_format"); 102 | llvm::Value* ret = generator->builder.CreateCall(llvm_scanf, scanf_args, "call_scanf"); 103 | if (new_line) { 104 | //consume \n 105 | generator->builder.CreateCall(llvm_scanf, generator->builder.CreateGlobalStringPtr("%*c", "scanf_newline"), "call_scanf"); 106 | } 107 | return ret; 108 | } 109 | bool Generator::isSysFunc(std::string id) { 110 | for (auto &ch: id) ch = tolower(ch); 111 | if (id == "write") return true; 112 | if (id == "writeln") return true; 113 | if (id == "read") return true; 114 | if (id == "readln") return true; 115 | } 116 | 117 | llvm::Value* Generator::genSysFunc(std::string id, const std::vector> &args_list) { 118 | for (auto &ch: id) ch = tolower(ch); 119 | if (id == "write") return GenSysWrite(args_list, false, this); 120 | if (id == "writeln") return GenSysWrite(args_list, true, this); 121 | if (id == "read") return GenSysRead(args_list, false, this); 122 | if (id == "readln") return GenSysRead(args_list, true, this); 123 | } 124 | -------------------------------------------------------------------------------- /test/hanoi.pas.ll: -------------------------------------------------------------------------------- 1 | ; ModuleID = 'pascal_module' 2 | source_filename = "pascal_module" 3 | 4 | @N = common global i32 0 5 | @printf_format = private unnamed_addr constant [3 x i8] c"%d\00" 6 | @0 = private unnamed_addr constant [3 x i8] c"->\00" 7 | @printf_format.1 = private unnamed_addr constant [3 x i8] c"%s\00" 8 | @printf_format.2 = private unnamed_addr constant [4 x i8] c"%d\0A\00" 9 | @printf_format.3 = private unnamed_addr constant [3 x i8] c"%d\00" 10 | @1 = private unnamed_addr constant [3 x i8] c"->\00" 11 | @printf_format.4 = private unnamed_addr constant [3 x i8] c"%s\00" 12 | @printf_format.5 = private unnamed_addr constant [4 x i8] c"%d\0A\00" 13 | @scanf_format = private unnamed_addr constant [3 x i8] c"%d\00" 14 | 15 | define i32 @main() { 16 | entry: 17 | br label %label_ 18 | 19 | label_: ; preds = %entry 20 | %0 = load i32, i32* @N 21 | %call_scanf = call i32 (i8*, ...) @scanf(i8* getelementptr inbounds ([3 x i8], [3 x i8]* @scanf_format, i32 0, i32 0), i32* @N) 22 | br label %label_1 23 | 24 | label_1: ; preds = %label_ 25 | %1 = load i32, i32* @N 26 | %"0_3" = alloca i32 27 | store i32 1, i32* %"0_3" 28 | %"0_4" = alloca i32 29 | store i32 3, i32* %"0_4" 30 | %"0_5" = alloca i32 31 | store i32 2, i32* %"0_5" 32 | call void @move(i32* %"0_3", i32* %"0_4", i32* %"0_5", i32* @N) 33 | ret i32 0 34 | } 35 | 36 | define void @move(i32*, i32*, i32*, i32*) { 37 | entry: 38 | %4 = load i32, i32* %0 39 | %a = alloca i32 40 | store i32 %4, i32* %a 41 | %5 = load i32, i32* %1 42 | %b = alloca i32 43 | store i32 %5, i32* %b 44 | %6 = load i32, i32* %2 45 | %c = alloca i32 46 | store i32 %6, i32* %c 47 | %7 = load i32, i32* %3 48 | %N = alloca i32 49 | store i32 %7, i32* %N 50 | br label %label_ 51 | 52 | label_: ; preds = %entry 53 | %8 = load i32, i32* %N 54 | %cmptmp = icmp eq i32 %8, 1 55 | br i1 %cmptmp, label %if_then, label %if_else 56 | 57 | if_then: ; preds = %label_ 58 | br label %label_1 59 | 60 | if_else: ; preds = %label_ 61 | br label %label_7 62 | 63 | if_cont: ; preds = %label_15, %label_5 64 | ret void 65 | 66 | label_1: ; preds = %if_then 67 | br label %label_2 68 | 69 | label_2: ; preds = %label_1 70 | %9 = load i32, i32* %a 71 | %call_printf = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([3 x i8], [3 x i8]* @printf_format, i32 0, i32 0), i32 %9) 72 | br label %label_3 73 | 74 | label_3: ; preds = %label_2 75 | %10 = load [3 x i8], [3 x i8]* @0 76 | %call_printf4 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([3 x i8], [3 x i8]* @printf_format.1, i32 0, i32 0), [3 x i8]* @0) 77 | br label %label_5 78 | 79 | label_5: ; preds = %label_3 80 | %11 = load i32, i32* %b 81 | %call_printf6 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @printf_format.2, i32 0, i32 0), i32 %11) 82 | br label %if_cont 83 | 84 | label_7: ; preds = %if_else 85 | br label %label_8 86 | 87 | label_8: ; preds = %label_7 88 | %12 = load i32, i32* %a 89 | %13 = load i32, i32* %c 90 | %14 = load i32, i32* %b 91 | %15 = load i32, i32* %N 92 | %subtmp = sub i32 %15, 1 93 | %"0_1" = alloca i32 94 | store i32 %subtmp, i32* %"0_1" 95 | call void @move(i32* %a, i32* %c, i32* %b, i32* %"0_1") 96 | br label %label_9 97 | 98 | label_9: ; preds = %label_8 99 | %16 = load i32, i32* %a 100 | %call_printf10 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([3 x i8], [3 x i8]* @printf_format.3, i32 0, i32 0), i32 %16) 101 | br label %label_11 102 | 103 | label_11: ; preds = %label_9 104 | %17 = load [3 x i8], [3 x i8]* @1 105 | %call_printf12 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([3 x i8], [3 x i8]* @printf_format.4, i32 0, i32 0), [3 x i8]* @1) 106 | br label %label_13 107 | 108 | label_13: ; preds = %label_11 109 | %18 = load i32, i32* %b 110 | %call_printf14 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @printf_format.5, i32 0, i32 0), i32 %18) 111 | br label %label_15 112 | 113 | label_15: ; preds = %label_13 114 | %19 = load i32, i32* %c 115 | %20 = load i32, i32* %b 116 | %21 = load i32, i32* %a 117 | %22 = load i32, i32* %N 118 | %subtmp16 = sub i32 %22, 1 119 | %"0_2" = alloca i32 120 | store i32 %subtmp16, i32* %"0_2" 121 | call void @move(i32* %c, i32* %b, i32* %a, i32* %"0_2") 122 | br label %if_cont 123 | } 124 | 125 | declare i32 @printf(i8*, ...) 126 | 127 | declare i32 @scanf(i8*, ...) 128 | -------------------------------------------------------------------------------- /src/ast/ast_type.h: -------------------------------------------------------------------------------- 1 | #ifndef OPC_AST_AST_TYPE_H 2 | #define OPC_AST_AST_TYPE_H 3 | 4 | #include "ast_base.h" 5 | #include "ast_value.h" 6 | 7 | class Generator; 8 | 9 | class Visitor; 10 | 11 | class ASTNode; 12 | 13 | class ASTType; 14 | 15 | class ASTTypeDecl; 16 | 17 | class ASTSimpleTypeDecl; 18 | 19 | class ASTConstValue; 20 | 21 | class ASTArrayTypeDecl; 22 | 23 | class ASTFieldDecl; 24 | 25 | class ASTFieldDeclList; 26 | 27 | class ASTRecordTypeDecl; 28 | 29 | class ASTTypeDefinition; 30 | 31 | class ASTTypeDeclList; 32 | 33 | class ASTTypePart; 34 | 35 | class ASTType : public ASTNode { 36 | public: 37 | enum class TypeName { 38 | INTEGER, REAL, BOOLEAN, CHAR, STRING 39 | }; 40 | 41 | ASTType(TypeName type_name); 42 | 43 | 44 | 45 | virtual std::shared_ptr Accept(Visitor *visitor); 46 | 47 | TypeName getTypeName() const; 48 | 49 | private: 50 | TypeName type_name; 51 | }; 52 | 53 | class ASTTypeDecl : public ASTNode { 54 | public: 55 | virtual std::shared_ptr Accept(Visitor *visitor) { return nullptr; } 56 | }; 57 | 58 | class ASTSimpleTypeDecl : public ASTTypeDecl { 59 | friend class Generator; 60 | public: 61 | enum class MyType { BUILTIN_TYPE, DEFINED_ID, VALUE_RANGE, ID_RANGE, ENUM }; 62 | 63 | ASTSimpleTypeDecl(ASTType *); // Now only implement the simple type. 64 | ASTSimpleTypeDecl(ASTConstValue *low, bool neg_low, ASTConstValue* high, bool neg_high); 65 | ASTSimpleTypeDecl(std::string low_name, std::string high_name); 66 | ASTSimpleTypeDecl(std::string defined_id); 67 | ASTSimpleTypeDecl(ASTNameList *name_list); 68 | 69 | virtual std::shared_ptr Accept(Visitor *visitor); 70 | 71 | ASTType *getTypeName() const; 72 | 73 | MyType my_type; 74 | 75 | private: 76 | ASTType *type_name; 77 | std::string defined_id; 78 | public: 79 | const std::string &getDefinedId() const; 80 | 81 | private: 82 | bool neg_low, neg_high; 83 | ASTConstValue *low, *high; 84 | std::string low_name, high_name; 85 | ASTNameList *name_list; 86 | 87 | friend class Generator; 88 | }; 89 | 90 | class ASTArrayTypeDecl : public ASTTypeDecl { 91 | public: 92 | ASTArrayTypeDecl(ASTSimpleTypeDecl *, ASTTypeDecl *); 93 | 94 | 95 | 96 | virtual std::shared_ptr Accept(Visitor *visitor); 97 | 98 | ASTSimpleTypeDecl *getSimpleTypeDecl() const; 99 | 100 | ASTTypeDecl *getTypeDecl() const; 101 | 102 | private: 103 | ASTSimpleTypeDecl *simple_type_decl; 104 | ASTTypeDecl *type_decl; 105 | }; 106 | 107 | class ASTFieldDecl : public ASTNode { 108 | public: 109 | ASTFieldDecl(ASTNameList *, ASTTypeDecl *); 110 | 111 | 112 | 113 | virtual std::shared_ptr Accept(Visitor *visitor); 114 | 115 | ASTNameList *getNameList() const; 116 | 117 | ASTTypeDecl *getTypeDecl() const; 118 | 119 | // void setBelongToRecord(bool _); 120 | private: 121 | ASTNameList *name_list; 122 | ASTTypeDecl *type_decl; 123 | bool belong_to_record = false; 124 | }; 125 | 126 | class ASTFieldDeclList : public ASTNode { 127 | public: 128 | ASTFieldDeclList(ASTFieldDecl *); 129 | 130 | void addFieldDecl(ASTFieldDecl *); 131 | 132 | virtual std::shared_ptr Accept(Visitor *visitor); 133 | 134 | const std::vector &getFielddeclList() const; 135 | 136 | // void setBelongToRecord(bool _); 137 | // void getBelongToRecord(); 138 | private: 139 | std::vector fielddeclList; 140 | bool belong_to_record = false; 141 | }; 142 | 143 | class ASTRecordTypeDecl : public ASTTypeDecl { 144 | public: 145 | ASTRecordTypeDecl(ASTFieldDeclList *); 146 | 147 | 148 | 149 | virtual std::shared_ptr Accept(Visitor *visitor); 150 | 151 | ASTFieldDeclList *getFieldDeclList() const; 152 | 153 | private: 154 | ASTFieldDeclList *field_decl_list; 155 | }; 156 | 157 | class ASTTypeDefinition : public ASTNode { 158 | public: 159 | ASTTypeDefinition(std::string, ASTTypeDecl *); 160 | 161 | 162 | 163 | virtual std::shared_ptr Accept(Visitor *visitor); 164 | 165 | const std::string &getId() const; 166 | 167 | ASTTypeDecl *getTypeDecl() const; 168 | 169 | private: 170 | std::string id_; 171 | ASTTypeDecl *type_decl_; 172 | }; 173 | 174 | class ASTTypeDeclList : public ASTNode { 175 | public: 176 | ASTTypeDeclList(ASTTypeDefinition *); 177 | 178 | void addASTTypeDefinition(ASTTypeDefinition *); 179 | 180 | 181 | 182 | virtual std::shared_ptr Accept(Visitor *visitor); 183 | 184 | const std::vector &getTypeList() const; 185 | 186 | private: 187 | std::vector typeList; 188 | }; 189 | 190 | class ASTTypePart : public ASTNode { 191 | public: 192 | ASTTypePart(ASTTypeDeclList *); 193 | 194 | 195 | virtual std::shared_ptr Accept(Visitor *visitor); 196 | 197 | ASTTypeDeclList *getTypeDeclList() const; 198 | 199 | private: 200 | ASTTypeDeclList *type_decl_list_; 201 | 202 | }; 203 | 204 | #endif //OPC_AST_AST_TYPE_H -------------------------------------------------------------------------------- /src/visitor.h: -------------------------------------------------------------------------------- 1 | #ifndef OPC_VISITOR_H 2 | #define OPC_VISITOR_H 3 | 4 | #include 5 | #include 6 | #include "ast/ast.h" 7 | using namespace std; 8 | 9 | class VisitorResult { 10 | 11 | }; 12 | 13 | class Visitor { 14 | 15 | public: 16 | virtual ~Visitor() = default; 17 | 18 | virtual shared_ptr VisitASTNode(ASTNode *node) = 0; 19 | 20 | virtual shared_ptr VisitASTNameList(ASTNameList *node) = 0; 21 | 22 | virtual shared_ptr VisitASTExpressionList(ASTExpressionList *node) = 0; 23 | 24 | virtual shared_ptr VisitASTBinaryExpr(ASTBinaryExpr *node) = 0; 25 | 26 | virtual shared_ptr VisitASTUnaryExpr(ASTUnaryExpr *node) = 0; 27 | 28 | virtual shared_ptr VisitASTPropExpr(ASTPropExpr *node) = 0; 29 | 30 | virtual shared_ptr VisitASTConstValueExpr(ASTConstValueExpr *node) = 0; 31 | 32 | virtual shared_ptr VisitASTFuncCall(ASTFuncCall *node) = 0; 33 | 34 | virtual shared_ptr VisitASTIDExpr(ASTIDExpr *node) = 0; 35 | 36 | virtual shared_ptr VisitASTArrayExpr(ASTArrayExpr *node) = 0; 37 | 38 | virtual shared_ptr VisitASTProgramHead(ASTProgramHead *node) = 0; 39 | 40 | virtual shared_ptr VisitASTRoutineHead(ASTRoutineHead *node) = 0; 41 | 42 | virtual shared_ptr VisitASTRoutineBody(ASTRoutineBody *node) = 0; 43 | 44 | virtual shared_ptr VisitASTRoutine(ASTRoutine *node) = 0; 45 | 46 | virtual shared_ptr VisitASTProgram(ASTProgram *node) = 0; 47 | 48 | virtual shared_ptr VisitASTRoutinePart(ASTRoutinePart *node) = 0; 49 | 50 | virtual shared_ptr VisitASTFuncProcBase(ASTFuncProcBase *node) = 0; 51 | 52 | virtual shared_ptr VisitASTFunctionHead(ASTFunctionHead *node) = 0; 53 | 54 | virtual shared_ptr VisitASTProcedureHead(ASTProcedureHead *node) = 0; 55 | 56 | virtual shared_ptr VisitASTParaDeclList(ASTParaDeclList *node) = 0; 57 | 58 | virtual shared_ptr VisitASTParaTypeList(ASTParaTypeList *node) = 0; 59 | 60 | virtual shared_ptr VisitASTVarParaList(ASTVarParaList *node) = 0; 61 | 62 | virtual shared_ptr VisitASTValParaList(ASTValParaList *node) = 0; 63 | 64 | virtual shared_ptr VisitASTNonLabelStmt(ASTNonLabelStmt *node) = 0; 65 | 66 | virtual shared_ptr VisitASTStmt(ASTStmt *node) = 0; 67 | 68 | virtual shared_ptr VisitASTStmtList(ASTStmtList *node) = 0; 69 | 70 | virtual shared_ptr VisitASTAssignStmt(ASTAssignStmt *node) = 0; 71 | 72 | virtual shared_ptr VisitASTProcStmt(ASTProcStmt *node) = 0; 73 | 74 | virtual shared_ptr VisitASTIfStmt(ASTIfStmt *node) = 0; 75 | 76 | virtual shared_ptr VisitASTElseClause(ASTElseClause *node) = 0; 77 | 78 | virtual shared_ptr VisitASTRepeatStmt(ASTRepeatStmt *node) = 0; 79 | 80 | virtual shared_ptr VisitASTWhileStmt(ASTWhileStmt *node) = 0; 81 | 82 | virtual shared_ptr VisitASTForStmt(ASTForStmt *node) = 0; 83 | 84 | virtual shared_ptr VisitASTCaseStmt(ASTCaseStmt *node) = 0; 85 | 86 | virtual shared_ptr VisitASTCaseExprList(ASTCaseExprList *node) = 0; 87 | 88 | virtual shared_ptr VisitASTCaseExpr(ASTCaseExpr *node) = 0; 89 | 90 | virtual shared_ptr VisitASTGotoStmt(ASTGotoStmt *node) = 0; 91 | 92 | virtual shared_ptr VisitASTType(ASTType *node) = 0; 93 | 94 | virtual shared_ptr VisitASTSimpleTypeDecl(ASTSimpleTypeDecl *node) = 0; 95 | 96 | virtual shared_ptr VisitASTArrayTypeDecl(ASTArrayTypeDecl *node) = 0; 97 | 98 | virtual shared_ptr VisitASTFieldDecl(ASTFieldDecl *node) = 0; 99 | 100 | virtual shared_ptr VisitASTFieldDeclList(ASTFieldDeclList *node) = 0; 101 | 102 | virtual shared_ptr VisitASTRecordTypeDecl(ASTRecordTypeDecl *node) = 0; 103 | 104 | virtual shared_ptr VisitASTTypeDefinition(ASTTypeDefinition *node) = 0; 105 | 106 | virtual shared_ptr VisitASTTypeDeclList(ASTTypeDeclList *node) = 0; 107 | 108 | virtual shared_ptr VisitASTTypePart(ASTTypePart *node) = 0; 109 | 110 | virtual shared_ptr VisitASTConstValue(ASTConstValue *node) = 0; 111 | 112 | virtual shared_ptr VisitASTConstExprList(ASTConstExprList *node) = 0; 113 | 114 | virtual shared_ptr VisitASTConstExpr(ASTConstExpr *node) = 0; 115 | 116 | virtual shared_ptr VisitASTConstPart(ASTConstPart *node) = 0; 117 | 118 | virtual shared_ptr VisitASTVarPart(ASTVarPart *node) = 0; 119 | 120 | virtual shared_ptr VisitASTVarDeclList(ASTVarDeclList *node) = 0; 121 | 122 | virtual shared_ptr VisitASTVarDecl(ASTVarDecl *node) = 0; 123 | 124 | virtual shared_ptr VisitASTExitStmt(ASTExitStmt *node) = 0; 125 | 126 | virtual shared_ptr VisitASTBreakStmt(ASTBreakStmt *node) = 0; 127 | 128 | virtual shared_ptr VisitASTFunctionDecl(ASTFunctionDecl *node) = 0; 129 | 130 | virtual shared_ptr VisitASTProcedureDecl(ASTProcedureDecl *node) = 0; 131 | }; 132 | 133 | 134 | #endif // OPC_VISITOR_H 135 | -------------------------------------------------------------------------------- /test/ten.pas.ll: -------------------------------------------------------------------------------- 1 | ; ModuleID = 'pascal_module' 2 | source_filename = "pascal_module" 3 | 4 | @a = common global double 0.000000e+00 5 | @s = common global double 0.000000e+00 6 | @max = common global double 0.000000e+00 7 | @min = common global double 0.000000e+00 8 | @avg = common global double 0.000000e+00 9 | @i = common global i32 0 10 | @0 = private unnamed_addr constant [14 x i8] c"please input:\00" 11 | @printf_format = private unnamed_addr constant [3 x i8] c"%s\00" 12 | @scanf_format = private unnamed_addr constant [4 x i8] c"%lf\00" 13 | @scanf_format.1 = private unnamed_addr constant [4 x i8] c"%lf\00" 14 | @printf_format.2 = private unnamed_addr constant [5 x i8] c"%lf\0A\00" 15 | 16 | define i32 @main() { 17 | entry: 18 | br label %label_ 19 | 20 | label_: ; preds = %entry 21 | %0 = load [14 x i8], [14 x i8]* @0 22 | %call_printf = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([3 x i8], [3 x i8]* @printf_format, i32 0, i32 0), [14 x i8]* @0) 23 | br label %label_1 24 | 25 | label_1: ; preds = %label_ 26 | %1 = load double, double* @a 27 | %call_scanf = call i32 (i8*, ...) @scanf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @scanf_format, i32 0, i32 0), double* @a) 28 | br label %label_2 29 | 30 | label_2: ; preds = %label_1 31 | %2 = load double, double* @s 32 | %3 = load double, double* @a 33 | store double %3, double* @s 34 | br label %label_3 35 | 36 | label_3: ; preds = %label_2 37 | %4 = load double, double* @max 38 | %5 = load double, double* @a 39 | store double %5, double* @max 40 | br label %label_4 41 | 42 | label_4: ; preds = %label_3 43 | %6 = load double, double* @min 44 | %7 = load double, double* @a 45 | store double %7, double* @min 46 | br label %label_5 47 | 48 | label_5: ; preds = %label_4 49 | br label %for_start 50 | 51 | for_start: ; preds = %label_5 52 | %8 = load i32, i32* @i 53 | store i32 2, i32* @i 54 | br label %for_body 55 | 56 | for_body: ; preds = %for_cond, %for_start 57 | br label %label_6 58 | 59 | for_cond: ; preds = %if_cont 60 | %9 = load i32, i32* @i 61 | %10 = load i32, i32* @i 62 | %addtmp = add i32 %10, 1 63 | store i32 %addtmp, i32* @i 64 | %11 = load i32, i32* @i 65 | %cmptmp = icmp sgt i32 %11, 10 66 | br i1 %cmptmp, label %for_end, label %for_body 67 | 68 | for_end: ; preds = %for_cond 69 | br label %label_18 70 | 71 | label_6: ; preds = %for_body 72 | br label %label_7 73 | 74 | label_7: ; preds = %label_6 75 | %12 = load double, double* @a 76 | %call_scanf8 = call i32 (i8*, ...) @scanf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @scanf_format.1, i32 0, i32 0), double* @a) 77 | br label %label_9 78 | 79 | label_9: ; preds = %label_7 80 | %13 = load double, double* @s 81 | %14 = load double, double* @s 82 | %15 = load double, double* @a 83 | %addftmp = fadd double %14, %15 84 | store double %addftmp, double* @s 85 | br label %label_10 86 | 87 | label_10: ; preds = %label_9 88 | %16 = load double, double* @a 89 | %17 = load double, double* @max 90 | %cmpftmp = fcmp ogt double %16, %17 91 | br i1 %cmpftmp, label %if_then, label %if_else 92 | 93 | if_then: ; preds = %label_10 94 | br label %label_11 95 | 96 | if_else: ; preds = %label_10 97 | br label %label_12 98 | 99 | if_cont: ; preds = %if_cont15, %label_11 100 | br label %for_cond 101 | 102 | label_11: ; preds = %if_then 103 | %18 = load double, double* @max 104 | %19 = load double, double* @a 105 | store double %19, double* @max 106 | br label %if_cont 107 | 108 | label_12: ; preds = %if_else 109 | %20 = load double, double* @a 110 | %21 = load double, double* @min 111 | %cmpftmp16 = fcmp olt double %20, %21 112 | br i1 %cmpftmp16, label %if_then13, label %if_else14 113 | 114 | if_then13: ; preds = %label_12 115 | br label %label_17 116 | 117 | if_else14: ; preds = %label_12 118 | br label %if_cont15 119 | 120 | if_cont15: ; preds = %if_else14, %label_17 121 | br label %if_cont 122 | 123 | label_17: ; preds = %if_then13 124 | %22 = load double, double* @min 125 | %23 = load double, double* @a 126 | store double %23, double* @min 127 | br label %if_cont15 128 | 129 | label_18: ; preds = %for_end 130 | %24 = load double, double* @avg 131 | %25 = load double, double* @s 132 | %26 = load i32, i32* @i 133 | %27 = uitofp i32 %26 to double 134 | %divftmp = fdiv double %25, %27 135 | store double %divftmp, double* @avg 136 | br label %label_19 137 | 138 | label_19: ; preds = %label_18 139 | %28 = load double, double* @avg 140 | %call_printf20 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([5 x i8], [5 x i8]* @printf_format.2, i32 0, i32 0), double %28) 141 | ret i32 0 142 | } 143 | 144 | declare i32 @printf(i8*, ...) 145 | 146 | declare i32 @scanf(i8*, ...) 147 | -------------------------------------------------------------------------------- /src/vis/graph_generator.h: -------------------------------------------------------------------------------- 1 | #ifndef OPC_AST_GRAPH_GENERATOR_H 2 | #define OPC_AST_GRAPH_GENERATOR_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include "../visitor.h" 8 | 9 | class GraphGenerator : public Visitor { 10 | private: 11 | int id_cnt_ = 0; 12 | std::stack stk_; 13 | std::vector nodes_; 14 | std::vector edges_; 15 | 16 | public: 17 | GraphGenerator() = default; 18 | 19 | ~GraphGenerator() = default; 20 | 21 | void AddNode(std::string label, int line, int col); 22 | 23 | void AddValue(std::string value_type, std::string content); 24 | 25 | void AddIdentifier(std::string content); 26 | 27 | void Pop(); 28 | 29 | void Save(std::string path); 30 | 31 | virtual shared_ptr VisitASTNode(ASTNode *node) ; 32 | 33 | virtual shared_ptr VisitASTNameList(ASTNameList *node) ; 34 | 35 | virtual shared_ptr VisitASTExpressionList(ASTExpressionList *node) ; 36 | 37 | virtual shared_ptr VisitASTBinaryExpr(ASTBinaryExpr *node) ; 38 | 39 | virtual shared_ptr VisitASTUnaryExpr(ASTUnaryExpr *node) ; 40 | 41 | virtual shared_ptr VisitASTPropExpr(ASTPropExpr *node) ; 42 | 43 | virtual shared_ptr VisitASTConstValueExpr(ASTConstValueExpr *node) ; 44 | 45 | virtual shared_ptr VisitASTFuncCall(ASTFuncCall *node) ; 46 | 47 | virtual shared_ptr VisitASTIDExpr(ASTIDExpr *node) ; 48 | 49 | virtual shared_ptr VisitASTArrayExpr(ASTArrayExpr *node) ; 50 | 51 | virtual shared_ptr VisitASTProgramHead(ASTProgramHead *node) ; 52 | 53 | virtual shared_ptr VisitASTRoutineHead(ASTRoutineHead *node) ; 54 | 55 | virtual shared_ptr VisitASTRoutineBody(ASTRoutineBody *node) ; 56 | 57 | virtual shared_ptr VisitASTRoutine(ASTRoutine *node) ; 58 | 59 | virtual shared_ptr VisitASTProgram(ASTProgram *node) ; 60 | 61 | virtual shared_ptr VisitASTRoutinePart(ASTRoutinePart *node) ; 62 | 63 | virtual shared_ptr VisitASTFuncProcBase(ASTFuncProcBase *node) ; 64 | 65 | virtual shared_ptr VisitASTFunctionHead(ASTFunctionHead *node) ; 66 | 67 | virtual shared_ptr VisitASTProcedureHead(ASTProcedureHead *node) ; 68 | 69 | virtual shared_ptr VisitASTParaDeclList(ASTParaDeclList *node) ; 70 | 71 | virtual shared_ptr VisitASTParaTypeList(ASTParaTypeList *node) ; 72 | 73 | virtual shared_ptr VisitASTVarParaList(ASTVarParaList *node) ; 74 | 75 | virtual shared_ptr VisitASTValParaList(ASTValParaList *node) ; 76 | 77 | virtual shared_ptr VisitASTNonLabelStmt(ASTNonLabelStmt *node) ; 78 | 79 | virtual shared_ptr VisitASTStmt(ASTStmt *node) ; 80 | 81 | virtual shared_ptr VisitASTStmtList(ASTStmtList *node) ; 82 | 83 | virtual shared_ptr VisitASTAssignStmt(ASTAssignStmt *node) ; 84 | 85 | virtual shared_ptr VisitASTProcStmt(ASTProcStmt *node) ; 86 | 87 | virtual shared_ptr VisitASTIfStmt(ASTIfStmt *node) ; 88 | 89 | virtual shared_ptr VisitASTElseClause(ASTElseClause *node) ; 90 | 91 | virtual shared_ptr VisitASTRepeatStmt(ASTRepeatStmt *node) ; 92 | 93 | virtual shared_ptr VisitASTWhileStmt(ASTWhileStmt *node) ; 94 | 95 | virtual shared_ptr VisitASTForStmt(ASTForStmt *node) ; 96 | 97 | virtual shared_ptr VisitASTCaseStmt(ASTCaseStmt *node) ; 98 | 99 | virtual shared_ptr VisitASTCaseExprList(ASTCaseExprList *node) ; 100 | 101 | virtual shared_ptr VisitASTCaseExpr(ASTCaseExpr *node) ; 102 | 103 | virtual shared_ptr VisitASTGotoStmt(ASTGotoStmt *node) ; 104 | 105 | virtual shared_ptr VisitASTType(ASTType *node) ; 106 | 107 | virtual shared_ptr VisitASTSimpleTypeDecl(ASTSimpleTypeDecl *node) ; 108 | 109 | virtual shared_ptr VisitASTArrayTypeDecl(ASTArrayTypeDecl *node) ; 110 | 111 | virtual shared_ptr VisitASTFieldDecl(ASTFieldDecl *node) ; 112 | 113 | virtual shared_ptr VisitASTFieldDeclList(ASTFieldDeclList *node) ; 114 | 115 | virtual shared_ptr VisitASTRecordTypeDecl(ASTRecordTypeDecl *node) ; 116 | 117 | virtual shared_ptr VisitASTTypeDefinition(ASTTypeDefinition *node) ; 118 | 119 | virtual shared_ptr VisitASTTypeDeclList(ASTTypeDeclList *node) ; 120 | 121 | virtual shared_ptr VisitASTTypePart(ASTTypePart *node) ; 122 | 123 | virtual shared_ptr VisitASTConstValue(ASTConstValue *node) ; 124 | 125 | virtual shared_ptr VisitASTConstExprList(ASTConstExprList *node) ; 126 | 127 | virtual shared_ptr VisitASTConstExpr(ASTConstExpr *node) ; 128 | 129 | virtual shared_ptr VisitASTConstPart(ASTConstPart *node) ; 130 | 131 | virtual shared_ptr VisitASTVarPart(ASTVarPart *node) ; 132 | 133 | virtual shared_ptr VisitASTVarDeclList(ASTVarDeclList *node) ; 134 | 135 | virtual shared_ptr VisitASTVarDecl(ASTVarDecl *node) ; 136 | 137 | virtual shared_ptr VisitASTExitStmt(ASTExitStmt *node) ; 138 | 139 | virtual shared_ptr VisitASTBreakStmt(ASTBreakStmt *node) ; 140 | 141 | virtual shared_ptr VisitASTFunctionDecl(ASTFunctionDecl *node); 142 | 143 | virtual shared_ptr VisitASTProcedureDecl(ASTProcedureDecl *node); 144 | }; 145 | 146 | #endif -------------------------------------------------------------------------------- /src/ast/ast_stmt.cpp: -------------------------------------------------------------------------------- 1 | #include "ast_stmt.h" 2 | #include "../visitor.h" 3 | 4 | #include 5 | 6 | ASTStmtList::ASTStmtList() { 7 | stmt_list.clear(); 8 | } 9 | 10 | void ASTStmtList::addStmt(ASTStmt *stmt) { stmt_list.push_back(stmt); } 11 | 12 | ASTStmt::ASTStmt(ASTNonLabelStmt *non_label_stmt, std::string label) 13 | : non_label_stmt(non_label_stmt), label(label) {} 14 | 15 | ASTAssignStmt::ASTAssignStmt(ASTExpr *expr1, ASTExpr *expr2) 16 | : expr1(expr1), expr2(expr2) {}; 17 | 18 | ASTProcStmt::ASTProcStmt(std::string id, ASTExpressionList *expr_list) 19 | : id(id), expr_list(expr_list) {} 20 | 21 | ASTIfStmt::ASTIfStmt(ASTExpr *expr, ASTStmt *stmt, 22 | ASTElseClause *else_clause = nullptr) 23 | : expr(expr), stmt(stmt), else_clause(else_clause) {} 24 | 25 | ASTElseClause::ASTElseClause(ASTStmt *stmt) : stmt(stmt) {} 26 | 27 | ASTRepeatStmt::ASTRepeatStmt(ASTStmtList *stmt_list, ASTExpr *expr) 28 | : stmt_list_(stmt_list), expr_(expr) {} 29 | 30 | ASTWhileStmt::ASTWhileStmt(ASTExpr *expr, ASTStmt *stmt) 31 | : expr_(expr), stmt_(stmt) {} 32 | 33 | ASTForStmt::ASTForStmt(std::string id, ASTExpr *for_expr, ForDir dir, 34 | ASTExpr *to_expr, ASTStmt *stmt) 35 | : id_(id), for_expr_(for_expr), dir_(dir), to_expr_(to_expr), stmt_(stmt) {} 36 | 37 | ASTCaseStmt::ASTCaseStmt(ASTExpr *expr, ASTCaseExprList *case_expr_list) 38 | : expr_(expr), case_expr_list_(case_expr_list) {} 39 | 40 | ASTCaseExprList::ASTCaseExprList() {} 41 | 42 | void ASTCaseExprList::add_case_expr(ASTCaseExpr *expr) { 43 | this->case_expr_list_.push_back(expr); 44 | } 45 | 46 | ASTCaseExpr::ASTCaseExpr(ASTExpr *expr, ASTStmt *stmt) 47 | : expr_(expr), stmt_(stmt) {} 48 | 49 | ASTGotoStmt::ASTGotoStmt(std::string label) : label_(label) {} 50 | 51 | std::shared_ptr ASTStmt::Accept(Visitor *visitor) { return visitor->VisitASTStmt(this); } 52 | 53 | const string &ASTStmt::getLabel() const { 54 | return label; 55 | } 56 | 57 | ASTNonLabelStmt *ASTStmt::getNonLabelStmt() const { 58 | return non_label_stmt; 59 | } 60 | 61 | std::shared_ptr ASTStmtList::Accept(Visitor *visitor) { return visitor->VisitASTStmtList(this); } 62 | 63 | const vector &ASTStmtList::getStmtList() const { 64 | return stmt_list; 65 | } 66 | 67 | std::shared_ptr ASTAssignStmt::Accept(Visitor *visitor) { return visitor->VisitASTAssignStmt(this); } 68 | 69 | ASTExpr *ASTAssignStmt::getExpr1() const { 70 | return expr1; 71 | } 72 | 73 | ASTExpr *ASTAssignStmt::getExpr2() const { 74 | return expr2; 75 | } 76 | 77 | std::shared_ptr ASTProcStmt::Accept(Visitor *visitor) { return visitor->VisitASTProcStmt(this); } 78 | 79 | const string &ASTProcStmt::getId() const { 80 | return id; 81 | } 82 | 83 | ASTExpressionList *ASTProcStmt::getExprList() const { 84 | return expr_list; 85 | } 86 | 87 | std::shared_ptr ASTIfStmt::Accept(Visitor *visitor) { return visitor->VisitASTIfStmt(this); } 88 | 89 | ASTExpr *ASTIfStmt::getExpr() const { 90 | return expr; 91 | } 92 | 93 | ASTStmt *ASTIfStmt::getStmt() const { 94 | return stmt; 95 | } 96 | 97 | ASTElseClause *ASTIfStmt::getElseClause() const { 98 | return else_clause; 99 | } 100 | 101 | std::shared_ptr ASTElseClause::Accept(Visitor *visitor) { return visitor->VisitASTElseClause(this); } 102 | 103 | ASTStmt *ASTElseClause::getStmt() const { 104 | return stmt; 105 | } 106 | 107 | std::shared_ptr ASTRepeatStmt::Accept(Visitor *visitor) { return visitor->VisitASTRepeatStmt(this); } 108 | 109 | ASTStmtList *ASTRepeatStmt::getStmtList() const { 110 | return stmt_list_; 111 | } 112 | 113 | ASTExpr *ASTRepeatStmt::getExpr() const { 114 | return expr_; 115 | } 116 | 117 | std::shared_ptr ASTWhileStmt::Accept(Visitor *visitor) { return visitor->VisitASTWhileStmt(this); } 118 | 119 | ASTExpr *ASTWhileStmt::getExpr() const { 120 | return expr_; 121 | } 122 | 123 | ASTStmt *ASTWhileStmt::getStmt() const { 124 | return stmt_; 125 | } 126 | 127 | std::shared_ptr ASTForStmt::Accept(Visitor *visitor) { return visitor->VisitASTForStmt(this); } 128 | 129 | const string &ASTForStmt::getId() const { 130 | return id_; 131 | } 132 | 133 | ASTExpr *ASTForStmt::getForExpr() const { 134 | return for_expr_; 135 | } 136 | 137 | ASTExpr *ASTForStmt::getToExpr() const { 138 | return to_expr_; 139 | } 140 | 141 | ASTForStmt::ForDir ASTForStmt::getDir() const { 142 | return dir_; 143 | } 144 | 145 | ASTStmt *ASTForStmt::getStmt() const { 146 | return stmt_; 147 | } 148 | 149 | std::shared_ptr ASTCaseStmt::Accept(Visitor *visitor) { return visitor->VisitASTCaseStmt(this); } 150 | 151 | ASTExpr *ASTCaseStmt::getExpr() const { 152 | return expr_; 153 | } 154 | 155 | ASTCaseExprList *ASTCaseStmt::getCaseExprList() const { 156 | return case_expr_list_; 157 | } 158 | 159 | std::shared_ptr ASTCaseExprList::Accept(Visitor *visitor) { return visitor->VisitASTCaseExprList(this); } 160 | 161 | const vector &ASTCaseExprList::getCaseExprList() const { 162 | return case_expr_list_; 163 | } 164 | 165 | std::shared_ptr ASTCaseExpr::Accept(Visitor *visitor) { return visitor->VisitASTCaseExpr(this); } 166 | 167 | ASTExpr *ASTCaseExpr::getExpr() const { 168 | return expr_; 169 | } 170 | 171 | ASTStmt *ASTCaseExpr::getStmt() const { 172 | return stmt_; 173 | } 174 | 175 | std::shared_ptr ASTGotoStmt::Accept(Visitor *visitor) { return visitor->VisitASTGotoStmt(this); } 176 | 177 | const string &ASTGotoStmt::getLabel() const { 178 | return label_; 179 | } 180 | 181 | ASTExpr *ASTExitStmt::getExpr() const { 182 | return expr_; 183 | } 184 | 185 | ASTExitStmt::ASTExitStmt(ASTExpr *expr) : expr_(expr) {} 186 | 187 | std::shared_ptr ASTExitStmt::Accept(Visitor *visitor) { 188 | return visitor->VisitASTExitStmt(this); 189 | } 190 | 191 | 192 | std::shared_ptr ASTBreakStmt::Accept(Visitor *visitor) { 193 | return visitor->VisitASTBreakStmt(this); 194 | } 195 | -------------------------------------------------------------------------------- /test/myten.pas.ll: -------------------------------------------------------------------------------- 1 | ; ModuleID = 'pascal_module' 2 | source_filename = "pascal_module" 3 | 4 | @a = common global double 0.000000e+00 5 | @s = common global double 0.000000e+00 6 | @max = common global double 0.000000e+00 7 | @min = common global double 0.000000e+00 8 | @avg = common global double 0.000000e+00 9 | @i = common global i32 0 10 | @0 = private unnamed_addr constant [14 x i8] c"please input:\00" 11 | @printf_format = private unnamed_addr constant [3 x i8] c"%s\00" 12 | @scanf_format = private unnamed_addr constant [4 x i8] c"%lf\00" 13 | @printf_format.1 = private unnamed_addr constant [4 x i8] c"%d\0A\00" 14 | @printf_format.2 = private unnamed_addr constant [5 x i8] c"%lf\0A\00" 15 | @scanf_format.3 = private unnamed_addr constant [4 x i8] c"%lf\00" 16 | @printf_format.4 = private unnamed_addr constant [5 x i8] c"%lf\0A\00" 17 | 18 | define i32 @main() { 19 | entry: 20 | br label %label_ 21 | 22 | label_: ; preds = %entry 23 | %0 = load [14 x i8], [14 x i8]* @0 24 | %call_printf = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([3 x i8], [3 x i8]* @printf_format, i32 0, i32 0), [14 x i8]* @0) 25 | br label %label_1 26 | 27 | label_1: ; preds = %label_ 28 | %1 = load double, double* @a 29 | %call_scanf = call i32 (i8*, ...) @scanf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @scanf_format, i32 0, i32 0), double* @a) 30 | br label %label_2 31 | 32 | label_2: ; preds = %label_1 33 | %2 = load double, double* @s 34 | %3 = load double, double* @a 35 | store double %3, double* @s 36 | br label %label_3 37 | 38 | label_3: ; preds = %label_2 39 | %4 = load double, double* @max 40 | %5 = load double, double* @a 41 | store double %5, double* @max 42 | br label %label_4 43 | 44 | label_4: ; preds = %label_3 45 | %6 = load double, double* @min 46 | %7 = load double, double* @a 47 | store double %7, double* @min 48 | br label %label_5 49 | 50 | label_5: ; preds = %label_4 51 | br label %for_start 52 | 53 | for_start: ; preds = %label_5 54 | %8 = load i32, i32* @i 55 | store i32 2, i32* @i 56 | br label %for_body 57 | 58 | for_body: ; preds = %for_cond, %for_start 59 | br label %label_6 60 | 61 | for_cond: ; preds = %if_cont 62 | %9 = load i32, i32* @i 63 | %10 = load i32, i32* @i 64 | %addtmp = add i32 %10, 1 65 | store i32 %addtmp, i32* @i 66 | %11 = load i32, i32* @i 67 | %cmptmp = icmp sgt i32 %11, 5 68 | br i1 %cmptmp, label %for_end, label %for_body 69 | 70 | for_end: ; preds = %for_cond 71 | br label %label_22 72 | 73 | label_6: ; preds = %for_body 74 | br label %label_7 75 | 76 | label_7: ; preds = %label_6 77 | %12 = load i32, i32* @i 78 | %call_printf8 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @printf_format.1, i32 0, i32 0), i32 %12) 79 | br label %label_9 80 | 81 | label_9: ; preds = %label_7 82 | %13 = load double, double* @a 83 | %call_printf10 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([5 x i8], [5 x i8]* @printf_format.2, i32 0, i32 0), double %13) 84 | br label %label_11 85 | 86 | label_11: ; preds = %label_9 87 | %14 = load double, double* @a 88 | %call_scanf12 = call i32 (i8*, ...) @scanf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @scanf_format.3, i32 0, i32 0), double* @a) 89 | br label %label_13 90 | 91 | label_13: ; preds = %label_11 92 | %15 = load double, double* @s 93 | %16 = load double, double* @s 94 | %17 = load double, double* @a 95 | %addftmp = fadd double %16, %17 96 | store double %addftmp, double* @s 97 | br label %label_14 98 | 99 | label_14: ; preds = %label_13 100 | %18 = load double, double* @a 101 | %19 = load double, double* @max 102 | %cmpftmp = fcmp ogt double %18, %19 103 | br i1 %cmpftmp, label %if_then, label %if_else 104 | 105 | if_then: ; preds = %label_14 106 | br label %label_15 107 | 108 | if_else: ; preds = %label_14 109 | br label %label_16 110 | 111 | if_cont: ; preds = %if_cont19, %label_15 112 | br label %for_cond 113 | 114 | label_15: ; preds = %if_then 115 | %20 = load double, double* @max 116 | %21 = load double, double* @a 117 | store double %21, double* @max 118 | br label %if_cont 119 | 120 | label_16: ; preds = %if_else 121 | %22 = load double, double* @a 122 | %23 = load double, double* @min 123 | %cmpftmp20 = fcmp olt double %22, %23 124 | br i1 %cmpftmp20, label %if_then17, label %if_else18 125 | 126 | if_then17: ; preds = %label_16 127 | br label %label_21 128 | 129 | if_else18: ; preds = %label_16 130 | br label %if_cont19 131 | 132 | if_cont19: ; preds = %if_else18, %label_21 133 | br label %if_cont 134 | 135 | label_21: ; preds = %if_then17 136 | %24 = load double, double* @min 137 | %25 = load double, double* @a 138 | store double %25, double* @min 139 | br label %if_cont19 140 | 141 | label_22: ; preds = %for_end 142 | %26 = load double, double* @s 143 | %27 = load i32, i32* @i 144 | %28 = uitofp i32 %27 to double 145 | %addftmp23 = fadd double %26, %28 146 | %call_printf24 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([5 x i8], [5 x i8]* @printf_format.4, i32 0, i32 0), double %addftmp23) 147 | ret i32 0 148 | } 149 | 150 | declare i32 @printf(i8*, ...) 151 | 152 | declare i32 @scanf(i8*, ...) 153 | -------------------------------------------------------------------------------- /test/p.pas.dot: -------------------------------------------------------------------------------- 1 | digraph g { 2 | node_0->node_1; 3 | node_1->node_2; 4 | node_0->node_3; 5 | node_3->node_4; 6 | node_4->node_5; 7 | node_5->node_6; 8 | node_6->node_7; 9 | node_7->node_8; 10 | node_8->node_9; 11 | node_8->node_10; 12 | node_8->node_11; 13 | node_7->node_12; 14 | node_12->node_13; 15 | node_4->node_14; 16 | node_14->node_15; 17 | node_15->node_16; 18 | node_16->node_17; 19 | node_17->node_18; 20 | node_18->node_19; 21 | node_19->node_20; 22 | node_20->node_21; 23 | node_18->node_22; 24 | node_22->node_23; 25 | node_17->node_24; 26 | node_24->node_25; 27 | node_25->node_26; 28 | node_26->node_27; 29 | node_24->node_28; 30 | node_28->node_29; 31 | node_16->node_30; 32 | node_30->node_31; 33 | node_15->node_32; 34 | node_32->node_33; 35 | node_32->node_34; 36 | node_34->node_35; 37 | node_35->node_36; 38 | node_36->node_37; 39 | node_37->node_38; 40 | node_38->node_39; 41 | node_37->node_40; 42 | node_36->node_41; 43 | node_41->node_42; 44 | node_42->node_43; 45 | node_41->node_44; 46 | node_44->node_45; 47 | node_36->node_46; 48 | node_46->node_47; 49 | node_47->node_48; 50 | node_48->node_49; 51 | node_47->node_50; 52 | node_50->node_51; 53 | node_50->node_52; 54 | node_52->node_53; 55 | node_53->node_54; 56 | node_52->node_55; 57 | node_55->node_56; 58 | node_56->node_57; 59 | node_55->node_58; 60 | node_58->node_59; 61 | node_3->node_60; 62 | node_60->node_61; 63 | node_61->node_62; 64 | node_62->node_63; 65 | node_62->node_64; 66 | node_64->node_65; 67 | node_65->node_66; 68 | node_61->node_67; 69 | node_67->node_68; 70 | node_68->node_69; 71 | node_69->node_70; 72 | node_68->node_71; 73 | node_67->node_72; 74 | node_72->node_73; 75 | node_73->node_74; 76 | node_74->node_75; 77 | node_73->node_76; 78 | node_76->node_77; 79 | node_77->node_78; 80 | node_76->node_79; 81 | node_72->node_80; 82 | node_80->node_81; 83 | node_80->node_82; 84 | node_82->node_83; 85 | node_83->node_84; 86 | node_82->node_85; 87 | node_85->node_86; 88 | node_72->node_87; 89 | node_87->node_88; 90 | node_87->node_89; 91 | node_89->node_90; 92 | node_90->node_91; 93 | node_90->node_92; 94 | node_92->node_93; 95 | node_93->node_94; 96 | node_92->node_95; 97 | node_95->node_96; 98 | node_0[label="program\n[19, 4]"]; 99 | node_1[label="program_head\n[1, 27]"]; 100 | node_2[label="test_recursive_gcd"]; 101 | node_3[label="routine\n[19, 1]"]; 102 | node_4[label="routine_head\n[11, 1]"]; 103 | node_5[label="var_part:\n[4, 1]"]; 104 | node_6[label="var_decl_list:\n[3, 25]"]; 105 | node_7[label="Var_decl:\n[3, 25]"]; 106 | node_8[label="name_list\n[3, 15]"]; 107 | node_9[label="tcase"]; 108 | node_10[label="a"]; 109 | node_11[label="b"]; 110 | node_12[label="simple_type_decl\n[3, 18]"]; 111 | node_13[label="Integer"]; 112 | node_14[label="routine_part\n[10, 8]"]; 113 | node_15[label="function_decl\n[10, 8]"]; 114 | node_16[label="function_head of gcd\n[4, 39]"]; 115 | node_17[label="para_decl_list\n[4, 36]"]; 116 | node_18[label="para_type_list\n[4, 17]"]; 117 | node_19[label="val_para_list\n[4, 15]"]; 118 | node_20[label="name_list\n[4, 14]"]; 119 | node_21[label="a"]; 120 | node_22[label="simple_type_decl\n[4, 17]"]; 121 | node_23[label="Integer"]; 122 | node_24[label="para_type_list\n[4, 29]"]; 123 | node_25[label="val_para_list\n[4, 27]"]; 124 | node_26[label="name_list\n[4, 26]"]; 125 | node_27[label="b"]; 126 | node_28[label="simple_type_decl\n[4, 29]"]; 127 | node_29[label="Integer"]; 128 | node_30[label="simple_type_decl\n[4, 39]"]; 129 | node_31[label="Integer"]; 130 | node_32[label="routine\n[10, 5]"]; 131 | node_33[label="routine_head\n[5, 5]"]; 132 | node_34[label="routine_body\n[10, 5]"]; 133 | node_35[label="stmt_list\n[10, 5]"]; 134 | node_36[label="if_stmt\n[9, 35]"]; 135 | node_37[label="binary_op_expr: EQUAL\n[6, 18]"]; 136 | node_38[label="ID_expr\n[6, 14]"]; 137 | node_39[label="b"]; 138 | node_40[label="0"]; 139 | node_41[label="assign_stmt\n[8, 9]"]; 140 | node_42[label="ID_expr\n[0, 0]"]; 141 | node_43[label="gcd"]; 142 | node_44[label="ID_expr\n[8, 9]"]; 143 | node_45[label="a"]; 144 | node_46[label="else_clause\n[9, 35]"]; 145 | node_47[label="assign_stmt\n[9, 35]"]; 146 | node_48[label="ID_expr\n[0, 0]"]; 147 | node_49[label="gcd"]; 148 | node_50[label="func_call\n[9, 35]"]; 149 | node_51[label="gcd"]; 150 | node_52[label="expression_list\n[9, 34]"]; 151 | node_53[label="ID_expr\n[9, 25]"]; 152 | node_54[label="b"]; 153 | node_55[label="binary_op_expr: MOD\n[9, 34]"]; 154 | node_56[label="ID_expr\n[9, 29]"]; 155 | node_57[label="a"]; 156 | node_58[label="ID_expr\n[9, 34]"]; 157 | node_59[label="b"]; 158 | node_60[label="routine_body\n[19, 1]"]; 159 | node_61[label="stmt_list\n[19, 1]"]; 160 | node_62[label="proc_stmt\n[12, 15]"]; 161 | node_63[label="read"]; 162 | node_64[label="expression_list\n[12, 15]"]; 163 | node_65[label="ID_expr\n[12, 15]"]; 164 | node_66[label="tcase"]; 165 | node_67[label="while_stmt\n[18, 5]"]; 166 | node_68[label="binary_op_expr: GT\n[13, 21]"]; 167 | node_69[label="ID_expr\n[13, 17]"]; 168 | node_70[label="tcase"]; 169 | node_71[label="0"]; 170 | node_72[label="stmt_list\n[18, 5]"]; 171 | node_73[label="assign_stmt\n[15, 27]"]; 172 | node_74[label="ID_expr\n[0, 0]"]; 173 | node_75[label="tcase"]; 174 | node_76[label="binary_op_expr: MINUS\n[15, 27]"]; 175 | node_77[label="ID_expr\n[15, 24]"]; 176 | node_78[label="tcase"]; 177 | node_79[label="1"]; 178 | node_80[label="proc_stmt\n[16, 18]"]; 179 | node_81[label="read"]; 180 | node_82[label="expression_list\n[16, 18]"]; 181 | node_83[label="ID_expr\n[16, 15]"]; 182 | node_84[label="a"]; 183 | node_85[label="ID_expr\n[16, 18]"]; 184 | node_86[label="b"]; 185 | node_87[label="proc_stmt\n[17, 26]"]; 186 | node_88[label="writeln"]; 187 | node_89[label="expression_list\n[17, 26]"]; 188 | node_90[label="func_call\n[17, 26]"]; 189 | node_91[label="gcd"]; 190 | node_92[label="expression_list\n[17, 25]"]; 191 | node_93[label="ID_expr\n[17, 22]"]; 192 | node_94[label="a"]; 193 | node_95[label="ID_expr\n[17, 25]"]; 194 | node_96[label="b"]; 195 | } -------------------------------------------------------------------------------- /test/func.pas.dot: -------------------------------------------------------------------------------- 1 | digraph g { 2 | node_0->node_1; 3 | node_1->node_2; 4 | node_0->node_3; 5 | node_3->node_4; 6 | node_4->node_5; 7 | node_5->node_6; 8 | node_6->node_7; 9 | node_7->node_8; 10 | node_8->node_9; 11 | node_8->node_10; 12 | node_7->node_11; 13 | node_11->node_12; 14 | node_4->node_13; 15 | node_13->node_14; 16 | node_14->node_15; 17 | node_15->node_16; 18 | node_16->node_17; 19 | node_17->node_18; 20 | node_18->node_19; 21 | node_19->node_20; 22 | node_17->node_21; 23 | node_21->node_22; 24 | node_16->node_23; 25 | node_23->node_24; 26 | node_24->node_25; 27 | node_25->node_26; 28 | node_23->node_27; 29 | node_27->node_28; 30 | node_14->node_29; 31 | node_29->node_30; 32 | node_30->node_31; 33 | node_31->node_32; 34 | node_32->node_33; 35 | node_33->node_34; 36 | node_32->node_35; 37 | node_35->node_36; 38 | node_35->node_37; 39 | node_37->node_38; 40 | node_38->node_39; 41 | node_39->node_40; 42 | node_40->node_41; 43 | node_39->node_42; 44 | node_29->node_43; 45 | node_43->node_44; 46 | node_44->node_45; 47 | node_45->node_46; 48 | node_45->node_47; 49 | node_47->node_48; 50 | node_48->node_49; 51 | node_47->node_50; 52 | node_47->node_51; 53 | node_51->node_52; 54 | node_44->node_53; 55 | node_53->node_54; 56 | node_44->node_55; 57 | node_55->node_56; 58 | node_56->node_57; 59 | node_55->node_58; 60 | node_44->node_59; 61 | node_59->node_60; 62 | node_59->node_61; 63 | node_61->node_62; 64 | node_62->node_63; 65 | node_61->node_64; 66 | node_61->node_65; 67 | node_65->node_66; 68 | node_3->node_67; 69 | node_67->node_68; 70 | node_68->node_69; 71 | node_69->node_70; 72 | node_70->node_71; 73 | node_69->node_72; 74 | node_68->node_73; 75 | node_73->node_74; 76 | node_74->node_75; 77 | node_73->node_76; 78 | node_68->node_77; 79 | node_77->node_78; 80 | node_77->node_79; 81 | node_79->node_80; 82 | node_80->node_81; 83 | node_79->node_82; 84 | node_79->node_83; 85 | node_83->node_84; 86 | node_68->node_85; 87 | node_85->node_86; 88 | node_85->node_87; 89 | node_87->node_88; 90 | node_88->node_89; 91 | node_87->node_90; 92 | node_90->node_91; 93 | node_68->node_92; 94 | node_92->node_93; 95 | node_92->node_94; 96 | node_94->node_95; 97 | node_95->node_96; 98 | node_94->node_97; 99 | node_94->node_98; 100 | node_98->node_99; 101 | node_0[label="program\n[20, 4]"]; 102 | node_1[label="program_head\n[1, 15]"]; 103 | node_2[label="myfunc"]; 104 | node_3[label="routine\n[20, 1]"]; 105 | node_4[label="routine_head\n[14, 1]"]; 106 | node_5[label="var_part:\n[3, 1]"]; 107 | node_6[label="var_decl_list:\n[2, 19]"]; 108 | node_7[label="Var_decl:\n[2, 19]"]; 109 | node_8[label="name_list\n[2, 8]"]; 110 | node_9[label="a"]; 111 | node_10[label="b"]; 112 | node_11[label="simple_type_decl\n[2, 12]"]; 113 | node_12[label="Integer"]; 114 | node_13[label="routine_part\n[13, 4]"]; 115 | node_14[label="procedure_decl\n[13, 4]"]; 116 | node_15[label="procedure_head of f\n[3, 40]"]; 117 | node_16[label="para_decl_list\n[3, 40]"]; 118 | node_17[label="para_type_list\n[3, 17]"]; 119 | node_18[label="val_para_list\n[3, 15]"]; 120 | node_19[label="name_list\n[3, 13]"]; 121 | node_20[label="a"]; 122 | node_21[label="simple_type_decl\n[3, 17]"]; 123 | node_22[label="Integer"]; 124 | node_23[label="para_type_list\n[3, 33]"]; 125 | node_24[label="var_para_list\n[3, 31]"]; 126 | node_25[label="name_list\n[3, 30]"]; 127 | node_26[label="b"]; 128 | node_27[label="simple_type_decl\n[3, 33]"]; 129 | node_28[label="Integer"]; 130 | node_29[label="routine\n[13, 1]"]; 131 | node_30[label="routine_head\n[8, 1]"]; 132 | node_31[label="routine_part\n[7, 8]"]; 133 | node_32[label="procedure_decl\n[7, 8]"]; 134 | node_33[label="procedure_head of g\n[4, 16]"]; 135 | node_34[label="para_decl_list\n[0, 0]"]; 136 | node_35[label="routine\n[7, 5]"]; 137 | node_36[label="routine_head\n[5, 5]"]; 138 | node_37[label="routine_body\n[7, 5]"]; 139 | node_38[label="stmt_list\n[7, 5]"]; 140 | node_39[label="assign_stmt\n[6, 15]"]; 141 | node_40[label="ID_expr\n[0, 0]"]; 142 | node_41[label="a"]; 143 | node_42[label="2"]; 144 | node_43[label="routine_body\n[13, 1]"]; 145 | node_44[label="stmt_list\n[13, 1]"]; 146 | node_45[label="proc_stmt\n[9, 22]"]; 147 | node_46[label="writeln"]; 148 | node_47[label="expression_list\n[9, 22]"]; 149 | node_48[label="ID_expr\n[9, 14]"]; 150 | node_49[label="a"]; 151 | node_50[label="' '"]; 152 | node_51[label="ID_expr\n[9, 22]"]; 153 | node_52[label="b"]; 154 | node_53[label="proc_stmt\n[10, 6]"]; 155 | node_54[label="g"]; 156 | node_55[label="assign_stmt\n[11, 11]"]; 157 | node_56[label="ID_expr\n[0, 0]"]; 158 | node_57[label="b"]; 159 | node_58[label="5"]; 160 | node_59[label="proc_stmt\n[12, 22]"]; 161 | node_60[label="writeln"]; 162 | node_61[label="expression_list\n[12, 22]"]; 163 | node_62[label="ID_expr\n[12, 14]"]; 164 | node_63[label="a"]; 165 | node_64[label="' '"]; 166 | node_65[label="ID_expr\n[12, 22]"]; 167 | node_66[label="b"]; 168 | node_67[label="routine_body\n[20, 1]"]; 169 | node_68[label="stmt_list\n[20, 1]"]; 170 | node_69[label="assign_stmt\n[15, 11]"]; 171 | node_70[label="ID_expr\n[0, 0]"]; 172 | node_71[label="a"]; 173 | node_72[label="3"]; 174 | node_73[label="assign_stmt\n[16, 11]"]; 175 | node_74[label="ID_expr\n[0, 0]"]; 176 | node_75[label="b"]; 177 | node_76[label="4"]; 178 | node_77[label="proc_stmt\n[17, 22]"]; 179 | node_78[label="writeln"]; 180 | node_79[label="expression_list\n[17, 22]"]; 181 | node_80[label="ID_expr\n[17, 14]"]; 182 | node_81[label="a"]; 183 | node_82[label="' '"]; 184 | node_83[label="ID_expr\n[17, 22]"]; 185 | node_84[label="b"]; 186 | node_85[label="proc_stmt\n[18, 11]"]; 187 | node_86[label="f"]; 188 | node_87[label="expression_list\n[18, 11]"]; 189 | node_88[label="ID_expr\n[18, 8]"]; 190 | node_89[label="a"]; 191 | node_90[label="ID_expr\n[18, 11]"]; 192 | node_91[label="b"]; 193 | node_92[label="proc_stmt\n[19, 22]"]; 194 | node_93[label="writeln"]; 195 | node_94[label="expression_list\n[19, 22]"]; 196 | node_95[label="ID_expr\n[19, 14]"]; 197 | node_96[label="a"]; 198 | node_97[label="' '"]; 199 | node_98[label="ID_expr\n[19, 22]"]; 200 | node_99[label="b"]; 201 | } -------------------------------------------------------------------------------- /src/ast/ast_stmt.h: -------------------------------------------------------------------------------- 1 | #ifndef OPC_AST_AST_STMT_H 2 | #define OPC_AST_AST_STMT_H 3 | 4 | #include "ast_base.h" 5 | #include "ast_expr.h" 6 | 7 | using namespace std; 8 | class Visitor; 9 | 10 | class ASTNode; 11 | 12 | class ASTNonLabelStmt; 13 | 14 | class ASTStmt; 15 | 16 | class ASTStmtList; 17 | 18 | class ASTAssignStmt; 19 | 20 | class ASTProcStmt; 21 | 22 | class ASTIfStmt; 23 | 24 | class ASTElseClause; 25 | 26 | class ASTRepeatStmt; 27 | 28 | class ASTWhileStmt; 29 | 30 | class ASTForStmt; 31 | 32 | class ASTCaseStmt; 33 | 34 | class ASTCaseExprList; 35 | 36 | class ASTCaseExpr; 37 | 38 | class ASTGotoStmt; 39 | 40 | class ASTNonLabelStmt : public ASTNode { 41 | }; 42 | 43 | class ASTStmt : public ASTNode { 44 | private: 45 | std::string label; 46 | ASTNonLabelStmt *non_label_stmt; 47 | 48 | public: 49 | ASTStmt(ASTNonLabelStmt *non_label_stmt, std::string label = ""); 50 | 51 | virtual std::shared_ptr Accept(Visitor *visitor); 52 | 53 | const std::string &getLabel() const; 54 | 55 | ASTNonLabelStmt *getNonLabelStmt() const; 56 | }; 57 | 58 | class ASTStmtList : public ASTNonLabelStmt { 59 | public: 60 | ASTStmtList(); 61 | 62 | void addStmt(ASTStmt *); 63 | 64 | virtual std::shared_ptr Accept(Visitor *visitor); 65 | 66 | const std::vector &getStmtList() const; 67 | 68 | private: 69 | std::vector stmt_list; 70 | }; 71 | 72 | class ASTAssignStmt : public ASTNonLabelStmt { 73 | public: 74 | ASTAssignStmt(ASTExpr *, ASTExpr *); 75 | 76 | 77 | 78 | virtual std::shared_ptr Accept(Visitor *visitor); 79 | 80 | ASTExpr *getExpr1() const; 81 | 82 | ASTExpr *getExpr2() const; 83 | 84 | private: 85 | ASTExpr *expr1; 86 | ASTExpr *expr2; 87 | }; 88 | 89 | class ASTProcStmt : public ASTNonLabelStmt { 90 | public: 91 | ASTProcStmt(std::string id, ASTExpressionList *expr = nullptr); 92 | 93 | 94 | 95 | virtual std::shared_ptr Accept(Visitor *visitor); 96 | 97 | const std::string &getId() const; 98 | 99 | ASTExpressionList *getExprList() const; 100 | 101 | private: 102 | std::string id; 103 | ASTExpressionList *expr_list; 104 | }; 105 | 106 | class ASTIfStmt : public ASTNonLabelStmt { 107 | public: 108 | ASTIfStmt(ASTExpr *, ASTStmt *, ASTElseClause *); 109 | 110 | 111 | 112 | virtual std::shared_ptr Accept(Visitor *visitor); 113 | 114 | ASTExpr *getExpr() const; 115 | 116 | ASTStmt *getStmt() const; 117 | 118 | ASTElseClause *getElseClause() const; 119 | 120 | private: 121 | ASTExpr *expr; 122 | ASTStmt *stmt; 123 | ASTElseClause *else_clause; 124 | }; 125 | 126 | class ASTElseClause : public ASTNonLabelStmt { 127 | public: 128 | ASTElseClause(ASTStmt *); 129 | 130 | 131 | 132 | virtual std::shared_ptr Accept(Visitor *visitor); 133 | 134 | ASTStmt *getStmt() const; 135 | 136 | private: 137 | ASTStmt *stmt; 138 | }; 139 | 140 | class ASTRepeatStmt : public ASTNonLabelStmt { 141 | public: 142 | ASTRepeatStmt(ASTStmtList *, ASTExpr *); 143 | 144 | 145 | 146 | virtual std::shared_ptr Accept(Visitor *visitor); 147 | 148 | ASTStmtList *getStmtList() const; 149 | 150 | ASTExpr *getExpr() const; 151 | 152 | private: 153 | ASTStmtList *stmt_list_; 154 | ASTExpr *expr_; 155 | }; 156 | 157 | class ASTWhileStmt : public ASTNonLabelStmt { 158 | public: 159 | ASTWhileStmt(ASTExpr *, ASTStmt *); 160 | 161 | 162 | 163 | virtual std::shared_ptr Accept(Visitor *visitor); 164 | 165 | ASTExpr *getExpr() const; 166 | 167 | ASTStmt *getStmt() const; 168 | 169 | private: 170 | ASTExpr *expr_; 171 | ASTStmt *stmt_; 172 | }; 173 | 174 | class ASTForStmt : public ASTNonLabelStmt { 175 | public: 176 | enum class ForDir { 177 | TO, DOWNTO 178 | }; 179 | 180 | ASTForStmt(std::string id, ASTExpr *for_expr, ForDir dir, ASTExpr *to_expr, 181 | ASTStmt *stmt); 182 | 183 | 184 | 185 | virtual std::shared_ptr Accept(Visitor *visitor); 186 | 187 | const string &getId() const; 188 | 189 | ASTExpr *getForExpr() const; 190 | 191 | ASTExpr *getToExpr() const; 192 | 193 | ForDir getDir() const; 194 | 195 | ASTStmt *getStmt() const; 196 | 197 | private: 198 | std::string id_; 199 | ASTExpr *for_expr_, *to_expr_; 200 | ForDir dir_; 201 | ASTStmt *stmt_; 202 | }; 203 | 204 | class ASTCaseStmt : public ASTNonLabelStmt { 205 | public: 206 | ASTCaseStmt(ASTExpr *, ASTCaseExprList *); 207 | 208 | 209 | 210 | virtual std::shared_ptr Accept(Visitor *visitor); 211 | 212 | ASTExpr *getExpr() const; 213 | 214 | ASTCaseExprList *getCaseExprList() const; 215 | 216 | private: 217 | ASTExpr *expr_; 218 | ASTCaseExprList *case_expr_list_; 219 | }; 220 | 221 | class ASTCaseExprList : public ASTNonLabelStmt { 222 | public: 223 | ASTCaseExprList(); 224 | 225 | void add_case_expr(ASTCaseExpr *); 226 | 227 | 228 | 229 | virtual std::shared_ptr Accept(Visitor *visitor); 230 | 231 | const vector &getCaseExprList() const; 232 | 233 | private: 234 | std::vector case_expr_list_; 235 | }; 236 | 237 | class ASTCaseExpr : public ASTNonLabelStmt { 238 | public: 239 | ASTCaseExpr(ASTExpr *, ASTStmt *); 240 | 241 | 242 | 243 | virtual std::shared_ptr Accept(Visitor *visitor); 244 | 245 | ASTExpr *getExpr() const; 246 | 247 | ASTStmt *getStmt() const; 248 | 249 | private: 250 | ASTExpr *expr_; 251 | ASTStmt *stmt_; 252 | }; 253 | 254 | class ASTGotoStmt : public ASTNonLabelStmt { 255 | public: 256 | ASTGotoStmt(std::string label); 257 | 258 | 259 | 260 | virtual std::shared_ptr Accept(Visitor *visitor); 261 | 262 | const string &getLabel() const; 263 | 264 | private: 265 | std::string label_; 266 | }; 267 | 268 | class ASTExitStmt : public ASTNonLabelStmt { 269 | public: 270 | ASTExitStmt(ASTExpr *expr = nullptr); 271 | 272 | virtual std::shared_ptr Accept(Visitor *visitor); 273 | 274 | ASTExpr *getExpr() const; 275 | 276 | private: 277 | ASTExpr *expr_; 278 | }; 279 | 280 | class ASTBreakStmt : public ASTNonLabelStmt { 281 | public: 282 | ASTBreakStmt() = default; 283 | 284 | virtual std::shared_ptr Accept(Visitor *visitor); 285 | }; 286 | #endif //OPC_AST_AST_STMT_H -------------------------------------------------------------------------------- /src/generator/generator_value.cpp: -------------------------------------------------------------------------------- 1 | #include "generator.h" 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include "generator_result.hpp" 8 | 9 | 10 | std::shared_ptr Generator::VisitASTConstValue(ASTConstValue *node) { 11 | llvm::Type *tp; 12 | if (node->getValueType() == ASTConstValue::ValueType::INTEGER) { 13 | tp = llvm::Type::getInt32Ty(this->context); 14 | int v_int = atoi(node->getContent().c_str()); 15 | return std::make_shared( 16 | OurType::INT_TYPE, 17 | llvm::ConstantInt::get(tp, (uint64_t) v_int, true), 18 | nullptr 19 | ); 20 | } 21 | if (node->getValueType() == ASTConstValue::ValueType::FLOAT) { 22 | 23 | tp = llvm::Type::getDoubleTy(this->context); 24 | 25 | double v_float = atof(node->getContent().c_str()); 26 | std::cout << v_float << std::endl; 27 | return std::make_shared( 28 | OurType::REAL_TYPE, 29 | llvm::ConstantFP::get(tp, v_float), 30 | nullptr 31 | ); 32 | } 33 | if (node->getValueType() == ASTConstValue::ValueType::CHAR) { 34 | tp = llvm::Type::getInt8Ty(this->context); 35 | char v_int = node->getContent()[1]; 36 | return std::make_shared( 37 | OurType::CHAR_TYPE, 38 | llvm::ConstantInt::get(tp, (uint64_t) v_int, true), 39 | nullptr 40 | ); 41 | } 42 | if (node->getValueType() == ASTConstValue::ValueType::STRING) { 43 | // to make str things can store, alloc with each other 44 | // we have to make all string values have the same length 45 | // we make this 256 46 | // so we add suffix zero to all constant string 47 | // VERY BAD CODING STYLE 48 | // NEED TO BE MODIFIED ASAP 49 | std::string tmp = node->getContent().substr(1, node->getContent().length() - 2); 50 | int tmp_len = tmp.size(); 51 | if (tmp_len > 255) { 52 | std::cerr << node->get_location() << "this string constant is too long, use first 255 characters instead." << std::endl; 53 | //This is not error but just warning. Maybe we can add a 'warning type' to report all warnings. 54 | tmp = tmp.substr(0, 255); 55 | tmp_len = tmp.size(); 56 | } 57 | char zero = 0; 58 | for (int i = 0; i < 255 - tmp_len; i++) tmp = tmp + zero; 59 | llvm::Value *mem_str = this->builder.CreateGlobalString(tmp); 60 | llvm::Value *v_str = this->builder.CreateLoad(mem_str); 61 | return std::make_shared( 62 | new OurType::StrType(), 63 | v_str, 64 | mem_str 65 | ); 66 | } 67 | if (node->getValueType() == ASTConstValue::ValueType::BOOL) { 68 | tp = llvm::Type::getInt1Ty(this->context); 69 | std::string lit = node->getContent(); 70 | for (int i=0;i < lit.length(); i++) lit[i] = tolower(lit[i]); 71 | bool p = lit == "true" ? true : false; 72 | return std::make_shared( 73 | OurType::BOOLEAN_TYPE, 74 | llvm::ConstantInt::get(tp, (uint64_t) p, true), 75 | nullptr 76 | ); 77 | } 78 | const PascalType *ty = BOOLEAN_TYPE; 79 | return nullptr; 80 | } 81 | 82 | std::shared_ptr Generator::VisitASTConstExprList(ASTConstExprList *node) { 83 | for (auto expr: node->getConstExprList()) expr->Accept(this); 84 | return nullptr; 85 | } 86 | 87 | std::shared_ptr Generator::VisitASTConstExpr(ASTConstExpr *node) { 88 | std::shared_ptr res = std::static_pointer_cast(node->getValue()->Accept(this)); 89 | llvm::GlobalVariable *constant = new llvm::GlobalVariable( 90 | /*Module=*/*(this->module), 91 | /*Type=*/OurType::getLLVMType(this->context, res->getType()), 92 | /*isConstant=*/true, 93 | /*Linkage=*/llvm::GlobalValue::CommonLinkage, 94 | /*Initializer=*/(llvm::Constant *) res->getValue(), // has initializer, specified below 95 | /*Name=*/node->getId()); 96 | if (this->block_stack.back()->named_values.count(node->getId()) || this->named_constants.count(node->getId())) { 97 | //error 98 | } 99 | this->named_constants[node->getId()] = (llvm::Constant *) (res->getValue()); 100 | this->block_stack[0]->named_values[node->getId()] = constant; 101 | return nullptr; 102 | } 103 | 104 | std::shared_ptr Generator::VisitASTConstPart(ASTConstPart *node) { 105 | return node->getConstExprList()->Accept(this); 106 | } 107 | 108 | std::shared_ptr Generator::VisitASTVarPart(ASTVarPart *node) { 109 | return node->getVarDeclList()->Accept(this); 110 | } 111 | 112 | std::shared_ptr Generator::VisitASTVarDeclList(ASTVarDeclList *node) { 113 | for (auto expr: node->getVarDeclList()) 114 | expr->Accept(this); 115 | return nullptr; 116 | } 117 | 118 | std::shared_ptr Generator::VisitASTVarDecl(ASTVarDecl *node) { 119 | auto res = std::static_pointer_cast(node->getTypeDecl()->Accept(this)); 120 | auto name_list = std::static_pointer_cast(node->getNameList()->Accept(this)); 121 | if (res == nullptr) return nullptr; //The error has been reported. 122 | for (auto id: name_list->getNameList()) { 123 | llvm::Type *ty = OurType::getLLVMType(this->context, res->getType()); 124 | if (this->block_stack.size() == 1) { 125 | llvm::Constant * initializer; 126 | if (res->getType()->isBuiltInTy()) initializer = llvm::Constant::getNullValue(ty); 127 | else initializer = llvm::ConstantAggregateZero::get(ty); 128 | llvm::GlobalVariable *var = new llvm::GlobalVariable( 129 | /*Module=*/*(this->module), 130 | /*Type=*/ty, 131 | /*isConstant=*/false, 132 | /*Linkage=*/llvm::GlobalValue::CommonLinkage, 133 | /*Initializer=*/initializer, // has initializer, specified below 134 | /*Name=*/id); 135 | if (this->block_stack.back()->named_values.count(id)) { 136 | //error 137 | } 138 | this->block_stack.back()->named_values[id] = var; 139 | this->block_stack.back()->named_types[id] = res->getType(); 140 | } else { 141 | llvm::AllocaInst *var = this->builder.CreateAlloca( 142 | ty, 143 | nullptr, 144 | id 145 | ); 146 | if (this->block_stack.back()->named_values.count(id)) { 147 | //error 148 | } 149 | this->block_stack.back()->named_values[id] = var; 150 | this->block_stack.back()->named_types[id] = res->getType(); 151 | } 152 | } 153 | return nullptr; 154 | } 155 | -------------------------------------------------------------------------------- /src/ast/ast_prog.h: -------------------------------------------------------------------------------- 1 | #ifndef OPC_AST_PROG_H 2 | #define OPC_AST_PROG_H 3 | 4 | #include "ast_base.h" 5 | #include "ast_expr.h" 6 | #include "ast_stmt.h" 7 | #include "ast_type.h" 8 | #include "ast_value.h" 9 | 10 | class Visitor; 11 | 12 | class ASTNode; 13 | 14 | class ASTProgramHead; 15 | 16 | class ASTRoutineHead; 17 | 18 | class ASTRoutineBody; 19 | 20 | class ASTRoutinePart; 21 | 22 | class ASTRoutine; 23 | 24 | class ASTFuncProcBase; 25 | 26 | class ASTProgram; 27 | 28 | class ASTFunctionDecl; 29 | 30 | class ASTFunctionHead; 31 | 32 | class ASTProcedureDecl; 33 | 34 | class ASTProcedureHead; 35 | 36 | class ASTParaTypeList; 37 | 38 | class ASTParaList; 39 | 40 | class ASTParaDeclList; 41 | 42 | class ASTProgramHead : public ASTNode { 43 | public: 44 | ASTProgramHead(std::string id); 45 | 46 | 47 | 48 | virtual std::shared_ptr Accept(Visitor *visitor); 49 | 50 | private: 51 | public: 52 | const string &getId() const; 53 | 54 | private: 55 | std::string id; 56 | }; 57 | 58 | class ASTRoutineHead : public ASTNode { 59 | public: 60 | ASTRoutineHead(ASTConstPart *const_part, ASTTypePart *type_part, 61 | ASTVarPart *var_part, ASTRoutinePart *routine_part); 62 | 63 | 64 | 65 | virtual std::shared_ptr Accept(Visitor *visitor); 66 | 67 | private: 68 | ASTConstPart *const_part; 69 | ASTTypePart *type_part; 70 | public: 71 | ASTConstPart *getConstPart() const; 72 | 73 | ASTTypePart *getTypePart() const; 74 | 75 | ASTVarPart *getVarPart() const; 76 | 77 | ASTRoutinePart *getRoutinePart() const; 78 | 79 | private: 80 | ASTVarPart *var_part; 81 | ASTRoutinePart *routine_part; 82 | }; 83 | 84 | class ASTRoutineBody : public ASTNode { 85 | public: 86 | ASTRoutineBody(ASTStmtList *compound_stmt); 87 | 88 | virtual std::shared_ptr Accept(Visitor *visitor); 89 | 90 | ASTStmtList *getCompoundStmt(); 91 | 92 | private: 93 | ASTStmtList *compound_stmt; 94 | }; 95 | 96 | class ASTRoutine : public ASTNode { 97 | public: 98 | ASTRoutine(ASTRoutineHead *routine_head, ASTRoutineBody *routine_body); 99 | 100 | 101 | 102 | virtual std::shared_ptr Accept(Visitor *visitor); 103 | 104 | ASTRoutineHead *getRoutineHead() const; 105 | 106 | ASTRoutineBody *getRoutineBody() const; 107 | 108 | private: 109 | ASTRoutineHead *routine_head; 110 | ASTRoutineBody *routine_body; 111 | }; 112 | 113 | class ASTProgram : public ASTNode { 114 | public: 115 | ASTProgram(ASTProgramHead *, ASTRoutine *); 116 | 117 | 118 | 119 | virtual std::shared_ptr Accept(Visitor *visitor); 120 | 121 | ASTProgramHead *getProgramHead() const; 122 | 123 | ASTRoutine *getRoutine() const; 124 | 125 | private: 126 | ASTProgramHead *program_head; 127 | ASTRoutine *routine; 128 | }; 129 | 130 | class ASTRoutinePart : public ASTNode { 131 | public: 132 | ASTRoutinePart(ASTFuncProcBase *); 133 | 134 | 135 | 136 | void addFuncProcDecl(ASTFuncProcBase *); 137 | 138 | virtual std::shared_ptr Accept(Visitor *visitor); 139 | 140 | private: 141 | std::vector routine_list; 142 | public: 143 | const vector &getRoutineList() const; 144 | }; 145 | 146 | class ASTFuncProcBase : public ASTNode { 147 | public: 148 | enum class FuncType { 149 | FUNCTION, PROCEDURE 150 | }; 151 | FuncType iam; 152 | 153 | FuncType getIam() const; 154 | 155 | ASTFuncProcBase(FuncType whoami) : iam(whoami) {} 156 | 157 | virtual std::shared_ptr Accept(Visitor *visitor); 158 | }; 159 | 160 | class ASTFunctionDecl : public ASTFuncProcBase { 161 | public: 162 | ASTFunctionDecl(ASTFunctionHead *, ASTRoutine *); 163 | 164 | virtual std::shared_ptr Accept(Visitor *visitor); 165 | 166 | ASTFunctionHead *getFunctionHead() const; 167 | 168 | ASTRoutine *getRoutine() const; 169 | 170 | private: 171 | ASTFunctionHead *function_head; 172 | ASTRoutine *routine; 173 | }; 174 | 175 | class ASTFunctionHead : public ASTNode { 176 | public: 177 | ASTFunctionHead(std::string, ASTParaDeclList *, ASTSimpleTypeDecl *); 178 | 179 | 180 | 181 | virtual std::shared_ptr Accept(Visitor *visitor); 182 | 183 | const string &getFuncName() const; 184 | 185 | ASTParaDeclList *getParameters() const; 186 | 187 | ASTSimpleTypeDecl *getSimpleTypeDecl() const; 188 | 189 | private: 190 | std::string func_name; 191 | ASTParaDeclList *parameters; 192 | ASTSimpleTypeDecl *simple_type_decl; 193 | }; 194 | 195 | class ASTProcedureDecl : public ASTFuncProcBase { 196 | public: 197 | ASTProcedureDecl(ASTProcedureHead *, ASTRoutine *); 198 | 199 | virtual std::shared_ptr Accept(Visitor *visitor); 200 | 201 | ASTProcedureHead *getProcedureHead() const; 202 | 203 | ASTRoutine *getRoutine() const; 204 | 205 | private: 206 | ASTProcedureHead *procedure_head; 207 | ASTRoutine *routine; 208 | }; 209 | 210 | class ASTProcedureHead : public ASTNode { 211 | public: 212 | ASTProcedureHead(std::string proc_name, ASTParaDeclList *); 213 | 214 | 215 | 216 | virtual std::shared_ptr Accept(Visitor *visitor); 217 | 218 | const string &getProcName() const; 219 | 220 | ASTParaDeclList *getParameters() const; 221 | 222 | private: 223 | std::string proc_name; 224 | ASTParaDeclList *parameters; 225 | }; 226 | 227 | /* 228 | * not required in yacc 229 | * 230 | class ASTParameters : public ASTNode { 231 | public: 232 | ASTParameters(ASTParaDeclList *); 233 | 234 | 235 | private: 236 | ASTParaDeclList *para_dec_list; 237 | }; 238 | */ 239 | 240 | class ASTParaDeclList : public ASTNode { 241 | public: 242 | ASTParaDeclList(); 243 | 244 | void addParaTypeList(ASTParaTypeList *); 245 | 246 | 247 | 248 | virtual std::shared_ptr Accept(Visitor *visitor); 249 | 250 | const vector &getParaDeclList() const; 251 | 252 | private: 253 | std::vector para_decl_list; 254 | }; 255 | 256 | class ASTParaTypeList : public ASTNode { 257 | public: 258 | ASTParaTypeList(ASTParaList *, ASTSimpleTypeDecl *); 259 | 260 | 261 | 262 | virtual std::shared_ptr Accept(Visitor *visitor); 263 | 264 | ASTParaList *getParaList() const; 265 | 266 | ASTSimpleTypeDecl *getSimpleTypeDecl() const; 267 | 268 | private: 269 | ASTParaList *para_list; 270 | ASTSimpleTypeDecl *simple_type_decl; 271 | }; 272 | 273 | class ASTParaList : public ASTNode { 274 | public: 275 | bool is_var; 276 | 277 | bool isVar() const { 278 | return is_var; 279 | } 280 | 281 | ASTParaList(bool isVar) : is_var(isVar) {} 282 | }; 283 | 284 | 285 | class ASTVarParaList : public ASTParaList { 286 | public: 287 | ASTVarParaList(ASTNameList *); 288 | 289 | 290 | 291 | virtual std::shared_ptr Accept(Visitor *visitor); 292 | 293 | ASTNameList *getNameList() const; 294 | 295 | private: 296 | ASTNameList *name_list; 297 | }; 298 | 299 | class ASTValParaList : public ASTParaList { 300 | public: 301 | ASTValParaList(ASTNameList *); 302 | 303 | 304 | 305 | virtual std::shared_ptr Accept(Visitor *visitor); 306 | 307 | ASTNameList *getNameList() const; 308 | 309 | private: 310 | ASTNameList *name_list; 311 | }; 312 | 313 | #endif -------------------------------------------------------------------------------- /src/type/type.cpp: -------------------------------------------------------------------------------- 1 | #include "type.h" 2 | namespace OurType { 3 | 4 | const BuiltinType INT_TYPE_INST(BuiltinType::BasicTypes::INT); 5 | const BuiltinType REAL_TYPE_INST(BuiltinType::BasicTypes::REAL); 6 | const BuiltinType CHAR_TYPE_INST(BuiltinType::BasicTypes::CHAR); 7 | const BuiltinType BOOLEAN_TYPE_INST(BuiltinType::BasicTypes::BOOLEAN); 8 | const BuiltinType VOID_TYPE_INST(BuiltinType::BasicTypes::VOID); 9 | PascalType *const INT_TYPE = (PascalType *) (&INT_TYPE_INST); 10 | PascalType *const REAL_TYPE = (PascalType *) (&REAL_TYPE_INST); 11 | PascalType *const CHAR_TYPE = (PascalType *) (&CHAR_TYPE_INST); 12 | PascalType *const BOOLEAN_TYPE = (PascalType *) (&BOOLEAN_TYPE_INST); 13 | PascalType *const VOID_TYPE = (PascalType *) (&VOID_TYPE_INST); 14 | bool PascalType::isSimple() const { return tg == TypeGroup::BUILT_IN; } 15 | 16 | bool PascalType::isIntegerTy() const { return isEqual(this, INT_TYPE); } 17 | 18 | bool PascalType::isFloatingPointTy() const { return isEqual(this, REAL_TYPE); } 19 | 20 | bool PascalType::isCharTy() const { return isEqual(this, CHAR_TYPE); } 21 | 22 | bool PascalType::isStringTy() const { return this->tg == TypeGroup::STR; }; 23 | 24 | bool PascalType::isBuiltInTy() const { 25 | return this->tg == TypeGroup::BUILT_IN; 26 | } 27 | 28 | bool PascalType::isSubRangeTy() const { return this->tg == TypeGroup::SUBRANGE; }; 29 | 30 | bool PascalType::isRecordTy() const { return this->tg == TypeGroup::RECORD; }; 31 | 32 | bool PascalType::isArrayTy() const { return this->tg == TypeGroup::ARRAY; } 33 | 34 | PascalType::PascalType(PascalType::TypeGroup tg) : tg(tg) {}; 35 | 36 | EnumType::EnumType(std::vector names, Generator *g) : 37 | names_(names), PascalType(PascalType::TypeGroup::ENUM) { 38 | for (int i = 0; i < names.size(); i++) { 39 | if (g->named_constants.find(names[i]) != g->named_constants.end()) { 40 | // multiple constant 41 | continue; 42 | } else { 43 | g->named_constants[names[i]] = llvm::ConstantInt::get( 44 | llvm::Type::getInt32Ty(g->context), i, true); 45 | } 46 | } 47 | } 48 | 49 | SubRangeType::SubRangeType(int low, int high) : low(low), high(high), PascalType(PascalType::TypeGroup::SUBRANGE) {} 50 | 51 | llvm::ConstantInt *ArrayType::getLLVMLow(llvm::LLVMContext &context) { 52 | return llvm::ConstantInt::get(llvm::Type::getInt32Ty(context), range.first, true); 53 | } 54 | 55 | llvm::ConstantInt *ArrayType::getLLVMHigh(llvm::LLVMContext &context) { 56 | return llvm::ConstantInt::get(llvm::Type::getInt32Ty(context), range.second, true); 57 | } 58 | 59 | ArrayType::ArrayType(std::pair range, PascalType *type) : 60 | range(range), element_type(type), PascalType(PascalType::TypeGroup::ARRAY) {} 61 | 62 | StrType::StrType(int dim) : dim(dim), PascalType(PascalType::TypeGroup::STR) {} 63 | 64 | RecordType::RecordType(std::vector name_vec, std::vector type_vec) : 65 | name_vec(name_vec), type_vec(type_vec), PascalType(PascalType::TypeGroup::RECORD) { 66 | this->size = name_vec.size(); 67 | } 68 | 69 | bool isEqual(const PascalType *const a, const PascalType *const b) { 70 | if (a == nullptr || b == nullptr) return false; 71 | if (a->tg != b->tg) return false; 72 | if (a->tg == PascalType::TypeGroup::BUILT_IN) 73 | return ((BuiltinType *) a)->type == ((BuiltinType *) b)->type; 74 | else if (a->tg == PascalType::TypeGroup::RECORD) { 75 | RecordType *ra = (RecordType *)a, *rb = (RecordType *)b; 76 | if (ra->name_vec.size() != rb->name_vec.size()) 77 | return false; 78 | for(int i = 0; i < ra->name_vec.size(); i++) { 79 | if (ra->name_vec[i] != rb->name_vec[i]) return false; 80 | if (ra->type_vec[i] != rb->type_vec[i]) return false; 81 | } 82 | return true; 83 | } else if (a->tg == PascalType::TypeGroup::ARRAY) { 84 | ArrayType *aa = (ArrayType *)a, *ab = (ArrayType *)b; 85 | if (aa->range != ab->range) return false; 86 | return isEqual(aa->element_type, ab->element_type); 87 | } else if (a->tg == PascalType::TypeGroup::SUBRANGE) { 88 | SubRangeType *sa = (SubRangeType *)a, *sb = (SubRangeType *)b; 89 | return (sa->low == sb->low && sa->high == sb->high); 90 | } else if (a->tg == PascalType::TypeGroup::STR) { 91 | StrType *stra = (StrType *)a, *strb = (StrType *)b; 92 | return stra->dim == strb->dim; 93 | } else if (a->tg == PascalType::TypeGroup::ENUM) { 94 | EnumType *ea = (EnumType *)a, *eb = (EnumType *)b; 95 | if (ea->names_.size() != eb->names_.size()) return false; 96 | for(int i = 0; i < ea->names_.size(); i++) 97 | if (ea->names_[i] != eb->names_[i]) return false; 98 | return true; 99 | } else { 100 | std::cout << "Unknown Error Occurred at OurType::isEqual" << std::endl; 101 | return false; 102 | } 103 | } 104 | 105 | llvm::Type *getLLVMType(llvm::LLVMContext &context, PascalType *const p_type) { 106 | 107 | if (p_type->tg == PascalType::TypeGroup::BUILT_IN) { 108 | if (isEqual(p_type, INT_TYPE)) 109 | return llvm::Type::getInt32Ty(context); 110 | else if (isEqual(p_type, REAL_TYPE)) 111 | return llvm::Type::getDoubleTy(context); 112 | else if (isEqual(p_type, CHAR_TYPE)) 113 | return llvm::Type::getInt8Ty(context); 114 | else if (isEqual(p_type, BOOLEAN_TYPE)) 115 | return llvm::Type::getInt1Ty(context); 116 | else if (isEqual(p_type, VOID_TYPE)) 117 | return llvm::Type::getVoidTy(context); 118 | else 119 | return nullptr; 120 | 121 | } else if (p_type->tg == PascalType::TypeGroup::STR) { 122 | StrType *str = (StrType *) p_type; 123 | return llvm::ArrayType::get(getLLVMType(context, CHAR_TYPE), (uint64_t) (str->dim)); 124 | 125 | } else if (p_type->tg == PascalType::TypeGroup::ARRAY) { 126 | ArrayType *array = (ArrayType *) p_type; 127 | llvm::ArrayType *ret = nullptr; 128 | int len = array->range.second - array->range.first + 1; 129 | std::cout << "creating array of length " <element_type), (uint64_t) len); 131 | return ret; 132 | 133 | } else if (p_type->tg == PascalType::TypeGroup::RECORD) { 134 | RecordType *record = (RecordType *) p_type; 135 | std::vector llvm_type_vec; 136 | for (auto t : record->type_vec) { 137 | llvm_type_vec.push_back(getLLVMType(context, t)); 138 | } 139 | return llvm::StructType::get(context, llvm_type_vec); 140 | 141 | } else if (p_type->tg == PascalType::TypeGroup::ENUM) { 142 | // does not mean that enum type does not exist 143 | // it means that we do not consider it as a basic type 144 | return llvm::Type::getInt32Ty(context); 145 | 146 | } else if (p_type->tg == PascalType::TypeGroup::SUBRANGE) { 147 | // not implemented 148 | return nullptr; 149 | } 150 | } 151 | 152 | BuiltinType::BuiltinType(BuiltinType::BasicTypes type) : type(type), PascalType(PascalType::TypeGroup::BUILT_IN) {} 153 | } -------------------------------------------------------------------------------- /src/ast/ast_prog.cpp: -------------------------------------------------------------------------------- 1 | #include "ast_prog.h" 2 | #include "../visitor.h" 3 | 4 | 5 | ASTProgramHead::ASTProgramHead(std::string id) : id(id) {} 6 | 7 | ASTRoutineHead::ASTRoutineHead(ASTConstPart *const_part, ASTTypePart *type_part, 8 | ASTVarPart *var_part, 9 | ASTRoutinePart *routine_part) 10 | : const_part(const_part), 11 | type_part(type_part), 12 | var_part(var_part), 13 | routine_part(routine_part) {} 14 | 15 | ASTRoutineBody::ASTRoutineBody(ASTStmtList *compound_stmt) 16 | : compound_stmt(compound_stmt) {} 17 | 18 | ASTStmtList *ASTRoutineBody::getCompoundStmt(){ 19 | return this->compound_stmt; 20 | }; 21 | 22 | ASTRoutine::ASTRoutine(ASTRoutineHead *routine_head, 23 | ASTRoutineBody *routine_body) 24 | : routine_head(routine_head), routine_body(routine_body) {} 25 | 26 | ASTProgram::ASTProgram(ASTProgramHead *program_head, ASTRoutine *routine) 27 | : program_head(program_head), routine(routine) {} 28 | 29 | ASTRoutinePart::ASTRoutinePart(ASTFuncProcBase *func_proc) { 30 | this->routine_list.clear(); 31 | this->routine_list.push_back(func_proc); 32 | } 33 | 34 | void ASTRoutinePart::addFuncProcDecl(ASTFuncProcBase *func_proc) { 35 | this->routine_list.push_back(func_proc); 36 | } 37 | 38 | ASTFunctionDecl::ASTFunctionDecl(ASTFunctionHead *function_head, 39 | ASTRoutine *routine) 40 | : function_head(function_head), 41 | routine(routine), 42 | ASTFuncProcBase(ASTFuncProcBase::FuncType::FUNCTION) {} 43 | 44 | ASTFunctionHead::ASTFunctionHead(std::string func_name, 45 | ASTParaDeclList *parameters, 46 | ASTSimpleTypeDecl *simple_type_decl) 47 | : func_name(func_name), 48 | parameters(parameters), 49 | simple_type_decl(simple_type_decl) {} 50 | 51 | ASTProcedureDecl::ASTProcedureDecl(ASTProcedureHead *procedure_head, 52 | ASTRoutine *routine) 53 | : procedure_head(procedure_head), 54 | routine(routine), 55 | ASTFuncProcBase(ASTFuncProcBase::FuncType::PROCEDURE) {} 56 | 57 | ASTProcedureHead::ASTProcedureHead(std::string proc_name, 58 | ASTParaDeclList *parameters) 59 | : proc_name(proc_name), parameters(parameters) {} 60 | 61 | /* 62 | ASTParameters::ASTParameters(ASTParaDeclList* para_dec_list) 63 | : para_dec_list(para_dec_list) {} 64 | std::shared_ptr GraphGenerator::VisitASTParameters(ASTParameters *node) { 65 | g->AddNode("parameters", this->line(), this->col()); 66 | 67 | g->Pop(); 68 | } 69 | */ 70 | 71 | ASTParaDeclList::ASTParaDeclList() { 72 | this->para_decl_list.clear(); 73 | } 74 | 75 | void ASTParaDeclList::addParaTypeList(ASTParaTypeList *para_type_list) { 76 | this->para_decl_list.push_back(para_type_list); 77 | } 78 | 79 | ASTParaTypeList::ASTParaTypeList(ASTParaList *para_list, 80 | ASTSimpleTypeDecl *simple_type_decl) 81 | : para_list(para_list), simple_type_decl(simple_type_decl) {} 82 | 83 | ASTVarParaList::ASTVarParaList(ASTNameList *name_list) 84 | : name_list(name_list), ASTParaList(true) {} 85 | 86 | ASTValParaList::ASTValParaList(ASTNameList *name_list) 87 | : name_list(name_list), ASTParaList(false) {} 88 | 89 | std::shared_ptr ASTProgramHead::Accept(Visitor *visitor) { return visitor->VisitASTProgramHead(this); } 90 | 91 | const string &ASTProgramHead::getId() const { 92 | return id; 93 | } 94 | 95 | std::shared_ptr ASTRoutineHead::Accept(Visitor *visitor) { return visitor->VisitASTRoutineHead(this); } 96 | 97 | ASTConstPart *ASTRoutineHead::getConstPart() const { 98 | return const_part; 99 | } 100 | 101 | ASTTypePart *ASTRoutineHead::getTypePart() const { 102 | return type_part; 103 | } 104 | 105 | ASTVarPart *ASTRoutineHead::getVarPart() const { 106 | return var_part; 107 | } 108 | 109 | ASTRoutinePart *ASTRoutineHead::getRoutinePart() const { 110 | return routine_part; 111 | } 112 | 113 | std::shared_ptr ASTRoutineBody::Accept(Visitor *visitor) { return visitor->VisitASTRoutineBody(this); } 114 | 115 | std::shared_ptr ASTRoutine::Accept(Visitor *visitor) { return visitor->VisitASTRoutine(this); } 116 | 117 | ASTRoutineHead *ASTRoutine::getRoutineHead() const { 118 | return routine_head; 119 | } 120 | 121 | ASTRoutineBody *ASTRoutine::getRoutineBody() const { 122 | return routine_body; 123 | } 124 | 125 | std::shared_ptr ASTProgram::Accept(Visitor *visitor) { return visitor->VisitASTProgram(this); } 126 | 127 | ASTProgramHead *ASTProgram::getProgramHead() const { 128 | return program_head; 129 | } 130 | 131 | ASTRoutine *ASTProgram::getRoutine() const { 132 | return routine; 133 | } 134 | 135 | std::shared_ptr ASTRoutinePart::Accept(Visitor *visitor) { return visitor->VisitASTRoutinePart(this); } 136 | 137 | const vector &ASTRoutinePart::getRoutineList() const { 138 | return routine_list; 139 | } 140 | 141 | std::shared_ptr ASTFuncProcBase::Accept(Visitor *visitor) { return visitor->VisitASTFuncProcBase(this); } 142 | 143 | ASTFuncProcBase::FuncType ASTFuncProcBase::getIam() const { 144 | return iam; 145 | } 146 | 147 | ASTFunctionHead *ASTFunctionDecl::getFunctionHead() const { 148 | return function_head; 149 | } 150 | 151 | ASTRoutine *ASTFunctionDecl::getRoutine() const { 152 | return routine; 153 | } 154 | 155 | std::shared_ptr ASTFunctionDecl::Accept(Visitor *visitor) { 156 | return visitor->VisitASTFunctionDecl(this); 157 | } 158 | 159 | std::shared_ptr ASTFunctionHead::Accept(Visitor *visitor) { return visitor->VisitASTFunctionHead(this); } 160 | 161 | const string &ASTFunctionHead::getFuncName() const { 162 | return func_name; 163 | } 164 | 165 | ASTParaDeclList *ASTFunctionHead::getParameters() const { 166 | return parameters; 167 | } 168 | 169 | ASTSimpleTypeDecl *ASTFunctionHead::getSimpleTypeDecl() const { 170 | return simple_type_decl; 171 | } 172 | 173 | ASTProcedureHead *ASTProcedureDecl::getProcedureHead() const { 174 | return procedure_head; 175 | } 176 | 177 | ASTRoutine *ASTProcedureDecl::getRoutine() const { 178 | return routine; 179 | } 180 | 181 | std::shared_ptr ASTProcedureDecl::Accept(Visitor *visitor) { 182 | return visitor->VisitASTProcedureDecl(this); 183 | } 184 | 185 | std::shared_ptr ASTProcedureHead::Accept(Visitor *visitor) { 186 | return visitor->VisitASTProcedureHead(this); 187 | } 188 | 189 | const string &ASTProcedureHead::getProcName() const { 190 | return proc_name; 191 | } 192 | 193 | ASTParaDeclList *ASTProcedureHead::getParameters() const { 194 | return parameters; 195 | } 196 | 197 | std::shared_ptr ASTParaDeclList::Accept(Visitor *visitor) { return visitor->VisitASTParaDeclList(this); } 198 | 199 | const vector &ASTParaDeclList::getParaDeclList() const { 200 | return para_decl_list; 201 | } 202 | 203 | std::shared_ptr ASTParaTypeList::Accept(Visitor *visitor) { return visitor->VisitASTParaTypeList(this); } 204 | 205 | ASTParaList *ASTParaTypeList::getParaList() const { 206 | return para_list; 207 | } 208 | 209 | ASTSimpleTypeDecl *ASTParaTypeList::getSimpleTypeDecl() const { 210 | return simple_type_decl; 211 | } 212 | 213 | std::shared_ptr ASTVarParaList::Accept(Visitor *visitor) { return visitor->VisitASTVarParaList(this); } 214 | 215 | ASTNameList *ASTVarParaList::getNameList() const { 216 | return name_list; 217 | } 218 | 219 | std::shared_ptr ASTValParaList::Accept(Visitor *visitor) { return visitor->VisitASTValParaList(this); } 220 | 221 | ASTNameList *ASTValParaList::getNameList() const { 222 | return name_list; 223 | } 224 | -------------------------------------------------------------------------------- /test/bubble.pas.dot: -------------------------------------------------------------------------------- 1 | digraph g { 2 | node_0->node_1; 3 | node_1->node_2; 4 | node_0->node_3; 5 | node_3->node_4; 6 | node_4->node_5; 7 | node_5->node_6; 8 | node_6->node_7; 9 | node_7->node_8; 10 | node_8->node_9; 11 | node_7->node_10; 12 | node_10->node_11; 13 | node_11->node_12; 14 | node_10->node_13; 15 | node_13->node_14; 16 | node_6->node_15; 17 | node_15->node_16; 18 | node_16->node_17; 19 | node_16->node_18; 20 | node_16->node_19; 21 | node_16->node_20; 22 | node_15->node_21; 23 | node_21->node_22; 24 | node_6->node_23; 25 | node_23->node_24; 26 | node_24->node_25; 27 | node_23->node_26; 28 | node_26->node_27; 29 | node_3->node_28; 30 | node_28->node_29; 31 | node_29->node_30; 32 | node_30->node_31; 33 | node_30->node_32; 34 | node_32->node_33; 35 | node_33->node_34; 36 | node_29->node_35; 37 | node_35->node_36; 38 | node_35->node_37; 39 | node_35->node_38; 40 | node_38->node_39; 41 | node_35->node_40; 42 | node_40->node_41; 43 | node_40->node_42; 44 | node_42->node_43; 45 | node_43->node_44; 46 | node_43->node_45; 47 | node_45->node_46; 48 | node_29->node_47; 49 | node_47->node_48; 50 | node_47->node_49; 51 | node_47->node_50; 52 | node_50->node_51; 53 | node_51->node_52; 54 | node_50->node_53; 55 | node_47->node_54; 56 | node_54->node_55; 57 | node_55->node_56; 58 | node_56->node_57; 59 | node_55->node_58; 60 | node_54->node_59; 61 | node_59->node_60; 62 | node_59->node_61; 63 | node_61->node_62; 64 | node_62->node_63; 65 | node_61->node_64; 66 | node_59->node_65; 67 | node_65->node_66; 68 | node_59->node_67; 69 | node_67->node_68; 70 | node_68->node_69; 71 | node_69->node_70; 72 | node_69->node_71; 73 | node_71->node_72; 74 | node_72->node_73; 75 | node_71->node_74; 76 | node_68->node_75; 77 | node_75->node_76; 78 | node_75->node_77; 79 | node_77->node_78; 80 | node_67->node_79; 81 | node_79->node_80; 82 | node_80->node_81; 83 | node_81->node_82; 84 | node_80->node_83; 85 | node_83->node_84; 86 | node_83->node_85; 87 | node_85->node_86; 88 | node_86->node_87; 89 | node_85->node_88; 90 | node_79->node_89; 91 | node_89->node_90; 92 | node_90->node_91; 93 | node_90->node_92; 94 | node_92->node_93; 95 | node_93->node_94; 96 | node_92->node_95; 97 | node_89->node_96; 98 | node_96->node_97; 99 | node_96->node_98; 100 | node_98->node_99; 101 | node_79->node_100; 102 | node_100->node_101; 103 | node_101->node_102; 104 | node_101->node_103; 105 | node_103->node_104; 106 | node_100->node_105; 107 | node_105->node_106; 108 | node_79->node_107; 109 | node_107->node_108; 110 | node_108->node_109; 111 | node_107->node_110; 112 | node_54->node_111; 113 | node_111->node_112; 114 | node_112->node_113; 115 | node_111->node_114; 116 | node_29->node_115; 117 | node_115->node_116; 118 | node_115->node_117; 119 | node_115->node_118; 120 | node_118->node_119; 121 | node_115->node_120; 122 | node_120->node_121; 123 | node_121->node_122; 124 | node_122->node_123; 125 | node_121->node_124; 126 | node_124->node_125; 127 | node_120->node_126; 128 | node_126->node_127; 129 | node_126->node_128; 130 | node_128->node_129; 131 | node_129->node_130; 132 | node_129->node_131; 133 | node_131->node_132; 134 | node_128->node_133; 135 | node_120->node_134; 136 | node_134->node_135; 137 | node_135->node_136; 138 | node_135->node_137; 139 | node_137->node_138; 140 | node_138->node_139; 141 | node_138->node_140; 142 | node_140->node_141; 143 | node_0[label="program\n[25, 4]"]; 144 | node_1[label="program_head\n[1, 20]"]; 145 | node_2[label="test_bubble"]; 146 | node_3[label="routine\n[25, 1]"]; 147 | node_4[label="routine_head\n[6, 1]"]; 148 | node_5[label="var_part:\n[6, 1]"]; 149 | node_6[label="var_decl_list:\n[5, 15]"]; 150 | node_7[label="Var_decl:\n[3, 28]"]; 151 | node_8[label="name_list\n[3, 2]"]; 152 | node_9[label="r"]; 153 | node_10[label="array_type_decl\n[3, 21]"]; 154 | node_11[label="simple_type_decl\n[3, 13]"]; 155 | node_12[label=""]; 156 | node_13[label="simple_type_decl\n[3, 21]"]; 157 | node_14[label="Integer"]; 158 | node_15[label="Var_decl:\n[4, 24]"]; 159 | node_16[label="name_list\n[4, 11]"]; 160 | node_17[label="i"]; 161 | node_18[label="j"]; 162 | node_19[label="n"]; 163 | node_20[label="temp"]; 164 | node_21[label="simple_type_decl\n[4, 17]"]; 165 | node_22[label="Integer"]; 166 | node_23[label="Var_decl:\n[5, 15]"]; 167 | node_24[label="name_list\n[5, 2]"]; 168 | node_25[label="flag"]; 169 | node_26[label="simple_type_decl\n[5, 8]"]; 170 | node_27[label="Boolean"]; 171 | node_28[label="routine_body\n[25, 1]"]; 172 | node_29[label="stmt_list\n[25, 1]"]; 173 | node_30[label="proc_stmt\n[7, 10]"]; 174 | node_31[label="readln"]; 175 | node_32[label="expression_list\n[7, 10]"]; 176 | node_33[label="ID_expr\n[7, 10]"]; 177 | node_34[label="n"]; 178 | node_35[label="for_stmt: TO\n[9, 12]"]; 179 | node_36[label="i"]; 180 | node_37[label="1"]; 181 | node_38[label="ID_expr\n[8, 16]"]; 182 | node_39[label="n"]; 183 | node_40[label="proc_stmt\n[9, 12]"]; 184 | node_41[label="read"]; 185 | node_42[label="expression_list\n[9, 12]"]; 186 | node_43[label="array_expr\n[9, 12]"]; 187 | node_44[label="r"]; 188 | node_45[label="ID_expr\n[9, 11]"]; 189 | node_46[label="i"]; 190 | node_47[label="for_stmt: TO\n[22, 4]"]; 191 | node_48[label="i"]; 192 | node_49[label="1"]; 193 | node_50[label="binary_op_expr: MINUS\n[10, 18]"]; 194 | node_51[label="ID_expr\n[10, 15]"]; 195 | node_52[label="n"]; 196 | node_53[label="1"]; 197 | node_54[label="stmt_list\n[22, 4]"]; 198 | node_55[label="assign_stmt\n[12, 16]"]; 199 | node_56[label="ID_expr\n[0, 0]"]; 200 | node_57[label="flag"]; 201 | node_58[label="true"]; 202 | node_59[label="for_stmt: DOWNTO\n[20, 13]"]; 203 | node_60[label="j"]; 204 | node_61[label="binary_op_expr: MINUS\n[13, 17]"]; 205 | node_62[label="ID_expr\n[13, 14]"]; 206 | node_63[label="n"]; 207 | node_64[label="1"]; 208 | node_65[label="ID_expr\n[13, 26]"]; 209 | node_66[label="i"]; 210 | node_67[label="if_stmt\n[20, 13]"]; 211 | node_68[label="binary_op_expr: LT\n[14, 23]"]; 212 | node_69[label="array_expr\n[14, 17]"]; 213 | node_70[label="r"]; 214 | node_71[label="binary_op_expr: PLUS\n[14, 16]"]; 215 | node_72[label="ID_expr\n[14, 14]"]; 216 | node_73[label="j"]; 217 | node_74[label="1"]; 218 | node_75[label="array_expr\n[14, 23]"]; 219 | node_76[label="r"]; 220 | node_77[label="ID_expr\n[14, 21]"]; 221 | node_78[label="j"]; 222 | node_79[label="stmt_list\n[20, 10]"]; 223 | node_80[label="assign_stmt\n[16, 24]"]; 224 | node_81[label="ID_expr\n[0, 0]"]; 225 | node_82[label="temp"]; 226 | node_83[label="array_expr\n[16, 24]"]; 227 | node_84[label="r"]; 228 | node_85[label="binary_op_expr: PLUS\n[16, 23]"]; 229 | node_86[label="ID_expr\n[16, 21]"]; 230 | node_87[label="j"]; 231 | node_88[label="1"]; 232 | node_89[label="assign_stmt\n[17, 24]"]; 233 | node_90[label="array_expr\n[0, 0]"]; 234 | node_91[label="r"]; 235 | node_92[label="binary_op_expr: PLUS\n[17, 17]"]; 236 | node_93[label="ID_expr\n[17, 15]"]; 237 | node_94[label="j"]; 238 | node_95[label="1"]; 239 | node_96[label="array_expr\n[17, 24]"]; 240 | node_97[label="r"]; 241 | node_98[label="ID_expr\n[17, 23]"]; 242 | node_99[label="j"]; 243 | node_100[label="assign_stmt\n[18, 22]"]; 244 | node_101[label="array_expr\n[0, 0]"]; 245 | node_102[label="r"]; 246 | node_103[label="ID_expr\n[18, 15]"]; 247 | node_104[label="j"]; 248 | node_105[label="ID_expr\n[18, 22]"]; 249 | node_106[label="temp"]; 250 | node_107[label="assign_stmt\n[19, 23]"]; 251 | node_108[label="ID_expr\n[0, 0]"]; 252 | node_109[label="flag"]; 253 | node_110[label="false"]; 254 | node_111[label="if_stmt\n[21, 26]"]; 255 | node_112[label="ID_expr\n[21, 16]"]; 256 | node_113[label="flag"]; 257 | node_114[label="break\n[21, 21]"]; 258 | node_115[label="for_stmt: TO\n[24, 51]"]; 259 | node_116[label="i"]; 260 | node_117[label="1"]; 261 | node_118[label="ID_expr\n[23, 16]"]; 262 | node_119[label="n"]; 263 | node_120[label="if_stmt\n[24, 51]"]; 264 | node_121[label="binary_op_expr: LT\n[24, 12]"]; 265 | node_122[label="ID_expr\n[24, 8]"]; 266 | node_123[label="i"]; 267 | node_124[label="ID_expr\n[24, 12]"]; 268 | node_125[label="n"]; 269 | node_126[label="proc_stmt\n[24, 32]"]; 270 | node_127[label="write"]; 271 | node_128[label="expression_list\n[24, 32]"]; 272 | node_129[label="array_expr\n[24, 27]"]; 273 | node_130[label="r"]; 274 | node_131[label="ID_expr\n[24, 26]"]; 275 | node_132[label="i"]; 276 | node_133[label="' '"]; 277 | node_134[label="else_clause\n[24, 51]"]; 278 | node_135[label="proc_stmt\n[24, 51]"]; 279 | node_136[label="writeln"]; 280 | node_137[label="expression_list\n[24, 51]"]; 281 | node_138[label="array_expr\n[24, 51]"]; 282 | node_139[label="r"]; 283 | node_140[label="ID_expr\n[24, 50]"]; 284 | node_141[label="i"]; 285 | } -------------------------------------------------------------------------------- /src/generator/generator.h: -------------------------------------------------------------------------------- 1 | #ifndef OPC_GENERATOR_H 2 | #define OPC_GENERATOR_H 3 | 4 | #include 5 | #include "../visitor.h" 6 | #include 7 | #include 8 | 9 | namespace OurType { 10 | class EnumType; 11 | 12 | class PascalType; 13 | 14 | extern PascalType *const VOID_TYPE; 15 | }; 16 | 17 | class ValueResult; 18 | 19 | class FuncSign { 20 | public: 21 | FuncSign(int n_local, std::vector name_list, std::vector type_list, 22 | std::vector is_var, OurType::PascalType *return_type = nullptr) 23 | : name_list_(name_list), type_list_(type_list), is_var_(is_var), return_type_(return_type), 24 | n_local_variables(n_local) { 25 | if (return_type == nullptr) 26 | return_type_ = OurType::VOID_TYPE; 27 | } 28 | 29 | 30 | std::vector getTypeList() { return type_list_; } 31 | 32 | std::vector getNameList() { return name_list_; } 33 | 34 | std::vector getVarList() { return is_var_; } 35 | 36 | OurType::PascalType *getReturnType() { return return_type_; } 37 | 38 | int getLocalVariablesNum() { return this->n_local_variables; } 39 | 40 | private: 41 | int n_local_variables; // used for parameter passing 42 | std::vector type_list_; 43 | std::vector name_list_; 44 | std::vector is_var_; 45 | OurType::PascalType *return_type_; 46 | }; 47 | 48 | class CodeBlock { 49 | public: 50 | std::map named_values; 51 | std::map named_types; 52 | std::map named_functions; 53 | std::map named_funcsigns; 54 | std::map labels; 55 | std::string block_name; 56 | bool is_function; 57 | std::vector loop_breaks; 58 | 59 | bool isType(std::string id, bool check_defined = false) { 60 | return named_types.find(id) != named_types.end() && 61 | (named_values.find(id) == named_values.end() || check_defined); 62 | } 63 | 64 | bool isValue(std::string id) { 65 | return named_values.find(id) != named_values.end(); 66 | } 67 | 68 | llvm::Function *find_function(std::string id) { 69 | if (named_functions.find(id) == named_functions.end()) 70 | return nullptr; 71 | return named_functions[id]; 72 | } 73 | 74 | FuncSign *find_funcsign(std::string id) { 75 | if (named_funcsigns.find(id) == named_funcsigns.end()) 76 | return nullptr; 77 | return named_funcsigns[id]; 78 | } 79 | 80 | void set_function(std::string id, llvm::Function *function, FuncSign *funcsign) { 81 | named_funcsigns[id] = funcsign; 82 | named_functions[id] = function; 83 | } 84 | }; 85 | 86 | class Generator : public Visitor { 87 | public: 88 | int temp_variable_count = 0; 89 | llvm::LLVMContext context; 90 | llvm::IRBuilder<> builder; 91 | std::unique_ptr module; 92 | std::vector block_stack; 93 | std::map named_constants; 94 | std::vector error_message; 95 | std::vector > error_position; 96 | 97 | friend class OurType::EnumType; 98 | 99 | public: 100 | Generator(); 101 | 102 | ~Generator(); 103 | 104 | void Save(std::string path); 105 | 106 | bool genAssign(llvm::Value *dest_ptr, OurType::PascalType *dest_type, llvm::Value *src, OurType::PascalType *src_type); 107 | 108 | llvm::Value *genSysFunc(std::string id, const std::vector> &args_list); 109 | 110 | std::shared_ptr 111 | RecordErrorMessage(std::string cur_error_message, std::pair location = std::make_pair(-1, -1)); 112 | 113 | bool hasError(); 114 | 115 | void printError(); 116 | 117 | bool isSysFunc(std::string id); 118 | 119 | virtual std::shared_ptr VisitASTNode(ASTNode *node); 120 | 121 | virtual std::shared_ptr VisitASTNameList(ASTNameList *node); 122 | 123 | virtual std::shared_ptr VisitASTExpressionList(ASTExpressionList *node); 124 | 125 | virtual std::shared_ptr VisitASTBinaryExpr(ASTBinaryExpr *node); 126 | 127 | virtual std::shared_ptr VisitASTUnaryExpr(ASTUnaryExpr *node); 128 | 129 | virtual std::shared_ptr VisitASTPropExpr(ASTPropExpr *node); 130 | 131 | virtual std::shared_ptr VisitASTConstValueExpr(ASTConstValueExpr *node); 132 | 133 | virtual std::shared_ptr VisitASTFuncCall(ASTFuncCall *node); 134 | 135 | virtual std::shared_ptr VisitASTIDExpr(ASTIDExpr *node); 136 | 137 | virtual std::shared_ptr VisitASTArrayExpr(ASTArrayExpr *node); 138 | 139 | virtual std::shared_ptr VisitASTProgramHead(ASTProgramHead *node); 140 | 141 | virtual std::shared_ptr VisitASTRoutineHead(ASTRoutineHead *node); 142 | 143 | virtual std::shared_ptr VisitASTRoutineBody(ASTRoutineBody *node); 144 | 145 | virtual std::shared_ptr VisitASTRoutine(ASTRoutine *node); 146 | 147 | virtual std::shared_ptr VisitASTProgram(ASTProgram *node); 148 | 149 | virtual std::shared_ptr VisitASTRoutinePart(ASTRoutinePart *node); 150 | 151 | virtual std::shared_ptr VisitASTFuncProcBase(ASTFuncProcBase *node); 152 | 153 | virtual std::shared_ptr VisitASTFunctionDecl(ASTFunctionDecl *node); 154 | 155 | virtual std::shared_ptr VisitASTProcedureDecl(ASTProcedureDecl *node); 156 | 157 | virtual std::shared_ptr VisitASTFunctionHead(ASTFunctionHead *node); 158 | 159 | virtual std::shared_ptr VisitASTProcedureHead(ASTProcedureHead *node); 160 | 161 | virtual std::shared_ptr VisitASTParaDeclList(ASTParaDeclList *node); 162 | 163 | virtual std::shared_ptr VisitASTParaTypeList(ASTParaTypeList *node); 164 | 165 | virtual std::shared_ptr VisitASTVarParaList(ASTVarParaList *node); 166 | 167 | virtual std::shared_ptr VisitASTValParaList(ASTValParaList *node); 168 | 169 | virtual std::shared_ptr VisitASTNonLabelStmt(ASTNonLabelStmt *node); 170 | 171 | virtual std::shared_ptr VisitASTStmt(ASTStmt *node); 172 | 173 | virtual std::shared_ptr VisitASTStmtList(ASTStmtList *node); 174 | 175 | virtual std::shared_ptr VisitASTAssignStmt(ASTAssignStmt *node); 176 | 177 | virtual std::shared_ptr VisitASTProcStmt(ASTProcStmt *node); 178 | 179 | virtual std::shared_ptr VisitASTIfStmt(ASTIfStmt *node); 180 | 181 | virtual std::shared_ptr VisitASTElseClause(ASTElseClause *node); 182 | 183 | virtual std::shared_ptr VisitASTRepeatStmt(ASTRepeatStmt *node); 184 | 185 | virtual std::shared_ptr VisitASTWhileStmt(ASTWhileStmt *node); 186 | 187 | virtual std::shared_ptr VisitASTForStmt(ASTForStmt *node); 188 | 189 | virtual std::shared_ptr VisitASTCaseStmt(ASTCaseStmt *node); 190 | 191 | virtual std::shared_ptr VisitASTCaseExprList(ASTCaseExprList *node); 192 | 193 | virtual std::shared_ptr VisitASTCaseExpr(ASTCaseExpr *node); 194 | 195 | virtual std::shared_ptr VisitASTGotoStmt(ASTGotoStmt *node); 196 | 197 | shared_ptr VisitASTExitStmt(ASTExitStmt *node); 198 | 199 | shared_ptr VisitASTBreakStmt(ASTBreakStmt *node); 200 | 201 | virtual std::shared_ptr VisitASTType(ASTType *node); 202 | 203 | virtual std::shared_ptr VisitASTSimpleTypeDecl(ASTSimpleTypeDecl *node); 204 | 205 | virtual std::shared_ptr VisitASTArrayTypeDecl(ASTArrayTypeDecl *node); 206 | 207 | virtual std::shared_ptr VisitASTFieldDecl(ASTFieldDecl *node); 208 | 209 | virtual std::shared_ptr VisitASTFieldDeclList(ASTFieldDeclList *node); 210 | 211 | virtual std::shared_ptr VisitASTRecordTypeDecl(ASTRecordTypeDecl *node); 212 | 213 | virtual std::shared_ptr VisitASTTypeDefinition(ASTTypeDefinition *node); 214 | 215 | virtual std::shared_ptr VisitASTTypeDeclList(ASTTypeDeclList *node); 216 | 217 | virtual std::shared_ptr VisitASTTypePart(ASTTypePart *node); 218 | 219 | virtual std::shared_ptr VisitASTConstValue(ASTConstValue *node); 220 | 221 | virtual std::shared_ptr VisitASTConstExprList(ASTConstExprList *node); 222 | 223 | virtual std::shared_ptr VisitASTConstExpr(ASTConstExpr *node); 224 | 225 | virtual std::shared_ptr VisitASTConstPart(ASTConstPart *node); 226 | 227 | virtual std::shared_ptr VisitASTVarPart(ASTVarPart *node); 228 | 229 | virtual std::shared_ptr VisitASTVarDeclList(ASTVarDeclList *node); 230 | 231 | virtual std::shared_ptr VisitASTVarDecl(ASTVarDecl *node); 232 | 233 | 234 | CodeBlock *getCurrentBlock(void); 235 | 236 | pair, vector> getAllLocalVarNameType(); 237 | 238 | OurType::PascalType *getVarType(std::string id); 239 | }; 240 | 241 | #endif //OPC_GENERATOR_H -------------------------------------------------------------------------------- /test/bubble.pas.ll: -------------------------------------------------------------------------------- 1 | ; ModuleID = 'pascal_module' 2 | source_filename = "pascal_module" 3 | 4 | @r = common global [100 x i32] zeroinitializer 5 | @i = common global i32 0 6 | @j = common global i32 0 7 | @n = common global i32 0 8 | @temp = common global i32 0 9 | @flag = common global i1 false 10 | @scanf_format = private unnamed_addr constant [9 x i8] c"%d%*[^\0A]\00" 11 | @scanf_newline = private unnamed_addr constant [4 x i8] c"%*c\00" 12 | @scanf_format.1 = private unnamed_addr constant [3 x i8] c"%d\00" 13 | @printf_format = private unnamed_addr constant [5 x i8] c"%d%c\00" 14 | @printf_format.2 = private unnamed_addr constant [4 x i8] c"%d\0A\00" 15 | 16 | define i32 @main() { 17 | entry: 18 | %0 = load i32, i32* @n 19 | %call_scanf = call i32 (i8*, ...) @scanf(i8* getelementptr inbounds ([9 x i8], [9 x i8]* @scanf_format, i32 0, i32 0), i32* @n) 20 | %call_scanf1 = call i32 (i8*, ...) @scanf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @scanf_newline, i32 0, i32 0)) 21 | br label %for_start 22 | 23 | for_start: ; preds = %entry 24 | %1 = load i32, i32* @i 25 | store i32 1, i32* @i 26 | %2 = load i32, i32* @i 27 | %3 = load i32, i32* @n 28 | %cmptmp = icmp sgt i32 %2, %3 29 | br i1 %cmptmp, label %for_end, label %for_body 30 | 31 | for_body: ; preds = %for_cond, %for_start 32 | %4 = load i32, i32* @i 33 | %5 = load [100 x i32], [100 x i32]* @r 34 | %subtmp = sub i32 %4, 1 35 | %ArrayCall = getelementptr [100 x i32], [100 x i32]* @r, i32 0, i32 %subtmp 36 | %6 = load i32, i32* %ArrayCall 37 | %call_scanf2 = call i32 (i8*, ...) @scanf(i8* getelementptr inbounds ([3 x i8], [3 x i8]* @scanf_format.1, i32 0, i32 0), i32* %ArrayCall) 38 | br label %for_cond 39 | 40 | for_cond: ; preds = %for_body 41 | %7 = load i32, i32* @i 42 | %8 = load i32, i32* @i 43 | %addtmp = add i32 %8, 1 44 | store i32 %addtmp, i32* @i 45 | %9 = load i32, i32* @i 46 | %10 = load i32, i32* @n 47 | %cmptmp3 = icmp sgt i32 %9, %10 48 | br i1 %cmptmp3, label %for_step_back, label %for_body 49 | 50 | for_step_back: ; preds = %for_cond 51 | %11 = load i32, i32* @i 52 | %12 = load i32, i32* @i 53 | %subtmp4 = sub i32 %12, 1 54 | store i32 %subtmp4, i32* @i 55 | br label %for_end 56 | 57 | for_end: ; preds = %for_step_back, %for_start 58 | br label %for_start5 59 | 60 | for_start5: ; preds = %for_end 61 | %13 = load i32, i32* @i 62 | store i32 1, i32* @i 63 | %14 = load i32, i32* @i 64 | %15 = load i32, i32* @n 65 | %subtmp10 = sub i32 %15, 1 66 | %cmptmp11 = icmp sgt i32 %14, %subtmp10 67 | br i1 %cmptmp11, label %for_end9, label %for_body6 68 | 69 | for_body6: ; preds = %for_cond7, %for_start5 70 | %16 = load i1, i1* @flag 71 | store i1 true, i1* @flag 72 | br label %for_start12 73 | 74 | for_cond7: ; preds = %if_cont40 75 | %17 = load i32, i32* @i 76 | %18 = load i32, i32* @i 77 | %addtmp41 = add i32 %18, 1 78 | store i32 %addtmp41, i32* @i 79 | %19 = load i32, i32* @i 80 | %20 = load i32, i32* @n 81 | %subtmp42 = sub i32 %20, 1 82 | %cmptmp43 = icmp sgt i32 %19, %subtmp42 83 | br i1 %cmptmp43, label %for_step_back8, label %for_body6 84 | 85 | for_step_back8: ; preds = %for_cond7 86 | %21 = load i32, i32* @i 87 | %22 = load i32, i32* @i 88 | %subtmp44 = sub i32 %22, 1 89 | store i32 %subtmp44, i32* @i 90 | br label %for_end9 91 | 92 | for_end9: ; preds = %for_step_back8, %if_then38, %for_start5 93 | br label %for_start45 94 | 95 | for_start12: ; preds = %for_body6 96 | %23 = load i32, i32* @j 97 | %24 = load i32, i32* @n 98 | %subtmp17 = sub i32 %24, 1 99 | store i32 %subtmp17, i32* @j 100 | %25 = load i32, i32* @j 101 | %26 = load i32, i32* @i 102 | %cmptmp18 = icmp slt i32 %25, %26 103 | br i1 %cmptmp18, label %for_end16, label %for_body13 104 | 105 | for_body13: ; preds = %for_cond14, %for_start12 106 | %27 = load i32, i32* @j 107 | %addtmp19 = add i32 %27, 1 108 | %28 = load [100 x i32], [100 x i32]* @r 109 | %subtmp20 = sub i32 %addtmp19, 1 110 | %ArrayCall21 = getelementptr [100 x i32], [100 x i32]* @r, i32 0, i32 %subtmp20 111 | %29 = load i32, i32* %ArrayCall21 112 | %30 = load i32, i32* @j 113 | %31 = load [100 x i32], [100 x i32]* @r 114 | %subtmp22 = sub i32 %30, 1 115 | %ArrayCall23 = getelementptr [100 x i32], [100 x i32]* @r, i32 0, i32 %subtmp22 116 | %32 = load i32, i32* %ArrayCall23 117 | %cmptmp24 = icmp slt i32 %29, %32 118 | br i1 %cmptmp24, label %if_then, label %if_else 119 | 120 | for_cond14: ; preds = %if_cont 121 | %33 = load i32, i32* @j 122 | %34 = load i32, i32* @j 123 | %addtmp35 = add i32 %34, -1 124 | store i32 %addtmp35, i32* @j 125 | %35 = load i32, i32* @j 126 | %36 = load i32, i32* @i 127 | %cmptmp36 = icmp slt i32 %35, %36 128 | br i1 %cmptmp36, label %for_step_back15, label %for_body13 129 | 130 | for_step_back15: ; preds = %for_cond14 131 | %37 = load i32, i32* @j 132 | %38 = load i32, i32* @j 133 | %subtmp37 = sub i32 %38, -1 134 | store i32 %subtmp37, i32* @j 135 | br label %for_end16 136 | 137 | for_end16: ; preds = %for_step_back15, %for_start12 138 | %39 = load i1, i1* @flag 139 | br i1 %39, label %if_then38, label %if_else39 140 | 141 | if_then: ; preds = %for_body13 142 | %40 = load i32, i32* @temp 143 | %41 = load i32, i32* @j 144 | %addtmp25 = add i32 %41, 1 145 | %42 = load [100 x i32], [100 x i32]* @r 146 | %subtmp26 = sub i32 %addtmp25, 1 147 | %ArrayCall27 = getelementptr [100 x i32], [100 x i32]* @r, i32 0, i32 %subtmp26 148 | %43 = load i32, i32* %ArrayCall27 149 | store i32 %43, i32* @temp 150 | %44 = load i32, i32* @j 151 | %addtmp28 = add i32 %44, 1 152 | %45 = load [100 x i32], [100 x i32]* @r 153 | %subtmp29 = sub i32 %addtmp28, 1 154 | %ArrayCall30 = getelementptr [100 x i32], [100 x i32]* @r, i32 0, i32 %subtmp29 155 | %46 = load i32, i32* %ArrayCall30 156 | %47 = load i32, i32* @j 157 | %48 = load [100 x i32], [100 x i32]* @r 158 | %subtmp31 = sub i32 %47, 1 159 | %ArrayCall32 = getelementptr [100 x i32], [100 x i32]* @r, i32 0, i32 %subtmp31 160 | %49 = load i32, i32* %ArrayCall32 161 | store i32 %49, i32* %ArrayCall30 162 | %50 = load i32, i32* @j 163 | %51 = load [100 x i32], [100 x i32]* @r 164 | %subtmp33 = sub i32 %50, 1 165 | %ArrayCall34 = getelementptr [100 x i32], [100 x i32]* @r, i32 0, i32 %subtmp33 166 | %52 = load i32, i32* %ArrayCall34 167 | %53 = load i32, i32* @temp 168 | store i32 %53, i32* %ArrayCall34 169 | %54 = load i1, i1* @flag 170 | store i1 false, i1* @flag 171 | br label %if_cont 172 | 173 | if_else: ; preds = %for_body13 174 | br label %if_cont 175 | 176 | if_cont: ; preds = %if_else, %if_then 177 | br label %for_cond14 178 | 179 | if_then38: ; preds = %for_end16 180 | br label %for_end9 181 | 182 | if_else39: ; preds = %for_end16 183 | br label %if_cont40 184 | 185 | if_cont40: ; preds = %if_else39, %break_cont 186 | br label %for_cond7 187 | 188 | break_cont: ; No predecessors! 189 | br label %if_cont40 190 | 191 | for_start45: ; preds = %for_end9 192 | %55 = load i32, i32* @i 193 | store i32 1, i32* @i 194 | %56 = load i32, i32* @i 195 | %57 = load i32, i32* @n 196 | %cmptmp50 = icmp sgt i32 %56, %57 197 | br i1 %cmptmp50, label %for_end49, label %for_body46 198 | 199 | for_body46: ; preds = %for_cond47, %for_start45 200 | %58 = load i32, i32* @i 201 | %59 = load i32, i32* @n 202 | %cmptmp54 = icmp slt i32 %58, %59 203 | br i1 %cmptmp54, label %if_then51, label %if_else52 204 | 205 | for_cond47: ; preds = %if_cont53 206 | %60 = load i32, i32* @i 207 | %61 = load i32, i32* @i 208 | %addtmp60 = add i32 %61, 1 209 | store i32 %addtmp60, i32* @i 210 | %62 = load i32, i32* @i 211 | %63 = load i32, i32* @n 212 | %cmptmp61 = icmp sgt i32 %62, %63 213 | br i1 %cmptmp61, label %for_step_back48, label %for_body46 214 | 215 | for_step_back48: ; preds = %for_cond47 216 | %64 = load i32, i32* @i 217 | %65 = load i32, i32* @i 218 | %subtmp62 = sub i32 %65, 1 219 | store i32 %subtmp62, i32* @i 220 | br label %for_end49 221 | 222 | for_end49: ; preds = %for_step_back48, %for_start45 223 | ret i32 0 224 | 225 | if_then51: ; preds = %for_body46 226 | %66 = load i32, i32* @i 227 | %67 = load [100 x i32], [100 x i32]* @r 228 | %subtmp55 = sub i32 %66, 1 229 | %ArrayCall56 = getelementptr [100 x i32], [100 x i32]* @r, i32 0, i32 %subtmp55 230 | %68 = load i32, i32* %ArrayCall56 231 | %call_printf = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([5 x i8], [5 x i8]* @printf_format, i32 0, i32 0), i32 %68, i8 32) 232 | br label %if_cont53 233 | 234 | if_else52: ; preds = %for_body46 235 | %69 = load i32, i32* @i 236 | %70 = load [100 x i32], [100 x i32]* @r 237 | %subtmp57 = sub i32 %69, 1 238 | %ArrayCall58 = getelementptr [100 x i32], [100 x i32]* @r, i32 0, i32 %subtmp57 239 | %71 = load i32, i32* %ArrayCall58 240 | %call_printf59 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @printf_format.2, i32 0, i32 0), i32 %71) 241 | br label %if_cont53 242 | 243 | if_cont53: ; preds = %if_else52, %if_then51 244 | br label %for_cond47 245 | } 246 | 247 | declare i32 @scanf(i8*, ...) 248 | 249 | declare i32 @printf(i8*, ...) 250 | -------------------------------------------------------------------------------- /src/lexer/pascal.l: -------------------------------------------------------------------------------- 1 | %option noyywrap yylineno caseless 2 | %{ 3 | #define YYSTYPE char* 4 | //#define DEBUG_LEXER 5 | 6 | #include 7 | #include "pascal.y.hpp" 8 | using namespace std; 9 | int yycolumn = 1; 10 | #define YY_USER_ACTION yylloc.first_line = yylloc.last_line = yylineno; \ 11 | yylloc.first_column = yycolumn; yylloc.last_column = yycolumn + yyleng - 1; \ 12 | yycolumn += yyleng; 13 | 14 | #ifdef DEBUG_LEXER 15 | #define RETURN_TOKEN(X) printf(#X); printf("\n");// return (X); 16 | #else 17 | #define RETURN_TOKEN(X) return(X); 18 | #endif 19 | 20 | %} 21 | 22 | 23 | KWD_AND and 24 | KWD_ARRAY array 25 | KWD_ASM asm 26 | KWD_BEGIN begin 27 | KWD_BREAK break 28 | KWD_CASE case 29 | KWD_CONST const 30 | KWD_CONSTRUCTOR constructor 31 | KWD_DESTRUCTOR destructor 32 | KWD_DIV div 33 | KWD_DO do 34 | KWD_DOWNTO downto 35 | KWD_ELSE else 36 | KWD_END end 37 | KWD_EXIT exit 38 | KWD_FILE file 39 | KWD_FOR for 40 | KWD_FUNCTION function 41 | KWD_GOTO goto 42 | KWD_IF if 43 | KWD_IMPLEMENTATION implementation 44 | KWD_IN in 45 | KWD_INHERITED inherited 46 | KWD_INLINE inline 47 | KWD_INTERFACE interface 48 | KWD_LABEL label 49 | KWD_MOD mod 50 | KWD_NIL nil 51 | KWD_NOT not 52 | KWD_OBJECT object 53 | KWD_OF of 54 | KWD_OPERATOR operator 55 | KWD_OR or 56 | KWD_PACKED packed 57 | KWD_PROCEDURE procedure 58 | KWD_PROGRAM program 59 | KWD_RECORD record 60 | KWD_REINTRODUCE reintroduce 61 | KWD_REPEAT repeat 62 | KWD_SELF self 63 | KWD_SET set 64 | KWD_SHL shl 65 | KWD_SHR shr 66 | KWD_THEN then 67 | KWD_TO to 68 | KWD_TYPE type 69 | KWD_UNIT unit 70 | KWD_UNTIL until 71 | KWD_USES uses 72 | KWD_VAR var 73 | KWD_WHILE while 74 | KWD_WITH with 75 | KWD_XOR xor 76 | 77 | /* TODO: Some of the Pascal base types here: P24 3.1*/ 78 | TYPE_INT integer 79 | TYPE_INT_8 short 80 | TYPE_INT_16 smallint 81 | TYPE_INT_32 longint 82 | TYPE_INT_64 int64 83 | TYPE_UNSIGNED_INT_8 byte 84 | TYPE_UNSIGNED_INT_16 word 85 | TYPE_UNSIGNED_INT_32 longword 86 | TYPE_UNSIGNED_INT_64 qword 87 | TYPE_BOOLEAN boolean 88 | TYPE_FLOAT real 89 | TYPE_FLOAT_16 single 90 | TYPE_FLOAT_32 double 91 | TYPE_CHAR char|character 92 | TYPE_STRING string 93 | /* Values here*/ 94 | SIGN "+"|"-" 95 | LITERAL_TRUE true 96 | LITERAL_FALSE false 97 | LITERAL_INT [0-9]+ 98 | LITERAL_FLOAT ([0-9]+\.[0-9]+)|([0-9]+\.[0-9]+e{SIGN}?[0-9]+)|([0-9]+e{SIGN}?[0-9]+) 99 | LITERAL_CHAR \'.\' 100 | LITERAL_ESC_CHAR '\'#\' 101 | LITERAL_STR \'([^']|{LITERAL_ESC_CHAR})*\' 102 | 103 | /* TODO: Pascal symbols here: */ 104 | SYM_ADD "+" 105 | SYM_SUB "-" 106 | SYM_MUL "*" 107 | SYM_DIV "/" 108 | SYM_EQ "=" 109 | SYM_LT "<" 110 | SYM_GT ">" 111 | SYM_LBRAC "[" 112 | SYM_RBRAC "]" 113 | SYM_PERIOD "." 114 | SYM_COMMA "," 115 | SYM_COLON ":" 116 | SYM_SEMICOLON ";" 117 | SYM_AT "@" 118 | SYM_CARET "^" 119 | SYM_LPAREN "(" 120 | SYM_RPAREN ")" 121 | SYM_NE "<>" 122 | SYM_LE "<=" 123 | SYM_GE ">=" 124 | SYM_ASSIGN ":=" 125 | SYM_RANGE ".." 126 | 127 | /* TODO: Other tokens */ 128 | COMMENT "{"[^\}]*"}" 129 | IDENTIFIER [a-zA-Z_][a-zA-Z0-9_]* 130 | %% 131 | 132 | {KWD_AND} { 133 | RETURN_TOKEN(KWD_AND) 134 | } 135 | 136 | {KWD_ARRAY} { 137 | RETURN_TOKEN(KWD_ARRAY) 138 | } 139 | 140 | {KWD_ASM} { 141 | RETURN_TOKEN(KWD_ASM) 142 | } 143 | 144 | {KWD_BEGIN} { 145 | RETURN_TOKEN(KWD_BEGIN) 146 | } 147 | 148 | {KWD_BREAK} { 149 | RETURN_TOKEN(KWD_BREAK) 150 | } 151 | 152 | {KWD_CASE} { 153 | RETURN_TOKEN(KWD_CASE) 154 | } 155 | 156 | {KWD_CONST} { 157 | RETURN_TOKEN(KWD_CONST) 158 | } 159 | 160 | {KWD_CONSTRUCTOR} { 161 | RETURN_TOKEN(KWD_CONSTRUCTOR) 162 | } 163 | 164 | {KWD_DESTRUCTOR} { 165 | RETURN_TOKEN(KWD_DESTRUCTOR) 166 | } 167 | 168 | {KWD_DIV} { 169 | RETURN_TOKEN(KWD_DIV) 170 | } 171 | 172 | {KWD_DO} { 173 | RETURN_TOKEN(KWD_DO) 174 | } 175 | 176 | {KWD_DOWNTO} { 177 | RETURN_TOKEN(KWD_DOWNTO) 178 | } 179 | 180 | {KWD_ELSE} { 181 | RETURN_TOKEN(KWD_ELSE) 182 | } 183 | 184 | {KWD_END} { 185 | RETURN_TOKEN(KWD_END) 186 | } 187 | 188 | {KWD_FILE} { 189 | RETURN_TOKEN(KWD_FILE) 190 | } 191 | 192 | {KWD_FOR} { 193 | RETURN_TOKEN(KWD_FOR) 194 | } 195 | 196 | {KWD_FUNCTION} { 197 | RETURN_TOKEN(KWD_FUNCTION) 198 | } 199 | 200 | {KWD_GOTO} { 201 | RETURN_TOKEN(KWD_GOTO) 202 | } 203 | 204 | {KWD_EXIT} { 205 | RETURN_TOKEN(KWD_EXIT) 206 | } 207 | 208 | {KWD_IF} { 209 | RETURN_TOKEN(KWD_IF) 210 | } 211 | 212 | {KWD_IMPLEMENTATION} { 213 | RETURN_TOKEN(KWD_IMPLEMENTATION) 214 | } 215 | 216 | {KWD_IN} { 217 | RETURN_TOKEN(KWD_IN) 218 | } 219 | 220 | {KWD_INHERITED} { 221 | RETURN_TOKEN(KWD_INHERITED) 222 | } 223 | 224 | {KWD_INLINE} { 225 | RETURN_TOKEN(KWD_INLINE) 226 | } 227 | 228 | {KWD_INTERFACE} { 229 | RETURN_TOKEN(KWD_INTERFACE) 230 | } 231 | 232 | {KWD_LABEL} { 233 | RETURN_TOKEN(KWD_LABEL) 234 | } 235 | 236 | {KWD_MOD} { 237 | RETURN_TOKEN(KWD_MOD) 238 | } 239 | 240 | {KWD_NIL} { 241 | RETURN_TOKEN(KWD_NIL) 242 | } 243 | 244 | {KWD_NOT} { 245 | RETURN_TOKEN(KWD_NOT) 246 | } 247 | 248 | {KWD_OBJECT} { 249 | RETURN_TOKEN(KWD_OBJECT) 250 | } 251 | 252 | {KWD_OF} { 253 | RETURN_TOKEN(KWD_OF) 254 | } 255 | 256 | {KWD_OPERATOR} { 257 | RETURN_TOKEN(KWD_OPERATOR) 258 | } 259 | 260 | {KWD_OR} { 261 | RETURN_TOKEN(KWD_OR) 262 | } 263 | 264 | {KWD_PACKED} { 265 | RETURN_TOKEN(KWD_PACKED) 266 | } 267 | 268 | {KWD_PROCEDURE} { 269 | RETURN_TOKEN(KWD_PROCEDURE) 270 | } 271 | 272 | {KWD_PROGRAM} { 273 | RETURN_TOKEN(KWD_PROGRAM) 274 | } 275 | 276 | {KWD_RECORD} { 277 | RETURN_TOKEN(KWD_RECORD) 278 | } 279 | 280 | {KWD_REINTRODUCE} { 281 | RETURN_TOKEN(KWD_REINTRODUCE) 282 | } 283 | 284 | {KWD_REPEAT} { 285 | RETURN_TOKEN(KWD_REPEAT) 286 | } 287 | 288 | {KWD_SELF} { 289 | RETURN_TOKEN(KWD_SELF) 290 | } 291 | 292 | {KWD_SET} { 293 | RETURN_TOKEN(KWD_SET) 294 | } 295 | 296 | {KWD_SHL} { 297 | RETURN_TOKEN(KWD_SHL) 298 | } 299 | 300 | {KWD_SHR} { 301 | RETURN_TOKEN(KWD_SHR) 302 | } 303 | 304 | {KWD_THEN} { 305 | RETURN_TOKEN(KWD_THEN) 306 | } 307 | 308 | {KWD_TO} { 309 | RETURN_TOKEN(KWD_TO) 310 | } 311 | 312 | {KWD_TYPE} { 313 | RETURN_TOKEN(KWD_TYPE) 314 | } 315 | 316 | {KWD_UNIT} { 317 | RETURN_TOKEN(KWD_UNIT) 318 | } 319 | 320 | {KWD_UNTIL} { 321 | RETURN_TOKEN(KWD_UNTIL) 322 | } 323 | 324 | {KWD_USES} { 325 | RETURN_TOKEN(KWD_USES) 326 | } 327 | 328 | {KWD_VAR} { 329 | RETURN_TOKEN(KWD_VAR) 330 | } 331 | 332 | {KWD_WHILE} { 333 | RETURN_TOKEN(KWD_WHILE) 334 | } 335 | 336 | {KWD_WITH} { 337 | RETURN_TOKEN(KWD_WITH) 338 | } 339 | 340 | {KWD_XOR} { 341 | RETURN_TOKEN(KWD_XOR) 342 | } 343 | 344 | {TYPE_INT} { 345 | RETURN_TOKEN(TYPE_INT) 346 | } 347 | 348 | {TYPE_INT_8} { 349 | RETURN_TOKEN(TYPE_INT_8) 350 | } 351 | 352 | {TYPE_INT_16} { 353 | RETURN_TOKEN(TYPE_INT_16) 354 | } 355 | 356 | {TYPE_INT_32} { 357 | RETURN_TOKEN(TYPE_INT_32) 358 | } 359 | 360 | {TYPE_INT_64} { 361 | RETURN_TOKEN(TYPE_INT_64) 362 | } 363 | 364 | {TYPE_UNSIGNED_INT_8} { 365 | RETURN_TOKEN(TYPE_UNSIGNED_INT_8) 366 | } 367 | 368 | {TYPE_UNSIGNED_INT_16} { 369 | RETURN_TOKEN(TYPE_UNSIGNED_INT_16) 370 | } 371 | 372 | {TYPE_UNSIGNED_INT_32} { 373 | RETURN_TOKEN(TYPE_UNSIGNED_INT_32) 374 | } 375 | 376 | {TYPE_UNSIGNED_INT_64} { 377 | RETURN_TOKEN(TYPE_UNSIGNED_INT_64) 378 | } 379 | 380 | {TYPE_BOOLEAN} { 381 | RETURN_TOKEN(TYPE_BOOLEAN) 382 | } 383 | 384 | {TYPE_FLOAT} { 385 | RETURN_TOKEN(TYPE_FLOAT) 386 | } 387 | 388 | {TYPE_FLOAT_16} { 389 | RETURN_TOKEN(TYPE_FLOAT_16) 390 | } 391 | 392 | {TYPE_FLOAT_32} { 393 | RETURN_TOKEN(TYPE_FLOAT_32) 394 | } 395 | 396 | {TYPE_CHAR} { 397 | RETURN_TOKEN(TYPE_CHAR) 398 | } 399 | 400 | {TYPE_STRING} { 401 | RETURN_TOKEN(TYPE_STRING) 402 | } 403 | 404 | {LITERAL_INT} { 405 | yylval = strdup(yytext); 406 | RETURN_TOKEN(LITERAL_INT) 407 | } 408 | 409 | {LITERAL_FLOAT} { 410 | yylval = strdup(yytext); 411 | RETURN_TOKEN(LITERAL_FLOAT) 412 | } 413 | 414 | {LITERAL_CHAR} { 415 | yylval = strdup(yytext); 416 | RETURN_TOKEN(LITERAL_CHAR) 417 | } 418 | 419 | {LITERAL_ESC_CHAR} { 420 | yylval = strdup(yytext); 421 | RETURN_TOKEN(LITERAL_ESC_CHAR) 422 | } 423 | 424 | {LITERAL_STR} { 425 | yylval = strdup(yytext); 426 | RETURN_TOKEN(LITERAL_STR) 427 | } 428 | 429 | {LITERAL_TRUE} { 430 | yylval = strdup(yytext); 431 | RETURN_TOKEN(LITERAL_TRUE) 432 | } 433 | 434 | {LITERAL_FALSE} { 435 | yylval = strdup(yytext); 436 | RETURN_TOKEN(LITERAL_FALSE) 437 | } 438 | 439 | {IDENTIFIER} { 440 | yylval = strdup(yytext); 441 | RETURN_TOKEN(IDENTIFIER) 442 | } 443 | 444 | {SYM_ADD} { 445 | RETURN_TOKEN(SYM_ADD) 446 | } 447 | 448 | {SYM_SUB} { 449 | RETURN_TOKEN(SYM_SUB) 450 | } 451 | 452 | {SYM_MUL} { 453 | RETURN_TOKEN(SYM_MUL) 454 | } 455 | 456 | {SYM_DIV} { 457 | RETURN_TOKEN(SYM_DIV) 458 | } 459 | 460 | {SYM_EQ} { 461 | RETURN_TOKEN(SYM_EQ) 462 | } 463 | 464 | {SYM_LT} { 465 | RETURN_TOKEN(SYM_LT) 466 | } 467 | 468 | {SYM_GT} { 469 | RETURN_TOKEN(SYM_GT) 470 | } 471 | 472 | {SYM_LBRAC} { 473 | RETURN_TOKEN(SYM_LBRAC) 474 | } 475 | 476 | {SYM_RBRAC} { 477 | RETURN_TOKEN(SYM_RBRAC) 478 | } 479 | 480 | {SYM_PERIOD} { 481 | RETURN_TOKEN(SYM_PERIOD) 482 | } 483 | 484 | {SYM_COMMA} { 485 | RETURN_TOKEN(SYM_COMMA) 486 | } 487 | 488 | {SYM_COLON} { 489 | RETURN_TOKEN(SYM_COLON) 490 | } 491 | 492 | {SYM_SEMICOLON} { 493 | RETURN_TOKEN(SYM_SEMICOLON) 494 | } 495 | 496 | {SYM_AT} { 497 | RETURN_TOKEN(SYM_AT) 498 | } 499 | 500 | {SYM_CARET} { 501 | RETURN_TOKEN(SYM_CARET) 502 | } 503 | 504 | {SYM_LPAREN} { 505 | RETURN_TOKEN(SYM_LPAREN) 506 | } 507 | 508 | {SYM_RPAREN} { 509 | RETURN_TOKEN(SYM_RPAREN) 510 | } 511 | 512 | {SYM_NE} { 513 | RETURN_TOKEN(SYM_NE) 514 | } 515 | 516 | {SYM_LE} { 517 | RETURN_TOKEN(SYM_LE) 518 | } 519 | 520 | {SYM_GE} { 521 | RETURN_TOKEN(SYM_GE) 522 | } 523 | 524 | {SYM_ASSIGN} { 525 | RETURN_TOKEN(SYM_ASSIGN) 526 | } 527 | 528 | {SYM_RANGE} { 529 | RETURN_TOKEN(SYM_RANGE) 530 | } 531 | 532 | 533 | {COMMENT} {} 534 | 535 | \n|(\r\n) { 536 | yycolumn = 1; 537 | } 538 | " "|\t {} 539 | 540 | . { 541 | printf("unknown character %d\n", (int) yytext[0]); 542 | return yytext[0]; 543 | } 544 | %% 545 | 546 | void yyerror(const char *s) { 547 | fprintf(stderr, "LexError: %s (at Line %d, Column%d)\n", s, yylloc.first_line, yylloc.first_column); 548 | } 549 | 550 | #ifdef DEBUG_LEXER 551 | 552 | int main() { 553 | yylex(); 554 | return 0; 555 | } 556 | 557 | #endif -------------------------------------------------------------------------------- /src/generator/generator_program.cpp: -------------------------------------------------------------------------------- 1 | #include "generator.h" 2 | #include "../ast/ast_prog.h" 3 | #include "generator_result.hpp" 4 | #include 5 | 6 | std::shared_ptr Generator::VisitASTProgramHead(ASTProgramHead *node) { 7 | //do nothing 8 | return nullptr; 9 | } 10 | 11 | std::shared_ptr Generator::VisitASTRoutineHead(ASTRoutineHead *node) { 12 | if (node->getConstPart()) node->getConstPart()->Accept(this); 13 | if (node->getTypePart()) node->getTypePart()->Accept(this); 14 | if (node->getVarPart()) node->getVarPart()->Accept(this); 15 | if (node->getRoutinePart()) node->getRoutinePart()->Accept(this); 16 | return nullptr; 17 | } 18 | 19 | std::shared_ptr Generator::VisitASTRoutineBody(ASTRoutineBody *node) { 20 | return node->getCompoundStmt()->Accept(this); 21 | } 22 | 23 | std::shared_ptr Generator::VisitASTRoutine(ASTRoutine *node) { 24 | node->getRoutineHead()->Accept(this); 25 | //std::cout << "routine_head ready" << std::endl; 26 | node->getRoutineBody()->Accept(this); 27 | return nullptr; 28 | } 29 | 30 | std::shared_ptr Generator::VisitASTProgram(ASTProgram *node) { 31 | node->getProgramHead()->Accept(this); 32 | this->block_stack.push_back(new CodeBlock()); 33 | llvm::FunctionType *func_type = llvm::FunctionType::get(OurType::getLLVMType(this->context, OurType::INT_TYPE), false); 34 | llvm::Function *main_func = llvm::Function::Create(func_type, llvm::Function::ExternalLinkage, "main", &*(this->module)); 35 | llvm::BasicBlock *entry = llvm::BasicBlock::Create(this->context, "entry", main_func); 36 | this->builder.SetInsertPoint(entry); 37 | node->getRoutine()->Accept(this); 38 | this->builder.CreateRet(llvm::ConstantInt::get(llvm::Type::getInt32Ty(this->context), 0, true)); 39 | return nullptr; 40 | } 41 | 42 | std::shared_ptr Generator::VisitASTRoutinePart(ASTRoutinePart *node) { 43 | for (auto decl: node->getRoutineList()) decl->Accept(this); 44 | return nullptr; 45 | } 46 | 47 | std::shared_ptr Generator::VisitASTFuncProcBase(ASTFuncProcBase *node) { 48 | bool is_function = node->getIam() == ASTFuncProcBase::FuncType::FUNCTION; 49 | auto parameters = std::static_pointer_cast( 50 | is_function ? ((ASTFunctionDecl*)node)->getFunctionHead()->getParameters()->Accept(this) 51 | : ((ASTProcedureDecl*)node)->getProcedureHead()->getParameters()->Accept(this)); 52 | 53 | if (parameters == nullptr) 54 | return RecordErrorMessage("Can not recognize the parameters for function/procedure definition.", node->get_location_pairs()); 55 | 56 | OurType::PascalType *return_type = OurType::VOID_TYPE; 57 | std::string func_name; 58 | if (is_function){ 59 | func_name = ((ASTFunctionDecl*)node)->getFunctionHead()->getFuncName(); 60 | auto return_type_result = std::static_pointer_cast(((ASTFunctionDecl*)node)->getFunctionHead()->getSimpleTypeDecl()->Accept(this)); 61 | if (return_type_result == nullptr) 62 | return RecordErrorMessage("Can not recognize the return type for the function definition.", node->get_location_pairs()); 63 | return_type = return_type_result->getType(); 64 | }else{ 65 | func_name = ((ASTProcedureDecl*)node)->getProcedureHead()->getProcName(); 66 | } 67 | llvm::Type *llvm_return_type = OurType::getLLVMType(context, return_type); 68 | auto name_list = parameters->getNameList(); 69 | auto type_var_list = parameters->getTypeList(); 70 | std::vector llvm_type_list; 71 | std::vector type_list; 72 | std::vector var_list; 73 | 74 | for (int i = 0; i < name_list.size(); i++) 75 | for (int j = i+1; j < name_list.size(); j++) 76 | if (name_list[i] == name_list[j]) 77 | return RecordErrorMessage("The parameters in the function/procedure definition are duplicated.", node->get_location_pairs()); 78 | 79 | // Adding local variables 80 | // we must put local variables first 81 | // because after we create this function, 82 | // we have to add the variables to the next CodeBlock 83 | // in this step, we must add the function parameters later 84 | // so as to overwrite the older local variables 85 | auto local_vars = this->getAllLocalVarNameType(); 86 | std::vector local_name_list = local_vars.first; 87 | std::vector local_type_list = local_vars.second; 88 | for(int i = 0; i < local_name_list.size(); i++) { 89 | name_list.push_back(local_name_list[i]); 90 | type_list.push_back(local_type_list[i]); 91 | var_list.push_back(true); 92 | llvm_type_list.push_back(llvm::PointerType::getUnqual(OurType::getLLVMType(context, local_type_list[i]))); 93 | } 94 | 95 | // adding function parameters 96 | for (auto type: type_var_list){ 97 | type_list.push_back(type->getType()); 98 | var_list.push_back(type->is_var()); 99 | llvm_type_list.push_back(llvm::PointerType::getUnqual(OurType::getLLVMType(context, type->getType()))); 100 | } 101 | 102 | FuncSign *funcsign = new FuncSign((int)(local_name_list.size()), name_list, type_list, var_list, return_type); 103 | llvm::FunctionType *functionType = llvm::FunctionType::get(llvm_return_type, llvm_type_list, false); 104 | llvm::Function *function = llvm::Function::Create(functionType, llvm::GlobalValue::ExternalLinkage, func_name, module.get()); 105 | 106 | this->getCurrentBlock()->set_function(func_name, function, funcsign); 107 | 108 | llvm::BasicBlock* oldBlock = this->builder.GetInsertBlock(); 109 | llvm::BasicBlock* basicBlock = llvm::BasicBlock::Create(context, "entry", function, nullptr); 110 | this->builder.SetInsertPoint(basicBlock); 111 | 112 | // MODIFY PARAMETERS PASSING 113 | block_stack.push_back(new CodeBlock()); 114 | this->getCurrentBlock()->block_name = func_name; 115 | this->getCurrentBlock()->is_function = is_function; 116 | int iter_i = 0; 117 | for(llvm::Function::arg_iterator arg_it = function->arg_begin(); arg_it != function->arg_end(); arg_it++, iter_i++) { 118 | if (var_list[iter_i]) { 119 | this->getCurrentBlock()->named_values[name_list[iter_i]] = (llvm::Value *)arg_it; 120 | if (iter_i >= local_name_list.size()) 121 | this->getCurrentBlock()->named_types[name_list[iter_i]] = type_list[iter_i]; 122 | std::cout << "Inserted var param " << name_list[iter_i] << std::endl; 123 | } else { 124 | llvm::Value *value = this->builder.CreateLoad((llvm::Value *)arg_it); 125 | llvm::AllocaInst *mem = this->builder.CreateAlloca( 126 | OurType::getLLVMType(this->context, type_list[iter_i]), 127 | nullptr, 128 | name_list[iter_i] 129 | ); 130 | this->builder.CreateStore(value, mem); 131 | this->getCurrentBlock()->named_values[name_list[iter_i]] = mem; 132 | if (iter_i >= local_name_list.size()) 133 | this->getCurrentBlock()->named_types[name_list[iter_i]] = type_list[iter_i]; 134 | std::cout << "Inserted val param " << name_list[iter_i] << std::endl; 135 | } 136 | } 137 | 138 | // add function to named_value for itself 139 | if (is_function) { 140 | llvm::AllocaInst *mem = this->builder.CreateAlloca( 141 | OurType::getLLVMType(this->context, return_type), 142 | nullptr, 143 | func_name 144 | ); 145 | this->getCurrentBlock()->named_values[func_name] = mem; 146 | this->getCurrentBlock()->named_types[func_name] = return_type; 147 | std::cout << "Inserted val param " << func_name << std::endl; 148 | } 149 | 150 | // add return mechanism 151 | if (is_function) { 152 | ((ASTFunctionDecl*)node)->getRoutine()->Accept(this); 153 | if (this->block_stack.size() == 1) { 154 | this->builder.CreateRet(llvm::ConstantInt::get(llvm::Type::getInt32Ty(this->context), 0, true)); 155 | } else { 156 | llvm::Value *ret = this->builder.CreateLoad(this->getCurrentBlock()->named_values[func_name]); 157 | this->builder.CreateRet(ret); 158 | } 159 | } else { 160 | ((ASTProcedureDecl*)node)->getRoutine()->Accept(this); 161 | this->builder.CreateRetVoid(); 162 | } 163 | 164 | this->builder.SetInsertPoint(oldBlock); 165 | this->block_stack.pop_back(); 166 | return nullptr; 167 | } 168 | 169 | std::shared_ptr Generator::VisitASTFunctionHead(ASTFunctionHead *node) { 170 | return nullptr; 171 | } 172 | 173 | std::shared_ptr Generator::VisitASTProcedureHead(ASTProcedureHead *node) { 174 | return nullptr; 175 | } 176 | 177 | std::shared_ptr Generator::VisitASTParaDeclList(ASTParaDeclList *node) { 178 | vector name_list; 179 | std::vector > type_list; 180 | for (auto son: node->getParaDeclList()){ 181 | auto temp_list = std::static_pointer_cast(son->Accept(this)); 182 | name_list.insert(name_list.end(), temp_list->getNameList().begin(), temp_list->getNameList().end()); 183 | type_list.insert(type_list.end(), temp_list->getTypeList().begin(), temp_list->getTypeList().end()); 184 | } 185 | return std::make_shared(type_list, name_list); 186 | } 187 | 188 | std::shared_ptr Generator::VisitASTParaTypeList(ASTParaTypeList *node) { 189 | std::shared_ptr list; 190 | if (node->getParaList()->isVar()) 191 | list = ((ASTVarParaList*)(node->getParaList()))->Accept(this); 192 | else 193 | list = ((ASTValParaList*)(node->getParaList()))->Accept(this); 194 | 195 | auto name_list = std::static_pointer_cast(list)->getNameList(); 196 | auto type_value = std::static_pointer_cast(node->getSimpleTypeDecl()->Accept(this)); 197 | if (node->getParaList()->isVar()) 198 | type_value->setIsVar(true); 199 | std::vector > type_list(name_list.size(), type_value); 200 | return std::make_shared(type_list, name_list); 201 | } 202 | 203 | std::shared_ptr Generator::VisitASTVarParaList(ASTVarParaList *node) { 204 | return node->getNameList()->Accept(this); 205 | } 206 | 207 | std::shared_ptr Generator::VisitASTValParaList(ASTValParaList *node) { 208 | return node->getNameList()->Accept(this); 209 | } --------------------------------------------------------------------------------