From dd437ae39948031dc04836f245c8b77d459a428a Mon Sep 17 00:00:00 2001 From: Veikka Tuominen Date: Mon, 24 Oct 2022 14:41:22 +0300 Subject: stage2: optimize size of optional slices --- src/codegen/c.zig | 14 +++++++++----- src/codegen/llvm.zig | 10 ++++++++-- 2 files changed, 17 insertions(+), 7 deletions(-) (limited to 'src/codegen') diff --git a/src/codegen/c.zig b/src/codegen/c.zig index d6584d75ae..5f6f2fd6d5 100644 --- a/src/codegen/c.zig +++ b/src/codegen/c.zig @@ -726,7 +726,11 @@ pub const DeclGen = struct { } if (ty.optionalReprIsPayload()) { - return dg.renderValue(writer, payload_ty, val, location); + if (val.castTag(.opt_payload)) |payload| { + return dg.renderValue(writer, payload_ty, payload.data, location); + } else { + return dg.renderValue(writer, payload_ty, val, location); + } } try writer.writeByte('('); @@ -3263,11 +3267,9 @@ fn airIsNull( try f.writeCValue(writer, operand); const ty = f.air.typeOf(un_op); + const opt_ty = if (deref_suffix[0] != 0) ty.childType() else ty; var opt_buf: Type.Payload.ElemType = undefined; - const payload_ty = if (deref_suffix[0] != 0) - ty.childType().optionalChild(&opt_buf) - else - ty.optionalChild(&opt_buf); + const payload_ty = opt_ty.optionalChild(&opt_buf); if (!payload_ty.hasRuntimeBitsIgnoreComptime()) { try writer.print("){s} {s} true;\n", .{ deref_suffix, operator }); @@ -3276,6 +3278,8 @@ fn airIsNull( try writer.print("){s} {s} NULL;\n", .{ deref_suffix, operator }); } else if (payload_ty.zigTypeTag() == .ErrorSet) { try writer.print("){s} {s} 0;\n", .{ deref_suffix, operator }); + } else if (payload_ty.isSlice() and opt_ty.optionalReprIsPayload()) { + try writer.print("){s}.ptr {s} NULL;\n", .{ deref_suffix, operator }); } else { try writer.print("){s}.is_null {s} true;\n", .{ deref_suffix, operator }); } diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index ffc19cb6f6..d4a94d1308 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -6316,18 +6316,24 @@ pub const FuncGen = struct { const operand_ty = self.air.typeOf(un_op); const optional_ty = if (operand_is_ptr) operand_ty.childType() else operand_ty; const optional_llvm_ty = try self.dg.lowerType(optional_ty); + var buf: Type.Payload.ElemType = undefined; + const payload_ty = optional_ty.optionalChild(&buf); if (optional_ty.optionalReprIsPayload()) { const loaded = if (operand_is_ptr) self.builder.buildLoad(optional_llvm_ty, operand, "") else operand; + if (payload_ty.isSlice()) { + const slice_ptr = self.builder.buildExtractValue(loaded, 0, ""); + var slice_buf: Type.SlicePtrFieldTypeBuffer = undefined; + const ptr_ty = try self.dg.lowerType(payload_ty.slicePtrFieldType(&slice_buf)); + return self.builder.buildICmp(pred, slice_ptr, ptr_ty.constNull(), ""); + } return self.builder.buildICmp(pred, loaded, optional_llvm_ty.constNull(), ""); } comptime assert(optional_layout_version == 3); - var buf: Type.Payload.ElemType = undefined; - const payload_ty = optional_ty.optionalChild(&buf); if (!payload_ty.hasRuntimeBitsIgnoreComptime()) { const loaded = if (operand_is_ptr) self.builder.buildLoad(optional_llvm_ty, operand, "") -- cgit v1.2.3 From 78a7bb108ad9f7bf59061675bcae8947d65afc3a Mon Sep 17 00:00:00 2001 From: Veikka Tuominen Date: Mon, 24 Oct 2022 14:46:14 +0300 Subject: llvm: handle namespace like packed structs Closes #13159 Closes #13188 --- src/codegen/llvm.zig | 2 +- test/behavior.zig | 1 + test/behavior/bugs/13159.zig | 14 ++++++++++++++ 3 files changed, 16 insertions(+), 1 deletion(-) create mode 100644 test/behavior/bugs/13159.zig (limited to 'src/codegen') diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index d4a94d1308..18b89eef78 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -1916,7 +1916,7 @@ pub const Object = struct { if (ty.castTag(.@"struct")) |payload| { const struct_obj = payload.data; - if (struct_obj.layout == .Packed) { + if (struct_obj.layout == .Packed and struct_obj.haveFieldTypes()) { const info = struct_obj.backing_int_ty.intInfo(target); const dwarf_encoding: c_uint = switch (info.signedness) { .signed => DW.ATE.signed, diff --git a/test/behavior.zig b/test/behavior.zig index 2f5d752087..442b27c09f 100644 --- a/test/behavior.zig +++ b/test/behavior.zig @@ -109,6 +109,7 @@ test { _ = @import("behavior/bugs/13128.zig"); _ = @import("behavior/bugs/13164.zig"); _ = @import("behavior/bugs/13171.zig"); + _ = @import("behavior/bugs/13159.zig"); _ = @import("behavior/byteswap.zig"); _ = @import("behavior/byval_arg_var.zig"); _ = @import("behavior/call.zig"); diff --git a/test/behavior/bugs/13159.zig b/test/behavior/bugs/13159.zig new file mode 100644 index 0000000000..6119c498a9 --- /dev/null +++ b/test/behavior/bugs/13159.zig @@ -0,0 +1,14 @@ +const std = @import("std"); +const expect = std.testing.expect; + +const Bar = packed struct { + const Baz = enum { + fizz, + buzz, + }; +}; + +test { + var foo = Bar.Baz.fizz; + try expect(foo == .fizz); +} -- cgit v1.2.3 From 595ccecd88d82874e7f677ee1809c04fc29424ff Mon Sep 17 00:00:00 2001 From: Veikka Tuominen Date: Tue, 25 Oct 2022 16:10:09 +0300 Subject: llvm: do not return undefined pointers from array_to_slice --- src/codegen/llvm.zig | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'src/codegen') diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index 18b89eef78..2eb95dc5e3 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -5434,10 +5434,11 @@ pub const FuncGen = struct { const llvm_usize = try self.dg.lowerType(Type.usize); const len = llvm_usize.constInt(array_ty.arrayLen(), .False); const slice_llvm_ty = try self.dg.lowerType(self.air.typeOfIndex(inst)); + const operand = try self.resolveInst(ty_op.operand); if (!array_ty.hasRuntimeBitsIgnoreComptime()) { - return self.builder.buildInsertValue(slice_llvm_ty.getUndef(), len, 1, ""); + const partial = self.builder.buildInsertValue(slice_llvm_ty.getUndef(), operand, 0, ""); + return self.builder.buildInsertValue(partial, len, 1, ""); } - const operand = try self.resolveInst(ty_op.operand); const indices: [2]*llvm.Value = .{ llvm_usize.constNull(), llvm_usize.constNull(), }; -- cgit v1.2.3 From f3a3fb3d880528e8b6404648c605ed092ef1412c Mon Sep 17 00:00:00 2001 From: Veikka Tuominen Date: Thu, 27 Oct 2022 00:23:43 +0300 Subject: llvm: pass optional slices like regular slices --- src/codegen/llvm.zig | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) (limited to 'src/codegen') diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index 2eb95dc5e3..2660b19bf3 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -1027,7 +1027,9 @@ pub const Object = struct { dg.addArgAttr(llvm_func, llvm_arg_i, "noalias"); } } - dg.addArgAttr(llvm_func, llvm_arg_i, "nonnull"); + if (param_ty.zigTypeTag() != .Optional) { + dg.addArgAttr(llvm_func, llvm_arg_i, "nonnull"); + } if (!ptr_info.mutable) { dg.addArgAttr(llvm_func, llvm_arg_i, "readonly"); } @@ -3117,7 +3119,11 @@ pub const DeclGen = struct { .slice => { const param_ty = fn_info.param_types[it.zig_index - 1]; var buf: Type.SlicePtrFieldTypeBuffer = undefined; - const ptr_ty = param_ty.slicePtrFieldType(&buf); + var opt_buf: Type.Payload.ElemType = undefined; + const ptr_ty = if (param_ty.zigTypeTag() == .Optional) + param_ty.optionalChild(&opt_buf).slicePtrFieldType(&buf) + else + param_ty.slicePtrFieldType(&buf); const ptr_llvm_ty = try dg.lowerType(ptr_ty); const len_llvm_ty = try dg.lowerType(Type.usize); @@ -10358,7 +10364,8 @@ const ParamTypeIterator = struct { .Unspecified, .Inline => { it.zig_index += 1; it.llvm_index += 1; - if (ty.isSlice()) { + var buf: Type.Payload.ElemType = undefined; + if (ty.isSlice() or (ty.zigTypeTag() == .Optional and ty.optionalChild(&buf).isSlice())) { return .slice; } else if (isByRef(ty)) { return .byref; -- cgit v1.2.3