| author | |
| committer | |
| log | 0ccac79c8ebc1ed56dbdab068076a86924a015bc |
| tree | a7dfe2ba2535f7d4c50f2f8bae07e97df1a2ef19 |
| parent | 08a26fea0918fba1dd315781fa96d457da5bcb50 |
7 files changed, 30 insertions(+), 14 deletions(-)
lib/std/builtin.zig+1| ... | ... | @@ -104,6 +104,7 @@ pub const CallingConvention = enum { |
| 104 | 104 | Stdcall, |
| 105 | 105 | Fastcall, |
| 106 | 106 | Vectorcall, |
| 107 | Thiscall, | |
| 107 | 108 | APCS, |
| 108 | 109 | AAPCS, |
| 109 | 110 | AAPCSVFP, |
src-self-hosted/translate_c.zig+1| ... | ... | @@ -3975,6 +3975,7 @@ fn transCC( |
| 3975 | 3975 | .X86StdCall => return CallingConvention.Stdcall, |
| 3976 | 3976 | .X86FastCall => return CallingConvention.Fastcall, |
| 3977 | 3977 | .X86VectorCall, .AArch64VectorCall => return CallingConvention.Vectorcall, |
| 3978 | .X86ThisCall => return CallingConvention.Thiscall, | |
| 3978 | 3979 | .AAPCS => return CallingConvention.AAPCS, |
| 3979 | 3980 | .AAPCS_VFP => return CallingConvention.AAPCSVFP, |
| 3980 | 3981 | else => return revertAndWarn( |
src/all_types.hpp+1| ... | ... | @@ -68,6 +68,7 @@ enum CallingConvention { |
| 68 | 68 | CallingConventionStdcall, |
| 69 | 69 | CallingConventionFastcall, |
| 70 | 70 | CallingConventionVectorcall, |
| 71 | CallingConventionThiscall, | |
| 71 | 72 | CallingConventionAPCS, |
| 72 | 73 | CallingConventionAAPCS, |
| 73 | 74 | CallingConventionAAPCSVFP, |
src/analyze.cpp+15-11| ... | ... | @@ -929,6 +929,7 @@ const char *calling_convention_name(CallingConvention cc) { |
| 929 | 929 | case CallingConventionStdcall: return "Stdcall"; |
| 930 | 930 | case CallingConventionFastcall: return "Fastcall"; |
| 931 | 931 | case CallingConventionVectorcall: return "Vectorcall"; |
| 932 | case CallingConventionThiscall: return "Thiscall"; | |
| 932 | 933 | case CallingConventionAPCS: return "Apcs"; |
| 933 | 934 | case CallingConventionAAPCS: return "Aapcs"; |
| 934 | 935 | case CallingConventionAAPCSVFP: return "Aapcsvfp"; |
| ... | ... | @@ -949,6 +950,7 @@ bool calling_convention_allows_zig_types(CallingConvention cc) { |
| 949 | 950 | case CallingConventionStdcall: |
| 950 | 951 | case CallingConventionFastcall: |
| 951 | 952 | case CallingConventionVectorcall: |
| 953 | case CallingConventionThiscall: | |
| 952 | 954 | case CallingConventionAPCS: |
| 953 | 955 | case CallingConventionAAPCS: |
| 954 | 956 | case CallingConventionAAPCSVFP: |
| ... | ... | @@ -1706,9 +1708,7 @@ Error type_allowed_in_extern(CodeGen *g, ZigType *type_entry, bool *result) { |
| 1706 | 1708 | case ZigTypeIdArray: |
| 1707 | 1709 | return type_allowed_in_extern(g, type_entry->data.array.child_type, result); |
| 1708 | 1710 | case ZigTypeIdFn: |
| 1709 | *result = type_entry->data.fn.fn_type_id.cc == CallingConventionC || | |
| 1710 | type_entry->data.fn.fn_type_id.cc == CallingConventionStdcall || | |
| 1711 | type_entry->data.fn.fn_type_id.cc == CallingConventionAAPCS; | |
| 1711 | *result = !calling_convention_allows_zig_types(type_entry->data.fn.fn_type_id.cc); | |
| 1712 | 1712 | return ErrorNone; |
| 1713 | 1713 | case ZigTypeIdPointer: |
| 1714 | 1714 | if ((err = type_resolve(g, type_entry, ResolveStatusZeroBitsKnown))) |
| ... | ... | @@ -3445,24 +3445,21 @@ static void resolve_decl_fn(CodeGen *g, TldFn *tld_fn) { |
| 3445 | 3445 | fn_table_entry->cc = (CallingConvention)bigint_as_u32(&result_val->data.x_enum_tag); |
| 3446 | 3446 | } |
| 3447 | 3447 | |
| 3448 | fn_table_entry->type_entry = analyze_fn_type(g, source_node, child_scope, fn_table_entry); | |
| 3449 | ||
| 3450 | 3448 | if (fn_proto->section_expr != nullptr) { |
| 3451 | 3449 | if (!analyze_const_string(g, child_scope, fn_proto->section_expr, &fn_table_entry->section_name)) { |
| 3452 | 3450 | fn_table_entry->type_entry = g->builtin_types.entry_invalid; |
| 3451 | tld_fn->base.resolution = TldResolutionInvalid; | |
| 3452 | return; | |
| 3453 | 3453 | } |
| 3454 | 3454 | } |
| 3455 | 3455 | |
| 3456 | if (fn_table_entry->type_entry->id == ZigTypeIdInvalid) { | |
| 3456 | fn_table_entry->type_entry = analyze_fn_type(g, source_node, child_scope, fn_table_entry); | |
| 3457 | ||
| 3458 | if (type_is_invalid(fn_table_entry->type_entry)) { | |
| 3457 | 3459 | tld_fn->base.resolution = TldResolutionInvalid; |
| 3458 | 3460 | return; |
| 3459 | 3461 | } |
| 3460 | 3462 | |
| 3461 | if (!fn_table_entry->type_entry->data.fn.is_generic) { | |
| 3462 | if (fn_def_node) | |
| 3463 | g->fn_defs.append(fn_table_entry); | |
| 3464 | } | |
| 3465 | ||
| 3466 | 3463 | const CallingConvention fn_cc = fn_table_entry->type_entry->data.fn.fn_type_id.cc; |
| 3467 | 3464 | |
| 3468 | 3465 | if (fn_proto->is_export) { |
| ... | ... | @@ -3470,6 +3467,7 @@ static void resolve_decl_fn(CodeGen *g, TldFn *tld_fn) { |
| 3470 | 3467 | case CallingConventionAsync: |
| 3471 | 3468 | add_node_error(g, fn_def_node, |
| 3472 | 3469 | buf_sprintf("exported function cannot be async")); |
| 3470 | fn_table_entry->type_entry = g->builtin_types.entry_invalid; | |
| 3473 | 3471 | tld_fn->base.resolution = TldResolutionInvalid; |
| 3474 | 3472 | return; |
| 3475 | 3473 | case CallingConventionC: |
| ... | ... | @@ -3480,6 +3478,7 @@ static void resolve_decl_fn(CodeGen *g, TldFn *tld_fn) { |
| 3480 | 3478 | case CallingConventionStdcall: |
| 3481 | 3479 | case CallingConventionFastcall: |
| 3482 | 3480 | case CallingConventionVectorcall: |
| 3481 | case CallingConventionThiscall: | |
| 3483 | 3482 | case CallingConventionAPCS: |
| 3484 | 3483 | case CallingConventionAAPCS: |
| 3485 | 3484 | case CallingConventionAAPCSVFP: |
| ... | ... | @@ -3495,6 +3494,11 @@ static void resolve_decl_fn(CodeGen *g, TldFn *tld_fn) { |
| 3495 | 3494 | } |
| 3496 | 3495 | } |
| 3497 | 3496 | |
| 3497 | if (!fn_table_entry->type_entry->data.fn.is_generic) { | |
| 3498 | if (fn_def_node) | |
| 3499 | g->fn_defs.append(fn_table_entry); | |
| 3500 | } | |
| 3501 | ||
| 3498 | 3502 | // if the calling convention implies that it cannot be async, we save that for later |
| 3499 | 3503 | // and leave the value to be nullptr to indicate that we have not emitted possible |
| 3500 | 3504 | // compile errors for improperly calling async functions. |
src/codegen.cpp+9-3| ... | ... | @@ -301,6 +301,10 @@ static LLVMCallConv get_llvm_cc(CodeGen *g, CallingConvention cc) { |
| 301 | 301 | return LLVMAARCH64VectorCallCallConv; |
| 302 | 302 | #endif |
| 303 | 303 | return LLVMCCallConv; |
| 304 | case CallingConventionThiscall: | |
| 305 | if (g->zig_target->arch == ZigLLVM_x86) | |
| 306 | return LLVMX86ThisCallCallConv; | |
| 307 | return LLVMCCallConv; | |
| 304 | 308 | case CallingConventionAsync: |
| 305 | 309 | return LLVMFastCallConv; |
| 306 | 310 | case CallingConventionAPCS: |
| ... | ... | @@ -424,6 +428,7 @@ static bool cc_want_sret_attr(CallingConvention cc) { |
| 424 | 428 | case CallingConventionStdcall: |
| 425 | 429 | case CallingConventionFastcall: |
| 426 | 430 | case CallingConventionVectorcall: |
| 431 | case CallingConventionThiscall: | |
| 427 | 432 | case CallingConventionAPCS: |
| 428 | 433 | case CallingConventionAAPCS: |
| 429 | 434 | case CallingConventionAAPCSVFP: |
| ... | ... | @@ -8512,9 +8517,10 @@ Buf *codegen_generate_builtin_source(CodeGen *g) { |
| 8512 | 8517 | static_assert(CallingConventionStdcall == 7, ""); |
| 8513 | 8518 | static_assert(CallingConventionFastcall == 8, ""); |
| 8514 | 8519 | static_assert(CallingConventionVectorcall == 9, ""); |
| 8515 | static_assert(CallingConventionAPCS == 10, ""); | |
| 8516 | static_assert(CallingConventionAAPCS == 11, ""); | |
| 8517 | static_assert(CallingConventionAAPCSVFP == 12, ""); | |
| 8520 | static_assert(CallingConventionThiscall == 10, ""); | |
| 8521 | static_assert(CallingConventionAPCS == 11, ""); | |
| 8522 | static_assert(CallingConventionAAPCS == 12, ""); | |
| 8523 | static_assert(CallingConventionAAPCSVFP == 13, ""); | |
| 8518 | 8524 | |
| 8519 | 8525 | static_assert(FnInlineAuto == 0, ""); |
| 8520 | 8526 | static_assert(FnInlineAlways == 1, ""); |
src/ir.cpp+1| ... | ... | @@ -16752,6 +16752,7 @@ static IrInstruction *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructio |
| 16752 | 16752 | case CallingConventionStdcall: |
| 16753 | 16753 | case CallingConventionFastcall: |
| 16754 | 16754 | case CallingConventionVectorcall: |
| 16755 | case CallingConventionThiscall: | |
| 16755 | 16756 | case CallingConventionAPCS: |
| 16756 | 16757 | case CallingConventionAAPCS: |
| 16757 | 16758 | case CallingConventionAAPCSVFP: |
test/translate_c.zig+2| ... | ... | @@ -850,11 +850,13 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 850 | 850 | \\void __attribute__((stdcall)) foo2(float *a); |
| 851 | 851 | \\void __attribute__((vectorcall)) foo3(float *a); |
| 852 | 852 | \\void __attribute__((cdecl)) foo4(float *a); |
| 853 | \\void __attribute__((thiscall)) foo5(float *a); | |
| 853 | 854 | , &[_][]const u8{ |
| 854 | 855 | \\pub fn foo1(a: [*c]f32) callconv(.Fastcall) void; |
| 855 | 856 | \\pub fn foo2(a: [*c]f32) callconv(.Stdcall) void; |
| 856 | 857 | \\pub fn foo3(a: [*c]f32) callconv(.Vectorcall) void; |
| 857 | 858 | \\pub extern fn foo4(a: [*c]f32) void; |
| 859 | \\pub fn foo5(a: [*c]f32) callconv(.Thiscall) void; | |
| 858 | 860 | }); |
| 859 | 861 | |
| 860 | 862 | cases.addWithTarget("Calling convention", tests.Target{ |