Skip to content

Commit d03a03e

Browse files
authored
Merge pull request #41448 from gottesmm/debug-info-move-vars
[move-function] Teach debug info how to handle reinits properly of vars.
2 parents 487234c + 65e20e7 commit d03a03e

File tree

4 files changed

+226
-47
lines changed

4 files changed

+226
-47
lines changed

lib/IRGen/IRGenDebugInfo.cpp

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,7 @@ class IRGenDebugInfoImpl : public IRGenDebugInfo {
216216
bool buildDebugInfoExpression(const SILDebugVariable &VarInfo,
217217
SmallVectorImpl<uint64_t> &Operands);
218218

219+
/// Emit a dbg.declare at the current insertion point in Builder.
219220
void emitVariableDeclaration(IRBuilder &Builder,
220221
ArrayRef<llvm::Value *> Storage,
221222
DebugTypeInfo Ty, const SILDebugScope *DS,
@@ -224,6 +225,7 @@ class IRGenDebugInfoImpl : public IRGenDebugInfo {
224225
IndirectionKind = DirectValue,
225226
ArtificialKind = RealValue,
226227
AddrDbgInstrKind = AddrDbgInstrKind::DbgDeclare);
228+
227229
void emitDbgIntrinsic(IRBuilder &Builder, llvm::Value *Storage,
228230
llvm::DILocalVariable *Var, llvm::DIExpression *Expr,
229231
unsigned Line, unsigned Col, llvm::DILocalScope *Scope,
@@ -2643,7 +2645,6 @@ void IRGenDebugInfoImpl::emitDbgIntrinsic(
26432645
auto *InlinedAt = createInlinedAt(DS);
26442646
auto DL =
26452647
llvm::DILocation::get(IGM.getLLVMContext(), Line, Col, Scope, InlinedAt);
2646-
auto *BB = Builder.GetInsertBlock();
26472648

26482649
// An alloca may only be described by exactly one dbg.declare.
26492650
if (isa<llvm::AllocaInst>(Storage) &&
@@ -2692,17 +2693,25 @@ void IRGenDebugInfoImpl::emitDbgIntrinsic(
26922693
};
26932694
DbgInserter inserter{DBuilder, AddrDInstKind};
26942695

2695-
// If we have a single alloca, just insert the debug in
2696+
// If we have a single alloca...
26962697
if (auto *Alloca = dyn_cast<llvm::AllocaInst>(Storage)) {
2697-
auto *ParentBB = Alloca->getParent();
2698-
auto InsertBefore = std::next(Alloca->getIterator());
2699-
if (InsertBefore != ParentBB->end())
2698+
auto *ParentBB = Builder.GetInsertBlock();
2699+
auto InsertBefore = Builder.GetInsertPoint();
2700+
2701+
if (AddrDInstKind == AddrDbgInstrKind::DbgDeclare) {
2702+
ParentBB = Alloca->getParent();
2703+
InsertBefore = std::next(Alloca->getIterator());
2704+
}
2705+
2706+
if (InsertBefore != ParentBB->end()) {
27002707
inserter.insert(Alloca, Var, Expr, DL, &*InsertBefore);
2701-
else
2708+
} else {
27022709
inserter.insert(Alloca, Var, Expr, DL, ParentBB);
2710+
}
27032711
return;
27042712
}
27052713

2714+
auto *BB = Builder.GetInsertBlock();
27062715
if ((isa<llvm::IntrinsicInst>(Storage) &&
27072716
cast<llvm::IntrinsicInst>(Storage)->getIntrinsicID() ==
27082717
llvm::Intrinsic::coro_alloca_get)) {

lib/IRGen/IRGenSIL.cpp

Lines changed: 69 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -893,19 +893,44 @@ class IRGenSILFunction :
893893
/// Unconditionally emit a stack shadow copy of an \c llvm::Value.
894894
llvm::Value *emitShadowCopy(llvm::Value *Storage, const SILDebugScope *Scope,
895895
SILDebugVariable VarInfo,
896-
llvm::Optional<Alignment> _Align, bool Init) {
896+
llvm::Optional<Alignment> _Align, bool Init,
897+
bool WasMoved) {
897898
auto Align = _Align.getValueOr(IGM.getPointerAlignment());
898899
unsigned ArgNo = VarInfo.ArgNo;
899900
auto &Alloca = ShadowStackSlots[{ArgNo, {Scope, VarInfo.Name}}];
901+
900902
if (!Alloca.isValid())
901903
Alloca = createAlloca(Storage->getType(), Align, VarInfo.Name + ".debug");
902-
assert(canAllocaStoreValue(Alloca.getAddress(), Storage, VarInfo, Scope) &&
904+
905+
// If our value was ever moved, we may be reinitializing the shadow
906+
// copy. Insert the bit cast so that the types line up and we do not get the
907+
// duplicate shadow copy error (which triggers based off of type
908+
// differences).
909+
auto *Address = Alloca.getAddress();
910+
if (WasMoved) {
911+
auto nonPtrAllocaType =
912+
cast<llvm::PointerType>(Address->getType())->getElementType();
913+
if (nonPtrAllocaType != Storage->getType())
914+
Address = Builder.CreateBitOrPointerCast(
915+
Address, llvm::PointerType::get(Storage->getType(), 0));
916+
}
917+
918+
assert(canAllocaStoreValue(Address, Storage, VarInfo, Scope) &&
903919
"bad scope?");
920+
904921
if (Init) {
922+
// Zero init our bare allocation.
905923
zeroInit(cast<llvm::AllocaInst>(Alloca.getAddress()));
906924
ArtificialLocation AutoRestore(Scope, IGM.DebugInfo.get(), Builder);
907-
Builder.CreateStore(Storage, Alloca.getAddress(), Align);
925+
// But store into the address with maybe bitcast.
926+
Builder.CreateStore(Storage, Address, Align);
908927
}
928+
929+
// If this allocation was moved at some point, we might be reinitializing a
930+
// shadow copy. In such a case, lets insert an identity bit cast so that our
931+
// callers will use this address with respect to the place where we
932+
// reinit. Otherwise, callers may use the alloca's insert point. The
933+
// optimizer will eliminate these later without issue.
909934
return Alloca.getAddress();
910935
}
911936

@@ -928,7 +953,7 @@ class IRGenSILFunction :
928953
llvm::Value *emitShadowCopyIfNeeded(llvm::Value *Storage,
929954
const SILDebugScope *Scope,
930955
SILDebugVariable VarInfo,
931-
bool IsAnonymous,
956+
bool IsAnonymous, bool WasMoved,
932957
llvm::Optional<Alignment> Align = None) {
933958
// Never emit shadow copies when optimizing, or if already on the stack. No
934959
// debug info is emitted for refcounts either
@@ -950,7 +975,8 @@ class IRGenSILFunction :
950975
}
951976

952977
// Emit a shadow copy.
953-
auto shadow = emitShadowCopy(Storage, Scope, VarInfo, Align, true);
978+
auto shadow =
979+
emitShadowCopy(Storage, Scope, VarInfo, Align, true, WasMoved);
954980

955981
// Mark variables in async functions for lifetime extension, so they get
956982
// spilled into the async context.
@@ -969,14 +995,16 @@ class IRGenSILFunction :
969995
llvm::Value *emitShadowCopyIfNeeded(Address Storage,
970996
const SILDebugScope *Scope,
971997
SILDebugVariable VarInfo,
972-
bool IsAnonymous) {
998+
bool IsAnonymous, bool WasMoved) {
973999
return emitShadowCopyIfNeeded(Storage.getAddress(), Scope, VarInfo,
974-
IsAnonymous, Storage.getAlignment());
1000+
IsAnonymous, WasMoved,
1001+
Storage.getAlignment());
9751002
}
9761003

9771004
/// Like \c emitShadowCopyIfNeeded() but takes an exploded value.
9781005
void emitShadowCopyIfNeeded(SILValue &SILVal, const SILDebugScope *Scope,
9791006
SILDebugVariable VarInfo, bool IsAnonymous,
1007+
bool WasMoved,
9801008
llvm::SmallVectorImpl<llvm::Value *> &copy) {
9811009
Explosion e = getLoweredExplosion(SILVal);
9821010

@@ -1003,8 +1031,8 @@ class IRGenSILFunction :
10031031
return;
10041032

10051033
if (e.size() == 1) {
1006-
copy.push_back(
1007-
emitShadowCopyIfNeeded(e.claimNext(), Scope, VarInfo, IsAnonymous));
1034+
copy.push_back(emitShadowCopyIfNeeded(e.claimNext(), Scope, VarInfo,
1035+
IsAnonymous, WasMoved));
10081036
return;
10091037
}
10101038

@@ -1053,12 +1081,11 @@ class IRGenSILFunction :
10531081

10541082
/// Emit debug info for a function argument or a local variable.
10551083
template <typename StorageType>
1056-
void emitDebugVariableDeclaration(StorageType Storage, DebugTypeInfo Ty,
1057-
SILType SILTy, const SILDebugScope *DS,
1058-
SILLocation VarLoc,
1059-
SILDebugVariable VarInfo,
1060-
IndirectionKind Indirection,
1061-
AddrDbgInstrKind DbgInstrKind = AddrDbgInstrKind::DbgDeclare) {
1084+
void emitDebugVariableDeclaration(
1085+
StorageType Storage, DebugTypeInfo Ty, SILType SILTy,
1086+
const SILDebugScope *DS, SILLocation VarLoc, SILDebugVariable VarInfo,
1087+
IndirectionKind Indirection,
1088+
AddrDbgInstrKind DbgInstrKind = AddrDbgInstrKind::DbgDeclare) {
10621089
// TODO: fix demangling for C++ types (SR-13223).
10631090
if (swift::TypeBase *ty = SILTy.getASTType().getPointer()) {
10641091
if (MetatypeType *metaTy = dyn_cast<MetatypeType>(ty))
@@ -1070,15 +1097,18 @@ class IRGenSILFunction :
10701097
}
10711098

10721099
assert(IGM.DebugInfo && "debug info not enabled");
1100+
10731101
if (VarInfo.ArgNo) {
10741102
PrologueLocation AutoRestore(IGM.DebugInfo.get(), Builder);
10751103
IGM.DebugInfo->emitVariableDeclaration(Builder, Storage, Ty, DS, VarLoc,
10761104
VarInfo, Indirection, ArtificialKind::RealValue,
10771105
DbgInstrKind);
1078-
} else
1079-
IGM.DebugInfo->emitVariableDeclaration(Builder, Storage, Ty, DS, VarLoc,
1080-
VarInfo, Indirection, ArtificialKind::RealValue,
1081-
DbgInstrKind);
1106+
return;
1107+
}
1108+
1109+
IGM.DebugInfo->emitVariableDeclaration(
1110+
Builder, Storage, Ty, DS, VarLoc, VarInfo, Indirection,
1111+
ArtificialKind::RealValue, DbgInstrKind);
10821112
}
10831113

10841114
void emitFailBB() {
@@ -4787,8 +4817,9 @@ void IRGenSILFunction::emitErrorResultVar(CanSILFunctionType FnTy,
47874817
ErrorInfo, FnTy, IGM.getMaximalTypeExpansionContext()));
47884818
auto Var = DbgValue->getVarInfo();
47894819
assert(Var && "error result without debug info");
4790-
auto Storage = emitShadowCopyIfNeeded(ErrorResultSlot.getAddress(),
4791-
getDebugScope(), *Var, false);
4820+
auto Storage =
4821+
emitShadowCopyIfNeeded(ErrorResultSlot.getAddress(), getDebugScope(),
4822+
*Var, false, false /*was move*/);
47924823
if (!IGM.DebugInfo)
47934824
return;
47944825
auto DbgTy = DebugTypeInfo::getErrorResult(
@@ -4853,7 +4884,8 @@ void IRGenSILFunction::emitPoisonDebugValueInst(DebugValueInst *i) {
48534884
// vs. multi-value explosions.
48544885
llvm::Value *shadowAddress;
48554886
if (singleValueExplosion) {
4856-
shadowAddress = emitShadowCopy(storage, scope, *varInfo, ptrAlign, false);
4887+
shadowAddress = emitShadowCopy(storage, scope, *varInfo, ptrAlign, false,
4888+
false /*was moved*/);
48574889
} else {
48584890
assert(refTy->isClassExistentialType() && "unknown multi-value explosion");
48594891
// FIXME: Handling Optional existentials requires TypeInfo
@@ -4984,12 +5016,12 @@ void IRGenSILFunction::visitDebugValueInst(DebugValueInst *i) {
49845016
// Put the value into a shadow-copy stack slot at -Onone.
49855017
llvm::SmallVector<llvm::Value *, 8> Copy;
49865018
if (IsAddrVal)
4987-
Copy.emplace_back(
4988-
emitShadowCopyIfNeeded(getLoweredAddress(SILVal).getAddress(),
4989-
i->getDebugScope(), *VarInfo, IsAnonymous));
5019+
Copy.emplace_back(emitShadowCopyIfNeeded(
5020+
getLoweredAddress(SILVal).getAddress(), i->getDebugScope(), *VarInfo,
5021+
IsAnonymous, i->getWasMoved()));
49905022
else
49915023
emitShadowCopyIfNeeded(SILVal, i->getDebugScope(), *VarInfo, IsAnonymous,
4992-
Copy);
5024+
i->getWasMoved(), Copy);
49935025

49945026
bindArchetypes(DbgTy.getType());
49955027
if (!IGM.DebugInfo)
@@ -5314,7 +5346,7 @@ void IRGenSILFunction::emitDebugInfoForAllocStack(AllocStackInst *i,
53145346
if (!Alloca->isStaticAlloca()) {
53155347
// Store the address of the dynamic alloca on the stack.
53165348
addr = emitShadowCopy(addr, DS, *VarInfo, IGM.getPointerAlignment(),
5317-
/*init*/ true);
5349+
/*init*/ true, i->getWasMoved());
53185350
Indirection =
53195351
InCoroContext(*CurSILFn, *i) ? CoroIndirectValue : IndirectValue;
53205352
}
@@ -5356,17 +5388,18 @@ void IRGenSILFunction::emitDebugInfoForAllocStack(AllocStackInst *i,
53565388
!isa<llvm::UndefValue>(shadow)) {
53575389
if (ValueVariables.insert(shadow).second)
53585390
ValueDomPoints.push_back({shadow, getActiveDominancePoint()});
5359-
auto inst = cast<llvm::Instruction>(shadow);
5360-
llvm::IRBuilder<> builder(inst->getNextNode());
5391+
auto shadowInst = cast<llvm::Instruction>(shadow);
5392+
llvm::IRBuilder<> builder(shadowInst->getNextNode());
53615393
addr =
53625394
builder.CreateLoad(shadow->getType()->getPointerElementType(), shadow);
53635395
}
53645396

53655397
bindArchetypes(DbgTy.getType());
5366-
if (IGM.DebugInfo)
5367-
emitDebugVariableDeclaration(addr, DbgTy, SILTy, DS,
5368-
i->getLoc(), *VarInfo,
5369-
Indirection);
5398+
if (IGM.DebugInfo) {
5399+
emitDebugVariableDeclaration(addr, DbgTy, SILTy, DS, i->getLoc(), *VarInfo,
5400+
Indirection,
5401+
AddrDbgInstrKind(i->getWasMoved()));
5402+
}
53705403
}
53715404

53725405
void IRGenSILFunction::visitAllocStackInst(swift::AllocStackInst *i) {
@@ -5585,8 +5618,9 @@ void IRGenSILFunction::visitAllocBoxInst(swift::AllocBoxInst *i) {
55855618
auto VarInfo = i->getVarInfo();
55865619
assert(VarInfo && "debug_value without debug info");
55875620

5588-
auto Storage = emitShadowCopyIfNeeded(
5589-
boxWithAddr.getAddress(), i->getDebugScope(), *VarInfo, IsAnonymous);
5621+
auto Storage =
5622+
emitShadowCopyIfNeeded(boxWithAddr.getAddress(), i->getDebugScope(),
5623+
*VarInfo, IsAnonymous, false /*was moved*/);
55905624

55915625
if (!IGM.DebugInfo)
55925626
return;

lib/SILOptimizer/Mandatory/MoveKillsCopyableAddressesChecker.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1429,6 +1429,8 @@ bool DataflowState::cleanupAllDestroyAddr(
14291429
bool madeChange = false;
14301430
BasicBlockWorklist worklist(fn);
14311431

1432+
auto debugVarInst = DebugVarCarryingInst::getFromValue(address);
1433+
14321434
LLVM_DEBUG(llvm::dbgs() << "Cleanup up destroy addr!\n");
14331435
LLVM_DEBUG(llvm::dbgs() << " Visiting destroys!\n");
14341436
LLVM_DEBUG(llvm::dbgs() << " Destroy Indices: " << destroyIndices << "\n");
@@ -1531,6 +1533,15 @@ bool DataflowState::cleanupAllDestroyAddr(
15311533
continue;
15321534
LLVM_DEBUG(llvm::dbgs() << "Converting reinit to init: " << *reinit);
15331535
convertMemoryReinitToInitForm(*reinit);
1536+
1537+
// Make sure to create a new debug_value for the reinit value.
1538+
if (debugVarInst) {
1539+
if (auto varInfo = debugVarInst.getVarInfo()) {
1540+
SILBuilderWithScope reinitBuilder(*reinit);
1541+
reinitBuilder.createDebugValue(debugVarInst.inst->getLoc(), address,
1542+
*varInfo, false, /*was moved*/ true);
1543+
}
1544+
}
15341545
madeChange = true;
15351546
}
15361547

@@ -2025,6 +2036,14 @@ static bool performSingleBasicBlockAnalysis(DataflowState &dataflowState,
20252036
SILUndef::get(address->getType(), builder.getModule()), *varInfo,
20262037
false,
20272038
/*was moved*/ true);
2039+
{
2040+
// Make sure at the reinit point to create a new debug value after the
2041+
// reinit instruction so we reshow the variable.
2042+
auto *next = interestingUser->getNextInstruction();
2043+
SILBuilderWithScope reinitBuilder(next);
2044+
reinitBuilder.createDebugValue(debug.inst->getLoc(), address,
2045+
*varInfo, false, /*was moved*/ true);
2046+
}
20282047
}
20292048
debug.markAsMoved();
20302049
}

0 commit comments

Comments
 (0)