diff options
-rw-r--r-- | src/codegen.c | 146 | ||||
-rw-r--r-- | src/codegen.h | 3 | ||||
-rw-r--r-- | src/common.h | 2 | ||||
-rw-r--r-- | src/main.c | 2 |
4 files changed, 86 insertions, 67 deletions
diff --git a/src/codegen.c b/src/codegen.c index a9c3397..08f5ab5 100644 --- a/src/codegen.c +++ b/src/codegen.c @@ -30,13 +30,13 @@ struct cgctx { static LLVMTypeRef type2llvm(struct cgctx, type_t); -static void codegenast(struct cgctx, mpq_t *, type_t *, ast_t, +static void codegenast(struct cgctx, mpq_t *, type_t *, ast_t, aux_t , lexemes_t) __attribute__((nonnull)); void codegen(const char *file, mpq_t *folds, scope_t *scps, type_t *types, - ast_t ast, lexemes_t toks) + ast_t ast, aux_t aux, lexemes_t toks) { (void)scps; char *triple = LLVMGetDefaultTargetTriple(); @@ -51,7 +51,7 @@ codegen(const char *file, mpq_t *folds, scope_t *scps, type_t *types, LLVMSetTarget(ctx.mod, triple); LLVMDisposeMessage(triple); - codegenast(ctx, folds, types, ast, toks); + codegenast(ctx, folds, types, ast, aux, toks); arena_free(&ctx.a); @@ -69,65 +69,61 @@ codegen(const char *file, mpq_t *folds, scope_t *scps, type_t *types, static idx_t codegendecl(struct cgctx ctx, mpq_t *folds, type_t *types, ast_t ast, - lexemes_t toks, idx_t i); + aux_t aux, lexemes_t toks, idx_t i); idx_t codegentypedexpr(struct cgctx ctx, mpq_t *folds, type_t *types, ast_t ast, - lexemes_t toks, idx_t i, type_t type, LLVMValueRef *outv) + aux_t aux, lexemes_t toks, idx_t i, type_t type, + LLVMValueRef *outv) { - if ((*folds[i])._mp_den._mp_d != NULL) { - if (type.kind == TYPE_NUM) { - mpz_ptr num, den; - num = mpq_numref(folds[i]); - den = mpq_denref(folds[i]); - if (mpz_cmp_ui(den, 1) != 0) - err("Invalid integer"); - - int cmp; - if ((sizeof(unsigned long) >= 8 && type.size <= 8) - || type.size <= 4) - { - unsigned long x = 1UL << (type.size * 8 - type.issigned); - cmp = mpz_cmp_ui(num, x - 1); - } else { - mpz_t x; - - /* Compute ‘(1 << bits) - 1’ to get the maximum value for the - integer type */ - mp_bitcnt_t bits = type.size * 8; - if (type.issigned) - bits--; - mpz_init_set_ui(x, 1); - mpz_mul_2exp(x, x, bits); - mpz_sub_ui(x, x, 1); - - cmp = mpz_cmp(num, x); - - mpz_clear(x); - } + /* If true, implies numeric constant */ + if (MPQ_IS_INIT(folds[i])) { + mpz_ptr num, den; + num = mpq_numref(folds[i]); + den = mpq_denref(folds[i]); + if (mpz_cmp_ui(den, 1) != 0) + err("Invalid integer"); + + int cmp; + if ((sizeof(unsigned long) >= 8 && type.size <= 8) + || type.size <= 4) + { + unsigned long x = 1UL << (type.size * 8 - type.issigned); + cmp = mpz_cmp_ui(num, x - 1); + } else { + mpz_t x; + mp_bitcnt_t bits = type.size * 8; + if (type.issigned) + bits--; + mpz_init_set_ui(x, 1); + mpz_mul_2exp(x, x, bits); + mpz_sub_ui(x, x, 1); + cmp = mpz_cmp(num, x); + mpz_clear(x); + } - if (cmp > 0) - err("Integer too large for datatype"); + if (cmp > 0) + err("Integer too large for datatype"); - /* The max value of a u128 is length 39 */ - char buf[40]; - mpz_get_str(buf, 10, num); - *outv = LLVMConstIntOfString(type2llvm(ctx, type), buf, 10); - } else - err("not implemented 1"); + /* The max value of a u128 is length 39 */ + char buf[40]; + mpz_get_str(buf, 10, num); + *outv = LLVMConstIntOfString(type2llvm(ctx, type), buf, 10); return fwdnode(ast, i); } - err("not implemented 2"); + + assert(ast.kinds[i] == ASTIDENT); + err("%s():%d: not implemented", __func__, __LINE__); } idx_t codegenstmt(struct cgctx ctx, mpq_t *folds, type_t *types, ast_t ast, - lexemes_t toks, idx_t i) + aux_t aux, lexemes_t toks, idx_t i) { switch (ast.kinds[i]) { case ASTDECL: case ASTCDECL: - return codegendecl(ctx, folds, types, ast, toks, i); + return codegendecl(ctx, folds, types, ast, aux, toks, i); case ASTRET: { idx_t expr = ast.kids[i].rhs; if (expr == AST_EMPTY) { @@ -136,7 +132,8 @@ codegenstmt(struct cgctx ctx, mpq_t *folds, type_t *types, ast_t ast, } LLVMValueRef v; - i = codegentypedexpr(ctx, folds, types, ast, toks, expr, types[i], &v); + i = codegentypedexpr(ctx, folds, types, ast, aux, toks, expr, types[i], + &v); (void)LLVMBuildRet(ctx.bob, v); return i; } @@ -146,19 +143,19 @@ codegenstmt(struct cgctx ctx, mpq_t *folds, type_t *types, ast_t ast, } idx_t -codegenblk(struct cgctx ctx, mpq_t *folds, type_t *types, ast_t ast, +codegenblk(struct cgctx ctx, mpq_t *folds, type_t *types, ast_t ast, aux_t aux, lexemes_t toks, idx_t i) { pair_t p = ast.kids[i]; for (i = p.lhs; i <= p.rhs; - i = codegenstmt(ctx, folds, types, ast, toks, i)) + i = codegenstmt(ctx, folds, types, ast, aux, toks, i)) ; return i; } idx_t codegenfunc(struct cgctx ctx, mpq_t *folds, type_t *types, ast_t ast, - lexemes_t toks, idx_t i, const char *name) + aux_t aux, lexemes_t toks, idx_t i, const char *name) { LLVMTypeRef ret = types[i].ret == NULL ? LLVMVoidTypeInContext(ctx.ctx) @@ -171,32 +168,37 @@ codegenfunc(struct cgctx ctx, mpq_t *folds, type_t *types, ast_t ast, LLVMPositionBuilderAtEnd(ctx.bob, entry); pair_t p = ast.kids[i]; - i = codegenblk(ctx, folds, types, ast, toks, p.rhs); + i = codegenblk(ctx, folds, types, ast, aux, toks, p.rhs); if (ast.kids[p.lhs].rhs == AST_EMPTY) LLVMBuildRetVoid(ctx.bob); return i; } idx_t -codegendecl(struct cgctx ctx, mpq_t *folds, type_t *types, ast_t ast, +codegendecl(struct cgctx ctx, mpq_t *folds, type_t *types, ast_t ast, aux_t aux, lexemes_t toks, idx_t i) { pair_t p = ast.kids[i]; - /* Constants are purely a compiler concept; they aren’t generated - into anything */ - if (ast.kinds[i] == ASTCDECL && ast.kinds[p.rhs] != ASTFN) - return fwdnode(ast, i); - if (ast.kinds[p.rhs] == ASTFN) { + if (ast.kinds[i] == ASTCDECL) { + /* Constants are purely a compiler concept; they aren’t generated + into anything */ + if (ast.kinds[p.rhs] != ASTFN) + return fwdnode(ast, i); + strview_t sv = toks.strs[ast.lexemes[i]]; /* TODO: Namespace the name */ /* TODO: Temporary allocator */ char *name = bufalloc(NULL, sv.len + 1, 1); svtocstr(name, sv); - i = codegenfunc(ctx, folds, types, ast, toks, p.rhs, name); + i = codegenfunc(ctx, folds, types, ast, aux, toks, p.rhs, name); free(name); return i; - } else if (!types[i].isfloat) { + } + + assert(ast.kinds[i] == ASTDECL); + + if (!types[i].isfloat && aux.buf[p.lhs].decl.isstatic) { strview_t sv = toks.strs[ast.lexemes[i]]; /* TODO: Namespace the name */ /* TODO: Temporary allocator */ @@ -206,21 +208,35 @@ codegendecl(struct cgctx ctx, mpq_t *folds, type_t *types, ast_t ast, free(name); LLVMValueRef v; - (void)codegentypedexpr(ctx, folds, types, ast, toks, ast.kids[i].rhs, types[i], &v); + i = codegentypedexpr(ctx, folds, types, ast, aux, toks, p.rhs, types[i], &v); LLVMSetInitializer(globl, v); LLVMSetLinkage(globl, LLVMInternalLinkage); + return i; + } + if (!types[i].isfloat /* && !aux.buf[p.lhs].decl.isstatic */) { + strview_t 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 var, val; + var = LLVMBuildAlloca(ctx.bob, t, svtocstr(name, sv)); + free(name); + i = codegentypedexpr(ctx, folds, types, ast, aux, toks, p.rhs, types[i], &val); + LLVMBuildStore(ctx.bob, val, var); + return i; + } - return fwdnode(ast, i); - } else /* && types[i].isfloat */ - err("%s():%d: TODO", __func__, __LINE__); + /* types[i].isfloat */ + err("%s():%d: TODO", __func__, __LINE__); } void -codegenast(struct cgctx ctx, mpq_t *folds, type_t *types, ast_t ast, +codegenast(struct cgctx ctx, mpq_t *folds, type_t *types, ast_t ast, aux_t aux, lexemes_t toks) { for (idx_t i = 0; i < ast.len; - i = codegendecl(ctx, folds, types, ast, toks, i)) + i = codegendecl(ctx, folds, types, ast, aux, toks, i)) ; } diff --git a/src/codegen.h b/src/codegen.h index ece93aa..338ade4 100644 --- a/src/codegen.h +++ b/src/codegen.h @@ -7,7 +7,8 @@ #include "lexer.h" #include "parser.h" -void codegen(const char *, mpq_t *, scope_t *, type_t *, ast_t, lexemes_t) +void codegen(const char *, mpq_t *, scope_t *, type_t *, ast_t, aux_t, + lexemes_t) __attribute__((nonnull)); #endif /* !ORYX_CODEGEN_H */ diff --git a/src/common.h b/src/common.h index 6a142f7..7030e4b 100644 --- a/src/common.h +++ b/src/common.h @@ -17,4 +17,6 @@ # include <stdio.h> #endif +#define MPQ_IS_INIT(x) (mpq_denref(x)->_mp_d != NULL) + #endif /* !ORYX_COMMON_H */ @@ -40,7 +40,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, toks); + codegen(argv[1], folds, scps, types, ast, aux, toks); #if DEBUG for (size_t i = 0; i < ast.len; i++) { |