authorgravatar for jacoblevgw@gmail.comJacob G-W <jacoblevgw@gmail.com> 2021-08-16 23:11:55-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-08-21 23:52:55-04:00
log4ac37eb484737e98269e198b31b81ee8e929b4f1
tree2d5e66fcd1a2f6c9f129583d2ea8f671fff4832b
parentf378b0adce80aa6f85d9bf6bf97172426de2c719

stage2 Air: add struct_field_ptr_index_{0..3}

Since these are very common, it will save memory.

9 files changed, 123 insertions(+), 12 deletions(-)

src/Air.zig+11
...@@ -264,6 +264,13 @@ pub const Inst = struct {...@@ -264,6 +264,13 @@ pub const Inst = struct {
264 /// Given a pointer to a struct and a field index, returns a pointer to the field.264 /// Given a pointer to a struct and a field index, returns a pointer to the field.
265 /// Uses the `ty_pl` field, payload is `StructField`.265 /// Uses the `ty_pl` field, payload is `StructField`.
266 struct_field_ptr,266 struct_field_ptr,
267 /// Given a pointer to a struct, returns a pointer to the field.
268 /// The field index is the number at the end of the name.
269 /// Uses `ty_op` field.
270 struct_field_ptr_index_0,
271 struct_field_ptr_index_1,
272 struct_field_ptr_index_2,
273 struct_field_ptr_index_3,
267 /// Given a byval struct and a field index, returns the field byval.274 /// Given a byval struct and a field index, returns the field byval.
268 /// Uses the `ty_pl` field, payload is `StructField`.275 /// Uses the `ty_pl` field, payload is `StructField`.
269 struct_field_val,276 struct_field_val,
...@@ -510,6 +517,10 @@ pub fn typeOfIndex(air: Air, inst: Air.Inst.Index) Type {...@@ -510,6 +517,10 @@ pub fn typeOfIndex(air: Air, inst: Air.Inst.Index) Type {
510 .wrap_errunion_payload,517 .wrap_errunion_payload,
511 .wrap_errunion_err,518 .wrap_errunion_err,
512 .slice_ptr,519 .slice_ptr,
520 .struct_field_ptr_index_0,
521 .struct_field_ptr_index_1,
522 .struct_field_ptr_index_2,
523 .struct_field_ptr_index_3,
513 => return air.getRefType(datas[inst].ty_op.ty),524 => return air.getRefType(datas[inst].ty_op.ty),
514525
515 .loop,526 .loop,
src/Liveness.zig+4
...@@ -282,6 +282,10 @@ fn analyzeInst(...@@ -282,6 +282,10 @@ fn analyzeInst(
282 .wrap_errunion_err,282 .wrap_errunion_err,
283 .slice_ptr,283 .slice_ptr,
284 .slice_len,284 .slice_len,
285 .struct_field_ptr_index_0,
286 .struct_field_ptr_index_1,
287 .struct_field_ptr_index_2,
288 .struct_field_ptr_index_3,
285 => {289 => {
286 const o = inst_datas[inst].ty_op;290 const o = inst_datas[inst].ty_op;
287 return trackOperands(a, new_set, inst, main_tomb, .{ o.operand, .none, .none });291 return trackOperands(a, new_set, inst, main_tomb, .{ o.operand, .none, .none });
src/Sema.zig+21-6
...@@ -8119,14 +8119,29 @@ fn structFieldPtr(...@@ -8119,14 +8119,29 @@ fn structFieldPtr(
8119 }8119 }
81208120
8121 try sema.requireRuntimeBlock(block, src);8121 try sema.requireRuntimeBlock(block, src);
8122 const tag: Air.Inst.Tag = switch (field_index) {
8123 0 => .struct_field_ptr_index_0,
8124 1 => .struct_field_ptr_index_1,
8125 2 => .struct_field_ptr_index_2,
8126 3 => .struct_field_ptr_index_3,
8127 else => {
8128 return block.addInst(.{
8129 .tag = .struct_field_ptr,
8130 .data = .{ .ty_pl = .{
8131 .ty = try sema.addType(ptr_field_ty),
8132 .payload = try sema.addExtra(Air.StructField{
8133 .struct_operand = struct_ptr,
8134 .field_index = @intCast(u32, field_index),
8135 }),
8136 } },
8137 });
8138 },
8139 };
8122 return block.addInst(.{8140 return block.addInst(.{
8123 .tag = .struct_field_ptr,8141 .tag = tag,
8124 .data = .{ .ty_pl = .{8142 .data = .{ .ty_op = .{
8125 .ty = try sema.addType(ptr_field_ty),8143 .ty = try sema.addType(ptr_field_ty),
8126 .payload = try sema.addExtra(Air.StructField{8144 .operand = struct_ptr,
8127 .struct_operand = struct_ptr,
8128 .field_index = @intCast(u32, field_index),
8129 }),
8130 } },8145 } },
8131 });8146 });
8132}8147}
src/codegen.zig+18-1
...@@ -855,6 +855,12 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {...@@ -855,6 +855,12 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
855 .store => try self.airStore(inst),855 .store => try self.airStore(inst),
856 .struct_field_ptr=> try self.airStructFieldPtr(inst),856 .struct_field_ptr=> try self.airStructFieldPtr(inst),
857 .struct_field_val=> try self.airStructFieldVal(inst),857 .struct_field_val=> try self.airStructFieldVal(inst),
858
859 .struct_field_ptr_index_0 => try self.airStructFieldPtrIndex(inst, 0),
860 .struct_field_ptr_index_1 => try self.airStructFieldPtrIndex(inst, 1),
861 .struct_field_ptr_index_2 => try self.airStructFieldPtrIndex(inst, 2),
862 .struct_field_ptr_index_3 => try self.airStructFieldPtrIndex(inst, 3),
863
858 .switch_br => try self.airSwitch(inst),864 .switch_br => try self.airSwitch(inst),
859 .slice_ptr => try self.airSlicePtr(inst),865 .slice_ptr => try self.airSlicePtr(inst),
860 .slice_len => try self.airSliceLen(inst),866 .slice_len => try self.airSliceLen(inst),
...@@ -1592,7 +1598,18 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {...@@ -1592,7 +1598,18 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
1592 fn airStructFieldPtr(self: *Self, inst: Air.Inst.Index) !void {1598 fn airStructFieldPtr(self: *Self, inst: Air.Inst.Index) !void {
1593 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;1599 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
1594 const extra = self.air.extraData(Air.StructField, ty_pl.payload).data;1600 const extra = self.air.extraData(Air.StructField, ty_pl.payload).data;
1595 _ = extra;1601 return self.structFieldPtr(extra.struct_operand, ty_pl.ty, extra.field_index);
1602 }
1603
1604 fn airStructFieldPtrIndex(self: *Self, inst: Air.Inst.Index, index: u8) !void {
1605 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
1606 return self.structFieldPtr(ty_op.operand, ty_op.ty, index);
1607 }
1608 fn structFieldPtr(self: *Self, operand: Air.Inst.Ref, ty: Air.Inst.Ref, index: u32) !void {
1609 _ = self;
1610 _ = operand;
1611 _ = ty;
1612 _ = index;
1596 return self.fail("TODO implement codegen struct_field_ptr", .{});1613 return self.fail("TODO implement codegen struct_field_ptr", .{});
1597 //return self.finishAir(inst, result, .{ extra.struct_ptr, .none, .none });1614 //return self.finishAir(inst, result, .{ extra.struct_ptr, .none, .none });
1598 }1615 }
src/codegen/c.zig+25-3
...@@ -909,6 +909,12 @@ fn genBody(o: *Object, body: []const Air.Inst.Index) error{ AnalysisFail, OutOfM...@@ -909,6 +909,12 @@ fn genBody(o: *Object, body: []const Air.Inst.Index) error{ AnalysisFail, OutOfM
909 .switch_br => try airSwitchBr(o, inst),909 .switch_br => try airSwitchBr(o, inst),
910 .wrap_optional => try airWrapOptional(o, inst),910 .wrap_optional => try airWrapOptional(o, inst),
911 .struct_field_ptr => try airStructFieldPtr(o, inst),911 .struct_field_ptr => try airStructFieldPtr(o, inst),
912
913 .struct_field_ptr_index_0 => try airStructFieldPtrIndex(o, inst, 0),
914 .struct_field_ptr_index_1 => try airStructFieldPtrIndex(o, inst, 1),
915 .struct_field_ptr_index_2 => try airStructFieldPtrIndex(o, inst, 2),
916 .struct_field_ptr_index_3 => try airStructFieldPtrIndex(o, inst, 3),
917
912 .struct_field_val => try airStructFieldVal(o, inst),918 .struct_field_val => try airStructFieldVal(o, inst),
913 .slice_ptr => try airSliceField(o, inst, ".ptr;\n"),919 .slice_ptr => try airSliceField(o, inst, ".ptr;\n"),
914 .slice_len => try airSliceField(o, inst, ".len;\n"),920 .slice_len => try airSliceField(o, inst, ".len;\n"),
...@@ -1651,15 +1657,31 @@ fn airOptionalPayload(o: *Object, inst: Air.Inst.Index) !CValue {...@@ -1651,15 +1657,31 @@ fn airOptionalPayload(o: *Object, inst: Air.Inst.Index) !CValue {
16511657
1652fn airStructFieldPtr(o: *Object, inst: Air.Inst.Index) !CValue {1658fn airStructFieldPtr(o: *Object, inst: Air.Inst.Index) !CValue {
1653 if (o.liveness.isUnused(inst))1659 if (o.liveness.isUnused(inst))
1654 return CValue.none;1660 // TODO this @as is needed because of a stage1 bug
1661 return @as(CValue, CValue.none);
16551662
1656 const ty_pl = o.air.instructions.items(.data)[inst].ty_pl;1663 const ty_pl = o.air.instructions.items(.data)[inst].ty_pl;
1657 const extra = o.air.extraData(Air.StructField, ty_pl.payload).data;1664 const extra = o.air.extraData(Air.StructField, ty_pl.payload).data;
1658 const writer = o.writer();
1659 const struct_ptr = try o.resolveInst(extra.struct_operand);1665 const struct_ptr = try o.resolveInst(extra.struct_operand);
1660 const struct_ptr_ty = o.air.typeOf(extra.struct_operand);1666 const struct_ptr_ty = o.air.typeOf(extra.struct_operand);
1667 return structFieldPtr(o, inst, struct_ptr_ty, struct_ptr, extra.field_index);
1668}
1669
1670fn airStructFieldPtrIndex(o: *Object, inst: Air.Inst.Index, index: u8) !CValue {
1671 if (o.liveness.isUnused(inst))
1672 // TODO this @as is needed because of a stage1 bug
1673 return @as(CValue, CValue.none);
1674
1675 const ty_op = o.air.instructions.items(.data)[inst].ty_op;
1676 const struct_ptr = try o.resolveInst(ty_op.operand);
1677 const struct_ptr_ty = o.air.typeOf(ty_op.operand);
1678 return structFieldPtr(o, inst, struct_ptr_ty, struct_ptr, index);
1679}
1680
1681fn structFieldPtr(o: *Object, inst: Air.Inst.Index, struct_ptr_ty: Type, struct_ptr: CValue, index: u32) !CValue {
1682 const writer = o.writer();
1661 const struct_obj = struct_ptr_ty.elemType().castTag(.@"struct").?.data;1683 const struct_obj = struct_ptr_ty.elemType().castTag(.@"struct").?.data;
1662 const field_name = struct_obj.fields.keys()[extra.field_index];1684 const field_name = struct_obj.fields.keys()[index];
16631685
1664 const inst_ty = o.air.typeOfIndex(inst);1686 const inst_ty = o.air.typeOfIndex(inst);
1665 const local = try o.allocLocal(inst_ty, .Const);1687 const local = try o.allocLocal(inst_ty, .Const);
src/codegen/llvm.zig+14
...@@ -1037,6 +1037,11 @@ pub const FuncGen = struct {...@@ -1037,6 +1037,11 @@ pub const FuncGen = struct {
1037 .struct_field_ptr => try self.airStructFieldPtr(inst),1037 .struct_field_ptr => try self.airStructFieldPtr(inst),
1038 .struct_field_val => try self.airStructFieldVal(inst),1038 .struct_field_val => try self.airStructFieldVal(inst),
10391039
1040 .struct_field_ptr_index_0 => try self.airStructFieldPtrIndex(inst, 0),
1041 .struct_field_ptr_index_1 => try self.airStructFieldPtrIndex(inst, 1),
1042 .struct_field_ptr_index_2 => try self.airStructFieldPtrIndex(inst, 2),
1043 .struct_field_ptr_index_3 => try self.airStructFieldPtrIndex(inst, 3),
1044
1040 .slice_elem_val => try self.airSliceElemVal(inst),1045 .slice_elem_val => try self.airSliceElemVal(inst),
1041 .ptr_slice_elem_val => try self.airPtrSliceElemVal(inst),1046 .ptr_slice_elem_val => try self.airPtrSliceElemVal(inst),
1042 .ptr_elem_val => try self.airPtrElemVal(inst),1047 .ptr_elem_val => try self.airPtrElemVal(inst),
...@@ -1350,6 +1355,15 @@ pub const FuncGen = struct {...@@ -1350,6 +1355,15 @@ pub const FuncGen = struct {
1350 return self.builder.buildStructGEP(struct_ptr, field_index, "");1355 return self.builder.buildStructGEP(struct_ptr, field_index, "");
1351 }1356 }
13521357
1358 fn airStructFieldPtrIndex(self: *FuncGen, inst: Air.Inst.Index, field_index: c_uint) !?*const llvm.Value {
1359 if (self.liveness.isUnused(inst))
1360 return null;
1361
1362 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
1363 const struct_ptr = try self.resolveInst(ty_op.operand);
1364 return self.builder.buildStructGEP(struct_ptr, field_index, "");
1365 }
1366
1353 fn airStructFieldVal(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value {1367 fn airStructFieldVal(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value {
1354 if (self.liveness.isUnused(inst))1368 if (self.liveness.isUnused(inst))
1355 return null;1369 return null;
src/codegen/wasm.zig+13-2
...@@ -862,6 +862,10 @@ pub const Context = struct {...@@ -862,6 +862,10 @@ pub const Context = struct {
862 .ret => self.airRet(inst),862 .ret => self.airRet(inst),
863 .store => self.airStore(inst),863 .store => self.airStore(inst),
864 .struct_field_ptr => self.airStructFieldPtr(inst),864 .struct_field_ptr => self.airStructFieldPtr(inst),
865 .struct_field_ptr_index_0 => self.airStructFieldPtrIndex(inst, 0),
866 .struct_field_ptr_index_1 => self.airStructFieldPtrIndex(inst, 1),
867 .struct_field_ptr_index_2 => self.airStructFieldPtrIndex(inst, 2),
868 .struct_field_ptr_index_3 => self.airStructFieldPtrIndex(inst, 3),
865 .switch_br => self.airSwitchBr(inst),869 .switch_br => self.airSwitchBr(inst),
866 .unreach => self.airUnreachable(inst),870 .unreach => self.airUnreachable(inst),
867 .wrap_optional => self.airWrapOptional(inst),871 .wrap_optional => self.airWrapOptional(inst),
...@@ -1441,8 +1445,15 @@ pub const Context = struct {...@@ -1441,8 +1445,15 @@ pub const Context = struct {
1441 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;1445 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
1442 const extra = self.air.extraData(Air.StructField, ty_pl.payload);1446 const extra = self.air.extraData(Air.StructField, ty_pl.payload);
1443 const struct_ptr = self.resolveInst(extra.data.struct_operand);1447 const struct_ptr = self.resolveInst(extra.data.struct_operand);
14441448 return structFieldPtr(struct_ptr, extra.data.field_index);
1445 return WValue{ .local = struct_ptr.multi_value.index + @intCast(u32, extra.data.field_index) };1449 }
1450 fn airStructFieldPtrIndex(self: *Context, inst: Air.Inst.Index, index: u32) InnerError!WValue {
1451 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
1452 const struct_ptr = self.resolveInst(ty_op.operand);
1453 return structFieldPtr(struct_ptr, index);
1454 }
1455 fn structFieldPtr(struct_ptr: WValue, index: u32) InnerError!WValue {
1456 return WValue{ .local = struct_ptr.multi_value.index + index };
1446 }1457 }
14471458
1448 fn airSwitchBr(self: *Context, inst: Air.Inst.Index) InnerError!WValue {1459 fn airSwitchBr(self: *Context, inst: Air.Inst.Index) InnerError!WValue {
src/print_air.zig+4
...@@ -169,6 +169,10 @@ const Writer = struct {...@@ -169,6 +169,10 @@ const Writer = struct {
169 .wrap_errunion_err,169 .wrap_errunion_err,
170 .slice_ptr,170 .slice_ptr,
171 .slice_len,171 .slice_len,
172 .struct_field_ptr_index_0,
173 .struct_field_ptr_index_1,
174 .struct_field_ptr_index_2,
175 .struct_field_ptr_index_3,
172 => try w.writeTyOp(s, inst),176 => try w.writeTyOp(s, inst),
173177
174 .block,178 .block,
test/stage2/cbe.zig+13
...@@ -555,6 +555,19 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -555,6 +555,19 @@ pub fn addCases(ctx: *TestContext) !void {
555 \\ return p.y - p.x - p.x;555 \\ return p.y - p.x - p.x;
556 \\}556 \\}
557 , "");557 , "");
558 case.addCompareOutput(
559 \\const Point = struct { x: i32, y: i32, z: i32, a: i32, b: i32 };
560 \\pub export fn main() c_int {
561 \\ var p: Point = .{
562 \\ .x = 18,
563 \\ .y = 24,
564 \\ .z = 1,
565 \\ .a = 2,
566 \\ .b = 3,
567 \\ };
568 \\ return p.y - p.x - p.z - p.a - p.b;
569 \\}
570 , "");
558 }571 }
559572
560 {573 {