Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 0a5d89b

Browse files
authored
Merge pull request #2328 from Shaikh-Ubaid/setup_online_lpython
Setup online lpython
2 parents df83b5a + 1b52a44 commit 0a5d89b

25 files changed

+138
-85
lines changed

.github/workflows/CI.yml

Lines changed: 1 addition & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -170,21 +170,7 @@ jobs:
170170
run: |
171171
set -ex
172172
source $HOME/ext/emsdk/emsdk_env.sh # Activate Emscripten
173-
./build0.sh
174-
emcmake cmake . -GNinja \
175-
-DCMAKE_BUILD_TYPE=Debug \
176-
-DCMAKE_CXX_FLAGS_DEBUG="-Wall -Wextra -fexceptions" \
177-
-DWITH_LLVM=no \
178-
-DLPYTHON_BUILD_TO_WASM=yes \
179-
-DLFORTRAN_BUILD_ALL=yes \
180-
-DWITH_STACKTRACE=no \
181-
-DWITH_RUNTIME_STACKTRACE=no \
182-
-DCMAKE_PREFIX_PATH="$CONDA_PREFIX" \
183-
-DCMAKE_INSTALL_PREFIX=`pwd`/inst \
184-
-DCMAKE_C_COMPILER_LAUNCHER=sccache \
185-
-DCMAKE_CXX_COMPILER_LAUNCHER=sccache
186-
187-
cmake --build . -j16 --target install
173+
./build_to_wasm.sh
188174
189175
- name: Test built lpython.wasm
190176
shell: bash -l {0}

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,7 @@ output
175175
*.smod
176176
*.js
177177
*.wasm
178+
*.data
178179
/.ccls-cache/
179180
.cache/
180181
ext/

build_to_wasm.sh

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,11 @@
33
set -e
44
set -x
55

6+
mkdir -p src/bin/asset_dir
7+
cp src/runtime/*.py src/bin/asset_dir
8+
cp -r src/runtime/lpython src/bin/asset_dir
9+
10+
./build0.sh
611
emcmake cmake \
712
-DCMAKE_BUILD_TYPE=Debug \
813
-DCMAKE_CXX_FLAGS_DEBUG="-Wall -Wextra -fexceptions" \

integration_tests/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -495,6 +495,7 @@ RUN(NAME expr_20 LABELS cpython llvm c)
495495
RUN(NAME expr_21 LABELS cpython llvm c)
496496
RUN(NAME expr_22 LABELS cpython llvm c)
497497
RUN(NAME expr_23 LABELS cpython llvm c)
498+
RUN(NAME expr_24 LABELS cpython wasm) # mandelbrot
498499

499500
RUN(NAME expr_01u LABELS cpython llvm c NOFAST)
500501
RUN(NAME expr_02u LABELS cpython llvm c NOFAST)

integration_tests/expr_24.py

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
from lpython import i32, f64, TypeVar, Const
2+
from numpy import empty, int32
3+
4+
h = TypeVar("h")
5+
w = TypeVar("w")
6+
7+
def show_img(w: i32, h: i32, A: i32[h, w]):
8+
print(w, h)
9+
print(A[0, 0])
10+
print(A[h - 1, w - 1])
11+
12+
assert w == 600
13+
assert h == 450
14+
assert A[0, 0] == 254
15+
assert A[h - 1, w - 1] == 254
16+
17+
def show_img_color(w: i32, h: i32, A: i32[h, w, 4]):
18+
print(w, h)
19+
print(A[0, 0, 0])
20+
print(A[h - 1, w - 1, 3])
21+
22+
assert w == 600
23+
assert h == 450
24+
assert A[0, 0, 0] == 214
25+
assert A[h - 1, w - 1, 3] == 255
26+
27+
def main0():
28+
Nx: Const[i32] = 600; Ny: Const[i32] = 450; Nz: Const[i32] = 4; n_max: i32 = 255
29+
30+
xcenter: f64 = f64(-0.5); ycenter: f64 = f64(0.0)
31+
width: f64 = f64(4); height: f64 = f64(3)
32+
dx_di: f64 = width/f64(Nx); dy_dj: f64 = -height/f64(Ny)
33+
x_offset: f64 = xcenter - f64(Nx+1)*dx_di/f64(2.0)
34+
y_offset: f64 = ycenter - f64(Ny+1)*dy_dj/f64(2.0)
35+
36+
i: i32; j: i32; n: i32; idx: i32
37+
x: f64; y: f64; x_0: f64; y_0: f64; x_sqr: f64; y_sqr: f64
38+
39+
image: i32[450, 600] = empty([Ny, Nx], dtype=int32)
40+
image_color: i32[450, 600, 4] = empty([Ny, Nx, Nz], dtype=int32)
41+
palette: i32[4, 3] = empty([4, 3], dtype=int32)
42+
43+
for j in range(Ny):
44+
y_0 = y_offset + dy_dj * f64(j + 1)
45+
for i in range(Nx):
46+
x_0 = x_offset + dx_di * f64(i + 1)
47+
x = 0.0; y = 0.0; n = 0
48+
while(True):
49+
x_sqr = x ** 2.0
50+
y_sqr = y ** 2.0
51+
if (x_sqr + y_sqr > f64(4) or n == n_max):
52+
image[j,i] = 255 - n
53+
break
54+
y = y_0 + f64(2.0) * x * y
55+
x = x_0 + x_sqr - y_sqr
56+
n = n + 1
57+
58+
palette[0,0] = 0; palette[0,1] = 135; palette[0,2] = 68
59+
palette[1,0] = 0; palette[1,1] = 87; palette[1,2] = 231
60+
palette[2,0] = 214; palette[2,1] = 45; palette[2,2] = 32
61+
palette[3,0] = 255; palette[3,1] = 167; palette[3,2] = 0
62+
63+
for j in range(Ny):
64+
for i in range(Nx):
65+
idx = image[j,i] - i32(image[j,i]/4)*4
66+
image_color[j,i,0] = palette[idx,0] # Red
67+
image_color[j,i,1] = palette[idx,1] # Green
68+
image_color[j,i,2] = palette[idx,2] # Blue
69+
image_color[j,i,3] = 255 # Alpha
70+
71+
print("The Mandelbrot image in color:")
72+
show_img_color(Nx, Ny, image_color)
73+
print("The Mandelbrot image in grayscale:")
74+
show_img(Nx, Ny, image)
75+
print("Done.")
76+
77+
main0()

src/bin/CMakeLists.txt

Lines changed: 13 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -48,29 +48,24 @@ set_target_properties(lpython PROPERTIES
4848
)
4949

5050
if (HAVE_BUILD_TO_WASM)
51-
# set(WASM_LINK_FLAGS
52-
# "-g0" # Store no debugging information in the generated wasm file. This helps reduce generated file size
53-
# "-Oz" # Optimize for size. With this code size ~ 2.4mb. Without this code size ~49mb
54-
# "-fexceptions" # Enable Cpp exception support
55-
# "--no-entry" # No start function to execute
56-
# "-s ASSERTIONS" # Compile with Assertions which (as per docs) are helpful to debug compilation process
57-
# "-s ALLOW_MEMORY_GROWTH" # Allow dynamic memory growth upto the maximum page size limit
58-
# "-s WASM_BIGINT" # Allow use of i64 integers. ASR is needing this option to be enabled.
59-
# "-s EXPORTED_RUNTIME_METHODS=['cwrap']" # Export cwarp. cwarp helps us to call our EMSCRIPTEN_KEEPALIVE functions
60-
# )
61-
62-
# Some extra flags below that we may need in future. But these may/might increase the code size
63-
# "--preload-file ./asset_dir"
64-
# "-s SAFE_HEAP=1"
65-
# "-s \"EXPORTED_RUNTIME_METHODS=['ccall']\""
66-
# "-s EXPORTED_FUNCTIONS=\"['_free', '_malloc']\""
51+
# "-g0": Store no debugging information in the generated wasm file. This helps reduce generated file size
52+
# "-Oz": Optimize for size. With this code size ~ 2.4mb. Without this code size ~49mb
53+
# "-fexceptions": Enable Cpp exception support
54+
# "--no-entry": No start function to execute
55+
# "-s ASSERTIONS": Compile with Assertions which (as per docs) are helpful to debug compilation process
56+
# "-s ALLOW_MEMORY_GROWTH": Allow dynamic memory growth upto the maximum page size limit
57+
# "-s WASM_BIGINT": Allow use of i64 integers. ASR is needing this option to be enabled.
58+
# "-s EXPORTED_RUNTIME_METHODS=['cwrap']": Export cwarp. cwarp helps us to call our EMSCRIPTEN_KEEPALIVE functions
59+
# "-fsanitize=undefined": Clang's Undefined Behaviour Sanitizer. The LPython parser segfaults.
60+
# This option is for debugging, but currently helps avoid the segfault in the parser.
61+
# "-s INITIAL_MEMORY=536870912": Start the wasm linear memory with sufficiently large size 512Mb.
6762

6863
# Notes:
6964
# STANDALONE_WASM is disabling support for exceptions, so it is currently omitted
7065
# In build_to_wasm.sh, we need CMAKE_CXX_FLAGS_DEBUG="-Wall -Wextra -fexceptions" flags for exception support
71-
set(WASM_COMPILE_FLAGS "-g0 -fexceptions")
66+
set(WASM_COMPILE_FLAGS "-g0 -fexceptions -fsanitize=undefined")
7267
set(WASM_LINK_FLAGS
73-
"-g0 -Oz -fexceptions -Wall -Wextra --no-entry -s ASSERTIONS -s ALLOW_MEMORY_GROWTH=1 -s WASM_BIGINT -s \"EXPORTED_RUNTIME_METHODS=['cwrap']\""
68+
"-g0 -Oz -fexceptions -fsanitize=undefined --preload-file asset_dir -Wall -Wextra --no-entry -sASSERTIONS=1 -s INITIAL_MEMORY=536870912 -s ALLOW_MEMORY_GROWTH=1 -s WASM_BIGINT -s \"EXPORTED_RUNTIME_METHODS=['cwrap']\""
7469
)
7570
set_target_properties(lpython PROPERTIES COMPILE_FLAGS ${WASM_COMPILE_FLAGS})
7671
set_target_properties(lpython PROPERTIES LINK_FLAGS ${WASM_LINK_FLAGS})

src/libasr/ASR.asdl

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,10 @@ presence = Required | Optional
147147
-- LPython manages the conversion of arguments to be passed to such symbols
148148
-- and also converts the return values from such symbols.
149149

150+
-- abi=BindJS: the symbol's implementation is
151+
-- available with Javascript.
152+
-- This abi type is to be mainly used with the WASM Backend.
153+
150154
-- abi=Interactive: the symbol's implementation has been provided by the
151155
-- previous REPL execution (e.g., if LLVM backend is used for the interactive
152156
-- mode, the previous execution generated machine code for this symbol's
@@ -164,6 +168,7 @@ abi -- External ABI
164168
| GFortranModule -- Yes GFortran
165169
| BindC -- Yes C
166170
| BindPython -- Yes Python
171+
| BindJS -- Yes Javascript
167172
| Interactive -- Yes Unspecified
168173
| Intrinsic -- Yes Unspecified
169174

src/libasr/codegen/asr_to_wasm.cpp

Lines changed: 18 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -142,8 +142,8 @@ class ASRToWASMVisitor : public ASR::BaseVisitor<ASRToWASMVisitor> {
142142
main_func = nullptr;
143143
avail_mem_loc = 0;
144144

145-
min_no_pages = 100; // fixed 6.4 Mb memory currently
146-
max_no_pages = 100; // fixed 6.4 Mb memory currently
145+
min_no_pages = 1000; // fixed 64 Mb memory currently
146+
max_no_pages = 1000; // fixed 64 Mb memory currently
147147

148148
m_compiler_globals.resize(GLOBAL_VARS_CNT);
149149
m_import_func_idx_map.resize(IMPORT_FUNCS_CNT);
@@ -160,10 +160,7 @@ class ASRToWASMVisitor : public ASR::BaseVisitor<ASRToWASMVisitor> {
160160
}
161161

162162
void import_function(ASR::Function_t* fn) {
163-
if (ASRUtils::get_FunctionType(fn)->m_abi != ASR::abiType::BindC) return;
164-
if (ASRUtils::get_FunctionType(fn)->m_deftype != ASR::deftypeType::Interface) return;
165-
if (ASRUtils::get_FunctionType(fn)->m_abi != ASR::abiType::BindC) return;
166-
if (ASRUtils::is_intrinsic_function2(fn)) return;
163+
if (ASRUtils::get_FunctionType(fn)->m_abi != ASR::abiType::BindJS) return;
167164

168165
emit_function_prototype(*fn);
169166
m_wa.emit_import_fn("js", fn->m_name,
@@ -189,6 +186,14 @@ class ASRToWASMVisitor : public ASR::BaseVisitor<ASRToWASMVisitor> {
189186
import_function(fn);
190187
}
191188
}
189+
} else if (ASR::is_a<ASR::Module_t>(*item.second)) {
190+
ASR::Module_t *m = ASR::down_cast<ASR::Module_t>(item.second);
191+
for (auto &item : m->m_symtab->get_scope()) {
192+
if (ASR::is_a<ASR::Function_t>(*item.second)) {
193+
ASR::Function_t *fn = ASR::down_cast<ASR::Function_t>(item.second);
194+
import_function(fn);
195+
}
196+
}
192197
} else if (ASR::is_a<ASR::Function_t>(*item.second)) {
193198
ASR::Function_t *fn = ASR::down_cast<ASR::Function_t>(item.second);
194199
import_function(fn);
@@ -1152,13 +1157,12 @@ class ASRToWASMVisitor : public ASR::BaseVisitor<ASRToWASMVisitor> {
11521157
bool is_unsupported_function(const ASR::Function_t &x) {
11531158
if (strcmp(x.m_name, "_start") == 0) return false;
11541159

1155-
if (ASRUtils::get_FunctionType(x)->m_abi == ASR::abiType::BindC &&
1156-
ASRUtils::get_FunctionType(x)->m_deftype == ASR::deftypeType::Interface) {
1157-
if (ASRUtils::is_intrinsic_function2(&x)) {
1158-
diag.codegen_warning_label(
1159-
"WASM: C Intrinsic Functions not yet supported",
1160-
{x.base.base.loc}, std::string(x.m_name));
1161-
}
1160+
if (ASRUtils::get_FunctionType(x)->m_abi == ASR::abiType::BindJS) {
1161+
return true;
1162+
}
1163+
1164+
if (ASRUtils::get_FunctionType(x)->m_abi == ASR::abiType::BindC) {
1165+
// Skip C Intrinsic Functions
11621166
return true;
11631167
}
11641168
for (size_t i = 0; i < x.n_body; i++) {
@@ -1167,13 +1171,8 @@ class ASRToWASMVisitor : public ASR::BaseVisitor<ASRToWASMVisitor> {
11671171
ASR::Function_t *s = ASR::down_cast<ASR::Function_t>(
11681172
ASRUtils::symbol_get_past_external(sub_call.m_name));
11691173
if (ASRUtils::get_FunctionType(s)->m_abi == ASR::abiType::BindC &&
1170-
ASRUtils::get_FunctionType(s)->m_deftype == ASR::deftypeType::Interface &&
11711174
ASRUtils::is_intrinsic_function2(s)) {
1172-
diag.codegen_warning_label(
1173-
"WASM: Calls to C Intrinsic Functions are not yet "
1174-
"supported",
1175-
{x.m_body[i]->base.loc},
1176-
"Function: calls " + std::string(s->m_name));
1175+
// Skip functions that call into C Intrinsic Functions
11771176
return true;
11781177
}
11791178
}

src/lpython/semantics/python_ast_to_asr.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4230,6 +4230,8 @@ class SymbolTableVisitor : public CommonVisitor<SymbolTableVisitor> {
42304230
} else if (name == "pythoncall" || name == "pythoncallable") {
42314231
current_procedure_abi_type = ASR::abiType::BindPython;
42324232
current_procedure_interface = (name == "pythoncall");
4233+
} else if (name == "jscall") {
4234+
current_procedure_abi_type = ASR::abiType::BindJS;
42334235
} else if (name == "overload") {
42344236
overload = true;
42354237
} else if (name == "interface") {

src/lpython/utils.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,9 @@ void get_executable_path(std::string &executable_path, int &dirname_length)
5252

5353
std::string get_runtime_library_dir()
5454
{
55+
#ifdef HAVE_BUILD_TO_WASM
56+
return "asset_dir";
57+
#endif
5558
char *env_p = std::getenv("LFORTRAN_RUNTIME_LIBRARY_DIR");
5659
if (env_p) return env_p;
5760

tests/reference/asr-elemental_01-b58df26.stderr

Lines changed: 0 additions & 5 deletions
This file was deleted.

tests/reference/asr-modules_02-ec92e6f.stderr

Lines changed: 0 additions & 8 deletions
This file was deleted.

tests/reference/asr_json-modules_02-53952e6.stderr

Lines changed: 0 additions & 8 deletions
This file was deleted.

tests/reference/wat-bool1-234bcd1.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
"outfile": null,
77
"outfile_hash": null,
88
"stdout": "wat-bool1-234bcd1.stdout",
9-
"stdout_hash": "2ad7e7fd37dbdc380ed1fb9e4879efed1cf87dc9472196189215487b",
9+
"stdout_hash": "1ac138f5c0fd3b21a75e6bf4e0024d5f0df2f0a6b195defd472677c2",
1010
"stderr": null,
1111
"stderr_hash": null,
1212
"returncode": 0

tests/reference/wat-bool1-234bcd1.stdout

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,7 @@
175175
end
176176
return
177177
)
178-
(memory (;0;) 100 100)
178+
(memory (;0;) 1000 1000)
179179
(export "memory" (memory 0))
180180
(export "__main__global_stmts" (func 2))
181181
(export "test_bool" (func 3))

tests/reference/wat-expr14-5e0cb96.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
"outfile": null,
77
"outfile_hash": null,
88
"stdout": "wat-expr14-5e0cb96.stdout",
9-
"stdout_hash": "731682ff49eaab392c46e72e575f595873b89b30309c62c75cc6e36b",
9+
"stdout_hash": "f8ff7eb9eb4bc533fc4d36c58a0378df6dfbf135313962dbf379d69a",
1010
"stderr": null,
1111
"stderr_hash": null,
1212
"returncode": 0

tests/reference/wat-expr14-5e0cb96.stdout

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
call 0
1818
return
1919
)
20-
(memory (;0;) 100 100)
20+
(memory (;0;) 1000 1000)
2121
(export "memory" (memory 0))
2222
(export "_start" (func 2))
2323
(data (;0;) (i32.const 4) "\0c\00\00\00\01\00\00\00")

tests/reference/wat-expr2-8b17723.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
"outfile": null,
77
"outfile_hash": null,
88
"stdout": "wat-expr2-8b17723.stdout",
9-
"stdout_hash": "731682ff49eaab392c46e72e575f595873b89b30309c62c75cc6e36b",
9+
"stdout_hash": "f8ff7eb9eb4bc533fc4d36c58a0378df6dfbf135313962dbf379d69a",
1010
"stderr": null,
1111
"stderr_hash": null,
1212
"returncode": 0

tests/reference/wat-expr2-8b17723.stdout

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
call 0
1818
return
1919
)
20-
(memory (;0;) 100 100)
20+
(memory (;0;) 1000 1000)
2121
(export "memory" (memory 0))
2222
(export "_start" (func 2))
2323
(data (;0;) (i32.const 4) "\0c\00\00\00\01\00\00\00")

tests/reference/wat-expr9-f73afd1.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
"outfile": null,
77
"outfile_hash": null,
88
"stdout": "wat-expr9-f73afd1.stdout",
9-
"stdout_hash": "24c9e7908c6c26b7b02f35db04295334fd8a45c90aa411146cf1cb16",
9+
"stdout_hash": "169634bcbf991ebd3a4315e3824320762aea19971ac0a85026095e6c",
1010
"stderr": null,
1111
"stderr_hash": null,
1212
"returncode": 0

tests/reference/wat-expr9-f73afd1.stdout

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@
6666
call 0
6767
return
6868
)
69-
(memory (;0;) 100 100)
69+
(memory (;0;) 1000 1000)
7070
(export "memory" (memory 0))
7171
(export "__main__global_stmts" (func 2))
7272
(export "main0" (func 3))

tests/reference/wat-loop1-e0046d4.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
"outfile": null,
77
"outfile_hash": null,
88
"stdout": "wat-loop1-e0046d4.stdout",
9-
"stdout_hash": "b8c4cf026606e374e199425dede3419e41b30f935b6a1c71add8f508",
9+
"stdout_hash": "186355413b04732159a4ea9cf108245721b5a41d5a6630a4f8cc7785",
1010
"stderr": null,
1111
"stderr_hash": null,
1212
"returncode": 0

tests/reference/wat-loop1-e0046d4.stdout

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,7 @@
152152
call 0
153153
return
154154
)
155-
(memory (;0;) 100 100)
155+
(memory (;0;) 1000 1000)
156156
(export "memory" (memory 0))
157157
(export "__main__global_stmts" (func 2))
158158
(export "main0" (func 3))

0 commit comments

Comments
 (0)