aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorThomas Voss <mail@thomasvoss.com> 2024-06-25 15:50:13 +0200
committerThomas Voss <mail@thomasvoss.com> 2024-06-25 15:50:21 +0200
commitff415f69a93812418cc60a33dd14452fc6b2901a (patch)
tree1578ef579b958927e64e0835c81339a00fce65fb /src
parent0d28ae797b89f05b08b1051f0d2dd72d2416d409 (diff)
Support generation of asm/obj files
Diffstat (limited to 'src')
-rw-r--r--src/codegen.c26
-rw-r--r--src/main.c51
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);
diff --git a/src/main.c b/src/main.c
index a8dabea..cc6cfd7 100644
--- a/src/main.c
+++ b/src/main.c
@@ -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++) {