diff options
Diffstat (limited to 'src/codegen.c')
-rw-r--r-- | src/codegen.c | 69 |
1 files changed, 24 insertions, 45 deletions
diff --git a/src/codegen.c b/src/codegen.c index 6b5f5e0..ff16b73 100644 --- a/src/codegen.c +++ b/src/codegen.c @@ -145,38 +145,8 @@ codegentypedexpr(struct cgctx ctx, idx_t i, type_t type, LLVMValueRef *outv) { /* If true, implies numeric constant */ if (MPQ_IS_INIT(ctx.folds[i]) && !type.isfloat) { - /* TODO: Move this kind of range checking to the - constant folding stage? */ - if (!type.issigned && mpq_sgn(ctx.folds[i]) == -1) - err("Cannot convert negative value to unsigned type"); - - if (!MPQ_IS_WHOLE(ctx.folds[i])) - err("codegen: Invalid integer"); - - int cmp; - mpz_ptr num = mpq_numref(ctx.folds[i]); - assert(type.size != 0); - /* TODO: Can we make the first branch work when the type has the - same size as an unsigned long? */ - if (type.size < sizeof(unsigned long)) { - 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 - type.issigned; - 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"); - - /* The max value of a u128 is length 39 */ - char buf[40]; - mpz_get_str(buf, 10, num); + char buf[40 /* The max value of a u128 is length 39 */]; + mpz_get_str(buf, 10, mpq_numref(ctx.folds[i])); *outv = LLVMConstIntOfString(type2llvm(ctx, type), buf, 10); return fwdnode(ctx.ast, i); } else if (MPQ_IS_INIT(ctx.folds[i]) /* && type.isfloat */) { @@ -229,26 +199,28 @@ codegentypedexpr(struct cgctx ctx, idx_t i, type_t type, LLVMValueRef *outv) LLVMTypeRef t = type2llvm(ctx, ctx.types[i]); LLVMValueRef ptrval = symtab_insert(&ctx.scps[ctx.scpi].map, sv, NULL)->v; - *outv = LLVMBuildLoad2(ctx.bob, t, ptrval, "loadtmp"); + *outv = LLVMBuildLoad2(ctx.bob, t, ptrval, "load"); return fwdnode(ctx.ast, i); } case ASTUNCMPL: { LLVMValueRef v, minus_one; minus_one = LLVMConstInt(type2llvm(ctx, ctx.types[i]), -1, false); idx_t ni = codegentypedexpr(ctx, ctx.ast.kids[i].rhs, ctx.types[i], &v); - *outv = LLVMBuildXor(ctx.bob, v, minus_one, "cmpltmp"); + *outv = LLVMBuildXor(ctx.bob, v, minus_one, "cmpl"); return ni; } case ASTUNNEG: { LLVMValueRef v; idx_t ni = codegentypedexpr(ctx, ctx.ast.kids[i].rhs, ctx.types[i], &v); - *outv = LLVMBuildNeg(ctx.bob, v, "negtmp"); + *outv = LLVMBuildNeg(ctx.bob, v, "neg"); return ni; } case ASTBINADD: case ASTBINDIV: case ASTBINMOD: case ASTBINMUL: + case ASTBINSHL: + case ASTBINSHR: case ASTBINSUB: case ASTBINXOR: { typedef LLVMValueRef llbfn(LLVMBuilderRef, LLVMValueRef, LLVMValueRef, @@ -256,19 +228,26 @@ codegentypedexpr(struct cgctx ctx, idx_t i, type_t type, LLVMValueRef *outv) static const struct binop { llbfn *fn[2]; const char *name; - } binoptbl[UINT8_MAX] = { - ['+'] = {{LLVMBuildAdd, LLVMBuildAdd}, "addtmp"}, - ['*'] = {{LLVMBuildMul, LLVMBuildMul}, "multmp"}, - ['-'] = {{LLVMBuildSub, LLVMBuildSub}, "subtmp"}, - ['/'] = {{LLVMBuildUDiv, LLVMBuildSDiv}, "divtmp"}, - ['%'] = {{LLVMBuildURem, LLVMBuildSRem}, "remtmp"}, - ['~'] = {{LLVMBuildXor, LLVMBuildXor}, "xortmp"}, + } binoptbl[UINT8_MAX + 1] = { + ['+'] = {{LLVMBuildAdd, LLVMBuildAdd}, "add"}, + ['*'] = {{LLVMBuildMul, LLVMBuildMul}, "mul"}, + ['-'] = {{LLVMBuildSub, LLVMBuildSub}, "sub"}, + ['/'] = {{LLVMBuildUDiv, LLVMBuildSDiv}, "div"}, + ['%'] = {{LLVMBuildURem, LLVMBuildSRem}, "rem"}, + ['~'] = {{LLVMBuildXor, LLVMBuildXor}, "xor"}, + [ASTBINSHL] = {{LLVMBuildShl, LLVMBuildShl}, "shl"}, + [ASTBINSHR] = {{LLVMBuildLShr, LLVMBuildLShr}, "shr"}, }; + idx_t lhs = ctx.ast.kids[i].lhs, rhs = ctx.ast.kids[i].rhs; LLVMValueRef vl, vr; - (void)codegentypedexpr(ctx, ctx.ast.kids[i].lhs, ctx.types[i], &vl); - idx_t ni = codegentypedexpr(ctx, ctx.ast.kids[i].rhs, ctx.types[i], - &vr); + (void)codegentypedexpr(ctx, lhs, ctx.types[i], &vl); + idx_t ni = codegentypedexpr(ctx, rhs, ctx.types[i], &vr); + + if (ctx.ast.kinds[i] >= ASTBINSHL && ctx.types[rhs].size != 0) { + vr = LLVMBuildIntCast2(ctx.bob, vr, type2llvm(ctx, ctx.types[lhs]), + false, "cast"); + } struct binop bo = binoptbl[ctx.ast.kinds[i]]; *outv = bo.fn[ctx.types[i].issigned](ctx.bob, vl, vr, bo.name); |