From 75639fbf01bd6ae1212521b6cf822025eb8b598d Mon Sep 17 00:00:00 2001 From: Carlos Maniero Date: Wed, 10 May 2023 16:07:39 -0300 Subject: namespaces: Add a namespace structure that represents a file We have been always parsing a single function. Since we want to have multiple functions in a near future, this patch introduces an namespace that represents an entire file. To ensure a function is defined inside a namespace, a helper function was created. Today our ast_node structure is highly exposed, and this is something that Johnny and I have been discussed. So then, this is a first step to try to protected the code generation from our ast tree. Signed-off-by: Carlos Maniero --- src/ast.c | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) (limited to 'src/ast.c') diff --git a/src/ast.c b/src/ast.c index 5790c05..47d658d 100644 --- a/src/ast.c +++ b/src/ast.c @@ -44,6 +44,9 @@ void ast_node_destroy(ast_node_t *node) { switch (node->kind) { + case AST_NAMESPACE: + ast_node_destroy_vector(node->data.ns.nodes); + break; case AST_FUNCTION_DECLARATION: ast_node_destroy(node->data.function.body); break; @@ -107,6 +110,24 @@ ast_node_new_function_declaration(string_view_t function_name, type_t return_typ return node; } +ast_node_t * +ast_node_new_namespace(vector_t *nodes) +{ + ast_node_t *node = ast_node_new(); + + *node = (ast_node_t){ + .kind = AST_NAMESPACE, + .result_type = TYPE_VOID, + .data = { + .ns = { + .nodes = nodes, + } + }, + }; + + return node; +} + ast_node_t * ast_node_new_block(vector_t *body) { @@ -254,6 +275,27 @@ ast_node_new_variable(ast_identifier_t *identifier, type_t result_type) return node; } +ast_node_t * +ast_node_ns_get_function_node_by_sv(ast_node_t *ns, string_view_t name) +{ + assert(ns->kind == AST_NAMESPACE); + + for (size_t i = 0; i < ns->data.ns.nodes->size; i++) { + ast_node_t *node = vector_at(ns->data.ns.nodes, i); + + if (node->kind == AST_FUNCTION_DECLARATION && string_view_eq(node->data.function.identifier.name, name)) { + return node; + } + } + return NULL; +} + +ast_node_t * +ast_node_ns_get_function_node_by_name(ast_node_t *ns, char *function_name) +{ + return ast_node_ns_get_function_node_by_sv(ns, string_view_from_str(function_name)); +} + char * ast_type_to_str(type_t type) { -- cgit v1.2.3 From 3129b741064c2b4f2c6c2408bd42cc83f7341ea8 Mon Sep 17 00:00:00 2001 From: Carlos Maniero Date: Wed, 10 May 2023 16:53:05 -0300 Subject: gas: Generate function call This is an initial commit that enables function calls. At this point only functions with no parameters is going to work. Signed-off-by: Carlos Maniero --- src/ast.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) (limited to 'src/ast.c') diff --git a/src/ast.c b/src/ast.c index 47d658d..e9aa677 100644 --- a/src/ast.c +++ b/src/ast.c @@ -72,6 +72,7 @@ ast_node_destroy(ast_node_t *node) case AST_LITERAL: case AST_UNKOWN_NODE: case AST_VARIABLE: + case AST_FUNCTION_CALL: break; } free(node); @@ -275,6 +276,20 @@ ast_node_new_variable(ast_identifier_t *identifier, type_t result_type) return node; } +ast_node_t * +ast_node_new_function_call(ast_identifier_t *identifier, type_t result_type) +{ + ast_node_t *node = ast_node_new(); + + *node = (ast_node_t){ + .kind = AST_FUNCTION_CALL, + .result_type = result_type, + .data = { .function_call = { .identifier = identifier } }, + }; + + return node; +} + ast_node_t * ast_node_ns_get_function_node_by_sv(ast_node_t *ns, string_view_t name) { @@ -296,6 +311,18 @@ ast_node_ns_get_function_node_by_name(ast_node_t *ns, char *function_name) return ast_node_ns_get_function_node_by_sv(ns, string_view_from_str(function_name)); } +bool +ast_node_is_variable_declaration(ast_node_t *node) +{ + return node->kind == AST_VARIABLE_DECLARATION; +} + +bool +ast_node_is_function_declaration(ast_node_t *node) +{ + return node->kind == AST_FUNCTION_DECLARATION; +} + char * ast_type_to_str(type_t type) { -- cgit v1.2.3 From 5042a4ffc1363d6f0f99a3afd79f76cf2da738d6 Mon Sep 17 00:00:00 2001 From: Carlos Maniero Date: Wed, 10 May 2023 22:24:14 -0300 Subject: gas: implement function calls For now function calls are following the C's calling convention, which means they are using the following registers to pass functions' arguments: rdi, rsi, rdx, rcx, r8, r9 If a function has more then 6 parameters, the compilation will fail. To enable function with more than 6 parameters we will need to save the extra arguments on stack. Naming: parameters: function parameters are the variables a function receives. arguments: Arguments are the values passed to a function when calling it. Calling mechanism: When a function is called, all the expressions passed as argument are evaluated, after the evaluation, the result is stored on the register that represents its argument position, the first argument will be stored on rdi, the second on rsi and so on. Receiving mechanism: When a function starts, the first thing it does is store all the registers onto the stack. So rdi will be stored on -8(rbp), rsi on -16(rbp) and so on. And, a ref_entry is created making the relationship parameter-stack_offset. Signed-off-by: Carlos Maniero --- src/ast.c | 54 ++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 48 insertions(+), 6 deletions(-) (limited to 'src/ast.c') diff --git a/src/ast.c b/src/ast.c index e9aa677..f6f8f08 100644 --- a/src/ast.c +++ b/src/ast.c @@ -49,6 +49,7 @@ ast_node_destroy(ast_node_t *node) break; case AST_FUNCTION_DECLARATION: ast_node_destroy(node->data.function.body); + ast_node_destroy_vector(node->data.function.prototype.parameters); break; case AST_IF_STMT: ast_node_destroy(node->data.if_stmt.condition); @@ -69,6 +70,7 @@ ast_node_destroy(ast_node_t *node) break; case AST_VARIABLE_ASSIGNMENT: ast_node_destroy(node->data.variable_assignment.expression); + case AST_FUNCTION_PARAMETER: case AST_LITERAL: case AST_UNKOWN_NODE: case AST_VARIABLE: @@ -93,7 +95,30 @@ ast_node_new_return_stmt(ast_node_t *argument) } ast_node_t * -ast_node_new_function_declaration(string_view_t function_name, type_t return_type, ast_node_t *body) +ast_node_new_function_parameter(string_view_t name, type_t type) +{ + ast_node_t *node = ast_node_new(); + + *node = (ast_node_t){ + .kind = AST_FUNCTION_PARAMETER, + .data = { + .function_parameter = { + .identifier = { + .name = name, + }, + .type = type, + }, + }, + }; + + return node; +} + +ast_node_t * +ast_node_new_function_declaration(string_view_t function_name, + type_t return_type, + vector_t *parameters, + ast_node_t *body) { ast_node_t *node = ast_node_new(); @@ -101,8 +126,11 @@ ast_node_new_function_declaration(string_view_t function_name, type_t return_typ .kind = AST_FUNCTION_DECLARATION, .data = { .function = { - .identifier = { .name = function_name }, - .return_type = return_type, + .prototype = { + .identifier = { .name = function_name }, + .return_type = return_type, + .parameters = parameters, + }, .body = body, } }, @@ -277,14 +305,14 @@ ast_node_new_variable(ast_identifier_t *identifier, type_t result_type) } ast_node_t * -ast_node_new_function_call(ast_identifier_t *identifier, type_t result_type) +ast_node_new_function_call(ast_identifier_t *identifier, type_t result_type, vector_t *arguments) { ast_node_t *node = ast_node_new(); *node = (ast_node_t){ .kind = AST_FUNCTION_CALL, .result_type = result_type, - .data = { .function_call = { .identifier = identifier } }, + .data = { .function_call = { .identifier = identifier, .arguments = arguments } }, }; return node; @@ -298,7 +326,7 @@ ast_node_ns_get_function_node_by_sv(ast_node_t *ns, string_view_t name) for (size_t i = 0; i < ns->data.ns.nodes->size; i++) { ast_node_t *node = vector_at(ns->data.ns.nodes, i); - if (node->kind == AST_FUNCTION_DECLARATION && string_view_eq(node->data.function.identifier.name, name)) { + if (node->kind == AST_FUNCTION_DECLARATION && string_view_eq(node->data.function.prototype.identifier.name, name)) { return node; } } @@ -323,6 +351,20 @@ ast_node_is_function_declaration(ast_node_t *node) return node->kind == AST_FUNCTION_DECLARATION; } +ast_identifier_t * +ast_node_function_declaration_identifier(ast_node_t *node) +{ + assert(node->kind == AST_FUNCTION_DECLARATION); + + return &node->data.function.prototype.identifier; +} + +string_view_t +ast_node_function_declaration_name(ast_node_t *node) +{ + return ast_node_function_declaration_identifier(node)->name; +} + char * ast_type_to_str(type_t type) { -- cgit v1.2.3