| ... | @@ -1586,11 +1586,53 @@ fn structFieldPtr(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, ty: | ... | @@ -1586,11 +1586,53 @@ fn structFieldPtr(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, ty: |
| 1586 | | 1586 | |
| 1587 | fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void { | 1587 | fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void { |
| 1588 | const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; | 1588 | const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; |
| 1589 | _ = ty_pl; | 1589 | const extra = self.air.extraData(Air.StructField, ty_pl.payload).data; |
| | 1590 | const operand = extra.struct_operand; |
| | 1591 | const index = extra.field_index; |
| | 1592 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { |
| | 1593 | const mod = self.bin_file.comp.module.?; |
| | 1594 | const src_mcv = try self.resolveInst(operand); |
| | 1595 | const struct_ty = self.typeOf(operand); |
| | 1596 | const field_ty = struct_ty.structFieldType(index, mod); |
| | 1597 | if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) break :result .none; |
| | 1598 | |
| | 1599 | const field_off = @as(u32, @intCast(struct_ty.structFieldOffset(index, mod))); |
| | 1600 | |
| | 1601 | switch (src_mcv) { |
| | 1602 | .dead, .unreach => unreachable, |
| | 1603 | .register => |src_reg| { |
| | 1604 | const src_reg_lock = self.register_manager.lockRegAssumeUnused(src_reg); |
| | 1605 | defer self.register_manager.unlockReg(src_reg_lock); |
| | 1606 | |
| | 1607 | const dst_reg = if (field_off == 0) |
| | 1608 | (try self.copyToNewRegister(inst, src_mcv)).register |
| | 1609 | else |
| | 1610 | try self.copyToTmpRegister(Type.usize, .{ .register = src_reg }); |
| | 1611 | |
| | 1612 | const dst_mcv: MCValue = .{ .register = dst_reg }; |
| | 1613 | const dst_lock = self.register_manager.lockReg(dst_reg); |
| | 1614 | defer if (dst_lock) |lock| self.register_manager.unlockReg(lock); |
| | 1615 | |
| | 1616 | if (field_off > 0) { |
| | 1617 | _ = try self.addInst(.{ |
| | 1618 | .tag = .srli, |
| | 1619 | .data = .{ |
| | 1620 | .i_type = .{ |
| | 1621 | .imm12 = @intCast(field_off), |
| | 1622 | .rd = dst_reg, |
| | 1623 | .rs1 = dst_reg, |
| | 1624 | }, |
| | 1625 | }, |
| | 1626 | }); |
| | 1627 | } |
| 1590 | | 1628 | |
| 1591 | return self.fail("TODO: airStructFieldVal", .{}); | 1629 | break :result if (field_off == 0) dst_mcv else try self.copyToNewRegister(inst, dst_mcv); |
| | 1630 | }, |
| | 1631 | else => return self.fail("TODO: airStructField {s}", .{@tagName(src_mcv)}), |
| | 1632 | } |
| | 1633 | }; |
| 1592 | | 1634 | |
| 1593 | // return self.finishAir(inst, result, .{ extra.struct_operand, .none, .none }); | 1635 | return self.finishAir(inst, result, .{ extra.struct_operand, .none, .none }); |
| 1594 | } | 1636 | } |
| 1595 | | 1637 | |
| 1596 | fn airFieldParentPtr(self: *Self, inst: Air.Inst.Index) !void { | 1638 | fn airFieldParentPtr(self: *Self, inst: Air.Inst.Index) !void { |
| ... | @@ -1626,8 +1668,6 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -1626,8 +1668,6 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void { |
| 1626 | self.arg_index = arg_index + 1; | 1668 | self.arg_index = arg_index + 1; |
| 1627 | | 1669 | |
| 1628 | const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else result: { | 1670 | const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else result: { |
| 1629 | const arg_ty = self.typeOfIndex(inst); | | |
| 1630 | _ = arg_ty; | | |
| 1631 | const src_mcv = self.args[arg_index]; | 1671 | const src_mcv = self.args[arg_index]; |
| 1632 | | 1672 | |
| 1633 | const dst_mcv = switch (src_mcv) { | 1673 | const dst_mcv = switch (src_mcv) { |
| ... | @@ -2471,12 +2511,14 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, src_val: MCValue) Inner | ... | @@ -2471,12 +2511,14 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, src_val: MCValue) Inner |
| 2471 | } | 2511 | } |
| 2472 | }, | 2512 | }, |
| 2473 | .stack_offset, .load_symbol => { | 2513 | .stack_offset, .load_symbol => { |
| 2474 | if (true) | 2514 | switch (src_val) { |
| 2475 | return self.fail("TODO: genSetStack {s}", .{@tagName(src_val)}); | 2515 | .stack_offset => |off| if (off == stack_offset) return, |
| | 2516 | else => {}, |
| | 2517 | } |
| 2476 | | 2518 | |
| 2477 | if (abi_size <= 8) { | 2519 | if (abi_size <= 8) { |
| 2478 | const reg = try self.copyToTmpRegister(ty, src_val); | 2520 | const reg = try self.copyToTmpRegister(ty, src_val); |
| 2479 | return self.genSetStack(ty, stack_offset, MCValue{ .register = reg }); | 2521 | return self.genSetStack(ty, stack_offset, .{ .register = reg }); |
| 2480 | } | 2522 | } |
| 2481 | | 2523 | |
| 2482 | const ptr_ty = try mod.singleMutPtrType(ty); | 2524 | const ptr_ty = try mod.singleMutPtrType(ty); |
| ... | @@ -2496,7 +2538,6 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, src_val: MCValue) Inner | ... | @@ -2496,7 +2538,6 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, src_val: MCValue) Inner |
| 2496 | | 2538 | |
| 2497 | switch (src_val) { | 2539 | switch (src_val) { |
| 2498 | .stack_offset => |offset| { | 2540 | .stack_offset => |offset| { |
| 2499 | if (offset == stack_offset) return; | | |
| 2500 | try self.genSetReg(ptr_ty, src_reg, .{ .ptr_stack_offset = offset }); | 2541 | try self.genSetReg(ptr_ty, src_reg, .{ .ptr_stack_offset = offset }); |
| 2501 | }, | 2542 | }, |
| 2502 | .load_symbol => |sym_off| { | 2543 | .load_symbol => |sym_off| { |
| ... | @@ -2553,11 +2594,34 @@ fn genInlineMemcpy( | ... | @@ -2553,11 +2594,34 @@ fn genInlineMemcpy( |
| 2553 | ) !void { | 2594 | ) !void { |
| 2554 | _ = src; | 2595 | _ = src; |
| 2555 | _ = dst; | 2596 | _ = dst; |
| 2556 | _ = len; | | |
| 2557 | _ = count; | | |
| 2558 | _ = tmp; | | |
| 2559 | | 2597 | |
| 2560 | return self.fail("TODO: genInlineMemcpy", .{}); | 2598 | // store 0 in the count |
| | 2599 | try self.genSetReg(Type.usize, count, .{ .immediate = 0 }); |
| | 2600 | |
| | 2601 | // compare count to length |
| | 2602 | const compare_inst = try self.addInst(.{ |
| | 2603 | .tag = .cmp_gt, |
| | 2604 | .data = .{ .r_type = .{ |
| | 2605 | .rd = tmp, |
| | 2606 | .rs1 = count, |
| | 2607 | .rs2 = len, |
| | 2608 | } }, |
| | 2609 | }); |
| | 2610 | |
| | 2611 | // end if true |
| | 2612 | _ = try self.addInst(.{ |
| | 2613 | .tag = .bne, |
| | 2614 | .data = .{ |
| | 2615 | .b_type = .{ |
| | 2616 | .inst = @intCast(self.mir_instructions.len + 0), // points after the last inst |
| | 2617 | .rs1 = .zero, |
| | 2618 | .rs2 = tmp, |
| | 2619 | }, |
| | 2620 | }, |
| | 2621 | }); |
| | 2622 | _ = compare_inst; |
| | 2623 | |
| | 2624 | return self.fail("TODO: finish genInlineMemcpy", .{}); |
| 2561 | } | 2625 | } |
| 2562 | | 2626 | |
| 2563 | /// Sets the value of `src_val` into `reg`. Assumes you have a lock on it. | 2627 | /// Sets the value of `src_val` into `reg`. Assumes you have a lock on it. |
| ... | @@ -2567,7 +2631,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, src_val: MCValue) InnerError! | ... | @@ -2567,7 +2631,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, src_val: MCValue) InnerError! |
| 2567 | | 2631 | |
| 2568 | switch (src_val) { | 2632 | switch (src_val) { |
| 2569 | .dead => unreachable, | 2633 | .dead => unreachable, |
| 2570 | .ptr_stack_offset => return self.fail("TODO genSetReg ptr_stack_offset", .{}), | 2634 | .ptr_stack_offset => |off| try self.genSetReg(ty, reg, .{ .stack_offset = off }), |
| 2571 | .unreach, .none => return, // Nothing to do. | 2635 | .unreach, .none => return, // Nothing to do. |
| 2572 | .undef => { | 2636 | .undef => { |
| 2573 | if (!self.wantSafety()) | 2637 | if (!self.wantSafety()) |