| author | |
| committer | |
| log | 4ac37eb484737e98269e198b31b81ee8e929b4f1 |
| tree | 2d5e66fcd1a2f6c9f129583d2ea8f671fff4832b |
| parent | f378b0adce80aa6f85d9bf6bf97172426de2c719 |
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 | 264 | /// Given a pointer to a struct and a field index, returns a pointer to the field. |
| 265 | 265 | /// Uses the `ty_pl` field, payload is `StructField`. |
| 266 | 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 | 274 | /// Given a byval struct and a field index, returns the field byval. |
| 268 | 275 | /// Uses the `ty_pl` field, payload is `StructField`. |
| 269 | 276 | struct_field_val, |
| ... | ... | @@ -510,6 +517,10 @@ pub fn typeOfIndex(air: Air, inst: Air.Inst.Index) Type { |
| 510 | 517 | .wrap_errunion_payload, |
| 511 | 518 | .wrap_errunion_err, |
| 512 | 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 | 524 | => return air.getRefType(datas[inst].ty_op.ty), |
| 514 | 525 | |
| 515 | 526 | .loop, |
src/Liveness.zig+4| ... | ... | @@ -282,6 +282,10 @@ fn analyzeInst( |
| 282 | 282 | .wrap_errunion_err, |
| 283 | 283 | .slice_ptr, |
| 284 | 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 | 290 | const o = inst_datas[inst].ty_op; |
| 287 | 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 | 8119 | } |
| 8120 | 8120 | |
| 8121 | 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 | 8140 | return block.addInst(.{ |
| 8123 | .tag = .struct_field_ptr, | |
| 8124 | .data = .{ .ty_pl = .{ | |
| 8141 | .tag = tag, | |
| 8142 | .data = .{ .ty_op = .{ | |
| 8125 | 8143 | .ty = try sema.addType(ptr_field_ty), |
| 8126 | .payload = try sema.addExtra(Air.StructField{ | |
| 8127 | .struct_operand = struct_ptr, | |
| 8128 | .field_index = @intCast(u32, field_index), | |
| 8129 | }), | |
| 8144 | .operand = struct_ptr, | |
| 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 | 855 | .store => try self.airStore(inst), |
| 856 | 856 | .struct_field_ptr=> try self.airStructFieldPtr(inst), |
| 857 | 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 | 864 | .switch_br => try self.airSwitch(inst), |
| 859 | 865 | .slice_ptr => try self.airSlicePtr(inst), |
| 860 | 866 | .slice_len => try self.airSliceLen(inst), |
| ... | ... | @@ -1592,7 +1598,18 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 1592 | 1598 | fn airStructFieldPtr(self: *Self, inst: Air.Inst.Index) !void { |
| 1593 | 1599 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; |
| 1594 | 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 | 1613 | return self.fail("TODO implement codegen struct_field_ptr", .{}); |
| 1597 | 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 | 909 | .switch_br => try airSwitchBr(o, inst), |
| 910 | 910 | .wrap_optional => try airWrapOptional(o, inst), |
| 911 | 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 | 918 | .struct_field_val => try airStructFieldVal(o, inst), |
| 913 | 919 | .slice_ptr => try airSliceField(o, inst, ".ptr;\n"), |
| 914 | 920 | .slice_len => try airSliceField(o, inst, ".len;\n"), |
| ... | ... | @@ -1651,15 +1657,31 @@ fn airOptionalPayload(o: *Object, inst: Air.Inst.Index) !CValue { |
| 1651 | 1657 | |
| 1652 | 1658 | fn airStructFieldPtr(o: *Object, inst: Air.Inst.Index) !CValue { |
| 1653 | 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); | |
| 1655 | 1662 | |
| 1656 | 1663 | const ty_pl = o.air.instructions.items(.data)[inst].ty_pl; |
| 1657 | 1664 | const extra = o.air.extraData(Air.StructField, ty_pl.payload).data; |
| 1658 | const writer = o.writer(); | |
| 1659 | 1665 | const struct_ptr = try o.resolveInst(extra.struct_operand); |
| 1660 | 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 | ||
| 1670 | fn 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 | ||
| 1681 | fn structFieldPtr(o: *Object, inst: Air.Inst.Index, struct_ptr_ty: Type, struct_ptr: CValue, index: u32) !CValue { | |
| 1682 | const writer = o.writer(); | |
| 1661 | 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]; | |
| 1663 | 1685 | |
| 1664 | 1686 | const inst_ty = o.air.typeOfIndex(inst); |
| 1665 | 1687 | const local = try o.allocLocal(inst_ty, .Const); |
src/codegen/llvm.zig+14| ... | ... | @@ -1037,6 +1037,11 @@ pub const FuncGen = struct { |
| 1037 | 1037 | .struct_field_ptr => try self.airStructFieldPtr(inst), |
| 1038 | 1038 | .struct_field_val => try self.airStructFieldVal(inst), |
| 1039 | 1039 | |
| 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 | 1045 | .slice_elem_val => try self.airSliceElemVal(inst), |
| 1041 | 1046 | .ptr_slice_elem_val => try self.airPtrSliceElemVal(inst), |
| 1042 | 1047 | .ptr_elem_val => try self.airPtrElemVal(inst), |
| ... | ... | @@ -1350,6 +1355,15 @@ pub const FuncGen = struct { |
| 1350 | 1355 | return self.builder.buildStructGEP(struct_ptr, field_index, ""); |
| 1351 | 1356 | } |
| 1352 | 1357 | |
| 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 | 1367 | fn airStructFieldVal(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value { |
| 1354 | 1368 | if (self.liveness.isUnused(inst)) |
| 1355 | 1369 | return null; |
src/codegen/wasm.zig+13-2| ... | ... | @@ -862,6 +862,10 @@ pub const Context = struct { |
| 862 | 862 | .ret => self.airRet(inst), |
| 863 | 863 | .store => self.airStore(inst), |
| 864 | 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 | 869 | .switch_br => self.airSwitchBr(inst), |
| 866 | 870 | .unreach => self.airUnreachable(inst), |
| 867 | 871 | .wrap_optional => self.airWrapOptional(inst), |
| ... | ... | @@ -1441,8 +1445,15 @@ pub const Context = struct { |
| 1441 | 1445 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; |
| 1442 | 1446 | const extra = self.air.extraData(Air.StructField, ty_pl.payload); |
| 1443 | 1447 | const struct_ptr = self.resolveInst(extra.data.struct_operand); |
| 1444 | ||
| 1445 | return WValue{ .local = struct_ptr.multi_value.index + @intCast(u32, extra.data.field_index) }; | |
| 1448 | return structFieldPtr(struct_ptr, 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 | } |
| 1447 | 1458 | |
| 1448 | 1459 | fn airSwitchBr(self: *Context, inst: Air.Inst.Index) InnerError!WValue { |
src/print_air.zig+4| ... | ... | @@ -169,6 +169,10 @@ const Writer = struct { |
| 169 | 169 | .wrap_errunion_err, |
| 170 | 170 | .slice_ptr, |
| 171 | 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 | 176 | => try w.writeTyOp(s, inst), |
| 173 | 177 | |
| 174 | 178 | .block, |
test/stage2/cbe.zig+13| ... | ... | @@ -555,6 +555,19 @@ pub fn addCases(ctx: *TestContext) !void { |
| 555 | 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 | } |
| 559 | 572 | |
| 560 | 573 | { |