diff options
| author | 2022-08-29 21:57:58 +0200 | |
|---|---|---|
| committer | 2022-08-29 21:57:58 +0200 | |
| commit | 2f243de6ce9402f880677a07b832c0e56a7f688d (patch) | |
| tree | 7f2844b121f52b0acbb5e03d2bdc83c51c187abc /src/llvm.cff | |
| parent | e0385225b5a4a0d7b391d3d71c19228efe06ed04 (diff) | |
many things ,varags
Diffstat (limited to 'src/llvm.cff')
| -rw-r--r-- | src/llvm.cff | 164 |
1 files changed, 121 insertions, 43 deletions
diff --git a/src/llvm.cff b/src/llvm.cff index eb13919..1a7f24a 100644 --- a/src/llvm.cff +++ b/src/llvm.cff @@ -23,7 +23,7 @@ struct Value { } } -static ty_i1 *Type = as(*void)&outfp; // dummy +static ty_i1 Type = {}; // dummy fn gen(fmt *const u8, ...) void; extern fn genagg(ty *const Type) void { @@ -87,7 +87,7 @@ fn gen(fmt *const u8, ...) void { ap->start(fmt); fn pritype(ty *const Type) void { - if ty == ty_i1 { + if ty == &ty_i1 { gen("i1"); return; } @@ -121,7 +121,8 @@ fn gen(fmt *const u8, ...) void { } } gen(") "); - case VaList; gen("%s", g_targ.valistllvmty); + case VaList; gen("%%.type.valist"); + case else assert(#f, "type?"); } } @@ -142,7 +143,7 @@ fn gen(fmt *const u8, ...) void { fputc('"', outfp); foreach(c, _, str) { extern fn isprint(int) int; - if isprint(c) == 0 { + if isprint(c) == 0 or c == '"' or c == '\\' { fprintf(outfp, "\\%.2X", c); } else { fputc(c, outfp); @@ -344,6 +345,12 @@ fn genref(f *Fn, ex *Expr) Ref { gen("\tstore %t %v, %t %v\n", fex.ty, convert(f, ty.u.Arr.child, fex), ptr.ty, ptr); } return :Addr(tmp); + + case else + let it = genexpr(f, ex); + let tmp = gentmp(mkptrtype(ex.ty), "alloca %t", ex.ty); + gen("store %t %v, %t %v", it.ty, it, tmp.ty, tmp); + return :Addr(tmp); } assert(#f, "genref %d", ex.u.#tag); } @@ -362,7 +369,7 @@ fn genload(f *Fn, ref Ref) Value { let res = mktmp(fld.ty); switch { case dot.fld.ty->is(:Bool); - let tmp = gentmp(ty_i1, "icmp ne i%d %v, 0", fld.size, truncd); + let tmp = gentmp(&ty_i1, "icmp ne i%d %v, 0", fld.size, truncd); gen("\t%v = zext i1 %v to %t\n", res, tmp, res.ty); case dot.fld.ty->is(:Int); gen("\t%v = %s i%d %v to %t\n", res, @@ -402,21 +409,18 @@ fn convert(f *Fn, to *const Type, ex *Expr) Value { if from->is(:Enum) { from = from.u.Enum.intty; } defmacro cvt(inst) [ - (do let t = mktmp(to), + (do let $t = mktmp(to), val = genexpr(f, ex); - gen("\t%v = %s %t %v to %t\n", t, inst, from, val, to); - t; + gen("\t%v = %s %t %v to %t\n", $t, inst, from, val, to); + $t; ) ] switch { case from == to; return genexpr(f, ex); - case to->is(:Int) and from->is(:Int) and to.size == from.size and to.u.Int.sgn != from.u.Int.sgn; - return genexpr(f, ex); - case to->is(:Int) and from->is(:Int) and to.size == from.size; - return cvt("bitcast"); + return genexpr(f, ex); case to->is(:Int) and from->is(:Int) and to.size < from.size; return cvt("trunc"); @@ -454,25 +458,24 @@ fn convert(f *Fn, to *const Type, ex *Expr) Value { return cvt(to.u.Int.sgn ? "fptosi" : "fptoui"); case to->is(:Int) and from->is(:Bool); - let t0 = mktmp(ty_i1); + let t0 = mktmp(&ty_i1); gen("\t%v = icmp ne %t %v, 0\n", t0, ex.ty, genexpr(f, ex)); let t1 = mktmp(to); gen("\t%v = zext %t %v to %t\n", t1, t0.ty, t0, t1.ty); return t1; case to->is(:Bool) and from->is(:Int); - let t0 = mktmp(ty_i1); + let t0 = mktmp(&ty_i1); gen("\t%v = icmp ne %t %v, 0\n", t0, ex.ty, genexpr(f, ex)); let t1 = mktmp(to); gen("\t%v = zext %t %v to %t\n", t1, t0.ty, t0, t1.ty); return t1; - case to->is(:Ptr) and from->is(:Ptr); - let t = mktmp(to), - val = genexpr(f, ex); - gen("\t%v = bitcast %t %v to %t\n", t, from, val, to); - return t; + return genexpr(f, ex); + + case to->is(:Slice) and from->is(:Slice); + return genexpr(f, ex); case to->is(:Ptr) and from->is(:Arr); let addr = genref(f, ex).Addr; @@ -483,11 +486,9 @@ fn convert(f *Fn, to *const Type, ex *Expr) Value { case to->is(:Arr) and from->is(:Arr); return genexpr(f, ex); - - case else - efmt("%t %t\n",from,to); - assert(#f, "convert"); } + efmt("%t %t\n",from,to); + assert(#f, "convert"); } fn genblock(f *Fn, block Block) Option<Value>; @@ -537,8 +538,12 @@ fn genexpr(f *Fn, ex *Expr) Value { $t, lhs.ty.u.Ptr, lhs.ty, lhs, rhs.ty, rhs); res = $t; } else if rhs.ty->is(:Ptr) { + let $t = mktmp(type); + gen("\t%v = getelementptr %t, %t %v, %t %v\n", + $t, rhs.ty.u.Ptr, rhs.ty, rhs, rhs.ty, lhs); + res = $t; } else { - assert(#f, "bad sub"); + assert(#f, "bad ad"); } res; ) @@ -546,7 +551,7 @@ fn genexpr(f *Fn, ex *Expr) Value { defmacro gensub(type, lhs, rhs) [ (do let res Value #?; - if isnumtype(type) { + if isnumtype(type) and !lhs.ty->is(:Ptr) { let $t = mktmp(type); gen("\t%v = %s %t %v, %v\n", $t, ex.ty->is(:Flo) ? "fsub" : "sub", ex.ty, lhs, rhs); res = $t; @@ -555,10 +560,16 @@ fn genexpr(f *Fn, ex *Expr) Value { gen("\t%v = sub %t 0, %v\n", $off, rhs.ty, rhs); let $t = mktmp(type); gen("\t%v = getelementptr %t, %t %v, %t %v\n", - $t, lhs.ty.u.Ptr, lhs.ty, lhs, $off.ty, $off); + $t, lhs.ty.u.Ptr == ty_void ? ty_i8 : lhs.ty.u.Ptr, lhs.ty, lhs, $off.ty, $off); res = $t; + } else if lhs.ty->is(:Ptr) and rhs.ty->is(:Ptr) { + let $l = gentmp(ty_isize, "ptrtoint ptr %v to %t", lhs, ty_isize); + let $r = gentmp(ty_isize, "ptrtoint ptr %v to %t", rhs, ty_isize); + let $diff = gentmp(ty_isize, "sub %t %v, %v", ty_isize, $l, $r); + let $res = gentmp(ty_isize, "sdiv %t %v, %v", ty_isize, $l, $r); + return $res; } else { - assert(#f, "bad add"); + assert(#f, "bad sub"); } res; ) @@ -637,7 +648,7 @@ fn genexpr(f *Fn, ex *Expr) Value { static orid int = {}; let id = orid++; let lhs = genexpr(f, b.lhs); - let cnd = mktmp(ty_i1); + let cnd = mktmp(&ty_i1); let tmpvar = mktmp(mkptrtype(ex.ty)); let res = mktmp(ex.ty); gen("\t%v = alloca %t\n", tmpvar, ex.ty); @@ -656,7 +667,7 @@ fn genexpr(f *Fn, ex *Expr) Value { static andid int = {}; let id = andid++; let lhs = genexpr(f, b.lhs); - let cnd = mktmp(ty_i1); + let cnd = mktmp(&ty_i1); let tmpvar = mktmp(mkptrtype(ex.ty)); let res = mktmp(ex.ty); gen("\t%v = alloca %t\n", tmpvar, ex.ty); @@ -670,6 +681,25 @@ fn genexpr(f *Fn, ex *Expr) Value { gen("AndF%d: ", id); gen("\t%v = load %t, %t %v\n", res, ex.ty, tmpvar.ty, tmpvar); return res; + + case '??'; + static orid int = {}; + let id = orid++; + let lhs = genexpr(f, b.lhs); + let cnd = mktmp(&ty_i1); + let tmpvar = mktmp(mkptrtype(ex.ty)); + let res = mktmp(ex.ty); + gen("\t%v = alloca %t\n", tmpvar, ex.ty); + gen("\tstore %t %v, %t %v\n", ex.ty, lhs, tmpvar.ty, tmpvar); + gen("\t%v = icmp ne %t %v, null\n", cnd, lhs.ty, lhs); + gen("\tbr i1 %v, label %%OrT%d, label %%OrF%d\n", cnd, id, id); + gen("OrF%d: ", id); + let rhs = genexpr(f, b.rhs); + gen("\tstore %t %v, %t %v\n", ex.ty, rhs, tmpvar.ty, tmpvar); + gen("\tbr label %%OrT%d\n", cnd, id, id); + gen("OrT%d: ", id); + gen("\t%v = load %t, %t %v\n", res, ex.ty, tmpvar.ty, tmpvar); + return res; case else assert(#f, "binop? %c", b.op); @@ -678,7 +708,7 @@ fn genexpr(f *Fn, ex *Expr) Value { static condid int = {}; let id = condid++; let lhs = genexpr(f, cond.test); - let cnd = mktmp(ty_i1); + let cnd = mktmp(&ty_i1); let tmpvar = mktmp(mkptrtype(ex.ty)); let res = mktmp(ex.ty); gen("\t%v = alloca %t\n", tmpvar, ex.ty); @@ -713,7 +743,7 @@ fn genexpr(f *Fn, ex *Expr) Value { return tmp; case :not; - let tmp = mktmp(ty_i1); + let tmp = mktmp(&ty_i1); gen("\t%v = xor i1 1, %v\n", tmp, ex.ty, llvmbool(f, un.ex)); let res = mktmp(ex.ty); gen("\t%v = zext i1 %v to %t\n", res, tmp, res.ty); @@ -863,13 +893,12 @@ fn genexpr(f *Fn, ex *Expr) Value { let ty = i < fnty.params.#len ? fnty.params[i] : varargpromote(arg.ty); args[i] = convert(f, ty, arg); } - let t Value #?; + let t Value = mktmp(ex.ty); if fnty.ret->is(:Void) { - t = {ty_void}; - gen("\tcall %t %v(", call.lhs.ty, lhs); + gen("\tcall void %v(", lhs); } else { t = mktmp(ex.ty); - gen("\t%v = call %t %v(", t, call.lhs.ty, lhs); + gen("\t%v = call %t %v(", t, call.lhs.ty->is(:Ptr) ? call.lhs.ty.u.Ptr : call.lhs.ty, lhs); } foreach_ptr(arg, i, call.args) { let ty = i < fnty.params.#len ? fnty.params[i] : varargpromote(arg.ty); @@ -910,6 +939,17 @@ fn genexpr(f *Fn, ex *Expr) Value { gen("\t%v = load %t, %t %v\n", res, res.ty, t0.ty, t0); return res; + case VaStart ap; + gen("\tcall void @llvm.va_start(ptr %v)\n", genref(f, ap).Addr); + return mktmp(ty_void); + + case VaArg ap; + return gentmp(ex.ty, "va_arg ptr %v, %t", genref(f, ap).Addr, ex.ty); + + case VaEnd ap; + gen("\tcall void @llvm.va_end(ptr %v)\n", genref(f, ap).Addr); + return mktmp(ty_void); + case Stmt block; switch genblock(f, block) { case Some val; return val; @@ -923,7 +963,7 @@ fn genexpr(f *Fn, ex *Expr) Value { fn llvmbool(f *Fn, ex *Expr) Value { let v = genexpr(f, ex); - let t = mktmp(ty_i1); + let t = mktmp(&ty_i1); if v.ty->is(:Bool) or v.ty->is(:Int) { gen("\t%v = icmp ne %t %v, 0\n", t, v.ty, v); } else { @@ -951,9 +991,10 @@ fn genstmt(f *Fn, block *Block, st *Stmt) void { let nam = decl.name, ty = var.ty; gen("\t%%%s.%d = alloca %t\n", nam, var.id, ty); - if !var.ini->empty() { + switch var.ini { + case Some *ex; gen("\tstore %t %v, %t %%%s.%d\n", - ty, convert(f, ty, &var.ini.Some), mkptrtype(ty), nam, var.id); + ty, convert(f, ty, ex), mkptrtype(ty), nam, var.id); } } case If *cnd; @@ -1234,9 +1275,9 @@ extern fn llvm_genfn(externp bool, name *const u8, f *Fn) void { gen("}\n"); } -struct I64Traits { - fn hash(x i64) u32 { return x ^ 7; } - fn eq(a i64, b i64) bool { return a == b; } +struct IntTraits<T> { + fn hash(x T) u32 { return x ^ 7; } + fn eq(a T, b T) bool { return a == b; } } fn gendata(ty *const Type, ex *Expr) void { @@ -1249,6 +1290,10 @@ fn gendata(ty *const Type, ex *Expr) void { if !decl.externp { gen("@%s.%d", decl.name, f.id); } else { gen("@%s", decl.name); } return; + case Static v; + if !decl.externp { gen("@%s.%d", decl.name, v.id); + } else { gen("@%s", decl.name); } + return; } } assert(#f, "bad static addr"); @@ -1276,7 +1321,7 @@ fn gendata(ty *const Type, ex *Expr) void { case ArrIni ini; assert(ty->is(:Arr), "not arr arr ini"); - let map Map<i64, *Expr, I64Traits> = {}; + let map Map<i64, *Expr, IntTraits<i64>,> = {}; defer map->clear(); foreach (idx, i, ini.idxs) { map->put(idx, &ini.exs[i]); @@ -1295,7 +1340,36 @@ fn gendata(ty *const Type, ex *Expr) void { } } gen(" ]"); - return; + return; + + case AggIni ini; + assert(ty->is(:Agg), "not agg agg ini"); + + let map Map<u16, *Expr, IntTraits<u16>,> = {}; + defer map->clear(); + if ty.u.Agg.kind == :Struct { + foreach (fld, i, ini.flds) { + let idx = fld - ty.u.Agg.flds.#ptr; + map->put(idx, &ini.exs[i]); + } + gen("{ "); + for let i = 0z; i < ty.u.Agg.flds.#len; ++i { + gen("%t ", ty.u.Agg.flds[i].ty); + let ex **Expr = map->get(i); + if ex { + gendata(ty.u.Agg.flds[i].ty, *ex); + } else { + gen("zeroinitializer"); + } + if i < ty.u.Agg.flds.#len - 1 { + gen(", "); + } + } + gen(" }"); + } else { + assert(#f, "NYI static"); + } + return; } assert(#f, "bad static %d", ex.u.#tag); } @@ -1312,6 +1386,9 @@ extern fn llvm_genstatic(externp bool, name *const u8, var *Var) void { } extern fn llvm_fini() void { + gen("declare void @llvm.va_start(ptr)\n"); + gen("declare void @llvm.va_copy(ptr, ptr)\n"); + gen("declare void @llvm.va_end(ptr)\n"); vec_each(s, i, strs) { gen("@.str.%z = private unnamed_addr constant [%z x i8] c%S;\n", i, s.#len + 1, s); } @@ -1356,5 +1433,6 @@ extern fn llvm_init(out *FILE) void { outfp = out; gen("target triple = \"%s\"\n", g_targ.triple); gen("%%.type.opaque = type opaque\n"); + gen("%%.type.valist = type %s\n", g_targ.valistllvmty); gen("\n"); } |