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 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<Typecked>[]): ComplexMap<string[], ItemId> {
const knows = new ComplexMap<string[], ItemId>();
@ -384,7 +384,7 @@ function lowerFunc(cx: Context, func: ItemFunction<Typecked>) {
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");
}

View file

@ -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,

View file

@ -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);
);
);

View file

@ -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");
);