void genif(SNODE *stmt) /* * generate code to evaluate an if statement. */ { int lab1, lab2; int areg, sreg; lab1 = nextlabel++; /* else label */ lab2 = nextlabel++; /* exit label */ InitRegs(); /* clear temps */ ChooseRegs(&areg, &sreg); falsejp(stmt->exp, areg, sreg, lab1); genstmt(stmt->s1); if (stmt->s2 != 0) /* else part exists */ { gen_codes(op_jmp, 0, make_label(lab2), 0); gen_label(lab1); genstmt(stmt->s2); gen_label(lab2); } else /* no else code */ gen_label(lab1); }
/* Assums the dseg is the next higher seg value from the cseg */ void loadds(void) { gen_code(op_push, makesegreg(DS), 0); gen_code(op_push, makesegreg(CS), 0); gen_codes(op_add, 2, make_stack(0), make_immed(8)); gen_code(op_pop, makesegreg(DS), 0); }
void gen_for(SNODE *stmt) /* * generate code to evaluate a for loop */ { int old_break, old_cont, exit_label, loop_label, start_label; int areg, sreg; old_break = breaklab; old_cont = contlab; loop_label = nextlabel++; contlab = nextlabel++; start_label = nextlabel++; exit_label = nextlabel++; InitRegs(); if (stmt->label != 0) { gen_void_external(stmt->label); } gen_codes(op_jmp, 0, make_label(start_label), 0); gen_label(loop_label); if (stmt->s1 != 0) { breaklab = exit_label; genstmt(stmt->s1); } if (stmt->lst) gen_line(stmt->lst); gen_label(contlab); InitRegs(); if (stmt->s2 != 0) { gen_void_external(stmt->s2); } gen_label(start_label); InitRegs(); ChooseRegs(&areg, &sreg); if (stmt->exp != 0) truejp(stmt->exp, areg, sreg, loop_label); else gen_codes(op_jmp, 0, make_label(loop_label), 0); gen_label(exit_label); breaklab = old_break; contlab = old_cont; }
void gencompactswitch(SNODE *stmt, struct cases *cs) { int tablab, size; AMODE *ap, *ap2; LLONG_TYPE i; tablab = nextlabel++; InitRegs(); size = natural_size(stmt->exp); if (size == BESZ_QWORD || size == - BESZ_QWORD) { ap = gen_expr_external(stmt->exp, FALSE, F_AXDX, BESZ_QWORD); if (cs->bottom) { gen_codes(op_sub, BESZ_DWORD, makedreg(EAX), make_immed(cs->bottom)); #if sizeof(LLONG_TYPE) == 4 gen_codes(op_sbb, BESZ_DWORD, makedreg(EDX), make_immed(cs->bottom < 0 ? - 1: 0)); #else gen_codes(op_sbb, BESZ_DWORD, makedreg(EDX), make_immed(cs->bottom >> 32)); #endif }
void call_library(char *lib_name) /* * generate a call to a library routine. */ { AMODE *ap; ap = set_symbol(lib_name, 1); if (prm_lscrtdll) { ap->mode = am_direct; } gen_codes(op_call, 0, ap, 0); }
void genwhile(SNODE *stmt) /* * generate code to evaluate a while statement. */ { int lab1, lab2, lab3; int areg, sreg; InitRegs(); /* initialize temp registers */ lab1 = contlab; /* save old continue label */ contlab = nextlabel++; /* new continue label */ if (stmt->s1 != 0) /* has block */ { lab2 = breaklab; /* save old break label */ breaklab = nextlabel++; gen_codes(op_jmp, 0, make_label(contlab), 0); lab3 = nextlabel++; gen_label(lab3); genstmt(stmt->s1); gen_label(contlab); if (stmt->lst) gen_line(stmt->lst); InitRegs(); ChooseRegs(&areg, &sreg); truejp(stmt->exp, areg, sreg, lab3); gen_label(breaklab); breaklab = lab2; /* restore old break label */ } else /* no loop code */ { if (stmt->lst) gen_line(stmt->lst); gen_label(contlab); InitRegs(); ChooseRegs(&areg, &sreg); truejp(stmt->exp, areg, sreg, contlab); } contlab = lab1; /* restore old continue label */ }
/* =========================================================================== * Construct one Huffman tree and assigns the code bit strings and lengths. * Update the total bit length for the current block. * IN assertion: the field freq is set for all tree elements. * OUT assertions: the fields len and code are set to the optimal bit length * and corresponding code. The length opt_len is updated; static_len is * also updated if stree is not null. The field max_code is set. */ void build_tree(tree_desc near *desc) //tree_desc near *desc; /* the tree descriptor */ { ct_data near *tree = desc->dyn_tree; ct_data near *stree = desc->static_tree; int elems = desc->elems; int n, m; /* iterate over heap elements */ int max_code = -1; /* largest code with non zero frequency */ int node = elems; /* next internal node of the tree */ /* Construct the initial heap, with least frequent element in * heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n+1]. * heap[0] is not used. */ heap_len = 0, heap_max = HEAP_SIZE; for (n = 0; n < elems; n++) { if (tree[n].Freq != 0) { heap[++heap_len] = max_code = n; depth[n] = 0; } else { tree[n].Len = 0; } } /* The pkzip format requires that at least one distance code exists, * and that at least one bit should be sent even if there is only one * possible code. So to avoid special checks later on we force at least * two codes of non zero frequency. */ while (heap_len < 2) { int new_ = heap[++heap_len] = (max_code < 2 ? ++max_code : 0); tree[new_].Freq = 1; depth[new_] = 0; opt_len--; if (stree) static_len -= stree[new_].Len; /* new is 0 or 1 so it does not have extra bits */ } desc->max_code = max_code; /* The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree, * establish sub-heaps of increasing lengths: */ for (n = heap_len/2; n >= 1; n--) pqdownheap(tree, n); /* Construct the Huffman tree by repeatedly combining the least two * frequent nodes. */ do { pqremove(tree, n); /* n = node of least frequency */ m = heap[SMALLEST]; /* m = node of next least frequency */ heap[--heap_max] = n; /* keep the nodes sorted by frequency */ heap[--heap_max] = m; /* Create a new node father of n and m */ tree[node].Freq = (u16)(tree[n].Freq + tree[m].Freq); depth[node] = (u8) (max(depth[n], depth[m]) + 1); tree[n].Dad = tree[m].Dad = (u16)node; /* and insert the new node in the heap */ heap[SMALLEST] = node++; pqdownheap(tree, SMALLEST); } while (heap_len >= 2); heap[--heap_max] = heap[SMALLEST]; /* At this point, the fields freq and dad are set. We can now * generate the bit lengths. */ gen_bitlen((tree_desc near *)desc); /* The field len is now set, we can generate the bit codes */ gen_codes ((ct_data near *)tree, max_code); }
/* =========================================================================== * Allocate the match buffer, initialize the various tables and save the * location of the internal file attribute (ascii/binary) and method * (DEFLATE/STORE). */ void ct_init(int* method) //ush *attr; /* pointer to internal file attribute */ //int *method; /* pointer to compression method */ { int n; /* iterates over tree elements */ int bits; /* bit counter */ int length; /* length value */ int code; /* code value */ int dist; /* distance index */ file_method = method; cmpr_bytelen = cmpr_len_bits = 0L; #ifdef _DEBUG input_len = 0L; #endif if (static_dtree[0].Len != 0) return; /* ct_init already called */ /* Initialize the mapping length (0..255) -> length code (0..28) */ length = 0; for (code = 0; code < LENGTH_CODES-1; code++) { base_length[code] = length; for (n = 0; n < (1<<extra_lbits[code]); n++) { length_code[length++] = (u8)code; } } Assert(length == 256);//, "ct_init: length != 256"); /* Note that the length 255 (match length 258) can be represented * in two different ways: code 284 + 5 bits or code 285, so we * overwrite length_code[255] to use the best encoding: */ length_code[length-1] = (u8)code; /* Initialize the mapping dist (0..32K) -> dist code (0..29) */ dist = 0; for (code = 0 ; code < 16; code++) { base_dist[code] = dist; for (n = 0; n < (1<<extra_dbits[code]); n++) { dist_code[dist++] = (u8)code; } } Assert(dist == 256);//, "ct_init: dist != 256"); dist >>= 7; /* from now on, all distances are divided by 128 */ for ( ; code < D_CODES; code++) { base_dist[code] = dist << 7; for (n = 0; n < (1<<(extra_dbits[code]-7)); n++) { dist_code[256 + dist++] = (u8)code; } } Assert(dist == 256);//, "ct_init: 256+dist != 512"); /* Construct the codes of the static literal tree */ for (bits = 0; bits <= MAX_BITS; bits++) bl_count[bits] = 0; n = 0; while (n <= 143) static_ltree[n++].Len = 8, bl_count[8]++; while (n <= 255) static_ltree[n++].Len = 9, bl_count[9]++; while (n <= 279) static_ltree[n++].Len = 7, bl_count[7]++; while (n <= 287) static_ltree[n++].Len = 8, bl_count[8]++; /* Codes 286 and 287 do not exist, but we must include them in the * tree construction to get a canonical Huffman tree (longest code * all ones) */ gen_codes((ct_data near *)static_ltree, L_CODES+1); /* The static distance tree is trivial: */ for (n = 0; n < D_CODES; n++) { static_dtree[n].Len = 5; static_dtree[n].Code = (u16)bi_reverse(n, 5); } /* Initialize the first block of the first file: */ init_block(); }
void loadregs(void) /* * initialize allocated registers */ { CSE *csp; ENODE *exptr; unsigned mask, rmask, i, fmask, frmask, size; AMODE *ap, *ap2; csp = olist; while (csp != 0) { int sz; if (csp->reg != - 1) { /* see if preload needed */ exptr = csp->exp; if (!lvalue(exptr) || ((SYM*)exptr->v.p[0]->v.p[0])->funcparm) { exptr = csp->exp; InitRegs(); sz = csp->size; ap = gen_expr_external(exptr, FALSE, F_MEM | F_DREG | F_IMMED, sz); if (csp->reg < 16) { if (ap->mode == am_dreg) peep_tail->oper1->preg = csp->reg; else { if (csp->reg > 3 && chksize(BESZ_WORD, sz)) DIAG("byte sized non-register in analyze"); ap2 = makedreg(csp->reg); ap2->length = BESZ_DWORD; if (ap->mode == am_immed || ap->length == BESZ_DWORD || ap ->length == - BESZ_DWORD) gen_codes(op_mov, BESZ_DWORD, ap2, ap); else if (sz < 0) gen_code(op_movsx, ap2, ap); else gen_code(op_movzx, ap2, ap); } } else if (csp->reg < 32) { if (ap->mode == am_dreg) peep_tail->oper1->preg = csp->reg - 12; else { if (csp->reg - 12 > 3 && chksize(BESZ_WORD, sz)) DIAG("byte sized non-register in analyze"); ap2 = makedreg(csp->reg - 12); ap2->length = BESZ_DWORD; if (ap->mode == am_immed || ap->length == BESZ_DWORD || ap ->length == - BESZ_DWORD) gen_codes(op_mov, BESZ_DWORD, ap2, ap); else if (sz < 0) gen_code(op_movsx, ap2, ap); else gen_code(op_movzx, ap2, ap); } } else { /* Should never get here */ DIAG("float reg assigned in analyze"); } if (lvalue(exptr) && ((SYM*)exptr->v.p[0]->v.p[0])->funcparm) { ((SYM*)exptr->v.p[0]->v.p[0])->mainsym->inreg = TRUE; ((SYM*)exptr->v.p[0]->v.p[0])->mainsym->value.i = - csp ->reg - (csp->size < 0 ? - csp->size: csp->size) *256; } } } csp = csp->next; } gen_label(startlab); }
void allocate(int datareg, int addreg, int floatreg, SNODE *block) /* * allocate will allocate registers for the expressions that have * a high enough desirability. It also puts the function * header, consisting of saved registers and stack decrments for local * variables */ { CSE *csp; ENODE *exptr; unsigned mask, rmask, i, fmask, frmask, size; AMODE *ap, *ap2; mask = asmMask; rmask = asmRMask; fmask = frmask = 0; for (i = cf_freedata; i < datareg; i++) { rmask = rmask | (1 << (15-i)); mask = mask | (1 << i); } for (i = cf_freeaddress + 16; i < addreg; i++) { rmask = rmask | (1 << (23-i)); mask = mask | (1 << (i - 8)); } while (bsort(&olist)) ; /* sort the expression list */ csp = olist; while (csp != 0) { if (csp->reg == - 1 && !(csp->exp->cflags &DF_VOL) && !csp->voidf) { if (desire(csp) < 3) csp->reg = - 1; else { if (csp->exp->nodetype == en_rcon || csp->exp->nodetype == en_fcon || csp->exp->nodetype == en_lrcon || csp->exp ->nodetype == en_floatref || csp->exp->nodetype == en_doubleref || csp->exp->nodetype == en_longdoubleref || csp->exp->nodetype == en_fimaginarycon || csp->exp->nodetype == en_rimaginarycon || csp->exp->nodetype == en_lrimaginarycon || csp->exp->nodetype == en_fimaginaryref || csp->exp->nodetype == en_rimaginaryref || csp->exp->nodetype == en_lrimaginaryref) {} else if ((csp->duses <= csp->uses / 4) && (datareg < cf_maxdata) && dataregs) csp->reg = (datareg)++; else if (!(csp->size == 1 || csp->size == - 1 || csp->size == 5) && (addreg < cf_maxaddress) && addrregs) csp->reg = (addreg)++; else if ((datareg < cf_maxdata) && dataregs) csp->reg = (datareg)++; if (csp->reg != - 1) // if (lvalue(csp->exp)) // csp->seg = defseg(csp->exp->v.p[0]) ; // else if (!csp->seg) { csp->seg = defseg(csp->exp); if (csp->seg) csp->reg = -1; } } } if (csp->reg != - 1) { if (lvalue(csp->exp) && !((SYM*)csp->exp->v.p[0]->v.p[0])->funcparm) { ((SYM*)csp->exp->v.p[0]->v.p[0])->mainsym->inreg = TRUE; ((SYM*)csp->exp->v.p[0]->v.p[0])->mainsym->value.i = - csp ->reg - (csp->size < 0 ? - csp->size: csp->size) *256; } if (csp->reg < 16) { rmask = rmask | (1 << (15-csp->reg)); mask = mask | (1 << csp->reg); } if (csp->reg < 32) { rmask = rmask | (1 << (23-csp->reg)); mask = mask | (1 << (csp->reg - 8)); } else { frmask = frmask | (1 << (39-csp->reg)); fmask = fmask | (1 << (csp->reg - 32)); } } csp = csp->next; } allocstack(); /* Allocate stack space for the local vars */ floatstack_mode = 0; /* no space for floating point temps */ if (currentfunc->intflag || currentfunc->faultflag) { mask = 0; rmask = 0; if (currentfunc->loadds) loadds(); if (prm_farkeyword) { GenPush(ES + 24, am_dreg, 0); GenPush(FS + 24, am_dreg, 0); GenPush(GS + 24, am_dreg, 0); } gen_code(op_pushad, 0, 0); } if ((conscount || try_block_list || currentfunc->value.classdata.throwlist && currentfunc->value.classdata.throwlist->data) && prm_xcept) { xceptoffs = lc_maxauto += sizeof(XCEPTDATA); } if (prm_debug) { rmask = rmask | (1 << (15-EBX)); mask = mask | (1 << EBX); rmask = rmask | (1 << (15-ESI-4)); mask = mask | (1 << (ESI+4)); rmask = rmask | (1 << (15-EDI-4)); mask = mask | (1 << (EDI+4)); } if (prm_cplusplus && prm_xcept || (funcfloat || lc_maxauto || currentfunc ->tp->lst.head && currentfunc->tp->lst.head != (SYM*) - 1) || (currentfunc->value.classdata.cppflags &PF_MEMBER) && !(currentfunc ->value.classdata.cppflags &PF_STATIC) || !prm_smartframes || !stackframeoff) { /* enter is *really* inefficient so we will not use it */ if (!currentfunc->intflag) gen_codes(op_push, 4, makedreg(EBP), 0); gen_codes(op_mov, 4, makedreg(EBP), makedreg(ESP)); if (lc_maxauto) gen_code(op_sub, makedreg(ESP), make_immed(lc_maxauto)); // FIXME ... could auto-alloc an FP value when no frame! frame_ins = peep_tail; } else frame_ins = 0; if (mask != 0) PushRegs(rmask); save_mask = mask; if (fmask != 0) fsave_mask = fmask; if (currentfunc->loadds && !currentfunc->intflag) { loadds(); } if (prm_stackcheck && lc_maxauto) { AMODE *ap1; ap = set_symbol("__stackerror", 1); ap1 = set_symbol("__stackbottom", 0); ap1->mode = am_direct; gen_codes(op_cmp, 4, makedreg(ESP), ap1); gen_codes(op_jb, 0, ap, 0); } AddProfilerData(); if ((conscount || try_block_list || currentfunc->value.classdata.throwlist && currentfunc->value.classdata.throwlist->data) && prm_xcept) { currentfunc->value.classdata.conslabel = nextlabel++; currentfunc->value.classdata.destlabel = nextlabel++; gen_codes(op_mov, 4, makedreg(EAX), make_label(nextlabel - 2)); call_library("__InitExceptBlock"); gen_label(nextlabel - 1); } }
/* Allocate the match buffer and initialize the various tables. */ CodeTree::CodeTree(int deflate_level, BufferedTransformation &outQ) : BitOutput(outQ), deflate_level(deflate_level), dyn_ltree(HEAP_SIZE), dyn_dtree(2*D_CODES+1), bl_tree(2*BL_CODES+1), bl_count(MAX_BITS+1), l_desc(dyn_ltree, static_ltree, extra_lbits, LITERALS+1, L_CODES, MAX_BITS, 0), d_desc(dyn_dtree, static_dtree, extra_dbits, 0, D_CODES, MAX_BITS, 0), bl_desc(bl_tree, (ct_data *)0, extra_blbits, 0, BL_CODES, MAX_BL_BITS, 0), heap(2*L_CODES+1), depth(2*L_CODES+1), length_code(MAX_MATCH-MIN_MATCH+1), dist_code(512), base_length(LENGTH_CODES), base_dist(D_CODES), l_buf(LIT_BUFSIZE), d_buf(DIST_BUFSIZE), flag_buf(LIT_BUFSIZE/8) { unsigned int n; /* iterates over tree elements */ int bits; /* bit counter */ int length; /* length value */ register int code; /* code value */ int dist; /* distance index */ compressed_len = input_len = 0L; /* Initialize the mapping length (0..255) -> length code (0..28) */ length = 0; for (code=0; code < LENGTH_CODES-1; code++) { base_length[code] = length; for (n=0; n < (1<<extra_lbits[code]); n++) { length_code[length++] = (byte)code; } } assert (length == 256); /* Note that the length 255 (match length 258) can be represented in two different ways: code 284 + 5 bits or code 285, so we overwrite length_code[255] to use the best encoding: */ length_code[length-1] = (byte)code; /* Initialize the mapping dist (0..32K) -> dist code (0..29) */ dist = 0; for (code=0 ; code < 16; code++) { base_dist[code] = dist; for (n=0; n < (1<<extra_dbits[code]); n++) { dist_code[dist++] = (byte)code; } } assert (dist == 256); dist >>= 7; /* from now on, all distances are divided by 128 */ for (; code < D_CODES; code++) { base_dist[code] = dist << 7; for (n=0; n < (1<<(extra_dbits[code]-7)); n++) { dist_code[256 + dist++] = (byte)code; } } assert (dist == 256); if (!streesBuilt) { /* Construct the codes of the static literal tree */ for (bits=0; bits <= MAX_BITS; bits++) bl_count[bits] = 0; n = 0; while (n <= 143) static_ltree[n++].Len = 8, bl_count[8]++; while (n <= 255) static_ltree[n++].Len = 9, bl_count[9]++; while (n <= 279) static_ltree[n++].Len = 7, bl_count[7]++; while (n <= 287) static_ltree[n++].Len = 8, bl_count[8]++; /* Codes 286 and 287 do not exist, but we must include them in the tree construction to get a canonical Huffman tree (longest code all ones) */ gen_codes(static_ltree, L_CODES+1); /* The static distance tree is trivial: */ for (n=0; n < D_CODES; n++) { static_dtree[n].Len = 5; static_dtree[n].Code = reverse(n, 5); } streesBuilt = true; } /* Initialize the first block of the first file: */ init_block(); }
static void build_tree( z_stream& s, tree_desc* desc ) { ct_data* tree = desc->dyn_tree; const ct_data* stree = desc->stat_desc->static_tree; int elems = desc->stat_desc->elems; int max_code = -1; int n, m; int node; s.heap_len = 0, s.heap_max = HEAP_SIZE; for( n = 0 ; n < elems ; n++ ) { if( tree[ n ].Freq ) { s.heap[ ++s.heap_len ] = max_code = n; s.depth[ n ] = 0; } else { tree[ n ].Len = 0; } } while( s.heap_len < 2 ) { node = s.heap[ ++s.heap_len ] = ( max_code < 2 ? ++max_code : 0 ); tree[ node ].Freq = 1; s.depth[ node ] = 0; s.opt_len--; if( stree ) s.static_len -= stree[ node ].Len; } desc->max_code = max_code; for( n = s.heap_len / 2 ; n >= 1 ; n-- ) pqdownheap( s, tree, n ); node = elems; do { pqremove( s, tree, n ); m = s.heap[ SMALLEST ]; s.heap[ --s.heap_max ] = n; s.heap[ --s.heap_max ] = m; tree[ node ].Freq = tree[ n ].Freq + tree[ m ].Freq; s.depth[ node ] = (unsigned char) ( ( s.depth[ n ] >= s.depth[ m ] ? s.depth[ n ] : s.depth[ m ] ) + 1 ); tree[ n ].Dad = tree[ m ].Dad = (unsigned short) node; s.heap[ SMALLEST ] = node++; pqdownheap( s, tree, SMALLEST ); } while( s.heap_len >= 2 ); s.heap[ --s.heap_max ] = s.heap[ SMALLEST ]; gen_bitlen( s, (tree_desc*) desc ); gen_codes( (ct_data*) tree, max_code, s.bl_count ); }