authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-03-12 14:00:07-04:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2020-03-12 14:00:07-04:00
logaa49f972d655eb61ca899f76ba37933254f780a2
treefc73e90e37daa25f02c0995f40a216a844197062
parent8a22c50c081e4495216ef961a9c1f2db6fbac916
parent02c491e42affedf6dd33e75a456531bb60aff8a3
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #4720 from Vexu/translate-c

Translate-c treat C bools as ints

2 files changed, 82 insertions(+), 7 deletions(-)

src-self-hosted/translate_c.zig+63-7
...@@ -560,7 +560,7 @@ fn visitVarDecl(c: *Context, var_decl: *const ZigClangVarDecl) Error!void {...@@ -560,7 +560,7 @@ fn visitVarDecl(c: *Context, var_decl: *const ZigClangVarDecl) Error!void {
560560
561 // TODO https://github.com/ziglang/zig/issues/3756561 // TODO https://github.com/ziglang/zig/issues/3756
562 // TODO https://github.com/ziglang/zig/issues/1802562 // TODO https://github.com/ziglang/zig/issues/1802
563 const checked_name = if (isZigPrimitiveType(var_name)) try std.fmt.allocPrint(c.a(), "{}_{}", .{var_name, c.getMangle()}) else var_name;563 const checked_name = if (isZigPrimitiveType(var_name)) try std.fmt.allocPrint(c.a(), "{}_{}", .{ var_name, c.getMangle() }) else var_name;
564 const var_decl_loc = ZigClangVarDecl_getLocation(var_decl);564 const var_decl_loc = ZigClangVarDecl_getLocation(var_decl);
565565
566 const qual_type = ZigClangVarDecl_getTypeSourceInfo_getType(var_decl);566 const qual_type = ZigClangVarDecl_getTypeSourceInfo_getType(var_decl);
...@@ -677,7 +677,7 @@ fn transTypeDef(c: *Context, typedef_decl: *const ZigClangTypedefNameDecl, top_l...@@ -677,7 +677,7 @@ fn transTypeDef(c: *Context, typedef_decl: *const ZigClangTypedefNameDecl, top_l
677677
678 // TODO https://github.com/ziglang/zig/issues/3756678 // TODO https://github.com/ziglang/zig/issues/3756
679 // TODO https://github.com/ziglang/zig/issues/1802679 // TODO https://github.com/ziglang/zig/issues/1802
680 const checked_name = if (isZigPrimitiveType(typedef_name)) try std.fmt.allocPrint(c.a(), "{}_{}", .{typedef_name, c.getMangle()}) else typedef_name;680 const checked_name = if (isZigPrimitiveType(typedef_name)) try std.fmt.allocPrint(c.a(), "{}_{}", .{ typedef_name, c.getMangle() }) else typedef_name;
681681
682 if (mem.eql(u8, checked_name, "uint8_t"))682 if (mem.eql(u8, checked_name, "uint8_t"))
683 return transTypeDefAsBuiltin(c, typedef_decl, "u8")683 return transTypeDefAsBuiltin(c, typedef_decl, "u8")
...@@ -4871,7 +4871,7 @@ fn transPreprocessorEntities(c: *Context, unit: *ZigClangASTUnit) Error!void {...@@ -4871,7 +4871,7 @@ fn transPreprocessorEntities(c: *Context, unit: *ZigClangASTUnit) Error!void {
4871 const name = try c.str(raw_name);4871 const name = try c.str(raw_name);
4872 // TODO https://github.com/ziglang/zig/issues/37564872 // TODO https://github.com/ziglang/zig/issues/3756
4873 // TODO https://github.com/ziglang/zig/issues/18024873 // TODO https://github.com/ziglang/zig/issues/1802
4874 const mangled_name = if (isZigPrimitiveType(name)) try std.fmt.allocPrint(c.a(), "{}_{}", .{name, c.getMangle()}) else name;4874 const mangled_name = if (isZigPrimitiveType(name)) try std.fmt.allocPrint(c.a(), "{}_{}", .{ name, c.getMangle() }) else name;
4875 if (scope.containsNow(mangled_name)) {4875 if (scope.containsNow(mangled_name)) {
4876 continue;4876 continue;
4877 }4877 }
...@@ -5375,7 +5375,7 @@ fn parseCPrimaryExpr(c: *Context, it: *CTokenList.Iterator, source: []const u8,...@@ -5375,7 +5375,7 @@ fn parseCPrimaryExpr(c: *Context, it: *CTokenList.Iterator, source: []const u8,
5375 const first_tok = it.list.at(0);5375 const first_tok = it.list.at(0);
5376 const token = try appendToken(c, .CharLiteral, try zigifyEscapeSequences(c, source[tok.start..tok.end], source[first_tok.start..first_tok.end], source_loc));5376 const token = try appendToken(c, .CharLiteral, try zigifyEscapeSequences(c, source[tok.start..tok.end], source[first_tok.start..first_tok.end], source_loc));
5377 const node = try c.a().create(ast.Node.CharLiteral);5377 const node = try c.a().create(ast.Node.CharLiteral);
5378 node.* = ast.Node.CharLiteral{5378 node.* = .{
5379 .token = token,5379 .token = token,
5380 };5380 };
5381 return &node.base;5381 return &node.base;
...@@ -5384,7 +5384,7 @@ fn parseCPrimaryExpr(c: *Context, it: *CTokenList.Iterator, source: []const u8,...@@ -5384,7 +5384,7 @@ fn parseCPrimaryExpr(c: *Context, it: *CTokenList.Iterator, source: []const u8,
5384 const first_tok = it.list.at(0);5384 const first_tok = it.list.at(0);
5385 const token = try appendToken(c, .StringLiteral, try zigifyEscapeSequences(c, source[tok.start..tok.end], source[first_tok.start..first_tok.end], source_loc));5385 const token = try appendToken(c, .StringLiteral, try zigifyEscapeSequences(c, source[tok.start..tok.end], source[first_tok.start..first_tok.end], source_loc));
5386 const node = try c.a().create(ast.Node.StringLiteral);5386 const node = try c.a().create(ast.Node.StringLiteral);
5387 node.* = ast.Node.StringLiteral{5387 node.* = .{
5388 .token = token,5388 .token = token,
5389 };5389 };
5390 return &node.base;5390 return &node.base;
...@@ -5560,12 +5560,63 @@ fn parseCPrimaryExpr(c: *Context, it: *CTokenList.Iterator, source: []const u8,...@@ -5560,12 +5560,63 @@ fn parseCPrimaryExpr(c: *Context, it: *CTokenList.Iterator, source: []const u8,
5560 }5560 }
5561}5561}
55625562
5563fn macroBoolToInt(c: *Context, node: *ast.Node) !*ast.Node {
5564 if (!isBoolRes(node)) {
5565 if (node.id != .InfixOp) return node;
5566
5567 const group_node = try c.a().create(ast.Node.GroupedExpression);
5568 group_node.* = .{
5569 .lparen = try appendToken(c, .LParen, "("),
5570 .expr = node,
5571 .rparen = try appendToken(c, .RParen, ")"),
5572 };
5573 return &group_node.base;
5574 }
5575
5576 const builtin_node = try transCreateNodeBuiltinFnCall(c, "@boolToInt");
5577 try builtin_node.params.push(node);
5578 builtin_node.rparen_token = try appendToken(c, .RParen, ")");
5579 return &builtin_node.base;
5580}
5581
5582fn macroIntToBool(c: *Context, node: *ast.Node) !*ast.Node {
5583 if (isBoolRes(node)) {
5584 if (node.id != .InfixOp) return node;
5585
5586 const group_node = try c.a().create(ast.Node.GroupedExpression);
5587 group_node.* = .{
5588 .lparen = try appendToken(c, .LParen, "("),
5589 .expr = node,
5590 .rparen = try appendToken(c, .RParen, ")"),
5591 };
5592 return &group_node.base;
5593 }
5594
5595 const op_token = try appendToken(c, .BangEqual, "!=");
5596 const zero = try transCreateNodeInt(c, 0);
5597 const res = try c.a().create(ast.Node.InfixOp);
5598 res.* = .{
5599 .op_token = op_token,
5600 .lhs = node,
5601 .op = .BangEqual,
5602 .rhs = zero,
5603 };
5604 const group_node = try c.a().create(ast.Node.GroupedExpression);
5605 group_node.* = .{
5606 .lparen = try appendToken(c, .LParen, "("),
5607 .expr = &res.base,
5608 .rparen = try appendToken(c, .RParen, ")"),
5609 };
5610 return &group_node.base;
5611}
5612
5563fn parseCSuffixOpExpr(c: *Context, it: *CTokenList.Iterator, source: []const u8, source_loc: ZigClangSourceLocation, scope: *Scope) ParseError!*ast.Node {5613fn parseCSuffixOpExpr(c: *Context, it: *CTokenList.Iterator, source: []const u8, source_loc: ZigClangSourceLocation, scope: *Scope) ParseError!*ast.Node {
5564 var node = try parseCPrimaryExpr(c, it, source, source_loc, scope);5614 var node = try parseCPrimaryExpr(c, it, source, source_loc, scope);
5565 while (true) {5615 while (true) {
5566 const tok = it.next().?;5616 const tok = it.next().?;
5567 var op_token: ast.TokenIndex = undefined;5617 var op_token: ast.TokenIndex = undefined;
5568 var op_id: ast.Node.InfixOp.Op = undefined;5618 var op_id: ast.Node.InfixOp.Op = undefined;
5619 var bool_op = false;
5569 switch (tok.id) {5620 switch (tok.id) {
5570 .Period => {5621 .Period => {
5571 const name_tok = it.next().?;5622 const name_tok = it.next().?;
...@@ -5654,10 +5705,12 @@ fn parseCSuffixOpExpr(c: *Context, it: *CTokenList.Iterator, source: []const u8,...@@ -5654,10 +5705,12 @@ fn parseCSuffixOpExpr(c: *Context, it: *CTokenList.Iterator, source: []const u8,
5654 .AmpersandAmpersand => {5705 .AmpersandAmpersand => {
5655 op_token = try appendToken(c, .Keyword_and, "and");5706 op_token = try appendToken(c, .Keyword_and, "and");
5656 op_id = .BoolAnd;5707 op_id = .BoolAnd;
5708 bool_op = true;
5657 },5709 },
5658 .PipePipe => {5710 .PipePipe => {
5659 op_token = try appendToken(c, .Keyword_or, "or");5711 op_token = try appendToken(c, .Keyword_or, "or");
5660 op_id = .BoolOr;5712 op_id = .BoolOr;
5713 bool_op = true;
5661 },5714 },
5662 .AngleBracketRight => {5715 .AngleBracketRight => {
5663 op_token = try appendToken(c, .AngleBracketRight, ">");5716 op_token = try appendToken(c, .AngleBracketRight, ">");
...@@ -5740,12 +5793,15 @@ fn parseCSuffixOpExpr(c: *Context, it: *CTokenList.Iterator, source: []const u8,...@@ -5740,12 +5793,15 @@ fn parseCSuffixOpExpr(c: *Context, it: *CTokenList.Iterator, source: []const u8,
5740 return node;5793 return node;
5741 },5794 },
5742 }5795 }
5796 const cast_fn = if (bool_op) macroIntToBool else macroBoolToInt;
5797 const lhs_node = try cast_fn(c, node);
5798 const rhs_node = try parseCPrefixOpExpr(c, it, source, source_loc, scope);
5743 const op_node = try c.a().create(ast.Node.InfixOp);5799 const op_node = try c.a().create(ast.Node.InfixOp);
5744 op_node.* = .{5800 op_node.* = .{
5745 .op_token = op_token,5801 .op_token = op_token,
5746 .lhs = node,5802 .lhs = lhs_node,
5747 .op = op_id,5803 .op = op_id,
5748 .rhs = try parseCPrefixOpExpr(c, it, source, source_loc, scope),5804 .rhs = try cast_fn(c, rhs_node),
5749 };5805 };
5750 node = &op_node.base;5806 node = &op_node.base;
5751 }5807 }
test/translate_c.zig+19
...@@ -3,6 +3,25 @@ const std = @import("std");...@@ -3,6 +3,25 @@ const std = @import("std");
3const CrossTarget = std.zig.CrossTarget;3const CrossTarget = std.zig.CrossTarget;
44
5pub fn addCases(cases: *tests.TranslateCContext) void {5pub fn addCases(cases: *tests.TranslateCContext) void {
6 cases.add("correct semicolon after infixop",
7 \\#define __ferror_unlocked_body(_fp) (((_fp)->_flags & _IO_ERR_SEEN) != 0)
8 , &[_][]const u8{
9 \\pub inline fn __ferror_unlocked_body(_fp: var) @TypeOf(((_fp.*._flags) & _IO_ERR_SEEN) != 0) {
10 \\ return ((_fp.*._flags) & _IO_ERR_SEEN) != 0;
11 \\}
12 });
13
14 cases.add("c booleans are just ints",
15 \\#define FOO(x) ((x >= 0) + (x >= 0))
16 \\#define BAR 1 && 2 > 4
17 , &[_][]const u8{
18 \\pub inline fn FOO(x: var) @TypeOf(@boolToInt(x >= 0) + @boolToInt(x >= 0)) {
19 \\ return @boolToInt(x >= 0) + @boolToInt(x >= 0);
20 \\}
21 ,
22 \\pub const BAR = (1 != 0) and (2 > 4);
23 });
24
6 cases.add("struct with aligned fields",25 cases.add("struct with aligned fields",
7 \\struct foo {26 \\struct foo {
8 \\ __attribute__((aligned(1))) short bar;27 \\ __attribute__((aligned(1))) short bar;