annotate paper/gotoWithEnv.tex @ 17:3afb4bfe1100

fix
author Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
date Mon, 15 Feb 2016 07:30:44 +0900
parents e9a6d390a401
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
8
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
1 \chapter{環境付き継続の実装}
17
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents: 8
diff changeset
2 環境付き継続を行うためには \_\_return, \_\_environment という変数を用いる. 環境とはスタックの状態を指す. C の関数の環境を持って軽量継続を行い, 保存した環境に戻すことで, 環境を持たない code segment から関数に戻ることが可能になる. code segment から C の関数に戻るために保存しなければならないのはスタックポインタとフレームポインタのふたつである. 環境付き継続の実装にはいくつかの方法がある. GCC コンパイラでは nested function を, 以前の LLVM Clang CbC コンパイラでは setjmp, longjmp を使用して実装を行っていた. これら二つの方法に加えて本研究では LLVM builtin の setjmp, longjmp を利用する実装を行った. 本章ではそれぞれに実装について述べる.
8
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
3
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
4 \section{nested function による実装}
17
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents: 8
diff changeset
5 GCC 上に実装した CbC コンパイラでは nested function を利用して環境付き継続の実装を行った\cite{gcc}. 実装の詳細は本論文の趣旨から大きくそれるので, どのようにじつげんしているかについてのみ記す.
8
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
6
17
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents: 8
diff changeset
7 具体的には, リスト\ref{code:cbcreturn2}の関数funcBをコンパイラは次のコード\ref{code:nestedcode}の様に解釈し, 内部 code segment を自動生成する.
8
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
8
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
9
17
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents: 8
diff changeset
10 6 行目から 20 行目が GCC により追加される処理である. 内部 code segment \verb|inner|は受け取った引数を関数の返り値として保持し, ラベル\verb|label|に jumpする. この時点で内部 code segment を抜けて元の関数 int の環境に復帰する.
8
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
11
17
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents: 8
diff changeset
12 さらに jump 先も GCC により自動で追加される. しかしこの jump 先は\verb|inner|以外からは実行してはならない. そのため条件式が真にならない if 文で囲み, 実行を回避している. jump 先での処理は, \verb|inner|内で代入された値を持って reutnr するのみである.
8
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
13
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
14 \begin{lstlisting}[frame=lrbt,label=code:cbcreturn2,caption={環境付き継続の例}]
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
15 __code cs(int retval,__code(*ret)(int,void *),void *env){
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
16 goto ret(n, env);
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
17 }
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
18
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
19 int func (){
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
20 goto cs(30, __return, __environment);
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
21 return 0;
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
22 }
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
23 \end{lstlisting}
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
24
17
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents: 8
diff changeset
25 \begin{lstlisting}[frame=lrbt,label=code:nestedcode,caption={GCC 環境付き継続の内部での解釈}]
8
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
26 __code cs(int retval,__code(*ret)(int,void *),void *env){
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
27 goto ret(n, env);
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
28 }
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
29
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
30 int func (){
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
31 code (*ret)(int);
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
32 int retval;
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
33 __code inner(int val){
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
34 retval = val;
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
35 goto label;
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
36 }
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
37 if(0){
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
38 label:
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
39 return retval;
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
40 }
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
41 ret = inner;
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
42
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
43 goto cs(30, ret);
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
44 return 0;
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
45 }
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
46 \end{lstlisting}
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
47
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
48 \section{setjmp, longjmp による実装}
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
49 nested function は clang, llvm が対応しておらず, 別の方法を取る必要があった. 過去の研究においてこの機能は実装されたが, その際には setjmp, longjmp を用いた実装を行った.
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
50
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
51 環境付き継続は, \_\_return, \_\_environment が使用された時に自動的にあるコードを生成することで実現される. 具体的には, リスト \ref{autoCodeGenB} のようなコードをコンパイルした場合にリスト \ref{autoCodeGenA} のように解釈することで実現される.
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
52
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
53 \begin{lstlisting}[frame=lrbt,label=autoCodeGenB,caption={環境付き継続の例}]
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
54 __code cs(int retval,__code(*ret)(int,void *),void *env){
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
55 goto ret(n, env);
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
56 }
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
57
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
58 int func (){
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
59 goto cs(30, __return, __environment);
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
60 return 0;
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
61 }
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
62 \end{lstlisting}
17
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents: 8
diff changeset
63 \begin{lstlisting}[frame=lrbt,label=autoCodeGenA,caption={LLVM clang の内部での解釈}]
8
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
64 #include <setjmp.h>
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
65
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
66 struct CbC_env {
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
67 void *ret_p,*env;
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
68 };
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
69
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
70 __code cs(int retval,__code(*ret)(int,void *),void *env){
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
71 goto ret(n, env);
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
72 }
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
73
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
74 __code return1 (int retval, void* env){
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
75 *(int*)((struct CbC_env *)(env))->ret_p = retcal;
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
76 longjmp((int*)(((struct CbC_env *)env)->env),1);
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
77 }
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
78
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
79 int func (){
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
80 __code (*__return)();
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
81 struct CbC_env __environment;
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
82 jmp_buf env;
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
83 int retval;
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
84 __environment.ret_p = &retval;
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
85 __environment.env = &env;
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
86 __return = return1;
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
87 if (setjmp(__environment.env)){
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
88 return retval;
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
89 }
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
90 goto code1(30, __return, &__environment);
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
91 return 0;
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
92 }
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
93 \end{lstlisting}
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
94
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
95 追加された処理は, setjmp ヘッダのインクルード, 環境と戻り値を保持する構造体 CbC\_env の定義, 元の環境に戻るための特殊 code segment return1 の定義, そして関数 func 内の 17 行目から 26 行目までの処理であり, 27 行目の継続の第三引数も参照渡しに変更される. 追加された処理の大まかな流れを説明する. 環境付き継続を用いる関数は継続前に setjmp を用いて戻り先の環境を保存し, 継続を行う. このとき, 引数として渡される \_\_return には特殊 code segment return1 のアドレス, \_\_environment の持つメンバには戻り値として返される値を持つ変数のアドレスと, setjmp により保存された継続前の環境が保持されている. 元の環境に戻るための code segment は自動生成されるので, 継続先の code segment は返す戻り値と \_\_environemnt を引数として \_\_return の指す code segment を呼び出すだけで元の環境に戻れる. return1 は 構造体の持つ戻り値へのポインタを利用して戻り値を更新した後, longjmp を用いて元の環境に戻る. longjmp によって再度 setjmp の呼び出しに戻るが今回は if文内に入り, 戻り値を返す.
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
96
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
97 自動生成される文をまとめるといかのようになる.
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
98
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
99 \begin{itemize}
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
100 \item \_\_return
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
101 \begin{itemize}
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
102 \item 元の環境に戻るための特殊な code segment
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
103 \item 各変数の宣言及び代入文
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
104 \end{itemize}
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
105 \item \_\_environment
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
106 \begin{itemize}
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
107 \item 環境を保持する構造体 CbC\_env の定義
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
108 \item 各変数の宣言及び代入文
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
109 \item setjmp を条件文にとり, 真の場合に関数の戻り値を返す if文
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
110 \end{itemize}
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
111 \item どちらにも依存しない
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
112 \begin{itemize}
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
113 \item setjmp.h のインクルード文
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
114 \end{itemize}
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
115 \end{itemize}
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
116
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
117 setjmp.h のインクルード文がどちらにも属さないのは, 無条件でこのヘッダをインクルードするようにしてもよいからである. 必要のないコードは最適化によって除去されるので, 使用されない場合でもインクルードして構わない. また, これらの文を生成する際, 元の関数の型の戻り値を返せるようにしなければならないが, \ref{sec:clang} 節で説明したように, clang では型情報を QualType が管理しているので, 生成する関数や変数に対して元の関数の返り値に対応する QualType を与えるだけでこの問題は解決する. 尚, 二つの予約語を登録する処理は既に説明したので省く.
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
118
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
119 まずはじめに setjmp.h のインクルード文の生成について説明する. clang では include マクロによって他のファイルのインクルードを行う場合, 字句解析対象となるのファイルの変更を行う. 本研究では, これらの処理に必要なものを IncludeHeader という一つの関数にまとめ, それを呼び出すことで任意のファイルをインクルードできるようにした. その関数のうち, 重要な部分を抜き出したものを以下のリスト \ref{IncludeHeader} に示す. この関数は引数に現在の token とインクルードするファイルの名前を求める. まずこの関数は, 現在の token の保存処理を行う. これは, この関数が呼ばれた時点で取得された token はすでに字句解析対象のバッファから取り除かれており, これを保存しておかないとインクルード処理終了後の構文解析に影響が出るために行っている. 次に, 指定されたファイルの検索を行う. その処理を行っているのは 11行目であり, このときファイルが見つからなかった場合には NULL が返るので, これを利用してエラーの生成も行っている. 解析対象の変更を行っているのが 16行目以降の処理で, 実際にファイルを移っているのは 18行目の EnterSourceFile 関数である. この関数によって字句解析対象が現在のファイルから指定したファイルへと変更される. また, この関数の戻り値はファイルのインクルード処理を行ったかどうかを判断するために用いる.
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
120
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
121 \begin{lstlisting}[frame=lrbt,label=IncludeHeader,caption={IncludeHeader 関数}]
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
122 bool Preprocessor::IncludeHeader(Token Tok, const char* Name) {
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
123 if (SavedTokenFlag) // If the lexer has already entered a header file, we have to leave this function.
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
124 return false;
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
125 SourceLocation Loc = Tok.getLocation();
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
126 SavedToken = Tok;
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
127 SavedDepth = IncludeMacroStack.size();
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
128 SavedTokenFlag = true;
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
129
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
130 :
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
131
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
132 const FileEntry *File = LookupFile(Loc, Filename, isAngled, LookupFrom, CurDir, NULL, NULL,
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
133 HeaderInfo.getHeaderSearchOpts().ModuleMaps ? &SuggestedModule : 0);
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
134
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
135 :
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
136
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
137 FileID FID = SourceMgr.createFileID(File, Loc, FileCharacter);
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
138 EnterSourceFile(FID, CurDir, FilenameTok.getLocation(), static_cast<bool>(BuildingModule));
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
139 return true;
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
140 }
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
141 \end{lstlisting}
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
142
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
143 次に, 元の環境に戻るための特殊な code segment の定義生成処理の説明をする. これを行うためには clang の持つ AST に関数の定義を加えてやれば良い. 今回の実装でその処理を担うのが以下のリスト \ref{return1} に示される CreateRetCS 関数である. ただしここでは重要でない箇所を省いている. この関数は引数として生成する関数の名前を受け取る. 2, 3 行目が元の関数の QualType を取得する処理である. 5 行目から 14 行目までの処理は関数宣言のためにスコープをグローバルスコープに変更するための処理で, すべての処理を終えた後, 59 行目から 62 行目の処理によって元のスコープに戻す. 16 行目から 42 行目までが関数のプロトタイプ宣言に関する設定処理を行っており, 29 行目で 取得しておいた QualType を利用していることがわかる. 44 行目からが関数の持つ処理の定義を指定する部分にあたり, 52 行目にある StmtVector クラスのインスタンスに対して任意の文に対応する StmtResult を追加し, 54 行目の関数を呼び出すと戻り値としてこの関数の中身を表す StmtResult を得ることができる. その後これを定義や宣言を管理するクラスである Decl へと変換し, 58 行目の関数を呼び出すことで生成した関数の定義が AST に追加される.
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
144
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
145 \begin{lstlisting}[frame=lrbt,label=return1,caption={CreateRetCS 関数}]
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
146 bool Parser::CreateRetCS(IdentifierInfo *csName){
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
147 FunctionDecl *CurFunctionDecl = Actions.getCurFunctionDecl();
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
148 QualType CurFuncResQT = CurFunctionDecl->getResultType();
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
149
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
150 Scope *SavedScope = getCurScope();
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
151 DeclContext *SavedContext = Actions.CurContext;
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
152 TypeSourceInfo *CurFuncTI = Actions.Context.CreateTypeSourceInfo(CurFuncResQT);
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
153 sema::FunctionScopeInfo *SavedFSI = Actions.FunctionScopes.pop_back_val();
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
154
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
155 Actions.CurContext = static_cast<DeclContext *>(Actions.Context.getTranslationUnitDecl());
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
156 Scope *TopScope = getCurScope();
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
157 while(TopScope->getParent() != NULL)
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
158 TopScope = TopScope->getParent();
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
159 Actions.CurScope = TopScope;
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
160
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
161 DeclGroupPtrTy returnDecl = DeclGroupPtrTy();
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
162 ParsingDeclSpec PDS(*this);
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
163 setTST(&PDS, DeclSpec::TST___code);
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
164 ParsingDeclarator D(*this, PDS, static_cast<Declarator::TheContext>(Declarator::FileContext));
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
165 D.SetIdentifier(csName, Loc);
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
166 ParseScope PrototypeScope(this,Scope::FunctionPrototypeScope|Scope::DeclScope|Scope::FunctionDeclarationScope);
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
167 SmallVector<DeclaratorChunk::ParamInfo, 16> ParamInfo;
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
168 DeclSpec FDS(AttrFactory);
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
169 ParmVarDecl *Param;
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
170
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
171 IdentifierInfo *retvalII = CreateIdentifierInfo(__CBC_RETVAL_NAME, Loc);
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
172 Param = CreateParam(retvalII);
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
173 Param->setTypeSourceInfo(CurFuncTI);
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
174 Param->setType(CurFuncResQT);
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
175
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
176 ParamInfo.push_back(DeclaratorChunk::ParamInfo(retvalII, Loc, Param, 0));
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
177 IdentifierInfo *envII = CreateIdentifierInfo(__CBC_STRUCT_ENV_NAME, Loc);
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
178 Param = CreateParam(envII, 1, DeclSpec::TST_void);
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
179 ParamInfo.push_back(DeclaratorChunk::ParamInfo(envII, Loc, Param, 0));
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
180
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
181 D.AddTypeInfo(DeclaratorChunk::getFunction(HasProto, IsAmbiguous, Loc, ParamInfo.data(), ParamInfo.size(), EllipsisLoc, Loc,
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
182 FDS.getTypeQualifiers(), RefQualifierIsLValueRef, RefQualifierLoc, ConstQualifierLoc,
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
183 VolatileQualifierLoc, SourceLocation(), ESpecType, ESpecRange.getBegin(),
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
184 DynamicExceptions.data(), DynamicExceptionRanges.data(), DynamicExceptions.size(),
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
185 NoexceptExpr.isUsable() ? NoexceptExpr.get() : 0,
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
186 Loc, Loc, D, TrailingReturnType), FnAttrs, Loc);
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
187 PrototypeScope.Exit();
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
188
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
189 Decl *TheDecl;
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
190 ParseScope BodyScope(this, Scope::FnScope|Scope::DeclScope);
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
191 Decl *BodyRes = Actions.ActOnStartOfFunctionDef(getCurScope(), D);
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
192
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
193 D.complete(BodyRes);
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
194 D.getMutableDeclSpec().abort();
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
195 Actions.ActOnDefaultCtorInitializers(BodyRes);
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
196 StmtResult FnBody;
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
197 StmtVector FnStmts;
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
198 /* add function body statements */
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
199 FnBody = Actions.ActOnCompoundStmt(Loc, Loc, FnStmts, false);
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
200 BodyScope.Exit();
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
201 TheDecl = Actions.ActOnFinishFunctionBody(BodyRes, FnBody.take());
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
202 returnDecl = Actions.ConvertDeclToDeclGroup(TheDecl);
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
203 (&Actions.getASTConsumer())->HandleTopLevelDecl(returnDecl.get());
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
204 Actions.CurScope = SavedScope;
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
205 Actions.CurContext = SavedContext;
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
206 Actions.FunctionScopes.push_back(SavedFSI);
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
207 return false;
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
208 }
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
209 \end{lstlisting}
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
210
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
211 つづいて構造体 CbC\_env の定義を行う. この構造体は setjmp, longjmp が環境の保持に使う jmp\_buf へのポインタと元の関数の戻り値となる変数へのポインタを持つ. 構造体の宣言は通常, 構文解析器によって Decl というクラスのインスタンスが生成され, それを利用して行う. 今回の実装では Decl の生成を手書きのコードで行うことで, 自動で構造体の定義を行う処理を実現した. 今回の実装ではそのコード群を Create\_\_CbC\_envStruct という一つの関数にまとめた. その関数のうち,重要な部分を抜き出したものを以下のリスト \ref{CbC_env} に示す. この関数はソースコードの位置と C++ で用いられるアクセス修飾子を引数に取る. この関数もスコープを変更する処理を持つが, それについては先ほど説明したので省いている. 12 行目から 22 行目までが, この構造体の Decl を生成する処理である. メンバの設定を行っているのが 27 行目から 30 行目で, ここで使用している Create\_\_CbC\_envBody 関数はメンバの宣言を行うために独自に作成した関数である. 構造体のメンバとして宣言するために ActOnField という Sema クラスの関数を呼び出す以外は後述する CreateDeclStmt 関数と処理内容にあまり差が無いため, この関数については本論文では説明を省く. 32 行目で呼び出している ActOnTagFinishDefinision が, 生成した Decl を元に構造体の宣言の意味解析を行ってくれる関数である. これにより, 生成した構造体に対応する Type も生成される.
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
212
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
213 \begin{lstlisting}[frame=lrbt,label=CbC_env,caption={Create\_\_CbC\_envStruct 関数}]
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
214 void Parser::Create__CbC_envStruct(SourceLocation Loc, AccessSpecifier AS) {
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
215
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
216 :
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
217
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
218 ParsingDeclSpec SDS(*this);
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
219 DeclSpec::TST TagType = DeclSpec::TST_struct;
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
220 DeclResult TagOrTempResult = true;
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
221 bool Owned = false;
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
222 bool IsDependent = false;
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
223 TagOrTempResult = Actions.ActOnTag(getCurScope(), TagType, Sema::TUK_Definition, Loc,
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
224 SDS.getTypeSpecScope(), Name, Loc, attrs.getList(), AS,
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
225 SDS.getModulePrivateSpecLoc(), TParams, Owned, IsDependent,
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
226 SourceLocation(), false, clang::TypeResult());
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
227
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
228 Decl *TagDecl = TagOrTempResult.get();
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
229 ParseScope StructScope(this, Scope::ClassScope|Scope::DeclScope);
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
230 Actions.ActOnTagStartDefinition(getCurScope(), TagDecl);
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
231 SmallVector<Decl *, 32> FieldDecls;
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
232
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
233 FieldDecls.push_back(Create__CbC_envBody(TagDecl, DeclSpec::TST_void, Loc, __CBC_STRUCT_POINTER_NAME));
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
234 FieldDecls.push_back(Create__CbC_envBody(TagDecl, DeclSpec::TST_int, Loc, __CBC_STRUCT_ENV_NAME));
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
235
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
236 Actions.ActOnFields(getCurScope(),Loc, TagDecl, FieldDecls,Loc, Loc,attrs.getList());
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
237 StructScope.Exit();
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
238 Actions.ActOnTagFinishDefinition(getCurScope(), TagDecl, Loc);
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
239
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
240 :
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
241 }
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
242 \end{lstlisting}
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
243
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
244 つづいて両予約語解析時に共通する処理の一つである変数の定義文に関して説明する. これも定義に関する文であるので Decl の生成がメインとなる. 今回の実装では以下のリスト\ref{DeclStmt} に示す CreateDeclStmt という関数を作り, その関数によってその処理を行う. ここでも重要でない処理は省いている. この関数は引数として変数名, code segment へのポインタかどうか, 呼び出し元の関数の型をコピーするかどうか, 変数の型, 構造体だった場合の構造体名を持つ. 4 行目の setTST 関数が指定された型修飾子を設定している箇所である. 変数名は 6 行目の SetIdentifier 関数によって設定され, その後は関数へのポインタだった場合や構造体だった場合のときにのみ行われる処理が来るがここでは省いた. その後型コピーを行うかどうかで処理が異なる. 型コピーの方法については既に述べたのでここでは省く. すべての処理を終えると, Decl の意味解析が行われ, その結果が StmtResult として返る.
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
245
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
246 \begin{lstlisting}[frame=lrbt,label=DeclStmt,caption={CreateDeclStmt 関数}]
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
247 StmtResult Parser::CreateDeclStmt(IdentifierInfo *II, bool isRetCS, bool copyType, DeclSpec::TST valueType, IdentifierInfo* Name){
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
248 DeclGroupPtrTy DeclGPT;
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
249 ParsingDeclSpec DS(*this);
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
250 setTST(&DS, valueType, Name);
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
251 ParsingDeclarator D(*this, DS, static_cast<Declarator::TheContext>(Declarator::BlockContext));
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
252 D.SetIdentifier(II, Loc);
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
253
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
254 :
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
255
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
256 SmallVector<Decl *, 8> DeclsInGroup;
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
257 Decl *FirstDecl;
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
258
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
259 if (copyType)
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
260 FirstDecl = HandleDeclAndChangeDeclType(D);
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
261 else
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
262 FirstDecl = ParseDeclarationAfterDeclaratorAndAttributes(D);
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
263
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
264 D.complete(FirstDecl);
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
265 DeclsInGroup.push_back(FirstDecl);
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
266 DeclGPT = Actions.FinalizeDeclaratorGroup(getCurScope(), *DSp, DeclsInGroup);
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
267 return Actions.ActOnDeclStmt(DeclGPT, Loc, Loc);
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
268 }
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
269 \end{lstlisting}
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
270
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
271 つづいて両予約語解析時に共通するもう一つの処理, 代入文の生成について説明する. 今回の実装ではこの処理を以下のリスト \ref{assignment} に示す CreateAssginmentStmt 関数にまとめた. ここでも重要でない処理は省いている. この関数は引数として左辺,右辺の変数名と, 左辺が構造体のメンバかどうか, 右辺が演算子 \& を持つかどうか, 左辺が構造体だった場合の構造体名を求める. 8 行目から 14 行目までは左辺に対応する ExprResult を取得する処理で, ExprResult は一つの式に対応するクラスである. 同様に, 18 行目が右辺に対応する ExprResult を取得する処理で, 代入式の生成は 20 行目に当たる. ここで生成した ExprResult を ActOnExprStmt に渡すことで, 式として StmtResult に変換される.
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
272
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
273 \begin{lstlisting}[frame=lrbt,label=assignment,caption={CreateAssignmentStmt 関数}]
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
274 StmtResult Parser::CreateAssignmentStmt(IdentifierInfo* LHSII, IdentifierInfo* RHSII, bool LHSisMemberAccess, bool RHShasAmp,
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
275 IdentifierInfo* extraLHSII){
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
276 ExprResult Expr,LHS,RHS;
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
277 Token Next,LHSToken;
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
278
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
279 :
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
280
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
281 ExternalSpace::StatementFilterCCC Validator(Next);
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
282 Sema::NameClassification Classification = Actions.ClassifyName(getCurScope(), SS, LHSII, Loc, Next, false, SS.isEmpty() ? &Validator : 0);
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
283 setExprAnnotation(LHSToken, Classification.getExpression());
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
284 LHSToken.setAnnotationEndLoc(Loc);
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
285 PP.AnnotateCachedTokens(LHSToken);
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
286
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
287 LHS = getExprAnnotation(LHSToken);
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
288
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
289 :
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
290
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
291 RHS = LookupNameAndBuildExpr(RHSII);
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
292
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
293 Expr = Actions.ActOnBinOp(getCurScope(), Loc,tok::equal,LHS.take(),RHS.take());
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
294
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
295 return Actions.ActOnExprStmt(Expr);
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
296 }
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
297 \end{lstlisting}
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
298
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
299 if 文の自動生成についてであるが, これは if 文のためのスコープを生成した後条件文を作り, その後 if 文内のスコープを作りそこに文を生成していくことで行える. この処理を実現する関数がリスト \ref{} である. この処理は前述した code segment の生成に含まれる処理に酷似する. したがってここではその説明を省略する.
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
300
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
301 \begin{lstlisting}[frame=lrbt,label=assignment,caption={CreateAssignmentStmt 関数}]
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
302 StmtResult Parser::CreateSjForContinuationWithTheEnv(){
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
303 SourceLocation Loc = Tok.getLocation();
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
304 StmtResult IfRes;
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
305 ParseScope IfScope(this, Scope::DeclScope | Scope::ControlScope, true/* C99 or CXX */);
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
306 ExprResult CondExp;
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
307 Decl *CondVar = 0;
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
308
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
309 CondExp = LookupNameAndBuildExpr(CreateIdentifierInfo(``setjmp'', Loc));
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
310 ExprVector ArgExprs;
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
311 ExprResult __envExprRes = CondExp.get();
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
312
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
313 __envExprRes = LookupNameAndBuildExpr(CreateIdentifierInfo(__CBC_ENVIRONMENT_NAME, Loc));
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
314 __envExprRes = LookupMemberAndBuildExpr(CreateIdentifierInfo(__CBC_STRUCT_ENV_NAME, Loc), __envExprRes.get(), false);
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
315
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
316 ArgExprs.push_back(__envExprRes.get());
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
317 CondExp = Actions.ActOnCallExpr(getCurScope(), CondExp.get(), Loc, ArgExprs, Loc, 0);
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
318 CondExp = Actions.ActOnBooleanCondition(getCurScope(), Loc, CondExp.get());
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
319
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
320 FullExprArg FullCondExp(Actions.MakeFullExpr(CondExp.get(), Loc));
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
321 ParseScope InnerScope(this, Scope::DeclScope,false);
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
322 SourceLocation InnerStatementTrailingElseLoc;
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
323
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
324 StmtResult StmtRes;
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
325 ParseScope CompoundScope(this, Scope::DeclScope);
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
326 PrettyStackTraceLoc CrashInfo(PP.getSourceManager(),Loc,''in create setjmp statement for CbC'');
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
327 StmtVector innerStmts;
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
328 StmtResult innerStmtRes;
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
329 ExprResult innerExprRes;
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
330 innerExprRes = LookupNameAndBuildExpr(CreateIdentifierInfo(__CBC_RETVAL_NAME, Loc));
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
331 innerStmtRes = Actions.ActOnReturnStmt(Loc, innerExprRes.get(), getCurScope());
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
332 if (innerStmtRes.isUsable())
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
333 innerStmts.push_back(innerStmtRes.get());
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
334 StmtRes = Actions.ActOnCompoundStmt(Loc, Loc,innerStmts, false);
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
335 StmtResult ThenStmt(StmtRes);
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
336 InnerScope.Exit();
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
337 IfScope.Exit();
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
338 StmtResult ElseStmt;
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
339 IfRes = Actions.ActOnIfStmt(Loc, FullCondExp, CondVar, ThenStmt.get(),Loc, ElseStmt.get());
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
340 return IfRes;
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
341 }
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
342 \end{lstlisting}
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
343
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
344 \section{\_\_builtin\_setjmp, \_\_builtin\_longjmp を用いた実装}
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
345 本研究では llvm, clang 上に実装した CbC の環境付き継続に, \_\_builtin\_setjmp, \_\_builtin\_longjmp を用いるように変更を加えた. これらの関数は LLVM builtin の関数であり, setjmp, longjmp よりも軽量なものであり, 互換性もある.
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
346
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
347 これらの関数を利用するために変更を加えなければならないのは以下の二点である.
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
348
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
349 \begin{itemize}
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
350 \item 使用する関数名の変更
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
351 \item \_\_builtin\_setjmp 用に生成するコードの引数の型を変更
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
352 \end{itemize}
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
353
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
354 使用する関数名の変更は単純に与える文字列を変更すれば良い. なのでこの説明については省く.
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
355
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
356 引数の型について, setjmp も \_\_builtin\_setjmp も引数として jmp\_buf を受け取るが, setjmp が int** で受けるのに対して, \_\_builtin\_setjmp は void** で受ける. そのままでもコンパイル及び実行は可能であるが, コンパイルするたびに警告文が出るのでよろしくない. そのため void** で jmp\_buf を持つように変更を加え, 警告文が出ないよう変更した.
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
357
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
358 変更を行うのはリスト \ref{CbC_env} に示した Create\_\_CbC\_envStruct の一部だけで良い. 変更前がリスト \ref{typeB}, 変更後がリスト \ref{typeA} である. TST\_int を TST\_void に変えただけで他に変更を加える必要はない. これは \ref{sec:clang} 節で説明したとおり, clang が型の表現を QualType を使って簡潔にしている恩恵だと言える.
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
359 \begin{lstlisting}[frame=lrbt,label=typeB,caption={CreateAssignmentStmt 関数変更前}]
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
360 void Parser::Create__CbC_envStruct(SourceLocation Loc, AccessSpecifier AS) {
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
361
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
362 :
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
363
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
364 FieldDecls.push_back(Create__CbC_envBody(TagDecl, DeclSpec::TST_void, Loc, __CBC_STRUCT_POINTER_NAME));
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
365 FieldDecls.push_back(Create__CbC_envBody(TagDecl, DeclSpec::TST_int, Loc, __CBC_STRUCT_ENV_NAME));
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
366
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
367 :
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
368 }
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
369 \end{lstlisting}
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
370
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
371 \begin{lstlisting}[frame=lrbt,label=typeA,caption={CreateAssignmentStmt 関数変更後}]
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
372 void Parser::Create__CbC_envStruct(SourceLocation Loc, AccessSpecifier AS) {
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
373
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
374 :
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
375
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
376 FieldDecls.push_back(Create__CbC_envBody(TagDecl, DeclSpec::TST_void, Loc, __CBC_STRUCT_POINTER_NAME));
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
377 FieldDecls.push_back(Create__CbC_envBody(TagDecl, DeclSpec::TST_void, Loc, __CBC_STRUCT_ENV_NAME));
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
378
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
379 :
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
380 }
Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
parents:
diff changeset
381 \end{lstlisting}