dcc/src/ast.cpp

907 lines
25 KiB
C++

/*
* File: ast.c
* Purpose: Support module for abstract syntax trees.
* Date: September 1993
* (C) Cristina Cifuentes
*/
#include "ast.h"
#include "msvc_fixes.h"
#include "types.h"
#include "bundle.h"
#include "machine_x86.h"
#include "project.h"
#include <QtCore/QTextStream>
#include <boost/range.hpp>
#include <boost/range/adaptor/filtered.hpp>
#include <boost/range/algorithm.hpp>
#include <boost/assign.hpp>
#include <stdint.h>
#include <string>
#include <sstream>
#include <iostream>
#include <cassert>
using namespace std;
using namespace boost;
using namespace boost::adaptors;
extern int strSize (const uint8_t *, char);
extern char *cChar(uint8_t c);
// Conditional operator symbols in C. Index by condOp enumeration type
static const char * const condOpSym[] = { " <= ", " < ", " == ", " != ", " > ", " >= ",
" & ", " | ", " ^ ", " ~ ",
" + ", " - ", " * ", " / ",
" >> ", " << ", " % ", " && ", " || " };
/* Local expression stack */
//typedef struct _EXP_STK {
// COND_EXPR *exp;
// struct _EXP_STK *next;
//} EXP_STK; - for local expression stack
/* Returns the integer i in C hexadecimal format */
static const char *hexStr (uint16_t i)
{
static char buf[10];
sprintf (buf, "%s%x", (i > 9) ? "0x" : "", i);
return (buf);
}
/* Sets the du record for registers according to the du flag */
void ICODE::setRegDU (eReg regi, operDu du_in)
{
// printf("%s %d %x\n",__FUNCTION__,regi,int(du_in));
if(regi==rSP)
{
printf("Discarding SP def&use info for now\n");
return;
}
switch (du_in)
{
case eDEF:
du.def.addReg(regi);
du1.addDef(regi);
break;
case eUSE:
du.use.addReg(regi);
break;
case USE_DEF:
du.addDefinedAndUsed(regi);
du1.addDef(regi);
break;
case NONE: /* do nothing */
break;
}
}
/* Copies the def, use, or def and use fields of duIcode into pIcode */
void ICODE::copyDU(const ICODE &duIcode, operDu _du, operDu duDu)
{
switch (_du)
{
case eDEF:
if (duDu == eDEF)
du.def=duIcode.du.def;
else
du.def=duIcode.du.use;
break;
case eUSE:
if (duDu == eDEF)
du.use = duIcode.du.def;
else
du.use = duIcode.du.use;
break;
case USE_DEF:
du = duIcode.du;
break;
case NONE:
assert(false);
break;
}
}
/* Creates a conditional boolean expression and returns it */
//COND_EXPR *COND_EXPR::boolOp(COND_EXPR *_lhs, COND_EXPR *_rhs, condOp _op)
//{
// return BinaryOperator::Create(_op,_lhs,_rhs);
//}
/* Returns a unary conditional expression node. This procedure should
* only be used with the following conditional node types: NEGATION,
* ADDRESSOF, DEREFERENCE, POST_INC, POST_DEC, PRE_INC, PRE_DEC */
/* Returns an identifier conditional expression node of type GLOB_VAR */
GlobalVariable::GlobalVariable(int16_t segValue, int16_t off)
{
uint32_t adr;
valid = true;
ident.idType = GLOB_VAR;
adr = opAdr(segValue, off);
auto i=Project::get()->getSymIdxByAdd(adr);
if ( not Project::get()->validSymIdx(i) )
{
printf ("Error, glob var not found in symtab\n");
valid = false;
}
globIdx = i;
}
QString GlobalVariable::walkCondExpr(Function *, int *) const
{
if(valid)
return Project::get()->symtab[globIdx].name;
return "INVALID GlobalVariable";
}
/* Returns an identifier conditional expression node of type LOCAL_VAR */
AstIdent *AstIdent::Loc(int off, LOCAL_ID *localId)
{
size_t i;
AstIdent *newExp = new AstIdent();
newExp->ident.idType = LOCAL_VAR;
for (i = 0; i < localId->csym(); i++)
{
const ID &lID(localId->id_arr[i]);
if ((lID.id.bwId.off == off) and (lID.id.bwId.regOff == 0))
break;
}
if (i == localId->csym())
printf ("Error, cannot find local var\n");
newExp->ident.idNode.localIdx = i;
localId->id_arr[i].setLocalName(i);
return (newExp);
}
/* Returns an identifier conditional expression node of type PARAM */
AstIdent *AstIdent::Param(int off, const STKFRAME * argSymtab)
{
AstIdent *newExp;
newExp = new AstIdent();
newExp->ident.idType = PARAM;
auto iter=argSymtab->findByLabel(off);
if (iter == argSymtab->end())
printf ("Error, cannot find argument var\n");
newExp->ident.idNode.localIdx = distance(argSymtab->begin(),iter);
return (newExp);
}
/* Returns an identifier conditional expression node of type GLOB_VAR_IDX.
* This global variable is indexed by regi. */
GlobalVariableIdx::GlobalVariableIdx (int16_t segValue, int16_t off, uint8_t regi, const LOCAL_ID *locSym)
{
size_t i;
ident.type(GLOB_VAR_IDX);
for (i = 0; i < locSym->csym(); i++)
{
const BWGLB_TYPE &lID(locSym->id_arr[i].id.bwGlb);
if ((lID.seg == segValue) and (lID.off == off) and (lID.regi == regi))
break;
}
if (i == locSym->csym())
printf ("Error, indexed-glob var not found in local id table\n");
idxGlbIdx = i;
}
QString GlobalVariableIdx::walkCondExpr(Function *pProc, int *) const
{
auto bwGlb = &pProc->localId.id_arr[idxGlbIdx].id.bwGlb;
return QString("%1[%2]").arg((bwGlb->seg << 4) + bwGlb->off).arg(Machine_X86::regName(bwGlb->regi));
}
/* Returns an identifier conditional expression node of type LONG_VAR,
* that points to the given index idx. */
AstIdent *AstIdent::LongIdx (int idx)
{
AstIdent *newExp = new AstIdent;
newExp->ident.idType = LONG_VAR;
newExp->ident.idNode.longIdx = idx;
return (newExp);
}
AstIdent *AstIdent::String(uint32_t idx)
{
AstIdent *newExp = new AstIdent;
newExp->ident.idNode.strIdx = idx;
newExp->ident.type(STRING);
return newExp;
}
/* Returns an identifier conditional expression node of type LONG_VAR */
AstIdent *AstIdent::Long(LOCAL_ID *localId, opLoc sd, iICODE pIcode, hlFirst f, iICODE ix, operDu du, LLInst &atOffset)
{
AstIdent *newExp;
/* Check for long constant and save it as a constant expression */
if ((sd == SRC) and pIcode->ll()->srcIsImmed()) /* constant */
{
int value;
if (f == HIGH_FIRST)
value = (pIcode->ll()->src().getImm2() << 16) + atOffset.src().getImm2();
else/* LOW_FIRST */
value = (atOffset.src().getImm2() << 16)+ pIcode->ll()->src().getImm2();
newExp = new Constant(value,4);
}
/* Save it as a long expression (reg, stack or glob) */
else
{
newExp = new AstIdent();
newExp->ident.idType = LONG_VAR;
newExp->ident.idNode.longIdx = localId->newLong(sd, pIcode, f, ix, du, atOffset);
}
return (newExp);
}
/* Returns an identifier conditional expression node of type OTHER.
* Temporary solution, should really be encoded as an indexed type (eg.
* arrays). */
AstIdent *AstIdent::Other(eReg seg, eReg regi, int16_t off)
{
AstIdent *newExp = new AstIdent();
newExp->ident.idType = OTHER;
newExp->ident.idNode.other.seg = seg;
newExp->ident.idNode.other.regi = regi;
newExp->ident.idNode.other.off = off;
return (newExp);
}
/* Returns an identifier conditional expression node of type TYPE_LONG or
* TYPE_WORD_SIGN */
AstIdent *AstIdent::idID (const ID *retVal, LOCAL_ID *locsym, iICODE ix_)
{
int idx;
AstIdent *newExp=nullptr;
switch(retVal->type)
{
case TYPE_LONG_SIGN:
{
newExp = new AstIdent();
idx = locsym->newLongReg (TYPE_LONG_SIGN, retVal->longId(), ix_);
newExp->ident.idType = LONG_VAR;
newExp->ident.idNode.longIdx = idx;
break;
}
case TYPE_WORD_SIGN:
newExp = new RegisterNode(locsym->newByteWordReg(retVal->type, retVal->id.regi),WORD_REG,locsym);
break;
case TYPE_BYTE_SIGN:
newExp = new RegisterNode(locsym->newByteWordReg(retVal->type, retVal->id.regi),BYTE_REG,locsym);
break;
default:
fprintf(stderr,"AstIdent::idID unhandled type %d\n",retVal->type);
}
return (newExp);
}
/* Returns an identifier conditional expression node, according to the given
* type.
* Arguments:
* duIcode: icode instruction that needs the du set.
* du: operand is defined or used in current instruction. */
Expr *AstIdent::id(const LLInst &ll_insn, opLoc sd, Function * pProc, iICODE ix_,ICODE &duIcode, operDu du)
{
Expr *newExp;
int idx; /* idx into pIcode->localId table */
const LLOperand &pm(*ll_insn.get(sd));
if ( ((sd == DST) and ll_insn.testFlags(IM_DST)) or
((sd == SRC) and ll_insn.testFlags(IM_SRC)) or
(sd == LHS_OP)) /* for MUL lhs */
{ /* implicit dx:ax */
idx = pProc->localId.newLongReg (TYPE_LONG_SIGN, LONGID_TYPE(rDX, rAX), ix_);
newExp = AstIdent::LongIdx (idx);
duIcode.setRegDU (rDX, du);
duIcode.setRegDU (rAX, du);
}
else if ((sd == DST) and ll_insn.testFlags(IM_TMP_DST))
{ /* implicit tmp */
newExp = new RegisterNode(LLOperand(rTMP,2), &pProc->localId);
duIcode.setRegDU(rTMP, (operDu)eUSE);
}
else if ((sd == SRC) and ll_insn.srcIsImmed()) /* constant */
newExp = new Constant(ll_insn.src().getImm2(), 2);
else if (pm.regi == rUNDEF) /* global variable */
newExp = new GlobalVariable(pm.segValue, pm.off);
else if ( pm.isReg() ) /* register */
{
//(sd == SRC) ? ll_insn.getFlag() : ll_insn.getFlag() & NO_SRC_B
newExp = new RegisterNode(pm, &pProc->localId);
duIcode.setRegDU( pm.regi, du);
}
else if (pm.off) /* offset */
{ // TODO: this is ABI specific, should be actually based on Function calling conv
if ((pm.seg == rSS) and (pm.regi == INDEX_BP)) /* idx on bp */
{
if (pm.off >= 0) /* argument */
newExp = AstIdent::Param (pm.off, &pProc->args);
else /* local variable */
newExp = AstIdent::Loc (pm.off, &pProc->localId);
}
else if ((pm.seg == rDS) and (pm.regi == INDEX_BX)) /* bx */
{
if (pm.off > 0) /* global variable */
newExp = new GlobalVariableIdx(pm.segValue, pm.off, rBX,&pProc->localId);
else
newExp = AstIdent::Other (pm.seg, pm.regi, pm.off);
duIcode.setRegDU( rBX, eUSE);
}
else /* idx <> bp, bx */
newExp = AstIdent::Other (pm.seg, pm.regi, pm.off);
/**** check long ops, indexed global var *****/
}
else /* (pm->regi >= INDEXBASE and pm->off = 0) => indexed and no off */
{
if ((pm.seg == rDS) and (pm.regi > INDEX_BP_DI)) /* dereference */
{
eReg selected;
switch (pm.regi) {
case INDEX_SI: selected = rSI; break;
case INDEX_DI: selected = rDI; break;
case INDEX_BP: selected = rBP; break;
case INDEX_BX: selected = rBX; break;
default:
newExp = nullptr;
assert(false);
}
//NOTICE: was selected, 0
newExp = new RegisterNode(LLOperand(selected, 0), &pProc->localId);
duIcode.setRegDU( selected, du);
newExp = UnaryOperator::Create(DEREFERENCE, newExp);
}
else
newExp = AstIdent::Other (pm.seg, pm.regi, 0);
}
return (newExp);
}
/* Returns the identifier type */
condId LLInst::idType(opLoc sd) const
{
const LLOperand &pm((sd == SRC) ? src() : m_dst);
if ((sd == SRC) and srcIsImmed())
return (CONSTANT);
else if (pm.regi == 0)
return (GLOB_VAR);
else if ( pm.isReg() )
return (REGISTER);
else if ((pm.seg == rSS) and (pm.regi == INDEX_BP))
{
//TODO: which pm.seg/pm.regi pairs should produce PARAM/LOCAL_VAR ?
if (pm.off >= 0)
return (PARAM);
else
return (LOCAL_VAR);
}
else
return (OTHER);
}
/* Size of hl types */
int hlSize[] = {2, 1, 1, 2, 2, 4, 4, 4, 2, 2, 1, 4, 4};
int Expr::hlTypeSize(Function * pproc) const
{
if (this == nullptr)
return (2); /* for TYPE_UNKNOWN */
fprintf(stderr,"hlTypeSize queried for Unkown type %d \n",m_type);
return 2; // CC: is this correct?
}
/* Returns the type of the expression */
int BinaryOperator::hlTypeSize(Function * pproc) const
{
return std::max(lhs()->hlTypeSize (pproc),rhs()->hlTypeSize (pproc));
}
int UnaryOperator::hlTypeSize(Function *pproc) const
{
return (unaryExp->hlTypeSize (pproc));
}
int GlobalVariable::hlTypeSize(Function *pproc) const
{
return (Project::get()->symbolSize(globIdx));
}
int GlobalVariableIdx::hlTypeSize(Function *pproc) const
{
return (hlSize[pproc->localId.id_arr[idxGlbIdx].type]);
}
int AstIdent::hlTypeSize(Function *pproc) const
{
switch (ident.idType)
{
case GLOB_VAR:
assert(false);
return 1;
case LOCAL_VAR:
return (hlSize[pproc->localId.id_arr[ident.idNode.localIdx].type]);
case PARAM:
return (hlSize[pproc->args[ident.idNode.paramIdx].type]);
case STRING:
return (2);
case LONG_VAR:
return (4);
case OTHER:
return (2);
default:
assert(false);
return -1;
} /* eos */
}
hlType BinaryOperator::expType(Function *pproc) const
{
hlType first = lhs()->expType ( pproc );
hlType second = rhs()->expType ( pproc );
if (first != second)
{
if (lhs()->hlTypeSize(pproc) > rhs()->hlTypeSize (pproc))
return (first);
else
return (second);
}
else
return (first);
}
hlType UnaryOperator::expType(Function *pproc) const
{
return unaryExp->expType (pproc);
}
hlType GlobalVariable::expType(Function *pproc) const
{
return Project::get()->symbolType(globIdx);
}
hlType GlobalVariableIdx::expType(Function *pproc) const
{
return (pproc->localId.id_arr[idxGlbIdx].type);
}
hlType AstIdent::expType(Function *pproc) const
{
switch (ident.idType)
{
case UNDEF:
case CONSTANT:
case FUNCTION:
case REGISTER:
case GLOB_VAR:
case GLOB_VAR_IDX:
assert(false);
return TYPE_UNKNOWN;
case LOCAL_VAR:
return (pproc->localId.id_arr[ident.idNode.localIdx].type);
case PARAM:
return (pproc->args[ident.idNode.paramIdx].type);
case STRING:
return (TYPE_STR);
case LONG_VAR:
return (pproc->localId.id_arr[ident.idNode.longIdx].type);
default:
return (TYPE_UNKNOWN);
} /* eos */
return (TYPE_UNKNOWN);
}
/* Returns the type of the expression */
/* Removes the register from the tree. If the register was part of a long
* register (eg. dx:ax), the node gets transformed into an integer register
* node. */
Expr * HlTypeSupport::performLongRemoval (eReg regi, LOCAL_ID *locId, Expr *tree)
{
switch (tree->m_type) {
case BOOLEAN_OP:
case POST_INC: case POST_DEC:
case PRE_INC: case PRE_DEC:
case NEGATION: case ADDRESSOF:
case DEREFERENCE:
case IDENTIFIER:
return tree->performLongRemoval(regi,locId);
break;
default:
fprintf(stderr,"performLongRemoval attemped on %d\n",tree->m_type);
break;
}
return tree;
}
/* Returns the string located in image, formatted in C format. */
static QString getString (int offset)
{
PROG &prog(Project::get()->prog);
QString o;
int strLen, i;
strLen = strSize (&prog.image()[offset], '\0');
o += '"';
for (i = 0; i < strLen; i++)
o += cChar(prog.image()[offset+i]);
o += "\"\0";
return o;
}
QString BinaryOperator::walkCondExpr(Function * pProc, int* numLoc) const
{
assert(rhs());
return QString("(%1%2%3)")
.arg((m_op!=NOT) ? lhs()->walkCondExpr(pProc, numLoc) : "")
.arg(condOpSym[m_op])
.arg(rhs()->walkCondExpr(pProc, numLoc));
}
QString AstIdent::walkCondExpr(Function *pProc, int *numLoc) const
{
int16_t off; /* temporal - for OTHER */
ID* id; /* Pointer to local identifier table */
BWGLB_TYPE* bwGlb; /* Ptr to BWGLB_TYPE (global indexed var) */
STKSYM * psym; /* Pointer to argument in the stack */
QString codeContents;
QString collectedContents;
QTextStream codeOut(&codeContents);
QTextStream o(&collectedContents);
switch (ident.idType)
{
case LOCAL_VAR:
o << pProc->localId.id_arr[ident.idNode.localIdx].name;
break;
case PARAM:
psym = &pProc->args[ident.idNode.paramIdx];
if (psym->hasMacro)
o << psym->macro<<"("<<psym->name<< ")";
else
o << psym->name;
break;
case STRING:
o << getString (ident.idNode.strIdx);
break;
case LONG_VAR:
id = &pProc->localId.id_arr[ident.idNode.longIdx];
if (id->name[0] != '\0') /* STK_FRAME & REG w/name*/
o << id->name;
else if (id->loc == REG_FRAME)
{
id->setLocalName(++(*numLoc));
codeOut <<TypeContainer::typeName(id->type)<< " "<<id->name<<"; ";
codeOut <<"/* "<<Machine_X86::regName(id->longId().h()) << ":" <<
Machine_X86::regName(id->longId().l()) << " */\n";
o << id->name;
pProc->localId.propLongId (id->longId().l(),id->longId().h(), id->name);
}
else /* GLB_FRAME */
{
if (id->id.longGlb.regi == 0) /* not indexed */
o << "[" << (id->id.longGlb.seg<<4) + id->id.longGlb.offH <<"]";
else if (id->id.longGlb.regi == rBX)
o << "[" << (id->id.longGlb.seg<<4) + id->id.longGlb.offH <<"][bx]";
}
break;
case OTHER:
off = ident.idNode.other.off;
o << Machine_X86::regName(ident.idNode.other.seg)<< "[";
o << Machine_X86::regName(ident.idNode.other.regi);
if (off < 0)
o << "-"<< hexStr (-off);
else if (off>0)
o << "+"<< hexStr (off);
o << "]";
break;
default:
assert(false);
return "";
} /* eos */
cCode.appendDecl(codeContents);
return collectedContents;
}
QString UnaryOperator::wrapUnary(Function *pProc, int *numLoc,QChar op) const
{
QString outStr = op;
QString inner = unaryExp->walkCondExpr (pProc, numLoc);
if (unaryExp->m_type == IDENTIFIER)
outStr += inner;
else
outStr += "("+inner+')';
return outStr;
}
QString UnaryOperator::walkCondExpr(Function *pProc, int *numLoc) const
{
QString outStr;
switch(m_type)
{
case NEGATION:
outStr+=wrapUnary(pProc,numLoc,'!');
break;
case ADDRESSOF:
outStr+=wrapUnary(pProc,numLoc,'&');
break;
case DEREFERENCE:
outStr+=wrapUnary(pProc,numLoc,'*');
break;
case POST_INC:
outStr += unaryExp->walkCondExpr (pProc, numLoc) + "++";
break;
case POST_DEC:
outStr += unaryExp->walkCondExpr (pProc, numLoc) + "--";
break;
case PRE_INC:
outStr += "++" + unaryExp->walkCondExpr (pProc, numLoc);
break;
case PRE_DEC:
outStr += "--" + unaryExp->walkCondExpr (pProc, numLoc);
break;
}
return outStr;
}
/* Walks the conditional expression tree and returns the result on a string */
/* Changes the boolean conditional operator at the root of this expression */
void BinaryOperator::changeBoolOp (condOp newOp)
{
m_op = newOp;
}
bool Expr::insertSubTreeReg (AstIdent *&tree, Expr *_expr, eReg regi,const LOCAL_ID *locsym)
{
Expr *nd = tree;
bool res=insertSubTreeReg (nd, _expr, regi,locsym);
if(res)
{
tree= dynamic_cast<AstIdent *>(nd);
return true;
assert(tree);
}
return false;
}
/* Inserts the expression exp into the tree at the location specified by the
* register regi */
bool Expr::insertSubTreeReg (Expr *&tree, Expr *_expr, eReg regi,const LOCAL_ID *locsym)
{
if (tree == nullptr)
return false;
Expr *temp=tree->insertSubTreeReg(_expr,regi,locsym);
if(nullptr!=temp)
{
tree=temp;
return true;
}
return false;
}
Expr *UnaryOperator::insertSubTreeReg(Expr *_expr, eReg regi, const LOCAL_ID *locsym)
{
Expr *temp;
switch (m_type) {
case NEGATION:
case ADDRESSOF:
case DEREFERENCE:
temp = unaryExp->insertSubTreeReg( _expr, regi, locsym);
if (nullptr!=temp)
{
unaryExp = temp;
return this;
}
return nullptr;
default:
fprintf(stderr,"insertSubTreeReg attempt on unhandled type %d\n",m_type);
}
return nullptr;
}
Expr *BinaryOperator::insertSubTreeReg(Expr *_expr, eReg regi, const LOCAL_ID *locsym)
{
Expr *r;
if(this->op()!=NOT)
{
assert(m_lhs);
r=m_lhs->insertSubTreeReg(_expr,regi,locsym);
if(r)
{
m_lhs = r;
return this;
}
}
assert(m_rhs);
r=m_rhs->insertSubTreeReg(_expr,regi,locsym);
if(r)
{
m_rhs = r;
return this;
}
return nullptr;
}
Expr *AstIdent::insertSubTreeReg(Expr *_expr, eReg regi, const LOCAL_ID *locsym)
{
if (ident.idType == REGISTER)
{
assert(false);
}
return nullptr;
}
/* Inserts the expression exp into the tree at the location specified by the
* long register index longIdx*/
bool Expr::insertSubTreeLongReg(Expr *_expr, Expr *&tree, int longIdx)
{
if (tree == nullptr)
return false;
Expr *temp=tree->insertSubTreeLongReg(_expr,longIdx);
if(nullptr!=temp)
{
tree=temp;
return true;
}
return false;
}
Expr *UnaryOperator::insertSubTreeLongReg(Expr *_expr, int longIdx)
{
Expr *temp = unaryExp->insertSubTreeLongReg(_expr,longIdx);
if (nullptr!=temp)
{
unaryExp = temp;
return this;
}
return nullptr;
}
Expr *BinaryOperator::insertSubTreeLongReg(Expr *_expr, int longIdx)
{
Expr *r;
if(m_op!=NOT)
{
r=m_lhs->insertSubTreeLongReg(_expr,longIdx);
if(r)
{
m_lhs = r;
return this;
}
}
r=m_rhs->insertSubTreeLongReg(_expr,longIdx);
if(r)
{
m_rhs = r;
return this;
}
return nullptr;
}
Expr *AstIdent::insertSubTreeLongReg(Expr *_expr, int longIdx)
{
if (ident.idNode.longIdx == longIdx)
{
return _expr;
}
return nullptr;
}
/* Makes a copy of the given expression. Allocates newExp storage for each
* node. Returns the copy. */
Expr *BinaryOperator::clone() const
{
/* Expression node copy */
return new BinaryOperator(m_op,m_lhs->clone(),m_rhs->clone());
}
Expr *BinaryOperator::inverse() const
{
static condOp invCondOp[] = {GREATER, GREATER_EQUAL, NOT_EQUAL, EQUAL,
LESS_EQUAL, LESS, DUMMY,DUMMY,DUMMY,DUMMY,
DUMMY, DUMMY, DUMMY, DUMMY, DUMMY, DUMMY,
DUMMY, DBL_OR, DBL_AND};
BinaryOperator *res=reinterpret_cast<BinaryOperator *>(this->clone());
switch (m_op)
{
case LESS_EQUAL: case LESS: case EQUAL:
case NOT_EQUAL: case GREATER: case GREATER_EQUAL:
res->m_op = invCondOp[m_op];
return res;
case AND: case OR: case XOR: case NOT: case ADD:
case SUB: case MUL: case DIV: case SHR: case SHL: case MOD:
return UnaryOperator::Create(NEGATION, res);
case DBL_AND: case DBL_OR:
res->m_op = invCondOp[m_op];
res->m_lhs=m_lhs->inverse ();
res->m_rhs=m_rhs->inverse ();
return res;
default:
fprintf(stderr,"BinaryOperator::inverse attempt on unhandled op %d\n",m_op);
} /* eos */
assert(false);
return res;
}
Expr *AstIdent::performLongRemoval(eReg regi, LOCAL_ID *locId)
{
eReg otherRegi; /* high or low part of long register */
if (ident.idType == LONG_VAR)
{
otherRegi = otherLongRegi (regi, ident.idNode.longIdx, locId);
delete this;
return new RegisterNode(locId->newByteWordReg(TYPE_WORD_SIGN,otherRegi),WORD_REG,locId);
}
return this;
}
eReg AstIdent::otherLongRegi (eReg regi, int idx, LOCAL_ID *locTbl)
{
ID *id = &locTbl->id_arr[idx];
if ((id->loc == REG_FRAME) and ((id->type == TYPE_LONG_SIGN) or
(id->type == TYPE_LONG_UNSIGN)))
{
if (id->longId().h() == regi)
return (id->longId().l());
else if (id->longId().l() == regi)
return (id->longId().h());
}
return rUNDEF; // Cristina: please check this!
}
QString Constant::walkCondExpr(Function *, int *) const
{
if (kte.kte < 1000)
return QString::number(kte.kte);
else
return "0x" + QString::number(kte.kte,16);
}
int Constant::hlTypeSize(Function *) const
{
return kte.size;
}
hlType Constant::expType(Function *pproc) const
{
return TYPE_CONST;
}
QString FuncNode::walkCondExpr(Function *pProc, int *numLoc) const
{
return pProc->writeCall(call.proc,*call.args, numLoc);
}
int FuncNode::hlTypeSize(Function *) const
{
return hlSize[call.proc->getReturnType()];
}
hlType FuncNode::expType(Function *) const
{
return call.proc->getReturnType();
}