Commit a34f3ff04a
Changed files (1)
src
arch
arm
src/arch/arm/CodeGen.zig
@@ -677,8 +677,8 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
.prefetch => try self.airPrefetch(inst),
.mul_add => try self.airMulAdd(inst),
- .@"try" => @panic("TODO"),
- .try_ptr => @panic("TODO"),
+ .@"try" => try self.airTry(inst),
+ .try_ptr => try self.airTryPtr(inst),
.dbg_var_ptr,
.dbg_var_val,
@@ -1837,8 +1837,8 @@ fn airUnwrapErrPayload(self: *Self, inst: Air.Inst.Index) !void {
const ty_op = self.air.instructions.items(.data)[inst].ty_op;
const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
const error_union_ty = self.air.typeOf(ty_op.operand);
- const mcv = try self.resolveInst(ty_op.operand);
- break :result try self.errUnionPayload(mcv, error_union_ty);
+ const error_union = try self.resolveInst(ty_op.operand);
+ break :result try self.errUnionPayload(error_union, error_union_ty);
};
return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
}
@@ -3705,6 +3705,42 @@ fn airDbgVar(self: *Self, inst: Air.Inst.Index) !void {
return self.finishAir(inst, .dead, .{ operand, .none, .none });
}
+/// Given a boolean condition, emit a jump that is taken when that
+/// condition is false.
+fn condBr(self: *Self, condition: MCValue) !Mir.Inst.Index {
+ const condition_code: Condition = switch (condition) {
+ .cpsr_flags => |cond| cond.negate(),
+ else => blk: {
+ const reg = switch (condition) {
+ .register => |r| r,
+ else => try self.copyToTmpRegister(Type.bool, condition),
+ };
+
+ try self.spillCompareFlagsIfOccupied();
+
+ // cmp reg, 1
+ // bne ...
+ _ = try self.addInst(.{
+ .tag = .cmp,
+ .cond = .al,
+ .data = .{ .rr_op = .{
+ .rd = .r0,
+ .rn = reg,
+ .op = Instruction.Operand.imm(1, 0),
+ } },
+ });
+
+ break :blk .ne;
+ },
+ };
+
+ return try self.addInst(.{
+ .tag = .b,
+ .cond = condition_code,
+ .data = .{ .inst = undefined }, // populated later through performReloc
+ });
+}
+
fn airCondBr(self: *Self, inst: Air.Inst.Index) !void {
const pl_op = self.air.instructions.items(.data)[inst].pl_op;
const cond_inst = try self.resolveInst(pl_op.operand);
@@ -3713,39 +3749,7 @@ fn airCondBr(self: *Self, inst: Air.Inst.Index) !void {
const else_body = self.air.extra[extra.end + then_body.len ..][0..extra.data.else_body_len];
const liveness_condbr = self.liveness.getCondBr(inst);
- const reloc: Mir.Inst.Index = reloc: {
- const condition: Condition = switch (cond_inst) {
- .cpsr_flags => |cond| cond.negate(),
- else => blk: {
- const reg = switch (cond_inst) {
- .register => |r| r,
- else => try self.copyToTmpRegister(Type.bool, cond_inst),
- };
-
- try self.spillCompareFlagsIfOccupied();
-
- // cmp reg, 1
- // bne ...
- _ = try self.addInst(.{
- .tag = .cmp,
- .cond = .al,
- .data = .{ .rr_op = .{
- .rd = .r0,
- .rn = reg,
- .op = Instruction.Operand.imm(1, 0),
- } },
- });
-
- break :blk .ne;
- },
- };
-
- break :reloc try self.addInst(.{
- .tag = .b,
- .cond = condition,
- .data = .{ .inst = undefined }, // populated later through performReloc
- });
- };
+ const reloc: Mir.Inst.Index = try self.condBr(cond_inst);
// If the condition dies here in this condbr instruction, process
// that death now instead of later as this has an effect on
@@ -4157,13 +4161,8 @@ fn airSwitch(self: *Self, inst: Air.Inst.Index) !void {
.lhs = condition,
.rhs = item,
} };
- const cmp_result = try self.cmp(operands, condition_ty, .neq);
-
- relocs[0] = try self.addInst(.{
- .tag = .b,
- .cond = cmp_result.cpsr_flags,
- .data = .{ .inst = undefined }, // populated later through performReloc
- });
+ const cmp_result = try self.cmp(operands, condition_ty, .eq);
+ relocs[0] = try self.condBr(cmp_result);
} else {
return self.fail("TODO switch with multiple items", .{});
}
@@ -5148,6 +5147,33 @@ fn airMulAdd(self: *Self, inst: Air.Inst.Index) !void {
return self.finishAir(inst, result, .{ extra.lhs, extra.rhs, pl_op.operand });
}
+fn airTry(self: *Self, inst: Air.Inst.Index) !void {
+ const pl_op = self.air.instructions.items(.data)[inst].pl_op;
+ const extra = self.air.extraData(Air.Try, pl_op.payload);
+ const body = self.air.extra[extra.end..][0..extra.data.body_len];
+ const result: MCValue = result: {
+ const error_union_ty = self.air.typeOf(pl_op.operand);
+ const error_union = try self.resolveInst(pl_op.operand);
+ const is_err_result = try self.isErr(error_union_ty, error_union);
+ const reloc = try self.condBr(is_err_result);
+
+ try self.genBody(body);
+
+ try self.performReloc(reloc);
+ break :result try self.errUnionPayload(error_union, error_union_ty);
+ };
+ return self.finishAir(inst, result, .{ pl_op.operand, .none, .none });
+}
+
+fn airTryPtr(self: *Self, inst: Air.Inst.Index) !void {
+ const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
+ const extra = self.air.extraData(Air.TryPtr, ty_pl.payload);
+ const body = self.air.extra[extra.end..][0..extra.data.body_len];
+ _ = body;
+ return self.fail("TODO implement airTryPtr for arm", .{});
+ // return self.finishAir(inst, result, .{ extra.data.ptr, .none, .none });
+}
+
fn resolveInst(self: *Self, inst: Air.Inst.Ref) InnerError!MCValue {
// First section of indexes correspond to a set number of constant values.
const ref_int = @enumToInt(inst);