aboutsummaryrefslogtreecommitdiff
path: root/src/stage1
diff options
context:
space:
mode:
authorTadeo Kondrak <me@tadeo.ca>2020-10-07 17:38:42 -0600
committerVexu <git@vexu.eu>2020-11-19 13:59:11 +0200
commit6b9dc82fa596ac2470810bfda53d61e2add93d33 (patch)
tree086194972af6204490b6f2604ef80a5e63232cbc /src/stage1
parent2b7781d82ad8d2234b89257676670957e005f214 (diff)
downloadzig-6b9dc82fa596ac2470810bfda53d61e2add93d33.tar.gz
zig-6b9dc82fa596ac2470810bfda53d61e2add93d33.zip
stage1: Compile error instead of falling back to C for unsupported cc
Diffstat (limited to 'src/stage1')
-rw-r--r--src/stage1/analyze.cpp55
-rw-r--r--src/stage1/codegen.cpp40
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();
}