diff options
| author | Mike Pall <mike> | 2025-04-10 22:06:47 +0200 |
|---|---|---|
| committer | Mike Pall <mike> | 2025-04-10 22:06:47 +0200 |
| commit | c262976486e1e007b56380b6a36bfbea5f51d470 (patch) | |
| tree | c4bd4bc2d8e3acea5ce5a15ab24da533d68f11ca /src | |
| parent | e0a7ea8a924d8137e6950b97c3e36f17264f6c79 (diff) | |
| download | luajit-c262976486e1e007b56380b6a36bfbea5f51d470.tar.gz luajit-c262976486e1e007b56380b6a36bfbea5f51d470.tar.bz2 luajit-c262976486e1e007b56380b6a36bfbea5f51d470.zip | |
ARM64: Fix pass-by-value struct calling conventions.
Reported by AnthonyK213. #1357
Diffstat (limited to 'src')
| -rw-r--r-- | src/lj_ccall.c | 18 |
1 files changed, 13 insertions, 5 deletions
diff --git a/src/lj_ccall.c b/src/lj_ccall.c index ae69cd28..f003d756 100644 --- a/src/lj_ccall.c +++ b/src/lj_ccall.c | |||
| @@ -781,17 +781,24 @@ static unsigned int ccall_classify_struct(CTState *cts, CType *ct) | |||
| 781 | { | 781 | { |
| 782 | CTSize sz = ct->size; | 782 | CTSize sz = ct->size; |
| 783 | unsigned int r = 0, n = 0, isu = (ct->info & CTF_UNION); | 783 | unsigned int r = 0, n = 0, isu = (ct->info & CTF_UNION); |
| 784 | while (ct->sib) { | 784 | while (ct->sib && n <= 4) { |
| 785 | unsigned int m = 1; | ||
| 785 | CType *sct; | 786 | CType *sct; |
| 786 | ct = ctype_get(cts, ct->sib); | 787 | ct = ctype_get(cts, ct->sib); |
| 787 | if (ctype_isfield(ct->info)) { | 788 | if (ctype_isfield(ct->info)) { |
| 788 | sct = ctype_rawchild(cts, ct); | 789 | sct = ctype_rawchild(cts, ct); |
| 790 | if (ctype_isarray(sct->info)) { | ||
| 791 | CType *cct = ctype_rawchild(cts, sct); | ||
| 792 | if (!cct->size) continue; | ||
| 793 | m = sct->size / cct->size; | ||
| 794 | sct = cct; | ||
| 795 | } | ||
| 789 | if (ctype_isfp(sct->info)) { | 796 | if (ctype_isfp(sct->info)) { |
| 790 | r |= sct->size; | 797 | r |= sct->size; |
| 791 | if (!isu) n++; else if (n == 0) n = 1; | 798 | if (!isu) n += m; else if (n < m) n = m; |
| 792 | } else if (ctype_iscomplex(sct->info)) { | 799 | } else if (ctype_iscomplex(sct->info)) { |
| 793 | r |= (sct->size >> 1); | 800 | r |= (sct->size >> 1); |
| 794 | if (!isu) n += 2; else if (n < 2) n = 2; | 801 | if (!isu) n += 2*m; else if (n < 2*m) n = 2*m; |
| 795 | } else if (ctype_isstruct(sct->info)) { | 802 | } else if (ctype_isstruct(sct->info)) { |
| 796 | goto substruct; | 803 | goto substruct; |
| 797 | } else { | 804 | } else { |
| @@ -803,10 +810,11 @@ static unsigned int ccall_classify_struct(CTState *cts, CType *ct) | |||
| 803 | sct = ctype_rawchild(cts, ct); | 810 | sct = ctype_rawchild(cts, ct); |
| 804 | substruct: | 811 | substruct: |
| 805 | if (sct->size > 0) { | 812 | if (sct->size > 0) { |
| 806 | unsigned int s = ccall_classify_struct(cts, sct); | 813 | unsigned int s = ccall_classify_struct(cts, sct), sn; |
| 807 | if (s <= 1) goto noth; | 814 | if (s <= 1) goto noth; |
| 808 | r |= (s & 255); | 815 | r |= (s & 255); |
| 809 | if (!isu) n += (s >> 8); else if (n < (s >>8)) n = (s >> 8); | 816 | sn = (s >> 8) * m; |
| 817 | if (!isu) n += sn; else if (n < sn) n = sn; | ||
| 810 | } | 818 | } |
| 811 | } | 819 | } |
| 812 | } | 820 | } |
