summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--compiler.c246
1 files changed, 161 insertions, 85 deletions
diff --git a/compiler.c b/compiler.c
index 2b1c4fa..6582233 100644
--- a/compiler.c
+++ b/compiler.c
@@ -800,20 +800,20 @@ void var_chg_register(CompData *out, Variable *swap, int new_reg) {
// or value setting.
void var_op_dereference(CompData *out, Variable *store, Variable *from) {
*store = var_copy(from);
- if(from->ptr_chain.count < 1 || _var_ptr_type(from) != PTYPE_REF) {
- printf("WARNING: var_op_dereference called on variable which is not a reference!");
+ if(from->ptr_chain.count < 1) {
+ printf("WARNING: var_op_dereference called on variable which is not a pointer!\n");
return;
}
- if (from->location < 1 || from->ptr_chain.count > 1) {
+ // If we are not in a register, or we are a multiref not already in rsi
+ if (from->location < 1 || (_var_ptr_type(from) == PTYPE_REF && from->location != 5 && from->ptr_chain.count > 1)) {
// Generate initial move (from -> rsi)
- if (_var_ptr_type(from) > 0)
+ if (_var_ptr_type(from) > 1)
+ // If in-place array, generate reference by lea
vect_push_string(&out->text, "\tlea rsi, ");
else
+ // If pointer, generate reference by mov
vect_push_string(&out->text, "\tmov rsi, ");
-
- if (from->location == LOC_DATA || from->location == LOC_STCK)
- vect_push_string(&out->text, PREFIXES[7]);
vect_push_free_string(&out->text, _op_get_location(from));
vect_push_string(&out->text, "; Move for dereference\n");
@@ -1111,8 +1111,8 @@ char *_var_get_from(CompData *out, Variable *store, Variable *from) {
vect_push_free_string(&out->text, _op_get_location(from));
vect_push_string(&out->text, " ; pre-deref for inbuilt mov (from)\n");
- for(size_t i = store->ptr_chain.count - 1; i > 0; i--){
- int *cur = vect_get(&store->ptr_chain, i);
+ for(size_t i = from->ptr_chain.count - 1; i > 0; i--){
+ int *cur = vect_get(&from->ptr_chain, i);
if (cur == PTYPE_REF) {
vect_push_string(&out->text, "\tmov rsi, [rsi] ; deref for mov\n");
} else
@@ -1122,7 +1122,7 @@ char *_var_get_from(CompData *out, Variable *store, Variable *from) {
vect_push_string(&out->text, "\tmov ");
vect_push_free_string(&out->text, _op_get_register(5, _var_size(from)));
vect_push_string(&out->text, ", ");
- vect_push_string(&out->text, PREFIXES[_var_size(from)]);
+ vect_push_string(&out->text, PREFIXES[_var_size(from) - 1]);
vect_push_string(&out->text, "[rsi] ; pre-deref for inbuilt mov (from)\n");
mov_from = _op_get_register(5, _var_size(from));
@@ -1317,6 +1317,22 @@ void var_op_reference(CompData *out, Variable *store, Variable *from) {
printf("ERROR: Unable to do dereference with literal value\n\n");
return;
}
+
+ *store = var_copy(from);
+ if (store->ptr_chain.count > 0) {
+ for(size_t i = 0; i < store->ptr_chain.count; i++) {
+ int *cur = vect_get(&store->ptr_chain, i);
+ if (*cur == PTYPE_REF) {
+ *cur = PTYPE_PTR;
+ break;
+ }
+ }
+ } else {
+ int ref = PTYPE_REF;
+ vect_push(&store->ptr_chain, &ref);
+ }
+ store->location = 5;
+ store->offset = 0;
if(from->ptr_chain.count > 0 && _var_ptr_type(from) == PTYPE_REF) {
// The value is a reference to data, so we should just copy it
@@ -1331,33 +1347,14 @@ void var_op_reference(CompData *out, Variable *store, Variable *from) {
}
vect_push_string(&out->text, "\tlea ");
- if(store->location < 1) {
- // Store is on stack or in data sec, so we need to
- // copy into a tmp register first (we use rsi by convention)
- vect_push_free_string(&out->text, _op_get_register(5, _var_pure_size(store)));
- } else {
- // Since store is in a register we can directly lea
- vect_push_free_string(&out->text, _op_get_register(store->location, _var_pure_size(store)));
- }
-
+ vect_push_free_string(&out->text, _op_get_register(5, _var_pure_size(store)));
vect_push_string(&out->text, ", ");
vect_push_free_string(&out->text, _op_get_location(from));
vect_push_string(&out->text, " ; Generate reference\n");
-
- if(store->location < 1) {
- // If we stored in a tmp register, we need to complete
- // the move
- vect_push_string(&out->text, "\tmov ");
- vect_push_free_string(&out->text, _op_get_location(store));
- vect_push_string(&out->text, ", ");
- vect_push_free_string(&out->text, _op_get_register(5, _var_pure_size(store)));
- vect_push_string(&out->text, " ; Move ref from tmp register to final location\n");
- }
-
vect_push_string(&out->text, "\n");
}
-Variable var_op_member(Variable *from, char *member) {
+Variable var_op_member(CompData *data, Variable *from, char *member) {
Variable out = {0};
out.name = NULL; // This is how you can check weather we succeeded
@@ -1365,6 +1362,11 @@ Variable var_op_member(Variable *from, char *member) {
printf("ERROR: Unable to take member from literal value");
return out;
}
+
+ if (from->ptr_chain.count > 1 || (from->ptr_chain.count == 1 && _var_ptr_type(from) != PTYPE_REF)) {
+ printf("ERROR: Can't generate member for pointer!\n");
+ return out;
+ }
for (size_t i = 0; i < from->type->members.count; i++) {
Variable *mem = vect_get(&from->type->members, i);
@@ -1373,6 +1375,9 @@ Variable var_op_member(Variable *from, char *member) {
break;
}
}
+
+ if (out.name == NULL)
+ return out;
// Copy ptr_chain so when using the variable we follow all references
for(size_t i = 0; i < from->ptr_chain.count; i++) {
@@ -1385,14 +1390,25 @@ Variable var_op_member(Variable *from, char *member) {
// If the variable is in the data section, we should copy
// the name as well so references are properly handled
- if(out.location == LOC_DATA) {
+ if (out.location != 5 && _var_ptr_type(&out) == PTYPE_REF) {
+ out.location = 5;
+ var_op_pure_set(data, &out, from);
+ } else if(out.location == LOC_DATA) {
free(out.name);
Vector name = vect_from_string(from->name);
out.name = vect_as_string(&name);
}
- // If from is already offset, we should base our new offset on the old one.
- out.offset += from->offset;
+ if (out.location == 5 && out.offset > 0) {
+ vect_push_string(&data->text, "\tadd rsi, ");
+ vect_push_free_string(&data->text, int_to_str(out.offset));
+ vect_push_string(&data->text, "; Member generation in reference\n");
+ out.offset = 0;
+ } else {
+ // If from is already offset, we should base our new offset on the old one.
+ out.offset += from->offset;
+ }
+
return out;
}
@@ -1897,7 +1913,7 @@ Variable *mod_find_var(Module *mod, Artifact *art) {
Module *mod_find_sub(Module *mod, char *chk) {
for(size_t i = 0; i < mod->submods.count; i++) {
Module *m = vect_get(&mod->submods, i);
- if(strcmp(m->name, chk))
+ if(strcmp(m->name, chk) == 0)
return m;
}
return NULL;
@@ -3110,9 +3126,8 @@ void p1_parse_module(Artifact *path, Module *root, Vector *tokens, size_t *pos)
if (out == NULL) {
Module tmp = mod_init(name, root, export);
- out = &tmp;
- p1_file_loop(path, out, tokens, *pos, end);
- vect_push(&(root->submods), out);
+ p1_file_loop(path, &tmp, tokens, *pos, end);
+ vect_push(&(root->submods), &tmp);
} else {
p1_file_loop(path, out, tokens, *pos, end);
vect_push(&(root->submods), out);
@@ -3263,6 +3278,8 @@ void p1_size_type (Module *root, Type *t) {
free(var->name);
var->name = vect_as_string(&name);
+ var->offset = sum;
+
Type *mt = mod_find_type(root, &rta);
art_end(&rta);
@@ -3710,7 +3727,7 @@ void scope_free_all_tmp(Scope* s, CompData *data) {
int new_top = 0;
for (size_t i = 0; i < s->stack_vars.count; i++) {
Variable *to_free = vect_get(&s->stack_vars, i);
- if(strcmp(to_free->name, "#tmp")) {
+ if(strcmp(to_free->name, "#tmp") == 0) {
var_end(to_free);
vect_remove(&s->stack_vars, i);
i--;
@@ -3774,7 +3791,7 @@ Variable scope_mk_var(Scope *s, CompData *data, Variable *v) {
return var_copy(&out);
}
-Variable _scope_check_vars(Scope *s, char *name) {
+Variable _scope_get_var(Scope *s, char *name) {
for (size_t i = 0; i < s->reg_vars.count; i++) {
Variable *v = vect_get(&s->reg_vars, i);
if (strcmp(v->name, name) == 0)
@@ -3793,27 +3810,31 @@ Variable _scope_check_vars(Scope *s, char *name) {
return out;
}
- return _scope_check_vars(s->parent, name);
+ return _scope_get_var(s->parent, name);
}
-// Get a variable from the scope
-// should be freed
-Variable scope_get_var(Scope *s, char *name) {
- Variable out = _scope_check_vars(s, name);
+
+Variable scope_get_var(Scope *s, Artifact *name) {
+ Variable out = {0};
+ out.name = NULL;
+
+ if (name->count == 1) {
+ char *full = art_to_str(name, '.');
+ out = _scope_get_var(s, full);
+ free(full);
+ }
if (out.name != NULL)
return out;
- Artifact v_art = art_from_str(name, '.');
- Variable *maybe = mod_find_var(s->current, &v_art);
- art_end(&v_art);
+ Variable *mod_search = mod_find_var(s->current, name);
+
+ if (mod_search == NULL)
+ return out;
- if (maybe != NULL)
- out = var_copy(maybe);
- return out;
+ return var_copy(mod_search);
}
-
// TODO: Scope ops like sub-scoping, variable management
// conditional handling, data-section parts for function
// literals, etc.
@@ -3928,14 +3949,8 @@ int op_order(Token *t) {
return -1;
}
-// Strict eval for top-level definitions
-Vector eval_strict() {
- Vector out = vect_init(sizeof(int));
- // TODO
- return out;
-}
-Variable _eval_call(Scope *s, CompData *data, Vector *tokens, Function *f, size_t start) {
+Variable _eval_call(Scope *s, CompData *data, Vector *tokens, Function *f, Variable *self, size_t start) {
Variable v = {0};
v.name = NULL;
// TODO
@@ -3945,20 +3960,21 @@ Variable _eval_call(Scope *s, CompData *data, Vector *tokens, Function *f, size_
Variable _eval_dot(Scope *s, CompData *data, Vector *tokens, size_t start, size_t end) {
Token *t = vect_get(tokens, start);
+ Artifact name = art_from_str(t->data, '.');
+
if (start == end - 1) {
- return scope_get_var(s, t->data);
+ return scope_get_var(s, &name);
}
- Artifact name = art_from_str(t->data, '.');
Variable v = {0};
v.name = NULL;
// Match with first possible variable
+ start = tnsl_next_non_nl(tokens, start);
for (; start < end; start = tnsl_next_non_nl(tokens, start)) {
// Try match variable
- char *full = art_to_str(&name, '.');
- v = scope_get_var(s, full);
- free(full);
+
+ v = scope_get_var(s, &name);
if (v.name != NULL) {
break;
@@ -3967,7 +3983,7 @@ Variable _eval_dot(Scope *s, CompData *data, Vector *tokens, size_t start, size_
// Try expand artifact, or call
t = vect_get(tokens, start);
if (tok_str_eq(t, ".")) {
- t = vect_get(tokens, ++start);
+ t = vect_get(tokens, start);
if (t->type != TT_DEFWORD) {
printf("ERROR: Expected defword after '.' operator but found \"%s\" (%d:%d)\n\n", t->data, t->line, t->col);
return v;
@@ -3977,21 +3993,66 @@ Variable _eval_dot(Scope *s, CompData *data, Vector *tokens, size_t start, size_
// Call
break;
} else {
- printf("Failed to find variable or call in dot chain \"%s\" (%d:%d)\n\n", t->data, t->line, t->col);
+ printf("ERROR: Failed to find variable or call in dot chain \"%s\" (%d:%d)\n\n", t->data, t->line, t->col);
return v;
}
}
+
+ for (; start < end; start = tnsl_next_non_nl(tokens, start)) {
+ t = vect_get(tokens, start);
- // After found var, or in call. We need to check.
- if (v.name == NULL) {
- // Call
- Function *f = mod_find_func(s->current, &name);
- if (f == NULL) {
- printf("ERROR: Could not find function \"%s\" (%d:%d)\n\n", t->data, t->line, t->col);
+ // After found var, or in call. We need to check.
+ if (tok_str_eq(t, "(")) {
+ if (v.name == NULL) {
+ Function *f = mod_find_func(s->current, &name);
+ if (f == NULL) {
+ printf("ERROR: Could not find function \"%s\" (%d:%d)\n\n", t->data, t->line, t->col);
+ art_end(&name);
+ return v;
+ }
+ v = _eval_call(s, data, tokens, f, NULL, start);
+ } else {
+ Function *m = mod_find_func(v.mod, &name);
+ if (m == NULL) {
+ printf("ERROR: Could not find function \"%s\" (%d:%d)\n\n", t->data, t->line, t->col);
+ art_end(&name);
+ return v;
+ }
+ Variable tmp = _eval_call(s, data, tokens, m, &v, start);
+ var_end(&v);
+ v = tmp;
+ }
art_end(&name);
- return v;
+ start = tnsl_find_closing(tokens, start);
+ name = art_from_str("", '.');
+ } else if (tok_str_eq(t, "`")) {
+ Variable store;
+ var_op_dereference(data, &store, &v);
+ var_end(&v);
+ v = store;
+ } else if (tok_str_eq(t, ".")) {
+ Token *next = vect_get(tokens, start + 1);
+ if (next == NULL || next->type != TT_DEFWORD) {
+ printf("ERROR: Expected defword after dot in dotchain: \"%s\" (%d:%d)\n", t->data, t->line, t->col);
+ art_end(&name);
+ return v;
+ }
+ char *m_name = next->data;
+ next = vect_get(tokens, start + 2);
+ if (next == NULL || !tok_str_eq(next, "(")) {
+ Variable m = var_op_member(data, &v, m_name);
+ if (m.name == NULL) {
+ printf("ERROR: Unable to find member variable: \"%s\" of variable \"%s\" (%d:%d)\n", next->data, v.name, next->line, next->col);
+ art_end(&name);
+ return v;
+ }
+ var_end(&v);
+ v = m;
+ } else if (tok_str_eq(next, "(")) {
+ art_add_str(&name, next->data);
+ }
+ start++;
}
- v = _eval_call(s, data, tokens, f, start);
}
art_end(&name);
@@ -4089,7 +4150,13 @@ Variable _eval(Scope *s, CompData *data, Vector *tokens, size_t start, size_t en
Token *d = vect_get(tokens, delim);
if (delim == -1 || (d->data[0] == '(' && delim > start)) {
// Handle dot chains and calls
- return _eval_dot(s, data, tokens, start, end);
+ out = _eval_dot(s, data, tokens, start, end);
+ if (out.location == 5) {
+ Variable tmp = scope_mk_tmp(s, data, &out);
+ var_end(&out);
+ out = tmp;
+ }
+ return out;
}
// Handle delim
@@ -4141,6 +4208,24 @@ Variable _eval(Scope *s, CompData *data, Vector *tokens, size_t start, size_t en
// TODO
Variable rhs = _eval(s, data, tokens, op_pos + 1, end);
+
+ if (op_pos == start) {
+ if (op_token->data[0] == '~') {
+ if (rhs.location > 0 && rhs.ptr_chain.count < 1) {
+ // Move to stack
+ }
+ Variable store;
+ var_op_reference(data, &store, &rhs);
+ var_end(&rhs);
+ rhs = scope_mk_tmp(s, data, &store);
+ var_end(&store);
+ return rhs;
+ } else {
+ printf("ERROR: Unexpected prefix token\n");
+ return rhs;
+ }
+ }
+
out = _eval(s, data, tokens, start, op_pos);
if (out.location == LOC_LITL) {
if (rhs.location != LOC_LITL) {
@@ -4707,15 +4792,6 @@ void p2_file_loop(
}
}
-void p2_finalize_data(Module *root, CompData *out) {
- // TODO: deal with all module vars, create data section.
-}
-
-CompData phase_2(Artifact *path, Module *root) {
- CompData out = p2_compile_file(path, root);
- p2_finalize_data(root, &out);
- return out;
-}
void compile(Artifact *path_in, Artifact *path_out) {
@@ -4730,7 +4806,7 @@ void compile(Artifact *path_in, Artifact *path_out) {
return;
}
- CompData out = phase_2(path_in, &root);
+ CompData out = p2_compile_file(path_in, &root);
mod_deep_end(&root);
if (p2_error) {