⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 oxccl.c

📁 OXCC is a multipass, interpreting C compiler with several language extensions. It generates an Archi
💻 C
📖 第 1 页 / 共 5 页
字号:
	  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 + -