stage2: make error{} the same size as anyerror
Having `error{}` be a zero bit type causes issues when it interracts
with empty inferred error sets which are the same size as `anyerror`.
This commit is contained in:
@@ -752,12 +752,6 @@ pub const DeclGen = struct {
|
||||
const error_type = ty.errorUnionSet();
|
||||
const payload_type = ty.errorUnionPayload();
|
||||
|
||||
if (error_type.errorSetCardinality() == .zero) {
|
||||
// We use the payload directly as the type.
|
||||
const payload_val = val.castTag(.eu_payload).?.data;
|
||||
return dg.renderValue(writer, payload_type, payload_val, location);
|
||||
}
|
||||
|
||||
if (!payload_type.hasRuntimeBits()) {
|
||||
// We use the error type directly as the type.
|
||||
const err_val = if (val.errorUnionIsPayload()) Value.initTag(.zero) else val;
|
||||
@@ -1381,13 +1375,8 @@ pub const DeclGen = struct {
|
||||
return w.writeAll("uint16_t");
|
||||
},
|
||||
.ErrorUnion => {
|
||||
const error_ty = t.errorUnionSet();
|
||||
const payload_ty = t.errorUnionPayload();
|
||||
|
||||
if (error_ty.errorSetCardinality() == .zero) {
|
||||
return dg.renderType(w, payload_ty);
|
||||
}
|
||||
|
||||
if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {
|
||||
return dg.renderType(w, Type.anyerror);
|
||||
}
|
||||
@@ -2892,41 +2881,36 @@ fn lowerTry(
|
||||
operand_is_ptr: bool,
|
||||
result_ty: Type,
|
||||
) !CValue {
|
||||
if (err_union_ty.errorUnionSet().errorSetCardinality() == .zero) {
|
||||
// If the error set has no fields, then the payload and the error
|
||||
// union are the same value.
|
||||
return err_union;
|
||||
}
|
||||
|
||||
const writer = f.object.writer();
|
||||
const payload_ty = err_union_ty.errorUnionPayload();
|
||||
const payload_has_bits = payload_ty.hasRuntimeBitsIgnoreComptime();
|
||||
|
||||
const writer = f.object.writer();
|
||||
|
||||
err: {
|
||||
if (!payload_has_bits) {
|
||||
if (operand_is_ptr) {
|
||||
try writer.writeAll("if(*");
|
||||
} else {
|
||||
try writer.writeAll("if(");
|
||||
if (!err_union_ty.errorUnionSet().errorSetIsEmpty()) {
|
||||
err: {
|
||||
if (!payload_has_bits) {
|
||||
if (operand_is_ptr) {
|
||||
try writer.writeAll("if(*");
|
||||
} else {
|
||||
try writer.writeAll("if(");
|
||||
}
|
||||
try f.writeCValue(writer, err_union);
|
||||
try writer.writeAll(")");
|
||||
break :err;
|
||||
}
|
||||
if (operand_is_ptr or isByRef(err_union_ty)) {
|
||||
try writer.writeAll("if(");
|
||||
try f.writeCValue(writer, err_union);
|
||||
try writer.writeAll("->error)");
|
||||
break :err;
|
||||
}
|
||||
try f.writeCValue(writer, err_union);
|
||||
try writer.writeAll(")");
|
||||
break :err;
|
||||
}
|
||||
if (operand_is_ptr or isByRef(err_union_ty)) {
|
||||
try writer.writeAll("if(");
|
||||
try f.writeCValue(writer, err_union);
|
||||
try writer.writeAll("->error)");
|
||||
break :err;
|
||||
try writer.writeAll(".error)");
|
||||
}
|
||||
try writer.writeAll("if(");
|
||||
try f.writeCValue(writer, err_union);
|
||||
try writer.writeAll(".error)");
|
||||
}
|
||||
|
||||
try genBody(f, body);
|
||||
try f.object.indent_writer.insertNewline();
|
||||
try genBody(f, body);
|
||||
try f.object.indent_writer.insertNewline();
|
||||
}
|
||||
|
||||
if (!payload_has_bits) {
|
||||
if (!operand_is_ptr) {
|
||||
@@ -3466,7 +3450,7 @@ fn airUnwrapErrUnionErr(f: *Function, inst: Air.Inst.Index) !CValue {
|
||||
|
||||
if (operand_ty.zigTypeTag() == .Pointer) {
|
||||
const err_union_ty = operand_ty.childType();
|
||||
if (err_union_ty.errorUnionSet().errorSetCardinality() == .zero) {
|
||||
if (err_union_ty.errorUnionSet().errorSetIsEmpty()) {
|
||||
return CValue{ .bytes = "0" };
|
||||
}
|
||||
if (!err_union_ty.errorUnionPayload().hasRuntimeBits()) {
|
||||
@@ -3478,7 +3462,7 @@ fn airUnwrapErrUnionErr(f: *Function, inst: Air.Inst.Index) !CValue {
|
||||
try writer.writeAll(";\n");
|
||||
return local;
|
||||
}
|
||||
if (operand_ty.errorUnionSet().errorSetCardinality() == .zero) {
|
||||
if (operand_ty.errorUnionSet().errorSetIsEmpty()) {
|
||||
return CValue{ .bytes = "0" };
|
||||
}
|
||||
if (!operand_ty.errorUnionPayload().hasRuntimeBits()) {
|
||||
@@ -3507,10 +3491,6 @@ fn airUnwrapErrUnionPay(f: *Function, inst: Air.Inst.Index, maybe_addrof: [*:0]c
|
||||
const operand_is_ptr = operand_ty.zigTypeTag() == .Pointer;
|
||||
const error_union_ty = if (operand_is_ptr) operand_ty.childType() else operand_ty;
|
||||
|
||||
if (error_union_ty.errorUnionSet().errorSetCardinality() == .zero) {
|
||||
return operand;
|
||||
}
|
||||
|
||||
if (!error_union_ty.errorUnionPayload().hasRuntimeBits()) {
|
||||
return CValue.none;
|
||||
}
|
||||
@@ -3575,11 +3555,6 @@ fn airErrUnionPayloadPtrSet(f: *Function, inst: Air.Inst.Index) !CValue {
|
||||
const error_ty = error_union_ty.errorUnionSet();
|
||||
const payload_ty = error_union_ty.errorUnionPayload();
|
||||
|
||||
if (error_ty.errorSetCardinality() == .zero) {
|
||||
// TODO: write undefined bytes through the pointer here
|
||||
return operand;
|
||||
}
|
||||
|
||||
// First, set the non-error value.
|
||||
if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {
|
||||
try f.writeCValueDeref(writer, operand);
|
||||
@@ -3623,9 +3598,6 @@ fn airWrapErrUnionPay(f: *Function, inst: Air.Inst.Index) !CValue {
|
||||
const operand = try f.resolveInst(ty_op.operand);
|
||||
|
||||
const inst_ty = f.air.typeOfIndex(inst);
|
||||
if (inst_ty.errorUnionSet().errorSetCardinality() == .zero) {
|
||||
return operand;
|
||||
}
|
||||
const local = try f.allocLocal(inst_ty, .Const);
|
||||
try writer.writeAll(" = { .error = 0, .payload = ");
|
||||
try f.writeCValue(writer, operand);
|
||||
@@ -3652,7 +3624,7 @@ fn airIsErr(
|
||||
|
||||
try writer.writeAll(" = ");
|
||||
|
||||
if (error_ty.errorSetCardinality() == .zero) {
|
||||
if (error_ty.errorSetIsEmpty()) {
|
||||
try writer.print("0 {s} 0;\n", .{op_str});
|
||||
} else {
|
||||
if (is_ptr) {
|
||||
|
||||
@@ -1571,22 +1571,6 @@ pub const Object = struct {
|
||||
},
|
||||
.ErrorUnion => {
|
||||
const payload_ty = ty.errorUnionPayload();
|
||||
switch (ty.errorUnionSet().errorSetCardinality()) {
|
||||
.zero => {
|
||||
const payload_di_ty = try o.lowerDebugType(payload_ty, .full);
|
||||
// The recursive call to `lowerDebugType` means we can't use `gop` anymore.
|
||||
try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.initFull(payload_di_ty), .{ .mod = o.module });
|
||||
return payload_di_ty;
|
||||
},
|
||||
.one => {
|
||||
if (payload_ty.isNoReturn()) {
|
||||
const di_type = dib.createBasicType("void", 0, DW.ATE.signed);
|
||||
gop.value_ptr.* = AnnotatedDITypePtr.initFull(di_type);
|
||||
return di_type;
|
||||
}
|
||||
},
|
||||
.many => {},
|
||||
}
|
||||
if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {
|
||||
const err_set_di_ty = try o.lowerDebugType(Type.anyerror, .full);
|
||||
// The recursive call to `lowerDebugType` means we can't use `gop` anymore.
|
||||
@@ -2554,15 +2538,6 @@ pub const DeclGen = struct {
|
||||
},
|
||||
.ErrorUnion => {
|
||||
const payload_ty = t.errorUnionPayload();
|
||||
switch (t.errorUnionSet().errorSetCardinality()) {
|
||||
.zero => return dg.lowerType(payload_ty),
|
||||
.one => {
|
||||
if (payload_ty.isNoReturn()) {
|
||||
return dg.context.voidType();
|
||||
}
|
||||
},
|
||||
.many => {},
|
||||
}
|
||||
if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {
|
||||
return try dg.lowerType(Type.anyerror);
|
||||
}
|
||||
@@ -3222,10 +3197,6 @@ pub const DeclGen = struct {
|
||||
},
|
||||
.ErrorUnion => {
|
||||
const payload_type = tv.ty.errorUnionPayload();
|
||||
if (tv.ty.errorUnionSet().errorSetCardinality() == .zero) {
|
||||
const payload_val = tv.val.castTag(.eu_payload).?.data;
|
||||
return dg.lowerValue(.{ .ty = payload_type, .val = payload_val });
|
||||
}
|
||||
const is_pl = tv.val.errorUnionIsPayload();
|
||||
|
||||
if (!payload_type.hasRuntimeBitsIgnoreComptime()) {
|
||||
@@ -4795,40 +4766,37 @@ pub const FuncGen = struct {
|
||||
}
|
||||
|
||||
fn lowerTry(fg: *FuncGen, err_union: *const llvm.Value, body: []const Air.Inst.Index, err_union_ty: Type, operand_is_ptr: bool, result_ty: Type) !?*const llvm.Value {
|
||||
if (err_union_ty.errorUnionSet().errorSetCardinality() == .zero) {
|
||||
// If the error set has no fields, then the payload and the error
|
||||
// union are the same value.
|
||||
return err_union;
|
||||
}
|
||||
|
||||
const payload_ty = err_union_ty.errorUnionPayload();
|
||||
const payload_has_bits = payload_ty.hasRuntimeBitsIgnoreComptime();
|
||||
const target = fg.dg.module.getTarget();
|
||||
const is_err = err: {
|
||||
const err_set_ty = try fg.dg.lowerType(Type.anyerror);
|
||||
const zero = err_set_ty.constNull();
|
||||
if (!payload_has_bits) {
|
||||
const loaded = if (operand_is_ptr) fg.builder.buildLoad(err_union, "") else err_union;
|
||||
|
||||
if (!err_union_ty.errorUnionSet().errorSetIsEmpty()) {
|
||||
const is_err = err: {
|
||||
const err_set_ty = try fg.dg.lowerType(Type.anyerror);
|
||||
const zero = err_set_ty.constNull();
|
||||
if (!payload_has_bits) {
|
||||
const loaded = if (operand_is_ptr) fg.builder.buildLoad(err_union, "") else err_union;
|
||||
break :err fg.builder.buildICmp(.NE, loaded, zero, "");
|
||||
}
|
||||
const err_field_index = errUnionErrorOffset(payload_ty, target);
|
||||
if (operand_is_ptr or isByRef(err_union_ty)) {
|
||||
const err_field_ptr = fg.builder.buildStructGEP(err_union, err_field_index, "");
|
||||
const loaded = fg.builder.buildLoad(err_field_ptr, "");
|
||||
break :err fg.builder.buildICmp(.NE, loaded, zero, "");
|
||||
}
|
||||
const loaded = fg.builder.buildExtractValue(err_union, err_field_index, "");
|
||||
break :err fg.builder.buildICmp(.NE, loaded, zero, "");
|
||||
}
|
||||
const err_field_index = errUnionErrorOffset(payload_ty, target);
|
||||
if (operand_is_ptr or isByRef(err_union_ty)) {
|
||||
const err_field_ptr = fg.builder.buildStructGEP(err_union, err_field_index, "");
|
||||
const loaded = fg.builder.buildLoad(err_field_ptr, "");
|
||||
break :err fg.builder.buildICmp(.NE, loaded, zero, "");
|
||||
}
|
||||
const loaded = fg.builder.buildExtractValue(err_union, err_field_index, "");
|
||||
break :err fg.builder.buildICmp(.NE, loaded, zero, "");
|
||||
};
|
||||
};
|
||||
|
||||
const return_block = fg.context.appendBasicBlock(fg.llvm_func, "TryRet");
|
||||
const continue_block = fg.context.appendBasicBlock(fg.llvm_func, "TryCont");
|
||||
_ = fg.builder.buildCondBr(is_err, return_block, continue_block);
|
||||
const return_block = fg.context.appendBasicBlock(fg.llvm_func, "TryRet");
|
||||
const continue_block = fg.context.appendBasicBlock(fg.llvm_func, "TryCont");
|
||||
_ = fg.builder.buildCondBr(is_err, return_block, continue_block);
|
||||
|
||||
fg.builder.positionBuilderAtEnd(return_block);
|
||||
try fg.genBody(body);
|
||||
fg.builder.positionBuilderAtEnd(return_block);
|
||||
try fg.genBody(body);
|
||||
|
||||
fg.builder.positionBuilderAtEnd(continue_block);
|
||||
fg.builder.positionBuilderAtEnd(continue_block);
|
||||
}
|
||||
if (!payload_has_bits) {
|
||||
if (!operand_is_ptr) return null;
|
||||
|
||||
@@ -5665,7 +5633,7 @@ pub const FuncGen = struct {
|
||||
const err_set_ty = try self.dg.lowerType(Type.initTag(.anyerror));
|
||||
const zero = err_set_ty.constNull();
|
||||
|
||||
if (err_union_ty.errorUnionSet().errorSetCardinality() == .zero) {
|
||||
if (err_union_ty.errorUnionSet().errorSetIsEmpty()) {
|
||||
const llvm_i1 = self.context.intType(1);
|
||||
switch (op) {
|
||||
.EQ => return llvm_i1.constInt(1, .False), // 0 == 0
|
||||
@@ -5788,13 +5756,6 @@ pub const FuncGen = struct {
|
||||
|
||||
const ty_op = self.air.instructions.items(.data)[inst].ty_op;
|
||||
const operand = try self.resolveInst(ty_op.operand);
|
||||
const operand_ty = self.air.typeOf(ty_op.operand);
|
||||
const error_union_ty = if (operand_is_ptr) operand_ty.childType() else operand_ty;
|
||||
if (error_union_ty.errorUnionSet().errorSetCardinality() == .zero) {
|
||||
// If the error set has no fields, then the payload and the error
|
||||
// union are the same value.
|
||||
return operand;
|
||||
}
|
||||
const result_ty = self.air.typeOfIndex(inst);
|
||||
const payload_ty = if (operand_is_ptr) result_ty.childType() else result_ty;
|
||||
const target = self.dg.module.getTarget();
|
||||
@@ -5825,7 +5786,7 @@ pub const FuncGen = struct {
|
||||
const operand = try self.resolveInst(ty_op.operand);
|
||||
const operand_ty = self.air.typeOf(ty_op.operand);
|
||||
const err_union_ty = if (operand_is_ptr) operand_ty.childType() else operand_ty;
|
||||
if (err_union_ty.errorUnionSet().errorSetCardinality() == .zero) {
|
||||
if (err_union_ty.errorUnionSet().errorSetIsEmpty()) {
|
||||
const err_llvm_ty = try self.dg.lowerType(Type.anyerror);
|
||||
if (operand_is_ptr) {
|
||||
return self.builder.buildBitCast(operand, err_llvm_ty.pointerType(0), "");
|
||||
@@ -5856,10 +5817,6 @@ pub const FuncGen = struct {
|
||||
const operand = try self.resolveInst(ty_op.operand);
|
||||
const error_union_ty = self.air.typeOf(ty_op.operand).childType();
|
||||
|
||||
if (error_union_ty.errorUnionSet().errorSetCardinality() == .zero) {
|
||||
// TODO: write undefined bytes through the pointer here
|
||||
return operand;
|
||||
}
|
||||
const payload_ty = error_union_ty.errorUnionPayload();
|
||||
const non_error_val = try self.dg.lowerValue(.{ .ty = Type.anyerror, .val = Value.zero });
|
||||
if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {
|
||||
@@ -5938,9 +5895,6 @@ pub const FuncGen = struct {
|
||||
const ty_op = self.air.instructions.items(.data)[inst].ty_op;
|
||||
const inst_ty = self.air.typeOfIndex(inst);
|
||||
const operand = try self.resolveInst(ty_op.operand);
|
||||
if (inst_ty.errorUnionSet().errorSetCardinality() == .zero) {
|
||||
return operand;
|
||||
}
|
||||
const payload_ty = self.air.typeOf(ty_op.operand);
|
||||
if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {
|
||||
return operand;
|
||||
|
||||
Reference in New Issue
Block a user