authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-02-28 19:22:16-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-02-28 19:22:16-07:00
log157f66ec077ad02f08891bec1a426c0ffef98e09
tree75b207ed6ccbbd2af83a338e09b86bc8de2965c4
parenta7ca40b2817dbf3f2085141f32f20f431707391b

Sema: fix pointer type hash and equality functions

Several issues with pointer types are fixed: Prior to this commit, Zig would not canonicalize a pointer type with an explicit alignment to alignment=0 if it matched the pointee ABI alignment. In order to fix this, `Type.ptr` now takes a Target parameter. I also moved the host_size canonicalization to `Type.ptr` since target is now available. Similarly, is_allowzero in the case of C pointers is now treated as a canonicalization done by the function rather than a precondition. in-memory coercion for pointers now properly checks ABI alignment of pointee types instead of incorrectly treating the 0 value as an alignment. Type equality is completely reworked based on the tag() rather than the zigTypeTag(). It's still semantically based on zigTypeTag() but that knowledge is implied rather than dictating the control flow of the logic. Importantly, this fixes cases for opaques, structs, tuples, enums, and unions, where type equality was incorrectly returning based on whether the tag() values were equal. Additionally, pointer type equality now takes into account alignment. Because we canonicalize non-zero alignment which equals pointee type ABI alignment to alignment=0, this now can be a simple integer comparison. Type hashing is implemented for pointers and floats. Array types now additionally hash their sentinels. This regressed some behavior tests that were passing but only because of bugs regarding type equality. The C backend has a noticeable problem with lowering differently-aligned pointers (particularly slices) as the same type, causing C compilation errors due to duplicate declarations.

7 files changed, 492 insertions(+), 267 deletions(-)

src/Sema.zig+126-77
...@@ -1555,7 +1555,8 @@ fn zirCoerceResultPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE...@@ -1555,7 +1555,8 @@ fn zirCoerceResultPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE
1555 const bin_inst = sema.code.instructions.items(.data)[inst].bin;1555 const bin_inst = sema.code.instructions.items(.data)[inst].bin;
1556 const pointee_ty = try sema.resolveType(block, src, bin_inst.lhs);1556 const pointee_ty = try sema.resolveType(block, src, bin_inst.lhs);
1557 const ptr = sema.resolveInst(bin_inst.rhs);1557 const ptr = sema.resolveInst(bin_inst.rhs);
1558 const addr_space = target_util.defaultAddressSpace(sema.mod.getTarget(), .local);1558 const target = sema.mod.getTarget();
1559 const addr_space = target_util.defaultAddressSpace(target, .local);
15591560
1560 if (Air.refToIndex(ptr)) |ptr_inst| {1561 if (Air.refToIndex(ptr)) |ptr_inst| {
1561 if (sema.air_instructions.items(.tag)[ptr_inst] == .constant) {1562 if (sema.air_instructions.items(.tag)[ptr_inst] == .constant) {
...@@ -1575,7 +1576,7 @@ fn zirCoerceResultPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE...@@ -1575,7 +1576,7 @@ fn zirCoerceResultPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE
1575 try inferred_alloc.stored_inst_list.append(sema.arena, operand);1576 try inferred_alloc.stored_inst_list.append(sema.arena, operand);
15761577
1577 try sema.requireRuntimeBlock(block, src);1578 try sema.requireRuntimeBlock(block, src);
1578 const ptr_ty = try Type.ptr(sema.arena, .{1579 const ptr_ty = try Type.ptr(sema.arena, target, .{
1579 .pointee_type = pointee_ty,1580 .pointee_type = pointee_ty,
1580 .@"align" = inferred_alloc.alignment,1581 .@"align" = inferred_alloc.alignment,
1581 .@"addrspace" = addr_space,1582 .@"addrspace" = addr_space,
...@@ -1593,7 +1594,7 @@ fn zirCoerceResultPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE...@@ -1593,7 +1594,7 @@ fn zirCoerceResultPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE
1593 try pointee_ty.copy(anon_decl.arena()),1594 try pointee_ty.copy(anon_decl.arena()),
1594 Value.undef,1595 Value.undef,
1595 );1596 );
1596 const ptr_ty = try Type.ptr(sema.arena, .{1597 const ptr_ty = try Type.ptr(sema.arena, target, .{
1597 .pointee_type = pointee_ty,1598 .pointee_type = pointee_ty,
1598 .@"align" = iac.data.alignment,1599 .@"align" = iac.data.alignment,
1599 .@"addrspace" = addr_space,1600 .@"addrspace" = addr_space,
...@@ -1642,7 +1643,7 @@ fn zirCoerceResultPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE...@@ -1642,7 +1643,7 @@ fn zirCoerceResultPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE
1642 }1643 }
1643 }1644 }
16441645
1645 const ptr_ty = try Type.ptr(sema.arena, .{1646 const ptr_ty = try Type.ptr(sema.arena, target, .{
1646 .pointee_type = pointee_ty,1647 .pointee_type = pointee_ty,
1647 .@"addrspace" = addr_space,1648 .@"addrspace" = addr_space,
1648 });1649 });
...@@ -1663,7 +1664,7 @@ fn zirCoerceResultPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE...@@ -1663,7 +1664,7 @@ fn zirCoerceResultPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE
1663 }1664 }
1664 const ty_op = air_datas[trash_inst].ty_op;1665 const ty_op = air_datas[trash_inst].ty_op;
1665 const operand_ty = sema.getTmpAir().typeOf(ty_op.operand);1666 const operand_ty = sema.getTmpAir().typeOf(ty_op.operand);
1666 const ptr_operand_ty = try Type.ptr(sema.arena, .{1667 const ptr_operand_ty = try Type.ptr(sema.arena, target, .{
1667 .pointee_type = operand_ty,1668 .pointee_type = operand_ty,
1668 .@"addrspace" = addr_space,1669 .@"addrspace" = addr_space,
1669 });1670 });
...@@ -2225,9 +2226,10 @@ fn zirRetPtr(...@@ -2225,9 +2226,10 @@ fn zirRetPtr(
2225 return sema.analyzeComptimeAlloc(block, fn_ret_ty, 0, src);2226 return sema.analyzeComptimeAlloc(block, fn_ret_ty, 0, src);
2226 }2227 }
22272228
2228 const ptr_type = try Type.ptr(sema.arena, .{2229 const target = sema.mod.getTarget();
2230 const ptr_type = try Type.ptr(sema.arena, target, .{
2229 .pointee_type = sema.fn_ret_ty,2231 .pointee_type = sema.fn_ret_ty,
2230 .@"addrspace" = target_util.defaultAddressSpace(sema.mod.getTarget(), .local),2232 .@"addrspace" = target_util.defaultAddressSpace(target, .local),
2231 });2233 });
22322234
2233 if (block.inlining != null) {2235 if (block.inlining != null) {
...@@ -2389,10 +2391,11 @@ fn zirAllocExtended(...@@ -2389,10 +2391,11 @@ fn zirAllocExtended(
2389 if (!small.is_const) {2391 if (!small.is_const) {
2390 try sema.validateVarType(block, ty_src, var_ty, false);2392 try sema.validateVarType(block, ty_src, var_ty, false);
2391 }2393 }
2392 const ptr_type = try Type.ptr(sema.arena, .{2394 const target = sema.mod.getTarget();
2395 const ptr_type = try Type.ptr(sema.arena, target, .{
2393 .pointee_type = var_ty,2396 .pointee_type = var_ty,
2394 .@"align" = alignment,2397 .@"align" = alignment,
2395 .@"addrspace" = target_util.defaultAddressSpace(sema.mod.getTarget(), .local),2398 .@"addrspace" = target_util.defaultAddressSpace(target, .local),
2396 });2399 });
2397 try sema.requireRuntimeBlock(block, src);2400 try sema.requireRuntimeBlock(block, src);
2398 try sema.resolveTypeLayout(block, src, var_ty);2401 try sema.resolveTypeLayout(block, src, var_ty);
...@@ -2450,9 +2453,10 @@ fn zirAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I...@@ -2450,9 +2453,10 @@ fn zirAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I
2450 if (block.is_comptime) {2453 if (block.is_comptime) {
2451 return sema.analyzeComptimeAlloc(block, var_ty, 0, ty_src);2454 return sema.analyzeComptimeAlloc(block, var_ty, 0, ty_src);
2452 }2455 }
2453 const ptr_type = try Type.ptr(sema.arena, .{2456 const target = sema.mod.getTarget();
2457 const ptr_type = try Type.ptr(sema.arena, target, .{
2454 .pointee_type = var_ty,2458 .pointee_type = var_ty,
2455 .@"addrspace" = target_util.defaultAddressSpace(sema.mod.getTarget(), .local),2459 .@"addrspace" = target_util.defaultAddressSpace(target, .local),
2456 });2460 });
2457 try sema.requireRuntimeBlock(block, var_decl_src);2461 try sema.requireRuntimeBlock(block, var_decl_src);
2458 try sema.resolveTypeLayout(block, ty_src, var_ty);2462 try sema.resolveTypeLayout(block, ty_src, var_ty);
...@@ -2471,9 +2475,10 @@ fn zirAllocMut(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -2471,9 +2475,10 @@ fn zirAllocMut(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
2471 return sema.analyzeComptimeAlloc(block, var_ty, 0, ty_src);2475 return sema.analyzeComptimeAlloc(block, var_ty, 0, ty_src);
2472 }2476 }
2473 try sema.validateVarType(block, ty_src, var_ty, false);2477 try sema.validateVarType(block, ty_src, var_ty, false);
2474 const ptr_type = try Type.ptr(sema.arena, .{2478 const target = sema.mod.getTarget();
2479 const ptr_type = try Type.ptr(sema.arena, target, .{
2475 .pointee_type = var_ty,2480 .pointee_type = var_ty,
2476 .@"addrspace" = target_util.defaultAddressSpace(sema.mod.getTarget(), .local),2481 .@"addrspace" = target_util.defaultAddressSpace(target, .local),
2477 });2482 });
2478 try sema.requireRuntimeBlock(block, var_decl_src);2483 try sema.requireRuntimeBlock(block, var_decl_src);
2479 try sema.resolveTypeLayout(block, ty_src, var_ty);2484 try sema.resolveTypeLayout(block, ty_src, var_ty);
...@@ -2542,7 +2547,7 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com...@@ -2542,7 +2547,7 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com
2542 try sema.mod.declareDeclDependency(sema.owner_decl, decl);2547 try sema.mod.declareDeclDependency(sema.owner_decl, decl);
25432548
2544 const final_elem_ty = try decl.ty.copy(sema.arena);2549 const final_elem_ty = try decl.ty.copy(sema.arena);
2545 const final_ptr_ty = try Type.ptr(sema.arena, .{2550 const final_ptr_ty = try Type.ptr(sema.arena, target, .{
2546 .pointee_type = final_elem_ty,2551 .pointee_type = final_elem_ty,
2547 .mutable = var_is_mut,2552 .mutable = var_is_mut,
2548 .@"align" = iac.data.alignment,2553 .@"align" = iac.data.alignment,
...@@ -2565,7 +2570,7 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com...@@ -2565,7 +2570,7 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com
2565 const peer_inst_list = inferred_alloc.data.stored_inst_list.items;2570 const peer_inst_list = inferred_alloc.data.stored_inst_list.items;
2566 const final_elem_ty = try sema.resolvePeerTypes(block, ty_src, peer_inst_list, .none);2571 const final_elem_ty = try sema.resolvePeerTypes(block, ty_src, peer_inst_list, .none);
25672572
2568 const final_ptr_ty = try Type.ptr(sema.arena, .{2573 const final_ptr_ty = try Type.ptr(sema.arena, target, .{
2569 .pointee_type = final_elem_ty,2574 .pointee_type = final_elem_ty,
2570 .mutable = var_is_mut,2575 .mutable = var_is_mut,
2571 .@"align" = inferred_alloc.data.alignment,2576 .@"align" = inferred_alloc.data.alignment,
...@@ -3335,10 +3340,11 @@ fn storeToInferredAlloc(...@@ -3335,10 +3340,11 @@ fn storeToInferredAlloc(
3335 // for the inferred allocation.3340 // for the inferred allocation.
3336 try inferred_alloc.data.stored_inst_list.append(sema.arena, operand);3341 try inferred_alloc.data.stored_inst_list.append(sema.arena, operand);
3337 // Create a runtime bitcast instruction with exactly the type the pointer wants.3342 // Create a runtime bitcast instruction with exactly the type the pointer wants.
3338 const ptr_ty = try Type.ptr(sema.arena, .{3343 const target = sema.mod.getTarget();
3344 const ptr_ty = try Type.ptr(sema.arena, target, .{
3339 .pointee_type = operand_ty,3345 .pointee_type = operand_ty,
3340 .@"align" = inferred_alloc.data.alignment,3346 .@"align" = inferred_alloc.data.alignment,
3341 .@"addrspace" = target_util.defaultAddressSpace(sema.mod.getTarget(), .local),3347 .@"addrspace" = target_util.defaultAddressSpace(target, .local),
3342 });3348 });
3343 const bitcasted_ptr = try block.addBitCast(ptr_ty, ptr);3349 const bitcasted_ptr = try block.addBitCast(ptr_ty, ptr);
3344 return sema.storePtr(block, src, bitcasted_ptr, operand);3350 return sema.storePtr(block, src, bitcasted_ptr, operand);
...@@ -5444,7 +5450,8 @@ fn analyzeOptionalPayloadPtr(...@@ -5444,7 +5450,8 @@ fn analyzeOptionalPayloadPtr(
5444 }5450 }
54455451
5446 const child_type = try opt_type.optionalChildAlloc(sema.arena);5452 const child_type = try opt_type.optionalChildAlloc(sema.arena);
5447 const child_pointer = try Type.ptr(sema.arena, .{5453 const target = sema.mod.getTarget();
5454 const child_pointer = try Type.ptr(sema.arena, target, .{
5448 .pointee_type = child_type,5455 .pointee_type = child_type,
5449 .mutable = !optional_ptr_ty.isConstPtr(),5456 .mutable = !optional_ptr_ty.isConstPtr(),
5450 .@"addrspace" = optional_ptr_ty.ptrAddressSpace(),5457 .@"addrspace" = optional_ptr_ty.ptrAddressSpace(),
...@@ -5509,7 +5516,8 @@ fn zirOptionalPayload(...@@ -5509,7 +5516,8 @@ fn zirOptionalPayload(
5509 return sema.failWithExpectedOptionalType(block, src, operand_ty);5516 return sema.failWithExpectedOptionalType(block, src, operand_ty);
5510 }5517 }
5511 const ptr_info = operand_ty.ptrInfo().data;5518 const ptr_info = operand_ty.ptrInfo().data;
5512 break :t try Type.ptr(sema.arena, .{5519 const target = sema.mod.getTarget();
5520 break :t try Type.ptr(sema.arena, target, .{
5513 .pointee_type = try ptr_info.pointee_type.copy(sema.arena),5521 .pointee_type = try ptr_info.pointee_type.copy(sema.arena),
5514 .@"align" = ptr_info.@"align",5522 .@"align" = ptr_info.@"align",
5515 .@"addrspace" = ptr_info.@"addrspace",5523 .@"addrspace" = ptr_info.@"addrspace",
...@@ -5607,7 +5615,8 @@ fn analyzeErrUnionPayloadPtr(...@@ -5607,7 +5615,8 @@ fn analyzeErrUnionPayloadPtr(
5607 return sema.fail(block, src, "expected error union type, found {}", .{operand_ty.elemType()});5615 return sema.fail(block, src, "expected error union type, found {}", .{operand_ty.elemType()});
56085616
5609 const payload_ty = operand_ty.elemType().errorUnionPayload();5617 const payload_ty = operand_ty.elemType().errorUnionPayload();
5610 const operand_pointer_ty = try Type.ptr(sema.arena, .{5618 const target = sema.mod.getTarget();
5619 const operand_pointer_ty = try Type.ptr(sema.arena, target, .{
5611 .pointee_type = payload_ty,5620 .pointee_type = payload_ty,
5612 .mutable = !operand_ty.isConstPtr(),5621 .mutable = !operand_ty.isConstPtr(),
5613 .@"addrspace" = operand_ty.ptrAddressSpace(),5622 .@"addrspace" = operand_ty.ptrAddressSpace(),
...@@ -6517,7 +6526,8 @@ fn zirSwitchCapture(...@@ -6517,7 +6526,8 @@ fn zirSwitchCapture(
6517 if (is_ref) {6526 if (is_ref) {
6518 assert(operand_is_ref);6527 assert(operand_is_ref);
65196528
6520 const field_ty_ptr = try Type.ptr(sema.arena, .{6529 const target = sema.mod.getTarget();
6530 const field_ty_ptr = try Type.ptr(sema.arena, target, .{
6521 .pointee_type = field.ty,6531 .pointee_type = field.ty,
6522 .@"addrspace" = .generic,6532 .@"addrspace" = .generic,
6523 .mutable = operand_ptr_ty.ptrIsMutable(),6533 .mutable = operand_ptr_ty.ptrIsMutable(),
...@@ -11327,7 +11337,8 @@ fn zirPtrTypeSimple(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErr...@@ -11327,7 +11337,8 @@ fn zirPtrTypeSimple(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErr
1132711337
11328 const inst_data = sema.code.instructions.items(.data)[inst].ptr_type_simple;11338 const inst_data = sema.code.instructions.items(.data)[inst].ptr_type_simple;
11329 const elem_type = try sema.resolveType(block, .unneeded, inst_data.elem_type);11339 const elem_type = try sema.resolveType(block, .unneeded, inst_data.elem_type);
11330 const ty = try Type.ptr(sema.arena, .{11340 const target = sema.mod.getTarget();
11341 const ty = try Type.ptr(sema.arena, target, .{
11331 .pointee_type = elem_type,11342 .pointee_type = elem_type,
11332 .@"addrspace" = .generic,11343 .@"addrspace" = .generic,
11333 .mutable = inst_data.is_mutable,11344 .mutable = inst_data.is_mutable,
...@@ -11343,6 +11354,7 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air...@@ -11343,6 +11354,7 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
11343 defer tracy.end();11354 defer tracy.end();
1134411355
11345 const src: LazySrcLoc = .unneeded;11356 const src: LazySrcLoc = .unneeded;
11357 const elem_ty_src: LazySrcLoc = .unneeded;
11346 const inst_data = sema.code.instructions.items(.data)[inst].ptr_type;11358 const inst_data = sema.code.instructions.items(.data)[inst].ptr_type;
11347 const extra = sema.code.extraData(Zir.Inst.PtrType, inst_data.payload_index);11359 const extra = sema.code.extraData(Zir.Inst.PtrType, inst_data.payload_index);
1134811360
...@@ -11366,41 +11378,40 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air...@@ -11366,41 +11378,40 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
11366 break :blk try sema.analyzeAddrspace(block, .unneeded, ref, .pointer);11378 break :blk try sema.analyzeAddrspace(block, .unneeded, ref, .pointer);
11367 } else .generic;11379 } else .generic;
1136811380
11369 const bit_start = if (inst_data.flags.has_bit_range) blk: {11381 const bit_offset = if (inst_data.flags.has_bit_range) blk: {
11370 const ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_i]);11382 const ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_i]);
11371 extra_i += 1;11383 extra_i += 1;
11372 break :blk try sema.resolveAlreadyCoercedInt(block, .unneeded, ref, u16);11384 break :blk try sema.resolveAlreadyCoercedInt(block, .unneeded, ref, u16);
11373 } else 0;11385 } else 0;
1137411386
11375 var host_size: u16 = if (inst_data.flags.has_bit_range) blk: {11387 const host_size: u16 = if (inst_data.flags.has_bit_range) blk: {
11376 const ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_i]);11388 const ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_i]);
11377 extra_i += 1;11389 extra_i += 1;
11378 break :blk try sema.resolveAlreadyCoercedInt(block, .unneeded, ref, u16);11390 break :blk try sema.resolveAlreadyCoercedInt(block, .unneeded, ref, u16);
11379 } else 0;11391 } else 0;
1138011392
11381 const elem_type = try sema.resolveType(block, .unneeded, extra.data.elem_type);11393 if (host_size != 0 and bit_offset >= host_size * 8) {
1138211394 return sema.fail(block, src, "bit offset starts after end of host integer", .{});
11383 if (host_size != 0) {
11384 if (bit_start >= host_size * 8) {
11385 return sema.fail(block, src, "bit offset starts after end of host integer", .{});
11386 }
11387 const target = sema.mod.getTarget();
11388 const elem_type_bits = elem_type.bitSize(target);
11389 if (host_size * 8 == elem_type_bits) {
11390 assert(bit_start == 0);
11391 host_size = 0;
11392 }
11393 }11395 }
1139411396
11395 const ty = try Type.ptr(sema.arena, .{11397 const unresolved_elem_ty = try sema.resolveType(block, elem_ty_src, extra.data.elem_type);
11396 .pointee_type = elem_type,11398 const elem_ty = if (abi_align == 0)
11399 unresolved_elem_ty
11400 else t: {
11401 const elem_ty = try sema.resolveTypeFields(block, elem_ty_src, unresolved_elem_ty);
11402 try sema.resolveTypeLayout(block, elem_ty_src, elem_ty);
11403 break :t elem_ty;
11404 };
11405 const target = sema.mod.getTarget();
11406 const ty = try Type.ptr(sema.arena, target, .{
11407 .pointee_type = elem_ty,
11397 .sentinel = sentinel,11408 .sentinel = sentinel,
11398 .@"align" = abi_align,11409 .@"align" = abi_align,
11399 .@"addrspace" = address_space,11410 .@"addrspace" = address_space,
11400 .bit_offset = bit_start,11411 .bit_offset = bit_offset,
11401 .host_size = host_size,11412 .host_size = host_size,
11402 .mutable = inst_data.flags.is_mutable,11413 .mutable = inst_data.flags.is_mutable,
11403 .@"allowzero" = inst_data.flags.is_allowzero or inst_data.size == .C,11414 .@"allowzero" = inst_data.flags.is_allowzero,
11404 .@"volatile" = inst_data.flags.is_volatile,11415 .@"volatile" = inst_data.flags.is_volatile,
11405 .size = inst_data.size,11416 .size = inst_data.size,
11406 });11417 });
...@@ -11721,15 +11732,16 @@ fn zirArrayInit(...@@ -11721,15 +11732,16 @@ fn zirArrayInit(
11721 try sema.resolveTypeLayout(block, src, elem_ty);11732 try sema.resolveTypeLayout(block, src, elem_ty);
1172211733
11723 if (is_ref) {11734 if (is_ref) {
11724 const alloc_ty = try Type.ptr(sema.arena, .{11735 const target = sema.mod.getTarget();
11736 const alloc_ty = try Type.ptr(sema.arena, target, .{
11725 .pointee_type = array_ty,11737 .pointee_type = array_ty,
11726 .@"addrspace" = target_util.defaultAddressSpace(sema.mod.getTarget(), .local),11738 .@"addrspace" = target_util.defaultAddressSpace(target, .local),
11727 });11739 });
11728 const alloc = try block.addTy(.alloc, alloc_ty);11740 const alloc = try block.addTy(.alloc, alloc_ty);
1172911741
11730 const elem_ptr_ty = try Type.ptr(sema.arena, .{11742 const elem_ptr_ty = try Type.ptr(sema.arena, target, .{
11731 .mutable = true,11743 .mutable = true,
11732 .@"addrspace" = target_util.defaultAddressSpace(sema.mod.getTarget(), .local),11744 .@"addrspace" = target_util.defaultAddressSpace(target, .local),
11733 .pointee_type = elem_ty,11745 .pointee_type = elem_ty,
11734 });11746 });
11735 const elem_ptr_ty_ref = try sema.addType(elem_ptr_ty);11747 const elem_ptr_ty_ref = try sema.addType(elem_ptr_ty);
...@@ -11788,12 +11800,13 @@ fn zirArrayInitAnon(...@@ -11788,12 +11800,13 @@ fn zirArrayInitAnon(
11788 try sema.requireRuntimeBlock(block, runtime_src);11800 try sema.requireRuntimeBlock(block, runtime_src);
1178911801
11790 if (is_ref) {11802 if (is_ref) {
11803 const target = sema.mod.getTarget();
11791 const alloc = try block.addTy(.alloc, tuple_ty);11804 const alloc = try block.addTy(.alloc, tuple_ty);
11792 for (operands) |operand, i_usize| {11805 for (operands) |operand, i_usize| {
11793 const i = @intCast(u32, i_usize);11806 const i = @intCast(u32, i_usize);
11794 const field_ptr_ty = try Type.ptr(sema.arena, .{11807 const field_ptr_ty = try Type.ptr(sema.arena, target, .{
11795 .mutable = true,11808 .mutable = true,
11796 .@"addrspace" = target_util.defaultAddressSpace(sema.mod.getTarget(), .local),11809 .@"addrspace" = target_util.defaultAddressSpace(target, .local),
11797 .pointee_type = types[i],11810 .pointee_type = types[i],
11798 });11811 });
11799 const field_ptr = try block.addStructFieldPtr(alloc, i, field_ptr_ty);11812 const field_ptr = try block.addStructFieldPtr(alloc, i, field_ptr_ty);
...@@ -12068,6 +12081,7 @@ fn zirReify(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I...@@ -12068,6 +12081,7 @@ fn zirReify(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I
12068 const union_val = val.cast(Value.Payload.Union).?.data;12081 const union_val = val.cast(Value.Payload.Union).?.data;
12069 const tag_ty = type_info_ty.unionTagType().?;12082 const tag_ty = type_info_ty.unionTagType().?;
12070 const tag_index = tag_ty.enumTagFieldIndex(union_val.tag).?;12083 const tag_index = tag_ty.enumTagFieldIndex(union_val.tag).?;
12084 const target = sema.mod.getTarget();
12071 switch (@intToEnum(std.builtin.TypeId, tag_index)) {12085 switch (@intToEnum(std.builtin.TypeId, tag_index)) {
12072 .Type => return Air.Inst.Ref.type_type,12086 .Type => return Air.Inst.Ref.type_type,
12073 .Void => return Air.Inst.Ref.void_type,12087 .Void => return Air.Inst.Ref.void_type,
...@@ -12146,11 +12160,14 @@ fn zirReify(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I...@@ -12146,11 +12160,14 @@ fn zirReify(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I
12146 return sema.fail(block, src, "sentinels are only allowed on slices and unknown-length pointers", .{});12160 return sema.fail(block, src, "sentinels are only allowed on slices and unknown-length pointers", .{});
12147 }12161 }
12148 const sentinel_ptr_val = sentinel_val.castTag(.opt_payload).?.data;12162 const sentinel_ptr_val = sentinel_val.castTag(.opt_payload).?.data;
12149 const ptr_ty = try Type.ptr(sema.arena, .{ .@"addrspace" = .generic, .pointee_type = child_ty });12163 const ptr_ty = try Type.ptr(sema.arena, target, .{
12164 .@"addrspace" = .generic,
12165 .pointee_type = child_ty,
12166 });
12150 actual_sentinel = (try sema.pointerDeref(block, src, sentinel_ptr_val, ptr_ty)).?;12167 actual_sentinel = (try sema.pointerDeref(block, src, sentinel_ptr_val, ptr_ty)).?;
12151 }12168 }
1215212169
12153 const ty = try Type.ptr(sema.arena, .{12170 const ty = try Type.ptr(sema.arena, target, .{
12154 .size = ptr_size,12171 .size = ptr_size,
12155 .mutable = !is_const_val.toBool(),12172 .mutable = !is_const_val.toBool(),
12156 .@"volatile" = is_volatile_val.toBool(),12173 .@"volatile" = is_volatile_val.toBool(),
...@@ -12176,7 +12193,10 @@ fn zirReify(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I...@@ -12176,7 +12193,10 @@ fn zirReify(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I
12176 var buffer: Value.ToTypeBuffer = undefined;12193 var buffer: Value.ToTypeBuffer = undefined;
12177 const child_ty = try child_val.toType(&buffer).copy(sema.arena);12194 const child_ty = try child_val.toType(&buffer).copy(sema.arena);
12178 const sentinel = if (sentinel_val.castTag(.opt_payload)) |p| blk: {12195 const sentinel = if (sentinel_val.castTag(.opt_payload)) |p| blk: {
12179 const ptr_ty = try Type.ptr(sema.arena, .{ .@"addrspace" = .generic, .pointee_type = child_ty });12196 const ptr_ty = try Type.ptr(sema.arena, target, .{
12197 .@"addrspace" = .generic,
12198 .pointee_type = child_ty,
12199 });
12180 break :blk (try sema.pointerDeref(block, src, p.data, ptr_ty)).?;12200 break :blk (try sema.pointerDeref(block, src, p.data, ptr_ty)).?;
12181 } else null;12201 } else null;
1218212202
...@@ -12468,7 +12488,8 @@ fn zirAlignCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A...@@ -12468,7 +12488,8 @@ fn zirAlignCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
12468 // TODO insert safety check that the alignment is correct12488 // TODO insert safety check that the alignment is correct
1246912489
12470 const ptr_info = ptr_ty.ptrInfo().data;12490 const ptr_info = ptr_ty.ptrInfo().data;
12471 const dest_ty = try Type.ptr(sema.arena, .{12491 const target = sema.mod.getTarget();
12492 const dest_ty = try Type.ptr(sema.arena, target, .{
12472 .pointee_type = ptr_info.pointee_type,12493 .pointee_type = ptr_info.pointee_type,
12473 .@"align" = dest_align,12494 .@"align" = dest_align,
12474 .@"addrspace" = ptr_info.@"addrspace",12495 .@"addrspace" = ptr_info.@"addrspace",
...@@ -13408,11 +13429,12 @@ fn zirFieldParentPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr...@@ -13408,11 +13429,12 @@ fn zirFieldParentPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr
13408 ptr_ty_data.@"align" = @intCast(u32, field.abi_align.toUnsignedInt());13429 ptr_ty_data.@"align" = @intCast(u32, field.abi_align.toUnsignedInt());
13409 }13430 }
1341013431
13411 const actual_field_ptr_ty = try Type.ptr(sema.arena, ptr_ty_data);13432 const target = sema.mod.getTarget();
13433 const actual_field_ptr_ty = try Type.ptr(sema.arena, target, ptr_ty_data);
13412 const casted_field_ptr = try sema.coerce(block, actual_field_ptr_ty, field_ptr, ptr_src);13434 const casted_field_ptr = try sema.coerce(block, actual_field_ptr_ty, field_ptr, ptr_src);
1341313435
13414 ptr_ty_data.pointee_type = struct_ty;13436 ptr_ty_data.pointee_type = struct_ty;
13415 const result_ptr = try Type.ptr(sema.arena, ptr_ty_data);13437 const result_ptr = try Type.ptr(sema.arena, target, ptr_ty_data);
1341613438
13417 if (try sema.resolveDefinedValue(block, src, casted_field_ptr)) |field_ptr_val| {13439 if (try sema.resolveDefinedValue(block, src, casted_field_ptr)) |field_ptr_val| {
13418 const payload = field_ptr_val.castTag(.field_ptr).?.data;13440 const payload = field_ptr_val.castTag(.field_ptr).?.data;
...@@ -13509,7 +13531,8 @@ fn zirMemcpy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void...@@ -13509,7 +13531,8 @@ fn zirMemcpy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void
13509 const uncasted_src_ptr_ty = sema.typeOf(uncasted_src_ptr);13531 const uncasted_src_ptr_ty = sema.typeOf(uncasted_src_ptr);
13510 try sema.checkPtrOperand(block, src_src, uncasted_src_ptr_ty);13532 try sema.checkPtrOperand(block, src_src, uncasted_src_ptr_ty);
13511 const src_ptr_info = uncasted_src_ptr_ty.ptrInfo().data;13533 const src_ptr_info = uncasted_src_ptr_ty.ptrInfo().data;
13512 const wanted_src_ptr_ty = try Type.ptr(sema.arena, .{13534 const target = sema.mod.getTarget();
13535 const wanted_src_ptr_ty = try Type.ptr(sema.arena, target, .{
13513 .pointee_type = dest_ptr_ty.elemType2(),13536 .pointee_type = dest_ptr_ty.elemType2(),
13514 .@"align" = src_ptr_info.@"align",13537 .@"align" = src_ptr_info.@"align",
13515 .@"addrspace" = src_ptr_info.@"addrspace",13538 .@"addrspace" = src_ptr_info.@"addrspace",
...@@ -14149,9 +14172,10 @@ fn panicWithMsg(...@@ -14149,9 +14172,10 @@ fn panicWithMsg(
14149 const panic_fn = try sema.getBuiltin(block, src, "panic");14172 const panic_fn = try sema.getBuiltin(block, src, "panic");
14150 const unresolved_stack_trace_ty = try sema.getBuiltinType(block, src, "StackTrace");14173 const unresolved_stack_trace_ty = try sema.getBuiltinType(block, src, "StackTrace");
14151 const stack_trace_ty = try sema.resolveTypeFields(block, src, unresolved_stack_trace_ty);14174 const stack_trace_ty = try sema.resolveTypeFields(block, src, unresolved_stack_trace_ty);
14152 const ptr_stack_trace_ty = try Type.ptr(arena, .{14175 const target = mod.getTarget();
14176 const ptr_stack_trace_ty = try Type.ptr(arena, target, .{
14153 .pointee_type = stack_trace_ty,14177 .pointee_type = stack_trace_ty,
14154 .@"addrspace" = target_util.defaultAddressSpace(mod.getTarget(), .global_constant), // TODO might need a place that is more dynamic14178 .@"addrspace" = target_util.defaultAddressSpace(target, .global_constant), // TODO might need a place that is more dynamic
14155 });14179 });
14156 const null_stack_trace = try sema.addConstant(14180 const null_stack_trace = try sema.addConstant(
14157 try Type.optional(arena, ptr_stack_trace_ty),14181 try Type.optional(arena, ptr_stack_trace_ty),
...@@ -14405,6 +14429,8 @@ fn fieldPtr(...@@ -14405,6 +14429,8 @@ fn fieldPtr(
14405 else14429 else
14406 object_ty;14430 object_ty;
1440714431
14432 const target = sema.mod.getTarget();
14433
14408 switch (inner_ty.zigTypeTag()) {14434 switch (inner_ty.zigTypeTag()) {
14409 .Array => {14435 .Array => {
14410 if (mem.eql(u8, field_name, "len")) {14436 if (mem.eql(u8, field_name, "len")) {
...@@ -14444,7 +14470,7 @@ fn fieldPtr(...@@ -14444,7 +14470,7 @@ fn fieldPtr(
14444 }14470 }
14445 try sema.requireRuntimeBlock(block, src);14471 try sema.requireRuntimeBlock(block, src);
1444614472
14447 const result_ty = try Type.ptr(sema.arena, .{14473 const result_ty = try Type.ptr(sema.arena, target, .{
14448 .pointee_type = slice_ptr_ty,14474 .pointee_type = slice_ptr_ty,
14449 .mutable = object_ptr_ty.ptrIsMutable(),14475 .mutable = object_ptr_ty.ptrIsMutable(),
14450 .@"addrspace" = object_ptr_ty.ptrAddressSpace(),14476 .@"addrspace" = object_ptr_ty.ptrAddressSpace(),
...@@ -14463,7 +14489,7 @@ fn fieldPtr(...@@ -14463,7 +14489,7 @@ fn fieldPtr(
14463 }14489 }
14464 try sema.requireRuntimeBlock(block, src);14490 try sema.requireRuntimeBlock(block, src);
1446514491
14466 const result_ty = try Type.ptr(sema.arena, .{14492 const result_ty = try Type.ptr(sema.arena, target, .{
14467 .pointee_type = Type.usize,14493 .pointee_type = Type.usize,
14468 .mutable = object_ptr_ty.ptrIsMutable(),14494 .mutable = object_ptr_ty.ptrIsMutable(),
14469 .@"addrspace" = object_ptr_ty.ptrAddressSpace(),14495 .@"addrspace" = object_ptr_ty.ptrAddressSpace(),
...@@ -14692,7 +14718,8 @@ fn finishFieldCallBind(...@@ -14692,7 +14718,8 @@ fn finishFieldCallBind(
14692 object_ptr: Air.Inst.Ref,14718 object_ptr: Air.Inst.Ref,
14693) CompileError!Air.Inst.Ref {14719) CompileError!Air.Inst.Ref {
14694 const arena = sema.arena;14720 const arena = sema.arena;
14695 const ptr_field_ty = try Type.ptr(arena, .{14721 const target = sema.mod.getTarget();
14722 const ptr_field_ty = try Type.ptr(arena, target, .{
14696 .pointee_type = field_ty,14723 .pointee_type = field_ty,
14697 .mutable = ptr_ty.ptrIsMutable(),14724 .mutable = ptr_ty.ptrIsMutable(),
14698 .@"addrspace" = ptr_ty.ptrAddressSpace(),14725 .@"addrspace" = ptr_ty.ptrAddressSpace(),
...@@ -14831,7 +14858,8 @@ fn structFieldPtrByIndex(...@@ -14831,7 +14858,8 @@ fn structFieldPtrByIndex(
14831 }14858 }
14832 }14859 }
1483314860
14834 const ptr_field_ty = try Type.ptr(sema.arena, ptr_ty_data);14861 const target = sema.mod.getTarget();
14862 const ptr_field_ty = try Type.ptr(sema.arena, target, ptr_ty_data);
1483514863
14836 if (try sema.resolveDefinedValue(block, src, struct_ptr)) |struct_ptr_val| {14864 if (try sema.resolveDefinedValue(block, src, struct_ptr)) |struct_ptr_val| {
14837 return sema.addConstant(14865 return sema.addConstant(
...@@ -14959,7 +14987,8 @@ fn unionFieldPtr(...@@ -14959,7 +14987,8 @@ fn unionFieldPtr(
14959 const field_index = @intCast(u32, field_index_big);14987 const field_index = @intCast(u32, field_index_big);
1496014988
14961 const field = union_obj.fields.values()[field_index];14989 const field = union_obj.fields.values()[field_index];
14962 const ptr_field_ty = try Type.ptr(arena, .{14990 const target = sema.mod.getTarget();
14991 const ptr_field_ty = try Type.ptr(arena, target, .{
14963 .pointee_type = field.ty,14992 .pointee_type = field.ty,
14964 .mutable = union_ptr_ty.ptrIsMutable(),14993 .mutable = union_ptr_ty.ptrIsMutable(),
14965 .@"addrspace" = union_ptr_ty.ptrAddressSpace(),14994 .@"addrspace" = union_ptr_ty.ptrAddressSpace(),
...@@ -15033,7 +15062,8 @@ fn elemPtr(...@@ -15033,7 +15062,8 @@ fn elemPtr(
15033 .Pointer => {15062 .Pointer => {
15034 // In all below cases, we have to deref the ptr operand to get the actual array pointer.15063 // In all below cases, we have to deref the ptr operand to get the actual array pointer.
15035 const array = try sema.analyzeLoad(block, array_ptr_src, array_ptr, array_ptr_src);15064 const array = try sema.analyzeLoad(block, array_ptr_src, array_ptr, array_ptr_src);
15036 const result_ty = try array_ty.elemPtrType(sema.arena);15065 const target = sema.mod.getTarget();
15066 const result_ty = try array_ty.elemPtrType(sema.arena, target);
15037 switch (array_ty.ptrSize()) {15067 switch (array_ty.ptrSize()) {
15038 .Slice => {15068 .Slice => {
15039 const maybe_slice_val = try sema.resolveDefinedValue(block, array_ptr_src, array);15069 const maybe_slice_val = try sema.resolveDefinedValue(block, array_ptr_src, array);
...@@ -15172,7 +15202,8 @@ fn tupleFieldPtr(...@@ -15172,7 +15202,8 @@ fn tupleFieldPtr(
15172 }15202 }
1517315203
15174 const field_ty = tuple_info.types[field_index];15204 const field_ty = tuple_info.types[field_index];
15175 const ptr_field_ty = try Type.ptr(sema.arena, .{15205 const target = sema.mod.getTarget();
15206 const ptr_field_ty = try Type.ptr(sema.arena, target, .{
15176 .pointee_type = field_ty,15207 .pointee_type = field_ty,
15177 .mutable = tuple_ptr_ty.ptrIsMutable(),15208 .mutable = tuple_ptr_ty.ptrIsMutable(),
15178 .@"addrspace" = tuple_ptr_ty.ptrAddressSpace(),15209 .@"addrspace" = tuple_ptr_ty.ptrAddressSpace(),
...@@ -15264,7 +15295,8 @@ fn elemPtrArray(...@@ -15264,7 +15295,8 @@ fn elemPtrArray(
15264 elem_index_src: LazySrcLoc,15295 elem_index_src: LazySrcLoc,
15265) CompileError!Air.Inst.Ref {15296) CompileError!Air.Inst.Ref {
15266 const array_ptr_ty = sema.typeOf(array_ptr);15297 const array_ptr_ty = sema.typeOf(array_ptr);
15267 const result_ty = try array_ptr_ty.elemPtrType(sema.arena);15298 const target = sema.mod.getTarget();
15299 const result_ty = try array_ptr_ty.elemPtrType(sema.arena, target);
1526815300
15269 if (try sema.resolveDefinedValue(block, src, array_ptr)) |array_ptr_val| {15301 if (try sema.resolveDefinedValue(block, src, array_ptr)) |array_ptr_val| {
15270 if (try sema.resolveDefinedValue(block, elem_index_src, elem_index)) |index_val| {15302 if (try sema.resolveDefinedValue(block, elem_index_src, elem_index)) |index_val| {
...@@ -15957,15 +15989,28 @@ fn coerceInMemoryAllowedPtrs(...@@ -15957,15 +15989,28 @@ fn coerceInMemoryAllowedPtrs(
15957 // In this case, if they share the same child type, no need to resolve15989 // In this case, if they share the same child type, no need to resolve
15958 // pointee type alignment. Otherwise both pointee types must have their alignment15990 // pointee type alignment. Otherwise both pointee types must have their alignment
15959 // resolved and we compare the alignment numerically.15991 // resolved and we compare the alignment numerically.
15960 if (src_info.@"align" != 0 or dest_info.@"align" != 0 or15992 alignment: {
15961 !dest_info.pointee_type.eql(src_info.pointee_type))15993 if (src_info.@"align" == 0 and dest_info.@"align" == 0 and
15962 {15994 dest_info.pointee_type.eql(src_info.pointee_type))
15963 const src_align = src_info.@"align";15995 {
15964 const dest_align = dest_info.@"align";15996 break :alignment;
15997 }
15998
15999 const src_align = if (src_info.@"align" != 0)
16000 src_info.@"align"
16001 else
16002 src_info.pointee_type.abiAlignment(target);
16003
16004 const dest_align = if (dest_info.@"align" != 0)
16005 dest_info.@"align"
16006 else
16007 dest_info.pointee_type.abiAlignment(target);
1596516008
15966 if (dest_align > src_align) {16009 if (dest_align > src_align) {
15967 return .no_match;16010 return .no_match;
15968 }16011 }
16012
16013 break :alignment;
15969 }16014 }
1597016015
15971 return .ok;16016 return .ok;
...@@ -16874,6 +16919,7 @@ fn analyzeDeclRef(sema: *Sema, decl: *Decl) CompileError!Air.Inst.Ref {...@@ -16874,6 +16919,7 @@ fn analyzeDeclRef(sema: *Sema, decl: *Decl) CompileError!Air.Inst.Ref {
16874 try sema.mod.declareDeclDependency(sema.owner_decl, decl);16919 try sema.mod.declareDeclDependency(sema.owner_decl, decl);
16875 try sema.ensureDeclAnalyzed(decl);16920 try sema.ensureDeclAnalyzed(decl);
1687616921
16922 const target = sema.mod.getTarget();
16877 const decl_tv = try decl.typedValue();16923 const decl_tv = try decl.typedValue();
16878 if (decl_tv.val.castTag(.variable)) |payload| {16924 if (decl_tv.val.castTag(.variable)) |payload| {
16879 const variable = payload.data;16925 const variable = payload.data;
...@@ -16881,7 +16927,7 @@ fn analyzeDeclRef(sema: *Sema, decl: *Decl) CompileError!Air.Inst.Ref {...@@ -16881,7 +16927,7 @@ fn analyzeDeclRef(sema: *Sema, decl: *Decl) CompileError!Air.Inst.Ref {
16881 016927 0
16882 else16928 else
16883 @intCast(u32, decl.align_val.toUnsignedInt());16929 @intCast(u32, decl.align_val.toUnsignedInt());
16884 const ty = try Type.ptr(sema.arena, .{16930 const ty = try Type.ptr(sema.arena, target, .{
16885 .pointee_type = decl_tv.ty,16931 .pointee_type = decl_tv.ty,
16886 .mutable = variable.is_mutable,16932 .mutable = variable.is_mutable,
16887 .@"addrspace" = decl.@"addrspace",16933 .@"addrspace" = decl.@"addrspace",
...@@ -16890,7 +16936,7 @@ fn analyzeDeclRef(sema: *Sema, decl: *Decl) CompileError!Air.Inst.Ref {...@@ -16890,7 +16936,7 @@ fn analyzeDeclRef(sema: *Sema, decl: *Decl) CompileError!Air.Inst.Ref {
16890 return sema.addConstant(ty, try Value.Tag.decl_ref.create(sema.arena, decl));16936 return sema.addConstant(ty, try Value.Tag.decl_ref.create(sema.arena, decl));
16891 }16937 }
16892 return sema.addConstant(16938 return sema.addConstant(
16893 try Type.ptr(sema.arena, .{16939 try Type.ptr(sema.arena, target, .{
16894 .pointee_type = decl_tv.ty,16940 .pointee_type = decl_tv.ty,
16895 .mutable = false,16941 .mutable = false,
16896 .@"addrspace" = decl.@"addrspace",16942 .@"addrspace" = decl.@"addrspace",
...@@ -16918,12 +16964,13 @@ fn analyzeRef(...@@ -16918,12 +16964,13 @@ fn analyzeRef(
1691816964
16919 try sema.requireRuntimeBlock(block, src);16965 try sema.requireRuntimeBlock(block, src);
16920 const address_space = target_util.defaultAddressSpace(sema.mod.getTarget(), .local);16966 const address_space = target_util.defaultAddressSpace(sema.mod.getTarget(), .local);
16921 const ptr_type = try Type.ptr(sema.arena, .{16967 const target = sema.mod.getTarget();
16968 const ptr_type = try Type.ptr(sema.arena, target, .{
16922 .pointee_type = operand_ty,16969 .pointee_type = operand_ty,
16923 .mutable = false,16970 .mutable = false,
16924 .@"addrspace" = address_space,16971 .@"addrspace" = address_space,
16925 });16972 });
16926 const mut_ptr_type = try Type.ptr(sema.arena, .{16973 const mut_ptr_type = try Type.ptr(sema.arena, target, .{
16927 .pointee_type = operand_ty,16974 .pointee_type = operand_ty,
16928 .@"addrspace" = address_space,16975 .@"addrspace" = address_space,
16929 });16976 });
...@@ -17174,11 +17221,12 @@ fn analyzeSlice(...@@ -17174,11 +17221,12 @@ fn analyzeSlice(
1717417221
17175 const new_ptr_ty_info = sema.typeOf(new_ptr).ptrInfo().data;17222 const new_ptr_ty_info = sema.typeOf(new_ptr).ptrInfo().data;
17176 const new_allowzero = new_ptr_ty_info.@"allowzero" and sema.typeOf(ptr).ptrSize() != .C;17223 const new_allowzero = new_ptr_ty_info.@"allowzero" and sema.typeOf(ptr).ptrSize() != .C;
17224 const target = sema.mod.getTarget();
1717717225
17178 if (opt_new_len_val) |new_len_val| {17226 if (opt_new_len_val) |new_len_val| {
17179 const new_len_int = new_len_val.toUnsignedInt();17227 const new_len_int = new_len_val.toUnsignedInt();
1718017228
17181 const return_ty = try Type.ptr(sema.arena, .{17229 const return_ty = try Type.ptr(sema.arena, target, .{
17182 .pointee_type = try Type.array(sema.arena, new_len_int, sentinel, elem_ty),17230 .pointee_type = try Type.array(sema.arena, new_len_int, sentinel, elem_ty),
17183 .sentinel = null,17231 .sentinel = null,
17184 .@"align" = new_ptr_ty_info.@"align",17232 .@"align" = new_ptr_ty_info.@"align",
...@@ -17206,7 +17254,7 @@ fn analyzeSlice(...@@ -17206,7 +17254,7 @@ fn analyzeSlice(
17206 return sema.fail(block, ptr_src, "non-zero length slice of undefined pointer", .{});17254 return sema.fail(block, ptr_src, "non-zero length slice of undefined pointer", .{});
17207 }17255 }
1720817256
17209 const return_ty = try Type.ptr(sema.arena, .{17257 const return_ty = try Type.ptr(sema.arena, target, .{
17210 .pointee_type = elem_ty,17258 .pointee_type = elem_ty,
17211 .sentinel = sentinel,17259 .sentinel = sentinel,
17212 .@"align" = new_ptr_ty_info.@"align",17260 .@"align" = new_ptr_ty_info.@"align",
...@@ -17904,14 +17952,14 @@ fn resolvePeerTypes(...@@ -17904,14 +17952,14 @@ fn resolvePeerTypes(
17904 else => unreachable,17952 else => unreachable,
17905 };17953 };
1790617954
17907 return Type.ptr(sema.arena, info.data);17955 return Type.ptr(sema.arena, target, info.data);
17908 }17956 }
1790917957
17910 if (make_the_slice_const) {17958 if (make_the_slice_const) {
17911 // turn []T => []const T17959 // turn []T => []const T
17912 var info = chosen_ty.ptrInfo();17960 var info = chosen_ty.ptrInfo();
17913 info.data.mutable = false;17961 info.data.mutable = false;
17914 return Type.ptr(sema.arena, info.data);17962 return Type.ptr(sema.arena, target, info.data);
17915 }17963 }
1791617964
17917 return chosen_ty;17965 return chosen_ty;
...@@ -19121,7 +19169,8 @@ fn analyzeComptimeAlloc(...@@ -19121,7 +19169,8 @@ fn analyzeComptimeAlloc(
19121 // Needed to make an anon decl with type `var_type` (the `finish()` call below).19169 // Needed to make an anon decl with type `var_type` (the `finish()` call below).
19122 _ = try sema.typeHasOnePossibleValue(block, src, var_type);19170 _ = try sema.typeHasOnePossibleValue(block, src, var_type);
1912319171
19124 const ptr_type = try Type.ptr(sema.arena, .{19172 const target = sema.mod.getTarget();
19173 const ptr_type = try Type.ptr(sema.arena, target, .{
19125 .pointee_type = var_type,19174 .pointee_type = var_type,
19126 .@"addrspace" = target_util.defaultAddressSpace(sema.mod.getTarget(), .global_constant),19175 .@"addrspace" = target_util.defaultAddressSpace(sema.mod.getTarget(), .global_constant),
19127 .@"align" = alignment,19176 .@"align" = alignment,
src/codegen.zig+1-1
...@@ -657,7 +657,7 @@ fn lowerDeclRef(...@@ -657,7 +657,7 @@ fn lowerDeclRef(
657 .data = typed_value.val.sliceLen(),657 .data = typed_value.val.sliceLen(),
658 };658 };
659 switch (try generateSymbol(bin_file, parent_atom_index, src_loc, .{659 switch (try generateSymbol(bin_file, parent_atom_index, src_loc, .{
660 .ty = Type.initTag(.usize),660 .ty = Type.usize,
661 .val = Value.initPayload(&slice_len.base),661 .val = Value.initPayload(&slice_len.base),
662 }, code, debug_output)) {662 }, code, debug_output)) {
663 .appended => {},663 .appended => {},
src/type.zig+351-184
...@@ -491,94 +491,115 @@ pub const Type = extern union {...@@ -491,94 +491,115 @@ pub const Type = extern union {
491491
492 pub fn eql(a: Type, b: Type) bool {492 pub fn eql(a: Type, b: Type) bool {
493 // As a shortcut, if the small tags / addresses match, we're done.493 // As a shortcut, if the small tags / addresses match, we're done.
494 if (a.tag_if_small_enough == b.tag_if_small_enough)494 if (a.tag_if_small_enough == b.tag_if_small_enough) return true;
495 return true;
496 const zig_tag_a = a.zigTypeTag();
497 const zig_tag_b = b.zigTypeTag();
498 if (zig_tag_a != zig_tag_b)
499 return false;
500 switch (zig_tag_a) {
501 .EnumLiteral => return true,
502 .Type => return true,
503 .Void => return true,
504 .Bool => return true,
505 .NoReturn => return true,
506 .ComptimeFloat => return true,
507 .ComptimeInt => return true,
508 .Undefined => return true,
509 .Null => return true,
510 .AnyFrame => {
511 return a.elemType().eql(b.elemType());
512 },
513 .Pointer => {
514 const info_a = a.ptrInfo().data;
515 const info_b = b.ptrInfo().data;
516 if (!info_a.pointee_type.eql(info_b.pointee_type))
517 return false;
518 if (info_a.size != info_b.size)
519 return false;
520 if (info_a.mutable != info_b.mutable)
521 return false;
522 if (info_a.@"volatile" != info_b.@"volatile")
523 return false;
524 if (info_a.@"allowzero" != info_b.@"allowzero")
525 return false;
526 if (info_a.bit_offset != info_b.bit_offset)
527 return false;
528 if (info_a.host_size != info_b.host_size)
529 return false;
530 if (info_a.@"addrspace" != info_b.@"addrspace")
531 return false;
532495
533 const sentinel_a = info_a.sentinel;496 switch (a.tag()) {
534 const sentinel_b = info_b.sentinel;497 .generic_poison => unreachable,
535 if (sentinel_a) |sa| {
536 if (sentinel_b) |sb| {
537 if (!sa.eql(sb, info_a.pointee_type))
538 return false;
539 } else {
540 return false;
541 }
542 } else {
543 if (sentinel_b != null)
544 return false;
545 }
546498
547 return true;499 // Detect that e.g. u64 != usize, even if the bits match on a particular target.
500 .usize,
501 .isize,
502 .c_short,
503 .c_ushort,
504 .c_int,
505 .c_uint,
506 .c_long,
507 .c_ulong,
508 .c_longlong,
509 .c_ulonglong,
510
511 .f16,
512 .f32,
513 .f64,
514 .f80,
515 .f128,
516 .c_longdouble,
517
518 .bool,
519 .void,
520 .type,
521 .comptime_int,
522 .comptime_float,
523 .noreturn,
524 .@"null",
525 .@"undefined",
526 .@"anyopaque",
527 .@"anyframe",
528 .enum_literal,
529 => |a_tag| {
530 assert(a_tag != b.tag()); // because of the comparison at the top of the function.
531 return false;
548 },532 },
549 .Int => {533
550 // Detect that e.g. u64 != usize, even if the bits match on a particular target.534 .u1,
551 const a_is_named_int = a.isNamedInt();535 .u8,
552 const b_is_named_int = b.isNamedInt();536 .i8,
553 if (a_is_named_int != b_is_named_int)537 .u16,
554 return false;538 .i16,
555 if (a_is_named_int)539 .u32,
556 return a.tag() == b.tag();540 .i32,
557 // Remaining cases are arbitrary sized integers.541 .u64,
558 // The target will not be branched upon, because we handled target-dependent cases above.542 .i64,
543 .u128,
544 .i128,
545 .int_signed,
546 .int_unsigned,
547 => {
548 if (b.zigTypeTag() != .Int) return false;
549 if (b.isNamedInt()) return false;
550
551 // Arbitrary sized integers. The target will not be branched upon,
552 // because we handled target-dependent cases above.
559 const info_a = a.intInfo(@as(Target, undefined));553 const info_a = a.intInfo(@as(Target, undefined));
560 const info_b = b.intInfo(@as(Target, undefined));554 const info_b = b.intInfo(@as(Target, undefined));
561 return info_a.signedness == info_b.signedness and info_a.bits == info_b.bits;555 return info_a.signedness == info_b.signedness and info_a.bits == info_b.bits;
562 },556 },
563 .Array, .Vector => {557
564 if (a.arrayLen() != b.arrayLen())558 .error_set,
565 return false;559 .error_set_single,
566 const elem_ty = a.elemType();560 .anyerror,
567 if (!elem_ty.eql(b.elemType()))561 .error_set_inferred,
568 return false;562 .error_set_merged,
569 const sentinel_a = a.sentinel();563 => {
570 const sentinel_b = b.sentinel();564 if (b.zigTypeTag() != .ErrorSet) return false;
571 if (sentinel_a) |sa| {565
572 if (sentinel_b) |sb| {566 // TODO: revisit the language specification for how to evaluate equality
573 return sa.eql(sb, elem_ty);567 // for error set types.
574 } else {568
575 return false;569 if (a.tag() == .anyerror and b.tag() == .anyerror) {
576 }570 return true;
577 } else {571 }
578 return sentinel_b == null;572
573 if (a.tag() == .error_set and b.tag() == .error_set) {
574 return a.castTag(.error_set).?.data.owner_decl == b.castTag(.error_set).?.data.owner_decl;
579 }575 }
576
577 if (a.tag() == .error_set_inferred and b.tag() == .error_set_inferred) {
578 return a.castTag(.error_set_inferred).?.data == b.castTag(.error_set_inferred).?.data;
579 }
580
581 if (a.tag() == .error_set_single and b.tag() == .error_set_single) {
582 const a_data = a.castTag(.error_set_single).?.data;
583 const b_data = b.castTag(.error_set_single).?.data;
584 return std.mem.eql(u8, a_data, b_data);
585 }
586 return false;
580 },587 },
581 .Fn => {588
589 .@"opaque" => {
590 const opaque_obj_a = a.castTag(.@"opaque").?.data;
591 const opaque_obj_b = (b.castTag(.@"opaque") orelse return false).data;
592 return opaque_obj_a == opaque_obj_b;
593 },
594
595 .fn_noreturn_no_args,
596 .fn_void_no_args,
597 .fn_naked_noreturn_no_args,
598 .fn_ccc_void_no_args,
599 .function,
600 => {
601 if (b.zigTypeTag() != .Fn) return false;
602
582 const a_info = a.fnInfo();603 const a_info = a.fnInfo();
583 const b_info = b.fnInfo();604 const b_info = b.fnInfo();
584605
...@@ -613,76 +634,105 @@ pub const Type = extern union {...@@ -613,76 +634,105 @@ pub const Type = extern union {
613634
614 return true;635 return true;
615 },636 },
616 .Optional => {
617 var buf_a: Payload.ElemType = undefined;
618 var buf_b: Payload.ElemType = undefined;
619 return a.optionalChild(&buf_a).eql(b.optionalChild(&buf_b));
620 },
621 .Struct => {
622 if (a.castTag(.@"struct")) |a_payload| {
623 if (b.castTag(.@"struct")) |b_payload| {
624 return a_payload.data == b_payload.data;
625 }
626 }
627 if (a.castTag(.tuple)) |a_payload| {
628 if (b.castTag(.tuple)) |b_payload| {
629 if (a_payload.data.types.len != b_payload.data.types.len) return false;
630
631 for (a_payload.data.types) |a_ty, i| {
632 const b_ty = b_payload.data.types[i];
633 if (!eql(a_ty, b_ty)) return false;
634 }
635637
636 for (a_payload.data.values) |a_val, i| {638 .array,
637 const ty = a_payload.data.types[i];639 .array_u8_sentinel_0,
638 const b_val = b_payload.data.values[i];640 .array_u8,
639 if (a_val.tag() == .unreachable_value) {641 .array_sentinel,
640 if (b_val.tag() == .unreachable_value) {642 .vector,
641 continue;643 => {
642 } else {644 if (a.zigTypeTag() != b.zigTypeTag()) return false;
643 return false;
644 }
645 } else {
646 if (b_val.tag() == .unreachable_value) {
647 return false;
648 } else {
649 if (!Value.eql(a_val, b_val, ty)) return false;
650 }
651 }
652 }
653645
654 return true;646 if (a.arrayLen() != b.arrayLen())
647 return false;
648 const elem_ty = a.elemType();
649 if (!elem_ty.eql(b.elemType()))
650 return false;
651 const sentinel_a = a.sentinel();
652 const sentinel_b = b.sentinel();
653 if (sentinel_a) |sa| {
654 if (sentinel_b) |sb| {
655 return sa.eql(sb, elem_ty);
656 } else {
657 return false;
655 }658 }
659 } else {
660 return sentinel_b == null;
656 }661 }
657 return a.tag() == b.tag();
658 },662 },
659 .Enum => {663
660 if (a.cast(Payload.EnumFull)) |a_payload| {664 .single_const_pointer_to_comptime_int,
661 if (b.cast(Payload.EnumFull)) |b_payload| {665 .const_slice_u8,
662 return a_payload.data == b_payload.data;666 .const_slice_u8_sentinel_0,
663 }667 .single_const_pointer,
664 }668 .single_mut_pointer,
665 if (a.cast(Payload.EnumSimple)) |a_payload| {669 .many_const_pointer,
666 if (b.cast(Payload.EnumSimple)) |b_payload| {670 .many_mut_pointer,
667 return a_payload.data == b_payload.data;671 .c_const_pointer,
672 .c_mut_pointer,
673 .const_slice,
674 .mut_slice,
675 .pointer,
676 .inferred_alloc_const,
677 .inferred_alloc_mut,
678 .manyptr_u8,
679 .manyptr_const_u8,
680 .manyptr_const_u8_sentinel_0,
681 => {
682 if (b.zigTypeTag() != .Pointer) return false;
683
684 const info_a = a.ptrInfo().data;
685 const info_b = b.ptrInfo().data;
686 if (!info_a.pointee_type.eql(info_b.pointee_type))
687 return false;
688 if (info_a.@"align" != info_b.@"align")
689 return false;
690 if (info_a.@"addrspace" != info_b.@"addrspace")
691 return false;
692 if (info_a.bit_offset != info_b.bit_offset)
693 return false;
694 if (info_a.host_size != info_b.host_size)
695 return false;
696 if (info_a.@"allowzero" != info_b.@"allowzero")
697 return false;
698 if (info_a.mutable != info_b.mutable)
699 return false;
700 if (info_a.@"volatile" != info_b.@"volatile")
701 return false;
702 if (info_a.size != info_b.size)
703 return false;
704
705 const sentinel_a = info_a.sentinel;
706 const sentinel_b = info_b.sentinel;
707 if (sentinel_a) |sa| {
708 if (sentinel_b) |sb| {
709 if (!sa.eql(sb, info_a.pointee_type))
710 return false;
711 } else {
712 return false;
668 }713 }
714 } else {
715 if (sentinel_b != null)
716 return false;
669 }717 }
670 return a.tag() == b.tag();718
671 },719 return true;
672 .Opaque => {
673 const opaque_obj_a = a.castTag(.@"opaque").?.data;
674 const opaque_obj_b = b.castTag(.@"opaque").?.data;
675 return opaque_obj_a == opaque_obj_b;
676 },720 },
677 .Union => {721
678 if (a.cast(Payload.Union)) |a_payload| {722 .optional,
679 if (b.cast(Payload.Union)) |b_payload| {723 .optional_single_const_pointer,
680 return a_payload.data == b_payload.data;724 .optional_single_mut_pointer,
681 }725 => {
682 }726 if (b.zigTypeTag() != .Optional) return false;
683 return a.tag() == b.tag();727
728 var buf_a: Payload.ElemType = undefined;
729 var buf_b: Payload.ElemType = undefined;
730 return a.optionalChild(&buf_a).eql(b.optionalChild(&buf_b));
684 },731 },
685 .ErrorUnion => {732
733 .anyerror_void_error_union, .error_union => {
734 if (b.zigTypeTag() != .ErrorUnion) return false;
735
686 const a_set = a.errorUnionSet();736 const a_set = a.errorUnionSet();
687 const b_set = b.errorUnionSet();737 const b_set = b.errorUnionSet();
688 if (!a_set.eql(b_set)) return false;738 if (!a_set.eql(b_set)) return false;
...@@ -693,34 +743,100 @@ pub const Type = extern union {...@@ -693,34 +743,100 @@ pub const Type = extern union {
693743
694 return true;744 return true;
695 },745 },
696 .ErrorSet => {
697 // TODO: revisit the language specification for how to evaluate equality
698 // for error set types.
699746
700 if (a.tag() == .anyerror and b.tag() == .anyerror) {747 .anyframe_T => {
701 return true;748 if (b.zigTypeTag() != .AnyFrame) return false;
702 }749 return a.childType().eql(b.childType());
750 },
703751
704 if (a.tag() == .error_set and b.tag() == .error_set) {752 .empty_struct => {
705 return a.castTag(.error_set).?.data.owner_decl == b.castTag(.error_set).?.data.owner_decl;753 const a_namespace = a.castTag(.empty_struct).?.data;
706 }754 const b_namespace = (b.castTag(.empty_struct) orelse return false).data;
755 return a_namespace == b_namespace;
756 },
757 .@"struct" => {
758 const a_struct_obj = a.castTag(.@"struct").?.data;
759 const b_struct_obj = (b.castTag(.@"struct") orelse return false).data;
760 return a_struct_obj == b_struct_obj;
761 },
762 .tuple, .empty_struct_literal => {
763 if (!b.isTuple()) return false;
707764
708 if (a.tag() == .error_set_inferred and b.tag() == .error_set_inferred) {765 const a_tuple = a.tupleFields();
709 return a.castTag(.error_set_inferred).?.data == b.castTag(.error_set_inferred).?.data;766 const b_tuple = b.tupleFields();
767
768 if (a_tuple.types.len != b_tuple.types.len) return false;
769
770 for (a_tuple.types) |a_ty, i| {
771 const b_ty = b_tuple.types[i];
772 if (!eql(a_ty, b_ty)) return false;
710 }773 }
711774
712 if (a.tag() == .error_set_single and b.tag() == .error_set_single) {775 for (a_tuple.values) |a_val, i| {
713 const a_data = a.castTag(.error_set_single).?.data;776 const ty = a_tuple.types[i];
714 const b_data = b.castTag(.error_set_single).?.data;777 const b_val = b_tuple.values[i];
715 return std.mem.eql(u8, a_data, b_data);778 if (a_val.tag() == .unreachable_value) {
779 if (b_val.tag() == .unreachable_value) {
780 continue;
781 } else {
782 return false;
783 }
784 } else {
785 if (b_val.tag() == .unreachable_value) {
786 return false;
787 } else {
788 if (!Value.eql(a_val, b_val, ty)) return false;
789 }
790 }
716 }791 }
717 return false;792
793 return true;
718 },794 },
719 .Float => return a.tag() == b.tag(),
720795
721 .BoundFn,796 // we can't compare these based on tags because it wouldn't detect if,
722 .Frame,797 // for example, a was resolved into .@"struct" but b was one of these tags.
723 => std.debug.panic("TODO implement Type equality comparison of {} and {}", .{ a, b }),798 .call_options,
799 .prefetch_options,
800 .export_options,
801 .extern_options,
802 => unreachable, // needed to resolve the type before now
803
804 .enum_full, .enum_nonexhaustive => {
805 const a_enum_obj = a.cast(Payload.EnumFull).?.data;
806 const b_enum_obj = (b.cast(Payload.EnumFull) orelse return false).data;
807 return a_enum_obj == b_enum_obj;
808 },
809 .enum_simple => {
810 const a_enum_obj = a.cast(Payload.EnumSimple).?.data;
811 const b_enum_obj = (b.cast(Payload.EnumSimple) orelse return false).data;
812 return a_enum_obj == b_enum_obj;
813 },
814 .enum_numbered => {
815 const a_enum_obj = a.cast(Payload.EnumNumbered).?.data;
816 const b_enum_obj = (b.cast(Payload.EnumNumbered) orelse return false).data;
817 return a_enum_obj == b_enum_obj;
818 },
819 // we can't compare these based on tags because it wouldn't detect if,
820 // for example, a was resolved into .enum_simple but b was one of these tags.
821 .atomic_order,
822 .atomic_rmw_op,
823 .calling_convention,
824 .address_space,
825 .float_mode,
826 .reduce_op,
827 => unreachable, // needed to resolve the type before now
828
829 .@"union", .union_tagged => {
830 const a_union_obj = a.cast(Payload.Union).?.data;
831 const b_union_obj = (b.cast(Payload.Union) orelse return false).data;
832 return a_union_obj == b_union_obj;
833 },
834 // we can't compare these based on tags because it wouldn't detect if,
835 // for example, a was resolved into .union_tagged but b was one of these tags.
836 .type_info => unreachable, // needed to resolve the type before now
837
838 .bound_fn => unreachable,
839 .var_args_param => unreachable, // can be any type
724 }840 }
725 }841 }
726842
...@@ -730,8 +846,8 @@ pub const Type = extern union {...@@ -730,8 +846,8 @@ pub const Type = extern union {
730 return hasher.final();846 return hasher.final();
731 }847 }
732848
733 pub fn hashWithHasher(self: Type, hasher: *std.hash.Wyhash) void {849 pub fn hashWithHasher(ty: Type, hasher: *std.hash.Wyhash) void {
734 const zig_type_tag = self.zigTypeTag();850 const zig_type_tag = ty.zigTypeTag();
735 std.hash.autoHash(hasher, zig_type_tag);851 std.hash.autoHash(hasher, zig_type_tag);
736 switch (zig_type_tag) {852 switch (zig_type_tag) {
737 .Type,853 .Type,
...@@ -745,41 +861,58 @@ pub const Type = extern union {...@@ -745,41 +861,58 @@ pub const Type = extern union {
745 => {}, // The zig type tag is all that is needed to distinguish.861 => {}, // The zig type tag is all that is needed to distinguish.
746862
747 .Pointer => {863 .Pointer => {
748 // TODO implement more pointer type hashing864 const info = ty.ptrInfo().data;
865 hashWithHasher(info.pointee_type, hasher);
866 hashSentinel(info.sentinel, info.pointee_type, hasher);
867 std.hash.autoHash(hasher, info.@"align");
868 std.hash.autoHash(hasher, info.@"addrspace");
869 std.hash.autoHash(hasher, info.bit_offset);
870 std.hash.autoHash(hasher, info.host_size);
871 std.hash.autoHash(hasher, info.@"allowzero");
872 std.hash.autoHash(hasher, info.mutable);
873 std.hash.autoHash(hasher, info.@"volatile");
874 std.hash.autoHash(hasher, info.size);
749 },875 },
750 .Int => {876 .Int => {
751 // Detect that e.g. u64 != usize, even if the bits match on a particular target.877 // Detect that e.g. u64 != usize, even if the bits match on a particular target.
752 if (self.isNamedInt()) {878 if (ty.isNamedInt()) {
753 std.hash.autoHash(hasher, self.tag());879 std.hash.autoHash(hasher, ty.tag());
754 } else {880 } else {
755 // Remaining cases are arbitrary sized integers.881 // Remaining cases are arbitrary sized integers.
756 // The target will not be branched upon, because we handled target-dependent cases above.882 // The target will not be branched upon, because we handled target-dependent cases above.
757 const info = self.intInfo(@as(Target, undefined));883 const info = ty.intInfo(@as(Target, undefined));
758 std.hash.autoHash(hasher, info.signedness);884 std.hash.autoHash(hasher, info.signedness);
759 std.hash.autoHash(hasher, info.bits);885 std.hash.autoHash(hasher, info.bits);
760 }886 }
761 },887 },
762 .Array, .Vector => {888 .Array, .Vector => {
763 std.hash.autoHash(hasher, self.arrayLen());889 const elem_ty = ty.elemType();
764 std.hash.autoHash(hasher, self.elemType().hash());890 std.hash.autoHash(hasher, ty.arrayLen());
765 // TODO hash array sentinel891 hashWithHasher(elem_ty, hasher);
892 hashSentinel(ty.sentinel(), elem_ty, hasher);
766 },893 },
767 .Fn => {894 .Fn => {
768 std.hash.autoHash(hasher, self.fnReturnType().hash());895 const fn_info = ty.fnInfo();
769 std.hash.autoHash(hasher, self.fnCallingConvention());896 hashWithHasher(fn_info.return_type, hasher);
770 const params_len = self.fnParamLen();897 std.hash.autoHash(hasher, fn_info.alignment);
771 std.hash.autoHash(hasher, params_len);898 std.hash.autoHash(hasher, fn_info.cc);
772 var i: usize = 0;899 std.hash.autoHash(hasher, fn_info.is_var_args);
773 while (i < params_len) : (i += 1) {900 std.hash.autoHash(hasher, fn_info.is_generic);
774 std.hash.autoHash(hasher, self.fnParamType(i).hash());901
902 std.hash.autoHash(hasher, fn_info.param_types.len);
903 for (fn_info.param_types) |param_ty, i| {
904 std.hash.autoHash(hasher, fn_info.paramIsComptime(i));
905 if (param_ty.tag() == .generic_poison) continue;
906 hashWithHasher(param_ty, hasher);
775 }907 }
776 std.hash.autoHash(hasher, self.fnIsVarArgs());
777 },908 },
778 .Optional => {909 .Optional => {
779 var buf: Payload.ElemType = undefined;910 var buf: Payload.ElemType = undefined;
780 std.hash.autoHash(hasher, self.optionalChild(&buf).hash());911 hashWithHasher(ty.optionalChild(&buf), hasher);
912 },
913 .Float => {
914 std.hash.autoHash(hasher, ty.tag());
781 },915 },
782 .Float,
783 .Struct,916 .Struct,
784 .ErrorUnion,917 .ErrorUnion,
785 .ErrorSet,918 .ErrorSet,
...@@ -796,6 +929,15 @@ pub const Type = extern union {...@@ -796,6 +929,15 @@ pub const Type = extern union {
796 }929 }
797 }930 }
798931
932 fn hashSentinel(opt_val: ?Value, ty: Type, hasher: *std.hash.Wyhash) void {
933 if (opt_val) |s| {
934 std.hash.autoHash(hasher, true);
935 s.hash(ty, hasher);
936 } else {
937 std.hash.autoHash(hasher, false);
938 }
939 }
940
799 pub const HashContext64 = struct {941 pub const HashContext64 = struct {
800 pub fn hash(self: @This(), t: Type) u64 {942 pub fn hash(self: @This(), t: Type) u64 {
801 _ = self;943 _ = self;
...@@ -2834,8 +2976,8 @@ pub const Type = extern union {...@@ -2834,8 +2976,8 @@ pub const Type = extern union {
2834 /// For [*]T, returns *T2976 /// For [*]T, returns *T
2835 /// For []T, returns *T2977 /// For []T, returns *T
2836 /// Handles const-ness and address spaces in particular.2978 /// Handles const-ness and address spaces in particular.
2837 pub fn elemPtrType(ptr_ty: Type, arena: Allocator) !Type {2979 pub fn elemPtrType(ptr_ty: Type, arena: Allocator, target: Target) !Type {
2838 return try Type.ptr(arena, .{2980 return try Type.ptr(arena, target, .{
2839 .pointee_type = ptr_ty.elemType2(),2981 .pointee_type = ptr_ty.elemType2(),
2840 .mutable = ptr_ty.ptrIsMutable(),2982 .mutable = ptr_ty.ptrIsMutable(),
2841 .@"addrspace" = ptr_ty.ptrAddressSpace(),2983 .@"addrspace" = ptr_ty.ptrAddressSpace(),
...@@ -4635,6 +4777,8 @@ pub const Type = extern union {...@@ -4635,6 +4777,8 @@ pub const Type = extern union {
4635 pointee_type: Type,4777 pointee_type: Type,
4636 sentinel: ?Value = null,4778 sentinel: ?Value = null,
4637 /// If zero use pointee_type.abiAlignment()4779 /// If zero use pointee_type.abiAlignment()
4780 /// When creating pointer types, if alignment is equal to pointee type
4781 /// abi alignment, this value should be set to 0 instead.
4638 @"align": u32 = 0,4782 @"align": u32 = 0,
4639 /// See src/target.zig defaultAddressSpace function for how to obtain4783 /// See src/target.zig defaultAddressSpace function for how to obtain
4640 /// an appropriate value for this field.4784 /// an appropriate value for this field.
...@@ -4643,6 +4787,8 @@ pub const Type = extern union {...@@ -4643,6 +4787,8 @@ pub const Type = extern union {
4643 /// If this is non-zero it means the pointer points to a sub-byte4787 /// If this is non-zero it means the pointer points to a sub-byte
4644 /// range of data, which is backed by a "host integer" with this4788 /// range of data, which is backed by a "host integer" with this
4645 /// number of bytes.4789 /// number of bytes.
4790 /// When host_size=pointee_abi_size and bit_offset=0, this must be
4791 /// represented with host_size=0 instead.
4646 host_size: u16 = 0,4792 host_size: u16 = 0,
4647 @"allowzero": bool = false,4793 @"allowzero": bool = false,
4648 mutable: bool = true, // TODO rename this to const, not mutable4794 mutable: bool = true, // TODO rename this to const, not mutable
...@@ -4739,10 +4885,30 @@ pub const Type = extern union {...@@ -4739,10 +4885,30 @@ pub const Type = extern union {
4739 pub const @"type" = initTag(.type);4885 pub const @"type" = initTag(.type);
4740 pub const @"anyerror" = initTag(.anyerror);4886 pub const @"anyerror" = initTag(.anyerror);
47414887
4742 pub fn ptr(arena: Allocator, d: Payload.Pointer.Data) !Type {4888 pub fn ptr(arena: Allocator, target: Target, data: Payload.Pointer.Data) !Type {
4743 assert(d.host_size == 0 or d.bit_offset < d.host_size * 8);4889 var d = data;
4890
4744 if (d.size == .C) {4891 if (d.size == .C) {
4745 assert(d.@"allowzero"); // All C pointers must set allowzero to true.4892 d.@"allowzero" = true;
4893 }
4894
4895 // Canonicalize non-zero alignment. If it matches the ABI alignment of the pointee
4896 // type, we change it to 0 here. If this causes an assertion trip because the
4897 // pointee type needs to be resolved more, that needs to be done before calling
4898 // this ptr() function.
4899 if (d.@"align" != 0 and d.@"align" == d.pointee_type.abiAlignment(target)) {
4900 d.@"align" = 0;
4901 }
4902
4903 // Canonicalize host_size. If it matches the bit size of the pointee type,
4904 // we change it to 0 here. If this causes an assertion trip, the pointee type
4905 // needs to be resolved before calling this ptr() function.
4906 if (d.host_size != 0) {
4907 assert(d.bit_offset < d.host_size * 8);
4908 if (d.host_size * 8 == d.pointee_type.bitSize(target)) {
4909 assert(d.bit_offset == 0);
4910 d.host_size = 0;
4911 }
4746 }4912 }
47474913
4748 if (d.@"align" == 0 and d.@"addrspace" == .generic and4914 if (d.@"align" == 0 and d.@"addrspace" == .generic and
...@@ -4789,6 +4955,7 @@ pub const Type = extern union {...@@ -4789,6 +4955,7 @@ pub const Type = extern union {
4789 return Type.initPayload(&type_payload.base);4955 return Type.initPayload(&type_payload.base);
4790 }4956 }
4791 }4957 }
4958
4792 return Type.Tag.pointer.create(arena, d);4959 return Type.Tag.pointer.create(arena, d);
4793 }4960 }
47944961
test/behavior/align.zig+11-3
...@@ -6,6 +6,8 @@ const native_arch = builtin.target.cpu.arch;...@@ -6,6 +6,8 @@ const native_arch = builtin.target.cpu.arch;
6var foo: u8 align(4) = 100;6var foo: u8 align(4) = 100;
77
8test "global variable alignment" {8test "global variable alignment" {
9 if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
10
9 comptime try expect(@typeInfo(@TypeOf(&foo)).Pointer.alignment == 4);11 comptime try expect(@typeInfo(@TypeOf(&foo)).Pointer.alignment == 4);
10 comptime try expect(@TypeOf(&foo) == *align(4) u8);12 comptime try expect(@TypeOf(&foo) == *align(4) u8);
11 {13 {
...@@ -84,6 +86,8 @@ test "size of extern struct with 128-bit field" {...@@ -84,6 +86,8 @@ test "size of extern struct with 128-bit field" {
84}86}
8587
86test "@ptrCast preserves alignment of bigger source" {88test "@ptrCast preserves alignment of bigger source" {
89 if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
90
87 var x: u32 align(16) = 1234;91 var x: u32 align(16) = 1234;
88 const ptr = @ptrCast(*u8, &x);92 const ptr = @ptrCast(*u8, &x);
89 try expect(@TypeOf(ptr) == *align(16) u8);93 try expect(@TypeOf(ptr) == *align(16) u8);
...@@ -99,6 +103,7 @@ fn fnWithAlignedStack() i32 {...@@ -99,6 +103,7 @@ fn fnWithAlignedStack() i32 {
99}103}
100104
101test "implicitly decreasing slice alignment" {105test "implicitly decreasing slice alignment" {
106 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
102 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;107 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
103 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;108 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
104109
...@@ -111,6 +116,7 @@ fn addUnalignedSlice(a: []align(1) const u32, b: []align(1) const u32) u32 {...@@ -111,6 +116,7 @@ fn addUnalignedSlice(a: []align(1) const u32, b: []align(1) const u32) u32 {
111}116}
112117
113test "specifying alignment allows pointer cast" {118test "specifying alignment allows pointer cast" {
119 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
114 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;120 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
115 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;121 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
116122
...@@ -123,6 +129,7 @@ fn testBytesAlign(b: u8) !void {...@@ -123,6 +129,7 @@ fn testBytesAlign(b: u8) !void {
123}129}
124130
125test "@alignCast slices" {131test "@alignCast slices" {
132 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
126 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;133 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
127 if (builtin.zig_backend == .stage2_x86_64 or builtin.zig_backend == .stage2_arm) return error.SkipZigTest;134 if (builtin.zig_backend == .stage2_x86_64 or builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
128135
...@@ -260,9 +267,10 @@ fn whyWouldYouEverDoThis(comptime align_bytes: u8) align(align_bytes) u8 {...@@ -260,9 +267,10 @@ fn whyWouldYouEverDoThis(comptime align_bytes: u8) align(align_bytes) u8 {
260}267}
261268
262test "runtime known array index has best alignment possible" {269test "runtime known array index has best alignment possible" {
263 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;270 if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
264 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;271 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
265 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;272 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
273 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
266274
267 // take full advantage of over-alignment275 // take full advantage of over-alignment
268 var array align(4) = [_]u8{ 1, 2, 3, 4 };276 var array align(4) = [_]u8{ 1, 2, 3, 4 };
test/behavior/array.zig+1
...@@ -6,6 +6,7 @@ const expect = testing.expect;...@@ -6,6 +6,7 @@ const expect = testing.expect;
6const expectEqual = testing.expectEqual;6const expectEqual = testing.expectEqual;
77
8test "array to slice" {8test "array to slice" {
9 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
9 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;10 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
10 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;11 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
1112
test/behavior/ptrcast.zig+2
...@@ -63,6 +63,8 @@ const Bytes = struct {...@@ -63,6 +63,8 @@ const Bytes = struct {
63};63};
6464
65test "comptime ptrcast keeps larger alignment" {65test "comptime ptrcast keeps larger alignment" {
66 if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
67
66 comptime {68 comptime {
67 const a: u32 = 1234;69 const a: u32 = 1234;
68 const p = @ptrCast([*]const u8, &a);70 const p = @ptrCast([*]const u8, &a);
test/behavior/union.zig-2
...@@ -876,8 +876,6 @@ test "union no tag with struct member" {...@@ -876,8 +876,6 @@ test "union no tag with struct member" {
876}876}
877877
878test "union with comptime_int tag" {878test "union with comptime_int tag" {
879 if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
880
881 const Union = union(enum(comptime_int)) {879 const Union = union(enum(comptime_int)) {
882 X: u32,880 X: u32,
883 Y: u16,881 Y: u16,