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