changeset 367:34dfc9747f23

Reduction passes complete
author lost@starbug
date Thu, 15 Apr 2010 21:56:06 -0600
parents 84dc6d2ec6ba
children 656630007668
files doc/internals.txt lwasm/Makefile.am lwasm/lwasm.h lwasm/main.c lwasm/pass5.c lwasm/pass6.c lwasm/section.c lwlib/lw_expr.c lwlib/lw_expr.h
diffstat 9 files changed, 232 insertions(+), 3 deletions(-) [+]
line wrap: on
line diff
--- 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.
--- 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
--- 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
--- 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 }
 };
 
--- /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 <http://www.gnu.org/licenses/>.
+*/
+
+#include <config.h>
+
+#include <stdio.h>
+#include <string.h>
+
+#include <lw_alloc.h>
+#include <lw_string.h>
+
+#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");
+			}
+		}
+	}
+}
--- /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 <http://www.gnu.org/licenses/>.
+*/
+
+#include <config.h>
+
+#include <stdio.h>
+#include <string.h>
+
+#include <lw_alloc.h>
+#include <lw_string.h>
+
+#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);
+		}
+	}
+}
--- 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"))
 		{
--- 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);
+}
--- 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___ */