implement some more stuff around raw pointers

This commit is contained in:
nora 2023-11-05 11:29:41 +01:00
parent ef04f21100
commit 3af8f4fc40
8 changed files with 67 additions and 17 deletions

View file

@ -465,6 +465,7 @@ export const BUILTINS = [
"false",
"trap",
// Intrinsics:
"__NULL", // null raw pointer
"__i32_store",
"__i64_store",
"__i32_load",
@ -536,7 +537,7 @@ export type TyStruct = {
export type TyRawPtr = {
kind: "rawptr";
inner: TyStruct;
inner: Ty;
};
export type TyNever = {

View file

@ -669,6 +669,9 @@ function lowerExpr(
break;
case "print":
todo("print function");
case "__NULL":
instrs.push({ kind: "i32.const", imm: 0n });
break;
default: {
unreachable(`${res.name}#B is not a value`);
}
@ -688,7 +691,8 @@ function lowerExpr(
const rhsTy = expr.rhs.ty;
if (
(lhsTy.kind === "int" && rhsTy.kind === "int") ||
(lhsTy.kind === "i32" && rhsTy.kind === "i32")
(lhsTy.kind === "i32" && rhsTy.kind === "i32") ||
(lhsTy.kind === "rawptr" && rhsTy.kind === "rawptr")
) {
let kind: wasm.Instr["kind"];
const valty = lhsTy.kind === "int" ? "i64" : "i32";
@ -1332,6 +1336,9 @@ function sizeOfValtype(type: wasm.ValType): number {
export function layoutOfStruct(ty_: TyStruct | TyRawPtr): StructLayout {
const ty = ty_.kind === "struct" ? ty_ : ty_.inner;
if (ty.kind !== "struct") {
unreachable("must be struct");
}
const fieldWasmTys = ty.fields.map(([, field]) => wasmTypeForBody(field));
// TODO: Use the max alignment instead.

View file

@ -93,7 +93,7 @@ function builtinAsTy(cx: TypeckCtx, name: string, span: Span): Ty {
}
}
function typeOfBuiltinValue(cx: TypeckCtx, name: BuiltinName, span: Span): Ty {
function typeOfBuiltinValue(fcx: FuncCtx, name: BuiltinName, span: Span): Ty {
switch (name) {
case "false":
case "true":
@ -102,6 +102,8 @@ function typeOfBuiltinValue(cx: TypeckCtx, name: BuiltinName, span: Span): Ty {
return mkTyFn([TY_STRING], TY_UNIT);
case "trap":
return mkTyFn([], TY_NEVER);
case "__NULL":
return { kind: "rawptr", inner: fcx.infcx.newVar() };
case "__i32_store":
return mkTyFn([TY_I32, TY_I32], TY_UNIT);
case "__i64_store":
@ -118,7 +120,7 @@ function typeOfBuiltinValue(cx: TypeckCtx, name: BuiltinName, span: Span): Ty {
return mkTyFn([TY_I32], TY_INT);
default: {
return tyError(
cx,
fcx.cx,
new CompilerError(`\`${name}\` cannot be used as a value`, span),
);
}
@ -696,7 +698,7 @@ function typeOfValue(fcx: FuncCtx, res: Resolution, span: Span): Ty {
return typeOfItem(fcx.cx, res.id, span);
}
case "builtin":
return typeOfBuiltinValue(fcx.cx, res.name, span);
return typeOfBuiltinValue(fcx, res.name, span);
case "error":
return tyErrorFrom(res);
}
@ -906,8 +908,29 @@ export function checkBody(
}
case "struct":
case "rawptr": {
const fields =
lhs.ty.kind === "struct" ? lhs.ty.fields : lhs.ty.inner.fields;
let fields: [string, Ty][];
if (lhs.ty.kind === "struct") {
fields = lhs.ty.fields;
} else if (lhs.ty.kind === "rawptr") {
let inner = fcx.infcx.resolveIfPossible(lhs.ty.inner);
if (inner.kind !== "struct") {
inner = tyError(
fcx.cx,
new CompilerError(
"fields can only be accessed on pointers pointing to a struct",
expr.lhs.span,
),
);
ty = inner;
break;
} else {
fields = inner.fields;
}
} else {
fields = [];
unreachable("must be struct or rawptr here");
}
if (typeof field.value === "string") {
const idx = fields.findIndex(([name]) => name === field.value);
if (idx === -1) {
@ -1149,6 +1172,11 @@ function checkBinary(
return { ...expr, lhs, rhs, ty: TY_BOOL };
}
if (lhsTy.kind === "rawptr" && rhsTy.kind === "rawptr") {
fcx.infcx.assign(lhsTy.inner, rhsTy.inner, expr.span);
return { ...expr, lhs, rhs, ty: TY_BOOL };
}
if (EQUALITY_KINDS.includes(expr.binaryKind)) {
if (lhsTy.kind === "bool" && rhsTy.kind === "bool") {
return { ...expr, lhs, rhs, ty: TY_BOOL };