Implement Thiscall CC
This commit is contained in:
parent
08a26fea09
commit
0ccac79c8e
@ -104,6 +104,7 @@ pub const CallingConvention = enum {
|
||||
Stdcall,
|
||||
Fastcall,
|
||||
Vectorcall,
|
||||
Thiscall,
|
||||
APCS,
|
||||
AAPCS,
|
||||
AAPCSVFP,
|
||||
|
@ -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(
|
||||
|
@ -68,6 +68,7 @@ enum CallingConvention {
|
||||
CallingConventionStdcall,
|
||||
CallingConventionFastcall,
|
||||
CallingConventionVectorcall,
|
||||
CallingConventionThiscall,
|
||||
CallingConventionAPCS,
|
||||
CallingConventionAAPCS,
|
||||
CallingConventionAAPCSVFP,
|
||||
|
@ -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.
|
||||
|
@ -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, "");
|
||||
|
@ -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:
|
||||
|
@ -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{
|
||||
|
Loading…
x
Reference in New Issue
Block a user