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

Commit

Permalink
check for pdf output.
Browse files Browse the repository at this point in the history
  • Loading branch information
xiaoweiChen committed Sep 21, 2021
1 parent beefe34 commit 5ff24b1
Show file tree
Hide file tree
Showing 18 changed files with 40 additions and 40 deletions.
2 changes: 1 addition & 1 deletion content/1/chapter2/4.tex
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@
endmacro()
\end{tcolorbox}

包含该模块,可以使用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
包含该模块,可以使用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

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

Expand Down
4 changes: 2 additions & 2 deletions content/2/chapter4/8.tex
Original file line number Diff line number Diff line change
Expand Up @@ -219,11 +219,11 @@
}
\end{lstlisting}

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

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

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

\begin{lstlisting}[caption={}]
void Sema::actOnVariableDeclaration(DeclList &Decls,
Expand Down
4 changes: 2 additions & 2 deletions content/2/chapter6/4.tex
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@
\begin{tcolorbox}[colback=white,colframe=black]
TYPE Shape = RECORD \\
\hspace*{3cm}color: INTEGER; \\
\hspace*{3cm}PROCEDURE (VAR s: Shape) GetColor(): \
\hspace*{3cm}PROCEDURE (VAR s: Shape) GetColor(): \\
\hspace*{3.5cm}INTEGER; \\
\hspace*{3cm}PROCEDURE (VAR s: Shape) Area(): REAL;\\
\hspace*{2.5cm}cmEND;
\hspace*{2.5cm}END;
\end{tcolorbox}

GetColor方法只返回颜色编号:\par
Expand Down
2 changes: 1 addition & 1 deletion content/2/chapter7/2.tex
Original file line number Diff line number Diff line change
Expand Up @@ -337,7 +337,7 @@
{Ptr});
\end{lstlisting}

\item 通过调用puts()函数来处理异常,将消息打印到控制台。为此,首先通过调用CreateGlobalStringPtr()函数生成一个指向该字符串的指针,然后在生成的调用puts()函数中将该指针作为参数传入:
\item 通过调用puts()函数来处理异常,将消息打印到控制台。为此,首先通过调用CreateGlobalString\allowbreak Ptr()函数生成一个指向该字符串的指针,然后在生成的调用puts()函数中将该指针作为参数传入:
\begin{lstlisting}[caption={}]
Builder.CreateCall(EndCatchFty, EndCatchFn);
Builder.CreateRet(Int32Zero);
Expand Down
2 changes: 1 addition & 1 deletion content/2/chapter7/3.tex
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,7 @@
\end{lstlisting}
\end{enumerate}

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

\begin{lstlisting}[caption={}]
Builder.CreateStore(Val, CGM.getGlobal(D));
Expand Down
10 changes: 5 additions & 5 deletions content/2/chapter7/4.tex
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@
\begin{itemize}
\item lvm::DIFile: 使用文件名和包含该文件的目录的绝对路径来描述一个文件,可以使用createFile()方法来创建。一个文件可以包含主编译单元,也可以包含导入的声明。

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

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

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

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

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

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

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

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

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

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

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

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

Expand Down
4 changes: 2 additions & 2 deletions content/2/chapter8/3.tex
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@
目前为止,已经实现了新Pass的功能。稍后将对out-of-tree Pass重用此实现。对于LLVM树中的解决方案,必须更改LLVM中的几个文件来声明新的Pass:\par

\begin{enumerate}
\item 首先,需要将CMakeLists.txt添加到源文件夹。这个文件包含一个新的LLVM库名称LLVMCountIR的构建说明。新库需要链接到LLVM Support组件,因为我们使用了调试和统计基础设施,还需要链接到LLVM Core组件,其中包含LLVM IR的定义:
\item 首先,需要将CMakeLists.txt添加到源文件夹。这个文件包含一个新的LLVM库名称LLVM\allowbreak CountIR的构建说明。新库需要链接到LLVM Support组件,因为我们使用了调试和统计基础设施,还需要链接到LLVM Core组件,其中包含LLVM IR的定义:
\begin{tcolorbox}[colback=white,colframe=black]
add\underline{~}llvm\underline{~}component\underline{~}library(LLVMCountIR \\
\hspace*{0.5cm}CountIR.cpp \\
Expand Down Expand Up @@ -215,7 +215,7 @@
RegisterCB};
}
\end{lstlisting}
为每个回调函数实现一个单独的函数有助于理解发生了什么。如果插件提供了几个Pass,那么可以扩展RegisterCB回调函数来注册所有Pass。通常,可以找到一种紧凑的方法。下面的llvmGetPassPluginInfo()函数将前面的PipelineParsingCB()、RegisterCB()和llvmGetPassPluginInfo()组合成一个函数,并通过Lambda函数来实现:
为每个回调函数实现一个单独的函数有助于理解发生了什么。如果插件提供了几个Pass,那么可以扩展RegisterCB回调函数来注册所有Pass。通常,可以找到一种紧凑的方法。下面的llvmGetPassPluginInfo()函数将前面的PipelineParsingCB()、RegisterCB()和llvmGetPass\allowbreak PluginInfo()组合成一个函数,并通过Lambda函数来实现:
\begin{lstlisting}[caption={}]
extern "C" ::llvm::PassPluginLibraryInfo LLVM_ATTRIBUTE_
WEAK
Expand Down
10 changes: 5 additions & 5 deletions content/2/chapter8/5.tex
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
为了实现功能,我们将tinylang编译器中的tools/driver/Driver.cpp文件进行了扩展:\par

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

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

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

\begin{lstlisting}[caption={}]
PB.registerPipelineStartEPCallback(
Expand All @@ -262,9 +262,9 @@
});
\end{lstlisting}

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

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

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

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

0 comments on commit 5ff24b1

Please sign in to comment.