Skip to content

Commit 308a6fe

Browse files
committed
Move AddressWalker::walk into the header and eliminate AddressWalker.cpp.
1 parent 62fb241 commit 308a6fe

File tree

3 files changed

+205
-222
lines changed

3 files changed

+205
-222
lines changed

include/swift/SIL/AddressWalker.h

Lines changed: 205 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,11 @@
2121
#ifndef SWIFT_SIL_ADDRESSWALKER_H
2222
#define SWIFT_SIL_ADDRESSWALKER_H
2323

24+
#include "swift/Basic/Defer.h"
2425
#include "swift/SIL/AddressUseKind.h"
26+
#include "swift/SIL/BasicBlockDatastructures.h"
27+
#include "swift/SIL/InstructionUtils.h"
28+
#include "swift/SIL/Projection.h"
2529
#include "swift/SIL/SILValue.h"
2630

2731
namespace swift {
@@ -71,6 +75,207 @@ class TransitiveAddressWalker {
7175
AddressUseKind walk(SILValue address) &&;
7276
};
7377

78+
inline AddressUseKind TransitiveAddressWalker::walk(SILValue projectedAddress) && {
79+
assert(!didInvalidate);
80+
81+
// When we exit, set the result to be invalidated so we can't use this again.
82+
SWIFT_DEFER { didInvalidate = true; };
83+
84+
StackList<Operand *> worklist(projectedAddress->getFunction());
85+
SmallPtrSet<Operand *, 32> visitedOperands;
86+
87+
auto addToWorklist = [&](Operand *use) {
88+
if (visitedOperands.insert(use).second)
89+
worklist.push_back(use);
90+
};
91+
92+
for (auto *use : projectedAddress->getUses()) {
93+
addToWorklist(use);
94+
}
95+
96+
// Record all uses that aren't transitively followed. These are either
97+
// instanteneous uses of the addres, or cause a pointer escape.
98+
auto transitiveResultUses = [&](Operand *use) {
99+
auto *svi = cast<SingleValueInstruction>(use->getUser());
100+
if (svi->use_empty()) {
101+
callVisitUse(use);
102+
} else {
103+
for (auto *use : svi->getUses())
104+
addToWorklist(use);
105+
}
106+
};
107+
108+
while (!worklist.empty()) {
109+
if (result == AddressUseKind::Unknown)
110+
return AddressUseKind::Unknown;
111+
112+
auto *op = worklist.pop_back_val();
113+
114+
// Skip type dependent operands.
115+
if (op->isTypeDependent())
116+
continue;
117+
118+
// Then update the worklist with new things to find if we recognize this
119+
// inst and then continue. If we fail, we emit an error at the bottom of the
120+
// loop that we didn't recognize the user.
121+
auto *user = op->getUser();
122+
123+
if (auto *ti = dyn_cast<TermInst>(user)) {
124+
switch (ti->getTermKind()) {
125+
case TermKind::BranchInst:
126+
case TermKind::CondBranchInst:
127+
// We could have an address phi. To be conservative, just treat this as
128+
// a point escape.
129+
meet(AddressUseKind::PointerEscape);
130+
for (auto succBlockArgList : ti->getSuccessorBlockArgumentLists()) {
131+
auto *succ = succBlockArgList[op->getOperandNumber()];
132+
for (auto *use : succ->getUses())
133+
addToWorklist(use);
134+
}
135+
continue;
136+
137+
case TermKind::UnreachableInst:
138+
case TermKind::UnwindInst:
139+
llvm_unreachable("Should never be used");
140+
case TermKind::SwitchEnumInst:
141+
case TermKind::SwitchValueInst:
142+
case TermKind::DynamicMethodBranchInst:
143+
case TermKind::AwaitAsyncContinuationInst:
144+
case TermKind::CheckedCastBranchInst:
145+
llvm_unreachable("Never takes an address");
146+
// Point uses.
147+
case TermKind::ReturnInst:
148+
case TermKind::ThrowInst:
149+
case TermKind::YieldInst:
150+
case TermKind::TryApplyInst:
151+
case TermKind::SwitchEnumAddrInst:
152+
case TermKind::CheckedCastAddrBranchInst:
153+
callVisitUse(op);
154+
continue;
155+
}
156+
}
157+
158+
// TODO: Partial apply should be NonEscaping, but then we need to consider
159+
// the apply to be a use point.
160+
if (isa<PartialApplyInst>(user) || isa<AddressToPointerInst>(user)) {
161+
meet(AddressUseKind::PointerEscape);
162+
callVisitUse(op);
163+
continue;
164+
}
165+
166+
// First, eliminate "end point uses" that we just need to check liveness at
167+
// and do not need to check transitive uses of.
168+
if (isa<LoadInst>(user) || isa<CopyAddrInst>(user) ||
169+
isa<MarkUnresolvedMoveAddrInst>(user) || isIncidentalUse(user) ||
170+
isa<StoreInst>(user) || isa<DestroyAddrInst>(user) ||
171+
isa<AssignInst>(user) || isa<LoadUnownedInst>(user) ||
172+
isa<StoreUnownedInst>(user) || isa<EndApplyInst>(user) ||
173+
isa<LoadWeakInst>(user) || isa<StoreWeakInst>(user) ||
174+
isa<AssignByWrapperInst>(user) || isa<AssignOrInitInst>(user) ||
175+
isa<BeginUnpairedAccessInst>(user) ||
176+
isa<EndUnpairedAccessInst>(user) || isa<WitnessMethodInst>(user) ||
177+
isa<SelectEnumAddrInst>(user) || isa<InjectEnumAddrInst>(user) ||
178+
isa<IsUniqueInst>(user) || isa<ValueMetatypeInst>(user) ||
179+
isa<DebugValueInst>(user) || isa<EndBorrowInst>(user) ||
180+
isa<ExplicitCopyAddrInst>(user) || isa<DeallocStackInst>(user) ||
181+
isa<InitBlockStorageHeaderInst>(user) ||
182+
isa<GetAsyncContinuationAddrInst>(user) ||
183+
isa<ExistentialMetatypeInst>(user) ||
184+
isa<UncheckedRefCastAddrInst>(user) || isa<KeyPathInst>(user) ||
185+
isa<RetainValueAddrInst>(user) || isa<ReleaseValueAddrInst>(user) ||
186+
isa<PackElementSetInst>(user) || isa<PackElementGetInst>(user) ||
187+
isa<DeinitExistentialAddrInst>(user) || isa<LoadBorrowInst>(user)) {
188+
callVisitUse(op);
189+
continue;
190+
}
191+
192+
if (isa<UnconditionalCheckedCastAddrInst>(user) ||
193+
isa<MarkFunctionEscapeInst>(user)) {
194+
assert(!user->hasResults());
195+
callVisitUse(op);
196+
continue;
197+
}
198+
199+
// Then handle users that we need to look at transitive uses of.
200+
if (Projection::isAddressProjection(user) ||
201+
isa<ProjectBlockStorageInst>(user) ||
202+
isa<OpenExistentialAddrInst>(user) ||
203+
isa<InitExistentialAddrInst>(user) || isa<InitEnumDataAddrInst>(user) ||
204+
isa<BeginAccessInst>(user) || isa<TailAddrInst>(user) ||
205+
isa<IndexAddrInst>(user) || isa<StoreBorrowInst>(user) ||
206+
isa<UncheckedAddrCastInst>(user) || isa<MarkMustCheckInst>(user) ||
207+
isa<MarkUninitializedInst>(user) || isa<DropDeinitInst>(user) ||
208+
isa<ProjectBlockStorageInst>(user) || isa<UpcastInst>(user) ||
209+
isa<TuplePackElementAddrInst>(user) ||
210+
isa<CopyableToMoveOnlyWrapperAddrInst>(user) ||
211+
isa<MoveOnlyWrapperToCopyableAddrInst>(user)) {
212+
transitiveResultUses(op);
213+
continue;
214+
}
215+
216+
if (auto *builtin = dyn_cast<BuiltinInst>(user)) {
217+
if (auto kind = builtin->getBuiltinKind()) {
218+
switch (*kind) {
219+
case BuiltinValueKind::TSanInoutAccess:
220+
case BuiltinValueKind::ResumeThrowingContinuationReturning:
221+
case BuiltinValueKind::ResumeNonThrowingContinuationReturning:
222+
case BuiltinValueKind::Copy:
223+
case BuiltinValueKind::GenericAdd:
224+
case BuiltinValueKind::GenericFAdd:
225+
case BuiltinValueKind::GenericAnd:
226+
case BuiltinValueKind::GenericAShr:
227+
case BuiltinValueKind::GenericLShr:
228+
case BuiltinValueKind::GenericOr:
229+
case BuiltinValueKind::GenericFDiv:
230+
case BuiltinValueKind::GenericMul:
231+
case BuiltinValueKind::GenericFMul:
232+
case BuiltinValueKind::GenericSDiv:
233+
case BuiltinValueKind::GenericExactSDiv:
234+
case BuiltinValueKind::GenericShl:
235+
case BuiltinValueKind::GenericSRem:
236+
case BuiltinValueKind::GenericSub:
237+
case BuiltinValueKind::GenericFSub:
238+
case BuiltinValueKind::GenericUDiv:
239+
case BuiltinValueKind::GenericExactUDiv:
240+
case BuiltinValueKind::GenericURem:
241+
case BuiltinValueKind::GenericFRem:
242+
case BuiltinValueKind::GenericXor:
243+
case BuiltinValueKind::TaskRunInline:
244+
case BuiltinValueKind::ZeroInitializer:
245+
callVisitUse(op);
246+
continue;
247+
default:
248+
break;
249+
}
250+
}
251+
}
252+
253+
if (auto fas = FullApplySite::isa(user)) {
254+
callVisitUse(op);
255+
continue;
256+
}
257+
258+
if (auto *mdi = dyn_cast<MarkDependenceInst>(user)) {
259+
// If this is the base, just treat it as a liveness use.
260+
if (op->get() == mdi->getBase()) {
261+
callVisitUse(op);
262+
continue;
263+
}
264+
265+
// If we are the value use, look through it.
266+
transitiveResultUses(op);
267+
continue;
268+
}
269+
270+
// We were unable to recognize this user, so set AddressUseKind to unknown
271+
// and call onError with the specific user that caused the problem.
272+
onError(op);
273+
return AddressUseKind::Unknown;
274+
}
275+
276+
return result;
277+
}
278+
74279
} // namespace swift
75280

76281
#endif

0 commit comments

Comments
 (0)