Skip to content

Commit

Permalink
cc: implement proper support for return statements
Browse files Browse the repository at this point in the history
  • Loading branch information
atirut-w committed Jul 27, 2024
1 parent a5adfc3 commit b4de0bd
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 10 deletions.
23 changes: 22 additions & 1 deletion src/cc/analyzer.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include "CParser.h"
#include <analyzer.hpp>
#include <any>

using namespace std;
using namespace antlr4;
Expand All @@ -20,7 +21,27 @@ any Analyzer::visitFunctionDefinition(CParser::FunctionDefinitionContext *ctx)
}
current_function = &meta.functions[name];

return visitChildren(ctx);
if (auto *itemlist_ctx = ctx->compoundStatement()->blockItemList())
{
for (auto *item_ctx : itemlist_ctx->blockItem())
{
// We check for return statements here because we only want to check if this function *ends* with a return statement
if (auto *statement_ctx = item_ctx->statement())
{
if (auto *jump_statement_ctx = statement_ctx->jumpStatement())
{
if (jump_statement_ctx->Return())
{
current_function->has_return = true;
}
}
}

visit(item_ctx);
}
}

return any();
}

any Analyzer::visitDeclaration(CParser::DeclarationContext *ctx)
Expand Down
41 changes: 32 additions & 9 deletions src/cc/codegen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,20 @@ CodeGen::CodeGen(ProgramMeta &program_meta, std::ostream &output) : program_meta
output << "\t; Generated by ZDK C Compiler\n\n";
}

void CodeGen::teardown_frame()
{
// TODO: clause for arguments
if (current_function->local_alloc > 0 || false)
{
output << "\tld sp, ix\n";
output << "\tpop ix\n";
if (current_function->local_alloc > 0)
{
output << "\tpop iy\n";
}
}
}

any CodeGen::visitFunctionDefinition(CParser::FunctionDefinitionContext *ctx)
{
string name = ctx->declarator()->directDeclarator()->directDeclarator()->Identifier()->getText();
Expand Down Expand Up @@ -91,18 +105,27 @@ any CodeGen::visitFunctionDefinition(CParser::FunctionDefinitionContext *ctx)
}
}

// TODO: clause for arguments
if (current_function->local_alloc > 0 || false)
if (!current_function->has_return)
{
output << "\tld sp, ix\n";
output << "\tpop ix\n";
if (current_function->local_alloc > 0)
{
output << "\tpop iy\n";
}
teardown_frame();
output << "\tret\n";
}

output << "\tret\n";
return any();
}

any CodeGen::visitJumpStatement(CParser::JumpStatementContext *ctx)
{
if (ctx->Return())
{
visit(ctx->expression());
teardown_frame();
output << "\tret\n";
}
else
{
throw runtime_error("unsupported jump statement");
}

return any();
}
Expand Down
1 change: 1 addition & 0 deletions src/cc/include/analyzer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ struct FunctionMeta
// Offset into the local frame for local variables
std::map<std::string, LocalMeta> variables;
int local_alloc = 0;
bool has_return = false; // TODO: Come up with a better name for this
};

struct ProgramMeta
Expand Down
3 changes: 3 additions & 0 deletions src/cc/include/codegen.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,10 @@ class CodeGen : public CBaseVisitor
FunctionMeta *current_function = nullptr;
std::ostream &output;

void teardown_frame();

virtual std::any visitFunctionDefinition(CParser::FunctionDefinitionContext *ctx) override;
virtual std::any visitJumpStatement(CParser::JumpStatementContext *ctx) override;

// All of these are for math expressions. Yes, all of them.
virtual std::any visitPrimaryExpression(CParser::PrimaryExpressionContext *ctx) override; // Your pain starts here
Expand Down

0 comments on commit b4de0bd

Please sign in to comment.