327 lines
11 KiB
C
327 lines
11 KiB
C
#включить "руси.з"
|
||
|
||
// =====================================================================
|
||
// Механизм отслеживания выделенной памяти для типов
|
||
// =====================================================================
|
||
|
||
стат Type **все_типы = NULL;
|
||
стат цел счётчик_типов = 0;
|
||
стат цел ёмкость_типов = 0;
|
||
|
||
стат пусто отследить_тип(Type *тип) {
|
||
если (счётчик_типов == ёмкость_типов) {
|
||
ёмкость_типов = ёмкость_типов ? ёмкость_типов * 2 : 1024;
|
||
все_типы = realloc(все_типы, ёмкость_типов * размер(Type *));
|
||
}
|
||
все_типы[счётчик_типов++] = тип;
|
||
}
|
||
|
||
пусто free_all_types(пусто) {
|
||
для (цел ш = 0; ш < счётчик_типов; ш++) {
|
||
free(все_типы[ш]);
|
||
}
|
||
free(все_типы);
|
||
|
||
все_типы = NULL;
|
||
счётчик_типов = 0;
|
||
ёмкость_типов = 0;
|
||
}
|
||
// =====================================================================
|
||
|
||
Type *ty_void = &(Type){TY_VOID, 1, 1};
|
||
Type *ty_bool = &(Type){TY_BOOL, 1, 1};
|
||
Type *ty_char = &(Type){TY_CHAR, 1, 1};
|
||
Type *ty_short = &(Type){TY_SHORT, 2, 2};
|
||
Type *ty_int = &(Type){TY_INT, 4, 4};
|
||
Type *ty_long = &(Type){TY_LONG, 8, 8};
|
||
|
||
Type *ty_uchar = &(Type){TY_CHAR, 1, 1, истина};
|
||
Type *ty_ushort = &(Type){TY_SHORT, 2, 2, истина};
|
||
Type *ty_uint = &(Type){TY_INT, 4, 4, истина};
|
||
Type *ty_ulong = &(Type){TY_LONG, 8, 8, истина};
|
||
|
||
Type *ty_float = &(Type){TY_FLOAT, 4, 4};
|
||
Type *ty_double = &(Type){TY_DOUBLE, 8, 8};
|
||
Type *ty_ldouble = &(Type){TY_LDOUBLE, 16, 16};
|
||
|
||
стат Type *выделить_тип(TypeKind вид, цел разм, цел выравн) {
|
||
Type *тип = calloc(1, размер(Type));
|
||
тип->kind = вид;
|
||
тип->size = разм;
|
||
тип->align = выравн;
|
||
|
||
отследить_тип(тип);
|
||
возврат тип;
|
||
}
|
||
|
||
бул is_integer(Type *тип) {
|
||
TypeKind вид = тип->kind;
|
||
возврат вид == TY_BOOL || вид == TY_CHAR || вид == TY_SHORT ||
|
||
вид == TY_INT || вид == TY_LONG || вид == TY_ENUM;
|
||
}
|
||
|
||
бул is_flonum(Type *тип) {
|
||
возврат тип->kind == TY_FLOAT || тип->kind == TY_DOUBLE ||
|
||
тип->kind == TY_LDOUBLE;
|
||
}
|
||
|
||
бул is_numeric(Type *тип) {
|
||
возврат is_integer(тип) || is_flonum(тип);
|
||
}
|
||
|
||
бул is_compatible(Type *т1, Type *т2) {
|
||
если (т1 == т2)
|
||
возврат истина;
|
||
|
||
если (т1->origin)
|
||
возврат is_compatible(т1->origin, т2);
|
||
если (т2->origin)
|
||
возврат is_compatible(т1, т2->origin);
|
||
|
||
если (т1->kind != т2->kind)
|
||
возврат ложь;
|
||
|
||
выбор (т1->kind) {
|
||
случай TY_CHAR:
|
||
случай TY_SHORT:
|
||
случай TY_INT:
|
||
случай TY_LONG:
|
||
возврат т1->is_unsigned == т2->is_unsigned;
|
||
случай TY_FLOAT:
|
||
случай TY_DOUBLE:
|
||
случай TY_LDOUBLE:
|
||
возврат истина;
|
||
случай TY_PTR:
|
||
возврат is_compatible(т1->base, т2->base);
|
||
случай TY_FUNC: {
|
||
если (!is_compatible(т1->return_ty, т2->return_ty))
|
||
возврат ложь;
|
||
если (т1->is_variadic != т2->is_variadic)
|
||
возврат ложь;
|
||
|
||
Type *пар1 = т1->params;
|
||
Type *пар2 = т2->params;
|
||
для (; пар1 && пар2; пар1 = пар1->next, пар2 = пар2->next)
|
||
если (!is_compatible(пар1, пар2))
|
||
возврат ложь;
|
||
|
||
возврат пар1 == NULL && пар2 == NULL;
|
||
}
|
||
случай TY_ARRAY:
|
||
если (!is_compatible(т1->base, т2->base))
|
||
возврат ложь;
|
||
возврат т1->array_len < 0 && т2->array_len < 0 &&
|
||
т1->array_len == т2->array_len;
|
||
}
|
||
возврат ложь;
|
||
}
|
||
|
||
Type *copy_type(Type *тип) {
|
||
Type *копия = calloc(1, размер(Type));
|
||
*копия = *тип;
|
||
копия->origin = тип;
|
||
|
||
отследить_тип(копия);
|
||
возврат копия;
|
||
}
|
||
|
||
Type *pointer_to(Type *база) {
|
||
Type *указ = выделить_тип(TY_PTR, 8, 8);
|
||
указ->base = база;
|
||
указ->is_unsigned = истина;
|
||
возврат указ;
|
||
}
|
||
|
||
Type *func_type(Type *возвр_тип) {
|
||
Type *фн = выделить_тип(TY_FUNC, 1, 1);
|
||
фн->return_ty = возвр_тип;
|
||
возврат фн;
|
||
}
|
||
|
||
Type *array_of(Type *база, цел длина) {
|
||
Type *масс = выделить_тип(TY_ARRAY, база->size * длина, база->align);
|
||
масс->base = база;
|
||
масс->array_len = длина;
|
||
возврат масс;
|
||
}
|
||
|
||
Type *vla_of(Type *база, Node *узел_длины) {
|
||
Type *вла = выделить_тип(TY_VLA, 8, 8);
|
||
вла->base = база;
|
||
вла->vla_len = узел_длины;
|
||
возврат вла;
|
||
}
|
||
|
||
Type *enum_type(пусто) {
|
||
возврат выделить_тип(TY_ENUM, 4, 4);
|
||
}
|
||
|
||
Type *struct_type(пусто) {
|
||
возврат выделить_тип(TY_STRUCT, 0, 1);
|
||
}
|
||
|
||
стат Type *общий_тип(Type *т1, Type *т2) {
|
||
если (т1->base)
|
||
возврат pointer_to(т1->base);
|
||
|
||
если (т1->kind == TY_FUNC)
|
||
возврат pointer_to(т1);
|
||
если (т2->kind == TY_FUNC)
|
||
возврат pointer_to(т2);
|
||
|
||
если (т1->kind == TY_LDOUBLE || т2->kind == TY_LDOUBLE)
|
||
возврат ty_ldouble;
|
||
если (т1->kind == TY_DOUBLE || т2->kind == TY_DOUBLE)
|
||
возврат ty_double;
|
||
если (т1->kind == TY_FLOAT || т2->kind == TY_FLOAT)
|
||
возврат ty_float;
|
||
|
||
если (т1->size < 4)
|
||
т1 = ty_int;
|
||
если (т2->size < 4)
|
||
т2 = ty_int;
|
||
|
||
если (т1->size != т2->size)
|
||
возврат (т1->size < т2->size) ? т2 : т1;
|
||
|
||
если (т2->is_unsigned)
|
||
возврат т2;
|
||
возврат т1;
|
||
}
|
||
|
||
стат пусто арифм_преобразование(Node **лев, Node **прав) {
|
||
Type *общий = общий_тип((*лев)->ty, (*прав)->ty);
|
||
*лев = new_cast(*лев, общий);
|
||
*прав = new_cast(*прав, общий);
|
||
}
|
||
|
||
пусто add_type(Node *узел) {
|
||
если (!узел || узел->ty)
|
||
возврат;
|
||
|
||
add_type(узел->lhs);
|
||
add_type(узел->rhs);
|
||
add_type(узел->cond);
|
||
add_type(узел->then);
|
||
add_type(узел->els);
|
||
add_type(узел->init);
|
||
add_type(узел->inc);
|
||
|
||
для (Node *п = узел->body; п; п = п->next)
|
||
add_type(п);
|
||
для (Node *п = узел->args; п; п = п->next)
|
||
add_type(п);
|
||
|
||
выбор (узел->kind) {
|
||
случай ND_NUM:
|
||
узел->ty = ty_int;
|
||
возврат;
|
||
случай ND_ADD:
|
||
случай ND_SUB:
|
||
случай ND_MUL:
|
||
случай ND_DIV:
|
||
случай ND_MOD:
|
||
случай ND_BITAND:
|
||
случай ND_BITOR:
|
||
случай ND_BITXOR:
|
||
арифм_преобразование(&узел->lhs, &узел->rhs);
|
||
узел->ty = узел->lhs->ty;
|
||
возврат;
|
||
случай ND_NEG: {
|
||
Type *рез_тип = общий_тип(ty_int, узел->lhs->ty);
|
||
узел->lhs = new_cast(узел->lhs, рез_тип);
|
||
узел->ty = рез_тип;
|
||
возврат;
|
||
}
|
||
случай ND_ASSIGN:
|
||
если (узел->lhs->ty->kind == TY_ARRAY)
|
||
error_tok(узел->lhs->tok, "не lvalue");
|
||
если (узел->lhs->ty->kind != TY_STRUCT)
|
||
узел->rhs = new_cast(узел->rhs, узел->lhs->ty);
|
||
узел->ty = узел->lhs->ty;
|
||
возврат;
|
||
случай ND_EQ:
|
||
случай ND_NE:
|
||
случай ND_LT:
|
||
случай ND_LE:
|
||
арифм_преобразование(&узел->lhs, &узел->rhs);
|
||
узел->ty = ty_int;
|
||
возврат;
|
||
случай ND_FUNCALL:
|
||
узел->ty = узел->func_ty->return_ty;
|
||
возврат;
|
||
случай ND_NOT:
|
||
случай ND_LOGOR:
|
||
случай ND_LOGAND:
|
||
узел->ty = ty_int;
|
||
возврат;
|
||
случай ND_BITNOT:
|
||
случай ND_SHL:
|
||
случай ND_SHR:
|
||
узел->ty = узел->lhs->ty;
|
||
возврат;
|
||
случай ND_VAR:
|
||
случай ND_VLA_PTR:
|
||
узел->ty = узел->var->ty;
|
||
возврат;
|
||
случай ND_COND:
|
||
если (узел->then->ty->kind == TY_VOID || узел->els->ty->kind == TY_VOID) {
|
||
узел->ty = ty_void;
|
||
} иначе {
|
||
арифм_преобразование(&узел->then, &узел->els);
|
||
узел->ty = узел->then->ty;
|
||
}
|
||
возврат;
|
||
случай ND_COMMA:
|
||
узел->ty = узел->rhs->ty;
|
||
возврат;
|
||
случай ND_MEMBER:
|
||
узел->ty = узел->member->ty;
|
||
возврат;
|
||
случай ND_ADDR: {
|
||
Type *тип_операнда = узел->lhs->ty;
|
||
если (тип_операнда->kind == TY_ARRAY)
|
||
узел->ty = pointer_to(тип_операнда->base);
|
||
иначе
|
||
узел->ty = pointer_to(тип_операнда);
|
||
возврат;
|
||
}
|
||
случай ND_DEREF:
|
||
если (!узел->lhs->ty->base)
|
||
error_tok(узел->tok, "недопустимое разыменование указателя");
|
||
если (узел->lhs->ty->base->kind == TY_VOID)
|
||
error_tok(узел->tok, "разыменование указателя на void");
|
||
узел->ty = узел->lhs->ty->base;
|
||
возврат;
|
||
случай ND_STMT_EXPR:
|
||
если (узел->body) {
|
||
Node *оп = узел->body;
|
||
пока (оп->next)
|
||
оп = оп->next;
|
||
если (оп->kind == ND_EXPR_STMT) {
|
||
узел->ty = оп->lhs->ty;
|
||
возврат;
|
||
}
|
||
}
|
||
error_tok(узел->tok, "выражение-инструкция, возвращающая void, не поддерживается");
|
||
возврат;
|
||
случай ND_LABEL_VAL:
|
||
узел->ty = pointer_to(ty_void);
|
||
возврат;
|
||
случай ND_CAS:
|
||
add_type(узел->cas_addr);
|
||
add_type(узел->cas_old);
|
||
add_type(узел->cas_new);
|
||
узел->ty = ty_bool;
|
||
если (узел->cas_addr->ty->kind != TY_PTR)
|
||
error_tok(узел->cas_addr->tok, "ожидался указатель");
|
||
если (узел->cas_old->ty->kind != TY_PTR)
|
||
error_tok(узел->cas_old->tok, "ожидался указатель");
|
||
возврат;
|
||
случай ND_EXCH:
|
||
если (узел->lhs->ty->kind != TY_PTR)
|
||
error_tok(узел->cas_addr->tok, "ожидался указатель");
|
||
узел->ty = узел->lhs->ty->base;
|
||
возврат;
|
||
}
|
||
} |