From b2b80fe2ee71a629989ef14c5567644ec88fedad Mon Sep 17 00:00:00 2001 From: Nilstrieb <48135649+Nilstrieb@users.noreply.github.com> Date: Sat, 16 Dec 2023 14:13:45 +0100 Subject: [PATCH] list or whatever --- src/codegen.test.ts | 2 +- src/codegen.ts | 22 +++++++++++----------- src/typeck/expr.ts | 9 +++++++++ std/list.nil | 41 ++++++++++++++++++++++++++++++++++------- std/rt/alloc.nil | 18 ++++-------------- 5 files changed, 59 insertions(+), 33 deletions(-) diff --git a/src/codegen.test.ts b/src/codegen.test.ts index 27b73c4..23416b3 100644 --- a/src/codegen.test.ts +++ b/src/codegen.test.ts @@ -75,7 +75,7 @@ it("should compute single field struct layout correctly", () => { ], }, ], - "size": 8, + "size": 16, } `); }); diff --git a/src/codegen.ts b/src/codegen.ts index 9880f66..71c01e6 100644 --- a/src/codegen.ts +++ b/src/codegen.ts @@ -42,8 +42,8 @@ const WASM_PAGE = 65536; const DUMMY_IDX = 9999999; -const ALLOCATE_ITEM: string[] = ["std", "rt", "alloc", "allocateItem"]; -const DEALLOCATE_ITEM: string[] = ["std", "rt", "alloc", "deallocateItem"]; +const ALLOCATE: string[] = ["std", "rt", "alloc", "allocate"]; +const DEALLOCATE: string[] = ["std", "rt", "alloc", "deallocate"]; type RelocationKind = | { @@ -118,7 +118,7 @@ function appendData(cx: Context, newData: Uint8Array): number { } } -const KNOWN_DEF_PATHS = [ALLOCATE_ITEM, DEALLOCATE_ITEM]; +const KNOWN_DEF_PATHS = [ALLOCATE, DEALLOCATE]; function getKnownDefPaths(pkgs: Pkg[]): ComplexMap { const knows = new ComplexMap(); @@ -384,7 +384,7 @@ function lowerFunc(cx: Context, func: ItemFunction) { fcx.wasm.body = body.instructions; } else { lowerExpr(fcx, wasmFunc.body, body); - paramLocations.forEach((local) => { + paramLocations.forEach((local) => { const refcount = needsRefcount(local.ty); if (refcount !== undefined) { // TODO: correctly deal with tuples @@ -814,7 +814,10 @@ function lowerExpr( const { res } = expr.lhs.value; if (res.kind === "builtin") { const assertArgs = (n: number) => { - if (expr.args.length !== n) unreachable("nope"); + if (expr.args.length !== n) + unreachable( + `wrong amount of arguments for ${res.name}: expected ${n} found ${expr.args.length}`, + ); }; switch (res.name) { case "trap": { @@ -842,7 +845,7 @@ function lowerExpr( break exprKind; } case "__i64_store": { - assertArgs(3); + assertArgs(2); lowerExpr(fcx, instrs, expr.args[0]); lowerExpr(fcx, instrs, expr.args[1]); instrs.push({ kind: "i64.store", imm: {} }); @@ -1053,7 +1056,7 @@ function lowerExpr( instrs.push({ kind: "i32.const", imm: BigInt(layout.size) }); instrs.push({ kind: "i32.const", imm: BigInt(layout.align) }); const allocate: wasm.Instr = { kind: "call", func: DUMMY_IDX }; - const allocateItemId = fcx.cx.knownDefPaths.get(ALLOCATE_ITEM); + const allocateItemId = fcx.cx.knownDefPaths.get(ALLOCATE); if (!allocateItemId) { unreachable("std.rt.allocateItem not found"); } @@ -1384,9 +1387,6 @@ export function layoutOfStruct(ty_: TyStruct | TyRawPtr): StructLayout { return value; }); - // we ignore the refcount for struct size. - offset -= 4; - if (align === 8 && offset % 8 !== 0) { offset += 4; } @@ -1508,7 +1508,7 @@ function subRefcount( instrs: wasm.Instr[], kind: StructLayout | "string", ) { - const deallocateItemId = fcx.cx.knownDefPaths.get(DEALLOCATE_ITEM); + const deallocateItemId = fcx.cx.knownDefPaths.get(DEALLOCATE); if (!deallocateItemId) { unreachable("std.rt.deallocateItem not found"); } diff --git a/src/typeck/expr.ts b/src/typeck/expr.ts index 2c9956e..3fbb6cf 100644 --- a/src/typeck/expr.ts +++ b/src/typeck/expr.ts @@ -286,6 +286,10 @@ export function checkBody( let ty: Ty; let fieldIdx: number | undefined; switch (lhs.ty.kind) { + case "error": { + ty = tyErrorFrom(lhs.ty); + break; + } case "tuple": { const { elems } = lhs.ty; if (typeof field.value === "number") { @@ -777,6 +781,11 @@ function checkCall( const args = expr.args.map((arg) => fcx.checkExpr(arg)); const lhsTy = lhs.ty; + + if (lhsTy.kind === "error") { + return { ...expr, lhs, args, ty: lhsTy }; + } + if (lhsTy.kind !== "fn") { const ty = tyError( fcx.cx, diff --git a/std/list.nil b/std/list.nil index d7e0184..b01e31b 100644 --- a/std/list.nil +++ b/std/list.nil @@ -1,21 +1,48 @@ type List[T] = struct { - ptr: Int, - len: Int, - cap: Int, + ptr: I32, + len: I32, + cap: I32, }; function new(): List[Int] = ( - List { ptr: 0, len: 0, cap: 0 } + List { ptr: 0_I32, len: 0_I32, cap: 0_I32 } ); function push(list: List[Int], elem: Int) = ( - growIfNeeded(list, 1); + growIfNeeded(list, 1_I32); + let addr = list.ptr + (SIZEOF * list.len); + __i64_store(addr, elem); + list.len = list.len + 1_I32; +); + +function debugPrint(list: List[Int]) = ( + let i = 0_I32; + print("["); + loop ( + if i >= list.len then ( + break; + ); + let elem = __i64_load(list.ptr + (i * SIZEOF)); + std.printInt(elem); + if (i + 1_I32) < list.len then print(", "); + + i = i + 1_I32; + ); + std.println("]"); ); // PRIVATE: -function growIfNeeded(list: List[Int], elems: Int) = ( +global SIZEOF: I32 = 8_I32; +global ALIGNOF: I32 = 8_I32; + +function growIfNeeded(list: List[Int], elems: I32) = ( if (list.len + elems) < list.cap then ( - let newMemory = std.rt.alloc.allocateItem(0_I32, 0_I32); + let newMemory = std.rt.alloc.allocate(SIZEOF * list.cap * 2_I32, ALIGNOF); + let oldMemory = list.ptr; + let amount = SIZEOF * list.len; + std.rt.memcpy(newMemory, oldMemory, amount); + + if list.cap > 0_I32 then std.rt.alloc.deallocate(list.ptr, list.cap * SIZEOF); ); ); diff --git a/std/rt/alloc.nil b/std/rt/alloc.nil index 3c29983..d6f2709 100644 --- a/std/rt/alloc.nil +++ b/std/rt/alloc.nil @@ -7,23 +7,13 @@ global HEAD_PTR: I32 = 1024_I32; // Allocate a new item. We do not deallocate anything yet. // lol. -function allocateItem(objSize: I32, align: I32): I32 = ( +function allocate(size: I32, align: I32): I32 = ( if align < 4_I32 then std.abort("invalid alignment"); - // Include the refcount header. - let actualSize = 4_I32 + objSize; - // Let's see whether we can fit the refcount into the align bits. // I happen to know that everything will always be at least 4 bytes aligned. let alignedPtr = std.alignUp(HEAD_PTR, align); - let actualObjPtr = if (alignedPtr - HEAD_PTR) > align then ( - alignedPtr - 4_I32 - ) else ( - // Take up the next spot. - alignedPtr + align - 4_I32 - ); - - let newHeadPtr = actualObjPtr + actualSize; + let newHeadPtr = alignedPtr + size; if newHeadPtr > __memory_size() then ( // 16 pages, very arbitrary. @@ -36,10 +26,10 @@ function allocateItem(objSize: I32, align: I32): I32 = ( HEAD_PTR = newHeadPtr; - actualObjPtr + alignedPtr ); -function deallocateItem(ptr: I32, objSize: I32) = ( +function deallocate(ptr: I32, size: I32) = ( std.println("uwu deawwocate :3"); );