| ... | ... | @@ -78,7 +78,6 @@ const LoopDepth = u16; |
| 78 | 78 | const Local = struct { |
| 79 | 79 | cty_idx: CType.Index, |
| 80 | 80 | alignas: CType.AlignAs, |
| 81 | | is_in_clone: bool, |
| 82 | 81 | |
| 83 | 82 | pub fn getType(local: Local) LocalType { |
| 84 | 83 | return .{ .cty_idx = local.cty_idx, .alignas = local.alignas }; |
| ... | ... | @@ -275,16 +274,13 @@ pub const Function = struct { |
| 275 | 274 | /// All the locals, to be emitted at the top of the function. |
| 276 | 275 | locals: std.ArrayListUnmanaged(Local) = .{}, |
| 277 | 276 | /// Which locals are available for reuse, based on Type. |
| 278 | | /// Only locals in the last stack entry are available for reuse, |
| 279 | | /// other entries will become available on loop exit. |
| 280 | 277 | free_locals_map: LocalsMap = .{}, |
| 281 | | is_in_clone: bool = false, |
| 282 | 278 | /// Locals which will not be freed by Liveness. This is used after a |
| 283 | 279 | /// Function body is lowered in order to make `free_locals_map` have |
| 284 | 280 | /// 100% of the locals within so that it can be used to render the block |
| 285 | 281 | /// of variable declarations at the top of a function, sorted descending |
| 286 | 282 | /// by type alignment. |
| 287 | | /// The value is whether the alloc is static or not. |
| 283 | /// The value is whether the alloc needs to be emitted in the header. |
| 288 | 284 | allocs: std.AutoArrayHashMapUnmanaged(LocalIndex, bool) = .{}, |
| 289 | 285 | /// Needed for memory used by the keys of free_locals_map entries. |
| 290 | 286 | arena: std.heap.ArenaAllocator, |
| ... | ... | @@ -302,7 +298,7 @@ pub const Function = struct { |
| 302 | 298 | const alignment = 0; |
| 303 | 299 | const decl_c_value = try f.allocLocalValue(ty, alignment); |
| 304 | 300 | const gpa = f.object.dg.gpa; |
| 305 | | try f.allocs.put(gpa, decl_c_value.new_local, true); |
| 301 | try f.allocs.put(gpa, decl_c_value.new_local, false); |
| 306 | 302 | try writer.writeAll("static "); |
| 307 | 303 | try f.object.dg.renderTypeAndName(writer, ty, decl_c_value, Const, alignment, .complete); |
| 308 | 304 | try writer.writeAll(" = "); |
| ... | ... | @@ -323,14 +319,15 @@ pub const Function = struct { |
| 323 | 319 | }; |
| 324 | 320 | } |
| 325 | 321 | |
| 326 | | /// Skips the reuse logic. |
| 322 | /// Skips the reuse logic. This function should be used for any persistent allocation, i.e. |
| 323 | /// those which go into `allocs`. This function does not add the resulting local into `allocs`; |
| 324 | /// that responsibility lies with the caller. |
| 327 | 325 | fn allocLocalValue(f: *Function, ty: Type, alignment: u32) !CValue { |
| 328 | 326 | const gpa = f.object.dg.gpa; |
| 329 | 327 | const target = f.object.dg.module.getTarget(); |
| 330 | 328 | try f.locals.append(gpa, .{ |
| 331 | 329 | .cty_idx = try f.typeToIndex(ty, .complete), |
| 332 | 330 | .alignas = CType.AlignAs.init(alignment, ty.abiAlignment(target)), |
| 333 | | .is_in_clone = f.is_in_clone, |
| 334 | 331 | }); |
| 335 | 332 | return .{ .new_local = @intCast(LocalIndex, f.locals.items.len - 1) }; |
| 336 | 333 | } |
| ... | ... | @@ -341,7 +338,8 @@ pub const Function = struct { |
| 341 | 338 | return result; |
| 342 | 339 | } |
| 343 | 340 | |
| 344 | | /// Only allocates the local; does not print anything. |
| 341 | /// Only allocates the local; does not print anything. Will attempt to re-use locals, so should |
| 342 | /// not be used for persistent locals (i.e. those in `allocs`). |
| 345 | 343 | fn allocAlignedLocal(f: *Function, ty: Type, _: CQualifiers, alignment: u32) !CValue { |
| 346 | 344 | const target = f.object.dg.module.getTarget(); |
| 347 | 345 | if (f.free_locals_map.getPtr(.{ |
| ... | ... | @@ -2586,7 +2584,7 @@ pub fn genFunc(f: *Function) !void { |
| 2586 | 2584 | f.free_locals_map.clearRetainingCapacity(); |
| 2587 | 2585 | |
| 2588 | 2586 | const main_body = f.air.getMainBody(); |
| 2589 | | try genBody(f, main_body); |
| 2587 | try genBodyResolveState(f, undefined, &.{}, main_body, false); |
| 2590 | 2588 | |
| 2591 | 2589 | try o.indent_writer.insertNewline(); |
| 2592 | 2590 | |
| ... | ... | @@ -2597,8 +2595,8 @@ pub fn genFunc(f: *Function) !void { |
| 2597 | 2595 | // alignment, descending. |
| 2598 | 2596 | const free_locals = &f.free_locals_map; |
| 2599 | 2597 | assert(f.value_map.count() == 0); // there must not be any unfreed locals |
| 2600 | | for (f.allocs.keys(), f.allocs.values()) |local_index, value| { |
| 2601 | | if (value) continue; // static |
| 2598 | for (f.allocs.keys(), f.allocs.values()) |local_index, should_emit| { |
| 2599 | if (!should_emit) continue; |
| 2602 | 2600 | const local = f.locals.items[local_index]; |
| 2603 | 2601 | log.debug("inserting local {d} into free_locals", .{local_index}); |
| 2604 | 2602 | const gop = try free_locals.getOrPut(gpa, local.getType()); |
| ... | ... | @@ -2715,6 +2713,10 @@ pub fn genHeader(dg: *DeclGen) error{ AnalysisFail, OutOfMemory }!void { |
| 2715 | 2713 | } |
| 2716 | 2714 | } |
| 2717 | 2715 | |
| 2716 | /// Generate code for an entire body which ends with a `noreturn` instruction. The states of |
| 2717 | /// `value_map` and `free_locals_map` are undefined after the generation, and new locals may not |
| 2718 | /// have been added to `free_locals_map`. For a version of this function that restores this state, |
| 2719 | /// see `genBodyResolveState`. |
| 2718 | 2720 | fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutOfMemory }!void { |
| 2719 | 2721 | const writer = f.object.writer(); |
| 2720 | 2722 | if (body.len == 0) { |
| ... | ... | @@ -2728,10 +2730,69 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO |
| 2728 | 2730 | } |
| 2729 | 2731 | } |
| 2730 | 2732 | |
| 2733 | /// Generate code for an entire body which ends with a `noreturn` instruction. The states of |
| 2734 | /// `value_map` and `free_locals_map` are restored to their original values, and any non-allocated |
| 2735 | /// locals introduced within the body are correctly added to `free_locals_map`. Operands in |
| 2736 | /// `leading_deaths` have their deaths processed before the body is generated. |
| 2737 | /// A scope is introduced (using braces) only if `inner` is `false`. |
| 2738 | /// If `leading_deaths` is empty, `inst` may be `undefined`. |
| 2739 | fn genBodyResolveState(f: *Function, inst: Air.Inst.Index, leading_deaths: []const Air.Inst.Index, body: []const Air.Inst.Index, inner: bool) error{ AnalysisFail, OutOfMemory }!void { |
| 2740 | if (body.len == 0) { |
| 2741 | // Don't go to the expense of cloning everything! |
| 2742 | if (!inner) try f.object.writer().writeAll("{}"); |
| 2743 | return; |
| 2744 | } |
| 2745 | |
| 2746 | // TODO: we can probably avoid the copies in some other common cases too. |
| 2747 | |
| 2748 | const gpa = f.object.dg.gpa; |
| 2749 | |
| 2750 | // Save the original value_map and free_locals_map so that we can restore them after the body. |
| 2751 | var old_value_map = try f.value_map.clone(); |
| 2752 | defer old_value_map.deinit(); |
| 2753 | var old_free_locals = try cloneFreeLocalsMap(gpa, &f.free_locals_map); |
| 2754 | defer deinitFreeLocalsMap(gpa, &old_free_locals); |
| 2755 | |
| 2756 | // Remember how many locals there were before entering the body so that we can free any that |
| 2757 | // were newly introduced. Any new locals must necessarily be logically free after the then |
| 2758 | // branch is complete. |
| 2759 | const pre_locals_len = @intCast(LocalIndex, f.locals.items.len); |
| 2760 | |
| 2761 | for (leading_deaths) |death| { |
| 2762 | try die(f, inst, Air.indexToRef(death)); |
| 2763 | } |
| 2764 | |
| 2765 | if (inner) { |
| 2766 | try genBodyInner(f, body); |
| 2767 | } else { |
| 2768 | try genBody(f, body); |
| 2769 | } |
| 2770 | |
| 2771 | f.value_map.deinit(); |
| 2772 | f.value_map = old_value_map.move(); |
| 2773 | deinitFreeLocalsMap(gpa, &f.free_locals_map); |
| 2774 | f.free_locals_map = old_free_locals.move(); |
| 2775 | |
| 2776 | // Now, use the lengths we stored earlier to detect any locals the body generated, and free |
| 2777 | // them, unless they were used to store allocs. |
| 2778 | |
| 2779 | for (pre_locals_len..f.locals.items.len) |local_i| { |
| 2780 | const local_index = @intCast(LocalIndex, local_i); |
| 2781 | if (f.allocs.contains(local_index)) { |
| 2782 | continue; |
| 2783 | } |
| 2784 | try freeLocal(f, inst, local_index, 0); |
| 2785 | } |
| 2786 | } |
| 2787 | |
| 2731 | 2788 | fn genBodyInner(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutOfMemory }!void { |
| 2732 | 2789 | const air_tags = f.air.instructions.items(.tag); |
| 2733 | 2790 | |
| 2734 | 2791 | for (body) |inst| { |
| 2792 | if (f.liveness.isUnused(inst) and !f.air.mustLower(inst)) { |
| 2793 | continue; |
| 2794 | } |
| 2795 | |
| 2735 | 2796 | const result_value = switch (air_tags[inst]) { |
| 2736 | 2797 | // zig fmt: off |
| 2737 | 2798 | .constant => unreachable, // excluded from function bodies |
| ... | ... | @@ -3009,11 +3070,6 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, |
| 3009 | 3070 | fn airSliceField(f: *Function, inst: Air.Inst.Index, is_ptr: bool, field_name: []const u8) !CValue { |
| 3010 | 3071 | const ty_op = f.air.instructions.items(.data)[inst].ty_op; |
| 3011 | 3072 | |
| 3012 | | if (f.liveness.isUnused(inst)) { |
| 3013 | | try reap(f, inst, &.{ty_op.operand}); |
| 3014 | | return .none; |
| 3015 | | } |
| 3016 | | |
| 3017 | 3073 | const inst_ty = f.air.typeOfIndex(inst); |
| 3018 | 3074 | const operand = try f.resolveInst(ty_op.operand); |
| 3019 | 3075 | try reap(f, inst, &.{ty_op.operand}); |
| ... | ... | @@ -3032,10 +3088,7 @@ fn airSliceField(f: *Function, inst: Air.Inst.Index, is_ptr: bool, field_name: [ |
| 3032 | 3088 | fn airPtrElemVal(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3033 | 3089 | const inst_ty = f.air.typeOfIndex(inst); |
| 3034 | 3090 | const bin_op = f.air.instructions.items(.data)[inst].bin_op; |
| 3035 | | const ptr_ty = f.air.typeOf(bin_op.lhs); |
| 3036 | | if ((!ptr_ty.isVolatilePtr() and f.liveness.isUnused(inst)) or |
| 3037 | | !inst_ty.hasRuntimeBitsIgnoreComptime()) |
| 3038 | | { |
| 3091 | if (!inst_ty.hasRuntimeBitsIgnoreComptime()) { |
| 3039 | 3092 | try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); |
| 3040 | 3093 | return .none; |
| 3041 | 3094 | } |
| ... | ... | @@ -3074,11 +3127,6 @@ fn airPtrElemPtr(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3074 | 3127 | const ty_pl = f.air.instructions.items(.data)[inst].ty_pl; |
| 3075 | 3128 | const bin_op = f.air.extraData(Air.Bin, ty_pl.payload).data; |
| 3076 | 3129 | |
| 3077 | | if (f.liveness.isUnused(inst)) { |
| 3078 | | try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); |
| 3079 | | return .none; |
| 3080 | | } |
| 3081 | | |
| 3082 | 3130 | const inst_ty = f.air.typeOfIndex(inst); |
| 3083 | 3131 | const ptr_ty = f.air.typeOf(bin_op.lhs); |
| 3084 | 3132 | const child_ty = ptr_ty.childType(); |
| ... | ... | @@ -3116,10 +3164,7 @@ fn airPtrElemPtr(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3116 | 3164 | fn airSliceElemVal(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3117 | 3165 | const inst_ty = f.air.typeOfIndex(inst); |
| 3118 | 3166 | const bin_op = f.air.instructions.items(.data)[inst].bin_op; |
| 3119 | | const slice_ty = f.air.typeOf(bin_op.lhs); |
| 3120 | | if ((!slice_ty.isVolatilePtr() and f.liveness.isUnused(inst)) or |
| 3121 | | !inst_ty.hasRuntimeBitsIgnoreComptime()) |
| 3122 | | { |
| 3167 | if (!inst_ty.hasRuntimeBitsIgnoreComptime()) { |
| 3123 | 3168 | try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); |
| 3124 | 3169 | return .none; |
| 3125 | 3170 | } |
| ... | ... | @@ -3158,11 +3203,6 @@ fn airSliceElemPtr(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3158 | 3203 | const ty_pl = f.air.instructions.items(.data)[inst].ty_pl; |
| 3159 | 3204 | const bin_op = f.air.extraData(Air.Bin, ty_pl.payload).data; |
| 3160 | 3205 | |
| 3161 | | if (f.liveness.isUnused(inst)) { |
| 3162 | | try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); |
| 3163 | | return .none; |
| 3164 | | } |
| 3165 | | |
| 3166 | 3206 | const slice_ty = f.air.typeOf(bin_op.lhs); |
| 3167 | 3207 | const child_ty = slice_ty.elemType2(); |
| 3168 | 3208 | const slice = try f.resolveInst(bin_op.lhs); |
| ... | ... | @@ -3188,7 +3228,7 @@ fn airSliceElemPtr(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3188 | 3228 | fn airArrayElemVal(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3189 | 3229 | const bin_op = f.air.instructions.items(.data)[inst].bin_op; |
| 3190 | 3230 | const inst_ty = f.air.typeOfIndex(inst); |
| 3191 | | if (f.liveness.isUnused(inst) or !inst_ty.hasRuntimeBitsIgnoreComptime()) { |
| 3231 | if (!inst_ty.hasRuntimeBitsIgnoreComptime()) { |
| 3192 | 3232 | try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); |
| 3193 | 3233 | return .none; |
| 3194 | 3234 | } |
| ... | ... | @@ -3224,40 +3264,34 @@ fn airArrayElemVal(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3224 | 3264 | } |
| 3225 | 3265 | |
| 3226 | 3266 | fn airAlloc(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3227 | | if (f.liveness.isUnused(inst)) return .none; |
| 3228 | | |
| 3229 | 3267 | const inst_ty = f.air.typeOfIndex(inst); |
| 3230 | 3268 | const elem_type = inst_ty.elemType(); |
| 3231 | 3269 | if (!elem_type.isFnOrHasRuntimeBitsIgnoreComptime()) return .{ .undef = inst_ty }; |
| 3232 | 3270 | |
| 3233 | 3271 | const target = f.object.dg.module.getTarget(); |
| 3234 | | const local = try f.allocAlignedLocal( |
| 3272 | const local = try f.allocLocalValue( |
| 3235 | 3273 | elem_type, |
| 3236 | | CQualifiers.init(.{ .@"const" = inst_ty.isConstPtr() }), |
| 3237 | 3274 | inst_ty.ptrAlignment(target), |
| 3238 | 3275 | ); |
| 3239 | 3276 | log.debug("%{d}: allocated unfreeable t{d}", .{ inst, local.new_local }); |
| 3240 | 3277 | const gpa = f.object.dg.module.gpa; |
| 3241 | | try f.allocs.put(gpa, local.new_local, false); |
| 3278 | try f.allocs.put(gpa, local.new_local, true); |
| 3242 | 3279 | return .{ .local_ref = local.new_local }; |
| 3243 | 3280 | } |
| 3244 | 3281 | |
| 3245 | 3282 | fn airRetPtr(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3246 | | if (f.liveness.isUnused(inst)) return .none; |
| 3247 | | |
| 3248 | 3283 | const inst_ty = f.air.typeOfIndex(inst); |
| 3249 | 3284 | const elem_ty = inst_ty.elemType(); |
| 3250 | 3285 | if (!elem_ty.isFnOrHasRuntimeBitsIgnoreComptime()) return .{ .undef = inst_ty }; |
| 3251 | 3286 | |
| 3252 | 3287 | const target = f.object.dg.module.getTarget(); |
| 3253 | | const local = try f.allocAlignedLocal( |
| 3288 | const local = try f.allocLocalValue( |
| 3254 | 3289 | elem_ty, |
| 3255 | | CQualifiers.init(.{ .@"const" = inst_ty.isConstPtr() }), |
| 3256 | 3290 | inst_ty.ptrAlignment(target), |
| 3257 | 3291 | ); |
| 3258 | 3292 | log.debug("%{d}: allocated unfreeable t{d}", .{ inst, local.new_local }); |
| 3259 | 3293 | const gpa = f.object.dg.module.gpa; |
| 3260 | | try f.allocs.put(gpa, local.new_local, false); |
| 3294 | try f.allocs.put(gpa, local.new_local, true); |
| 3261 | 3295 | return .{ .local_ref = local.new_local }; |
| 3262 | 3296 | } |
| 3263 | 3297 | |
| ... | ... | @@ -3293,9 +3327,7 @@ fn airLoad(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3293 | 3327 | const ptr_info = ptr_scalar_ty.ptrInfo().data; |
| 3294 | 3328 | const src_ty = ptr_info.pointee_type; |
| 3295 | 3329 | |
| 3296 | | if (!src_ty.hasRuntimeBitsIgnoreComptime() or |
| 3297 | | (!ptr_info.@"volatile" and f.liveness.isUnused(inst))) |
| 3298 | | { |
| 3330 | if (!src_ty.hasRuntimeBitsIgnoreComptime()) { |
| 3299 | 3331 | try reap(f, inst, &.{ty_op.operand}); |
| 3300 | 3332 | return .none; |
| 3301 | 3333 | } |
| ... | ... | @@ -3442,11 +3474,6 @@ fn airRet(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !CValue { |
| 3442 | 3474 | fn airIntCast(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3443 | 3475 | const ty_op = f.air.instructions.items(.data)[inst].ty_op; |
| 3444 | 3476 | |
| 3445 | | if (f.liveness.isUnused(inst)) { |
| 3446 | | try reap(f, inst, &.{ty_op.operand}); |
| 3447 | | return .none; |
| 3448 | | } |
| 3449 | | |
| 3450 | 3477 | const operand = try f.resolveInst(ty_op.operand); |
| 3451 | 3478 | try reap(f, inst, &.{ty_op.operand}); |
| 3452 | 3479 | |
| ... | ... | @@ -3470,10 +3497,6 @@ fn airIntCast(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3470 | 3497 | |
| 3471 | 3498 | fn airTrunc(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3472 | 3499 | const ty_op = f.air.instructions.items(.data)[inst].ty_op; |
| 3473 | | if (f.liveness.isUnused(inst)) { |
| 3474 | | try reap(f, inst, &.{ty_op.operand}); |
| 3475 | | return .none; |
| 3476 | | } |
| 3477 | 3500 | |
| 3478 | 3501 | const operand = try f.resolveInst(ty_op.operand); |
| 3479 | 3502 | try reap(f, inst, &.{ty_op.operand}); |
| ... | ... | @@ -3569,10 +3592,6 @@ fn airTrunc(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3569 | 3592 | |
| 3570 | 3593 | fn airBoolToInt(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3571 | 3594 | const un_op = f.air.instructions.items(.data)[inst].un_op; |
| 3572 | | if (f.liveness.isUnused(inst)) { |
| 3573 | | try reap(f, inst, &.{un_op}); |
| 3574 | | return .none; |
| 3575 | | } |
| 3576 | 3595 | const operand = try f.resolveInst(un_op); |
| 3577 | 3596 | try reap(f, inst, &.{un_op}); |
| 3578 | 3597 | const writer = f.object.writer(); |
| ... | ... | @@ -3746,11 +3765,6 @@ fn airOverflow(f: *Function, inst: Air.Inst.Index, operation: []const u8, info: |
| 3746 | 3765 | const ty_pl = f.air.instructions.items(.data)[inst].ty_pl; |
| 3747 | 3766 | const bin_op = f.air.extraData(Air.Bin, ty_pl.payload).data; |
| 3748 | 3767 | |
| 3749 | | if (f.liveness.isUnused(inst)) { |
| 3750 | | try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); |
| 3751 | | return .none; |
| 3752 | | } |
| 3753 | | |
| 3754 | 3768 | const lhs = try f.resolveInst(bin_op.lhs); |
| 3755 | 3769 | const rhs = try f.resolveInst(bin_op.rhs); |
| 3756 | 3770 | try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); |
| ... | ... | @@ -3790,11 +3804,6 @@ fn airNot(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3790 | 3804 | const scalar_ty = operand_ty.scalarType(); |
| 3791 | 3805 | if (scalar_ty.tag() != .bool) return try airUnBuiltinCall(f, inst, "not", .bits); |
| 3792 | 3806 | |
| 3793 | | if (f.liveness.isUnused(inst)) { |
| 3794 | | try reap(f, inst, &.{ty_op.operand}); |
| 3795 | | return .none; |
| 3796 | | } |
| 3797 | | |
| 3798 | 3807 | const op = try f.resolveInst(ty_op.operand); |
| 3799 | 3808 | try reap(f, inst, &.{ty_op.operand}); |
| 3800 | 3809 | |
| ... | ... | @@ -3829,11 +3838,6 @@ fn airBinOp( |
| 3829 | 3838 | if ((scalar_ty.isInt() and scalar_ty.bitSize(target) > 64) or scalar_ty.isRuntimeFloat()) |
| 3830 | 3839 | return try airBinBuiltinCall(f, inst, operation, info); |
| 3831 | 3840 | |
| 3832 | | if (f.liveness.isUnused(inst)) { |
| 3833 | | try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); |
| 3834 | | return .none; |
| 3835 | | } |
| 3836 | | |
| 3837 | 3841 | const lhs = try f.resolveInst(bin_op.lhs); |
| 3838 | 3842 | const rhs = try f.resolveInst(bin_op.rhs); |
| 3839 | 3843 | try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); |
| ... | ... | @@ -3865,11 +3869,6 @@ fn airCmpOp( |
| 3865 | 3869 | data: anytype, |
| 3866 | 3870 | operator: std.math.CompareOperator, |
| 3867 | 3871 | ) !CValue { |
| 3868 | | if (f.liveness.isUnused(inst)) { |
| 3869 | | try reap(f, inst, &.{ data.lhs, data.rhs }); |
| 3870 | | return .none; |
| 3871 | | } |
| 3872 | | |
| 3873 | 3872 | const operand_ty = f.air.typeOf(data.lhs); |
| 3874 | 3873 | const scalar_ty = operand_ty.scalarType(); |
| 3875 | 3874 | |
| ... | ... | @@ -3918,11 +3917,6 @@ fn airEquality( |
| 3918 | 3917 | ) !CValue { |
| 3919 | 3918 | const bin_op = f.air.instructions.items(.data)[inst].bin_op; |
| 3920 | 3919 | |
| 3921 | | if (f.liveness.isUnused(inst)) { |
| 3922 | | try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); |
| 3923 | | return .none; |
| 3924 | | } |
| 3925 | | |
| 3926 | 3920 | const operand_ty = f.air.typeOf(bin_op.lhs); |
| 3927 | 3921 | const target = f.object.dg.module.getTarget(); |
| 3928 | 3922 | const operand_bits = operand_ty.bitSize(target); |
| ... | ... | @@ -3987,11 +3981,6 @@ fn airEquality( |
| 3987 | 3981 | fn airCmpLtErrorsLen(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3988 | 3982 | const un_op = f.air.instructions.items(.data)[inst].un_op; |
| 3989 | 3983 | |
| 3990 | | if (f.liveness.isUnused(inst)) { |
| 3991 | | try reap(f, inst, &.{un_op}); |
| 3992 | | return .none; |
| 3993 | | } |
| 3994 | | |
| 3995 | 3984 | const inst_ty = f.air.typeOfIndex(inst); |
| 3996 | 3985 | const operand = try f.resolveInst(un_op); |
| 3997 | 3986 | try reap(f, inst, &.{un_op}); |
| ... | ... | @@ -4008,10 +3997,6 @@ fn airCmpLtErrorsLen(f: *Function, inst: Air.Inst.Index) !CValue { |
| 4008 | 3997 | fn airPtrAddSub(f: *Function, inst: Air.Inst.Index, operator: u8) !CValue { |
| 4009 | 3998 | const ty_pl = f.air.instructions.items(.data)[inst].ty_pl; |
| 4010 | 3999 | const bin_op = f.air.extraData(Air.Bin, ty_pl.payload).data; |
| 4011 | | if (f.liveness.isUnused(inst)) { |
| 4012 | | try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); |
| 4013 | | return .none; |
| 4014 | | } |
| 4015 | 4000 | |
| 4016 | 4001 | const lhs = try f.resolveInst(bin_op.lhs); |
| 4017 | 4002 | const rhs = try f.resolveInst(bin_op.rhs); |
| ... | ... | @@ -4059,11 +4044,6 @@ fn airPtrAddSub(f: *Function, inst: Air.Inst.Index, operator: u8) !CValue { |
| 4059 | 4044 | fn airMinMax(f: *Function, inst: Air.Inst.Index, operator: u8, operation: []const u8) !CValue { |
| 4060 | 4045 | const bin_op = f.air.instructions.items(.data)[inst].bin_op; |
| 4061 | 4046 | |
| 4062 | | if (f.liveness.isUnused(inst)) { |
| 4063 | | try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); |
| 4064 | | return .none; |
| 4065 | | } |
| 4066 | | |
| 4067 | 4047 | const inst_ty = f.air.typeOfIndex(inst); |
| 4068 | 4048 | const inst_scalar_ty = inst_ty.scalarType(); |
| 4069 | 4049 | |
| ... | ... | @@ -4107,11 +4087,6 @@ fn airSlice(f: *Function, inst: Air.Inst.Index) !CValue { |
| 4107 | 4087 | const ty_pl = f.air.instructions.items(.data)[inst].ty_pl; |
| 4108 | 4088 | const bin_op = f.air.extraData(Air.Bin, ty_pl.payload).data; |
| 4109 | 4089 | |
| 4110 | | if (f.liveness.isUnused(inst)) { |
| 4111 | | try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); |
| 4112 | | return .none; |
| 4113 | | } |
| 4114 | | |
| 4115 | 4090 | const ptr = try f.resolveInst(bin_op.lhs); |
| 4116 | 4091 | const len = try f.resolveInst(bin_op.rhs); |
| 4117 | 4092 | try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); |
| ... | ... | @@ -4316,6 +4291,7 @@ fn airBlock(f: *Function, inst: Air.Inst.Index) !CValue { |
| 4316 | 4291 | const ty_pl = f.air.instructions.items(.data)[inst].ty_pl; |
| 4317 | 4292 | const extra = f.air.extraData(Air.Block, ty_pl.payload); |
| 4318 | 4293 | const body = f.air.extra[extra.end..][0..extra.data.body_len]; |
| 4294 | const liveness_block = f.liveness.getBlock(inst); |
| 4319 | 4295 | |
| 4320 | 4296 | const block_id: usize = f.next_block_index; |
| 4321 | 4297 | f.next_block_index += 1; |
| ... | ... | @@ -4332,7 +4308,15 @@ fn airBlock(f: *Function, inst: Air.Inst.Index) !CValue { |
| 4332 | 4308 | .result = result, |
| 4333 | 4309 | }); |
| 4334 | 4310 | |
| 4335 | | try genBodyInner(f, body); |
| 4311 | try genBodyResolveState(f, inst, &.{}, body, true); |
| 4312 | |
| 4313 | assert(f.blocks.remove(inst)); |
| 4314 | |
| 4315 | // The body might result in some values we had beforehand being killed |
| 4316 | for (liveness_block.deaths) |death| { |
| 4317 | try die(f, inst, Air.indexToRef(death)); |
| 4318 | } |
| 4319 | |
| 4336 | 4320 | try f.object.indent_writer.insertNewline(); |
| 4337 | 4321 | // label might be unused, add a dummy goto |
| 4338 | 4322 | // label must be followed by an expression, add an empty one. |
| ... | ... | @@ -4366,6 +4350,7 @@ fn lowerTry( |
| 4366 | 4350 | ) !CValue { |
| 4367 | 4351 | const err_union = try f.resolveInst(operand); |
| 4368 | 4352 | const result_ty = f.air.typeOfIndex(inst); |
| 4353 | const liveness_condbr = f.liveness.getCondBr(inst); |
| 4369 | 4354 | const writer = f.object.writer(); |
| 4370 | 4355 | const payload_ty = err_union_ty.errorUnionPayload(); |
| 4371 | 4356 | const payload_has_bits = payload_ty.hasRuntimeBitsIgnoreComptime(); |
| ... | ... | @@ -4389,10 +4374,15 @@ fn lowerTry( |
| 4389 | 4374 | } |
| 4390 | 4375 | try writer.writeByte(')'); |
| 4391 | 4376 | |
| 4392 | | try genBody(f, body); |
| 4377 | try genBodyResolveState(f, inst, liveness_condbr.else_deaths, body, false); |
| 4393 | 4378 | try f.object.indent_writer.insertNewline(); |
| 4394 | 4379 | } |
| 4395 | 4380 | |
| 4381 | // Now we have the "then branch" (in terms of the liveness data); process any deaths. |
| 4382 | for (liveness_condbr.then_deaths) |death| { |
| 4383 | try die(f, inst, Air.indexToRef(death)); |
| 4384 | } |
| 4385 | |
| 4396 | 4386 | if (!payload_has_bits) { |
| 4397 | 4387 | if (!operand_is_ptr) { |
| 4398 | 4388 | return .none; |
| ... | ... | @@ -4466,10 +4456,6 @@ fn airBr(f: *Function, inst: Air.Inst.Index) !CValue { |
| 4466 | 4456 | fn airBitcast(f: *Function, inst: Air.Inst.Index) !CValue { |
| 4467 | 4457 | const ty_op = f.air.instructions.items(.data)[inst].ty_op; |
| 4468 | 4458 | const dest_ty = f.air.typeOfIndex(inst); |
| 4469 | | if (f.liveness.isUnused(inst)) { |
| 4470 | | try reap(f, inst, &.{ty_op.operand}); |
| 4471 | | return .none; |
| 4472 | | } |
| 4473 | 4459 | |
| 4474 | 4460 | const operand = try f.resolveInst(ty_op.operand); |
| 4475 | 4461 | try reap(f, inst, &.{ty_op.operand}); |
| ... | ... | @@ -4593,7 +4579,6 @@ fn airBreakpoint(writer: anytype) !CValue { |
| 4593 | 4579 | } |
| 4594 | 4580 | |
| 4595 | 4581 | fn airRetAddr(f: *Function, inst: Air.Inst.Index) !CValue { |
| 4596 | | if (f.liveness.isUnused(inst)) return .none; |
| 4597 | 4582 | const writer = f.object.writer(); |
| 4598 | 4583 | const local = try f.allocLocal(inst, Type.usize); |
| 4599 | 4584 | try f.writeCValue(writer, local, .Other); |
| ... | ... | @@ -4604,7 +4589,6 @@ fn airRetAddr(f: *Function, inst: Air.Inst.Index) !CValue { |
| 4604 | 4589 | } |
| 4605 | 4590 | |
| 4606 | 4591 | fn airFrameAddress(f: *Function, inst: Air.Inst.Index) !CValue { |
| 4607 | | if (f.liveness.isUnused(inst)) return .none; |
| 4608 | 4592 | const writer = f.object.writer(); |
| 4609 | 4593 | const local = try f.allocLocal(inst, Type.usize); |
| 4610 | 4594 | try f.writeCValue(writer, local, .Other); |
| ... | ... | @@ -4640,7 +4624,7 @@ fn airLoop(f: *Function, inst: Air.Inst.Index) !CValue { |
| 4640 | 4624 | const writer = f.object.writer(); |
| 4641 | 4625 | |
| 4642 | 4626 | try writer.writeAll("for (;;) "); |
| 4643 | | try genBody(f, body); |
| 4627 | try genBody(f, body); // no need to restore state, we're noreturn |
| 4644 | 4628 | try writer.writeByte('\n'); |
| 4645 | 4629 | |
| 4646 | 4630 | return .none; |
| ... | ... | @@ -4656,61 +4640,24 @@ fn airCondBr(f: *Function, inst: Air.Inst.Index) !CValue { |
| 4656 | 4640 | const liveness_condbr = f.liveness.getCondBr(inst); |
| 4657 | 4641 | const writer = f.object.writer(); |
| 4658 | 4642 | |
| 4659 | | // Keep using the original for the then branch; use a clone of the value |
| 4660 | | // map for the else branch. |
| 4661 | | const gpa = f.object.dg.gpa; |
| 4662 | | var cloned_map = try f.value_map.clone(); |
| 4663 | | defer cloned_map.deinit(); |
| 4664 | | var cloned_frees = try cloneFreeLocalsMap(gpa, &f.free_locals_map); |
| 4665 | | defer deinitFreeLocalsMap(gpa, &cloned_frees); |
| 4666 | | |
| 4667 | | // Remember how many locals there were before entering the then branch so |
| 4668 | | // that we can notice and use them in the else branch. Any new locals must |
| 4669 | | // necessarily be free already after the then branch is complete. |
| 4670 | | const pre_locals_len = @intCast(LocalIndex, f.locals.items.len); |
| 4671 | | // Remember how many allocs there were before entering the then branch so |
| 4672 | | // that we can notice and make sure not to use them in the else branch. |
| 4673 | | // Any new allocs must be removed from the free list. |
| 4674 | | const pre_allocs_len = @intCast(LocalIndex, f.allocs.count()); |
| 4675 | | const was_in_clone = f.is_in_clone; |
| 4676 | | f.is_in_clone = true; |
| 4677 | | |
| 4678 | | for (liveness_condbr.then_deaths) |operand| { |
| 4679 | | try die(f, inst, Air.indexToRef(operand)); |
| 4680 | | } |
| 4681 | | |
| 4682 | 4643 | try writer.writeAll("if ("); |
| 4683 | 4644 | try f.writeCValue(writer, cond, .Other); |
| 4684 | 4645 | try writer.writeAll(") "); |
| 4685 | | try genBody(f, then_body); |
| 4686 | 4646 | |
| 4687 | | // TODO: If body ends in goto, elide the else block? |
| 4688 | | const needs_else = then_body.len <= 0 or f.air.instructions.items(.tag)[then_body[then_body.len - 1]] != .br; |
| 4689 | | if (needs_else) { |
| 4690 | | try writer.writeAll(" else "); |
| 4691 | | } else { |
| 4692 | | try writer.writeByte('\n'); |
| 4693 | | } |
| 4647 | try genBodyResolveState(f, inst, liveness_condbr.then_deaths, then_body, false); |
| 4694 | 4648 | |
| 4695 | | f.value_map.deinit(); |
| 4696 | | f.value_map = cloned_map.move(); |
| 4697 | | const free_locals = &f.free_locals_map; |
| 4698 | | deinitFreeLocalsMap(gpa, free_locals); |
| 4699 | | free_locals.* = cloned_frees.move(); |
| 4700 | | f.is_in_clone = was_in_clone; |
| 4701 | | for (liveness_condbr.else_deaths) |operand| { |
| 4702 | | try die(f, inst, Air.indexToRef(operand)); |
| 4703 | | } |
| 4704 | | |
| 4705 | | try noticeBranchFrees(f, pre_locals_len, pre_allocs_len, inst); |
| 4649 | // We don't need to use `genBodyResolveState` for the else block, because this instruction is |
| 4650 | // noreturn so must terminate a body, therefore we don't need to leave `value_map` or |
| 4651 | // `free_locals_map` well defined (our parent is responsible for doing that). |
| 4706 | 4652 | |
| 4707 | | if (needs_else) { |
| 4708 | | try genBody(f, else_body); |
| 4709 | | } else { |
| 4710 | | try genBodyInner(f, else_body); |
| 4653 | for (liveness_condbr.else_deaths) |death| { |
| 4654 | try die(f, inst, Air.indexToRef(death)); |
| 4711 | 4655 | } |
| 4712 | 4656 | |
| 4713 | | try f.object.indent_writer.insertNewline(); |
| 4657 | // We never actually need an else block, because our branches are noreturn so must (for |
| 4658 | // instance) `br` to a block (label). |
| 4659 | |
| 4660 | try genBodyInner(f, else_body); |
| 4714 | 4661 | |
| 4715 | 4662 | return .none; |
| 4716 | 4663 | } |
| ... | ... | @@ -4741,9 +4688,8 @@ fn airSwitchBr(f: *Function, inst: Air.Inst.Index) !CValue { |
| 4741 | 4688 | const liveness = try f.liveness.getSwitchBr(gpa, inst, switch_br.data.cases_len + 1); |
| 4742 | 4689 | defer gpa.free(liveness.deaths); |
| 4743 | 4690 | |
| 4744 | | // On the final iteration we do not clone the map. This ensures that |
| 4745 | | // lowering proceeds after the switch_br taking into account the |
| 4746 | | // mutations to the liveness information. |
| 4691 | // On the final iteration we do not need to fix any state. This is because, like in the `else` |
| 4692 | // branch of a `cond_br`, our parent has to do it for this entire body anyway. |
| 4747 | 4693 | const last_case_i = switch_br.data.cases_len - @boolToInt(switch_br.data.else_body_len == 0); |
| 4748 | 4694 | |
| 4749 | 4695 | var extra_index: usize = switch_br.end; |
| ... | ... | @@ -4767,56 +4713,23 @@ fn airSwitchBr(f: *Function, inst: Air.Inst.Index) !CValue { |
| 4767 | 4713 | try writer.writeByte(' '); |
| 4768 | 4714 | |
| 4769 | 4715 | if (case_i != last_case_i) { |
| 4770 | | const old_value_map = f.value_map; |
| 4771 | | f.value_map = try old_value_map.clone(); |
| 4772 | | var free_locals = &f.free_locals_map; |
| 4773 | | const old_free_locals = free_locals.*; |
| 4774 | | free_locals.* = try cloneFreeLocalsMap(gpa, free_locals); |
| 4775 | | |
| 4776 | | // Remember how many locals there were before entering each branch so that |
| 4777 | | // we can notice and use them in subsequent branches. Any new locals must |
| 4778 | | // necessarily be free already after the previous branch is complete. |
| 4779 | | const pre_locals_len = @intCast(LocalIndex, f.locals.items.len); |
| 4780 | | // Remember how many allocs there were before entering each branch so that |
| 4781 | | // we can notice and make sure not to use them in subsequent branches. |
| 4782 | | // Any new allocs must be removed from the free list. |
| 4783 | | const pre_allocs_len = @intCast(LocalIndex, f.allocs.count()); |
| 4784 | | const was_in_clone = f.is_in_clone; |
| 4785 | | f.is_in_clone = true; |
| 4786 | | |
| 4787 | | { |
| 4788 | | defer { |
| 4789 | | f.is_in_clone = was_in_clone; |
| 4790 | | f.value_map.deinit(); |
| 4791 | | deinitFreeLocalsMap(gpa, free_locals); |
| 4792 | | f.value_map = old_value_map; |
| 4793 | | free_locals.* = old_free_locals; |
| 4794 | | } |
| 4795 | | |
| 4796 | | for (liveness.deaths[case_i]) |operand| { |
| 4797 | | try die(f, inst, Air.indexToRef(operand)); |
| 4798 | | } |
| 4799 | | |
| 4800 | | try genBody(f, case_body); |
| 4801 | | } |
| 4802 | | |
| 4803 | | try noticeBranchFrees(f, pre_locals_len, pre_allocs_len, inst); |
| 4716 | try genBodyResolveState(f, inst, liveness.deaths[case_i], case_body, false); |
| 4804 | 4717 | } else { |
| 4805 | | for (liveness.deaths[case_i]) |operand| { |
| 4806 | | try die(f, inst, Air.indexToRef(operand)); |
| 4718 | for (liveness.deaths[case_i]) |death| { |
| 4719 | try die(f, inst, Air.indexToRef(death)); |
| 4807 | 4720 | } |
| 4808 | 4721 | try genBody(f, case_body); |
| 4809 | 4722 | } |
| 4810 | 4723 | |
| 4811 | 4724 | // The case body must be noreturn so we don't need to insert a break. |
| 4812 | | |
| 4813 | 4725 | } |
| 4814 | 4726 | |
| 4815 | 4727 | const else_body = f.air.extra[extra_index..][0..switch_br.data.else_body_len]; |
| 4816 | 4728 | try f.object.indent_writer.insertNewline(); |
| 4817 | 4729 | if (else_body.len > 0) { |
| 4818 | | for (liveness.deaths[liveness.deaths.len - 1]) |operand| { |
| 4819 | | try die(f, inst, Air.indexToRef(operand)); |
| 4730 | // Note that this must be the last case (i.e. the `last_case_i` case was not hit above) |
| 4731 | for (liveness.deaths[liveness.deaths.len - 1]) |death| { |
| 4732 | try die(f, inst, Air.indexToRef(death)); |
| 4820 | 4733 | } |
| 4821 | 4734 | try writer.writeAll("default: "); |
| 4822 | 4735 | try genBody(f, else_body); |
| ... | ... | @@ -4843,6 +4756,7 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue { |
| 4843 | 4756 | const extra = f.air.extraData(Air.Asm, ty_pl.payload); |
| 4844 | 4757 | const is_volatile = @truncate(u1, extra.data.flags >> 31) != 0; |
| 4845 | 4758 | const clobbers_len = @truncate(u31, extra.data.flags); |
| 4759 | const gpa = f.object.dg.gpa; |
| 4846 | 4760 | var extra_i: usize = extra.end; |
| 4847 | 4761 | const outputs = @ptrCast([]const Air.Inst.Ref, f.air.extra[extra_i..][0..extra.data.outputs_len]); |
| 4848 | 4762 | extra_i += outputs.len; |
| ... | ... | @@ -4850,8 +4764,6 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue { |
| 4850 | 4764 | extra_i += inputs.len; |
| 4851 | 4765 | |
| 4852 | 4766 | const result = result: { |
| 4853 | | if (!is_volatile and f.liveness.isUnused(inst)) break :result .none; |
| 4854 | | |
| 4855 | 4767 | const writer = f.object.writer(); |
| 4856 | 4768 | const inst_ty = f.air.typeOfIndex(inst); |
| 4857 | 4769 | const local = if (inst_ty.hasRuntimeBitsIgnoreComptime()) local: { |
| ... | ... | @@ -4887,6 +4799,7 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue { |
| 4887 | 4799 | try writer.writeAll("register "); |
| 4888 | 4800 | const alignment = 0; |
| 4889 | 4801 | const local_value = try f.allocLocalValue(output_ty, alignment); |
| 4802 | try f.allocs.put(gpa, local_value.new_local, false); |
| 4890 | 4803 | try f.object.dg.renderTypeAndName(writer, output_ty, local_value, .{}, alignment, .complete); |
| 4891 | 4804 | try writer.writeAll(" __asm(\""); |
| 4892 | 4805 | try writer.writeAll(constraint["={".len .. constraint.len - "}".len]); |
| ... | ... | @@ -4919,6 +4832,7 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue { |
| 4919 | 4832 | if (is_reg) try writer.writeAll("register "); |
| 4920 | 4833 | const alignment = 0; |
| 4921 | 4834 | const local_value = try f.allocLocalValue(input_ty, alignment); |
| 4835 | try f.allocs.put(gpa, local_value.new_local, false); |
| 4922 | 4836 | try f.object.dg.renderTypeAndName(writer, input_ty, local_value, Const, alignment, .complete); |
| 4923 | 4837 | if (is_reg) { |
| 4924 | 4838 | try writer.writeAll(" __asm(\""); |
| ... | ... | @@ -5101,11 +5015,6 @@ fn airIsNull( |
| 5101 | 5015 | ) !CValue { |
| 5102 | 5016 | const un_op = f.air.instructions.items(.data)[inst].un_op; |
| 5103 | 5017 | |
| 5104 | | if (f.liveness.isUnused(inst)) { |
| 5105 | | try reap(f, inst, &.{un_op}); |
| 5106 | | return .none; |
| 5107 | | } |
| 5108 | | |
| 5109 | 5018 | const writer = f.object.writer(); |
| 5110 | 5019 | const operand = try f.resolveInst(un_op); |
| 5111 | 5020 | try reap(f, inst, &.{un_op}); |
| ... | ... | @@ -5151,11 +5060,6 @@ fn airIsNull( |
| 5151 | 5060 | fn airOptionalPayload(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5152 | 5061 | const ty_op = f.air.instructions.items(.data)[inst].ty_op; |
| 5153 | 5062 | |
| 5154 | | if (f.liveness.isUnused(inst)) { |
| 5155 | | try reap(f, inst, &.{ty_op.operand}); |
| 5156 | | return .none; |
| 5157 | | } |
| 5158 | | |
| 5159 | 5063 | const operand = try f.resolveInst(ty_op.operand); |
| 5160 | 5064 | try reap(f, inst, &.{ty_op.operand}); |
| 5161 | 5065 | const opt_ty = f.air.typeOf(ty_op.operand); |
| ... | ... | @@ -5203,11 +5107,6 @@ fn airOptionalPayload(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5203 | 5107 | fn airOptionalPayloadPtr(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5204 | 5108 | const ty_op = f.air.instructions.items(.data)[inst].ty_op; |
| 5205 | 5109 | |
| 5206 | | if (f.liveness.isUnused(inst)) { |
| 5207 | | try reap(f, inst, &.{ty_op.operand}); |
| 5208 | | return .none; |
| 5209 | | } |
| 5210 | | |
| 5211 | 5110 | const writer = f.object.writer(); |
| 5212 | 5111 | const operand = try f.resolveInst(ty_op.operand); |
| 5213 | 5112 | try reap(f, inst, &.{ty_op.operand}); |
| ... | ... | @@ -5337,11 +5236,6 @@ fn airStructFieldPtr(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5337 | 5236 | const ty_pl = f.air.instructions.items(.data)[inst].ty_pl; |
| 5338 | 5237 | const extra = f.air.extraData(Air.StructField, ty_pl.payload).data; |
| 5339 | 5238 | |
| 5340 | | if (f.liveness.isUnused(inst)) { |
| 5341 | | try reap(f, inst, &.{extra.struct_operand}); |
| 5342 | | return .none; |
| 5343 | | } |
| 5344 | | |
| 5345 | 5239 | const container_ptr_val = try f.resolveInst(extra.struct_operand); |
| 5346 | 5240 | try reap(f, inst, &.{extra.struct_operand}); |
| 5347 | 5241 | const container_ptr_ty = f.air.typeOf(extra.struct_operand); |
| ... | ... | @@ -5351,11 +5245,6 @@ fn airStructFieldPtr(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5351 | 5245 | fn airStructFieldPtrIndex(f: *Function, inst: Air.Inst.Index, index: u8) !CValue { |
| 5352 | 5246 | const ty_op = f.air.instructions.items(.data)[inst].ty_op; |
| 5353 | 5247 | |
| 5354 | | if (f.liveness.isUnused(inst)) { |
| 5355 | | try reap(f, inst, &.{ty_op.operand}); |
| 5356 | | return .none; |
| 5357 | | } |
| 5358 | | |
| 5359 | 5248 | const container_ptr_val = try f.resolveInst(ty_op.operand); |
| 5360 | 5249 | try reap(f, inst, &.{ty_op.operand}); |
| 5361 | 5250 | const container_ptr_ty = f.air.typeOf(ty_op.operand); |
| ... | ... | @@ -5366,11 +5255,6 @@ fn airFieldParentPtr(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5366 | 5255 | const ty_pl = f.air.instructions.items(.data)[inst].ty_pl; |
| 5367 | 5256 | const extra = f.air.extraData(Air.FieldParentPtr, ty_pl.payload).data; |
| 5368 | 5257 | |
| 5369 | | if (f.liveness.isUnused(inst)) { |
| 5370 | | try reap(f, inst, &.{extra.field_ptr}); |
| 5371 | | return .none; |
| 5372 | | } |
| 5373 | | |
| 5374 | 5258 | const target = f.object.dg.module.getTarget(); |
| 5375 | 5259 | const container_ptr_ty = f.air.typeOfIndex(inst); |
| 5376 | 5260 | const container_ty = container_ptr_ty.childType(); |
| ... | ... | @@ -5489,11 +5373,6 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5489 | 5373 | const ty_pl = f.air.instructions.items(.data)[inst].ty_pl; |
| 5490 | 5374 | const extra = f.air.extraData(Air.StructField, ty_pl.payload).data; |
| 5491 | 5375 | |
| 5492 | | if (f.liveness.isUnused(inst)) { |
| 5493 | | try reap(f, inst, &.{extra.struct_operand}); |
| 5494 | | return .none; |
| 5495 | | } |
| 5496 | | |
| 5497 | 5376 | const inst_ty = f.air.typeOfIndex(inst); |
| 5498 | 5377 | if (!inst_ty.hasRuntimeBitsIgnoreComptime()) { |
| 5499 | 5378 | try reap(f, inst, &.{extra.struct_operand}); |
| ... | ... | @@ -5639,11 +5518,6 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5639 | 5518 | fn airUnwrapErrUnionErr(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5640 | 5519 | const ty_op = f.air.instructions.items(.data)[inst].ty_op; |
| 5641 | 5520 | |
| 5642 | | if (f.liveness.isUnused(inst)) { |
| 5643 | | try reap(f, inst, &.{ty_op.operand}); |
| 5644 | | return .none; |
| 5645 | | } |
| 5646 | | |
| 5647 | 5521 | const inst_ty = f.air.typeOfIndex(inst); |
| 5648 | 5522 | const operand = try f.resolveInst(ty_op.operand); |
| 5649 | 5523 | const operand_ty = f.air.typeOf(ty_op.operand); |
| ... | ... | @@ -5676,11 +5550,6 @@ fn airUnwrapErrUnionErr(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5676 | 5550 | fn airUnwrapErrUnionPay(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !CValue { |
| 5677 | 5551 | const ty_op = f.air.instructions.items(.data)[inst].ty_op; |
| 5678 | 5552 | |
| 5679 | | if (f.liveness.isUnused(inst)) { |
| 5680 | | try reap(f, inst, &.{ty_op.operand}); |
| 5681 | | return .none; |
| 5682 | | } |
| 5683 | | |
| 5684 | 5553 | const inst_ty = f.air.typeOfIndex(inst); |
| 5685 | 5554 | const operand = try f.resolveInst(ty_op.operand); |
| 5686 | 5555 | try reap(f, inst, &.{ty_op.operand}); |
| ... | ... | @@ -5718,11 +5587,6 @@ fn airUnwrapErrUnionPay(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !CValu |
| 5718 | 5587 | fn airWrapOptional(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5719 | 5588 | const ty_op = f.air.instructions.items(.data)[inst].ty_op; |
| 5720 | 5589 | |
| 5721 | | if (f.liveness.isUnused(inst)) { |
| 5722 | | try reap(f, inst, &.{ty_op.operand}); |
| 5723 | | return .none; |
| 5724 | | } |
| 5725 | | |
| 5726 | 5590 | const inst_ty = f.air.typeOfIndex(inst); |
| 5727 | 5591 | const payload = try f.resolveInst(ty_op.operand); |
| 5728 | 5592 | try reap(f, inst, &.{ty_op.operand}); |
| ... | ... | @@ -5764,10 +5628,6 @@ fn airWrapOptional(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5764 | 5628 | |
| 5765 | 5629 | fn airWrapErrUnionErr(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5766 | 5630 | const ty_op = f.air.instructions.items(.data)[inst].ty_op; |
| 5767 | | if (f.liveness.isUnused(inst)) { |
| 5768 | | try reap(f, inst, &.{ty_op.operand}); |
| 5769 | | return .none; |
| 5770 | | } |
| 5771 | 5631 | |
| 5772 | 5632 | const writer = f.object.writer(); |
| 5773 | 5633 | const operand = try f.resolveInst(ty_op.operand); |
| ... | ... | @@ -5831,7 +5691,7 @@ fn airErrUnionPayloadPtrSet(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5831 | 5691 | } |
| 5832 | 5692 | |
| 5833 | 5693 | fn airErrReturnTrace(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5834 | | if (f.liveness.isUnused(inst)) return .none; |
| 5694 | _ = inst; |
| 5835 | 5695 | return f.fail("TODO: C backend: implement airErrReturnTrace", .{}); |
| 5836 | 5696 | } |
| 5837 | 5697 | |
| ... | ... | @@ -5847,10 +5707,6 @@ fn airSaveErrReturnTraceIndex(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5847 | 5707 | |
| 5848 | 5708 | fn airWrapErrUnionPay(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5849 | 5709 | const ty_op = f.air.instructions.items(.data)[inst].ty_op; |
| 5850 | | if (f.liveness.isUnused(inst)) { |
| 5851 | | try reap(f, inst, &.{ty_op.operand}); |
| 5852 | | return .none; |
| 5853 | | } |
| 5854 | 5710 | |
| 5855 | 5711 | const inst_ty = f.air.typeOfIndex(inst); |
| 5856 | 5712 | const payload_ty = inst_ty.errorUnionPayload(); |
| ... | ... | @@ -5885,11 +5741,6 @@ fn airWrapErrUnionPay(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5885 | 5741 | fn airIsErr(f: *Function, inst: Air.Inst.Index, is_ptr: bool, operator: []const u8) !CValue { |
| 5886 | 5742 | const un_op = f.air.instructions.items(.data)[inst].un_op; |
| 5887 | 5743 | |
| 5888 | | if (f.liveness.isUnused(inst)) { |
| 5889 | | try reap(f, inst, &.{un_op}); |
| 5890 | | return .none; |
| 5891 | | } |
| 5892 | | |
| 5893 | 5744 | const writer = f.object.writer(); |
| 5894 | 5745 | const operand = try f.resolveInst(un_op); |
| 5895 | 5746 | try reap(f, inst, &.{un_op}); |
| ... | ... | @@ -5923,11 +5774,6 @@ fn airIsErr(f: *Function, inst: Air.Inst.Index, is_ptr: bool, operator: []const |
| 5923 | 5774 | fn airArrayToSlice(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5924 | 5775 | const ty_op = f.air.instructions.items(.data)[inst].ty_op; |
| 5925 | 5776 | |
| 5926 | | if (f.liveness.isUnused(inst)) { |
| 5927 | | try reap(f, inst, &.{ty_op.operand}); |
| 5928 | | return .none; |
| 5929 | | } |
| 5930 | | |
| 5931 | 5777 | const operand = try f.resolveInst(ty_op.operand); |
| 5932 | 5778 | try reap(f, inst, &.{ty_op.operand}); |
| 5933 | 5779 | const inst_ty = f.air.typeOfIndex(inst); |
| ... | ... | @@ -5961,11 +5807,6 @@ fn airArrayToSlice(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5961 | 5807 | fn airFloatCast(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5962 | 5808 | const ty_op = f.air.instructions.items(.data)[inst].ty_op; |
| 5963 | 5809 | |
| 5964 | | if (f.liveness.isUnused(inst)) { |
| 5965 | | try reap(f, inst, &.{ty_op.operand}); |
| 5966 | | return .none; |
| 5967 | | } |
| 5968 | | |
| 5969 | 5810 | const inst_ty = f.air.typeOfIndex(inst); |
| 5970 | 5811 | const operand = try f.resolveInst(ty_op.operand); |
| 5971 | 5812 | try reap(f, inst, &.{ty_op.operand}); |
| ... | ... | @@ -6009,11 +5850,6 @@ fn airFloatCast(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6009 | 5850 | fn airPtrToInt(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6010 | 5851 | const un_op = f.air.instructions.items(.data)[inst].un_op; |
| 6011 | 5852 | |
| 6012 | | if (f.liveness.isUnused(inst)) { |
| 6013 | | try reap(f, inst, &.{un_op}); |
| 6014 | | return .none; |
| 6015 | | } |
| 6016 | | |
| 6017 | 5853 | const operand = try f.resolveInst(un_op); |
| 6018 | 5854 | try reap(f, inst, &.{un_op}); |
| 6019 | 5855 | const inst_ty = f.air.typeOfIndex(inst); |
| ... | ... | @@ -6037,11 +5873,6 @@ fn airUnBuiltinCall( |
| 6037 | 5873 | ) !CValue { |
| 6038 | 5874 | const ty_op = f.air.instructions.items(.data)[inst].ty_op; |
| 6039 | 5875 | |
| 6040 | | if (f.liveness.isUnused(inst)) { |
| 6041 | | try reap(f, inst, &.{ty_op.operand}); |
| 6042 | | return .none; |
| 6043 | | } |
| 6044 | | |
| 6045 | 5876 | const operand = try f.resolveInst(ty_op.operand); |
| 6046 | 5877 | try reap(f, inst, &.{ty_op.operand}); |
| 6047 | 5878 | const inst_ty = f.air.typeOfIndex(inst); |
| ... | ... | @@ -6085,11 +5916,6 @@ fn airBinBuiltinCall( |
| 6085 | 5916 | ) !CValue { |
| 6086 | 5917 | const bin_op = f.air.instructions.items(.data)[inst].bin_op; |
| 6087 | 5918 | |
| 6088 | | if (f.liveness.isUnused(inst)) { |
| 6089 | | try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); |
| 6090 | | return .none; |
| 6091 | | } |
| 6092 | | |
| 6093 | 5919 | const operand_ty = f.air.typeOf(bin_op.lhs); |
| 6094 | 5920 | const operand_cty = try f.typeToCType(operand_ty, .complete); |
| 6095 | 5921 | const is_big = operand_cty.tag() == .array; |
| ... | ... | @@ -6142,11 +5968,6 @@ fn airCmpBuiltinCall( |
| 6142 | 5968 | operation: enum { cmp, operator }, |
| 6143 | 5969 | info: BuiltinInfo, |
| 6144 | 5970 | ) !CValue { |
| 6145 | | if (f.liveness.isUnused(inst)) { |
| 6146 | | try reap(f, inst, &.{ data.lhs, data.rhs }); |
| 6147 | | return .none; |
| 6148 | | } |
| 6149 | | |
| 6150 | 5971 | const lhs = try f.resolveInst(data.lhs); |
| 6151 | 5972 | const rhs = try f.resolveInst(data.rhs); |
| 6152 | 5973 | try reap(f, inst, &.{ data.lhs, data.rhs }); |
| ... | ... | @@ -6317,9 +6138,6 @@ fn airAtomicLoad(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6317 | 6138 | const ptr = try f.resolveInst(atomic_load.ptr); |
| 6318 | 6139 | try reap(f, inst, &.{atomic_load.ptr}); |
| 6319 | 6140 | const ptr_ty = f.air.typeOf(atomic_load.ptr); |
| 6320 | | if (!ptr_ty.isVolatilePtr() and f.liveness.isUnused(inst)) { |
| 6321 | | return .none; |
| 6322 | | } |
| 6323 | 6141 | |
| 6324 | 6142 | const inst_ty = f.air.typeOfIndex(inst); |
| 6325 | 6143 | const writer = f.object.writer(); |
| ... | ... | @@ -6463,11 +6281,6 @@ fn airSetUnionTag(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6463 | 6281 | fn airGetUnionTag(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6464 | 6282 | const ty_op = f.air.instructions.items(.data)[inst].ty_op; |
| 6465 | 6283 | |
| 6466 | | if (f.liveness.isUnused(inst)) { |
| 6467 | | try reap(f, inst, &.{ty_op.operand}); |
| 6468 | | return .none; |
| 6469 | | } |
| 6470 | | |
| 6471 | 6284 | const operand = try f.resolveInst(ty_op.operand); |
| 6472 | 6285 | try reap(f, inst, &.{ty_op.operand}); |
| 6473 | 6286 | |
| ... | ... | @@ -6491,11 +6304,6 @@ fn airGetUnionTag(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6491 | 6304 | fn airTagName(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6492 | 6305 | const un_op = f.air.instructions.items(.data)[inst].un_op; |
| 6493 | 6306 | |
| 6494 | | if (f.liveness.isUnused(inst)) { |
| 6495 | | try reap(f, inst, &.{un_op}); |
| 6496 | | return .none; |
| 6497 | | } |
| 6498 | | |
| 6499 | 6307 | const inst_ty = f.air.typeOfIndex(inst); |
| 6500 | 6308 | const enum_ty = f.air.typeOf(un_op); |
| 6501 | 6309 | const operand = try f.resolveInst(un_op); |
| ... | ... | @@ -6516,11 +6324,6 @@ fn airTagName(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6516 | 6324 | fn airErrorName(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6517 | 6325 | const un_op = f.air.instructions.items(.data)[inst].un_op; |
| 6518 | 6326 | |
| 6519 | | if (f.liveness.isUnused(inst)) { |
| 6520 | | try reap(f, inst, &.{un_op}); |
| 6521 | | return .none; |
| 6522 | | } |
| 6523 | | |
| 6524 | 6327 | const writer = f.object.writer(); |
| 6525 | 6328 | const inst_ty = f.air.typeOfIndex(inst); |
| 6526 | 6329 | const operand = try f.resolveInst(un_op); |
| ... | ... | @@ -6537,11 +6340,6 @@ fn airErrorName(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6537 | 6340 | fn airSplat(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6538 | 6341 | const ty_op = f.air.instructions.items(.data)[inst].ty_op; |
| 6539 | 6342 | |
| 6540 | | if (f.liveness.isUnused(inst)) { |
| 6541 | | try reap(f, inst, &.{ty_op.operand}); |
| 6542 | | return .none; |
| 6543 | | } |
| 6544 | | |
| 6545 | 6343 | const operand = try f.resolveInst(ty_op.operand); |
| 6546 | 6344 | try reap(f, inst, &.{ty_op.operand}); |
| 6547 | 6345 | |
| ... | ... | @@ -6573,11 +6371,6 @@ fn airSelect(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6573 | 6371 | const pl_op = f.air.instructions.items(.data)[inst].pl_op; |
| 6574 | 6372 | const extra = f.air.extraData(Air.Bin, pl_op.payload).data; |
| 6575 | 6373 | |
| 6576 | | if (f.liveness.isUnused(inst)) { |
| 6577 | | try reap(f, inst, &.{ pl_op.operand, extra.lhs, extra.rhs }); |
| 6578 | | return .none; |
| 6579 | | } |
| 6580 | | |
| 6581 | 6374 | const pred = try f.resolveInst(pl_op.operand); |
| 6582 | 6375 | const lhs = try f.resolveInst(extra.lhs); |
| 6583 | 6376 | const rhs = try f.resolveInst(extra.rhs); |
| ... | ... | @@ -6609,11 +6402,6 @@ fn airShuffle(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6609 | 6402 | const ty_pl = f.air.instructions.items(.data)[inst].ty_pl; |
| 6610 | 6403 | const extra = f.air.extraData(Air.Shuffle, ty_pl.payload).data; |
| 6611 | 6404 | |
| 6612 | | if (f.liveness.isUnused(inst)) { |
| 6613 | | try reap(f, inst, &.{ extra.a, extra.b }); |
| 6614 | | return .none; |
| 6615 | | } |
| 6616 | | |
| 6617 | 6405 | const mask = f.air.values[extra.mask]; |
| 6618 | 6406 | const lhs = try f.resolveInst(extra.a); |
| 6619 | 6407 | const rhs = try f.resolveInst(extra.b); |
| ... | ... | @@ -6655,11 +6443,6 @@ fn airShuffle(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6655 | 6443 | fn airReduce(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6656 | 6444 | const reduce = f.air.instructions.items(.data)[inst].reduce; |
| 6657 | 6445 | |
| 6658 | | if (f.liveness.isUnused(inst)) { |
| 6659 | | try reap(f, inst, &.{reduce.operand}); |
| 6660 | | return .none; |
| 6661 | | } |
| 6662 | | |
| 6663 | 6446 | const target = f.object.dg.module.getTarget(); |
| 6664 | 6447 | const scalar_ty = f.air.typeOfIndex(inst); |
| 6665 | 6448 | const operand = try f.resolveInst(reduce.operand); |
| ... | ... | @@ -6831,8 +6614,6 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6831 | 6614 | } |
| 6832 | 6615 | } |
| 6833 | 6616 | |
| 6834 | | if (f.liveness.isUnused(inst)) return .none; |
| 6835 | | |
| 6836 | 6617 | const target = f.object.dg.module.getTarget(); |
| 6837 | 6618 | |
| 6838 | 6619 | const writer = f.object.writer(); |
| ... | ... | @@ -6999,11 +6780,6 @@ fn airUnionInit(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6999 | 6780 | const ty_pl = f.air.instructions.items(.data)[inst].ty_pl; |
| 7000 | 6781 | const extra = f.air.extraData(Air.UnionInit, ty_pl.payload).data; |
| 7001 | 6782 | |
| 7002 | | if (f.liveness.isUnused(inst)) { |
| 7003 | | try reap(f, inst, &.{extra.init}); |
| 7004 | | return .none; |
| 7005 | | } |
| 7006 | | |
| 7007 | 6783 | const union_ty = f.air.typeOfIndex(inst); |
| 7008 | 6784 | const target = f.object.dg.module.getTarget(); |
| 7009 | 6785 | const union_obj = union_ty.cast(Type.Payload.Union).?.data; |
| ... | ... | @@ -7070,8 +6846,6 @@ fn airPrefetch(f: *Function, inst: Air.Inst.Index) !CValue { |
| 7070 | 6846 | } |
| 7071 | 6847 | |
| 7072 | 6848 | fn airWasmMemorySize(f: *Function, inst: Air.Inst.Index) !CValue { |
| 7073 | | if (f.liveness.isUnused(inst)) return .none; |
| 7074 | | |
| 7075 | 6849 | const pl_op = f.air.instructions.items(.data)[inst].pl_op; |
| 7076 | 6850 | |
| 7077 | 6851 | const writer = f.object.writer(); |
| ... | ... | @@ -7104,10 +6878,6 @@ fn airWasmMemoryGrow(f: *Function, inst: Air.Inst.Index) !CValue { |
| 7104 | 6878 | |
| 7105 | 6879 | fn airFloatNeg(f: *Function, inst: Air.Inst.Index) !CValue { |
| 7106 | 6880 | const un_op = f.air.instructions.items(.data)[inst].un_op; |
| 7107 | | if (f.liveness.isUnused(inst)) { |
| 7108 | | try reap(f, inst, &.{un_op}); |
| 7109 | | return .none; |
| 7110 | | } |
| 7111 | 6881 | |
| 7112 | 6882 | const operand = try f.resolveInst(un_op); |
| 7113 | 6883 | try reap(f, inst, &.{un_op}); |
| ... | ... | @@ -7133,10 +6903,6 @@ fn airFloatNeg(f: *Function, inst: Air.Inst.Index) !CValue { |
| 7133 | 6903 | |
| 7134 | 6904 | fn airUnFloatOp(f: *Function, inst: Air.Inst.Index, operation: []const u8) !CValue { |
| 7135 | 6905 | const un_op = f.air.instructions.items(.data)[inst].un_op; |
| 7136 | | if (f.liveness.isUnused(inst)) { |
| 7137 | | try reap(f, inst, &.{un_op}); |
| 7138 | | return .none; |
| 7139 | | } |
| 7140 | 6906 | |
| 7141 | 6907 | const operand = try f.resolveInst(un_op); |
| 7142 | 6908 | try reap(f, inst, &.{un_op}); |
| ... | ... | @@ -7164,10 +6930,6 @@ fn airUnFloatOp(f: *Function, inst: Air.Inst.Index, operation: []const u8) !CVal |
| 7164 | 6930 | |
| 7165 | 6931 | fn airBinFloatOp(f: *Function, inst: Air.Inst.Index, operation: []const u8) !CValue { |
| 7166 | 6932 | const bin_op = f.air.instructions.items(.data)[inst].bin_op; |
| 7167 | | if (f.liveness.isUnused(inst)) { |
| 7168 | | try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); |
| 7169 | | return .none; |
| 7170 | | } |
| 7171 | 6933 | |
| 7172 | 6934 | const lhs = try f.resolveInst(bin_op.lhs); |
| 7173 | 6935 | const rhs = try f.resolveInst(bin_op.rhs); |
| ... | ... | @@ -7200,10 +6962,6 @@ fn airBinFloatOp(f: *Function, inst: Air.Inst.Index, operation: []const u8) !CVa |
| 7200 | 6962 | fn airMulAdd(f: *Function, inst: Air.Inst.Index) !CValue { |
| 7201 | 6963 | const pl_op = f.air.instructions.items(.data)[inst].pl_op; |
| 7202 | 6964 | const bin_op = f.air.extraData(Air.Bin, pl_op.payload).data; |
| 7203 | | if (f.liveness.isUnused(inst)) { |
| 7204 | | try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs, pl_op.operand }); |
| 7205 | | return .none; |
| 7206 | | } |
| 7207 | 6965 | |
| 7208 | 6966 | const mulend1 = try f.resolveInst(bin_op.lhs); |
| 7209 | 6967 | const mulend2 = try f.resolveInst(bin_op.rhs); |
| ... | ... | @@ -7236,8 +6994,6 @@ fn airMulAdd(f: *Function, inst: Air.Inst.Index) !CValue { |
| 7236 | 6994 | } |
| 7237 | 6995 | |
| 7238 | 6996 | fn airCVaStart(f: *Function, inst: Air.Inst.Index) !CValue { |
| 7239 | | if (f.liveness.isUnused(inst)) return .none; |
| 7240 | | |
| 7241 | 6997 | const inst_ty = f.air.typeOfIndex(inst); |
| 7242 | 6998 | const fn_cty = try f.typeToCType(f.object.dg.decl.?.ty, .complete); |
| 7243 | 6999 | const param_len = fn_cty.castTag(.varargs_function).?.data.param_types.len; |
| ... | ... | @@ -7256,10 +7012,6 @@ fn airCVaStart(f: *Function, inst: Air.Inst.Index) !CValue { |
| 7256 | 7012 | |
| 7257 | 7013 | fn airCVaArg(f: *Function, inst: Air.Inst.Index) !CValue { |
| 7258 | 7014 | const ty_op = f.air.instructions.items(.data)[inst].ty_op; |
| 7259 | | if (f.liveness.isUnused(inst)) { |
| 7260 | | try reap(f, inst, &.{ty_op.operand}); |
| 7261 | | return .none; |
| 7262 | | } |
| 7263 | 7015 | |
| 7264 | 7016 | const inst_ty = f.air.typeOfIndex(inst); |
| 7265 | 7017 | const va_list = try f.resolveInst(ty_op.operand); |
| ... | ... | @@ -7291,10 +7043,6 @@ fn airCVaEnd(f: *Function, inst: Air.Inst.Index) !CValue { |
| 7291 | 7043 | |
| 7292 | 7044 | fn airCVaCopy(f: *Function, inst: Air.Inst.Index) !CValue { |
| 7293 | 7045 | const ty_op = f.air.instructions.items(.data)[inst].ty_op; |
| 7294 | | if (f.liveness.isUnused(inst)) { |
| 7295 | | try reap(f, inst, &.{ty_op.operand}); |
| 7296 | | return .none; |
| 7297 | | } |
| 7298 | 7046 | |
| 7299 | 7047 | const inst_ty = f.air.typeOfIndex(inst); |
| 7300 | 7048 | const va_list = try f.resolveInst(ty_op.operand); |
| ... | ... | @@ -7858,7 +7606,6 @@ fn freeLocal(f: *Function, inst: Air.Inst.Index, local_index: LocalIndex, ref_in |
| 7858 | 7606 | const gpa = f.object.dg.gpa; |
| 7859 | 7607 | const local = &f.locals.items[local_index]; |
| 7860 | 7608 | log.debug("%{d}: freeing t{d} (operand %{d})", .{ inst, local_index, ref_inst }); |
| 7861 | | if (f.is_in_clone != local.is_in_clone) return; |
| 7862 | 7609 | const gop = try f.free_locals_map.getOrPut(gpa, local.getType()); |
| 7863 | 7610 | if (!gop.found_existing) gop.value_ptr.* = .{}; |
| 7864 | 7611 | if (std.debug.runtime_safety) { |
| ... | ... | @@ -7916,35 +7663,3 @@ fn deinitFreeLocalsMap(gpa: mem.Allocator, map: *LocalsMap) void { |
| 7916 | 7663 | } |
| 7917 | 7664 | map.deinit(gpa); |
| 7918 | 7665 | } |
| 7919 | | |
| 7920 | | fn noticeBranchFrees( |
| 7921 | | f: *Function, |
| 7922 | | pre_locals_len: LocalIndex, |
| 7923 | | pre_allocs_len: LocalIndex, |
| 7924 | | inst: Air.Inst.Index, |
| 7925 | | ) !void { |
| 7926 | | for (f.locals.items[pre_locals_len..], pre_locals_len..) |*local, local_i| { |
| 7927 | | const local_index = @intCast(LocalIndex, local_i); |
| 7928 | | if (f.allocs.contains(local_index)) { |
| 7929 | | if (std.debug.runtime_safety) { |
| 7930 | | // new allocs are no longer freeable, so make sure they aren't in the free list |
| 7931 | | if (f.free_locals_map.getPtr(local.getType())) |locals_list| { |
| 7932 | | assert(!locals_list.contains(local_index)); |
| 7933 | | } |
| 7934 | | } |
| 7935 | | continue; |
| 7936 | | } |
| 7937 | | |
| 7938 | | // free cloned locals from other branches at current cloned-ness |
| 7939 | | std.debug.assert(local.is_in_clone or !f.is_in_clone); |
| 7940 | | local.is_in_clone = f.is_in_clone; |
| 7941 | | try freeLocal(f, inst, local_index, 0); |
| 7942 | | } |
| 7943 | | |
| 7944 | | for (f.allocs.keys()[pre_allocs_len..]) |local_i| { |
| 7945 | | const local_index = @intCast(LocalIndex, local_i); |
| 7946 | | const local = &f.locals.items[local_index]; |
| 7947 | | // new allocs are no longer freeable, so remove them from the free list |
| 7948 | | if (f.free_locals_map.getPtr(local.getType())) |locals_list| _ = locals_list.swapRemove(local_index); |
| 7949 | | } |
| 7950 | | } |