fix: comptime VM reg→value bridge for optional results (issue 0162)
Add an .optional arm to regToValue in comptime_vm.zig: read the
has_value flag at offset sizeof(child), bridge the payload recursively
into a { payload, i1=true } aggregate when set, yield .null_val (zero
{T,i1}) when clear or the bare null sentinel. Matching serialize arm in
serializeAggregateValue (emit_llvm.zig). Pointer/?Closure/?Protocol-child
optionals and array-payload aggregates bail loudly, not silently.
Regression: examples/comptime/0643-comptime-run-optional-aggregate.sx
(present ?T, present ?i64, null ?i64). Verified by 3 adversarial reviews.
This commit is contained in:
@@ -1230,6 +1230,25 @@ pub const LLVMEmitter = struct {
|
||||
}
|
||||
return c.LLVMConstArray2(llvm_elem_ty, elem_vals.items.ptr, @intCast(elem_vals.items.len));
|
||||
}
|
||||
// Present optional `?T` → `{ <payload>, i1 1 }`, matching the
|
||||
// anonymous-struct layout `toLLVMType` builds for a non-pointer
|
||||
// optional (the absent case is a `.null_val`, serialized at the
|
||||
// `valueToLLVMConst` top level as `LLVMConstNull` of `{T,i1}`).
|
||||
// The VM's reg→value optional arm only produces this 2-field
|
||||
// `[payload, bool]` aggregate for present, non-pointer optionals.
|
||||
if (info == .optional) {
|
||||
if (fields.len != 2) {
|
||||
std.debug.print(
|
||||
"error: comptime init of '{s}' produced an optional aggregate with {} fields (expected 2: payload, has_value)\n",
|
||||
.{ global_name, fields.len },
|
||||
);
|
||||
return self.failGlobalInit(llvm_ty);
|
||||
}
|
||||
const payload = self.valueToLLVMConst(fields[0], info.optional.child, global_name);
|
||||
const has = self.valueToLLVMConst(fields[1], .bool, global_name);
|
||||
var ofields = [_]c.LLVMValueRef{ payload, has };
|
||||
return c.LLVMConstStructInContext(self.context, &ofields, 2, 0);
|
||||
}
|
||||
}
|
||||
|
||||
std.debug.print(
|
||||
|
||||
Reference in New Issue
Block a user