⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 basic-optimizer.c

📁 支持AMD64的汇编编译器源码
💻 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 + -