关于设置的一点
1个
我将深入探讨Swift编译器内部。 我认为最好做一点笔记并描述整个旅程的步骤。
目前,我对Swift或LLVM的内部知识一无所知,但对我在大学期间学到的编译器有一些常识。
因此,这些说明对将要跟随我并了解快速编译器实际工作原理的每个人都是有用的。 我将在每个步骤之后写一个简短的摘要。 而且,我认为从公开准备步骤开始非常重要,以便在我的机器或OS发生问题时能够重现环境。
步骤1.获取源代码并进行一些调整
我从探索swift.org开始。 有一个名为“编译器和标准库”的页面,其中包含编译器体系结构的简要概述以及指向主存储库的链接。 可通过github获得源代码。 README.md包含使用Ninja和CMake设置和构建编译器以及创建.xcodeproj的所有信息。 我选择了后者。
〜$ utils / build-script -x
它可能会运行很长时间。 在构建过程中,我试图准备自己阅读swift.org上的所有可用文档。 它指出编译器由几个模块组成,每个模块代表下一个抽象级别:解析,语义分析,SIL生成,优化,最后是LLVM IR生成阶段。 我将重点介绍官方文档中缺少的内容。
生成的Swift.xcodeproj
可以在build / Xcode-DebugAssert / swift-macosx-x86_64 /子目录中找到。 当我第一次打开它时,Xcode用一个模式提示向我打招呼:
但是我可以完成任务,并通过一个简单的步骤解决了该问题:
我做了什么? 我为尚未存在的目标BUILD_ALL添加了构建方案,并设置了可执行文件以使用lldb进行调试:
太容易了。 因此,是时候启动并尝试调试可执行文件了,不是吗? 设置断点,按Cmd + R
并…
程序以退出代码结束:0
执行并没有在我的断点处停止。 嗯当然了 我尚未将源文件传递给进程。 使用/path/to/working/dir/A.swift和…调整启动时传递的参数 。
程序以退出代码结束:0
在这里我卡住了。
步骤2.探索执行流程
在继续之前,让我们深入了解swiftc的工作原理。 我的意思是,当您通过命令行调用swiftc并将其传递给源文件时,它会做什么。 你知道吗? 我也不。
我认为这非常简单:迅速的编译器读取输入参数,实例化环境,然后启动lexer,解析器,AST分析器等 。 它的工作方式是这样,但前提是您传递了命令行参数的特定顺序。 通常,它只是设置并启动其他程序来编译,分析和链接可执行文件。 您可以通过传递-v(表示详细信息)标志来找出对其他程序的实际调用顺序。
〜$ swiftc -v A.swift
Apple Swift版本3.0.1(swiftlang-800.0.58.6 clang-800.0.42.1)
目标:x86_64-apple-macosx10.9
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/swift -frontend -c -primary-file A.swift -target x86_64-apple-macosx10.9 -sdk / path / to / SDKs /MacOSX10.12.sdk-模块名称A -o /path/to/tmp/dir/A-5654c7.o
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/ld /path/to/tmp/dir/A-5654c7.o -force_load /Applications/Xcode.app/Contents/Developer/Toolchains /XcodeDefault.xctoolchain/usr/lib/arc/libarclite_macosx.a -framework CoreFoundation -syslibroot /path/to/SDKs/MacOSX10.12.sdk -lobjc -lSystem -arch x86_64 -L /Applications/Xcode.app/Contents/Developer /Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/macosx -rpath /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/macosx -macosx_version_min 10.9.0 -no_objc_category_merging -o A
如果要遍历和调试Lexer,必须重现第一个命令以启动swift编译器前端。 因此,我们必须将所有调用中的参数复制到启动时传递的参数部分:
好。 现在开始运行! 在那一步之后,我在工作目录中找到了绝对新的Ao
文件。 并且,如果在Lexer.cpp或Parser.cpp中的某个位置放置断点,则编译器将在请求的位置停止。
我在Lexer::lex(Token &Result)
例程中留下了一个。 下次,我将从这一点开始,也许幸运的话,找出如何使用swiftc
从单词列表中获取标记列表的方法。
够了,伙计们!
从一个空的swift文件编译的二进制文件的PS内容: