mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
StripObjectHeaders: make sure that a dealloc_ref comes from the original root allocation.
Fixes a miscompile
This commit is contained in:
@@ -37,13 +37,15 @@ let stripObjectHeadersPass = FunctionPass(name: "strip-object-headers") {
|
||||
|
||||
private extension Value {
|
||||
func needObjectHeader() -> Bool {
|
||||
var walker = IsBareObjectWalker()
|
||||
var walker = IsBareObjectWalker(rootDef: self)
|
||||
return walker.walkDownUses(ofValue: self, path: SmallProjectionPath()) == .abortWalk
|
||||
}
|
||||
}
|
||||
|
||||
private struct IsBareObjectWalker : ValueDefUseWalker {
|
||||
private struct IsBareObjectWalker : ValueDefUseWalker, ValueUseDefWalker {
|
||||
var walkUpCache = WalkerCache<SmallProjectionPath>()
|
||||
var walkDownCache = WalkerCache<SmallProjectionPath>()
|
||||
let rootDef: Value
|
||||
|
||||
mutating func walkDown(value operand: Operand, path: Path) -> WalkResult {
|
||||
switch operand.instruction {
|
||||
@@ -67,11 +69,20 @@ private struct IsBareObjectWalker : ValueDefUseWalker {
|
||||
switch operand.instruction {
|
||||
// White-list all instructions which don't use the object header.
|
||||
case is RefElementAddrInst, is RefTailAddrInst,
|
||||
is DeallocRefInst, is DeallocStackRefInst,
|
||||
is DeallocStackRefInst,
|
||||
is DebugValueInst, is FixLifetimeInst:
|
||||
return .continueWalk
|
||||
case let deallocRef as DeallocRefInst:
|
||||
// Check if the final dealloc_ref comes from the single `rootDef`.
|
||||
// In case of phi-arguments it might come from multiple root definitions.
|
||||
return walkUp(value: deallocRef.operand.value, path: path)
|
||||
default:
|
||||
return .abortWalk
|
||||
}
|
||||
}
|
||||
|
||||
mutating func rootDef(value: Value, path: SmallProjectionPath) -> WalkResult {
|
||||
return value == rootDef ? .continueWalk : .abortWalk
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user