Initial checkin of expression handling.

svn path=/trunk/yasm/; revision=106
0.3
Michael Urman 24 years ago
parent ce22ed6337
commit fb3e968a29
  1. 1
      include/Makefile.am
  2. 72
      include/expr.h
  3. 191
      libyasm/expr.c
  4. 72
      libyasm/expr.h
  5. 191
      modules/arch/x86/expr.c
  6. 191
      modules/arch/x86/x86expr.c
  7. 1
      src/Makefile.am
  8. 191
      src/arch/x86/expr.c
  9. 191
      src/arch/x86/x86expr.c
  10. 191
      src/expr.c
  11. 72
      src/expr.h

@ -1,6 +1,7 @@
EXTRA_DIST = \
bytecode.h \
errwarn.h \
expr.h \
globals.h \
section.h \
symrec.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

@ -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 <stdlib.h>
#include <string.h>
#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;
}

@ -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

@ -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 <stdlib.h>
#include <string.h>
#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;
}

@ -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 <stdlib.h>
#include <string.h>
#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;
}

@ -5,6 +5,7 @@ yasm_SOURCES = \
token.l \
bytecode.c \
errwarn.c \
expr.c \
main.c \
symrec.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 <stdlib.h>
#include <string.h>
#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;
}

@ -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 <stdlib.h>
#include <string.h>
#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;
}

@ -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 <stdlib.h>
#include <string.h>
#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;
}

@ -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
Loading…
Cancel
Save