From e3f1bfe48388b3c585792367a898a25c58324000 Mon Sep 17 00:00:00 2001 From: Vexu Date: Mon, 16 Dec 2019 17:55:51 +0200 Subject: [PATCH] translate-c-2 if statements --- src-self-hosted/clang.zig | 4 +++ src-self-hosted/translate_c.zig | 59 ++++++++++++++++++++++++++++----- test/translate_c.zig | 23 +++++++++++++ 3 files changed, 78 insertions(+), 8 deletions(-) diff --git a/src-self-hosted/clang.zig b/src-self-hosted/clang.zig index b9435f96f4..381673e704 100644 --- a/src-self-hosted/clang.zig +++ b/src-self-hosted/clang.zig @@ -1036,3 +1036,7 @@ pub extern fn ZigClangPreprocessedEntity_getKind(*const ZigClangPreprocessedEnti pub extern fn ZigClangMacroDefinitionRecord_getName_getNameStart(*const ZigClangMacroDefinitionRecord) [*:0]const u8; pub extern fn ZigClangMacroDefinitionRecord_getSourceRange_getBegin(*const ZigClangMacroDefinitionRecord) ZigClangSourceLocation; pub extern fn ZigClangMacroDefinitionRecord_getSourceRange_getEnd(*const ZigClangMacroDefinitionRecord) ZigClangSourceLocation; + +pub extern fn ZigClangIfStmt_getThen(*const ZigClangIfStmt) *const ZigClangStmt; +pub extern fn ZigClangIfStmt_getElse(*const ZigClangIfStmt) ?*const ZigClangStmt; +pub extern fn ZigClangIfStmt_getCond(*const ZigClangIfStmt) *const ZigClangStmt; diff --git a/src-self-hosted/translate_c.zig b/src-self-hosted/translate_c.zig index fd7db400a1..d8fc5ece9c 100644 --- a/src-self-hosted/translate_c.zig +++ b/src-self-hosted/translate_c.zig @@ -67,18 +67,17 @@ const Scope = struct { variables: AliasList, label: ?[]const u8, - /// Don't forget to set rbrace token later + /// Don't forget to set rbrace token and block_node later fn init(c: *Context, parent: *Scope, want_label: bool) !*Block { // TODO removing `?[]const u8` here causes LLVM error const label: ?[]const u8 = if (want_label) try std.fmt.allocPrint(c.a(), "blk_{}", .{c.getMangle()}) else null; - const block_node = try transCreateNodeBlock(c, label); const block = try c.a().create(Block); block.* = .{ .base = .{ .id = .Block, .parent = parent, }, - .block_node = block_node, + .block_node = undefined, .variables = AliasList.init(c.a()), .label = label, }; @@ -126,7 +125,6 @@ const Scope = struct { }; const Condition = struct { - expr: *ast.Node, base: Scope, }; @@ -612,6 +610,7 @@ fn transStmt( .ParenExprClass => return transExpr(rp, scope, ZigClangParenExpr_getSubExpr(@ptrCast(*const ZigClangParenExpr, stmt)), result_used, lrvalue), .InitListExprClass => return transInitListExpr(rp, scope, @ptrCast(*const ZigClangInitListExpr, stmt), result_used), .ImplicitValueInitExprClass => return transImplicitValueInitExpr(rp, scope, @ptrCast(*const ZigClangExpr, stmt), result_used), + .IfStmtClass => return transIfStmt(rp, scope, @ptrCast(*const ZigClangIfStmt, stmt), result_used), else => { return revertAndWarn( rp, @@ -718,18 +717,31 @@ fn transBinaryOperator( ), .Comma => { const block_scope = try scope.findBlockScope(rp.c); + const expr = block_scope.base.parent == scope; + const lparen = if (expr) blk: { + const l = try appendToken(rp.c, .LParen, "("); + block_scope.block_node = try transCreateNodeBlock(rp.c, block_scope.label); + break :blk l; + } else undefined; const lhs = try transExpr(rp, &block_scope.base, ZigClangBinaryOperator_getLHS(stmt), .unused, .r_value); try block_scope.block_node.statements.push(lhs); const rhs = try transExpr(rp, &block_scope.base, ZigClangBinaryOperator_getRHS(stmt), .used, .r_value); - if (block_scope.base.parent == scope) { + if (expr) { + _ = try appendToken(rp.c, .Semicolon, ";"); const break_node = try transCreateNodeBreak(rp.c, block_scope.label); break_node.rhs = rhs; - _ = try appendToken(rp.c, .Semicolon, ";"); try block_scope.block_node.statements.push(&break_node.base); block_scope.block_node.rbrace = try appendToken(rp.c, .RBrace, "}"); - return maybeSuppressResult(rp, scope, result_used, &block_scope.block_node.base); + const rparen = try appendToken(rp.c, .RParen, ")"); + const grouped_expr = try rp.c.a().create(ast.Node.GroupedExpression); + grouped_expr.* = .{ + .lparen = lparen, + .expr = &block_scope.block_node.base, + .rparen = rparen, + }; + return maybeSuppressResult(rp, scope, result_used, &grouped_expr.base); } else { return maybeSuppressResult(rp, scope, result_used, rhs); } @@ -766,6 +778,7 @@ fn transCompoundStmtInline( fn transCompoundStmt(rp: RestorePoint, scope: *Scope, stmt: *const ZigClangCompoundStmt) TransError!*ast.Node { const block_scope = try Scope.Block.init(rp.c, scope, false); + block_scope.block_node = try transCreateNodeBlock(rp.c, block_scope.label); try transCompoundStmtInline(rp, &block_scope.base, stmt, block_scope.block_node); block_scope.block_node.rbrace = try appendToken(rp.c, .RBrace, "}"); return &block_scope.block_node.base; @@ -792,7 +805,7 @@ fn transCStyleCastExprClass( fn transDeclStmt(rp: RestorePoint, scope: *Scope, stmt: *const ZigClangDeclStmt) TransError!*ast.Node { const c = rp.c; - const block_scope = try scope.findBlockScope(c); + const block_scope = scope.findBlockScope(c) catch unreachable; var it = ZigClangDeclStmt_decl_begin(stmt); const end_it = ZigClangDeclStmt_decl_end(stmt); @@ -1167,6 +1180,35 @@ fn transImplicitValueInitExpr( }; } +fn transIfStmt( + rp: RestorePoint, + scope: *Scope, + stmt: *const ZigClangIfStmt, + used: ResultUsed, +) TransError!*ast.Node { + // if (c) t + // if (c) t else e + const if_node = try transCreateNodeIf(rp.c); + + var cond_scope = Scope.Condition{ + .base = .{ + .parent = scope, + .id = .Condition, + }, + }; + if_node.condition = try transBoolExpr(rp, &cond_scope.base, @ptrCast(*const ZigClangExpr, ZigClangIfStmt_getCond(stmt)), .used, .r_value); + _ = try appendToken(rp.c, .RParen, ")"); + + if_node.body = try transStmt(rp, scope, ZigClangIfStmt_getThen(stmt), .used, .r_value); + + if (ZigClangIfStmt_getElse(stmt)) |expr| { + if_node.@"else" = try transCreateNodeElse(rp.c); + if_node.@"else".?.body = try transStmt(rp, scope, expr, .used, .r_value); + } + _ = try appendToken(rp.c, .Semicolon, ";"); + return &if_node.base; +} + fn transCPtrCast( rp: RestorePoint, loc: ZigClangSourceLocation, @@ -1602,6 +1644,7 @@ fn transCreateNodeAssign( // zig: }) _ = try appendToken(rp.c, .LParen, "("); const block_scope = try Scope.Block.init(rp.c, scope, true); + block_scope.block_node = try transCreateNodeBlock(rp.c, block_scope.label); const tmp = try std.fmt.allocPrint(rp.c.a(), "_tmp_{}", .{rp.c.getMangle()}); const node = try transCreateNodeVarDecl(rp.c, false, true, tmp); diff --git a/test/translate_c.zig b/test/translate_c.zig index 7a9479034d..c97ccfa6ab 100644 --- a/test/translate_c.zig +++ b/test/translate_c.zig @@ -732,6 +732,29 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\} }); + cases.add_2("if statements", + \\int foo(char c) { + \\ if (2) { + \\ int a = 2; + \\ } + \\ if (2, 5) { + \\ int a = 2; + \\ } + \\} + , &[_][]const u8{ + \\pub export fn foo(c: u8) c_int { + \\ if (2 != 0) { + \\ var a: c_int = 2; + \\ } + \\ if ((blk_1: { + \\ _ = 2; + \\ break :blk_1 5; + \\ }) != 0) { + \\ var a: c_int = 2; + \\ } + \\} + }); + /////////////// Cases for only stage1 which are TODO items for stage2 //////////////// if (builtin.os != builtin.Os.windows) {