diff options
| author | Andrew Kelley <andrew@ziglang.org> | 2021-10-22 23:35:46 -0700 |
|---|---|---|
| committer | Andrew Kelley <andrew@ziglang.org> | 2021-10-22 23:35:46 -0700 |
| commit | 6aeb6bcc84f48fdc88374fa4a3d5a2b9d0bd147e (patch) | |
| tree | d470bb4aff252454118b418f007c005ac755f14f /src/codegen | |
| parent | d97928bf52a217f75c359ae9b1513bd9d42c82d3 (diff) | |
| download | zig-6aeb6bcc84f48fdc88374fa4a3d5a2b9d0bd147e.tar.gz zig-6aeb6bcc84f48fdc88374fa4a3d5a2b9d0bd147e.zip | |
stage2: LLVM backend: fix optional_payload instructions
They previously did not respect the optional type layout, but now they
do.
Diffstat (limited to 'src/codegen')
| -rw-r--r-- | src/codegen/llvm.zig | 64 |
1 files changed, 42 insertions, 22 deletions
diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index 3f24bb535d..3a01440135 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -1770,8 +1770,8 @@ pub const FuncGen = struct { .ptr_elem_val => try self.airPtrElemVal(inst), .ptr_elem_ptr => try self.airPtrElemPtr(inst), - .optional_payload => try self.airOptionalPayload(inst, false), - .optional_payload_ptr => try self.airOptionalPayload(inst, true), + .optional_payload => try self.airOptionalPayload(inst), + .optional_payload_ptr => try self.airOptionalPayloadPtr(inst), .unwrap_errunion_payload => try self.airErrUnionPayload(inst, false), .unwrap_errunion_payload_ptr => try self.airErrUnionPayload(inst, true), @@ -2520,35 +2520,55 @@ pub const FuncGen = struct { return self.builder.buildICmp(op, loaded, zero, ""); } - fn airOptionalPayload( - self: *FuncGen, - inst: Air.Inst.Index, - operand_is_ptr: bool, - ) !?*const llvm.Value { - if (self.liveness.isUnused(inst)) - return null; + fn airOptionalPayloadPtr(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value { + if (self.liveness.isUnused(inst)) return null; const ty_op = self.air.instructions.items(.data)[inst].ty_op; const operand = try self.resolveInst(ty_op.operand); + const optional_ty = self.air.typeOf(ty_op.operand).childType(); + var buf: Type.Payload.ElemType = undefined; + const payload_ty = optional_ty.optionalChild(&buf); + if (!payload_ty.hasCodeGenBits()) { + // We have a pointer to a zero-bit value and we need to return + // a pointer to a zero-bit value. + return operand; + } + if (optional_ty.isPtrLikeOptional()) { + // The payload and the optional are the same value. + return operand; + } + const index_type = self.context.intType(32); + const indices: [2]*const llvm.Value = .{ + index_type.constNull(), // dereference the pointer + index_type.constNull(), // first field is the payload + }; + return self.builder.buildInBoundsGEP(operand, &indices, indices.len, ""); + } - if (operand_is_ptr) { - const operand_ty = self.air.typeOf(ty_op.operand).elemType(); - if (operand_ty.isPtrLikeOptional()) { - return self.builder.buildLoad(operand, ""); - } + fn airOptionalPayload(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value { + if (self.liveness.isUnused(inst)) return null; - const index_type = self.context.intType(32); - var indices: [2]*const llvm.Value = .{ - index_type.constNull(), index_type.constNull(), - }; - return self.builder.buildInBoundsGEP(operand, &indices, 2, ""); - } + const ty_op = self.air.instructions.items(.data)[inst].ty_op; + const operand = try self.resolveInst(ty_op.operand); + const optional_ty = self.air.typeOf(ty_op.operand); + const payload_ty = self.air.typeOfIndex(inst); + if (!payload_ty.hasCodeGenBits()) return null; - const operand_ty = self.air.typeOf(ty_op.operand); - if (operand_ty.isPtrLikeOptional()) { + if (optional_ty.isPtrLikeOptional()) { + // Payload value is the same as the optional value. return operand; } + if (isByRef(payload_ty)) { + // We have a pointer and we need to return a pointer to the first field. + const index_type = self.context.intType(32); + const indices: [2]*const llvm.Value = .{ + index_type.constNull(), // dereference the pointer + index_type.constNull(), // first field is the payload + }; + return self.builder.buildInBoundsGEP(operand, &indices, indices.len, ""); + } + return self.builder.buildExtractValue(operand, 0, ""); } |
