source: src/CodeGen/CodeGenerator.cc@ 94b4364

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 94b4364 was 94b4364, checked in by Rob Schluntz <rschlunt@…>, 10 years ago

implemented resolver methods for aggregate initialization

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