#define _POSIX_C_SOURCE 200809L #include #include #include #include "codegen.h" #include "cgC.h" #include "messages.h" #include "libs/stb_ds.h" /* (Std)In --> process --> (Std)Out */ void spawn_with_iofp(const char *path, char *const *argv, pid_t *pid, FILE **in, FILE **out) { int irp[2], asmp[2]; posix_spawn_file_actions_t fileacts; posix_spawn_file_actions_init(&fileacts); if (in != nil) { /* the "in" pipe */ if (pipe(irp) < 0) fatal(nil, nil, "could not open pipe"); posix_spawn_file_actions_addclose(&fileacts, irp[1]); posix_spawn_file_actions_adddup2(&fileacts, irp[0], STDIN_FILENO); } if (out != nil) { /* the "out" pipe */ if (pipe(asmp) < 0) fatal(nil, nil, "could not open pipe"); posix_spawn_file_actions_addclose(&fileacts, asmp[0]); posix_spawn_file_actions_adddup2(&fileacts, asmp[1], STDOUT_FILENO); } if (posix_spawn(pid, path, &fileacts, nil, argv, nil) != 0) fatal(nil, nil, "posix_spawn failed"); posix_spawn_file_actions_destroy(&fileacts); if (in != nil) { close(irp[0]); if ((*in = fdopen(irp[1], "wb")) == nil) fatal(nil, nil, "fdopen fail"); } if (out != nil) { close(asmp[1]); if ((*out = fdopen(asmp[0], "rb")) == nil) fatal(nil, nil, "fdopen fail"); } } void process_wait(pid_t pid) { int pstat; waitpid(pid, &pstat, 0); if (!WIFEXITED(pstat)) fatal(nil, nil, "qbe crashed"); /* did not crash, read return status */ int exitc; if ((exitc = WEXITSTATUS(pstat)) != 0) fatal(nil, nil, "qbe exited with non-zero status %d", exitc); } CodegenCtx * codegen_new(Compiler *cm, enum CodegenBackends backend) { CodegenCtx *ctx = calloc(1, sizeof(*ctx)); ctx->ext_pid = ctx->ld_pid = -1; ctx->backend = backend; ctx->cctx = cm; sh_new_arena(ctx->strings); shdefault(ctx->strings, -1); return ctx; } void codegen_destroy(CodegenCtx *cgctx) { if (cgctx->ext_pid != -1) process_wait(cgctx->ext_pid); if (cgctx->ld_pid != -1) process_wait(cgctx->ld_pid); shfree(cgctx->strings); free(cgctx); } void codegen(CodegenCtx *cgctx, Ast *program) { switch (cgctx->backend) { case CgBackendC: cgC(&(CodegenC){.cgctx = cgctx, .indent = 2}, program); break; case CgBackendLibGccJit: fatal(nil, nil, "libgccjit backend not implemented yet"); break; } }