Merge pull request #6829 from tadeokondrak/error-unsupported-callconv

stage1: Compile error instead of falling back to C for unsupported cc
This commit is contained in:
Veikka Tuominen
2020-11-19 19:03:08 +02:00
committed by GitHub
17 changed files with 380 additions and 244 deletions

View File

@@ -971,9 +971,9 @@ const char *calling_convention_name(CallingConvention cc) {
case CallingConventionFastcall: return "Fastcall";
case CallingConventionVectorcall: return "Vectorcall";
case CallingConventionThiscall: return "Thiscall";
case CallingConventionAPCS: return "Apcs";
case CallingConventionAAPCS: return "Aapcs";
case CallingConventionAAPCSVFP: return "Aapcsvfp";
case CallingConventionAPCS: return "APCS";
case CallingConventionAAPCS: return "AAPCS";
case CallingConventionAAPCSVFP: return "AAPCSVFP";
}
zig_unreachable();
}
@@ -1880,6 +1880,58 @@ ZigType *get_auto_err_set_type(CodeGen *g, ZigFn *fn_entry) {
return err_set_type;
}
// Sync this with get_llvm_cc in codegen.cpp
static Error emit_error_unless_callconv_allowed_for_target(CodeGen *g, AstNode *source_node, CallingConvention cc) {
Error ret = ErrorNone;
const char *allowed_platforms = nullptr;
switch (cc) {
case CallingConventionUnspecified:
case CallingConventionC:
case CallingConventionNaked:
case CallingConventionAsync:
break;
case CallingConventionInterrupt:
if (g->zig_target->arch != ZigLLVM_x86
&& g->zig_target->arch != ZigLLVM_x86_64
&& g->zig_target->arch != ZigLLVM_avr
&& g->zig_target->arch != ZigLLVM_msp430)
{
allowed_platforms = "x86, x86_64, AVR, and MSP430";
}
break;
case CallingConventionSignal:
if (g->zig_target->arch != ZigLLVM_avr)
allowed_platforms = "AVR";
break;
case CallingConventionStdcall:
case CallingConventionFastcall:
case CallingConventionThiscall:
if (g->zig_target->arch != ZigLLVM_x86)
allowed_platforms = "x86";
break;
case CallingConventionVectorcall:
if (g->zig_target->arch != ZigLLVM_x86
&& !(target_is_arm(g->zig_target) && target_arch_pointer_bit_width(g->zig_target->arch) == 64))
{
allowed_platforms = "x86 and AArch64";
}
break;
case CallingConventionAPCS:
case CallingConventionAAPCS:
case CallingConventionAAPCSVFP:
if (!target_is_arm(g->zig_target))
allowed_platforms = "ARM";
}
if (allowed_platforms != nullptr) {
add_node_error(g, source_node, buf_sprintf(
"callconv '%s' is only available on %s, not %s",
calling_convention_name(cc), allowed_platforms,
target_arch_name(g->zig_target->arch)));
ret = ErrorSemanticAnalyzeFail;
}
return ret;
}
static ZigType *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *child_scope, ZigFn *fn_entry,
CallingConvention cc)
{
@@ -2014,6 +2066,9 @@ static ZigType *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *child_sc
fn_entry->align_bytes = fn_type_id.alignment;
}
if ((err = emit_error_unless_callconv_allowed_for_target(g, proto_node->data.fn_proto.callconv_expr, cc)))
return g->builtin_types.entry_invalid;
if (fn_proto->return_anytype_token != nullptr) {
if (!calling_convention_allows_zig_types(fn_type_id.cc)) {
add_node_error(g, fn_proto->return_type,
@@ -3577,9 +3632,13 @@ void add_var_export(CodeGen *g, ZigVar *var, const char *symbol_name, GlobalLink
}
void add_fn_export(CodeGen *g, ZigFn *fn_table_entry, const char *symbol_name, GlobalLinkageId linkage, CallingConvention cc) {
CallingConvention winapi_cc = g->zig_target->arch == ZigLLVM_x86
? CallingConventionStdcall
: CallingConventionC;
if (cc == CallingConventionC && strcmp(symbol_name, "main") == 0 && g->link_libc) {
g->stage1.have_c_main = true;
} else if (cc == CallingConventionStdcall && g->zig_target->os == OsWindows) {
} else if (cc == winapi_cc && g->zig_target->os == OsWindows) {
if (strcmp(symbol_name, "WinMain") == 0) {
g->stage1.have_winmain = true;
} else if (strcmp(symbol_name, "wWinMain") == 0) {

View File

@@ -155,6 +155,7 @@ static const char *get_mangled_name(CodeGen *g, const char *original_name) {
}
}
// Sync this with emit_error_unless_callconv_allowed_for_target in analyze.cpp
static ZigLLVM_CallingConv get_llvm_cc(CodeGen *g, CallingConvention cc) {
switch (cc) {
case CallingConventionUnspecified:
@@ -164,38 +165,32 @@ static ZigLLVM_CallingConv get_llvm_cc(CodeGen *g, CallingConvention cc) {
case CallingConventionNaked:
zig_unreachable();
case CallingConventionStdcall:
if (g->zig_target->arch == ZigLLVM_x86)
return ZigLLVM_X86_StdCall;
return ZigLLVM_C;
assert(g->zig_target->arch == ZigLLVM_x86);
return ZigLLVM_X86_StdCall;
case CallingConventionFastcall:
if (g->zig_target->arch == ZigLLVM_x86)
return ZigLLVM_X86_FastCall;
return ZigLLVM_C;
assert(g->zig_target->arch == ZigLLVM_x86);
return ZigLLVM_X86_FastCall;
case CallingConventionVectorcall:
if (g->zig_target->arch == ZigLLVM_x86)
return ZigLLVM_X86_VectorCall;
if (target_is_arm(g->zig_target) &&
target_arch_pointer_bit_width(g->zig_target->arch) == 64)
return ZigLLVM_AArch64_VectorCall;
return ZigLLVM_C;
zig_unreachable();
case CallingConventionThiscall:
if (g->zig_target->arch == ZigLLVM_x86)
return ZigLLVM_X86_ThisCall;
return ZigLLVM_C;
assert(g->zig_target->arch == ZigLLVM_x86);
return ZigLLVM_X86_ThisCall;
case CallingConventionAsync:
return ZigLLVM_Fast;
case CallingConventionAPCS:
if (target_is_arm(g->zig_target))
return ZigLLVM_ARM_APCS;
return ZigLLVM_C;
assert(target_is_arm(g->zig_target));
return ZigLLVM_ARM_APCS;
case CallingConventionAAPCS:
if (target_is_arm(g->zig_target))
return ZigLLVM_ARM_AAPCS;
return ZigLLVM_C;
assert(target_is_arm(g->zig_target));
return ZigLLVM_ARM_AAPCS;
case CallingConventionAAPCSVFP:
if (target_is_arm(g->zig_target))
return ZigLLVM_ARM_AAPCS_VFP;
return ZigLLVM_C;
assert(target_is_arm(g->zig_target));
return ZigLLVM_ARM_AAPCS_VFP;
case CallingConventionInterrupt:
if (g->zig_target->arch == ZigLLVM_x86 ||
g->zig_target->arch == ZigLLVM_x86_64)
@@ -204,11 +199,10 @@ static ZigLLVM_CallingConv get_llvm_cc(CodeGen *g, CallingConvention cc) {
return ZigLLVM_AVR_INTR;
if (g->zig_target->arch == ZigLLVM_msp430)
return ZigLLVM_MSP430_INTR;
return ZigLLVM_C;
zig_unreachable();
case CallingConventionSignal:
if (g->zig_target->arch == ZigLLVM_avr)
return ZigLLVM_AVR_SIGNAL;
return ZigLLVM_C;
assert(g->zig_target->arch == ZigLLVM_avr);
return ZigLLVM_AVR_SIGNAL;
}
zig_unreachable();
}