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 {
33503350 const writer = f.object.writer();
33513351 const inst_ty = f.air.typeOfIndex(inst);
33523352 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
33533359 try f.writeCValue(writer, local, .Other);
33543360 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) {
33583371 try writer.writeAll("zig_as_");
33593372 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);
33623379 try writer.writeByte('(');
3363 try f.renderTypecast(writer, inst_ty);
3380 try f.writeCValue(writer, operand, .FunctionArgument);
33643381 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("))");
33653394 }
3366 try f.writeCValue(writer, operand, .Other);
3367 if (cant_cast) try writer.writeByte(')');
3395
33683396 try writer.writeAll(";\n");
33693397 return local;
33703398}
......@@ -3384,15 +3412,29 @@ fn airTrunc(f: *Function, inst: Air.Inst.Index) !CValue {
33843412 const target = f.object.dg.module.getTarget();
33853413 const dest_int_info = inst_ty.intInfo(target);
33863414 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
33883420 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 }
33923435
33933436 if (dest_bits >= 8 and std.math.isPowerOfTwo(dest_bits)) {
33943437 try f.writeCValue(writer, operand, .Other);
3395 try writer.writeAll(";\n");
33963438 } else switch (dest_int_info.signedness) {
33973439 .unsigned => {
33983440 var arena = std.heap.ArenaAllocator.init(f.object.dg.gpa);
......@@ -3404,13 +3446,13 @@ fn airTrunc(f: *Function, inst: Air.Inst.Index) !CValue {
34043446
34053447 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
34073450 try writer.writeByte('(');
34083451 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)});
34103453 },
34113454 .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
34143456 return f.fail("TODO: C backend: implement integer types larger than 128 bits", .{});
34153457 var shift_pl = Value.Payload.U64{
34163458 .base = .{ .tag = .int_u64 },
......@@ -3418,11 +3460,15 @@ fn airTrunc(f: *Function, inst: Air.Inst.Index) !CValue {
34183460 };
34193461 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
34213464 try writer.print("((int{d}_t)((uint{0d}_t)", .{c_bits});
34223465 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)});
34243467 },
34253468 }
3469
3470 if (needs_lo) try writer.writeByte(')');
3471 try writer.writeAll(";\n");
34263472 return local;
34273473}
34283474
......@@ -7010,9 +7056,9 @@ fn formatIntLiteral(
70107056 return writer.print("{s}_{s}", .{ abbrev, if (int.positive) "MAX" else "MIN" });
70117057 }
70127058
7013 // TODO: If > 64 bit, need to use a subtract from zero fn here instead of negate
70147059 if (!int.positive) {
70157060 if (c_bits > 64) {
7061 // TODO: Could use negate function instead?
70167062 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 });
70177063 } else {
70187064 try writer.writeByte('-');