aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorlemon <lsof@mailbox.org>2022-08-31 11:23:14 +0200
committerlemon <lsof@mailbox.org>2022-08-31 11:23:14 +0200
commitaf617f24c5f2f2cab357ace9d822c6948c7e487f (patch)
tree196657ff59552219e7928b7bba300ee2c540b354 /src
parentf1d4407044b5cd5eaabf0a53d1d7cb5d8b270ea6 (diff)
get close to self hosting (ack works)
Diffstat (limited to 'src')
-rw-r--r--src/cffc.hff8
-rw-r--r--src/llvm.cff76
-rw-r--r--src/parse.cff19
3 files changed, 64 insertions, 39 deletions
diff --git a/src/cffc.hff b/src/cffc.hff
index 4d57d3d..d6de469 100644
--- a/src/cffc.hff
+++ b/src/cffc.hff
@@ -467,10 +467,12 @@ fn mkarrtype(len i64, konst bool, child *const Type) *const Type {
});
}
fn mkptrtype(child *const Type) *const Type {
- return interntype(&Type {
+ let tmp typeof((Type{}).u) = :Ptr(child);
+ let ty = Type {
g_targ.ptrsize,
- .u: :Ptr(child)
- });
+ .u: tmp
+ };
+ return interntype(&ty);
}
extern fn mkslicetype(child *const Type) *const Type;
diff --git a/src/llvm.cff b/src/llvm.cff
index bb6af3f..b0b1027 100644
--- a/src/llvm.cff
+++ b/src/llvm.cff
@@ -23,7 +23,8 @@ struct Value {
}
}
-fn gen(fmt *const u8, ...) void;
+// XXX if gen isn't extern llvm hates it and wooshes it away ?
+extern fn gen(fmt *const u8, ...) void;
extern fn genagg(ty *const Type) void {
let agg = &ty.u.Agg;
if agg.fwd {
@@ -42,29 +43,39 @@ extern fn genagg(ty *const Type) void {
} else if agg.kind == :Union {
let size = ty.size;
let ty *const Type = #null;
- foreach (fld, i, agg.flds) {
- if ty == #null or fld.ty.align > ty.align {
- ty = fld.ty;
+ do {
+ foreach (fld, i, agg.flds) {
+ if ty == #null or fld.ty.align > ty.align or fld.ty.size > ty.size {
+ ty = fld.ty;
+ }
}
+ } while ty->is(:Agg) and ty.u.Agg.kind != :Struct;
+ if ty->is(:Agg) {
+ // struct
+ gen("{ i%z, [%z x i8] }", ty.align * 8, size - ty.align);
+ } else {
+ gen("{ %t, [%z x i8] }", ty, size - ty.size);
}
- gen("{ %t ", ty);
- if ty.size < size {
- gen(", [%z x i8] ", size - ty.size);
- }
- gen("}");
} else if agg.kind == :EUnion {
- gen("{ %t, ", agg.enumty);
let size = ty.size;
+ gen("{ %t, [%z x i8],", agg.enumty, ty.align - agg.enumty.size);
let ty *const Type = #null;
let off isize #?;
- foreach (fld, i, agg.flds) {
- if ty == #null or (fld.ty != #null and fld.ty.align > ty.align) {
- ty = fld.ty;
- off = fld.off;
+ do {
+ foreach (fld, i, agg.flds) {
+ if ty == #null or (fld.ty != #null and (fld.ty.align > ty.align or fld.ty.size > ty.size)) {
+ ty = fld.ty;
+ off = fld.off;
+ }
}
- }
+ } while ty->is(:Agg) and ty.u.Agg.kind != :Struct;
ty = ty ?? ty_void;
- gen(" %t, [%z x i8] }", ty, size - ty.size - off);
+ if ty->is(:Agg) {
+ // struct
+ gen(" i%z, [%z x i8] }", ty.align * 8, size - off - ty.align);
+ } else {
+ gen(" %t, [%z x i8] }", ty, size - ty.size - off);
+ }
}
}
@@ -77,7 +88,7 @@ extern fn llvm_addtype(ty *const Type) void {
}
fn gendata(ty *const Type, ex *Expr) void;
-fn gen(fmt *const u8, ...) void {
+extern fn gen(fmt *const u8, ...) void {
let ap va_list #?;
ap->start(fmt);
@@ -297,9 +308,9 @@ fn genref(f *Fn, ex *Expr) Ref {
lhs.ty.u.Ptr, lhs.ty, &lhs, idx);
case :Union;
addr = gentmp(ptrty, "bitcast %t %v to %t", lhs.ty, &lhs, ptrty);
- case else
+ case :EUnion;
let off int = dot.fld.off;
- addr = gentmp(ptrty, "getelementptr i8, %t %v, i32 %d", lhs.ty, &lhs, off);
+ addr = gentmp(ptrty, "getelementptr i8, ptr %v, i32 %d", &lhs, off);
}
return :Addr(addr);
@@ -326,9 +337,10 @@ fn genref(f *Fn, ex *Expr) Ref {
gen("\t%v = getelementptr %t, %t %v, i32 0, i32 %d\n", &ptr, ex.ty, tmp.ty, &tmp, idx);
case :Union;
gen("\t%v = bitcast %t %v to %t\n", &ptr, tmp.ty, &tmp, ptr.ty);
+ case else assert(#f, "?");
}
let it = convert(f, fld.ty, fex);
- gen("\tstore %t %v, %t %v\n", fld.ty, &it, ptr.ty, &ptr);
+ gen("\tstore %t %v, ptr %v\n", fld.ty, &it, &ptr);
}
return :Addr(tmp);
@@ -444,6 +456,12 @@ fn convert(f *Fn, to *const Type, ex *Expr) Value {
case to->is(:Flo) and from->is(:Int);
return cvt(from.u.Int.sgn ? "sitofp" : "uitofp");
+
+ case to->is(:Ptr) and from->is(:Int);
+ return cvt("inttoptr");
+
+ case to->is(:Int) and from->is(:Ptr);
+ return cvt("ptrtoint");
case to->is(:Int) and from->is(:Flo) and to.size < ty_int.size;
let t0 = mktmp(ty_int);
@@ -958,15 +976,12 @@ fn genexpr(f *Fn, ex *Expr) Value {
let t0 = mktmp(mkptrtype(ex.ty));
let vidx = ini.var - ex.ty.u.Agg.flds.#ptr;
gen("\t%v = alloca %t\n", &t0, ex.ty);
- gen("\tstore %t zeroinitializer, %t %v\n", ex.ty, t0.ty, &t0);
- gen("\tstore %t %d, %t %v\n", ex.ty.u.Agg.enumty.u.Enum.intty, vidx, t0.ty, &t0);
+ gen("\tstore %t zeroinitializer, ptr %v\n", ex.ty, &t0);
+ gen("\tstore %t %d, ptr %v\n", ex.ty.u.Agg.enumty, vidx, &t0);
if ini.var.ty != #null {
let tini = convert(f, ini.var.ty, ini.ex);
- let t1 = mktmp(mkptrtype(ini.var.ty));
- gen("\t%v = bitcast %t %v to %t\n", &t1, t0.ty, &t0, t1.ty);
- let t2 = mktmp(t1.ty);
- gen("\t%v = getelementptr %t, %t %v, i32 1\n", &t2, ini.var.ty, t1.ty, &t1);
- gen("\tstore %t %v, %t %v\n", tini.ty, &tini, t2.ty, &t2);
+ let t2 = gentmp(t0.ty, "getelementptr i8, ptr %v, i32 %z", &t0, ini.var.off);
+ gen("\tstore %t %v, ptr %v\n", tini.ty, &tini, &t2);
}
let res = mktmp(ex.ty);
gen("\t%v = load %t, %t %v\n", &res, res.ty, t0.ty, &t0);
@@ -975,7 +990,6 @@ fn genexpr(f *Fn, ex *Expr) Value {
case VaStart ap;
let ap = genref(f, ap).Addr;
gen("\tcall void @llvm.va_start(ptr %v)\n", &ap);
- return nop();
case VaArg ap;
let ap = genref(f, ap).Addr;
@@ -984,7 +998,6 @@ fn genexpr(f *Fn, ex *Expr) Value {
case VaEnd ap;
let ap = genref(f, ap).Addr;
gen("\tcall void @llvm.va_end(ptr %v)\n", &ap);
- return nop();
case Stmt block;
switch genblock(f, block) {
@@ -1151,7 +1164,7 @@ fn genstmt(f *Fn, block *Block, st *Stmt) void {
exaddr = genref(f, &sw.ex).Addr;
} else {
exaddr = mktmp(mkptrtype(sw.ex.ty));
- gen("\t%v = alloca %t\n", &exaddr, exaddr.ty);
+ gen("\t%v = alloca %t\n", &exaddr, sw.ex.ty);
let test = genexpr(f, &sw.ex);
gen("\tstore %t %v, %t %v\n", test.ty, &test, exaddr.ty, &exaddr);
}
@@ -1173,8 +1186,7 @@ fn genstmt(f *Fn, block *Block, st *Stmt) void {
if c.capt {
gen("\t%%%s.%d = alloca %t\n", c.capt, c.captid, c.captty);
let valaddr = mktmp(mkptrtype(c.fld.ty));
- gen("\t%v = getelementptr i8, %t %v, i32 %d\n", &valaddr, exaddr.ty, &exaddr,
- as(int)c.fld.off);
+ gen("\t%v = getelementptr i8, ptr %v, i32 %z\n", &valaddr, &exaddr, c.fld.off);
if c.captptr {
gen("\tstore %t %v, %t %%%s.%d\n", valaddr.ty, &valaddr, mkptrtype(c.captty), c.capt, c.captid);
} else {
diff --git a/src/parse.cff b/src/parse.cff
index bd5262e..7249390 100644
--- a/src/parse.cff
+++ b/src/parse.cff
@@ -561,7 +561,8 @@ fn lex(P *Parser) Tok {
fn lexpeek(P *Parser) Tok {
switch P.peektok {
- case Some t; return t;
+ case Some t;
+ return t;
}
let tok = lex(P);
P.peektok = :Some(tok);
@@ -2763,6 +2764,8 @@ fn parsevardecl(P *Parser, toplevel bool, externp bool, letp bool, yield DeclYie
} while !lexmatch(P, &tok, ';');
}
+ extern fn BREAK() void {}
+
fn parsefn(P *Parser, loc Loc, toplevel bool, externp bool, name *const u8) *Decl {
let decl Decl = {
name,
@@ -2784,6 +2787,11 @@ fn parsefn(P *Parser, loc Loc, toplevel bool, externp bool, name *const u8) *Dec
static id int = 0;
Fn.id = ++id;
// TODO tlalloc necessary for templates. but it leaks some memory
+ let d Decl #?;
+ extern fn memset(*void, int, usize) *void;
+ memset(&d, 0, sizeof(d));
+ d = decl;
+
let decl = putdecl_alloc(P, P.tlalloc, loc, decl);
let Fn = &decl.u.Fn;
decl.toplevel = toplevel;
@@ -3040,6 +3048,12 @@ fn parsedecls(P *Parser, loc Loc, yield DeclYielder, yarg *void, toplevel bool)
externp = #f,
name *const u8 = #null;
+
+ if lexmatch(P, &tok, ';') or lexmatch(P, &tok, :eof) {
+ // no-op
+ return;
+ }
+
let attr u32 = 0;
if lexmatch(P, &tok, '#') {
lexexpect(P, '[');
@@ -3062,9 +3076,6 @@ fn parsedecls(P *Parser, loc Loc, yield DeclYielder, yarg *void, toplevel bool)
switch {
- case lexmatch(P, &tok, ';') or lexmatch(P, &tok, :eof);
- // no-op
-
case lexmatch(P, &tok, :kw_fn);
let name = lexmatch(P, &tok, :ident) ? tok.u.ident : #null;
decl = parsefn(P, tok.loc, toplevel, externp, name);