The input code: package main is body ma: integer; procedure a is -- proc level 1 begin aa,ab: integer; procedure b is -- proc level 2 begin ba: integer; procedure c is -- proc level 3 begin ca,cb: integer; begin ca := ba + 1; ma := ma + 1; writeln(" ca = ",ca," ma = ",ma); if ca <= -3 then writeln(" c calls a"); a; writeln(" ca = ",ca," ma = ",ma); end if; writeln(" return from c"); end; -- proc level 3 end begin ba := aa + 2; writeln(" ba = ",ba," and then b calls c"); c; writeln(" return from b: ba = ",ba); end; -- proc level 2 end begin aa := ma - 4; writeln(" aa = ",aa," and then a calls b"); b; writeln(" return from a: aa = ",aa); end; -- proc level 1 end begin ma := -2; writeln("ma = ",ma,"and then main calls a"); a; writeln("done in main: ma = ",ma); end; -------------------------------------- Running SIMPLE with command line -i (AST) -s (SymbolTable dump) -v (var addrs) in simple.c Symbol table dump: checking scope (0): SymRoot level 0 variables: Type name Undeclared Type name a Type name integer ma is used = 1 init = 1 type = integer Type name main checking scope (1): SymRoot level 1 variables: aa is used = 1 init = 1 type = integer ab is used = 0 init = 0 type = integer Type name b checking scope (2): SymRoot level 2 variables: ba is used = 1 init = 1 type = integer Type name c checking scope (3): SymRoot level 3 variables: ca is used = 1 init = 1 type = integer cb is used = 0 init = 0 type = integer dumping from simple.c Symbol table dump: checking scope (0): SymRoot level 0 variables: Type name Undeclared Type name a Type name integer ma is used = 1 init = 1 type = integer Type name main checking scope (1): SymRoot level 1 variables: aa is used = 1 init = 1 type = integer ab is used = 0 init = 0 type = integer Type name b checking scope (2): SymRoot level 2 variables: ba is used = 1 init = 1 type = integer Type name c checking scope (3): SymRoot level 3 variables: ca is used = 1 init = 1 type = integer cb is used = 0 init = 0 type = integer Intermediate Representation - the Abstract Syntax Tree Procdures Procdure (a) Procdure (b) Procdure (c) Body (c) Assign ca gets ba add Immediate Value 1 Assign ma gets ma add Immediate Value 1 Writeln parameters ca = ca ma = ma If Bool Expr ca LessThenEqual Immediate Value -3 Then Writeln parameters c calls a Call Proc (a) Writeln parameters ca = ca ma = ma End If Writeln parameters return from c END Body (c) Body (b) Assign ba gets aa add Immediate Value 2 Writeln parameters ba = ba and then b calls c Call Proc (c) Writeln parameters return from b: ba = ba END Body (b) Body (a) Assign aa gets ma subtract Immediate Value 4 Writeln parameters aa = aa and then a calls b Call Proc (b) Writeln parameters return from a: aa = aa END Body (a) Main Statements Assign ma gets Immediate Value -2 Writeln parameters ma = ma and then main calls a Call Proc (a) Writeln parameters done in main: ma = ma From codegen.c - DisplayRegs() marks used registers Register: 0 1 2 3 4 5 6 7 8 9 - - - - - - - - - - Used = x: Variable dump from GenStorage ID: ma Offset: 0 Proc. Level: 0 COMPILATION COMPLETE out simple.c ------------------------------------- The listing file produced by simple package main is body -- example from Fischer and LeBlanc, p. 295 ma: integer; procedure a is -- proc level 1 begin aa,ab: integer; procedure b is -- proc level 2 begin ba: integer; procedure c is -- proc level 3 begin ca,cb: integer; begin ca := ba + 1; ma := ma + 1; writeln( ca = ,ca, ma = ,ma); if ca <= -3 then writeln( c calls a); a; writeln( ca = ,ca, ma = ,ma); end if; writeln( return from c); end; -- proc level 3 end begin ba := aa + 2; writeln( ba = ,ba, and then b calls c); c; writeln( return from b: ba = ,ba); end; -- proc level 2 end begin aa := ma - 4; writeln( aa = ,aa, and then a calls b); b; writeln( return from a: aa = ,aa); end; -- proc level 1 end begin ma := -2; writeln(ma = ,ma,and then main calls a); a; writeln(done in main: ma = ,ma); end; ------------------------------------- The assembler file produced by simple # Register Usage: # $s0 for global variables # $s1 for procedure depth 1 # $s2 for procedure depth 2 # $s3 for procedure depth 3 # .text .globl main main: la $s0, GVARS # # Start Code # # Generate Assignment Statement li $t0,-2 sw $t0,0($s0) # # Generate Writeln statement la $a0, S3 li $v0, 4 syscall li $v0, 1 lw $a0,0($s0) syscall la $a0, S2 li $v0, 4 syscall la $a0, S0 li $v0, 4 syscall # Procedure "a" Call jal ProLable0 # # Generate Writeln statement la $a0, S1 li $v0, 4 syscall li $v0, 1 lw $a0,0($s0) syscall la $a0, S0 li $v0, 4 syscall # # Halt execution li $v0 10 syscall # PROCEDURE HEADER ProLable2: # Start of level 3 procedure c sw $ra, ($sp) #store return address sw $s3, -4($sp) #store old level 3 display move $s3, $sp #set new level 3 display to top of stack addi $sp, -16 #move by AR size # BODY OF THE PROCEDURE # # Generate Assignment Statement lw $t0,-8($s2) add $t0,$t0,1 sw $t0,-8($s3) # # Generate Assignment Statement lw $t0,0($s0) add $t0,$t0,1 sw $t0,0($s0) # # Generate Writeln statement la $a0, S15 li $v0, 4 syscall li $v0, 1 lw $a0,-8($s3) syscall la $a0, S14 li $v0, 4 syscall li $v0, 1 lw $a0,0($s0) syscall la $a0, S0 li $v0, 4 syscall # # Generate If Statment lw $t0,-8($s3) sle $t0,$t0,-3 beq $t0, 0,IF1 # # Generate Writeln statement la $a0, S13 li $v0, 4 syscall la $a0, S0 li $v0, 4 syscall # Procedure "a" Call jal ProLable0 # # Generate Writeln statement la $a0, S12 li $v0, 4 syscall li $v0, 1 lw $a0,-8($s3) syscall la $a0, S11 li $v0, 4 syscall li $v0, 1 lw $a0,0($s0) syscall la $a0, S0 li $v0, 4 syscall j IF0 IF1: IF0: # # Generate Writeln statement la $a0, S10 li $v0, 4 syscall la $a0, S0 li $v0, 4 syscall # END OF Procdure addi $sp, 16 #move by AR size lw $s3, -4($sp) #restore old level display lw $ra, ($sp) #retore return address jr $ra #return # END OF Procdure (c) # PROCEDURE HEADER ProLable1: # Start of level 2 procedure b sw $ra, ($sp) #store return address sw $s2, -4($sp) #store old level 3 display move $s2, $sp #set new level 3 display to top of stack addi $sp, -12 #move by AR size # BODY OF THE PROCEDURE # # Generate Assignment Statement lw $t0,-8($s1) add $t0,$t0,2 sw $t0,-8($s2) # # Generate Writeln statement la $a0, S9 li $v0, 4 syscall li $v0, 1 lw $a0,-8($s2) syscall la $a0, S8 li $v0, 4 syscall la $a0, S0 li $v0, 4 syscall # Procedure "c" Call jal ProLable2 # # Generate Writeln statement la $a0, S7 li $v0, 4 syscall li $v0, 1 lw $a0,-8($s2) syscall la $a0, S0 li $v0, 4 syscall # END OF Procdure addi $sp, 12 #move by AR size lw $s2, -4($sp) #restore old level display lw $ra, ($sp) #retore return address jr $ra #return # END OF Procdure (b) # PROCEDURE HEADER ProLable0: # Start of level 1 procedure a sw $ra, ($sp) #store return address sw $s1, -4($sp) #store old level 3 display move $s1, $sp #set new level 3 display to top of stack addi $sp, -16 #move by AR size # BODY OF THE PROCEDURE # # Generate Assignment Statement lw $t0,0($s0) li $t1,4 sub $t0,$t0,$t1 sw $t0,-8($s1) # # Generate Writeln statement la $a0, S6 li $v0, 4 syscall li $v0, 1 lw $a0,-8($s1) syscall la $a0, S5 li $v0, 4 syscall la $a0, S0 li $v0, 4 syscall # Procedure "b" Call jal ProLable1 # # Generate Writeln statement la $a0, S4 li $v0, 4 syscall li $v0, 1 lw $a0,-8($s1) syscall la $a0, S0 li $v0, 4 syscall # END OF Procdure addi $sp, 16 #move by AR size lw $s1, -4($sp) #restore old level display lw $ra, ($sp) #retore return address jr $ra #return # END OF Procdure (a) # # Finish up by writing out constants .word 0 .data CONST: #Constant storage area S0: .asciiz "\n" S1: .asciiz "done in main: ma = " S2: .asciiz "and then main calls a" S3: .asciiz "ma = " S4: .asciiz " return from a: aa = " S5: .asciiz " and then a calls b" S6: .asciiz " aa = " S7: .asciiz " return from b: ba = " S8: .asciiz " and then b calls c" S9: .asciiz " ba = " S10: .asciiz " return from c" S11: .asciiz " ma = " S12: .asciiz " ca = " S13: .asciiz " c calls a" S14: .asciiz " ma = " S15: .asciiz " ca = " # # Reserve space for global variables .word 0 GVARS: # space for Global Variables .data _ma: .word 0 # Offset at 0 Temp_Wr: .word 0 #just for alignment of write(exprtree) ------------------------------------- execute the code in spim: SPIM Version 6.2 of January 11, 1999 Copyright 1990-1998 by James R. Larus (larus@cs.wisc.edu). All Rights Reserved. See the file README for a full copyright notice. Loaded: /opt/spim/bin/trap.handler ma = -2and then main calls a aa = -6 and then a calls b ba = -4 and then b calls c ca = -3 ma = -1 c calls a aa = -5 and then a calls b ba = -3 and then b calls c ca = -2 ma = 0 return from c return from b: ba = -3 return from a: aa = -5 ca = -3 ma = 0 return from c return from b: ba = -4 return from a: aa = -6 done in main: ma = 0