なかだです。

At Tue, 12 Mar 2002 13:27:41 +0900,
K.Kosako <kosako / sofnec.co.jp> wrote:
> > alignmentの制約の厳しいアーキテクチャでは、これはSIGBUSかなにか
> > になりそうな気がします。
(snip)
> GNU regexでも整数の読み書きでserializeしているので、
> まずい環境もあるのかなあと思っていたのですが、
> やはり問題ですか。

mc68000はさすがにもう使われてないでしょうが(X68kなら現役?)、一
般にRISCではalignmentされてない(ハーフ)ワードアクセスはできませ
ん。エミュレートしてくれるOSもありますが、速度的なペナルティは
桁違いです。

> 修正するにしても、僅かでも速度を落としたくないので、
> 問題になるアーキテクチャでだけserializeするように
> コンパイル時点で判定できれば良いのですが、そのような
> 方法はないでしょうか?

コンパイラによりますが、たとえばgccなら__i386__、VCなら_M_IX86
というプリプロセッサマクロが定義されています。こういったもので
チマチマと判定してやるしかないような気がします。

#if defined __i386__ || defined _M_IX86 /* intel x86 */
# define UNALIGNED_WORD_ACCESS 1
#elif defined __mc68020__ /* motorola 68020 or later */
# define UNALIGNED_WORD_ACCESS 1
#endif
#ifdef UNALIGNED_WORD_ACCESS
#define GET_RELADDR_INC(addr,p) do{\
  addr = *((RelAddrType* )(p));\
  (p) += SIZE_RELADDR;\
} while(0)
#else
#define GET_2BYTE_INC(addr, p) do{\
  addr = (unsigned short)((UChar)(p)[0] << CHAR_BIT) | (UChar)(p)[1];\
  (p) += 2;\
} while(0)
#define GET_4BYTE_INC(addr, p) do{\
  addr = (unsigned int)((UChar)(p)[0] << 3*CHAR_BIT) | \
	 (unsigned int)((UChar)(p)[1] << 2*CHAR_BIT) | \
	 (unsigned int)((UChar)(p)[2] << CHAR_BIT) | \
	 (UChar)(p)[3];\
  (p) += 2;\
} while(0)
#define GET_RELADDR_INC(addr,p) GET_2BYTE_INC(addr, p)
#endif

あるいは、configureでSIGBUSをトラップすれば、上記のエミュレート
するようなシステムでも判定できるかも知れませんが、実際にそうい
う環境は使ったことがないのでよく分かりません。

AC_CACHE_CHECK(for unaligned word access, rb_cv_unaligned_word_access,
  [AC_TRY_RUN([
#include <signal.h>
#include <stdlib.h>

int main()
{
    char buf[2*sizeof(int)];
    signal(SIGBUS, exit);
    *(int volatile *)(buf+1) = 0;
    return *(int volatile *)(buf+1);
}
],
rb_cv_unaligned_word_access=yes,
rb_cv_unaligned_word_access=no,
rb_cv_unaligned_word_access=no)])

-- 
--- 僕の前にBugはない。
--- 僕の後ろにBugはできる。
    中田 伸悦