[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

stdarg.h



stdarg.h を書き直してみました。

# どーしてこんなに複雑になっちゃうんだー。(;_;)
# long long は 64bit align されるのに double はされなかったり〜

alpha が va_list を構造体にしているので、まねっこしました (alpha に
合わせときゃだいじょうぶだろう:-)。一応バイナリー互換性はあるように
したつもりですが、保証できません(し、完全じゃありません)。

  ↑の説明
  va-ppc.h の va_list は struct {...} va_list[1]; です。また、gcc は
  struct を引数に渡すとコピーを作ってそのアドレスを渡します。よって、
  va_list を構造体にしても同じ構造へのポインターが渡ります。

typedef struct {
	char __gpr;	/* GPR offset */
	char __fpr;	/* FPR offset */
	int *__base;	/* args passed by registers (r3-r10, f1-f8) */
	int *__stack;	/* args passed on stack */
} __va_list;

#define _BSD_VA_LIST_	__va_list
typedef _BSD_VA_LIST_	va_list;

#define	va_start(ap, last)						\
	(__builtin_next_arg(last),					\
	(ap).__stack = __builtin_saveregs(),				\
	(ap).__base = __builtin_frame_address(0) + __builtin_args_info(4), \
	(ap).__gpr = __builtin_args_info(0),				\
	(ap).__fpr = __builtin_args_info(1) - 33 + 8)

#define	__va_size(type)							\
	((sizeof(type) + sizeof(int) - 1) / sizeof(int))

#define __va_longlong(type)						\
	(__builtin_classify_type(*(type *)0) == 1 && sizeof(type) == 8)

#define __va_double(type)						\
	(__builtin_classify_type(*(type *)0) == 8)

#define __va_struct(type)						\
	(__builtin_classify_type(*(type *)0) >= 12)

#define __va_savedgpr(ap, type)						\
	((ap).__base + (ap).__gpr - __va_size(type))

#define __va_savedfpr(ap, type)						\
	((ap).__base + (ap).__fpr - __va_size(type))

#define __va_stack(ap, type)						\
	((ap).__stack += __va_size(type) +				\
			(__va_longlong(type) && ((int)(ap).__stack & 4)), \
	 (ap).__stack - __va_size(type))

#define __va_gpr(ap, type)						\
	((ap).__gpr += __va_size(type) +				\
		      (__va_longlong(type) && ((ap).__gpr & 1)),	\
	 (ap).__gpr <= 8 ?						\
	     __va_savedgpr(ap, type) : __va_stack(ap, type))

#define __va_fpr(ap, type)						\
	((ap).__fpr += __va_size(type),					\
	 (ap).__fpr <= (8 + 2 * 8) ?					\
	     __va_savedfpr(ap, type) : __va_stack(ap, type))

#define	va_arg(ap, type)						\
	(*(type *)(__va_struct(type) ? (*(void **)__va_gpr(ap, void *)) : \
		   __va_double(type) ? __va_fpr(ap, type) :		\
		   __va_gpr(ap, type)))

#define	va_end(ap)