diff --git a/src/llvm/backend.c b/src/llvm/backend.c index eccdd14..3621338 100644 --- a/src/llvm/backend.c +++ b/src/llvm/backend.c @@ -1,4 +1,5 @@ +#include #include #include #include @@ -30,6 +31,7 @@ static BackendError llvm_backend_codegen(const AST_NODE_PTR module_node, void**) GemstoneTypedefRef typedefref; GemstoneFunRef funref; + GArray* decls; switch (global_node->kind) { case AST_Typedef: @@ -40,6 +42,13 @@ static BackendError llvm_backend_codegen(const AST_NODE_PTR module_node, void**) funref = fun_from_ast(global_scope, global_node); type_scope_add_fun(global_scope, funref); break; + case AST_Decl: + decls = declaration_from_ast(global_scope, global_node); + for (size_t i = 0; i < decls->len; i++) { + GemstoneDeclRef decl = ((GemstoneDeclRef*) decls->data)[i]; + type_scope_add_variable(global_scope, decl); + } + break; default: PANIC("NOT IMPLEMENTED"); } diff --git a/src/llvm/decl/variable.c b/src/llvm/decl/variable.c new file mode 100644 index 0000000..15e902b --- /dev/null +++ b/src/llvm/decl/variable.c @@ -0,0 +1,65 @@ +#include "llvm/types/structs.h" +#include +#include +#include +#include +#include + +static StorageQualifier get_storage_qualifier_from_ast(AST_NODE_PTR storageQualifierNode) { + if (storageQualifierNode->kind != AST_Storage) { + PANIC("Node must be of type AST_Fun: %s", AST_node_to_string(storageQualifierNode)); + } + + StorageQualifier storageQualifier; + + if (strcmp(storageQualifierNode->value, "local") == 0) { + storageQualifier = StorageQualifierLocal; + } else if (strcmp(storageQualifierNode->value, "static") == 0) { + storageQualifier = StorageQualifierStatic; + } else if (strcmp(storageQualifierNode->value, "global") == 0) { + storageQualifier = StorageQualifierGlobal; + } else { + PANIC("unknown storage qualifier: %s", storageQualifierNode->value); + } + + return storageQualifier; +} + +GArray* declaration_from_ast(TypeScopeRef scope, const AST_NODE_PTR node) { + if (node->kind != AST_Decl) { + PANIC("Node must be of type AST_Fun: %s", AST_node_to_string(node)); + } + + GArray* decls = g_array_new(FALSE, FALSE, sizeof(GemstoneDeclRef)); + + AST_NODE_PTR first_child = AST_get_node(node, 0); + + StorageQualifier qualifier = StorageQualifierLocal; + GemstoneTypeRef type = NULL; + AST_NODE_PTR list = NULL; + + if (first_child->kind == AST_Storage) { + qualifier = get_storage_qualifier_from_ast(first_child); + type = get_type_from_ast(scope, AST_get_node(node, 1)); + list = AST_get_node(node, 2); + + } else { + type = get_type_from_ast(scope, first_child); + list = AST_get_node(node, 1); + } + + if (list->kind != AST_IdentList) { + PANIC("Node must be of type AST_IdentList: %s", AST_node_to_string(node)); + } + + for (size_t i = 0; i < list->child_count; i++) { + GemstoneDeclRef ref = malloc(sizeof(GemstoneDecl)); + ref->name = AST_get_node(list, i)->value; + ref->storageQualifier = qualifier; + ref->type = type; + + g_array_append_val(decls, ref); + } + + return decls; +} diff --git a/src/llvm/decl/variable.h b/src/llvm/decl/variable.h new file mode 100644 index 0000000..8548391 --- /dev/null +++ b/src/llvm/decl/variable.h @@ -0,0 +1,11 @@ + +#ifndef LLVM_DECL_VAR_H_ +#define LLVM_DECL_VAR_H_ + +#include +#include +#include + +GArray* declaration_from_ast(TypeScopeRef scope, const AST_NODE_PTR node); + +#endif // LLVM_DECL_VAR_H_ diff --git a/src/llvm/types/scope.c b/src/llvm/types/scope.c index 347b83e..851da03 100644 --- a/src/llvm/types/scope.c +++ b/src/llvm/types/scope.c @@ -1,4 +1,5 @@ +#include #include #include #include @@ -8,6 +9,7 @@ struct TypeScope_t { GArray* types; GArray* scopes; GArray* funcs; + GHashTable* vars; TypeScopeRef parent; }; @@ -18,6 +20,7 @@ TypeScopeRef type_scope_new() { scope->scopes = g_array_new(FALSE, FALSE, sizeof(TypeScopeRef)); scope->types = g_array_new(FALSE, FALSE, sizeof(GemstoneTypedefRef)); scope->funcs = g_array_new(FALSE, FALSE, sizeof(GemstoneFunRef)); + scope->vars = g_hash_table_new(g_str_hash, g_str_equal); scope->parent = NULL; return scope; @@ -74,10 +77,23 @@ void type_scope_delete(TypeScopeRef scope) { g_array_free(scope->scopes, TRUE); g_array_free(scope->types, TRUE); g_array_free(scope->funcs, TRUE); + g_hash_table_destroy(scope->vars); free(scope); } +void type_scope_add_variable(TypeScopeRef scope, GemstoneDeclRef decl) { + g_hash_table_insert(scope->vars, (gpointer) decl->name, decl); +} + +GemstoneDeclRef type_scope_get_variable(TypeScopeRef scope, const char* name) { + if (g_hash_table_contains(scope->vars, name)) { + return g_hash_table_lookup(scope->vars, name); + } + + return NULL; +} + void type_scope_add_fun(TypeScopeRef scope, GemstoneFunRef function) { g_array_append_val(scope->funcs, function); } diff --git a/src/llvm/types/scope.h b/src/llvm/types/scope.h index c58a367..a8beac2 100644 --- a/src/llvm/types/scope.h +++ b/src/llvm/types/scope.h @@ -6,6 +6,21 @@ #include #include +typedef enum StorageQualifier_t { + StorageQualifierLocal, + StorageQualifierStatic, + StorageQualifierGlobal +} StorageQualifier; + +// Varaible declaration +typedef struct GemstoneDecl_t { + const char* name; + StorageQualifier storageQualifier; + GemstoneTypeRef type; +} GemstoneDecl; + +typedef GemstoneDecl* GemstoneDeclRef; + typedef struct TypeScope_t TypeScope; typedef TypeScope* TypeScopeRef; @@ -99,4 +114,6 @@ void type_scope_add_fun(TypeScopeRef scope, GemstoneFunRef function); [[gnu::nonnull(1), gnu::nonnull(2)]] GemstoneFunRef type_scope_get_fun_from_name(TypeScopeRef scope, const char* name); +void type_scope_add_variable(TypeScopeRef scope, GemstoneDeclRef decl); + #endif // LLVM_TYPE_SCOPE_H_