精华内容
参与话题
问答
  • Compiler

    千次阅读 2013-09-09 16:07:19
    http://en.wikipedia.org/wiki/Compiler ...Compiler From Wikipedia, the free encyclopedia This article is about the computing term. For the anime, see Compiler (anime). A

    http://en.wikipedia.org/wiki/Compiler

    Compiler

    From Wikipedia, the free encyclopedia
    A diagram of the operation of a typical multi-language, multi-target compiler

    compiler is a computer program (or set of programs) that transformssource code written in a programming language (the source language) into another computer language (the target language, often having a binary form known as object code). The most common reason for wanting to transform source code is to create an executable program.

    The name "compiler" is primarily used for programs that translate source code from a high-level programming language to a lower level language (e.g., assembly language or machine code). If the compiled program can run on a computer whose CPU or operating system is different from the one on which the compiler runs, the compiler is known as a cross-compiler. A program that translates from a low level language to a higher level one is adecompiler. A program that translates between high-level languages is usually called a language translatorsource to source translator, orlanguage 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: lexical analysispreprocessingparsing, semantic analysis (Syntax-directed translation), code generation, and code optimization.

    Program faults caused by incorrect compiler behavior can be very difficult to track down and work around; therefore, compiler implementors invest significant effort to ensure compiler correctness.

    The term compiler-compiler is sometimes used to refer to a parser generator, a tool often used to help create the lexer and parser.

    History[edit source | editbeta]

    Software for early computers was primarily written in assembly language. Higher level programming languages were not invented until the benefits of being able to reuse software on different kinds of CPUs started to become significantly greater than the costs of writing a compiler. The limited memory capacity of early computers led to substantial technical challenges when the first compilers were being designed.

    Towards the end of the 1950s, machine-independent programming languages were first proposed. Subsequently several experimental compilers were developed. The first compiler was written by Grace Hopper, in 1952, for the A-0 programming language. 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]

    In many application domains the idea of using a higher level language quickly caught on. Because of the expanding functionality supported by newer programming languages and the increasing complexity of computer architectures, compilers have become more complex.

    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 in 1962 for Lisp by Tim Hart and Mike Levin at MIT.[2] Since the 1970s it has become common practice to implement a compiler in the language it compiles, although both Pascal and C have been popular choices for implementation language. Building a self-hosting compiler is a bootstrapping problem—the first such compiler for a language must be compiled either by hand or 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.

    Compilers in education[edit source | editbeta]

    Compiler construction and compiler optimization are taught at universities and schools as part of a computer sciencecurriculum.[3] Such courses are usually supplemented with the implementation of a compiler for an educational programming language. A well-documented example is Niklaus Wirth's PL/0 compiler, which Wirth used to teach compiler construction in the 1970s.[4] In spite of its simplicity, the PL/0 compiler introduced several influential concepts to the field:

    1. Program development by stepwise refinement (also the title of a 1971 paper by Wirth)[5]
    2. The use of a recursive descent parser
    3. The use of EBNF to specify the syntax of a language
    4. code generator producing portable P-code
    5. The use of T-diagrams[6] in the formal description of the bootstrapping problem

    Compilation[edit source | editbeta]

    Compilers enabled the development of programs that are machine-independent. Before the development of FORTRAN (FORmula TRANslator), the first higher-level language, in the 1950s, machine-dependent assembly language was widely used. Whileassembly language produces more abstraction than machine code on the same architecture, just as with machine code, it has to be modified or rewritten if the program is to be executed on different computer hardware architecture.

    With the advance of high-level programming languages that followed FORTRAN, such as COBOLC, and BASIC, programmers could write machine-independent source programs. A compiler translates the high-level source programs into target programs in machine languages for the specific hardwares. Once the target program is generated, the user can execute the program.

    Structure of a compiler[edit source | editbeta]

    Compilers bridge source programs in high-level languages with the underlying hardware. A compiler requires 1) determining the correctness of the syntax of programs, 2) generating correct and efficient object code, 3) run-time organization, and 4) formatting output according to assembler and/or linker conventions. A compiler consists of three main parts: the frontend, the middle-end, and the backend.

    The front end checks whether the program is correctly written in terms of the programming language syntax and semantics. Here legal and illegal programs are recognized. Errors are reported, if any, in a useful way. Type checking is also performed by collecting type information. The frontend then generates an intermediate representation or IR of the source code for processing by the middle-end.

    The middle end is where optimization takes place. Typical transformations for optimization are removal of useless or unreachable code, discovery and propagation of constant values, relocation of computation to a less frequently executed place (e.g., out of a loop), or specialization of computation based on the context. The middle-end generates another IR for the following backend. Most optimization efforts are focused on this part.

    The back end is responsible for translating the IR from the middle-end into assembly code. The target instruction(s) are chosen for each IR instruction. Register allocation assigns processor registers for the program variables where possible. The backend utilizes the hardware by figuring out how to keep parallel execution units busy, filling delay slots, and so on. Although most algorithms for optimization are in NP, heuristic techniques are well-developed.

    Compiler output[edit source | editbeta]

    One classification of compilers is by the platform on which their generated code executes. This is known as the target platform.

    native or hosted compiler is one which output is intended to directly run on the same type of computer and operating system that 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 a software development environment.

    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.

    The lower level language that is the target of a compiler may itself be a high-level programming languageC, often viewed as some sort of portable assembler, can also be the target language of a compiler. E.g.: Cfront, the original compiler for C++ used C as target language. The C created by such a compiler is usually not intended to be read and maintained by humans. So indent style and pretty C intermediate code are irrelevant. Some features of C turn it into a good target language. E.g.: C code with#line directives can be generated to support debugging of the original source.

    Compiled versus interpreted languages[edit source | editbeta]

    Higher-level programming languages usually appear with a type of translation in mind: either designed as compiled language orinterpreted language. However, in practice there is rarely anything about a language that requires it to be exclusively compiled or exclusively interpreted, although it is possible to design languages that rely on re-interpretation at run time. The categorization usually reflects the most popular or widespread implementations of a language — for instance, BASIC is sometimes called an interpreted language, and C a compiled one, despite the existence of BASIC compilers and C interpreters.

    Interpretation does not replace compilation completely. It only hides it from the user and makes it gradual. Even though an interpreter can itself be interpreted, a directly executed program is needed somewhere at the bottom of the stack (see machine language). Modern trends toward just-in-time compilation and bytecode interpretation at times blur the traditional categorizations of compilers and interpreters.

    Some language specifications spell out that implementations must include a compilation facility; for example, Common Lisp. However, there is nothing inherent in the definition of Common Lisp that stops it from being interpreted. Other languages have features that are very easy to implement in an interpreter, but make writing a compiler much harder; for example, APLSNOBOL4, and many scripting languages allow programs to construct arbitrary source code at runtime with regular string operations, and then execute 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 library that includes a version of the compiler itself.

    Hardware compilation[edit source | editbeta]

    The output of some compilers may target computer hardware at a very low level, for example a Field Programmable Gate Array(FPGA) or structured Application-specific integrated circuit (ASIC). Such compilers are said to be hardware compilers or synthesis tools because the source code they compile effectively controls the final configuration of the hardware and how it operates; the output of the compilation is not instructions that are executed in sequence - only an interconnection of transistors or lookup tables. For example, XST is the Xilinx Synthesis Tool used for configuring FPGAs. Similar tools are available from Altera, Synplicity, Synopsys and other vendors.

    Compiler construction[edit source | editbeta]

    In the early days, the approach taken to compiler design used to be directly affected by the complexity of the processing, the experience of the person(s) designing it, and the resources 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. 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 (e.g., additional optimizations).

    The division of the compilation processes into phases was championed by the Production Quality Compiler-Compiler Project(PQCC) at Carnegie Mellon University. This project introduced the terms front endmiddle end, 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 which these two ends meet is 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. Practical examples of this approach are the GNU Compiler CollectionLLVM, and the Amsterdam Compiler Kit, which have multiple front-ends, shared analysis and multiple back-ends.

    One-pass versus multi-pass compilers[edit source | editbeta]

    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 has classically been seen as a benefit because it simplifies the job of writing a compiler and one-pass compilers generally perform compilations faster than multi-pass compilers. Thus, partly driven by the resource limitations of early systems, many early languages were specifically 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 requires 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
    • 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.

    Front end[edit source | editbeta]

    The compiler frontend analyzes 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, which includes some of the following:

    1. Line reconstruction. Languages which strop their keywords or allow arbitrary spaces within identifiers require a phase before parsing, which converts the input character sequence to a canonical form ready for the parser. The top-downrecursive-descent, table-driven parsers used in the 1960s typically read the source one character at a time and did not require a separate tokenizing phase. Atlas Autocode, and Imp (and some implementations of ALGOL and Coral 66) are examples of stropped languages which 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 keywordidentifier 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. This may not be a separate step – it can be combined with the parsing step in scannerless parsing, in which case parsing is done at the character level, not the token level.
    3. Preprocessing. Some languages, e.g., C, require a preprocessing phase which supports macro substitution and conditional compilation. Typically the preprocessing phase occurs before syntactic or semantic analysis; e.g. in the case of C, the preprocessor manipulates lexical tokens rather than syntactic forms. However, some languages such as Scheme support macro substitutions based on syntactic forms.
    4. Syntax analysis involves parsing the token sequence to identify the syntactic structure of the program. This phase typically builds a parse tree, which replaces the linear sequence of tokens with a tree structure built according to the rules of a formal grammar which define the language's syntax. The parse tree is often analyzed, augmented, and transformed by later phases in the compiler.
    5. Semantic analysis is the phase in which the compiler adds semantic information to the parse tree and builds the symbol table. This phase performs semantic checks such as type checking (checking for type errors), or object binding (associating variable and function references with their definitions), or definite assignment (requiring all local variables to be initialized before use), rejecting incorrect programs or issuing warnings. Semantic analysis usually requires a complete parse tree, meaning that this phase logically follows the parsing phase, and logically precedes the code generation phase, though it is often possible to fold multiple phases into one pass over the code in a compiler implementation.

    Back end[edit source | editbeta]

    The term back end is sometimes confused with code generator because of the overlapped functionality of generating assembly code. Some literature uses middle end to distinguish the generic analysis and optimization phases in the back end from the machine-dependent code generators.

    The main phases of the back end include the following:

    1. Analysis: This is the gathering of program information from the intermediate representation derived from the input. Typical analyses are data flow analysis to build use-define chainsdependence analysisalias analysispointer analysisescape analysis etc. Accurate analysis is the basis 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 expansiondead code eliminationconstant propagationloop transformation,register allocation and even automatic parallelization.
    3. Code generation: the transformed intermediate language is translated into the output language, usually the nativemachine 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). Debug data may also need to be generated to facilitate debugging.

    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.

    Interprocedural analysis and optimizations are common in modern commercial compilers from HPIBMSGIIntelMicrosoft, andSun Microsystems. The open source GCC was criticized for a long time for lacking powerful interprocedural optimizations, but it is changing in this respect. Another 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.

    Compiler correctness[edit source | editbeta]

    Compiler correctness is the branch of software engineering that deals with trying to show that a compiler behaves according to itslanguage specification.[citation needed] Techniques include developing the compiler using formal methods and using rigorous testing (often called compiler validation) on an existing compiler.

    Related techniques[edit source | editbeta]

    Assembly language is a type of low-level language and a program that compiles it is more commonly known as an assembler, with the inverse program known as a disassembler.

    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 translatorsource to source translator,language converter, or language rewriter. The last term is usually applied to translations that do not involve a change of language.

    A program that translates into an object code format that is not supported on the compilation machine is called a cross compilerand is commonly used to prepare code for embedded applications.

    International conferences and organizations[edit source | editbeta]

    Every year, the European Joint Conferences on Theory and Practice of Software (ETAPS) sponsors the International Conference on Compiler Construction, with papers from both the academic and industrial sectors.[7]

    See also[edit source | editbeta]

    Notes[edit source | editbeta]

    1. ^ "IP: The World's First COBOL Compilers". interesting-people.org. 12 June 1997.
    2. ^ T. Hart and M. Levin. "The New Compiler, AIM-39 - CSAIL Digital Archive - Artificial Intelligence Laboratory Series". publications.ai.mit.edu.
    3. ^ Chakraborty, P., Saxena, P. C., Katti, C. P., Pahwa, G., Taneja, S. A new practicum in compiler construction. Computer Applications in Engineering Education, In Press.http://onlinelibrary.wiley.com/doi/10.1002/cae.20566/pdf
    4. ^ "The PL/0 compiler/interpreter".
    5. ^ "The ACM Digital Library".
    6. ^ T diagrams were first introduced for describing bootstrapping and cross-compiling compilers in McKeeman et al. A Compiler Generator (1971). Conway described the broader concept before that with his UNCOL in 1958, to which Bratman added in 1961: H. Bratman, “An alternate form of the ´UNCOL diagram´“, Comm. ACM 4 (March 1961) 3, p. 142. Later on, others, including P.D. Terry, gave an explanation and usage of T-diagrams in their textbooks on the topic of compiler construction. Cf. Terry, 1997, Chapter 3. T-diagrams are also now used to describe client-server interconnectivity on the World Wide Web: cf. Patrick Closhen, et al. 1997: T-Diagrams as Visual Language to Illustrate WWW Technology, Darmstadt University of Technology, Darmstadt, Germany
    7. ^ ETAPS - European Joint Conferences on Theory and Practice of Software. Cf. "CC" (Compiler Construction) subsection.

    References[edit source | editbeta]

    External links[edit source | editbeta]


    展开全文
  • 最近需要用DC做一些事,然后需要转库,...DC2015及以后的版本中,Library Compiler(下称LC)是独立出来的!!!于是乎,我下了个LC2016.12的的,安装了,把.lib转成.db了。 2.接下来是在DC中读入.db,然后...坑...

    最近需要用DC做一些事,然后需要转库,中午偷个闲,特来记录一下中间的一些坎坷。

    1.首先是要转库。我们只有.lib文件的格式,所以需要把.lib文件转换成.db格式。然后坑来了!!!DC2015及以后的版本中,Library Compiler(下称LC)是独立出来的!!!于是乎,我下了个LC2016.12的的,安装了,把.lib转成.db了。

     

    2.接下来是在DC中读入.db,然后...坑又来了!!!LC版本太高,DC(DC版本是2015的)不认这个.db!!!也就是说,LC的版本不能高于DC的版本!!!

     

    3.好吧,那我继续寻找解决方案,安装个低级的LC吧...然后搜索资源...绝望,找不到LC低版本(2015版本)的资源...于是乎改变主意,安装低版本的DC。

     

    4.找到了一个2013版本的DC,花费四五百信元(某论坛货币单位,老司机们都懂的),下了下来。内心想:安装DC这些EDA工具对我来说是家常便饭了,结果轻敌了(坑又来了)!!!一般安装包里面有各种不同系统的安装包,而installer全给你识别了......这个时候只需要安装某一个版本就可以了。比如我是redhat6 64bit,就安装64位的,就点64位那个选项。为了防止选错,这里建议安装的时候,仅把需要的安装包准备好,比如安装64位的,就只准备AMD64跟common包;安装32位的就只准备linux跟common包。最后建议 64位的系统最好不要安装32位的软件,因为64位的系统中,某些32位的运行库/共享库可能不全,32位的软件可能跑不起来,需要手动补包/库(贼麻烦!)。

     

    5.DC2013安装完成后...启动dc_shell,然而...在DC内不能直接转,我也不知道什么情况。无奈,只好直接启动lc_shell转了。

     

    6.lc_shell启动成功,坑还有,先记到这里。

     

    7.继续补坑,lc_shell启动后,需要把待转换的库放到启动目录中,才能确保转换成功。

     

    8.好了,转库成功了,综合完成了,导师又叫我去做APR了 T_T   T_T   T_T

    我只是个研一的啊QAQ,不过...这的确让我又熟悉了一遍工具。好了,我转到后端了QAQ!

     

    转载于:https://www.cnblogs.com/IClearner/p/11008940.html

    展开全文
  • WebCompiler.exe

    2013-01-17 13:38:20
    WebCompiler WebCompiler
  • Compiler vs. Interpreter

    2018-07-16 23:12:32
    What is a compiler? https://hackernoon.com/compilers-and-interpreters-3e354a2e41cf The simplest definition of a compiler is a program that translates code written in a high-level programming langu....

    What is a compiler?

    https://hackernoon.com/compilers-and-interpreters-3e354a2e41cf

    The simplest definition of a compiler is a program that translates code written in a high-level programming language (like JavaScript or Java) into low-level code (like Assembly) directly executable by the computer or another program such as a virtual machine.

    For example, the Java compiler converts Java code to Java Bytecodeexecutable by the JVM (Java Virtual Machine). Other examples are V8, the JavaScript engine from Google which converts JavaScript code to machine code or GCC which can convert code written in programming languages like C, C++, Objective-C, Go among others to native machine code.

     

    What’s in the black box?

    So far we’ve looked at a compiler as a magic black box which contains some spell to convert high-level code to low-level code. Let’s open that box and see what’s inside.

    A compiler can be divided into 2 parts.

    • The first one generally called the front end scans the submitted source code for syntax errors, checks (and infers if necessary) the type of each declared variable and ensures that each variable is declared before use. If there is any error, it provides informative error messages to the user. It also maintains a data structure called symbol table which contains information about all the symbols found in the source code. Finally, if no error is detected, another data structure, an intermediate representation of the code, is built from the source code and passed as input to the second part.
    • The second part, the back end uses the intermediate representation and the symbol table built by the front end to generate low-level code.

    Both the front end and the back end perform their operations in a sequence of phases. Each phase generates a particular data structure from another data structure emitted by the phase before it.

    The phases of the front end generally include lexical analysissyntax analysissemantic analysis and intermediate code generation while theback end includes optimization and code generation.

    Structure of a compiler

    Lexical Analysis

    The first phase of the compiler is the lexical analysis. In this phase, the compiler breaks the submitted source code into meaningful elements called lexemes and generates a sequence of tokens from the lexemes.

    lexeme can be thought of as a uniquely identifiable string of characters in the source programming language, for example, keywords such as ifwhileor funcidentifiersstringsnumbersoperators or single characters like (). or :.

    token is an object describing a lexeme. Along with the value of the lexeme(the actual string of characters of the lexeme), it contains information such as its type (is it a keyword? an identifier? an operator? …) and the position (line and/or column number) in the source code where it appears.

    Sequence of lexemes generated during lexical analysis

     

    If the compiler encounters a string of characters for which it cannot create a token, it will stop its execution by throwing an error; for example, if it encounters a malformed string or number or an invalid character (such as a non-ASCII character in Java).

    Syntax Analysis

    During syntax analysis, the compiler uses the sequence of tokens generated during the lexical analysis to generate a tree-like data structure called Abstract Syntax TreeAST for short. The AST reflects the syntactic and logical structure of the program.

    Abstract Syntax Tree generated after syntax analysis

    Syntax analysis is also the phase where eventual syntax errors are detected and reported to the user in the form of informative messages. For instance, in the example above, if we forget the closing brace } after the definition of the sum function, the compiler should return an error stating that there is a missing } and the error should point to the line and column where the } is missing.

    If no error is found during this phase, the compiler moves to the semantic analysis phase.

    Semantic Analysis

    During semantic analysis, the compiler uses the AST generated during syntax analysis to check if the program is consistent with all the rules of the source programming language. Semantic analysis encompasses

    • Type inference. If the programming language supports type inference, the compiler will try to infer the type of all untyped expressions in the program. If a type is successfully inferred, the compiler will annotate the corresponding node in the AST with the inferred type information.
    • Type checking. Here, the compiler checks that all values being assigned to variables and all arguments involved in an operation have the correct type. For example, the compiler makes sure that no variable of type String is being assigned a Double value or that a value of type Bool is not passed to a function accepting a parameter of type Double or again that we’re not trying to divide a String by an Int"Hello" / 2 (unless the language definition allows it).
    • Symbol management. Along with performing type inference and type checking, the compiler maintains a data structure called symbol tablewhich contains information about all the symbols (or names) encountered in the program. The compiler uses the symbol table to answer questions such as Is this variable declared before use?Are there 2 variables with the same name in the same scope? What is the type of this variable? Is this variable available in the current scope? and many more.

    The output of the semantic analysis phase is an annotated AST and the symbol table.

    Intermediate Code Generation

    After the semantic analysis phase, the compiler uses the annotated AST to generate an intermediate and machine-independent low-level code. One such intermediate representation is the three-address code.

    The three-address code (3AC), in its simplest form, is a language in which an instruction is an assignment and has at most 3 operands.

    Most instructions in 3AC are of the form := b <operator> c or := b.

    The above drawing depicts a 3AC code generated from an annotated ASTcreated during the compilation of the function

    func sum(n: Int): Int = {
        n * (n + 1) / 2
    }

    The intermediate code generation concludes the front end phase of the compiler.

    Optimization

    In the optimization phase, the first phase of the back end, the compiler uses different optimization techniques to improve on the intermediate code generated by making the code faster or shorter for example.

    For example, a very simple optimization on the 3AC code in the previous example would be to eliminate the temporary assignment t3 := t2 / 2 and directly assign to id1 the value t2 / 2.

    Code Generation

    In this last phase, the compiler translates the optimized intermediate code into machine-dependent code, Assembly or any other target low-level language.

    Compiler vs. Interpreter

    Let’s conclude this article with a note about the difference between compilers and interpreters.

    Interpreters and compilers are very similar in structure. The main difference is that an interpreter directly executes the instructions in the source programming language while a compiler translates those instructions into efficient machine code.

    An interpreter will typically generate an efficient intermediate representation and immediately evaluate it. Depending on the interpreter, the intermediate representation can be an AST, an annotated AST or a machine-independent low-level representation such as the three-address code.

    Difference between Compiler and Interpreter

    http://www.c4learn.com/c-programming/compiler-vs-interpreter/

    No Compiler Interpreter
    1 Compiler Takes Entire program as input Interpreter Takes Single instruction as input .
    2 Intermediate Object Code is Generated No Intermediate Object Code is Generated
    3 Conditional Control Statements are Executes faster Conditional Control Statements are Executes slower
    4 Memory Requirement : More(Since Object Code is Generated) Memory Requirement is Less
    5 Program need not be compiledevery time Every time higher level program is converted into lower level program
    6 Errors are displayed after entire program is checked Errors are displayed for every instruction interpreted (if any)
    7 Example : C Compiler Example : BASIC

    https://www.programiz.com/article/difference-compiler-interpreter

    Interpreter Compiler
    Translates program one statement at a time. Scans the entire program and translates it as a whole into machine code.
    It takes less amount of time to analyze the source code but the overall execution time is slower. It takes large amount of time to analyze the source code but the overall execution time is comparatively faster.
    No intermediate object code is generated, hence are memory efficient. Generates intermediate object code which further requires linking, hence requires more memory.
    Continues translating the program until the first error is met, in which case it stops. Hence debugging is easy. It generates the error message only after scanning the whole program. Hence debugging is comparatively hard.
    Programming language like Python, Ruby use interpreters. Programming language like C, C++ use compilers.

    https://stackoverflow.com/questions/2377273/how-does-an-interpreter-compiler-work

    Compiler characteristics:

    • spends a lot of time analyzing and processing the program
    • the resulting executable is some form of machine- specific binary code
    • the computer hardware interprets (executes) the resulting code
    • program execution is fast

    Interpreter characteristics:

    • relatively little time is spent analyzing and processing the program
    • the resulting code is some sort of intermediate code
    • the resulting code is interpreted by another program
    • program execution is relatively slow

    What is a translator?

    An S -> T translator accepts code expressed in source language S, and translates it to equivalent code expressed in another (target) language T.

    Examples of translators:

    • Compilers - translates high level code to low level code, e.g. Java -> JVM
    • Assemblers - translates assembly language code to machine code, e.g. x86as -> x86
    • High-level translators - translates code from one PL to another, e.g. Java -> C
    • Decompilers - translates low-level code to high-level code, e.g. Java JVM bytecode -> Java

    What is an interpreter?

    An S interpreter accepts code expressed in language S, and immediately executes that code. It works by fetching, analysing, and executing one instruction at a time.

    Great when user is entering instructions interactively (think Python) and would like to get the output before putting in the next instruction. Also useful when the program is to be executed only once or requires to be portable.

    • Interpreting a program is much slower than executing native machine code
    • Interpreting a high-level language is ~100 times slower
    • Interpreting an intermediate-level (such as JVM bytecode) language is ~10 slower
    • If an instruction is called repeatedly, it will be analysed repeatedly - time-consuming!
    • No need to compile code

    Differences

    Behaviour

    • A compiler translates source code to machine code, but does not execute the source or object code.

    • An interpreter executes source code one instruction at a time, but does not translate the source code.

    Performance

    • A compiler takes quite a long time to translate the source program to native machine code, but subsequent execution is fast
    • An interpreter starts executing the source program immediately, but execution is slow

    Interpretive compilers

    An interpretive compiler is a good compromise between compilers and interpreters. It translates source program into virtual machine code, which is then interpreted.

    An interpretive compiler combines fast translation with moderately fast execution, provided that:

    • VM code is lower than the source language, but higher than native machine code
    • VM instructions have simple formats (can be quickly analysed by an interpreter)

    Example: JDK provides an interpretive compiler for Java.


    enter image description here

    The Compiler translates the entire program before it is run.

    The Interpreters translates one statement into machine language, executes it, and proceeds to next statement.

    enter image description here

    Examples with Languages

    Interpreted

    • Python
    • Ruby
    • PHP
    • JAVA(Almighty)
    • Perl
    • R
    • Powershell

    compiled

    • C
    • C++
    • C#
    • Objective-C
    • SWIFT
    • Fortran

    ...


    Java is Both a Compiled and Interpreted Language

    https://techwelkin.com/compiler-vs-interpreter

    When you write a Java program, the javac compiler converts your program into something called bytecode. All the Java programs run inside a JVM (this is the secret behind Java being cross-platform language). Bytecode compiled by javac, enters into JVM memory and there it is interpreted by another program called java. This java program interprets bytecode line-by-line and converts it into machine code to be run by the JVM. Following flowchart shows how a Java program executes.

    Execution of a Java program. Java is both a compiled and interpreted language.Execution of a Java program. Java is both a compiled and interpreted language.

     

    展开全文
  • MDK版本5.23提供两个编译器,分别是ARM Compiler 5.06和ARM Compiler 6.6。 软件包也需要支持ARM Compiler 6,以下是支持ARM Compiler 6的最低软件包版本: Keil MDK-Middleware 包: 版本7.4.0及以上 Keil ARM ...

    在开始之前,建议先备份你的工程代码。

    迁移条件

    要使用 ARM Compiler 6,建议MDK的版本至少为:

    • MDK版本5.23或更高版本

    MDK版本5.23提供两个编译器,分别是 ARM Compiler 5.06 和 ARM Compiler 6.6。

    软件包也需要支持 ARM Compiler 6,以下是支持 ARM Compiler 6 的最低软件包版本:

    • Keil MDK-Middleware包: 版本7.4.0及以上
    • Keil ARM Compiler Support 包: 版本1.3.0及以上
    • ARM CMSIS 包: 版本5.0.1及以上

    切换编译器

    1. 使用MDK打开工程。

    2. 选择 Project - Options for Target from the menu

    3. 点击 Target 选项卡,找到 ARM Compiler: 下拉列表。

    4. 设置ARM编译器为 Version 6

    5. 点击 OK 键确认更改。

    切换后的ARM Compiler 6所有设置都为默认值。

    设置警告级别

    ARM Compiler 6 提供的警告级别比 ARM Compiler 5 多,如果你习惯 ARM Compiler 5 的警告级别,选择AC5-like Wamings

    可以通过在参数前面加上-Wno-来禁用特定诊断组的警告。

    例如,通过选项-Wno-missing-noreturn禁用了–Wmissing-noreturn
    Misc Controls

    在迁移的第一步中,建议将级别切换为“无警告”。 这将使您可以专注于错误消息。

    解决所有错误信息后,选择AC5-like Wamings,设置-Wno-invalid-source-encoding选项:禁用源代码编码检测,因为LCD和打印信息有中文,编译器认为这些是无效编码。

    如果想测试下代码是否规范,可以选择All wamings

    设置优化级别

    选择-Os babanced级别,平衡代码大小和性能。
    如果想代码执行速度快,可以选择-O2-O3-Ofast级别,优化性能(速度),优化依次提升,但生成的代码大小可能会变大。
    如果想减少代码大小,可以选择-Os babanced-Oz image size级别,代码大小优化依次提升。
    比如我的工程,使用-Oz image size级别编译出的code大小为103026、使用-Os babanced级别编译出的code大小为115848字节、使用-O3级别编译出的code大小为160536。差别很大。

    -O0级别没有做任何优化。注意ARM Compiler 5的-O0实际上是有优化的,所以ARM Compiler 6的-O1级别与ARM Compiler 5的-O0级别最为相似,都可以获取良好的调试体验,在调试阶段可以选用。

    不兼容的语言扩展

    主要是代码中的__align(x)__packed__weak等编译器扩展语言。解决方法是使用CMSIS定义的相关宏。

    1. 替换CMSIS头文件,这里使用的是5.6.0版本的CMSIS。
      如果安装了较新的Keil,可以在路径.\Keil_v5\ARM\PACK\ARM\CMSIS目录中找到合适的CMSIS版本。
      .\Keil_v5\ARM\PACK\ARM\CMSIS\5.6.0\CMSIS\Core\Include内的文件替换到工程code_cm3.h所在的文件夹。

    2. 修改lwip协议栈的cc.h文件,因为lwip使用到了编译器的扩展语言,比如取消结构体的对齐优化、指定变量对齐方式等,这些扩展语言 ARM Compiler 5 和 ARM Compiler 6 并不相同。
      cc.h文件中引用CMSIS提供的cmsis_compiler.h文件,然后修改结构体封装与对齐宏代码为:

      /* Arm Compiler 4/5 */
      #if   defined ( __CC_ARM )
          #define PACK_STRUCT_BEGIN __packed
          #define PACK_STRUCT_STRUCT
          #define PACK_STRUCT_END
          #define PACK_STRUCT_FIELD(fld) fld
      	#define ALIGNED(n)  __ALIGNED(n)
      
        /* Arm Compiler above 6.10.1 (armclang) */
      #elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6100100)
          #define PACK_STRUCT_BEGIN
          #define PACK_STRUCT_STRUCT __PACKED
          #define PACK_STRUCT_END
          #define PACK_STRUCT_FIELD(fld) fld
      	#define ALIGNED(n)  __ALIGNED(n)
      
      /* GNU Compiler */
      #elif defined ( __GNUC__ )
          #define PACK_STRUCT_BEGIN
          #define PACK_STRUCT_STRUCT __PACKED
          #define PACK_STRUCT_END
          #define PACK_STRUCT_FIELD(fld) fld
      	#define ALIGNED(n)  __ALIGNED(n)
      	
      #else
          #error "Unsupported compiler"
      #endif
      
    3. 程序中使用了__packed__align(n)__inline__weak的地方分别用CMSIS提供的宏__PACKED__ALIGNED(n)__INLINE__WEAK代替。

      注意__packed__attribute__((packed))的使用区别:

      ARM Compiler 5 使用__packed

      typedef __packed struct
      {
          char x;           
          int y;
      } X; 
      

      ARM Compiler 6 使用__attribute__((packed))

      typedef struct __attribute__((packed))
      {
          char x;                   
          int y;
      } X; 
      
    4. 如果使用ARM Compiler 5 时习惯使用typedef __packed struct {}X;句法,推荐改为CMSIS提供的宏句法:typedef __PACKED_STRUCT {}X;

      当使用ARM Compiler 5 时会自动扩展为:typedef __packed struct {}X;

      当使用ARM Compiler 6 时会自动扩展为:typedef struct __attribute__((packed)) {}X;

    5. 如果使用内联函数建议按照以下格式:

      __STATIC_INLINE func_name(arg)
      {
          //函数体
      }
      

      防止ARM Compiler 6在-O0-O1级别设置下,链接时出现未定义符号的错误。(在这种优化级别下__INLINE可能并不会内联)

    不兼容的语言扩展总结如下:

    ARM Compiler 5 ARM Compiler 6 CMSIS(推荐)
    __align(x) __attribute__((aligned(x))) __ALIGNED(x)
    __alignof__ __alignof__
    __ALIGNOF__ __alignof__
    __asm 汇编迁移 __ASM
    __const __attribute__((const))
    __forceinline __attribute__((always_inline))
    __global_reg 不支持
    __inline __inline__ 此功能使用取决于语言模式 __INLINE
    __STATIC_INLINE
    __int64 没有对等选项.使用 long long int64_t
    __irq __attribute__((interrupt)) Cortex-M ISR不需要此关键字
    __packed
    __packed x struct
    __attribute__((packed))
    struct x attribute((packed))
    __PACKED
    __PACKED_STRUCT x
    __pure __attribute__((const))
    __smc 不支持,使用内联汇编或等效程序
    __softfp __attribute__((pcs(“aapcs”)))
    __svc 不支持,使用内联汇编或等效程序
    __svc_indirect 不支持,使用内联汇编或等效程序
    __thread __thread
    __value_in_regs __attribute__((value_in_regs))
    __weak __attribute__((weak)) __WEAK
    __writeonly 不支持

    提示:可以使用uVision IDE的查找功能来查找上述关键字,然后做迁移处理。

    内嵌汇编

    ARM Compiler 6 完全改变了处理汇编代码的策略。

    汇编语法现在兼容GNU风格而不是ARM风格。 汇编也是由C编译器完成, 无需单独的汇编器。

    1. FreeRTOS的移植层由..\FreeRTOS\Source\portable\RVDS\ARM_CM3目录下的port.cportmacro.h文件改为..\FreeRTOS\Source\portable\GCC\ARM_CM3目录下的port.cportmacro.h文件。

      这是因为这两个文件会涉及内嵌汇编。

    2. 自定义的内嵌汇编函数。

      ARM Compiler 5:

      __asm  uint32_t __get_flash_base(void) 
      {
         IMPORT |Image$$ER_IROM1$$RO$$Base|;
          
          ldr r0,=|Image$$ER_IROM1$$RO$$Base|;
          bx lr;
      }
      

      ARM Compiler 6:(看了下帮助手册,也可以不使用汇编)

      uint32_t get_flash_base(void)
      {
          extern uint32_t Image$$ER_IROM1$$RO$$Base;
          
          return (uint32_t)&Image$$ER_IROM1$$RO$$Base;
      }
      

    语法更严格

    1. 比如某个函数之前要对外开放,.c和.h中定义和声明都相同。后来在.c文件中将该函数定义为本地函数,使用static修饰,但.h中忘记删除也没有做相应修改。这种情况下,ARM Compiler 5 不会报错,ARM Compiler 6 会报错:

      ../file_name.c(10): error: static declaration of 'func_name' follows non-static declaration

    2. 如下代码:

      for(i=0; i<0x7E-0x20; i++)
      

      ARM Compiler 5 不会报错,ARM Compiler 6 会报错:

      ../file_name.c(332): error: invalid suffix '-0x20' on integer constant

      需要将代码改为:

      for(i=0; i<0x7E - 0x20; i++)
      

    优化问题

    以下代码在 ARM Compiler 5 中,正常执行,但在 ARM Compiler 6 中,只要不是-O0级别,整个函数因为空循环问题,都被优化掉。也就是延时没有起作用。

    void delay_us (uint32_t ul_time)
    {
        ul_time *= 30; 
    	while(--ul_time != 0)}
    

    所以当升级到 ARM Compiler 6 出现使用软延时的外设不工作,比如软件IIC出错、软件SPI出错、LCD黑屏等问题,可以检查是否有类似的代码。

    需要改成:

    void delay_us (uint32_t ul_time)
    {
        ul_time *= 30; 
    	while(--ul_time != 0)
            __nop()}
    

    Keil编译器保证__nop()必定会插入一个NOP指令,在这里可以阻止编译器优化。当然,延时的初始值也要做相应的调整。

    编译时间和大小

    • -O0:Program Size: Code=200360 RO-data=20576 RW-data=96 ZI-data=76316
      Build Time Elapsed: 00:00:25

    • -O1:Program Size: Code=119328 RO-data=16824 RW-data=96 ZI-data=76300
      Build Time Elapsed: 00:00:25

    • -O2:Program Size: Code=153340 RO-data=17100 RW-data=96 ZI-data=76300
      Build Time Elapsed: 00:00:26

    • -O3:Program Size: Code=162292 RO-data=17040 RW-data=96 ZI-data=76308
      Build Time Elapsed: 00:00:27

    • -Ofast:Program Size: Code=161896 RO-data=17040 RW-data=96 ZI-data=76308
      Build Time Elapsed: 00:00:26

    • -Os balanced:Program Size: Code=115628 RO-data=17048 RW-data=96 ZI-data=76300
      Build Time Elapsed: 00:00:28

    • -Oz image size:Program Size: Code=103784 RO-data=17020 RW-data=96 ZI-data=76308
      Build Time Elapsed: 00:00:25

    • -Oz image size LTO:Program Size: Code=85888 RO-data=17064 RW-data=40 ZI-data=75960
      Build Time Elapsed: 00:00:32

    与Compiler 5 对比(我的程序-可能不具有一般性):

    • -O2:Program Size: Code=94232 RO-data=16736 RW-data=540 ZI-data=75640
      Build Time Elapsed: 00:00:16

    参考文档

    • 《Arm® Compiler Migration and Compatibility Guide》(内容详细)
    • 《Migrate ARM Compiler 5 to ARM Compiler 6》 (AN298)
    展开全文
  • 原文地址: juejin.im/post/5cea0c… 在计算机的世界中,一个Programmer多多少少有听说过编辑器,解释器,机器码,字节码这些名词, 现在我们稍微深入问一问: 这些名词分别表示的是什么? 编辑器和解释器是如何运行?...
  • 几款好的C/C++编译器(编译器而非IDE)

    万次阅读 多人点赞 2018-11-10 17:38:39
    几款好的C/C++编译器(编译器而非IDE)
  • 一看发现,Project compiler output 路径下的项目Lib文件夹没有东西。也就是说jar没有编译进来,一直在寻找问题。结果在我细心观察下,终于找到原因。下面我来给大家讲解一下原因。 1.点开Settings—-》搜索maven...
  • [ERROR] No compiler is provided in this environment. Perhaps you are running on a JRE rather than a JDK? 的问题, 原以为这是个个例, 源于同事粗心, 配置环境出问题造成, 后到百度查看一下, 遇到这个问题的不...
  • compiler.setProject(new Project()); // 编译后的.class文件存放的路径 destFile = new File("d:/generator-output/hibernate/code/"); destFile.mkdirs(); // 要编译的源文件目录 ...
  • mvn clean package -Dmaven.test.skip=true 今天项目用maven命令...Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.7.0:compile (default-compile) on project springbootdemo: Fata...
  • 背景:本项目使用JDK...Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.1 pom中如下配置maven插件,配置中声明使用JDK1.8: org.apache.maven.plugins maven-compiler-plugin 3
  • 可能很多人在使用Android studio 中的插件中会发现这个错误提示:Compiler output path for module can not be null. check your module/project settings。 会报这个错误是因为你工程没有make。因为Findbugs并不是...
  • Error:Execution failed for task ':app:compileDebugJavaWithJavac'. &gt; Compilation failed; see the compiler error output for details.编译代码的
  • JavaCompiler

    千次阅读 2016-06-13 15:17:52
    一、使用JavaCompiler接口来编译Java源程式  使用Java API来编译Java源程式有非常多方法,目前让我们来看一种最简单的方法,通过JavaCompiler进行编译。  我们能通过ToolProvider类的静态方法...
  • GCC(GNU Compiler Collection,GNU编译器套件)

    千次阅读 多人点赞 2019-05-04 23:19:00
    GCC(GNU Compiler Collection,GNU编译器套件),是由GNU开发的编程语言编译器。 gcc主要软件包如下: 名称 功能描述 cpp C 预处理器 gcc C 编译器 g++ C++编译器 gccbug 创建BUG报告的Shell脚本 ...
  • 工程编译出现问题,提示Set project compiler compliance settings to '1.5' 解决方案:右击项目-->properties-->java compiler -->选择enabel project specific setting -->Compiler compliance level :选择1.7...
  • Build -&gt; Clean Project Build -&gt; Rebuild Project 解决! 找不到 R,也可以用这个方法
  • 使用vs2015打开Qtcreator建的工程.pro文件...--- (Import): Generating new project of liteidex.pro file --- (qmake) : Using: C:\QT\QT5.9.1\5.9.1\MSVC2015\bin\qmake --- (qmake) : Working Directory: C:\Use
  • 使用这个kit _Qt_5_13_0_MinGW_32_bit

空空如也

1 2 3 4 5 ... 20
收藏数 319,560
精华内容 127,824
关键字:

compiler