Skip to content
This repository was archived by the owner on Feb 2, 2022. It is now read-only.

Commit 5ff24b1

Browse files
committed
check for pdf output.
1 parent beefe34 commit 5ff24b1

File tree

18 files changed

+40
-40
lines changed

18 files changed

+40
-40
lines changed

content/1/chapter2/4.tex

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@
160160
endmacro()
161161
\end{tcolorbox}
162162

163-
包含该模块,可以使用add\underline{~}tinylang\underline{~}subdirectory()、add\underline{~}tinylang\underline{~}library()、add\underline{~}tinylang\underline{~}executable()和add\underline{~}tinylang\underline{~}tool()函数。这些是LLVM(在AddLLVM模块中)提供的函数包装器。tinylang\underline{~}subdirectory()为构建添加了一个新的源目录。此外,还添加了一个新的CMake选项。使用此选项,用户可以控制是否应该编译目录的内容。使用add\underline{~}tinylang\underline{~}library(),可以定义库并安装。Add \underline{~}tinylang\underline{~}executable()定义了可执行文件,Add \underline{~}tinylang\underline{~}tool()定义了同样安装的可执行文件。\par
163+
包含该模块,可以使用add\underline{~}tinylang\underline{~}subdirectory()、add\underline{~}tinylang\underline{~}library()、add\underline{~}tinylang\underline{~}exe\allowbreak cutable()和add\underline{~}tinylang\underline{~}tool()函数。这些是LLVM(在AddLLVM模块中)提供的函数包装器。tinylang\underline{~}subdirectory()为构建添加了一个新的源目录。此外,还添加了一个新的CMake选项。使用此选项,用户可以控制是否应该编译目录的内容。使用add\underline{~}tinylang\underline{~}library(),可以定义库并安装。Add \underline{~}tinylang\underline{~}executable()定义了可执行文件,Add \underline{~}tinylang\underline{~}tool()定义了同样安装的可执行文件。\par
164164

165165
lib目录中,即使没有源代码,也需要CMakeLists.txt文件,必须包含这个项目库的源目录。打开文本编辑器,将以下内容保存在文件中:\par
166166

content/2/chapter4/8.tex

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -219,11 +219,11 @@
219219
}
220220
\end{lstlisting}
221221

222-
DeclList是一个名为std::vector<Decl*>的声明列表,而IdentList是一个类型为std::vector<std::pair<SMLoc, StringRef>>的位置和标识符列表。\par
222+
DeclList是一个名为std::vector<Decl*>的声明列表,而IdentList是一个类型为std::vector<\allowbreak std::pair<SMLoc, StringRef>>的位置和标识符列表。\par
223223

224224
parseQualident()方法返回一个声明。本例中,应该是一个类型声明。\par
225225

226-
解析器类知道语义分析器类Sema的一个实例,该实例存储在Actions成员中。对actOnVariableDeclaration()的调用运行语义分析器和AST构造。实现在lib/Sema/Sema.cpp中:\par
226+
解析器类知道语义分析器类Sema的一个实例,该实例存储在Actions成员中。对actOnVariable\allowbreak Declaration()的调用运行语义分析器和AST构造。实现在lib/Sema/Sema.cpp中:\par
227227

228228
\begin{lstlisting}[caption={}]
229229
void Sema::actOnVariableDeclaration(DeclList &Decls,

content/2/chapter6/4.tex

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,10 @@
88
\begin{tcolorbox}[colback=white,colframe=black]
99
TYPE Shape = RECORD \\
1010
\hspace*{3cm}color: INTEGER; \\
11-
\hspace*{3cm}PROCEDURE (VAR s: Shape) GetColor(): \
11+
\hspace*{3cm}PROCEDURE (VAR s: Shape) GetColor(): \\
1212
\hspace*{3.5cm}INTEGER; \\
1313
\hspace*{3cm}PROCEDURE (VAR s: Shape) Area(): REAL;\\
14-
\hspace*{2.5cm}cmEND;
14+
\hspace*{2.5cm}END;
1515
\end{tcolorbox}
1616

1717
GetColor方法只返回颜色编号:\par

content/2/chapter7/2.tex

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -337,7 +337,7 @@
337337
{Ptr});
338338
\end{lstlisting}
339339

340-
\item 通过调用puts()函数来处理异常,将消息打印到控制台。为此,首先通过调用CreateGlobalStringPtr()函数生成一个指向该字符串的指针,然后在生成的调用puts()函数中将该指针作为参数传入:
340+
\item 通过调用puts()函数来处理异常,将消息打印到控制台。为此,首先通过调用CreateGlobalString\allowbreak Ptr()函数生成一个指向该字符串的指针,然后在生成的调用puts()函数中将该指针作为参数传入:
341341
\begin{lstlisting}[caption={}]
342342
Builder.CreateCall(EndCatchFty, EndCatchFn);
343343
Builder.CreateRet(Int32Zero);

content/2/chapter7/3.tex

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,7 @@
219219
\end{lstlisting}
220220
\end{enumerate}
221221

222-
要启用TBAA元数据的生成,只需要将元数据附加到生成的加载和存储指令。例如,在CGProcedure::writeVariable()中,对全局变量进行存储,使用存储指令:\par
222+
要启用TBAA元数据的生成,只需要将元数据附加到生成的加载和存储指令。例如,在CGProced\allowbreak ure::writeVariable()中,对全局变量进行存储,使用存储指令:\par
223223

224224
\begin{lstlisting}[caption={}]
225225
Builder.CreateStore(Val, CGM.getGlobal(D));

content/2/chapter7/4.tex

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,9 @@
1111
\begin{itemize}
1212
\item lvm::DIFile: 使用文件名和包含该文件的目录的绝对路径来描述一个文件,可以使用createFile()方法来创建。一个文件可以包含主编译单元,也可以包含导入的声明。
1313

14-
\item llvm::DICompileUnit: 这用于描述当前的编译单元,还需要指定源语言、特定于编译器的生成器字符串、是否启用了优化,当然还有编译单元所在的DIFile。您可以通过调用createCompileUnit()来创建。
14+
\item llvm::DICompileUnit: 这用于描述当前的编译单元,还需要指定源语言、特定于编译器的生成器字符串、是否启用了优化,当然还有编译单元所在的DIFile。您可以通过调用createCompile\allowbreak Unit()来创建。
1515

16-
\item llvm::DISubprogram: 描述一个函数。其中重要的信息有:作用域(通常是嵌套函数的DICompileUnit或DISubprogram)、函数名、修饰过的函数名和函数类型。可以通过调用createFunction()来创建。
16+
\item llvm::DISubprogram: 描述一个函数。其中重要的信息有:作用域(通常是嵌套函数的DIComp\allowbreak ileUnit或DISubprogram)、函数名、修饰过的函数名和函数类型。可以通过调用createFunction()来创建。
1717

1818
\item llvm::DILexicalBlock: 描述了如何在语言中对块作用域进行建模的词汇块。可以通过调用createLexicalBlock()来创建。
1919

@@ -24,7 +24,7 @@
2424
\begin{itemize}
2525
\item createBasicType()函数返回一个指向llvm::DIBasicType类的指针,创建元数据来描述基本类型,如tinylang中的INTEGER或C++中的int。除了类型的名称之外,所需参数是以位为单位大小和编码的。例如,有符号类型还是无符号类型。
2626

27-
\item 有几种方法可以构造复合数据类型的元数据,用llvm::DIComposite类表示。可以使用createArrayType()、createStructType()、createUnionType()和createVectorType()函数实例化数组、结构、联合和向量数据类型的元数据。这些函数需要相应的参数—例如,数组类型的基类型和下标,或者结构类型的字段成员列表。
27+
\item 有几种方法可以构造复合数据类型的元数据,用llvm::DIComposite类表示。可以使用create\allowbreak ArrayType()、createStructType()、createUnionType()和createVectorType()函数实例化数组、结构、联合和向量数据类型的元数据。这些函数需要相应的参数—例如,数组类型的基类型和下标,或者结构类型的字段成员列表。
2828

2929
\item 还有一些方法支持枚举、模板、类等。
3030
\end{itemize}
@@ -202,7 +202,7 @@
202202

203203
调试器允许程序员逐行调试应用程序。为此,调试器需要知道哪个机器指令属于源代码中的哪一行,LLVM允许在每个指令中添加一个源位置。上一节中,创建了llvm::DILocation类型的位置信息。调试位置包含的信息不仅仅是行、列和范围。如果需要,可以指定这一行内联到的范围。还可以指出此调试位置属于隐式代码,即前端生成的但不在源代码中的代码。\par
204204

205-
将它附加到指令之前,必须将调试位置包装在llvm::DebugLoc对象中。为此,只需将从llvm::DILocation类获得的位置信息传递给llvm::DebugLoc构造函数。通过这种包装,LLVM可以跟踪位置信息。虽然源代码中的位置显然没有改变,但在优化期间可以删除为源代码级语句或表达式生成的机器码。封装有助于处理这些可能的更改。\par
205+
将它附加到指令之前,必须将调试位置包装在llvm::DebugLoc对象中。为此,只需将从llvm::DI\allowbreak Location类获得的位置信息传递给llvm::DebugLoc构造函数。通过这种包装,LLVM可以跟踪位置信息。虽然源代码中的位置显然没有改变,但在优化期间可以删除为源代码级语句或表达式生成的机器码。封装有助于处理这些可能的更改。\par
206206

207207
添加行号信息主要可以归结为从AST检索行号信息并将其添加到生成的指令中。指令类有setDebugLoc()方法,将位置信息附加到指令上。\par
208208

@@ -211,7 +211,7 @@
211211
\hspace*{\fill} \par %插入空行
212212
\textbf{为tinylang添加调试支持}
213213

214-
我们将调试元数据的生成封装在新的CGDebugInfo类中。把声明放到tinylang/CodeGen/CGDebugInfo.h头文件中,把定义放到tinylang/CodeGen/CGDebugInfo.cpp文件中。\par
214+
我们将调试元数据的生成封装在新的CGDebugInfo类中。把声明放到tinylang/CodeGen/CG\allowbreak DebugInfo.h头文件中,把定义放到tinylang/CodeGen/CGDebugInfo.cpp文件中。\par
215215

216216
CGDebugInfo类有五个重要成员。我们需要引用模块CGM的代码生成器,因为我们需要将类型从AST表示转换为LLVM类型。当然,还需要llvm::DIBuilder类的一个实例,称为DBuilder,如上一节所述。还需要一个指向编译单元实例的指针,我们将它存储在名为CU的成员中。\par
217217

content/2/chapter8/3.tex

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@
8686
目前为止,已经实现了新Pass的功能。稍后将对out-of-tree Pass重用此实现。对于LLVM树中的解决方案,必须更改LLVM中的几个文件来声明新的Pass:\par
8787

8888
\begin{enumerate}
89-
\item 首先,需要将CMakeLists.txt添加到源文件夹。这个文件包含一个新的LLVM库名称LLVMCountIR的构建说明。新库需要链接到LLVM Support组件,因为我们使用了调试和统计基础设施,还需要链接到LLVM Core组件,其中包含LLVM IR的定义:
89+
\item 首先,需要将CMakeLists.txt添加到源文件夹。这个文件包含一个新的LLVM库名称LLVM\allowbreak CountIR的构建说明。新库需要链接到LLVM Support组件,因为我们使用了调试和统计基础设施,还需要链接到LLVM Core组件,其中包含LLVM IR的定义:
9090
\begin{tcolorbox}[colback=white,colframe=black]
9191
add\underline{~}llvm\underline{~}component\underline{~}library(LLVMCountIR \\
9292
\hspace*{0.5cm}CountIR.cpp \\
@@ -215,7 +215,7 @@
215215
RegisterCB};
216216
}
217217
\end{lstlisting}
218-
为每个回调函数实现一个单独的函数有助于理解发生了什么。如果插件提供了几个Pass,那么可以扩展RegisterCB回调函数来注册所有Pass。通常,可以找到一种紧凑的方法。下面的llvmGetPassPluginInfo()函数将前面的PipelineParsingCB()、RegisterCB()和llvmGetPassPluginInfo()组合成一个函数,并通过Lambda函数来实现:
218+
为每个回调函数实现一个单独的函数有助于理解发生了什么。如果插件提供了几个Pass,那么可以扩展RegisterCB回调函数来注册所有Pass。通常,可以找到一种紧凑的方法。下面的llvmGetPassPluginInfo()函数将前面的PipelineParsingCB()、RegisterCB()和llvmGetPass\allowbreak PluginInfo()组合成一个函数,并通过Lambda函数来实现:
219219
\begin{lstlisting}[caption={}]
220220
extern "C" ::llvm::PassPluginLibraryInfo LLVM_ATTRIBUTE_
221221
WEAK

content/2/chapter8/5.tex

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
为了实现功能,我们将tinylang编译器中的tools/driver/Driver.cpp文件进行了扩展:\par
1212

1313
\begin{enumerate}
14-
\item 我们使用新的类,因此从添加新的包含文件开始。llvm/Passes/PassBuilder.h文件提供了PassBuilder类的定义。llvm/Passes/PassPlugin.h文件是插件支持所必需的。最后,llvm/Analysis/TargetTransformInfo.h文件提供了一个连接IR级转换和特定目标信息的Pass:
14+
\item 我们使用新的类,因此从添加新的包含文件开始。llvm/Passes/PassBuilder.h文件提供了PassBuilder类的定义。llvm/Passes/PassPlugin.h文件是插件支持所必需的。最后,llvm/An\allowbreak alysis/TargetTransformInfo.h文件提供了一个连接IR级转换和特定目标信息的Pass:
1515
\begin{lstlisting}[caption={}]
1616
#include "llvm/Passes/PassBuilder.h"
1717
#include "llvm/Passes/PassPlugin.h"
@@ -251,7 +251,7 @@
251251

252252
还有其他扩展点。要使用扩展点,需要注册一个回调。在构造Pass流水期间,回调将在定义的扩展点运行,并可以向给定的Pass管理器添加一个Pass。\par
253253

254-
要为流水起始扩展点注册回调,可以调用PassBuilder类的registerPipelineStartEPCallback()方法。例如,将CountIRPass Pass添加到流水的开头,需要通过调用createModuleToFunctionPassAdaptor()模板函数来调整Pass作为模块Pass使用,然后将Pass添加到模块Pass管理器中:\par
254+
要为流水起始扩展点注册回调,可以调用PassBuilder类的registerPipelineStartEPCallback()方法。例如,将CountIRPass Pass添加到流水的开头,需要通过调用createModuleToFunctionPass\allowbreak Adaptor()模板函数来调整Pass作为模块Pass使用,然后将Pass添加到模块Pass管理器中:\par
255255

256256
\begin{lstlisting}[caption={}]
257257
PB.registerPipelineStartEPCallback(
@@ -262,9 +262,9 @@
262262
});
263263
\end{lstlisting}
264264

265-
可以在Pass流水创建之前的任何时刻,也就是调用parsepaspipeline()方法之前,在Pass流水设置代码中添加此代码。\par
265+
可以在Pass流水创建之前的任何时刻,也就是调用parsePassPipeline()方法之前,在Pass流水设置代码中添加此代码。\par
266266

267-
对于上一节中所做的工作,一个非常自然的扩展是让用户在命令行上传递一个扩展点的Pass流水描述(opt工具也允许这样做)。先为流水起始扩展点这样做。首先,将以下代码添加到tools/driver/Driver.cpp文件中:\par
267+
对于上一节中所做的工作,一个非常自然的扩展是让用户在命令行上传递一个扩展点的Pass流水描述(opt工具也允许这样做)。先为流水起始扩展点这样做。首先,将以下代码添加到tools/driver/\allowbreak Driver.cpp文件中:\par
268268

269269
\begin{enumerate}
270270
\item 为用户添加了一个新的命令行来指定管道描述。同样,从opt工具中获取选项名:
@@ -298,7 +298,7 @@
298298
LLVM 12支持-print-changed选项,与之前Pass的结果相比,该选项仅在IR代码发生更改时打印。大大减少的输出,使得跟踪IR转换更加容易。
299299
\end{tcolorbox}
300300

301-
PassBuilder类有一个嵌套的OptimizationLevel类来表示六个不同的优化级别。而不是使用"default<O?>"流水描述作为parsepaspipeline()方法的参数,我们也可以调用buildPerModuleDefaultPipeline()方法,为优化级别构建相应的优化管道——除了级别O0。优化级别为O0,表示不执行优化。因此,Pass管理器中不会添加任何Pass。如果我们仍然想运行某个Pass,可以手动将它添加到Pass管理器中。这个级别运行的是一个简单的Pass:AlwaysInliner Pass,它将一个标记有always\underline{~}内联属性的函数内联到调用者中。将优化级别的命令行选项值转换为OptimizationLevel类的相应成员,实现如下:
301+
PassBuilder类有一个嵌套的OptimizationLevel类来表示六个不同的优化级别。而不是使用"default<O?>"流水描述作为parsepaspipeline()方法的参数,我们也可以调用buildPer\allowbreak ModuleDefaultPipeline()方法,为优化级别构建相应的优化管道——除了级别O0。优化级别为O0,表示不执行优化。因此,Pass管理器中不会添加任何Pass。如果我们仍然想运行某个Pass,可以手动将它添加到Pass管理器中。这个级别运行的是一个简单的Pass:AlwaysInliner Pass,它将一个标记有always\underline{~}内联属性的函数内联到调用者中。将优化级别的命令行选项值转换为OptimizationLevel类的相应成员,实现如下:
302302
\begin{lstlisting}[caption={}]
303303
PassBuilder::OptimizationLevel Olevel = …;
304304
if (OLevel == PassBuilder::OptimizationLevel::O0)

0 commit comments

Comments
 (0)