From fb3e968a292603e1ff5254c9e93adead33f78aa3 Mon Sep 17 00:00:00 2001 From: Michael Urman Date: Thu, 5 Jul 2001 06:28:54 +0000 Subject: [PATCH] Initial checkin of expression handling. svn path=/trunk/yasm/; revision=106 --- include/Makefile.am | 1 + include/expr.h | 72 ++++++++++++++ libyasm/expr.c | 191 +++++++++++++++++++++++++++++++++++++ libyasm/expr.h | 72 ++++++++++++++ modules/arch/x86/expr.c | 191 +++++++++++++++++++++++++++++++++++++ modules/arch/x86/x86expr.c | 191 +++++++++++++++++++++++++++++++++++++ src/Makefile.am | 1 + src/arch/x86/expr.c | 191 +++++++++++++++++++++++++++++++++++++ src/arch/x86/x86expr.c | 191 +++++++++++++++++++++++++++++++++++++ src/expr.c | 191 +++++++++++++++++++++++++++++++++++++ src/expr.h | 72 ++++++++++++++ 11 files changed, 1364 insertions(+) create mode 100644 include/expr.h create mode 100644 libyasm/expr.c create mode 100644 libyasm/expr.h create mode 100644 modules/arch/x86/expr.c create mode 100644 modules/arch/x86/x86expr.c create mode 100644 src/arch/x86/expr.c create mode 100644 src/arch/x86/x86expr.c create mode 100644 src/expr.c create mode 100644 src/expr.h diff --git a/include/Makefile.am b/include/Makefile.am index 07b5cc16..62832edd 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -1,6 +1,7 @@ EXTRA_DIST = \ bytecode.h \ errwarn.h \ + expr.h \ globals.h \ section.h \ symrec.h \ diff --git a/include/expr.h b/include/expr.h new file mode 100644 index 00000000..18d6eee1 --- /dev/null +++ b/include/expr.h @@ -0,0 +1,72 @@ +/* $Id: expr.h,v 1.1 2001/07/05 06:28:54 mu Exp $ + * Expression handling header file + * + * Copyright (C) 2001 Michael Urman + * + * 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 _EXPR_H_ +#define _EXPR_H_ + +typedef enum { + EXPR_ADD, + EXPR_SUB, + EXPR_MUL, + EXPR_DIV, + EXPR_MOD, + EXPR_NEG, + EXPR_NOT, + EXPR_OR, + EXPR_AND, + EXPR_XOR, + EXPR_SHL, + EXPR_SHR, + EXPR_LOR, + EXPR_LAND, + EXPR_LNOT, + EXPR_LT, + EXPR_GT, + EXPR_EQ, + EXPR_LE, + EXPR_GE, + EXPR_NE, + EXPR_IDENT /* if right is IDENT, then the entire expr is just a num */ +} ExprOp; + +typedef enum { + EXPR_NONE, /* for left side of a NOT, NEG, etc. */ + EXPR_NUM, + EXPR_EXPR, + EXPR_SYM +} ExprType; + +typedef union expritem_u { + struct symrec_s *sym; + struct expr_s *expr; + int num; +} ExprItem; + +typedef struct expr_s { + ExprType ltype, rtype; + ExprItem left, right; + ExprOp op; +} expr; + +expr *expr_new (ExprType, ExprItem, ExprOp, ExprType, ExprItem); +int expr_simplify (expr *); + +#endif diff --git a/libyasm/expr.c b/libyasm/expr.c new file mode 100644 index 00000000..e6210957 --- /dev/null +++ b/libyasm/expr.c @@ -0,0 +1,191 @@ +/* $Id: expr.c,v 1.1 2001/07/05 06:28:54 mu Exp $ + * Expression handling + * + * Copyright (C) 2001 Michael Urman + * + * 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 + */ +#include +#include +#include "expr.h" +#include "symrec.h" +#include "globals.h" +#include "errwarn.h" + +/* allocate a new expression node, with children as defined. + * If it's a unary operator, put the element on the right */ +expr *expr_new (ExprType ltype, + ExprItem left, + ExprOp op, + ExprType rtype, + ExprItem right) +{ + expr *ptr; + ptr = malloc (sizeof (expr)); + if (ptr == NULL) Fatal (FATAL_NOMEM); + ptr->ltype = ltype; + ptr->op = op; + ptr->rtype = rtype; + switch (ltype) + { + case EXPR_NUM: + case EXPR_SYM: + case EXPR_EXPR: + memcpy (&ptr->left, &left, sizeof (ExprItem)); + break; + case EXPR_NONE: break; + } + switch (rtype) + { + case EXPR_NUM: + case EXPR_SYM: + case EXPR_EXPR: + memcpy (&ptr->right, &right, sizeof (ExprItem)); + break; + case EXPR_NONE: + Fatal (FATAL_UNKNOWN); /* TODO: better error? */ + break; + } + return ptr; +} + +/* get rid of unnecessary branches if possible. report. */ +int expr_simplify (expr *e) +{ + int simplified = 0; + + /* 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 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) + { + 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)); + 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; + /* don't try to free the symrec here. */ + e->left.num = e->left.sym->value; + simplified = 1; + } + } + + /* ditto on the right */ + if (e->rtype == EXPR_EXPR) + { + if (e->right.expr->op != EXPR_IDENT) + simplified |= expr_simplify (e->right.expr); + + while (e->rtype == EXPR_EXPR && e->right.expr->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)); + simplified = 1; + } + } + else if (e->rtype == EXPR_SYM) + { + if (e->right.sym->status & SYM_VALUED) + { + e->rtype = EXPR_NUM; + /* don't try to free the symrec here. */ + e->right.num = e->right.sym->value; + simplified = 1; + } + } + + if ((e->ltype == EXPR_NUM || e->ltype == EXPR_NONE) + && e->rtype == EXPR_NUM + && e->op != EXPR_IDENT) + { + switch (e->op) + { + case EXPR_ADD: e->right.num = e->left.num + e->right.num; break; + case EXPR_SUB: e->right.num = e->left.num - e->right.num; break; + case EXPR_MUL: e->right.num = e->left.num * e->right.num; break; + case EXPR_DIV: e->right.num = e->left.num / e->right.num; break; + case EXPR_MOD: e->right.num = e->left.num % e->right.num; break; + case EXPR_NEG: e->right.num = -(e->right.num); break; + case EXPR_NOT: e->right.num = ~(e->right.num); break; + case EXPR_OR: e->right.num = e->left.num | e->right.num; break; + case EXPR_AND: e->right.num = e->left.num & e->right.num; break; + case EXPR_XOR: e->right.num = e->left.num ^ e->right.num; break; + case EXPR_SHL: e->right.num = e->right.num << e->left.num; break; + case EXPR_SHR: e->right.num = e->right.num << e->left.num; break; + case EXPR_LOR: e->right.num = e->left.num || e->right.num; break; + case EXPR_LAND: e->right.num = e->left.num && e->right.num; break; + case EXPR_LNOT: e->right.num = !e->right.num; break; + case EXPR_EQ: e->right.num = e->right.num == e->left.num; break; + case EXPR_LT: e->right.num = e->right.num < e->left.num; break; + case EXPR_GT: e->right.num = e->right.num > e->left.num; break; + case EXPR_LE: e->right.num = e->right.num <= e->left.num; break; + case EXPR_GE: e->right.num = e->right.num >= e->left.num; break; + case EXPR_NE: e->right.num = e->right.num != e->left.num; break; + case EXPR_IDENT: break; + } + e->op = EXPR_IDENT; + simplified = 1; + } + + /* 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 && e->op == EXPR_ADD) + ||(e->left.num == -1 && e->op == EXPR_AND) + ||(e->left.num == 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 && e->op == EXPR_DIV) + ||(e->right.num == 0 && e->op == EXPR_ADD) + ||(e->right.num == 0 && e->op == EXPR_SUB) + ||(e->right.num == -1 && e->op == EXPR_AND) + ||(e->right.num == 0 && e->op == EXPR_OR) + ||(e->right.num == 0 && e->op == EXPR_SHL) + ||(e->right.num == 0 && e->op == EXPR_SHR))) + { + e->op = EXPR_IDENT; + e->rtype = e->ltype; + memcpy (&e->right, &e->left, sizeof (ExprItem)); + simplified = 1; + } + + return simplified; +} diff --git a/libyasm/expr.h b/libyasm/expr.h new file mode 100644 index 00000000..18d6eee1 --- /dev/null +++ b/libyasm/expr.h @@ -0,0 +1,72 @@ +/* $Id: expr.h,v 1.1 2001/07/05 06:28:54 mu Exp $ + * Expression handling header file + * + * Copyright (C) 2001 Michael Urman + * + * 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 _EXPR_H_ +#define _EXPR_H_ + +typedef enum { + EXPR_ADD, + EXPR_SUB, + EXPR_MUL, + EXPR_DIV, + EXPR_MOD, + EXPR_NEG, + EXPR_NOT, + EXPR_OR, + EXPR_AND, + EXPR_XOR, + EXPR_SHL, + EXPR_SHR, + EXPR_LOR, + EXPR_LAND, + EXPR_LNOT, + EXPR_LT, + EXPR_GT, + EXPR_EQ, + EXPR_LE, + EXPR_GE, + EXPR_NE, + EXPR_IDENT /* if right is IDENT, then the entire expr is just a num */ +} ExprOp; + +typedef enum { + EXPR_NONE, /* for left side of a NOT, NEG, etc. */ + EXPR_NUM, + EXPR_EXPR, + EXPR_SYM +} ExprType; + +typedef union expritem_u { + struct symrec_s *sym; + struct expr_s *expr; + int num; +} ExprItem; + +typedef struct expr_s { + ExprType ltype, rtype; + ExprItem left, right; + ExprOp op; +} expr; + +expr *expr_new (ExprType, ExprItem, ExprOp, ExprType, ExprItem); +int expr_simplify (expr *); + +#endif diff --git a/modules/arch/x86/expr.c b/modules/arch/x86/expr.c new file mode 100644 index 00000000..e6210957 --- /dev/null +++ b/modules/arch/x86/expr.c @@ -0,0 +1,191 @@ +/* $Id: expr.c,v 1.1 2001/07/05 06:28:54 mu Exp $ + * Expression handling + * + * Copyright (C) 2001 Michael Urman + * + * 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 + */ +#include +#include +#include "expr.h" +#include "symrec.h" +#include "globals.h" +#include "errwarn.h" + +/* allocate a new expression node, with children as defined. + * If it's a unary operator, put the element on the right */ +expr *expr_new (ExprType ltype, + ExprItem left, + ExprOp op, + ExprType rtype, + ExprItem right) +{ + expr *ptr; + ptr = malloc (sizeof (expr)); + if (ptr == NULL) Fatal (FATAL_NOMEM); + ptr->ltype = ltype; + ptr->op = op; + ptr->rtype = rtype; + switch (ltype) + { + case EXPR_NUM: + case EXPR_SYM: + case EXPR_EXPR: + memcpy (&ptr->left, &left, sizeof (ExprItem)); + break; + case EXPR_NONE: break; + } + switch (rtype) + { + case EXPR_NUM: + case EXPR_SYM: + case EXPR_EXPR: + memcpy (&ptr->right, &right, sizeof (ExprItem)); + break; + case EXPR_NONE: + Fatal (FATAL_UNKNOWN); /* TODO: better error? */ + break; + } + return ptr; +} + +/* get rid of unnecessary branches if possible. report. */ +int expr_simplify (expr *e) +{ + int simplified = 0; + + /* 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 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) + { + 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)); + 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; + /* don't try to free the symrec here. */ + e->left.num = e->left.sym->value; + simplified = 1; + } + } + + /* ditto on the right */ + if (e->rtype == EXPR_EXPR) + { + if (e->right.expr->op != EXPR_IDENT) + simplified |= expr_simplify (e->right.expr); + + while (e->rtype == EXPR_EXPR && e->right.expr->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)); + simplified = 1; + } + } + else if (e->rtype == EXPR_SYM) + { + if (e->right.sym->status & SYM_VALUED) + { + e->rtype = EXPR_NUM; + /* don't try to free the symrec here. */ + e->right.num = e->right.sym->value; + simplified = 1; + } + } + + if ((e->ltype == EXPR_NUM || e->ltype == EXPR_NONE) + && e->rtype == EXPR_NUM + && e->op != EXPR_IDENT) + { + switch (e->op) + { + case EXPR_ADD: e->right.num = e->left.num + e->right.num; break; + case EXPR_SUB: e->right.num = e->left.num - e->right.num; break; + case EXPR_MUL: e->right.num = e->left.num * e->right.num; break; + case EXPR_DIV: e->right.num = e->left.num / e->right.num; break; + case EXPR_MOD: e->right.num = e->left.num % e->right.num; break; + case EXPR_NEG: e->right.num = -(e->right.num); break; + case EXPR_NOT: e->right.num = ~(e->right.num); break; + case EXPR_OR: e->right.num = e->left.num | e->right.num; break; + case EXPR_AND: e->right.num = e->left.num & e->right.num; break; + case EXPR_XOR: e->right.num = e->left.num ^ e->right.num; break; + case EXPR_SHL: e->right.num = e->right.num << e->left.num; break; + case EXPR_SHR: e->right.num = e->right.num << e->left.num; break; + case EXPR_LOR: e->right.num = e->left.num || e->right.num; break; + case EXPR_LAND: e->right.num = e->left.num && e->right.num; break; + case EXPR_LNOT: e->right.num = !e->right.num; break; + case EXPR_EQ: e->right.num = e->right.num == e->left.num; break; + case EXPR_LT: e->right.num = e->right.num < e->left.num; break; + case EXPR_GT: e->right.num = e->right.num > e->left.num; break; + case EXPR_LE: e->right.num = e->right.num <= e->left.num; break; + case EXPR_GE: e->right.num = e->right.num >= e->left.num; break; + case EXPR_NE: e->right.num = e->right.num != e->left.num; break; + case EXPR_IDENT: break; + } + e->op = EXPR_IDENT; + simplified = 1; + } + + /* 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 && e->op == EXPR_ADD) + ||(e->left.num == -1 && e->op == EXPR_AND) + ||(e->left.num == 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 && e->op == EXPR_DIV) + ||(e->right.num == 0 && e->op == EXPR_ADD) + ||(e->right.num == 0 && e->op == EXPR_SUB) + ||(e->right.num == -1 && e->op == EXPR_AND) + ||(e->right.num == 0 && e->op == EXPR_OR) + ||(e->right.num == 0 && e->op == EXPR_SHL) + ||(e->right.num == 0 && e->op == EXPR_SHR))) + { + e->op = EXPR_IDENT; + e->rtype = e->ltype; + memcpy (&e->right, &e->left, sizeof (ExprItem)); + simplified = 1; + } + + return simplified; +} diff --git a/modules/arch/x86/x86expr.c b/modules/arch/x86/x86expr.c new file mode 100644 index 00000000..f653822a --- /dev/null +++ b/modules/arch/x86/x86expr.c @@ -0,0 +1,191 @@ +/* $Id: x86expr.c,v 1.1 2001/07/05 06:28:54 mu Exp $ + * Expression handling + * + * Copyright (C) 2001 Michael Urman + * + * 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 + */ +#include +#include +#include "expr.h" +#include "symrec.h" +#include "globals.h" +#include "errwarn.h" + +/* allocate a new expression node, with children as defined. + * If it's a unary operator, put the element on the right */ +expr *expr_new (ExprType ltype, + ExprItem left, + ExprOp op, + ExprType rtype, + ExprItem right) +{ + expr *ptr; + ptr = malloc (sizeof (expr)); + if (ptr == NULL) Fatal (FATAL_NOMEM); + ptr->ltype = ltype; + ptr->op = op; + ptr->rtype = rtype; + switch (ltype) + { + case EXPR_NUM: + case EXPR_SYM: + case EXPR_EXPR: + memcpy (&ptr->left, &left, sizeof (ExprItem)); + break; + case EXPR_NONE: break; + } + switch (rtype) + { + case EXPR_NUM: + case EXPR_SYM: + case EXPR_EXPR: + memcpy (&ptr->right, &right, sizeof (ExprItem)); + break; + case EXPR_NONE: + Fatal (FATAL_UNKNOWN); /* TODO: better error? */ + break; + } + return ptr; +} + +/* get rid of unnecessary branches if possible. report. */ +int expr_simplify (expr *e) +{ + int simplified = 0; + + /* 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 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) + { + 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)); + 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; + /* don't try to free the symrec here. */ + e->left.num = e->left.sym->value; + simplified = 1; + } + } + + /* ditto on the right */ + if (e->rtype == EXPR_EXPR) + { + if (e->right.expr->op != EXPR_IDENT) + simplified |= expr_simplify (e->right.expr); + + while (e->rtype == EXPR_EXPR && e->right.expr->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)); + simplified = 1; + } + } + else if (e->rtype == EXPR_SYM) + { + if (e->right.sym->status & SYM_VALUED) + { + e->rtype = EXPR_NUM; + /* don't try to free the symrec here. */ + e->right.num = e->right.sym->value; + simplified = 1; + } + } + + if ((e->ltype == EXPR_NUM || e->ltype == EXPR_NONE) + && e->rtype == EXPR_NUM + && e->op != EXPR_IDENT) + { + switch (e->op) + { + case EXPR_ADD: e->right.num = e->left.num + e->right.num; break; + case EXPR_SUB: e->right.num = e->left.num - e->right.num; break; + case EXPR_MUL: e->right.num = e->left.num * e->right.num; break; + case EXPR_DIV: e->right.num = e->left.num / e->right.num; break; + case EXPR_MOD: e->right.num = e->left.num % e->right.num; break; + case EXPR_NEG: e->right.num = -(e->right.num); break; + case EXPR_NOT: e->right.num = ~(e->right.num); break; + case EXPR_OR: e->right.num = e->left.num | e->right.num; break; + case EXPR_AND: e->right.num = e->left.num & e->right.num; break; + case EXPR_XOR: e->right.num = e->left.num ^ e->right.num; break; + case EXPR_SHL: e->right.num = e->right.num << e->left.num; break; + case EXPR_SHR: e->right.num = e->right.num << e->left.num; break; + case EXPR_LOR: e->right.num = e->left.num || e->right.num; break; + case EXPR_LAND: e->right.num = e->left.num && e->right.num; break; + case EXPR_LNOT: e->right.num = !e->right.num; break; + case EXPR_EQ: e->right.num = e->right.num == e->left.num; break; + case EXPR_LT: e->right.num = e->right.num < e->left.num; break; + case EXPR_GT: e->right.num = e->right.num > e->left.num; break; + case EXPR_LE: e->right.num = e->right.num <= e->left.num; break; + case EXPR_GE: e->right.num = e->right.num >= e->left.num; break; + case EXPR_NE: e->right.num = e->right.num != e->left.num; break; + case EXPR_IDENT: break; + } + e->op = EXPR_IDENT; + simplified = 1; + } + + /* 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 && e->op == EXPR_ADD) + ||(e->left.num == -1 && e->op == EXPR_AND) + ||(e->left.num == 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 && e->op == EXPR_DIV) + ||(e->right.num == 0 && e->op == EXPR_ADD) + ||(e->right.num == 0 && e->op == EXPR_SUB) + ||(e->right.num == -1 && e->op == EXPR_AND) + ||(e->right.num == 0 && e->op == EXPR_OR) + ||(e->right.num == 0 && e->op == EXPR_SHL) + ||(e->right.num == 0 && e->op == EXPR_SHR))) + { + e->op = EXPR_IDENT; + e->rtype = e->ltype; + memcpy (&e->right, &e->left, sizeof (ExprItem)); + simplified = 1; + } + + return simplified; +} diff --git a/src/Makefile.am b/src/Makefile.am index 78d7f253..80eacbb7 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -5,6 +5,7 @@ yasm_SOURCES = \ token.l \ bytecode.c \ errwarn.c \ + expr.c \ main.c \ symrec.c diff --git a/src/arch/x86/expr.c b/src/arch/x86/expr.c new file mode 100644 index 00000000..e6210957 --- /dev/null +++ b/src/arch/x86/expr.c @@ -0,0 +1,191 @@ +/* $Id: expr.c,v 1.1 2001/07/05 06:28:54 mu Exp $ + * Expression handling + * + * Copyright (C) 2001 Michael Urman + * + * 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 + */ +#include +#include +#include "expr.h" +#include "symrec.h" +#include "globals.h" +#include "errwarn.h" + +/* allocate a new expression node, with children as defined. + * If it's a unary operator, put the element on the right */ +expr *expr_new (ExprType ltype, + ExprItem left, + ExprOp op, + ExprType rtype, + ExprItem right) +{ + expr *ptr; + ptr = malloc (sizeof (expr)); + if (ptr == NULL) Fatal (FATAL_NOMEM); + ptr->ltype = ltype; + ptr->op = op; + ptr->rtype = rtype; + switch (ltype) + { + case EXPR_NUM: + case EXPR_SYM: + case EXPR_EXPR: + memcpy (&ptr->left, &left, sizeof (ExprItem)); + break; + case EXPR_NONE: break; + } + switch (rtype) + { + case EXPR_NUM: + case EXPR_SYM: + case EXPR_EXPR: + memcpy (&ptr->right, &right, sizeof (ExprItem)); + break; + case EXPR_NONE: + Fatal (FATAL_UNKNOWN); /* TODO: better error? */ + break; + } + return ptr; +} + +/* get rid of unnecessary branches if possible. report. */ +int expr_simplify (expr *e) +{ + int simplified = 0; + + /* 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 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) + { + 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)); + 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; + /* don't try to free the symrec here. */ + e->left.num = e->left.sym->value; + simplified = 1; + } + } + + /* ditto on the right */ + if (e->rtype == EXPR_EXPR) + { + if (e->right.expr->op != EXPR_IDENT) + simplified |= expr_simplify (e->right.expr); + + while (e->rtype == EXPR_EXPR && e->right.expr->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)); + simplified = 1; + } + } + else if (e->rtype == EXPR_SYM) + { + if (e->right.sym->status & SYM_VALUED) + { + e->rtype = EXPR_NUM; + /* don't try to free the symrec here. */ + e->right.num = e->right.sym->value; + simplified = 1; + } + } + + if ((e->ltype == EXPR_NUM || e->ltype == EXPR_NONE) + && e->rtype == EXPR_NUM + && e->op != EXPR_IDENT) + { + switch (e->op) + { + case EXPR_ADD: e->right.num = e->left.num + e->right.num; break; + case EXPR_SUB: e->right.num = e->left.num - e->right.num; break; + case EXPR_MUL: e->right.num = e->left.num * e->right.num; break; + case EXPR_DIV: e->right.num = e->left.num / e->right.num; break; + case EXPR_MOD: e->right.num = e->left.num % e->right.num; break; + case EXPR_NEG: e->right.num = -(e->right.num); break; + case EXPR_NOT: e->right.num = ~(e->right.num); break; + case EXPR_OR: e->right.num = e->left.num | e->right.num; break; + case EXPR_AND: e->right.num = e->left.num & e->right.num; break; + case EXPR_XOR: e->right.num = e->left.num ^ e->right.num; break; + case EXPR_SHL: e->right.num = e->right.num << e->left.num; break; + case EXPR_SHR: e->right.num = e->right.num << e->left.num; break; + case EXPR_LOR: e->right.num = e->left.num || e->right.num; break; + case EXPR_LAND: e->right.num = e->left.num && e->right.num; break; + case EXPR_LNOT: e->right.num = !e->right.num; break; + case EXPR_EQ: e->right.num = e->right.num == e->left.num; break; + case EXPR_LT: e->right.num = e->right.num < e->left.num; break; + case EXPR_GT: e->right.num = e->right.num > e->left.num; break; + case EXPR_LE: e->right.num = e->right.num <= e->left.num; break; + case EXPR_GE: e->right.num = e->right.num >= e->left.num; break; + case EXPR_NE: e->right.num = e->right.num != e->left.num; break; + case EXPR_IDENT: break; + } + e->op = EXPR_IDENT; + simplified = 1; + } + + /* 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 && e->op == EXPR_ADD) + ||(e->left.num == -1 && e->op == EXPR_AND) + ||(e->left.num == 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 && e->op == EXPR_DIV) + ||(e->right.num == 0 && e->op == EXPR_ADD) + ||(e->right.num == 0 && e->op == EXPR_SUB) + ||(e->right.num == -1 && e->op == EXPR_AND) + ||(e->right.num == 0 && e->op == EXPR_OR) + ||(e->right.num == 0 && e->op == EXPR_SHL) + ||(e->right.num == 0 && e->op == EXPR_SHR))) + { + e->op = EXPR_IDENT; + e->rtype = e->ltype; + memcpy (&e->right, &e->left, sizeof (ExprItem)); + simplified = 1; + } + + return simplified; +} diff --git a/src/arch/x86/x86expr.c b/src/arch/x86/x86expr.c new file mode 100644 index 00000000..f653822a --- /dev/null +++ b/src/arch/x86/x86expr.c @@ -0,0 +1,191 @@ +/* $Id: x86expr.c,v 1.1 2001/07/05 06:28:54 mu Exp $ + * Expression handling + * + * Copyright (C) 2001 Michael Urman + * + * 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 + */ +#include +#include +#include "expr.h" +#include "symrec.h" +#include "globals.h" +#include "errwarn.h" + +/* allocate a new expression node, with children as defined. + * If it's a unary operator, put the element on the right */ +expr *expr_new (ExprType ltype, + ExprItem left, + ExprOp op, + ExprType rtype, + ExprItem right) +{ + expr *ptr; + ptr = malloc (sizeof (expr)); + if (ptr == NULL) Fatal (FATAL_NOMEM); + ptr->ltype = ltype; + ptr->op = op; + ptr->rtype = rtype; + switch (ltype) + { + case EXPR_NUM: + case EXPR_SYM: + case EXPR_EXPR: + memcpy (&ptr->left, &left, sizeof (ExprItem)); + break; + case EXPR_NONE: break; + } + switch (rtype) + { + case EXPR_NUM: + case EXPR_SYM: + case EXPR_EXPR: + memcpy (&ptr->right, &right, sizeof (ExprItem)); + break; + case EXPR_NONE: + Fatal (FATAL_UNKNOWN); /* TODO: better error? */ + break; + } + return ptr; +} + +/* get rid of unnecessary branches if possible. report. */ +int expr_simplify (expr *e) +{ + int simplified = 0; + + /* 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 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) + { + 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)); + 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; + /* don't try to free the symrec here. */ + e->left.num = e->left.sym->value; + simplified = 1; + } + } + + /* ditto on the right */ + if (e->rtype == EXPR_EXPR) + { + if (e->right.expr->op != EXPR_IDENT) + simplified |= expr_simplify (e->right.expr); + + while (e->rtype == EXPR_EXPR && e->right.expr->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)); + simplified = 1; + } + } + else if (e->rtype == EXPR_SYM) + { + if (e->right.sym->status & SYM_VALUED) + { + e->rtype = EXPR_NUM; + /* don't try to free the symrec here. */ + e->right.num = e->right.sym->value; + simplified = 1; + } + } + + if ((e->ltype == EXPR_NUM || e->ltype == EXPR_NONE) + && e->rtype == EXPR_NUM + && e->op != EXPR_IDENT) + { + switch (e->op) + { + case EXPR_ADD: e->right.num = e->left.num + e->right.num; break; + case EXPR_SUB: e->right.num = e->left.num - e->right.num; break; + case EXPR_MUL: e->right.num = e->left.num * e->right.num; break; + case EXPR_DIV: e->right.num = e->left.num / e->right.num; break; + case EXPR_MOD: e->right.num = e->left.num % e->right.num; break; + case EXPR_NEG: e->right.num = -(e->right.num); break; + case EXPR_NOT: e->right.num = ~(e->right.num); break; + case EXPR_OR: e->right.num = e->left.num | e->right.num; break; + case EXPR_AND: e->right.num = e->left.num & e->right.num; break; + case EXPR_XOR: e->right.num = e->left.num ^ e->right.num; break; + case EXPR_SHL: e->right.num = e->right.num << e->left.num; break; + case EXPR_SHR: e->right.num = e->right.num << e->left.num; break; + case EXPR_LOR: e->right.num = e->left.num || e->right.num; break; + case EXPR_LAND: e->right.num = e->left.num && e->right.num; break; + case EXPR_LNOT: e->right.num = !e->right.num; break; + case EXPR_EQ: e->right.num = e->right.num == e->left.num; break; + case EXPR_LT: e->right.num = e->right.num < e->left.num; break; + case EXPR_GT: e->right.num = e->right.num > e->left.num; break; + case EXPR_LE: e->right.num = e->right.num <= e->left.num; break; + case EXPR_GE: e->right.num = e->right.num >= e->left.num; break; + case EXPR_NE: e->right.num = e->right.num != e->left.num; break; + case EXPR_IDENT: break; + } + e->op = EXPR_IDENT; + simplified = 1; + } + + /* 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 && e->op == EXPR_ADD) + ||(e->left.num == -1 && e->op == EXPR_AND) + ||(e->left.num == 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 && e->op == EXPR_DIV) + ||(e->right.num == 0 && e->op == EXPR_ADD) + ||(e->right.num == 0 && e->op == EXPR_SUB) + ||(e->right.num == -1 && e->op == EXPR_AND) + ||(e->right.num == 0 && e->op == EXPR_OR) + ||(e->right.num == 0 && e->op == EXPR_SHL) + ||(e->right.num == 0 && e->op == EXPR_SHR))) + { + e->op = EXPR_IDENT; + e->rtype = e->ltype; + memcpy (&e->right, &e->left, sizeof (ExprItem)); + simplified = 1; + } + + return simplified; +} diff --git a/src/expr.c b/src/expr.c new file mode 100644 index 00000000..e6210957 --- /dev/null +++ b/src/expr.c @@ -0,0 +1,191 @@ +/* $Id: expr.c,v 1.1 2001/07/05 06:28:54 mu Exp $ + * Expression handling + * + * Copyright (C) 2001 Michael Urman + * + * 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 + */ +#include +#include +#include "expr.h" +#include "symrec.h" +#include "globals.h" +#include "errwarn.h" + +/* allocate a new expression node, with children as defined. + * If it's a unary operator, put the element on the right */ +expr *expr_new (ExprType ltype, + ExprItem left, + ExprOp op, + ExprType rtype, + ExprItem right) +{ + expr *ptr; + ptr = malloc (sizeof (expr)); + if (ptr == NULL) Fatal (FATAL_NOMEM); + ptr->ltype = ltype; + ptr->op = op; + ptr->rtype = rtype; + switch (ltype) + { + case EXPR_NUM: + case EXPR_SYM: + case EXPR_EXPR: + memcpy (&ptr->left, &left, sizeof (ExprItem)); + break; + case EXPR_NONE: break; + } + switch (rtype) + { + case EXPR_NUM: + case EXPR_SYM: + case EXPR_EXPR: + memcpy (&ptr->right, &right, sizeof (ExprItem)); + break; + case EXPR_NONE: + Fatal (FATAL_UNKNOWN); /* TODO: better error? */ + break; + } + return ptr; +} + +/* get rid of unnecessary branches if possible. report. */ +int expr_simplify (expr *e) +{ + int simplified = 0; + + /* 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 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) + { + 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)); + 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; + /* don't try to free the symrec here. */ + e->left.num = e->left.sym->value; + simplified = 1; + } + } + + /* ditto on the right */ + if (e->rtype == EXPR_EXPR) + { + if (e->right.expr->op != EXPR_IDENT) + simplified |= expr_simplify (e->right.expr); + + while (e->rtype == EXPR_EXPR && e->right.expr->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)); + simplified = 1; + } + } + else if (e->rtype == EXPR_SYM) + { + if (e->right.sym->status & SYM_VALUED) + { + e->rtype = EXPR_NUM; + /* don't try to free the symrec here. */ + e->right.num = e->right.sym->value; + simplified = 1; + } + } + + if ((e->ltype == EXPR_NUM || e->ltype == EXPR_NONE) + && e->rtype == EXPR_NUM + && e->op != EXPR_IDENT) + { + switch (e->op) + { + case EXPR_ADD: e->right.num = e->left.num + e->right.num; break; + case EXPR_SUB: e->right.num = e->left.num - e->right.num; break; + case EXPR_MUL: e->right.num = e->left.num * e->right.num; break; + case EXPR_DIV: e->right.num = e->left.num / e->right.num; break; + case EXPR_MOD: e->right.num = e->left.num % e->right.num; break; + case EXPR_NEG: e->right.num = -(e->right.num); break; + case EXPR_NOT: e->right.num = ~(e->right.num); break; + case EXPR_OR: e->right.num = e->left.num | e->right.num; break; + case EXPR_AND: e->right.num = e->left.num & e->right.num; break; + case EXPR_XOR: e->right.num = e->left.num ^ e->right.num; break; + case EXPR_SHL: e->right.num = e->right.num << e->left.num; break; + case EXPR_SHR: e->right.num = e->right.num << e->left.num; break; + case EXPR_LOR: e->right.num = e->left.num || e->right.num; break; + case EXPR_LAND: e->right.num = e->left.num && e->right.num; break; + case EXPR_LNOT: e->right.num = !e->right.num; break; + case EXPR_EQ: e->right.num = e->right.num == e->left.num; break; + case EXPR_LT: e->right.num = e->right.num < e->left.num; break; + case EXPR_GT: e->right.num = e->right.num > e->left.num; break; + case EXPR_LE: e->right.num = e->right.num <= e->left.num; break; + case EXPR_GE: e->right.num = e->right.num >= e->left.num; break; + case EXPR_NE: e->right.num = e->right.num != e->left.num; break; + case EXPR_IDENT: break; + } + e->op = EXPR_IDENT; + simplified = 1; + } + + /* 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 && e->op == EXPR_ADD) + ||(e->left.num == -1 && e->op == EXPR_AND) + ||(e->left.num == 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 && e->op == EXPR_DIV) + ||(e->right.num == 0 && e->op == EXPR_ADD) + ||(e->right.num == 0 && e->op == EXPR_SUB) + ||(e->right.num == -1 && e->op == EXPR_AND) + ||(e->right.num == 0 && e->op == EXPR_OR) + ||(e->right.num == 0 && e->op == EXPR_SHL) + ||(e->right.num == 0 && e->op == EXPR_SHR))) + { + e->op = EXPR_IDENT; + e->rtype = e->ltype; + memcpy (&e->right, &e->left, sizeof (ExprItem)); + simplified = 1; + } + + return simplified; +} diff --git a/src/expr.h b/src/expr.h new file mode 100644 index 00000000..18d6eee1 --- /dev/null +++ b/src/expr.h @@ -0,0 +1,72 @@ +/* $Id: expr.h,v 1.1 2001/07/05 06:28:54 mu Exp $ + * Expression handling header file + * + * Copyright (C) 2001 Michael Urman + * + * 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 _EXPR_H_ +#define _EXPR_H_ + +typedef enum { + EXPR_ADD, + EXPR_SUB, + EXPR_MUL, + EXPR_DIV, + EXPR_MOD, + EXPR_NEG, + EXPR_NOT, + EXPR_OR, + EXPR_AND, + EXPR_XOR, + EXPR_SHL, + EXPR_SHR, + EXPR_LOR, + EXPR_LAND, + EXPR_LNOT, + EXPR_LT, + EXPR_GT, + EXPR_EQ, + EXPR_LE, + EXPR_GE, + EXPR_NE, + EXPR_IDENT /* if right is IDENT, then the entire expr is just a num */ +} ExprOp; + +typedef enum { + EXPR_NONE, /* for left side of a NOT, NEG, etc. */ + EXPR_NUM, + EXPR_EXPR, + EXPR_SYM +} ExprType; + +typedef union expritem_u { + struct symrec_s *sym; + struct expr_s *expr; + int num; +} ExprItem; + +typedef struct expr_s { + ExprType ltype, rtype; + ExprItem left, right; + ExprOp op; +} expr; + +expr *expr_new (ExprType, ExprItem, ExprOp, ExprType, ExprItem); +int expr_simplify (expr *); + +#endif