Skip to content

Commit 2c5034a

Browse files
authored
Merge pull request #1456 from Shaikh-Ubaid/wasm_bitoperations
WASM: Support bitwise operations
2 parents 88cb648 + 725a580 commit 2c5034a

File tree

4 files changed

+230
-1
lines changed

4 files changed

+230
-1
lines changed

integration_tests/CMakeLists.txt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -343,7 +343,7 @@ RUN(NAME test_complex LABELS cpython llvm c)
343343
RUN(NAME test_max_min LABELS cpython llvm c)
344344
RUN(NAME test_global LABELS cpython llvm c)
345345
RUN(NAME test_global_decl LABELS cpython llvm c)
346-
RUN(NAME test_integer_bitnot LABELS cpython llvm c)
346+
RUN(NAME test_integer_bitnot LABELS cpython llvm c wasm)
347347
RUN(NAME test_ifexp LABELS cpython llvm c)
348348
RUN(NAME test_unary_minus LABELS cpython llvm c)
349349
RUN(NAME test_unary_plus LABELS cpython llvm c)
@@ -417,5 +417,7 @@ RUN(NAME func_dep_04 LABELS cpython llvm c)
417417
RUN(NAME float_01 LABELS cpython llvm wasm wasm_x64)
418418
RUN(NAME recursive_01 LABELS cpython llvm wasm wasm_x64 wasm_x86)
419419
RUN(NAME comp_01 LABELS cpython llvm wasm wasm_x64)
420+
RUN(NAME bit_operations_i32 LABELS cpython llvm wasm)
421+
RUN(NAME bit_operations_i64 LABELS cpython llvm wasm)
420422

421423
RUN(NAME test_argv_01 LABELS llvm) # TODO: Test using CPython
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
from ltypes import i32
2+
3+
def test_bitnot():
4+
x: i32 = 5
5+
y: i32 = 0
6+
z: i32 = 2147483647
7+
w: i32 = -2147483648
8+
9+
p: i32 = ~x
10+
q: i32 = ~y
11+
r: i32 = ~z
12+
s: i32 = ~w
13+
14+
print(p)
15+
print(q)
16+
print(r)
17+
print(s)
18+
19+
assert(p == -6)
20+
assert(q == -1)
21+
assert(r == -2147483648)
22+
assert(s == 2147483647)
23+
24+
def test_bitand():
25+
x: i32 = 5
26+
y: i32 = 3
27+
z: i32 = 2147483647
28+
w: i32 = -2147483648
29+
30+
31+
p: i32 = x & y
32+
q: i32 = y & z
33+
r: i32 = z & w
34+
s: i32 = x & w
35+
36+
print(p)
37+
print(q)
38+
print(r)
39+
print(s)
40+
41+
assert(p == 1)
42+
assert(q == 3)
43+
assert(r == 0)
44+
assert(s == 0)
45+
46+
def test_bitor():
47+
x: i32 = 5
48+
y: i32 = 3
49+
z: i32 = 2147483647
50+
w: i32 = -2147483648
51+
52+
53+
p: i32 = x | y
54+
q: i32 = y | z
55+
r: i32 = z | w
56+
s: i32 = x | w
57+
58+
print(p)
59+
print(q)
60+
print(r)
61+
print(s)
62+
63+
assert(p == 7)
64+
assert(q == 2147483647)
65+
assert(r == -1)
66+
assert(s == -2147483643)
67+
68+
def test_bitxor():
69+
x: i32 = 5
70+
y: i32 = 3
71+
z: i32 = 2147483647
72+
w: i32 = -2147483648
73+
74+
75+
p: i32 = x ^ y
76+
q: i32 = y ^ z
77+
r: i32 = z ^ w
78+
s: i32 = x ^ w
79+
80+
print(p)
81+
print(q)
82+
print(r)
83+
print(s)
84+
85+
assert(p == 6)
86+
assert(q == 2147483644)
87+
assert(r == -1)
88+
assert(s == -2147483643)
89+
90+
def main0():
91+
test_bitnot()
92+
test_bitand()
93+
test_bitor()
94+
test_bitxor()
95+
96+
main0()
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
from ltypes import i64
2+
3+
def test_bitnot():
4+
x: i64 = i64(123)
5+
y: i64 = i64(456)
6+
z: i64 = i64(115292150460684)
7+
w: i64 = i64(-115292150460685)
8+
9+
p: i64 = ~x
10+
q: i64 = ~y
11+
r: i64 = ~z
12+
s: i64 = ~w
13+
14+
print(p)
15+
print(q)
16+
print(r)
17+
print(s)
18+
19+
assert(p == i64(-124))
20+
assert(q == i64(-457))
21+
assert(r == i64(-115292150460685))
22+
assert(s == i64(115292150460684))
23+
24+
def test_bitand():
25+
x: i64 = i64(741)
26+
y: i64 = i64(982)
27+
z: i64 = i64(115292150460684)
28+
w: i64 = i64(-115292150460685)
29+
30+
p: i64 = x & y
31+
q: i64 = y & z
32+
r: i64 = z & w
33+
s: i64 = x & w
34+
35+
print(p)
36+
print(q)
37+
print(r)
38+
print(s)
39+
40+
assert(p == i64(708))
41+
assert(q == i64(260))
42+
assert(r == i64(0))
43+
assert(s == i64(737))
44+
45+
def test_bitor():
46+
x: i64 = i64(741)
47+
y: i64 = i64(982)
48+
z: i64 = i64(115292150460684)
49+
w: i64 = i64(-115292150460685)
50+
51+
p: i64 = x | y
52+
q: i64 = y | z
53+
r: i64 = z | w
54+
s: i64 = x | w
55+
56+
print(p)
57+
print(q)
58+
print(r)
59+
print(s)
60+
61+
assert(p == i64(1015))
62+
assert(q == i64(115292150461406))
63+
assert(r == i64(-1))
64+
assert(s == i64(-115292150460681))
65+
66+
def test_bitxor():
67+
x: i64 = i64(741)
68+
y: i64 = i64(982)
69+
z: i64 = i64(115292150460684)
70+
w: i64 = i64(-115292150460685)
71+
72+
p: i64 = x ^ y
73+
q: i64 = y ^ z
74+
r: i64 = z ^ w
75+
s: i64 = x ^ w
76+
77+
print(p)
78+
print(q)
79+
print(r)
80+
print(s)
81+
82+
assert(p == i64(307))
83+
assert(q == i64(115292150461146))
84+
assert(r == i64(-1))
85+
assert(s == i64(-115292150461418))
86+
87+
def main0():
88+
test_bitnot()
89+
test_bitand()
90+
test_bitor()
91+
test_bitxor()
92+
93+
main0()

src/libasr/codegen/asr_to_wasm.cpp

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -882,6 +882,14 @@ class ASRToWASMVisitor : public ASR::BaseVisitor<ASRToWASMVisitor> {
882882
wasm::emit_i32_and(m_code_section, m_al);
883883
break;
884884
};
885+
case ASR::binopType::BitOr: {
886+
wasm::emit_i32_or(m_code_section, m_al);
887+
break;
888+
};
889+
case ASR::binopType::BitXor: {
890+
wasm::emit_i32_xor(m_code_section, m_al);
891+
break;
892+
};
885893
default: {
886894
throw CodeGenError(
887895
"ICE IntegerBinop kind 4: unknown operation");
@@ -931,6 +939,14 @@ class ASRToWASMVisitor : public ASR::BaseVisitor<ASRToWASMVisitor> {
931939
wasm::emit_i64_and(m_code_section, m_al);
932940
break;
933941
};
942+
case ASR::binopType::BitOr: {
943+
wasm::emit_i64_or(m_code_section, m_al);
944+
break;
945+
};
946+
case ASR::binopType::BitXor: {
947+
wasm::emit_i64_xor(m_code_section, m_al);
948+
break;
949+
};
934950
default: {
935951
throw CodeGenError(
936952
"ICE IntegerBinop kind 8: unknown operation");
@@ -941,6 +957,28 @@ class ASRToWASMVisitor : public ASR::BaseVisitor<ASRToWASMVisitor> {
941957
}
942958
}
943959

960+
void visit_IntegerBitNot(const ASR::IntegerBitNot_t &x) {
961+
if (x.m_value) {
962+
visit_expr(*x.m_value);
963+
return;
964+
}
965+
this->visit_expr(*x.m_arg);
966+
ASR::Integer_t *i = ASR::down_cast<ASR::Integer_t>(x.m_type);
967+
// there is no direct bit-invert inst in wasm,
968+
// so xor-ing with -1 (sequence of 32/64 1s)
969+
if(i->m_kind == 4){
970+
wasm::emit_i32_const(m_code_section, m_al, -1);
971+
wasm::emit_i32_xor(m_code_section, m_al);
972+
}
973+
else if(i->m_kind == 8){
974+
wasm::emit_i64_const(m_code_section, m_al, -1LL);
975+
wasm::emit_i64_xor(m_code_section, m_al);
976+
}
977+
else{
978+
throw CodeGenError("IntegerBitNot: Only kind 4 and 8 supported");
979+
}
980+
}
981+
944982
void visit_RealBinOp(const ASR::RealBinOp_t &x) {
945983
if (x.m_value) {
946984
visit_expr(*x.m_value);

0 commit comments

Comments
 (0)