-
-
Notifications
You must be signed in to change notification settings - Fork 2.8k
Introduce callconv annotation #3977
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
else if (builtin.os == .windows) | ||
// https://locklessinc.com/articles/keyed_events/ | ||
else if (builtin.os == .windows) | ||
// https://locklessinc.com/articles/keyed_events/ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This doesn't look right to me. Created #3978
63252ce
to
4fbe848
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some CCs are architecture specific, do we want to add a prefix to those (eg.
Fastcall
->X86_Fastcall
) ?
Makes sense to me, let's do it. For "fastcall" it is especially nice because I don't want people to be confused and think "fastcall" is actually somehow "faster", it's more like "quicksort" is to sorting. So it's nice to have the architecture there to imply that this is a calling convention, not a performance thing.
Right now we "group" all the CCs under the same name (eg. AVR interrupt & X86 interrupt are both under the
Interrupt
entry) and are chosen according to the target architecture. Is this ok or do we want to split them into independent entities?
Hmm, good question. I really can't think of a reason to favor one or the other. With "C calling convention" we already have precedent for a calling convention that means different things on different architecture, so "interrupt" meaning "the architecture's native interrupt calling convention" seems reasonable to me. I defer to your judgment on this one.
This PR is already close enough to mergeable that I would feel comfortable with a hand-off. So let me know when you're done with it, and I'll make sure it lands swiftly in master branch.
const char *cc_str = calling_convention_fn_type_str(fn_type->data.fn.fn_type_id.cc); | ||
buf_appendf(&fn_type->name, "%s", cc_str); | ||
if (fn_type->data.fn.fn_type_id.cc == CallingConventionC) | ||
buf_append_str(&fn_type->name, "extern "); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was thinking we could drop extern
for the C calling convention, once we have callconv
. Any reason to keep using extern
for C calling convention functions?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Decoupling extern
from the CC is definitely a good idea, I tried not to change the status quo too much in this PR so I think I'll leave the breaking changes to you :)
bool is_nakedcc; | ||
bool is_stdcallcc; | ||
bool is_async; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Feel free to delete nakedcc and stdcallcc keywords from stage1. (If you don't do it, I'll do it.) I'm happy to tell people to use the auto-fixing you added to zig fmt
in order to upgrade code to the latest version.
I'll open a separate proposal to remove support for async fn
in favor of callconv(.Async)
for uniformity.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ditto, if you want to drop nakedcc
and stdcallcc
in this release cycle go for it! The less legacy cruft the better.
@@ -2162,7 +2180,7 @@ static Error resolve_struct_type(CodeGen *g, ZigType *struct_type) { | |||
ZigType *field_type = resolve_struct_field_type(g, field); | |||
if (field_type == nullptr) { | |||
struct_type->data.structure.resolve_status = ResolveStatusInvalid; | |||
return err; | |||
return ErrorSemanticAnalyzeFail; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yikes! nice catch.
src/codegen.cpp
Outdated
case CallingConventionVectorcall: | ||
if (g->zig_target->arch == ZigLLVM_x86) | ||
return LLVMX86VectorCallCallConv; | ||
// XXX Enable this when the C API exports this enum member too |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should work around this with zig_llvm.h
/zig_llvm.cpp
. The official LLVM C API always lags behind the C++ API.
In fact:
Lines 74 to 75 in 86ba8c0
ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildCall(LLVMBuilderRef B, LLVMValueRef Fn, LLVMValueRef *Args, | |
unsigned NumArgs, unsigned CC, enum ZigLLVM_CallAttr attr, const char *Name); |
Lines 275 to 297 in 86ba8c0
LLVMValueRef ZigLLVMBuildCall(LLVMBuilderRef B, LLVMValueRef Fn, LLVMValueRef *Args, | |
unsigned NumArgs, unsigned CC, ZigLLVM_CallAttr attr, const char *Name) | |
{ | |
CallInst *call_inst = CallInst::Create(unwrap(Fn), makeArrayRef(unwrap(Args), NumArgs), Name); | |
call_inst->setCallingConv(CC); | |
switch (attr) { | |
case ZigLLVM_CallAttrAuto: | |
break; | |
case ZigLLVM_CallAttrNeverTail: | |
call_inst->setTailCallKind(CallInst::TCK_NoTail); | |
break; | |
case ZigLLVM_CallAttrNeverInline: | |
call_inst->addAttribute(AttributeList::FunctionIndex, Attribute::NoInline); | |
break; | |
case ZigLLVM_CallAttrAlwaysTail: | |
call_inst->setTailCallKind(CallInst::TCK_MustTail); | |
break; | |
case ZigLLVM_CallAttrAlwaysInline: | |
call_inst->addAttribute(AttributeList::FunctionIndex, Attribute::AlwaysInline); | |
break; | |
} | |
return wrap(unwrap(B)->Insert(call_inst)); | |
} |
Looks like all we're missing is a copy-paste of LLVM's calling convention enum, with some static_assert
s in zig_llvm.cpp to make sure the values don't change. See src/zig_clang.cpp for inspiration.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've sent a patch that hopefully will get in by the time LLVM 10 is out. But moving away from the C API is also a good idea.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Makes sense to me, let's do it. For "fastcall" it is especially nice because I don't want people to be confused and think "fastcall" is actually somehow "faster", it's more like "quicksort" is to sorting. So it's nice to have the architecture there to imply that this is a calling convention, not a performance thing.
If we go for the prefix route then we should also split the common CCs (Vectorcall
becomes X86_Vectorcall
and AArch64_Vectorcall
, same for Interrupt
and so on). IMO it's fine to leave the enums un-prefixed and merged with some hints in the documentation about what to expect.
👍 |
This is ready to go on my end, I'll send a follow-up PR to make |
Returning the uninitialized/stale error condition made the compiler turn a blind eye to some problems.
Done according to the accepted proposal,
zig fmt
has been patched up to use the new notation when possible and the whole stdlib has been already updated.A few new calling conventions have been introduced, you can now write your interrupt handlers (for x86 & AVR) with pure Zig code.
Missing:
translate-c-2
Not critical but possibly wanted:
export
/extern
/callconv
combinationsA few open questions:
Fastcall
->X86_Fastcall
) ?Interrupt
entry) and are chosen according to the target architecture. Is this ok or do we want to split them into independent entities?I'm submitting this as-is to see if the CI is green,
in case this is merged please rebase it.Closes #661