From 11c64bfe6ec921a481b340392ab1d2377359586d Mon Sep 17 00:00:00 2001 From: Veikka Tuominen Date: Sun, 13 Nov 2022 20:19:46 +0200 Subject: llvm: implement arbitrary precision debug enumerators Closes #645 --- src/codegen/llvm.zig | 29 ++++++++++++++++++++++++----- src/codegen/llvm/bindings.zig | 13 ++++++++++++- 2 files changed, 36 insertions(+), 6 deletions(-) (limited to 'src/codegen') diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index abe4256a30..763dde170b 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -1507,6 +1507,11 @@ pub const Object = struct { }; const field_index_val = Value.initPayload(&buf_field_index.base); + var buffer: Type.Payload.Bits = undefined; + const int_ty = ty.intTagType(&buffer); + const int_info = ty.intInfo(target); + assert(int_info.bits != 0); + for (field_names) |field_name, i| { const field_name_z = try gpa.dupeZ(u8, field_name); defer gpa.free(field_name_z); @@ -1514,9 +1519,25 @@ pub const Object = struct { buf_field_index.data = @intCast(u32, i); var buf_u64: Value.Payload.U64 = undefined; const field_int_val = field_index_val.enumToInt(ty, &buf_u64); - // See https://github.com/ziglang/zig/issues/645 - const field_int = field_int_val.toSignedInt(); - enumerators[i] = dib.createEnumerator(field_name_z, field_int); + + var bigint_space: Value.BigIntSpace = undefined; + const bigint = field_int_val.toBigInt(&bigint_space, target); + + if (bigint.limbs.len == 1) { + enumerators[i] = dib.createEnumerator(field_name_z, bigint.limbs[0], int_info.signedness == .unsigned); + continue; + } + if (@sizeOf(usize) == @sizeOf(u64)) { + enumerators[i] = dib.createEnumerator2( + field_name_z, + @intCast(c_uint, bigint.limbs.len), + bigint.limbs.ptr, + int_info.bits, + int_info.signedness == .unsigned, + ); + continue; + } + @panic("TODO implement bigint debug enumerators to llvm int for 32-bit compiler builds"); } const di_file = try o.getDIFile(gpa, owner_decl.src_namespace.file_scope); @@ -1524,8 +1545,6 @@ pub const Object = struct { const name = try ty.nameAlloc(gpa, o.module); defer gpa.free(name); - var buffer: Type.Payload.Bits = undefined; - const int_ty = ty.intTagType(&buffer); const enum_di_ty = dib.createEnumerationType( di_scope, diff --git a/src/codegen/llvm/bindings.zig b/src/codegen/llvm/bindings.zig index a5b01d6ddf..1b462312cd 100644 --- a/src/codegen/llvm/bindings.zig +++ b/src/codegen/llvm/bindings.zig @@ -1662,7 +1662,18 @@ pub const DIBuilder = opaque { extern fn ZigLLVMCreateDebugEnumerator( dib: *DIBuilder, name: [*:0]const u8, - val: i64, + val: u64, + is_unsigned: bool, + ) *DIEnumerator; + + pub const createEnumerator2 = ZigLLVMCreateDebugEnumeratorOfArbitraryPrecision; + extern fn ZigLLVMCreateDebugEnumeratorOfArbitraryPrecision( + dib: *DIBuilder, + name: [*:0]const u8, + num_words: c_uint, + words: [*]const u64, + bits: c_uint, + is_unsigned: bool, ) *DIEnumerator; pub const createEnumerationType = ZigLLVMCreateDebugEnumerationType; -- cgit v1.2.3 From 28cbe5e92a36c81177dbcd2f33fc792468c08304 Mon Sep 17 00:00:00 2001 From: Veikka Tuominen Date: Wed, 16 Nov 2022 01:11:12 +0200 Subject: Sema+llvm: improve handling of namespace-like unions Closes #13557 --- src/Sema.zig | 5 ++--- src/codegen/llvm.zig | 4 ++-- test/behavior/union.zig | 22 ++++++++++++++++++++++ 3 files changed, 26 insertions(+), 5 deletions(-) (limited to 'src/codegen') diff --git a/src/Sema.zig b/src/Sema.zig index 454722728b..64b4bf97db 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -22476,13 +22476,12 @@ fn fieldVal( ); }, .Union => { - const union_ty = try sema.resolveTypeFields(child_type); - - if (union_ty.getNamespace()) |namespace| { + if (child_type.getNamespace()) |namespace| { if (try sema.namespaceLookupVal(block, src, namespace, field_name)) |inst| { return inst; } } + const union_ty = try sema.resolveTypeFields(child_type); if (union_ty.unionTagType()) |enum_ty| { if (enum_ty.enumFieldIndex(field_name)) |field_index_usize| { const field_index = @intCast(u32, field_index_usize); diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index 763dde170b..af9dcacf48 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -2137,7 +2137,8 @@ pub const Object = struct { break :blk fwd_decl; }; - if (!ty.hasRuntimeBitsIgnoreComptime()) { + const union_obj = ty.cast(Type.Payload.Union).?.data; + if (!union_obj.haveFieldTypes() or !ty.hasRuntimeBitsIgnoreComptime()) { const union_di_ty = try o.makeEmptyNamespaceDIType(owner_decl_index); dib.replaceTemporary(fwd_decl, union_di_ty); // The recursive call to `lowerDebugType` via `makeEmptyNamespaceDIType` @@ -2147,7 +2148,6 @@ pub const Object = struct { } const layout = ty.unionGetLayout(target); - const union_obj = ty.cast(Type.Payload.Union).?.data; if (layout.payload_size == 0) { const tag_di_ty = try o.lowerDebugType(union_obj.tag_ty, .full); diff --git a/test/behavior/union.zig b/test/behavior/union.zig index d473debe1f..37cd72e319 100644 --- a/test/behavior/union.zig +++ b/test/behavior/union.zig @@ -1388,3 +1388,25 @@ test "packed union in packed struct" { const a: S = .{ .nested = .{ .foo = 123 }, .bar = 5 }; try expect(a.unpack() == 123); } + +test "Namespace-like union" { + const DepType = enum { + git, + http, + const DepType = @This(); + const Version = union(DepType) { + git: Git, + http: void, + const Git = enum { + branch, + tag, + commit, + fn frozen(self: Git) bool { + return self == .tag; + } + }; + }; + }; + var a: DepType.Version.Git = .tag; + try expect(a.frozen()); +} -- cgit v1.2.3