1 / 30

Lecture #15, May 22, 2007

Lecture #15, May 22, 2007. Project 3 C calling convention The IA32 module Translating. Project #3. In class today we describe project #3 It is due Thursday, June 7, 2007 at 5:00 PM this is in 17 days. In order to get the course graded, there will be no extensions

fahim
Download Presentation

Lecture #15, May 22, 2007

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Lecture #15, May 22, 2007 • Project 3 • C calling convention • The IA32 module • Translating

  2. Project #3 • In class today we describe project #3 • It is due Thursday, June 7, 2007 at 5:00 PM • this is in 17 days. • In order to get the course graded, there will be no extensions • Final exam will be week of June 11 • Monday June 11

  3. Properties of the X86 translation • In project 3 we translate IR1 to x86 assembly. • Because of the sparseness of the X86 register set we assume variables all live in memory. • We have a number of types of variables • local variables (VAR n) • instance variables (MEMBER(address,n)) • parameters (PARAM n) • temporaries (TEMP n) • How do we access these variables? • Where in memory do they live?

  4. C calling convention • Callers Job • Before the call • Save any registers that might be needed later • push the n arguments in reverse order • call the function • after the call • remove the arguments from the stack • restore any saved registers • return value is in register %eax • Callees Job • Set up the framepointer (%ebp) • allocate space for local variables on the stack • reset the old framepointer • put return value in %eax • return

  5. . . . arg0 higher addresses → return address argn arg1 The X86 stack • Our translation is faithful to the calling convention of the GNU compiler. • The stack on entry to a function looks as follows: %esp

  6. return address var1 argn old %ebp var0 . . . temp1 arg0 higher addresses → Allocating room for locals and temps • Temporaries and locals are treated identically • One exception locals may have some initialization code • Everything is reachable via the frame pointer (%ebp) %ebp %esp return address 4(%ebp) arg0 8(%ebp) arg1 12(%ebp) var0 -4(%ebp) var1 -8(%ebp)

  7. prolog Call prolog precall postcall Return epilog epilog Procedure Call • Has 4 parts • Precall • Postreturn • Prolog • Epilog

  8. Caller - Precall • Save registers that need it • write them to memory • save them on the stack • Push arguments on the stack • pushL arg2 • pushL arg1 • pushL arg0 • call the function • call _malloc

  9. Caller - Postcall • Remove n arguments from stack • addl $(4*n), %esp • Pop saved registers if any

  10. . . . arg0 higher addresses → return address argn arg1 Callee -- Prolog • Set up the framepointer (%ebx) • pushL %ebp # save the old framepointer • movl %esp,%ebp # initialize new framepointer • allocate space for local variables on the stack • subl $(n*4),%esp #subtract from spackpointer %esp

  11. return address var2 argn old %ebp var1 . . . temp1 arg0 higher addresses → Callee -- Epilog • put return value in %eax • movL ans,%eax • reset the old framepointer • movl %ebp,%esp • popl %ebp • return • return %esp %ebp

  12. The IA32 module • We build some data structures to represent IA32 code as SML data. • Registers • represent the machine registers • Modes • represent the addressing modes • Instructions • represent instructions • every instruction has room for a label and a comment

  13. Registers datatype Register = eax (* Accumulator *) | ebx (* Base *) | ecx (* Count *) | edx (* Data *) | esi (* Source index *) | edi (* Destination index *) | ebp (* Base pointer *) | esp (* Stack Pointer *) | eip (* Instruction pointer *) | eflag (* Flags *)

  14. Modes type Label = string; datatype Mode = Mem of string (* top *) | % of Register (* %eax *) | $ of int (* $12 *) | & of (int * Mode); (& n(%eax) *)

  15. Instructions datatype IA32 = Movl of (Label * Mode * Mode * string) | Xchgl of (Label * Mode * Mode * string) | Addl of (Label * Mode * Mode * string) | Subl of (Label * Mode * Mode * string) | Imull of (Label * Mode * Mode * string) | Andl of (Label * Mode * Mode * string) | Orl of (Label * Mode * Mode * string) | Xorl of (Label * Mode * Mode * string) | Cmpl of (Label * Mode * Mode * string) | Idivl of (Label * Mode * string) | Negl of (Label * Mode * string) | Notl of (Label * Mode * string) | Incl of (Label * Mode * string) | Decl of (Label * Mode * string) | Pushl of (Label * Mode * string) | Popl of (Label * Mode * string) | Jmp of (Label * Label * string) | Jz of (Label * Label * string) | Jnz of (Label * Label * string) | Jl of (Label * Label * string) | Jnl of (Label * Label * string) | Jg of (Label * Label * string) | Jng of (Label * Label * string)

  16. lower case instuctions fun movl (m1,m2) = Movl("",m1,m2,""); fun xchgl(m1,m2) = Xchgl("",m1,m2,""); fun addl (m1,m2) = Addl("",m1,m2,""); fun subl (m1,m2) = Subl("",m1,m2,""); fun imull(m1,m2) = Imull("",m1,m2,""); fun andl (m1,m2) = Andl("",m1,m2,""); fun orl (m1,m2) = Orl("",m1,m2,""); fun xorl (m1,m2) = Xorl("",m1,m2,""); fun cmpl (m1,m2) = Cmpl("",m1,m2,""); fun idivl(m1) = Idivl("",m1,""); • etc

  17. Adding Labels fun addLabel l x = case x of Movl (_,m1,m2,s) => Movl (l,m1,m2,s) | Xchgl(_,m1,m2,s) => Xchgl(l,m1,m2,s) | Addl (_,m1,m2,s) => Addl (l,m1,m2,s) | Subl (_,m1,m2,s) => Subl (l,m1,m2,s) | Imull(_,m1,m2,s) => Imull(l,m1,m2,s) | Andl (_,m1,m2,s) => Andl (l,m1,m2,s) | Orl (_,m1,m2,s) => Orl (l,m1,m2,s) | Xorl (_,m1,m2,s) => Xorl (l,m1,m2,s) | Cmpl (_,m1,m2,s) => Cmpl (l,m1,m2,s)

  18. Adding Comments fun addComment s x = case x of Movl (l,m1,m2,_) => Movl (l,m1,m2,s) | Xchgl(l,m1,m2,_) => Xchgl(l,m1,m2,s) | Addl (l,m1,m2,_) => Addl (l,m1,m2,s) | Subl (l,m1,m2,_) => Subl (l,m1,m2,s) | Imull(l,m1,m2,_) => Imull(l,m1,m2,s) | Andl (l,m1,m2,_) => Andl (l,m1,m2,s) | Orl (l,m1,m2,_) => Orl (l,m1,m2,s) | Xorl (l,m1,m2,_) => Xorl (l,m1,m2,s) | Cmpl (l,m1,m2,_) => Cmpl (l,m1,m2,s)

  19. Translation scheme • Translate every IR.Exp into a IA32 list • Simple translation scheme • Every translation of an Expression leaves the answer in the %eax register.

  20. Getting started fun compileE exp = case exp of BINOP(ADD,x,y) => let val xCode = compileE x val yCode = compileE y in xCode @ [ pushl(%eax) ] @ yCode @ [ popl(%ebx), addl(%ebx,%eax) ] end | CONST(s,typ) => let val n = valOf(Int.fromString s) in [ movl($n,%eax) ] end | NAME s => [ movl(Mem s,%eax) ]

  21. Translating function calls fun compileE exp = case exp of | CALL(NAME f,args) => let fun pushargs [] = [] | pushargs (x::xs) = (pushargs xs) @ (compileE x) @ [ pushl (%eax) ] val n = length args in (pushargs args) @ [call f] @ [addl($(wdsize*n),%esp)] end

  22. Translating Statements fun compileS x = case x of MOVE(dest,src) => (compileE src)@ [pushl (%eax)]@ (address dest)@ [popl (%ebx),Movl("",%ebx,&(0,%eax), sSTMT x)] | JUMP n => [Jmp("",label32 n,"")]

  23. return address var2 argn old %ebp var1 . . . temp1 arg0 higher addresses → Translating addresses fun address (VAR n) = [movl(%ebp,%eax) , addl ($(~(n + wdsize)),%eax)] | address (PARAM n) = [movl(%ebp,%eax) ,addl ($( 2*wdsize + n),%eax) ] %esp %ebp

  24. Translating Function definitions fun compileFunc (FUNC(nm,_,vs,ss)) = let fun size((typ),x) = ProgramTypes.typeSize typ + x val n = foldr size 0 vs in [ Pushl(nm,%ebp,"Entering "^nm) , movl (%esp,%ebp) , subl($ n, %esp) ] @ (compileSS ss) @ [ Movl("",%ebp,%esp,"Default Epilog") , popl (%ebp) , return() ] end; Prolog Epilog

  25. Example class T { int instance2 = 0; public int f(int j) { int k = 1; return (j+k); } }

  26. IR1 code ================================= The Class Table with inherited instance variables: class Object has vars: class T has vars: 0: int instance2 := 0 ================================= T_f(int P1) int V0; V0 := 1 return MEM(P1) + MEM(V0)

  27. IA32 code T_f: pushl %ebp # Entering T_f movl %esp,%ebp subl $4,%esp movl $1,%eax pushl %eax movl %ebp,%eax addl $-4,%eax popl %ebx movl %ebx,0(%eax) # V0 := 1 movl %ebp,%eax addl $12,%eax movl 0(%eax),%eax # P1 pushl %eax movl %ebp,%eax addl $-4,%eax movl 0(%eax),%eax # V0 popl %ebx addl %ebx,%eax movl %ebp,%esp # Epilog popl %ebp return movl %ebp,%esp # Default Epilog popl %ebp return

  28. Using the assembler • We will write some code in class.

  29. What to turn in • You should hand in the module Phase3.sml • It should include a function • compileFunc :: IR1.FUNC list -> IA32.IA32 list • You should also write a function • toplevel :: string -> string -> unit • toplevel src dest • parses and compiles src to IA32 list • Then prints it out as assembly code to file dest

  30. The template • I will supply a template. • The template will provide drivers and a complete solution to projects 1 and 2. • I will supply a file runtime.c • you will link your code with this file • You may ask for the template by emailing me. • I have posted the IA32 code on the web page.

More Related