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

📄 cctype.c

📁 KCC , a good c compiler, write by Ken Harrenstien
💻 C
📖 第 1 页 / 共 3 页
字号:
	PTRREP_WD,	/* (double *) */
	PTRREP_WD,	/* (long double *) */
	PTRREP_CH,	/* (bitfield *) */
	PTRREP_CH,	/* (char *) */
	PTRREP_WD,	/* (short *) */
	PTRREP_WD,	/* (int *) */
	PTRREP_WD,	/* (long *) */
	PTRREP_CH,	/* (unsigned bitfield *) */
	PTRREP_CH,	/* (unsigned char *) */
	PTRREP_WD,	/* (unsigned short *) */
	PTRREP_WD,	/* (unsigned int *) */
	PTRREP_WD,	/* (unsigned long *) */
};

/* Pointer conversion table, [to][from] */
static pconvtab[PTRREP_MAX][PTRREP_MAX] = {
	/* To word ptr */
	CAST_NONE,		/* From word ptr */
	CAST_PC_PI,		/* From char ptr */

	/* To char ptr */
	CAST_PI_PC,		/* From word ptr */
	CAST_NONE,		/* From char ptr */
};
#endif

/* CAST_OP	Find CAST_ conversion type to use.	[H&S 6.2 - 6.9 incl]
**	This is the only routine that references the conversion table.
**	The returned operation is based purely on the top type of
**	each type, ignoring qualifiers.  Minimal checking is done.
*/
static int
cast_op(to, frm)
TYPE *to, *frm;
{
    int cop;

    switch (cop = convtab[castidx(frm->Tspec,to->Tspec)]) {
	case CAST_TRIV:		/* Verify that types are identical */
	    if (to == frm	/* This should have been caught before call */
	      || cmputype(to, frm))	/* Ignore type-qualifiers */
		return CAST_NONE;
	    cop = CAST_ILL;	/* Otherwise drop through to complain */
	case CAST_ILL:
	    error("Illegal conversion - %s to %s",
		tsnames[frm->Tspec], tsnames[to->Tspec]);
	    break;
	case CAST_VOID:		/* Discard -- converting to void */
	case CAST_NONE:		/* No actual conversion operation needed */
	    break;

	/* These two conversions should have been caught before this.
	*/
	case CAST_AR_PA:	/* Array to T should be ptr to T */
	case CAST_FN_PF:	/* Function should be ptr to function */
	    int_error("cast_op: bad cast - %s to %s",
		tsnames[frm->Tspec], tsnames[to->Tspec]);
	    cop = CAST_ILL;
	    break;

	case CAST_PT_PT:	/* OK as is.  Someday convert into more */
	    break;		/* specific type of conversion? */

	/* Integer to integer conversion.
	**	May be able to detect that no actual conversion is needed.
	**	This code assumes that signed and unsigned types occupy the
	**	same amount of space, and that there is no representation
	**	change when converting between the two!  This will be true
	**	for just about all computers.
	*/
	case CAST_IT_IT:
	    if ((tbitsize(frm) == tbitsize(to))		/* If same size */
		/* && tisunsigned(frm) == tisunsigned(to) *//* & signedness? */
		)
		return CAST_NONE;
	    break;
    default:
	;	/* do nothing */
    }
    return cop;
}

/* CONVCAST - Apply "cast conversions" to an expression.  [H&S 6.10]
**	This is called for explicit casts by the user, and by
**	some implicit conversions elsewhere in CCTYPE.
**	Any type qualifiers are removed from the target type.
**
**	For easier debugging, this almost always forces a cast to the indicated
**	type, even if it may not be necessary.  Optimization can clean up
**	such no-ops farther on.
*/
NODE *
convcast(t,n)
NODE *n;
TYPE *t;
{
    int op;

    if (n->Ntype->Tspec == TS_FUNCT || n->Ntype->Tspec == TS_ARRAY)
	n = convarrfn(n);		/* Pre-convert funct/arrays here */
    if (t == n->Ntype)			/* May now be a trivial cast */
	return n;
    if (tisqualif(t))
	t = findutype(t);		/* Use unqualified type as target */

    op = cast_op(t, n->Ntype);		/* find out which cast to use */
    if (op == CAST_PT_PT && clevkcc	/* Special hack for KCC extension */
	&& n->Nop == N_SCONST		/* If casting string literal */
	&& tischar(t->Tsubt)) {		/* to another kind of char ptr */
	n->Ntype = t;			/* then just change type of const! */
	return n;			/* And code gen will win. */
    }
    return ndefcast(op, t, n);		/* Make cast using that cast op */
}

/* CONVASGN - Apply "assignment conversions" to an expression.  [H&S 6.11]
**	[dpANS 3.3.16.1]
**	Takes two args, a pointer to the type of the left-hand op
** (destination type) and a node pointer to the right-hand expression
** which needs to have its type checked and perhaps fixed up.
*/
NODE *
convasgn(lt,n)
TYPE *lt;		/* Left (destination) type */
NODE *n;
{
    TYPE *rt;		/* Right (source) type */
    NODE *cn;		/* New cast node if any */

    /* If same type, OK */
    if (lt == n->Ntype) return n;
    rt = n->Ntype;

    /* Not same type.  Check to see if it's OK to silently convert the
    ** right-hand type to left-hand type.  If so, call convcast() to do it.
    */
    if (tisarith(lt) && tisarith(rt))	/* Any arith type to any arith type */
	return convcast(lt, n);		/* OK, do the specified conversion */

    switch (lt->Tspec) {
    case TS_PTR:
	if (nisnull(&n))		/* Integer 0 to any ptr type */
	    return convcast(lt, n);	/* OK, do the specified conversion */
	rt = n->Ntype;			/* n may have changed */
	if (rt->Tspec != TS_PTR)	/* Ensure all ptr-to-ptr after here */
	    break;
	/* Ensure left subtype has all qualifiers that right subtype does */
	if (((~lt->Tsubt->Tflag) & rt->Tsubt->Tflag)&TF_QUALS)
	    break;			/* R has qual that L doesnt */
	if (cmputype(lt->Tsubt, rt->Tsubt)
	  || (lt->Tsubt->Tspec == TS_VOID && rt->Tsubt->Tspec != TS_FUNCT)
	  || (rt->Tsubt->Tspec == TS_VOID && lt->Tsubt->Tspec != TS_FUNCT) )
	    return convcast(lt, n);	/* OK, do the specified conversion */
	break;

    case TS_STRUCT:
    case TS_UNION:
	if (lt->Tspec == rt->Tspec	/* Ignore qualifiers, check tag */
	  && lt->Tsmtag == rt->Tsmtag)
	    return convcast(lt, n);	/* OK, do the specified conversion */
	break;
    default:
	;	/* do nothing */
    }

    /* Last-resort attempt */
    if (rt->Tspec == TS_FUNCT || rt->Tspec == TS_ARRAY)
	return convasgn(lt, convarrfn(n));

    /* Technically nothing else is OK.  But we try to do it anyway
    ** and print a warning message.  If the attempted conversion is illegal
    ** then cast_op will complain.
    */
    cn = convcast(lt, n);		/* Attempt to force the cast */
    if (cn != n && cn->Nop == N_CAST	/* If cast was done, print warning */
      && cn->Ncast != CAST_ILL)		/* unless cast_op already barfed. */
	if (clevel >= CLEV_STRICT)
	    error("Illegal conversion - %s to %s", 
		tsnames[rt->Tspec], tsnames[lt->Tspec]);
	else
	    warn("Implicit conversion - %s to %s",
		tsnames[rt->Tspec], tsnames[lt->Tspec]);
    return cn;
}

/* CONVARRFN - Apply array/function conversions to an expression node.
**	Returns pointer to a converted expression (usually the same node)
*/
NODE *
convarrfn(n)
NODE *n;
{
    switch (n->Ntype->Tspec) {
	default: break;		/* Not array or function */

	case TS_ARRAY:		/* Convert "array of T" to "pointer to T" */
	    if (!(n->Nflag & NF_LVALUE)) {	/* Can only convert lvalues */
		error("Array ref must be lvalue");
	    }				/* Do it anyway after complaint */

	    if (!(n->Nflag & NF_GLOBAL)) { /* If obj has local extent */
		stackrefs++;		/* then count it as a */
		n->Nflag |= NF_STKREF;	/* stack reference */
	    }

	    /* For array name, or array subscripting, just set the type.
	    ** Anything else requires using & to get the address.
	    ** That can only be N_PTR, Q_DOT, or Q_MEMBER.
	    */
	    if (n->Nop == Q_IDENT || n->Nop == Q_PLUS) {
		n->Ntype = findtype(TS_PTR, n->Ntype->Tsubt);
		n->Nflag &= ~NF_LVALUE;		/* Ensure not an lvalue */
	    } else
		return ndef(N_ADDR, findtype(TS_PTR, n->Ntype->Tsubt),
				n->Nflag & ~NF_LVALUE,
				n, (NODE *)NULL);
	    break;

	case TS_FUNCT:	/* Convert "function of T" to "pointer to fun of T" */
	    if (n->Nop == Q_IDENT)	/* For function name, just set type */
		n->Ntype = findtype(TS_PTR, n->Ntype);
	    else
		return ndeftl(N_ADDR, findtype(TS_PTR, n->Ntype), n);
    }
    return n;
}

/* CONVUNARY - Apply "usual unary conversions" to a node. [H&S 6.12]
**	Returns pointer to a converted expression (usually the same node)
**	Note that for ANSI there are two differences:
**		(1) the float -> double conversion is suppressed!
**		(2) integer promotions preserve value, not unsignedness.
**			For the PDP-10 this means chars/shorts always
**			are converted to "int", as are bitfields less
**			than the length of an int.
**	The new type, if any, is always the unqualified type.  This may
**	cause a "trivial conversion" merely to get rid of any qualifiers.
*/
NODE *
convunary(n)
NODE *n;
{
    TYPE *newtype;

    switch (n->Ntype->Tspec) {
	case TS_FLOAT:			/* If ANSI, leave float alone */
	    if (clevel < CLEV_ANSI) {
		newtype = dbltype;	/* Float to double */
		break;
	    }
	    /* Not converting, drop thru to default */

	default:	/* Usual case, no conversion needed unless qualified */
	    if (tisqualif(n->Ntype))
		n = convcast(findutype(n->Ntype), n);
	    return n;

	case TS_BITF:
	case TS_CHAR:
	case TS_SHORT:		/* Signed bitfield, char and short */
		newtype = inttype;	/* always become signed int */
		break;

	case TS_UBITF:
	case TS_UCHAR:
	case TS_USHORT:		/* But if unsigned, depends on ANSIness */
	    if ((clevel >= CLEV_ANSI)			/* If ANSI, */
		&& (TGSIZ_INT > tbitsize(n->Ntype)))	/* check size */
		newtype = inttype;	/* ANSI and int is big enough */
	    else newtype = uinttype;	/* Not ANSI, or not big enough */
	    break;


	case TS_ARRAY:	/* Convert "array of T" to "pointer to T" */
	case TS_FUNCT:	/* Convert "function of T" to "pointer to fun of T" */
	    return convarrfn(n);
    }

    /* Apply some simple cast operation and return result */
    return ndefcast(cast_op(newtype, n->Ntype), newtype, n);
}

/* CONVBINARY - Apply "usual binary conversions" to a node. [H&S 6.13]
**	Takes pointer to a binary operator node, with the operands
** pointed to by the left and right links.
** Returns pointer to a converted expression (usually the same node)
** The type will always be unqualified.
**	Note that normally a float-float rule exists ("2a" in H&S 6.13),
** as ANSI requires this.
**	Also note the check in convboth() to avoid doing a double implicit
** conversion (once by convunary and again by convboth); this makes things
** more efficient and avoids confusing the assignment-op code generation,
** which expects only a single implicit cast.
*/

NODE *
convbinary(n)
NODE *n;
{
    TYPE  *lt, *rt;

    n->Nleft = convunary(n->Nleft);	/* First do unary convs on both */
    n->Nright = convunary(n->Nright);	/* Note this removes qualifiers! */
    n->Ntype = n->Nleft->Ntype;		/* Set type in case of quick return */

    if (n->Nleft->Ntype == n->Nright->Ntype) return n;
    lt = n->Nleft->Ntype;
    rt = n->Nright->Ntype;

    /* 1. If either operand is not arith type, do no additional conversion */
    if (!tisarith(lt) || !tisarith(rt)) return n;

    /* 2x. If one operand is "long double", make both "long double". */
    if (lt == lngdbltype || rt == lngdbltype)
	convboth(n, lngdbltype);

    /* 2. If one operand is "double", make both "double". */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -