From 7f524c427597cc998f243769b0e22e4f450c55cf Mon Sep 17 00:00:00 2001 From: dec05eba Date: Wed, 24 Apr 2019 21:22:53 +0200 Subject: Progressing on bytecode (to c), fix ssa resolving multiple times --- src/ast.c | 70 +++++++++++++++----------------- src/bytecode/bytecode.c | 103 ++++++++++++++++++++++++++++++++++++++++++++---- src/compiler.c | 1 + src/parser.c | 12 ++---- src/ssa/ssa.c | 74 ++++++++++++++++++++++++---------- src/std/file.c | 15 +++---- 6 files changed, 193 insertions(+), 82 deletions(-) (limited to 'src') diff --git a/src/ast.c b/src/ast.c index 680eb50..983b3a4 100644 --- a/src/ast.c +++ b/src/ast.c @@ -4,6 +4,7 @@ #include "../include/std/log.h" #include "../include/std/hash.h" #include +#include #define throw(result) do { throw_debug_msg; longjmp(context->env, (result)); } while(0) #define throw_if_error(result) \ @@ -26,6 +27,7 @@ int ast_create(ScopedAllocator *allocator, void *value, AstType type, Ast **resu (*result)->value.data = value; (*result)->type = type; resolve_data_init(&(*result)->resolve_data); + (*result)->ssa_reg = 0; return 0; } @@ -186,10 +188,23 @@ static Parser* scope_get_parser(Scope *scope) { return scope->parser; scope = scope->parent; } - assert(bool_false && "BUG: At least some scope parent is supposed to have a parser"); return NULL; } +static void parser_print_error(Parser *parser, const char *ref, const char *fmt, ...) { + va_list args; + va_start(args, fmt); + if(parser) { + tokenizer_print_error(&parser->tokenizer, + tokenizer_get_code_reference_index(&parser->tokenizer, ref), + fmt, args); + } else { + /* TODO: Redirect error to compiler error callback if set */ + amal_log_error(fmt, args); + } + va_end(args); +} + static Ast* scope_get_resolved_variable(Scope *self, AstCompilerContext *context, BufferView name) { Ast *result; bool exists; @@ -203,9 +218,7 @@ static Ast* scope_get_resolved_variable(Scope *self, AstCompilerContext *context return scope_get_resolved_variable(self->parent, context, name); parser = scope_get_parser(self); - tokenizer_print_error(&parser->tokenizer, - tokenizer_get_code_reference_index(&parser->tokenizer, name.data), - "Undefined reference to variable \"%.*s\"", name.size, name.data); + parser_print_error(parser, name.data, "Undefined reference to variable \"%.*s\"", name.size, name.data); throw(AST_ERR); } @@ -264,9 +277,8 @@ static void lhsexpr_resolve(Ast *ast, AstCompilerContext *context) { if(ast->resolve_data.type && self->rhs_expr && ast->resolve_data.type != rhs_resolve_type) { Parser *parser; parser = scope_get_parser(context->scope); - tokenizer_print_error(&parser->tokenizer, - tokenizer_get_code_reference_index(&parser->tokenizer, self->type.name.data), - "Variable type and variable assignment type (right-hand side) do not match"); + parser_print_error(parser, self->type.name.data, + "Variable type and variable assignment type (right-hand side) do not match"); throw(AST_ERR); } } @@ -328,14 +340,11 @@ static void funccall_resolve(Ast *self, AstCompilerContext *context) { callee_parser = get_resolved_type_parser(self); callee_code_ref = self->resolve_data.type->var_name; - tokenizer_print_error(&caller_parser->tokenizer, - tokenizer_get_code_reference_index(&caller_parser->tokenizer, func_call->func.name.data), + parser_print_error(caller_parser, func_call->func.name.data, "\"%.*s\" is not a function. Only functions can be called", func_call->func.name.size, func_call->func.name.data); /* TODO: use tokenizer_print_note, once it has been added */ /* TODO: Print type */ - tokenizer_print_error(&callee_parser->tokenizer, - tokenizer_get_code_reference_index(&callee_parser->tokenizer, callee_code_ref.data), - "Type was declared here"); + parser_print_error(callee_parser, callee_code_ref.data, "Type was declared here"); throw(AST_ERR); } @@ -375,9 +384,7 @@ static void binop_resolve_dot_access(Ast *ast, AstCompilerContext *context) { /* TODO: Allow field access for numbers and string as well */ BufferView code_ref; code_ref = ast_get_code_reference(self->lhs); - tokenizer_print_error(&caller_parser->tokenizer, - tokenizer_get_code_reference_index(&caller_parser->tokenizer, code_ref.data), - "Accessing fields is only applicable for variables"); + parser_print_error(caller_parser, code_ref.data, "Accessing fields is only applicable for variables"); throw(AST_ERR); } @@ -389,26 +396,18 @@ static void binop_resolve_dot_access(Ast *ast, AstCompilerContext *context) { callee_code_ref = self->rhs->resolve_data.type->var_name; if(self->lhs->resolve_data.type->rhs_expr->type != AST_STRUCT_DECL) { - tokenizer_print_error(&caller_parser->tokenizer, - tokenizer_get_code_reference_index(&caller_parser->tokenizer, caller_code_ref.data), - "Can only access field of structs"); + parser_print_error(caller_parser, caller_code_ref.data, "Can only access field of structs"); /* TODO: use tokenizer_print_note, once it has been added */ /* TODO: Print type */ - tokenizer_print_error(&callee_parser->tokenizer, - tokenizer_get_code_reference_index(&callee_parser->tokenizer, callee_code_ref.data), - "Type was declared here"); + parser_print_error(callee_parser, callee_code_ref.data, "Type was declared here"); throw(AST_ERR); } if(!self->rhs->resolve_data.type->is_pub) { - tokenizer_print_error(&caller_parser->tokenizer, - tokenizer_get_code_reference_index(&caller_parser->tokenizer, caller_code_ref.data), - "Can't access non-public field \"%.*s\"", caller_code_ref.size, caller_code_ref.data); + parser_print_error(caller_parser, caller_code_ref.data, "Can't access non-public field \"%.*s\"", caller_code_ref.size, caller_code_ref.data); /* TODO: use tokenizer_print_note, once it has been added */ /* TODO: Print type */ - tokenizer_print_error(&callee_parser->tokenizer, - tokenizer_get_code_reference_index(&callee_parser->tokenizer, callee_code_ref.data), - "Type was declared non-public here"); + parser_print_error(callee_parser, callee_code_ref.data, "Type was declared non-public here"); throw(AST_ERR); } } @@ -437,17 +436,14 @@ static void binop_resolve(Ast *ast, AstCompilerContext *context) { */ Parser *parser; parser = scope_get_parser(context->scope); - tokenizer_print_error(&parser->tokenizer, - tokenizer_get_code_reference_index(&parser->tokenizer, ast_get_code_reference(self->rhs).data), + parser_print_error(parser, ast_get_code_reference(self->rhs).data, "Can't cast type \"%.*s\" to type \"%.*s\"", self->rhs->resolve_data.type->var_name.size, self->rhs->resolve_data.type->var_name.data, self->lhs->resolve_data.type->var_name.size, self->lhs->resolve_data.type->var_name.data); - tokenizer_print_error(&parser->tokenizer, - tokenizer_get_code_reference_index(&parser->tokenizer, ast_get_code_reference(self->lhs).data), + parser_print_error(parser, ast_get_code_reference(self->lhs).data, "Left-hand side is of type %.*s", self->lhs->resolve_data.type->var_name.size, self->lhs->resolve_data.type->var_name.data); - tokenizer_print_error(&parser->tokenizer, - tokenizer_get_code_reference_index(&parser->tokenizer, ast_get_code_reference(self->rhs).data), + parser_print_error(parser, ast_get_code_reference(self->rhs).data, "Right-hand side is of type %.*s", self->rhs->resolve_data.type->var_name.size, self->rhs->resolve_data.type->var_name.data); throw(AST_ERR); @@ -474,9 +470,7 @@ void ast_resolve(Ast *self, AstCompilerContext *context) { } else if(self->resolve_data.status == AST_RESOLVING) { Parser *parser; parser = scope_get_parser(context->scope); - tokenizer_print_error(&parser->tokenizer, - tokenizer_get_code_reference_index(&parser->tokenizer, ast_get_code_reference(self).data), - "Found recursive dependency"); + parser_print_error(parser, ast_get_code_reference(self).data, "Found recursive dependency"); throw(AST_ERR); } @@ -489,9 +483,7 @@ void ast_resolve(Ast *self, AstCompilerContext *context) { Parser *parser; parser = scope_get_parser(context->scope); amal_mutex_tryunlock(self->value.lhs_expr->mutex); - tokenizer_print_error(&parser->tokenizer, - tokenizer_get_code_reference_index(&parser->tokenizer, ast_get_code_reference(self).data), - "Found recursive dependency"); + parser_print_error(parser, ast_get_code_reference(self).data, "Found recursive dependency"); throw(AST_ERR); } } diff --git a/src/bytecode/bytecode.c b/src/bytecode/bytecode.c index 7feb185..6774a54 100644 --- a/src/bytecode/bytecode.c +++ b/src/bytecode/bytecode.c @@ -2,7 +2,11 @@ #include "../../include/std/mem.h" #include "../../include/ssa/ssa.h" #include "../../include/parser.h" +#include "../../include/compiler.h" #include +#include /* TODO: Remove this */ +#include +#include #define throw(result) do { throw_debug_msg; longjmp(self->env, (result)); } while(0) #define throw_if_error(result) \ @@ -62,6 +66,8 @@ static void add_intermediates(BytecodeCompilerContext *self) { } } +#define NUM_MAX_REGS 256 + static void add_instructions(BytecodeCompilerContext *self) { Ssa *ssa; u8 *instruction; @@ -70,10 +76,26 @@ static void add_instructions(BytecodeCompilerContext *self) { SsaInsForm2 ssa_ins_form2; SsaInsFuncStart ssa_ins_func_start; SsaInsFuncCall ssa_ins_func_call; + FILE *file; + char *filename; + LhsExpr *reg_types[NUM_MAX_REGS]; /* TODO: Remove this. Encode this data in the register itself */ ssa = self->parser->ssa; instruction = buffer_begin(&ssa->instructions); instructions_end = buffer_end(&ssa->instructions); + /*#warning "dont forget to remove this" */ + filename = malloc(self->parser->tokenizer.code_name.size + 3); + filename[0] = '\0'; + strcat(filename, self->parser->tokenizer.code_name.data); + strcat(filename, ".z"); + file = fopen(filename, "wb"); + free(filename); + #ifdef DEBUG + am_memset(reg_types, 0, sizeof(reg_types)); + #endif + + fputs("typedef i64 signed long long;\n", file); + fputs("typedef f64 double;\n", file); while(instruction != instructions_end) { switch(*instruction++) { @@ -81,43 +103,108 @@ static void add_instructions(BytecodeCompilerContext *self) { SsaNumber number; instruction += ssa_extract_form1(instruction, &ssa_ins_form1); number = ssa_get_intermediate(ssa, ssa_ins_form1.rhs); - (void)number; + assert(ssa_ins_form1.lhs < NUM_MAX_REGS); + if(number.type == SSA_NUMBER_TYPE_INTEGER) { + fprintf(file, "i64 r%d = %zu;\n", ssa_ins_form1.lhs, number.value.integer); + reg_types[ssa_ins_form1.lhs] = self->parser->compiler->default_types.i64; + } else if(number.type == SSA_NUMBER_TYPE_FLOAT) { + fprintf(file, "f64 r%d = %f;\n", ssa_ins_form1.lhs, number.value.floating); + reg_types[ssa_ins_form1.lhs] = self->parser->compiler->default_types.f64; + } else { + assert(bool_false && "TODO: Implement"); + } break; } - case SSA_ASSIGN_STRING: + case SSA_ASSIGN_STRING: { + BufferView str; instruction += ssa_extract_form1(instruction, &ssa_ins_form1); + str = ssa_get_string(ssa, ssa_ins_form1.rhs); + fprintf(file, "const char* r%d = \"%.*s\";\n", ssa_ins_form1.lhs, (int)str.size, str.data); + assert(ssa_ins_form1.lhs < NUM_MAX_REGS); + reg_types[ssa_ins_form1.lhs] = self->parser->compiler->default_types.str; break; - case SSA_ASSIGN_REG: + } + case SSA_ASSIGN_REG: { + LhsExpr *rhs_type; + const char *rhs_type_name; instruction += ssa_extract_form1(instruction, &ssa_ins_form1); + assert(ssa_ins_form1.rhs < NUM_MAX_REGS); + rhs_type = reg_types[ssa_ins_form1.rhs]; + if(rhs_type == self->parser->compiler->default_types.i64) { + rhs_type_name = "i64"; + } else if(rhs_type == self->parser->compiler->default_types.f64) { + rhs_type_name = "f64"; + } else if(rhs_type == self->parser->compiler->default_types.str) { + rhs_type_name = "const char*"; + } else { + amal_log_error("Invalid rhs type %p for reg %d", rhs_type, ssa_ins_form1.rhs); + assert(bool_false && "TODO: Implement"); + } + fprintf(file, "%s r%d = r%d;\n", rhs_type_name, ssa_ins_form1.lhs, ssa_ins_form1.rhs); break; - case SSA_ADD: + } + case SSA_ADD: { instruction += ssa_extract_form2(instruction, &ssa_ins_form2); + fprintf(file, "r%d = r%d + r%d;\n", ssa_ins_form2.result, ssa_ins_form2.lhs, ssa_ins_form2.rhs); + assert(ssa_ins_form2.result < NUM_MAX_REGS); + assert(ssa_ins_form2.rhs < NUM_MAX_REGS); + reg_types[ssa_ins_form2.result] = reg_types[ssa_ins_form2.rhs]; break; - case SSA_SUB: + } + case SSA_SUB: { instruction += ssa_extract_form2(instruction, &ssa_ins_form2); + fprintf(file, "r%d = r%d - r%d;\n", ssa_ins_form2.result, ssa_ins_form2.lhs, ssa_ins_form2.rhs); + assert(ssa_ins_form2.result < NUM_MAX_REGS); + assert(ssa_ins_form2.rhs < NUM_MAX_REGS); + reg_types[ssa_ins_form2.result] = reg_types[ssa_ins_form2.rhs]; break; - case SSA_MUL: + } + case SSA_MUL: { instruction += ssa_extract_form2(instruction, &ssa_ins_form2); + fprintf(file, "r%d = r%d * r%d;\n", ssa_ins_form2.result, ssa_ins_form2.lhs, ssa_ins_form2.rhs); + assert(ssa_ins_form2.result < NUM_MAX_REGS); + assert(ssa_ins_form2.rhs < NUM_MAX_REGS); + reg_types[ssa_ins_form2.result] = reg_types[ssa_ins_form2.rhs]; break; - case SSA_DIV: + } + case SSA_DIV: { instruction += ssa_extract_form2(instruction, &ssa_ins_form2); + fprintf(file, "r%d = r%d / r%d;\n", ssa_ins_form2.result, ssa_ins_form2.lhs, ssa_ins_form2.rhs); + assert(ssa_ins_form2.result < NUM_MAX_REGS); + assert(ssa_ins_form2.rhs < NUM_MAX_REGS); + reg_types[ssa_ins_form2.result] = reg_types[ssa_ins_form2.rhs]; break; - case SSA_FUNC_START: + } + case SSA_FUNC_START: { + int i; instruction += ssa_extract_func_start(instruction, &ssa_ins_func_start); + fprintf(file, "void f%zu(", ssa_ins_func_start.func_index); + fputs(") {\n", file); + for(i = 0; i < ssa_ins_func_start.num_args; ++i) { + if(i > 0) + fputs(", ", file); + fprintf(file, "p%d", i); + } break; + } case SSA_FUNC_END: + fputs("}\n", file); break; case SSA_PUSH: { SsaRegister reg; am_memcpy(®, instruction, sizeof(SsaRegister)); instruction += sizeof(SsaRegister); + fprintf(file, "PUSH r%d ***\n", reg); break; } case SSA_CALL: instruction += ssa_extract_func_call(instruction, &ssa_ins_func_call); + fprintf(file, "r%d = CALL %p ***\n", ssa_ins_func_call.result, ssa_ins_func_call.func_decl); break; } } + + fclose(file); } void generate_bytecode_from_ssa(BytecodeCompilerContext *self) { diff --git a/src/compiler.c b/src/compiler.c index 3a921c3..30a583a 100644 --- a/src/compiler.c +++ b/src/compiler.c @@ -464,6 +464,7 @@ static CHECK_RESULT int try_create_file_scope(amal_compiler *compiler, const cha result_path = NULL; *new_entry = bool_false; + /* TODO: Optimize. No need to allocate everytime... */ return_if_error(file_get_canonical_path(filepath, &result_path, &result_path_size)); path_view = create_buffer_view(result_path, result_path_size); cleanup_if_error(amal_mutex_lock(&compiler->mutex, "try_create_file_scope")); diff --git a/src/parser.c b/src/parser.c index 8e122fd..f05b31d 100644 --- a/src/parser.c +++ b/src/parser.c @@ -598,17 +598,13 @@ int parser_parse_buffer(Parser *self, BufferView code_buffer, BufferView buffer_ } int parser_parse_file(Parser *self, BufferView filepath) { - int result; - char *file_data; - usize file_size; - + Buffer file_content; + return_if_error(buffer_init(&file_content, self->allocator)); assert(!self->started && "Parser can't be reused. Create a new parser."); self->started = bool_true; assert(filepath.size > 0 && filepath.data[filepath.size] == '\0'); - result = read_whole_file(filepath.data, &file_data, &file_size); - if(result != 0) return result; - result = parser_parse_buffer(self, create_buffer_view(file_data, file_size), filepath); - return result; + return_if_error(read_whole_file(filepath.data, &file_content)); + return parser_parse_buffer(self, create_buffer_view(file_content.data, file_content.size), filepath); } static CHECK_RESULT int file_path_join(BufferView directory, BufferView file, char **result_path) { diff --git a/src/ssa/ssa.c b/src/ssa/ssa.c index e7434f8..c4ed0d3 100644 --- a/src/ssa/ssa.c +++ b/src/ssa/ssa.c @@ -50,7 +50,8 @@ int ssa_init(Ssa *self, ScopedAllocator *allocator) { return_if_error(buffer_init(&self->instructions, allocator)); return_if_error(hash_map_init(&self->intermediates_map, allocator, sizeof(SsaIntermediateIndex), compare_number, hash_number)); return_if_error(buffer_init(&self->intermediates, allocator)); - return_if_error(hash_map_init(&self->strings, allocator, sizeof(SsaStringIndex), hash_compare_string, amal_hash_string)); + return_if_error(hash_map_init(&self->strings_map, allocator, sizeof(SsaStringIndex), hash_compare_string, amal_hash_string)); + return_if_error(buffer_init(&self->strings, allocator)); self->intermediate_counter = 0; self->string_counter = 0; self->reg_counter = 0; @@ -69,7 +70,14 @@ int ssa_get_unique_reg(Ssa *self, SsaRegister *result) { SsaNumber ssa_get_intermediate(Ssa *self, SsaIntermediateIndex index) { SsaNumber result; assert(index < buffer_get_size(&self->intermediates, SsaNumber)); - am_memcpy(&result, buffer_get(&self->intermediates, index, sizeof(SsaNumber)), sizeof(result)); + am_memcpy(&result, buffer_get(&self->intermediates, index, sizeof(SsaNumber)), sizeof(SsaNumber)); + return result; +} + +BufferView ssa_get_string(Ssa *self, SsaStringIndex index) { + BufferView result; + assert(index < buffer_get_size(&self->strings, BufferView)); + am_memcpy(&result, buffer_get(&self->strings, index, sizeof(BufferView)), sizeof(BufferView)); return result; } @@ -109,7 +117,7 @@ static CHECK_RESULT int ssa_try_add_string(Ssa *self, BufferView str, SsaStringI bool exists; assert(result_index); - exists = hash_map_get(&self->strings, str, result_index); + exists = hash_map_get(&self->strings_map, str, result_index); if(exists) return 0; @@ -120,7 +128,8 @@ static CHECK_RESULT int ssa_try_add_string(Ssa *self, BufferView str, SsaStringI *result_index = self->string_counter; ++self->string_counter; amal_log_debug("s%u = \"%.*s\"", *result_index, str.size, str.data); - return hash_map_insert(&self->strings, str, result_index); + return_if_error(buffer_append(&self->strings, &str, sizeof(str))); + return hash_map_insert(&self->strings_map, str, result_index); } static CHECK_RESULT int ssa_add_ins_form1(Ssa *self, SsaInstruction ins_type, SsaRegister lhs, u16 rhs) { @@ -157,7 +166,7 @@ static CHECK_RESULT int ssa_add_ins_form2(Ssa *self, SsaInstruction ins_type, Ss return_if_error(buffer_append_empty(&self->instructions, sizeof(u8) + sizeof(SsaRegister) + sizeof(SsaRegister) + sizeof(SsaRegister))); *result = self->reg_counter++; self->instructions.data[index + 0] = ins_type; - am_memcpy(self->instructions.data + index + 1, &result, sizeof(*result)); + am_memcpy(self->instructions.data + index + 1, result, sizeof(SsaRegister)); am_memcpy(self->instructions.data + index + 3, &lhs, sizeof(lhs)); am_memcpy(self->instructions.data + index + 5, &rhs, sizeof(rhs)); amal_log_debug("r%u = r%u %s r%u", *result, lhs, binop_type_to_string(ins_type), rhs); @@ -199,7 +208,7 @@ int ssa_ins_func_start(Ssa *self, u8 num_args, SsaFuncIndex *result) { return_if_error(buffer_append_empty(&self->instructions, sizeof(u8) + sizeof(SsaFuncIndex) + sizeof(u8))); *result = self->func_counter++; self->instructions.data[index + 0] = SSA_FUNC_START; - am_memcpy(self->instructions.data + index + 1, result, sizeof(*result)); + am_memcpy(self->instructions.data + index + 1, result, sizeof(SsaFuncIndex)); self->instructions.data[index + 1 + sizeof(SsaFuncIndex)] = num_args; amal_log_debug("FUNC_START f%u(%u)", *result, num_args); return 0; @@ -234,7 +243,7 @@ int ssa_ins_call(Ssa *self, FunctionDecl *func_decl, SsaRegister *result) { return_if_error(buffer_append_empty(&self->instructions, sizeof(u8) + sizeof(SsaRegister) + sizeof(func_decl))); *result = self->reg_counter++; self->instructions.data[index + 0] = SSA_CALL; - am_memcpy(self->instructions.data + index + 1, result, sizeof(*result)); + am_memcpy(self->instructions.data + index + 1, result, sizeof(SsaRegister)); am_memcpy(self->instructions.data + index + 1 + sizeof(SsaRegister), &func_decl, sizeof(func_decl)); amal_log_debug("r%u = CALL %p", *result, func_decl); return 0; @@ -358,7 +367,7 @@ static CHECK_RESULT SsaRegister string_generate_ssa(String *self, SsaCompilerCon } static CHECK_RESULT SsaRegister variable_generate_ssa(Variable *self, SsaCompilerContext *context) { - /* TODO: Implement */ + /* TODO: Implement, and with cross field references */ (void)self; (void)context; return 0; @@ -399,34 +408,59 @@ static CHECK_RESULT SsaRegister binop_generate_ssa(Binop *self, SsaCompilerConte CHECK_RESULT SsaRegister ast_generate_ssa(Ast *self, SsaCompilerContext *context) { assert(self); #ifdef DEBUG - if(self->resolve_data.status != AST_RESOLVED) { + if(self->resolve_data.status != AST_RESOLVED && self->resolve_data.status != AST_SSA_RESOLVED) { amal_log_error("Ast type not resolved: %d", self->type); assert(bool_false); } #endif + + if(self->resolve_data.status == AST_SSA_RESOLVED) + return self->ssa_reg; + switch(self->type) { case AST_NUMBER: - return number_generate_ssa(self->value.number, context); + self->ssa_reg = number_generate_ssa(self->value.number, context); + self->resolve_data.status = AST_SSA_RESOLVED; + return self->ssa_reg; case AST_FUNCTION_DECL: - return funcdecl_generate_ssa(self->value.func_decl, context); + self->ssa_reg = funcdecl_generate_ssa(self->value.func_decl, context); + self->resolve_data.status = AST_SSA_RESOLVED; + return self->ssa_reg; case AST_FUNCTION_CALL: - return funccall_generate_ssa(self, context); + self->ssa_reg = funccall_generate_ssa(self, context); + self->resolve_data.status = AST_SSA_RESOLVED; + return self->ssa_reg; case AST_STRUCT_DECL: - return structdecl_generate_ssa(self->value.struct_decl, context); + self->ssa_reg = structdecl_generate_ssa(self->value.struct_decl, context); + self->resolve_data.status = AST_SSA_RESOLVED; + return self->ssa_reg; case AST_STRUCT_FIELD: - return structfield_generate_ssa(self->value.struct_field, context); + self->ssa_reg = structfield_generate_ssa(self->value.struct_field, context); + self->resolve_data.status = AST_SSA_RESOLVED; + return self->ssa_reg; case AST_LHS: - return lhsexpr_generate_ssa(self, context); + self->ssa_reg = lhsexpr_generate_ssa(self, context); + self->resolve_data.status = AST_SSA_RESOLVED; + return self->ssa_reg; case AST_IMPORT: - /* TODO: When @import(...).data syntax is added, implement the generate ssa for it */ - return 0; + /* TODO: Implement cross file references */ + self->ssa_reg = 0; + self->resolve_data.status = AST_SSA_RESOLVED; + return self->ssa_reg; case AST_STRING: - return string_generate_ssa(self->value.string, context); + self->ssa_reg = string_generate_ssa(self->value.string, context); + self->resolve_data.status = AST_SSA_RESOLVED; + return self->ssa_reg; case AST_VARIABLE: - return variable_generate_ssa(self->value.variable, context); + self->ssa_reg = variable_generate_ssa(self->value.variable, context); + self->resolve_data.status = AST_SSA_RESOLVED; + return self->ssa_reg; case AST_BINOP: - return binop_generate_ssa(self->value.binop, context); + self->ssa_reg = binop_generate_ssa(self->value.binop, context); + self->resolve_data.status = AST_SSA_RESOLVED; + return self->ssa_reg; } + return 0; } diff --git a/src/std/file.c b/src/std/file.c index 7de2b6c..84f4b0c 100644 --- a/src/std/file.c +++ b/src/std/file.c @@ -192,11 +192,12 @@ static CHECK_RESULT int file_get_type(const char *filepath, FileType *type) { return 0; } -int read_whole_file(const char *filepath, char **data, usize *size) { +int read_whole_file(const char *filepath, Buffer *data_result) { FileType file_type; FILE *file; int result; usize bytes_read; + usize size; return_if_error(file_get_type(filepath, &file_type)); if(file_type != REGULAR) { @@ -218,24 +219,24 @@ int read_whole_file(const char *filepath, char **data, usize *size) { goto cleanup; } - *size = ftell(file); + size = ftell(file); result = fseek(file, 0, SEEK_SET); if(result != 0) { result = ferror(file); goto cleanup; } - if(*size > MAX_FILE_SIZE) { + if(size > MAX_FILE_SIZE) { amal_log_error("File %s is too large (larger than 48 megabytes)", filepath); result = -1; goto cleanup; } - cleanup_if_error(am_malloc(*size, (void**)data)); - bytes_read = fread(*data, 1, *size, file); - if(bytes_read != *size) { + assert(data_result->capacity == 0 && data_result->size == 0); + cleanup_if_error(buffer_append_empty(data_result, size)); + bytes_read = fread(data_result->data, 1, data_result->size, file); + if(bytes_read != size) result = ferror(file); - } cleanup: fclose(file); -- cgit v1.2.3