diff options
| author | Tadeo Kondrak <me@tadeo.ca> | 2020-10-07 17:38:42 -0600 |
|---|---|---|
| committer | Vexu <git@vexu.eu> | 2020-11-19 13:59:11 +0200 |
| commit | 6b9dc82fa596ac2470810bfda53d61e2add93d33 (patch) | |
| tree | 086194972af6204490b6f2604ef80a5e63232cbc /src | |
| parent | 2b7781d82ad8d2234b89257676670957e005f214 (diff) | |
| download | zig-6b9dc82fa596ac2470810bfda53d61e2add93d33.tar.gz zig-6b9dc82fa596ac2470810bfda53d61e2add93d33.zip | |
stage1: Compile error instead of falling back to C for unsupported cc
Diffstat (limited to 'src')
| -rw-r--r-- | src/stage1/analyze.cpp | 55 | ||||
| -rw-r--r-- | src/stage1/codegen.cpp | 40 |
2 files changed, 72 insertions, 23 deletions
diff --git a/src/stage1/analyze.cpp b/src/stage1/analyze.cpp index 547d2d9ae2..57239b6c4a 100644 --- a/src/stage1/analyze.cpp +++ b/src/stage1/analyze.cpp @@ -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 MS430"; + } + 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, 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, diff --git a/src/stage1/codegen.cpp b/src/stage1/codegen.cpp index 9474b4fa56..4a999b33ca 100644 --- a/src/stage1/codegen.cpp +++ b/src/stage1/codegen.cpp @@ -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(); } |
