| author | |
| committer | |
| log | c1ca16d779a3f3201a5a35a88eff188290b2091a |
| tree | f6af6b5ac4da7bb28c1b2821c835e51e5b797be4 |
| parent | 9d9e1a29911c0ecf92eb9db10027cf691cd4b07e |
5 files changed, 213 insertions(+), 134 deletions(-)
src/Module.zig+14-3| ... | ... | @@ -934,9 +934,12 @@ pub const Decl = struct { |
| 934 | 934 | |
| 935 | 935 | pub fn isExtern(decl: Decl) bool { |
| 936 | 936 | assert(decl.has_tv); |
| 937 | return switch (decl.val.tag()) { | |
| 938 | .extern_fn => true, | |
| 939 | .variable => decl.val.castTag(.variable).?.data.init.ip_index == .unreachable_value, | |
| 937 | return switch (decl.val.ip_index) { | |
| 938 | .none => switch (decl.val.tag()) { | |
| 939 | .extern_fn => true, | |
| 940 | .variable => decl.val.castTag(.variable).?.data.init.ip_index == .unreachable_value, | |
| 941 | else => false, | |
| 942 | }, | |
| 940 | 943 | else => false, |
| 941 | 944 | }; |
| 942 | 945 | } |
| ... | ... | @@ -6833,6 +6836,10 @@ pub fn intType(mod: *Module, signedness: std.builtin.Signedness, bits: u16) Allo |
| 6833 | 6836 | } |
| 6834 | 6837 | |
| 6835 | 6838 | pub fn arrayType(mod: *Module, info: InternPool.Key.ArrayType) Allocator.Error!Type { |
| 6839 | if (std.debug.runtime_safety and info.sentinel != .none) { | |
| 6840 | const sent_ty = mod.intern_pool.indexToKey(info.sentinel).typeOf(); | |
| 6841 | assert(sent_ty == info.child); | |
| 6842 | } | |
| 6836 | 6843 | const i = try intern(mod, .{ .array_type = info }); |
| 6837 | 6844 | return i.toType(); |
| 6838 | 6845 | } |
| ... | ... | @@ -6848,6 +6855,10 @@ pub fn optionalType(mod: *Module, child_type: InternPool.Index) Allocator.Error! |
| 6848 | 6855 | } |
| 6849 | 6856 | |
| 6850 | 6857 | pub fn ptrType(mod: *Module, info: InternPool.Key.PtrType) Allocator.Error!Type { |
| 6858 | if (std.debug.runtime_safety and info.sentinel != .none) { | |
| 6859 | const sent_ty = mod.intern_pool.indexToKey(info.sentinel).typeOf(); | |
| 6860 | assert(sent_ty == info.elem_type); | |
| 6861 | } | |
| 6851 | 6862 | const i = try intern(mod, .{ .ptr_type = info }); |
| 6852 | 6863 | return i.toType(); |
| 6853 | 6864 | } |
src/Sema.zig+58-41| ... | ... | @@ -5146,7 +5146,7 @@ fn addStrLit(sema: *Sema, block: *Block, zir_bytes: []const u8) CompileError!Air |
| 5146 | 5146 | defer anon_decl.deinit(); |
| 5147 | 5147 | |
| 5148 | 5148 | const decl_index = try anon_decl.finish( |
| 5149 | try Type.array(anon_decl.arena(), gop.key_ptr.len, Value.zero, Type.u8, mod), | |
| 5149 | try Type.array(anon_decl.arena(), gop.key_ptr.len, try mod.intValue(Type.u8, 0), Type.u8, mod), | |
| 5150 | 5150 | try Value.Tag.str_lit.create(anon_decl.arena(), gop.key_ptr.*), |
| 5151 | 5151 | 0, // default alignment |
| 5152 | 5152 | ); |
| ... | ... | @@ -15567,7 +15567,7 @@ fn zirSizeOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. |
| 15567 | 15567 | => {}, |
| 15568 | 15568 | } |
| 15569 | 15569 | const val = try ty.lazyAbiSize(mod, sema.arena); |
| 15570 | if (val.tag() == .lazy_size) { | |
| 15570 | if (val.ip_index == .none and val.tag() == .lazy_size) { | |
| 15571 | 15571 | try sema.queueFullTypeResolution(ty); |
| 15572 | 15572 | } |
| 15573 | 15573 | return sema.addConstant(Type.comptime_int, val); |
| ... | ... | @@ -16006,8 +16006,8 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 16006 | 16006 | sema.arena, |
| 16007 | 16007 | @enumToInt(info.signedness), |
| 16008 | 16008 | ); |
| 16009 | // bits: comptime_int, | |
| 16010 | field_values[1] = try mod.intValue(Type.comptime_int, info.bits); | |
| 16009 | // bits: u16, | |
| 16010 | field_values[1] = try mod.intValue(Type.u16, info.bits); | |
| 16011 | 16011 | |
| 16012 | 16012 | return sema.addConstant( |
| 16013 | 16013 | type_info_ty, |
| ... | ... | @@ -16019,8 +16019,8 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 16019 | 16019 | }, |
| 16020 | 16020 | .Float => { |
| 16021 | 16021 | const field_values = try sema.arena.alloc(Value, 1); |
| 16022 | // bits: comptime_int, | |
| 16023 | field_values[0] = try mod.intValue(Type.comptime_int, ty.bitSize(mod)); | |
| 16022 | // bits: u16, | |
| 16023 | field_values[0] = try mod.intValue(Type.u16, ty.bitSize(mod)); | |
| 16024 | 16024 | |
| 16025 | 16025 | return sema.addConstant( |
| 16026 | 16026 | type_info_ty, |
| ... | ... | @@ -25957,7 +25957,21 @@ fn coerceExtra( |
| 25957 | 25957 | if (!opts.report_err) return error.NotCoercible; |
| 25958 | 25958 | return sema.fail(block, inst_src, "type '{}' cannot represent integer value '{}'", .{ dest_ty.fmt(sema.mod), val.fmtValue(inst_ty, sema.mod) }); |
| 25959 | 25959 | } |
| 25960 | return try sema.addConstant(dest_ty, val); | |
| 25960 | const key = mod.intern_pool.indexToKey(val.ip_index); | |
| 25961 | // If the int is represented as a bigint, copy it so we can safely pass it to `mod.intern` | |
| 25962 | const int_storage: InternPool.Key.Int.Storage = switch (key.int.storage) { | |
| 25963 | .u64 => |x| .{ .u64 = x }, | |
| 25964 | .i64 => |x| .{ .i64 = x }, | |
| 25965 | .big_int => |big_int| .{ .big_int = .{ | |
| 25966 | .limbs = try sema.arena.dupe(std.math.big.Limb, big_int.limbs), | |
| 25967 | .positive = big_int.positive, | |
| 25968 | } }, | |
| 25969 | }; | |
| 25970 | const new_val = try mod.intern(.{ .int = .{ | |
| 25971 | .ty = dest_ty.ip_index, | |
| 25972 | .storage = int_storage, | |
| 25973 | } }); | |
| 25974 | return try sema.addConstant(dest_ty, new_val.toValue()); | |
| 25961 | 25975 | } |
| 25962 | 25976 | if (dest_ty.zigTypeTag(mod) == .ComptimeInt) { |
| 25963 | 25977 | if (!opts.report_err) return error.NotCoercible; |
| ... | ... | @@ -31061,39 +31075,42 @@ pub fn resolveFnTypes(sema: *Sema, fn_info: Type.Payload.Function.Data) CompileE |
| 31061 | 31075 | /// Make it so that calling hash() and eql() on `val` will not assert due |
| 31062 | 31076 | /// to a type not having its layout resolved. |
| 31063 | 31077 | fn resolveLazyValue(sema: *Sema, val: Value) CompileError!void { |
| 31064 | switch (val.tag()) { | |
| 31065 | .lazy_align => { | |
| 31066 | const ty = val.castTag(.lazy_align).?.data; | |
| 31067 | return sema.resolveTypeLayout(ty); | |
| 31068 | }, | |
| 31069 | .lazy_size => { | |
| 31070 | const ty = val.castTag(.lazy_size).?.data; | |
| 31071 | return sema.resolveTypeLayout(ty); | |
| 31072 | }, | |
| 31073 | .comptime_field_ptr => { | |
| 31074 | const field_ptr = val.castTag(.comptime_field_ptr).?.data; | |
| 31075 | return sema.resolveLazyValue(field_ptr.field_val); | |
| 31076 | }, | |
| 31077 | .eu_payload, | |
| 31078 | .opt_payload, | |
| 31079 | => { | |
| 31080 | const sub_val = val.cast(Value.Payload.SubValue).?.data; | |
| 31081 | return sema.resolveLazyValue(sub_val); | |
| 31082 | }, | |
| 31083 | .@"union" => { | |
| 31084 | const union_val = val.castTag(.@"union").?.data; | |
| 31085 | return sema.resolveLazyValue(union_val.val); | |
| 31086 | }, | |
| 31087 | .aggregate => { | |
| 31088 | const aggregate = val.castTag(.aggregate).?.data; | |
| 31089 | for (aggregate) |elem_val| { | |
| 31090 | try sema.resolveLazyValue(elem_val); | |
| 31091 | } | |
| 31092 | }, | |
| 31093 | .slice => { | |
| 31094 | const slice = val.castTag(.slice).?.data; | |
| 31095 | try sema.resolveLazyValue(slice.ptr); | |
| 31096 | return sema.resolveLazyValue(slice.len); | |
| 31078 | switch (val.ip_index) { | |
| 31079 | .none => switch (val.tag()) { | |
| 31080 | .lazy_align => { | |
| 31081 | const ty = val.castTag(.lazy_align).?.data; | |
| 31082 | return sema.resolveTypeLayout(ty); | |
| 31083 | }, | |
| 31084 | .lazy_size => { | |
| 31085 | const ty = val.castTag(.lazy_size).?.data; | |
| 31086 | return sema.resolveTypeLayout(ty); | |
| 31087 | }, | |
| 31088 | .comptime_field_ptr => { | |
| 31089 | const field_ptr = val.castTag(.comptime_field_ptr).?.data; | |
| 31090 | return sema.resolveLazyValue(field_ptr.field_val); | |
| 31091 | }, | |
| 31092 | .eu_payload, | |
| 31093 | .opt_payload, | |
| 31094 | => { | |
| 31095 | const sub_val = val.cast(Value.Payload.SubValue).?.data; | |
| 31096 | return sema.resolveLazyValue(sub_val); | |
| 31097 | }, | |
| 31098 | .@"union" => { | |
| 31099 | const union_val = val.castTag(.@"union").?.data; | |
| 31100 | return sema.resolveLazyValue(union_val.val); | |
| 31101 | }, | |
| 31102 | .aggregate => { | |
| 31103 | const aggregate = val.castTag(.aggregate).?.data; | |
| 31104 | for (aggregate) |elem_val| { | |
| 31105 | try sema.resolveLazyValue(elem_val); | |
| 31106 | } | |
| 31107 | }, | |
| 31108 | .slice => { | |
| 31109 | const slice = val.castTag(.slice).?.data; | |
| 31110 | try sema.resolveLazyValue(slice.ptr); | |
| 31111 | return sema.resolveLazyValue(slice.len); | |
| 31112 | }, | |
| 31113 | else => return, | |
| 31097 | 31114 | }, |
| 31098 | 31115 | else => return, |
| 31099 | 31116 | } |
| ... | ... | @@ -31200,7 +31217,7 @@ fn resolveStructLayout(sema: *Sema, ty: Type) CompileError!void { |
| 31200 | 31217 | }; |
| 31201 | 31218 | |
| 31202 | 31219 | for (struct_obj.fields.values(), 0..) |field, i| { |
| 31203 | optimized_order[i] = if (!(try sema.typeHasRuntimeBits(field.ty))) | |
| 31220 | optimized_order[i] = if (try sema.typeHasRuntimeBits(field.ty)) | |
| 31204 | 31221 | @intCast(u32, i) |
| 31205 | 31222 | else |
| 31206 | 31223 | Module.Struct.omitted_field; |
src/codegen/llvm.zig+1-1| ... | ... | @@ -2481,7 +2481,7 @@ pub const DeclGen = struct { |
| 2481 | 2481 | log.debug("gen: {s} type: {}, value: {}", .{ |
| 2482 | 2482 | decl.name, decl.ty.fmtDebug(), decl.val.fmtDebug(), |
| 2483 | 2483 | }); |
| 2484 | assert(decl.val.tag() != .function); | |
| 2484 | assert(decl.val.ip_index != .none or decl.val.tag() != .function); | |
| 2485 | 2485 | if (decl.val.castTag(.extern_fn)) |extern_fn| { |
| 2486 | 2486 | _ = try dg.resolveLlvmFunction(extern_fn.data.owner_decl); |
| 2487 | 2487 | } else { |
src/type.zig+82-39| ... | ... | @@ -2471,7 +2471,7 @@ pub const Type = struct { |
| 2471 | 2471 | pub fn lazyAbiSize(ty: Type, mod: *Module, arena: Allocator) !Value { |
| 2472 | 2472 | switch (try ty.abiSizeAdvanced(mod, .{ .lazy = arena })) { |
| 2473 | 2473 | .val => |val| return val, |
| 2474 | .scalar => |x| return mod.intValue(ty, x), | |
| 2474 | .scalar => |x| return mod.intValue(Type.comptime_int, x), | |
| 2475 | 2475 | } |
| 2476 | 2476 | } |
| 2477 | 2477 | |
| ... | ... | @@ -2504,8 +2504,20 @@ pub const Type = struct { |
| 2504 | 2504 | if (int_type.bits == 0) return AbiSizeAdvanced{ .scalar = 0 }; |
| 2505 | 2505 | return AbiSizeAdvanced{ .scalar = intAbiSize(int_type.bits, target) }; |
| 2506 | 2506 | }, |
| 2507 | .ptr_type => @panic("TODO"), | |
| 2508 | .array_type => @panic("TODO"), | |
| 2507 | .ptr_type => |ptr_type| switch (ptr_type.size) { | |
| 2508 | .Slice => return .{ .scalar = @divExact(target.ptrBitWidth(), 8) * 2 }, | |
| 2509 | else => return .{ .scalar = @divExact(target.ptrBitWidth(), 8) }, | |
| 2510 | }, | |
| 2511 | .array_type => |array_type| { | |
| 2512 | const len = array_type.len + @boolToInt(array_type.sentinel != .none); | |
| 2513 | switch (try array_type.child.toType().abiSizeAdvanced(mod, strat)) { | |
| 2514 | .scalar => |elem_size| return .{ .scalar = len * elem_size }, | |
| 2515 | .val => switch (strat) { | |
| 2516 | .sema, .eager => unreachable, | |
| 2517 | .lazy => |arena| return .{ .val = try Value.Tag.lazy_size.create(arena, ty) }, | |
| 2518 | }, | |
| 2519 | } | |
| 2520 | }, | |
| 2509 | 2521 | .vector_type => |vector_type| { |
| 2510 | 2522 | const opt_sema = switch (strat) { |
| 2511 | 2523 | .sema => |sema| sema, |
| ... | ... | @@ -2528,7 +2540,7 @@ pub const Type = struct { |
| 2528 | 2540 | return AbiSizeAdvanced{ .scalar = result }; |
| 2529 | 2541 | }, |
| 2530 | 2542 | |
| 2531 | .opt_type => @panic("TODO"), | |
| 2543 | .opt_type => return ty.abiSizeAdvancedOptional(mod, strat), | |
| 2532 | 2544 | .error_union_type => @panic("TODO"), |
| 2533 | 2545 | .simple_type => |t| switch (t) { |
| 2534 | 2546 | .bool, |
| ... | ... | @@ -2698,39 +2710,7 @@ pub const Type = struct { |
| 2698 | 2710 | .error_set_single, |
| 2699 | 2711 | => return AbiSizeAdvanced{ .scalar = 2 }, |
| 2700 | 2712 | |
| 2701 | .optional => { | |
| 2702 | const child_type = ty.optionalChild(mod); | |
| 2703 | ||
| 2704 | if (child_type.isNoReturn()) { | |
| 2705 | return AbiSizeAdvanced{ .scalar = 0 }; | |
| 2706 | } | |
| 2707 | ||
| 2708 | if (!(child_type.hasRuntimeBitsAdvanced(mod, false, strat) catch |err| switch (err) { | |
| 2709 | error.NeedLazy => return AbiSizeAdvanced{ .val = try Value.Tag.lazy_size.create(strat.lazy, ty) }, | |
| 2710 | else => |e| return e, | |
| 2711 | })) return AbiSizeAdvanced{ .scalar = 1 }; | |
| 2712 | ||
| 2713 | if (ty.optionalReprIsPayload(mod)) { | |
| 2714 | return abiSizeAdvanced(child_type, mod, strat); | |
| 2715 | } | |
| 2716 | ||
| 2717 | const payload_size = switch (try child_type.abiSizeAdvanced(mod, strat)) { | |
| 2718 | .scalar => |elem_size| elem_size, | |
| 2719 | .val => switch (strat) { | |
| 2720 | .sema => unreachable, | |
| 2721 | .eager => unreachable, | |
| 2722 | .lazy => |arena| return AbiSizeAdvanced{ .val = try Value.Tag.lazy_size.create(arena, ty) }, | |
| 2723 | }, | |
| 2724 | }; | |
| 2725 | ||
| 2726 | // Optional types are represented as a struct with the child type as the first | |
| 2727 | // field and a boolean as the second. Since the child type's abi alignment is | |
| 2728 | // guaranteed to be >= that of bool's (1 byte) the added size is exactly equal | |
| 2729 | // to the child type's ABI alignment. | |
| 2730 | return AbiSizeAdvanced{ | |
| 2731 | .scalar = child_type.abiAlignment(mod) + payload_size, | |
| 2732 | }; | |
| 2733 | }, | |
| 2713 | .optional => return ty.abiSizeAdvancedOptional(mod, strat), | |
| 2734 | 2714 | |
| 2735 | 2715 | .error_union => { |
| 2736 | 2716 | // This code needs to be kept in sync with the equivalent switch prong |
| ... | ... | @@ -2791,6 +2771,44 @@ pub const Type = struct { |
| 2791 | 2771 | return AbiSizeAdvanced{ .scalar = union_obj.abiSize(mod, have_tag) }; |
| 2792 | 2772 | } |
| 2793 | 2773 | |
| 2774 | fn abiSizeAdvancedOptional( | |
| 2775 | ty: Type, | |
| 2776 | mod: *const Module, | |
| 2777 | strat: AbiAlignmentAdvancedStrat, | |
| 2778 | ) Module.CompileError!AbiSizeAdvanced { | |
| 2779 | const child_ty = ty.optionalChild(mod); | |
| 2780 | ||
| 2781 | if (child_ty.isNoReturn()) { | |
| 2782 | return AbiSizeAdvanced{ .scalar = 0 }; | |
| 2783 | } | |
| 2784 | ||
| 2785 | if (!(child_ty.hasRuntimeBitsAdvanced(mod, false, strat) catch |err| switch (err) { | |
| 2786 | error.NeedLazy => return AbiSizeAdvanced{ .val = try Value.Tag.lazy_size.create(strat.lazy, ty) }, | |
| 2787 | else => |e| return e, | |
| 2788 | })) return AbiSizeAdvanced{ .scalar = 1 }; | |
| 2789 | ||
| 2790 | if (ty.optionalReprIsPayload(mod)) { | |
| 2791 | return abiSizeAdvanced(child_ty, mod, strat); | |
| 2792 | } | |
| 2793 | ||
| 2794 | const payload_size = switch (try child_ty.abiSizeAdvanced(mod, strat)) { | |
| 2795 | .scalar => |elem_size| elem_size, | |
| 2796 | .val => switch (strat) { | |
| 2797 | .sema => unreachable, | |
| 2798 | .eager => unreachable, | |
| 2799 | .lazy => |arena| return AbiSizeAdvanced{ .val = try Value.Tag.lazy_size.create(arena, ty) }, | |
| 2800 | }, | |
| 2801 | }; | |
| 2802 | ||
| 2803 | // Optional types are represented as a struct with the child type as the first | |
| 2804 | // field and a boolean as the second. Since the child type's abi alignment is | |
| 2805 | // guaranteed to be >= that of bool's (1 byte) the added size is exactly equal | |
| 2806 | // to the child type's ABI alignment. | |
| 2807 | return AbiSizeAdvanced{ | |
| 2808 | .scalar = child_ty.abiAlignment(mod) + payload_size, | |
| 2809 | }; | |
| 2810 | } | |
| 2811 | ||
| 2794 | 2812 | fn intAbiSize(bits: u16, target: Target) u64 { |
| 2795 | 2813 | const alignment = intAbiAlignment(bits, target); |
| 2796 | 2814 | return std.mem.alignForwardGeneric(u64, @intCast(u16, (@as(u17, bits) + 7) / 8), alignment); |
| ... | ... | @@ -2819,8 +2837,19 @@ pub const Type = struct { |
| 2819 | 2837 | |
| 2820 | 2838 | if (ty.ip_index != .none) switch (mod.intern_pool.indexToKey(ty.ip_index)) { |
| 2821 | 2839 | .int_type => |int_type| return int_type.bits, |
| 2822 | .ptr_type => @panic("TODO"), | |
| 2823 | .array_type => @panic("TODO"), | |
| 2840 | .ptr_type => |ptr_type| switch (ptr_type.size) { | |
| 2841 | .Slice => return target.ptrBitWidth() * 2, | |
| 2842 | else => return target.ptrBitWidth() * 2, | |
| 2843 | }, | |
| 2844 | .array_type => |array_type| { | |
| 2845 | const len = array_type.len + @boolToInt(array_type.sentinel != .none); | |
| 2846 | if (len == 0) return 0; | |
| 2847 | const elem_ty = array_type.child.toType(); | |
| 2848 | const elem_size = std.math.max(elem_ty.abiAlignment(mod), elem_ty.abiSize(mod)); | |
| 2849 | if (elem_size == 0) return 0; | |
| 2850 | const elem_bit_size = try bitSizeAdvanced(elem_ty, mod, opt_sema); | |
| 2851 | return (len - 1) * 8 * elem_size + elem_bit_size; | |
| 2852 | }, | |
| 2824 | 2853 | .vector_type => |vector_type| { |
| 2825 | 2854 | const child_ty = vector_type.child.toType(); |
| 2826 | 2855 | const elem_bit_size = try bitSizeAdvanced(child_ty, mod, opt_sema); |
| ... | ... | @@ -3208,6 +3237,20 @@ pub const Type = struct { |
| 3208 | 3237 | |
| 3209 | 3238 | /// See also `isPtrLikeOptional`. |
| 3210 | 3239 | pub fn optionalReprIsPayload(ty: Type, mod: *const Module) bool { |
| 3240 | if (ty.ip_index != .none) return switch (mod.intern_pool.indexToKey(ty.ip_index)) { | |
| 3241 | .opt_type => |child| switch (child.toType().zigTypeTag(mod)) { | |
| 3242 | .Pointer => { | |
| 3243 | const info = child.toType().ptrInfo(mod); | |
| 3244 | switch (info.size) { | |
| 3245 | .C => return false, | |
| 3246 | else => return !info.@"allowzero", | |
| 3247 | } | |
| 3248 | }, | |
| 3249 | .ErrorSet => true, | |
| 3250 | else => false, | |
| 3251 | }, | |
| 3252 | else => false, | |
| 3253 | }; | |
| 3211 | 3254 | switch (ty.tag()) { |
| 3212 | 3255 | .optional => { |
| 3213 | 3256 | const child_ty = ty.castTag(.optional).?.data; |
src/value.zig+58-50| ... | ... | @@ -1832,35 +1832,37 @@ pub const Value = struct { |
| 1832 | 1832 | } |
| 1833 | 1833 | } |
| 1834 | 1834 | |
| 1835 | switch (lhs.tag()) { | |
| 1836 | .repeated => return lhs.castTag(.repeated).?.data.compareAllWithZeroAdvancedExtra(op, mod, opt_sema), | |
| 1837 | .aggregate => { | |
| 1838 | for (lhs.castTag(.aggregate).?.data) |elem_val| { | |
| 1839 | if (!(try elem_val.compareAllWithZeroAdvancedExtra(op, mod, opt_sema))) return false; | |
| 1840 | } | |
| 1841 | return true; | |
| 1842 | }, | |
| 1843 | .empty_array => return true, | |
| 1844 | .str_lit => { | |
| 1845 | const str_lit = lhs.castTag(.str_lit).?.data; | |
| 1846 | const bytes = mod.string_literal_bytes.items[str_lit.index..][0..str_lit.len]; | |
| 1847 | for (bytes) |byte| { | |
| 1848 | if (!std.math.compare(byte, op, 0)) return false; | |
| 1849 | } | |
| 1850 | return true; | |
| 1851 | }, | |
| 1852 | .bytes => { | |
| 1853 | const bytes = lhs.castTag(.bytes).?.data; | |
| 1854 | for (bytes) |byte| { | |
| 1855 | if (!std.math.compare(byte, op, 0)) return false; | |
| 1856 | } | |
| 1857 | return true; | |
| 1835 | switch (lhs.ip_index) { | |
| 1836 | .none => switch (lhs.tag()) { | |
| 1837 | .repeated => return lhs.castTag(.repeated).?.data.compareAllWithZeroAdvancedExtra(op, mod, opt_sema), | |
| 1838 | .aggregate => { | |
| 1839 | for (lhs.castTag(.aggregate).?.data) |elem_val| { | |
| 1840 | if (!(try elem_val.compareAllWithZeroAdvancedExtra(op, mod, opt_sema))) return false; | |
| 1841 | } | |
| 1842 | return true; | |
| 1843 | }, | |
| 1844 | .str_lit => { | |
| 1845 | const str_lit = lhs.castTag(.str_lit).?.data; | |
| 1846 | const bytes = mod.string_literal_bytes.items[str_lit.index..][0..str_lit.len]; | |
| 1847 | for (bytes) |byte| { | |
| 1848 | if (!std.math.compare(byte, op, 0)) return false; | |
| 1849 | } | |
| 1850 | return true; | |
| 1851 | }, | |
| 1852 | .bytes => { | |
| 1853 | const bytes = lhs.castTag(.bytes).?.data; | |
| 1854 | for (bytes) |byte| { | |
| 1855 | if (!std.math.compare(byte, op, 0)) return false; | |
| 1856 | } | |
| 1857 | return true; | |
| 1858 | }, | |
| 1859 | .float_16 => if (std.math.isNan(lhs.castTag(.float_16).?.data)) return op == .neq, | |
| 1860 | .float_32 => if (std.math.isNan(lhs.castTag(.float_32).?.data)) return op == .neq, | |
| 1861 | .float_64 => if (std.math.isNan(lhs.castTag(.float_64).?.data)) return op == .neq, | |
| 1862 | .float_80 => if (std.math.isNan(lhs.castTag(.float_80).?.data)) return op == .neq, | |
| 1863 | .float_128 => if (std.math.isNan(lhs.castTag(.float_128).?.data)) return op == .neq, | |
| 1864 | else => {}, | |
| 1858 | 1865 | }, |
| 1859 | .float_16 => if (std.math.isNan(lhs.castTag(.float_16).?.data)) return op == .neq, | |
| 1860 | .float_32 => if (std.math.isNan(lhs.castTag(.float_32).?.data)) return op == .neq, | |
| 1861 | .float_64 => if (std.math.isNan(lhs.castTag(.float_64).?.data)) return op == .neq, | |
| 1862 | .float_80 => if (std.math.isNan(lhs.castTag(.float_80).?.data)) return op == .neq, | |
| 1863 | .float_128 => if (std.math.isNan(lhs.castTag(.float_128).?.data)) return op == .neq, | |
| 1864 | 1866 | else => {}, |
| 1865 | 1867 | } |
| 1866 | 1868 | return (try orderAgainstZeroAdvanced(lhs, mod, opt_sema)).compare(op); |
| ... | ... | @@ -2404,37 +2406,43 @@ pub const Value = struct { |
| 2404 | 2406 | }; |
| 2405 | 2407 | |
| 2406 | 2408 | pub fn isComptimeMutablePtr(val: Value) bool { |
| 2407 | return switch (val.tag()) { | |
| 2408 | .decl_ref_mut, .comptime_field_ptr => true, | |
| 2409 | .elem_ptr => isComptimeMutablePtr(val.castTag(.elem_ptr).?.data.array_ptr), | |
| 2410 | .field_ptr => isComptimeMutablePtr(val.castTag(.field_ptr).?.data.container_ptr), | |
| 2411 | .eu_payload_ptr => isComptimeMutablePtr(val.castTag(.eu_payload_ptr).?.data.container_ptr), | |
| 2412 | .opt_payload_ptr => isComptimeMutablePtr(val.castTag(.opt_payload_ptr).?.data.container_ptr), | |
| 2413 | .slice => isComptimeMutablePtr(val.castTag(.slice).?.data.ptr), | |
| 2409 | return switch (val.ip_index) { | |
| 2410 | .none => switch (val.tag()) { | |
| 2411 | .decl_ref_mut, .comptime_field_ptr => true, | |
| 2412 | .elem_ptr => isComptimeMutablePtr(val.castTag(.elem_ptr).?.data.array_ptr), | |
| 2413 | .field_ptr => isComptimeMutablePtr(val.castTag(.field_ptr).?.data.container_ptr), | |
| 2414 | .eu_payload_ptr => isComptimeMutablePtr(val.castTag(.eu_payload_ptr).?.data.container_ptr), | |
| 2415 | .opt_payload_ptr => isComptimeMutablePtr(val.castTag(.opt_payload_ptr).?.data.container_ptr), | |
| 2416 | .slice => isComptimeMutablePtr(val.castTag(.slice).?.data.ptr), | |
| 2414 | 2417 | |
| 2418 | else => false, | |
| 2419 | }, | |
| 2415 | 2420 | else => false, |
| 2416 | 2421 | }; |
| 2417 | 2422 | } |
| 2418 | 2423 | |
| 2419 | 2424 | pub fn canMutateComptimeVarState(val: Value) bool { |
| 2420 | 2425 | if (val.isComptimeMutablePtr()) return true; |
| 2421 | switch (val.tag()) { | |
| 2422 | .repeated => return val.castTag(.repeated).?.data.canMutateComptimeVarState(), | |
| 2423 | .eu_payload => return val.castTag(.eu_payload).?.data.canMutateComptimeVarState(), | |
| 2424 | .eu_payload_ptr => return val.castTag(.eu_payload_ptr).?.data.container_ptr.canMutateComptimeVarState(), | |
| 2425 | .opt_payload => return val.castTag(.opt_payload).?.data.canMutateComptimeVarState(), | |
| 2426 | .opt_payload_ptr => return val.castTag(.opt_payload_ptr).?.data.container_ptr.canMutateComptimeVarState(), | |
| 2427 | .aggregate => { | |
| 2428 | const fields = val.castTag(.aggregate).?.data; | |
| 2429 | for (fields) |field| { | |
| 2430 | if (field.canMutateComptimeVarState()) return true; | |
| 2431 | } | |
| 2432 | return false; | |
| 2426 | return switch (val.ip_index) { | |
| 2427 | .none => switch (val.tag()) { | |
| 2428 | .repeated => return val.castTag(.repeated).?.data.canMutateComptimeVarState(), | |
| 2429 | .eu_payload => return val.castTag(.eu_payload).?.data.canMutateComptimeVarState(), | |
| 2430 | .eu_payload_ptr => return val.castTag(.eu_payload_ptr).?.data.container_ptr.canMutateComptimeVarState(), | |
| 2431 | .opt_payload => return val.castTag(.opt_payload).?.data.canMutateComptimeVarState(), | |
| 2432 | .opt_payload_ptr => return val.castTag(.opt_payload_ptr).?.data.container_ptr.canMutateComptimeVarState(), | |
| 2433 | .aggregate => { | |
| 2434 | const fields = val.castTag(.aggregate).?.data; | |
| 2435 | for (fields) |field| { | |
| 2436 | if (field.canMutateComptimeVarState()) return true; | |
| 2437 | } | |
| 2438 | return false; | |
| 2439 | }, | |
| 2440 | .@"union" => return val.cast(Payload.Union).?.data.val.canMutateComptimeVarState(), | |
| 2441 | .slice => return val.castTag(.slice).?.data.ptr.canMutateComptimeVarState(), | |
| 2442 | else => return false, | |
| 2433 | 2443 | }, |
| 2434 | .@"union" => return val.cast(Payload.Union).?.data.val.canMutateComptimeVarState(), | |
| 2435 | .slice => return val.castTag(.slice).?.data.ptr.canMutateComptimeVarState(), | |
| 2436 | 2444 | else => return false, |
| 2437 | } | |
| 2445 | }; | |
| 2438 | 2446 | } |
| 2439 | 2447 | |
| 2440 | 2448 | /// Gets the decl referenced by this pointer. If the pointer does not point |