Google
 

Trailing-Edge - PDP-10 Archives - SRI_NIC_PERM_FS_1_19910112 - c/old/kc/cc8.c
There are no other files named cc8.c in the archive.
/* cc8.c -- Code generator TOPS-20   (C) 1981  K. Chen */

#define	    sd
#include    "cc.g"

/* ------------------------------------------------------------ */
/*	    code generation (KL-10, FAIL)	   	        */
/*						   		*/
/*    char is stored as right justified character    		*/
/*    char[] is stored as 7 bit bytes, always word aligned	*/
/*    *char is stored as a byte pointer		   		*/
/*    *int is stored as an address in the right half 		*/
/*								*/
/*	An activation record looks like:			*/
/*								*/
/*		argument n		(low memory)		*/
/*		argument n-1					*/
/*		...						*/
/*		argument 1					*/
/*		return address  	<- SP at entry		*/
/*		local 1						*/
/*		...						*/
/*		local m			<- SP at start of func	*/
/*								*/
/*	Function return is through AC0 (and AC1, if needed)	*/
/*								*/
/*	Calling routine looks like:				*/
/*								*/
/*		PUSH	17,arg_n				*/
/*		PUSH	17,arg_n-1				*/
/*		...						*/
/*		PUSH	17,arg_1				*/
/*		PUSHJ	17,function				*/
/*		ADJSP	17,-n					*/
/*								*/
/*	Register 17 (octal) used for stack manipulation,	*/
/*	Registers 2 through 16 (octal) may be used by callee.	*/
/* ------------------------------------------------------------ */

gencode(n)
struct NODE *n;
{
  struct SYMBOL *s;
  int  scl;

  if (eflag) {
      maxnode = 0;
      return;	/* generate no further code upon error */
  }

  switch (n->nop) {
  case DATA:
       s = n->right->left->nid;
       scl = s->sclass;
       if (scl == SEXTERN && s->svalue == 1) scl = XTERN;
       switch (scl) {
       case XTERN:
       case SSTATIC:
	    gendata(n); 
	    break;
       case SAUTO:
            if (n->right->right) gendata(n);
	    break;
       }
       break;
  case FUNCTION:
       genbody(n);
  }
  maxnode = 0;
  return;
}

/* ----------------------------- */
/*	assembler preambles      */
/* ----------------------------- */

preamble()
{
  char *s,*t,u[16];

  outstr("\tTITLE\t");
  outstr(module); 
  nl();
  outstr("\t.LIBRARY ");
  t = libprefix;
  s = u;
  strcpy(s,t);		/* needed before complete 9-bit byte implem. */
  outstr(u);
  outstr("CLIB");
  t = libpstfix;
  s = u;
  strcpy(s,t);
  outstr(u);
  outstr("\n");
  outstr("\tEXTERN\t.START\n");
}

/* ------------------------------ */
/*	assembler postambles      */
/* ------------------------------ */

postamble()
{
  int t, u, l;

#ifdef NOADJBP
  outstr("$BYTE:\tOCT\t0,110000000000,220000000000,330000000000\n");
#endif

  gdecl();
  outstr("\n\tEND\n");
  t = (_cputm() - time)/10;
  l = tline * 6000 / t;
  u = t%100;
  if (ncond) {
      fprintf(stderr,"Unterminated compiler control line seen.\n\n");
  }
  fprintf(stderr,"Processed %d lines in %d.%d%d seconds (%d lines/min.)\n",
		  tline, t/100, u/10, u%10, l);
}

/* ------------------------------------------ */
/*	external & internal declarations      */
/* ------------------------------------------ */

gdecl()
{
  struct NODE *u;
  char *op;
  int  count;

  gdecl0("\tINTERN\t", 1, 1000);
  gdecl0("\tEXTERN\t", 0, 1000);
}

gdecl0(op, val, count)
char *op;
{
  int n;
  struct SYMBOL *s;

  n = 0;
  while(n < maxsym) {
      s = &symbol[n];
      if (s->sclass == SEXTERN && s->svalue == val) {
          if (count > 48) {
	      nl();
   	      outstr(op);
	      count = 0;
          }
          if (count) putc(',', out);
          count += (outsym(s->sname)+1);
      }
      n++;
  }
  if (count < 50) nl();
}


/* ---------------------------- */
/*	generate code body      */
/* ---------------------------- */

genbody(n)
struct NODE *n;
{
  struct NODE *s;
  int    size;

  previous = NULL;
  for (mincode = 0; mincode < 32; mincode++) regis[mincode] = -1;
  stackoffset = looplabel = brklabel = maxcode = mincode = maxlit = 0;
  glabel(n->left->left->nid->sname);
  if (maxauto) {
      code8(ADJSP, 017, maxauto);
      stackoffset += maxauto;
  }
  while (maxinit--) {
      size = tsize(isym[maxinit]->sptr);
      if (size == 1) {
          code18(vsym[maxinit]);
      }
      else fprintf(stderr,"Cannot init %s.\n", isym[maxinit]->sname);
  }
  s = n->right;
  while (s->nop == STATEMENT) {
      if (s->right != NULL)
          release(genstmt(s->right));
      s = s->left;
  }
  gend();
}

/* ----------------------------------- */
/*	generate data definitions      */
/* ----------------------------------- */

gendata(n)
struct NODE *n;
{
  struct NODE *nod, *r, *l;
  int    state, count, ncount;

  if (n->left != NULL) gendata(n->left);
  r = n->right;
  if (r->nop == IZ) {
      l = r->left;
      if ((r = r->right) == NULL) {
	  if (l->nid->sptr->ttype == FUNCTION) {
	      /* a function declaration, really */
	      l->nid->sclass = SEXTERN;
	      l->nid->svalue = 0;
	      return;
	  }
	  izsym(l->nid);
	  if ((count = tsize(l->nid->sptr)) == 1) {
	      outstr("0");
	      nl();
	  }
	  else {
	      outstr("BLOCK\t");
	      outnum(count);
	      nl();
	  }
      }
      else {
          switch (r->nop) {
	  case IZLIST:
	       izsym(l->nid);
	       giz(r, l->ntype);
	       break;
          case ICONST:
	       izsym(l->nid);
	       outnum(r->niconst);
	       nl();
	       break;
          case SCONST:
	       izsym(l->nid);
	       if (NBYTES == 5) {
   	           outstr("POINT\t7,[");
                   asciz(r->nsconst);
	           outstr("],6");
	       }
	       else {
   	           outstr("POINT\t9,[");
                   asciz(r->nsconst);
	           outstr("],8");
	       }
	       nl();
	       break;
          default:
	       fprintf(stderr,"Internal inconsistency.\n");
	       exit(0);
          }
      }
  }
}

/* ---------------------------- */
/*	initializer symbol      */
/* ---------------------------- */

izsym(sym)
struct SYMBOL *sym;
{
  char sn[32];

  if (sym->sclass == SAUTO) {
      maklabel(sn,getlabel());
      outsym(sn);
      isym[maxinit] = sym;
      vsym[maxinit++] = maxlabel;
  }
  else outsym(sym->sname);
  outstr(":\t");
}


giz(r, t)
struct NODE *r;
struct TY   *t;
{
  int state, count, ncount, byte;
  char *op;
  struct NODE *nod;

  state = count = 0;
  byte = chararray(t);
  ncount = (byte) ? 4 : 7;
  while (1) {
      nod = r->right;
      switch (nod->nop) {
      case IZLIST:
	   if (state) {
	       nl();
	       tab();
	   }
   	   giz(nod, t->tptr);
   	   state = 0;
	   break;
      case BLOCK:
	   if (state) {
	       nl();
	       tab();
	       state = 0;
	   }
           outstr("BLOCK\t");
	   count = 0;
	   state = 2;
	   outnum(nod->niconst);
	   break;
      case ICONST:
	   if (state >= 2 || count >= ncount || !byte) {
	       nl();
	       tab();
	       state = 0;
	   }
	   if (!state) {
	       if (byte) {
		   if (NBYTES == 5) outstr("BYTE (7)\t");
		   else outstr("BYTE (9)\t");
	       }
	       count = 0;
	   }
	   else {
	       outc(',');
	   }
   	   state = 1;
           outnum(nod->niconst);
	   break;
      case SCONST:
	   if (state != 0) {
	       nl();
	       tab();
	   }
	   if (NBYTES == 5) {
   	       outstr("POINT\t7,[");
               asciz(nod->nsconst);
	       outstr("],6");
	   }
	   else {
   	       outstr("POINT\t9,[");
               asciz(nod->nsconst);
	       outstr("],8");
	   }
	   state = 3;
 	   break;
      }
      count++;
      if ((r = r->left) == NULL) break;
  }
  nl();
}


/* ----------------------------------------- */
/*	output string to assembler file      */
/* ----------------------------------------- */

outstr(s)
char *s;
{
  int n;

  n = 0;
  while (*s) {
      putc(*s++,out);
      n++;
  }
  return n;
}

/* ----------------------------------------- */
/*	output symbol to assembler file      */
/* ----------------------------------------- */

outsym(s)
char *s;
{
  int n;

  n = 0;
  while (*s) {
      putc(((*s == '_') ? '.' : *s), out);
      if (n++ >= 5) break;
      s++;
  }
  return n;
}

/* -------------------------------------------- */
/*	output character to assembler file      */
/* -------------------------------------------- */

outc(n)
{
  putc(n, out);
}

/* ----------------------------- */
/*	tab to second field      */
/* ----------------------------- */

outt(n)
{
  putc(((n < 7) ? '\t' : ' '), out);
}

/* ----------------------------- */
/*	output octal number      */
/* ----------------------------- */

outnum(n)
{
  int k;
  char str[12], *s;

  if (n < 0) {
      n = -n;
      putc('-', out);
  }
  s = str;
  *s = '\0';
  do {
      *++s = (n&07) + '0';
      n = n>>3;
  } while (n);

  while (*s) putc(*s--, out);
}

/* ---------------------- */
/*	asciz string      */
/* ---------------------- */

asciz(s)
char *s;
{
  int k;
  if (NBYTES == 5) {
      if (k = delimit(s)) {
          outstr("ASCIZ ");
          putc(k, out);
          while (*s) _putc(*s++, out);
          putc(k, out);
          return;
      }
      /* "funny" sting, need to generate long form ASCIZ here */
  }
  else {  /* 9-bit bytes */
      while (1) {
          outstr("BYTE\t(9) ");
	  if (*s) outnum(*s);
	  else {
	      outnum(0);
	      break;
	  }
	  if (!*s++) break;
	      putc(',', out);
	      outnum(*s);
	  if (!*s++) break;
	      putc(',', out);
	      outnum(*s);
	  if (!*s++) break;
	      putc(',', out);
	      outnum(*s);
	  if (!*s++) break;
	      outstr("\n\t");
      }
      nl();
  }
}

/* -------------------------------------------------- */
/*	find a usable delimiter for ASCIZ string      */
/*	 otherwise return 0			      */
/* -------------------------------------------------- */

delimit(s)
char *s;
{
  int i,d1,d2,d3,d4;

  d1 = d2 = d3 = d4 = 0;
  while (i=*s++) {
      if (i == '\\') return 0; /* has escape character, use long form */
      switch (i) {
      case '/': d1++; break;
      case '"': d2++; break;
      case '%': d3++; break;
      case '|': d4++; break;
      }
  }
  if (d1) {
      if (d2) {
	  if (d3) {
	      if (d4) {
		 /* cannot find delimiter, use long form */
		 return 0;
 	      }
	      return '|';
	  }
	  return '%';
      }
      return '"';
  }
  return '/';
}