ref: f85a7bfa8943a40c196cb4e3778106bcc77e7eb5
dir: /cc1/types.c/
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "../inc/sizes.h"
#include "../inc/cc.h"
#include "cc1.h"
#define NR_TYPE_HASH 16
/*
* Initializaion of type pointers were done with
* a C99 initilizator '... = &(Type) {...', but
* c compiler in Plan9 gives error with this
* syntax, so I have switched it to this ugly form
* I hope I will change it again in the future
*/
static Type types[] = {
{ /* 0 = voidtype */
.op = VOID,
.letter = L_VOID
},
{ /* 1 = pvoidtype */
.op = PTR,
.letter = L_POINTER
},
{ /* 2 = booltype */
.op = INT,
.letter = L_BOOL,
.defined = 1,
.n.rank = RANK_BOOL
},
{ /* 3 = schartype */
.op = INT,
.letter = L_SCHAR,
.defined = 1,
.n.rank = RANK_SCHAR
},
{ /* 4 = uchartype */
.op = INT,
.letter = L_UCHAR,
.defined = 1,
.n.rank = RANK_UCHAR
},
{ /* 5 = chartype */
.op = INT,
.letter = L_CHAR,
.defined = 1,
.n.rank = RANK_CHAR
},
{ /* 6 = ushortype */
.op = INT,
.letter = L_USHORT,
.defined = 1,
.n.rank = RANK_USHORT
},
{ /* 7 = shortype */
.op = INT,
.letter = L_SHORT,
.defined = 1,
.n.rank = RANK_SHORT
},
{ /* 8 = uinttype */
.op = INT,
.letter = L_UINT,
.defined = 1,
.n.rank = RANK_UINT
},
{ /* 9 = inttype */
.op = INT,
.letter = L_INT,
.defined = 1,
.n.rank = RANK_INT
},
{ /* 10 = longtype */
.op = INT,
.letter = L_LONG,
.defined = 1,
.n.rank = RANK_LONG
},
{ /* 11 = ulongtype
.op = INT,
.letter = L_ULONG,
.defined = 1,
.n.rank = RANK_ULONG
},
{ /* 12 = ullongtype */
.op = INT,
.letter = L_ULLONG,
.defined = 1,
.n.rank = RANK_ULLONG
},
{ /* 13 = llongtype */
.op = INT,
.letter = L_LLONG,
.defined = 1,
.n.rank = RANK_LLONG
},
{ /* 14 = floattype */
.op = FLOAT,
.letter = L_FLOAT,
.defined = 1,
.n.rank = RANK_FLOAT
},
{ /* 15 = doubletype */
.op = FLOAT,
.letter = L_DOUBLE,
.defined = 1,
.n.rank = RANK_DOUBLE
},
{ /* 16 = ldoubletype */
.op = FLOAT,
.letter = L_LDOUBLE,
.defined = 1,
.n.rank = RANK_LDOUBLE
}
};
Type *voidtype = &types[0], *pvoidtype = &types[1],
*booltype = &types[2], *schartype = &types[3],
*uchartype = &types[4], *chartype = &types[5],
*ushortype = &types[6], *shortype = &types[7],
*uinttype = &types[8], *inttype = &types[9],
*longtype = &types[10], *ulongtype = &types[11],
*ullongtype = &types[12], *llongtype = &types[13],
*floattype = &types[14], *doubletype = &types[15],
*ldoubletype = &types[16];
static Symbol dummy0 = {.u.i = 0, .type = &types[9]},
dummy1 = {.u.i = 1, .type = &types[9]};
Symbol *zero = &dummy0, *one = &dummy1;
Type *
ctype(unsigned type, unsigned sign, unsigned size)
{
switch (type) {
case CHAR:
if (size)
goto invalid_type;
switch (sign) {
case 0:
return chartype;
case SIGNED:
return schartype;
case UNSIGNED:
return uchartype;
}
break;
case VOID:
if (size || sign)
goto invalid_type;
return voidtype;
case BOOL:
if (size || sign)
goto invalid_type;
return booltype;
case 0:
if (!sign && !size) {
warn("type defaults to 'int' in declaration");
}
/* fallthrough */
case INT:
switch (size) {
case 0:
return (sign == UNSIGNED) ? uinttype : inttype;
case SHORT:
return (sign == UNSIGNED) ? ushortype : shortype;
case LONG:
return (sign == UNSIGNED) ? ulongtype : longtype;
case LLONG:
return (sign == UNSIGNED) ? ullongtype : llongtype;
}
break;
case DOUBLE:
if (size == LLONG)
goto invalid_type;
size += LONG;
goto floating;
case FLOAT:
if (size == LLONG)
goto invalid_type;
floating:
if (sign)
goto invalid_type;
switch (size) {
case 0:
return floattype;
case LONG:
return doubletype;
case LLONG:
return ldoubletype;
}
break;
}
fputs("internal type error, aborting\n", stderr);
abort();
invalid_type:
error("invalid type specification");
}
Type *
mktype(Type *tp, unsigned op, short nelem, void *data)
{
static Type *typetab[NR_TYPE_HASH];
Type **tbl, type;
unsigned t;
Type *bp;
static char letters[] = {
[PTR] = L_POINTER, [ARY] = L_ARRAY,
[FTN] = L_FUNCTION, [ENUM] = L_INT,
[STRUCT] = L_STRUCT, [UNION] = L_UNION
};
if (op == PTR && tp == voidtype)
return pvoidtype;
type.type = tp;
type.op = op;
type.letter = letters[op];
type.pars = data;
type.n.elem = nelem;
type.ns = 0;
if (op == ARY && nelem == 0 || op == STRUCT || op == UNION)
type.defined = 0;
else
type.defined = 1;
t = (op ^ (char) ((unsigned short) tp >> 3)) & NR_TYPE_HASH-1;
tbl = &typetab[t];
for (bp = *tbl; bp; bp = bp->next) {
if (eqtype(bp, &type)) {
/* FIXME: data can be a pointer to static data */
free(data);
return bp;
}
}
bp = xmalloc(sizeof(*bp));
*bp = type;
bp->next = *tbl;
return *tbl = bp;
}
bool
eqtype(Type *tp1, Type *tp2)
{
unsigned n;
Type **p1, **p2;
if (tp1 == tp2)
return 1;
if (tp1->op != tp2->op || tp1->n.elem != tp2->n.elem)
return 0;
switch (tp1->op) {
case ARY:
case PTR:
return eqtype(tp1->type, tp2->type);
case UNION:
case STRUCT:
case FTN:
p1 = tp1->pars, p2 = tp2->pars;
for (n = tp1->n.elem; n != 0; --n) {
if (!eqtype(*p1++, *p2++))
return 0;
}
return 1;
case ENUM:
/* TODO: Check when two enum are the same type */
case INT: case FLOAT:
return tp1->letter == tp2->letter;
default:
fputs("internal type error, aborting\n", stderr);
abort();
}
}