aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJacob G-W <jacoblevgw@gmail.com>2021-08-16 23:11:55 -0400
committerAndrew Kelley <andrew@ziglang.org>2021-08-21 23:52:55 -0400
commit4ac37eb484737e98269e198b31b81ee8e929b4f1 (patch)
tree2d5e66fcd1a2f6c9f129583d2ea8f671fff4832b /src
parentf378b0adce80aa6f85d9bf6bf97172426de2c719 (diff)
downloadzig-4ac37eb484737e98269e198b31b81ee8e929b4f1.tar.gz
zig-4ac37eb484737e98269e198b31b81ee8e929b4f1.zip
stage2 Air: add struct_field_ptr_index_{0..3}
Since these are very common, it will save memory.
Diffstat (limited to 'src')
-rw-r--r--src/Air.zig11
-rw-r--r--src/Liveness.zig4
-rw-r--r--src/Sema.zig27
-rw-r--r--src/codegen.zig19
-rw-r--r--src/codegen/c.zig28
-rw-r--r--src/codegen/llvm.zig14
-rw-r--r--src/codegen/wasm.zig15
-rw-r--r--src/print_air.zig4
8 files changed, 110 insertions, 12 deletions
diff --git a/src/Air.zig b/src/Air.zig
index 81d220ba59..6e4125be44 100644
--- a/src/Air.zig
+++ b/src/Air.zig
@@ -264,6 +264,13 @@ pub const Inst = struct {
/// Given a pointer to a struct and a field index, returns a pointer to the field.
/// Uses the `ty_pl` field, payload is `StructField`.
struct_field_ptr,
+ /// Given a pointer to a struct, returns a pointer to the field.
+ /// The field index is the number at the end of the name.
+ /// Uses `ty_op` field.
+ struct_field_ptr_index_0,
+ struct_field_ptr_index_1,
+ struct_field_ptr_index_2,
+ struct_field_ptr_index_3,
/// Given a byval struct and a field index, returns the field byval.
/// Uses the `ty_pl` field, payload is `StructField`.
struct_field_val,
@@ -510,6 +517,10 @@ pub fn typeOfIndex(air: Air, inst: Air.Inst.Index) Type {
.wrap_errunion_payload,
.wrap_errunion_err,
.slice_ptr,
+ .struct_field_ptr_index_0,
+ .struct_field_ptr_index_1,
+ .struct_field_ptr_index_2,
+ .struct_field_ptr_index_3,
=> return air.getRefType(datas[inst].ty_op.ty),
.loop,
diff --git a/src/Liveness.zig b/src/Liveness.zig
index f6d51e58b4..6a47bfe597 100644
--- a/src/Liveness.zig
+++ b/src/Liveness.zig
@@ -282,6 +282,10 @@ fn analyzeInst(
.wrap_errunion_err,
.slice_ptr,
.slice_len,
+ .struct_field_ptr_index_0,
+ .struct_field_ptr_index_1,
+ .struct_field_ptr_index_2,
+ .struct_field_ptr_index_3,
=> {
const o = inst_datas[inst].ty_op;
return trackOperands(a, new_set, inst, main_tomb, .{ o.operand, .none, .none });
diff --git a/src/Sema.zig b/src/Sema.zig
index d543b59ac0..a11bdec66d 100644
--- a/src/Sema.zig
+++ b/src/Sema.zig
@@ -8119,14 +8119,29 @@ fn structFieldPtr(
}
try sema.requireRuntimeBlock(block, src);
+ const tag: Air.Inst.Tag = switch (field_index) {
+ 0 => .struct_field_ptr_index_0,
+ 1 => .struct_field_ptr_index_1,
+ 2 => .struct_field_ptr_index_2,
+ 3 => .struct_field_ptr_index_3,
+ else => {
+ return block.addInst(.{
+ .tag = .struct_field_ptr,
+ .data = .{ .ty_pl = .{
+ .ty = try sema.addType(ptr_field_ty),
+ .payload = try sema.addExtra(Air.StructField{
+ .struct_operand = struct_ptr,
+ .field_index = @intCast(u32, field_index),
+ }),
+ } },
+ });
+ },
+ };
return block.addInst(.{
- .tag = .struct_field_ptr,
- .data = .{ .ty_pl = .{
+ .tag = tag,
+ .data = .{ .ty_op = .{
.ty = try sema.addType(ptr_field_ty),
- .payload = try sema.addExtra(Air.StructField{
- .struct_operand = struct_ptr,
- .field_index = @intCast(u32, field_index),
- }),
+ .operand = struct_ptr,
} },
});
}
diff --git a/src/codegen.zig b/src/codegen.zig
index ca7a04a4a0..9103c7ad17 100644
--- a/src/codegen.zig
+++ b/src/codegen.zig
@@ -855,6 +855,12 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
.store => try self.airStore(inst),
.struct_field_ptr=> try self.airStructFieldPtr(inst),
.struct_field_val=> try self.airStructFieldVal(inst),
+
+ .struct_field_ptr_index_0 => try self.airStructFieldPtrIndex(inst, 0),
+ .struct_field_ptr_index_1 => try self.airStructFieldPtrIndex(inst, 1),
+ .struct_field_ptr_index_2 => try self.airStructFieldPtrIndex(inst, 2),
+ .struct_field_ptr_index_3 => try self.airStructFieldPtrIndex(inst, 3),
+
.switch_br => try self.airSwitch(inst),
.slice_ptr => try self.airSlicePtr(inst),
.slice_len => try self.airSliceLen(inst),
@@ -1592,7 +1598,18 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
fn airStructFieldPtr(self: *Self, inst: Air.Inst.Index) !void {
const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
const extra = self.air.extraData(Air.StructField, ty_pl.payload).data;
- _ = extra;
+ return self.structFieldPtr(extra.struct_operand, ty_pl.ty, extra.field_index);
+ }
+
+ fn airStructFieldPtrIndex(self: *Self, inst: Air.Inst.Index, index: u8) !void {
+ const ty_op = self.air.instructions.items(.data)[inst].ty_op;
+ return self.structFieldPtr(ty_op.operand, ty_op.ty, index);
+ }
+ fn structFieldPtr(self: *Self, operand: Air.Inst.Ref, ty: Air.Inst.Ref, index: u32) !void {
+ _ = self;
+ _ = operand;
+ _ = ty;
+ _ = index;
return self.fail("TODO implement codegen struct_field_ptr", .{});
//return self.finishAir(inst, result, .{ extra.struct_ptr, .none, .none });
}
diff --git a/src/codegen/c.zig b/src/codegen/c.zig
index bc3e357827..2084b1e1ce 100644
--- a/src/codegen/c.zig
+++ b/src/codegen/c.zig
@@ -909,6 +909,12 @@ fn genBody(o: *Object, body: []const Air.Inst.Index) error{ AnalysisFail, OutOfM
.switch_br => try airSwitchBr(o, inst),
.wrap_optional => try airWrapOptional(o, inst),
.struct_field_ptr => try airStructFieldPtr(o, inst),
+
+ .struct_field_ptr_index_0 => try airStructFieldPtrIndex(o, inst, 0),
+ .struct_field_ptr_index_1 => try airStructFieldPtrIndex(o, inst, 1),
+ .struct_field_ptr_index_2 => try airStructFieldPtrIndex(o, inst, 2),
+ .struct_field_ptr_index_3 => try airStructFieldPtrIndex(o, inst, 3),
+
.struct_field_val => try airStructFieldVal(o, inst),
.slice_ptr => try airSliceField(o, inst, ".ptr;\n"),
.slice_len => try airSliceField(o, inst, ".len;\n"),
@@ -1651,15 +1657,31 @@ fn airOptionalPayload(o: *Object, inst: Air.Inst.Index) !CValue {
fn airStructFieldPtr(o: *Object, inst: Air.Inst.Index) !CValue {
if (o.liveness.isUnused(inst))
- return CValue.none;
+ // TODO this @as is needed because of a stage1 bug
+ return @as(CValue, CValue.none);
const ty_pl = o.air.instructions.items(.data)[inst].ty_pl;
const extra = o.air.extraData(Air.StructField, ty_pl.payload).data;
- const writer = o.writer();
const struct_ptr = try o.resolveInst(extra.struct_operand);
const struct_ptr_ty = o.air.typeOf(extra.struct_operand);
+ return structFieldPtr(o, inst, struct_ptr_ty, struct_ptr, extra.field_index);
+}
+
+fn airStructFieldPtrIndex(o: *Object, inst: Air.Inst.Index, index: u8) !CValue {
+ if (o.liveness.isUnused(inst))
+ // TODO this @as is needed because of a stage1 bug
+ return @as(CValue, CValue.none);
+
+ const ty_op = o.air.instructions.items(.data)[inst].ty_op;
+ const struct_ptr = try o.resolveInst(ty_op.operand);
+ const struct_ptr_ty = o.air.typeOf(ty_op.operand);
+ return structFieldPtr(o, inst, struct_ptr_ty, struct_ptr, index);
+}
+
+fn structFieldPtr(o: *Object, inst: Air.Inst.Index, struct_ptr_ty: Type, struct_ptr: CValue, index: u32) !CValue {
+ const writer = o.writer();
const struct_obj = struct_ptr_ty.elemType().castTag(.@"struct").?.data;
- const field_name = struct_obj.fields.keys()[extra.field_index];
+ const field_name = struct_obj.fields.keys()[index];
const inst_ty = o.air.typeOfIndex(inst);
const local = try o.allocLocal(inst_ty, .Const);
diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig
index b80dcf0feb..d7aa2d45b3 100644
--- a/src/codegen/llvm.zig
+++ b/src/codegen/llvm.zig
@@ -1037,6 +1037,11 @@ pub const FuncGen = struct {
.struct_field_ptr => try self.airStructFieldPtr(inst),
.struct_field_val => try self.airStructFieldVal(inst),
+ .struct_field_ptr_index_0 => try self.airStructFieldPtrIndex(inst, 0),
+ .struct_field_ptr_index_1 => try self.airStructFieldPtrIndex(inst, 1),
+ .struct_field_ptr_index_2 => try self.airStructFieldPtrIndex(inst, 2),
+ .struct_field_ptr_index_3 => try self.airStructFieldPtrIndex(inst, 3),
+
.slice_elem_val => try self.airSliceElemVal(inst),
.ptr_slice_elem_val => try self.airPtrSliceElemVal(inst),
.ptr_elem_val => try self.airPtrElemVal(inst),
@@ -1350,6 +1355,15 @@ pub const FuncGen = struct {
return self.builder.buildStructGEP(struct_ptr, field_index, "");
}
+ fn airStructFieldPtrIndex(self: *FuncGen, inst: Air.Inst.Index, field_index: c_uint) !?*const llvm.Value {
+ if (self.liveness.isUnused(inst))
+ return null;
+
+ const ty_op = self.air.instructions.items(.data)[inst].ty_op;
+ const struct_ptr = try self.resolveInst(ty_op.operand);
+ return self.builder.buildStructGEP(struct_ptr, field_index, "");
+ }
+
fn airStructFieldVal(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value {
if (self.liveness.isUnused(inst))
return null;
diff --git a/src/codegen/wasm.zig b/src/codegen/wasm.zig
index 422afef9c4..bb05567236 100644
--- a/src/codegen/wasm.zig
+++ b/src/codegen/wasm.zig
@@ -862,6 +862,10 @@ pub const Context = struct {
.ret => self.airRet(inst),
.store => self.airStore(inst),
.struct_field_ptr => self.airStructFieldPtr(inst),
+ .struct_field_ptr_index_0 => self.airStructFieldPtrIndex(inst, 0),
+ .struct_field_ptr_index_1 => self.airStructFieldPtrIndex(inst, 1),
+ .struct_field_ptr_index_2 => self.airStructFieldPtrIndex(inst, 2),
+ .struct_field_ptr_index_3 => self.airStructFieldPtrIndex(inst, 3),
.switch_br => self.airSwitchBr(inst),
.unreach => self.airUnreachable(inst),
.wrap_optional => self.airWrapOptional(inst),
@@ -1441,8 +1445,15 @@ pub const Context = struct {
const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
const extra = self.air.extraData(Air.StructField, ty_pl.payload);
const struct_ptr = self.resolveInst(extra.data.struct_operand);
-
- return WValue{ .local = struct_ptr.multi_value.index + @intCast(u32, extra.data.field_index) };
+ return structFieldPtr(struct_ptr, extra.data.field_index);
+ }
+ fn airStructFieldPtrIndex(self: *Context, inst: Air.Inst.Index, index: u32) InnerError!WValue {
+ const ty_op = self.air.instructions.items(.data)[inst].ty_op;
+ const struct_ptr = self.resolveInst(ty_op.operand);
+ return structFieldPtr(struct_ptr, index);
+ }
+ fn structFieldPtr(struct_ptr: WValue, index: u32) InnerError!WValue {
+ return WValue{ .local = struct_ptr.multi_value.index + index };
}
fn airSwitchBr(self: *Context, inst: Air.Inst.Index) InnerError!WValue {
diff --git a/src/print_air.zig b/src/print_air.zig
index 20badcdc31..276158f720 100644
--- a/src/print_air.zig
+++ b/src/print_air.zig
@@ -169,6 +169,10 @@ const Writer = struct {
.wrap_errunion_err,
.slice_ptr,
.slice_len,
+ .struct_field_ptr_index_0,
+ .struct_field_ptr_index_1,
+ .struct_field_ptr_index_2,
+ .struct_field_ptr_index_3,
=> try w.writeTyOp(s, inst),
.block,