authorgravatar for kavika@gmail.comMerlyn Morgan-Graham <kavika@gmail.com> 2019-12-10 23:52:35-08:00
committergravatar for kavika@gmail.comMerlyn Morgan-Graham <kavika@gmail.com> 2019-12-10 23:52:40-08:00
log12171dba92a4e55e7c3a7871fb5588e652e52ee8
treed94f5d4568fe362ce7a7a15b9c601e27745716e4
parent5e8186a8ce680894547112d43da3781b9e1c0793

Add function parameters to self-hosted translate-C


2 files changed, 73 insertions(+), 35 deletions(-)

src-self-hosted/translate_c.zig+72-34
...@@ -272,7 +272,7 @@ fn visitFnDecl(c: *Context, fn_decl: *const ZigClangFunctionDecl) Error!void {...@@ -272,7 +272,7 @@ fn visitFnDecl(c: *Context, fn_decl: *const ZigClangFunctionDecl) Error!void {
272 const proto_node = switch (ZigClangType_getTypeClass(fn_type)) {272 const proto_node = switch (ZigClangType_getTypeClass(fn_type)) {
273 .FunctionProto => blk: {273 .FunctionProto => blk: {
274 const fn_proto_type = @ptrCast(*const ZigClangFunctionProtoType, fn_type);274 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) {
276 error.UnsupportedType => {276 error.UnsupportedType => {
277 return failDecl(c, fn_decl_loc, fn_name, "unable to resolve prototype of function", .{});277 return failDecl(c, fn_decl_loc, fn_name, "unable to resolve prototype of function", .{});
278 },278 },
...@@ -1178,11 +1178,11 @@ fn transCreateNodePtrType(...@@ -1178,11 +1178,11 @@ fn transCreateNodePtrType(
1178 break :blk lbracket;1178 break :blk lbracket;
1179 },1179 },
1180 .Identifier => blk: {1180 .Identifier => blk: {
1181 _ = try appendToken(c, .LBracket, "[");1181 const lbracket = try appendToken(c, .LBracket, "["); // Rendering checks if this token + 2 == .Identifier, so needs to return this token
1182 _ = try appendToken(c, .Asterisk, "*");1182 _ = try appendToken(c, .Asterisk, "*");
1183 const c_ident = try appendToken(c, .Identifier, "c");1183 _ = try appendToken(c, .Identifier, "c");
1184 _ = try appendToken(c, .RBracket, "]");1184 _ = try appendToken(c, .RBracket, "]");
1185 break :blk c_ident;1185 break :blk lbracket;
1186 },1186 },
1187 .Asterisk => try appendToken(c, .Asterisk, "*"),1187 .Asterisk => try appendToken(c, .Asterisk, "*"),
1188 else => unreachable,1188 else => unreachable,
...@@ -1281,7 +1281,7 @@ fn transType(rp: RestorePoint, ty: *const ZigClangType, source_loc: ZigClangSour...@@ -1281,7 +1281,7 @@ fn transType(rp: RestorePoint, ty: *const ZigClangType, source_loc: ZigClangSour
1281 },1281 },
1282 .FunctionProto => {1282 .FunctionProto => {
1283 const fn_proto_ty = @ptrCast(*const ZigClangFunctionProtoType, ty);1283 const fn_proto_ty = @ptrCast(*const ZigClangFunctionProtoType, ty);
1284 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);
1285 return &fn_proto.base;1285 return &fn_proto.base;
1286 },1286 },
1287 .Paren => {1287 .Paren => {
...@@ -1352,6 +1352,7 @@ fn transCC(...@@ -1352,6 +1352,7 @@ fn transCC(
13521352
1353fn transFnProto(1353fn transFnProto(
1354 rp: RestorePoint,1354 rp: RestorePoint,
1355 fn_decl: ?*const ZigClangFunctionDecl,
1355 fn_proto_ty: *const ZigClangFunctionProtoType,1356 fn_proto_ty: *const ZigClangFunctionProtoType,
1356 source_loc: ZigClangSourceLocation,1357 source_loc: ZigClangSourceLocation,
1357 fn_decl_context: ?FnDeclContext,1358 fn_decl_context: ?FnDeclContext,
...@@ -1360,19 +1361,7 @@ fn transFnProto(...@@ -1360,19 +1361,7 @@ fn transFnProto(
1360 const fn_ty = @ptrCast(*const ZigClangFunctionType, fn_proto_ty);1361 const fn_ty = @ptrCast(*const ZigClangFunctionType, fn_proto_ty);
1361 const cc = try transCC(rp, fn_ty, source_loc);1362 const cc = try transCC(rp, fn_ty, source_loc);
1362 const is_var_args = ZigClangFunctionProtoType_isVariadic(fn_proto_ty);1363 const is_var_args = ZigClangFunctionProtoType_isVariadic(fn_proto_ty);
1363 const param_count: usize = ZigClangFunctionProtoType_getNumParams(fn_proto_ty);1364 return finishTransFnProto(rp, fn_decl, fn_proto_ty, fn_ty, source_loc, fn_decl_context, is_var_args, cc, is_pub);
1364 var i: usize = 0;
1365 while (i < param_count) : (i += 1) {
1366 return revertAndWarn(
1367 rp,
1368 error.UnsupportedType,
1369 source_loc,
1370 "TODO: implement parameters for FunctionProto in transType",
1371 .{},
1372 );
1373 }
1374
1375 return finishTransFnProto(rp, fn_ty, source_loc, fn_decl_context, is_var_args, cc, is_pub);
1376}1365}
13771366
1378fn transFnNoProto(1367fn transFnNoProto(
...@@ -1384,11 +1373,13 @@ fn transFnNoProto(...@@ -1384,11 +1373,13 @@ fn transFnNoProto(
1384) !*ast.Node.FnProto {1373) !*ast.Node.FnProto {
1385 const cc = try transCC(rp, fn_ty, source_loc);1374 const cc = try transCC(rp, fn_ty, source_loc);
1386 const is_var_args = if (fn_decl_context) |ctx| !ctx.is_export else true;1375 const is_var_args = if (fn_decl_context) |ctx| !ctx.is_export else true;
1387 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);
1388}1377}
13891378
1390fn finishTransFnProto(1379fn finishTransFnProto(
1391 rp: RestorePoint,1380 rp: RestorePoint,
1381 fn_decl: ?*const ZigClangFunctionDecl,
1382 fn_proto_ty: ?*const ZigClangFunctionProtoType,
1392 fn_ty: *const ZigClangFunctionType,1383 fn_ty: *const ZigClangFunctionType,
1393 source_loc: ZigClangSourceLocation,1384 source_loc: ZigClangSourceLocation,
1394 fn_decl_context: ?FnDeclContext,1385 fn_decl_context: ?FnDeclContext,
...@@ -1414,7 +1405,67 @@ fn finishTransFnProto(...@@ -1414,7 +1405,67 @@ fn finishTransFnProto(
1414 const fn_tok = try appendToken(rp.c, .Keyword_fn, "fn");1405 const fn_tok = try appendToken(rp.c, .Keyword_fn, "fn");
1415 const name_tok = if (fn_decl_context) |ctx| try appendToken(rp.c, .Identifier, ctx.fn_name) else null;1406 const name_tok = if (fn_decl_context) |ctx| try appendToken(rp.c, .Identifier, ctx.fn_name) else null;
1416 const lparen_tok = try appendToken(rp.c, .LParen, "(");1407 const lparen_tok = try appendToken(rp.c, .LParen, "(");
1417 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
1418 const rparen_tok = try appendToken(rp.c, .RParen, ")");1469 const rparen_tok = try appendToken(rp.c, .RParen, ")");
14191470
1420 const return_type_node = blk: {1471 const return_type_node = blk: {
...@@ -1443,7 +1494,7 @@ fn finishTransFnProto(...@@ -1443,7 +1494,7 @@ fn finishTransFnProto(
1443 .visib_token = pub_tok,1494 .visib_token = pub_tok,
1444 .fn_token = fn_tok,1495 .fn_token = fn_tok,
1445 .name_token = name_tok,1496 .name_token = name_tok,
1446 .params = ast.Node.FnProto.ParamList.init(rp.c.a()),1497 .params = fn_params,
1447 .return_type = ast.Node.FnProto.ReturnType{ .Explicit = return_type_node },1498 .return_type = ast.Node.FnProto.ReturnType{ .Explicit = return_type_node },
1448 .var_args_token = null, // TODO this field is broken in the AST data model1499 .var_args_token = null, // TODO this field is broken in the AST data model
1449 .extern_export_inline_token = extern_export_inline_tok,1500 .extern_export_inline_token = extern_export_inline_tok,
...@@ -1453,19 +1504,6 @@ fn finishTransFnProto(...@@ -1453,19 +1504,6 @@ fn finishTransFnProto(
1453 .align_expr = null,1504 .align_expr = null,
1454 .section_expr = null,1505 .section_expr = null,
1455 };1506 };
1456 if (is_var_args) {
1457 const var_arg_node = try rp.c.a().create(ast.Node.ParamDecl);
1458 var_arg_node.* = ast.Node.ParamDecl{
1459 .base = ast.Node{ .id = ast.Node.Id.ParamDecl },
1460 .doc_comments = null,
1461 .comptime_token = null,
1462 .noalias_token = null,
1463 .name_token = null,
1464 .type_node = undefined,
1465 .var_args_token = var_args_tok,
1466 };
1467 try fn_proto.params.push(&var_arg_node.base);
1468 }
1469 return fn_proto;1507 return fn_proto;
1470}1508}
14711509
test/translate_c.zig+1-1
...@@ -719,7 +719,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -719,7 +719,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
719 \\}719 \\}
720 });720 });
721721
722 cases.addC("add, sub, mul, div, rem",722 cases.addC_both("add, sub, mul, div, rem",
723 \\int s(int a, int b) {723 \\int s(int a, int b) {
724 \\ int c;724 \\ int c;
725 \\ c = a + b;725 \\ c = a + b;