mirror of
https://github.com/ziglang/zig.git
synced 2026-02-13 21:08:36 +00:00
translate-c-2 copy parametrs to stack
This commit is contained in:
parent
b7f18164f9
commit
d172a7335c
@ -1456,8 +1456,8 @@ pub const Node = struct {
|
||||
LessThan,
|
||||
MergeErrorSets,
|
||||
Mod,
|
||||
Mult,
|
||||
MultWrap,
|
||||
Mul,
|
||||
MulWrap,
|
||||
Period,
|
||||
Range,
|
||||
Sub,
|
||||
@ -1514,8 +1514,8 @@ pub const Node = struct {
|
||||
Op.LessThan,
|
||||
Op.MergeErrorSets,
|
||||
Op.Mod,
|
||||
Op.Mult,
|
||||
Op.MultWrap,
|
||||
Op.Mul,
|
||||
Op.MulWrap,
|
||||
Op.Period,
|
||||
Op.Range,
|
||||
Op.Sub,
|
||||
|
||||
@ -2120,11 +2120,11 @@ fn parseMultiplyOp(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
|
||||
const token = nextToken(it);
|
||||
const op = switch (token.ptr.id) {
|
||||
.PipePipe => ops{ .BoolOr = {} },
|
||||
.Asterisk => ops{ .Mult = {} },
|
||||
.Asterisk => ops{ .Mul = {} },
|
||||
.Slash => ops{ .Div = {} },
|
||||
.Percent => ops{ .Mod = {} },
|
||||
.AsteriskAsterisk => ops{ .ArrayMult = {} },
|
||||
.AsteriskPercent => ops{ .MultWrap = {} },
|
||||
.AsteriskPercent => ops{ .MulWrap = {} },
|
||||
else => {
|
||||
putBackToken(it, token.index);
|
||||
return null;
|
||||
|
||||
@ -49,7 +49,6 @@ const Scope = struct {
|
||||
Block,
|
||||
Root,
|
||||
Condition,
|
||||
FnDef,
|
||||
Loop,
|
||||
};
|
||||
|
||||
@ -121,39 +120,6 @@ const Scope = struct {
|
||||
}
|
||||
};
|
||||
|
||||
const FnDef = struct {
|
||||
base: Scope,
|
||||
params: AliasList,
|
||||
|
||||
fn init(c: *Context) FnDef {
|
||||
return .{
|
||||
.base = .{
|
||||
.id = .FnDef,
|
||||
.parent = &c.global_scope.base,
|
||||
},
|
||||
.params = AliasList.init(c.a()),
|
||||
};
|
||||
}
|
||||
|
||||
fn getAlias(scope: *FnDef, name: []const u8) ?[]const u8 {
|
||||
var it = scope.params.iterator(0);
|
||||
while (it.next()) |p| {
|
||||
if (mem.eql(u8, p.name, name))
|
||||
return p.alias;
|
||||
}
|
||||
return scope.base.parent.?.getAlias(name);
|
||||
}
|
||||
|
||||
fn contains(scope: *FnDef, name: []const u8) bool {
|
||||
var it = scope.params.iterator(0);
|
||||
while (it.next()) |p| {
|
||||
if (mem.eql(u8, p.name, name))
|
||||
return true;
|
||||
}
|
||||
return scope.base.parent.?.contains(name);
|
||||
}
|
||||
};
|
||||
|
||||
fn findBlockScope(inner: *Scope, c: *Context) !*Scope.Block {
|
||||
var scope = inner;
|
||||
while (true) {
|
||||
@ -179,7 +145,6 @@ const Scope = struct {
|
||||
fn getAlias(scope: *Scope, name: []const u8) ?[]const u8 {
|
||||
return switch (scope.id) {
|
||||
.Root => null,
|
||||
.FnDef => @fieldParentPtr(FnDef, "base", scope).getAlias(name),
|
||||
.Block => @fieldParentPtr(Block, "base", scope).getAlias(name),
|
||||
.Switch, .Loop, .Condition => scope.parent.?.getAlias(name),
|
||||
};
|
||||
@ -188,7 +153,6 @@ const Scope = struct {
|
||||
fn contains(scope: *Scope, name: []const u8) bool {
|
||||
return switch (scope.id) {
|
||||
.Root => @fieldParentPtr(Root, "base", scope).contains(name),
|
||||
.FnDef => @fieldParentPtr(FnDef, "base", scope).contains(name),
|
||||
.Block => @fieldParentPtr(Block, "base", scope).contains(name),
|
||||
.Switch, .Loop, .Condition => scope.parent.?.contains(name),
|
||||
};
|
||||
@ -198,7 +162,7 @@ const Scope = struct {
|
||||
var scope = inner;
|
||||
while (true) {
|
||||
switch (scope.id) {
|
||||
.FnDef => unreachable,
|
||||
.Root => unreachable,
|
||||
.Switch => return scope,
|
||||
.Loop => return scope,
|
||||
else => scope = scope.parent.?,
|
||||
@ -210,7 +174,7 @@ const Scope = struct {
|
||||
var scope = inner;
|
||||
while (true) {
|
||||
switch (scope.id) {
|
||||
.FnDef => unreachable,
|
||||
.Root => unreachable,
|
||||
.Switch => return @fieldParentPtr(Switch, "base", scope),
|
||||
else => scope = scope.parent.?,
|
||||
}
|
||||
@ -382,17 +346,12 @@ fn visitFnDecl(c: *Context, fn_decl: *const ZigClangFunctionDecl) Error!void {
|
||||
const fn_name = try c.str(ZigClangDecl_getName_bytes_begin(@ptrCast(*const ZigClangDecl, fn_decl)));
|
||||
_ = try c.decl_table.put(@ptrToInt(fn_decl), fn_name);
|
||||
const fn_decl_loc = ZigClangFunctionDecl_getLocation(fn_decl);
|
||||
const fn_qt = ZigClangFunctionDecl_getType(fn_decl);
|
||||
const fn_type = ZigClangQualType_getTypePtr(fn_qt);
|
||||
var fndef_scope = Scope.FnDef.init(c);
|
||||
var scope = &fndef_scope.base;
|
||||
const has_body = ZigClangFunctionDecl_hasBody(fn_decl);
|
||||
const storage_class = ZigClangFunctionDecl_getStorageClass(fn_decl);
|
||||
const decl_ctx = FnDeclContext{
|
||||
.fn_name = fn_name,
|
||||
.has_body = has_body,
|
||||
.storage_class = storage_class,
|
||||
.scope = &scope,
|
||||
.is_export = switch (storage_class) {
|
||||
.None => has_body,
|
||||
.Extern, .Static => false,
|
||||
@ -402,6 +361,15 @@ fn visitFnDecl(c: *Context, fn_decl: *const ZigClangFunctionDecl) Error!void {
|
||||
else => unreachable,
|
||||
},
|
||||
};
|
||||
|
||||
var fn_qt = ZigClangFunctionDecl_getType(fn_decl);
|
||||
var fn_type = ZigClangQualType_getTypePtr(fn_qt);
|
||||
if (ZigClangType_getTypeClass(fn_type) == .Attributed) {
|
||||
const attr_type = @ptrCast(*const ZigClangAttributedType, fn_type);
|
||||
fn_qt = ZigClangAttributedType_getEquivalentType(attr_type);
|
||||
fn_type = ZigClangQualType_getTypePtr(fn_qt);
|
||||
}
|
||||
|
||||
const proto_node = switch (ZigClangType_getTypeClass(fn_type)) {
|
||||
.FunctionProto => blk: {
|
||||
const fn_proto_type = @ptrCast(*const ZigClangFunctionProtoType, fn_type);
|
||||
@ -431,15 +399,39 @@ fn visitFnDecl(c: *Context, fn_decl: *const ZigClangFunctionDecl) Error!void {
|
||||
|
||||
// actual function definition with body
|
||||
const body_stmt = ZigClangFunctionDecl_getBody(fn_decl);
|
||||
const body_node = transStmt(rp, scope, body_stmt, .unused, .r_value) catch |err| switch (err) {
|
||||
const block_scope = try Scope.Block.init(rp.c, &c.global_scope.base, null);
|
||||
var scope = &block_scope.base;
|
||||
const block_node = try transCreateNodeBlock(rp.c, null);
|
||||
block_scope.block_node = block_node;
|
||||
|
||||
var it = proto_node.params.iterator(0);
|
||||
while (it.next()) |p| {
|
||||
const param = @fieldParentPtr(ast.Node.ParamDecl, "base", p.*);
|
||||
const param_name = tokenSlice(c, param.name_token.?);
|
||||
|
||||
const checked_param_name = if (try scope.createAlias(rp.c, param_name)) |a| blk: {
|
||||
try block_scope.variables.push(.{ .name = param_name, .alias = a });
|
||||
break :blk a;
|
||||
} else param_name;
|
||||
const arg_name = try std.fmt.allocPrint(c.a(), "_arg_{}", .{checked_param_name});
|
||||
|
||||
const node = try transCreateNodeVarDecl(c, false, false, checked_param_name);
|
||||
node.eq_token = try appendToken(c, .Equal, "=");
|
||||
node.init_node = try transCreateNodeIdentifier(c, arg_name);
|
||||
node.semicolon_token = try appendToken(c, .Semicolon, ";");
|
||||
try block_node.statements.push(&node.base);
|
||||
param.name_token = try appendIdentifier(c, arg_name);
|
||||
_ = try appendToken(c, .Colon, ":");
|
||||
}
|
||||
|
||||
transCompoundStmtInline(rp, &block_scope.base, @ptrCast(*const ZigClangCompoundStmt, body_stmt), block_node) catch |err| switch (err) {
|
||||
error.OutOfMemory => |e| return e,
|
||||
error.UnsupportedTranslation,
|
||||
error.UnsupportedType,
|
||||
=> return failDecl(c, fn_decl_loc, fn_name, "unable to translate function", .{}),
|
||||
};
|
||||
assert(body_node.id == .Block);
|
||||
proto_node.body_node = body_node;
|
||||
|
||||
block_node.rbrace = try appendToken(rp.c, .RBrace, "}");
|
||||
proto_node.body_node = &block_node.base;
|
||||
return addTopLevelDecl(c, fn_name, &proto_node.base);
|
||||
}
|
||||
|
||||
@ -614,7 +606,7 @@ fn transRecordDecl(c: *Context, record_decl: *const ZigClangRecordDecl) Error!?*
|
||||
const name = try std.fmt.allocPrint(c.a(), "{}_{}", .{ container_kind_name, bare_name });
|
||||
_ = try c.decl_table.put(@ptrToInt(ZigClangRecordDecl_getCanonicalDecl(record_decl)), name);
|
||||
|
||||
const node = try transCreateNodeVarDecl(c, true, true, name);
|
||||
const node = try transCreateNodeVarDecl(c, !is_unnamed, true, name);
|
||||
|
||||
node.eq_token = try appendToken(c, .Equal, "=");
|
||||
|
||||
@ -1020,10 +1012,10 @@ fn transBinaryOperator(
|
||||
.Mul => {
|
||||
if (cIsUnsignedInteger(qt)) {
|
||||
op_token = try appendToken(rp.c, .AsteriskPercent, "*%");
|
||||
op_id = .MultWrap;
|
||||
op_id = .MulWrap;
|
||||
} else {
|
||||
op_token = try appendToken(rp.c, .Asterisk, "*");
|
||||
op_id = .Mult;
|
||||
op_id = .Mul;
|
||||
}
|
||||
},
|
||||
.Div => {
|
||||
@ -1287,8 +1279,16 @@ fn transBoolExpr(
|
||||
undefined;
|
||||
var res = try transExpr(rp, scope, expr, used, lrvalue);
|
||||
|
||||
if (isBoolRes(res))
|
||||
if (isBoolRes(res)) {
|
||||
if (!grouped and res.id == .GroupedExpression) {
|
||||
const group = @fieldParentPtr(ast.Node.GroupedExpression, "base", res);
|
||||
res = group.expr;
|
||||
// get zig fmt to work properly
|
||||
tokenSlice(rp.c, group.lparen)[0] = ')';
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
const ty = ZigClangQualType_getTypePtr(getExprQualTypeBeforeImplicitCast(rp.c, expr));
|
||||
const node = try finishBoolExpr(rp, scope, ZigClangExpr_getBeginLoc(expr), ty, res, used);
|
||||
|
||||
@ -2399,9 +2399,9 @@ fn transCreatePostCrement(
|
||||
fn transCompoundAssignOperator(rp: RestorePoint, scope: *Scope, stmt: *const ZigClangCompoundAssignOperator, used: ResultUsed) TransError!*ast.Node {
|
||||
switch (ZigClangCompoundAssignOperator_getOpcode(stmt)) {
|
||||
.MulAssign => if (qualTypeHaswrappingOverflow(ZigClangCompoundAssignOperator_getType(stmt)))
|
||||
return transCreateCompoundAssign(rp, scope, stmt, .AssignMulWrap, .AsteriskPercentEqual, "*%=", .MultWrap, .AsteriskPercent, "*%", used)
|
||||
return transCreateCompoundAssign(rp, scope, stmt, .AssignMulWrap, .AsteriskPercentEqual, "*%=", .MulWrap, .AsteriskPercent, "*%", used)
|
||||
else
|
||||
return transCreateCompoundAssign(rp, scope, stmt, .AssignMul, .AsteriskEqual, "*=", .Mult, .Asterisk, "*", used),
|
||||
return transCreateCompoundAssign(rp, scope, stmt, .AssignMul, .AsteriskEqual, "*=", .Mul, .Asterisk, "*", used),
|
||||
.AddAssign => if (qualTypeHaswrappingOverflow(ZigClangCompoundAssignOperator_getType(stmt)))
|
||||
return transCreateCompoundAssign(rp, scope, stmt, .AssignAddWrap, .PlusPercentEqual, "+%=", .AddWrap, .PlusPercent, "+%", used)
|
||||
else
|
||||
@ -3688,7 +3688,6 @@ const FnDeclContext = struct {
|
||||
fn_name: []const u8,
|
||||
has_body: bool,
|
||||
storage_class: ZigClangStorageClass,
|
||||
scope: **Scope,
|
||||
is_export: bool,
|
||||
};
|
||||
|
||||
@ -3754,9 +3753,6 @@ fn finishTransFnProto(
|
||||
// TODO check for always_inline attribute
|
||||
// TODO check for align attribute
|
||||
|
||||
var fndef_scope = Scope.FnDef.init(rp.c);
|
||||
const scope = &fndef_scope.base;
|
||||
|
||||
// pub extern fn name(...) T
|
||||
const pub_tok = if (is_pub) try appendToken(rp.c, .Keyword_pub, "pub") else null;
|
||||
const cc_tok = if (cc == .Stdcall) try appendToken(rp.c, .Keyword_stdcallcc, "stdcallcc") else null;
|
||||
@ -3782,15 +3778,11 @@ fn finishTransFnProto(
|
||||
const param_name_tok: ?ast.TokenIndex = blk: {
|
||||
if (fn_decl != null) {
|
||||
const param = ZigClangFunctionDecl_getParamDecl(fn_decl.?, @intCast(c_uint, i));
|
||||
var param_name: []const u8 = try rp.c.str(ZigClangDecl_getName_bytes_begin(@ptrCast(*const ZigClangDecl, param)));
|
||||
const param_name: []const u8 = try rp.c.str(ZigClangDecl_getName_bytes_begin(@ptrCast(*const ZigClangDecl, param)));
|
||||
if (param_name.len < 1)
|
||||
param_name = try std.fmt.allocPrint(rp.c.a(), "arg_{}", .{rp.c.getMangle()});
|
||||
const checked_param_name = if (try scope.createAlias(rp.c, param_name)) |a| blk: {
|
||||
try fndef_scope.params.push(.{ .name = param_name, .alias = a });
|
||||
break :blk a;
|
||||
} else param_name;
|
||||
break :blk null;
|
||||
|
||||
const result = try appendIdentifier(rp.c, checked_param_name);
|
||||
const result = try appendIdentifier(rp.c, param_name);
|
||||
_ = try appendToken(rp.c, .Colon, ":");
|
||||
break :blk result;
|
||||
}
|
||||
@ -4124,8 +4116,8 @@ fn transMacroDefine(c: *Context, it: *ctok.TokenList.Iterator, name: []const u8,
|
||||
|
||||
fn transMacroFnDefine(c: *Context, it: *ctok.TokenList.Iterator, name: []const u8, source_loc: ZigClangSourceLocation) ParseError!void {
|
||||
const rp = makeRestorePoint(c);
|
||||
var fndef_scope = Scope.FnDef.init(c);
|
||||
const scope = &fndef_scope.base;
|
||||
const block_scope = try Scope.Block.init(c, &c.global_scope.base, null);
|
||||
const scope = &block_scope.base;
|
||||
|
||||
const pub_tok = try appendToken(c, .Keyword_pub, "pub");
|
||||
const inline_tok = try appendToken(c, .Keyword_inline, "inline");
|
||||
@ -4143,7 +4135,7 @@ fn transMacroFnDefine(c: *Context, it: *ctok.TokenList.Iterator, name: []const u
|
||||
return error.ParseError;
|
||||
|
||||
const checked_name = if (try scope.createAlias(c, param_tok.bytes)) |alias| blk: {
|
||||
try fndef_scope.params.push(.{ .name = param_tok.bytes, .alias = alias });
|
||||
try block_scope.variables.push(.{ .name = param_tok.bytes, .alias = alias });
|
||||
break :blk alias;
|
||||
} else param_tok.bytes;
|
||||
|
||||
@ -4521,9 +4513,9 @@ fn parseCPrefixOpExpr(rp: RestorePoint, it: *ctok.TokenList.Iterator, source_loc
|
||||
}
|
||||
}
|
||||
|
||||
fn tokenSlice(c: *Context, token: ast.TokenIndex) []const u8 {
|
||||
fn tokenSlice(c: *Context, token: ast.TokenIndex) []u8 {
|
||||
const tok = c.tree.tokens.at(token);
|
||||
return c.source_buffer.toSliceConst()[tok.start..tok.end];
|
||||
return c.source_buffer.toSlice()[tok.start..tok.end];
|
||||
}
|
||||
|
||||
fn getContainer(c: *Context, node: *ast.Node) ?*ast.Node {
|
||||
|
||||
@ -127,16 +127,16 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
||||
});
|
||||
|
||||
cases.addC_both("add, sub, mul, div, rem",
|
||||
\\int s(int a, int b) {
|
||||
\\ int c;
|
||||
\\int s() {
|
||||
\\ int a, b, c;
|
||||
\\ c = a + b;
|
||||
\\ c = a - b;
|
||||
\\ c = a * b;
|
||||
\\ c = a / b;
|
||||
\\ c = a % b;
|
||||
\\}
|
||||
\\unsigned u(unsigned a, unsigned b) {
|
||||
\\ unsigned c;
|
||||
\\unsigned u() {
|
||||
\\ unsigned a, b, c;
|
||||
\\ c = a + b;
|
||||
\\ c = a - b;
|
||||
\\ c = a * b;
|
||||
@ -144,7 +144,9 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
||||
\\ c = a % b;
|
||||
\\}
|
||||
, &[_][]const u8{
|
||||
\\pub export fn s(a: c_int, b: c_int) c_int {
|
||||
\\pub export fn s() c_int {
|
||||
\\ var a: c_int = undefined;
|
||||
\\ var b: c_int = undefined;
|
||||
\\ var c: c_int = undefined;
|
||||
\\ c = (a + b);
|
||||
\\ c = (a - b);
|
||||
@ -152,7 +154,9 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
||||
\\ c = @divTrunc(a, b);
|
||||
\\ c = @rem(a, b);
|
||||
\\}
|
||||
\\pub export fn u(a: c_uint, b: c_uint) c_uint {
|
||||
\\pub export fn u() c_uint {
|
||||
\\ var a: c_uint = undefined;
|
||||
\\ var b: c_uint = undefined;
|
||||
\\ var c: c_uint = undefined;
|
||||
\\ c = (a +% b);
|
||||
\\ c = (a -% b);
|
||||
@ -544,21 +548,25 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
||||
});
|
||||
|
||||
cases.addC_both("void cast",
|
||||
\\void foo(int a) {
|
||||
\\void foo() {
|
||||
\\ int a;
|
||||
\\ (void) a;
|
||||
\\}
|
||||
, &[_][]const u8{
|
||||
\\pub export fn foo(a: c_int) void {
|
||||
\\pub export fn foo() void {
|
||||
\\ var a: c_int = undefined;
|
||||
\\ _ = a;
|
||||
\\}
|
||||
});
|
||||
|
||||
cases.addC_both("implicit cast to void *",
|
||||
\\void *foo(unsigned short *x) {
|
||||
\\void *foo() {
|
||||
\\ unsigned short *x;
|
||||
\\ return x;
|
||||
\\}
|
||||
, &[_][]const u8{
|
||||
\\pub export fn foo(x: [*c]c_ushort) ?*c_void {
|
||||
\\pub export fn foo() ?*c_void {
|
||||
\\ var x: [*c]c_ushort = undefined;
|
||||
\\ return @ptrCast(?*c_void, x);
|
||||
\\}
|
||||
});
|
||||
@ -659,11 +667,13 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
||||
});
|
||||
|
||||
cases.addC_both("pointer casting",
|
||||
\\float *ptrcast(int *a) {
|
||||
\\float *ptrcast() {
|
||||
\\ int *a;
|
||||
\\ return (float *)a;
|
||||
\\}
|
||||
, &[_][]const u8{
|
||||
\\pub export fn ptrcast(a: [*c]c_int) [*c]f32 {
|
||||
\\pub export fn ptrcast() [*c]f32 {
|
||||
\\ var a: [*c]c_int = undefined;
|
||||
\\ return @ptrCast([*c]f32, @alignCast(@alignOf(f32), a));
|
||||
\\}
|
||||
});
|
||||
@ -702,29 +712,21 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
||||
\\}
|
||||
});
|
||||
|
||||
cases.addC_both("function call",
|
||||
\\static void bar(void) { }
|
||||
\\void foo(int *(baz)(void)) {
|
||||
\\ bar();
|
||||
\\ baz();
|
||||
\\}
|
||||
, &[_][]const u8{
|
||||
\\pub fn bar() void {}
|
||||
\\pub export fn foo(baz: ?extern fn () [*c]c_int) void {
|
||||
\\ bar();
|
||||
\\ _ = baz.?();
|
||||
\\}
|
||||
});
|
||||
|
||||
cases.addC_both("while on non-bool",
|
||||
\\int while_none_bool(int a, float b, void *c) {
|
||||
\\int while_none_bool() {
|
||||
\\ int a;
|
||||
\\ float b;
|
||||
\\ void *c;
|
||||
\\ while (a) return 0;
|
||||
\\ while (b) return 1;
|
||||
\\ while (c) return 2;
|
||||
\\ return 3;
|
||||
\\}
|
||||
, &[_][]const u8{
|
||||
\\pub export fn while_none_bool(a: c_int, b: f32, c: ?*c_void) c_int {
|
||||
\\pub export fn while_none_bool() c_int {
|
||||
\\ var a: c_int = undefined;
|
||||
\\ var b: f32 = undefined;
|
||||
\\ var c: ?*c_void = undefined;
|
||||
\\ while (a != 0) return 0;
|
||||
\\ while (b != 0) return 1;
|
||||
\\ while (c != null) return 2;
|
||||
@ -733,14 +735,20 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
||||
});
|
||||
|
||||
cases.addC_both("for on non-bool",
|
||||
\\int for_none_bool(int a, float b, void *c) {
|
||||
\\int for_none_bool() {
|
||||
\\ int a;
|
||||
\\ float b;
|
||||
\\ void *c;
|
||||
\\ for (;a;) return 0;
|
||||
\\ for (;b;) return 1;
|
||||
\\ for (;c;) return 2;
|
||||
\\ return 3;
|
||||
\\}
|
||||
, &[_][]const u8{
|
||||
\\pub export fn for_none_bool(a: c_int, b: f32, c: ?*c_void) c_int {
|
||||
\\pub export fn for_none_bool() c_int {
|
||||
\\ var a: c_int = undefined;
|
||||
\\ var b: f32 = undefined;
|
||||
\\ var c: ?*c_void = undefined;
|
||||
\\ while (a != 0) return 0;
|
||||
\\ while (b != 0) return 1;
|
||||
\\ while (c != null) return 2;
|
||||
@ -770,11 +778,13 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
||||
});
|
||||
|
||||
cases.addC_both("normal deref",
|
||||
\\void foo(int *x) {
|
||||
\\void foo() {
|
||||
\\ int *x;
|
||||
\\ *x = 1;
|
||||
\\}
|
||||
, &[_][]const u8{
|
||||
\\pub export fn foo(x: [*c]c_int) void {
|
||||
\\pub export fn foo() void {
|
||||
\\ var x: [*c]c_int = undefined;
|
||||
\\ x.?.* = 1;
|
||||
\\}
|
||||
});
|
||||
@ -794,24 +804,32 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
||||
});
|
||||
|
||||
cases.addC_both("bin not",
|
||||
\\int foo(int x) {
|
||||
\\int foo() {
|
||||
\\ int x;
|
||||
\\ return ~x;
|
||||
\\}
|
||||
, &[_][]const u8{
|
||||
\\pub export fn foo(x: c_int) c_int {
|
||||
\\pub export fn foo() c_int {
|
||||
\\ var x: c_int = undefined;
|
||||
\\ return ~x;
|
||||
\\}
|
||||
});
|
||||
|
||||
cases.addC_both("bool not",
|
||||
\\int foo(int a, float b, void *c) {
|
||||
\\int foo() {
|
||||
\\ int a;
|
||||
\\ float b;
|
||||
\\ void *c;
|
||||
\\ return !(a == 0);
|
||||
\\ return !a;
|
||||
\\ return !b;
|
||||
\\ return !c;
|
||||
\\}
|
||||
, &[_][]const u8{
|
||||
\\pub export fn foo(a: c_int, b: f32, c: ?*c_void) c_int {
|
||||
\\pub export fn foo() c_int {
|
||||
\\ var a: c_int = undefined;
|
||||
\\ var b: f32 = undefined;
|
||||
\\ var c: ?*c_void = undefined;
|
||||
\\ return !(a == 0);
|
||||
\\ return !(a != 0);
|
||||
\\ return !(b != 0);
|
||||
@ -829,6 +847,15 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
||||
\\}
|
||||
});
|
||||
|
||||
if (builtin.os != builtin.Os.windows) {
|
||||
// sysv_abi not currently supported on windows
|
||||
cases.add_both("Macro qualified functions",
|
||||
\\void __attribute__((sysv_abi)) foo(void);
|
||||
, &[_][]const u8{
|
||||
\\pub extern fn foo() void;
|
||||
});
|
||||
}
|
||||
|
||||
/////////////// Cases that pass for only stage2 ////////////////
|
||||
|
||||
cases.add_2("Parameterless function prototypes",
|
||||
@ -1027,7 +1054,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
||||
\\pub const GLbitfield = c_uint;
|
||||
\\pub const PFNGLCLEARPROC = ?extern fn (GLbitfield) void;
|
||||
\\pub const OpenGLProc = ?extern fn () void;
|
||||
\\pub const struct_unnamed_1 = extern struct {
|
||||
\\const struct_unnamed_1 = extern struct {
|
||||
\\ Clear: PFNGLCLEARPROC,
|
||||
\\};
|
||||
\\pub const union_OpenGLProcs = extern union {
|
||||
@ -1088,7 +1115,8 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
||||
\\pub var a: c_long = @as(c_long, 2);
|
||||
\\pub var b: c_long = @as(c_long, 2);
|
||||
\\pub var c: c_int = 4;
|
||||
\\pub export fn foo(c_1: u8) void {
|
||||
\\pub export fn foo(_arg_c_1: u8) void {
|
||||
\\ var c_1 = _arg_c_1;
|
||||
\\ var a_2: c_int = undefined;
|
||||
\\ var b_3: u8 = @as(u8, 123);
|
||||
\\ b_3 = @as(u8, a_2);
|
||||
@ -1105,7 +1133,8 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
||||
\\ return 2, 4, 6;
|
||||
\\}
|
||||
, &[_][]const u8{
|
||||
\\pub export fn foo(c: u8) c_int {
|
||||
\\pub export fn foo(_arg_c: u8) c_int {
|
||||
\\ var c = _arg_c;
|
||||
\\ _ = 2;
|
||||
\\ _ = 4;
|
||||
\\ _ = 2;
|
||||
@ -1121,7 +1150,8 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
||||
\\ a = b = 2;
|
||||
\\}
|
||||
, &[_][]const u8{
|
||||
\\pub export fn foo(c: u8) c_int {
|
||||
\\pub export fn foo(_arg_c: u8) c_int {
|
||||
\\ var c = _arg_c;
|
||||
\\ var a: c_int = undefined;
|
||||
\\ var b: c_int = undefined;
|
||||
\\ a = blk: {
|
||||
@ -1142,7 +1172,8 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
||||
\\ }
|
||||
\\}
|
||||
, &[_][]const u8{
|
||||
\\pub export fn foo(c: u8) c_int {
|
||||
\\pub export fn foo(_arg_c: u8) c_int {
|
||||
\\ var c = _arg_c;
|
||||
\\ if (2 != 0) {
|
||||
\\ var a: c_int = 2;
|
||||
\\ }
|
||||
@ -1265,7 +1296,8 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
||||
\\ }
|
||||
\\}
|
||||
, &[_][]const u8{
|
||||
\\pub export fn switch_fn(i: c_int) c_int {
|
||||
\\pub export fn switch_fn(_arg_i: c_int) c_int {
|
||||
\\ var i = _arg_i;
|
||||
\\ var res: c_int = 0;
|
||||
\\ __switch: {
|
||||
\\ __case_2: {
|
||||
@ -1316,7 +1348,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
||||
cases.add_2("restrict -> noalias",
|
||||
\\void foo(void *restrict bar, void *restrict);
|
||||
, &[_][]const u8{
|
||||
\\pub extern fn foo(noalias bar: ?*c_void, noalias arg_1: ?*c_void) void;
|
||||
\\pub extern fn foo(noalias bar: ?*c_void, noalias ?*c_void) void;
|
||||
});
|
||||
|
||||
cases.add_2("assign",
|
||||
@ -1326,7 +1358,8 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
||||
\\ a = tmp;
|
||||
\\}
|
||||
, &[_][]const u8{
|
||||
\\pub export fn max(a: c_int) c_int {
|
||||
\\pub export fn max(_arg_a: c_int) c_int {
|
||||
\\ var a = _arg_a;
|
||||
\\ var tmp: c_int = undefined;
|
||||
\\ tmp = a;
|
||||
\\ a = tmp;
|
||||
@ -1339,7 +1372,8 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
||||
\\ c = b = a;
|
||||
\\}
|
||||
, &[_][]const u8{
|
||||
\\pub export fn max(a: c_int) void {
|
||||
\\pub export fn max(_arg_a: c_int) void {
|
||||
\\ var a = _arg_a;
|
||||
\\ var b: c_int = undefined;
|
||||
\\ var c: c_int = undefined;
|
||||
\\ c = blk: {
|
||||
@ -1369,7 +1403,8 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
||||
\\ return (int)a;
|
||||
\\}
|
||||
, &[_][]const u8{
|
||||
\\pub export fn float_to_int(a: f32) c_int {
|
||||
\\pub export fn float_to_int(_arg_a: f32) c_int {
|
||||
\\ var a = _arg_a;
|
||||
\\ return @floatToInt(c_int, a);
|
||||
\\}
|
||||
});
|
||||
@ -1434,19 +1469,6 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
||||
\\}
|
||||
});
|
||||
|
||||
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
|
||||
\\#include <stdint.h>
|
||||
\\uint32_t some_func(uint32_t a) {
|
||||
\\ uint32_t b = a >> 1;
|
||||
\\ return b;
|
||||
\\}
|
||||
, &[_][]const u8{
|
||||
\\pub export fn some_func(a: u32) u32 {
|
||||
\\ var b: u32 = a >> @as(u5, 1);
|
||||
\\ return b;
|
||||
\\}
|
||||
});
|
||||
|
||||
cases.add_2("logical and, logical or, on non-bool values, extra parens",
|
||||
\\enum Foo {
|
||||
\\ FooA,
|
||||
@ -1480,7 +1502,10 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
||||
\\ C,
|
||||
\\};
|
||||
\\pub const SomeTypedef = c_int;
|
||||
\\pub export fn and_or_non_bool(a: c_int, b: f32, c: ?*c_void) c_int {
|
||||
\\pub export fn and_or_non_bool(_arg_a: c_int, _arg_b: f32, _arg_c: ?*c_void) c_int {
|
||||
\\ var a = _arg_a;
|
||||
\\ var b = _arg_b;
|
||||
\\ var c = _arg_c;
|
||||
\\ var d: enum_Foo = @as(enum_Foo, FooA);
|
||||
\\ var e: c_int = @boolToInt(((a != 0) and (b != 0)));
|
||||
\\ var f: c_int = @boolToInt(((b != 0) and (c != null)));
|
||||
@ -1532,12 +1557,14 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
||||
\\ return (a & b) ^ (a | b);
|
||||
\\}
|
||||
, &[_][]const u8{
|
||||
\\pub export fn max(a: c_int, b: c_int) c_int {
|
||||
\\pub export fn max(_arg_a: c_int, _arg_b: c_int) c_int {
|
||||
\\ var a = _arg_a;
|
||||
\\ var b = _arg_b;
|
||||
\\ return ((a & b) ^ (a | b));
|
||||
\\}
|
||||
});
|
||||
|
||||
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-2
|
||||
cases.add_2("comparison operators (no if)", // TODO Come up with less contrived tests? Make sure to cover all these comparisons.
|
||||
\\int test_comparisons(int a, int b) {
|
||||
\\ int c = (a < b);
|
||||
\\ int d = (a > b);
|
||||
@ -1549,7 +1576,9 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
||||
\\ return i;
|
||||
\\}
|
||||
, &[_][]const u8{
|
||||
\\pub export fn test_comparisons(a: c_int, b: c_int) c_int {
|
||||
\\pub export fn test_comparisons(_arg_a: c_int, _arg_b: c_int) c_int {
|
||||
\\ var a = _arg_a;
|
||||
\\ var b = _arg_b;
|
||||
\\ var c: c_int = @boolToInt((a < b));
|
||||
\\ var d: c_int = @boolToInt((a > b));
|
||||
\\ var e: c_int = @boolToInt((a <= b));
|
||||
@ -1570,9 +1599,11 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
||||
\\ return a;
|
||||
\\}
|
||||
, &[_][]const u8{
|
||||
\\pub export fn max(a: c_int, b: c_int) c_int {
|
||||
\\ if ((a == b)) return a;
|
||||
\\ if ((a != b)) return b;
|
||||
\\pub export fn max(_arg_a: c_int, _arg_b: c_int) c_int {
|
||||
\\ var a = _arg_a;
|
||||
\\ var b = _arg_b;
|
||||
\\ if (a == b) return a;
|
||||
\\ if (a != b) return b;
|
||||
\\ return a;
|
||||
\\}
|
||||
});
|
||||
@ -1646,7 +1677,8 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
||||
\\}
|
||||
, &[_][]const u8{
|
||||
\\pub export var array: [100]c_int = .{0} ** 100;
|
||||
\\pub export fn foo(index: c_int) c_int {
|
||||
\\pub export fn foo(_arg_index: c_int) c_int {
|
||||
\\ var index = _arg_index;
|
||||
\\ return array[index];
|
||||
\\}
|
||||
,
|
||||
@ -1670,9 +1702,11 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
||||
\\ return a;
|
||||
\\}
|
||||
, &[_][]const u8{
|
||||
\\pub export fn max(a: c_int, b: c_int) c_int {
|
||||
\\ if (((a < b) or (a == b))) return b;
|
||||
\\ if (((a >= b) and (a == b))) return a;
|
||||
\\pub export fn max(_arg_a: c_int, _arg_b: c_int) c_int {
|
||||
\\ var a = _arg_a;
|
||||
\\ var b = _arg_b;
|
||||
\\ if ((a < b) or (a == b)) return b;
|
||||
\\ if ((a >= b) and (a == b)) return a;
|
||||
\\ return a;
|
||||
\\}
|
||||
});
|
||||
@ -1690,10 +1724,12 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
||||
\\ if (a < b) ; else ;
|
||||
\\}
|
||||
, &[_][]const u8{
|
||||
\\pub export fn max(a: c_int, b: c_int) c_int {
|
||||
\\ if ((a < b)) return b;
|
||||
\\ if ((a < b)) return b else return a;
|
||||
\\ if ((a < b)) {} else {}
|
||||
\\pub export fn max(_arg_a: c_int, _arg_b: c_int) c_int {
|
||||
\\ var a = _arg_a;
|
||||
\\ var b = _arg_b;
|
||||
\\ if (a < b) return b;
|
||||
\\ if (a < b) return b else return a;
|
||||
\\ if (a < b) {} else {}
|
||||
\\}
|
||||
});
|
||||
|
||||
@ -1715,7 +1751,11 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
||||
\\ B,
|
||||
\\ C,
|
||||
\\};
|
||||
\\pub export fn if_none_bool(a: c_int, b: f32, c: ?*c_void, d: enum_SomeEnum) c_int {
|
||||
\\pub export fn if_none_bool(_arg_a: c_int, _arg_b: f32, _arg_c: ?*c_void, _arg_d: enum_SomeEnum) c_int {
|
||||
\\ var a = _arg_a;
|
||||
\\ var b = _arg_b;
|
||||
\\ var c = _arg_c;
|
||||
\\ var d = _arg_d;
|
||||
\\ if (a != 0) return 0;
|
||||
\\ if (b != 0) return 1;
|
||||
\\ if (c != null) return 2;
|
||||
@ -1741,8 +1781,9 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
||||
\\ return a < 0 ? -a : a;
|
||||
\\}
|
||||
, &[_][]const u8{
|
||||
\\pub export fn abs(a: c_int) c_int {
|
||||
\\ return if ((a < 0)) -a else a;
|
||||
\\pub export fn abs(_arg_a: c_int) c_int {
|
||||
\\ var a = _arg_a;
|
||||
\\ return if (a < 0) -a else a;
|
||||
\\}
|
||||
});
|
||||
|
||||
@ -1756,11 +1797,13 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
||||
\\ return a;
|
||||
\\}
|
||||
, &[_][]const u8{
|
||||
\\pub export fn foo1(a: c_uint) c_uint {
|
||||
\\pub export fn foo1(_arg_a: c_uint) c_uint {
|
||||
\\ var a = _arg_a;
|
||||
\\ a +%= 1;
|
||||
\\ return a;
|
||||
\\}
|
||||
\\pub export fn foo2(a: c_int) c_int {
|
||||
\\pub export fn foo2(_arg_a: c_int) c_int {
|
||||
\\ var a = _arg_a;
|
||||
\\ a += 1;
|
||||
\\ return a;
|
||||
\\}
|
||||
@ -1848,10 +1891,11 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
||||
\\ }
|
||||
\\ return i;
|
||||
\\}
|
||||
, &[_][]const u8{// TODO function arguments should be copied
|
||||
\\pub export fn log2(a: c_uint) c_int {
|
||||
, &[_][]const u8{
|
||||
\\pub export fn log2(_arg_a: c_uint) c_int {
|
||||
\\ var a = _arg_a;
|
||||
\\ var i: c_int = 0;
|
||||
\\ while ((a > @as(c_uint, 0))) {
|
||||
\\ while (a > @as(c_uint, 0)) {
|
||||
\\ a >>= @as(@import("std").math.Log2Int(c_int), 1);
|
||||
\\ }
|
||||
\\ return i;
|
||||
@ -1868,9 +1912,10 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
||||
\\ return i;
|
||||
\\}
|
||||
, &[_][]const u8{
|
||||
\\pub export fn log2(a: u32) c_int {
|
||||
\\pub export fn log2(_arg_a: u32) c_int {
|
||||
\\ var a = _arg_a;
|
||||
\\ var i: c_int = 0;
|
||||
\\ while ((a > @as(c_uint, 0))) {
|
||||
\\ while (a > @as(c_uint, 0)) {
|
||||
\\ a >>= @as(@import("std").math.Log2Int(c_int), 1);
|
||||
\\ }
|
||||
\\ return i;
|
||||
@ -2076,7 +2121,8 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
||||
\\pub extern fn fn_char(x: u8) void;
|
||||
\\pub extern fn fn_bool(x: bool) void;
|
||||
\\pub extern fn fn_ptr(x: ?*c_void) void;
|
||||
\\pub export fn call(q: c_int) void {
|
||||
\\pub export fn call(_arg_q: c_int) void {
|
||||
\\ var q = _arg_q;
|
||||
\\ fn_int(@floatToInt(c_int, 3));
|
||||
\\ fn_int(@floatToInt(c_int, 3));
|
||||
\\ fn_int(@floatToInt(c_int, 3));
|
||||
@ -2096,6 +2142,21 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
||||
\\}
|
||||
});
|
||||
|
||||
cases.add_2("function call",
|
||||
\\static void bar(void) { }
|
||||
\\void foo(int *(baz)(void)) {
|
||||
\\ bar();
|
||||
\\ baz();
|
||||
\\}
|
||||
, &[_][]const u8{
|
||||
\\pub fn bar() void {}
|
||||
\\pub export fn foo(_arg_baz: ?extern fn () [*c]c_int) void {
|
||||
\\ var baz = _arg_baz;
|
||||
\\ bar();
|
||||
\\ _ = baz.?();
|
||||
\\}
|
||||
});
|
||||
|
||||
/////////////// Cases for only stage1 which are TODO items for stage2 ////////////////
|
||||
|
||||
cases.add("macro defines string literal with hex",
|
||||
@ -2122,15 +2183,6 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
||||
\\pub const FOO_CHAR = 63;
|
||||
});
|
||||
|
||||
if (builtin.os != builtin.Os.windows) {
|
||||
// sysv_abi not currently supported on windows
|
||||
cases.add("Macro qualified functions",
|
||||
\\void __attribute__((sysv_abi)) foo(void);
|
||||
, &[_][]const u8{
|
||||
\\pub extern fn foo() void;
|
||||
});
|
||||
}
|
||||
|
||||
/////////////// Cases for only stage1 because stage2 behavior is better ////////////////
|
||||
cases.addC("Parameterless function prototypes",
|
||||
\\void foo() {}
|
||||
@ -3045,4 +3097,18 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
||||
\\ fn_ptr(@intToPtr(?*c_void, 42));
|
||||
\\}
|
||||
});
|
||||
|
||||
cases.addC("function call",
|
||||
\\static void bar(void) { }
|
||||
\\void foo(int *(baz)(void)) {
|
||||
\\ bar();
|
||||
\\ baz();
|
||||
\\}
|
||||
, &[_][]const u8{
|
||||
\\pub fn bar() void {}
|
||||
\\pub export fn foo(baz: ?extern fn () [*c]c_int) void {
|
||||
\\ bar();
|
||||
\\ _ = baz.?();
|
||||
\\}
|
||||
});
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user