From 6878528c62ecfb505da8c320511414c9473010bb Mon Sep 17 00:00:00 2001 From: Shaikh Ubaid Date: Tue, 31 Jan 2023 22:19:16 +0530 Subject: [PATCH 1/4] WASM: Support shift operations BitRShift is currently signed/arithmetic right shift. This is similar to LLVM Backend. --- src/libasr/codegen/asr_to_wasm.cpp | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/libasr/codegen/asr_to_wasm.cpp b/src/libasr/codegen/asr_to_wasm.cpp index 8b69eea222..49cfd90d6b 100644 --- a/src/libasr/codegen/asr_to_wasm.cpp +++ b/src/libasr/codegen/asr_to_wasm.cpp @@ -890,6 +890,14 @@ class ASRToWASMVisitor : public ASR::BaseVisitor { wasm::emit_i32_xor(m_code_section, m_al); break; }; + case ASR::binopType::BitLShift: { + wasm::emit_i32_shl(m_code_section, m_al); + break; + }; + case ASR::binopType::BitRShift: { + wasm::emit_i32_shr_s(m_code_section, m_al); + break; + }; default: { throw CodeGenError( "ICE IntegerBinop kind 4: unknown operation"); @@ -947,6 +955,14 @@ class ASRToWASMVisitor : public ASR::BaseVisitor { wasm::emit_i64_xor(m_code_section, m_al); break; }; + case ASR::binopType::BitLShift: { + wasm::emit_i64_shl(m_code_section, m_al); + break; + }; + case ASR::binopType::BitRShift: { + wasm::emit_i64_shr_s(m_code_section, m_al); + break; + }; default: { throw CodeGenError( "ICE IntegerBinop kind 8: unknown operation"); From cdf08dd2741ed078f74799fbb166aae81e387fff Mon Sep 17 00:00:00 2001 From: Shaikh Ubaid Date: Tue, 31 Jan 2023 22:19:44 +0530 Subject: [PATCH 2/4] TEST: Add/Update test for shift operations --- integration_tests/bit_operations_i32.py | 28 +++++++++++++++++++++++++ integration_tests/bit_operations_i64.py | 28 +++++++++++++++++++++++++ 2 files changed, 56 insertions(+) diff --git a/integration_tests/bit_operations_i32.py b/integration_tests/bit_operations_i32.py index 859be4dd12..67934c8ce3 100644 --- a/integration_tests/bit_operations_i32.py +++ b/integration_tests/bit_operations_i32.py @@ -87,10 +87,38 @@ def test_bitxor(): assert(r == -1) assert(s == -2147483643) +def test_left_shift(): + a: i32 = 4 + shift_amount: i32 = 2 + b: i32 = a << shift_amount + print(b) + assert b == 16 + + a = -16 + shift_amount = 2 + b = a << shift_amount + print(b) + assert b == -64 + +def test_right_shift(): + a: i32 = 16 + shift_amount: i32 = 2 + b: i32 = a >> shift_amount + print(b) + assert b == 4 + + a = -16 + shift_amount = 2 + b = a >> shift_amount + print(b) + assert b == -4 + def main0(): test_bitnot() test_bitand() test_bitor() test_bitxor() + test_left_shift() + test_right_shift() main0() diff --git a/integration_tests/bit_operations_i64.py b/integration_tests/bit_operations_i64.py index 6b9eb2ef1c..c1ac77c413 100644 --- a/integration_tests/bit_operations_i64.py +++ b/integration_tests/bit_operations_i64.py @@ -84,10 +84,38 @@ def test_bitxor(): assert(r == i64(-1)) assert(s == i64(-115292150461418)) +def test_left_shift(): + a: i64 = i64(4294967296) + shift_amount: i64 = i64(2) + b: i64 = a << shift_amount + print(b) + assert b == i64(17179869184) + + a = i64(-4294967296) + shift_amount = i64(2) + b = a << shift_amount + print(b) + assert b == i64(-17179869184) + +def test_right_shift(): + a: i64 = i64(4294967296) + shift_amount: i64 = i64(2) + b: i64 = a >> shift_amount + print(b) + assert b == i64(1073741824) + + a = i64(-4294967296) + shift_amount = i64(2) + b = a >> shift_amount + print(b) + assert b == i64(-1073741824) + def main0(): test_bitnot() test_bitand() test_bitor() test_bitxor() + test_left_shift() + test_right_shift() main0() From a0458491bc69d0747484de46fcb20b823ca9aafb Mon Sep 17 00:00:00 2001 From: Shaikh Ubaid Date: Wed, 1 Feb 2023 12:09:21 +0530 Subject: [PATCH 3/4] X86Assembler: Implement SHL and SAR Instructions --- src/libasr/codegen/x86_assembler.h | 32 ++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/src/libasr/codegen/x86_assembler.h b/src/libasr/codegen/x86_assembler.h index 2f5925aa1b..2b2d37e5ff 100644 --- a/src/libasr/codegen/x86_assembler.h +++ b/src/libasr/codegen/x86_assembler.h @@ -1254,6 +1254,38 @@ class X86Assembler { EMIT("syscall"); } + // SHL - Shift Logical/Unsigned Left + void asm_shl_r64_cl(X64Reg r64) { + X86Reg r32 = X86Reg(r64 & 7); + m_code.push_back(m_al, rex(1, 0, 0, r64 >> 3)); + m_code.push_back(m_al, 0xD3); + modrm_sib_disp(m_code, m_al, X86Reg::esp, &r32, nullptr, 1, 0, false); + EMIT("shl " + r2s(r64) + ", cl"); + } + + // SHL - Shift Logical/Unsigned Left + void asm_shl_r32_cl(X86Reg r32) { + m_code.push_back(m_al, 0xD3); + modrm_sib_disp(m_code, m_al, X86Reg::esp, &r32, nullptr, 1, 0, false); + EMIT("shl " + r2s(r32) + ", cl"); + } + + // SAR - Shift Arithmetic/Signed Right + void asm_sar_r64_cl(X64Reg r64) { + X86Reg r32 = X86Reg(r64 & 7); + m_code.push_back(m_al, rex(1, 0, 0, r64 >> 3)); + m_code.push_back(m_al, 0xD3); + modrm_sib_disp(m_code, m_al, X86Reg::edi, &r32, nullptr, 1, 0, false); + EMIT("sar " + r2s(r64) + ", cl"); + } + + // SAR - Shift Arithmetic/Signed Right + void asm_sar_r32_cl(X86Reg r32) { + m_code.push_back(m_al, 0xD3); + modrm_sib_disp(m_code, m_al, X86Reg::edi, &r32, nullptr, 1, 0, false); + EMIT("sar " + r2s(r32) + ", cl"); + } + void asm_fld_m32(X86Reg *base, X86Reg *index, uint8_t scale, int32_t disp) { m_code.push_back(m_al, 0xd9); From 177a12d65fd76e3ce60cd556a9db04275e84dd71 Mon Sep 17 00:00:00 2001 From: Shaikh Ubaid Date: Wed, 1 Feb 2023 12:10:14 +0530 Subject: [PATCH 4/4] WASM_X64: Support I32Shl() and I32ShrS() --- src/libasr/codegen/wasm_to_x64.cpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/libasr/codegen/wasm_to_x64.cpp b/src/libasr/codegen/wasm_to_x64.cpp index acad7b971e..8a531a4eac 100644 --- a/src/libasr/codegen/wasm_to_x64.cpp +++ b/src/libasr/codegen/wasm_to_x64.cpp @@ -309,6 +309,19 @@ class X64Visitor : public WASMDecoder, handleI32Opt([&](){ m_a.asm_xor_r64_r64(X64Reg::rax, X64Reg::rbx);}); } + void visit_I32Shl() { + m_a.asm_pop_r64(X64Reg::rcx); + m_a.asm_pop_r64(X64Reg::rax); + m_a.asm_shl_r64_cl(X64Reg::rax); + m_a.asm_push_r64(X64Reg::rax); + } + void visit_I32ShrS() { + m_a.asm_pop_r64(X64Reg::rcx); + m_a.asm_pop_r64(X64Reg::rax); + m_a.asm_sar_r64_cl(X64Reg::rax); + m_a.asm_push_r64(X64Reg::rax); + } + void visit_I32Eqz() { m_a.asm_mov_r64_imm64(X64Reg::rax, 0); m_a.asm_push_r64(X64Reg::rax);