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