From: Peter Johnson Date: Wed, 26 Sep 2001 00:57:55 +0000 (-0000) Subject: Fix large parts of expression and symbol handling. Actually link in labels X-Git-Tag: v0.1.0~295 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=1abd74ba04ac4b5c39c61fd625bc0cbc7e0fd290;p=yasm Fix large parts of expression and symbol handling. Actually link in labels properly (bug #8). Framework added for portable floating point support (bug #7). Lots of functions still not finished in this commit. svn path=/trunk/yasm/; revision=229 --- diff --git a/libyasm/bytecode.c b/libyasm/bytecode.c index a8b17ed2..01695afe 100644 --- a/libyasm/bytecode.c +++ b/libyasm/bytecode.c @@ -37,9 +37,11 @@ #include "globals.h" #include "errwarn.h" +#include "floatnum.h" #include "expr.h" #include "bytecode.h" +#include "section.h" RCSID("$IdPath$"); @@ -119,7 +121,7 @@ ConvertIntToImm(immval *ptr, unsigned long int_val) ptr = &im_static; /* FIXME: this will leak expr's if static is used */ - ptr->val = expr_new_ident(EXPR_NUM, ExprNum(int_val)); + ptr->val = expr_new_ident(EXPR_INT, ExprInt(int_val)); if ((int_val & 0xFF) == int_val) ptr->len = 1; @@ -432,6 +434,12 @@ bytecode_new_reserve(expr *numitems, unsigned long itemsize) return bc; } +int +bytecode_get_offset(section *sect, bytecode *bc, unsigned long *ret_val) +{ + return 0; /* TODO */ +} + void bytecode_print(bytecode *bc) { @@ -553,15 +561,18 @@ bytecode_print(bytecode *bc) printf("Offset=%lx BITS=%u\n", bc->offset, bc->mode_bits); } -void +bytecode * bytecodes_append(bytecodehead *headp, bytecode *bc) { if (bc) { - if (bc->type != BC_EMPTY) + if (bc->type != BC_EMPTY) { STAILQ_INSERT_TAIL(headp, bc, link); - else + return bc; + } else { free(bc); + } } + return (bytecode *)NULL; } dataval * @@ -579,7 +590,7 @@ dataval_new_expr(expr *exp) } dataval * -dataval_new_float(double float_val) +dataval_new_float(floatnum *flt) { dataval *retval = malloc(sizeof(dataval)); @@ -587,7 +598,7 @@ dataval_new_float(double float_val) Fatal(FATAL_NOMEM); retval->type = DV_FLOAT; - retval->data.float_val = float_val; + retval->data.flt = flt; return retval; } @@ -622,7 +633,9 @@ dataval_print(datavalhead *head) printf("\n"); break; case DV_FLOAT: - printf(" Float=%e\n", cur->data.float_val); + printf(" Float="); + floatnum_print(cur->data.flt); + printf("\n"); break; case DV_STRING: printf(" String=%s\n", cur->data.str_val); diff --git a/libyasm/bytecode.h b/libyasm/bytecode.h index 5ff60a8c..01a0ac19 100644 --- a/libyasm/bytecode.h +++ b/libyasm/bytecode.h @@ -22,6 +22,8 @@ #ifndef YASM_BYTECODE_H #define YASM_BYTECODE_H +struct section_s; + typedef struct effaddr_s { struct expr_s *disp; /* address displacement */ unsigned char len; /* length of disp (in bytes), 0 if none */ @@ -56,7 +58,7 @@ typedef struct dataval_s { union { struct expr_s *exp; - double float_val; + struct floatnum_s *flt; char *str_val; } data; } dataval; @@ -210,6 +212,12 @@ bytecode *bytecode_new_data(datavalhead *datahead, unsigned long size); bytecode *bytecode_new_reserve(struct expr_s *numitems, unsigned long itemsize); +/* Gets the offset of the bytecode specified by bc if possible. + * Return value is IF POSSIBLE, not the value. + */ +int bytecode_get_offset(struct section_s *sect, bytecode *bc, + unsigned long *ret_val); + void bytecode_print(bytecode *bc); /* void bytecodes_initialize(bytecodehead *headp); */ @@ -218,12 +226,13 @@ void bytecode_print(bytecode *bc); /* Adds bc to the list of bytecodes headp. * NOTE: Does not make a copy of bc; so don't pass this function * static or local variables, and discard the bc pointer after calling - * this function. + * this function. If bc was actually appended (it wasn't NULL or empty), + * then returns bc, otherwise returns NULL. */ -void bytecodes_append(bytecodehead *headp, bytecode *bc); +bytecode *bytecodes_append(bytecodehead *headp, bytecode *bc); dataval *dataval_new_expr(struct expr_s *exp); -dataval *dataval_new_float(double float_val); +dataval *dataval_new_float(struct floatnum_s *flt); dataval *dataval_new_string(char *str_val); void dataval_print(datavalhead *head); diff --git a/libyasm/expr.c b/libyasm/expr.c index 20da3572..030b2c58 100644 --- a/libyasm/expr.c +++ b/libyasm/expr.c @@ -1,7 +1,7 @@ /* $IdPath$ * Expression handling * - * Copyright (C) 2001 Michael Urman + * Copyright (C) 2001 Michael Urman, Peter Johnson * * This file is part of YASM. * @@ -34,6 +34,7 @@ #include "globals.h" #include "errwarn.h" +#include "floatnum.h" #include "expr.h" #include "symrec.h" @@ -56,18 +57,20 @@ expr_new(ExprType ltype, ptr->op = op; ptr->rtype = rtype; switch (ltype) { - case EXPR_NUM: case EXPR_SYM: case EXPR_EXPR: + case EXPR_INT: + case EXPR_FLOAT: memcpy(&ptr->left, &left, sizeof(ExprItem)); break; case EXPR_NONE: break; } switch (rtype) { - case EXPR_NUM: case EXPR_SYM: case EXPR_EXPR: + case EXPR_INT: + case EXPR_FLOAT: memcpy(&ptr->right, &right, sizeof(ExprItem)); break; case EXPR_NONE: @@ -91,17 +94,26 @@ ExprItem ExprExpr(expr *x) { ExprItem e; - e.expr = x; + e.exp = x; return e; } ExprItem -ExprNum(unsigned long n) +ExprInt(unsigned long i) { ExprItem e; - e.num = n; + e.int_val = i; + return e; +} + +ExprItem +ExprFloat(floatnum *f) +{ + ExprItem e; + + e.flt = f; return e; } @@ -110,7 +122,7 @@ ExprNone(void) { ExprItem e; - e.num = 0; + e.int_val = 0; return e; } @@ -119,121 +131,121 @@ int expr_simplify(expr *e) { int simplified = 0; + unsigned long int_val; /* try to simplify the left side */ if (e->ltype == EXPR_EXPR) { /* if the left subexpr isn't an IDENT, recurse simplification */ - if (e->left.expr->op != EXPR_IDENT) - simplified |= expr_simplify(e->left.expr); + if (e->left.exp->op != EXPR_IDENT) + simplified |= expr_simplify(e->left.exp); /* if the left subexpr is just an IDENT (or string thereof), * pull it up into the current node */ - while (e->ltype == EXPR_EXPR && e->left.expr->op == EXPR_IDENT) { + while (e->ltype == EXPR_EXPR && e->left.exp->op == EXPR_IDENT) { ExprItem tmp; - e->ltype = e->left.expr->rtype; - memcpy(&tmp, &(e->left.expr->right), sizeof(ExprItem)); - free(e->left.expr); - memcpy(&(e->left.num), &tmp, sizeof(ExprItem)); + e->ltype = e->left.exp->rtype; + memcpy(&tmp, &(e->left.exp->right), sizeof(ExprItem)); + free(e->left.exp); + memcpy(&(e->left.int_val), &tmp, sizeof(ExprItem)); simplified = 1; } } else if (e->ltype == EXPR_SYM) { - /* if it's a symbol that has a defined value, turn it into a - * number */ - if (e->left.sym->status & SYM_VALUED) { - e->ltype = EXPR_NUM; + /* try to get value of symbol */ + if (symrec_get_int_value(e->left.sym, &int_val, 0)) { + e->ltype = EXPR_INT; /* don't try to free the symrec here. */ - e->left.num = e->left.sym->value; + e->left.int_val = int_val; simplified = 1; } } /* ditto on the right */ if (e->rtype == EXPR_EXPR) { - if (e->right.expr->op != EXPR_IDENT) - simplified |= expr_simplify(e->right.expr); + if (e->right.exp->op != EXPR_IDENT) + simplified |= expr_simplify(e->right.exp); - while (e->rtype == EXPR_EXPR && e->right.expr->op == EXPR_IDENT) { + while (e->rtype == EXPR_EXPR && e->right.exp->op == EXPR_IDENT) { ExprItem tmp; - e->rtype = e->right.expr->rtype; - memcpy(&tmp, &(e->right.expr->right), sizeof(ExprItem)); - free(e->right.expr); - memcpy(&(e->right.num), &tmp, sizeof(ExprItem)); + e->rtype = e->right.exp->rtype; + memcpy(&tmp, &(e->right.exp->right), sizeof(ExprItem)); + free(e->right.exp); + memcpy(&(e->right.int_val), &tmp, sizeof(ExprItem)); simplified = 1; } } else if (e->rtype == EXPR_SYM) { - if (e->right.sym->status & SYM_VALUED) { - e->rtype = EXPR_NUM; + if (symrec_get_int_value(e->right.sym, &int_val, 0)) { + e->rtype = EXPR_INT; /* don't try to free the symrec here. */ - e->right.num = e->right.sym->value; + e->right.int_val = int_val; simplified = 1; } } - if ((e->ltype == EXPR_NUM || e->ltype == EXPR_NONE) - && e->rtype == EXPR_NUM && e->op != EXPR_IDENT) { + if ((e->ltype == EXPR_INT || e->ltype == EXPR_NONE) + && e->rtype == EXPR_INT && e->op != EXPR_IDENT) { switch (e->op) { case EXPR_ADD: - e->right.num = e->left.num + e->right.num; + e->right.int_val = e->left.int_val + e->right.int_val; break; case EXPR_SUB: - e->right.num = e->left.num - e->right.num; + e->right.int_val = e->left.int_val - e->right.int_val; break; case EXPR_MUL: - e->right.num = e->left.num * e->right.num; + e->right.int_val = e->left.int_val * e->right.int_val; break; case EXPR_DIV: - e->right.num = e->left.num / e->right.num; + e->right.int_val = e->left.int_val / e->right.int_val; break; case EXPR_MOD: - e->right.num = e->left.num % e->right.num; + e->right.int_val = e->left.int_val % e->right.int_val; break; case EXPR_NEG: - e->right.num = -(e->right.num); + e->right.int_val = -(e->right.int_val); break; case EXPR_NOT: - e->right.num = ~(e->right.num); + e->right.int_val = ~(e->right.int_val); break; case EXPR_OR: - e->right.num = e->left.num | e->right.num; + e->right.int_val = e->left.int_val | e->right.int_val; break; case EXPR_AND: - e->right.num = e->left.num & e->right.num; + e->right.int_val = e->left.int_val & e->right.int_val; break; case EXPR_XOR: - e->right.num = e->left.num ^ e->right.num; + e->right.int_val = e->left.int_val ^ e->right.int_val; break; case EXPR_SHL: - e->right.num = e->right.num << e->left.num; + e->right.int_val = e->right.int_val << e->left.int_val; break; case EXPR_SHR: - e->right.num = e->right.num << e->left.num; + e->right.int_val = e->right.int_val << e->left.int_val; break; case EXPR_LOR: - e->right.num = e->left.num || e->right.num; + e->right.int_val = e->left.int_val || e->right.int_val; break; case EXPR_LAND: - e->right.num = e->left.num && e->right.num; + e->right.int_val = e->left.int_val && e->right.int_val; break; case EXPR_LNOT: - e->right.num = !e->right.num; + e->right.int_val = !e->right.int_val; break; case EXPR_EQ: - e->right.num = e->right.num == e->left.num; + e->right.int_val = e->right.int_val == e->left.int_val; break; case EXPR_LT: - e->right.num = e->right.num < e->left.num; + e->right.int_val = e->right.int_val < e->left.int_val; break; case EXPR_GT: - e->right.num = e->right.num > e->left.num; + e->right.int_val = e->right.int_val > e->left.int_val; break; case EXPR_LE: - e->right.num = e->right.num <= e->left.num; + e->right.int_val = e->right.int_val <= e->left.int_val; break; case EXPR_GE: - e->right.num = e->right.num >= e->left.num; + e->right.int_val = e->right.int_val >= e->left.int_val; break; case EXPR_NE: - e->right.num = e->right.num != e->left.num; + e->right.int_val = e->right.int_val != e->left.int_val; break; case EXPR_IDENT: break; @@ -243,31 +255,31 @@ expr_simplify(expr *e) } /* catch simple identities like 0+x, 1*x, etc., for x not a num */ - else if (e->ltype == EXPR_NUM && ((e->left.num == 1 && e->op == EXPR_MUL) - || (e->left.num == 0 && + else if (e->ltype == EXPR_INT && ((e->left.int_val == 1 && e->op == EXPR_MUL) + || (e->left.int_val == 0 && e->op == EXPR_ADD) - || (e->left.num == -1 && + || (e->left.int_val == -1 && e->op == EXPR_AND) - || (e->left.num == 0 && + || (e->left.int_val == 0 && e->op == EXPR_OR))) { e->op = EXPR_IDENT; simplified = 1; } /* and the corresponding x+|-0, x*&/1 */ - else if (e->rtype == EXPR_NUM && ((e->right.num == 1 && e->op == EXPR_MUL) - || (e->right.num == 1 && + else if (e->rtype == EXPR_INT && ((e->right.int_val == 1 && e->op == EXPR_MUL) + || (e->right.int_val == 1 && e->op == EXPR_DIV) - || (e->right.num == 0 && + || (e->right.int_val == 0 && e->op == EXPR_ADD) - || (e->right.num == 0 && + || (e->right.int_val == 0 && e->op == EXPR_SUB) - || (e->right.num == -1 && + || (e->right.int_val == -1 && e->op == EXPR_AND) - || (e->right.num == 0 && + || (e->right.int_val == 0 && e->op == EXPR_OR) - || (e->right.num == 0 && + || (e->right.int_val == 0 && e->op == EXPR_SHL) - || (e->right.num == 0 && + || (e->right.int_val == 0 && e->op == EXPR_SHR))) { e->op = EXPR_IDENT; e->rtype = e->ltype; @@ -281,11 +293,11 @@ expr_simplify(expr *e) int expr_get_value(expr *e, unsigned long *retval) { - while (!(e->op == EXPR_IDENT && e->rtype == EXPR_NUM) + while (!(e->op == EXPR_IDENT && e->rtype == EXPR_INT) && expr_simplify(e)) ; - if (e->op == EXPR_IDENT && e->rtype == EXPR_NUM) { - *retval = e->right.num; + if (e->op == EXPR_IDENT && e->rtype == EXPR_INT) { + *retval = e->right.int_val; return 1; } else return 0; @@ -296,17 +308,20 @@ expr_print(expr *e) { if (e->op != EXPR_IDENT) { switch (e->ltype) { - case EXPR_NUM: - printf("%lu", e->left.num); - break; case EXPR_SYM: printf("%s", e->left.sym->name); break; case EXPR_EXPR: printf("("); - expr_print(e->left.expr); - + expr_print(e->left.exp); printf(")"); + break; + case EXPR_INT: + printf("%lu", e->left.int_val); + break; + case EXPR_FLOAT: + floatnum_print(e->left.flt); + break; case EXPR_NONE: break; } @@ -379,17 +394,20 @@ expr_print(expr *e) break; } switch (e->rtype) { - case EXPR_NUM: - printf("%lu", e->right.num); - break; case EXPR_SYM: printf("%s", e->right.sym->name); break; case EXPR_EXPR: printf("("); - expr_print(e->right.expr); - + expr_print(e->right.exp); printf(")"); + break; + case EXPR_INT: + printf("%lu", e->right.int_val); + break; + case EXPR_FLOAT: + floatnum_print(e->right.flt); + break; case EXPR_NONE: break; } diff --git a/libyasm/expr.h b/libyasm/expr.h index 8723d898..6846fdb2 100644 --- a/libyasm/expr.h +++ b/libyasm/expr.h @@ -1,7 +1,7 @@ /* $IdPath$ * Expression handling header file * - * Copyright (C) 2001 Michael Urman + * Copyright (C) 2001 Michael Urman, Peter Johnson * * This file is part of YASM. * @@ -49,15 +49,17 @@ typedef enum { typedef enum { EXPR_NONE, /* for left side of a NOT, NEG, etc. */ - EXPR_NUM, + EXPR_SYM, EXPR_EXPR, - EXPR_SYM + EXPR_INT, + EXPR_FLOAT } ExprType; typedef union expritem_u { struct symrec_s *sym; - struct expr_s *expr; - unsigned long num; + struct expr_s *exp; + unsigned long int_val; + struct floatnum_s *flt; } ExprItem; typedef struct expr_s { @@ -70,7 +72,8 @@ expr *expr_new(ExprType, ExprItem, ExprOp, ExprType, ExprItem); ExprItem ExprSym(struct symrec_s *); ExprItem ExprExpr(expr *); -ExprItem ExprNum(unsigned long); +ExprItem ExprInt(unsigned long); +ExprItem ExprFloat(struct floatnum_s *); ExprItem ExprNone(void); #define expr_new_tree(l,o,r) \ diff --git a/libyasm/floatnum.c b/libyasm/floatnum.c new file mode 100644 index 00000000..bef9080e --- /dev/null +++ b/libyasm/floatnum.c @@ -0,0 +1,77 @@ +/* $IdPath$ + * Floating point number functions. + * + * Copyright (C) 2001 Peter Johnson + * + * This file is part of YASM. + * + * YASM 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 2 of the License, or + * (at your option) any later version. + * + * YASM 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "util.h" + +#include + +#ifdef STDC_HEADERS +# include +#endif + +#include "errwarn.h" +#include "floatnum.h" + +RCSID("$IdPath$"); + +floatnum * +floatnum_new(char *str) +{ + floatnum *flt = malloc(sizeof(floatnum)); + if (!flt) + Fatal(FATAL_NOMEM); + /* TODO */ + return flt; +} + +unsigned long +floatnum_get_int(floatnum *flt) +{ + return 0; /* TODO */ +} + +unsigned char * +floatnum_get_single(unsigned char *ptr, floatnum *flt) +{ + return ptr; /* TODO */ +} + +unsigned char * +floatnum_get_double(unsigned char *ptr, floatnum *flt) +{ + return ptr; /* TODO */ +} + +unsigned char * +floatnum_get_extended(unsigned char *ptr, floatnum *flt) +{ + return ptr; /* TODO */ +} + +void +floatnum_print(floatnum *flt) +{ + /* TODO */ +} diff --git a/libyasm/floatnum.h b/libyasm/floatnum.h new file mode 100644 index 00000000..bbea9755 --- /dev/null +++ b/libyasm/floatnum.h @@ -0,0 +1,37 @@ +/* $IdPath$ + * Floating point number functions header file. + * + * Copyright (C) 2001 Peter Johnson + * + * This file is part of YASM. + * + * YASM 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 2 of the License, or + * (at your option) any later version. + * + * YASM 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef YASM_FLOATNUM_H +#define YASM_FLOATNUM_H + +typedef struct floatnum_s { + unsigned char extval[10]; /* float stored in extended precision */ +} floatnum; + +floatnum *floatnum_new(char *str); +unsigned long floatnum_get_int(floatnum *flt); +unsigned char *floatnum_get_single(unsigned char *ptr, floatnum *flt); +unsigned char *floatnum_get_double(unsigned char *ptr, floatnum *flt); +unsigned char *floatnum_get_extended(unsigned char *ptr, floatnum *flt); + +void floatnum_print(floatnum *flt); + +#endif diff --git a/libyasm/symrec.c b/libyasm/symrec.c index 2196638e..2c7947cd 100644 --- a/libyasm/symrec.c +++ b/libyasm/symrec.c @@ -1,7 +1,7 @@ /* $IdPath$ * Symbol table handling * - * Copyright (C) 2001 Michael Urman + * Copyright (C) 2001 Michael Urman, Peter Johnson * * This file is part of YASM. * @@ -35,19 +35,24 @@ #include "globals.h" #include "errwarn.h" +#include "floatnum.h" #include "symrec.h" +#include "bytecode.h" +#include "section.h" + RCSID("$IdPath$"); /* private functions */ -static symrec *symrec_get_or_new(char *, SymType); +static symrec *symrec_get_or_new(const char *); +static symrec *symrec_define(const char *, SymType type); /* The symbol table: a ternary tree. */ static ternary_tree sym_table = (ternary_tree)NULL; /* create a new symrec */ static symrec * -symrec_get_or_new(char *name, SymType type) +symrec_get_or_new(const char *name) { symrec *rec, *rec2; @@ -65,41 +70,128 @@ symrec_get_or_new(char *name, SymType type) rec->name = strdup(name); if (!rec->name) Fatal(FATAL_NOMEM); - rec->type = type; - rec->value = 0; + rec->type = SYM_UNKNOWN; rec->filename = strdup(filename); rec->line = line_number; rec->status = SYM_NOSTATUS; + rec->visibility = SYM_LOCAL; return rec; } /* call a function with each symrec. stop early if 0 returned */ void -symrec_foreach(int (*func) (char *name, symrec *rec)) +symrec_foreach(int (*func) (const char *name, symrec *rec)) { + /* TODO */ } symrec * -symrec_use(char *name, SymType type) +symrec_use(const char *name) { - symrec *rec; + symrec *rec = symrec_get_or_new(name); - rec = symrec_get_or_new(name, type); rec->status |= SYM_USED; return rec; } +static symrec * +symrec_define(const char *name, SymType type) +{ + symrec *rec = symrec_get_or_new(name); + + /* Has it been defined before (either by DEFINED or COMMON/EXTERN)? */ + if (rec->status & SYM_DEFINED) { + Error(_("duplicate definition of `%s'; first defined on line %d"), + name, rec->line); + } else { + rec->line = line_number; /* set line number of definition */ + rec->type = type; + rec->status |= SYM_DEFINED; + } + return rec; +} + +symrec * +symrec_define_constant_int(const char *name, unsigned long int_val) +{ + symrec *rec = symrec_define(name, SYM_CONSTANT_INT); + rec->value.int_val = int_val; + rec->status |= SYM_VALUED; + return rec; +} + symrec * -symrec_define(char *name, SymType type) +symrec_define_constant_float(const char *name, floatnum *flt) { - symrec *rec; + symrec *rec = symrec_define(name, SYM_CONSTANT_FLOAT); + rec->value.flt = flt; + rec->status |= SYM_VALUED; + return rec; +} - rec = symrec_get_or_new(name, type); - if (rec->status & SYM_DECLARED) - Error(_("duplicate definition of `%s'; previously defined on line %d"), +symrec * +symrec_define_label(const char *name, section *sect, bytecode *precbc) +{ + symrec *rec = symrec_define(name, SYM_LABEL); + rec->value.label.sect = sect; + rec->value.label.bc = precbc; + return rec; +} + +symrec * +symrec_declare(const char *name, SymVisibility vis) +{ + symrec *rec = symrec_get_or_new(name); + + /* Don't allow EXTERN and COMMON if symbol has already been DEFINED. */ + /* Also, EXTERN and COMMON are mutually exclusive. */ + if ((rec->status & SYM_DEFINED) || + ((rec->visibility & SYM_COMMON) && (vis == SYM_EXTERN)) || + ((rec->visibility & SYM_EXTERN) && (vis == SYM_COMMON))) { + Error(_("duplicate definition of `%s'; first defined on line %d"), name, rec->line); - rec->line = line_number; /* set line number of definition */ - rec->status |= SYM_DECLARED; + } else { + rec->line = line_number; /* set line number of declaration */ + rec->visibility |= vis; + + /* If declared as COMMON or EXTERN, set as DEFINED. */ + if ((vis == SYM_COMMON) || (vis == SYM_EXTERN)) + rec->status |= SYM_DEFINED; + } return rec; } + +int +symrec_get_int_value(const symrec *sym, unsigned long *ret_val, + int resolve_label) +{ + /* If we already know the value, just return it. */ + if (sym->status & SYM_VALUED) { + switch (sym->type) { + case SYM_CONSTANT_INT: + *ret_val = sym->value.int_val; + break; + case SYM_CONSTANT_FLOAT: + *ret_val = floatnum_get_int(sym->value.flt); + break; + case SYM_LABEL: + if (!bytecode_get_offset(sym->value.label.sect, + sym->value.label.bc, ret_val)) + InternalError(__LINE__, __FILE__, + _("Label symbol is valued but cannot get offset")); + case SYM_UNKNOWN: + InternalError(__LINE__, __FILE__, + _("Have a valued symbol but of unknown type")); + } + return 1; + } + + /* Try to get offset of unvalued label */ + if (resolve_label && sym->type == SYM_LABEL) + return bytecode_get_offset(sym->value.label.sect, sym->value.label.bc, + ret_val); + + /* We can't get the value right now. */ + return 0; +} diff --git a/libyasm/symrec.h b/libyasm/symrec.h index fd2e5c38..21183f4b 100644 --- a/libyasm/symrec.h +++ b/libyasm/symrec.h @@ -1,7 +1,7 @@ /* $IdPath$ * Symbol table handling header file * - * Copyright (C) 2001 Michael Urman + * Copyright (C) 2001 Michael Urman, Peter Johnson * * This file is part of YASM. * @@ -22,15 +22,26 @@ #ifndef YASM_SYMREC_H #define YASM_SYMREC_H +/* DEFINED is set with EXTERN and COMMON below */ typedef enum { SYM_NOSTATUS = 0, - SYM_USED = 1 << 0, /* for using variables before declared */ - SYM_DECLARED = 1 << 1, /* once it's been declared */ + SYM_USED = 1 << 0, /* for using variables before definition */ + SYM_DEFINED = 1 << 1, /* once it's been defined in the file */ SYM_VALUED = 1 << 2 /* once its value has been determined */ } SymStatus; +/* EXTERN and COMMON are mutually exclusive */ typedef enum { - SYM_CONSTANT, /* for EQU defined symbols */ + SYM_LOCAL = 0, /* default, local only */ + SYM_GLOBAL = 1 << 0, /* if it's declared GLOBAL */ + SYM_COMMON = 1 << 1, /* if it's declared COMMON */ + SYM_EXTERN = 1 << 2 /* if it's declared EXTERN */ +} SymVisibility; + +typedef enum { + SYM_UNKNOWN, /* for unknown type (COMMON/EXTERN) */ + SYM_CONSTANT_INT, /* for EQU defined symbols (integers) */ + SYM_CONSTANT_FLOAT, /* (floating point) */ SYM_LABEL /* for labels */ } SymType; @@ -38,13 +49,34 @@ typedef struct symrec_s { char *name; SymType type; SymStatus status; + SymVisibility visibility; char *filename; /* file and line */ - int line; /* symbol was first declared or used on */ - double value; + unsigned long line; /* symbol was first declared or used on */ + union { + unsigned long int_val; /* integer constant */ + struct floatnum_s *flt; /* floating point constant */ + struct label_s { /* bytecode immediately preceding a label */ + struct section_s *sect; + struct bytecode_s *bc; + } label; + } value; } symrec; -symrec *symrec_use(char *name, SymType type); -symrec *symrec_define(char *name, SymType type); -void symrec_foreach(int (*func) (char *name, symrec *rec)); +symrec *symrec_use(const char *name); +symrec *symrec_define_constant_int(const char *name, unsigned long int_val); +symrec *symrec_define_constant_float(const char *name, struct floatnum_s *flt); +symrec *symrec_define_label(const char *name, struct section_s *sect, + struct bytecode_s *precbc); +symrec *symrec_declare(const char *name, SymVisibility vis); + +/* Get the numeric 32-bit value of a symbol if possible. + * Return value is IF POSSIBLE, not the value. + * If resolve_label is true, tries to get offset of labels, otherwise it + * returns not possible. + */ +int symrec_get_int_value(const symrec *sym, unsigned long *ret_val, + int resolve_label); + +void symrec_foreach(int (*func) (const char *name, symrec *rec)); #endif diff --git a/modules/arch/x86/expr.c b/modules/arch/x86/expr.c index 20da3572..030b2c58 100644 --- a/modules/arch/x86/expr.c +++ b/modules/arch/x86/expr.c @@ -1,7 +1,7 @@ /* $IdPath$ * Expression handling * - * Copyright (C) 2001 Michael Urman + * Copyright (C) 2001 Michael Urman, Peter Johnson * * This file is part of YASM. * @@ -34,6 +34,7 @@ #include "globals.h" #include "errwarn.h" +#include "floatnum.h" #include "expr.h" #include "symrec.h" @@ -56,18 +57,20 @@ expr_new(ExprType ltype, ptr->op = op; ptr->rtype = rtype; switch (ltype) { - case EXPR_NUM: case EXPR_SYM: case EXPR_EXPR: + case EXPR_INT: + case EXPR_FLOAT: memcpy(&ptr->left, &left, sizeof(ExprItem)); break; case EXPR_NONE: break; } switch (rtype) { - case EXPR_NUM: case EXPR_SYM: case EXPR_EXPR: + case EXPR_INT: + case EXPR_FLOAT: memcpy(&ptr->right, &right, sizeof(ExprItem)); break; case EXPR_NONE: @@ -91,17 +94,26 @@ ExprItem ExprExpr(expr *x) { ExprItem e; - e.expr = x; + e.exp = x; return e; } ExprItem -ExprNum(unsigned long n) +ExprInt(unsigned long i) { ExprItem e; - e.num = n; + e.int_val = i; + return e; +} + +ExprItem +ExprFloat(floatnum *f) +{ + ExprItem e; + + e.flt = f; return e; } @@ -110,7 +122,7 @@ ExprNone(void) { ExprItem e; - e.num = 0; + e.int_val = 0; return e; } @@ -119,121 +131,121 @@ int expr_simplify(expr *e) { int simplified = 0; + unsigned long int_val; /* try to simplify the left side */ if (e->ltype == EXPR_EXPR) { /* if the left subexpr isn't an IDENT, recurse simplification */ - if (e->left.expr->op != EXPR_IDENT) - simplified |= expr_simplify(e->left.expr); + if (e->left.exp->op != EXPR_IDENT) + simplified |= expr_simplify(e->left.exp); /* if the left subexpr is just an IDENT (or string thereof), * pull it up into the current node */ - while (e->ltype == EXPR_EXPR && e->left.expr->op == EXPR_IDENT) { + while (e->ltype == EXPR_EXPR && e->left.exp->op == EXPR_IDENT) { ExprItem tmp; - e->ltype = e->left.expr->rtype; - memcpy(&tmp, &(e->left.expr->right), sizeof(ExprItem)); - free(e->left.expr); - memcpy(&(e->left.num), &tmp, sizeof(ExprItem)); + e->ltype = e->left.exp->rtype; + memcpy(&tmp, &(e->left.exp->right), sizeof(ExprItem)); + free(e->left.exp); + memcpy(&(e->left.int_val), &tmp, sizeof(ExprItem)); simplified = 1; } } else if (e->ltype == EXPR_SYM) { - /* if it's a symbol that has a defined value, turn it into a - * number */ - if (e->left.sym->status & SYM_VALUED) { - e->ltype = EXPR_NUM; + /* try to get value of symbol */ + if (symrec_get_int_value(e->left.sym, &int_val, 0)) { + e->ltype = EXPR_INT; /* don't try to free the symrec here. */ - e->left.num = e->left.sym->value; + e->left.int_val = int_val; simplified = 1; } } /* ditto on the right */ if (e->rtype == EXPR_EXPR) { - if (e->right.expr->op != EXPR_IDENT) - simplified |= expr_simplify(e->right.expr); + if (e->right.exp->op != EXPR_IDENT) + simplified |= expr_simplify(e->right.exp); - while (e->rtype == EXPR_EXPR && e->right.expr->op == EXPR_IDENT) { + while (e->rtype == EXPR_EXPR && e->right.exp->op == EXPR_IDENT) { ExprItem tmp; - e->rtype = e->right.expr->rtype; - memcpy(&tmp, &(e->right.expr->right), sizeof(ExprItem)); - free(e->right.expr); - memcpy(&(e->right.num), &tmp, sizeof(ExprItem)); + e->rtype = e->right.exp->rtype; + memcpy(&tmp, &(e->right.exp->right), sizeof(ExprItem)); + free(e->right.exp); + memcpy(&(e->right.int_val), &tmp, sizeof(ExprItem)); simplified = 1; } } else if (e->rtype == EXPR_SYM) { - if (e->right.sym->status & SYM_VALUED) { - e->rtype = EXPR_NUM; + if (symrec_get_int_value(e->right.sym, &int_val, 0)) { + e->rtype = EXPR_INT; /* don't try to free the symrec here. */ - e->right.num = e->right.sym->value; + e->right.int_val = int_val; simplified = 1; } } - if ((e->ltype == EXPR_NUM || e->ltype == EXPR_NONE) - && e->rtype == EXPR_NUM && e->op != EXPR_IDENT) { + if ((e->ltype == EXPR_INT || e->ltype == EXPR_NONE) + && e->rtype == EXPR_INT && e->op != EXPR_IDENT) { switch (e->op) { case EXPR_ADD: - e->right.num = e->left.num + e->right.num; + e->right.int_val = e->left.int_val + e->right.int_val; break; case EXPR_SUB: - e->right.num = e->left.num - e->right.num; + e->right.int_val = e->left.int_val - e->right.int_val; break; case EXPR_MUL: - e->right.num = e->left.num * e->right.num; + e->right.int_val = e->left.int_val * e->right.int_val; break; case EXPR_DIV: - e->right.num = e->left.num / e->right.num; + e->right.int_val = e->left.int_val / e->right.int_val; break; case EXPR_MOD: - e->right.num = e->left.num % e->right.num; + e->right.int_val = e->left.int_val % e->right.int_val; break; case EXPR_NEG: - e->right.num = -(e->right.num); + e->right.int_val = -(e->right.int_val); break; case EXPR_NOT: - e->right.num = ~(e->right.num); + e->right.int_val = ~(e->right.int_val); break; case EXPR_OR: - e->right.num = e->left.num | e->right.num; + e->right.int_val = e->left.int_val | e->right.int_val; break; case EXPR_AND: - e->right.num = e->left.num & e->right.num; + e->right.int_val = e->left.int_val & e->right.int_val; break; case EXPR_XOR: - e->right.num = e->left.num ^ e->right.num; + e->right.int_val = e->left.int_val ^ e->right.int_val; break; case EXPR_SHL: - e->right.num = e->right.num << e->left.num; + e->right.int_val = e->right.int_val << e->left.int_val; break; case EXPR_SHR: - e->right.num = e->right.num << e->left.num; + e->right.int_val = e->right.int_val << e->left.int_val; break; case EXPR_LOR: - e->right.num = e->left.num || e->right.num; + e->right.int_val = e->left.int_val || e->right.int_val; break; case EXPR_LAND: - e->right.num = e->left.num && e->right.num; + e->right.int_val = e->left.int_val && e->right.int_val; break; case EXPR_LNOT: - e->right.num = !e->right.num; + e->right.int_val = !e->right.int_val; break; case EXPR_EQ: - e->right.num = e->right.num == e->left.num; + e->right.int_val = e->right.int_val == e->left.int_val; break; case EXPR_LT: - e->right.num = e->right.num < e->left.num; + e->right.int_val = e->right.int_val < e->left.int_val; break; case EXPR_GT: - e->right.num = e->right.num > e->left.num; + e->right.int_val = e->right.int_val > e->left.int_val; break; case EXPR_LE: - e->right.num = e->right.num <= e->left.num; + e->right.int_val = e->right.int_val <= e->left.int_val; break; case EXPR_GE: - e->right.num = e->right.num >= e->left.num; + e->right.int_val = e->right.int_val >= e->left.int_val; break; case EXPR_NE: - e->right.num = e->right.num != e->left.num; + e->right.int_val = e->right.int_val != e->left.int_val; break; case EXPR_IDENT: break; @@ -243,31 +255,31 @@ expr_simplify(expr *e) } /* catch simple identities like 0+x, 1*x, etc., for x not a num */ - else if (e->ltype == EXPR_NUM && ((e->left.num == 1 && e->op == EXPR_MUL) - || (e->left.num == 0 && + else if (e->ltype == EXPR_INT && ((e->left.int_val == 1 && e->op == EXPR_MUL) + || (e->left.int_val == 0 && e->op == EXPR_ADD) - || (e->left.num == -1 && + || (e->left.int_val == -1 && e->op == EXPR_AND) - || (e->left.num == 0 && + || (e->left.int_val == 0 && e->op == EXPR_OR))) { e->op = EXPR_IDENT; simplified = 1; } /* and the corresponding x+|-0, x*&/1 */ - else if (e->rtype == EXPR_NUM && ((e->right.num == 1 && e->op == EXPR_MUL) - || (e->right.num == 1 && + else if (e->rtype == EXPR_INT && ((e->right.int_val == 1 && e->op == EXPR_MUL) + || (e->right.int_val == 1 && e->op == EXPR_DIV) - || (e->right.num == 0 && + || (e->right.int_val == 0 && e->op == EXPR_ADD) - || (e->right.num == 0 && + || (e->right.int_val == 0 && e->op == EXPR_SUB) - || (e->right.num == -1 && + || (e->right.int_val == -1 && e->op == EXPR_AND) - || (e->right.num == 0 && + || (e->right.int_val == 0 && e->op == EXPR_OR) - || (e->right.num == 0 && + || (e->right.int_val == 0 && e->op == EXPR_SHL) - || (e->right.num == 0 && + || (e->right.int_val == 0 && e->op == EXPR_SHR))) { e->op = EXPR_IDENT; e->rtype = e->ltype; @@ -281,11 +293,11 @@ expr_simplify(expr *e) int expr_get_value(expr *e, unsigned long *retval) { - while (!(e->op == EXPR_IDENT && e->rtype == EXPR_NUM) + while (!(e->op == EXPR_IDENT && e->rtype == EXPR_INT) && expr_simplify(e)) ; - if (e->op == EXPR_IDENT && e->rtype == EXPR_NUM) { - *retval = e->right.num; + if (e->op == EXPR_IDENT && e->rtype == EXPR_INT) { + *retval = e->right.int_val; return 1; } else return 0; @@ -296,17 +308,20 @@ expr_print(expr *e) { if (e->op != EXPR_IDENT) { switch (e->ltype) { - case EXPR_NUM: - printf("%lu", e->left.num); - break; case EXPR_SYM: printf("%s", e->left.sym->name); break; case EXPR_EXPR: printf("("); - expr_print(e->left.expr); - + expr_print(e->left.exp); printf(")"); + break; + case EXPR_INT: + printf("%lu", e->left.int_val); + break; + case EXPR_FLOAT: + floatnum_print(e->left.flt); + break; case EXPR_NONE: break; } @@ -379,17 +394,20 @@ expr_print(expr *e) break; } switch (e->rtype) { - case EXPR_NUM: - printf("%lu", e->right.num); - break; case EXPR_SYM: printf("%s", e->right.sym->name); break; case EXPR_EXPR: printf("("); - expr_print(e->right.expr); - + expr_print(e->right.exp); printf(")"); + break; + case EXPR_INT: + printf("%lu", e->right.int_val); + break; + case EXPR_FLOAT: + floatnum_print(e->right.flt); + break; case EXPR_NONE: break; } diff --git a/modules/arch/x86/x86expr.c b/modules/arch/x86/x86expr.c index 20da3572..030b2c58 100644 --- a/modules/arch/x86/x86expr.c +++ b/modules/arch/x86/x86expr.c @@ -1,7 +1,7 @@ /* $IdPath$ * Expression handling * - * Copyright (C) 2001 Michael Urman + * Copyright (C) 2001 Michael Urman, Peter Johnson * * This file is part of YASM. * @@ -34,6 +34,7 @@ #include "globals.h" #include "errwarn.h" +#include "floatnum.h" #include "expr.h" #include "symrec.h" @@ -56,18 +57,20 @@ expr_new(ExprType ltype, ptr->op = op; ptr->rtype = rtype; switch (ltype) { - case EXPR_NUM: case EXPR_SYM: case EXPR_EXPR: + case EXPR_INT: + case EXPR_FLOAT: memcpy(&ptr->left, &left, sizeof(ExprItem)); break; case EXPR_NONE: break; } switch (rtype) { - case EXPR_NUM: case EXPR_SYM: case EXPR_EXPR: + case EXPR_INT: + case EXPR_FLOAT: memcpy(&ptr->right, &right, sizeof(ExprItem)); break; case EXPR_NONE: @@ -91,17 +94,26 @@ ExprItem ExprExpr(expr *x) { ExprItem e; - e.expr = x; + e.exp = x; return e; } ExprItem -ExprNum(unsigned long n) +ExprInt(unsigned long i) { ExprItem e; - e.num = n; + e.int_val = i; + return e; +} + +ExprItem +ExprFloat(floatnum *f) +{ + ExprItem e; + + e.flt = f; return e; } @@ -110,7 +122,7 @@ ExprNone(void) { ExprItem e; - e.num = 0; + e.int_val = 0; return e; } @@ -119,121 +131,121 @@ int expr_simplify(expr *e) { int simplified = 0; + unsigned long int_val; /* try to simplify the left side */ if (e->ltype == EXPR_EXPR) { /* if the left subexpr isn't an IDENT, recurse simplification */ - if (e->left.expr->op != EXPR_IDENT) - simplified |= expr_simplify(e->left.expr); + if (e->left.exp->op != EXPR_IDENT) + simplified |= expr_simplify(e->left.exp); /* if the left subexpr is just an IDENT (or string thereof), * pull it up into the current node */ - while (e->ltype == EXPR_EXPR && e->left.expr->op == EXPR_IDENT) { + while (e->ltype == EXPR_EXPR && e->left.exp->op == EXPR_IDENT) { ExprItem tmp; - e->ltype = e->left.expr->rtype; - memcpy(&tmp, &(e->left.expr->right), sizeof(ExprItem)); - free(e->left.expr); - memcpy(&(e->left.num), &tmp, sizeof(ExprItem)); + e->ltype = e->left.exp->rtype; + memcpy(&tmp, &(e->left.exp->right), sizeof(ExprItem)); + free(e->left.exp); + memcpy(&(e->left.int_val), &tmp, sizeof(ExprItem)); simplified = 1; } } else if (e->ltype == EXPR_SYM) { - /* if it's a symbol that has a defined value, turn it into a - * number */ - if (e->left.sym->status & SYM_VALUED) { - e->ltype = EXPR_NUM; + /* try to get value of symbol */ + if (symrec_get_int_value(e->left.sym, &int_val, 0)) { + e->ltype = EXPR_INT; /* don't try to free the symrec here. */ - e->left.num = e->left.sym->value; + e->left.int_val = int_val; simplified = 1; } } /* ditto on the right */ if (e->rtype == EXPR_EXPR) { - if (e->right.expr->op != EXPR_IDENT) - simplified |= expr_simplify(e->right.expr); + if (e->right.exp->op != EXPR_IDENT) + simplified |= expr_simplify(e->right.exp); - while (e->rtype == EXPR_EXPR && e->right.expr->op == EXPR_IDENT) { + while (e->rtype == EXPR_EXPR && e->right.exp->op == EXPR_IDENT) { ExprItem tmp; - e->rtype = e->right.expr->rtype; - memcpy(&tmp, &(e->right.expr->right), sizeof(ExprItem)); - free(e->right.expr); - memcpy(&(e->right.num), &tmp, sizeof(ExprItem)); + e->rtype = e->right.exp->rtype; + memcpy(&tmp, &(e->right.exp->right), sizeof(ExprItem)); + free(e->right.exp); + memcpy(&(e->right.int_val), &tmp, sizeof(ExprItem)); simplified = 1; } } else if (e->rtype == EXPR_SYM) { - if (e->right.sym->status & SYM_VALUED) { - e->rtype = EXPR_NUM; + if (symrec_get_int_value(e->right.sym, &int_val, 0)) { + e->rtype = EXPR_INT; /* don't try to free the symrec here. */ - e->right.num = e->right.sym->value; + e->right.int_val = int_val; simplified = 1; } } - if ((e->ltype == EXPR_NUM || e->ltype == EXPR_NONE) - && e->rtype == EXPR_NUM && e->op != EXPR_IDENT) { + if ((e->ltype == EXPR_INT || e->ltype == EXPR_NONE) + && e->rtype == EXPR_INT && e->op != EXPR_IDENT) { switch (e->op) { case EXPR_ADD: - e->right.num = e->left.num + e->right.num; + e->right.int_val = e->left.int_val + e->right.int_val; break; case EXPR_SUB: - e->right.num = e->left.num - e->right.num; + e->right.int_val = e->left.int_val - e->right.int_val; break; case EXPR_MUL: - e->right.num = e->left.num * e->right.num; + e->right.int_val = e->left.int_val * e->right.int_val; break; case EXPR_DIV: - e->right.num = e->left.num / e->right.num; + e->right.int_val = e->left.int_val / e->right.int_val; break; case EXPR_MOD: - e->right.num = e->left.num % e->right.num; + e->right.int_val = e->left.int_val % e->right.int_val; break; case EXPR_NEG: - e->right.num = -(e->right.num); + e->right.int_val = -(e->right.int_val); break; case EXPR_NOT: - e->right.num = ~(e->right.num); + e->right.int_val = ~(e->right.int_val); break; case EXPR_OR: - e->right.num = e->left.num | e->right.num; + e->right.int_val = e->left.int_val | e->right.int_val; break; case EXPR_AND: - e->right.num = e->left.num & e->right.num; + e->right.int_val = e->left.int_val & e->right.int_val; break; case EXPR_XOR: - e->right.num = e->left.num ^ e->right.num; + e->right.int_val = e->left.int_val ^ e->right.int_val; break; case EXPR_SHL: - e->right.num = e->right.num << e->left.num; + e->right.int_val = e->right.int_val << e->left.int_val; break; case EXPR_SHR: - e->right.num = e->right.num << e->left.num; + e->right.int_val = e->right.int_val << e->left.int_val; break; case EXPR_LOR: - e->right.num = e->left.num || e->right.num; + e->right.int_val = e->left.int_val || e->right.int_val; break; case EXPR_LAND: - e->right.num = e->left.num && e->right.num; + e->right.int_val = e->left.int_val && e->right.int_val; break; case EXPR_LNOT: - e->right.num = !e->right.num; + e->right.int_val = !e->right.int_val; break; case EXPR_EQ: - e->right.num = e->right.num == e->left.num; + e->right.int_val = e->right.int_val == e->left.int_val; break; case EXPR_LT: - e->right.num = e->right.num < e->left.num; + e->right.int_val = e->right.int_val < e->left.int_val; break; case EXPR_GT: - e->right.num = e->right.num > e->left.num; + e->right.int_val = e->right.int_val > e->left.int_val; break; case EXPR_LE: - e->right.num = e->right.num <= e->left.num; + e->right.int_val = e->right.int_val <= e->left.int_val; break; case EXPR_GE: - e->right.num = e->right.num >= e->left.num; + e->right.int_val = e->right.int_val >= e->left.int_val; break; case EXPR_NE: - e->right.num = e->right.num != e->left.num; + e->right.int_val = e->right.int_val != e->left.int_val; break; case EXPR_IDENT: break; @@ -243,31 +255,31 @@ expr_simplify(expr *e) } /* catch simple identities like 0+x, 1*x, etc., for x not a num */ - else if (e->ltype == EXPR_NUM && ((e->left.num == 1 && e->op == EXPR_MUL) - || (e->left.num == 0 && + else if (e->ltype == EXPR_INT && ((e->left.int_val == 1 && e->op == EXPR_MUL) + || (e->left.int_val == 0 && e->op == EXPR_ADD) - || (e->left.num == -1 && + || (e->left.int_val == -1 && e->op == EXPR_AND) - || (e->left.num == 0 && + || (e->left.int_val == 0 && e->op == EXPR_OR))) { e->op = EXPR_IDENT; simplified = 1; } /* and the corresponding x+|-0, x*&/1 */ - else if (e->rtype == EXPR_NUM && ((e->right.num == 1 && e->op == EXPR_MUL) - || (e->right.num == 1 && + else if (e->rtype == EXPR_INT && ((e->right.int_val == 1 && e->op == EXPR_MUL) + || (e->right.int_val == 1 && e->op == EXPR_DIV) - || (e->right.num == 0 && + || (e->right.int_val == 0 && e->op == EXPR_ADD) - || (e->right.num == 0 && + || (e->right.int_val == 0 && e->op == EXPR_SUB) - || (e->right.num == -1 && + || (e->right.int_val == -1 && e->op == EXPR_AND) - || (e->right.num == 0 && + || (e->right.int_val == 0 && e->op == EXPR_OR) - || (e->right.num == 0 && + || (e->right.int_val == 0 && e->op == EXPR_SHL) - || (e->right.num == 0 && + || (e->right.int_val == 0 && e->op == EXPR_SHR))) { e->op = EXPR_IDENT; e->rtype = e->ltype; @@ -281,11 +293,11 @@ expr_simplify(expr *e) int expr_get_value(expr *e, unsigned long *retval) { - while (!(e->op == EXPR_IDENT && e->rtype == EXPR_NUM) + while (!(e->op == EXPR_IDENT && e->rtype == EXPR_INT) && expr_simplify(e)) ; - if (e->op == EXPR_IDENT && e->rtype == EXPR_NUM) { - *retval = e->right.num; + if (e->op == EXPR_IDENT && e->rtype == EXPR_INT) { + *retval = e->right.int_val; return 1; } else return 0; @@ -296,17 +308,20 @@ expr_print(expr *e) { if (e->op != EXPR_IDENT) { switch (e->ltype) { - case EXPR_NUM: - printf("%lu", e->left.num); - break; case EXPR_SYM: printf("%s", e->left.sym->name); break; case EXPR_EXPR: printf("("); - expr_print(e->left.expr); - + expr_print(e->left.exp); printf(")"); + break; + case EXPR_INT: + printf("%lu", e->left.int_val); + break; + case EXPR_FLOAT: + floatnum_print(e->left.flt); + break; case EXPR_NONE: break; } @@ -379,17 +394,20 @@ expr_print(expr *e) break; } switch (e->rtype) { - case EXPR_NUM: - printf("%lu", e->right.num); - break; case EXPR_SYM: printf("%s", e->right.sym->name); break; case EXPR_EXPR: printf("("); - expr_print(e->right.expr); - + expr_print(e->right.exp); printf(")"); + break; + case EXPR_INT: + printf("%lu", e->right.int_val); + break; + case EXPR_FLOAT: + floatnum_print(e->right.flt); + break; case EXPR_NONE: break; } diff --git a/modules/parsers/nasm/bison.y.in b/modules/parsers/nasm/bison.y.in index cb596260..5aa68e6f 100644 --- a/modules/parsers/nasm/bison.y.in +++ b/modules/parsers/nasm/bison.y.in @@ -37,6 +37,7 @@ #include "globals.h" #include "errwarn.h" +#include "floatnum.h" #include "expr.h" #include "symrec.h" @@ -58,17 +59,15 @@ extern sectionhead nasm_parser_sections; extern section *nasm_parser_cur_section; extern char *nasm_parser_locallabel_base; +static bytecode *nasm_parser_prev_bc = (bytecode *)NULL; +static bytecode *nasm_parser_temp_bc; + %} %union { unsigned long int_val; char *str_val; - double double_val; - symrec *sym; - struct { - char *name; - int line; - } syminfo; + floatnum *flt; unsigned char groupdata[4]; effaddr *ea; expr *exp; @@ -80,7 +79,7 @@ extern char *nasm_parser_locallabel_base; } %token INTNUM -%token FLTNUM +%token FLTNUM %token DIRECTIVE_NAME DIRECTIVE_VAL STRING %token BYTE WORD DWORD QWORD TWORD DQWORD %token DECLARE_DATA @@ -96,7 +95,7 @@ extern char *nasm_parser_locallabel_base; %token REG_AL REG_CL REG_DL REG_BL REG_AH REG_CH REG_DH REG_BH %token REG_ES REG_CS REG_SS REG_DS REG_FS REG_GS %token LEFT_OP RIGHT_OP SIGNDIV SIGNMOD -%token ID LOCAL_ID SPECIAL_ID +%token ID LOCAL_ID SPECIAL_ID /* instruction tokens (dynamically generated) */ /* @TOKENS@ */ @@ -113,8 +112,7 @@ extern char *nasm_parser_locallabel_base; %type rm8 rm16 rm32 rm64 rm128 %type imm imm8x imm16x imm32x imm8 imm16 imm32 %type expr expr_no_string -%type explabel -%type label_id +%type explabel label_id %type target %type dataval %type datavals @@ -130,7 +128,10 @@ extern char *nasm_parser_locallabel_base; %% input: /* empty */ | input line { - bytecodes_append(&nasm_parser_cur_section->bc, $2); + nasm_parser_temp_bc = bytecodes_append(&nasm_parser_cur_section->bc, + $2); + if (nasm_parser_temp_bc) + nasm_parser_prev_bc = nasm_parser_temp_bc; line_number++; } ; @@ -171,25 +172,31 @@ dataval: expr_no_string { $$ = dataval_new_expr($1); } } ; -label: label_id { $1->value = 0; } /* TODO: add pointer to bytecode */ - | label_id ':' { $1->value = 0; } /* TODO: add pointer to bytecode */ +label: label_id { + symrec_define_label($1, nasm_parser_cur_section, nasm_parser_prev_bc); + } + | label_id ':' { + symrec_define_label($1, nasm_parser_cur_section, nasm_parser_prev_bc); + } ; label_id: ID { - $$ = symrec_define($1.name, SYM_LABEL); - nasm_parser_locallabel_base = strdup($1.name); + $$ = $1; + nasm_parser_locallabel_base = strdup($1); } - | SPECIAL_ID { $$ = symrec_define($1.name, SYM_LABEL); } - | LOCAL_ID { $$ = symrec_define($1.name, SYM_LABEL); } + | SPECIAL_ID + | LOCAL_ID ; /* directives */ directive: '[' DIRECTIVE_NAME DIRECTIVE_VAL ']' { - if (strcasecmp($2, "section") == 0) + if (strcasecmp($2, "section") == 0) { nasm_parser_cur_section = sections_switch(&nasm_parser_sections, nasm_parser_objfmt, $3); - else + nasm_parser_prev_bc = (bytecode *)NULL; + } else { printf("Directive: Name='%s' Value='%s'\n", $2, $3); + } } | '[' DIRECTIVE_NAME DIRECTIVE_VAL error { Error(_("missing `%c'"), ']'); @@ -375,9 +382,9 @@ target: expr { $$.val = $1; $$.op_sel = JR_NONE; } ; /* expression trees */ -expr_no_string: INTNUM { $$ = expr_new_ident(EXPR_NUM, ExprNum($1)); } +expr_no_string: INTNUM { $$ = expr_new_ident(EXPR_INT, ExprInt($1)); } | explabel { - $$ = expr_new_ident(EXPR_SYM, ExprSym(symrec_use($1.name, SYM_LABEL))); + $$ = expr_new_ident(EXPR_SYM, ExprSym(symrec_use($1))); } /*| expr '||' expr { $$ = expr_new_tree($1, EXPR_LOR, $3); }*/ | expr '|' expr { $$ = expr_new_tree($1, EXPR_OR, $3); } @@ -406,7 +413,7 @@ expr_no_string: INTNUM { $$ = expr_new_ident(EXPR_NUM, ExprNum($1)); } expr: expr_no_string | STRING { - $$ = expr_new_ident (EXPR_NUM, ExprNum(ConvertCharConstToInt($1))); + $$ = expr_new_ident (EXPR_INT, ExprInt(ConvertCharConstToInt($1))); } ; diff --git a/modules/parsers/nasm/nasm-bison.y b/modules/parsers/nasm/nasm-bison.y index cb596260..5aa68e6f 100644 --- a/modules/parsers/nasm/nasm-bison.y +++ b/modules/parsers/nasm/nasm-bison.y @@ -37,6 +37,7 @@ #include "globals.h" #include "errwarn.h" +#include "floatnum.h" #include "expr.h" #include "symrec.h" @@ -58,17 +59,15 @@ extern sectionhead nasm_parser_sections; extern section *nasm_parser_cur_section; extern char *nasm_parser_locallabel_base; +static bytecode *nasm_parser_prev_bc = (bytecode *)NULL; +static bytecode *nasm_parser_temp_bc; + %} %union { unsigned long int_val; char *str_val; - double double_val; - symrec *sym; - struct { - char *name; - int line; - } syminfo; + floatnum *flt; unsigned char groupdata[4]; effaddr *ea; expr *exp; @@ -80,7 +79,7 @@ extern char *nasm_parser_locallabel_base; } %token INTNUM -%token FLTNUM +%token FLTNUM %token DIRECTIVE_NAME DIRECTIVE_VAL STRING %token BYTE WORD DWORD QWORD TWORD DQWORD %token DECLARE_DATA @@ -96,7 +95,7 @@ extern char *nasm_parser_locallabel_base; %token REG_AL REG_CL REG_DL REG_BL REG_AH REG_CH REG_DH REG_BH %token REG_ES REG_CS REG_SS REG_DS REG_FS REG_GS %token LEFT_OP RIGHT_OP SIGNDIV SIGNMOD -%token ID LOCAL_ID SPECIAL_ID +%token ID LOCAL_ID SPECIAL_ID /* instruction tokens (dynamically generated) */ /* @TOKENS@ */ @@ -113,8 +112,7 @@ extern char *nasm_parser_locallabel_base; %type rm8 rm16 rm32 rm64 rm128 %type imm imm8x imm16x imm32x imm8 imm16 imm32 %type expr expr_no_string -%type explabel -%type label_id +%type explabel label_id %type target %type dataval %type datavals @@ -130,7 +128,10 @@ extern char *nasm_parser_locallabel_base; %% input: /* empty */ | input line { - bytecodes_append(&nasm_parser_cur_section->bc, $2); + nasm_parser_temp_bc = bytecodes_append(&nasm_parser_cur_section->bc, + $2); + if (nasm_parser_temp_bc) + nasm_parser_prev_bc = nasm_parser_temp_bc; line_number++; } ; @@ -171,25 +172,31 @@ dataval: expr_no_string { $$ = dataval_new_expr($1); } } ; -label: label_id { $1->value = 0; } /* TODO: add pointer to bytecode */ - | label_id ':' { $1->value = 0; } /* TODO: add pointer to bytecode */ +label: label_id { + symrec_define_label($1, nasm_parser_cur_section, nasm_parser_prev_bc); + } + | label_id ':' { + symrec_define_label($1, nasm_parser_cur_section, nasm_parser_prev_bc); + } ; label_id: ID { - $$ = symrec_define($1.name, SYM_LABEL); - nasm_parser_locallabel_base = strdup($1.name); + $$ = $1; + nasm_parser_locallabel_base = strdup($1); } - | SPECIAL_ID { $$ = symrec_define($1.name, SYM_LABEL); } - | LOCAL_ID { $$ = symrec_define($1.name, SYM_LABEL); } + | SPECIAL_ID + | LOCAL_ID ; /* directives */ directive: '[' DIRECTIVE_NAME DIRECTIVE_VAL ']' { - if (strcasecmp($2, "section") == 0) + if (strcasecmp($2, "section") == 0) { nasm_parser_cur_section = sections_switch(&nasm_parser_sections, nasm_parser_objfmt, $3); - else + nasm_parser_prev_bc = (bytecode *)NULL; + } else { printf("Directive: Name='%s' Value='%s'\n", $2, $3); + } } | '[' DIRECTIVE_NAME DIRECTIVE_VAL error { Error(_("missing `%c'"), ']'); @@ -375,9 +382,9 @@ target: expr { $$.val = $1; $$.op_sel = JR_NONE; } ; /* expression trees */ -expr_no_string: INTNUM { $$ = expr_new_ident(EXPR_NUM, ExprNum($1)); } +expr_no_string: INTNUM { $$ = expr_new_ident(EXPR_INT, ExprInt($1)); } | explabel { - $$ = expr_new_ident(EXPR_SYM, ExprSym(symrec_use($1.name, SYM_LABEL))); + $$ = expr_new_ident(EXPR_SYM, ExprSym(symrec_use($1))); } /*| expr '||' expr { $$ = expr_new_tree($1, EXPR_LOR, $3); }*/ | expr '|' expr { $$ = expr_new_tree($1, EXPR_OR, $3); } @@ -406,7 +413,7 @@ expr_no_string: INTNUM { $$ = expr_new_ident(EXPR_NUM, ExprNum($1)); } expr: expr_no_string | STRING { - $$ = expr_new_ident (EXPR_NUM, ExprNum(ConvertCharConstToInt($1))); + $$ = expr_new_ident (EXPR_INT, ExprInt(ConvertCharConstToInt($1))); } ; diff --git a/modules/parsers/nasm/token.l.in b/modules/parsers/nasm/token.l.in index 47a6fdb7..4f4b72b2 100644 --- a/modules/parsers/nasm/token.l.in +++ b/modules/parsers/nasm/token.l.in @@ -35,6 +35,7 @@ #define _(String) gettext(String) #include "errwarn.h" +#include "floatnum.h" #include "expr.h" #include "symrec.h" @@ -114,7 +115,7 @@ WS [ \t\r] /* floating point value */ {DIGIT}+\.{DIGIT}*(e[-+]?{DIGIT}+)? { - yylval.double_val = strtod(yytext, (char **)NULL); + yylval.flt = floatnum_new(yytext); return FLTNUM; } @@ -295,10 +296,9 @@ gs { yylval.int_val = 5; return REG_GS; } /* special non-local ..@label and labels like ..start */ $$|$|\.\.[a-z0-9_$#@~.?]+ { - yylval.syminfo.name = strdup(yytext); - if (!yylval.syminfo.name) + yylval.str_val = strdup(yytext); + if (!yylval.str_val) Fatal(FATAL_NOMEM); - yylval.syminfo.line = line_number; return SPECIAL_ID; } @@ -307,18 +307,17 @@ $$|$|\.\.[a-z0-9_$#@~.?]+ { \.[a-z0-9_$#@~?][a-z0-9_$#@~.?]* { if (!nasm_parser_locallabel_base) { Warning(_("no non-local label before `%s'"), yytext); - yylval.syminfo.name = strdup(yytext); - if (!yylval.syminfo.name) + yylval.str_val = strdup(yytext); + if (!yylval.str_val) Fatal(FATAL_NOMEM); } else { - yylval.syminfo.name = malloc(strlen(yytext) + - strlen(nasm_parser_locallabel_base) + 1); - if (!yylval.syminfo.name) + yylval.str_val = malloc(strlen(yytext) + + strlen(nasm_parser_locallabel_base) + 1); + if (!yylval.str_val) Fatal(FATAL_NOMEM); - strcpy(yylval.syminfo.name, nasm_parser_locallabel_base); - strcat(yylval.syminfo.name, yytext); + strcpy(yylval.str_val, nasm_parser_locallabel_base); + strcat(yylval.str_val, yytext); } - yylval.syminfo.line = line_number; return LOCAL_ID; } @@ -328,10 +327,9 @@ $$|$|\.\.[a-z0-9_$#@~.?]+ { /* label */ [a-z_?][a-z0-9_$#@~.?]* { - yylval.syminfo.name = strdup(yytext); - if (!yylval.syminfo.name) + yylval.str_val = strdup(yytext); + if (!yylval.str_val) Fatal(FATAL_NOMEM); - yylval.syminfo.line = line_number; return ID; } diff --git a/src/Makefile.am b/src/Makefile.am index c5d0c919..c41f41ce 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -39,6 +39,8 @@ libyasm_a_SOURCES = \ parser.c \ parser.h \ optimizer.h \ + floatnum.c \ + floatnum.h \ ternary.c \ ternary.h \ strcasecmp.c diff --git a/src/arch/x86/expr.c b/src/arch/x86/expr.c index 20da3572..030b2c58 100644 --- a/src/arch/x86/expr.c +++ b/src/arch/x86/expr.c @@ -1,7 +1,7 @@ /* $IdPath$ * Expression handling * - * Copyright (C) 2001 Michael Urman + * Copyright (C) 2001 Michael Urman, Peter Johnson * * This file is part of YASM. * @@ -34,6 +34,7 @@ #include "globals.h" #include "errwarn.h" +#include "floatnum.h" #include "expr.h" #include "symrec.h" @@ -56,18 +57,20 @@ expr_new(ExprType ltype, ptr->op = op; ptr->rtype = rtype; switch (ltype) { - case EXPR_NUM: case EXPR_SYM: case EXPR_EXPR: + case EXPR_INT: + case EXPR_FLOAT: memcpy(&ptr->left, &left, sizeof(ExprItem)); break; case EXPR_NONE: break; } switch (rtype) { - case EXPR_NUM: case EXPR_SYM: case EXPR_EXPR: + case EXPR_INT: + case EXPR_FLOAT: memcpy(&ptr->right, &right, sizeof(ExprItem)); break; case EXPR_NONE: @@ -91,17 +94,26 @@ ExprItem ExprExpr(expr *x) { ExprItem e; - e.expr = x; + e.exp = x; return e; } ExprItem -ExprNum(unsigned long n) +ExprInt(unsigned long i) { ExprItem e; - e.num = n; + e.int_val = i; + return e; +} + +ExprItem +ExprFloat(floatnum *f) +{ + ExprItem e; + + e.flt = f; return e; } @@ -110,7 +122,7 @@ ExprNone(void) { ExprItem e; - e.num = 0; + e.int_val = 0; return e; } @@ -119,121 +131,121 @@ int expr_simplify(expr *e) { int simplified = 0; + unsigned long int_val; /* try to simplify the left side */ if (e->ltype == EXPR_EXPR) { /* if the left subexpr isn't an IDENT, recurse simplification */ - if (e->left.expr->op != EXPR_IDENT) - simplified |= expr_simplify(e->left.expr); + if (e->left.exp->op != EXPR_IDENT) + simplified |= expr_simplify(e->left.exp); /* if the left subexpr is just an IDENT (or string thereof), * pull it up into the current node */ - while (e->ltype == EXPR_EXPR && e->left.expr->op == EXPR_IDENT) { + while (e->ltype == EXPR_EXPR && e->left.exp->op == EXPR_IDENT) { ExprItem tmp; - e->ltype = e->left.expr->rtype; - memcpy(&tmp, &(e->left.expr->right), sizeof(ExprItem)); - free(e->left.expr); - memcpy(&(e->left.num), &tmp, sizeof(ExprItem)); + e->ltype = e->left.exp->rtype; + memcpy(&tmp, &(e->left.exp->right), sizeof(ExprItem)); + free(e->left.exp); + memcpy(&(e->left.int_val), &tmp, sizeof(ExprItem)); simplified = 1; } } else if (e->ltype == EXPR_SYM) { - /* if it's a symbol that has a defined value, turn it into a - * number */ - if (e->left.sym->status & SYM_VALUED) { - e->ltype = EXPR_NUM; + /* try to get value of symbol */ + if (symrec_get_int_value(e->left.sym, &int_val, 0)) { + e->ltype = EXPR_INT; /* don't try to free the symrec here. */ - e->left.num = e->left.sym->value; + e->left.int_val = int_val; simplified = 1; } } /* ditto on the right */ if (e->rtype == EXPR_EXPR) { - if (e->right.expr->op != EXPR_IDENT) - simplified |= expr_simplify(e->right.expr); + if (e->right.exp->op != EXPR_IDENT) + simplified |= expr_simplify(e->right.exp); - while (e->rtype == EXPR_EXPR && e->right.expr->op == EXPR_IDENT) { + while (e->rtype == EXPR_EXPR && e->right.exp->op == EXPR_IDENT) { ExprItem tmp; - e->rtype = e->right.expr->rtype; - memcpy(&tmp, &(e->right.expr->right), sizeof(ExprItem)); - free(e->right.expr); - memcpy(&(e->right.num), &tmp, sizeof(ExprItem)); + e->rtype = e->right.exp->rtype; + memcpy(&tmp, &(e->right.exp->right), sizeof(ExprItem)); + free(e->right.exp); + memcpy(&(e->right.int_val), &tmp, sizeof(ExprItem)); simplified = 1; } } else if (e->rtype == EXPR_SYM) { - if (e->right.sym->status & SYM_VALUED) { - e->rtype = EXPR_NUM; + if (symrec_get_int_value(e->right.sym, &int_val, 0)) { + e->rtype = EXPR_INT; /* don't try to free the symrec here. */ - e->right.num = e->right.sym->value; + e->right.int_val = int_val; simplified = 1; } } - if ((e->ltype == EXPR_NUM || e->ltype == EXPR_NONE) - && e->rtype == EXPR_NUM && e->op != EXPR_IDENT) { + if ((e->ltype == EXPR_INT || e->ltype == EXPR_NONE) + && e->rtype == EXPR_INT && e->op != EXPR_IDENT) { switch (e->op) { case EXPR_ADD: - e->right.num = e->left.num + e->right.num; + e->right.int_val = e->left.int_val + e->right.int_val; break; case EXPR_SUB: - e->right.num = e->left.num - e->right.num; + e->right.int_val = e->left.int_val - e->right.int_val; break; case EXPR_MUL: - e->right.num = e->left.num * e->right.num; + e->right.int_val = e->left.int_val * e->right.int_val; break; case EXPR_DIV: - e->right.num = e->left.num / e->right.num; + e->right.int_val = e->left.int_val / e->right.int_val; break; case EXPR_MOD: - e->right.num = e->left.num % e->right.num; + e->right.int_val = e->left.int_val % e->right.int_val; break; case EXPR_NEG: - e->right.num = -(e->right.num); + e->right.int_val = -(e->right.int_val); break; case EXPR_NOT: - e->right.num = ~(e->right.num); + e->right.int_val = ~(e->right.int_val); break; case EXPR_OR: - e->right.num = e->left.num | e->right.num; + e->right.int_val = e->left.int_val | e->right.int_val; break; case EXPR_AND: - e->right.num = e->left.num & e->right.num; + e->right.int_val = e->left.int_val & e->right.int_val; break; case EXPR_XOR: - e->right.num = e->left.num ^ e->right.num; + e->right.int_val = e->left.int_val ^ e->right.int_val; break; case EXPR_SHL: - e->right.num = e->right.num << e->left.num; + e->right.int_val = e->right.int_val << e->left.int_val; break; case EXPR_SHR: - e->right.num = e->right.num << e->left.num; + e->right.int_val = e->right.int_val << e->left.int_val; break; case EXPR_LOR: - e->right.num = e->left.num || e->right.num; + e->right.int_val = e->left.int_val || e->right.int_val; break; case EXPR_LAND: - e->right.num = e->left.num && e->right.num; + e->right.int_val = e->left.int_val && e->right.int_val; break; case EXPR_LNOT: - e->right.num = !e->right.num; + e->right.int_val = !e->right.int_val; break; case EXPR_EQ: - e->right.num = e->right.num == e->left.num; + e->right.int_val = e->right.int_val == e->left.int_val; break; case EXPR_LT: - e->right.num = e->right.num < e->left.num; + e->right.int_val = e->right.int_val < e->left.int_val; break; case EXPR_GT: - e->right.num = e->right.num > e->left.num; + e->right.int_val = e->right.int_val > e->left.int_val; break; case EXPR_LE: - e->right.num = e->right.num <= e->left.num; + e->right.int_val = e->right.int_val <= e->left.int_val; break; case EXPR_GE: - e->right.num = e->right.num >= e->left.num; + e->right.int_val = e->right.int_val >= e->left.int_val; break; case EXPR_NE: - e->right.num = e->right.num != e->left.num; + e->right.int_val = e->right.int_val != e->left.int_val; break; case EXPR_IDENT: break; @@ -243,31 +255,31 @@ expr_simplify(expr *e) } /* catch simple identities like 0+x, 1*x, etc., for x not a num */ - else if (e->ltype == EXPR_NUM && ((e->left.num == 1 && e->op == EXPR_MUL) - || (e->left.num == 0 && + else if (e->ltype == EXPR_INT && ((e->left.int_val == 1 && e->op == EXPR_MUL) + || (e->left.int_val == 0 && e->op == EXPR_ADD) - || (e->left.num == -1 && + || (e->left.int_val == -1 && e->op == EXPR_AND) - || (e->left.num == 0 && + || (e->left.int_val == 0 && e->op == EXPR_OR))) { e->op = EXPR_IDENT; simplified = 1; } /* and the corresponding x+|-0, x*&/1 */ - else if (e->rtype == EXPR_NUM && ((e->right.num == 1 && e->op == EXPR_MUL) - || (e->right.num == 1 && + else if (e->rtype == EXPR_INT && ((e->right.int_val == 1 && e->op == EXPR_MUL) + || (e->right.int_val == 1 && e->op == EXPR_DIV) - || (e->right.num == 0 && + || (e->right.int_val == 0 && e->op == EXPR_ADD) - || (e->right.num == 0 && + || (e->right.int_val == 0 && e->op == EXPR_SUB) - || (e->right.num == -1 && + || (e->right.int_val == -1 && e->op == EXPR_AND) - || (e->right.num == 0 && + || (e->right.int_val == 0 && e->op == EXPR_OR) - || (e->right.num == 0 && + || (e->right.int_val == 0 && e->op == EXPR_SHL) - || (e->right.num == 0 && + || (e->right.int_val == 0 && e->op == EXPR_SHR))) { e->op = EXPR_IDENT; e->rtype = e->ltype; @@ -281,11 +293,11 @@ expr_simplify(expr *e) int expr_get_value(expr *e, unsigned long *retval) { - while (!(e->op == EXPR_IDENT && e->rtype == EXPR_NUM) + while (!(e->op == EXPR_IDENT && e->rtype == EXPR_INT) && expr_simplify(e)) ; - if (e->op == EXPR_IDENT && e->rtype == EXPR_NUM) { - *retval = e->right.num; + if (e->op == EXPR_IDENT && e->rtype == EXPR_INT) { + *retval = e->right.int_val; return 1; } else return 0; @@ -296,17 +308,20 @@ expr_print(expr *e) { if (e->op != EXPR_IDENT) { switch (e->ltype) { - case EXPR_NUM: - printf("%lu", e->left.num); - break; case EXPR_SYM: printf("%s", e->left.sym->name); break; case EXPR_EXPR: printf("("); - expr_print(e->left.expr); - + expr_print(e->left.exp); printf(")"); + break; + case EXPR_INT: + printf("%lu", e->left.int_val); + break; + case EXPR_FLOAT: + floatnum_print(e->left.flt); + break; case EXPR_NONE: break; } @@ -379,17 +394,20 @@ expr_print(expr *e) break; } switch (e->rtype) { - case EXPR_NUM: - printf("%lu", e->right.num); - break; case EXPR_SYM: printf("%s", e->right.sym->name); break; case EXPR_EXPR: printf("("); - expr_print(e->right.expr); - + expr_print(e->right.exp); printf(")"); + break; + case EXPR_INT: + printf("%lu", e->right.int_val); + break; + case EXPR_FLOAT: + floatnum_print(e->right.flt); + break; case EXPR_NONE: break; } diff --git a/src/arch/x86/x86expr.c b/src/arch/x86/x86expr.c index 20da3572..030b2c58 100644 --- a/src/arch/x86/x86expr.c +++ b/src/arch/x86/x86expr.c @@ -1,7 +1,7 @@ /* $IdPath$ * Expression handling * - * Copyright (C) 2001 Michael Urman + * Copyright (C) 2001 Michael Urman, Peter Johnson * * This file is part of YASM. * @@ -34,6 +34,7 @@ #include "globals.h" #include "errwarn.h" +#include "floatnum.h" #include "expr.h" #include "symrec.h" @@ -56,18 +57,20 @@ expr_new(ExprType ltype, ptr->op = op; ptr->rtype = rtype; switch (ltype) { - case EXPR_NUM: case EXPR_SYM: case EXPR_EXPR: + case EXPR_INT: + case EXPR_FLOAT: memcpy(&ptr->left, &left, sizeof(ExprItem)); break; case EXPR_NONE: break; } switch (rtype) { - case EXPR_NUM: case EXPR_SYM: case EXPR_EXPR: + case EXPR_INT: + case EXPR_FLOAT: memcpy(&ptr->right, &right, sizeof(ExprItem)); break; case EXPR_NONE: @@ -91,17 +94,26 @@ ExprItem ExprExpr(expr *x) { ExprItem e; - e.expr = x; + e.exp = x; return e; } ExprItem -ExprNum(unsigned long n) +ExprInt(unsigned long i) { ExprItem e; - e.num = n; + e.int_val = i; + return e; +} + +ExprItem +ExprFloat(floatnum *f) +{ + ExprItem e; + + e.flt = f; return e; } @@ -110,7 +122,7 @@ ExprNone(void) { ExprItem e; - e.num = 0; + e.int_val = 0; return e; } @@ -119,121 +131,121 @@ int expr_simplify(expr *e) { int simplified = 0; + unsigned long int_val; /* try to simplify the left side */ if (e->ltype == EXPR_EXPR) { /* if the left subexpr isn't an IDENT, recurse simplification */ - if (e->left.expr->op != EXPR_IDENT) - simplified |= expr_simplify(e->left.expr); + if (e->left.exp->op != EXPR_IDENT) + simplified |= expr_simplify(e->left.exp); /* if the left subexpr is just an IDENT (or string thereof), * pull it up into the current node */ - while (e->ltype == EXPR_EXPR && e->left.expr->op == EXPR_IDENT) { + while (e->ltype == EXPR_EXPR && e->left.exp->op == EXPR_IDENT) { ExprItem tmp; - e->ltype = e->left.expr->rtype; - memcpy(&tmp, &(e->left.expr->right), sizeof(ExprItem)); - free(e->left.expr); - memcpy(&(e->left.num), &tmp, sizeof(ExprItem)); + e->ltype = e->left.exp->rtype; + memcpy(&tmp, &(e->left.exp->right), sizeof(ExprItem)); + free(e->left.exp); + memcpy(&(e->left.int_val), &tmp, sizeof(ExprItem)); simplified = 1; } } else if (e->ltype == EXPR_SYM) { - /* if it's a symbol that has a defined value, turn it into a - * number */ - if (e->left.sym->status & SYM_VALUED) { - e->ltype = EXPR_NUM; + /* try to get value of symbol */ + if (symrec_get_int_value(e->left.sym, &int_val, 0)) { + e->ltype = EXPR_INT; /* don't try to free the symrec here. */ - e->left.num = e->left.sym->value; + e->left.int_val = int_val; simplified = 1; } } /* ditto on the right */ if (e->rtype == EXPR_EXPR) { - if (e->right.expr->op != EXPR_IDENT) - simplified |= expr_simplify(e->right.expr); + if (e->right.exp->op != EXPR_IDENT) + simplified |= expr_simplify(e->right.exp); - while (e->rtype == EXPR_EXPR && e->right.expr->op == EXPR_IDENT) { + while (e->rtype == EXPR_EXPR && e->right.exp->op == EXPR_IDENT) { ExprItem tmp; - e->rtype = e->right.expr->rtype; - memcpy(&tmp, &(e->right.expr->right), sizeof(ExprItem)); - free(e->right.expr); - memcpy(&(e->right.num), &tmp, sizeof(ExprItem)); + e->rtype = e->right.exp->rtype; + memcpy(&tmp, &(e->right.exp->right), sizeof(ExprItem)); + free(e->right.exp); + memcpy(&(e->right.int_val), &tmp, sizeof(ExprItem)); simplified = 1; } } else if (e->rtype == EXPR_SYM) { - if (e->right.sym->status & SYM_VALUED) { - e->rtype = EXPR_NUM; + if (symrec_get_int_value(e->right.sym, &int_val, 0)) { + e->rtype = EXPR_INT; /* don't try to free the symrec here. */ - e->right.num = e->right.sym->value; + e->right.int_val = int_val; simplified = 1; } } - if ((e->ltype == EXPR_NUM || e->ltype == EXPR_NONE) - && e->rtype == EXPR_NUM && e->op != EXPR_IDENT) { + if ((e->ltype == EXPR_INT || e->ltype == EXPR_NONE) + && e->rtype == EXPR_INT && e->op != EXPR_IDENT) { switch (e->op) { case EXPR_ADD: - e->right.num = e->left.num + e->right.num; + e->right.int_val = e->left.int_val + e->right.int_val; break; case EXPR_SUB: - e->right.num = e->left.num - e->right.num; + e->right.int_val = e->left.int_val - e->right.int_val; break; case EXPR_MUL: - e->right.num = e->left.num * e->right.num; + e->right.int_val = e->left.int_val * e->right.int_val; break; case EXPR_DIV: - e->right.num = e->left.num / e->right.num; + e->right.int_val = e->left.int_val / e->right.int_val; break; case EXPR_MOD: - e->right.num = e->left.num % e->right.num; + e->right.int_val = e->left.int_val % e->right.int_val; break; case EXPR_NEG: - e->right.num = -(e->right.num); + e->right.int_val = -(e->right.int_val); break; case EXPR_NOT: - e->right.num = ~(e->right.num); + e->right.int_val = ~(e->right.int_val); break; case EXPR_OR: - e->right.num = e->left.num | e->right.num; + e->right.int_val = e->left.int_val | e->right.int_val; break; case EXPR_AND: - e->right.num = e->left.num & e->right.num; + e->right.int_val = e->left.int_val & e->right.int_val; break; case EXPR_XOR: - e->right.num = e->left.num ^ e->right.num; + e->right.int_val = e->left.int_val ^ e->right.int_val; break; case EXPR_SHL: - e->right.num = e->right.num << e->left.num; + e->right.int_val = e->right.int_val << e->left.int_val; break; case EXPR_SHR: - e->right.num = e->right.num << e->left.num; + e->right.int_val = e->right.int_val << e->left.int_val; break; case EXPR_LOR: - e->right.num = e->left.num || e->right.num; + e->right.int_val = e->left.int_val || e->right.int_val; break; case EXPR_LAND: - e->right.num = e->left.num && e->right.num; + e->right.int_val = e->left.int_val && e->right.int_val; break; case EXPR_LNOT: - e->right.num = !e->right.num; + e->right.int_val = !e->right.int_val; break; case EXPR_EQ: - e->right.num = e->right.num == e->left.num; + e->right.int_val = e->right.int_val == e->left.int_val; break; case EXPR_LT: - e->right.num = e->right.num < e->left.num; + e->right.int_val = e->right.int_val < e->left.int_val; break; case EXPR_GT: - e->right.num = e->right.num > e->left.num; + e->right.int_val = e->right.int_val > e->left.int_val; break; case EXPR_LE: - e->right.num = e->right.num <= e->left.num; + e->right.int_val = e->right.int_val <= e->left.int_val; break; case EXPR_GE: - e->right.num = e->right.num >= e->left.num; + e->right.int_val = e->right.int_val >= e->left.int_val; break; case EXPR_NE: - e->right.num = e->right.num != e->left.num; + e->right.int_val = e->right.int_val != e->left.int_val; break; case EXPR_IDENT: break; @@ -243,31 +255,31 @@ expr_simplify(expr *e) } /* catch simple identities like 0+x, 1*x, etc., for x not a num */ - else if (e->ltype == EXPR_NUM && ((e->left.num == 1 && e->op == EXPR_MUL) - || (e->left.num == 0 && + else if (e->ltype == EXPR_INT && ((e->left.int_val == 1 && e->op == EXPR_MUL) + || (e->left.int_val == 0 && e->op == EXPR_ADD) - || (e->left.num == -1 && + || (e->left.int_val == -1 && e->op == EXPR_AND) - || (e->left.num == 0 && + || (e->left.int_val == 0 && e->op == EXPR_OR))) { e->op = EXPR_IDENT; simplified = 1; } /* and the corresponding x+|-0, x*&/1 */ - else if (e->rtype == EXPR_NUM && ((e->right.num == 1 && e->op == EXPR_MUL) - || (e->right.num == 1 && + else if (e->rtype == EXPR_INT && ((e->right.int_val == 1 && e->op == EXPR_MUL) + || (e->right.int_val == 1 && e->op == EXPR_DIV) - || (e->right.num == 0 && + || (e->right.int_val == 0 && e->op == EXPR_ADD) - || (e->right.num == 0 && + || (e->right.int_val == 0 && e->op == EXPR_SUB) - || (e->right.num == -1 && + || (e->right.int_val == -1 && e->op == EXPR_AND) - || (e->right.num == 0 && + || (e->right.int_val == 0 && e->op == EXPR_OR) - || (e->right.num == 0 && + || (e->right.int_val == 0 && e->op == EXPR_SHL) - || (e->right.num == 0 && + || (e->right.int_val == 0 && e->op == EXPR_SHR))) { e->op = EXPR_IDENT; e->rtype = e->ltype; @@ -281,11 +293,11 @@ expr_simplify(expr *e) int expr_get_value(expr *e, unsigned long *retval) { - while (!(e->op == EXPR_IDENT && e->rtype == EXPR_NUM) + while (!(e->op == EXPR_IDENT && e->rtype == EXPR_INT) && expr_simplify(e)) ; - if (e->op == EXPR_IDENT && e->rtype == EXPR_NUM) { - *retval = e->right.num; + if (e->op == EXPR_IDENT && e->rtype == EXPR_INT) { + *retval = e->right.int_val; return 1; } else return 0; @@ -296,17 +308,20 @@ expr_print(expr *e) { if (e->op != EXPR_IDENT) { switch (e->ltype) { - case EXPR_NUM: - printf("%lu", e->left.num); - break; case EXPR_SYM: printf("%s", e->left.sym->name); break; case EXPR_EXPR: printf("("); - expr_print(e->left.expr); - + expr_print(e->left.exp); printf(")"); + break; + case EXPR_INT: + printf("%lu", e->left.int_val); + break; + case EXPR_FLOAT: + floatnum_print(e->left.flt); + break; case EXPR_NONE: break; } @@ -379,17 +394,20 @@ expr_print(expr *e) break; } switch (e->rtype) { - case EXPR_NUM: - printf("%lu", e->right.num); - break; case EXPR_SYM: printf("%s", e->right.sym->name); break; case EXPR_EXPR: printf("("); - expr_print(e->right.expr); - + expr_print(e->right.exp); printf(")"); + break; + case EXPR_INT: + printf("%lu", e->right.int_val); + break; + case EXPR_FLOAT: + floatnum_print(e->right.flt); + break; case EXPR_NONE: break; } diff --git a/src/bytecode.c b/src/bytecode.c index a8b17ed2..01695afe 100644 --- a/src/bytecode.c +++ b/src/bytecode.c @@ -37,9 +37,11 @@ #include "globals.h" #include "errwarn.h" +#include "floatnum.h" #include "expr.h" #include "bytecode.h" +#include "section.h" RCSID("$IdPath$"); @@ -119,7 +121,7 @@ ConvertIntToImm(immval *ptr, unsigned long int_val) ptr = &im_static; /* FIXME: this will leak expr's if static is used */ - ptr->val = expr_new_ident(EXPR_NUM, ExprNum(int_val)); + ptr->val = expr_new_ident(EXPR_INT, ExprInt(int_val)); if ((int_val & 0xFF) == int_val) ptr->len = 1; @@ -432,6 +434,12 @@ bytecode_new_reserve(expr *numitems, unsigned long itemsize) return bc; } +int +bytecode_get_offset(section *sect, bytecode *bc, unsigned long *ret_val) +{ + return 0; /* TODO */ +} + void bytecode_print(bytecode *bc) { @@ -553,15 +561,18 @@ bytecode_print(bytecode *bc) printf("Offset=%lx BITS=%u\n", bc->offset, bc->mode_bits); } -void +bytecode * bytecodes_append(bytecodehead *headp, bytecode *bc) { if (bc) { - if (bc->type != BC_EMPTY) + if (bc->type != BC_EMPTY) { STAILQ_INSERT_TAIL(headp, bc, link); - else + return bc; + } else { free(bc); + } } + return (bytecode *)NULL; } dataval * @@ -579,7 +590,7 @@ dataval_new_expr(expr *exp) } dataval * -dataval_new_float(double float_val) +dataval_new_float(floatnum *flt) { dataval *retval = malloc(sizeof(dataval)); @@ -587,7 +598,7 @@ dataval_new_float(double float_val) Fatal(FATAL_NOMEM); retval->type = DV_FLOAT; - retval->data.float_val = float_val; + retval->data.flt = flt; return retval; } @@ -622,7 +633,9 @@ dataval_print(datavalhead *head) printf("\n"); break; case DV_FLOAT: - printf(" Float=%e\n", cur->data.float_val); + printf(" Float="); + floatnum_print(cur->data.flt); + printf("\n"); break; case DV_STRING: printf(" String=%s\n", cur->data.str_val); diff --git a/src/bytecode.h b/src/bytecode.h index 5ff60a8c..01a0ac19 100644 --- a/src/bytecode.h +++ b/src/bytecode.h @@ -22,6 +22,8 @@ #ifndef YASM_BYTECODE_H #define YASM_BYTECODE_H +struct section_s; + typedef struct effaddr_s { struct expr_s *disp; /* address displacement */ unsigned char len; /* length of disp (in bytes), 0 if none */ @@ -56,7 +58,7 @@ typedef struct dataval_s { union { struct expr_s *exp; - double float_val; + struct floatnum_s *flt; char *str_val; } data; } dataval; @@ -210,6 +212,12 @@ bytecode *bytecode_new_data(datavalhead *datahead, unsigned long size); bytecode *bytecode_new_reserve(struct expr_s *numitems, unsigned long itemsize); +/* Gets the offset of the bytecode specified by bc if possible. + * Return value is IF POSSIBLE, not the value. + */ +int bytecode_get_offset(struct section_s *sect, bytecode *bc, + unsigned long *ret_val); + void bytecode_print(bytecode *bc); /* void bytecodes_initialize(bytecodehead *headp); */ @@ -218,12 +226,13 @@ void bytecode_print(bytecode *bc); /* Adds bc to the list of bytecodes headp. * NOTE: Does not make a copy of bc; so don't pass this function * static or local variables, and discard the bc pointer after calling - * this function. + * this function. If bc was actually appended (it wasn't NULL or empty), + * then returns bc, otherwise returns NULL. */ -void bytecodes_append(bytecodehead *headp, bytecode *bc); +bytecode *bytecodes_append(bytecodehead *headp, bytecode *bc); dataval *dataval_new_expr(struct expr_s *exp); -dataval *dataval_new_float(double float_val); +dataval *dataval_new_float(struct floatnum_s *flt); dataval *dataval_new_string(char *str_val); void dataval_print(datavalhead *head); diff --git a/src/expr.c b/src/expr.c index 20da3572..030b2c58 100644 --- a/src/expr.c +++ b/src/expr.c @@ -1,7 +1,7 @@ /* $IdPath$ * Expression handling * - * Copyright (C) 2001 Michael Urman + * Copyright (C) 2001 Michael Urman, Peter Johnson * * This file is part of YASM. * @@ -34,6 +34,7 @@ #include "globals.h" #include "errwarn.h" +#include "floatnum.h" #include "expr.h" #include "symrec.h" @@ -56,18 +57,20 @@ expr_new(ExprType ltype, ptr->op = op; ptr->rtype = rtype; switch (ltype) { - case EXPR_NUM: case EXPR_SYM: case EXPR_EXPR: + case EXPR_INT: + case EXPR_FLOAT: memcpy(&ptr->left, &left, sizeof(ExprItem)); break; case EXPR_NONE: break; } switch (rtype) { - case EXPR_NUM: case EXPR_SYM: case EXPR_EXPR: + case EXPR_INT: + case EXPR_FLOAT: memcpy(&ptr->right, &right, sizeof(ExprItem)); break; case EXPR_NONE: @@ -91,17 +94,26 @@ ExprItem ExprExpr(expr *x) { ExprItem e; - e.expr = x; + e.exp = x; return e; } ExprItem -ExprNum(unsigned long n) +ExprInt(unsigned long i) { ExprItem e; - e.num = n; + e.int_val = i; + return e; +} + +ExprItem +ExprFloat(floatnum *f) +{ + ExprItem e; + + e.flt = f; return e; } @@ -110,7 +122,7 @@ ExprNone(void) { ExprItem e; - e.num = 0; + e.int_val = 0; return e; } @@ -119,121 +131,121 @@ int expr_simplify(expr *e) { int simplified = 0; + unsigned long int_val; /* try to simplify the left side */ if (e->ltype == EXPR_EXPR) { /* if the left subexpr isn't an IDENT, recurse simplification */ - if (e->left.expr->op != EXPR_IDENT) - simplified |= expr_simplify(e->left.expr); + if (e->left.exp->op != EXPR_IDENT) + simplified |= expr_simplify(e->left.exp); /* if the left subexpr is just an IDENT (or string thereof), * pull it up into the current node */ - while (e->ltype == EXPR_EXPR && e->left.expr->op == EXPR_IDENT) { + while (e->ltype == EXPR_EXPR && e->left.exp->op == EXPR_IDENT) { ExprItem tmp; - e->ltype = e->left.expr->rtype; - memcpy(&tmp, &(e->left.expr->right), sizeof(ExprItem)); - free(e->left.expr); - memcpy(&(e->left.num), &tmp, sizeof(ExprItem)); + e->ltype = e->left.exp->rtype; + memcpy(&tmp, &(e->left.exp->right), sizeof(ExprItem)); + free(e->left.exp); + memcpy(&(e->left.int_val), &tmp, sizeof(ExprItem)); simplified = 1; } } else if (e->ltype == EXPR_SYM) { - /* if it's a symbol that has a defined value, turn it into a - * number */ - if (e->left.sym->status & SYM_VALUED) { - e->ltype = EXPR_NUM; + /* try to get value of symbol */ + if (symrec_get_int_value(e->left.sym, &int_val, 0)) { + e->ltype = EXPR_INT; /* don't try to free the symrec here. */ - e->left.num = e->left.sym->value; + e->left.int_val = int_val; simplified = 1; } } /* ditto on the right */ if (e->rtype == EXPR_EXPR) { - if (e->right.expr->op != EXPR_IDENT) - simplified |= expr_simplify(e->right.expr); + if (e->right.exp->op != EXPR_IDENT) + simplified |= expr_simplify(e->right.exp); - while (e->rtype == EXPR_EXPR && e->right.expr->op == EXPR_IDENT) { + while (e->rtype == EXPR_EXPR && e->right.exp->op == EXPR_IDENT) { ExprItem tmp; - e->rtype = e->right.expr->rtype; - memcpy(&tmp, &(e->right.expr->right), sizeof(ExprItem)); - free(e->right.expr); - memcpy(&(e->right.num), &tmp, sizeof(ExprItem)); + e->rtype = e->right.exp->rtype; + memcpy(&tmp, &(e->right.exp->right), sizeof(ExprItem)); + free(e->right.exp); + memcpy(&(e->right.int_val), &tmp, sizeof(ExprItem)); simplified = 1; } } else if (e->rtype == EXPR_SYM) { - if (e->right.sym->status & SYM_VALUED) { - e->rtype = EXPR_NUM; + if (symrec_get_int_value(e->right.sym, &int_val, 0)) { + e->rtype = EXPR_INT; /* don't try to free the symrec here. */ - e->right.num = e->right.sym->value; + e->right.int_val = int_val; simplified = 1; } } - if ((e->ltype == EXPR_NUM || e->ltype == EXPR_NONE) - && e->rtype == EXPR_NUM && e->op != EXPR_IDENT) { + if ((e->ltype == EXPR_INT || e->ltype == EXPR_NONE) + && e->rtype == EXPR_INT && e->op != EXPR_IDENT) { switch (e->op) { case EXPR_ADD: - e->right.num = e->left.num + e->right.num; + e->right.int_val = e->left.int_val + e->right.int_val; break; case EXPR_SUB: - e->right.num = e->left.num - e->right.num; + e->right.int_val = e->left.int_val - e->right.int_val; break; case EXPR_MUL: - e->right.num = e->left.num * e->right.num; + e->right.int_val = e->left.int_val * e->right.int_val; break; case EXPR_DIV: - e->right.num = e->left.num / e->right.num; + e->right.int_val = e->left.int_val / e->right.int_val; break; case EXPR_MOD: - e->right.num = e->left.num % e->right.num; + e->right.int_val = e->left.int_val % e->right.int_val; break; case EXPR_NEG: - e->right.num = -(e->right.num); + e->right.int_val = -(e->right.int_val); break; case EXPR_NOT: - e->right.num = ~(e->right.num); + e->right.int_val = ~(e->right.int_val); break; case EXPR_OR: - e->right.num = e->left.num | e->right.num; + e->right.int_val = e->left.int_val | e->right.int_val; break; case EXPR_AND: - e->right.num = e->left.num & e->right.num; + e->right.int_val = e->left.int_val & e->right.int_val; break; case EXPR_XOR: - e->right.num = e->left.num ^ e->right.num; + e->right.int_val = e->left.int_val ^ e->right.int_val; break; case EXPR_SHL: - e->right.num = e->right.num << e->left.num; + e->right.int_val = e->right.int_val << e->left.int_val; break; case EXPR_SHR: - e->right.num = e->right.num << e->left.num; + e->right.int_val = e->right.int_val << e->left.int_val; break; case EXPR_LOR: - e->right.num = e->left.num || e->right.num; + e->right.int_val = e->left.int_val || e->right.int_val; break; case EXPR_LAND: - e->right.num = e->left.num && e->right.num; + e->right.int_val = e->left.int_val && e->right.int_val; break; case EXPR_LNOT: - e->right.num = !e->right.num; + e->right.int_val = !e->right.int_val; break; case EXPR_EQ: - e->right.num = e->right.num == e->left.num; + e->right.int_val = e->right.int_val == e->left.int_val; break; case EXPR_LT: - e->right.num = e->right.num < e->left.num; + e->right.int_val = e->right.int_val < e->left.int_val; break; case EXPR_GT: - e->right.num = e->right.num > e->left.num; + e->right.int_val = e->right.int_val > e->left.int_val; break; case EXPR_LE: - e->right.num = e->right.num <= e->left.num; + e->right.int_val = e->right.int_val <= e->left.int_val; break; case EXPR_GE: - e->right.num = e->right.num >= e->left.num; + e->right.int_val = e->right.int_val >= e->left.int_val; break; case EXPR_NE: - e->right.num = e->right.num != e->left.num; + e->right.int_val = e->right.int_val != e->left.int_val; break; case EXPR_IDENT: break; @@ -243,31 +255,31 @@ expr_simplify(expr *e) } /* catch simple identities like 0+x, 1*x, etc., for x not a num */ - else if (e->ltype == EXPR_NUM && ((e->left.num == 1 && e->op == EXPR_MUL) - || (e->left.num == 0 && + else if (e->ltype == EXPR_INT && ((e->left.int_val == 1 && e->op == EXPR_MUL) + || (e->left.int_val == 0 && e->op == EXPR_ADD) - || (e->left.num == -1 && + || (e->left.int_val == -1 && e->op == EXPR_AND) - || (e->left.num == 0 && + || (e->left.int_val == 0 && e->op == EXPR_OR))) { e->op = EXPR_IDENT; simplified = 1; } /* and the corresponding x+|-0, x*&/1 */ - else if (e->rtype == EXPR_NUM && ((e->right.num == 1 && e->op == EXPR_MUL) - || (e->right.num == 1 && + else if (e->rtype == EXPR_INT && ((e->right.int_val == 1 && e->op == EXPR_MUL) + || (e->right.int_val == 1 && e->op == EXPR_DIV) - || (e->right.num == 0 && + || (e->right.int_val == 0 && e->op == EXPR_ADD) - || (e->right.num == 0 && + || (e->right.int_val == 0 && e->op == EXPR_SUB) - || (e->right.num == -1 && + || (e->right.int_val == -1 && e->op == EXPR_AND) - || (e->right.num == 0 && + || (e->right.int_val == 0 && e->op == EXPR_OR) - || (e->right.num == 0 && + || (e->right.int_val == 0 && e->op == EXPR_SHL) - || (e->right.num == 0 && + || (e->right.int_val == 0 && e->op == EXPR_SHR))) { e->op = EXPR_IDENT; e->rtype = e->ltype; @@ -281,11 +293,11 @@ expr_simplify(expr *e) int expr_get_value(expr *e, unsigned long *retval) { - while (!(e->op == EXPR_IDENT && e->rtype == EXPR_NUM) + while (!(e->op == EXPR_IDENT && e->rtype == EXPR_INT) && expr_simplify(e)) ; - if (e->op == EXPR_IDENT && e->rtype == EXPR_NUM) { - *retval = e->right.num; + if (e->op == EXPR_IDENT && e->rtype == EXPR_INT) { + *retval = e->right.int_val; return 1; } else return 0; @@ -296,17 +308,20 @@ expr_print(expr *e) { if (e->op != EXPR_IDENT) { switch (e->ltype) { - case EXPR_NUM: - printf("%lu", e->left.num); - break; case EXPR_SYM: printf("%s", e->left.sym->name); break; case EXPR_EXPR: printf("("); - expr_print(e->left.expr); - + expr_print(e->left.exp); printf(")"); + break; + case EXPR_INT: + printf("%lu", e->left.int_val); + break; + case EXPR_FLOAT: + floatnum_print(e->left.flt); + break; case EXPR_NONE: break; } @@ -379,17 +394,20 @@ expr_print(expr *e) break; } switch (e->rtype) { - case EXPR_NUM: - printf("%lu", e->right.num); - break; case EXPR_SYM: printf("%s", e->right.sym->name); break; case EXPR_EXPR: printf("("); - expr_print(e->right.expr); - + expr_print(e->right.exp); printf(")"); + break; + case EXPR_INT: + printf("%lu", e->right.int_val); + break; + case EXPR_FLOAT: + floatnum_print(e->right.flt); + break; case EXPR_NONE: break; } diff --git a/src/expr.h b/src/expr.h index 8723d898..6846fdb2 100644 --- a/src/expr.h +++ b/src/expr.h @@ -1,7 +1,7 @@ /* $IdPath$ * Expression handling header file * - * Copyright (C) 2001 Michael Urman + * Copyright (C) 2001 Michael Urman, Peter Johnson * * This file is part of YASM. * @@ -49,15 +49,17 @@ typedef enum { typedef enum { EXPR_NONE, /* for left side of a NOT, NEG, etc. */ - EXPR_NUM, + EXPR_SYM, EXPR_EXPR, - EXPR_SYM + EXPR_INT, + EXPR_FLOAT } ExprType; typedef union expritem_u { struct symrec_s *sym; - struct expr_s *expr; - unsigned long num; + struct expr_s *exp; + unsigned long int_val; + struct floatnum_s *flt; } ExprItem; typedef struct expr_s { @@ -70,7 +72,8 @@ expr *expr_new(ExprType, ExprItem, ExprOp, ExprType, ExprItem); ExprItem ExprSym(struct symrec_s *); ExprItem ExprExpr(expr *); -ExprItem ExprNum(unsigned long); +ExprItem ExprInt(unsigned long); +ExprItem ExprFloat(struct floatnum_s *); ExprItem ExprNone(void); #define expr_new_tree(l,o,r) \ diff --git a/src/floatnum.c b/src/floatnum.c new file mode 100644 index 00000000..bef9080e --- /dev/null +++ b/src/floatnum.c @@ -0,0 +1,77 @@ +/* $IdPath$ + * Floating point number functions. + * + * Copyright (C) 2001 Peter Johnson + * + * This file is part of YASM. + * + * YASM 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 2 of the License, or + * (at your option) any later version. + * + * YASM 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "util.h" + +#include + +#ifdef STDC_HEADERS +# include +#endif + +#include "errwarn.h" +#include "floatnum.h" + +RCSID("$IdPath$"); + +floatnum * +floatnum_new(char *str) +{ + floatnum *flt = malloc(sizeof(floatnum)); + if (!flt) + Fatal(FATAL_NOMEM); + /* TODO */ + return flt; +} + +unsigned long +floatnum_get_int(floatnum *flt) +{ + return 0; /* TODO */ +} + +unsigned char * +floatnum_get_single(unsigned char *ptr, floatnum *flt) +{ + return ptr; /* TODO */ +} + +unsigned char * +floatnum_get_double(unsigned char *ptr, floatnum *flt) +{ + return ptr; /* TODO */ +} + +unsigned char * +floatnum_get_extended(unsigned char *ptr, floatnum *flt) +{ + return ptr; /* TODO */ +} + +void +floatnum_print(floatnum *flt) +{ + /* TODO */ +} diff --git a/src/floatnum.h b/src/floatnum.h new file mode 100644 index 00000000..bbea9755 --- /dev/null +++ b/src/floatnum.h @@ -0,0 +1,37 @@ +/* $IdPath$ + * Floating point number functions header file. + * + * Copyright (C) 2001 Peter Johnson + * + * This file is part of YASM. + * + * YASM 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 2 of the License, or + * (at your option) any later version. + * + * YASM 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef YASM_FLOATNUM_H +#define YASM_FLOATNUM_H + +typedef struct floatnum_s { + unsigned char extval[10]; /* float stored in extended precision */ +} floatnum; + +floatnum *floatnum_new(char *str); +unsigned long floatnum_get_int(floatnum *flt); +unsigned char *floatnum_get_single(unsigned char *ptr, floatnum *flt); +unsigned char *floatnum_get_double(unsigned char *ptr, floatnum *flt); +unsigned char *floatnum_get_extended(unsigned char *ptr, floatnum *flt); + +void floatnum_print(floatnum *flt); + +#endif diff --git a/src/parsers/nasm/bison.y.in b/src/parsers/nasm/bison.y.in index cb596260..5aa68e6f 100644 --- a/src/parsers/nasm/bison.y.in +++ b/src/parsers/nasm/bison.y.in @@ -37,6 +37,7 @@ #include "globals.h" #include "errwarn.h" +#include "floatnum.h" #include "expr.h" #include "symrec.h" @@ -58,17 +59,15 @@ extern sectionhead nasm_parser_sections; extern section *nasm_parser_cur_section; extern char *nasm_parser_locallabel_base; +static bytecode *nasm_parser_prev_bc = (bytecode *)NULL; +static bytecode *nasm_parser_temp_bc; + %} %union { unsigned long int_val; char *str_val; - double double_val; - symrec *sym; - struct { - char *name; - int line; - } syminfo; + floatnum *flt; unsigned char groupdata[4]; effaddr *ea; expr *exp; @@ -80,7 +79,7 @@ extern char *nasm_parser_locallabel_base; } %token INTNUM -%token FLTNUM +%token FLTNUM %token DIRECTIVE_NAME DIRECTIVE_VAL STRING %token BYTE WORD DWORD QWORD TWORD DQWORD %token DECLARE_DATA @@ -96,7 +95,7 @@ extern char *nasm_parser_locallabel_base; %token REG_AL REG_CL REG_DL REG_BL REG_AH REG_CH REG_DH REG_BH %token REG_ES REG_CS REG_SS REG_DS REG_FS REG_GS %token LEFT_OP RIGHT_OP SIGNDIV SIGNMOD -%token ID LOCAL_ID SPECIAL_ID +%token ID LOCAL_ID SPECIAL_ID /* instruction tokens (dynamically generated) */ /* @TOKENS@ */ @@ -113,8 +112,7 @@ extern char *nasm_parser_locallabel_base; %type rm8 rm16 rm32 rm64 rm128 %type imm imm8x imm16x imm32x imm8 imm16 imm32 %type expr expr_no_string -%type explabel -%type label_id +%type explabel label_id %type target %type dataval %type datavals @@ -130,7 +128,10 @@ extern char *nasm_parser_locallabel_base; %% input: /* empty */ | input line { - bytecodes_append(&nasm_parser_cur_section->bc, $2); + nasm_parser_temp_bc = bytecodes_append(&nasm_parser_cur_section->bc, + $2); + if (nasm_parser_temp_bc) + nasm_parser_prev_bc = nasm_parser_temp_bc; line_number++; } ; @@ -171,25 +172,31 @@ dataval: expr_no_string { $$ = dataval_new_expr($1); } } ; -label: label_id { $1->value = 0; } /* TODO: add pointer to bytecode */ - | label_id ':' { $1->value = 0; } /* TODO: add pointer to bytecode */ +label: label_id { + symrec_define_label($1, nasm_parser_cur_section, nasm_parser_prev_bc); + } + | label_id ':' { + symrec_define_label($1, nasm_parser_cur_section, nasm_parser_prev_bc); + } ; label_id: ID { - $$ = symrec_define($1.name, SYM_LABEL); - nasm_parser_locallabel_base = strdup($1.name); + $$ = $1; + nasm_parser_locallabel_base = strdup($1); } - | SPECIAL_ID { $$ = symrec_define($1.name, SYM_LABEL); } - | LOCAL_ID { $$ = symrec_define($1.name, SYM_LABEL); } + | SPECIAL_ID + | LOCAL_ID ; /* directives */ directive: '[' DIRECTIVE_NAME DIRECTIVE_VAL ']' { - if (strcasecmp($2, "section") == 0) + if (strcasecmp($2, "section") == 0) { nasm_parser_cur_section = sections_switch(&nasm_parser_sections, nasm_parser_objfmt, $3); - else + nasm_parser_prev_bc = (bytecode *)NULL; + } else { printf("Directive: Name='%s' Value='%s'\n", $2, $3); + } } | '[' DIRECTIVE_NAME DIRECTIVE_VAL error { Error(_("missing `%c'"), ']'); @@ -375,9 +382,9 @@ target: expr { $$.val = $1; $$.op_sel = JR_NONE; } ; /* expression trees */ -expr_no_string: INTNUM { $$ = expr_new_ident(EXPR_NUM, ExprNum($1)); } +expr_no_string: INTNUM { $$ = expr_new_ident(EXPR_INT, ExprInt($1)); } | explabel { - $$ = expr_new_ident(EXPR_SYM, ExprSym(symrec_use($1.name, SYM_LABEL))); + $$ = expr_new_ident(EXPR_SYM, ExprSym(symrec_use($1))); } /*| expr '||' expr { $$ = expr_new_tree($1, EXPR_LOR, $3); }*/ | expr '|' expr { $$ = expr_new_tree($1, EXPR_OR, $3); } @@ -406,7 +413,7 @@ expr_no_string: INTNUM { $$ = expr_new_ident(EXPR_NUM, ExprNum($1)); } expr: expr_no_string | STRING { - $$ = expr_new_ident (EXPR_NUM, ExprNum(ConvertCharConstToInt($1))); + $$ = expr_new_ident (EXPR_INT, ExprInt(ConvertCharConstToInt($1))); } ; diff --git a/src/parsers/nasm/nasm-bison.y b/src/parsers/nasm/nasm-bison.y index cb596260..5aa68e6f 100644 --- a/src/parsers/nasm/nasm-bison.y +++ b/src/parsers/nasm/nasm-bison.y @@ -37,6 +37,7 @@ #include "globals.h" #include "errwarn.h" +#include "floatnum.h" #include "expr.h" #include "symrec.h" @@ -58,17 +59,15 @@ extern sectionhead nasm_parser_sections; extern section *nasm_parser_cur_section; extern char *nasm_parser_locallabel_base; +static bytecode *nasm_parser_prev_bc = (bytecode *)NULL; +static bytecode *nasm_parser_temp_bc; + %} %union { unsigned long int_val; char *str_val; - double double_val; - symrec *sym; - struct { - char *name; - int line; - } syminfo; + floatnum *flt; unsigned char groupdata[4]; effaddr *ea; expr *exp; @@ -80,7 +79,7 @@ extern char *nasm_parser_locallabel_base; } %token INTNUM -%token FLTNUM +%token FLTNUM %token DIRECTIVE_NAME DIRECTIVE_VAL STRING %token BYTE WORD DWORD QWORD TWORD DQWORD %token DECLARE_DATA @@ -96,7 +95,7 @@ extern char *nasm_parser_locallabel_base; %token REG_AL REG_CL REG_DL REG_BL REG_AH REG_CH REG_DH REG_BH %token REG_ES REG_CS REG_SS REG_DS REG_FS REG_GS %token LEFT_OP RIGHT_OP SIGNDIV SIGNMOD -%token ID LOCAL_ID SPECIAL_ID +%token ID LOCAL_ID SPECIAL_ID /* instruction tokens (dynamically generated) */ /* @TOKENS@ */ @@ -113,8 +112,7 @@ extern char *nasm_parser_locallabel_base; %type rm8 rm16 rm32 rm64 rm128 %type imm imm8x imm16x imm32x imm8 imm16 imm32 %type expr expr_no_string -%type explabel -%type label_id +%type explabel label_id %type target %type dataval %type datavals @@ -130,7 +128,10 @@ extern char *nasm_parser_locallabel_base; %% input: /* empty */ | input line { - bytecodes_append(&nasm_parser_cur_section->bc, $2); + nasm_parser_temp_bc = bytecodes_append(&nasm_parser_cur_section->bc, + $2); + if (nasm_parser_temp_bc) + nasm_parser_prev_bc = nasm_parser_temp_bc; line_number++; } ; @@ -171,25 +172,31 @@ dataval: expr_no_string { $$ = dataval_new_expr($1); } } ; -label: label_id { $1->value = 0; } /* TODO: add pointer to bytecode */ - | label_id ':' { $1->value = 0; } /* TODO: add pointer to bytecode */ +label: label_id { + symrec_define_label($1, nasm_parser_cur_section, nasm_parser_prev_bc); + } + | label_id ':' { + symrec_define_label($1, nasm_parser_cur_section, nasm_parser_prev_bc); + } ; label_id: ID { - $$ = symrec_define($1.name, SYM_LABEL); - nasm_parser_locallabel_base = strdup($1.name); + $$ = $1; + nasm_parser_locallabel_base = strdup($1); } - | SPECIAL_ID { $$ = symrec_define($1.name, SYM_LABEL); } - | LOCAL_ID { $$ = symrec_define($1.name, SYM_LABEL); } + | SPECIAL_ID + | LOCAL_ID ; /* directives */ directive: '[' DIRECTIVE_NAME DIRECTIVE_VAL ']' { - if (strcasecmp($2, "section") == 0) + if (strcasecmp($2, "section") == 0) { nasm_parser_cur_section = sections_switch(&nasm_parser_sections, nasm_parser_objfmt, $3); - else + nasm_parser_prev_bc = (bytecode *)NULL; + } else { printf("Directive: Name='%s' Value='%s'\n", $2, $3); + } } | '[' DIRECTIVE_NAME DIRECTIVE_VAL error { Error(_("missing `%c'"), ']'); @@ -375,9 +382,9 @@ target: expr { $$.val = $1; $$.op_sel = JR_NONE; } ; /* expression trees */ -expr_no_string: INTNUM { $$ = expr_new_ident(EXPR_NUM, ExprNum($1)); } +expr_no_string: INTNUM { $$ = expr_new_ident(EXPR_INT, ExprInt($1)); } | explabel { - $$ = expr_new_ident(EXPR_SYM, ExprSym(symrec_use($1.name, SYM_LABEL))); + $$ = expr_new_ident(EXPR_SYM, ExprSym(symrec_use($1))); } /*| expr '||' expr { $$ = expr_new_tree($1, EXPR_LOR, $3); }*/ | expr '|' expr { $$ = expr_new_tree($1, EXPR_OR, $3); } @@ -406,7 +413,7 @@ expr_no_string: INTNUM { $$ = expr_new_ident(EXPR_NUM, ExprNum($1)); } expr: expr_no_string | STRING { - $$ = expr_new_ident (EXPR_NUM, ExprNum(ConvertCharConstToInt($1))); + $$ = expr_new_ident (EXPR_INT, ExprInt(ConvertCharConstToInt($1))); } ; diff --git a/src/parsers/nasm/token.l.in b/src/parsers/nasm/token.l.in index 47a6fdb7..4f4b72b2 100644 --- a/src/parsers/nasm/token.l.in +++ b/src/parsers/nasm/token.l.in @@ -35,6 +35,7 @@ #define _(String) gettext(String) #include "errwarn.h" +#include "floatnum.h" #include "expr.h" #include "symrec.h" @@ -114,7 +115,7 @@ WS [ \t\r] /* floating point value */ {DIGIT}+\.{DIGIT}*(e[-+]?{DIGIT}+)? { - yylval.double_val = strtod(yytext, (char **)NULL); + yylval.flt = floatnum_new(yytext); return FLTNUM; } @@ -295,10 +296,9 @@ gs { yylval.int_val = 5; return REG_GS; } /* special non-local ..@label and labels like ..start */ $$|$|\.\.[a-z0-9_$#@~.?]+ { - yylval.syminfo.name = strdup(yytext); - if (!yylval.syminfo.name) + yylval.str_val = strdup(yytext); + if (!yylval.str_val) Fatal(FATAL_NOMEM); - yylval.syminfo.line = line_number; return SPECIAL_ID; } @@ -307,18 +307,17 @@ $$|$|\.\.[a-z0-9_$#@~.?]+ { \.[a-z0-9_$#@~?][a-z0-9_$#@~.?]* { if (!nasm_parser_locallabel_base) { Warning(_("no non-local label before `%s'"), yytext); - yylval.syminfo.name = strdup(yytext); - if (!yylval.syminfo.name) + yylval.str_val = strdup(yytext); + if (!yylval.str_val) Fatal(FATAL_NOMEM); } else { - yylval.syminfo.name = malloc(strlen(yytext) + - strlen(nasm_parser_locallabel_base) + 1); - if (!yylval.syminfo.name) + yylval.str_val = malloc(strlen(yytext) + + strlen(nasm_parser_locallabel_base) + 1); + if (!yylval.str_val) Fatal(FATAL_NOMEM); - strcpy(yylval.syminfo.name, nasm_parser_locallabel_base); - strcat(yylval.syminfo.name, yytext); + strcpy(yylval.str_val, nasm_parser_locallabel_base); + strcat(yylval.str_val, yytext); } - yylval.syminfo.line = line_number; return LOCAL_ID; } @@ -328,10 +327,9 @@ $$|$|\.\.[a-z0-9_$#@~.?]+ { /* label */ [a-z_?][a-z0-9_$#@~.?]* { - yylval.syminfo.name = strdup(yytext); - if (!yylval.syminfo.name) + yylval.str_val = strdup(yytext); + if (!yylval.str_val) Fatal(FATAL_NOMEM); - yylval.syminfo.line = line_number; return ID; } diff --git a/src/symrec.c b/src/symrec.c index 2196638e..2c7947cd 100644 --- a/src/symrec.c +++ b/src/symrec.c @@ -1,7 +1,7 @@ /* $IdPath$ * Symbol table handling * - * Copyright (C) 2001 Michael Urman + * Copyright (C) 2001 Michael Urman, Peter Johnson * * This file is part of YASM. * @@ -35,19 +35,24 @@ #include "globals.h" #include "errwarn.h" +#include "floatnum.h" #include "symrec.h" +#include "bytecode.h" +#include "section.h" + RCSID("$IdPath$"); /* private functions */ -static symrec *symrec_get_or_new(char *, SymType); +static symrec *symrec_get_or_new(const char *); +static symrec *symrec_define(const char *, SymType type); /* The symbol table: a ternary tree. */ static ternary_tree sym_table = (ternary_tree)NULL; /* create a new symrec */ static symrec * -symrec_get_or_new(char *name, SymType type) +symrec_get_or_new(const char *name) { symrec *rec, *rec2; @@ -65,41 +70,128 @@ symrec_get_or_new(char *name, SymType type) rec->name = strdup(name); if (!rec->name) Fatal(FATAL_NOMEM); - rec->type = type; - rec->value = 0; + rec->type = SYM_UNKNOWN; rec->filename = strdup(filename); rec->line = line_number; rec->status = SYM_NOSTATUS; + rec->visibility = SYM_LOCAL; return rec; } /* call a function with each symrec. stop early if 0 returned */ void -symrec_foreach(int (*func) (char *name, symrec *rec)) +symrec_foreach(int (*func) (const char *name, symrec *rec)) { + /* TODO */ } symrec * -symrec_use(char *name, SymType type) +symrec_use(const char *name) { - symrec *rec; + symrec *rec = symrec_get_or_new(name); - rec = symrec_get_or_new(name, type); rec->status |= SYM_USED; return rec; } +static symrec * +symrec_define(const char *name, SymType type) +{ + symrec *rec = symrec_get_or_new(name); + + /* Has it been defined before (either by DEFINED or COMMON/EXTERN)? */ + if (rec->status & SYM_DEFINED) { + Error(_("duplicate definition of `%s'; first defined on line %d"), + name, rec->line); + } else { + rec->line = line_number; /* set line number of definition */ + rec->type = type; + rec->status |= SYM_DEFINED; + } + return rec; +} + +symrec * +symrec_define_constant_int(const char *name, unsigned long int_val) +{ + symrec *rec = symrec_define(name, SYM_CONSTANT_INT); + rec->value.int_val = int_val; + rec->status |= SYM_VALUED; + return rec; +} + symrec * -symrec_define(char *name, SymType type) +symrec_define_constant_float(const char *name, floatnum *flt) { - symrec *rec; + symrec *rec = symrec_define(name, SYM_CONSTANT_FLOAT); + rec->value.flt = flt; + rec->status |= SYM_VALUED; + return rec; +} - rec = symrec_get_or_new(name, type); - if (rec->status & SYM_DECLARED) - Error(_("duplicate definition of `%s'; previously defined on line %d"), +symrec * +symrec_define_label(const char *name, section *sect, bytecode *precbc) +{ + symrec *rec = symrec_define(name, SYM_LABEL); + rec->value.label.sect = sect; + rec->value.label.bc = precbc; + return rec; +} + +symrec * +symrec_declare(const char *name, SymVisibility vis) +{ + symrec *rec = symrec_get_or_new(name); + + /* Don't allow EXTERN and COMMON if symbol has already been DEFINED. */ + /* Also, EXTERN and COMMON are mutually exclusive. */ + if ((rec->status & SYM_DEFINED) || + ((rec->visibility & SYM_COMMON) && (vis == SYM_EXTERN)) || + ((rec->visibility & SYM_EXTERN) && (vis == SYM_COMMON))) { + Error(_("duplicate definition of `%s'; first defined on line %d"), name, rec->line); - rec->line = line_number; /* set line number of definition */ - rec->status |= SYM_DECLARED; + } else { + rec->line = line_number; /* set line number of declaration */ + rec->visibility |= vis; + + /* If declared as COMMON or EXTERN, set as DEFINED. */ + if ((vis == SYM_COMMON) || (vis == SYM_EXTERN)) + rec->status |= SYM_DEFINED; + } return rec; } + +int +symrec_get_int_value(const symrec *sym, unsigned long *ret_val, + int resolve_label) +{ + /* If we already know the value, just return it. */ + if (sym->status & SYM_VALUED) { + switch (sym->type) { + case SYM_CONSTANT_INT: + *ret_val = sym->value.int_val; + break; + case SYM_CONSTANT_FLOAT: + *ret_val = floatnum_get_int(sym->value.flt); + break; + case SYM_LABEL: + if (!bytecode_get_offset(sym->value.label.sect, + sym->value.label.bc, ret_val)) + InternalError(__LINE__, __FILE__, + _("Label symbol is valued but cannot get offset")); + case SYM_UNKNOWN: + InternalError(__LINE__, __FILE__, + _("Have a valued symbol but of unknown type")); + } + return 1; + } + + /* Try to get offset of unvalued label */ + if (resolve_label && sym->type == SYM_LABEL) + return bytecode_get_offset(sym->value.label.sect, sym->value.label.bc, + ret_val); + + /* We can't get the value right now. */ + return 0; +} diff --git a/src/symrec.h b/src/symrec.h index fd2e5c38..21183f4b 100644 --- a/src/symrec.h +++ b/src/symrec.h @@ -1,7 +1,7 @@ /* $IdPath$ * Symbol table handling header file * - * Copyright (C) 2001 Michael Urman + * Copyright (C) 2001 Michael Urman, Peter Johnson * * This file is part of YASM. * @@ -22,15 +22,26 @@ #ifndef YASM_SYMREC_H #define YASM_SYMREC_H +/* DEFINED is set with EXTERN and COMMON below */ typedef enum { SYM_NOSTATUS = 0, - SYM_USED = 1 << 0, /* for using variables before declared */ - SYM_DECLARED = 1 << 1, /* once it's been declared */ + SYM_USED = 1 << 0, /* for using variables before definition */ + SYM_DEFINED = 1 << 1, /* once it's been defined in the file */ SYM_VALUED = 1 << 2 /* once its value has been determined */ } SymStatus; +/* EXTERN and COMMON are mutually exclusive */ typedef enum { - SYM_CONSTANT, /* for EQU defined symbols */ + SYM_LOCAL = 0, /* default, local only */ + SYM_GLOBAL = 1 << 0, /* if it's declared GLOBAL */ + SYM_COMMON = 1 << 1, /* if it's declared COMMON */ + SYM_EXTERN = 1 << 2 /* if it's declared EXTERN */ +} SymVisibility; + +typedef enum { + SYM_UNKNOWN, /* for unknown type (COMMON/EXTERN) */ + SYM_CONSTANT_INT, /* for EQU defined symbols (integers) */ + SYM_CONSTANT_FLOAT, /* (floating point) */ SYM_LABEL /* for labels */ } SymType; @@ -38,13 +49,34 @@ typedef struct symrec_s { char *name; SymType type; SymStatus status; + SymVisibility visibility; char *filename; /* file and line */ - int line; /* symbol was first declared or used on */ - double value; + unsigned long line; /* symbol was first declared or used on */ + union { + unsigned long int_val; /* integer constant */ + struct floatnum_s *flt; /* floating point constant */ + struct label_s { /* bytecode immediately preceding a label */ + struct section_s *sect; + struct bytecode_s *bc; + } label; + } value; } symrec; -symrec *symrec_use(char *name, SymType type); -symrec *symrec_define(char *name, SymType type); -void symrec_foreach(int (*func) (char *name, symrec *rec)); +symrec *symrec_use(const char *name); +symrec *symrec_define_constant_int(const char *name, unsigned long int_val); +symrec *symrec_define_constant_float(const char *name, struct floatnum_s *flt); +symrec *symrec_define_label(const char *name, struct section_s *sect, + struct bytecode_s *precbc); +symrec *symrec_declare(const char *name, SymVisibility vis); + +/* Get the numeric 32-bit value of a symbol if possible. + * Return value is IF POSSIBLE, not the value. + * If resolve_label is true, tries to get offset of labels, otherwise it + * returns not possible. + */ +int symrec_get_int_value(const symrec *sym, unsigned long *ret_val, + int resolve_label); + +void symrec_foreach(int (*func) (const char *name, symrec *rec)); #endif