Mercurial > pub > dyncall > dyncall
comparison dyncall/dyncall_aggregate_x64.c @ 542:a73a5cd50c19
- fix passing aggregate-by-val on x64/sysv: subaggr classification for
aggr *arrays* was wrong (was problematic when there ware exactly 2 8bytes to
be classified, potentially be passed via registers)
author | Tassilo Philipp |
---|---|
date | Mon, 02 May 2022 15:32:41 +0200 |
parents | 71c884e610f0 |
children | ba70fb631bea |
comparison
equal
deleted
inserted
replaced
541:3c715848d7fd | 542:a73a5cd50c19 |
---|---|
32 /* helper - long long mask with each byte being X */ | 32 /* helper - long long mask with each byte being X */ |
33 #define LLBYTE(X) ((X)&0xFFULL) | 33 #define LLBYTE(X) ((X)&0xFFULL) |
34 #define SYSVC_CHECK_ALL_CLASSES(X) ((LLBYTE(X)<<56)|(LLBYTE(X)<<48)|(LLBYTE(X)<<40)|(LLBYTE(X)<<32)|(LLBYTE(X)<<24)|(LLBYTE(X)<<16)|(LLBYTE(X)<<8)|LLBYTE(X)) | 34 #define SYSVC_CHECK_ALL_CLASSES(X) ((LLBYTE(X)<<56)|(LLBYTE(X)<<48)|(LLBYTE(X)<<40)|(LLBYTE(X)<<32)|(LLBYTE(X)<<24)|(LLBYTE(X)<<16)|(LLBYTE(X)<<8)|LLBYTE(X)) |
35 | 35 |
36 | 36 |
37 static DCuchar dc_merge_sysv_classes(DCuchar clz, DCuchar new_class) | |
38 { | |
39 if(clz == SYSVC_NONE) | |
40 return new_class; | |
41 | |
42 if(new_class == SYSVC_NONE) | |
43 return clz; | |
44 | |
45 if(clz == SYSVC_MEMORY || new_class == SYSVC_MEMORY) | |
46 return SYSVC_MEMORY; | |
47 | |
48 if(clz == SYSVC_INTEGER || new_class == SYSVC_INTEGER) | |
49 return SYSVC_INTEGER; | |
50 | |
51 /* @@@AGGR implement when implementing x87 types | |
52 if((clz & (SYSVC_X87|SYSVC_X87UP|SYSVC_COMPLEX_X87)) || (new_class & (SYSVC_X87|SYSVC_X87UP|SYSVC_COMPLEX_X87))) | |
53 return SYSVC_MEMORY;*/ | |
54 | |
55 return SYSVC_SSE; | |
56 } | |
57 | |
58 | |
37 static DCuchar dc_get_sysv_class_for_8byte(const DCaggr *ag, int index, int base_offset) | 59 static DCuchar dc_get_sysv_class_for_8byte(const DCaggr *ag, int index, int base_offset) |
38 { | 60 { |
39 int qword_offset = index * DC_ONE_8BYTE, i; | 61 int qword_offset = index * DC_ONE_8BYTE, i; |
40 DCuchar clz = SYSVC_NONE; | 62 DCuchar clz = SYSVC_NONE; |
41 | 63 |
42 for(i = 0; i < ag->n_fields; i++) { | 64 for(i=0; i<ag->n_fields; ++i) { |
43 const DCfield *f = ag->fields + i; | 65 const DCfield *f = ag->fields + i; |
44 DCsize offset = base_offset + f->offset; | 66 DCsize offset = base_offset + f->offset; |
45 | 67 |
46 /* field outside of qword at index? */ | 68 /* field outside of qword at index? */ |
47 if(offset >= (qword_offset + DC_ONE_8BYTE) || (offset + f->size * f->array_len) <= qword_offset) | 69 if(offset >= (qword_offset + DC_ONE_8BYTE) || (offset + f->size * f->array_len) <= qword_offset) |
68 case DC_SIGCHAR_FLOAT: | 90 case DC_SIGCHAR_FLOAT: |
69 case DC_SIGCHAR_DOUBLE: | 91 case DC_SIGCHAR_DOUBLE: |
70 new_class = SYSVC_SSE; | 92 new_class = SYSVC_SSE; |
71 break; | 93 break; |
72 case DC_SIGCHAR_AGGREGATE: | 94 case DC_SIGCHAR_AGGREGATE: |
73 new_class = dc_get_sysv_class_for_8byte(f->sub_aggr, index, offset); | 95 /* skip empty structs */ |
96 if(f->size) | |
97 { | |
98 /* aggregate arrays need to be checked per element, as an aggregate can be composed of | |
99 * multiple types, potentially split across an 8byte; loop only over parts within 8byte */ | |
100 int j = (qword_offset-offset) / f->size; | |
101 int k = DC_ONE_8BYTE / f->size + j + 1; /* +1 for split array elements at end of 8byte */ | |
102 if(k > f->array_len) | |
103 k = f->array_len; | |
104 | |
105 for(; j<k; ++j) { | |
106 //@@@STRUCT new_class = dc_get_sysv_class_for_8byte(f->sub_aggr, index, offset + f->size*j); | |
107 //@@@STRUCT clz = dc_merge_sysv_classes(clz, new_class); | |
108 new_class = dc_merge_sysv_classes(new_class, dc_get_sysv_class_for_8byte(f->sub_aggr, index, offset + f->size*j)); | |
109 } | |
110 } | |
74 break; | 111 break; |
75 /*case DClongdouble, DCcomplexfloat DCcomplexdouble DCcomplexlongdouble etc... -> x87/x87up/complexx87 classes @@@AGGR implement */ | 112 /*case DClongdouble, DCcomplexfloat DCcomplexdouble DCcomplexlongdouble etc... -> x87/x87up/complexx87 classes @@@AGGR implement */ |
76 } | 113 } |
77 | 114 |
78 if (clz == new_class) | 115 if (clz == new_class) |
79 continue; | 116 continue; |
80 | 117 |
81 if (clz == SYSVC_NONE) | 118 clz = dc_merge_sysv_classes(clz, new_class); |
82 clz = new_class; | |
83 else if (new_class == SYSVC_NONE) | |
84 continue; | |
85 else if (clz == SYSVC_MEMORY || new_class == SYSVC_MEMORY) | |
86 clz = SYSVC_MEMORY; | |
87 else if (clz == SYSVC_INTEGER || new_class == SYSVC_INTEGER) | |
88 clz = SYSVC_INTEGER; | |
89 /* @@@AGGR implement when implementing x87 types | |
90 else if ((clz & (SYSVC_X87|SYSVC_X87UP|SYSVC_COMPLEX_X87)) || (new_class & (SYSVC_X87|SYSVC_X87UP|SYSVC_COMPLEX_X87))) | |
91 clz = SYSVC_MEMORY;*/ | |
92 else | |
93 clz = SYSVC_SSE; | |
94 } | 119 } |
95 | 120 |
96 return clz; | 121 return clz; |
97 } | 122 } |
98 | 123 |