authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-10-22 23:35:46-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-10-22 23:35:46-07:00
log6aeb6bcc84f48fdc88374fa4a3d5a2b9d0bd147e
treed470bb4aff252454118b418f007c005ac755f14f
parentd97928bf52a217f75c359ae9b1513bd9d42c82d3

stage2: LLVM backend: fix optional_payload instructions

They previously did not respect the optional type layout, but now they do.

1 files changed, 42 insertions(+), 22 deletions(-)

src/codegen/llvm.zig+42-22
......@@ -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