mirror of
https://github.com/rui314/chibicc
synced 2024-11-22 06:11:18 +03:00
Allow variadic function to take more than 6 parameters
This commit is contained in:
parent
d7bad96114
commit
b6d3cd00df
@ -1178,9 +1178,11 @@ static void emit_text(Obj *prog) {
|
|||||||
int off = fn->va_area->offset;
|
int off = fn->va_area->offset;
|
||||||
|
|
||||||
// va_elem
|
// va_elem
|
||||||
println(" movl $%d, %d(%%rbp)", gp * 8, off);
|
println(" movl $%d, %d(%%rbp)", gp * 8, off); // gp_offset
|
||||||
println(" movl $%d, %d(%%rbp)", fp * 8 + 48, off + 4);
|
println(" movl $%d, %d(%%rbp)", fp * 8 + 48, off + 4); // fp_offset
|
||||||
println(" movq %%rbp, %d(%%rbp)", off + 16);
|
println(" movq %%rbp, %d(%%rbp)", off + 8); // overflow_arg_area
|
||||||
|
println(" addq $16, %d(%%rbp)", off + 8);
|
||||||
|
println(" movq %%rbp, %d(%%rbp)", off + 16); // reg_save_area
|
||||||
println(" addq $%d, %d(%%rbp)", off + 24, off + 16);
|
println(" addq $%d, %d(%%rbp)", off + 24, off + 16);
|
||||||
|
|
||||||
// __reg_save_area__
|
// __reg_save_area__
|
||||||
|
@ -15,28 +15,38 @@ typedef __va_elem va_list[1];
|
|||||||
|
|
||||||
#define va_end(ap)
|
#define va_end(ap)
|
||||||
|
|
||||||
static void *__va_arg_gp(__va_elem *ap) {
|
static void *__va_arg_mem(__va_elem *ap, int sz, int align) {
|
||||||
void *r = (char *)ap->reg_save_area + ap->gp_offset;
|
void *p = ap->overflow_arg_area;
|
||||||
|
if (align > 8)
|
||||||
|
p = (p + 15) / 16 * 16;
|
||||||
|
ap->overflow_arg_area = ((unsigned long)p + sz + 7) / 8 * 8;
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void *__va_arg_gp(__va_elem *ap, int sz, int align) {
|
||||||
|
if (ap->gp_offset >= 48)
|
||||||
|
return __va_arg_mem(ap, sz, align);
|
||||||
|
|
||||||
|
void *r = ap->reg_save_area + ap->gp_offset;
|
||||||
ap->gp_offset += 8;
|
ap->gp_offset += 8;
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void *__va_arg_fp(__va_elem *ap) {
|
static void *__va_arg_fp(__va_elem *ap, int sz, int align) {
|
||||||
void *r = (char *)ap->reg_save_area + ap->fp_offset;
|
if (ap->fp_offset >= 112)
|
||||||
|
return __va_arg_mem(ap, sz, align);
|
||||||
|
|
||||||
|
void *r = ap->reg_save_area + ap->fp_offset;
|
||||||
ap->fp_offset += 8;
|
ap->fp_offset += 8;
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void *__va_arg_mem(__va_elem *ap) {
|
#define va_arg(ap, ty) \
|
||||||
1 / 0; // not implemented
|
({ \
|
||||||
}
|
int klass = __builtin_reg_class(ty); \
|
||||||
|
*(ty *)(klass == 0 ? __va_arg_gp(ap, sizeof(ty), _Alignof(ty)) : \
|
||||||
#define va_arg(ap, type) \
|
klass == 1 ? __va_arg_fp(ap, sizeof(ty), _Alignof(ty)) : \
|
||||||
({ \
|
__va_arg_mem(ap, sizeof(ty), _Alignof(ty))); \
|
||||||
int klass = __builtin_reg_class(type); \
|
|
||||||
*(type *)(klass == 0 ? __va_arg_gp(ap) : \
|
|
||||||
klass == 1 ? __va_arg_fp(ap) : \
|
|
||||||
__va_arg_mem(ap)); \
|
|
||||||
})
|
})
|
||||||
|
|
||||||
#define __GNUC_VA_LIST 1
|
#define __GNUC_VA_LIST 1
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
void assert(int expected, int actual, char *code);
|
void assert(int expected, int actual, char *code);
|
||||||
int printf(char *fmt, ...);
|
int printf(char *fmt, ...);
|
||||||
int sprintf(char *buf, char *fmt, ...);
|
int sprintf(char *buf, char *fmt, ...);
|
||||||
|
int vsprintf(char *buf, char *fmt, void *ap);
|
||||||
int strcmp(char *p, char *q);
|
int strcmp(char *p, char *q);
|
||||||
int strncmp(char *p, char *q, long n);
|
int strncmp(char *p, char *q, long n);
|
||||||
int memcmp(char *p, char *q, long n);
|
int memcmp(char *p, char *q, long n);
|
||||||
|
@ -28,9 +28,20 @@ int sum2(int x, ...) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char *fmt(char *buf, char *fmt, ...) {
|
||||||
|
va_list ap;
|
||||||
|
va_start(ap, fmt);
|
||||||
|
vsprintf(buf, fmt, ap);
|
||||||
|
va_end(ap);
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
ASSERT(6, sum1(1, 2, 3, 0));
|
ASSERT(6, sum1(1, 2, 3, 0));
|
||||||
|
ASSERT(55, sum1(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 0));
|
||||||
ASSERT(21, sum2(1, 2.0, 3, 4.0, 5, 6.0, 0));
|
ASSERT(21, sum2(1, 2.0, 3, 4.0, 5, 6.0, 0));
|
||||||
|
ASSERT(21, sum2(1, 2.0, 3, 4.0, 5, 6.0, 0));
|
||||||
|
ASSERT(210, sum2(1, 2.0, 3, 4.0, 5, 6.0, 7, 8.0, 9, 10.0, 11, 12.0, 13, 14.0, 15, 16.0, 17, 18.0, 19, 20.0, 0));
|
||||||
|
|
||||||
printf("OK\n");
|
printf("OK\n");
|
||||||
return 0;
|
return 0;
|
||||||
|
Loading…
Reference in New Issue
Block a user