diff options
| author | Jacob Young <jacobly0@users.noreply.github.com> | 2023-06-01 22:05:54 -0400 |
|---|---|---|
| committer | Andrew Kelley <andrew@ziglang.org> | 2023-06-10 20:47:59 -0700 |
| commit | bc3b56f957d950edb6fde3585f8e9f4dda009d3e (patch) | |
| tree | a1757c0438d0d5a613f36fac9600bfe9cf3e3cbb /src/codegen/llvm.zig | |
| parent | 35550c840b07df017b360c81c3cd0a8a3da55aae (diff) | |
| download | zig-bc3b56f957d950edb6fde3585f8e9f4dda009d3e.tar.gz zig-bc3b56f957d950edb6fde3585f8e9f4dda009d3e.zip | |
llvm: fix undefined pointer type
Diffstat (limited to 'src/codegen/llvm.zig')
| -rw-r--r-- | src/codegen/llvm.zig | 247 |
1 files changed, 120 insertions, 127 deletions
diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index bd50528095..723a550027 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -3789,10 +3789,7 @@ pub const DeclGen = struct { fn lowerIntAsPtr(dg: *DeclGen, val: Value) Error!*llvm.Value { switch (dg.module.intern_pool.indexToKey(val.toIntern())) { - .undef => { - const llvm_usize = try dg.lowerType(Type.usize); - return llvm_usize.getUndef(); - }, + .undef => return dg.context.pointerType(0).getUndef(), .int => { var bigint_space: Value.BigIntSpace = undefined; const bigint = val.toBigInt(&bigint_space, dg.module); @@ -3847,141 +3844,137 @@ pub const DeclGen = struct { fn lowerParentPtr(dg: *DeclGen, ptr_val: Value, byte_aligned: bool) Error!*llvm.Value { const mod = dg.module; const target = mod.getTarget(); - return switch (mod.intern_pool.indexToKey(ptr_val.toIntern())) { - .int => dg.lowerIntAsPtr(ptr_val), - .ptr => |ptr| switch (ptr.addr) { - .decl => |decl| dg.lowerParentPtrDecl(ptr_val, decl), - .mut_decl => |mut_decl| dg.lowerParentPtrDecl(ptr_val, mut_decl.decl), - .int => |int| dg.lowerIntAsPtr(int.toValue()), - .eu_payload => |eu_ptr| { - const parent_llvm_ptr = try dg.lowerParentPtr(eu_ptr.toValue(), true); - - const eu_ty = mod.intern_pool.typeOf(eu_ptr).toType().childType(mod); - const payload_ty = eu_ty.errorUnionPayload(mod); - if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) { - // In this case, we represent pointer to error union the same as pointer - // to the payload. - return parent_llvm_ptr; - } + return switch (mod.intern_pool.indexToKey(ptr_val.toIntern()).ptr.addr) { + .decl => |decl| dg.lowerParentPtrDecl(ptr_val, decl), + .mut_decl => |mut_decl| dg.lowerParentPtrDecl(ptr_val, mut_decl.decl), + .int => |int| dg.lowerIntAsPtr(int.toValue()), + .eu_payload => |eu_ptr| { + const parent_llvm_ptr = try dg.lowerParentPtr(eu_ptr.toValue(), true); + + const eu_ty = mod.intern_pool.typeOf(eu_ptr).toType().childType(mod); + const payload_ty = eu_ty.errorUnionPayload(mod); + if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) { + // In this case, we represent pointer to error union the same as pointer + // to the payload. + return parent_llvm_ptr; + } - const payload_offset: u8 = if (payload_ty.abiAlignment(mod) > Type.anyerror.abiSize(mod)) 2 else 1; - const llvm_u32 = dg.context.intType(32); - const indices: [2]*llvm.Value = .{ - llvm_u32.constInt(0, .False), - llvm_u32.constInt(payload_offset, .False), - }; - const eu_llvm_ty = try dg.lowerType(eu_ty); - return eu_llvm_ty.constInBoundsGEP(parent_llvm_ptr, &indices, indices.len); - }, - .opt_payload => |opt_ptr| { - const parent_llvm_ptr = try dg.lowerParentPtr(opt_ptr.toValue(), true); + const payload_offset: u8 = if (payload_ty.abiAlignment(mod) > Type.anyerror.abiSize(mod)) 2 else 1; + const llvm_u32 = dg.context.intType(32); + const indices: [2]*llvm.Value = .{ + llvm_u32.constInt(0, .False), + llvm_u32.constInt(payload_offset, .False), + }; + const eu_llvm_ty = try dg.lowerType(eu_ty); + return eu_llvm_ty.constInBoundsGEP(parent_llvm_ptr, &indices, indices.len); + }, + .opt_payload => |opt_ptr| { + const parent_llvm_ptr = try dg.lowerParentPtr(opt_ptr.toValue(), true); - const opt_ty = mod.intern_pool.typeOf(opt_ptr).toType().childType(mod); - const payload_ty = opt_ty.optionalChild(mod); - if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod) or - payload_ty.optionalReprIsPayload(mod)) - { - // In this case, we represent pointer to optional the same as pointer - // to the payload. - return parent_llvm_ptr; - } + const opt_ty = mod.intern_pool.typeOf(opt_ptr).toType().childType(mod); + const payload_ty = opt_ty.optionalChild(mod); + if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod) or + payload_ty.optionalReprIsPayload(mod)) + { + // In this case, we represent pointer to optional the same as pointer + // to the payload. + return parent_llvm_ptr; + } - const llvm_u32 = dg.context.intType(32); - const indices: [2]*llvm.Value = .{ - llvm_u32.constInt(0, .False), - llvm_u32.constInt(0, .False), - }; - const opt_llvm_ty = try dg.lowerType(opt_ty); - return opt_llvm_ty.constInBoundsGEP(parent_llvm_ptr, &indices, indices.len); - }, - .comptime_field => unreachable, - .elem => |elem_ptr| { - const parent_llvm_ptr = try dg.lowerParentPtr(elem_ptr.base.toValue(), true); + const llvm_u32 = dg.context.intType(32); + const indices: [2]*llvm.Value = .{ + llvm_u32.constInt(0, .False), + llvm_u32.constInt(0, .False), + }; + const opt_llvm_ty = try dg.lowerType(opt_ty); + return opt_llvm_ty.constInBoundsGEP(parent_llvm_ptr, &indices, indices.len); + }, + .comptime_field => unreachable, + .elem => |elem_ptr| { + const parent_llvm_ptr = try dg.lowerParentPtr(elem_ptr.base.toValue(), true); - const llvm_usize = try dg.lowerType(Type.usize); - const indices: [1]*llvm.Value = .{ - llvm_usize.constInt(elem_ptr.index, .False), - }; - const elem_ty = mod.intern_pool.typeOf(elem_ptr.base).toType().elemType2(mod); - const elem_llvm_ty = try dg.lowerType(elem_ty); - return elem_llvm_ty.constInBoundsGEP(parent_llvm_ptr, &indices, indices.len); - }, - .field => |field_ptr| { - const parent_llvm_ptr = try dg.lowerParentPtr(field_ptr.base.toValue(), byte_aligned); - const parent_ty = mod.intern_pool.typeOf(field_ptr.base).toType().childType(mod); - - const field_index = @intCast(u32, field_ptr.index); - const llvm_u32 = dg.context.intType(32); - switch (parent_ty.zigTypeTag(mod)) { - .Union => { - if (parent_ty.containerLayout(mod) == .Packed) { - return parent_llvm_ptr; - } + const llvm_usize = try dg.lowerType(Type.usize); + const indices: [1]*llvm.Value = .{ + llvm_usize.constInt(elem_ptr.index, .False), + }; + const elem_ty = mod.intern_pool.typeOf(elem_ptr.base).toType().elemType2(mod); + const elem_llvm_ty = try dg.lowerType(elem_ty); + return elem_llvm_ty.constInBoundsGEP(parent_llvm_ptr, &indices, indices.len); + }, + .field => |field_ptr| { + const parent_llvm_ptr = try dg.lowerParentPtr(field_ptr.base.toValue(), byte_aligned); + const parent_ty = mod.intern_pool.typeOf(field_ptr.base).toType().childType(mod); + + const field_index = @intCast(u32, field_ptr.index); + const llvm_u32 = dg.context.intType(32); + switch (parent_ty.zigTypeTag(mod)) { + .Union => { + if (parent_ty.containerLayout(mod) == .Packed) { + return parent_llvm_ptr; + } - const layout = parent_ty.unionGetLayout(mod); - if (layout.payload_size == 0) { - // In this case a pointer to the union and a pointer to any - // (void) payload is the same. - return parent_llvm_ptr; - } - const llvm_pl_index = if (layout.tag_size == 0) - 0 - else - @boolToInt(layout.tag_align >= layout.payload_align); - const indices: [2]*llvm.Value = .{ - llvm_u32.constInt(0, .False), - llvm_u32.constInt(llvm_pl_index, .False), + const layout = parent_ty.unionGetLayout(mod); + if (layout.payload_size == 0) { + // In this case a pointer to the union and a pointer to any + // (void) payload is the same. + return parent_llvm_ptr; + } + const llvm_pl_index = if (layout.tag_size == 0) + 0 + else + @boolToInt(layout.tag_align >= layout.payload_align); + const indices: [2]*llvm.Value = .{ + llvm_u32.constInt(0, .False), + llvm_u32.constInt(llvm_pl_index, .False), + }; + const parent_llvm_ty = try dg.lowerType(parent_ty); + return parent_llvm_ty.constInBoundsGEP(parent_llvm_ptr, &indices, indices.len); + }, + .Struct => { + if (parent_ty.containerLayout(mod) == .Packed) { + if (!byte_aligned) return parent_llvm_ptr; + const llvm_usize = dg.context.intType(target.ptrBitWidth()); + const base_addr = parent_llvm_ptr.constPtrToInt(llvm_usize); + // count bits of fields before this one + const prev_bits = b: { + var b: usize = 0; + for (parent_ty.structFields(mod).values()[0..field_index]) |field| { + if (field.is_comptime or !field.ty.hasRuntimeBitsIgnoreComptime(mod)) continue; + b += @intCast(usize, field.ty.bitSize(mod)); + } + break :b b; }; - const parent_llvm_ty = try dg.lowerType(parent_ty); - return parent_llvm_ty.constInBoundsGEP(parent_llvm_ptr, &indices, indices.len); - }, - .Struct => { - if (parent_ty.containerLayout(mod) == .Packed) { - if (!byte_aligned) return parent_llvm_ptr; - const llvm_usize = dg.context.intType(target.ptrBitWidth()); - const base_addr = parent_llvm_ptr.constPtrToInt(llvm_usize); - // count bits of fields before this one - const prev_bits = b: { - var b: usize = 0; - for (parent_ty.structFields(mod).values()[0..field_index]) |field| { - if (field.is_comptime or !field.ty.hasRuntimeBitsIgnoreComptime(mod)) continue; - b += @intCast(usize, field.ty.bitSize(mod)); - } - break :b b; - }; - const byte_offset = llvm_usize.constInt(prev_bits / 8, .False); - const field_addr = base_addr.constAdd(byte_offset); - const final_llvm_ty = dg.context.pointerType(0); - return field_addr.constIntToPtr(final_llvm_ty); - } + const byte_offset = llvm_usize.constInt(prev_bits / 8, .False); + const field_addr = base_addr.constAdd(byte_offset); + const final_llvm_ty = dg.context.pointerType(0); + return field_addr.constIntToPtr(final_llvm_ty); + } - const parent_llvm_ty = try dg.lowerType(parent_ty); - if (llvmField(parent_ty, field_index, mod)) |llvm_field| { - const indices: [2]*llvm.Value = .{ - llvm_u32.constInt(0, .False), - llvm_u32.constInt(llvm_field.index, .False), - }; - return parent_llvm_ty.constInBoundsGEP(parent_llvm_ptr, &indices, indices.len); - } else { - const llvm_index = llvm_u32.constInt(@boolToInt(parent_ty.hasRuntimeBitsIgnoreComptime(mod)), .False); - const indices: [1]*llvm.Value = .{llvm_index}; - return parent_llvm_ty.constInBoundsGEP(parent_llvm_ptr, &indices, indices.len); - } - }, - .Pointer => { - assert(parent_ty.isSlice(mod)); + const parent_llvm_ty = try dg.lowerType(parent_ty); + if (llvmField(parent_ty, field_index, mod)) |llvm_field| { const indices: [2]*llvm.Value = .{ llvm_u32.constInt(0, .False), - llvm_u32.constInt(field_index, .False), + llvm_u32.constInt(llvm_field.index, .False), }; - const parent_llvm_ty = try dg.lowerType(parent_ty); return parent_llvm_ty.constInBoundsGEP(parent_llvm_ptr, &indices, indices.len); - }, - else => unreachable, - } - }, + } else { + const llvm_index = llvm_u32.constInt(@boolToInt(parent_ty.hasRuntimeBitsIgnoreComptime(mod)), .False); + const indices: [1]*llvm.Value = .{llvm_index}; + return parent_llvm_ty.constInBoundsGEP(parent_llvm_ptr, &indices, indices.len); + } + }, + .Pointer => { + assert(parent_ty.isSlice(mod)); + const indices: [2]*llvm.Value = .{ + llvm_u32.constInt(0, .False), + llvm_u32.constInt(field_index, .False), + }; + const parent_llvm_ty = try dg.lowerType(parent_ty); + return parent_llvm_ty.constInBoundsGEP(parent_llvm_ptr, &indices, indices.len); + }, + else => unreachable, + } }, - else => unreachable, }; } |
