From ad54d804fef1e1eb646d8ea4bd7ce65363e94fa8 Mon Sep 17 00:00:00 2001 From: dec05eba Date: Wed, 13 Mar 2019 00:22:31 +0100 Subject: Fix bugs Fix hash map bug on rorder (invalid size). Fix string to int/float conversion in tokenizer. Add more ssa functions --- include/ssa/ssa.h | 8 ++- src/compiler.c | 8 +-- src/ssa/ssa.c | 144 +++++++++++++++++++++++++++++++++++++++++++++++++---- src/std/hash_map.c | 12 ++--- src/tokenizer.c | 33 ++++++++---- 5 files changed, 171 insertions(+), 34 deletions(-) diff --git a/include/ssa/ssa.h b/include/ssa/ssa.h index a21b45a..5411259 100644 --- a/include/ssa/ssa.h +++ b/include/ssa/ssa.h @@ -27,7 +27,10 @@ typedef enum { } SsaNumberType; typedef struct { - i64 value; + union { + i64 integer; + f64 floating; + } value; SsaNumberType type; } SsaNumber; @@ -44,7 +47,8 @@ typedef struct { } Ssa; /* None of these functions are thread-safe */ -SsaNumber create_ssa_number(i64 value, SsaNumberType type); +SsaNumber create_ssa_integer(i64 value); +SsaNumber create_ssa_float(f64 value); CHECK_RESULT int ssa_init(Ssa *self, ScopedAllocator *allocator); CHECK_RESULT int ssa_get_unique_reg(Ssa *self, SsaRegister *result); diff --git a/src/compiler.c b/src/compiler.c index c50ffac..08d0225 100644 --- a/src/compiler.c +++ b/src/compiler.c @@ -27,12 +27,12 @@ int amal_compiler_init(amal_compiler *self) { if(result != 0) { self->usable_thread_count = amal_get_usable_thread_count(); if(self->usable_thread_count == 0) { - amal_log_info("Unable to get the number of threads available on the system, using 1 thread."); - amal_log_info("You can override the number of threads using by setting the environment variable THREADS"); + amal_log_warning("Unable to get the number of threads available on the system, using 1 thread."); + amal_log_warning("You can override the number of threads using by setting the environment variable THREADS"); self->usable_thread_count = 1; } - } else if(self->usable_thread_count == 0) { - amal_log_info("Environment variable THREADS contains invalid number for threads. THREADS has to be at least 1."); + } else if(self->usable_thread_count <= 0) { + amal_log_error("Environment variable THREADS contains invalid number for threads. THREADS has to be at least 1."); return AMAL_COMPILER_ERR; } diff --git a/src/ssa/ssa.c b/src/ssa/ssa.c index f5187af..1b5ed3d 100644 --- a/src/ssa/ssa.c +++ b/src/ssa/ssa.c @@ -4,12 +4,21 @@ #include "../../include/ast.h" #include +#define throw(result) do { longjmp(context->env, (result)); } while(0) +#define throw_if_error(result) \ +do { \ + int return_if_result; \ + return_if_result = (result); \ + if((return_if_result) != 0) \ + throw(return_if_result); \ +} while(0) + static int compare_number(const void *a, const void *b) { const SsaNumber *lhs; const SsaNumber *rhs; lhs = a; rhs = b; - if(rhs->type == lhs->type && rhs->value == lhs->value) + if(rhs->type == lhs->type && rhs->value.integer == lhs->value.integer) return 0; return 1; } @@ -18,13 +27,20 @@ static usize hash_number(const u8 *data, usize size) { SsaNumber number; assert(size == sizeof(SsaNumber)); am_memcpy(&number, data, size); - return number.value; + return number.value.integer; +} + +SsaNumber create_ssa_integer(i64 value) { + SsaNumber result; + result.value.integer = value; + result.type = SSA_NUMBER_TYPE_INTEGER; + return result; } -SsaNumber create_ssa_number(i64 value, SsaNumberType type) { +SsaNumber create_ssa_float(f64 value) { SsaNumber result; - result.value = value; - result.type = type; + result.value.floating = value; + result.type = SSA_NUMBER_TYPE_FLOAT; return result; } @@ -45,13 +61,11 @@ int ssa_get_unique_reg(Ssa *self, SsaRegister *result) { return 0; } -static CHECK_RESULT int ssa_try_add_intermediate(Ssa *self, i64 intermediate, SsaNumberType number_type, SsaIntermediateIndex *result_index) { - SsaNumber number; +static CHECK_RESULT int ssa_try_add_intermediate(Ssa *self, SsaNumber number, SsaIntermediateIndex *result_index) { bool exists; BufferView key; assert(result_index); - number = create_ssa_number(intermediate, number_type); key = create_buffer_view((const char*)&number, sizeof(number)); exists = hash_map_get(&self->intermediates, key, result_index); @@ -64,6 +78,16 @@ static CHECK_RESULT int ssa_try_add_intermediate(Ssa *self, i64 intermediate, Ss *result_index = self->intermediate_counter; ++self->intermediate_counter; + switch(number.type) { + case SSA_NUMBER_TYPE_INTEGER: { + amal_log_debug("i%u = %lld", *result_index, number.value.integer); + break; + } + case SSA_NUMBER_TYPE_FLOAT: { + amal_log_debug("i%u = %f", *result_index, number.value.floating); + break; + } + } return hash_map_insert(&self->intermediates, key, result_index); } @@ -99,7 +123,7 @@ static CHECK_RESULT int ssa_add_ins_form2(Ssa *self, SsaInstructionType ins_type int ssa_ins_assign_inter(Ssa *self, SsaRegister dest, SsaNumber number) { SsaIntermediateIndex index; - return_if_error(ssa_try_add_intermediate(self, number.value, number.type, &index)); + return_if_error(ssa_try_add_intermediate(self, number, &index)); amal_log_debug("r%u = i%u", dest, index); return ssa_add_ins_form1(self, SSA_ASSIGN_INTER, dest, index); } @@ -165,10 +189,108 @@ int ssa_ins_call(Ssa *self, SsaFuncIndex func, SsaRegister *result) { return 0; } -static void ast_generate_ssa(Ast *self, SsaCompilerContext *context) { +static CHECK_RESULT SsaRegister ast_generate_ssa(Ast *self, SsaCompilerContext *context); + +static CHECK_RESULT SsaRegister number_generate_ssa(Number *self, SsaCompilerContext *context) { + SsaRegister reg; + SsaNumber number; + if(self->is_integer) { + number = create_ssa_integer(self->value.integer); + throw_if_error(ssa_get_unique_reg(&context->ssa, ®)); + throw_if_error(ssa_ins_assign_inter(&context->ssa, reg, number)); + } else { + number = create_ssa_float(self->value.floating); + throw_if_error(ssa_get_unique_reg(&context->ssa, ®)); + throw_if_error(ssa_ins_assign_inter(&context->ssa, reg, number)); + } + return reg; +} + +static CHECK_RESULT SsaRegister funcdecl_generate_ssa(FunctionDecl *self, SsaCompilerContext *context) { + /* TODO: Implement */ + scope_generate_ssa(&self->body, context); + return 0; +} + +static CHECK_RESULT SsaRegister funccall_generate_ssa(FunctionCall *self, SsaCompilerContext *context) { + /* TODO: Implement */ + (void)self; + (void)context; + return 0; +} + +static CHECK_RESULT SsaRegister lhs_generate_ssa(LhsExpr *self, SsaCompilerContext *context) { + /* TODO: Implement */ + SsaRegister rhs_reg; + amal_log_debug("lhs_generate_ssa"); + rhs_reg = ast_generate_ssa(&self->rhs_expr, context); + return rhs_reg; +} + +static CHECK_RESULT SsaRegister string_generate_ssa(String *self, SsaCompilerContext *context) { /* TODO: Implement */ (void)self; (void)context; + return 0; +} + +static CHECK_RESULT SsaRegister variable_generate_ssa(Variable *self, SsaCompilerContext *context) { + /* TODO: Implement */ + (void)self; + (void)context; + return 0; +} + +static SsaInstructionType binop_type_to_ssa_type(BinopType binop_type) { + switch(binop_type) { + case BINOP_ADD: + return SSA_ADD; + case BINOP_SUB: + return SSA_SUB; + case BINOP_MUL: + return SSA_MUL; + case BINOP_DIV: + return SSA_DIV; + case BINOP_DOT: + assert(bool_false && "TODO: Implement dot access"); + return 0; + } + return 0; +} + +static CHECK_RESULT SsaRegister binop_generate_ssa(Binop *self, SsaCompilerContext *context) { + SsaRegister lhs_reg; + SsaRegister rhs_reg; + SsaRegister reg; + lhs_reg = ast_generate_ssa(&self->lhs, context); + rhs_reg = ast_generate_ssa(&self->rhs, context); + throw_if_error(ssa_ins_binop(&context->ssa, binop_type_to_ssa_type(self->type), lhs_reg, rhs_reg, ®)); + return reg; +} + +CHECK_RESULT SsaRegister ast_generate_ssa(Ast *self, SsaCompilerContext *context) { + switch(self->type) { + case AST_NONE: + return 0; + case AST_NUMBER: + return number_generate_ssa(self->value.number, context); + case AST_FUNCTION_DECL: + return funcdecl_generate_ssa(self->value.func_decl, context); + case AST_FUNCTION_CALL: + return funccall_generate_ssa(self->value.func_call, context); + case AST_LHS: + return lhs_generate_ssa(self->value.lhs_expr, context); + case AST_IMPORT: + /* TODO: When @import(...).data syntax is added, implement the generate ssa for it */ + return 0; + case AST_STRING: + return string_generate_ssa(self->value.string, context); + case AST_VARIABLE: + return variable_generate_ssa(self->value.variable, context); + case AST_BINOP: + return binop_generate_ssa(self->value.binop, context); + } + return 0; } void scope_generate_ssa(Scope *self, SsaCompilerContext *context) { @@ -177,6 +299,6 @@ void scope_generate_ssa(Scope *self, SsaCompilerContext *context) { ast = buffer_start(&self->ast_objects); ast_end = buffer_end(&self->ast_objects); for(; ast != ast_end; ++ast) { - ast_generate_ssa(ast, context); + ignore_result_int(ast_generate_ssa(ast, context)); } } diff --git a/src/std/hash_map.c b/src/std/hash_map.c index 402c56d..61030da 100644 --- a/src/std/hash_map.c +++ b/src/std/hash_map.c @@ -116,7 +116,7 @@ static void hash_map_reorder_nodes(HashMap *self, usize end_index) { bucket_node = bucket_node_get_next(bucket_node); bucket_node_set_next(moved_node, new_bucket->start); new_bucket->start = moved_node; - /* Mark bucket node to be removed bucket by dechaining */ + /* Remove current from chain by chaining previous and next */ if(prev_bucket_node) bucket_node_set_next(prev_bucket_node, bucket_node); else @@ -134,13 +134,13 @@ static void hash_map_reorder_nodes(HashMap *self, usize end_index) { } static CHECK_RESULT int hash_map_increase_buckets(HashMap *self) { - usize prev_size; + usize prev_num_elements; usize bytes_to_append; - prev_size = buffer_get_size(&self->buckets, HashMapBucket); - bytes_to_append = prev_size * 1.5; + prev_num_elements = buffer_get_size(&self->buckets, HashMapBucket); + bytes_to_append = (usize)(prev_num_elements * 1.5) * sizeof(HashMapBucket); return_if_error(buffer_append(&self->buckets, NULL, bytes_to_append)); - am_memset(((HashMapBucket*)self->buckets.data) + prev_size, 0, bytes_to_append); - hash_map_reorder_nodes(self, prev_size); + am_memset(((HashMapBucket*)self->buckets.data) + prev_num_elements, 0, bytes_to_append); + hash_map_reorder_nodes(self, prev_num_elements); return 0; } diff --git a/src/tokenizer.c b/src/tokenizer.c index 4f1871b..5f6e59c 100644 --- a/src/tokenizer.c +++ b/src/tokenizer.c @@ -82,6 +82,7 @@ static CHECK_RESULT int find_end_of_string(BufferView buf, int index) { return -1; } +/* TODO: Optimize string to integer and string to float */ #define I64_OVERFLOW_ERROR -1 static CHECK_RESULT int string_to_integer_unchecked(BufferView str, i64 *result) { int i; @@ -91,7 +92,7 @@ static CHECK_RESULT int string_to_integer_unchecked(BufferView str, i64 *result) for(i = 0; i < (int)str.size; ++i) { i64 value_before; value_before = value; - value *= 10 + str.data[i]; + value = value * 10 + (str.data[i] - '0'); /* overflow */ if(value < value_before) return I64_OVERFLOW_ERROR; @@ -102,21 +103,31 @@ static CHECK_RESULT int string_to_integer_unchecked(BufferView str, i64 *result) } #define F64_OVERFLOW_ERROR -1 -static CHECK_RESULT int string_to_float_unchecked(BufferView str, f64 *result) { +static CHECK_RESULT int string_to_float_unchecked(BufferView str, int dot_index, f64 *result) { int i; - f64 value; + f64 value_before_dot; + f64 value_after_dot; + f64 div_factor; - value = 0.0; - for(i = 0; i < (int)str.size; ++i) { + value_before_dot = 0.0; + for(i = 0; i < dot_index; ++i) { f64 value_before; - value_before = value; - value *= 10.0 + str.data[i]; + value_before = value_before_dot; + value_before_dot = value_before_dot * 10.0 + (str.data[i] - '0'); /* overflow */ - if(value < value_before) + if(value_before_dot < value_before) return F64_OVERFLOW_ERROR; } - *result = value; + value_after_dot = 0.0; + div_factor = 1.0; + for(i = dot_index + 1; i < (int)str.size; ++i) { + value_after_dot = value_after_dot * 10.0 + (str.data[i] - '0'); + div_factor *= 10.0; + /* TODO: Check mantissa overflow */ + } + + *result = value_before_dot + (value_after_dot / div_factor); return 0; } @@ -201,7 +212,7 @@ static CHECK_RESULT int __tokenizer_next(Tokenizer *self, Token *token) { if(isDigit(c)) ++self->index; else if(c == '.' && dot_index == -1) { - dot_index = self->index; + dot_index = self->index - number_start; ++self->index; } else { break; @@ -221,7 +232,7 @@ static CHECK_RESULT int __tokenizer_next(Tokenizer *self, Token *token) { self->number_is_integer = bool_true; } else { int result; - result = string_to_float_unchecked(number_str, &self->value.floating); + result = string_to_float_unchecked(number_str, dot_index, &self->value.floating); if(result != 0) { /* TODO */ tokenizer_print_error(self, self->prev_index, "Float value %.*s is too large to fit in 64-bit. Support for large floating numbers is not supported yet.", number_str.size, number_str.data); -- cgit v1.2.3