CSC448: Phases: Code Generation [8/8] Previous pageContents

For programs, suppose that all the global variable declarations precede the function declarations, then we have:

    code (T1 x1) = asmd1
    ...
    code (Tn xn) = asmdn
    context((decl1 ... decln fundef1 ... fundefm)) |- code (fundef1) = asmf1
    ...
    context((decl1 ... decln fundef1 ... fundefm)) |- code (fundefm) = asmfm
    ------------------------------------------------------------------------
    code ((decl1 ... decln fundef1 ... fundefm)) =
      .text
      asmf1
      ...
      asmfm
      .data
      asmd1
      ...
      asmdm

For global variable declarations:

    --------------------------------------------
    code ((T x;)) =
      .align 4
      .global x
      x:
      .long  0

For function declarations:

    G,x1:S1,...,xn:Sn |- code (compoundStat) = asm
    -------------------------------------------------
    G |- code ((T f(S1 x1,...,Sn xn) compoundStat)) =
          .align 4
          .global f
          f:
          pushl   %ebp
          movl    %esp, %ebp
          asm

Recall the three-address syntax for statements:

    stat ::= { decl1 ... decln stat1 ... statm }     (StatCompound)
           | exp;                                    (StatExp)
           | goto l;                                 (StatGoto)
           | if (exp) goto l1; else goto l2;         (StatIf)
           | return;                                 (StatReturn)
           | return exp;                             (StatReturn)
           | skip;                                   (StatSkip)

case StatCompound:

    G,x1:T1,...,xn:Tn |- code (stat1) = asm1
    ...
    G,x1:T1,...,xn:Tn |- code (statm) = asmm
    ---------------------------------------------------
    G |- code ({ T1 x1; ... Tn xn; stat1 ... statm }) =
          subl $(n*intSize), %esp
          asm1
          ...
          asmm
          addl $(n*intSize), %esp

case StatExp:

    G |- code (exp) = asm
    ---------------------------------------------------
    G |- code ((exp;)) = asm

case StatGoto:

    ---------------------------------------------------
    G |- code ((goto l;)) = jmp l

case StatIf:

    G |- location (v) = v''
    ---------------------------------------------
    G |- code ((if (v) goto l1; else goto l2;)) =
          movl   v'', %eax
          testl  %eax, %eax
          jne    %l1
          jmp    %l2

case StatReturn:

    ---------------------------------------------
    G |- code ((return;)) =
          movl   %ebp, %esp
          popl   %ebp
          ret
    
    G |- location (v) = v''
    ---------------------------------------------
    G |- code ((return v;)) =
          movl   v'', %eax
          movl   %ebp, %esp
          popl   %ebp
          ret

case StatSkip:

    ---------------------------------------------
    G |- code ((skip;)) = nop

Recall the three-address syntax for expressions:

    exp ::= rhs
          | lhs = rhs                               (ExpAssign)

    lhs ::= x                                       (ExpVar)
          | x[v]                                    (ExpArrayAccess)

    rhs ::= n                                       (ExpInt)
          | x                                       (ExpVar)
          | "value"                                 (ExpString)
          | new T[v]                                (ExpNew)
          | x[v]                                    (ExpArrayAccess)
          | unop v                                  (ExpUnOp)
          | vL binop vR                             (ExpBinOp)
          | f(v1,...,vn)                            (ExpFunCall)

First generate code for the RHS, and put the result in %eax

case ExpInt:

    ---------------------------------------------
    G |- code (n) =
          movl   $n, %eax

case ExpVar:

    G |- location (x) = x''
    ---------------------------------------------
    G |- code (x) =
          movl   x'', %eax

case ExpString:

    ---------------------------------------------
    G |- code (("value")) =
          movl lab_string, %eax
    
          lab_string:
          .int  'v'
          .int  'a'
          .int  'l'
          .int  'u'
          .int  'e'
          .int  0

case ExpNew:

    G |- location (v) = v''
    ---------------------------------------------
    G |- code ((new T[v])) =
          movl   v'', %eax
          sall   $(log_2(intSize)), %eax
          push   %eax
          call   _malloc
          addl   $(1*intSize), %esp

case ExpArrayAccess:

    G |- location (x) = x''
    G |- location (v) = v''
    ---------------------------------------------
    G |- code (x[v]) =
          movl   x'', %edx
          movl   v'', %ecx
          sall   $(log_2(intSize)), %ecx
          addl   %ecx, %edx
          movl   0(%edx), %eax

case ExpUnOp:

    G |- location (v) = v''
    ---------------------------------------------
    G |- code ((- v)) =
          movl   v1'', %eax
          negl   %eax

case ExpBinOp:

    G |- location (v1) = v1''
    G |- location (v2) = v2''
    ---------------------------------------------
    G |- code ((v1 + v2)) =
          movl   v1'', %eax
          movl   v2'', %ecx
          addl   %ecx, %eax

case ExpFunCall:

    G |- location (v1) = v1''
    ...
    G |- location (vn) = vn''
    ---------------------------------------------
    G |- code ((f(v1,...,vn))) =
          pushl  vn''
          ...
          pushl  v1''
          call   f
          addl   $(n*intSize), %esp

Then generate code for the LHS, if any, getting the result from %eax

case ExpVar:

      G |- location (x) = x''
      ---------------------------------------------
      G |- code (x) =
            movl   %eax, x''

case ExpArrayAccess:

      G |- location (x) = x''
      G |- location (v) = v''
      ---------------------------------------------
      G |- code (x[v]) =
            movl   x'', %edx
            movl   v'', %ecx
            sall   $(log_2(intSize)), %ecx
            addl   %ecx, %edx
            movl   %eax, 0(%edx)

Previous pageContents