| ... | @@ -9255,6 +9255,7 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai | ... | @@ -9255,6 +9255,7 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 9255 | const rhs = try sema.resolveInst(extra.rhs); | 9255 | const rhs = try sema.resolveInst(extra.rhs); |
| 9256 | const lhs_ty = sema.typeOf(lhs); | 9256 | const lhs_ty = sema.typeOf(lhs); |
| 9257 | const rhs_ty = sema.typeOf(rhs); | 9257 | const rhs_ty = sema.typeOf(rhs); |
| | 9258 | const src = inst_data.src(); |
| 9258 | | 9259 | |
| 9259 | if (lhs_ty.isTuple() and rhs_ty.isTuple()) { | 9260 | if (lhs_ty.isTuple() and rhs_ty.isTuple()) { |
| 9260 | return sema.analyzeTupleCat(block, inst_data.src_node, lhs, rhs); | 9261 | return sema.analyzeTupleCat(block, inst_data.src_node, lhs, rhs); |
| ... | @@ -9267,73 +9268,138 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai | ... | @@ -9267,73 +9268,138 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 9267 | return sema.fail(block, lhs_src, "expected array, found '{}'", .{lhs_ty.fmt(sema.mod)}); | 9268 | return sema.fail(block, lhs_src, "expected array, found '{}'", .{lhs_ty.fmt(sema.mod)}); |
| 9268 | const rhs_info = (try sema.getArrayCatInfo(block, rhs_src, rhs)) orelse | 9269 | const rhs_info = (try sema.getArrayCatInfo(block, rhs_src, rhs)) orelse |
| 9269 | return sema.fail(block, rhs_src, "expected array, found '{}'", .{rhs_ty.fmt(sema.mod)}); | 9270 | return sema.fail(block, rhs_src, "expected array, found '{}'", .{rhs_ty.fmt(sema.mod)}); |
| 9270 | if (!lhs_info.elem_type.eql(rhs_info.elem_type, sema.mod)) { | 9271 | |
| 9271 | return sema.fail(block, rhs_src, "expected array of type '{}', found '{}'", .{ | 9272 | const resolved_elem_ty = t: { |
| 9272 | lhs_info.elem_type.fmt(sema.mod), rhs_ty.fmt(sema.mod), | 9273 | var trash_block = block.makeSubBlock(); |
| | 9274 | trash_block.is_comptime = false; |
| | 9275 | defer trash_block.instructions.deinit(sema.gpa); |
| | 9276 | |
| | 9277 | const instructions = [_]Air.Inst.Ref{ |
| | 9278 | try trash_block.addBitCast(lhs_info.elem_type, .void_value), |
| | 9279 | try trash_block.addBitCast(rhs_info.elem_type, .void_value), |
| | 9280 | }; |
| | 9281 | break :t try sema.resolvePeerTypes(block, src, &instructions, .{ |
| | 9282 | .override = &[_]LazySrcLoc{ lhs_src, rhs_src }, |
| 9273 | }); | 9283 | }); |
| 9274 | } | 9284 | }; |
| 9275 | | 9285 | |
| 9276 | // When there is a sentinel mismatch, no sentinel on the result. The type system | 9286 | // When there is a sentinel mismatch, no sentinel on the result. |
| 9277 | // will catch this if it is a problem. | 9287 | // Otherwise, use the sentinel value provided by either operand, |
| 9278 | var res_sent: ?Value = null; | 9288 | // coercing it to the peer-resolved element type. |
| 9279 | if (rhs_info.sentinel != null and lhs_info.sentinel != null) { | 9289 | const res_sent_val: ?Value = s: { |
| 9280 | if (rhs_info.sentinel.?.eql(lhs_info.sentinel.?, lhs_info.elem_type, sema.mod)) { | 9290 | if (lhs_info.sentinel) |lhs_sent_val| { |
| 9281 | res_sent = lhs_info.sentinel.?; | 9291 | const lhs_sent = try sema.addConstant(lhs_info.elem_type, lhs_sent_val); |
| | 9292 | if (rhs_info.sentinel) |rhs_sent_val| { |
| | 9293 | const rhs_sent = try sema.addConstant(rhs_info.elem_type, rhs_sent_val); |
| | 9294 | const lhs_sent_casted = try sema.coerce(block, resolved_elem_ty, lhs_sent, lhs_src); |
| | 9295 | const rhs_sent_casted = try sema.coerce(block, resolved_elem_ty, rhs_sent, rhs_src); |
| | 9296 | const lhs_sent_casted_val = try sema.resolveConstValue(block, lhs_src, lhs_sent_casted); |
| | 9297 | const rhs_sent_casted_val = try sema.resolveConstValue(block, rhs_src, rhs_sent_casted); |
| | 9298 | if (try sema.valuesEqual(block, src, lhs_sent_casted_val, rhs_sent_casted_val, resolved_elem_ty)) { |
| | 9299 | break :s lhs_sent_casted_val; |
| | 9300 | } else { |
| | 9301 | break :s null; |
| | 9302 | } |
| | 9303 | } else { |
| | 9304 | const lhs_sent_casted = try sema.coerce(block, resolved_elem_ty, lhs_sent, lhs_src); |
| | 9305 | const lhs_sent_casted_val = try sema.resolveConstValue(block, lhs_src, lhs_sent_casted); |
| | 9306 | break :s lhs_sent_casted_val; |
| | 9307 | } |
| | 9308 | } else { |
| | 9309 | if (rhs_info.sentinel) |rhs_sent_val| { |
| | 9310 | const rhs_sent = try sema.addConstant(rhs_info.elem_type, rhs_sent_val); |
| | 9311 | const rhs_sent_casted = try sema.coerce(block, resolved_elem_ty, rhs_sent, rhs_src); |
| | 9312 | const rhs_sent_casted_val = try sema.resolveConstValue(block, rhs_src, rhs_sent_casted); |
| | 9313 | break :s rhs_sent_casted_val; |
| | 9314 | } else { |
| | 9315 | break :s null; |
| | 9316 | } |
| 9282 | } | 9317 | } |
| 9283 | } | 9318 | }; |
| 9284 | | 9319 | |
| 9285 | if (try sema.resolveDefinedValue(block, lhs_src, lhs)) |lhs_val| { | 9320 | const lhs_len = try sema.usizeCast(block, lhs_src, lhs_info.len); |
| | 9321 | const rhs_len = try sema.usizeCast(block, lhs_src, rhs_info.len); |
| | 9322 | const result_len = lhs_len + rhs_len; |
| | 9323 | const result_ty = try Type.array(sema.arena, result_len, res_sent_val, resolved_elem_ty, sema.mod); |
| | 9324 | const is_ref = lhs_ty.zigTypeTag() == .Pointer or rhs_ty.zigTypeTag() == .Pointer; |
| | 9325 | |
| | 9326 | const runtime_src = if (try sema.resolveDefinedValue(block, lhs_src, lhs)) |lhs_val| rs: { |
| 9286 | if (try sema.resolveDefinedValue(block, rhs_src, rhs)) |rhs_val| { | 9327 | if (try sema.resolveDefinedValue(block, rhs_src, rhs)) |rhs_val| { |
| 9287 | const lhs_len = try sema.usizeCast(block, lhs_src, lhs_info.len); | 9328 | const lhs_sub_val = if (lhs_ty.isSinglePointer()) |
| 9288 | const rhs_len = try sema.usizeCast(block, lhs_src, rhs_info.len); | 9329 | (try sema.pointerDeref(block, lhs_src, lhs_val, lhs_ty)).? |
| 9289 | const final_len = lhs_len + rhs_len; | 9330 | else |
| 9290 | const final_len_including_sent = final_len + @boolToInt(res_sent != null); | 9331 | lhs_val; |
| 9291 | const lhs_single_ptr = lhs_ty.isSinglePointer(); | | |
| 9292 | const rhs_single_ptr = rhs_ty.isSinglePointer(); | | |
| 9293 | const lhs_sub_val = if (lhs_single_ptr) (try sema.pointerDeref(block, lhs_src, lhs_val, lhs_ty)).? else lhs_val; | | |
| 9294 | const rhs_sub_val = if (rhs_single_ptr) (try sema.pointerDeref(block, rhs_src, rhs_val, rhs_ty)).? else rhs_val; | | |
| 9295 | var anon_decl = try block.startAnonDecl(LazySrcLoc.unneeded); | | |
| 9296 | defer anon_decl.deinit(); | | |
| 9297 | | 9332 | |
| 9298 | const buf = try anon_decl.arena().alloc(Value, final_len_including_sent); | 9333 | const rhs_sub_val = if (rhs_ty.isSinglePointer()) |
| 9299 | { | 9334 | (try sema.pointerDeref(block, rhs_src, rhs_val, rhs_ty)).? |
| 9300 | var i: usize = 0; | 9335 | else |
| 9301 | while (i < lhs_len) : (i += 1) { | 9336 | rhs_val; |
| 9302 | const val = try lhs_sub_val.elemValue(sema.mod, sema.arena, i); | 9337 | |
| 9303 | buf[i] = try val.copy(anon_decl.arena()); | 9338 | const final_len_including_sent = result_len + @boolToInt(res_sent_val != null); |
| 9304 | } | 9339 | const element_vals = try sema.arena.alloc(Value, final_len_including_sent); |
| | 9340 | var elem_i: usize = 0; |
| | 9341 | while (elem_i < lhs_len) : (elem_i += 1) { |
| | 9342 | element_vals[elem_i] = try lhs_sub_val.elemValue(sema.mod, sema.arena, elem_i); |
| 9305 | } | 9343 | } |
| 9306 | { | 9344 | while (elem_i < result_len) : (elem_i += 1) { |
| 9307 | var i: usize = 0; | 9345 | element_vals[elem_i] = try rhs_sub_val.elemValue(sema.mod, sema.arena, elem_i - lhs_len); |
| 9308 | while (i < rhs_len) : (i += 1) { | | |
| 9309 | const val = try rhs_sub_val.elemValue(sema.mod, sema.arena, i); | | |
| 9310 | buf[lhs_len + i] = try val.copy(anon_decl.arena()); | | |
| 9311 | } | | |
| 9312 | } | 9346 | } |
| 9313 | const ty = if (res_sent) |rs| ty: { | 9347 | if (res_sent_val) |sent_val| { |
| 9314 | buf[final_len] = try rs.copy(anon_decl.arena()); | 9348 | element_vals[result_len] = sent_val; |
| 9315 | break :ty try Type.Tag.array_sentinel.create(anon_decl.arena(), .{ | | |
| 9316 | .len = final_len, | | |
| 9317 | .elem_type = try lhs_info.elem_type.copy(anon_decl.arena()), | | |
| 9318 | .sentinel = try rs.copy(anon_decl.arena()), | | |
| 9319 | }); | | |
| 9320 | } else try Type.Tag.array.create(anon_decl.arena(), .{ | | |
| 9321 | .len = final_len, | | |
| 9322 | .elem_type = try lhs_info.elem_type.copy(anon_decl.arena()), | | |
| 9323 | }); | | |
| 9324 | const val = try Value.Tag.aggregate.create(anon_decl.arena(), buf); | | |
| 9325 | const decl = try anon_decl.finish(ty, val, 0); | | |
| 9326 | if (lhs_ty.zigTypeTag() == .Pointer or rhs_ty.zigTypeTag() == .Pointer) { | | |
| 9327 | return sema.analyzeDeclRef(decl); | | |
| 9328 | } else { | | |
| 9329 | return sema.analyzeDeclVal(block, .unneeded, decl); | | |
| 9330 | } | 9349 | } |
| 9331 | } else { | 9350 | const val = try Value.Tag.aggregate.create(sema.arena, element_vals); |
| 9332 | return sema.fail(block, lhs_src, "TODO runtime array_cat", .{}); | 9351 | return sema.addConstantMaybeRef(block, src, result_ty, val, is_ref); |
| | 9352 | } else break :rs rhs_src; |
| | 9353 | } else lhs_src; |
| | 9354 | |
| | 9355 | try sema.requireRuntimeBlock(block, runtime_src); |
| | 9356 | |
| | 9357 | if (is_ref) { |
| | 9358 | const target = sema.mod.getTarget(); |
| | 9359 | const alloc_ty = try Type.ptr(sema.arena, sema.mod, .{ |
| | 9360 | .pointee_type = result_ty, |
| | 9361 | .@"addrspace" = target_util.defaultAddressSpace(target, .local), |
| | 9362 | }); |
| | 9363 | const alloc = try block.addTy(.alloc, alloc_ty); |
| | 9364 | const elem_ptr_ty = try Type.ptr(sema.arena, sema.mod, .{ |
| | 9365 | .pointee_type = resolved_elem_ty, |
| | 9366 | .@"addrspace" = target_util.defaultAddressSpace(target, .local), |
| | 9367 | }); |
| | 9368 | |
| | 9369 | var elem_i: usize = 0; |
| | 9370 | while (elem_i < lhs_len) : (elem_i += 1) { |
| | 9371 | const elem_index = try sema.addIntUnsigned(Type.usize, elem_i); |
| | 9372 | const elem_ptr = try block.addPtrElemPtr(alloc, elem_index, elem_ptr_ty); |
| | 9373 | const init = try sema.elemVal(block, lhs_src, lhs, elem_index, src); |
| | 9374 | try sema.storePtr2(block, src, elem_ptr, src, init, lhs_src, .store); |
| 9333 | } | 9375 | } |
| 9334 | } else { | 9376 | while (elem_i < result_len) : (elem_i += 1) { |
| 9335 | return sema.fail(block, lhs_src, "TODO runtime array_cat", .{}); | 9377 | const elem_index = try sema.addIntUnsigned(Type.usize, elem_i); |
| | 9378 | const rhs_index = try sema.addIntUnsigned(Type.usize, elem_i - lhs_len); |
| | 9379 | const elem_ptr = try block.addPtrElemPtr(alloc, elem_index, elem_ptr_ty); |
| | 9380 | const init = try sema.elemVal(block, rhs_src, rhs, rhs_index, src); |
| | 9381 | try sema.storePtr2(block, src, elem_ptr, src, init, rhs_src, .store); |
| | 9382 | } |
| | 9383 | |
| | 9384 | return alloc; |
| 9336 | } | 9385 | } |
| | 9386 | |
| | 9387 | const element_refs = try sema.arena.alloc(Air.Inst.Ref, result_len); |
| | 9388 | { |
| | 9389 | var elem_i: usize = 0; |
| | 9390 | while (elem_i < lhs_len) : (elem_i += 1) { |
| | 9391 | const index = try sema.addIntUnsigned(Type.usize, elem_i); |
| | 9392 | const init = try sema.elemVal(block, lhs_src, lhs, index, src); |
| | 9393 | element_refs[elem_i] = try sema.coerce(block, resolved_elem_ty, init, lhs_src); |
| | 9394 | } |
| | 9395 | while (elem_i < result_len) : (elem_i += 1) { |
| | 9396 | const index = try sema.addIntUnsigned(Type.usize, elem_i - lhs_len); |
| | 9397 | const init = try sema.elemVal(block, rhs_src, rhs, index, src); |
| | 9398 | element_refs[elem_i] = try sema.coerce(block, resolved_elem_ty, init, rhs_src); |
| | 9399 | } |
| | 9400 | } |
| | 9401 | |
| | 9402 | return block.addAggregateInit(result_ty, element_refs); |
| 9337 | } | 9403 | } |
| 9338 | | 9404 | |
| 9339 | fn getArrayCatInfo(sema: *Sema, block: *Block, src: LazySrcLoc, inst: Air.Inst.Ref) !?Type.ArrayInfo { | 9405 | fn getArrayCatInfo(sema: *Sema, block: *Block, src: LazySrcLoc, inst: Air.Inst.Ref) !?Type.ArrayInfo { |
| ... | @@ -24947,7 +25013,7 @@ fn valuesEqual( | ... | @@ -24947,7 +25013,7 @@ fn valuesEqual( |
| 24947 | } | 25013 | } |
| 24948 | | 25014 | |
| 24949 | /// Asserts the values are comparable vectors of type `ty`. | 25015 | /// Asserts the values are comparable vectors of type `ty`. |
| 24950 | pub fn compareVector( | 25016 | fn compareVector( |
| 24951 | sema: *Sema, | 25017 | sema: *Sema, |
| 24952 | block: *Block, | 25018 | block: *Block, |
| 24953 | src: LazySrcLoc, | 25019 | src: LazySrcLoc, |