diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/codegen.c | 26 | ||||
-rw-r--r-- | src/main.c | 51 |
2 files changed, 69 insertions, 8 deletions
diff --git a/src/codegen.c b/src/codegen.c index 1567adf..a9b1430 100644 --- a/src/codegen.c +++ b/src/codegen.c @@ -29,7 +29,6 @@ LLVMInitialize##x##TargetMC(); \ } while (false) - /* A context structure we can pass to all the codegen functions just so they have easy access to everything */ struct cgctx { @@ -53,9 +52,11 @@ struct cgctx { strview_t namespace; }; +static void codegenast(struct cgctx); static LLVMTypeRef type2llvm(struct cgctx, type_t); -static void codegenast(struct cgctx); +extern bool lflag, sflag; +extern const char *oflag; void codegen(const char *file, mpq_t *folds, scope_t *scps, type_t *types, ast_t ast, @@ -103,7 +104,26 @@ codegen(const char *file, mpq_t *folds, scope_t *scps, type_t *types, ast_t ast, if (LLVMVerifyModule(ctx.mod, LLVMReturnStatusAction, &error) == 1) err("codegen: %s", error); - LLVMDumpModule(ctx.mod); + if (lflag) { + if (oflag == NULL) + LLVMDumpModule(ctx.mod); + else if (LLVMPrintModuleToFile(llmod, oflag, &error) == 1) + err("codegen: %s", error); + } else { + LLVMCodeGenFileType ft; + const char *dst = oflag == NULL ? "out.o" : oflag; + + if (sflag) { + size_t n = strlen(dst); + char *buf = memcpy(tmpalloc(ctx.s, n + 1, 1), dst, n); + buf[n - 1] = 's'; + buf[n - 0] = 0; + dst = buf; + ft = LLVMAssemblyFile; + } else + ft = LLVMObjectFile; + LLVMTargetMachineEmitToFile(llmach, llmod, dst, ft, &error); + } #if DEBUG tmpfree(ctx.s); @@ -6,6 +6,9 @@ #include <unistd.h> #include <gmp.h> +#define OPTPARSE_API static +#define OPTPARSE_IMPLEMENTATION +#include <optparse.h> #include "alloc.h" #include "analyzer.h" @@ -20,16 +23,54 @@ static char *readfile(const char *file, size_t *bufsz) __attribute__((returns_nonnull, nonnull)); +bool lflag, sflag; +const char *oflag; + int main(int argc, char **argv) { - if (argc != 2) { - fputs("Usage: oryx file\n", stderr); - exit(EXIT_FAILURE); + struct optparse_long longopts[] = { + {"assembly", 's', OPTPARSE_NONE}, + {"emit-llvm", 'l', OPTPARSE_NONE}, + {"output", 'o', OPTPARSE_REQUIRED}, + {0}, + }; + + int opt; + struct optparse opts; + optparse_init(&opts, argv); + + while ((opt = optparse_long(&opts, longopts, NULL)) != -1) { + switch (opt) { + case 'o': + oflag = opts.optarg; + break; + case 'l': + lflag = true; + break; + case 's': + sflag = true; + break; + default: + /* TODO: Add warn() to errors.h */ + fprintf(stderr, "oryx: %s\n", opts.errmsg); +usage: + fprintf(stderr, "Usage: oryx [-l | -s] [-o file] source\n"); + exit(EXIT_FAILURE); + } } + if (lflag && sflag) + goto usage; + + argc -= opts.optind; + argv += opts.optind; + + if (argc != 1) + goto usage; + size_t srclen; - char *src = readfile(argv[1], &srclen); + char *src = readfile(argv[0], &srclen); aux_t aux; mpq_t *folds; @@ -40,7 +81,7 @@ main(int argc, char **argv) lexemes_t toks = lexstring(src, srclen); ast_t ast = parsetoks(toks, &aux); analyzeprog(ast, aux, toks, &a, &types, &scps, &folds); - codegen(argv[1], folds, scps, types, ast, aux, toks); + codegen(argv[0], folds, scps, types, ast, aux, toks); #if DEBUG for (size_t i = 0; i < ast.len; i++) { |