Mercurial > hg > Papers > 2016 > kaito-master
comparison paper/chapter3.tex @ 17:3afb4bfe1100
fix
author | Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp> |
---|---|
date | Mon, 15 Feb 2016 07:30:44 +0900 |
parents | 7161b80a7e19 |
children |
comparison
equal
deleted
inserted
replaced
16:bea98599d11f | 17:3afb4bfe1100 |
---|---|
1 \chapter{LLVM clang 上での CbC の実装} | 1 \chapter{LLVM clang 上での CbC の実装} |
2 第 \ref{chapter:CbC}, \ref{chapter:LLVM/clang} 章をもとに LLVM, clang への CbC コンパイル機能の実装を行う. コードセグメントの解釈, 軽量継続などいくつかの機能は過去の研究によって実装されたが, 本研究での実装に繋がるので説明する. | 2 第 \ref{chapter:CbC}, \ref{chapter:LLVM/clang} 章をもとに LLVM, clang への CbC コンパイル機能の実装を行う. コードセグメントの解釈, 軽量継続などいくつかの機能は過去の研究によって実装されたが, 本研究での実装に繋がるのでここでも説明する. |
3 | 3 |
4 以降に示される LLVM, clang のファイルパスについて, \$(CLANG) を clang のソースコードを展開したディレクトリのパス, \$(LLVM) を LLVM のソースコードを展開したディレクトリのパスとする. | 4 以降に示される LLVM, clang のファイルパスについて, \$(CLANG) を clang のソースコードを展開したディレクトリのパス, \$(LLVM) を LLVM のソースコードを展開したディレクトリのパスとする. |
5 \section{code segment} | 5 \section{code segment} |
6 \label{sec:codeSegment} | 6 \label{sec:codeSegment} |
7 code segment は \_\_code 型の関数のように扱えるよう実装する. また, code segment は 戻り値を返さないので void 型を参考に変更を加えていく. 最初に関数が code segment であることを示す \_\_code 型の追加を行う. これは clang, llvm 別々で行う必要がある. clang 側の作業は \_\_code を予約語として定義する改変から始める. clang では, 予約語は全て \$(CLANG)/include/ clang/Basic/TokenKinds.def に定義されており, ここで定義した予約語の頭に kw\_ を付けたものがその予約語の ID となる. ここに, 次のように変更を加えて \_\_code を追加した. ここで使われている KEYWORD マクロは予約語の定義に用いられるもので, 第一引数が登録したい予約語, 第二引数がその予約語が利用される範囲を表す. KEYALL は全ての C, C++ でサポートされることを示し, この他には C++ の予約語であることを示す KEYCXX や C++11 以降で利用されることを示す KEYCXX11 等がある. code segment は C のバージョンに関わらずサポートされるべきであるので KEYALL を選択した. ここで環境付き継続に用いる予約語である \_\_return, \_\_environment の定義も同時に行う. | 7 code segment は \_\_code 型の関数のように扱えるよう実装する. また, code segment は 戻り値を返さないので void 型を参考に変更を加えていく. 最初に関数が code segment であることを示す \_\_code 型の追加を行う. これは clang, llvm 別々で行う必要がある. clang 側の作業は \_\_code を予約語として定義する改変から始める. clang では, 予約語は全て \$(CLANG)/include/ clang/Basic/TokenKinds.def に定義されており, ここで定義した予約語の頭に kw\_ を付けたものがその予約語の ID となる. ここに, 次のように変更を加えて \_\_code を追加した. ここで使われている KEYWORD マクロは予約語の定義に用いられるもので, 第一引数が登録したい予約語, 第二引数がその予約語が利用される範囲を表す. KEYALL は全ての C, C++ でサポートされることを示し, この他には C++ の予約語であることを示す KEYCXX や C++11 以降で利用されることを示す KEYCXX11 等がある. code segment は C のバージョンに関わらずサポートされるべきであるので KEYALL を選択した. ここで環境付き継続に用いる予約語である \_\_return, \_\_environment の定義も同時に行う. |
329 return false; | 329 return false; |
330 } | 330 } |
331 \end{lstlisting} | 331 \end{lstlisting} |
332 | 332 |
333 \section{フレームポインタ操作最適化} | 333 \section{フレームポインタ操作最適化} |
334 フレームポインタ操作の最適化は omit leaf frame pointer を強制することで行う. この最適化は \ref{sec:olfp} 節でしたとおり leaf function に対して行われるが, 継続を続ける code segment は何もせずとも leaf function の条件を満たしているので内部で有効化するだけで良い. | 334 フレームポインタ操作の最適化は omit leaf frame pointer を強制することで行う. この最適化は関数呼び出しの際に行われるフレームポインタ操作に関わる最適化である. 通常関数呼び出しを行う際にはフレームポインタの値をスタックに積み, return 直前に戻すという作業を行う. omit leaf frame pointer はこの操作を leaf function を呼び出す際に行わないようにする最適化である. |
335 | 335 leaf function とはコールツリーの終端の位置する関数のことを指し, この関数が関数を呼び出さないことを意味する. 軽量継続を続ける code segment は何もせずとも leaf function の条件を満たしているので内部で有効化するだけで良い. |
336 | |
337 以下のリスト \ref{loptno}, \ref{lopt} はどちらもリスト \ref{leaf} をコンパイルして得られるアセンブリコードから関数 caller の部分を抜き出したものであり, 前者が omit leaf frame pointer 無し, 後者が omit leaf frame pointer ありのコードである. push, pop 命令によるフレームポインタの操作がリスト \ref{lopt} ではなくなっていることがわかる. | |
338 | |
339 \begin{lstlisting}[frame=lrbt, label=leaf, caption={関数 caller}] | |
340 void caller(int a, int b, int c){ | |
341 B(a, b, c, 40); | |
342 return; | |
343 } | |
344 \end{lstlisting} | |
345 \begin{lstlisting}[frame=lrbt, label=loptno, caption={関数 caller (omit leaf frame pointer 無し)}] | |
346 _caller: ## @caller | |
347 .cfi_startproc | |
348 ## BB#0: | |
349 pushq %rbp | |
350 Ltmp0: | |
351 .cfi_def_cfa_offset 16 | |
352 Ltmp1: | |
353 .cfi_offset %rbp, -16 | |
354 movq %rsp, %rbp | |
355 Ltmp2: | |
356 .cfi_def_cfa_register %rbp | |
357 movl %edi, -4(%rbp) | |
358 movl %esi, -8(%rbp) | |
359 movl -4(%rbp), %esi | |
360 addl -8(%rbp), %esi | |
361 movl %esi, %eax | |
362 popq %rbp | |
363 retq | |
364 .cfi_endproc | |
365 \end{lstlisting} | |
366 \begin{lstlisting}[frame=lrbt, label=lopt, caption={関数 caller (omit leaf frame pointer 有り)}] | |
367 _caller: ## @caller | |
368 .cfi_startproc | |
369 ## BB#0: | |
370 movl %edi, -4(%rbp) | |
371 movl %esi, -8(%rbp) | |
372 movl -4(%rbp), %esi | |
373 addl -8(%rbp), %esi | |
374 movl %esi, %eax | |
375 retq | |
376 .cfi_endproc | |
377 \end{lstlisting} | |
378 | |
336 omit leaf frame pointer は clang 内部では CodeGenOpts.OmitLeafFramePointer として表現されている. clang は CodeGen で LLVM IR の function を生成する際にこのフラグが立っているかどうかを確認し, 立っている場合には関数の no-frame-pointer-elim という attribute を false にする. それにより最適化が当該関数に作用するようになる. この, LLVM IR function への attribute 設定を行っているのは \$(CLANG)/lib/CodeGen/CGCall.cpp である. ここをリスト \ref{olfp} のように変更した. 通常は OmitLeafFramePointer のみを確認する部分を HasCodeSegment によって code segment の有無も確認するように変更している. これにより, code segment を含むコードのコンパイル, 即ち CbC のコードのコンパイルの際には自動的に omit leaf frame pointer が有効化されるようになった. | 379 omit leaf frame pointer は clang 内部では CodeGenOpts.OmitLeafFramePointer として表現されている. clang は CodeGen で LLVM IR の function を生成する際にこのフラグが立っているかどうかを確認し, 立っている場合には関数の no-frame-pointer-elim という attribute を false にする. それにより最適化が当該関数に作用するようになる. この, LLVM IR function への attribute 設定を行っているのは \$(CLANG)/lib/CodeGen/CGCall.cpp である. ここをリスト \ref{olfp} のように変更した. 通常は OmitLeafFramePointer のみを確認する部分を HasCodeSegment によって code segment の有無も確認するように変更している. これにより, code segment を含むコードのコンパイル, 即ち CbC のコードのコンパイルの際には自動的に omit leaf frame pointer が有効化されるようになった. |
337 | 380 |
338 \begin{lstlisting}[frame=lrbt,label=olfp,caption={omit leaf frame pointer 有効化}] | 381 \begin{lstlisting}[frame=lrbt,label=olfp,caption={omit leaf frame pointer 有効化}] |
339 } else if (CodeGenOpts.OmitLeafFramePointer || LangOpts.HasCodeSegment) { | 382 } else if (CodeGenOpts.OmitLeafFramePointer || LangOpts.HasCodeSegment) { |
340 FuncAttrs.addAttribute("no-frame-pointer-elim", "false"); | 383 FuncAttrs.addAttribute("no-frame-pointer-elim", "false"); |