| ... | @@ -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); |
| ... | @@ -9263,103 +9264,188 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai | ... | @@ -9263,103 +9264,188 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 9263 | const lhs_src: LazySrcLoc = .{ .node_offset_bin_lhs = inst_data.src_node }; | 9264 | const lhs_src: LazySrcLoc = .{ .node_offset_bin_lhs = inst_data.src_node }; |
| 9264 | const rhs_src: LazySrcLoc = .{ .node_offset_bin_rhs = inst_data.src_node }; | 9265 | const rhs_src: LazySrcLoc = .{ .node_offset_bin_rhs = inst_data.src_node }; |
| 9265 | | 9266 | |
| 9266 | const lhs_info = (try sema.getArrayCatInfo(block, lhs_src, lhs)) orelse | 9267 | const lhs_info = try sema.getArrayCatInfo(block, lhs_src, lhs); |
| 9267 | 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); |
| 9268 | const rhs_info = (try sema.getArrayCatInfo(block, rhs_src, rhs)) orelse | 9269 | |
| 9269 | return sema.fail(block, rhs_src, "expected array, found '{}'", .{rhs_ty.fmt(sema.mod)}); | 9270 | const resolved_elem_ty = t: { |
| 9270 | if (!lhs_info.elem_type.eql(rhs_info.elem_type, sema.mod)) { | 9271 | var trash_block = block.makeSubBlock(); |
| 9271 | return sema.fail(block, rhs_src, "expected array of type '{}', found '{}'", .{ | 9272 | trash_block.is_comptime = false; |
| 9272 | lhs_info.elem_type.fmt(sema.mod), rhs_ty.fmt(sema.mod), | 9273 | defer trash_block.instructions.deinit(sema.gpa); |
| | 9274 | |
| | 9275 | const instructions = [_]Air.Inst.Ref{ |
| | 9276 | try trash_block.addBitCast(lhs_info.elem_type, .void_value), |
| | 9277 | try trash_block.addBitCast(rhs_info.elem_type, .void_value), |
| | 9278 | }; |
| | 9279 | break :t try sema.resolvePeerTypes(block, src, &instructions, .{ |
| | 9280 | .override = &[_]LazySrcLoc{ lhs_src, rhs_src }, |
| 9273 | }); | 9281 | }); |
| 9274 | } | 9282 | }; |
| 9275 | | 9283 | |
| 9276 | // When there is a sentinel mismatch, no sentinel on the result. The type system | 9284 | // When there is a sentinel mismatch, no sentinel on the result. |
| 9277 | // will catch this if it is a problem. | 9285 | // Otherwise, use the sentinel value provided by either operand, |
| 9278 | var res_sent: ?Value = null; | 9286 | // coercing it to the peer-resolved element type. |
| 9279 | if (rhs_info.sentinel != null and lhs_info.sentinel != null) { | 9287 | const res_sent_val: ?Value = s: { |
| 9280 | if (rhs_info.sentinel.?.eql(lhs_info.sentinel.?, lhs_info.elem_type, sema.mod)) { | 9288 | if (lhs_info.sentinel) |lhs_sent_val| { |
| 9281 | res_sent = lhs_info.sentinel.?; | 9289 | const lhs_sent = try sema.addConstant(lhs_info.elem_type, lhs_sent_val); |
| | 9290 | if (rhs_info.sentinel) |rhs_sent_val| { |
| | 9291 | const rhs_sent = try sema.addConstant(rhs_info.elem_type, rhs_sent_val); |
| | 9292 | const lhs_sent_casted = try sema.coerce(block, resolved_elem_ty, lhs_sent, lhs_src); |
| | 9293 | const rhs_sent_casted = try sema.coerce(block, resolved_elem_ty, rhs_sent, rhs_src); |
| | 9294 | const lhs_sent_casted_val = try sema.resolveConstValue(block, lhs_src, lhs_sent_casted); |
| | 9295 | const rhs_sent_casted_val = try sema.resolveConstValue(block, rhs_src, rhs_sent_casted); |
| | 9296 | if (try sema.valuesEqual(block, src, lhs_sent_casted_val, rhs_sent_casted_val, resolved_elem_ty)) { |
| | 9297 | break :s lhs_sent_casted_val; |
| | 9298 | } else { |
| | 9299 | break :s null; |
| | 9300 | } |
| | 9301 | } else { |
| | 9302 | const lhs_sent_casted = try sema.coerce(block, resolved_elem_ty, lhs_sent, lhs_src); |
| | 9303 | const lhs_sent_casted_val = try sema.resolveConstValue(block, lhs_src, lhs_sent_casted); |
| | 9304 | break :s lhs_sent_casted_val; |
| | 9305 | } |
| | 9306 | } else { |
| | 9307 | if (rhs_info.sentinel) |rhs_sent_val| { |
| | 9308 | const rhs_sent = try sema.addConstant(rhs_info.elem_type, rhs_sent_val); |
| | 9309 | const rhs_sent_casted = try sema.coerce(block, resolved_elem_ty, rhs_sent, rhs_src); |
| | 9310 | const rhs_sent_casted_val = try sema.resolveConstValue(block, rhs_src, rhs_sent_casted); |
| | 9311 | break :s rhs_sent_casted_val; |
| | 9312 | } else { |
| | 9313 | break :s null; |
| | 9314 | } |
| 9282 | } | 9315 | } |
| 9283 | } | 9316 | }; |
| 9284 | | 9317 | |
| 9285 | if (try sema.resolveDefinedValue(block, lhs_src, lhs)) |lhs_val| { | 9318 | const lhs_len = try sema.usizeCast(block, lhs_src, lhs_info.len); |
| | 9319 | const rhs_len = try sema.usizeCast(block, lhs_src, rhs_info.len); |
| | 9320 | const result_len = std.math.add(usize, lhs_len, rhs_len) catch |err| switch (err) { |
| | 9321 | error.Overflow => return sema.fail( |
| | 9322 | block, |
| | 9323 | src, |
| | 9324 | "concatenating arrays of length {d} and {d} produces an array too large for this compiler implementation to handle", |
| | 9325 | .{ lhs_len, rhs_len }, |
| | 9326 | ), |
| | 9327 | }; |
| | 9328 | |
| | 9329 | const result_ty = try Type.array(sema.arena, result_len, res_sent_val, resolved_elem_ty, sema.mod); |
| | 9330 | const ptr_addrspace = p: { |
| | 9331 | if (lhs_ty.zigTypeTag() == .Pointer) break :p lhs_ty.ptrAddressSpace(); |
| | 9332 | if (rhs_ty.zigTypeTag() == .Pointer) break :p rhs_ty.ptrAddressSpace(); |
| | 9333 | break :p null; |
| | 9334 | }; |
| | 9335 | |
| | 9336 | 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| { | 9337 | if (try sema.resolveDefinedValue(block, rhs_src, rhs)) |rhs_val| { |
| 9287 | const lhs_len = try sema.usizeCast(block, lhs_src, lhs_info.len); | 9338 | const lhs_sub_val = if (lhs_ty.isSinglePointer()) |
| 9288 | const rhs_len = try sema.usizeCast(block, lhs_src, rhs_info.len); | 9339 | (try sema.pointerDeref(block, lhs_src, lhs_val, lhs_ty)).? |
| 9289 | const final_len = lhs_len + rhs_len; | 9340 | else |
| 9290 | const final_len_including_sent = final_len + @boolToInt(res_sent != null); | 9341 | 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 | | 9342 | |
| 9298 | const buf = try anon_decl.arena().alloc(Value, final_len_including_sent); | 9343 | const rhs_sub_val = if (rhs_ty.isSinglePointer()) |
| 9299 | { | 9344 | (try sema.pointerDeref(block, rhs_src, rhs_val, rhs_ty)).? |
| 9300 | var i: usize = 0; | 9345 | else |
| 9301 | while (i < lhs_len) : (i += 1) { | 9346 | rhs_val; |
| 9302 | const val = try lhs_sub_val.elemValue(sema.mod, sema.arena, i); | 9347 | |
| 9303 | buf[i] = try val.copy(anon_decl.arena()); | 9348 | const final_len_including_sent = result_len + @boolToInt(res_sent_val != null); |
| 9304 | } | 9349 | const element_vals = try sema.arena.alloc(Value, final_len_including_sent); |
| | 9350 | var elem_i: usize = 0; |
| | 9351 | while (elem_i < lhs_len) : (elem_i += 1) { |
| | 9352 | element_vals[elem_i] = try lhs_sub_val.elemValue(sema.mod, sema.arena, elem_i); |
| 9305 | } | 9353 | } |
| 9306 | { | 9354 | while (elem_i < result_len) : (elem_i += 1) { |
| 9307 | var i: usize = 0; | 9355 | 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 | } | 9356 | } |
| 9313 | const ty = if (res_sent) |rs| ty: { | 9357 | if (res_sent_val) |sent_val| { |
| 9314 | buf[final_len] = try rs.copy(anon_decl.arena()); | 9358 | 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 | } | 9359 | } |
| 9331 | } else { | 9360 | const val = try Value.Tag.aggregate.create(sema.arena, element_vals); |
| 9332 | return sema.fail(block, lhs_src, "TODO runtime array_cat", .{}); | 9361 | return sema.addConstantMaybeRef(block, src, result_ty, val, ptr_addrspace != null); |
| | 9362 | } else break :rs rhs_src; |
| | 9363 | } else lhs_src; |
| | 9364 | |
| | 9365 | try sema.requireRuntimeBlock(block, runtime_src); |
| | 9366 | |
| | 9367 | if (ptr_addrspace) |ptr_as| { |
| | 9368 | const alloc_ty = try Type.ptr(sema.arena, sema.mod, .{ |
| | 9369 | .pointee_type = result_ty, |
| | 9370 | .@"addrspace" = ptr_as, |
| | 9371 | }); |
| | 9372 | const alloc = try block.addTy(.alloc, alloc_ty); |
| | 9373 | const elem_ptr_ty = try Type.ptr(sema.arena, sema.mod, .{ |
| | 9374 | .pointee_type = resolved_elem_ty, |
| | 9375 | .@"addrspace" = ptr_as, |
| | 9376 | }); |
| | 9377 | |
| | 9378 | var elem_i: usize = 0; |
| | 9379 | while (elem_i < lhs_len) : (elem_i += 1) { |
| | 9380 | const elem_index = try sema.addIntUnsigned(Type.usize, elem_i); |
| | 9381 | const elem_ptr = try block.addPtrElemPtr(alloc, elem_index, elem_ptr_ty); |
| | 9382 | const init = try sema.elemVal(block, lhs_src, lhs, elem_index, src); |
| | 9383 | try sema.storePtr2(block, src, elem_ptr, src, init, lhs_src, .store); |
| 9333 | } | 9384 | } |
| 9334 | } else { | 9385 | while (elem_i < result_len) : (elem_i += 1) { |
| 9335 | return sema.fail(block, lhs_src, "TODO runtime array_cat", .{}); | 9386 | const elem_index = try sema.addIntUnsigned(Type.usize, elem_i); |
| | 9387 | const rhs_index = try sema.addIntUnsigned(Type.usize, elem_i - lhs_len); |
| | 9388 | const elem_ptr = try block.addPtrElemPtr(alloc, elem_index, elem_ptr_ty); |
| | 9389 | const init = try sema.elemVal(block, rhs_src, rhs, rhs_index, src); |
| | 9390 | try sema.storePtr2(block, src, elem_ptr, src, init, rhs_src, .store); |
| | 9391 | } |
| | 9392 | if (res_sent_val) |sent_val| { |
| | 9393 | const elem_index = try sema.addIntUnsigned(Type.usize, result_len); |
| | 9394 | const elem_ptr = try block.addPtrElemPtr(alloc, elem_index, elem_ptr_ty); |
| | 9395 | const init = try sema.addConstant(lhs_info.elem_type, sent_val); |
| | 9396 | try sema.storePtr2(block, src, elem_ptr, src, init, lhs_src, .store); |
| | 9397 | } |
| | 9398 | |
| | 9399 | return alloc; |
| 9336 | } | 9400 | } |
| | 9401 | |
| | 9402 | const element_refs = try sema.arena.alloc(Air.Inst.Ref, result_len); |
| | 9403 | { |
| | 9404 | var elem_i: usize = 0; |
| | 9405 | while (elem_i < lhs_len) : (elem_i += 1) { |
| | 9406 | const index = try sema.addIntUnsigned(Type.usize, elem_i); |
| | 9407 | const init = try sema.elemVal(block, lhs_src, lhs, index, src); |
| | 9408 | element_refs[elem_i] = try sema.coerce(block, resolved_elem_ty, init, lhs_src); |
| | 9409 | } |
| | 9410 | while (elem_i < result_len) : (elem_i += 1) { |
| | 9411 | const index = try sema.addIntUnsigned(Type.usize, elem_i - lhs_len); |
| | 9412 | const init = try sema.elemVal(block, rhs_src, rhs, index, src); |
| | 9413 | element_refs[elem_i] = try sema.coerce(block, resolved_elem_ty, init, rhs_src); |
| | 9414 | } |
| | 9415 | } |
| | 9416 | |
| | 9417 | return block.addAggregateInit(result_ty, element_refs); |
| 9337 | } | 9418 | } |
| 9338 | | 9419 | |
| 9339 | fn getArrayCatInfo(sema: *Sema, block: *Block, src: LazySrcLoc, inst: Air.Inst.Ref) !?Type.ArrayInfo { | 9420 | fn getArrayCatInfo(sema: *Sema, block: *Block, src: LazySrcLoc, operand: Air.Inst.Ref) !Type.ArrayInfo { |
| 9340 | const t = sema.typeOf(inst); | 9421 | const operand_ty = sema.typeOf(operand); |
| 9341 | return switch (t.zigTypeTag()) { | 9422 | switch (operand_ty.zigTypeTag()) { |
| 9342 | .Array => t.arrayInfo(), | 9423 | .Array => return operand_ty.arrayInfo(), |
| 9343 | .Pointer => blk: { | 9424 | .Pointer => { |
| 9344 | const ptrinfo = t.ptrInfo().data; | 9425 | const ptr_info = operand_ty.ptrInfo().data; |
| 9345 | switch (ptrinfo.size) { | 9426 | switch (ptr_info.size) { |
| | 9427 | // TODO: in the Many case here this should only work if the type |
| | 9428 | // has a sentinel, and this code should compute the length based |
| | 9429 | // on the sentinel value. |
| 9346 | .Slice, .Many => { | 9430 | .Slice, .Many => { |
| 9347 | const val = try sema.resolveConstValue(block, src, inst); | 9431 | const val = try sema.resolveConstValue(block, src, operand); |
| 9348 | return Type.ArrayInfo{ | 9432 | return Type.ArrayInfo{ |
| 9349 | .elem_type = t.childType(), | 9433 | .elem_type = ptr_info.pointee_type, |
| 9350 | .sentinel = t.sentinel(), | 9434 | .sentinel = ptr_info.sentinel, |
| 9351 | .len = val.sliceLen(sema.mod), | 9435 | .len = val.sliceLen(sema.mod), |
| 9352 | }; | 9436 | }; |
| 9353 | }, | 9437 | }, |
| 9354 | .One => { | 9438 | .One => { |
| 9355 | if (ptrinfo.pointee_type.zigTypeTag() != .Array) return null; | 9439 | if (ptr_info.pointee_type.zigTypeTag() == .Array) { |
| 9356 | break :blk ptrinfo.pointee_type.arrayInfo(); | 9440 | return ptr_info.pointee_type.arrayInfo(); |
| | 9441 | } |
| 9357 | }, | 9442 | }, |
| 9358 | .C => return null, | 9443 | .C => {}, |
| 9359 | } | 9444 | } |
| 9360 | }, | 9445 | }, |
| 9361 | else => null, | 9446 | else => {}, |
| 9362 | }; | 9447 | } |
| | 9448 | return sema.fail(block, src, "expected indexable; found '{}'", .{operand_ty.fmt(sema.mod)}); |
| 9363 | } | 9449 | } |
| 9364 | | 9450 | |
| 9365 | fn analyzeTupleMul( | 9451 | fn analyzeTupleMul( |
| ... | @@ -9448,65 +9534,99 @@ fn zirArrayMul(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai | ... | @@ -9448,65 +9534,99 @@ fn zirArrayMul(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 9448 | return sema.analyzeTupleMul(block, inst_data.src_node, lhs, factor); | 9534 | return sema.analyzeTupleMul(block, inst_data.src_node, lhs, factor); |
| 9449 | } | 9535 | } |
| 9450 | | 9536 | |
| 9451 | const mulinfo = (try sema.getArrayCatInfo(block, lhs_src, lhs)) orelse | 9537 | const lhs_info = try sema.getArrayCatInfo(block, lhs_src, lhs); |
| 9452 | return sema.fail(block, lhs_src, "expected array, found '{}'", .{lhs_ty.fmt(sema.mod)}); | | |
| 9453 | | 9538 | |
| 9454 | const final_len_u64 = std.math.mul(u64, mulinfo.len, factor) catch | 9539 | const result_len_u64 = std.math.mul(u64, lhs_info.len, factor) catch |
| 9455 | return sema.fail(block, rhs_src, "operation results in overflow", .{}); | 9540 | return sema.fail(block, rhs_src, "operation results in overflow", .{}); |
| | 9541 | const result_len = try sema.usizeCast(block, src, result_len_u64); |
| 9456 | | 9542 | |
| 9457 | if (try sema.resolveDefinedValue(block, lhs_src, lhs)) |lhs_val| { | 9543 | const result_ty = try Type.array(sema.arena, result_len, lhs_info.sentinel, lhs_info.elem_type, sema.mod); |
| 9458 | const final_len = try sema.usizeCast(block, src, final_len_u64); | | |
| 9459 | const final_len_including_sent = final_len + @boolToInt(mulinfo.sentinel != null); | | |
| 9460 | const lhs_len = try sema.usizeCast(block, lhs_src, mulinfo.len); | | |
| 9461 | | 9544 | |
| 9462 | const is_single_ptr = lhs_ty.zigTypeTag() == .Pointer and !lhs_ty.isSlice(); | 9545 | const ptr_addrspace = if (lhs_ty.zigTypeTag() == .Pointer) lhs_ty.ptrAddressSpace() else null; |
| 9463 | const lhs_sub_val = if (is_single_ptr) (try sema.pointerDeref(block, lhs_src, lhs_val, lhs_ty)).? else lhs_val; | 9546 | const lhs_len = try sema.usizeCast(block, lhs_src, lhs_info.len); |
| 9464 | | 9547 | |
| 9465 | var anon_decl = try block.startAnonDecl(src); | 9548 | if (try sema.resolveDefinedValue(block, lhs_src, lhs)) |lhs_val| { |
| 9466 | defer anon_decl.deinit(); | 9549 | const final_len_including_sent = result_len + @boolToInt(lhs_info.sentinel != null); |
| 9467 | | 9550 | |
| 9468 | const final_ty = if (mulinfo.sentinel) |sent| | 9551 | const lhs_sub_val = if (lhs_ty.isSinglePointer()) |
| 9469 | try Type.Tag.array_sentinel.create(anon_decl.arena(), .{ | 9552 | (try sema.pointerDeref(block, lhs_src, lhs_val, lhs_ty)).? |
| 9470 | .len = final_len, | | |
| 9471 | .elem_type = try mulinfo.elem_type.copy(anon_decl.arena()), | | |
| 9472 | .sentinel = try sent.copy(anon_decl.arena()), | | |
| 9473 | }) | | |
| 9474 | else | 9553 | else |
| 9475 | try Type.Tag.array.create(anon_decl.arena(), .{ | 9554 | lhs_val; |
| 9476 | .len = final_len, | 9555 | |
| 9477 | .elem_type = try mulinfo.elem_type.copy(anon_decl.arena()), | 9556 | const val = v: { |
| 9478 | }); | 9557 | // Optimization for the common pattern of a single element repeated N times, such |
| 9479 | const buf = try anon_decl.arena().alloc(Value, final_len_including_sent); | 9558 | // as zero-filling a byte array. |
| 9480 | | 9559 | if (lhs_len == 1) { |
| 9481 | // Optimization for the common pattern of a single element repeated N times, such | 9560 | const elem_val = try lhs_sub_val.elemValue(sema.mod, sema.arena, 0); |
| 9482 | // as zero-filling a byte array. | 9561 | break :v try Value.Tag.repeated.create(sema.arena, elem_val); |
| 9483 | const val = if (lhs_len == 1) blk: { | 9562 | } |
| 9484 | const elem_val = try lhs_sub_val.elemValue(sema.mod, sema.arena, 0); | 9563 | |
| 9485 | const copied_val = try elem_val.copy(anon_decl.arena()); | 9564 | const element_vals = try sema.arena.alloc(Value, final_len_including_sent); |
| 9486 | break :blk try Value.Tag.repeated.create(anon_decl.arena(), copied_val); | 9565 | var elem_i: usize = 0; |
| 9487 | } else blk: { | 9566 | while (elem_i < result_len) { |
| 9488 | // the actual loop | 9567 | var lhs_i: usize = 0; |
| 9489 | var i: usize = 0; | 9568 | while (lhs_i < lhs_len) : (lhs_i += 1) { |
| 9490 | while (i < factor) : (i += 1) { | 9569 | const elem_val = try lhs_sub_val.elemValue(sema.mod, sema.arena, lhs_i); |
| 9491 | var j: usize = 0; | 9570 | element_vals[elem_i] = elem_val; |
| 9492 | while (j < lhs_len) : (j += 1) { | 9571 | elem_i += 1; |
| 9493 | const val = try lhs_sub_val.elemValue(sema.mod, sema.arena, j); | | |
| 9494 | buf[lhs_len * i + j] = try val.copy(anon_decl.arena()); | | |
| 9495 | } | 9572 | } |
| 9496 | } | 9573 | } |
| 9497 | if (mulinfo.sentinel) |sent| { | 9574 | if (lhs_info.sentinel) |sent_val| { |
| 9498 | buf[final_len] = try sent.copy(anon_decl.arena()); | 9575 | element_vals[result_len] = sent_val; |
| 9499 | } | 9576 | } |
| 9500 | break :blk try Value.Tag.aggregate.create(anon_decl.arena(), buf); | 9577 | break :v try Value.Tag.aggregate.create(sema.arena, element_vals); |
| 9501 | }; | 9578 | }; |
| 9502 | const decl = try anon_decl.finish(final_ty, val, 0); | 9579 | return sema.addConstantMaybeRef(block, src, result_ty, val, ptr_addrspace != null); |
| 9503 | if (lhs_ty.zigTypeTag() == .Pointer) { | 9580 | } |
| 9504 | return sema.analyzeDeclRef(decl); | 9581 | |
| 9505 | } else { | 9582 | try sema.requireRuntimeBlock(block, lhs_src); |
| 9506 | return sema.analyzeDeclVal(block, .unneeded, decl); | 9583 | |
| | 9584 | if (ptr_addrspace) |ptr_as| { |
| | 9585 | const alloc_ty = try Type.ptr(sema.arena, sema.mod, .{ |
| | 9586 | .pointee_type = result_ty, |
| | 9587 | .@"addrspace" = ptr_as, |
| | 9588 | }); |
| | 9589 | const alloc = try block.addTy(.alloc, alloc_ty); |
| | 9590 | const elem_ptr_ty = try Type.ptr(sema.arena, sema.mod, .{ |
| | 9591 | .pointee_type = lhs_info.elem_type, |
| | 9592 | .@"addrspace" = ptr_as, |
| | 9593 | }); |
| | 9594 | |
| | 9595 | var elem_i: usize = 0; |
| | 9596 | while (elem_i < result_len) { |
| | 9597 | var lhs_i: usize = 0; |
| | 9598 | while (lhs_i < lhs_len) : (lhs_i += 1) { |
| | 9599 | const elem_index = try sema.addIntUnsigned(Type.usize, elem_i); |
| | 9600 | elem_i += 1; |
| | 9601 | const lhs_index = try sema.addIntUnsigned(Type.usize, lhs_i); |
| | 9602 | const elem_ptr = try block.addPtrElemPtr(alloc, elem_index, elem_ptr_ty); |
| | 9603 | const init = try sema.elemVal(block, lhs_src, lhs, lhs_index, src); |
| | 9604 | try sema.storePtr2(block, src, elem_ptr, src, init, lhs_src, .store); |
| | 9605 | } |
| | 9606 | } |
| | 9607 | if (lhs_info.sentinel) |sent_val| { |
| | 9608 | const elem_index = try sema.addIntUnsigned(Type.usize, result_len); |
| | 9609 | const elem_ptr = try block.addPtrElemPtr(alloc, elem_index, elem_ptr_ty); |
| | 9610 | const init = try sema.addConstant(lhs_info.elem_type, sent_val); |
| | 9611 | try sema.storePtr2(block, src, elem_ptr, src, init, lhs_src, .store); |
| 9507 | } | 9612 | } |
| | 9613 | |
| | 9614 | return alloc; |
| 9508 | } | 9615 | } |
| 9509 | return sema.fail(block, lhs_src, "TODO runtime array_mul", .{}); | 9616 | |
| | 9617 | const element_refs = try sema.arena.alloc(Air.Inst.Ref, result_len); |
| | 9618 | var elem_i: usize = 0; |
| | 9619 | while (elem_i < result_len) { |
| | 9620 | var lhs_i: usize = 0; |
| | 9621 | while (lhs_i < lhs_len) : (lhs_i += 1) { |
| | 9622 | const lhs_index = try sema.addIntUnsigned(Type.usize, lhs_i); |
| | 9623 | const init = try sema.elemVal(block, lhs_src, lhs, lhs_index, src); |
| | 9624 | element_refs[elem_i] = init; |
| | 9625 | elem_i += 1; |
| | 9626 | } |
| | 9627 | } |
| | 9628 | |
| | 9629 | return block.addAggregateInit(result_ty, element_refs); |
| 9510 | } | 9630 | } |
| 9511 | | 9631 | |
| 9512 | fn zirNegate(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { | 9632 | fn zirNegate(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| ... | @@ -24947,7 +25067,7 @@ fn valuesEqual( | ... | @@ -24947,7 +25067,7 @@ fn valuesEqual( |
| 24947 | } | 25067 | } |
| 24948 | | 25068 | |
| 24949 | /// Asserts the values are comparable vectors of type `ty`. | 25069 | /// Asserts the values are comparable vectors of type `ty`. |
| 24950 | pub fn compareVector( | 25070 | fn compareVector( |
| 24951 | sema: *Sema, | 25071 | sema: *Sema, |
| 24952 | block: *Block, | 25072 | block: *Block, |
| 24953 | src: LazySrcLoc, | 25073 | src: LazySrcLoc, |