| ... | @@ -543,7 +543,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { | ... | @@ -543,7 +543,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { |
| 543 | .assembly => try self.airAsm(inst), | 543 | .assembly => try self.airAsm(inst), |
| 544 | .bitcast => @panic("TODO try self.airBitCast(inst)"), | 544 | .bitcast => @panic("TODO try self.airBitCast(inst)"), |
| 545 | .block => try self.airBlock(inst), | 545 | .block => try self.airBlock(inst), |
| 546 | .br => @panic("TODO try self.airBr(inst)"), | 546 | .br => try self.airBr(inst), |
| 547 | .breakpoint => try self.airBreakpoint(), | 547 | .breakpoint => try self.airBreakpoint(), |
| 548 | .ret_addr => @panic("TODO try self.airRetAddr(inst)"), | 548 | .ret_addr => @panic("TODO try self.airRetAddr(inst)"), |
| 549 | .frame_addr => @panic("TODO try self.airFrameAddress(inst)"), | 549 | .frame_addr => @panic("TODO try self.airFrameAddress(inst)"), |
| ... | @@ -852,6 +852,12 @@ fn airBlock(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -852,6 +852,12 @@ fn airBlock(self: *Self, inst: Air.Inst.Index) !void { |
| 852 | return self.finishAir(inst, result, .{ .none, .none, .none }); | 852 | return self.finishAir(inst, result, .{ .none, .none, .none }); |
| 853 | } | 853 | } |
| 854 | | 854 | |
| | 855 | fn airBr(self: *Self, inst: Air.Inst.Index) !void { |
| | 856 | const branch = self.air.instructions.items(.data)[inst].br; |
| | 857 | try self.br(branch.block_inst, branch.operand); |
| | 858 | return self.finishAir(inst, .dead, .{ branch.operand, .none, .none }); |
| | 859 | } |
| | 860 | |
| 855 | fn airBreakpoint(self: *Self) !void { | 861 | fn airBreakpoint(self: *Self) !void { |
| 856 | // ta 0x01 | 862 | // ta 0x01 |
| 857 | _ = try self.addInst(.{ | 863 | _ = try self.addInst(.{ |
| ... | @@ -1365,6 +1371,56 @@ fn allocRegOrMem(self: *Self, inst: Air.Inst.Index, reg_ok: bool) !MCValue { | ... | @@ -1365,6 +1371,56 @@ fn allocRegOrMem(self: *Self, inst: Air.Inst.Index, reg_ok: bool) !MCValue { |
| 1365 | return MCValue{ .stack_offset = stack_offset }; | 1371 | return MCValue{ .stack_offset = stack_offset }; |
| 1366 | } | 1372 | } |
| 1367 | | 1373 | |
| | 1374 | fn br(self: *Self, block: Air.Inst.Index, operand: Air.Inst.Ref) !void { |
| | 1375 | const block_data = self.blocks.getPtr(block).?; |
| | 1376 | |
| | 1377 | if (self.air.typeOf(operand).hasRuntimeBits()) { |
| | 1378 | const operand_mcv = try self.resolveInst(operand); |
| | 1379 | const block_mcv = block_data.mcv; |
| | 1380 | if (block_mcv == .none) { |
| | 1381 | block_data.mcv = switch (operand_mcv) { |
| | 1382 | .none, .dead, .unreach => unreachable, |
| | 1383 | .register, .stack_offset, .memory => operand_mcv, |
| | 1384 | .immediate => blk: { |
| | 1385 | const new_mcv = try self.allocRegOrMem(block, true); |
| | 1386 | try self.setRegOrMem(self.air.typeOfIndex(block), new_mcv, operand_mcv); |
| | 1387 | break :blk new_mcv; |
| | 1388 | }, |
| | 1389 | else => return self.fail("TODO implement block_data.mcv = operand_mcv for {}", .{operand_mcv}), |
| | 1390 | }; |
| | 1391 | } else { |
| | 1392 | try self.setRegOrMem(self.air.typeOfIndex(block), block_mcv, operand_mcv); |
| | 1393 | } |
| | 1394 | } |
| | 1395 | return self.brVoid(block); |
| | 1396 | } |
| | 1397 | |
| | 1398 | fn brVoid(self: *Self, block: Air.Inst.Index) !void { |
| | 1399 | const block_data = self.blocks.getPtr(block).?; |
| | 1400 | |
| | 1401 | // Emit a jump with a relocation. It will be patched up after the block ends. |
| | 1402 | try block_data.relocs.ensureUnusedCapacity(self.gpa, 1); |
| | 1403 | |
| | 1404 | const br_index = try self.addInst(.{ |
| | 1405 | .tag = .bpcc, |
| | 1406 | .data = .{ |
| | 1407 | .branch_predict_int = .{ |
| | 1408 | .ccr = .xcc, |
| | 1409 | .cond = .al, |
| | 1410 | .inst = undefined, // Will be filled by performReloc |
| | 1411 | }, |
| | 1412 | }, |
| | 1413 | }); |
| | 1414 | |
| | 1415 | // TODO Find a way to fill this delay slot |
| | 1416 | _ = try self.addInst(.{ |
| | 1417 | .tag = .nop, |
| | 1418 | .data = .{ .nop = {} }, |
| | 1419 | }); |
| | 1420 | |
| | 1421 | block_data.relocs.appendAssumeCapacity(br_index); |
| | 1422 | } |
| | 1423 | |
| 1368 | /// Copies a value to a register without tracking the register. The register is not considered | 1424 | /// Copies a value to a register without tracking the register. The register is not considered |
| 1369 | /// allocated. A second call to `copyToTmpRegister` may return the same register. | 1425 | /// allocated. A second call to `copyToTmpRegister` may return the same register. |
| 1370 | /// This can have a side effect of spilling instructions to the stack to free up a register. | 1426 | /// This can have a side effect of spilling instructions to the stack to free up a register. |