Skip to content

Commit 0b8efc9

Browse files
authored
[SUA][IRGen] Change IRGen to emit calls to swift_coroFrameAlloc (#79384)
When TMO is enabled, change IRGen to pass the newly introduced runtime function `swift_coroFrameAlloc` (and pass an additional argument — the hash value) instead of `malloc` when it inserts calls to `coro_id_retcon_once`. The hashValue is computed based on the current function name (computed in `getDiscriminatorForString`) rdar://141235957
1 parent 8337815 commit 0b8efc9

13 files changed

+225
-30
lines changed

include/swift/AST/IRGenOptions.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -488,6 +488,9 @@ class IRGenOptions {
488488

489489
unsigned EmitAsyncFramePushPopMetadata : 1;
490490

491+
// Whether to emit typed malloc during coroutine frame allocation.
492+
unsigned EmitTypeMallocForCoroFrame : 1;
493+
491494
// Whether to use the yield_once ABI when emitting yield_once_2 coroutines.
492495
unsigned EmitYieldOnce2AsYieldOnce : 1;
493496

@@ -597,8 +600,9 @@ class IRGenOptions {
597600
DisableReadonlyStaticObjects(false), CollocatedMetadataFunctions(false),
598601
ColocateTypeDescriptors(true), UseRelativeProtocolWitnessTables(false),
599602
UseFragileResilientProtocolWitnesses(false), EnableHotColdSplit(false),
600-
EmitAsyncFramePushPopMetadata(true), EmitYieldOnce2AsYieldOnce(true),
601-
AsyncFramePointerAll(false), UseProfilingMarkerThunks(false),
603+
EmitAsyncFramePushPopMetadata(true), EmitTypeMallocForCoroFrame(false),
604+
EmitYieldOnce2AsYieldOnce(true), AsyncFramePointerAll(false),
605+
UseProfilingMarkerThunks(false),
602606
DebugInfoForProfiling(false), CmdArgs(),
603607
SanitizeCoverage(llvm::SanitizerCoverageOptions()),
604608
TypeInfoFilter(TypeInfoDumpFilter::All),

include/swift/Option/FrontendOptions.td

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1345,6 +1345,13 @@ def disable_async_frame_push_pop_metadata :
13451345
Flag<["-"], "disable-async-frame-push-pop-metadata">,
13461346
HelpText<"Disable async frame push pop metadata">;
13471347

1348+
def enable_emit_type_malloc_for_coro_frame :
1349+
Flag<["-"], "enable-emit-type-malloc-for-coro-frame">,
1350+
HelpText<"Enable emitting typed malloc for coroutine frame allocation">;
1351+
def disable_emit_type_malloc_for_coro_frame :
1352+
Flag<["-"], "disable-emit-type-malloc-for-coro-frame">,
1353+
HelpText<"Disable emitting typed malloc for coroutine frame allocation">;
1354+
13481355
def enable_async_frame_pointer_all :
13491356
Flag<["-"], "enable-async-frame-pointer-all">,
13501357
HelpText<"Always emit async frame stack frames (frame-pointer=all)">;

lib/Frontend/CompilerInvocation.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3630,6 +3630,10 @@ static bool ParseIRGenArgs(IRGenOptions &Opts, ArgList &Args,
36303630
Args.hasFlag(OPT_enable_async_frame_push_pop_metadata,
36313631
OPT_disable_async_frame_push_pop_metadata,
36323632
Opts.EmitAsyncFramePushPopMetadata);
3633+
Opts.EmitTypeMallocForCoroFrame =
3634+
Args.hasFlag(OPT_enable_emit_type_malloc_for_coro_frame,
3635+
OPT_disable_emit_type_malloc_for_coro_frame,
3636+
Opts.EmitTypeMallocForCoroFrame);
36333637
Opts.AsyncFramePointerAll = Args.hasFlag(OPT_enable_async_frame_pointer_all,
36343638
OPT_disable_async_frame_pointer_all,
36353639
Opts.AsyncFramePointerAll);

lib/IRGen/GenCall.cpp

Lines changed: 31 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4818,20 +4818,41 @@ emitRetconCoroutineEntry(IRGenFunction &IGF, CanSILFunctionType fnType,
48184818
auto prototype =
48194819
IGF.IGM.getOpaquePtr(IGF.IGM.getAddrOfContinuationPrototype(fnType));
48204820

4821-
// Use malloc and free as our allocator.
4822-
auto allocFn = IGF.IGM.getOpaquePtr(IGF.IGM.getMallocFn());
4821+
4822+
4823+
// Use free as our deallocator.
48234824
auto deallocFn = IGF.IGM.getOpaquePtr(IGF.IGM.getFreeFn());
48244825

48254826
// Call the right 'llvm.coro.id.retcon' variant.
48264827
llvm::Value *buffer = emission.getCoroutineBuffer();
4827-
llvm::Value *id = IGF.Builder.CreateIntrinsicCall(idIntrinsic, {
4828-
llvm::ConstantInt::get(IGF.IGM.Int32Ty, bufferSize.getValue()),
4829-
llvm::ConstantInt::get(IGF.IGM.Int32Ty, bufferAlignment.getValue()),
4830-
buffer,
4831-
prototype,
4832-
allocFn,
4833-
deallocFn
4834-
});
4828+
4829+
llvm::Value *id;
4830+
if (IGF.getOptions().EmitTypeMallocForCoroFrame) {
4831+
// Use swift_coroFrameAlloc as our allocator.
4832+
auto coroAllocFn = IGF.IGM.getOpaquePtr(IGF.IGM.getCoroFrameAllocFn());
4833+
auto mallocTypeId = IGF.getMallocTypeId();
4834+
id = IGF.Builder.CreateIntrinsicCall(idIntrinsic, {
4835+
llvm::ConstantInt::get(IGF.IGM.Int32Ty, bufferSize.getValue()),
4836+
llvm::ConstantInt::get(IGF.IGM.Int32Ty, bufferAlignment.getValue()),
4837+
buffer,
4838+
prototype,
4839+
coroAllocFn,
4840+
deallocFn,
4841+
mallocTypeId
4842+
});
4843+
} else {
4844+
// Use mallocas our allocator.
4845+
auto allocFn = IGF.IGM.getOpaquePtr(IGF.IGM.getMallocFn());
4846+
id = IGF.Builder.CreateIntrinsicCall(idIntrinsic, {
4847+
llvm::ConstantInt::get(IGF.IGM.Int32Ty, bufferSize.getValue()),
4848+
llvm::ConstantInt::get(IGF.IGM.Int32Ty, bufferAlignment.getValue()),
4849+
buffer,
4850+
prototype,
4851+
allocFn,
4852+
deallocFn
4853+
});
4854+
}
4855+
48354856

48364857
// Call 'llvm.coro.begin', just for consistency with the normal pattern.
48374858
// This serves as a handle that we can pass around to other intrinsics.

lib/IRGen/GenFunc.cpp

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1459,13 +1459,30 @@ class CoroPartialApplicationForwarderEmission
14591459
cast<SILFunctionType>(
14601460
unsubstType->mapTypeOutOfContext()->getCanonicalType())));
14611461

1462-
// Use malloc and free as our allocator.
1463-
auto allocFn = subIGF.IGM.getOpaquePtr(subIGF.IGM.getMallocFn());
1462+
1463+
// Use free as our allocator.
14641464
auto deallocFn = subIGF.IGM.getOpaquePtr(subIGF.IGM.getFreeFn());
14651465

14661466
// Call the right 'llvm.coro.id.retcon' variant.
14671467
llvm::Value *buffer = origParams.claimNext();
1468-
llvm::Value *id = subIGF.Builder.CreateIntrinsicCall(
1468+
llvm::Value *id;
1469+
if (subIGF.IGM.getOptions().EmitTypeMallocForCoroFrame) {
1470+
// Use swift_coroFrameAlloc as our allocator.
1471+
auto coroAllocFn = subIGF.IGM.getOpaquePtr(subIGF.IGM.getCoroFrameAllocFn());
1472+
auto mallocTypeId = subIGF.getMallocTypeId();
1473+
id = subIGF.Builder.CreateIntrinsicCall(
1474+
llvm::Intrinsic::coro_id_retcon_once,
1475+
{llvm::ConstantInt::get(
1476+
subIGF.IGM.Int32Ty,
1477+
getYieldOnceCoroutineBufferSize(subIGF.IGM).getValue()),
1478+
llvm::ConstantInt::get(
1479+
subIGF.IGM.Int32Ty,
1480+
getYieldOnceCoroutineBufferAlignment(subIGF.IGM).getValue()),
1481+
buffer, prototype, coroAllocFn, deallocFn, mallocTypeId});
1482+
} else {
1483+
// Use malloc as our allocator.
1484+
auto allocFn = subIGF.IGM.getOpaquePtr(subIGF.IGM.getMallocFn());
1485+
id = subIGF.Builder.CreateIntrinsicCall(
14691486
llvm::Intrinsic::coro_id_retcon_once,
14701487
{llvm::ConstantInt::get(
14711488
subIGF.IGM.Int32Ty,
@@ -1474,6 +1491,7 @@ class CoroPartialApplicationForwarderEmission
14741491
subIGF.IGM.Int32Ty,
14751492
getYieldOnceCoroutineBufferAlignment(subIGF.IGM).getValue()),
14761493
buffer, prototype, allocFn, deallocFn});
1494+
}
14771495

14781496
// Call 'llvm.coro.begin', just for consistency with the normal pattern.
14791497
// This serves as a handle that we can pass around to other intrinsics.

lib/IRGen/GenPointerAuth.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -767,3 +767,7 @@ void ConstantAggregateBuilderBase::addSignedPointer(llvm::Constant *pointer,
767767
addSignedPointer(pointer, schema.getKey(), schema.isAddressDiscriminated(),
768768
llvm::ConstantInt::get(IGM().Int64Ty, otherDiscriminator));
769769
}
770+
771+
llvm::ConstantInt* IRGenFunction::getMallocTypeId() {
772+
return getDiscriminatorForString(IGM, CurFn->getName());
773+
}

lib/IRGen/IRGenFunction.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,8 @@ class IRGenFunction {
142142
Address getCalleeTypedErrorResultSlot(SILType errorType);
143143
void setCalleeTypedErrorResultSlot(Address addr);
144144

145+
llvm::ConstantInt* getMallocTypeId();
146+
145147
/// Are we currently emitting a coroutine?
146148
bool isCoroutine() {
147149
return CoroutineHandle != nullptr;

test/IRGen/yield_once.sil

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ sil @marker : $(Builtin.Int32) -> ()
1010
// CHECK-SAME: [[CORO_ATTRIBUTES:#[0-9]+]]
1111
sil @test_simple : $@yield_once () -> () {
1212
entry:
13-
// CHECK-32: [[ID:%.*]] = call token @llvm.coro.id.retcon.once(i32 [[BUFFER_SIZE]], i32 [[BUFFER_ALIGN:4]], ptr %0, ptr @"$sIetA_TC", ptr @malloc, ptr @free)
14-
// CHECK-64: [[ID:%.*]] = call token @llvm.coro.id.retcon.once(i32 [[BUFFER_SIZE]], i32 [[BUFFER_ALIGN:8]], ptr %0, ptr @"$sIetA_TC", ptr @malloc, ptr @free)
13+
// CHECK-32: [[ID:%.*]] = call token (i32, i32, ptr, ptr, ptr, ptr, ...) @llvm.coro.id.retcon.once(i32 [[BUFFER_SIZE]], i32 [[BUFFER_ALIGN:4]], ptr %0, ptr @"$sIetA_TC", ptr @malloc, ptr @free)
14+
// CHECK-64: [[ID:%.*]] = call token (i32, i32, ptr, ptr, ptr, ptr, ...) @llvm.coro.id.retcon.once(i32 [[BUFFER_SIZE]], i32 [[BUFFER_ALIGN:8]], ptr %0, ptr @"$sIetA_TC", ptr @malloc, ptr @free)
1515
// CHECK-NEXT: [[BEGIN:%.*]] = call ptr @llvm.coro.begin(token [[ID]], ptr null)
1616

1717
// CHECK-NEXT: call swiftcc void @marker(i32 1000)

test/IRGen/yield_once_big.sil

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,8 @@ entry:
4444
// CHECK-64-SAME: , align 8
4545

4646
// Coroutine setup.
47-
// CHECK-32-NEXT: [[ID:%.*]] = call token @llvm.coro.id.retcon.once(i32 [[BUFFER_SIZE]], i32 [[BUFFER_ALIGN:4]], ptr %0, ptr @"$s14yield_once_big3BigVyxGAA9SomeClassCRbzlIetAYi_TC", ptr @malloc, ptr @free)
48-
// CHECK-64-NEXT: [[ID:%.*]] = call token @llvm.coro.id.retcon.once(i32 [[BUFFER_SIZE]], i32 [[BUFFER_ALIGN:8]], ptr %0, ptr @"$s14yield_once_big3BigVyxGAA9SomeClassCRbzlIetAYi_TC", ptr @malloc, ptr @free)
47+
// CHECK-32-NEXT: [[ID:%.*]] = call token (i32, i32, ptr, ptr, ptr, ptr, ...) @llvm.coro.id.retcon.once(i32 [[BUFFER_SIZE]], i32 [[BUFFER_ALIGN:4]], ptr %0, ptr @"$s14yield_once_big3BigVyxGAA9SomeClassCRbzlIetAYi_TC", ptr @malloc, ptr @free)
48+
// CHECK-64-NEXT: [[ID:%.*]] = call token (i32, i32, ptr, ptr, ptr, ptr, ...) @llvm.coro.id.retcon.once(i32 [[BUFFER_SIZE]], i32 [[BUFFER_ALIGN:8]], ptr %0, ptr @"$s14yield_once_big3BigVyxGAA9SomeClassCRbzlIetAYi_TC", ptr @malloc, ptr @free)
4949
// CHECK-NEXT: [[BEGIN:%.*]] = call ptr @llvm.coro.begin(token [[ID]], ptr null)
5050
// CHECK-NEXT: store ptr
5151

@@ -181,8 +181,8 @@ entry(%arg : $*BigWrapper<C>):
181181
// CHECK-64-SAME: , align 8
182182

183183
// Coroutine setup.
184-
// CHECK-32-NEXT: [[ID:%.*]] = call token @llvm.coro.id.retcon.once(i32 [[BUFFER_SIZE]], i32 [[BUFFER_ALIGN:4]], ptr %0, ptr @"$s14yield_once_big10BigWrapperVyxGAA0D0VyxGAA9SomeClassCRbzlIetAnYn_TC", ptr @malloc, ptr @free)
185-
// CHECK-64-NEXT: [[ID:%.*]] = call token @llvm.coro.id.retcon.once(i32 [[BUFFER_SIZE]], i32 [[BUFFER_ALIGN:8]], ptr %0, ptr @"$s14yield_once_big10BigWrapperVyxGAA0D0VyxGAA9SomeClassCRbzlIetAnYn_TC", ptr @malloc, ptr @free)
184+
// CHECK-32-NEXT: [[ID:%.*]] = call token (i32, i32, ptr, ptr, ptr, ptr, ...) @llvm.coro.id.retcon.once(i32 [[BUFFER_SIZE]], i32 [[BUFFER_ALIGN:4]], ptr %0, ptr @"$s14yield_once_big10BigWrapperVyxGAA0D0VyxGAA9SomeClassCRbzlIetAnYn_TC", ptr @malloc, ptr @free)
185+
// CHECK-64-NEXT: [[ID:%.*]] = call token (i32, i32, ptr, ptr, ptr, ptr, ...) @llvm.coro.id.retcon.once(i32 [[BUFFER_SIZE]], i32 [[BUFFER_ALIGN:8]], ptr %0, ptr @"$s14yield_once_big10BigWrapperVyxGAA0D0VyxGAA9SomeClassCRbzlIetAnYn_TC", ptr @malloc, ptr @free)
186186
// CHECK-NEXT: [[BEGIN:%.*]] = call ptr @llvm.coro.begin(token [[ID]], ptr null)
187187
// CHECK-NEXT: store ptr
188188

test/IRGen/yield_once_biggish.sil

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,8 @@ entry:
4040
// CHECK-64-SAME: , align 8
4141

4242
// Coroutine setup.
43-
// CHECK-32-NEXT: [[ID:%.*]] = call token @llvm.coro.id.retcon.once(i32 [[BUFFER_SIZE]], i32 [[BUFFER_ALIGN:4]], ptr %0, ptr @"$s18yield_once_biggish7BiggishVyxGAA9SomeClassCRbzlIetAYx_TC", ptr @malloc, ptr @free)
44-
// CHECK-64-NEXT: [[ID:%.*]] = call token @llvm.coro.id.retcon.once(i32 [[BUFFER_SIZE]], i32 [[BUFFER_ALIGN:8]], ptr %0, ptr @"$s18yield_once_biggish7BiggishVyxGAA9SomeClassCRbzlIetAYx_TC", ptr @malloc, ptr @free)
43+
// CHECK-32-NEXT: [[ID:%.*]] = call token (i32, i32, ptr, ptr, ptr, ptr, ...) @llvm.coro.id.retcon.once(i32 [[BUFFER_SIZE]], i32 [[BUFFER_ALIGN:4]], ptr %0, ptr @"$s18yield_once_biggish7BiggishVyxGAA9SomeClassCRbzlIetAYx_TC", ptr @malloc, ptr @free)
44+
// CHECK-64-NEXT: [[ID:%.*]] = call token (i32, i32, ptr, ptr, ptr, ptr, ...) @llvm.coro.id.retcon.once(i32 [[BUFFER_SIZE]], i32 [[BUFFER_ALIGN:8]], ptr %0, ptr @"$s18yield_once_biggish7BiggishVyxGAA9SomeClassCRbzlIetAYx_TC", ptr @malloc, ptr @free)
4545
// CHECK-NEXT: [[BEGIN:%.*]] = call ptr @llvm.coro.begin(token [[ID]], ptr null)
4646
// CHECK-NEXT: store ptr
4747
// CHECK-NEXT: call swiftcc void @marker(i32 1000)

0 commit comments

Comments
 (0)