INLINE_STATIC void switch_to_line (int line) { int sz = CURRENT_PROGRAM_SIZE - last_size_generated; ADDRESS_TYPE s; unsigned char *p; if (sz) { s = line_being_generated; last_size_generated += sz; while (sz > 255) { p = (unsigned char *)allocate_in_mem_block(A_LINENUMBERS, sizeof(ADDRESS_TYPE) + 1); *p++ = 255; #if !defined(USE_32BIT_ADDRESSES) STORE_SHORT(p, s); #else STORE_INT(p, s); #endif sz -= 255; } p = (unsigned char *)allocate_in_mem_block(A_LINENUMBERS, sizeof(ADDRESS_TYPE) + 1); *p++ = sz; #if !defined(USE_32BIT_ADDRESSES) STORE_SHORT(p, s); #else STORE_INT(p, s); #endif } line_being_generated = line; }
INLINE void switch_to_line P1(int, line) { int sz = CURRENT_PROGRAM_SIZE - last_size_generated; short s; unsigned char *p; /* should be fixed later */ if (current_block != A_PROGRAM) return; if (sz) { s = line_being_generated; last_size_generated += sz; while (sz > 255) { p = (unsigned char *)allocate_in_mem_block(A_LINENUMBERS, 3); *p++ = 255; STORE_SHORT(p, s); sz -= 255; } p = (unsigned char *)allocate_in_mem_block(A_LINENUMBERS, 3); *p++ = sz; STORE_SHORT(p, s); } line_being_generated = line; }
/* * Store a 2 byte number. It is stored in such a way as to be sure * that correct byte order is used, regardless of machine architecture. * Also beware that some machines can't write a word to odd addresses. */ static void ins_short P1(short, l) { if (prog_code + 2 > prog_code_max) { mem_block_t *mbp = &mem_block[A_PROGRAM]; UPDATE_PROGRAM_SIZE; realloc_mem_block(mbp); prog_code = mbp->block + mbp->current_size; prog_code_max = mbp->block + mbp->max_size; } STORE_SHORT(prog_code, l); }
/* Currently, this procedure handles: * - jump threading */ void optimize_icode P3(char *, start, char *, pc, char *, end) { int instr; if (start == 0) { /* we don't optimize the initializer block right now b/c all the * stuff we do (jump threading, etc) can't occur there. */ start = mem_block[A_PROGRAM].block; pc = start; end = pc + mem_block[A_PROGRAM].current_size; if (*pc == 0) { /* no initializer jump */ pc += 3; } } while (pc < end) { switch (instr = EXTRACT_UCHAR(pc++)) { case F_NUMBER: case F_REAL: case F_CALL_INHERITED: pc += 4; break; case F_SIMUL_EFUN: case F_CALL_FUNCTION_BY_ADDRESS: pc += 3; break; case F_BRANCH: case F_BRANCH_WHEN_ZERO: case F_BRANCH_WHEN_NON_ZERO: case F_BBRANCH: case F_BBRANCH_WHEN_ZERO: case F_BBRANCH_WHEN_NON_ZERO: { char *tmp; short sarg; /* thread jumps */ COPY_SHORT(&sarg, pc); if (instr > F_BRANCH) tmp = pc - sarg; else tmp = pc + sarg; sarg = 0; while (1) { if (EXTRACT_UCHAR(tmp) == F_BRANCH) { COPY_SHORT(&sarg, tmp + 1); tmp += sarg + 1; } else if (EXTRACT_UCHAR(tmp) == F_BBRANCH) { COPY_SHORT(&sarg, tmp + 1); tmp -= sarg - 1; } else break; } if (!sarg) { pc += 2; break; } /* be careful; in the process of threading a forward jump * may have changed to a reverse one or vice versa */ if (tmp > pc) { if (instr > F_BRANCH) { pc[-1] -= 3; /* change to forward branch */ } sarg = tmp - pc; } else { if (instr <= F_BRANCH) { pc[-1] += 3; /* change to backwards branch */ } sarg = pc - tmp; } STORE_SHORT(pc, sarg); break; } #ifdef F_LOR case F_LOR: case F_LAND: { char *tmp; short sarg; /* thread jumps */ COPY_SHORT(&sarg, pc); tmp = pc + sarg; sarg = 0; while (1) { if (EXTRACT_UCHAR(tmp) == F_BRANCH) { COPY_SHORT(&sarg, tmp + 1); tmp += sarg + 1; } else if (EXTRACT_UCHAR(tmp) == F_BBRANCH) { COPY_SHORT(&sarg, tmp + 1); tmp -= sarg - 1; } else break; } if (!sarg) { pc += 2; break; } /* be careful; in the process of threading a forward jump * may have changed to a reverse one or vice versa */ if (tmp > pc) { sarg = tmp - pc; } else { #ifdef DEBUG fprintf(stderr,"Optimization failed; can't || or && backwards.\n"); #endif pc += 2; break; } STORE_SHORT(pc, sarg); break; } #endif case F_CATCH: case F_AGGREGATE: case F_AGGREGATE_ASSOC: case F_STRING: #ifdef F_JUMP_WHEN_ZERO case F_JUMP_WHEN_ZERO: case F_JUMP_WHEN_NON_ZERO: #endif #ifdef F_JUMP case F_JUMP: #endif pc += 2; break; case F_GLOBAL_LVALUE: case F_GLOBAL: case F_SHORT_STRING: case F_LOOP_INCR: case F_WHILE_DEC: case F_LOCAL: case F_LOCAL_LVALUE: case F_SSCANF: case F_PARSE_COMMAND: case F_BYTE: case F_POP_BREAK: case F_NBYTE: pc++; break; case F_FUNCTION_CONSTRUCTOR: switch (EXTRACT_UCHAR(pc++)) { case FP_SIMUL: case FP_LOCAL: pc += 2; break; case FP_FUNCTIONAL: case FP_FUNCTIONAL | FP_NOT_BINDABLE: pc += 3; break; case FP_ANONYMOUS: pc += 4; break; case FP_EFUN: #ifdef NEEDS_CALL_EXTRA if (EXTRACT_UCHAR(pc++) == F_CALL_EXTRA) #endif pc++; break; } break; case F_LOOP_COND: if (*pc++ == F_LOCAL) pc += 3; else pc += 7; break; case F_SWITCH: { unsigned short stable, etable; pc++; /* table type */ LOAD_SHORT(stable, pc); LOAD_SHORT(etable, pc); pc += 2; /* def */ DEBUG_CHECK(stable < pc - start || etable < pc - start || etable < stable, "Error in switch table found while optimizing\n"); /* recursively optimize the inside of the switch */ optimize_icode(start, pc, start + stable); pc = start + etable; break; } case F_CALL_EXTRA: instr = EXTRACT_UCHAR(pc++) + 0xff; default: if ((instr >= BASE) && (instrs[instr].min_arg != instrs[instr].max_arg)) pc++; } } }