From f04c7f8fe9714a10aba592efbe681a6eecb074e6 Mon Sep 17 00:00:00 2001 From: Jesse Chen Date: Mon, 9 Oct 2023 13:17:44 +0800 Subject: [PATCH] return --- CMakeLists.txt | 1 + src/AST.hpp | 13 +++++++++++++ src/JIT.hpp | 9 +++++++++ src/Parser.hpp | 14 ++++++++++++++ src/Token.hpp | 7 ++++++- tests/acceptance/return.pas | 4 ++++ tests/cases/return.pas | 4 ++++ tests/e2e.cpp | 7 ++++--- 8 files changed, 55 insertions(+), 4 deletions(-) create mode 100644 tests/acceptance/return.pas create mode 100644 tests/cases/return.pas diff --git a/CMakeLists.txt b/CMakeLists.txt index 0110da4..ee51002 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -8,6 +8,7 @@ enable_testing() aux_source_directory(${CMAKE_CURRENT_LIST_DIR}/src sources) add_executable(pascal_jit_compiler ${sources} main.cpp) + if(ENABLE_TEST) add_subdirectory(tests) endif() diff --git a/src/AST.hpp b/src/AST.hpp index 353cd12..d9d7c53 100644 --- a/src/AST.hpp +++ b/src/AST.hpp @@ -178,6 +178,19 @@ class AssignmentExpressionAST: public ExpressionAST { } }; +class ResultExpressionAST : public ExpressionAST{ + public: + std::unique_ptr assignment; + std::vector codegen() override { + std::vector result; + auto assignmentR9 = assignment->codegen(); + addAssemblyToExecutable(result, assignmentR9); + addAssemblyToExecutable(result, mov_register_register(0, 9)); + DEBUG("addAssemblyToExecutable(executable, mov_register_register(0, 9));"); + return result; + } +}; + // TODO find call type with signature of callee class CallExpressionAST : public ExpressionAST { public: diff --git a/src/JIT.hpp b/src/JIT.hpp index 799ce2c..bb0d1dd 100644 --- a/src/JIT.hpp +++ b/src/JIT.hpp @@ -7,10 +7,19 @@ typedef void (*FuncPtr)(); +typedef int (*IntFuncPtr)(); + static FuncPtr createJit(const std::vector& executable){ void *jitPtr = mmap(nullptr, 4096, PROT_READ | PROT_EXEC | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); std::memcpy(jitPtr, executable.data(), executable.size()); return (FuncPtr)jitPtr; } + +static IntFuncPtr createJitInt(const std::vector& executable){ + void *jitPtr = mmap(nullptr, 4096, PROT_READ | PROT_EXEC | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + std::memcpy(jitPtr, executable.data(), executable.size()); + return (IntFuncPtr)jitPtr; +} #endif \ No newline at end of file diff --git a/src/Parser.hpp b/src/Parser.hpp index 2545ba6..461fdbe 100644 --- a/src/Parser.hpp +++ b/src/Parser.hpp @@ -102,11 +102,25 @@ class Parser { } } + std::unique_ptr parseResultExpression(){ + std::unique_ptr resultExpr = std::make_unique(); + getNextToken(); // eat Result + if(currentToken == Token::tok_assign) { + getNextToken(); // eat assign + resultExpr->assignment = parseExpression(); + } else { + throw std::runtime_error("Result without assignment"); + } + return resultExpr; + } + std::unique_ptr parseExpression() { // parse call switch (currentToken) { case tok_identifier: return parseIdentifierExpression(); + case tok_result: + return parseResultExpression(); case tok_string_literal: { std::string strValue = tokenizer.stringLiteral; getNextToken(); diff --git a/src/Token.hpp b/src/Token.hpp index 61f04cb..7c558e0 100644 --- a/src/Token.hpp +++ b/src/Token.hpp @@ -41,6 +41,7 @@ enum Token : int { tok_assign = -15, tok_assign_type = -16, + tok_result = -17, }; class Tokenizer { @@ -89,6 +90,10 @@ class Tokenizer { return Token::tok_program; } + if (identifier == "Result") { + return Token::tok_result; + } + if (identifier == "begin") { return Token::tok_begin; } @@ -148,7 +153,7 @@ class Tokenizer { nextChar(); return Token::tok_neg; } - if(_lastChar == '+') { + if (_lastChar == '+') { nextChar(); return Token::tok_positive; } diff --git a/tests/acceptance/return.pas b/tests/acceptance/return.pas new file mode 100644 index 0000000..4503568 --- /dev/null +++ b/tests/acceptance/return.pas @@ -0,0 +1,4 @@ +program ReturnInt; +begin + Result := 42; +end. \ No newline at end of file diff --git a/tests/cases/return.pas b/tests/cases/return.pas new file mode 100644 index 0000000..4503568 --- /dev/null +++ b/tests/cases/return.pas @@ -0,0 +1,4 @@ +program ReturnInt; +begin + Result := 42; +end. \ No newline at end of file diff --git a/tests/e2e.cpp b/tests/e2e.cpp index 093e917..3020eb3 100644 --- a/tests/e2e.cpp +++ b/tests/e2e.cpp @@ -44,16 +44,17 @@ template void printAssemblyMachineCode(T &&runtime) { } TEST(compiler_e2e, parser) { - std::ifstream t(workspace / "tests" / "cases" / "binaryExpression.pas"); + std::ifstream t(workspace / "tests" / "cases" / "return.pas"); std::stringstream buffer; buffer << t.rdbuf(); Tokenizer tokenizer(buffer.str()); Parser parser(tokenizer, std::make_shared()); parser.debug = true; auto program = parser.parse(); - auto fun = createJit(program->codegen()); + auto fun = createJitInt(program->codegen()); std::cout << "ptr: " << std::hex << (void *)fun << std::endl; - fun(); + const int result = fun(); + std::cout << std::dec << result << std::endl; // printAssemblyMachineCode(program->codegen()); }