Skip to content

Commit c92805e

Browse files
Merge pull request swiftlang#38693 from aschwaighofer/irgen_earliest_insert_pt
IRGen: Define and use an earliest insertion point
2 parents 1e6402a + 8cdde7a commit c92805e

File tree

6 files changed

+75
-17
lines changed

6 files changed

+75
-17
lines changed

lib/IRGen/GenCall.cpp

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,12 @@ Alignment IRGenModule::getAsyncContextAlignment() const {
174174
void IRGenFunction::setupAsync(unsigned asyncContextIndex) {
175175
llvm::Value *c = CurFn->getArg(asyncContextIndex);
176176
asyncContextLocation = createAlloca(c->getType(), IGM.getPointerAlignment());
177-
Builder.CreateStore(c, asyncContextLocation);
177+
178+
IRBuilder builder(IGM.getLLVMContext(), IGM.DebugInfo != nullptr);
179+
// Insert the stores after the coro.begin.
180+
builder.SetInsertPoint(getEarliestInsertionPoint()->getParent(),
181+
getEarliestInsertionPoint()->getIterator());
182+
builder.CreateStore(c, asyncContextLocation);
178183
}
179184

180185
llvm::Value *IRGenFunction::getAsyncTask() {
@@ -3771,6 +3776,11 @@ emitRetconCoroutineEntry(IRGenFunction &IGF, CanSILFunctionType fnType,
37713776
// Set the coroutine handle; this also flags that is a coroutine so that
37723777
// e.g. dynamic allocas use the right code generation.
37733778
IGF.setCoroutineHandle(hdl);
3779+
3780+
auto *pt = IGF.Builder.IRBuilderBase::CreateAlloca(IGF.IGM.Int1Ty,
3781+
/*array size*/ nullptr,
3782+
"earliest insert point");
3783+
IGF.setEarliestInsertionPoint(pt);
37743784
}
37753785

37763786
void irgen::emitAsyncFunctionEntry(IRGenFunction &IGF,
@@ -3796,6 +3806,11 @@ void irgen::emitAsyncFunctionEntry(IRGenFunction &IGF,
37963806
// Set the coroutine handle; this also flags that is a coroutine so that
37973807
// e.g. dynamic allocas use the right code generation.
37983808
IGF.setCoroutineHandle(hdl);
3809+
auto *pt = IGF.Builder.IRBuilderBase::CreateAlloca(IGF.IGM.Int1Ty,
3810+
/*array size*/ nullptr,
3811+
"earliest insert point");
3812+
IGF.setEarliestInsertionPoint(pt);
3813+
IGF.setupAsync(asyncContextIndex);
37993814
}
38003815

38013816
void irgen::emitYieldOnceCoroutineEntry(
@@ -4054,6 +4069,11 @@ Address IRGenFunction::createErrorResultSlot(SILType errorType, bool isAsync) {
40544069
auto addr = createAlloca(errorTI.getStorageType(),
40554070
errorTI.getFixedAlignment(), "swifterror");
40564071

4072+
if (!isAsync) {
4073+
builder.SetInsertPoint(getEarliestInsertionPoint()->getParent(),
4074+
getEarliestInsertionPoint()->getIterator());
4075+
}
4076+
40574077
// Only add the swifterror attribute on ABIs that pass it in a register.
40584078
// We create a shadow stack location of the swifterror parameter for the
40594079
// debugger on platforms that pass swifterror by reference and so we can't
@@ -4131,6 +4151,7 @@ void IRGenFunction::emitPrologue() {
41314151
AllocaIP = Builder.IRBuilderBase::CreateAlloca(IGM.Int1Ty,
41324152
/*array size*/ nullptr,
41334153
"alloca point");
4154+
EarliestIP = AllocaIP;
41344155
}
41354156

41364157
/// Emit a branch to the return block and set the insert point there.
@@ -4170,6 +4191,8 @@ bool IRGenFunction::emitBranchToReturnBB() {
41704191

41714192
/// Emit the epilogue for the function.
41724193
void IRGenFunction::emitEpilogue() {
4194+
if (EarliestIP != AllocaIP)
4195+
EarliestIP->eraseFromParent();
41734196
// Destroy the alloca insertion point.
41744197
AllocaIP->eraseFromParent();
41754198
}

lib/IRGen/GenFunc.cpp

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1275,8 +1275,6 @@ static llvm::Value *emitPartialApplicationForwarder(IRGenModule &IGM,
12751275
FunctionPointer::Kind(
12761276
FunctionPointer::BasicKind::AsyncFunctionPointer)));
12771277

1278-
subIGF.setupAsync(asyncContextIdx);
1279-
12801278
//auto *calleeAFP = staticFnPtr->getDirectPointer();
12811279
LinkEntity entity = LinkEntity::forPartialApplyForwarder(fwd);
12821280
assert(!asyncFunctionPtr &&

lib/IRGen/GenThunk.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -255,7 +255,6 @@ void IRGenThunk::emit() {
255255
auto asyncContextIdx = Signature::forAsyncEntry(
256256
IGF.IGM, origTy, /*useSpecialConvention*/ false)
257257
.getAsyncContextIndex();
258-
IGF.setupAsync(asyncContextIdx);
259258

260259
auto entity = LinkEntity::forDispatchThunk(declRef);
261260
emitAsyncFunctionEntry(IGF, *asyncLayout, entity, asyncContextIdx);

lib/IRGen/IRGenFunction.h

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -364,8 +364,20 @@ class IRGenFunction {
364364
private:
365365
llvm::Instruction *AllocaIP;
366366
const SILDebugScope *DbgScope;
367+
/// The insertion point where we should but instructions we would normally put
368+
/// at the beginning of the function. LLVM's coroutine lowering really does
369+
/// not like it if we put instructions with side-effectrs before the
370+
/// coro.begin.
371+
llvm::Instruction *EarliestIP;
367372

368-
//--- Reference-counting methods -----------------------------------------------
373+
public:
374+
void setEarliestInsertionPoint(llvm::Instruction *inst) { EarliestIP = inst; }
375+
/// Returns the first insertion point before which we should insert
376+
/// instructions which have side-effects.
377+
llvm::Instruction *getEarliestInsertionPoint() const { return EarliestIP; }
378+
379+
//--- Reference-counting methods
380+
//-----------------------------------------------
369381
public:
370382
// Returns the default atomicity of the module.
371383
Atomicity getDefaultAtomicity();

lib/IRGen/IRGenSIL.cpp

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -687,7 +687,8 @@ class IRGenSILFunction :
687687
return;
688688

689689
llvm::IRBuilder<> ZeroInitBuilder(AI->getNextNode());
690-
690+
ZeroInitBuilder.SetInsertPoint(getEarliestInsertionPoint()->getParent(),
691+
getEarliestInsertionPoint()->getIterator());
691692
// No debug location is how LLVM marks prologue instructions.
692693
ZeroInitBuilder.SetCurrentDebugLocation(nullptr);
693694
ZeroInitBuilder.CreateMemSet(
@@ -1731,12 +1732,6 @@ IRGenSILFunction::IRGenSILFunction(IRGenModule &IGM, SILFunction *f)
17311732
if (f->isDynamicallyReplaceable() && !f->isAsync()) {
17321733
IGM.createReplaceableProlog(*this, f);
17331734
}
1734-
1735-
if (f->getLoweredFunctionType()->isAsync()) {
1736-
setupAsync(Signature::forAsyncEntry(IGM, f->getLoweredFunctionType(),
1737-
/*useSpecialConvention*/ false)
1738-
.getAsyncContextIndex());
1739-
}
17401735
}
17411736

17421737
IRGenSILFunction::~IRGenSILFunction() {
@@ -1935,11 +1930,6 @@ static void emitEntryPointArgumentsNativeCC(IRGenSILFunction &IGF,
19351930
witnessMetadata);
19361931
}
19371932

1938-
// Bind the error result by popping it off the parameter list.
1939-
if (funcTy->hasErrorResult() && !funcTy->isAsync()) {
1940-
IGF.setCallerErrorResultSlot(emission->getCallerErrorResultArgument());
1941-
}
1942-
19431933
// The coroutine context should be the first parameter.
19441934
switch (funcTy->getCoroutineKind()) {
19451935
case SILCoroutineKind::None:
@@ -1965,6 +1955,11 @@ static void emitEntryPointArgumentsNativeCC(IRGenSILFunction &IGF,
19651955
}
19661956
}
19671957

1958+
// Bind the error result by popping it off the parameter list.
1959+
if (funcTy->hasErrorResult() && !funcTy->isAsync()) {
1960+
IGF.setCallerErrorResultSlot(emission->getCallerErrorResultArgument());
1961+
}
1962+
19681963
SILFunctionConventions conv(funcTy, IGF.getSILModule());
19691964

19701965
// The 'self' argument might be in the context position, which is
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// RUN: %target-swift-frontend -module-name A -enable-implicit-dynamic -emit-ir %s | %FileCheck %s
2+
3+
4+
extension Int {
5+
public struct Thing {
6+
var _int: Int
7+
init(_ int: Int) {
8+
self._int = int
9+
}
10+
}
11+
12+
public var thing: Thing {
13+
get { Thing(self) }
14+
// Make sure the initialization of `thing` is after the dynamic replacement
15+
// check. Coro splitting does not like memsets before the coro.begin.
16+
17+
// CHECK: define{{.*}} swiftcc { i8*, %TSi1AE5ThingV* } @"$sSi1AE5thingSiAAE5ThingVvM"
18+
// CHECK: call i8* @swift_getFunctionReplacement
19+
// CHECK: br
20+
// CHECK: original_entry:
21+
// CHECK: [[FRAMEPTR:%.*]] = bitcast i8* %0 to
22+
// CHECK: [[THING:%.*]] = getelementptr inbounds {{.*}}* [[FRAMEPTR]], i32 0
23+
// CHECK: [[THING2:%.*]] = bitcast %TSi1AE5ThingV* [[THING]] to i8*
24+
// CHECK: call void @llvm.memset{{.*}}(i8* {{.*}} [[THING2]]
25+
// CHECK: ret
26+
_modify {
27+
var thing = Thing(self)
28+
yield &thing
29+
}
30+
}
31+
}

0 commit comments

Comments
 (0)