aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorlemon <lsof@mailbox.org>2025-11-23 21:54:40 +0100
committerlemon <lsof@mailbox.org>2025-11-23 21:57:01 +0100
commit6464ec389e2da17b1674858858406e211b16e5f6 (patch)
tree1b82b733851b88a0868635c6ab5afe1ea2298b7c
parentd79251d487b57ea0e3b10640747eed723a06365c (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--Makefile12
-rw-r--r--c/c.c5
-rw-r--r--ir/builder.c37
-rw-r--r--test/flt.c4
-rw-r--r--todo.txt4
5 files changed, 50 insertions, 12 deletions
diff --git a/Makefile b/Makefile
index be28de4..eb69747 100644
--- a/Makefile
+++ b/Makefile
@@ -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
diff --git a/c/c.c b/c/c.c
index d609cd0..6d1996a 100644
--- a/c/c.c
+++ b/c/c.c
@@ -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:
diff --git a/test/flt.c b/test/flt.c
index 2ae773d..04ce3e3 100644
--- a/test/flt.c
+++ b/test/flt.c
@@ -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; }
diff --git a/todo.txt b/todo.txt
index 3c747de..a03ee11 100644
--- a/todo.txt
+++ b/todo.txt
@@ -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..