?? basic-optimizer.c
字號:
/* * Basic optimizer (equivalent to the NASM 2-pass 'no optimizer' design) * * Copyright (C) 2001 Peter Johnson * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS'' * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */#include <util.h>/*@unused@*/ RCSID("$Id: basic-optimizer.c 1137 2004-09-04 01:24:57Z peter $");#define YASM_LIB_INTERNAL#define YASM_BC_INTERNAL#include <libyasm.h>#define SECTFLAG_NONE 0UL#define SECTFLAG_INPROGRESS (1UL<<0)#define SECTFLAG_DONE (1UL<<1)#define BCFLAG_NONE 0UL#define BCFLAG_INPROGRESS (1UL<<0)#define BCFLAG_DONE (1UL<<1)static int basic_optimize_section_1(yasm_section *sect, /*@unused@*/ /*@null@*/ void *d);static /*@null@*/ yasm_intnum *basic_optimize_calc_bc_dist_1(yasm_bytecode *precbc1, yasm_bytecode *precbc2){ unsigned int dist; yasm_intnum *intn; if (precbc1->section != precbc2->section) yasm_internal_error(N_("Trying to calc_bc_dist between sections")); if (yasm_section_get_opt_flags(precbc1->section) == SECTFLAG_NONE) { /* Section not started. Optimize it (recursively). */ basic_optimize_section_1(precbc1->section, NULL); } /* If a section is done, the following will always succeed. If it's in- * progress, this will fail if the bytecode comes AFTER the current one. */ if (precbc2 != yasm_section_bcs_first(precbc2->section)) { if (precbc2->opt_flags == BCFLAG_DONE) { dist = precbc2->offset + precbc2->len; if (precbc1 != yasm_section_bcs_first(precbc1->section)) { if (precbc1->opt_flags == BCFLAG_DONE) { if (dist < precbc1->offset + precbc1->len) { intn = yasm_intnum_create_uint(precbc1->offset + precbc1->len - dist); yasm_intnum_calc(intn, YASM_EXPR_NEG, NULL, precbc1->line); return intn; } dist -= precbc1->offset + precbc1->len; } else { return NULL; } } return yasm_intnum_create_uint(dist); } else { return NULL; } } else { if (precbc1 != yasm_section_bcs_first(precbc1->section)) { if (precbc1->opt_flags == BCFLAG_DONE) { intn = yasm_intnum_create_uint(precbc1->offset + precbc1->len); yasm_intnum_calc(intn, YASM_EXPR_NEG, NULL, precbc1->line); return intn; } else { return NULL; } } else { return yasm_intnum_create_uint(0); } }}typedef struct basic_optimize_data { /*@observer@*/ yasm_bytecode *precbc; int saw_unknown;} basic_optimize_data;static intbasic_optimize_bytecode_1(/*@observer@*/ yasm_bytecode *bc, void *d){ basic_optimize_data *data = (basic_optimize_data *)d; yasm_bc_resolve_flags bcr_retval; /* Don't even bother if we're in-progress or done. */ if (bc->opt_flags == BCFLAG_INPROGRESS) return 1; if (bc->opt_flags == BCFLAG_DONE) return 0; bc->opt_flags = BCFLAG_INPROGRESS; bc->offset = data->precbc->offset + data->precbc->len; data->precbc = bc; /* We're doing just a single pass, so essentially ignore whether the size * is minimum or not, and just check for indeterminate length (indicative * of circular reference). */ bcr_retval = yasm_bc_resolve(bc, 0, basic_optimize_calc_bc_dist_1); if (bcr_retval & YASM_BC_RESOLVE_UNKNOWN_LEN) { if (!(bcr_retval & YASM_BC_RESOLVE_ERROR)) yasm__error(bc->line, N_("circular reference detected.")); data->saw_unknown = -1; return 0; } bc->opt_flags = BCFLAG_DONE; return 0;}static intbasic_optimize_section_1(yasm_section *sect, /*@null@*/ void *d){ /*@null@*/ int *saw_unknown = (int *)d; basic_optimize_data data; unsigned long flags; int retval; data.precbc = yasm_section_bcs_first(sect); data.saw_unknown = 0; /* Don't even bother if we're in-progress or done. */ flags = yasm_section_get_opt_flags(sect); if (flags == SECTFLAG_INPROGRESS) return 1; if (flags == SECTFLAG_DONE) return 0; yasm_section_set_opt_flags(sect, SECTFLAG_INPROGRESS); retval = yasm_section_bcs_traverse(sect, &data, basic_optimize_bytecode_1); if (retval != 0) return retval; if (data.saw_unknown != 0 && saw_unknown) *saw_unknown = data.saw_unknown; yasm_section_set_opt_flags(sect, SECTFLAG_DONE); return 0;}static intbasic_optimize_bytecode_2(/*@observer@*/ yasm_bytecode *bc, /*@null@*/ void *d){ basic_optimize_data *data = (basic_optimize_data *)d; assert(data != NULL); if (bc->opt_flags != BCFLAG_DONE) yasm_internal_error(N_("Optimizer pass 1 missed a bytecode!")); bc->offset = data->precbc->offset + data->precbc->len; data->precbc = bc; if (yasm_bc_resolve(bc, 1, yasm_common_calc_bc_dist) < 0) return -1; return 0;}static intbasic_optimize_section_2(yasm_section *sect, /*@unused@*/ /*@null@*/ void *d){ basic_optimize_data data; data.precbc = yasm_section_bcs_first(sect); if (yasm_section_get_opt_flags(sect) != SECTFLAG_DONE) yasm_internal_error(N_("Optimizer pass 1 missed a section!")); return yasm_section_bcs_traverse(sect, &data, basic_optimize_bytecode_2);}static voidbasic_optimize(yasm_object *object){ int saw_unknown = 0; /* Optimization process: (essentially NASM's pass 1) * Determine the size of all bytecodes. * Forward references are /not/ resolved (only backward references are * computed and sized). * Check "critical" expressions (must be computable on the first pass, * i.e. depend only on symbols before it). * Differences from NASM: * - right-hand side of EQU is /not/ a critical expr (as the entire file * has already been parsed, we know all their values at this point). * - not strictly top->bottom scanning; we scan through a section and * hop to other sections as necessary. */ if (yasm_object_sections_traverse(object, &saw_unknown, basic_optimize_section_1) < 0 || saw_unknown != 0) return; /* Check completion of all sections and save bytecode changes */ yasm_object_sections_traverse(object, NULL, basic_optimize_section_2);}/* Define optimizer structure -- see optimizer.h for details */yasm_optimizer_module yasm_basic_LTX_optimizer = { YASM_OPTIMIZER_VERSION, "Only the most basic optimizations", "basic", basic_optimize};
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -