abc, abc9_exe: fix build on WASI (and others with `const* stdout`).

C does not guarantee that stdout/stderr can be reassigned.
Most platforms do make them assignable, however musl and WASI that
is based on musl do not. WASI does not have `dup2()`; instead it has
its own non-portable version of it that can only assign to previously
allocated fds.

Update the stream redirection code so that it does the right thing
on WASI and other platforms.
This commit is contained in:
Catherine 2023-07-23 01:36:37 +00:00
parent 411b6e98cd
commit 6965abeefa
2 changed files with 44 additions and 14 deletions

View File

@ -1091,17 +1091,28 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin
buffer = stringf("\"%s\" -s -f %s/abc.script 2>&1", exe_file.c_str(), tempdir_name.c_str());
log("Running ABC command: %s\n", replace_tempdir(buffer, tempdir_name, show_tempdir).c_str());
abc_output_filter filt(tempdir_name, show_tempdir);
#ifndef YOSYS_LINK_ABC
abc_output_filter filt(tempdir_name, show_tempdir);
int ret = run_command(buffer, std::bind(&abc_output_filter::next_line, filt, std::placeholders::_1));
#else
string temp_stdouterr_name = stringf("%s/stdouterr.txt", tempdir_name.c_str());
FILE *temp_stdouterr_w = fopen(temp_stdouterr_name.c_str(), "w");
if (temp_stdouterr_w == NULL)
log_error("ABC: cannot open a temporary file for output redirection");
FILE *old_stdout = stdout;
FILE *old_stderr = stderr;
stdout = stderr = temp_stdouterr_w;
fflush(stdout);
fflush(stderr);
FILE *old_stdout = fopen(temp_stdouterr_name.c_str(), "r"); // need any fd for renumbering
FILE *old_stderr = fopen(temp_stdouterr_name.c_str(), "r"); // need any fd for renumbering
#if defined(__wasm)
#define fd_renumber(from, to) (void)__wasi_fd_renumber(from, to)
#else
#define fd_renumber(from, to) dup2(from, to)
#endif
fd_renumber(fileno(stdout), fileno(old_stdout));
fd_renumber(fileno(stderr), fileno(old_stderr));
fd_renumber(fileno(temp_stdouterr_w), fileno(stdout));
fd_renumber(fileno(temp_stdouterr_w), fileno(stderr));
fclose(temp_stdouterr_w);
// These needs to be mutable, supposedly due to getopt
char *abc_argv[5];
string tmp_script_name = stringf("%s/abc.script", tempdir_name.c_str());
@ -1115,10 +1126,14 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin
free(abc_argv[1]);
free(abc_argv[2]);
free(abc_argv[3]);
stdout = old_stdout;
stderr = old_stderr;
fclose(temp_stdouterr_w);
fflush(stdout);
fflush(stderr);
fd_renumber(fileno(old_stdout), fileno(stdout));
fd_renumber(fileno(old_stderr), fileno(stderr));
fclose(old_stdout);
fclose(old_stderr);
std::ifstream temp_stdouterr_r(temp_stdouterr_name);
abc_output_filter filt(tempdir_name, show_tempdir);
for (std::string line; std::getline(temp_stdouterr_r, line); )
filt.next_line(line + "\n");
temp_stdouterr_r.close();

View File

@ -267,17 +267,28 @@ void abc9_module(RTLIL::Design *design, std::string script_file, std::string exe
buffer = stringf("\"%s\" -s -f %s/abc.script 2>&1", exe_file.c_str(), tempdir_name.c_str());
log("Running ABC command: %s\n", replace_tempdir(buffer, tempdir_name, show_tempdir).c_str());
abc9_output_filter filt(tempdir_name, show_tempdir);
#ifndef YOSYS_LINK_ABC
abc9_output_filter filt(tempdir_name, show_tempdir);
int ret = run_command(buffer, std::bind(&abc9_output_filter::next_line, filt, std::placeholders::_1));
#else
string temp_stdouterr_name = stringf("%s/stdouterr.txt", tempdir_name.c_str());
FILE *temp_stdouterr_w = fopen(temp_stdouterr_name.c_str(), "w");
if (temp_stdouterr_w == NULL)
log_error("ABC: cannot open a temporary file for output redirection");
FILE *old_stdout = stdout;
FILE *old_stderr = stderr;
stdout = stderr = temp_stdouterr_w;
fflush(stdout);
fflush(stderr);
FILE *old_stdout = fopen(temp_stdouterr_name.c_str(), "r"); // need any fd for renumbering
FILE *old_stderr = fopen(temp_stdouterr_name.c_str(), "r"); // need any fd for renumbering
#if defined(__wasm)
#define fd_renumber(from, to) (void)__wasi_fd_renumber(from, to)
#else
#define fd_renumber(from, to) dup2(from, to)
#endif
fd_renumber(fileno(stdout), fileno(old_stdout));
fd_renumber(fileno(stderr), fileno(old_stderr));
fd_renumber(fileno(temp_stdouterr_w), fileno(stdout));
fd_renumber(fileno(temp_stdouterr_w), fileno(stderr));
fclose(temp_stdouterr_w);
// These needs to be mutable, supposedly due to getopt
char *abc9_argv[5];
string tmp_script_name = stringf("%s/abc.script", tempdir_name.c_str());
@ -291,10 +302,14 @@ void abc9_module(RTLIL::Design *design, std::string script_file, std::string exe
free(abc9_argv[1]);
free(abc9_argv[2]);
free(abc9_argv[3]);
stdout = old_stdout;
stderr = old_stderr;
fclose(temp_stdouterr_w);
fflush(stdout);
fflush(stderr);
fd_renumber(fileno(old_stdout), fileno(stdout));
fd_renumber(fileno(old_stderr), fileno(stderr));
fclose(old_stdout);
fclose(old_stderr);
std::ifstream temp_stdouterr_r(temp_stdouterr_name);
abc9_output_filter filt(tempdir_name, show_tempdir);
for (std::string line; std::getline(temp_stdouterr_r, line); )
filt.next_line(line + "\n");
temp_stdouterr_r.close();