diff options
Diffstat (limited to 'src/codegen.c')
-rw-r--r-- | src/codegen.c | 53 |
1 files changed, 38 insertions, 15 deletions
diff --git a/src/codegen.c b/src/codegen.c index a263db2..252ac29 100644 --- a/src/codegen.c +++ b/src/codegen.c @@ -12,6 +12,7 @@ #include "alloc.h" #include "analyzer.h" +#include "bitset.h" #include "common.h" #include "errors.h" #include "parser.h" @@ -34,12 +35,13 @@ struct cgctx { arena_t *a; scratch_t *s; - mpq_t *folds; - scope_t *scps; - type_t **types; ast_t ast; aux_t aux; + bitset_t *cnst; + fold_t *folds; lexemes_t toks; + scope_t *scps; + type_t **types; LLVMBuilderRef bob; LLVMContextRef ctx; @@ -60,8 +62,8 @@ 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, aux_t aux, lexemes_t toks) +codegen(const char *file, bitset_t *cnst, fold_t *folds, scope_t *scps, + type_t **types, ast_t ast, aux_t aux, lexemes_t toks) { LLVM_TARGET_INIT(AArch64); LLVM_TARGET_INIT(X86); @@ -81,12 +83,13 @@ codegen(const char *file, mpq_t *folds, scope_t *scps, type_t **types, .a = &(arena_t){0}, .s = &(scratch_t){0}, - .folds = folds, - .scps = scps, - .types = types, .ast = ast, .aux = aux, + .cnst = cnst, + .folds = folds, + .scps = scps, .toks = toks, + .types = types, .ctx = llctx, .mod = llmod, @@ -143,13 +146,12 @@ static idx_t codegendecl(struct cgctx ctx, idx_t); idx_t codegentypedexpr(struct cgctx ctx, idx_t i, type_t *T, LLVMValueRef *outv) { - /* If true, implies numeric constant */ - if (MPQ_IS_INIT(ctx.folds[i]) && !T->isfloat) { + if (T->kind == TYPE_NUM && TESTBIT(ctx.cnst, i) && !T->isfloat) { char buf[40 /* The max value of a u128 is length 39 */]; - mpz_get_str(buf, 10, mpq_numref(ctx.folds[i])); + mpz_get_str(buf, 10, mpq_numref(ctx.folds[i].q)); *outv = LLVMConstIntOfString(type2llvm(ctx, T), buf, 10); return fwdnode(ctx.ast, i); - } else if (MPQ_IS_INIT(ctx.folds[i]) /* && type.isfloat */) { + } else if (T->kind == TYPE_NUM && TESTBIT(ctx.cnst, i)) { char *s, *buf; size_t len; mpf_t x; @@ -175,7 +177,7 @@ codegentypedexpr(struct cgctx ctx, idx_t i, type_t *T, LLVMValueRef *outv) } mpf_init2(x, prec); - mpf_set_q(x, ctx.folds[i]); + mpf_set_q(x, ctx.folds[i].q); s = mpf_get_str(NULL, &e, 10, 0, x); len = strlen(s); @@ -191,6 +193,9 @@ codegentypedexpr(struct cgctx ctx, idx_t i, type_t *T, LLVMValueRef *outv) free(s); mpf_clear(x); return fwdnode(ctx.ast, i); + } else if (T->kind == TYPE_BOOL && TESTBIT(ctx.cnst, i)) { + *outv = LLVMConstInt(type2llvm(ctx, ctx.types[i]), ctx.folds[i].b, false); + return fwdnode(ctx.ast, i); } switch (ctx.ast.kinds[i]) { @@ -257,6 +262,24 @@ codegentypedexpr(struct cgctx ctx, idx_t i, type_t *T, LLVMValueRef *outv) ctx.bob, vl, vr, bo.name); return ni; } + case ASTBINEQ: + case ASTBINNEQ: { + static const struct binop { + LLVMIntPredicate pred; + const char *name; + } binoptbl[UINT8_MAX + 1] = { + [ASTBINEQ] = {LLVMIntEQ, "ieq"}, + [ASTBINNEQ] = {LLVMIntNE, "ine"}, + }; + + idx_t lhs = ctx.ast.kids[i].lhs, rhs = ctx.ast.kids[i].rhs; + LLVMValueRef vl, vr; + (void)codegentypedexpr(ctx, lhs, ctx.types[i], &vl); + idx_t ni = codegentypedexpr(ctx, rhs, ctx.types[i], &vr); + struct binop bo = binoptbl[ctx.ast.kinds[i]]; + *outv = LLVMBuildICmp(ctx.bob, bo.pred, vl, vr, bo.name); + return ni; + } default: __builtin_unreachable(); } @@ -451,8 +474,8 @@ LLVMTypeRef type2llvm(struct cgctx ctx, type_t *T) { switch (T->kind) { - case TYPE_FN: - err("codegen: %s: Not implemented for function types", __func__); + case TYPE_BOOL: + return LLVMInt1TypeInContext(ctx.ctx); case TYPE_NUM: assert(T->size != 0); assert((unsigned)T->size * 8 <= 128); |