| ... | ... | @@ -4419,51 +4419,94 @@ fn airBitcast(f: *Function, inst: Air.Inst.Index) !CValue { |
| 4419 | 4419 | const dest_ty = f.air.typeOfIndex(inst); |
| 4420 | 4420 | |
| 4421 | 4421 | const operand = try f.resolveInst(ty_op.operand); |
| 4422 | | try reap(f, inst, &.{ty_op.operand}); |
| 4423 | 4422 | const operand_ty = f.air.typeOf(ty_op.operand); |
| 4424 | | const target = f.object.dg.module.getTarget(); |
| 4425 | | const writer = f.object.writer(); |
| 4426 | 4423 | |
| 4427 | | const local = try f.allocLocal(inst, dest_ty); |
| 4424 | const bitcasted = try bitcast(f, dest_ty, operand, operand_ty); |
| 4425 | try reap(f, inst, &.{ty_op.operand}); |
| 4426 | return bitcasted.move(f, inst, dest_ty); |
| 4427 | } |
| 4428 | |
| 4429 | const LocalResult = struct { |
| 4430 | c_value: CValue, |
| 4431 | need_free: bool, |
| 4432 | |
| 4433 | fn move(lr: LocalResult, f: *Function, inst: Air.Inst.Index, dest_ty: Type) !CValue { |
| 4434 | if (lr.need_free) { |
| 4435 | // Move the freshly allocated local to be owned by this instruction, |
| 4436 | // by returning it here instead of freeing it. |
| 4437 | return lr.c_value; |
| 4438 | } |
| 4439 | |
| 4440 | const local = try f.allocLocal(inst, dest_ty); |
| 4441 | try lr.free(f); |
| 4442 | const writer = f.object.writer(); |
| 4443 | try f.writeCValue(writer, local, .Other); |
| 4444 | if (dest_ty.isAbiInt()) { |
| 4445 | try writer.writeAll(" = "); |
| 4446 | } else { |
| 4447 | try writer.writeAll(" = ("); |
| 4448 | try f.renderType(writer, dest_ty); |
| 4449 | try writer.writeByte(')'); |
| 4450 | } |
| 4451 | try f.writeCValue(writer, lr.c_value, .Initializer); |
| 4452 | try writer.writeAll(";\n"); |
| 4453 | return local; |
| 4454 | } |
| 4455 | |
| 4456 | fn free(lr: LocalResult, f: *Function) !void { |
| 4457 | if (lr.need_free) { |
| 4458 | try freeLocal(f, 0, lr.c_value.new_local, 0); |
| 4459 | } |
| 4460 | } |
| 4461 | }; |
| 4428 | 4462 | |
| 4429 | | // If the assignment looks like 'x = x', we don't need it |
| 4430 | | const can_elide = operand == .local and operand.local == local.new_local; |
| 4463 | fn bitcast(f: *Function, dest_ty: Type, operand: CValue, operand_ty: Type) !LocalResult { |
| 4464 | const target = f.object.dg.module.getTarget(); |
| 4465 | const writer = f.object.writer(); |
| 4431 | 4466 | |
| 4432 | 4467 | if (operand_ty.isAbiInt() and dest_ty.isAbiInt()) { |
| 4433 | | if (can_elide) return local; |
| 4434 | 4468 | const src_info = dest_ty.intInfo(target); |
| 4435 | 4469 | const dest_info = operand_ty.intInfo(target); |
| 4436 | 4470 | if (src_info.signedness == dest_info.signedness and |
| 4437 | 4471 | src_info.bits == dest_info.bits) |
| 4438 | 4472 | { |
| 4439 | | try f.writeCValue(writer, local, .Other); |
| 4440 | | try writer.writeAll(" = "); |
| 4441 | | try f.writeCValue(writer, operand, .Initializer); |
| 4442 | | try writer.writeAll(";\n"); |
| 4443 | | return local; |
| 4473 | return .{ |
| 4474 | .c_value = operand, |
| 4475 | .need_free = false, |
| 4476 | }; |
| 4444 | 4477 | } |
| 4445 | 4478 | } |
| 4446 | 4479 | |
| 4447 | 4480 | if (dest_ty.isPtrAtRuntime() and operand_ty.isPtrAtRuntime()) { |
| 4448 | | if (can_elide) return local; |
| 4481 | const local = try f.allocLocal(0, dest_ty); |
| 4449 | 4482 | try f.writeCValue(writer, local, .Other); |
| 4450 | 4483 | try writer.writeAll(" = ("); |
| 4451 | 4484 | try f.renderType(writer, dest_ty); |
| 4452 | 4485 | try writer.writeByte(')'); |
| 4453 | 4486 | try f.writeCValue(writer, operand, .Other); |
| 4454 | 4487 | try writer.writeAll(";\n"); |
| 4455 | | return local; |
| 4488 | return .{ |
| 4489 | .c_value = local, |
| 4490 | .need_free = true, |
| 4491 | }; |
| 4456 | 4492 | } |
| 4457 | 4493 | |
| 4458 | 4494 | const operand_lval = if (operand == .constant) blk: { |
| 4459 | | const operand_local = try f.allocLocal(inst, operand_ty); |
| 4495 | const operand_local = try f.allocLocal(0, operand_ty); |
| 4460 | 4496 | try f.writeCValue(writer, operand_local, .Other); |
| 4461 | | try writer.writeAll(" = "); |
| 4497 | if (operand_ty.isAbiInt()) { |
| 4498 | try writer.writeAll(" = "); |
| 4499 | } else { |
| 4500 | try writer.writeAll(" = ("); |
| 4501 | try f.renderType(writer, operand_ty); |
| 4502 | try writer.writeByte(')'); |
| 4503 | } |
| 4462 | 4504 | try f.writeCValue(writer, operand, .Initializer); |
| 4463 | 4505 | try writer.writeAll(";\n"); |
| 4464 | 4506 | break :blk operand_local; |
| 4465 | 4507 | } else operand; |
| 4466 | 4508 | |
| 4509 | const local = try f.allocLocal(0, dest_ty); |
| 4467 | 4510 | try writer.writeAll("memcpy(&"); |
| 4468 | 4511 | try f.writeCValue(writer, local, .Other); |
| 4469 | 4512 | try writer.writeAll(", &"); |
| ... | ... | @@ -4528,10 +4571,13 @@ fn airBitcast(f: *Function, inst: Air.Inst.Index) !CValue { |
| 4528 | 4571 | } |
| 4529 | 4572 | |
| 4530 | 4573 | if (operand == .constant) { |
| 4531 | | try freeLocal(f, inst, operand_lval.new_local, 0); |
| 4574 | try freeLocal(f, 0, operand_lval.new_local, 0); |
| 4532 | 4575 | } |
| 4533 | 4576 | |
| 4534 | | return local; |
| 4577 | return .{ |
| 4578 | .c_value = local, |
| 4579 | .need_free = true, |
| 4580 | }; |
| 4535 | 4581 | } |
| 4536 | 4582 | |
| 4537 | 4583 | fn airTrap(writer: anytype) !CValue { |
| ... | ... | @@ -6288,15 +6334,27 @@ fn airMemset(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue { |
| 6288 | 6334 | } |
| 6289 | 6335 | try writer.writeAll("; ++"); |
| 6290 | 6336 | try f.writeCValue(writer, index, .Other); |
| 6291 | | try writer.writeAll(") (("); |
| 6292 | | try f.renderType(writer, elem_ptr_ty); |
| 6293 | | try writer.writeByte(')'); |
| 6294 | | try writeSliceOrPtr(f, writer, dest_slice, dest_ty); |
| 6295 | | try writer.writeAll(")["); |
| 6296 | | try f.writeCValue(writer, index, .Other); |
| 6297 | | try writer.writeAll("] = "); |
| 6298 | | try f.writeCValue(writer, value, .FunctionArgument); |
| 6299 | | try writer.writeAll(";\n"); |
| 6337 | try writer.writeAll(") "); |
| 6338 | if (lowersToArray(elem_ty, target)) { |
| 6339 | // Arrays are not assignable, so we use memcpy here. |
| 6340 | try writer.writeAll("memcpy("); |
| 6341 | try writeSliceOrPtr(f, writer, dest_slice, dest_ty); |
| 6342 | try writer.writeAll("["); |
| 6343 | try f.writeCValue(writer, index, .Other); |
| 6344 | try writer.writeAll("], "); |
| 6345 | try f.writeCValue(writer, value, .FunctionArgument); |
| 6346 | try writer.print(", {d});\n", .{elem_abi_size}); |
| 6347 | } else { |
| 6348 | try writer.writeAll("(("); |
| 6349 | try f.renderType(writer, elem_ptr_ty); |
| 6350 | try writer.writeByte(')'); |
| 6351 | try writeSliceOrPtr(f, writer, dest_slice, dest_ty); |
| 6352 | try writer.writeAll(")["); |
| 6353 | try f.writeCValue(writer, index, .Other); |
| 6354 | try writer.writeAll("] = "); |
| 6355 | try f.writeCValue(writer, value, .FunctionArgument); |
| 6356 | try writer.writeAll(";\n"); |
| 6357 | } |
| 6300 | 6358 | |
| 6301 | 6359 | try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); |
| 6302 | 6360 | try freeLocal(f, inst, index.new_local, 0); |
| ... | ... | @@ -6304,12 +6362,14 @@ fn airMemset(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue { |
| 6304 | 6362 | return .none; |
| 6305 | 6363 | } |
| 6306 | 6364 | |
| 6365 | const bitcasted = try bitcast(f, Type.u8, value, elem_ty); |
| 6366 | |
| 6307 | 6367 | try writer.writeAll("memset("); |
| 6308 | 6368 | switch (dest_ty.ptrSize()) { |
| 6309 | 6369 | .Slice => { |
| 6310 | 6370 | try f.writeCValueMember(writer, dest_slice, .{ .identifier = "ptr" }); |
| 6311 | 6371 | try writer.writeAll(", "); |
| 6312 | | try f.writeCValue(writer, value, .FunctionArgument); |
| 6372 | try f.writeCValue(writer, bitcasted.c_value, .FunctionArgument); |
| 6313 | 6373 | try writer.writeAll(", "); |
| 6314 | 6374 | try f.writeCValueMember(writer, dest_slice, .{ .identifier = "len" }); |
| 6315 | 6375 | try writer.writeAll(");\n"); |
| ... | ... | @@ -6320,11 +6380,12 @@ fn airMemset(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue { |
| 6320 | 6380 | |
| 6321 | 6381 | try f.writeCValue(writer, dest_slice, .FunctionArgument); |
| 6322 | 6382 | try writer.writeAll(", "); |
| 6323 | | try f.writeCValue(writer, value, .FunctionArgument); |
| 6383 | try f.writeCValue(writer, bitcasted.c_value, .FunctionArgument); |
| 6324 | 6384 | try writer.print(", {d});\n", .{len}); |
| 6325 | 6385 | }, |
| 6326 | 6386 | .Many, .C => unreachable, |
| 6327 | 6387 | } |
| 6388 | try bitcasted.free(f); |
| 6328 | 6389 | try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); |
| 6329 | 6390 | return .none; |
| 6330 | 6391 | } |