LLVM, Clang 上の Continuation based C コンパイラの改良 |
Kaito TOKUMORI
|
関数やクラス、オブジェクト等は分割、結合を行うことは困難である。
アセンブリは分割、結合が可能だが易しくない。
当研究室ではプログラムを code segment、data segmentという単位を用いて書くという手法を提案しており、Cerium, Continuation based C(CbC)等がそれらを利用する。
それぞれの単位は分割と結合を行うことが可能で、プログラムの分割、結合を容易にする。
それぞれの単位はメタレベルのものが存在し, メタ計算の記述も可能である。
__code f() { goto g(); } __code g() { goto h(); } |
|
clang はソースコードを読み込むと Parser を用いて clangAST を生成する。CodeGenがASTを元にLLVM IRを生成し, それが LLVM の入力に対応する。
LLVM は中間表現の形を何度も変化させる。最適化をかけながら徐々にターゲットへの依存度が高くし、最終的にアセンブリコードや実行可能ファイルを出力する。最適化を含む全ての処理がパスによって行われる。
define fastcc void @factorial(i32 %x) #0 { entry: tail call fastcc void @factorial0(i32 1, i32 %x) ret void } |
元のコード | 生成される AST に対応するコード |
__code code1() { : goto code2(); } | void code1() { : code2(); return; } |
元のコード | 生成される AST に対応するコード |
__code code1(int a, int b) { : goto code2(a,b); } __code code2(int a, int b){ : } | __code code2(int a, int b); __code code1(int a, int b) { : goto code2(a,b); } __code code2(int a, int b){ : } |
元のコード | LLVM IR |
__code code1() { : goto code2(); } __code code2(){ : } | define fastcc void @code1() #0 { entry: : tail call fastcc void @code2() ret void } define fastcc void @code2() #0 { : } |
|
|
|
|
|
|
従来のコード | 記述を簡易化したコード |
__code meta(struct Context* context, enum Code next) { goto (context->code[next])(context); } __code code1_stub(struct Context* context) { goto code1(context, &context->data[Allocate]->allocate); } __code code1(struct Context* context, struct Allocate* allocate) { allocate->size = sizeof(long); allocator(context); goto meta(context, Code2); } __code code2(struct Context* context, long* count) { *count = 0; goto meta(context, Code3); } __code code2_stub(struct Context* context) { goto code2(context, &context->data[Count]->count); } | __code meta(struct Context* context, enum Code next) { goto (context->code[next])(context); } __code code1(struct Allocate* allocate) { allocate->size = sizeof(long); allocator(); goto code2(); } __code code2(long* count) { *count = 0; goto code3(); } |
CbCのコード | 出力されたアセンブリ |
__code f(int i,stack sp) { int k,j; k = 3+i; goto f_g0(i,k,sp); } | _f: ## @f .cfi_startproc ## BB#0: ## %entry subq $24, %rsp Ltmp9: .cfi_def_cfa_offset 32 movl %edi, %eax addl $3, %eax movq %rsi, 16(%rsp) ## 8-byte Spill movl %eax, %esi movq 16(%rsp), %rdx ## 8-byte Reload addq $24, %rsp jmp _f_g0 ## TAILCALL .cfi_endproc |