Skip to content

Commit 6aeb6bc

Browse files
committed
stage2: LLVM backend: fix optional_payload instructions
They previously did not respect the optional type layout, but now they do.
1 parent d97928b commit 6aeb6bc

File tree

1 file changed

+42
-22
lines changed

1 file changed

+42
-22
lines changed

src/codegen/llvm.zig

Lines changed: 42 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1770,8 +1770,8 @@ pub const FuncGen = struct {
17701770
.ptr_elem_val => try self.airPtrElemVal(inst),
17711771
.ptr_elem_ptr => try self.airPtrElemPtr(inst),
17721772

1773-
.optional_payload => try self.airOptionalPayload(inst, false),
1774-
.optional_payload_ptr => try self.airOptionalPayload(inst, true),
1773+
.optional_payload => try self.airOptionalPayload(inst),
1774+
.optional_payload_ptr => try self.airOptionalPayloadPtr(inst),
17751775

17761776
.unwrap_errunion_payload => try self.airErrUnionPayload(inst, false),
17771777
.unwrap_errunion_payload_ptr => try self.airErrUnionPayload(inst, true),
@@ -2520,35 +2520,55 @@ pub const FuncGen = struct {
25202520
return self.builder.buildICmp(op, loaded, zero, "");
25212521
}
25222522

2523-
fn airOptionalPayload(
2524-
self: *FuncGen,
2525-
inst: Air.Inst.Index,
2526-
operand_is_ptr: bool,
2527-
) !?*const llvm.Value {
2528-
if (self.liveness.isUnused(inst))
2529-
return null;
2523+
fn airOptionalPayloadPtr(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value {
2524+
if (self.liveness.isUnused(inst)) return null;
25302525

25312526
const ty_op = self.air.instructions.items(.data)[inst].ty_op;
25322527
const operand = try self.resolveInst(ty_op.operand);
2528+
const optional_ty = self.air.typeOf(ty_op.operand).childType();
2529+
var buf: Type.Payload.ElemType = undefined;
2530+
const payload_ty = optional_ty.optionalChild(&buf);
2531+
if (!payload_ty.hasCodeGenBits()) {
2532+
// We have a pointer to a zero-bit value and we need to return
2533+
// a pointer to a zero-bit value.
2534+
return operand;
2535+
}
2536+
if (optional_ty.isPtrLikeOptional()) {
2537+
// The payload and the optional are the same value.
2538+
return operand;
2539+
}
2540+
const index_type = self.context.intType(32);
2541+
const indices: [2]*const llvm.Value = .{
2542+
index_type.constNull(), // dereference the pointer
2543+
index_type.constNull(), // first field is the payload
2544+
};
2545+
return self.builder.buildInBoundsGEP(operand, &indices, indices.len, "");
2546+
}
25332547

2534-
if (operand_is_ptr) {
2535-
const operand_ty = self.air.typeOf(ty_op.operand).elemType();
2536-
if (operand_ty.isPtrLikeOptional()) {
2537-
return self.builder.buildLoad(operand, "");
2538-
}
2548+
fn airOptionalPayload(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value {
2549+
if (self.liveness.isUnused(inst)) return null;
25392550

2540-
const index_type = self.context.intType(32);
2541-
var indices: [2]*const llvm.Value = .{
2542-
index_type.constNull(), index_type.constNull(),
2543-
};
2544-
return self.builder.buildInBoundsGEP(operand, &indices, 2, "");
2545-
}
2551+
const ty_op = self.air.instructions.items(.data)[inst].ty_op;
2552+
const operand = try self.resolveInst(ty_op.operand);
2553+
const optional_ty = self.air.typeOf(ty_op.operand);
2554+
const payload_ty = self.air.typeOfIndex(inst);
2555+
if (!payload_ty.hasCodeGenBits()) return null;
25462556

2547-
const operand_ty = self.air.typeOf(ty_op.operand);
2548-
if (operand_ty.isPtrLikeOptional()) {
2557+
if (optional_ty.isPtrLikeOptional()) {
2558+
// Payload value is the same as the optional value.
25492559
return operand;
25502560
}
25512561

2562+
if (isByRef(payload_ty)) {
2563+
// We have a pointer and we need to return a pointer to the first field.
2564+
const index_type = self.context.intType(32);
2565+
const indices: [2]*const llvm.Value = .{
2566+
index_type.constNull(), // dereference the pointer
2567+
index_type.constNull(), // first field is the payload
2568+
};
2569+
return self.builder.buildInBoundsGEP(operand, &indices, indices.len, "");
2570+
}
2571+
25522572
return self.builder.buildExtractValue(operand, 0, "");
25532573
}
25542574

0 commit comments

Comments
 (0)