Presentation is loading. Please wait.

Presentation is loading. Please wait.

CSE 131B – Compiler Construction II Discussion 6: Operations, Branches and Functions 2/21/2007.

Similar presentations


Presentation on theme: "CSE 131B – Compiler Construction II Discussion 6: Operations, Branches and Functions 2/21/2007."— Presentation transcript:

1 CSE 131B – Compiler Construction II Discussion 6: Operations, Branches and Functions 2/21/2007

2 Overview  Phase 1  Some Phase 2

3 Refresher  Remember to work in increments! BEGIN END..section“.text”.align4.globalmain main: set.SAVE.main, %g1 save%sp, %g1, %sp ret restore.SAVE.main = -(92 + 0) & -8

4 Refresher  Remember to work in increments! VAR x: INTEGER; BEGIN x := 99; END..section“.data”.align4.varX:.word0! Global label method.section“.text”.align4.globalmain main: set.SAVE.main, %g1 save%sp, %g1, %sp set99, %l0 st%l0, [%fp-4]! Temporary storage set.varX, %l0 ld[%fp-4], %l1 st%l1, [%l0] ret restore.SAVE.main = -(92 + 4) & -8! 4 bytes of temp storage

5 General Principles  Start off doing simple load-load-compute-store. Don’t worry about efficiency or speed, as you won’t get any points for those.  VarSTOs will always be somewhere in memory (offsets from %fp or %g6). If the VarSTO is a parameter, it is initially in the I-registers until you move it to it’s proper place (%fp+68, %fp+72, etc).  ExprSTOs will always be in some temporary memory location (offsets from %fp).  ConstSTOs shouldn’t be stored in the run-time memory. Just do a “set” instruction with the value when you need it.

6 Things to Know  We won't be passing more than 6 parameters to procedures (hence, allowing you to rely on the %o0-%o5/%i0-%i5 registers). For the purposes of procedures with receiver variables, we'll only pass up to 5 parameters (with the 6th parameter implicitly being "this").  We WILL test more than 4K local variables/temporary memory (as well as large arrays). Make sure your load/store instructions and save instructions can handle those cases where the constant is more than +/- 4K.  When you make labels for things, make sure you make them unique. Think of cases like a procedure in Oberon named "main" (this is legal). You should name- mangle procedure, variable, and loop labels with a "." in front of them, as Oberon won't allow names with a "." (and thus avoid colliding names).  Don't assume statements will be simple. We may having complex things like: Z := X + (Y + (Z + (W + (B + C)))) DIV (X + Y + A + B + C). Your compiler should easily scale if you properly do the load-load-compute-store scheme.

7 Phase 1 –Arithmetic Expressions  Given (assume x is in %fp-4): x := x + 7; ld[%fp-4], %l0 set7, %l1 add%l0, %l1, %l0 st%l0, [%fp-8]! Tmp ld[%fp-8], %l0 st%l0, [%fp-4]

8 Arithmetic Expressions  OK, that’s simple for a simple statement.  What if we had a statement like this: Z := ((A+B) + (C+D)) + ((E+F) + (X+Y))  Which registers do we use???

9 Method 1 – Simplicity  Doing load-load-compute-store will only require 3 registers at any given time.  Thus, even with that complicated example, you just load two operands, compute it, and store the result into some temporary memory location. Then, the registers are all free again for use.  You will need to store the temporary memory location you used in your ExprSTO so you can reference it later.

10 Method 2 – Register Allocation  Have some data structure that lets you know what registers are free and which are currently in use.  Every time you need a register, request one from the data structure, which will remove that register from the available list  When you are done with a register, let the data structure know it is available for use again.  This is a good method too!

11 Method 2 – Register Allocation  Make some class (RegClass) with: GetFreeReg() – returns an available register FreeReg(String r) – marks that “r” is available  You will need to store the allotted register in your ExprSTO so you can reference it later.

12 Method 3 – Clumsy/Bad!  We can take advantage of Java Strings and encapsulate chunks of assembly code within each ExprSTO.  This will require a fixed register approach – you will need to have registers that serve a specific purpose (ie, a specific register is the result of an operation, etc).  Very confusing to keep track of – avoid this unless you really feel it is necessary!

13 Method 3 – Clumsy/Bad!  Always put operands into %o0 and %o1 Useful for calling.mul and.div  Compute operation, and place result in %g1  Store the resulting assembly code string into the ExprSTO, without outputting to the file  When that ExprSTO is used in another Expression, dump the stored code and make some small register moves.

14 Method 3 – Example (a + b) + (x + y) lda, %o0ldx, %o0 ldb, %o1ldy, %o1 add%o0, %o1, %g1add%o0, %o1, %g1 {place code (a+b) here} mov%g1, %l0 {place code (x+y) here} mov%l0, %o0 mov%g1, %o1 add%o0, %o1, %g1

15 Methods are your Friend!  Consider adding methods to your STO’s that make generating assembly for certain cases easier: GetAddress() – returns base/offset (ie, %fp – 4) GetValue() – will combine GetAddress with an appropriate load instruction Etc.

16 Conditions – Branching  Given this: IF x THEN (* … *) END; ldx, %l0 cmp%l0, %g0! Compare with zero be.IfL1! Opposite logic nop (* … *).IfL1:

17 Branching – Where to?  You will need to generate labels for your branch statements. These labels must be unique  A simple solution would be to use some prefix string (i.e., “.IfL”), and append some counter at the end:.IfL1,.IfL2,.IfL3, …

18 Branching – Label Stack  Consider you had: IF X THEN IF Y THEN (*…*) END; END;  You will eventually need some sort of label stack to alleviate issues that arise from nested conditions.

19 Branching – Label Stack IF X THEN – load X, compare, branch to L1, push L1 onto stack IF Y THEN – load Y, compare, branch to L2, push L2 onto stack (*…*) END;- Pop L2 from stack and output label END;- Pop L1 from stack and output label

20 Procedures  How to call a procedure? Ex:call foo nop  How to return from a procedure? Ex:ret restore  How to return a value from a procedure? Ex:mov%l0, %i0 ret restore

21 Procedures – Example PROCEDURE foo () : INTEGER; VAR x: INTEGER; BEGIN x := 2; RETURN x; END foo;

22 Procedures – Example The following can be generated just by parsing “PROCEDURE foo”:.section“.text”.align4.global.foo.foo: set.foo.SIZE, %g1 save%sp, %g1, %sp

23 Procedures – Example Now, the body of the function: set2, %l0! Put “2” in a reg. st%l0, [%fp-8]! Store in tmp mem ld[%fp-8], %l0! Load from tmp st%l0, [%fp-4]! Store expr into “x” ld[%fp-4], %i0! Put “x” in return ret! Return statement restore

24 Procedures – Example Lastly, now that we got to “END foo;”:.foo.SIZE = -(92 + 8) & -8 ! Bytes of local and tmp vars  By leaving this to the end, you can also allocate extra stack space for intermediate expression storage if needed during the body of the function.

25 Large Example VAR y : INTEGER; PROCEDURE foo() : INTEGER; VAR x : INTEGER; BEGIN x := y;(* note how this uses a global that is set at runtime *) RETURN (x + 1); END foo; VAR z : BOOLEAN; BEGIN y := 4; IF y < foo() THEN WRITE “yes\n”; z := TRUE; END; WRITE z, NL; END.

26 Large Example.section“.rodata”.align4.I.s:.asciz“%d” ! General stuff we should always have handy.NL.s:.asciz“\n”! Good idea to output this when you open the file.T.s:.asciz“TRUE”.F.s:.asciz“FALSE”.section“.text”.align4.global.foo.foo: set.SAVE.foo, %g1 save%sp, %g1, %sp ! x := y; ld[%g6-4], %l0! Load global y st%l0, [%fp-8]! Store in temporary mem ld[%fp-8], %l0! Get expression to assign statement st%l0, [%fp-4]! Store result into local x ! RETURN (x+1); ld[%fp-4], %l0 set1, %l1! Use set for a const (ConstSTO or literal) add%l0, %l1, %l2! Do addition st%l2, [%fp-12]! Store in temporary mem ld[%fp-12], %l0! Get expression result from temp mem mov%l0, %i0! Put result in %i0, which is return value for procedure ret! Do return restore! Restore register window.SAVE.foo = -(92 + 12) & -8! We had 1 local var and 2 temporary locations  12 bytes

27 Large Example.section“.bss” ! Right before “main”, we go into BSS and set all the “globals”..align4.skip4! Global z  [%g6-8].skip4! Global y  [%g6-4].globals:! Note how they are in reverse order. The easiest way to do this is to have a vector of VarSTOs ! that you add to every time you do a global VarDecl. Then, walk through it backwards right before “main”.section“.text”.align4.globalmain main: set.SAVEmain, %g1 save%sp, %g1, %sp set.globals, %g6! One-time initialization of %g6 the be the base address of the globals ! y := 4; set4, %l0! Use set for integer literal st%l0, [%fp-4]! Store in temporary mem ld[%fp-4], %l0! Get expression to assign statement st%l0, [%g6-4]! Store result into global y ! IF y < foo() ld[%g6-4], %l0! Load global y call.foo nop mov%o0, %l1! Get result of foo into %l1 mov%g0, %l2! Initialize boolean result to FALSE cmp%l0, %l1! Compare the two bge.L1! Opposite logic! nop

28 Large Example set 1, %l2! Change boolean result to TRUE if branch failed.L1:! Branch will jump to here, skipping setting to TRUE st%l2, [%fp-8]! Store y < foo() boolean result into temporary mem ld[%fp-8], %l0! Get y < foo() result from temp mem cmp%l0, %g0! Compare with FALSE be.L2! Skip over code if FALSE nop ! WRITE “yes\n”;.section“.rodata”! Switch to read-only data segment (data segment also OK).L3:.asciz“yes\n”! No align necessary for.asciz (since byte-array, no alignment restrictions).section“.text”! Switch back to text segment.align4 set.L3, %o0! Used a unique global label to point to string literal callprintf nop ! z := TRUE; set1, %l0! Set TRUE constant literal into register st%l0, [%fp-12]! Store into temp mem ld[%fp-12], %l0! Get from result expression from temp mem st%l0, [%g6-8]! Store into global z.L2:! Skip-over label from IF stmt

29 Large Example ! WRITE z, NL; ld[%g6-8], %l0! Load global z st%l0, [%fp-16]! Store into temp mem ld[%fp-16], %l0! Load expression result from temp mem set.F.s, %o0! Default to print “FALSE” cmp%l0, %g0! Since z is boolean, determine if we print TRUE or FALSE be.L4! Skip over if FALSE nop set.T.s, %o0! Change to “TRUE” if z is TRUE.L4:! Branch over here callprintf! Will print TRUE or FALSE depending on what %o0 was nop set.NL.s, %o0! Set NL literal for output callprintf! Output newline nop ret! Implicit return at end of every procedure (including main) restore.SAVEmain = -(92 + 16) & -8! No local vars and 4 temp locations (16 bytes) When you run this, you should get: yes TRUE -bash-3.00$

30 What to do Next! 1.Continue planning out how you want to structure your project – good planning leads to an easier design in the long run. 2.Finish Phase 1. 3.Start of Phase 2. 4.Come to lab hours and ask questions.

31 Topics/Questions you may have  Anything else you would like me to go over now?  Anything in particular you would like to see next week?


Download ppt "CSE 131B – Compiler Construction II Discussion 6: Operations, Branches and Functions 2/21/2007."

Similar presentations


Ads by Google