* [[https://www.amazon.com/Language-Implementation-Patterns-Domain-Specific-Programming/dp/193435645X|Language Implementation Patterns]]
* 簡介前端主要幾個元件。
* 簡介函式庫。
clang 的簡介請見
* [[http://llvm.org/devmtg/2007-05/09-Naroff-CFE.pdf|New LLVM C Front-end]]
* [[http://llvm.org/devmtg/2008-08/Naroff_Clang.pdf|Clang Intro]]
* [[http://llvm.org/devmtg/2009-10/StateOfClang.pdf|State of Clang]]
* [[http://llvm.org/devmtg/2011-11/Gregor_ExtendingClang.pdf|Extending Clang]]
線上文章:
* [[http://eli.thegreenplace.net/2011/07/03/parsing-c-in-python-with-clang/|Parsing C++ in Python with Clang]]
* [[http://eli.thegreenplace.net/2014/05/01/modern-source-to-source-transformation-with-clang-and-libtooling|Modern source-to-source transformation with Clang and libTooling]]
* [[https://kevinaboos.wordpress.com/2013/07/23/clang-tutorial-part-i-introduction/|CLANG TUTORIAL PART I: INTRODUCTION]]
* [[https://kevinaboos.wordpress.com/2013/07/23/clang-tutorial-part-ii-libtooling-example/|CLANG TUTORIAL PART II: LIBTOOLING EXAMPLE]]
* [[https://kevinaboos.wordpress.com/2013/07/29/clang-tutorial-part-iii-plugin-example/|CLANG TUTORIAL PART III: PLUGIN EXAMPLE]]
* [[http://bastian.rieck.ru/blog/posts/2015/baby_steps_libclang_ast/|Baby steps with `libclang`: Walking an abstract syntax tree]]
* [[http://bastian.rieck.ru/blog/posts/2016/baby_steps_libclang_function_extents/|Baby steps with `libclang`: Counting function extents]]
====== 使用範例 ======
# 這裡的 clang 是 compiler driver,負責解析命令行,調用相關工具,並傳遞對應的命令行參數。
# -Xclang 代表其後參數是給 clang -cc1 調用的編譯器。
$ clang -Xclang -ast-dump sum.c
# 這裡的 clang -cc1 調用的是實際上的編譯器。
$ clang -cc1 -ast-dump sum.c
# -### 列出完整的命令行參數。
$ clang -### sum.c
# -xir 指示輸入的是 LLVM IR。
$ clang -xir -c sum.ll
* ''clang'' 本身是 compiler driver。
$ lldb clang
(lldb) b Driver.cpp:97
(lldb) r --help
* 入口點 ''llvm/tools/clang/tools/driver/driver.cpp:main''。
* 下斷點在實際的前端和後端,跳過 compiler driver。
# 可以看到實際上下給前端的命令行選項。
$ clang -c -v sum.c
$ lldb clang
(lldb) b X86TargetLowering::LowerOperation
(lldb) r -cc1 -triple x86_64-apple-macosx10.11.0 -Wdeprecated-objc-isa-usage -Werror=deprecated-objc-isa-usage -emit-obj -mrelax-all -disable-free -main-file-name sum.c -mrelocation-model pic -pic-level 2 -mthread-model posix -mdisable-fp-elim -masm-verbose -munwind-tables -target-cpu core2 -target-linker-version 274.2 -v -dwarf-column-info -debugger-tuning=lldb -coverage-notes-file /Users/chenwj/Projects/temp/sum.gcno -resource-dir /Users/chenwj/Projects/install/lib/clang/5.0.0 -fdebug-compilation-dir /Users/chenwj/Projects/temp -ferror-limit 19 -fmessage-length 179 -stack-protector 1 -fblocks -fobjc-runtime=macosx-10.11.0 -fencode-extended-block-signature -fmax-type-align=16 -fdiagnostics-show-option -fcolor-diagnostics -o sum.o -x c sum.c
* 如果使用 GDB,可以下 ''set follow-fork-mode child'' ([[http://stackoverflow.com/questions/28105766/how-to-debug-llvm-source|How to debug llvm source?]])。
* 如果只是要查看後端,可以於 ''llc'' 下斷點。
====== 內部實現 ======
透過 gdb 下斷點,觀察 backtrace。
* [[http://clang.llvm.org/docs/InternalsManual.html|"Clang" CFE Internals Manual]]
底下是 Clang 前端主要流程:
Driver -> Lex -> Parse -> Sema -> CodeGen (LLVM IR)
分別在 include/clang 和 lib 底下有對應。Driver 負責調用編譯流程中所需的工具鏈,並傳遞相應參數。真正意義上的前端是自 Lex 以後至 CodeGen 的部分。
* [[https://clang.llvm.org/doxygen/Driver_8h_source.html|Driver]]
# 可以觀察 driver 如何調用所有工具鏈。
$ clang -v sum.c
* [[http://clang.llvm.org/docs/DriverInternals.html|Driver Design & Internals]]
* [[https://clang.llvm.org/doxygen/Lexer_8h_source.html|Lexer]]
$ clang -cc1 -dump-tokens sum.c
* [[http://clang.llvm.org/docs/InternalsManual.html#the-lexer-and-preprocessor-library|The Lexer and Preprocessor Library]]
* [[https://clang.llvm.org/doxygen/Parse_2Parser_8h_source.html|Parser]]
$ clang -cc1 -fsyntax-only -ast-dump sum.c
* [[http://clang.llvm.org/docs/InternalsManual.html#the-parser-library|The Parser Library]]
* [[http://clang.llvm.org/docs/IntroductionToTheClangAST.html|Introduction to the Clang AST]]
* [[https://clang.llvm.org/doxygen/classclang_1_1TranslationUnitDecl.html|TranslationUnitDecl]] 是 AST 根節點,對應當前正在編譯的檔案。
* [[https://clang.llvm.org/doxygen/Sema_8h_source.html|Sema]]
* 提供回調函式 ''ActOn'' 供 Parse 調用,建立 AST 和進行語義檢查。
* ''lib/CodeGen'' 迭代 AST 生成 LLVM IR。例如: [[https://clang.llvm.org/doxygen/CodeGenFunction_8h_source.html|CodeGenFunction]]。
* 編譯錯誤或是警告,全部寫成 *.td 檔,位於 ''include/clang/Basic/''。
* [[http://clang.llvm.org/docs/InternalsManual.html#the-diagnostics-subsystem|The Diagnostics Subsystem]]
* ''DiagnosticParseKinds.td'' 包含所有 ''lib/Parse/*'' 會報出的警告或錯誤。其它檔案依此類推。想要添加新的警告或是錯誤,可以在 *.td 檔中尋找類似的項目,反推應該在哪裡做相關的檢查。
* Parse 所得資訊皆存成 AST 節點。
* [[http://clang.llvm.org/docs/InternalsManual.html#the-ast-library|The AST Library]]
* [[http://clang.llvm.org/docs/InternalsManual.html#canonical-types|Canonical Types]]
* [[http://stackoverflow.com/questions/25231080/what-are-canonical-types-in-clang|What are canonical types in Clang?]]
* 概念應該近似 GCC 的 [[https://gcc.gnu.org/onlinedocs/gccint/Types.html|TYPE_CANONICAL]]。
* [[http://clang.llvm.org/docs/InternalsManual.html#canonical-types|The QualType class]]
* 包含 type 本身,和與其相關連的 qualifier。
====== IRBuilder ======
熟悉生成 LLVM IR 生成的方式,和使用到相關的類。
* [[https://clang.llvm.org/doxygen/classclang_1_1CodeGen_1_1CGBuilderTy.html|CGBuilderTy]]
* 基本上是 [[http://llvm.org/doxygen/classllvm_1_1IRBuilder.html|IRBuilder]] 的包裝。
* [[https://clang.llvm.org/doxygen/Address_8h.html|Address.h]]
* [[https://clang.llvm.org/doxygen/CGValue_8h.html|CGValue.h]]
* 基本上是 [[http://llvm.org/doxygen/classllvm_1_1Value.html|Value]] 的包裝。
* [[https://clang.llvm.org/doxygen/classclang_1_1CodeGen_1_1LValue.html|LValue]]
* [[https://clang.llvm.org/doxygen/classclang_1_1CodeGen_1_1RValue.html|RValue]]
* [[https://clang.llvm.org/doxygen/CodeGenFunction_8h.html|CodeGenFunction.h]]
* [[https://clang.llvm.org/doxygen/classclang_1_1CodeGen_1_1CodeGenFunction.html#ada2bbe60d33f290a0ef688d71c491ca8|EmitScalarExpr]]
* [[https://clang.llvm.org/doxygen/classclang_1_1CodeGen_1_1CodeGenFunction.html#aa0edab9cd404123428caf6cf599aa09e|EmitLValue]]
* [[https://clang.llvm.org/doxygen/CodeGenFunction_8cpp_source.html|CodeGenFunction.cpp]]
* 觀察 LLVM IR 生成的方式。
llvm::Value *Zero = llvm::Constant::getNullValue(Size->getType());
* [[https://clang.llvm.org/doxygen/CGBuiltin_8cpp.html|CGBuiltin.cpp]]
====== 函式庫 ======
* [[http://clang.llvm.org/docs/Tooling.html|Choosing the Right Interface for Your Application]]
* [[http://llvm.org/devmtg/2010-11/Gregor-libclang.pdf|libclang: Thinking Beyond the Compiler]]
$ cat example.c
#include "clang-c/Index.h"
#include
int main(int argc, char *argv[]) {
CXIndex Index = clang_createIndex(0, 0);
CXTranslationUnit TU = clang_parseTranslationUnit(Index, 0,
argv, argc, 0, 0, CXTranslationUnit_None);
for (unsigned I = 0, N = clang_getNumDiagnostics(TU); I != N; ++I) {
CXDiagnostic Diag = clang_getDiagnostic(TU, I);
CXString String = clang_formatDiagnostic(Diag,
clang_defaultDiagnosticDisplayOptions());
fprintf(stderr, "%s\n", clang_getCString(String));
clang_disposeString(String);
}
clang_disposeTranslationUnit(TU);
clang_disposeIndex(Index);
}
$ clang example.c -I/PATH/TO/INCLUDE -L/PATH/TO/LIB -lclang -o example
$ export LD_LIBRARY_PATH=/PATH/TO/LIB
$ cat bug.c
void foo() {
int i = 1
}
$ ./example bug.c
bug.c:2:12: error: expected ';' at end of declaration
* [[http://clang.llvm.org/doxygen/group__CINDEX.html|libclang: C Interface to Clang]]
====== Sanitizer ======
* [[https://compiler-rt.llvm.org/|"compiler-rt" runtime libraries]]
* [[https://github.com/google/sanitizers]] 是原來的代碼庫,現在已合入 compiler-rt。
* compiler-rt 基本上是 LLVM 版的 [[https://gcc.gnu.org/onlinedocs/gccint/Libgcc.html|libgcc]]。
* [[http://llvm.org/docs/GettingStarted.html|Getting Started with the LLVM System]] 已說明 sanitizer 需要編譯 compiler-rt。
$ cd llvm/projects
$ git clone http://llvm.org/git/compiler-rt.git
* [[http://clang.llvm.org/docs/AddressSanitizer.html|AddressSanitizer]] 可用。
====== 靜態檢查 ======
* [[https://clang-analyzer.llvm.org/|Clang Static Analyzer]]
* [[http://lcs.ios.ac.cn/~xuzb/canalyze/memmodel.pdf|A Memory Model for Static Analysis of C Programs]]
* 透過 [[wp>Symbolic execution]] 進行檢查。
# 列出可用的 CHECKER 列表。
$ clang -cc1 -analyzer-checker-help
$ cat bug.c
#include
int main() {
int i;
printf("%d", i);
}
$ clang -cc1 -analyze -analyzer-checker=core bug.c
bug.c:5:3: warning: Function call argument is an uninitialized value
printf("%d", i);
^~~~~~~~~~~~~~~
1 warning generated.
* 編譯整個 project 建議使用 ''scan-build''。
====== 其它 ======
* 添加 builtin 函式。
* include/clang/Basic/BuiltinsNVPTX.def
* lib/CodeGen/CGBuiltin.cpp
====== 外部連結 ======
* [[http://clang.llvm.org/|clang: a C language family frontend for LLVM]]
* [[http://channel9.msdn.com/Events/GoingNative/GoingNative-2012/Clang-Defending-C-from-Murphy-s-Million-Monkeys|Clang: Defending C++ from Murphy's Million Monkeys]]
* [[http://kitoslab.blogspot.tw/2012/01/clang-llvm-as-cross-compiler.html|Clang + LLVM as cross compiler]]
* [[http://amnoid.de/tmp/clangtut/tut.html|How to parse C programs with clang: A tutorial in 9 parts]]