| author | |
| committer | |
| log | 7c9979a02e830a4383995e66ff623a7d07cac091 |
| tree | 81d0cc15b1c60eaf618ea0d3660f7ca81b7b39de |
| parent | fa50e179f7f8d523ff00be4cac90bf7659394140 |
12 files changed, 66 insertions(+), 10 deletions(-)
src/Air.zig+5| ... | ... | @@ -673,6 +673,10 @@ pub const Inst = struct { |
| 673 | 673 | /// Uses the `un_op` field. |
| 674 | 674 | error_name, |
| 675 | 675 | |
| 676 | /// Returns true if error set has error with value. | |
| 677 | /// Uses the `ty_op` field. | |
| 678 | error_set_has_value, | |
| 679 | ||
| 676 | 680 | /// Constructs a vector, tuple, struct, or array value out of runtime-known elements. |
| 677 | 681 | /// Some of the elements may be comptime-known. |
| 678 | 682 | /// Uses the `ty_pl` field, payload is index of an array of elements, each of which |
| ... | ... | @@ -1062,6 +1066,7 @@ pub fn typeOfIndex(air: Air, inst: Air.Inst.Index) Type { |
| 1062 | 1066 | .is_err_ptr, |
| 1063 | 1067 | .is_non_err_ptr, |
| 1064 | 1068 | .is_named_enum_value, |
| 1069 | .error_set_has_value, | |
| 1065 | 1070 | => return Type.bool, |
| 1066 | 1071 | |
| 1067 | 1072 | .const_ty => return Type.type, |
src/Liveness.zig+2| ... | ... | @@ -267,6 +267,7 @@ pub fn categorizeOperand( |
| 267 | 267 | .byte_swap, |
| 268 | 268 | .bit_reverse, |
| 269 | 269 | .splat, |
| 270 | .error_set_has_value, | |
| 270 | 271 | => { |
| 271 | 272 | const o = air_datas[inst].ty_op; |
| 272 | 273 | if (o.operand == operand_ref) return matchOperandSmallIndex(l, inst, 0, .none); |
| ... | ... | @@ -842,6 +843,7 @@ fn analyzeInst( |
| 842 | 843 | .byte_swap, |
| 843 | 844 | .bit_reverse, |
| 844 | 845 | .splat, |
| 846 | .error_set_has_value, | |
| 845 | 847 | => { |
| 846 | 848 | const o = inst_datas[inst].ty_op; |
| 847 | 849 | return trackOperands(a, new_set, inst, main_tomb, .{ o.operand, .none, .none }); |
src/Sema.zig+3-10| ... | ... | @@ -17359,17 +17359,10 @@ fn zirErrSetCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDat |
| 17359 | 17359 | } |
| 17360 | 17360 | |
| 17361 | 17361 | try sema.requireRuntimeBlock(block, src, operand_src); |
| 17362 | if (block.wantSafety() and !dest_ty.isAnyError()) { | |
| 17362 | if (block.wantSafety() and !dest_ty.isAnyError() and sema.mod.comp.bin_file.options.use_llvm) { | |
| 17363 | 17363 | const err_int_inst = try block.addBitCast(Type.u16, operand); |
| 17364 | // TODO: Output a switch instead of chained OR's. | |
| 17365 | var found_match: Air.Inst.Ref = undefined; | |
| 17366 | for (dest_ty.errorSetNames()) |dest_err_name, i| { | |
| 17367 | const dest_err_int = (try sema.mod.getErrorValue(dest_err_name)).value; | |
| 17368 | const dest_err_int_inst = try sema.addIntUnsigned(Type.u16, dest_err_int); | |
| 17369 | const next_match = try block.addBinOp(.cmp_eq, dest_err_int_inst, err_int_inst); | |
| 17370 | found_match = if (i == 0) next_match else try block.addBinOp(.bool_or, found_match, next_match); | |
| 17371 | } | |
| 17372 | try sema.addSafetyCheck(block, found_match, .invalid_error_code); | |
| 17364 | const ok = try block.addTyOp(.error_set_has_value, dest_ty, err_int_inst); | |
| 17365 | try sema.addSafetyCheck(block, ok, .invalid_error_code); | |
| 17373 | 17366 | } |
| 17374 | 17367 | return block.addBitCast(dest_ty, operand); |
| 17375 | 17368 | } |
src/arch/aarch64/CodeGen.zig+1| ... | ... | @@ -778,6 +778,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { |
| 778 | 778 | => return self.fail("TODO implement optimized float mode", .{}), |
| 779 | 779 | |
| 780 | 780 | .is_named_enum_value => return self.fail("TODO implement is_named_enum_value", .{}), |
| 781 | .error_set_has_value => return self.fail("TODO implement error_set_has_value", .{}), | |
| 781 | 782 | |
| 782 | 783 | .wasm_memory_size => unreachable, |
| 783 | 784 | .wasm_memory_grow => unreachable, |
src/arch/arm/CodeGen.zig+1| ... | ... | @@ -769,6 +769,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { |
| 769 | 769 | => return self.fail("TODO implement optimized float mode", .{}), |
| 770 | 770 | |
| 771 | 771 | .is_named_enum_value => return self.fail("TODO implement is_named_enum_value", .{}), |
| 772 | .error_set_has_value => return self.fail("TODO implement error_set_has_value", .{}), | |
| 772 | 773 | |
| 773 | 774 | .wasm_memory_size => unreachable, |
| 774 | 775 | .wasm_memory_grow => unreachable, |
src/arch/riscv64/CodeGen.zig+1| ... | ... | @@ -694,6 +694,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { |
| 694 | 694 | => return self.fail("TODO implement optimized float mode", .{}), |
| 695 | 695 | |
| 696 | 696 | .is_named_enum_value => return self.fail("TODO implement is_named_enum_value", .{}), |
| 697 | .error_set_has_value => return self.fail("TODO implement error_set_has_value", .{}), | |
| 697 | 698 | |
| 698 | 699 | .wasm_memory_size => unreachable, |
| 699 | 700 | .wasm_memory_grow => unreachable, |
src/arch/sparc64/CodeGen.zig+1| ... | ... | @@ -706,6 +706,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { |
| 706 | 706 | => @panic("TODO implement optimized float mode"), |
| 707 | 707 | |
| 708 | 708 | .is_named_enum_value => @panic("TODO implement is_named_enum_value"), |
| 709 | .error_set_has_value => @panic("TODO implement error_set_has_value"), | |
| 709 | 710 | |
| 710 | 711 | .wasm_memory_size => unreachable, |
| 711 | 712 | .wasm_memory_grow => unreachable, |
src/arch/wasm/CodeGen.zig+1| ... | ... | @@ -1694,6 +1694,7 @@ fn genInst(self: *Self, inst: Air.Inst.Index) !WValue { |
| 1694 | 1694 | .err_return_trace, |
| 1695 | 1695 | .set_err_return_trace, |
| 1696 | 1696 | .is_named_enum_value, |
| 1697 | .error_set_has_value, | |
| 1697 | 1698 | => |tag| return self.fail("TODO: Implement wasm inst: {s}", .{@tagName(tag)}), |
| 1698 | 1699 | |
| 1699 | 1700 | .add_optimized, |
src/arch/x86_64/CodeGen.zig+1| ... | ... | @@ -776,6 +776,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { |
| 776 | 776 | => return self.fail("TODO implement optimized float mode", .{}), |
| 777 | 777 | |
| 778 | 778 | .is_named_enum_value => return self.fail("TODO implement is_named_enum_value", .{}), |
| 779 | .error_set_has_value => return self.fail("TODO implement error_set_has_value", .{}), | |
| 779 | 780 | |
| 780 | 781 | .wasm_memory_size => unreachable, |
| 781 | 782 | .wasm_memory_grow => unreachable, |
src/codegen/c.zig+1| ... | ... | @@ -1954,6 +1954,7 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO |
| 1954 | 1954 | => return f.fail("TODO implement optimized float mode", .{}), |
| 1955 | 1955 | |
| 1956 | 1956 | .is_named_enum_value => return f.fail("TODO: C backend: implement is_named_enum_value", .{}), |
| 1957 | .error_set_has_value => return f.fail("TODO: C backend: implement error_set_has_value", .{}), | |
| 1957 | 1958 | // zig fmt: on |
| 1958 | 1959 | }; |
| 1959 | 1960 | switch (result_value) { |
src/codegen/llvm.zig+48| ... | ... | @@ -4247,6 +4247,7 @@ pub const FuncGen = struct { |
| 4247 | 4247 | .prefetch => try self.airPrefetch(inst), |
| 4248 | 4248 | |
| 4249 | 4249 | .is_named_enum_value => try self.airIsNamedEnumValue(inst), |
| 4250 | .error_set_has_value => try self.airErrorSetHasValue(inst), | |
| 4250 | 4251 | |
| 4251 | 4252 | .reduce => try self.airReduce(inst, false), |
| 4252 | 4253 | .reduce_optimized => try self.airReduce(inst, true), |
| ... | ... | @@ -7983,6 +7984,53 @@ pub const FuncGen = struct { |
| 7983 | 7984 | } |
| 7984 | 7985 | } |
| 7985 | 7986 | |
| 7987 | fn airErrorSetHasValue(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value { | |
| 7988 | if (self.liveness.isUnused(inst)) return null; | |
| 7989 | ||
| 7990 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; | |
| 7991 | const operand = try self.resolveInst(ty_op.operand); | |
| 7992 | const error_set_ty = self.air.getRefType(ty_op.ty); | |
| 7993 | ||
| 7994 | const names = error_set_ty.errorSetNames(); | |
| 7995 | const valid_block = self.dg.context.appendBasicBlock(self.llvm_func, "Valid"); | |
| 7996 | const invalid_block = self.dg.context.appendBasicBlock(self.llvm_func, "Invalid"); | |
| 7997 | const end_block = self.context.appendBasicBlock(self.llvm_func, "End"); | |
| 7998 | const switch_instr = self.builder.buildSwitch(operand, invalid_block, @intCast(c_uint, names.len)); | |
| 7999 | ||
| 8000 | for (names) |name| { | |
| 8001 | const err_int = self.dg.module.global_error_set.get(name).?; | |
| 8002 | const this_tag_int_value = int: { | |
| 8003 | var tag_val_payload: Value.Payload.U64 = .{ | |
| 8004 | .base = .{ .tag = .int_u64 }, | |
| 8005 | .data = err_int, | |
| 8006 | }; | |
| 8007 | break :int try self.dg.lowerValue(.{ | |
| 8008 | .ty = Type.u16, | |
| 8009 | .val = Value.initPayload(&tag_val_payload.base), | |
| 8010 | }); | |
| 8011 | }; | |
| 8012 | switch_instr.addCase(this_tag_int_value, valid_block); | |
| 8013 | } | |
| 8014 | self.builder.positionBuilderAtEnd(valid_block); | |
| 8015 | _ = self.builder.buildBr(end_block); | |
| 8016 | ||
| 8017 | self.builder.positionBuilderAtEnd(invalid_block); | |
| 8018 | _ = self.builder.buildBr(end_block); | |
| 8019 | ||
| 8020 | self.builder.positionBuilderAtEnd(end_block); | |
| 8021 | ||
| 8022 | const llvm_type = self.dg.context.intType(1); | |
| 8023 | const incoming_values: [2]*const llvm.Value = .{ | |
| 8024 | llvm_type.constInt(1, .False), llvm_type.constInt(0, .False), | |
| 8025 | }; | |
| 8026 | const incoming_blocks: [2]*const llvm.BasicBlock = .{ | |
| 8027 | valid_block, invalid_block, | |
| 8028 | }; | |
| 8029 | const phi_node = self.builder.buildPhi(llvm_type, ""); | |
| 8030 | phi_node.addIncoming(&incoming_values, &incoming_blocks, 2); | |
| 8031 | return phi_node; | |
| 8032 | } | |
| 8033 | ||
| 7986 | 8034 | fn airIsNamedEnumValue(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value { |
| 7987 | 8035 | if (self.liveness.isUnused(inst)) return null; |
| 7988 | 8036 |
src/print_air.zig+1| ... | ... | @@ -243,6 +243,7 @@ const Writer = struct { |
| 243 | 243 | .popcount, |
| 244 | 244 | .byte_swap, |
| 245 | 245 | .bit_reverse, |
| 246 | .error_set_has_value, | |
| 246 | 247 | => try w.writeTyOp(s, inst), |
| 247 | 248 | |
| 248 | 249 | .block, |