#include "objfmt.h"
#include "preproc.h"
#include "parser.h"
+#include "optimizer.h"
#include "arch.h"
indent_level--;
symrec_parser_finalize();
- sections_parser_finalize(sections);
+ basic_optimizer.optimize(sections);
- fprintf(obj, "\nSections after post-parser-finalization:\n");
+ fprintf(obj, "\nSections after optimization:\n");
indent_level++;
sections_print(obj, sections);
indent_level--;
void (*bc_delete) (bytecode *bc);
void (*bc_print) (FILE *f, const bytecode *bc);
- void (*bc_parser_finalize) (bytecode *bc);
+
+ /* See bytecode.h comments on bc_calc_len() */
+ int (*bc_calc_len) (bytecode *bc, /*@only@*/ /*@null@*/
+ intnum *(*resolve_label) (section *sect, /*@null@*/
+ bytecode *bc));
} bc;
};
xfree(bc);
}
-int
-bc_get_offset(/*@unused@*/ section *sect, /*@unused@*/ bytecode *bc,
- /*@unused@*/ unsigned long *ret_val)
-{
- return 0; /* TODO */
-}
-
void
bc_print(FILE *f, const bytecode *bc)
{
fprintf(f, "%*sOffset=%lx\n", indent_level, "", bc->offset);
}
-void
-bc_parser_finalize(bytecode *bc)
+int
+bc_calc_len(bytecode *bc,
+ intnum *(*resolve_label) (section *sect, /*@null@*/ bytecode *bc))
{
switch (bc->type) {
case BC_EMPTY:
- /* FIXME: delete it (probably in bytecodes_ level, not here */
- InternalError(_("got empty bytecode in parser_finalize"));
+ InternalError(_("got empty bytecode in bc_calc_len"));
+ case BC_DATA:
+ break;
+ case BC_RESERVE:
+ break;
+ case BC_INCBIN:
+ break;
default:
if (bc->type < cur_arch->bc.type_max)
- cur_arch->bc.bc_parser_finalize(bc);
+ return cur_arch->bc.bc_calc_len(bc, resolve_label);
else
InternalError(_("Unknown bytecode type"));
- break;
}
+ return 0;
}
void
}
}
-void
-bcs_parser_finalize(bytecodehead *headp)
+int
+bcs_traverse(bytecodehead *headp, void *d,
+ int (*func) (bytecode *bc, /*@null@*/ void *d))
{
bytecode *cur;
STAILQ_FOREACH(cur, headp, link)
- bc_parser_finalize(cur);
+ if (func(cur, d) == 0)
+ return 0;
+ return 1;
}
dataval *
void bc_delete(/*@only@*/ /*@null@*/ bytecode *bc);
-/* Gets the offset of the bytecode specified by bc if possible.
- * Return value is IF POSSIBLE, not the value.
- */
-int bc_get_offset(section *sect, bytecode *bc,
- /*@out@*/ unsigned long *ret_val);
-
void bc_print(FILE *f, const bytecode *bc);
-void bc_parser_finalize(bytecode *bc);
+/* Calculates length of bytecode, saving in bc structure.
+ * Returns whether the length is the minimum possible (1=yes, 0=no).
+ * resolve_label is the function used to determine the value (offset) of a
+ * in-file label (eg, not an EXTERN variable, which is indeterminate).
+ */
+int bc_calc_len(bytecode *bc, /*@only@*/ /*@null@*/
+ intnum *(*resolve_label) (section *sect,
+ /*@null@*/ bytecode *bc));
-/* void bytecodes_initialize(bytecodehead *headp); */
-#define bytecodes_initialize(headp) STAILQ_INIT(headp)
+/* void bcs_initialize(bytecodehead *headp); */
+#define bcs_initialize(headp) STAILQ_INIT(headp)
void bcs_delete(bytecodehead *headp);
void bcs_print(FILE *f, const bytecodehead *headp);
-void bcs_parser_finalize(bytecodehead *headp);
+int bcs_traverse(bytecodehead *headp, /*@null@*/ void *d,
+ int (*func) (bytecode *bc, /*@null@*/ void *d));
dataval *dv_new_expr(/*@keep@*/ expr *expn);
dataval *dv_new_float(/*@keep@*/ floatnum *flt);
* This function takes the unoptimized linked list of sections and returns
* an optimized linked list of sections ready for output to an object file.
*/
+ sectionhead *(*optimize) (sectionhead *sections);
};
/* Available optimizers */
s->type = SECTION_GENERAL;
s->data.general.name = xstrdup(name);
s->data.general.of_data = of_data;
- bytecodes_initialize(&s->bc);
+ bcs_initialize(&s->bc);
s->opt_flags = 0;
s->res_only = res_only;
s->type = SECTION_ABSOLUTE;
s->data.start = start;
- bytecodes_initialize(&s->bc);
+ bcs_initialize(&s->bc);
s->opt_flags = 0;
s->res_only = 1;
}
}
-void
-sections_parser_finalize(sectionhead *headp)
+int
+sections_traverse(sectionhead *headp, /*@null@*/ void *d,
+ int (*func) (section *sect, /*@null@*/ void *d))
{
section *cur;
STAILQ_FOREACH(cur, headp, link)
- bcs_parser_finalize(&cur->bc);
+ if (func(cur, d) == 0)
+ return 0;
+ return 1;
}
bytecodehead *
void sections_print(FILE *f, const sectionhead *headp);
-void sections_parser_finalize(sectionhead *headp);
+int sections_traverse(sectionhead *headp, /*@null@*/ void *d,
+ int (*func) (section *sect, /*@null@*/ void *d));
/*@dependent@*/ bytecodehead *section_get_bytecodes(section *sect);
X86_BYTECODE_TYPE_MAX,
x86_bc_delete,
x86_bc_print,
- x86_bc_parser_finalize
+ x86_bc_calc_len
}
};
}
}
-static void
-x86_bc_parser_finalize_insn(x86_insn *insn)
+static int
+x86_bc_calc_len_insn(x86_insn *insn, /*@only@*/ /*@null@*/
+ intnum *(*resolve_label) (section *sect,
+ /*@null@*/ bytecode *bc))
{
effaddr *ea = insn->ea;
x86_effaddr_data *ead = ea_get_data(ea);
ea->nosplit, &ea->len, &ead->modrm,
&ead->valid_modrm, &ead->need_modrm,
&ead->sib, &ead->valid_sib, &ead->need_sib))
- return; /* failed, don't bother checking rest of insn */
+ return 0; /* failed, don't bother checking rest of insn */
}
}
}
}
-
+ return 0;
}
-void
-x86_bc_parser_finalize(bytecode *bc)
+int
+x86_bc_calc_len(bytecode *bc,
+ intnum *(*resolve_label) (section *sect,
+ /*@null@*/ bytecode *bc))
{
x86_insn *insn;
switch ((x86_bytecode_type)bc->type) {
case X86_BC_INSN:
insn = bc_get_data(bc);
- x86_bc_parser_finalize_insn(insn);
- break;
+ return x86_bc_calc_len_insn(insn, resolve_label);
default:
break;
}
+ return 0;
}
void x86_bc_delete(bytecode *bc);
void x86_bc_print(FILE *f, const bytecode *bc);
-void x86_bc_parser_finalize(bytecode *bc);
+int x86_bc_calc_len(bytecode *bc, /*@only@*/ /*@null@*/
+ intnum *(*resolve_label) (section *sect,
+ /*@null@*/ bytecode *bc));
int x86_expr_checkea(expr **ep, unsigned char *addrsize, unsigned char bits,
unsigned char nosplit, unsigned char *displen,
X86_BYTECODE_TYPE_MAX,
x86_bc_delete,
x86_bc_print,
- x86_bc_parser_finalize
+ x86_bc_calc_len
}
};
}
}
-static void
-x86_bc_parser_finalize_insn(x86_insn *insn)
+static int
+x86_bc_calc_len_insn(x86_insn *insn, /*@only@*/ /*@null@*/
+ intnum *(*resolve_label) (section *sect,
+ /*@null@*/ bytecode *bc))
{
effaddr *ea = insn->ea;
x86_effaddr_data *ead = ea_get_data(ea);
ea->nosplit, &ea->len, &ead->modrm,
&ead->valid_modrm, &ead->need_modrm,
&ead->sib, &ead->valid_sib, &ead->need_sib))
- return; /* failed, don't bother checking rest of insn */
+ return 0; /* failed, don't bother checking rest of insn */
}
}
}
}
-
+ return 0;
}
-void
-x86_bc_parser_finalize(bytecode *bc)
+int
+x86_bc_calc_len(bytecode *bc,
+ intnum *(*resolve_label) (section *sect,
+ /*@null@*/ bytecode *bc))
{
x86_insn *insn;
switch ((x86_bytecode_type)bc->type) {
case X86_BC_INSN:
insn = bc_get_data(bc);
- x86_bc_parser_finalize_insn(insn);
- break;
+ return x86_bc_calc_len_insn(insn, resolve_label);
default:
break;
}
+ return 0;
}
#include "util.h"
RCSID("$IdPath$");
+#include "bytecode.h"
+#include "section.h"
+
+#include "bc-int.h"
+
#include "optimizer.h"
+#define SECTFLAG_NONE 0
+#define SECTFLAG_INPROGRESS (1<<0)
+#define SECTFLAG_DONE (1<<1)
+
+#define BCFLAG_NONE 0
+#define BCFLAG_INPROGRESS (1<<0)
+#define BCFLAG_DONE (1<<1)
+
+static /*@only@*/ /*@null@*/ intnum *
+basic_optimize_resolve_label(section *sect, bytecode *bc)
+{
+ unsigned long flags;
+
+ flags = section_get_opt_flags(sect);
+
+ return NULL;
+}
+
+static int
+basic_optimize_bytecode(bytecode *bc, /*@unused@*/ /*@null@*/ void *d)
+{
+ bc->opt_flags = BCFLAG_INPROGRESS;
+
+ bc_calc_len(bc, basic_optimize_resolve_label);
+
+ bc->opt_flags = BCFLAG_DONE;
+
+ return 1;
+}
+
+static int
+basic_optimize_section(section *sect, /*@unused@*/ /*@null@*/ void *d)
+{
+ section_set_opt_flags(sect, SECTFLAG_INPROGRESS);
+
+ bcs_traverse(section_get_bytecodes(sect), NULL, basic_optimize_bytecode);
+
+ section_set_opt_flags(sect, SECTFLAG_DONE);
+
+ return 1;
+}
+
+static sectionhead *
+basic_optimize(sectionhead *sections)
+{
+ /* Optimization process: (essentially NASM's pass 1)
+ * Determine the size of all bytecodes.
+ * 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.
+ */
+ sections_traverse(sections, NULL, basic_optimize_section);
+
+ /* NASM's pass 2 is output, so we just return. */
+ return sections;
+}
+
/* Define optimizer structure -- see optimizer.h for details */
optimizer basic_optimizer = {
"Only the most basic optimizations",
- "basic"
+ "basic",
+ basic_optimize
};
#include "util.h"
RCSID("$IdPath$");
+#include "bytecode.h"
+#include "section.h"
+
+#include "bc-int.h"
+
#include "optimizer.h"
+#define SECTFLAG_NONE 0
+#define SECTFLAG_INPROGRESS (1<<0)
+#define SECTFLAG_DONE (1<<1)
+
+#define BCFLAG_NONE 0
+#define BCFLAG_INPROGRESS (1<<0)
+#define BCFLAG_DONE (1<<1)
+
+static /*@only@*/ /*@null@*/ intnum *
+basic_optimize_resolve_label(section *sect, bytecode *bc)
+{
+ unsigned long flags;
+
+ flags = section_get_opt_flags(sect);
+
+ return NULL;
+}
+
+static int
+basic_optimize_bytecode(bytecode *bc, /*@unused@*/ /*@null@*/ void *d)
+{
+ bc->opt_flags = BCFLAG_INPROGRESS;
+
+ bc_calc_len(bc, basic_optimize_resolve_label);
+
+ bc->opt_flags = BCFLAG_DONE;
+
+ return 1;
+}
+
+static int
+basic_optimize_section(section *sect, /*@unused@*/ /*@null@*/ void *d)
+{
+ section_set_opt_flags(sect, SECTFLAG_INPROGRESS);
+
+ bcs_traverse(section_get_bytecodes(sect), NULL, basic_optimize_bytecode);
+
+ section_set_opt_flags(sect, SECTFLAG_DONE);
+
+ return 1;
+}
+
+static sectionhead *
+basic_optimize(sectionhead *sections)
+{
+ /* Optimization process: (essentially NASM's pass 1)
+ * Determine the size of all bytecodes.
+ * 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.
+ */
+ sections_traverse(sections, NULL, basic_optimize_section);
+
+ /* NASM's pass 2 is output, so we just return. */
+ return sections;
+}
+
/* Define optimizer structure -- see optimizer.h for details */
optimizer basic_optimizer = {
"Only the most basic optimizations",
- "basic"
+ "basic",
+ basic_optimize
};
void (*bc_delete) (bytecode *bc);
void (*bc_print) (FILE *f, const bytecode *bc);
- void (*bc_parser_finalize) (bytecode *bc);
+
+ /* See bytecode.h comments on bc_calc_len() */
+ int (*bc_calc_len) (bytecode *bc, /*@only@*/ /*@null@*/
+ intnum *(*resolve_label) (section *sect, /*@null@*/
+ bytecode *bc));
} bc;
};
X86_BYTECODE_TYPE_MAX,
x86_bc_delete,
x86_bc_print,
- x86_bc_parser_finalize
+ x86_bc_calc_len
}
};
}
}
-static void
-x86_bc_parser_finalize_insn(x86_insn *insn)
+static int
+x86_bc_calc_len_insn(x86_insn *insn, /*@only@*/ /*@null@*/
+ intnum *(*resolve_label) (section *sect,
+ /*@null@*/ bytecode *bc))
{
effaddr *ea = insn->ea;
x86_effaddr_data *ead = ea_get_data(ea);
ea->nosplit, &ea->len, &ead->modrm,
&ead->valid_modrm, &ead->need_modrm,
&ead->sib, &ead->valid_sib, &ead->need_sib))
- return; /* failed, don't bother checking rest of insn */
+ return 0; /* failed, don't bother checking rest of insn */
}
}
}
}
-
+ return 0;
}
-void
-x86_bc_parser_finalize(bytecode *bc)
+int
+x86_bc_calc_len(bytecode *bc,
+ intnum *(*resolve_label) (section *sect,
+ /*@null@*/ bytecode *bc))
{
x86_insn *insn;
switch ((x86_bytecode_type)bc->type) {
case X86_BC_INSN:
insn = bc_get_data(bc);
- x86_bc_parser_finalize_insn(insn);
- break;
+ return x86_bc_calc_len_insn(insn, resolve_label);
default:
break;
}
+ return 0;
}
void x86_bc_delete(bytecode *bc);
void x86_bc_print(FILE *f, const bytecode *bc);
-void x86_bc_parser_finalize(bytecode *bc);
+int x86_bc_calc_len(bytecode *bc, /*@only@*/ /*@null@*/
+ intnum *(*resolve_label) (section *sect,
+ /*@null@*/ bytecode *bc));
int x86_expr_checkea(expr **ep, unsigned char *addrsize, unsigned char bits,
unsigned char nosplit, unsigned char *displen,
X86_BYTECODE_TYPE_MAX,
x86_bc_delete,
x86_bc_print,
- x86_bc_parser_finalize
+ x86_bc_calc_len
}
};
}
}
-static void
-x86_bc_parser_finalize_insn(x86_insn *insn)
+static int
+x86_bc_calc_len_insn(x86_insn *insn, /*@only@*/ /*@null@*/
+ intnum *(*resolve_label) (section *sect,
+ /*@null@*/ bytecode *bc))
{
effaddr *ea = insn->ea;
x86_effaddr_data *ead = ea_get_data(ea);
ea->nosplit, &ea->len, &ead->modrm,
&ead->valid_modrm, &ead->need_modrm,
&ead->sib, &ead->valid_sib, &ead->need_sib))
- return; /* failed, don't bother checking rest of insn */
+ return 0; /* failed, don't bother checking rest of insn */
}
}
}
}
-
+ return 0;
}
-void
-x86_bc_parser_finalize(bytecode *bc)
+int
+x86_bc_calc_len(bytecode *bc,
+ intnum *(*resolve_label) (section *sect,
+ /*@null@*/ bytecode *bc))
{
x86_insn *insn;
switch ((x86_bytecode_type)bc->type) {
case X86_BC_INSN:
insn = bc_get_data(bc);
- x86_bc_parser_finalize_insn(insn);
- break;
+ return x86_bc_calc_len_insn(insn, resolve_label);
default:
break;
}
+ return 0;
}
xfree(bc);
}
-int
-bc_get_offset(/*@unused@*/ section *sect, /*@unused@*/ bytecode *bc,
- /*@unused@*/ unsigned long *ret_val)
-{
- return 0; /* TODO */
-}
-
void
bc_print(FILE *f, const bytecode *bc)
{
fprintf(f, "%*sOffset=%lx\n", indent_level, "", bc->offset);
}
-void
-bc_parser_finalize(bytecode *bc)
+int
+bc_calc_len(bytecode *bc,
+ intnum *(*resolve_label) (section *sect, /*@null@*/ bytecode *bc))
{
switch (bc->type) {
case BC_EMPTY:
- /* FIXME: delete it (probably in bytecodes_ level, not here */
- InternalError(_("got empty bytecode in parser_finalize"));
+ InternalError(_("got empty bytecode in bc_calc_len"));
+ case BC_DATA:
+ break;
+ case BC_RESERVE:
+ break;
+ case BC_INCBIN:
+ break;
default:
if (bc->type < cur_arch->bc.type_max)
- cur_arch->bc.bc_parser_finalize(bc);
+ return cur_arch->bc.bc_calc_len(bc, resolve_label);
else
InternalError(_("Unknown bytecode type"));
- break;
}
+ return 0;
}
void
}
}
-void
-bcs_parser_finalize(bytecodehead *headp)
+int
+bcs_traverse(bytecodehead *headp, void *d,
+ int (*func) (bytecode *bc, /*@null@*/ void *d))
{
bytecode *cur;
STAILQ_FOREACH(cur, headp, link)
- bc_parser_finalize(cur);
+ if (func(cur, d) == 0)
+ return 0;
+ return 1;
}
dataval *
void bc_delete(/*@only@*/ /*@null@*/ bytecode *bc);
-/* Gets the offset of the bytecode specified by bc if possible.
- * Return value is IF POSSIBLE, not the value.
- */
-int bc_get_offset(section *sect, bytecode *bc,
- /*@out@*/ unsigned long *ret_val);
-
void bc_print(FILE *f, const bytecode *bc);
-void bc_parser_finalize(bytecode *bc);
+/* Calculates length of bytecode, saving in bc structure.
+ * Returns whether the length is the minimum possible (1=yes, 0=no).
+ * resolve_label is the function used to determine the value (offset) of a
+ * in-file label (eg, not an EXTERN variable, which is indeterminate).
+ */
+int bc_calc_len(bytecode *bc, /*@only@*/ /*@null@*/
+ intnum *(*resolve_label) (section *sect,
+ /*@null@*/ bytecode *bc));
-/* void bytecodes_initialize(bytecodehead *headp); */
-#define bytecodes_initialize(headp) STAILQ_INIT(headp)
+/* void bcs_initialize(bytecodehead *headp); */
+#define bcs_initialize(headp) STAILQ_INIT(headp)
void bcs_delete(bytecodehead *headp);
void bcs_print(FILE *f, const bytecodehead *headp);
-void bcs_parser_finalize(bytecodehead *headp);
+int bcs_traverse(bytecodehead *headp, /*@null@*/ void *d,
+ int (*func) (bytecode *bc, /*@null@*/ void *d));
dataval *dv_new_expr(/*@keep@*/ expr *expn);
dataval *dv_new_float(/*@keep@*/ floatnum *flt);
#include "objfmt.h"
#include "preproc.h"
#include "parser.h"
+#include "optimizer.h"
#include "arch.h"
indent_level--;
symrec_parser_finalize();
- sections_parser_finalize(sections);
+ basic_optimizer.optimize(sections);
- fprintf(obj, "\nSections after post-parser-finalization:\n");
+ fprintf(obj, "\nSections after optimization:\n");
indent_level++;
sections_print(obj, sections);
indent_level--;
* This function takes the unoptimized linked list of sections and returns
* an optimized linked list of sections ready for output to an object file.
*/
+ sectionhead *(*optimize) (sectionhead *sections);
};
/* Available optimizers */
#include "util.h"
RCSID("$IdPath$");
+#include "bytecode.h"
+#include "section.h"
+
+#include "bc-int.h"
+
#include "optimizer.h"
+#define SECTFLAG_NONE 0
+#define SECTFLAG_INPROGRESS (1<<0)
+#define SECTFLAG_DONE (1<<1)
+
+#define BCFLAG_NONE 0
+#define BCFLAG_INPROGRESS (1<<0)
+#define BCFLAG_DONE (1<<1)
+
+static /*@only@*/ /*@null@*/ intnum *
+basic_optimize_resolve_label(section *sect, bytecode *bc)
+{
+ unsigned long flags;
+
+ flags = section_get_opt_flags(sect);
+
+ return NULL;
+}
+
+static int
+basic_optimize_bytecode(bytecode *bc, /*@unused@*/ /*@null@*/ void *d)
+{
+ bc->opt_flags = BCFLAG_INPROGRESS;
+
+ bc_calc_len(bc, basic_optimize_resolve_label);
+
+ bc->opt_flags = BCFLAG_DONE;
+
+ return 1;
+}
+
+static int
+basic_optimize_section(section *sect, /*@unused@*/ /*@null@*/ void *d)
+{
+ section_set_opt_flags(sect, SECTFLAG_INPROGRESS);
+
+ bcs_traverse(section_get_bytecodes(sect), NULL, basic_optimize_bytecode);
+
+ section_set_opt_flags(sect, SECTFLAG_DONE);
+
+ return 1;
+}
+
+static sectionhead *
+basic_optimize(sectionhead *sections)
+{
+ /* Optimization process: (essentially NASM's pass 1)
+ * Determine the size of all bytecodes.
+ * 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.
+ */
+ sections_traverse(sections, NULL, basic_optimize_section);
+
+ /* NASM's pass 2 is output, so we just return. */
+ return sections;
+}
+
/* Define optimizer structure -- see optimizer.h for details */
optimizer basic_optimizer = {
"Only the most basic optimizations",
- "basic"
+ "basic",
+ basic_optimize
};
#include "util.h"
RCSID("$IdPath$");
+#include "bytecode.h"
+#include "section.h"
+
+#include "bc-int.h"
+
#include "optimizer.h"
+#define SECTFLAG_NONE 0
+#define SECTFLAG_INPROGRESS (1<<0)
+#define SECTFLAG_DONE (1<<1)
+
+#define BCFLAG_NONE 0
+#define BCFLAG_INPROGRESS (1<<0)
+#define BCFLAG_DONE (1<<1)
+
+static /*@only@*/ /*@null@*/ intnum *
+basic_optimize_resolve_label(section *sect, bytecode *bc)
+{
+ unsigned long flags;
+
+ flags = section_get_opt_flags(sect);
+
+ return NULL;
+}
+
+static int
+basic_optimize_bytecode(bytecode *bc, /*@unused@*/ /*@null@*/ void *d)
+{
+ bc->opt_flags = BCFLAG_INPROGRESS;
+
+ bc_calc_len(bc, basic_optimize_resolve_label);
+
+ bc->opt_flags = BCFLAG_DONE;
+
+ return 1;
+}
+
+static int
+basic_optimize_section(section *sect, /*@unused@*/ /*@null@*/ void *d)
+{
+ section_set_opt_flags(sect, SECTFLAG_INPROGRESS);
+
+ bcs_traverse(section_get_bytecodes(sect), NULL, basic_optimize_bytecode);
+
+ section_set_opt_flags(sect, SECTFLAG_DONE);
+
+ return 1;
+}
+
+static sectionhead *
+basic_optimize(sectionhead *sections)
+{
+ /* Optimization process: (essentially NASM's pass 1)
+ * Determine the size of all bytecodes.
+ * 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.
+ */
+ sections_traverse(sections, NULL, basic_optimize_section);
+
+ /* NASM's pass 2 is output, so we just return. */
+ return sections;
+}
+
/* Define optimizer structure -- see optimizer.h for details */
optimizer basic_optimizer = {
"Only the most basic optimizations",
- "basic"
+ "basic",
+ basic_optimize
};
s->type = SECTION_GENERAL;
s->data.general.name = xstrdup(name);
s->data.general.of_data = of_data;
- bytecodes_initialize(&s->bc);
+ bcs_initialize(&s->bc);
s->opt_flags = 0;
s->res_only = res_only;
s->type = SECTION_ABSOLUTE;
s->data.start = start;
- bytecodes_initialize(&s->bc);
+ bcs_initialize(&s->bc);
s->opt_flags = 0;
s->res_only = 1;
}
}
-void
-sections_parser_finalize(sectionhead *headp)
+int
+sections_traverse(sectionhead *headp, /*@null@*/ void *d,
+ int (*func) (section *sect, /*@null@*/ void *d))
{
section *cur;
STAILQ_FOREACH(cur, headp, link)
- bcs_parser_finalize(&cur->bc);
+ if (func(cur, d) == 0)
+ return 0;
+ return 1;
}
bytecodehead *
void sections_print(FILE *f, const sectionhead *headp);
-void sections_parser_finalize(sectionhead *headp);
+int sections_traverse(sectionhead *headp, /*@null@*/ void *d,
+ int (*func) (section *sect, /*@null@*/ void *d));
/*@dependent@*/ bytecodehead *section_get_bytecodes(section *sect);