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); }
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); }