- Great Painters
- Accounting
- Fundamentals of Law
- Marketing
- Shorthand
- Concept Cars
- Videogames
- The World of Sports

- Blogs
- Free Software
- Google
- My Computer

- PHP Language and Applications
- Wikipedia
- Windows Vista

- Education
- Masterpieces of English Literature
- American English

- English Dictionaries
- The English Language

- Medical Emergencies
- The Theory of Memory
- The Beatles
- Dances
- Microphones
- Musical Notation
- Music Instruments
- Batteries
- Nanotechnology
- Cosmetics
- Diets
- Vegetarianism and Veganism
- Christmas Traditions
- Animals

- Fruits And Vegetables


  1. Adobe Reader
  2. Adware
  3. Altavista
  4. AOL
  5. Apple Macintosh
  6. Application software
  7. Arrow key
  8. Artificial Intelligence
  9. ASCII
  10. Assembly language
  11. Automatic translation
  12. Avatar
  13. Babylon
  14. Bandwidth
  15. Bit
  16. BitTorrent
  17. Black hat
  18. Blog
  19. Bluetooth
  20. Bulletin board system
  21. Byte
  22. Cache memory
  23. Celeron
  24. Central processing unit
  25. Chat room
  26. Client
  27. Command line interface
  28. Compiler
  29. Computer
  30. Computer bus
  31. Computer card
  32. Computer display
  33. Computer file
  34. Computer games
  35. Computer graphics
  36. Computer hardware
  37. Computer keyboard
  38. Computer networking
  39. Computer printer
  40. Computer program
  41. Computer programmer
  42. Computer science
  43. Computer security
  44. Computer software
  45. Computer storage
  46. Computer system
  47. Computer terminal
  48. Computer virus
  49. Computing
  50. Conference call
  51. Context menu
  52. Creative commons
  53. Creative Commons License
  54. Creative Technology
  55. Cursor
  56. Data
  57. Database
  58. Data storage device
  59. Debuggers
  60. Demo
  61. Desktop computer
  62. Digital divide
  63. Discussion groups
  64. DNS server
  65. Domain name
  66. DOS
  67. Download
  68. Download manager
  69. DVD-ROM
  70. DVD-RW
  71. E-mail
  72. E-mail spam
  73. File Transfer Protocol
  74. Firewall
  75. Firmware
  76. Flash memory
  77. Floppy disk drive
  78. GNU
  79. GNU General Public License
  80. GNU Project
  81. Google
  82. Google AdWords
  83. Google bomb
  84. Graphics
  85. Graphics card
  86. Hacker
  87. Hacker culture
  88. Hard disk
  89. High-level programming language
  90. Home computer
  91. HTML
  92. Hyperlink
  93. IBM
  94. Image processing
  95. Image scanner
  96. Instant messaging
  97. Instruction
  98. Intel
  99. Intel Core 2
  100. Interface
  101. Internet
  102. Internet bot
  103. Internet Explorer
  104. Internet protocols
  105. Internet service provider
  106. Interoperability
  107. IP addresses
  108. IPod
  109. Joystick
  110. JPEG
  111. Keyword
  112. Laptop computer
  113. Linux
  114. Linux kernel
  115. Liquid crystal display
  116. List of file formats
  117. List of Google products
  118. Local area network
  119. Logitech
  120. Machine language
  121. Mac OS X
  122. Macromedia Flash
  123. Mainframe computer
  124. Malware
  125. Media center
  126. Media player
  127. Megabyte
  128. Microsoft
  129. Microsoft Windows
  130. Microsoft Word
  131. Mirror site
  132. Modem
  133. Motherboard
  134. Mouse
  135. Mouse pad
  136. Mozilla Firefox
  137. Mp3
  138. MPEG
  139. MPEG-4
  140. Multimedia
  141. Musical Instrument Digital Interface
  142. Netscape
  143. Network card
  144. News ticker
  145. Office suite
  146. Online auction
  147. Online chat
  148. Open Directory Project
  149. Open source
  150. Open source software
  151. Opera
  152. Operating system
  153. Optical character recognition
  154. Optical disc
  155. output
  156. PageRank
  157. Password
  158. Pay-per-click
  159. PC speaker
  160. Peer-to-peer
  161. Pentium
  162. Peripheral
  163. Personal computer
  164. Personal digital assistant
  165. Phishing
  166. Pirated software
  167. Podcasting
  168. Pointing device
  169. POP3
  170. Programming language
  171. QuickTime
  172. Random access memory
  173. Routers
  174. Safari
  175. Scalability
  176. Scrollbar
  177. Scrolling
  178. Scroll wheel
  179. Search engine
  180. Security cracking
  181. Server
  182. Simple Mail Transfer Protocol
  183. Skype
  184. Social software
  185. Software bug
  186. Software cracker
  187. Software library
  188. Software utility
  189. Solaris Operating Environment
  190. Sound Blaster
  191. Soundcard
  192. Spam
  193. Spamdexing
  194. Spam in blogs
  195. Speech recognition
  196. Spoofing attack
  197. Spreadsheet
  198. Spyware
  199. Streaming media
  200. Supercomputer
  201. Tablet computer
  202. Telecommunications
  203. Text messaging
  204. Trackball
  205. Trojan horse
  206. TV card
  207. Unicode
  208. Uniform Resource Identifier
  209. Unix
  210. URL redirection
  211. USB flash drive
  212. USB port
  213. User interface
  214. Vlog
  215. Voice over IP
  216. Warez
  217. Wearable computer
  218. Web application
  219. Web banner
  220. Web browser
  221. Web crawler
  222. Web directories
  223. Web indexing
  224. Webmail
  225. Web page
  226. Website
  227. Wiki
  228. Wikipedia
  229. WIMP
  230. Windows CE
  231. Windows key
  232. Windows Media Player
  233. Windows Vista
  234. Word processor
  235. World Wide Web
  236. Worm
  237. XML
  238. X Window System
  239. Yahoo
  240. Zombie computer

This article is from:

All text is available under the terms of the GNU Free Documentation License: 


From Wikipedia, the free encyclopedia

This article is about the computing term. For the anime, see Compiler (anime).
A diagram of the operation of a typical multi-language, multi-target compiler.
A diagram of the operation of a typical multi-language, multi-target compiler.

A compiler is a computer program (or set of programs) that translates text written in a computer language (the source language) into another computer language (the target language). The original sequence is usually called the source code and the output called object code. Commonly the output has a form suitable for processing by other programs (e.g., a linker), but it may be a human readable text file.

The most common reason for wanting to translate source code is to create an executable program. The name "compiler" is primarily used for programs that translate source code from a high level language to a lower level language (e.g., assembly language or machine language). A program that translates from a low level language to a higher level one is a decompiler. A program that translates between high-level languages is usually called a language translator, source to source translator, or language converter. A language rewriter is usually a program that translates the form of expressions without a change of language.

A compiler is likely to perform many or all of the following operations: lexing, preprocessing, parsing, semantic analysis, code optimizations, and code generation.


Early computers did not use compilers. Compilers had not yet been invented because early computers had very little memory and programs were necessarily quite short. Users often entered the decimal or binary machine code for a program directly by turning or toggling switches on the computer console or entering digits via paper tape.

Programmers soon began to create programs to help with the tedious task of entering machine code. Such a program which would translate an alphabetic letter (which were chosen to be mnemonic) into a corresponding numeric instruction which the machine could execute. In this manner, assembly languages and the primitive compiler, the assembler, emerged.

Towards the end of the 1950s, machine-independent programming languages evolved. Subsequently, several experimental compilers were developed then (see, for example, the seminal work by Grace Hopper on the A-0 programming language), but the FORTRAN team led by John Backus at IBM is generally credited as having introduced the first complete compiler, in 1957. COBOL was an early language to be compiled on multiple architectures, in 1960. [1]

The idea of compilation quickly caught on, and most of the principles of compiler design were developed during the 1960s.

With the evolution of programming languages and the increasing power of computers, compilers are becoming more and more complex to bridge the gap between problem-solving modern programming languages and the various computer systems, aiming at getting the highest performance out of the target machines.

A compiler is itself a computer program written in some implementation language. Early compilers were written in assembly language. The first self-hosting compiler capable of compiling its own source code in a high-level language was created for Lisp by Hart and Levin at MIT in 1962 [2]. The use of high-level languages for writing compilers gained added impetus in the early 1970s when Pascal and C compilers were written in their own languages. Building a self-hosting compiler is a bootstrapping problem -- the first such compiler for a language must be compiled either by a compiler written in a different language, or (as in Hart and Levin's Lisp compiler) compiled by running the compiler in an interpreter.

Compiler construction and compiler optimization are taught at universities as part of the computer science curriculum. Such courses are usually supplemented with the implementation of a compiler for an educational programming language. A well documented example is the PL/0 compiler, which was originally used by Niklaus Wirth for teaching compiler construction in the 1970s. In spite of its simplicity, the PL/0 compiler introduced several concepts to the field which have since become established educational standards:

  1. The use of Program Development by Stepwise Refinement
  2. The use of a Recursive descent parser
  3. The use of EBNF to specify the syntax of a language
  4. The use of P-Code during generation of portable output code
  5. The use of T-diagrams for the formal description of the bootstrapping problem

Types of compilers

There are many ways to classify compilers according to the input and output, internal structure, and runtime behavior. For example,

  • A program that translates from a low level language to a higher level one is a decompiler.
  • A program that translates between high-level languages is usually called a language translator, source to source translator, language converter, or language rewriter (this last term is usually applied to translations that do not involve a change of language)

Where does the code execute?

One method used to classify compilers is by the platform on which the generated code they produce executes.

A native or hosted compiler is one whose output is intended to directly run on the same type of computer and operating system as the compiler itself runs on. The output of a cross compiler is designed to run on a different platform. Cross compilers are often used when developing software for embedded systems that are not intended to support an environment intended for software development.

The output of a compiler that produces code for a Virtual machine (VM) may or may not be executed on the same platform as the compiler that produced it. For this reason such compilers are not usually classified as native or cross compilers.

One-pass versus multi-pass compilers

Classifying compilers by number of passes has its background in the hardware resource limitations of computers. Compiling involves performing lots of work and early computers did not have enough memory to contain one program that did all of this work. So compilers were split up into smaller programs which each made a pass over the source (or some representation of it) performing some of the required analysis and translations.

The ability to compile in a single pass is often seen as a benefit because it simplifies the job of writing a compiler and one pass compilers are generally faster than multi-pass compilers. Many languages were designed so that they could be compiled in a single pass (e.g., Pascal).

In some cases the design of a language feature may require a compiler to perform more than one pass over the source. For instance, consider a declaration appearing on line 20 of the source which affects the translation of a statement appearing on line 10. In this case, the first pass needs to gather information about declarations appearing after statements that they affect, with the actual translation happening during a subsequent pass.

The disadvantage of compiling in a single pass is that it is not possible to perform many of the sophisticated optimizations needed to generate high quality code. It can be difficult to count exactly how many passes an optimizing compiler makes. For instance, different phases of optimization may analyse one expression many times but only analyse another expression once.

Splitting a compiler up into small programs is a technique used by researchers interested in producing provably correct compilers. Proving the correctness of a set of small programs often requiring less effort than proving the correctness of a larger, single, equivalent program.

While the typical multi-pass compiler outputs machine code from its final pass, there are several other types:

  • A "source-to-source compiler" is a type of compiler that takes a high level language as its input and outputs a high level language. For example, an automatic parallelizing compiler will frequently take in a high level language program as an input and then transform the code and annotate it with parallel code annotations (e.g. OpenMP) or language constructs (e.g. Fortran's DOALL statements).
  • Stage compiler that compiles to assembly language of a theoretical machine, like some Prolog implementations
    • This Prolog machine is also known as the Warren Abstract Machine (or WAM). Bytecode compilers for Java, Python, and many more are also a subtype of this.
  • Just-in-time compiler, used by Smalltalk and Java systems, and also by Microsoft .Net's Common Intermediate Language (CIL)
    • Applications are delivered in bytecode, which is compiled to native machine code just prior to execution.

Compiled versus interpreted languages

Many people divide higher-level programming languages into compiled languages and interpreted languages. However, there is rarely anything about a language that requires it to be compiled or interpreted. Compilers and interpreters are implementations of languages, not languages themselves. The categorization usually reflects the most popular or widespread implementations of a language -- for instance, BASIC is thought of as an interpreted language, and C a compiled one, despite the existence of BASIC compilers and C interpreters.

There are exceptions; some language specifications spell out that implementations must include a compilation facility (eg, Common Lisp), while other languages have features that are very easy to implement in an interpreter, but make writing a compiler much harder; for example, SNOBOL4, and many scripting languages are capable of constructing arbitrary source code at runtime with regular string operations, and then executing that code by passing it to a special evaluation function. To implement these features in a compiled language, programs must usually be shipped with a runtime environment that includes the compiler itself.

Hardware compilation

The output of some compilers may target hardware at a very low level, eg a Field Programmable Gate Array (FPGA). Such compilers are said to be hardware compilers because the programs they compile effectively control the final configuration of the hardware and how it operates; there are no instructions that are executed in sequence.

Compiler design

The approach taken to compiler design is affected by the complexity of the processing that needs to be done, the experience of the person(s) designing it, and the resources (eg, people and tools) available.

A compiler for a relatively simple language written by one person might be a single, monolithic, piece of software. When the source language is large and complex, and high quality output is required the design may be split into a number of relatively independent phases, or passes. Having separate phases means development can be parceled up into small parts and given to different people. It also becomes much easier to replace a single phase by an improved one, or to insert new phases later (eg, additional optimizations).

The division of the compilation processes in phases (or passes) was championed by the Production Quality Compiler-Compiler Project (PQCC) at Carnegie Mellon University. This project introduced the terms front end, middle end (rarely heard today), and back end.

All but the smallest of compilers have more than two phases. However, these phases are usually regarded as being part of the front end or the back end. The point at where these two ends meet is always open to debate. The front end is generally considered to be where syntactic and semantic processing takes place, along with translation to a lower level of representation (than source code).

The middle end is usually designed to perform optimizations on a form other than the source code or machine code. This source code/machine code independence is intended to enable generic optimizations to be shared between versions of the compiler supporting different languages and target processors.

The back end takes the output from the middle. It may perform more analysis, transformations and optimizations that are for a particular computer. Then, it generates code for a particular processor and OS.

This front-end/middle/back-end approach makes it possible to combine front ends for different languages with back ends for different CPUs. A practical example of this approach is the GNU Compiler Collection and the Amsterdam Compiler Kit, which have multiple front-ends, shared analysis and multiple back-ends.

Front end

The front end analyses the source code to build an internal representation of the program, called the intermediate representation or IR. It also manages the symbol table, a data structure mapping each symbol in the source code to associated information such as location, type and scope. This is done over several phases:

  1. Line reconstruction. Languages which strop their keywords (and allow arbitrary spaces within identifiers) require a phase before parsing, which is to take the input source and convert it to a canonical form ready for the parser. The top-down recursive-descent table-driven parsers used in the 1960s typically would read the source a character at a time and would not require a separate tokenizing phase. Algol, Coral66, Atlas Autocode, and Imp are examples of stropped languages whose compilers would have a Line Reconstruction phase.
  2. Lexical analysis breaks the source code text into small pieces called tokens. Each token is a single atomic unit of the language, for instance a keyword, identifier or symbol name. The token syntax is typically a regular language, so a finite state automaton constructed from a regular expression can be used to recognize it. This phase is also called lexing or scanning, and the software doing lexical analysis is called a lexical analyzer or scanner.
  3. Preprocessing. Some languages, e.g., C, require a preprocessing phase to do things such as conditional compilation and macro substitution. In the case of C the preprocessing phase includes lexical analysis.
  4. Syntax analysis involves parsing the token sequence to identify the syntactic structure of the program.
  5. Semantic analysis is the phase that checks the meaning of the program to ensure it obeys the rules of the language. One example is type checking. The compiler emits most diagnostics during semantic analysis, and frequently combines it with syntax analysis.

Back end

The term of Back end is sometime confused with code generator for the overlapped functionality of generating assembly code. Some literature use Middle end to distinguish the generic analysis and optimization phases in the back end from the machine dependent code generators.

The work in the back end is done in multiple steps:

  1. Compiler analysis - This is the process to gather program information from the intermediate representation of the input source files. Typical analyses are variable define-use and use-define chain, dependence analysis, alias analysis, pointer analysis, escape analysis etc. Accurate analysis is the base for any compiler optimization. The call graph and control flow graph are usually also built during the analysis phase.
  2. Optimization - the intermediate language representation is transformed into functionally equivalent but faster (or smaller) forms. Popular optimizations are inline expansion, dead code elimination, constant propagation, loop transformation, register allocation or even automatic parallelization.
  3. Code generation - the transformed intermediate language is translated into the output language, usually the native machine language of the system. This involves resource and storage decisions, such as deciding which variables to fit into registers and memory and the selection and scheduling of appropriate machine instructions along with their associated addressing modes (see also Sethi-Ullman algorithm).

Compiler analysis is the prerequisite for any compiler optimization, and they tightly work together. For example, dependence analysis is crucial for loop transformation.

In addition, the scope of compiler analysis and optimizations vary greatly, from as small as a basic block to the procedure/function level, or even over the whole program (interprocedural optimization). Obviously, a compiler can potentially do a better job using a broader view. But that broad view is not free: large scope analysis and optimizations are very costly in terms of compilation time and memory space; this is especially true for interprocedural analysis and optimizations.

The existence of interprocedural analysis and optimizations is common in modern commercial compilers from IBM, SGI, Intel, Microsoft, and Sun Microsystems. The open source GCC was criticized for a long time for lacking powerful interprocedural optimizations, but it is changing in this respect. Another good open source compiler with full analysis and optimization infrastructure is Open64, which is used by many organizations for research and commercial purposes.

Due to the extra time and space needed for compiler analysis and optimizations, some compilers skip them by default. Users have to use compilation options to explicitly tell the compiler which optimizations should be enabled.

A compiler example

The following program represents a very simple one-pass compiler, written in C. This compiler compiles an expression defined in infix notation to postfix notation and also into an assembly-like machine language. This compiler uses the recursive descent strategy. This strategy is recognizable by the fact that each function corresponds to a non-terminal symbol in a language grammar.

#include <stdlib.h>#include <stdio.h>#include <string.h>#define MODE_POSTFIX    0#define MODE_ASSEMBLY   1char    lookahead;int     pos;int     compile_mode;char    expression[20+1];void error(){        printf("Syntax error!\n");}void match( char t ){        if( lookahead == t )        {                pos++;                lookahead = expression[pos];                    }        else                error();}void digit(){        switch( lookahead )        {                case '0':                case '1':                case '2':                case '3':                case '4':                case '5':                case '6':                case '7':                case '8':                case '9':                        if( compile_mode == MODE_POSTFIX )                                printf("%c", lookahead);                        else                                printf("\tPUSH %c\n", lookahead);                                                                     match( lookahead );                        break;                default:                        error();                        break;        }}void term(){        digit();        while(1)        {                switch( lookahead )                {                        case '*':                                match('*');                                digit();                                                                                                printf( "%s", compile_mode == MODE_POSTFIX ? "*"                                         : "\tPOP B\n\tPOP A\n\tMUL A, B\n\tPUSH A\n");                                                                        break;                        case '/':                                match('/');                                digit();                                printf( "%s", compile_mode == MODE_POSTFIX ? "/"                                         : "\tPOP B\n\tPOP A\n\tDIV A, B\n\tPUSH A\n");                                break;                        default:                                return;                }        }}void expr(){        term();        while(1)        {                switch( lookahead )                {                        case '+':                                match('+');                                term();                                                                printf( "%s", compile_mode == MODE_POSTFIX ? "+"                                         : "\tPOP B\n\tPOP A\n\tADD A, B\n\tPUSH A\n");                                break;                        case '-':                                match('-');                                term();                                printf( "%s", compile_mode == MODE_POSTFIX ? "-"                                         : "\tPOP B\n\tPOP A\n\tSUB A, B\n\tPUSH A\n");                                break;                        default:                                return;                }        }}int main ( int argc, char** argv ){        printf("Please enter an infix-notated expression with single digits:\n\n\t");        scanf("%20s", expression);                printf("\nCompiling to postfix-notated expression:\n\n\t");           compile_mode = MODE_POSTFIX;        pos = 0;        lookahead = *expression;        expr();                        printf("\n\nCompiling to assembly-notated machine code:\n\n");                compile_mode = MODE_ASSEMBLY;        pos = 0;        lookahead = *expression;        expr();        return 0;}

A possible execution of this simple compiler results in the following output:

Please enter an infix-notated expression with single digits:        3-4*2+2Compiling to postfix-notated expression:        342*-2+Compiling to assembly-notated machine code:        PUSH 3        PUSH 4        PUSH 2        POP B        POP A        MUL A, B        PUSH A        POP B        POP A        SUB A, B        PUSH A        PUSH 2        POP B        POP A        ADD A, B        PUSH A



  • Compiler textbook references A collection of references to mainstream Compiler Construction Textbooks
  • Compilers: Principles, Techniques and Tools by Alfred V. Aho, Ravi Sethi, and Jeffrey D. Ullman (ISBN 0-201-10088-6) is considered to be the standard authority on compiler basics(undergraduate level), and makes a good primer for the techniques mentioned above. (It is often called the Dragon Book because of the picture on its cover showing a Knight of Programming fighting the Dragon of Compiler Design.) link to publisher
  • Advanced Compiler Design and Implementation by Steven Muchnick (ISBN 1-55860-320-4). One of the widely-used text books for advanced compiler courses(graduate level).
  • Engineering a Compiler by Keith D. Cooper and Linda Torczon . Morgan Kaufmann 2004, ISBN 1-55860-699-8. This is a very practical compiler book.
  • Understanding and Writing Compilers: A Do It Yourself Guide (ISBN 0-333-21732-2) by Richard Bornat is an unusually helpful book, being one of the few that adequately explains the recursive generation of machine instructions from a parse tree. The authors experience from the early days of mainframes and minicomputers, provides useful insights that more recent books often fail to convey.
  • An Overview of the Production Quality Compiler-Compiler Project by Leverett, Cattel, Hobbs, Newcomer, Reiner, Schatz and Wulf. Computer 13(8):38-49 (August 1980)
  • Compiler Construction by Niklaus Wirth (ISBN 0-201-40353-6) Addison-Wesley 1996, 176 pages, also available at [3]. Step-by-step guide to using recursive descent parser. Describes a compiler for Oberon-0, a subset of the author's programming language, Oberon.
  • "Programming Language Pragmatics" by Michael Scott (ISBN 0-12-633951-1) Morgan Kaufmann 2005, 2nd edition, 912 pages. This book offers a broad and in-depth introduction to compilation techniques and programming languages, illustrated with many examples. More information on the book can be found at the author's site.
  • "A History of Language Processor Technology in IBM", by F.E. Allen, IBM Journal of Research and Development, v.25, no.5, September 1981.

See also

  • List of compilers
  • Compiler optimization
  • Assembler
  • Interpreters:
    • Interpreter software
    • Abstract interpretation
  • Linker
  • Parsing:
    • Top-down parsing
      • Recursive descent parser
    • Bottom-up parsing
    • Attribute grammar
  • Semantic analysis
    • Semantics encoding
  • Error avalanche
  • Decompiler
  • Just-in-time compiler
  • Meta-Compilation
  • Preprocessor
  • Important publications in compilers for programming languages
  • Code generation

External links

Look up compiler in
Wiktionary, the free dictionary.
Wikibooks has more about this subject:
Compiler construction
  • software download
  • What is "compile"? from the developer's encyclopedia
  • GCC, a widely-used open-source compiler
  • Compilr, an online compiler
  • Building and Testing gcc/glibc cross toolchains
  • The Amsterdam Compiler Kit open-source
  • The comp.compilers newsgroup and RSS feed
  • Let's Build a Compiler by Jack Crenshaw (1988 to 1995) "a non-technical introduction to compiler construction"
  • Hardware compilation information
  • Hardware compilation mailing list
Retrieved from ""