Download presentation
Presentation is loading. Please wait.
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?
Similar presentations
© 2024 SlidePlayer.com Inc.
All rights reserved.