authorgravatar for jhc@dismail.deJimmi Holst Christensen <jhc@dismail.de> 2019-05-11 18:49:23+02:00
committergravatar for jhc@dismail.deJimmi Holst Christensen <jhc@dismail.de> 2019-05-11 18:49:23+02:00
logb2a196e01dce9856eb43ae92a43d1a5b260d11d4
treefe46421244952509fc93eeac237c0965ca3eddbc
parentc051904903e65f6bd2cb9d71f52688ce9d17d52d
parent10e9d47b499752f5c40e8ded1bf50385d84912ff

Merge branch 'master' of github.com:ziglang/zig


4 files changed, 142 insertions(+), 64 deletions(-)

src-self-hosted/translate_c.zig+74-38
......@@ -254,11 +254,20 @@ fn visitFnDecl(c: *Context, fn_decl: *const ZigClangFunctionDecl) Error!void {
254254 const fn_qt = ZigClangFunctionDecl_getType(fn_decl);
255255 const fn_type = ZigClangQualType_getTypePtr(fn_qt);
256256 var scope = &c.global_scope.base;
257 const has_body = ZigClangFunctionDecl_hasBody(fn_decl);
258 const storage_class = ZigClangFunctionDecl_getStorageClass(fn_decl);
257259 const decl_ctx = FnDeclContext{
258260 .fn_name = fn_name,
259 .has_body = ZigClangFunctionDecl_hasBody(fn_decl),
260 .storage_class = ZigClangFunctionDecl_getStorageClass(fn_decl),
261 .has_body = has_body,
262 .storage_class = storage_class,
261263 .scope = &scope,
264 .is_export = switch (storage_class) {
265 .None => has_body,
266 .Extern, .Static => false,
267 .PrivateExtern => return failDecl(c, fn_decl_loc, fn_name, "unsupported storage class: private extern"),
268 .Auto => unreachable, // Not legal on functions
269 .Register => unreachable, // Not legal on functions
270 },
262271 };
263272 const proto_node = switch (ZigClangType_getTypeClass(fn_type)) {
264273 .FunctionProto => blk: {
......@@ -270,7 +279,15 @@ fn visitFnDecl(c: *Context, fn_decl: *const ZigClangFunctionDecl) Error!void {
270279 error.OutOfMemory => return error.OutOfMemory,
271280 };
272281 },
273 .FunctionNoProto => return failDecl(c, fn_decl_loc, fn_name, "TODO support functions with no prototype"),
282 .FunctionNoProto => blk: {
283 const fn_no_proto_type = @ptrCast(*const ZigClangFunctionType, fn_type);
284 break :blk transFnNoProto(rp, fn_no_proto_type, fn_decl_loc, decl_ctx) catch |err| switch (err) {
285 error.UnsupportedType => {
286 return failDecl(c, fn_decl_loc, fn_name, "unable to resolve prototype of function");
287 },
288 error.OutOfMemory => return error.OutOfMemory,
289 };
290 },
274291 else => unreachable,
275292 };
276293
......@@ -432,8 +449,22 @@ const FnDeclContext = struct {
432449 has_body: bool,
433450 storage_class: ZigClangStorageClass,
434451 scope: **Scope,
452 is_export: bool,
435453};
436454
455fn transCC(
456 rp: RestorePoint,
457 fn_ty: *const ZigClangFunctionType,
458 source_loc: ZigClangSourceLocation,
459) !CallingConvention {
460 const clang_cc = ZigClangFunctionType_getCallConv(fn_ty);
461 switch (clang_cc) {
462 .C => return CallingConvention.C,
463 .X86StdCall => return CallingConvention.Stdcall,
464 else => return revertAndWarn(rp, error.UnsupportedType, source_loc, "unsupported calling convention: {}", @tagName(clang_cc)),
465 }
466}
467
437468fn transFnProto(
438469 rp: RestorePoint,
439470 fn_proto_ty: *const ZigClangFunctionProtoType,
......@@ -441,52 +472,44 @@ fn transFnProto(
441472 fn_decl_context: ?FnDeclContext,
442473) !*ast.Node.FnProto {
443474 const fn_ty = @ptrCast(*const ZigClangFunctionType, fn_proto_ty);
444 const cc = switch (ZigClangFunctionType_getCallConv(fn_ty)) {
445 .C => CallingConvention.C,
446 .X86StdCall => CallingConvention.Stdcall,
447 .X86FastCall => return revertAndWarn(rp, error.UnsupportedType, source_loc, "unsupported calling convention: x86 fastcall"),
448 .X86ThisCall => return revertAndWarn(rp, error.UnsupportedType, source_loc, "unsupported calling convention: x86 thiscall"),
449 .X86VectorCall => return revertAndWarn(rp, error.UnsupportedType, source_loc, "unsupported calling convention: x86 vectorcall"),
450 .X86Pascal => return revertAndWarn(rp, error.UnsupportedType, source_loc, "unsupported calling convention: x86 pascal"),
451 .Win64 => return revertAndWarn(rp, error.UnsupportedType, source_loc, "unsupported calling convention: win64"),
452 .X86_64SysV => return revertAndWarn(rp, error.UnsupportedType, source_loc, "unsupported calling convention: x86 64sysv"),
453 .X86RegCall => return revertAndWarn(rp, error.UnsupportedType, source_loc, "unsupported calling convention: x86 reg"),
454 .AAPCS => return revertAndWarn(rp, error.UnsupportedType, source_loc, "unsupported calling convention: aapcs"),
455 .AAPCS_VFP => return revertAndWarn(rp, error.UnsupportedType, source_loc, "unsupported calling convention: aapcs-vfp"),
456 .IntelOclBicc => return revertAndWarn(rp, error.UnsupportedType, source_loc, "unsupported calling convention: intel_ocl_bicc"),
457 .SpirFunction => return revertAndWarn(rp, error.UnsupportedType, source_loc, "unsupported calling convention: SPIR function"),
458 .OpenCLKernel => return revertAndWarn(rp, error.UnsupportedType, source_loc, "unsupported calling convention: OpenCLKernel"),
459 .Swift => return revertAndWarn(rp, error.UnsupportedType, source_loc, "unsupported calling convention: Swift"),
460 .PreserveMost => return revertAndWarn(rp, error.UnsupportedType, source_loc, "unsupported calling convention: PreserveMost"),
461 .PreserveAll => return revertAndWarn(rp, error.UnsupportedType, source_loc, "unsupported calling convention: PreserveAll"),
462 .AArch64VectorCall => return revertAndWarn(rp, error.UnsupportedType, source_loc, "unsupported calling convention: AArch64VectorCall"),
463 };
464
475 const cc = try transCC(rp, fn_ty, source_loc);
465476 const is_var_args = ZigClangFunctionProtoType_isVariadic(fn_proto_ty);
466477 const param_count: usize = ZigClangFunctionProtoType_getNumParams(fn_proto_ty);
467478 var i: usize = 0;
468479 while (i < param_count) : (i += 1) {
469480 return revertAndWarn(rp, error.UnsupportedType, source_loc, "TODO: implement parameters for FunctionProto in transType");
470481 }
482
483 return finishTransFnProto(rp, fn_ty, source_loc, fn_decl_context, is_var_args, cc);
484}
485
486fn transFnNoProto(
487 rp: RestorePoint,
488 fn_ty: *const ZigClangFunctionType,
489 source_loc: ZigClangSourceLocation,
490 fn_decl_context: ?FnDeclContext,
491) !*ast.Node.FnProto {
492 const cc = try transCC(rp, fn_ty, source_loc);
493 const is_var_args = if (fn_decl_context) |ctx| !ctx.is_export else true;
494 return finishTransFnProto(rp, fn_ty, source_loc, fn_decl_context, is_var_args, cc);
495}
496
497fn finishTransFnProto(
498 rp: RestorePoint,
499 fn_ty: *const ZigClangFunctionType,
500 source_loc: ZigClangSourceLocation,
501 fn_decl_context: ?FnDeclContext,
502 is_var_args: bool,
503 cc: CallingConvention,
504) !*ast.Node.FnProto {
505 const is_export = if (fn_decl_context) |ctx| ctx.is_export else false;
506
471507 // TODO check for always_inline attribute
472508 // TODO check for align attribute
473509
474510 // pub extern fn name(...) T
475511 const pub_tok = try appendToken(rp.c, .Keyword_pub, "pub");
476512 const cc_tok = if (cc == .Stdcall) try appendToken(rp.c, .Keyword_stdcallcc, "stdcallcc") else null;
477 const is_export = exp: {
478 const decl_ctx = fn_decl_context orelse break :exp false;
479 break :exp switch (decl_ctx.storage_class) {
480 .None => switch (rp.c.mode) {
481 .import => false,
482 .translate => decl_ctx.has_body,
483 },
484 .Extern, .Static => false,
485 .PrivateExtern => return revertAndWarn(rp, error.UnsupportedType, source_loc, "unsupported storage class: private extern"),
486 .Auto => unreachable, // Not legal on functions
487 .Register => unreachable, // Not legal on functions
488 };
489 };
490513 const extern_export_inline_tok = if (is_export)
491514 try appendToken(rp.c, .Keyword_export, "export")
492515 else if (cc == .C)
......@@ -527,7 +550,7 @@ fn transFnProto(
527550 .name_token = name_tok,
528551 .params = ast.Node.FnProto.ParamList.init(rp.c.a()),
529552 .return_type = ast.Node.FnProto.ReturnType{ .Explicit = return_type_node },
530 .var_args_token = var_args_tok,
553 .var_args_token = null, // TODO this field is broken in the AST data model
531554 .extern_export_inline_token = extern_export_inline_tok,
532555 .cc_token = cc_tok,
533556 .async_attr = null,
......@@ -536,6 +559,19 @@ fn transFnProto(
536559 .align_expr = null,
537560 .section_expr = null,
538561 };
562 if (is_var_args) {
563 const var_arg_node = try rp.c.a().create(ast.Node.ParamDecl);
564 var_arg_node.* = ast.Node.ParamDecl{
565 .base = ast.Node{ .id = ast.Node.Id.ParamDecl },
566 .doc_comments = null,
567 .comptime_token = null,
568 .noalias_token = null,
569 .name_token = null,
570 .type_node = undefined,
571 .var_args_token = var_args_tok,
572 };
573 try fn_proto.params.push(&var_arg_node.base);
574 }
539575 return fn_proto;
540576}
541577
std/os/linux.zig+27-13
......@@ -959,10 +959,13 @@ pub fn waitpid(pid: i32, status: *i32, options: i32) usize {
959959 return syscall4(SYS_wait4, @bitCast(usize, isize(pid)), @ptrToInt(status), @bitCast(usize, isize(options)), 0);
960960}
961961
962var vdso_clock_gettime = @ptrCast(?*const c_void, init_vdso_clock_gettime);
963
962964pub fn clock_gettime(clk_id: i32, tp: *timespec) usize {
963965 if (VDSO_CGT_SYM.len != 0) {
964 const f = @atomicLoad(@typeOf(init_vdso_clock_gettime), &vdso_clock_gettime, builtin.AtomicOrder.Unordered);
965 if (@ptrToInt(f) != 0) {
966 const ptr = @atomicLoad(?*const c_void, &vdso_clock_gettime, .Unordered);
967 if (ptr) |fn_ptr| {
968 const f = @ptrCast(@typeOf(clock_gettime), fn_ptr);
966969 const rc = f(clk_id, tp);
967970 switch (rc) {
968971 0, @bitCast(usize, isize(-EINVAL)) => return rc,
......@@ -972,13 +975,18 @@ pub fn clock_gettime(clk_id: i32, tp: *timespec) usize {
972975 }
973976 return syscall2(SYS_clock_gettime, @bitCast(usize, isize(clk_id)), @ptrToInt(tp));
974977}
975var vdso_clock_gettime = init_vdso_clock_gettime;
978
976979extern fn init_vdso_clock_gettime(clk: i32, ts: *timespec) usize {
977 const addr = vdso.lookup(VDSO_CGT_VER, VDSO_CGT_SYM);
978 var f = @intToPtr(@typeOf(init_vdso_clock_gettime), addr);
979 _ = @cmpxchgStrong(@typeOf(init_vdso_clock_gettime), &vdso_clock_gettime, init_vdso_clock_gettime, f, builtin.AtomicOrder.Monotonic, builtin.AtomicOrder.Monotonic);
980 if (@ptrToInt(f) == 0) return @bitCast(usize, isize(-ENOSYS));
981 return f(clk, ts);
980 const ptr = @intToPtr(?*const c_void, vdso.lookup(VDSO_CGT_VER, VDSO_CGT_SYM));
981 // Note that we may not have a VDSO at all, update the stub address anyway
982 // so that clock_gettime will fall back on the good old (and slow) syscall
983 _ = @cmpxchgStrong(?*const c_void, &vdso_clock_gettime, &init_vdso_clock_gettime, ptr, .Monotonic, .Monotonic);
984 // Call into the VDSO if available
985 if (ptr) |fn_ptr| {
986 const f = @ptrCast(@typeOf(clock_gettime), fn_ptr);
987 return f(clk, ts);
988 }
989 return @bitCast(usize, isize(-ENOSYS));
982990}
983991
984992pub fn clock_getres(clk_id: i32, tp: *timespec) usize {
......@@ -1104,8 +1112,8 @@ pub fn sigaction(sig: u6, noalias act: *const Sigaction, noalias oact: ?*Sigacti
11041112
11051113const NSIG = 65;
11061114const sigset_t = [128 / @sizeOf(usize)]usize;
1107const all_mask = []u32{0xffffffff, 0xffffffff};
1108const app_mask = []u32{0xfffffffc, 0x7fffffff};
1115const all_mask = []u32{ 0xffffffff, 0xffffffff };
1116const app_mask = []u32{ 0xfffffffc, 0x7fffffff };
11091117
11101118const k_sigaction = extern struct {
11111119 handler: extern fn (i32) void,
......@@ -1403,9 +1411,15 @@ pub const epoll_data = extern union {
14031411// On x86_64 the structure is packed so that it matches the definition of its
14041412// 32bit counterpart
14051413pub const epoll_event = if (builtin.arch != .x86_64)
1406 extern struct { events: u32, data: epoll_data }
1407 else
1408 packed struct { events: u32, data: epoll_data };
1414 extern struct {
1415 events: u32,
1416 data: epoll_data,
1417 }
1418else
1419 packed struct {
1420 events: u32,
1421 data: epoll_data,
1422 };
14091423
14101424pub fn epoll_create() usize {
14111425 return epoll_create1(0);
test/tests.zig+9-1
......@@ -1076,6 +1076,14 @@ pub const TranslateCContext = struct {
10761076 }
10771077
10781078 pub fn add_both(self: *TranslateCContext, name: []const u8, source: []const u8, expected_lines: ...) void {
1079 for ([]bool{ false, true }) |stage2| {
1080 const tc = self.create(false, "source.h", name, source, expected_lines);
1081 tc.stage2 = stage2;
1082 self.addCase(tc);
1083 }
1084 }
1085
1086 pub fn addC_both(self: *TranslateCContext, name: []const u8, source: []const u8, expected_lines: ...) void {
10791087 for ([]bool{ false, true }) |stage2| {
10801088 const tc = self.create(false, "source.c", name, source, expected_lines);
10811089 tc.stage2 = stage2;
......@@ -1084,7 +1092,7 @@ pub const TranslateCContext = struct {
10841092 }
10851093
10861094 pub fn add_2(self: *TranslateCContext, name: []const u8, source: []const u8, expected_lines: ...) void {
1087 const tc = self.create(false, "source.c", name, source, expected_lines);
1095 const tc = self.create(false, "source.h", name, source, expected_lines);
10881096 tc.stage2 = true;
10891097 self.addCase(tc);
10901098 }
test/translate_c.zig+32-12
......@@ -1,6 +1,13 @@
11const tests = @import("tests.zig");
22const builtin = @import("builtin");
33
4// add_both - test for stage1 and stage2, in #include mode
5// add - test stage1 only, in #include mode
6// add_2 - test stage2 only, in #include mode
7// addC_both - test for stage1 and stage2, in -c mode
8// addC - test stage1 only, in -c mode
9// addC_2 - test stage2 only, in -c mode
10
411pub fn addCases(cases: *tests.TranslateCContext) void {
512 /////////////// Cases that pass for both stage1/stage2 ////////////////
613 cases.add_both("simple function prototypes",
......@@ -11,25 +18,29 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
1118 \\pub extern fn bar() c_int;
1219 );
1320
14 cases.add_both("simple function definition",
15 \\void foo(void) {};
21 /////////////// Cases that pass for only stage2 ////////////////
22 cases.add_2("Parameterless function prototypes",
23 \\void a() {}
24 \\void b(void) {}
25 \\void c();
26 \\void d(void);
1627 ,
17 \\pub export fn foo() void {}
28 \\pub export fn a() void {}
29 \\pub export fn b() void {}
30 \\pub extern fn c(...) void;
31 \\pub extern fn d() void;
1832 );
1933
20 /////////////// Cases that pass for only stage2 ////////////////
21 // (none)
22
23 /////////////// Cases that pass for only stage1 ////////////////
24
25 cases.addC("Parameterless function prototypes",
26 \\void foo() {}
27 \\void bar(void) {}
34 cases.add_2("simple function definition",
35 \\void foo(void) {}
36 \\static void bar(void) {}
2837 ,
2938 \\pub export fn foo() void {}
30 \\pub export fn bar() void {}
39 \\pub extern fn bar() void {}
3140 );
3241
42 /////////////// Cases for only stage1 which are TODO items for stage2 ////////////////
43
3344 cases.add("macro with left shift",
3445 \\#define REDISMODULE_READ (1<<0)
3546 ,
......@@ -1681,4 +1692,13 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
16811692 \\ }
16821693 \\}
16831694 );
1695
1696 /////////////// Cases for only stage1 because stage2 behavior is better ////////////////
1697 cases.addC("Parameterless function prototypes",
1698 \\void foo() {}
1699 \\void bar(void) {}
1700 ,
1701 \\pub export fn foo() void {}
1702 \\pub export fn bar() void {}
1703 );
16841704}