📄 gstmt386.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 <limits.h>
#include "lists.h"
#include "expr.h"
#include "c.h"
#include "gen386.h"
#include "diag.h"
extern int virtualfuncs;
extern SYM *templateSP;
extern SNODE *funcstmt, *funcendstmt;
extern ENODE *thisenode;
extern SYM *thissp;
extern TABLE *gsyms;
extern int stdaddrsize;
extern int global_flag;
extern int fsave_mask, save_mask;
extern TYP stdfunc;
extern struct amode push[], pop[];
extern OCODE *peep_tail, *peep_head, *peep_insert;
extern SYM *currentfunc;
extern int regs[3];
extern int prm_cplusplus, prm_profiler, prm_farkeyword;
extern int firstlabel, nextlabel;
extern long lc_maxauto;
extern ENODE *block_rundown;
extern SYM *declclass;
extern int funcfloat;
extern int prm_smartframes;
extern OCODE *frame_ins;
extern int vtabhead;
extern int conscount;
extern int prm_xcept;
extern TRYBLOCK *try_block_list;
extern int xceptoffs;
extern int prm_cplusplus, prm_xcept;
extern int genning_inline;
int retlab, startlab;
LIST *mpthunklist;
struct cases {
LLONG_TYPE bottom;
LLONG_TYPE top;
int count;
int deflab;
int tablepos;
int diddef : 1;
struct caseptrs {
int label;
int binlabel;
LLONG_TYPE id;
} *ptrs;
} ;
static int returndreg;
static int breaklab;
static int contlab;
static long plabel;
static int retsize;
AMODE *makedreg(int r)
/*
* make an address reference to a data register.
*/
{
AMODE *ap;
ap = xalloc(sizeof(AMODE));
ap->mode = am_dreg;
ap->preg = r;
ap->length = BESZ_DWORD;
return ap;
}
AMODE *makefreg(int r)
/*
* make an address reference to a data register.
*/
{
AMODE *ap;
ap = xalloc(sizeof(AMODE));
ap->mode = am_freg;
ap->preg = r;
ap->length = 10;
return ap;
}
//-------------------------------------------------------------------------
AMODE *make_direct(int i)
/*
* make a direct reference to an immediate value.
*/
{
return make_offset(makeintnode(en_icon, i));
}
//-------------------------------------------------------------------------
AMODE *make_strlab(char *s)
/*
* generate a direct reference to a string label.
*/
{
AMODE *ap;
ap = xalloc(sizeof(AMODE));
ap->mode = am_direct;
ap->offset = makenode(en_nacon, s, 0);
return ap;
}
//-------------------------------------------------------------------------
void genwhile(SNODE *stmt)
/*
* generate code to evaluate a while statement.
*/
{
int lab1, lab2, lab3;
initstack(); /* initialize temp registers */
lab1 = contlab; /* save old continue label */
contlab = nextlabel++; /* new continue label */
if (stmt->s1 != 0)
/* has block */
{
lab2 = breaklab; /* save old break label */
breaklab = nextlabel++;
gen_codes(op_jmp, 0, make_label(contlab), 0);
lab3 = nextlabel++;
gen_label(lab3);
genstmt(stmt->s1);
gen_label(contlab);
if (stmt->lst)
gen_line(stmt->lst);
initstack();
truejp(stmt->exp, lab3);
gen_label(breaklab);
breaklab = lab2; /* restore old break label */
}
else
/* no loop code */
{
if (stmt->lst)
gen_line(stmt->lst);
gen_label(contlab);
initstack();
truejp(stmt->exp, contlab);
}
contlab = lab1; /* restore old continue label */
}
//-------------------------------------------------------------------------
void gen_for(SNODE *stmt)
/*
* generate code to evaluate a for loop
*/
{
int old_break, old_cont, exit_label, loop_label, start_label;
old_break = breaklab;
old_cont = contlab;
loop_label = nextlabel++;
contlab = nextlabel++;
start_label = nextlabel++;
exit_label = nextlabel++;
initstack();
if (stmt->label != 0)
{
gen_void(stmt->label);
}
gen_codes(op_jmp, 0, make_label(start_label), 0);
gen_label(loop_label);
if (stmt->s1 != 0)
{
breaklab = exit_label;
genstmt(stmt->s1);
}
if (stmt->lst)
gen_line(stmt->lst);
gen_label(contlab);
initstack();
if (stmt->s2 != 0)
{
gen_void(stmt->s2);
}
gen_label(start_label);
initstack();
if (stmt->exp != 0)
truejp(stmt->exp, loop_label);
else
gen_codes(op_jmp, 0, make_label(loop_label), 0);
gen_label(exit_label);
breaklab = old_break;
contlab = old_cont;
}
//-------------------------------------------------------------------------
void genif(SNODE *stmt)
/*
* generate code to evaluate an if statement.
*/
{
int lab1, lab2;
lab1 = nextlabel++; /* else label */
lab2 = nextlabel++; /* exit label */
initstack(); /* clear temps */
falsejp(stmt->exp, lab1);
genstmt(stmt->s1);
if (stmt->s2 != 0)
/* else part exists */
{
gen_codes(op_jmp, 0, make_label(lab2), 0);
gen_label(lab1);
genstmt(stmt->s2);
gen_label(lab2);
}
else
/* no else code */
gen_label(lab1);
}
//-------------------------------------------------------------------------
void gendo(SNODE *stmt)
/*
* generate code for a do - while loop.
*/
{
int oldcont, oldbreak, looplab;
oldcont = contlab;
oldbreak = breaklab;
looplab = nextlabel++;
contlab = nextlabel++;
breaklab = nextlabel++;
gen_label(looplab);
genstmt(stmt->s1); /* generate body */
gen_label(contlab);
initstack();
truejp(stmt->exp, looplab);
gen_label(breaklab);
breaklab = oldbreak;
contlab = oldcont;
}
//-------------------------------------------------------------------------
AMODE *set_symbol(char *name, int flag)
{
SYM *sp;
AMODE *ap;
sp = gsearch(name);
if (sp == 0)
{
++global_flag;
sp = makesym(flag ? sc_externalfunc : sc_external);
sp->tp = &stdfunc;
sp->name = name;
sp->extflag = 1;
insert(sp, gsyms);
--global_flag;
}
ap = xalloc(sizeof(AMODE));
ap->mode = am_immed;
ap->length = BESZ_DWORD;
ap->offset = makenode(en_nacon, sp, 0);
return ap;
}
//-------------------------------------------------------------------------
void call_library(char *lib_name)
/*
* generate a call to a library routine.
*/
{
AMODE *ap;
ap = set_symbol(lib_name, 1);
gen_codes(op_call, 0, ap, 0);
}
//-------------------------------------------------------------------------
void count_cases(SNODE *stmt, struct cases *cs)
{
while (stmt)
{
switch(stmt->stype) {
case st_tryblock:
break;
case st_throw:
break;
case st_return:
case st_expr:
break;
case st_while:
case st_do:
count_cases(stmt->s1,cs);
break;
case st_for:
count_cases(stmt->s1,cs);
break;
case st_if:
count_cases(stmt->s1,cs);
count_cases(stmt->s2,cs);
break;
case st_switch:
break;
case st_block:
count_cases(stmt->exp,cs);
break;
case st_asm:
break;
case st_case:
if (!stmt->s2)
{
cs->count++;
if (stmt->switchid < cs->bottom)
cs->bottom = stmt->switchid;
if (stmt->switchid > cs->top)
cs->top = stmt->switchid;
}
break;
}
stmt = stmt->next;
}
}
//-------------------------------------------------------------------------
void gather_cases(SNODE *stmt, struct cases *cs, int compact)
{
if (!cs->ptrs) {
global_flag++;
if (compact) {
int i;
cs->ptrs = xalloc((cs->top - cs->bottom) * sizeof(struct cases));
for (i = cs->bottom; i < cs->top; i++)
cs->ptrs[i - cs->bottom].label = cs->deflab;
} else
cs->ptrs = xalloc((cs->count) * sizeof(struct cases));
global_flag--;
}
while (stmt)
{
switch(stmt->stype) {
case st_tryblock:
break;
case st_throw:
break;
case st_return:
case st_expr:
break;
case st_while:
case st_do:
gather_cases(stmt->s1,cs,compact);
break;
case st_for:
gather_cases(stmt->s1,cs,compact);
break;
case st_if:
gather_cases(stmt->s1,cs,compact);
gather_cases(stmt->s2,cs,compact);
break;
case st_switch:
break;
case st_block:
gather_cases(stmt->exp,cs,compact);
break;
case st_asm:
break;
case st_case:
if (stmt->s2)
/* default case */
{
cs->diddef = TRUE;
stmt->label = (SNODE*)cs->deflab;
}
else
{
if (compact) {
cs->ptrs[stmt->switchid - cs->bottom].label = nextlabel;
stmt->label = (SNODE*)nextlabel++;
} else {
cs->ptrs[cs->tablepos].label = nextlabel;
cs->ptrs[cs->tablepos].binlabel = - 1;
cs->ptrs[cs->tablepos++].id = stmt->switchid;
stmt->label = (SNODE*)nextlabel++;
}
}
break;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -