Skip to content

Commit cd8144a

Browse files
committed
[NFC] IRGen: Move these functions.
1 parent 4183eca commit cd8144a

File tree

3 files changed

+159
-135
lines changed

3 files changed

+159
-135
lines changed

lib/IRGen/GenCall.cpp

Lines changed: 1 addition & 135 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
#include "EntryPointArgumentEmission.h"
4949
#include "Explosion.h"
5050
#include "GenCall.h"
51+
#include "GenCoro.h"
5152
#include "GenFunc.h"
5253
#include "GenHeap.h"
5354
#include "GenKeyPath.h"
@@ -5131,141 +5132,6 @@ void irgen::emitYieldManyCoroutineEntry(
51315132
allocFn, deallocFn, {});
51325133
}
51335134

5134-
static llvm::Constant *getCoroAllocFn(IRGenModule &IGM) {
5135-
auto isSwiftCoroCCAvailable = IGM.SwiftCoroCC == llvm::CallingConv::SwiftCoro;
5136-
return IGM.getOrCreateHelperFunction(
5137-
"_swift_coro_alloc", IGM.Int8PtrTy, {IGM.CoroAllocatorPtrTy, IGM.SizeTy},
5138-
[isSwiftCoroCCAvailable](IRGenFunction &IGF) {
5139-
auto parameters = IGF.collectParameters();
5140-
auto *allocator = parameters.claimNext();
5141-
auto *size = parameters.claimNext();
5142-
if (isSwiftCoroCCAvailable) {
5143-
// swiftcorocc is available, so if there's no allocator pointer,
5144-
// allocate storage on the stack and return a pointer to it without
5145-
// popping the stack.
5146-
auto *nullAllocator = IGF.Builder.CreateCmp(
5147-
llvm::CmpInst::Predicate::ICMP_EQ, allocator,
5148-
llvm::ConstantPointerNull::get(
5149-
cast<llvm::PointerType>(allocator->getType())));
5150-
auto *poplessReturn = IGF.createBasicBlock("popless");
5151-
auto *normalReturn = IGF.createBasicBlock("normal");
5152-
IGF.Builder.CreateCondBr(nullAllocator, poplessReturn, normalReturn);
5153-
IGF.Builder.emitBlock(poplessReturn);
5154-
// Emit the dynamic alloca.
5155-
auto *alloca =
5156-
IGF.Builder.IRBuilderBase::CreateAlloca(IGF.IGM.Int8Ty, size);
5157-
alloca->setAlignment(llvm::Align(MaximumAlignment));
5158-
auto *retPopless = IGF.Builder.CreateIntrinsic(
5159-
IGF.IGM.VoidTy, llvm::Intrinsic::ret_popless, {});
5160-
retPopless->setTailCallKind(
5161-
llvm::CallInst::TailCallKind::TCK_MustTail);
5162-
IGF.Builder.CreateRet(alloca);
5163-
// Start emitting the "normal" block.
5164-
IGF.Builder.emitBlock(normalReturn);
5165-
}
5166-
auto *calleePtr = IGF.Builder.CreateInBoundsGEP(
5167-
IGF.IGM.CoroAllocatorTy, allocator,
5168-
{llvm::ConstantInt::get(IGF.IGM.Int32Ty, 0),
5169-
llvm::ConstantInt::get(IGF.IGM.Int32Ty, 1)});
5170-
auto *callee = IGF.Builder.CreateLoad(
5171-
Address(calleePtr, IGF.IGM.PtrTy, IGF.IGM.getPointerAlignment()),
5172-
"allocate_fn");
5173-
auto fnPtr = FunctionPointer::createUnsigned(
5174-
FunctionPointer::Kind::Function, callee,
5175-
Signature(cast<llvm::FunctionType>(IGF.IGM.CoroAllocateFnTy), {},
5176-
IGF.IGM.SwiftCC));
5177-
auto *call = IGF.Builder.CreateCall(fnPtr, {size});
5178-
call->setDoesNotThrow();
5179-
call->setCallingConv(IGF.IGM.SwiftCC);
5180-
IGF.Builder.CreateRet(call);
5181-
},
5182-
/*setIsNoInline=*/true,
5183-
/*forPrologue=*/false,
5184-
/*isPerformanceConstraint=*/false,
5185-
/*optionalLinkageOverride=*/nullptr, IGM.SwiftCoroCC,
5186-
/*transformAttributes=*/
5187-
[&IGM](llvm::AttributeList &attrs) {
5188-
IGM.addSwiftCoroAttributes(attrs, 0);
5189-
});
5190-
}
5191-
5192-
static llvm::Constant *getCoroDeallocFn(IRGenModule &IGM) {
5193-
auto isSwiftCoroCCAvailable = IGM.SwiftCoroCC == llvm::CallingConv::SwiftCoro;
5194-
return IGM.getOrCreateHelperFunction(
5195-
"_swift_coro_dealloc", IGM.VoidTy,
5196-
{IGM.CoroAllocatorPtrTy, IGM.Int8PtrTy},
5197-
[isSwiftCoroCCAvailable](IRGenFunction &IGF) {
5198-
auto parameters = IGF.collectParameters();
5199-
auto *allocator = parameters.claimNext();
5200-
auto *ptr = parameters.claimNext();
5201-
if (isSwiftCoroCCAvailable) {
5202-
// swiftcorocc is available, so if there's no allocator pointer,
5203-
// storage was allocated on the stack which will be naturally cleaned
5204-
// up when the coroutine's frame is "freed".
5205-
auto *nullAllocator = IGF.Builder.CreateCmp(
5206-
llvm::CmpInst::Predicate::ICMP_EQ, allocator,
5207-
llvm::ConstantPointerNull::get(
5208-
cast<llvm::PointerType>(allocator->getType())));
5209-
auto *bailBlock = IGF.createBasicBlock("null_allocator");
5210-
auto *normalBlock = IGF.createBasicBlock("nonnull_allocator");
5211-
IGF.Builder.CreateCondBr(nullAllocator, bailBlock, normalBlock);
5212-
IGF.Builder.emitBlock(bailBlock);
5213-
// Nothing to do here.
5214-
IGF.Builder.CreateRetVoid();
5215-
// Start emitting the "normal" block.
5216-
IGF.Builder.emitBlock(normalBlock);
5217-
}
5218-
auto shouldDeallocateImmediatelyFlag = CoroAllocatorFlags(0);
5219-
shouldDeallocateImmediatelyFlag.setShouldDeallocateImmediately(true);
5220-
auto *flagsPtr = IGF.Builder.CreateInBoundsGEP(
5221-
IGF.IGM.CoroAllocatorTy, allocator,
5222-
{llvm::ConstantInt::get(IGF.IGM.Int32Ty, 0),
5223-
llvm::ConstantInt::get(IGF.IGM.Int32Ty, 0)});
5224-
auto *flags = IGF.Builder.CreateLoad(
5225-
Address(flagsPtr, IGF.IGM.Int32Ty, Alignment(4)), "");
5226-
auto *deallocDeferringAllocator = IGF.Builder.CreateAnd(
5227-
flags,
5228-
llvm::APInt(IGF.IGM.Int32Ty->getBitWidth(),
5229-
shouldDeallocateImmediatelyFlag.getOpaqueValue()));
5230-
auto *isDeallocDeferringAllocator = IGF.Builder.CreateICmpNE(
5231-
deallocDeferringAllocator,
5232-
llvm::ConstantInt::get(IGF.IGM.Int32Ty, 0));
5233-
auto *deferringAllocatorBlock =
5234-
IGF.createBasicBlock("deferring_allocator");
5235-
auto *normalBlock = IGF.createBasicBlock("normal");
5236-
IGF.Builder.CreateCondBr(isDeallocDeferringAllocator,
5237-
deferringAllocatorBlock, normalBlock);
5238-
IGF.Builder.emitBlock(deferringAllocatorBlock);
5239-
// Nothing to do here.
5240-
IGF.Builder.CreateRetVoid();
5241-
// Start emitting the "normal" block.
5242-
IGF.Builder.emitBlock(normalBlock);
5243-
auto *calleePtr = IGF.Builder.CreateInBoundsGEP(
5244-
IGF.IGM.CoroAllocatorTy, allocator,
5245-
{llvm::ConstantInt::get(IGF.IGM.Int32Ty, 0),
5246-
llvm::ConstantInt::get(IGF.IGM.Int32Ty, 2)});
5247-
auto *callee = IGF.Builder.CreateLoad(
5248-
Address(calleePtr, IGF.IGM.PtrTy, IGF.IGM.getPointerAlignment()),
5249-
"deallocate_fn");
5250-
auto fnPtr = FunctionPointer::createUnsigned(
5251-
FunctionPointer::Kind::Function, callee,
5252-
Signature(cast<llvm::FunctionType>(IGF.IGM.CoroDeallocateFnTy), {},
5253-
IGF.IGM.SwiftCC));
5254-
auto *call = IGF.Builder.CreateCall(fnPtr, {ptr});
5255-
call->setDoesNotThrow();
5256-
call->setCallingConv(IGF.IGM.SwiftCC);
5257-
IGF.Builder.CreateRetVoid();
5258-
},
5259-
/*setIsNoInline=*/true,
5260-
/*forPrologue=*/false,
5261-
/*isPerformanceConstraint=*/false,
5262-
/*optionalLinkageOverride=*/nullptr, IGM.SwiftCoroCC,
5263-
/*transformAttributes=*/
5264-
[&IGM](llvm::AttributeList &attrs) {
5265-
IGM.addSwiftCoroAttributes(attrs, 0);
5266-
});
5267-
}
5268-
52695135
void irgen::emitYieldOnce2CoroutineEntry(IRGenFunction &IGF,
52705136
CanSILFunctionType fnType,
52715137
llvm::Value *buffer,

lib/IRGen/GenCoro.cpp

Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include "llvm/IR/Module.h"
1919

2020
#include "Explosion.h"
21+
#include "GenCoro.h"
2122
#include "IRGenFunction.h"
2223
#include "IRGenModule.h"
2324

@@ -612,3 +613,138 @@ void IRGenFunction::emitTaskDeallocThrough(Address address) {
612613
call->setDoesNotThrow();
613614
call->setCallingConv(IGM.SwiftCC);
614615
}
616+
617+
llvm::Constant *swift::irgen::getCoroAllocFn(IRGenModule &IGM) {
618+
auto isSwiftCoroCCAvailable = IGM.SwiftCoroCC == llvm::CallingConv::SwiftCoro;
619+
return IGM.getOrCreateHelperFunction(
620+
"_swift_coro_alloc", IGM.Int8PtrTy, {IGM.CoroAllocatorPtrTy, IGM.SizeTy},
621+
[isSwiftCoroCCAvailable](IRGenFunction &IGF) {
622+
auto parameters = IGF.collectParameters();
623+
auto *allocator = parameters.claimNext();
624+
auto *size = parameters.claimNext();
625+
if (isSwiftCoroCCAvailable) {
626+
// swiftcorocc is available, so if there's no allocator pointer,
627+
// allocate storage on the stack and return a pointer to it without
628+
// popping the stack.
629+
auto *nullAllocator = IGF.Builder.CreateCmp(
630+
llvm::CmpInst::Predicate::ICMP_EQ, allocator,
631+
llvm::ConstantPointerNull::get(
632+
cast<llvm::PointerType>(allocator->getType())));
633+
auto *poplessReturn = IGF.createBasicBlock("popless");
634+
auto *normalReturn = IGF.createBasicBlock("normal");
635+
IGF.Builder.CreateCondBr(nullAllocator, poplessReturn, normalReturn);
636+
IGF.Builder.emitBlock(poplessReturn);
637+
// Emit the dynamic alloca.
638+
auto *alloca =
639+
IGF.Builder.IRBuilderBase::CreateAlloca(IGF.IGM.Int8Ty, size);
640+
alloca->setAlignment(llvm::Align(MaximumAlignment));
641+
auto *retPopless = IGF.Builder.CreateIntrinsic(
642+
IGF.IGM.VoidTy, llvm::Intrinsic::ret_popless, {});
643+
retPopless->setTailCallKind(
644+
llvm::CallInst::TailCallKind::TCK_MustTail);
645+
IGF.Builder.CreateRet(alloca);
646+
// Start emitting the "normal" block.
647+
IGF.Builder.emitBlock(normalReturn);
648+
}
649+
auto *calleePtr = IGF.Builder.CreateInBoundsGEP(
650+
IGF.IGM.CoroAllocatorTy, allocator,
651+
{llvm::ConstantInt::get(IGF.IGM.Int32Ty, 0),
652+
llvm::ConstantInt::get(IGF.IGM.Int32Ty, 1)});
653+
auto *callee = IGF.Builder.CreateLoad(
654+
Address(calleePtr, IGF.IGM.PtrTy, IGF.IGM.getPointerAlignment()),
655+
"allocate_fn");
656+
auto fnPtr = FunctionPointer::createUnsigned(
657+
FunctionPointer::Kind::Function, callee,
658+
Signature(cast<llvm::FunctionType>(IGF.IGM.CoroAllocateFnTy), {},
659+
IGF.IGM.SwiftCC));
660+
auto *call = IGF.Builder.CreateCall(fnPtr, {size});
661+
call->setDoesNotThrow();
662+
call->setCallingConv(IGF.IGM.SwiftCC);
663+
IGF.Builder.CreateRet(call);
664+
},
665+
/*setIsNoInline=*/true,
666+
/*forPrologue=*/false,
667+
/*isPerformanceConstraint=*/false,
668+
/*optionalLinkageOverride=*/nullptr, IGM.SwiftCoroCC,
669+
/*transformAttributes=*/
670+
[&IGM](llvm::AttributeList &attrs) {
671+
IGM.addSwiftCoroAttributes(attrs, 0);
672+
});
673+
}
674+
675+
llvm::Constant *swift::irgen::getCoroDeallocFn(IRGenModule &IGM) {
676+
auto isSwiftCoroCCAvailable = IGM.SwiftCoroCC == llvm::CallingConv::SwiftCoro;
677+
return IGM.getOrCreateHelperFunction(
678+
"_swift_coro_dealloc", IGM.VoidTy,
679+
{IGM.CoroAllocatorPtrTy, IGM.Int8PtrTy},
680+
[isSwiftCoroCCAvailable](IRGenFunction &IGF) {
681+
auto parameters = IGF.collectParameters();
682+
auto *allocator = parameters.claimNext();
683+
auto *ptr = parameters.claimNext();
684+
if (isSwiftCoroCCAvailable) {
685+
// swiftcorocc is available, so if there's no allocator pointer,
686+
// storage was allocated on the stack which will be naturally cleaned
687+
// up when the coroutine's frame is "freed".
688+
auto *nullAllocator = IGF.Builder.CreateCmp(
689+
llvm::CmpInst::Predicate::ICMP_EQ, allocator,
690+
llvm::ConstantPointerNull::get(
691+
cast<llvm::PointerType>(allocator->getType())));
692+
auto *bailBlock = IGF.createBasicBlock("null_allocator");
693+
auto *normalBlock = IGF.createBasicBlock("nonnull_allocator");
694+
IGF.Builder.CreateCondBr(nullAllocator, bailBlock, normalBlock);
695+
IGF.Builder.emitBlock(bailBlock);
696+
// Nothing to do here.
697+
IGF.Builder.CreateRetVoid();
698+
// Start emitting the "normal" block.
699+
IGF.Builder.emitBlock(normalBlock);
700+
}
701+
auto shouldDeallocateImmediatelyFlag = CoroAllocatorFlags(0);
702+
shouldDeallocateImmediatelyFlag.setShouldDeallocateImmediately(true);
703+
auto *flagsPtr = IGF.Builder.CreateInBoundsGEP(
704+
IGF.IGM.CoroAllocatorTy, allocator,
705+
{llvm::ConstantInt::get(IGF.IGM.Int32Ty, 0),
706+
llvm::ConstantInt::get(IGF.IGM.Int32Ty, 0)});
707+
auto *flags = IGF.Builder.CreateLoad(
708+
Address(flagsPtr, IGF.IGM.Int32Ty, Alignment(4)), "");
709+
auto *deallocDeferringAllocator = IGF.Builder.CreateAnd(
710+
flags,
711+
llvm::APInt(IGF.IGM.Int32Ty->getBitWidth(),
712+
shouldDeallocateImmediatelyFlag.getOpaqueValue()));
713+
auto *isDeallocDeferringAllocator = IGF.Builder.CreateICmpNE(
714+
deallocDeferringAllocator,
715+
llvm::ConstantInt::get(IGF.IGM.Int32Ty, 0));
716+
auto *deferringAllocatorBlock =
717+
IGF.createBasicBlock("deferring_allocator");
718+
auto *normalBlock = IGF.createBasicBlock("normal");
719+
IGF.Builder.CreateCondBr(isDeallocDeferringAllocator,
720+
deferringAllocatorBlock, normalBlock);
721+
IGF.Builder.emitBlock(deferringAllocatorBlock);
722+
// Nothing to do here.
723+
IGF.Builder.CreateRetVoid();
724+
// Start emitting the "normal" block.
725+
IGF.Builder.emitBlock(normalBlock);
726+
auto *calleePtr = IGF.Builder.CreateInBoundsGEP(
727+
IGF.IGM.CoroAllocatorTy, allocator,
728+
{llvm::ConstantInt::get(IGF.IGM.Int32Ty, 0),
729+
llvm::ConstantInt::get(IGF.IGM.Int32Ty, 2)});
730+
auto *callee = IGF.Builder.CreateLoad(
731+
Address(calleePtr, IGF.IGM.PtrTy, IGF.IGM.getPointerAlignment()),
732+
"deallocate_fn");
733+
auto fnPtr = FunctionPointer::createUnsigned(
734+
FunctionPointer::Kind::Function, callee,
735+
Signature(cast<llvm::FunctionType>(IGF.IGM.CoroDeallocateFnTy), {},
736+
IGF.IGM.SwiftCC));
737+
auto *call = IGF.Builder.CreateCall(fnPtr, {ptr});
738+
call->setDoesNotThrow();
739+
call->setCallingConv(IGF.IGM.SwiftCC);
740+
IGF.Builder.CreateRetVoid();
741+
},
742+
/*setIsNoInline=*/true,
743+
/*forPrologue=*/false,
744+
/*isPerformanceConstraint=*/false,
745+
/*optionalLinkageOverride=*/nullptr, IGM.SwiftCoroCC,
746+
/*transformAttributes=*/
747+
[&IGM](llvm::AttributeList &attrs) {
748+
IGM.addSwiftCoroAttributes(attrs, 0);
749+
});
750+
}

lib/IRGen/GenCoro.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
//===----- GenCoro.h - Code generation related to coroutines --------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2025 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
namespace swift {
14+
namespace irgen {
15+
16+
class IRGenModule;
17+
18+
llvm::Constant *getCoroAllocFn(IRGenModule &IGM);
19+
llvm::Constant *getCoroDeallocFn(IRGenModule &IGM);
20+
21+
} // end namespace irgen
22+
} // end namespace swift

0 commit comments

Comments
 (0)