int type_rank(Type *type) { int rank = type_ranks[(int)type->kind]; assert(rank != 0); return(rank); }
Type *unsigned_type(Type *type) { switch (type->kind) { case TYPE_BOOL: return(type_bool); case TYPE_CHAR: case TYPE_SCHAR: case TYPE_UCHAR: return(type_uchar); case TYPE_SHORT: case TYPE_USHORT: return(type_ushort); case TYPE_INT: case TYPE_UINT: return(type_uint); case TYPE_LONG: case TYPE_ULONG: return(type_ulong); case TYPE_LLONG: case TYPE_ULLONG: return(type_ullong); default: assert(false); return(null); } }
Type *type_func(Type *[] params_a, int num_params, Type *ret, bool intrinsic, bool has_varargs, Type *varargs_type) { fixed(Type ** @params = params_a) { return(type_func(@params, num_params, ret, intrinsic, has_varargs, varargs_type)); } }
Type *type_array(Type * @base, int num_elems, bool incomplete_elems) { var hash = Map.hash_mix(Map.hash_ptr(@base), Map.hash_uint64((ulong)num_elems)); var key = hash != 0 ? hash : 1; var cached = (CachedArrayType *)cached_array_types.map_get_from_uint64(key); if (!incomplete_elems) { for (CachedArrayType *it = cached; it != null; it = it->next) { Type *t = it->type; if (t->@base == @base && t->num_elems == num_elems) { return(t); } } } complete_type(@base); Type *type = type_alloc(TYPE_ARRAY); type->nonmodifiable = @base->nonmodifiable; type->size = num_elems * type_sizeof(@base); type->align = type_alignof(@base); type->@base = @base; type->num_elems = num_elems; type->incomplete_elems = incomplete_elems; if (!incomplete_elems) { CachedArrayType *new_cached = xmalloc <CachedArrayType>(); new_cached->type = type; new_cached->next = cached; cached_array_types.map_put_from_uint64(key, new_cached); } return(type); }
Type *type_complete_union(Type *type, TypeField *fields, int num_fields) { assert(type->kind == TYPE_COMPLETING); type->kind = TYPE_UNION; type->size = 0; type->align = 0; bool nonmodifiable = false; var new_fields = Buffer <TypeField> .Create(); for (var it = fields; it != fields + num_fields; it++) { assert(it->type->kind > TYPE_COMPLETING); if (it->name != null) { it->offset = 0; new_fields.Add(it); } else { add_type_fields(&new_fields, it->type, 0); } type->align = MAX(type->align, type_alignof(it->type)); type->size = MAX(type->size, type_sizeof(it->type)); nonmodifiable = it->type->nonmodifiable || nonmodifiable; } type->size = ALIGN_UP(type->size, type->align); type->aggregate.fields = new_fields; type->aggregate.num_fields = new_fields.count; type->nonmodifiable = nonmodifiable; return(type); }
Type *type_complete_struct(Type *type, TypeField *fields, int num_fields) { assert(type->kind == TYPE_COMPLETING); type->kind = TYPE_STRUCT; type->size = 0; type->align = 0; bool nonmodifiable = false; long field_sizes = 0; var new_fields = Buffer <TypeField> .Create(); for (var it = fields; it != fields + num_fields; it++) { assert(IS_POW2(type_alignof(it->type))); if (it->name != null) { it->offset = type->size; new_fields.Add(it); } else { add_type_fields(&new_fields, it->type, type->size); } field_sizes += type_sizeof(it->type); type->align = MAX(type->align, type_alignof(it->type)); type->size = type_sizeof(it->type) + ALIGN_UP(type->size, type_alignof(it->type)); nonmodifiable = it->type->nonmodifiable || nonmodifiable; } type->size = ALIGN_UP(type->size, type->align); type->padding = type->size - field_sizes; type->aggregate.fields = new_fields; type->aggregate.num_fields = new_fields.count; type->nonmodifiable = nonmodifiable; return(type); }
void type_complete_tuple(Type *type, Type **fields, int num_fields) { type->kind = TYPE_TUPLE; type->size = 0; type->align = 0; bool nonmodifiable = false; long elem_sizes = 0; var new_fields = Buffer <TypeField> .Create(); for (int i = 0; i < num_fields; i++) { Type *field = fields[i]; complete_type(fields[i]); assert(IS_POW2(type_alignof(field))); char *name = ("_" + i).ToPtr(); var new_field = new TypeField { name = _I(name), type = fields[i], offset = type->size, }; new_fields.Add(new_field); elem_sizes += type_sizeof(field); type->align = MAX(type->align, type_alignof(field)); type->size = type_sizeof(field) + ALIGN_UP(type->size, type_alignof(field)); nonmodifiable = field->nonmodifiable || nonmodifiable; } type->size = ALIGN_UP(type->size, type->align); type->padding = type->size - elem_sizes; type->aggregate.fields = new_fields; type->aggregate.num_fields = new_fields.count; type->nonmodifiable = nonmodifiable; }
Type *type_tuple(Type **fields, int num_fields) { int fields_size = num_fields * PTR_SIZE; var hash = Map.hash_bytes(fields, fields_size); var key = hash != 0 ? hash : 1ul; var cached = (TypeLink *)cached_tuple_types.map_get_from_uint64(key); for (TypeLink *it = cached; it != null; it = it->next) { Type *cached_type = it->type; if (cached_type->aggregate.num_fields == num_fields) { for (int i = 0; i < num_fields; i++) { if (cached_type->aggregate.fields[i].type != fields[i]) { goto next; } } return(cached_type); } next :; } Type *type = type_alloc(TYPE_TUPLE); type_complete_tuple(type, fields, num_fields); TypeLink *new_cached = xmalloc <TypeLink>(); new_cached->type = type; new_cached->next = cached; cached_tuple_types.map_put_from_uint64(key, new_cached); tuple_types->Add(type); return(type); }
void init_builtin_type(Type *type) { type->typeid = next_typeid++; register_typeid(type); type->size = type_metrics[(int)type->kind].size; type->align = type_metrics[(int)type->kind].align; }
Type *unqualify_ptr_type(Type *type) { if (type->kind == TYPE_PTR) { type = type_ptr(unqualify_type(type->@base)); } return(type); }
Type *qualify_type(Type *type, Type *qual) { type = unqualify_type(type); while (qual->kind == TYPE_CONST) { type = type_const(type); qual = qual->@base; } return(type); }
Type *type_enum(Sym *sym, Type * @base) { Type *type = type_alloc(TYPE_ENUM); type->sym = sym; type->@base = @base; type->size = type_int->size; type->align = type_int->align; return(type); }
Type *unqualify_type(Type *type) { if (type->kind == TYPE_CONST) { return(type->@base); } else { return(type); } }
Type *aggregate_item_field_type_from_name(Type *type, char *name) { assert(is_aggregate_type(type)); int index = aggregate_item_field_index(type, name); if (index < 0) { return(null); } return(aggregate_item_field_type_from_index(type, index)); }
void add_type_fields(Buffer <TypeField> *fields, Type *type, long offset) //TypeField** { assert(type->kind == TYPE_STRUCT || type->kind == TYPE_UNION); for (var i = 0; i < type->aggregate.num_fields; i++) { TypeField *field = &type->aggregate.fields[i]; fields->Add(new TypeField { name = field->name, type = field->type, offset = (field->offset + offset) }); } }
int aggregate_item_field_index(Type *type, char *name) { assert(is_aggregate_type(type)); for (int i = 0; i < type->aggregate.num_fields; i++) { if (type->aggregate.fields[i].name == name) { return(i); } } return(-1); }
// TODO: This probably shouldn't use an O(n^2) algorithm bool has_duplicate_fields(Type *type) { for (var i = 0; i < type->aggregate.num_fields; i++) { for (var j = i + 1; j < type->aggregate.num_fields; j++) { if (type->aggregate.fields[i].name == type->aggregate.fields[j].name) { return(true); } } } return(false); }
Type *type_ptr(Type * @base) { var type = cached_ptr_types.map_get <Type>(@base); if (type == null) { type = type_alloc(TYPE_PTR); type->size = type_metrics[(int)TYPE_PTR].size; type->align = type_metrics[(int)TYPE_PTR].align; type->@base = @base; cached_ptr_types.map_put(@base, type); } return(type); }
bool is_signed_type(Type *type) { switch (type->kind) { case TYPE_CHAR: return(type_metrics[(int)TYPE_CHAR].sign); case TYPE_SCHAR: case TYPE_SHORT: case TYPE_INT: case TYPE_LONG: case TYPE_LLONG: return(true); default: return(false); } }
Type *type_const(Type * @base) { if (@base->kind == TYPE_CONST) { return(@base); } Type *type = cached_const_types.map_get <Type>(@base); if (type == null) { complete_type(@base); type = type_alloc(TYPE_CONST); type->nonmodifiable = true; type->size = @base->size; type->align = @base->align; type->@base = @base; cached_const_types.map_put(@base, type); } return(type); }
void init_builtin_types() { init_builtin_type(type_void); init_builtin_type(type_bool); init_builtin_type(type_char); init_builtin_type(type_uchar); init_builtin_type(type_schar); init_builtin_type(type_short); init_builtin_type(type_ushort); init_builtin_type(type_int); init_builtin_type(type_uint); init_builtin_type(type_long); init_builtin_type(type_ulong); init_builtin_type(type_llong); init_builtin_type(type_ullong); init_builtin_type(type_float); init_builtin_type(type_double); type_char_ptr = type_ptr(type_char); type_alloc_func = type_func(new [] { type_usize, type_usize }, 2, type_ptr(type_void), false, false, type_void); }
Type *type_func(Type ** @params, int num_params, Type *ret, bool intrinsic, bool has_varargs, Type *varargs_type) { var params_size = num_params * PTR_SIZE; var hash = Map.hash_mix(Map.hash_bytes(@params, params_size), Map.hash_ptr(ret)); var key = hash != 0 ? hash : 1; var cached = (TypeLink *)cached_func_types.map_get_from_uint64(key); for (TypeLink *it = cached; it != null; it = it->next) { Type *type1 = it->type; if (type1->func.num_params == num_params && type1->func.ret == ret && type1->func.intrinsic == intrinsic && type1->func.has_varargs == has_varargs && type1->func.varargs_type == varargs_type) { if (memcmp(type1->func.@params, @params, num_params)) { return(type1); } } } Type *type = type_alloc(TYPE_FUNC); type->size = type_metrics[(int)TYPE_PTR].size; type->align = type_metrics[(int)TYPE_PTR].align; type->func.@params = (Type **)memdup(@params, params_size); type->func.num_params = num_params; type->func.intrinsic = intrinsic; type->func.has_varargs = has_varargs; type->func.varargs_type = varargs_type; type->func.ret = ret; TypeLink *new_cached = xmalloc <TypeLink>(); new_cached->type = type; new_cached->next = cached; cached_func_types.map_put_from_uint64(key, new_cached); return(type); }
bool is_ptr_like_type(Type *type) { return(type != null && type->kind == TYPE_PTR || type->kind == TYPE_FUNC); }
bool is_incomplete_array_type(Type *type) { return(type != null && is_array_type(type) && type->num_elems == 0); }
bool is_array_type(Type *type) { return(type != null && type->kind == TYPE_ARRAY); }
long type_alignof(Type *type) { assert(type->kind > TYPE_COMPLETING); assert(IS_POW2(type->align)); return(type->align); }
bool is_const_type(Type *type) { return(type != null && type->kind == TYPE_CONST); }
void register_typeid(Type *type) { typeid_map.map_put((void *)type->typeid, type); }
long type_sizeof(Type *type) { assert(type->kind > TYPE_COMPLETING); return(type->size); }
Type *aggregate_item_field_type_from_index(Type *type, int index) { assert(is_aggregate_type(type)); assert(0 <= index && index < (int)type->aggregate.num_fields); return(type->aggregate.fields[index].type); }