-
Notifications
You must be signed in to change notification settings - Fork 10.5k
[Async CC] Add constant "pointer" for async func. #34589
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
[Async CC] Add constant "pointer" for async func. #34589
Conversation
54d70ba
to
be5273a
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.
Very cool!
lib/IRGen/GenCall.cpp
Outdated
auto *sizeValue = | ||
llvm::ConstantInt::get(IGF.IGM.Int32Ty, size.getValue()); | ||
phiValues.push_back({staticSizeBlock, sizeValue}); | ||
auto *ptr = functionPointer.getRawPointer(); |
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.
You need logic for pointer authentication here.
lib/IRGen/GenCall.cpp
Outdated
if (kind == KindTy::AsyncFunctionPointer) { | ||
assert(fnType->getRepresentation() != SILFunctionTypeRepresentation::Thick); | ||
} | ||
return forDirect(kind, fnPtr, IGM.getSignature(fnType)); |
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 is determinable from the function type, right?
Should we lay the groundwork to make direct calls actually be direct in IR and just also record the context-size pointer?
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.
Something like this?
// Have to dig the size out of the AsyncFunctionPointer so that it can be rewritten downstream
%afp = `AsyncFunctionPointer(callee)`
%size_addr = getelementptr %afp, 0, 1
%size = load %size_addr
%context = call @swift_task_alloc(%task, %size)
// But we don't have to dig the function pointer out of the AsyncFunctionPointer because we already know what it is
call @callee(%task, %executor, %context)
lib/IRGen/GenCall.cpp
Outdated
switch (Kind) { | ||
case KindTy::Function: | ||
return Value; | ||
case KindTy::AsyncFunctionPointer: |
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.
Pointer auth logic required.
b061dcb
to
2fef32a
Compare
@swift-ci please test |
@swift-ci please clean test windows platform |
2fef32a
to
0280141
Compare
@swift-ci please test |
@swift-ci please clean test windows |
0280141
to
27f1d5b
Compare
@swift-ci please test |
27f1d5b
to
4827118
Compare
@swift-ci please test |
Build failed |
4827118
to
fb6045b
Compare
@swift-ci please test |
@swift-ci please clean test windows |
Build failed |
fb6045b
to
3470f75
Compare
@swift-ci please test |
67d9e21
to
ad74809
Compare
@swift-ci please test |
1 similar comment
@swift-ci please test |
ClassMetadataLayout::getOffsett -> ClassMetadataLayout::getOffset
Two LinkEntities are needed to enable the construction during both IRGen and TBDGen.
In order to call async functions, instances of the AsyncFunctionPointer struct must be used. If those functions are exported from a module, the AsyncFunctionPointer by means of which the function is to be called must be exported as well. For now, the symbol is exported by manually appending the relevant suffix to the mangled name of the function.
An AsyncFunctionPointer, defined in Task.h, is a struct consisting of two i32s: (1) the relative address of the async function and (2) the size of the async context to be allocated when calling that function. Here, such structs are emitted for every async SILFunction that is emitted.
While the pointer auth details are worked out, to unblock other work, disable the tests on arm64e where they will fail until those details are worked out.
ae4dbe3
to
6962874
Compare
@swift-ci please test |
Build failed |
Build failed |
An AsyncFunctionPointer, defined in Task.h, is a struct consisting of two i32s: (1) the relative address of the async function and (2) the size of the async context to be allocated when calling that function.
Here, such structs are emitted for every async SILFunction that is emitted. Furthermore, pointers to these new structs rather than pointers directly to async functions are passed around. The async context size is now read out of these function pointers and used to allocate the async context. This will enable the size constants to be rewritten by an LLVM pass with the ideal storage space to minimize additional allocations.
The following tasks need to be completed before merge:
The following related task will be completed in follow-on PRs: