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