compiler

Unnamed repository; edit this file 'description' to name the repository.
git clone https://git.deepztream.com/compiler
Log | Files | Refs

commit 4f394f9ac8ea9732fd67d8a360a52ad1c229075a
parent 56b3154a739b979d92f86334d9785296ac252c6e
Author: William Djupström <william@deepztream.com>
Date:   Mon,  4 Mar 2019 00:24:09 +0000

Currently broken, whatever

Diffstat:
Mparse.y | 815++++++++++++++++++++++++-------------------------------------------------------
1 file changed, 243 insertions(+), 572 deletions(-)

diff --git a/parse.y b/parse.y @@ -93,6 +93,7 @@ struct expression *find_idnt(char *name) } struct expression *ZERO = &(struct expression){ .type = number, .constant = 1 }; +struct expression *ONE = &(struct expression){ .type = number, .constant = 1, .i = 1 }; struct expression *final; struct expression *e(enum e_type type, struct expression *arg1, struct expression *arg2, int nofree) @@ -342,16 +343,16 @@ expression: IDENTIFIER {$$ = copy(find_idnt($1));} | expression "<<" expression {$$ = e(shift_l, $1, $3, 0);} | expression ">>" expression {$$ = e(shift_r, $1, $3, 0);} | expression '=' expression {$$ = e(set, $1, $3, 0);} -| expression "+=" expression {printf("uh-oh\n");$$ = NULL;} -| expression "-=" expression {printf("uh-oh\n");$$ = NULL;} -| expression "*=" expression {printf("uh-oh\n");$$ = NULL;} -| expression "/=" expression {printf("uh-oh\n");$$ = NULL;} -| expression "%=" expression {printf("uh-oh\n");$$ = NULL;} -| expression "&=" expression {printf("uh-oh\n");$$ = NULL;} +| expression "+=" expression {$$ = e(set, $1, e(add, $1, $3, 0), 0);} +| expression "-=" expression {$$ = e(set, $1, e(add, $1, e(neg, $3, NULL, 0), 0), 0);} +| expression "*=" expression {$$ = e(set, $1, e(mul, $1, $3, 0), 0);} +| expression "/=" expression {$$ = e(set, $1, e(divide, $1, $3, 0), 0);} +| expression "%=" expression {$$ = e(set, $1, e(mod, $1, $3, 0), 0);} +| expression "&=" expression {$$ = e(set, $1, e(b_and, $1, $3, 0), 0);} | expression "|=" expression {printf("uh-oh\n");$$ = NULL;} | expression "^=" expression {printf("uh-oh\n");$$ = NULL;} -| expression "<<=" expression {printf("uh-oh\n");$$ = NULL;} -| expression ">>=" expression {printf("uh-oh\n");$$ = NULL;} +| expression "<<=" expression {$$ = e(set, $1, e(shift_l, $1, $3, 0), 0);} +| expression ">>=" expression {$$ = e(set, $1, e(shift_r, $1, $3, 0), 0);} | expression "==" expression {$$ = e(l_eq, $1, $3, 0);} | expression "!=" expression {$$ = e(l_not, e(l_eq, $1, $3, 0), NULL, 0);} | expression '<' expression {$$ = e(l_lt, $1, $3, 0);} @@ -364,8 +365,8 @@ expression: IDENTIFIER {$$ = copy(find_idnt($1));} | '&' expression %prec REF {$$ = e(ref, $2, NULL, 0);} | '-' expression %prec NEG {$$ = e(neg, $2, NULL, 0);} | '+' expression %prec NEG {printf("uh-oh\n");$$ = NULL;} -| "++" expression {printf("uh-oh\n");$$ = NULL;} -| "--" expression {printf("uh-oh\n");$$ = NULL;} +| "++" expression {$$ = e(set, $2, e(add, $2, ONE, 0), 0);} +| "--" expression {$$ = e(set, $2, e(add, $2, e(neg, ONE, NULL, 0), 0), 0);} | expression "++" {printf("uh-oh\n");$$ = NULL;} | expression "--" {printf("uh-oh\n");$$ = NULL;} ; @@ -418,8 +419,20 @@ struct storage { int type; char *var; char rbp; + int rev; }; +struct reg_history { + /* 0 - undefined + * 1 - variable + * 2 - constant */ + int type; + int reg; + int val; + int rev; +}; + struct storage regs[1024]; +struct reg_history reg_hist[16]; const int registers = 16; int next_reg; uint16_t used_regs; @@ -451,7 +464,7 @@ int get_free_reg(int mark_used) exit(1); } -void push(int reg, int *pushed, char *order) { +void push(int reg, int *pushed, char *order, char *from) { int i; if (used_regs & (1 << reg)) { machine_code[mc_ptr++] = 0x48 | (reg > 7 ? 1 : 0); @@ -480,6 +493,7 @@ void pop(int reg, int *pushed) { *pushed &= ~(1 << reg); used_regs |= (1 << reg); next_rbp -= 8; + reg_hist[reg].type = 0; } int compile_tree(FILE *output, struct expression *tree, int discard_result, int out_reg) @@ -491,7 +505,7 @@ int compile_tree(FILE *output, struct expression *tree, int discard_result, int -1, -1, -1, -1 }; int pushed = 0; struct expression *tmp; - fprintf(stderr, "Type: %s\n", exp_str[tree->type]); + //fprintf(stderr, "Type: %s\n", exp_str[tree->type]); switch (tree->type) { case function: next_reg = registers; @@ -499,6 +513,7 @@ int compile_tree(FILE *output, struct expression *tree, int discard_result, int next_rbp = 8; tree->i = mc_ptr; find_idnt(tree->args->str)->i = mc_ptr + start_addr; + memset(reg_hist, 0, sizeof(reg_hist)); if (!strcmp(tree->args->str, "_start")) { entry_addr = mc_ptr; machine_code[mc_ptr++] = 0x55; @@ -532,7 +547,6 @@ int compile_tree(FILE *output, struct expression *tree, int discard_result, int } } func_declares = tree->declares; - used_regs |= (1 << 5); machine_code[mc_ptr++] = 0x55; machine_code[mc_ptr++] = 0x48; machine_code[mc_ptr++] = 0x89; @@ -547,16 +561,22 @@ int compile_tree(FILE *output, struct expression *tree, int discard_result, int } if (tree->args[1].type == idnt && tree->args[1].id_type == parameter) { - machine_code[mc_ptr++] = 0x48; + machine_code[mc_ptr++] = 0x48 | (arg_order[0] > 7 ? 4 : 0); machine_code[mc_ptr++] = 0x89; - machine_code[mc_ptr++] = 0x45 + 8*arg_order[0]; + machine_code[mc_ptr++] = 0x45 + (arg_order[0] % 8) * 8; machine_code[mc_ptr++] = -regs[registers].rbp; + reg_hist[arg_order[0]].type = 1; + reg_hist[arg_order[0]].reg = registers; + reg_hist[arg_order[0]].rev = ++regs[registers].rev; } else if (tree->args[1].type == comma && tree->args[1].args->type == idnt && tree->args[1].args->id_type == parameter) { for (i = 0; i < tree->args[1].args_count; i++) { machine_code[mc_ptr++] = 0x48; machine_code[mc_ptr++] = 0x89; machine_code[mc_ptr++] = 0x45 + 8*arg_order[i]; machine_code[mc_ptr++] = -regs[registers + i].rbp; + reg_hist[arg_order[i]].type = 1; + reg_hist[arg_order[i]].reg = registers + i; + reg_hist[arg_order[i]].rev = ++regs[registers + i].rev; } } } @@ -576,13 +596,7 @@ int compile_tree(FILE *output, struct expression *tree, int discard_result, int case fcall: for (i = 0; i < registers; i++) { if (caller_save & (1 << i)) { - push(i, &pushed, push_order); - /* - machine_code[mc_ptr++] = 0x48 | (i > 7 ? 1 : 0); - machine_code[mc_ptr++] = 0x50 + (i % 8); - next_rbp += 8; - pushed |= (1 << i); - */ + push(i, &pushed, push_order, "fcall (caller_save)"); } } if (tree->args_count == 2) { @@ -594,109 +608,119 @@ int compile_tree(FILE *output, struct expression *tree, int discard_result, int j = compile_tree(output, &tree->args[1], 0, arg_order[0]); } } - if (!(pushed & 1)) { - used_regs |= 1; - } j = find_idnt(tree->args->str)->i; machine_code[mc_ptr++] = 0xe8; *(int32_t *) &machine_code[mc_ptr] = j - start_addr - mc_ptr - 4; mc_ptr += 4; + if (tree->args[1].type == comma) + for (i = 0; i < tree->args[1].args_count; i++) + used_regs &= ~(1 << arg_order[i]); + else + used_regs &= ~(1 << arg_order[0]); + + memset(reg_hist, 0, sizeof(reg_hist)); if (!discard_result) { - if (pushed & 1 && (out_reg < 0 || out_reg >= registers)) { - for (i = 0; i < registers; i++) { - if (!(used_regs & (1 << i))) { - reg = i; - used_regs |= (1 << reg); - break; - } - } - if (i == registers) { - fprintf(stderr, "Out of registers?!? fix me\n"); - exit(1); - } - - } else if (out_reg >= 0 && out_reg < registers){ - reg = out_reg; - machine_code[mc_ptr++] = 0x48 | (reg > 7 ? 1 : 0); - machine_code[mc_ptr++] = 0x89; - machine_code[mc_ptr++] = 0xC0 + (reg % 8); - } - } - for (i = registers - 1; i >= 0; i--) { - if (pushed & (1 << i)) { - machine_code[mc_ptr++] = 0x48 | (i > 7 ? 1 : 0); - machine_code[mc_ptr++] = 0x58 + (i % 8); - next_rbp -= 8; - pushed &= ~(1 << i); - } else { - if (i != reg) used_regs &= ~(1 << i); - } + reg = 0; + used_regs |= !(pushed & 1); } break; case add: - j = compile_tree(output, tree->args, discard_result, get_free_reg(1)); - k = compile_tree(output, &tree->args[1], discard_result, get_free_reg(1)); + j = compile_tree(output, tree->args, discard_result, -1); + k = compile_tree(output, &tree->args[1], discard_result, -1); if (discard_result) { if (j >= 0 && j < registers) used_regs &= ~(1 << j); if (k >= 0 && k < registers) used_regs &= ~(1 << k); break; } - reg = j; - /* - if (reg >= registers) { - reg = get_free_reg(1); - } - if (j >= registers) { - machine_code[mc_ptr++] = 0x48 | (reg > 7 ? 4 : 0); - machine_code[mc_ptr++] = 0x8b; - machine_code[mc_ptr++] = 0x45 + (reg % 8) * 8; - machine_code[mc_ptr++] = -regs[j].rbp; - } - */ - machine_code[mc_ptr++] = 0x48 | (reg > 7 ? 4 : 0); - machine_code[mc_ptr++] = 0x03; - /* - if (tree->args[1].type == idnt) { - machine_code[mc_ptr++] = 0x45 + (reg % 8) * 8; - machine_code[mc_ptr++] = -regs[k].rbp; + if (out_reg < 0 || out_reg != j && out_reg != k) { + if (k >= registers) { + if (j >= registers) { + reg = out_reg; + if (out_reg < 0 || out_reg >= registers) + reg = get_free_reg(1); + machine_code[mc_ptr++] = 0x48 | (reg > 7 ? 4 : 0); + machine_code[mc_ptr++] = 0x8b; + machine_code[mc_ptr++] = 0x45 + (reg % 8) * 8; + machine_code[mc_ptr++] = -regs[j].rbp; + j = reg; + } + machine_code[mc_ptr++] = 0x48 | (j > 7 ? 4 : 0); + machine_code[mc_ptr++] = 0x03; + machine_code[mc_ptr++] = 0x45 + (j % 8) * 8; + machine_code[mc_ptr++] = -regs[k].rbp; + reg = j, l = k; + } else if (j >= registers) { + machine_code[mc_ptr++] = 0x48 | (k > 7 ? 4 : 0); + machine_code[mc_ptr++] = 0x03; + machine_code[mc_ptr++] = 0x45 + (k % 8) * 8; + machine_code[mc_ptr++] = -regs[j].rbp; + reg = k, l = j; + } else { + machine_code[mc_ptr++] = 0x48 | (j > 7 ? 4 : 0) | (k > 7 ? 1 : 0); + machine_code[mc_ptr++] = 0x03; + machine_code[mc_ptr++] = 0xC0 + (j % 8) * 8 + k; + reg = j, l = k; + } } else { - */ - machine_code[mc_ptr-2] |= k > 7 ? 1 : 0; - machine_code[mc_ptr++] = 0xC0 + (reg % 8) * 8 + k; - //} - if (k >= 0 && k < registers) used_regs &= ~(1 << k); + if (out_reg == k) { + l = j; + j = k; + k = l; + } + if (j >= registers) { + if (k >= registers) { + reg = get_free_reg(1); + machine_code[mc_ptr++] = 0x48 | (reg > 7 ? 4 : 0); + machine_code[mc_ptr++] = 0x8b; + machine_code[mc_ptr++] = 0x45 + (reg % 8) * 8; + machine_code[mc_ptr++] = -regs[k].rbp; + k = reg; + } + machine_code[mc_ptr++] = 0x48 | (k > 7 ? 4 : 0); + machine_code[mc_ptr++] = 0x01; + machine_code[mc_ptr++] = 0x45 + (k % 8) * 8; + machine_code[mc_ptr++] = -regs[j].rbp; + } else if (k >= registers) { + machine_code[mc_ptr++] = 0x48 | (j > 7 ? 4 : 0); + machine_code[mc_ptr++] = 0x03; + machine_code[mc_ptr++] = 0x45 + (j % 8) * 8; + machine_code[mc_ptr++] = -regs[k].rbp; + } else { + machine_code[mc_ptr++] = 0x48 | (j > 7 ? 4 : 0) | (k > 7 ? 1 : 0); + machine_code[mc_ptr++] = 0x03; + machine_code[mc_ptr++] = 0xC0 + (j % 8) * 8 + k; + if (reg_hist[j].type & 2 && reg_hist[k].type & 2) { + reg_hist[j].type = 2; + reg_hist[j].val += reg_hist[k].val; + } else if (reg_hist[j].type & 2) { + reg_hist[j].type = 0; + } + } + reg = j, l = k; + } + if (l < registers) used_regs &= ~(1 << l); break; case neg: - j = compile_tree(output, tree->args, discard_result, out_reg); + j = compile_tree(output, tree->args, discard_result, (out_reg >= 0 ? out_reg : get_free_reg(1))); if (discard_result) { if (j < registers) used_regs &= ~(1 << j); break; } reg = j; - if (j >= registers) { - for (i = 0; i < registers; i++) { - if (!(used_regs & (1 << i))) { - reg = i; - used_regs |= (1 << reg); - break; - } - } - if (i == registers) { - fprintf(stderr, "Out of registers?!? fix me\n"); - exit(1); - } + if (reg >= registers) { machine_code[mc_ptr++] = 0x48; - machine_code[mc_ptr++] = 0x8b; - machine_code[mc_ptr++] = 0x45 + reg*8; - machine_code[mc_ptr++] = -regs[j].rbp; + machine_code[mc_ptr++] = 0xf7; + machine_code[mc_ptr++] = 0x5d; + machine_code[mc_ptr++] = -regs[reg].rbp; + } else { + machine_code[mc_ptr++] = 0x48 | (reg > 7 ? 1 : 0); + machine_code[mc_ptr++] = 0xf7; + machine_code[mc_ptr++] = 0xd8 + (reg % 8); } - machine_code[mc_ptr++] = 0x48 | (reg > 7 ? 1 : 0); - machine_code[mc_ptr++] = 0xf7; - machine_code[mc_ptr++] = 0xd8 + (reg % 8); break; case mul: - j = compile_tree(output, tree->args, discard_result, out_reg); + j = compile_tree(output, tree->args, discard_result, -1); k = compile_tree(output, &tree->args[1], discard_result, -1); if (discard_result) { if (j < registers) used_regs &= ~(1 << j); @@ -705,17 +729,7 @@ int compile_tree(FILE *output, struct expression *tree, int discard_result, int } reg = j; if ((out_reg == -1 || out_reg >= registers) && j >= registers) { - for (i = 0; i < registers; i++) { - if (!(used_regs & (1 << i))) { - reg = i; - used_regs |= (1 << reg); - break; - } - } - if (i == registers) { - fprintf(stderr, "Out of registers?!? fix me\n"); - exit(1); - } + reg = get_free_reg(1); if (j >= registers) { machine_code[mc_ptr++] = 0x48 | (reg > 7 ? 4 : 0); machine_code[mc_ptr++] = 0x8b; @@ -728,17 +742,17 @@ int compile_tree(FILE *output, struct expression *tree, int discard_result, int } } - machine_code[mc_ptr++] = 0x48; + machine_code[mc_ptr++] = 0x48 | (reg > 7 ? 4 : 0); machine_code[mc_ptr++] = 0x0F; machine_code[mc_ptr++] = 0xAF; if (k >= registers) { - machine_code[mc_ptr++] = 0x45 + reg*8; + machine_code[mc_ptr++] = 0x45 + (reg % 8) * 8; machine_code[mc_ptr++] = -regs[k].rbp; } else { - machine_code[mc_ptr++] = 0xC0 + reg*8 + k; + machine_code[mc_ptr-3] |= (k > 7 ? 1 : 0); + machine_code[mc_ptr++] = 0xC0 + (reg % 8) * 8 + (k % 8); + used_regs &= ~(1 << k); } - //used_regs &= ~(1 << j); - used_regs &= ~(1 << k); break; case divide: if (discard_result) { @@ -747,38 +761,17 @@ int compile_tree(FILE *output, struct expression *tree, int discard_result, int if (j < registers) used_regs &= ~(1 << j); break; } - used_regs |= 1 | 4; - j = compile_tree(output, tree->args, 0, -1); - used_regs &= ~(1 | 4); - if (j != 0) { - if (used_regs & 1) { - fprintf(stderr, "Not implemented yet! (rax)\n"); - exit(1); - } else { - machine_code[mc_ptr++] = 0x48; - machine_code[mc_ptr++] = 0x8b; - if (j >= registers) { - machine_code[mc_ptr++] = 0x45 + (0 % 8) * 8; - machine_code[mc_ptr++] = -regs[j].rbp; - } else { - machine_code[mc_ptr-2] |= (j > 7 ? 1 : 0); - machine_code[mc_ptr++] = 0xc0 + (j % 8); - } - used_regs |= (1 << 0); - } - used_regs &= ~(1 << j); - } - if (used_regs & 4) { - fprintf(stderr, "Not implemented yet! (rdx)\n"); - } - used_regs |= 1 << 2; + push(0, &pushed, push_order, "divide (rax)"); + push(2, &pushed, push_order, "divide (rdx)"); + j = compile_tree(output, tree->args, 0, 0); machine_code[mc_ptr++] = 0x48; machine_code[mc_ptr++] = 0x99; + used_regs |= (1 << 0) | (1 << 2); k = compile_tree(output, &tree->args[1], 0, -1); machine_code[mc_ptr++] = 0x48; machine_code[mc_ptr++] = 0xF7; - if (tree->args[1].type == idnt) { + if (k >= registers) { machine_code[mc_ptr++] = 0x7d; machine_code[mc_ptr++] = -regs[k].rbp; } else { @@ -795,32 +788,9 @@ int compile_tree(FILE *output, struct expression *tree, int discard_result, int if (j < registers) used_regs &= ~(1 << j); break; } - used_regs |= 1 | 4; - j = compile_tree(output, tree->args, 0, -1); - used_regs &= ~(1 | 4); - if (j != 0) { - if (used_regs & 1) { - fprintf(stderr, "Not implemented yet! (rax)\n"); - exit(1); - } else { - machine_code[mc_ptr++] = 0x48; - machine_code[mc_ptr++] = 0x8b; - if (j >= registers) { - machine_code[mc_ptr++] = 0x45 + (0 % 8) * 8; - machine_code[mc_ptr++] = -regs[j].rbp; - } else { - machine_code[mc_ptr-2] |= (j > 7 ? 1 : 0); - machine_code[mc_ptr++] = 0xc0 + (j % 8); - } - used_regs |= (1 << 0); - } - used_regs &= ~(1 << j); - } - if (used_regs & 4) { - fprintf(stderr, "Not implemented yet! (rdx)\n"); - } - used_regs |= 1 << 0; - used_regs |= 1 << 2; + push(0, &pushed, push_order, "mod (rax)"); + push(2, &pushed, push_order, "mod (rdx)"); + j = compile_tree(output, tree->args, 0, 0); machine_code[mc_ptr++] = 0x48; machine_code[mc_ptr++] = 0x99; @@ -866,17 +836,7 @@ int compile_tree(FILE *output, struct expression *tree, int discard_result, int } reg = j; if (reg >= registers) { - for (i = 0; i < registers; i++) { - if (!(used_regs & (1 << i))) { - reg = i; - used_regs |= (1 << reg); - break; - } - } - if (i == registers) { - fprintf(stderr, "Out of registers?!? fix me\n"); - exit(1); - } + reg = get_free_reg(1); machine_code[mc_ptr++] = 0x48; machine_code[mc_ptr++] = 0x8b; machine_code[mc_ptr++] = 0x45 + reg*8; @@ -917,17 +877,7 @@ int compile_tree(FILE *output, struct expression *tree, int discard_result, int } reg = j; if (reg >= registers) { - for (i = 0; i < registers; i++) { - if (!(used_regs & (1 << i))) { - reg = i; - used_regs |= (1 << reg); - break; - } - } - if (i == registers) { - fprintf(stderr, "Out of registers?!? fix me\n"); - exit(1); - } + reg = get_free_reg(1); machine_code[mc_ptr++] = 0x48; machine_code[mc_ptr++] = 0x8b; machine_code[mc_ptr++] = 0x45 + reg*8; @@ -949,17 +899,7 @@ int compile_tree(FILE *output, struct expression *tree, int discard_result, int } reg = j; if (reg >= registers) { - for (i = 0; i < registers; i++) { - if (!(used_regs & (1 << i))) { - reg = i; - used_regs |= (1 << reg); - break; - } - } - if (i == registers) { - fprintf(stderr, "Out of registers?!? fix me\n"); - exit(1); - } + reg = get_free_reg(1); machine_code[mc_ptr++] = 0x48 | (reg > 7 ? 4 : 0); machine_code[mc_ptr++] = 0x8b; machine_code[mc_ptr++] = 0x45 + (reg % 8) * 8; @@ -986,42 +926,6 @@ int compile_tree(FILE *output, struct expression *tree, int discard_result, int case set: reg = compile_tree(output, tree->args, 0, -1); j = compile_tree(output, &tree->args[1], 0, reg); - /* - if (j < 0) { - fprintf(stderr, "No rvalue for assignment\n"); - exit(1); - } - used_regs &= ~(1 << j); - if (j >= registers) { - for (i = 0; i < registers; i++) { - if (!(used_regs & (1 << i))) { - k = i; - break; - } - } - if (i == registers) { - fprintf(stderr, "Out of registers?!? fix me\n"); - exit(1); - } - machine_code[mc_ptr++] = 0x48 | (k > 7 ? 4 : 0); - machine_code[mc_ptr++] = 0x8b; - machine_code[mc_ptr++] = 0x45 + (k % 8) * 8; - machine_code[mc_ptr++] = -regs[j].rbp; - } else { - k = j; - } - if (reg >= registers) { - machine_code[mc_ptr++] = 0x48 | (k > 7 ? 4 : 0); - machine_code[mc_ptr++] = 0x89; - machine_code[mc_ptr++] = 0x45 + (k % 8) * 8; - machine_code[mc_ptr++] = -regs[reg].rbp; - } else if (tree->args->type == deref) { - machine_code[mc_ptr++] = 0x48 | (reg > 7 ? 1 : 0) | (k > 7 ? 4 : 0); - machine_code[mc_ptr++] = 0x89; - machine_code[mc_ptr++] = 0x00 + (reg % 8) + (k % 8) * 8; - } - if (discard_result) reg = -1; - */ break; case ref: if (tree->args->type != idnt) { @@ -1031,18 +935,8 @@ int compile_tree(FILE *output, struct expression *tree, int discard_result, int if (discard_result) break; j = compile_tree(output, tree->args, 0, -1); reg = out_reg; - if (out_reg < 0 || out_reg >= registers) { - for (i = 0; i < registers; i++) { - if (!(used_regs & (1 << i))) { - k = i; - break; - } - } - if (i == registers) { - fprintf(stderr, "Out of registers?!? fix me\n"); - exit(1); - } - } + if (out_reg < 0 || out_reg >= registers) + reg = get_free_reg(1); used_regs |= (1 << reg); machine_code[mc_ptr++] = 0x48 | (reg > 7 ? 4 : 0); machine_code[mc_ptr++] = 0x8d; @@ -1057,17 +951,7 @@ int compile_tree(FILE *output, struct expression *tree, int discard_result, int } reg = j; if (j >= registers) { - for (i = 0; i < registers; i++) { - if (!(used_regs & (1 << i))) { - reg = i; - break; - } - } - if (i == registers) { - fprintf(stderr, "Out of registers?!? fix me\n"); - exit(1); - } - used_regs |= (1 << reg); + reg = get_free_reg(1); machine_code[mc_ptr++] = 0x48 | (reg > 7 ? 4 : 0); machine_code[mc_ptr++] = 0x8b; machine_code[mc_ptr++] = 0x45 + (reg % 8) * 8; @@ -1087,63 +971,46 @@ int compile_tree(FILE *output, struct expression *tree, int discard_result, int fprintf(stderr, "Unable to locate identifier <%s>\n", tree->str); exit(1); } - /* - if (out_reg != -1 && out_reg < registers) { - reg = out_reg; - machine_code[mc_ptr++] = 0x48 | (reg > 7 ? 4 : 0); - machine_code[mc_ptr++] = 0x8b; - machine_code[mc_ptr++] = 0x45 + (reg % 8) * 8; - machine_code[mc_ptr++] = -regs[i].rbp; - used_regs |= (1 << reg); - } else { - reg = i; + for (i = 0; i < registers; i++) { + if (reg_hist[i].type & 1 && reg_hist[i].reg == reg && reg_hist[i].rev == regs[reg].rev) { + reg = i; + used_regs |= (1 << reg); + break; + } } - */ break; case number: if (discard_result) break; - if (out_reg == -1 || out_reg >= registers) { - for (i = 0; i < registers; i++) { - if (!(used_regs & (1 << i))) { - reg = i; - break; - } - } - if (i == registers) { - fprintf(stderr, "Out of registers?!? fix me\n"); - exit(1); + for (i = 0; i < registers; i++) { + if (reg_hist[i].type & 2 && reg_hist[i].val == tree->i) { + reg = i; + break; } - } else { + } + if (reg < 0) { reg = out_reg; + if (reg == -1 || reg >= registers) + reg = get_free_reg(0); + if (tree->i) { + machine_code[mc_ptr++] = 0x48 | (reg > 7 ? 1 : 0); + machine_code[mc_ptr++] = 0xb8 + (reg % 8); + *(int64_t *) &machine_code[mc_ptr] = tree->i; + mc_ptr += 8; + } else { + machine_code[mc_ptr++] = 0x48 | (reg > 7 ? 5 : 0); + machine_code[mc_ptr++] = 0x33; + machine_code[mc_ptr++] = 0xc0 + (reg % 8) + (reg % 8) * 8; + } + reg_hist[reg].type = 2; + reg_hist[reg].val = tree->i; } used_regs |= (1 << reg); - if (tree->i) { - machine_code[mc_ptr++] = 0x48 | (reg > 7 ? 1 : 0); - machine_code[mc_ptr++] = 0xb8 + (reg % 8); - *(int64_t *) &machine_code[mc_ptr] = tree->i; - mc_ptr += 8; - } else { - machine_code[mc_ptr++] = 0x48 | (reg > 7 ? 5 : 0); - machine_code[mc_ptr++] = 0x33; - machine_code[mc_ptr++] = 0xc0 + (reg % 8) + (reg % 8) * 8; - } break; case string: if (discard_result) break; - if (out_reg == -1 || out_reg >= registers) { - for (i = 0; i < registers; i++) { - if (!(used_regs & (1 << i))) { - reg = i; - break; - } - } - if (i == registers) { - fprintf(stderr, "Out of registers?!? fix me\n"); - exit(1); - } - } else { - reg = out_reg; - } + reg = out_reg; + if (reg == -1 || reg >= registers) + reg = get_free_reg(0); if (!tree->i) { strcpy(&rodata[rd_ptr], tree->str); tree->i = rodata_addr + rd_ptr; @@ -1156,6 +1023,7 @@ int compile_tree(FILE *output, struct expression *tree, int discard_result, int used_regs |= (1 << reg); break; case loop: + memset(reg_hist, 0, sizeof(reg_hist)); machine_code[mc_ptr++] = 0xe9; k = mc_ptr; mc_ptr += 4; @@ -1221,17 +1089,7 @@ int compile_tree(FILE *output, struct expression *tree, int discard_result, int } reg = j; if (j >= registers) { - for (i = 0; i < registers; i++) { - if (!(used_regs & (1 << i))) { - reg = i; - used_regs |= (1 << reg); - break; - } - } - if (i == registers) { - fprintf(stderr, "Out of registers?!? fix me\n"); - exit(1); - } + reg = get_free_reg(1); machine_code[mc_ptr++] = 0x48; machine_code[mc_ptr++] = 0x83; machine_code[mc_ptr++] = 0x7d; @@ -1258,7 +1116,7 @@ int compile_tree(FILE *output, struct expression *tree, int discard_result, int break; case l_eq: j = compile_tree(output, tree->args, discard_result, -1); - k = compile_tree(output, &tree->args[1], discard_result, out_reg); + k = compile_tree(output, &tree->args[1], discard_result, -1); if (discard_result) { if (j < registers) used_regs &= ~(1 << j); if (k < registers) used_regs &= ~(1 << k); @@ -1268,17 +1126,7 @@ int compile_tree(FILE *output, struct expression *tree, int discard_result, int if (j >= registers) { if (k >= registers) { - for (i = 0; i < registers; i++) { - if (!(used_regs & (1 << i))) { - reg = i; - used_regs |= (1 << reg); - break; - } - } - if (i == registers) { - fprintf(stderr, "Out of registers?!? fix me\n"); - exit(1); - } + reg = get_free_reg(1); machine_code[mc_ptr++] = 0x48 | (reg > 7 ? 4 : 0); machine_code[mc_ptr++] = 0x8b; machine_code[mc_ptr++] = 0x45 + (reg % 8) * 8; @@ -1290,26 +1138,10 @@ int compile_tree(FILE *output, struct expression *tree, int discard_result, int machine_code[mc_ptr++] = 0x45 + (k % 8) * 8; machine_code[mc_ptr++] = -regs[j].rbp; } else if (k >= registers) { - for (i = 0; i < registers; i++) { - if (!(used_regs & (1 << i))) { - reg = i; - used_regs |= (1 << reg); - break; - } - } - if (i == registers) { - fprintf(stderr, "Out of registers?!? fix me\n"); - exit(1); - } - machine_code[mc_ptr++] = 0x48 | (reg > 7 ? 4 : 0); - machine_code[mc_ptr++] = 0x8b; - machine_code[mc_ptr++] = 0x45 + (reg % 8) * 8; + machine_code[mc_ptr++] = 0x48 | (j > 7 ? 1 : 0); + machine_code[mc_ptr++] = 0x3b; + machine_code[mc_ptr++] = 0x45 + (j % 8) * 8; machine_code[mc_ptr++] = -regs[k].rbp; - - k = reg; - machine_code[mc_ptr++] = 0x48 | (j > 7 ? 1 : 0) | (k > 7 ? 4 : 0); - machine_code[mc_ptr++] = 0x39; - machine_code[mc_ptr++] = 0xc0 + (j % 8) + (k % 8) * 8; } else { machine_code[mc_ptr++] = 0x48 | (j > 7 ? 1 : 0) | (k > 7 ? 4 : 0); machine_code[mc_ptr++] = 0x39; @@ -1331,67 +1163,44 @@ int compile_tree(FILE *output, struct expression *tree, int discard_result, int mc_ptr += 8; break; case l_lt: - j = compile_tree(output, tree->args, discard_result, out_reg); + j = compile_tree(output, tree->args, discard_result, -1); k = compile_tree(output, &tree->args[1], discard_result, -1); if (discard_result) { if (j < registers) used_regs &= ~(1 << j); if (k < registers) used_regs &= ~(1 << k); break; } - reg = k; + reg = j; if (j >= registers) { + reg = k; if (k >= registers) { - for (i = 0; i < registers; i++) { - if (!(used_regs & (1 << i))) { - reg = i; - used_regs |= (1 << reg); - break; - } - } - if (i == registers) { - fprintf(stderr, "Out of registers?!? fix me\n"); - exit(1); - } + reg = get_free_reg(1); machine_code[mc_ptr++] = 0x48 | (reg > 7 ? 4 : 0); machine_code[mc_ptr++] = 0x8b; machine_code[mc_ptr++] = 0x45 + (reg % 8) * 8; machine_code[mc_ptr++] = -regs[k].rbp; - } else { - //reg = k; + k = reg; } - k = reg; machine_code[mc_ptr++] = 0x48 | (k > 7 ? 4 : 0); machine_code[mc_ptr++] = 0x39; machine_code[mc_ptr++] = 0x45 + (k % 8) * 8; machine_code[mc_ptr++] = -regs[j].rbp; } else if (k >= registers) { - for (i = 0; i < registers; i++) { - if (!(used_regs & (1 << i))) { - reg = i; - used_regs |= (1 << reg); - break; - } - } - if (i == registers) { - fprintf(stderr, "Out of registers?!? fix me\n"); - exit(1); - } - machine_code[mc_ptr++] = 0x48 | (reg > 7 ? 4 : 0); - machine_code[mc_ptr++] = 0x8b; - machine_code[mc_ptr++] = 0x45 + (reg % 8) * 8; + machine_code[mc_ptr++] = 0x48 | (j > 7 ? 4 : 0); + machine_code[mc_ptr++] = 0x3b; + machine_code[mc_ptr++] = 0x45 + (j % 8) * 8; machine_code[mc_ptr++] = -regs[k].rbp; - - k = reg; - machine_code[mc_ptr++] = 0x48 | (j > 7 ? 1 : 0) | (k > 7 ? 4 : 0); - machine_code[mc_ptr++] = 0x39; - machine_code[mc_ptr++] = 0xc0 + (j % 8) + (k % 8) * 8; } else { machine_code[mc_ptr++] = 0x48 | (j > 7 ? 1 : 0) | (k > 7 ? 4 : 0); machine_code[mc_ptr++] = 0x39; machine_code[mc_ptr++] = 0xc0 + (j % 8) + (k % 8) * 8; used_regs &= ~(1 << k); } + if (reg != out_reg && out_reg >= 0) { + used_regs &= ~(1 << reg); + reg = out_reg; + } machine_code[mc_ptr++] = 0x7c; machine_code[mc_ptr++] = 0x05; //Offset // Not less than: @@ -1407,31 +1216,18 @@ int compile_tree(FILE *output, struct expression *tree, int discard_result, int mc_ptr += 8; break; case ret: - reg = compile_tree(output, tree->args, 0, 0); - if (reg) { - if (reg >= registers) { - machine_code[mc_ptr++] = 0x48; - machine_code[mc_ptr++] = 0x8b; - machine_code[mc_ptr++] = 0x45; - machine_code[mc_ptr++] = -regs[reg].rbp; - } else { - machine_code[mc_ptr++] = 0x48 | (reg > 7 ? 1 : 0); - machine_code[mc_ptr++] = 0x8b; - machine_code[mc_ptr++] = 0xC0 + (reg % 8); - } - } + compile_tree(output, tree->args, 0, 0); machine_code[mc_ptr++] = 0xc9; machine_code[mc_ptr++] = 0xc3; return -3; case writestring: - push(syscall_arg[2], &pushed, push_order); - compile_tree(output, tree->args, 0, syscall_arg[2]); - - push(syscall_arg[1], &pushed, push_order); + push(0, &pushed, push_order, "writestring (rax)"); + push(syscall_arg[0], &pushed, push_order, "writestring (syscall_arg 0)"); + push(syscall_arg[1], &pushed, push_order, "writestring (syscall_arg 1)"); + push(syscall_arg[2], &pushed, push_order, "writestring (syscall_arg 2)"); compile_tree(output, &tree->args[1], 0, syscall_arg[1]); + compile_tree(output, tree->args, 0, syscall_arg[2]); - push(syscall_arg[0], &pushed, push_order); - push(0, &pushed, push_order); machine_code[mc_ptr++] = 0x48; machine_code[mc_ptr++] = 0xb8; *(int64_t *) &machine_code[mc_ptr] = 0x01; @@ -1440,124 +1236,18 @@ int compile_tree(FILE *output, struct expression *tree, int discard_result, int machine_code[mc_ptr++] = 0x48 | (syscall_arg[0] > 7 ? 1 : 0); machine_code[mc_ptr++] = 0x89; machine_code[mc_ptr++] = 0xc0 + (syscall_arg[0] % 8); - /* - if (used_regs & (1 << 0)) { - machine_code[mc_ptr++] = 0x48; - machine_code[mc_ptr++] = 0x50; - next_rbp += 8; - pushed |= (1 << 0); - } - for (int i = 0; i <= 2; i++) { - if (used_regs & (1 << arg_order[i])) { - machine_code[mc_ptr++] = 0x48 | (arg_order[i] > 7 ? 1 : 0); - machine_code[mc_ptr++] = 0x50 + (arg_order[i] % 8); - next_rbp += 8; - pushed |= (1 << arg_order[i]); - } - } - */ - - //used_regs |= (1 << 0) | (1 << syscall_arg[0]); machine_code[mc_ptr++] = 0x0F; machine_code[mc_ptr++] = 0x05; reg = 0; - - // Reset saved variables - /* - for (i = 2; i >= 0; i--) { - if (pushed & (1 << arg_order[i])) { - machine_code[mc_ptr++] = 0x48 | (arg_order[i] > 7 ? 1 : 0); - machine_code[mc_ptr++] = 0x58 + (arg_order[i] % 8); - next_rbp -= 8; - pushed &= ~(1 << arg_order[i]); - } else { - used_regs &= ~(1 << arg_order[i]); - } - } - if (pushed & (1 << 0)) { - if (!discard_result) { - reg = out_reg; - if (reg < 0 || reg >= registers) { - for (i = 0; i < registers; i++) { - if (!(used_regs & (1 << i))) { - reg = i; - used_regs |= (1 << reg); - break; - } - } - if (i == registers) { - fprintf(stderr, "Out of registers?!? fix me\n"); - exit(1); - } - } - machine_code[mc_ptr++] = 0x48 | (reg > 7 ? 1 : 0); - machine_code[mc_ptr++] = 0x8b; - machine_code[mc_ptr++] = 0xc0 + (reg % 8) * 8; - } - - machine_code[mc_ptr++] = 0x48; - machine_code[mc_ptr++] = 0x58; - next_rbp -= 8; - pushed &= ~(1 << 0); - } else { - if (discard_result) used_regs &= ~(1 << 0); - } - */ break; case printchar: - push(arg_order[1], &pushed, push_order); - j = compile_tree(output, tree->args, 0, syscall_arg[1]); - /* - if (used_regs & (1 << arg_order[1]) && j != arg_order[1]) { - machine_code[mc_ptr++] = 0x48 | (arg_order[1] > 7 ? 1 : 0); - machine_code[mc_ptr++] = 0x50 + (arg_order[1] % 8); - next_rbp += 8; - pushed |= (1 << arg_order[1]); - } - if (j >= registers) { - k = 0; - machine_code[mc_ptr++] = 0x48 | (arg_order[1] > 7 ? 1 : 0); - machine_code[mc_ptr++] = 0x8d; - machine_code[mc_ptr++] = 0x45 + (arg_order[1] % 8) * 8; - machine_code[mc_ptr++] = -regs[j].rbp; - } else { - k = 1; - - // Allocate extra space on the stack for the character - // Because of scratch space, this might be unnecessary - machine_code[mc_ptr++] = 0x48; - machine_code[mc_ptr++] = 0x81; - machine_code[mc_ptr++] = 0xEC; - *(int *) &machine_code[mc_ptr] = 0x08; - mc_ptr += 4; + push(0, &pushed, push_order, "printchar (rax)"); + push(syscall_arg[0], &pushed, push_order, "printchar (syscall_arg 0)"); + push(syscall_arg[1], &pushed, push_order, "printchar (syscall_arg 1)"); + push(syscall_arg[2], &pushed, push_order, "printchar (syscall_arg 2)"); - machine_code[mc_ptr++] = 0x48 | (j > 7 ? 4 : 0); - machine_code[mc_ptr++] = 0x89; - machine_code[mc_ptr++] = 0x45 + (j % 8) * 8; - machine_code[mc_ptr++] = -next_rbp; - - machine_code[mc_ptr++] = 0x48 | (arg_order[1] > 7 ? 1 : 0); - machine_code[mc_ptr++] = 0x8d; - machine_code[mc_ptr++] = 0x45 + (arg_order[1] % 8) * 8; - machine_code[mc_ptr++] = -next_rbp; - used_regs &= ~(1 << j); - } - */ - push(0, &pushed, push_order); - push(syscall_arg[0], &pushed, push_order); - push(syscall_arg[2], &pushed, push_order); - - machine_code[mc_ptr++] = 0x48; - machine_code[mc_ptr++] = 0xb8; - *(int64_t *) &machine_code[mc_ptr] = 0x01; - mc_ptr += 8; - machine_code[mc_ptr++] = 0x48 | (arg_order[0] > 7 ? 1 : 0); - machine_code[mc_ptr++] = 0x89; - machine_code[mc_ptr++] = 0xc0 + (arg_order[0] % 8); - machine_code[mc_ptr++] = 0x48 | (arg_order[2] > 7 ? 1 : 0); - machine_code[mc_ptr++] = 0x89; - machine_code[mc_ptr++] = 0xc0 + (arg_order[2] % 8); + j = compile_tree(output, tree->args, 0, syscall_arg[1]); // Allocate extra space on the stack for the character // Because of scratch space, this might be unnecessary @@ -1575,8 +1265,18 @@ int compile_tree(FILE *output, struct expression *tree, int discard_result, int machine_code[mc_ptr++] = 0x8d; machine_code[mc_ptr++] = 0x45 + (j % 8) * 8; machine_code[mc_ptr++] = -next_rbp; - used_regs &= ~(1 << j); - + + machine_code[mc_ptr++] = 0x48; + machine_code[mc_ptr++] = 0xb8; + *(int64_t *) &machine_code[mc_ptr] = 0x01; + mc_ptr += 8; + machine_code[mc_ptr++] = 0x48 | (arg_order[0] > 7 ? 1 : 0); + machine_code[mc_ptr++] = 0x89; + machine_code[mc_ptr++] = 0xc0 + (arg_order[0] % 8); + machine_code[mc_ptr++] = 0x48 | (arg_order[2] > 7 ? 1 : 0); + machine_code[mc_ptr++] = 0x89; + machine_code[mc_ptr++] = 0xc0 + (arg_order[2] % 8); + machine_code[mc_ptr++] = 0x0f; machine_code[mc_ptr++] = 0x05; @@ -1584,57 +1284,6 @@ int compile_tree(FILE *output, struct expression *tree, int discard_result, int machine_code[mc_ptr++] = 0x83; machine_code[mc_ptr++] = 0xc4; machine_code[mc_ptr++] = 0x08; - // Reset saved variables - /* - if (pushed & (1 << arg_order[1])) { - machine_code[mc_ptr++] = 0x48 | (arg_order[1] > 7 ? 1 : 0); - machine_code[mc_ptr++] = 0x58 + (arg_order[1] % 8); - next_rbp -= 8; - pushed &= ~(1 << arg_order[1]); - } else { - used_regs &= ~(1 << arg_order[1]); - } - if (pushed & (1 << arg_order[2])) { - machine_code[mc_ptr++] = 0x48 | (arg_order[2] > 7 ? 1 : 0); - machine_code[mc_ptr++] = 0x58 + (arg_order[2] % 8); - next_rbp -= 8; - pushed &= ~(1 << arg_order[2]); - } else { - used_regs &= ~(1 << arg_order[2]); - } - if (pushed & (1 << arg_order[0])) { - machine_code[mc_ptr++] = 0x48 | (arg_order[0] > 7 ? 1 : 0); - machine_code[mc_ptr++] = 0x58 + (arg_order[0] % 8); - next_rbp -= 8; - pushed &= ~(1 << arg_order[0]); - } else { - used_regs &= ~(1 << arg_order[0]); - } - if (pushed & (1 << 0)) { - if (!discard_result) { - for (i = 0; i < registers; i++) { - if (!(used_regs & (1 << i))) { - reg = i; - used_regs |= (1 << reg); - break; - } - } - if (i == registers) { - fprintf(stderr, "Out of registers?!? fix me\n"); - exit(1); - } - machine_code[mc_ptr++] = 0x48 | (reg > 7 ? 1 : 0); - machine_code[mc_ptr++] = 0x8b; - machine_code[mc_ptr++] = 0xc0 + (reg % 8) * 8; - } - - machine_code[mc_ptr++] = 0x48; - machine_code[mc_ptr++] = 0x58; - next_rbp -= 8; - pushed &= ~(1 << 0); - } - if (discard_result) used_regs &= ~(1 << 0); - */ reg = 0; break; case exit_p: @@ -1650,10 +1299,19 @@ int compile_tree(FILE *output, struct expression *tree, int discard_result, int if (!discard_result) { if (reg < 0) { fprintf(stderr, "No value in <reg>\n"); + fprintf(stderr, "type: %s\n", exp_str[tree->type]); exit(1); } - if (out_reg < 0) return reg; - if (reg == out_reg) goto end; + if (out_reg < 0 && !(pushed & (1 << reg))) { + out_reg = reg; + goto pop_used; + } else if (out_reg < 0) { + k = used_regs; + used_regs |= pushed; + out_reg = get_free_reg(1); + used_regs = k; + } + if (reg == out_reg) goto pop_used; if (reg >= registers && out_reg >= registers) { j = get_free_reg(0); machine_code[mc_ptr++] = 0x48 | (j > 7 ? 4 : 0); @@ -1665,27 +1323,37 @@ int compile_tree(FILE *output, struct expression *tree, int discard_result, int machine_code[mc_ptr++] = 0x89; machine_code[mc_ptr++] = 0x45 + (reg % 8) * 8; machine_code[mc_ptr++] = -regs[out_reg].rbp; + regs[out_reg].rev++; } else if (reg >= registers && out_reg < registers) { machine_code[mc_ptr++] = 0x48 | (out_reg > 7 ? 4 : 0); machine_code[mc_ptr++] = 0x8b; machine_code[mc_ptr++] = 0x45 + (out_reg % 8) * 8; machine_code[mc_ptr++] = -regs[reg].rbp; + reg_hist[out_reg].type = 1; + reg_hist[out_reg].reg = reg; + reg_hist[out_reg].rev = ++regs[reg].rev; } else { machine_code[mc_ptr++] = 0x48 | (reg > 7 ? 4 : 0); machine_code[mc_ptr++] = 0x89; if (out_reg >= registers) { machine_code[mc_ptr++] = 0x45 + (reg % 8) * 8; machine_code[mc_ptr++] = -regs[out_reg].rbp; + reg_hist[reg].type |= 1; + reg_hist[reg].reg = reg; + reg_hist[reg].rev = ++regs[out_reg].rev; } else { machine_code[mc_ptr-2] |= (out_reg > 7 ? 1 : 0); machine_code[mc_ptr++] = 0xc0 + (out_reg % 8) + (reg % 8) * 8; + memcpy(&reg_hist[out_reg], &reg_hist[reg], sizeof(struct reg_history)); } used_regs &= ~(1 << reg); } } +pop_used: if (pushed) - for (i = 0; pushed && i < registers; i++) - pop(push_order[i], &pushed); + for (i = registers-1; i >= 0; i--) { + if (push_order[i] >= 0) pop(push_order[i], &pushed); + } end: return out_reg; } @@ -1750,9 +1418,12 @@ char padding[4096] = { 0 }; int main(int argc, char **argv) { - int i, outfd, use_rodata = 0; + int i, outfd, use_rodata = 1; - if (argc < 3) { + if (argc == 1) { + fname = "stdin"; + outfd = 1; + } else if (argc < 3) { fprintf(stderr, "Too few arguments\nUsage: %s <in-file> <out-file>\n", *argv); exit(1); } else { @@ -1767,7 +1438,7 @@ int main(int argc, char **argv) yyparse(); - stringify(final, -3, 0, NULL, 0); + //stringify(final, -3, 0, NULL, 0); if (use_rodata) elf_hdr.phcount = 2; else elf_hdr.phcount = 1;