mirror of https://github.com/yasm/yasm.git
This doesn't really work yet, which is why it's on a branch! svn path=/branches/new-optimizer/; revision=12690.6.0
parent
be801e73db
commit
77a535f673
24 changed files with 609 additions and 891 deletions
@ -1,54 +0,0 @@ |
|||||||
/**
|
|
||||||
* \file libyasm/optimizer.h |
|
||||||
* \brief YASM optimizer module interface. |
|
||||||
* |
|
||||||
* \rcs |
|
||||||
* $Id$ |
|
||||||
* \endrcs |
|
||||||
* |
|
||||||
* \license |
|
||||||
* 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. |
|
||||||
* \endlicense |
|
||||||
*/ |
|
||||||
#ifndef YASM_OPTIMIZER_H |
|
||||||
#define YASM_OPTIMIZER_H |
|
||||||
|
|
||||||
/** YASM optimizer module interface. */ |
|
||||||
typedef struct yasm_optimizer_module { |
|
||||||
/** One-line description of the optimizer */ |
|
||||||
const char *name; |
|
||||||
|
|
||||||
/** Keyword used to select optimizer on the command line */ |
|
||||||
const char *keyword; |
|
||||||
|
|
||||||
/** Optimize an object. Takes the unoptimized object and optimizes it.
|
|
||||||
* If successful, the object is ready for output to an object file. |
|
||||||
* \param object object |
|
||||||
* \note Optimization failures are indicated by this function calling |
|
||||||
* yasm__error_at(); see errwarn.h for details. |
|
||||||
*/ |
|
||||||
void (*optimize) (yasm_object *object); |
|
||||||
} yasm_optimizer_module; |
|
||||||
|
|
||||||
#endif |
|
@ -1,5 +0,0 @@ |
|||||||
# $Id$ |
|
||||||
|
|
||||||
EXTRA_DIST += modules/optimizers/basic/Makefile.inc |
|
||||||
|
|
||||||
include modules/optimizers/basic/Makefile.inc |
|
@ -1,5 +0,0 @@ |
|||||||
# $Id$ |
|
||||||
|
|
||||||
libyasm_a_SOURCES += modules/optimizers/basic/basic-optimizer.c |
|
||||||
|
|
||||||
YASM_MODULES += optimizer_basic |
|
@ -1,234 +0,0 @@ |
|||||||
/*
|
|
||||||
* 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$"); |
|
||||||
|
|
||||||
#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 int |
|
||||||
basic_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 int |
|
||||||
basic_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 int |
|
||||||
basic_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) |
|
||||||
& YASM_BC_RESOLVE_ERROR) |
|
||||||
return -1; |
|
||||||
return 0; |
|
||||||
} |
|
||||||
|
|
||||||
static int |
|
||||||
basic_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 void |
|
||||||
basic_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 = { |
|
||||||
"Only the most basic optimizations", |
|
||||||
"basic", |
|
||||||
basic_optimize |
|
||||||
}; |
|
Loading…
Reference in new issue