Download presentation
Presentation is loading. Please wait.
1
参照されないリテラル 長谷川啓
2
例 void g(char*); int f(void) { } char a[] = "hello"; g(&a[0]);
return sizeof "world"; }
3
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
4
記号表の最適化 "hello", "world" が記号表に残ったままなのでこれらを削除する。
削除の対象は文字列だけでなく、(おそらくメモリにとられる)定数であってもいい。 1.234L ← long double 型の定数 もちろんユーザー定義のローカル変数、コンパイラの生成した中間変数も削除の対象
5
参照されないリテラルを消すのはそこそこ大変
void f() { リテラル1 を参照; リテラル2 を参照; ... } void g() { どのリテラルも参照しない; } ここで f で作られたリテラルが全て削除されたとすると・・・ バックエンドジェネレータはリテラル1、リテラル2、・・・に対するアドレス記述子を保持しているので、・・・ int x = 1; // これが削除されたリテラルi と同じアドレスに割り当てられたとすれば・・・ バックエンドジェネレータはリテラルi に対するアドレス記述子を既に持っているので上の宣言に対しては何も行わない(コード生成しない)ことになってしまう。
6
函数が 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; // 単純だが一応機能する。
7
3番地コードだけじゃなく初期値付きの変数も考慮する必要がある。
char* p = "hello"; char a[] = "world"; void f(void){ ... } f のコード生成で "hello" を削除するのはもちろん間違い a の初期値は 'w', 'o', 'r', 'l', 'd', '\0' だから "world" を記号表から削除するのは ok
8
リテラルを記号表以外のテーブルで参照していると、記号表から単純に削できない
最適化の都合で、定数は別のテーブルでも参照されている 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;
Similar presentations
© 2024 slidesplayer.net Inc.
All rights reserved.