Give the self-hosting layout fixture the nullable-union host members

WalkerHost now carries the nullable-union registry and the record-field ABSENT test; the natively compiled layout/metadata fixture builds them the same way the emitter does.
This commit is contained in:
Malte Ubl
2026-10-09 11:59:24 -05:00
committed by GitHub
parent 9d963d3937
commit fb23f3bf17
+14 -1
View File
@@ -6,6 +6,9 @@ import { emitLlvmLayouts } from "../../../packages/compiler/src/backend/llvm/lay
import { LlvmDebugInfo } from "../../../packages/compiler/src/backend/llvm/debug-info.js";
import { LlWalkers, type WalkerHost } from "../../../packages/compiler/src/backend/llvm/walkers.js";
import { BlockBuilder } from "../../../packages/compiler/src/backend/llvm/blocks.js";
import { NULLABLE_ABSENT, NullableUnions } from "../../../packages/compiler/src/backend/llvm/nullable-unions.js";
import { emitFieldAbsentTest } from "../../../packages/compiler/src/backend/llvm/common.js";
import { undefinedArmTag } from "../../../packages/compiler/src/ir/analysis.js";
import { f64Lit } from "../../../packages/compiler/src/backend/llvm/common.js";
import { mangleClassObj } from "../../../packages/compiler/src/backend/mangle.js";
import { type IrType } from "../../../packages/compiler/src/ir/ir.js";
@@ -30,6 +33,8 @@ try {
let needsOom = false;
let needsBadTag = false;
const traced = computeTraced(mod);
const nullableUnions = new NullableUnions(mod);
const unionsById = new Map((mod.unions ?? []).map((union) => [union.id, union]));
const host: ClassHost & WalkerHost = {
declare: (decl) => { declarations.add(decl); },
needOom: () => { needsOom = true; },
@@ -46,7 +51,8 @@ try {
recordsById: new Map((mod.records ?? []).map((record) => [record.id, record])),
// emitLlvmModule enables the inline allocator for 64-bit host targets.
inlineAlloc: request.bits === 64,
unionsById: new Map((mod.unions ?? []).map((union) => [union.id, union])),
unionsById,
nullableUnions,
recordCloneShapes: new Set(request.clones),
rcHelpers: null,
unitInstanceRef: (union, tag) => {
@@ -57,6 +63,13 @@ try {
}
return `@native_unit_${index}`;
},
// Mirrors the emitter: a nullable slot's ABSENT state is the sentinel.
fieldAbsentTestIn: (B, value, unionId) => {
if (!nullableUnions.has(unionId)) return emitFieldAbsentTest(B, value, undefinedArmTag({ kind: "union", unionId }, unionsById));
const absent = B.tmp();
B.line(`${absent} = icmp eq ptr ${value}, ${NULLABLE_ABSENT}`);
return absent;
},
cstr: (text) => {
let index = strings.indexOf(text);
if (index === -1) { index = strings.length; strings.push(text); }