From 28146f5eab920a001a7c1be04ab8ff4e5aa7f20e Mon Sep 17 00:00:00 2001 From: Michael Forney Date: Sat, 17 Aug 2019 23:23:21 -0700 Subject: driver: Preprocess assembly files with .S extension --- driver.c | 117 ++++++++++++++++++++++++++++++++++++++------------------------- 1 file changed, 70 insertions(+), 47 deletions(-) diff --git a/driver.c b/driver.c index 52616fd..f9cf944 100644 --- a/driver.c +++ b/driver.c @@ -17,8 +17,18 @@ #include "util.h" +enum filetype { + NONE, /* detect based on file extension */ + ASM, /* assembly source */ + ASMPP, /* assembly source requiring preprocessing */ + C, /* C source */ + CPPOUT, /* preprocessed C source */ + OBJ, /* object file */ + QBE, /* QBE IL */ +}; + enum phaseid { - PREPROCESS = 1, + PREPROCESS, COMPILE, CODEGEN, ASSEMBLE, @@ -36,7 +46,8 @@ struct phase { struct input { char *name; - enum phaseid phase; + unsigned phases; + enum filetype filetype; bool lib; }; @@ -68,8 +79,8 @@ usage(const char *fmt, ...) exit(2); } -static enum phaseid -inputphase(const char *name) +static enum filetype +detectfiletype(const char *name) { const char *dot; @@ -77,16 +88,18 @@ inputphase(const char *name) if (dot) { ++dot; if (strcmp(dot, "c") == 0) - return PREPROCESS; + return C; if (strcmp(dot, "i") == 0) - return COMPILE; + return CPPOUT; if (strcmp(dot, "qbe") == 0) - return CODEGEN; - if (strcmp(dot, "s") == 0 || strcmp(dot, "S") == 0) - return ASSEMBLE; + return QBE; + if (strcmp(dot, "s") == 0) + return ASM; + if (strcmp(dot, "S") == 0) + return ASMPP; } - return LINK; + return OBJ; } static char * @@ -131,11 +144,11 @@ spawnphase(struct phase *phase, int *fd, char *input, char *output, bool last) posix_spawn_file_actions_t actions; phase->cmd.len = phase->cmdbase; - if (output) { + if (last && output) { arrayaddptr(&phase->cmd, "-o"); arrayaddptr(&phase->cmd, output); } - if (input) + if (input && *fd == -1) arrayaddptr(&phase->cmd, input); arrayaddptr(&phase->cmd, NULL); @@ -200,20 +213,18 @@ succeeded(const char *phase, pid_t pid, int status) } static void -buildobj(struct input *input, char *output, enum phaseid last) +buildobj(struct input *input, char *output) { - const char *phase, *ext; - char *phaseoutput; + const char *phase; size_t i, npids; pid_t pid; int status, ret, fd; - enum phaseid first = input->phase; bool success = true; - if (input->phase > last || input->phase == LINK) + if (input->filetype == OBJ) return; - if (last == LINK) { - last = ASSEMBLE; + if (input->phases & 1<phases &= ~(1<name, ext); + } else if (input->phases & 1<name, "o"); + } else if (input->phases & 1<name, "s"); + } else if (input->phases & 1<name, "qbe"); } if (strcmp(input->name, "-") == 0) input->name = NULL; npids = 0; - for (i = first, fd = -1, phaseoutput = NULL; i <= last; ++i, ++npids) { - if (i == last) - phaseoutput = output; - ret = spawnphase(&phases[i], &fd, input->name, phaseoutput, i == last); + for (i = PREPROCESS, fd = -1; input->phases; ++i) { + if (!(input->phases & 1<phases &= ~(1<name, output, !input->phases); if (ret) { warn("%s: spawn \"%s\": %s", phases[i].name, *(char **)phases[i].cmd.val, strerror(ret)); goto kill; } - input->name = phaseoutput; + ++npids; } + input->name = output; while (npids > 0) { pid = wait(&status); @@ -306,7 +318,7 @@ buildexe(struct input *inputs, size_t ninputs, char *output) if (waitpid(pid, &status, 0) < 0) fatal("waitpid %ju:", (uintmax_t)pid); for (i = 0; i < ninputs; ++i) { - if (inputs[i].phase < LINK) + if (inputs[i].filetype != OBJ) unlink(inputs[i].name); } exit(!succeeded(p->name, pid, status)); @@ -354,7 +366,8 @@ hasprefix(const char *str, const char *pfx) int main(int argc, char *argv[]) { - enum phaseid first = 0, last = LINK; + enum phaseid last = LINK; + enum filetype filetype = 0; char *arg, *end, *output = NULL, *arch, *qbearch; struct array inputs = {0}, *cmd; struct input *input; @@ -391,12 +404,16 @@ main(int argc, char *argv[]) input = arrayadd(&inputs, sizeof(*input)); input->name = arg; input->lib = false; - if (first) - input->phase = first; - else if (arg[1]) - input->phase = inputphase(arg); - else - usage("reading from standard input requires -x"); + input->filetype = filetype == NONE && arg[1] ? detectfiletype(arg) : filetype; + switch (input->filetype) { + case ASM: input->phases = 1<phases = 1<phases = 1<phases = 1<phases = 1<phases = 1<name = nextarg(&argv); input->lib = true; - input->phase = LINK; + input->filetype = OBJ; + input->phases = 1<phases &= (1 << last + 1) - 1; + buildobj(input, output); + } if (last == LINK) { if (!output) output = "a.out"; -- cgit v1.2.3