diff options
| author | 2025-11-23 21:54:40 +0100 | |
|---|---|---|
| committer | 2025-11-23 21:57:01 +0100 | |
| commit | 6464ec389e2da17b1674858858406e211b16e5f6 (patch) | |
| tree | 1b82b733851b88a0868635c6ab5afe1ea2298b7c | |
| parent | d79251d487b57ea0e3b10640747eed723a06365c (diff) | |
ir: implement cvtu64f. and other bug fixes
compiler is bootstrapping?! however, stage1 and stage2+ executables
aren't bit-identical.. small differences in the codegen.. need to look into that
| -rw-r--r-- | Makefile | 12 | ||||
| -rw-r--r-- | c/c.c | 5 | ||||
| -rw-r--r-- | ir/builder.c | 37 | ||||
| -rw-r--r-- | test/flt.c | 4 | ||||
| -rw-r--r-- | todo.txt | 4 |
5 files changed, 50 insertions, 12 deletions
@@ -5,7 +5,8 @@ SRC=main.c io.c mem.c c/c.c c/lex.c c/eval.c c/builtin.c type.c targ.c \ CFLAGS=-Wall -std=c11 -pedantic OBJ=$(patsubst %.c,build/%.o,$(SRC)) DEP=$(OBJ:.o=.d) -OUT=antcc +BUILDDIR?=build +OUT?=antcc all: CFLAGS += -g all: $(OUT) @@ -13,18 +14,19 @@ all: $(OUT) opt: CFLAGS += -g -O2 opt: $(OUT) -dbg: CFLAGS += -g -fsanitize=address -fsanitize=undefined +dbg: CFLAGS += -g -fsanitize=address,undefined +dbg: CC:=clang dbg: $(OUT) $(OUT): $(OBJ) $(CC) $(CFLAGS) -o $@ $(OBJ) -build/%.o: %.c common.h +$(BUILDDIR)/%.o: %.c common.h @mkdir -p `dirname $@` - $(CC) $(CFLAGS) -MMD -MP -MT $@ -MF build/$*.d -c -o $@ $< + $(CC) $(CFLAGS) -MMD -MP -MT $@ -MF $(BUILDDIR)/$*.d -c -o $@ $< clean: - $(RM) -r build/ test/build/ $(OUT) *.o a.out + $(RM) -r $(BUILDDIR)/ test/build/ $(OUT) *.o a.out .PHONY: clean @@ -3051,11 +3051,14 @@ condexprrec(struct function *fn, const struct expr *ex, struct condphis *phis, condexprrec(fn, &ex->sub[2], phis, phityp, -1, end, end); } else { union ref r, val; + union type valty; if (!phis && (!next || next == end)) { expreffects(fn, ex); } else { val = r = exprvalue(fn, ex); + valty = ex->ty; if (boolcon >= 0) { + valty = mktype(TYBOOL); if (!next || next == end) { boolcon = -1; val = cvt(fn, mktype(TYBOOL), ex->ty, r); @@ -3066,7 +3069,7 @@ condexprrec(struct function *fn, const struct expr *ex, struct condphis *phis, } if (phis) { if (isscalar(phityp)) - val = cvt(fn, phityp, ex->ty, val); + val = cvt(fn, phityp, valty, val); else assert(ex->ty.bits == phityp.bits); vpush(&phis->ref, val); } diff --git a/ir/builder.c b/ir/builder.c index 752c1bc..c793f80 100644 --- a/ir/builder.c +++ b/ir/builder.c @@ -20,6 +20,7 @@ irbinop(struct function *fn, enum op op, enum irclass k, union ref l, union ref break; case Omul: if (isnumcon(l)) rswap(l, r); /* put const in rhs */ + if (kisflt(k)) break; if (r.bits == ZEROREF.bits) /* x * 0 ==> 0 */ return ZEROREF; if (r.bits == ONE.bits) /* x * 1 ==> x */ @@ -33,6 +34,7 @@ irbinop(struct function *fn, enum op op, enum irclass k, union ref l, union ref case Odiv: break; case Oudiv: + if (kisflt(k)) break; if (isintcon(r) && ispo2(iv = intconval(r))) { /* x / 2^y ==> x >> y */ op = Oslr; @@ -42,6 +44,7 @@ irbinop(struct function *fn, enum op op, enum irclass k, union ref l, union ref case Orem: break; case Ourem: + if (kisflt(k)) break; if (isintcon(r) && ispo2(iv = intconval(r))) { /* x % 2^y ==> x & 2^y-1 */ op = Oand; @@ -123,6 +126,33 @@ cvtfu64(struct function *fn, enum irclass from, union ref x) return addphi(fn, KI64, phiarg); } +/* implements u64 -> f32/f64 conversion */ +static union ref +cvtu64f(struct function *fn, enum irclass to, union ref x) +{ + struct block *t, *f, *merge; + union ref t1, t2, phiarg[2]; + + /* if ((s64)x >= 0) cvts64f(x) else cvts64f((x>>1)|(x&1))*2 */ + + putcondbranch(fn, irbinop(fn, Ogte, KI64, x, ZEROREF), t = newblk(fn), f = newblk(fn)); + + useblk(fn, t); + phiarg[0] = irunop(fn, Ocvts64f, to, x); + putbranch(fn, merge = newblk(fn)); + + useblk(fn, f); + t1 = irbinop(fn, Oslr, KI64, x, mkref(RICON, 1)); + t2 = irbinop(fn, Oand, KI64, x, mkref(RICON, 1)); + t1 = irbinop(fn, Oior, KI64, t1, t2); + t1 = irunop(fn, Ocvts64f, to, t1); + phiarg[1] = irbinop(fn, Oadd, to, t1, t1); + putbranch(fn, merge); + + useblk(fn, merge); + return addphi(fn, to, phiarg); +} + union ref irunop(struct function *fn, enum op op, enum irclass k, union ref a) { @@ -141,6 +171,8 @@ irunop(struct function *fn, enum op op, enum irclass k, union ref a) return ins->l; break; case Ocvtf32s: case Ocvtf32f64: case Ocvtf64s: + case Ocvtf64f32: case Ocvts32f: case Ocvtu32f: + case Ocvts64f: break; case Ocvtf32u: case Ocvtf64u: if (k == KI64) { @@ -150,8 +182,9 @@ irunop(struct function *fn, enum op op, enum irclass k, union ref a) return cvtfu64(fn, op == Ocvtf32u ? KF32 : KF64, a); } break; - case Ocvtf64f32: case Ocvts32f: case Ocvtu32f: - case Ocvts64f: case Ocvtu64f: + case Ocvtu64f: + /* XXX see above */ + return cvtu64f(fn, k, a); case Oexts8: case Oextu8: case Oexts16: case Oextu16: case Oexts32: case Oextu32: case Ocopy: @@ -10,9 +10,9 @@ f32 u32_to_f32(u32 x) { return x; } f64 s32_to_f64(s32 x) { return x; } f64 u32_to_f64(u32 x) { return x; } f32 s64_to_f32(s64 x) { return x; } -//f32 u64_to_f32(u64 x) { return x; } +f32 u64_to_f32(u64 x) { return x; } f64 s64_to_f64(s64 x) { return x; } -//f64 u64_to_f64(u64 x) { return x; } +f64 u64_to_f64(u64 x) { return x; } s32 f32_to_s32(f32 x) { return x; } u32 f32_to_u32(f32 x) { return x; } s32 f64_to_s32(f64 x) { return x; } @@ -1,6 +1,6 @@ Things to finish before moving onto compiler optimizations, C extensions, other nice features -- self host. not yet compiling: - - c/eval.c, ir/fold.c (NYI flt -> u64 cvt) +- self host -- working?? test thoroughly +- fix preprocessor regressions though - e.g. <math.h> at some point add another backend like arm64 to make sure the non target specific stuff is generic enough.. |