diff --git a/libtcc.c b/libtcc.c
index 478d23b..22778c9 100644
--- a/libtcc.c
+++ b/libtcc.c
@@ -843,6 +843,9 @@ LIBTCCAPI TCCState *tcc_new(void)
     tcc_define_symbol(s, "__unix__", NULL);
     tcc_define_symbol(s, "__unix", NULL);
     tcc_define_symbol(s, "unix", NULL);
+# if defined(__APPLE__)
+    tcc_define_symbol(s, "__APPLE__", NULL);
+# endif
 # if defined(__linux__)
     tcc_define_symbol(s, "__linux__", NULL);
     tcc_define_symbol(s, "__linux", NULL);
diff --git a/tccrun.c b/tccrun.c
index fe7a757..ae74e3b 100644
--- a/tccrun.c
+++ b/tccrun.c
@@ -26,6 +26,9 @@
 #ifndef _WIN32
 # include <sys/mman.h>
 #endif
+#ifdef __APPLE__
+# include <libkern/OSCacheControl.h>
+#endif
 
 #ifdef CONFIG_TCC_BACKTRACE
 # ifndef _WIN32
@@ -292,7 +295,12 @@ static void set_pages_executable(void *ptr, unsigned long length)
         tcc_error("mprotect failed: did you mean to configure --with-selinux?");
 # endif
 # if defined TCC_TARGET_ARM || defined TCC_TARGET_ARM64
+#  ifdef __APPLE__
+    sys_icache_invalidate(ptr, length);
+    sys_dcache_flush(ptr, length);
+#  else
     __clear_cache(ptr, (char *)ptr + length);
+#  endif
 # endif
 #endif
 }
@@ -702,11 +710,19 @@ static int rt_get_caller_pc(addr_t *paddr, ucontext_t *uc, int level)
     if (level < 0)
         return -1;
     else if (level == 0) {
+#if defined(__APPLE__)
+        *paddr = uc->uc_mcontext->__ss.__pc;
+#else
         *paddr = uc->uc_mcontext.pc;
+#endif
         return 0;
     }
     else {
+#if defined(__APPLE__)
+        addr_t *fp = (addr_t *)uc->uc_mcontext->__ss.__fp;
+#else
         addr_t *fp = (addr_t *)uc->uc_mcontext.regs[29];
+#endif
         int i;
         for (i = 1; i < level; i++)
             fp = (addr_t *)fp[0];
diff --git a/arm64-gen.c b/arm64-gen.c
index 5606271..5b3a60c 100644
--- a/arm64-gen.c
+++ b/arm64-gen.c
@@ -65,7 +65,11 @@ ST_DATA const int reg_classes[NB_REGS] = {
   RC_INT | RC_R(15),
   RC_INT | RC_R(16),
   RC_INT | RC_R(17),
+#ifdef __APPLE__
+  RC_R(18),
+#else
   RC_INT | RC_R(18),
+#endif
   RC_R30, // not in RC_INT as we make special use of x30
   RC_FLOAT | RC_F(0),
   RC_FLOAT | RC_F(1),
@@ -662,17 +666,56 @@ static int arm64_hfa(CType *type, int *fsize)
     return 0;
 }
 
-static unsigned long arm64_pcs_aux(int n, CType **type, unsigned long *a)
+typedef struct PCSAlloc PCSAlloc;
+
+enum {
+    PCS_VOID,
+    PCS_IREG,
+    PCS_FREG,
+    PCS_STACK
+} PCSType;
+
+struct PCSAlloc {
+    unsigned long
+    type     : 2,
+    value    : 61,
+    indirect : 1;
+};
+
+#define PCS_ALLOC_MAKE_VOID() (PCSAlloc) { PCS_VOID, 0, 0 }
+#define PCS_ALLOC_MAKE_IREG(v) (PCSAlloc) { PCS_IREG, v, 0 }
+#define PCS_ALLOC_MAKE_FREG(v) (PCSAlloc) { PCS_FREG, v, 0 }
+#define PCS_ALLOC_MAKE_STACK(v) (PCSAlloc) { PCS_STACK, v, 0 }
+
+#define PCS_ALLOC_MAKE_IREG_INDIRECT(v) (PCSAlloc) { PCS_IREG, v, 1 }
+#define PCS_ALLOC_MAKE_STACK_INDIRECT(v) (PCSAlloc) { PCS_STACK, v, 1 }
+
+static unsigned long arm64_pcs_aux(int n, int nb_fixed, CType **type,
+                                   PCSAlloc *a)
 {
     int nx = 0; // next integer register
     int nv = 0; // next vector register
-    unsigned long ns = 32; // next stack offset
+    unsigned long ns = 0; // next stack offset
     int i;
+    int align_and_enlarge_small = 1;
+
+#ifdef __APPLE__
+    align_and_enlarge_small = 0;
+#endif
 
     for (i = 0; i < n; i++) {
         int hfa = arm64_hfa(type[i], 0);
         int size, align;
 
+#ifdef __APPLE__
+        if (i == nb_fixed) {
+            nx = 8;
+            nv = 8;
+
+            align_and_enlarge_small = 1;
+        }
+#endif
+
         if ((type[i]->t & VT_ARRAY) ||
             (type[i]->t & VT_BTYPE) == VT_FUNC)
             size = align = 8;
@@ -684,11 +727,11 @@ static unsigned long arm64_pcs_aux(int n, CType **type, unsigned long *a)
             ;
         else if (size > 16) {
             // B.3: replace with pointer
-            if (nx < 8)
-                a[i] = nx++ << 1 | 1;
-            else {
+            if (nx < 8) {
+                a[i] = PCS_ALLOC_MAKE_IREG_INDIRECT(nx++);
+            } else {
                 ns = (ns + 7) & ~7;
-                a[i] = ns | 1;
+                a[i] = PCS_ALLOC_MAKE_STACK_INDIRECT(ns);
                 ns += 8;
             }
             continue;
@@ -699,13 +742,13 @@ static unsigned long arm64_pcs_aux(int n, CType **type, unsigned long *a)
 
         // C.1
         if (is_float(type[i]->t) && nv < 8) {
-            a[i] = 16 + (nv++ << 1);
+            a[i] = PCS_ALLOC_MAKE_FREG(nv++);
             continue;
         }
 
         // C.2
         if (hfa && nv + hfa <= 8) {
-            a[i] = 16 + (nv << 1);
+            a[i] = PCS_ALLOC_MAKE_FREG(nv);
             nv += hfa;
             continue;
         }
@@ -718,7 +761,8 @@ static unsigned long arm64_pcs_aux(int n, CType **type, unsigned long *a)
 
         // C.4
         if (hfa || (type[i]->t & VT_BTYPE) == VT_LDOUBLE) {
-            ns = (ns + 7) & ~7;
+            if (align_and_enlarge_small)
+                ns = (ns + 7) & ~7;
             ns = (ns + align - 1) & -align;
         }
 
@@ -728,31 +772,33 @@ static unsigned long arm64_pcs_aux(int n, CType **type, unsigned long *a)
 
         // C.6
         if (hfa || is_float(type[i]->t)) {
-            a[i] = ns;
+            a[i] = PCS_ALLOC_MAKE_STACK(ns);
             ns += size;
             continue;
         }
 
         // C.7
         if ((type[i]->t & VT_BTYPE) != VT_STRUCT && size <= 8 && nx < 8) {
-            a[i] = nx++ << 1;
+            a[i] = PCS_ALLOC_MAKE_IREG(nx++);
             continue;
         }
 
         // C.8
+#ifndef __APPLE__
         if (align == 16)
             nx = (nx + 1) & ~1;
+#endif
 
         // C.9
         if ((type[i]->t & VT_BTYPE) != VT_STRUCT && size == 16 && nx < 7) {
-            a[i] = nx << 1;
+            a[i] = PCS_ALLOC_MAKE_IREG(nx);
             nx += 2;
             continue;
         }
 
         // C.10
         if ((type[i]->t & VT_BTYPE) == VT_STRUCT && size <= (8 - nx) * 8) {
-            a[i] = nx << 1;
+            a[i] = PCS_ALLOC_MAKE_IREG(nx);
             nx += (size + 7) >> 3;
             continue;
         }
@@ -761,42 +807,44 @@ static unsigned long arm64_pcs_aux(int n, CType **type, unsigned long *a)
         nx = 8;
 
         // C.12
-        ns = (ns + 7) & ~7;
+        if (align_and_enlarge_small)
+            ns = (ns + 7) & ~7;
         ns = (ns + align - 1) & -align;
 
         // C.13
         if ((type[i]->t & VT_BTYPE) == VT_STRUCT) {
-            a[i] = ns;
+            a[i] = PCS_ALLOC_MAKE_STACK(ns);
             ns += size;
             continue;
         }
 
         // C.14
-        if (size < 8)
+        if (align_and_enlarge_small && size < 8)
             size = 8;
 
         // C.15
-        a[i] = ns;
+        a[i] = PCS_ALLOC_MAKE_STACK(ns);
         ns += size;
     }
 
-    return ns - 32;
+    return ns;
 }
 
-static unsigned long arm64_pcs(int n, CType **type, unsigned long *a)
+static unsigned long arm64_pcs(int n, int nb_fixed, CType **type, PCSAlloc *a)
 {
     unsigned long stack;
 
     // Return type:
     if ((type[0]->t & VT_BTYPE) == VT_VOID)
-        a[0] = -1;
+        a[0] = PCS_ALLOC_MAKE_VOID();
     else {
-        arm64_pcs_aux(1, type, a);
-        assert(a[0] == 0 || a[0] == 1 || a[0] == 16);
+        arm64_pcs_aux(1, -1, type, a);
+        assert((a[0].type == PCS_IREG && a[0].value == 0) ||
+               (a[0].type == PCS_FREG && a[0].value == 0 && !a[0].indirect));
     }
 
     // Argument types:
-    stack = arm64_pcs_aux(n, type + 1, a + 1);
+    stack = arm64_pcs_aux(n, nb_fixed, type + 1, a + 1);
 
     if (0) {
         int i;
@@ -805,17 +853,17 @@ static unsigned long arm64_pcs(int n, CType **type, unsigned long *a)
                 printf("arm64_pcs return: ");
             else
                 printf("arm64_pcs arg %d: ", i);
-            if (a[i] == (unsigned long)-1)
+            if (a[i].type == PCS_VOID)
                 printf("void\n");
-            else if (a[i] == 1 && !i)
+            else if (a[i].indirect && !i)
                 printf("X8 pointer\n");
-            else if (a[i] < 16)
-                printf("X%lu%s\n", a[i] / 2, a[i] & 1 ? " pointer" : "");
-            else if (a[i] < 32)
-                printf("V%lu\n", a[i] / 2 - 8);
+            else if (a[i].type == PCS_IREG)
+                printf("X%lu%s\n", a[i].value, a[i].indirect ? " pointer" : "");
+            else if (a[i].type == PCS_FREG)
+                printf("V%lu\n", a[i].value);
             else
                 printf("stack %lu%s\n",
-                       (a[i] - 32) & ~1, a[i] & 1 ? " pointer" : "");
+                       a[i].value, a[i].indirect ? " pointer" : "");
         }
     }
 
@@ -824,13 +872,28 @@ static unsigned long arm64_pcs(int n, CType **type, unsigned long *a)
 
 ST_FUNC void gfunc_call(int nb_args)
 {
+    Sym *return_sym;
+    int nb_fixed;
     CType *return_type;
     CType **t;
-    unsigned long *a, *a1;
+    PCSAlloc *a;
+    unsigned long *a1;
     unsigned long stack;
     int i;
 
-    return_type = &vtop[-nb_args].type.ref->type;
+    return_sym = vtop[-nb_args].type.ref;
+
+    if (return_sym->f.func_type == FUNC_ELLIPSIS) {
+        Sym *cur;
+
+        nb_fixed = 0;
+        for (cur = return_sym->next; cur; cur = cur->next)
+            nb_fixed++;
+    } else {
+        nb_fixed = -1;
+    }
+
+    return_type = &return_sym->type;
     if ((return_type->t & VT_BTYPE) == VT_STRUCT)
         --nb_args;
 
@@ -842,11 +905,11 @@ ST_FUNC void gfunc_call(int nb_args)
     for (i = 0; i < nb_args; i++)
         t[nb_args - i] = &vtop[-i].type;
 
-    stack = arm64_pcs(nb_args, t, a);
+    stack = arm64_pcs(nb_args, nb_fixed, t, a);
 
     // Allocate space for structs replaced by pointer:
     for (i = nb_args; i; i--)
-        if (a[i] & 1) {
+        if (a[i].indirect) {
             SValue *arg = &vtop[i - nb_args];
             int align, size = type_size(&arg->type, &align);
             assert((arg->type.t & VT_BTYPE) == VT_STRUCT);
@@ -865,25 +928,25 @@ ST_FUNC void gfunc_call(int nb_args)
     for (i = nb_args; i; i--) {
         vpushv(vtop - nb_args + i);
 
-        if (a[i] & 1) {
+        if (a[i].indirect) {
             // struct replaced by pointer
             int r = get_reg(RC_INT);
             arm64_spoff(intr(r), a1[i]);
             vset(&vtop->type, r | VT_LVAL, 0);
             vswap();
             vstore();
-            if (a[i] >= 32) {
+            if (a[i].type == PCS_STACK) {
                 // pointer on stack
                 r = get_reg(RC_INT);
                 arm64_spoff(intr(r), a1[i]);
-                arm64_strx(3, intr(r), 31, (a[i] - 32) >> 1 << 1);
+                arm64_strx(3, intr(r), 31, a[i].value);
             }
         }
-        else if (a[i] >= 32) {
+        else if (a[i].type == PCS_STACK) {
             // value on stack
             if ((vtop->type.t & VT_BTYPE) == VT_STRUCT) {
                 int r = get_reg(RC_INT);
-                arm64_spoff(intr(r), a[i] - 32);
+                arm64_spoff(intr(r), a[i].value);
                 vset(&vtop->type, r | VT_LVAL, 0);
                 vswap();
                 vstore();
@@ -891,7 +954,7 @@ ST_FUNC void gfunc_call(int nb_args)
             else if (is_float(vtop->type.t)) {
                 gv(RC_FLOAT);
                 arm64_strv(arm64_type_size(vtop[0].type.t),
-                           fltr(vtop[0].r), 31, a[i] - 32);
+                           fltr(vtop[0].r), 31, a[i].value);
             }
             else {
                 gv(RC_INT);
@@ -905,22 +968,22 @@ ST_FUNC void gfunc_call(int nb_args)
 
     // Second pass: assign values to registers
     for (i = nb_args; i; i--, vtop--) {
-        if (a[i] < 16 && !(a[i] & 1)) {
+        if (a[i].type == PCS_IREG && !a[i].indirect) {
             // value in general-purpose registers
             if ((vtop->type.t & VT_BTYPE) == VT_STRUCT) {
                 int align, size = type_size(&vtop->type, &align);
                 vtop->type.t = VT_PTR;
                 gaddrof();
-                gv(RC_R(a[i] / 2));
-                arm64_ldrs(a[i] / 2, size);
+                gv(RC_R(a[i].value));
+                arm64_ldrs(a[i].value, size);
             }
             else
-                gv(RC_R(a[i] / 2));
+                gv(RC_R(a[i].value));
         }
-        else if (a[i] < 16)
+        else if (a[i].type == PCS_IREG)
             // struct replaced by pointer in register
-            arm64_spoff(a[i] / 2, a1[i]);
-        else if (a[i] < 32) {
+            arm64_spoff(a[i].value, a1[i]);
+        else if (a[i].type == PCS_FREG) {
             // value in floating-point registers
             if ((vtop->type.t & VT_BTYPE) == VT_STRUCT) {
                 uint32_t j, sz, n = arm64_hfa(&vtop->type, &sz);
@@ -930,16 +993,16 @@ ST_FUNC void gfunc_call(int nb_args)
                 for (j = 0; j < n; j++)
                     o(0x3d4003c0 |
                       (sz & 16) << 19 | -(sz & 8) << 27 | (sz & 4) << 29 |
-                      (a[i] / 2 - 8 + j) |
+                      (a[i].value + j) |
                       j << 10); // ldr ([sdq])(*),[x30,#(j * sz)]
             }
             else
-                gv(RC_F(a[i] / 2 - 8));
+                gv(RC_F(a[i].value));
         }
     }
 
     if ((return_type->t & VT_BTYPE) == VT_STRUCT) {
-        if (a[0] == 1) {
+        if (a[0].indirect) {
             // indirect return: set x8 and discard the stack value
             gv(RC_R(8));
             --vtop;
@@ -962,11 +1025,11 @@ ST_FUNC void gfunc_call(int nb_args)
             // Promote small integers:
             o(0x13001c00 | (bt == VT_SHORT) << 13 |
               (uint32_t)!!(rt & VT_UNSIGNED) << 30); // [su]xt[bh] w0,w0
-        else if (bt == VT_STRUCT && !(a[0] & 1)) {
+        else if (bt == VT_STRUCT && !a[0].indirect) {
             // A struct was returned in registers, so write it out:
             gv(RC_R(8));
             --vtop;
-            if (a[0] == 0) {
+            if (a[0].type == PCS_IREG) {
                 int align, size = type_size(return_type, &align);
                 assert(size <= 16);
                 if (size > 8)
@@ -975,12 +1038,12 @@ ST_FUNC void gfunc_call(int nb_args)
                     arm64_strx(size > 4 ? 3 : size > 2 ? 2 : size > 1, 0, 8, 0);
 
             }
-            else if (a[0] == 16) {
+            else if (a[0].type == PCS_FREG) {
                 uint32_t j, sz, n = arm64_hfa(return_type, &sz);
                 for (j = 0; j < n; j++)
                     o(0x3d000100 |
                       (sz & 16) << 19 | -(sz & 8) << 27 | (sz & 4) << 29 |
-                      (a[i] / 2 - 8 + j) |
+                      (a[i].value + j) |
                       j << 10); // str ([sdq])(*),[x8,#(j * sz)]
             }
         }
@@ -992,8 +1055,10 @@ ST_FUNC void gfunc_call(int nb_args)
 }
 
 static unsigned long arm64_func_va_list_stack;
+#ifndef __APPLE__
 static int arm64_func_va_list_gr_offs;
 static int arm64_func_va_list_vr_offs;
+#endif
 static int arm64_func_sub_sp_offset;
 
 ST_FUNC void gfunc_prolog(CType *func_type)
@@ -1002,7 +1067,7 @@ ST_FUNC void gfunc_prolog(CType *func_type)
     int i = 0;
     Sym *sym;
     CType **t;
-    unsigned long *a;
+    PCSAlloc *a;
 
     // Why doesn't the caller (gen_function) set func_vt?
     func_vt = func_type->ref->type;
@@ -1016,7 +1081,7 @@ ST_FUNC void gfunc_prolog(CType *func_type)
     for (sym = func_type->ref; sym; sym = sym->next)
         t[i++] = &sym->type;
 
-    arm64_func_va_list_stack = arm64_pcs(n - 1, t, a);
+    arm64_func_va_list_stack = arm64_pcs(n - 1, -1, t, a);
 
     o(0xa9b27bfd); // stp x29,x30,[sp,#-224]!
     o(0xad0087e0); // stp q0,q1,[sp,#16]
@@ -1029,35 +1094,39 @@ ST_FUNC void gfunc_prolog(CType *func_type)
     o(0xa90c17e4); // stp x4,x5,[sp,#192]
     o(0xa90d1fe6); // stp x6,x7,[sp,#208]
 
+#ifndef __APPLE__
     arm64_func_va_list_gr_offs = -64;
     arm64_func_va_list_vr_offs = -128;
+#endif
 
     for (i = 1, sym = func_type->ref->next; sym; i++, sym = sym->next) {
-        int off = (a[i] < 16 ? 160 + a[i] / 2 * 8 :
-                   a[i] < 32 ? 16 + (a[i] - 16) / 2 * 16 :
-                   224 + ((a[i] - 32) >> 1 << 1));
+        int off = (a[i].type == PCS_IREG ? 160 + a[i].value * 8 :
+                   a[i].type == PCS_FREG ? 16 + a[i].value * 16 :
+                   224 + a[i].value);
         sym_push(sym->v & ~SYM_FIELD, &sym->type,
-                 (a[i] & 1 ? VT_LLOCAL : VT_LOCAL) | lvalue_type(sym->type.t),
+                 (a[i].indirect ? VT_LLOCAL : VT_LOCAL) | lvalue_type(sym->type.t),
                  off);
 
-        if (a[i] < 16) {
+#ifndef __APPLE__
+        if (a[i].type == PCS_IREG) {
             int align, size = type_size(&sym->type, &align);
-            arm64_func_va_list_gr_offs = (a[i] / 2 - 7 +
-                                          (!(a[i] & 1) && size > 8)) * 8;
+            arm64_func_va_list_gr_offs = (a[i].value - 7 +
+                                          (!a[i].indirect && size > 8)) * 8;
         }
-        else if (a[i] < 32) {
+        else if (a[i].type == PCS_FREG) {
             uint32_t hfa = arm64_hfa(&sym->type, 0);
-            arm64_func_va_list_vr_offs = (a[i] / 2 - 16 +
+            arm64_func_va_list_vr_offs = (a[i].value - 8 +
                                           (hfa ? hfa : 1)) * 16;
         }
+#endif
 
         // HFAs of float and double need to be written differently:
-        if (16 <= a[i] && a[i] < 32 && (sym->type.t & VT_BTYPE) == VT_STRUCT) {
+        if (a[i].type == PCS_FREG && (sym->type.t & VT_BTYPE) == VT_STRUCT) {
             uint32_t j, sz, k = arm64_hfa(&sym->type, &sz);
             if (sz < 16)
                 for (j = 0; j < k; j++) {
                     o(0x3d0003e0 | -(sz & 8) << 27 | (sz & 4) << 29 |
-                      ((a[i] - 16) / 2 + j) | (off / sz + j) << 10);
+                      (a[i].value + j) | (off / sz + j) << 10);
                     // str ([sdq])(*),[sp,#(j * sz)]
                 }
         }
@@ -1090,6 +1159,7 @@ ST_FUNC void gen_va_start(void)
         o(0x910383be); // add x30,x29,#224
     o(0xf900001e | r << 5); // str x30,[x(r)]
 
+#ifndef __APPLE__
     if (arm64_func_va_list_gr_offs) {
         if (arm64_func_va_list_stack)
             o(0x910383be); // add x30,x29,#224
@@ -1106,6 +1176,7 @@ ST_FUNC void gen_va_start(void)
 
     arm64_movimm(30, arm64_func_va_list_vr_offs);
     o(0xb9001c1e | r << 5); // str w30,[x(r),#28]
+#endif
 
     --vtop;
 }
@@ -1129,6 +1200,7 @@ ST_FUNC void gen_va_arg(CType *t)
 
     if (!hfa) {
         uint32_t n = size > 16 ? 8 : (size + 7) & -8;
+#ifndef __APPLE__
         o(0xb940181e | r0 << 5); // ldr w30,[x(r0),#24] // __gr_offs
         if (align == 16) {
             assert(0); // this path untested but needed for __uint128_t
@@ -1137,23 +1209,28 @@ ST_FUNC void gen_va_arg(CType *t)
         }
         o(0x310003c0 | r1 | n << 10); // adds w(r1),w30,#(n)
         o(0x540000ad); // b.le .+20
+#endif
         o(0xf9400000 | r1 | r0 << 5); // ldr x(r1),[x(r0)] // __stack
         o(0x9100001e | r1 << 5 | n << 10); // add x30,x(r1),#(n)
         o(0xf900001e | r0 << 5); // str x30,[x(r0)] // __stack
+#ifndef __APPLE__
         o(0x14000004); // b .+16
         o(0xb9001800 | r1 | r0 << 5); // str w(r1),[x(r0),#24] // __gr_offs
         o(0xf9400400 | r1 | r0 << 5); // ldr x(r1),[x(r0),#8] // __gr_top
         o(0x8b3ec000 | r1 | r1 << 5); // add x(r1),x(r1),w30,sxtw
+#endif
         if (size > 16)
             o(0xf9400000 | r1 | r1 << 5); // ldr x(r1),[x(r1)]
     }
     else {
-        uint32_t rsz = hfa << 4;
         uint32_t ssz = (size + 7) & -(uint32_t)8;
+#ifndef __APPLE__
+        uint32_t rsz = hfa << 4;
         uint32_t b1, b2;
         o(0xb9401c1e | r0 << 5); // ldr w30,[x(r0),#28] // __vr_offs
         o(0x310003c0 | r1 | rsz << 10); // adds w(r1),w30,#(rsz)
         b1 = ind; o(0x5400000d); // b.le lab1
+#endif
         o(0xf9400000 | r1 | r0 << 5); // ldr x(r1),[x(r0)] // __stack
         if (fsize == 16) {
             o(0x91003c00 | r1 | r1 << 5); // add x(r1),x(r1),#15
@@ -1161,6 +1238,7 @@ ST_FUNC void gen_va_arg(CType *t)
         }
         o(0x9100001e | r1 << 5 | ssz << 10); // add x30,x(r1),#(ssz)
         o(0xf900001e | r0 << 5); // str x30,[x(r0)] // __stack
+#ifndef __APPLE__
         b2 = ind; o(0x14000000); // b lab2
         // lab1:
         write32le(cur_text_section->data + b1, 0x5400000d | (ind - b1) << 3);
@@ -1184,6 +1262,7 @@ ST_FUNC void gen_va_arg(CType *t)
         }
         // lab2:
         write32le(cur_text_section->data + b2, 0x14000000 | (ind - b2) >> 2);
+#endif
     }
 }
 
@@ -1196,13 +1275,13 @@ ST_FUNC int gfunc_sret(CType *vt, int variadic, CType *ret,
 ST_FUNC void gfunc_return(CType *func_type)
 {
     CType *t = func_type;
-    unsigned long a;
+    PCSAlloc a;
 
-    arm64_pcs(0, &t, &a);
-    switch (a) {
-    case -1:
-        break;
-    case 0:
+    arm64_pcs(0, -1, &t, &a);
+
+    if (a.type == PCS_VOID) {
+    }
+    else if (a.type == PCS_IREG && !a.indirect) {
         if ((func_type->t & VT_BTYPE) == VT_STRUCT) {
             int align, size = type_size(func_type, &align);
             gaddrof();
@@ -1211,17 +1290,16 @@ ST_FUNC void gfunc_return(CType *func_type)
         }
         else
             gv(RC_IRET);
-        break;
-    case 1: {
+    }
+    else if (a.indirect) {
         CType type = *func_type;
         mk_pointer(&type);
         vset(&type, VT_LOCAL | VT_LVAL, func_vc);
         indir();
         vswap();
         vstore();
-        break;
     }
-    case 16:
+    else if (a.type == PCS_FREG) {
         if ((func_type->t & VT_BTYPE) == VT_STRUCT) {
           uint32_t j, sz, n = arm64_hfa(&vtop->type, &sz);
           gaddrof();
@@ -1233,8 +1311,8 @@ ST_FUNC void gfunc_return(CType *func_type)
         }
         else
             gv(RC_FRET);
-        break;
-    default:
+    }
+    else {
       assert(0);
     }
     vtop--;
diff --git a/include/stdarg.h b/include/stdarg.h
index 00c5585..b6ba9d6 100644
--- a/include/stdarg.h
+++ b/include/stdarg.h
@@ -51,6 +51,9 @@ typedef char *va_list;
 #define va_end(ap) ((void)0)
 
 #elif defined(__aarch64__)
+#if defined(__APPLE__)
+typedef char *va_list;
+#else
 typedef struct {
     void *__stack;
     void *__gr_top;
@@ -58,6 +61,7 @@ typedef struct {
     int   __gr_offs;
     int   __vr_offs;
 } va_list;
+#endif
 #define va_start(ap, last) __va_start(ap, last)
 #define va_arg(ap, type) __va_arg(ap, type)
 #define va_end(ap) ((void)0)
