ref: 9fdb7c764740da5a852bb02ec407c8b72da8db95
dir: /types.c/
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include "sizes.h"
#include "cc.h"
#define NR_TYPE_HASH 16
Type
*voidtype = &(Type) {
.op = VOID,
.letter = 'W'
},
*pvoidtype = &(Type) {
.op = PTR,
.letter = 'R'
},
*booltype = &(Type) {
.op = INT,
.letter = 'B',
.defined = 1,
.u.size = 0
},
*uchartype = &(Type) {
.op = INT,
.letter = 'M',
.sign = 1,
.defined = 1,
.u.size = 1
},
*chartype = &(Type) {
.op = INT,
.letter = 'C',
.defined = 1,
.u.size = 1
},
*ushortype = &(Type) {
.op = INT,
.letter = 'E',
.defined = 1,
.u.size = 2
},
*shortype = &(Type) {
.op = INT,
.letter = 'K',
.defined = 1,
.u.size = 2
},
*uinttype = &(Type) {
.op = INT,
.letter = 'U',
.sign = 1,
.defined = 1,
.u.size = 3
},
*inttype = &(Type) {
.op = INT,
.letter = 'I',
.defined = 1,
.u.size = 3
},
*longtype = &(Type) {
.op = INT,
.letter = 'L',
.defined = 1,
.u.size = 4
},
*ulongtype = &(Type) {
.op = INT,
.letter = 'Z',
.sign = 1,
.defined = 1,
.u.size = 4
},
*ullongtype = &(Type) {
.op = INT,
.letter = 'O',
.sign = 1,
.defined = 1,
.u.size = 5
},
*llongtype = &(Type) {
.op = INT,
.letter = 'G',
.defined = 1,
.u.size = 5
},
*floattype = &(Type) {
.op = FLOAT,
.letter = 'F',
.defined = 1,
.u.size = 10
},
*doubletype = &(Type) {
.op = FLOAT,
.letter = 'D',
.defined = 1,
.u.size = 11
},
*ldoubletype = &(Type) {
.op = FLOAT,
.letter = 'H',
.defined = 1,
.u.size = 12
};
Type *
ctype(int8_t type, int8_t sign, int8_t size)
{
if (type == CHAR && !sign)
sign = options.charsign;
if (sign == SIGNED)
sign = 0;
if (type == DOUBLE)
type = FLOAT, size += LONG;
switch (type) {
case VOID: return voidtype;
case BOOL: return booltype;
case CHAR: return (sign) ? uchartype : chartype;
case INT: switch (size) {
case 0: return (sign) ? uinttype : inttype;
case SHORT: return (sign) ? ushortype : shortype;
case LONG: return (sign) ? ulongtype : longtype;
case LONG+LONG: return (sign) ? ullongtype : llongtype;
}
case FLOAT: switch (size) {
case 0: return floattype;
case LONG: return doubletype;
case LONG+LONG: return ldoubletype;
}
}
}
Type *
mktype(Type *tp, uint8_t op,
Symbol *sym, uint16_t nelem)
{
static Type *typetab[NR_TYPE_HASH], **tbl;
static uint8_t t;
register Type *bp;
char letter;
if (op == PTR && tp == voidtype)
return pvoidtype;
t = (op ^ (uint8_t) ((unsigned short) tp >> 3))
& NR_TYPE_HASH-1;
tbl = &typetab[t];
if (op != FTN || op != STRUCT || op != UNION || op != ENUM) {
for (bp = *tbl; bp; bp = bp->next) {
if (bp->type == tp && bp->op == op &&
bp->sym == sym && bp->u.nelem == nelem) {
return bp;
}
}
}
switch (op) {
case PTR: letter = 'R'; break;
case FTN: letter = 'F'; break;
case ARY: letter = 'V'; break;
case ENUM: letter = 'E'; break;
case STRUCT: letter = 'S'; break;
default: letter = tp->letter;
}
bp = xmalloc(sizeof(*bp));
bp->next = *tbl;
bp->type = tp;
bp->op = op;
bp->u.nelem = nelem;
bp->sym = sym;
bp->letter = letter;
return *tbl = bp;
}
Type *
qualifier(Type *tp, uint8_t qlf)
{
uint8_t q = tp->op;
if (!qlf)
return tp;
if (q & TQUALIFIER) {
if (q == qlf)
return tp;
tp = tp->type;
qlf |= q;
}
return mktype(tp, qlf|TQUALIFIER, NULL, 0);
}