Subversion Repositories Kolibri OS

Rev

Rev 647 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. /*
  2.  *  CIL code generator for TCC
  3.  *
  4.  *  Copyright (c) 2002 Fabrice Bellard
  5.  *
  6.  * This library is free software; you can redistribute it and/or
  7.  * modify it under the terms of the GNU Lesser General Public
  8.  * License as published by the Free Software Foundation; either
  9.  * version 2 of the License, or (at your option) any later version.
  10.  *
  11.  * This library is distributed in the hope that it will be useful,
  12.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  14.  * Lesser General Public License for more details.
  15.  *
  16.  * You should have received a copy of the GNU Lesser General Public
  17.  * License along with this library; if not, write to the Free Software
  18.  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  19.  */
  20.  
  21. /* number of available registers */
  22. #define NB_REGS             3
  23.  
  24. /* a register can belong to several classes. The classes must be
  25.    sorted from more general to more precise (see gv2() code which does
  26.    assumptions on it). */
  27. #define RC_ST      0x0001  /* any stack entry */
  28. #define RC_ST0     0x0002  /* top of stack */
  29. #define RC_ST1     0x0004  /* top - 1 */
  30.  
  31. #define RC_INT     RC_ST
  32. #define RC_FLOAT   RC_ST
  33. #define RC_IRET    RC_ST0 /* function return: integer register */
  34. #define RC_LRET    RC_ST0 /* function return: second integer register */
  35. #define RC_FRET    RC_ST0 /* function return: float register */
  36.  
  37. /* pretty names for the registers */
  38. enum {
  39.     REG_ST0 = 0,
  40.     REG_ST1,
  41.     REG_ST2,
  42. };
  43.  
  44. const int reg_classes[NB_REGS] = {
  45.     /* ST0 */ RC_ST | RC_ST0,
  46.     /* ST1 */ RC_ST | RC_ST1,
  47.     /* ST2 */ RC_ST,
  48. };
  49.  
  50. /* return registers for function */
  51. #define REG_IRET REG_ST0 /* single word int return register */
  52. #define REG_LRET REG_ST0 /* second word return register (for long long) */
  53. #define REG_FRET REG_ST0 /* float return register */
  54.  
  55. /* defined if function parameters must be evaluated in reverse order */
  56. /* #define INVERT_FUNC_PARAMS */
  57.  
  58. /* defined if structures are passed as pointers. Otherwise structures
  59.    are directly pushed on stack. */
  60. /* #define FUNC_STRUCT_PARAM_AS_PTR */
  61.  
  62. /* pointer size, in bytes */
  63. #define PTR_SIZE 4
  64.  
  65. /* long double size and alignment, in bytes */
  66. #define LDOUBLE_SIZE  8
  67. #define LDOUBLE_ALIGN 8
  68.  
  69. /* function call context */
  70. typedef struct GFuncContext {
  71.     int func_call; /* func call type (FUNC_STDCALL or FUNC_CDECL) */
  72. } GFuncContext;
  73.  
  74. /******************************************************/
  75. /* opcode definitions */
  76.  
  77. #define IL_OP_PREFIX 0xFE
  78.  
  79. enum ILOPCodes {
  80. #define OP(name, str, n) IL_OP_ ## name = n,
  81. #include "il-opcodes.h"
  82. #undef OP
  83. };
  84.  
  85. char *il_opcodes_str[] = {
  86. #define OP(name, str, n) [n] = str,
  87. #include "il-opcodes.h"
  88. #undef OP
  89. };
  90.  
  91. /******************************************************/
  92.  
  93. /* arguments variable numbers start from there */
  94. #define ARG_BASE 0x70000000
  95.  
  96. static FILE *il_outfile;
  97.  
  98. static void out_byte(int c)
  99. {
  100.     *(char *)ind++ = c;
  101. }
  102.  
  103. static void out_le32(int c)
  104. {
  105.     out_byte(c);
  106.     out_byte(c >> 8);
  107.     out_byte(c >> 16);
  108.     out_byte(c >> 24);
  109. }
  110.  
  111. static void init_outfile(void)
  112. {
  113.     if (!il_outfile) {
  114.         il_outfile = stdout;
  115.         fprintf(il_outfile,
  116.                 ".assembly extern mscorlib\n"
  117.                 "{\n"
  118.                 ".ver 1:0:2411:0\n"
  119.                 "}\n\n");
  120.     }
  121. }
  122.  
  123. static void out_op1(int op)
  124. {
  125.     if (op & 0x100)
  126.         out_byte(IL_OP_PREFIX);
  127.     out_byte(op & 0xff);
  128. }
  129.  
  130. /* output an opcode with prefix */
  131. static void out_op(int op)
  132. {
  133.     out_op1(op);
  134.     fprintf(il_outfile, " %s\n", il_opcodes_str[op]);
  135. }
  136.  
  137. static void out_opb(int op, int c)
  138. {
  139.     out_op1(op);
  140.     out_byte(c);
  141.     fprintf(il_outfile, " %s %d\n", il_opcodes_str[op], c);
  142. }
  143.  
  144. static void out_opi(int op, int c)
  145. {
  146.     out_op1(op);
  147.     out_le32(c);
  148.     fprintf(il_outfile, " %s 0x%x\n", il_opcodes_str[op], c);
  149. }
  150.  
  151. /* XXX: not complete */
  152. static void il_type_to_str(char *buf, int buf_size,
  153.                            int t, const char *varstr)
  154. {
  155.     int bt;
  156.     Sym *s, *sa;
  157.     char buf1[256];
  158.     const char *tstr;
  159.  
  160.     t = t & VT_TYPE;
  161.     bt = t & VT_BTYPE;
  162.     buf[0] = '\0';
  163.     if (t & VT_UNSIGNED)
  164.         pstrcat(buf, buf_size, "unsigned ");
  165.     switch(bt) {
  166.     case VT_VOID:
  167.         tstr = "void";
  168.         goto add_tstr;
  169.     case VT_BOOL:
  170.         tstr = "bool";
  171.         goto add_tstr;
  172.     case VT_BYTE:
  173.         tstr = "int8";
  174.         goto add_tstr;
  175.     case VT_SHORT:
  176.         tstr = "int16";
  177.         goto add_tstr;
  178.     case VT_ENUM:
  179.     case VT_INT:
  180.     case VT_LONG:
  181.         tstr = "int32";
  182.         goto add_tstr;
  183.     case VT_LLONG:
  184.         tstr = "int64";
  185.         goto add_tstr;
  186.     case VT_FLOAT:
  187.         tstr = "float32";
  188.         goto add_tstr;
  189.     case VT_DOUBLE:
  190.     case VT_LDOUBLE:
  191.         tstr = "float64";
  192.     add_tstr:
  193.         pstrcat(buf, buf_size, tstr);
  194.         break;
  195.     case VT_STRUCT:
  196.         tcc_error("structures not handled yet");
  197.         break;
  198.     case VT_FUNC:
  199.         s = sym_find((unsigned)t >> VT_STRUCT_SHIFT);
  200.         il_type_to_str(buf, buf_size, s->t, varstr);
  201.         pstrcat(buf, buf_size, "(");
  202.         sa = s->next;
  203.         while (sa != NULL) {
  204.             il_type_to_str(buf1, sizeof(buf1), sa->t, NULL);
  205.             pstrcat(buf, buf_size, buf1);
  206.             sa = sa->next;
  207.             if (sa)
  208.                 pstrcat(buf, buf_size, ", ");
  209.         }
  210.         pstrcat(buf, buf_size, ")");
  211.         goto no_var;
  212.     case VT_PTR:
  213.         s = sym_find((unsigned)t >> VT_STRUCT_SHIFT);
  214.         pstrcpy(buf1, sizeof(buf1), "*");
  215.         if (varstr)
  216.             pstrcat(buf1, sizeof(buf1), varstr);
  217.         il_type_to_str(buf, buf_size, s->t, buf1);
  218.         goto no_var;
  219.     }
  220.     if (varstr) {
  221.         pstrcat(buf, buf_size, " ");
  222.         pstrcat(buf, buf_size, varstr);
  223.     }
  224.  no_var: ;
  225. }
  226.  
  227.  
  228. /* patch relocation entry with value 'val' */
  229. void greloc_patch1(Reloc *p, int val)
  230. {
  231. }
  232.  
  233. /* output a symbol and patch all calls to it */
  234. void gsym_addr(t, a)
  235. {
  236. }
  237.  
  238. /* output jump and return symbol */
  239. static int out_opj(int op, int c)
  240. {
  241.     out_op1(op);
  242.     out_le32(0);
  243.     if (c == 0) {
  244.         c = ind - (int)cur_text_section->data;
  245.     }
  246.     fprintf(il_outfile, " %s L%d\n", il_opcodes_str[op], c);
  247.     return c;
  248. }
  249.  
  250. void gsym(int t)
  251. {
  252.     fprintf(il_outfile, "L%d:\n", t);
  253. }
  254.  
  255. /* load 'r' from value 'sv' */
  256. void load(int r, SValue *sv)
  257. {
  258.     int v, fc, ft;
  259.  
  260.     v = sv->r & VT_VALMASK;
  261.     fc = sv->c.i;
  262.     ft = sv->t;
  263.  
  264.     if (sv->r & VT_LVAL) {
  265.         if (v == VT_LOCAL) {
  266.             if (fc >= ARG_BASE) {
  267.                 fc -= ARG_BASE;
  268.                 if (fc >= 0 && fc <= 4) {
  269.                     out_op(IL_OP_LDARG_0 + fc);
  270.                 } else if (fc <= 0xff) {
  271.                     out_opb(IL_OP_LDARG_S, fc);
  272.                 } else {
  273.                     out_opi(IL_OP_LDARG, fc);
  274.                 }
  275.             } else {
  276.                 if (fc >= 0 && fc <= 4) {
  277.                     out_op(IL_OP_LDLOC_0 + fc);
  278.                 } else if (fc <= 0xff) {
  279.                     out_opb(IL_OP_LDLOC_S, fc);
  280.                 } else {
  281.                     out_opi(IL_OP_LDLOC, fc);
  282.                 }
  283.             }
  284.         } else if (v == VT_CONST) {
  285.                 /* XXX: handle globals */
  286.                 out_opi(IL_OP_LDSFLD, 0);
  287.         } else {
  288.             if ((ft & VT_BTYPE) == VT_FLOAT) {
  289.                 out_op(IL_OP_LDIND_R4);
  290.             } else if ((ft & VT_BTYPE) == VT_DOUBLE) {
  291.                 out_op(IL_OP_LDIND_R8);
  292.             } else if ((ft & VT_BTYPE) == VT_LDOUBLE) {
  293.                 out_op(IL_OP_LDIND_R8);
  294.             } else if ((ft & VT_TYPE) == VT_BYTE)
  295.                 out_op(IL_OP_LDIND_I1);
  296.             else if ((ft & VT_TYPE) == (VT_BYTE | VT_UNSIGNED))
  297.                 out_op(IL_OP_LDIND_U1);
  298.             else if ((ft & VT_TYPE) == VT_SHORT)
  299.                 out_op(IL_OP_LDIND_I2);
  300.             else if ((ft & VT_TYPE) == (VT_SHORT | VT_UNSIGNED))
  301.                 out_op(IL_OP_LDIND_U2);
  302.             else
  303.                 out_op(IL_OP_LDIND_I4);
  304.         }
  305.     } else {
  306.         if (v == VT_CONST) {
  307.             /* XXX: handle globals */
  308.             if (fc >= -1 && fc <= 8) {
  309.                 out_op(IL_OP_LDC_I4_M1 + fc + 1);
  310.             } else {
  311.                 out_opi(IL_OP_LDC_I4, fc);
  312.             }
  313.         } else if (v == VT_LOCAL) {
  314.             if (fc >= ARG_BASE) {
  315.                 fc -= ARG_BASE;
  316.                 if (fc <= 0xff) {
  317.                     out_opb(IL_OP_LDARGA_S, fc);
  318.                 } else {
  319.                     out_opi(IL_OP_LDARGA, fc);
  320.                 }
  321.             } else {
  322.                 if (fc <= 0xff) {
  323.                     out_opb(IL_OP_LDLOCA_S, fc);
  324.                 } else {
  325.                     out_opi(IL_OP_LDLOCA, fc);
  326.                 }
  327.             }
  328.         } else {
  329.             /* XXX: do it */
  330.         }
  331.     }
  332. }
  333.  
  334. /* store register 'r' in lvalue 'v' */
  335. void store(int r, SValue *sv)
  336. {
  337.     int v, fc, ft;
  338.  
  339.     v = sv->r & VT_VALMASK;
  340.     fc = sv->c.i;
  341.     ft = sv->t;
  342.     if (v == VT_LOCAL) {
  343.         if (fc >= ARG_BASE) {
  344.             fc -= ARG_BASE;
  345.             /* XXX: check IL arg store semantics */
  346.             if (fc <= 0xff) {
  347.                 out_opb(IL_OP_STARG_S, fc);
  348.             } else {
  349.                 out_opi(IL_OP_STARG, fc);
  350.             }
  351.         } else {
  352.             if (fc >= 0 && fc <= 4) {
  353.                 out_op(IL_OP_STLOC_0 + fc);
  354.             } else if (fc <= 0xff) {
  355.                 out_opb(IL_OP_STLOC_S, fc);
  356.             } else {
  357.                 out_opi(IL_OP_STLOC, fc);
  358.             }
  359.         }
  360.     } else if (v == VT_CONST) {
  361.         /* XXX: handle globals */
  362.         out_opi(IL_OP_STSFLD, 0);
  363.     } else {
  364.         if ((ft & VT_BTYPE) == VT_FLOAT)
  365.             out_op(IL_OP_STIND_R4);
  366.         else if ((ft & VT_BTYPE) == VT_DOUBLE)
  367.             out_op(IL_OP_STIND_R8);
  368.         else if ((ft & VT_BTYPE) == VT_LDOUBLE)
  369.             out_op(IL_OP_STIND_R8);
  370.         else if ((ft & VT_BTYPE) == VT_BYTE)
  371.             out_op(IL_OP_STIND_I1);
  372.         else if ((ft & VT_BTYPE) == VT_SHORT)
  373.             out_op(IL_OP_STIND_I2);
  374.         else
  375.             out_op(IL_OP_STIND_I4);
  376.     }
  377. }
  378.  
  379. /* start function call and return function call context */
  380. void gfunc_start(GFuncContext *c, int func_call)
  381. {
  382.     c->func_call = func_call;
  383. }
  384.  
  385. /* push function parameter which is in (vtop->t, vtop->c). Stack entry
  386.    is then popped. */
  387. void gfunc_param(GFuncContext *c)
  388. {
  389.     if ((vtop->t & VT_BTYPE) == VT_STRUCT) {
  390.         tcc_error("structures passed as value not handled yet");
  391.     } else {
  392.         /* simply push on stack */
  393.         gv(RC_ST0);
  394.     }
  395.     vtop--;
  396. }
  397.  
  398. /* generate function call with address in (vtop->t, vtop->c) and free function
  399.    context. Stack entry is popped */
  400. void gfunc_call(GFuncContext *c)
  401. {
  402.     char buf[1024];
  403.  
  404.     if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
  405.         /* XXX: more info needed from tcc */
  406.         il_type_to_str(buf, sizeof(buf), vtop->t, "xxx");
  407.         fprintf(il_outfile, " call %s\n", buf);
  408.     } else {
  409.         /* indirect call */
  410.         gv(RC_INT);
  411.         il_type_to_str(buf, sizeof(buf), vtop->t, NULL);
  412.         fprintf(il_outfile, " calli %s\n", buf);
  413.     }
  414.     vtop--;
  415. }
  416.  
  417. /* generate function prolog of type 't' */
  418. void gfunc_prolog(int t)
  419. {
  420.     int addr, u, func_call;
  421.     Sym *sym;
  422.     char buf[1024];
  423.  
  424.     init_outfile();
  425.  
  426.     /* XXX: pass function name to gfunc_prolog */
  427.     il_type_to_str(buf, sizeof(buf), t, funcname);
  428.     fprintf(il_outfile, ".method static %s il managed\n", buf);
  429.     fprintf(il_outfile, "{\n");
  430.     /* XXX: cannot do better now */
  431.     fprintf(il_outfile, " .maxstack %d\n", NB_REGS);
  432.     fprintf(il_outfile, " .locals (int32, int32, int32, int32, int32, int32, int32, int32)\n");
  433.    
  434.     if (!strcmp(funcname, "main"))
  435.         fprintf(il_outfile, " .entrypoint\n");
  436.        
  437.     sym = sym_find((unsigned)t >> VT_STRUCT_SHIFT);
  438.     func_call = sym->r;
  439.  
  440.     addr = ARG_BASE;
  441.     /* if the function returns a structure, then add an
  442.        implicit pointer parameter */
  443.     func_vt = sym->t;
  444.     func_var = (sym->c == FUNC_ELLIPSIS);
  445.     if ((func_vt & VT_BTYPE) == VT_STRUCT) {
  446.         func_vc = addr;
  447.         addr++;
  448.     }
  449.     /* define parameters */
  450.     while ((sym = sym->next) != NULL) {
  451.         u = sym->t;
  452.         sym_push(sym->v & ~SYM_FIELD, u,
  453.                  VT_LOCAL | lvalue_type(sym->type.t), addr);
  454.         addr++;
  455.     }
  456. }
  457.  
  458. /* generate function epilog */
  459. void gfunc_epilog(void)
  460. {
  461.     out_op(IL_OP_RET);
  462.     fprintf(il_outfile, "}\n\n");
  463. }
  464.  
  465. /* generate a jump to a label */
  466. int gjmp(int t)
  467. {
  468.     return out_opj(IL_OP_BR, t);
  469. }
  470.  
  471. /* generate a jump to a fixed address */
  472. void gjmp_addr(int a)
  473. {
  474.     /* XXX: handle syms */
  475.     out_opi(IL_OP_BR, a);
  476. }
  477.  
  478. /* generate a test. set 'inv' to invert test. Stack entry is popped */
  479. int gtst(int inv, int t)
  480. {
  481.     int v, *p, c;
  482.  
  483.     v = vtop->r & VT_VALMASK;
  484.     if (v == VT_CMP) {
  485.         c = vtop->c.i ^ inv;
  486.         switch(c) {
  487.         case TOK_EQ:
  488.             c = IL_OP_BEQ;
  489.             break;
  490.         case TOK_NE:
  491.             c = IL_OP_BNE_UN;
  492.             break;
  493.         case TOK_LT:
  494.             c = IL_OP_BLT;
  495.             break;
  496.         case TOK_LE:
  497.             c = IL_OP_BLE;
  498.             break;
  499.         case TOK_GT:
  500.             c = IL_OP_BGT;
  501.             break;
  502.         case TOK_GE:
  503.             c = IL_OP_BGE;
  504.             break;
  505.         case TOK_ULT:
  506.             c = IL_OP_BLT_UN;
  507.             break;
  508.         case TOK_ULE:
  509.             c = IL_OP_BLE_UN;
  510.             break;
  511.         case TOK_UGT:
  512.             c = IL_OP_BGT_UN;
  513.             break;
  514.         case TOK_UGE:
  515.             c = IL_OP_BGE_UN;
  516.             break;
  517.         }
  518.         t = out_opj(c, t);
  519.     } else if (v == VT_JMP || v == VT_JMPI) {
  520.         /* && or || optimization */
  521.         if ((v & 1) == inv) {
  522.             /* insert vtop->c jump list in t */
  523.             p = &vtop->c.i;
  524.             while (*p != 0)
  525.                 p = (int *)*p;
  526.             *p = t;
  527.             t = vtop->c.i;
  528.         } else {
  529.             t = gjmp(t);
  530.             gsym(vtop->c.i);
  531.         }
  532.     }
  533.     vtop--;
  534.     return t;
  535. }
  536.  
  537. /* generate an integer binary operation */
  538. void gen_opi(int op)
  539. {
  540.     gv2(RC_ST1, RC_ST0);
  541.     switch(op) {
  542.     case '+':
  543.         out_op(IL_OP_ADD);
  544.         goto std_op;
  545.     case '-':
  546.         out_op(IL_OP_SUB);
  547.         goto std_op;
  548.     case '&':
  549.         out_op(IL_OP_AND);
  550.         goto std_op;
  551.     case '^':
  552.         out_op(IL_OP_XOR);
  553.         goto std_op;
  554.     case '|':
  555.         out_op(IL_OP_OR);
  556.         goto std_op;
  557.     case '*':
  558.         out_op(IL_OP_MUL);
  559.         goto std_op;
  560.     case TOK_SHL:
  561.         out_op(IL_OP_SHL);
  562.         goto std_op;
  563.     case TOK_SHR:
  564.         out_op(IL_OP_SHR_UN);
  565.         goto std_op;
  566.     case TOK_SAR:
  567.         out_op(IL_OP_SHR);
  568.         goto std_op;
  569.     case '/':
  570.     case TOK_PDIV:
  571.         out_op(IL_OP_DIV);
  572.         goto std_op;
  573.     case TOK_UDIV:
  574.         out_op(IL_OP_DIV_UN);
  575.         goto std_op;
  576.     case '%':
  577.         out_op(IL_OP_REM);
  578.         goto std_op;
  579.     case TOK_UMOD:
  580.         out_op(IL_OP_REM_UN);
  581.     std_op:
  582.         vtop--;
  583.         vtop[0].r = REG_ST0;
  584.         break;
  585.     case TOK_EQ:
  586.     case TOK_NE:
  587.     case TOK_LT:
  588.     case TOK_LE:
  589.     case TOK_GT:
  590.     case TOK_GE:
  591.     case TOK_ULT:
  592.     case TOK_ULE:
  593.     case TOK_UGT:
  594.     case TOK_UGE:
  595.         vtop--;
  596.         vtop[0].r = VT_CMP;
  597.         vtop[0].c.i = op;
  598.         break;
  599.     }
  600. }
  601.  
  602. /* generate a floating point operation 'v = t1 op t2' instruction. The
  603.    two operands are guaranted to have the same floating point type */
  604. void gen_opf(int op)
  605. {
  606.     /* same as integer */
  607.     gen_opi(op);
  608. }
  609.  
  610. /* convert integers to fp 't' type. Must handle 'int', 'unsigned int'
  611.    and 'long long' cases. */
  612. void gen_cvt_itof(int t)
  613. {
  614.     gv(RC_ST0);
  615.     if (t == VT_FLOAT)
  616.         out_op(IL_OP_CONV_R4);
  617.     else
  618.         out_op(IL_OP_CONV_R8);
  619. }
  620.  
  621. /* convert fp to int 't' type */
  622. /* XXX: handle long long case */
  623. void gen_cvt_ftoi(int t)
  624. {
  625.     gv(RC_ST0);
  626.     switch(t) {
  627.     case VT_INT | VT_UNSIGNED:
  628.         out_op(IL_OP_CONV_U4);
  629.         break;
  630.     case VT_LLONG:
  631.         out_op(IL_OP_CONV_I8);
  632.         break;
  633.     case VT_LLONG | VT_UNSIGNED:
  634.         out_op(IL_OP_CONV_U8);
  635.         break;
  636.     default:
  637.         out_op(IL_OP_CONV_I4);
  638.         break;
  639.     }
  640. }
  641.  
  642. /* convert from one floating point type to another */
  643. void gen_cvt_ftof(int t)
  644. {
  645.     gv(RC_ST0);
  646.     if (t == VT_FLOAT) {
  647.         out_op(IL_OP_CONV_R4);
  648.     } else {
  649.         out_op(IL_OP_CONV_R8);
  650.     }
  651. }
  652.  
  653. /* end of CIL code generator */
  654. /*************************************************************/
  655.  
  656.