昔の最近の出来事(2013.01)

2013/01/31

気持ち遅めに帰着。

もそもそとコーディング。ふむー。

2013/01/30

気持ち早めに帰着。

もそもそとコーディング。んー。

2013/01/29

気持ち早めに帰着。

もそもそとコーディング。

2013/01/28

気持ち早めに帰着。

何気にD言語向けの WindowsAPIバインディングのソースを見ていたらWin64対応の変更が rev403〜404でコミットされていたり。手持ちのWin64対応と見比べてみたところ完全に 置き換えるには少し修正が足りなさそうだったので、手持ちと同じ変更 になっている部分と、手持ちでは修正されていなかった部分だけを取り込んだり。

もそもそとコーディング。PNG書き込みでシグネチャが 書き込めないのを なんとなく回避していたのですがその原因が判明してみたり。 png_write_info()を使っても何故かファイルの先頭8byteのシグネチャが 書き込まれないというのが謎でした。png_write_sig()を使用しても 書き込まれなかった為、fputc()で強制的に書き込んでました。 書き込まれなかった原因はpng_set_sig_bytes()を使用していた為でした。 png_set_sig_bytes()は本来シグネチャを読み飛ばす為に使用するようなのですが、 書き込みの場合は指定バイト数分のシグネチャ書き込みをスキップします。 ここに8を指定していたもんですから、一切書き込みされなかったという事でした。 png_set_sig_bytes()を削除すれば、png_write_sig()による書き込みも不要 (むしろ入れてしまうと二重書き込みが行われてしまい、そのPNGをWindowsフォトビュアー やファイルエクスプローラのプリビューに食わせるとクラッシュしてしまいました(^^;)で、 png_write_info()だけでシグネチャ書き込みまで行ってくれます。

2013/01/27

昼頃起床。

cairoではぼかしなどのエフェクト系描画は行えません。 この為、いきなりwin32_surfaceにレンダリングするよりは、 image_surfaceというメモリバッファにレンダリングして、 必要に応じて画像加工した後、win32_surfaceにコピーする という感じの方が良いみたい。 image_surfaceの段階ではメモリの配列イメージそのもの なので扱いは比較的簡単なようです。

2013/01/26

起きたら午後もいい時間。寝すぎ。

Web検索したりもそもそ過ごして一日終了。

2013/01/25

早めに帰着。

「書道ガールズ!! わたしたちの甲子園」。最初に辞めた子が 一人足りない子の事かと思ってたのですが、なんか違うらしい というのにしばらく気づきませんでした(^^; でも面白かったです。

「書道ガールズ!! わたしたちの甲子園」の Wikipedia を見ていたら、 「書道ガールズ 青い青い空」へのWikipedia ってのに転送先があって、そちらも見ていたら同時期に同じ 感じの映画が製作されたらしいのを知ったり。 「〜青い空」の方も実話が元になっていそうですが、日本テレビ製作の 「〜甲子園」の方は、実際にズームインSUPERでも取材されていた事や 公開時期が少し早い事などから「〜青い空」の方がタイトル変更となってる みたい。

2013/01/24

早めに帰着。

あまりの眠さに急速停止。

2013/01/23

気持ち早めに。

先日の「Moleman 2」の中でコモドール64(C64)のグラフィック機能について の話がありました。なにやらややこしいルールがあるらしいという事 しか判らなかったので Wikipedia で調べてみたり。引用すると以下のような感じらしい。


4x8ピクセル単位に4色とか、指定色1色+共通色2色とか、ピクセル的には 自由に配置可能だけど、パレットだけがなんとなくファミコンやX68kで 言うところのBG画面のように区切りがあるという感じみたい。 単純に8色しか使えないよりも難しそうですが、うまくやると 多色で凄い絵が描けるという感じでしょうか。まぁでも、 「Moleman 2」の中では、直接描くよりもC64グラフィック向けの (減色)フィルターを通して生成すると言ってましたが(^^;

ややこしいVRAM構造ですが容量って何バイト?と思ったり。 160x200ピクセルだと、(4x8x2+4x4)x(40x25)bit という計算 になるのかな?4x8ピクセル毎に4色選べる(==2bit)ので (4x8x2)。4x8ピクセル毎に16色パレット(4bit)へのポインタが 4色分あると考えると(4x4)。これを1ブロックと定義すると1ブロック あたり(4x8x2+4x4)bit。(40x25)ブロックあるので 160x200ピクセル表現の総bit数は (4x8x2+4x4)x(40x25)bit = 80000bit =10000byte。 単純な16色VRAMの場合 160x200x4bit = 128000bit = 16000byte 。 1/1.6で済んでいると考えると省メモリ構造だと言えるかも。

2013/01/22

気持ち早めに。

Webを検索していたら全然関係無い流れで 「Tokyo Demo Fest」なる イベントの存在を知ったり。表紙ページに紹介されている インビテーションデモは64kイントロなのですが、どうやりゃ64kバイトに 収まるんだよ?!って感じです(^^;
因みに、「メガデモ アドベントカレンダー」 ってページの 「日本のデモグループを一方的に紹介しちゃうよ」 にも紹介されていて、Githubでソースコードが 公開されているのを 知ったり。コード自体はC++で書かれているようですが、圧縮したとして 64kバイトに入るものなのかしら?

そういや、現行の我が家のPCはGPUもそこそこって感じなので、前のPCでは 惨敗していたデモも良い感じで実行できる気も。

Tokyo Demo Fest内ページで紹介されていた 「Moleman 2 - Demoscene - The Art of the Algorithms」を観たり。 1h30mのドキュメンタリームービーでしたが面白かったです。

2013/01/21

気持ち早めに帰着。

Webで調べ事をして終了。

2013/01/20

昼頃起床。

もそもそとコーディング。

cairo描画はレンダリング品質は高いのですが描画速度はいまひとつ。

2013/01/19

AM中に起床。体調不調。

もそもそとコーディング。

2013/01/18

早くも無く遅くもなく。

具合が悪くて急速停止。

2013/01/17

気持ち早めに帰着。

調べ事をして終了。

2013/01/16

早めに帰着。

cairoでアルファ付のimage_surfaceを描画してみたり。 最初、何故かアルファが反映される感じにならなかったのですが、 予め色をアルファ値を掛けた値に加工しておかなくては駄目らしい。

2013/01/15

早くも無く遅くも無く。

調べ事をして終了。

2013/01/14

昼頃起床。

なにやら雪でえらい事になってたり。 関東地方ってなんだかんだと年に1回は雪が降るんですよね。 明日も休みにしたくなる雰囲気です。

以前、VGA的なちょっとしたグラフィック画像を描画するフレームワークを 作成してほっぽらかしにしていたのですが、LINEなどを自力描画していたのを cairo描画におきかえて遊んでみました。

vga_cairo_test

ワイヤーフレーム描画はアンチエリアス無しのほうが良いかもと思ったりも。

Webを検索していたら、 「イース2 オープニング比較動画【ほぼ全機種】」 なる動画を知ったり。機種毎の特徴が出ていて面白いのです。 例えばX1turboは何故か色々と尺が削られていたり、FM77AVやMSX2は色が 沢山使えたり、PC-Engine CD-ROM^2版はそれまでのものから 極端に進化している/判り易くなっている事が伺えたり。
また、ビジュアル比較も面白かった のですが、発売の時期も面白いと思ったりも。動画はソフトの 発売順に並んでいるようなのですが、以下のような並びになってました。

    +------------+------------+
    |マシン      | 時期       |
    +------------+------------+
    |PC-8801     | 1988.04.22 |
    |PC-9801     | 1988.06.24 |
    |X1turbo     | 1988.06.24 |
    |FM77AV      | 1988.07.08 |
    |MSX2        | 1988.07.15 |
    |PCE ROM^2   | 1989.12.21 |
    |ファミコン  | 1990.05.25 |
    |SEGA Saturn | 1998.10.29 |
    |Windows     | 2000.07.06 |
    +------------+------------+

リードプラットフォームのPC-8801版の発売から3ヶ月以内にPC-9801〜MSX2まで 発売されています。恐らくアセンブラもしくはメタアセンブラのような言語で 開発していたとして、PC-8801のCPUはZ80なのでX1turboやMSX2はギリギリ どうにかしたとしても、CPUアーキテクチャの異なるPC-9801やFM77AVは あまり簡単な事では無いと考えられます。 今更ですがどうやってたんだろう?と思う訳です。

さらに動画を漁っていたら、 「PCエンジン・スペースファンタジーゾーン(beta ver)」 なるものを見つけたり。これ、結局出ることの無かった幻のソフト なのですが開発版が流出しているって事なのかしら?因みに当時は開発中の画面写真 が雑誌に掲載されていました(ネットなどというものは無い)。 まぁでも基本的にはスペースハリアーという感じみたいですね。

Webを検索していたら、 HTML5でグラディウスを移植した というのを知ったり。面白いなぁ。

2013/01/13

昼頃起床。

もそもそとコーディング。コードを整理していたらデグってしまって なかなかまとまらなかったり。修行が足りません。

録画してあった「ちはやふる2」を観たり。忘れた頃に二期があると いいなぁと書いたのですが 来ました。面白くなりそうです。

2013/01/12

昼頃起床。微妙な体調。

もそもそとコーディング。

2013/01/11

遅めに帰着。

なんだか風邪を引きそうな感じだったので急速停止。

2013/01/10

遅めに帰着。

cairoを64bitビルドしてみたり。pkg-configを入れなくてはならない事とかをすっかり 忘れていましたが、ひとまずビルドできたり。で、64bit gdcを使って cairo時計をビルド。ひとまずビルドも実行も問題無し。

2013/01/09

少し早めに帰着。

cairo+GDIバックエンド。GDIサイズを大きくするとなぜかメモリリークする件。 一部の文字表示に「cairo_show_text()」を使用していたのですが、これを 外すと問題無かったり。cairo_show_text()の代わりに、 「cairo_text_path();cairo_fill();」で描画する分には問題無し。 何やらバグっているのかしら?

2013/01/08

少し早めに帰着。

cairo+GDIバックエンド。GDIサイズが500x500より大きくなると何故か ウインドサイズを変更した時にメモリリークしていたり。 描画サイズが大きくなった時にWM_PAINTが捨てられるとcairo_surfaceが メモリリークするみたい?原因はイマイチよくわからず。

2013/01/07

少し早めに帰着。

先日のgdcワーニングメッセージ。

c:\mingw\gdc031_2060_463\include\d\4.6.3\std\regex.d: In member function 'std.regex.Regex!(char).Regex.lightPostprocess':
c:\mingw\gdc031_2060_463\include\d\4.6.3\std\regex.d:2025: warning: comparison always true due to limited range of data type

で、実際のコードは

   2018     @trusted void lightPostprocess()
   2019     {//@@@BUG@@@ write is @system
   2020         struct FixedStack(T)
   2021         {
   2022             T[] arr;
   2023             uint _top;
   2024             //this(T[] storage){   arr = storage; _top = -1; }
   2025             @property ref T top(){  assert(!empty); return arr[_top]; }
   2026             void push(T x){  arr[++_top] = x; }
   2027             T pop() { assert(!empty);   return arr[_top--]; }
   2028             @property bool empty(){   return _top == -1; }
   2029         }
   2030         auto counterRange = FixedStack!uint(new uint[maxCounterDepth+1], -1);
   2031         counterRange.push(1);

てな感じ。どうやら2025行目の assert(!empty); が常に条件成立している?(していない?) という事のようなのですが、このstruct FixedStack(T)の部分を最小コードとして 抜き出してみると何故かワーニングメッセージが出ません。 「assert(!empty);」を削ってしまうとメッセージが出なくなる事から、メッセージに 関係がある事は確かなのですが........

どうやら、uint型の_topを -1と比較しているのが引っかかるみたい。 uint型の範囲は 0〜4294967295 で -1にはならないという点を指してワーニング メッセージが出るようになったという流れの様です。_topを int型に変えるか、 empty() 内の比較式 _top==-1 を_top==0xffffffff に変えるとメッセージは出なくなる という感じ。ただ、最小コードでメッセージが出ない理由はやっぱり判りません。謎。

2013/01/06

昼過ぎ起床。

ひとまずlong定数問題に対応した32bit gdcで手持ちコードをいくつかテスト。 概ね問題無い感じだったのですが、一つだけ符号の扱いに若干の問題があるコードが あったり。signed intの変数をフラグのように使っているのが具合が悪い ようでした。で、unsigned int型に変えれば問題無し。他に、std.regexで 常にtrueが成立するようなコードになっている箇所が存在するという ワーニングメッセージが出るようになったり。こちらはまだ調べが付いていません。 そんな訳で32bit gdcはしばらく使ってみて様子見してみようと思います。

随分横道に逸れてしまいましたが、そもそもやってた事はMinGW向けにcairoをビルド して使ってみるという事でした。で、弄り回してなんとなくそれっぽい感じに 動いたり。

CairoClockテスト

最初、なぜか激しくメモリリークしていたのですが、 surfaceを破棄するのにcairo_surface_destroy()を実行しただけではダメで、 cairo_surface_flush()してcairo_surface_finish()した後に cairo_surface_destroy()が必要なようです。

2013/01/05

起きたら午後もいい時間。寝すぎ。

long定数の件。RTLが変っぽいのは判ったのですが、原因については見当が 付かず。GCCの4.xからはフロントエンドが直接RTLを生成するのではなく、 GENERICなるものやGIMPLEなる中間形式を介してRTLが生成される のを知ったり。この段階から変じゃないのか?って事で -fdump-tree-originalなるオプションを使ってダンプしてみたり。

;; Function main (_Dmain)
;; enabled by -tree-original

{
  long foo;

  (void) (foo = 1640261632);
  writef ({.length=3, .ptr="%d\n"}, foo);
  return <retval> = 0;
}

この時点で「long foo = 36000000000 ;」が 「(foo = 1640261632);」になってます。うーむ。

ダンプオプションで-fdump-tree-allを指定すると様々な 中間形式がファイル出力されるようです。ただ、*.originalファイルは 全ての始まりという感じなので、ここがダメだとその後も全てダメ になります。そんな訳でフロントエンドでここんところを出力している 箇所が判れば直せそうなのですがどこら辺なのか見当がつかず。

とりあえずgdbにcc1dを食わせて、それっぽい事をしてそうなところに 勘でブレークポイントを仕込んで変数表示してみれば何か判らないかしら? と思い試してみるのですが、どうにもうまく引っ掛けられず。

そういや、writef()を加えるとwritef()に関係するコードがツリーに 出てくる為、コードを更に以下のように絞ってみました。
$ cat long_test.d
import std.stdio;
import std.string;

int main(string[] args)
{
    long foo1 = 36000000000 ;
    return( cast(int)(foo1) ) ;
}

$ gdc -O0 -fdump-tree-original long_test.d -S

$ cat long_test.d.003t.original

;; Function main (_Dmain)
;; enabled by -tree-original

{
  long foo1;

  (void) (foo1 = 1640261632);
  return <retval> = (int) foo1;
}

;; Function _D9long_test9__modinitFZv (_D9long_test9__modinitFZv)
;; enabled by -tree-original

{
  D.2171.next = _Dmodule_ref;, _Dmodule_ref = &D.2171;;
}

これでgdbを使って値を代入してるコードっぽい所にブレークポイントを設定して 適当に値を見ていたところ、それっぽい値を扱っていそうな感じが見えたので、 スタックダンプを見てみたり。

(gdb) where
#0  build_int_cst_wide (type=0x60f0420, low=1640261632, hi=0) at ../../gcc-4.6.3/gcc/tree.c:1214
#1  0x004f5ce4 in build_int_cst_type (type=0x60f0420, low=1640261632) at ../../gcc-4.6.3/gcc/tree.c:1056
#2  0x004d6414 in IntegerExp::toElem (this=0x61a9568, irs=0x851ff50) at ../../gcc-4.6.3/gcc/d/d-glue.cc:2413
#3  0x004c7528 in IRState::convertForAssignment (this=0x851ff50, expr=0x61a9568, target_type=0x6107998) at ../../gcc-4.6.3/gcc/d/d-codegen.cc:607
#4  0x004d1b50 in AssignExp::toElem (this=0x851efc0, irs=0x851ff50) at ../../gcc-4.6.3/gcc/d/d-glue.cc:932
#5  0x004caaf5 in IRState::emitLocalVar (this=0x851ff50, v=0x61a95d0, no_init=false) at ../../gcc-4.6.3/gcc/d/d-codegen.cc:139
#6  0x004cabac in d_gcc_emit_local_variable (v=0x61a95d0) at ../../gcc-4.6.3/gcc/d/d-codegen.cc:47
#7  0x004d4071 in DeclarationExp::toElem (this=0x61a96b8, irs=0x851ff50) at ../../gcc-4.6.3/gcc/d/d-glue.cc:1686
#8  0x004d35e0 in Expression::toElemDtor (this=0x61a96b8, irs=0x851ff50) at ../../gcc-4.6.3/gcc/d/d-glue.cc:1478
#9  0x004d96fe in ExpStatement::toIR (this=0x61a9688, irs=0x851ff50) at ../../gcc-4.6.3/gcc/d/d-glue.cc:4119
#10 0x004d960a in CompoundStatement::toIR (this=0x61a98f0, irs=0x851ff50) at ../../gcc-4.6.3/gcc/d/d-glue.cc:4086
#11 0x004d960a in CompoundStatement::toIR (this=0x851f160, irs=0x851ff50) at ../../gcc-4.6.3/gcc/d/d-glue.cc:4086
#12 0x004d6925 in FuncDeclaration::toObjFile (this=0x61a9328) at ../../gcc-4.6.3/gcc/d/d-glue.cc:2647
#13 0x004d71d9 in Module::genobjfile (this=0x61a5170, multiobj=0) at ../../gcc-4.6.3/gcc/d/d-glue.cc:2794
#14 0x004c20b7 in d_parse_file () at ../../gcc-4.6.3/gcc/d/d-lang.cc:1111
#15 0x0053dc3e in compile_file (argc=16, argv=0x141d20) at ../../gcc-4.6.3/gcc/toplev.c:579
#16 do_compile (argc=16, argv=0x141d20) at ../../gcc-4.6.3/gcc/toplev.c:1900
#17 toplev_main (argc=16, argv=0x141d20) at ../../gcc-4.6.3/gcc/toplev.c:1963
#18 0x00b19de4 in main (argc=16, argv=0x141d20) at ../../gcc-4.6.3/gcc/main.c:36

gcc/tree.c内に入ってきた頃には「low=1640261632, hi=0」となっているので 既に壊れていそうな予感。スタックトレースに出てきた関数やその周辺コードから 原因箇所に到達できないかと思ったり。

壊れている現場を発見。
d-codegen.cc:IRState::integerConstant (dinteger_t value, tree type)の valueには36000000000という値が保持されているのですが、この中で実行 されるbuild_int_cst_type()という関数の中に入ると値がint32にキャスト されています。でも、この関数では更に shwi_to_double_int()という 関数を実行しており、ここでわざわざ int32を double_int型として 符号拡張しているようです。という訳で意図的に実行しているような気も。
main()のreturnとしてintにキャストしているのがここに見えているのかと思い、

import std.stdio;
import std.string;

void main(string[] args)
{
    long foo1 = 36000000000 ;
}

としてみましたが、やっぱりint32にキャストするコードになりました。

「d/d-codegen.cc:IRState::integerConstant (dinteger_t value, tree type)」の dinteger_tはint64なのですが、この中で実行しているbuild_int_cst_type()で int32にキャストされる事が判りました。しかし、build_int_cst_type()の中では また「double_int_to_tree (type, shwi_to_double_int (low))」という関数実行 でもってint64風の型に再び戻しています。もう少しステップ実行を進めてみたところ、 build_int_cst_type()→double_int_to_tree()→build_int_cst_wide() というように実行されていて、最後のbuild_int_cst_wide()は 「build_int_cst_wide (tree type, unsigned HOST_WIDE_INT low, HOST_WIDE_INT hi)」 てな感じになってました。で思った訳ですが「意味無くね?」と。 そしてbuild_int_cst_wide()を実行するだけで良いのでは?と思い、そんな感じで 直してみた所、longのコードも事の発端となったstd.datetimeの時間取得の コードもうまく動きました。

なぜ64bitターゲットだとうまくいくのかという点。 64bitターゲットだと HOST_WIDE_INT がint64 相当になっており、 この場合 build_int_cst_type()の入力となるint64値を符号拡張して int128相当で扱います。しかし、元々int64の値を入力としている為 int128相当に変換する意味は無く、結果的にint64の値がそのまま 使われる事となり、うまく動くように見えるという感じみたい。 でも、DMD2.058ベースのgdcでも同じコードとなっているのですが、 こちらはうまく動いていて、どう違うのかがイマイチよく判りません。

2013/01/04

仕事始め。遅めに帰着。

あまりの眠さに急速停止。

2013/01/03

昼過ぎ起床。

そういやDMD2.061がリリースされている模様。gdcに来るのはもう少し先か。

datetimeの件改めlong定数の件。ソースを眺めてみるも見当がつかず。 そもそも同じソースでx86_64ターゲットのMinGW gdcは大丈夫だったり するので、gdcがバグっている訳では無い気がしたりも?.....

mingwのgccが4.5.0だったので4.6.2にアップデートしてgdcの再ビルドを試してみたり。 ひとまずビルドはできたものの、やっぱりlong定数の件は解決せず。コンパイラ の問題でもないのか?

以下のコードを使って-fdump-final-insnsオプションを使ってRTLをダンプしてみたり。

$ cat long_test.d
import std.stdio;
import std.string;

void main(string[] args)
{
    long foo = 36000000000 ;
    writef("%d\n",foo ) ;
}

$ gdc -O0 -fdump-final-insns long_test.d

$ ./a.exe
1640261632

long_test.o.gkdというファイルにRTLがダンプされます。該当箇所は以下の ような感じに。
(insn# 0 0 2 (set (mem/c/i:SI (plus:SI (reg/f:SI 6 bp)
                (const_int -16 [0xfffffff0])) [ foo+0 S4 A64])
        (const_int 1640261632 [0x61c46800])) long_test.d:6# {*movsi_internal}
     (nil))
(insn# 0 0 2 (set (mem/c/i:SI (plus:SI (reg/f:SI 6 bp)
                (const_int -12 [0xfffffff4])) [ foo+4 S4 A32])
        (const_int 0 [0])) long_test.d:6# {*movsi_internal}
     (nil))

よく判らない(^^;。ですが、バグっていない64bit gdcで同じようにダンプ してみると以下のような感じでした。

(insn# 0 0 2 (set (mem/c/i:SI (plus:DI (reg/f:DI 6 bp)
                (const_int -8 [0xfffffffffffffff8])) [ foo+0 S4 A64])
        (const_int 1640261632 [0x61c46800])) long_test.d:6# {*movsi_internal}
     (nil))
(insn# 0 0 2 (set (mem/c/i:SI (plus:DI (reg/f:DI 6 bp)
                (const_int -4 [0xfffffffffffffffc])) [ foo+4 S4 A32])
        (const_int 8 [0x8])) long_test.d:6# {*movsi_internal}                  ;;←上位4byteの正しい値
     (nil))

という感じから、やっぱりバグっている方は上位4byteが0になっているようです。 RTLが変という点からフロントエンドがバグっているとも考えられます。

2013/01/02

昼頃起床。

datetimeの件。なかなか追いきれない理由の一つにDate自身をhnsecsに 変換できないというのがあります。例えば、 Date(1, 1, 1).total!"hnsecs"とかやっても 「Error: undefined identifier 'total'」とエラーになってしまいます。 これが使えれば話が簡単なのになんで?って感じ。
で、一度変換を挟む必要がありそう。ただ、これだと怪しい箇所が二つに なるので追いかけにくいですが、ダメになる状況は得られたり。

    auto datetime2 = DateTime(1,1,2,0,0,0) ;
    auto systime2  = SysTime(datetime2) ;
    writef("2: %d\n",systime2.stdTime()) ;

単純にこの変換結果がダメな感じ。期待値540000000000(hnsecs)に対して -323288426496(hnsecs)てな値が返ってきます。因みにこれより1日前の

    auto datetime1 = DateTime(1,1,1,0,0,0) ;
    auto systime1  = SysTime(datetime1) ;
    writef("1: %d\n",systime1.stdTime()) ;

は期待値通り-324000000000(hnsecs)になっています。どう間違うとこうなるんだ?

「writef("%s\n",dur!"days"(1)) ;」の結果が変と いう所が判ってみたり。「1 day」と返ってきて欲しいところが なぜか「1 week, 2 secs, 552 ms, 627 μs, and 2 hnsecs」とか返ってきて 謎。問題はテンプレートであるdurがどこで定義されているのか良くわからない という所。

そういや最近のD言語はアカデミックなフィーチャーが盛り込まれている のですが、あれってデバッグする時の事を考えているんだろうか?と思わなくは ありません。新しいフィーチャーの文法にちっとも付いていけてないTANEには それらを使ったコードを見ても何をやってるのかさっぱり判りません(^^;;

どうやら、libdruntime/core/time.dの中にあるのを発見。これ、テンプレートじゃないの?
やっとこ変っぽい箇所に到達したかも。libdruntime/core/time.dの中に 以下のようなコードがあるのですが、これの返す値が変になっているようです。

   2931 template hnsecsPer(string units)
   2932     if(units == "weeks" ||
   2933        units == "days" ||
   2934        units == "hours" ||
   2935        units == "minutes" ||
   2936        units == "seconds" ||
   2937        units == "msecs" ||
   2938        units == "usecs" ||
   2939        units == "hnsecs")
   2940 {
   2941     static if(units == "hnsecs")
   2942         enum hnsecsPer = 1L;
   2943     else static if(units == "usecs")
   2944         enum hnsecsPer = 10L;
   2945     else static if(units == "msecs")
   2946         enum hnsecsPer = 1000 * hnsecsPer!"usecs";
   2947     else static if(units == "seconds")
   2948         enum hnsecsPer = 1000 * hnsecsPer!"msecs";
   2949     else static if(units == "minutes")
   2950         enum hnsecsPer = 60 * hnsecsPer!"seconds";
   2951     else static if(units == "hours")
   2952         enum hnsecsPer = 60 * hnsecsPer!"minutes";
   2953     else static if(units == "days")
   2954         enum hnsecsPer = 24 * hnsecsPer!"hours";
   2955     else static if(units == "weeks")
   2956         enum hnsecsPer = 7 * hnsecsPer!"days";
   2957 }

これを以下のコードで結果を見てみると、

    writef(" hnsecs/hnsecs...%s\n",hnsecsPer!"hnsecs") ;
    writef("  usecs/hnsecs...%s\n",hnsecsPer!"usecs") ;
    writef("  msecs/hnsecs...%s\n",hnsecsPer!"msecs") ;
    writef("seconds/hnsecs...%s\n",hnsecsPer!"seconds") ;
    writef("minutes/hnsecs...%s\n",hnsecsPer!"minutes") ;
    writef("  hours/hnsecs...%s\n",hnsecsPer!"hours") ;
    writef("   days/hnsecs...%s\n",hnsecsPer!"days") ;

以下のようになりました。

 hnsecs/hnsecs...1
  usecs/hnsecs...10
  msecs/hnsecs...10000
seconds/hnsecs...10000000
minutes/hnsecs...600000000
  hours/hnsecs...1640261632
   days/hnsecs...711573504

hoursとdayaの値が壊れた感じに。なんかこれ、enumの基底型がint(32bit) になってるんじゃ?

さらに絞り込んで、longの定数のコンパイル結果が怪しい感じになっている事が 判明。以下のようなコードで、

    long foo = 36000000000 ;
    writef("%d\n", foo ) ;

次のようなアセンブラコードが生成されていました。因みに最適化オプションは-O0です。

        .loc 1 35 0
        movl    $1640261632, -32(%ebp)   #←─┬36000000000????
        movl    $0, -28(%ebp)            #←─┘
        .loc 1 36 0
        movl    $3, -128(%ebp)
        movl    $LC5, -124(%ebp)
        movl    -32(%ebp), %eax
        movl    -28(%ebp), %edx
        movl    %eax, 8(%esp)
        movl    %edx, 12(%esp)
        movl    -128(%ebp), %esi
        movl    -124(%ebp), %edi
        movl    %esi, (%esp)
        movl    %edi, 4(%esp)
        call    __D3std5stdio17__T6writefTAyaTlZ6writefFAyalZv

即値が変です。もう少し正確に言うと、longの下位4byteは 1640261632==0x61C46800で合っているのですが、 上位4byteの期待値は0x00000008なのが0になっています。 上位4byteが8だとすると、0x861C46800==36000000000で 元のコードに対応します。
うーむ、これはpow式のバグ の仲間のような気も。さて、どうしたもんか。

2013/01/01

明けましておめでとうございますm(_'_)m 今年もよろしくお願いします。

といってもまだ新年から8分を経過した所ですが。 先日買った「ハイスコアガール(3)」を読みふけっていたら 新年を迎えているのに全く気づいていませんでした(^^; 新年早々そんな感じです(^^;;;

寝て起きたら昼頃。

datetimeの件。「static shared」を使用しているのは phobos/druntimeの中でも std/datetime.dだけだったので、この辺を使って最小コードで再現しないか試して みたのですが再現できず。

例外が発生している事はあまり関係無いような気がしてきたのと、どうにも gdbでは見たい変数をうまく表示できない為、結局 datetime.d内をwritef() デバッグしてみたり。その結果、 「immutable dateDiff = (dateTime.date - Date(1, 1, 1)).total!"hnsecs";」 の値が変らしいという事が判ったり。1年1月1日からの差分を100ns単位に変換しています。
で、「writef("%x\n",(Date(1,1,2) - Date(1, 1, 1)).total!"hnsecs") ;」 の様に1日=24時間を 100ns単位に変換してみたところ、 バグっているMinGW-gdcでは「711573504(hnsec)」という結果になったのですが、 正解は「864000000000(hnsec)==24*60*60*10000000」。でも、どう間違えているの かがイマイチ追いきれず。

「ほこ×たて」ドリル対金属頂上決戦。金属強えぇ。ドリルは18mmも 削られてしまっていた上に12mmしか穴を空けられなかった所からも、 金属の硬さをうかがい知る事ができるかも。


TOP PREV