Skip to content

Commit a34f3ff

Browse files
stage2 ARM: implement try AIR instruction
1 parent ff00bbf commit a34f3ff

File tree

1 file changed

+70
-44
lines changed

1 file changed

+70
-44
lines changed

src/arch/arm/CodeGen.zig

Lines changed: 70 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -677,8 +677,8 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
677677
.prefetch => try self.airPrefetch(inst),
678678
.mul_add => try self.airMulAdd(inst),
679679

680-
.@"try" => @panic("TODO"),
681-
.try_ptr => @panic("TODO"),
680+
.@"try" => try self.airTry(inst),
681+
.try_ptr => try self.airTryPtr(inst),
682682

683683
.dbg_var_ptr,
684684
.dbg_var_val,
@@ -1837,8 +1837,8 @@ fn airUnwrapErrPayload(self: *Self, inst: Air.Inst.Index) !void {
18371837
const ty_op = self.air.instructions.items(.data)[inst].ty_op;
18381838
const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
18391839
const error_union_ty = self.air.typeOf(ty_op.operand);
1840-
const mcv = try self.resolveInst(ty_op.operand);
1841-
break :result try self.errUnionPayload(mcv, error_union_ty);
1840+
const error_union = try self.resolveInst(ty_op.operand);
1841+
break :result try self.errUnionPayload(error_union, error_union_ty);
18421842
};
18431843
return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
18441844
}
@@ -3705,6 +3705,42 @@ fn airDbgVar(self: *Self, inst: Air.Inst.Index) !void {
37053705
return self.finishAir(inst, .dead, .{ operand, .none, .none });
37063706
}
37073707

3708+
/// Given a boolean condition, emit a jump that is taken when that
3709+
/// condition is false.
3710+
fn condBr(self: *Self, condition: MCValue) !Mir.Inst.Index {
3711+
const condition_code: Condition = switch (condition) {
3712+
.cpsr_flags => |cond| cond.negate(),
3713+
else => blk: {
3714+
const reg = switch (condition) {
3715+
.register => |r| r,
3716+
else => try self.copyToTmpRegister(Type.bool, condition),
3717+
};
3718+
3719+
try self.spillCompareFlagsIfOccupied();
3720+
3721+
// cmp reg, 1
3722+
// bne ...
3723+
_ = try self.addInst(.{
3724+
.tag = .cmp,
3725+
.cond = .al,
3726+
.data = .{ .rr_op = .{
3727+
.rd = .r0,
3728+
.rn = reg,
3729+
.op = Instruction.Operand.imm(1, 0),
3730+
} },
3731+
});
3732+
3733+
break :blk .ne;
3734+
},
3735+
};
3736+
3737+
return try self.addInst(.{
3738+
.tag = .b,
3739+
.cond = condition_code,
3740+
.data = .{ .inst = undefined }, // populated later through performReloc
3741+
});
3742+
}
3743+
37083744
fn airCondBr(self: *Self, inst: Air.Inst.Index) !void {
37093745
const pl_op = self.air.instructions.items(.data)[inst].pl_op;
37103746
const cond_inst = try self.resolveInst(pl_op.operand);
@@ -3713,39 +3749,7 @@ fn airCondBr(self: *Self, inst: Air.Inst.Index) !void {
37133749
const else_body = self.air.extra[extra.end + then_body.len ..][0..extra.data.else_body_len];
37143750
const liveness_condbr = self.liveness.getCondBr(inst);
37153751

3716-
const reloc: Mir.Inst.Index = reloc: {
3717-
const condition: Condition = switch (cond_inst) {
3718-
.cpsr_flags => |cond| cond.negate(),
3719-
else => blk: {
3720-
const reg = switch (cond_inst) {
3721-
.register => |r| r,
3722-
else => try self.copyToTmpRegister(Type.bool, cond_inst),
3723-
};
3724-
3725-
try self.spillCompareFlagsIfOccupied();
3726-
3727-
// cmp reg, 1
3728-
// bne ...
3729-
_ = try self.addInst(.{
3730-
.tag = .cmp,
3731-
.cond = .al,
3732-
.data = .{ .rr_op = .{
3733-
.rd = .r0,
3734-
.rn = reg,
3735-
.op = Instruction.Operand.imm(1, 0),
3736-
} },
3737-
});
3738-
3739-
break :blk .ne;
3740-
},
3741-
};
3742-
3743-
break :reloc try self.addInst(.{
3744-
.tag = .b,
3745-
.cond = condition,
3746-
.data = .{ .inst = undefined }, // populated later through performReloc
3747-
});
3748-
};
3752+
const reloc: Mir.Inst.Index = try self.condBr(cond_inst);
37493753

37503754
// If the condition dies here in this condbr instruction, process
37513755
// 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 {
41574161
.lhs = condition,
41584162
.rhs = item,
41594163
} };
4160-
const cmp_result = try self.cmp(operands, condition_ty, .neq);
4161-
4162-
relocs[0] = try self.addInst(.{
4163-
.tag = .b,
4164-
.cond = cmp_result.cpsr_flags,
4165-
.data = .{ .inst = undefined }, // populated later through performReloc
4166-
});
4164+
const cmp_result = try self.cmp(operands, condition_ty, .eq);
4165+
relocs[0] = try self.condBr(cmp_result);
41674166
} else {
41684167
return self.fail("TODO switch with multiple items", .{});
41694168
}
@@ -5148,6 +5147,33 @@ fn airMulAdd(self: *Self, inst: Air.Inst.Index) !void {
51485147
return self.finishAir(inst, result, .{ extra.lhs, extra.rhs, pl_op.operand });
51495148
}
51505149

5150+
fn airTry(self: *Self, inst: Air.Inst.Index) !void {
5151+
const pl_op = self.air.instructions.items(.data)[inst].pl_op;
5152+
const extra = self.air.extraData(Air.Try, pl_op.payload);
5153+
const body = self.air.extra[extra.end..][0..extra.data.body_len];
5154+
const result: MCValue = result: {
5155+
const error_union_ty = self.air.typeOf(pl_op.operand);
5156+
const error_union = try self.resolveInst(pl_op.operand);
5157+
const is_err_result = try self.isErr(error_union_ty, error_union);
5158+
const reloc = try self.condBr(is_err_result);
5159+
5160+
try self.genBody(body);
5161+
5162+
try self.performReloc(reloc);
5163+
break :result try self.errUnionPayload(error_union, error_union_ty);
5164+
};
5165+
return self.finishAir(inst, result, .{ pl_op.operand, .none, .none });
5166+
}
5167+
5168+
fn airTryPtr(self: *Self, inst: Air.Inst.Index) !void {
5169+
const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
5170+
const extra = self.air.extraData(Air.TryPtr, ty_pl.payload);
5171+
const body = self.air.extra[extra.end..][0..extra.data.body_len];
5172+
_ = body;
5173+
return self.fail("TODO implement airTryPtr for arm", .{});
5174+
// return self.finishAir(inst, result, .{ extra.data.ptr, .none, .none });
5175+
}
5176+
51515177
fn resolveInst(self: *Self, inst: Air.Inst.Ref) InnerError!MCValue {
51525178
// First section of indexes correspond to a set number of constant values.
51535179
const ref_int = @enumToInt(inst);

0 commit comments

Comments
 (0)