authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-12-01 18:14:54-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-12-04 15:57:40-07:00
log2a0efbee56b03d9deafaa7918433ea10b46305c9
tree29f2dd885e12a2acafacd821cbfdd0b2bb9f384b
parent46f4a97d051e630dfae75e3856c81ffd1c7811e3

Revert "cbe: reduce amount of temporary locals"

This reverts commit 15cc83e27ae8a1740d9b7e2ec14044903979a832.

1 files changed, 128 insertions(+), 163 deletions(-)

src/codegen/c.zig+128-163
...@@ -50,8 +50,6 @@ pub const CValue = union(enum) {...@@ -50,8 +50,6 @@ pub const CValue = union(enum) {
50 /// Render these bytes literally.50 /// Render these bytes literally.
51 /// TODO make this a [*:0]const u8 to save memory51 /// TODO make this a [*:0]const u8 to save memory
52 bytes: []const u8,52 bytes: []const u8,
53 /// Index of an instruction that should later be rendered inline.
54 inline_index: Air.Inst.Index,
55};53};
5654
57const BlockData = struct {55const BlockData = struct {
...@@ -81,7 +79,6 @@ const ValueRenderLocation = enum {...@@ -81,7 +79,6 @@ const ValueRenderLocation = enum {
81 FunctionArgument,79 FunctionArgument,
82 Initializer,80 Initializer,
83 Other,81 Other,
84 condition,
85};82};
8683
87const BuiltinInfo = enum {84const BuiltinInfo = enum {
...@@ -281,19 +278,6 @@ pub const Function = struct {...@@ -281,19 +278,6 @@ pub const Function = struct {
281 return result;278 return result;
282 }279 }
283280
284 fn resolveInstNoInline(f: *Function, inst: Air.Inst.Ref) !CValue {
285 const operand = try f.resolveInst(inst);
286 if (operand != .inline_index) return operand;
287
288 const inst_ty = f.air.typeOf(inst);
289 const writer = f.object.writer();
290 const local = try f.allocLocal(inst_ty, .Const);
291 try writer.writeAll(" = ");
292 try f.writeCValueInline(operand.inline_index);
293 try writer.writeAll(";\n");
294 return local;
295 }
296
297 fn wantSafety(f: *Function) bool {281 fn wantSafety(f: *Function) bool {
298 return switch (f.object.dg.module.optimizeMode()) {282 return switch (f.object.dg.module.optimizeMode()) {
299 .Debug, .ReleaseSafe => true,283 .Debug, .ReleaseSafe => true,
...@@ -329,74 +313,10 @@ pub const Function = struct {...@@ -329,74 +313,10 @@ pub const Function = struct {
329 .constant => |inst| {313 .constant => |inst| {
330 const ty = f.air.typeOf(inst);314 const ty = f.air.typeOf(inst);
331 const val = f.air.value(inst).?;315 const val = f.air.value(inst).?;
332 try f.object.dg.renderValue(w, ty, val, location);316 return f.object.dg.renderValue(w, ty, val, location);
333 },
334 .undef => |ty| try f.object.dg.renderValue(w, ty, Value.undef, location),
335 .inline_index => |node| {
336 if (location != .condition) try w.writeByte('(');
337 try f.writeCValueInline(node);
338 if (location != .condition) try w.writeByte(')');
339 },
340 else => try f.object.dg.writeCValue(w, c_value),
341 }
342 }
343
344 const E = error{ OutOfMemory, AnalysisFail };
345
346 fn writeCValueInline(f: *Function, inst: Air.Inst.Index) E!void {
347 switch (f.air.instructions.items(.tag)[inst]) {
348 // zig fmt: off
349 // TODO use a different strategy for add, sub, mul, div
350 // that communicates to the optimizer that wrapping is UB.
351 .add => try airBinOp(f, inst, "+", "add", .None),
352 .sub => try airBinOp(f, inst, "-", "sub", .None),
353 .mul => try airBinOp(f, inst, "*", "mul", .None),
354
355 .div_float => try airBinBuiltinCall(f, inst, "div", .None),
356
357 .div_trunc, .div_exact => try airBinOp(f, inst, "/", "div_trunc", .None),
358 .rem => {
359 const bin_op = f.air.instructions.items(.data)[inst].bin_op;
360 const lhs_ty = f.air.typeOf(bin_op.lhs);
361 // For binary operations @TypeOf(lhs)==@TypeOf(rhs),
362 // so we only check one.
363 if (lhs_ty.isInt())
364 try airBinOp(f, inst, "%", "rem", .None)
365 else
366 try airBinFloatOp(f, inst, "fmod");
367 },317 },
368 .div_floor => try airBinBuiltinCall(f, inst, "div_floor", .None),318 .undef => |ty| return f.object.dg.renderValue(w, ty, Value.undef, location),
369 .mod => try airBinBuiltinCall(f, inst, "mod", .None),319 else => return f.object.dg.writeCValue(w, c_value),
370
371 .addwrap => try airBinBuiltinCall(f, inst, "addw", .Bits),
372 .subwrap => try airBinBuiltinCall(f, inst, "subw", .Bits),
373 .mulwrap => try airBinBuiltinCall(f, inst, "mulw", .Bits),
374
375 .add_sat => try airBinBuiltinCall(f, inst, "adds", .Bits),
376 .sub_sat => try airBinBuiltinCall(f, inst, "subs", .Bits),
377 .mul_sat => try airBinBuiltinCall(f, inst, "muls", .Bits),
378 .shl_sat => try airBinBuiltinCall(f, inst, "shls", .Bits),
379
380 .min => try airMinMax(f, inst, '<', "fmin"),
381 .max => try airMinMax(f, inst, '>', "fmax"),
382
383 .cmp_gt => try airCmpOp(f, inst, ">", "gt"),
384 .cmp_gte => try airCmpOp(f, inst, ">=", "ge"),
385 .cmp_lt => try airCmpOp(f, inst, "<", "lt"),
386 .cmp_lte => try airCmpOp(f, inst, "<=", "le"),
387
388 .cmp_eq => try airEquality(f, inst, "((", "==", "eq"),
389 .cmp_neq => try airEquality(f, inst, "!((", "!=", "ne"),
390
391 .bool_and, .bit_and => try airBinOp(f, inst, "&", "and", .None),
392 .bool_or, .bit_or => try airBinOp(f, inst, "|", "or", .None),
393 .xor => try airBinOp(f, inst, "^", "xor", .None),
394 .shr, .shr_exact => try airBinBuiltinCall(f, inst, "shr", .None),
395 .shl, => try airBinBuiltinCall(f, inst, "shlw", .Bits),
396 .shl_exact => try airBinOp(f, inst, "<<", "shl", .None),
397 .not => try airNot (f, inst),
398 else => unreachable,
399 // zig fmt: on
400 }320 }
401 }321 }
402322
...@@ -2245,7 +2165,7 @@ pub const DeclGen = struct {...@@ -2245,7 +2165,7 @@ pub const DeclGen = struct {
22452165
2246 fn writeCValue(dg: *DeclGen, w: anytype, c_value: CValue) !void {2166 fn writeCValue(dg: *DeclGen, w: anytype, c_value: CValue) !void {
2247 switch (c_value) {2167 switch (c_value) {
2248 .none, .inline_index => unreachable,2168 .none => unreachable,
2249 .local => |i| return w.print("t{d}", .{i}),2169 .local => |i| return w.print("t{d}", .{i}),
2250 .local_ref => |i| return w.print("&t{d}", .{i}),2170 .local_ref => |i| return w.print("&t{d}", .{i}),
2251 .constant => unreachable,2171 .constant => unreachable,
...@@ -2264,7 +2184,7 @@ pub const DeclGen = struct {...@@ -2264,7 +2184,7 @@ pub const DeclGen = struct {
22642184
2265 fn writeCValueDeref(dg: *DeclGen, w: anytype, c_value: CValue) !void {2185 fn writeCValueDeref(dg: *DeclGen, w: anytype, c_value: CValue) !void {
2266 switch (c_value) {2186 switch (c_value) {
2267 .none, .inline_index => unreachable,2187 .none => unreachable,
2268 .local => |i| return w.print("(*t{d})", .{i}),2188 .local => |i| return w.print("(*t{d})", .{i}),
2269 .local_ref => |i| return w.print("t{d}", .{i}),2189 .local_ref => |i| return w.print("t{d}", .{i}),
2270 .constant => unreachable,2190 .constant => unreachable,
...@@ -2294,7 +2214,7 @@ pub const DeclGen = struct {...@@ -2294,7 +2214,7 @@ pub const DeclGen = struct {
22942214
2295 fn writeCValueDerefMember(dg: *DeclGen, writer: anytype, c_value: CValue, member: CValue) !void {2215 fn writeCValueDerefMember(dg: *DeclGen, writer: anytype, c_value: CValue, member: CValue) !void {
2296 switch (c_value) {2216 switch (c_value) {
2297 .none, .constant, .field, .undef, .inline_index => unreachable,2217 .none, .constant, .field, .undef => unreachable,
2298 .local, .arg, .decl, .identifier, .bytes => {2218 .local, .arg, .decl, .identifier, .bytes => {
2299 try dg.writeCValue(writer, c_value);2219 try dg.writeCValue(writer, c_value);
2300 try writer.writeAll("->");2220 try writer.writeAll("->");
...@@ -2633,26 +2553,37 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail,...@@ -2633,26 +2553,37 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail,
2633 .ptr_add => try airPtrAddSub(f, inst, '+'),2553 .ptr_add => try airPtrAddSub(f, inst, '+'),
2634 .ptr_sub => try airPtrAddSub(f, inst, '-'),2554 .ptr_sub => try airPtrAddSub(f, inst, '-'),
26352555
2636 .add => CValue{ .inline_index = inst },2556 // TODO use a different strategy for add, sub, mul, div
2637 .sub => CValue{ .inline_index = inst },2557 // that communicates to the optimizer that wrapping is UB.
2638 .mul => CValue{ .inline_index = inst },2558 .add => try airBinOp(f, inst, "+", "add", .None),
2559 .sub => try airBinOp(f, inst, "-", "sub", .None),
2560 .mul => try airBinOp(f, inst, "*", "mul", .None),
26392561
2640 .neg => try airFloatNeg(f, inst),2562 .neg => try airFloatNeg(f, inst),
2641 .div_float => CValue{ .inline_index = inst },2563 .div_float => try airBinBuiltinCall(f, inst, "div", .None),
26422564
2643 .div_trunc, .div_exact => CValue{ .inline_index = inst },2565 .div_trunc, .div_exact => try airBinOp(f, inst, "/", "div_trunc", .None),
2644 .rem => CValue{ .inline_index = inst },2566 .rem => blk: {
2645 .div_floor => CValue{ .inline_index = inst },2567 const bin_op = f.air.instructions.items(.data)[inst].bin_op;
2646 .mod => CValue{ .inline_index = inst },2568 const lhs_ty = f.air.typeOf(bin_op.lhs);
2569 // For binary operations @TypeOf(lhs)==@TypeOf(rhs),
2570 // so we only check one.
2571 break :blk if (lhs_ty.isInt())
2572 try airBinOp(f, inst, "%", "rem", .None)
2573 else
2574 try airBinFloatOp(f, inst, "fmod");
2575 },
2576 .div_floor => try airBinBuiltinCall(f, inst, "div_floor", .None),
2577 .mod => try airBinBuiltinCall(f, inst, "mod", .None),
26472578
2648 .addwrap => CValue{ .inline_index = inst },2579 .addwrap => try airBinBuiltinCall(f, inst, "addw", .Bits),
2649 .subwrap => CValue{ .inline_index = inst },2580 .subwrap => try airBinBuiltinCall(f, inst, "subw", .Bits),
2650 .mulwrap => CValue{ .inline_index = inst },2581 .mulwrap => try airBinBuiltinCall(f, inst, "mulw", .Bits),
26512582
2652 .add_sat => CValue{ .inline_index = inst },2583 .add_sat => try airBinBuiltinCall(f, inst, "adds", .Bits),
2653 .sub_sat => CValue{ .inline_index = inst },2584 .sub_sat => try airBinBuiltinCall(f, inst, "subs", .Bits),
2654 .mul_sat => CValue{ .inline_index = inst },2585 .mul_sat => try airBinBuiltinCall(f, inst, "muls", .Bits),
2655 .shl_sat => CValue{ .inline_index = inst },2586 .shl_sat => try airBinBuiltinCall(f, inst, "shls", .Bits),
26562587
2657 .sqrt,2588 .sqrt,
2658 .sin,2589 .sin,
...@@ -2677,30 +2608,30 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail,...@@ -2677,30 +2608,30 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail,
2677 .mul_with_overflow => try airOverflow(f, inst, "mul", .Bits),2608 .mul_with_overflow => try airOverflow(f, inst, "mul", .Bits),
2678 .shl_with_overflow => try airOverflow(f, inst, "shl", .Bits),2609 .shl_with_overflow => try airOverflow(f, inst, "shl", .Bits),
26792610
2680 .min => CValue{ .inline_index = inst },2611 .min => try airMinMax(f, inst, '<', "fmin"),
2681 .max => CValue{ .inline_index = inst },2612 .max => try airMinMax(f, inst, '>', "fmax"),
26822613
2683 .slice => try airSlice(f, inst),2614 .slice => try airSlice(f, inst),
26842615
2685 .cmp_gt => CValue{ .inline_index = inst },2616 .cmp_gt => try airCmpOp(f, inst, ">", "gt"),
2686 .cmp_gte => CValue{ .inline_index = inst },2617 .cmp_gte => try airCmpOp(f, inst, ">=", "ge"),
2687 .cmp_lt => CValue{ .inline_index = inst },2618 .cmp_lt => try airCmpOp(f, inst, "<", "lt"),
2688 .cmp_lte => CValue{ .inline_index = inst },2619 .cmp_lte => try airCmpOp(f, inst, "<=", "le"),
26892620
2690 .cmp_eq => CValue{ .inline_index = inst },2621 .cmp_eq => try airEquality(f, inst, "((", "==", "eq"),
2691 .cmp_neq => CValue{ .inline_index = inst },2622 .cmp_neq => try airEquality(f, inst, "!((", "!=", "ne"),
26922623
2693 .cmp_vector => return f.fail("TODO: C backend: implement cmp_vector", .{}),2624 .cmp_vector => return f.fail("TODO: C backend: implement cmp_vector", .{}),
2694 .cmp_lt_errors_len => try airCmpLtErrorsLen(f, inst),2625 .cmp_lt_errors_len => try airCmpLtErrorsLen(f, inst),
26952626
2696 // bool_and and bool_or are non-short-circuit operations2627 // bool_and and bool_or are non-short-circuit operations
2697 .bool_and, .bit_and => CValue{ .inline_index = inst },2628 .bool_and, .bit_and => try airBinOp(f, inst, "&", "and", .None),
2698 .bool_or, .bit_or => CValue{ .inline_index = inst },2629 .bool_or, .bit_or => try airBinOp(f, inst, "|", "or", .None),
2699 .xor => CValue{ .inline_index = inst },2630 .xor => try airBinOp(f, inst, "^", "xor", .None),
2700 .shr, .shr_exact => CValue{ .inline_index = inst },2631 .shr, .shr_exact => try airBinBuiltinCall(f, inst, "shr", .None),
2701 .shl, => CValue{ .inline_index = inst },2632 .shl, => try airBinBuiltinCall(f, inst, "shlw", .Bits),
2702 .shl_exact => CValue{ .inline_index = inst },2633 .shl_exact => try airBinOp(f, inst, "<<", "shl", .None),
2703 .not => CValue{ .inline_index = inst },2634 .not => try airNot (f, inst),
27042635
2705 .optional_payload => try airOptionalPayload(f, inst),2636 .optional_payload => try airOptionalPayload(f, inst),
2706 .optional_payload_ptr => try airOptionalPayloadPtr(f, inst),2637 .optional_payload_ptr => try airOptionalPayloadPtr(f, inst),
...@@ -3449,21 +3380,22 @@ fn airOverflow(f: *Function, inst: Air.Inst.Index, operation: []const u8, info:...@@ -3449,21 +3380,22 @@ fn airOverflow(f: *Function, inst: Air.Inst.Index, operation: []const u8, info:
3449 return local;3380 return local;
3450}3381}
34513382
3452fn airNot(f: *Function, inst: Air.Inst.Index) !void {3383fn airNot(f: *Function, inst: Air.Inst.Index) !CValue {
3384 if (f.liveness.isUnused(inst)) return CValue.none;
3385
3453 const ty_op = f.air.instructions.items(.data)[inst].ty_op;3386 const ty_op = f.air.instructions.items(.data)[inst].ty_op;
3454 const op = try f.resolveInst(ty_op.operand);3387 const op = try f.resolveInst(ty_op.operand);
34553388
3456 const writer = f.object.writer();3389 const writer = f.object.writer();
3457 const inst_ty = f.air.typeOfIndex(inst);3390 const inst_ty = f.air.typeOfIndex(inst);
3391 const local = try f.allocLocal(inst_ty, .Const);
34583392
3459 const target = f.object.dg.module.getTarget();3393 try writer.writeAll(" = ");
3460 if (inst_ty.bitSize(target) > 64) {}
3461
3462 try writer.writeByte('(');
3463 try f.renderTypecast(writer, inst_ty);
3464 try writer.writeByte(')');
3465 try writer.writeByte(if (inst_ty.tag() == .bool) '!' else '~');3394 try writer.writeByte(if (inst_ty.tag() == .bool) '!' else '~');
3466 try f.writeCValue(writer, op, .Other);3395 try f.writeCValue(writer, op, .Other);
3396 try writer.writeAll(";\n");
3397
3398 return local;
3467}3399}
34683400
3469fn airBinOp(3401fn airBinOp(
...@@ -3472,54 +3404,62 @@ fn airBinOp(...@@ -3472,54 +3404,62 @@ fn airBinOp(
3472 operator: []const u8,3404 operator: []const u8,
3473 operation: []const u8,3405 operation: []const u8,
3474 info: BuiltinInfo,3406 info: BuiltinInfo,
3475) !void {3407) !CValue {
3408 if (f.liveness.isUnused(inst)) return CValue.none;
3409
3476 const bin_op = f.air.instructions.items(.data)[inst].bin_op;3410 const bin_op = f.air.instructions.items(.data)[inst].bin_op;
34773411
3478 const operand_ty = f.air.typeOf(bin_op.lhs);3412 const operand_ty = f.air.typeOf(bin_op.lhs);
3479 const target = f.object.dg.module.getTarget();3413 const target = f.object.dg.module.getTarget();
3480 if ((operand_ty.isInt() and operand_ty.bitSize(target) > 64) or operand_ty.isRuntimeFloat())3414 if ((operand_ty.isInt() and operand_ty.bitSize(target) > 64) or operand_ty.isRuntimeFloat())
3481 return airBinBuiltinCall(f, inst, operation, info);3415 return try airBinBuiltinCall(f, inst, operation, info);
34823416
3483 const inst_ty = f.air.typeOfIndex(inst);3417 const inst_ty = f.air.typeOfIndex(inst);
3484 const lhs = try f.resolveInst(bin_op.lhs);3418 const lhs = try f.resolveInst(bin_op.lhs);
3485 const rhs = try f.resolveInst(bin_op.rhs);3419 const rhs = try f.resolveInst(bin_op.rhs);
34863420
3487 const writer = f.object.writer();3421 const writer = f.object.writer();
3488 try writer.writeByte('(');3422 const local = try f.allocLocal(inst_ty, .Const);
3489 try f.renderTypecast(writer, inst_ty);3423
3490 try writer.writeAll(")(");3424 try writer.writeAll(" = ");
3491 try f.writeCValue(writer, lhs, .Other);3425 try f.writeCValue(writer, lhs, .Other);
3492 try writer.writeByte(' ');3426 try writer.writeByte(' ');
3493 try writer.writeAll(operator);3427 try writer.writeAll(operator);
3494 try writer.writeByte(' ');3428 try writer.writeByte(' ');
3495 try f.writeCValue(writer, rhs, .Other);3429 try f.writeCValue(writer, rhs, .Other);
3496 try writer.writeByte(')');3430 try writer.writeAll(";\n");
3431
3432 return local;
3497}3433}
34983434
3499fn airCmpOp(3435fn airCmpOp(f: *Function, inst: Air.Inst.Index, operator: []const u8, operation: []const u8) !CValue {
3500 f: *Function,3436 if (f.liveness.isUnused(inst)) return CValue.none;
3501 inst: Air.Inst.Index,3437
3502 operator: []const u8,
3503 operation: []const u8,
3504) !void {
3505 const bin_op = f.air.instructions.items(.data)[inst].bin_op;3438 const bin_op = f.air.instructions.items(.data)[inst].bin_op;
35063439
3507 const operand_ty = f.air.typeOf(bin_op.lhs);3440 const operand_ty = f.air.typeOf(bin_op.lhs);
3508 const target = f.object.dg.module.getTarget();3441 const target = f.object.dg.module.getTarget();
3509 if (operand_ty.isInt() and operand_ty.bitSize(target) > 64)3442 if (operand_ty.isInt() and operand_ty.bitSize(target) > 64)
3510 return airCmpBuiltinCall(f, inst, operator, "cmp");3443 return try airCmpBuiltinCall(f, inst, operator, "cmp");
3511 if (operand_ty.isRuntimeFloat())3444 if (operand_ty.isRuntimeFloat())
3512 return airCmpBuiltinCall(f, inst, operator, operation);3445 return try airCmpBuiltinCall(f, inst, operator, operation);
35133446
3447 const inst_ty = f.air.typeOfIndex(inst);
3514 const lhs = try f.resolveInst(bin_op.lhs);3448 const lhs = try f.resolveInst(bin_op.lhs);
3515 const rhs = try f.resolveInst(bin_op.rhs);3449 const rhs = try f.resolveInst(bin_op.rhs);
35163450
3517 const writer = f.object.writer();3451 const writer = f.object.writer();
3452 const local = try f.allocLocal(inst_ty, .Const);
3453
3454 try writer.writeAll(" = ");
3518 try f.writeCValue(writer, lhs, .Other);3455 try f.writeCValue(writer, lhs, .Other);
3519 try writer.writeByte(' ');3456 try writer.writeByte(' ');
3520 try writer.writeAll(operator);3457 try writer.writeAll(operator);
3521 try writer.writeByte(' ');3458 try writer.writeByte(' ');
3522 try f.writeCValue(writer, rhs, .Other);3459 try f.writeCValue(writer, rhs, .Other);
3460 try writer.writeAll(";\n");
3461
3462 return local;
3523}3463}
35243464
3525fn airEquality(3465fn airEquality(
...@@ -3528,20 +3468,27 @@ fn airEquality(...@@ -3528,20 +3468,27 @@ fn airEquality(
3528 negate_prefix: []const u8,3468 negate_prefix: []const u8,
3529 operator: []const u8,3469 operator: []const u8,
3530 operation: []const u8,3470 operation: []const u8,
3531) !void {3471) !CValue {
3472 if (f.liveness.isUnused(inst)) return CValue.none;
3473
3532 const bin_op = f.air.instructions.items(.data)[inst].bin_op;3474 const bin_op = f.air.instructions.items(.data)[inst].bin_op;
35333475
3534 const operand_ty = f.air.typeOf(bin_op.lhs);3476 const operand_ty = f.air.typeOf(bin_op.lhs);
3535 const target = f.object.dg.module.getTarget();3477 const target = f.object.dg.module.getTarget();
3536 if (operand_ty.isInt() and operand_ty.bitSize(target) > 64)3478 if (operand_ty.isInt() and operand_ty.bitSize(target) > 64)
3537 return airCmpBuiltinCall(f, inst, operator, "cmp");3479 return try airCmpBuiltinCall(f, inst, operator, "cmp");
3538 if (operand_ty.isRuntimeFloat())3480 if (operand_ty.isRuntimeFloat())
3539 return airCmpBuiltinCall(f, inst, operator, operation);3481 return try airCmpBuiltinCall(f, inst, operator, operation);
35403482
3541 const lhs = try f.resolveInst(bin_op.lhs);3483 const lhs = try f.resolveInst(bin_op.lhs);
3542 const rhs = try f.resolveInst(bin_op.rhs);3484 const rhs = try f.resolveInst(bin_op.rhs);
35433485
3544 const writer = f.object.writer();3486 const writer = f.object.writer();
3487 const inst_ty = f.air.typeOfIndex(inst);
3488 const local = try f.allocLocal(inst_ty, .Const);
3489
3490 try writer.writeAll(" = ");
3491
3545 if (operand_ty.zigTypeTag() == .Optional and !operand_ty.isPtrLikeOptional()) {3492 if (operand_ty.zigTypeTag() == .Optional and !operand_ty.isPtrLikeOptional()) {
3546 // (A && B) || (C && (A == B))3493 // (A && B) || (C && (A == B))
3547 // A = lhs.is_null ; B = rhs.is_null ; C = rhs.payload == lhs.payload3494 // A = lhs.is_null ; B = rhs.is_null ; C = rhs.payload == lhs.payload
...@@ -3558,8 +3505,9 @@ fn airEquality(...@@ -3558,8 +3505,9 @@ fn airEquality(
3558 try f.writeCValue(writer, lhs, .Other);3505 try f.writeCValue(writer, lhs, .Other);
3559 try writer.writeAll(".is_null == ");3506 try writer.writeAll(".is_null == ");
3560 try f.writeCValue(writer, rhs, .Other);3507 try f.writeCValue(writer, rhs, .Other);
3561 try writer.writeAll(".is_null))");3508 try writer.writeAll(".is_null));\n");
3562 return;3509
3510 return local;
3563 }3511 }
35643512
3565 try f.writeCValue(writer, lhs, .Other);3513 try f.writeCValue(writer, lhs, .Other);
...@@ -3567,6 +3515,9 @@ fn airEquality(...@@ -3567,6 +3515,9 @@ fn airEquality(
3567 try writer.writeAll(operator);3515 try writer.writeAll(operator);
3568 try writer.writeByte(' ');3516 try writer.writeByte(' ');
3569 try f.writeCValue(writer, rhs, .Other);3517 try f.writeCValue(writer, rhs, .Other);
3518 try writer.writeAll(";\n");
3519
3520 return local;
3570}3521}
35713522
3572fn airCmpLtErrorsLen(f: *Function, inst: Air.Inst.Index) !CValue {3523fn airCmpLtErrorsLen(f: *Function, inst: Air.Inst.Index) !CValue {
...@@ -3620,23 +3571,26 @@ fn airPtrAddSub(f: *Function, inst: Air.Inst.Index, operator: u8) !CValue {...@@ -3620,23 +3571,26 @@ fn airPtrAddSub(f: *Function, inst: Air.Inst.Index, operator: u8) !CValue {
3620 return local;3571 return local;
3621}3572}
36223573
3623fn airMinMax(f: *Function, inst: Air.Inst.Index, operator: u8, operation: []const u8) !void {3574fn airMinMax(f: *Function, inst: Air.Inst.Index, operator: u8, operation: []const u8) !CValue {
3575 if (f.liveness.isUnused(inst)) return CValue.none;
3576
3624 const bin_op = f.air.instructions.items(.data)[inst].bin_op;3577 const bin_op = f.air.instructions.items(.data)[inst].bin_op;
36253578
3626 const inst_ty = f.air.typeOfIndex(inst);3579 const inst_ty = f.air.typeOfIndex(inst);
3627 const target = f.object.dg.module.getTarget();3580 const target = f.object.dg.module.getTarget();
3628 if (inst_ty.isInt() and inst_ty.bitSize(target) > 64)3581 if (inst_ty.isInt() and inst_ty.bitSize(target) > 64)
3629 return airBinBuiltinCall(f, inst, operation[1..], .None);3582 return try airBinBuiltinCall(f, inst, operation[1..], .None);
3630 if (inst_ty.isRuntimeFloat())3583 if (inst_ty.isRuntimeFloat())
3631 return airBinFloatOp(f, inst, operation);3584 return try airBinFloatOp(f, inst, operation);
36323585
3633 const lhs = try f.resolveInst(bin_op.lhs);3586 const lhs = try f.resolveInst(bin_op.lhs);
3634 const rhs = try f.resolveInst(bin_op.rhs);3587 const rhs = try f.resolveInst(bin_op.rhs);
36353588
3636 const writer = f.object.writer();3589 const writer = f.object.writer();
3590 const local = try f.allocLocal(inst_ty, .Const);
36373591
3638 // (lhs <> rhs) ? lhs : rhs3592 // (lhs <> rhs) ? lhs : rhs
3639 try writer.writeAll("(");3593 try writer.writeAll(" = (");
3640 try f.writeCValue(writer, lhs, .Other);3594 try f.writeCValue(writer, lhs, .Other);
3641 try writer.writeByte(' ');3595 try writer.writeByte(' ');
3642 try writer.writeByte(operator);3596 try writer.writeByte(operator);
...@@ -3646,6 +3600,9 @@ fn airMinMax(f: *Function, inst: Air.Inst.Index, operator: u8, operation: []cons...@@ -3646,6 +3600,9 @@ fn airMinMax(f: *Function, inst: Air.Inst.Index, operator: u8, operation: []cons
3646 try f.writeCValue(writer, lhs, .Other);3600 try f.writeCValue(writer, lhs, .Other);
3647 try writer.writeAll(" : ");3601 try writer.writeAll(" : ");
3648 try f.writeCValue(writer, rhs, .Other);3602 try f.writeCValue(writer, rhs, .Other);
3603 try writer.writeAll(";\n");
3604
3605 return local;
3649}3606}
36503607
3651fn airSlice(f: *Function, inst: Air.Inst.Index) !CValue {3608fn airSlice(f: *Function, inst: Air.Inst.Index) !CValue {
...@@ -3961,7 +3918,7 @@ fn airBitcast(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -3961,7 +3918,7 @@ fn airBitcast(f: *Function, inst: Air.Inst.Index) !CValue {
3961 if (f.liveness.isUnused(inst) or !src_ty.hasRuntimeBits()) return CValue.none;3918 if (f.liveness.isUnused(inst) or !src_ty.hasRuntimeBits()) return CValue.none;
39623919
3963 const ty_op = f.air.instructions.items(.data)[inst].ty_op;3920 const ty_op = f.air.instructions.items(.data)[inst].ty_op;
3964 const operand = try f.resolveInstNoInline(ty_op.operand);3921 const operand = try f.resolveInst(ty_op.operand);
3965 const dest_ty = f.air.typeOf(ty_op.operand);3922 const dest_ty = f.air.typeOf(ty_op.operand);
3966 const target = f.object.dg.module.getTarget();3923 const target = f.object.dg.module.getTarget();
39673924
...@@ -4067,7 +4024,7 @@ fn airLoop(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -4067,7 +4024,7 @@ fn airLoop(f: *Function, inst: Air.Inst.Index) !CValue {
4067 const body = f.air.extra[loop.end..][0..loop.data.body_len];4024 const body = f.air.extra[loop.end..][0..loop.data.body_len];
4068 const writer = f.object.writer();4025 const writer = f.object.writer();
4069 try writer.writeAll("while (");4026 try writer.writeAll("while (");
4070 try f.object.dg.renderValue(writer, Type.bool, Value.true, .condition);4027 try f.object.dg.renderValue(writer, Type.bool, Value.true, .Other);
4071 try writer.writeAll(") ");4028 try writer.writeAll(") ");
4072 try genBody(f, body);4029 try genBody(f, body);
4073 try writer.writeByte('\n');4030 try writer.writeByte('\n');
...@@ -4083,7 +4040,7 @@ fn airCondBr(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -4083,7 +4040,7 @@ fn airCondBr(f: *Function, inst: Air.Inst.Index) !CValue {
4083 const writer = f.object.writer();4040 const writer = f.object.writer();
40844041
4085 try writer.writeAll("if (");4042 try writer.writeAll("if (");
4086 try f.writeCValue(writer, cond, .condition);4043 try f.writeCValue(writer, cond, .Other);
4087 try writer.writeAll(") ");4044 try writer.writeAll(") ");
4088 try genBody(f, then_body);4045 try genBody(f, then_body);
4089 try writer.writeAll(" else ");4046 try writer.writeAll(" else ");
...@@ -5174,12 +5131,16 @@ fn airBinBuiltinCall(...@@ -5174,12 +5131,16 @@ fn airBinBuiltinCall(
5174 inst: Air.Inst.Index,5131 inst: Air.Inst.Index,
5175 operation: []const u8,5132 operation: []const u8,
5176 info: BuiltinInfo,5133 info: BuiltinInfo,
5177) !void {5134) !CValue {
5135 if (f.liveness.isUnused(inst)) return CValue.none;
5136
5137 const inst_ty = f.air.typeOfIndex(inst);
5178 const bin_op = f.air.instructions.items(.data)[inst].bin_op;5138 const bin_op = f.air.instructions.items(.data)[inst].bin_op;
5179 const operand_ty = f.air.typeOf(bin_op.lhs);5139 const operand_ty = f.air.typeOf(bin_op.lhs);
51805140
5141 const local = try f.allocLocal(inst_ty, .Const);
5181 const writer = f.object.writer();5142 const writer = f.object.writer();
5182 try writer.writeAll("zig_");5143 try writer.writeAll(" = zig_");
5183 try writer.writeAll(operation);5144 try writer.writeAll(operation);
5184 try writer.writeByte('_');5145 try writer.writeByte('_');
5185 try f.object.dg.renderTypeForBuiltinFnName(writer, operand_ty);5146 try f.object.dg.renderTypeForBuiltinFnName(writer, operand_ty);
...@@ -5188,7 +5149,8 @@ fn airBinBuiltinCall(...@@ -5188,7 +5149,8 @@ fn airBinBuiltinCall(
5188 try writer.writeAll(", ");5149 try writer.writeAll(", ");
5189 try f.writeCValue(writer, try f.resolveInst(bin_op.rhs), .FunctionArgument);5150 try f.writeCValue(writer, try f.resolveInst(bin_op.rhs), .FunctionArgument);
5190 try f.object.dg.renderBuiltinInfo(writer, operand_ty, info);5151 try f.object.dg.renderBuiltinInfo(writer, operand_ty, info);
5191 try writer.writeAll(")");5152 try writer.writeAll(");\n");
5153 return local;
5192}5154}
51935155
5194fn airCmpBuiltinCall(5156fn airCmpBuiltinCall(
...@@ -5196,12 +5158,16 @@ fn airCmpBuiltinCall(...@@ -5196,12 +5158,16 @@ fn airCmpBuiltinCall(
5196 inst: Air.Inst.Index,5158 inst: Air.Inst.Index,
5197 operator: []const u8,5159 operator: []const u8,
5198 operation: []const u8,5160 operation: []const u8,
5199) !void {5161) !CValue {
5162 if (f.liveness.isUnused(inst)) return CValue.none;
5163
5164 const inst_ty = f.air.typeOfIndex(inst);
5200 const bin_op = f.air.instructions.items(.data)[inst].bin_op;5165 const bin_op = f.air.instructions.items(.data)[inst].bin_op;
5201 const operand_ty = f.air.typeOf(bin_op.lhs);5166 const operand_ty = f.air.typeOf(bin_op.lhs);
52025167
5168 const local = try f.allocLocal(inst_ty, .Const);
5203 const writer = f.object.writer();5169 const writer = f.object.writer();
5204 try writer.writeAll("zig_");5170 try writer.writeAll(" = zig_");
5205 try writer.writeAll(operation);5171 try writer.writeAll(operation);
5206 try writer.writeByte('_');5172 try writer.writeByte('_');
5207 try f.object.dg.renderTypeForBuiltinFnName(writer, operand_ty);5173 try f.object.dg.renderTypeForBuiltinFnName(writer, operand_ty);
...@@ -5209,7 +5175,8 @@ fn airCmpBuiltinCall(...@@ -5209,7 +5175,8 @@ fn airCmpBuiltinCall(
5209 try f.writeCValue(writer, try f.resolveInst(bin_op.lhs), .FunctionArgument);5175 try f.writeCValue(writer, try f.resolveInst(bin_op.lhs), .FunctionArgument);
5210 try writer.writeAll(", ");5176 try writer.writeAll(", ");
5211 try f.writeCValue(writer, try f.resolveInst(bin_op.rhs), .FunctionArgument);5177 try f.writeCValue(writer, try f.resolveInst(bin_op.rhs), .FunctionArgument);
5212 try writer.print(") {s} {}", .{ operator, try f.fmtIntLiteral(Type.initTag(.i32), Value.zero) });5178 try writer.print(") {s} {};\n", .{ operator, try f.fmtIntLiteral(Type.initTag(.i32), Value.zero) });
5179 return local;
5213}5180}
52145181
5215fn airCmpxchg(f: *Function, inst: Air.Inst.Index, flavor: [*:0]const u8) !CValue {5182fn airCmpxchg(f: *Function, inst: Air.Inst.Index, flavor: [*:0]const u8) !CValue {
...@@ -5946,18 +5913,15 @@ fn airUnFloatOp(f: *Function, inst: Air.Inst.Index, operation: []const u8) !CVal...@@ -5946,18 +5913,15 @@ fn airUnFloatOp(f: *Function, inst: Air.Inst.Index, operation: []const u8) !CVal
5946 return local;5913 return local;
5947}5914}
59485915
5949fn airBinFloatOp(5916fn airBinFloatOp(f: *Function, inst: Air.Inst.Index, operation: []const u8) !CValue {
5950 f: *Function,5917 if (f.liveness.isUnused(inst)) return CValue.none;
5951 inst: Air.Inst.Index,
5952 operation: []const u8,
5953) !void {
5954 const bin_op = f.air.instructions.items(.data)[inst].bin_op;5918 const bin_op = f.air.instructions.items(.data)[inst].bin_op;
5955 const writer = f.object.writer();5919 const writer = f.object.writer();
5956 const inst_ty = f.air.typeOfIndex(inst);5920 const inst_ty = f.air.typeOfIndex(inst);
5957 const lhs = try f.resolveInst(bin_op.lhs);5921 const lhs = try f.resolveInst(bin_op.lhs);
5958 const rhs = try f.resolveInst(bin_op.rhs);5922 const rhs = try f.resolveInst(bin_op.rhs);
59595923 const local = try f.allocLocal(inst_ty, .Const);
5960 try writer.writeAll("zig_libc_name_");5924 try writer.writeAll(" = zig_libc_name_");
5961 try f.object.dg.renderTypeForBuiltinFnName(writer, inst_ty);5925 try f.object.dg.renderTypeForBuiltinFnName(writer, inst_ty);
5962 try writer.writeByte('(');5926 try writer.writeByte('(');
5963 try writer.writeAll(operation);5927 try writer.writeAll(operation);
...@@ -5965,7 +5929,8 @@ fn airBinFloatOp(...@@ -5965,7 +5929,8 @@ fn airBinFloatOp(
5965 try f.writeCValue(writer, lhs, .FunctionArgument);5929 try f.writeCValue(writer, lhs, .FunctionArgument);
5966 try writer.writeAll(", ");5930 try writer.writeAll(", ");
5967 try f.writeCValue(writer, rhs, .FunctionArgument);5931 try f.writeCValue(writer, rhs, .FunctionArgument);
5968 try writer.writeAll(")");5932 try writer.writeAll(");\n");
5933 return local;
5969}5934}
59705935
5971fn airMulAdd(f: *Function, inst: Air.Inst.Index) !CValue {5936fn airMulAdd(f: *Function, inst: Air.Inst.Index) !CValue {