mirror of
https://github.com/ziglang/zig.git
synced 2026-02-14 13:30:45 +00:00
stage2 Air: add struct_field_ptr_index_{0..3}
Since these are very common, it will save memory.
This commit is contained in:
parent
f378b0adce
commit
4ac37eb484
11
src/Air.zig
11
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,
|
||||
|
||||
@ -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 });
|
||||
|
||||
27
src/Sema.zig
27
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,
|
||||
} },
|
||||
});
|
||||
}
|
||||
|
||||
@ -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 });
|
||||
}
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -555,6 +555,19 @@ pub fn addCases(ctx: *TestContext) !void {
|
||||
\\ return p.y - p.x - p.x;
|
||||
\\}
|
||||
, "");
|
||||
case.addCompareOutput(
|
||||
\\const Point = struct { x: i32, y: i32, z: i32, a: i32, b: i32 };
|
||||
\\pub export fn main() c_int {
|
||||
\\ var p: Point = .{
|
||||
\\ .x = 18,
|
||||
\\ .y = 24,
|
||||
\\ .z = 1,
|
||||
\\ .a = 2,
|
||||
\\ .b = 3,
|
||||
\\ };
|
||||
\\ return p.y - p.x - p.z - p.a - p.b;
|
||||
\\}
|
||||
, "");
|
||||
}
|
||||
|
||||
{
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user