diff --git a/tests/fixtures/self-hosting/llvm-layouts.ts b/tests/fixtures/self-hosting/llvm-layouts.ts index e8207b89f..d117363d0 100644 --- a/tests/fixtures/self-hosting/llvm-layouts.ts +++ b/tests/fixtures/self-hosting/llvm-layouts.ts @@ -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); }