# HG changeset patch # User lost # Date 1231383444 0 # Node ID 2fe5fd7d65a38e25454944888bb85a2671d91b72 # Parent 92eb93bffa2810b1cd4ddf623dff428f23607482 Checkpointing object target implementation diff -r 92eb93bffa28 -r 2fe5fd7d65a3 src/expr.c --- 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 diff -r 92eb93bffa28 -r 2fe5fd7d65a3 src/expr.h --- 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)? diff -r 92eb93bffa28 -r 2fe5fd7d65a3 src/lwasm.c --- 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; diff -r 92eb93bffa28 -r 2fe5fd7d65a3 src/lwasm.h --- 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__