diff --git a/src/Sema.zig b/src/Sema.zig index d2b2a665e6..360d936b61 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -5294,9 +5294,25 @@ fn zirShl(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!A const tracy = trace(@src()); defer tracy.end(); - _ = block; - _ = inst; - return sema.mod.fail(&block.base, sema.src, "TODO implement zirShl", .{}); + const inst_data = sema.code.instructions.items(.data)[inst].pl_node; + const src: LazySrcLoc = .{ .node_offset_bin_op = inst_data.src_node }; + const lhs_src: LazySrcLoc = .{ .node_offset_bin_lhs = inst_data.src_node }; + const rhs_src: LazySrcLoc = .{ .node_offset_bin_rhs = inst_data.src_node }; + const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; + const lhs = sema.resolveInst(extra.lhs); + const rhs = sema.resolveInst(extra.rhs); + + if (try sema.resolveMaybeUndefVal(block, lhs_src, lhs)) |lhs_val| { + if (try sema.resolveMaybeUndefVal(block, rhs_src, rhs)) |rhs_val| { + if (lhs_val.isUndef() or rhs_val.isUndef()) { + return sema.addConstUndef(sema.typeOf(lhs)); + } + return sema.mod.fail(&block.base, src, "TODO implement comptime shl", .{}); + } + } + + try sema.requireRuntimeBlock(block, src); + return block.addBinOp(.shl, lhs, rhs); } fn zirShr(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index 4b5ac9efe9..632b275704 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -1745,7 +1745,13 @@ pub const FuncGen = struct { const bin_op = self.air.instructions.items(.data)[inst].bin_op; const lhs = try self.resolveInst(bin_op.lhs); const rhs = try self.resolveInst(bin_op.rhs); - return self.builder.buildShl(lhs, rhs, ""); + const lhs_type = self.air.typeOf(bin_op.lhs); + const tg = self.dg.module.getTarget(); + const casted_rhs = if (self.air.typeOf(bin_op.rhs).bitSize(tg) < lhs_type.bitSize(tg)) + self.builder.buildZExt(rhs, try self.dg.llvmType(lhs_type), "") + else + rhs; + return self.builder.buildShl(lhs, casted_rhs, ""); } fn airShr(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value { diff --git a/test/stage2/cbe.zig b/test/stage2/cbe.zig index 5025d2ad9f..c2c82c20e6 100644 --- a/test/stage2/cbe.zig +++ b/test/stage2/cbe.zig @@ -809,12 +809,23 @@ pub fn addCases(ctx: *TestContext) !void { } { - var case = ctx.exeUsingLlvmBackend("shift right", linux_x64); - + var case = ctx.exeFromCompiledC("shift right + left", .{}); case.addCompareOutput( - \\pub export fn main() void { + \\pub export fn main() c_int { \\ var i: u32 = 16; \\ assert(i >> 1, 8); + \\ return 0; + \\} + \\fn assert(a: u32, b: u32) void { + \\ if (a != b) unreachable; + \\} + , ""); + + case.addCompareOutput( + \\pub export fn main() c_int { + \\ var i: u32 = 16; + \\ assert(i << 1, 32); + \\ return 0; \\} \\fn assert(a: u32, b: u32) void { \\ if (a != b) unreachable; diff --git a/test/stage2/llvm.zig b/test/stage2/llvm.zig index e49641b997..9e6e938a8c 100644 --- a/test/stage2/llvm.zig +++ b/test/stage2/llvm.zig @@ -29,7 +29,7 @@ pub fn addCases(ctx: *TestContext) !void { } { - var case = ctx.exeUsingLlvmBackend("shift right", linux_x64); + var case = ctx.exeUsingLlvmBackend("shift right + left", linux_x64); case.addCompareOutput( \\pub export fn main() void { @@ -40,6 +40,15 @@ pub fn addCases(ctx: *TestContext) !void { \\ if (a != b) unreachable; \\} , ""); + case.addCompareOutput( + \\pub export fn main() void { + \\ var i: u32 = 16; + \\ assert(i << 1, 32); + \\} + \\fn assert(a: u32, b: u32) void { + \\ if (a != b) unreachable; + \\} + , ""); } {