From b7f18164f96f7e695d295c12c06fddf25803b08b Mon Sep 17 00:00:00 2001 From: Vexu Date: Thu, 19 Dec 2019 21:30:51 +0200 Subject: [PATCH] translate-c-2 add missing casts --- src-self-hosted/translate_c.zig | 48 ++++++++- test/translate_c.zig | 185 +++++++++++++++++++++----------- 2 files changed, 166 insertions(+), 67 deletions(-) diff --git a/src-self-hosted/translate_c.zig b/src-self-hosted/translate_c.zig index aa7fe335aefdf1153e52b75bf826efe4a0ef6ce8..aa6f06db3928231b0d94ee32a54122f316c4861c 100644 --- a/src-self-hosted/translate_c.zig +++ b/src-self-hosted/translate_c.zig @@ -1210,10 +1210,10 @@ fn transImplicitCastExpr( const c = rp.c; const sub_expr = ZigClangImplicitCastExpr_getSubExpr(expr); const sub_expr_node = try transExpr(rp, scope, @ptrCast(*const ZigClangExpr, sub_expr), .used, .r_value); + const dest_type = getExprQualType(c, @ptrCast(*const ZigClangExpr, expr)); + const src_type = getExprQualType(c, sub_expr); switch (ZigClangImplicitCastExpr_getCastKind(expr)) { .BitCast, .FloatingCast, .FloatingToIntegral, .IntegralToFloating, .IntegralCast => { - const dest_type = getExprQualType(c, @ptrCast(*const ZigClangExpr, expr)); - const src_type = getExprQualType(c, sub_expr); return transCCast(rp, scope, ZigClangImplicitCastExpr_getBeginLoc(expr), dest_type, src_type, sub_expr_node); }, .LValueToRValue, .NoOp, .FunctionToPointerDecay, .ArrayToPointerDecay => { @@ -1222,6 +1222,47 @@ fn transImplicitCastExpr( .NullToPointer => { return try transCreateNodeNullLiteral(rp.c); }, + .PointerToBoolean => { + // @ptrToInt(val) != 0 + const ptr_to_int = try transCreateNodeBuiltinFnCall(rp.c, "@ptrToInt"); + try ptr_to_int.params.push(try transExpr(rp, scope, sub_expr, .used, .r_value)); + ptr_to_int.rparen_token = try appendToken(rp.c, .RParen, ")"); + + const op_token = try appendToken(rp.c, .BangEqual, "!="); + const rhs_node = try transCreateNodeInt(rp.c, 0); + return transCreateNodeInfixOp(rp, scope, &ptr_to_int.base, .BangEqual, op_token, rhs_node, result_used, false); + }, + .IntegralToBoolean => { + // val != 0 + const node = try transExpr(rp, scope, sub_expr, .used, .r_value); + + const op_token = try appendToken(rp.c, .BangEqual, "!="); + const rhs_node = try transCreateNodeInt(rp.c, 0); + return transCreateNodeInfixOp(rp, scope, node, .BangEqual, op_token, rhs_node, result_used, false); + }, + .PointerToIntegral => { + // @intCast(dest_type, @ptrToInt(val)) + const cast_node = try transCreateNodeBuiltinFnCall(rp.c, "@intCast"); + try cast_node.params.push(try transQualType(rp, dest_type, ZigClangImplicitCastExpr_getBeginLoc(expr))); + _ = try appendToken(rp.c, .Comma, ","); + + const ptr_to_int = try transCreateNodeBuiltinFnCall(rp.c, "@ptrToInt"); + try ptr_to_int.params.push(try transExpr(rp, scope, sub_expr, .used, .r_value)); + ptr_to_int.rparen_token = try appendToken(rp.c, .RParen, ")"); + try cast_node.params.push(&ptr_to_int.base); + cast_node.rparen_token = try appendToken(rp.c, .RParen, ")"); + return maybeSuppressResult(rp, scope, result_used, &cast_node.base); + }, + .IntegralToPointer => { + // @intToPtr(dest_type, val) + const int_to_ptr = try transCreateNodeBuiltinFnCall(rp.c, "@intToPtr"); + try int_to_ptr.params.push(try transQualType(rp, dest_type, ZigClangImplicitCastExpr_getBeginLoc(expr))); + _ = try appendToken(rp.c, .Comma, ","); + + try int_to_ptr.params.push(try transExpr(rp, scope, sub_expr, .used, .r_value)); + int_to_ptr.rparen_token = try appendToken(rp.c, .RParen, ")"); + return maybeSuppressResult(rp, scope, result_used, &int_to_ptr.base); + }, else => |kind| return revertAndWarn( rp, error.UnsupportedTranslation, @@ -2224,6 +2265,9 @@ fn transUnaryOperator(rp: RestorePoint, scope: *Scope, stmt: *const ZigClangUnar op_node.rhs = try transBoolExpr(rp, scope, op_expr, .used, .r_value, true); return &op_node.base; }, + .Extension => { + return transExpr(rp, scope, ZigClangUnaryOperator_getSubExpr(stmt), used, .l_value); + }, else => return revertAndWarn(rp, error.UnsupportedTranslation, ZigClangUnaryOperator_getBeginLoc(stmt), "unsupported C translation {}", .{ZigClangUnaryOperator_getOpcode(stmt)}), } } diff --git a/test/translate_c.zig b/test/translate_c.zig index 517a1907565f1bacce218399ea57233a45201d89..9bafe90d2a25d6731e9cdf477d4be8f13252ab1b 100644 --- a/test/translate_c.zig +++ b/test/translate_c.zig @@ -819,6 +819,16 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\} }); + cases.addC("__extension__ cast", + \\int foo(void) { + \\ return __extension__ 1; + \\} + , &[_][]const u8{ + \\pub export fn foo() c_int { + \\ return 1; + \\} + }); + /////////////// Cases that pass for only stage2 //////////////// cases.add_2("Parameterless function prototypes", @@ -2031,6 +2041,61 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\} }); + cases.add_2("implicit casts", + \\#include + \\ + \\void fn_int(int x); + \\void fn_f32(float x); + \\void fn_f64(double x); + \\void fn_char(char x); + \\void fn_bool(bool x); + \\void fn_ptr(void *x); + \\ + \\void call(int q) { + \\ fn_int(3.0f); + \\ fn_int(3.0); + \\ fn_int(3.0L); + \\ fn_int('ABCD'); + \\ fn_f32(3); + \\ fn_f64(3); + \\ fn_char('3'); + \\ fn_char('\x1'); + \\ fn_char(0); + \\ fn_f32(3.0f); + \\ fn_f64(3.0); + \\ fn_bool(123); + \\ fn_bool(0); + \\ fn_bool(&fn_int); + \\ fn_int(&fn_int); + \\ fn_ptr(42); + \\} + , &[_][]const u8{ + \\pub extern fn fn_int(x: c_int) void; + \\pub extern fn fn_f32(x: f32) void; + \\pub extern fn fn_f64(x: f64) void; + \\pub extern fn fn_char(x: u8) void; + \\pub extern fn fn_bool(x: bool) void; + \\pub extern fn fn_ptr(x: ?*c_void) void; + \\pub export fn call(q: c_int) void { + \\ fn_int(@floatToInt(c_int, 3)); + \\ fn_int(@floatToInt(c_int, 3)); + \\ fn_int(@floatToInt(c_int, 3)); + \\ fn_int(1094861636); + \\ fn_f32(@intToFloat(f32, 3)); + \\ fn_f64(@intToFloat(f64, 3)); + \\ fn_char(@as(u8, '3')); + \\ fn_char(@as(u8, '\x01')); + \\ fn_char(@as(u8, 0)); + \\ fn_f32(3); + \\ fn_f64(3); + \\ fn_bool(123 != 0); + \\ fn_bool(0 != 0); + \\ fn_bool(@ptrToInt(&fn_int) != 0); + \\ fn_int(@intCast(c_int, @ptrToInt(&fn_int))); + \\ fn_ptr(@intToPtr(?*c_void, 42)); + \\} + }); + /////////////// Cases for only stage1 which are TODO items for stage2 //////////////// cases.add("macro defines string literal with hex", @@ -2057,71 +2122,6 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\pub const FOO_CHAR = 63; }); - cases.addC("__extension__ cast", - \\int foo(void) { - \\ return __extension__ 1; - \\} - , &[_][]const u8{ - \\pub export fn foo() c_int { - \\ return 1; - \\} - }); - - cases.addC("implicit casts", - \\#include - \\ - \\void fn_int(int x); - \\void fn_f32(float x); - \\void fn_f64(double x); - \\void fn_char(char x); - \\void fn_bool(bool x); - \\void fn_ptr(void *x); - \\ - \\void call(int q) { - \\ fn_int(3.0f); - \\ fn_int(3.0); - \\ fn_int(3.0L); - \\ fn_int('ABCD'); - \\ fn_f32(3); - \\ fn_f64(3); - \\ fn_char('3'); - \\ fn_char('\x1'); - \\ fn_char(0); - \\ fn_f32(3.0f); - \\ fn_f64(3.0); - \\ fn_bool(123); - \\ fn_bool(0); - \\ fn_bool(&fn_int); - \\ fn_int(&fn_int); - \\ fn_ptr(42); - \\} - , &[_][]const u8{ - \\pub extern fn fn_int(x: c_int) void; - \\pub extern fn fn_f32(x: f32) void; - \\pub extern fn fn_f64(x: f64) void; - \\pub extern fn fn_char(x: u8) void; - \\pub extern fn fn_bool(x: bool) void; - \\pub extern fn fn_ptr(x: ?*c_void) void; - \\pub export fn call(q: c_int) void { - \\ fn_int(@floatToInt(c_int, 3.000000)); - \\ fn_int(@floatToInt(c_int, 3.000000)); - \\ fn_int(@floatToInt(c_int, 3.000000)); - \\ fn_int(1094861636); - \\ fn_f32(@intToFloat(f32, 3)); - \\ fn_f64(@intToFloat(f64, 3)); - \\ fn_char(@as(u8, '3')); - \\ fn_char(@as(u8, '\x01')); - \\ fn_char(@as(u8, 0)); - \\ fn_f32(3.000000); - \\ fn_f64(3.000000); - \\ fn_bool(true); - \\ fn_bool(false); - \\ fn_bool(@ptrToInt(&fn_int) != 0); - \\ fn_int(@intCast(c_int, @ptrToInt(&fn_int))); - \\ fn_ptr(@intToPtr(?*c_void, 42)); - \\} - }); - if (builtin.os != builtin.Os.windows) { // sysv_abi not currently supported on windows cases.add("Macro qualified functions", @@ -2990,4 +2990,59 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\ }); \\} }); + + cases.addC("implicit casts", + \\#include + \\ + \\void fn_int(int x); + \\void fn_f32(float x); + \\void fn_f64(double x); + \\void fn_char(char x); + \\void fn_bool(bool x); + \\void fn_ptr(void *x); + \\ + \\void call(int q) { + \\ fn_int(3.0f); + \\ fn_int(3.0); + \\ fn_int(3.0L); + \\ fn_int('ABCD'); + \\ fn_f32(3); + \\ fn_f64(3); + \\ fn_char('3'); + \\ fn_char('\x1'); + \\ fn_char(0); + \\ fn_f32(3.0f); + \\ fn_f64(3.0); + \\ fn_bool(123); + \\ fn_bool(0); + \\ fn_bool(&fn_int); + \\ fn_int(&fn_int); + \\ fn_ptr(42); + \\} + , &[_][]const u8{ + \\pub extern fn fn_int(x: c_int) void; + \\pub extern fn fn_f32(x: f32) void; + \\pub extern fn fn_f64(x: f64) void; + \\pub extern fn fn_char(x: u8) void; + \\pub extern fn fn_bool(x: bool) void; + \\pub extern fn fn_ptr(x: ?*c_void) void; + \\pub export fn call(q: c_int) void { + \\ fn_int(@floatToInt(c_int, 3.000000)); + \\ fn_int(@floatToInt(c_int, 3.000000)); + \\ fn_int(@floatToInt(c_int, 3.000000)); + \\ fn_int(1094861636); + \\ fn_f32(@intToFloat(f32, 3)); + \\ fn_f64(@intToFloat(f64, 3)); + \\ fn_char(@as(u8, '3')); + \\ fn_char(@as(u8, '\x01')); + \\ fn_char(@as(u8, 0)); + \\ fn_f32(3.000000); + \\ fn_f64(3.000000); + \\ fn_bool(true); + \\ fn_bool(false); + \\ fn_bool(@ptrToInt(&fn_int) != 0); + \\ fn_int(@intCast(c_int, @ptrToInt(&fn_int))); + \\ fn_ptr(@intToPtr(?*c_void, 42)); + \\} + }); } -- 2.54.0