| author | |
| committer | |
| log | e03056d45a864c8176cdd897d771457005ead592 |
| tree | 2831c341924bf2b9c5c07825cecb96e1a687fa67 |
| parent | 6c003e84338bc1f8ceaf7ca869cb343b31be9fc7 |
- Annotate function pointers with calling convention.
- Support `incoming_stack_alignment`.
- Fix noreturn attribute position.6 files changed, 239 insertions(+), 149 deletions(-)
lib/zig.h+6-13| ... | ... | @@ -199,10 +199,8 @@ |
| 199 | 199 | #endif |
| 200 | 200 | |
| 201 | 201 | #if defined(zig_msvc) |
| 202 | #define zig_const_arr | |
| 203 | 202 | #define zig_callconv(c) __##c |
| 204 | 203 | #else |
| 205 | #define zig_const_arr static const | |
| 206 | 204 | #define zig_callconv(c) __attribute__((c)) |
| 207 | 205 | #endif |
| 208 | 206 | |
| ... | ... | @@ -5841,11 +5839,6 @@ typedef zig_u128 zig_f80; |
| 5841 | 5839 | #define zig_init_special_f80(sign, name, arg, repr) repr |
| 5842 | 5840 | #endif |
| 5843 | 5841 | |
| 5844 | #if defined(zig_gcc) && defined(zig_x86) | |
| 5845 | #define zig_f128_has_miscompilations 1 | |
| 5846 | #else | |
| 5847 | #define zig_f128_has_miscompilations 0 | |
| 5848 | #endif | |
| 5849 | 5842 | #define zig_has_f128 1 |
| 5850 | 5843 | #define zig_libc_name_f128(name) name##f128 |
| 5851 | 5844 | #define zig_init_special_f128(sign, name, arg, repr) zig_make_special_f128(sign, name, arg, repr) |
| ... | ... | @@ -5859,22 +5852,22 @@ typedef struct { uint64_t hi, lo; } zig_f128; |
| 5859 | 5852 | #define zig_init_repr_f128(hi, lo) { .h##i = hi, .l##o = lo } |
| 5860 | 5853 | #define zig_lo_repr_f128(arg) (arg).lo |
| 5861 | 5854 | #define zig_hi_repr_f128(arg) (arg).hi |
| 5862 | #elif !zig_f128_has_miscompilations && FLT_MANT_DIG == 113 | |
| 5855 | #elif FLT_MANT_DIG == 113 | |
| 5863 | 5856 | typedef float zig_f128; |
| 5864 | 5857 | #define zig_make_f128(fp, repr) fp##f |
| 5865 | #elif !zig_f128_has_miscompilations && DBL_MANT_DIG == 113 | |
| 5858 | #elif DBL_MANT_DIG == 113 | |
| 5866 | 5859 | typedef double zig_f128; |
| 5867 | 5860 | #define zig_make_f128(fp, repr) fp |
| 5868 | #elif !zig_f128_has_miscompilations && LDBL_MANT_DIG == 113 | |
| 5861 | #elif LDBL_MANT_DIG == 113 | |
| 5869 | 5862 | typedef long double zig_f128; |
| 5870 | 5863 | #define zig_make_f128(fp, repr) fp##l |
| 5871 | #elif !zig_f128_has_miscompilations && FLT128_MANT_DIG == 113 | |
| 5864 | #elif FLT128_MANT_DIG == 113 | |
| 5872 | 5865 | typedef _Float128 zig_f128; |
| 5873 | 5866 | #define zig_make_f128(fp, repr) fp##f128 |
| 5874 | #elif !zig_f128_has_miscompilations && FLT64X_MANT_DIG == 113 | |
| 5867 | #elif FLT64X_MANT_DIG == 113 | |
| 5875 | 5868 | typedef _Float64x zig_f128; |
| 5876 | 5869 | #define zig_make_f128(fp, repr) fp##f64x |
| 5877 | #elif !zig_f128_has_miscompilations && defined(__SIZEOF_FLOAT128__) | |
| 5870 | #elif defined(__SIZEOF_FLOAT128__) | |
| 5878 | 5871 | typedef __float128 zig_f128; |
| 5879 | 5872 | #define zig_make_f128(fp, repr) fp##q |
| 5880 | 5873 | #undef zig_make_special_f128 |
src/Zcu.zig+6-24| ... | ... | @@ -4617,44 +4617,26 @@ pub fn callconvSupported(zcu: *Zcu, cc: std.lang.CallingConvention) union(enum) |
| 4617 | 4617 | .m68k_rtd, |
| 4618 | 4618 | .m68k_interrupt, |
| 4619 | 4619 | .msp430_interrupt, |
| 4620 | => |opts| opts.incoming_stack_alignment == null, | |
| 4621 | ||
| 4622 | 4620 | .arm_aapcs_vfp, |
| 4623 | => |opts| opts.incoming_stack_alignment == null, | |
| 4624 | ||
| 4625 | 4621 | .arc_interrupt, |
| 4626 | => |opts| opts.incoming_stack_alignment == null, | |
| 4627 | ||
| 4628 | 4622 | .arm_interrupt, |
| 4629 | => |opts| opts.incoming_stack_alignment == null, | |
| 4630 | ||
| 4631 | 4623 | .microblaze_interrupt, |
| 4632 | => |opts| opts.incoming_stack_alignment == null, | |
| 4633 | ||
| 4634 | 4624 | .mips_interrupt, |
| 4635 | 4625 | .mips64_interrupt, |
| 4636 | => |opts| opts.incoming_stack_alignment == null, | |
| 4637 | ||
| 4638 | 4626 | .riscv32_interrupt, |
| 4639 | 4627 | .riscv64_interrupt, |
| 4640 | => |opts| opts.incoming_stack_alignment == null, | |
| 4641 | ||
| 4642 | 4628 | .sh_interrupt, |
| 4643 | => |opts| opts.incoming_stack_alignment == null, | |
| 4629 | .avr_interrupt, | |
| 4630 | .avr_signal, | |
| 4631 | .ez80_tiflags, | |
| 4632 | .naked, | |
| 4633 | => true, // incoming stack alignment supported | |
| 4644 | 4634 | |
| 4645 | 4635 | .x86_sysv, |
| 4646 | 4636 | .x86_win, |
| 4647 | 4637 | .x86_mingw, |
| 4648 | 4638 | .x86_stdcall, |
| 4649 | => |opts| opts.incoming_stack_alignment == null and opts.register_params == 0, | |
| 4650 | ||
| 4651 | .avr_interrupt, | |
| 4652 | .avr_signal, | |
| 4653 | => true, | |
| 4654 | ||
| 4655 | .ez80_tiflags => true, | |
| 4656 | ||
| 4657 | .naked => true, | |
| 4639 | => |opts| opts.register_params == 0, // incoming stack alignment supported | |
| 4658 | 4640 | |
| 4659 | 4641 | else => false, |
| 4660 | 4642 | }; |
src/codegen/c.zig+41-101| ... | ... | @@ -1750,8 +1750,6 @@ pub const DeclGen = struct { |
| 1750 | 1750 | try w.writeAll("zig_no_builtin "); |
| 1751 | 1751 | } |
| 1752 | 1752 | |
| 1753 | if (fn_info.return_type == .noreturn_type) try w.writeAll("zig_noreturn "); | |
| 1754 | ||
| 1755 | 1753 | // While incomplete types are usually an acceptable substitute for "void", this is not true |
| 1756 | 1754 | // in function return types, where "void" is the only incomplete type permitted. |
| 1757 | 1755 | const actual_return_type: Type = .fromInterned(fn_info.return_type); |
| ... | ... | @@ -1763,8 +1761,9 @@ pub const DeclGen = struct { |
| 1763 | 1761 | |
| 1764 | 1762 | const ret_cty: CType = try .lower(effective_return_type, &dg.ctype_deps, dg.arena, zcu); |
| 1765 | 1763 | try w.print("{f}", .{ret_cty.fmtDeclaratorPrefix(zcu)}); |
| 1766 | if (toCallingConvention(fn_info.cc, zcu)) |call_conv| { | |
| 1767 | try w.print("zig_callconv({s}) ", .{call_conv}); | |
| 1764 | switch (CType.CallingConvention.fromLang(fn_info.cc, zcu.getTarget())) { | |
| 1765 | .c => {}, | |
| 1766 | else => |cc| try w.print("zig_callconv({t}) ", .{cc}), | |
| 1768 | 1767 | } |
| 1769 | 1768 | switch (name) { |
| 1770 | 1769 | .nav => |nav| try renderNavName(w, nav, ip), |
| ... | ... | @@ -2221,6 +2220,7 @@ pub fn genLazyCallModifierFn( |
| 2221 | 2220 | |
| 2222 | 2221 | const fn_val = zcu.navValue(fn_nav); |
| 2223 | 2222 | |
| 2223 | if (fn_val.typeOf(zcu).fnReturnType(zcu).isNoReturn(zcu)) try w.writeAll("zig_noreturn "); | |
| 2224 | 2224 | try w.print("static zig_{t} ", .{kind}); |
| 2225 | 2225 | try dg.renderFunctionSignature(w, fn_val, .none, .definition, switch (kind) { |
| 2226 | 2226 | .never_tail => .{ .nav_never_tail = fn_nav }, |
| ... | ... | @@ -2326,8 +2326,10 @@ pub fn genFunc(f: *Function, fwd_decl_writer: *Writer, header_writer: *Writer) E |
| 2326 | 2326 | const gpa = f.dg.gpa; |
| 2327 | 2327 | const nav_index = f.dg.owner_nav.unwrap().?; |
| 2328 | 2328 | const nav_val = zcu.navValue(nav_index); |
| 2329 | const fn_info = zcu.typeToFunc(nav_val.typeOf(zcu)).?; | |
| 2329 | 2330 | const nav = ip.getNav(nav_index); |
| 2330 | 2331 | |
| 2332 | if (Type.fromInterned(fn_info.return_type).isNoReturn(zcu)) try fwd_decl_writer.writeAll("zig_noreturn "); | |
| 2331 | 2333 | try fwd_decl_writer.writeAll("static "); |
| 2332 | 2334 | try f.dg.renderFunctionSignature( |
| 2333 | 2335 | fwd_decl_writer, |
| ... | ... | @@ -2354,6 +2356,35 @@ pub fn genFunc(f: *Function, fwd_decl_writer: *Writer, header_writer: *Writer) E |
| 2354 | 2356 | |
| 2355 | 2357 | const main_body = f.air.getMainBody(); |
| 2356 | 2358 | f.indent(); |
| 2359 | if (switch (fn_info.cc) { | |
| 2360 | inline else => |pl| switch (@TypeOf(pl)) { | |
| 2361 | void, | |
| 2362 | std.lang.CallingConvention.SpirvKernelOptions, | |
| 2363 | std.lang.CallingConvention.SpirvFragmentOptions, | |
| 2364 | std.lang.CallingConvention.SpirvMeshOptions, | |
| 2365 | => null, | |
| 2366 | std.lang.CallingConvention.ArcInterruptOptions, | |
| 2367 | std.lang.CallingConvention.ArmInterruptOptions, | |
| 2368 | std.lang.CallingConvention.RiscvInterruptOptions, | |
| 2369 | std.lang.CallingConvention.ShInterruptOptions, | |
| 2370 | std.lang.CallingConvention.MicroblazeInterruptOptions, | |
| 2371 | std.lang.CallingConvention.MipsInterruptOptions, | |
| 2372 | std.lang.CallingConvention.CommonOptions, | |
| 2373 | std.lang.CallingConvention.X86RegparmOptions, | |
| 2374 | => pl.incoming_stack_alignment, | |
| 2375 | else => @compileError(@tagName(pl)), | |
| 2376 | }, | |
| 2377 | }) |incoming_stack_alignment| realign_stack: { | |
| 2378 | const normal_stack_align = zcu.getTarget().stackAlignment(); | |
| 2379 | if (incoming_stack_alignment >= normal_stack_align) break :realign_stack; | |
| 2380 | try header_writer.print("char zig_align({d}) zig_realign_stack;\n ", .{ | |
| 2381 | normal_stack_align << 1, | |
| 2382 | }); | |
| 2383 | try f.code.writer.writeAll( | |
| 2384 | \\__asm volatile("" :: [zig_realign_stack] "m" (zig_realign_stack)); | |
| 2385 | ); | |
| 2386 | try f.newline(); | |
| 2387 | } | |
| 2357 | 2388 | try genBodyResolveState(f, undefined, &.{}, main_body, true); |
| 2358 | 2389 | try f.outdent(); |
| 2359 | 2390 | try f.code.writer.writeByte('}'); |
| ... | ... | @@ -2456,10 +2487,12 @@ pub fn genDeclFwd(dg: *DeclGen, w: *Writer) Error!void { |
| 2456 | 2487 | |
| 2457 | 2488 | .@"extern" => |@"extern"| switch (nav_ty.zigTypeTag(zcu)) { |
| 2458 | 2489 | .@"fn" => { |
| 2490 | const fn_val: Value = .fromInterned(nav.resolved.?.value); | |
| 2491 | if (fn_val.typeOf(zcu).fnReturnType(zcu).isNoReturn(zcu)) try w.writeAll("zig_noreturn "); | |
| 2459 | 2492 | try w.writeAll("zig_extern "); |
| 2460 | 2493 | try dg.renderFunctionSignature( |
| 2461 | 2494 | w, |
| 2462 | .fromInterned(nav.resolved.?.value), | |
| 2495 | fn_val, | |
| 2463 | 2496 | nav.resolved.?.@"align", |
| 2464 | 2497 | .forward_decl, |
| 2465 | 2498 | .{ .@"export" = .{ |
| ... | ... | @@ -2560,11 +2593,13 @@ pub fn genExports(dg: *DeclGen, w: *Writer, exported: Zcu.Exported, export_indic |
| 2560 | 2593 | const exported_val = exported.getValue(zcu); |
| 2561 | 2594 | if (ip.isFunctionType(exported_val.typeOf(zcu).toIntern())) return for (export_indices) |export_index| { |
| 2562 | 2595 | const @"export" = export_index.ptr(zcu); |
| 2596 | const fn_val = exported.getValue(zcu); | |
| 2597 | if (fn_val.typeOf(zcu).fnReturnType(zcu).isNoReturn(zcu)) try w.writeAll("zig_noreturn "); | |
| 2563 | 2598 | try w.writeAll("zig_extern "); |
| 2564 | 2599 | if (@"export".opts.linkage == .weak) try w.writeAll("zig_weak_linkage_fn "); |
| 2565 | 2600 | try dg.renderFunctionSignature( |
| 2566 | 2601 | w, |
| 2567 | exported.getValue(zcu), | |
| 2602 | fn_val, | |
| 2568 | 2603 | exported.getAlign(zcu), |
| 2569 | 2604 | .forward_decl, |
| 2570 | 2605 | .{ .@"export" = .{ |
| ... | ... | @@ -7277,101 +7312,6 @@ fn writeMemoryOrder(w: *Writer, order: std.lang.AtomicOrder) !void { |
| 7277 | 7312 | return w.writeAll(toMemoryOrder(order)); |
| 7278 | 7313 | } |
| 7279 | 7314 | |
| 7280 | fn toCallingConvention(cc: std.lang.CallingConvention, zcu: *Zcu) ?[]const u8 { | |
| 7281 | if (zcu.getTarget().cCallingConvention()) |ccc| { | |
| 7282 | if (cc.eql(ccc)) { | |
| 7283 | return null; | |
| 7284 | } | |
| 7285 | } | |
| 7286 | return switch (cc) { | |
| 7287 | .auto, .naked => null, | |
| 7288 | ||
| 7289 | .x86_16_cdecl => "cdecl", | |
| 7290 | .x86_16_regparmcall => "regparmcall", | |
| 7291 | .x86_64_sysv, .x86_sysv => "sysv_abi", | |
| 7292 | .x86_64_win, .x86_win, .x86_mingw => "ms_abi", | |
| 7293 | .x86_16_stdcall, .x86_stdcall => "stdcall", | |
| 7294 | .x86_fastcall => "fastcall", | |
| 7295 | .x86_thiscall => "thiscall", | |
| 7296 | ||
| 7297 | .x86_vectorcall, | |
| 7298 | .x86_64_vectorcall, | |
| 7299 | => "vectorcall", | |
| 7300 | ||
| 7301 | .x86_64_regcall_v3_sysv, | |
| 7302 | .x86_64_regcall_v4_win, | |
| 7303 | .x86_regcall_v3, | |
| 7304 | .x86_regcall_v4_win, | |
| 7305 | => "regcall", | |
| 7306 | ||
| 7307 | .aarch64_vfabi => "aarch64_vector_pcs", | |
| 7308 | .aarch64_vfabi_sve => "aarch64_sve_pcs", | |
| 7309 | ||
| 7310 | .arm_aapcs => "pcs(\"aapcs\")", | |
| 7311 | .arm_aapcs_vfp => "pcs(\"aapcs-vfp\")", | |
| 7312 | ||
| 7313 | .arc_interrupt => |opts| switch (opts.type) { | |
| 7314 | inline else => |t| "interrupt(\"" ++ @tagName(t) ++ "\")", | |
| 7315 | }, | |
| 7316 | ||
| 7317 | .arm_interrupt => |opts| switch (opts.type) { | |
| 7318 | .generic => "interrupt", | |
| 7319 | .irq => "interrupt(\"IRQ\")", | |
| 7320 | .fiq => "interrupt(\"FIQ\")", | |
| 7321 | .swi => "interrupt(\"SWI\")", | |
| 7322 | .abort => "interrupt(\"ABORT\")", | |
| 7323 | .undef => "interrupt(\"UNDEF\")", | |
| 7324 | }, | |
| 7325 | ||
| 7326 | .avr_signal => "signal", | |
| 7327 | ||
| 7328 | .microblaze_interrupt => |opts| switch (opts.type) { | |
| 7329 | .user => "save_volatiles", | |
| 7330 | .regular => "interrupt_handler", | |
| 7331 | .fast => "fast_interrupt", | |
| 7332 | .breakpoint => "break_handler", | |
| 7333 | }, | |
| 7334 | ||
| 7335 | .mips_interrupt, | |
| 7336 | .mips64_interrupt, | |
| 7337 | => |opts| switch (opts.mode) { | |
| 7338 | inline else => |m| "interrupt(\"" ++ @tagName(m) ++ "\")", | |
| 7339 | }, | |
| 7340 | ||
| 7341 | .riscv64_lp64_v, .riscv32_ilp32_v => "riscv_vector_cc", | |
| 7342 | ||
| 7343 | .riscv32_interrupt, | |
| 7344 | .riscv64_interrupt, | |
| 7345 | => |opts| switch (opts.mode) { | |
| 7346 | inline else => |m| "interrupt(\"" ++ @tagName(m) ++ "\")", | |
| 7347 | }, | |
| 7348 | ||
| 7349 | .sh_renesas => "renesas", | |
| 7350 | .sh_interrupt => |opts| switch (opts.save) { | |
| 7351 | .fpscr => "trapa_handler", // Implies `interrupt_handler`. | |
| 7352 | .high => "interrupt_handler, nosave_low_regs", | |
| 7353 | .full => "interrupt_handler", | |
| 7354 | .bank => "interrupt_handler, resbank", | |
| 7355 | }, | |
| 7356 | ||
| 7357 | .m68k_rtd => "m68k_rtd", | |
| 7358 | ||
| 7359 | .avr_interrupt, | |
| 7360 | .csky_interrupt, | |
| 7361 | .m68k_interrupt, | |
| 7362 | .msp430_interrupt, | |
| 7363 | .x86_16_interrupt, | |
| 7364 | .x86_interrupt, | |
| 7365 | .x86_64_interrupt, | |
| 7366 | => "interrupt", | |
| 7367 | ||
| 7368 | .ez80_tiflags, | |
| 7369 | => "__tiflags__", | |
| 7370 | ||
| 7371 | else => unreachable, // `Zcu.callconvSupported` | |
| 7372 | }; | |
| 7373 | } | |
| 7374 | ||
| 7375 | 7315 | fn toAtomicRmwSuffix(order: std.lang.AtomicRmwOp) []const u8 { |
| 7376 | 7316 | return switch (order) { |
| 7377 | 7317 | .Xchg => "xchg", |
src/codegen/c/type.zig+176-1| ... | ... | @@ -44,8 +44,175 @@ pub const CType = union(enum) { |
| 44 | 44 | param_tys: []const CType, |
| 45 | 45 | ret_ty: *const CType, |
| 46 | 46 | varargs: bool, |
| 47 | cc: CallingConvention, | |
| 47 | 48 | }, |
| 48 | 49 | |
| 50 | pub const CallingConvention = enum { | |
| 51 | c, | |
| 52 | ||
| 53 | cdecl, | |
| 54 | regparmcall, | |
| 55 | sysv_abi, | |
| 56 | ms_abi, | |
| 57 | stdcall, | |
| 58 | fastcall, | |
| 59 | thiscall, | |
| 60 | ||
| 61 | vectorcall, | |
| 62 | ||
| 63 | regcall, | |
| 64 | ||
| 65 | aarch64_vector_pcs, | |
| 66 | aarch64_sve_pcs, | |
| 67 | ||
| 68 | @"pcs(\"aapcs\")", | |
| 69 | @"pcs(\"aapcs-vfp\")", | |
| 70 | ||
| 71 | @"interrupt(\"ilink1\")", | |
| 72 | @"interrupt(\"ilink2\")", | |
| 73 | @"interrupt(\"ilink\")", | |
| 74 | @"interrupt(\"firq\")", | |
| 75 | ||
| 76 | interrupt, | |
| 77 | @"interrupt(\"IRQ\")", | |
| 78 | @"interrupt(\"FIQ\")", | |
| 79 | @"interrupt(\"SWI\")", | |
| 80 | @"interrupt(\"ABORT\")", | |
| 81 | @"interrupt(\"UNDEF\")", | |
| 82 | ||
| 83 | signal, | |
| 84 | ||
| 85 | save_volatiles, | |
| 86 | interrupt_handler, | |
| 87 | fast_interrupt, | |
| 88 | break_handler, | |
| 89 | ||
| 90 | @"interrupt(\"eic\")", | |
| 91 | @"interrupt(\"sw0\")", | |
| 92 | @"interrupt(\"sw1\")", | |
| 93 | @"interrupt(\"hw0\")", | |
| 94 | @"interrupt(\"hw1\")", | |
| 95 | @"interrupt(\"hw2\")", | |
| 96 | @"interrupt(\"hw3\")", | |
| 97 | @"interrupt(\"hw4\")", | |
| 98 | @"interrupt(\"hw5\")", | |
| 99 | ||
| 100 | riscv_vector_cc, | |
| 101 | @"interrupt(\"supervisor\")", | |
| 102 | @"interrupt(\"machine\")", | |
| 103 | ||
| 104 | renesas, | |
| 105 | /// Implies `interrupt_handler`. | |
| 106 | trapa_handler, | |
| 107 | @"interrupt_handler, nosave_low_regs", | |
| 108 | @"interrupt_handler, resbank", | |
| 109 | ||
| 110 | m68k_rtd, | |
| 111 | ||
| 112 | tiflags, | |
| 113 | ||
| 114 | pub fn fromLang(cc: std.lang.CallingConvention, target: *const std.Target) CallingConvention { | |
| 115 | if (target.cCallingConvention()) |ccc| { | |
| 116 | if (cc.eql(ccc)) { | |
| 117 | return .c; | |
| 118 | } | |
| 119 | } | |
| 120 | return switch (cc) { | |
| 121 | .auto, .naked => .c, | |
| 122 | ||
| 123 | .x86_16_cdecl => .cdecl, | |
| 124 | .x86_16_regparmcall => .regparmcall, | |
| 125 | .x86_64_sysv, .x86_sysv => .sysv_abi, | |
| 126 | .x86_64_win, .x86_win, .x86_mingw => .ms_abi, | |
| 127 | .x86_16_stdcall, .x86_stdcall => .stdcall, | |
| 128 | .x86_fastcall => .fastcall, | |
| 129 | .x86_thiscall => .thiscall, | |
| 130 | ||
| 131 | .x86_vectorcall, | |
| 132 | .x86_64_vectorcall, | |
| 133 | => .vectorcall, | |
| 134 | ||
| 135 | .x86_64_regcall_v3_sysv, | |
| 136 | .x86_64_regcall_v4_win, | |
| 137 | .x86_regcall_v3, | |
| 138 | .x86_regcall_v4_win, | |
| 139 | => .regcall, | |
| 140 | ||
| 141 | .aarch64_vfabi => .aarch64_vector_pcs, | |
| 142 | .aarch64_vfabi_sve => .aarch64_sve_pcs, | |
| 143 | ||
| 144 | .arm_aapcs => .@"pcs(\"aapcs\")", | |
| 145 | .arm_aapcs_vfp => .@"pcs(\"aapcs-vfp\")", | |
| 146 | ||
| 147 | .arc_interrupt => |opts| switch (opts.type) { | |
| 148 | .ilink1 => .@"interrupt(\"ilink1\")", | |
| 149 | .ilink2 => .@"interrupt(\"ilink2\")", | |
| 150 | .ilink => .@"interrupt(\"ilink\")", | |
| 151 | .firq => .@"interrupt(\"firq\")", | |
| 152 | }, | |
| 153 | ||
| 154 | .arm_interrupt => |opts| switch (opts.type) { | |
| 155 | .generic => .interrupt, | |
| 156 | .irq => .@"interrupt(\"IRQ\")", | |
| 157 | .fiq => .@"interrupt(\"FIQ\")", | |
| 158 | .swi => .@"interrupt(\"SWI\")", | |
| 159 | .abort => .@"interrupt(\"ABORT\")", | |
| 160 | .undef => .@"interrupt(\"UNDEF\")", | |
| 161 | }, | |
| 162 | ||
| 163 | .avr_signal => .signal, | |
| 164 | ||
| 165 | .microblaze_interrupt => |opts| switch (opts.type) { | |
| 166 | .user => .save_volatiles, | |
| 167 | .regular => .interrupt_handler, | |
| 168 | .fast => .fast_interrupt, | |
| 169 | .breakpoint => .break_handler, | |
| 170 | }, | |
| 171 | ||
| 172 | .mips_interrupt, .mips64_interrupt => |opts| switch (opts.mode) { | |
| 173 | .eic => .@"interrupt(\"eic\")", | |
| 174 | .sw0 => .@"interrupt(\"sw0\")", | |
| 175 | .sw1 => .@"interrupt(\"sw1\")", | |
| 176 | .hw0 => .@"interrupt(\"hw0\")", | |
| 177 | .hw1 => .@"interrupt(\"hw1\")", | |
| 178 | .hw2 => .@"interrupt(\"hw2\")", | |
| 179 | .hw3 => .@"interrupt(\"hw3\")", | |
| 180 | .hw4 => .@"interrupt(\"hw4\")", | |
| 181 | .hw5 => .@"interrupt(\"hw5\")", | |
| 182 | }, | |
| 183 | ||
| 184 | .riscv64_lp64_v, .riscv32_ilp32_v => .riscv_vector_cc, | |
| 185 | .riscv32_interrupt, .riscv64_interrupt => |opts| switch (opts.mode) { | |
| 186 | .supervisor => .@"interrupt(\"supervisor\")", | |
| 187 | .machine => .@"interrupt(\"machine\")", | |
| 188 | }, | |
| 189 | ||
| 190 | .sh_renesas => .renesas, | |
| 191 | .sh_interrupt => |opts| switch (opts.save) { | |
| 192 | .fpscr => .trapa_handler, | |
| 193 | .high => .@"interrupt_handler, nosave_low_regs", | |
| 194 | .full => .interrupt_handler, | |
| 195 | .bank => .@"interrupt_handler, resbank", | |
| 196 | }, | |
| 197 | ||
| 198 | .m68k_rtd => .m68k_rtd, | |
| 199 | ||
| 200 | .avr_interrupt, | |
| 201 | .csky_interrupt, | |
| 202 | .m68k_interrupt, | |
| 203 | .msp430_interrupt, | |
| 204 | .x86_16_interrupt, | |
| 205 | .x86_interrupt, | |
| 206 | .x86_64_interrupt, | |
| 207 | => .interrupt, | |
| 208 | ||
| 209 | .ez80_tiflags => .tiflags, | |
| 210 | ||
| 211 | else => unreachable, // `Zcu.callconvSupported` | |
| 212 | }; | |
| 213 | } | |
| 214 | }; | |
| 215 | ||
| 49 | 216 | /// Returns `true` if this node has a postfix operator, meaning an `[...]` or `(...)` appears |
| 50 | 217 | /// after the identifier in a declarator with this type. In this case, if this node is wrapped |
| 51 | 218 | /// in a pointer type, we will need to add parentheses due to operator precedence. |
| ... | ... | @@ -376,6 +543,7 @@ pub const CType = union(enum) { |
| 376 | 543 | .ret_ty = ret_cty_buf, |
| 377 | 544 | .param_tys = param_cty_buf, |
| 378 | 545 | .varargs = func_type.is_var_args, |
| 546 | .cc = .fromLang(func_type.cc, zcu.getTarget()), | |
| 379 | 547 | } }; |
| 380 | 548 | } |
| 381 | 549 | try deps.addType(gpa, cur_ty, allow_incomplete); |
| ... | ... | @@ -763,6 +931,13 @@ pub const CType = union(enum) { |
| 763 | 931 | try w.writeByte('('); |
| 764 | 932 | }, |
| 765 | 933 | } |
| 934 | switch (ptr.elem_ty.*) { | |
| 935 | else => {}, | |
| 936 | .function => |function| switch (function.cc) { | |
| 937 | .c => {}, | |
| 938 | else => |cc| try w.print("zig_callconv({t}) ", .{cc}), | |
| 939 | }, | |
| 940 | } | |
| 766 | 941 | try w.writeByte('*'); |
| 767 | 942 | }, |
| 768 | 943 | |
| ... | ... | @@ -812,7 +987,7 @@ pub const CType = union(enum) { |
| 812 | 987 | => {}, |
| 813 | 988 | |
| 814 | 989 | .pointer => |ptr| { |
| 815 | // Match opening paren "(" write `writeTypePrefix`. | |
| 990 | // Match opening paren "(" in `writeTypePrefix`. | |
| 816 | 991 | switch (ptr.elem_ty.kind()) { |
| 817 | 992 | .specifier, .pointer => {}, |
| 818 | 993 | .postfix_op => try w.writeByte(')'), |
src/codegen/c/type/render_defs.zig+8-8| ... | ... | @@ -203,10 +203,12 @@ pub fn defineComplete( |
| 203 | 203 | const name_cty: CType = .{ .@"fn" = ty }; |
| 204 | 204 | const ret_cty: CType = try .lower(effective_ret_ty, deps, arena, zcu); |
| 205 | 205 | |
| 206 | try w.print("typedef {f}{f}(", .{ | |
| 207 | ret_cty.fmtDeclaratorPrefix(zcu), | |
| 208 | name_cty.fmtTypeName(zcu), | |
| 209 | }); | |
| 206 | try w.print("typedef {f}", .{ret_cty.fmtDeclaratorPrefix(zcu)}); | |
| 207 | switch (CType.CallingConvention.fromLang(func_type.cc, zcu.getTarget())) { | |
| 208 | .c => {}, | |
| 209 | else => |cc| try w.print("zig_callconv({t}) ", .{cc}), | |
| 210 | } | |
| 211 | try w.print("{f}(", .{name_cty.fmtTypeName(zcu)}); | |
| 210 | 212 | var any_params = false; |
| 211 | 213 | for (func_type.param_types.get(ip)) |param_ty_ip| { |
| 212 | 214 | const param_ty: Type = .fromInterned(param_ty_ip); |
| ... | ... | @@ -222,9 +224,7 @@ pub fn defineComplete( |
| 222 | 224 | } else if (!any_params) { |
| 223 | 225 | try w.writeAll("void"); |
| 224 | 226 | } |
| 225 | try w.print("){f};", .{ | |
| 226 | ret_cty.fmtDeclaratorSuffixIgnoreNonstring(zcu), | |
| 227 | }); | |
| 227 | try w.print("){f};", .{ret_cty.fmtDeclaratorSuffixIgnoreNonstring(zcu)}); | |
| 228 | 228 | break :check_cty null; |
| 229 | 229 | }, |
| 230 | 230 | .@"enum" => { |
| ... | ... | @@ -254,7 +254,7 @@ pub fn defineComplete( |
| 254 | 254 | try w.print( |
| 255 | 255 | \\{f} {{ |
| 256 | 256 | \\ {f}ptr{f}; |
| 257 | \\ size_t len; | |
| 257 | \\ uintptr_t len; | |
| 258 | 258 | \\}}; |
| 259 | 259 | , .{ |
| 260 | 260 | name_cty.fmtTypeName(zcu), |
src/codegen/llvm.zig+2-2| ... | ... | @@ -2550,7 +2550,7 @@ pub const Object = struct { |
| 2550 | 2550 | llvm_function.setCallConv(cc_info.llvm_cc, &o.builder); |
| 2551 | 2551 | |
| 2552 | 2552 | if (cc_info.align_stack) { |
| 2553 | try attributes.addFnAttr(.{ .alignstack = .wrap(.fromByteUnits(target.stackAlignment())) }, &o.builder); | |
| 2553 | try attributes.addFnAttr(.{ .string = .{ .kind = try o.builder.string("stackrealign"), .value = .empty } }, &o.builder); | |
| 2554 | 2554 | } |
| 2555 | 2555 | |
| 2556 | 2556 | if (cc_info.naked) { |
| ... | ... | @@ -4522,7 +4522,7 @@ pub fn toLlvmCallConv(cc: std.lang.CallingConvention, target: *const std.Target) |
| 4522 | 4522 | std.lang.CallingConvention.SpirvFragmentOptions, |
| 4523 | 4523 | std.lang.CallingConvention.SpirvMeshOptions, |
| 4524 | 4524 | => .{ null, 0, 0 }, |
| 4525 | else => @compileError("TODO: toLlvmCallConv" ++ @tagName(pl)), | |
| 4525 | else => @compileError("TODO: toLlvmCallConv(." ++ @tagName(pl) ++ ")"), | |
| 4526 | 4526 | }, |
| 4527 | 4527 | }; |
| 4528 | 4528 | return .{ |