authorgravatar for kcbanner@gmail.comCasey Banner <kcbanner@gmail.com> 2022-12-10 18:17:36-05:00
committergravatar for kcbanner@gmail.comCasey Banner <kcbanner@gmail.com> 2023-01-01 16:44:28-05:00
log36212e9d178c32facd0d9d0c1069327758efb943
tree923b1afc3c6370e55a05e3135955f0afb6eb90e4
parentc675a8e35c1c9296fe98e98c19acfa22dd1d9a23

cbe: msvc compatibility for > 64 bit intcasts and truncating from > 64 to < 64 bit

- Uses zig_as/zig_lo as necessary when int casting to support !zig_has_int128 - Remove redundant cast if the type is the same - Use zig_lo when truncating > 64 bits

1 files changed, 63 insertions(+), 17 deletions(-)

src/codegen/c.zig+63-17
...@@ -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);
33873419
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 }
33923435
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 {
34043446
3405 const mask_val = try inst_ty.maxInt(stack.get(), target);3447 const mask_val = try inst_ty.maxInt(stack.get(), target);
34063448
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);
34203462
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}
34283474
...@@ -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 }
70127058
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('-');