diff options
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/driver.cc | 17 | ||||
-rw-r--r-- | kernel/log.cc | 7 | ||||
-rw-r--r-- | kernel/log.h | 40 | ||||
-rw-r--r-- | kernel/register.cc | 4 | ||||
-rw-r--r-- | kernel/yosys.cc | 27 | ||||
-rw-r--r-- | kernel/yosys.h | 2 |
6 files changed, 84 insertions, 13 deletions
diff --git a/kernel/driver.cc b/kernel/driver.cc index 5f0959776..57ed7b8b4 100644 --- a/kernel/driver.cc +++ b/kernel/driver.cc @@ -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 diff --git a/kernel/log.cc b/kernel/log.cc index d84a4381e..a21ba480a 100644 --- a/kernel/log.cc +++ b/kernel/log.cc @@ -354,6 +354,9 @@ static void logv_error_with_prefix(const char *prefix, if (check_expected_logs) log_check_expected(); + + YS_DEBUGTRAP_IF_DEBUGGING; + #ifdef EMSCRIPTEN log_files = backup_log_files; throw 0; @@ -673,7 +676,7 @@ void log_check_expected() } if (item.second.current_count != item.second.expected_count) { log_warn_regexes.clear(); - log_error("Expected warning pattern '%s' found %d time(s), instead of %d time(s) !\n", + log_error("Expected warning pattern '%s' found %d time(s), instead of %d time(s) !\n", item.second.pattern.c_str(), item.second.current_count, item.second.expected_count); } } @@ -700,7 +703,7 @@ void log_check_expected() _exit(0); #else _Exit(0); - #endif + #endif } else { display_error_log_msg = false; log_warn_regexes.clear(); diff --git a/kernel/log.h b/kernel/log.h index 5478482ac..dee5d44d7 100644 --- a/kernel/log.h +++ b/kernel/log.h @@ -50,9 +50,12 @@ std::regex_constants::egrep) #endif -#ifndef _WIN32 +#if defined(_WIN32) +# include <intrin.h> +#else # include <sys/time.h> # include <sys/resource.h> +# include <signal.h> #endif #if defined(_MSC_VER) @@ -69,6 +72,41 @@ YOSYS_NAMESPACE_BEGIN #define S__LINE__sub1(x) S__LINE__sub2(x) #define S__LINE__ S__LINE__sub1(__LINE__) +// YS_DEBUGTRAP is a macro that is functionally equivalent to a breakpoint +// if the platform provides such functionality, and does nothing otherwise. +// If no debugger is attached, it starts a just-in-time debugger if available, +// and crashes the process otherwise. +#if defined(_WIN32) +# define YS_DEBUGTRAP __debugbreak() +#else +# ifndef __has_builtin +// __has_builtin is a GCC/Clang extension; on a different compiler (or old enough GCC/Clang) +// that does not have it, using __has_builtin(...) is a syntax error. +# define __has_builtin(x) 0 +# endif +# if __has_builtin(__builtin_debugtrap) +# define YS_DEBUGTRAP __builtin_debugtrap() +# elif defined(__unix__) +# define YS_DEBUGTRAP raise(SIGTRAP) +# else +# define YS_DEBUGTRAP do {} while(0) +# endif +#endif + +// YS_DEBUGTRAP_IF_DEBUGGING is a macro that is functionally equivalent to a breakpoint +// if a debugger is attached, and does nothing otherwise. +#if defined(_WIN32) +# define YS_DEBUGTRAP_IF_DEBUGGING do { if (IsDebuggerPresent()) DebugBreak(); } while(0) +#elif defined(__unix__) +// There is no reliable (or portable) *nix equivalent of IsDebuggerPresent(). However, +// debuggers will stop when SIGTRAP is raised, even if the action is set to ignore. +# define YS_DEBUGTRAP_IF_DEBUGGING do { \ + sighandler_t old = signal(SIGTRAP, SIG_IGN); raise(SIGTRAP); signal(SIGTRAP, old); \ + } while(0) +#else +# define YS_DEBUGTRAP_IF_DEBUGGING do {} while(0) +#endif + struct log_cmd_error_exception { }; extern std::vector<FILE*> log_files; diff --git a/kernel/register.cc b/kernel/register.cc index 925d0d776..02974e534 100644 --- a/kernel/register.cc +++ b/kernel/register.cc @@ -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()) { diff --git a/kernel/yosys.cc b/kernel/yosys.cc index 01131601f..2ec3dca0c 100644 --- a/kernel/yosys.cc +++ b/kernel/yosys.cc @@ -45,8 +45,10 @@ # 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/"; diff --git a/kernel/yosys.h b/kernel/yosys.h index ed48eec09..af1e376b1 100644 --- a/kernel/yosys.h +++ b/kernel/yosys.h @@ -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); |