diff --git a/src/Air.zig b/src/Air.zig index ff88990bfa52c8dfe7ed5a3a108f70ba9c11e598..a3de9c84c867cc0e4ca158087b0e60c7efc6e1c2 100644 --- a/src/Air.zig +++ b/src/Air.zig @@ -1843,15 +1843,6 @@ pub fn internedToRef(ip_index: InternPool.Index) Inst.Ref { return .fromIntern(ip_index); } -/// Returns `null` if runtime-known. -pub fn value(air: Air, inst: Inst.Ref, pt: Zcu.PerThread) !?Value { - if (inst.toInterned()) |ip_index| { - return .fromInterned(ip_index); - } - const index = inst.toIndex().?; - return air.typeOfIndex(index, &pt.zcu.intern_pool).onePossibleValue(pt); -} - pub const NullTerminatedString = enum(u32) { none = std.math.maxInt(u32), _, diff --git a/src/Sema.zig b/src/Sema.zig index 1876ec5dbea763a21673adc8ed0ad7f51d07b703..0629e827a97a3acd68dc811714020b600616e341 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -18896,7 +18896,7 @@ fn finishStructInit( var bit_offset: u16 = 0; for (field_inits) |field_init| { const field_val = sema.resolveValue(field_init).?; - field_val.writeToPackedMemory(pt, buf, bit_offset) catch |err| switch (err) { + field_val.writeToPackedMemory(zcu, buf, bit_offset) catch |err| switch (err) { error.ReinterpretDeclRef => unreachable, // bitpack fields cannot be pointers error.OutOfMemory => |e| return e, }; diff --git a/src/Sema/bitcast.zig b/src/Sema/bitcast.zig index 0e4c90027e959e02a9c023680a8c22489e5502f9..6d3da8daf4ec2a51b3f2c36b55812863e70f8d8a 100644 --- a/src/Sema/bitcast.zig +++ b/src/Sema/bitcast.zig @@ -443,7 +443,7 @@ const UnpackValueBits = struct { // This @intCast is okay because no primitive can exceed the size of a u16. const int_ty = try unpack.pt.intType(.unsigned, @intCast(bit_count)); const buf = try unpack.arena.alloc(u8, @intCast((val_bits + 7) / 8)); - try val.writeToPackedMemory(unpack.pt, buf, 0); + try val.writeToPackedMemory(zcu, buf, 0); const sub_val = try Value.readFromPackedMemory(int_ty, unpack.pt, buf, @intCast(bit_offset), unpack.arena); try unpack.primitive(sub_val); }, @@ -722,7 +722,7 @@ const PackValueBits = struct { const val = Value.fromInterned(ip_val); const ty = val.typeOf(zcu); if (!val.isUndef(zcu)) { - try val.writeToPackedMemory(pt, buf, cur_bit_off); + try val.writeToPackedMemory(zcu, buf, cur_bit_off); } cur_bit_off += @intCast(ty.bitSize(zcu)); } diff --git a/src/Value.zig b/src/Value.zig index 826fba11e6a214dd3248933d2111df58dce22626..cc0e577f84717beacf9398b0bdc7a98173d3276f 100644 --- a/src/Value.zig +++ b/src/Value.zig @@ -245,13 +245,12 @@ pub fn toBool(val: Value) bool { /// /// Asserts that buffer.len >= ty.abiSize(). The buffer is allowed to extend past /// the end of the value in memory. -pub fn writeToMemory(val: Value, pt: Zcu.PerThread, buffer: []u8) error{ +pub fn writeToMemory(val: Value, zcu: *const Zcu, buffer: []u8) error{ ReinterpretDeclRef, IllDefinedMemoryLayout, Unimplemented, OutOfMemory, }!void { - const zcu = pt.zcu; const target = zcu.getTarget(); const endian = target.cpu.arch.endian(); const ip = &zcu.intern_pool; @@ -289,14 +288,18 @@ pub fn writeToMemory(val: Value, pt: Zcu.PerThread, buffer: []u8) error{ else => unreachable, }, .array => { + const aggregate = ip.indexToKey(val.toIntern()).aggregate; const len = ty.arrayLen(zcu); const elem_ty = ty.childType(zcu); const elem_size: usize = @intCast(elem_ty.abiSize(zcu)); var elem_i: usize = 0; var buf_off: usize = 0; while (elem_i < len) : (elem_i += 1) { - const elem_val = try val.elemValue(pt, elem_i); - try elem_val.writeToMemory(pt, buffer[buf_off..]); + switch (aggregate.storage) { + .bytes => |bytes| buffer[buf_off] = bytes.at(elem_i, ip), + .elems => |elems| try Value.fromInterned(elems[elem_i]).writeToMemory(zcu, buffer[buf_off..]), + .repeated_elem => |elem| try Value.fromInterned(elem).writeToMemory(zcu, buffer[buf_off..]), + } buf_off += elem_size; } }, @@ -304,7 +307,7 @@ pub fn writeToMemory(val: Value, pt: Zcu.PerThread, buffer: []u8) error{ // We use byte_count instead of abi_size here, so that any padding bytes // follow the data bytes, on both big- and little-endian systems. const byte_count = (@as(usize, @intCast(ty.bitSize(zcu))) + 7) / 8; - return writeToPackedMemory(val, pt, buffer[0..byte_count], 0); + return writeToPackedMemory(val, zcu, buffer[0..byte_count], 0); }, .@"struct" => { const struct_type = zcu.typeToStruct(ty) orelse return error.IllDefinedMemoryLayout; @@ -320,42 +323,33 @@ pub fn writeToMemory(val: Value, pt: Zcu.PerThread, buffer: []u8) error{ .elems => |elems| elems[field_index], .repeated_elem => |elem| elem, }); - try writeToMemory(field_val, pt, buffer[off..]); + try writeToMemory(field_val, zcu, buffer[off..]); }, .@"packed" => { const int_index = ip.indexToKey(val.toIntern()).bitpack.backing_int_val; - return Value.fromInterned(int_index).writeToMemory(pt, buffer); + return Value.fromInterned(int_index).writeToMemory(zcu, buffer); }, } }, .@"union" => switch (ty.containerLayout(zcu)) { .auto => return error.IllDefinedMemoryLayout, // Sema is supposed to have emitted a compile error already .@"extern" => { - if (val.unionTag(zcu)) |union_tag| { - const union_obj = zcu.typeToUnion(ty).?; - const field_index = zcu.unionTagFieldIndex(union_obj, union_tag).?; - const field_type = Type.fromInterned(union_obj.field_types.get(ip)[field_index]); - const field_val = try val.fieldValue(pt, field_index); - const byte_count: usize = @intCast(field_type.abiSize(zcu)); - return writeToMemory(field_val, pt, buffer[0..byte_count]); - } else { - const backing_ty = try ty.externUnionBackingType(pt); - const byte_count: usize = @intCast(backing_ty.abiSize(zcu)); - return writeToMemory(val.unionPayload(zcu), pt, buffer[0..byte_count]); - } + const payload_val = val.unionPayload(zcu); + return writeToMemory(payload_val, zcu, buffer); }, .@"packed" => { const int_val: Value = .fromInterned(ip.indexToKey(val.toIntern()).bitpack.backing_int_val); - return writeToMemory(int_val, pt, buffer); + return writeToMemory(int_val, zcu, buffer); }, }, .optional => { if (!ty.isPtrLikeOptional(zcu)) return error.IllDefinedMemoryLayout; const opt_val = val.optionalValue(zcu); if (opt_val) |some| { - return some.writeToMemory(pt, buffer); + return some.writeToMemory(zcu, buffer); } else { - return writeToMemory(try pt.intValue(Type.usize, 0), pt, buffer); + const byte_count = Type.usize.abiSize(zcu); + @memset(buffer[0..@intCast(byte_count)], 0); // null pointer } }, else => return error.Unimplemented, @@ -368,11 +362,10 @@ pub fn writeToMemory(val: Value, pt: Zcu.PerThread, buffer: []u8) error{ /// big-endian packed memory layouts start at the end of the buffer. pub fn writeToPackedMemory( val: Value, - pt: Zcu.PerThread, + zcu: *const Zcu, buffer: []u8, bit_offset: usize, ) error{ ReinterpretDeclRef, OutOfMemory }!void { - const zcu = pt.zcu; const ip = &zcu.intern_pool; const target = zcu.getTarget(); const endian = target.cpu.arch.endian(); @@ -399,7 +392,7 @@ pub fn writeToPackedMemory( }, .@"enum" => { const int_val = val.intFromEnum(zcu); - return int_val.writeToPackedMemory(pt, buffer, bit_offset); + return int_val.writeToPackedMemory(zcu, buffer, bit_offset); }, .pointer => { assert(!ty.isSlice(zcu)); // No well defined layout. @@ -430,25 +423,29 @@ pub fn writeToPackedMemory( var bits: u16 = 0; var elem_i: usize = 0; + const aggregate = ip.indexToKey(val.toIntern()).aggregate; while (elem_i < len) : (elem_i += 1) { // On big-endian systems, LLVM reverses the element order of vectors by default const tgt_elem_i = if (endian == .big) len - elem_i - 1 else elem_i; - const elem_val = try val.elemValue(pt, tgt_elem_i); - try elem_val.writeToPackedMemory(pt, buffer, bit_offset + bits); + switch (aggregate.storage) { + .bytes => |bytes| std.mem.writePackedInt(u8, buffer, bit_offset + bits, bytes.at(tgt_elem_i, ip), endian), + .elems => |elems| try Value.fromInterned(elems[tgt_elem_i]).writeToPackedMemory(zcu, buffer, bit_offset + bits), + .repeated_elem => |elem| try Value.fromInterned(elem).writeToPackedMemory(zcu, buffer, bit_offset + bits), + } bits += elem_bit_size; } }, .@"struct", .@"union" => { assert(ty.containerLayout(zcu) == .@"packed"); const int_val: Value = .fromInterned(ip.indexToKey(val.toIntern()).bitpack.backing_int_val); - return int_val.writeToPackedMemory(pt, buffer, bit_offset); + return int_val.writeToPackedMemory(zcu, buffer, bit_offset); }, .optional => { assert(ty.isPtrLikeOptional(zcu)); if (val.optionalValue(zcu)) |ptr_val| { - return ptr_val.writeToPackedMemory(pt, buffer, bit_offset); + return ptr_val.writeToPackedMemory(zcu, buffer, bit_offset); } else { - return Value.zero_usize.writeToPackedMemory(pt, buffer, bit_offset); + return Value.zero_usize.writeToPackedMemory(zcu, buffer, bit_offset); } }, else => @panic("TODO implement writeToPackedMemory for more types"), @@ -889,7 +886,7 @@ pub fn fieldValue(val: Value, pt: Zcu.PerThread, index: usize) !Value { const sfba = sfba_state.get(); const buf = try sfba.alloc(u8, @intCast((ty.bitSize(zcu) + 7) / 8)); defer sfba.free(buf); - int_val.writeToPackedMemory(pt, buf, 0) catch |err| switch (err) { + int_val.writeToPackedMemory(zcu, buf, 0) catch |err| switch (err) { error.ReinterpretDeclRef => unreachable, // it's an integer error.OutOfMemory => |e| return e, }; @@ -902,7 +899,7 @@ pub fn fieldValue(val: Value, pt: Zcu.PerThread, index: usize) !Value { }; } -pub fn unionTag(val: Value, zcu: *Zcu) ?Value { +pub fn unionTag(val: Value, zcu: *const Zcu) ?Value { return switch (zcu.intern_pool.indexToKey(val.toIntern())) { .undef, .enum_tag => val, .un => |un| if (un.tag != .none) Value.fromInterned(un.tag) else return null, @@ -910,7 +907,7 @@ pub fn unionTag(val: Value, zcu: *Zcu) ?Value { }; } -pub fn unionPayload(val: Value, zcu: *Zcu) Value { +pub fn unionPayload(val: Value, zcu: *const Zcu) Value { return switch (zcu.intern_pool.indexToKey(val.toIntern())) { .un => |un| Value.fromInterned(un.val), else => unreachable, @@ -1605,15 +1602,14 @@ pub fn mulAddScalar( /// If the value is represented in-memory as a series of bytes that all /// have the same value, return that byte value, otherwise null. -pub fn hasRepeatedByteRepr(val: Value, pt: Zcu.PerThread) !?u8 { - const zcu = pt.zcu; +pub fn hasRepeatedByteRepr(val: Value, zcu: *const Zcu) !?u8 { const ty = val.typeOf(zcu); const abi_size = std.math.cast(usize, ty.abiSize(zcu)) orelse return null; assert(abi_size >= 1); const byte_buffer = try zcu.gpa.alloc(u8, abi_size); defer zcu.gpa.free(byte_buffer); - writeToMemory(val, pt, byte_buffer) catch |err| switch (err) { + writeToMemory(val, zcu, byte_buffer) catch |err| switch (err) { error.OutOfMemory => return error.OutOfMemory, error.ReinterpretDeclRef => return null, // TODO: The writeToMemory function was originally created for the purpose diff --git a/src/Zcu/PerThread.zig b/src/Zcu/PerThread.zig index 88dcbe2431fac65e7c3923253eaf2eacc9518771..c9972a300abea99261410ce5ea2de893040a3b8a 100644 --- a/src/Zcu/PerThread.zig +++ b/src/Zcu/PerThread.zig @@ -3751,7 +3751,7 @@ fn processExportsInner( if (skip_linker_work) return; if (zcu.llvm_object) |llvm_object| { - try zcu.handleUpdateExports(export_indices, llvm_object.updateExports(pt, exported, export_indices)); + try zcu.handleUpdateExports(export_indices, llvm_object.updateExports(exported, export_indices)); } else if (zcu.comp.bin_file) |lf| { try zcu.handleUpdateExports(export_indices, lf.updateExports(pt, exported, export_indices)); } diff --git a/src/codegen/aarch64/Select.zig b/src/codegen/aarch64/Select.zig index 779994980e8c6fee39bc3f262c2635d35dfdc135..c8a9f41cb3d6c2906e7011373ede8fca90a031a3 100644 --- a/src/codegen/aarch64/Select.zig +++ b/src/codegen/aarch64/Select.zig @@ -11364,7 +11364,7 @@ fn writeToMemory(isel: *Select, constant: Constant, buffer: []u8) error{OutOfMem const zcu = isel.pt.zcu; const ip = &zcu.intern_pool; if (try isel.writeKeyToMemory(ip.indexToKey(constant.toIntern()), buffer)) return true; - constant.writeToMemory(isel.pt, buffer) catch |err| switch (err) { + constant.writeToMemory(zcu, buffer) catch |err| switch (err) { error.OutOfMemory => return error.OutOfMemory, error.ReinterpretDeclRef, error.Unimplemented, error.IllDefinedMemoryLayout => return false, }; diff --git a/src/codegen/c.zig b/src/codegen/c.zig index e126cf535b08ee7fef804e051455e4f419c5a32f..1b72c8759907bb004e0c31850bc1e53ccde57dea 100644 --- a/src/codegen/c.zig +++ b/src/codegen/c.zig @@ -435,8 +435,7 @@ pub const Function = struct { fn resolveInst(f: *Function, ref: Air.Inst.Ref) !CValue { const gop = try f.value_map.getOrPut(ref); if (!gop.found_existing) { - const val = try f.air.value(ref, f.dg.pt); - gop.value_ptr.* = .{ .constant = val.? }; + gop.value_ptr.* = .{ .constant = .fromInterned(ref.toInterned().?) }; } return gop.value_ptr.*; } @@ -3389,7 +3388,7 @@ fn airStore(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue { const ptr_val = try f.resolveInst(bin_op.lhs); const src_ty = f.typeOf(bin_op.rhs); - const val_is_undef = if (try f.air.value(bin_op.rhs, pt)) |v| v.isUndef(zcu) else false; + const val_is_undef = if (bin_op.rhs.toInterned()) |ip_index| Value.fromInterned(ip_index).isUndef(zcu) else false; const w = &f.code.writer; if (val_is_undef) { @@ -3922,8 +3921,8 @@ fn airCall( callee: { known: { - const callee_val = (try f.air.value(call.callee, pt)) orelse break :known; - const fn_nav, const need_cast = switch (ip.indexToKey(callee_val.toIntern())) { + const callee_ip_index = call.callee.toInterned() orelse break :known; + const fn_nav, const need_cast = switch (ip.indexToKey(callee_ip_index)) { .@"extern" => |@"extern"| .{ @"extern".owner_nav, false }, .func => |func| .{ func.owner_nav, Type.fromInterned(func.ty).fnCallingConvention(zcu) != .naked and Type.fromInterned(func.uncoerced_ty).fnCallingConvention(zcu) == .naked }, @@ -4027,7 +4026,7 @@ fn airDbgVar(f: *Function, inst: Air.Inst.Index) !CValue { const tag = f.air.instructions.items(.tag)[@intFromEnum(inst)]; const pl_op = f.air.instructions.items(.data)[@intFromEnum(inst)].pl_op; const name: Air.NullTerminatedString = @enumFromInt(pl_op.payload); - const operand_is_undef = if (try f.air.value(pl_op.operand, pt)) |v| v.isUndef(zcu) else false; + const operand_is_undef = if (pl_op.operand.toInterned()) |ip_index| Value.fromInterned(ip_index).isUndef(zcu) else false; if (!operand_is_undef) _ = try f.resolveInst(pl_op.operand); try reap(f, inst, &.{pl_op.operand}); @@ -4204,7 +4203,8 @@ fn airSwitchDispatch(f: *Function, inst: Air.Inst.Index) !void { const br = f.air.instructions.items(.data)[@intFromEnum(inst)].br; const w = &f.code.writer; - if (try f.air.value(br.operand, pt)) |cond_val| { + if (br.operand.toInterned()) |cond_ip_index| { + const cond_val: Value = .fromInterned(cond_ip_index); // Comptime-known dispatch. Iterate the cases to find the correct // one, and branch directly to the corresponding case. const switch_br = f.air.unwrapSwitch(br.block_inst); @@ -4539,12 +4539,12 @@ fn airSwitchBr(f: *Function, inst: Air.Inst.Index, is_dispatch_loop: bool) !void try f.writeCValue(w, cond_val, .other); try w.writeAll(", "); } - const item_value = try f.air.value(item, pt); + const item_value: Value = .fromInterned(item.toInterned().?); // If `item_value` is a pointer with a known integer address, print the address // with no cast to avoid a warning. write_val: { if (cond_ty.zigTypeTag(zcu) == .pointer) { - if (item_value.?.getUnsignedInt(zcu)) |item_int| { + if (item_value.getUnsignedInt(zcu)) |item_int| { try w.print("{f}", .{try f.fmtIntLiteralDec(try pt.intValue(lowered_cond_ty, item_int))}); break :write_val; } @@ -4552,7 +4552,7 @@ fn airSwitchBr(f: *Function, inst: Air.Inst.Index, is_dispatch_loop: bool) !void try f.renderType(w, .usize); try w.writeByte(')'); } - try f.dg.renderValue(w, (try f.air.value(item, pt)).?, .other); + try f.dg.renderValue(w, .fromInterned(item.toInterned().?), .other); } switch (cond_cint) { .zig_u128, .zig_i128 => try w.writeByte(')'), @@ -4710,7 +4710,7 @@ fn lowerSwitchCmp( try f.writeCValue(w, cond_val, .other); try w.writeAll(if (use_builtin) ", " else compareOperatorC(operator)); if (class == .big) try w.writeByte('&'); - try f.dg.renderValue(w, (try f.air.value(case_inst, pt)).?, .other); + try f.dg.renderValue(w, .fromInterned(case_inst.toInterned().?), .other); if (use_builtin) { try f.dg.renderBuiltinInfo(w, ty, if (class == .big) .bits else .none); try w.writeByte(')'); @@ -6100,7 +6100,7 @@ fn airMemset(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue { const value = try f.resolveInst(bin_op.rhs); const elem_ty = f.typeOf(bin_op.rhs); const elem_abi_size = elem_ty.abiSize(zcu); - const val_is_undef = if (try f.air.value(bin_op.rhs, pt)) |val| val.isUndef(zcu) else false; + const val_is_undef = if (bin_op.rhs.toInterned()) |ip_index| Value.fromInterned(ip_index).isUndef(zcu) else false; const w = &f.code.writer; if (val_is_undef) { diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index c5ea440405d1ceca9f3f9a1ff2266764bbdb76ad..b34f630fc21e87c4e49d51dd9c9c27c991bbf0bf 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -696,11 +696,11 @@ pub const Object = struct { self.* = undefined; } - fn genErrorNameTable(o: *Object, pt: Zcu.PerThread) Allocator.Error!void { + fn genErrorNameTable(o: *Object) Allocator.Error!void { // If o.error_name_table is null, then it was not referenced by any instructions. if (o.error_name_table == .none) return; - const zcu = pt.zcu; + const zcu = o.zcu; const ip = &zcu.intern_pool; const error_name_list = ip.global_error_set.getNamesFromMainThread(); @@ -709,8 +709,8 @@ pub const Object = struct { // TODO: Address space const slice_ty = Type.slice_const_u8_sentinel_0; - const llvm_usize_ty = try o.lowerType(pt, Type.usize); - const llvm_slice_ty = try o.lowerType(pt, slice_ty); + const llvm_usize_ty = try o.lowerType(.usize); + const llvm_slice_ty = try o.lowerType(slice_ty); const llvm_table_ty = try o.builder.arrayType(1 + error_name_list.len, llvm_slice_ty); llvm_errors[0] = try o.builder.undefConst(llvm_slice_ty); @@ -768,7 +768,7 @@ pub const Object = struct { }; pub fn emit(o: *Object, pt: Zcu.PerThread, options: EmitOptions) error{ LinkFailure, OutOfMemory }!void { - const zcu = pt.zcu; + const zcu = o.zcu; const comp = zcu.comp; const io = comp.io; const diags = &comp.link_diags; @@ -779,7 +779,7 @@ pub const Object = struct { const init_val = try o.builder.intConst(try o.errorIntType(), errors_len); try o.errors_len_variable.setInitializer(init_val, &o.builder); } - try o.genErrorNameTable(pt); + try o.genErrorNameTable(); try o.genModuleLevelAssembly(); if (o.used.items.len > 0) { @@ -1139,7 +1139,7 @@ pub const Object = struct { air: *const Air, liveness: *const ?Air.Liveness, ) !void { - const zcu = pt.zcu; + const zcu = o.zcu; const comp = zcu.comp; const ip = &zcu.intern_pool; const func = zcu.funcInfo(func_index); @@ -1150,7 +1150,7 @@ pub const Object = struct { const fn_info = zcu.typeToFunc(fn_ty).?; const target = &owner_mod.resolved_target.result; - const function_index = try o.resolveLlvmFunction(pt, func.owner_nav); + const function_index = try o.resolveLlvmFunction(func.owner_nav); var attributes = try function_index.ptrConst(&o.builder).attributes.toWip(&o.builder); defer attributes.deinit(&o.builder); @@ -1262,7 +1262,7 @@ pub const Object = struct { defer args.deinit(gpa); { - var it = iterateParamTypes(o, pt, fn_info); + var it = iterateParamTypes(o, fn_info); while (try it.next()) |lowering| { try args.ensureUnusedCapacity(gpa, 1); @@ -1289,7 +1289,7 @@ pub const Object = struct { }, .byref => { const param_ty = Type.fromInterned(fn_info.param_types.get(ip)[it.zig_index - 1]); - const param_llvm_ty = try o.lowerType(pt, param_ty); + const param_llvm_ty = try o.lowerType(param_ty); const param = wip.arg(llvm_arg_i); const alignment = param_ty.abiAlignment(zcu).toLlvm(); @@ -1304,7 +1304,7 @@ pub const Object = struct { }, .byref_mut => { const param_ty = Type.fromInterned(fn_info.param_types.get(ip)[it.zig_index - 1]); - const param_llvm_ty = try o.lowerType(pt, param_ty); + const param_llvm_ty = try o.lowerType(param_ty); const param = wip.arg(llvm_arg_i); const alignment = param_ty.abiAlignment(zcu).toLlvm(); @@ -1323,7 +1323,7 @@ pub const Object = struct { const param = wip.arg(llvm_arg_i); llvm_arg_i += 1; - const param_llvm_ty = try o.lowerType(pt, param_ty); + const param_llvm_ty = try o.lowerType(param_ty); const alignment = param_ty.abiAlignment(zcu).toLlvm(); const arg_ptr = try buildAllocaInner(&wip, param_llvm_ty, alignment, target); _ = try wip.store(.normal, param, arg_ptr, alignment); @@ -1362,7 +1362,7 @@ pub const Object = struct { const len_param = wip.arg(llvm_arg_i); llvm_arg_i += 1; - const slice_llvm_ty = try o.lowerType(pt, param_ty); + const slice_llvm_ty = try o.lowerType(param_ty); args.appendAssumeCapacity( try wip.buildAggregate(slice_llvm_ty, &.{ ptr_param, len_param }, ""), ); @@ -1371,7 +1371,7 @@ pub const Object = struct { assert(!it.byval_attr); const field_types = it.types_buffer[0..it.types_len]; const param_ty = Type.fromInterned(fn_info.param_types.get(ip)[it.zig_index - 1]); - const param_llvm_ty = try o.lowerType(pt, param_ty); + const param_llvm_ty = try o.lowerType(param_ty); const param_alignment = param_ty.abiAlignment(zcu).toLlvm(); const arg_ptr = try buildAllocaInner(&wip, param_llvm_ty, param_alignment, target); const llvm_ty = try o.builder.structType(.normal, field_types); @@ -1391,7 +1391,7 @@ pub const Object = struct { }, .float_array => { const param_ty = Type.fromInterned(fn_info.param_types.get(ip)[it.zig_index - 1]); - const param_llvm_ty = try o.lowerType(pt, param_ty); + const param_llvm_ty = try o.lowerType(param_ty); const param = wip.arg(llvm_arg_i); llvm_arg_i += 1; @@ -1406,7 +1406,7 @@ pub const Object = struct { }, .i32_array, .i64_array => { const param_ty = Type.fromInterned(fn_info.param_types.get(ip)[it.zig_index - 1]); - const param_llvm_ty = try o.lowerType(pt, param_ty); + const param_llvm_ty = try o.lowerType(param_ty); const param = wip.arg(llvm_arg_i); llvm_arg_i += 1; @@ -1560,7 +1560,7 @@ pub const Object = struct { } pub fn updateNav(o: *Object, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) !void { - const zcu = pt.zcu; + const zcu = o.zcu; const ip = &zcu.intern_pool; const nav = ip.getNav(nav_index); @@ -1573,12 +1573,12 @@ pub const Object = struct { const ty: Type = .fromInterned(nav.resolved.?.type); if (linkage != .internal and ip.isFunctionType(ty.toIntern())) { - const function_index = try o.resolveLlvmFunction(pt, owner_nav); + const function_index = try o.resolveLlvmFunction(owner_nav); // Add parameter attributes which weren't set by `resolveLlvmFunction` const fn_info = zcu.typeToFunc(ty).?; var attributes = try function_index.ptrConst(&o.builder).attributes.toWip(&o.builder); defer attributes.deinit(&o.builder); - var it = iterateParamTypes(o, pt, fn_info); + var it = iterateParamTypes(o, fn_info); if (firstParamSRet(fn_info, zcu, zcu.getTarget())) it.llvm_index += 1; if (fn_info.cc == .auto and zcu.comp.config.any_error_tracing) it.llvm_index += 1; while (try it.next()) |lowering| switch (lowering) { @@ -1591,7 +1591,7 @@ pub const Object = struct { }, .byref => { const param_ty = Type.fromInterned(fn_info.param_types.get(ip)[it.zig_index - 1]); - const param_llvm_ty = try o.lowerType(pt, param_ty); + const param_llvm_ty = try o.lowerType(param_ty); const alignment = param_ty.abiAlignment(zcu); try o.addByRefParamAttrs(&attributes, it.llvm_index - 1, alignment.toLlvm(), it.byval_attr, param_llvm_ty); }, @@ -1609,14 +1609,14 @@ pub const Object = struct { }; function_index.setAttributes(try attributes.finish(&o.builder), &o.builder); } else { - const variable_index = try o.resolveGlobalNav(pt, nav_index); + const variable_index = try o.resolveGlobalNav(nav_index); variable_index.setAlignment(zcu.navAlignment(nav_index).toLlvm(), &o.builder); if (resolved.@"linksection".toSlice(ip)) |section| variable_index.setSection(try o.builder.string(section), &o.builder); if (resolved.@"const") variable_index.setMutability(.constant, &o.builder); try variable_index.setInitializer(switch (init_val) { .none => .no_init, - else => try o.lowerValue(pt, init_val), + else => try o.lowerValue(init_val), }, &o.builder); variable_index.setVisibility(visibility, &o.builder); @@ -1703,14 +1703,13 @@ pub const Object = struct { pub fn updateExports( self: *Object, - pt: Zcu.PerThread, exported: Zcu.Exported, export_indices: []const Zcu.Export.Index, ) link.File.UpdateExportsError!void { - const zcu = pt.zcu; + const zcu = self.zcu; const nav_index = switch (exported) { .nav => |nav| nav, - .uav => |uav| return updateExportedValue(self, pt, uav, export_indices), + .uav => |uav| return updateExportedValue(self, uav, export_indices), }; const ip = &zcu.intern_pool; const global_index = self.nav_map.get(nav_index).?; @@ -1751,11 +1750,10 @@ pub const Object = struct { fn updateExportedValue( o: *Object, - pt: Zcu.PerThread, exported_value: InternPool.Index, export_indices: []const Zcu.Export.Index, ) link.File.UpdateExportsError!void { - const zcu = pt.zcu; + const zcu = o.zcu; const gpa = zcu.gpa; const ip = &zcu.intern_pool; const main_exp_name = try o.builder.strtabString(export_indices[0].ptr(zcu).opts.name.toSlice(ip)); @@ -1769,13 +1767,13 @@ pub const Object = struct { const llvm_addr_space = toLlvmAddressSpace(.generic, zcu.getTarget()); const variable_index = try o.builder.addVariable( main_exp_name, - try o.lowerType(pt, Type.fromInterned(ip.typeOf(exported_value))), + try o.lowerType(.fromInterned(ip.typeOf(exported_value))), llvm_addr_space, ); const global_index = variable_index.ptrConst(&o.builder).global; gop.value_ptr.* = global_index; // This line invalidates `gop`. - const init_val = try o.lowerValue(pt, exported_value); + const init_val = try o.lowerValue(exported_value); try variable_index.setInitializer(init_val, &o.builder); break :i global_index; }; @@ -1894,7 +1892,7 @@ pub const Object = struct { pub fn updateContainerType(o: *Object, pt: Zcu.PerThread, ty: InternPool.Index, success: bool) Allocator.Error!void { try o.type_pool.updateContainerType(pt, .{ .llvm = o }, ty, success); if (o.named_enum_map.get(ty)) |function_index| { - try o.updateIsNamedEnumValueFunction(pt, .fromInterned(ty), function_index); + try o.updateIsNamedEnumValueFunction(.fromInterned(ty), function_index); } } @@ -1902,7 +1900,8 @@ pub const Object = struct { /// /// `val` is always a type because `o.type_pool` only contains types. pub fn addConst(o: *Object, pt: Zcu.PerThread, index: link.ConstPool.Index, val: InternPool.Index) Allocator.Error!void { - const zcu = pt.zcu; + _ = pt; + const zcu = o.zcu; const gpa = zcu.comp.gpa; assert(zcu.intern_pool.typeOf(val) == .type_type); @@ -1928,7 +1927,7 @@ pub const Object = struct { /// /// `val` is always a type because `o.type_pool` only contains types. pub fn updateConstIncomplete(o: *Object, pt: Zcu.PerThread, index: link.ConstPool.Index, val: InternPool.Index) Allocator.Error!void { - const zcu = pt.zcu; + const zcu = o.zcu; assert(zcu.intern_pool.typeOf(val) == .type_type); const ty: Type = .fromInterned(val); @@ -1950,7 +1949,7 @@ pub const Object = struct { /// /// `val` is always a type because `o.type_pool` only contains types. pub fn updateConst(o: *Object, pt: Zcu.PerThread, index: link.ConstPool.Index, val: InternPool.Index) Allocator.Error!void { - const zcu = pt.zcu; + const zcu = o.zcu; assert(zcu.intern_pool.typeOf(val) == .type_type); const ty: Type = .fromInterned(val); @@ -2005,7 +2004,7 @@ pub const Object = struct { assert(!o.builder.strip); const gpa = o.gpa; - const zcu = pt.zcu; + const zcu = o.zcu; const target = zcu.getTarget(); const ip = &zcu.intern_pool; @@ -2712,30 +2711,20 @@ pub const Object = struct { } fn namespaceToDebugScope(o: *Object, pt: Zcu.PerThread, namespace_index: InternPool.NamespaceIndex) !Builder.Metadata { - const zcu = pt.zcu; + const zcu = o.zcu; const namespace = zcu.namespacePtr(namespace_index); if (namespace.parent == .none) return try o.getDebugFile(namespace.file_scope); return o.getDebugType(pt, .fromInterned(namespace.owner_type)); } - fn allocTypeName(o: *Object, pt: Zcu.PerThread, ty: Type) Allocator.Error![:0]const u8 { - var aw: Io.Writer.Allocating = .init(o.gpa); - defer aw.deinit(); - ty.print(&aw.writer, pt, null) catch |err| switch (err) { - error.WriteFailed => return error.OutOfMemory, - }; - return aw.toOwnedSliceSentinel(0); - } - /// If the llvm function does not exist, create it. /// Note that this can be called before the function's semantic analysis has /// completed, so if any attributes rely on that, they must be done in updateFunc, not here. pub fn resolveLlvmFunction( o: *Object, - pt: Zcu.PerThread, nav_index: InternPool.Nav.Index, ) Allocator.Error!Builder.Function.Index { - const zcu = pt.zcu; + const zcu = o.zcu; const ip = &zcu.intern_pool; const gpa = o.gpa; const nav = ip.getNav(nav_index); @@ -2752,7 +2741,7 @@ pub const Object = struct { else .{ false, .none }; const function_index = try o.builder.addFunction( - try o.lowerType(pt, ty), + try o.lowerType(ty), try o.builder.strtabString((if (is_extern) nav.name else nav.fqn).toSlice(ip)), toLlvmAddressSpace(nav.resolved.?.@"addrspace", target), ); @@ -2785,7 +2774,7 @@ pub const Object = struct { try attributes.addParamAttr(llvm_arg_i, .nonnull, &o.builder); try attributes.addParamAttr(llvm_arg_i, .@"noalias", &o.builder); - const raw_llvm_ret_ty = try o.lowerType(pt, Type.fromInterned(fn_info.return_type)); + const raw_llvm_ret_ty = try o.lowerType(.fromInterned(fn_info.return_type)); try attributes.addParamAttr(llvm_arg_i, .{ .sret = raw_llvm_ret_ty }, &o.builder); llvm_arg_i += 1; @@ -2965,7 +2954,6 @@ pub const Object = struct { fn resolveGlobalUav( o: *Object, - pt: Zcu.PerThread, uav: InternPool.Index, llvm_addr_space: Builder.AddrSpace, alignment: InternPool.Alignment, @@ -2983,17 +2971,17 @@ pub const Object = struct { } errdefer assert(o.uav_map.remove(uav)); - const zcu = pt.zcu; + const zcu = o.zcu; const decl_ty = zcu.intern_pool.typeOf(uav); const variable_index = try o.builder.addVariable( try o.builder.strtabStringFmt("__anon_{d}", .{@intFromEnum(uav)}), - try o.lowerType(pt, Type.fromInterned(decl_ty)), + try o.lowerType(.fromInterned(decl_ty)), llvm_addr_space, ); gop.value_ptr.* = variable_index.ptrConst(&o.builder).global; - try variable_index.setInitializer(try o.lowerValue(pt, uav), &o.builder); + try variable_index.setInitializer(try o.lowerValue(uav), &o.builder); variable_index.setLinkage(if (o.builder.strip) .private else .internal, &o.builder); variable_index.setMutability(.constant, &o.builder); variable_index.setUnnamedAddr(.unnamed_addr, &o.builder); @@ -3003,14 +2991,13 @@ pub const Object = struct { fn resolveGlobalNav( o: *Object, - pt: Zcu.PerThread, nav_index: InternPool.Nav.Index, ) Allocator.Error!Builder.Variable.Index { const gop = try o.nav_map.getOrPut(o.gpa, nav_index); if (gop.found_existing) return gop.value_ptr.ptr(&o.builder).kind.variable; errdefer assert(o.nav_map.remove(nav_index)); - const zcu = pt.zcu; + const zcu = o.zcu; const ip = &zcu.intern_pool; const nav = ip.getNav(nav_index); const linkage: std.builtin.GlobalLinkage, const visibility: Builder.Visibility, const is_dll_import: bool = switch (nav.resolved.?.value) { @@ -3027,7 +3014,7 @@ pub const Object = struct { .strong, .weak => nav.name, .link_once => unreachable, }.toSlice(ip)), - try o.lowerType(pt, .fromInterned(nav.resolved.?.type)), + try o.lowerType(.fromInterned(nav.resolved.?.type)), toLlvmGlobalAddressSpace(nav.resolved.?.@"addrspace", zcu.getTarget()), ); gop.value_ptr.* = variable_index.ptrConst(&o.builder).global; @@ -3060,8 +3047,8 @@ pub const Object = struct { return o.builder.intType(o.zcu.errorSetBits()); } - pub fn lowerType(o: *Object, pt: Zcu.PerThread, t: Type) Allocator.Error!Builder.Type { - const zcu = pt.zcu; + pub fn lowerType(o: *Object, t: Type) Allocator.Error!Builder.Type { + const zcu = o.zcu; const target = zcu.getTarget(); const ip = &zcu.intern_pool; return switch (t.toIntern()) { @@ -3134,7 +3121,7 @@ pub const Object = struct { => .ptr, .slice_const_u8_type, .slice_const_u8_sentinel_0_type, - => try o.builder.structType(.normal, &.{ .ptr, try o.lowerType(pt, Type.usize) }), + => try o.builder.structType(.normal, &.{ .ptr, try o.lowerType(.usize) }), .optional_noreturn_type => unreachable, .anyerror_void_error_union_type, .adhoc_inferred_error_set_type, @@ -3175,24 +3162,24 @@ pub const Object = struct { .one, .many, .c => ptr_ty, .slice => try o.builder.structType(.normal, &.{ ptr_ty, - try o.lowerType(pt, Type.usize), + try o.lowerType(.usize), }), }; }, .array_type => |array_type| o.builder.arrayType( array_type.lenIncludingSentinel(), - try o.lowerType(pt, Type.fromInterned(array_type.child)), + try o.lowerType(.fromInterned(array_type.child)), ), .vector_type => |vector_type| o.builder.vectorType( .normal, vector_type.len, - try o.lowerType(pt, Type.fromInterned(vector_type.child)), + try o.lowerType(.fromInterned(vector_type.child)), ), .opt_type => |child_ty| { // Must stay in sync with `opt_payload` logic in `lowerPtr`. if (!Type.fromInterned(child_ty).hasRuntimeBits(zcu)) return .i8; - const payload_ty = try o.lowerType(pt, Type.fromInterned(child_ty)); + const payload_ty = try o.lowerType(.fromInterned(child_ty)); if (t.optionalReprIsPayload(zcu)) return payload_ty; comptime assert(optional_layout_version == 3); @@ -3214,7 +3201,7 @@ pub const Object = struct { const error_type = try o.errorIntType(); if (!Type.fromInterned(error_union_type.payload_type).hasRuntimeBits(zcu)) return error_type; - const payload_type = try o.lowerType(pt, Type.fromInterned(error_union_type.payload_type)); + const payload_type = try o.lowerType(.fromInterned(error_union_type.payload_type)); const payload_align = Type.fromInterned(error_union_type.payload_type).abiAlignment(zcu); const error_align: InternPool.Alignment = .fromByteUnits(std.zig.target.intAlignment(target, zcu.errorSetBits())); @@ -3254,7 +3241,7 @@ pub const Object = struct { const struct_type = ip.loadStructType(t.toIntern()); if (struct_type.layout == .@"packed") { - const int_ty = try o.lowerType(pt, .fromInterned(struct_type.packed_backing_int_type)); + const int_ty = try o.lowerType(.fromInterned(struct_type.packed_backing_int_type)); try o.type_map.put(o.gpa, t.toIntern(), int_ty); return int_ty; } @@ -3290,7 +3277,7 @@ pub const Object = struct { if (!field_ty.hasRuntimeBits(zcu)) continue; - try llvm_field_types.append(o.gpa, try o.lowerType(pt, field_ty)); + try llvm_field_types.append(o.gpa, try o.lowerType(field_ty)); offset += field_ty.abiSize(zcu); } @@ -3346,7 +3333,7 @@ pub const Object = struct { if (!Type.fromInterned(field_ty).hasRuntimeBits(zcu)) { continue; } - try llvm_field_types.append(o.gpa, try o.lowerType(pt, Type.fromInterned(field_ty))); + try llvm_field_types.append(o.gpa, try o.lowerType(.fromInterned(field_ty))); offset += Type.fromInterned(field_ty).abiSize(zcu); } @@ -3367,7 +3354,7 @@ pub const Object = struct { const union_obj = ip.loadUnionType(t.toIntern()); if (union_obj.layout == .@"packed") { - const int_ty = try o.lowerType(pt, .fromInterned(union_obj.packed_backing_int_type)); + const int_ty = try o.lowerType(.fromInterned(union_obj.packed_backing_int_type)); try o.type_map.put(o.gpa, t.toIntern(), int_ty); return int_ty; } @@ -3375,13 +3362,13 @@ pub const Object = struct { const layout = Type.getUnionLayout(union_obj, zcu); if (layout.payload_size == 0) { - const enum_tag_ty = try o.lowerType(pt, .fromInterned(union_obj.enum_tag_type)); + const enum_tag_ty = try o.lowerType(.fromInterned(union_obj.enum_tag_type)); try o.type_map.put(o.gpa, t.toIntern(), enum_tag_ty); return enum_tag_ty; } const aligned_field_ty = Type.fromInterned(union_obj.field_types.get(ip)[layout.most_aligned_field]); - const aligned_field_llvm_ty = try o.lowerType(pt, aligned_field_ty); + const aligned_field_llvm_ty = try o.lowerType(aligned_field_ty); const payload_ty = ty: { if (layout.most_aligned_field_size == layout.payload_size) { @@ -3407,7 +3394,7 @@ pub const Object = struct { ); return ty; } - const enum_tag_ty = try o.lowerType(pt, .fromInterned(union_obj.enum_tag_type)); + const enum_tag_ty = try o.lowerType(.fromInterned(union_obj.enum_tag_type)); // Put the tag before or after the payload depending on which one's // alignment is greater. @@ -3442,8 +3429,8 @@ pub const Object = struct { } return gop.value_ptr.*; }, - .enum_type => try o.lowerType(pt, t.intTagType(zcu)), - .func_type => |func_type| try o.lowerFnType(pt, func_type), + .enum_type => try o.lowerType(t.intTagType(zcu)), + .func_type => |func_type| try o.lowerFnType(func_type), .error_set_type, .inferred_error_set_type => try o.errorIntType(), // values, not types .undef, @@ -3469,11 +3456,11 @@ pub const Object = struct { }; } - fn lowerFnType(o: *Object, pt: Zcu.PerThread, fn_info: InternPool.Key.FuncType) Allocator.Error!Builder.Type { - const zcu = pt.zcu; + fn lowerFnType(o: *Object, fn_info: InternPool.Key.FuncType) Allocator.Error!Builder.Type { + const zcu = o.zcu; const ip = &zcu.intern_pool; const target = zcu.getTarget(); - const ret_ty = try lowerFnRetTy(o, pt, fn_info); + const ret_ty = try lowerFnRetTy(o, fn_info); var llvm_params: std.ArrayList(Builder.Type) = .empty; defer llvm_params.deinit(o.gpa); @@ -3488,12 +3475,12 @@ pub const Object = struct { try llvm_params.append(o.gpa, llvm_ptr_ty); } - var it = iterateParamTypes(o, pt, fn_info); + var it = iterateParamTypes(o, fn_info); while (try it.next()) |lowering| switch (lowering) { .no_bits => continue, .byval => { const param_ty = Type.fromInterned(fn_info.param_types.get(ip)[it.zig_index - 1]); - try llvm_params.append(o.gpa, try o.lowerType(pt, param_ty)); + try llvm_params.append(o.gpa, try o.lowerType(param_ty)); }, .byref, .byref_mut => { try llvm_params.append(o.gpa, .ptr); @@ -3508,7 +3495,7 @@ pub const Object = struct { const param_ty = Type.fromInterned(fn_info.param_types.get(ip)[it.zig_index - 1]); try llvm_params.appendSlice(o.gpa, &.{ try o.builder.ptrType(toLlvmAddressSpace(param_ty.ptrAddressSpace(zcu), target)), - try o.lowerType(pt, Type.usize), + try o.lowerType(.usize), }); }, .multiple_llvm_types => { @@ -3516,7 +3503,7 @@ pub const Object = struct { }, .float_array => |count| { const param_ty = Type.fromInterned(fn_info.param_types.get(ip)[it.zig_index - 1]); - const float_ty = try o.lowerType(pt, aarch64_c_abi.getFloatArrayType(param_ty, zcu).?); + const float_ty = try o.lowerType(aarch64_c_abi.getFloatArrayType(param_ty, zcu).?); try llvm_params.append(o.gpa, try o.builder.arrayType(count, float_ty)); }, .i32_array, .i64_array => |arr_len| { @@ -3535,8 +3522,8 @@ pub const Object = struct { ); } - pub fn lowerValue(o: *Object, pt: Zcu.PerThread, arg_val: InternPool.Index) Allocator.Error!Builder.Constant { - const zcu = pt.zcu; + pub fn lowerValue(o: *Object, arg_val: InternPool.Index) Allocator.Error!Builder.Constant { + const zcu = o.zcu; const ip = &zcu.intern_pool; const target = zcu.getTarget(); @@ -3544,7 +3531,7 @@ pub const Object = struct { const val_key = ip.indexToKey(val.toIntern()); if (val.isUndef(zcu)) { - return o.builder.undefConst(try o.lowerType(pt, Type.fromInterned(val_key.typeOf()))); + return o.builder.undefConst(try o.lowerType(.fromInterned(val_key.typeOf()))); } const ty: Type = .fromInterned(val_key.typeOf()); @@ -3580,45 +3567,45 @@ pub const Object = struct { }, .enum_literal => unreachable, // non-runtime value .@"extern" => |@"extern"| { - const function_index = try o.resolveLlvmFunction(pt, @"extern".owner_nav); + const function_index = try o.resolveLlvmFunction(@"extern".owner_nav); return function_index.ptrConst(&o.builder).global.toConst(); }, .func => |func| { - const function_index = try o.resolveLlvmFunction(pt, func.owner_nav); + const function_index = try o.resolveLlvmFunction(func.owner_nav); return function_index.ptrConst(&o.builder).global.toConst(); }, .int => { var bigint_space: Value.BigIntSpace = undefined; const bigint = val.toBigInt(&bigint_space, zcu); - return lowerBigInt(o, pt, ty, bigint); + const llvm_int_ty = try o.builder.intType(ty.intInfo(zcu).bits); + return o.builder.bigIntConst(llvm_int_ty, bigint); }, .err => |err| { - const int = try pt.getErrorValue(err.name); - const llvm_int = try o.builder.intConst(try o.errorIntType(), int); - return llvm_int; + const int = zcu.intern_pool.getErrorValueIfExists(err.name).?; + return o.builder.intConst(try o.errorIntType(), int); }, .error_union => |error_union| { - const err_val = switch (error_union.val) { - .err_name => |err_name| try pt.intern(.{ .err = .{ - .ty = ty.errorUnionSet(zcu).toIntern(), - .name = err_name, - } }), - .payload => (try pt.intValue(try pt.errorIntType(), 0)).toIntern(), + const llvm_error_ty = try o.errorIntType(); + const llvm_error_value = switch (error_union.val) { + .err_name => |name| try o.builder.intConst( + llvm_error_ty, + zcu.intern_pool.getErrorValueIfExists(name).?, + ), + .payload => try o.builder.intConst(llvm_error_ty, 0), }; - const err_int_ty = try pt.errorIntType(); + const payload_type = ty.errorUnionPayload(zcu); if (!payload_type.hasRuntimeBits(zcu)) { // We use the error type directly as the type. - return o.lowerValue(pt, err_val); + return llvm_error_value; } const payload_align = payload_type.abiAlignment(zcu); - const error_align = err_int_ty.abiAlignment(zcu); - const llvm_error_value = try o.lowerValue(pt, err_val); - const llvm_payload_value = try o.lowerValue(pt, switch (error_union.val) { - .err_name => try pt.intern(.{ .undef = payload_type.toIntern() }), - .payload => |payload| payload, - }); + const error_align = Type.errorAbiAlignment(zcu); + const llvm_payload_value = switch (error_union.val) { + .err_name => try o.builder.undefConst(try o.lowerType(payload_type)), + .payload => |payload| try o.lowerValue(payload), + }; var fields: [3]Builder.Type = undefined; var vals: [3]Builder.Constant = undefined; @@ -3632,7 +3619,7 @@ pub const Object = struct { fields[0] = vals[0].typeOf(&o.builder); fields[1] = vals[1].typeOf(&o.builder); - const llvm_ty = try o.lowerType(pt, ty); + const llvm_ty = try o.lowerType(ty); const llvm_ty_fields = llvm_ty.structFields(&o.builder); if (llvm_ty_fields.len > 2) { assert(llvm_ty_fields.len == 3); @@ -3644,7 +3631,7 @@ pub const Object = struct { fields[0..llvm_ty_fields.len], ), vals[0..llvm_ty_fields.len]); }, - .enum_tag => |enum_tag| o.lowerValue(pt, enum_tag.int), + .enum_tag => |enum_tag| o.lowerValue(enum_tag.int), .float => switch (ty.floatBits(target)) { 16 => if (backendSupportsF16(target)) try o.builder.halfConst(val.toFloat(f16, zcu)) @@ -3659,10 +3646,10 @@ pub const Object = struct { 128 => try o.builder.fp128Const(val.toFloat(f128, zcu)), else => unreachable, }, - .ptr => try o.lowerPtr(pt, arg_val, 0), - .slice => |slice| return o.builder.structConst(try o.lowerType(pt, ty), &.{ - try o.lowerValue(pt, slice.ptr), - try o.lowerValue(pt, slice.len), + .ptr => try o.lowerPtr(arg_val, 0), + .slice => |slice| return o.builder.structConst(try o.lowerType(ty), &.{ + try o.lowerValue(slice.ptr), + try o.lowerValue(slice.len), }), .opt => |opt| { comptime assert(optional_layout_version == 3); @@ -3672,7 +3659,7 @@ pub const Object = struct { if (!payload_ty.hasRuntimeBits(zcu)) { return non_null_bit; } - const llvm_ty = try o.lowerType(pt, ty); + const llvm_ty = try o.lowerType(ty); if (ty.optionalReprIsPayload(zcu)) return switch (opt.val) { .none => switch (llvm_ty.tag(&o.builder)) { .integer => try o.builder.intConst(llvm_ty, 0), @@ -3680,16 +3667,16 @@ pub const Object = struct { .structure => try o.builder.zeroInitConst(llvm_ty), else => unreachable, }, - else => |payload| try o.lowerValue(pt, payload), + else => |payload| try o.lowerValue(payload), }; assert(payload_ty.zigTypeTag(zcu) != .@"fn"); var fields: [3]Builder.Type = undefined; var vals: [3]Builder.Constant = undefined; - vals[0] = try o.lowerValue(pt, switch (opt.val) { - .none => try pt.intern(.{ .undef = payload_ty.toIntern() }), - else => |payload| payload, - }); + vals[0] = switch (opt.val) { + .none => try o.builder.undefConst(try o.lowerType(payload_ty)), + else => |payload| try o.lowerValue(payload), + }; vals[1] = non_null_bit; fields[0] = vals[0].typeOf(&o.builder); fields[1] = vals[1].typeOf(&o.builder); @@ -3705,14 +3692,14 @@ pub const Object = struct { fields[0..llvm_ty_fields.len], ), vals[0..llvm_ty_fields.len]); }, - .bitpack => |bitpack| return o.lowerValue(pt, bitpack.backing_int_val), + .bitpack => |bitpack| return o.lowerValue(bitpack.backing_int_val), .aggregate => |aggregate| switch (ip.indexToKey(ty.toIntern())) { .array_type => |array_type| switch (aggregate.storage) { .bytes => |bytes| try o.builder.stringConst(try o.builder.string( bytes.toSlice(array_type.lenIncludingSentinel(), ip), )), .elems => |elems| { - const array_ty = try o.lowerType(pt, ty); + const array_ty = try o.lowerType(ty); const elem_ty = array_ty.childType(&o.builder); assert(elems.len == array_ty.aggregateLen(&o.builder)); @@ -3732,7 +3719,7 @@ pub const Object = struct { var need_unnamed = false; for (vals, fields, elems) |*result_val, *result_field, elem| { - result_val.* = try o.lowerValue(pt, elem); + result_val.* = try o.lowerValue(elem); result_field.* = result_val.typeOf(&o.builder); if (result_field.* != elem_ty) need_unnamed = true; } @@ -3744,7 +3731,7 @@ pub const Object = struct { .repeated_elem => |elem| { const len: usize = @intCast(array_type.len); const len_including_sentinel: usize = @intCast(array_type.lenIncludingSentinel()); - const array_ty = try o.lowerType(pt, ty); + const array_ty = try o.lowerType(ty); const elem_ty = array_ty.childType(&o.builder); const ExpectedContents = extern struct { @@ -3762,12 +3749,12 @@ pub const Object = struct { defer allocator.free(fields); var need_unnamed = false; - @memset(vals[0..len], try o.lowerValue(pt, elem)); + @memset(vals[0..len], try o.lowerValue(elem)); @memset(fields[0..len], vals[0].typeOf(&o.builder)); if (fields[0] != elem_ty) need_unnamed = true; if (array_type.sentinel != .none) { - vals[len] = try o.lowerValue(pt, array_type.sentinel); + vals[len] = try o.lowerValue(array_type.sentinel); fields[len] = vals[len].typeOf(&o.builder); if (fields[len] != elem_ty) need_unnamed = true; } @@ -3779,7 +3766,7 @@ pub const Object = struct { }, }, .vector_type => |vector_type| { - const vector_ty = try o.lowerType(pt, ty); + const vector_ty = try o.lowerType(ty); switch (aggregate.storage) { .bytes, .elems => { const ExpectedContents = [Builder.expected_fields_len]Builder.Constant; @@ -3796,7 +3783,7 @@ pub const Object = struct { result_val.* = try o.builder.intConst(.i8, byte); }, .elems => |elems| for (vals, elems) |*result_val, elem| { - result_val.* = try o.lowerValue(pt, elem); + result_val.* = try o.lowerValue(elem); }, .repeated_elem => unreachable, } @@ -3804,12 +3791,12 @@ pub const Object = struct { }, .repeated_elem => |elem| return o.builder.splatConst( vector_ty, - try o.lowerValue(pt, elem), + try o.lowerValue(elem), ), } }, .tuple_type => |tuple| { - const struct_ty = try o.lowerType(pt, ty); + const struct_ty = try o.lowerType(ty); const llvm_len = struct_ty.aggregateLen(&o.builder); const ExpectedContents = extern struct { @@ -3835,8 +3822,8 @@ pub const Object = struct { tuple.types.get(ip), tuple.values.get(ip), 0.., - ) |field_ty, field_val, field_index| { - if (field_val != .none) continue; + ) |field_ty, field_comptime_val, field_index| { + if (field_comptime_val != .none) continue; if (!Type.fromInterned(field_ty).hasRuntimeBits(zcu)) continue; const field_align = Type.fromInterned(field_ty).abiAlignment(zcu); @@ -3854,8 +3841,11 @@ pub const Object = struct { llvm_index += 1; } - vals[llvm_index] = - try o.lowerValue(pt, (try val.fieldValue(pt, field_index)).toIntern()); + vals[llvm_index] = switch (aggregate.storage) { + .bytes => |bytes| try o.builder.intConst(.i8, bytes.at(field_index, ip)), + .elems => |elems| try o.lowerValue(elems[field_index]), + .repeated_elem => |elem| try o.lowerValue(elem), + }; fields[llvm_index] = vals[llvm_index].typeOf(&o.builder); if (fields[llvm_index] != struct_ty.structFields(&o.builder)[llvm_index]) need_unnamed = true; @@ -3883,7 +3873,7 @@ pub const Object = struct { }, .struct_type => { const struct_type = ip.loadStructType(ty.toIntern()); - const struct_ty = try o.lowerType(pt, ty); + const struct_ty = try o.lowerType(ty); assert(struct_type.layout != .@"packed"); const llvm_len = struct_ty.aggregateLen(&o.builder); @@ -3927,10 +3917,11 @@ pub const Object = struct { continue; } - vals[llvm_index] = try o.lowerValue( - pt, - (try val.fieldValue(pt, field_index)).toIntern(), - ); + vals[llvm_index] = switch (aggregate.storage) { + .bytes => |bytes| try o.builder.intConst(.i8, bytes.at(field_index, ip)), + .elems => |elems| try o.lowerValue(elems[field_index]), + .repeated_elem => |elem| try o.lowerValue(elem), + }; fields[llvm_index] = vals[llvm_index].typeOf(&o.builder); if (fields[llvm_index] != struct_ty.structFields(&o.builder)[llvm_index]) need_unnamed = true; @@ -3959,9 +3950,9 @@ pub const Object = struct { else => unreachable, }, .un => |un| { - const union_ty = try o.lowerType(pt, ty); + const union_ty = try o.lowerType(ty); const layout = ty.unionGetLayout(zcu); - if (layout.payload_size == 0) return o.lowerValue(pt, un.tag); + if (layout.payload_size == 0) return o.lowerValue(un.tag); const union_obj = zcu.typeToUnion(ty).?; const container_layout = union_obj.layout; @@ -3982,7 +3973,7 @@ pub const Object = struct { const padding_len = layout.payload_size; break :p try o.builder.undefConst(try o.builder.arrayType(padding_len, .i8)); } - const payload = try o.lowerValue(pt, un.val); + const payload = try o.lowerValue(un.val); const payload_ty = payload.typeOf(&o.builder); if (payload_ty != union_ty.structFields(&o.builder)[ @intFromBool(layout.tag_size > 0 and layout.tag_align.compare(.gte, layout.payload_align)) @@ -3997,7 +3988,7 @@ pub const Object = struct { ); } else p: { assert(layout.tag_size == 0); - const union_val = try o.lowerValue(pt, un.val); + const union_val = try o.lowerValue(un.val); need_unnamed = true; break :p union_val; }; @@ -4007,7 +3998,7 @@ pub const Object = struct { try o.builder.structType(union_ty.structKind(&o.builder), &.{payload_ty}) else union_ty, &.{payload}); - const tag = try o.lowerValue(pt, un.tag); + const tag = try o.lowerValue(un.tag); const tag_ty = tag.typeOf(&o.builder); var fields: [3]Builder.Type = undefined; var vals: [3]Builder.Constant = undefined; @@ -4033,52 +4024,45 @@ pub const Object = struct { }; } - fn lowerBigInt( - o: *Object, - pt: Zcu.PerThread, - ty: Type, - bigint: std.math.big.int.Const, - ) Allocator.Error!Builder.Constant { - const zcu = pt.zcu; - return o.builder.bigIntConst(try o.builder.intType(ty.intInfo(zcu).bits), bigint); - } - fn lowerPtr( o: *Object, - pt: Zcu.PerThread, ptr_val: InternPool.Index, prev_offset: u64, ) Allocator.Error!Builder.Constant { - const zcu = pt.zcu; + const zcu = o.zcu; const ptr = zcu.intern_pool.indexToKey(ptr_val).ptr; const offset: u64 = prev_offset + ptr.byte_offset; return switch (ptr.base_addr) { .nav => |nav| { - const base_ptr = try o.lowerNavRefValue(pt, nav); + const base_ptr = try o.lowerNavRefValue(nav); return o.builder.gepConst(.inbounds, .i8, base_ptr, null, &.{ try o.builder.intConst(.i64, offset), }); }, .uav => |uav| { - const base_ptr = try o.lowerUavRef(pt, uav); + const orig_ptr_ty: Type = .fromInterned(uav.orig_ty); + const base_ptr = try o.lowerUavRef( + uav.val, + orig_ptr_ty.ptrAlignment(zcu), + orig_ptr_ty.ptrAddressSpace(zcu), + ); return o.builder.gepConst(.inbounds, .i8, base_ptr, null, &.{ try o.builder.intConst(.i64, offset), }); }, .int => try o.builder.castConst( .inttoptr, - try o.builder.intConst(try o.lowerType(pt, Type.usize), offset), - try o.lowerType(pt, Type.fromInterned(ptr.ty)), + try o.builder.intConst(try o.lowerType(.usize), offset), + try o.lowerType(.fromInterned(ptr.ty)), ), .eu_payload => |eu_ptr| try o.lowerPtr( - pt, eu_ptr, offset + codegen.errUnionPayloadOffset( Value.fromInterned(eu_ptr).typeOf(zcu).childType(zcu), zcu, ), ), - .opt_payload => |opt_ptr| try o.lowerPtr(pt, opt_ptr, offset), + .opt_payload => |opt_ptr| try o.lowerPtr(opt_ptr, offset), .field => |field| { const agg_ty = Value.fromInterned(field.base).typeOf(zcu).childType(zcu); const field_off: u64 = switch (agg_ty.zigTypeTag(zcu)) { @@ -4096,13 +4080,13 @@ pub const Object = struct { }, else => unreachable, }; - return o.lowerPtr(pt, field.base, offset + field_off); + return o.lowerPtr(field.base, offset + field_off); }, .arr_elem => |arr_elem| { const base_ptr_ty = Value.fromInterned(arr_elem.base).typeOf(zcu); assert(base_ptr_ty.ptrSize(zcu) == .many); const elem_size = base_ptr_ty.childType(zcu).abiSize(zcu); - return o.lowerPtr(pt, arr_elem.base, offset + elem_size * arr_elem.index); + return o.lowerPtr(arr_elem.base, offset + elem_size * arr_elem.index); }, .comptime_field => unreachable, .comptime_alloc => unreachable, @@ -4113,88 +4097,84 @@ pub const Object = struct { /// Maybe the logic could be unified. pub fn lowerUavRef( o: *Object, - pt: Zcu.PerThread, - uav: InternPool.Key.Ptr.BaseAddr.Uav, + uav_val: InternPool.Index, + /// Must not be `.none`. + @"align": InternPool.Alignment, + @"addrspace": std.builtin.AddressSpace, ) Allocator.Error!Builder.Constant { - const zcu = pt.zcu; + assert(@"align" != .none); + + const zcu = o.zcu; const ip = &zcu.intern_pool; - const uav_val = uav.val; - const uav_ty = Type.fromInterned(ip.typeOf(uav_val)); - const target = zcu.getTarget(); + const uav_ty: Type = .fromInterned(ip.typeOf(uav_val)); switch (ip.indexToKey(uav_val)) { - .func => @panic("TODO"), - .@"extern" => @panic("TODO"), + .func => unreachable, // should be using a Nav ref + .@"extern" => unreachable, // should be using a Nav ref else => {}, } - const ptr_ty = Type.fromInterned(uav.orig_ty); - - if (!uav_ty.isRuntimeFnOrHasRuntimeBits(zcu)) { - return o.lowerPtrToVoid(pt, ptr_ty); + if (!uav_ty.hasRuntimeBits(zcu)) { + return o.lowerPtrToVoid(@"align", @"addrspace"); } - assert(uav_ty.zigTypeTag(zcu) != .@"fn"); // should be using a Nav ref + const llvm_addrspace = toLlvmAddressSpace(@"addrspace", zcu.getTarget()); + const llvm_global = (try o.resolveGlobalUav(uav_val, llvm_addrspace, @"align")).ptrConst(&o.builder).global; - const llvm_addr_space = toLlvmAddressSpace(ptr_ty.ptrAddressSpace(zcu), target); - const alignment = ptr_ty.ptrAlignment(zcu); - const llvm_global = (try o.resolveGlobalUav(pt, uav.val, llvm_addr_space, alignment)).ptrConst(&o.builder).global; - - const llvm_val = try o.builder.convConst( + return o.builder.convConst( llvm_global.toConst(), - try o.builder.ptrType(llvm_addr_space), + try o.builder.ptrType(llvm_addrspace), ); - - return o.builder.convConst(llvm_val, try o.lowerType(pt, ptr_ty)); } - pub fn lowerNavRefValue(o: *Object, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) Allocator.Error!Builder.Constant { - const zcu = pt.zcu; + pub fn lowerNavRefValue(o: *Object, nav_index: InternPool.Nav.Index) Allocator.Error!Builder.Constant { + const zcu = o.zcu; const ip = &zcu.intern_pool; const nav = ip.getNav(nav_index); const nav_ty: Type = .fromInterned(nav.resolved.?.type); - const ptr_ty = try pt.navPtrType(nav_index); if (nav.getExtern(ip) == null and !nav_ty.isRuntimeFnOrHasRuntimeBits(zcu)) { - return o.lowerPtrToVoid(pt, ptr_ty); + return o.lowerPtrToVoid(nav.resolved.?.@"align", nav.resolved.?.@"addrspace"); } const llvm_global = if (nav_ty.zigTypeTag(zcu) == .@"fn") - (try o.resolveLlvmFunction(pt, nav_index)).ptrConst(&o.builder).global + (try o.resolveLlvmFunction(nav_index)).ptrConst(&o.builder).global else - (try o.resolveGlobalNav(pt, nav_index)).ptrConst(&o.builder).global; + (try o.resolveGlobalNav(nav_index)).ptrConst(&o.builder).global; - const llvm_val = try o.builder.convConst( + return try o.builder.convConst( llvm_global.toConst(), try o.builder.ptrType(toLlvmAddressSpace(nav.resolved.?.@"addrspace", zcu.getTarget())), ); - - return o.builder.convConst(llvm_val, try o.lowerType(pt, ptr_ty)); } - pub fn lowerPtrToVoid(o: *Object, pt: Zcu.PerThread, ptr_ty: Type) Allocator.Error!Builder.Constant { - const zcu = pt.zcu; + pub fn lowerPtrToVoid( + o: *Object, + @"align": InternPool.Alignment, + @"addrspace": std.builtin.AddressSpace, + ) Allocator.Error!Builder.Constant { + const target = o.zcu.getTarget(); // Even though we are pointing at something which has zero bits (e.g. `void`), // Pointers are defined to have bits. So we must return something here. // The value cannot be undefined, because we use the `nonnull` annotation // for non-optional pointers. We also need to respect the alignment, even though // the address will never be dereferenced. - const int: u64 = ptr_ty.ptrInfo(zcu).flags.alignment.toByteUnits() orelse + const int: u64 = @"align".toByteUnits() orelse // Note that these 0xaa values are appropriate even in release-optimized builds // because we need a well-defined value that is not null, and LLVM does not // have an "undef_but_not_null" attribute. As an example, if this `alloc` AIR // instruction is followed by a `wrap_optional`, it will return this value // verbatim, and the result should test as non-null. - switch (zcu.getTarget().ptrBitWidth()) { + switch (target.ptrBitWidth()) { 16 => 0xaaaa, 32 => 0xaaaaaaaa, 64 => 0xaaaaaaaa_aaaaaaaa, else => unreachable, }; - const llvm_usize = try o.lowerType(pt, Type.usize); - const llvm_ptr_ty = try o.lowerType(pt, ptr_ty); + const llvm_usize = try o.lowerType(.usize); + const llvm_ptr_ty = try o.builder.ptrType(toLlvmAddressSpace(@"addrspace", target)); return o.builder.castConst(.inttoptr, try o.builder.intConst(llvm_usize, int), llvm_ptr_ty); } @@ -4207,7 +4187,7 @@ pub const Object = struct { fn_info: InternPool.Key.FuncType, llvm_arg_i: u32, ) Allocator.Error!void { - const zcu = pt.zcu; + const zcu = o.zcu; if (param_ty.isPtrAtRuntime(zcu)) { const ptr_info = param_ty.ptrInfo(zcu); if (std.math.cast(u5, param_index)) |i| { @@ -4226,7 +4206,7 @@ pub const Object = struct { .x86_64_interrupt, .x86_interrupt, => { - const child_type = try lowerType(o, pt, Type.fromInterned(ptr_info.child)); + const child_type = try lowerType(o, Type.fromInterned(ptr_info.child)); try attributes.addParamAttr(llvm_arg_i, .{ .byval = child_type }, &o.builder); }, } @@ -4292,8 +4272,8 @@ pub const Object = struct { } /// MLUGG TODO: this also needs incremental updates dumbass - pub fn getEnumTagNameFunction(o: *Object, pt: Zcu.PerThread, enum_ty: Type) !Builder.Function.Index { - const zcu = pt.zcu; + pub fn getEnumTagNameFunction(o: *Object, enum_ty: Type) !Builder.Function.Index { + const zcu = o.zcu; const ip = &zcu.intern_pool; const enum_type = ip.loadEnumType(enum_ty.toIntern()); @@ -4301,11 +4281,12 @@ pub const Object = struct { if (gop.found_existing) return gop.value_ptr.ptrConst(&o.builder).kind.function; errdefer assert(o.enum_tag_name_map.remove(enum_ty.toIntern())); - const usize_ty = try o.lowerType(pt, Type.usize); - const ret_ty = try o.lowerType(pt, Type.slice_const_u8_sentinel_0); + const usize_ty = try o.lowerType(.usize); + const ret_ty = try o.lowerType(.slice_const_u8_sentinel_0); + const llvm_int_ty = try o.lowerType(.fromInterned(enum_type.int_tag_type)); const target = &zcu.root_mod.resolved_target.result; const function_index = try o.builder.addFunction( - try o.builder.fnType(ret_ty, &.{try o.lowerType(pt, Type.fromInterned(enum_type.int_tag_type))}, .normal), + try o.builder.fnType(ret_ty, &.{llvm_int_ty}, .normal), try o.builder.strtabStringFmt("__zig_tag_name_{f}", .{enum_type.name.fmt(ip)}), toLlvmAddressSpace(.generic, target), ); @@ -4353,11 +4334,11 @@ pub const Object = struct { }); const return_block = try wip.block(1, "Name"); - const this_tag_int_value = try o.lowerValue( - pt, - (try pt.enumValueFieldIndex(enum_ty, @intCast(field_index))).toIntern(), - ); - try wip_switch.addCase(this_tag_int_value, return_block, &wip); + const llvm_tag_val = switch (enum_type.field_values.getOrNone(ip, field_index)) { + .none => try o.builder.intConst(llvm_int_ty, field_index), // auto-numbered + else => |tag_val_ip| try o.lowerValue(tag_val_ip), + }; + try wip_switch.addCase(llvm_tag_val, return_block, &wip); wip.cursor = .{ .block = return_block }; _ = try wip.ret(name_val); @@ -4375,8 +4356,8 @@ pub const Object = struct { return o.lazy_abi_aligns.items[@intFromEnum(index)]; } - pub fn getIsNamedEnumValueFunction(o: *Object, pt: Zcu.PerThread, enum_ty: Type) !Builder.Function.Index { - const zcu = pt.zcu; + pub fn getIsNamedEnumValueFunction(o: *Object, enum_ty: Type) !Builder.Function.Index { + const zcu = o.zcu; const ip = &zcu.intern_pool; const gop = try o.named_enum_map.getOrPut(o.gpa, enum_ty.toIntern()); @@ -4390,23 +4371,21 @@ pub const Object = struct { toLlvmAddressSpace(.generic, zcu.getTarget()), ); gop.value_ptr.* = function_index; - try o.updateIsNamedEnumValueFunction(pt, enum_ty, function_index); + try o.updateIsNamedEnumValueFunction(enum_ty, function_index); return function_index; } fn updateIsNamedEnumValueFunction( o: *Object, - pt: Zcu.PerThread, enum_ty: Type, function_index: Builder.Function.Index, ) Allocator.Error!void { - const zcu = pt.zcu; + const zcu = o.zcu; const builder = &o.builder; const loaded_enum = zcu.intern_pool.loadEnumType(enum_ty.toIntern()); - function_index.ptrConst(builder).global.ptr(builder).type = try builder.fnType( - .i1, - &.{try o.lowerType(pt, .fromInterned(loaded_enum.int_tag_type))}, - .normal, - ); + + const llvm_int_ty = try o.lowerType(.fromInterned(loaded_enum.int_tag_type)); + function_index.ptrConst(builder).global.ptr(builder).type = + try builder.fnType(.i1, &.{llvm_int_ty}, .normal); var attributes: Builder.FunctionAttributes.Wip = .{}; defer attributes.deinit(builder); @@ -4429,13 +4408,19 @@ pub const Object = struct { var wip_switch = try wip.@"switch"(tag_int_value, unnamed_block, @intCast(loaded_enum.field_names.len), .none); defer wip_switch.finish(&wip); - for (0..loaded_enum.field_names.len) |field_index| { - const this_tag_int_value = try o.lowerValue( - pt, - (try pt.enumValueFieldIndex(enum_ty, @intCast(field_index))).toIntern(), - ); - try wip_switch.addCase(this_tag_int_value, named_block, &wip); + if (loaded_enum.field_values.len > 0) { + for (loaded_enum.field_values.get(&zcu.intern_pool)) |tag_val_ip| { + const llvm_tag_val = try o.lowerValue(tag_val_ip); + try wip_switch.addCase(llvm_tag_val, named_block, &wip); + } + } else { + // Auto-numbered. + for (0..loaded_enum.field_names.len) |field_index| { + const llvm_tag_val = try o.builder.intConst(llvm_int_ty, field_index); + try wip_switch.addCase(llvm_tag_val, named_block, &wip); + } } + wip.cursor = .{ .block = named_block }; _ = try wip.ret(.true); diff --git a/src/codegen/llvm/FuncGen.zig b/src/codegen/llvm/FuncGen.zig index 4b1edf9ff9c1d8076c9c736f71ed73f1b69de636..ec8e0b1d0577dadd8a299bf0cb274be8723a76e9 100644 --- a/src/codegen/llvm/FuncGen.zig +++ b/src/codegen/llvm/FuncGen.zig @@ -73,7 +73,7 @@ const TodoError = Zcu.CodegenFailError; /// Avoid introducing new calls to this function---see documentation comment on `TodoError`. fn todo(fg: *FuncGen, comptime format: []const u8, args: anytype) TodoError { @branchHint(.cold); - return fg.pt.zcu.codegenFail( + return fg.object.zcu.codegenFail( fg.nav_index, "TODO (LLVM): " ++ format, args, @@ -81,7 +81,7 @@ fn todo(fg: *FuncGen, comptime format: []const u8, args: anytype) TodoError { } fn ownerModule(fg: *const FuncGen) *Package.Module { - return fg.pt.zcu.navFileScope(fg.nav_index).mod.?; + return fg.object.zcu.navFileScope(fg.nav_index).mod.?; } fn maybeMarkAllowZeroAccess(self: *FuncGen, info: InternPool.Key.PtrType) void { @@ -154,34 +154,35 @@ fn resolveInst(self: *FuncGen, inst: Air.Inst.Ref) Allocator.Error!Builder.Value const gop = try self.func_inst_table.getOrPut(gpa, inst); if (gop.found_existing) return gop.value_ptr.*; - const llvm_val = try self.resolveValue((try self.air.value(inst, self.pt)).?); + const llvm_val = try self.resolveValue(.fromInterned(inst.toInterned().?)); gop.value_ptr.* = llvm_val.toValue(); return llvm_val.toValue(); } fn resolveValue(self: *FuncGen, val: Value) Allocator.Error!Builder.Constant { const o = self.object; - const pt = self.pt; - const zcu = pt.zcu; + const zcu = o.zcu; const ty = val.typeOf(zcu); if (!isByRef(ty, zcu)) { - return o.lowerValue(pt, val.toIntern()); + return o.lowerValue(val.toIntern()); } else { // We need a pointer to a global constant, i.e. a UAV. - return o.lowerUavRef(pt, .{ - .val = val.toIntern(), - .orig_ty = (try pt.singleConstPtrType(ty)).toIntern(), - }); + return o.lowerUavRef( + val.toIntern(), + ty.abiAlignment(zcu), + target_util.defaultAddressSpace(zcu.getTarget(), .global_constant), + ); } } +/// MLUGG TODO okay yeah prolly delete this again fn lowerType(fg: *const FuncGen, ty: Type) Allocator.Error!Builder.Type { - return fg.object.lowerType(fg.pt, ty); + return fg.object.lowerType(ty); } pub fn genBody(self: *FuncGen, body: []const Air.Inst.Index, coverage_point: Air.CoveragePoint) TodoError!void { const o = self.object; - const zcu = self.pt.zcu; + const zcu = self.object.zcu; const ip = &zcu.intern_pool; const air_tags = self.air.instructions.items(.tag); switch (coverage_point) { @@ -514,8 +515,7 @@ fn genBodyDebugScope( defer self.scope = old_scope; if (maybe_inline_func) |inline_func| { - const pt = self.pt; - const zcu = pt.zcu; + const zcu = o.zcu; const ip = &zcu.intern_pool; const func = zcu.funcInfo(inline_func); @@ -529,18 +529,13 @@ fn genBodyDebugScope( const line_number = self.base_line + 1; self.inlined_at = try self.wip.debug_location.toMetadata(&o.builder); - const fn_ty = try pt.funcType(.{ - .param_types = &.{}, - .return_type = .void_type, - }); - self.scope = try o.builder.debugSubprogram( self.file, try o.builder.metadataString(nav.name.toSlice(&zcu.intern_pool)), try o.builder.metadataString(nav.fqn.toSlice(&zcu.intern_pool)), line_number, line_number + func.lbrace_line, - try o.getDebugType(pt, fn_ty), + try o.builder.debugSubroutineType(null), .{ .di_flags = .{ .StaticMember = true }, .sp_flags = .{ @@ -582,7 +577,7 @@ fn airCall(self: *FuncGen, inst: Air.Inst.Index, modifier: std.builtin.CallModif const args = air_call.args; const o = self.object; const pt = self.pt; - const zcu = pt.zcu; + const zcu = o.zcu; const ip = &zcu.intern_pool; const callee_ty = self.typeOf(air_call.callee); const zig_fn_ty = switch (callee_ty.zigTypeTag(zcu)) { @@ -628,7 +623,7 @@ fn airCall(self: *FuncGen, inst: Air.Inst.Index, modifier: std.builtin.CallModif try llvm_args.append(self.err_ret_trace); } - var it = iterateParamTypes(o, pt, fn_info); + var it = iterateParamTypes(o, fn_info); while (try it.nextCall(self, args)) |lowering| switch (lowering) { .no_bits => continue, .byval => { @@ -761,7 +756,7 @@ fn airCall(self: *FuncGen, inst: Air.Inst.Index, modifier: std.builtin.CallModif { // Add argument attributes. - it = iterateParamTypes(o, pt, fn_info); + it = iterateParamTypes(o, fn_info); it.llvm_index += @intFromBool(sret); it.llvm_index += @intFromBool(err_return_tracing); while (try it.next()) |lowering| switch (lowering) { @@ -852,7 +847,7 @@ fn airCall(self: *FuncGen, inst: Air.Inst.Index, modifier: std.builtin.CallModif } } - const abi_ret_ty = try lowerFnRetTy(o, pt, fn_info); + const abi_ret_ty = try lowerFnRetTy(o, fn_info); if (abi_ret_ty != llvm_ret_ty) { // In this case the function return type is honoring the calling convention by having @@ -881,12 +876,11 @@ fn airCall(self: *FuncGen, inst: Air.Inst.Index, modifier: std.builtin.CallModif fn buildSimplePanic(fg: *FuncGen, panic_id: Zcu.SimplePanicId) Allocator.Error!void { const o = fg.object; - const pt = fg.pt; - const zcu = pt.zcu; + const zcu = o.zcu; const target = zcu.getTarget(); const panic_func = zcu.funcInfo(zcu.builtin_decl_values.get(panic_id.toBuiltin())); const fn_info = zcu.typeToFunc(.fromInterned(panic_func.ty)).?; - const panic_global = try o.resolveLlvmFunction(pt, panic_func.owner_nav); + const panic_global = try o.resolveLlvmFunction(panic_func.owner_nav); const has_err_trace = zcu.comp.config.any_error_tracing and fn_info.cc == .auto; if (has_err_trace) assert(fg.err_ret_trace != .none); @@ -905,30 +899,19 @@ fn buildSimplePanic(fg: *FuncGen, panic_id: Zcu.SimplePanicId) Allocator.Error!v fn airRet(self: *FuncGen, inst: Air.Inst.Index, safety: bool) Allocator.Error!void { const o = self.object; - const pt = self.pt; - const zcu = pt.zcu; + const zcu = o.zcu; const ip = &zcu.intern_pool; const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op; const ret_ty = self.typeOf(un_op); if (self.ret_ptr != .none) { - const ptr_ty = try pt.singleMutPtrType(ret_ty); - const operand = try self.resolveInst(un_op); - const val_is_undef = if (try self.air.value(un_op, pt)) |val| val.isUndef(zcu) else false; - if (val_is_undef and safety) undef: { - const ptr_info = ptr_ty.ptrInfo(zcu); - const needs_bitmask = (ptr_info.packed_offset.host_size != 0); - if (needs_bitmask) { - // TODO: only some bits are to be undef, we cannot write with a simple memset. - // meanwhile, ignore the write rather than stomping over valid bits. - // https://github.com/ziglang/zig/issues/15337 - break :undef; - } + const val_is_undef = if (un_op.toInterned()) |i| Value.fromInterned(i).isUndef(zcu) else false; + if (val_is_undef and safety) { const len = try o.builder.intValue(try self.lowerType(.usize), ret_ty.abiSize(zcu)); _ = try self.wip.callMemSet( self.ret_ptr, - ptr_ty.ptrAlignment(zcu).toLlvm(), + ret_ty.abiAlignment(zcu).toLlvm(), try o.builder.intValue(.i8, 0xaa), len, .normal, @@ -951,7 +934,12 @@ fn airRet(self: *FuncGen, inst: Air.Inst.Index, safety: bool) Allocator.Error!vo return; } - try self.store(self.ret_ptr, ptr_ty, operand, .none); + try self.store( + self.ret_ptr, + .none, + operand, + ret_ty, + ); _ = try self.wip.retVoid(); return; } @@ -968,15 +956,15 @@ fn airRet(self: *FuncGen, inst: Air.Inst.Index, safety: bool) Allocator.Error!vo return; } - const abi_ret_ty = try lowerFnRetTy(o, pt, fn_info); + const abi_ret_ty = try lowerFnRetTy(o, fn_info); const operand = try self.resolveInst(un_op); - const val_is_undef = if (try self.air.value(un_op, pt)) |val| val.isUndef(zcu) else false; + const val_is_undef = if (un_op.toInterned()) |i| Value.fromInterned(i).isUndef(zcu) else false; const alignment = ret_ty.abiAlignment(zcu).toLlvm(); if (val_is_undef and safety) { const llvm_ret_ty = operand.typeOfWip(&self.wip); const rp = try self.buildAlloca(llvm_ret_ty, alignment); - const len = try o.builder.intValue(try self.lowerType(Type.usize), ret_ty.abiSize(zcu)); + const len = try o.builder.intValue(try self.lowerType(.usize), ret_ty.abiSize(zcu)); _ = try self.wip.callMemSet( rp, alignment, @@ -1014,8 +1002,7 @@ fn airRet(self: *FuncGen, inst: Air.Inst.Index, safety: bool) Allocator.Error!vo fn airRetLoad(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!void { const o = self.object; - const pt = self.pt; - const zcu = pt.zcu; + const zcu = o.zcu; const ip = &zcu.intern_pool; const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op; const ptr_ty = self.typeOf(un_op); @@ -1037,7 +1024,7 @@ fn airRetLoad(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!void { return; } const ptr = try self.resolveInst(un_op); - const abi_ret_ty = try lowerFnRetTy(o, pt, fn_info); + const abi_ret_ty = try lowerFnRetTy(o, fn_info); const alignment = ret_ty.abiAlignment(zcu).toLlvm(); _ = try self.wip.ret(try self.wip.load(.normal, abi_ret_ty, ptr, alignment, "")); return; @@ -1053,14 +1040,13 @@ fn airCVaArg(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value } fn airCVaCopy(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { - const pt = self.pt; - const zcu = pt.zcu; + const zcu = self.object.zcu; const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; const src_list = try self.resolveInst(ty_op.operand); const va_list_ty = ty_op.ty.toType(); const llvm_va_list_ty = try self.lowerType(va_list_ty); - const result_alignment = va_list_ty.abiAlignment(pt.zcu).toLlvm(); + const result_alignment = va_list_ty.abiAlignment(zcu).toLlvm(); const dest_list = try self.buildAlloca(llvm_va_list_ty, result_alignment); _ = try self.wip.callIntrinsic(.normal, .none, .va_copy, &.{dest_list.typeOfWip(&self.wip)}, &.{ dest_list, src_list }, ""); @@ -1079,12 +1065,11 @@ fn airCVaEnd(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value } fn airCVaStart(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { - const pt = self.pt; - const zcu = pt.zcu; + const zcu = self.object.zcu; const va_list_ty = self.typeOfIndex(inst); const llvm_va_list_ty = try self.lowerType(va_list_ty); - const result_alignment = va_list_ty.abiAlignment(pt.zcu).toLlvm(); + const result_alignment = va_list_ty.abiAlignment(zcu).toLlvm(); const dest_list = try self.buildAlloca(llvm_va_list_ty, result_alignment); _ = try self.wip.callIntrinsic(.normal, .none, .va_start, &.{dest_list.typeOfWip(&self.wip)}, &.{dest_list}, ""); @@ -1145,8 +1130,7 @@ fn cmp( rhs: Builder.Value, ) Allocator.Error!Builder.Value { const o = self.object; - const pt = self.pt; - const zcu = pt.zcu; + const zcu = o.zcu; const scalar_ty = operand_ty.scalarType(zcu); const int_ty = switch (scalar_ty.zigTypeTag(zcu)) { .@"enum" => scalar_ty.intTagType(zcu), @@ -1244,8 +1228,7 @@ fn lowerBlock( maybe_inline_func: ?InternPool.Index, body: []const Air.Inst.Index, ) TodoError!Builder.Value { - const pt = self.pt; - const zcu = pt.zcu; + const zcu = self.object.zcu; const inst_ty = self.typeOfIndex(inst); if (inst_ty.isNoReturn(zcu)) { @@ -1294,7 +1277,7 @@ fn lowerBlock( } fn airBr(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!void { - const zcu = self.pt.zcu; + const zcu = self.object.zcu; const branch = self.air.instructions.items(.data)[@intFromEnum(inst)].br; const block = self.blocks.get(branch.block_inst).?; @@ -1324,12 +1307,12 @@ fn lowerSwitchDispatch( dispatch_info: SwitchDispatchInfo, ) Allocator.Error!void { const o = self.object; - const pt = self.pt; - const zcu = pt.zcu; + const zcu = o.zcu; const cond_ty = self.typeOf(cond_ref); const switch_br = self.air.unwrapSwitch(switch_inst); - if (try self.air.value(cond_ref, pt)) |cond_val| { + if (cond_ref.toInterned()) |cond_ip_index| { + const cond_val: Value = .fromInterned(cond_ip_index); // Comptime-known dispatch. Iterate the cases to find the correct // one, and branch to the corresponding element of `case_blocks`. var it = switch_br.iterateCases(); @@ -1413,7 +1396,7 @@ fn lowerSwitchDispatch( // The switch prongs will correspond to our scalar cases. Ranges will // be handled by conditional branches in the `else` prong. - const llvm_usize = try self.lowerType(Type.usize); + const llvm_usize = try self.lowerType(.usize); const cond_int = if (cond.typeOfWip(&self.wip).isPointer(&o.builder)) try self.wip.cast(.ptrtoint, cond, llvm_usize, "") else @@ -1581,7 +1564,7 @@ fn airTry(self: *FuncGen, inst: Air.Inst.Index, err_cold: bool) TodoError!Builde } fn airTryPtr(self: *FuncGen, inst: Air.Inst.Index, err_cold: bool) TodoError!Builder.Value { - const zcu = self.pt.zcu; + const zcu = self.object.zcu; const unwrapped_try = self.air.unwrapTryPtr(inst); const err_union_ptr = try self.resolveInst(unwrapped_try.error_union_ptr); const body = unwrapped_try.else_body; @@ -1605,8 +1588,7 @@ fn lowerTry( err_cold: bool, ) TodoError!Builder.Value { const o = fg.object; - const pt = fg.pt; - const zcu = pt.zcu; + const zcu = o.zcu; const payload_ty = err_union_ty.errorUnionPayload(zcu); const payload_has_bits = payload_ty.hasRuntimeBits(zcu); const error_type = try o.errorIntType(); @@ -1667,8 +1649,7 @@ fn lowerTry( fn airSwitchBr(self: *FuncGen, inst: Air.Inst.Index, is_dispatch_loop: bool) TodoError!void { const o = self.object; - const pt = self.pt; - const zcu = pt.zcu; + const zcu = o.zcu; const switch_br = self.air.unwrapSwitch(inst); @@ -1773,8 +1754,8 @@ fn airSwitchBr(self: *FuncGen, inst: Air.Inst.Index, is_dispatch_loop: bool) Tod const table_includes_else = item_count != table_len; break :jmp_table .{ - .min = try o.lowerValue(pt, min.toIntern()), - .max = try o.lowerValue(pt, max.toIntern()), + .min = try o.lowerValue(min.toIntern()), + .max = try o.lowerValue(max.toIntern()), .in_bounds_hint = if (table_includes_else) .none else switch (switch_br.getElseHint()) { .none, .cold => .none, .unpredictable => .unpredictable, @@ -1883,7 +1864,7 @@ fn airSwitchBr(self: *FuncGen, inst: Air.Inst.Index, is_dispatch_loop: bool) Tod } fn switchCaseItemRange(self: *FuncGen, switch_br: Air.UnwrappedSwitch) ?[2]Value { - const zcu = self.pt.zcu; + const zcu = self.object.zcu; var it = switch_br.iterateCases(); var min: ?Value = null; var max: ?Value = null; @@ -1928,8 +1909,7 @@ fn airLoop(self: *FuncGen, inst: Air.Inst.Index) TodoError!void { fn airArrayToSlice(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { const o = self.object; - const pt = self.pt; - const zcu = pt.zcu; + const zcu = o.zcu; const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; const operand_ty = self.typeOf(ty_op.operand); const array_ty = operand_ty.childType(zcu); @@ -1942,8 +1922,7 @@ fn airArrayToSlice(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder fn airFloatFromInt(self: *FuncGen, inst: Air.Inst.Index) TodoError!Builder.Value { const o = self.object; - const pt = self.pt; - const zcu = pt.zcu; + const zcu = o.zcu; const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; const operand = try self.resolveInst(ty_op.operand); @@ -1964,7 +1943,7 @@ fn airFloatFromInt(self: *FuncGen, inst: Air.Inst.Index) TodoError!Builder.Value ); const rt_int_bits = compilerRtIntBits(@intCast(operand_scalar_ty.bitSize(zcu))) orelse { - return self.todo("float_from_int from '{f}' without intrinsics", .{operand_scalar_ty.fmt(pt)}); + return self.todo("float_from_int on {d} bit integer", .{operand_scalar_ty.bitSize(zcu)}); }; const rt_int_ty = try o.builder.intType(rt_int_bits); var extended = try self.wip.conv( @@ -2011,8 +1990,7 @@ fn airIntFromFloat( _ = fast; const o = self.object; - const pt = self.pt; - const zcu = pt.zcu; + const zcu = o.zcu; const target = zcu.getTarget(); const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; @@ -2035,7 +2013,7 @@ fn airIntFromFloat( } const rt_int_bits = compilerRtIntBits(@intCast(dest_scalar_ty.bitSize(zcu))) orelse { - return self.todo("int_from_float to '{f}' without intrinsics", .{dest_scalar_ty.fmt(pt)}); + return self.todo("int_from_float to {d} bit integer", .{dest_scalar_ty.bitSize(zcu)}); }; const ret_ty = try o.builder.intType(rt_int_bits); const libc_ret_ty = if (rt_int_bits == 128 and (target.os.tag == .windows and target.cpu.arch == .x86_64)) b: { @@ -2074,14 +2052,13 @@ fn airIntFromFloat( } fn sliceOrArrayPtr(fg: *FuncGen, ptr: Builder.Value, ty: Type) Allocator.Error!Builder.Value { - const zcu = fg.pt.zcu; + const zcu = fg.object.zcu; return if (ty.isSlice(zcu)) fg.wip.extractValue(ptr, &.{0}, "") else ptr; } fn sliceOrArrayLenInBytes(fg: *FuncGen, ptr: Builder.Value, ty: Type) Allocator.Error!Builder.Value { const o = fg.object; - const pt = fg.pt; - const zcu = pt.zcu; + const zcu = o.zcu; const llvm_usize = try fg.lowerType(.usize); switch (ty.ptrSize(zcu)) { .slice => { @@ -2109,15 +2086,14 @@ fn airSliceField(self: *FuncGen, inst: Air.Inst.Index, index: u32) Allocator.Err } fn airPtrSliceFieldPtr(self: *FuncGen, inst: Air.Inst.Index, index: u1) Allocator.Error!Builder.Value { - const zcu = self.pt.zcu; + const zcu = self.object.zcu; const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; const slice_ptr = try self.resolveInst(ty_op.operand); return self.ptraddConst(slice_ptr, index * Type.usize.abiSize(zcu)); } fn airSliceElemVal(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { - const pt = self.pt; - const zcu = pt.zcu; + const zcu = self.object.zcu; const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; const slice_ty = self.typeOf(bin_op.lhs); const slice = try self.resolveInst(bin_op.lhs); @@ -2138,8 +2114,7 @@ fn airSliceElemVal(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder } fn airSliceElemPtr(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { - const pt = self.pt; - const zcu = pt.zcu; + const zcu = self.object.zcu; const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data; const slice_ty = self.typeOf(bin_op.lhs); @@ -2151,8 +2126,7 @@ fn airSliceElemPtr(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder } fn airArrayElemVal(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { - const pt = self.pt; - const zcu = pt.zcu; + const zcu = self.object.zcu; const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; const array_ty = self.typeOf(bin_op.lhs); @@ -2174,28 +2148,25 @@ fn airArrayElemVal(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder } fn airPtrElemVal(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { - const pt = self.pt; - const zcu = pt.zcu; + const zcu = self.object.zcu; const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; const ptr_ty = self.typeOf(bin_op.lhs); const elem_ty = ptr_ty.indexableElem(zcu); const base_ptr = try self.resolveInst(bin_op.lhs); const rhs = try self.resolveInst(bin_op.rhs); - const ptr = try self.ptraddScaled(base_ptr, rhs, elem_ty.abiSize(zcu)); - if (isByRef(elem_ty, zcu)) { - self.maybeMarkAllowZeroAccess(ptr_ty.ptrInfo(zcu)); - const ptr_align = (ptr_ty.ptrAlignment(zcu).min(elem_ty.abiAlignment(zcu))).toLlvm(); - return self.loadByRef(ptr, elem_ty, ptr_align, if (ptr_ty.isVolatilePtr(zcu)) .@"volatile" else .normal); - } self.maybeMarkAllowZeroAccess(ptr_ty.ptrInfo(zcu)); - return self.load(ptr, ptr_ty); + return self.load( + try self.ptraddScaled(base_ptr, rhs, elem_ty.abiSize(zcu)), + elem_ty, + ptr_ty.ptrAlignment(zcu).min(elem_ty.abiAlignment(zcu)).toLlvm(), + if (ptr_ty.isVolatilePtr(zcu)) .@"volatile" else .normal, + ); } fn airPtrElemPtr(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { - const pt = self.pt; - const zcu = pt.zcu; + const zcu = self.object.zcu; const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data; const ptr_ty = self.typeOf(bin_op.lhs); @@ -2232,8 +2203,7 @@ fn airStructFieldPtrIndex( fn airStructFieldVal(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { const o = self.object; - const pt = self.pt; - const zcu = pt.zcu; + const zcu = o.zcu; const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; const struct_field = self.air.extraData(Air.StructField, ty_pl.payload).data; const struct_ty = self.typeOf(struct_field.struct_operand); @@ -2298,8 +2268,7 @@ fn airStructFieldVal(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Build fn airFieldParentPtr(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { const o = self.object; - const pt = self.pt; - const zcu = pt.zcu; + const zcu = o.zcu; const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; const extra = self.air.extraData(Air.FieldParentPtr, ty_pl.payload).data; @@ -2310,7 +2279,7 @@ fn airFieldParentPtr(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Build if (field_offset == 0) return field_ptr; const res_ty = try self.lowerType(ty_pl.ty.toType()); - const llvm_usize = try self.lowerType(Type.usize); + const llvm_usize = try self.lowerType(.usize); const field_ptr_int = try self.wip.cast(.ptrtoint, field_ptr, llvm_usize, ""); const base_ptr_int = try self.wip.bin( @@ -2358,7 +2327,7 @@ fn airDbgEmptyStmt(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder fn airDbgVarPtr(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { const o = self.object; const pt = self.pt; - const zcu = pt.zcu; + const zcu = o.zcu; const pl_op = self.air.instructions.items(.data)[@intFromEnum(inst)].pl_op; const operand = try self.resolveInst(pl_op.operand); const name: Air.NullTerminatedString = @enumFromInt(pl_op.payload); @@ -2415,7 +2384,7 @@ fn airDbgVarVal(self: *FuncGen, inst: Air.Inst.Index, is_arg: bool) Allocator.Er try o.getDebugType(pt, operand_ty), ); - const zcu = pt.zcu; + const zcu = o.zcu; const owner_mod = self.ownerModule(); if (isByRef(operand_ty, zcu)) { _ = try self.wip.callIntrinsic( @@ -2501,8 +2470,7 @@ fn airAssembly(self: *FuncGen, inst: Air.Inst.Index) TodoError!Builder.Value { // This stores whether we need to add an elementtype attribute and // if so, the element type itself. const llvm_param_attrs = try arena.alloc(Builder.Type, max_param_count); - const pt = self.pt; - const zcu = pt.zcu; + const zcu = o.zcu; const ip = &zcu.intern_pool; const target = zcu.getTarget(); @@ -2855,8 +2823,7 @@ fn airIsNonNull( cond: Builder.IntegerCondition, ) Allocator.Error!Builder.Value { const o = self.object; - const pt = self.pt; - const zcu = pt.zcu; + const zcu = o.zcu; const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op; const operand = try self.resolveInst(un_op); const operand_ty = self.typeOf(un_op); @@ -2905,8 +2872,7 @@ fn airIsErr( operand_is_ptr: bool, ) Allocator.Error!Builder.Value { const o = self.object; - const pt = self.pt; - const zcu = pt.zcu; + const zcu = o.zcu; const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op; const operand = try self.resolveInst(un_op); const operand_ty = self.typeOf(un_op); @@ -2959,8 +2925,7 @@ fn airOptionalPayloadPtrSet(self: *FuncGen, inst: Air.Inst.Index) Allocator.Erro comptime assert(optional_layout_version == 3); const o = self.object; - const pt = self.pt; - const zcu = pt.zcu; + const zcu = o.zcu; const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; const operand = try self.resolveInst(ty_op.operand); const optional_ptr_ty = self.typeOf(ty_op.operand); @@ -3001,8 +2966,7 @@ fn airOptionalPayloadPtrSet(self: *FuncGen, inst: Air.Inst.Index) Allocator.Erro } fn airOptionalPayload(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { - const pt = self.pt; - const zcu = pt.zcu; + const zcu = self.object.zcu; const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; const operand = try self.resolveInst(ty_op.operand); const optional_ty = self.typeOf(ty_op.operand); @@ -3018,8 +2982,7 @@ fn airOptionalPayload(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Buil } fn airErrUnionPayload(self: *FuncGen, inst: Air.Inst.Index, operand_is_ptr: bool) Allocator.Error!Builder.Value { - const pt = self.pt; - const zcu = pt.zcu; + const zcu = self.object.zcu; const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; const operand = try self.resolveInst(ty_op.operand); const operand_ty = self.typeOf(ty_op.operand); @@ -3050,8 +3013,7 @@ fn airErrUnionErr( operand_is_ptr: bool, ) Allocator.Error!Builder.Value { const o = self.object; - const pt = self.pt; - const zcu = pt.zcu; + const zcu = o.zcu; const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; const operand = try self.resolveInst(ty_op.operand); const operand_ty = self.typeOf(ty_op.operand); @@ -3093,8 +3055,7 @@ fn airErrUnionErr( fn airErrUnionPayloadPtrSet(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { const o = self.object; - const pt = self.pt; - const zcu = pt.zcu; + const zcu = o.zcu; const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; const operand = try self.resolveInst(ty_op.operand); const err_union_ptr_ty = self.typeOf(ty_op.operand); @@ -3133,8 +3094,7 @@ fn airSetErrReturnTrace(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Bu } fn airSaveErrReturnTraceIndex(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { - const pt = self.pt; - const zcu = pt.zcu; + const zcu = self.object.zcu; const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; const struct_ty = ty_pl.ty.toType(); @@ -3150,12 +3110,7 @@ fn airSaveErrReturnTraceIndex(self: *FuncGen, inst: Air.Inst.Index) Allocator.Er }; const field_ptr = try self.ptraddConst(self.err_ret_trace, field_offset); - - const field_ptr_ty = try pt.ptrType(.{ - .child = field_ty.toIntern(), - .flags = .{ .alignment = field_align }, - }); - return self.load(field_ptr, field_ptr_ty); + return self.load(field_ptr, field_ty, field_align.toLlvm(), .normal); } /// As an optimization, we want to avoid unnecessary copies of @@ -3183,8 +3138,7 @@ fn isNextRet( fn airWrapOptional(self: *FuncGen, body_tail: []const Air.Inst.Index) Allocator.Error!Builder.Value { const o = self.object; - const pt = self.pt; - const zcu = pt.zcu; + const zcu = o.zcu; const inst = body_tail[0]; const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; const payload_ty = self.typeOf(ty_op.operand); @@ -3205,8 +3159,12 @@ fn airWrapOptional(self: *FuncGen, body_tail: []const Air.Inst.Index) Allocator. }; const payload_ptr = optional_ptr; // payload always at offset 0 - const payload_ptr_ty = try pt.singleMutPtrType(payload_ty); - try self.store(payload_ptr, payload_ptr_ty, operand, .none); + try self.store( + payload_ptr, + .none, + operand, + payload_ty, + ); // Non-null bit immediately after payload (no padding because the bit has alignment 1). const non_null_ptr = try self.ptraddConst(optional_ptr, payload_ty.abiSize(zcu)); _ = try self.wip.store(.normal, non_null_bit, non_null_ptr, .default); @@ -3215,8 +3173,7 @@ fn airWrapOptional(self: *FuncGen, body_tail: []const Air.Inst.Index) Allocator. fn airWrapErrUnionPayload(self: *FuncGen, body_tail: []const Air.Inst.Index) Allocator.Error!Builder.Value { const o = self.object; - const pt = self.pt; - const zcu = pt.zcu; + const zcu = o.zcu; const inst = body_tail[0]; const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; const err_un_ty = self.typeOfIndex(inst); @@ -3230,23 +3187,26 @@ fn airWrapErrUnionPayload(self: *FuncGen, body_tail: []const Air.Inst.Index) All const result_ptr = if (self.isNextRet(body_tail)) self.ret_ptr else brk: { - const alignment = err_un_ty.abiAlignment(pt.zcu).toLlvm(); + const alignment = err_un_ty.abiAlignment(o.zcu).toLlvm(); const result_ptr = try self.buildAlloca(err_un_llvm_ty, alignment); break :brk result_ptr; }; const err_ptr = try self.ptraddConst(result_ptr, codegen.errUnionErrorOffset(payload_ty, zcu)); - const error_alignment = Type.anyerror.abiAlignment(pt.zcu).toLlvm(); + const error_alignment = Type.anyerror.abiAlignment(o.zcu).toLlvm(); _ = try self.wip.store(.normal, ok_err_code, err_ptr, error_alignment); const payload_ptr = try self.ptraddConst(result_ptr, codegen.errUnionPayloadOffset(payload_ty, zcu)); - const payload_ptr_ty = try pt.singleMutPtrType(payload_ty); - try self.store(payload_ptr, payload_ptr_ty, operand, .none); + try self.store( + payload_ptr, + .none, + operand, + payload_ty, + ); return result_ptr; } fn airWrapErrUnionErr(self: *FuncGen, body_tail: []const Air.Inst.Index) Allocator.Error!Builder.Value { - const pt = self.pt; - const zcu = pt.zcu; + const zcu = self.object.zcu; const inst = body_tail[0]; const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; const err_un_ty = self.typeOfIndex(inst); @@ -3268,10 +3228,8 @@ fn airWrapErrUnionErr(self: *FuncGen, body_tail: []const Air.Inst.Index) Allocat const error_alignment = Type.anyerror.abiAlignment(zcu).toLlvm(); _ = try self.wip.store(.normal, operand, err_ptr, error_alignment); const payload_ptr = try self.ptraddConst(result_ptr, codegen.errUnionPayloadOffset(payload_ty, zcu)); - const payload_ptr_ty = try pt.singleMutPtrType(payload_ty); // TODO store undef to payload_ptr _ = payload_ptr; - _ = payload_ptr_ty; return result_ptr; } @@ -3279,7 +3237,7 @@ fn airWasmMemorySize(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Build const o = self.object; const pl_op = self.air.instructions.items(.data)[@intFromEnum(inst)].pl_op; const index = pl_op.payload; - const llvm_usize = try self.lowerType(Type.usize); + const llvm_usize = try self.lowerType(.usize); return self.wip.callIntrinsic(.normal, .none, .@"wasm.memory.size", &.{llvm_usize}, &.{ try o.builder.intValue(.i32, index), }, ""); @@ -3289,7 +3247,7 @@ fn airWasmMemoryGrow(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Build const o = self.object; const pl_op = self.air.instructions.items(.data)[@intFromEnum(inst)].pl_op; const index = pl_op.payload; - const llvm_isize = try self.lowerType(Type.isize); + const llvm_isize = try self.lowerType(.isize); return self.wip.callIntrinsic(.normal, .none, .@"wasm.memory.grow", &.{llvm_isize}, &.{ try o.builder.intValue(.i32, index), try self.resolveInst(pl_op.operand), }, ""); @@ -3297,15 +3255,13 @@ fn airWasmMemoryGrow(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Build fn airRuntimeNavPtr(fg: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { const o = fg.object; - const pt = fg.pt; const ty_nav = fg.air.instructions.items(.data)[@intFromEnum(inst)].ty_nav; - const llvm_ptr_const = try o.lowerNavRefValue(pt, ty_nav.nav); + const llvm_ptr_const = try o.lowerNavRefValue(ty_nav.nav); return llvm_ptr_const.toValue(); } fn airMin(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { - const pt = self.pt; - const zcu = pt.zcu; + const zcu = self.object.zcu; const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; const lhs = try self.resolveInst(bin_op.lhs); const rhs = try self.resolveInst(bin_op.rhs); @@ -3324,8 +3280,7 @@ fn airMin(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { } fn airMax(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { - const pt = self.pt; - const zcu = pt.zcu; + const zcu = self.object.zcu; const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; const lhs = try self.resolveInst(bin_op.lhs); const rhs = try self.resolveInst(bin_op.rhs); @@ -3353,7 +3308,7 @@ fn airSlice(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value } fn airAdd(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) Allocator.Error!Builder.Value { - const zcu = self.pt.zcu; + const zcu = self.object.zcu; const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; const lhs = try self.resolveInst(bin_op.lhs); const rhs = try self.resolveInst(bin_op.rhs); @@ -3371,8 +3326,7 @@ fn airSafeArithmetic( unsigned_intrinsic: Builder.Intrinsic, ) Allocator.Error!Builder.Value { const o = fg.object; - const pt = fg.pt; - const zcu = pt.zcu; + const zcu = o.zcu; const bin_op = fg.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; const lhs = try fg.resolveInst(bin_op.lhs); @@ -3419,8 +3373,7 @@ fn airAddWrap(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Valu } fn airAddSat(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { - const pt = self.pt; - const zcu = pt.zcu; + const zcu = self.object.zcu; const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; const lhs = try self.resolveInst(bin_op.lhs); const rhs = try self.resolveInst(bin_op.rhs); @@ -3438,7 +3391,7 @@ fn airAddSat(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value } fn airSub(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) Allocator.Error!Builder.Value { - const zcu = self.pt.zcu; + const zcu = self.object.zcu; const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; const lhs = try self.resolveInst(bin_op.lhs); const rhs = try self.resolveInst(bin_op.rhs); @@ -3458,8 +3411,7 @@ fn airSubWrap(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Valu } fn airSubSat(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { - const pt = self.pt; - const zcu = pt.zcu; + const zcu = self.object.zcu; const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; const lhs = try self.resolveInst(bin_op.lhs); const rhs = try self.resolveInst(bin_op.rhs); @@ -3477,7 +3429,7 @@ fn airSubSat(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value } fn airMul(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) Allocator.Error!Builder.Value { - const zcu = self.pt.zcu; + const zcu = self.object.zcu; const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; const lhs = try self.resolveInst(bin_op.lhs); const rhs = try self.resolveInst(bin_op.rhs); @@ -3497,8 +3449,7 @@ fn airMulWrap(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Valu } fn airMulSat(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { - const pt = self.pt; - const zcu = pt.zcu; + const zcu = self.object.zcu; const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; const lhs = try self.resolveInst(bin_op.lhs); const rhs = try self.resolveInst(bin_op.rhs); @@ -3525,7 +3476,7 @@ fn airDivFloat(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) } fn airDivTrunc(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) Allocator.Error!Builder.Value { - const zcu = self.pt.zcu; + const zcu = self.object.zcu; const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; const lhs = try self.resolveInst(bin_op.lhs); const rhs = try self.resolveInst(bin_op.rhs); @@ -3541,8 +3492,7 @@ fn airDivTrunc(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) fn airDivFloor(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) Allocator.Error!Builder.Value { const o = self.object; - const pt = self.pt; - const zcu = pt.zcu; + const zcu = o.zcu; const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; const lhs = try self.resolveInst(bin_op.lhs); const rhs = try self.resolveInst(bin_op.rhs); @@ -3591,7 +3541,7 @@ fn airDivFloor(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) } fn airDivExact(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) Allocator.Error!Builder.Value { - const zcu = self.pt.zcu; + const zcu = self.object.zcu; const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; const lhs = try self.resolveInst(bin_op.lhs); const rhs = try self.resolveInst(bin_op.rhs); @@ -3608,7 +3558,7 @@ fn airDivExact(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) } fn airRem(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) Allocator.Error!Builder.Value { - const zcu = self.pt.zcu; + const zcu = self.object.zcu; const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; const lhs = try self.resolveInst(bin_op.lhs); const rhs = try self.resolveInst(bin_op.rhs); @@ -3625,8 +3575,7 @@ fn airRem(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) Allo fn airMod(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) Allocator.Error!Builder.Value { const o = self.object; - const pt = self.pt; - const zcu = pt.zcu; + const zcu = o.zcu; const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; const lhs = try self.resolveInst(bin_op.lhs); const rhs = try self.resolveInst(bin_op.rhs); @@ -3678,7 +3627,7 @@ fn airMod(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) Allo } fn airPtrAdd(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { - const zcu = self.pt.zcu; + const zcu = self.object.zcu; const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data; const ptr_or_slice = try self.resolveInst(bin_op.lhs); @@ -3694,8 +3643,7 @@ fn airPtrAdd(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value fn airPtrSub(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { const o = self.object; - const pt = self.pt; - const zcu = pt.zcu; + const zcu = o.zcu; const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data; const ptr_or_slice = try self.resolveInst(bin_op.lhs); @@ -3718,8 +3666,7 @@ fn airOverflow( signed_intrinsic: Builder.Intrinsic, unsigned_intrinsic: Builder.Intrinsic, ) Allocator.Error!Builder.Value { - const pt = self.pt; - const zcu = pt.zcu; + const zcu = self.object.zcu; const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; const extra = self.air.extraData(Air.Bin, ty_pl.payload).data; @@ -3801,8 +3748,7 @@ fn buildFloatCmp( params: [2]Builder.Value, ) Allocator.Error!Builder.Value { const o = self.object; - const pt = self.pt; - const zcu = pt.zcu; + const zcu = o.zcu; const target = zcu.getTarget(); const scalar_ty = ty.scalarType(zcu); const scalar_llvm_ty = try self.lowerType(scalar_ty); @@ -3908,8 +3854,7 @@ fn buildFloatOp( params: [params_len]Builder.Value, ) Allocator.Error!Builder.Value { const o = self.object; - const pt = self.pt; - const zcu = pt.zcu; + const zcu = o.zcu; const target = zcu.getTarget(); const scalar_ty = ty.scalarType(zcu); const llvm_ty = try self.lowerType(ty); @@ -4049,8 +3994,7 @@ fn airMulAdd(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value } fn airShlWithOverflow(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { - const pt = self.pt; - const zcu = pt.zcu; + const zcu = self.object.zcu; const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; const extra = self.air.extraData(Air.Bin, ty_pl.payload).data; @@ -4120,8 +4064,7 @@ fn airXor(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { } fn airShlExact(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { - const pt = self.pt; - const zcu = pt.zcu; + const zcu = self.object.zcu; const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; const lhs = try self.resolveInst(bin_op.lhs); @@ -4143,8 +4086,7 @@ fn airShlExact(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Val } fn airShl(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { - const pt = self.pt; - const zcu = pt.zcu; + const zcu = self.object.zcu; const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; const lhs = try self.resolveInst(bin_op.lhs); @@ -4162,8 +4104,7 @@ fn airShl(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { fn airShlSat(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { const o = self.object; - const pt = self.pt; - const zcu = pt.zcu; + const zcu = o.zcu; const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; const lhs = try self.resolveInst(bin_op.lhs); @@ -4244,8 +4185,7 @@ fn airShlSat(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value } fn airShr(self: *FuncGen, inst: Air.Inst.Index, is_exact: bool) Allocator.Error!Builder.Value { - const pt = self.pt; - const zcu = pt.zcu; + const zcu = self.object.zcu; const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; const lhs = try self.resolveInst(bin_op.lhs); @@ -4269,8 +4209,7 @@ fn airShr(self: *FuncGen, inst: Air.Inst.Index, is_exact: bool) Allocator.Error! fn airAbs(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { const o = self.object; - const pt = self.pt; - const zcu = pt.zcu; + const zcu = o.zcu; const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; const operand = try self.resolveInst(ty_op.operand); const operand_ty = self.typeOf(ty_op.operand); @@ -4292,8 +4231,7 @@ fn airAbs(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { fn airIntCast(fg: *FuncGen, inst: Air.Inst.Index, safety: bool) Allocator.Error!Builder.Value { const o = fg.object; - const pt = fg.pt; - const zcu = pt.zcu; + const zcu = o.zcu; const ty_op = fg.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; const dest_ty = fg.typeOfIndex(inst); const dest_llvm_ty = try fg.lowerType(dest_ty); @@ -4379,7 +4317,7 @@ fn airIntCast(fg: *FuncGen, inst: Air.Inst.Index, safety: bool) Allocator.Error! }, operand, dest_llvm_ty, ""); if (safety and dest_is_enum and !dest_ty.isNonexhaustiveEnum(zcu)) { - const llvm_fn = try o.getIsNamedEnumValueFunction(pt, dest_ty); + const llvm_fn = try o.getIsNamedEnumValueFunction(dest_ty); const is_valid_enum_val = try fg.wip.call( .normal, .fastcc, @@ -4409,8 +4347,7 @@ fn airTrunc(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value fn airFptrunc(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { const o = self.object; - const pt = self.pt; - const zcu = pt.zcu; + const zcu = o.zcu; const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; const operand = try self.resolveInst(ty_op.operand); const operand_ty = self.typeOf(ty_op.operand); @@ -4444,8 +4381,7 @@ fn airFptrunc(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Valu fn airFpext(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { const o = self.object; - const pt = self.pt; - const zcu = pt.zcu; + const zcu = o.zcu; const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; const operand = try self.resolveInst(ty_op.operand); const operand_ty = self.typeOf(ty_op.operand); @@ -4493,8 +4429,7 @@ fn airBitCast(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Valu fn bitCast(self: *FuncGen, operand: Builder.Value, operand_ty: Type, inst_ty: Type) Allocator.Error!Builder.Value { const o = self.object; - const pt = self.pt; - const zcu = pt.zcu; + const zcu = o.zcu; const operand_is_ref = isByRef(operand_ty, zcu); const result_is_ref = isByRef(inst_ty, zcu); const llvm_dest_ty = try self.lowerType(inst_ty); @@ -4599,7 +4534,7 @@ fn bitCast(self: *FuncGen, operand: Builder.Value, operand_ty: Type, inst_ty: Ty fn airArg(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { const o = self.object; const pt = self.pt; - const zcu = pt.zcu; + const zcu = o.zcu; const arg_val = self.args[self.arg_index]; self.arg_index += 1; @@ -4688,13 +4623,13 @@ fn airArg(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { fn airAlloc(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { const o = self.object; - const pt = self.pt; - const zcu = pt.zcu; + const zcu = o.zcu; const ptr_ty = self.typeOfIndex(inst); const pointee_type = ptr_ty.childType(zcu); - if (!pointee_type.hasRuntimeBits(zcu)) - return (try o.lowerPtrToVoid(pt, ptr_ty)).toValue(); - + if (!pointee_type.hasRuntimeBits(zcu)) { + const ptr_info = ptr_ty.ptrInfo(zcu); + return (try o.lowerPtrToVoid(ptr_info.flags.alignment, ptr_info.flags.address_space)).toValue(); + } const pointee_llvm_ty = try self.lowerType(pointee_type); const alignment = ptr_ty.ptrAlignment(zcu).toLlvm(); return self.buildAlloca(pointee_llvm_ty, alignment); @@ -4702,12 +4637,13 @@ fn airAlloc(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value fn airRetPtr(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { const o = self.object; - const pt = self.pt; - const zcu = pt.zcu; + const zcu = o.zcu; const ptr_ty = self.typeOfIndex(inst); const ret_ty = ptr_ty.childType(zcu); - if (!ret_ty.hasRuntimeBits(zcu)) - return (try o.lowerPtrToVoid(pt, ptr_ty)).toValue(); + if (!ret_ty.hasRuntimeBits(zcu)) { + const ptr_info = ptr_ty.ptrInfo(zcu); + return (try o.lowerPtrToVoid(ptr_info.flags.alignment, ptr_info.flags.address_space)).toValue(); + } if (self.ret_ptr != .none) return self.ret_ptr; const ret_llvm_ty = try self.lowerType(ret_ty); const alignment = ptr_ty.ptrAlignment(zcu).toLlvm(); @@ -4721,20 +4657,19 @@ fn buildAlloca( llvm_ty: Builder.Type, alignment: Builder.Alignment, ) Allocator.Error!Builder.Value { - const target = self.pt.zcu.getTarget(); + const target = self.object.zcu.getTarget(); return buildAllocaInner(&self.wip, llvm_ty, alignment, target); } fn airStore(self: *FuncGen, inst: Air.Inst.Index, safety: bool) Allocator.Error!Builder.Value { const o = self.object; - const pt = self.pt; - const zcu = pt.zcu; + const zcu = o.zcu; const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; const dest_ptr = try self.resolveInst(bin_op.lhs); const ptr_ty = self.typeOf(bin_op.lhs); const operand_ty = ptr_ty.childType(zcu); - const val_is_undef = if (try self.air.value(bin_op.rhs, pt)) |val| val.isUndef(zcu) else false; + const val_is_undef = if (bin_op.rhs.toInterned()) |i| Value.fromInterned(i).isUndef(zcu) else false; if (val_is_undef) { const owner_mod = self.ownerModule(); @@ -4762,7 +4697,7 @@ fn airStore(self: *FuncGen, inst: Air.Inst.Index, safety: bool) Allocator.Error! self.maybeMarkAllowZeroAccess(ptr_info); - const len = try o.builder.intValue(try self.lowerType(Type.usize), operand_ty.abiSize(zcu)); + const len = try o.builder.intValue(try self.lowerType(.usize), operand_ty.abiSize(zcu)); _ = try self.wip.callMemSet( dest_ptr, ptr_ty.ptrAlignment(zcu).toLlvm(), @@ -4780,24 +4715,75 @@ fn airStore(self: *FuncGen, inst: Air.Inst.Index, safety: bool) Allocator.Error! self.maybeMarkAllowZeroAccess(ptr_ty.ptrInfo(zcu)); const src_operand = try self.resolveInst(bin_op.rhs); - try self.store(dest_ptr, ptr_ty, src_operand, .none); + try self.storeFull(dest_ptr, ptr_ty, src_operand, .none); return .none; } fn airLoad(fg: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { - const pt = fg.pt; - const zcu = pt.zcu; + const o = fg.object; + const zcu = o.zcu; const ty_op = fg.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; const ptr_ty = fg.typeOf(ty_op.operand); const ptr_info = ptr_ty.ptrInfo(zcu); const ptr = try fg.resolveInst(ty_op.operand); + const elem_ty = ptr_ty.childType(zcu); + const llvm_ptr_align = ptr_ty.ptrAlignment(zcu).toLlvm(); + fg.maybeMarkAllowZeroAccess(ptr_info); - return fg.load(ptr, ptr_ty); + + const access_kind: Builder.MemoryAccessKind = + if (ptr_info.flags.is_volatile) .@"volatile" else .normal; + + if (ptr_info.flags.vector_index != .none) { + const index_u32 = try o.builder.intValue(.i32, ptr_info.flags.vector_index); + const vec_elem_ty = try fg.lowerType(elem_ty); + const vec_ty = try o.builder.vectorType(.normal, ptr_info.packed_offset.host_size, vec_elem_ty); + + const loaded_vector = try fg.wip.load(access_kind, vec_ty, ptr, llvm_ptr_align, ""); + return fg.wip.extractElement(loaded_vector, index_u32, ""); + } + + if (ptr_info.packed_offset.host_size == 0) { + return fg.load(ptr, elem_ty, llvm_ptr_align, access_kind); + } + + const containing_int_ty = try o.builder.intType(@intCast(ptr_info.packed_offset.host_size * 8)); + const containing_int = + try fg.wip.load(access_kind, containing_int_ty, ptr, llvm_ptr_align, ""); + + const elem_bits = ptr_ty.childType(zcu).bitSize(zcu); + const shift_amt = try o.builder.intValue(containing_int_ty, ptr_info.packed_offset.bit_offset); + const shifted_value = try fg.wip.bin(.lshr, containing_int, shift_amt, ""); + const elem_llvm_ty = try fg.lowerType(elem_ty); + + if (isByRef(elem_ty, zcu)) { + const result_align = elem_ty.abiAlignment(zcu).toLlvm(); + const result_ptr = try fg.buildAlloca(elem_llvm_ty, result_align); + + const same_size_int = try o.builder.intType(@intCast(elem_bits)); + const truncated_int = try fg.wip.cast(.trunc, shifted_value, same_size_int, ""); + _ = try fg.wip.store(.normal, truncated_int, result_ptr, result_align); + return result_ptr; + } + + if (elem_ty.zigTypeTag(zcu) == .float or elem_ty.zigTypeTag(zcu) == .vector) { + const same_size_int = try o.builder.intType(@intCast(elem_bits)); + const truncated_int = try fg.wip.cast(.trunc, shifted_value, same_size_int, ""); + return fg.wip.cast(.bitcast, truncated_int, elem_llvm_ty, ""); + } + + if (elem_ty.isPtrAtRuntime(zcu)) { + const same_size_int = try o.builder.intType(@intCast(elem_bits)); + const truncated_int = try fg.wip.cast(.trunc, shifted_value, same_size_int, ""); + return fg.wip.cast(.inttoptr, truncated_int, elem_llvm_ty, ""); + } + + return fg.wip.cast(.trunc, shifted_value, elem_llvm_ty, ""); } fn airTrap(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!void { _ = inst; - const target = self.pt.zcu.getTarget(); + const target = self.object.zcu.getTarget(); if ((target.cpu.arch == .mips or target.cpu.arch == .mipsel) and target.cpu.has(.mips, .notraps)) { @@ -4828,8 +4814,8 @@ fn airBreakpoint(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.V fn airRetAddr(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { _ = inst; const o = self.object; - const llvm_usize = try self.lowerType(Type.usize); - if (!target_util.supportsReturnAddress(self.pt.zcu.getTarget(), self.ownerModule().optimize_mode)) { + const llvm_usize = try self.lowerType(.usize); + if (!target_util.supportsReturnAddress(self.object.zcu.getTarget(), self.ownerModule().optimize_mode)) { // https://github.com/ziglang/zig/issues/11946 return o.builder.intValue(llvm_usize, 0); } @@ -4840,7 +4826,7 @@ fn airRetAddr(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Valu fn airFrameAddress(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { _ = inst; const result = try self.wip.callIntrinsic(.normal, .none, .frameaddress, &.{.ptr}, &.{.@"0"}, ""); - return self.wip.cast(.ptrtoint, result, try self.lowerType(Type.usize), ""); + return self.wip.cast(.ptrtoint, result, try self.lowerType(.usize), ""); } fn airCmpxchg( @@ -4849,8 +4835,7 @@ fn airCmpxchg( kind: Builder.Function.Instruction.CmpXchg.Kind, ) Allocator.Error!Builder.Value { const o = self.object; - const pt = self.pt; - const zcu = pt.zcu; + const zcu = o.zcu; const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; const extra = self.air.extraData(Air.Cmpxchg, ty_pl.payload).data; const ptr = try self.resolveInst(extra.ptr); @@ -4915,8 +4900,7 @@ fn airCmpxchg( fn airAtomicRmw(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { const o = self.object; - const pt = self.pt; - const zcu = pt.zcu; + const zcu = o.zcu; const pl_op = self.air.instructions.items(.data)[@intFromEnum(inst)].pl_op; const extra = self.air.extraData(Air.AtomicRmw, pl_op.payload).data; const ptr = try self.resolveInst(pl_op.operand); @@ -4971,7 +4955,7 @@ fn airAtomicRmw(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Va access_kind, op, ptr, - try self.wip.cast(.ptrtoint, operand, try self.lowerType(Type.usize), ""), + try self.wip.cast(.ptrtoint, operand, try self.lowerType(.usize), ""), self.sync_scope, ordering, ptr_alignment, @@ -4980,8 +4964,7 @@ fn airAtomicRmw(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Va } fn airAtomicLoad(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { - const pt = self.pt; - const zcu = pt.zcu; + const zcu = self.object.zcu; const atomic_load = self.air.instructions.items(.data)[@intFromEnum(inst)].atomic_load; const ptr = try self.resolveInst(atomic_load.ptr); const ptr_ty = self.typeOf(atomic_load.ptr); @@ -5029,8 +5012,7 @@ fn airAtomicStore( inst: Air.Inst.Index, ordering: Builder.AtomicOrdering, ) Allocator.Error!Builder.Value { - const pt = self.pt; - const zcu = pt.zcu; + const zcu = self.object.zcu; const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; const ptr_ty = self.typeOf(bin_op.lhs); const operand_ty = ptr_ty.childType(zcu); @@ -5051,14 +5033,13 @@ fn airAtomicStore( self.maybeMarkAllowZeroAccess(ptr_ty.ptrInfo(zcu)); - try self.store(ptr, ptr_ty, element, ordering); + try self.storeFull(ptr, ptr_ty, element, ordering); return .none; } fn airMemset(self: *FuncGen, inst: Air.Inst.Index, safety: bool) Allocator.Error!Builder.Value { const o = self.object; - const pt = self.pt; - const zcu = pt.zcu; + const zcu = o.zcu; const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; const dest_slice = try self.resolveInst(bin_op.lhs); const ptr_ty = self.typeOf(bin_op.lhs); @@ -5070,7 +5051,8 @@ fn airMemset(self: *FuncGen, inst: Air.Inst.Index, safety: bool) Allocator.Error self.maybeMarkAllowZeroAccess(ptr_ty.ptrInfo(zcu)); - if (try self.air.value(bin_op.rhs, pt)) |elem_val| { + if (bin_op.rhs.toInterned()) |elem_ip_index| { + const elem_val: Value = .fromInterned(elem_ip_index); if (elem_val.isUndef(zcu)) { // Even if safety is disabled, we still emit a memset to undefined since it conveys // extra information to LLVM. However, safety makes the difference between using @@ -5099,7 +5081,7 @@ fn airMemset(self: *FuncGen, inst: Air.Inst.Index, safety: bool) Allocator.Error // repeating byte pattern, for example, `@as(u64, 0)` has a // repeating byte pattern of 0 bytes. In such case, the memset // intrinsic can be used. - if (try elem_val.hasRepeatedByteRepr(pt)) |byte_val| { + if (try elem_val.hasRepeatedByteRepr(zcu)) |byte_val| { const fill_byte = try o.builder.intValue(.i8, byte_val); const len = try self.sliceOrArrayLenInBytes(dest_slice, ptr_ty); _ = try self.wip.callMemSet( @@ -5154,7 +5136,7 @@ fn airMemset(self: *FuncGen, inst: Air.Inst.Index, safety: bool) Allocator.Error const body_block = try self.wip.block(1, "InlineMemsetBody"); const end_block = try self.wip.block(1, "InlineMemsetEnd"); - const llvm_usize_ty = try self.lowerType(Type.usize); + const llvm_usize_ty = try self.lowerType(.usize); const end_ptr = switch (ptr_ty.ptrSize(zcu)) { .slice => try self.ptraddScaled( dest_ptr, @@ -5194,8 +5176,7 @@ fn airMemset(self: *FuncGen, inst: Air.Inst.Index, safety: bool) Allocator.Error } fn airMemcpy(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { - const pt = self.pt; - const zcu = pt.zcu; + const zcu = self.object.zcu; const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; const dest_slice = try self.resolveInst(bin_op.lhs); const dest_ptr_ty = self.typeOf(bin_op.lhs); @@ -5223,8 +5204,7 @@ fn airMemcpy(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value } fn airMemmove(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { - const pt = self.pt; - const zcu = pt.zcu; + const zcu = self.object.zcu; const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; const dest_slice = try self.resolveInst(bin_op.lhs); const dest_ptr_ty = self.typeOf(bin_op.lhs); @@ -5248,8 +5228,7 @@ fn airMemmove(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Valu } fn airSetUnionTag(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { - const pt = self.pt; - const zcu = pt.zcu; + const zcu = self.object.zcu; const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; const un_ptr_ty = self.typeOf(bin_op.lhs); const un_ty = un_ptr_ty.childType(zcu); @@ -5280,8 +5259,7 @@ fn airSetUnionTag(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder. fn airGetUnionTag(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { const o = self.object; - const pt = self.pt; - const zcu = pt.zcu; + const zcu = o.zcu; const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; const un_ty = self.typeOf(ty_op.operand); const layout = un_ty.unionGetLayout(zcu); @@ -5354,8 +5332,7 @@ fn airBitOp(self: *FuncGen, inst: Air.Inst.Index, intrinsic: Builder.Intrinsic) fn airByteSwap(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { const o = self.object; - const pt = self.pt; - const zcu = pt.zcu; + const zcu = o.zcu; const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; const operand_ty = self.typeOf(ty_op.operand); var bits = operand_ty.intInfo(zcu).bits; @@ -5389,8 +5366,7 @@ fn airByteSwap(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Val fn airErrorSetHasValue(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { const o = self.object; - const pt = self.pt; - const zcu = pt.zcu; + const zcu = o.zcu; const ip = &zcu.intern_pool; const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; const operand = try self.resolveInst(ty_op.operand); @@ -5426,7 +5402,7 @@ fn airIsNamedEnumValue(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Bui const operand = try self.resolveInst(un_op); const enum_ty = self.typeOf(un_op); - const llvm_fn = try o.getIsNamedEnumValueFunction(self.pt, enum_ty); + const llvm_fn = try o.getIsNamedEnumValueFunction(enum_ty); return self.wip.call( .normal, .fastcc, @@ -5440,12 +5416,11 @@ fn airIsNamedEnumValue(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Bui fn airTagName(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { const o = self.object; - const pt = self.pt; const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op; const operand = try self.resolveInst(un_op); const enum_ty = self.typeOf(un_op); - const llvm_fn = try o.getEnumTagNameFunction(pt, enum_ty); + const llvm_fn = try o.getEnumTagNameFunction(enum_ty); return self.wip.call( .normal, .fastcc, @@ -5459,8 +5434,7 @@ fn airTagName(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Valu fn airErrorName(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { const o = self.object; - const pt = self.pt; - const zcu = pt.zcu; + const zcu = o.zcu; const un_op = self.air.instructions.items(.data)[@intFromEnum(inst)].un_op; const operand = try self.resolveInst(un_op); const slice_ty = self.typeOfIndex(inst); @@ -5493,8 +5467,7 @@ fn airSelect(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value fn airShuffleOne(fg: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { const o = fg.object; - const pt = fg.pt; - const zcu = pt.zcu; + const zcu = o.zcu; const gpa = zcu.gpa; const unwrapped = fg.air.unwrapShuffleOne(zcu, inst); @@ -5534,7 +5507,7 @@ fn airShuffleOne(fg: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Val .elem => llvm_poison_elem, .value => |val| if (!Value.fromInterned(val).isUndef(zcu)) elem: { any_defined_comptime_value = true; - break :elem try o.lowerValue(pt, val); + break :elem try o.lowerValue(val); } else llvm_poison_elem, }; } @@ -5600,8 +5573,7 @@ fn airShuffleOne(fg: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Val fn airShuffleTwo(fg: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { const o = fg.object; - const pt = fg.pt; - const zcu = pt.zcu; + const zcu = o.zcu; const gpa = zcu.gpa; const unwrapped = fg.air.unwrapShuffleTwo(zcu, inst); @@ -5699,7 +5671,7 @@ fn buildReducedCall( accum_init: Builder.Value, ) Allocator.Error!Builder.Value { const o = self.object; - const usize_ty = try self.lowerType(Type.usize); + const usize_ty = try self.lowerType(.usize); const llvm_vector_len = try o.builder.intValue(usize_ty, vector_len); const llvm_result_ty = accum_init.typeOfWip(&self.wip); @@ -5753,8 +5725,7 @@ fn buildReducedCall( fn airReduce(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) Allocator.Error!Builder.Value { const o = self.object; - const pt = self.pt; - const zcu = pt.zcu; + const zcu = o.zcu; const target = zcu.getTarget(); const reduce = self.air.instructions.items(.data)[@intFromEnum(inst)].reduce; @@ -5863,8 +5834,7 @@ fn airReduce(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) A fn airAggregateInit(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { const o = self.object; - const pt = self.pt; - const zcu = pt.zcu; + const zcu = o.zcu; const ip = &zcu.intern_pool; const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; const result_ty = self.typeOfIndex(inst); @@ -5960,19 +5930,18 @@ fn airAggregateInit(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builde const alloca_inst = try self.buildAlloca(llvm_result_ty, alignment); const array_info = result_ty.arrayInfo(zcu); - const elem_ptr_ty = try pt.singleConstPtrType(array_info.elem_type); const elem_size = array_info.elem_type.abiSize(zcu); for (elements, 0..) |elem, i| { const elem_ptr = try self.ptraddConst(alloca_inst, elem_size * i); const llvm_elem = try self.resolveInst(elem); - try self.store(elem_ptr, elem_ptr_ty, llvm_elem, .none); + try self.store(elem_ptr, .none, llvm_elem, array_info.elem_type); } if (array_info.sentinel) |sent_val| { const elem_ptr = try self.ptraddConst(alloca_inst, elem_size * array_info.len); const llvm_elem = try self.resolveValue(sent_val); - try self.store(elem_ptr, elem_ptr_ty, llvm_elem.toValue(), .none); + try self.store(elem_ptr, .none, llvm_elem.toValue(), array_info.elem_type); } return alloca_inst; @@ -5983,8 +5952,7 @@ fn airAggregateInit(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builde fn airUnionInit(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { const o = self.object; - const pt = self.pt; - const zcu = pt.zcu; + const zcu = o.zcu; const ip = &zcu.intern_pool; const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; const extra = self.air.extraData(Air.UnionInit, ty_pl.payload).data; @@ -6006,18 +5974,19 @@ fn airUnionInit(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Va assert(field_ty.hasRuntimeBits(zcu)); { - const payload_ptr_ty = try pt.ptrType(.{ - .child = field_ty.toIntern(), - .flags = .{ .alignment = layout.payload_align }, - }); const payload_ptr = try self.ptraddConst(result_ptr, layout.payloadOffset()); - try self.store(payload_ptr, payload_ptr_ty, llvm_payload, .none); + try self.store(payload_ptr, layout.payload_align, llvm_payload, field_ty); } if (layout.tag_size != 0) { - const tag_ty: Type = .fromInterned(union_obj.enum_tag_type); - const tag_val = try pt.enumValueFieldIndex(tag_ty, extra.field_index); - const llvm_tag_val = try o.lowerValue(pt, tag_val.toIntern()); + const loaded_enum = ip.loadEnumType(union_obj.enum_tag_type); + const llvm_tag_val = switch (loaded_enum.field_values.getOrNone(ip, extra.field_index)) { + .none => try o.builder.intConst( + try o.lowerType(.fromInterned(union_obj.enum_tag_type)), + extra.field_index, // auto-numbered + ), + else => |tag_val_ip| try o.lowerValue(tag_val_ip), + }; const tag_ptr = try self.ptraddConst(result_ptr, layout.tagOffset()); _ = try self.wip.store(.normal, llvm_tag_val.toValue(), tag_ptr, layout.tag_align.toLlvm()); } @@ -6043,7 +6012,7 @@ fn airPrefetch(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Val // by the target. // To work around this, don't emit llvm.prefetch in this case. // See https://bugs.llvm.org/show_bug.cgi?id=21037 - const zcu = self.pt.zcu; + const zcu = self.object.zcu; const target = zcu.getTarget(); switch (prefetch.cache) { .instruction => switch (target.cpu.arch) { @@ -6097,7 +6066,7 @@ fn workIntrinsic( } fn airWorkItemId(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { - const target = self.pt.zcu.getTarget(); + const target = self.object.zcu.getTarget(); const pl_op = self.air.instructions.items(.data)[@intFromEnum(inst)].pl_op; const dimension = pl_op.payload; @@ -6110,8 +6079,7 @@ fn airWorkItemId(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.V } fn airWorkGroupSize(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { - const pt = self.pt; - const target = pt.zcu.getTarget(); + const target = self.object.zcu.getTarget(); const pl_op = self.air.instructions.items(.data)[@intFromEnum(inst)].pl_op; const dimension = pl_op.payload; @@ -6138,7 +6106,7 @@ fn airWorkGroupSize(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builde } fn airWorkGroupId(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { - const target = self.pt.zcu.getTarget(); + const target = self.object.zcu.getTarget(); const pl_op = self.air.instructions.items(.data)[@intFromEnum(inst)].pl_op; const dimension = pl_op.payload; @@ -6158,7 +6126,7 @@ fn optCmpNull( opt_ptr: Builder.Value, access_kind: Builder.MemoryAccessKind, ) Allocator.Error!Builder.Value { - const zcu = self.pt.zcu; + const zcu = self.object.zcu; assert(isByRef(opt_ty, zcu)); comptime assert(optional_layout_version == 3); // Non-null bit is always after the payload, with no padding because it has alignment 1. @@ -6174,8 +6142,7 @@ fn optPayloadHandle( opt_ty: Type, can_elide_load: bool, ) Allocator.Error!Builder.Value { - const pt = fg.pt; - const zcu = pt.zcu; + const zcu = fg.object.zcu; assert(isByRef(opt_ty, zcu)); const payload_ty = opt_ty.optionalChild(zcu); @@ -6197,8 +6164,7 @@ fn fieldPtr( aggregate_ptr_ty: Type, field_index: u32, ) Allocator.Error!Builder.Value { - const pt = self.pt; - const zcu = pt.zcu; + const zcu = self.object.zcu; const aggregate_ty = aggregate_ptr_ty.childType(zcu); if (aggregate_ty.containerLayout(zcu) == .@"packed") { // A pointer to a bitpack field is equivalent to a pointer to the whole bitpack; the @@ -6226,8 +6192,7 @@ fn loadTruncate( // => so load the byte aligned value and trunc the unwanted bits. const o = fg.object; - const pt = fg.pt; - const zcu = pt.zcu; + const zcu = o.zcu; const payload_llvm_ty = try fg.lowerType(payload_ty); const abi_size = payload_ty.abiSize(zcu); @@ -6256,12 +6221,11 @@ fn loadByRef( access_kind: Builder.MemoryAccessKind, ) Allocator.Error!Builder.Value { const o = fg.object; - const pt = fg.pt; const pointee_llvm_ty = try fg.lowerType(pointee_type); const result_align = InternPool.Alignment.fromLlvm(ptr_alignment) - .max(pointee_type.abiAlignment(pt.zcu)).toLlvm(); + .max(pointee_type.abiAlignment(o.zcu)).toLlvm(); const result_ptr = try fg.buildAlloca(pointee_llvm_ty, result_align); - const size_bytes = pointee_type.abiSize(pt.zcu); + const size_bytes = pointee_type.abiSize(o.zcu); _ = try fg.wip.callMemCpy( result_ptr, result_align, @@ -6274,76 +6238,24 @@ fn loadByRef( return result_ptr; } -/// This function always performs a copy. For isByRef=true types, it creates a new -/// alloca and copies the value into it, then returns the alloca instruction. -/// For isByRef=false types, it creates a load instruction and returns it. -fn load(self: *FuncGen, ptr: Builder.Value, ptr_ty: Type) Allocator.Error!Builder.Value { - const o = self.object; - const pt = self.pt; - const zcu = pt.zcu; - const info = ptr_ty.ptrInfo(zcu); - const elem_ty = Type.fromInterned(info.child); - if (!elem_ty.hasRuntimeBits(zcu)) return .none; - - const ptr_alignment = (if (info.flags.alignment != .none) - @as(InternPool.Alignment, info.flags.alignment) - else - elem_ty.abiAlignment(zcu)).toLlvm(); - - const access_kind: Builder.MemoryAccessKind = - if (info.flags.is_volatile) .@"volatile" else .normal; - - if (info.flags.vector_index != .none) { - const index_u32 = try o.builder.intValue(.i32, info.flags.vector_index); - const vec_elem_ty = try self.lowerType(elem_ty); - const vec_ty = try o.builder.vectorType(.normal, info.packed_offset.host_size, vec_elem_ty); - - const loaded_vector = try self.wip.load(access_kind, vec_ty, ptr, ptr_alignment, ""); - return self.wip.extractElement(loaded_vector, index_u32, ""); - } - - if (info.packed_offset.host_size == 0) { - if (isByRef(elem_ty, zcu)) { - return self.loadByRef(ptr, elem_ty, ptr_alignment, access_kind); - } - return self.loadTruncate(access_kind, elem_ty, ptr, ptr_alignment); - } - - const containing_int_ty = try o.builder.intType(@intCast(info.packed_offset.host_size * 8)); - const containing_int = - try self.wip.load(access_kind, containing_int_ty, ptr, ptr_alignment, ""); - - const elem_bits = ptr_ty.childType(zcu).bitSize(zcu); - const shift_amt = try o.builder.intValue(containing_int_ty, info.packed_offset.bit_offset); - const shifted_value = try self.wip.bin(.lshr, containing_int, shift_amt, ""); - const elem_llvm_ty = try self.lowerType(elem_ty); - +/// If `isByRef` returns `true` for `elem_ty`, this still performs a copy by memcpy'ing the value +/// into a new alloca. +fn load( + fg: *FuncGen, + ptr: Builder.Value, + elem_ty: Type, + ptr_alignment: Builder.Alignment, + access_kind: Builder.MemoryAccessKind, +) Allocator.Error!Builder.Value { + const zcu = fg.object.zcu; if (isByRef(elem_ty, zcu)) { - const result_align = elem_ty.abiAlignment(zcu).toLlvm(); - const result_ptr = try self.buildAlloca(elem_llvm_ty, result_align); - - const same_size_int = try o.builder.intType(@intCast(elem_bits)); - const truncated_int = try self.wip.cast(.trunc, shifted_value, same_size_int, ""); - _ = try self.wip.store(.normal, truncated_int, result_ptr, result_align); - return result_ptr; + return fg.loadByRef(ptr, elem_ty, ptr_alignment, access_kind); + } else { + return fg.loadTruncate(access_kind, elem_ty, ptr, ptr_alignment); } - - if (elem_ty.zigTypeTag(zcu) == .float or elem_ty.zigTypeTag(zcu) == .vector) { - const same_size_int = try o.builder.intType(@intCast(elem_bits)); - const truncated_int = try self.wip.cast(.trunc, shifted_value, same_size_int, ""); - return self.wip.cast(.bitcast, truncated_int, elem_llvm_ty, ""); - } - - if (elem_ty.isPtrAtRuntime(zcu)) { - const same_size_int = try o.builder.intType(@intCast(elem_bits)); - const truncated_int = try self.wip.cast(.trunc, shifted_value, same_size_int, ""); - return self.wip.cast(.inttoptr, truncated_int, elem_llvm_ty, ""); - } - - return self.wip.cast(.trunc, shifted_value, elem_llvm_ty, ""); } -fn store( +fn storeFull( self: *FuncGen, ptr: Builder.Value, ptr_ty: Type, @@ -6351,8 +6263,7 @@ fn store( ordering: Builder.AtomicOrdering, ) Allocator.Error!void { const o = self.object; - const pt = self.pt; - const zcu = pt.zcu; + const zcu = o.zcu; const info = ptr_ty.ptrInfo(zcu); const elem_ty = Type.fromInterned(info.child); if (!elem_ty.hasRuntimeBits(zcu)) { @@ -6433,12 +6344,51 @@ fn store( ptr_alignment, elem, elem_ty.abiAlignment(zcu).toLlvm(), - try o.builder.intValue(try self.lowerType(Type.usize), elem_ty.abiSize(zcu)), + try o.builder.intValue(try self.lowerType(.usize), elem_ty.abiSize(zcu)), access_kind, self.disable_intrinsics, ); } +/// Non-atomic, non-volatile, non-packed store. +fn store( + fg: *FuncGen, + ptr: Builder.Value, + ptr_align: InternPool.Alignment, + elem: Builder.Value, + elem_ty: Type, +) Allocator.Error!void { + const o = fg.object; + const zcu = o.zcu; + const llvm_ptr_align = switch (ptr_align) { + .none => elem_ty.abiAlignment(zcu).toLlvm(), + else => ptr_align.toLlvm(), + }; + if (isByRef(elem_ty, zcu)) { + _ = try fg.wip.callMemCpy( + ptr, + llvm_ptr_align, + elem, + elem_ty.abiAlignment(zcu).toLlvm(), + try o.builder.intValue( + try fg.lowerType(.usize), + elem_ty.abiSize(zcu), + ), + .normal, + fg.disable_intrinsics, + ); + } else { + _ = try fg.wip.storeAtomic( + .normal, + elem, + ptr, + fg.sync_scope, + .none, + llvm_ptr_align, + ); + } +} + fn valgrindMarkUndef(fg: *FuncGen, ptr: Builder.Value, len: Builder.Value) Allocator.Error!void { const VG_USERREQ__MAKE_MEM_UNDEFINED = 1296236545; const o = fg.object; @@ -6460,8 +6410,7 @@ fn valgrindClientRequest( a5: Builder.Value, ) Allocator.Error!Builder.Value { const o = fg.object; - const pt = fg.pt; - const zcu = pt.zcu; + const zcu = o.zcu; const target = zcu.getTarget(); if (!target_util.hasValgrindSupport(target, .stage2_llvm)) return default_value; @@ -6588,18 +6537,17 @@ fn valgrindClientRequest( } fn typeOf(fg: *FuncGen, inst: Air.Inst.Ref) Type { - const zcu = fg.pt.zcu; + const zcu = fg.object.zcu; return fg.air.typeOf(inst, &zcu.intern_pool); } fn typeOfIndex(fg: *FuncGen, inst: Air.Inst.Index) Type { - const zcu = fg.pt.zcu; + const zcu = fg.object.zcu; return fg.air.typeOfIndex(inst, &zcu.intern_pool); } const ParamTypeIterator = struct { object: *Object, - pt: Zcu.PerThread, fn_info: InternPool.Key.FuncType, zig_index: u32, llvm_index: u32, @@ -6622,7 +6570,7 @@ const ParamTypeIterator = struct { pub fn next(it: *ParamTypeIterator) Allocator.Error!?Lowering { if (it.zig_index >= it.fn_info.param_types.len) return null; - const ip = &it.pt.zcu.intern_pool; + const ip = &it.object.zcu.intern_pool; const ty = it.fn_info.param_types.get(ip)[it.zig_index]; it.byval_attr = false; return nextInner(it, Type.fromInterned(ty)); @@ -6630,8 +6578,7 @@ const ParamTypeIterator = struct { /// `airCall` uses this instead of `next` so that it can take into account variadic functions. fn nextCall(it: *ParamTypeIterator, fg: *FuncGen, args: []const Air.Inst.Ref) Allocator.Error!?Lowering { - assert(std.meta.eql(it.pt, fg.pt)); - const ip = &it.pt.zcu.intern_pool; + const ip = &it.object.zcu.intern_pool; if (it.zig_index >= it.fn_info.param_types.len) { if (it.zig_index >= args.len) { return null; @@ -6644,8 +6591,7 @@ const ParamTypeIterator = struct { } fn nextInner(it: *ParamTypeIterator, ty: Type) Allocator.Error!?Lowering { - const pt = it.pt; - const zcu = pt.zcu; + const zcu = it.object.zcu; const target = zcu.getTarget(); if (!ty.hasRuntimeBits(zcu)) { @@ -6744,7 +6690,7 @@ const ParamTypeIterator = struct { for (0..ty.structFieldCount(zcu)) |field_index| { const field_ty = ty.fieldType(field_index, zcu); if (!field_ty.hasRuntimeBits(zcu)) continue; - it.types_buffer[it.types_len] = try it.object.lowerType(pt, field_ty); + it.types_buffer[it.types_len] = try it.object.lowerType(field_ty); it.types_len += 1; } it.llvm_index += it.types_len - 1; @@ -6760,7 +6706,7 @@ const ParamTypeIterator = struct { return .byval; } else { var types_buffer: [8]Builder.Type = undefined; - types_buffer[0] = try it.object.lowerType(pt, scalar_ty); + types_buffer[0] = try it.object.lowerType(scalar_ty); it.types_buffer = types_buffer; it.types_len = 1; it.llvm_index += 1; @@ -6785,7 +6731,7 @@ const ParamTypeIterator = struct { } fn nextWin64(it: *ParamTypeIterator, ty: Type) ?Lowering { - const zcu = it.pt.zcu; + const zcu = it.object.zcu; switch (x86_64_abi.classifyWindows(ty, zcu, zcu.getTarget(), .arg)) { .integer => { if (isScalar(zcu, ty)) { @@ -6818,7 +6764,7 @@ const ParamTypeIterator = struct { } fn nextSystemV(it: *ParamTypeIterator, ty: Type) Allocator.Error!?Lowering { - const zcu = it.pt.zcu; + const zcu = it.object.zcu; const ip = &zcu.intern_pool; ty.assertHasLayout(zcu); const classes = x86_64_abi.classifySystemV(ty, zcu, zcu.getTarget(), .arg); @@ -6909,10 +6855,9 @@ const ParamTypeIterator = struct { return .multiple_llvm_types; } }; -pub fn iterateParamTypes(object: *Object, pt: Zcu.PerThread, fn_info: InternPool.Key.FuncType) ParamTypeIterator { +pub fn iterateParamTypes(object: *Object, fn_info: InternPool.Key.FuncType) ParamTypeIterator { return .{ .object = object, - .pt = pt, .fn_info = fn_info, .zig_index = 0, .llvm_index = 0, @@ -6976,8 +6921,8 @@ fn firstParamSRetSystemV(ty: Type, zcu: *Zcu, target: *const std.Target) bool { /// In order to support the C calling convention, some return types need to be lowered /// completely differently in the function prototype to honor the C ABI, and then /// be effectively bitcasted to the actual return type. -pub fn lowerFnRetTy(o: *Object, pt: Zcu.PerThread, fn_info: InternPool.Key.FuncType) Allocator.Error!Builder.Type { - const zcu = pt.zcu; +pub fn lowerFnRetTy(o: *Object, fn_info: InternPool.Key.FuncType) Allocator.Error!Builder.Type { + const zcu = o.zcu; const return_type = Type.fromInterned(fn_info.return_type); if (!return_type.hasRuntimeBits(zcu)) { assert(!return_type.isError(zcu)); @@ -6986,27 +6931,27 @@ pub fn lowerFnRetTy(o: *Object, pt: Zcu.PerThread, fn_info: InternPool.Key.FuncT const target = zcu.getTarget(); switch (fn_info.cc) { .@"inline" => unreachable, - .auto => return if (returnTypeByRef(zcu, target, return_type)) .void else o.lowerType(pt, return_type), + .auto => return if (returnTypeByRef(zcu, target, return_type)) .void else o.lowerType(return_type), - .x86_64_sysv => return lowerSystemVFnRetTy(o, pt, fn_info), - .x86_64_win => return lowerWin64FnRetTy(o, pt, fn_info), - .x86_stdcall => return if (isScalar(zcu, return_type)) o.lowerType(pt, return_type) else .void, - .x86_sysv, .x86_win => return if (isByRef(return_type, zcu)) .void else o.lowerType(pt, return_type), + .x86_64_sysv => return lowerSystemVFnRetTy(o, fn_info), + .x86_64_win => return lowerWin64FnRetTy(o, fn_info), + .x86_stdcall => return if (isScalar(zcu, return_type)) o.lowerType(return_type) else .void, + .x86_sysv, .x86_win => return if (isByRef(return_type, zcu)) .void else o.lowerType(return_type), .aarch64_aapcs, .aarch64_aapcs_darwin, .aarch64_aapcs_win => switch (aarch64_c_abi.classifyType(return_type, zcu)) { .memory => return .void, - .float_array => return o.lowerType(pt, return_type), - .byval => return o.lowerType(pt, return_type), + .float_array => return o.lowerType(return_type), + .byval => return o.lowerType(return_type), .integer => return o.builder.intType(@intCast(return_type.bitSize(zcu))), .double_integer => return o.builder.arrayType(2, .i64), }, .arm_aapcs, .arm_aapcs_vfp => switch (arm_c_abi.classifyType(return_type, zcu, .ret)) { .memory, .i64_array => return .void, .i32_array => |len| return if (len == 1) .i32 else .void, - .byval => return o.lowerType(pt, return_type), + .byval => return o.lowerType(return_type), }, .mips_o32 => switch (mips_c_abi.classifyType(return_type, zcu, .ret)) { .memory, .i32_array => return .void, - .byval => return o.lowerType(pt, return_type), + .byval => return o.lowerType(return_type), }, .riscv64_lp64, .riscv32_ilp32 => switch (riscv_c_abi.classifyType(return_type, zcu)) { .memory => return .void, @@ -7019,53 +6964,53 @@ pub fn lowerFnRetTy(o: *Object, pt: Zcu.PerThread, fn_info: InternPool.Key.FuncT }; return o.builder.structType(.normal, &.{ integer, integer }); }, - .byval => return o.lowerType(pt, return_type), + .byval => return o.lowerType(return_type), .fields => { var types_len: usize = 0; var types: [8]Builder.Type = undefined; for (0..return_type.structFieldCount(zcu)) |field_index| { const field_ty = return_type.fieldType(field_index, zcu); if (!field_ty.hasRuntimeBits(zcu)) continue; - types[types_len] = try o.lowerType(pt, field_ty); + types[types_len] = try o.lowerType(field_ty); types_len += 1; } return o.builder.structType(.normal, types[0..types_len]); }, }, .wasm_mvp => switch (wasm_c_abi.classifyType(return_type, zcu)) { - .direct => |scalar_ty| return o.lowerType(pt, scalar_ty), + .direct => |scalar_ty| return o.lowerType(scalar_ty), .indirect => return .void, }, // TODO investigate other callconvs - else => return o.lowerType(pt, return_type), + else => return o.lowerType(return_type), } } -fn lowerWin64FnRetTy(o: *Object, pt: Zcu.PerThread, fn_info: InternPool.Key.FuncType) Allocator.Error!Builder.Type { - const zcu = pt.zcu; +fn lowerWin64FnRetTy(o: *Object, fn_info: InternPool.Key.FuncType) Allocator.Error!Builder.Type { + const zcu = o.zcu; const return_type = Type.fromInterned(fn_info.return_type); switch (x86_64_abi.classifyWindows(return_type, zcu, zcu.getTarget(), .ret)) { .integer => { if (isScalar(zcu, return_type)) { - return o.lowerType(pt, return_type); + return o.lowerType(return_type); } else { return o.builder.intType(@intCast(return_type.abiSize(zcu) * 8)); } }, .win_i128 => return o.builder.vectorType(.normal, 2, .i64), .memory => return .void, - .sse => return o.lowerType(pt, return_type), + .sse => return o.lowerType(return_type), else => unreachable, } } -fn lowerSystemVFnRetTy(o: *Object, pt: Zcu.PerThread, fn_info: InternPool.Key.FuncType) Allocator.Error!Builder.Type { - const zcu = pt.zcu; +fn lowerSystemVFnRetTy(o: *Object, fn_info: InternPool.Key.FuncType) Allocator.Error!Builder.Type { + const zcu = o.zcu; const ip = &zcu.intern_pool; const return_type = Type.fromInterned(fn_info.return_type); return_type.assertHasLayout(zcu); if (isScalar(zcu, return_type)) { - return o.lowerType(pt, return_type); + return o.lowerType(return_type); } const classes = x86_64_abi.classifySystemV(return_type, zcu, zcu.getTarget(), .ret); var types_index: u32 = 0; @@ -7297,7 +7242,7 @@ pub fn isByRef(ty: Type, zcu: *const Zcu) bool { /// RMW exchange of floating-point values is bitcasted to same-sized integer /// types to work around a LLVM deficiency when targeting ARM/AArch64. fn getAtomicAbiType(fg: *const FuncGen, ty: Type, is_rmw_xchg: bool) Allocator.Error!Builder.Type { - const zcu = fg.pt.zcu; + const zcu = fg.object.zcu; switch (ty.zigTypeTag(zcu)) { .int, .@"enum", .@"struct", .@"union" => {}, .float => { diff --git a/src/codegen/riscv64/CodeGen.zig b/src/codegen/riscv64/CodeGen.zig index 3ad6faf805259154ae35f347e1dee712bea196cf..d50f6a71254877ca7cad6b0c82af9b79381d7a7b 100644 --- a/src/codegen/riscv64/CodeGen.zig +++ b/src/codegen/riscv64/CodeGen.zig @@ -4956,8 +4956,8 @@ fn genCall( // on linking. switch (info) { .air => |callee| { - if (try func.air.value(callee, pt)) |func_value| { - const func_key = zcu.intern_pool.indexToKey(func_value.ip_index); + if (callee.toInterned()) |func_ip_index| { + const func_key = zcu.intern_pool.indexToKey(func_ip_index); switch (switch (func_key) { else => func_key, .ptr => |ptr| if (ptr.byte_offset == 0) switch (ptr.base_addr) { diff --git a/src/codegen/sparc64/CodeGen.zig b/src/codegen/sparc64/CodeGen.zig index 3b38d6319ac325cb462b805727197121be348bfd..d4744e0fd0921de6aac44c859c9f9363ef37d677 100644 --- a/src/codegen/sparc64/CodeGen.zig +++ b/src/codegen/sparc64/CodeGen.zig @@ -1310,7 +1310,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier // Due to incremental compilation, how function calls are generated depends // on linking. - if (try self.air.value(call.callee, pt)) |func_value| switch (ip.indexToKey(func_value.toIntern())) { + if (call.callee.toInterned()) |func_ip_index| switch (ip.indexToKey(func_ip_index)) { .func => { return self.fail("TODO implement calling functions", .{}); }, @@ -4487,7 +4487,7 @@ fn resolveInst(self: *Self, ref: Air.Inst.Ref) InnerError!MCValue { return self.getResolvedInstValue(inst); } - return self.genTypedValue((try self.air.value(ref, pt)).?); + return self.genTypedValue(.fromInterned(ref.toInterned().?)); } fn ret(self: *Self, mcv: MCValue) !void { diff --git a/src/codegen/spirv/CodeGen.zig b/src/codegen/spirv/CodeGen.zig index 865b7f9dcff79a5181b85c30e207f998a664b4d0..4ce1681129568085499a611caea0d5f0c1b8eeef 100644 --- a/src/codegen/spirv/CodeGen.zig +++ b/src/codegen/spirv/CodeGen.zig @@ -387,13 +387,12 @@ fn importExtendedSet(cg: *CodeGen) !Id { /// Fetch the result-id for a previously generated instruction or constant. fn resolve(cg: *CodeGen, inst: Air.Inst.Ref) !Id { - const pt = cg.pt; const zcu = cg.module.zcu; const ip = &zcu.intern_pool; - if (try cg.air.value(inst, pt)) |val| { + if (inst.toInterned()) |val_ip_index| { const ty = cg.typeOf(inst); if (ty.zigTypeTag(zcu) == .@"fn") { - const fn_nav = switch (zcu.intern_pool.indexToKey(val.ip_index)) { + const fn_nav = switch (zcu.intern_pool.indexToKey(val_ip_index)) { .@"extern" => |@"extern"| @"extern".owner_nav, .func => |func| func.owner_nav, else => unreachable, @@ -403,7 +402,7 @@ fn resolve(cg: *CodeGen, inst: Air.Inst.Ref) !Id { return cg.module.declPtr(spv_decl_index).result_id; } - return try cg.constant(ty, val, .direct); + return try cg.constant(ty, .fromInterned(val_ip_index), .direct); } const index = inst.toIndex().?; return cg.inst_results.get(index).?; // Assertion means instruction does not dominate usage. @@ -5657,7 +5656,6 @@ fn airWrapOptional(cg: *CodeGen, inst: Air.Inst.Index) !?Id { fn airSwitchBr(cg: *CodeGen, inst: Air.Inst.Index) !void { const gpa = cg.module.gpa; - const pt = cg.pt; const zcu = cg.module.zcu; const target = cg.module.zcu.getTarget(); const switch_br = cg.air.unwrapSwitch(inst); @@ -5732,7 +5730,7 @@ fn airSwitchBr(cg: *CodeGen, inst: Air.Inst.Index) !void { const label = case_labels.at(case.idx); for (case.items) |item| { - const value = (try cg.air.value(item, pt)) orelse unreachable; + const value: Value = .fromInterned(item.toInterned().?); const int_val: u64 = switch (cond_ty.zigTypeTag(zcu)) { .bool, .int => if (cond_ty.isSignedInt(zcu)) @bitCast(value.toSignedInt(zcu)) else value.toUnsignedInt(zcu), .@"enum" => blk: { @@ -5875,9 +5873,9 @@ fn airAssembly(cg: *CodeGen, inst: Air.Inst.Index) !?Id { if (std.mem.eql(u8, in.constraint, "c")) { // constant - const val = (try cg.air.value(in.operand, cg.pt)) orelse { + const val: Value = .fromInterned(in.operand.toInterned() orelse { return cg.fail("assembly inputs with 'c' constraint have to be compile-time known", .{}); - }; + }); // TODO: This entire function should be handled a bit better... const ip = &zcu.intern_pool; @@ -5911,8 +5909,7 @@ fn airAssembly(cg: *CodeGen, inst: Air.Inst.Index) !?Id { if (input_ty.zigTypeTag(zcu) == .type) { // This assembly input is a type instead of a value. // That's fine for now, just make sure to resolve it as such. - const val = (try cg.air.value(in.operand, cg.pt)).?; - const ty_id = try cg.resolveType(val.toType(), .direct); + const ty_id = try cg.resolveType(in.operand.toType(), .direct); try ass.value_map.put(gpa, in.name, .{ .ty = ty_id }); } else { const ty_id = try cg.resolveType(input_ty, .direct); diff --git a/src/codegen/wasm/CodeGen.zig b/src/codegen/wasm/CodeGen.zig index c97892a10c22cacc4b7ecc3422694793fc1b7221..83049921ef7f6d4dca1cef1208266fb3f578118d 100644 --- a/src/codegen/wasm/CodeGen.zig +++ b/src/codegen/wasm/CodeGen.zig @@ -303,7 +303,7 @@ fn resolveInst(cg: *CodeGen, ref: Air.Inst.Ref) InnerError!WValue { const pt = cg.pt; const zcu = pt.zcu; - const val = (try cg.air.value(ref, pt)).?; + const val: Value = .fromInterned(ref.toInterned().?); const ty = cg.typeOf(ref); if (!ty.hasRuntimeBits(zcu) and !ty.isInt(zcu) and !ty.isError(zcu)) { gop.value_ptr.* = .none; @@ -2006,7 +2006,7 @@ fn airCall(cg: *CodeGen, inst: Air.Inst.Index, modifier: std.builtin.CallModifie const first_param_sret = firstParamSRet(fn_info.cc, Type.fromInterned(fn_info.return_type), zcu, cg.target); const callee: ?InternPool.Nav.Index = blk: { - const func_val = (try cg.air.value(call.callee, pt)) orelse break :blk null; + const func_val: Value = .fromInterned(call.callee.toInterned() orelse break :blk null); switch (ip.indexToKey(func_val.toIntern())) { inline .func, .@"extern" => |x| break :blk x.owner_nav, @@ -4464,7 +4464,7 @@ fn lowerConstant(cg: *CodeGen, val: Value) InnerError!WValue { .vector_type => { assert(determineSimdStoreStrategy(ty, zcu, cg.target) == .direct); var buf: [16]u8 = undefined; - val.writeToMemory(pt, &buf) catch unreachable; + val.writeToMemory(zcu, &buf) catch unreachable; return cg.storeSimdImmd(buf); }, .struct_type => unreachable, // packed structs use `bitpack` diff --git a/src/codegen/x86_64/CodeGen.zig b/src/codegen/x86_64/CodeGen.zig index 9ba98c3e833cc11ff996a61a7d624a62ebdda3fa..69e6a94f08684905a47417c66a6518d544cdbbe7 100644 --- a/src/codegen/x86_64/CodeGen.zig +++ b/src/codegen/x86_64/CodeGen.zig @@ -176185,8 +176185,8 @@ fn genCall(self: *CodeGen, info: union(enum) { // Due to incremental compilation, how function calls are generated depends // on linking. switch (info) { - .air => |callee| if (try self.air.value(callee, pt)) |func_value| { - const func_key = ip.indexToKey(func_value.ip_index); + .air => |callee| if (callee.toInterned()) |func_ip_index| { + const func_key = ip.indexToKey(func_ip_index); switch (switch (func_key) { else => func_key, .ptr => |ptr| if (ptr.byte_offset == 0) switch (ptr.base_addr) {