translate-c-2 if statements

This commit is contained in:
Vexu 2019-12-16 17:55:51 +02:00
parent 626562555e
commit e3f1bfe483
No known key found for this signature in database
GPG Key ID: 59AEB8936E16A6AC
3 changed files with 78 additions and 8 deletions

View File

@ -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;

View File

@ -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);

View File

@ -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) {