Add WASI platform support.
authorwhitequark <whitequark@whitequark.org>
Mon, 11 Nov 2019 09:23:06 +0000 (09:23 +0000)
committerwhitequark <whitequark@whitequark.org>
Thu, 30 Apr 2020 18:56:25 +0000 (18:56 +0000)
This includes the following significant changes:
  * Patching ezsat and minisat to disable resource limiting code
    on WASM/WASI, since the POSIX functions they use are unavailable.
  * Adding a new definition, YOSYS_DISABLE_SPAWN, present if platform
    does not support spawning subprocesses (i.e. Emscripten or WASI).
    This definition hides the definition of `run_command()`.
  * Adding a new Makefile flag, DISABLE_SPAWN, present in the same
    condition. This flag disables all passes that require spawning
    subprocesses for their function.

17 files changed:
Makefile
frontends/rpc/Makefile.inc
kernel/driver.cc
kernel/register.cc
kernel/yosys.cc
kernel/yosys.h
libs/ezsat/ezminisat.cc
libs/minisat/00_PATCH_wasm.patch [new file with mode: 0644]
libs/minisat/00_UPDATE.sh
libs/minisat/System.cc
passes/cmds/Makefile.inc
passes/cmds/cover.cc
passes/cmds/show.cc
passes/sat/Makefile.inc
passes/techmap/Makefile.inc
passes/techmap/abc.cc
passes/techmap/abc9_exe.cc

index da8701355406bf5ca7e4b572648e2e272e0a783c..c719094b45bc1461b9c2b8ad48a2dc461bc6bc6f 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -4,6 +4,7 @@ CONFIG := clang
 # CONFIG := gcc-4.8
 # CONFIG := afl-gcc
 # CONFIG := emcc
+# CONFIG := wasi
 # CONFIG := mxe
 # CONFIG := msys2
 # CONFIG := msys2-64
@@ -32,7 +33,9 @@ ENABLE_NDEBUG := 0
 LINK_CURSES := 0
 LINK_TERMCAP := 0
 LINK_ABC := 0
-# Needed for environments that don't have proper thread support (i.e. emscripten)
+# Needed for environments that can't run executables (i.e. emscripten, wasm)
+DISABLE_SPAWN := 0
+# Needed for environments that don't have proper thread support (i.e. emscripten, wasm--for now)
 DISABLE_ABC_THREADS := 0
 
 # clang sanitizers
@@ -42,7 +45,7 @@ SANITIZER =
 # SANITIZER = undefined
 # SANITIZER = cfi
 
-PROGRAM_PREFIX := 
+PROGRAM_PREFIX :=
 
 OS := $(shell uname -s)
 PREFIX ?= /usr/local
@@ -253,6 +256,8 @@ LDFLAGS += $(EMCCFLAGS)
 LDLIBS =
 EXE = .js
 
+DISABLE_SPAWN := 1
+
 TARGETS := $(filter-out $(PROGRAM_PREFIX)yosys-config,$(TARGETS))
 EXTRA_TARGETS += yosysjs-$(YOSYS_VER).zip
 
@@ -274,6 +279,35 @@ yosysjs-$(YOSYS_VER).zip: yosys.js yosys.wasm viz.js misc/yosysjs/*
 yosys.html: misc/yosys.html
        $(P) cp misc/yosys.html yosys.html
 
+else ifeq ($(CONFIG),wasi)
+ifeq ($(WASI_SDK),)
+CXX = clang++
+LD = clang++
+AR = llvm-ar
+RANLIB = llvm-ranlib
+WASIFLAGS := -target wasm32-wasi --sysroot $(WASI_SYSROOT) $(WASIFLAGS)
+else
+CXX = $(WASI_SDK)/bin/clang++
+LD = $(WASI_SDK)/bin/clang++
+AR = $(WASI_SDK)/bin/ar
+RANLIB = $(WASI_SDK)/bin/ranlib
+WASIFLAGS := --sysroot $(WASI_SDK)/share/wasi-sysroot $(WASIFLAGS)
+endif
+CXXFLAGS := $(WASIFLAGS) -std=c++11 -Os $(filter-out -fPIC,$(CXXFLAGS))
+LDFLAGS := $(WASIFLAGS) -Wl,-z,stack-size=1048576 $(filter-out -rdynamic,$(LDFLAGS))
+LDLIBS := $(filter-out -lrt,$(LDLIBS))
+ABCMKARGS += AR="$(AR)" RANLIB="$(RANLIB)"
+ABCMKARGS += ARCHFLAGS="$(WASIFLAGS) -DABC_USE_STDINT_H -DABC_NO_DYNAMIC_LINKING"
+ABCMKARGS += OPTFLAGS="-Os"
+EXE = .wasm
+
+DISABLE_SPAWN := 1
+
+ifeq ($(ENABLE_ABC),1)
+LINK_ABC := 1
+DISABLE_ABC_THREADS := 1
+endif
+
 else ifeq ($(CONFIG),mxe)
 PKG_CONFIG = /usr/local/src/mxe/usr/bin/i686-w64-mingw32.static-pkg-config
 CXX = /usr/local/src/mxe/usr/bin/i686-w64-mingw32.static-g++
@@ -396,6 +430,10 @@ ifeq ($(DISABLE_ABC_THREADS),1)
 ABCMKARGS += "ABC_USE_NO_PTHREADS=1"
 endif
 
+ifeq ($(DISABLE_SPAWN),1)
+CXXFLAGS += -DYOSYS_DISABLE_SPAWN
+endif
+
 ifeq ($(ENABLE_PLUGINS),1)
 CXXFLAGS += $(shell PKG_CONFIG_PATH=$(PKG_CONFIG_PATH) $(PKG_CONFIG) --silence-errors --cflags libffi) -DYOSYS_ENABLE_PLUGINS
 LDLIBS += $(shell PKG_CONFIG_PATH=$(PKG_CONFIG_PATH) $(PKG_CONFIG) --silence-errors --libs libffi || echo -lffi)
@@ -911,6 +949,14 @@ config-emcc: clean
        echo 'ENABLE_READLINE := 0' >> Makefile.conf
        echo 'ENABLE_ZLIB := 0' >> Makefile.conf
 
+config-wasi: clean
+       echo 'CONFIG := wasi' > Makefile.conf
+       echo 'ENABLE_TCL := 0' >> Makefile.conf
+       echo 'ENABLE_ABC := 0' >> Makefile.conf
+       echo 'ENABLE_PLUGINS := 0' >> Makefile.conf
+       echo 'ENABLE_READLINE := 0' >> Makefile.conf
+       echo 'ENABLE_ZLIB := 0' >> Makefile.conf
+
 config-mxe: clean
        echo 'CONFIG := mxe' > Makefile.conf
        echo 'ENABLE_PLUGINS := 0' >> Makefile.conf
index 7b270b6feb21e177e01081f7cfabcce65779ef74..fa1d068f941b1058c34249d409abfd82837f41cb 100644 (file)
@@ -1,3 +1,3 @@
-ifneq ($(CONFIG),emcc)
+ifeq ($(DISABLE_SPAWN),0)
 OBJS += frontends/rpc/rpc_frontend.o
 endif
index 5f0959776786ff4acec88596cc1ec0c73e807f44..57ed7b8b45292c2b75e195baf234c127dd65878c 100644 (file)
@@ -155,6 +155,19 @@ int yosys_history_offset = 0;
 std::string yosys_history_file;
 #endif
 
+#if defined(__wasm)
+extern "C" {
+       // FIXME: WASI does not currently support exceptions.
+       void* __cxa_allocate_exception(size_t thrown_size) throw() {
+               return malloc(thrown_size);
+       }
+       bool __cxa_uncaught_exception() throw();
+       void __cxa_throw(void* thrown_exception, struct std::type_info * tinfo, void (*dest)(void*)) {
+               std::terminate();
+       }
+}
+#endif
+
 void yosys_atexit()
 {
 #if defined(YOSYS_ENABLE_READLINE) || defined(YOSYS_ENABLE_EDITLINE)
@@ -587,9 +600,11 @@ int main(int argc, char **argv)
                        ru_buffer.ru_utime.tv_usec += ru_buffer_children.ru_utime.tv_usec;
                        ru_buffer.ru_stime.tv_sec += ru_buffer_children.ru_stime.tv_sec;
                        ru_buffer.ru_stime.tv_usec += ru_buffer_children.ru_stime.tv_usec;
+#if defined(__linux__) || defined(__FreeBSD__)
                        ru_buffer.ru_maxrss = std::max(ru_buffer.ru_maxrss, ru_buffer_children.ru_maxrss);
+#endif
                }
-#  if defined(__linux__) || defined(__FreeBSD__)
+#if defined(__linux__) || defined(__FreeBSD__)
                meminfo = stringf(", MEM: %.2f MB peak",
                                ru_buffer.ru_maxrss / 1024.0);
 #endif
index 925d0d77615262ab7b32ac7c77920747b52a470d..02974e5349f92c0090b141cbbc6dc4d39294c830 100644 (file)
@@ -238,6 +238,7 @@ void Pass::call(RTLIL::Design *design, std::string command)
                return;
 
        if (tok[0] == '!') {
+#if !defined(YOSYS_DISABLE_SPAWN)
                cmd_buf = command.substr(command.find('!') + 1);
                while (!cmd_buf.empty() && (cmd_buf.back() == ' ' || cmd_buf.back() == '\t' ||
                                cmd_buf.back() == '\r' || cmd_buf.back() == '\n'))
@@ -247,6 +248,9 @@ void Pass::call(RTLIL::Design *design, std::string command)
                if (retCode != 0)
                        log_cmd_error("Shell command returned error code %d.\n", retCode);
                return;
+#else
+               log_cmd_error("Shell is not available.\n");
+#endif
        }
 
        while (!tok.empty()) {
index 01131601f8b3d8feb7acaa2de4093a732473437d..2ec3dca0cffeda704d13141a25c81250b0b07e94 100644 (file)
 #  include <unistd.h>
 #  include <dirent.h>
 #  include <sys/types.h>
-#  include <sys/wait.h>
 #  include <sys/stat.h>
+#  if !defined(YOSYS_DISABLE_SPAWN)
+#    include <sys/wait.h>
+#  endif
 #endif
 
 #if !defined(_WIN32) && defined(YOSYS_ENABLE_GLOB)
@@ -336,16 +338,13 @@ bool patmatch(const char *pattern, const char *string)
        return false;
 }
 
+#if !defined(YOSYS_DISABLE_SPAWN)
 int run_command(const std::string &command, std::function<void(const std::string&)> process_line)
 {
        if (!process_line)
                return system(command.c_str());
 
-#ifdef EMSCRIPTEN
-       FILE *f = nullptr;
-#else
        FILE *f = popen(command.c_str(), "r");
-#endif
        if (f == nullptr)
                return -1;
 
@@ -368,10 +367,16 @@ int run_command(const std::string &command, std::function<void(const std::string
        return WEXITSTATUS(ret);
 #endif
 }
+#endif
 
 std::string make_temp_file(std::string template_str)
 {
-#ifdef _WIN32
+#if defined(__wasm)
+       size_t pos = template_str.rfind("XXXXXX");
+       log_assert(pos != std::string::npos);
+       static size_t index = 0;
+       template_str.replace(pos, 6, stringf("%06zu", index++));
+#elif defined(_WIN32)
        if (template_str.rfind("/tmp/", 0) == 0) {
 #  ifdef __MINGW32__
                char longpath[MAX_PATH + 1];
@@ -420,10 +425,14 @@ std::string make_temp_file(std::string template_str)
 
 std::string make_temp_dir(std::string template_str)
 {
-#ifdef _WIN32
+#if defined(_WIN32)
        template_str = make_temp_file(template_str);
        mkdir(template_str.c_str());
        return template_str;
+#elif defined(__wasm)
+       template_str = make_temp_file(template_str);
+       mkdir(template_str.c_str(), 0777);
+       return template_str;
 #else
 #  ifndef NDEBUG
        size_t pos = template_str.rfind("XXXXXX");
@@ -806,7 +815,7 @@ std::string proc_self_dirname()
                path += char(shortpath[i]);
        return path;
 }
-#elif defined(EMSCRIPTEN)
+#elif defined(EMSCRIPTEN) || defined(__wasm)
 std::string proc_self_dirname()
 {
        return "/";
@@ -815,7 +824,7 @@ std::string proc_self_dirname()
        #error "Don't know how to determine process executable base path!"
 #endif
 
-#ifdef EMSCRIPTEN
+#if defined(EMSCRIPTEN) || defined(__wasm)
 std::string proc_share_dirname()
 {
        return "/share/";
index ed48eec09fbb3a2fa833525ab0a67c7331ef5a37..af1e376b12ceae3d334f3268010bc0fd5c6310cf 100644 (file)
@@ -264,7 +264,9 @@ int readsome(std::istream &f, char *s, int n);
 std::string next_token(std::string &text, const char *sep = " \t\r\n", bool long_strings = false);
 std::vector<std::string> split_tokens(const std::string &text, const char *sep = " \t\r\n");
 bool patmatch(const char *pattern, const char *string);
+#if !defined(YOSYS_DISABLE_SPAWN)
 int run_command(const std::string &command, std::function<void(const std::string&)> process_line = std::function<void(const std::string&)>());
+#endif
 std::string make_temp_file(std::string template_str = "/tmp/yosys_XXXXXX");
 std::string make_temp_dir(std::string template_str = "/tmp/yosys_XXXXXX");
 bool check_file_exists(std::string filename, bool is_exec = false);
index 4be5fd4931a6044d36d1a22bcff803ce55e6389c..ac4defac386558d12727779b72e143ca99e50283 100644 (file)
 
 #include <limits.h>
 #include <stdint.h>
-#include <csignal>
 #include <cinttypes>
 
-#ifndef _WIN32
+#if !defined(_WIN32) && !defined(__wasm)
+#  include <csignal>
 #  include <unistd.h>
+#  define HAS_ALARM
 #endif
 
 #include "../minisat/Solver.h"
@@ -84,7 +85,7 @@ bool ezMiniSAT::eliminated(int idx)
 }
 #endif
 
-#ifndef _WIN32
+#if defined(HAS_ALARM)
 ezMiniSAT *ezMiniSAT::alarmHandlerThis = NULL;
 clock_t ezMiniSAT::alarmHandlerTimeout = 0;
 
@@ -183,7 +184,7 @@ contradiction:
 #endif
        }
 
-#ifndef _WIN32
+#if defined(HAS_ALARM)
        struct sigaction sig_action;
        struct sigaction old_sig_action;
        int old_alarm_timeout = 0;
@@ -202,7 +203,7 @@ contradiction:
 
        bool foundSolution = minisatSolver->solve(assumps);
 
-#ifndef _WIN32
+#if defined(HAS_ALARM)
        if (solverTimeout > 0) {
                if (alarmHandlerTimeout == 0)
                        solverTimoutStatus = true;
diff --git a/libs/minisat/00_PATCH_wasm.patch b/libs/minisat/00_PATCH_wasm.patch
new file mode 100644 (file)
index 0000000..0bcff7d
--- /dev/null
@@ -0,0 +1,34 @@
+--- System.cc
++++ System.cc
+@@ -101,7 +101,7 @@ double Minisat::memUsedPeak(bool) { return 0; }
+ #endif
+
+
+-#if !defined(_MSC_VER) && !defined(__MINGW32__)
++#if !defined(_MSC_VER) && !defined(__MINGW32__) && !defined(__wasm)
+ void Minisat::limitMemory(uint64_t max_mem_mb)
+ {
+ // FIXME: OpenBSD does not support RLIMIT_AS. Not sure how well RLIMIT_DATA works instead.
+@@ -133,7 +133,7 @@ void Minisat::limitMemory(uint64_t /*max_mem_mb*/)
+ #endif
+
+
+-#if !defined(_MSC_VER) && !defined(__MINGW32__)
++#if !defined(_MSC_VER) && !defined(__MINGW32__) && !defined(__wasm)
+ void Minisat::limitTime(uint32_t max_cpu_time)
+ {
+     if (max_cpu_time != 0){
+@@ -156,9 +156,13 @@ void Minisat::limitTime(uint32_t /*max_cpu_time*/)
+
+ void Minisat::sigTerm(void handler(int))
+ {
++#if defined(__wasm)
++    (void)handler;
++#else
+     signal(SIGINT, handler);
+     signal(SIGTERM,handler);
+ #ifdef SIGXCPU
+     signal(SIGXCPU,handler);
+ #endif
++#endif
+ }
index ea26215ab2a9f8ac67a657fdcc647c7adc240887..51107e4506a7edeae2f93ef15129337ce5ed7653 100755 (executable)
@@ -16,4 +16,4 @@ patch -p0 < 00_PATCH_mkLit_default_arg.patch
 patch -p0 < 00_PATCH_remove_zlib.patch
 patch -p0 < 00_PATCH_no_fpu_control.patch
 patch -p0 < 00_PATCH_typofixes.patch
-
+patch -p0 < 00_PATCH_wasm.patch
index 1921a1d7157d5a3fe3795762d3c3546b88c5ec4a..345be8c4c75a54515552f1fd88a30b0f74840e49 100644 (file)
@@ -101,7 +101,7 @@ double Minisat::memUsedPeak(bool) { return 0; }
 #endif
 
 
-#if !defined(_MSC_VER) && !defined(__MINGW32__)
+#if !defined(_MSC_VER) && !defined(__MINGW32__) && !defined(__wasm)
 void Minisat::limitMemory(uint64_t max_mem_mb)
 {
 // FIXME: OpenBSD does not support RLIMIT_AS. Not sure how well RLIMIT_DATA works instead.
@@ -133,7 +133,7 @@ void Minisat::limitMemory(uint64_t /*max_mem_mb*/)
 #endif
 
 
-#if !defined(_MSC_VER) && !defined(__MINGW32__)
+#if !defined(_MSC_VER) && !defined(__MINGW32__) && !defined(__wasm)
 void Minisat::limitTime(uint32_t max_cpu_time)
 {
     if (max_cpu_time != 0){
@@ -156,9 +156,13 @@ void Minisat::limitTime(uint32_t /*max_cpu_time*/)
 
 void Minisat::sigTerm(void handler(int))
 {
+#if defined(__wasm)
+    (void)handler;
+#else
     signal(SIGINT, handler);
     signal(SIGTERM,handler);
 #ifdef SIGXCPU
     signal(SIGXCPU,handler);
 #endif
+#endif
 }
index 60f20fa6dd2daec4cad003a06e766875e6784d19..a88980eafe0167a89494c30c73195c91b972c595 100644 (file)
@@ -1,5 +1,7 @@
 
+ifeq ($(DISABLE_SPAWN),0)
 OBJS += passes/cmds/exec.o
+endif
 OBJS += passes/cmds/add.o
 OBJS += passes/cmds/delete.o
 OBJS += passes/cmds/design.o
@@ -32,6 +34,8 @@ OBJS += passes/cmds/chformal.o
 OBJS += passes/cmds/chtype.o
 OBJS += passes/cmds/blackbox.o
 OBJS += passes/cmds/ltp.o
+ifeq ($(DISABLE_SPAWN),0)
 OBJS += passes/cmds/bugpoint.o
+endif
 OBJS += passes/cmds/scratchpad.o
 OBJS += passes/cmds/logger.o
index 628ac4c5e56ec3fa5d0aeaef7873f149f4c57cb4..89d27c9aab735b88ae5feef0d44131cf9e53315a 100644 (file)
@@ -101,8 +101,8 @@ struct CoverPass : public Pass {
                                const std::string &filename = args[++argidx];
                                FILE *f = nullptr;
                                if (args[argidx-1] == "-d") {
-                       #ifdef _WIN32
-                                       log_cmd_error("The 'cover -d' option is not supported on win32.\n");
+                       #if defined(_WIN32) || defined(__wasm)
+                                       log_cmd_error("The 'cover -d' option is not supported on this platform.\n");
                        #else
                                        char filename_buffer[4096];
                                        snprintf(filename_buffer, 4096, "%s/yosys_cover_%d_XXXXXX.txt", filename.c_str(), getpid());
index 155ed0fcd02732d09765b24ffdec4e475a745452..fa922454aac46bdf726cfb269349ef5103e7c875 100644 (file)
@@ -682,7 +682,7 @@ struct ShowPass : public Pass {
                std::vector<std::pair<std::string, RTLIL::Selection>> color_selections;
                std::vector<std::pair<std::string, RTLIL::Selection>> label_selections;
 
-#if defined(EMSCRIPTEN) || defined(_WIN32)
+#if defined(_WIN32) || defined(YOSYS_DISABLE_SPAWN)
                std::string format = "dot";
                std::string prefix = "show";
 #else
@@ -849,10 +849,15 @@ struct ShowPass : public Pass {
                        std::string cmd = stringf(DOT_CMD, format.c_str(), dot_file.c_str(), out_file.c_str(), out_file.c_str(), out_file.c_str());
                        #undef DOT_CMD
                        log("Exec: %s\n", cmd.c_str());
-                       if (run_command(cmd) != 0)
-                               log_cmd_error("Shell command failed!\n");
+                       #if !defined(YOSYS_DISABLE_SPAWN)
+                               if (run_command(cmd) != 0)
+                                       log_cmd_error("Shell command failed!\n");
+                       #endif
                }
 
+               #if defined(YOSYS_DISABLE_SPAWN)
+                       log_assert(viewer_exe.empty() && !format.empty());
+               #else
                if (!viewer_exe.empty()) {
                        #ifdef _WIN32
                                // system()/cmd.exe does not understand single quotes nor
@@ -876,6 +881,7 @@ struct ShowPass : public Pass {
                        if (run_command(cmd) != 0)
                                log_cmd_error("Shell command failed!\n");
                }
+               #endif
 
                if (flag_pause) {
                #ifdef YOSYS_ENABLE_READLINE
index a928c57de4dfc45a6e9ff5a9e618754d15254f8f..7118c1563427a102b484206b6956133aedbbe3e3 100644 (file)
@@ -13,5 +13,6 @@ OBJS += passes/sat/fmcombine.o
 OBJS += passes/sat/mutate.o
 OBJS += passes/sat/cutpoint.o
 OBJS += passes/sat/fminit.o
+ifeq ($(DISABLE_SPAWN),0)
 OBJS += passes/sat/qbfsat.o
-
+endif
index 766b954df0782ff868f2e98deeb9e6b07b69f814..1802ba0de446c6d27c3f4bde7c64caa756c2d366 100644 (file)
@@ -57,7 +57,7 @@ passes/techmap/techmap.inc: techlibs/common/techmap.v
 
 passes/techmap/techmap.o: passes/techmap/techmap.inc
 
-ifneq ($(CONFIG),emcc)
+ifeq ($(DISABLE_SPAWN),0)
 TARGETS += $(PROGRAM_PREFIX)yosys-filterlib$(EXE)
 EXTRA_OBJS += passes/techmap/filterlib.o
 
index aff0baa448073a46db7d78bd75dc95e3518b8e62..fae8b24263fd8ac96b5d14433fca241bb8a69933 100644 (file)
@@ -771,7 +771,10 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin
                if (abc_script[i] == ';' && abc_script[i+1] == ' ')
                        abc_script[i+1] = '\n';
 
-       FILE *f = fopen(stringf("%s/abc.script", tempdir_name.c_str()).c_str(), "wt");
+       std::string buffer = stringf("%s/abc.script", tempdir_name.c_str());
+       FILE *f = fopen(buffer.c_str(), "wt");
+       if (f == nullptr)
+               log_error("Opening %s for writing failed: %s\n", buffer.c_str(), strerror(errno));
        fprintf(f, "%s\n", abc_script.c_str());
        fclose(f);
 
@@ -807,7 +810,7 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin
 
        handle_loops();
 
-       std::string buffer = stringf("%s/input.blif", tempdir_name.c_str());
+       buffer = stringf("%s/input.blif", tempdir_name.c_str());
        f = fopen(buffer.c_str(), "wt");
        if (f == nullptr)
                log_error("Opening %s for writing failed: %s\n", buffer.c_str(), strerror(errno));
@@ -1541,11 +1544,15 @@ struct AbcPass : public Pass {
 
                size_t argidx, g_argidx;
                bool g_arg_from_cmd = false;
+#if defined(__wasm)
+               const char *pwd = ".";
+#else
                char pwd [PATH_MAX];
                if (!getcwd(pwd, sizeof(pwd))) {
                        log_cmd_error("getcwd failed: %s\n", strerror(errno));
                        log_abort();
                }
+#endif
                for (argidx = 1; argidx < args.size(); argidx++) {
                        std::string arg = args[argidx];
                        if (arg == "-exe" && argidx+1 < args.size()) {
index bad91a2243ecddfb9f533d69c95a780e4ad06b66..0bf547921f53d34e83156c45587b59e82cae8f23 100644 (file)
@@ -420,11 +420,15 @@ struct Abc9ExePass : public Pass {
                }
 
                size_t argidx;
+#if defined(__wasm)
+               const char *pwd = ".";
+#else
                char pwd [PATH_MAX];
                if (!getcwd(pwd, sizeof(pwd))) {
                        log_cmd_error("getcwd failed: %s\n", strerror(errno));
                        log_abort();
                }
+#endif
                for (argidx = 1; argidx < args.size(); argidx++) {
                        std::string arg = args[argidx];
                        if (arg == "-exe" && argidx+1 < args.size()) {