compiler

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

commit c67390f2b74b07d576675fd6165e2132af0b79c4
parent 992236e47e3d81d906a71fae6d05cce2dc2ef08f
Author: William Djupström <william@deepztream.com>
Date:   Fri,  1 Mar 2019 00:46:58 +0100

More of better and some of worse

Diffstat:
Mexamples/example.6 | 2+-
Aexamples/example.7 | 15+++++++++++++++
Mparse.y | 860+++++++++++++++++++++++++++++++++++++++++++++++--------------------------------
3 files changed, 533 insertions(+), 344 deletions(-)

diff --git a/examples/example.6 b/examples/example.6 @@ -1,7 +1,7 @@ _start() { decl c = 64; while (c < 64+26) - putc(c = c + 1); + putc(c = 1 + c); putc(10); exit(0); } diff --git a/examples/example.7 b/examples/example.7 @@ -0,0 +1,15 @@ +strlen(s) { + decl i = 0; + while (s[i] & 255) + i = i + 1; + return i; +} + +print(s) { + write(strlen(s), s); +} + +_start() { + print("Hello There!\n"); + exit(0); +} diff --git a/parse.y b/parse.y @@ -168,6 +168,69 @@ struct expression *copy(struct expression *e) memcpy(r, e, sizeof(struct expression)); return r; } + +char *expand_str(char *str) { + int i, j = 0, l = strlen(str); + for (i = 0; i < l; i++) { + if (str[i] == '\\') { + switch (str[i+1]) { + case 'n': + j = 1; + str[i+j] = '\n'; + break; + case 'r': + j = 1; + str[i+j] = '\r'; + break; + case 't': + j = 1; + str[i+j] = '\t'; + break; + case '\\': + i++; + default: + j = 0; + break; + } + l -= j; + if (j) memmove(&str[i], &str[i+j], l - i + 1); + } + } + return str; +} + +char *escape_str(char *str) { + int i, j, l = strlen(str); + char *r; + for (i = 0, j = 1; i < l; i++) + if (str[i] == '\\' || str[i] == '\n' || str[i] == '\r' || str[i] == '\t') + j++; + r = calloc(l + j, 1); + for (i = 0, j = 0; i < l; i++, j++) { + switch (str[i]) { + case '\n': + r[j++] = '\\'; + r[j] = 'n'; + break; + case '\r': + r[j++] = '\\'; + r[j] = 'r'; + break; + case '\t': + r[j++] = '\\'; + r[j] = 't'; + break; + case '\\': + r[j++] = '\\'; + r[j] = '\\'; + break; + default: + r[j] = str[i]; + break; + } + } + return r; +} %} %union {struct expression *expr; char *str; int64_t i;} @@ -237,7 +300,7 @@ if_stmt: "if" '(' expression ')' statement {$$ = e(ifnz, $3, $5, 0);} ; comp_stmt: '{' {$$ = e(comma, NULL, NULL, 1);} -| comp_stmt statement {$$ = move($1); append($$, $2);}/*$$ = e(comma, $1, $2, 0);}*/ +| comp_stmt statement {$$ = move($1); append($$, $2);} ; var_defs: "decl" var_def {$$ = e(comma, $2, NULL, 0);} @@ -261,8 +324,8 @@ c_expr: expression {$$ = move($1);} expression: IDENTIFIER {$$ = copy(find_idnt($1));} | NUMBER {$$ = e(number, (void *)$1, NULL, 1);} -| str {$$ = e(string, (void *)$1, NULL, 0);} -| expression '[' expression ']' {printf("uh-oh\n");$$ = NULL;} +| str {$$ = e(string, (void *)expand_str($1), NULL, 0);} +| expression '[' expression ']' {$$ = e(deref, e(add, $1, $3, 0), NULL, 0);} | '(' exprs ')' {$$ = move($2);} | expression '(' ')' {$$ = e(fcall, $1, NULL, 0);} | expression '(' c_expr ')' {$$ = e(fcall, $1, $3, 0);} @@ -273,7 +336,7 @@ expression: IDENTIFIER {$$ = copy(find_idnt($1));} | expression '*' expression {$$ = e(mul, $1, $3, 0);} | expression '/' expression {$$ = e(divide, $1, $3, 0);} | expression '%' expression {$$ = e(mod, $1, $3, 0);} -| expression '&' expression {printf("uh-oh\n");$$ = NULL;} +| expression '&' expression {$$ = e(b_and, $1, $3, 0);} | expression '|' expression {printf("uh-oh\n");$$ = NULL;} | expression '^' expression {printf("uh-oh\n");$$ = NULL;} | expression "<<" expression {$$ = e(shift_l, $1, $3, 0);} @@ -289,12 +352,12 @@ expression: IDENTIFIER {$$ = copy(find_idnt($1));} | 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(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);} | expression '>' expression {$$ = e(l_lt, $3, $1, 0);} -| expression "<=" expression {printf("uh-oh\n");$$ = NULL;} -| expression ">=" expression {printf("uh-oh\n");$$ = NULL;} +| expression "<=" expression {$$ = e(l_not, e(l_lt, $3, $1, 0), NULL, 0);} +| expression ">=" expression {$$ = e(l_not, e(l_lt, $1, $3, 0), NULL, 0);} | '!' expression {$$ = e(l_not, $2, NULL, 0);} | '~' expression {printf("uh-oh\n");$$ = NULL;} | '*' expression %prec REF {$$ = e(deref, $2, NULL, 0);} @@ -313,6 +376,7 @@ str: str STRING {$$ = calloc(strlen($1) + strl %% #include <stdio.h> +#include <fcntl.h> char *exp_str[] = { #define f(e) #e, @@ -323,12 +387,15 @@ EXPRESSION_TYPES(f) void stringify(struct expression *e, int p_indent, int last, char *name, uint64_t idmap) { int i, indent = p_indent + 3; + char *str; if (last) idmap |= (1 << p_indent/3); for (i = 0; i < p_indent; i+=3) fprintf(stderr, "%s ", (idmap & (1 << (i/3))) ? " " : "│"); if (p_indent >= 0) fprintf(stderr, "%s━ ", last ? "┕": "┝"); switch(e->type) { case string: - fprintf(stderr, "%s: \"%s\"\n", name ? name : "string", e->str); + str = escape_str(e->str); + fprintf(stderr, "%s: \"%s\"\n", name ? name : "string", str); + free(str); break; case idnt: fprintf(stderr, "%s: %s\n", name ? name : "ident", e->str); @@ -366,13 +433,62 @@ int entry_addr = -1; long start_addr, rodata_addr; int func_declares; -int arg_order[16] = {7, 6, 2, 1, 8, 9, 0, 10, 11, 12, 13, 14, 15, 3, 5}; -int caller_save = 0b0000000011001111; +int arg_order[16] = {7, 6, 2, 1, 8, 9, 1, 0, 11, 12, 13, 14, 15, 3, 5}; +int syscall_arg[16] = {7, 6, 2, 10, 8, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1}; +int caller_save = 0b0000111111001111; + +int get_free_reg(int mark_used) +{ + int i; + for (i = 0; i < registers; i++) { + if (!(used_regs & (1 << i))) { + if (mark_used) used_regs |= (1 << i); + return i; + break; + } + } + fprintf(stderr, "Out of registers?!? fix me\n"); + exit(1); +} + +void push(int reg, int *pushed, char *order) { + int i; + if (used_regs & (1 << reg)) { + machine_code[mc_ptr++] = 0x48 | (reg > 7 ? 1 : 0); + machine_code[mc_ptr++] = 0x50 + (reg % 8); + for (i = 0; i < registers; i++) { + if (order[i] == -1) { + order[i] = reg; + used_regs &= ~(1 << reg); + *pushed |= (1 << reg); + next_rbp += 8; + return; + } + } + fprintf(stderr, "Unable to push any more registers\n"); + exit(1); + } +} + +void pop(int reg, int *pushed) { + if (!(*pushed & (1 << reg))) { + fprintf(stderr, "Trying to pop a register which hasn't been pushed\n"); + exit(1); + } + machine_code[mc_ptr++] = 0x48 | (reg > 7 ? 1 : 0); + machine_code[mc_ptr++] = 0x58 + (reg % 8); + *pushed &= ~(1 << reg); + used_regs |= (1 << reg); + next_rbp -= 8; +} int compile_tree(FILE *output, struct expression *tree, int discard_result, int out_reg) { int i, j, k, l, reg = -1; - char out[1024]; + char push_order[16] = { -1, -1, -1, -1, + -1, -1, -1, -1, + -1, -1, -1, -1, + -1, -1, -1, -1 }; int pushed = 0; struct expression *tmp; fprintf(stderr, "Type: %s\n", exp_str[tree->type]); @@ -444,64 +560,38 @@ int compile_tree(FILE *output, struct expression *tree, int discard_result, int } } } - compile_tree(output, &tree->args[tree->args_count-1], 1, 0); - if (strcmp(tree->args->str, "_start")) { + j = compile_tree(output, &tree->args[tree->args_count-1], 1, 0); + if (strcmp(tree->args->str, "_start") && j != -3 && j != -2) { machine_code[mc_ptr++] = 0xc9; machine_code[mc_ptr++] = 0xc3; } break; case comma: for (i = 0; i < tree->args_count; i++) { - j = compile_tree(output, &tree->args[i], (i+1 == tree->args_count ? discard_result : 1), out_reg); + j = compile_tree(output, &tree->args[i], (i+1 == tree->args_count ? discard_result : 1), (i+1 == tree->args_count ? out_reg : -1)); + if (j == -2 || j == -3) return j; } if (!discard_result) reg = j; break; case fcall: for (i = 0; i < registers; i++) { - if ((1 << i) & caller_save && (1 << i) & used_regs) { + 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); + */ } } if (tree->args_count == 2) { if (tree->args[1].type == comma) { for (i = 0; i < tree->args[1].args_count; i++) { j = compile_tree(output, &tree->args[1].args[i], 0, arg_order[i]); - if (j != arg_order[i]) { - if (j >= registers) { - machine_code[mc_ptr++] = 0x48 | (arg_order[i] > 7 ? 1 : 0); - machine_code[mc_ptr++] = 0x8b; - machine_code[mc_ptr++] = 0x45 + (arg_order[i] % 8) * 8; - machine_code[mc_ptr++] = -regs[j].rbp; - } else { - machine_code[mc_ptr++] = 0x48 | (j > 7 ? 4 : 0) | (arg_order[i] > 7 ? 1 : 0); - machine_code[mc_ptr++] = 0x89; - machine_code[mc_ptr++] = 0xC0 + (j % 8) * 8 + arg_order[i]; - used_regs &= ~(1 << j); - } - } - used_regs |= (1 << arg_order[i]); } - k = i; } else { j = compile_tree(output, &tree->args[1], 0, arg_order[0]); - if (j != arg_order[0]) { - used_regs |= (1 << arg_order[0]); - if (j >= registers) { - machine_code[mc_ptr++] = 0x48 | (arg_order[0] > 7 ? 1 : 0); - machine_code[mc_ptr++] = 0x8b; - machine_code[mc_ptr++] = 0x45 + (arg_order[0] % 8) * 8; - machine_code[mc_ptr++] = -regs[j].rbp; - } else { - machine_code[mc_ptr++] = 0x48 | (j > 7 ? 4 : 0) | (arg_order[0] > 7 ? 1 : 0); - machine_code[mc_ptr++] = 0x89; - machine_code[mc_ptr++] = 0xC0 + (j % 8) * 8 + arg_order[0]; - used_regs &= ~(1 << j); - } - } - k = 1; } } if (!(pushed & 1)) { @@ -512,22 +602,26 @@ int compile_tree(FILE *output, struct expression *tree, int discard_result, int *(int32_t *) &machine_code[mc_ptr] = j - start_addr - mc_ptr - 4; mc_ptr += 4; - if (!discard_result) reg = 0; - if (pushed & 1 && !discard_result) { - for (i = 0; i < registers; i++) { - if (!(used_regs & (1 << i))) { - reg = i; - used_regs |= (1 << reg); - break; + 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); } - 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++] = 0x89; - machine_code[mc_ptr++] = 0xC0 + (reg % 8); } for (i = registers - 1; i >= 0; i--) { if (pushed & (1 << i)) { @@ -550,19 +644,9 @@ 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); } - if (tree->args->type == idnt) { + 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; @@ -851,6 +935,43 @@ int compile_tree(FILE *output, struct expression *tree, int discard_result, int if (k < registers) used_regs &= ~(1 << k); break; + case b_and: + j = compile_tree(output, tree->args, 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); + break; + } + 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); + } + 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++] = 0x23; + if (tree->args[1].type == idnt) { + machine_code[mc_ptr++] = 0x45 + (reg % 8) * 8; + machine_code[mc_ptr++] = -regs[k].rbp; + } else { + machine_code[mc_ptr-2] |= k > 7 ? 1 : 0; + machine_code[mc_ptr++] = 0xC0 + (reg % 8) * 8 + k; + } + if (k < registers) used_regs &= ~(1 << k); + break; case decl: reg = next_reg++; regs[reg].type = 1; @@ -860,41 +981,43 @@ int compile_tree(FILE *output, struct expression *tree, int discard_result, int break; case set: reg = compile_tree(output, tree->args, 0, -1); - j = compile_tree(output, &tree->args[1], 0, out_reg); + 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 (reg >= registers) { - 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); + if (j >= registers) { + for (i = 0; i < registers; i++) { + if (!(used_regs & (1 << i))) { + k = i; + break; } - 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; - - 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 { - 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++] = -regs[reg].rbp; } + 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) { @@ -923,17 +1046,44 @@ int compile_tree(FILE *output, struct expression *tree, int discard_result, int machine_code[mc_ptr++] = -regs[j].rbp; break; case deref: + j = compile_tree(output, tree->args, discard_result, out_reg); + if (discard_result) { + if (used_regs & (1 << j)) used_regs &= ~(1 << j); + break; + } + 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); + 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 ? 5 : 0); + machine_code[mc_ptr++] = 0x8b; + machine_code[mc_ptr++] = 0x00 + (reg % 8) + (reg % 8) * 8; break; case idnt: if (discard_result) break; - for (i = registers; i < 1024; i++) { - if (regs[i].type != 1) continue; - if (!strcmp(regs[i].var, tree->str)) break; + for (reg = registers; reg < 1024; reg++) { + if (regs[reg].type != 1) continue; + if (!strcmp(regs[reg].var, tree->str)) break; } - if (i == 1024) { + if (reg == 1024) { 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); @@ -944,6 +1094,7 @@ int compile_tree(FILE *output, struct expression *tree, int discard_result, int } else { reg = i; } + */ break; case number: if (discard_result) break; @@ -1003,7 +1154,6 @@ int compile_tree(FILE *output, struct expression *tree, int discard_result, int case loop: machine_code[mc_ptr++] = 0xe9; k = mc_ptr; - //*(int32_t *) &machine_code[mc_ptr] = 0x00; mc_ptr += 4; compile_tree(output, &tree->args[1], 1, -1); *(int32_t *) &machine_code[k] = mc_ptr - k - 4; @@ -1041,7 +1191,6 @@ int compile_tree(FILE *output, struct expression *tree, int discard_result, int machine_code[mc_ptr++] = 0x0f; machine_code[mc_ptr++] = 0x84; k = mc_ptr; - //*(int32_t *) &machine_code[mc_ptr] = 0x00; //Offset mc_ptr += 4; // True used_regs = (1 << 5) | (1 << 4); @@ -1103,6 +1252,80 @@ int compile_tree(FILE *output, struct expression *tree, int discard_result, int *(int64_t *) &machine_code[mc_ptr] = 1; mc_ptr += 8; break; + case l_eq: + j = compile_tree(output, tree->args, discard_result, -1); + k = compile_tree(output, &tree->args[1], discard_result, out_reg); + if (discard_result) { + if (j < registers) used_regs &= ~(1 << j); + if (k < registers) used_regs &= ~(1 << k); + break; + } + reg = k; + + 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); + } + 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++] = 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++] = -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); + } + machine_code[mc_ptr++] = 0x74; + machine_code[mc_ptr++] = 0x05; //Offset + // Not less than: + machine_code[mc_ptr++] = 0x48 | (reg > 7 ? 5 : 0); + machine_code[mc_ptr++] = 0x33; + machine_code[mc_ptr++] = 0xc0 + (reg % 8) + (reg % 8) * 8; + machine_code[mc_ptr++] = 0xeb; + machine_code[mc_ptr++] = 0x0a; + // Less than: + machine_code[mc_ptr++] = 0x48 + (reg > 7 ? 1 : 0); + machine_code[mc_ptr++] = 0xb8 + (reg % 8); + *(int64_t *) &machine_code[mc_ptr] = 1; + mc_ptr += 8; + break; case l_lt: j = compile_tree(output, tree->args, discard_result, out_reg); k = compile_tree(output, &tree->args[1], discard_result, -1); @@ -1195,110 +1418,74 @@ int compile_tree(FILE *output, struct expression *tree, int discard_result, int } machine_code[mc_ptr++] = 0xc9; machine_code[mc_ptr++] = 0xc3; - break; + return -3; case writestring: - if (used_regs & (1 << 0)) { - machine_code[mc_ptr++] = 0x48; - machine_code[mc_ptr++] = 0x50; - next_rbp += 8; - pushed |= (1 << 0); - } - if (used_regs & (1 << arg_order[0])) { - machine_code[mc_ptr++] = 0x48 | (arg_order[0] > 7 ? 1 : 0); - machine_code[mc_ptr++] = 0x50 + (arg_order[0] % 8); - next_rbp += 8; - pushed |= (1 << arg_order[0]); - } - if (used_regs & (1 << 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 (used_regs & (1 << arg_order[2])) { - machine_code[mc_ptr++] = 0x48 | (arg_order[2] > 7 ? 1 : 0); - machine_code[mc_ptr++] = 0x50 + (arg_order[2] % 8); - next_rbp += 8; - pushed |= (1 << arg_order[2]); - } + push(syscall_arg[2], &pushed, push_order); + compile_tree(output, tree->args, 0, syscall_arg[2]); + + push(syscall_arg[1], &pushed, push_order); + compile_tree(output, &tree->args[1], 0, syscall_arg[1]); + + 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; 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); - */ - used_regs |= (1 << 0) | (1 << arg_order[0]); - - compile_tree(output, tree->args, 0, arg_order[2]); - j = compile_tree(output, &tree->args[1], 0, arg_order[1]); + 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 << 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); + if (used_regs & (1 << 0)) { + machine_code[mc_ptr++] = 0x48; + machine_code[mc_ptr++] = 0x50; next_rbp += 8; - pushed |= (1 << arg_order[1]); + pushed |= (1 << 0); } - 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; - 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); + 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 - 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]); - } - 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]); - } - 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]); + /* + 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) { - for (i = 0; i < registers; i++) { - if (!(used_regs & (1 << i))) { - reg = i; - used_regs |= (1 << reg); - break; + 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); } - } - 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; @@ -1309,41 +1496,15 @@ int compile_tree(FILE *output, struct expression *tree, int discard_result, int machine_code[mc_ptr++] = 0x58; next_rbp -= 8; pushed &= ~(1 << 0); + } else { + if (discard_result) used_regs &= ~(1 << 0); } + */ break; case printchar: - if (used_regs & (1 << 0)) { - machine_code[mc_ptr++] = 0x48; - machine_code[mc_ptr++] = 0x50; - next_rbp += 8; - pushed |= (1 << 0); - } - if (used_regs & (1 << arg_order[0])) { - machine_code[mc_ptr++] = 0x48 | (arg_order[0] > 7 ? 1 : 0); - machine_code[mc_ptr++] = 0x50 + (arg_order[0] % 8); - next_rbp += 8; - pushed |= (1 << arg_order[0]); - } - if (used_regs & (1 << arg_order[2])) { - machine_code[mc_ptr++] = 0x48 | (arg_order[2] > 7 ? 1 : 0); - machine_code[mc_ptr++] = 0x50 + (arg_order[2] % 8); - next_rbp += 8; - pushed |= (1 << arg_order[2]); - } - 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); - - used_regs |= (1 << 0) | (1 << arg_order[0]) | (1 << arg_order[2]); - - j = compile_tree(output, tree->args, 0, -1); + 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); @@ -1361,13 +1522,11 @@ int compile_tree(FILE *output, struct expression *tree, int discard_result, int // 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; - */ machine_code[mc_ptr++] = 0x48 | (j > 7 ? 4 : 0); machine_code[mc_ptr++] = 0x89; @@ -1380,27 +1539,72 @@ int compile_tree(FILE *output, struct expression *tree, int discard_result, int machine_code[mc_ptr++] = -next_rbp; used_regs &= ~(1 << j); } - machine_code[mc_ptr++] = 0x0F; + */ + 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); + + // 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++] = 0x83; + machine_code[mc_ptr++] = 0xec; + machine_code[mc_ptr++] = 0x08; + + 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 | (j > 7 ? 1 : 0); + 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++] = 0x0f; machine_code[mc_ptr++] = 0x05; + machine_code[mc_ptr++] = 0x48; + 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) { @@ -1425,18 +1629,61 @@ int compile_tree(FILE *output, struct expression *tree, int discard_result, int next_rbp -= 8; pushed &= ~(1 << 0); } + if (discard_result) used_regs &= ~(1 << 0); + */ + reg = 0; break; case exit_p: - j = compile_tree(output, tree->args, 0, arg_order[0]); + j = compile_tree(output, tree->args, 0, syscall_arg[0]); machine_code[mc_ptr++] = 0x48; machine_code[mc_ptr++] = 0xb8; *(int64_t *) &machine_code[mc_ptr] = 0x3c; mc_ptr += 8; machine_code[mc_ptr++] = 0x0F; machine_code[mc_ptr++] = 0x05; - break; + return -2; } - return reg; + if (!discard_result) { + if (reg < 0) { + fprintf(stderr, "No value in <reg>\n"); + exit(1); + } + if (out_reg < 0) return reg; + if (reg == out_reg) goto end; + if (reg >= registers && out_reg >= registers) { + j = get_free_reg(0); + machine_code[mc_ptr++] = 0x48 | (j > 7 ? 4 : 0); + machine_code[mc_ptr++] = 0x8b; + machine_code[mc_ptr++] = 0x45 + (j % 8) * 8; + machine_code[mc_ptr++] = -regs[reg].rbp; + reg = j; + machine_code[mc_ptr++] = 0x48 | (reg > 7 ? 4 : 0); + machine_code[mc_ptr++] = 0x89; + machine_code[mc_ptr++] = 0x45 + (reg % 8) * 8; + machine_code[mc_ptr++] = -regs[out_reg].rbp; + } 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; + } 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; + } else { + machine_code[mc_ptr-2] |= (out_reg > 7 ? 1 : 0); + machine_code[mc_ptr++] = 0xc0 + (out_reg % 8) + (reg % 8) * 8; + } + used_regs &= ~(1 << reg); + } + } + if (pushed) + for (i = 0; pushed && i < registers; i++) + pop(push_order[i], &pushed); +end: + return out_reg; } struct elf_hdr { @@ -1492,80 +1739,31 @@ struct prg_hdr load_rodata = { 1, 4, 0, 0, 0, 0, 0, 1 }; struct sec_hdr null_section = { 0 }; struct sec_hdr text_section = { 1, 1, 6, 0, 0, 0, 0, 0, 1, 0 }; struct sec_hdr rodata_section = { 7, 1, 2, 0, 0, 0, 0, 0, 1, 0 }; -struct sec_hdr strtab_section = { 15, 3, 0x20, 0, 0, 0, 0, 0, 1, 0 }; +struct sec_hdr strtab_section = { 15, 3, 0, 0, 0, 0, 0, 0, 1, 0 }; char strtab[] = "\0.text\0.rodata\0.strtab"; +char padding[4096] = { 0 }; + int main(int argc, char **argv) { - int i; - char hdr1[] = { // ELF Header - 0x7f, 'E' , 'L' , 'F' , 0x02, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x02, 0x00, 0x3E, 0x00, 0x01, 0x00, 0x00, 0x00, 0xb0, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x38, 0x00, 0x02, 0x00, 0x40, 0x00, 0x03, 0x00, 0x02, 0x00, - // LOAD TEXT - 0x01, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xb0, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, - // LOAD RODATA - 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xb0, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - /* - // GNU_STACK - 0x51, 0xe5, 0x74, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - */ - }; - char phdr[] = { // Program Headers - // LOAD TEXT - 0x01, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xb0, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, - // LOAD RODATA - 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xb0, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - }; - char hdr2[] = { // Section Header - // NULL shdr - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - // TEXT shdr - 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xb0, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x5f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - /* - // RODATA shdr - 0x0f, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x5f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - */ - // STRTAB shdr - 0x07, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xcf, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - }; - if (argc == 1) fname = "stdin"; - else { + int i, outfd; + + if (argc < 3) { + fprintf(stderr, "Too few arguments\nUsage: %s <in-file> <out-file>\n", *argv); + exit(1); + } else { fname = argv[1]; yyin = fopen(fname, "r"); + outfd = open(argv[2], O_TRUNC | O_WRONLY | O_CREAT, (S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) & 0x1ff); + if (outfd == -1) { + fprintf(stderr, "Unable to open out-file\n"); + exit(1); + } } + yyparse(); - breakpoint(); + stringify(final, -3, 0, NULL, 0); - //start_addr = 0x400000 + sizeof(hdr1); elf_hdr.phcount = 2; elf_hdr.shcount = 4; @@ -1573,8 +1771,8 @@ int main(int argc, char **argv) int hdr1_size = sizeof(elf_hdr) + sizeof(struct prg_hdr) * elf_hdr.phcount; start_addr = 0x400000 + hdr1_size; - rodata_addr = 0x600000 + sizeof(hdr1) + 0xbb; - fprintf(stderr, "final args: %i\n", final->args_count); + rodata_addr = 0x600000; + for (i = 0; i < final->args_count; i++) { compile_tree(stdout, &final->args[i], 1, -1); } @@ -1582,73 +1780,49 @@ int main(int argc, char **argv) fprintf(stderr, "No _start symbol found!\n"); exit(1); } - *(int64_t *) &hdr1[0x18] = start_addr + entry_addr; - *(int64_t *) &hdr1[0x28] = sizeof(hdr1) + mc_ptr + rd_ptr; + + int rodata_offset = sizeof(elf_hdr) + sizeof(load_text) + sizeof(load_rodata) + + mc_ptr + sizeof(null_section) + sizeof(text_section) + + sizeof(rodata_section) + sizeof(strtab_section) + + sizeof(strtab); + int rodata_pad_len = 4096 - (rodata_offset % 4096); + rodata_offset += rodata_pad_len; + elf_hdr.entry = start_addr + entry_addr; - elf_hdr.shoff = hdr1_size + mc_ptr + rd_ptr; + elf_hdr.shoff = hdr1_size + mc_ptr; - *(int64_t *) &hdr1[0x48] = 0;//sizeof(hdr1); - *(int64_t *) &hdr1[0x50] = start_addr - sizeof(hdr1); - *(int64_t *) &hdr1[0x58] = start_addr - sizeof(hdr1); - *(int64_t *) &hdr1[0x60] = rd_ptr + mc_ptr + sizeof(hdr1); - *(int64_t *) &hdr1[0x68] = rd_ptr + mc_ptr + sizeof(hdr1); load_text.offset = 0; load_text.vaddr = 0x400000; load_text.paddr = 0x400000; load_text.fsize = hdr1_size + mc_ptr; load_text.msize = hdr1_size + mc_ptr; - *(int64_t *) &hdr1[0x80] = sizeof(hdr1) + mc_ptr; - *(int64_t *) &hdr1[0x88] = rodata_addr; - *(int64_t *) &hdr1[0x90] = rodata_addr; - *(int64_t *) &hdr1[0x98] = rd_ptr; - *(int64_t *) &hdr1[0xa0] = rd_ptr; - load_rodata.offset = hdr1_size + mc_ptr; + load_rodata.offset = rodata_offset; load_rodata.vaddr = 0x600000; load_rodata.paddr = 0x600000; - //load_rodata.fsize = rd_ptr; load_rodata.fsize = rd_ptr; - load_rodata.msize = rd_ptr + load_rodata.offset; - - *(int64_t *) &hdr2[0x50] = start_addr; - *(int64_t *) &hdr2[0x58] = sizeof(hdr1); - *(int64_t *) &hdr2[0x60] = mc_ptr; - /* - *(int64_t *) &hdr2[0x90] = rodata_addr; - *(int64_t *) &hdr2[0x98] = sizeof(hdr1) + mc_ptr; - *(int64_t *) &hdr2[0xa0] = rd_ptr; - *(int64_t *) &hdr2[0xd8] = sizeof(hdr1) + mc_ptr + rd_ptr + sizeof(hdr2); - *(int64_t *) &hdr2[0xe0] = sizeof(strtab); - */ - *(int64_t *) &hdr2[0x98] = sizeof(hdr1) + mc_ptr + rd_ptr + sizeof(hdr2); - *(int64_t *) &hdr2[0xa0] = sizeof(strtab); + load_rodata.msize = rd_ptr; + text_section.addr = start_addr; text_section.offset = hdr1_size; text_section.size = mc_ptr; rodata_section.addr = load_rodata.vaddr; rodata_section.offset = load_rodata.offset; - rodata_section.size = rd_ptr; + rodata_section.size = load_rodata.fsize; - //strtab_section.addr = 0; - strtab_section.offset = hdr1_size + mc_ptr + rd_ptr + sizeof(struct sec_hdr) * elf_hdr.shcount; + strtab_section.offset = hdr1_size + mc_ptr + sizeof(struct sec_hdr) * elf_hdr.shcount; strtab_section.size = sizeof(strtab); - write(1, &elf_hdr, sizeof(elf_hdr)); - write(1, &load_text, sizeof(load_text)); - write(1, &load_rodata, sizeof(load_rodata)); - write(1, machine_code, mc_ptr); - write(1, rodata, rd_ptr); - write(1, &null_section, sizeof(null_section)); - write(1, &text_section, sizeof(text_section)); - write(1, &rodata_section, sizeof(rodata_section)); - write(1, &strtab_section, sizeof(strtab_section)); - write(1, strtab, sizeof(strtab)); - /* - write(1, hdr1, sizeof(hdr1)); - write(1, machine_code, mc_ptr); - write(1, rodata, rd_ptr); - write(1, hdr2, sizeof(hdr2)); - write(1, strtab, sizeof(strtab)); - */ + write(outfd, &elf_hdr, sizeof(elf_hdr)); + write(outfd, &load_text, sizeof(load_text)); + write(outfd, &load_rodata, sizeof(load_rodata)); + write(outfd, machine_code, mc_ptr); + write(outfd, &null_section, sizeof(null_section)); + write(outfd, &text_section, sizeof(text_section)); + write(outfd, &rodata_section, sizeof(rodata_section)); + write(outfd, &strtab_section, sizeof(strtab_section)); + write(outfd, strtab, sizeof(strtab)); + write(outfd, padding, rodata_pad_len); + write(outfd, rodata, rd_ptr); }