diff options
| author | Andrew Kelley <andrew@ziglang.org> | 2021-10-28 18:33:13 -0700 |
|---|---|---|
| committer | Andrew Kelley <andrew@ziglang.org> | 2021-10-28 18:33:13 -0700 |
| commit | bbe4a9fa991d1d0756323e67ed546a58d2d2be7e (patch) | |
| tree | f9b4827a1408a156eb65ee82eb9c9f138f8698fa /src/codegen/c.zig | |
| parent | 98009a2f66de32d1ea4df41cc03d5ad3d723b3ed (diff) | |
| download | zig-bbe4a9fa991d1d0756323e67ed546a58d2d2be7e.tar.gz zig-bbe4a9fa991d1d0756323e67ed546a58d2d2be7e.zip | |
C backend: implement trunc for unsigned non-pow2 ints
Diffstat (limited to 'src/codegen/c.zig')
| -rw-r--r-- | src/codegen/c.zig | 53 |
1 files changed, 45 insertions, 8 deletions
diff --git a/src/codegen/c.zig b/src/codegen/c.zig index 444adf0aa1..3ab74a85be 100644 --- a/src/codegen/c.zig +++ b/src/codegen/c.zig @@ -501,14 +501,9 @@ pub const DeclGen = struct { .signed => "", .unsigned => "u", }; - inline for (.{ 8, 16, 32, 64, 128 }) |nbits| { - if (info.bits <= nbits) { - try w.print("{s}int{d}_t", .{ sign_prefix, nbits }); - break; - } - } else { + const c_bits = toCIntBits(info.bits) orelse return dg.fail("TODO: C backend: implement integer types larger than 128 bits", .{}); - } + try w.print("{s}int{d}_t", .{ sign_prefix, c_bits }); }, else => unreachable, } @@ -1089,6 +1084,7 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO .call => try airCall(f, inst), .dbg_stmt => try airDbgStmt(f, inst), .intcast => try airIntCast(f, inst), + .trunc => try airTrunc(f, inst), .bool_to_int => try airBoolToInt(f, inst), .load => try airLoad(f, inst), .ret => try airRet(f, inst), @@ -1116,7 +1112,6 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO .float_to_int, .fptrunc, .fpext, - .trunc, => try airSimpleCast(f, inst), .ptrtoint => try airPtrToInt(f, inst), @@ -1366,6 +1361,39 @@ fn airIntCast(f: *Function, inst: Air.Inst.Index) !CValue { return local; } +fn airTrunc(f: *Function, inst: Air.Inst.Index) !CValue { + if (f.liveness.isUnused(inst)) return CValue.none; + + const inst_ty = f.air.typeOfIndex(inst); + const local = try f.allocLocal(inst_ty, .Const); + const ty_op = f.air.instructions.items(.data)[inst].ty_op; + const writer = f.object.writer(); + const operand = try f.resolveInst(ty_op.operand); + const target = f.object.dg.module.getTarget(); + const dest_int_info = inst_ty.intInfo(target); + const dest_bits = dest_int_info.bits; + + try writer.writeAll(" = "); + + if (dest_bits >= 8 and std.math.isPowerOfTwo(dest_bits)) { + try f.writeCValue(writer, operand); + try writer.writeAll(";\n"); + return local; + } + + switch (dest_int_info.signedness) { + .unsigned => { + try f.writeCValue(writer, operand); + const mask = (@as(u65, 1) << @intCast(u7, dest_bits)) - 1; + try writer.print(" & {d}ULL;\n", .{mask}); + return local; + }, + .signed => { + return f.fail("TODO: C backend: implement trunc for signed integers", .{}); + }, + } +} + fn airBoolToInt(f: *Function, inst: Air.Inst.Index) !CValue { if (f.liveness.isUnused(inst)) return CValue.none; @@ -2615,3 +2643,12 @@ fn IndentWriter(comptime UnderlyingWriter: type) type { } }; } + +fn toCIntBits(zig_bits: u32) ?u32 { + for (&[_]u8{ 8, 16, 32, 64, 128 }) |c_bits| { + if (zig_bits <= c_bits) { + return c_bits; + } + } + return null; +} |
