| ... | @@ -3350,21 +3350,49 @@ fn airIntCast(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -3350,21 +3350,49 @@ fn airIntCast(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3350 | const writer = f.object.writer(); | 3350 | const writer = f.object.writer(); |
| 3351 | const inst_ty = f.air.typeOfIndex(inst); | 3351 | const inst_ty = f.air.typeOfIndex(inst); |
| 3352 | const local = try f.allocLocal(inst, inst_ty); | 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 | try f.writeCValue(writer, local, .Other); | 3359 | try f.writeCValue(writer, local, .Other); |
| 3354 | try writer.writeAll(" = "); | 3360 | try writer.writeAll(" = "); |
| 3355 | const cant_cast = inst_ty.isInt() and inst_ty.bitSize(target) > 64; | 3361 | |
| 3356 | if (cant_cast) { | 3362 | if (inst_bits <= 64 and operand_bits <= 64) { |
| 3357 | if (f.air.typeOf(ty_op.operand).bitSize(target) > 64) return f.fail("TODO: C backend: implement casting between types > 64 bits", .{}); | 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 | try writer.writeAll("zig_as_"); | 3371 | try writer.writeAll("zig_as_"); |
| 3359 | try f.object.dg.renderTypeForBuiltinFnName(writer, inst_ty); | 3372 | try f.object.dg.renderTypeForBuiltinFnName(writer, inst_ty); |
| 3360 | try writer.writeAll("(0, "); | 3373 | try writer.writeAll("(0, "); // TODO: Should the 0 go through fmtIntLiteral? |
| 3361 | } else { | 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 | try writer.writeByte('('); | 3379 | try writer.writeByte('('); |
| 3363 | try f.renderTypecast(writer, inst_ty); | 3380 | try f.writeCValue(writer, operand, .FunctionArgument); |
| 3364 | try writer.writeByte(')'); | 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); | 3395 | |
| 3367 | if (cant_cast) try writer.writeByte(')'); | | |
| 3368 | try writer.writeAll(";\n"); | 3396 | try writer.writeAll(";\n"); |
| 3369 | return local; | 3397 | return local; |
| 3370 | } | 3398 | } |
| ... | @@ -3384,15 +3412,29 @@ fn airTrunc(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -3384,15 +3412,29 @@ fn airTrunc(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3384 | const target = f.object.dg.module.getTarget(); | 3412 | const target = f.object.dg.module.getTarget(); |
| 3385 | const dest_int_info = inst_ty.intInfo(target); | 3413 | const dest_int_info = inst_ty.intInfo(target); |
| 3386 | const dest_bits = dest_int_info.bits; | 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 | try f.writeCValue(writer, local, .Other); | 3420 | try f.writeCValue(writer, local, .Other); |
| 3389 | try writer.writeAll(" = ("); | 3421 | try writer.writeAll(" = "); |
| 3390 | try f.renderTypecast(writer, inst_ty); | 3422 | |
| 3391 | try writer.writeByte(')'); | 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 | if (dest_bits >= 8 and std.math.isPowerOfTwo(dest_bits)) { | 3436 | if (dest_bits >= 8 and std.math.isPowerOfTwo(dest_bits)) { |
| 3394 | try f.writeCValue(writer, operand, .Other); | 3437 | try f.writeCValue(writer, operand, .Other); |
| 3395 | try writer.writeAll(";\n"); | | |
| 3396 | } else switch (dest_int_info.signedness) { | 3438 | } else switch (dest_int_info.signedness) { |
| 3397 | .unsigned => { | 3439 | .unsigned => { |
| 3398 | var arena = std.heap.ArenaAllocator.init(f.object.dg.gpa); | 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,13 +3446,13 @@ fn airTrunc(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3404 | | 3446 | |
| 3405 | const mask_val = try inst_ty.maxInt(stack.get(), target); | 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 | try writer.writeByte('('); | 3450 | try writer.writeByte('('); |
| 3408 | try f.writeCValue(writer, operand, .Other); | 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 | .signed => { | 3454 | .signed => { |
| 3412 | const operand_ty = f.air.typeOf(ty_op.operand); | 3455 | const c_bits = toCIntBits(operand_int_info.bits) orelse |
| 3413 | const c_bits = toCIntBits(operand_ty.intInfo(target).bits) orelse | | |
| 3414 | return f.fail("TODO: C backend: implement integer types larger than 128 bits", .{}); | 3456 | return f.fail("TODO: C backend: implement integer types larger than 128 bits", .{}); |
| 3415 | var shift_pl = Value.Payload.U64{ | 3457 | var shift_pl = Value.Payload.U64{ |
| 3416 | .base = .{ .tag = .int_u64 }, | 3458 | .base = .{ .tag = .int_u64 }, |
| ... | @@ -3418,11 +3460,15 @@ fn airTrunc(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -3418,11 +3460,15 @@ fn airTrunc(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3418 | }; | 3460 | }; |
| 3419 | const shift_val = Value.initPayload(&shift_pl.base); | 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 | try writer.print("((int{d}_t)((uint{0d}_t)", .{c_bits}); | 3464 | try writer.print("((int{d}_t)((uint{0d}_t)", .{c_bits}); |
| 3422 | try f.writeCValue(writer, operand, .Other); | 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 | return local; | 3472 | return local; |
| 3427 | } | 3473 | } |
| 3428 | | 3474 | |
| ... | @@ -7010,9 +7056,9 @@ fn formatIntLiteral( | ... | @@ -7010,9 +7056,9 @@ fn formatIntLiteral( |
| 7010 | return writer.print("{s}_{s}", .{ abbrev, if (int.positive) "MAX" else "MIN" }); | 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 | if (!int.positive) { | 7059 | if (!int.positive) { |
| 7015 | if (c_bits > 64) { | 7060 | if (c_bits > 64) { |
| | 7061 | // TODO: Could use negate function instead? |
| 7016 | 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 }); | 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 | } else { | 7063 | } else { |
| 7018 | try writer.writeByte('-'); | 7064 | try writer.writeByte('-'); |