source: src/CodeGen/CodeGenerator2.cc@ 09d789c

ADT aaron-thesis arm-eh ast-experimental cleanup-dtors ctor deferred_resn demangler enum forall-pointer-decay gc_noraii jacob/cs343-translation jenkins-sandbox memory new-ast new-ast-unique-expr new-env no_list persistent-indexer pthread-emulation qualifiedEnum resolv-new string with_gc
Last change on this file since 09d789c was 843054c2, checked in by Peter A. Buhr <pabuhr@…>, 10 years ago

licencing: seventh groups of files

  • Property mode set to 100644
File size: 18.0 KB
Line 
1//
2// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
3//
4// The contents of this file are covered under the licence agreement in the
5// file "LICENCE" distributed with Cforall.
6//
7// CodeGenerator2.cc --
8//
9// Author : Richard C. Bilson
10// Created On : Mon May 18 07:44:20 2015
11// Last Modified By : Peter A. Buhr
12// Last Modified On : Thu May 21 17:13:35 2015
13// Update Count : 7
14//
15
16#include <algorithm>
17#include <iostream>
18#include <cassert>
19#include <list>
20
21#include "SynTree/Type.h"
22#include "SynTree/Declaration.h"
23#include "SynTree/Statement.h"
24#include "SynTree/Expression.h"
25#include "SynTree/Initializer.h"
26
27#include "utility.h"
28#include "UnimplementedError.h"
29
30#include "CodeGenerator2.h"
31#include "OperatorTable.h"
32#include "GenType.h"
33
34using namespace std;
35
36namespace CodeGen {
37 int CodeGenerator2::tabsize = 4;
38
39 CodeGenerator2::CodeGenerator2( std::ostream &os ) : cur_indent( 0 ), insideFunction( false ), before( os ), after() { }
40
41 CodeGenerator2::CodeGenerator2( std::ostream &os, std::string init, int indent, bool infunp )
42 : cur_indent( indent ), insideFunction( infunp ), before( os ) {
43 //before << std::string( init );
44 }
45
46 CodeGenerator2::CodeGenerator2( std::ostream &os, char *init, int indent, bool infunp )
47 : cur_indent( indent ), insideFunction( infunp ), before( os ) {
48 //before << std::string( init );
49 }
50
51 string mangleName( DeclarationWithType *decl ) {
52 if ( decl->get_mangleName() != "" ) {
53 return decl->get_mangleName();
54 } else {
55 return decl->get_name();
56 } // if
57 }
58
59 //*** Declarations
60 void CodeGenerator2::visit( FunctionDecl *functionDecl ) {
61 handleStorageClass( functionDecl );
62 before << genType( functionDecl->get_functionType(), mangleName( functionDecl ) );
63
64 // how to get this to the Functype?
65 std::list< Declaration * > olds = functionDecl->get_oldDecls();
66 if ( ! olds.empty() ) {
67 before << " /* function has old declaration */";
68 } // if
69
70 // acceptAll( functionDecl->get_oldDecls(), *this );
71 if ( functionDecl->get_statements() ) {
72 functionDecl->get_statements()->accept(*this );
73 } // if
74 }
75
76 void CodeGenerator2::visit( ObjectDecl *objectDecl ) {
77 handleStorageClass( objectDecl );
78 before << genType( objectDecl->get_type(), mangleName( objectDecl ) );
79
80 if ( objectDecl->get_init() ) {
81 before << " = ";
82 objectDecl->get_init()->accept( *this );
83 } // if
84 if ( objectDecl->get_bitfieldWidth() ) {
85 before << ":";
86 objectDecl->get_bitfieldWidth()->accept( *this );
87 } // if
88 }
89
90 void CodeGenerator2::handleAggregate( AggregateDecl *aggDecl ) {
91 if ( aggDecl->get_name() != "" )
92 before << aggDecl->get_name();
93
94 std::list< Declaration * > &memb = aggDecl->get_members();
95
96 if ( ! memb.empty() ) {
97 before << endl << string( cur_indent, ' ' ) << "{" << endl;
98
99 cur_indent += CodeGenerator2::tabsize;
100 for ( std::list< Declaration* >::iterator i = memb.begin(); i != memb.end(); i++) {
101 before << string( cur_indent, ' ' );
102 (*i)->accept(*this );
103 before << ";" << endl;
104 }
105
106 cur_indent -= CodeGenerator2::tabsize;
107
108 before << string( cur_indent, ' ' ) << "}";
109 } // if
110 }
111
112 void CodeGenerator2::visit( StructDecl *structDecl ) {
113 before << "struct ";
114 handleAggregate( structDecl );
115 }
116
117 void CodeGenerator2::visit( UnionDecl *aggregateDecl ) {
118 before << "union ";
119 handleAggregate( aggregateDecl );
120 }
121
122 void CodeGenerator2::visit( EnumDecl *aggDecl ) {
123 before << "enum ";
124
125 if ( aggDecl->get_name() != "" )
126 before << aggDecl->get_name();
127
128 std::list< Declaration* > &memb = aggDecl->get_members();
129
130 if ( ! memb.empty() ) {
131 before << endl << "{" << endl;
132
133 cur_indent += CodeGenerator2::tabsize;
134 for ( std::list< Declaration* >::iterator i = memb.begin(); i != memb.end(); i++) {
135 ObjectDecl *obj = dynamic_cast< ObjectDecl* >( *i );
136 assert( obj );
137 before << string( cur_indent, ' ' ) << mangleName( obj );
138 if ( obj->get_init() ) {
139 before << " = ";
140 obj->get_init()->accept(*this );
141 } // if
142 before << "," << endl;
143 } // for
144
145 cur_indent -= CodeGenerator2::tabsize;
146
147 before << "}" << endl;
148 } // if
149 }
150
151 void CodeGenerator2::visit( ContextDecl *aggregateDecl ) {}
152
153 void CodeGenerator2::visit( TypedefDecl *typeDecl ) {
154 before << "typedef ";
155 before << genType( typeDecl->get_base(), typeDecl->get_name() );
156 }
157
158 void CodeGenerator2::visit( TypeDecl *typeDecl ) {
159 // really, we should mutate this into something that isn't a TypeDecl but that requires large-scale changes,
160 // still to be done
161 before << "extern unsigned long " << typeDecl->get_name();
162 if ( typeDecl->get_base() ) {
163 before << " = sizeof( " << genType( typeDecl->get_base(), "" ) << " )";
164 } // if
165 }
166
167 void CodeGenerator2::visit( SingleInit *init ) {
168 init->get_value()->accept( *this );
169 }
170
171 void CodeGenerator2::visit( ListInit *init ) {
172 before << "{ ";
173 genCommaList( init->begin_initializers(), init->end_initializers() );
174 before << " }";
175 }
176
177 void CodeGenerator2::visit( Constant *constant ) {
178 before << constant->get_value() ;
179 }
180
181 //*** Expressions
182 void CodeGenerator2::visit( ApplicationExpr *applicationExpr ) {
183 if ( VariableExpr *varExpr = dynamic_cast< VariableExpr* >( applicationExpr->get_function() ) ) {
184 OperatorInfo opInfo;
185 if ( varExpr->get_var()->get_linkage() == LinkageSpec::Intrinsic && operatorLookup( varExpr->get_var()->get_name(), opInfo ) ) {
186 std::list< Expression* >::iterator arg = applicationExpr->get_args().begin();
187 switch ( opInfo.type ) {
188 case OT_PREFIXASSIGN:
189 case OT_POSTFIXASSIGN:
190 case OT_INFIXASSIGN:
191 {
192 assert( arg != applicationExpr->get_args().end() );
193 if ( AddressExpr *addrExpr = dynamic_cast< AddressExpr * >( *arg ) ) {
194
195 *arg = addrExpr->get_arg();
196 } else {
197 UntypedExpr *newExpr = new UntypedExpr( new NameExpr( "*?" ) );
198 newExpr->get_args().push_back( *arg );
199 *arg = newExpr;
200 } // if
201 break;
202 }
203
204 default:
205 // do nothing
206 ;
207 }
208
209 switch ( opInfo.type ) {
210 case OT_INDEX:
211 assert( applicationExpr->get_args().size() == 2 );
212 (*arg++)->accept( *this );
213 before << "[";
214 (*arg)->accept( *this );
215 before << "]";
216 break;
217
218 case OT_CALL:
219 // there are no intrinsic definitions of the function call operator
220 assert( false );
221 break;
222
223 case OT_PREFIX:
224 case OT_PREFIXASSIGN:
225 assert( applicationExpr->get_args().size() == 1 );
226 before << "(";
227 before << opInfo.symbol;
228 (*arg)->accept( *this );
229 before << ")";
230 break;
231
232 case OT_POSTFIX:
233 case OT_POSTFIXASSIGN:
234 assert( applicationExpr->get_args().size() == 1 );
235 (*arg)->accept( *this );
236 before << opInfo.symbol;
237 break;
238
239 case OT_INFIX:
240 case OT_INFIXASSIGN:
241 assert( applicationExpr->get_args().size() == 2 );
242 before << "(";
243 (*arg++)->accept( *this );
244 before << opInfo.symbol;
245 (*arg)->accept( *this );
246 before << ")";
247 break;
248
249 case OT_CONSTANT:
250 // there are no intrinsic definitions of 0 or 1 as functions
251 assert( false );
252 }
253 } else {
254 varExpr->accept( *this );
255 before << "(";
256 genCommaList( applicationExpr->get_args().begin(), applicationExpr->get_args().end() );
257 before << ")";
258 } // if
259 } else {
260 applicationExpr->get_function()->accept( *this );
261 before << "(";
262 genCommaList( applicationExpr->get_args().begin(), applicationExpr->get_args().end() );
263 before << ")";
264 } // if
265 }
266
267 void CodeGenerator2::visit( UntypedExpr *untypedExpr ) {
268 if ( NameExpr *nameExpr = dynamic_cast< NameExpr* >( untypedExpr->get_function() ) ) {
269 OperatorInfo opInfo;
270 if ( operatorLookup( nameExpr->get_name(), opInfo ) ) {
271 std::list< Expression* >::iterator arg = untypedExpr->get_args().begin();
272 switch ( opInfo.type ) {
273 case OT_INDEX:
274 assert( untypedExpr->get_args().size() == 2 );
275 (*arg++)->accept( *this );
276 before << "[";
277 (*arg)->accept( *this );
278 before << "]";
279 break;
280
281 case OT_CALL:
282 assert( false );
283 break;
284
285 case OT_PREFIX:
286 case OT_PREFIXASSIGN:
287 assert( untypedExpr->get_args().size() == 1 );
288 before << "(";
289 before << opInfo.symbol;
290 (*arg)->accept( *this );
291 before << ")";
292 break;
293
294 case OT_POSTFIX:
295 case OT_POSTFIXASSIGN:
296 assert( untypedExpr->get_args().size() == 1 );
297 (*arg)->accept( *this );
298 before << opInfo.symbol;
299 break;
300
301 case OT_INFIX:
302 case OT_INFIXASSIGN:
303 assert( untypedExpr->get_args().size() == 2 );
304 before << "(";
305 (*arg++)->accept( *this );
306 before << opInfo.symbol;
307 (*arg)->accept( *this );
308 before << ")";
309 break;
310
311 case OT_CONSTANT:
312 // there are no intrinsic definitions of 0 or 1 as functions
313 assert( false );
314 }
315 } else {
316 nameExpr->accept( *this );
317 before << "(";
318 genCommaList( untypedExpr->get_args().begin(), untypedExpr->get_args().end() );
319 before << ")";
320 } // if
321 } else {
322 untypedExpr->get_function()->accept( *this );
323 before << "(";
324 genCommaList( untypedExpr->get_args().begin(), untypedExpr->get_args().end() );
325 before << ")";
326 } // if
327 }
328
329 void CodeGenerator2::visit( NameExpr *nameExpr ) {
330 OperatorInfo opInfo;
331 if ( operatorLookup( nameExpr->get_name(), opInfo ) ) {
332 assert( opInfo.type == OT_CONSTANT );
333 before << opInfo.symbol;
334 } else {
335 before << nameExpr->get_name();
336 } // if
337 }
338
339 void CodeGenerator2::visit( AddressExpr *addressExpr ) {
340 before << "(&";
341 // this hack makes sure that we don't convert "constant_zero" to "0" if we're taking its address
342 if ( VariableExpr *variableExpr = dynamic_cast< VariableExpr* >( addressExpr->get_arg() ) ) {
343 before << mangleName( variableExpr->get_var() );
344 } else {
345 addressExpr->get_arg()->accept( *this );
346 } // if
347 before << ")";
348 }
349
350 void CodeGenerator2::visit( CastExpr *castExpr ) {
351 before << "((";
352 if ( castExpr->get_results().empty() ) {
353 before << "void" ;
354 } else {
355 before << genType( castExpr->get_results().front(), "" );
356 } // if
357 before << ")";
358 castExpr->get_arg()->accept( *this );
359 before << ")";
360 }
361
362 void CodeGenerator2::visit( UntypedMemberExpr *memberExpr ) {
363 assert( false );
364 }
365
366 void CodeGenerator2::visit( MemberExpr *memberExpr ) {
367 memberExpr->get_aggregate()->accept( *this );
368 before << "." << mangleName( memberExpr->get_member() );
369 }
370
371 void CodeGenerator2::visit( VariableExpr *variableExpr ) {
372 OperatorInfo opInfo;
373 if ( variableExpr->get_var()->get_linkage() == LinkageSpec::Intrinsic && operatorLookup( variableExpr->get_var()->get_name(), opInfo ) && opInfo.type == OT_CONSTANT ) {
374 before << opInfo.symbol;
375 } else {
376 before << mangleName( variableExpr->get_var() );
377 } // if
378 }
379
380 void CodeGenerator2::visit( ConstantExpr *constantExpr ) {
381 assert( constantExpr->get_constant() );
382 constantExpr->get_constant()->accept( *this );
383 }
384
385 void CodeGenerator2::visit( SizeofExpr *sizeofExpr ) {
386 before << "sizeof(";
387 if ( sizeofExpr->get_isType() ) {
388 before << genType( sizeofExpr->get_type(), "" );
389 } else {
390 sizeofExpr->get_expr()->accept( *this );
391 } // if
392 before << ")";
393 }
394
395 void CodeGenerator2::visit( LogicalExpr *logicalExpr ) {
396 before << "(";
397 logicalExpr->get_arg1()->accept( *this );
398 if ( logicalExpr->get_isAnd() ) {
399 before << " && ";
400 } else {
401 before << " || ";
402 } // if
403 logicalExpr->get_arg2()->accept( *this );
404 before << ")";
405 }
406
407 void CodeGenerator2::visit( ConditionalExpr *conditionalExpr ) {
408 before << "(";
409 conditionalExpr->get_arg1()->accept( *this );
410 before << " ? ";
411 conditionalExpr->get_arg2()->accept( *this );
412 before << " : ";
413 conditionalExpr->get_arg3()->accept( *this );
414 before << ")";
415 }
416
417 void CodeGenerator2::visit( CommaExpr *commaExpr ) {
418 before << "(";
419 commaExpr->get_arg1()->accept( *this );
420 before << " , ";
421 commaExpr->get_arg2()->accept( *this );
422 before << ")";
423 }
424
425 void CodeGenerator2::visit( TupleExpr *tupleExpr ) {}
426
427 void CodeGenerator2::visit( TypeExpr *typeExpr ) {}
428
429
430 //*** Statements
431 void CodeGenerator2::visit( CompoundStmt *compoundStmt ) {
432 std::list<Statement*> ks = compoundStmt->get_kids();
433
434 before << endl << string( cur_indent, ' ' ) << "{" << endl;
435
436 cur_indent += CodeGenerator2::tabsize;
437
438 for ( std::list<Statement *>::iterator i = ks.begin(); i != ks.end(); i++) {
439 before << string( cur_indent, ' ' ) << printLabels( (*i)->get_labels() ) ;
440 (*i)->accept(*this );
441 shift_left();
442 before << endl;
443 }
444 cur_indent -= CodeGenerator2::tabsize;
445
446 before << string( cur_indent, ' ' ) << "}" << endl;
447 }
448
449 void CodeGenerator2::visit( ExprStmt *exprStmt ) {
450 if ( exprStmt != 0 ) {
451 exprStmt->get_expr()->accept( *this );
452 shift_left();
453 before << ";" ;
454 } // if
455 }
456
457 void CodeGenerator2::visit( IfStmt *ifStmt ) {
458 before << "if (";
459 ifStmt->get_condition()->accept(*this );
460 after += ")\n";
461 shift_left();
462
463 cur_indent += CodeGenerator2::tabsize;
464 before << string( cur_indent, ' ' );
465 ifStmt->get_thenPart()->accept(*this );
466 cur_indent -= CodeGenerator2::tabsize;
467 shift_left(); before << endl;
468
469 if ( ifStmt->get_elsePart() != 0) {
470 before << string( cur_indent, ' ' ) << " else " << endl ;
471
472 cur_indent += CodeGenerator2::tabsize;
473 ifStmt->get_elsePart()->accept(*this );
474 cur_indent -= CodeGenerator2::tabsize;
475 } // if
476 }
477
478 void CodeGenerator2::visit( SwitchStmt *switchStmt ) {
479 //before << /* "\r" << */ string( cur_indent, ' ' ) << CodeGenerator2::printLabels( switchStmt->get_labels() )
480 before << "switch (" ;
481 switchStmt->get_condition()->accept(*this );
482 after += ")\n";
483 shift_left();
484
485 before << string( cur_indent, ' ' ) << "{" << std::endl;
486 cur_indent += CodeGenerator2::tabsize;
487
488 std::list< Statement * > stmts = switchStmt->get_branches();
489 bool lastBreak = false;
490
491 // horrible, horrible hack
492 if ( dynamic_cast<BranchStmt *>( stmts.back() ) != 0 ) {
493 lastBreak = true;
494 stmts.pop_back();
495 } // if
496 acceptAll( stmts, *this );
497 if ( lastBreak ) {
498 Statement *st = switchStmt->get_branches().back();
499 before << CodeGenerator2::printLabels( st->get_labels());
500 st->accept( *this );
501 } // if
502
503 cur_indent -= CodeGenerator2::tabsize;
504
505 before << /* "\r" << */ string( cur_indent, ' ' ) << "}" << endl ;
506 }
507
508 void CodeGenerator2::visit( CaseStmt *caseStmt ) {
509 before << string( cur_indent, ' ' );
510 if ( caseStmt->isDefault())
511 before << "default " ;
512 else {
513 before << "case " ;
514 caseStmt->get_condition()->accept(*this );
515 } // if
516 after += ":\n";
517 shift_left();
518
519 std::list<Statement *> sts = caseStmt->get_statements();
520
521 cur_indent += CodeGenerator2::tabsize;
522 for ( std::list<Statement *>::iterator i = sts.begin(); i != sts.end(); i++) {
523 before << /* "\r" << */ string( cur_indent, ' ' ) << printLabels( (*i)->get_labels() ) ;
524 (*i)->accept(*this );
525 shift_left();
526 before << ";" << endl;
527 }
528 cur_indent -= CodeGenerator2::tabsize;
529 }
530
531 void CodeGenerator2::visit( BranchStmt *branchStmt ) {
532 switch ( branchStmt->get_type()) {
533 case BranchStmt::Goto:
534 if ( ! branchStmt->get_target().empty() )
535 before << "goto " << branchStmt->get_target();
536 else {
537 if ( branchStmt->get_computedTarget() != 0 ) {
538 before << "goto *";
539 branchStmt->get_computedTarget()->accept( *this );
540 } // if
541 } // if
542 break;
543 case BranchStmt::Break:
544 before << "break";
545 break;
546 case BranchStmt::Continue:
547 before << "continue";
548 break;
549 }
550 before << ";";
551 }
552
553
554 void CodeGenerator2::visit( ReturnStmt *returnStmt ) {
555 before << "return ";
556
557 // xxx -- check for null expression;
558 if ( returnStmt->get_expr() ) {
559 returnStmt->get_expr()->accept( *this );
560 } // if
561 after += ";";
562 }
563
564 void CodeGenerator2::visit( WhileStmt *whileStmt ) {
565 if ( whileStmt->get_isDoWhile() )
566 before << "do" ;
567 else {
568 before << "while (" ;
569 whileStmt->get_condition()->accept(*this );
570 after += ")";
571 } // if
572 after += "{\n";
573 shift_left();
574
575 whileStmt->get_body()->accept( *this );
576
577 before << /* "\r" << */ string( cur_indent, ' ' ) << "}" ;
578
579 if ( whileStmt->get_isDoWhile() ) {
580 before << " while (" ;
581 whileStmt->get_condition()->accept(*this );
582 after += ");";
583 } // if
584
585 after += "\n";
586 }
587
588 void CodeGenerator2::visit( ForStmt *forStmt ) {
589 before << "for (";
590
591 if ( forStmt->get_initialization() != 0 )
592 forStmt->get_initialization()->accept( *this );
593 else
594 before << ";";
595 shift_left();
596
597 if ( forStmt->get_condition() != 0 )
598 forStmt->get_condition()->accept( *this );
599 shift_left(); before << ";";
600
601 if ( forStmt->get_increment() != 0 )
602 forStmt->get_increment()->accept( *this );
603 shift_left(); before << ")" << endl;
604
605 if ( forStmt->get_body() != 0 ) {
606 cur_indent += CodeGenerator2::tabsize;
607 before << string( cur_indent, ' ' ) << CodeGenerator2::printLabels( forStmt->get_body()->get_labels() );
608 forStmt->get_body()->accept( *this );
609 cur_indent -= CodeGenerator2::tabsize;
610 } // if
611 }
612
613 void CodeGenerator2::visit( NullStmt *nullStmt ) {
614 //before << /* "\r" << */ string( cur_indent, ' ' ) << CodeGenerator2::printLabels( nullStmt->get_labels() );
615 before << "/* null statement */ ;";
616 }
617
618 void CodeGenerator2::visit( DeclStmt *declStmt ) {
619 declStmt->get_decl()->accept( *this );
620
621 if ( doSemicolon( declStmt->get_decl() ) ) {
622 after += ";";
623 } // if
624 shift_left();
625 }
626
627 std::string CodeGenerator2::printLabels( std::list< Label > &l ) {
628 std::string str( "" );
629 l.unique();
630
631 for ( std::list< Label >::iterator i = l.begin(); i != l.end(); i++ )
632 str += *i + ": ";
633
634 return str;
635 }
636
637 void CodeGenerator2::shift_left() {
638 before << after;
639 after = "";
640 }
641
642 void CodeGenerator2::handleStorageClass( Declaration *decl ) {
643 switch ( decl->get_storageClass() ) {
644 case Declaration::NoStorageClass:
645 break;
646 case Declaration::Extern:
647 before << "extern ";
648 break;
649 case Declaration::Static:
650 before << "static ";
651 break;
652 case Declaration::Auto:
653 // silently drop storage class
654 break;
655 case Declaration::Register:
656 before << "register ";
657 break;
658 } // switch
659 }
660} // namespace CodeGen
661
662// Local Variables: //
663// tab-width: 4 //
664// mode: c++ //
665// compile-command: "make install" //
666// End: //
Note: See TracBrowser for help on using the repository browser.