|
10 | 10 | // |
11 | 11 | //===----------------------------------------------------------------------===// |
12 | 12 |
|
| 13 | +#include "swift/ABI/Coro.h" |
13 | 14 | #include "swift/ABI/MetadataValues.h" |
14 | 15 | #include "swift/Basic/Assertions.h" |
15 | 16 | #include "swift/IRGen/Linking.h" |
16 | 17 | #include "llvm/IR/Function.h" |
17 | 18 | #include "llvm/IR/Instructions.h" |
18 | 19 | #include "llvm/IR/Module.h" |
19 | 20 |
|
| 21 | +#include "ConstantBuilder.h" |
20 | 22 | #include "Explosion.h" |
21 | 23 | #include "GenCoro.h" |
22 | 24 | #include "IRGenFunction.h" |
@@ -811,3 +813,86 @@ llvm::Constant *swift::irgen::getCoroDeallocFn(IRGenModule &IGM) { |
811 | 813 | IGM.addSwiftCoroAttributes(attrs, 0); |
812 | 814 | }); |
813 | 815 | } |
| 816 | + |
| 817 | +static llvm::Constant *getAddrOfGlobalCoroAllocator( |
| 818 | + IRGenModule &IGM, CoroAllocatorKind kind, bool shouldDeallocateImmediately, |
| 819 | + llvm::Constant *allocFn, llvm::Constant *deallocFn) { |
| 820 | + auto entity = LinkEntity::forCoroAllocator(kind); |
| 821 | + auto taskAllocator = IGM.getOrCreateLazyGlobalVariable( |
| 822 | + entity, |
| 823 | + [&](ConstantInitBuilder &builder) -> ConstantInitFuture { |
| 824 | + auto allocator = builder.beginStruct(IGM.CoroAllocatorTy); |
| 825 | + auto flags = CoroAllocatorFlags(kind); |
| 826 | + flags.setShouldDeallocateImmediately(shouldDeallocateImmediately); |
| 827 | + allocator.addInt32(flags.getOpaqueValue()); |
| 828 | + allocator.add(allocFn); |
| 829 | + allocator.add(deallocFn); |
| 830 | + return allocator.finishAndCreateFuture(); |
| 831 | + }, |
| 832 | + [&](llvm::GlobalVariable *var) { var->setConstant(true); }); |
| 833 | + return taskAllocator; |
| 834 | +} |
| 835 | + |
| 836 | +static llvm::Constant *getAddrOfSwiftCCMalloc(IRGenModule &IGM) { |
| 837 | + auto mallocFnPtr = IGM.getMallocFunctionPointer(); |
| 838 | + auto sig = mallocFnPtr.getSignature(); |
| 839 | + if (sig.getCallingConv() == IGM.SwiftCC) { |
| 840 | + return IGM.getMallocFn(); |
| 841 | + } |
| 842 | + return IGM.getOrCreateHelperFunction( |
| 843 | + "_swift_malloc", sig.getType()->getReturnType(), sig.getType()->params(), |
| 844 | + [](IRGenFunction &IGF) { |
| 845 | + auto parameters = IGF.collectParameters(); |
| 846 | + auto *size = parameters.claimNext(); |
| 847 | + auto malloc = IGF.IGM.getMallocFunctionPointer(); |
| 848 | + auto *call = IGF.Builder.CreateCall(malloc, {size}); |
| 849 | + IGF.Builder.CreateRet(call); |
| 850 | + }); |
| 851 | +} |
| 852 | + |
| 853 | +static llvm::Constant *getAddrOfSwiftCCFree(IRGenModule &IGM) { |
| 854 | + auto freeFnPtr = IGM.getFreeFunctionPointer(); |
| 855 | + auto sig = freeFnPtr.getSignature(); |
| 856 | + if (sig.getCallingConv() == IGM.SwiftCC) { |
| 857 | + return IGM.getFreeFn(); |
| 858 | + } |
| 859 | + return IGM.getOrCreateHelperFunction( |
| 860 | + "_swift_free", sig.getType()->getReturnType(), sig.getType()->params(), |
| 861 | + [](IRGenFunction &IGF) { |
| 862 | + auto parameters = IGF.collectParameters(); |
| 863 | + auto *ptr = parameters.claimNext(); |
| 864 | + auto free = IGF.IGM.getFreeFunctionPointer(); |
| 865 | + IGF.Builder.CreateCall(free, {ptr}); |
| 866 | + IGF.Builder.CreateRetVoid(); |
| 867 | + }); |
| 868 | +} |
| 869 | + |
| 870 | +llvm::Constant *IRGenModule::getAddrOfGlobalCoroMallocAllocator() { |
| 871 | + return getAddrOfGlobalCoroAllocator(*this, CoroAllocatorKind::Malloc, |
| 872 | + /*shouldDeallocateImmediately=*/true, |
| 873 | + getAddrOfSwiftCCMalloc(*this), |
| 874 | + getAddrOfSwiftCCFree(*this)); |
| 875 | +} |
| 876 | + |
| 877 | +llvm::Constant *IRGenModule::getAddrOfGlobalCoroAsyncTaskAllocator() { |
| 878 | + return getAddrOfGlobalCoroAllocator(*this, CoroAllocatorKind::Async, |
| 879 | + /*shouldDeallocateImmediately=*/false, |
| 880 | + getTaskAllocFn(), getTaskDeallocFn()); |
| 881 | +} |
| 882 | + |
| 883 | +llvm::Value * |
| 884 | +irgen::emitYieldOnce2CoroutineAllocator(IRGenFunction &IGF, |
| 885 | + std::optional<CoroAllocatorKind> kind) { |
| 886 | + if (!kind) { |
| 887 | + return IGF.getCoroutineAllocator(); |
| 888 | + } |
| 889 | + switch (*kind) { |
| 890 | + case CoroAllocatorKind::Stack: |
| 891 | + return llvm::ConstantPointerNull::get(IGF.IGM.CoroAllocatorPtrTy); |
| 892 | + case CoroAllocatorKind::Async: |
| 893 | + return IGF.IGM.getAddrOfGlobalCoroAsyncTaskAllocator(); |
| 894 | + case CoroAllocatorKind::Malloc: |
| 895 | + return IGF.IGM.getAddrOfGlobalCoroMallocAllocator(); |
| 896 | + } |
| 897 | + llvm_unreachable("unhandled case"); |
| 898 | +} |
0 commit comments