compiler

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

parse.y (78945B)


      1 %define parse.error verbose
      2 
      3 %{
      4 #include "lex.h"
      5 int line = 1;
      6 char *fname;
      7 int yywrap(void){ return 1; }
      8 int yylex(void);
      9 void yyerror(const char *s)
     10 {
     11   fprintf(stderr, "%s:%i:%s\n", fname, line, s);
     12   exit(1);
     13 }
     14 
     15 #define IDENTIFIER_TYPES( f ) \
     16   f(undefined) \
     17   f(variable) \
     18   f(func) \
     19   f(parameter)
     20 
     21 enum id_type {
     22   #define f(n) n,
     23   IDENTIFIER_TYPES(f)
     24   #undef f
     25 };
     26 
     27 #define EXPRESSION_TYPES( f ) \
     28   f(nop) f(string) f(number) f(idnt) \
     29   f(neg) f(add) f(mul) f(divide) f(mod)\
     30   f(comma) \
     31   f(ref) f(deref) \
     32   f(l_eq) f(l_lt) \
     33   f(l_and) f(l_or) f(l_not) \
     34   f(b_and) f(b_or) f(b_not) f(b_xor) \
     35   f(shift_l) f(shift_r) \
     36   f(set) f(decl) \
     37   f(ifnz) f(loop) \
     38   f(printchar) f(writestring) f(readstring)\
     39   f(brk_sys) f(_syscall) \
     40   f(function) f(fcall) f(ret) f(exit_p)
     41 
     42 enum e_type {
     43   #define f(n) n,
     44   EXPRESSION_TYPES(f)
     45   #undef f
     46 };
     47 
     48 struct expression {
     49   enum e_type type;
     50   enum id_type id_type;
     51   int constant;
     52   int declares;
     53   char *str;
     54   char flags;
     55   int64_t i;
     56   size_t args_count;
     57   struct expression *args;
     58 };
     59 
     60 struct identifiers{
     61   size_t count;
     62   struct expression *identifiers;
     63 };
     64 struct identifiers *ids = NULL;
     65 struct expression *defid(char *name)
     66 {
     67   int i;
     68   if (!ids)
     69     ids = calloc(sizeof(struct identifiers), 1);
     70   for (i = 0; i < ids->count; i++) {
     71     if (!strcmp(ids->identifiers[i].str, name)) return &ids->identifiers[i];
     72   }
     73   ids->count++;
     74   ids->identifiers = realloc(ids->identifiers, sizeof(struct expression) * ids->count);
     75 
     76   ids->identifiers[ids->count-1].type = idnt;
     77   ids->identifiers[ids->count-1].id_type = undefined;
     78   ids->identifiers[ids->count-1].constant = 1;
     79   ids->identifiers[ids->count-1].str = malloc(strlen(name) + 1);
     80 
     81   strcpy(ids->identifiers[ids->count-1].str, name);
     82   free(name);
     83 
     84   return &ids->identifiers[ids->count-1];
     85 }
     86 
     87 struct expression *find_idnt(char *name)
     88 {
     89   struct expression *r = NULL;
     90   size_t i;
     91   for (i = 0; i < ids->count; i++) {
     92     if (!strcmp(ids->identifiers[i].str, name)) {
     93       r = &ids->identifiers[i];
     94       break;
     95     }
     96   }
     97   if (!r) yyerror("undefined symbol");
     98   return r;
     99 }
    100 
    101 struct expression *ZERO = &(struct expression){ .type = number, .constant = 1 };
    102 struct expression *ONE = &(struct expression){ .type = number, .constant = 1, .i = 1 };
    103 struct expression *final;
    104 
    105 struct expression *e(enum e_type type, struct expression *arg1, struct expression *arg2, int nofree)
    106 {
    107   struct expression *r = calloc(sizeof(struct expression), 1);
    108   r->type = type;
    109   if (r->type == comma && (arg1 && arg1->type == comma || arg2 && arg2->type == comma)) {
    110     if (arg1 && arg1->type == comma && arg2 && arg2->type == comma) {
    111       r->args_count = arg1->args_count + arg2->args_count;
    112       r->args = calloc(sizeof(struct expression), r->args_count);
    113       memmove(r->args, arg1->args, sizeof(struct expression) * arg1->args_count);
    114       memmove(&r->args[arg1->args_count], arg2->args, sizeof(struct expression) * arg2->args_count);
    115     } else if (arg1 && arg1->type == comma) {
    116       r->args_count = arg1->args_count + 1;
    117       r->args = calloc(sizeof(struct expression), r->args_count);
    118       memmove(r->args, arg1->args, sizeof(struct expression) * arg1->args_count);
    119       if (arg2) memmove(&r->args[arg1->args_count], arg2, sizeof(struct expression));
    120     } else if (arg2 && arg2->type == comma) {
    121       r->args_count = arg2->args_count + 1;
    122       r->args = calloc(sizeof(struct expression), r->args_count);
    123       if (arg1) memmove(r->args, arg1, sizeof(struct expression));
    124       memmove(&r->args[arg1 ? 1 : 0], arg2->args, sizeof(struct expression) * arg2->args_count);
    125     }
    126   } else if (r->type == number) {
    127     r->i = (int64_t) arg1;
    128   } else if (r->type == string && arg1) {
    129     r->str = calloc(strlen((char *)arg1) + 1, 1);
    130     strcpy(r->str, (char *)arg1);
    131   } else {
    132     r->args_count = (arg1 ? 1 : 0) + (arg2 ? 1 : 0);
    133     r->args = calloc(sizeof(struct expression), r->args_count);
    134     if (arg1) memmove(r->args, arg1, sizeof(struct expression));
    135     if (arg2) memmove(&r->args[arg1 ? 1 : 0], arg2, sizeof(struct expression));
    136   }
    137   //if (!nofree && arg1 && !arg1->constant) free(arg1);
    138   if (!nofree && arg2 && !arg2->constant) free(arg2);
    139   return r;
    140 }
    141 int curr_decl = 0;
    142 struct expression *defun(struct expression *identifier, struct expression *params, struct expression *body)
    143 {
    144   struct expression *r = calloc(sizeof(struct expression), 1);
    145   r->type = function;
    146   r->declares = curr_decl;
    147   curr_decl = 0;
    148   r->args_count = params ? 3 : 2;
    149   r->args = calloc(sizeof(struct expression), r->args_count);
    150   memmove(r->args, identifier, sizeof(struct expression));
    151   if (params) memmove(&r->args[1], params, sizeof(struct expression));
    152   memmove(&r->args[r->args_count-1], body, sizeof(struct expression));
    153   if (params) free(params);
    154   if (body) free(body);
    155   return r;
    156 }
    157 
    158 void append(struct expression *base, struct expression *arg)
    159 {
    160   base->args = realloc(base->args, sizeof(struct expression) * (++base->args_count));
    161   memmove(&base->args[base->args_count-1], arg, sizeof(struct expression));
    162   free(arg);
    163 }
    164 
    165 struct expression *move(struct expression *e)
    166 {
    167   struct expression *r = calloc(sizeof(struct expression), 1);
    168   memmove(r, e, sizeof(struct expression));
    169   free(e);
    170   return r;
    171 }
    172 struct expression *copy(struct expression *e)
    173 {
    174   struct expression *r = calloc(sizeof(struct expression), 1);
    175   memcpy(r, e, sizeof(struct expression));
    176   return r;
    177 }
    178 
    179 char *expand_str(char *str) {
    180   int i, j = 0, l = strlen(str);
    181   for (i = 0; i < l; i++) {
    182     if (str[i] == '\\') {
    183       switch (str[i+1]) {
    184       case 'n':
    185         j = 1;
    186         str[i+j] = '\n';
    187         break;
    188       case 'r':
    189         j = 1;
    190         str[i+j] = '\r';
    191         break;
    192       case 't':
    193         j = 1;
    194         str[i+j] = '\t';
    195         break;
    196       case '\\':
    197         i++;
    198       default:
    199         j = 0;
    200         break;
    201       }
    202       l -= j;
    203       if (j) memmove(&str[i], &str[i+j], l - i + 1);
    204     }
    205   }
    206   return str;
    207 }
    208 
    209 char *escape_str(char *str) {
    210   int i, j, l = strlen(str);
    211   char *r;
    212   for (i = 0, j = 1; i < l; i++)
    213     if (str[i] == '\\' || str[i] == '\n' || str[i] == '\r' || str[i] == '\t')
    214       j++;
    215   r = calloc(l + j, 1);
    216   for (i = 0, j = 0; i < l; i++, j++) {
    217     switch (str[i]) {
    218     case '\n':
    219       r[j++] = '\\';
    220       r[j] = 'n';
    221       break;
    222     case '\r':
    223       r[j++] = '\\';
    224       r[j] = 'r';
    225       break;
    226     case '\t':
    227       r[j++] = '\\';
    228       r[j] = 't';
    229       break;
    230     case '\\':
    231       r[j++] = '\\';
    232       r[j] = '\\';
    233       break;
    234     default:
    235       r[j] = str[i];
    236       break;
    237     }
    238   }
    239   return r;
    240 }
    241 %}
    242 
    243 %union {struct expression *expr; char *str; int64_t i;}
    244 
    245 %token END 0
    246 %token <str> IDENTIFIER STRING
    247 %token <i> NUMBER
    248 %token INC "++" DEC "--"
    249 %token EQ "==" LTEQ "<=" GTEQ ">=" AND "&&" OR "||" NOT_EQ "!="
    250 %token SHIFT_L "<<" SHIFT_R ">>"
    251 %token ADD_EQ "+=" SUB_EQ "-=" MUL_EQ "*=" DIV_EQ "/=" MOD_EQ "%="
    252 %token OR_EQ "|=" AND_EQ "&=" XOR_EQ "^=" SHL_EQ "<<=" SHR_EQ ">>="
    253 %token RETURN "return" IF "if" ELSE "else" WHILE "while" DECL "decl"
    254 %token EXIT "exit" PUTC "putc" WRITE "write" READ "read" BRK "brk"
    255 %token SYSCALL1 "_syscall1" SYSCALL2 "_syscall2" SYSCALL3 "_syscall3"
    256 %token SYSCALL4 "_syscall4" SYSCALL5 "_syscall5" SYSCALL6 "_syscall6"
    257 
    258 %nonassoc "if"
    259 %nonassoc "else"
    260 
    261 %left  ','
    262 %right '?' ':' '=' "+=" "-=" "*=" "/=" "%=" "&=" "|=" "^=" "<<=" ">>="
    263 %left  "||"
    264 %left  "&&"
    265 %left  '|'
    266 %left  '^'
    267 %left  '&'
    268 %left  "==" "!="
    269 %left  '<' '>' "<=" ">="
    270 %left  "<<" ">>"
    271 %left  '+' '-'
    272 %left  '*' '/' '%'
    273 %right REF NEG "++" "--" '!' '~'
    274 %left  '(' '['
    275 
    276 %type <expr> expression exprs c_expr var_def var_defs statement comp_stmt if_stmt
    277 %type <expr> parameters parameter identifier program function ifelse
    278 %type <str> str
    279 
    280 %%
    281 
    282 program:    program function                      {$$ = move($1); append($$, $2); final = $$;}
    283 |           function                              {$$ = e(comma, $1, NULL, 0); final = $$;}
    284 ;
    285 
    286 function:   identifier '(' parameters ')' statement {$1->id_type = function; $$ = defun(copy($1), $3, $5);}
    287 ;
    288 
    289 parameters: parameter                             {$$ = move($1);}
    290 |           %empty                                {$$ = NULL;}
    291 ;
    292 
    293 parameter:  parameter ',' parameter               {$$ = e(comma, $1, $3, 0);}
    294 |           identifier                            {$1->id_type = parameter; $$ = copy($1);}
    295 ;
    296 
    297 statement:  "return" exprs ';'                    {$$ = e(ret, $2, NULL, 0);}
    298 |           "while" '(' expression ')' statement  {$$ = e(loop, $3, $5, 0);}
    299 |           ifelse                                {$$ = move($1);}
    300 |           exprs ';'                             {$$ = move($1);}
    301 |           "exit" ';'                            {$$ = e(exit_p, ZERO, NULL, 0);}
    302 |           "exit" expression ';'                 {$$ = e(exit_p, $2, NULL, 0);}
    303 |           comp_stmt '}'                         {$$ = move($1);}
    304 |           ';'                                   {$$ = e(nop, NULL, NULL, 1);}
    305 ;
    306 
    307 ;
    308 
    309 ifelse:     if_stmt "else" statement %prec "else" {$$ = move($1); append($$, $3);}
    310 |           if_stmt %prec "if"                    {$$ = move($1);}
    311 ;
    312 
    313 if_stmt:    "if" '(' expression ')' statement     {$$ = e(ifnz, $3, $5, 0);}
    314 ;
    315 
    316 comp_stmt:  '{'                                   {$$ = e(comma, NULL, NULL, 1);}
    317 |           comp_stmt statement                   {$$ = move($1); append($$, $2);}
    318 ;
    319 
    320 var_defs:   "decl" var_def                        {$$ = move($2);}
    321 |           var_defs ',' var_def                  {$$ = e(comma, $1, $3, 0);}
    322 ;
    323 
    324 var_def:    identifier                            {curr_decl++; $1->id_type = variable; $$ = e(decl, $1, NULL, 0);}
    325 |           identifier '=' expression             {curr_decl++; $1->id_type = variable; $$ = e(comma, e(decl, $1, NULL, 0), e(set, $1, $3, 0), 0);}
    326 ;
    327 
    328 identifier: IDENTIFIER                            {$$ = copy(defid($1));}
    329 ;
    330 
    331 exprs:      c_expr                                {$$ = move($1);}
    332 |           var_defs                              {$$ = move($1);}
    333 ;
    334 
    335 c_expr:     expression                            {$$ = move($1);}
    336 |           c_expr ',' expression                 {$$ = e(comma, $1, $3, 0);}
    337 ;
    338 
    339 expression: IDENTIFIER                            {$$ = copy(defid($1)); /*$$ = copy(find_idnt($1));*/}
    340 |           NUMBER                                {$$ = e(number, (void *)$1, NULL, 1);}
    341 |           str                                   {$$ = e(string, (void *)expand_str($1), NULL, 0);}
    342 |           expression '[' expression ']'         {$$ = e(deref, e(add, $1, $3, 0), NULL, 0);}
    343 |           '(' exprs ')'                         {$$ = move($2);}
    344 |           expression '(' ')'                    {$$ = e(fcall, $1, NULL, 0);}
    345 |           expression '(' c_expr ')'             {$$ = e(fcall, $1, $3, 0);}
    346 |           "putc" '(' expression ')'             {$$ = e(printchar, $3, NULL, 0);}
    347 |           "write" '(' expression ',' expression ',' expression ')' {$$ = e(writestring, e(comma, e(comma, $3, $5, 0), $7, 0), NULL, 0);}
    348 |           "read" '(' expression ',' expression ',' expression ')' {$$ = e(readstring, e(comma, e(comma, $3, $5, 0), $7, 0), NULL, 0);}
    349 |           "brk" '(' expression ')'              {$$ = e(brk_sys, $3, NULL, 0);}
    350 |           "_syscall1" '(' expression ','
    351                             expression ')'        {$$ = e(_syscall, $3, $5, 0);}
    352 
    353 |           "_syscall2" '(' expression ','
    354                             expression ','
    355                             expression ')'        {$$ = e(_syscall, $3, e(comma, $5, $7, 0), 0);}
    356 
    357 |           "_syscall3" '(' expression ','
    358                             expression ','
    359                             expression ','
    360                             expression ')'        {$$ = e(_syscall, $3, e(comma, e(comma, $5, $7, 0), $9, 0), 0);}
    361 
    362 |           "_syscall4" '(' expression ','
    363                             expression ','
    364                             expression ','
    365                             expression ','
    366                             expression ')'        {$$ = e(_syscall, $3, e(comma, e(comma, e(comma, $5, $7, 0), $9, 0), $11, 0), 0);}
    367 
    368 |           "_syscall5" '(' expression ','
    369                             expression ','
    370                             expression ','
    371                             expression ','
    372                             expression ','
    373                             expression ')'        {$$ = e(_syscall, $3, e(comma, e(comma, e(comma, e(comma, $5, $7, 0), $9, 0), $11, 0), $13, 0), 0);}
    374 
    375 |           "_syscall6" '(' expression ','
    376                             expression ','
    377                             expression ','
    378                             expression ','
    379                             expression ','
    380                             expression ','
    381                             expression ')'        {$$ = e(_syscall, $3, e(comma, e(comma, e(comma, e(comma, e(comma, $5, $7, 0), $9, 0), $11, 0), $13, 0), $15, 0), 0);}
    382 
    383 |           expression '+' expression             {$$ = e(add, $1, $3, 0);}
    384 |           expression '-' expression             {if ($3->type == number) {
    385                                                      $$ = e(add, $1, $3, 0);
    386                                                      $$->args[1].i = -$$->args[1].i;
    387                                                    } else {
    388                                                      $$ = e(add, $1, e(neg, $3, NULL, 0), 0);
    389                                                    }}
    390 |           expression '*' expression             {$$ = e(mul, $1, $3, 0);}
    391 |           expression '/' expression             {$$ = e(divide, $1, $3, 0);}
    392 |           expression '%' expression             {$$ = e(mod, $1, $3, 0);}
    393 |           expression '&' expression             {$$ = e(b_and, $1, $3, 0);}
    394 |           expression '|' expression             {$$ = e(b_or, $1, $3, 0);}
    395 |           expression '^' expression             {$$ = e(b_xor, $1, $3, 0);}
    396 |           expression "<<" expression            {$$ = e(shift_l, $1, $3, 0);}
    397 |           expression ">>" expression            {$$ = e(shift_r, $1, $3, 0);}
    398 |           expression '=' expression             {$$ = e(set, $1, $3, 0);}
    399 |           expression "+=" expression            {$$ = e(set, $1, e(add, $1, $3, 0), 0);}
    400 |           expression "-=" expression            {if ($3->type == number) {
    401                                                      $$ = e(add, $1, $3, 0);
    402                                                      $$->args[1].i = -$$->args[1].i;
    403                                                      $$ = e(set, $1, $$, 0);
    404                                                    } else {
    405                                                      $$ = e(set, $1, e(add, $1, e(neg, $3, NULL, 0), 0), 0);
    406                                                    }}
    407 |           expression "*=" expression            {$$ = e(set, $1, e(mul, $1, $3, 0), 0);}
    408 |           expression "/=" expression            {$$ = e(set, $1, e(divide, $1, $3, 0), 0);}
    409 |           expression "%=" expression            {$$ = e(set, $1, e(mod, $1, $3, 0), 0);}
    410 |           expression "&=" expression            {$$ = e(set, $1, e(b_and, $1, $3, 0), 0);}
    411 |           expression "|=" expression            {$$ = e(set, $1, e(b_or, $1, $3, 0), 0);}
    412 |           expression "^=" expression            {$$ = e(set, $1, e(b_xor, $1, $3, 0), 0);}
    413 |           expression "<<=" expression           {$$ = e(set, $1, e(shift_l, $1, $3, 0), 0);}
    414 |           expression ">>=" expression           {$$ = e(set, $1, e(shift_r, $1, $3, 0), 0);}
    415 |           expression "==" expression            {$$ = e(l_eq, $1, $3, 0);}
    416 |           expression "!=" expression            {$$ = e(l_not, e(l_eq, $1, $3, 0), NULL, 0);}
    417 |           expression '<' expression             {$$ = e(l_lt, $1, $3, 0);}
    418 |           expression '>' expression             {$$ = e(l_lt, $3, $1, 0);}
    419 |           expression "<=" expression            {$$ = e(l_not, e(l_lt, $1, $3, 0), NULL, 0);}
    420 |           expression ">=" expression            {$$ = e(l_not, e(l_lt, $3, $1, 0), NULL, 0);}
    421 |           expression "&&" expression            {$$ = e(l_and, $1, $3, 0);}
    422 |           expression "||" expression            {$$ = e(l_or, $1, $3, 0);}
    423 |           '!' expression                        {$$ = e(l_not, $2, NULL, 0);}
    424 |           '~' expression                        {printf("uh-oh\n");$$ = NULL;}
    425 |           '*' expression %prec REF              {$$ = e(deref, $2, NULL, 0);}
    426 |           '&' expression %prec REF              {$$ = e(ref, $2, NULL, 0);}
    427 |           '-' expression %prec NEG              {if ($2->type == number) {
    428                                                      $$ = $2;
    429                                                      $$->i = -$$->i;
    430                                                    } else {
    431                                                      $$ = e(neg, $2, NULL, 0);
    432                                                    }}
    433 |           '+' expression %prec NEG              {printf("uh-oh\n");$$ = NULL;}
    434 |           "++" expression                       {$$ = e(set, $2, e(add, $2, ONE, 0), 0);}
    435 |           "--" expression                       {$$ = e(set, $2, e(add, $2, e(neg, ONE, NULL, 0), 0), 0);}
    436 |           expression "++"                       {printf("uh-oh ++\n");$$ = NULL;}
    437 |           expression "--"                       {printf("uh-oh --\n");$$ = NULL;}
    438 ;          
    439 
    440 str:        str STRING                            {$$ = calloc(strlen($1) + strlen($2) + 1, 1); strcpy($$, $1); strcpy(&$$[strlen($$)], $2); free($1); free($2);}
    441 |           STRING                                {$$ = $1;}
    442 ;
    443 
    444 %%
    445 #include <stdio.h>
    446 #include <fcntl.h>
    447 
    448 char *exp_str[] = {
    449 #define f(e) #e,
    450 EXPRESSION_TYPES(f)
    451 #undef f
    452 };
    453 
    454 int has_sideeffect(struct expression *n)
    455 {
    456   int i, r = 0;
    457   switch (n->type) {
    458   case nop: case number: case idnt: case string:
    459     return 0;
    460   case set: case decl: case ret: 
    461     return 1;
    462   case brk_sys: case printchar: case writestring:
    463   case readstring: case _syscall: case exit_p:
    464     return 2;
    465   case neg: case l_not: case b_not: case ref: case deref:
    466     return has_sideeffect(n->args);
    467   case add: case mul: case divide: case mod: case b_and: case b_or: case b_xor:
    468   case l_and: case l_or: case l_lt: case l_eq: case shift_l: case shift_r:
    469   case loop: case comma: case ifnz:
    470     for (i = 0; i < n->args_count; i++)
    471       r |= has_sideeffect(&n->args[i]);
    472     return r;
    473   default:
    474     return 1;
    475   }
    476 }
    477 
    478 void stringify(struct expression *e, int p_indent, int last, char *name, uint64_t idmap)
    479 {
    480   int i, indent = p_indent + 3;
    481   char *str;
    482   if (last) idmap |= (1 << p_indent/3);
    483   for (i = 0; i < p_indent; i+=3) fprintf(stderr, "%s  ", (idmap & (1 << (i/3))) ? " " : "│");
    484   if (p_indent >= 0) fprintf(stderr, "%s- ", last ? "-": "+");
    485   switch(e->type) {
    486   case function:
    487     fprintf(stderr, "%s (", e->args->str);
    488     if (e->args_count == 3) {
    489       if (e->args[1].type == comma) {
    490         for (i = 0; i < e->args[1].args_count; i++)
    491           fprintf(stderr, "%s%s", e->args[1].args[i].str, i+1 == e->args[1].args_count ? "" : ", ");
    492       } else {
    493         fprintf(stderr, "%s", e->args[1].str);
    494       }
    495     }
    496     fprintf(stderr, "):\n");
    497     stringify(&e->args[e->args_count-1], indent, 1, NULL, idmap);
    498     break;
    499   case string:
    500     str = escape_str(e->str);
    501     fprintf(stderr, "%s: \"%s\"\n", name ? name : "string", str);
    502     free(str);
    503     break;
    504   case idnt:
    505     fprintf(stderr, "%s: %s\n", name ? name : "ident", e->str);
    506     break;
    507   case number:
    508     fprintf(stderr, "%s: %li\n", name ? name : "number", e->i);
    509     break;
    510   default:
    511     fprintf(stderr, "%s: (pure: %i)\n", exp_str[e->type], !has_sideeffect(e));
    512     for (i = 0; i < e->args_count;) {
    513       stringify(&e->args[i++], indent, i+1 == e->args_count, NULL, idmap);
    514     }
    515     break;
    516   }
    517 }
    518 
    519 void breakpoint(void) {}
    520 
    521 struct storage {
    522   int type;
    523   char *var;
    524   char rbp;
    525   int rev;
    526 };
    527 struct reg_history {
    528   /* 0 - undefined
    529    * 1 - variable
    530    * 2 - constant */
    531   int type;
    532   int reg;
    533   int val;
    534   int rev;
    535 };
    536 
    537 struct storage regs[1024];
    538 struct reg_history reg_hist[16];
    539 const int registers = 16;
    540 int next_reg;
    541 uint16_t used_regs;
    542 int next_rbp;
    543 
    544 char machine_code[16384] = { 0 };
    545 int mc_ptr = 0;
    546 char rodata[8192] = { 0 };
    547 int rd_ptr = 0;
    548 int entry_addr = -1;
    549 long start_addr, rodata_addr;
    550 int func_declares;
    551 
    552 int arg_order[16] = {7, 6, 2, 1, 8, 9, 1, 0, 11, 12, 13, 14, 15, 3, 5};
    553 int syscall_arg[16] = {7, 6, 2, 10, 8, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1};
    554 //int caller_save = 0b0000111111001111;
    555 int caller_save = 0b1111111111001111;
    556 
    557 int get_free_reg(int mark_used)
    558 {
    559   int i;
    560   for (i = 0; i < registers; i++) {
    561     if (!(used_regs & (1 << i))) {
    562       if (mark_used) used_regs |= (1 << i);
    563       return i;
    564       break;
    565     }
    566   }
    567   fprintf(stderr, "Out of registers?!? fix me\n");
    568   exit(1);
    569 }
    570 
    571 void push(int reg, int *pushed, char *order, char *from) {
    572   int i;
    573   if (used_regs & (1 << reg)) {
    574     machine_code[mc_ptr++] = 0x48 | (reg > 7 ? 1 : 0);
    575     machine_code[mc_ptr++] = 0x50 + (reg % 8);
    576     for (i = 0; i < registers; i++) {
    577       if (order[i] == -1) {
    578         order[i] = reg;
    579         used_regs &= ~(1 << reg);
    580         *pushed |= (1 << reg);
    581         next_rbp += 8;
    582         return;
    583       }
    584     }
    585     fprintf(stderr, "Unable to push any more registers\n");
    586     exit(1);
    587   }
    588 }
    589 
    590 void pop(int reg, int *pushed) {
    591   if (!(*pushed & (1 << reg))) {
    592     fprintf(stderr, "Trying to pop a register which hasn't been pushed\n");
    593     exit(1);
    594   }
    595   machine_code[mc_ptr++] = 0x48 | (reg > 7 ? 1 : 0);
    596   machine_code[mc_ptr++] = 0x58 + (reg % 8);
    597   *pushed &= ~(1 << reg);
    598   used_regs |= (1 << reg);
    599   next_rbp -= 8;
    600   reg_hist[reg].type = 0;
    601 }
    602 
    603 struct func_template {
    604   char *fname;
    605   int fptr;
    606 };
    607 
    608 struct func_template *ftemp;
    609 int ftemp_len = 0;
    610 
    611 void func_append(char *fname, int ptr)
    612 {
    613   int i, j;
    614   for (i = 0; i < ftemp_len; i++)
    615     if (!strcmp(ftemp[i].fname, fname)) break;
    616   if (i == ftemp_len) {
    617     ftemp = realloc(ftemp, sizeof(struct func_template) * ++ftemp_len);
    618     ftemp[i].fname = malloc(strlen(fname) + 1);
    619     strcpy(ftemp[i].fname, fname);
    620     ftemp[i].fptr = 0;
    621   }
    622   if (!ftemp[i].fptr) {
    623     ftemp[i].fptr = ptr;
    624   } else {
    625     for (j = ftemp[i].fptr; *((int *) &machine_code[j]); j = *((int *) &machine_code[j]));
    626     *((int *) &machine_code[j]) = ptr;
    627   }
    628 }
    629 
    630 void func_retrofit(char *fname, int ptr)
    631 {
    632   int i, j, k;
    633   for (i = 0; i < ftemp_len; i++)
    634     if (!strcmp(ftemp[i].fname, fname)) break;
    635   if (i == ftemp_len) return;
    636 
    637   for (j = ftemp[i].fptr, k = 1; k; j = k) {
    638     k = *((int *) &machine_code[j]);
    639     *((int *) &machine_code[j]) = ptr - j - 4;
    640   }
    641   ftemp[i].fptr = 0;
    642 }
    643 
    644 int compile_tree(FILE *output, struct expression *tree, int discard_result, int out_reg)
    645 {
    646   int i, j, k, l, reg = -1;
    647   char push_order[16] = { -1, -1, -1, -1,
    648                           -1, -1, -1, -1,
    649                           -1, -1, -1, -1,
    650                           -1, -1, -1, -1 };
    651   int pushed = 0;
    652   struct expression *tmp;
    653   switch (tree->type) {
    654   case function:
    655     next_reg = registers;
    656     used_regs = (1 << 5) | (1 << 4);
    657     next_rbp = 8;
    658     tree->i = mc_ptr;
    659     find_idnt(tree->args->str)->i = mc_ptr + start_addr;
    660     find_idnt(tree->args->str)->flags |= 1;
    661     func_retrofit(tree->args->str, mc_ptr);
    662     memset(reg_hist, 0, sizeof(reg_hist));
    663     if (!strcmp(tree->args->str, "_start")) {
    664       entry_addr = mc_ptr;
    665       machine_code[mc_ptr++] = 0x55;
    666       machine_code[mc_ptr++] = 0x48;
    667       machine_code[mc_ptr++] = 0x89;
    668       machine_code[mc_ptr++] = 0xE5;
    669 
    670       if (tree->declares) {
    671         machine_code[mc_ptr++] = 0x48;
    672         machine_code[mc_ptr++] = 0x81;
    673         machine_code[mc_ptr++] = 0xEC;
    674         *(int *) &machine_code[mc_ptr] = tree->declares*8;
    675         mc_ptr += 4;
    676       }
    677     } else {
    678       if (tree->args[1].type == idnt && tree->args[1].id_type == parameter) {
    679         tree->declares++;
    680         regs[next_reg].type = 1;
    681         regs[next_reg].var = tree->args[1].str;
    682         regs[next_reg].rbp = next_rbp;
    683         next_rbp += 8;
    684         next_reg++;
    685       } else if (tree->args[1].type == comma && tree->args[1].args->type == idnt && tree->args[1].args->id_type == parameter) {
    686         for (i = 0; i < tree->args[1].args_count; i++) {
    687           tree->declares++;
    688           regs[next_reg].type = 1;
    689           regs[next_reg].var = tree->args[1].args[i].str;
    690           regs[next_reg].rbp = next_rbp;
    691           next_rbp += 8;
    692           next_reg++;
    693         }
    694       }
    695       func_declares = tree->declares;
    696       machine_code[mc_ptr++] = 0x55;
    697       machine_code[mc_ptr++] = 0x48;
    698       machine_code[mc_ptr++] = 0x89;
    699       machine_code[mc_ptr++] = 0xE5;
    700 
    701       if (tree->declares) {
    702         machine_code[mc_ptr++] = 0x48;
    703         machine_code[mc_ptr++] = 0x81;
    704         machine_code[mc_ptr++] = 0xEC;
    705         *(int *) &machine_code[mc_ptr] = tree->declares*8;
    706         mc_ptr += 4;
    707       }
    708 
    709       if (tree->args[1].type == idnt && tree->args[1].id_type == parameter) {
    710         machine_code[mc_ptr++] = 0x48 | (arg_order[0] > 7 ? 4 : 0);
    711         machine_code[mc_ptr++] = 0x89;
    712         machine_code[mc_ptr++] = 0x45 + (arg_order[0] % 8) * 8;
    713         machine_code[mc_ptr++] = -regs[registers].rbp;
    714         reg_hist[arg_order[0]].type = 1;
    715         reg_hist[arg_order[0]].reg = registers;
    716         reg_hist[arg_order[0]].rev = ++regs[registers].rev;
    717       } else if (tree->args[1].type == comma && tree->args[1].args->type == idnt && tree->args[1].args->id_type == parameter) {
    718         for (i = 0; i < tree->args[1].args_count; i++) {
    719           machine_code[mc_ptr++] = 0x48 | (arg_order[i] > 7 ? 4 : 0);
    720           machine_code[mc_ptr++] = 0x89;
    721           machine_code[mc_ptr++] = 0x45 + (arg_order[i] % 8) * 8;
    722           machine_code[mc_ptr++] = -regs[registers + i].rbp;
    723           reg_hist[arg_order[i]].type = 1;
    724           reg_hist[arg_order[i]].reg = registers + i;
    725           reg_hist[arg_order[i]].rev = ++regs[registers + i].rev;
    726         }
    727       }
    728     }
    729     j = compile_tree(output, &tree->args[tree->args_count-1], 1, 0);
    730     if (strcmp(tree->args->str, "_start") && j != -3 && j != -2) {
    731       machine_code[mc_ptr++] = 0xc9;
    732       machine_code[mc_ptr++] = 0xc3;
    733     }
    734     break;
    735   case comma:
    736     for (i = 0; i < tree->args_count; i++) {
    737       j = compile_tree(output, &tree->args[i], (i+1 == tree->args_count ? discard_result : 1), (i+1 == tree->args_count ? out_reg : -1));
    738       if (j == -2 || j == -3) return j;
    739     }
    740     if (!discard_result) reg = j;
    741     break;
    742   case fcall:
    743     for (i = 0; i < registers; i++) {
    744       if (caller_save & (1 << i)) {
    745         push(i, &pushed, push_order, "fcall (caller_save)");
    746       }
    747     }
    748     if (tree->args_count == 2) {
    749       if (tree->args[1].type == comma) {
    750         for (i = 0; i < tree->args[1].args_count; i++) {
    751           j = compile_tree(output, &tree->args[1].args[i], 0, arg_order[i]);
    752         }
    753       } else {
    754         j = compile_tree(output, &tree->args[1], 0, arg_order[0]);
    755       }
    756     }
    757     machine_code[mc_ptr++] = 0xe8;
    758     if (find_idnt(tree->args->str)->flags & 1) {
    759       j = find_idnt(tree->args->str)->i - start_addr - mc_ptr - 4;
    760     } else {
    761       func_append(tree->args->str, mc_ptr);
    762       j = 0;
    763     }
    764     *(int32_t *) &machine_code[mc_ptr] = j;
    765     mc_ptr += 4;
    766 
    767     if (tree->args[1].type == comma)
    768       for (i = 0; i < tree->args[1].args_count; i++)
    769         used_regs &= ~(1 << arg_order[i]);
    770     else
    771       used_regs &= ~(1 << arg_order[0]);
    772 
    773     memset(reg_hist, 0, sizeof(reg_hist));
    774     if (!discard_result) {
    775       reg = 0;
    776       used_regs |= !(pushed & 1);
    777     }
    778     break;
    779   case add:
    780     if (!discard_result &&
    781         (tree->args->type == idnt || tree->args[1].type == idnt)) {
    782       if (tree->args->type == idnt) {
    783         j = compile_tree(output, tree->args, discard_result, -1);
    784         tmp = &tree->args[1];
    785       } else {
    786         j = compile_tree(output, &tree->args[1], discard_result, -1);
    787         tmp = tree->args;
    788       }
    789       if (j == out_reg && tmp->type == number &&
    790           tmp->i < (long) 0x80000000 && tmp->i >= (long) -0x80000000) {
    791         reg = j;
    792         k = (int) tmp->i;
    793         machine_code[mc_ptr++] = 0x48;
    794         machine_code[mc_ptr++] = 0x81;
    795         machine_code[mc_ptr++] = 0x45;
    796         *(int32_t *) &machine_code[mc_ptr] = k;
    797         mc_ptr += 4;
    798         break;
    799       }
    800     } else {
    801       j = compile_tree(output, tree->args, discard_result, -1);
    802     }
    803     k = compile_tree(output, &tree->args[1], discard_result, -1);
    804     if (discard_result) {
    805       if (j >= 0 && j < registers) used_regs &= ~(1 << j);
    806       if (k >= 0 && k < registers) used_regs &= ~(1 << k);
    807       break;
    808     }
    809     if (out_reg < 0 || out_reg != j && out_reg != k) {
    810       if (k >= registers) {
    811         if (j >= registers) {
    812             reg = out_reg;
    813           if (out_reg < 0 || out_reg >= registers)
    814             reg = get_free_reg(1);
    815           machine_code[mc_ptr++] = 0x48 | (reg > 7 ? 4 : 0);
    816           machine_code[mc_ptr++] = 0x8b;
    817           machine_code[mc_ptr++] = 0x45 + (reg % 8) * 8;
    818           machine_code[mc_ptr++] = -regs[j].rbp;
    819           j = reg;
    820         }
    821         machine_code[mc_ptr++] = 0x48 | (j > 7 ? 4 : 0);
    822         machine_code[mc_ptr++] = 0x03;
    823         machine_code[mc_ptr++] = 0x45 + (j % 8) * 8;
    824         machine_code[mc_ptr++] = -regs[k].rbp;
    825         reg = j, l = k;
    826       } else if (j >= registers) {
    827         machine_code[mc_ptr++] = 0x48 | (k > 7 ? 4 : 0);
    828         machine_code[mc_ptr++] = 0x03;
    829         machine_code[mc_ptr++] = 0x45 + (k % 8) * 8;
    830         machine_code[mc_ptr++] = -regs[j].rbp;
    831         reg = k, l = j;
    832       } else {
    833         machine_code[mc_ptr++] = 0x48 | (j > 7 ? 4 : 0) | (k > 7 ? 1 : 0);
    834         machine_code[mc_ptr++] = 0x03;
    835         machine_code[mc_ptr++] = 0xC0 + (j % 8) * 8 + (k % 8);
    836         reg = j, l = k;
    837       }
    838     } else {
    839       if (out_reg == k) {
    840         l = j;
    841         j = k;
    842         k = l;
    843       }
    844       if (j >= registers) {
    845         if (k >= registers) {
    846           reg = get_free_reg(1);
    847           machine_code[mc_ptr++] = 0x48 | (reg > 7 ? 4 : 0);
    848           machine_code[mc_ptr++] = 0x8b;
    849           machine_code[mc_ptr++] = 0x45 + (reg % 8) * 8;
    850           machine_code[mc_ptr++] = -regs[k].rbp;
    851           k = reg;
    852         }
    853         machine_code[mc_ptr++] = 0x48 | (k > 7 ? 4 : 0);
    854         machine_code[mc_ptr++] = 0x01;
    855         machine_code[mc_ptr++] = 0x45 + (k % 8) * 8;
    856         machine_code[mc_ptr++] = -regs[j].rbp;
    857       } else if (k >= registers) {
    858         machine_code[mc_ptr++] = 0x48 | (j > 7 ? 4 : 0);
    859         machine_code[mc_ptr++] = 0x03;
    860         machine_code[mc_ptr++] = 0x45 + (j % 8) * 8;
    861         machine_code[mc_ptr++] = -regs[k].rbp;
    862       } else {
    863         machine_code[mc_ptr++] = 0x48 | (j > 7 ? 4 : 0) | (k > 7 ? 1 : 0);
    864         machine_code[mc_ptr++] = 0x03;
    865         machine_code[mc_ptr++] = 0xC0 + (j % 8) * 8 + (k % 8);
    866         if (reg_hist[j].type & 2 && reg_hist[k].type & 2) {
    867           reg_hist[j].type = 2;
    868           reg_hist[j].val += reg_hist[k].val;
    869         } else if (reg_hist[j].type & 2) {
    870           reg_hist[j].type = 0;
    871         }
    872       }
    873       reg = j, l = k;
    874     }
    875     if (l < registers) used_regs &= ~(1 << l);
    876     break;
    877   case neg:
    878     j = compile_tree(output, tree->args, discard_result, (out_reg >= 0 ? out_reg : get_free_reg(1)));
    879     if (discard_result) {
    880       if (j < registers) used_regs &= ~(1 << j);
    881       break;
    882     }
    883     reg = j;
    884     if (reg >= registers) {
    885       machine_code[mc_ptr++] = 0x48;
    886       machine_code[mc_ptr++] = 0xf7;
    887       machine_code[mc_ptr++] = 0x5d;
    888       machine_code[mc_ptr++] = -regs[reg].rbp;
    889     } else {
    890       machine_code[mc_ptr++] = 0x48 | (reg > 7 ? 1 : 0);
    891       machine_code[mc_ptr++] = 0xf7;
    892       machine_code[mc_ptr++] = 0xd8 + (reg % 8);
    893     }
    894     break;
    895   case mul:
    896     j = compile_tree(output, tree->args, discard_result, -1);
    897     k = compile_tree(output, &tree->args[1], discard_result, -1);
    898     if (discard_result) {
    899       if (j < registers) used_regs &= ~(1 << j);
    900       if (k < registers) used_regs &= ~(1 << k);
    901       break;
    902     }
    903     if (out_reg < 0 || out_reg != j && out_reg != k) {
    904       if (k >= registers) {
    905         if (j >= registers) {
    906             reg = out_reg;
    907           if (out_reg < 0 || out_reg >= registers)
    908             reg = get_free_reg(1);
    909           machine_code[mc_ptr++] = 0x48 | (reg > 7 ? 4 : 0);
    910           machine_code[mc_ptr++] = 0x8b;
    911           machine_code[mc_ptr++] = 0x45 + (reg % 8) * 8;
    912           machine_code[mc_ptr++] = -regs[j].rbp;
    913           j = reg;
    914         }
    915         machine_code[mc_ptr++] = 0x48 | (j > 7 ? 4 : 0);
    916         machine_code[mc_ptr++] = 0x0F;
    917         machine_code[mc_ptr++] = 0xAF;
    918         machine_code[mc_ptr++] = 0x45 + (j % 8) * 8;
    919         machine_code[mc_ptr++] = -regs[k].rbp;
    920         reg = j, l = k;
    921       } else if (j >= registers) {
    922         machine_code[mc_ptr++] = 0x48 | (k > 7 ? 4 : 0);
    923         machine_code[mc_ptr++] = 0x0F;
    924         machine_code[mc_ptr++] = 0xAF;
    925         machine_code[mc_ptr++] = 0x45 + (k % 8) * 8;
    926         machine_code[mc_ptr++] = -regs[j].rbp;
    927         reg = k, l = j;
    928       } else {
    929         machine_code[mc_ptr++] = 0x48 | (j > 7 ? 4 : 0) | (k > 7 ? 1 : 0);
    930         machine_code[mc_ptr++] = 0x0F;
    931         machine_code[mc_ptr++] = 0xAF;
    932         machine_code[mc_ptr++] = 0xC0 + (j % 8) * 8 + (k % 8);
    933         reg = j, l = k;
    934       }
    935     } else {
    936       if (out_reg == k) {
    937         l = j;
    938         j = k;
    939         k = l;
    940       }
    941       if (j >= registers) {
    942         reg = get_free_reg(1);
    943         machine_code[mc_ptr++] = 0x48 | (reg > 7 ? 4 : 0);
    944         machine_code[mc_ptr++] = 0x8b;
    945         machine_code[mc_ptr++] = 0x45 + (reg % 8) * 8;
    946         machine_code[mc_ptr++] = -regs[j].rbp;
    947         j = reg;
    948         if (k >= registers) {
    949           machine_code[mc_ptr++] = 0x48 | (j > 7 ? 4 : 0);
    950           machine_code[mc_ptr++] = 0x0F;
    951           machine_code[mc_ptr++] = 0xAF;
    952           machine_code[mc_ptr++] = 0x45 + (j % 8) * 8;
    953           machine_code[mc_ptr++] = -regs[k].rbp;
    954         } else {
    955           machine_code[mc_ptr++] = 0x48 | (j > 7 ? 4 : 0) | (k > 7 ? 1 : 0);
    956           machine_code[mc_ptr++] = 0x0F;
    957           machine_code[mc_ptr++] = 0xAF;
    958           machine_code[mc_ptr++] = 0xC0 + (j % 8) * 8 + (k % 8);
    959           //machine_code[mc_ptr++] = -regs[j].rbp;
    960         }
    961       } else if (k >= registers) {
    962         machine_code[mc_ptr++] = 0x48 | (j > 7 ? 4 : 0);
    963         machine_code[mc_ptr++] = 0x0F;
    964         machine_code[mc_ptr++] = 0xAF;
    965         machine_code[mc_ptr++] = 0x45 + (j % 8) * 8;
    966         machine_code[mc_ptr++] = -regs[k].rbp;
    967       } else {
    968         machine_code[mc_ptr++] = 0x48 | (j > 7 ? 4 : 0) | (k > 7 ? 1 : 0);
    969         machine_code[mc_ptr++] = 0x0F;
    970         machine_code[mc_ptr++] = 0xAF;
    971         machine_code[mc_ptr++] = 0xC0 + (j % 8) * 8 + (k % 8);
    972         if (reg_hist[j].type & 2 && reg_hist[k].type & 2) {
    973           reg_hist[j].type = 2;
    974           reg_hist[j].val += reg_hist[k].val;
    975         } else if (reg_hist[j].type & 2) {
    976           reg_hist[j].type = 0;
    977         }
    978       }
    979       reg = j, l = k;
    980     }
    981     if (l < registers) used_regs &= ~(1 << l);
    982     break;
    983     /*
    984     j = compile_tree(output, tree->args, discard_result, -1);
    985     k = compile_tree(output, &tree->args[1], discard_result, -1);
    986     if (discard_result) {
    987       if (j < registers) used_regs &= ~(1 << j);
    988       if (k < registers) used_regs &= ~(1 << k);
    989       break;
    990     }
    991     reg = j;
    992     if ((out_reg == -1 || out_reg >= registers) && j >= registers) {
    993       reg = get_free_reg(1);
    994       if (j >= registers) {
    995         machine_code[mc_ptr++] = 0x48 | (reg > 7 ? 4 : 0);
    996         machine_code[mc_ptr++] = 0x8b;
    997         machine_code[mc_ptr++] = 0x45 + reg*8;
    998         machine_code[mc_ptr++] = -regs[j].rbp;
    999       } else {
   1000         machine_code[mc_ptr++] = 0x48 | (reg > 7 ? 4 : 0);
   1001         machine_code[mc_ptr++] = 0x8b;
   1002         machine_code[mc_ptr++] = 0x45 + reg*8;
   1003       }
   1004     }
   1005 
   1006     machine_code[mc_ptr++] = 0x48 | (reg > 7 ? 4 : 0);
   1007     machine_code[mc_ptr++] = 0x0F;
   1008     machine_code[mc_ptr++] = 0xAF;
   1009     if (k >= registers) {
   1010       machine_code[mc_ptr++] = 0x45 + (reg % 8) * 8;
   1011       machine_code[mc_ptr++] = -regs[k].rbp;
   1012     } else {
   1013       machine_code[mc_ptr-3] |= (k > 7 ? 1 : 0);
   1014       machine_code[mc_ptr++] = 0xC0 + (reg % 8) * 8 + (k % 8);
   1015       used_regs &= ~(1 << k);
   1016     }
   1017     break;
   1018     */
   1019   case divide:
   1020     if (discard_result) {
   1021       j = compile_tree(output, tree->args, 1, -1);
   1022       k = compile_tree(output, &tree->args[1], 1, -1);
   1023       if (j < registers) used_regs &= ~(1 << j);
   1024       break;
   1025     }
   1026     push(0, &pushed, push_order, "divide (rax)");
   1027     push(2, &pushed, push_order, "divide (rdx)");
   1028     j = compile_tree(output, tree->args, 0, 0);
   1029     machine_code[mc_ptr++] = 0x48;
   1030     machine_code[mc_ptr++] = 0x99;
   1031     used_regs |= (1 << 0) | (1 << 2);
   1032 
   1033     k = compile_tree(output, &tree->args[1], 0, -1);
   1034     machine_code[mc_ptr++] = 0x48;
   1035     machine_code[mc_ptr++] = 0xF7;
   1036     if (k >= registers) {
   1037       machine_code[mc_ptr++] = 0x7d;
   1038       machine_code[mc_ptr++] = -regs[k].rbp;
   1039     } else {
   1040       machine_code[mc_ptr-2] |= (k > 7 ? 1 : 0);
   1041       machine_code[mc_ptr++] = 0xf8 + (k % 8);
   1042       used_regs &= ~(1 << k);
   1043     }
   1044     reg = 0;
   1045     break;
   1046   case mod:
   1047     if (discard_result) {
   1048       j = compile_tree(output, tree->args, 1, -1);
   1049       k = compile_tree(output, &tree->args[1], 1, -1);
   1050       if (j < registers) used_regs &= ~(1 << j);
   1051       break;
   1052     }
   1053     push(0, &pushed, push_order, "mod (rax)");
   1054     push(2, &pushed, push_order, "mod (rdx)");
   1055     j = compile_tree(output, tree->args, 0, 0);
   1056     machine_code[mc_ptr++] = 0x48;
   1057     machine_code[mc_ptr++] = 0x99;
   1058     used_regs |= (1 << 0) | (1 << 2);
   1059 
   1060     k = compile_tree(output, &tree->args[1], 0, -1);
   1061     machine_code[mc_ptr++] = 0x48;
   1062     machine_code[mc_ptr++] = 0xF7;
   1063     if (k >= registers) {
   1064       machine_code[mc_ptr++] = 0x7d;
   1065       machine_code[mc_ptr++] = -regs[k].rbp;
   1066     } else {
   1067       machine_code[mc_ptr-2] |= (k > 7 ? 1 : 0);
   1068       machine_code[mc_ptr++] = 0xf8 + (k % 8);
   1069       used_regs &= ~(1 << k);
   1070     }
   1071     reg = 2;
   1072     break;
   1073   case shift_l:
   1074     j = compile_tree(output, tree->args, discard_result, out_reg);
   1075     k = compile_tree(output, &tree->args[1], discard_result, 1);
   1076     if (discard_result) {
   1077       if (j < registers) used_regs &= ~(1 << j);
   1078       if (k < registers) used_regs &= ~(1 << k);
   1079       break;
   1080     }
   1081     if (k != 1) {
   1082       if (used_regs & (1 << 1)) {
   1083         fprintf(stderr, "Not implemented yet! (rcx)\n");
   1084         exit(1);
   1085       }
   1086       used_regs |= (1 << 1);
   1087       if (k >= registers) {
   1088         machine_code[mc_ptr++] = 0x48;
   1089         machine_code[mc_ptr++] = 0x8b;
   1090         machine_code[mc_ptr++] = 0x4d;
   1091         machine_code[mc_ptr++] = -regs[k].rbp;
   1092       } else {
   1093         machine_code[mc_ptr++] = 0x48 | (k > 7 ? 1 : 0);
   1094         machine_code[mc_ptr++] = 0x8b;
   1095         machine_code[mc_ptr++] = 0xc8 + (k % 8);
   1096         used_regs &= ~(1 << k);
   1097       }
   1098       k = 1;
   1099     }
   1100     reg = j;
   1101     if (reg >= registers) {
   1102       reg = get_free_reg(1);
   1103       machine_code[mc_ptr++] = 0x48;
   1104       machine_code[mc_ptr++] = 0x8b;
   1105       machine_code[mc_ptr++] = 0x45 + reg*8;
   1106       machine_code[mc_ptr++] = -regs[j].rbp;
   1107     }
   1108     machine_code[mc_ptr++] = 0x48;
   1109     machine_code[mc_ptr++] = 0xd3;
   1110     machine_code[mc_ptr++] = 0xe0 + reg;
   1111 
   1112     if (k < registers) used_regs &= ~(1 << k);
   1113     break;
   1114   case shift_r:
   1115     j = compile_tree(output, tree->args, discard_result, out_reg);
   1116     k = compile_tree(output, &tree->args[1], discard_result, 1);
   1117     if (discard_result) {
   1118       if (j < registers) used_regs &= ~(1 << j);
   1119       if (k < registers) used_regs &= ~(1 << k);
   1120       break;
   1121     }
   1122     if (k != 1) {
   1123       if (used_regs & (1 << 1)) {
   1124         fprintf(stderr, "Not implemented yet! (rcx)\n");
   1125         exit(1);
   1126       }
   1127       used_regs |= (1 << 1);
   1128       if (k >= registers) {
   1129         machine_code[mc_ptr++] = 0x48;
   1130         machine_code[mc_ptr++] = 0x8b;
   1131         machine_code[mc_ptr++] = 0x4d;
   1132         machine_code[mc_ptr++] = -regs[k].rbp;
   1133       } else {
   1134         machine_code[mc_ptr++] = 0x48 | (k > 7 ? 1 : 0);
   1135         machine_code[mc_ptr++] = 0x8b;
   1136         machine_code[mc_ptr++] = 0xc8 + (k % 8);
   1137         used_regs &= ~(1 << k);
   1138       }
   1139       k = 1;
   1140     }
   1141     reg = j;
   1142     if (reg >= registers) {
   1143       reg = get_free_reg(1);
   1144       machine_code[mc_ptr++] = 0x48;
   1145       machine_code[mc_ptr++] = 0x8b;
   1146       machine_code[mc_ptr++] = 0x45 + reg*8;
   1147       machine_code[mc_ptr++] = -regs[j].rbp;
   1148     }
   1149     machine_code[mc_ptr++] = 0x48;
   1150     machine_code[mc_ptr++] = 0xd3;
   1151     machine_code[mc_ptr++] = 0xe8 + reg;
   1152 
   1153     if (k < registers) used_regs &= ~(1 << k);
   1154     break;
   1155   case b_and:
   1156     j = compile_tree(output, tree->args, discard_result, out_reg);
   1157     k = compile_tree(output, &tree->args[1], discard_result, -1);
   1158     if (discard_result) {
   1159       if (j < registers) used_regs &= ~(1 << j);
   1160       if (k < registers) used_regs &= ~(1 << k);
   1161       break;
   1162     }
   1163     reg = j;
   1164     if (reg >= registers) {
   1165       reg = get_free_reg(1);
   1166       machine_code[mc_ptr++] = 0x48 | (reg > 7 ? 4 : 0);
   1167       machine_code[mc_ptr++] = 0x8b;
   1168       machine_code[mc_ptr++] = 0x45 + (reg % 8) * 8;
   1169       machine_code[mc_ptr++] = -regs[j].rbp;
   1170     }
   1171     machine_code[mc_ptr++] = 0x48 | (reg > 7 ? 4 : 0);
   1172     machine_code[mc_ptr++] = 0x23;
   1173     if (tree->args[1].type == idnt) {
   1174       machine_code[mc_ptr++] = 0x45 + (reg % 8) * 8;
   1175       machine_code[mc_ptr++] = -regs[k].rbp;
   1176     } else {
   1177       machine_code[mc_ptr-2] |= k > 7 ? 1 : 0;
   1178       machine_code[mc_ptr++] = 0xC0 + (reg % 8) * 8 + (k % 8);
   1179     }
   1180     if (k < registers) used_regs &= ~(1 << k);
   1181     break;
   1182   case b_or:
   1183     j = compile_tree(output, tree->args, discard_result, out_reg);
   1184     k = compile_tree(output, &tree->args[1], discard_result, -1);
   1185     if (discard_result) {
   1186       if (j < registers) used_regs &= ~(1 << j);
   1187       if (k < registers) used_regs &= ~(1 << k);
   1188       break;
   1189     }
   1190     reg = j;
   1191     if (reg >= registers) {
   1192       reg = get_free_reg(1);
   1193       machine_code[mc_ptr++] = 0x48 | (reg > 7 ? 4 : 0);
   1194       machine_code[mc_ptr++] = 0x8b;
   1195       machine_code[mc_ptr++] = 0x45 + (reg % 8) * 8;
   1196       machine_code[mc_ptr++] = -regs[j].rbp;
   1197     }
   1198     machine_code[mc_ptr++] = 0x48 | (reg > 7 ? 4 : 0);
   1199     machine_code[mc_ptr++] = 0x0b;
   1200     if (tree->args[1].type == idnt) {
   1201       machine_code[mc_ptr++] = 0x45 + (reg % 8) * 8;
   1202       machine_code[mc_ptr++] = -regs[k].rbp;
   1203     } else {
   1204       machine_code[mc_ptr-2] |= k > 7 ? 1 : 0;
   1205       machine_code[mc_ptr++] = 0xC0 + (reg % 8) * 8 + (k % 8);
   1206     }
   1207     if (k < registers) used_regs &= ~(1 << k);
   1208     break;
   1209   case b_xor:
   1210     j = compile_tree(output, tree->args, discard_result, out_reg);
   1211     k = compile_tree(output, &tree->args[1], discard_result, -1);
   1212     if (discard_result) {
   1213       if (j < registers) used_regs &= ~(1 << j);
   1214       if (k < registers) used_regs &= ~(1 << k);
   1215       break;
   1216     }
   1217     reg = j;
   1218     if (reg >= registers) {
   1219       reg = get_free_reg(1);
   1220       machine_code[mc_ptr++] = 0x48 | (reg > 7 ? 4 : 0);
   1221       machine_code[mc_ptr++] = 0x8b;
   1222       machine_code[mc_ptr++] = 0x45 + (reg % 8) * 8;
   1223       machine_code[mc_ptr++] = -regs[j].rbp;
   1224     }
   1225     machine_code[mc_ptr++] = 0x48 | (reg > 7 ? 4 : 0);
   1226     machine_code[mc_ptr++] = 0x33;
   1227     if (tree->args[1].type == idnt) {
   1228       machine_code[mc_ptr++] = 0x45 + (reg % 8) * 8;
   1229       machine_code[mc_ptr++] = -regs[k].rbp;
   1230     } else {
   1231       machine_code[mc_ptr-2] |= k > 7 ? 1 : 0;
   1232       machine_code[mc_ptr++] = 0xC0 + (reg % 8) * 8 + (k % 8);
   1233     }
   1234     if (k < registers) used_regs &= ~(1 << k);
   1235     break;
   1236   case decl:
   1237     reg = next_reg++;
   1238     regs[reg].type = 1;
   1239     regs[reg].rbp = next_rbp;
   1240     next_rbp += 8;
   1241     regs[reg].var = tree->args->str;
   1242     break;
   1243   case set:
   1244     /*
   1245     reg = compile_tree(output, tree->args, 0, -1);
   1246     j = compile_tree(output, &tree->args[1], 0, reg);
   1247     break;
   1248   case set:
   1249   */
   1250     if (tree->args->type == deref)
   1251       reg = compile_tree(output, tree->args->args, 0, -1);
   1252     else
   1253       reg = compile_tree(output, tree->args, 0, -1);
   1254     if (reg >= registers && tree->args->type != deref) {
   1255       j = compile_tree(output, &tree->args[1], 0, reg);
   1256       break;
   1257     }
   1258     j = compile_tree(output, &tree->args[1], 0, -1);
   1259     if (j < 0) {
   1260       fprintf(stderr, "No rvalue for assignment\n");
   1261       exit(1);
   1262     }
   1263     if (j >= registers) {
   1264       k = get_free_reg(1);
   1265       machine_code[mc_ptr++] = 0x48 | (k > 7 ? 4 : 0);
   1266       machine_code[mc_ptr++] = 0x8b;
   1267       machine_code[mc_ptr++] = 0x45 + (k % 8) * 8;
   1268       machine_code[mc_ptr++] = -regs[j].rbp;
   1269     } else {
   1270       k = j;
   1271     }
   1272     if (tree->args->type == deref) {
   1273       if (reg >= registers) {
   1274         j = get_free_reg(1);
   1275         machine_code[mc_ptr++] = 0x48 | (j > 7 ? 4 : 0);
   1276         machine_code[mc_ptr++] = 0x8b;
   1277         machine_code[mc_ptr++] = 0x45 + (j % 8) * 8;
   1278         machine_code[mc_ptr++] = -regs[reg].rbp;
   1279         reg = j;
   1280       }
   1281       machine_code[mc_ptr++] = 0x48 | (reg > 7 ? 1 : 0) | (k > 7 ? 4 : 0);
   1282       machine_code[mc_ptr++] = 0x89;
   1283       machine_code[mc_ptr++] = 0x00 + (reg % 8) + (k % 8) * 8;
   1284     } else if (reg >= registers) {
   1285       machine_code[mc_ptr++] = 0x48 | (k > 7 ? 4 : 0);
   1286       machine_code[mc_ptr++] = 0x89;
   1287       machine_code[mc_ptr++] = 0x45 + (k % 8) * 8;
   1288       machine_code[mc_ptr++] = -regs[reg].rbp;
   1289     }
   1290     if (discard_result) {
   1291       used_regs &= ~(1 << k);
   1292       used_regs &= ~(1 << reg);
   1293       reg = -1;
   1294       break;
   1295     }
   1296     reg = k;
   1297     break;
   1298   case ref:
   1299     if (tree->args->type != idnt) {
   1300       fprintf(stderr, "Unable to reference non-identifier\n");
   1301       exit(1);
   1302     }
   1303     if (discard_result) break;
   1304     j = compile_tree(output, tree->args, 0, -1);
   1305     reg = out_reg;
   1306     if (out_reg < 0 || out_reg >= registers)
   1307       reg = get_free_reg(1);
   1308     used_regs |= (1 << reg);
   1309     machine_code[mc_ptr++] = 0x48 | (reg > 7 ? 4 : 0);
   1310     machine_code[mc_ptr++] = 0x8d;
   1311     machine_code[mc_ptr++] = 0x45 + (reg % 8) * 8;
   1312     machine_code[mc_ptr++] = -regs[j].rbp;
   1313     break;
   1314   case deref:
   1315     j = compile_tree(output, tree->args, discard_result, out_reg);
   1316     if (discard_result) {
   1317       if (used_regs & (1 << j)) used_regs &= ~(1 << j);
   1318       break;
   1319     }
   1320     reg = j;
   1321     if (j >= registers) {
   1322       reg = get_free_reg(1);
   1323       machine_code[mc_ptr++] = 0x48 | (reg > 7 ? 4 : 0);
   1324       machine_code[mc_ptr++] = 0x8b;
   1325       machine_code[mc_ptr++] = 0x45 + (reg % 8) * 8;
   1326       machine_code[mc_ptr++] = -regs[j].rbp;
   1327     }
   1328     machine_code[mc_ptr++] = 0x48 | (reg > 7 ? 5 : 0);
   1329     machine_code[mc_ptr++] = 0x8b;
   1330     machine_code[mc_ptr++] = 0x00 + (reg % 8) + (reg % 8) * 8;
   1331     break;
   1332   case idnt:
   1333     if (discard_result) break;
   1334     for (reg = registers; reg < 1024; reg++) {
   1335       if (regs[reg].type != 1) continue;
   1336       if (!strcmp(regs[reg].var, tree->str)) break;
   1337     }
   1338     if (reg == 1024) {
   1339       fprintf(stderr, "Unable to locate identifier <%s>\n", tree->str);
   1340       exit(1);
   1341     }
   1342     /*
   1343     for (i = 0; i < registers; i++) {
   1344       if (reg_hist[i].type & 1 && reg_hist[i].reg == reg && reg_hist[i].rev == regs[reg].rev) {
   1345         reg = i;
   1346         used_regs |= (1 << reg);
   1347         break;
   1348       }
   1349     }
   1350     */
   1351     break;
   1352   case number:
   1353     if (discard_result) break;
   1354     /*
   1355     for (i = 0; i < registers; i++) {
   1356       if (reg_hist[i].type & 2 && reg_hist[i].val == tree->i) {
   1357         reg = i;
   1358         break;
   1359       }
   1360     }
   1361     */
   1362     if (out_reg < 0 || out_reg >= registers)
   1363       reg = get_free_reg(1);
   1364     else
   1365       reg = out_reg;
   1366     if (tree->i) {
   1367       if (tree->i == 1) {
   1368         if (reg > 7)
   1369           machine_code[mc_ptr++] = 0x41;
   1370         machine_code[mc_ptr++] = 0x33;
   1371         machine_code[mc_ptr++] = 0xc0 + (reg % 8) + (reg % 8) * 8;
   1372         if (reg > 7)
   1373           machine_code[mc_ptr++] = 0x41;
   1374         machine_code[mc_ptr++] = 0xff;
   1375         machine_code[mc_ptr++] = 0xc0 + (reg % 8);
   1376       } else if (tree->i == -1) {
   1377         if (reg > 7)
   1378           machine_code[mc_ptr++] = 0x41;
   1379         machine_code[mc_ptr++] = 0x33;
   1380         machine_code[mc_ptr++] = 0xc0 + (reg % 8) + (reg % 8) * 8;
   1381 
   1382         machine_code[mc_ptr++] = 0x48 | (reg > 7 ? 1 : 0);
   1383         machine_code[mc_ptr++] = 0xff;
   1384         machine_code[mc_ptr++] = 0xc8 + (reg % 8);
   1385       } else if (tree->i <= 0x7FFFFFFF && tree->i > 0) {
   1386         if (reg > 7)
   1387           machine_code[mc_ptr++] = 0x41;
   1388         machine_code[mc_ptr++] = 0xb8 + (reg % 8);
   1389         *(int32_t *) &machine_code[mc_ptr] = (int) tree->i;
   1390         mc_ptr += 4;
   1391       } else if (tree->i < 0 && -tree->i <= 0x7FFFFFFF) {
   1392         machine_code[mc_ptr++] = 0x48 | (reg > 7 ? 1 : 0);
   1393         machine_code[mc_ptr++] = 0xc7;
   1394         machine_code[mc_ptr++] = 0xc0 + (reg % 8);
   1395         *(int32_t *) &machine_code[mc_ptr] = (int) tree->i;
   1396         mc_ptr += 4;
   1397       } else {
   1398         machine_code[mc_ptr++] = 0x48 | (reg > 7 ? 1 : 0);
   1399         machine_code[mc_ptr++] = 0xb8 + (reg % 8);
   1400         *(int64_t *) &machine_code[mc_ptr] = tree->i;
   1401         mc_ptr += 8;
   1402       }
   1403     } else {
   1404       if (reg > 7)
   1405         machine_code[mc_ptr++] = 0x45;
   1406       machine_code[mc_ptr++] = 0x33;
   1407       machine_code[mc_ptr++] = 0xc0 + (reg % 8) + (reg % 8) * 8;
   1408     }
   1409     reg_hist[reg].type = 2;
   1410     reg_hist[reg].val = tree->i;
   1411     break;
   1412   case string:
   1413     if (discard_result) break;
   1414     reg = out_reg;
   1415     if (reg == -1 || reg >= registers)
   1416       reg = get_free_reg(1);
   1417     if (!tree->i) {
   1418       strcpy(&rodata[rd_ptr], tree->str);
   1419       tree->i = rodata_addr + rd_ptr;
   1420       rd_ptr += strlen(tree->str) + 1;
   1421     }
   1422     machine_code[mc_ptr++] = 0x48 | (reg > 7 ? 1 : 0);
   1423     machine_code[mc_ptr++] = 0xb8 + (reg % 8);
   1424     *(int64_t *) &machine_code[mc_ptr] = tree->i;
   1425     mc_ptr += 8;
   1426     break;
   1427   case loop:
   1428     memset(reg_hist, 0, sizeof(reg_hist));
   1429     machine_code[mc_ptr++] = 0xe9;
   1430     l = mc_ptr;
   1431     mc_ptr += 4;
   1432     compile_tree(output, &tree->args[1], 1, -1);
   1433     *(int32_t *) &machine_code[l] = mc_ptr - l - 4;
   1434     switch (tree->args->type) {
   1435     case l_not:
   1436       j = compile_tree(output, tree->args->args, 0, -1);
   1437       if (j >= registers) {
   1438         machine_code[mc_ptr++] = 0x48;
   1439         machine_code[mc_ptr++] = 0x83;
   1440         machine_code[mc_ptr++] = 0x7d;
   1441         machine_code[mc_ptr++] = -regs[j].rbp;
   1442       } else {
   1443         machine_code[mc_ptr++] = 0x48 | (j > 7 ? 1 : 0);
   1444         machine_code[mc_ptr++] = 0x83;
   1445         machine_code[mc_ptr++] = 0xf8 + (j % 8);
   1446       }
   1447       machine_code[mc_ptr++] = 0x00;
   1448       machine_code[mc_ptr++] = 0x0f;
   1449       machine_code[mc_ptr++] = 0x84;
   1450       *(int32_t *) &machine_code[mc_ptr] = -(mc_ptr - l);
   1451       mc_ptr += 4;
   1452       break;
   1453     case l_eq:
   1454       j = compile_tree(output, tree->args->args, 0, -1);
   1455       k = compile_tree(output, &tree->args->args[1], 0, -1);
   1456       if (j >= registers) {
   1457         if (k >= registers) {
   1458           k = compile_tree(output, &tree->args->args[1], 0, get_free_reg(0));
   1459         }
   1460         machine_code[mc_ptr++] = 0x48 | (k > 7 ? 4 : 0);
   1461         machine_code[mc_ptr++] = 0x39;
   1462         machine_code[mc_ptr++] = 0x45 + (k % 8) * 8;
   1463         machine_code[mc_ptr++] = -regs[j].rbp;
   1464       } else {
   1465         machine_code[mc_ptr++] = 0x48 | (j > 7 ? 4 : 0);
   1466         machine_code[mc_ptr++] = 0x3b;
   1467         if (k >= registers) {
   1468           machine_code[mc_ptr++] = 0x45 + (j % 8) * 8;
   1469           machine_code[mc_ptr++] = -regs[k].rbp;
   1470         } else {
   1471           machine_code[mc_ptr-2] |= (k > 7 ? 1 : 0);
   1472           machine_code[mc_ptr++] = 0xc0 + (k % 8) + (j % 8) * 8;
   1473         }
   1474       }
   1475       machine_code[mc_ptr++] = 0x0f;
   1476       machine_code[mc_ptr++] = 0x84;
   1477       *(int32_t *) &machine_code[mc_ptr] = -(mc_ptr - l);
   1478       mc_ptr += 4;
   1479       break;
   1480     case l_lt:
   1481       j = compile_tree(output, tree->args->args, 0, -1);
   1482       k = compile_tree(output, &tree->args->args[1], 0, -1);
   1483       if (j >= registers) {
   1484         if (k >= registers) {
   1485           k = compile_tree(output, &tree->args->args[1], 0, get_free_reg(0));
   1486         }
   1487         machine_code[mc_ptr++] = 0x48 | (k > 7 ? 4 : 0);
   1488         machine_code[mc_ptr++] = 0x39;
   1489         machine_code[mc_ptr++] = 0x45 + (k % 8) * 8;
   1490         machine_code[mc_ptr++] = -regs[j].rbp;
   1491       } else {
   1492         machine_code[mc_ptr++] = 0x48 | (j > 7 ? 4 : 0);
   1493         machine_code[mc_ptr++] = 0x3b;
   1494         if (k >= registers) {
   1495           machine_code[mc_ptr++] = 0x45 + (j % 8) * 8;
   1496           machine_code[mc_ptr++] = -regs[k].rbp;
   1497         } else {
   1498           machine_code[mc_ptr-2] |= (k > 7 ? 1 : 0);
   1499           machine_code[mc_ptr++] = 0xc0 + (k % 8) + (j % 8) * 8;
   1500         }
   1501       }
   1502       machine_code[mc_ptr++] = 0x0f;
   1503       machine_code[mc_ptr++] = 0x8c;
   1504       *(int32_t *) &machine_code[mc_ptr] = -(mc_ptr - l);
   1505       mc_ptr += 4;
   1506       break;
   1507     default:
   1508       j = compile_tree(output, tree->args, 0, -1);
   1509       if (j >= registers) {
   1510         machine_code[mc_ptr++] = 0x48;
   1511         machine_code[mc_ptr++] = 0x83;
   1512         machine_code[mc_ptr++] = 0x7d;
   1513         machine_code[mc_ptr++] = -regs[j].rbp;
   1514       } else {
   1515         machine_code[mc_ptr++] = 0x48 | (j > 7 ? 1 : 0);
   1516         machine_code[mc_ptr++] = 0x83;
   1517         machine_code[mc_ptr++] = 0xf8 + (j % 8);
   1518       }
   1519       machine_code[mc_ptr++] = 0x00;
   1520       machine_code[mc_ptr++] = 0x0f;
   1521       machine_code[mc_ptr++] = 0x85;
   1522       *(int32_t *) &machine_code[mc_ptr] = -(mc_ptr - l);
   1523       mc_ptr += 4;
   1524       break;
   1525     }
   1526     used_regs = (1 << 5) | (1 << 4);
   1527     for (i = 0; i < registers; i++)
   1528       reg_hist[i].type = 0;
   1529     break;
   1530   case ifnz:
   1531     /*
   1532     j = compile_tree(output, tree->args, 0, -1);
   1533     if (j >= registers) {
   1534       machine_code[mc_ptr++] = 0x48;
   1535       machine_code[mc_ptr++] = 0x83;
   1536       machine_code[mc_ptr++] = 0x7d;
   1537       machine_code[mc_ptr++] = -regs[j].rbp;
   1538       machine_code[mc_ptr++] = 0x00;
   1539     } else {
   1540       machine_code[mc_ptr++] = 0x48 | (j > 7 ? 1 : 0);
   1541       machine_code[mc_ptr++] = 0x83;
   1542       machine_code[mc_ptr++] = 0xf8 + (j % 8);
   1543       machine_code[mc_ptr++] = 0x00;
   1544     }
   1545     //machine_code[mc_ptr++] = 0x00;
   1546     machine_code[mc_ptr++] = 0x0f;
   1547     machine_code[mc_ptr++] = 0x84;
   1548     k = mc_ptr;
   1549     mc_ptr += 4;
   1550     */
   1551     switch (tree->args->type) {
   1552     case l_not:
   1553       j = compile_tree(output, tree->args->args, 0, -1);
   1554       if (j >= registers) {
   1555         machine_code[mc_ptr++] = 0x48;
   1556         machine_code[mc_ptr++] = 0x83;
   1557         machine_code[mc_ptr++] = 0x7d;
   1558         machine_code[mc_ptr++] = -regs[j].rbp;
   1559       } else {
   1560         machine_code[mc_ptr++] = 0x48 | (j > 7 ? 1 : 0);
   1561         machine_code[mc_ptr++] = 0x83;
   1562         machine_code[mc_ptr++] = 0xf8 + (j % 8);
   1563       }
   1564       machine_code[mc_ptr++] = 0x00;
   1565       machine_code[mc_ptr++] = 0x0f;
   1566       machine_code[mc_ptr++] = 0x85;
   1567       //*(int32_t *) &machine_code[mc_ptr] = -(mc_ptr - l);
   1568       k = mc_ptr;
   1569       mc_ptr += 4;
   1570       break;
   1571     case l_eq:
   1572       j = compile_tree(output, tree->args->args, 0, -1);
   1573       k = compile_tree(output, &tree->args->args[1], 0, -1);
   1574       if (j >= registers) {
   1575         if (k >= registers) {
   1576           k = compile_tree(output, &tree->args->args[1], 0, get_free_reg(0));
   1577         }
   1578         machine_code[mc_ptr++] = 0x48 | (k > 7 ? 4 : 0);
   1579         machine_code[mc_ptr++] = 0x39;
   1580         machine_code[mc_ptr++] = 0x45 + (k % 8) * 8;
   1581         machine_code[mc_ptr++] = -regs[j].rbp;
   1582       } else {
   1583         machine_code[mc_ptr++] = 0x48 | (j > 7 ? 4 : 0);
   1584         machine_code[mc_ptr++] = 0x3b;
   1585         if (k >= registers) {
   1586           machine_code[mc_ptr++] = 0x45 + (j % 8) * 8;
   1587           machine_code[mc_ptr++] = -regs[k].rbp;
   1588         } else {
   1589           machine_code[mc_ptr-2] |= (k > 7 ? 1 : 0);
   1590           machine_code[mc_ptr++] = 0xc0 + (k % 8) + (j % 8) * 8;
   1591         }
   1592       }
   1593       machine_code[mc_ptr++] = 0x0f;
   1594       machine_code[mc_ptr++] = 0x85;
   1595       //*(int32_t *) &machine_code[mc_ptr] = -(mc_ptr - l);
   1596       k = mc_ptr;
   1597       mc_ptr += 4;
   1598       break;
   1599     case l_lt:
   1600       j = compile_tree(output, tree->args->args, 0, -1);
   1601       k = compile_tree(output, &tree->args->args[1], 0, -1);
   1602       if (j >= registers) {
   1603         if (k >= registers) {
   1604           k = compile_tree(output, &tree->args->args[1], 0, get_free_reg(0));
   1605         }
   1606         machine_code[mc_ptr++] = 0x48 | (k > 7 ? 4 : 0);
   1607         machine_code[mc_ptr++] = 0x39;
   1608         machine_code[mc_ptr++] = 0x45 + (k % 8) * 8;
   1609         machine_code[mc_ptr++] = -regs[j].rbp;
   1610       } else {
   1611         machine_code[mc_ptr++] = 0x48 | (j > 7 ? 4 : 0);
   1612         machine_code[mc_ptr++] = 0x3b;
   1613         if (k >= registers) {
   1614           machine_code[mc_ptr++] = 0x45 + (j % 8) * 8;
   1615           machine_code[mc_ptr++] = -regs[k].rbp;
   1616         } else {
   1617           machine_code[mc_ptr-2] |= (k > 7 ? 1 : 0);
   1618           machine_code[mc_ptr++] = 0xc0 + (k % 8) + (j % 8) * 8;
   1619         }
   1620       }
   1621       machine_code[mc_ptr++] = 0x0f;
   1622       machine_code[mc_ptr++] = 0x8d;
   1623       //*(int32_t *) &machine_code[mc_ptr] = -(mc_ptr - l);
   1624       k = mc_ptr;
   1625       mc_ptr += 4;
   1626       break;
   1627     case b_and:
   1628       j = compile_tree(output, tree->args->args, 0, -1);
   1629       k = compile_tree(output, &tree->args->args[1], 0, -1);
   1630       if (j >= registers) {
   1631         if (k >= registers) {
   1632           k = compile_tree(output, &tree->args->args[1], 0, get_free_reg(0));
   1633         }
   1634         machine_code[mc_ptr++] = 0x48 | (k > 7 ? 4 : 0);
   1635         machine_code[mc_ptr++] = 0x85;
   1636         machine_code[mc_ptr++] = 0x45 + (k % 8) * 8;
   1637         machine_code[mc_ptr++] = -regs[j].rbp;
   1638       } else {
   1639         machine_code[mc_ptr++] = 0x48 | (j > 7 ? 4 : 0);
   1640         machine_code[mc_ptr++] = 0x85;
   1641         if (k >= registers) {
   1642           machine_code[mc_ptr++] = 0x45 + (j % 8) * 8;
   1643           machine_code[mc_ptr++] = -regs[k].rbp;
   1644         } else {
   1645           machine_code[mc_ptr-2] |= (k > 7 ? 1 : 0);
   1646           machine_code[mc_ptr++] = 0xc0 + (k % 8) + (j % 8) * 8;
   1647         }
   1648       }
   1649       machine_code[mc_ptr++] = 0x0f;
   1650       machine_code[mc_ptr++] = 0x84;
   1651       //*(int32_t *) &machine_code[mc_ptr] = -(mc_ptr - l);
   1652       k = mc_ptr;
   1653       mc_ptr += 4;
   1654       break;
   1655     default:
   1656       j = compile_tree(output, tree->args, 0, -1);
   1657       if (j >= registers) {
   1658         machine_code[mc_ptr++] = 0x48;
   1659         machine_code[mc_ptr++] = 0x83;
   1660         machine_code[mc_ptr++] = 0x7d;
   1661         machine_code[mc_ptr++] = -regs[j].rbp;
   1662       } else {
   1663         machine_code[mc_ptr++] = 0x48 | (j > 7 ? 1 : 0);
   1664         machine_code[mc_ptr++] = 0x83;
   1665         machine_code[mc_ptr++] = 0xf8 + (j % 8);
   1666       }
   1667       machine_code[mc_ptr++] = 0x00;
   1668       machine_code[mc_ptr++] = 0x0f;
   1669       machine_code[mc_ptr++] = 0x84;
   1670       //*(int32_t *) &machine_code[mc_ptr] = -(mc_ptr - l);
   1671       k = mc_ptr;
   1672       mc_ptr += 4;
   1673       break;
   1674     }
   1675     // True
   1676     used_regs = (1 << 5) | (1 << 4);
   1677     compile_tree(output, &tree->args[1], 1, -1);
   1678     if (tree->args_count == 3) {
   1679       machine_code[mc_ptr++] = 0xe9;
   1680       l = mc_ptr;
   1681       *(int32_t *) &machine_code[mc_ptr] = 0x00;
   1682       mc_ptr += 4;
   1683       // Else
   1684       *(int32_t *) &machine_code[k] = mc_ptr - k - 4;
   1685       compile_tree(output, &tree->args[2], 1, -1);
   1686       *(int32_t *) &machine_code[l] = mc_ptr - l - 4;
   1687     } else {
   1688       *(int32_t *) &machine_code[k] = mc_ptr - k - 4;
   1689     }
   1690     used_regs = (1 << 5) | (1 << 4);
   1691     for (i = 0; i < registers; i++)
   1692       reg_hist[i].type = 0;
   1693     break;
   1694   case l_not:
   1695     j = compile_tree(output, tree->args, discard_result, out_reg);
   1696     if (discard_result) {
   1697       if (j < registers) used_regs &= ~(1 << j);
   1698       break;
   1699     }
   1700     reg = j;
   1701     if (j >= registers) {
   1702       reg = get_free_reg(1);
   1703       machine_code[mc_ptr++] = 0x48;
   1704       machine_code[mc_ptr++] = 0x83;
   1705       machine_code[mc_ptr++] = 0x7d;
   1706       machine_code[mc_ptr++] = -regs[j].rbp;
   1707     } else {
   1708       machine_code[mc_ptr++] = 0x48 | (reg > 7 ? 1 : 0);
   1709       machine_code[mc_ptr++] = 0x83;
   1710       machine_code[mc_ptr++] = 0xf8 + (reg % 8);
   1711     }
   1712     machine_code[mc_ptr++] = 0x00;
   1713     machine_code[mc_ptr++] = 0x74;
   1714     machine_code[mc_ptr++] = 0x05;
   1715     // Not zero
   1716     machine_code[mc_ptr++] = 0x48 | (reg > 7 ? 5 : 0);
   1717     machine_code[mc_ptr++] = 0x33;
   1718     machine_code[mc_ptr++] = 0xc0 + (reg % 8) + (reg % 8) * 8;
   1719     machine_code[mc_ptr++] = 0xeb;
   1720     machine_code[mc_ptr++] = 0x0a;
   1721     // Zero
   1722     machine_code[mc_ptr++] = 0x48 + (reg > 7 ? 1 : 0);
   1723     machine_code[mc_ptr++] = 0xb8 + (reg % 8);
   1724     *(int64_t *) &machine_code[mc_ptr] = 1;
   1725     mc_ptr += 8;
   1726     break;
   1727   case l_and:
   1728     if (tree->args->type == number)
   1729       k = tree->args->i, l = 1;
   1730     else
   1731       l = 0;
   1732     if (l) {
   1733       if (k)
   1734         reg = compile_tree(output, &tree->args[1], discard_result, out_reg);
   1735       else
   1736         reg = compile_tree(output, tree->args, discard_result, out_reg);
   1737       break;
   1738     }
   1739     j = compile_tree(output, tree->args, discard_result, out_reg);
   1740     reg = j;
   1741     if (j >= registers) {
   1742       reg = get_free_reg(1);
   1743       machine_code[mc_ptr++] = 0x48;
   1744       machine_code[mc_ptr++] = 0x83;
   1745       machine_code[mc_ptr++] = 0x7d;
   1746       machine_code[mc_ptr++] = -regs[j].rbp;
   1747     } else {
   1748       machine_code[mc_ptr++] = 0x48 | (reg > 7 ? 1 : 0);
   1749       machine_code[mc_ptr++] = 0x83;
   1750       machine_code[mc_ptr++] = 0xf8 + (reg % 8);
   1751     }
   1752     machine_code[mc_ptr++] = 0x00;
   1753 
   1754     machine_code[mc_ptr++] = 0x0f;
   1755     machine_code[mc_ptr++] = 0x84;
   1756     //machine_code[mc_ptr++] = 0x05;
   1757     l = mc_ptr;
   1758     mc_ptr += 4;
   1759     // Not zero
   1760     compile_tree(output, &tree->args[1], discard_result, reg);
   1761     if (discard_result) {
   1762       *(int32_t *) &machine_code[l] = mc_ptr - l;
   1763       if (reg < registers) used_regs &= ~(1 << reg);
   1764       break;
   1765     }
   1766     machine_code[mc_ptr++] = 0xeb;
   1767     machine_code[mc_ptr++] = 0x03;
   1768     *(int32_t *) &machine_code[l] = mc_ptr - l - 4;
   1769     // Zero
   1770     machine_code[mc_ptr++] = 0x48 + (reg > 7 ? 5 : 0);
   1771     machine_code[mc_ptr++] = 0x33;
   1772     machine_code[mc_ptr++] = 0xc0 + (reg % 8) * 8 + (reg % 8);
   1773     break;
   1774   case l_or:
   1775     if (has_sideeffect(tree->args) || has_sideeffect(&tree->args[1]) ||
   1776         !discard_result) {
   1777       if (tree->args->type == number)
   1778         k = tree->args->i, l = 1;
   1779       else
   1780         l = 0;
   1781       if (l) {
   1782         if (k)
   1783           reg = compile_tree(output, tree->args, discard_result, out_reg);
   1784         else
   1785           reg = compile_tree(output, &tree->args[1], discard_result, out_reg);
   1786         break;
   1787       }
   1788       j = compile_tree(output, tree->args, 0, out_reg);
   1789       reg = j;
   1790       if (j >= registers) {
   1791         reg = get_free_reg(1);
   1792         machine_code[mc_ptr++] = 0x48;
   1793         machine_code[mc_ptr++] = 0x83;
   1794         machine_code[mc_ptr++] = 0x7d;
   1795         machine_code[mc_ptr++] = -regs[j].rbp;
   1796       } else {
   1797         machine_code[mc_ptr++] = 0x48 | (reg > 7 ? 1 : 0);
   1798         machine_code[mc_ptr++] = 0x83;
   1799         machine_code[mc_ptr++] = 0xf8 + (reg % 8);
   1800       }
   1801       machine_code[mc_ptr++] = 0x00;
   1802     }
   1803 
   1804     if (has_sideeffect(&tree->args[1]) || !discard_result) {
   1805       machine_code[mc_ptr++] = 0x0f;
   1806       machine_code[mc_ptr++] = 0x85;
   1807       l = mc_ptr;
   1808       mc_ptr += 4;
   1809       compile_tree(output, &tree->args[1], discard_result, reg);
   1810       *(int32_t *) &machine_code[l] = mc_ptr - l - 4;
   1811     }
   1812     if (discard_result) {
   1813       if (reg >= 0 && reg < registers) used_regs &= ~(1 << reg);
   1814       break;
   1815     }
   1816     break;
   1817   case l_eq:
   1818     j = compile_tree(output, tree->args, discard_result, -1);
   1819     k = compile_tree(output, &tree->args[1], discard_result, -1);
   1820     if (discard_result) {
   1821       if (j < registers) used_regs &= ~(1 << j);
   1822       if (k < registers) used_regs &= ~(1 << k);
   1823       break;
   1824     }
   1825     reg = k;
   1826 
   1827     if (j >= registers) {
   1828       if (k >= registers) {
   1829         reg = get_free_reg(1);
   1830         machine_code[mc_ptr++] = 0x48 | (reg > 7 ? 4 : 0);
   1831         machine_code[mc_ptr++] = 0x8b;
   1832         machine_code[mc_ptr++] = 0x45 + (reg % 8) * 8;
   1833         machine_code[mc_ptr++] = -regs[k].rbp;
   1834         k = reg;
   1835       }
   1836       machine_code[mc_ptr++] = 0x48 | (k > 7 ? 4 : 0);
   1837       machine_code[mc_ptr++] = 0x39;
   1838       machine_code[mc_ptr++] = 0x45 + (k % 8) * 8;
   1839       machine_code[mc_ptr++] = -regs[j].rbp;
   1840     } else if (k >= registers) {
   1841       machine_code[mc_ptr++] = 0x48 | (j > 7 ? 4 : 0);
   1842       machine_code[mc_ptr++] = 0x3b;
   1843       machine_code[mc_ptr++] = 0x45 + (j % 8) * 8;
   1844       machine_code[mc_ptr++] = -regs[k].rbp;
   1845     } else {
   1846       machine_code[mc_ptr++] = 0x48 | (j > 7 ? 1 : 0) | (k > 7 ? 4 : 0);
   1847       machine_code[mc_ptr++] = 0x39;
   1848       machine_code[mc_ptr++] = 0xc0 + (j % 8) + (k % 8) * 8;
   1849       used_regs &= ~(1 << k);
   1850     }
   1851     if (j < registers && k >= registers) used_regs &= ~(1 << reg), reg = j;
   1852     machine_code[mc_ptr++] = 0x74;
   1853     machine_code[mc_ptr++] = 0x05; //Offset
   1854     // Not less than:
   1855     machine_code[mc_ptr++] = 0x48 | (reg > 7 ? 5 : 0);
   1856     machine_code[mc_ptr++] = 0x33;
   1857     machine_code[mc_ptr++] = 0xc0 + (reg % 8) + (reg % 8) * 8;
   1858     machine_code[mc_ptr++] = 0xeb;
   1859     machine_code[mc_ptr++] = 0x0a;
   1860     // Less than:
   1861     machine_code[mc_ptr++] = 0x48 + (reg > 7 ? 1 : 0);
   1862     machine_code[mc_ptr++] = 0xb8 + (reg % 8);
   1863     *(int64_t *) &machine_code[mc_ptr] = 1;
   1864     mc_ptr += 8;
   1865     break;
   1866   case l_lt:
   1867     j = compile_tree(output, tree->args, discard_result, -1);
   1868     k = compile_tree(output, &tree->args[1], discard_result, -1);
   1869     if (discard_result) {
   1870       if (j < registers) used_regs &= ~(1 << j);
   1871       if (k < registers) used_regs &= ~(1 << k);
   1872       break;
   1873     }
   1874 
   1875     reg = j;
   1876     if (j >= registers) {
   1877       reg = k;
   1878       if (k >= registers) {
   1879         reg = get_free_reg(1);
   1880         machine_code[mc_ptr++] = 0x48 | (reg > 7 ? 4 : 0);
   1881         machine_code[mc_ptr++] = 0x8b;
   1882         machine_code[mc_ptr++] = 0x45 + (reg % 8) * 8;
   1883         machine_code[mc_ptr++] = -regs[k].rbp;
   1884         k = reg;
   1885       }
   1886       machine_code[mc_ptr++] = 0x48 | (k > 7 ? 4 : 0);
   1887       machine_code[mc_ptr++] = 0x39;
   1888       machine_code[mc_ptr++] = 0x45 + (k % 8) * 8;
   1889       machine_code[mc_ptr++] = -regs[j].rbp;
   1890     } else if (k >= registers) {
   1891       machine_code[mc_ptr++] = 0x48 | (j > 7 ? 4 : 0);
   1892       machine_code[mc_ptr++] = 0x3b;
   1893       machine_code[mc_ptr++] = 0x45 + (j % 8) * 8;
   1894       machine_code[mc_ptr++] = -regs[k].rbp;
   1895     } else {
   1896       machine_code[mc_ptr++] = 0x48 | (j > 7 ? 1 : 0) | (k > 7 ? 4 : 0);
   1897       machine_code[mc_ptr++] = 0x39;
   1898       machine_code[mc_ptr++] = 0xc0 + (j % 8) + (k % 8) * 8;
   1899       used_regs &= ~(1 << k);
   1900     }
   1901     if (reg != out_reg && out_reg >= 0) {
   1902       used_regs &= ~(1 << reg);
   1903       reg = out_reg;
   1904     }
   1905     machine_code[mc_ptr++] = 0x7c;
   1906     machine_code[mc_ptr++] = 0x05; //Offset
   1907     // Not less than:
   1908     machine_code[mc_ptr++] = 0x48 | (reg > 7 ? 5 : 0);
   1909     machine_code[mc_ptr++] = 0x33;
   1910     machine_code[mc_ptr++] = 0xc0 + (reg % 8) + (reg % 8) * 8;
   1911     machine_code[mc_ptr++] = 0xeb;
   1912     machine_code[mc_ptr++] = 0x0a;
   1913     // Less than:
   1914     machine_code[mc_ptr++] = 0x48 + (reg > 7 ? 1 : 0);
   1915     machine_code[mc_ptr++] = 0xb8 + (reg % 8);
   1916     *(int64_t *) &machine_code[mc_ptr] = 1;
   1917     mc_ptr += 8;
   1918     break;
   1919   case ret:
   1920     compile_tree(output, tree->args, 0, 0);
   1921     machine_code[mc_ptr++] = 0xc9;
   1922     machine_code[mc_ptr++] = 0xc3;
   1923     return -3;
   1924   case _syscall:
   1925     push(0, &pushed, push_order, "readstring (rax)");
   1926     if (tree->args[1].type != comma) {
   1927       push(syscall_arg[0], &pushed, push_order, "readstring (syscall_arg 0)");
   1928       compile_tree(output, &tree->args->args[0], 0, syscall_arg[0]);
   1929       i = 1;
   1930     } else {
   1931       for (i = 0; i < tree->args[1].args_count; i++) {
   1932         push(syscall_arg[i], &pushed, push_order, "readstring (syscall_arg loop)");
   1933         compile_tree(output, &tree->args[1].args[i], 0, syscall_arg[i]);
   1934       }
   1935     }
   1936 
   1937     compile_tree(output, tree->args, 0, 0);
   1938 
   1939     machine_code[mc_ptr++] = 0x0f;
   1940     machine_code[mc_ptr++] = 0x05;
   1941     for (j = 0; j < i; j++)
   1942       used_regs &= ~(1 << syscall_arg[j]);
   1943     reg = 0;
   1944     break;
   1945   case readstring:
   1946     push(0, &pushed, push_order, "readstring (rax)");
   1947     push(syscall_arg[0], &pushed, push_order, "readstring (syscall_arg 0)");
   1948     push(syscall_arg[1], &pushed, push_order, "readstring (syscall_arg 1)");
   1949     push(syscall_arg[2], &pushed, push_order, "readstring (syscall_arg 2)");
   1950     compile_tree(output, &tree->args->args[0], 0, syscall_arg[0]);
   1951     compile_tree(output, &tree->args->args[1], 0, syscall_arg[1]);
   1952     compile_tree(output, &tree->args->args[2], 0, syscall_arg[2]);
   1953 
   1954     compile_tree(output, ZERO, 0, 0);
   1955     /*
   1956     machine_code[mc_ptr++] = 0x48;
   1957     machine_code[mc_ptr++] = 0xb8;
   1958     *(int64_t *) &machine_code[mc_ptr] = 0x00;
   1959     mc_ptr += 8;
   1960     */
   1961 
   1962     machine_code[mc_ptr++] = 0x0f;
   1963     machine_code[mc_ptr++] = 0x05;
   1964     used_regs &= ~(1 << syscall_arg[0]);
   1965     used_regs &= ~(1 << syscall_arg[1]);
   1966     used_regs &= ~(1 << syscall_arg[2]);
   1967     reg = 0;
   1968     break;
   1969   case writestring:
   1970     push(0, &pushed, push_order, "writestring (rax)");
   1971     push(syscall_arg[0], &pushed, push_order, "writestring (syscall_arg 0)");
   1972     push(syscall_arg[1], &pushed, push_order, "writestring (syscall_arg 1)");
   1973     push(syscall_arg[2], &pushed, push_order, "writestring (syscall_arg 2)");
   1974     compile_tree(output, &tree->args->args[0], 0, syscall_arg[0]);
   1975     used_regs |= (1 << syscall_arg[0]);
   1976     compile_tree(output, &tree->args->args[1], 0, syscall_arg[1]);
   1977     used_regs |= (1 << syscall_arg[1]);
   1978     compile_tree(output, &tree->args->args[2], 0, syscall_arg[2]);
   1979     used_regs |= (1 << syscall_arg[2]);
   1980 
   1981     compile_tree(output, ONE, 0, 0);
   1982     /*
   1983     machine_code[mc_ptr++] = 0x48;
   1984     machine_code[mc_ptr++] = 0xb8;
   1985     *(int64_t *) &machine_code[mc_ptr] = 0x01;
   1986     mc_ptr += 8;
   1987     */
   1988 
   1989     machine_code[mc_ptr++] = 0x0f;
   1990     machine_code[mc_ptr++] = 0x05;
   1991     used_regs &= ~(1 << syscall_arg[0]);
   1992     used_regs &= ~(1 << syscall_arg[1]);
   1993     used_regs &= ~(1 << syscall_arg[2]);
   1994     reg = 0;
   1995     break;
   1996   case printchar:
   1997     push(0, &pushed, push_order, "printchar (rax)");
   1998     push(syscall_arg[0], &pushed, push_order, "printchar (syscall_arg 0)");
   1999     push(syscall_arg[1], &pushed, push_order, "printchar (syscall_arg 1)");
   2000     push(syscall_arg[2], &pushed, push_order, "printchar (syscall_arg 2)");
   2001 
   2002     j = compile_tree(output, tree->args, 0, syscall_arg[1]);
   2003 
   2004     // Allocate extra space on the stack for the character
   2005     // Because of scratch space, this might be unnecessary
   2006     machine_code[mc_ptr++] = 0x48;
   2007     machine_code[mc_ptr++] = 0x83;
   2008     machine_code[mc_ptr++] = 0xec;
   2009     machine_code[mc_ptr++] = 0x08;
   2010 
   2011     machine_code[mc_ptr++] = 0x48 | (j > 7 ? 4 : 0);
   2012     machine_code[mc_ptr++] = 0x89;
   2013     machine_code[mc_ptr++] = 0x45 + (j % 8) * 8;
   2014     machine_code[mc_ptr++] = -next_rbp;
   2015 
   2016     machine_code[mc_ptr++] = 0x48 | (j > 7 ? 4 : 0);
   2017     machine_code[mc_ptr++] = 0x8d;
   2018     machine_code[mc_ptr++] = 0x45 + (j % 8) * 8;
   2019     machine_code[mc_ptr++] = -next_rbp;
   2020 
   2021 
   2022     compile_tree(output, ONE, 0, 0);
   2023     /*
   2024     machine_code[mc_ptr++] = 0x48;
   2025     machine_code[mc_ptr++] = 0xb8;
   2026     *(int64_t *) &machine_code[mc_ptr] = 0x01;
   2027     mc_ptr += 8;
   2028     */
   2029     machine_code[mc_ptr++] = 0x48 | (arg_order[0] > 7 ? 1 : 0);
   2030     machine_code[mc_ptr++] = 0x89;
   2031     machine_code[mc_ptr++] = 0xc0 + (arg_order[0] % 8);
   2032     machine_code[mc_ptr++] = 0x48 | (arg_order[2] > 7 ? 1 : 0);
   2033     machine_code[mc_ptr++] = 0x89;
   2034     machine_code[mc_ptr++] = 0xc0 + (arg_order[2] % 8);
   2035 
   2036     machine_code[mc_ptr++] = 0x0f;
   2037     machine_code[mc_ptr++] = 0x05;
   2038 
   2039     machine_code[mc_ptr++] = 0x48;
   2040     machine_code[mc_ptr++] = 0x83;
   2041     machine_code[mc_ptr++] = 0xc4;
   2042     machine_code[mc_ptr++] = 0x08;
   2043 
   2044     used_regs &= ~(1 << syscall_arg[0]);
   2045     used_regs &= ~(1 << syscall_arg[1]);
   2046     used_regs &= ~(1 << syscall_arg[2]);
   2047     reg = 0;
   2048     break;
   2049   case brk_sys:
   2050     push(0, &pushed, push_order, "brk_sys (rax)");
   2051     push(syscall_arg[0], &pushed, push_order, "brk_sys (syscall_arg 0)");
   2052     j = compile_tree(output, tree->args, 0, syscall_arg[0]);
   2053     machine_code[mc_ptr++] = 0xb8;
   2054     *(int32_t *) &machine_code[mc_ptr] = 0x0c;
   2055     mc_ptr += 4;
   2056     machine_code[mc_ptr++] = 0x0f;
   2057     machine_code[mc_ptr++] = 0x05;
   2058     reg = 0;
   2059     break;
   2060   case exit_p:
   2061     j = compile_tree(output, tree->args, 0, syscall_arg[0]);
   2062     machine_code[mc_ptr++] = 0xb8;
   2063     *(int32_t *) &machine_code[mc_ptr] = 0x3c;
   2064     mc_ptr += 4;
   2065     machine_code[mc_ptr++] = 0x0f;
   2066     machine_code[mc_ptr++] = 0x05;
   2067     return -2;
   2068   }
   2069   if (!discard_result) {
   2070     if (reg < 0) {
   2071       fprintf(stderr, "No value in <reg>\n");
   2072       fprintf(stderr, "type: %s\n", exp_str[tree->type]);
   2073       exit(1);
   2074     }
   2075     if (out_reg == reg || out_reg < 0 && !(pushed & (1 << reg))) {
   2076       out_reg = reg;
   2077       used_regs |= (1 << out_reg);
   2078       goto pop_used;
   2079     } else if (out_reg < 0) {
   2080       k = used_regs;
   2081       used_regs |= pushed;
   2082       out_reg = get_free_reg(1);
   2083       used_regs = k;
   2084       used_regs |= (1 << out_reg);
   2085     }
   2086     if (reg >= registers && out_reg >= registers) {
   2087       j = get_free_reg(0);
   2088       machine_code[mc_ptr++] = 0x48 | (j > 7 ? 4 : 0);
   2089       machine_code[mc_ptr++] = 0x8b;
   2090       machine_code[mc_ptr++] = 0x45 + (j % 8) * 8;
   2091       machine_code[mc_ptr++] = -regs[reg].rbp;
   2092       
   2093       machine_code[mc_ptr++] = 0x48 | (j > 7 ? 4 : 0);
   2094       machine_code[mc_ptr++] = 0x89;
   2095       machine_code[mc_ptr++] = 0x45 + (j % 8) * 8;
   2096       machine_code[mc_ptr++] = -regs[out_reg].rbp;
   2097       regs[out_reg].rev++;
   2098     } else if (reg >= registers && out_reg < registers) {
   2099       machine_code[mc_ptr++] = 0x48 | (out_reg > 7 ? 4 : 0);
   2100       machine_code[mc_ptr++] = 0x8b;
   2101       machine_code[mc_ptr++] = 0x45 + (out_reg % 8) * 8;
   2102       machine_code[mc_ptr++] = -regs[reg].rbp;
   2103       reg_hist[out_reg].type = 1;
   2104       reg_hist[out_reg].reg = reg;
   2105       reg_hist[out_reg].rev = ++regs[reg].rev;
   2106     } else {
   2107       machine_code[mc_ptr++] = 0x48 | (reg > 7 ? 4 : 0);
   2108       machine_code[mc_ptr++] = 0x89;
   2109       if (out_reg >= registers) {
   2110         machine_code[mc_ptr++] = 0x45 + (reg % 8) * 8;
   2111         machine_code[mc_ptr++] = -regs[out_reg].rbp;
   2112         reg_hist[reg].type |= 1;
   2113         reg_hist[reg].reg = reg;
   2114         reg_hist[reg].rev = ++regs[out_reg].rev;
   2115       } else {
   2116         machine_code[mc_ptr-2] |= (out_reg > 7 ? 1 : 0);
   2117         machine_code[mc_ptr++] = 0xc0 + (out_reg % 8) + (reg % 8) * 8;
   2118         memcpy(&reg_hist[out_reg], &reg_hist[reg], sizeof(struct reg_history));
   2119         used_regs |= (1 << out_reg);
   2120       }
   2121       used_regs &= ~(1 << reg);
   2122     }
   2123   }
   2124 pop_used:
   2125   if (pushed)
   2126     for (i = registers-1; i >= 0; i--) {
   2127       if (push_order[i] >= 0) pop(push_order[i], &pushed);
   2128     }
   2129 end:
   2130   return out_reg;
   2131 }
   2132 
   2133 struct elf_hdr {
   2134   unsigned int magic;
   2135   unsigned char class;
   2136   unsigned char endianness;
   2137   unsigned char version;
   2138   unsigned char abi;
   2139   unsigned char abi_version;
   2140   unsigned char pad[7];
   2141   unsigned short type;
   2142   unsigned short arch;
   2143   unsigned int version2;
   2144   unsigned long entry;
   2145   unsigned long phoff;
   2146   unsigned long shoff;
   2147   unsigned int flags;
   2148   unsigned short ehsize;
   2149   unsigned short phsize;
   2150   unsigned short phcount;
   2151   unsigned short shsize;
   2152   unsigned short shcount;
   2153   unsigned short shstrindx;
   2154 } __attribute((packed));
   2155 
   2156 struct prg_hdr {
   2157   unsigned int type;
   2158   unsigned int flags;
   2159   unsigned long offset;
   2160   unsigned long vaddr;
   2161   unsigned long paddr;
   2162   unsigned long fsize;
   2163   unsigned long msize;
   2164   unsigned long align;
   2165 } __attribute((packed));
   2166 
   2167 struct sec_hdr {
   2168   unsigned int name;
   2169   unsigned int type;
   2170   unsigned long flags;
   2171   unsigned long addr;
   2172   unsigned long offset;
   2173   unsigned long size;
   2174   unsigned int link;
   2175   unsigned int info;
   2176   unsigned long align;
   2177   unsigned long esize;
   2178 } __attribute((packed));
   2179 
   2180 struct elf_hdr elf_hdr = { 0x464c457f, 2, 1, 1, 0, 0, { 0 }, 2, 0x3e, 1, 0, 0x40, 0, 0, 0x40, 0x38, 0, 0x40, 0, 0 };
   2181 struct prg_hdr load_text =   { 1, 5, 0, 0, 0, 0, 0, 1 };
   2182 struct prg_hdr load_rodata = { 1, 4, 0, 0, 0, 0, 0, 1 };
   2183 struct sec_hdr null_section = { 0 };
   2184 struct sec_hdr text_section = { 1, 1, 6, 0, 0, 0, 0, 0, 1, 0 };
   2185 struct sec_hdr rodata_section = { 7, 1, 2, 0, 0, 0, 0, 0, 1, 0 };
   2186 struct sec_hdr strtab_section = { 15, 3, 0, 0, 0, 0, 0, 0, 1, 0 };
   2187 char strtab[] = "\0.text\0.rodata\0.strtab";
   2188 
   2189 char padding[4096] = { 0 };
   2190 
   2191 int main(int argc, char **argv)
   2192 {
   2193   int failed = 0, i, outfd, use_rodata = 1, flag_s = 0, first_arg = 1;
   2194 
   2195   if (argc > 1 && argv[1][0] == '-' && argv[1][1]) {
   2196     switch (argv[1][1]) {
   2197     case 's':
   2198       flag_s = 1;
   2199       break;
   2200     }
   2201     argc--;
   2202     first_arg = 2;
   2203   }
   2204   if (argc == 1) {
   2205     fname = "stdin";
   2206     outfd = 1;
   2207   } else if (argc < 3) {
   2208     fprintf(stderr, "Too few arguments\nUsage: %s <in-file> <out-file>\n", *argv);
   2209     exit(1);
   2210   } else {
   2211     if (argv[first_arg][0] == '-' && !argv[first_arg][1]) {
   2212       fname = "stdin";
   2213       yyin = stdin;
   2214     } else {
   2215       fname = argv[first_arg];
   2216       yyin = fopen(fname, "r");
   2217     }
   2218     outfd = open(argv[first_arg + 1], O_TRUNC  | O_WRONLY | O_CREAT,
   2219                  (S_IRUSR | S_IWUSR | S_IXUSR  | S_IRGRP  |
   2220                   S_IXGRP | S_IROTH | S_IXOTH) & 0x1ff);
   2221     if (outfd == -1) {
   2222       fprintf(stderr, "Unable to open out-file\n");
   2223       exit(1);
   2224     }
   2225   }
   2226 
   2227   yyparse();
   2228 
   2229   if (flag_s) stringify(final, -3, 0, NULL, 0);
   2230 
   2231   if (use_rodata) elf_hdr.phcount = 2;
   2232   else elf_hdr.phcount = 1;
   2233   if (use_rodata) elf_hdr.shcount = 4;
   2234   else elf_hdr.shcount = 3;
   2235   elf_hdr.shstrindx = elf_hdr.shcount - 1;
   2236 
   2237   int hdr1_size = sizeof(elf_hdr) + sizeof(struct prg_hdr) * elf_hdr.phcount;
   2238   start_addr = 0x400000 + hdr1_size;
   2239   rodata_addr = 0x600000;
   2240 
   2241   for (i = 0; i < final->args_count; i++) {
   2242     compile_tree(stdout, &final->args[i], 1, -1);
   2243   }
   2244   for (i = 0; i < ftemp_len; i++) {
   2245     if (ftemp[i].fptr) {
   2246       fprintf(stderr, "No definition for function <%s> found\n", ftemp[i].fname);
   2247 
   2248     }
   2249   }
   2250   if (failed) exit(1);
   2251   if (entry_addr < 0) {
   2252     fprintf(stderr, "No _start symbol found!\n");
   2253     exit(1);
   2254   }
   2255 
   2256   int section_pad = 16 - ((hdr1_size + mc_ptr) % 16);
   2257   int rodata_offset = sizeof(elf_hdr) + sizeof(load_text) + sizeof(load_rodata)
   2258                     + mc_ptr + section_pad + sizeof(null_section) + sizeof(text_section)
   2259                     + sizeof(rodata_section) + sizeof(strtab_section) 
   2260                     + sizeof(strtab);
   2261   int rodata_pad_len = 4096 - (rodata_offset % 4096);
   2262   rodata_offset += rodata_pad_len;
   2263 
   2264   elf_hdr.entry = start_addr + entry_addr;
   2265   elf_hdr.shoff = hdr1_size + mc_ptr + section_pad;
   2266 
   2267   load_text.offset = 0;
   2268   load_text.vaddr = 0x400000;
   2269   load_text.paddr = 0x400000;
   2270   load_text.fsize = hdr1_size + mc_ptr;
   2271   load_text.msize = hdr1_size + mc_ptr;
   2272 
   2273   load_rodata.offset = rodata_offset;
   2274   load_rodata.vaddr = 0x600000;
   2275   load_rodata.paddr = 0x600000;
   2276   load_rodata.fsize = rd_ptr;
   2277   load_rodata.msize = rd_ptr;
   2278 
   2279   text_section.addr = start_addr;
   2280   text_section.offset = hdr1_size;
   2281   text_section.size = mc_ptr;
   2282 
   2283   rodata_section.addr = load_rodata.vaddr;
   2284   rodata_section.offset = load_rodata.offset;
   2285   rodata_section.size = load_rodata.fsize;
   2286 
   2287   strtab_section.offset = hdr1_size + mc_ptr + section_pad + sizeof(struct sec_hdr) * elf_hdr.shcount;
   2288   strtab_section.size = sizeof(strtab);
   2289 
   2290   write(outfd, &elf_hdr, sizeof(elf_hdr));
   2291   write(outfd, &load_text, sizeof(load_text));
   2292   if (use_rodata) write(outfd, &load_rodata, sizeof(load_rodata));
   2293   write(outfd, machine_code, mc_ptr);
   2294   write(outfd, padding, section_pad);
   2295   write(outfd, &null_section, sizeof(null_section));
   2296   write(outfd, &text_section, sizeof(text_section));
   2297   if (use_rodata) write(outfd, &rodata_section, sizeof(rodata_section));
   2298   write(outfd, &strtab_section, sizeof(strtab_section));
   2299   write(outfd, strtab, sizeof(strtab));
   2300   if (use_rodata) write(outfd, padding, rodata_pad_len);
   2301   if (use_rodata) write(outfd, rodata, rd_ptr);
   2302 }