| ... | @@ -1579,6 +1579,8 @@ fn zirCoerceResultPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE | ... | @@ -1579,6 +1579,8 @@ fn zirCoerceResultPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE |
| 1579 | const target = sema.mod.getTarget(); | 1579 | const target = sema.mod.getTarget(); |
| 1580 | const addr_space = target_util.defaultAddressSpace(target, .local); | 1580 | const addr_space = target_util.defaultAddressSpace(target, .local); |
| 1581 | | 1581 | |
| | 1582 | try sema.resolveTypeLayout(block, src, pointee_ty); |
| | 1583 | |
| 1582 | if (Air.refToIndex(ptr)) |ptr_inst| { | 1584 | if (Air.refToIndex(ptr)) |ptr_inst| { |
| 1583 | if (sema.air_instructions.items(.tag)[ptr_inst] == .constant) { | 1585 | if (sema.air_instructions.items(.tag)[ptr_inst] == .constant) { |
| 1584 | const air_datas = sema.air_instructions.items(.data); | 1586 | const air_datas = sema.air_instructions.items(.data); |
| ... | @@ -1885,6 +1887,7 @@ fn zirEnumDecl( | ... | @@ -1885,6 +1887,7 @@ fn zirEnumDecl( |
| 1885 | enum_obj.* = .{ | 1887 | enum_obj.* = .{ |
| 1886 | .owner_decl = new_decl, | 1888 | .owner_decl = new_decl, |
| 1887 | .tag_ty = Type.initTag(.@"null"), | 1889 | .tag_ty = Type.initTag(.@"null"), |
| | 1890 | .tag_ty_inferred = true, |
| 1888 | .fields = .{}, | 1891 | .fields = .{}, |
| 1889 | .values = .{}, | 1892 | .values = .{}, |
| 1890 | .node_offset = src.node_offset, | 1893 | .node_offset = src.node_offset, |
| ... | @@ -1907,6 +1910,7 @@ fn zirEnumDecl( | ... | @@ -1907,6 +1910,7 @@ fn zirEnumDecl( |
| 1907 | // TODO better source location | 1910 | // TODO better source location |
| 1908 | const ty = try sema.resolveType(block, src, tag_type_ref); | 1911 | const ty = try sema.resolveType(block, src, tag_type_ref); |
| 1909 | enum_obj.tag_ty = try ty.copy(new_decl_arena_allocator); | 1912 | enum_obj.tag_ty = try ty.copy(new_decl_arena_allocator); |
| | 1913 | enum_obj.tag_ty_inferred = false; |
| 1910 | } | 1914 | } |
| 1911 | try new_decl.finalizeNewArena(&new_decl_arena); | 1915 | try new_decl.finalizeNewArena(&new_decl_arena); |
| 1912 | return sema.analyzeDeclVal(block, src, new_decl); | 1916 | return sema.analyzeDeclVal(block, src, new_decl); |
| ... | @@ -1956,16 +1960,16 @@ fn zirEnumDecl( | ... | @@ -1956,16 +1960,16 @@ fn zirEnumDecl( |
| 1956 | | 1960 | |
| 1957 | try wip_captures.finalize(); | 1961 | try wip_captures.finalize(); |
| 1958 | | 1962 | |
| 1959 | const tag_ty = blk: { | 1963 | if (tag_type_ref != .none) { |
| 1960 | if (tag_type_ref != .none) { | 1964 | // TODO better source location |
| 1961 | // TODO better source location | 1965 | const ty = try sema.resolveType(block, src, tag_type_ref); |
| 1962 | const ty = try sema.resolveType(block, src, tag_type_ref); | 1966 | enum_obj.tag_ty = try ty.copy(new_decl_arena_allocator); |
| 1963 | break :blk try ty.copy(new_decl_arena_allocator); | 1967 | enum_obj.tag_ty_inferred = false; |
| 1964 | } | 1968 | } else { |
| 1965 | const bits = std.math.log2_int_ceil(usize, fields_len); | 1969 | const bits = std.math.log2_int_ceil(usize, fields_len); |
| 1966 | break :blk try Type.Tag.int_unsigned.create(new_decl_arena_allocator, bits); | 1970 | enum_obj.tag_ty = try Type.Tag.int_unsigned.create(new_decl_arena_allocator, bits); |
| 1967 | }; | 1971 | enum_obj.tag_ty_inferred = true; |
| 1968 | enum_obj.tag_ty = tag_ty; | 1972 | } |
| 1969 | } | 1973 | } |
| 1970 | | 1974 | |
| 1971 | try enum_obj.fields.ensureTotalCapacity(new_decl_arena_allocator, fields_len); | 1975 | try enum_obj.fields.ensureTotalCapacity(new_decl_arena_allocator, fields_len); |
| ... | @@ -2417,13 +2421,13 @@ fn zirAllocExtended( | ... | @@ -2417,13 +2421,13 @@ fn zirAllocExtended( |
| 2417 | try sema.validateVarType(block, ty_src, var_ty, false); | 2421 | try sema.validateVarType(block, ty_src, var_ty, false); |
| 2418 | } | 2422 | } |
| 2419 | const target = sema.mod.getTarget(); | 2423 | const target = sema.mod.getTarget(); |
| | 2424 | try sema.requireRuntimeBlock(block, src); |
| | 2425 | try sema.resolveTypeLayout(block, src, var_ty); |
| 2420 | const ptr_type = try Type.ptr(sema.arena, target, .{ | 2426 | const ptr_type = try Type.ptr(sema.arena, target, .{ |
| 2421 | .pointee_type = var_ty, | 2427 | .pointee_type = var_ty, |
| 2422 | .@"align" = alignment, | 2428 | .@"align" = alignment, |
| 2423 | .@"addrspace" = target_util.defaultAddressSpace(target, .local), | 2429 | .@"addrspace" = target_util.defaultAddressSpace(target, .local), |
| 2424 | }); | 2430 | }); |
| 2425 | try sema.requireRuntimeBlock(block, src); | | |
| 2426 | try sema.resolveTypeLayout(block, src, var_ty); | | |
| 2427 | return block.addTy(.alloc, ptr_type); | 2431 | return block.addTy(.alloc, ptr_type); |
| 2428 | } | 2432 | } |
| 2429 | | 2433 | |
| ... | @@ -21209,6 +21213,182 @@ fn typePtrOrOptionalPtrTy( | ... | @@ -21209,6 +21213,182 @@ fn typePtrOrOptionalPtrTy( |
| 21209 | } | 21213 | } |
| 21210 | } | 21214 | } |
| 21211 | | 21215 | |
| | 21216 | fn typeHasWellDefinedLayout(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) CompileError!bool { |
| | 21217 | return switch (ty.tag()) { |
| | 21218 | .u1, |
| | 21219 | .u8, |
| | 21220 | .i8, |
| | 21221 | .u16, |
| | 21222 | .i16, |
| | 21223 | .u32, |
| | 21224 | .i32, |
| | 21225 | .u64, |
| | 21226 | .i64, |
| | 21227 | .u128, |
| | 21228 | .i128, |
| | 21229 | .usize, |
| | 21230 | .isize, |
| | 21231 | .c_short, |
| | 21232 | .c_ushort, |
| | 21233 | .c_int, |
| | 21234 | .c_uint, |
| | 21235 | .c_long, |
| | 21236 | .c_ulong, |
| | 21237 | .c_longlong, |
| | 21238 | .c_ulonglong, |
| | 21239 | .c_longdouble, |
| | 21240 | .f16, |
| | 21241 | .f32, |
| | 21242 | .f64, |
| | 21243 | .f80, |
| | 21244 | .f128, |
| | 21245 | .bool, |
| | 21246 | .void, |
| | 21247 | .manyptr_u8, |
| | 21248 | .manyptr_const_u8, |
| | 21249 | .manyptr_const_u8_sentinel_0, |
| | 21250 | .anyerror_void_error_union, |
| | 21251 | .empty_struct_literal, |
| | 21252 | .empty_struct, |
| | 21253 | .array_u8, |
| | 21254 | .array_u8_sentinel_0, |
| | 21255 | .int_signed, |
| | 21256 | .int_unsigned, |
| | 21257 | .pointer, |
| | 21258 | .single_const_pointer, |
| | 21259 | .single_mut_pointer, |
| | 21260 | .many_const_pointer, |
| | 21261 | .many_mut_pointer, |
| | 21262 | .c_const_pointer, |
| | 21263 | .c_mut_pointer, |
| | 21264 | .single_const_pointer_to_comptime_int, |
| | 21265 | .enum_numbered, |
| | 21266 | => true, |
| | 21267 | |
| | 21268 | .anyopaque, |
| | 21269 | .anyerror, |
| | 21270 | .noreturn, |
| | 21271 | .@"null", |
| | 21272 | .@"anyframe", |
| | 21273 | .@"undefined", |
| | 21274 | .atomic_order, |
| | 21275 | .atomic_rmw_op, |
| | 21276 | .calling_convention, |
| | 21277 | .address_space, |
| | 21278 | .float_mode, |
| | 21279 | .reduce_op, |
| | 21280 | .call_options, |
| | 21281 | .prefetch_options, |
| | 21282 | .export_options, |
| | 21283 | .extern_options, |
| | 21284 | .error_set, |
| | 21285 | .error_set_single, |
| | 21286 | .error_set_inferred, |
| | 21287 | .error_set_merged, |
| | 21288 | .@"opaque", |
| | 21289 | .generic_poison, |
| | 21290 | .type, |
| | 21291 | .comptime_int, |
| | 21292 | .comptime_float, |
| | 21293 | .enum_literal, |
| | 21294 | .type_info, |
| | 21295 | // These are function bodies, not function pointers. |
| | 21296 | .fn_noreturn_no_args, |
| | 21297 | .fn_void_no_args, |
| | 21298 | .fn_naked_noreturn_no_args, |
| | 21299 | .fn_ccc_void_no_args, |
| | 21300 | .function, |
| | 21301 | .const_slice_u8, |
| | 21302 | .const_slice_u8_sentinel_0, |
| | 21303 | .const_slice, |
| | 21304 | .mut_slice, |
| | 21305 | .enum_simple, |
| | 21306 | .error_union, |
| | 21307 | .anyframe_T, |
| | 21308 | .tuple, |
| | 21309 | .anon_struct, |
| | 21310 | => false, |
| | 21311 | |
| | 21312 | .enum_full, |
| | 21313 | .enum_nonexhaustive, |
| | 21314 | => !ty.cast(Type.Payload.EnumFull).?.data.tag_ty_inferred, |
| | 21315 | |
| | 21316 | .var_args_param => unreachable, |
| | 21317 | .inferred_alloc_mut => unreachable, |
| | 21318 | .inferred_alloc_const => unreachable, |
| | 21319 | .bound_fn => unreachable, |
| | 21320 | |
| | 21321 | .array, |
| | 21322 | .array_sentinel, |
| | 21323 | .vector, |
| | 21324 | => sema.typeHasWellDefinedLayout(block, src, ty.childType()), |
| | 21325 | |
| | 21326 | .optional, |
| | 21327 | .optional_single_mut_pointer, |
| | 21328 | .optional_single_const_pointer, |
| | 21329 | => blk: { |
| | 21330 | var buf: Type.Payload.ElemType = undefined; |
| | 21331 | break :blk sema.typeHasWellDefinedLayout(block, src, ty.optionalChild(&buf)); |
| | 21332 | }, |
| | 21333 | |
| | 21334 | .@"struct" => { |
| | 21335 | const struct_obj = ty.castTag(.@"struct").?.data; |
| | 21336 | if (struct_obj.layout == .Auto) { |
| | 21337 | struct_obj.has_well_defined_layout = .no; |
| | 21338 | return false; |
| | 21339 | } |
| | 21340 | switch (struct_obj.has_well_defined_layout) { |
| | 21341 | .no => return false, |
| | 21342 | .yes, .wip => return true, |
| | 21343 | .unknown => { |
| | 21344 | if (struct_obj.status == .field_types_wip) |
| | 21345 | return true; |
| | 21346 | |
| | 21347 | try sema.resolveTypeFieldsStruct(block, src, ty, struct_obj); |
| | 21348 | |
| | 21349 | struct_obj.has_well_defined_layout = .wip; |
| | 21350 | for (struct_obj.fields.values()) |field| { |
| | 21351 | if (!(try sema.typeHasWellDefinedLayout(block, src, field.ty))) { |
| | 21352 | struct_obj.has_well_defined_layout = .no; |
| | 21353 | return false; |
| | 21354 | } |
| | 21355 | } |
| | 21356 | struct_obj.has_well_defined_layout = .yes; |
| | 21357 | return true; |
| | 21358 | }, |
| | 21359 | } |
| | 21360 | }, |
| | 21361 | |
| | 21362 | .@"union", .union_tagged => { |
| | 21363 | const union_obj = ty.cast(Type.Payload.Union).?.data; |
| | 21364 | if (union_obj.layout == .Auto) { |
| | 21365 | union_obj.has_well_defined_layout = .no; |
| | 21366 | return false; |
| | 21367 | } |
| | 21368 | switch (union_obj.has_well_defined_layout) { |
| | 21369 | .no => return false, |
| | 21370 | .yes, .wip => return true, |
| | 21371 | .unknown => { |
| | 21372 | if (union_obj.status == .field_types_wip) |
| | 21373 | return true; |
| | 21374 | |
| | 21375 | try sema.resolveTypeFieldsUnion(block, src, ty, union_obj); |
| | 21376 | |
| | 21377 | union_obj.has_well_defined_layout = .wip; |
| | 21378 | for (union_obj.fields.values()) |field| { |
| | 21379 | if (!(try sema.typeHasWellDefinedLayout(block, src, field.ty))) { |
| | 21380 | union_obj.has_well_defined_layout = .no; |
| | 21381 | return false; |
| | 21382 | } |
| | 21383 | } |
| | 21384 | union_obj.has_well_defined_layout = .yes; |
| | 21385 | return true; |
| | 21386 | }, |
| | 21387 | } |
| | 21388 | }, |
| | 21389 | }; |
| | 21390 | } |
| | 21391 | |
| 21212 | /// `generic_poison` will return false. | 21392 | /// `generic_poison` will return false. |
| 21213 | /// This function returns false negatives when structs and unions are having their | 21393 | /// This function returns false negatives when structs and unions are having their |
| 21214 | /// field types resolved. | 21394 | /// field types resolved. |
| ... | @@ -21412,6 +21592,12 @@ pub fn typeHasRuntimeBits(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) | ... | @@ -21412,6 +21592,12 @@ pub fn typeHasRuntimeBits(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) |
| 21412 | return true; | 21592 | return true; |
| 21413 | } | 21593 | } |
| 21414 | | 21594 | |
| | 21595 | fn typeAbiSize(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) !u64 { |
| | 21596 | try sema.resolveTypeLayout(block, src, ty); |
| | 21597 | const target = sema.mod.getTarget(); |
| | 21598 | return ty.abiSize(target); |
| | 21599 | } |
| | 21600 | |
| 21415 | fn typeAbiAlignment(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) !u32 { | 21601 | fn typeAbiAlignment(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) !u32 { |
| 21416 | try sema.resolveTypeLayout(block, src, ty); | 21602 | try sema.resolveTypeLayout(block, src, ty); |
| 21417 | const target = sema.mod.getTarget(); | 21603 | const target = sema.mod.getTarget(); |