mirror of https://github.com/yasm/yasm.git
parent
ce22ed6337
commit
fb3e968a29
11 changed files with 1364 additions and 0 deletions
@ -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; |
||||
} |
@ -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…
Reference in new issue