From 826d1afd58c2e064a9c8fdb09eda1b08469de1a8 Mon Sep 17 00:00:00 2001 From: pommicket Date: Fri, 18 Feb 2022 12:36:57 -0500 Subject: newer version of tcc almost working --- 05/tcc-0.9.25/il-gen.c | 667 ------------------------------------------------- 1 file changed, 667 deletions(-) delete mode 100644 05/tcc-0.9.25/il-gen.c (limited to '05/tcc-0.9.25/il-gen.c') diff --git a/05/tcc-0.9.25/il-gen.c b/05/tcc-0.9.25/il-gen.c deleted file mode 100644 index 29f0526..0000000 --- a/05/tcc-0.9.25/il-gen.c +++ /dev/null @@ -1,667 +0,0 @@ -/* - * CIL code generator for TCC - * - * Copyright (c) 2002 Fabrice Bellard - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* number of available registers */ -#define NB_REGS 3 - -/* a register can belong to several classes. The classes must be - sorted from more general to more precise (see gv2() code which does - assumptions on it). */ -#define RC_ST 0x0001 /* any stack entry */ -#define RC_ST0 0x0002 /* top of stack */ -#define RC_ST1 0x0004 /* top - 1 */ - -#define RC_INT RC_ST -#define RC_FLOAT RC_ST -#define RC_IRET RC_ST0 /* function return: integer register */ -#define RC_LRET RC_ST0 /* function return: second integer register */ -#define RC_FRET RC_ST0 /* function return: float register */ - -/* pretty names for the registers */ -enum { - REG_ST0 = 0, - REG_ST1, - REG_ST2, -}; - -int reg_classes[NB_REGS] = { - /* ST0 */ RC_ST | RC_ST0, - /* ST1 */ RC_ST | RC_ST1, - /* ST2 */ RC_ST, -}; - -/* return registers for function */ -#define REG_IRET REG_ST0 /* single word int return register */ -#define REG_LRET REG_ST0 /* second word return register (for long long) */ -#define REG_FRET REG_ST0 /* float return register */ - -/* defined if function parameters must be evaluated in reverse order */ -//#define INVERT_FUNC_PARAMS - -/* defined if structures are passed as pointers. Otherwise structures - are directly pushed on stack. */ -//#define FUNC_STRUCT_PARAM_AS_PTR - -/* pointer size, in bytes */ -#define PTR_SIZE 4 - -/* long double size and alignment, in bytes */ -#define LDOUBLE_SIZE 8 -#define LDOUBLE_ALIGN 8 - -/* function call context */ -typedef struct GFuncContext { - int func_call; /* func call type (FUNC_STDCALL or FUNC_CDECL) */ -} GFuncContext; - -/******************************************************/ -/* opcode definitions */ - -#define IL_OP_PREFIX 0xFE - -enum ILOPCodes { -#define OP(name, str, n) IL_OP_ ## name = n, -#include "il-opcodes.h" -#undef OP -}; - -char *il_opcodes_str[] = { -#define OP(name, str, n) [n] = str, -#include "il-opcodes.h" -#undef OP -}; - -/******************************************************/ - -/* arguments variable numbers start from there */ -#define ARG_BASE 0x70000000 - -static FILE *il_outfile; - -static void out_byte(int c) -{ - *(char *)ind++ = c; -} - -static void out_le32(int c) -{ - out_byte(c); - out_byte(c >> 8); - out_byte(c >> 16); - out_byte(c >> 24); -} - -static void init_outfile(void) -{ - if (!il_outfile) { - il_outfile = stdout; - fprintf(il_outfile, - ".assembly extern mscorlib\n" - "{\n" - ".ver 1:0:2411:0\n" - "}\n\n"); - } -} - -static void out_op1(int op) -{ - if (op & 0x100) - out_byte(IL_OP_PREFIX); - out_byte(op & 0xff); -} - -/* output an opcode with prefix */ -static void out_op(int op) -{ - out_op1(op); - fprintf(il_outfile, " %s\n", il_opcodes_str[op]); -} - -static void out_opb(int op, int c) -{ - out_op1(op); - out_byte(c); - fprintf(il_outfile, " %s %d\n", il_opcodes_str[op], c); -} - -static void out_opi(int op, int c) -{ - out_op1(op); - out_le32(c); - fprintf(il_outfile, " %s 0x%x\n", il_opcodes_str[op], c); -} - -/* XXX: not complete */ -static void il_type_to_str(char *buf, int buf_size, - int t, const char *varstr) -{ - int bt; - Sym *s, *sa; - char buf1[256]; - const char *tstr; - - t = t & VT_TYPE; - bt = t & VT_BTYPE; - buf[0] = '\0'; - if (t & VT_UNSIGNED) - pstrcat(buf, buf_size, "unsigned "); - switch(bt) { - case VT_VOID: - tstr = "void"; - goto add_tstr; - case VT_BOOL: - tstr = "bool"; - goto add_tstr; - case VT_BYTE: - tstr = "int8"; - goto add_tstr; - case VT_SHORT: - tstr = "int16"; - goto add_tstr; - case VT_ENUM: - case VT_INT: - case VT_LONG: - tstr = "int32"; - goto add_tstr; - case VT_LLONG: - tstr = "int64"; - goto add_tstr; - case VT_FLOAT: - tstr = "float32"; - goto add_tstr; - case VT_DOUBLE: - case VT_LDOUBLE: - tstr = "float64"; - add_tstr: - pstrcat(buf, buf_size, tstr); - break; - case VT_STRUCT: - error("structures not handled yet"); - break; - case VT_FUNC: - s = sym_find((unsigned)t >> VT_STRUCT_SHIFT); - il_type_to_str(buf, buf_size, s->t, varstr); - pstrcat(buf, buf_size, "("); - sa = s->next; - while (sa != NULL) { - il_type_to_str(buf1, sizeof(buf1), sa->t, NULL); - pstrcat(buf, buf_size, buf1); - sa = sa->next; - if (sa) - pstrcat(buf, buf_size, ", "); - } - pstrcat(buf, buf_size, ")"); - goto no_var; - case VT_PTR: - s = sym_find((unsigned)t >> VT_STRUCT_SHIFT); - pstrcpy(buf1, sizeof(buf1), "*"); - if (varstr) - pstrcat(buf1, sizeof(buf1), varstr); - il_type_to_str(buf, buf_size, s->t, buf1); - goto no_var; - } - if (varstr) { - pstrcat(buf, buf_size, " "); - pstrcat(buf, buf_size, varstr); - } - no_var: ; -} - - -/* patch relocation entry with value 'val' */ -void greloc_patch1(Reloc *p, int val) -{ -} - -/* output a symbol and patch all calls to it */ -void gsym_addr(t, a) -{ -} - -/* output jump and return symbol */ -static int out_opj(int op, int c) -{ - out_op1(op); - out_le32(0); - if (c == 0) { - c = ind - (int)cur_text_section->data; - } - fprintf(il_outfile, " %s L%d\n", il_opcodes_str[op], c); - return c; -} - -void gsym(int t) -{ - fprintf(il_outfile, "L%d:\n", t); -} - -/* load 'r' from value 'sv' */ -void load(int r, SValue *sv) -{ - int v, fc, ft; - - v = sv->r & VT_VALMASK; - fc = sv->c.i; - ft = sv->t; - - if (sv->r & VT_LVAL) { - if (v == VT_LOCAL) { - if (fc >= ARG_BASE) { - fc -= ARG_BASE; - if (fc >= 0 && fc <= 4) { - out_op(IL_OP_LDARG_0 + fc); - } else if (fc <= 0xff) { - out_opb(IL_OP_LDARG_S, fc); - } else { - out_opi(IL_OP_LDARG, fc); - } - } else { - if (fc >= 0 && fc <= 4) { - out_op(IL_OP_LDLOC_0 + fc); - } else if (fc <= 0xff) { - out_opb(IL_OP_LDLOC_S, fc); - } else { - out_opi(IL_OP_LDLOC, fc); - } - } - } else if (v == VT_CONST) { - /* XXX: handle globals */ - out_opi(IL_OP_LDSFLD, 0); - } else { - if ((ft & VT_BTYPE) == VT_FLOAT) { - out_op(IL_OP_LDIND_R4); - } else if ((ft & VT_BTYPE) == VT_DOUBLE) { - out_op(IL_OP_LDIND_R8); - } else if ((ft & VT_BTYPE) == VT_LDOUBLE) { - out_op(IL_OP_LDIND_R8); - } else if ((ft & VT_TYPE) == VT_BYTE) - out_op(IL_OP_LDIND_I1); - else if ((ft & VT_TYPE) == (VT_BYTE | VT_UNSIGNED)) - out_op(IL_OP_LDIND_U1); - else if ((ft & VT_TYPE) == VT_SHORT) - out_op(IL_OP_LDIND_I2); - else if ((ft & VT_TYPE) == (VT_SHORT | VT_UNSIGNED)) - out_op(IL_OP_LDIND_U2); - else - out_op(IL_OP_LDIND_I4); - } - } else { - if (v == VT_CONST) { - /* XXX: handle globals */ - if (fc >= -1 && fc <= 8) { - out_op(IL_OP_LDC_I4_M1 + fc + 1); - } else { - out_opi(IL_OP_LDC_I4, fc); - } - } else if (v == VT_LOCAL) { - if (fc >= ARG_BASE) { - fc -= ARG_BASE; - if (fc <= 0xff) { - out_opb(IL_OP_LDARGA_S, fc); - } else { - out_opi(IL_OP_LDARGA, fc); - } - } else { - if (fc <= 0xff) { - out_opb(IL_OP_LDLOCA_S, fc); - } else { - out_opi(IL_OP_LDLOCA, fc); - } - } - } else { - /* XXX: do it */ - } - } -} - -/* store register 'r' in lvalue 'v' */ -void store(int r, SValue *sv) -{ - int v, fc, ft; - - v = sv->r & VT_VALMASK; - fc = sv->c.i; - ft = sv->t; - if (v == VT_LOCAL) { - if (fc >= ARG_BASE) { - fc -= ARG_BASE; - /* XXX: check IL arg store semantics */ - if (fc <= 0xff) { - out_opb(IL_OP_STARG_S, fc); - } else { - out_opi(IL_OP_STARG, fc); - } - } else { - if (fc >= 0 && fc <= 4) { - out_op(IL_OP_STLOC_0 + fc); - } else if (fc <= 0xff) { - out_opb(IL_OP_STLOC_S, fc); - } else { - out_opi(IL_OP_STLOC, fc); - } - } - } else if (v == VT_CONST) { - /* XXX: handle globals */ - out_opi(IL_OP_STSFLD, 0); - } else { - if ((ft & VT_BTYPE) == VT_FLOAT) - out_op(IL_OP_STIND_R4); - else if ((ft & VT_BTYPE) == VT_DOUBLE) - out_op(IL_OP_STIND_R8); - else if ((ft & VT_BTYPE) == VT_LDOUBLE) - out_op(IL_OP_STIND_R8); - else if ((ft & VT_BTYPE) == VT_BYTE) - out_op(IL_OP_STIND_I1); - else if ((ft & VT_BTYPE) == VT_SHORT) - out_op(IL_OP_STIND_I2); - else - out_op(IL_OP_STIND_I4); - } -} - -/* start function call and return function call context */ -void gfunc_start(GFuncContext *c, int func_call) -{ - c->func_call = func_call; -} - -/* push function parameter which is in (vtop->t, vtop->c). Stack entry - is then popped. */ -void gfunc_param(GFuncContext *c) -{ - if ((vtop->t & VT_BTYPE) == VT_STRUCT) { - error("structures passed as value not handled yet"); - } else { - /* simply push on stack */ - gv(RC_ST0); - } - vtop--; -} - -/* generate function call with address in (vtop->t, vtop->c) and free function - context. Stack entry is popped */ -void gfunc_call(GFuncContext *c) -{ - char buf[1024]; - - if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) { - /* XXX: more info needed from tcc */ - il_type_to_str(buf, sizeof(buf), vtop->t, "xxx"); - fprintf(il_outfile, " call %s\n", buf); - } else { - /* indirect call */ - gv(RC_INT); - il_type_to_str(buf, sizeof(buf), vtop->t, NULL); - fprintf(il_outfile, " calli %s\n", buf); - } - vtop--; -} - -/* generate function prolog of type 't' */ -void gfunc_prolog(int t) -{ - int addr, u, func_call; - Sym *sym; - char buf[1024]; - - init_outfile(); - - /* XXX: pass function name to gfunc_prolog */ - il_type_to_str(buf, sizeof(buf), t, funcname); - fprintf(il_outfile, ".method static %s il managed\n", buf); - fprintf(il_outfile, "{\n"); - /* XXX: cannot do better now */ - fprintf(il_outfile, " .maxstack %d\n", NB_REGS); - fprintf(il_outfile, " .locals (int32, int32, int32, int32, int32, int32, int32, int32)\n"); - - if (!strcmp(funcname, "main")) - fprintf(il_outfile, " .entrypoint\n"); - - sym = sym_find((unsigned)t >> VT_STRUCT_SHIFT); - func_call = sym->r; - - addr = ARG_BASE; - /* if the function returns a structure, then add an - implicit pointer parameter */ - func_vt = sym->t; - if ((func_vt & VT_BTYPE) == VT_STRUCT) { - func_vc = addr; - addr++; - } - /* define parameters */ - while ((sym = sym->next) != NULL) { - u = sym->t; - sym_push(sym->v & ~SYM_FIELD, u, - VT_LOCAL | lvalue_type(sym->type.t), addr); - addr++; - } -} - -/* generate function epilog */ -void gfunc_epilog(void) -{ - out_op(IL_OP_RET); - fprintf(il_outfile, "}\n\n"); -} - -/* generate a jump to a label */ -int gjmp(int t) -{ - return out_opj(IL_OP_BR, t); -} - -/* generate a jump to a fixed address */ -void gjmp_addr(int a) -{ - /* XXX: handle syms */ - out_opi(IL_OP_BR, a); -} - -/* generate a test. set 'inv' to invert test. Stack entry is popped */ -int gtst(int inv, int t) -{ - int v, *p, c; - - v = vtop->r & VT_VALMASK; - if (v == VT_CMP) { - c = vtop->c.i ^ inv; - switch(c) { - case TOK_EQ: - c = IL_OP_BEQ; - break; - case TOK_NE: - c = IL_OP_BNE_UN; - break; - case TOK_LT: - c = IL_OP_BLT; - break; - case TOK_LE: - c = IL_OP_BLE; - break; - case TOK_GT: - c = IL_OP_BGT; - break; - case TOK_GE: - c = IL_OP_BGE; - break; - case TOK_ULT: - c = IL_OP_BLT_UN; - break; - case TOK_ULE: - c = IL_OP_BLE_UN; - break; - case TOK_UGT: - c = IL_OP_BGT_UN; - break; - case TOK_UGE: - c = IL_OP_BGE_UN; - break; - } - t = out_opj(c, t); - } else if (v == VT_JMP || v == VT_JMPI) { - /* && or || optimization */ - if ((v & 1) == inv) { - /* insert vtop->c jump list in t */ - p = &vtop->c.i; - while (*p != 0) - p = (int *)*p; - *p = t; - t = vtop->c.i; - } else { - t = gjmp(t); - gsym(vtop->c.i); - } - } else { - if (is_float(vtop->t)) { - vpushi(0); - gen_op(TOK_NE); - } - if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_FORWARD)) == VT_CONST) { - /* constant jmp optimization */ - if ((vtop->c.i != 0) != inv) - t = gjmp(t); - } else { - v = gv(RC_INT); - t = out_opj(IL_OP_BRTRUE - inv, t); - } - } - vtop--; - return t; -} - -/* generate an integer binary operation */ -void gen_opi(int op) -{ - gv2(RC_ST1, RC_ST0); - switch(op) { - case '+': - out_op(IL_OP_ADD); - goto std_op; - case '-': - out_op(IL_OP_SUB); - goto std_op; - case '&': - out_op(IL_OP_AND); - goto std_op; - case '^': - out_op(IL_OP_XOR); - goto std_op; - case '|': - out_op(IL_OP_OR); - goto std_op; - case '*': - out_op(IL_OP_MUL); - goto std_op; - case TOK_SHL: - out_op(IL_OP_SHL); - goto std_op; - case TOK_SHR: - out_op(IL_OP_SHR_UN); - goto std_op; - case TOK_SAR: - out_op(IL_OP_SHR); - goto std_op; - case '/': - case TOK_PDIV: - out_op(IL_OP_DIV); - goto std_op; - case TOK_UDIV: - out_op(IL_OP_DIV_UN); - goto std_op; - case '%': - out_op(IL_OP_REM); - goto std_op; - case TOK_UMOD: - out_op(IL_OP_REM_UN); - std_op: - vtop--; - vtop[0].r = REG_ST0; - break; - case TOK_EQ: - case TOK_NE: - case TOK_LT: - case TOK_LE: - case TOK_GT: - case TOK_GE: - case TOK_ULT: - case TOK_ULE: - case TOK_UGT: - case TOK_UGE: - vtop--; - vtop[0].r = VT_CMP; - vtop[0].c.i = op; - break; - } -} - -/* generate a floating point operation 'v = t1 op t2' instruction. The - two operands are guaranted to have the same floating point type */ -void gen_opf(int op) -{ - /* same as integer */ - gen_opi(op); -} - -/* convert integers to fp 't' type. Must handle 'int', 'unsigned int' - and 'long long' cases. */ -void gen_cvt_itof(int t) -{ - gv(RC_ST0); - if (t == VT_FLOAT) - out_op(IL_OP_CONV_R4); - else - out_op(IL_OP_CONV_R8); -} - -/* convert fp to int 't' type */ -/* XXX: handle long long case */ -void gen_cvt_ftoi(int t) -{ - gv(RC_ST0); - switch(t) { - case VT_INT | VT_UNSIGNED: - out_op(IL_OP_CONV_U4); - break; - case VT_LLONG: - out_op(IL_OP_CONV_I8); - break; - case VT_LLONG | VT_UNSIGNED: - out_op(IL_OP_CONV_U8); - break; - default: - out_op(IL_OP_CONV_I4); - break; - } -} - -/* convert from one floating point type to another */ -void gen_cvt_ftof(int t) -{ - gv(RC_ST0); - if (t == VT_FLOAT) { - out_op(IL_OP_CONV_R4); - } else { - out_op(IL_OP_CONV_R8); - } -} - -/* end of CIL code generator */ -/*************************************************************/ - -- cgit v1.2.3