平成26年4月20日
HItech CとGAIO Cの比較
せっかく移植したHitech Cコンパイラですが、全く使い物にならないのではないかという心配はあります。当然、古い時代のコンパイラですから現在のコンパイラと比較して性能の優劣を競うのは無理があります。多少の見劣りはあるとしても実用上問題が無いことがゴールになります。
どの程度の性能かを測る物差しとしてメモリサイズを比較してみました。プログラムは先に移植したモニタプログラムを使用します。このプログラムはプログラム全体では500〜600行(コメント含む)程度です。これをGIOCコンパイラでサイズ優先の最適化を指定してコンパイルすると0xe55(3669)バイトでした。最適化を無しとしても数十バイト程度の増加に留まります。
Hitech Cコンパイラでは、最適化を指示すると0x1141(4417)バイトでした。最適化を無しにすると0x168A(5770)バイトになります。それなりに最適化されているようです。
この比較ではコードサイズは20%程度の増加に留まります。両者のCコードは完全に同じではない(割り込み処理ルーチンの登録の関係でGAIOではdefaultInterrupt()関数を登録したが、Hitech側では個別の関数を用意した)ので、少しだけHitechに不利な条件になっています。まあ大勢には影響しない程度です。
その他で、今回のコンパイルを通す過程で見つかった注意点を書いておきます。その内に注意点をまとめて雛形と一緒にダウンロードできるようにします。
・if文の記述が長いと複雑すぎると怒られる
どうも構文解析のネストをあまり深くはしてくれないようです。アンド条件を4個並べると怒られてしまいます。
if ((i < len) && (i < 0) && (c >= ' ') &&
(c <= '~')) //NG
if ((i < len) && (c >= ' ') && (c <= '~'))
//OK
・関数へのポインタはtypedefする
関数の引数部分に関数へのポインタを定義する、つまり関数へのポインタを引数渡しするとき、関数の引数リストの部分に直接これを記述するとプロトタイプ宣言と一致しないと怒られます。最初は何のことか分からなかったのですが、先にtypedefで関数へのポインタを宣言してその型で引数部分を記述すれば通ります。
例: int abc(int (*i_func)(int), char c); //NG
typedef int (*i_func_t)(int);
int abc(i_func_t i_func, char c); //OK
全体としてCプログラムの構文解析では、あまり複雑な構文は処理してくれないようです。出来るだけ簡潔な記述を優先すべきということでしょう。
これでCコンパイラの移植作業自体は終了です。次には移植の中心となるスタートアップコードの説明とそれに関連するアセンブラやリンカについて書いていきます。