clang 的簡介請見

線上文章:

使用範例

# 這裡的 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 (How to debug llvm source?)。
    • 如果只是要查看後端,可以於 llc 下斷點。

內部實現

透過 gdb 下斷點,觀察 backtrace。

底下是 Clang 前端主要流程:

 Driver -> Lex -> Parse -> Sema -> CodeGen (LLVM IR)

分別在 include/clang 和 lib 底下有對應。Driver 負責調用編譯流程中所需的工具鏈,並傳遞相應參數。真正意義上的前端是自 Lex 以後至 CodeGen 的部分。

  • 編譯錯誤或是警告,全部寫成 *.td 檔,位於 include/clang/Basic/
    • DiagnosticParseKinds.td 包含所有 lib/Parse/* 會報出的警告或錯誤。其它檔案依此類推。想要添加新的警告或是錯誤,可以在 *.td 檔中尋找類似的項目,反推應該在哪裡做相關的檢查。

IRBuilder

熟悉生成 LLVM IR 生成的方式,和使用到相關的類。

函式庫

    • libclang: Thinking Beyond the Compiler
      $ cat example.c
      #include "clang-c/Index.h"
      #include <stdio.h>
       
      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

Sanitizer

靜態檢查

# 列出可用的 CHECKER 列表。
$ clang -cc1 -analyzer-checker-help
$ cat bug.c
#include <stdio.h>
 
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

外部連結

登录