📄 analyze.c
字号:
/*
Copyright 1994-2003 Free Software Foundation, Inc.
This program 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.
This program 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.
This program is derived from the cc68k complier by
Matthew Brandt (mattb@walkingdog.net)
You may contact the author of this derivative at:
mailto::camille@bluegrass.net
or by snail mail at:
David Lindauer
850 Washburn Ave Apt 99
Louisville, KY 40222
*/
#include <stdio.h>
#include <string.h>
#include "lists.h"
#include "expr.h"
#include "c.h"
#include "ccerr.h"
#include "diag.h"
extern SYM *currentfunc;
extern int prm_xcept;
extern TRYBLOCK *try_block_list;
extern int cf_freeaddress, cf_freedata, cf_freefloat;
extern long framedepth, stackdepth;
extern LIST *varlisthead;
extern int lc_maxauto;
extern int stackadd, stackmod;
extern int anyusedfloat;
extern int stdaddrsize;
int funcfloat;
int floatregs = 1, dataregs = 1, addrregs = 1;
CSE *olist; /* list of optimizable expressions */
/*
* this module will step through the parse tree and find all
* optimizable expressions. at present these expressions are
* limited to expressions that are valid throughout the scope
* of the function. the list of optimizable expressions is:
*
* constants
* global and static addresses
* auto addresses
* contents of auto addresses.
*
* contents of auto addresses are valid only if the address is
* never referred to without dereferencing.
*
* scan will build a list of optimizable expressions which
* opt1 will replace during the second optimization pass.
*/
int equalnode(ENODE *node1, ENODE *node2)
/*
* equalnode will return 1 if the expressions pointed to by
* node1 and node2 are equivalent.
*/
{
if (node1 == 0 || node2 == 0)
return 0;
if (node1->nodetype != node2->nodetype)
{
if (lvalue(node1) && lvalue(node2))
{
return equalnode(node1->v.p[0], node2->v.p[0]);
}
return 0;
}
if (natural_size(node1) != natural_size(node2))
return 0;
switch (node1->nodetype)
{
default:
return (lvalue(node1) && equalnode(node1->v.p[0], node2->v.p[0]));
return 1;
case en_autoreg:
case en_autocon:
case en_nacon:
case en_napccon:
return node1->v.sp->mainsym == node2->v.sp->mainsym;
case en_labcon:
case en_nalabcon:
case en_absacon:
case en_icon:
case en_lcon:
case en_lucon:
case en_iucon:
case en_boolcon:
case en_ccon:
case en_cucon:
case en_llcon:
case en_llucon:
return node1->v.i == node2->v.i;
case en_rcon:
case en_fcon:
case en_lrcon:
case en_rimaginarycon:
case en_fimaginarycon:
case en_lrimaginarycon:
return node1->v.f == node2->v.f;
case en_rcomplexcon:
case en_fcomplexcon:
case en_lrcomplexcon:
return node1->v.c.r == node2->v.c.r && node1->v.c.i == node2->v.c.i;
}
}
//-------------------------------------------------------------------------
CSE *searchnode(ENODE *node)
/*
* searchnode will search the common expression table for an entry
* that matches the node passed and return a pointer to it.
*/
{
CSE *csp;
csp = olist;
while (csp != 0)
{
if (equalnode(node, csp->exp))
return csp;
csp = csp->next;
}
return 0;
}
//-------------------------------------------------------------------------
CSE *enternode(ENODE *node, int duse, int size)
/*
* enternode will enter a reference to an expression node into the
* common expression table. duse is a flag indicating whether or not
* this reference will be dereferenced.
*/
{
CSE *csp;
if (size == 0)
size = natural_size(node);
if ((csp = searchnode(node)) == 0)
{
/* add to tree */
csp = xalloc(sizeof(CSE));
csp->next = olist;
csp->uses = 1;
csp->reg = - 1;
csp->duses = (duse != 0);
csp->exp = copynode(node);
csp->voidf = 0;
csp->size = size;
olist = csp;
return csp;
}
else
if (chksize(csp->size, size))
csp->size = size;
++(csp->uses);
if (duse)
++(csp->duses);
return csp;
}
//-------------------------------------------------------------------------
CSE *voidauto(ENODE *node)
/*
* voidauto will void an auto dereference node which points to
* the same auto constant as node.
*/
{
CSE *csp;
csp = olist;
while (csp != 0)
{
if (lvalue(csp->exp) && equalnode(node, csp->exp->v.p[0]))
{
if (csp->voidf)
return 0;
csp->voidf = 1;
return csp;
}
csp = csp->next;
}
return 0;
}
//-------------------------------------------------------------------------
CSE *voidlref(ENODE *node)
/*
* voidlref will void an lref
*/
{
CSE *csp;
csp = olist;
while (csp != 0)
{
if (equalnode(node, csp->exp))
{
if (csp->voidf)
return 0;
csp->voidf = 1;
return csp;
}
csp = csp->next;
}
return 0;
}
//-------------------------------------------------------------------------
void voidall(void)
/*
* Go through the CSP list voiding any use of a variable that
* has its address taken or is volatile
*/
{
CSE *csp;
csp = olist;
while (csp)
{
if (lvalue(csp->exp) && (csp->exp->v.p[0]->nodetype == en_autocon ||
csp->exp->v.p[0]->nodetype == en_autoreg))
{
int tp;
if (tp = csp->exp->v.p[0]->v.sp->tp->type == bt_union || tp ==
bt_struct || tp == bt_class)
csp->voidf = 1;
}
if (csp->exp->nodetype == en_autocon || csp->exp->nodetype ==
en_autoreg)
{
CSE *two = voidauto(csp->exp);
if (two)
{
csp->uses += two->duses;
}
}
csp = csp->next;
}
}
//-------------------------------------------------------------------------
void scan_for_inline(ENODE *node)
{
SYM *sp;
ENODE *node2 = node->v.p[1]->v.p[0];
if (node2->nodetype == en_nacon || node2->nodetype == en_napccon)
{
sp = node2->v.sp;
if (sp && (sp->value.classdata.cppflags &PF_INLINE))
scan(sp->value.classdata.inlinefunc->stmt);
}
}
//-------------------------------------------------------------------------
void scanexpr(ENODE *node, int duse, int size)
/*
* scanexpr will scan the expression pointed to by node for optimizable
* subexpressions. when an optimizable expression is found it is entered
* into the tree. if a reference to an autocon node is scanned the
* corresponding auto dereferenced node will be voided. duse should be
* set if the expression will be dereferenced.
*
*/
{
CSE *csp, *csp1;
int sz;
if (node == 0)
return ;
switch (node->nodetype)
{
case en_tempref:
case en_labcon:
case en_nalabcon:
case en_regref:
break;
case en_structret:
break;
case en_conslabel:
case en_destlabel:
case en_movebyref:
scanexpr(node->v.p[0], duse, size);
break;
case en_rcon:
case en_lrcon:
case en_fcon:
case en_rcomplexcon:
case en_lrcomplexcon:
case en_fcomplexcon:
case en_rimaginarycon:
case en_lrimaginarycon:
case en_fimaginarycon:
funcfloat++;
anyusedfloat++;
case en_icon:
case en_lcon:
case en_iucon:
case en_lucon:
case en_boolcon:
case en_ccon:
case en_cucon:
case en_llcon:
case en_llucon:
/* not putting constants in registers */
break;
case en_autocon:
if (node->v.sp->iscatchvar)
break;
case en_autoreg:
case en_nacon:
case en_absacon:
enternode(node, duse, 4);
case en_napccon:
break;
case en_bits:
scanexpr(node->v.p[0], duse, natural_size(node));
break;
case en_fcomplexref:
case en_rcomplexref:
case en_lrcomplexref:
funcfloat++;
scanexpr(node->v.p[0], 1, natural_size(node->v.p[0]));
break;
case en_fp_ref:
scanexpr(node->v.p[0], 1, natural_size(node->v.p[0]));
break;
case en_fimaginaryref:
case en_rimaginaryref:
case en_lrimaginaryref:
case en_floatref:
case en_doubleref:
case en_longdoubleref:
funcfloat++;
case en_b_ref:
case en_bool_ref:
case en_w_ref:
case en_ub_ref:
case en_uw_ref:
case en_ul_ref:
case en_l_ref:
case en_i_ref:
case en_ui_ref:
case en_a_ref: case en_ua_ref:
if (node->v.p[0]->nodetype == en_autocon && !node->v.p[0]->v.sp
->iscatchvar || node->v.p[0]->nodetype == en_autoreg)
enternode(node, duse, natural_size(node));
else
scanexpr(node->v.p[0], 1, natural_size(node->v.p[0]));
break;
case en_ll_ref:
case en_ull_ref:
case en_cl_reg:
scanexpr(node->v.p[0], 1, natural_size(node->v.p[0]));
break;
case en_uminus:
case en_asuminus:
case en_ascompl:
case en_compl:
case en_not:
scanexpr(node->v.p[0], duse, natural_size(node->v.p[0]));
break;
case en_cf:
case en_cd:
case en_cld:
case en_cfc:
case en_crc:
case en_clrc:
case en_cfi:
case en_cri:
case en_clri:
funcfloat++;
case en_cb:
case en_cub:
case en_cbool:
case en_cw:
case en_cuw:
case en_cfp:
case en_csp:
case en_cl:
case en_cul:
case en_ci:
case en_cui:
case en_cp:
case en_cll:
case en_cull:
scanexpr(node->v.p[0], duse, natural_size(node));
break;
case en_asadd:
case en_assub:
size = natural_size(node->v.p[0]);
scanexpr(node->v.p[0], duse, 0);
scanexpr(node->v.p[1], duse, size);
break;
case en_ainc:
case en_adec:
case en_add:
case en_sub:
case en_addstruc:
en_addcast: scanexpr(node->v.p[0], duse, natural_size(node->v.p[0]))
;
scanexpr(node->v.p[1], duse, natural_size(node->v.p[1]));
break;
case en_asalsh:
case en_asarsh:
case en_alsh:
case en_arsh:
case en_arshd:
case en_asarshd:
case en_asmul:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -