|
|
1.1 ! root 1: .\" @(#)porttour1.ms 6.3 (Berkeley) 5/30/86 ! 2: .\" ! 3: .ds f \fIf77\fP ! 4: .ds U \s-2UNIX\s0 ! 5: .ds V \s-2VAX\s0 ! 6: .de Bl ! 7: .na ! 8: .fi ! 9: .ll 3i ! 10: .. ! 11: .de Sp ! 12: .sp 0.25v ! 13: .. ! 14: .TL ! 15: A Tour Through the Portable C Compiler ! 16: .AU ! 17: S. C. Johnson ! 18: .AI ! 19: AT&T Bell Laboratories ! 20: .sp ! 21: .AU ! 22: Donn Seeley ! 23: .AI ! 24: Department of Computer Science ! 25: University of Utah ! 26: .AB ! 27: .OH 'A Tour Through the Portable C Compiler''SMM:19-%' ! 28: .EH 'SMM:19-%''A Tour Through the Portable C Compiler' ! 29: .PP ! 30: Since its introduction, ! 31: the Portable C Compiler has become the standard ! 32: \*U C compiler for many machines. ! 33: Three quarters or more of the code ! 34: in the compiler is machine independent ! 35: and much of the rest can be generated easily ! 36: using knowledge of the target architecture. ! 37: This paper describes the structure ! 38: and organization of the compiler ! 39: and tries to further simplify the job ! 40: of the compiler porter. ! 41: .PP ! 42: This document originally appeared with the Seventh Edition of \*U, ! 43: and has been revised and extended for publication ! 44: with the Fourth Berkeley Software Distribution. ! 45: The new material covers changes which ! 46: have been made in the compiler since the Seventh Edition, ! 47: and includes some discussion of secondary topics ! 48: which were thought to be of interest ! 49: in future ports of the compiler. ! 50: .sp ! 51: .LP ! 52: Revised April, 1986 ! 53: .AE ! 54: .SH ! 55: Introduction ! 56: .PP ! 57: A C compiler has been implemented that has proved to be quite portable, ! 58: serving as the basis for C compilers on roughly a dozen machines, including ! 59: the DEC \*V, Honeywell 6000, IBM 370, and Interdata 8/32. ! 60: The compiler is highly compatible with the C language standard. ! 61: .[ ! 62: Kernighan Ritchie Prentice 1978 ! 63: .] ! 64: .PP ! 65: Among the goals of this compiler are portability, high reliability, ! 66: and the use of state-of-the-art techniques and tools wherever practical. ! 67: Although the efficiency of the compiling process is not ! 68: a primary goal, the compiler is efficient enough, and produces ! 69: good enough code, to serve as a production compiler. ! 70: .PP ! 71: The language implemented is highly compatible with the current PDP-11 version of C. ! 72: Moreover, roughly 75% of the compiler, including ! 73: nearly all the syntactic and semantic routines, is machine independent. ! 74: The compiler also serves as the major portion of the program ! 75: .I lint , ! 76: described elsewhere. ! 77: .[ ! 78: Johnson Lint Program Checker ! 79: .] ! 80: .PP ! 81: A number of earlier attempts to make portable compilers are worth noting. ! 82: While on CO-OP assignment to Bell Labs in 1973, Alan Snyder wrote a portable C ! 83: compiler which was the basis of his Master's Thesis at M.I.T. ! 84: .[ ! 85: Snyder Portable C Compiler ! 86: .] ! 87: This compiler was very slow and complicated, and contained a number of rather ! 88: serious implementation difficulties; ! 89: nevertheless, a number of Snyder's ideas appear in this work. ! 90: .PP ! 91: Most earlier portable compilers, including Snyder's, have proceeded by ! 92: defining an intermediate language, perhaps based ! 93: on three-address code or code for a stack machine, ! 94: and writing a machine independent program to ! 95: translate from the source code to this ! 96: intermediate code. ! 97: The intermediate code is then read by a second pass, and interpreted or compiled. ! 98: This approach is elegant, and has a number of advantages, especially if the ! 99: target machine is far removed from the host. ! 100: It suffers from some disadvantages as well. ! 101: Some constructions, like initialization and subroutine prologs, ! 102: are difficult or expensive to express in a ! 103: machine independent way that still allows them ! 104: to be easily adapted to the target assemblers. ! 105: Most of these approaches require a symbol table to be constructed ! 106: in the second (machine dependent) pass, and/or ! 107: require powerful target assemblers. ! 108: Also, many conversion operators may be generated ! 109: that have no effect on a given machine, ! 110: but may be needed on others (for example, pointer to pointer ! 111: conversions usually do nothing in C, but must be generated because ! 112: there are some machines where they are significant). ! 113: .PP ! 114: For these reasons, the first pass of the portable compiler ! 115: is not entirely machine independent. ! 116: It contains some machine dependent features, such as initialization, subroutine ! 117: prolog and epilog, certain storage allocation functions, ! 118: code for the ! 119: .I switch ! 120: statement, and code to throw out unneeded conversion operators. ! 121: .PP ! 122: As a crude measure of the degree of ! 123: portability actually achieved, ! 124: the Interdata 8/32 C compiler has ! 125: roughly 600 machine dependent lines of source out of 4600 in Pass 1, and 1000 ! 126: out of 3400 in Pass 2. ! 127: In total, 1600 out of 8000, or 20%, ! 128: of the total source is machine dependent ! 129: (12% in Pass 1, 30% in Pass 2). ! 130: These percentages can be expected to rise slightly as the ! 131: compiler is tuned. ! 132: The percentage of machine-dependent code for the IBM is 22%, for ! 133: the Honeywell 25%. ! 134: If the assembler format and structure were the same for all ! 135: these machines, perhaps another 5-10% of the code ! 136: would become machine independent. ! 137: .PP ! 138: These figures are sufficiently misleading as to be almost ! 139: meaningless. ! 140: A large fraction of the machine dependent code can be converted ! 141: in a straightforward, almost mechanical way. ! 142: On the other hand, a certain amount of the code requires hard ! 143: intellectual effort to convert, since the algorithms ! 144: embodied in this part of the code are typically complicated ! 145: and machine dependent. ! 146: .PP ! 147: To summarize, however, if you need a C compiler written for a machine with ! 148: a reasonable architecture, the compiler is already three quarters finished! ! 149: .SH ! 150: Overview ! 151: .PP ! 152: This paper discusses the structure and organization of the portable compiler. ! 153: The intent is to give the big picture, rather than discussing the details of a particular machine ! 154: implementation. ! 155: After a brief overview and a discussion of the source file structure, ! 156: the paper describes the major data structures, and then delves more ! 157: closely into the two passes. ! 158: Some of the theoretical work on which the compiler is based, and ! 159: its application to the compiler, is discussed elsewhere. ! 160: .[ ! 161: johnson portable theory practice ! 162: .] ! 163: One of the major design issues in any C compiler, the design of ! 164: the calling sequence and stack frame, is the subject of a separate ! 165: memorandum. ! 166: .[ ! 167: johnson lesk ritchie calling sequence ! 168: .] ! 169: .PP ! 170: The compiler consists of two passes, ! 171: .I pass1 ! 172: and ! 173: .I pass2 , ! 174: that together turn C source code into assembler code for the target ! 175: machine. ! 176: The two passes are preceded by a preprocessor, that ! 177: handles the ! 178: .B "#define" ! 179: and ! 180: .B "#include" ! 181: statements, and related features (e.g., ! 182: .B #ifdef , ! 183: etc.). ! 184: The two passes may optionally be followed by ! 185: a machine dependent code improver. ! 186: .PP ! 187: The output of the preprocessor is a text file that is read as the standard ! 188: input of the first pass. ! 189: This ! 190: produces as standard output another text file that becomes the standard ! 191: input of the second pass. ! 192: The second pass produces, as standard output, the desired assembler language source code. ! 193: The code improver, if used, converts the assembler code ! 194: to more effective code, ! 195: and the result is passed to the assembler. ! 196: The preprocessor and the two passes ! 197: all write error messages on the standard error file. ! 198: Thus the compiler itself makes few demands on the I/O ! 199: library support, aiding in the bootstrapping process. ! 200: .PP ! 201: The division of the compiler into two passes is somewhat artificial. ! 202: The compiler can optionally be loaded ! 203: so that both passes operate in the same program. ! 204: This ``one pass'' operation eliminates the overhead of ! 205: reading and writing the intermediate file, so the compiler ! 206: operates about 30% faster in this mode. ! 207: It also occupies about 30% more space than the larger ! 208: of the two component passes. ! 209: This ``one pass'' compiler is the standard version ! 210: on machines with large address spaces, such as the \*V. ! 211: .PP ! 212: Because the compiler is fundamentally structured as two ! 213: passes, even when loaded as one, this document primarily ! 214: describes the two pass version. ! 215: .PP ! 216: The first pass does the lexical analysis, parsing, and ! 217: symbol table maintenance. ! 218: It also constructs parse trees for expressions, ! 219: and keeps track of the types of the nodes in these trees. ! 220: Additional code is devoted to initialization. ! 221: Machine dependent portions of the first pass serve to ! 222: generate subroutine prologs and epilogs, ! 223: code for switches, and code for branches, label definitions, ! 224: alignment operations, ! 225: changes of location counter, etc. ! 226: .PP ! 227: The intermediate file is a text file organized into lines. ! 228: Lines beginning with a right parenthesis are copied by the second ! 229: pass directly to its output file, with the ! 230: parenthesis stripped off. ! 231: Thus, when the first pass produces assembly code, such as subroutine prologs, ! 232: etc., each line is prefaced with a right parenthesis; ! 233: the second pass passes these lines to through to the assembler. ! 234: .PP ! 235: The major job done by the second pass is generation of code ! 236: for expressions. ! 237: The expression parse trees produced in the first pass are ! 238: written onto the ! 239: intermediate file in Polish Prefix form: ! 240: first, there is a line beginning with a period, followed by the source ! 241: file line number and name on which the expression appeared (for debugging purposes). ! 242: The successive lines represent the nodes of the parse tree, ! 243: one node per line. ! 244: Each line contains the node number, type, and ! 245: any values (e.g., values of constants) ! 246: that may appear in the node. ! 247: Lines representing nodes with descendants are immediately ! 248: followed by the left subtree of descendants, then the ! 249: right. ! 250: Since the number of descendants of any node is completely ! 251: determined by the node number, there is no need to mark the end ! 252: of the tree. ! 253: .PP ! 254: There are only two other line types in the intermediate file. ! 255: Lines beginning with a left square bracket (`[') represent the beginning of ! 256: blocks (delimited by { ... } in the C source); ! 257: lines beginning with right square brackets (`]') represent the end of blocks. ! 258: The remainder of these lines tell how much ! 259: stack space, and how many register variables, ! 260: are currently in use. ! 261: .PP ! 262: Thus, the second pass reads the intermediate files, copies the `)' lines, ! 263: makes note of the information in the `[' and `]' lines, ! 264: and devotes most of its effort to the ! 265: `.' lines and their associated expression trees, turning them ! 266: turns into assembly code to evaluate the expressions. ! 267: .PP ! 268: In the one pass version of the compiler, the expression ! 269: trees contain information useful to both logical passes. ! 270: Instead of writing the trees onto an intermediate file, ! 271: each tree is transformed in place into an acceptable ! 272: form for the code generator. ! 273: The code generator then writes the result of compiling ! 274: this tree onto the standard output. ! 275: Instead of `[' and `]' lines in the intermediate file, the information is passed ! 276: directly to the second pass routines. ! 277: Assembly code produced by the first pass is simply written out, ! 278: without the need for `)' at the head of each line. ! 279: .SH ! 280: The Source Files ! 281: .PP ! 282: The compiler source consists of 25 source files. ! 283: Several header files contain information ! 284: which is needed across various source modules. ! 285: .I Manifest.h ! 286: has declarations for node types, type manipulation ! 287: macros and other macros, and some global data definitions. ! 288: .I Macdefs.h ! 289: has machine-dependent definitions, such as the size and alignment of the ! 290: various data representations. ! 291: .I Config.h ! 292: defines symbols which control the configuration of the compiler, ! 293: including such things as the sizes of various tables ! 294: and whether the compiler is ``one pass''. ! 295: The compiler conditionally includes another file, ! 296: .I onepass.h , ! 297: which contains definitions which are particular to ! 298: a ``one pass'' compiler. ! 299: .I Ndu.h ! 300: defines the basic tree building structure ! 301: which is used throughout the compiler ! 302: to construct expression trees. ! 303: .I Manifest.h ! 304: includes a file of opcode and type definitions named ! 305: .I pcclocal.h ; ! 306: this file is automatically generated from ! 307: a header file specific to the C compiler named ! 308: .I localdefs.h ! 309: and a public header file ! 310: .I /usr/include/pcc.h . ! 311: Another file, ! 312: .I pcctokens , ! 313: is generated in a similar way ! 314: and contains token definitions for the compiler's Yacc ! 315: .[ ! 316: Johnson Yacc Compiler cstr ! 317: .] ! 318: grammar. ! 319: Two machine independent header files, ! 320: .I pass1.h ! 321: and ! 322: .I pass2.h , ! 323: contain the data structure and manifest definitions ! 324: for the first and second passes, respectively. ! 325: In the second pass, a machine dependent header file, ! 326: .I mac2defs.h , ! 327: contains declarations of register names, etc. ! 328: .PP ! 329: .I Common.c ! 330: contains machine independent routines used in both passes. ! 331: These include routines for allocating and freeing trees, walking over trees, ! 332: printing debugging information, and printing error messages. ! 333: This file can be compiled in two flavors, ! 334: one for pass 1 and one for pass 2, ! 335: depending on what conditional compilation symbol is used. ! 336: .PP ! 337: Entire sections of this document are devoted to the detailed structure of the ! 338: passes. ! 339: For the moment, we just give a brief description of the files. ! 340: The first pass ! 341: is obtained by compiling and loading ! 342: .I cgram.y , ! 343: .I code.c , ! 344: .I common.c , ! 345: .I local.c , ! 346: .I optim.c , ! 347: .I pftn.c , ! 348: .I scan.c , ! 349: .I stab.c , ! 350: .I trees.c ! 351: and ! 352: .I xdefs.c . ! 353: .I Scan.c ! 354: is the lexical analyzer, which provides tokens to the ! 355: bottom-up parser which is defined by the Yacc grammar ! 356: .I cgram.y . ! 357: .I Xdefs.c ! 358: is a short file of external definitions. ! 359: .I Pftn.c ! 360: maintains the symbol table, and does initialization. ! 361: .I Trees.c ! 362: builds the expression trees, and computes the node types. ! 363: .I Optim.c ! 364: does some machine independent optimizations on the expression trees. ! 365: .I Common.c ! 366: contains service routines common to the two passes of the compiler. ! 367: All the above files are machine independent. ! 368: The files ! 369: .I local.c ! 370: and ! 371: .I code.c ! 372: contain machine dependent code for generating subroutine ! 373: prologs, switch code, and the like. ! 374: .I Stab.c ! 375: contains machine dependent code for ! 376: producing external symbol table information ! 377: which can drive a symbolic debugger. ! 378: .PP ! 379: The second pass ! 380: is produced by compiling and loading ! 381: .I allo.c , ! 382: .I common.c , ! 383: .I local2.c , ! 384: .I match.c , ! 385: .I order.c , ! 386: .I reader.c ! 387: and ! 388: .I table.c . ! 389: .I Reader.c ! 390: reads the intermediate file, and controls the major logic of the ! 391: code generation. ! 392: .I Allo.c ! 393: keeps track of busy and free registers. ! 394: .I Match.c ! 395: controls the matching ! 396: of code templates to subtrees of the expression tree to be compiled. ! 397: .I Common.c ! 398: defines certain service routines, ! 399: as in the first pass. ! 400: The above files are machine independent. ! 401: .I Order.c ! 402: controls the machine dependent details of the code generation strategy. ! 403: .I Local2.c ! 404: has many small machine dependent routines, ! 405: and tables of opcodes, register types, etc. ! 406: .I Table.c ! 407: has the code template tables, ! 408: which are also clearly machine dependent. ! 409: .SH ! 410: Data Structure Considerations ! 411: .PP ! 412: This section discusses the node numbers, type words, and expression trees, used ! 413: throughout both passes of the compiler. ! 414: .PP ! 415: The file ! 416: .I manifest.h ! 417: defines those symbols used throughout both passes. ! 418: The intent is to use the same symbol name (e.g., MINUS) ! 419: for the given operator throughout the lexical analysis, parsing, tree building, ! 420: and code generation phases. ! 421: .I Manifest.h ! 422: obtains some of its definitions from ! 423: two other header files, ! 424: .I localdefs.h ! 425: and ! 426: .I pcc.h . ! 427: .I Localdefs.h ! 428: contains definitions for operator symbols ! 429: which are specific to the C compiler. ! 430: .I Pcc.h ! 431: contains definitions for operators and types ! 432: which may be used by other compilers ! 433: to communicate with a portable code generator ! 434: based on pass 2; ! 435: this code generator will be described later. ! 436: .PP ! 437: A token ! 438: like MINUS may be seen in the lexical analyzer before it is known ! 439: whether it is a unary or binary operator; ! 440: clearly, it is necessary to know this by the time the parse tree ! 441: is constructed. ! 442: Thus, an operator (really a macro) called ! 443: UNARY is provided, so that MINUS ! 444: and UNARY MINUS are both distinct node numbers. ! 445: Similarly, many binary operators exist in an assignment form (for example, \-=), ! 446: and the operator ASG may be applied to such node names to generate new ones, e.g. ASG MINUS. ! 447: .PP ! 448: It is frequently desirable to know if a node represents a leaf (no descendants), a unary operator (one ! 449: descendant) or a binary operator (two descendants). ! 450: The macro ! 451: .I optype(o) ! 452: returns one of the manifest constants LTYPE, UTYPE, or BITYPE, respectively, depending ! 453: on the node number ! 454: .I o . ! 455: Similarly, ! 456: .I asgop(o) ! 457: returns true if ! 458: .I o ! 459: is an assignment operator number (=, +=, etc. ), and ! 460: .I logop(o) ! 461: returns true if ! 462: .I o ! 463: is a relational or logical (&&, \(or\(or, or !) operator. ! 464: .PP ! 465: C has a rich typing structure, with a potentially infinite number of types. ! 466: To begin with, there are the basic types: CHAR, SHORT, INT, LONG, the unsigned versions ! 467: known as ! 468: UCHAR, USHORT, UNSIGNED, ULONG, and FLOAT, DOUBLE, ! 469: and finally ! 470: STRTY (a structure), UNIONTY, and ENUMTY. ! 471: Then, there are three operators that can be applied to types to make others: ! 472: if ! 473: .I t ! 474: is a type, we may potentially have types ! 475: .I "pointer to t" , ! 476: .I "function returning t" , ! 477: and ! 478: .I "array of t's" ! 479: generated from ! 480: .I t . ! 481: Thus, an arbitrary type in C consists of a basic type, and zero or more of these operators. ! 482: .PP ! 483: In the compiler, a type is represented by an unsigned integer; the rightmost four bits hold the basic ! 484: type, and the remaining bits are divided into two-bit fields, containing ! 485: 0 (no operator), or one of the three operators ! 486: described above. ! 487: The modifiers are read right to left in the word, starting with the two-bit ! 488: field adjacent to the basic type, until a field with 0 in it is reached. ! 489: The macros PTR, FTN, and ARY represent the ! 490: .I "pointer to" , ! 491: .I "function returning" , ! 492: and ! 493: .I "array of" ! 494: operators. ! 495: The macro values are shifted so that they align with the first two-bit ! 496: field; thus PTR+INT ! 497: represents the type for an integer pointer, and ! 498: .DS ! 499: ARY + (PTR<<2) + (FTN<<4) + DOUBLE ! 500: .DE ! 501: represents the type of an array of pointers to functions returning \fBdouble\fPs. ! 502: .PP ! 503: The type words are ordinarily manipulated by macros. ! 504: If ! 505: .I t ! 506: is a type word, ! 507: .I BTYPE(t) ! 508: gives the basic type. ! 509: .I ISPTR(t) , ! 510: .I ISARY(t) , ! 511: and ! 512: .I ISFTN(t) ! 513: ask if an object of this type is a pointer, array, or a function, ! 514: respectively. ! 515: .I MODTYPE(t,b) ! 516: sets the basic type of ! 517: .I t ! 518: to ! 519: .I b . ! 520: .I DECREF(t) ! 521: gives the type resulting from removing the first operator from ! 522: .I t . ! 523: Thus, if ! 524: .I t ! 525: is a pointer to ! 526: .I t\(fm , ! 527: a function returning ! 528: .I t\(fm , ! 529: or an array of ! 530: .I t\(fm , ! 531: then ! 532: .I DECREF(t) ! 533: would equal ! 534: .I t\(fm . ! 535: .I INCREF(t) ! 536: gives the type representing a pointer to ! 537: .I t . ! 538: Finally, there are operators for dealing with the unsigned types. ! 539: .I ISUNSIGNED(t) ! 540: returns true if ! 541: .I t ! 542: is one of the four basic unsigned types; ! 543: in this case, ! 544: .I DEUNSIGN(t) ! 545: gives the associated `signed' type. ! 546: Similarly, ! 547: .I UNSIGNABLE(t) ! 548: returns true if ! 549: .I t ! 550: is one of the four basic types that could become unsigned, and ! 551: .I ENUNSIGN(t) ! 552: returns the unsigned analogue of ! 553: .I t ! 554: in this case. ! 555: .PP ! 556: The other important global data structure is that of expression trees. ! 557: The actual shapes of the nodes are given in ! 558: .I ndu.h . ! 559: The information stored for each pass is not quite the same; ! 560: in the first pass, nodes contain ! 561: dimension and size information, while in the second pass ! 562: nodes contain register allocation information. ! 563: Nevertheless, all nodes contain fields called ! 564: .I op , ! 565: containing the node number, ! 566: and ! 567: .I type , ! 568: containing the type word. ! 569: A function called ! 570: .I talloc() ! 571: returns a pointer to a new tree node. ! 572: To free a node, its ! 573: .I op ! 574: field need merely be set to FREE. ! 575: The other fields in the node will remain intact at least until the next allocation. ! 576: .PP ! 577: Nodes representing binary operators contain fields, ! 578: .I left ! 579: and ! 580: .I right , ! 581: that contain pointers to the left and right descendants. ! 582: Unary operator nodes have the ! 583: .I left ! 584: field, and a value field called ! 585: .I rval . ! 586: Leaf nodes, with no descendants, have two value fields: ! 587: .I lval ! 588: and ! 589: .I rval . ! 590: .PP ! 591: At appropriate times, the function ! 592: .I tcheck() ! 593: can be called, to check that there are no busy nodes remaining. ! 594: This is used as a compiler consistency check. ! 595: The function ! 596: .I tcopy(p) ! 597: takes a pointer ! 598: .I p ! 599: that points to an expression tree, and returns a pointer ! 600: to a disjoint copy of the tree. ! 601: The function ! 602: .I walkf(p,f) ! 603: performs a postorder walk of the tree pointed to by ! 604: .I p , ! 605: and applies the function ! 606: .I f ! 607: to each node. ! 608: The function ! 609: .I fwalk(p,f,d) ! 610: does a preorder walk of the tree pointed to by ! 611: .I p . ! 612: At each node, it calls a function ! 613: .I f , ! 614: passing to it the node pointer, a value passed down ! 615: from its ancestor, and two pointers to values to be passed ! 616: down to the left and right descendants (if any). ! 617: The value ! 618: .I d ! 619: is the value passed down to the root. ! 620: .I Fwalk ! 621: is used for a number of tree labeling and debugging activities. ! 622: .PP ! 623: The other major data structure, the symbol table, exists only in pass one, ! 624: and will be discussed later. ! 625: .SH ! 626: Pass One ! 627: .PP ! 628: The first pass does lexical analysis, parsing, symbol table maintenance, ! 629: tree building, optimization, and a number of machine dependent things. ! 630: This pass is largely machine independent, and the machine independent ! 631: sections can be pretty successfully ignored. ! 632: Thus, they will be only sketched here. ! 633: .SH ! 634: Lexical Analysis ! 635: .PP ! 636: The lexical analyzer is a conceptually simple routine that reads the input ! 637: and returns the tokens of the C language as it encounters them: ! 638: names, constants, operators, and keywords. ! 639: The conceptual simplicity of this job is confounded a bit by several ! 640: other simple jobs that unfortunately must go on simultaneously. ! 641: These include ! 642: .IP \(bu ! 643: Keeping track of the current filename and line number, and occasionally ! 644: setting this information as the result of preprocessor control lines. ! 645: .IP \(bu ! 646: Skipping comments. ! 647: .IP \(bu ! 648: Properly dealing with octal, decimal, hex, floating ! 649: point, and character constants, as well as character strings. ! 650: .PP ! 651: To achieve speed, the program maintains several tables ! 652: that are indexed into by character value, to tell ! 653: the lexical analyzer what to do next. ! 654: To achieve portability, these tables must be initialized ! 655: each time the compiler is run, in order that the ! 656: table entries reflect the local character set values. ! 657: .SH ! 658: Parsing ! 659: .PP ! 660: As mentioned above, the parser is generated by Yacc from the grammar ! 661: .I cgram.y. ! 662: The grammar is relatively readable, but contains some unusual features ! 663: that are worth comment. ! 664: .PP ! 665: Perhaps the strangest feature of the grammar is the treatment of ! 666: declarations. ! 667: The problem is to keep track of the basic type ! 668: and the storage class while interpreting the various ! 669: stars, brackets, and parentheses that may surround a given name. ! 670: The entire declaration mechanism must be recursive, ! 671: since declarations may appear within declarations of ! 672: structures and unions, or even within a ! 673: .B sizeof ! 674: construction ! 675: inside a dimension in another declaration! ! 676: .PP ! 677: There are some difficulties in using a bottom-up parser, ! 678: such as produced by Yacc, to handle constructions where a lot ! 679: of left context information must be kept around. ! 680: The problem is that the original PDP-11 compiler is top-down in ! 681: implementation, and some of the semantics of C reflect this. ! 682: In a top-down parser, the input rules are restricted ! 683: somewhat, but one can naturally associate temporary ! 684: storage with a rule at a very early stage in the recognition ! 685: of that rule. ! 686: In a bottom-up parser, there is more freedom in the ! 687: specification of rules, but it is more difficult to know what ! 688: rule is being matched until the entire rule is seen. ! 689: The parser described by ! 690: .I cgram.y ! 691: makes effective use of ! 692: the bottom-up parsing mechanism in some places (notably the treatment ! 693: of expressions), but struggles against the ! 694: restrictions in others. ! 695: The usual result is that it is necessary to run a stack of values ! 696: ``on the side'', independent of the Yacc value stack, ! 697: in order to be able to store and access information ! 698: deep within inner constructions, where the relationship of the ! 699: rules being recognized to the total picture is not yet clear. ! 700: .PP ! 701: In the case of declarations, the attribute information ! 702: (type, etc.) for a declaration is carefully ! 703: kept immediately to the left of the declarator ! 704: (that part of the declaration involving the name). ! 705: In this way, when it is time to declare the name, the ! 706: name and the type information can be quickly brought together. ! 707: The ``$0'' mechanism of Yacc is used to accomplish this. ! 708: The result is not pretty, but it works. ! 709: The storage class information changes more slowly, ! 710: so it is kept in an external variable, and stacked if ! 711: necessary. ! 712: Some of the grammar could be considerably cleaned up by using ! 713: some more recent features of Yacc, notably actions within ! 714: rules and the ability to return multiple values for actions. ! 715: .PP ! 716: A stack is also used to keep track of the current location ! 717: to be branched to when a ! 718: .B break ! 719: or ! 720: .B continue ! 721: statement is processed. ! 722: .PP ! 723: This use of external stacks dates from the time when Yacc did not permit ! 724: values to be structures. ! 725: Some, or most, of this use of external stacks ! 726: could be eliminated by redoing the grammar to use the mechanisms now provided. ! 727: There are some areas, however, particularly the processing of structure, union, ! 728: and enumeration declarations, function ! 729: prologs, and switch statement processing, when having ! 730: all the affected data together in an array speeds later ! 731: processing; in this case, use of external storage seems essential. ! 732: .PP ! 733: The ! 734: .I cgram.y ! 735: file also contains some small functions used as ! 736: utility functions in the parser. ! 737: These include routines for saving case values and labels in processing switches, ! 738: and stacking and popping ! 739: values on the external stack described above. ! 740: .SH ! 741: Storage Classes ! 742: .PP ! 743: C has a finite, but fairly extensive, number of storage classes ! 744: available. ! 745: One of the compiler design decisions was to ! 746: process the storage class information totally in the first pass; ! 747: by the second pass, this information must have ! 748: been totally dealt with. ! 749: This means that all of the storage allocation must take place in the first ! 750: pass, so that references to automatics and ! 751: parameters can be turned into references to cells lying a certain ! 752: number of bytes offset from certain machine registers. ! 753: Much of this transformation is machine dependent, and strongly ! 754: depends on the storage class. ! 755: .PP ! 756: The classes include EXTERN (for externally declared, but not defined variables), ! 757: EXTDEF (for external definitions), and similar distinctions for ! 758: USTATIC and STATIC, UFORTRAN and FORTRAN (for fortran functions) and ! 759: ULABEL and LABEL. ! 760: The storage classes REGISTER and AUTO are obvious, as ! 761: are STNAME, UNAME, and ENAME (for structure, union, and enumeration ! 762: tags), and the associated MOS, MOU, and MOE (for the members). ! 763: TYPEDEF is treated as a storage class as well. ! 764: There are two special storage classes: PARAM and SNULL. ! 765: SNULL is used to distinguish the case where no explicit ! 766: storage class has been given; before an entry is made ! 767: in the symbol table the true storage class is discovered. ! 768: Similarly, PARAM is used for the temporary entry in the symbol ! 769: table made before the declaration of function parameters is completed. ! 770: .PP ! 771: The most complexity in the storage class process comes from ! 772: bit fields. ! 773: A separate storage class is kept for each width bit field; ! 774: a ! 775: .I k ! 776: bit bit field has storage class ! 777: .I k ! 778: plus FIELD. ! 779: This enables the size to be quickly recovered from the storage class. ! 780: .SH ! 781: Symbol Table Maintenance ! 782: .PP ! 783: The symbol table routines do far more than simply enter ! 784: names into the symbol table; ! 785: considerable semantic processing and checking is done as well. ! 786: For example, if a new declaration comes in, it must be checked ! 787: to see if there is a previous declaration of the same symbol. ! 788: If there is, there are many cases. ! 789: The declarations may agree and be compatible (for example, ! 790: an \fBextern\fP declaration can appear twice) in which case the ! 791: new declaration is ignored. ! 792: The new declaration may add information (such as an explicit array ! 793: dimension) to an already present declaration. ! 794: The new declaration may be different, but still correct (for example, ! 795: an \fBextern\fP declaration of something may be entered, ! 796: and then later the definition may be seen). ! 797: The new declaration may be incompatible, but appear in an inner block; ! 798: in this case, the old declaration is carefully hidden away, and ! 799: the new one comes into force until the block is left. ! 800: Finally, the declarations may be incompatible, and an error ! 801: message must be produced. ! 802: .PP ! 803: A number of other factors make for additional complexity. ! 804: The type declared by the user is not always the type ! 805: entered into the symbol table (for example, if a formal parameter to a function ! 806: is declared to be an array, C requires that this be changed into ! 807: a pointer before entry in the symbol table). ! 808: Moreover, there are various kinds of illegal types that ! 809: may be declared which are difficult to ! 810: check for syntactically (for example, ! 811: a function returning an array). ! 812: Finally, there is a strange feature in C that requires ! 813: structure tag names and member names for structures and unions ! 814: to be taken from a different logical symbol table than ordinary identifiers. ! 815: Keeping track of which kind of name is involved is a bit of struggle ! 816: (consider typedef names used within structure declarations, for example). ! 817: .PP ! 818: The symbol table handling routines have been rewritten a number of times to ! 819: extend features, improve performance, and fix bugs. ! 820: They address the above problems with reasonable effectiveness ! 821: but a singular lack of grace. ! 822: .PP ! 823: When a name is read in the input, it is hashed, and the ! 824: routine ! 825: .I lookup ! 826: is called, together with a flag which tells which symbol table ! 827: should be searched (actually, both symbol tables are stored in one, and a flag ! 828: is used to distinguish individual entries). ! 829: If the name is found, ! 830: .I lookup ! 831: returns the index to the entry found; otherwise, it makes ! 832: a new entry, marks it UNDEF (undefined), and returns the ! 833: index of the new entry. ! 834: This index is stored in the ! 835: .I rval ! 836: field of a NAME node. ! 837: .PP ! 838: When a declaration is being parsed, this NAME node is ! 839: made part of a tree with UNARY MUL nodes for each \fB*\fP, ! 840: LB nodes for each array descriptor (the right descendant ! 841: has the dimension), and UNARY CALL nodes for each function ! 842: descriptor. ! 843: This tree is passed to the routine ! 844: .I tymerge , ! 845: along with the attribute type of the whole declaration; ! 846: this routine collapses the tree to a single node, by calling ! 847: .I tyreduce , ! 848: and then modifies the type to reflect the overall ! 849: type of the declaration. ! 850: .PP ! 851: Dimension and size information is stored in a table called ! 852: .I dimtab . ! 853: To properly describe a type in C, one needs not just the ! 854: type information but also size information (for structures and ! 855: enumerations) and dimension information (for arrays). ! 856: Sizes and offsets are dealt with in the compiler by ! 857: giving the associated indices into ! 858: .I dimtab . ! 859: .I Tymerge ! 860: and ! 861: .I tyreduce ! 862: call ! 863: .I dstash ! 864: to put the discovered dimensions away into the ! 865: .I dimtab ! 866: array. ! 867: .I Tymerge ! 868: returns a pointer to a single node that contains ! 869: the symbol table index in its ! 870: .I rval ! 871: field, and the size and dimension indices in ! 872: fields ! 873: .I csiz ! 874: and ! 875: .I cdim , ! 876: respectively. ! 877: This information is properly considered part of the type in the first pass, ! 878: and is carried around at all times. ! 879: .PP ! 880: To enter an element into the symbol table, the routine ! 881: .I defid ! 882: is called; it is handed a storage class, and a pointer ! 883: to the node produced by ! 884: .I tymerge . ! 885: .I Defid ! 886: calls ! 887: .I fixtype , ! 888: which adjusts and checks the given type depending on the storage ! 889: class, and converts null types appropriately. ! 890: It then calls ! 891: .I fixclass , ! 892: which does a similar job for the storage class; ! 893: it is here, for example, that ! 894: \fBregister\fP declarations are either allowed or changed ! 895: to \fBauto\fP. ! 896: .PP ! 897: The new declaration is now compared against an older one, ! 898: if present, and several pages of validity checks performed. ! 899: If the definitions are compatible, with possibly some added information, ! 900: the processing is straightforward. ! 901: If the definitions differ, the block levels of the ! 902: current and the old declaration are compared. ! 903: The current block level is kept in ! 904: .I blevel , ! 905: an external variable; the old declaration level is kept in the symbol table. ! 906: Block level 0 is for external declarations, 1 is for arguments to functions, ! 907: and 2 and above are blocks within a function. ! 908: If the current block level is the same as the old declaration, an error ! 909: results. ! 910: If the current block level is higher, the new declaration overrides the old. ! 911: This is done by marking the old symbol table entry ``hidden'', and making ! 912: a new entry, marked ``hiding''. ! 913: .I Lookup ! 914: will skip over hidden entries. ! 915: When a block is left, the symbol table is searched, ! 916: and any entries defined in that block are destroyed; if ! 917: they hid other entries, the old entries are ``unhidden''. ! 918: .PP ! 919: This nice block structure is warped a bit because labels ! 920: do not follow the block structure rules (one can do a ! 921: .B goto ! 922: into ! 923: a block, for example); ! 924: default definitions of functions in inner blocks also persist clear out to the outermost scope. ! 925: This implies that cleaning up the symbol table after block exit is more ! 926: subtle than it might first seem. ! 927: .PP ! 928: For successful new definitions, ! 929: .I defid ! 930: also initializes a ``general purpose'' field, ! 931: .I offset , ! 932: in the symbol table. ! 933: It contains the stack offset for automatics and parameters, the register number ! 934: for register variables, the bit offset into the structure for ! 935: structure members, and ! 936: the internal label number for static variables and labels. ! 937: The offset field is set by ! 938: .I falloc ! 939: for bit fields, and ! 940: .I dclstruct ! 941: for structures and unions. ! 942: .PP ! 943: The symbol table entry itself thus contains ! 944: the name, type word, size and dimension offsets, ! 945: offset value, and declaration block level. ! 946: It also has a field of flags, describing what symbol table the ! 947: name is in, and whether the entry is hidden, or hides another. ! 948: Finally, a field gives the line number of the last use, ! 949: or of the definition, of the name. ! 950: This is used mainly for diagnostics, but is useful to ! 951: .I lint ! 952: as well. ! 953: .PP ! 954: In some special cases, there is more than the above amount of information kept ! 955: for the use of the compiler. ! 956: This is especially true with structures; for use in initialization, ! 957: structure declarations must have access to a list of the members of the ! 958: structure. ! 959: This list is also kept in ! 960: .I dimtab . ! 961: Because a structure can be mentioned long before the ! 962: members are known, it is necessary to have another ! 963: level of indirection in the table. ! 964: The two words following the ! 965: .I csiz ! 966: entry in ! 967: .I dimtab ! 968: are used to hold the alignment of the structure, and ! 969: the index in dimtab of the list of members. ! 970: This list contains the symbol table indices for the structure members, terminated by a ! 971: \-1. ! 972: .SH ! 973: Tree Building ! 974: .PP ! 975: The portable compiler transforms expressions ! 976: into expression trees. ! 977: As the parser recognizes each rule making up an ! 978: expression, ! 979: it calls ! 980: .I buildtree ! 981: which is given an operator number, and pointers to the ! 982: left and right descendants. ! 983: .I Buildtree ! 984: first examines the left and right descendants, ! 985: and, if they are both constants, and the operator ! 986: is appropriate, simply does the constant ! 987: computation at compile time, and returns ! 988: the result as a constant. ! 989: Otherwise, ! 990: .I buildtree ! 991: allocates a node for the head of the tree, ! 992: attaches the descendants to it, and ensures that ! 993: conversion operators are generated if needed, and that ! 994: the type of the new node is consistent with the types ! 995: of the operands. ! 996: There is also a considerable amount of semantic complexity here; ! 997: many combinations of types are illegal, and the portable ! 998: compiler makes a strong effort to check ! 999: the legality of expression types completely. ! 1000: This is done both for ! 1001: .I lint ! 1002: purposes, and to prevent such semantic errors ! 1003: from being passed through to the code generator. ! 1004: .PP ! 1005: The heart of ! 1006: .I buildtree ! 1007: is a large table, accessed by the routine ! 1008: .I opact . ! 1009: This routine maps the types of the left and right ! 1010: operands into a rather smaller set of descriptors, and then ! 1011: accesses a table (actually encoded in a switch statement) which ! 1012: for each operator and pair of types causes ! 1013: an action to be returned. ! 1014: The actions are logical or's of a number of ! 1015: separate actions, which may be ! 1016: carried out by ! 1017: .I buildtree . ! 1018: These component actions may include ! 1019: checking the left side to ensure that it ! 1020: is an lvalue (can be stored into), ! 1021: applying a type conversion to the left or right operand, ! 1022: setting the type of the new node to ! 1023: the type of the left or right operand, calling various ! 1024: routines to balance the types of the left and right operands, ! 1025: and suppressing the ordinary conversion ! 1026: of arrays and function operands to pointers. ! 1027: An important operation is OTHER, which causes ! 1028: some special code to be invoked ! 1029: in ! 1030: .I buildtree , ! 1031: to handle issues which are unique to a particular operator. ! 1032: Examples of this are ! 1033: structure and union reference ! 1034: (actually handled by ! 1035: the routine ! 1036: .I stref ), ! 1037: the building of NAME, ICON, STRING and FCON (floating point constant) nodes, ! 1038: unary \fB*\fP and \fB&\fP, structure assignment, and calls. ! 1039: In the case of unary \fB*\fP and \fB&\fP, ! 1040: .I buildtree ! 1041: will cancel a \fB*\fP applied to a tree, the top node of which ! 1042: is \fB&\fP, and conversely. ! 1043: .PP ! 1044: Another special operation is ! 1045: PUN; this ! 1046: causes the compiler to check for type mismatches, ! 1047: such as intermixing pointers and integers. ! 1048: .PP ! 1049: The treatment of conversion operators is a rather ! 1050: strange area of the compiler (and of C!). ! 1051: The introduction of type casts only confounded this ! 1052: situation. ! 1053: Most of the conversion operators are generated by ! 1054: calls to ! 1055: .I tymatch ! 1056: and ! 1057: .I ptmatch , ! 1058: both of which are given a tree, and asked to make the ! 1059: operands agree in type. ! 1060: .I Ptmatch ! 1061: treats the case where one of the operands is a pointer; ! 1062: .I tymatch ! 1063: treats all other cases. ! 1064: Where these routines have decided on the ! 1065: proper type for an operand, they call ! 1066: .I makety , ! 1067: which is handed a tree, and a type word, dimension offset, and size offset. ! 1068: If necessary, it inserts a conversion operation to make the ! 1069: types correct. ! 1070: Conversion operations are never inserted on the left side of ! 1071: assignment operators, however. ! 1072: There are two conversion operators used; ! 1073: PCONV, if the conversion is to a non-basic type (usually a pointer), ! 1074: and ! 1075: SCONV, if the conversion is to a basic type (scalar). ! 1076: .PP ! 1077: To allow for maximum flexibility, every node produced by ! 1078: .I buildtree ! 1079: is given to a machine dependent routine, ! 1080: .I clocal , ! 1081: immediately after it is produced. ! 1082: This is to allow more or less immediate rewriting of those ! 1083: nodes which must be adapted for the local machine. ! 1084: The conversion operations are given to ! 1085: .I clocal ! 1086: as well; on most machines, many of these ! 1087: conversions do nothing, and should be thrown away ! 1088: (being careful to retain the type). ! 1089: If this operation is done too early, ! 1090: however, ! 1091: later calls to ! 1092: .I buildtree ! 1093: may get confused about correct type of the ! 1094: subtrees; ! 1095: thus ! 1096: .I clocal ! 1097: is given the conversion operations only after the entire tree is built. ! 1098: This topic will be dealt with in more detail later. ! 1099: .SH ! 1100: Initialization ! 1101: .PP ! 1102: Initialization is one of the messier areas in the portable compiler. ! 1103: The only consolation is that most of the mess takes place ! 1104: in the machine independent part, where it ! 1105: is may be safely ignored by the implementor of the ! 1106: compiler for a particular machine. ! 1107: .PP ! 1108: The basic problem is that the semantics of initialization ! 1109: really calls for a co-routine structure; one collection ! 1110: of programs reading constants from the input stream, while another, ! 1111: independent set of programs places these constants into the ! 1112: appropriate spots in memory. ! 1113: The dramatic differences in the local assemblers also ! 1114: come to the fore here. ! 1115: The parsing problems are dealt with by keeping a rather ! 1116: extensive stack containing the current ! 1117: state of the initialization; the assembler ! 1118: problems are dealt with by having a fair number of machine dependent routines. ! 1119: .PP ! 1120: The stack contains the symbol table number, ! 1121: type, dimension index, and size index for the current identifier ! 1122: being initialized. ! 1123: Another entry has the offset, in bits, of the beginning ! 1124: of the current identifier. ! 1125: Another entry keeps track of how many elements have been seen, ! 1126: if the current identifier is an array. ! 1127: Still another entry keeps track of the current ! 1128: member of a structure being initialized. ! 1129: Finally, there is an entry containing flags ! 1130: which keep track of the current state of the initialization process ! 1131: (e.g., tell if a `}' has been seen for the current identifier). ! 1132: .PP ! 1133: When an initialization begins, the routine ! 1134: .I beginit ! 1135: is called; it handles the alignment restrictions, if ! 1136: any, and calls ! 1137: .I instk ! 1138: to create the stack entry. ! 1139: This is done by first making an entry on the top of the stack for the item ! 1140: being initialized. ! 1141: If the top entry is an array, another entry is made on the stack ! 1142: for the first element. ! 1143: If the top entry is a structure, another entry is made on the ! 1144: stack for the first member of the structure. ! 1145: This continues until the top element of the stack is a scalar. ! 1146: .I Instk ! 1147: then returns, and the parser begins collecting initializers. ! 1148: .PP ! 1149: When a constant is obtained, the routine ! 1150: .I doinit ! 1151: is called; it examines the stack, and does whatever ! 1152: is necessary to assign the current constant to the ! 1153: scalar on the top of the stack. ! 1154: .I gotscal ! 1155: is then called, which rearranges the stack so that the ! 1156: next scalar to be initialized gets placed on top of the stack. ! 1157: This process continues until the end of the initializers; ! 1158: .I endinit ! 1159: cleans up. ! 1160: If a `{' or `}' is encountered in the ! 1161: string of initializers, it is handled by calling ! 1162: .I ilbrace ! 1163: or ! 1164: .I irbrace , ! 1165: respectively. ! 1166: .PP ! 1167: A central issue is the treatment of the ``holes'' that ! 1168: arise as a result of alignment restrictions or explicit ! 1169: requests for holes in bit fields. ! 1170: There is a global variable, ! 1171: .I inoff , ! 1172: which contains the current offset in the initialization ! 1173: (all offsets in the first pass of the compiler are in bits). ! 1174: .I Doinit ! 1175: figures out from the top entry on the stack the expected ! 1176: bit offset of the next identifier; it calls the ! 1177: machine dependent ! 1178: routine ! 1179: .I inforce ! 1180: which, in a machine dependent way, forces ! 1181: the assembler to ! 1182: set aside space if need be so that the ! 1183: next scalar seen will go into the appropriate ! 1184: bit offset position. ! 1185: The scalar itself is passed to one of the machine dependent ! 1186: routines ! 1187: .I fincode ! 1188: (for floating point initialization), ! 1189: .I incode ! 1190: (for fields, and other initializations less than an int in ! 1191: size), ! 1192: and ! 1193: .I cinit ! 1194: (for all other initializations). ! 1195: The size is passed to all these routines, and it is up to ! 1196: the machine dependent routines to ensure that the ! 1197: initializer occupies exactly the right size. ! 1198: .PP ! 1199: Character strings represent a bit of an exception. ! 1200: If a character string is seen as the initializer for ! 1201: a pointer, the characters making up the string must ! 1202: be put out under a different location counter. ! 1203: When the lexical analyzer sees the quote at the head ! 1204: of a character string, it returns the token STRING, ! 1205: but does not do anything with the contents. ! 1206: The parser calls ! 1207: .I getstr , ! 1208: which sets up the appropriate location counters ! 1209: and flags, and calls ! 1210: .I lxstr ! 1211: to read and process the contents of the string. ! 1212: .PP ! 1213: If the string is being used to initialize a character array, ! 1214: .I lxstr ! 1215: calls ! 1216: .I putbyte , ! 1217: which in effect simulates ! 1218: .I doinit ! 1219: for each character read. ! 1220: If the string is used to initialize a character pointer, ! 1221: .I lxstr ! 1222: calls a machine dependent routine, ! 1223: .I bycode , ! 1224: which stashes away each character. ! 1225: The pointer to this string is then returned, ! 1226: and processed normally by ! 1227: .I doinit . ! 1228: .PP ! 1229: The null at the end of the string is treated as if it ! 1230: were read explicitly by ! 1231: .I lxstr . ! 1232: .SH ! 1233: Statements ! 1234: .PP ! 1235: The first pass addresses four main areas; declarations, expressions, initialization, and statements. ! 1236: The statement processing is relatively simple; most of it is carried out in the ! 1237: parser directly. ! 1238: Most of the logic is concerned with allocating ! 1239: label numbers, defining the labels, and branching appropriately. ! 1240: An external symbol, ! 1241: .I reached , ! 1242: is 1 if a statement can be reached, 0 otherwise; this is ! 1243: used to do a bit of simple flow analysis as the program is being parsed, ! 1244: and also to avoid generating the subroutine return sequence if the subroutine ! 1245: cannot ``fall through'' the last statement. ! 1246: .PP ! 1247: Conditional branches are handled by generating an expression ! 1248: node, CBRANCH, ! 1249: whose left descendant is the conditional expression and the ! 1250: right descendant is an ICON node containing the internal label ! 1251: number to be branched to. ! 1252: For efficiency, the semantics are that ! 1253: the label is gone to if the condition is ! 1254: .I false . ! 1255: .PP ! 1256: The switch statement is ! 1257: compiled by collecting the case entries, and an indication as to whether ! 1258: there is a default case; ! 1259: an internal label number is generated for each of these, ! 1260: and remembered in a big array. ! 1261: The expression comprising the value to be switched on is ! 1262: compiled when the switch keyword is encountered, ! 1263: but the expression tree is headed by ! 1264: a special node, FORCE, which tells the code generator to ! 1265: put the expression value into a special distinguished ! 1266: register (this same mechanism is used for processing the ! 1267: return statement). ! 1268: When the end of the switch block is reached, the array ! 1269: containing the case values is sorted, and checked for ! 1270: duplicate entries (an error); if all is ! 1271: correct, the machine dependent routine ! 1272: .I genswitch ! 1273: is called, with this array of labels and values in increasing order. ! 1274: .I Genswitch ! 1275: can assume that the value to be tested is already in the ! 1276: register which is the usual integer return value register. ! 1277: .SH ! 1278: Optimization ! 1279: .PP ! 1280: There is a machine independent file, ! 1281: .I optim.c , ! 1282: which contains a relatively short optimization routine, ! 1283: .I optim . ! 1284: Actually the word optimization is something of a misnomer; ! 1285: the results are not optimum, only improved, and the ! 1286: routine is in fact not optional; it must ! 1287: be called for proper operation of the compiler. ! 1288: .PP ! 1289: .I Optim ! 1290: is called after an expression tree is built, but ! 1291: before the code generator is called. ! 1292: The essential part of its job is to call ! 1293: .I clocal ! 1294: on the conversion operators. ! 1295: On most machines, the treatment of ! 1296: \fB&\fP is also essential: ! 1297: by this time in the processing, the only node which ! 1298: is a legal descendant of \fB&\fP is NAME. ! 1299: (Possible descendants of \fB*\fP have been eliminated by ! 1300: .I buildtree .) ! 1301: The address of a static name is, almost by definition, a ! 1302: constant, and can be represented by an ICON node on most machines ! 1303: (provided that the loader has enough power). ! 1304: Unfortunately, this is not universally true; on some machine, such as the IBM 370, ! 1305: the issue of addressability rears its ugly head; ! 1306: thus, before turning a NAME node into an ICON node, ! 1307: the machine dependent function ! 1308: .I andable ! 1309: is called. ! 1310: .PP ! 1311: The optimization attempts of ! 1312: .I optim ! 1313: are quite limited. ! 1314: It is primarily concerned with improving the behavior of ! 1315: the compiler with operations one of whose arguments is a constant. ! 1316: In the simplest case, the constant is placed on the right if the ! 1317: operation is commutative. ! 1318: The compiler also makes a limited search for expressions ! 1319: such as ! 1320: .DS ! 1321: ( \fIx\fP + \fIa\fP ) + \fIb\fP ! 1322: .DE ! 1323: where ! 1324: .I a ! 1325: and ! 1326: .I b ! 1327: are constants, and attempts to combine ! 1328: .I a ! 1329: and ! 1330: .I b ! 1331: at compile time. ! 1332: A number of special cases are also examined; ! 1333: additions of 0 and multiplications by 1 are removed, ! 1334: although the correct processing of these cases to get ! 1335: the type of the resulting tree correct is ! 1336: decidedly nontrivial. ! 1337: In some cases, the addition or multiplication must be replaced by ! 1338: a conversion operator to keep the types from becoming ! 1339: fouled up. ! 1340: In cases where a relational operation is being done ! 1341: and one operand is a constant, the operands are permuted and the operator altered, if necessary, ! 1342: to put the constant on the right. ! 1343: Finally, multiplications by a power of 2 are changed to shifts. ! 1344: .SH ! 1345: Machine Dependent Stuff ! 1346: .PP ! 1347: A number of the first pass machine dependent routines have been discussed above. ! 1348: In general, the routines are short, and easy to adapt from ! 1349: machine to machine. ! 1350: The two exceptions to this general rule are ! 1351: .I clocal ! 1352: and ! 1353: the function prolog and epilog generation routines, ! 1354: .I bfcode ! 1355: and ! 1356: .I efcode . ! 1357: .PP ! 1358: .I Clocal ! 1359: has the job of rewriting, if appropriate and desirable, ! 1360: the nodes constructed by ! 1361: .I buildtree . ! 1362: There are two major areas where this ! 1363: is important: ! 1364: NAME nodes and conversion operations. ! 1365: In the case of NAME nodes, ! 1366: .I clocal ! 1367: must rewrite the NAME node to reflect the ! 1368: actual physical location of the name in the machine. ! 1369: In effect, the NAME node must be examined, the symbol table ! 1370: entry found (through the ! 1371: .I rval ! 1372: field of the node), ! 1373: and, based on the storage class of the node, ! 1374: the tree must be rewritten. ! 1375: Automatic variables and parameters are typically ! 1376: rewritten by treating the reference to the variable as ! 1377: a structure reference, off the register which ! 1378: holds the stack or argument pointer; ! 1379: the ! 1380: .I stref ! 1381: routine is set up to be called in this way, and to ! 1382: build the appropriate tree. ! 1383: In the most general case, the tree consists ! 1384: of a unary \fB*\fP node, whose descendant is ! 1385: a \fB+\fP node, with the stack or argument register as left operand, ! 1386: and a constant offset as right operand. ! 1387: In the case of LABEL and internal static nodes, the ! 1388: .I rval ! 1389: field is rewritten to be the negative of the internal ! 1390: label number; a negative ! 1391: .I rval ! 1392: field is taken to be an internal label number. ! 1393: Finally, a name of class REGISTER must be converted into a REG node, ! 1394: and the ! 1395: .I rval ! 1396: field replaced by the register number. ! 1397: In fact, this part of the ! 1398: .I clocal ! 1399: routine is nearly machine independent; only for machines ! 1400: with addressability problems (IBM 370 again!) does it ! 1401: have to be noticeably different. ! 1402: .PP ! 1403: The conversion operator treatment is rather tricky. ! 1404: It is necessary to handle the application of conversion operators ! 1405: to constants in ! 1406: .I clocal , ! 1407: in order that all constant expressions can have their values known ! 1408: at compile time. ! 1409: In extreme cases, this may mean that some simulation of the ! 1410: arithmetic of the target machine might have to be done in a ! 1411: cross-compiler. ! 1412: In the most common case, ! 1413: conversions from pointer to pointer do nothing. ! 1414: For some machines, however, conversion from byte pointer to short or long ! 1415: pointer might require a shift or rotate operation, which would ! 1416: have to be generated here. ! 1417: .PP ! 1418: The extension of the portable compiler to machines where the size of a pointer ! 1419: depends on its type would be straightforward, but has not yet been done. ! 1420: .PP ! 1421: Another machine dependent issue in the first pass ! 1422: is the generation of external ``symbol table'' information. ! 1423: This sort of symbol table is used by programs such as symbolic debuggers ! 1424: to relate object code back to source code. ! 1425: Symbol table routines are provided in ! 1426: the file \fIstab.c\fP, ! 1427: which is included in the machine dependent sources ! 1428: for the first pass. ! 1429: The symbol table routines insert assembly code ! 1430: containing assembly pseudo-ops directly into ! 1431: the instruction stream generated by the compiler. ! 1432: .PP ! 1433: There are two basic kinds of symbol table operations. ! 1434: The simplest operation is the generation of a source line number; ! 1435: this serves to map an address in an executable image ! 1436: into a line in a source file so that a debugger ! 1437: can find the source code ! 1438: corresponding to the instructions being executed. ! 1439: The routine \fIpsline\fP is called by the scanner ! 1440: to emit source line numbers when ! 1441: a nonempty source line is seen. ! 1442: The other variety of symbol table operation ! 1443: is the generation of type and address information ! 1444: about C symbols. ! 1445: This is done through the \fIoutstab\fP routine, ! 1446: which is normally called using the FIXDEF macro ! 1447: in the monster \fIdefid\fP routine in \fIpftn.c\fP ! 1448: that enters symbols into the compiler's internal symbol table. ! 1449: .PP ! 1450: Yet another major machine dependent issue involves function prolog and epilog ! 1451: generation. ! 1452: The hard part here is the design of the stack frame ! 1453: and calling sequence; this design issue is discussed elsewhere. ! 1454: .[ ! 1455: Johnson Lesk Ritchie calling sequence ! 1456: .] ! 1457: The routine ! 1458: .I bfcode ! 1459: is called with the number of arguments ! 1460: the function is defined with, and ! 1461: an array containing the symbol table indices of the ! 1462: declared parameters. ! 1463: .I Bfcode ! 1464: must generate the code to establish the new stack frame, ! 1465: save the return address and previous stack pointer ! 1466: value on the stack, and save whatever ! 1467: registers are to be used for register variables. ! 1468: The stack size and the number of register variables is not ! 1469: known when ! 1470: .I bfcode ! 1471: is called, so these numbers must be ! 1472: referred to by assembler constants, which are ! 1473: defined when they are known (usually in the second pass, ! 1474: after all register variables, automatics, and temporaries have been seen). ! 1475: The final job is to find those parameters which may have been declared ! 1476: register, and generate the code to initialize ! 1477: the register with the value passed on the stack. ! 1478: Once again, for most machines, the general logic of ! 1479: .I bfcode ! 1480: remains the same, but the contents of the ! 1481: .I printf ! 1482: calls in it will change from machine to machine. ! 1483: .I efcode ! 1484: is rather simpler, having just to generate the default ! 1485: return at the end of a function. ! 1486: This may be nontrivial in the case of a function returning a structure or union, however. ! 1487: .PP ! 1488: There seems to be no really good place to discuss structures and unions, but ! 1489: this is as good a place as any. ! 1490: The C language now supports structure assignment, ! 1491: and the passing of structures as arguments to functions, ! 1492: and the receiving of structures back from functions. ! 1493: This was added rather late to C, and thus to the portable compiler. ! 1494: Consequently, it fits in less well than the older features. ! 1495: Moreover, most of the burden of making these features work is ! 1496: placed on the machine dependent code. ! 1497: .PP ! 1498: There are both conceptual and practical problems. ! 1499: Conceptually, the compiler is structured around ! 1500: the idea that to compute something, you put it into ! 1501: a register and work on it. ! 1502: This notion causes a bit of trouble on some machines (e.g., machines with 3-address opcodes), but ! 1503: matches many machines quite well. ! 1504: Unfortunately, this notion breaks down with structures. ! 1505: The closest that one can come is to keep the addresses of the ! 1506: structures in registers. ! 1507: The actual code sequences used to move structures vary from the ! 1508: trivial (a multiple byte move) to the horrible (a ! 1509: function call), and are very machine dependent. ! 1510: .PP ! 1511: The practical problem is more painful. ! 1512: When a function returning a structure is called, this function ! 1513: has to have some place to put the structure value. ! 1514: If it places it on the stack, it has difficulty popping its stack frame. ! 1515: If it places the value in a static temporary, the routine fails to be ! 1516: reentrant. ! 1517: The most logically consistent way of implementing this is for the ! 1518: caller to pass in a pointer to a spot where the called function ! 1519: should put the value before returning. ! 1520: This is relatively straightforward, although a bit tedious, to implement, ! 1521: but means that the caller must have properly declared ! 1522: the function type, even if the value is never used. ! 1523: On some machines, such as the Interdata 8/32, the return value ! 1524: simply overlays the argument region (which on the 8/32 is part ! 1525: of the caller's stack frame). ! 1526: The caller takes care of leaving enough room if the returned value is larger ! 1527: than the arguments. ! 1528: This also assumes that the caller declares the ! 1529: function properly. ! 1530: .PP ! 1531: The PDP-11 and the \*V have stack hardware which is used in function calls and returns; ! 1532: this makes it very inconvenient to ! 1533: use either of the above mechanisms. ! 1534: In these machines, a static area within the called function ! 1535: is allocated, and ! 1536: the function return value is copied into it on return; the function ! 1537: returns the address of that region. ! 1538: This is simple to implement, but is non-reentrant. ! 1539: However, the function can now be called as a subroutine ! 1540: without being properly declared, without the disaster which would otherwise ensue. ! 1541: No matter what choice is taken, the convention is that the function ! 1542: actually returns the address of the return structure value. ! 1543: .PP ! 1544: In building expression trees, the portable compiler takes a bit for granted about ! 1545: structures. ! 1546: It assumes that functions returning structures ! 1547: actually return a pointer to the structure, and it assumes that ! 1548: a reference to a structure is actually a reference to its address. ! 1549: The structure assignment operator is rebuilt so that the left ! 1550: operand is the structure being assigned to, but the ! 1551: right operand is the address of the structure being assigned; ! 1552: this makes it easier to deal with ! 1553: .DS ! 1554: .I "a = b = c" ! 1555: .DE ! 1556: and similar constructions. ! 1557: .PP ! 1558: There are four special tree nodes associated with these ! 1559: operations: ! 1560: STASG (structure assignment), STARG (structure argument ! 1561: to a function call), and STCALL and UNARY STCALL ! 1562: (calls of a function with nonzero and zero arguments, respectively). ! 1563: These four nodes are unique in that the size and alignment information, which can be determined by ! 1564: the type for all other objects in C, ! 1565: must be known to carry out these operations; special ! 1566: fields are set aside in these nodes to contain ! 1567: this information, and special ! 1568: intermediate code is used to transmit this information. ! 1569: .SH ! 1570: First Pass Summary ! 1571: .PP ! 1572: There are may other issues which have been ignored here, ! 1573: partly to justify the title ``tour'', and partially ! 1574: because they have seemed to cause little trouble. ! 1575: There are some debugging flags ! 1576: which may be turned on, by giving the compiler's first pass ! 1577: the argument ! 1578: .DS ! 1579: .B \-X [flags] ! 1580: .DE ! 1581: Some of the more interesting flags are ! 1582: \fB\-Xd\fP for the defining and freeing of symbols, ! 1583: \fB\-Xi\fP for initialization comments, and ! 1584: \fB\-Xb\fP for various comments about the building of trees. ! 1585: In many cases, repeating the flag more than once gives more information; ! 1586: thus, ! 1587: \fB\-Xddd\fP gives more information than \fB\-Xd\fP. ! 1588: In the two pass version of the compiler, the ! 1589: flags should not be set when the output is sent to the second ! 1590: pass, since the debugging output and the intermediate code both go onto the standard ! 1591: output. ! 1592: .PP ! 1593: We turn now to consideration of the second pass.
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.