| ... | @@ -28115,6 +28115,50 @@ fn coerceInMemoryAllowed( | ... | @@ -28115,6 +28115,50 @@ fn coerceInMemoryAllowed( |
| 28115 | return .ok; | 28115 | return .ok; |
| 28116 | } | 28116 | } |
| 28117 | | 28117 | |
| | 28118 | // Arrays <-> Vectors |
| | 28119 | if ((dest_tag == .Vector and src_tag == .Array) or |
| | 28120 | (dest_tag == .Array and src_tag == .Vector)) |
| | 28121 | { |
| | 28122 | const dest_len = dest_ty.arrayLen(mod); |
| | 28123 | const src_len = src_ty.arrayLen(mod); |
| | 28124 | if (dest_len != src_len) { |
| | 28125 | return InMemoryCoercionResult{ .array_len = .{ |
| | 28126 | .actual = src_len, |
| | 28127 | .wanted = dest_len, |
| | 28128 | } }; |
| | 28129 | } |
| | 28130 | |
| | 28131 | const dest_elem_ty = dest_ty.childType(mod); |
| | 28132 | const src_elem_ty = src_ty.childType(mod); |
| | 28133 | const child = try sema.coerceInMemoryAllowed(block, dest_elem_ty, src_elem_ty, dest_is_mut, target, dest_src, src_src); |
| | 28134 | if (child != .ok) { |
| | 28135 | return InMemoryCoercionResult{ .array_elem = .{ |
| | 28136 | .child = try child.dupe(sema.arena), |
| | 28137 | .actual = src_elem_ty, |
| | 28138 | .wanted = dest_elem_ty, |
| | 28139 | } }; |
| | 28140 | } |
| | 28141 | |
| | 28142 | if (dest_tag == .Array) { |
| | 28143 | const dest_info = dest_ty.arrayInfo(mod); |
| | 28144 | if (dest_info.sentinel != null) { |
| | 28145 | return InMemoryCoercionResult{ .array_sentinel = .{ |
| | 28146 | .actual = Value.@"unreachable", |
| | 28147 | .wanted = dest_info.sentinel.?, |
| | 28148 | .ty = dest_info.elem_type, |
| | 28149 | } }; |
| | 28150 | } |
| | 28151 | } |
| | 28152 | |
| | 28153 | // The memory layout of @Vector(N, iM) is the same as the integer type i(N*M), |
| | 28154 | // that is to say, the padding bits are not in the same place as the array [N]iM. |
| | 28155 | // If there's no padding, the bitcast is possible. |
| | 28156 | const elem_bit_size = dest_elem_ty.bitSize(mod); |
| | 28157 | const elem_abi_byte_size = dest_elem_ty.abiSize(mod); |
| | 28158 | if (elem_abi_byte_size * 8 == elem_bit_size) |
| | 28159 | return .ok; |
| | 28160 | } |
| | 28161 | |
| 28118 | // Optionals | 28162 | // Optionals |
| 28119 | if (dest_tag == .Optional and src_tag == .Optional) { | 28163 | if (dest_tag == .Optional and src_tag == .Optional) { |
| 28120 | if ((maybe_dest_ptr_ty != null) != (maybe_src_ptr_ty != null)) { | 28164 | if ((maybe_dest_ptr_ty != null) != (maybe_src_ptr_ty != null)) { |
| ... | @@ -30005,10 +30049,22 @@ fn coerceArrayLike( | ... | @@ -30005,10 +30049,22 @@ fn coerceArrayLike( |
| 30005 | ) !Air.Inst.Ref { | 30049 | ) !Air.Inst.Ref { |
| 30006 | const mod = sema.mod; | 30050 | const mod = sema.mod; |
| 30007 | const inst_ty = sema.typeOf(inst); | 30051 | const inst_ty = sema.typeOf(inst); |
| 30008 | const inst_len = inst_ty.arrayLen(mod); | | |
| 30009 | const dest_len = try sema.usizeCast(block, dest_ty_src, dest_ty.arrayLen(mod)); | | |
| 30010 | const target = mod.getTarget(); | 30052 | const target = mod.getTarget(); |
| 30011 | | 30053 | |
| | 30054 | // try coercion of the whole array |
| | 30055 | const in_memory_result = try sema.coerceInMemoryAllowed(block, dest_ty, inst_ty, false, target, dest_ty_src, inst_src); |
| | 30056 | if (in_memory_result == .ok) { |
| | 30057 | if (try sema.resolveMaybeUndefVal(inst)) |inst_val| { |
| | 30058 | // These types share the same comptime value representation. |
| | 30059 | return sema.coerceInMemory(inst_val, dest_ty); |
| | 30060 | } |
| | 30061 | try sema.requireRuntimeBlock(block, inst_src, null); |
| | 30062 | return block.addBitCast(dest_ty, inst); |
| | 30063 | } |
| | 30064 | |
| | 30065 | // otherwise, try element by element |
| | 30066 | const inst_len = inst_ty.arrayLen(mod); |
| | 30067 | const dest_len = try sema.usizeCast(block, dest_ty_src, dest_ty.arrayLen(mod)); |
| 30012 | if (dest_len != inst_len) { | 30068 | if (dest_len != inst_len) { |
| 30013 | const msg = msg: { | 30069 | const msg = msg: { |
| 30014 | const msg = try sema.errMsg(block, inst_src, "expected type '{}', found '{}'", .{ | 30070 | const msg = try sema.errMsg(block, inst_src, "expected type '{}', found '{}'", .{ |
| ... | @@ -30023,17 +30079,6 @@ fn coerceArrayLike( | ... | @@ -30023,17 +30079,6 @@ fn coerceArrayLike( |
| 30023 | } | 30079 | } |
| 30024 | | 30080 | |
| 30025 | const dest_elem_ty = dest_ty.childType(mod); | 30081 | const dest_elem_ty = dest_ty.childType(mod); |
| 30026 | const inst_elem_ty = inst_ty.childType(mod); | | |
| 30027 | const in_memory_result = try sema.coerceInMemoryAllowed(block, dest_elem_ty, inst_elem_ty, false, target, dest_ty_src, inst_src); | | |
| 30028 | if (in_memory_result == .ok) { | | |
| 30029 | if (try sema.resolveMaybeUndefVal(inst)) |inst_val| { | | |
| 30030 | // These types share the same comptime value representation. | | |
| 30031 | return sema.coerceInMemory(inst_val, dest_ty); | | |
| 30032 | } | | |
| 30033 | try sema.requireRuntimeBlock(block, inst_src, null); | | |
| 30034 | return block.addBitCast(dest_ty, inst); | | |
| 30035 | } | | |
| 30036 | | | |
| 30037 | const element_vals = try sema.arena.alloc(InternPool.Index, dest_len); | 30082 | const element_vals = try sema.arena.alloc(InternPool.Index, dest_len); |
| 30038 | const element_refs = try sema.arena.alloc(Air.Inst.Ref, dest_len); | 30083 | const element_refs = try sema.arena.alloc(Air.Inst.Ref, dest_len); |
| 30039 | var runtime_src: ?LazySrcLoc = null; | 30084 | var runtime_src: ?LazySrcLoc = null; |