| ... | ... | @@ -1586,11 +1586,53 @@ fn structFieldPtr(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, ty: |
| 1586 | 1586 | |
| 1587 | 1587 | fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void { |
| 1588 | 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 | 1638 | fn airFieldParentPtr(self: *Self, inst: Air.Inst.Index) !void { |
| ... | ... | @@ -1626,8 +1668,6 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void { |
| 1626 | 1668 | self.arg_index = arg_index + 1; |
| 1627 | 1669 | |
| 1628 | 1670 | const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else result: { |
| 1629 | | const arg_ty = self.typeOfIndex(inst); |
| 1630 | | _ = arg_ty; |
| 1631 | 1671 | const src_mcv = self.args[arg_index]; |
| 1632 | 1672 | |
| 1633 | 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 | 2511 | } |
| 2472 | 2512 | }, |
| 2473 | 2513 | .stack_offset, .load_symbol => { |
| 2474 | | if (true) |
| 2475 | | return self.fail("TODO: genSetStack {s}", .{@tagName(src_val)}); |
| 2514 | switch (src_val) { |
| 2515 | .stack_offset => |off| if (off == stack_offset) return, |
| 2516 | else => {}, |
| 2517 | } |
| 2476 | 2518 | |
| 2477 | 2519 | if (abi_size <= 8) { |
| 2478 | 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 | 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 | 2538 | |
| 2497 | 2539 | switch (src_val) { |
| 2498 | 2540 | .stack_offset => |offset| { |
| 2499 | | if (offset == stack_offset) return; |
| 2500 | 2541 | try self.genSetReg(ptr_ty, src_reg, .{ .ptr_stack_offset = offset }); |
| 2501 | 2542 | }, |
| 2502 | 2543 | .load_symbol => |sym_off| { |
| ... | ... | @@ -2553,11 +2594,34 @@ fn genInlineMemcpy( |
| 2553 | 2594 | ) !void { |
| 2554 | 2595 | _ = src; |
| 2555 | 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 | 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 | 2631 | |
| 2568 | 2632 | switch (src_val) { |
| 2569 | 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 | 2635 | .unreach, .none => return, // Nothing to do. |
| 2572 | 2636 | .undef => { |
| 2573 | 2637 | if (!self.wantSafety()) |