authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-02-24 15:52:56-05:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2022-02-24 15:52:56-05:00
loge06cb31659ff5afd1e0b846fbaa852df2f5a0af4
tree18e085201d076dea7320365f47d79ebc00c589eb
parent5ab5e2e6731a9f1198df6c53134545ccc6a6bbd3
parentcbd5d6c704c03177be90a891fc8fd48e6966487b
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #10982 from Vexu/stage2

stage2: implement fieldParentPtr

18 files changed, 172 insertions(+), 35 deletions(-)

src/Air.zig+10
...@@ -574,6 +574,10 @@ pub const Inst = struct {...@@ -574,6 +574,10 @@ pub const Inst = struct {
574 /// Uses the `prefetch` field.574 /// Uses the `prefetch` field.
575 prefetch,575 prefetch,
576576
577 /// Implements @fieldParentPtr builtin.
578 /// Uses the `ty_pl` field.
579 field_parent_ptr,
580
577 pub fn fromCmpOp(op: std.math.CompareOperator) Tag {581 pub fn fromCmpOp(op: std.math.CompareOperator) Tag {
578 return switch (op) {582 return switch (op) {
579 .lt => .cmp_lt,583 .lt => .cmp_lt,
...@@ -703,6 +707,11 @@ pub const Bin = struct {...@@ -703,6 +707,11 @@ pub const Bin = struct {
703 rhs: Inst.Ref,707 rhs: Inst.Ref,
704};708};
705709
710pub const FieldParentPtr = struct {
711 field_ptr: Inst.Ref,
712 field_index: u32,
713};
714
706/// Trailing:715/// Trailing:
707/// 0. `Inst.Ref` for every outputs_len716/// 0. `Inst.Ref` for every outputs_len
708/// 1. `Inst.Ref` for every inputs_len717/// 1. `Inst.Ref` for every inputs_len
...@@ -856,6 +865,7 @@ pub fn typeOfIndex(air: Air, inst: Air.Inst.Index) Type {...@@ -856,6 +865,7 @@ pub fn typeOfIndex(air: Air, inst: Air.Inst.Index) Type {
856 .cmpxchg_strong,865 .cmpxchg_strong,
857 .slice,866 .slice,
858 .vector_init,867 .vector_init,
868 .field_parent_ptr,
859 => return air.getRefType(datas[inst].ty_pl.ty),869 => return air.getRefType(datas[inst].ty_pl.ty),
860870
861 .not,871 .not,
src/AstGen.zig+1-3
...@@ -2296,7 +2296,6 @@ fn unusedResultExpr(gz: *GenZir, scope: *Scope, statement: Ast.Node.Index) Inner...@@ -2296,7 +2296,6 @@ fn unusedResultExpr(gz: *GenZir, scope: *Scope, statement: Ast.Node.Index) Inner
2296 .atomic_rmw,2296 .atomic_rmw,
2297 .mul_add,2297 .mul_add,
2298 .builtin_call,2298 .builtin_call,
2299 .field_ptr_type,
2300 .field_parent_ptr,2299 .field_parent_ptr,
2301 .maximum,2300 .maximum,
2302 .minimum,2301 .minimum,
...@@ -7403,11 +7402,10 @@ fn builtinCall(...@@ -7403,11 +7402,10 @@ fn builtinCall(
7403 .field_parent_ptr => {7402 .field_parent_ptr => {
7404 const parent_type = try typeExpr(gz, scope, params[0]);7403 const parent_type = try typeExpr(gz, scope, params[0]);
7405 const field_name = try comptimeExpr(gz, scope, .{ .ty = .const_slice_u8_type }, params[1]);7404 const field_name = try comptimeExpr(gz, scope, .{ .ty = .const_slice_u8_type }, params[1]);
7406 const field_ptr_type = try gz.addBin(.field_ptr_type, parent_type, field_name);
7407 const result = try gz.addPlNode(.field_parent_ptr, node, Zir.Inst.FieldParentPtr{7405 const result = try gz.addPlNode(.field_parent_ptr, node, Zir.Inst.FieldParentPtr{
7408 .parent_type = parent_type,7406 .parent_type = parent_type,
7409 .field_name = field_name,7407 .field_name = field_name,
7410 .field_ptr = try expr(gz, scope, .{ .ty = field_ptr_type }, params[2]),7408 .field_ptr = try expr(gz, scope, .none, params[2]),
7411 });7409 });
7412 return rvalue(gz, rl, result, node);7410 return rvalue(gz, rl, result, node);
7413 },7411 },
src/Liveness.zig+4
...@@ -446,6 +446,10 @@ fn analyzeInst(...@@ -446,6 +446,10 @@ fn analyzeInst(
446 const extra = a.air.extraData(Air.StructField, inst_datas[inst].ty_pl.payload).data;446 const extra = a.air.extraData(Air.StructField, inst_datas[inst].ty_pl.payload).data;
447 return trackOperands(a, new_set, inst, main_tomb, .{ extra.struct_operand, .none, .none });447 return trackOperands(a, new_set, inst, main_tomb, .{ extra.struct_operand, .none, .none });
448 },448 },
449 .field_parent_ptr => {
450 const extra = a.air.extraData(Air.FieldParentPtr, inst_datas[inst].ty_pl.payload).data;
451 return trackOperands(a, new_set, inst, main_tomb, .{ extra.field_ptr, .none, .none });
452 },
449 .ptr_elem_ptr, .slice_elem_ptr, .slice => {453 .ptr_elem_ptr, .slice_elem_ptr, .slice => {
450 const extra = a.air.extraData(Air.Bin, inst_datas[inst].ty_pl.payload).data;454 const extra = a.air.extraData(Air.Bin, inst_datas[inst].ty_pl.payload).data;
451 return trackOperands(a, new_set, inst, main_tomb, .{ extra.lhs, extra.rhs, .none });455 return trackOperands(a, new_set, inst, main_tomb, .{ extra.lhs, extra.rhs, .none });
src/Sema.zig+59-8
...@@ -732,7 +732,6 @@ fn analyzeBodyInner(...@@ -732,7 +732,6 @@ fn analyzeBodyInner(
732 .atomic_rmw => try sema.zirAtomicRmw(block, inst),732 .atomic_rmw => try sema.zirAtomicRmw(block, inst),
733 .mul_add => try sema.zirMulAdd(block, inst),733 .mul_add => try sema.zirMulAdd(block, inst),
734 .builtin_call => try sema.zirBuiltinCall(block, inst),734 .builtin_call => try sema.zirBuiltinCall(block, inst),
735 .field_ptr_type => try sema.zirFieldPtrType(block, inst),
736 .field_parent_ptr => try sema.zirFieldParentPtr(block, inst),735 .field_parent_ptr => try sema.zirFieldParentPtr(block, inst),
737 .builtin_async_call => try sema.zirBuiltinAsyncCall(block, inst),736 .builtin_async_call => try sema.zirBuiltinAsyncCall(block, inst),
738 .@"resume" => try sema.zirResume(block, inst),737 .@"resume" => try sema.zirResume(block, inst),
...@@ -12839,16 +12838,68 @@ fn zirBuiltinCall(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -12839,16 +12838,68 @@ fn zirBuiltinCall(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
12839 return sema.fail(block, src, "TODO: Sema.zirBuiltinCall", .{});12838 return sema.fail(block, src, "TODO: Sema.zirBuiltinCall", .{});
12840}12839}
1284112840
12842fn zirFieldPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
12843 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
12844 const src = inst_data.src();
12845 return sema.fail(block, src, "TODO: Sema.zirFieldPtrType", .{});
12846}
12847
12848fn zirFieldParentPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {12841fn zirFieldParentPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
12849 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;12842 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
12843 const extra = sema.code.extraData(Zir.Inst.FieldParentPtr, inst_data.payload_index).data;
12850 const src = inst_data.src();12844 const src = inst_data.src();
12851 return sema.fail(block, src, "TODO: Sema.zirFieldParentPtr", .{});12845 const ty_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };
12846 const name_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node };
12847 const ptr_src: LazySrcLoc = .{ .node_offset_builtin_call_arg2 = inst_data.src_node };
12848
12849 const struct_ty = try sema.resolveType(block, ty_src, extra.parent_type);
12850 const field_name = try sema.resolveConstString(block, name_src, extra.field_name);
12851 const field_ptr = sema.resolveInst(extra.field_ptr);
12852 const field_ptr_ty = sema.typeOf(field_ptr);
12853
12854 if (struct_ty.zigTypeTag() != .Struct) {
12855 return sema.fail(block, ty_src, "expected struct type, found '{}'", .{struct_ty});
12856 }
12857 try sema.resolveTypeLayout(block, ty_src, struct_ty);
12858
12859 const struct_obj = struct_ty.castTag(.@"struct").?.data;
12860 const field_index = struct_obj.fields.getIndex(field_name) orelse
12861 return sema.failWithBadStructFieldAccess(block, struct_obj, name_src, field_name);
12862
12863 if (field_ptr_ty.zigTypeTag() != .Pointer) {
12864 return sema.fail(block, ty_src, "expected pointer type, found '{}'", .{field_ptr_ty});
12865 }
12866 const field = struct_obj.fields.values()[field_index];
12867 const field_ptr_ty_info = field_ptr_ty.ptrInfo().data;
12868
12869 var ptr_ty_data: Type.Payload.Pointer.Data = .{
12870 .pointee_type = field.ty,
12871 .mutable = field_ptr_ty_info.mutable,
12872 .@"addrspace" = field_ptr_ty_info.@"addrspace",
12873 };
12874
12875 if (struct_obj.layout == .Packed) {
12876 // TODO handle packed structs
12877 } else if (field.abi_align.tag() != .abi_align_default) {
12878 ptr_ty_data.@"align" = @intCast(u32, field.abi_align.toUnsignedInt());
12879 }
12880
12881 const actual_field_ptr_ty = try Type.ptr(sema.arena, ptr_ty_data);
12882 const casted_field_ptr = try sema.coerce(block, actual_field_ptr_ty, field_ptr, ptr_src);
12883
12884 ptr_ty_data.pointee_type = struct_ty;
12885 const result_ptr = try Type.ptr(sema.arena, ptr_ty_data);
12886
12887 if (try sema.resolveDefinedValue(block, src, casted_field_ptr)) |field_ptr_val| {
12888 const payload = field_ptr_val.castTag(.field_ptr).?.data;
12889 return sema.addConstant(result_ptr, payload.container_ptr);
12890 }
12891
12892 try sema.requireRuntimeBlock(block, src);
12893 return block.addInst(.{
12894 .tag = .field_parent_ptr,
12895 .data = .{ .ty_pl = .{
12896 .ty = try sema.addType(result_ptr),
12897 .payload = try block.sema.addExtra(Air.FieldParentPtr{
12898 .field_ptr = casted_field_ptr,
12899 .field_index = @intCast(u32, field_index),
12900 }),
12901 } },
12902 });
12852}12903}
1285312904
12854fn zirMinMax(12905fn zirMinMax(
src/Zir.zig-6
...@@ -892,10 +892,6 @@ pub const Inst = struct {...@@ -892,10 +892,6 @@ pub const Inst = struct {
892 /// Implements the `@call` builtin.892 /// Implements the `@call` builtin.
893 /// Uses the `pl_node` union field with payload `BuiltinCall`.893 /// Uses the `pl_node` union field with payload `BuiltinCall`.
894 builtin_call,894 builtin_call,
895 /// Given a type and a field name, returns a pointer to the field type.
896 /// Assumed to be part of a `@fieldParentPtr` builtin call.
897 /// Uses the `bin` union field. LHS is type, RHS is field name.
898 field_ptr_type,
899 /// Implements the `@fieldParentPtr` builtin.895 /// Implements the `@fieldParentPtr` builtin.
900 /// Uses the `pl_node` union field with payload `FieldParentPtr`.896 /// Uses the `pl_node` union field with payload `FieldParentPtr`.
901 field_parent_ptr,897 field_parent_ptr,
...@@ -1192,7 +1188,6 @@ pub const Inst = struct {...@@ -1192,7 +1188,6 @@ pub const Inst = struct {
1192 .atomic_store,1188 .atomic_store,
1193 .mul_add,1189 .mul_add,
1194 .builtin_call,1190 .builtin_call,
1195 .field_ptr_type,
1196 .field_parent_ptr,1191 .field_parent_ptr,
1197 .maximum,1192 .maximum,
1198 .memcpy,1193 .memcpy,
...@@ -1466,7 +1461,6 @@ pub const Inst = struct {...@@ -1466,7 +1461,6 @@ pub const Inst = struct {
1466 .atomic_store = .pl_node,1461 .atomic_store = .pl_node,
1467 .mul_add = .pl_node,1462 .mul_add = .pl_node,
1468 .builtin_call = .pl_node,1463 .builtin_call = .pl_node,
1469 .field_ptr_type = .bin,
1470 .field_parent_ptr = .pl_node,1464 .field_parent_ptr = .pl_node,
1471 .maximum = .pl_node,1465 .maximum = .pl_node,
1472 .memcpy = .pl_node,1466 .memcpy = .pl_node,
src/arch/aarch64/CodeGen.zig+9
...@@ -638,6 +638,8 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {...@@ -638,6 +638,8 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
638 .struct_field_ptr_index_2 => try self.airStructFieldPtrIndex(inst, 2),638 .struct_field_ptr_index_2 => try self.airStructFieldPtrIndex(inst, 2),
639 .struct_field_ptr_index_3 => try self.airStructFieldPtrIndex(inst, 3),639 .struct_field_ptr_index_3 => try self.airStructFieldPtrIndex(inst, 3),
640640
641 .field_parent_ptr => try self.airFieldParentPtr(inst),
642
641 .switch_br => try self.airSwitch(inst),643 .switch_br => try self.airSwitch(inst),
642 .slice_ptr => try self.airSlicePtr(inst),644 .slice_ptr => try self.airSlicePtr(inst),
643 .slice_len => try self.airSliceLen(inst),645 .slice_len => try self.airSliceLen(inst),
...@@ -2118,6 +2120,13 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {...@@ -2118,6 +2120,13 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {
2118 //return self.finishAir(inst, result, .{ extra.struct_ptr, .none, .none });2120 //return self.finishAir(inst, result, .{ extra.struct_ptr, .none, .none });
2119}2121}
21202122
2123fn airFieldParentPtr(self: *Self, inst: Air.Inst.Index) !void {
2124 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
2125 const extra = self.air.extraData(Air.StructField, ty_pl.payload).data;
2126 _ = extra;
2127 return self.fail("TODO implement codegen airFieldParentPtr", .{});
2128}
2129
2121fn airArg(self: *Self, inst: Air.Inst.Index) !void {2130fn airArg(self: *Self, inst: Air.Inst.Index) !void {
2122 const arg_index = self.arg_index;2131 const arg_index = self.arg_index;
2123 self.arg_index += 1;2132 self.arg_index += 1;
src/arch/arm/CodeGen.zig+9
...@@ -622,6 +622,8 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {...@@ -622,6 +622,8 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
622 .struct_field_ptr_index_2 => try self.airStructFieldPtrIndex(inst, 2),622 .struct_field_ptr_index_2 => try self.airStructFieldPtrIndex(inst, 2),
623 .struct_field_ptr_index_3 => try self.airStructFieldPtrIndex(inst, 3),623 .struct_field_ptr_index_3 => try self.airStructFieldPtrIndex(inst, 3),
624624
625 .field_parent_ptr => try self.airFieldParentPtr(inst),
626
625 .switch_br => try self.airSwitch(inst),627 .switch_br => try self.airSwitch(inst),
626 .slice_ptr => try self.airSlicePtr(inst),628 .slice_ptr => try self.airSlicePtr(inst),
627 .slice_len => try self.airSliceLen(inst),629 .slice_len => try self.airSliceLen(inst),
...@@ -1735,6 +1737,13 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {...@@ -1735,6 +1737,13 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {
1735 return self.finishAir(inst, result, .{ extra.struct_operand, .none, .none });1737 return self.finishAir(inst, result, .{ extra.struct_operand, .none, .none });
1736}1738}
17371739
1740fn airFieldParentPtr(self: *Self, inst: Air.Inst.Index) !void {
1741 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
1742 const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data;
1743 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement airFieldParentPtr", .{});
1744 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
1745}
1746
1738/// Don't call this function directly. Use binOp instead.1747/// Don't call this function directly. Use binOp instead.
1739///1748///
1740/// Calling this function signals an intention to generate a Mir1749/// Calling this function signals an intention to generate a Mir
src/arch/riscv64/CodeGen.zig+8
...@@ -609,6 +609,8 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {...@@ -609,6 +609,8 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
609 .struct_field_ptr_index_2 => try self.airStructFieldPtrIndex(inst, 2),609 .struct_field_ptr_index_2 => try self.airStructFieldPtrIndex(inst, 2),
610 .struct_field_ptr_index_3 => try self.airStructFieldPtrIndex(inst, 3),610 .struct_field_ptr_index_3 => try self.airStructFieldPtrIndex(inst, 3),
611611
612 .field_parent_ptr => try self.airFieldParentPtr(inst),
613
612 .switch_br => try self.airSwitch(inst),614 .switch_br => try self.airSwitch(inst),
613 .slice_ptr => try self.airSlicePtr(inst),615 .slice_ptr => try self.airSlicePtr(inst),
614 .slice_len => try self.airSliceLen(inst),616 .slice_len => try self.airSliceLen(inst),
...@@ -1360,6 +1362,12 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {...@@ -1360,6 +1362,12 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {
1360 //return self.finishAir(inst, result, .{ extra.struct_ptr, .none, .none });1362 //return self.finishAir(inst, result, .{ extra.struct_ptr, .none, .none });
1361}1363}
13621364
1365fn airFieldParentPtr(self: *Self, inst: Air.Inst.Index) !void {
1366 _ = self;
1367 _ = inst;
1368 return self.fail("TODO implement codegen airFieldParentPtr", .{});
1369}
1370
1363fn genArgDbgInfo(self: *Self, inst: Air.Inst.Index, mcv: MCValue, arg_index: u32) !void {1371fn genArgDbgInfo(self: *Self, inst: Air.Inst.Index, mcv: MCValue, arg_index: u32) !void {
1364 const ty = self.air.instructions.items(.data)[inst].ty;1372 const ty = self.air.instructions.items(.data)[inst].ty;
1365 const name = self.mod_fn.getParamName(arg_index);1373 const name = self.mod_fn.getParamName(arg_index);
src/arch/wasm/CodeGen.zig+1
...@@ -1730,6 +1730,7 @@ fn genInst(self: *Self, inst: Air.Inst.Index) !WValue {...@@ -1730,6 +1730,7 @@ fn genInst(self: *Self, inst: Air.Inst.Index) !WValue {
1730 .tag_name,1730 .tag_name,
1731 .error_name,1731 .error_name,
1732 .errunion_payload_ptr_set,1732 .errunion_payload_ptr_set,
1733 .field_parent_ptr,
17331734
1734 // For these 4, probably best to wait until https://github.com/ziglang/zig/issues/102481735 // For these 4, probably best to wait until https://github.com/ziglang/zig/issues/10248
1735 // is implemented in the frontend before implementing them here in the wasm backend.1736 // is implemented in the frontend before implementing them here in the wasm backend.
src/arch/x86_64/CodeGen.zig+11
...@@ -721,6 +721,8 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {...@@ -721,6 +721,8 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
721 .struct_field_ptr_index_2 => try self.airStructFieldPtrIndex(inst, 2),721 .struct_field_ptr_index_2 => try self.airStructFieldPtrIndex(inst, 2),
722 .struct_field_ptr_index_3 => try self.airStructFieldPtrIndex(inst, 3),722 .struct_field_ptr_index_3 => try self.airStructFieldPtrIndex(inst, 3),
723723
724 .field_parent_ptr => try self.airFieldParentPtr(inst),
725
724 .switch_br => try self.airSwitch(inst),726 .switch_br => try self.airSwitch(inst),
725 .slice_ptr => try self.airSlicePtr(inst),727 .slice_ptr => try self.airSlicePtr(inst),
726 .slice_len => try self.airSliceLen(inst),728 .slice_len => try self.airSliceLen(inst),
...@@ -2656,6 +2658,15 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {...@@ -2656,6 +2658,15 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {
2656 return self.finishAir(inst, result, .{ extra.struct_operand, .none, .none });2658 return self.finishAir(inst, result, .{ extra.struct_operand, .none, .none });
2657}2659}
26582660
2661fn airFieldParentPtr(self: *Self, inst: Air.Inst.Index) !void {
2662 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
2663 const result: MCValue = if (self.liveness.isUnused(inst))
2664 .dead
2665 else
2666 return self.fail("TODO implement airFieldParentPtr for {}", .{self.target.cpu.arch});
2667 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
2668}
2669
2659/// Perform "binary" operators, excluding comparisons.2670/// Perform "binary" operators, excluding comparisons.
2660/// Currently, the following ops are supported:2671/// Currently, the following ops are supported:
2661/// ADD, SUB, XOR, OR, AND2672/// ADD, SUB, XOR, OR, AND
src/codegen/c.zig+7
...@@ -1734,6 +1734,8 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO...@@ -1734,6 +1734,8 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO
1734 .struct_field_ptr_index_2 => try airStructFieldPtrIndex(f, inst, 2),1734 .struct_field_ptr_index_2 => try airStructFieldPtrIndex(f, inst, 2),
1735 .struct_field_ptr_index_3 => try airStructFieldPtrIndex(f, inst, 3),1735 .struct_field_ptr_index_3 => try airStructFieldPtrIndex(f, inst, 3),
17361736
1737 .field_parent_ptr => try airFieldParentPtr(f, inst),
1738
1737 .struct_field_val => try airStructFieldVal(f, inst),1739 .struct_field_val => try airStructFieldVal(f, inst),
1738 .slice_ptr => try airSliceField(f, inst, ".ptr;\n"),1740 .slice_ptr => try airSliceField(f, inst, ".ptr;\n"),
1739 .slice_len => try airSliceField(f, inst, ".len;\n"),1741 .slice_len => try airSliceField(f, inst, ".len;\n"),
...@@ -3026,6 +3028,11 @@ fn airStructFieldPtrIndex(f: *Function, inst: Air.Inst.Index, index: u8) !CValue...@@ -3026,6 +3028,11 @@ fn airStructFieldPtrIndex(f: *Function, inst: Air.Inst.Index, index: u8) !CValue
3026 return structFieldPtr(f, inst, struct_ptr_ty, struct_ptr, index);3028 return structFieldPtr(f, inst, struct_ptr_ty, struct_ptr, index);
3027}3029}
30283030
3031fn airFieldParentPtr(f: *Function, inst: Air.Inst.Index) !CValue {
3032 _ = inst;
3033 return f.fail("TODO: C backend: implement airFieldParentPtr", .{});
3034}
3035
3029fn structFieldPtr(f: *Function, inst: Air.Inst.Index, struct_ptr_ty: Type, struct_ptr: CValue, index: u32) !CValue {3036fn structFieldPtr(f: *Function, inst: Air.Inst.Index, struct_ptr_ty: Type, struct_ptr: CValue, index: u32) !CValue {
3030 const writer = f.object.writer();3037 const writer = f.object.writer();
3031 const struct_ty = struct_ptr_ty.elemType();3038 const struct_ty = struct_ptr_ty.elemType();
src/codegen/llvm.zig+25
...@@ -2191,6 +2191,8 @@ pub const FuncGen = struct {...@@ -2191,6 +2191,8 @@ pub const FuncGen = struct {
2191 .struct_field_ptr_index_2 => try self.airStructFieldPtrIndex(inst, 2),2191 .struct_field_ptr_index_2 => try self.airStructFieldPtrIndex(inst, 2),
2192 .struct_field_ptr_index_3 => try self.airStructFieldPtrIndex(inst, 3),2192 .struct_field_ptr_index_3 => try self.airStructFieldPtrIndex(inst, 3),
21932193
2194 .field_parent_ptr => try self.airFieldParentPtr(inst),
2195
2194 .array_elem_val => try self.airArrayElemVal(inst),2196 .array_elem_val => try self.airArrayElemVal(inst),
2195 .slice_elem_val => try self.airSliceElemVal(inst),2197 .slice_elem_val => try self.airSliceElemVal(inst),
2196 .slice_elem_ptr => try self.airSliceElemPtr(inst),2198 .slice_elem_ptr => try self.airSliceElemPtr(inst),
...@@ -2853,6 +2855,29 @@ pub const FuncGen = struct {...@@ -2853,6 +2855,29 @@ pub const FuncGen = struct {
2853 }2855 }
2854 }2856 }
28552857
2858 fn airFieldParentPtr(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value {
2859 if (self.liveness.isUnused(inst)) return null;
2860
2861 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
2862 const extra = self.air.extraData(Air.FieldParentPtr, ty_pl.payload).data;
2863
2864 const field_ptr = try self.resolveInst(extra.field_ptr);
2865
2866 const target = self.dg.module.getTarget();
2867 const struct_ty = self.air.getRefType(ty_pl.ty).childType();
2868 const field_offset = struct_ty.structFieldOffset(extra.field_index, target);
2869
2870 const res_ty = try self.dg.llvmType(self.air.getRefType(ty_pl.ty));
2871 if (field_offset == 0) {
2872 return self.builder.buildBitCast(field_ptr, res_ty, "");
2873 }
2874 const llvm_usize_ty = self.context.intType(target.cpu.arch.ptrBitWidth());
2875
2876 const field_ptr_int = self.builder.buildPtrToInt(field_ptr, llvm_usize_ty, "");
2877 const base_ptr_int = self.builder.buildNUWSub(field_ptr_int, llvm_usize_ty.constInt(field_offset, .False), "");
2878 return self.builder.buildIntToPtr(base_ptr_int, res_ty, "");
2879 }
2880
2856 fn airNot(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value {2881 fn airNot(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value {
2857 if (self.liveness.isUnused(inst))2882 if (self.liveness.isUnused(inst))
2858 return null;2883 return null;
src/codegen/spirv/spec.zig+10-10
...@@ -1206,7 +1206,7 @@ pub const Opcode = enum(u16) {...@@ -1206,7 +1206,7 @@ pub const Opcode = enum(u16) {
1206 }1206 }
1207};1207};
1208pub const ImageOperands = packed struct {1208pub const ImageOperands = packed struct {
1209 Bias: bool align(@alignOf(u32)) = false,1209 Bias: bool = false,
1210 Lod: bool = false,1210 Lod: bool = false,
1211 Grad: bool = false,1211 Grad: bool = false,
1212 ConstOffset: bool = false,1212 ConstOffset: bool = false,
...@@ -1280,7 +1280,7 @@ pub const ImageOperands = packed struct {...@@ -1280,7 +1280,7 @@ pub const ImageOperands = packed struct {
1280 };1280 };
1281};1281};
1282pub const FPFastMathMode = packed struct {1282pub const FPFastMathMode = packed struct {
1283 NotNaN: bool align(@alignOf(u32)) = false,1283 NotNaN: bool = false,
1284 NotInf: bool = false,1284 NotInf: bool = false,
1285 NSZ: bool = false,1285 NSZ: bool = false,
1286 AllowRecip: bool = false,1286 AllowRecip: bool = false,
...@@ -1314,7 +1314,7 @@ pub const FPFastMathMode = packed struct {...@@ -1314,7 +1314,7 @@ pub const FPFastMathMode = packed struct {
1314 _reserved_bit_31: bool = false,1314 _reserved_bit_31: bool = false,
1315};1315};
1316pub const SelectionControl = packed struct {1316pub const SelectionControl = packed struct {
1317 Flatten: bool align(@alignOf(u32)) = false,1317 Flatten: bool = false,
1318 DontFlatten: bool = false,1318 DontFlatten: bool = false,
1319 _reserved_bit_2: bool = false,1319 _reserved_bit_2: bool = false,
1320 _reserved_bit_3: bool = false,1320 _reserved_bit_3: bool = false,
...@@ -1348,7 +1348,7 @@ pub const SelectionControl = packed struct {...@@ -1348,7 +1348,7 @@ pub const SelectionControl = packed struct {
1348 _reserved_bit_31: bool = false,1348 _reserved_bit_31: bool = false,
1349};1349};
1350pub const LoopControl = packed struct {1350pub const LoopControl = packed struct {
1351 Unroll: bool align(@alignOf(u32)) = false,1351 Unroll: bool = false,
1352 DontUnroll: bool = false,1352 DontUnroll: bool = false,
1353 DependencyInfinite: bool = false,1353 DependencyInfinite: bool = false,
1354 DependencyLength: bool = false,1354 DependencyLength: bool = false,
...@@ -1417,7 +1417,7 @@ pub const LoopControl = packed struct {...@@ -1417,7 +1417,7 @@ pub const LoopControl = packed struct {
1417 };1417 };
1418};1418};
1419pub const FunctionControl = packed struct {1419pub const FunctionControl = packed struct {
1420 Inline: bool align(@alignOf(u32)) = false,1420 Inline: bool = false,
1421 DontInline: bool = false,1421 DontInline: bool = false,
1422 Pure: bool = false,1422 Pure: bool = false,
1423 Const: bool = false,1423 Const: bool = false,
...@@ -1451,7 +1451,7 @@ pub const FunctionControl = packed struct {...@@ -1451,7 +1451,7 @@ pub const FunctionControl = packed struct {
1451 _reserved_bit_31: bool = false,1451 _reserved_bit_31: bool = false,
1452};1452};
1453pub const MemorySemantics = packed struct {1453pub const MemorySemantics = packed struct {
1454 _reserved_bit_0: bool align(@alignOf(u32)) = false,1454 _reserved_bit_0: bool = false,
1455 Acquire: bool = false,1455 Acquire: bool = false,
1456 Release: bool = false,1456 Release: bool = false,
1457 AcquireRelease: bool = false,1457 AcquireRelease: bool = false,
...@@ -1489,7 +1489,7 @@ pub const MemorySemantics = packed struct {...@@ -1489,7 +1489,7 @@ pub const MemorySemantics = packed struct {
1489 pub const MakeVisibleKHR: MemorySemantics = .{ .MakeVisible = true };1489 pub const MakeVisibleKHR: MemorySemantics = .{ .MakeVisible = true };
1490};1490};
1491pub const MemoryAccess = packed struct {1491pub const MemoryAccess = packed struct {
1492 Volatile: bool align(@alignOf(u32)) = false,1492 Volatile: bool = false,
1493 Aligned: bool = false,1493 Aligned: bool = false,
1494 Nontemporal: bool = false,1494 Nontemporal: bool = false,
1495 MakePointerAvailable: bool = false,1495 MakePointerAvailable: bool = false,
...@@ -1562,7 +1562,7 @@ pub const MemoryAccess = packed struct {...@@ -1562,7 +1562,7 @@ pub const MemoryAccess = packed struct {
1562 };1562 };
1563};1563};
1564pub const KernelProfilingInfo = packed struct {1564pub const KernelProfilingInfo = packed struct {
1565 CmdExecTime: bool align(@alignOf(u32)) = false,1565 CmdExecTime: bool = false,
1566 _reserved_bit_1: bool = false,1566 _reserved_bit_1: bool = false,
1567 _reserved_bit_2: bool = false,1567 _reserved_bit_2: bool = false,
1568 _reserved_bit_3: bool = false,1568 _reserved_bit_3: bool = false,
...@@ -1596,7 +1596,7 @@ pub const KernelProfilingInfo = packed struct {...@@ -1596,7 +1596,7 @@ pub const KernelProfilingInfo = packed struct {
1596 _reserved_bit_31: bool = false,1596 _reserved_bit_31: bool = false,
1597};1597};
1598pub const RayFlags = packed struct {1598pub const RayFlags = packed struct {
1599 OpaqueKHR: bool align(@alignOf(u32)) = false,1599 OpaqueKHR: bool = false,
1600 NoOpaqueKHR: bool = false,1600 NoOpaqueKHR: bool = false,
1601 TerminateOnFirstHitKHR: bool = false,1601 TerminateOnFirstHitKHR: bool = false,
1602 SkipClosestHitShaderKHR: bool = false,1602 SkipClosestHitShaderKHR: bool = false,
...@@ -1630,7 +1630,7 @@ pub const RayFlags = packed struct {...@@ -1630,7 +1630,7 @@ pub const RayFlags = packed struct {
1630 _reserved_bit_31: bool = false,1630 _reserved_bit_31: bool = false,
1631};1631};
1632pub const FragmentShadingRate = packed struct {1632pub const FragmentShadingRate = packed struct {
1633 Vertical2Pixels: bool align(@alignOf(u32)) = false,1633 Vertical2Pixels: bool = false,
1634 Vertical4Pixels: bool = false,1634 Vertical4Pixels: bool = false,
1635 Horizontal2Pixels: bool = false,1635 Horizontal2Pixels: bool = false,
1636 Horizontal4Pixels: bool = false,1636 Horizontal4Pixels: bool = false,
src/print_air.zig+9
...@@ -247,6 +247,7 @@ const Writer = struct {...@@ -247,6 +247,7 @@ const Writer = struct {
247 .atomic_rmw => try w.writeAtomicRmw(s, inst),247 .atomic_rmw => try w.writeAtomicRmw(s, inst),
248 .memcpy => try w.writeMemcpy(s, inst),248 .memcpy => try w.writeMemcpy(s, inst),
249 .memset => try w.writeMemset(s, inst),249 .memset => try w.writeMemset(s, inst),
250 .field_parent_ptr => try w.writeFieldParentPtr(s, inst),
250251
251 .add_with_overflow,252 .add_with_overflow,
252 .sub_with_overflow,253 .sub_with_overflow,
...@@ -412,6 +413,14 @@ const Writer = struct {...@@ -412,6 +413,14 @@ const Writer = struct {
412 try w.writeOperand(s, inst, 2, extra.rhs);413 try w.writeOperand(s, inst, 2, extra.rhs);
413 }414 }
414415
416 fn writeFieldParentPtr(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void {
417 const pl_op = w.air.instructions.items(.data)[inst].ty_pl;
418 const extra = w.air.extraData(Air.FieldParentPtr, pl_op.payload).data;
419
420 try w.writeOperand(s, inst, 0, extra.field_ptr);
421 try s.print(", {d}", .{extra.field_index});
422 }
423
415 fn writeMemcpy(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void {424 fn writeMemcpy(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void {
416 const pl_op = w.air.instructions.items(.data)[inst].pl_op;425 const pl_op = w.air.instructions.items(.data)[inst].pl_op;
417 const extra = w.air.extraData(Air.Bin, pl_op.payload).data;426 const extra = w.air.extraData(Air.Bin, pl_op.payload).data;
src/print_zir.zig-1
...@@ -150,7 +150,6 @@ const Writer = struct {...@@ -150,7 +150,6 @@ const Writer = struct {
150 .store,150 .store,
151 .store_to_block_ptr,151 .store_to_block_ptr,
152 .store_to_inferred_ptr,152 .store_to_inferred_ptr,
153 .field_ptr_type,
154 => try self.writeBin(stream, inst),153 => try self.writeBin(stream, inst),
155154
156 .alloc,155 .alloc,
src/value.zig+7-1
...@@ -1852,7 +1852,13 @@ pub const Value = extern union {...@@ -1852,7 +1852,13 @@ pub const Value = extern union {
1852 return eql(a_payload.ptr, b_payload.ptr, ptr_ty);1852 return eql(a_payload.ptr, b_payload.ptr, ptr_ty);
1853 },1853 },
1854 .elem_ptr => @panic("TODO: Implement more pointer eql cases"),1854 .elem_ptr => @panic("TODO: Implement more pointer eql cases"),
1855 .field_ptr => @panic("TODO: Implement more pointer eql cases"),1855 .field_ptr => {
1856 const a_payload = a.castTag(.field_ptr).?.data;
1857 const b_payload = b.castTag(.field_ptr).?.data;
1858 if (a_payload.field_index != b_payload.field_index) return false;
1859
1860 return eql(a_payload.container_ptr, b_payload.container_ptr, ty);
1861 },
1856 .eu_payload_ptr => @panic("TODO: Implement more pointer eql cases"),1862 .eu_payload_ptr => @panic("TODO: Implement more pointer eql cases"),
1857 .opt_payload_ptr => @panic("TODO: Implement more pointer eql cases"),1863 .opt_payload_ptr => @panic("TODO: Implement more pointer eql cases"),
1858 .array => {1864 .array => {
test/behavior.zig+1-1
...@@ -129,6 +129,7 @@ test {...@@ -129,6 +129,7 @@ test {
129 _ = @import("behavior/switch_prong_err_enum.zig");129 _ = @import("behavior/switch_prong_err_enum.zig");
130 _ = @import("behavior/switch_prong_implicit_cast.zig");130 _ = @import("behavior/switch_prong_implicit_cast.zig");
131 _ = @import("behavior/union_with_members.zig");131 _ = @import("behavior/union_with_members.zig");
132 _ = @import("behavior/field_parent_ptr.zig");
132133
133 if (builtin.zig_backend == .stage1) {134 if (builtin.zig_backend == .stage1) {
134 // Tests that only pass for the stage1 backend.135 // Tests that only pass for the stage1 backend.
...@@ -160,7 +161,6 @@ test {...@@ -160,7 +161,6 @@ test {
160 _ = @import("behavior/bugs/10147.zig");161 _ = @import("behavior/bugs/10147.zig");
161 _ = @import("behavior/const_slice_child.zig");162 _ = @import("behavior/const_slice_child.zig");
162 _ = @import("behavior/export_self_referential_type_info.zig");163 _ = @import("behavior/export_self_referential_type_info.zig");
163 _ = @import("behavior/field_parent_ptr.zig");
164 _ = @import("behavior/misc.zig");164 _ = @import("behavior/misc.zig");
165 _ = @import("behavior/muladd.zig");165 _ = @import("behavior/muladd.zig");
166 _ = @import("behavior/select.zig");166 _ = @import("behavior/select.zig");
tools/gen_spirv_spec.zig+1-5
...@@ -329,11 +329,7 @@ fn renderBitEnum(...@@ -329,11 +329,7 @@ fn renderBitEnum(
329 try writer.print("_reserved_bit_{}", .{bitpos});329 try writer.print("_reserved_bit_{}", .{bitpos});
330 }330 }
331331
332 try writer.writeAll(": bool ");332 try writer.writeAll(": bool = false,\n");
333 if (bitpos == 0) { // Force alignment to integer boundaries
334 try writer.writeAll("align(@alignOf(u32)) ");
335 }
336 try writer.writeAll("= false,\n");
337 }333 }
338334
339 try writer.writeByte('\n');335 try writer.writeByte('\n');