1 | = INTRODUCTION =
|
---|
2 |
|
---|
3 | Welcome reader,
|
---|
4 |
|
---|
5 | You will find our solution on assignment 4 of Compiler Constructions 2008
|
---|
6 | given at LIACS University. First we will give you a grand overview of the files
|
---|
7 | altered, next we will bullet point the most important design decisions. After that
|
---|
8 | an example is shown.
|
---|
9 |
|
---|
10 | And the grand finale will show the usage of the program.
|
---|
11 |
|
---|
12 | Enjoy!
|
---|
13 | Johan and Rick <hvdzwet@liacs.nl>
|
---|
14 |
|
---|
15 | = FILES EDITED/ADDED =
|
---|
16 | A globals.h = Some global definitions
|
---|
17 | A MOperand.cc = Represents a operand for a MIPS statement
|
---|
18 | A MOperator.cc = Represents a MIPS operator/opcode
|
---|
19 | A MStatement.cc = Represents MIPS statements
|
---|
20 | E StackFrameManager.cc = Manages the stack frame
|
---|
21 | A RegisterManager.cc
|
---|
22 | E CodeGenerator.cc
|
---|
23 | E main.cc = Main program function, argument parsing
|
---|
24 |
|
---|
25 | = DESIGN DECISIONS =
|
---|
26 | * Added a register manager to keep track of what symbols are associated with what
|
---|
27 | registers. The register manager also loads the register if it's new and writes
|
---|
28 | it back to memory.
|
---|
29 |
|
---|
30 | * The current implementation for spilling a register is to select a random one. Also
|
---|
31 | all registers are written back before a function call, before the end of a
|
---|
32 | function and before jumps and branches. This can be optimized in the next assignment.
|
---|
33 |
|
---|
34 | * We prefix all the symbol names with "__" to prevent name clashes with MIPS
|
---|
35 | assembly instructions.
|
---|
36 |
|
---|
37 | * Register $V0 is used for integer function return values and $f0 for real
|
---|
38 | return values.
|
---|
39 |
|
---|
40 | * Register $V1 is used for expressions
|
---|
41 |
|
---|
42 | * Registers $A0, $A1, $A2 and $A3 do not have to be gotten through the RegisterManager
|
---|
43 | and can thus be used as temporaries inside a known code block while generating code.
|
---|
44 |
|
---|
45 | * The stack pointer $sp points to the last used word on the stack. We generate code
|
---|
46 | that assumes it's pointing to the first free word. Therefore the stack is increased
|
---|
47 | by one word in main before calling the program body.
|
---|
48 |
|
---|
49 | * The stack frame layout is as follows:
|
---|
50 | ^ ^
|
---|
51 | | |
|
---|
52 | $fp + 8 second parameter
|
---|
53 | $fp + 4 first parameter
|
---|
54 | $fp + 0 return address
|
---|
55 | $fp - 4 previous frame pointer
|
---|
56 | $fp - 8 return value
|
---|
57 | $fp - 12 first local variable
|
---|
58 | $fp - 16 second local variable
|
---|
59 | | |
|
---|
60 | v v
|
---|
61 |
|
---|
62 | * We created a framework for Assembly code, model-ed after the intermediate code
|
---|
63 | framework. This was done to separate the generation of the output file from
|
---|
64 | generation of the code. It can also later be used to implement further
|
---|
65 | optimizations on the MIPS assembly code.
|
---|
66 |
|
---|
67 | = SAMPLE GENERATED CODE =
|
---|
68 | C01) program example;
|
---|
69 | C02)
|
---|
70 | C03) var x, y, z: integer;
|
---|
71 | C04) function foo(a,b: integer): integer;
|
---|
72 | C05) begin
|
---|
73 | C06) foo := 1
|
---|
74 | C07) end;
|
---|
75 | C08)
|
---|
76 | C09) begin
|
---|
77 | C10) x := readinteger;
|
---|
78 | C11) y := 20;
|
---|
79 | C12) z := x + 20;
|
---|
80 | C13) z := z + foo(0,0)
|
---|
81 | C14) end.
|
---|
82 |
|
---|
83 | 1 ## Output generated by ./comp @ kubuntu-desktop
|
---|
84 | 2 ## Thu Nov 20 14:30:48 2008
|
---|
85 | 3
|
---|
86 | 4 ## Compiler Construction Course - Leiden University - LIACS
|
---|
87 | 5 ## Johan IJsveld - Rick van der Zwet
|
---|
88 | 6 ## BSD Licenced
|
---|
89 | 7
|
---|
90 | 8 .data # Global data section
|
---|
91 | 9 .align 4
|
---|
92 | 10 __x:
|
---|
93 | 11 .word 0
|
---|
94 | 12 __y:
|
---|
95 | 13 .word 0
|
---|
96 | 14 __z:
|
---|
97 | 15 .word 0
|
---|
98 | 16
|
---|
99 | 17 .text # Code section
|
---|
100 | 18 .align 4
|
---|
101 | 19 .globl main
|
---|
102 | 20
|
---|
103 | 21 .ent main
|
---|
104 | 22 main:
|
---|
105 | 23 addi $sp, $sp, -4
|
---|
106 | 24 jal __example # Jump to program body
|
---|
107 | 25 addi $sp, $sp, 4
|
---|
108 | 26 addi $v0, $0, 10 # Exit system call
|
---|
109 | 27 syscall
|
---|
110 | 28 .end main
|
---|
111 | 29
|
---|
112 | 30 .ent __example
|
---|
113 | 31 __example:
|
---|
114 | 32 sw $ra, 0($sp) # Set up stack frame
|
---|
115 | 33 sw $fp, -4($sp)
|
---|
116 | 34 move $fp, $sp
|
---|
117 | 35 addi $sp, $sp, -28
|
---|
118 | 36 jal __readinteger
|
---|
119 | 37 lw $t0, -12($fp) # Load integer Register
|
---|
120 | 38 move $t0, $v0 # Store integer function result
|
---|
121 | 39 lw $t1, __x # Load integer Register
|
---|
122 | 40 move $t1, $t0 # Assign integer
|
---|
123 | 41 lw $t2, __y # Load integer Register
|
---|
124 | 42 addi $t2, $0, 20 # Assign constant integer
|
---|
125 | 43 lw $t3, -16($fp) # Load integer Register
|
---|
126 | 44 addi $a0, $0, 20
|
---|
127 | 45 add $t3, $t1, $a0 # Add integers
|
---|
128 | 46 lw $t4, __z # Load integer Register
|
---|
129 | 47 move $t4, $t3 # Assign integer
|
---|
130 | 48 addi $v1, $0, 0 # Push constant integer parameter
|
---|
131 | 49 sw $v1, 0($sp)
|
---|
132 | 50 addi $sp, $sp, -4
|
---|
133 | 51 addi $v1, $0, 0 # Push constant integer parameter
|
---|
134 | 52 sw $v1, 0($sp)
|
---|
135 | 53 addi $sp, $sp, -4
|
---|
136 | 54 sw $t0, -12($fp) # Write back integer register
|
---|
137 | 55 sw $t1, __x # Write back integer register
|
---|
138 | 56 sw $t2, __y # Write back integer register
|
---|
139 | 57 sw $t3, -16($fp) # Write back integer register
|
---|
140 | 58 sw $t4, __z # Write back integer register
|
---|
141 | 59 jal __foo
|
---|
142 | 60 lw $t0, -20($fp) # Load integer Register
|
---|
143 | 61 move $t0, $v0 # Store integer function result
|
---|
144 | 62 lw $t1, -24($fp) # Load integer Register
|
---|
145 | 63 lw $t2, __z # Load integer Register
|
---|
146 | 64 add $t1, $t2, $t0 # Add integers
|
---|
147 | 65 move $t2, $t1 # Assign integer
|
---|
148 | 66 sw $t0, -20($fp) # Write back integer register
|
---|
149 | 67 sw $t1, -24($fp) # Write back integer register
|
---|
150 | 68 sw $t2, __z # Write back integer register
|
---|
151 | 69 lw $ra, 0($fp) # Return from call
|
---|
152 | 70 lw $fp, -4($fp)
|
---|
153 | 71 addi $sp, $sp, 28
|
---|
154 | 72 jr $ra
|
---|
155 | 73 .end __example
|
---|
156 | 74
|
---|
157 | 75 .ent __foo
|
---|
158 | 76 __foo:
|
---|
159 | 77 sw $ra, 0($sp) # Set up stack frame
|
---|
160 | 78 sw $fp, -4($sp)
|
---|
161 | 79 move $fp, $sp
|
---|
162 | 80 addi $sp, $sp, -12
|
---|
163 | 81 lw $t0, -8($fp) # Load integer Register
|
---|
164 | 82 addi $t0, $0, 1 # Assign constant integer
|
---|
165 | 83 sw $t0, -8($fp) # Write back integer register
|
---|
166 | 84 lw $t0, -8($fp) # Load integer Register
|
---|
167 | 85 move $v0, $t0 # Store integer return value
|
---|
168 | 86 lw $ra, 0($fp) # Return from call
|
---|
169 | 87 lw $fp, -4($fp)
|
---|
170 | 88 addi $sp, $sp, 20
|
---|
171 | 89 jr $ra
|
---|
172 | 90 .end __foo
|
---|
173 | 91
|
---|
174 | 92 .ent __readinteger # Start of builtin functions and procedures
|
---|
175 | 93 __readinteger:
|
---|
176 | 94 addi $v0, $0, 5
|
---|
177 | 95 syscall
|
---|
178 | 96 jr $ra
|
---|
179 | 97 .end __readinteger
|
---|
180 | 98
|
---|
181 | 99 .ent __writeinteger
|
---|
182 | 100 __writeinteger:
|
---|
183 | 101 lw $a0, 4($sp)
|
---|
184 | 102 addi $v0, $0, 1
|
---|
185 | 103 syscall
|
---|
186 | 104 addi $sp, $sp, 4
|
---|
187 | 105 jr $ra
|
---|
188 | 106 .end __writeinteger
|
---|
189 | 107
|
---|
190 | 108 .ent __readreal
|
---|
191 | 109 __readreal:
|
---|
192 | 110 addi $v0, $0, 6
|
---|
193 | 111 syscall
|
---|
194 | 112 jr $ra
|
---|
195 | 113 .end __readreal
|
---|
196 | 114
|
---|
197 | 115 .ent __writereal
|
---|
198 | 116 __writereal:
|
---|
199 | 117 l.s $f12, 4($sp)
|
---|
200 | 118 addi $v0, $0, 2
|
---|
201 | 119 syscall
|
---|
202 | 120 addi $sp, $sp, 4
|
---|
203 | 121 jr $ra
|
---|
204 | 122 .end __writereal
|
---|
205 | 123
|
---|
206 |
|
---|
207 | Lines 8 through 16 shows the space for globals being reserved.
|
---|
208 | Lines 21 through 28 is the main function calling the program body and doing a syscall to exit.
|
---|
209 | Lines 30 through 73 is the program body code.
|
---|
210 | Lines 75 through 90 is the function foo, where on lines 77 through 80 the stack
|
---|
211 | frame is set up. In lines 81 through 85 the return value 1 is stored on the stack
|
---|
212 | and then put in the return register $v0.
|
---|
213 | On line 86 and line 87, $ra and the old $fp are restored. The stack is shrunk back again,
|
---|
214 | including parameters, on line 88 and on line 89 is the jump back from where the call was made.
|
---|
215 | After line 92 are the builtin functions.
|
---|
216 |
|
---|
217 | = USAGE =
|
---|
218 | # Compile
|
---|
219 | $ make first
|
---|
220 | $ make
|
---|
221 | # Call without optimalisation
|
---|
222 | $ ./comp -w -00 <testfile
|
---|
223 | # Call with optimalisation
|
---|
224 | $ ./comp -w -01 <testfile
|
---|
225 | The resultant MIPS assembly is stored in the file "out.s".
|
---|