Presentation is loading. Please wait.

Presentation is loading. Please wait.

Intermediate Representation I High-Level to Low-Level IR Translation.

Similar presentations


Presentation on theme: "Intermediate Representation I High-Level to Low-Level IR Translation."— Presentation transcript:

1 Intermediate Representation I High-Level to Low-Level IR Translation

2 - 1 - Where We Are... Lexical Analysis Syntax Analysis Semantic Analysis Intermediate Code Gen Source code (character stream) token stream abstract syntax tree abstract syntax tree + symbol tables, types Intermediate code regular expressions grammars static semantics

3 - 2 - Intermediate Representation (aka IR) v The compilers internal representation »Is language-independent and machine- independent ASTIR Pentium Java bytecode Itanium TI C5x ARM optimize Enables machine independent and machine dependent optis

4 - 3 - What Makes a Good IR? v Captures high-level language constructs »Easy to translate from AST »Supports high-level optimizations v Captures low-level machine features »Easy to translate to assembly »Supports machine-dependent optimizations v Narrow interface: small number of node types (instructions) »Easy to optimize »Easy to retarget

5 - 4 - Multiple IRs v Most compilers use 2 IRs: »High-level IR (HIR): Language independent but closer to the language »Low-level IR (LIR): Machine independent but closer to the machine »A significant part of the compiler is both language and machine independent! ASTHIR Pentium Java bytecode Itanium TI C5x ARM optimize LIR optimize C++ C Fortran

6 - 5 - High-Level IR v HIR is essentially the AST »Must be expressive for all input languages v Preserves high-level language constructs »Structured control flow: if, while, for, switch »Variables, expressions, statements, functions v Allows high-level optimizations based on properties of source language »Function inlining, memory dependence analysis, loop transformations

7 - 6 - Low-Level IR v A set of instructions which emulates an abstract machine (typically RISC) v Has low-level constructs »Unstructured jumps, registers, memory locations v Types of instructions »Arithmetic/logic (a = b OP c), unary operations, data movement (move, load, store), function call/return, branches

8 - 7 - Alternatives for LIR v 3 general alternatives »Three-address code or quadruples  a = b OP c  Advantage: Makes compiler analysis/opti easier »Tree representation  Was popular for CISC architectures  Advantage: Easier to generate machine code »Stack machine  Like Java bytecode  Advantage: Easier to generate from AST

9 - 8 - Three-Address Code v a = b OP c »Originally, because instruction had at most 3 addresses or operands  This is not enforced today, ie MAC: a = b * c + d »May have fewer operands v Also called quadruples: (a,b,c,OP) v Example a = (b+c) * (-e) t1 = b + c t2 = -e a = t1 * t2 Compiler-generated temporary variable

10 - 9 - IR Instructions v Assignment instructions »a = b OP C (binary op)  arithmetic: ADD, SUB, MUL, DIV, MOD  logic: AND, OR, XOR  comparisons: EQ, NEQ, LT, GT, LEQ, GEQ »a = OP b (unary op)  arithmetic MINUS, logical NEG »a = b : copy instruction »a = [b] : load instruction »[a] = b : store instruction »a = addr b: symbolic address v Flow of control »label L: label instruction »jump L: unconditional jump »cjump a L : conditional jump v Function call »call f(a1,..., an) »a = call f(a1,..., an) v IR describes the instruction set of an abstract machine

11 - 10 - IR Operands v The operands in 3-address code can be: »Program variables »Constants or literals »Temporary variables v Temporary variables = new locations »Used to store intermediate values »Needed because 3-address code not as expressive as high-level languages

12 - 11 - Class Problem n = 0; while (n < 10) { n = n+1; } Convert the following code segment to assembly code

13 - 12 - Translating High IR to Low IR v May have nested language constructs »E.g., while nested within an if statement v Need an algorithmic way to translate »Strategy for each high IR construct »High IR construct  sequence of low IR instructions v Solution »Start from the high IR (AST like) representation »Define translation for each node in high IR »Recursively translate nodes

14 - 13 - Notation v Use the following notation: »[[e]] = the low IR representation of high IR construct e v [[e]] is a sequence of low IR instructions v If e is an expression (or statement expression), it represents a value »Denoted as: t = [[e]] »Low IR representation of e whose result value is stored in t v For variable v: t = [[v]] is the copy instruction »t = v

15 - 14 - Translating Expressions v Binary operations: t = [[e1 OP e2]] »(arithmetic, logical operations and comparisons) v Unary operations: t = [[OP e]] OP e1e2 t1 = [[e1]] t2 = [[e2]] t1 = t1 OP t2 OP e1 t1 = [[e1]] t = OP t1

16 - 15 - Translating Array Accesses v Array access: t = [[ v[e] ]] »(type of e is array [T] and S = size of T) t1 = addr v t2 = [[e]] t3 = t2 * S t4 = t1 + t3 t = [t4] /* ie load */ array ve

17 - 16 - Translating Structure Accesses v Structure access: t = [[ v.f ]] »(v is of type T, S = offset of f in T) t1 = addr v t2 = t1 + S t = [t2] /* ie load */ struct vf

18 - 17 - Translating Short-Circuit OR v Short-circuit OR: t = [[e1 SC-OR e2]] »e.g., || operator in C/C++ t = [[e1]] cjump t Lend t = [[e2]] Lend: semantics: 1. evaluate e1 2. if e1 is true, then done 3. else evaluate e2 SC-OR e1e2

19 - 18 - Class Problem v Short-circuit AND: t = [[e1 SC-AND e2]] »e.g., && operator in C/C++ Semantics: 1. Evaluate e1 2. if e1 is true, then evaluate e2 3. else done

20 - 19 - Translating Statements v Statement sequence: [[s1; s2;...; sN]] v IR instructions of a statement sequence = concatenation of IR instructions of statements [[ s1 ]] [[ s2 ]]... [[ sN ]] seq s1s2sN...

21 - 20 - Assignment Statements v Variable assignment: [[ v = e ]] v Array assignment: [[ v[e1] = e2 ]] v = [[ e ]] t1 = addr v t2 = [[e1]] t3 = t2 * S t4 = t1 + t3 t5 = [[e2] [t4] = t5 /* ie store */ recall S = sizeof(T) where v is array(T)

22 - 21 - Translating If-Then [-Else] v [[ if (e) then s ]] v [[ if (e) then s1 else s2 ]] t1 = [[ e ]] t2 = not t1 cjump t2 Lelse Lthen: [[ s1 ]] jump Lend Lelse: [[ s2 ]] Lend: t1 = [[ e ]] t2 = not t1 cjump t2 Lend [[ s ]] Lend: How could I do this more efficiently??

23 - 22 - While Statements v [[ while (e) s ]] Lloop: t1 = [[ e ]] t2 = NOT t1 cjump t2 Lend [[ s ]] jump Lloop Lend: or while-do translation do-while translation t1 = [[ e ]] t2 = NOT t1 cjump t2 Lend Lloop: [[ s ]] t3 = [[ e ]] cjump t3 Lloop Lend: Which is better and why?

24 - 23 - Switch Statements v [[ switch (e) case v1:s1,..., case vN:sN ]] t = [[ e ]] L1: c = t != v1 cjump c L2 [[ s1 ]] jump Lend /* if there is a break */ L2: c = t != v2 cjump c L3 [[ s2 ]] jump Lend /* if there is a break */... Lend: Can also implement switch as table lookup. Table contains target labels, ie L1, L2, L3. ‘t’ is used to index table. Benefit: k branches reduced to 1. Negative: target of branch hard to figure out in hardware

25 - 24 - Call and Return Statements v [[ call f(e1, e2,..., eN) ]] v [[ return e ]] t1 = [[ e1 ]] t2 = [[ e2 ]]... tN = [[ eN ]] call f(t1, t2,..., tN) t = [[ e ]] return t

26 - 25 - Nested Expressions v Translation recurses on the expression structure v Example: t = [[ (a – b) * (c + d) ]] t1 = a t2 = b t3 = t1 – t2 t4 = c t5 = d t5 = t4 + t5 t = t3 * t5 [[ (a – b) ]] [[ (c + d) ]] [[ (a-b) * (c+d) ]]

27 - 26 - Nested Statements v Same for statements: recursive translation v Example: t = [[ if c then if d then a = b ]] t1 = c t2 = NOT t1 cjump t2 Lend1 t3 = d t4 = NOT t3 cjump t4 Lend2 t3 = b a = t3 Lend2: Lend1: [[ if c... ]] [[ a = b ]] [[ if d... ]]

28 - 27 - Class Problem for (i=0; i<100; i++) { A[i] = 0; } if ((a > 0) && (b > 0)) c = 2; else c = 3; Translate the following to the generic assembly code discussed

29 - 28 - Issues v These translations are straightforward v But, inefficient: »Lots of temporaries »Lots of labels »Lots of instructions v Can we do this more intelligently? »Should we worry about it?

30 Intermediate Representation II Storage Allocation and Management

31 - 30 - Overview v Program Organization v Memory pools »Static »Automatic »Dynamic v Activation Records

32 - 31 - 2 Classes of Storage in Processor v Registers »Fast access, but only a few of them »Address space not visible to programmer  Doesn’t support pointer access! v Memory »Slow access, but large »Supports pointers v Storage class for each variable generally determined when map HIR to LIR

33 - 32 - 4 Distinct Regions of Memory v Code space – Instructions to be executed »Best if read-only v Static (or Global) – Variables that retain their value over the lifetime of the program v Stack – Variables that is only as long as the block within which they are defined (local) v Heap – Variables that are defined by calls to the system storage allocator (malloc, new)

34 - 33 - 33 Virtual Address Space v Traditional Organization »Code Area at the bottom »Static Data above  Constants  Static strings, variable  Global variables »Heap  Grows upward »Stack  Grows downward »Lot ’ s of free VM in between 0x0 0xffffffff

35 - 34 - Class Problem Specify whether each variable is stored in register or memory. For memory which area of the memory? int a; void foo(int b, double c) { int d; struct { int e; char f;} g; int h[10]; char i = 5; float j; }

36 - 35 - 35 Zooming In. v Close look on the code area

37 - 36 - 36 Execution Stack v A memory area at the top of the VM »Grows downward »Grows on demand (with OS collaboration) v Purpose »Automatic storage for local variables

38 - 37 - Overview v Program Organization v Memory pools »Static »Automatic »Dynamic v Activation Records v Parameter Passing Modes v Symbol Table

39 - 38 - Memory Pools v Where does memory comes from ? v Three pools »Static »Automatic »Dynamic Static Automatic Dynamic

40 - 39 - Static Pool v Content »All the static “ strings ” that appear in the program »All the static constants used in the program »All the global/static variables declared in the program  static int  static arrays  static records  static.... v Allocation ? »Well... it is static, i.e.,  All the sizes are determined at compile time.  Cannot grow or shrink Static

41 - 40 - Dynamic Pool v Content »Anything allocated by the program at runtime v Allocation »Depends on the language  C malloc  C++/Java/C#new  ML/Lisp/Schemeimplicit v Deallocation »Depends on the language  Cfree  C++delete  Java/C#/ML/Lisp/SchemeGarbage collection Dynamic

42 - 41 - Automatic Pool v Content »Local variables »Actuals (arguments to methods/functions/procedures) v Allocation »Automatic when calling a method/function/procedure v Deallocation »Automatic when returning from a method/function/procedure v Management policy »Stack-like

43 - 42 - Overview v Program Organization v Memory pools »Static »Automatic »Dynamic v Activation Records

44 - 43 - 43 Activation Records  Also known as “ Frames ” »A record pushed on the execution stack

45 - 44 - Creating the Frame v Three actors »The caller »The CPU »The callee int foo(int x,int y) {... } bar() {... x = foo(3,y);... } int foo(int x,int y) {... } bar() {... x = foo(3,y);... }

46 - 45 - Creating the Frame v Three actors »The caller »The CPU »The callee int foo(int x,int y) {... } bar() {... x = foo(3,y);... } int foo(int x,int y) {... } bar() {... x = foo(3,y);... } Actual Function Call

47 - 46 - Creating the Frame v Three actors »The caller »The CPU »The callee int foo(int x,int y) {... } bar() {... x = foo(3,y);... } int foo(int x,int y) {... } bar() {... x = foo(3,y);... }

48 - 47 - 47 Closeup on management data

49 - 48 - 48 Returning From a Call v Easy »The RET instruction simply  Access MGMT Area from FP  Restores SP  Restores FP  Transfer control to return address

50 - 49 - 49 Returning From a Call v Easy »The RET instruction simply  Access MGMT Area from FP  Restores SP  Restores FP  Transfer control to return address

51 - 50 - 50 Returning From a Call v Easy »The RET instruction simply  Access MGMT Area from FP  Restores SP  Restores FP  Transfer control to return address

52 - 51 - 51 Returning From a Call v Easy »The RET instruction simply  Access MGMT Area from FP  Restores SP  Restores FP  Transfer control to return address

53 - 52 - Stack Frame Construction Example int f(int a) { int b, c; } void g(int a) { int b, c;... b = f(a+c);... } main() { int a, b;... g(a+b);... } a b a + b ret addr to main FP/SP for main b c a + c ret addr to g FP/SP for g b main g f c parameter local var... Note: I have left out the temp part of the stack frame

54 - 53 - Class Problem For the following program: int foo(int a) { int x; if (a <= 1) return 1; x = foo(a-1) + foo(a-2); return (x); } main() { int y, z = 10; y = foo(z); } 1. Show the first 3 stack frames created when this program is executed (starting with main). 2. Whats the maximum number of frames the stack grows to during the execution of this program?

55 - 54 - Data Layout v Naive layout strategies generally employed »Place the data in the order the programmer declared it! v 2 issues: size, alignment v Size – How many bytes is the data item? »Base types have some fixed size  E.g., char, int, float, double »Composite types (structs, unions, arrays)  Overall size is sum of the components (not quite!)  Calculate an offset for each field

56 - 55 - Memory Alignment v Cannot arbitrarily pack variables into memory  Need to worry about alignment v Golden rule – Address of a variable is aligned based on the size of the variable »Char is byte aligned (any addr is fine) »Short is halfword aligned »Int is word aligned »This rule is for C/C++, other languages may have a slightly different rules

57 - 56 - Structure Alignment (for C) v Each field is layed out in the order it is declared using Golden Rule for aligning v Identify largest field »Starting address of overall struct is aligned based on the largest field »Size of overall struct is a multiple of the largest field »Reason for this is so can have an array of structs

58 - 57 - Structure Example struct { char w; int x[3] char y; short z; } Largest field is int (4 bytes) struct size is multiple of 4 struct starting addr is word aligned Struct must start at word-aligned address char w  1 byte, start anywhere x[3]  12 bytes, but must start at word aligned addr, so 3 empty bytes between w and x char y  1byte, start anywher short z  2 bytes, but must start at halfword aligned addr, so 1 empty byte between y and z Total size = 20 bytes!

59 - 58 - Class Problem short a[100]; char b; int c; double d; short e; struct { char f; int g[1]; char h[2]; } i; How many bytes of memory does the following sequence of C declarations require (int = 4 bytes) ?


Download ppt "Intermediate Representation I High-Level to Low-Level IR Translation."

Similar presentations


Ads by Google