changeset 76:2fe5fd7d65a3

Checkpointing object target implementation
author lost
date Thu, 08 Jan 2009 02:57:24 +0000
parents 92eb93bffa28
children a338d496350e
files src/expr.c src/expr.h src/lwasm.c src/lwasm.h
diffstat 4 files changed, 115 insertions(+), 23 deletions(-) [+]
line wrap: on
line diff
--- a/src/expr.c	Thu Jan 08 01:32:49 2009 +0000
+++ b/src/expr.c	Thu Jan 08 02:57:24 2009 +0000
@@ -654,7 +654,7 @@
 contain the pointer to the next character after the expression if and only
 if there is no error. In the case of an error, *outp is undefined.
 */
-lwasm_expr_stack_t *lwasm_expr_eval(const char *inp, const char **outp, int (*sfunc)(char *sym, void *state, int *val), void *state)
+lwasm_expr_stack_t *lwasm_expr_eval(const char *inp, const char **outp, lwasm_expr_stack_t *(*sfunc)(char *sym, void *state), void *state)
 {
 	lwasm_expr_stack_t *s;
 	const char *p;
@@ -703,26 +703,54 @@
 further operators or only a single term remains
 
 */
-int lwasm_expr_reval(lwasm_expr_stack_t *s, int (*sfunc)(char *sym, void *state, int *val), void *state)
+int lwasm_expr_reval(lwasm_expr_stack_t *s, lwasm_expr_stack_t *(*sfunc)(char *sym, void *state), void *state)
 {
-	lwasm_expr_stack_node_t *n;
-	int sval;
+	lwasm_expr_stack_node_t *n, *n2;
+	lwasm_expr_stack_t *ss;
+	int c;
 	
+next_iter_sym:
 	// resolve symbols
-	// symbols that do not resolve to a constant are left alone
-	for (n = s -> head; n; n = n -> next)
+	// symbols that do not resolve to an expression are left alone
+	for (c = 0, n = s -> head; n; n = n -> next)
 	{
 		if (n -> term -> term_type == LWASM_TERM_SYM)
 		{
-			if (sfunc(n -> term -> symbol, state, &sval) == 0)
+			ss = sfunc(n -> term -> symbol, state);
+			if (ss)
 			{
-				n -> term -> term_type = LWASM_TERM_INT;
-				n -> term -> value = sval;
-				lwasm_free(n -> term -> symbol);
-				n -> term -> symbol = NULL;
+				c++;
+				// splice in the result stack
+				if (n -> prev)
+				{
+					n -> prev -> next = ss -> head;
+				}
+				else
+				{
+					s -> head = ss -> head;
+				}
+				ss -> head -> prev = n -> prev;
+				ss -> tail -> next = n -> next;
+				if (n -> next)
+				{
+					n -> next -> prev = ss -> tail;
+				}
+				else
+				{
+					s -> tail = ss -> tail;
+				}
+				lwasm_expr_term_free(n -> term);
+				lwasm_free(n);
+				n = ss -> tail;
+				
+				ss -> head = NULL;
+				ss -> tail = NULL;
+				lwasm_expr_stack_free(ss);
 			}
 		}
 	}
+	if (c)
+		goto next_iter_sym;
 
 next_iter:	
 	// a single term
--- a/src/expr.h	Thu Jan 08 01:32:49 2009 +0000
+++ b/src/expr.h	Thu Jan 08 02:57:24 2009 +0000
@@ -97,10 +97,10 @@
 You must call lwasm_expr_stack_free() on the result when you are finished
 with it.
 */
-__expr_E__ lwasm_expr_stack_t *lwasm_expr_eval(const char *inp, const char **outp, int (*sfunc)(char *sym, void *state, int *val), void *state);
+__expr_E__ lwasm_expr_stack_t *lwasm_expr_eval(const char *inp, const char **outp, lwasm_expr_stack_t *(*sfunc)(char *sym, void *state), void *state);
 
 // simplify expression
-__expr_E__ int lwasm_expr_reval(lwasm_expr_stack_t *s, int (*sfunc)(char *sym, void *state, int *val), void *state);
+__expr_E__ int lwasm_expr_reval(lwasm_expr_stack_t *s, lwasm_expr_stack_t *(*sfunc)(char *sym, void *state), void *state);
 
 // useful macros
 // is the expression "simple" (one term)?
--- a/src/lwasm.c	Thu Jan 08 01:32:49 2009 +0000
+++ b/src/lwasm.c	Thu Jan 08 02:57:24 2009 +0000
@@ -175,10 +175,15 @@
 	lwasm_line_t *l;
 };	
 
-int lwasm_expr_lookup_symbol(char *sym, void *state, int *val)
+lwasm_expr_stack_t *lwasm_expr_lookup_symbol(char *sym, void *state)
 {
 	lwasm_symbol_ent_t *se;
 	struct symstateinfo *st;
+	lwasm_expr_stack_t *rs;
+	lwasm_expr_term_t *t;
+	lwasm_expr_stack_node_t *n;
+	
+	int val;
 	
 	st = state;
 	debug_message(3, "lwasm_expr_lookup_symbol(): find '%s' (context=%d)", sym, st -> as -> context);	
@@ -191,8 +196,8 @@
 		// current line address
 		case '*':
 		case '.':
-			*val = st -> l -> codeaddr;
-			return 0;
+			val = st -> l -> codeaddr;
+			goto retconst;
 		
 		case '<':
 			// previous branch point
@@ -211,9 +216,34 @@
 		se = lwasm_find_symbol(st -> as, sym, -1);
 	debug_message(3, "lwasm_expr_lookup_symbol(): got '%p'", se);
 	if (!se)
-		return -1;
-	*val = se -> value;
-	return 0;
+		return NULL;
+	if (st -> as -> outformat != OUTPUT_OBJ || se -> sect == NULL || se -> sect == st -> as -> csect)
+	{
+		// global symbol, intrasegment reference, or not an object target
+		val = se -> value;
+		goto retconst;
+	}
+	// an intersegment reference will return as NULL (to be resolved at output/link time)
+	// if se -> expr is NULL, it has to be an intersegment reference here
+	if (se -> expr == NULL)
+	{
+		return NULL;
+	}
+	
+	// duplicate the expression for return
+	rs = lwasm_expr_stack_create();
+	for (n = se -> expr -> head; n; n = n -> next)
+	{
+		lwasm_expr_stack_push(rs, n -> term);
+	}
+	return rs;
+
+retconst:
+	rs = lwasm_expr_stack_create();
+	t = lwasm_expr_term_create_int(val);
+	lwasm_expr_stack_push(rs, t);
+	lwasm_expr_term_free(t);
+	return rs;
 }
 
 lwasm_expr_stack_t *lwasm_evaluate_expr(asmstate_t *as, lwasm_line_t *l, const char *inp, const char **outp)
@@ -228,6 +258,38 @@
 	return(lwasm_expr_eval(inp, outp, lwasm_expr_lookup_symbol, &st));
 }
 
+// return 1 if no undefined symbols (externals and incompletes are okay)
+// return 0 if there are undefined symbols
+int lwasm_expr_result_ckconst(asmstate_t *as, lwasm_expr_stack_t *s)
+{
+	lwasm_expr_stack_node_t *n;
+	lwasm_symbol_ent_t *se;
+	
+	for (n = s -> head; n; n = n -> next)
+	{
+		if (n -> term -> term_type == LWASM_TERM_SYM)
+		{
+			se = lwasm_find_symbol(as, n -> term -> symbol, as -> context);
+			if (!se)
+				se = lwasm_find_symbol(as, n -> term -> symbol, -1);
+			if (!se)
+				return 0;
+		}
+	}
+	return 1;
+}
+
+/*
+Evaluate an expression according to the flag value. Return 0 if a constant result was
+obtained, 1 if an incomplete result was obtained, and -1 if an error was flagged.
+
+Symbol resolution will be modified for the object target as follows:
+- a symbol which is not defined within a section will evaluate as a constant
+- a symbol which is defined within the same section will evaluate as a constant
+- a symbol defined in another section will remain unresolved
+- external references will also remain unresolved
+
+*/
 int lwasm_expr_result(asmstate_t *as, lwasm_line_t *l, char **inp, int flag, int *val)
 {
 	lwasm_expr_stack_t *s;
--- a/src/lwasm.h	Thu Jan 08 01:32:49 2009 +0000
+++ b/src/lwasm.h	Thu Jan 08 02:57:24 2009 +0000
@@ -169,11 +169,13 @@
 __lwasm_E__ int lwasm_next_context(asmstate_t *as);
 
 // also throw an error on expression eval failure
-// return 0 on ok, -1 on error
+// return 0 on ok, -1 on error, 1 if a complex expression was returned
 #define EXPR_NOFLAG			0
-#define EXPR_PASS1CONST		1
-#define EXPR_PASS2CONST		2
-#define EXPR_BYTE			4
+#define EXPR_PASS1CONST		1	// no forward references on pass 1
+#define EXPR_PASS2CONST		2	// no undefined references on pass 2
+#define EXPR_BYTE			4	// the result must fit within 8 bits
+#define EXPR_COMPLEX		8	// a non-constant result is permitted (stored in l -> expr)
+
 __lwasm_E__ int lwasm_expr_result(asmstate_t *as, lwasm_line_t *l, char **inp, int flag, int *val);
 
 #undef __lwasm_E__