参照されないリテラル 長谷川啓 2018.09.13.

Slides:



Advertisements
Similar presentations
知能情報工学演習 I 第 12 回( C 言語第6 回) 課題の回答 岩村雅一
Advertisements

2.5 プログラムの構成要素 (1)文字セット ① ASCII ( American Standard Code for Interchange ) JIS コードと同じ ② EBCDIC ( Extended Binary Coded Decimal for Information Code ) 1.
1 例題 ex3b ( 配列 ) 科学科プログラミング. 2 例題 : ex3b  以下の 3 つについて例題を進める ステップ 1 :配列 ステップ 2 :最小と最大 ステップ 3 :文字型の配列.
復習 配列変数の要素 5は配列の要素数 これらの変数をそれぞれ配列の要素と呼ぶ この数字を配列の添え字,またはインデックスと呼ぶ
復習 配列変数の要素 5は配列の要素数 これらの変数をそれぞれ配列の要素と呼ぶ この数字を配列の添え字,またはインデックスと呼ぶ
情報基礎演習B 後半第5回 担当 岩村 TA 谷本君.
1.1 C/C++言語 Hello.ccを作りコンパイルしてa.outを作り出し実行する
第13回構造体.
データ構造とアルゴリズム 第10回 mallocとfree
アルゴリズムとプログラミング (Algorithms and Programming)
基礎プログラミングおよび演習 第9回
第2回:Javaの変数と型の宣言 プログラミングII 2007年10月2日.
第4回放送授業.
プログラミング演習Ⅰ 課題2 10進数と2進数 2回目.
第10章 char 文字列; 文字列を入力させるよ!.
ちょっとした練習問題① 配列iroを['R', 'W', 'R', 'R', 'W' , 'W' , 'W']を宣言して、「W」のときの配列の番号をprintfで表示するようなプログラムを記述しなさい。
プログラミング論 ファイル入出力
第9章 例外処理,パッケージ 9.1 例外処理 9.2 ガーベッジコレクション.
関数の定義.
プログラミング応用 printfと変数.
最適化の方法 中田育男著 コンパイラの構成と最適化 朝倉書店, 1999年 第11章.
Cプログラミング演習 第7回 メモリ内でのデータの配置.
Nakano School of Business 経営情報ビジネス科 【 Java概論(Test5)】
アルゴリズムとプログラミング (Algorithms and Programming)
プログラミング演習I 2003年5月7日(第4回) 木村巌.
第10章 これはかなり大変な事項!! ~ポインタ~
メモリの準備 メモリには、その準備の方法で2種類ある。 静的変数: コンパイル時にすでにメモリのサイズがわかっているもの。 普通の変数宣言
プログラミング入門2 第11回 情報工学科 篠埜 功.
第13章 文字の取り扱い方 13.1 文字と文字型変数 13.2 文字列 13.3 文字型配列への文字列の代入
第13章 文字の取り扱い方 13.1 文字と文字型関数 13.2 文字列 13.3 文字型配列への文字列の代入
プログラミング入門2 第11回 情報工学科 篠埜 功.
第7回 プログラミングⅡ 第7回
復習 前回の関数のまとめ(1) 関数はmain()関数または他の関数から呼び出されて実行される.
プログラミング言語論 第五回 理工学部 情報システム工学科 新田直也.
アルゴリズムとデータ構造 補足資料5-1 「メモリとポインタ」
プログラミング論 ファイル入出力
言語プロセッサ 第8回目 平成22年11月22日.
P n ポインタの基礎 5 q m 5 7 int* p; int 型の変数を指すポインタ int* q; int 型の変数を指すポインタ int n=5, m=7; int 型の変数 int array[3]; int* pArray[3]; p = &n; ポインタにアドレスを代入しているのでOK.
プログラミング基礎B 文字列の扱い.
一時的な型 長谷川啓
フロントエンドとバックエンドのインターフェース
再帰的手続き.
記号表の検索と登録 長谷川啓
岩村雅一 知能情報工学演習I 第12回(C言語第6回) 岩村雅一
オブジェクト指向言語論 第六回 知能情報学部 新田直也.
プログラミング言語論 第六回 理工学部 情報システム工学科 新田直也.
C言語ファミリー C# 高級言語(抽象的) Java オブジェクト指向 C++ C 機械語(原始的)
アルゴリズムとプログラミング (Algorithms and Programming)
C++ 構文解析 構文解析器の状態保存と復元
第13章 文字の取り扱い方 13.1 文字と文字型変数 13.2 文字列 13.3 文字型配列への文字列の代入
情報基礎演習B 後半第2回 担当 岩村 TA 谷本君.
計算機プログラミングI 第3回 プリミティブ値 クラスメソッド クラス変数 式と演算 変数の利用
高度プログラミング演習 (11).
オブジェクト指向言語論 第五回 知能情報学部 新田直也.
ドキュメントジェネレータ 詳細仕様 長谷川啓
オブジェクト指向言語論 第二回 知能情報学部 新田直也.
X64 函数呼び出し規約 長谷川啓
プログラミング 4 文字列.
Inline 展開のアルゴリズム 長谷川啓
演算子のオーバーロード.
Tacsim の実装 - 実行部分 長谷川啓
第12章 乱数という業の深い存在 ~ランダムな値・他~
プログラミング演習I 2003年6月11日(第9回) 木村巌.
:: の扱い 長谷川啓.
プログラミング演習II 2004年11月 16日(第5回) 理学部数学科・木村巌.
知能情報工学演習I 第9回(後半第3回) 課題の回答
岩村雅一 知能情報工学演習I 第13回(後半第7回) 岩村雅一
デフォルト引数 長谷川啓.
オブジェクト指向言語論 第六回 知能情報学部 新田直也.
プログラミング 2 静的変数.
Presentation transcript:

参照されないリテラル 長谷川啓 2018.09.13

例 void g(char*); int f(void) { } char a[] = "hello"; g(&a[0]); return sizeof "world"; }

f の3番地コード a[0] := 'h' a[1] := 'e' a[2] := 'l' a[3] := 'l' a[4] := 'o' t1 := &a param t1 call g return 6

記号表の最適化 "hello", "world" が記号表に残ったままなのでこれらを削除する。 削除の対象は文字列だけでなく、(おそらくメモリにとられる)定数であってもいい。 1.234L ← long double 型の定数 もちろんユーザー定義のローカル変数、コンパイラの生成した中間変数も削除の対象

参照されないリテラルを消すのはそこそこ大変 void f() { リテラル1 を参照; リテラル2 を参照; ... } void g() { どのリテラルも参照しない; } ここで f で作られたリテラルが全て削除されたとすると・・・ バックエンドジェネレータはリテラル1、リテラル2、・・・に対するアドレス記述子を保持しているので、・・・ int x = 1; // これが削除されたリテラルi と同じアドレスに割り当てられたとすれば・・・ バックエンドジェネレータはリテラルi に対するアドレス記述子を既に持っているので上の宣言に対しては何も行わない(コード生成しない)ことになってしまう。

函数が static や inline 宣言されていてる場合は注意 inline void f(void){ printf("`f' called\n"); } f のコード生成はされない void g(void){ ... } g は f を呼び出していないので "`f' called\n" は参照されていないという理由から記号表から削除してしまうと・・・ void h(void){ ... f(); ... } h: ... t0 := &"`f' called\n" param t0 call printf inline 展開の結果 "`f' called\n" が参照されるが、もはやこの文字列は記号表から削除されている. こういうのを避けるために、リテラルが static や inline 宣言された函数に参照されているかどうかを判別できるようにする必要がある。 set<usr*> referenced_by_static_inline_function; // 単純だが一応機能する。

3番地コードだけじゃなく初期値付きの変数も考慮する必要がある。 char* p = "hello"; char a[] = "world"; void f(void){ ... } f のコード生成で "hello" を削除するのはもちろん間違い a の初期値は 'w', 'o', 'r', 'l', 'd', '\0' だから "world" を記号表から削除するのは ok

リテラルを記号表以外のテーブルで参照していると、記号表から単純に削できない 最適化の都合で、定数は別のテーブルでも参照されている map<string, vector<usr*> >& usrs = scope::root::m_usrs; for ( IT p = usrs.begin() ; p != usrs.end() ; ){ vector<usr*>& v = p->second; usr* u = v.back(); if (erasable(u, code) ) { // code は現在コンパイル中の3番地コード列 IT q = p++; usrs.erase(q); delete u; // まずい. u はconstant<int> だったりして、別のテーブルにも参照されている. } else ++p;