aboutsummaryrefslogtreecommitdiff
path: root/src/codegen/llvm.zig
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2022-01-30 16:23:31 -0700
committerAndrew Kelley <andrew@ziglang.org>2022-01-30 16:23:31 -0700
commitfb7060d3c2e8ce4d7de5560adf8ec4a26fc5f6e8 (patch)
tree3710af0870e1e1d43f44830d6ff3e662761e93ce /src/codegen/llvm.zig
parent0c30799d4039c30f95eee29e2c2f8f604e8b9880 (diff)
downloadzig-fb7060d3c2e8ce4d7de5560adf8ec4a26fc5f6e8.tar.gz
zig-fb7060d3c2e8ce4d7de5560adf8ec4a26fc5f6e8.zip
stage2: implement shl_exact and shr_exact
These produce an undefined value when one bits are shifted out. New AIR instruction: shr_exact.
Diffstat (limited to 'src/codegen/llvm.zig')
-rw-r--r--src/codegen/llvm.zig20
1 files changed, 15 insertions, 5 deletions
diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig
index df64c0c912..81742d4866 100644
--- a/src/codegen/llvm.zig
+++ b/src/codegen/llvm.zig
@@ -2047,7 +2047,8 @@ pub const FuncGen = struct {
.bit_and, .bool_and => try self.airAnd(inst),
.bit_or, .bool_or => try self.airOr(inst),
.xor => try self.airXor(inst),
- .shr => try self.airShr(inst),
+ .shr => try self.airShr(inst, false),
+ .shr_exact => try self.airShr(inst, true),
.cmp_eq => try self.airCmp(inst, .eq),
.cmp_gt => try self.airCmp(inst, .gt),
@@ -3633,7 +3634,7 @@ pub const FuncGen = struct {
return self.builder.buildUShlSat(lhs, casted_rhs, "");
}
- fn airShr(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value {
+ fn airShr(self: *FuncGen, inst: Air.Inst.Index, is_exact: bool) !?*const llvm.Value {
if (self.liveness.isUnused(inst))
return null;
const bin_op = self.air.instructions.items(.data)[inst].bin_op;
@@ -3645,11 +3646,20 @@ pub const FuncGen = struct {
self.builder.buildZExt(rhs, try self.dg.llvmType(lhs_type), "")
else
rhs;
+ const is_signed_int = self.air.typeOfIndex(inst).isSignedInt();
- if (self.air.typeOfIndex(inst).isSignedInt()) {
- return self.builder.buildAShr(lhs, casted_rhs, "");
+ if (is_exact) {
+ if (is_signed_int) {
+ return self.builder.buildAShrExact(lhs, casted_rhs, "");
+ } else {
+ return self.builder.buildLShrExact(lhs, casted_rhs, "");
+ }
} else {
- return self.builder.buildLShr(lhs, casted_rhs, "");
+ if (is_signed_int) {
+ return self.builder.buildAShr(lhs, casted_rhs, "");
+ } else {
+ return self.builder.buildLShr(lhs, casted_rhs, "");
+ }
}
}