diff options
-rw-r--r-- | src/analyzer.c | 20 | ||||
-rw-r--r-- | src/codegen.c | 110 | ||||
-rw-r--r-- | src/codegen.h | 4 | ||||
-rw-r--r-- | src/main.c | 7 |
4 files changed, 109 insertions, 32 deletions
diff --git a/src/analyzer.c b/src/analyzer.c index eaf0ab2..798b34c 100644 --- a/src/analyzer.c +++ b/src/analyzer.c @@ -108,6 +108,7 @@ analyzeprog(struct ast ast, struct lexemes toks, arena *a, struct type **types, analyzeast(*scps, *types, ast, toks, a); *folds = bufalloc(NULL, ast.len, sizeof(**folds)); + memset(*folds, 0, ast.len * sizeof(**folds)); constfold(*folds, *scps, *types, ast, toks, a); } @@ -401,7 +402,8 @@ constfoldexpr(struct cfctx ctx, mpq_t *folds, struct scope *scps, } buf[len] = 0; - (void)mpq_set_str(folds[i], buf, 10); + int ret = mpq_set_str(folds[i], buf, 10); + assert(ret == 0); free(buf); return fwdnode(ast, i); @@ -427,12 +429,24 @@ constfoldexpr(struct cfctx ctx, mpq_t *folds, struct scope *scps, break; case ASTCDECL: case ASTPCDECL: { - *folds[i] = *folds[*ip]; + idx_t_ expr = ast.kids[*ip].rhs; + assert(expr != AST_EMPTY); +#if DEBUG + mpq_init(folds[i]); + mpq_set(folds[i], folds[expr]); +#else + *folds[i] = *folds[expr]; +#endif if ((*folds[i])._mp_den._mp_d == NULL) { ctx.si = lvl; (void)constfolddecl(ctx, folds, scps, types, ast, toks, *ip); - *folds[i] = *folds[*ip]; +#if DEBUG + mpq_init(folds[i]); + mpq_set(folds[i], folds[expr]); +#else + *folds[i] = *folds[expr]; +#endif assert((*folds[i])._mp_den._mp_d != NULL); } break; diff --git a/src/codegen.c b/src/codegen.c index 48c43ce..5b883b5 100644 --- a/src/codegen.c +++ b/src/codegen.c @@ -1,8 +1,12 @@ #include <ctype.h> +#include <stdbool.h> #include <stdint.h> #include <stdlib.h> #include <string.h> +#include <stdio.h> + +#include <gmp.h> #include <llvm-c/Analysis.h> #include <llvm-c/Core.h> #include <llvm-c/ExecutionEngine.h> @@ -25,30 +29,37 @@ struct cgctx { struct strview namespace; }; -// static LLVMTypeRef type2llvm(struct cgctx, struct type); +static LLVMTypeRef type2llvm(struct cgctx, struct type); // static void str2val(mpq_t, struct strview); // static struct val *cvmap_insert(cvmap **, struct strview, arena *) // __attribute__((nonnull(1))); +static void codegenast(struct cgctx, mpq_t *, struct type *, struct ast, + struct lexemes) + __attribute__((nonnull)); + void -codegen(const char *file, struct type *types, struct ast ast, - struct lexemes toks) +codegen(const char *file, mpq_t *folds, struct scope *scps, struct type *types, + struct ast ast, struct lexemes toks) { (void)types; + (void)scps; (void)ast; (void)toks; char *triple = LLVMGetDefaultTargetTriple(); struct cgctx ctx; - ctx.a = NULL; + ctx.a = NULL; ctx.namespace.p = NULL; - ctx.ctx = LLVMContextCreate(); - ctx.mod = LLVMModuleCreateWithNameInContext("oryx", ctx.ctx); - ctx.bob = LLVMCreateBuilderInContext(ctx.ctx); + ctx.ctx = LLVMContextCreate(); + ctx.mod = LLVMModuleCreateWithNameInContext("oryx", ctx.ctx); + ctx.bob = LLVMCreateBuilderInContext(ctx.ctx); LLVMSetSourceFileName(ctx.mod, file, strlen(file)); LLVMSetTarget(ctx.mod, triple); LLVMDisposeMessage(triple); + codegenast(ctx, folds, types, ast, toks); + arena_free(&ctx.a); LLVMDisposeBuilder(ctx.bob); @@ -63,26 +74,71 @@ codegen(const char *file, struct type *types, struct ast ast, LLVMContextDispose(ctx.ctx); } -// LLVMTypeRef -// type2llvm(struct cgctx ctx, struct type t) -// { -// switch (t.kind) { -// case TYPE_FN: -// err("codegen: %s: Not implemented for function types", __func__); -// case TYPE_NUM: -// /* TODO: Floats */ -// if (t.isfloat) -// err("codegen: %s: Not implemented for floats", __func__); -// /* TODO: Arbitrary precision */ -// if (t.size == 0) -// return LLVMInt64TypeInContext(ctx.ctx); -// assert((unsigned)t.size * 8 <= UINT8_MAX); -// return LLVMIntTypeInContext(ctx.ctx, t.size * 8); -// default: -// __builtin_unreachable(); -// } -// } -// +idx_t_ +codegendecl(struct cgctx ctx, mpq_t *folds, struct type *types, struct ast ast, + struct lexemes toks, idx_t_ i) +{ + /* Constants are purely a compiler concept; they aren’t generated + into anything */ + if ((ast.kinds[i] | 1) == ASTPCDECL) + return fwdnode(ast, i); + + struct pair p = ast.kids[i]; + switch (ast.kinds[p.rhs]) { + case ASTFN: + err("%s():%d: TODO", __func__, __LINE__); + default: { + struct strview sv = toks.strs[ast.lexemes[i]]; + /* TODO: Namespace the name */ + /* TODO: Temporary allocator */ + char *name = bufalloc(NULL, sv.len + 1, 1); + LLVMTypeRef t = type2llvm(ctx, types[i]); + LLVMValueRef globl = LLVMAddGlobal(ctx.mod, t, svtocstr(name, sv)); + free(name); + + /* TODO: Assert that the fold is an integer */ + + /* The max value of a u128 is length 39 */ + char buf[40]; + mpq_get_str(buf, 10, folds[p.rhs]); + + LLVMSetInitializer(globl, LLVMConstIntOfString(t, buf, 10)); + LLVMSetLinkage(globl, LLVMInternalLinkage); + + return fwdnode(ast, i); + } + } +} + +void +codegenast(struct cgctx ctx, mpq_t *folds, struct type *types, struct ast ast, + struct lexemes toks) +{ + for (idx_t_ i = 0; i < ast.len; + i = codegendecl(ctx, folds, types, ast, toks, i)) + ; +} + +LLVMTypeRef +type2llvm(struct cgctx ctx, struct type t) +{ + switch (t.kind) { + case TYPE_FN: + err("codegen: %s: Not implemented for function types", __func__); + case TYPE_NUM: + /* TODO: Floats */ + if (t.isfloat) + err("codegen: %s: Not implemented for floats", __func__); + /* TODO: Arbitrary precision */ + if (t.size == 0) + return LLVMInt64TypeInContext(ctx.ctx); + assert((unsigned)t.size * 8 <= UINT8_MAX); + return LLVMIntTypeInContext(ctx.ctx, t.size * 8); + default: + __builtin_unreachable(); + } +} + // void // str2val(mpq_t rop, struct strview sv) // { diff --git a/src/codegen.h b/src/codegen.h index eda799d..6f4af7a 100644 --- a/src/codegen.h +++ b/src/codegen.h @@ -1,11 +1,13 @@ #ifndef ORYX_CODEGEN_H #define ORYX_CODEGEN_H +#include <gmp.h> + #include "analyzer.h" #include "lexer.h" #include "parser.h" -void codegen(const char *, struct scope *, struct type *, struct ast, +void codegen(const char *, mpq_t *, struct scope *, struct type *, struct ast, struct lexemes) __attribute__((nonnull)); @@ -37,9 +37,14 @@ main(int argc, char **argv) struct lexemes toks = lexstring(src, srclen); struct ast ast = parsetoks(toks); analyzeprog(ast, toks, &a, &types, &scps, &folds); - codegen(argv[1], scps, types, ast, toks); + codegen(argv[1], folds, scps, types, ast, toks); #if DEBUG + for (size_t i = 0; i < ast.len; i++) { + if ((*folds[i])._mp_den._mp_d != NULL) + mpq_clear(folds[i]); + } + free(folds); free(scps); free(src); |