aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorjoachimschmidt557 <joachim.schmidt557@outlook.com>2022-11-20 21:02:20 +0100
committerJoachim Schmidt <joachim.schmidt557@outlook.com>2022-11-21 08:23:07 +0100
commit89c374cd2dff36477ac1513006c03721ef946a2a (patch)
treeedecb573b328e56941564b8ed413af8424739389 /src
parentc45c6cd492e9a5f351fa9290c7f7385d743b3818 (diff)
downloadzig-89c374cd2dff36477ac1513006c03721ef946a2a.tar.gz
zig-89c374cd2dff36477ac1513006c03721ef946a2a.zip
stage2 ARM: misc fixes
- remove redundant `new` from `binOpRegisterNew` name - fix mul_with_overflow
Diffstat (limited to 'src')
-rw-r--r--src/arch/arm/CodeGen.zig171
1 files changed, 105 insertions, 66 deletions
diff --git a/src/arch/arm/CodeGen.zig b/src/arch/arm/CodeGen.zig
index 67cf899dc3..e99d8bb256 100644
--- a/src/arch/arm/CodeGen.zig
+++ b/src/arch/arm/CodeGen.zig
@@ -1416,8 +1416,9 @@ fn airBinOp(self: *Self, inst: Air.Inst.Index, tag: Air.Inst.Tag) !void {
.div_float => try self.divFloat(lhs_bind, rhs_bind, lhs_ty, rhs_ty, inst),
- .div_trunc => try self.div(tag, lhs_bind, rhs_bind, lhs_ty, rhs_ty, inst),
- .div_floor => try self.div(tag, lhs_bind, rhs_bind, lhs_ty, rhs_ty, inst),
+ .div_trunc => try self.divTrunc(lhs_bind, rhs_bind, lhs_ty, rhs_ty, inst),
+
+ .div_floor => try self.divFloor(lhs_bind, rhs_bind, lhs_ty, rhs_ty, inst),
.div_exact => try self.divExact(lhs_bind, rhs_bind, lhs_ty, rhs_ty, inst),
@@ -1567,12 +1568,12 @@ fn airOverflow(self: *Self, inst: Air.Inst.Index) !void {
const dest = blk: {
if (rhs_immediate_ok) {
- break :blk try self.binOpImmediateNew(mir_tag, lhs_bind, rhs_immediate.?, lhs_ty, false, null);
+ break :blk try self.binOpImmediate(mir_tag, lhs_bind, rhs_immediate.?, lhs_ty, false, null);
} else if (lhs_immediate_ok) {
// swap lhs and rhs
- break :blk try self.binOpImmediateNew(mir_tag, rhs_bind, lhs_immediate.?, rhs_ty, true, null);
+ break :blk try self.binOpImmediate(mir_tag, rhs_bind, lhs_immediate.?, rhs_ty, true, null);
} else {
- break :blk try self.binOpRegisterNew(mir_tag, lhs_bind, rhs_bind, lhs_ty, rhs_ty, null);
+ break :blk try self.binOpRegister(mir_tag, lhs_bind, rhs_bind, lhs_ty, rhs_ty, null);
}
};
@@ -1625,7 +1626,7 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
.unsigned => .mul,
};
- const dest = try self.binOpRegisterNew(base_tag, lhs_bind, rhs_bind, lhs_ty, rhs_ty, null);
+ const dest = try self.binOpRegister(base_tag, lhs_bind, rhs_bind, lhs_ty, rhs_ty, null);
const dest_reg = dest.register;
const dest_reg_lock = self.register_manager.lockRegAssumeUnused(dest_reg);
defer self.register_manager.unlockReg(dest_reg_lock);
@@ -3123,7 +3124,7 @@ fn allocRegs(
/// instructions which are binary operations acting on two registers
///
/// Returns the destination register
-fn binOpRegisterNew(
+fn binOpRegister(
self: *Self,
mir_tag: Mir.Inst.Tag,
lhs_bind: ReadArg.Bind,
@@ -3196,7 +3197,7 @@ fn binOpRegisterNew(
/// an immediate
///
/// Returns the destination register
-fn binOpImmediateNew(
+fn binOpImmediate(
self: *Self,
mir_tag: Mir.Inst.Tag,
lhs_bind: ReadArg.Bind,
@@ -3265,11 +3266,11 @@ fn addSub(
rhs_ty: Type,
maybe_inst: ?Air.Inst.Index,
) InnerError!MCValue {
+ const mod = self.bin_file.options.module.?;
switch (lhs_ty.zigTypeTag()) {
.Float => return self.fail("TODO ARM binary operations on floats", .{}),
.Vector => return self.fail("TODO ARM binary operations on vectors", .{}),
.Int => {
- const mod = self.bin_file.options.module.?;
assert(lhs_ty.eql(rhs_ty, mod));
const int_info = lhs_ty.intInfo(self.target.*);
if (int_info.bits <= 32) {
@@ -3298,12 +3299,12 @@ fn addSub(
};
if (rhs_immediate_ok) {
- return try self.binOpImmediateNew(mir_tag, lhs_bind, rhs_immediate.?, lhs_ty, false, maybe_inst);
+ return try self.binOpImmediate(mir_tag, lhs_bind, rhs_immediate.?, lhs_ty, false, maybe_inst);
} else if (lhs_immediate_ok) {
// swap lhs and rhs
- return try self.binOpImmediateNew(mir_tag, rhs_bind, lhs_immediate.?, rhs_ty, true, maybe_inst);
+ return try self.binOpImmediate(mir_tag, rhs_bind, lhs_immediate.?, rhs_ty, true, maybe_inst);
} else {
- return try self.binOpRegisterNew(mir_tag, lhs_bind, rhs_bind, lhs_ty, rhs_ty, maybe_inst);
+ return try self.binOpRegister(mir_tag, lhs_bind, rhs_bind, lhs_ty, rhs_ty, maybe_inst);
}
} else {
return self.fail("TODO ARM binary operations on integers > u32/i32", .{});
@@ -3321,18 +3322,18 @@ fn mul(
rhs_ty: Type,
maybe_inst: ?Air.Inst.Index,
) InnerError!MCValue {
+ const mod = self.bin_file.options.module.?;
switch (lhs_ty.zigTypeTag()) {
.Float => return self.fail("TODO ARM binary operations on floats", .{}),
.Vector => return self.fail("TODO ARM binary operations on vectors", .{}),
.Int => {
- const mod = self.bin_file.options.module.?;
assert(lhs_ty.eql(rhs_ty, mod));
const int_info = lhs_ty.intInfo(self.target.*);
if (int_info.bits <= 32) {
// TODO add optimisations for multiplication
// with immediates, for example a * 2 can be
// lowered to a << 1
- return try self.binOpRegisterNew(.mul, lhs_bind, rhs_bind, lhs_ty, rhs_ty, maybe_inst);
+ return try self.binOpRegister(.mul, lhs_bind, rhs_bind, lhs_ty, rhs_ty, maybe_inst);
} else {
return self.fail("TODO ARM binary operations on integers > u32/i32", .{});
}
@@ -3361,22 +3362,62 @@ fn divFloat(
}
}
-fn div(
+fn divTrunc(
self: *Self,
- tag: Air.Inst.Tag,
lhs_bind: ReadArg.Bind,
rhs_bind: ReadArg.Bind,
lhs_ty: Type,
rhs_ty: Type,
maybe_inst: ?Air.Inst.Index,
) InnerError!MCValue {
- _ = tag;
+ const mod = self.bin_file.options.module.?;
+ switch (lhs_ty.zigTypeTag()) {
+ .Float => return self.fail("TODO ARM binary operations on floats", .{}),
+ .Vector => return self.fail("TODO ARM binary operations on vectors", .{}),
+ .Int => {
+ assert(lhs_ty.eql(rhs_ty, mod));
+ const int_info = lhs_ty.intInfo(self.target.*);
+ if (int_info.bits <= 32) {
+ switch (int_info.signedness) {
+ .signed => {
+ return self.fail("TODO ARM signed integer division", .{});
+ },
+ .unsigned => {
+ const rhs_immediate = try rhs_bind.resolveToImmediate(self);
+
+ if (rhs_immediate) |imm| {
+ if (std.math.isPowerOfTwo(imm)) {
+ const shift = std.math.log2_int(u32, imm);
+ return try self.binOpImmediate(.lsr, lhs_bind, shift, lhs_ty, false, maybe_inst);
+ } else {
+ return self.fail("TODO ARM integer division by constants", .{});
+ }
+ } else {
+ return self.fail("TODO ARM integer division", .{});
+ }
+ },
+ }
+ } else {
+ return self.fail("TODO ARM integer division for integers > u32/i32", .{});
+ }
+ },
+ else => unreachable,
+ }
+}
+fn divFloor(
+ self: *Self,
+ lhs_bind: ReadArg.Bind,
+ rhs_bind: ReadArg.Bind,
+ lhs_ty: Type,
+ rhs_ty: Type,
+ maybe_inst: ?Air.Inst.Index,
+) InnerError!MCValue {
+ const mod = self.bin_file.options.module.?;
switch (lhs_ty.zigTypeTag()) {
.Float => return self.fail("TODO ARM binary operations on floats", .{}),
.Vector => return self.fail("TODO ARM binary operations on vectors", .{}),
.Int => {
- const mod = self.bin_file.options.module.?;
assert(lhs_ty.eql(rhs_ty, mod));
const int_info = lhs_ty.intInfo(self.target.*);
if (int_info.bits <= 32) {
@@ -3390,7 +3431,7 @@ fn div(
if (rhs_immediate) |imm| {
if (std.math.isPowerOfTwo(imm)) {
const shift = std.math.log2_int(u32, imm);
- return try self.binOpImmediateNew(.lsr, lhs_bind, shift, lhs_ty, false, maybe_inst);
+ return try self.binOpImmediate(.lsr, lhs_bind, shift, lhs_ty, false, maybe_inst);
} else {
return self.fail("TODO ARM integer division by constants", .{});
}
@@ -3436,11 +3477,11 @@ fn rem(
rhs_ty: Type,
maybe_inst: ?Air.Inst.Index,
) InnerError!MCValue {
+ const mod = self.bin_file.options.module.?;
switch (lhs_ty.zigTypeTag()) {
.Float => return self.fail("TODO ARM binary operations on floats", .{}),
.Vector => return self.fail("TODO ARM binary operations on vectors", .{}),
.Int => {
- const mod = self.bin_file.options.module.?;
assert(lhs_ty.eql(rhs_ty, mod));
const int_info = lhs_ty.intInfo(self.target.*);
if (int_info.bits <= 32) {
@@ -3522,28 +3563,26 @@ fn wrappingArithmetic(
rhs_ty: Type,
maybe_inst: ?Air.Inst.Index,
) InnerError!MCValue {
- const base_tag: Air.Inst.Tag = switch (tag) {
- .addwrap => .add,
- .subwrap => .sub,
- .mulwrap => .mul,
- else => unreachable,
- };
-
- // Generate an add/sub/mul
- const result = try self.addSub(base_tag, lhs_bind, rhs_bind, lhs_ty, rhs_ty, maybe_inst);
-
- // Truncate if necessary
switch (lhs_ty.zigTypeTag()) {
.Vector => return self.fail("TODO ARM binary operations on vectors", .{}),
.Int => {
const int_info = lhs_ty.intInfo(self.target.*);
if (int_info.bits <= 32) {
- const result_reg = result.register;
+ // Generate an add/sub/mul
+ const result: MCValue = switch (tag) {
+ .addwrap => try self.addSub(.add, lhs_bind, rhs_bind, lhs_ty, rhs_ty, maybe_inst),
+ .subwrap => try self.addSub(.sub, lhs_bind, rhs_bind, lhs_ty, rhs_ty, maybe_inst),
+ .mulwrap => try self.mul(lhs_bind, rhs_bind, lhs_ty, rhs_ty, maybe_inst),
+ else => unreachable,
+ };
+ // Truncate if necessary
+ const result_reg = result.register;
if (int_info.bits < 32) {
try self.truncRegister(result_reg, result_reg, int_info.signedness, int_info.bits);
- return result;
- } else return result;
+ }
+
+ return result;
} else {
return self.fail("TODO ARM binary operations on integers > u32/i32", .{});
}
@@ -3582,12 +3621,12 @@ fn bitwise(
};
if (rhs_immediate_ok) {
- return try self.binOpImmediateNew(mir_tag, lhs_bind, rhs_immediate.?, lhs_ty, false, maybe_inst);
+ return try self.binOpImmediate(mir_tag, lhs_bind, rhs_immediate.?, lhs_ty, false, maybe_inst);
} else if (lhs_immediate_ok) {
// swap lhs and rhs
- return try self.binOpImmediateNew(mir_tag, rhs_bind, lhs_immediate.?, rhs_ty, true, maybe_inst);
+ return try self.binOpImmediate(mir_tag, rhs_bind, lhs_immediate.?, rhs_ty, true, maybe_inst);
} else {
- return try self.binOpRegisterNew(mir_tag, lhs_bind, rhs_bind, lhs_ty, rhs_ty, maybe_inst);
+ return try self.binOpRegister(mir_tag, lhs_bind, rhs_bind, lhs_ty, rhs_ty, maybe_inst);
}
} else {
return self.fail("TODO ARM binary operations on integers > u32/i32", .{});
@@ -3623,9 +3662,9 @@ fn shiftExact(
};
if (rhs_immediate) |imm| {
- return try self.binOpImmediateNew(mir_tag, lhs_bind, imm, lhs_ty, false, maybe_inst);
+ return try self.binOpImmediate(mir_tag, lhs_bind, imm, lhs_ty, false, maybe_inst);
} else {
- return try self.binOpRegisterNew(mir_tag, lhs_bind, rhs_bind, lhs_ty, rhs_ty, maybe_inst);
+ return try self.binOpRegister(mir_tag, lhs_bind, rhs_bind, lhs_ty, rhs_ty, maybe_inst);
}
} else {
return self.fail("TODO ARM binary operations on integers > u32/i32", .{});
@@ -3644,34 +3683,34 @@ fn shiftNormal(
rhs_ty: Type,
maybe_inst: ?Air.Inst.Index,
) InnerError!MCValue {
- const base_tag: Air.Inst.Tag = switch (tag) {
- .shl => .shl_exact,
- .shr => .shr_exact,
- else => unreachable,
- };
-
- // Generate a shl_exact/shr_exact
- const result = try self.shiftExact(base_tag, lhs_bind, rhs_bind, lhs_ty, rhs_ty, maybe_inst);
+ switch (lhs_ty.zigTypeTag()) {
+ .Vector => return self.fail("TODO ARM binary operations on vectors", .{}),
+ .Int => {
+ const int_info = lhs_ty.intInfo(self.target.*);
+ if (int_info.bits <= 32) {
+ // Generate a shl_exact/shr_exact
+ const result: MCValue = switch (tag) {
+ .shl => try self.shiftExact(.shl_exact, lhs_bind, rhs_bind, lhs_ty, rhs_ty, maybe_inst),
+ .shr => try self.shiftExact(.shr_exact, lhs_bind, rhs_bind, lhs_ty, rhs_ty, maybe_inst),
+ else => unreachable,
+ };
- // Truncate if necessary
- switch (tag) {
- .shr => return result,
- .shl => switch (lhs_ty.zigTypeTag()) {
- .Vector => return self.fail("TODO ARM binary operations on vectors", .{}),
- .Int => {
- const int_info = lhs_ty.intInfo(self.target.*);
- if (int_info.bits <= 32) {
- const result_reg = result.register;
+ // Truncate if necessary
+ switch (tag) {
+ .shr => return result,
+ .shl => {
+ const result_reg = result.register;
+ if (int_info.bits < 32) {
+ try self.truncRegister(result_reg, result_reg, int_info.signedness, int_info.bits);
+ }
- if (int_info.bits < 32) {
- try self.truncRegister(result_reg, result_reg, int_info.signedness, int_info.bits);
return result;
- } else return result;
- } else {
- return self.fail("TODO ARM binary operations on integers > u32/i32", .{});
+ },
+ else => unreachable,
}
- },
- else => unreachable,
+ } else {
+ return self.fail("TODO ARM binary operations on integers > u32/i32", .{});
+ }
},
else => unreachable,
}
@@ -3698,12 +3737,12 @@ fn booleanOp(
};
if (rhs_immediate) |imm| {
- return try self.binOpImmediateNew(mir_tag, lhs_bind, imm, lhs_ty, false, maybe_inst);
+ return try self.binOpImmediate(mir_tag, lhs_bind, imm, lhs_ty, false, maybe_inst);
} else if (lhs_immediate) |imm| {
// swap lhs and rhs
- return try self.binOpImmediateNew(mir_tag, rhs_bind, imm, rhs_ty, true, maybe_inst);
+ return try self.binOpImmediate(mir_tag, rhs_bind, imm, rhs_ty, true, maybe_inst);
} else {
- return try self.binOpRegisterNew(mir_tag, lhs_bind, rhs_bind, lhs_ty, rhs_ty, maybe_inst);
+ return try self.binOpRegister(mir_tag, lhs_bind, rhs_bind, lhs_ty, rhs_ty, maybe_inst);
}
},
else => unreachable,