Evaluation of Automatically-Generated Compilers Anthony M. Sloane Department of Computer Science James Cook University Townsville , QLD , 4811 AUSTRALIA Anthony.Sloane@jcu.edu.au Technical Report 94/6 September 9 , 1994 Abstract Compilers or language translators can be generated using a variety of formal specification techniques . Whether generation is worthwhile depends on the effort required to specify the translation task and the quality of the generated compiler . This paper reports the results from a systematic comparison of a hand-coded translator for the Icon programming language with one generated by the Eli compiler construction system . A direct comparison can be made since the generated program performs the same translation as the hand-coded program . The results of the comparison show that efficient compilers can be generated from specifications that are much smaller and more problem-oriented than the equivalent source code . We also show that further work must be done to reduce the dynamic memory usage of generated compilers . 1 Introduction Software systems research includes the development of new techniques for constructing general-purpose software systems . Where a new approach has equivalent or similar expressive power to an existing approach it is necessary to provide performance measurements to allow them to be compared . Also , analysis of the effort required to use different approaches is important . Consequently , systems research should include the following : 1 -RRB- definition , 2 -RRB- implementation , and 3 -RRB- evaluation . The definition phase involves identifying a problem and defining a solution . Implementation is necessary to turn the solution into a concrete form . -LRB- Often problems with the solution are not noticed until implementation is attempted . -RRB- Finally , evaluation compares the solution implementation with other solutions of similar or identical problems . Evaluation of a new approach serves two broad purposes depending on the outcome of experiments . Positive results indicate to other developers or researchers that the new approach is worth considering . Negative results help identify ways in which the new approach is deficient ; future development can address these deficiencies . It is important for evaluation to be carried out at regular intervals . Without timely comparison , research can be overtaken by practice resulting in wasted research effort . Conversely , much development effort can be wasted if improved approaches are not publicised . Considerable progress has been made towards the goal of automatically generating programming language compilers . Using specialised notations it is possibleto specify compilation sub-tasks such as lexical analysis -LSB- 22 , 17 , 9 , 16 , 1 -RSB- , parsing -LSB- 18 , 23 , 2 , 8 -RSB- , and semantic analysis -LSB- 24 , 3 , 21 , 27 -RSB- . Other compiler tasks such as code generation for complex architectures have partially yielded to attack and are the subject of continuing research -LSB- 4 , 6 -RSB- . Libraries of existing infrastructure can be used to combine solutions for sub-tasks into a complete compiler implementation -LSB- 11 -RSB- . Proponents of automatic compiler generation argue that it is a viable technique for producing compilers that would normally be coded by hand -LRB- e.g. , see -LSB- 21 , 11 -RSB- -RRB- . This claim must be validated by comparing the generation of compilers with the production of compilers without the use of generators . Evaluation should be carried out often enough to enable cross-pollenation to occur and isolation to be avoided . The potential benefits are large because improvements resulting from evaluation will be available to all users of a generation system . In contrast , improved techniques for hand-coding compilers are often not widely publicised and may be ? reinvented ? by many developers . Previous work evaluating the performance of generated compilers has largely concentrated on subtasks of the compilation problem . Lexical analyser generators have been compared with each other -LSB- 17 , 9 , 1 -RSB- and with the ? minimal ? lexical analyser : a program that examines each input character once without any further processing -LSB- 10 -RSB- . Similarly , the performance of parser generators has been examined -LRB- e.g. , see -LSB- 29 , 14 -RSB- -RRB- . Tofte reports timing results from a comparison of two generated code generators for the same simple language -LSB- 27 -RSB- . Comparatively little work has evaluated complete generated compilers . One study compared different ways of specifying the same compiler from a notational point of view -LSB- 30 -RSB- . Based on the same input language detailed experiments were performed to identify problems with generation tools -LSB- 10 -RSB- . Some comparison of generated scanners with hand-coded scanners was performed but was not extended to other compilation phases . Lee summarises results obtained measuring the performance of compilers generated from denotational specifications -LSB- 21 , p. 47 -RSB- . The generated compilers measured were between 25 % and 50 % slower than hand-written ones . Also , the code produced by the generated compilers was in an intermediate form that imposed significant time penalties compared to compiled code . Lee also reports performance results for compilers generated by his MESS system -LSB- 21 -RSB- . MESS-generated compilers generate good object code compared to compilers for related languages . Two main deficiencies in previous work are addressed by this paper : 1 -RRB- a lack of evaluation of complete generated compilers , and 2 -RRB- limited comparisons of generated compilers with hand-written ones . While independent evaluation of generated compiler components serves a purpose for tool developers , users rarely use these components in isolation . Since complete compilers are being generated , complete compilers should be evaluated . Similarly , it is useful for tool developers to know how their tools shape up against other tools . The ultimate test of a compiler generation system , however , is against the predominant compiler construction technique : hand coding . This paper reports the results of a comparison between a compiler generated by the Eli compiler con - struction system -LSB- 11 -RSB- and an equivalent existing compiler written largely by hand . To enable direct comparison , the generated compiler was constructed to duplicate the functionality of the existing compiler . We compare the construction methods along the dimensions of the amount of information the compiler writer must provide , and how long it takes to actually construct the compiler given that information . We also compare the quality of the two compilers by measuring their performance compiling a large suite of programs . Both time and space consumption are considered . Section 2 describes the functionality of the compilers and the test program suite used , while the next section summarises our results . We found that compiler generation techniques offer notational advantages because specifications are shorter than the equivalent code and are more closely related to the problem domain . The generated compiler is usually faster than the hand-written compiler but is much larger and consumes a lot more dynamic memory . Section 4 contains a detailed analysis of some of the more extreme measurement results . In particular , we consider the reasons why the generated compiler performs well and discuss areas for improvement . Finally , we analyse the reasons for the excessive memory consumption by the generated compiler . 2 Two Compilers and Their Input Building a full-scale compiler for a general-purpose programming language is a significant effort . For practical reasons it was necessary to find a language that did not require an inordinate amount of work to compile . At the same time it had to be complex enough to enable realistic evaluation . The Icon programming language -LSB- 12 -RSB- was chosen because translation of Icon is of intermediate difficulty and a welldocumented implementation of the language is freely available -LSB- 13 -RSB- . Icon is a general-purpose procedural language with particularly good support for string processing and high-level data structures such as tables and lists . More unusual features included in Icon are goal-directed evaluation , generators and co-expressions . 2.1 Icont The baseline for the experiment was provided by the program Icont , part of the Icon implementation from the University of Arizona .1 Icont translates Icon programs into a target form called Ucode -LSB- 13 -RSB- . Ucode is a stack-based , postfix language designed explicitly for implementing Icon programs but similar in style to conventional assembly languages . The distributed version of Icont was modified in the following ways : 1 . Invocation of the Icon pre-processor was disabled . Since we were not interested in measuring the implementation of the pre-processor its functionality was not duplicated . 2 . Icont as distributed contains code to link the Ucode for multiple input files together and to also invoke the generated program using a separate interpreter . This code was removed because it was unrelated to the translation task . 1This paper is based on version 8.10 of the Arizona distribution . Minimum Maximum Average Bytes 61 47067 4617 Lines 5 1265 160 Tokens 8 8411 642 Table 1 : Characteristics of the Icon program test suite . 3 . Icont outputs a variety of messages indicating its progress during translation -LRB- mainly procedure names as they are processed -RRB- . The code to generate these messages was removed to avoid biasing measurements with unnecessary output . 2.2 EliIcont Icont was compared to an Icon translator constructed using the Eli compiler construction system -LSB- 11 -RSB- -LRB- hereafter referred to as EliIcont -RRB- . EliIcont was specifically designed to produce the same Ucode output as Icont , except for label numbering . To reproduce the label numbering algorithm of Icont would have introduced code that would clearly not be written by anyone constructing the translator for any purpose other than comparison . The labels generated by EliIcont are placed in the same places as those generated by Icont and there is a one-to-one mapping between them . In all other respects the Ucode generated by EliIcont is identical to that produced by Icont . No tuning of either EliIcont or Icont was conducted for the purposes of the experiment . The specifications of EliIcont were ? frozen ? as soon as the functionality of Icont was duplicated . Also , no changes were made to Eli in an attempt to improve the output generated . 2.3 The Test Suite The two programs were compared usinga suite of 472 source files obtained from the University of Arizona Icon distribution . Every Icon program file from the distribution was included as distributed , except that those requiring pre-processing were pre-processed first . Their sizes by various measures are summarised in Table 1 . The majority of the files are real applications or parts thereof , including graphics programs , text processing applications , and various games . Thus the results reported later in this paper apply to a wide variety of typical Icon programs . The suite also provides a particularly good basis for a comparison of translator functionality because it includes inputs designed to fully test the Arizona implementation . This fact gives us confidence that EliIcont does in fact duplicate the functionality of Icont . 3 Results This paper concentrates on two attributes of compiler construction techniques which can be used for evaluation : effort and quality . This section summarises measurements of these attributes of Icont and EliIcont . Section 4 analyses the performance of the translators in more detail . Total Lexical Anal . Parsing Code Generation Misc . Decl Oper Decl Oper Decl Oper Decl Oper Decl Oper Icont 5675 717 909 1415 2634 343 5332 29 688 278 631 36 1379 2634 EliIcont 2534 323 169 1919 3 1826 708 10 433 169 1644 275 3 Table 2 : Specification Sizes -LRB- non-commented non-blank lines -RRB- . All measurements reported in this paper were performed on a DEC 3000/500 Alpha workstation running DEC OSF/1 AXP V2 .0 . All files were stored on a local disk . Timing measurements were conducted when the system had a light to moderate load . 3.1 Specification Size One way to assess the effort required to use a program construction method is to analyse the information that must be provided by the user . There are two categories of information that are used to construct our two compilers : operational specifications and declarative specifications . The former comprises code written in a general-purpose high-level language -LRB- in our case , C -RRB- . Declarative specifications are written in problem-specific notations and processed by tools to produce operational code . Table 2 summarises the sizes of the specifications of Icont and EliIcont .2 The two programs have the same basic structure . They both parse the input text and create an abstract tree representing the entire program . The abstract tree is then traversed to emit code . The ? Parsing ? column of Table 2 includes tree construction . ? Code Generation ? includes semantic analysis because the two sub-tasks are intertwined in both compilers . EliIcont is constructed mostly from declarative specifications with a small amount of supporting code . The declarative specifications are : 1 . A small set of regular expressions for lexical analysis . 2 . A concrete grammar for parsing . 3 . A five line specification to control tree construction . 4 . Just over 1500 lines of attribute grammar code to perform semantic analysis and code generation . 5 . A short specification of output structure . The supporting code is split about two-thirds to lexical analysis and one-third to output routines . The lexical analysis code deals with complexities of Icon such as the insertion of semicolons at the ends of line 2The Icont measurements include a small amount of configuration code which is shared with other parts of the Arizona Icon distribution . under various circumstances , handling multi-line strings with character escapes , and processing #line directives -LRB- similar to those supported by C -RRB- .3 Icont is built mostly from operational specifications . Declarative specifications are used for the parsing grammar and tables of operators and keywords . A hand-written scanner provides tokens for a YACC - generated parser . Parsing actions invoke tree construction routines and a tree walker emits code . Overall EliIcont requires specifications less than half the size of those required by Icont . Code generation is more verbose in the attribute grammar formalism , but otherwise the phases of EliIcont require much smaller specifications . The major differences are : ffl Icont 's lexical analysis phase is almost completely operational . The only declarative part is a table of operators . In contrast , the ? easy ? bits of EliIcont 's lexical analyser are specified with one line each . Only the complex parts -LRB- see above -RRB- require operational code . ffl Icont uses YACC for parsing but requires extra code to construct the abstract tree . Almost all of the tree construction necessary in EliIcont is provided automatically by Eli based on an analysis of the parsing and abstract grammars . ffl The Icont tree traversal for code generation is directly coded so it is hard to determine what -LRB- if any -RRB- side-effects there may be if the tree structure is changed . Since EliIcont uses an attribute grammar formalism tree traversals are computed automatically from dependences that reflect the structure of the output code . ffl Eli provides extensive infrastructure support , so almost no specification is needed other than for the translation tasks themselves .4 The code for Icont contains a large amount of infrastructure support including memory allocation , string manipulation , command-line processing and a driver to control the compilation phases . In summary , the support that Eli provides enables compiler writers to more easily concentrate on the translation problem rather than peripheral details . Eli 's philosophy -LSB- 11 -RSB- is to make the common things easy to do and to provide mechanisms by which more difficult tasks can be accommodated . This approach particularly pays off for EliIcont for lexical analysis , tree construction , automatic generation of tree traversal algorithms , and compiler infrastructure . Eli can be asked to provide complete source code so that a compiler implementation can be transported to sites where Eli is not present . The source code generated by Eli for EliIcont is much larger than the specifications provided by the user . For EliIcont , the total size is about twenty-four thousand noncommented non-blank lines in 86 files . Of this , about 80 % is generated code , 17 % is from Eli libraries , and the rest is the operational portion of the specifications . The generated code is mostly lexical analysis -LRB- 12 % -RRB- , parsing and tree construction -LRB- 28 % -RRB- , and code generation -LRB- 59 % -RRB- . 3This ratio of declarative to operational specifications for lexical analysis is not typical for Eli-generated compilers . It is usually the case that little or no operational specification is needed . 4The only miscellaneous specification is a three line description of the compiler 's command line . Icont EliIcont -LRB- from specs -RRB- -LRB- from source -RRB- -LRB- from specs -RRB- -LRB- from source -RRB- Real 27 20 231 49 User 13 10 52 22 System 6 4 47 11 Table 3 : Real , user and system time to generate dynamically linked executables for the compilers -LRB- in seconds averaged over ten runs -RRB- . 3.2 Generation Time Another measure of the utility of a compiler generation method is the amount of time it takes to process the specifications to produce the compiler . Icont and EliIcont can be built in two ways : from a mixture of declarative and operational specifications , or from entirely operational specifications where the declarative specifications have been replaced by generated code . Table 3 gives the time required to generate the compilers . Note that some of the time shown in the fourth column is not present in the third column because Eli contains much of its library in a pre-compiled form . It is no surprise that the overhead of Eli dominates the generation times because a large amount of analysis is needed even to generate source code , let alone compile the generated code . Also , as we saw in the previous section , Eli generates a lot more source code to implement EliIcont than is present in Icont . Nevertheless , the generation time is not prohibitive and , once the compiler has been generated , the complete sources are available for faster builds -LRB- column four of Table 3 -RRB- . 3.3 Compiler Execution Time To measure the relative speed of the two translators they were both instrumented usingATOM -LSB- 26 -RSB- . ATOM uses binary modification techniques to enable a large variety of performance analysis tools to be constructed -LSB- 5 -RSB- . ATOM was also used to collect the memory utilisation measurements reported later in the paper . The ATOM-based tool used for execution time measurements is a re-implementation of the gprof tool -LSB- 7 -RSB- which produces call-graph-based execution profiles . The original gprof used program counter sampling to estimate execution time . In contrast , the ATOM version uses the Alpha AXP cycle counter -LSB- 25 -RSB- to enable exact execution times to be collected . Also , gprof apportions execution time to the profile collection routine , so profiles are not exact representations of non-profiled execution . The ATOM version does not have this drawback . All execution times reported in this paper are in terms of Alpha AXP machine cycles . A benefit of the exact measurements obtainable with ATOM is that processing of small inputs can be used without the measurements being affected by measuring overhead or the granularity of the timing mechanism . Only user-level cycle counts were collected to remove perturbations due to factors outside the scope of this paper -LRB- such as operating system overhead and architectural features such caching -RRB- . Thus the figures reported are independent of system load . 5 10 15 20 25 30 35 40 45 50 -30 -25 -20 -15 -10 -5 5 10 15 20 25 30 Frequency Relative percentage of execution cycles Figure 1 : The execution time of EliIcont relative to the execution time of Icont . Zero on the X-axis represents the runtime of Icont . Lines to the left of zero -LRB- inclusive -RRB- indicate programs for which EliIcont was faster than Icont . Lexical Parsing Tree Code Output Analysis Construction Generation Icont 22 16 3 3 55 EliIcont 9 22 5 10 54 Table 4 : Execution time attributed to the major compiler sub-tasks . Both Icont and EliIcont were compiled with the OSF C compiler using the highest level of optimisation -LRB- - O3 option -RRB- . Optimisations performed at this level include global register allocation and extensive procedure inlining . The executables were statically linked to avoid runtime overheads associated with dynamic linking and to enable them to be processed by ATOM . Figure 1 summarises the execution times of the two programs running on the complete test suite . Each vertical line represents a subset of the test programs . The percentage axis indicates the cycles taken by EliIcont to process those inputs relative to the cycles taken by Icont on the same inputs . EliIcont processes 425 of the 472 programs -LRB- 90 % -RRB- faster than Icont . Averaged over the whole test suite EliIcont is approximately 5.5 % faster . Table 4 gives approximate percentages allocating the runtime of the two compilers to their major subtasks while translating the largest application file in the test suite -LRB- an X11 mouse-based text widget -RRB- .5 For this program , the execution time of the two compilers differs by less than one percent . The ? Code Generation ? column does not include the time spent actually performing the output ; that time is reported 5The source file for the widget consists of 1281 lines of code containing 8838 tokens in 47 kilobytes . The output generated by the translators for this program contains about 170 kilobytes . 8 Memory Category Icont EliCont Text 98 253 Initialised Data 49 65 Uninitialised Data 20 23 Heap 569 1580 Table 5 : Sizes of memory used by Icont and EliIcont -LRB- in kilobytes -RRB- . Heap consumption is the maximum amount allocated at any one time during translation of the largest available application program . in the last column . The major differences revealed by Table 4 occur in the lexical analysis and code generation subtasks . Apparently , Icont 's lexical analyser is doing quite a bit more work than EliIcont 's . Also , code generation is three times more expensive for EliIcont . Section 4 will return to these two areas in more extreme cases . 3.4 Memory Usage The memory usage of a program can play a large role in determining its overall performance . Memory access patterns can produce subtle performance problems due to architectural features such as cache organisation . Generally speaking , however , it is the overall amount of memory used that plays the biggest performance role over a large class of system architectures . Table 5 summarises the memory consumption of the two compilers . Heap consumptionwas measured while translating the X11 text widget . Two major points of difference can be seen from Table 5 . First , as was noted in Section 3.1 , the Eli-generated compiler contains a lot more code . Second , EliIcont uses a lot more dynamic memory . The reasons for this difference will be discussed in Section 4.3 . 4 Performance Analysis The measurements reported in Section 3 show that there is an overall performance advantage in generating a compiler for translating Icon compared to the available Icon translator . However , there are some programs for which the generated compiler comes off second best . Moreover , the memory consumption of the generated compiler is higher than it needs to be . This section considers the extreme points of Figure 1 in an attempt to understand the reasons for the performance differences . A program at the left end of the figure represents a significant advantage for the generated translator . These programs provide the best context in which we can determine the reasons why compiler generation is better . Conversely , the programs at the right end of the figure represent programs for which the generated compiler performs badly . Study of these programs may suggest refinements of compiler generators that will further improve the performance of generated compilers . We also analyse the reasons for the high memory consumption of the generated compiler . 4.1 Influence On Current Practice Compiler writers sometimes avoid using generators because of a perception that they can hand-code a more efficient solution . In some cases this is true but usually only if substantial effort is expended . Often developers are unaware of the full extent of research into compiler construction so the end result is not optimal . One of the benefits of a compiler generation system is that it allows users to take advantage of good compiler construction practices without necessarily being aware they are doing so . When efficient implementation techniques are developed they can be incorporated into the system for the benefit of all users . A good case in point is provided by the program for which EliIcont performs the best relative to Icont . When processing this program Icont 's lexical analyser consumes almost 46 % -LRB- 286 kilocycles -RRB- of the execution time , compared with about16 % -LRB- 71 kilocycles -RRB- for EliIcont ` slexical analyser on the same program . This difference is more than the overall difference in execution times for the two compilers on this input . Closer analysis of Icont reveals that most of the lexical analysis time -LRB- 32 % of the total execution time -RRB- is spent in a routine to get the next character from the input . Previous research has shown that this is an area which deserves to be handled carefully -LSB- 28 -RSB- . As a result , Eli includes a support module that provides efficient access to input characters without any special effort on the part of the compiler writer . 4.2 Efficiency Lessons To Be Learned On the other side of the coin are programs for which EliIcont performs poorly compared to Icont . By analysing performance on these programs we can identify areas in which further attention to efficiency should be directed . The main reason for EliIcont 's behaviour on the program for which it performed the worst appears to be the overhead of attribution . In the measurements reported in Table 4 , code generation only accounted for 10 % of EliIcont 's execution time . For the worst program it consumes over 40 % . In comparison Icont only spends 2-3 % of its time on corresponding tasks . Clearly more analysis is needed to determine the reason for the disparity between code generation times . It is likely that there is some fairly fixed overhead due to either the nature of the attribution or the implementation of the attribute evaluator that is dominating the timings . The program for which EliIcont performs worst is small so fixed overhead is particularly obvious . More research is needed to investigate this phenomena in more detail . 4.3 Dynamic Memory Consumption Section 3.4 drew attention to the large amount of dynamic memory used by EliIcont relative to Icont . While main memory is a relatively cheap resource compared to CPU speed , a factor of three is a high price to pay for using a generated compiler . To help guide future research into this problem , this section reports some more detailed measurements of dynamic memory consumption . Closer examination of the memory dynamically allocated by EliIcont shows that the majority of it constitutes nodes for either the abstract tree or the output tree . The abstract tree is the basis for attribution -LRB- semantic analysis and code generation -RRB- and stores much of the data used during this process . EliIcont uses an Eli tool that allows output to be built in a piecemeal fashion according to an output grammar . Once complete , the output tree is traversed in a depth-first manner to actually produce the output . Running on the text editor widget described in section 3.4 , EliIcont dynamically allocates about 1580 kilobytes of memory . Of this amount , about 745 kilobytes -LRB- 45 % -RRB- is used for 22203 abstract tree nodes and just over 555 kilobytes -LRB- 35 % -RRB- for 25582 output tree nodes . Abstract tree nodes consume 33 bytes on average and output tree nodes 21 bytes . For the same program , Icont allocates about 479 kilobytes for 13770 abstract tree nodes with an average node size of 34 bytes . The overhead of the EliIcont 's abstract tree nodes is not excessive compared to Icont but there are a lot more nodes . Presumably the abstract tree grammar could be restructured to reduce the number of nodes required . It is probable that such a change would achieve some savings via shared overhead information while at the same time increasing the size of nodes . Of course , compiler writers should be able to use the most appropriate abstract tree structure without having to worry about optimising space consumption . Much previous research has been devoted to space-saving optimisations for attribute grammar systems -LSB- 20 , 19 , 15 , 3 -RSB- . Further detailed analysis of the information stored in the abstract tree is necessary to improve the effectiveness of the optimisations currently built into Eli . Three general approaches to reducing output tree sizes are possible . Firstly , the EliIcont output grammar could be rewritten . While some space would likely be saved , large savings would probably only be possible with significant changes which would obscure what is currently a ? natural ? structure , closely related to the output code . Secondly , EliIcont could be rewritten to not construct a complete output tree . Thischange wouldcome at the expense of more complex attributionbecause attribute dependencieswould be needed to control the output . Such a change would go against one of the main advantages of the attribute grammar formalism used by EliIcont : implicitly-defined abstract tree traversal . The third approach involves research into more space-efficient methods of generating structured output . One possible aim is to increase the ratio of output produced per output tree node ; for the program measured for this section that ratio is 6.6 bytes per output tree node . Research into improving structured output is currently underway within the Eli project . 5 Conclusion Comparisons of automatically-generated compilers with equivalent hand-written compilers are important because they best enable the utility of generation systems to be ascertained . The results from these kinds of comparisons are useful for two reasons . Firstly , compiler writers who do not use generators may be convinced of the utility of their use . This paper shows that a generated compiler can be faster than a hand-written one and can be produced from smaller , more problem-oriented specifications . Eli embodies detailed domain-specific knowledge that allows the compiler writer to concentrate on aspects specific to the translation , while at the same time producing a competitive compiler . Secondly , developers of generation systems can use evidence from detailed comparisons to determine areas in which generated compilers lag behind hand-written compilers . For example , it is clear that the dynamic memory consumption of Eli-generated compilers should be addressed . Because any forthcoming improvements will be embodied in Eli , they will be available to all Eli users . This contrasts with the situation for hand-written compilers where improvements to one compiler are usually not easily incorpo - rated into other compilers . Future work should include more studies of the type described in this paper . While valuable information can be obtained from one study , more comparisons are needed to gauge the effectiveness of generated compilers over a range of languages and in competition with a variety of hand-written compilers . In particular , it would be useful to compare a generated compiler with a hand-written compiler that did n't explicitly build a complete abstract tree . Acknowledgements Many thanks to the Icon team at the University of Arizona for making their Icon implementation freely available . Thanks also to William Waite for his useful comments on a draft of this paper . References -LSB- 1 -RSB- BUMBULIS , P. , AND COWAN , D. D. RE2C : A more versitile scanner generator . ACM Letters on Programming Languages and Systems 2 , 1 ? 4 -LRB- March?December 1993 -RRB- , 70 ? 84 . -LSB- 2 -RSB- DENCKER , P. , D ? URRE , K. , AND HEUFT , J. Optimization of parser tables for portable compilers . ACM Transactions on Programming Languages and Systems 6 , 4 -LRB- Oct. 1984 -RRB- , 546 ? 572 . -LSB- 3 -RSB- DERANSART , P. , JOURDAN , M. , AND LORHO , B. Attribute Grammars : Definitions , Systems and Bibliography . No. 323 in Lecture Notes in Computer Science . Springer-Verlag , 1988 . -LSB- 4 -RSB- EMMELMANN , H. BEG ? a Back End Generator . GMD Forschungsstelle an der Universitaet Karlsruhe , Nov. 1989 . -LSB- 5 -RSB- EUSTACE , A. , AND SRIVASTAVA , A. ATOM : A flexible interface for building high performance program analysis tools . Tech . Rep. TN-44 , Digital Western Research Laboratory , July 1994 . -LSB- 6 -RSB- FRASER , C. W. , HENRY , R. R. , AND PROEBSTING , T. A. BURG?fast optimal instruction selection and tree parsing . ACM SIGPLAN Notices 27 , 4 -LRB- Apr. 1992 -RRB- , 68 ? 76 . -LSB- 7 -RSB- GRAHAM , S. L. , KESSLER , P. B. , AND MCKUSICK , M. K. gprof : A call graph execution profiler . SIGPLAN Notices 17 , 6 -LRB- June 1982 -RRB- , 120 ? 126 . Proceedings of the ACM SIGPLAN '82 Symposium on Compiler Construction . -LSB- 8 -RSB- GRAY , R. W. Generating fast , error recovering parsers . Master 's thesis , Department of Computer Science , University of Colorado , Boulder , Apr. 1987 . -LSB- 9 -RSB- GRAY , R. W . A generator for lexical analysis that programmers can use . In Proc . Summer USENIX Conference -LRB- San Francisco , CA , June 1988 -RRB- , pp. 147 ? 160 . -LSB- 10 -RSB- GRAY , R. W. Declarative Specifications for Automatically Constructed Compilers . Ph.D. thesis , Department of Computer Science , University of Colorado , Boulder , 1989 . -LSB- 11 -RSB- GRAY , R. W. , HEURING , V. P. , LEVI , S. P. , SLOANE , A. M. , AND WAITE , W. M. Eli : a complete , flexible compiler construction system . Communications of the ACM 35 , 2 -LRB- Feb. 1992 -RRB- , 121 ? 131 . -LSB- 12 -RSB- GRISWOLD , R. E. , AND GRISWOLD , M. T . The Icon Programming Language . Prentice-Hall , Inc. , Englewood Cliffs , N.J. , 1983 . -LSB- 13 -RSB- GRISWOLD , R. E. , AND GRISWOLD , M. T . The Implementation of the Icon Programming Language . Princeton University Press , 1986 . -LSB- 14 -RSB- GROSCH , J. Lalr?a generator for efficient parsers . Software ? Practice and Experience 20 , 11 -LRB- Nov. 1990 -RRB- , 1115 ? 1135 . -LSB- 15 -RSB- HALL , M. L . The Optimization of Automatically Generated Compilers . Ph.D. thesis , Department of Computer Science , University of Colorado , Boulder , 1987 . -LSB- 16 -RSB- HEERING , J. , KLINT , P. , AND REKERS , J. Incremental generation of lexical scanners . ACM Transactions on Programming Languages and Systems 14 , 4 -LRB- Oct. 1992 -RRB- , 490 ? 520 . -LSB- 17 -RSB- HEURING , V. P . The automatic generation of fast lexical analysers . Software ? Practice and Experience 16 , 9 -LRB- Sept. 1986 -RRB- , 801 ? 808 . -LSB- 18 -RSB- JOHNSON , S. C. Yacc ? yet another compiler-compiler . Computer Science Technical Report 32 , Bell Telephone Laboratories , Murray Hill , NJ , July 1975 . -LSB- 19 -RSB- KASTENS , U. Lifetime analysis for attributes . ACTA Informatica 24 -LRB- 1987 -RRB- , 633 ? 651 . -LSB- 20 -RSB- KASTENS , U. LIGA : A language independent generator for attribute evaluators . Bericht der Reihe Informatik Nr . 63 , Universit?at - GH Paderborn , Paderborn , FRG , 1989 . -LSB- 21 -RSB- LEE , P. Realistic Compiler Generation . Foundations of Computing . The MIT Press , Boston , Mass , 1989 . -LSB- 22 -RSB- LESK , M. E. LEX ? A lexical analyzer generator . Computing Science Technical Report 39 , Bell Telephone Laboratories , Murray Hill , NJ , 1975 . -LSB- 23 -RSB- R ? OHRICH , J. Methods for the automatic construction of error correcting parsers . Acta Informatica 13 , 2 -LRB- Feb. 1980 -RRB- , 115 ? 139 . -LSB- 24 -RSB- SCHMIDT , D. A. Denotational Semantics . Allyn and Bacon , Newton , MA , 1986 . -LSB- 25 -RSB- SITES , R. L. , Ed . Alpha Architecture Reference Manual . Digital Press , 1992 . -LSB- 26 -RSB- SRIVASTAVA , A. , AND EUSTACE , A. ATOM : A system for building customized program analysis tools . SIGPLAN Notices 29 , 6 -LRB- June 1994 -RRB- , 196 ? 205 . Proceedings of the ACM SIGPLAN '94 Conference on Programming Language Design and Implementation . -LSB- 27 -RSB- TOFTE , M. Compiler Generators , vol . 19 of EATCS Monographson Theoretical Computer Science . Springer-Verlag , 1990 . -LSB- 28 -RSB- WAITE , W. M . The cost of lexical analysis . Software?Practice and Experience 16 , 5 -LRB- May 1986 -RRB- , 473 ? 488 . -LSB- 29 -RSB- WAITE , W. M. , AND CARTER , L. R . The cost of a generated parser . SPE 15 , 3 -LRB- Mar. 1985 -RRB- , 221 ? 239 . -LSB- 30 -RSB- WAITE , W. M. , GROSCH , J. , AND SCHR ? OER , F. W. Three compiler specifications . GMD-Studien Nr . 166 , Gesellschaft f?ur Mathematik und Datenverarbeitung , Karlsruhe , FRG , Aug. 1989 .

O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O B I O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O B I O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O B I O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O B I O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O B I O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O B I O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O B I O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O

performance evaluation
programming language implementation