{"data":{"post":{"title":"当 Swift 编译器删除了标准库中的代码 - 记修复 Swift 6 中的冗余 Load 指令消除优化器","subtitle":"","isPublished":true,"createdTime":"2025-03-09T00:00:00.000Z","lastModifiedTime":null,"license":null,"tags":["Swift","Compiler"],"category":"Programming","file":{"childMdx":{"excerpt":"最新更新：苹果已接受该问题的修复。最终解决方案在相关代码所有者 review 后进行了调整。 蛇年春节假期前，一位同事向我展示了一个由 use-after-free…","code":{"body":"function _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; }\n\nfunction _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }\n\nconst layoutProps = {};\nreturn class MDXContent extends React.Component {\n  constructor(props) {\n    super(props);\n    this.layout = null;\n  }\n\n  render() {\n    const _this$props = this.props,\n          {\n      components\n    } = _this$props,\n          props = _objectWithoutProperties(_this$props, [\"components\"]);\n\n    return React.createElement(MDXTag, {\n      name: \"wrapper\",\n      components: components\n    }, React.createElement(MDXTag, {\n      name: \"blockquote\",\n      components: components\n    }, React.createElement(MDXTag, {\n      name: \"p\",\n      components: components,\n      parentName: \"blockquote\"\n    }, `最新更新：苹果已接受该问题的修复。最终解决方案在相关代码所有者 review 后进行了调整。`)), React.createElement(MDXTag, {\n      name: \"p\",\n      components: components\n    }, `蛇年春节假期前，一位同事向我展示了一个由 use-after-free（释放后使用）错误导致的神秘崩溃。最近，我有时间深入研究这个问题，并发现崩溃是由 Swift 编译器的错误编译引起的。下面是最小复现代码，必须使用 `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `-Osize`), ` 优化级别编译。我们可以通过在编译过程中启用地址检查器（address sanitizer）来检测 use-after-free 问题。`), React.createElement(MDXTag, {\n      name: \"pre\",\n      components: components\n    }, React.createElement(MDXTag, {\n      name: \"code\",\n      components: components,\n      parentName: \"pre\",\n      props: {\n        \"className\": \"language-swift\"\n      }\n    }, `let storage = ValueStorage()\nstorage.append(1)\n// 运行时崩溃！\nstorage.append(2)\n\npublic class ValueStorage {\n    \n    private class Data {\n    \n        var values: [Int] = []\n    \n    }\n    \n    private var data = Data()\n    \n    private func withAutoreleasingUnsafeMutableData<R>(_ body: (_ dataPtr: AutoreleasingUnsafeMutablePointer<Data>) throws -> R) rethrows -> R {\n        try withUnsafeMutablePointer(to: &data) { pointer in\n            try body(AutoreleasingUnsafeMutablePointer(pointer))\n        }\n    }\n    \n    public func append(_ value: Int) {\n        withAutoreleasingUnsafeMutableData { dataPtr in\n            // 立即崩溃的行\n            dataPtr.pointee.values.append(value)\n        }\n    }\n    \n}\n`)), React.createElement(MDXTag, {\n      name: \"p\",\n      components: components\n    }, React.createElement(MDXTag, {\n      name: \"figure\",\n      components: components,\n      parentName: \"p\"\n    }, `\n    `, React.createElement(MDXTag, {\n      name: \"a\",\n      components: components,\n      parentName: \"figure\",\n      props: {\n        \"href\": \"/static/ad00b90728b64c3d88e939013fbd74f7/deb5c/enable-asan-in-xcode.webp\"\n      }\n    }, React.createElement(MDXTag, {\n      name: \"picture\",\n      components: components,\n      parentName: \"a\"\n    }, `\n  `, React.createElement(MDXTag, {\n      name: \"source\",\n      components: components,\n      parentName: \"picture\",\n      props: {\n        \"src\": \"/static/ad00b90728b64c3d88e939013fbd74f7/0cc25/enable-asan-in-xcode.png\",\n        \"srcSet\": [\"/static/ad00b90728b64c3d88e939013fbd74f7/5116e/enable-asan-in-xcode.png 178w\", \"/static/ad00b90728b64c3d88e939013fbd74f7/92f55/enable-asan-in-xcode.png 356w\", \"/static/ad00b90728b64c3d88e939013fbd74f7/0cc25/enable-asan-in-xcode.png 712w\", \"/static/ad00b90728b64c3d88e939013fbd74f7/7ae06/enable-asan-in-xcode.png 1068w\", \"/static/ad00b90728b64c3d88e939013fbd74f7/eee47/enable-asan-in-xcode.png 1424w\", \"/static/ad00b90728b64c3d88e939013fbd74f7/38407/enable-asan-in-xcode.png 2136w\", \"/static/ad00b90728b64c3d88e939013fbd74f7/5b6d0/enable-asan-in-xcode.png 3024w\"],\n        \"sizes\": \"(max-width: 712px) 100vw, 712px\"\n      }\n    }), React.createElement(MDXTag, {\n      name: \"source\",\n      components: components,\n      parentName: \"picture\",\n      props: {\n        \"src\": \"/static/ad00b90728b64c3d88e939013fbd74f7/690c8/enable-asan-in-xcode.webp\",\n        \"srcSet\": [\"/static/ad00b90728b64c3d88e939013fbd74f7/25c8a/enable-asan-in-xcode.webp 178w\", \"/static/ad00b90728b64c3d88e939013fbd74f7/60698/enable-asan-in-xcode.webp 356w\", \"/static/ad00b90728b64c3d88e939013fbd74f7/690c8/enable-asan-in-xcode.webp 712w\", \"/static/ad00b90728b64c3d88e939013fbd74f7/d7e52/enable-asan-in-xcode.webp 1068w\", \"/static/ad00b90728b64c3d88e939013fbd74f7/456ef/enable-asan-in-xcode.webp 1424w\", \"/static/ad00b90728b64c3d88e939013fbd74f7/2a654/enable-asan-in-xcode.webp 2136w\", \"/static/ad00b90728b64c3d88e939013fbd74f7/deb5c/enable-asan-in-xcode.webp 3024w\"],\n        \"sizes\": \"(max-width: 712px) 100vw, 712px\"\n      }\n    }), `\n  `, React.createElement(MDXTag, {\n      name: \"img\",\n      components: components,\n      parentName: \"picture\",\n      props: {\n        \"src\": \"/static/ad00b90728b64c3d88e939013fbd74f7/deb5c/enable-asan-in-xcode.webp\",\n        \"alt\": \"在 Xcode 中打开地址检查器\",\n        \"title\": \"在 Xcode 中打开地址检查器\",\n        \"width\": 712,\n        \"height\": 502,\n        \"loading\": \"lazy\"\n      }\n    }))), `\n    `, React.createElement(MDXTag, {\n      name: \"figcaption\",\n      components: components,\n      parentName: \"figure\"\n    }, `\n        `, React.createElement(MDXTag, {\n      name: \"span\",\n      components: components,\n      parentName: \"figcaption\"\n    }, `\n            在 Xcode 中打开地址检查器\n        `), `\n    `))), React.createElement(MDXTag, {\n      name: \"p\",\n      components: components\n    }, React.createElement(MDXTag, {\n      name: \"figure\",\n      components: components,\n      parentName: \"p\"\n    }, `\n    `, React.createElement(MDXTag, {\n      name: \"a\",\n      components: components,\n      parentName: \"figure\",\n      props: {\n        \"href\": \"/static/fe5df802257e7505d12c12220aa11432/deb5c/uaf-issue.webp\"\n      }\n    }, React.createElement(MDXTag, {\n      name: \"picture\",\n      components: components,\n      parentName: \"a\"\n    }, `\n  `, React.createElement(MDXTag, {\n      name: \"source\",\n      components: components,\n      parentName: \"picture\",\n      props: {\n        \"src\": \"/static/fe5df802257e7505d12c12220aa11432/0cc25/uaf-issue.png\",\n        \"srcSet\": [\"/static/fe5df802257e7505d12c12220aa11432/5116e/uaf-issue.png 178w\", \"/static/fe5df802257e7505d12c12220aa11432/92f55/uaf-issue.png 356w\", \"/static/fe5df802257e7505d12c12220aa11432/0cc25/uaf-issue.png 712w\", \"/static/fe5df802257e7505d12c12220aa11432/7ae06/uaf-issue.png 1068w\", \"/static/fe5df802257e7505d12c12220aa11432/eee47/uaf-issue.png 1424w\", \"/static/fe5df802257e7505d12c12220aa11432/38407/uaf-issue.png 2136w\", \"/static/fe5df802257e7505d12c12220aa11432/5b6d0/uaf-issue.png 3024w\"],\n        \"sizes\": \"(max-width: 712px) 100vw, 712px\"\n      }\n    }), React.createElement(MDXTag, {\n      name: \"source\",\n      components: components,\n      parentName: \"picture\",\n      props: {\n        \"src\": \"/static/fe5df802257e7505d12c12220aa11432/690c8/uaf-issue.webp\",\n        \"srcSet\": [\"/static/fe5df802257e7505d12c12220aa11432/25c8a/uaf-issue.webp 178w\", \"/static/fe5df802257e7505d12c12220aa11432/60698/uaf-issue.webp 356w\", \"/static/fe5df802257e7505d12c12220aa11432/690c8/uaf-issue.webp 712w\", \"/static/fe5df802257e7505d12c12220aa11432/d7e52/uaf-issue.webp 1068w\", \"/static/fe5df802257e7505d12c12220aa11432/456ef/uaf-issue.webp 1424w\", \"/static/fe5df802257e7505d12c12220aa11432/2a654/uaf-issue.webp 2136w\", \"/static/fe5df802257e7505d12c12220aa11432/deb5c/uaf-issue.webp 3024w\"],\n        \"sizes\": \"(max-width: 712px) 100vw, 712px\"\n      }\n    }), `\n  `, React.createElement(MDXTag, {\n      name: \"img\",\n      components: components,\n      parentName: \"picture\",\n      props: {\n        \"src\": \"/static/fe5df802257e7505d12c12220aa11432/deb5c/uaf-issue.webp\",\n        \"alt\": \"UAF 问题出现\",\n        \"title\": \"UAF 问题出现\",\n        \"width\": 712,\n        \"height\": 502,\n        \"loading\": \"lazy\"\n      }\n    }))), `\n    `, React.createElement(MDXTag, {\n      name: \"figcaption\",\n      components: components,\n      parentName: \"figure\"\n    }, `\n        `, React.createElement(MDXTag, {\n      name: \"span\",\n      components: components,\n      parentName: \"figcaption\"\n    }, `\n            UAF 问题出现\n        `), `\n    `))), React.createElement(MDXTag, {\n      name: \"p\",\n      components: components\n    }, `有趣的是，将 `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `AutoreleasingUnsafeMutablePointer`), ` 替换为 `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `UnsafeMutablePointer`), ` 可以解决这个问题。`), React.createElement(MDXTag, {\n      name: \"p\",\n      components: components\n    }, React.createElement(MDXTag, {\n      name: \"figure\",\n      components: components,\n      parentName: \"p\"\n    }, `\n    `, React.createElement(MDXTag, {\n      name: \"a\",\n      components: components,\n      parentName: \"figure\",\n      props: {\n        \"href\": \"/static/5fecc6bb5e14e38c6eeab4a07b818f93/deb5c/no-uaf-issue.webp\"\n      }\n    }, React.createElement(MDXTag, {\n      name: \"picture\",\n      components: components,\n      parentName: \"a\"\n    }, `\n  `, React.createElement(MDXTag, {\n      name: \"source\",\n      components: components,\n      parentName: \"picture\",\n      props: {\n        \"src\": \"/static/5fecc6bb5e14e38c6eeab4a07b818f93/0cc25/no-uaf-issue.png\",\n        \"srcSet\": [\"/static/5fecc6bb5e14e38c6eeab4a07b818f93/5116e/no-uaf-issue.png 178w\", \"/static/5fecc6bb5e14e38c6eeab4a07b818f93/92f55/no-uaf-issue.png 356w\", \"/static/5fecc6bb5e14e38c6eeab4a07b818f93/0cc25/no-uaf-issue.png 712w\", \"/static/5fecc6bb5e14e38c6eeab4a07b818f93/7ae06/no-uaf-issue.png 1068w\", \"/static/5fecc6bb5e14e38c6eeab4a07b818f93/eee47/no-uaf-issue.png 1424w\", \"/static/5fecc6bb5e14e38c6eeab4a07b818f93/38407/no-uaf-issue.png 2136w\", \"/static/5fecc6bb5e14e38c6eeab4a07b818f93/5b6d0/no-uaf-issue.png 3024w\"],\n        \"sizes\": \"(max-width: 712px) 100vw, 712px\"\n      }\n    }), React.createElement(MDXTag, {\n      name: \"source\",\n      components: components,\n      parentName: \"picture\",\n      props: {\n        \"src\": \"/static/5fecc6bb5e14e38c6eeab4a07b818f93/690c8/no-uaf-issue.webp\",\n        \"srcSet\": [\"/static/5fecc6bb5e14e38c6eeab4a07b818f93/25c8a/no-uaf-issue.webp 178w\", \"/static/5fecc6bb5e14e38c6eeab4a07b818f93/60698/no-uaf-issue.webp 356w\", \"/static/5fecc6bb5e14e38c6eeab4a07b818f93/690c8/no-uaf-issue.webp 712w\", \"/static/5fecc6bb5e14e38c6eeab4a07b818f93/d7e52/no-uaf-issue.webp 1068w\", \"/static/5fecc6bb5e14e38c6eeab4a07b818f93/456ef/no-uaf-issue.webp 1424w\", \"/static/5fecc6bb5e14e38c6eeab4a07b818f93/2a654/no-uaf-issue.webp 2136w\", \"/static/5fecc6bb5e14e38c6eeab4a07b818f93/deb5c/no-uaf-issue.webp 3024w\"],\n        \"sizes\": \"(max-width: 712px) 100vw, 712px\"\n      }\n    }), `\n  `, React.createElement(MDXTag, {\n      name: \"img\",\n      components: components,\n      parentName: \"picture\",\n      props: {\n        \"src\": \"/static/5fecc6bb5e14e38c6eeab4a07b818f93/deb5c/no-uaf-issue.webp\",\n        \"alt\": \"没有 UAF 问题\",\n        \"title\": \"没有 UAF 问题\",\n        \"width\": 712,\n        \"height\": 502,\n        \"loading\": \"lazy\"\n      }\n    }))), `\n    `, React.createElement(MDXTag, {\n      name: \"figcaption\",\n      components: components,\n      parentName: \"figure\"\n    }, `\n        `, React.createElement(MDXTag, {\n      name: \"span\",\n      components: components,\n      parentName: \"figcaption\"\n    }, `\n            没有 UAF 问题\n        `), `\n    `))), React.createElement(MDXTag, {\n      name: \"h2\",\n      components: components\n    }, `调查崩溃现场`), React.createElement(MDXTag, {\n      name: \"p\",\n      components: components\n    }, `反汇编有问题的程序后，我们可以发现 `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `Array`), ` 的追加函数内联到了 `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `ValueStorage.append`), ` 函数中。关键问题是程序在 `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `Array`), ` 重新分配后没有重新获取 `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `Array`), ` 的缓冲区对象。这导致使用寄存器 `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `r12`), ` 计算的地址指向旧缓冲区（如果确实发生了重新分配）。这段反汇编代码可以被简化为：`), React.createElement(MDXTag, {\n      name: \"pre\",\n      components: components\n    }, React.createElement(MDXTag, {\n      name: \"code\",\n      components: components,\n      parentName: \"pre\",\n      props: {\n        \"className\": \"language-asm\"\n      }\n    }, `; 将 \\`self.values: [Int]\\` 加载到 r12\nmov r15, qword [r13 + 0x10]\n; r14 现在是 \\`self.values: [Int]\\`\nmov r14, r15\n; 将 Array 的缓冲区对象加载到 r12\nmov r12, qword [r14 + 0x10]\n; 重新分配，可能释放旧缓冲区对象\ncall Swift.Array._reserveCapacityAssumingUniqueBuffer\n; 将新计数设置到旧缓冲区对象\n; use-after-free（释放后使用）发生\nmov qword [r12 + 0x10] rax\n`)), React.createElement(MDXTag, {\n      name: \"p\",\n      components: components\n    }, `以下是 `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `ValueStorage.append`), ` 的完整反汇编代码：`), React.createElement(MDXTag, {\n      name: \"p\",\n      components: components\n    }, React.createElement(MDXTag, {\n      name: \"figure\",\n      components: components,\n      parentName: \"p\"\n    }, `\n    `, React.createElement(MDXTag, {\n      name: \"a\",\n      components: components,\n      parentName: \"figure\",\n      props: {\n        \"href\": \"/static/c570069615c6a8233ddeadee8385f35d/04e84/generated-target-code-with-uaf-issue.webp\"\n      }\n    }, React.createElement(MDXTag, {\n      name: \"picture\",\n      components: components,\n      parentName: \"a\"\n    }, `\n  `, React.createElement(MDXTag, {\n      name: \"source\",\n      components: components,\n      parentName: \"picture\",\n      props: {\n        \"src\": \"/static/c570069615c6a8233ddeadee8385f35d/0cc25/generated-target-code-with-uaf-issue.png\",\n        \"srcSet\": [\"/static/c570069615c6a8233ddeadee8385f35d/5116e/generated-target-code-with-uaf-issue.png 178w\", \"/static/c570069615c6a8233ddeadee8385f35d/92f55/generated-target-code-with-uaf-issue.png 356w\", \"/static/c570069615c6a8233ddeadee8385f35d/0cc25/generated-target-code-with-uaf-issue.png 712w\", \"/static/c570069615c6a8233ddeadee8385f35d/7ae06/generated-target-code-with-uaf-issue.png 1068w\", \"/static/c570069615c6a8233ddeadee8385f35d/eee47/generated-target-code-with-uaf-issue.png 1424w\", \"/static/c570069615c6a8233ddeadee8385f35d/38407/generated-target-code-with-uaf-issue.png 2136w\", \"/static/c570069615c6a8233ddeadee8385f35d/2d4b3/generated-target-code-with-uaf-issue.png 2508w\"],\n        \"sizes\": \"(max-width: 712px) 100vw, 712px\"\n      }\n    }), React.createElement(MDXTag, {\n      name: \"source\",\n      components: components,\n      parentName: \"picture\",\n      props: {\n        \"src\": \"/static/c570069615c6a8233ddeadee8385f35d/690c8/generated-target-code-with-uaf-issue.webp\",\n        \"srcSet\": [\"/static/c570069615c6a8233ddeadee8385f35d/25c8a/generated-target-code-with-uaf-issue.webp 178w\", \"/static/c570069615c6a8233ddeadee8385f35d/60698/generated-target-code-with-uaf-issue.webp 356w\", \"/static/c570069615c6a8233ddeadee8385f35d/690c8/generated-target-code-with-uaf-issue.webp 712w\", \"/static/c570069615c6a8233ddeadee8385f35d/d7e52/generated-target-code-with-uaf-issue.webp 1068w\", \"/static/c570069615c6a8233ddeadee8385f35d/456ef/generated-target-code-with-uaf-issue.webp 1424w\", \"/static/c570069615c6a8233ddeadee8385f35d/2a654/generated-target-code-with-uaf-issue.webp 2136w\", \"/static/c570069615c6a8233ddeadee8385f35d/04e84/generated-target-code-with-uaf-issue.webp 2508w\"],\n        \"sizes\": \"(max-width: 712px) 100vw, 712px\"\n      }\n    }), `\n  `, React.createElement(MDXTag, {\n      name: \"img\",\n      components: components,\n      parentName: \"picture\",\n      props: {\n        \"src\": \"/static/c570069615c6a8233ddeadee8385f35d/04e84/generated-target-code-with-uaf-issue.webp\",\n        \"alt\": \"ValueStorage.append 的反汇编码\",\n        \"title\": \"ValueStorage.append 的反汇编码\",\n        \"width\": 712,\n        \"height\": 543,\n        \"loading\": \"lazy\"\n      }\n    }))), `\n    `, React.createElement(MDXTag, {\n      name: \"figcaption\",\n      components: components,\n      parentName: \"figure\"\n    }, `\n        `, React.createElement(MDXTag, {\n      name: \"span\",\n      components: components,\n      parentName: \"figcaption\"\n    }, `\n            ValueStorage.append 的反汇编码\n        `), `\n    `))), React.createElement(MDXTag, {\n      name: \"p\",\n      components: components\n    }, `检查 Swift 标准库代码发现，其实际上是通过访问 `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `self`), ` 上的 `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `_buffer`), ` 属性来更新元素计数并插入新元素，而不是使用现有的旧缓冲区变量。Swift 编译器错误地删除了目标代码中重新获取 `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `_buffer`), ` 对象的操作。`), React.createElement(MDXTag, {\n      name: \"pre\",\n      components: components\n    }, React.createElement(MDXTag, {\n      name: \"code\",\n      components: components,\n      parentName: \"pre\",\n      props: {\n        \"className\": \"language-swift\"\n      }\n    }, `// 标准库中的实现\n@inlinable\n@_semantics(\"array.mutate_unknown\")\n@_effects(notEscaping self.**)\ninternal mutating func _appendElementAssumeUniqueAndCapacity(\n  _ oldCount: Int,\n  newElement: __owned Element\n) {\n  // 使用 \\`self\\` 上的 \\`_buffer\\`\n  _buffer.mutableCount = oldCount &+ 1\n  // 使用 \\`self\\` 上的 \\`_buffer\\`\n  (_buffer.mutableFirstElementAddress + oldCount).initialize(to: newElement)\n}\n\n// 可能产生生成目标代码的假想实现\n@inlinable\n@_semantics(\"array.mutate_unknown\")\n@_effects(notEscaping self.**)\ninternal mutating func _appendElementAssumeUniqueAndCapacity(\n    _ oldCount: Int,\n    newElement: __owned Element\n    // 显式重用旧缓冲区\n    oldBufer: _Buffer\n) {\n    // 使用 \\`oldBuffer\\`\n    oldBufer.mutableCount = oldCount &+ 1\n    (oldBufer.mutableFirstElementAddress + oldCount).initialize(to: newElement)\n}\n`)), React.createElement(MDXTag, {\n      name: \"h2\",\n      components: components\n    }, `为什么 Swift 编译器删除了代码？`), React.createElement(MDXTag, {\n      name: \"p\",\n      components: components\n    }, `通过检查中间编译产物，我们可以在\"优化 SIL\"输出中找到初始错误编译，这可以通过在调用 `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `swiftc`), ` 时添加 `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `-emit-sil`), ` 参数获得。比较使用 `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `AutoreleasingUnsafeMutablePointer`), `（左侧）和 `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `UnsafeMutablePointer`), `（右侧）程序的优化 SIL，我们发现使用 `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `AutoreleasingUnsafeMutablePointer`), ` 时，数组存储的关键 `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `load`), ` 指令缺失。`), React.createElement(MDXTag, {\n      name: \"p\",\n      components: components\n    }, React.createElement(MDXTag, {\n      name: \"figure\",\n      components: components,\n      parentName: \"p\"\n    }, `\n    `, React.createElement(MDXTag, {\n      name: \"a\",\n      components: components,\n      parentName: \"figure\",\n      props: {\n        \"href\": \"/static/69f84a2517263e76b6cf469c762d60a7/81220/comparing-crashing-non-crashing-sil.webp\"\n      }\n    }, React.createElement(MDXTag, {\n      name: \"picture\",\n      components: components,\n      parentName: \"a\"\n    }, `\n  `, React.createElement(MDXTag, {\n      name: \"source\",\n      components: components,\n      parentName: \"picture\",\n      props: {\n        \"src\": \"/static/69f84a2517263e76b6cf469c762d60a7/0cc25/comparing-crashing-non-crashing-sil.png\",\n        \"srcSet\": [\"/static/69f84a2517263e76b6cf469c762d60a7/5116e/comparing-crashing-non-crashing-sil.png 178w\", \"/static/69f84a2517263e76b6cf469c762d60a7/92f55/comparing-crashing-non-crashing-sil.png 356w\", \"/static/69f84a2517263e76b6cf469c762d60a7/0cc25/comparing-crashing-non-crashing-sil.png 712w\", \"/static/69f84a2517263e76b6cf469c762d60a7/7ae06/comparing-crashing-non-crashing-sil.png 1068w\", \"/static/69f84a2517263e76b6cf469c762d60a7/eee47/comparing-crashing-non-crashing-sil.png 1424w\", \"/static/69f84a2517263e76b6cf469c762d60a7/38407/comparing-crashing-non-crashing-sil.png 2136w\", \"/static/69f84a2517263e76b6cf469c762d60a7/de5ec/comparing-crashing-non-crashing-sil.png 5120w\"],\n        \"sizes\": \"(max-width: 712px) 100vw, 712px\"\n      }\n    }), React.createElement(MDXTag, {\n      name: \"source\",\n      components: components,\n      parentName: \"picture\",\n      props: {\n        \"src\": \"/static/69f84a2517263e76b6cf469c762d60a7/690c8/comparing-crashing-non-crashing-sil.webp\",\n        \"srcSet\": [\"/static/69f84a2517263e76b6cf469c762d60a7/25c8a/comparing-crashing-non-crashing-sil.webp 178w\", \"/static/69f84a2517263e76b6cf469c762d60a7/60698/comparing-crashing-non-crashing-sil.webp 356w\", \"/static/69f84a2517263e76b6cf469c762d60a7/690c8/comparing-crashing-non-crashing-sil.webp 712w\", \"/static/69f84a2517263e76b6cf469c762d60a7/d7e52/comparing-crashing-non-crashing-sil.webp 1068w\", \"/static/69f84a2517263e76b6cf469c762d60a7/456ef/comparing-crashing-non-crashing-sil.webp 1424w\", \"/static/69f84a2517263e76b6cf469c762d60a7/2a654/comparing-crashing-non-crashing-sil.webp 2136w\", \"/static/69f84a2517263e76b6cf469c762d60a7/81220/comparing-crashing-non-crashing-sil.webp 5120w\"],\n        \"sizes\": \"(max-width: 712px) 100vw, 712px\"\n      }\n    }), `\n  `, React.createElement(MDXTag, {\n      name: \"img\",\n      components: components,\n      parentName: \"picture\",\n      props: {\n        \"src\": \"/static/69f84a2517263e76b6cf469c762d60a7/81220/comparing-crashing-non-crashing-sil.webp\",\n        \"alt\": \"崩溃与不崩溃的 SIL 对比\",\n        \"title\": \"崩溃与不崩溃的 SIL 对比\",\n        \"width\": 712,\n        \"height\": 401,\n        \"loading\": \"lazy\"\n      }\n    }))), `\n    `, React.createElement(MDXTag, {\n      name: \"figcaption\",\n      components: components,\n      parentName: \"figure\"\n    }, `\n        `, React.createElement(MDXTag, {\n      name: \"span\",\n      components: components,\n      parentName: \"figcaption\"\n    }, `\n            崩溃与不崩溃的 SIL 对比\n        `), `\n    `))), React.createElement(MDXTag, {\n      name: \"p\",\n      components: components\n    }, `为了确定哪个编译器过程移除了这个 `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `load`), ` 指令，我们可以使用 `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `-Xllvm`), ` 参数启用编译器中的调试打印。具体来说，我们可以使用 `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `--sil-print-function`), ` 让编译器在每次有修改时打印指定函数的 SIL：`), React.createElement(MDXTag, {\n      name: \"pre\",\n      components: components\n    }, React.createElement(MDXTag, {\n      name: \"code\",\n      components: components,\n      parentName: \"pre\",\n      props: {\n        \"className\": \"language-shell\"\n      }\n    }, `swiftc YOUR_SWIFT_SOURCE.swift -Osize \\\\\n    -Xllvm '--sil-print-function=$MangledSwiftFunctionName'\n`)), React.createElement(MDXTag, {\n      name: \"p\",\n      components: components\n    }, `此分析的关键日志可总结为：`), React.createElement(MDXTag, {\n      name: \"pre\",\n      components: components\n    }, React.createElement(MDXTag, {\n      name: \"code\",\n      components: components,\n      parentName: \"pre\",\n      props: {\n        \"className\": \"language-sil\"\n      }\n    }, `  *** SIL function after  #10338, stage MidLevel,Function, pass 37: CSE (cse)\n// closure #1 in ValueStorage.append(_:)\n...\nsil private @$s8Crashing12ValueStorageC6appendyySiFySAyAA4Data33_A856358C389441A2F6EA224BB743344FLLCGXEfU_ : $@convention(thin) @substituted <τ_0_0> (AutoreleasingUnsafeMutablePointer<Data>, Int) -> (@out τ_0_0, @error any Error) for <()> {\n...\nbb3(%17 : $Optional<AnyObject>):\n    ...\n    %26 = load %25 : $*Builtin.BridgeObject\n    ...\n  %35 = function_ref @$sSa36_reserveCapacityAssumingUniqueBuffer8oldCountySi_tFSi_Tg5 : $@convention(method) (Int, @inout Array<Int>) -> () // user: %36\n  %36 = apply %35(%34, %20) : $@convention(method) (Int, @inout Array<Int>) -> ()\n  ...\n  // load 指令仍然存在\n  %42 = load %25 : $*Builtin.BridgeObject\n  %43 = unchecked_ref_cast %42 : $Builtin.BridgeObject to $__ContiguousArrayStorageBase\n  %44 = ref_element_addr %43 : $__ContiguousArrayStorageBase, #__ContiguousArrayStorageBase.countAndCapacity\n  %45 = struct_element_addr %44 : $*_ArrayBody, #_ArrayBody._storage\n  %46 = struct_element_addr %45 : $*_SwiftArrayBodyStorage, #_SwiftArrayBodyStorage.count\n  store %41 to %46 : $*Int\n\n  *** SIL function after  #10339, stage MidLevel,Function, pass 38: RedundantLoadElimination (redundant-load-elimination)\n// closure #1 in ValueStorage.append(_:)\n...\nsil private @$s8Crashing12ValueStorageC6appendyySiFySAyAA4Data33_A856358C389441A2F6EA224BB743344FLLCGXEfU_ : $@convention(thin) @substituted <τ_0_0> (AutoreleasingUnsafeMutablePointer<Data>, Int) -> (@out τ_0_0, @error any Error) for <()> {\n...\nbb3(%17 : $Optional<AnyObject>):\n    ...\n    %26 = load %25 : $*Builtin.BridgeObject\n    ...\n  %35 = function_ref @$sSa36_reserveCapacityAssumingUniqueBuffer8oldCountySi_tFSi_Tg5 : $@convention(method) (Int, @inout Array<Int>) -> ()\n  %36 = apply %35(%34, %20) : $@convention(method) (Int, @inout Array<Int>) -> ()\n  ...\n  // load 指令被消除了\n  %42 = unchecked_ref_cast %26 : $Builtin.BridgeObject to $__ContiguousArrayStorageBase\n  %43 = ref_element_addr %42 : $__ContiguousArrayStorageBase, #__ContiguousArrayStorageBase.countAndCapacity\n  %44 = struct_element_addr %43 : $*_ArrayBody, #_ArrayBody._storage\n  %45 = struct_element_addr %44 : $*_SwiftArrayBodyStorage, #_SwiftArrayBodyStorage.count\n  store %41 to %45 : $*Int\n`)), React.createElement(MDXTag, {\n      name: \"p\",\n      components: components\n    }, `从这些日志中，我们可以清楚地看到 redundant load elimination (冗余 load 指令消除，下称 RLE) 过程删除了以下 `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `load`), ` 指令：`), React.createElement(MDXTag, {\n      name: \"pre\",\n      components: components\n    }, React.createElement(MDXTag, {\n      name: \"code\",\n      components: components,\n      parentName: \"pre\",\n      props: {\n        \"className\": \"language-sil\"\n      }\n    }, `%42 = load %25 : $*Builtin.BridgeObject\n`)), React.createElement(MDXTag, {\n      name: \"h2\",\n      components: components\n    }, `思考修复方案`), React.createElement(MDXTag, {\n      name: \"p\",\n      components: components\n    }, `要完善修复方案，我们首先需要了解 RLE。这个优化过程通过消除虚拟寄存器和实际寄存器的冗余 \"get 和 set\" 操作来优化代码。考虑下面这个有关虚拟寄存器的例子：`), React.createElement(MDXTag, {\n      name: \"pre\",\n      components: components\n    }, React.createElement(MDXTag, {\n      name: \"code\",\n      components: components,\n      parentName: \"pre\",\n      props: {\n        \"className\": \"language-sil\"\n      }\n    }, `%1 = load %x\n%2 = store %1\n%3 = load %2\nreturn %3\n`)), React.createElement(MDXTag, {\n      name: \"p\",\n      components: components\n    }, `一个更优的等效版本会立即返回 `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `%1`), `，因为 `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `%2`), ` 只是一个中间结果。这是 RLE 应该正确处理的情况。这里，我们称之为情况 1。`), React.createElement(MDXTag, {\n      name: \"pre\",\n      components: components\n    }, React.createElement(MDXTag, {\n      name: \"code\",\n      components: components,\n      parentName: \"pre\",\n      props: {\n        \"className\": \"language-sil\"\n      }\n    }, `%1 = load %x\nreturn %1\n`)), React.createElement(MDXTag, {\n      name: \"p\",\n      components: components\n    }, `然而，考虑这个更复杂的情况：`), React.createElement(MDXTag, {\n      name: \"pre\",\n      components: components\n    }, React.createElement(MDXTag, {\n      name: \"code\",\n      components: components,\n      parentName: \"pre\",\n      props: {\n        \"className\": \"language-sil\"\n      }\n    }, `%1 = load %x\ncall print(%1)\ncall Foo(%x)\n%3 = load %x // 我们能消除这一行吗？\nreturn %3\n`)), React.createElement(MDXTag, {\n      name: \"p\",\n      components: components\n    }, `在这里，消除 `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `%3 = load %x`), ` 取决于 `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `Foo`), ` 是否修改了 `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `%x`), ` 的内容。如果修改了，我们就不能直接返回 `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `%1`), `，因为 `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `%3 = load %x`), ` 加载了更新后的内容。这里，我们称之为情况 2。`), React.createElement(MDXTag, {\n      name: \"p\",\n      components: components\n    }, `现在我们可以开始看看 Swift 中 RLE 的有关实现了。其入口位于 `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `RedundantLoadElimination.swift`), ` 文件：`), React.createElement(MDXTag, {\n      name: \"pre\",\n      components: components\n    }, React.createElement(MDXTag, {\n      name: \"code\",\n      components: components,\n      parentName: \"pre\",\n      props: {\n        \"className\": \"language-swift\"\n      }\n    }, `let redundantLoadElimination = FunctionPass(name: \"redundant-load-elimination\") {\n    (function: Function, context: FunctionPassContext) in\n  eliminateRedundantLoads(in: function, ignoreArrays: false, context)\n}\n`)), React.createElement(MDXTag, {\n      name: \"p\",\n      components: components\n    }, `从这个入口点阅读代码，我们发现其算法与经典的 RLE 方法不同：`), React.createElement(MDXTag, {\n      name: \"ol\",\n      components: components\n    }, React.createElement(MDXTag, {\n      name: \"li\",\n      components: components,\n      parentName: \"ol\"\n    }, `它在每个逆序的基本块中反向迭代所有指令，以查找所有 `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"li\"\n    }, `load`), ` 指令`), React.createElement(MDXTag, {\n      name: \"li\",\n      components: components,\n      parentName: \"ol\"\n    }, `对于每个 `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"li\"\n    }, `load`), `，它检查其先前的指令以查找：`, React.createElement(MDXTag, {\n      name: \"ul\",\n      components: components,\n      parentName: \"li\"\n    }, React.createElement(MDXTag, {\n      name: \"li\",\n      components: components,\n      parentName: \"ul\"\n    }, `可用的 `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"li\"\n    }, `store`), ` 指令进行优化（对应第一种情况）`), React.createElement(MDXTag, {\n      name: \"li\",\n      components: components,\n      parentName: \"ul\"\n    }, `可用的 `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"li\"\n    }, `load`), ` 指令进行优化（对应第二种情况），如果当两个 `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"li\"\n    }, `load`), ` 之间没有对地址有副作用的函数调用的话`))), React.createElement(MDXTag, {\n      name: \"li\",\n      components: components,\n      parentName: \"ol\"\n    }, `指令扫描有复杂度预算限制`)), React.createElement(MDXTag, {\n      name: \"p\",\n      components: components\n    }, `比较 RLE 与 `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `AutoreleasingUnsafeMutablePointer`), ` 和 `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `UnsafeMutablePointer`), `\n的详细行为，我们可以获得如下日志：`), React.createElement(MDXTag, {\n      name: \"pre\",\n      components: components\n    }, React.createElement(MDXTag, {\n      name: \"code\",\n      components: components,\n      parentName: \"pre\",\n      props: {\n        \"className\": \"language-text\"\n      }\n    }, `// AutoreleasingUnsafeMutablePointer\neliminating redundant loads in function: $s8Crashing12ValueStorageC6appendyySiFySAyAA4Data33_A856358C389441A2F6EA224BB743344FLLCGXEfU_\n...\nscanning prior instructions for the load:   %42 = load %25 : $*Builtin.BridgeObject         // users: %52, %43\n...\nvisiting instruction:   %36 = apply %35(%34, %20) : $@convention(method) (Int, @inout Array<Int>) -> ()\ntransparent\n// %35 = function_ref @$sSa36_reserveCapacityAssumingUniqueBuffer8oldCountySi_tFSi_Tg5 : $@convention(method) (Int, @inout Array<Int>) -> () // user: %36\n`)), React.createElement(MDXTag, {\n      name: \"pre\",\n      components: components\n    }, React.createElement(MDXTag, {\n      name: \"code\",\n      components: components,\n      parentName: \"pre\",\n      props: {\n        \"className\": \"language-text\"\n      }\n    }, `// UnsafeMutablePointer\neliminating redundant loads in function: $s11NonCrashing12ValueStorageC6appendyySiF\n...\nscanning prior instructions for the load:   %35 = load %18 : $*Builtin.BridgeObject         // users: %45, %36\n...\nvisiting instruction:   %29 = apply %28(%27, %12) : $@convention(method) (Int, @inout Array<Int>) -> ()\noverwritten\n// %28 = function_ref @$sSa36_reserveCapacityAssumingUniqueBuffer8oldCountySi_tFSi_Tg5 : $@convention(method) (Int, @inout Array<Int>) -> () // user: %36\n`)), React.createElement(MDXTag, {\n      name: \"p\",\n      components: components\n    }, `这揭示了：`), React.createElement(MDXTag, {\n      name: \"ul\",\n      components: components\n    }, React.createElement(MDXTag, {\n      name: \"li\",\n      components: components,\n      parentName: \"ul\"\n    }, `使用 `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"li\"\n    }, `AutoreleasingUnsafeMutablePointer`), ` 时，RLE 认为数组重新分配函数对 `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"li\"\n    }, `load`), ` 指令操作数的地址是\"透明的\"，从而启用了 load 指令消除`), React.createElement(MDXTag, {\n      name: \"li\",\n      components: components,\n      parentName: \"ul\"\n    }, `使用 `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"li\"\n    }, `UnsafeMutablePointer`), ` 时，RLE 正确地认识到该函数会覆写地址，从而阻止了 load 指令消除`)), React.createElement(MDXTag, {\n      name: \"p\",\n      components: components\n    }, `对于情况 2 所属场景，Swift 6 算法检查 `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `load`), ` 的所有先前指令，以确定 `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `load`), ` 操作数的源和 `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `load`), ` 指令本身之间的函数调用的副作用。`), React.createElement(MDXTag, {\n      name: \"p\",\n      components: components\n    }, React.createElement(MDXTag, {\n      name: \"figure\",\n      components: components,\n      parentName: \"p\"\n    }, `\n    `, React.createElement(MDXTag, {\n      name: \"a\",\n      components: components,\n      parentName: \"figure\",\n      props: {\n        \"href\": \"/static/ee70b9cfda3703ee4301c0cf91291a56/98878/side-effects-analysis.webp\"\n      }\n    }, React.createElement(MDXTag, {\n      name: \"picture\",\n      components: components,\n      parentName: \"a\"\n    }, `\n  `, React.createElement(MDXTag, {\n      name: \"source\",\n      components: components,\n      parentName: \"picture\",\n      props: {\n        \"src\": \"/static/ee70b9cfda3703ee4301c0cf91291a56/0cc25/side-effects-analysis.png\",\n        \"srcSet\": [\"/static/ee70b9cfda3703ee4301c0cf91291a56/5116e/side-effects-analysis.png 178w\", \"/static/ee70b9cfda3703ee4301c0cf91291a56/92f55/side-effects-analysis.png 356w\", \"/static/ee70b9cfda3703ee4301c0cf91291a56/0cc25/side-effects-analysis.png 712w\", \"/static/ee70b9cfda3703ee4301c0cf91291a56/7ae06/side-effects-analysis.png 1068w\", \"/static/ee70b9cfda3703ee4301c0cf91291a56/eee47/side-effects-analysis.png 1424w\", \"/static/ee70b9cfda3703ee4301c0cf91291a56/38407/side-effects-analysis.png 2136w\", \"/static/ee70b9cfda3703ee4301c0cf91291a56/fd91f/side-effects-analysis.png 3136w\"],\n        \"sizes\": \"(max-width: 712px) 100vw, 712px\"\n      }\n    }), React.createElement(MDXTag, {\n      name: \"source\",\n      components: components,\n      parentName: \"picture\",\n      props: {\n        \"src\": \"/static/ee70b9cfda3703ee4301c0cf91291a56/690c8/side-effects-analysis.webp\",\n        \"srcSet\": [\"/static/ee70b9cfda3703ee4301c0cf91291a56/25c8a/side-effects-analysis.webp 178w\", \"/static/ee70b9cfda3703ee4301c0cf91291a56/60698/side-effects-analysis.webp 356w\", \"/static/ee70b9cfda3703ee4301c0cf91291a56/690c8/side-effects-analysis.webp 712w\", \"/static/ee70b9cfda3703ee4301c0cf91291a56/d7e52/side-effects-analysis.webp 1068w\", \"/static/ee70b9cfda3703ee4301c0cf91291a56/456ef/side-effects-analysis.webp 1424w\", \"/static/ee70b9cfda3703ee4301c0cf91291a56/2a654/side-effects-analysis.webp 2136w\", \"/static/ee70b9cfda3703ee4301c0cf91291a56/98878/side-effects-analysis.webp 3136w\"],\n        \"sizes\": \"(max-width: 712px) 100vw, 712px\"\n      }\n    }), `\n  `, React.createElement(MDXTag, {\n      name: \"img\",\n      components: components,\n      parentName: \"picture\",\n      props: {\n        \"src\": \"/static/ee70b9cfda3703ee4301c0cf91291a56/98878/side-effects-analysis.webp\",\n        \"alt\": \"副作用分析\",\n        \"title\": \"副作用分析\",\n        \"width\": 712,\n        \"height\": 329,\n        \"loading\": \"lazy\"\n      }\n    }))), `\n    `, React.createElement(MDXTag, {\n      name: \"figcaption\",\n      components: components,\n      parentName: \"figure\"\n    }, `\n        `, React.createElement(MDXTag, {\n      name: \"span\",\n      components: components,\n      parentName: \"figcaption\"\n    }, `\n            副作用分析\n        `), `\n    `))), React.createElement(MDXTag, {\n      name: \"p\",\n      components: components\n    }, `在这里，关键的发现是 Swift 编译器仅在 `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `load`), ` 操作数的最终源头有未知逃逸结果时才会考虑函数的副作用。通过在 `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `AliasAnalysis.swift`), ` 中的函数设置断点，我发现了两种指针类型之间的关键差异：`), React.createElement(MDXTag, {\n      name: \"p\",\n      components: components\n    }, React.createElement(MDXTag, {\n      name: \"figure\",\n      components: components,\n      parentName: \"p\"\n    }, `\n    `, React.createElement(MDXTag, {\n      name: \"a\",\n      components: components,\n      parentName: \"figure\",\n      props: {\n        \"href\": \"/static/fe416bc81e8c76587339dcc9fb2d8ea6/4e8fe/get-apply-effect-function.webp\"\n      }\n    }, React.createElement(MDXTag, {\n      name: \"picture\",\n      components: components,\n      parentName: \"a\"\n    }, `\n  `, React.createElement(MDXTag, {\n      name: \"source\",\n      components: components,\n      parentName: \"picture\",\n      props: {\n        \"src\": \"/static/fe416bc81e8c76587339dcc9fb2d8ea6/0cc25/get-apply-effect-function.png\",\n        \"srcSet\": [\"/static/fe416bc81e8c76587339dcc9fb2d8ea6/5116e/get-apply-effect-function.png 178w\", \"/static/fe416bc81e8c76587339dcc9fb2d8ea6/92f55/get-apply-effect-function.png 356w\", \"/static/fe416bc81e8c76587339dcc9fb2d8ea6/0cc25/get-apply-effect-function.png 712w\", \"/static/fe416bc81e8c76587339dcc9fb2d8ea6/7ae06/get-apply-effect-function.png 1068w\", \"/static/fe416bc81e8c76587339dcc9fb2d8ea6/eee47/get-apply-effect-function.png 1424w\", \"/static/fe416bc81e8c76587339dcc9fb2d8ea6/38407/get-apply-effect-function.png 2136w\", \"/static/fe416bc81e8c76587339dcc9fb2d8ea6/b686c/get-apply-effect-function.png 2222w\"],\n        \"sizes\": \"(max-width: 712px) 100vw, 712px\"\n      }\n    }), React.createElement(MDXTag, {\n      name: \"source\",\n      components: components,\n      parentName: \"picture\",\n      props: {\n        \"src\": \"/static/fe416bc81e8c76587339dcc9fb2d8ea6/690c8/get-apply-effect-function.webp\",\n        \"srcSet\": [\"/static/fe416bc81e8c76587339dcc9fb2d8ea6/25c8a/get-apply-effect-function.webp 178w\", \"/static/fe416bc81e8c76587339dcc9fb2d8ea6/60698/get-apply-effect-function.webp 356w\", \"/static/fe416bc81e8c76587339dcc9fb2d8ea6/690c8/get-apply-effect-function.webp 712w\", \"/static/fe416bc81e8c76587339dcc9fb2d8ea6/d7e52/get-apply-effect-function.webp 1068w\", \"/static/fe416bc81e8c76587339dcc9fb2d8ea6/456ef/get-apply-effect-function.webp 1424w\", \"/static/fe416bc81e8c76587339dcc9fb2d8ea6/2a654/get-apply-effect-function.webp 2136w\", \"/static/fe416bc81e8c76587339dcc9fb2d8ea6/4e8fe/get-apply-effect-function.webp 2222w\"],\n        \"sizes\": \"(max-width: 712px) 100vw, 712px\"\n      }\n    }), `\n  `, React.createElement(MDXTag, {\n      name: \"img\",\n      components: components,\n      parentName: \"picture\",\n      props: {\n        \"src\": \"/static/fe416bc81e8c76587339dcc9fb2d8ea6/4e8fe/get-apply-effect-function.webp\",\n        \"alt\": \"getApplyEffect 函数\",\n        \"title\": \"getApplyEffect 函数\",\n        \"width\": 712,\n        \"height\": 305,\n        \"loading\": \"lazy\"\n      }\n    }))), `\n    `, React.createElement(MDXTag, {\n      name: \"figcaption\",\n      components: components,\n      parentName: \"figure\"\n    }, `\n        `, React.createElement(MDXTag, {\n      name: \"span\",\n      components: components,\n      parentName: \"figcaption\"\n    }, `\n            getApplyEffect 函数\n        `), `\n    `))), React.createElement(MDXTag, {\n      name: \"ul\",\n      components: components\n    }, React.createElement(MDXTag, {\n      name: \"li\",\n      components: components,\n      parentName: \"ul\"\n    }, `使用 `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"li\"\n    }, `AutoreleasingUnsafeMutablePointer`), ` 时，编译器检查 `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"li\"\n    }, `load`), ` 指令的操作数的定义源是否逃逸。当确定不逃逸时，编译器将错误地假设函数没有副作用。(line 376)`), React.createElement(MDXTag, {\n      name: \"li\",\n      components: components,\n      parentName: \"ul\"\n    }, `使用 `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"li\"\n    }, `UnsafeMutablePointer`), ` 时，编译器将获取数组重新分配函数的全局副作用（可能来自 `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"li\"\n    }, `@_effects`), ` 属性。只有标记为 `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"li\"\n    }, `readOnly`), ` 或 `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"li\"\n    }, `readNone`), ` 的函数会被视为无副作用。）(line 381)`)), React.createElement(MDXTag, {\n      name: \"p\",\n      components: components\n    }, `于是我们需要对第 371 行的 `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `visit`), ` 函数进行进一步调查。该行会对 `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `load`), ` 指令的操作数执行逃逸分析。下图说明了这个过程：`), React.createElement(MDXTag, {\n      name: \"p\",\n      components: components\n    }, React.createElement(MDXTag, {\n      name: \"figure\",\n      components: components,\n      parentName: \"p\"\n    }, `\n    `, React.createElement(MDXTag, {\n      name: \"a\",\n      components: components,\n      parentName: \"figure\",\n      props: {\n        \"href\": \"/static/807e9716c55071e6b412f2f65df84dab/a216e/escape-analaysis-1.png\"\n      }\n    }, React.createElement(MDXTag, {\n      name: \"img\",\n      components: components,\n      parentName: \"a\",\n      props: {\n        \"title\": \"逃逸分析 1\",\n        \"alt\": \"逃逸分析 1\",\n        \"src\": \"/static/807e9716c55071e6b412f2f65df84dab/a216e/escape-analaysis-1.png\",\n        \"srcSet\": [\"/static/807e9716c55071e6b412f2f65df84dab/a216e/escape-analaysis-1.png 1x\", \"/static/54ed03a518d4a59e41b6cb63d4a06782/92d5f/escape-analaysis-1%402x.png 2x\", \"/static/2462b38e40b620fe5d2bfcdee027dfb0/0c673/escape-analaysis-1%403x.png 3x\"],\n        \"loading\": \"lazy\"\n      }\n    })), `\n    `, React.createElement(MDXTag, {\n      name: \"figcaption\",\n      components: components,\n      parentName: \"figure\"\n    }, `\n        `, React.createElement(MDXTag, {\n      name: \"span\",\n      components: components,\n      parentName: \"figcaption\"\n    }, `\n            逃逸分析 1\n        `), `\n    `))), React.createElement(MDXTag, {\n      name: \"p\",\n      components: components\n    }, `以下是逃逸分析的过程：`), React.createElement(MDXTag, {\n      name: \"ol\",\n      components: components\n    }, React.createElement(MDXTag, {\n      name: \"li\",\n      components: components,\n      parentName: \"ol\"\n    }, `沿着 use-def chain (使用-定义链) 向上走，分析逃逸行为`), React.createElement(MDXTag, {\n      name: \"li\",\n      components: components,\n      parentName: \"ol\"\n    }, `每一步都将构建一个路径，表示如何从该点推导出 `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"li\"\n    }, `load`), ` 指令的操作数`)), React.createElement(MDXTag, {\n      name: \"p\",\n      components: components\n    }, `但当我们遇到 `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `AutoreleasingUnsafeMutablePointer`), ` 的 `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `pointee`), ` getter 实现时情况会变得复杂。它在上述逃逸分析过程中是一个非平凡的案例：`), React.createElement(MDXTag, {\n      name: \"pre\",\n      components: components\n    }, React.createElement(MDXTag, {\n      name: \"code\",\n      components: components,\n      parentName: \"pre\",\n      props: {\n        \"className\": \"language-swift\"\n      }\n    }, `@frozen\npublic struct AutoreleasingUnsafeMutablePointer<Pointee /* TODO : class */>\n  :  _Pointer {\n  \n  @inlinable\n  public var pointee: Pointee {\n    @_transparent get {\n      // The memory addressed by this pointer contains a non-owning reference,\n      // therefore we *must not* point an \\`UnsafePointer<AnyObject>\\` to\n      // it---otherwise we would allow the compiler to assume it has a +1\n      // refcount, enabling some optimizations that wouldn't be valid.\n      //\n      // Instead, we need to load the pointee as a +0 unmanaged reference. For\n      // an extra twist, \\`Pointee\\` is allowed (but not required) to be an\n      // optional type, so we actually need to load it as an optional, and\n      // explicitly handle the nil case.\n      let unmanaged =\n        UnsafePointer<Optional<Unmanaged<AnyObject>>>(_rawValue).pointee\n      return _unsafeReferenceCast(\n        unmanaged?.takeUnretainedValue(),\n        to: Pointee.self)\n    }\n    ...\n  }\n  \n  ...\n}\n`)), React.createElement(MDXTag, {\n      name: \"p\",\n      components: components\n    }, `实现细节揭示，`, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `AutoreleasingUnsafeMutablePointer`), ` 必须将引用从 `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `Optional<Unmanaged<AnyObject>>`), ` 转换为 `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `Pointee`), ` 类型以维持 +0 引用计数。这种转换通过 `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `_unsafeReferenceCast`), ` 函数执行：`), React.createElement(MDXTag, {\n      name: \"pre\",\n      components: components\n    }, React.createElement(MDXTag, {\n      name: \"code\",\n      components: components,\n      parentName: \"pre\",\n      props: {\n        \"className\": \"language-swift\"\n      }\n    }, `@_transparent\n@unsafe\npublic func _unsafeReferenceCast<T, U>(_ x: T, to: U.Type) -> U {\n  return Builtin.castReference(x)\n}\n`)), React.createElement(MDXTag, {\n      name: \"p\",\n      components: components\n    }, `编译器将其转换为 `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `Builtin.castReference`), ` 函数，最终在 SIL 中表示为 `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `unchecked_ref_cast`), ` 指令：`), React.createElement(MDXTag, {\n      name: \"pre\",\n      components: components\n    }, React.createElement(MDXTag, {\n      name: \"code\",\n      components: components,\n      parentName: \"pre\",\n      props: {\n        \"className\": \"language-sil\"\n      }\n    }, `%y = unchecked_ref_cast %x : $SourceSILType to $DesintationSILType\n`)), React.createElement(MDXTag, {\n      name: \"p\",\n      components: components\n    }, `因为 `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `AutoreleasingUnsafeMutablePointer`), ` 的引入，使得 `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `$SourceSILType`), ` 或 `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `$DesintationSILType`), ` 可能是 `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `Optional`), ` 类型，最终导致了问题：`), React.createElement(MDXTag, {\n      name: \"pre\",\n      components: components\n    }, React.createElement(MDXTag, {\n      name: \"code\",\n      components: components,\n      parentName: \"pre\",\n      props: {\n        \"className\": \"language-sil\"\n      }\n    }, `%y = unchecked_ref_cast %x : $Optional<AnyObject> to $Data\n`)), React.createElement(MDXTag, {\n      name: \"p\",\n      components: components\n    }, `此指令可以在 `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `Optional`), ` 和非 `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `Optional`), ` 类型之间进行转换，有效地包装或解包值。由于逃逸分析沿着 use-def chain (使用-定义链) 走，路径必须严格反映如何从定义点推导出 `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `load`), ` 操作数，这些隐式的 `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `Optional`), ` 转换会创建的路径不匹配，如图所示：`), React.createElement(MDXTag, {\n      name: \"p\",\n      components: components\n    }, React.createElement(MDXTag, {\n      name: \"figure\",\n      components: components,\n      parentName: \"p\"\n    }, `\n    `, React.createElement(MDXTag, {\n      name: \"a\",\n      components: components,\n      parentName: \"figure\",\n      props: {\n        \"href\": \"/static/f45ea8c289ffcfca0279317186798cfa/a216e/escape-analaysis-2.png\"\n      }\n    }, React.createElement(MDXTag, {\n      name: \"img\",\n      components: components,\n      parentName: \"a\",\n      props: {\n        \"title\": \"逃逸分析 2\",\n        \"alt\": \"逃逸分析 2\",\n        \"src\": \"/static/f45ea8c289ffcfca0279317186798cfa/a216e/escape-analaysis-2.png\",\n        \"srcSet\": [\"/static/f45ea8c289ffcfca0279317186798cfa/a216e/escape-analaysis-2.png 1x\", \"/static/fd7aa821b52b651595f05efa15865fd9/92d5f/escape-analaysis-2%402x.png 2x\", \"/static/d6a3db510965604678cf86e72cfabf04/0c673/escape-analaysis-2%403x.png 3x\"],\n        \"loading\": \"lazy\"\n      }\n    })), `\n    `, React.createElement(MDXTag, {\n      name: \"figcaption\",\n      components: components,\n      parentName: \"figure\"\n    }, `\n        `, React.createElement(MDXTag, {\n      name: \"span\",\n      components: components,\n      parentName: \"figcaption\"\n    }, `\n            逃逸分析 2\n        `), `\n    `))), React.createElement(MDXTag, {\n      name: \"p\",\n      components: components\n    }, `通过检查 `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `WalkUtils.swift`), ` 中的 `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `walkUpDefault`), ` 函数我们可以确认这一假设：该函数在向上走期间处理各种指令类型，但缺乏对 `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `unchecked_ref_cast`), ` 中 `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `Optional`), ` 转换的适当处理：`), React.createElement(MDXTag, {\n      name: \"pre\",\n      components: components\n    }, React.createElement(MDXTag, {\n      name: \"code\",\n      components: components,\n      parentName: \"pre\",\n      props: {\n        \"className\": \"language-swift\"\n      }\n    }, `public mutating func walkUpDefault(value def: Value, path: Path) -> WalkResult {\n    switch def {\n    ...\n    case let urc as UncheckedRefCastInst:\n      if urc.type.isClassExistential || urc.fromInstance.type.isClassExistential {\n        // Sometimes \\`unchecked_ref_cast\\` is misused to cast between AnyObject and a class (instead of\n        // init_existential_ref and open_existential_ref).\n        // We need to ignore this because otherwise the path wouldn't contain the right \\`existential\\` field kind.\n        return rootDef(value: urc, path: path)\n      }\n      return walkUp(value: urc.fromInstance, path: path)\n      ...\n    }\n}\n`)), React.createElement(MDXTag, {\n      name: \"h2\",\n      components: components\n    }, `修复方案`), React.createElement(MDXTag, {\n      name: \"p\",\n      components: components\n    }, `解决方案是在 use-def chain (使用-定义链) 走向上游时考虑 `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `Optional`), ` 和非 `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `Optional`), ` 类型转换：`), React.createElement(MDXTag, {\n      name: \"pre\",\n      components: components\n    }, React.createElement(MDXTag, {\n      name: \"code\",\n      components: components,\n      parentName: \"pre\",\n      props: {\n        \"className\": \"language-swift\"\n      }\n    }, `public mutating func walkUpDefault(value def: Value, path: Path) -> WalkResult {\n    switch def {\n    ...\n    case let urc as UncheckedRefCastInst:\n      if urc.type.isClassExistential || urc.fromInstance.type.isClassExistential {\n        // Sometimes \\`unchecked_ref_cast\\` is misused to cast between AnyObject and a class (instead of\n        // init_existential_ref and open_existential_ref).\n        // We need to ignore this because otherwise the path wouldn't contain the right \\`existential\\` field kind.\n        return rootDef(value: urc, path: path)\n      }\n      switch (urc.type.isOptional, urc.fromInstance.type.isOptional) {\n        case (true, false):\n          if let path = path.popIfMatches(.enumCase, index: 1) {\n            return walkUp(value: urc.fromInstance, path: path)\n          } else {\n            return unmatchedPath(value: urc.fromInstance, path: path)\n          }\n        case (false, true):\n          return walkUp(value: urc.fromInstance, path: path.push(.enumCase, index: 1))\n        default:\n          return walkUp(value: urc.fromInstance, path: path)\n      }\n        ...\n        }\n}\n`)), React.createElement(MDXTag, {\n      name: \"p\",\n      components: components\n    }, `下图说明了这个修复如何适应逃逸分析过程中的 `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `Optional`), ` 和非 `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `Optional`), ` 类型转换。当逃逸分析过程遇到 `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `Optional`), ` 和非 `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `Optional`), ` 类型之间的 `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `unchecked_ref_cast`), ` 时，该修复通过调整路径以考虑枚举 case 差异，确保了正确的路径转换。`), React.createElement(MDXTag, {\n      name: \"p\",\n      components: components\n    }, React.createElement(MDXTag, {\n      name: \"figure\",\n      components: components,\n      parentName: \"p\"\n    }, `\n    `, React.createElement(MDXTag, {\n      name: \"a\",\n      components: components,\n      parentName: \"figure\",\n      props: {\n        \"href\": \"/static/f253b0b736cb4a7a4ee741efae3b34bb/a216e/escape-analaysis-3.png\"\n      }\n    }, React.createElement(MDXTag, {\n      name: \"img\",\n      components: components,\n      parentName: \"a\",\n      props: {\n        \"title\": \"逃逸分析 3\",\n        \"alt\": \"逃逸分析 3\",\n        \"src\": \"/static/f253b0b736cb4a7a4ee741efae3b34bb/a216e/escape-analaysis-3.png\",\n        \"srcSet\": [\"/static/f253b0b736cb4a7a4ee741efae3b34bb/a216e/escape-analaysis-3.png 1x\", \"/static/da779ffdeafaa6a0513f4cf5e4f6dcaa/92d5f/escape-analaysis-3%402x.png 2x\", \"/static/ea0d911803efb5a35e1ae378c6fd9c37/0c673/escape-analaysis-3%403x.png 3x\"],\n        \"loading\": \"lazy\"\n      }\n    })), `\n    `, React.createElement(MDXTag, {\n      name: \"figcaption\",\n      components: components,\n      parentName: \"figure\"\n    }, `\n        `, React.createElement(MDXTag, {\n      name: \"span\",\n      components: components,\n      parentName: \"figcaption\"\n    }, `\n            逃逸分析 3\n        `), `\n    `))), React.createElement(MDXTag, {\n      name: \"p\",\n      components: components\n    }, `在 def-use chain (定义-使用链) 分析中，`, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `walkDownDefault`), ` 函数也需要类似的更改：`), React.createElement(MDXTag, {\n      name: \"pre\",\n      components: components\n    }, React.createElement(MDXTag, {\n      name: \"code\",\n      components: components,\n      parentName: \"pre\",\n      props: {\n        \"className\": \"language-swift\"\n      }\n    }, `public mutating func walkDownDefault(value operand: Operand, path: Path) -> WalkResult {\n    let instruction = operand.instruction\n    switch instruction {\n        ...\n        case let urc as UncheckedRefCastInst:\n      if urc.type.isClassExistential || urc.fromInstance.type.isClassExistential {\n        // Sometimes \\`unchecked_ref_cast\\` is misused to cast between AnyObject and a class (instead of\n        // init_existential_ref and open_existential_ref).\n        // We need to ignore this because otherwise the path wouldn't contain the right \\`existential\\` field kind.\n        return leafUse(value: operand, path: path)\n      }\n      switch (urc.type.isOptional, urc.fromInstance.type.isOptional) {\n        case (true, false):\n          return walkDownUses(ofValue: operand, path: path.push(.enumCase, index: 1))\n        case (false, true):\n          if let path = path.popIfMatches(.enumCase, index: 1) {\n            return walkDownUses(ofValue: operand, path: path)\n          } else {\n            return unmatchedPath(value: operand, path: path)\n          }\n        default:\n          return walkDownUses(ofValue: operand, path: path)\n      }\n      ...\n    }\n}\n`)), React.createElement(MDXTag, {\n      name: \"p\",\n      components: components\n    }, `实施此修复后，编译使用 `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `AutoreleasingUnsafeMutablePointer`), ` 的代码产生的日志显示 RLE 正确识别潜在的副作用：`), React.createElement(MDXTag, {\n      name: \"pre\",\n      components: components\n    }, React.createElement(MDXTag, {\n      name: \"code\",\n      components: components,\n      parentName: \"pre\",\n      props: {\n        \"className\": \"language-text\"\n      }\n    }, `eliminating redundant loads in function: $s8Crashing12ValueStorageC6appendyySiF\nscanning prior instructions for the load:   %45 = load %28 : $*Builtin.BridgeObject         // users: %55, %46\n...\nvisiting instruction:   %39 = apply %38(%37, %23) : $@convention(method) (Int, @inout Array<Int>) -> ()\noverwritten\n`)), React.createElement(MDXTag, {\n      name: \"p\",\n      components: components\n    }, `优化后的 SIL 现在保留了数组重新分配后的关键 `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `load`), ` 指令：`), React.createElement(MDXTag, {\n      name: \"pre\",\n      components: components\n    }, React.createElement(MDXTag, {\n      name: \"code\",\n      components: components,\n      parentName: \"pre\",\n      props: {\n        \"className\": \"language-sil\"\n      }\n    }, `// ValueStorage.append(_:)\n// Isolation: unspecified\nsil [noinline] @$s8Crashing12ValueStorageC6appendyySiF : $@convention(method) (Int, @guaranteed ValueStorage) -> () {\n[%1: noescape, read c*.v**, write c*.v**, copy c*.v**, destroy c*.v**]\n[global: read,write,copy,destroy,allocate,deinit_barrier]\n\n...\n\nbb3(%20 : $Optional<AnyObject>):\n    ...\n  // function_ref specialized Array._reserveCapacityAssumingUniqueBuffer(oldCount:)\n  %38 = function_ref @$sSa36_reserveCapacityAssumingUniqueBuffer8oldCountySi_tFSi_Tg5 : $@convention(method) (Int, @inout Array<Int>) -> ()\n  %39 = apply %38(%37, %23) : $@convention(method) (Int, @inout Array<Int>) -> ()\n  %45 = load %28 : $*Builtin.BridgeObject\n  ...\n} // end sil function '$s8Crashing12ValueStorageC6appendyySiF'\n`)), React.createElement(MDXTag, {\n      name: \"h2\",\n      components: components\n    }, `调试 Swift 编译器的技巧`), React.createElement(MDXTag, {\n      name: \"h3\",\n      components: components\n    }, `获取 Swift 编译器的中间产物`), React.createElement(MDXTag, {\n      name: \"p\",\n      components: components\n    }, `要检查 Swift 编译器在每个编译阶段的中间表示：`), React.createElement(MDXTag, {\n      name: \"pre\",\n      components: components\n    }, React.createElement(MDXTag, {\n      name: \"code\",\n      components: components,\n      parentName: \"pre\",\n      props: {\n        \"className\": \"language-shell\"\n      }\n    }, `swiftc YourSwiftSource.swift -Osize -emit-silgen > YourSwiftSource.silgen.sil # 生成原始 SIL\nswiftc YourSwiftSource.swift -Osize -emit-sil > YourSwiftSource.sil.sil # 生成优化 SIL\nswiftc YourSwiftSource.swift -Osize -emit-irgen > YourSwiftSource.irgen.ll # 生成原始 LLVM IR\nswiftc YourSwiftSource.swift -Osize -emit-ir > YourSwiftSource.ir.ll # 生成优化 LLVM IR\n`)), React.createElement(MDXTag, {\n      name: \"h3\",\n      components: components\n    }, `利用 LLVM 传递参数`), React.createElement(MDXTag, {\n      name: \"p\",\n      components: components\n    }, `LLVM 提供了许多可与 Swift 一起使用的传递参数：`), React.createElement(MDXTag, {\n      name: \"pre\",\n      components: components\n    }, React.createElement(MDXTag, {\n      name: \"code\",\n      components: components,\n      parentName: \"pre\",\n      props: {\n        \"className\": \"language-shell\"\n      }\n    }, `# 打印指定函数的 SIL 更改\nswiftc -Xllvm '--sil-print-function=$MangledSwiftFunctionName'\n# 在运行每个 SIL 过程前打印其名称\nswiftc -Xllvm '--sil-print-pass-name=pass-name'\n# 打印内联到其他函数中的函数\nswiftc -Xllvm '--sil-print-inlining-callee=true'\n`)), React.createElement(MDXTag, {\n      name: \"h3\",\n      components: components\n    }, `构建 Swift 编译器`), React.createElement(MDXTag, {\n      name: \"p\",\n      components: components\n    }, `需要注意的是，在这篇文章中，我们是在调试编译器的行为细节，但 Swift 编程语言和标准库捆绑在一起。由于问题与 `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `Array.append`), ` 函数的内联相关，我们应该构建一个 debug 版本的编译器和一个 release 版本的标准库，以确保 `, React.createElement(MDXTag, {\n      name: \"inlineCode\",\n      components: components,\n      parentName: \"p\"\n    }, `Array.append`), ` 的内联成本尽可能低。你可以使用以下命令实现：`), React.createElement(MDXTag, {\n      name: \"pre\",\n      components: components\n    }, React.createElement(MDXTag, {\n      name: \"code\",\n      components: components,\n      parentName: \"pre\",\n      props: {\n        \"className\": \"language-shell\"\n      }\n    }, `utils/build-script --no-swift-stdlib-assertions \\\\\n    --skip-ios --skip-tvos --skip-watchos --skip-build-benchmarks\n`)), React.createElement(MDXTag, {\n      name: \"h3\",\n      components: components\n    }, `SIL 和 LLVM IR 的语法高亮`), React.createElement(MDXTag, {\n      name: \"p\",\n      components: components\n    }, `你可以在 VS Code（或 Cursor）扩展市场中搜索\"WeZZard\"以获取相关 IDE 中的 SIL 语法高亮。`), React.createElement(MDXTag, {\n      name: \"p\",\n      components: components\n    }, `你可以在 VS Code（或 Cursor）扩展市场中找到 Ingvar Stepanyan 的\"LLVM\"扩展，以获取相关 IDE 中的 LLVM IR 语法高亮。`));\n  }\n\n}\nMDXContent.isMDXComponent = true;","scope":""},"headings":[{"value":"调查崩溃现场","depth":2},{"value":"为什么 Swift 编译器删除了代码？","depth":2},{"value":"思考修复方案","depth":2},{"value":"修复方案","depth":2},{"value":"调试 Swift 编译器的技巧","depth":2},{"value":"获取 Swift 编译器的中间产物","depth":3},{"value":"利用 LLVM 传递参数","depth":3},{"value":"构建 Swift 编译器","depth":3},{"value":"SIL 和 LLVM IR 的语法高亮","depth":3}]}}},"earlierPostExcerpt":{"slug":"/post/2023/08/swift-macro-revisited-traps-and-pitfalls-1034","title":"再探 Swift 宏 - 陷阱与缺陷","subtitle":"","createdTime":"2023-08-10T00:00:00.000Z","tags":["Swift","宏"],"category":"编程","file":{"childMdx":{"excerpt":"在之前的文章中，我们学习了使得 Swift 宏独一无二的优势和本质。文中的示例工作正常，但是我们现在可以放心大胆地实现任何 Swift 宏了吗？ 答案是否定的。 给 Swift 宏带来优势的特性也会引入陷阱与缺陷，从而让程序员自己给自己造成麻烦。在本文中，我想向你展示我发现的一些问题以及避免它们的方法。 陷阱与缺陷 控制流的潜在混乱 在之前的文章中的  #unwrap  示例中，Swift 宏展开可能涉及到 控制流操控 和 词法作用域共享 ： 展开之前： 展开之后： 由于示例宏展开中涉及控制流的  return…"}}},"laterPostExcerpt":{"slug":"/post/2025/09/build-your-first-agentic-loop-9d22","title":"打造你的第一个 7x24 Agent 循环","subtitle":"","createdTime":"2025-09-25T00:00:00.000Z","tags":["AI","Agent"],"category":"Programming","file":{"childMdx":{"excerpt":"小趣闻：  2025 年 9 月，我在 Claude Code 上的用量飙到了  3000 美元 。 原因很简单：我把 Claude Code 放进了一个  7x24 agent 循环  里帮我打理业余项目。我睡着时，循环会评估现场、派生 subagents、让事情持续推进。等我醒来，进度已经悄悄向前走了一截。 但这种魔法并不是 Claude 独有；只要你理解了配置的精髓，就能把这个魔法复刻到任何实现了相同要件的模型与 agent runtime 上。 下面就带你从头搭建。 幕后的秘密 事实是：最新的 Claude 4、GPT-5 这类大模型已经在  agent…"}}}},"pageContext":{"postId":"46abd102-d678-5362-9d51-00ffd4a02f90","earlierPostId":"c743b528-1454-53f9-9a0b-8aebda6e8d68","laterPostId":"fc91b6bc-17af-54a8-9f29-dc69f93daae6"}}