1#!/usr/bin/env python 2 3from __future__ import absolute_import, division, print_function 4from pprint import pprint 5import random, atexit, time 6from random import randrange 7import re 8 9from Enumeration import * 10from TypeGen import * 11 12#### 13 14 15class TypePrinter(object): 16 def __init__( 17 self, 18 output, 19 outputHeader=None, 20 outputTests=None, 21 outputDriver=None, 22 headerName=None, 23 info=None, 24 ): 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() 35 36 if info: 37 for f in ( 38 self.output, 39 self.outputHeader, 40 self.outputTests, 41 self.outputDriver, 42 ): 43 if f: 44 print(info, file=f) 45 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) 52 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) 57 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) 64 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) 75 76 if self.outputDriver: 77 print(' printf("DONE\\n");', file=self.outputDriver) 78 print(" return 0;", file=self.outputDriver) 79 print("}", file=self.outputDriver) 80 81 def addDeclaration(self, decl): 82 if decl in self.declarations: 83 return False 84 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 93 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 101 102 def writeLayoutTest(self, i, ty): 103 tyName = self.getTypeName(ty) 104 tyNameClean = tyName.replace(" ", "_").replace("*", "star") 105 fnName = "test_%s" % tyNameClean 106 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) 113 114 self.layoutTests.append((i, fnName)) 115 116 def writeFunction(self, i, FT): 117 args = ", ".join( 118 ["%s arg%d" % (self.getTypeName(t), i) for i, t in enumerate(FT.argTypes)] 119 ) 120 if not args: 121 args = "void" 122 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) 130 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) 136 137 print("%s %s(%s)" % (retvalTypeName, fnName, args), end=" ", file=self.output) 138 if self.writeBody: 139 print("{", file=self.output) 140 141 for i, t in enumerate(FT.argTypes): 142 self.printValueOfType(" %s" % fnName, "arg%d" % i, t) 143 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) 150 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) 156 157 if self.outputTests: 158 if self.outputHeader: 159 print("void test_%s(void);" % (fnName,), file=self.outputHeader) 160 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) 167 168 if retvalTests is not None: 169 print( 170 ' printf("%s: testing return.\\n");' % (fnName,), 171 file=self.outputTests, 172 ) 173 print( 174 " for (int i=0; i<%d; ++i) {" % (retvalTests[1],), 175 file=self.outputTests, 176 ) 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, 182 ) 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, 190 ) 191 self.checkTypeValues( 192 "RV", 193 "%s[i]" % retvalTests[0], 194 FT.returnType, 195 output=self.outputTests, 196 indent=4, 197 ) 198 print(" }", file=self.outputTests) 199 200 if tests: 201 print( 202 ' printf("%s: testing arguments.\\n");' % (fnName,), 203 file=self.outputTests, 204 ) 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);" 211 % ( 212 fnName, 213 ", ".join(args), 214 ), 215 file=self.outputTests, 216 ) 217 print("}", file=self.outputTests) 218 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 231 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 245 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()] 266 267 if not nonPadding: 268 yield "{ }" 269 return 270 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 277 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)) 284 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,)) 299 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, 305 ) 306 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, 312 ) 313 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, 324 ) 325 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 334 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, 351 ) 352 elif isinstance(t, EnumType): 353 print( 354 '%*sprintf("%s: %s = %%d\\n", %s);' % (indent, "", prefix, name, name), 355 file=output, 356 ) 357 elif isinstance(t, RecordType): 358 if not t.fields: 359 print( 360 '%*sprintf("%s: %s (empty)\\n");' % (indent, "", prefix, name), 361 file=output, 362 ) 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, 375 ) 376 self.printValueOfType( 377 prefix, 378 "(__imag %s)" % name, 379 t.elementType, 380 output=output, 381 indent=indent, 382 ) 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, 394 ) 395 else: 396 self.printValueOfType( 397 prefix, 398 "%s[%d]" % (name, i), 399 t.elementType, 400 output=output, 401 indent=indent, 402 ) 403 else: 404 raise NotImplementedError('Cannot print value of type: "%s"' % (t,)) 405 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), 421 f, 422 output=output, 423 indent=indent, 424 ) 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, 434 ) 435 self.checkTypeValues( 436 "(__imag %s)" % nameLHS, 437 "(__imag %s)" % nameRHS, 438 t.elementType, 439 output=output, 440 indent=indent, 441 ) 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, 453 ) 454 else: 455 self.checkTypeValues( 456 "%s[%d]" % (nameLHS, i), 457 "%s[%d]" % (nameRHS, i), 458 t.elementType, 459 output=output, 460 indent=indent, 461 ) 462 else: 463 raise NotImplementedError('Cannot print value of type: "%s"' % (t,)) 464 465 466import sys 467 468 469def main(): 470 from optparse import OptionParser, OptionGroup 471 472 parser = OptionParser("%prog [options] {indices}") 473 parser.add_option( 474 "", 475 "--mode", 476 dest="mode", 477 help="autogeneration mode (random or linear) [default %default]", 478 type="choice", 479 choices=("random", "linear"), 480 default="linear", 481 ) 482 parser.add_option( 483 "", 484 "--count", 485 dest="count", 486 help="autogenerate COUNT functions according to MODE", 487 type=int, 488 default=0, 489 ) 490 parser.add_option( 491 "", 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, 498 ) 499 parser.add_option( 500 "", 501 "--max", 502 dest="maxIndex", 503 metavar="N", 504 help="maximum index for random autogeneration [default %default]", 505 type=int, 506 default=10000000, 507 ) 508 parser.add_option( 509 "", 510 "--seed", 511 dest="seed", 512 help="random number generator seed [default %default]", 513 type=int, 514 default=1, 515 ) 516 parser.add_option( 517 "", 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, 523 ) 524 parser.add_option( 525 "", 526 "--skip", 527 dest="skipTests", 528 help="add a test index to skip", 529 type=int, 530 action="append", 531 default=[], 532 ) 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="-", 541 ) 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, 550 ) 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, 559 ) 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, 568 ) 569 parser.add_option( 570 "", 571 "--test-layout", 572 dest="testLayout", 573 metavar="FILE", 574 help="test structure layout", 575 action="store_true", 576 default=False, 577 ) 578 579 group = OptionGroup(parser, "Type Enumeration Options") 580 # Builtins - Ints 581 group.add_option( 582 "", 583 "--no-char", 584 dest="useChar", 585 help="do not generate char types", 586 action="store_false", 587 default=True, 588 ) 589 group.add_option( 590 "", 591 "--no-short", 592 dest="useShort", 593 help="do not generate short types", 594 action="store_false", 595 default=True, 596 ) 597 group.add_option( 598 "", 599 "--no-int", 600 dest="useInt", 601 help="do not generate int types", 602 action="store_false", 603 default=True, 604 ) 605 group.add_option( 606 "", 607 "--no-long", 608 dest="useLong", 609 help="do not generate long types", 610 action="store_false", 611 default=True, 612 ) 613 group.add_option( 614 "", 615 "--no-long-long", 616 dest="useLongLong", 617 help="do not generate long long types", 618 action="store_false", 619 default=True, 620 ) 621 group.add_option( 622 "", 623 "--no-unsigned", 624 dest="useUnsigned", 625 help="do not generate unsigned integer types", 626 action="store_false", 627 default=True, 628 ) 629 630 # Other builtins 631 group.add_option( 632 "", 633 "--no-bool", 634 dest="useBool", 635 help="do not generate bool types", 636 action="store_false", 637 default=True, 638 ) 639 group.add_option( 640 "", 641 "--no-float", 642 dest="useFloat", 643 help="do not generate float types", 644 action="store_false", 645 default=True, 646 ) 647 group.add_option( 648 "", 649 "--no-double", 650 dest="useDouble", 651 help="do not generate double types", 652 action="store_false", 653 default=True, 654 ) 655 group.add_option( 656 "", 657 "--no-long-double", 658 dest="useLongDouble", 659 help="do not generate long double types", 660 action="store_false", 661 default=True, 662 ) 663 group.add_option( 664 "", 665 "--no-void-pointer", 666 dest="useVoidPointer", 667 help="do not generate void* types", 668 action="store_false", 669 default=True, 670 ) 671 672 # Enumerations 673 group.add_option( 674 "", 675 "--no-enums", 676 dest="useEnum", 677 help="do not generate enum types", 678 action="store_false", 679 default=True, 680 ) 681 682 # Derived types 683 group.add_option( 684 "", 685 "--no-array", 686 dest="useArray", 687 help="do not generate record types", 688 action="store_false", 689 default=True, 690 ) 691 group.add_option( 692 "", 693 "--no-complex", 694 dest="useComplex", 695 help="do not generate complex types", 696 action="store_false", 697 default=True, 698 ) 699 group.add_option( 700 "", 701 "--no-record", 702 dest="useRecord", 703 help="do not generate record types", 704 action="store_false", 705 default=True, 706 ) 707 group.add_option( 708 "", 709 "--no-union", 710 dest="recordUseUnion", 711 help="do not generate union types", 712 action="store_false", 713 default=True, 714 ) 715 group.add_option( 716 "", 717 "--no-vector", 718 dest="useVector", 719 help="do not generate vector types", 720 action="store_false", 721 default=True, 722 ) 723 group.add_option( 724 "", 725 "--no-bit-field", 726 dest="useBitField", 727 help="do not generate bit-field record members", 728 action="store_false", 729 default=True, 730 ) 731 group.add_option( 732 "", 733 "--no-builtins", 734 dest="useBuiltins", 735 help="do not use any types", 736 action="store_false", 737 default=True, 738 ) 739 740 # Tuning 741 group.add_option( 742 "", 743 "--no-function-return", 744 dest="functionUseReturn", 745 help="do not generate return types for functions", 746 action="store_false", 747 default=True, 748 ) 749 group.add_option( 750 "", 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", 758 ) 759 group.add_option( 760 "", 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"), 767 ) 768 group.add_option( 769 "", 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", 777 ) 778 group.add_option( 779 "", 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", 787 ) 788 group.add_option( 789 "", 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", 797 ) 798 group.add_option( 799 "", 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", 807 ) 808 parser.add_option_group(group) 809 (opts, args) = parser.parse_args() 810 811 if not opts.useRandomSeed: 812 random.seed(opts.seed) 813 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 832 ] 833 builtins.extend(ints) 834 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)) 846 847 btg = FixedTypeGenerator([BuiltinType(n, s) for n, s in builtins]) 848 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) 856 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]) 864 865 atg = AnyTypeGenerator() 866 artg = AnyTypeGenerator() 867 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 877 ) 878 ) 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)) 904 905 atg.addGenerator(FixedTypeGenerator(vTypes)) 906 if opts.useEnum: 907 atg.addGenerator(EnumTypeGenerator([None, "-1", "1", "1u"], 1, 4)) 908 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) 933 934 if opts.testLayout: 935 ftg = atg 936 else: 937 ftg = FunctionTypeGenerator(atg, opts.functionUseReturn, opts.functionMaxArgs) 938 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) 949 950 if opts.output == "-": 951 output = sys.stdout 952 else: 953 output = open(opts.output, "w") 954 atexit.register(lambda: output.close()) 955 956 outputHeader = None 957 if opts.outputHeader: 958 outputHeader = open(opts.outputHeader, "w") 959 atexit.register(lambda: outputHeader.close()) 960 961 outputTests = None 962 if opts.outputTests: 963 outputTests = open(opts.outputTests, "w") 964 atexit.register(lambda: outputTests.close()) 965 966 outputDriver = None 967 if opts.outputDriver: 968 outputDriver = open(opts.outputDriver, "w") 969 atexit.register(lambda: outputDriver.close()) 970 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,) 976 977 if opts.testLayout: 978 info += "\n#include <stdio.h>" 979 980 P = TypePrinter( 981 output, 982 outputHeader=outputHeader, 983 outputTests=outputTests, 984 outputDriver=outputDriver, 985 headerName=opts.outputHeader, 986 info=info, 987 ) 988 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, 998 ) 999 return 1000 raise 1001 if opts.testLayout: 1002 P.writeLayoutTest(N, FT) 1003 else: 1004 P.writeFunction(N, FT) 1005 1006 if args: 1007 [write(int(a)) for a in args] 1008 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() 1016 ) 1017 if index in skipTests: 1018 continue 1019 write(index) 1020 1021 P.finish() 1022 1023 1024if __name__ == "__main__": 1025 main() 1026