Commit 0ccac79c8e
Changed files (7)
lib
std
src-self-hosted
test
lib/std/builtin.zig
@@ -104,6 +104,7 @@ pub const CallingConvention = enum {
Stdcall,
Fastcall,
Vectorcall,
+ Thiscall,
APCS,
AAPCS,
AAPCSVFP,
src/all_types.hpp
@@ -68,6 +68,7 @@ enum CallingConvention {
CallingConventionStdcall,
CallingConventionFastcall,
CallingConventionVectorcall,
+ CallingConventionThiscall,
CallingConventionAPCS,
CallingConventionAAPCS,
CallingConventionAAPCSVFP,
src/analyze.cpp
@@ -929,6 +929,7 @@ const char *calling_convention_name(CallingConvention cc) {
case CallingConventionStdcall: return "Stdcall";
case CallingConventionFastcall: return "Fastcall";
case CallingConventionVectorcall: return "Vectorcall";
+ case CallingConventionThiscall: return "Thiscall";
case CallingConventionAPCS: return "Apcs";
case CallingConventionAAPCS: return "Aapcs";
case CallingConventionAAPCSVFP: return "Aapcsvfp";
@@ -949,6 +950,7 @@ bool calling_convention_allows_zig_types(CallingConvention cc) {
case CallingConventionStdcall:
case CallingConventionFastcall:
case CallingConventionVectorcall:
+ case CallingConventionThiscall:
case CallingConventionAPCS:
case CallingConventionAAPCS:
case CallingConventionAAPCSVFP:
@@ -1706,9 +1708,7 @@ Error type_allowed_in_extern(CodeGen *g, ZigType *type_entry, bool *result) {
case ZigTypeIdArray:
return type_allowed_in_extern(g, type_entry->data.array.child_type, result);
case ZigTypeIdFn:
- *result = type_entry->data.fn.fn_type_id.cc == CallingConventionC ||
- type_entry->data.fn.fn_type_id.cc == CallingConventionStdcall ||
- type_entry->data.fn.fn_type_id.cc == CallingConventionAAPCS;
+ *result = !calling_convention_allows_zig_types(type_entry->data.fn.fn_type_id.cc);
return ErrorNone;
case ZigTypeIdPointer:
if ((err = type_resolve(g, type_entry, ResolveStatusZeroBitsKnown)))
@@ -3445,24 +3445,21 @@ static void resolve_decl_fn(CodeGen *g, TldFn *tld_fn) {
fn_table_entry->cc = (CallingConvention)bigint_as_u32(&result_val->data.x_enum_tag);
}
- fn_table_entry->type_entry = analyze_fn_type(g, source_node, child_scope, fn_table_entry);
-
if (fn_proto->section_expr != nullptr) {
if (!analyze_const_string(g, child_scope, fn_proto->section_expr, &fn_table_entry->section_name)) {
fn_table_entry->type_entry = g->builtin_types.entry_invalid;
+ tld_fn->base.resolution = TldResolutionInvalid;
+ return;
}
}
- if (fn_table_entry->type_entry->id == ZigTypeIdInvalid) {
+ fn_table_entry->type_entry = analyze_fn_type(g, source_node, child_scope, fn_table_entry);
+
+ if (type_is_invalid(fn_table_entry->type_entry)) {
tld_fn->base.resolution = TldResolutionInvalid;
return;
}
- if (!fn_table_entry->type_entry->data.fn.is_generic) {
- if (fn_def_node)
- g->fn_defs.append(fn_table_entry);
- }
-
const CallingConvention fn_cc = fn_table_entry->type_entry->data.fn.fn_type_id.cc;
if (fn_proto->is_export) {
@@ -3470,6 +3467,7 @@ static void resolve_decl_fn(CodeGen *g, TldFn *tld_fn) {
case CallingConventionAsync:
add_node_error(g, fn_def_node,
buf_sprintf("exported function cannot be async"));
+ fn_table_entry->type_entry = g->builtin_types.entry_invalid;
tld_fn->base.resolution = TldResolutionInvalid;
return;
case CallingConventionC:
@@ -3480,6 +3478,7 @@ static void resolve_decl_fn(CodeGen *g, TldFn *tld_fn) {
case CallingConventionStdcall:
case CallingConventionFastcall:
case CallingConventionVectorcall:
+ case CallingConventionThiscall:
case CallingConventionAPCS:
case CallingConventionAAPCS:
case CallingConventionAAPCSVFP:
@@ -3495,6 +3494,11 @@ static void resolve_decl_fn(CodeGen *g, TldFn *tld_fn) {
}
}
+ if (!fn_table_entry->type_entry->data.fn.is_generic) {
+ if (fn_def_node)
+ g->fn_defs.append(fn_table_entry);
+ }
+
// if the calling convention implies that it cannot be async, we save that for later
// and leave the value to be nullptr to indicate that we have not emitted possible
// compile errors for improperly calling async functions.
src/codegen.cpp
@@ -301,6 +301,10 @@ static LLVMCallConv get_llvm_cc(CodeGen *g, CallingConvention cc) {
return LLVMAARCH64VectorCallCallConv;
#endif
return LLVMCCallConv;
+ case CallingConventionThiscall:
+ if (g->zig_target->arch == ZigLLVM_x86)
+ return LLVMX86ThisCallCallConv;
+ return LLVMCCallConv;
case CallingConventionAsync:
return LLVMFastCallConv;
case CallingConventionAPCS:
@@ -424,6 +428,7 @@ static bool cc_want_sret_attr(CallingConvention cc) {
case CallingConventionStdcall:
case CallingConventionFastcall:
case CallingConventionVectorcall:
+ case CallingConventionThiscall:
case CallingConventionAPCS:
case CallingConventionAAPCS:
case CallingConventionAAPCSVFP:
@@ -8512,9 +8517,10 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {
static_assert(CallingConventionStdcall == 7, "");
static_assert(CallingConventionFastcall == 8, "");
static_assert(CallingConventionVectorcall == 9, "");
- static_assert(CallingConventionAPCS == 10, "");
- static_assert(CallingConventionAAPCS == 11, "");
- static_assert(CallingConventionAAPCSVFP == 12, "");
+ static_assert(CallingConventionThiscall == 10, "");
+ static_assert(CallingConventionAPCS == 11, "");
+ static_assert(CallingConventionAAPCS == 12, "");
+ static_assert(CallingConventionAAPCSVFP == 13, "");
static_assert(FnInlineAuto == 0, "");
static_assert(FnInlineAlways == 1, "");
src/ir.cpp
@@ -16752,6 +16752,7 @@ static IrInstruction *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructio
case CallingConventionStdcall:
case CallingConventionFastcall:
case CallingConventionVectorcall:
+ case CallingConventionThiscall:
case CallingConventionAPCS:
case CallingConventionAAPCS:
case CallingConventionAAPCSVFP:
src-self-hosted/translate_c.zig
@@ -3975,6 +3975,7 @@ fn transCC(
.X86StdCall => return CallingConvention.Stdcall,
.X86FastCall => return CallingConvention.Fastcall,
.X86VectorCall, .AArch64VectorCall => return CallingConvention.Vectorcall,
+ .X86ThisCall => return CallingConvention.Thiscall,
.AAPCS => return CallingConvention.AAPCS,
.AAPCS_VFP => return CallingConvention.AAPCSVFP,
else => return revertAndWarn(
test/translate_c.zig
@@ -850,11 +850,13 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\void __attribute__((stdcall)) foo2(float *a);
\\void __attribute__((vectorcall)) foo3(float *a);
\\void __attribute__((cdecl)) foo4(float *a);
+ \\void __attribute__((thiscall)) foo5(float *a);
, &[_][]const u8{
\\pub fn foo1(a: [*c]f32) callconv(.Fastcall) void;
\\pub fn foo2(a: [*c]f32) callconv(.Stdcall) void;
\\pub fn foo3(a: [*c]f32) callconv(.Vectorcall) void;
\\pub extern fn foo4(a: [*c]f32) void;
+ \\pub fn foo5(a: [*c]f32) callconv(.Thiscall) void;
});
cases.addWithTarget("Calling convention", tests.Target{