comparison test/suite_aggrs/mk-cases.lua @ 482:0f3b6898078d

suite_aggrs (still ahead of checked in version of dyncall, sorry): - renaming struct -> aggr - added knobs to: * control struct packing * whether to test immutability of aggr-by-val params * how to copy aggrs (field by field or via = op (which might do a memcpy and thus copy padding garbage, also)) - some macros to reduce file sizes of generated cases - setting default misalignment to 1
author Tassilo Philipp
date Wed, 16 Mar 2022 16:27:50 +0100
parents 653b65580cb4
children
comparison
equal deleted inserted replaced
481:0fc22b5feac7 482:0f3b6898078d
1 require"config"
1 require"math" 2 require"math"
2 local max = math.max 3 local max_numargs = 0
3 local maxargs = 0
4 4
5 local aggrs = { } 5 local aggrs = { }
6 local seen_aggrs = { } 6 local seen_aggrs = { }
7 7
8 8
64 end 64 end
65 65
66 -- no nesting (= actual func args), generate case code 66 -- no nesting (= actual func args), generate case code
67 if n_nest == 0 then 67 if n_nest == 0 then
68 h[#h+1] = canon_type(ch) 68 h[#h+1] = canon_type(ch)
69 -- aggregate types (more than one char) need copying via a func 69 -- aggregate types have more than one
70 if #h[#h] > 1 then 70 if #h[#h] > 1 then
71 t[#t+1] = 'f_cp'..h[#h]:sub(8)..'(V_a['..pos.."],&"..name..");" 71 if aggrcpsimple then
72 t[#t+1] = '*('..h[#h]..'*)V_a['..pos.."]="..name..";"
73 else
74 t[#t+1] = 'f_cp'..h[#h]:sub(8)..'(V_a['..pos.."],&"..name..");"
75 end
76 if aggrmutabletest then
77 t[#t] = t[#t]..'memset(&'..name..',0,sizeof('..name..'));'
78 end
72 else 79 else
73 t[#t+1] = "V_"..ch.."["..pos.."]="..name..";" 80 t[#t+1] = "V_"..ch.."["..pos.."]="..name..";"
74 end 81 end
75 82
76 -- is return type or func arg? 83 -- is return type or func arg?
85 92
86 pos = pos + 1 93 pos = pos + 1
87 end 94 end
88 end 95 end
89 end 96 end
90 maxargs = max(maxargs, pos-1) 97 max_numargs = math.max(max_numargs, pos-1)
91 h[#h] = "){" 98 h[#h] = "){"
92 if #h[6] == 1 then 99 if #h[6] == 1 then
93 t[#t+1] = "ret_"..h[6].."("..(pos-1)..")}\n" 100 t[#t+1] = "ret_"..h[6].."("..(pos-1)..")}\n"
94 else 101 else
95 t[#t+1] = "ret_a("..(pos-1)..","..h[6]..")}\n" 102 t[#t+1] = "ret_a("..(pos-1)..","..h[6]..")}\n"
150 agg_sigs [#agg_sigs + 1] = k 157 agg_sigs [#agg_sigs + 1] = k
151 agg_names[#agg_names + 1] = at:sub(8) 158 agg_names[#agg_names + 1] = at:sub(8)
152 159
153 -- aggregate def 160 -- aggregate def
154 io.write('/* '..k..' */\n') 161 io.write('/* '..k..' */\n')
162 if aggrpacking ~= 0 then
163 local pack = aggrpacking
164 if pack < 0 then
165 pack = math.floor(math.pow(2,math.floor(math.log(math.random(math.abs(pack)),2))))
166 end
167 io.write('#pragma pack(push,'..pack..')\n')
168 end
169
155 io.write(at..' { ') 170 io.write(at..' { ')
156 for i = 1, #am, 2 do 171 for i = 1, #am, 2 do
157 io.write(am[i]..' '..am[i+1]..'; ') 172 io.write(am[i]..' '..am[i+1]..'; ')
158 end 173 end
159 io.write("};\n") 174 io.write("};\n")
175
176 if aggrpacking ~= 0 then
177 io.write('#pragma pack(pop)\n')
178 end
160 179
161 -- aggregate cp and cmp funcs 180 -- aggregate cp and cmp funcs
162 s = { 181 s = {
163 'void f_cp'..at:sub(8)..'('..at..' *x, const '..at..' *y) { ', 182 'void f_cp'..at:sub(8)..'('..at..' *x, const '..at..' *y) { ',
164 'int f_cmp'..at:sub(8)..'(const '..at..' *x, const '..at..' *y) { return ' 183 'int f_cmp'..at:sub(8)..'(const '..at..' *x, const '..at..' *y) { return '
165 } 184 }
166 o = { '=', '==', 'f_cp', 'f_cmp', '; ', ' && ', '', '1' } 185 o = { '=', '==', 'f_cp', 'f_cmp', '; ', ' && ', '', '1' }
167 for t = 1, 2 do 186 for t = 1, 2 do
168 io.write(s[t]) 187 if t ~= 1 or aggrcpsimple == false then
169 local b = {} 188 io.write(s[t])
170 for i = 1, #am, 2 do 189 local b = {}
171 local m = split_array_decl(am[i+1]) 190 for i = 1, #am, 2 do
172 local fmt = '' 191 local m = split_array_decl(am[i+1])
173 if m[2] ~= nil then -- need array suffixes? 192 local fmt = ''
174 fmt = '[%d]' 193 if m[2] ~= nil then -- need array suffixes?
175 else 194 fmt = '[%d]'
176 m[2] = 1
177 end
178
179 for j = 1, m[2] do
180 name = m[1]..string.format(fmt, j-1)
181 if string.match(am[i], ' ') then -- aggregate canonical types contain at least one space
182 b[#b+1] = o[t+2]..am[i]:sub(8)..'(&x->'..name..', &y->'..name..')'
183 else 195 else
184 b[#b+1] = 'x->'..name..' '..o[t]..' y->'..name 196 m[2] = 1
185 end 197 end
186 end 198
187 end 199 for j = 1, m[2] do
188 if #b == 0 then -- to handle empty aggregates 200 name = m[1]..string.format(fmt, j-1)
189 b[1] = o[t+6] 201 if string.match(am[i], ' ') then -- aggregate canonical types contain at least one space
190 end 202 b[#b+1] = o[t+2]..am[i]:sub(8)..'(&x->'..name..', &y->'..name..')'
191 io.write(table.concat(b,o[t+4]).."; };\n") 203 else
204 b[#b+1] = 'x->'..name..' '..o[t]..' y->'..name
205 end
206 end
207 end
208 if #b == 0 then -- to handle empty aggregates
209 b[1] = o[t+6]
210 end
211 io.write(table.concat(b,o[t+4]).."; };\n")
212 end
192 end 213 end
193 214
194 -- convenient dcnewstruct helper funcs 215 -- convenient dcnewstruct helper funcs
195 io.write('DCstruct* f_touchdcst'..at:sub(8)..'() {\n\tstatic DCstruct* at = NULL;\n\tif(!at) {\n\t\tat = dcNewStruct('..(#am>>1)..', sizeof('..at..'), DC_TRUE);\n\t\t') 216 io.write('DCaggr* f_touchdcst'..at:sub(8)..'() {\n\tstatic DCaggr* at = NULL;\n\tif(!at) {\n\t\tat = dcNewAggr('..(#am>>1)..', sizeof('..at..'), DC_TRUE);\n\t\t')
196 for i = 1, #am, 2 do 217 for i = 1, #am, 2 do
197 local m = split_array_decl(am[i+1]) 218 local m = split_array_decl(am[i+1])
198 if m[2] == nil then -- need array suffixes? 219 if m[2] == nil then -- need array suffixes?
199 m[2] = 1 220 m[2] = 1
200 end 221 end
201 if string.match(am[i], ' ') then -- aggregate canonical types contain at least one space 222 if string.match(am[i], ' ') then -- aggregate canonical types contain at least one space
202 io.write('dcStructField(at, DC_SIGCHAR_STRUCT, offsetof('..at..', '..m[1]..'), '..m[2]..', f_touchdcst'..am[i]:sub(8)..'());\n\t\t') 223 --io.write('dcAggrField(at, DC_SIGCHAR_AGGREGATE, offsetof('..at..', '..m[1]..'), '..m[2]..', f_touchdcst'..am[i]:sub(8)..'());\n\t\t')
224 io.write("AFa("..at..','..m[1]..','..m[2]..','..am[i]:sub(8)..')\n\t\t')
203 else 225 else
204 io.write("dcStructField(at, '"..am[i].."', offsetof("..at..', '..m[1]..'), '..m[2]..');\n\t\t') 226 --io.write("dcAggrField(at, '"..am[i].."', offsetof("..at..', '..m[1]..'), '..m[2]..');\n\t\t')
205 end 227 io.write("AF('"..am[i].."',"..at..','..m[1]..','..m[2]..')\n\t\t')
206 end 228 end
207 io.write("dcCloseStruct(at);\n\t}\n\treturn at;\n};\n") 229 end
230 io.write("dcCloseAggr(at);\n\t}\n\treturn at;\n};\n")
208 end 231 end
209 232
210 -- make table.concat work 233 -- make table.concat work
211 if #agg_names > 0 then 234 if #agg_names > 0 then
212 table.insert(agg_names, 1, '') 235 table.insert(agg_names, 1, '')
217 io.write(mksigtab(sigtab)) 240 io.write(mksigtab(sigtab))
218 io.write('const char* G_agg_sigs[] = {\n\t"'..table.concat(agg_sigs, '",\n\t"')..'"\n};\n') 241 io.write('const char* G_agg_sigs[] = {\n\t"'..table.concat(agg_sigs, '",\n\t"')..'"\n};\n')
219 io.write('int G_agg_sizes[] = {\n\t'..table.concat(agg_sizes, ',\n\t')..'\n};\n') 242 io.write('int G_agg_sizes[] = {\n\t'..table.concat(agg_sizes, ',\n\t')..'\n};\n')
220 io.write('funptr G_agg_touchdcstfuncs[] = {'..string.sub(table.concat(agg_names, ',\n\t(funptr)&f_touchdcst'),2)..'\n};\n') 243 io.write('funptr G_agg_touchdcstfuncs[] = {'..string.sub(table.concat(agg_names, ',\n\t(funptr)&f_touchdcst'),2)..'\n};\n')
221 io.write('funptr G_agg_cmpfuncs[] = {'..string.sub(table.concat(agg_names, ',\n\t(funptr)&f_cmp'),2)..'\n};\n') 244 io.write('funptr G_agg_cmpfuncs[] = {'..string.sub(table.concat(agg_names, ',\n\t(funptr)&f_cmp'),2)..'\n};\n')
222 io.write("int G_maxargs = "..maxargs..";\n") 245 io.write("int G_maxargs = "..max_numargs..";\n")
223 end 246 end
224 247
248 math.randomseed(seed)
225 mkall() 249 mkall()
226 250