list or whatever

This commit is contained in:
nora 2023-12-16 14:13:45 +01:00
parent 179c4b3505
commit b2b80fe2ee
5 changed files with 59 additions and 33 deletions

View file

@ -75,7 +75,7 @@ it("should compute single field struct layout correctly", () => {
], ],
}, },
], ],
"size": 8, "size": 16,
} }
`); `);
}); });

View file

@ -42,8 +42,8 @@ const WASM_PAGE = 65536;
const DUMMY_IDX = 9999999; const DUMMY_IDX = 9999999;
const ALLOCATE_ITEM: string[] = ["std", "rt", "alloc", "allocateItem"]; const ALLOCATE: string[] = ["std", "rt", "alloc", "allocate"];
const DEALLOCATE_ITEM: string[] = ["std", "rt", "alloc", "deallocateItem"]; const DEALLOCATE: string[] = ["std", "rt", "alloc", "deallocate"];
type RelocationKind = 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<Typecked>[]): ComplexMap<string[], ItemId> { function getKnownDefPaths(pkgs: Pkg<Typecked>[]): ComplexMap<string[], ItemId> {
const knows = new ComplexMap<string[], ItemId>(); const knows = new ComplexMap<string[], ItemId>();
@ -814,7 +814,10 @@ function lowerExpr(
const { res } = expr.lhs.value; const { res } = expr.lhs.value;
if (res.kind === "builtin") { if (res.kind === "builtin") {
const assertArgs = (n: number) => { 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) { switch (res.name) {
case "trap": { case "trap": {
@ -842,7 +845,7 @@ function lowerExpr(
break exprKind; break exprKind;
} }
case "__i64_store": { case "__i64_store": {
assertArgs(3); assertArgs(2);
lowerExpr(fcx, instrs, expr.args[0]); lowerExpr(fcx, instrs, expr.args[0]);
lowerExpr(fcx, instrs, expr.args[1]); lowerExpr(fcx, instrs, expr.args[1]);
instrs.push({ kind: "i64.store", imm: {} }); 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.size) });
instrs.push({ kind: "i32.const", imm: BigInt(layout.align) }); instrs.push({ kind: "i32.const", imm: BigInt(layout.align) });
const allocate: wasm.Instr = { kind: "call", func: DUMMY_IDX }; 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) { if (!allocateItemId) {
unreachable("std.rt.allocateItem not found"); unreachable("std.rt.allocateItem not found");
} }
@ -1384,9 +1387,6 @@ export function layoutOfStruct(ty_: TyStruct | TyRawPtr): StructLayout {
return value; return value;
}); });
// we ignore the refcount for struct size.
offset -= 4;
if (align === 8 && offset % 8 !== 0) { if (align === 8 && offset % 8 !== 0) {
offset += 4; offset += 4;
} }
@ -1508,7 +1508,7 @@ function subRefcount(
instrs: wasm.Instr[], instrs: wasm.Instr[],
kind: StructLayout | "string", kind: StructLayout | "string",
) { ) {
const deallocateItemId = fcx.cx.knownDefPaths.get(DEALLOCATE_ITEM); const deallocateItemId = fcx.cx.knownDefPaths.get(DEALLOCATE);
if (!deallocateItemId) { if (!deallocateItemId) {
unreachable("std.rt.deallocateItem not found"); unreachable("std.rt.deallocateItem not found");
} }

View file

@ -286,6 +286,10 @@ export function checkBody(
let ty: Ty; let ty: Ty;
let fieldIdx: number | undefined; let fieldIdx: number | undefined;
switch (lhs.ty.kind) { switch (lhs.ty.kind) {
case "error": {
ty = tyErrorFrom(lhs.ty);
break;
}
case "tuple": { case "tuple": {
const { elems } = lhs.ty; const { elems } = lhs.ty;
if (typeof field.value === "number") { if (typeof field.value === "number") {
@ -777,6 +781,11 @@ function checkCall(
const args = expr.args.map((arg) => fcx.checkExpr(arg)); const args = expr.args.map((arg) => fcx.checkExpr(arg));
const lhsTy = lhs.ty; const lhsTy = lhs.ty;
if (lhsTy.kind === "error") {
return { ...expr, lhs, args, ty: lhsTy };
}
if (lhsTy.kind !== "fn") { if (lhsTy.kind !== "fn") {
const ty = tyError( const ty = tyError(
fcx.cx, fcx.cx,

View file

@ -1,21 +1,48 @@
type List[T] = struct { type List[T] = struct {
ptr: Int, ptr: I32,
len: Int, len: I32,
cap: Int, cap: I32,
}; };
function new(): List[Int] = ( 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) = ( 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: // 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 ( 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);
); );
); );

View file

@ -7,23 +7,13 @@ global HEAD_PTR: I32 = 1024_I32;
// Allocate a new item. We do not deallocate anything yet. // Allocate a new item. We do not deallocate anything yet.
// lol. // lol.
function allocateItem(objSize: I32, align: I32): I32 = ( function allocate(size: I32, align: I32): I32 = (
if align < 4_I32 then std.abort("invalid alignment"); 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. // 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. // I happen to know that everything will always be at least 4 bytes aligned.
let alignedPtr = std.alignUp(HEAD_PTR, align); let alignedPtr = std.alignUp(HEAD_PTR, align);
let actualObjPtr = if (alignedPtr - HEAD_PTR) > align then ( let newHeadPtr = alignedPtr + size;
alignedPtr - 4_I32
) else (
// Take up the next spot.
alignedPtr + align - 4_I32
);
let newHeadPtr = actualObjPtr + actualSize;
if newHeadPtr > __memory_size() then ( if newHeadPtr > __memory_size() then (
// 16 pages, very arbitrary. // 16 pages, very arbitrary.
@ -36,10 +26,10 @@ function allocateItem(objSize: I32, align: I32): I32 = (
HEAD_PTR = newHeadPtr; HEAD_PTR = newHeadPtr;
actualObjPtr alignedPtr
); );
function deallocateItem(ptr: I32, objSize: I32) = ( function deallocate(ptr: I32, size: I32) = (
std.println("uwu deawwocate :3"); std.println("uwu deawwocate :3");
); );