Skip to content

Commit

Permalink
user defined functions work
Browse files Browse the repository at this point in the history
  • Loading branch information
Raekye committed Nov 11, 2014
1 parent 7e11a56 commit 3d4d5da
Show file tree
Hide file tree
Showing 8 changed files with 62 additions and 42 deletions.
24 changes: 12 additions & 12 deletions sayaka/src/ast_node.h
Original file line number Diff line number Diff line change
Expand Up @@ -110,29 +110,29 @@ class ASTNodeBinaryOperator : public ASTNode {
virtual ASTNodeBinaryOperator* pass_types(CodeGenContext*, ASTType*) override;
};

class ASTNodeFunction : public ASTNode {
class ASTNodeFunctionPrototype : public ASTNode {
public:
ASTNodeBlock* body;
std::string return_type;
std::string function_name;
std::vector<ASTNodeDeclaration*>* args;

ASTNodeFunction(ASTNodeBlock*, std::string);
ASTNodeFunctionPrototype(std::string, std::string, std::vector<ASTNodeDeclaration*>*);

virtual ~ASTNodeFunction();
virtual ~ASTNodeFunctionPrototype();
virtual llvm::Value* gen_code(CodeGenContext*) override;
virtual ASTNodeFunction* pass_types(CodeGenContext*, ASTType*) override;
virtual ASTNodeFunctionPrototype* pass_types(CodeGenContext*, ASTType*) override;
};

class ASTNodeFunctionPrototype : public ASTNode {
class ASTNodeFunction : public ASTNode {
public:
std::string return_type;
std::string function_name;
std::vector<std::tuple<std::string, std::string>>* args;
ASTNodeFunctionPrototype* prototype;
ASTNodeBlock* body;

ASTNodeFunctionPrototype(std::string, std::string, std::vector<std::tuple<std::string, std::string>>*);
ASTNodeFunction(ASTNodeFunctionPrototype*, ASTNodeBlock*);

virtual ~ASTNodeFunctionPrototype();
virtual ~ASTNodeFunction();
virtual llvm::Value* gen_code(CodeGenContext*) override;
virtual ASTNodeFunctionPrototype* pass_types(CodeGenContext*, ASTType*) override;
virtual ASTNodeFunction* pass_types(CodeGenContext*, ASTType*) override;
};

class ASTNodeFunctionCall : public ASTNode {
Expand Down
16 changes: 9 additions & 7 deletions sayaka/src/ast_node_function.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,30 +2,31 @@

#include <iostream>

ASTNodeFunction::ASTNodeFunction(ASTNodeBlock* body, std::string return_type) {
ASTNodeFunction::ASTNodeFunction(ASTNodeFunctionPrototype* prototype, ASTNodeBlock* body) {
this->prototype = prototype;
this->body = body;
this->return_type = return_type;
}

ASTNodeFunction::~ASTNodeFunction() {
delete this->prototype;
delete this->body;
}

ASTNodeFunction* ASTNodeFunction::pass_types(CodeGenContext* code_gen_context, ASTType* ignore) {
this->type = NULL; // TODO;
this->body = this->body->pass_types(code_gen_context, code_gen_context->ast_types_resolver.get(this->return_type));
this->prototype = this->prototype->pass_types(code_gen_context, NULL);
this->body = this->body->pass_types(code_gen_context, code_gen_context->ast_types_resolver.get(this->prototype->return_type));
return this;
}

llvm::Value* ASTNodeFunction::gen_code(CodeGenContext* code_gen_context) {
std::cout << "Generating function" << std::endl;
std::cout << "Generating function " << this->prototype->function_name << std::endl;
std::vector<llvm::Type*> arg_types;
ASTType* type = code_gen_context->ast_types_resolver.get(this->return_type);
ASTType* type = code_gen_context->ast_types_resolver.get(this->prototype->return_type);
if (type == NULL) {
throw std::runtime_error("Unknown type");
}
llvm::FunctionType* fn_type = llvm::FunctionType::get(type->llvm_type, arg_types, false);
llvm::Function* fn = llvm::Function::Create(fn_type, llvm::Function::ExternalLinkage, "", code_gen_context->module);
llvm::Function* fn = (llvm::Function*) this->prototype->gen_code(code_gen_context);

llvm::BasicBlock* basic_block = llvm::BasicBlock::Create(llvm::getGlobalContext(), "entry", fn);
code_gen_context->push_block(basic_block);
Expand All @@ -35,6 +36,7 @@ llvm::Value* ASTNodeFunction::gen_code(CodeGenContext* code_gen_context) {
code_gen_context->builder.CreateRet(ret_val);
llvm::verifyFunction(*fn);
code_gen_context->pop_block();
fn->dump();
return fn;
}
code_gen_context->pop_block();
Expand Down
1 change: 1 addition & 0 deletions sayaka/src/ast_node_functioncall.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ ASTNodeFunctionCall* ASTNodeFunctionCall::pass_types(CodeGenContext* code_gen_co
}

llvm::Value* ASTNodeFunctionCall::gen_code(CodeGenContext* code_gen_context) {
std::cout << "Generating function call" << std::endl;
llvm::Function* callee = code_gen_context->module->getFunction(this->function_name);
if (callee == NULL) {
throw std::runtime_error("Unknown function called");
Expand Down
22 changes: 17 additions & 5 deletions sayaka/src/ast_node_functionprototype.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#include "ast_node.h"

ASTNodeFunctionPrototype::ASTNodeFunctionPrototype(std::string return_type, std::string function_name, std::vector<std::tuple<std::string, std::string>>* args) {
ASTNodeFunctionPrototype::ASTNodeFunctionPrototype(std::string return_type, std::string function_name, std::vector<ASTNodeDeclaration*>* args) {
this->return_type = return_type;
this->function_name = function_name;
this->args = args;
Expand All @@ -11,17 +11,29 @@ ASTNodeFunctionPrototype::~ASTNodeFunctionPrototype() {
}

ASTNodeFunctionPrototype* ASTNodeFunctionPrototype::pass_types(CodeGenContext* code_gen_context, ASTType* type) {
this->type = code_gen_context->ast_types_resolver.int_ty();
this->type = code_gen_context->ast_types_resolver.int_ty(); // TODO
for (std::vector<ASTNodeDeclaration*>::iterator it = this->args->begin(); it != this->args->end(); it++) {
*it = (*it)->pass_types(code_gen_context, NULL);
}
return this;
}

llvm::Value* ASTNodeFunctionPrototype::gen_code(CodeGenContext* code_gen_context) {
std::cout << "Generating prototype" << std::endl;
std::vector<llvm::Type*> args_types_list;
for (std::vector<std::tuple<std::string, std::string>>::iterator it = this->args->begin(); it != this->args->end(); it++) {
args_types_list.push_back(code_gen_context->ast_types_resolver.get(std::get<0>(*it))->llvm_type);
for (std::vector<ASTNodeDeclaration*>::iterator it = this->args->begin(); it != this->args->end(); it++) {
args_types_list.push_back(code_gen_context->ast_types_resolver.get((*it)->type_name)->llvm_type);
}
llvm::FunctionType* ft = llvm::FunctionType::get(code_gen_context->ast_types_resolver.get(this->return_type)->llvm_type, args_types_list, false);
llvm::Function* fn = llvm::Function::Create(ft, llvm::Function::ExternalLinkage, this->function_name, code_gen_context->module);
return llvm::ConstantInt::get(code_gen_context->ast_types_resolver.int_ty()->llvm_type, 0, true);
int i = 0;
for (llvm::Function::arg_iterator it = fn->arg_begin(); it != fn->arg_end(); it++) {
ASTNodeDeclaration* var = this->args->operator[](i);
it->setName(var->var_name);
code_gen_context->scope.put(var->var_name, new CodeGenVariable(code_gen_context->ast_types_resolver.get(var->type_name), it));
i++;
}
return fn;
//return llvm::ConstantInt::get(code_gen_context->ast_types_resolver.int_ty()->llvm_type, 0, true);
}

8 changes: 6 additions & 2 deletions sayaka/src/ast_node_identifier.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,14 @@ ASTNodeIdentifier* ASTNodeIdentifier::pass_types(CodeGenContext* code_gen_contex
}

llvm::Value* ASTNodeIdentifier::gen_code(CodeGenContext* code_gen_context) {
std::cout << "Generating identifier" << std::endl;
std::cout << "Generating identifier " << this->name << std::endl;
CodeGenVariable* var = code_gen_context->scope.get(this->name);
if (var == NULL) {
throw std::runtime_error("Undeclared variable");
}
return code_gen_context->builder.CreateLoad(std::get<1>(*var), false, this->name);
llvm::Value* val = std::get<1>(*var);
if (llvm::AllocaInst* alloc = dynamic_cast<llvm::AllocaInst*>(val)) {
return code_gen_context->builder.CreateLoad(alloc, false, this->name);
}
return val;
}
2 changes: 0 additions & 2 deletions sayaka/src/code_gen_context.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,10 @@ CodeGenContext::~CodeGenContext() {
void CodeGenContext::push_block(llvm::BasicBlock* block) {
std::cout << "Pushing block" << std::endl;
this->blocks.push(block);
this->push_scope();
this->builder.SetInsertPoint(this->current_block());
}

void CodeGenContext::pop_block() {
this->pop_scope();
std::cout << "Popping block" << std::endl;
this->blocks.pop();
this->builder.SetInsertPoint(this->current_block());
Expand Down
6 changes: 3 additions & 3 deletions sayaka/src/compiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,11 @@ ASTNode* Compiler::parse(std::string code) {
}

void Compiler::run_code(ASTNode* root) {
ASTNodeFunction main_fn((ASTNodeBlock*) root, "Int");
std::vector<ASTNodeDeclaration*>* args = new std::vector<ASTNodeDeclaration*>();
ASTNodeFunctionPrototype* main_fn_prototype = new ASTNodeFunctionPrototype("Int", "main", args);
ASTNodeFunction main_fn(main_fn_prototype, (ASTNodeBlock*) root);
main_fn.pass_types(&this->code_gen_context, NULL);
llvm::Function* main_fn_val = (llvm::Function*) main_fn.gen_code(&this->code_gen_context);
std::cout << "Main fn code:" << std::endl;
main_fn_val->dump();
void* fn_ptr = this->execution_engine->getPointerToFunction(main_fn_val);
int32_t ret = ((int32_t (*)()) fn_ptr)();
std::cout << "Main fn at " << fn_ptr << "; executed: " << ret << std::endl;
Expand Down
25 changes: 14 additions & 11 deletions sayaka/src/parser.y
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ void yyerror(YYLTYPE* llocp, ASTNode**, yyscan_t scanner, const char *s) {
class ASTNode;
class ASTNodeBlock;
class ASTNodeIdentifier;
class ASTNodeDeclaration;

#ifndef YY_TYPEDEF_YY_SCANNER_T
#define YY_TYPEDEF_YY_SCANNER_T
Expand All @@ -41,7 +42,7 @@ typedef void* yyscan_t;
ASTNode* node;
ASTNodeBlock* block;
ASTNodeIdentifier* identifier;
std::vector<std::tuple<std::string, std::string>>* typed_args_list;
std::vector<ASTNodeDeclaration*>* typed_args_list;
std::vector<ASTNode*>* args_list;
std::string* str;
}
Expand All @@ -56,7 +57,7 @@ typedef void* yyscan_t;
%token TOKEN_COMMA
%token <str> TOKEN_NUMBER TOKEN_IDENTIFIER TOKEN_TYPE_NAME

%type <node> program expr number binary_operator_expr assignment_expr variable_declaration_expr cast_expr function_call_expr function_prototype_expr
%type <node> program expr number binary_operator_expr assignment_expr variable_declaration_expr cast_expr function_call_expr function_prototype_expr function_expr
%type <block> stmts
%type <identifier> identifier
%type <typed_args_list> typed_args_list
Expand Down Expand Up @@ -85,6 +86,7 @@ expr
| variable_declaration_expr { $$ = $1; }
| assignment_expr { $$ = $1; }
| cast_expr { $$ = $1; }
| function_expr { $$ = $1; }
| function_prototype_expr { $$ = $1; }
| function_call_expr { $$ = $1; }
| binary_operator_expr { $$ = $1; }
Expand Down Expand Up @@ -139,18 +141,19 @@ function_prototype_expr
}
;

function_expr
: function_prototype_expr TOKEN_LBRACE stmts TOKEN_RBRACE {
$$ = new ASTNodeFunction((ASTNodeFunctionPrototype*) $1, $3);
}
;

typed_args_list
: TOKEN_TYPE_NAME TOKEN_IDENTIFIER {
$$ = new std::vector<std::tuple<std::string, std::string>>();
$$->push_back(std::make_tuple(*$1, *$2));
delete $1;
delete $2;
: variable_declaration_expr {
$$ = new std::vector<ASTNodeDeclaration*>();
$$->push_back((ASTNodeDeclaration*) $1);
}
| typed_args_list TOKEN_COMMA TOKEN_TYPE_NAME TOKEN_IDENTIFIER {
$$->push_back(std::make_tuple(*$3, *$4));
delete $3;
delete $4;
| typed_args_list TOKEN_COMMA variable_declaration_expr {
$$->push_back((ASTNodeDeclaration*) $3);
}
;

Expand Down

0 comments on commit 3d4d5da

Please sign in to comment.