authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-09-25 22:18:43-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-09-25 22:18:43-07:00
log1f2f9f05c254374044d8c30cce6f299d7a18da72
tree868df45684a4db5f092b4106e7b17ddb05fbda1e
parent04366576ea4be4959b596ebff7041d17e18d08d8

stage2: implement zirCoerceResultPtr

and remove Module.simplePtrType and Module.ptrType in favor of `Type.ptr`.

5 files changed, 239 insertions(+), 271 deletions(-)

src/Module.zig-76
...@@ -4460,82 +4460,6 @@ pub fn failWithOwnedErrorMsg(mod: *Module, scope: *Scope, err_msg: *ErrorMsg) Co...@@ -4460,82 +4460,6 @@ pub fn failWithOwnedErrorMsg(mod: *Module, scope: *Scope, err_msg: *ErrorMsg) Co
4460 return error.AnalysisFail;4460 return error.AnalysisFail;
4461}4461}
44624462
4463pub fn simplePtrType(
4464 arena: *Allocator,
4465 elem_ty: Type,
4466 mutable: bool,
4467 size: std.builtin.TypeInfo.Pointer.Size,
4468 @"addrspace": std.builtin.AddressSpace,
4469) Allocator.Error!Type {
4470 return ptrType(
4471 arena,
4472 elem_ty,
4473 null,
4474 0,
4475 @"addrspace",
4476 0,
4477 0,
4478 mutable,
4479 false,
4480 false,
4481 size,
4482 );
4483}
4484
4485pub fn ptrType(
4486 arena: *Allocator,
4487 elem_ty: Type,
4488 sentinel: ?Value,
4489 @"align": u32,
4490 @"addrspace": std.builtin.AddressSpace,
4491 bit_offset: u16,
4492 host_size: u16,
4493 mutable: bool,
4494 @"allowzero": bool,
4495 @"volatile": bool,
4496 size: std.builtin.TypeInfo.Pointer.Size,
4497) Allocator.Error!Type {
4498 assert(host_size == 0 or bit_offset < host_size * 8);
4499
4500 if (sentinel != null or @"align" != 0 or @"addrspace" != .generic or
4501 bit_offset != 0 or host_size != 0 or @"allowzero" or @"volatile")
4502 {
4503 return Type.Tag.pointer.create(arena, .{
4504 .pointee_type = elem_ty,
4505 .sentinel = sentinel,
4506 .@"align" = @"align",
4507 .@"addrspace" = @"addrspace",
4508 .bit_offset = bit_offset,
4509 .host_size = host_size,
4510 .@"allowzero" = @"allowzero",
4511 .mutable = mutable,
4512 .@"volatile" = @"volatile",
4513 .size = size,
4514 });
4515 }
4516
4517 if (!mutable and size == .Slice and elem_ty.eql(Type.initTag(.u8))) {
4518 return Type.initTag(.const_slice_u8);
4519 }
4520
4521 // TODO stage1 type inference bug
4522 const T = Type.Tag;
4523
4524 const type_payload = try arena.create(Type.Payload.ElemType);
4525 type_payload.* = .{
4526 .base = .{
4527 .tag = switch (size) {
4528 .One => if (mutable) T.single_mut_pointer else T.single_const_pointer,
4529 .Many => if (mutable) T.many_mut_pointer else T.many_const_pointer,
4530 .C => if (mutable) T.c_mut_pointer else T.c_const_pointer,
4531 .Slice => if (mutable) T.mut_slice else T.const_slice,
4532 },
4533 },
4534 .data = elem_ty,
4535 };
4536 return Type.initPayload(&type_payload.base);
4537}
4538
4539pub fn optionalType(arena: *Allocator, child_type: Type) Allocator.Error!Type {4463pub fn optionalType(arena: *Allocator, child_type: Type) Allocator.Error!Type {
4540 switch (child_type.tag()) {4464 switch (child_type.tag()) {
4541 .single_const_pointer => return Type.Tag.optional_single_const_pointer.create(4465 .single_const_pointer => return Type.Tag.optional_single_const_pointer.create(
src/Sema.zig+149-157
...@@ -979,10 +979,38 @@ fn zirBitcastResultPtr(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) C...@@ -979,10 +979,38 @@ fn zirBitcastResultPtr(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) C
979}979}
980980
981fn zirCoerceResultPtr(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {981fn zirCoerceResultPtr(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
982 _ = inst;
983 const tracy = trace(@src());982 const tracy = trace(@src());
984 defer tracy.end();983 defer tracy.end();
985 return sema.mod.fail(&block.base, sema.src, "TODO implement zirCoerceResultPtr", .{});984
985 const src: LazySrcLoc = sema.src;
986 const bin_inst = sema.code.instructions.items(.data)[inst].bin;
987 const pointee_ty = try sema.resolveType(block, src, bin_inst.lhs);
988 const ptr = sema.resolveInst(bin_inst.rhs);
989
990 // Create a runtime bitcast instruction with exactly the type the pointer wants.
991 const ptr_ty = try Type.ptr(sema.arena, .{
992 .pointee_type = pointee_ty,
993 .@"addrspace" = target_util.defaultAddressSpace(sema.mod.getTarget(), .local),
994 });
995 try sema.requireRuntimeBlock(block, src);
996 const bitcasted_ptr = try block.addTyOp(.bitcast, ptr_ty, ptr);
997
998 if (Air.refToIndex(ptr)) |ptr_inst| {
999 if (sema.air_instructions.items(.tag)[ptr_inst] == .constant) {
1000 const air_datas = sema.air_instructions.items(.data);
1001 const ptr_val = sema.air_values.items[air_datas[ptr_inst].ty_pl.payload];
1002 if (ptr_val.castTag(.inferred_alloc)) |inferred_alloc| {
1003 // Add the stored instruction to the set we will use to resolve peer types
1004 // for the inferred allocation.
1005 // This instruction will not make it to codegen; it is only to participate
1006 // in the `stored_inst_list` of the `inferred_alloc`.
1007 const operand = try block.addTyOp(.bitcast, pointee_ty, .void_value);
1008 try inferred_alloc.data.stored_inst_list.append(sema.arena, operand);
1009 }
1010 }
1011 }
1012
1013 return bitcasted_ptr;
986}1014}
9871015
988pub fn analyzeStructDecl(1016pub fn analyzeStructDecl(
...@@ -1427,13 +1455,10 @@ fn zirRetPtr(...@@ -1427,13 +1455,10 @@ fn zirRetPtr(
1427 return sema.analyzeComptimeAlloc(block, sema.fn_ret_ty);1455 return sema.analyzeComptimeAlloc(block, sema.fn_ret_ty);
1428 }1456 }
14291457
1430 const ptr_type = try Module.simplePtrType(1458 const ptr_type = try Type.ptr(sema.arena, .{
1431 sema.arena,1459 .pointee_type = sema.fn_ret_ty,
1432 sema.fn_ret_ty,1460 .@"addrspace" = target_util.defaultAddressSpace(sema.mod.getTarget(), .local),
1433 true,1461 });
1434 .One,
1435 target_util.defaultAddressSpace(sema.mod.getTarget(), .local),
1436 );
1437 return block.addTy(.alloc, ptr_type);1462 return block.addTy(.alloc, ptr_type);
1438}1463}
14391464
...@@ -1581,13 +1606,10 @@ fn zirAlloc(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError...@@ -1581,13 +1606,10 @@ fn zirAlloc(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError
1581 const ty_src: LazySrcLoc = .{ .node_offset_var_decl_ty = inst_data.src_node };1606 const ty_src: LazySrcLoc = .{ .node_offset_var_decl_ty = inst_data.src_node };
1582 const var_decl_src = inst_data.src();1607 const var_decl_src = inst_data.src();
1583 const var_type = try sema.resolveType(block, ty_src, inst_data.operand);1608 const var_type = try sema.resolveType(block, ty_src, inst_data.operand);
1584 const ptr_type = try Module.simplePtrType(1609 const ptr_type = try Type.ptr(sema.arena, .{
1585 sema.arena,1610 .pointee_type = var_type,
1586 var_type,1611 .@"addrspace" = target_util.defaultAddressSpace(sema.mod.getTarget(), .local),
1587 true,1612 });
1588 .One,
1589 target_util.defaultAddressSpace(sema.mod.getTarget(), .local),
1590 );
1591 try sema.requireRuntimeBlock(block, var_decl_src);1613 try sema.requireRuntimeBlock(block, var_decl_src);
1592 return block.addTy(.alloc, ptr_type);1614 return block.addTy(.alloc, ptr_type);
1593}1615}
...@@ -1604,13 +1626,10 @@ fn zirAllocMut(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileEr...@@ -1604,13 +1626,10 @@ fn zirAllocMut(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileEr
1604 return sema.analyzeComptimeAlloc(block, var_type);1626 return sema.analyzeComptimeAlloc(block, var_type);
1605 }1627 }
1606 try sema.validateVarType(block, ty_src, var_type);1628 try sema.validateVarType(block, ty_src, var_type);
1607 const ptr_type = try Module.simplePtrType(1629 const ptr_type = try Type.ptr(sema.arena, .{
1608 sema.arena,1630 .pointee_type = var_type,
1609 var_type,1631 .@"addrspace" = target_util.defaultAddressSpace(sema.mod.getTarget(), .local),
1610 true,1632 });
1611 .One,
1612 target_util.defaultAddressSpace(sema.mod.getTarget(), .local),
1613 );
1614 try sema.requireRuntimeBlock(block, var_decl_src);1633 try sema.requireRuntimeBlock(block, var_decl_src);
1615 return block.addTy(.alloc, ptr_type);1634 return block.addTy(.alloc, ptr_type);
1616}1635}
...@@ -1670,13 +1689,10 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Inde...@@ -1670,13 +1689,10 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Inde
1670 try sema.mod.declareDeclDependency(sema.owner_decl, decl);1689 try sema.mod.declareDeclDependency(sema.owner_decl, decl);
16711690
1672 const final_elem_ty = try decl.ty.copy(sema.arena);1691 const final_elem_ty = try decl.ty.copy(sema.arena);
1673 const final_ptr_ty = try Module.simplePtrType(1692 const final_ptr_ty = try Type.ptr(sema.arena, .{
1674 sema.arena,1693 .pointee_type = final_elem_ty,
1675 final_elem_ty,1694 .@"addrspace" = target_util.defaultAddressSpace(sema.mod.getTarget(), .local),
1676 true,1695 });
1677 .One,
1678 target_util.defaultAddressSpace(sema.mod.getTarget(), .local),
1679 );
1680 const final_ptr_ty_inst = try sema.addType(final_ptr_ty);1696 const final_ptr_ty_inst = try sema.addType(final_ptr_ty);
1681 sema.air_instructions.items(.data)[ptr_inst].ty_pl.ty = final_ptr_ty_inst;1697 sema.air_instructions.items(.data)[ptr_inst].ty_pl.ty = final_ptr_ty_inst;
16821698
...@@ -1698,13 +1714,10 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Inde...@@ -1698,13 +1714,10 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Inde
1698 try sema.validateVarType(block, ty_src, final_elem_ty);1714 try sema.validateVarType(block, ty_src, final_elem_ty);
1699 }1715 }
1700 // Change it to a normal alloc.1716 // Change it to a normal alloc.
1701 const final_ptr_ty = try Module.simplePtrType(1717 const final_ptr_ty = try Type.ptr(sema.arena, .{
1702 sema.arena,1718 .pointee_type = final_elem_ty,
1703 final_elem_ty,1719 .@"addrspace" = target_util.defaultAddressSpace(sema.mod.getTarget(), .local),
1704 true,1720 });
1705 .One,
1706 target_util.defaultAddressSpace(sema.mod.getTarget(), .local),
1707 );
1708 sema.air_instructions.set(ptr_inst, .{1721 sema.air_instructions.set(ptr_inst, .{
1709 .tag = .alloc,1722 .tag = .alloc,
1710 .data = .{ .ty = final_ptr_ty },1723 .data = .{ .ty = final_ptr_ty },
...@@ -1858,14 +1871,11 @@ fn zirStoreToBlockPtr(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) Co...@@ -1858,14 +1871,11 @@ fn zirStoreToBlockPtr(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) Co
1858 }1871 }
1859 const ptr = sema.resolveInst(bin_inst.lhs);1872 const ptr = sema.resolveInst(bin_inst.lhs);
1860 const value = sema.resolveInst(bin_inst.rhs);1873 const value = sema.resolveInst(bin_inst.rhs);
1861 const ptr_ty = try Module.simplePtrType(1874 const ptr_ty = try Type.ptr(sema.arena, .{
1862 sema.arena,1875 .pointee_type = sema.typeOf(value),
1863 sema.typeOf(value),
1864 true,
1865 .One,
1866 // TODO figure out which address space is appropriate here1876 // TODO figure out which address space is appropriate here
1867 target_util.defaultAddressSpace(sema.mod.getTarget(), .local),1877 .@"addrspace" = target_util.defaultAddressSpace(sema.mod.getTarget(), .local),
1868 );1878 });
1869 // TODO detect when this store should be done at compile-time. For example,1879 // TODO detect when this store should be done at compile-time. For example,
1870 // if expressions should force it when the condition is compile-time known.1880 // if expressions should force it when the condition is compile-time known.
1871 const src: LazySrcLoc = .unneeded;1881 const src: LazySrcLoc = .unneeded;
...@@ -1912,14 +1922,10 @@ fn zirStoreToInferredPtr(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index)...@@ -1912,14 +1922,10 @@ fn zirStoreToInferredPtr(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index)
1912 // for the inferred allocation.1922 // for the inferred allocation.
1913 try inferred_alloc.data.stored_inst_list.append(sema.arena, operand);1923 try inferred_alloc.data.stored_inst_list.append(sema.arena, operand);
1914 // Create a runtime bitcast instruction with exactly the type the pointer wants.1924 // Create a runtime bitcast instruction with exactly the type the pointer wants.
1915 const ptr_ty = try Module.simplePtrType(1925 const ptr_ty = try Type.ptr(sema.arena, .{
1916 sema.arena,1926 .pointee_type = operand_ty,
1917 operand_ty,1927 .@"addrspace" = target_util.defaultAddressSpace(sema.mod.getTarget(), .local),
1918 true,1928 });
1919 .One,
1920 // TODO figure out which address space is appropriate here
1921 target_util.defaultAddressSpace(sema.mod.getTarget(), .local),
1922 );
1923 const bitcasted_ptr = try block.addTyOp(.bitcast, ptr_ty, ptr);1929 const bitcasted_ptr = try block.addTyOp(.bitcast, ptr_ty, ptr);
1924 return sema.storePtr(block, src, bitcasted_ptr, operand);1930 return sema.storePtr(block, src, bitcasted_ptr, operand);
1925 }1931 }
...@@ -3845,13 +3851,11 @@ fn zirOptionalPayloadPtr(...@@ -3845,13 +3851,11 @@ fn zirOptionalPayloadPtr(
3845 }3851 }
38463852
3847 const child_type = try opt_type.optionalChildAlloc(sema.arena);3853 const child_type = try opt_type.optionalChildAlloc(sema.arena);
3848 const child_pointer = try Module.simplePtrType(3854 const child_pointer = try Type.ptr(sema.arena, .{
3849 sema.arena,3855 .pointee_type = child_type,
3850 child_type,3856 .mutable = !optional_ptr_ty.isConstPtr(),
3851 !optional_ptr_ty.isConstPtr(),3857 .@"addrspace" = optional_ptr_ty.ptrAddressSpace(),
3852 .One,3858 });
3853 optional_ptr_ty.ptrAddressSpace(),
3854 );
38553859
3856 if (try sema.resolveDefinedValue(block, src, optional_ptr)) |pointer_val| {3860 if (try sema.resolveDefinedValue(block, src, optional_ptr)) |pointer_val| {
3857 if (try pointer_val.pointerDeref(sema.arena)) |val| {3861 if (try pointer_val.pointerDeref(sema.arena)) |val| {
...@@ -3966,13 +3970,11 @@ fn zirErrUnionPayloadPtr(...@@ -3966,13 +3970,11 @@ fn zirErrUnionPayloadPtr(
3966 return sema.mod.fail(&block.base, src, "expected error union type, found {}", .{operand_ty.elemType()});3970 return sema.mod.fail(&block.base, src, "expected error union type, found {}", .{operand_ty.elemType()});
39673971
3968 const payload_ty = operand_ty.elemType().errorUnionPayload();3972 const payload_ty = operand_ty.elemType().errorUnionPayload();
3969 const operand_pointer_ty = try Module.simplePtrType(3973 const operand_pointer_ty = try Type.ptr(sema.arena, .{
3970 sema.arena,3974 .pointee_type = payload_ty,
3971 payload_ty,3975 .mutable = !operand_ty.isConstPtr(),
3972 !operand_ty.isConstPtr(),3976 .@"addrspace" = operand_ty.ptrAddressSpace(),
3973 .One,3977 });
3974 operand_ty.ptrAddressSpace(),
3975 );
39763978
3977 if (try sema.resolveDefinedValue(block, src, operand)) |pointer_val| {3979 if (try sema.resolveDefinedValue(block, src, operand)) |pointer_val| {
3978 if (try pointer_val.pointerDeref(sema.arena)) |val| {3980 if (try pointer_val.pointerDeref(sema.arena)) |val| {
...@@ -7306,19 +7308,14 @@ fn zirPtrTypeSimple(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) Comp...@@ -7306,19 +7308,14 @@ fn zirPtrTypeSimple(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) Comp
73067308
7307 const inst_data = sema.code.instructions.items(.data)[inst].ptr_type_simple;7309 const inst_data = sema.code.instructions.items(.data)[inst].ptr_type_simple;
7308 const elem_type = try sema.resolveType(block, .unneeded, inst_data.elem_type);7310 const elem_type = try sema.resolveType(block, .unneeded, inst_data.elem_type);
7309 const ty = try Module.ptrType(7311 const ty = try Type.ptr(sema.arena, .{
7310 sema.arena,7312 .pointee_type = elem_type,
7311 elem_type,7313 .@"addrspace" = .generic,
7312 null,7314 .mutable = inst_data.is_mutable,
7313 0,7315 .@"allowzero" = inst_data.is_allowzero,
7314 .generic,7316 .@"volatile" = inst_data.is_volatile,
7315 0,7317 .size = inst_data.size,
7316 0,7318 });
7317 inst_data.is_mutable,
7318 inst_data.is_allowzero,
7319 inst_data.is_volatile,
7320 inst_data.size,
7321 );
7322 return sema.addType(ty);7319 return sema.addType(ty);
7323}7320}
73247321
...@@ -7367,19 +7364,18 @@ fn zirPtrType(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileErr...@@ -7367,19 +7364,18 @@ fn zirPtrType(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileErr
73677364
7368 const elem_type = try sema.resolveType(block, .unneeded, extra.data.elem_type);7365 const elem_type = try sema.resolveType(block, .unneeded, extra.data.elem_type);
73697366
7370 const ty = try Module.ptrType(7367 const ty = try Type.ptr(sema.arena, .{
7371 sema.arena,7368 .pointee_type = elem_type,
7372 elem_type,7369 .sentinel = sentinel,
7373 sentinel,7370 .@"align" = abi_align,
7374 abi_align,7371 .@"addrspace" = address_space,
7375 address_space,7372 .bit_offset = bit_start,
7376 bit_start,7373 .host_size = bit_end,
7377 bit_end,7374 .mutable = inst_data.flags.is_mutable,
7378 inst_data.flags.is_mutable,7375 .@"allowzero" = inst_data.flags.is_allowzero,
7379 inst_data.flags.is_allowzero,7376 .@"volatile" = inst_data.flags.is_volatile,
7380 inst_data.flags.is_volatile,7377 .size = inst_data.size,
7381 inst_data.size,7378 });
7382 );
7383 return sema.addType(ty);7379 return sema.addType(ty);
7384}7380}
73857381
...@@ -8456,19 +8452,15 @@ fn zirMemcpy(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileErro...@@ -8456,19 +8452,15 @@ fn zirMemcpy(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileErro
8456 });8452 });
8457 }8453 }
8458 const src_ptr_info = uncasted_src_ptr_ty.ptrInfo().data;8454 const src_ptr_info = uncasted_src_ptr_ty.ptrInfo().data;
8459 const wanted_src_ptr_ty = try Module.ptrType(8455 const wanted_src_ptr_ty = try Type.ptr(sema.arena, .{
8460 sema.arena,8456 .pointee_type = dest_ptr_ty.elemType2(),
8461 dest_ptr_ty.elemType2(),8457 .@"align" = src_ptr_info.@"align",
8462 null,8458 .@"addrspace" = src_ptr_info.@"addrspace",
8463 src_ptr_info.@"align",8459 .mutable = false,
8464 src_ptr_info.@"addrspace",8460 .@"allowzero" = src_ptr_info.@"allowzero",
8465 0,8461 .@"volatile" = src_ptr_info.@"volatile",
8466 0,8462 .size = .Many,
8467 false,8463 });
8468 src_ptr_info.@"allowzero",
8469 src_ptr_info.@"volatile",
8470 .Many,
8471 );
8472 const src_ptr = try sema.coerce(block, wanted_src_ptr_ty, uncasted_src_ptr, src_src);8464 const src_ptr = try sema.coerce(block, wanted_src_ptr_ty, uncasted_src_ptr, src_src);
8473 const len = try sema.coerce(block, Type.initTag(.usize), sema.resolveInst(extra.byte_count), len_src);8465 const len = try sema.coerce(block, Type.initTag(.usize), sema.resolveInst(extra.byte_count), len_src);
84748466
...@@ -8922,13 +8914,10 @@ fn panicWithMsg(...@@ -8922,13 +8914,10 @@ fn panicWithMsg(
8922 const panic_fn = try sema.getBuiltin(block, src, "panic");8914 const panic_fn = try sema.getBuiltin(block, src, "panic");
8923 const unresolved_stack_trace_ty = try sema.getBuiltinType(block, src, "StackTrace");8915 const unresolved_stack_trace_ty = try sema.getBuiltinType(block, src, "StackTrace");
8924 const stack_trace_ty = try sema.resolveTypeFields(block, src, unresolved_stack_trace_ty);8916 const stack_trace_ty = try sema.resolveTypeFields(block, src, unresolved_stack_trace_ty);
8925 const ptr_stack_trace_ty = try Module.simplePtrType(8917 const ptr_stack_trace_ty = try Type.ptr(arena, .{
8926 arena,8918 .pointee_type = stack_trace_ty,
8927 stack_trace_ty,8919 .@"addrspace" = target_util.defaultAddressSpace(sema.mod.getTarget(), .global_constant), // TODO might need a place that is more dynamic
8928 true,8920 });
8929 .One,
8930 target_util.defaultAddressSpace(sema.mod.getTarget(), .global_constant), // TODO might need a place that is more dynamic
8931 );
8932 const null_stack_trace = try sema.addConstant(8921 const null_stack_trace = try sema.addConstant(
8933 try Module.optionalType(arena, ptr_stack_trace_ty),8922 try Module.optionalType(arena, ptr_stack_trace_ty),
8934 Value.initTag(.null_value),8923 Value.initTag(.null_value),
...@@ -9407,13 +9396,11 @@ fn structFieldPtr(...@@ -9407,13 +9396,11 @@ fn structFieldPtr(
9407 const field_index = struct_obj.fields.getIndex(field_name) orelse9396 const field_index = struct_obj.fields.getIndex(field_name) orelse
9408 return sema.failWithBadFieldAccess(block, struct_obj, field_name_src, field_name);9397 return sema.failWithBadFieldAccess(block, struct_obj, field_name_src, field_name);
9409 const field = struct_obj.fields.values()[field_index];9398 const field = struct_obj.fields.values()[field_index];
9410 const ptr_field_ty = try Module.simplePtrType(9399 const ptr_field_ty = try Type.ptr(arena, .{
9411 arena,9400 .pointee_type = field.ty,
9412 field.ty,9401 .mutable = struct_ptr_ty.ptrIsMutable(),
9413 struct_ptr_ty.ptrIsMutable(),9402 .@"addrspace" = struct_ptr_ty.ptrAddressSpace(),
9414 .One,9403 });
9415 struct_ptr_ty.ptrAddressSpace(),
9416 );
94179404
9418 if (try sema.resolveDefinedValue(block, src, struct_ptr)) |struct_ptr_val| {9405 if (try sema.resolveDefinedValue(block, src, struct_ptr)) |struct_ptr_val| {
9419 return sema.addConstant(9406 return sema.addConstant(
...@@ -9512,13 +9499,11 @@ fn unionFieldPtr(...@@ -9512,13 +9499,11 @@ fn unionFieldPtr(
9512 return sema.failWithBadUnionFieldAccess(block, union_obj, field_name_src, field_name);9499 return sema.failWithBadUnionFieldAccess(block, union_obj, field_name_src, field_name);
95139500
9514 const field = union_obj.fields.values()[field_index];9501 const field = union_obj.fields.values()[field_index];
9515 const ptr_field_ty = try Module.simplePtrType(9502 const ptr_field_ty = try Type.ptr(arena, .{
9516 arena,9503 .pointee_type = field.ty,
9517 field.ty,9504 .mutable = union_ptr_ty.ptrIsMutable(),
9518 union_ptr_ty.ptrIsMutable(),9505 .@"addrspace" = union_ptr_ty.ptrAddressSpace(),
9519 .One,9506 });
9520 union_ptr_ty.ptrAddressSpace(),
9521 );
95229507
9523 if (try sema.resolveDefinedValue(block, src, union_ptr)) |union_ptr_val| {9508 if (try sema.resolveDefinedValue(block, src, union_ptr)) |union_ptr_val| {
9524 // TODO detect inactive union field and emit compile error9509 // TODO detect inactive union field and emit compile error
...@@ -9694,13 +9679,11 @@ fn elemPtrArray(...@@ -9694,13 +9679,11 @@ fn elemPtrArray(
9694) CompileError!Air.Inst.Ref {9679) CompileError!Air.Inst.Ref {
9695 const array_ptr_ty = sema.typeOf(array_ptr);9680 const array_ptr_ty = sema.typeOf(array_ptr);
9696 const pointee_type = array_ptr_ty.elemType().elemType();9681 const pointee_type = array_ptr_ty.elemType().elemType();
9697 const result_ty = try Module.simplePtrType(9682 const result_ty = try Type.ptr(sema.arena, .{
9698 sema.arena,9683 .pointee_type = pointee_type,
9699 pointee_type,9684 .mutable = array_ptr_ty.ptrIsMutable(),
9700 array_ptr_ty.ptrIsMutable(),9685 .@"addrspace" = array_ptr_ty.ptrAddressSpace(),
9701 .One,9686 });
9702 array_ptr_ty.ptrAddressSpace(),
9703 );
97049687
9705 if (try sema.resolveDefinedValue(block, src, array_ptr)) |array_ptr_val| {9688 if (try sema.resolveDefinedValue(block, src, array_ptr)) |array_ptr_val| {
9706 if (try sema.resolveDefinedValue(block, elem_index_src, elem_index)) |index_val| {9689 if (try sema.resolveDefinedValue(block, elem_index_src, elem_index)) |index_val| {
...@@ -10243,11 +10226,19 @@ fn analyzeDeclRef(sema: *Sema, decl: *Decl) CompileError!Air.Inst.Ref {...@@ -10243,11 +10226,19 @@ fn analyzeDeclRef(sema: *Sema, decl: *Decl) CompileError!Air.Inst.Ref {
10243 const decl_tv = try decl.typedValue();10226 const decl_tv = try decl.typedValue();
10244 if (decl_tv.val.castTag(.variable)) |payload| {10227 if (decl_tv.val.castTag(.variable)) |payload| {
10245 const variable = payload.data;10228 const variable = payload.data;
10246 const ty = try Module.simplePtrType(sema.arena, decl_tv.ty, variable.is_mutable, .One, decl.@"addrspace");10229 const ty = try Type.ptr(sema.arena, .{
10230 .pointee_type = decl_tv.ty,
10231 .mutable = variable.is_mutable,
10232 .@"addrspace" = decl.@"addrspace",
10233 });
10247 return sema.addConstant(ty, try Value.Tag.decl_ref.create(sema.arena, decl));10234 return sema.addConstant(ty, try Value.Tag.decl_ref.create(sema.arena, decl));
10248 }10235 }
10249 return sema.addConstant(10236 return sema.addConstant(
10250 try Module.simplePtrType(sema.arena, decl_tv.ty, false, .One, decl.@"addrspace"),10237 try Type.ptr(sema.arena, .{
10238 .pointee_type = decl_tv.ty,
10239 .mutable = false,
10240 .@"addrspace" = decl.@"addrspace",
10241 }),
10251 try Value.Tag.decl_ref.create(sema.arena, decl),10242 try Value.Tag.decl_ref.create(sema.arena, decl),
10252 );10243 );
10253}10244}
...@@ -10271,8 +10262,15 @@ fn analyzeRef(...@@ -10271,8 +10262,15 @@ fn analyzeRef(
1027110262
10272 try sema.requireRuntimeBlock(block, src);10263 try sema.requireRuntimeBlock(block, src);
10273 const address_space = target_util.defaultAddressSpace(sema.mod.getTarget(), .local);10264 const address_space = target_util.defaultAddressSpace(sema.mod.getTarget(), .local);
10274 const ptr_type = try Module.simplePtrType(sema.arena, operand_ty, false, .One, address_space);10265 const ptr_type = try Type.ptr(sema.arena, .{
10275 const mut_ptr_type = try Module.simplePtrType(sema.arena, operand_ty, true, .One, address_space);10266 .pointee_type = operand_ty,
10267 .mutable = false,
10268 .@"addrspace" = address_space,
10269 });
10270 const mut_ptr_type = try Type.ptr(sema.arena, .{
10271 .pointee_type = operand_ty,
10272 .@"addrspace" = address_space,
10273 });
10276 const alloc = try block.addTy(.alloc, mut_ptr_type);10274 const alloc = try block.addTy(.alloc, mut_ptr_type);
10277 try sema.storePtr(block, src, alloc, operand);10275 try sema.storePtr(block, src, alloc, operand);
1027810276
...@@ -10428,19 +10426,16 @@ fn analyzeSlice(...@@ -10428,19 +10426,16 @@ fn analyzeSlice(
10428 }10426 }
10429 }10427 }
10430 }10428 }
10431 const return_type = try Module.ptrType(10429 const return_type = try Type.ptr(sema.arena, .{
10432 sema.arena,10430 .pointee_type = return_elem_type,
10433 return_elem_type,10431 .sentinel = if (end_opt == .none) slice_sentinel else null,
10434 if (end_opt == .none) slice_sentinel else null,10432 .@"align" = 0, // TODO alignment
10435 0, // TODO alignment10433 .@"addrspace" = if (ptr_child.zigTypeTag() == .Pointer) ptr_child.ptrAddressSpace() else .generic,
10436 if (ptr_child.zigTypeTag() == .Pointer) ptr_child.ptrAddressSpace() else .generic,10434 .mutable = !ptr_child.isConstPtr(),
10437 0,10435 .@"allowzero" = ptr_child.isAllowzeroPtr(),
10438 0,10436 .@"volatile" = ptr_child.isVolatilePtr(),
10439 !ptr_child.isConstPtr(),10437 .size = return_ptr_size,
10440 ptr_child.isAllowzeroPtr(),10438 });
10441 ptr_child.isVolatilePtr(),
10442 return_ptr_size,
10443 );
10444 _ = return_type;10439 _ = return_type;
1044510440
10446 return sema.mod.fail(&block.base, src, "TODO implement analysis of slice", .{});10441 return sema.mod.fail(&block.base, src, "TODO implement analysis of slice", .{});
...@@ -11626,13 +11621,10 @@ fn analyzeComptimeAlloc(...@@ -11626,13 +11621,10 @@ fn analyzeComptimeAlloc(
11626 block: *Scope.Block,11621 block: *Scope.Block,
11627 var_type: Type,11622 var_type: Type,
11628) CompileError!Air.Inst.Ref {11623) CompileError!Air.Inst.Ref {
11629 const ptr_type = try Module.simplePtrType(11624 const ptr_type = try Type.ptr(sema.arena, .{
11630 sema.arena,11625 .pointee_type = var_type,
11631 var_type,11626 .@"addrspace" = target_util.defaultAddressSpace(sema.mod.getTarget(), .global_constant),
11632 true,11627 });
11633 .One,
11634 target_util.defaultAddressSpace(sema.mod.getTarget(), .global_constant),
11635 );
1163611628
11637 var anon_decl = try block.startAnonDecl();11629 var anon_decl = try block.startAnonDecl();
11638 defer anon_decl.deinit();11630 defer anon_decl.deinit();
src/type.zig+48-13
...@@ -3652,12 +3652,12 @@ pub const Type = extern union {...@@ -3652,12 +3652,12 @@ pub const Type = extern union {
3652 }3652 }
36533653
3654 pub fn create(comptime t: Tag, ally: *Allocator, data: Data(t)) error{OutOfMemory}!file_struct.Type {3654 pub fn create(comptime t: Tag, ally: *Allocator, data: Data(t)) error{OutOfMemory}!file_struct.Type {
3655 const ptr = try ally.create(t.Type());3655 const p = try ally.create(t.Type());
3656 ptr.* = .{3656 p.* = .{
3657 .base = .{ .tag = t },3657 .base = .{ .tag = t },
3658 .data = data,3658 .data = data,
3659 };3659 };
3660 return file_struct.Type{ .ptr_otherwise = &ptr.base };3660 return file_struct.Type{ .ptr_otherwise = &p.base };
3661 }3661 }
36623662
3663 pub fn Data(comptime t: Tag) type {3663 pub fn Data(comptime t: Tag) type {
...@@ -3747,19 +3747,23 @@ pub const Type = extern union {...@@ -3747,19 +3747,23 @@ pub const Type = extern union {
3747 pub const base_tag = Tag.pointer;3747 pub const base_tag = Tag.pointer;
37483748
3749 base: Payload = Payload{ .tag = base_tag },3749 base: Payload = Payload{ .tag = base_tag },
3750 data: struct {3750 data: Data,
3751
3752 pub const Data = struct {
3751 pointee_type: Type,3753 pointee_type: Type,
3752 sentinel: ?Value,3754 sentinel: ?Value = null,
3753 /// If zero use pointee_type.AbiAlign()3755 /// If zero use pointee_type.AbiAlign()
3754 @"align": u32,3756 @"align": u32 = 0,
3757 /// See src/target.zig defaultAddressSpace function for how to obtain
3758 /// an appropriate value for this field.
3755 @"addrspace": std.builtin.AddressSpace,3759 @"addrspace": std.builtin.AddressSpace,
3756 bit_offset: u16,3760 bit_offset: u16 = 0,
3757 host_size: u16,3761 host_size: u16 = 0,
3758 @"allowzero": bool,3762 @"allowzero": bool = false,
3759 mutable: bool,3763 mutable: bool = true, // TODO change this to const, not mutable
3760 @"volatile": bool,3764 @"volatile": bool = false,
3761 size: std.builtin.TypeInfo.Pointer.Size,3765 size: std.builtin.TypeInfo.Pointer.Size = .One,
3762 },3766 };
3763 };3767 };
37643768
3765 pub const ErrorUnion = struct {3769 pub const ErrorUnion = struct {
...@@ -3815,6 +3819,37 @@ pub const Type = extern union {...@@ -3815,6 +3819,37 @@ pub const Type = extern union {
3815 data: *Module.EnumSimple,3819 data: *Module.EnumSimple,
3816 };3820 };
3817 };3821 };
3822
3823 pub fn ptr(arena: *Allocator, d: Payload.Pointer.Data) !Type {
3824 assert(d.host_size == 0 or d.bit_offset < d.host_size * 8);
3825
3826 if (d.sentinel != null or d.@"align" != 0 or d.@"addrspace" != .generic or
3827 d.bit_offset != 0 or d.host_size != 0 or d.@"allowzero" or d.@"volatile")
3828 {
3829 return Type.Tag.pointer.create(arena, d);
3830 }
3831
3832 if (!d.mutable and d.size == .Slice and d.pointee_type.eql(Type.initTag(.u8))) {
3833 return Type.initTag(.const_slice_u8);
3834 }
3835
3836 // TODO stage1 type inference bug
3837 const T = Type.Tag;
3838
3839 const type_payload = try arena.create(Type.Payload.ElemType);
3840 type_payload.* = .{
3841 .base = .{
3842 .tag = switch (d.size) {
3843 .One => if (d.mutable) T.single_mut_pointer else T.single_const_pointer,
3844 .Many => if (d.mutable) T.many_mut_pointer else T.many_const_pointer,
3845 .C => if (d.mutable) T.c_mut_pointer else T.c_const_pointer,
3846 .Slice => if (d.mutable) T.mut_slice else T.const_slice,
3847 },
3848 },
3849 .data = d.pointee_type,
3850 };
3851 return Type.initPayload(&type_payload.base);
3852 }
3818};3853};
38193854
3820pub const CType = enum {3855pub const CType = enum {
test/behavior/struct.zig+38
...@@ -52,3 +52,41 @@ fn testFoo(foo: StructFoo) !void {...@@ -52,3 +52,41 @@ fn testFoo(foo: StructFoo) !void {
52fn testMutation(foo: *StructFoo) void {52fn testMutation(foo: *StructFoo) void {
53 foo.c = 100;53 foo.c = 100;
54}54}
55
56test "struct byval assign" {
57 var foo1: StructFoo = undefined;
58 var foo2: StructFoo = undefined;
59
60 foo1.a = 1234;
61 foo2.a = 0;
62 try expect(foo2.a == 0);
63 foo2 = foo1;
64 try expect(foo2.a == 1234);
65}
66
67const Node = struct {
68 val: Val,
69 next: *Node,
70};
71
72const Val = struct {
73 x: i32,
74};
75
76test "struct initializer" {
77 const val = Val{ .x = 42 };
78 try expect(val.x == 42);
79}
80
81const MemberFnTestFoo = struct {
82 x: i32,
83 fn member(foo: MemberFnTestFoo) i32 {
84 return foo.x;
85 }
86};
87
88test "call member function directly" {
89 const instance = MemberFnTestFoo{ .x = 1234 };
90 const result = MemberFnTestFoo.member(instance);
91 try expect(result == 1234);
92}
test/behavior/struct_stage1.zig+4-25
...@@ -5,6 +5,7 @@ const expect = std.testing.expect;...@@ -5,6 +5,7 @@ const expect = std.testing.expect;
5const expectEqual = std.testing.expectEqual;5const expectEqual = std.testing.expectEqual;
6const expectEqualSlices = std.testing.expectEqualSlices;6const expectEqualSlices = std.testing.expectEqualSlices;
7const maxInt = std.math.maxInt;7const maxInt = std.math.maxInt;
8
8top_level_field: i32,9top_level_field: i32,
910
10test "top level fields" {11test "top level fields" {
...@@ -58,22 +59,6 @@ test "struct point to self" {...@@ -58,22 +59,6 @@ test "struct point to self" {
58 try expect(node.next.next.next.val.x == 1);59 try expect(node.next.next.next.val.x == 1);
59}60}
6061
61test "struct byval assign" {
62 var foo1: StructFoo = undefined;
63 var foo2: StructFoo = undefined;
64
65 foo1.a = 1234;
66 foo2.a = 0;
67 try expect(foo2.a == 0);
68 foo2 = foo1;
69 try expect(foo2.a == 1234);
70}
71
72test "struct initializer" {
73 const val = Val{ .x = 42 };
74 try expect(val.x == 42);
75}
76
77test "fn call of struct field" {62test "fn call of struct field" {
78 const Foo = struct {63 const Foo = struct {
79 ptr: fn () i32,64 ptr: fn () i32,
...@@ -91,22 +76,16 @@ test "fn call of struct field" {...@@ -91,22 +76,16 @@ test "fn call of struct field" {
91 try expect(S.callStructField(Foo{ .ptr = S.aFunc }) == 13);76 try expect(S.callStructField(Foo{ .ptr = S.aFunc }) == 13);
92}77}
9378
94test "store member function in variable" {
95 const instance = MemberFnTestFoo{ .x = 1234 };
96 const memberFn = MemberFnTestFoo.member;
97 const result = memberFn(instance);
98 try expect(result == 1234);
99}
100const MemberFnTestFoo = struct {79const MemberFnTestFoo = struct {
101 x: i32,80 x: i32,
102 fn member(foo: MemberFnTestFoo) i32 {81 fn member(foo: MemberFnTestFoo) i32 {
103 return foo.x;82 return foo.x;
104 }83 }
105};84};
10685test "store member function in variable" {
107test "call member function directly" {
108 const instance = MemberFnTestFoo{ .x = 1234 };86 const instance = MemberFnTestFoo{ .x = 1234 };
109 const result = MemberFnTestFoo.member(instance);87 const memberFn = MemberFnTestFoo.member;
88 const result = memberFn(instance);
110 try expect(result == 1234);89 try expect(result == 1234);
111}90}
11291