| ... | ... | @@ -3350,21 +3350,49 @@ fn airIntCast(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3350 | 3350 | const writer = f.object.writer(); |
| 3351 | 3351 | const inst_ty = f.air.typeOfIndex(inst); |
| 3352 | 3352 | const local = try f.allocLocal(inst, inst_ty); |
| 3353 | const inst_bits = inst_ty.bitSize(target); |
| 3354 | const inst_int_info = inst_ty.intInfo(target); |
| 3355 | const operand_ty = f.air.typeOf(ty_op.operand); |
| 3356 | const operand_bits = operand_ty.bitSize(target); |
| 3357 | const operand_int_info = operand_ty.intInfo(target); |
| 3358 | |
| 3353 | 3359 | try f.writeCValue(writer, local, .Other); |
| 3354 | 3360 | try writer.writeAll(" = "); |
| 3355 | | const cant_cast = inst_ty.isInt() and inst_ty.bitSize(target) > 64; |
| 3356 | | if (cant_cast) { |
| 3357 | | if (f.air.typeOf(ty_op.operand).bitSize(target) > 64) return f.fail("TODO: C backend: implement casting between types > 64 bits", .{}); |
| 3361 | |
| 3362 | if (inst_bits <= 64 and operand_bits <= 64) { |
| 3363 | if (toCIntBits(inst_int_info.bits) != toCIntBits(operand_int_info.bits) or inst_int_info.signedness != operand_int_info.signedness) { |
| 3364 | try writer.writeByte('('); |
| 3365 | try f.renderTypecast(writer, inst_ty); |
| 3366 | try writer.writeByte(')'); |
| 3367 | } |
| 3368 | |
| 3369 | try f.writeCValue(writer, operand, .Other); |
| 3370 | } else if (inst_bits > 64 and operand_bits <= 64) { |
| 3358 | 3371 | try writer.writeAll("zig_as_"); |
| 3359 | 3372 | try f.object.dg.renderTypeForBuiltinFnName(writer, inst_ty); |
| 3360 | | try writer.writeAll("(0, "); |
| 3361 | | } else { |
| 3373 | try writer.writeAll("(0, "); // TODO: Should the 0 go through fmtIntLiteral? |
| 3374 | try f.writeCValue(writer, operand, .FunctionArgument); |
| 3375 | try writer.writeByte(')'); |
| 3376 | } else if (inst_bits <= 64 and operand_bits > 64) { |
| 3377 | try writer.writeAll("zig_lo_"); |
| 3378 | try f.object.dg.renderTypeForBuiltinFnName(writer, operand_ty); |
| 3362 | 3379 | try writer.writeByte('('); |
| 3363 | | try f.renderTypecast(writer, inst_ty); |
| 3380 | try f.writeCValue(writer, operand, .FunctionArgument); |
| 3364 | 3381 | try writer.writeByte(')'); |
| 3382 | } else { |
| 3383 | try writer.writeAll("zig_as_"); |
| 3384 | try f.object.dg.renderTypeForBuiltinFnName(writer, inst_ty); |
| 3385 | try writer.writeAll("(zig_hi_"); |
| 3386 | try f.object.dg.renderTypeForBuiltinFnName(writer, operand_ty); |
| 3387 | try writer.writeByte('('); |
| 3388 | try f.writeCValue(writer, operand, .FunctionArgument); |
| 3389 | try writer.writeAll("), zig_lo_"); |
| 3390 | try f.object.dg.renderTypeForBuiltinFnName(writer, operand_ty); |
| 3391 | try writer.writeByte('('); |
| 3392 | try f.writeCValue(writer, operand, .FunctionArgument); |
| 3393 | try writer.writeAll("))"); |
| 3365 | 3394 | } |
| 3366 | | try f.writeCValue(writer, operand, .Other); |
| 3367 | | if (cant_cast) try writer.writeByte(')'); |
| 3395 | |
| 3368 | 3396 | try writer.writeAll(";\n"); |
| 3369 | 3397 | return local; |
| 3370 | 3398 | } |
| ... | ... | @@ -3384,15 +3412,29 @@ fn airTrunc(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3384 | 3412 | const target = f.object.dg.module.getTarget(); |
| 3385 | 3413 | const dest_int_info = inst_ty.intInfo(target); |
| 3386 | 3414 | const dest_bits = dest_int_info.bits; |
| 3415 | const dest_c_bits = toCIntBits(dest_int_info.bits) orelse |
| 3416 | return f.fail("TODO: C backend: implement integer types larger than 128 bits", .{}); |
| 3417 | const operand_ty = f.air.typeOf(ty_op.operand); |
| 3418 | const operand_int_info = operand_ty.intInfo(target); |
| 3387 | 3419 | |
| 3388 | 3420 | try f.writeCValue(writer, local, .Other); |
| 3389 | | try writer.writeAll(" = ("); |
| 3390 | | try f.renderTypecast(writer, inst_ty); |
| 3391 | | try writer.writeByte(')'); |
| 3421 | try writer.writeAll(" = "); |
| 3422 | |
| 3423 | const needs_lo = operand_int_info.bits > 64 and dest_bits <= 64; |
| 3424 | if (!needs_lo or dest_c_bits != 64 or dest_int_info.signedness != operand_int_info.signedness) { |
| 3425 | try writer.writeByte('('); |
| 3426 | try f.renderTypecast(writer, inst_ty); |
| 3427 | try writer.writeByte(')'); |
| 3428 | } |
| 3429 | |
| 3430 | if (needs_lo) { |
| 3431 | try writer.writeAll("zig_lo_"); |
| 3432 | try f.object.dg.renderTypeForBuiltinFnName(writer, operand_ty); |
| 3433 | try writer.writeByte('('); |
| 3434 | } |
| 3392 | 3435 | |
| 3393 | 3436 | if (dest_bits >= 8 and std.math.isPowerOfTwo(dest_bits)) { |
| 3394 | 3437 | try f.writeCValue(writer, operand, .Other); |
| 3395 | | try writer.writeAll(";\n"); |
| 3396 | 3438 | } else switch (dest_int_info.signedness) { |
| 3397 | 3439 | .unsigned => { |
| 3398 | 3440 | var arena = std.heap.ArenaAllocator.init(f.object.dg.gpa); |
| ... | ... | @@ -3404,13 +3446,13 @@ fn airTrunc(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3404 | 3446 | |
| 3405 | 3447 | const mask_val = try inst_ty.maxInt(stack.get(), target); |
| 3406 | 3448 | |
| 3449 | // TODO: This needs to use _and_ to do this to support > 64 bits and !zig_has_int128 |
| 3407 | 3450 | try writer.writeByte('('); |
| 3408 | 3451 | try f.writeCValue(writer, operand, .Other); |
| 3409 | | try writer.print(" & {x});\n", .{try f.fmtIntLiteral(inst_ty, mask_val)}); |
| 3452 | try writer.print(" & {x})", .{try f.fmtIntLiteral(inst_ty, mask_val)}); |
| 3410 | 3453 | }, |
| 3411 | 3454 | .signed => { |
| 3412 | | const operand_ty = f.air.typeOf(ty_op.operand); |
| 3413 | | const c_bits = toCIntBits(operand_ty.intInfo(target).bits) orelse |
| 3455 | const c_bits = toCIntBits(operand_int_info.bits) orelse |
| 3414 | 3456 | return f.fail("TODO: C backend: implement integer types larger than 128 bits", .{}); |
| 3415 | 3457 | var shift_pl = Value.Payload.U64{ |
| 3416 | 3458 | .base = .{ .tag = .int_u64 }, |
| ... | ... | @@ -3418,11 +3460,15 @@ fn airTrunc(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3418 | 3460 | }; |
| 3419 | 3461 | const shift_val = Value.initPayload(&shift_pl.base); |
| 3420 | 3462 | |
| 3463 | // TODO: This needs to use shl and shr to do this to support > 64 bits and !zig_has_int128 |
| 3421 | 3464 | try writer.print("((int{d}_t)((uint{0d}_t)", .{c_bits}); |
| 3422 | 3465 | try f.writeCValue(writer, operand, .Other); |
| 3423 | | try writer.print(" << {}) >> {0});\n", .{try f.fmtIntLiteral(Type.u8, shift_val)}); |
| 3466 | try writer.print(" << {}) >> {0})", .{try f.fmtIntLiteral(Type.u8, shift_val)}); |
| 3424 | 3467 | }, |
| 3425 | 3468 | } |
| 3469 | |
| 3470 | if (needs_lo) try writer.writeByte(')'); |
| 3471 | try writer.writeAll(";\n"); |
| 3426 | 3472 | return local; |
| 3427 | 3473 | } |
| 3428 | 3474 | |
| ... | ... | @@ -7010,9 +7056,9 @@ fn formatIntLiteral( |
| 7010 | 7056 | return writer.print("{s}_{s}", .{ abbrev, if (int.positive) "MAX" else "MIN" }); |
| 7011 | 7057 | } |
| 7012 | 7058 | |
| 7013 | | // TODO: If > 64 bit, need to use a subtract from zero fn here instead of negate |
| 7014 | 7059 | if (!int.positive) { |
| 7015 | 7060 | if (c_bits > 64) { |
| 7061 | // TODO: Could use negate function instead? |
| 7016 | 7062 | try writer.print("zig_sub_{c}{d}(zig_as_{c}{d}(0, 0), ", .{ signAbbrev(int_info.signedness), c_bits, signAbbrev(int_info.signedness), c_bits }); |
| 7017 | 7063 | } else { |
| 7018 | 7064 | try writer.writeByte('-'); |