aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authordec05eba <dec05eba@protonmail.com>2019-04-24 21:22:53 +0200
committerdec05eba <dec05eba@protonmail.com>2020-07-25 14:36:46 +0200
commit7f524c427597cc998f243769b0e22e4f450c55cf (patch)
tree0dba782c2214d1ce5309ba71cfd3dddaee4a52a1 /src
parent328a9c8310e8bab250b04e9e001ab0d890d33074 (diff)
Progressing on bytecode (to c), fix ssa resolving multiple times
Diffstat (limited to 'src')
-rw-r--r--src/ast.c70
-rw-r--r--src/bytecode/bytecode.c103
-rw-r--r--src/compiler.c1
-rw-r--r--src/parser.c12
-rw-r--r--src/ssa/ssa.c74
-rw-r--r--src/std/file.c15
6 files changed, 193 insertions, 82 deletions
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 <assert.h>
+#include <stdarg.h>
#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 <assert.h>
+#include <stdio.h> /* TODO: Remove this */
+#include <stdlib.h>
+#include <string.h>
#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(&reg, 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);