Mercurial > hg > Papers > 2011 > nobu-prosym
comparison Paper/nobu-prosym.tex @ 19:e89540b527cf
modify
author | Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp> |
---|---|
date | Sun, 20 Nov 2011 08:03:08 +0900 |
parents | 8ea8be1671d0 |
children | 9e904a731cf4 |
comparison
equal
deleted
inserted
replaced
18:085054e84bc5 | 19:e89540b527cf |
---|---|
239 | 239 |
240 \subsubsection{expand\_call} | 240 \subsubsection{expand\_call} |
241 ある関数が Tail Call Elimination を行えるかどうかは \verb+expand_call+ 関数で判断される. | 241 ある関数が Tail Call Elimination を行えるかどうかは \verb+expand_call+ 関数で判断される. |
242 \verb+expand_call+ 関数内でチェックされる Tail Call Elimination が行える条件は以下になる. | 242 \verb+expand_call+ 関数内でチェックされる Tail Call Elimination が行える条件は以下になる. |
243 | 243 |
244 \begin{itemize} | 244 %\begin{itemize} |
245 \begin{enumerate} | |
245 \item caller 側と callee 側の戻値の型が一致している. | 246 \item caller 側と callee 側の戻値の型が一致している. |
246 \item 関数呼び出しがリターンの直前に行われている. | 247 \item 関数呼び出しがリターンの直前に行われている. |
247 \item 呼出先関数の引数に用いられるスタックサイズが呼出元関数のそれより少ない. | 248 \item 呼出先関数の引数に用いられるスタックサイズが呼出元関数のそれより少ない. |
248 \item 引数の並びのコピーに上書きがない. | 249 \item 引数の並びのコピーに上書きがない. |
249 \end{itemize} | 250 \end{enumerate} |
251 %\end{itemize} | |
250 | 252 |
251 CbC の実装では上記の条件を,以下の様にして解決させている. | 253 CbC の実装では上記の条件を,以下の様にして解決させている. |
252 | 254 |
253 \begin{itemize} | 255 \begin{enumerate} |
256 %\begin{itemize} | |
254 \item コードセグメントは void 型で統一する. Cの関数からコードセグメントに goto する場合は返す値の型チェックを行わない. | 257 \item コードセグメントは void 型で統一する. Cの関数からコードセグメントに goto する場合は返す値の型チェックを行わない. |
255 \item goto の直後に retrun を置く. | 258 \item goto の直後に retrun を置く. |
256 \item スタックサイズは関数宣言時に決まったサイズにする. | 259 \item スタックサイズは関数宣言時に決まったサイズにする. |
257 \item 引数は一旦, 一時変数にコピーして重なりがないようにする. | 260 \item 引数は一旦, 一時変数にコピーして重なりがないようにする. |
258 \end{itemize} | 261 %\end{itemize} |
259 | 262 \end{enumerate} |
260 スタックサイズを決め打ちで行うことで,ベースポインタを変えずにスタックを扱うことができる. | 263 |
264 1 については自明だろう.コードセグメントは戻値を持たない為 void 型の扱いになる. | |
265 2, 3 と 4 については以下で詳しく説明を行う. | |
266 | |
267 \subsubsection{継続の直後に return の配置} | |
268 この処理は Generic Tree の生成時に組み込んである為, ユーザは return を記述する必要はない. | |
269 例をあげると, 図\ref{fig:factorial}の factorial0 は, | |
270 プログラム内部では図\ref{code:return}の様に処理されることになる. | |
271 \begin{figure}[h] | |
272 \begin{minipage}[b]{.45\textwidth} | |
273 \begin{lstlisting}[caption=継続の直後に return を置く,label=code:return] | |
274 __code factorial0(int prod, int x) | |
275 { | |
276 if ( x >= 1) { | |
277 goto factorial0(prod*x, x-1); | |
278 return; | |
279 }else{ | |
280 goto print_factorial(prod); | |
281 return; | |
282 } | |
283 } | |
284 \end{lstlisting} | |
285 \end{minipage} | |
286 \hfill | |
287 \end{figure} | |
288 | |
289 | |
290 %goto でコードセグメントの継続を行うプログラムの直後に return を表す情報を Generic Tree に追加を行う. | |
291 | |
292 \subsubsection{スタックサイズの固定化} | |
293 CbC では継続によりスタックに値が積まれていくということはない為サイズを固定することができる. | |
294 また, サイズが固定な為, スタックポインタを変えずにスタックを扱うことができる. | |
261 これも CbC の1つの特徴である. | 295 これも CbC の1つの特徴である. |
262 図\ref{fig:cs_stack}はコードセグメントの継続の際にスタックに積まれる引数を表している. | 296 図\ref{fig:cs_stack}はコードセグメントの継続の際にスタックに積まれる引数を表している. |
263 | 297 |
264 \begin{figure}[htpb] | 298 \begin{figure}[htpb] |
265 \begin{center} | 299 \begin{center} |
270 \end{figure} | 304 \end{figure} |
271 | 305 |
272 %GCCでは, この他にもTCEを禁止するルールがあり, GCC-4.5, 4.6 でも | 306 %GCCでは, この他にもTCEを禁止するルールがあり, GCC-4.5, 4.6 でも |
273 %Tail Call Elimination にかからないコードセグメントがある. | 307 %Tail Call Elimination にかからないコードセグメントがある. |
274 %この点を改善する必要がある. | 308 %この点を改善する必要がある. |
275 | |
276 | 309 |
277 %\subsection{引数の一時変数への避難} | 310 %\subsection{引数の一時変数への避難} |
278 %\subsection{スタック書き換えの問題} | 311 %\subsection{スタック書き換えの問題} |
279 \subsection{引数の並びの上書きコピー} | 312 \subsection{引数の並びの上書きコピー} |
280 CbC の継続では, 引数渡しでスタックを入れ替える為値が書き換えられる可能性がでてくる. | 313 CbC の継続では, 引数渡しでスタックを入れ替える為値が書き換えられる可能性がでてくる. |
281 例えばlistlising\ref{code:cs_prog}のような継続である. | 314 例えばlistlising\ref{code:cs_prog}のような継続である. |
282 \begin{figure}[h] | 315 \begin{figure}[h] |
283 \begin{minipage}[b]{.45\textwidth} | 316 \begin{minipage}[b]{.45\textwidth} |
284 \begin{lstlisting}[caption=,label=code:cs_prog] | 317 \begin{lstlisting}[caption=スタックの上書きが起こる継続の例,label=code:cs_prog] |
285 __code cs_a(int a, int b) { | 318 __code cs_a(int a, int b) { |
286 goto cs_b(b, a) | 319 goto cs_b(b, a) |
287 } | 320 } |
288 \end{lstlisting} | 321 \end{lstlisting} |
289 \end{minipage} | 322 \end{minipage} |
290 \hfill | 323 \hfill |
291 \end{figure} | 324 \end{figure} |
292 | 325 |
293 この時のスタックの様子を表したのが図\ref{fig:cs_prog}となる. | |
294 | 326 |
295 \begin{figure}[htpb] | 327 \begin{figure}[htpb] |
296 \begin{center} | 328 \begin{center} |
297 \scalebox{0.33}{\includegraphics{figure/cs_prog.eps}} | 329 \scalebox{0.33}{\includegraphics{figure/cs_prog.eps}} |
298 \end{center} | 330 \end{center} |
299 \caption{スタック書き換えの問題} | 331 \caption{スタック書き換えの問題} |
300 \label{fig:cs_prog} | 332 \label{fig:cs_prog} |
301 \end{figure} | 333 \end{figure} |
302 | 334 この時のスタックの様子を表したのが図\ref{fig:cs_prog}となる. |
303 数字の 1 と 2 は \verb+cs_b+ の引数をスタックに乗せる順を表している. | 335 数字の 1 と 2 は \verb+cs_b+ の引数をスタックに乗せる順を表している. |
304 CbC ではこの問題を一時変数に引数の値を代入することで問題を解決している. | 336 CbC ではこの問題を一時変数に引数の値を代入することで問題を解決している. |
305 | 337 |
306 \subsubsection{一時変数へのコピー} | 338 \subsubsection{一時変数へのコピー} |
307 一時変数へのコピーは, goto が行われた時の, コードセグメントの Generic Tree 生成時に行われる. | 339 一時変数へのコピーは, goto が行われた時の, コードセグメントの Generic Tree 生成時に行われる. |
327 \item 引数と同じ型の一時変数を作成 | 359 \item 引数と同じ型の一時変数を作成 |
328 \item 一時変数に引数の値を代入 | 360 \item 一時変数に引数の値を代入 |
329 \item 関数に渡す引数のポインタを一時変数に変更 | 361 \item 関数に渡す引数のポインタを一時変数に変更 |
330 \end{itemize} | 362 \end{itemize} |
331 | 363 |
332 tree call は継続を行うコードセグメントになる. | 364 tree call は継続を行うコードセグメントを指す. |
333 コードセグメントに渡された引数の情報を抜き出す部分が \verb+FOR_EACH_CALL_EXPR_ARG+ である. | 365 コードセグメントに渡された引数の情報を抜き出す部分が \verb+FOR_EACH_CALL_EXPR_ARG+ である. |
334 \verb+tmp_decl+ という一時変数を作り,最後に \verb+CALL_EXPR_ARG+ を使って引数の情報が入っていた | 366 \verb+tmp_decl+ という一時変数を作り,最後に \verb+CALL_EXPR_ARG+ を使って引数の情報が入っていた |
335 ところへ一時変数を入れている. | 367 ところへ一時変数を入れている. |
336 | |
337 | 368 |
338 | 369 |
339 \subsection{環境付き継続} | 370 \subsection{環境付き継続} |
340 CbC には通常の C の関数からコードセグメントに継続する際, | 371 CbC には通常の C の関数からコードセグメントに継続する際, |
341 その関数から値を戻す処理への継続を得ることができる. | 372 その関数から値を戻す処理への継続を得ることができる. |
395 GCC には引数渡しをスタックではなくレジスタを用いて行う機能として fastcall がある. | 426 GCC には引数渡しをスタックではなくレジスタを用いて行う機能として fastcall がある. |
396 fastcall を用いてコードセグメント間を継続することで, 速度の向上を図る. | 427 fastcall を用いてコードセグメント間を継続することで, 速度の向上を図る. |
397 | 428 |
398 \subsubsection{fastcall} | 429 \subsubsection{fastcall} |
399 C において fastcall を用いる場合は関数にキーワード ``\verb+__attribute__ ((fastcall))+'' をつけて行う. | 430 C において fastcall を用いる場合は関数にキーワード ``\verb+__attribute__ ((fastcall))+'' をつけて行う. |
400 だが, コードセグメントを全てこのキーワードをつけて宣言することは実用できではない. | 431 だが, コードセグメントを全てこのキーワードをつけて宣言することは実用的ではない. |
401 そこで, コードセグメントで宣言された場合, fastcall が自動で付くように実装を行う. | 432 そこで, コードセグメントで宣言された場合, fastcall が自動で付くように実装を行う. |
402 図\ref{fig:fastcall}はコードセグメントに fastcall 属性を付与しているコードである. | 433 図\ref{fig:fastcall}はコードセグメントに fastcall 属性を付与しているコードである. |
403 | 434 |
404 %\lstinputlisting[language=c]{source/fastcall.c} | 435 %\lstinputlisting[language=c]{source/fastcall.c} |
405 | 436 |