Commit d8d5e2d4b9

Jimmi Holst Christensen <jhc@dismail.de>
2022-01-08 13:00:49
Implement offsetOf builtin function
1 parent 3f58678
Changed files (2)
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.
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) {