From d8d5e2d4b959f9627853a9f1248609929f0f0de4 Mon Sep 17 00:00:00 2001 From: Jimmi Holst Christensen Date: Sat, 8 Jan 2022 13:00:49 +0100 Subject: [PATCH] Implement offsetOf builtin function --- src/Sema.zig | 32 ++++++++++++++++++++++++++++++-- src/type.zig | 10 ++++++++-- 2 files changed, 38 insertions(+), 4 deletions(-) diff --git a/src/Sema.zig b/src/Sema.zig index 9ecac34c77..d977826d72 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -11000,8 +11000,36 @@ fn zirBitOffsetOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError fn zirOffsetOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const inst_data = sema.code.instructions.items(.data)[inst].pl_node; - const src = inst_data.src(); - return sema.fail(block, src, "TODO: Sema.zirOffsetOf", .{}); + sema.src = .{ .node_offset_bin_op = inst_data.src_node }; + const lhs_src: LazySrcLoc = .{ .node_offset_bin_lhs = inst_data.src_node }; + const rhs_src: LazySrcLoc = .{ .node_offset_bin_rhs = inst_data.src_node }; + const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; + + const ty = try sema.resolveType(block, lhs_src, extra.lhs); + const field_name = try sema.resolveConstString(block, rhs_src, extra.rhs); + + try sema.resolveTypeLayout(block, lhs_src, ty); + if (ty.tag() != .@"struct") { + return sema.fail( + block, + lhs_src, + "expected struct type, found '{}'", + .{ty}, + ); + } + + const index = ty.structFields().getIndex(field_name) orelse { + return sema.fail( + block, + rhs_src, + "struct '{}' has no field '{s}'", + .{ ty, field_name }, + ); + }; + + const target = sema.mod.getTarget(); + const offset = ty.structFieldOffset(index, target); + return sema.addIntUnsigned(Type.comptime_int, offset); } /// Returns `true` if the type was a comptime_int. diff --git a/src/type.zig b/src/type.zig index f4561769e2..5e04a7e304 100644 --- a/src/type.zig +++ b/src/type.zig @@ -3777,7 +3777,10 @@ pub const Type = extern union { var offset: u64 = 0; var big_align: u32 = 0; for (struct_obj.fields.values()) |field, i| { - if (!field.ty.hasCodeGenBits()) continue; + if (!field.ty.hasCodeGenBits()) { + if (i == index) return offset; + continue; + } const field_align = field.normalAlignment(target); big_align = @maximum(big_align, field_align); @@ -3794,7 +3797,10 @@ pub const Type = extern union { var big_align: u32 = 0; var running_bits: u16 = 0; for (struct_obj.fields.values()) |field, i| { - if (!field.ty.hasCodeGenBits()) continue; + if (!field.ty.hasCodeGenBits()) { + if (i == index) return offset; + continue; + } const field_align = field.packedAlignment(); if (field_align == 0) {