annotate implementation.tex @ 3:d2999e94b97d

add gcc.
author kent <kent@cr.ie.u-ryukyu.ac.jp>
date Sat, 06 Feb 2010 04:47:35 +0900
parents 50e23a4b2f40
children 30c102343b37
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
2
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2 \chapter{GCCにおける実装・改善}
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
3 \label{chp:impl}
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
4
3
d2999e94b97d add gcc.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents: 2
diff changeset
5 この章では、GCCにおけるCbCコンパイラの実装方法と、 \ref{chp:cbc}章で洗
d2999e94b97d add gcc.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents: 2
diff changeset
6 い出したGCCでの問題点の改善を行う。
2
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
7
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
8 実装にはGCCのフロントエンドであるcc1というプログラムを直接変更する。
3
d2999e94b97d add gcc.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents: 2
diff changeset
9 このcc1はCからアセンブラへ変換を行う純粋なコンパイラとして実行されるプ
d2999e94b97d add gcc.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents: 2
diff changeset
10 ログラムである。このcc1をCbCの構文解析に対応させる。
d2999e94b97d add gcc.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents: 2
diff changeset
11
2
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
12 過去の研究においてはGCCのバージョン4.2.3が用いられた。現在はGCCのリリ
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
13 ースに並ぶ形で4.4.2(2010年1月時)を用いている。
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
14
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
15 \section{過去の研究における実装部分}
3
d2999e94b97d add gcc.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents: 2
diff changeset
16 今回の改善においての予備知識として、過去の研究での実装部分であるコード
2
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
17 セグメントと軽量継続がどのように実装されたかを簡単に説明する。
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
18
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
19 \subsection{コードセグメントの実装}
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
20
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
21 コードセグメント内部の実装は実際は単なる関数で良い。
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
22 変更の必要があったのは関数の返り値に当たる部分である。コードセグメント
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
23 では返り値が存在しないのでここは``code''キーワードを入力できるようにす
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
24 る。このcodeは内部でvoid型に変換する。
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
25
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
26 GCC(及び一般的なコンパイラ)ではコンパイルに必要な全ての要素、変数や式
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
27 、関数、構文などをすべて treeと呼ばれる構文木に保持している。コードセ
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
28 グメントの構文木も関数とほ
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
29 ぼ同じものを作成すれば良い。コード\ref{code:build-code-segment}はその
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
30 構文木を作成している部分である。
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
31
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
32 \lstinputlisting
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
33 [caption=構文木生成(gcc/c-typeck.c),label=code:build-code-segment]
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
34 {sources/build-code-segment.cbc}
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
35
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
36 \verb|build_code_segment_type|関数においてコードセグメントの構文木を作
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
37 成している。内部の処理は\verb|build_function_type|とほぼ同じだが、関数
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
38 のテーブルに登録せず、軽量継続の際にそれがコードセグメントであることを
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
39 示すためのフラグをセットしている。
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
40
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
41
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
42
3
d2999e94b97d add gcc.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents: 2
diff changeset
43 \subsection{軽量継続の実装} \label{sec:impl-goto}
2
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
44 % return somesegment();
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
45 % expand_call()
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
46
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
47 軽量継続はGCCの末尾呼び出し最適化の機構を用いて実装する。
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
48
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
49 \subsubsection{末尾呼び出し最適化}
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
50 プログラム中、関数を呼び出すときには通常はスタックを積み上げ、現在の環
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
51 境を保持した上で呼び出し先の処理を行う。これは元の関数に復帰して残りの
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
52 処理を続行する必要があるためである。しかし関数の最後、リターン直前に呼
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
53 び出しを行う場合は環境を保持する必要がない(図\ref{fig:tailcall}参照)
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
54 。そのためスタックの状態を変更することなく呼び出すことができる。この最
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
55 適化は末尾呼び出し最適化(tailcall)と呼ばれている。
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
56 \begin{figure}[htpb]
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
57 \begin{center}
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
58 \includegraphics[width=.6\textwidth]{figures/tailcall.eps}
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
59 \end{center}
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
60 \caption{末尾呼び出し最適化が可能な関数funcBの例}
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
61 \label{fig:tailcall}
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
62 \end{figure}
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
63
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
64 Scheme処理系では仕様上この最適化が必須となっているが、Cはそうではない。
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
65 しかしGCCはこの最適化をデフォルトで行っている。
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
66
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
67 \subsubsection{軽量継続への摘要}
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
68 tailcallをコードセグメントの呼び出しに適用することで軽量継続が実装でき
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
69 る。具体的にはソースコード上にコード\ref{code:goto}のような式があった
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
70 場合に、これをコード\ref{code:ret-call}と同じように解釈すれば良い。
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
71 この構文解析はGCCのgcc/c-parser.c内で行う。
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
72
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
73 \begin{minipage}[t]{.45\textwidth}
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
74 \lstinputlisting[caption=goto文の例,label=code:goto]
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
75 {sources/goto-expression.cbc}
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
76 \end{minipage}
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
77 \hfill
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
78 \begin{minipage}[t]{.45\textwidth}
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
79 \lstinputlisting[caption=構文木での解釈,label=code:ret-call]
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
80 {sources/ret-call.cbc}
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
81 \end{minipage}
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
82
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
83 しかし構文木の変更だけでは最適化が行われるとは限らない。特にスタックの
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
84 状態や変数の数、順番によっても最適化はカットされる場合がある。
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
85 そのため最適化を判断する条件式を修正、また構文木から中間コードを生
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
86 成する部分でも修正が必要になる。
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
87
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
88 \paragraph{expand-call}関数は関数を表す構文木から中間コードを生成する
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
89 処理である。この関数内では呼び出される関数のアドレスを取得するコードの
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
90 生成、スタックへの引数をプッシュするコードの生成、引数のプッシュの度に
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
91 tailcallが可能かのチェックなどが行われている。
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
92
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
93 ここでは以下の処理を追加することでtailcallカットの条件判断をパスしている。
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
94 \begin{itemize}
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
95 \item スタックのサイズをごまかす
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
96
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
97 tailcallは呼び出し元の全引数サイズが呼び出し先のそれより小さい場合
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
98 には実行できない。そのため呼び出し元、この場合コードセグメント全て
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
99 の引数にもちいるスタックサイズを大きな値でごまかす。
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
100 \item 並列代入
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
101
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
102 \ref{sec:cbc-problem}で説明したような並列代入の必要な関数呼び出し
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
103 を行った場合はtailcallは実行されない。そのためここで並列代入が必要
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
104 になる。
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
105 \end{itemize}
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
106
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
107 上記処理の追加により軽量継続が実装された。
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
108 継続の際にコードセグメントに渡す引数は関数と同じようにスタック上に格納
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
109 されるが、このスタックは拡張することはなく、図
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
110 \ref{fig:gotostack}のように連続した継続の中でスタックポインタは常
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
111 に同じアドレスを指し示す。(比較のため、図\ref{fig:funcstack}には関数
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
112 呼び出しの際のスタックの状態を例示した)
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
113 \begin{figure}[htpb]
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
114 \begin{center}
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
115 \subfloat[][関数呼び出し]{\label{fig:funcstack}
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
116 \includegraphics[width=.6\textwidth]{figures/functionstack.eps}}
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
117 \subfloat[][軽量継続]{\label{fig:gotostack}
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
118 \includegraphics[width=.6\textwidth]{figures/interfacestack.eps}}
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
119 \end{center}
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
120 \caption{継続制御と関数呼び出しでのスタックの違い}
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
121 \end{figure}
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
122
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
123 しかし並列代入の処理は構造体のようにオーバラップする引数に対しては対応
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
124 しておらず、プログラムによっては引数がちゃんと渡されないなどのバグが生
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
125 じていた。
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
126
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
127
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
128 \section{問題点の改善}
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
129 ここから\ref{sec:cbc-problem}節で紹介した問題点について、本研究での改
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
130 善点を説明する。
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
131
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
132
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
133 \subsection{並列代入}\label{sec:impl-parallel}
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
134 % 一時変数を取得する例を示す
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
135 % 最適化の期待
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
136 % おい、replace_arguments関数、あんまり意味ないぞ
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
137
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
138 \ref{sec:}のコード\ref{code:}で説明した様に、コードセグメントの受け取
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
139 った引数と継続の際に渡す引数の順序が変わる場合等に並列代入が必要になる。
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
140 過去の実装ではこの並列代入を、\verb|expand_call|という構文木から中間コ
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
141 ードを生成する処理の部分で行っていた。
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
142
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
143 しかし実際にはGCCは元より並列代入を実装しているため、独自の実装は必要
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
144 としない。また、この独自の実装にも問題があった。
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
145 そのため独自の実装は廃止し、GCCの機能を利用することにする。
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
146
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
147 コード\ref{code:parallel-example2}は並列代入の必要な軽量継続の例である。
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
148 \lstinputlisting
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
149 [caption=並列代入の必要な軽量継続の例,label=code:parallel-example2]
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
150 {sources/parallel-example.cbc}
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
151
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
152 継続の引数は現在の引数と同じメモリに格納されるため、引数\verb|a|は
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
153 \verb|b|の位置に、引数\verb|b|は\verb|a|の位置に代入されることになる。
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
154 この場合に並列代入を考慮せず、順に代入すると
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
155 \begin{verbatim}
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
156 a = b;
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
157 b = a;
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
158 \end{verbatim}
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
159 となり、両方が同じ値になってしまう。
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
160 ただしこの例は極端に簡略化した例であり、この程度であればtailcallに問題
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
161 はない。しかしより複雑な並列代入では同じ問題が現れる。特に、引数に含ま
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
162 れるコードセグメントポインタへ間接継続する場合には、ほぼ確実に失敗する。
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
163
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
164 この問題の回避策として単純にコード\ref{code:avoiding-parallel}の様に変
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
165 数の値を一時変数に退避することが考えられる。
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
166
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
167 \lstinputlisting
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
168 [caption=引数の退避,label=code:avoiding-parallel]
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
169 {sources/avoiding-parallel.cbc}
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
170
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
171 こうすることで引数が一時変数に確保され、その後そこからコピーする形で所
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
172 定のメモリ位置に戻されるため問題が回避できる。今回の並列代入の改善では
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
173 この手法を用いる。
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
174
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
175 \subsubsection{問題点と最適化の期待}
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
176 この手法でどのように引数を入れ替えても正しく代入可能になる。ただし、一
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
177 時変数の使用は処理速度に問題がある。特にレジスタの少ないアーキテクチャ
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
178 では一時変数の確保にはメモリ上のスタックを用いるため、余計なメモリアク
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
179 セスや冗長な命令が増えてしまう。このため、この手法を実践したコードでは
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
180 そうでないコードに比べて若干の速度低下が見込まれる。
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
181
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
182 その代わり、この速度低下はGCCのもつ最適化機構で回避され得るものである。
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
183 GCCでは中間コード生成後、必要のない一時変数へのコピーなどは最適化によ
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
184 りカットされる。そのため、最適化を有効にした場合はこの処理速度の低下は
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
185 起きないはずである。この影響に関しては\ref{chp:eval}章にて評価を行う。
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
186
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
187 \subsubsection{一時変数への退避の実装}
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
188
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
189 この手法の実装は、中間コード生成時ではなく構文木生成で可能である。
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
190 tailcallの関数呼び出しを表す構文木の生成時に以下の処理を追加する。
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
191 \begin{enumerate}
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
192 \item 関数呼び出しを表す構文木\verb|a|の取得
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
193 \item \verb|a|から引数を表す構文木を取得、それぞれについて
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
194 \begin{enumerate}
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
195 \item 同じ型の名前なし一時変数を作成
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
196 \item 引数の値を一時変数に代入
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
197 \item 関数に渡す引数を一時変数に変更
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
198 \end{enumerate}
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
199 \item 呼び出す関数がポインタだった場合
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
200 \item 関数と同じ型(関数ポインタ)の一時変数を作成
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
201 \item 関数アドレスを一時変数に代入
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
202 \item 呼び出す関数を一時変数に変更
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
203 \end{enumerate}
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
204
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
205 ここでは関数ポインタも引数と同じように扱い、一時変数に退避する。
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
206 実際のプログラムはコード\ref{code:replace-args}の様になる。
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
207 この関数\verb|cbc_replace_arguments|は関数呼び出し構文木を引数として受
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
208 け取り、上記の処理を行う。tree callがその構文木である。
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
209 \verb|build_decl|は名無し一時変数の宣言、 \verb|build_modify_expr|は一
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
210 時変数への代入を行う構文木の生成をしている。
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
211
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
212 \lstinputlisting
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
213 [caption=上記の処理を行う関数,label=code:replace-args]
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
214 {sources/replace-args.c}
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
215
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
216 これによりソースコードの構文解析時、軽量継続をパースしてその構文木を生
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
217 成した際にこの関数\verb|cbc_replace_arguments|を実行することで、この軽
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
218 量継続は並列代入に対応できるようになった。
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
219
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
220 この影響による速度変化の評価は\ref{sec:compare2old}節で行う。
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
221
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
222
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
223 \subsection{環境付き継続}
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
224
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
225 環境付き継続は過去の研究では実装されていなかった。
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
226 これはCとの互換性のために必要な制御構造である。
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
227
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
228 環境付き継続には\ref{ssec:gotowithenv}で述べたように、\verb|__return|
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
229 という擬似変数を使う。この変数の値を継続先のコードセグメントに渡すこと
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
230 で、そのコードセグメントから関数の環境へ復帰することを可能にする。
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
231 渡された\verb|__return|の値は、コードセグメント側からは他のコードセグ
3
d2999e94b97d add gcc.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents: 2
diff changeset
232 メントと区別する必要はない。
2
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
233
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
234 この環境付き継続にもちいる\verb|_ _return|擬似変数の実装には様々な方法
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
235 が考えられるが、今回の実装には内部関数をもちいることにした。内部関数は
3
d2999e94b97d add gcc.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents: 2
diff changeset
236 GCCによるCの拡張機能である\cite{bib:nestedfunc}。
2
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
237
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
238 \subsubsection{GCCにより追加されるコード}
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
239 環境付き継続で使う\verb|__return|変数は特殊なコードセグメントへのポイ
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
240 ンタとなる必要がある。このコードセグメントはユーザでは定義せず、その変
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
241 数を参照した関数の返り値型を基にコンパイラが自動で生成する事が望ましい。
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
242
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
243 具体的には、コード\ref{code:cbcreturn}の関数funcBをコンパイラは次のコ
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
244 ード\ref{code:nestedcode}の様に解釈し、内部コードセグメントを自動生成
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
245 する。
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
246 \lstinputlisting
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
247 [caption=コード\ref{code:cbcreturn}のfuncBに追加される処理,
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
248 label=code:nestedcode,numbers=left]
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
249 {sources/nestedcode.cbc}
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
250
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
251
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
252 5--14行がGCCにより追加される処理である。内部コードセグメント
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
253 \verb|__unnamed_code|は受け取った引数を関数の返り値として保持し、ラベ
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
254 ル\verb|__unnamed_label|にjumpする。この時点で内部コードセグメントを抜
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
255 けて元の関数funcBの環境に復帰する。
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
256
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
257 さらにjump先もGCCにより自動で追加される。しかしこのjump先は
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
258 \verb|__unnamd_code|以外からは実行してはならない。そのため条件式が真に
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
259 ならないif文で囲み、実行を回避している。
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
260 jump先での処理は、\verb|__unnamed_code|内で代入された値を持ってリター
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
261 ンするのみである。
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
262
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
263
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
264 \subsubsection{内部コードセグメント自動生成の実装方法}
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
265
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
266 GCCは変数や関数、また文字列や数値などのリテラルに関する処理を
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
267 \verb|c_parser_postfix_expression|で行っている。この関数では変数や数値
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
268 、文字列などの判定に500行にわたるswitch文を使っているが、ここに
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
269 \verb|__return|の判定も追加する。
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
270
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
271 必要な処理は以下の様になる。
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
272 \begin{itemize}
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
273 \item ラベル\verb|_ _unnamed_label|の宣言
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
274 \item 返り値を保持しておく変数の宣言
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
275 \item 内部関数の定義
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
276 \item 条件分岐制御の構文木生成
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
277 \item 条件分岐内でのラベルの定義
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
278 \item 条件分岐内での復帰構文の構文木生成
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
279 \end{itemize}
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
280 参考のため付録にコード\ref{code:nestedcode}を用意した。
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
281
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
282 %コード\ref{code:nestedcode}にその処理を示す。
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
283 %\lstinputlisting
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
284 % [caption=c\_parser\_postfix\_expressionでの処理,
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
285 % label=code:nestedcode]
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
286 % {sources/c_parser_postfix_expression.c}
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
287 %ここで使われている関数\verb|cbc_define_nested_code|,
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
288 %\verb|cbc_define_if_closed_goto |もこの処理のために作成したものである
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
289 %が割愛する。処理内容は GCCが通常行う関数やif文の構文木生成とほぼ同じで
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
290 %ある。
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
291
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
292 以上でコード\ref{code:nestedcode}に示すような処理がコンパイル時に自動
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
293 で追加され、環境付き継続の使用が可能になった。
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
294
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
295 \subsubsection{関数からの継続}
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
296
3
d2999e94b97d add gcc.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents: 2
diff changeset
297 ここで軽量継続の実装にtailcallを用いたことの弊害がでてくる。
d2999e94b97d add gcc.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents: 2
diff changeset
298 \ref{sec:impl-goto}節の実装では関数からの継続は考慮していない。通常の
2
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
299 継続の際は現コードセグメントのもつ引数は保持しないため、直接継続しよう
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
300 とすると、その関数やその関数を呼び出した関数の持つ環境(スタック)を破
3
d2999e94b97d add gcc.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents: 2
diff changeset
301 壊してしまう(\pageref{fig:gotostack}
d2999e94b97d add gcc.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents: 2
diff changeset
302 ページ、図\ref{fig:gotostack})。
2
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
303
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
304 この問題を回避するため、関数からの継続に限り、スタックを拡張し関数の環
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
305 境を保持する手法をとった。
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
306 この動作は本来の軽量継続の概念とは相容れないものだが、Cとの互換性維持
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
307 のために必要である。また、CbC部分での軽量継続ではいずれもスタックは定
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
308 常なので、CbC の目的である検証、状態遷移記述などの問題にはならない。
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
309
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
310
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
311
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
312 \subsection{PowerPCにおける間接継続}\label{sec:impl-indirect}
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
313
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
314 軽量継続の実装にtailcallを用いたことは\ref{sec:}で説明した。しかし、実
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
315 際にはtailcallが行われないアーキテクチャがいくつか存在する。 PowerPCも
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
316 その一つで、このアーキテクチャでは間接呼び出しの場合は tailcallが行わ
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
317 れない。このためこれまでPowerPCでの間接継続はコンパイルエラーで実行で
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
318 きなかった。
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
319
3
d2999e94b97d add gcc.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents: 2
diff changeset
320 間接呼び出しのtailcallは専用のRTL表現がある。
d2999e94b97d add gcc.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents: 2
diff changeset
321 PowerPCで問題となるのは、このRTLからアセンブラへの変換が定義されていな
d2999e94b97d add gcc.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents: 2
diff changeset
322 いことである。この問題に対処するため、PowerPCアーキテクチャにおけるmc
d2999e94b97d add gcc.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents: 2
diff changeset
323 を記述する。
d2999e94b97d add gcc.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents: 2
diff changeset
324
2
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
325 \subsubsection{RTLとMachine Description}
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
326 GCCは構文木からRTLと呼ばれる中間コードを生成する。この中間コードは一部
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
327 を除いてアーキテクチャ依存性はなく、どのアーキテクチャでもほぼ同じにな
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
328 る。さらに、最終的にこのRTLはアーキテクチャ毎に異なる規則でアセンブラ
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
329 に変換される。この規則を定義するのがMachine Description(以下md)であ
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
330 る。
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
331
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
332 RTL、およびmdはどちらもS式で表現されている。
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
333 GCCは自身のビルドの際、S式をパースするプログラムを作成し、そのプログラ
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
334 ムはmdを基にアーキテクチャ毎に異なるCのソースコードを出力する。このソ
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
335 ースコードがコンパイルされてGCCの一部となる。
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
336
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
337 RTLの例としてこの問題となっている間接継続を表すS式をコード
3
d2999e94b97d add gcc.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents: 2
diff changeset
338 \ref{code:rtl-indirecttailcall}に示す。
2
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
339 \lstinputlisting
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
340 [caption=PowerPCにおける間接継続のRTL,
3
d2999e94b97d add gcc.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents: 2
diff changeset
341 label=code:rtl-indirecttailcall,
2
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
342 language=Lisp]
3
d2999e94b97d add gcc.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents: 2
diff changeset
343 {sources/rtl-indirecttailcall.rtl}
2
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
344
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
345 % TODO: RTLの説明も入れるか?
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
346
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
347 \subsubsection{間接継続のmd}
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
348
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
349 mdにはこのRTLをアセンブラに変換するための情報を定義する。
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
350 定義すべき情報は以下の4つである。
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
351 \begin{itemize}
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
352 \item 規則の名前
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
353 \item 変換するRTL
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
354 \item 変換する条件
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
355 \item 出力するアセンブラを返すCの構文
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
356 \end{itemize}
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
357 同じくmdの例として、この問題となったRTL用の変換規則を定義したものをコ
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
358 ード\ref{code:md-example}に示す。
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
359 \lstinputlisting
3
d2999e94b97d add gcc.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents: 2
diff changeset
360 [caption=\ref{code:rtl-for-indirect}の変換規則,
d2999e94b97d add gcc.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents: 2
diff changeset
361 label=code:md-for-indirect,
2
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
362 language=Lisp]
3
d2999e94b97d add gcc.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents: 2
diff changeset
363 {sources/md-for-indirect.md}
d2999e94b97d add gcc.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents: 2
diff changeset
364 このコードの2番目の要素はコード\ref{code:rtl-indirecttailcall}とよく似
d2999e94b97d add gcc.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents: 2
diff changeset
365 ていることがわかる。これは変換対象としてこの型に合うものに制限するため
d2999e94b97d add gcc.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents: 2
diff changeset
366 である。
d2999e94b97d add gcc.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents: 2
diff changeset
367
2
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
368 ここでは出力するアセンブラとして\verb|b%T0|が使われている。
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
369 \verb|%T0|はレジスタ名に置き換えられる部分である。このアセンブラは最終
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
370 的には\verb|bctr|と置き換えられてPowerPCのアセンブラとして出力される。
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
371 %間接でない、通常の継続ではこれが\verb|bl%T0|となっているので対照的であ
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
372 %る。コード\ref{code:md-example}は実際に通常の継続用のmd修正して作られ
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
373 %た。
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
374
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
375
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
376
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
377
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
378 \subsection{x86における引数渡し}\label{sec:impl-fastcall}
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
379
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
380 コードセグメントの間の軽量継続は、Cの関数呼び出しと同じように引数を渡
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
381 すことができる。関数呼び出しでのこの引数の渡し型はほとんどの場合アーキ
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
382 テクチャやオペレーティングシステム、また各プログラミング言語毎に違った
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
383 規約があり、これは一般に呼出規約(Calling convention)と呼ばれている。
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
384
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
385 CbCでは同じアーキテクチャでもコンパイラによってこの呼出規約は違う。mc
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
386 の軽量継続では、なるべく多くの引数をレジスタに格納するようになっており
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
387 、 PowerPCでは最大11個のint型をレジスタに格納する。レジスタの少ない
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
388 x86でも2つだけだがやはりレジスタを使用している。
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
389
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
390 GCCベースコンパイラでは継続制御の引数渡しに関数の呼出規約と同じ方法を
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
391 使っている。そのため、x86では引数渡しに全てスタックを用いることになり
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
392 、mcに比べて速度低下がみられた。
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
393
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
394 引数渡しにレジスタを使用できるようにすることでこの問題を解決したい。
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
395
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
396 \subsubsection{fastcall}
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
397 そもそも引数渡しがスタックだけだということは、CbCだけでなくCにおいても
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
398 速度面で問題をはらんでいる。そのためGCCではもとより、x86でのレジスタ渡
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
399 しを可能にする拡張機能を実装している。それがfastcallである。
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
400
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
401 このfastcallも使用するレジスタ数は2つだけではあるが、継続制御でもこれ
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
402 を使うことにより高速化が図れるはずである。
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
403
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
404 \subsubsection{コードセグメントを全てfastcallに}
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
405
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
406 通常、GCCの拡張機能を用いて関数をfastcallにするにはコード
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
407 \ref{code:fastcall-example}の様に ``attribute''キーワードを関数宣言の
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
408 後ろに記述する。
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
409
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
410 \begin{minipage}[t]{.7\textwidth}
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
411 \lstinputlisting
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
412 [caption=fastcallな関数funcBを呼び出す例,label=code:fastcall-example]
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
413 {sources/fastcall-example.c}
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
414 \end{minipage}
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
415
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
416 しかし全てのコードセグメントに対してこの属性を宣言するのは現実的でなく
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
417 、mcとのソースコードレベルの整合性もとれない。そこでGCCではコードセグ
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
418 メントの解析時に全てfastcall属性を付加することにする。
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
419
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
420 具体的には「型」の構文解析の際、キーワード``code''で関数の型が宣言され
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
421 ている場合に、属性値を表す構文木を付加する。
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
422 \verb|c_parser_declspecs|関数が「型」に関する構文解析部である。
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
423 この関数内の型名キーワードを処理するswitch文内で、``code''のみ
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
424 fastcall属性を付加する。
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
425
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
426 コード\ref{code:declspecs}がその処理である。このコードの12--14行目が
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
427 fastcall属性付加の処理になる。それ以外の行は voidやintなど他の型の処理
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
428 と変わらない。
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
429
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
430 \lstinputlisting
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
431 [caption=c\_parser\_declspecsにおけるキーワード``code''の処理,
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
432 label=code:declspecs]
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
433 {sources/declspecs.c}
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
434
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
435 この処理で全てのコードセグメントがfastcall対応となり、軽量継続の際には
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
436 レジスタ\verb|ecx,edx|に引数をのせることが可能となる。
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
437
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
438
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
439 \subsection{プロトタイプ自動生成}
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
440 Cのプロトタイプ宣言はコンパイル時のエラー検出に役立っている。
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
441 しかしCbCのコードセグメントには返り値は存在しない。また状態遷移記
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
442 述という性質上、プログラムを記述する際は上から下に実行順にコードセ
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
443 グメントを並べることが多いため、プロトタイプ宣言をするとそれが膨大
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
444 な数になる。
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
445
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
446 また、mcベースコンパイラの方ではプロトタイプ宣言を減らすため、一種の簡
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
447 単な型推論を実装している。そのためこれまでに作られたCbCのプログラムで
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
448 は特殊な場合を除いてプロトタイプ宣言がほとんどなく、GCCでコンパイルす
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
449 る際に問題となる。
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
450
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
451 この問題に暫定的に対処するため、Pythonを用いてプロトタイプの自動生成を
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
452 行うスクリプトを作成した。このスクリプトでは関数の定義部を正規表現で検
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
453 索し、マッチする部分を変換して関数宣言として出力する。
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
454
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
455 全コードは付録\ref{apx:}に掲載する。
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
456
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
457 % TODO: prototype declaration
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
458
50e23a4b2f40 add many files.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
459