aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2021-12-28 20:48:21 -0700
committerAndrew Kelley <andrew@ziglang.org>2021-12-28 23:22:09 -0700
commit91619cdf57f54accbdbb3ff616856eaf79b537a3 (patch)
tree9da2362e728f068103a1ab83a89411f825a5c10b /src
parent2dd725571302a2e6e4101565554e88b4a10b0994 (diff)
downloadzig-91619cdf57f54accbdbb3ff616856eaf79b537a3.tar.gz
zig-91619cdf57f54accbdbb3ff616856eaf79b537a3.zip
Sema: implement calling a fn ptr via a union field
Also, ignore `packed` on unions because that will be removed from the language.
Diffstat (limited to 'src')
-rw-r--r--src/Module.zig3
-rw-r--r--src/Sema.zig58
2 files changed, 36 insertions, 25 deletions
diff --git a/src/Module.zig b/src/Module.zig
index 2c5c01bb7a..a1f804c282 100644
--- a/src/Module.zig
+++ b/src/Module.zig
@@ -1104,9 +1104,6 @@ pub const Union = struct {
pub fn getLayout(u: Union, target: Target, have_tag: bool) Layout {
assert(u.status == .have_layout);
- const is_packed = u.layout == .Packed;
- if (is_packed) @panic("TODO packed unions");
-
var most_aligned_field: usize = undefined;
var most_aligned_field_size: u64 = undefined;
var biggest_field: usize = undefined;
diff --git a/src/Sema.zig b/src/Sema.zig
index 2c2ba8bcb5..eca73a88e2 100644
--- a/src/Sema.zig
+++ b/src/Sema.zig
@@ -12152,34 +12152,16 @@ fn fieldCallBind(
const field_index = @intCast(u32, field_index_usize);
const field = struct_obj.fields.values()[field_index];
- const ptr_field_ty = try Type.ptr(arena, .{
- .pointee_type = field.ty,
- .mutable = ptr_ty.ptrIsMutable(),
- .@"addrspace" = ptr_ty.ptrAddressSpace(),
- });
-
- if (try sema.resolveDefinedValue(block, src, object_ptr)) |struct_ptr_val| {
- const pointer = try sema.addConstant(
- ptr_field_ty,
- try Value.Tag.field_ptr.create(arena, .{
- .container_ptr = struct_ptr_val,
- .field_index = field_index,
- }),
- );
- return sema.analyzeLoad(block, src, pointer, src);
- }
-
- try sema.requireRuntimeBlock(block, src);
- const ptr_inst = try block.addStructFieldPtr(object_ptr, field_index, ptr_field_ty);
- return sema.analyzeLoad(block, src, ptr_inst, src);
+ return finishFieldCallBind(sema, block, src, ptr_ty, field.ty, field_index, object_ptr);
},
.Union => {
const union_ty = try sema.resolveTypeFields(block, src, concrete_ty);
const fields = union_ty.unionFields();
const field_index_usize = fields.getIndex(field_name) orelse break :find_field;
+ const field_index = @intCast(u32, field_index_usize);
+ const field = fields.values()[field_index];
- _ = field_index_usize;
- return sema.fail(block, src, "TODO implement field calls on unions", .{});
+ return finishFieldCallBind(sema, block, src, ptr_ty, field.ty, field_index, object_ptr);
},
.Type => {
const namespace = try sema.analyzeLoad(block, src, object_ptr, src);
@@ -12236,6 +12218,38 @@ fn fieldCallBind(
return sema.fail(block, src, "type '{}' has no field or member function named '{s}'", .{ concrete_ty, field_name });
}
+fn finishFieldCallBind(
+ sema: *Sema,
+ block: *Block,
+ src: LazySrcLoc,
+ ptr_ty: Type,
+ field_ty: Type,
+ field_index: u32,
+ object_ptr: Air.Inst.Ref,
+) CompileError!Air.Inst.Ref {
+ const arena = sema.arena;
+ const ptr_field_ty = try Type.ptr(arena, .{
+ .pointee_type = field_ty,
+ .mutable = ptr_ty.ptrIsMutable(),
+ .@"addrspace" = ptr_ty.ptrAddressSpace(),
+ });
+
+ if (try sema.resolveDefinedValue(block, src, object_ptr)) |struct_ptr_val| {
+ const pointer = try sema.addConstant(
+ ptr_field_ty,
+ try Value.Tag.field_ptr.create(arena, .{
+ .container_ptr = struct_ptr_val,
+ .field_index = field_index,
+ }),
+ );
+ return sema.analyzeLoad(block, src, pointer, src);
+ }
+
+ try sema.requireRuntimeBlock(block, src);
+ const ptr_inst = try block.addStructFieldPtr(object_ptr, field_index, ptr_field_ty);
+ return sema.analyzeLoad(block, src, ptr_inst, src);
+}
+
fn namespaceLookup(
sema: *Sema,
block: *Block,