Not only is the Internet dead, it's starting to smell really bad.:2007年10月22日分

2007/10/22(Mon)

[pcc] integer promotion issue with +=

今の実装では(どうやら)TBOOL vs TANYにはならないのです。
事前にSCONVが呼ばれ0/1に変換(つまりTBOOL vs TBOOL)された上で
OPSIMPされるのでs/add/or/;s/sub/xor/してしまえばおkなはず。

...なのですが、これじゃぁC99の仕様的に駄目なんですよね。
JIS X0310:2003から引用。

6.3.1 算術オペランド
6.3.1.1 論理型, 文字型及び整数型
すべての整数型は, 次のとおり定義される整数変換の順位(integer conversion rank)をもつ。
(中略)
 - _Bool型は, その他すべての標準整数型より低い順位をもたなければならない。
(中略)
 - 整数変換の順位がint型及びunsigned int型より低い整数型をもつオブジェクト又は式
 - _Bool型, int型, signed int型,またはunsigned int型のビットフィールド
これらのものの元の型のすべての値をint型で表現可能な場合, その値をint型に変換する。
そうでない場合, unsigned int型に変換する。これらの処理を, 整数拡張(integer promotion)と呼ぶ。
(以下略)

この整数拡張が行われなければならないので
SCONVでTANYが先にTBOOLに変換してしまうと正しい結果が出ないのです。
これが前回の「多分駄目かも」の理由。

整数拡張は_Boolだけではなく、charやshortなどでも必要です。

char x;
int y;

x += y;

というCソースでは、charはintに拡張されますので

movsbl	x,%eax
movl	y,%edx
addl	%edx,%eax
movb	%al,x

というアセンブラになるはずです *1

しかしこのアセンブラは最適化 *2してしまえば

movl	y,%eax
addb	%al,x

と同じです *3
pccもpass1の時点で

0xbb901068) +=, char, 0x0, 0x8075818
    0xbb901154) NAME, 0, -1148186320, char, 0x0, 0x8075818
    0xbb901180) SCONV, char, 0x0, 0x8075818
        0xbb901104) NAME, 0, -1148186124, int, 0x0, 0x8075848

というNode treeを作成し、整数拡張を見事に無視してくれやがります。

ところが_Boolの場合この最適化をやられてしまうと困るのです。

#include <stdbool.h>

_Bool x = true;
int y = 100;
main(void)
{
	x -= y;
	printf("%d\n", x);
}

というコードを考えた場合、今の実装では

となりますが、実際には

とならなければなりません *4、あばばばばばばばばばば。

*1:gcc4は最適化なしだとこれに近いアセンブラを出力します。
*2:6.3.1.3 符号付き整数型及び符号無し整数型 も参照。
*3:gcc3は最適化の有無に関わらず、gcc4だと-01以上でこれに近いアセンブラを出力します。
*4:gccはちゃんと後者で出力されますな。

土曜日

PearlTAMAの檜原村へ。

今回は人数と荷物の関係でレンタカー借りたんだけど
ツーリングワゴンでなくミニバンにしとけばよかった、ちと狭い。
最近の車はよー判らん。

日曜は風邪寒鰤返して寝てた、ゲホゲホ。