authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2019-12-20 00:10:25+02:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2019-12-20 00:12:08+02:00
logd172a7335c5b943102e2c9e70c1bbdfa20eec955
tree7980681946a7d82bd79a2ba075b5009f0e7d96b8
parentb7f18164f96f7e695d295c12c06fddf25803b08b
signature Commit is signed but in an unrecognized format.

translate-c-2 copy parametrs to stack


4 files changed, 227 insertions(+), 169 deletions(-)

lib/std/zig/ast.zig+4-4
...@@ -1456,8 +1456,8 @@ pub const Node = struct {...@@ -1456,8 +1456,8 @@ pub const Node = struct {
1456 LessThan,1456 LessThan,
1457 MergeErrorSets,1457 MergeErrorSets,
1458 Mod,1458 Mod,
1459 Mult,1459 Mul,
1460 MultWrap,1460 MulWrap,
1461 Period,1461 Period,
1462 Range,1462 Range,
1463 Sub,1463 Sub,
...@@ -1514,8 +1514,8 @@ pub const Node = struct {...@@ -1514,8 +1514,8 @@ pub const Node = struct {
1514 Op.LessThan,1514 Op.LessThan,
1515 Op.MergeErrorSets,1515 Op.MergeErrorSets,
1516 Op.Mod,1516 Op.Mod,
1517 Op.Mult,1517 Op.Mul,
1518 Op.MultWrap,1518 Op.MulWrap,
1519 Op.Period,1519 Op.Period,
1520 Op.Range,1520 Op.Range,
1521 Op.Sub,1521 Op.Sub,
lib/std/zig/parse.zig+2-2
...@@ -2120,11 +2120,11 @@ fn parseMultiplyOp(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {...@@ -2120,11 +2120,11 @@ fn parseMultiplyOp(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
2120 const token = nextToken(it);2120 const token = nextToken(it);
2121 const op = switch (token.ptr.id) {2121 const op = switch (token.ptr.id) {
2122 .PipePipe => ops{ .BoolOr = {} },2122 .PipePipe => ops{ .BoolOr = {} },
2123 .Asterisk => ops{ .Mult = {} },2123 .Asterisk => ops{ .Mul = {} },
2124 .Slash => ops{ .Div = {} },2124 .Slash => ops{ .Div = {} },
2125 .Percent => ops{ .Mod = {} },2125 .Percent => ops{ .Mod = {} },
2126 .AsteriskAsterisk => ops{ .ArrayMult = {} },2126 .AsteriskAsterisk => ops{ .ArrayMult = {} },
2127 .AsteriskPercent => ops{ .MultWrap = {} },2127 .AsteriskPercent => ops{ .MulWrap = {} },
2128 else => {2128 else => {
2129 putBackToken(it, token.index);2129 putBackToken(it, token.index);
2130 return null;2130 return null;
src-self-hosted/translate_c.zig+61-69
...@@ -49,7 +49,6 @@ const Scope = struct {...@@ -49,7 +49,6 @@ const Scope = struct {
49 Block,49 Block,
50 Root,50 Root,
51 Condition,51 Condition,
52 FnDef,
53 Loop,52 Loop,
54 };53 };
5554
...@@ -121,39 +120,6 @@ const Scope = struct {...@@ -121,39 +120,6 @@ const Scope = struct {
121 }120 }
122 };121 };
123122
124 const FnDef = struct {
125 base: Scope,
126 params: AliasList,
127
128 fn init(c: *Context) FnDef {
129 return .{
130 .base = .{
131 .id = .FnDef,
132 .parent = &c.global_scope.base,
133 },
134 .params = AliasList.init(c.a()),
135 };
136 }
137
138 fn getAlias(scope: *FnDef, name: []const u8) ?[]const u8 {
139 var it = scope.params.iterator(0);
140 while (it.next()) |p| {
141 if (mem.eql(u8, p.name, name))
142 return p.alias;
143 }
144 return scope.base.parent.?.getAlias(name);
145 }
146
147 fn contains(scope: *FnDef, name: []const u8) bool {
148 var it = scope.params.iterator(0);
149 while (it.next()) |p| {
150 if (mem.eql(u8, p.name, name))
151 return true;
152 }
153 return scope.base.parent.?.contains(name);
154 }
155 };
156
157 fn findBlockScope(inner: *Scope, c: *Context) !*Scope.Block {123 fn findBlockScope(inner: *Scope, c: *Context) !*Scope.Block {
158 var scope = inner;124 var scope = inner;
159 while (true) {125 while (true) {
...@@ -179,7 +145,6 @@ const Scope = struct {...@@ -179,7 +145,6 @@ const Scope = struct {
179 fn getAlias(scope: *Scope, name: []const u8) ?[]const u8 {145 fn getAlias(scope: *Scope, name: []const u8) ?[]const u8 {
180 return switch (scope.id) {146 return switch (scope.id) {
181 .Root => null,147 .Root => null,
182 .FnDef => @fieldParentPtr(FnDef, "base", scope).getAlias(name),
183 .Block => @fieldParentPtr(Block, "base", scope).getAlias(name),148 .Block => @fieldParentPtr(Block, "base", scope).getAlias(name),
184 .Switch, .Loop, .Condition => scope.parent.?.getAlias(name),149 .Switch, .Loop, .Condition => scope.parent.?.getAlias(name),
185 };150 };
...@@ -188,7 +153,6 @@ const Scope = struct {...@@ -188,7 +153,6 @@ const Scope = struct {
188 fn contains(scope: *Scope, name: []const u8) bool {153 fn contains(scope: *Scope, name: []const u8) bool {
189 return switch (scope.id) {154 return switch (scope.id) {
190 .Root => @fieldParentPtr(Root, "base", scope).contains(name),155 .Root => @fieldParentPtr(Root, "base", scope).contains(name),
191 .FnDef => @fieldParentPtr(FnDef, "base", scope).contains(name),
192 .Block => @fieldParentPtr(Block, "base", scope).contains(name),156 .Block => @fieldParentPtr(Block, "base", scope).contains(name),
193 .Switch, .Loop, .Condition => scope.parent.?.contains(name),157 .Switch, .Loop, .Condition => scope.parent.?.contains(name),
194 };158 };
...@@ -198,7 +162,7 @@ const Scope = struct {...@@ -198,7 +162,7 @@ const Scope = struct {
198 var scope = inner;162 var scope = inner;
199 while (true) {163 while (true) {
200 switch (scope.id) {164 switch (scope.id) {
201 .FnDef => unreachable,165 .Root => unreachable,
202 .Switch => return scope,166 .Switch => return scope,
203 .Loop => return scope,167 .Loop => return scope,
204 else => scope = scope.parent.?,168 else => scope = scope.parent.?,
...@@ -210,7 +174,7 @@ const Scope = struct {...@@ -210,7 +174,7 @@ const Scope = struct {
210 var scope = inner;174 var scope = inner;
211 while (true) {175 while (true) {
212 switch (scope.id) {176 switch (scope.id) {
213 .FnDef => unreachable,177 .Root => unreachable,
214 .Switch => return @fieldParentPtr(Switch, "base", scope),178 .Switch => return @fieldParentPtr(Switch, "base", scope),
215 else => scope = scope.parent.?,179 else => scope = scope.parent.?,
216 }180 }
...@@ -382,17 +346,12 @@ fn visitFnDecl(c: *Context, fn_decl: *const ZigClangFunctionDecl) Error!void {...@@ -382,17 +346,12 @@ fn visitFnDecl(c: *Context, fn_decl: *const ZigClangFunctionDecl) Error!void {
382 const fn_name = try c.str(ZigClangDecl_getName_bytes_begin(@ptrCast(*const ZigClangDecl, fn_decl)));346 const fn_name = try c.str(ZigClangDecl_getName_bytes_begin(@ptrCast(*const ZigClangDecl, fn_decl)));
383 _ = try c.decl_table.put(@ptrToInt(fn_decl), fn_name);347 _ = try c.decl_table.put(@ptrToInt(fn_decl), fn_name);
384 const fn_decl_loc = ZigClangFunctionDecl_getLocation(fn_decl);348 const fn_decl_loc = ZigClangFunctionDecl_getLocation(fn_decl);
385 const fn_qt = ZigClangFunctionDecl_getType(fn_decl);
386 const fn_type = ZigClangQualType_getTypePtr(fn_qt);
387 var fndef_scope = Scope.FnDef.init(c);
388 var scope = &fndef_scope.base;
389 const has_body = ZigClangFunctionDecl_hasBody(fn_decl);349 const has_body = ZigClangFunctionDecl_hasBody(fn_decl);
390 const storage_class = ZigClangFunctionDecl_getStorageClass(fn_decl);350 const storage_class = ZigClangFunctionDecl_getStorageClass(fn_decl);
391 const decl_ctx = FnDeclContext{351 const decl_ctx = FnDeclContext{
392 .fn_name = fn_name,352 .fn_name = fn_name,
393 .has_body = has_body,353 .has_body = has_body,
394 .storage_class = storage_class,354 .storage_class = storage_class,
395 .scope = &scope,
396 .is_export = switch (storage_class) {355 .is_export = switch (storage_class) {
397 .None => has_body,356 .None => has_body,
398 .Extern, .Static => false,357 .Extern, .Static => false,
...@@ -402,6 +361,15 @@ fn visitFnDecl(c: *Context, fn_decl: *const ZigClangFunctionDecl) Error!void {...@@ -402,6 +361,15 @@ fn visitFnDecl(c: *Context, fn_decl: *const ZigClangFunctionDecl) Error!void {
402 else => unreachable,361 else => unreachable,
403 },362 },
404 };363 };
364
365 var fn_qt = ZigClangFunctionDecl_getType(fn_decl);
366 var fn_type = ZigClangQualType_getTypePtr(fn_qt);
367 if (ZigClangType_getTypeClass(fn_type) == .Attributed) {
368 const attr_type = @ptrCast(*const ZigClangAttributedType, fn_type);
369 fn_qt = ZigClangAttributedType_getEquivalentType(attr_type);
370 fn_type = ZigClangQualType_getTypePtr(fn_qt);
371 }
372
405 const proto_node = switch (ZigClangType_getTypeClass(fn_type)) {373 const proto_node = switch (ZigClangType_getTypeClass(fn_type)) {
406 .FunctionProto => blk: {374 .FunctionProto => blk: {
407 const fn_proto_type = @ptrCast(*const ZigClangFunctionProtoType, fn_type);375 const fn_proto_type = @ptrCast(*const ZigClangFunctionProtoType, fn_type);
...@@ -431,15 +399,39 @@ fn visitFnDecl(c: *Context, fn_decl: *const ZigClangFunctionDecl) Error!void {...@@ -431,15 +399,39 @@ fn visitFnDecl(c: *Context, fn_decl: *const ZigClangFunctionDecl) Error!void {
431399
432 // actual function definition with body400 // actual function definition with body
433 const body_stmt = ZigClangFunctionDecl_getBody(fn_decl);401 const body_stmt = ZigClangFunctionDecl_getBody(fn_decl);
434 const body_node = transStmt(rp, scope, body_stmt, .unused, .r_value) catch |err| switch (err) {402 const block_scope = try Scope.Block.init(rp.c, &c.global_scope.base, null);
403 var scope = &block_scope.base;
404 const block_node = try transCreateNodeBlock(rp.c, null);
405 block_scope.block_node = block_node;
406
407 var it = proto_node.params.iterator(0);
408 while (it.next()) |p| {
409 const param = @fieldParentPtr(ast.Node.ParamDecl, "base", p.*);
410 const param_name = tokenSlice(c, param.name_token.?);
411
412 const checked_param_name = if (try scope.createAlias(rp.c, param_name)) |a| blk: {
413 try block_scope.variables.push(.{ .name = param_name, .alias = a });
414 break :blk a;
415 } else param_name;
416 const arg_name = try std.fmt.allocPrint(c.a(), "_arg_{}", .{checked_param_name});
417
418 const node = try transCreateNodeVarDecl(c, false, false, checked_param_name);
419 node.eq_token = try appendToken(c, .Equal, "=");
420 node.init_node = try transCreateNodeIdentifier(c, arg_name);
421 node.semicolon_token = try appendToken(c, .Semicolon, ";");
422 try block_node.statements.push(&node.base);
423 param.name_token = try appendIdentifier(c, arg_name);
424 _ = try appendToken(c, .Colon, ":");
425 }
426
427 transCompoundStmtInline(rp, &block_scope.base, @ptrCast(*const ZigClangCompoundStmt, body_stmt), block_node) catch |err| switch (err) {
435 error.OutOfMemory => |e| return e,428 error.OutOfMemory => |e| return e,
436 error.UnsupportedTranslation,429 error.UnsupportedTranslation,
437 error.UnsupportedType,430 error.UnsupportedType,
438 => return failDecl(c, fn_decl_loc, fn_name, "unable to translate function", .{}),431 => return failDecl(c, fn_decl_loc, fn_name, "unable to translate function", .{}),
439 };432 };
440 assert(body_node.id == .Block);433 block_node.rbrace = try appendToken(rp.c, .RBrace, "}");
441 proto_node.body_node = body_node;434 proto_node.body_node = &block_node.base;
442
443 return addTopLevelDecl(c, fn_name, &proto_node.base);435 return addTopLevelDecl(c, fn_name, &proto_node.base);
444}436}
445437
...@@ -614,7 +606,7 @@ fn transRecordDecl(c: *Context, record_decl: *const ZigClangRecordDecl) Error!?*...@@ -614,7 +606,7 @@ fn transRecordDecl(c: *Context, record_decl: *const ZigClangRecordDecl) Error!?*
614 const name = try std.fmt.allocPrint(c.a(), "{}_{}", .{ container_kind_name, bare_name });606 const name = try std.fmt.allocPrint(c.a(), "{}_{}", .{ container_kind_name, bare_name });
615 _ = try c.decl_table.put(@ptrToInt(ZigClangRecordDecl_getCanonicalDecl(record_decl)), name);607 _ = try c.decl_table.put(@ptrToInt(ZigClangRecordDecl_getCanonicalDecl(record_decl)), name);
616608
617 const node = try transCreateNodeVarDecl(c, true, true, name);609 const node = try transCreateNodeVarDecl(c, !is_unnamed, true, name);
618610
619 node.eq_token = try appendToken(c, .Equal, "=");611 node.eq_token = try appendToken(c, .Equal, "=");
620612
...@@ -1020,10 +1012,10 @@ fn transBinaryOperator(...@@ -1020,10 +1012,10 @@ fn transBinaryOperator(
1020 .Mul => {1012 .Mul => {
1021 if (cIsUnsignedInteger(qt)) {1013 if (cIsUnsignedInteger(qt)) {
1022 op_token = try appendToken(rp.c, .AsteriskPercent, "*%");1014 op_token = try appendToken(rp.c, .AsteriskPercent, "*%");
1023 op_id = .MultWrap;1015 op_id = .MulWrap;
1024 } else {1016 } else {
1025 op_token = try appendToken(rp.c, .Asterisk, "*");1017 op_token = try appendToken(rp.c, .Asterisk, "*");
1026 op_id = .Mult;1018 op_id = .Mul;
1027 }1019 }
1028 },1020 },
1029 .Div => {1021 .Div => {
...@@ -1287,8 +1279,16 @@ fn transBoolExpr(...@@ -1287,8 +1279,16 @@ fn transBoolExpr(
1287 undefined;1279 undefined;
1288 var res = try transExpr(rp, scope, expr, used, lrvalue);1280 var res = try transExpr(rp, scope, expr, used, lrvalue);
12891281
1290 if (isBoolRes(res))1282 if (isBoolRes(res)) {
1283 if (!grouped and res.id == .GroupedExpression) {
1284 const group = @fieldParentPtr(ast.Node.GroupedExpression, "base", res);
1285 res = group.expr;
1286 // get zig fmt to work properly
1287 tokenSlice(rp.c, group.lparen)[0] = ')';
1288 }
1291 return res;1289 return res;
1290 }
1291
1292 const ty = ZigClangQualType_getTypePtr(getExprQualTypeBeforeImplicitCast(rp.c, expr));1292 const ty = ZigClangQualType_getTypePtr(getExprQualTypeBeforeImplicitCast(rp.c, expr));
1293 const node = try finishBoolExpr(rp, scope, ZigClangExpr_getBeginLoc(expr), ty, res, used);1293 const node = try finishBoolExpr(rp, scope, ZigClangExpr_getBeginLoc(expr), ty, res, used);
12941294
...@@ -2399,9 +2399,9 @@ fn transCreatePostCrement(...@@ -2399,9 +2399,9 @@ fn transCreatePostCrement(
2399fn transCompoundAssignOperator(rp: RestorePoint, scope: *Scope, stmt: *const ZigClangCompoundAssignOperator, used: ResultUsed) TransError!*ast.Node {2399fn transCompoundAssignOperator(rp: RestorePoint, scope: *Scope, stmt: *const ZigClangCompoundAssignOperator, used: ResultUsed) TransError!*ast.Node {
2400 switch (ZigClangCompoundAssignOperator_getOpcode(stmt)) {2400 switch (ZigClangCompoundAssignOperator_getOpcode(stmt)) {
2401 .MulAssign => if (qualTypeHaswrappingOverflow(ZigClangCompoundAssignOperator_getType(stmt)))2401 .MulAssign => if (qualTypeHaswrappingOverflow(ZigClangCompoundAssignOperator_getType(stmt)))
2402 return transCreateCompoundAssign(rp, scope, stmt, .AssignMulWrap, .AsteriskPercentEqual, "*%=", .MultWrap, .AsteriskPercent, "*%", used)2402 return transCreateCompoundAssign(rp, scope, stmt, .AssignMulWrap, .AsteriskPercentEqual, "*%=", .MulWrap, .AsteriskPercent, "*%", used)
2403 else2403 else
2404 return transCreateCompoundAssign(rp, scope, stmt, .AssignMul, .AsteriskEqual, "*=", .Mult, .Asterisk, "*", used),2404 return transCreateCompoundAssign(rp, scope, stmt, .AssignMul, .AsteriskEqual, "*=", .Mul, .Asterisk, "*", used),
2405 .AddAssign => if (qualTypeHaswrappingOverflow(ZigClangCompoundAssignOperator_getType(stmt)))2405 .AddAssign => if (qualTypeHaswrappingOverflow(ZigClangCompoundAssignOperator_getType(stmt)))
2406 return transCreateCompoundAssign(rp, scope, stmt, .AssignAddWrap, .PlusPercentEqual, "+%=", .AddWrap, .PlusPercent, "+%", used)2406 return transCreateCompoundAssign(rp, scope, stmt, .AssignAddWrap, .PlusPercentEqual, "+%=", .AddWrap, .PlusPercent, "+%", used)
2407 else2407 else
...@@ -3688,7 +3688,6 @@ const FnDeclContext = struct {...@@ -3688,7 +3688,6 @@ const FnDeclContext = struct {
3688 fn_name: []const u8,3688 fn_name: []const u8,
3689 has_body: bool,3689 has_body: bool,
3690 storage_class: ZigClangStorageClass,3690 storage_class: ZigClangStorageClass,
3691 scope: **Scope,
3692 is_export: bool,3691 is_export: bool,
3693};3692};
36943693
...@@ -3754,9 +3753,6 @@ fn finishTransFnProto(...@@ -3754,9 +3753,6 @@ fn finishTransFnProto(
3754 // TODO check for always_inline attribute3753 // TODO check for always_inline attribute
3755 // TODO check for align attribute3754 // TODO check for align attribute
37563755
3757 var fndef_scope = Scope.FnDef.init(rp.c);
3758 const scope = &fndef_scope.base;
3759
3760 // pub extern fn name(...) T3756 // pub extern fn name(...) T
3761 const pub_tok = if (is_pub) try appendToken(rp.c, .Keyword_pub, "pub") else null;3757 const pub_tok = if (is_pub) try appendToken(rp.c, .Keyword_pub, "pub") else null;
3762 const cc_tok = if (cc == .Stdcall) try appendToken(rp.c, .Keyword_stdcallcc, "stdcallcc") else null;3758 const cc_tok = if (cc == .Stdcall) try appendToken(rp.c, .Keyword_stdcallcc, "stdcallcc") else null;
...@@ -3782,15 +3778,11 @@ fn finishTransFnProto(...@@ -3782,15 +3778,11 @@ fn finishTransFnProto(
3782 const param_name_tok: ?ast.TokenIndex = blk: {3778 const param_name_tok: ?ast.TokenIndex = blk: {
3783 if (fn_decl != null) {3779 if (fn_decl != null) {
3784 const param = ZigClangFunctionDecl_getParamDecl(fn_decl.?, @intCast(c_uint, i));3780 const param = ZigClangFunctionDecl_getParamDecl(fn_decl.?, @intCast(c_uint, i));
3785 var param_name: []const u8 = try rp.c.str(ZigClangDecl_getName_bytes_begin(@ptrCast(*const ZigClangDecl, param)));3781 const param_name: []const u8 = try rp.c.str(ZigClangDecl_getName_bytes_begin(@ptrCast(*const ZigClangDecl, param)));
3786 if (param_name.len < 1)3782 if (param_name.len < 1)
3787 param_name = try std.fmt.allocPrint(rp.c.a(), "arg_{}", .{rp.c.getMangle()});3783 break :blk null;
3788 const checked_param_name = if (try scope.createAlias(rp.c, param_name)) |a| blk: {
3789 try fndef_scope.params.push(.{ .name = param_name, .alias = a });
3790 break :blk a;
3791 } else param_name;
37923784
3793 const result = try appendIdentifier(rp.c, checked_param_name);3785 const result = try appendIdentifier(rp.c, param_name);
3794 _ = try appendToken(rp.c, .Colon, ":");3786 _ = try appendToken(rp.c, .Colon, ":");
3795 break :blk result;3787 break :blk result;
3796 }3788 }
...@@ -4124,8 +4116,8 @@ fn transMacroDefine(c: *Context, it: *ctok.TokenList.Iterator, name: []const u8,...@@ -4124,8 +4116,8 @@ fn transMacroDefine(c: *Context, it: *ctok.TokenList.Iterator, name: []const u8,
41244116
4125fn transMacroFnDefine(c: *Context, it: *ctok.TokenList.Iterator, name: []const u8, source_loc: ZigClangSourceLocation) ParseError!void {4117fn transMacroFnDefine(c: *Context, it: *ctok.TokenList.Iterator, name: []const u8, source_loc: ZigClangSourceLocation) ParseError!void {
4126 const rp = makeRestorePoint(c);4118 const rp = makeRestorePoint(c);
4127 var fndef_scope = Scope.FnDef.init(c);4119 const block_scope = try Scope.Block.init(c, &c.global_scope.base, null);
4128 const scope = &fndef_scope.base;4120 const scope = &block_scope.base;
41294121
4130 const pub_tok = try appendToken(c, .Keyword_pub, "pub");4122 const pub_tok = try appendToken(c, .Keyword_pub, "pub");
4131 const inline_tok = try appendToken(c, .Keyword_inline, "inline");4123 const inline_tok = try appendToken(c, .Keyword_inline, "inline");
...@@ -4143,7 +4135,7 @@ fn transMacroFnDefine(c: *Context, it: *ctok.TokenList.Iterator, name: []const u...@@ -4143,7 +4135,7 @@ fn transMacroFnDefine(c: *Context, it: *ctok.TokenList.Iterator, name: []const u
4143 return error.ParseError;4135 return error.ParseError;
41444136
4145 const checked_name = if (try scope.createAlias(c, param_tok.bytes)) |alias| blk: {4137 const checked_name = if (try scope.createAlias(c, param_tok.bytes)) |alias| blk: {
4146 try fndef_scope.params.push(.{ .name = param_tok.bytes, .alias = alias });4138 try block_scope.variables.push(.{ .name = param_tok.bytes, .alias = alias });
4147 break :blk alias;4139 break :blk alias;
4148 } else param_tok.bytes;4140 } else param_tok.bytes;
41494141
...@@ -4521,9 +4513,9 @@ fn parseCPrefixOpExpr(rp: RestorePoint, it: *ctok.TokenList.Iterator, source_loc...@@ -4521,9 +4513,9 @@ fn parseCPrefixOpExpr(rp: RestorePoint, it: *ctok.TokenList.Iterator, source_loc
4521 }4513 }
4522}4514}
45234515
4524fn tokenSlice(c: *Context, token: ast.TokenIndex) []const u8 {4516fn tokenSlice(c: *Context, token: ast.TokenIndex) []u8 {
4525 const tok = c.tree.tokens.at(token);4517 const tok = c.tree.tokens.at(token);
4526 return c.source_buffer.toSliceConst()[tok.start..tok.end];4518 return c.source_buffer.toSlice()[tok.start..tok.end];
4527}4519}
45284520
4529fn getContainer(c: *Context, node: *ast.Node) ?*ast.Node {4521fn getContainer(c: *Context, node: *ast.Node) ?*ast.Node {
test/translate_c.zig+160-94
...@@ -127,16 +127,16 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -127,16 +127,16 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
127 });127 });
128128
129 cases.addC_both("add, sub, mul, div, rem",129 cases.addC_both("add, sub, mul, div, rem",
130 \\int s(int a, int b) {130 \\int s() {
131 \\ int c;131 \\ int a, b, c;
132 \\ c = a + b;132 \\ c = a + b;
133 \\ c = a - b;133 \\ c = a - b;
134 \\ c = a * b;134 \\ c = a * b;
135 \\ c = a / b;135 \\ c = a / b;
136 \\ c = a % b;136 \\ c = a % b;
137 \\}137 \\}
138 \\unsigned u(unsigned a, unsigned b) {138 \\unsigned u() {
139 \\ unsigned c;139 \\ unsigned a, b, c;
140 \\ c = a + b;140 \\ c = a + b;
141 \\ c = a - b;141 \\ c = a - b;
142 \\ c = a * b;142 \\ c = a * b;
...@@ -144,7 +144,9 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -144,7 +144,9 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
144 \\ c = a % b;144 \\ c = a % b;
145 \\}145 \\}
146 , &[_][]const u8{146 , &[_][]const u8{
147 \\pub export fn s(a: c_int, b: c_int) c_int {147 \\pub export fn s() c_int {
148 \\ var a: c_int = undefined;
149 \\ var b: c_int = undefined;
148 \\ var c: c_int = undefined;150 \\ var c: c_int = undefined;
149 \\ c = (a + b);151 \\ c = (a + b);
150 \\ c = (a - b);152 \\ c = (a - b);
...@@ -152,7 +154,9 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -152,7 +154,9 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
152 \\ c = @divTrunc(a, b);154 \\ c = @divTrunc(a, b);
153 \\ c = @rem(a, b);155 \\ c = @rem(a, b);
154 \\}156 \\}
155 \\pub export fn u(a: c_uint, b: c_uint) c_uint {157 \\pub export fn u() c_uint {
158 \\ var a: c_uint = undefined;
159 \\ var b: c_uint = undefined;
156 \\ var c: c_uint = undefined;160 \\ var c: c_uint = undefined;
157 \\ c = (a +% b);161 \\ c = (a +% b);
158 \\ c = (a -% b);162 \\ c = (a -% b);
...@@ -544,21 +548,25 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -544,21 +548,25 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
544 });548 });
545549
546 cases.addC_both("void cast",550 cases.addC_both("void cast",
547 \\void foo(int a) {551 \\void foo() {
552 \\ int a;
548 \\ (void) a;553 \\ (void) a;
549 \\}554 \\}
550 , &[_][]const u8{555 , &[_][]const u8{
551 \\pub export fn foo(a: c_int) void {556 \\pub export fn foo() void {
557 \\ var a: c_int = undefined;
552 \\ _ = a;558 \\ _ = a;
553 \\}559 \\}
554 });560 });
555561
556 cases.addC_both("implicit cast to void *",562 cases.addC_both("implicit cast to void *",
557 \\void *foo(unsigned short *x) {563 \\void *foo() {
564 \\ unsigned short *x;
558 \\ return x;565 \\ return x;
559 \\}566 \\}
560 , &[_][]const u8{567 , &[_][]const u8{
561 \\pub export fn foo(x: [*c]c_ushort) ?*c_void {568 \\pub export fn foo() ?*c_void {
569 \\ var x: [*c]c_ushort = undefined;
562 \\ return @ptrCast(?*c_void, x);570 \\ return @ptrCast(?*c_void, x);
563 \\}571 \\}
564 });572 });
...@@ -659,11 +667,13 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -659,11 +667,13 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
659 });667 });
660668
661 cases.addC_both("pointer casting",669 cases.addC_both("pointer casting",
662 \\float *ptrcast(int *a) {670 \\float *ptrcast() {
671 \\ int *a;
663 \\ return (float *)a;672 \\ return (float *)a;
664 \\}673 \\}
665 , &[_][]const u8{674 , &[_][]const u8{
666 \\pub export fn ptrcast(a: [*c]c_int) [*c]f32 {675 \\pub export fn ptrcast() [*c]f32 {
676 \\ var a: [*c]c_int = undefined;
667 \\ return @ptrCast([*c]f32, @alignCast(@alignOf(f32), a));677 \\ return @ptrCast([*c]f32, @alignCast(@alignOf(f32), a));
668 \\}678 \\}
669 });679 });
...@@ -702,29 +712,21 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -702,29 +712,21 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
702 \\}712 \\}
703 });713 });
704714
705 cases.addC_both("function call",
706 \\static void bar(void) { }
707 \\void foo(int *(baz)(void)) {
708 \\ bar();
709 \\ baz();
710 \\}
711 , &[_][]const u8{
712 \\pub fn bar() void {}
713 \\pub export fn foo(baz: ?extern fn () [*c]c_int) void {
714 \\ bar();
715 \\ _ = baz.?();
716 \\}
717 });
718
719 cases.addC_both("while on non-bool",715 cases.addC_both("while on non-bool",
720 \\int while_none_bool(int a, float b, void *c) {716 \\int while_none_bool() {
717 \\ int a;
718 \\ float b;
719 \\ void *c;
721 \\ while (a) return 0;720 \\ while (a) return 0;
722 \\ while (b) return 1;721 \\ while (b) return 1;
723 \\ while (c) return 2;722 \\ while (c) return 2;
724 \\ return 3;723 \\ return 3;
725 \\}724 \\}
726 , &[_][]const u8{725 , &[_][]const u8{
727 \\pub export fn while_none_bool(a: c_int, b: f32, c: ?*c_void) c_int {726 \\pub export fn while_none_bool() c_int {
727 \\ var a: c_int = undefined;
728 \\ var b: f32 = undefined;
729 \\ var c: ?*c_void = undefined;
728 \\ while (a != 0) return 0;730 \\ while (a != 0) return 0;
729 \\ while (b != 0) return 1;731 \\ while (b != 0) return 1;
730 \\ while (c != null) return 2;732 \\ while (c != null) return 2;
...@@ -733,14 +735,20 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -733,14 +735,20 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
733 });735 });
734736
735 cases.addC_both("for on non-bool",737 cases.addC_both("for on non-bool",
736 \\int for_none_bool(int a, float b, void *c) {738 \\int for_none_bool() {
739 \\ int a;
740 \\ float b;
741 \\ void *c;
737 \\ for (;a;) return 0;742 \\ for (;a;) return 0;
738 \\ for (;b;) return 1;743 \\ for (;b;) return 1;
739 \\ for (;c;) return 2;744 \\ for (;c;) return 2;
740 \\ return 3;745 \\ return 3;
741 \\}746 \\}
742 , &[_][]const u8{747 , &[_][]const u8{
743 \\pub export fn for_none_bool(a: c_int, b: f32, c: ?*c_void) c_int {748 \\pub export fn for_none_bool() c_int {
749 \\ var a: c_int = undefined;
750 \\ var b: f32 = undefined;
751 \\ var c: ?*c_void = undefined;
744 \\ while (a != 0) return 0;752 \\ while (a != 0) return 0;
745 \\ while (b != 0) return 1;753 \\ while (b != 0) return 1;
746 \\ while (c != null) return 2;754 \\ while (c != null) return 2;
...@@ -770,11 +778,13 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -770,11 +778,13 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
770 });778 });
771779
772 cases.addC_both("normal deref",780 cases.addC_both("normal deref",
773 \\void foo(int *x) {781 \\void foo() {
782 \\ int *x;
774 \\ *x = 1;783 \\ *x = 1;
775 \\}784 \\}
776 , &[_][]const u8{785 , &[_][]const u8{
777 \\pub export fn foo(x: [*c]c_int) void {786 \\pub export fn foo() void {
787 \\ var x: [*c]c_int = undefined;
778 \\ x.?.* = 1;788 \\ x.?.* = 1;
779 \\}789 \\}
780 });790 });
...@@ -794,24 +804,32 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -794,24 +804,32 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
794 });804 });
795805
796 cases.addC_both("bin not",806 cases.addC_both("bin not",
797 \\int foo(int x) {807 \\int foo() {
808 \\ int x;
798 \\ return ~x;809 \\ return ~x;
799 \\}810 \\}
800 , &[_][]const u8{811 , &[_][]const u8{
801 \\pub export fn foo(x: c_int) c_int {812 \\pub export fn foo() c_int {
813 \\ var x: c_int = undefined;
802 \\ return ~x;814 \\ return ~x;
803 \\}815 \\}
804 });816 });
805817
806 cases.addC_both("bool not",818 cases.addC_both("bool not",
807 \\int foo(int a, float b, void *c) {819 \\int foo() {
820 \\ int a;
821 \\ float b;
822 \\ void *c;
808 \\ return !(a == 0);823 \\ return !(a == 0);
809 \\ return !a;824 \\ return !a;
810 \\ return !b;825 \\ return !b;
811 \\ return !c;826 \\ return !c;
812 \\}827 \\}
813 , &[_][]const u8{828 , &[_][]const u8{
814 \\pub export fn foo(a: c_int, b: f32, c: ?*c_void) c_int {829 \\pub export fn foo() c_int {
830 \\ var a: c_int = undefined;
831 \\ var b: f32 = undefined;
832 \\ var c: ?*c_void = undefined;
815 \\ return !(a == 0);833 \\ return !(a == 0);
816 \\ return !(a != 0);834 \\ return !(a != 0);
817 \\ return !(b != 0);835 \\ return !(b != 0);
...@@ -829,6 +847,15 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -829,6 +847,15 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
829 \\}847 \\}
830 });848 });
831849
850 if (builtin.os != builtin.Os.windows) {
851 // sysv_abi not currently supported on windows
852 cases.add_both("Macro qualified functions",
853 \\void __attribute__((sysv_abi)) foo(void);
854 , &[_][]const u8{
855 \\pub extern fn foo() void;
856 });
857 }
858
832 /////////////// Cases that pass for only stage2 ////////////////859 /////////////// Cases that pass for only stage2 ////////////////
833860
834 cases.add_2("Parameterless function prototypes",861 cases.add_2("Parameterless function prototypes",
...@@ -1027,7 +1054,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -1027,7 +1054,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
1027 \\pub const GLbitfield = c_uint;1054 \\pub const GLbitfield = c_uint;
1028 \\pub const PFNGLCLEARPROC = ?extern fn (GLbitfield) void;1055 \\pub const PFNGLCLEARPROC = ?extern fn (GLbitfield) void;
1029 \\pub const OpenGLProc = ?extern fn () void;1056 \\pub const OpenGLProc = ?extern fn () void;
1030 \\pub const struct_unnamed_1 = extern struct {1057 \\const struct_unnamed_1 = extern struct {
1031 \\ Clear: PFNGLCLEARPROC,1058 \\ Clear: PFNGLCLEARPROC,
1032 \\};1059 \\};
1033 \\pub const union_OpenGLProcs = extern union {1060 \\pub const union_OpenGLProcs = extern union {
...@@ -1088,7 +1115,8 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -1088,7 +1115,8 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
1088 \\pub var a: c_long = @as(c_long, 2);1115 \\pub var a: c_long = @as(c_long, 2);
1089 \\pub var b: c_long = @as(c_long, 2);1116 \\pub var b: c_long = @as(c_long, 2);
1090 \\pub var c: c_int = 4;1117 \\pub var c: c_int = 4;
1091 \\pub export fn foo(c_1: u8) void {1118 \\pub export fn foo(_arg_c_1: u8) void {
1119 \\ var c_1 = _arg_c_1;
1092 \\ var a_2: c_int = undefined;1120 \\ var a_2: c_int = undefined;
1093 \\ var b_3: u8 = @as(u8, 123);1121 \\ var b_3: u8 = @as(u8, 123);
1094 \\ b_3 = @as(u8, a_2);1122 \\ b_3 = @as(u8, a_2);
...@@ -1105,7 +1133,8 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -1105,7 +1133,8 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
1105 \\ return 2, 4, 6;1133 \\ return 2, 4, 6;
1106 \\}1134 \\}
1107 , &[_][]const u8{1135 , &[_][]const u8{
1108 \\pub export fn foo(c: u8) c_int {1136 \\pub export fn foo(_arg_c: u8) c_int {
1137 \\ var c = _arg_c;
1109 \\ _ = 2;1138 \\ _ = 2;
1110 \\ _ = 4;1139 \\ _ = 4;
1111 \\ _ = 2;1140 \\ _ = 2;
...@@ -1121,7 +1150,8 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -1121,7 +1150,8 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
1121 \\ a = b = 2;1150 \\ a = b = 2;
1122 \\}1151 \\}
1123 , &[_][]const u8{1152 , &[_][]const u8{
1124 \\pub export fn foo(c: u8) c_int {1153 \\pub export fn foo(_arg_c: u8) c_int {
1154 \\ var c = _arg_c;
1125 \\ var a: c_int = undefined;1155 \\ var a: c_int = undefined;
1126 \\ var b: c_int = undefined;1156 \\ var b: c_int = undefined;
1127 \\ a = blk: {1157 \\ a = blk: {
...@@ -1142,7 +1172,8 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -1142,7 +1172,8 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
1142 \\ }1172 \\ }
1143 \\}1173 \\}
1144 , &[_][]const u8{1174 , &[_][]const u8{
1145 \\pub export fn foo(c: u8) c_int {1175 \\pub export fn foo(_arg_c: u8) c_int {
1176 \\ var c = _arg_c;
1146 \\ if (2 != 0) {1177 \\ if (2 != 0) {
1147 \\ var a: c_int = 2;1178 \\ var a: c_int = 2;
1148 \\ }1179 \\ }
...@@ -1265,7 +1296,8 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -1265,7 +1296,8 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
1265 \\ }1296 \\ }
1266 \\}1297 \\}
1267 , &[_][]const u8{1298 , &[_][]const u8{
1268 \\pub export fn switch_fn(i: c_int) c_int {1299 \\pub export fn switch_fn(_arg_i: c_int) c_int {
1300 \\ var i = _arg_i;
1269 \\ var res: c_int = 0;1301 \\ var res: c_int = 0;
1270 \\ __switch: {1302 \\ __switch: {
1271 \\ __case_2: {1303 \\ __case_2: {
...@@ -1316,7 +1348,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -1316,7 +1348,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
1316 cases.add_2("restrict -> noalias",1348 cases.add_2("restrict -> noalias",
1317 \\void foo(void *restrict bar, void *restrict);1349 \\void foo(void *restrict bar, void *restrict);
1318 , &[_][]const u8{1350 , &[_][]const u8{
1319 \\pub extern fn foo(noalias bar: ?*c_void, noalias arg_1: ?*c_void) void;1351 \\pub extern fn foo(noalias bar: ?*c_void, noalias ?*c_void) void;
1320 });1352 });
13211353
1322 cases.add_2("assign",1354 cases.add_2("assign",
...@@ -1326,7 +1358,8 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -1326,7 +1358,8 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
1326 \\ a = tmp;1358 \\ a = tmp;
1327 \\}1359 \\}
1328 , &[_][]const u8{1360 , &[_][]const u8{
1329 \\pub export fn max(a: c_int) c_int {1361 \\pub export fn max(_arg_a: c_int) c_int {
1362 \\ var a = _arg_a;
1330 \\ var tmp: c_int = undefined;1363 \\ var tmp: c_int = undefined;
1331 \\ tmp = a;1364 \\ tmp = a;
1332 \\ a = tmp;1365 \\ a = tmp;
...@@ -1339,7 +1372,8 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -1339,7 +1372,8 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
1339 \\ c = b = a;1372 \\ c = b = a;
1340 \\}1373 \\}
1341 , &[_][]const u8{1374 , &[_][]const u8{
1342 \\pub export fn max(a: c_int) void {1375 \\pub export fn max(_arg_a: c_int) void {
1376 \\ var a = _arg_a;
1343 \\ var b: c_int = undefined;1377 \\ var b: c_int = undefined;
1344 \\ var c: c_int = undefined;1378 \\ var c: c_int = undefined;
1345 \\ c = blk: {1379 \\ c = blk: {
...@@ -1369,7 +1403,8 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -1369,7 +1403,8 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
1369 \\ return (int)a;1403 \\ return (int)a;
1370 \\}1404 \\}
1371 , &[_][]const u8{1405 , &[_][]const u8{
1372 \\pub export fn float_to_int(a: f32) c_int {1406 \\pub export fn float_to_int(_arg_a: f32) c_int {
1407 \\ var a = _arg_a;
1373 \\ return @floatToInt(c_int, a);1408 \\ return @floatToInt(c_int, a);
1374 \\}1409 \\}
1375 });1410 });
...@@ -1434,19 +1469,6 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -1434,19 +1469,6 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
1434 \\}1469 \\}
1435 });1470 });
14361471
1437 cases.add_2("shift right with a fixed size type, no while", // TODO can fold this into "shift right assign with a fixed size type" once `>>=` is handled in translate-c-2
1438 \\#include <stdint.h>
1439 \\uint32_t some_func(uint32_t a) {
1440 \\ uint32_t b = a >> 1;
1441 \\ return b;
1442 \\}
1443 , &[_][]const u8{
1444 \\pub export fn some_func(a: u32) u32 {
1445 \\ var b: u32 = a >> @as(u5, 1);
1446 \\ return b;
1447 \\}
1448 });
1449
1450 cases.add_2("logical and, logical or, on non-bool values, extra parens",1472 cases.add_2("logical and, logical or, on non-bool values, extra parens",
1451 \\enum Foo {1473 \\enum Foo {
1452 \\ FooA,1474 \\ FooA,
...@@ -1480,7 +1502,10 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -1480,7 +1502,10 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
1480 \\ C,1502 \\ C,
1481 \\};1503 \\};
1482 \\pub const SomeTypedef = c_int;1504 \\pub const SomeTypedef = c_int;
1483 \\pub export fn and_or_non_bool(a: c_int, b: f32, c: ?*c_void) c_int {1505 \\pub export fn and_or_non_bool(_arg_a: c_int, _arg_b: f32, _arg_c: ?*c_void) c_int {
1506 \\ var a = _arg_a;
1507 \\ var b = _arg_b;
1508 \\ var c = _arg_c;
1484 \\ var d: enum_Foo = @as(enum_Foo, FooA);1509 \\ var d: enum_Foo = @as(enum_Foo, FooA);
1485 \\ var e: c_int = @boolToInt(((a != 0) and (b != 0)));1510 \\ var e: c_int = @boolToInt(((a != 0) and (b != 0)));
1486 \\ var f: c_int = @boolToInt(((b != 0) and (c != null)));1511 \\ var f: c_int = @boolToInt(((b != 0) and (c != null)));
...@@ -1532,12 +1557,14 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -1532,12 +1557,14 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
1532 \\ return (a & b) ^ (a | b);1557 \\ return (a & b) ^ (a | b);
1533 \\}1558 \\}
1534 , &[_][]const u8{1559 , &[_][]const u8{
1535 \\pub export fn max(a: c_int, b: c_int) c_int {1560 \\pub export fn max(_arg_a: c_int, _arg_b: c_int) c_int {
1561 \\ var a = _arg_a;
1562 \\ var b = _arg_b;
1536 \\ return ((a & b) ^ (a | b));1563 \\ return ((a & b) ^ (a | b));
1537 \\}1564 \\}
1538 });1565 });
15391566
1540 cases.add_2("comparison operators (no if)", // TODO Come up with less contrived tests? Make sure to cover all these comparisons. Can use `if` after it is added to translate-c-21567 cases.add_2("comparison operators (no if)", // TODO Come up with less contrived tests? Make sure to cover all these comparisons.
1541 \\int test_comparisons(int a, int b) {1568 \\int test_comparisons(int a, int b) {
1542 \\ int c = (a < b);1569 \\ int c = (a < b);
1543 \\ int d = (a > b);1570 \\ int d = (a > b);
...@@ -1549,7 +1576,9 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -1549,7 +1576,9 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
1549 \\ return i;1576 \\ return i;
1550 \\}1577 \\}
1551 , &[_][]const u8{1578 , &[_][]const u8{
1552 \\pub export fn test_comparisons(a: c_int, b: c_int) c_int {1579 \\pub export fn test_comparisons(_arg_a: c_int, _arg_b: c_int) c_int {
1580 \\ var a = _arg_a;
1581 \\ var b = _arg_b;
1553 \\ var c: c_int = @boolToInt((a < b));1582 \\ var c: c_int = @boolToInt((a < b));
1554 \\ var d: c_int = @boolToInt((a > b));1583 \\ var d: c_int = @boolToInt((a > b));
1555 \\ var e: c_int = @boolToInt((a <= b));1584 \\ var e: c_int = @boolToInt((a <= b));
...@@ -1570,9 +1599,11 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -1570,9 +1599,11 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
1570 \\ return a;1599 \\ return a;
1571 \\}1600 \\}
1572 , &[_][]const u8{1601 , &[_][]const u8{
1573 \\pub export fn max(a: c_int, b: c_int) c_int {1602 \\pub export fn max(_arg_a: c_int, _arg_b: c_int) c_int {
1574 \\ if ((a == b)) return a;1603 \\ var a = _arg_a;
1575 \\ if ((a != b)) return b;1604 \\ var b = _arg_b;
1605 \\ if (a == b) return a;
1606 \\ if (a != b) return b;
1576 \\ return a;1607 \\ return a;
1577 \\}1608 \\}
1578 });1609 });
...@@ -1646,7 +1677,8 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -1646,7 +1677,8 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
1646 \\}1677 \\}
1647 , &[_][]const u8{1678 , &[_][]const u8{
1648 \\pub export var array: [100]c_int = .{0} ** 100;1679 \\pub export var array: [100]c_int = .{0} ** 100;
1649 \\pub export fn foo(index: c_int) c_int {1680 \\pub export fn foo(_arg_index: c_int) c_int {
1681 \\ var index = _arg_index;
1650 \\ return array[index];1682 \\ return array[index];
1651 \\}1683 \\}
1652 ,1684 ,
...@@ -1670,9 +1702,11 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -1670,9 +1702,11 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
1670 \\ return a;1702 \\ return a;
1671 \\}1703 \\}
1672 , &[_][]const u8{1704 , &[_][]const u8{
1673 \\pub export fn max(a: c_int, b: c_int) c_int {1705 \\pub export fn max(_arg_a: c_int, _arg_b: c_int) c_int {
1674 \\ if (((a < b) or (a == b))) return b;1706 \\ var a = _arg_a;
1675 \\ if (((a >= b) and (a == b))) return a;1707 \\ var b = _arg_b;
1708 \\ if ((a < b) or (a == b)) return b;
1709 \\ if ((a >= b) and (a == b)) return a;
1676 \\ return a;1710 \\ return a;
1677 \\}1711 \\}
1678 });1712 });
...@@ -1690,10 +1724,12 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -1690,10 +1724,12 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
1690 \\ if (a < b) ; else ;1724 \\ if (a < b) ; else ;
1691 \\}1725 \\}
1692 , &[_][]const u8{1726 , &[_][]const u8{
1693 \\pub export fn max(a: c_int, b: c_int) c_int {1727 \\pub export fn max(_arg_a: c_int, _arg_b: c_int) c_int {
1694 \\ if ((a < b)) return b;1728 \\ var a = _arg_a;
1695 \\ if ((a < b)) return b else return a;1729 \\ var b = _arg_b;
1696 \\ if ((a < b)) {} else {}1730 \\ if (a < b) return b;
1731 \\ if (a < b) return b else return a;
1732 \\ if (a < b) {} else {}
1697 \\}1733 \\}
1698 });1734 });
16991735
...@@ -1715,7 +1751,11 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -1715,7 +1751,11 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
1715 \\ B,1751 \\ B,
1716 \\ C,1752 \\ C,
1717 \\};1753 \\};
1718 \\pub export fn if_none_bool(a: c_int, b: f32, c: ?*c_void, d: enum_SomeEnum) c_int {1754 \\pub export fn if_none_bool(_arg_a: c_int, _arg_b: f32, _arg_c: ?*c_void, _arg_d: enum_SomeEnum) c_int {
1755 \\ var a = _arg_a;
1756 \\ var b = _arg_b;
1757 \\ var c = _arg_c;
1758 \\ var d = _arg_d;
1719 \\ if (a != 0) return 0;1759 \\ if (a != 0) return 0;
1720 \\ if (b != 0) return 1;1760 \\ if (b != 0) return 1;
1721 \\ if (c != null) return 2;1761 \\ if (c != null) return 2;
...@@ -1741,8 +1781,9 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -1741,8 +1781,9 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
1741 \\ return a < 0 ? -a : a;1781 \\ return a < 0 ? -a : a;
1742 \\}1782 \\}
1743 , &[_][]const u8{1783 , &[_][]const u8{
1744 \\pub export fn abs(a: c_int) c_int {1784 \\pub export fn abs(_arg_a: c_int) c_int {
1745 \\ return if ((a < 0)) -a else a;1785 \\ var a = _arg_a;
1786 \\ return if (a < 0) -a else a;
1746 \\}1787 \\}
1747 });1788 });
17481789
...@@ -1756,11 +1797,13 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -1756,11 +1797,13 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
1756 \\ return a;1797 \\ return a;
1757 \\}1798 \\}
1758 , &[_][]const u8{1799 , &[_][]const u8{
1759 \\pub export fn foo1(a: c_uint) c_uint {1800 \\pub export fn foo1(_arg_a: c_uint) c_uint {
1801 \\ var a = _arg_a;
1760 \\ a +%= 1;1802 \\ a +%= 1;
1761 \\ return a;1803 \\ return a;
1762 \\}1804 \\}
1763 \\pub export fn foo2(a: c_int) c_int {1805 \\pub export fn foo2(_arg_a: c_int) c_int {
1806 \\ var a = _arg_a;
1764 \\ a += 1;1807 \\ a += 1;
1765 \\ return a;1808 \\ return a;
1766 \\}1809 \\}
...@@ -1848,10 +1891,11 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -1848,10 +1891,11 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
1848 \\ }1891 \\ }
1849 \\ return i;1892 \\ return i;
1850 \\}1893 \\}
1851 , &[_][]const u8{// TODO function arguments should be copied1894 , &[_][]const u8{
1852 \\pub export fn log2(a: c_uint) c_int {1895 \\pub export fn log2(_arg_a: c_uint) c_int {
1896 \\ var a = _arg_a;
1853 \\ var i: c_int = 0;1897 \\ var i: c_int = 0;
1854 \\ while ((a > @as(c_uint, 0))) {1898 \\ while (a > @as(c_uint, 0)) {
1855 \\ a >>= @as(@import("std").math.Log2Int(c_int), 1);1899 \\ a >>= @as(@import("std").math.Log2Int(c_int), 1);
1856 \\ }1900 \\ }
1857 \\ return i;1901 \\ return i;
...@@ -1868,9 +1912,10 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -1868,9 +1912,10 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
1868 \\ return i;1912 \\ return i;
1869 \\}1913 \\}
1870 , &[_][]const u8{1914 , &[_][]const u8{
1871 \\pub export fn log2(a: u32) c_int {1915 \\pub export fn log2(_arg_a: u32) c_int {
1916 \\ var a = _arg_a;
1872 \\ var i: c_int = 0;1917 \\ var i: c_int = 0;
1873 \\ while ((a > @as(c_uint, 0))) {1918 \\ while (a > @as(c_uint, 0)) {
1874 \\ a >>= @as(@import("std").math.Log2Int(c_int), 1);1919 \\ a >>= @as(@import("std").math.Log2Int(c_int), 1);
1875 \\ }1920 \\ }
1876 \\ return i;1921 \\ return i;
...@@ -2076,7 +2121,8 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -2076,7 +2121,8 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
2076 \\pub extern fn fn_char(x: u8) void;2121 \\pub extern fn fn_char(x: u8) void;
2077 \\pub extern fn fn_bool(x: bool) void;2122 \\pub extern fn fn_bool(x: bool) void;
2078 \\pub extern fn fn_ptr(x: ?*c_void) void;2123 \\pub extern fn fn_ptr(x: ?*c_void) void;
2079 \\pub export fn call(q: c_int) void {2124 \\pub export fn call(_arg_q: c_int) void {
2125 \\ var q = _arg_q;
2080 \\ fn_int(@floatToInt(c_int, 3));2126 \\ fn_int(@floatToInt(c_int, 3));
2081 \\ fn_int(@floatToInt(c_int, 3));2127 \\ fn_int(@floatToInt(c_int, 3));
2082 \\ fn_int(@floatToInt(c_int, 3));2128 \\ fn_int(@floatToInt(c_int, 3));
...@@ -2096,6 +2142,21 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -2096,6 +2142,21 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
2096 \\}2142 \\}
2097 });2143 });
20982144
2145 cases.add_2("function call",
2146 \\static void bar(void) { }
2147 \\void foo(int *(baz)(void)) {
2148 \\ bar();
2149 \\ baz();
2150 \\}
2151 , &[_][]const u8{
2152 \\pub fn bar() void {}
2153 \\pub export fn foo(_arg_baz: ?extern fn () [*c]c_int) void {
2154 \\ var baz = _arg_baz;
2155 \\ bar();
2156 \\ _ = baz.?();
2157 \\}
2158 });
2159
2099 /////////////// Cases for only stage1 which are TODO items for stage2 ////////////////2160 /////////////// Cases for only stage1 which are TODO items for stage2 ////////////////
21002161
2101 cases.add("macro defines string literal with hex",2162 cases.add("macro defines string literal with hex",
...@@ -2122,15 +2183,6 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -2122,15 +2183,6 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
2122 \\pub const FOO_CHAR = 63;2183 \\pub const FOO_CHAR = 63;
2123 });2184 });
21242185
2125 if (builtin.os != builtin.Os.windows) {
2126 // sysv_abi not currently supported on windows
2127 cases.add("Macro qualified functions",
2128 \\void __attribute__((sysv_abi)) foo(void);
2129 , &[_][]const u8{
2130 \\pub extern fn foo() void;
2131 });
2132 }
2133
2134 /////////////// Cases for only stage1 because stage2 behavior is better ////////////////2186 /////////////// Cases for only stage1 because stage2 behavior is better ////////////////
2135 cases.addC("Parameterless function prototypes",2187 cases.addC("Parameterless function prototypes",
2136 \\void foo() {}2188 \\void foo() {}
...@@ -3045,4 +3097,18 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -3045,4 +3097,18 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
3045 \\ fn_ptr(@intToPtr(?*c_void, 42));3097 \\ fn_ptr(@intToPtr(?*c_void, 42));
3046 \\}3098 \\}
3047 });3099 });
3100
3101 cases.addC("function call",
3102 \\static void bar(void) { }
3103 \\void foo(int *(baz)(void)) {
3104 \\ bar();
3105 \\ baz();
3106 \\}
3107 , &[_][]const u8{
3108 \\pub fn bar() void {}
3109 \\pub export fn foo(baz: ?extern fn () [*c]c_int) void {
3110 \\ bar();
3111 \\ _ = baz.?();
3112 \\}
3113 });
3048}3114}