1 | /*
|
---|
2 | * ICGenerator.cc - Implementation of the ICGenerator class
|
---|
3 | *
|
---|
4 | * Part of the assignment of the Compiler Construction course
|
---|
5 | * LIACS, Leiden University
|
---|
6 | *
|
---|
7 | * This file will contain most of your work for assignment 3.
|
---|
8 | */
|
---|
9 |
|
---|
10 | #include "ICGenerator.h"
|
---|
11 |
|
---|
12 | #include <sstream>
|
---|
13 | #include <cassert>
|
---|
14 | #include <list>
|
---|
15 | #include <iostream>
|
---|
16 |
|
---|
17 | extern bool bOptimize1;
|
---|
18 | extern IntermediateCode *icode;
|
---|
19 | extern SymbolTable *symtab;
|
---|
20 |
|
---|
21 | /* Macro to allow pretty display of parser tree calling stack debug print calls */
|
---|
22 | #define picg(x) pmesg(100, "Parser: '"); pmesg(100, x); pmesg(100, "'\n")
|
---|
23 |
|
---|
24 | // Constructor
|
---|
25 | ICGenerator::ICGenerator() {
|
---|
26 | }
|
---|
27 |
|
---|
28 |
|
---|
29 | // Destructor
|
---|
30 | ICGenerator::~ICGenerator() {
|
---|
31 | }
|
---|
32 |
|
---|
33 |
|
---|
34 | // Preprocesses the syntax tree; this method is called before
|
---|
35 | // GenerateIntermediateCode() if optimizations are enabled
|
---|
36 | void ICGenerator::Preprocess (SyntaxTree * tree, SymbolTable * symtab) {
|
---|
37 | }
|
---|
38 |
|
---|
39 |
|
---|
40 | // Takes a SyntaxTree and converts it into an IntermediateCode structure
|
---|
41 | IntermediateCode * ICGenerator::GenerateIntermediateCode (SyntaxTree * inputTree, SymbolTable * symtab) {
|
---|
42 | IStatement * istmt;
|
---|
43 |
|
---|
44 | icode = new IntermediateCode;
|
---|
45 |
|
---|
46 | /* Process program body */
|
---|
47 | /* Make sure temponary generated variables are added to the right scope */
|
---|
48 | symtab->SetCurrentScope(inputTree->GetProgramName());
|
---|
49 | icode->SetProgramName(inputTree->GetProgramName());
|
---|
50 | delete Treewalk(inputTree->GetProgramBody());
|
---|
51 |
|
---|
52 | /* Indicate end of program body */
|
---|
53 | istmt = new IStatement (IOP_RETURN);
|
---|
54 | icode->AppendStatement(istmt);
|
---|
55 |
|
---|
56 | /* Now walk through the list of subprograms, and process them one by one */
|
---|
57 | for (int i = 0; i < inputTree->GetSubprogramCount(); i++) {
|
---|
58 | // add subprogram code
|
---|
59 | Symbol *subprogram = symtab->GetSymbol(inputTree->GetSubprogramName(i));
|
---|
60 | /* Make sure temponary generated variables are added to the right scope */
|
---|
61 | symtab->SetCurrentScope(inputTree->GetSubprogramName(i));
|
---|
62 | icode->AppendStatement(new IStatement(IOP_SUBPROG, new IOperand_Symbol(subprogram), NULL, NULL));
|
---|
63 |
|
---|
64 | // add subprogram body code
|
---|
65 | delete Treewalk(inputTree->GetSubprogram(i));
|
---|
66 |
|
---|
67 | // add code for return value
|
---|
68 | IOperator op;
|
---|
69 | switch (subprogram->GetReturnType()) {
|
---|
70 | case RT_INT:
|
---|
71 | op = IOP_RETURN_I;
|
---|
72 | break;
|
---|
73 | case RT_REAL:
|
---|
74 | op = IOP_RETURN_R;
|
---|
75 | break;
|
---|
76 | case RT_VOID:
|
---|
77 | op = IOP_RETURN;
|
---|
78 | break;
|
---|
79 | default:
|
---|
80 | assert(0); // can't happen
|
---|
81 | }
|
---|
82 | icode->AppendStatement(new IStatement(op, (op == IOP_RETURN) ? NULL : new IOperand_Symbol(subprogram), NULL, NULL));
|
---|
83 | }
|
---|
84 |
|
---|
85 | return icode;
|
---|
86 | }
|
---|
87 |
|
---|
88 |
|
---|
89 | // Postprocesses the intermediate code; this method is called after
|
---|
90 | // GenerateIntermediateCode() if optimizations are enabled
|
---|
91 | void ICGenerator::Postprocess (IntermediateCode * code, SymbolTable * symtab) {
|
---|
92 | /* Some trivial optimalisations which could be implemented */
|
---|
93 |
|
---|
94 | /* 1) LABEL X
|
---|
95 | * 2) GOTO :Y
|
---|
96 | * Alter GOTO :X to GOTO :Y directly
|
---|
97 | */
|
---|
98 |
|
---|
99 | /* 1) LABEL X
|
---|
100 | * 2) RETURN tX
|
---|
101 | * Alter GOTO :X to RETURN tX directly
|
---|
102 | */
|
---|
103 |
|
---|
104 | /* 1) ASSIGN foo tX
|
---|
105 | * ... no use of tX, in the meantime ...
|
---|
106 | * X) ASSIGN bar tX
|
---|
107 | * Delete line 1)
|
---|
108 | */
|
---|
109 |
|
---|
110 | /* Less trivials optimalisations which could be implemented*/
|
---|
111 |
|
---|
112 | /* Unfold small for loops */
|
---|
113 |
|
---|
114 | /* Delete/mangle branching code if TEST expression to always to be evaluated TRUE of FALSE */
|
---|
115 |
|
---|
116 | /* Detect and remove useless IOP_ASSIGN_[IR] statements */
|
---|
117 |
|
---|
118 | /* When parameters of function are not used, do not assign */
|
---|
119 |
|
---|
120 | /* 1) ASSIGN int(1) tX
|
---|
121 | * 2) ASSIGN int(2) tY
|
---|
122 | * 3) ADD_I tX tY tZ
|
---|
123 | * Convert line 3) to ASSIGN int(3) tZ
|
---|
124 | */
|
---|
125 |
|
---|
126 | /* 1) LABEL L_1
|
---|
127 | * 2) LABEL L_2
|
---|
128 | * Convert all GOTO L_2 to GOTO L_1 and delete L_2
|
---|
129 | */
|
---|
130 | }
|
---|
131 |
|
---|
132 |
|
---|
133 | // Generate a temporary symbol
|
---|
134 | Symbol * ICGenerator::GenerateTempVar(ReturnType type) {
|
---|
135 | /* Keep track of variables given out, make all generated unique for the sake
|
---|
136 | * of debugging
|
---|
137 | */
|
---|
138 | static int count = 0;
|
---|
139 | count++;
|
---|
140 |
|
---|
141 | Symbol *symbol = new Symbol();
|
---|
142 | symbol->SetSymbolType(ST_TEMPVAR);
|
---|
143 | symbol->SetReturnType(type);
|
---|
144 | std::stringstream ss;
|
---|
145 | ss << "t" << count;
|
---|
146 | symbol->SetName(ss.str());
|
---|
147 |
|
---|
148 | /* Make sure to add it to the symbol table */
|
---|
149 | symtab->AddSymbol(symbol);
|
---|
150 | return symbol;
|
---|
151 | }
|
---|
152 |
|
---|
153 |
|
---|
154 | // Generates a Symbol for a label
|
---|
155 | Symbol * ICGenerator::GenerateLabel() {
|
---|
156 | /* Keep track of variables given out, make all generated unique for the sake
|
---|
157 | * of debugging
|
---|
158 | */
|
---|
159 | static int count = 0;
|
---|
160 | count++;
|
---|
161 |
|
---|
162 | Symbol *symbol = new Symbol();
|
---|
163 | symbol->SetSymbolType(ST_LABEL);
|
---|
164 | std::stringstream ss;
|
---|
165 | ss << "L_" << count;
|
---|
166 | symbol->SetName(ss.str());
|
---|
167 |
|
---|
168 | /* Make sure to add it to the symbol table */
|
---|
169 | symtab->AddSymbol(symbol);
|
---|
170 | return symbol;
|
---|
171 | }
|
---|
172 |
|
---|
173 | IOperand *ICGenerator::Treewalk (Node * node, IOperand *dest, IOperand *constant)
|
---|
174 | {
|
---|
175 | switch (node->GetNodeType ())
|
---|
176 | {
|
---|
177 | case NODE_UNKNOWN: // Unknown (yet)
|
---|
178 | assert (0); // can't happen
|
---|
179 | break;
|
---|
180 | case NODE_ERROR: // Error
|
---|
181 | assert (0); // can't happen
|
---|
182 | break;
|
---|
183 |
|
---|
184 | /*
|
---|
185 | * Statement list
|
---|
186 | * left child One of, NODE_ASSIGNMENT, NODE_IF, NODE_WHILE,
|
---|
187 | * NODE_PROCCALL, NODE_FUNCTIONCALL, NODE_STATEMENT_LIST.
|
---|
188 | * right child One of, NODE_ASSIGNMENT, NODE_IF, NODE_WHILE,
|
---|
189 | * NODE_PROCCALL, NODE_FUNCTIONCALL, NODE_STATEMENT_LIST, or
|
---|
190 | * NODE_EMPTY if no more statements follow.
|
---|
191 | */
|
---|
192 | case NODE_STATEMENT_LIST:
|
---|
193 | {
|
---|
194 | delete Treewalk(node->GetLeftChild());
|
---|
195 | delete Treewalk(node->GetRightChild());
|
---|
196 | return NULL;
|
---|
197 | }
|
---|
198 | break;
|
---|
199 |
|
---|
200 | /*
|
---|
201 | * Assignment
|
---|
202 | * left child A NODE_ID that identifies the destination variable
|
---|
203 | * right child A subtree representing an expression
|
---|
204 | */
|
---|
205 | case NODE_ASSIGNMENT:
|
---|
206 | {
|
---|
207 | IOperand *result = Treewalk(node->GetLeftChild());
|
---|
208 | IOperand *operand = Treewalk(node->GetRightChild(), bOptimize1 ? result : NULL);
|
---|
209 | if (operand != result) {
|
---|
210 | IOperator op = ( (node->GetLeftChild()->GetReturnType() == RT_REAL) ? IOP_ASSIGN_R : IOP_ASSIGN_I );
|
---|
211 | icode->AppendStatement(new IStatement(op, operand, NULL, result));
|
---|
212 | }
|
---|
213 | return NULL;
|
---|
214 | }
|
---|
215 | break;
|
---|
216 |
|
---|
217 | /*
|
---|
218 | * If statement
|
---|
219 | * left child A NODE_BOOLEXPR that provides the if condition
|
---|
220 | * right child A NODE_IF_TARGETS subtree (if there is an else clause) or
|
---|
221 | * a subtree consisting of statements (if there's no else)
|
---|
222 | */
|
---|
223 | case NODE_IF:
|
---|
224 | {
|
---|
225 | // generate labels
|
---|
226 | Symbol *false_label = GenerateLabel();
|
---|
227 | Symbol *end_label = GenerateLabel();
|
---|
228 |
|
---|
229 | // add evaluation code
|
---|
230 | IOperand *evaluation = Treewalk(node->GetLeftChild());
|
---|
231 | icode->AppendStatement(new IStatement(IOP_BEQ_I, evaluation, new IOperand_Int(0), new IOperand_Symbol(false_label)));
|
---|
232 |
|
---|
233 | // add code for true case
|
---|
234 | Node *rightchild = node->GetRightChild();
|
---|
235 | if (rightchild->GetNodeType() == NODE_IF_TARGETS) {
|
---|
236 | delete Treewalk(rightchild->GetLeftChild());
|
---|
237 | // there is a else part so skip over it
|
---|
238 | icode->AppendStatement(new IStatement(IOP_GOTO, new IOperand_Symbol(end_label), NULL, NULL));
|
---|
239 | } else {
|
---|
240 | delete Treewalk(rightchild);
|
---|
241 | }
|
---|
242 |
|
---|
243 | // add label for false part
|
---|
244 | icode->AppendStatement(new IStatement(IOP_LABEL, new IOperand_Symbol(false_label), NULL, NULL));
|
---|
245 |
|
---|
246 | // add code for false/else case if any
|
---|
247 | if (rightchild->GetNodeType() == NODE_IF_TARGETS) {
|
---|
248 | delete Treewalk(rightchild->GetRightChild ());
|
---|
249 | // add end label
|
---|
250 | icode->AppendStatement(new IStatement(IOP_LABEL, new IOperand_Symbol(end_label), NULL, NULL));
|
---|
251 | }
|
---|
252 |
|
---|
253 | return NULL;
|
---|
254 | }
|
---|
255 | break;
|
---|
256 |
|
---|
257 | /*
|
---|
258 | * Targets of an if-else-statement
|
---|
259 | * left child The statements that have to be executed when the condition
|
---|
260 | * of the parent if-statement is true.
|
---|
261 | * right child The statements that have to be executed when the condition
|
---|
262 | * of the parent if-statement is false: that is: the else
|
---|
263 | * part.
|
---|
264 | */
|
---|
265 | case NODE_IF_TARGETS:
|
---|
266 | assert(0); // handled in NODE_IF
|
---|
267 | break;
|
---|
268 |
|
---|
269 | /*
|
---|
270 | * While loop
|
---|
271 | * left child A NODE_BOOLEXPR that provides the loop condition
|
---|
272 | * right child A subtree consisting of statements
|
---|
273 | */
|
---|
274 | case NODE_WHILE:
|
---|
275 | {
|
---|
276 | /* Method while tree
|
---|
277 | * :START
|
---|
278 | * if <expr> = 0 GOTO END
|
---|
279 | * <body>
|
---|
280 | * GOTO START
|
---|
281 | * :END
|
---|
282 | */
|
---|
283 | // generate labels
|
---|
284 | Symbol *start_label = GenerateLabel();
|
---|
285 | Symbol *end_label = GenerateLabel();
|
---|
286 |
|
---|
287 | // add start label
|
---|
288 | icode->AppendStatement(new IStatement(IOP_LABEL, new IOperand_Symbol(start_label), NULL, NULL));
|
---|
289 |
|
---|
290 | // add evaluation code
|
---|
291 | IOperand *evaluation = Treewalk(node->GetLeftChild());
|
---|
292 | icode->AppendStatement(new IStatement(IOP_BEQ_I, evaluation, new IOperand_Int(0), new IOperand_Symbol(end_label)));
|
---|
293 |
|
---|
294 | // add code
|
---|
295 | delete Treewalk(node->GetLeftChild());
|
---|
296 |
|
---|
297 | // add jump back to start
|
---|
298 | icode->AppendStatement(new IStatement(IOP_GOTO, new IOperand_Symbol(start_label), NULL, NULL));
|
---|
299 |
|
---|
300 | // add end label
|
---|
301 | icode->AppendStatement(new IStatement(IOP_LABEL, new IOperand_Symbol(end_label), NULL, NULL));
|
---|
302 |
|
---|
303 | return NULL;
|
---|
304 | }
|
---|
305 | break;
|
---|
306 |
|
---|
307 | /*
|
---|
308 | * Subprogram calls
|
---|
309 | * left child A NODE_ID that identifies the called function/procedure
|
---|
310 | * right child A NODE_EXPRLIST that specifies the actual arguments: or
|
---|
311 | * NODE_EMPTY if no arguments required.
|
---|
312 | */
|
---|
313 | case NODE_PROCCALL:
|
---|
314 | {
|
---|
315 | // pass parameters
|
---|
316 | delete Treewalk(node->GetRightChild());
|
---|
317 |
|
---|
318 | // add call statement
|
---|
319 | IOperand *id = Treewalk(node->GetLeftChild());
|
---|
320 | icode->AppendStatement(new IStatement(IOP_PROCCALL, id, NULL, NULL));
|
---|
321 |
|
---|
322 | return NULL;
|
---|
323 | }
|
---|
324 | break;
|
---|
325 | case NODE_FUNCTIONCALL:
|
---|
326 | {
|
---|
327 | // pass parameters
|
---|
328 | delete Treewalk(node->GetRightChild());
|
---|
329 |
|
---|
330 | // add call statement
|
---|
331 | IOperand *id = Treewalk(node->GetLeftChild());
|
---|
332 | IOperand *result = (dest != NULL) ? dest : new IOperand_Symbol(GenerateTempVar(node->GetReturnType()));
|
---|
333 | icode->AppendStatement(new IStatement(IOP_FUNCCALL, id, NULL, result));
|
---|
334 |
|
---|
335 | return (dest != NULL) ? dest : result->Clone();
|
---|
336 | }
|
---|
337 | break;
|
---|
338 |
|
---|
339 | /*
|
---|
340 | * Expression list
|
---|
341 | * left child A subtree representing an expression
|
---|
342 | * right child A subtree representing an expression: another
|
---|
343 | * NODE_EXPRLIST: or NODE_EMPTY if no more expressions follow
|
---|
344 | * in the expression list.
|
---|
345 | */
|
---|
346 | case NODE_EXPRLIST:
|
---|
347 | {
|
---|
348 | // pass parameter
|
---|
349 | IOperand *parameter = Treewalk(node->GetLeftChild());
|
---|
350 | ReturnType type = node->GetLeftChild()->GetReturnType();
|
---|
351 | IOperator op = ( (type == RT_REAL) ? IOP_PARAM_R : IOP_PARAM_I );
|
---|
352 | icode->AppendStatement(new IStatement(op, parameter, NULL, NULL));
|
---|
353 |
|
---|
354 | // pass any other parameters
|
---|
355 | delete Treewalk(node->GetRightChild());
|
---|
356 |
|
---|
357 | return NULL;
|
---|
358 | }
|
---|
359 | break;
|
---|
360 |
|
---|
361 | /*
|
---|
362 | * Boolean-like expression
|
---|
363 | * child A subtree with any NODE_REL_ node as parent
|
---|
364 | */
|
---|
365 | case NODE_BOOLEXPR:
|
---|
366 | {
|
---|
367 | return Treewalk(node->GetChild());
|
---|
368 | }
|
---|
369 | break;
|
---|
370 |
|
---|
371 | /*
|
---|
372 | * Relational operators
|
---|
373 | * left child Left-hand side of the comparison
|
---|
374 | * right child Right-hand side of the comparison
|
---|
375 | */
|
---|
376 | case NODE_REL_EQUAL: // = operator
|
---|
377 | {
|
---|
378 | ReturnType type = node->GetLeftChild()->GetReturnType();
|
---|
379 | IOperator op = ((type == RT_INT) ? IOP_BEQ_I : IOP_BEQ_R);
|
---|
380 | return GenerateRelopCode(op, node);
|
---|
381 | }
|
---|
382 | break;
|
---|
383 | case NODE_REL_LT: // < operator
|
---|
384 | {
|
---|
385 | ReturnType type = node->GetLeftChild()->GetReturnType();
|
---|
386 | IOperator op = ((type == RT_INT) ? IOP_BLT_I : IOP_BLT_R);
|
---|
387 | return GenerateRelopCode(op, node);
|
---|
388 | }
|
---|
389 | break;
|
---|
390 | case NODE_REL_GT: // > operator
|
---|
391 | {
|
---|
392 | ReturnType type = node->GetLeftChild()->GetReturnType();
|
---|
393 | IOperator op = ((type == RT_INT) ? IOP_BGT_I : IOP_BGT_R);
|
---|
394 | return GenerateRelopCode(op, node);
|
---|
395 | }
|
---|
396 | break;
|
---|
397 | case NODE_REL_LTE: // <= operator
|
---|
398 | {
|
---|
399 | ReturnType type = node->GetLeftChild()->GetReturnType();
|
---|
400 | IOperator op = ((type == RT_INT) ? IOP_BLE_I : IOP_BLE_R);
|
---|
401 | return GenerateRelopCode(op, node);
|
---|
402 | }
|
---|
403 | break;
|
---|
404 | case NODE_REL_GTE: // >= operator
|
---|
405 | {
|
---|
406 | ReturnType type = node->GetLeftChild()->GetReturnType();
|
---|
407 | IOperator op = ((type == RT_INT) ? IOP_BGE_I : IOP_BGE_R);
|
---|
408 | return GenerateRelopCode(op, node);
|
---|
409 | }
|
---|
410 | break;
|
---|
411 | case NODE_REL_NOTEQUAL: // <> operator
|
---|
412 | {
|
---|
413 | ReturnType type = node->GetLeftChild()->GetReturnType();
|
---|
414 | IOperator op = ((type == RT_INT) ? IOP_BNE_I : IOP_BNE_R);
|
---|
415 | return GenerateRelopCode(op, node);
|
---|
416 | }
|
---|
417 | break;
|
---|
418 |
|
---|
419 | /*
|
---|
420 | * Binary arithmetic & logic operations
|
---|
421 | * left child Left-hand side of the operation
|
---|
422 | * right child Right-hand side of the operation
|
---|
423 | */
|
---|
424 | case NODE_ADD: // Add
|
---|
425 | {
|
---|
426 | IOperand *lhs = NULL;
|
---|
427 | IOperand *rhs = NULL;
|
---|
428 |
|
---|
429 | // attempt optimizations
|
---|
430 | if (bOptimize1) {
|
---|
431 | /* reverse evaluation of operands, due to the fact the tree is always
|
---|
432 | * set to be on the left and we like to fold constants where ever
|
---|
433 | * possible
|
---|
434 | */
|
---|
435 | rhs = Treewalk(node->GetRightChild());
|
---|
436 | // check if we need to push any constant down the tree
|
---|
437 | if (node->GetLeftChild()->GetNodeType() == NODE_ADD ||
|
---|
438 | node->GetLeftChild()->GetNodeType() == NODE_SUB ) {
|
---|
439 | if (IsConstant(rhs)) {
|
---|
440 | // right hand side is also constant
|
---|
441 | if (constant != NULL) {
|
---|
442 | if (IsInt(rhs)) {
|
---|
443 | rhs->SetIntValue(rhs->GetIntValue() + constant->GetIntValue());
|
---|
444 | } else {
|
---|
445 | rhs->SetRealValue(rhs->GetRealValue() + constant->GetRealValue());
|
---|
446 | }
|
---|
447 | }
|
---|
448 | // evaluate left hand side passing constant value
|
---|
449 | lhs = Treewalk(node->GetLeftChild(), dest, rhs);
|
---|
450 | return lhs;
|
---|
451 | } else {
|
---|
452 | // generate add instruction for the right hand side
|
---|
453 | IOperator op = ( (node->GetReturnType() == RT_INT) ? IOP_ADD_I : IOP_ADD_R );
|
---|
454 | lhs = Treewalk(node->GetLeftChild(), NULL, constant);
|
---|
455 | IOperand *result = (dest != NULL) ? dest : new IOperand_Symbol(GenerateTempVar(node->GetReturnType()));
|
---|
456 | icode->AppendStatement(new IStatement(op, lhs, rhs, result));
|
---|
457 | return (dest != NULL) ? dest : result->Clone();
|
---|
458 | }
|
---|
459 | } else {
|
---|
460 | // can't push down constant
|
---|
461 | lhs = Treewalk(node->GetLeftChild());
|
---|
462 | }
|
---|
463 |
|
---|
464 | // try to add the constant, if any, to any constant lhs or rhs
|
---|
465 | if (constant != NULL) {
|
---|
466 | if (IsConstant(lhs)) {
|
---|
467 | if (IsInt(lhs)) {
|
---|
468 | lhs->SetIntValue(lhs->GetIntValue() + constant->GetIntValue());
|
---|
469 | } else {
|
---|
470 | lhs->SetRealValue(lhs->GetRealValue() + constant->GetRealValue());
|
---|
471 | }
|
---|
472 | delete constant;
|
---|
473 | constant = NULL;
|
---|
474 | } else if (IsConstant(rhs)) {
|
---|
475 | if (IsInt(rhs)) {
|
---|
476 | rhs->SetIntValue(rhs->GetIntValue() + constant->GetIntValue());
|
---|
477 | } else {
|
---|
478 | rhs->SetRealValue(rhs->GetRealValue() + constant->GetRealValue());
|
---|
479 | }
|
---|
480 | delete constant;
|
---|
481 | constant = NULL;
|
---|
482 | }
|
---|
483 | }
|
---|
484 |
|
---|
485 | // algebraic identity
|
---|
486 | if (IsZero(lhs)) {
|
---|
487 | delete lhs;
|
---|
488 | return rhs;
|
---|
489 | }
|
---|
490 | if (IsZero(rhs)) {
|
---|
491 | delete rhs;
|
---|
492 | return lhs;
|
---|
493 | }
|
---|
494 |
|
---|
495 | // constant folding
|
---|
496 | if (IsConstant(lhs) && IsConstant(rhs)) {
|
---|
497 | IOperand *result = NULL;
|
---|
498 | if (IsInt(lhs)) {
|
---|
499 | result = new IOperand_Int(lhs->GetIntValue() + rhs->GetIntValue() + ((constant==NULL) ? 0 : constant->GetIntValue()));
|
---|
500 | } else {
|
---|
501 | result = new IOperand_Real(lhs->GetRealValue() + rhs->GetRealValue() + ((constant==NULL) ? 0 : constant->GetRealValue()));
|
---|
502 | }
|
---|
503 | delete lhs;
|
---|
504 | delete rhs;
|
---|
505 | return result;
|
---|
506 | }
|
---|
507 | } else {
|
---|
508 |
|
---|
509 | // calculate operands for unoptimized case
|
---|
510 | lhs = Treewalk(node->GetLeftChild());
|
---|
511 | rhs = Treewalk(node->GetRightChild());
|
---|
512 | }
|
---|
513 |
|
---|
514 | // generate add code
|
---|
515 | IOperand *result = (dest != NULL) ? dest : new IOperand_Symbol(GenerateTempVar(node->GetReturnType()));
|
---|
516 | IOperator op = ( (node->GetReturnType() == RT_INT) ? IOP_ADD_I : IOP_ADD_R );
|
---|
517 | if (constant == NULL) {
|
---|
518 | icode->AppendStatement(new IStatement(op, lhs, rhs, result));
|
---|
519 | } else {
|
---|
520 | IOperand *temp = new IOperand_Symbol(GenerateTempVar(node->GetReturnType()));
|
---|
521 | icode->AppendStatement(new IStatement(op, lhs, rhs, temp));
|
---|
522 | icode->AppendStatement(new IStatement(op, temp->Clone(), constant, result));
|
---|
523 | }
|
---|
524 | return (dest != NULL) ? dest : result->Clone();
|
---|
525 | }
|
---|
526 | break;
|
---|
527 | case NODE_SUB: // Substract
|
---|
528 | {
|
---|
529 | // calculate operands
|
---|
530 | IOperand *lhs = NULL;
|
---|
531 | IOperand *rhs = NULL;
|
---|
532 |
|
---|
533 | // attempt optimizations
|
---|
534 | if (bOptimize1) {
|
---|
535 | /* reverse evaluation of operands, due to the fact the tree is always
|
---|
536 | * set to be on the left and we like to fold constants where ever
|
---|
537 | * possible
|
---|
538 | */
|
---|
539 | rhs = Treewalk(node->GetRightChild());
|
---|
540 | // check if we need to push any constant down the tree
|
---|
541 | if (node->GetLeftChild()->GetNodeType() == NODE_ADD ||
|
---|
542 | node->GetLeftChild()->GetNodeType() == NODE_SUB ) {
|
---|
543 | if (IsConstant(rhs)) {
|
---|
544 | // right hand side is also constant
|
---|
545 | if (constant != NULL) {
|
---|
546 | if (IsInt(rhs)) {
|
---|
547 | rhs->SetIntValue((rhs->GetIntValue() * -1) + constant->GetIntValue());
|
---|
548 | } else {
|
---|
549 | rhs->SetRealValue((rhs->GetRealValue() * -1) + constant->GetRealValue());
|
---|
550 | }
|
---|
551 | } else {
|
---|
552 | /* Negate fresh new minus knob, if it is gonna be the first constant */
|
---|
553 | if (IsInt(rhs)) {
|
---|
554 | rhs->SetIntValue(rhs->GetIntValue() * -1);
|
---|
555 | } else {
|
---|
556 | rhs->SetRealValue(rhs->GetRealValue() * -1);
|
---|
557 | }
|
---|
558 | }
|
---|
559 |
|
---|
560 | // evaluate left hand side passing constant value
|
---|
561 | lhs = Treewalk(node->GetLeftChild(), dest, rhs);
|
---|
562 | return lhs;
|
---|
563 | } else {
|
---|
564 | // generate add instruction for the right hand side
|
---|
565 | IOperator op = ( (node->GetReturnType() == RT_INT) ? IOP_SUB_I : IOP_SUB_R );
|
---|
566 | lhs = Treewalk(node->GetLeftChild(), NULL, constant);
|
---|
567 | IOperand *result = (dest != NULL) ? dest : new IOperand_Symbol(GenerateTempVar(node->GetReturnType()));
|
---|
568 | icode->AppendStatement(new IStatement(op, lhs, rhs, result));
|
---|
569 | return (dest != NULL) ? dest : result->Clone();
|
---|
570 | }
|
---|
571 | } else {
|
---|
572 | // can't push down constant
|
---|
573 | lhs = Treewalk(node->GetLeftChild());
|
---|
574 | }
|
---|
575 |
|
---|
576 | // try to sub the constant, if any, to any constant lhs or rhs
|
---|
577 | if (constant != NULL) {
|
---|
578 | if (IsConstant(lhs)) {
|
---|
579 | if (IsInt(lhs)) {
|
---|
580 | lhs->SetIntValue(lhs->GetIntValue() + constant->GetIntValue());
|
---|
581 | } else {
|
---|
582 | lhs->SetRealValue(lhs->GetRealValue() + constant->GetRealValue());
|
---|
583 | }
|
---|
584 | delete constant;
|
---|
585 | constant = NULL;
|
---|
586 | } else if (IsConstant(rhs)) {
|
---|
587 | /* Negate right side as it is going to be negative constant value */
|
---|
588 | if (IsInt(rhs)) {
|
---|
589 | rhs->SetIntValue((rhs->GetIntValue() * -1) + constant->GetIntValue());
|
---|
590 | } else {
|
---|
591 | rhs->SetRealValue((rhs->GetRealValue() * -1) + constant->GetRealValue());
|
---|
592 | }
|
---|
593 | delete constant;
|
---|
594 | constant = NULL;
|
---|
595 | }
|
---|
596 | }
|
---|
597 |
|
---|
598 | // algebraic identity right side
|
---|
599 | if (IsZero(rhs)) {
|
---|
600 | delete rhs;
|
---|
601 | return lhs;
|
---|
602 | }
|
---|
603 |
|
---|
604 | // constant folding
|
---|
605 | if (IsConstant(lhs) && IsConstant(rhs)) {
|
---|
606 | IOperand *result = NULL;
|
---|
607 | if (IsInt(lhs)) {
|
---|
608 | result = new IOperand_Int(lhs->GetIntValue() - rhs->GetIntValue());
|
---|
609 | } else {
|
---|
610 | result = new IOperand_Real(lhs->GetRealValue() - rhs->GetRealValue());
|
---|
611 | }
|
---|
612 | delete lhs;
|
---|
613 | delete rhs;
|
---|
614 | return result;
|
---|
615 | }
|
---|
616 |
|
---|
617 | // algebraic identity left side
|
---|
618 | if (IsZero(lhs)) {
|
---|
619 | delete lhs;
|
---|
620 |
|
---|
621 | // generate unary minus code
|
---|
622 | IOperand *result = (dest != NULL) ? dest : new IOperand_Symbol(GenerateTempVar(node->GetReturnType()));
|
---|
623 | IOperator op = ( (node->GetReturnType() == RT_INT) ? IOP_UNARY_MINUS_I : IOP_UNARY_MINUS_R );
|
---|
624 | icode->AppendStatement(new IStatement(op, rhs, NULL, result));
|
---|
625 | return (dest != NULL) ? dest : result->Clone();
|
---|
626 | }
|
---|
627 | } else {
|
---|
628 |
|
---|
629 | // calculate operands for unoptimized case
|
---|
630 | lhs = Treewalk(node->GetLeftChild());
|
---|
631 | rhs = Treewalk(node->GetRightChild());
|
---|
632 | }
|
---|
633 |
|
---|
634 | // generate subtraction code
|
---|
635 | IOperand *result = (dest != NULL) ? dest : new IOperand_Symbol(GenerateTempVar(node->GetReturnType()));
|
---|
636 | IOperator op = ( (node->GetReturnType() == RT_INT) ? IOP_SUB_I : IOP_SUB_R );
|
---|
637 | if (constant == NULL) {
|
---|
638 | icode->AppendStatement(new IStatement(op, lhs, rhs, result));
|
---|
639 | } else {
|
---|
640 | IOperand *temp = new IOperand_Symbol(GenerateTempVar(node->GetReturnType()));
|
---|
641 | icode->AppendStatement(new IStatement(op, lhs, rhs, temp));
|
---|
642 | /* Constant could be negative, so always all value */
|
---|
643 | IOperator op = ( (node->GetReturnType() == RT_INT) ? IOP_ADD_I : IOP_ADD_R );
|
---|
644 | icode->AppendStatement(new IStatement(op, temp->Clone(), constant, result));
|
---|
645 | }
|
---|
646 |
|
---|
647 | return (dest != NULL) ? dest : result->Clone();
|
---|
648 | }
|
---|
649 | break;
|
---|
650 | case NODE_OR: // Bitwise OR operation
|
---|
651 | {
|
---|
652 | // calculate operands
|
---|
653 | IOperand *lhs = Treewalk(node->GetLeftChild());
|
---|
654 | IOperand *rhs = Treewalk(node->GetRightChild());
|
---|
655 |
|
---|
656 | // attempt optimizations
|
---|
657 | if (bOptimize1) {
|
---|
658 | // 0 or X will always evaluate to X
|
---|
659 | if (IsZero(lhs)) {
|
---|
660 | delete lhs;
|
---|
661 | return rhs;
|
---|
662 | }
|
---|
663 |
|
---|
664 | // X or 0 will always evaluate to X
|
---|
665 | if (IsZero(rhs)) {
|
---|
666 | delete rhs;
|
---|
667 | return lhs;
|
---|
668 | }
|
---|
669 |
|
---|
670 | // constant folding
|
---|
671 | if (IsConstant(lhs) && IsConstant(rhs)) {
|
---|
672 | IOperand *result = new IOperand_Int(lhs->GetIntValue() | rhs->GetIntValue());
|
---|
673 | delete lhs;
|
---|
674 | delete rhs;
|
---|
675 | return result;
|
---|
676 | }
|
---|
677 | }
|
---|
678 |
|
---|
679 | // generate bitwise or code
|
---|
680 | IOperand *result = (dest != NULL) ? dest : new IOperand_Symbol(GenerateTempVar(RT_INT));
|
---|
681 | icode->AppendStatement(new IStatement(IOP_OR, lhs, rhs, result));
|
---|
682 | return (dest != NULL) ? dest : result->Clone();
|
---|
683 | }
|
---|
684 | break;
|
---|
685 | case NODE_MUL: // Multiply
|
---|
686 | {
|
---|
687 | // calculate operands
|
---|
688 | IOperand *lhs = Treewalk(node->GetLeftChild());
|
---|
689 | IOperand *rhs = Treewalk(node->GetRightChild());
|
---|
690 |
|
---|
691 | // attempt optimizations
|
---|
692 | if (bOptimize1) {
|
---|
693 | // zero product
|
---|
694 | if (IsZero(lhs) || IsZero(rhs)) {
|
---|
695 | delete lhs;
|
---|
696 | delete rhs;
|
---|
697 | return new IOperand_Int(0);
|
---|
698 | }
|
---|
699 |
|
---|
700 | // algebraic identity
|
---|
701 | if (IsOne(lhs)) {
|
---|
702 | delete lhs;
|
---|
703 | return rhs;
|
---|
704 | }
|
---|
705 | if (IsOne(rhs)) {
|
---|
706 | delete rhs;
|
---|
707 | return lhs;
|
---|
708 | }
|
---|
709 |
|
---|
710 | // constant folding
|
---|
711 | if (IsConstant(lhs) && IsConstant(rhs)) {
|
---|
712 | IOperand *result = NULL;
|
---|
713 | if (IsInt(lhs)) {
|
---|
714 | result = new IOperand_Int(lhs->GetIntValue() * rhs->GetIntValue());
|
---|
715 | } else {
|
---|
716 | result = new IOperand_Real(lhs->GetRealValue() * rhs->GetRealValue());
|
---|
717 | }
|
---|
718 | delete lhs;
|
---|
719 | delete rhs;
|
---|
720 | return result;
|
---|
721 | }
|
---|
722 | }
|
---|
723 |
|
---|
724 | // generate multiply code
|
---|
725 | IOperand *result = (dest != NULL) ? dest : new IOperand_Symbol(GenerateTempVar(node->GetReturnType()));
|
---|
726 | IOperator op = ( (node->GetReturnType() == RT_INT) ? IOP_MUL_I : IOP_MUL_R );
|
---|
727 | icode->AppendStatement(new IStatement(op, lhs, rhs, result));
|
---|
728 | return (dest != NULL) ? dest : result->Clone();
|
---|
729 | }
|
---|
730 | break;
|
---|
731 | case NODE_DIV: // Divide
|
---|
732 | {
|
---|
733 | // calculate operands
|
---|
734 | IOperand *lhs = Treewalk(node->GetLeftChild());
|
---|
735 | IOperand *rhs = Treewalk(node->GetRightChild());
|
---|
736 |
|
---|
737 | // attempt optimizations
|
---|
738 | if (bOptimize1) {
|
---|
739 | // 0 / X will always evaluate to zero
|
---|
740 | if (IsZero(lhs)) {
|
---|
741 | delete lhs;
|
---|
742 | delete rhs;
|
---|
743 | return new IOperand_Real(0);
|
---|
744 | }
|
---|
745 |
|
---|
746 | // X / 1 will always evuluate to X
|
---|
747 | if (IsOne(rhs)) {
|
---|
748 | delete rhs;
|
---|
749 | return lhs;
|
---|
750 | }
|
---|
751 |
|
---|
752 | // XXX: How to act on X / 0, which should not be possible
|
---|
753 |
|
---|
754 | // constant folding
|
---|
755 | if (IsConstant(lhs) && IsConstant(rhs)) {
|
---|
756 | IOperand *result = NULL;
|
---|
757 | result = new IOperand_Real(lhs->GetRealValue() / rhs->GetRealValue());
|
---|
758 | delete lhs;
|
---|
759 | delete rhs;
|
---|
760 | return result;
|
---|
761 | }
|
---|
762 | }
|
---|
763 |
|
---|
764 | // generate division code
|
---|
765 | IOperand *result = (dest != NULL) ? dest : new IOperand_Symbol(GenerateTempVar(node->GetReturnType()));
|
---|
766 | icode->AppendStatement(new IStatement(IOP_DIV_R, lhs, rhs, result));
|
---|
767 | return (dest != NULL) ? dest : result->Clone();
|
---|
768 | }
|
---|
769 | break;
|
---|
770 | case NODE_IDIV: // Integer division
|
---|
771 | {
|
---|
772 | // calculate operands
|
---|
773 | IOperand *lhs = Treewalk(node->GetLeftChild());
|
---|
774 | IOperand *rhs = Treewalk(node->GetRightChild());
|
---|
775 |
|
---|
776 | // attempt optimizations
|
---|
777 | if (bOptimize1) {
|
---|
778 | // 0 / X will always evaluate to zero
|
---|
779 | if (IsZero(lhs)) {
|
---|
780 | delete lhs;
|
---|
781 | delete rhs;
|
---|
782 | return new IOperand_Int(0);
|
---|
783 | }
|
---|
784 |
|
---|
785 | // X / 1 will always evuluate to X
|
---|
786 | if (IsOne(rhs)) {
|
---|
787 | delete rhs;
|
---|
788 | return lhs;
|
---|
789 | }
|
---|
790 |
|
---|
791 | // XXX: How to act on X / 0, which should not be possible
|
---|
792 |
|
---|
793 | // constant folding
|
---|
794 | if (IsConstant(lhs) && IsConstant(rhs)) {
|
---|
795 | IOperand *result = NULL;
|
---|
796 | result = new IOperand_Int(lhs->GetIntValue() / rhs->GetIntValue());
|
---|
797 | delete lhs;
|
---|
798 | delete rhs;
|
---|
799 | return result;
|
---|
800 | }
|
---|
801 | }
|
---|
802 |
|
---|
803 | // generate division code
|
---|
804 | IOperand *result = (dest != NULL) ? dest : new IOperand_Symbol(GenerateTempVar(node->GetReturnType()));
|
---|
805 | icode->AppendStatement(new IStatement(IOP_DIV_I, lhs, rhs, result));
|
---|
806 | return (dest != NULL) ? dest : result->Clone();
|
---|
807 | }
|
---|
808 | break;
|
---|
809 | case NODE_MOD: // Modulo
|
---|
810 | {
|
---|
811 | // calculate operands
|
---|
812 | IOperand *lhs = Treewalk (node->GetLeftChild ());
|
---|
813 | IOperand *rhs = Treewalk (node->GetRightChild ());
|
---|
814 |
|
---|
815 | // attempt optimizations
|
---|
816 | if (bOptimize1) {
|
---|
817 | // 0 mod X will always evaluate to zero
|
---|
818 | if (IsZero (lhs)) {
|
---|
819 | delete lhs;
|
---|
820 | delete rhs;
|
---|
821 | return new IOperand_Int (0);
|
---|
822 | }
|
---|
823 |
|
---|
824 | // X mod 1 will always evaluate to zero
|
---|
825 | if (IsOne (rhs)) {
|
---|
826 | delete lhs;
|
---|
827 | delete rhs;
|
---|
828 | return new IOperand_Int (0);
|
---|
829 | }
|
---|
830 | // X mod -1 will always evaluate to zero
|
---|
831 | if (IsMinusOne (rhs)) {
|
---|
832 | delete lhs;
|
---|
833 | delete rhs;
|
---|
834 | return new IOperand_Int (0);
|
---|
835 | }
|
---|
836 | }
|
---|
837 |
|
---|
838 | // generate modulus code
|
---|
839 | IOperand *result = (dest != NULL) ? dest : new IOperand_Symbol(GenerateTempVar(node->GetReturnType()));
|
---|
840 | icode->AppendStatement (new IStatement (IOP_MOD, lhs, rhs, result));
|
---|
841 | return (dest != NULL) ? dest : result->Clone();
|
---|
842 | }
|
---|
843 | break;
|
---|
844 | case NODE_AND: // Bitwise AND operation
|
---|
845 | {
|
---|
846 | // calculate operands
|
---|
847 | IOperand *lhs = Treewalk (node->GetLeftChild ());
|
---|
848 | IOperand *rhs = Treewalk (node->GetRightChild ());
|
---|
849 |
|
---|
850 | // attempt optimizations
|
---|
851 | if (bOptimize1) {
|
---|
852 | // X and 0 will always evaluate to zero
|
---|
853 | if (IsZero (lhs) || IsZero (rhs)) {
|
---|
854 | delete lhs;
|
---|
855 | delete rhs;
|
---|
856 | return new IOperand_Int (0);
|
---|
857 | }
|
---|
858 | }
|
---|
859 |
|
---|
860 | // generate bitwise and code
|
---|
861 | IOperand *result = (dest != NULL) ? dest : new IOperand_Symbol(GenerateTempVar(node->GetReturnType()));
|
---|
862 | icode->AppendStatement (new IStatement (IOP_AND, lhs, rhs, result));
|
---|
863 | return (dest != NULL) ? dest : result->Clone();
|
---|
864 | }
|
---|
865 | break;
|
---|
866 |
|
---|
867 | /*
|
---|
868 | * Leafs
|
---|
869 | * these nodes have no child nodes
|
---|
870 | */
|
---|
871 | case NODE_NUM_INT: // Integer number
|
---|
872 | {
|
---|
873 | /* return the integer value */
|
---|
874 | return new IOperand_Int(node->GetIntValue());
|
---|
875 | }
|
---|
876 | break;
|
---|
877 | case NODE_NUM_REAL: // Real number
|
---|
878 | {
|
---|
879 | /* return the real value */
|
---|
880 | return new IOperand_Real(node->GetRealValue());
|
---|
881 | }
|
---|
882 | break;
|
---|
883 | case NODE_ID: // Identifier
|
---|
884 | {
|
---|
885 | /* ID requires returning its symbol */
|
---|
886 | return new IOperand_Symbol(node->GetSymbol());
|
---|
887 | }
|
---|
888 | break;
|
---|
889 | case NODE_EMPTY: // Empty leaf (terminates lists etc.)
|
---|
890 | {
|
---|
891 | return (NULL);
|
---|
892 | }
|
---|
893 | break;
|
---|
894 |
|
---|
895 | /*
|
---|
896 | * Unary nodes
|
---|
897 | * child The subtree to which the operation has to be applied
|
---|
898 | */
|
---|
899 | case NODE_NOT: // NOT operation
|
---|
900 | {
|
---|
901 | IOperand *operand = ICGenerator::Treewalk (node->GetChild ());
|
---|
902 |
|
---|
903 | // attempt optimizations
|
---|
904 | if (bOptimize1) {
|
---|
905 | // constant folding
|
---|
906 | if (IsConstant(operand)) {
|
---|
907 | IOperand *result = new IOperand_Int(~operand->GetIntValue());
|
---|
908 | delete operand;
|
---|
909 | return result;
|
---|
910 | }
|
---|
911 | }
|
---|
912 |
|
---|
913 | IOperand *result = (dest != NULL) ? dest : new IOperand_Symbol(GenerateTempVar(node->GetReturnType()));
|
---|
914 | icode->AppendStatement (new IStatement (IOP_NOT, operand, NULL, result));
|
---|
915 |
|
---|
916 | return (dest != NULL) ? dest : result->Clone();
|
---|
917 | }
|
---|
918 | break;
|
---|
919 | case NODE_SIGNPLUS: // Unary plus
|
---|
920 | {
|
---|
921 | /* Unary plus does not require any work, direct pass trough */
|
---|
922 | IOperand *operand = ICGenerator::Treewalk (node->GetChild ());
|
---|
923 | return (operand);
|
---|
924 | }
|
---|
925 | break;
|
---|
926 | case NODE_SIGNMINUS: // Unary minus
|
---|
927 | {
|
---|
928 | IOperand *operand = ICGenerator::Treewalk (node->GetChild ());
|
---|
929 |
|
---|
930 | // attempt optimizations
|
---|
931 | if (bOptimize1) {
|
---|
932 | // constant folding
|
---|
933 | if (IsConstant(operand)) {
|
---|
934 | IOperand *result = NULL;
|
---|
935 | if (IsInt(operand)) {
|
---|
936 | result = new IOperand_Int(-operand->GetIntValue());
|
---|
937 | } else {
|
---|
938 | result = new IOperand_Real(-operand->GetRealValue());
|
---|
939 | }
|
---|
940 | delete operand;
|
---|
941 | return result;
|
---|
942 | }
|
---|
943 | }
|
---|
944 |
|
---|
945 | ReturnType type = node->GetReturnType();
|
---|
946 | IOperator op = ( (type == RT_REAL) ? IOP_UNARY_MINUS_R : IOP_UNARY_MINUS_I );
|
---|
947 | IOperand *result = (dest != NULL) ? dest : new IOperand_Symbol(GenerateTempVar(type));
|
---|
948 | icode->AppendStatement (new IStatement (op, operand, NULL, result));
|
---|
949 | return (dest != NULL) ? dest : result->Clone();
|
---|
950 | }
|
---|
951 | break;
|
---|
952 | case NODE_COERCION: // Int to Real coercion
|
---|
953 | {
|
---|
954 | IOperand *operand = ICGenerator::Treewalk (node->GetChild ());
|
---|
955 |
|
---|
956 | // attempt optimizations
|
---|
957 | if (bOptimize1) {
|
---|
958 | // constant folding
|
---|
959 | if (IsConstant(operand)) {
|
---|
960 | IOperand *result = new IOperand_Real(operand->GetIntValue());
|
---|
961 | delete operand;
|
---|
962 | return result;
|
---|
963 | }
|
---|
964 | }
|
---|
965 |
|
---|
966 | IOperand *result = (dest != NULL) ? dest : new IOperand_Symbol(GenerateTempVar(RT_REAL));
|
---|
967 | icode->AppendStatement (new IStatement (IOP_INT_TO_REAL, operand, NULL, result));
|
---|
968 | return (dest != NULL) ? dest : result->Clone();
|
---|
969 | }
|
---|
970 | break;
|
---|
971 | default:
|
---|
972 | assert (0); // can't happen
|
---|
973 |
|
---|
974 | }
|
---|
975 | return NULL; // silences warning
|
---|
976 | }
|
---|
977 |
|
---|
978 | IOperand * ICGenerator::GenerateRelopCode(IOperator op, Node *node)
|
---|
979 | {
|
---|
980 | // generate labels
|
---|
981 | Symbol *true_label = GenerateLabel();
|
---|
982 |
|
---|
983 | // get operands
|
---|
984 | IOperand *lhs = Treewalk(node->GetLeftChild());
|
---|
985 | IOperand *rhs = Treewalk(node->GetRightChild());
|
---|
986 |
|
---|
987 | // attempt optimizations
|
---|
988 | if (bOptimize1) {
|
---|
989 | // constant folding
|
---|
990 | if (IsConstant(lhs) && IsConstant(rhs)) {
|
---|
991 | int value;
|
---|
992 | switch (op) {
|
---|
993 | case IOP_BEQ_I: value = lhs->GetIntValue() == rhs->GetIntValue(); break;
|
---|
994 | case IOP_BLT_I: value = lhs->GetIntValue() < rhs->GetIntValue(); break;
|
---|
995 | case IOP_BGT_I: value = lhs->GetIntValue() > rhs->GetIntValue(); break;
|
---|
996 | case IOP_BLE_I: value = lhs->GetIntValue() <= rhs->GetIntValue(); break;
|
---|
997 | case IOP_BGE_I: value = lhs->GetIntValue() >= rhs->GetIntValue(); break;
|
---|
998 | case IOP_BNE_I: value = lhs->GetIntValue() != rhs->GetIntValue(); break;
|
---|
999 | case IOP_BEQ_R: value = lhs->GetRealValue() == rhs->GetRealValue(); break;
|
---|
1000 | case IOP_BLT_R: value = lhs->GetRealValue() < rhs->GetRealValue(); break;
|
---|
1001 | case IOP_BGT_R: value = lhs->GetRealValue() > rhs->GetRealValue(); break;
|
---|
1002 | case IOP_BLE_R: value = lhs->GetRealValue() <= rhs->GetRealValue(); break;
|
---|
1003 | case IOP_BGE_R: value = lhs->GetRealValue() >= rhs->GetRealValue(); break;
|
---|
1004 | case IOP_BNE_R: value = lhs->GetRealValue() != rhs->GetRealValue(); break;
|
---|
1005 | default:
|
---|
1006 | assert(0); // can't happen
|
---|
1007 | }
|
---|
1008 | IOperand *result = new IOperand_Int(value);
|
---|
1009 | delete lhs;
|
---|
1010 | delete rhs;
|
---|
1011 | return result;
|
---|
1012 | }
|
---|
1013 | }
|
---|
1014 |
|
---|
1015 | /* generate code */
|
---|
1016 | /* Methode 1 | Methode 2
|
---|
1017 | * -------------------------------------
|
---|
1018 | * b = 0 goto TRUE | ret = 1
|
---|
1019 | * ret = 0 | b = 0 GOTO TRUE
|
---|
1020 | * goto END | ret = 0
|
---|
1021 | * :TRUE | :TRUE
|
---|
1022 | * ret = 1 |
|
---|
1023 | * :END |
|
---|
1024 | */
|
---|
1025 | /* Method 2 used */
|
---|
1026 | IOperand *result = new IOperand_Symbol(GenerateTempVar(RT_INT));
|
---|
1027 | icode->AppendStatement(new IStatement(IOP_ASSIGN_I, new IOperand_Int(1), NULL, result));
|
---|
1028 | icode->AppendStatement(new IStatement(op, lhs, rhs, new IOperand_Symbol(true_label)));
|
---|
1029 | icode->AppendStatement(new IStatement(IOP_ASSIGN_I, new IOperand_Int(0), NULL, result->Clone()));
|
---|
1030 | icode->AppendStatement(new IStatement(IOP_LABEL, new IOperand_Symbol(true_label), NULL, NULL));
|
---|
1031 | return result->Clone();
|
---|
1032 | }
|
---|
1033 |
|
---|
1034 | bool ICGenerator::IsZero(IOperand *operand) const
|
---|
1035 | {
|
---|
1036 | return (IsInt(operand) && operand->GetIntValue() == 0) ||
|
---|
1037 | (IsReal(operand) && operand->GetRealValue() == 0.0);
|
---|
1038 | }
|
---|
1039 |
|
---|
1040 | bool ICGenerator::IsOne(IOperand *operand) const
|
---|
1041 | {
|
---|
1042 | return (IsInt(operand) && operand->GetIntValue() == 1) ||
|
---|
1043 | (IsReal(operand) && operand->GetRealValue() == 1.0);
|
---|
1044 | }
|
---|
1045 |
|
---|
1046 | bool ICGenerator::IsMinusOne(IOperand *operand) const
|
---|
1047 | {
|
---|
1048 | return (IsInt(operand) && operand->GetIntValue() == -1) ||
|
---|
1049 | (IsReal(operand) && operand->GetRealValue() == -1.0);
|
---|
1050 | }
|
---|
1051 |
|
---|
1052 | bool ICGenerator::IsConstant(IOperand *operand) const
|
---|
1053 | {
|
---|
1054 | return IsInt(operand) || IsReal(operand);
|
---|
1055 | }
|
---|
1056 |
|
---|
1057 | bool ICGenerator::IsInt(IOperand *operand) const
|
---|
1058 | {
|
---|
1059 | return operand->GetOperandType() == OT_INT;
|
---|
1060 | }
|
---|
1061 |
|
---|
1062 | bool ICGenerator::IsReal(IOperand *operand) const
|
---|
1063 | {
|
---|
1064 | return operand->GetOperandType() == OT_REAL;
|
---|
1065 | }
|
---|