# HG changeset patch # User lost@starbug # Date 1271390166 21600 # Node ID 34dfc9747f234742c5cdabf5c0019d6dac7cda3c # Parent 84dc6d2ec6bae5ee2286c3945bce2fc46ee74215 Reduction passes complete diff -r 84dc6d2ec6ba -r 34dfc9747f23 doc/internals.txt --- a/doc/internals.txt Wed Apr 14 21:02:53 2010 -0600 +++ b/doc/internals.txt Thu Apr 15 21:56:06 2010 -0600 @@ -34,3 +34,19 @@ is forced, try re-resolving all other instructions. This is done starting at the beginning of the source and working forward. If any instruction does not resolve when forced, an error will be thrown. + +Pass 5 +------ + +Constantize all line addresses and throw errors if any cannot be. This +pass will repeat until no further lines addresses are reduced to constants +at which time all lines will be checked for constant-ness. + +Pass 6 +------ + +Finalize all expressions related to instructions. Carp about any that +cannot be reduced to a usable form. That means, for the non-object target +all expressions must resolve to a constant. For the object form, all +expressions must resolve to symbol references and constants. Those symbol +references may be internal or external. diff -r 84dc6d2ec6ba -r 34dfc9747f23 lwasm/Makefile.am --- a/lwasm/Makefile.am Wed Apr 14 21:02:53 2010 -0600 +++ b/lwasm/Makefile.am Thu Apr 15 21:56:06 2010 -0600 @@ -1,7 +1,7 @@ AM_CPPFLAGS = -I$(top_builddir)/lib -I$(top_srcdir)/lib -I$(top_builddir)/lwlib -I$(top_srcdir)/lwlib bin_PROGRAMS = lwasm lwasm_SOURCES = main.c pragma.c input.c pass1.c lwasm.c \ - instab.c symbol.c macro.c pass2.c pass3.c pass4.c \ + instab.c symbol.c macro.c pass2.c pass3.c pass4.c pass5.c pass6.c \ insn_inh.c insn_rtor.c insn_tfm.c insn_rlist.c insn_rel.c \ insn_bitbit.c insn_indexed.c insn_gen.c insn_logicmem.c \ pseudo.c section.c os9.c diff -r 84dc6d2ec6ba -r 34dfc9747f23 lwasm/lwasm.h --- a/lwasm/lwasm.h Wed Apr 14 21:02:53 2010 -0600 +++ b/lwasm/lwasm.h Thu Apr 15 21:56:06 2010 -0600 @@ -41,7 +41,8 @@ lwasm_expr_nextbp = 3, // next branch point lwasm_expr_prevbp = 4, // previous branch point lwasm_expr_syment = 5, // symbol table entry - lwasm_expr_import = 6 // symbol import entry + lwasm_expr_import = 6, // symbol import entry + lwasm_expr_secbase = 7 // section base address }; enum lwasm_output_e diff -r 84dc6d2ec6ba -r 34dfc9747f23 lwasm/main.c --- a/lwasm/main.c Wed Apr 14 21:02:53 2010 -0600 +++ b/lwasm/main.c Thu Apr 15 21:56:06 2010 -0600 @@ -168,6 +168,8 @@ extern void do_pass2(asmstate_t *as); extern void do_pass3(asmstate_t *as); extern void do_pass4(asmstate_t *as); +extern void do_pass5(asmstate_t *as); +extern void do_pass6(asmstate_t *as); extern lw_expr_t lwasm_evaluate_special(int t, void *ptr, void *priv); extern lw_expr_t lwasm_evaluate_var(char *var, void *priv); extern lw_expr_t lwasm_parse_term(char **p, void *priv); @@ -181,6 +183,8 @@ { "symcheck", do_pass2 }, { "resolve1", do_pass3 }, { "resolve2", do_pass4 }, + { "addressresolve", do_pass5 }, + { "finalize", do_pass6 }, { NULL, NULL } }; diff -r 84dc6d2ec6ba -r 34dfc9747f23 lwasm/pass5.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lwasm/pass5.c Thu Apr 15 21:56:06 2010 -0600 @@ -0,0 +1,121 @@ +/* +pass5.c + +Copyright © 2010 William Astle + +This file is part of LWTOOLS. + +LWTOOLS is free software: you can redistribute it and/or modify it under the +terms of the GNU General Public License as published by the Free Software +Foundation, either version 3 of the License, or (at your option) any later +version. + +This program is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +more details. + +You should have received a copy of the GNU General Public License along with +this program. If not, see . +*/ + +#include + +#include +#include + +#include +#include + +#include "lwasm.h" +#include "instab.h" + +/* +AssignAddresses Pass + +Force resolution of all line addresses + +*/ + +static int exprok_aux(lw_expr_t e, void *priv) +{ + asmstate_t *as = priv; + + if (lw_expr_istype(e, lw_expr_type_int)) + return 0; + if (lw_expr_istype(e, lw_expr_type_oper)) + return 0; + if (lw_expr_istype(e, lw_expr_type_special) && as -> output_format == OUTPUT_OBJ) + { + int t; + t = lw_expr_specint(e); + if (t == lwasm_expr_secbase) + return 0; + } + + return 1; +} + +static int exprok(asmstate_t *as, lw_expr_t e) +{ + if (lw_expr_testterms(e, exprok_aux, as)) + return 0; + return 1; +} + +void do_pass5(asmstate_t *as) +{ + int rc; + int cnt; + int ocnt; + line_t *cl, *sl; + struct line_expr_s *le; + + // first, count the number of non-constant addresses; do + // a reduction first on each one + for (cnt = 0, cl = as -> line_head; cl; cl = cl -> next) + { + as -> cl = cl; + lwasm_reduce_expr(as, cl -> addr); + if (!exprok(as, cl -> addr)) + cnt++; + } + + sl = as -> line_head; + while (cnt > 0) + { + ocnt = cnt; + + // find an unresolved address + for ( ; sl && exprok(as, sl -> addr); sl = sl -> next) + /* do nothing */ ; + + // simplify address + for (cl = sl; cl; cl = cl -> next) + { + as -> cl = sl; + lwasm_reduce_expr(as, sl -> addr); + + if (exprok(as, cl -> addr)) + { + if (0 == --cnt); + return; + } + } + + if (cnt == ocnt) + break; + } + + if (cnt) + { + // we have non-resolved line addresses here + for (cl = sl; cl; cl = cl -> next) + { + if (!exprok(as, cl -> addr)) + { + lwasm_register_error(as, cl, "Cannot resolve line address"); + } + } + } +} diff -r 84dc6d2ec6ba -r 34dfc9747f23 lwasm/pass6.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lwasm/pass6.c Thu Apr 15 21:56:06 2010 -0600 @@ -0,0 +1,57 @@ +/* +pass6.c + +Copyright © 2010 William Astle + +This file is part of LWTOOLS. + +LWTOOLS is free software: you can redistribute it and/or modify it under the +terms of the GNU General Public License as published by the Free Software +Foundation, either version 3 of the License, or (at your option) any later +version. + +This program is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +more details. + +You should have received a copy of the GNU General Public License along with +this program. If not, see . +*/ + +#include + +#include +#include + +#include +#include + +#include "lwasm.h" +#include "instab.h" + +/* +Finalize Pass + +Reduce all expressions in a final pass. + +Observation: + +Everything should reduce as far as it is going to in a single pass +because all line addresses are now constant (or section-base offset) + +*/ +void do_pass6(asmstate_t *as) +{ + line_t *cl; + struct line_expr_s *le; + + for (cl = as -> line_head; cl; cl = cl -> next) + { + as -> cl = cl; + for (le = cl -> exprs; le; le = le -> next) + { + lwasm_reduce_expr(as, le -> expr); + } + } +} diff -r 84dc6d2ec6ba -r 34dfc9747f23 lwasm/section.c --- a/lwasm/section.c Wed Apr 14 21:02:53 2010 -0600 +++ b/lwasm/section.c Thu Apr 15 21:56:06 2010 -0600 @@ -87,7 +87,7 @@ // create section data structure s = lw_alloc(sizeof(sectiontab_t)); s -> name = lw_strdup(sn); - s -> offset = lw_expr_build(lw_expr_type_int, 0); + s -> offset = lw_expr_build(lw_expr_type_special, lwasm_expr_secbase, s); s -> flags = section_flag_none; if (!strcasecmp(sn, "bss") || !strcasecmp(sn, ".bss")) { diff -r 84dc6d2ec6ba -r 34dfc9747f23 lwlib/lw_expr.c --- a/lwlib/lw_expr.c Wed Apr 14 21:02:53 2010 -0600 +++ b/lwlib/lw_expr.c Thu Apr 15 21:56:06 2010 -0600 @@ -49,6 +49,13 @@ return -1; } +int lw_expr_specint(lw_expr_t e) +{ + if (e -> type == lw_expr_type_special) + return e -> value; + return -1; +} + void lw_expr_set_term_parser(lw_expr_fn3_t *fn) { parse_term = fn; @@ -841,3 +848,17 @@ { return lw_expr_parse_expr(p, priv, 0); } + +int lw_expr_testterms(lw_expr_t e, lw_expr_testfn_t *fn, void *priv) +{ + struct lw_expr_opers *o; + int r; + + for (o = e -> operands; o; o = o -> next) + { + r = lw_expr_testterms(o -> p, fn, priv); + if (r) + return r; + } + return (fn)(e, priv); +} diff -r 84dc6d2ec6ba -r 34dfc9747f23 lwlib/lw_expr.h --- a/lwlib/lw_expr.h Wed Apr 14 21:02:53 2010 -0600 +++ b/lwlib/lw_expr.h Thu Apr 15 21:56:06 2010 -0600 @@ -70,6 +70,7 @@ typedef lw_expr_t lw_expr_fn_t(int t, void *ptr, void *priv); typedef lw_expr_t lw_expr_fn2_t(char *var, void *priv); typedef lw_expr_t lw_expr_fn3_t(char **p, void *priv); +typedef int lw_expr_testfn_t(lw_expr_t e, void *priv); #else /* def ___lw_expr_c_seen___ */ @@ -95,6 +96,14 @@ extern lw_expr_t lw_expr_parse(char **p, void *priv); extern int lw_expr_istype(lw_expr_t e, int t); extern int lw_expr_intval(lw_expr_t e); +extern int lw_expr_specint(lw_expr_t e); + +typedef int lw_expr_testfn_t(lw_expr_t e, void *priv); + +// run a function on all terms in an expression; if the function +// returns non-zero for any term, return non-zero, else return +// zero +extern int lw_expr_testterms(lw_expr_t e, lw_expr_testfn_t *fn, void *priv); #endif /* def ___lw_expr_c_seen___ */