authorgravatar for joachim.schmidt557@outlook.comJoachim Schmidt <joachim.schmidt557@outlook.com> 2022-08-25 22:17:57+02:00
committergravatar for joachim.schmidt557@outlook.comJoachim Schmidt <joachim.schmidt557@outlook.com> 2022-09-09 19:17:17+02:00
log95b8a5f157aa7552e3f125e56968b889e254497a
treef29fabd00fbcff48169a36ce243b5ea0e09987aa
parentfdb2c80bdc12bfb6be5235de6a5792e0b0619da8
signaturelock-open Commit is signed but in an unrecognized format.

stage2 ARM: extract remaining operations out of binOp


1 files changed, 282 insertions(+), 259 deletions(-)

src/arch/arm/CodeGen.zig+282-259
......@@ -1407,8 +1407,6 @@ fn airBinOp(self: *Self, inst: Air.Inst.Index, tag: Air.Inst.Tag) !void {
14071407 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
14081408 const lhs_bind: ReadArg.Bind = .{ .inst = bin_op.lhs };
14091409 const rhs_bind: ReadArg.Bind = .{ .inst = bin_op.rhs };
1410 const lhs = try self.resolveInst(bin_op.lhs);
1411 const rhs = try self.resolveInst(bin_op.rhs);
14121410
14131411 break :result switch (tag) {
14141412 .add => try self.addSub(tag, lhs_bind, rhs_bind, lhs_ty, rhs_ty, inst),
......@@ -1427,11 +1425,24 @@ fn airBinOp(self: *Self, inst: Air.Inst.Index, tag: Air.Inst.Tag) !void {
14271425
14281426 .mod => try self.modulo(lhs_bind, rhs_bind, lhs_ty, rhs_ty, inst),
14291427
1430 else => try self.binOp(tag, lhs, rhs, lhs_ty, rhs_ty, BinOpMetadata{
1431 .lhs = bin_op.lhs,
1432 .rhs = bin_op.rhs,
1433 .inst = inst,
1434 }),
1428 .addwrap => try self.wrappingArithmetic(tag, lhs_bind, rhs_bind, lhs_ty, rhs_ty, inst),
1429 .subwrap => try self.wrappingArithmetic(tag, lhs_bind, rhs_bind, lhs_ty, rhs_ty, inst),
1430 .mulwrap => try self.wrappingArithmetic(tag, lhs_bind, rhs_bind, lhs_ty, rhs_ty, inst),
1431
1432 .bit_and => try self.bitwise(tag, lhs_bind, rhs_bind, lhs_ty, rhs_ty, inst),
1433 .bit_or => try self.bitwise(tag, lhs_bind, rhs_bind, lhs_ty, rhs_ty, inst),
1434 .xor => try self.bitwise(tag, lhs_bind, rhs_bind, lhs_ty, rhs_ty, inst),
1435
1436 .shl_exact => try self.shiftExact(tag, lhs_bind, rhs_bind, lhs_ty, rhs_ty, inst),
1437 .shr_exact => try self.shiftExact(tag, lhs_bind, rhs_bind, lhs_ty, rhs_ty, inst),
1438
1439 .shl => try self.shiftNormal(tag, lhs_bind, rhs_bind, lhs_ty, rhs_ty, inst),
1440 .shr => try self.shiftNormal(tag, lhs_bind, rhs_bind, lhs_ty, rhs_ty, inst),
1441
1442 .bool_and => try self.booleanOp(tag, lhs_bind, rhs_bind, lhs_ty, rhs_ty, inst),
1443 .bool_or => try self.booleanOp(tag, lhs_bind, rhs_bind, lhs_ty, rhs_ty, inst),
1444
1445 else => unreachable,
14351446 };
14361447 };
14371448 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
......@@ -1440,19 +1451,15 @@ fn airBinOp(self: *Self, inst: Air.Inst.Index, tag: Air.Inst.Tag) !void {
14401451fn airPtrArithmetic(self: *Self, inst: Air.Inst.Index, tag: Air.Inst.Tag) !void {
14411452 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
14421453 const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data;
1443 const lhs = try self.resolveInst(bin_op.lhs);
1444 const rhs = try self.resolveInst(bin_op.rhs);
14451454 const lhs_ty = self.air.typeOf(bin_op.lhs);
14461455 const rhs_ty = self.air.typeOf(bin_op.rhs);
14471456
1448 const result: MCValue = if (self.liveness.isUnused(inst))
1449 .dead
1450 else
1451 try self.binOp(tag, lhs, rhs, lhs_ty, rhs_ty, BinOpMetadata{
1452 .lhs = bin_op.lhs,
1453 .rhs = bin_op.rhs,
1454 .inst = inst,
1455 });
1457 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
1458 const lhs_bind: ReadArg.Bind = .{ .inst = bin_op.lhs };
1459 const rhs_bind: ReadArg.Bind = .{ .inst = bin_op.rhs };
1460
1461 break :result try self.ptrArithmetic(tag, lhs_bind, rhs_bind, lhs_ty, rhs_ty, inst);
1462 };
14561463 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
14571464}
14581465
......@@ -2247,7 +2254,11 @@ fn airSliceElemVal(self: *Self, inst: Air.Inst.Index) !void {
22472254 },
22482255 else => {
22492256 const dest = try self.allocRegOrMem(inst, true);
2250 const addr = try self.binOp(.ptr_add, base_mcv, index_mcv, slice_ptr_field_type, Type.usize, null);
2257
2258 const base_bind: ReadArg.Bind = .{ .mcv = base_mcv };
2259 const index_bind: ReadArg.Bind = .{ .mcv = index_mcv };
2260
2261 const addr = try self.ptrArithmetic(.ptr_add, base_bind, index_bind, slice_ptr_field_type, Type.usize, null);
22512262 try self.load(dest, addr, slice_ptr_field_type);
22522263
22532264 break :result dest;
......@@ -2262,12 +2273,15 @@ fn airSliceElemPtr(self: *Self, inst: Air.Inst.Index) !void {
22622273 const extra = self.air.extraData(Air.Bin, ty_pl.payload).data;
22632274 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
22642275 const slice_mcv = try self.resolveInst(extra.lhs);
2265 const index_mcv = try self.resolveInst(extra.rhs);
22662276 const base_mcv = slicePtr(slice_mcv);
22672277
2278 const base_bind: ReadArg.Bind = .{ .mcv = base_mcv };
2279 const index_bind: ReadArg.Bind = .{ .inst = extra.rhs };
2280
22682281 const slice_ty = self.air.typeOf(extra.lhs);
2282 const index_ty = self.air.typeOf(extra.rhs);
22692283
2270 const addr = try self.binOp(.ptr_add, base_mcv, index_mcv, slice_ty, Type.usize, null);
2284 const addr = try self.ptrArithmetic(.ptr_add, base_bind, index_bind, slice_ty, index_ty, null);
22712285 break :result addr;
22722286 };
22732287 return self.finishAir(inst, result, .{ extra.lhs, extra.rhs, .none });
......@@ -2290,12 +2304,13 @@ fn airPtrElemPtr(self: *Self, inst: Air.Inst.Index) !void {
22902304 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
22912305 const extra = self.air.extraData(Air.Bin, ty_pl.payload).data;
22922306 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
2293 const ptr_mcv = try self.resolveInst(extra.lhs);
2294 const index_mcv = try self.resolveInst(extra.rhs);
2307 const ptr_bind: ReadArg.Bind = .{ .inst = extra.lhs };
2308 const index_bind: ReadArg.Bind = .{ .inst = extra.rhs };
22952309
22962310 const ptr_ty = self.air.typeOf(extra.lhs);
2311 const index_ty = self.air.typeOf(extra.rhs);
22972312
2298 const addr = try self.binOp(.ptr_add, ptr_mcv, index_mcv, ptr_ty, Type.usize, null);
2313 const addr = try self.ptrArithmetic(.ptr_add, ptr_bind, index_bind, ptr_ty, index_ty, null);
22992314 break :result addr;
23002315 };
23012316 return self.finishAir(inst, result, .{ extra.lhs, extra.rhs, .none });
......@@ -3219,240 +3234,6 @@ const BinOpMetadata = struct {
32193234 rhs: Air.Inst.Ref,
32203235};
32213236
3222/// For all your binary operation needs, this function will generate
3223/// the corresponding Mir instruction(s). Returns the location of the
3224/// result.
3225///
3226/// If the binary operation itself happens to be an Air instruction,
3227/// pass the corresponding index in the inst parameter. That helps
3228/// this function do stuff like reusing operands.
3229///
3230/// This function does not do any lowering to Mir itself, but instead
3231/// looks at the lhs and rhs and determines which kind of lowering
3232/// would be best suitable and then delegates the lowering to other
3233/// functions.
3234fn binOp(
3235 self: *Self,
3236 tag: Air.Inst.Tag,
3237 lhs: MCValue,
3238 rhs: MCValue,
3239 lhs_ty: Type,
3240 rhs_ty: Type,
3241 metadata: ?BinOpMetadata,
3242) InnerError!MCValue {
3243 switch (tag) {
3244 .addwrap,
3245 .subwrap,
3246 .mulwrap,
3247 => {
3248 const base_tag: Air.Inst.Tag = switch (tag) {
3249 .addwrap => .add,
3250 .subwrap => .sub,
3251 .mulwrap => .mul,
3252 else => unreachable,
3253 };
3254
3255 const lhs_bind = if (metadata) |md|
3256 ReadArg.Bind{ .inst = md.lhs }
3257 else
3258 ReadArg.Bind{ .mcv = lhs };
3259 const rhs_bind = if (metadata) |md|
3260 ReadArg.Bind{ .inst = md.rhs }
3261 else
3262 ReadArg.Bind{ .mcv = rhs };
3263
3264 // Generate an add/sub/mul
3265 const maybe_inst: ?Air.Inst.Index = if (metadata) |md| md.inst else null;
3266 const result = try self.addSub(base_tag, lhs_bind, rhs_bind, lhs_ty, rhs_ty, maybe_inst);
3267
3268 // Truncate if necessary
3269 switch (lhs_ty.zigTypeTag()) {
3270 .Vector => return self.fail("TODO ARM binary operations on vectors", .{}),
3271 .Int => {
3272 const int_info = lhs_ty.intInfo(self.target.*);
3273 if (int_info.bits <= 32) {
3274 const result_reg = result.register;
3275
3276 if (int_info.bits < 32) {
3277 try self.truncRegister(result_reg, result_reg, int_info.signedness, int_info.bits);
3278 return result;
3279 } else return result;
3280 } else {
3281 return self.fail("TODO ARM binary operations on integers > u32/i32", .{});
3282 }
3283 },
3284 else => unreachable,
3285 }
3286 },
3287 .bit_and,
3288 .bit_or,
3289 .xor,
3290 => {
3291 switch (lhs_ty.zigTypeTag()) {
3292 .Vector => return self.fail("TODO ARM binary operations on vectors", .{}),
3293 .Int => {
3294 const mod = self.bin_file.options.module.?;
3295 assert(lhs_ty.eql(rhs_ty, mod));
3296 const int_info = lhs_ty.intInfo(self.target.*);
3297 if (int_info.bits <= 32) {
3298 const lhs_immediate_ok = lhs == .immediate and Instruction.Operand.fromU32(lhs.immediate) != null;
3299 const rhs_immediate_ok = rhs == .immediate and Instruction.Operand.fromU32(rhs.immediate) != null;
3300
3301 const mir_tag: Mir.Inst.Tag = switch (tag) {
3302 .bit_and => .@"and",
3303 .bit_or => .orr,
3304 .xor => .eor,
3305 else => unreachable,
3306 };
3307
3308 if (rhs_immediate_ok) {
3309 return try self.binOpImmediate(mir_tag, lhs, rhs, lhs_ty, false, metadata);
3310 } else if (lhs_immediate_ok) {
3311 // swap lhs and rhs
3312 return try self.binOpImmediate(mir_tag, rhs, lhs, rhs_ty, true, metadata);
3313 } else {
3314 return try self.binOpRegister(mir_tag, lhs, rhs, lhs_ty, rhs_ty, metadata);
3315 }
3316 } else {
3317 return self.fail("TODO ARM binary operations on integers > u32/i32", .{});
3318 }
3319 },
3320 else => unreachable,
3321 }
3322 },
3323 .shl_exact,
3324 .shr_exact,
3325 => {
3326 switch (lhs_ty.zigTypeTag()) {
3327 .Vector => return self.fail("TODO ARM binary operations on vectors", .{}),
3328 .Int => {
3329 const int_info = lhs_ty.intInfo(self.target.*);
3330 if (int_info.bits <= 32) {
3331 const rhs_immediate_ok = rhs == .immediate;
3332
3333 const mir_tag: Mir.Inst.Tag = switch (tag) {
3334 .shl_exact => .lsl,
3335 .shr_exact => switch (lhs_ty.intInfo(self.target.*).signedness) {
3336 .signed => Mir.Inst.Tag.asr,
3337 .unsigned => Mir.Inst.Tag.lsr,
3338 },
3339 else => unreachable,
3340 };
3341
3342 if (rhs_immediate_ok) {
3343 return try self.binOpImmediate(mir_tag, lhs, rhs, lhs_ty, false, metadata);
3344 } else {
3345 return try self.binOpRegister(mir_tag, lhs, rhs, lhs_ty, rhs_ty, metadata);
3346 }
3347 } else {
3348 return self.fail("TODO ARM binary operations on integers > u32/i32", .{});
3349 }
3350 },
3351 else => unreachable,
3352 }
3353 },
3354 .shl,
3355 .shr,
3356 => {
3357 const base_tag: Air.Inst.Tag = switch (tag) {
3358 .shl => .shl_exact,
3359 .shr => .shr_exact,
3360 else => unreachable,
3361 };
3362
3363 // Generate a shl_exact/shr_exact
3364 const result = try self.binOp(base_tag, lhs, rhs, lhs_ty, rhs_ty, metadata);
3365
3366 // Truncate if necessary
3367 switch (tag) {
3368 .shr => return result,
3369 .shl => switch (lhs_ty.zigTypeTag()) {
3370 .Vector => return self.fail("TODO ARM binary operations on vectors", .{}),
3371 .Int => {
3372 const int_info = lhs_ty.intInfo(self.target.*);
3373 if (int_info.bits <= 32) {
3374 const result_reg = result.register;
3375
3376 if (int_info.bits < 32) {
3377 try self.truncRegister(result_reg, result_reg, int_info.signedness, int_info.bits);
3378 return result;
3379 } else return result;
3380 } else {
3381 return self.fail("TODO ARM binary operations on integers > u32/i32", .{});
3382 }
3383 },
3384 else => unreachable,
3385 },
3386 else => unreachable,
3387 }
3388 },
3389 .bool_and,
3390 .bool_or,
3391 => {
3392 switch (lhs_ty.zigTypeTag()) {
3393 .Bool => {
3394 const lhs_immediate_ok = lhs == .immediate;
3395 const rhs_immediate_ok = rhs == .immediate;
3396
3397 const mir_tag: Mir.Inst.Tag = switch (tag) {
3398 .bool_and => .@"and",
3399 .bool_or => .orr,
3400 else => unreachable,
3401 };
3402
3403 if (rhs_immediate_ok) {
3404 return try self.binOpImmediate(mir_tag, lhs, rhs, lhs_ty, false, metadata);
3405 } else if (lhs_immediate_ok) {
3406 // swap lhs and rhs
3407 return try self.binOpImmediate(mir_tag, rhs, lhs, rhs_ty, true, metadata);
3408 } else {
3409 return try self.binOpRegister(mir_tag, lhs, rhs, lhs_ty, rhs_ty, metadata);
3410 }
3411 },
3412 else => unreachable,
3413 }
3414 },
3415 .ptr_add,
3416 .ptr_sub,
3417 => {
3418 switch (lhs_ty.zigTypeTag()) {
3419 .Pointer => {
3420 const ptr_ty = lhs_ty;
3421 const elem_ty = switch (ptr_ty.ptrSize()) {
3422 .One => ptr_ty.childType().childType(), // ptr to array, so get array element type
3423 else => ptr_ty.childType(),
3424 };
3425 const elem_size = @intCast(u32, elem_ty.abiSize(self.target.*));
3426
3427 if (elem_size == 1) {
3428 const base_tag: Mir.Inst.Tag = switch (tag) {
3429 .ptr_add => .add,
3430 .ptr_sub => .sub,
3431 else => unreachable,
3432 };
3433
3434 return try self.binOpRegister(base_tag, lhs, rhs, lhs_ty, rhs_ty, metadata);
3435 } else {
3436 // convert the offset into a byte offset by
3437 // multiplying it with elem_size
3438 const rhs_bind = if (metadata) |md|
3439 ReadArg.Bind{ .inst = md.rhs }
3440 else
3441 ReadArg.Bind{ .mcv = rhs };
3442 const imm_bind = ReadArg.Bind{ .mcv = .{ .immediate = elem_size } };
3443
3444 const offset = try self.mul(rhs_bind, imm_bind, Type.usize, Type.usize, null);
3445 const addr = try self.binOp(tag, lhs, offset, Type.initTag(.manyptr_u8), Type.usize, null);
3446 return addr;
3447 }
3448 },
3449 else => unreachable,
3450 }
3451 },
3452 else => unreachable,
3453 }
3454}
3455
34563237fn addSub(
34573238 self: *Self,
34583239 tag: Air.Inst.Tag,
......@@ -3713,6 +3494,248 @@ fn modulo(
37133494 }
37143495}
37153496
3497fn wrappingArithmetic(
3498 self: *Self,
3499 tag: Air.Inst.Tag,
3500 lhs_bind: ReadArg.Bind,
3501 rhs_bind: ReadArg.Bind,
3502 lhs_ty: Type,
3503 rhs_ty: Type,
3504 maybe_inst: ?Air.Inst.Index,
3505) InnerError!MCValue {
3506 const base_tag: Air.Inst.Tag = switch (tag) {
3507 .addwrap => .add,
3508 .subwrap => .sub,
3509 .mulwrap => .mul,
3510 else => unreachable,
3511 };
3512
3513 // Generate an add/sub/mul
3514 const result = try self.addSub(base_tag, lhs_bind, rhs_bind, lhs_ty, rhs_ty, maybe_inst);
3515
3516 // Truncate if necessary
3517 switch (lhs_ty.zigTypeTag()) {
3518 .Vector => return self.fail("TODO ARM binary operations on vectors", .{}),
3519 .Int => {
3520 const int_info = lhs_ty.intInfo(self.target.*);
3521 if (int_info.bits <= 32) {
3522 const result_reg = result.register;
3523
3524 if (int_info.bits < 32) {
3525 try self.truncRegister(result_reg, result_reg, int_info.signedness, int_info.bits);
3526 return result;
3527 } else return result;
3528 } else {
3529 return self.fail("TODO ARM binary operations on integers > u32/i32", .{});
3530 }
3531 },
3532 else => unreachable,
3533 }
3534}
3535
3536fn bitwise(
3537 self: *Self,
3538 tag: Air.Inst.Tag,
3539 lhs_bind: ReadArg.Bind,
3540 rhs_bind: ReadArg.Bind,
3541 lhs_ty: Type,
3542 rhs_ty: Type,
3543 maybe_inst: ?Air.Inst.Index,
3544) InnerError!MCValue {
3545 switch (lhs_ty.zigTypeTag()) {
3546 .Vector => return self.fail("TODO ARM binary operations on vectors", .{}),
3547 .Int => {
3548 const mod = self.bin_file.options.module.?;
3549 assert(lhs_ty.eql(rhs_ty, mod));
3550 const int_info = lhs_ty.intInfo(self.target.*);
3551 if (int_info.bits <= 32) {
3552 const lhs_immediate = try lhs_bind.resolveToImmediate(self);
3553 const rhs_immediate = try rhs_bind.resolveToImmediate(self);
3554
3555 const lhs_immediate_ok = if (lhs_immediate) |imm| Instruction.Operand.fromU32(imm) != null else false;
3556 const rhs_immediate_ok = if (rhs_immediate) |imm| Instruction.Operand.fromU32(imm) != null else false;
3557
3558 const mir_tag: Mir.Inst.Tag = switch (tag) {
3559 .bit_and => .@"and",
3560 .bit_or => .orr,
3561 .xor => .eor,
3562 else => unreachable,
3563 };
3564
3565 if (rhs_immediate_ok) {
3566 return try self.binOpImmediateNew(mir_tag, lhs_bind, rhs_immediate.?, lhs_ty, false, maybe_inst);
3567 } else if (lhs_immediate_ok) {
3568 // swap lhs and rhs
3569 return try self.binOpImmediateNew(mir_tag, rhs_bind, lhs_immediate.?, rhs_ty, true, maybe_inst);
3570 } else {
3571 return try self.binOpRegisterNew(mir_tag, lhs_bind, rhs_bind, lhs_ty, rhs_ty, maybe_inst);
3572 }
3573 } else {
3574 return self.fail("TODO ARM binary operations on integers > u32/i32", .{});
3575 }
3576 },
3577 else => unreachable,
3578 }
3579}
3580
3581fn shiftExact(
3582 self: *Self,
3583 tag: Air.Inst.Tag,
3584 lhs_bind: ReadArg.Bind,
3585 rhs_bind: ReadArg.Bind,
3586 lhs_ty: Type,
3587 rhs_ty: Type,
3588 maybe_inst: ?Air.Inst.Index,
3589) InnerError!MCValue {
3590 switch (lhs_ty.zigTypeTag()) {
3591 .Vector => return self.fail("TODO ARM binary operations on vectors", .{}),
3592 .Int => {
3593 const int_info = lhs_ty.intInfo(self.target.*);
3594 if (int_info.bits <= 32) {
3595 const rhs_immediate = try rhs_bind.resolveToImmediate(self);
3596
3597 const mir_tag: Mir.Inst.Tag = switch (tag) {
3598 .shl_exact => .lsl,
3599 .shr_exact => switch (lhs_ty.intInfo(self.target.*).signedness) {
3600 .signed => Mir.Inst.Tag.asr,
3601 .unsigned => Mir.Inst.Tag.lsr,
3602 },
3603 else => unreachable,
3604 };
3605
3606 if (rhs_immediate) |imm| {
3607 return try self.binOpImmediateNew(mir_tag, lhs_bind, imm, lhs_ty, false, maybe_inst);
3608 } else {
3609 return try self.binOpRegisterNew(mir_tag, lhs_bind, rhs_bind, lhs_ty, rhs_ty, maybe_inst);
3610 }
3611 } else {
3612 return self.fail("TODO ARM binary operations on integers > u32/i32", .{});
3613 }
3614 },
3615 else => unreachable,
3616 }
3617}
3618
3619fn shiftNormal(
3620 self: *Self,
3621 tag: Air.Inst.Tag,
3622 lhs_bind: ReadArg.Bind,
3623 rhs_bind: ReadArg.Bind,
3624 lhs_ty: Type,
3625 rhs_ty: Type,
3626 maybe_inst: ?Air.Inst.Index,
3627) InnerError!MCValue {
3628 const base_tag: Air.Inst.Tag = switch (tag) {
3629 .shl => .shl_exact,
3630 .shr => .shr_exact,
3631 else => unreachable,
3632 };
3633
3634 // Generate a shl_exact/shr_exact
3635 const result = try self.shiftExact(base_tag, lhs_bind, rhs_bind, lhs_ty, rhs_ty, maybe_inst);
3636
3637 // Truncate if necessary
3638 switch (tag) {
3639 .shr => return result,
3640 .shl => switch (lhs_ty.zigTypeTag()) {
3641 .Vector => return self.fail("TODO ARM binary operations on vectors", .{}),
3642 .Int => {
3643 const int_info = lhs_ty.intInfo(self.target.*);
3644 if (int_info.bits <= 32) {
3645 const result_reg = result.register;
3646
3647 if (int_info.bits < 32) {
3648 try self.truncRegister(result_reg, result_reg, int_info.signedness, int_info.bits);
3649 return result;
3650 } else return result;
3651 } else {
3652 return self.fail("TODO ARM binary operations on integers > u32/i32", .{});
3653 }
3654 },
3655 else => unreachable,
3656 },
3657 else => unreachable,
3658 }
3659}
3660
3661fn booleanOp(
3662 self: *Self,
3663 tag: Air.Inst.Tag,
3664 lhs_bind: ReadArg.Bind,
3665 rhs_bind: ReadArg.Bind,
3666 lhs_ty: Type,
3667 rhs_ty: Type,
3668 maybe_inst: ?Air.Inst.Index,
3669) InnerError!MCValue {
3670 switch (lhs_ty.zigTypeTag()) {
3671 .Bool => {
3672 const lhs_immediate = try lhs_bind.resolveToImmediate(self);
3673 const rhs_immediate = try rhs_bind.resolveToImmediate(self);
3674
3675 const mir_tag: Mir.Inst.Tag = switch (tag) {
3676 .bool_and => .@"and",
3677 .bool_or => .orr,
3678 else => unreachable,
3679 };
3680
3681 if (rhs_immediate) |imm| {
3682 return try self.binOpImmediateNew(mir_tag, lhs_bind, imm, lhs_ty, false, maybe_inst);
3683 } else if (lhs_immediate) |imm| {
3684 // swap lhs and rhs
3685 return try self.binOpImmediateNew(mir_tag, rhs_bind, imm, rhs_ty, true, maybe_inst);
3686 } else {
3687 return try self.binOpRegisterNew(mir_tag, lhs_bind, rhs_bind, lhs_ty, rhs_ty, maybe_inst);
3688 }
3689 },
3690 else => unreachable,
3691 }
3692}
3693
3694fn ptrArithmetic(
3695 self: *Self,
3696 tag: Air.Inst.Tag,
3697 lhs_bind: ReadArg.Bind,
3698 rhs_bind: ReadArg.Bind,
3699 lhs_ty: Type,
3700 rhs_ty: Type,
3701 maybe_inst: ?Air.Inst.Index,
3702) InnerError!MCValue {
3703 switch (lhs_ty.zigTypeTag()) {
3704 .Pointer => {
3705 const mod = self.bin_file.options.module.?;
3706 assert(rhs_ty.eql(Type.usize, mod));
3707
3708 const ptr_ty = lhs_ty;
3709 const elem_ty = switch (ptr_ty.ptrSize()) {
3710 .One => ptr_ty.childType().childType(), // ptr to array, so get array element type
3711 else => ptr_ty.childType(),
3712 };
3713 const elem_size = @intCast(u32, elem_ty.abiSize(self.target.*));
3714
3715 const base_tag: Air.Inst.Tag = switch (tag) {
3716 .ptr_add => .add,
3717 .ptr_sub => .sub,
3718 else => unreachable,
3719 };
3720
3721 if (elem_size == 1) {
3722 return try self.addSub(base_tag, lhs_bind, rhs_bind, Type.usize, Type.usize, maybe_inst);
3723 } else {
3724 // convert the offset into a byte offset by
3725 // multiplying it with elem_size
3726 const imm_bind = ReadArg.Bind{ .mcv = .{ .immediate = elem_size } };
3727
3728 const offset = try self.mul(rhs_bind, imm_bind, Type.usize, Type.usize, null);
3729 const offset_bind = ReadArg.Bind{ .mcv = offset };
3730
3731 const addr = try self.addSub(base_tag, lhs_bind, offset_bind, Type.usize, Type.usize, null);
3732 return addr;
3733 }
3734 },
3735 else => unreachable,
3736 }
3737}
3738
37163739fn genLdrRegister(self: *Self, dest_reg: Register, addr_reg: Register, ty: Type) !void {
37173740 const abi_size = ty.abiSize(self.target.*);
37183741
......@@ -4614,7 +4637,7 @@ fn airCondBr(self: *Self, inst: Air.Inst.Index) !void {
46144637 if (else_value == .dead)
46154638 continue;
46164639 // The instruction is only overridden in the else branch.
4617 var i: usize = self.branch_stack.items.len - 2;
4640 var i: usize = self.branch_stack.items.len - 1;
46184641 while (true) {
46194642 i -= 1; // If this overflows, the question is: why wasn't the instruction marked dead?
46204643 if (self.branch_stack.items[i].inst_table.get(else_key)) |mcv| {
......@@ -4641,7 +4664,7 @@ fn airCondBr(self: *Self, inst: Air.Inst.Index) !void {
46414664 if (then_value == .dead)
46424665 continue;
46434666 const parent_mcv = blk: {
4644 var i: usize = self.branch_stack.items.len - 2;
4667 var i: usize = self.branch_stack.items.len - 1;
46454668 while (true) {
46464669 i -= 1;
46474670 if (self.branch_stack.items[i].inst_table.get(then_key)) |mcv| {