aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordec05eba <dec05eba@protonmail.com>2019-03-13 00:22:31 +0100
committerdec05eba <dec05eba@protonmail.com>2020-07-25 14:36:46 +0200
commitad54d804fef1e1eb646d8ea4bd7ce65363e94fa8 (patch)
tree41c2d7d9979c98bdd508929a01949ba2f02c679b
parent2d2c31cc18aa9af2cdf26fa462edf7a164d45328 (diff)
Fix bugs
Fix hash map bug on rorder (invalid size). Fix string to int/float conversion in tokenizer. Add more ssa functions
-rw-r--r--include/ssa/ssa.h8
-rw-r--r--src/compiler.c8
-rw-r--r--src/ssa/ssa.c144
-rw-r--r--src/std/hash_map.c12
-rw-r--r--src/tokenizer.c33
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 <assert.h>
+#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, &reg));
+ 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, &reg));
+ 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, &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);