# 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___ */