Try   HackMD
tags: 共筆

[共筆] 不深不淺,帶你認識 LLVM

請留下你的問題,課中我將直接回答你,課後我也可以使用文字的方式給與回覆。如果你分享會結束後,你仍然有些問題想一起討論也可以寫email給我或直接寫在共筆,再一起尋找答案吧!

Douglas Chen dougpuob@gmail.com


簡報


提議與建議

  1. OOOOO
  2. OOOOO
  3. OOOOO

問題 Q&A (新問題置上)


問題 Q&A (2020/01/14 @可可頭)

● 我有剛問題,我的問題是

●在iPad上實現MacOS VM的可能性如何?

你的意思是在 iPad 上也來一個 Parallels(VM) 嗎?
如果是的話:
iPad 的 CPU 使用了 ARM based 的 CPU,Linux 上 QEMU 支援能執行在 ARM (qemu-system-arm) 的版本,所以應該是有機會。
但私心認為實用性不大,因為 iPad 畢境屬於 mobile device,長效省電是產品的主軸,所以這樣子的應用應該是不會出現。
dougpuob20200122 @CocoaHeads

● 我發現有錯誤,錯誤是

●演講時interpreter的發音應該在第二個音節。

看到你的留言我自己又讀了幾次,我也發現我放在第三個音節,感謝糾正。如果有其它發現,還請不用客氣。
dougpuob20200122 @CocoaHeads


問題 Q&A (2019/12/18 @系統貓)

● LLVM 跟 Clang 的關係是?

Clang 是 LLVM 的 frontend。
簡單的說如果我編譯 sample.c 程式,使用 gcc 我會使用 gcc sample.c;使用 LLVM 我會這樣子下指令 clang sample.c
dougpuob20191217 @系統貓

● JIT 重複使用所產生的機器碼是以怎樣的區塊為單位?function?block?statement?您提到可以從llvm程式碼裡找到答案,能否告知在哪個檔案或模組?

從LLVM的JIT的範例,使用者的應用時,其中每一個branch都需要拆分開(eg.if-else就有兩個branch)為llvm::BasicBlock class,這兩個branchs需要由llvm::BranchInst選擇需要的條件式。接著,會透過llvm::Function class組合為函式,最後用透ExecutionEngine執行該函式。

您可能想接著問,如果有重覆內容的llvm::Function instances,或是LLVM實際執行JIT的方式。我目前還沒研究到那裡。 >
dougpuob20191217

另外,我說明的方式可能會讓大家把 QEMU's TCG 與 LLVM JIT 當成是同一件事。
我試著把這個問題分成兩個問題,如果理解錯誤再讓我知道,其它延伸問題也歡迎:

  1. LLVM 的 JIT 如何以「區塊為單位」,它的相關程式碼?
  2. QEMU 的 TCG 如何以「區塊為單位」,它的相關程式碼?

dougpuob20191217
我想這個問題是想問以「什麼」區塊為單位,是function,BB,statement?而不是問如何「以區塊為單位」。
mshockwave20191220

Hi mshockwave
謝謝提醒,原本想直接將問題引到程式碼,能更清楚。
dougpuob20191222

● LLVM 的 JIT 如何以「區塊為單位」,它的相關程式碼?

LLVM專案中的範例程式llvm/examples/Fibonacci/fibonacci.cpp 中試使用MCJIT實作 fibonacci函式,如下:

int fib(int x) {
  if(x<=2) return 1;
    return fib(x-1)+fib(x-2);
}

將fibonacci函式寫成JIT的版本,有興趣可以直接在 GitHub 上閱讀程式碼fibonacci.cpp,看過後應該會比較有感覺。另一個方式是,期侍我下一次的 presentation。
dougpuob20191217

值得一提的是MCJIT,LLVM舊的JIT,一次就會把整個Module都編譯完成。所以假設你的Module有10個function,就算你只有用到其中的一個function,它還是會編譯其他9個、浪費不少資源。LLVM的現役JIT,OrcJIT,就可以解決這個問題。
mshockwave20191220

Hi mshockwave 感謝補充。
dougpuob20191222

● QEMU 的 TCG 如何以「區塊為單位」,它的相關程式碼?

這是我之前 survey 時留下的筆記,如果有理解錯誤的部份再麻煩跟我說一聲。

TCG會動態將guest assembly code生成為host CPU的assembly code。轉換過的assembly code稱為translated block(TB)存放在記憶體中,其中為這段程式碼產生一個hash,下次要使用時就不需要轉換,直接取出使用。

而TB是以 Function 或是 Branch Block 為單位,以我初淺的瞭解它不是Function也不是Branch Block,因為轉換與執行的都是QEMU本身,所以它TB為單位執行時直接執行static_code_gen_buffer裡的assembly code。其中轉換的函式是tb_gen_code tcb_gen_code、執行使用到的函式是tcg_qemu_tb_exec。希望這樣子的回內容能回覆到您的疑惑。

下面是幾個函式的位置,方便查找:

  1. ./accel/tcg/cpu-exec.c!cpu_exec()
  2. ./accel/tcg/cpu-exec.c!tb_find()
  3. ./accel/tcg/cpu-exec.c!tb_htable_lookup()
  4. ./accel/tcg/translate-all.c!tb_gen_code()
/**
* DisasJumpType:
* @DISAS_NEXT: Next instruction in program order.
* @DISAS_TOO_MANY: Too many instructions translated.
* @DISAS_NORETURN: Following code is dead.
* @DISAS_TARGET_*: Start of target-specific conditions.
*
* What instruction to disassemble next.
*/
typedef enum DisasJumpType {
  DISAS_NEXT,
  DISAS_TOO_MANY,
  DISAS_NORETURN,
} DisasJumpType;

cpu_exec()
{
    tb_find()
    {
        tb = tb_htable_lookup();     // <-- 詢找已轉換過的TB。
        if (likely(tb == NULL)) {
            tb = tb_gen_code();      // <-- 執行DBT。
        }    
         cpu_tb_exec(cpu, tb);       // <-- 執行該TB。
    }
}

tb_gen_code()
{
    tcg_func_start();
    gen_intermediate_code()  // <-- 不同的CPU會有各自的實作(接下來的函式也會有)。
    {
        translator_loop()
        {
            gen_tb_start();
            ops->tb_start();
            
            while(true)
            {
                // 這裡開始真正的轉換,其中
                // db->is_jmp 不是 DISAS_NEXT 時會停止TB,也是TB結束點。
                db->num_insns++;
                ops->insn_start();
                ops->translate_insn();
            }            
            ops->tb_stop();
            gen_tb_end();
        }
    }
}

dougpuob20191217

● 你剛剛提到目前 LLVM 還沒有辦法編譯 Linux kernel,那 LLVM 目前有這打算嗎?

這題感謝會後跟我分享的朋友,他提到目前 LLVM 9.0 已經可以編譯 Linux Kernel (x86)。應該是這則新聞,AMD/Intel Benchmarks: Building The Mainline Linux x86_64 Kernel With LLVM Clang
dougpuob20191220


https://www.phoronix.com/scan.php?page=news_item&px=Linux-5.7-Kbuild-Easier-LLVM

dougpuob20200413

● 有些程式語言在 LLVM IR 之上又有另一種 IR 的目的是?

這是現場Q&A的問題

巷子裡的專案 Poga Po 大大的回覆:

因為有些語言需要的 optimization 或是 type checking 不容易在 LLVM IR 上做,像是檢查 tensor shape 或是 rust 的 affine types。MLIR 讓人能針對特殊需求設計 IR Dialects,省掉各自維護 IR 的重複工作
dougpuob20191217


問題 Q&A (2019/10/17 @TFC,Monospace)

● Slide 41 這張投影片裡面出現的 "0x12345678" 是 object 裡各 symbol 的記憶體位址?

Uploading file_8pxdd1gfh

createPointerRepresentation()函式看的出來它將出錯的pointer指到的記憶體位置為輸入,再以hex string為輸出。而呼叫此函式時帶的pointer是 class,所以這個16進制的數值應該是一個 class object address。
createPointerRepresentation()

dougpuob20191027 @TFC

● 如果有些很舊的語言像傳統VB寫的程式,也可以透過LLVM轉成成WebAssembly嗎?

應該是不行,我想的到的幾個原因:

  1. 我目前還沒有聽說Clang(LLVM's frontend)有支援VB。
  2. 就算有Clang支援了VB,但VB在link-time/run-time時需要的libraries也是個問題。

dougpuob20191027 @TFC

● Clang 目前不能 build 整個Linux kernel ?

看起來目前應該還是努力進行中的事項。

  1. 這份slide提到使用Clang build Linux kernel 會遇到那些問題
    Switching a Linux distribution’s main toolchain to LLVM/Clang
    (https://llvm.org/devmtg/2019-04/slides/TechTalk-Rosenkranzer-Switching_a_Linux_distro.pdf)

  2. 這份slide是FOSDEM 2019其中一場在討論這個主題的presentation,看起來目前已經達成的有下面這張圖的幾項。
    Uploading file_lovobmqk9
    Compiling the Linux kernel with LLVM tools(Slides/Video)

dougpuob20191027 @TFC


錯誤修正

● 4x 頁的投影篇標題有拼錯字->optimization

感謝,已更正。
dougpuob20191027 @TFC


資源

  1. emscripten: C++ to WebAssembly

  2. MLIR 影/投影片

  3. Ignition: An Interpreter for V8

  4. Clang vs Other Open Source Compilers
    LLVM 官網上比較 Clang 與其它 compilers 的優缺點。

  5. Clang supports many language extensions

  6. 20190415-開源教-教我正確選擇軟體授權
    主講者,林誠夏 (Lucien Lin) 是我聽過把 Open Source License 講的最好的講者之一,非常值得一看的影片。

    GPL, AGPL, LGPL, MIT, BSD 各種複雜的軟體授權條款,是大部分人在利用開源的軟體套件的時候會遇到的棘手問題。到底用了哪些授權方式的軟體、套件,或是用了開源的資料庫,會如何影響到我本來想要選擇的授權方式呢?我又應該要選擇哪一種授權方式,才能符合我心中希望這軟體被流通應用的方式?

    「開源教教我正確選擇軟體授權」第一堂課程,特地請到長年研究開源科技法律授權的林誠夏法制顧問,深入淺出介紹各種開源授權方式,並透過實例的操作,分析已經用了很多套件的開源軟體,如何選擇合適的授權。絕對保證能夠幫各位從頭根治到腳,通體舒暢從此不再煩惱授權!千萬不要錯過這次的分享!

  7. Diablo 1 for web browsers
    WebAssembly 的例子