📄 oxccl.c
字号:
if(TBL->nbins)
{/* hashed dictionary */
KEY cat;
NodePS *binp;
NodePS prev = 0;
hash(key, &cat);
binp = &TBL->bins[cat.hv % TBL->nbins];
if((node = *binp))
{
do {
if( node->key[0] == cat.k[0]
&& node->key[0] == cat.k[1])
{
if(prev)
prev->fptr[0] = node->fptr[0];
else
*binp = node->fptr[0];
free_Snode(tbl, node);
if(TBL->lastptr == node)
{
TBL->lastptr = 0;
TBL->lastbin = TBL->nbins;
}
return;
}
prev = node;
} while((node = node->fptr[0]));
}
}
else
{/* sorted dictionary */
int level;
NodePS update[SYM_MAXLEVEL+1];
node = TBL->header;
for(level = TBL->level; level >= 0; level--)
{
while ( KEYLT(node->fptr[level]->key, ((unsigned long*)key)) )
node = node->fptr[level];
update[level] = node;
}
node = node->fptr[0];
if( KEYEQ(node->key, ((unsigned long*)key)) )
{
for(level = 0; level <= TBL->level; level++)
{
if (update[level]->fptr[level] == node)
update[level]->fptr[level] = node->fptr[level];
else break;
}
while((TBL->level > 0) && (TBL->header->fptr[TBL->level] == _NNIL))
TBL->level--;
if(TBL->lastptr == node)
TBL->lastptr = 0;
free_Snode(tbl, node);
}
}
}
}
static int
SymHead(void *tbl)
{/* Set up for sequential access */
int nbins;
if(tbl)
{
if((nbins = TBL->nbins))
{/* hashed dictionary */
NodePS node;
int i;
TBL->lastptr = 0;
for(i = 0; i < nbins; ++i)
{
if( (node = TBL->bins[i]) != 0)
{
TBL->lastbin = i;
return 1;
}
}
TBL->lastbin = nbins;
return 0; /* empty */
}
else
{/* sorted dictionary */
TBL->lastptr = TBL->header;
return (TBL->lastptr->fptr[0] == _NNIL) ? 0 : 1;
}
}
return 0;
}
static int
SymNext(void *tbl)
{/* Move to next sequential entry */
int nbins;
if(tbl)
{
if((nbins = TBL->nbins))
{/* hashed dictionary */
if(TBL->lastptr && ((TBL->lastptr = TBL->lastptr->fptr[0])))
return 1;
else
{
int i;
for(i = TBL->lastbin; i < nbins; ++i)
{
if((TBL->lastptr = TBL->bins[i]) != 0)
{
TBL->lastbin = i+1;
return 1;
}
}
return 0;
}
}
else
{/* sorted dictionary */
if(TBL->lastptr)
{
if(TBL->lastptr != _NNIL)
TBL->lastptr = TBL->lastptr->fptr[0];
return (TBL->lastptr == _NNIL) ? 0 : 1;
}
}
}
return 0;
}
static void
SymGetMark(void *tbl, void *markptr)
{
if(tbl && markptr)
{
((long*)markptr)[0] = TBL->lastbin;
((long*)markptr)[1] = (long)TBL->lastptr;
}
}
static int
SymMarkNext(void *tbl, void *mark)
{/* Mark current position, and move to next sequential entry */
SymGetMark(tbl, mark);
return SymNext(tbl);
}
static void
SymSetMark(void *tbl, void *markptr)
{
if(tbl && markptr)
{
TBL->lastbin = ((long*)markptr)[0];
TBL->lastptr = (NodePS)((long*)markptr)[1];
}
}
static void
SymKey(void *tbl, void *keyptr)
{/* Retrieve key info pointer for current spot */
if(tbl && keyptr && TBL->lastptr)
*((unsigned long**)keyptr) = &TBL->lastptr->key[0];
}
static void
SymValue(void *tbl, void *datptr)
{/* Retrieve value pointer for current spot */
if(tbl && datptr && TBL->lastptr)
*((unsigned long**)datptr) = &TBL->lastptr->value[0];
}
/* ==================== END SYMBOL TABLE HANDLERS ========================== */
/* ========================== OPTIMIZATION ================================= */
static int
forward(unsigned char *p)
{
unsigned char *next;
do {
next = (void*)((Pop)p)->next;
while( *next == 0
|| *next == lineop
|| *next == labelop)
next = (void*)((Pop)next)->next;
if(*next == endop)
{
if(*p == *(next+8))
{
*p = 0;
*next = 0;
return 1;
}
return 0;
}
} while(forward(next));
return 0;
}
static void
eliminate_extraneous_infops(Piv iv, int level)
{
Pafile pf;
unsigned char *p;
int i;
for(i = 0; i < iv->numfiles; ++i)
{
iv->filenum = i;
pf = iv->files[i];
if(!(p = pf->prog_p))
continue;
if(pf->header_p->hdr.opt_level >= level)
continue;
pf->header_p->hdr.opt_level = level;
while(*p != endfileop)
{
switch(*p)
{
case unopop:
case arrayelemop:
case ptrelemop:
case strelemop:
case ptrdimsop:
case arraydimsop:
forward(p);
break;
}
p = POP->next;
}
}
}
static void
clean_temps(Piv iv)
{
long *key;
long *val;
long hitemp = iv->first_temp & 0xffff0000;
if(iv->temps_written == 0)
return;
if(SymHead(iv->tmptbl))
{
while(SymNext(iv->tmptbl))
{
SymKey(iv->tmptbl, &key);
if((key[0] & 0xffff0000) == hitemp)
{
char *ptr;
long saveit;
SymValue(iv->tmptbl, &val);
saveit = val[1];
ptr = (void*)val[0];
val[0] = 0; /* allow reuse of this slot */
val[1] = 0;
while(ptr)
{
void *nptr = (void*)((PopT)ptr)->tmpnum;
((PopT)ptr)->tmpnum = key[0];
if(!saveit)
{
*(ptr-8) = 0;
++iv->killop;
}
ptr = nptr;
}
}
}
if(!hitemp)
iv->temps_written = 0;
}
}
static void
read_temp(Piv iv, PopT ptr, unsigned long last)
{
unsigned long key[2];
long *result;
if(last == ptr->tmpnum)
return;
key[0] = ptr->tmpnum;
key[1] = 0;
if(SymFind(iv->tmptbl, key, &result) == 1)
{
result[1] = 1;
}
else PERROR(pName ":SYSERROR: read temp %d not found\n", key[0]);
}
static long
write_temp(Piv iv, PopT ptr)
{
long key[2];
long val[2];
long *result;
long hitemp = ptr->tmpnum & 0xffff0000;
if(ptr->atype & A_MEMADDR)
{/* actually reading from this destination slot */
read_temp(iv, ptr, 0);
return 0;
}
if(hitemp > (iv->first_temp & 0xffff0000))
{/* Inner block, CompoundExp or NestedFunc */
iv->first_temp = hitemp + 1;
}
else if(hitemp < (iv->first_temp & 0xffff0000))
{/* Exit inner block */
while(hitemp < (iv->first_temp & 0xffff0000))
{
clean_temps(iv);
iv->first_temp -= 0x00010000;
}
}
if(ptr->tmpnum == iv->first_temp)
{
clean_temps(iv);
}
++iv->temps_written;
key[0] = ptr->tmpnum;
key[1] = 0;
if(SymFind(iv->tmptbl, key, &result) == 1)
{
PopT optr = (PopT)result[0];
result[0] = (long)ptr;
ptr->tmpnum = (long)optr;
}
else
{
val[0] = (long)ptr;
val[1] = 0;
SymInsert(iv->tmptbl, key, val, 8);
ptr->tmpnum = 0;
}
return key[0];
}
static void
eliminate_unused_temps(Piv iv, int level)
{
Pafile pf;
unsigned char *p;
int i;
long last_write;
iv->tmptbl = NewSymTable(iv->category, 111);
for(i = 0; i < iv->numfiles; ++i)
{
iv->filenum = i;
pf = iv->files[i];
if(pf->header_p->hdr.opt_level >= level)
continue;
pf->header_p->hdr.opt_level = level;
rekill:
if(!(p = pf->prog_p))
continue;
iv->first_temp = 1;
iv->temps_written = 0;
iv->killop = 0;
while(*p != endfileop)
{
if(*p < labelop)
{
if(*p == truthop)
{/* truthops of single chars are unnecessary */
if((p[2] & 0xe0) == OPTEMP)
{
if(((PopT)(p+20))->dsize == 1)
{
if(((PopT)(p+8))->tmpnum == ((PopT)(p+20))->tmpnum)
{
*p = 0;
}
else
{/* may be needed for code generation */
*p = aliastmpop;
}
}
}
}
if(*p)
{
if(*p == jmptrueop || *p == jmpfalseop)
read_temp(iv,(PopT)(p+4), 0);
else
{
last_write = 0;
if((p[1] & 0xe0) == OPTEMP)
last_write = write_temp(iv, (PopT)(p+8));
if((p[2] & 0xe0) == OPTEMP)
read_temp(iv, (PopT)(p+8+(p[1]&0x1f)), last_write);
if((p[3] & 0xe0) == OPTEMP)
read_temp(iv, (PopT)(p+8+(p[1]&0x1f)+(p[2]&0x1f)), last_write);
}
}
}
p = POP->next;
}
do {
clean_temps(iv);
iv->first_temp -= 0x00010000;
} while(iv->first_temp > 0);
if(iv->killop)
goto rekill;
}
}
static void
retarget_jmps(Piv iv, int level)
{
Pafile pf;
unsigned char *p;
int i;
for(i = 0; i < iv->numfiles; ++i)
{
iv->filenum = i;
pf = iv->files[i];
if(!(p = pf->prog_p))
continue;
if(pf->header_p->hdr.opt_level >= level)
continue;
#if 0
pf->header_p->hdr.opt_level = level;
while(*p != endfileop)
{
p = POP->next;
}
#endif
}
}
static void
optimize(Piv iv)
{
eliminate_extraneous_infops(iv, 50);
eliminate_unused_temps(iv, 51);
retarget_jmps(iv, 52);
}
/* ========================== END OPTIMIZATION ============================= */
/* ====================== BASIC INPUT FILE PROCESSING ====================== */
static long
label_insert(Piv iv, long label, int filenum)
{
struct {
long k1;
long k2;
} key;
struct {
long newlabel;
} val;
key.k1 = label;
key.k2 = filenum;
val.newlabel = ++iv->lastlabel;
SymInsert(iv->labeltbl, &key, &val, 4);
#if REALLY_NEED_OFFSETS
key.k1 = val.newlabel;
val.newlabel = -1;
SymInsert(iv->newlabeltbl, &key, &val, 4);
#endif
return iv->lastlabel;
}
static long
label_find(Piv iv, long label, int filenum)
{
struct {
long k1;
long k2;
} key;
long *result;
key.k1 = label;
key.k2 = filenum;
if(SymFind(iv->labeltbl, &key, &result) == 1)
return *result;
else
return 0;
}
#if REALLY_NEED_OFFSETS
static long
newlabel_find(Piv iv, long label, int filenum)
{
struct {
long k1;
long k2;
} key;
long *result;
key.k1 = label;
key.k2 = filenum;
if(SymFind(iv->newlabeltbl, &key, &result) == 1)
return *result;
else
return 0;
}
#endif /* REALLY_NEED_OFFSETS */
static void
extern_insert(Piv iv, unsigned char *p, int filenum)
{
struct {
short k1;
short k2;
long k3;
} key;
struct {
unsigned char *p;
} val;
key.k1 = GS(POPI->s.symnum);
key.k2 = filenum;
key.k3 = 0;
val.p = p;
SymInsert(iv->extrntbl, &key, &val, 4);
}
static void
reloc_insert(Piv iv, int fileno, unsigned char *p)
{
struct {
unsigned long spot;
short fileno;
char opcode;
char rsize;
} key;
struct {
unsigned char *p;
unsigned long base;
long offset;
short rsym;
} val;
key.spot = GL(POPI->reloc.spot); /* reloc target offset */
key.fileno = (short)fileno; /* fileno */
key.opcode = *p; /* opcode */
key.rsize = GL(POPI->reloc.rsize); /* reloc size */
val.p = p; /* pointer to input buffer */
val.base = GL(POPI->reloc.base); /* base of data object pointed to */
val.offset = GL(POPI->reloc.offset); /* offset to be added to base */
val.rsym = GL(POPI->reloc.rsym); /* symbol number if external */
SymInsert(iv->reloctbl, &key, &val, 14);
}
static void
data_insert(void *tbl, unsigned long offset, unsigned long size, void *p)
{
struct {
unsigned long k1;
long k2;
} key;
struct {
unsigned long size;
void *p;
} val;
key.k1 = offset;
key.k2 = 0;
val.size = size;
val.p = p;
SymInsert(tbl, &key, &val, sizeof(val));
}
static void
global_insert(Piv iv, Pafile pf, unsigned char *p)
{
unsigned long key[2];
struct _gloval val;
PopI pp;
unsigned char opcode = *p;
if(opcode == extvarop)
pp = POPI;
else
pp = (PopI)(POP->next+8);
key[0] = 0;
key[1] = 0;
val.symnum = GS(pp->s.symnum);
val.symname = pf->symaddr[val.symnum];
val.p = p;
val.pf = pf;
sym_hash(key, val.symname);
SymInsert(iv->gbltbl, key, &val, sizeof(val));
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -