Pre-requisite knowledge on compilers
 

  • What information does a compiler need to translate the following statement into (ARM) assembler code correctly:

         x = y + z;         
      

Assembler code:

 




 

Pre-requisite knowledge on compilers
 

  • What information does a compiler need to translate the following statement into (ARM) assembler code correctly:

         x = y + z;         
      

Assembler code:

     movw    r0, #:lower16:y
     movw    r0, #:upper16:y
     ldr     r0, [r0]  ???


Is this translation to ARM assembler code always correct ???

Pre-requisite knowledge on compilers
 

  • What information does a compiler need to translate the following statement into (ARM) assembler code correctly:

         x = y + z;         
      

No, if the data type of the variable y was byte, we must use:

     movw    r0, #:lower16:y
     movw    r0, #:upper16:y
     ldrsb   r0, [r0]  !!!


Otherwise, we will get a runtime error !!!

Pre-requisite knowledge on compilers
 

  • What information does a compiler need to translate the following statement into (ARM) assembler code correctly:

         x = y + z;         
      

And if the data type of the variable y was short, we must use:

     movw    r0, #:lower16:y
     movw    r0, #:upper16:y
     ldrsh   r0, [r0]  !!!


Otherwise, we will get a runtime error !!!

Pre-requisite knowledge on compilers
 

  • What information does a compiler need to translate the following statement into (ARM) assembler code correctly:

         x = y + z;         
      

Answer:

  • The compiler need to know the data type of every variable used in the statement !!!

The 2-pass compilers

Two-pass compilers:

  • A 2-pass compiler reads the source code twice to compile (= translate) a program

  • In the 1st pass, the compiler will:

      • Gather the (type) definition of all variables and functions

  • In the 2nd pass, the compiler will:

      • Use the gathered (type) information on the variables and functions to translate the function calls

        (E.g., insert the necessary conversion instructions if the data types are mismatched)

Example of a two-pass compiler: Java
 

  • The Java compiler is a 2-pass compiler

Evidence: the Java compiler can compile this code:

  public class demo
  {
     public static void main(String[] args)
     {
       System.out.println(x); // How can Java compiler     
                              // know the data type of x ? 
     }                // Answer: read input file twice !

     static int x = 1234;
  }
   

DEMO:   /home/cs255001/demo/tmp/demo.java

The 1-pass compilers

One-pass compilers:

  • A 1-pass compiler reads the source code once to compile (= translate) the program

  • In the one-pass compiler, the compiler will:

      • Gather the definition of all variables and functions while it is translating the program !!!

Notable fact about 1 pass compilers:

  • When a 1-pass compiler processes a statement in a program, it cannot use the information that are given below that statement in the program !!!

Example of a one-pass compiler: C
 

  • The C compiler is a 1-pass compiler

Evidence: the C compiler can compile this code:

  #include <stdio.h>

  int x = 1234;

  int main( )
  {
     printf("%d\n", x);
  }
   

DEMO:   /home/cs255001/demo/tmp/demo.c

Example of a one-pass compiler: C
 

  • The C compiler is a 1-pass compiler

Evidence: the C compiler can not compile this code:

  #include <stdio.h>

  int main( )
  {
     printf("%d\n", x);  // <-- error !
  }

  int x = 1234; 

Reason: the data type of x is not (yet) known when the C compiler processes the highlight line !!

Pros and cons of 1-pass and 2-pass compilers
 

  • 2-pass compilers (like Java):

      • Pro:   convenience for programmers
      • Con:   slower

  • 1-pass compilers (like Java):

      • Pro:   faster
      • Con:   clumbersome....

        Specifically: the C language needs to use declarations to convey the data type information of (global) variables and function prototypes