[clang-format] Fix a bug in aligning comments above PPDirective (#72791)
[llvm-project.git] / clang / utils / ABITest / ABITestGen.py
blob119b3299ffa60fde42d249b7e28c51f57cbec0c0
1 #!/usr/bin/env python
3 from __future__ import absolute_import, division, print_function
4 from pprint import pprint
5 import random, atexit, time
6 from random import randrange
7 import re
9 from Enumeration import *
10 from TypeGen import *
12 ####
15 class TypePrinter(object):
16 def __init__(
17 self,
18 output,
19 outputHeader=None,
20 outputTests=None,
21 outputDriver=None,
22 headerName=None,
23 info=None,
25 self.output = output
26 self.outputHeader = outputHeader
27 self.outputTests = outputTests
28 self.outputDriver = outputDriver
29 self.writeBody = outputHeader or outputTests or outputDriver
30 self.types = {}
31 self.testValues = {}
32 self.testReturnValues = {}
33 self.layoutTests = []
34 self.declarations = set()
36 if info:
37 for f in (
38 self.output,
39 self.outputHeader,
40 self.outputTests,
41 self.outputDriver,
43 if f:
44 print(info, file=f)
46 if self.writeBody:
47 print("#include <stdio.h>\n", file=self.output)
48 if self.outputTests:
49 print("#include <stdio.h>", file=self.outputTests)
50 print("#include <string.h>", file=self.outputTests)
51 print("#include <assert.h>\n", file=self.outputTests)
53 if headerName:
54 for f in (self.output, self.outputTests, self.outputDriver):
55 if f is not None:
56 print('#include "%s"\n' % (headerName,), file=f)
58 if self.outputDriver:
59 print("#include <stdio.h>", file=self.outputDriver)
60 print("#include <stdlib.h>\n", file=self.outputDriver)
61 print("int main(int argc, char **argv) {", file=self.outputDriver)
62 print(" int index = -1;", file=self.outputDriver)
63 print(" if (argc > 1) index = atoi(argv[1]);", file=self.outputDriver)
65 def finish(self):
66 if self.layoutTests:
67 print("int main(int argc, char **argv) {", file=self.output)
68 print(" int index = -1;", file=self.output)
69 print(" if (argc > 1) index = atoi(argv[1]);", file=self.output)
70 for i, f in self.layoutTests:
71 print(" if (index == -1 || index == %d)" % i, file=self.output)
72 print(" %s();" % f, file=self.output)
73 print(" return 0;", file=self.output)
74 print("}", file=self.output)
76 if self.outputDriver:
77 print(' printf("DONE\\n");', file=self.outputDriver)
78 print(" return 0;", file=self.outputDriver)
79 print("}", file=self.outputDriver)
81 def addDeclaration(self, decl):
82 if decl in self.declarations:
83 return False
85 self.declarations.add(decl)
86 if self.outputHeader:
87 print(decl, file=self.outputHeader)
88 else:
89 print(decl, file=self.output)
90 if self.outputTests:
91 print(decl, file=self.outputTests)
92 return True
94 def getTypeName(self, T):
95 name = self.types.get(T)
96 if name is None:
97 # Reserve slot
98 self.types[T] = None
99 self.types[T] = name = T.getTypeName(self)
100 return name
102 def writeLayoutTest(self, i, ty):
103 tyName = self.getTypeName(ty)
104 tyNameClean = tyName.replace(" ", "_").replace("*", "star")
105 fnName = "test_%s" % tyNameClean
107 print("void %s(void) {" % fnName, file=self.output)
108 self.printSizeOfType(" %s" % fnName, tyName, ty, self.output)
109 self.printAlignOfType(" %s" % fnName, tyName, ty, self.output)
110 self.printOffsetsOfType(" %s" % fnName, tyName, ty, self.output)
111 print("}", file=self.output)
112 print(file=self.output)
114 self.layoutTests.append((i, fnName))
116 def writeFunction(self, i, FT):
117 args = ", ".join(
118 ["%s arg%d" % (self.getTypeName(t), i) for i, t in enumerate(FT.argTypes)]
120 if not args:
121 args = "void"
123 if FT.returnType is None:
124 retvalName = None
125 retvalTypeName = "void"
126 else:
127 retvalTypeName = self.getTypeName(FT.returnType)
128 if self.writeBody or self.outputTests:
129 retvalName = self.getTestReturnValue(FT.returnType)
131 fnName = "fn%d" % (FT.index,)
132 if self.outputHeader:
133 print("%s %s(%s);" % (retvalTypeName, fnName, args), file=self.outputHeader)
134 elif self.outputTests:
135 print("%s %s(%s);" % (retvalTypeName, fnName, args), file=self.outputTests)
137 print("%s %s(%s)" % (retvalTypeName, fnName, args), end=" ", file=self.output)
138 if self.writeBody:
139 print("{", file=self.output)
141 for i, t in enumerate(FT.argTypes):
142 self.printValueOfType(" %s" % fnName, "arg%d" % i, t)
144 if retvalName is not None:
145 print(" return %s;" % (retvalName,), file=self.output)
146 print("}", file=self.output)
147 else:
148 print("{}", file=self.output)
149 print(file=self.output)
151 if self.outputDriver:
152 print(" if (index == -1 || index == %d) {" % i, file=self.outputDriver)
153 print(" extern void test_%s(void);" % fnName, file=self.outputDriver)
154 print(" test_%s();" % fnName, file=self.outputDriver)
155 print(" }", file=self.outputDriver)
157 if self.outputTests:
158 if self.outputHeader:
159 print("void test_%s(void);" % (fnName,), file=self.outputHeader)
161 if retvalName is None:
162 retvalTests = None
163 else:
164 retvalTests = self.getTestValuesArray(FT.returnType)
165 tests = [self.getTestValuesArray(ty) for ty in FT.argTypes]
166 print("void test_%s(void) {" % (fnName,), file=self.outputTests)
168 if retvalTests is not None:
169 print(
170 ' printf("%s: testing return.\\n");' % (fnName,),
171 file=self.outputTests,
173 print(
174 " for (int i=0; i<%d; ++i) {" % (retvalTests[1],),
175 file=self.outputTests,
177 args = ", ".join(["%s[%d]" % (t, randrange(l)) for t, l in tests])
178 print(" %s RV;" % (retvalTypeName,), file=self.outputTests)
179 print(
180 " %s = %s[i];" % (retvalName, retvalTests[0]),
181 file=self.outputTests,
183 print(" RV = %s(%s);" % (fnName, args), file=self.outputTests)
184 self.printValueOfType(
185 " %s_RV" % fnName,
186 "RV",
187 FT.returnType,
188 output=self.outputTests,
189 indent=4,
191 self.checkTypeValues(
192 "RV",
193 "%s[i]" % retvalTests[0],
194 FT.returnType,
195 output=self.outputTests,
196 indent=4,
198 print(" }", file=self.outputTests)
200 if tests:
201 print(
202 ' printf("%s: testing arguments.\\n");' % (fnName,),
203 file=self.outputTests,
205 for i, (array, length) in enumerate(tests):
206 for j in range(length):
207 args = ["%s[%d]" % (t, randrange(l)) for t, l in tests]
208 args[i] = "%s[%d]" % (array, j)
209 print(
210 " %s(%s);"
212 fnName,
213 ", ".join(args),
215 file=self.outputTests,
217 print("}", file=self.outputTests)
219 def getTestReturnValue(self, type):
220 typeName = self.getTypeName(type)
221 info = self.testReturnValues.get(typeName)
222 if info is None:
223 name = "%s_retval" % (typeName.replace(" ", "_").replace("*", "star"),)
224 print("%s %s;" % (typeName, name), file=self.output)
225 if self.outputHeader:
226 print("extern %s %s;" % (typeName, name), file=self.outputHeader)
227 elif self.outputTests:
228 print("extern %s %s;" % (typeName, name), file=self.outputTests)
229 info = self.testReturnValues[typeName] = name
230 return info
232 def getTestValuesArray(self, type):
233 typeName = self.getTypeName(type)
234 info = self.testValues.get(typeName)
235 if info is None:
236 name = "%s_values" % (typeName.replace(" ", "_").replace("*", "star"),)
237 print("static %s %s[] = {" % (typeName, name), file=self.outputTests)
238 length = 0
239 for item in self.getTestValues(type):
240 print("\t%s," % (item,), file=self.outputTests)
241 length += 1
242 print("};", file=self.outputTests)
243 info = self.testValues[typeName] = (name, length)
244 return info
246 def getTestValues(self, t):
247 if isinstance(t, BuiltinType):
248 if t.name == "float":
249 for i in ["0.0", "-1.0", "1.0"]:
250 yield i + "f"
251 elif t.name == "double":
252 for i in ["0.0", "-1.0", "1.0"]:
253 yield i
254 elif t.name in ("void *"):
255 yield "(void*) 0"
256 yield "(void*) -1"
257 else:
258 yield "(%s) 0" % (t.name,)
259 yield "(%s) -1" % (t.name,)
260 yield "(%s) 1" % (t.name,)
261 elif isinstance(t, EnumType):
262 for i in range(0, len(t.enumerators)):
263 yield "enum%dval%d_%d" % (t.index, i, t.unique_id)
264 elif isinstance(t, RecordType):
265 nonPadding = [f for f in t.fields if not f.isPaddingBitField()]
267 if not nonPadding:
268 yield "{ }"
269 return
271 # FIXME: Use designated initializers to access non-first
272 # fields of unions.
273 if t.isUnion:
274 for v in self.getTestValues(nonPadding[0]):
275 yield "{ %s }" % v
276 return
278 fieldValues = [list(v) for v in map(self.getTestValues, nonPadding)]
279 for i, values in enumerate(fieldValues):
280 for v in values:
281 elements = [random.choice(fv) for fv in fieldValues]
282 elements[i] = v
283 yield "{ %s }" % (", ".join(elements))
285 elif isinstance(t, ComplexType):
286 for t in self.getTestValues(t.elementType):
287 yield "%s + %s * 1i" % (t, t)
288 elif isinstance(t, ArrayType):
289 values = list(self.getTestValues(t.elementType))
290 if not values:
291 yield "{ }"
292 for i in range(t.numElements):
293 for v in values:
294 elements = [random.choice(values) for i in range(t.numElements)]
295 elements[i] = v
296 yield "{ %s }" % (", ".join(elements))
297 else:
298 raise NotImplementedError('Cannot make tests values of type: "%s"' % (t,))
300 def printSizeOfType(self, prefix, name, t, output=None, indent=2):
301 print(
302 '%*sprintf("%s: sizeof(%s) = %%ld\\n", (long)sizeof(%s));'
303 % (indent, "", prefix, name, name),
304 file=output,
307 def printAlignOfType(self, prefix, name, t, output=None, indent=2):
308 print(
309 '%*sprintf("%s: __alignof__(%s) = %%ld\\n", (long)__alignof__(%s));'
310 % (indent, "", prefix, name, name),
311 file=output,
314 def printOffsetsOfType(self, prefix, name, t, output=None, indent=2):
315 if isinstance(t, RecordType):
316 for i, f in enumerate(t.fields):
317 if f.isBitField():
318 continue
319 fname = "field%d" % i
320 print(
321 '%*sprintf("%s: __builtin_offsetof(%s, %s) = %%ld\\n", (long)__builtin_offsetof(%s, %s));'
322 % (indent, "", prefix, name, fname, name, fname),
323 file=output,
326 def printValueOfType(self, prefix, name, t, output=None, indent=2):
327 if output is None:
328 output = self.output
329 if isinstance(t, BuiltinType):
330 value_expr = name
331 if t.name.split(" ")[-1] == "_Bool":
332 # Hack to work around PR5579.
333 value_expr = "%s ? 2 : 0" % name
335 if t.name.endswith("long long"):
336 code = "lld"
337 elif t.name.endswith("long"):
338 code = "ld"
339 elif t.name.split(" ")[-1] in ("_Bool", "char", "short", "int", "unsigned"):
340 code = "d"
341 elif t.name in ("float", "double"):
342 code = "f"
343 elif t.name == "long double":
344 code = "Lf"
345 else:
346 code = "p"
347 print(
348 '%*sprintf("%s: %s = %%%s\\n", %s);'
349 % (indent, "", prefix, name, code, value_expr),
350 file=output,
352 elif isinstance(t, EnumType):
353 print(
354 '%*sprintf("%s: %s = %%d\\n", %s);' % (indent, "", prefix, name, name),
355 file=output,
357 elif isinstance(t, RecordType):
358 if not t.fields:
359 print(
360 '%*sprintf("%s: %s (empty)\\n");' % (indent, "", prefix, name),
361 file=output,
363 for i, f in enumerate(t.fields):
364 if f.isPaddingBitField():
365 continue
366 fname = "%s.field%d" % (name, i)
367 self.printValueOfType(prefix, fname, f, output=output, indent=indent)
368 elif isinstance(t, ComplexType):
369 self.printValueOfType(
370 prefix,
371 "(__real %s)" % name,
372 t.elementType,
373 output=output,
374 indent=indent,
376 self.printValueOfType(
377 prefix,
378 "(__imag %s)" % name,
379 t.elementType,
380 output=output,
381 indent=indent,
383 elif isinstance(t, ArrayType):
384 for i in range(t.numElements):
385 # Access in this fashion as a hackish way to portably
386 # access vectors.
387 if t.isVector:
388 self.printValueOfType(
389 prefix,
390 "((%s*) &%s)[%d]" % (t.elementType, name, i),
391 t.elementType,
392 output=output,
393 indent=indent,
395 else:
396 self.printValueOfType(
397 prefix,
398 "%s[%d]" % (name, i),
399 t.elementType,
400 output=output,
401 indent=indent,
403 else:
404 raise NotImplementedError('Cannot print value of type: "%s"' % (t,))
406 def checkTypeValues(self, nameLHS, nameRHS, t, output=None, indent=2):
407 prefix = "foo"
408 if output is None:
409 output = self.output
410 if isinstance(t, BuiltinType):
411 print("%*sassert(%s == %s);" % (indent, "", nameLHS, nameRHS), file=output)
412 elif isinstance(t, EnumType):
413 print("%*sassert(%s == %s);" % (indent, "", nameLHS, nameRHS), file=output)
414 elif isinstance(t, RecordType):
415 for i, f in enumerate(t.fields):
416 if f.isPaddingBitField():
417 continue
418 self.checkTypeValues(
419 "%s.field%d" % (nameLHS, i),
420 "%s.field%d" % (nameRHS, i),
422 output=output,
423 indent=indent,
425 if t.isUnion:
426 break
427 elif isinstance(t, ComplexType):
428 self.checkTypeValues(
429 "(__real %s)" % nameLHS,
430 "(__real %s)" % nameRHS,
431 t.elementType,
432 output=output,
433 indent=indent,
435 self.checkTypeValues(
436 "(__imag %s)" % nameLHS,
437 "(__imag %s)" % nameRHS,
438 t.elementType,
439 output=output,
440 indent=indent,
442 elif isinstance(t, ArrayType):
443 for i in range(t.numElements):
444 # Access in this fashion as a hackish way to portably
445 # access vectors.
446 if t.isVector:
447 self.checkTypeValues(
448 "((%s*) &%s)[%d]" % (t.elementType, nameLHS, i),
449 "((%s*) &%s)[%d]" % (t.elementType, nameRHS, i),
450 t.elementType,
451 output=output,
452 indent=indent,
454 else:
455 self.checkTypeValues(
456 "%s[%d]" % (nameLHS, i),
457 "%s[%d]" % (nameRHS, i),
458 t.elementType,
459 output=output,
460 indent=indent,
462 else:
463 raise NotImplementedError('Cannot print value of type: "%s"' % (t,))
466 import sys
469 def main():
470 from optparse import OptionParser, OptionGroup
472 parser = OptionParser("%prog [options] {indices}")
473 parser.add_option(
475 "--mode",
476 dest="mode",
477 help="autogeneration mode (random or linear) [default %default]",
478 type="choice",
479 choices=("random", "linear"),
480 default="linear",
482 parser.add_option(
484 "--count",
485 dest="count",
486 help="autogenerate COUNT functions according to MODE",
487 type=int,
488 default=0,
490 parser.add_option(
492 "--min",
493 dest="minIndex",
494 metavar="N",
495 help="start autogeneration with the Nth function type [default %default]",
496 type=int,
497 default=0,
499 parser.add_option(
501 "--max",
502 dest="maxIndex",
503 metavar="N",
504 help="maximum index for random autogeneration [default %default]",
505 type=int,
506 default=10000000,
508 parser.add_option(
510 "--seed",
511 dest="seed",
512 help="random number generator seed [default %default]",
513 type=int,
514 default=1,
516 parser.add_option(
518 "--use-random-seed",
519 dest="useRandomSeed",
520 help="use random value for initial random number generator seed",
521 action="store_true",
522 default=False,
524 parser.add_option(
526 "--skip",
527 dest="skipTests",
528 help="add a test index to skip",
529 type=int,
530 action="append",
531 default=[],
533 parser.add_option(
534 "-o",
535 "--output",
536 dest="output",
537 metavar="FILE",
538 help="write output to FILE [default %default]",
539 type=str,
540 default="-",
542 parser.add_option(
543 "-O",
544 "--output-header",
545 dest="outputHeader",
546 metavar="FILE",
547 help="write header file for output to FILE [default %default]",
548 type=str,
549 default=None,
551 parser.add_option(
552 "-T",
553 "--output-tests",
554 dest="outputTests",
555 metavar="FILE",
556 help="write function tests to FILE [default %default]",
557 type=str,
558 default=None,
560 parser.add_option(
561 "-D",
562 "--output-driver",
563 dest="outputDriver",
564 metavar="FILE",
565 help="write test driver to FILE [default %default]",
566 type=str,
567 default=None,
569 parser.add_option(
571 "--test-layout",
572 dest="testLayout",
573 metavar="FILE",
574 help="test structure layout",
575 action="store_true",
576 default=False,
579 group = OptionGroup(parser, "Type Enumeration Options")
580 # Builtins - Ints
581 group.add_option(
583 "--no-char",
584 dest="useChar",
585 help="do not generate char types",
586 action="store_false",
587 default=True,
589 group.add_option(
591 "--no-short",
592 dest="useShort",
593 help="do not generate short types",
594 action="store_false",
595 default=True,
597 group.add_option(
599 "--no-int",
600 dest="useInt",
601 help="do not generate int types",
602 action="store_false",
603 default=True,
605 group.add_option(
607 "--no-long",
608 dest="useLong",
609 help="do not generate long types",
610 action="store_false",
611 default=True,
613 group.add_option(
615 "--no-long-long",
616 dest="useLongLong",
617 help="do not generate long long types",
618 action="store_false",
619 default=True,
621 group.add_option(
623 "--no-unsigned",
624 dest="useUnsigned",
625 help="do not generate unsigned integer types",
626 action="store_false",
627 default=True,
630 # Other builtins
631 group.add_option(
633 "--no-bool",
634 dest="useBool",
635 help="do not generate bool types",
636 action="store_false",
637 default=True,
639 group.add_option(
641 "--no-float",
642 dest="useFloat",
643 help="do not generate float types",
644 action="store_false",
645 default=True,
647 group.add_option(
649 "--no-double",
650 dest="useDouble",
651 help="do not generate double types",
652 action="store_false",
653 default=True,
655 group.add_option(
657 "--no-long-double",
658 dest="useLongDouble",
659 help="do not generate long double types",
660 action="store_false",
661 default=True,
663 group.add_option(
665 "--no-void-pointer",
666 dest="useVoidPointer",
667 help="do not generate void* types",
668 action="store_false",
669 default=True,
672 # Enumerations
673 group.add_option(
675 "--no-enums",
676 dest="useEnum",
677 help="do not generate enum types",
678 action="store_false",
679 default=True,
682 # Derived types
683 group.add_option(
685 "--no-array",
686 dest="useArray",
687 help="do not generate record types",
688 action="store_false",
689 default=True,
691 group.add_option(
693 "--no-complex",
694 dest="useComplex",
695 help="do not generate complex types",
696 action="store_false",
697 default=True,
699 group.add_option(
701 "--no-record",
702 dest="useRecord",
703 help="do not generate record types",
704 action="store_false",
705 default=True,
707 group.add_option(
709 "--no-union",
710 dest="recordUseUnion",
711 help="do not generate union types",
712 action="store_false",
713 default=True,
715 group.add_option(
717 "--no-vector",
718 dest="useVector",
719 help="do not generate vector types",
720 action="store_false",
721 default=True,
723 group.add_option(
725 "--no-bit-field",
726 dest="useBitField",
727 help="do not generate bit-field record members",
728 action="store_false",
729 default=True,
731 group.add_option(
733 "--no-builtins",
734 dest="useBuiltins",
735 help="do not use any types",
736 action="store_false",
737 default=True,
740 # Tuning
741 group.add_option(
743 "--no-function-return",
744 dest="functionUseReturn",
745 help="do not generate return types for functions",
746 action="store_false",
747 default=True,
749 group.add_option(
751 "--vector-types",
752 dest="vectorTypes",
753 help="comma separated list of vector types (e.g., v2i32) [default %default]",
754 action="store",
755 type=str,
756 default="v2i16, v1i64, v2i32, v4i16, v8i8, v2f32, v2i64, v4i32, v8i16, v16i8, v2f64, v4f32, v16f32",
757 metavar="N",
759 group.add_option(
761 "--bit-fields",
762 dest="bitFields",
763 help="comma separated list 'type:width' bit-field specifiers [default %default]",
764 action="store",
765 type=str,
766 default=("char:0,char:4,int:0,unsigned:1,int:1,int:4,int:13,int:24"),
768 group.add_option(
770 "--max-args",
771 dest="functionMaxArgs",
772 help="maximum number of arguments per function [default %default]",
773 action="store",
774 type=int,
775 default=4,
776 metavar="N",
778 group.add_option(
780 "--max-array",
781 dest="arrayMaxSize",
782 help="maximum array size [default %default]",
783 action="store",
784 type=int,
785 default=4,
786 metavar="N",
788 group.add_option(
790 "--max-record",
791 dest="recordMaxSize",
792 help="maximum number of fields per record [default %default]",
793 action="store",
794 type=int,
795 default=4,
796 metavar="N",
798 group.add_option(
800 "--max-record-depth",
801 dest="recordMaxDepth",
802 help="maximum nested structure depth [default %default]",
803 action="store",
804 type=int,
805 default=None,
806 metavar="N",
808 parser.add_option_group(group)
809 (opts, args) = parser.parse_args()
811 if not opts.useRandomSeed:
812 random.seed(opts.seed)
814 # Construct type generator
815 builtins = []
816 if opts.useBuiltins:
817 ints = []
818 if opts.useChar:
819 ints.append(("char", 1))
820 if opts.useShort:
821 ints.append(("short", 2))
822 if opts.useInt:
823 ints.append(("int", 4))
824 # FIXME: Wrong size.
825 if opts.useLong:
826 ints.append(("long", 4))
827 if opts.useLongLong:
828 ints.append(("long long", 8))
829 if opts.useUnsigned:
830 ints = [("unsigned %s" % i, s) for i, s in ints] + [
831 ("signed %s" % i, s) for i, s in ints
833 builtins.extend(ints)
835 if opts.useBool:
836 builtins.append(("_Bool", 1))
837 if opts.useFloat:
838 builtins.append(("float", 4))
839 if opts.useDouble:
840 builtins.append(("double", 8))
841 if opts.useLongDouble:
842 builtins.append(("long double", 16))
843 # FIXME: Wrong size.
844 if opts.useVoidPointer:
845 builtins.append(("void*", 4))
847 btg = FixedTypeGenerator([BuiltinType(n, s) for n, s in builtins])
849 bitfields = []
850 for specifier in opts.bitFields.split(","):
851 if not specifier.strip():
852 continue
853 name, width = specifier.strip().split(":", 1)
854 bitfields.append(BuiltinType(name, None, int(width)))
855 bftg = FixedTypeGenerator(bitfields)
857 charType = BuiltinType("char", 1)
858 shortType = BuiltinType("short", 2)
859 intType = BuiltinType("int", 4)
860 longlongType = BuiltinType("long long", 8)
861 floatType = BuiltinType("float", 4)
862 doubleType = BuiltinType("double", 8)
863 sbtg = FixedTypeGenerator([charType, intType, floatType, doubleType])
865 atg = AnyTypeGenerator()
866 artg = AnyTypeGenerator()
868 def makeGenerator(atg, subgen, subfieldgen, useRecord, useArray, useBitField):
869 atg.addGenerator(btg)
870 if useBitField and opts.useBitField:
871 atg.addGenerator(bftg)
872 if useRecord and opts.useRecord:
873 assert subgen
874 atg.addGenerator(
875 RecordTypeGenerator(
876 subfieldgen, opts.recordUseUnion, opts.recordMaxSize
879 if opts.useComplex:
880 # FIXME: Allow overriding builtins here
881 atg.addGenerator(ComplexTypeGenerator(sbtg))
882 if useArray and opts.useArray:
883 assert subgen
884 atg.addGenerator(ArrayTypeGenerator(subgen, opts.arrayMaxSize))
885 if opts.useVector:
886 vTypes = []
887 for i, t in enumerate(opts.vectorTypes.split(",")):
888 m = re.match("v([1-9][0-9]*)([if][1-9][0-9]*)", t.strip())
889 if not m:
890 parser.error("Invalid vector type: %r" % t)
891 count, kind = m.groups()
892 count = int(count)
893 type = {
894 "i8": charType,
895 "i16": shortType,
896 "i32": intType,
897 "i64": longlongType,
898 "f32": floatType,
899 "f64": doubleType,
900 }.get(kind)
901 if not type:
902 parser.error("Invalid vector type: %r" % t)
903 vTypes.append(ArrayType(i, True, type, count * type.size))
905 atg.addGenerator(FixedTypeGenerator(vTypes))
906 if opts.useEnum:
907 atg.addGenerator(EnumTypeGenerator([None, "-1", "1", "1u"], 1, 4))
909 if opts.recordMaxDepth is None:
910 # Fully recursive, just avoid top-level arrays.
911 subFTG = AnyTypeGenerator()
912 subTG = AnyTypeGenerator()
913 atg = AnyTypeGenerator()
914 makeGenerator(subFTG, atg, atg, True, True, True)
915 makeGenerator(subTG, atg, subFTG, True, True, False)
916 makeGenerator(atg, subTG, subFTG, True, False, False)
917 else:
918 # Make a chain of type generators, each builds smaller
919 # structures.
920 base = AnyTypeGenerator()
921 fbase = AnyTypeGenerator()
922 makeGenerator(base, None, None, False, False, False)
923 makeGenerator(fbase, None, None, False, False, True)
924 for i in range(opts.recordMaxDepth):
925 n = AnyTypeGenerator()
926 fn = AnyTypeGenerator()
927 makeGenerator(n, base, fbase, True, True, False)
928 makeGenerator(fn, base, fbase, True, True, True)
929 base = n
930 fbase = fn
931 atg = AnyTypeGenerator()
932 makeGenerator(atg, base, fbase, True, False, False)
934 if opts.testLayout:
935 ftg = atg
936 else:
937 ftg = FunctionTypeGenerator(atg, opts.functionUseReturn, opts.functionMaxArgs)
939 # Override max,min,count if finite
940 if opts.maxIndex is None:
941 if ftg.cardinality is aleph0:
942 opts.maxIndex = 10000000
943 else:
944 opts.maxIndex = ftg.cardinality
945 opts.maxIndex = min(opts.maxIndex, ftg.cardinality)
946 opts.minIndex = max(0, min(opts.maxIndex - 1, opts.minIndex))
947 if not opts.mode == "random":
948 opts.count = min(opts.count, opts.maxIndex - opts.minIndex)
950 if opts.output == "-":
951 output = sys.stdout
952 else:
953 output = open(opts.output, "w")
954 atexit.register(lambda: output.close())
956 outputHeader = None
957 if opts.outputHeader:
958 outputHeader = open(opts.outputHeader, "w")
959 atexit.register(lambda: outputHeader.close())
961 outputTests = None
962 if opts.outputTests:
963 outputTests = open(opts.outputTests, "w")
964 atexit.register(lambda: outputTests.close())
966 outputDriver = None
967 if opts.outputDriver:
968 outputDriver = open(opts.outputDriver, "w")
969 atexit.register(lambda: outputDriver.close())
971 info = ""
972 info += "// %s\n" % (" ".join(sys.argv),)
973 info += "// Generated: %s\n" % (time.strftime("%Y-%m-%d %H:%M"),)
974 info += "// Cardinality of function generator: %s\n" % (ftg.cardinality,)
975 info += "// Cardinality of type generator: %s\n" % (atg.cardinality,)
977 if opts.testLayout:
978 info += "\n#include <stdio.h>"
980 P = TypePrinter(
981 output,
982 outputHeader=outputHeader,
983 outputTests=outputTests,
984 outputDriver=outputDriver,
985 headerName=opts.outputHeader,
986 info=info,
989 def write(N):
990 try:
991 FT = ftg.get(N)
992 except RuntimeError as e:
993 if e.args[0] == "maximum recursion depth exceeded":
994 print(
995 "WARNING: Skipped %d, recursion limit exceeded (bad arguments?)"
996 % (N,),
997 file=sys.stderr,
999 return
1000 raise
1001 if opts.testLayout:
1002 P.writeLayoutTest(N, FT)
1003 else:
1004 P.writeFunction(N, FT)
1006 if args:
1007 [write(int(a)) for a in args]
1009 skipTests = set(opts.skipTests)
1010 for i in range(opts.count):
1011 if opts.mode == "linear":
1012 index = opts.minIndex + i
1013 else:
1014 index = opts.minIndex + int(
1015 (opts.maxIndex - opts.minIndex) * random.random()
1017 if index in skipTests:
1018 continue
1019 write(index)
1021 P.finish()
1024 if __name__ == "__main__":
1025 main()