Files
ldc/backend/cod5.c
Alexey Prokhin caad8cde58 Squashed 'dmd2/' content from commit 10017d5
git-subtree-dir: dmd2
git-subtree-split: 10017d50eaaff4ecdc37a0153b6c37ea0b004c81
2012-04-05 11:10:48 +04:00

208 lines
4.9 KiB
C

// Copyright (C) 1995-1998 by Symantec
// Copyright (C) 2000-2009 by Digital Mars
// All Rights Reserved
// http://www.digitalmars.com
// Written by Walter Bright
/*
* This source file is made available for personal use
* only. The license is in /dmd/src/dmd/backendlicense.txt
* or /dm/src/dmd/backendlicense.txt
* For any other uses, please contact Digital Mars.
*/
#if !SPP
#include <stdio.h>
#include <string.h>
#include <time.h>
#include "cc.h"
#include "el.h"
#include "oper.h"
#include "code.h"
#include "global.h"
#include "type.h"
static char __file__[] = __FILE__; /* for tassert.h */
#include "tassert.h"
STATIC void pe_add(block *b);
STATIC int need_prolog(block *b);
/********************************************************
* Determine which blocks get the function prolog and epilog
* attached to them.
*/
void cod5_prol_epi()
{
#if 1
cod5_noprol();
#else
tym_t tym;
tym_t tyf;
block *b;
block *bp;
list_t bl;
int nepis;
tyf = funcsym_p->ty();
tym = tybasic(tyf);
if (!(config.flags4 & CFG4optimized) ||
anyiasm ||
usedalloca ||
usednteh ||
tyf & (mTYnaked | mTYloadds) ||
tym == TYifunc ||
tym == TYmfunc || // can't yet handle ECX passed as parameter
tym == TYjfunc || // can't yet handle EAX passed as parameter
config.flags & (CFGalwaysframe | CFGtrace) ||
// config.fulltypes ||
(config.wflags & WFwindows && tyfarfunc(tym)) ||
need_prolog(startblock)
)
{ // First block gets the prolog, all return blocks
// get the epilog.
//printf("not even a candidate\n");
cod5_noprol();
return;
}
// Turn on BFLoutsideprolog for all blocks outside the ones needing the prolog.
for (b = startblock; b; b = b->Bnext)
b->Bflags &= ~BFLoutsideprolog; // start with them all off
pe_add(startblock);
// Look for only one block (bp) that will hold the prolog
bp = NULL;
nepis = 0;
for (b = startblock; b; b = b->Bnext)
{ int mark;
if (b->Bflags & BFLoutsideprolog)
continue;
// If all predecessors are marked
mark = 0;
assert(b->Bpred);
for (bl = b->Bpred; bl; bl = list_next(bl))
{
if (list_block(bl)->Bflags & BFLoutsideprolog)
{
if (mark == 2)
goto L1;
mark = 1;
}
else
{
if (mark == 1)
goto L1;
mark = 2;
}
}
if (mark == 1)
{
if (bp) // if already have one
goto L1;
bp = b;
}
// See if b is an epilog
mark = 0;
for (bl = b->Bsucc; bl; bl = list_next(bl))
{
if (list_block(bl)->Bflags & BFLoutsideprolog)
{
if (mark == 2)
goto L1;
mark = 1;
}
else
{
if (mark == 1)
goto L1;
mark = 2;
}
}
if (mark == 1 || b->BC == BCret || b->BC == BCretexp)
{ b->Bflags |= BFLepilog;
nepis++;
if (nepis > 1 && config.flags4 & CFG4space)
goto L1;
}
}
if (bp)
{ bp->Bflags |= BFLprolog;
//printf("=============== prolog opt\n");
}
#endif
}
/**********************************************
* No prolog/epilog optimization.
*/
void cod5_noprol()
{
block *b;
//printf("no prolog optimization\n");
startblock->Bflags |= BFLprolog;
for (b = startblock; b; b = b->Bnext)
{
b->Bflags &= ~BFLoutsideprolog;
switch (b->BC)
{ case BCret:
case BCretexp:
b->Bflags |= BFLepilog;
break;
default:
b->Bflags &= ~BFLepilog;
}
}
}
/*********************************************
* Add block b, and its successors, to those blocks outside those requiring
* the function prolog.
*/
STATIC void pe_add(block *b)
{ list_t bl;
if (b->Bflags & BFLoutsideprolog ||
need_prolog(b))
return;
b->Bflags |= BFLoutsideprolog;
for (bl = b->Bsucc; bl; bl = list_next(bl))
pe_add(list_block(bl));
}
/**********************************************
* Determine if block needs the function prolog to be set up.
*/
STATIC int need_prolog(block *b)
{
if (b->Bregcon.used & fregsaved)
goto Lneed;
// If block referenced a param in 16 bit code
if (!I32 && b->Bflags & BFLrefparam)
goto Lneed;
// If block referenced a stack local
if (b->Bflags & BFLreflocal)
goto Lneed;
return 0;
Lneed:
return 1;
}
#endif