authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-12-11 18:40:35-05:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2019-12-11 18:40:35-05:00
logd08dc21116fb2f21b170930475ab122e668144e3
treec04c8a68f0b3b7d1e658f9920425781eaa704cff
parentb375f6e027a159616e80906aa05e253fbe8cc9df
parent12171dba92a4e55e7c3a7871fb5588e652e52ee8
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #3886 from kavika13/master

Add function params, parens handling, and some infix operators to self-hosted translate-c

4 files changed, 140 insertions(+), 39 deletions(-)

lib/std/zig/ast.zig+3-1
......@@ -967,7 +967,9 @@ pub const Node = struct {
967967 pub fn iterate(self: *ParamDecl, index: usize) ?*Node {
968968 var i = index;
969969
970 if (i < 1) return self.type_node;
970 if (i < 1) {
971 return if (self.var_args_token == null) self.type_node else null;
972 }
971973 i -= 1;
972974
973975 return null;
src-self-hosted/clang.zig+2
......@@ -971,3 +971,5 @@ pub extern fn ZigClangBinaryOperator_getType(*const ZigClangBinaryOperator) ZigC
971971
972972pub extern fn ZigClangStringLiteral_getKind(*const ZigClangStringLiteral) ZigClangStringLiteral_StringKind;
973973pub extern fn ZigClangStringLiteral_getString_bytes_begin_size(*const ZigClangStringLiteral, *usize) [*c]const u8;
974
975pub extern fn ZigClangParenExpr_getSubExpr(*const ZigClangParenExpr) *const ZigClangExpr;
src-self-hosted/translate_c.zig+134-37
......@@ -272,7 +272,7 @@ fn visitFnDecl(c: *Context, fn_decl: *const ZigClangFunctionDecl) Error!void {
272272 const proto_node = switch (ZigClangType_getTypeClass(fn_type)) {
273273 .FunctionProto => blk: {
274274 const fn_proto_type = @ptrCast(*const ZigClangFunctionProtoType, fn_type);
275 break :blk transFnProto(rp, fn_proto_type, fn_decl_loc, decl_ctx, true) catch |err| switch (err) {
275 break :blk transFnProto(rp, fn_decl, fn_proto_type, fn_decl_loc, decl_ctx, true) catch |err| switch (err) {
276276 error.UnsupportedType => {
277277 return failDecl(c, fn_decl_loc, fn_name, "unable to resolve prototype of function", .{});
278278 },
......@@ -338,6 +338,7 @@ fn transStmt(
338338 .IntegerLiteralClass => return transIntegerLiteral(rp, scope, @ptrCast(*const ZigClangIntegerLiteral, stmt), result_used),
339339 .ReturnStmtClass => return transReturnStmt(rp, scope, @ptrCast(*const ZigClangReturnStmt, stmt)),
340340 .StringLiteralClass => return transStringLiteral(rp, scope, @ptrCast(*const ZigClangStringLiteral, stmt), result_used),
341 .ParenExprClass => return transExpr(rp, scope, ZigClangParenExpr_getSubExpr(@ptrCast(*const ZigClangParenExpr, stmt)), result_used, lrvalue),
341342 else => {
342343 return revertAndWarn(
343344 rp,
......@@ -393,9 +394,67 @@ fn transBinaryOperator(
393394 .node_scope = scope,
394395 });
395396 },
396 .Mul,
397 .Div,
398 .Rem,
397 .Mul => {
398 const node = if (cIsUnsignedInteger(qt))
399 try transCreateNodeInfixOp(rp, scope, stmt, .MultWrap, .AsteriskPercent, "*%", true)
400 else
401 try transCreateNodeInfixOp(rp, scope, stmt, .Mult, .Asterisk, "*", true);
402 return maybeSuppressResult(rp, scope, result_used, TransResult{
403 .node = node,
404 .child_scope = scope,
405 .node_scope = scope,
406 });
407 },
408 .Div => {
409 if (!cIsUnsignedInteger(qt)) {
410 // signed integer division uses @divTrunc
411 const div_trunc_node = try transCreateNodeBuiltinFnCall(rp.c, "@divTrunc");
412 const lhs = try transExpr(rp, scope, ZigClangBinaryOperator_getLHS(stmt), .used, .l_value);
413 try div_trunc_node.params.push(lhs.node);
414 _ = try appendToken(rp.c, .Comma, ",");
415 const rhs = try transExpr(rp, scope, ZigClangBinaryOperator_getRHS(stmt), .used, .r_value);
416 try div_trunc_node.params.push(rhs.node);
417 div_trunc_node.rparen_token = try appendToken(rp.c, .RParen, ")");
418 return maybeSuppressResult(rp, scope, result_used, TransResult{
419 .node = &div_trunc_node.base,
420 .child_scope = scope,
421 .node_scope = scope,
422 });
423 } else {
424 // unsigned/float division uses the operator
425 const node = try transCreateNodeInfixOp(rp, scope, stmt, .Div, .Slash, "/", true);
426 return maybeSuppressResult(rp, scope, result_used, TransResult{
427 .node = node,
428 .child_scope = scope,
429 .node_scope = scope,
430 });
431 }
432 },
433 .Rem => {
434 if (!cIsUnsignedInteger(qt)) {
435 // signed integer division uses @rem
436 const rem_node = try transCreateNodeBuiltinFnCall(rp.c, "@rem");
437 const lhs = try transExpr(rp, scope, ZigClangBinaryOperator_getLHS(stmt), .used, .l_value);
438 try rem_node.params.push(lhs.node);
439 _ = try appendToken(rp.c, .Comma, ",");
440 const rhs = try transExpr(rp, scope, ZigClangBinaryOperator_getRHS(stmt), .used, .r_value);
441 try rem_node.params.push(rhs.node);
442 rem_node.rparen_token = try appendToken(rp.c, .RParen, ")");
443 return maybeSuppressResult(rp, scope, result_used, TransResult{
444 .node = &rem_node.base,
445 .child_scope = scope,
446 .node_scope = scope,
447 });
448 } else {
449 // unsigned/float division uses the operator
450 const node = try transCreateNodeInfixOp(rp, scope, stmt, .Mod, .Percent, "%", true);
451 return maybeSuppressResult(rp, scope, result_used, TransResult{
452 .node = node,
453 .child_scope = scope,
454 .node_scope = scope,
455 });
456 }
457 },
399458 .Shl,
400459 .Shr,
401460 .LT,
......@@ -1119,11 +1178,11 @@ fn transCreateNodePtrType(
11191178 break :blk lbracket;
11201179 },
11211180 .Identifier => blk: {
1122 _ = try appendToken(c, .LBracket, "[");
1181 const lbracket = try appendToken(c, .LBracket, "["); // Rendering checks if this token + 2 == .Identifier, so needs to return this token
11231182 _ = try appendToken(c, .Asterisk, "*");
1124 const c_ident = try appendToken(c, .Identifier, "c");
1183 _ = try appendToken(c, .Identifier, "c");
11251184 _ = try appendToken(c, .RBracket, "]");
1126 break :blk c_ident;
1185 break :blk lbracket;
11271186 },
11281187 .Asterisk => try appendToken(c, .Asterisk, "*"),
11291188 else => unreachable,
......@@ -1222,7 +1281,7 @@ fn transType(rp: RestorePoint, ty: *const ZigClangType, source_loc: ZigClangSour
12221281 },
12231282 .FunctionProto => {
12241283 const fn_proto_ty = @ptrCast(*const ZigClangFunctionProtoType, ty);
1225 const fn_proto = try transFnProto(rp, fn_proto_ty, source_loc, null, false);
1284 const fn_proto = try transFnProto(rp, null, fn_proto_ty, source_loc, null, false);
12261285 return &fn_proto.base;
12271286 },
12281287 .Paren => {
......@@ -1293,6 +1352,7 @@ fn transCC(
12931352
12941353fn transFnProto(
12951354 rp: RestorePoint,
1355 fn_decl: ?*const ZigClangFunctionDecl,
12961356 fn_proto_ty: *const ZigClangFunctionProtoType,
12971357 source_loc: ZigClangSourceLocation,
12981358 fn_decl_context: ?FnDeclContext,
......@@ -1301,19 +1361,7 @@ fn transFnProto(
13011361 const fn_ty = @ptrCast(*const ZigClangFunctionType, fn_proto_ty);
13021362 const cc = try transCC(rp, fn_ty, source_loc);
13031363 const is_var_args = ZigClangFunctionProtoType_isVariadic(fn_proto_ty);
1304 const param_count: usize = ZigClangFunctionProtoType_getNumParams(fn_proto_ty);
1305 var i: usize = 0;
1306 while (i < param_count) : (i += 1) {
1307 return revertAndWarn(
1308 rp,
1309 error.UnsupportedType,
1310 source_loc,
1311 "TODO: implement parameters for FunctionProto in transType",
1312 .{},
1313 );
1314 }
1315
1316 return finishTransFnProto(rp, fn_ty, source_loc, fn_decl_context, is_var_args, cc, is_pub);
1364 return finishTransFnProto(rp, fn_decl, fn_proto_ty, fn_ty, source_loc, fn_decl_context, is_var_args, cc, is_pub);
13171365}
13181366
13191367fn transFnNoProto(
......@@ -1325,11 +1373,13 @@ fn transFnNoProto(
13251373) !*ast.Node.FnProto {
13261374 const cc = try transCC(rp, fn_ty, source_loc);
13271375 const is_var_args = if (fn_decl_context) |ctx| !ctx.is_export else true;
1328 return finishTransFnProto(rp, fn_ty, source_loc, fn_decl_context, is_var_args, cc, is_pub);
1376 return finishTransFnProto(rp, null, null, fn_ty, source_loc, fn_decl_context, is_var_args, cc, is_pub);
13291377}
13301378
13311379fn finishTransFnProto(
13321380 rp: RestorePoint,
1381 fn_decl: ?*const ZigClangFunctionDecl,
1382 fn_proto_ty: ?*const ZigClangFunctionProtoType,
13331383 fn_ty: *const ZigClangFunctionType,
13341384 source_loc: ZigClangSourceLocation,
13351385 fn_decl_context: ?FnDeclContext,
......@@ -1355,7 +1405,67 @@ fn finishTransFnProto(
13551405 const fn_tok = try appendToken(rp.c, .Keyword_fn, "fn");
13561406 const name_tok = if (fn_decl_context) |ctx| try appendToken(rp.c, .Identifier, ctx.fn_name) else null;
13571407 const lparen_tok = try appendToken(rp.c, .LParen, "(");
1358 const var_args_tok = if (is_var_args) try appendToken(rp.c, .Ellipsis3, "...") else null;
1408
1409 var fn_params = ast.Node.FnProto.ParamList.init(rp.c.a());
1410 const param_count: usize = if (fn_proto_ty != null) ZigClangFunctionProtoType_getNumParams(fn_proto_ty.?) else 0;
1411
1412 var i: usize = 0;
1413 while (i < param_count) : (i += 1) {
1414 const param_qt = ZigClangFunctionProtoType_getParamType(fn_proto_ty.?, @intCast(c_uint, i));
1415
1416 const noalias_tok = if (ZigClangQualType_isRestrictQualified(param_qt)) try appendToken(rp.c, .Keyword_noalias, "noalias") else null;
1417
1418 const param_name_tok: ?ast.TokenIndex = blk: {
1419 if (fn_decl != null) {
1420 const param = ZigClangFunctionDecl_getParamDecl(fn_decl.?, @intCast(c_uint, i));
1421 const param_name = try rp.c.str(ZigClangDecl_getName_bytes_begin(@ptrCast(*const ZigClangDecl, param)));
1422 if (param_name.len > 0) {
1423 // TODO: If len == 0, auto-generate arg1, arg2, etc? Or leave the name blank?
1424 const result = try appendToken(rp.c, .Identifier, param_name);
1425 _ = try appendToken(rp.c, .Colon, ":");
1426 break :blk result;
1427 }
1428 }
1429 break :blk null;
1430 };
1431
1432 const type_node = try transQualType(rp, param_qt, source_loc);
1433
1434 const param_node = try rp.c.a().create(ast.Node.ParamDecl);
1435 param_node.* = ast.Node.ParamDecl{
1436 .base = ast.Node{ .id = ast.Node.Id.ParamDecl },
1437 .doc_comments = null,
1438 .comptime_token = null,
1439 .noalias_token = noalias_tok,
1440 .name_token = param_name_tok,
1441 .type_node = type_node,
1442 .var_args_token = null,
1443 };
1444 try fn_params.push(&param_node.base);
1445
1446 if (i + 1 < param_count) {
1447 _ = try appendToken(rp.c, .Comma, ",");
1448 }
1449 }
1450
1451 if (is_var_args) {
1452 if (param_count > 0) {
1453 _ = try appendToken(rp.c, .Comma, ",");
1454 }
1455
1456 const var_arg_node = try rp.c.a().create(ast.Node.ParamDecl);
1457 var_arg_node.* = ast.Node.ParamDecl{
1458 .base = ast.Node{ .id = ast.Node.Id.ParamDecl },
1459 .doc_comments = null,
1460 .comptime_token = null,
1461 .noalias_token = null,
1462 .name_token = null,
1463 .type_node = undefined, // Note: Accessing this causes an access violation. Need to check .var_args_token first before trying this field
1464 .var_args_token = try appendToken(rp.c, .Ellipsis3, "..."),
1465 };
1466 try fn_params.push(&var_arg_node.base);
1467 }
1468
13591469 const rparen_tok = try appendToken(rp.c, .RParen, ")");
13601470
13611471 const return_type_node = blk: {
......@@ -1384,7 +1494,7 @@ fn finishTransFnProto(
13841494 .visib_token = pub_tok,
13851495 .fn_token = fn_tok,
13861496 .name_token = name_tok,
1387 .params = ast.Node.FnProto.ParamList.init(rp.c.a()),
1497 .params = fn_params,
13881498 .return_type = ast.Node.FnProto.ReturnType{ .Explicit = return_type_node },
13891499 .var_args_token = null, // TODO this field is broken in the AST data model
13901500 .extern_export_inline_token = extern_export_inline_tok,
......@@ -1394,19 +1504,6 @@ fn finishTransFnProto(
13941504 .align_expr = null,
13951505 .section_expr = null,
13961506 };
1397 if (is_var_args) {
1398 const var_arg_node = try rp.c.a().create(ast.Node.ParamDecl);
1399 var_arg_node.* = ast.Node.ParamDecl{
1400 .base = ast.Node{ .id = ast.Node.Id.ParamDecl },
1401 .doc_comments = null,
1402 .comptime_token = null,
1403 .noalias_token = null,
1404 .name_token = null,
1405 .type_node = undefined,
1406 .var_args_token = var_args_tok,
1407 };
1408 try fn_proto.params.push(&var_arg_node.base);
1409 }
14101507 return fn_proto;
14111508}
14121509
test/translate_c.zig+1-1
......@@ -719,7 +719,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
719719 \\}
720720 });
721721
722 cases.addC("add, sub, mul, div, rem",
722 cases.addC_both("add, sub, mul, div, rem",
723723 \\int s(int a, int b) {
724724 \\ int c;
725725 \\ c = a + b;