source: src/CodeGen/CodeGenerator.cc@ 4e8949f

ADT aaron-thesis arm-eh ast-experimental cleanup-dtors deferred_resn demangler enum forall-pointer-decay jacob/cs343-translation jenkins-sandbox new-ast new-ast-unique-expr new-env no_list persistent-indexer pthread-emulation qualifiedEnum resolv-new with_gc
Last change on this file since 4e8949f was 4e8949f, checked in by Rob Schluntz <rschlunt@…>, 8 years ago

Handle ConstructorExpr in CodeGenerator

  • Property mode set to 100644
File size: 32.1 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 : Peter A. Buhr
12// Last Modified On : Sun Sep 3 20:42:52 2017
13// Update Count : 490
14//
15#include "CodeGenerator.h"
16
17#include <cassert> // for assert, assertf
18#include <list> // for _List_iterator, list, list<>::it...
19
20#include "Common/SemanticError.h" // for SemanticError
21#include "Common/UniqueName.h" // for UniqueName
22#include "Common/utility.h" // for CodeLocation, toString
23#include "GenType.h" // for genType
24#include "InitTweak/InitTweak.h" // for getPointerBase
25#include "OperatorTable.h" // for OperatorInfo, operatorLookup
26#include "Parser/LinkageSpec.h" // for Spec, Intrinsic
27#include "SynTree/Attribute.h" // for Attribute
28#include "SynTree/BaseSyntaxNode.h" // for BaseSyntaxNode
29#include "SynTree/Constant.h" // for Constant
30#include "SynTree/Declaration.h" // for DeclarationWithType, TypeDecl
31#include "SynTree/Expression.h" // for Expression, UntypedExpr, Applica...
32#include "SynTree/Initializer.h" // for Initializer, ListInit, Designation
33#include "SynTree/Label.h" // for Label, operator<<
34#include "SynTree/Statement.h" // for Statement, AsmStmt, BranchStmt
35#include "SynTree/Type.h" // for Type, Type::StorageClasses, Func...
36
37using namespace std;
38
39namespace CodeGen {
40 int CodeGenerator::tabsize = 4;
41
42 // the kinds of statements that would ideally be followed by whitespace
43 bool wantSpacing( Statement * stmt) {
44 return dynamic_cast< IfStmt * >( stmt ) || dynamic_cast< CompoundStmt * >( stmt ) ||
45 dynamic_cast< WhileStmt * >( stmt ) || dynamic_cast< ForStmt * >( stmt ) || dynamic_cast< SwitchStmt *>( stmt );
46 }
47
48 void CodeGenerator::extension( Expression * expr ) {
49 if ( expr->get_extension() ) {
50 output << "__extension__ ";
51 } // if
52 } // extension
53
54 void CodeGenerator::extension( Declaration * decl ) {
55 if ( decl->get_extension() ) {
56 output << "__extension__ ";
57 } // if
58 } // extension
59
60 void CodeGenerator::asmName( DeclarationWithType * decl ) {
61 if ( ConstantExpr * asmName = dynamic_cast<ConstantExpr *>(decl->get_asmName()) ) {
62 output << " asm ( " << asmName->get_constant()->get_value() << " )";
63 } // if
64 } // extension
65
66 CodeGenerator::LabelPrinter & CodeGenerator::LabelPrinter::operator()( std::list< Label > & l ) {
67 labels = &l;
68 return *this;
69 }
70
71 ostream & operator<<( ostream & output, CodeGenerator::LabelPrinter & printLabels ) {
72 std::list< Label > & labs = *printLabels.labels;
73 // l.unique(); // assumes a sorted list. Why not use set? Does order matter?
74 for ( Label & l : labs ) {
75 output << l.get_name() + ": ";
76 printLabels.cg.genAttributes( l.get_attributes() );
77 } // for
78 return output;
79 }
80
81 /* Using updateLocation at the beginning of a node and nextLine
82 * within a node should become the method of formating.
83 */
84 void CodeGenerator::updateLocation( CodeLocation const & to ) {
85 if ( !lineMarks ) {
86 return;
87 } else if ( currentLocation.followedBy( to, 0 ) ) {
88 return;
89 } else if ( currentLocation.followedBy( to, 1 ) ) {
90 output << "\n" << indent;
91 currentLocation.linenumber += 1;
92 } else if ( currentLocation.followedBy( to, 2 ) ) {
93 output << "\n\n" << indent;
94 currentLocation.linenumber += 2;
95 } else {
96 output << "\n# " << to.linenumber << " \"" << to.filename
97 << "\"\n" << indent;
98 currentLocation = to;
99 }
100 output << std::flush;
101 }
102
103 void CodeGenerator::updateLocation( BaseSyntaxNode const * to ) {
104 updateLocation( to->location );
105 }
106
107 void CodeGenerator::nextLine() {
108 if ( !lineMarks ) {
109 output << "\n" << indent << std::flush;
110 }
111 }
112
113 CodeGenerator::CodeGenerator( std::ostream & os, bool pretty, bool genC, bool lineMarks ) : indent( CodeGenerator::tabsize ), insideFunction( false ), output( os ), printLabels( *this ), pretty( pretty ), genC( genC ), lineMarks( lineMarks ) {}
114
115 string CodeGenerator::mangleName( DeclarationWithType * decl ) {
116 if ( pretty ) return decl->get_name();
117 if ( decl->get_mangleName() != "" ) {
118 // need to incorporate scope level in order to differentiate names for destructors
119 return decl->get_scopedMangleName();
120 } else {
121 return decl->get_name();
122 } // if
123 }
124
125 void CodeGenerator::genAttributes( list< Attribute * > & attributes ) {
126 if ( attributes.empty() ) return;
127 output << "__attribute__ ((";
128 for ( list< Attribute * >::iterator attr( attributes.begin() );; ) {
129 output << (*attr)->get_name();
130 if ( ! (*attr)->get_parameters().empty() ) {
131 output << "(";
132 genCommaList( (*attr)->get_parameters().begin(), (*attr)->get_parameters().end() );
133 output << ")";
134 } // if
135 if ( ++attr == attributes.end() ) break;
136 output << ","; // separator
137 } // for
138 output << ")) ";
139 } // CodeGenerator::genAttributes
140
141 // *** BaseSyntaxNode
142 void CodeGenerator::previsit( BaseSyntaxNode * ) {
143 // turn off automatic recursion for all nodes, to allow each visitor to
144 // precisely control the order in which its children are visited.
145 visit_children = false;
146 }
147
148 // *** BaseSyntaxNode
149 void CodeGenerator::postvisit( BaseSyntaxNode * node ) {
150 std::stringstream ss;
151 node->print( ss );
152 assertf( false, "Unhandled node reached in CodeGenerator: %s", ss.str().c_str() );
153 }
154
155 // *** Declarations
156 void CodeGenerator::postvisit( FunctionDecl * functionDecl ) {
157 extension( functionDecl );
158 genAttributes( functionDecl->get_attributes() );
159
160 handleStorageClass( functionDecl );
161 functionDecl->get_funcSpec().print( output );
162
163 output << genType( functionDecl->get_functionType(), mangleName( functionDecl ), pretty, genC );
164
165 asmName( functionDecl );
166
167 // acceptAll( functionDecl->get_oldDecls(), *visitor );
168 if ( functionDecl->get_statements() ) {
169 functionDecl->get_statements()->accept( *visitor );
170 } // if
171 }
172
173 void CodeGenerator::postvisit( ObjectDecl * objectDecl ) {
174 if (objectDecl->get_name().empty() && genC ) {
175 // only generate an anonymous name when generating C code, otherwise it clutters the output too much
176 static UniqueName name = { "__anonymous_object" };
177 objectDecl->set_name( name.newName() );
178 }
179
180 extension( objectDecl );
181 genAttributes( objectDecl->get_attributes() );
182
183 handleStorageClass( objectDecl );
184 output << genType( objectDecl->get_type(), mangleName( objectDecl ), pretty, genC );
185
186 asmName( objectDecl );
187
188 if ( objectDecl->get_init() ) {
189 output << " = ";
190 objectDecl->get_init()->accept( *visitor );
191 } // if
192
193 if ( objectDecl->get_bitfieldWidth() ) {
194 output << ":";
195 objectDecl->get_bitfieldWidth()->accept( *visitor );
196 } // if
197 }
198
199 void CodeGenerator::handleAggregate( AggregateDecl * aggDecl, const std::string & kind ) {
200 genAttributes( aggDecl->get_attributes() );
201
202 if( ! aggDecl->get_parameters().empty() && ! genC ) {
203 // assertf( ! genC, "Aggregate type parameters should not reach code generation." );
204 output << "forall(";
205 genCommaList( aggDecl->get_parameters().begin(), aggDecl->get_parameters().end() );
206 output << ")" << endl;
207 output << indent;
208 }
209
210 output << kind << aggDecl->get_name();
211
212 if ( aggDecl->has_body() ) {
213 std::list< Declaration * > & memb = aggDecl->get_members();
214 output << " {" << endl;
215
216 ++indent;
217 for ( std::list< Declaration* >::iterator i = memb.begin(); i != memb.end(); i++ ) {
218 updateLocation( *i );
219 output << indent;
220 (*i)->accept( *visitor );
221 output << ";" << endl;
222 } // for
223
224 --indent;
225
226 output << indent << "}";
227 } // if
228 }
229
230 void CodeGenerator::postvisit( StructDecl * structDecl ) {
231 extension( structDecl );
232 handleAggregate( structDecl, "struct " );
233 }
234
235 void CodeGenerator::postvisit( UnionDecl * unionDecl ) {
236 extension( unionDecl );
237 handleAggregate( unionDecl, "union " );
238 }
239
240 void CodeGenerator::postvisit( EnumDecl * enumDecl ) {
241 extension( enumDecl );
242 updateLocation( enumDecl );
243 output << "enum ";
244 genAttributes( enumDecl->get_attributes() );
245
246 output << enumDecl->get_name();
247
248 std::list< Declaration* > &memb = enumDecl->get_members();
249
250 if ( ! memb.empty() ) {
251 output << " {" << endl;
252
253 ++indent;
254 for ( std::list< Declaration* >::iterator i = memb.begin(); i != memb.end(); i++) {
255 ObjectDecl * obj = dynamic_cast< ObjectDecl* >( *i );
256 assert( obj );
257 updateLocation( obj );
258 output << indent << mangleName( obj );
259 if ( obj->get_init() ) {
260 output << " = ";
261 obj->get_init()->accept( *visitor );
262 } // if
263 output << "," << endl;
264 } // for
265
266 --indent;
267
268 output << indent << "}";
269 } // if
270 }
271
272 void CodeGenerator::postvisit( TraitDecl * traitDecl ) {
273 assertf( ! genC, "TraitDecls should not reach code generation." );
274 extension( traitDecl );
275 handleAggregate( traitDecl, "trait " );
276 }
277
278 void CodeGenerator::postvisit( TypedefDecl * typeDecl ) {
279 assertf( ! genC, "Typedefs are removed and substituted in earlier passes." );
280 updateLocation( typeDecl );
281 output << "typedef ";
282 output << genType( typeDecl->get_base(), typeDecl->get_name(), pretty, genC ) << endl;
283 }
284
285 void CodeGenerator::postvisit( TypeDecl * typeDecl ) {
286 assertf( ! genC, "TypeDecls should not reach code generation." );
287 output << typeDecl->genTypeString() << " " << typeDecl->get_name();
288 if ( typeDecl->get_kind() != TypeDecl::Any && typeDecl->get_sized() ) {
289 output << " | sized(" << typeDecl->get_name() << ")";
290 }
291 if ( ! typeDecl->get_assertions().empty() ) {
292 output << " | { ";
293 genCommaList( typeDecl->get_assertions().begin(), typeDecl->get_assertions().end() );
294 output << " }";
295 }
296 }
297
298 void CodeGenerator::postvisit( Designation * designation ) {
299 std::list< Expression * > designators = designation->get_designators();
300 if ( designators.size() == 0 ) return;
301 for ( Expression * des : designators ) {
302 if ( dynamic_cast< NameExpr * >( des ) || dynamic_cast< VariableExpr * >( des ) ) {
303 // if expression is a NameExpr or VariableExpr, then initializing aggregate member
304 output << ".";
305 des->accept( *visitor );
306 } else {
307 // otherwise, it has to be a ConstantExpr or CastExpr, initializing array eleemnt
308 output << "[";
309 des->accept( *visitor );
310 output << "]";
311 } // if
312 } // for
313 output << " = ";
314 }
315
316 void CodeGenerator::postvisit( SingleInit * init ) {
317 init->get_value()->accept( *visitor );
318 }
319
320 void CodeGenerator::postvisit( ListInit * init ) {
321 auto initBegin = init->begin();
322 auto initEnd = init->end();
323 auto desigBegin = init->get_designations().begin();
324 auto desigEnd = init->get_designations().end();
325
326 output << "{ ";
327 for ( ; initBegin != initEnd && desigBegin != desigEnd; ) {
328 (*desigBegin)->accept( *visitor );
329 (*initBegin)->accept( *visitor );
330 ++initBegin, ++desigBegin;
331 if ( initBegin != initEnd ) {
332 output << ", ";
333 }
334 }
335 output << " }";
336 assertf( initBegin == initEnd && desigBegin == desigEnd, "Initializers and designators not the same length. %s", toString( init ).c_str() );
337 }
338
339 void CodeGenerator::postvisit( __attribute__((unused)) ConstructorInit * init ){
340 assertf( ! genC, "ConstructorInit nodes should not reach code generation." );
341 // pseudo-output for constructor/destructor pairs
342 output << "<ctorinit>{" << std::endl << ++indent << "ctor: ";
343 maybeAccept( init->get_ctor(), *visitor );
344 output << ", " << std::endl << indent << "dtor: ";
345 maybeAccept( init->get_dtor(), *visitor );
346 output << std::endl << --indent << "}";
347 }
348
349 void CodeGenerator::postvisit( Constant * constant ) {
350 output << constant->get_value() ;
351 }
352
353 // *** Expressions
354 void CodeGenerator::postvisit( ApplicationExpr * applicationExpr ) {
355 extension( applicationExpr );
356 if ( VariableExpr * varExpr = dynamic_cast< VariableExpr* >( applicationExpr->get_function() ) ) {
357 OperatorInfo opInfo;
358 if ( varExpr->get_var()->get_linkage() == LinkageSpec::Intrinsic && operatorLookup( varExpr->get_var()->get_name(), opInfo ) ) {
359 std::list< Expression* >::iterator arg = applicationExpr->get_args().begin();
360 switch ( opInfo.type ) {
361 case OT_INDEX:
362 assert( applicationExpr->get_args().size() == 2 );
363 (*arg++)->accept( *visitor );
364 output << "[";
365 (*arg)->accept( *visitor );
366 output << "]";
367 break;
368
369 case OT_CALL:
370 // there are no intrinsic definitions of the function call operator
371 assert( false );
372 break;
373
374 case OT_CTOR:
375 case OT_DTOR:
376 if ( applicationExpr->get_args().size() == 1 ) {
377 // the expression fed into a single parameter constructor or destructor may contain side
378 // effects, so must still output this expression
379 output << "(";
380 (*arg++)->accept( *visitor );
381 output << ") /* " << opInfo.inputName << " */";
382 } else if ( applicationExpr->get_args().size() == 2 ) {
383 // intrinsic two parameter constructors are essentially bitwise assignment
384 output << "(";
385 (*arg++)->accept( *visitor );
386 output << opInfo.symbol;
387 (*arg)->accept( *visitor );
388 output << ") /* " << opInfo.inputName << " */";
389 } else {
390 // no constructors with 0 or more than 2 parameters
391 assert( false );
392 } // if
393 break;
394
395 case OT_PREFIX:
396 case OT_PREFIXASSIGN:
397 assert( applicationExpr->get_args().size() == 1 );
398 output << "(";
399 output << opInfo.symbol;
400 (*arg)->accept( *visitor );
401 output << ")";
402 break;
403
404 case OT_POSTFIX:
405 case OT_POSTFIXASSIGN:
406 assert( applicationExpr->get_args().size() == 1 );
407 (*arg)->accept( *visitor );
408 output << opInfo.symbol;
409 break;
410
411
412 case OT_INFIX:
413 case OT_INFIXASSIGN:
414 assert( applicationExpr->get_args().size() == 2 );
415 output << "(";
416 (*arg++)->accept( *visitor );
417 output << opInfo.symbol;
418 (*arg)->accept( *visitor );
419 output << ")";
420 break;
421
422 case OT_CONSTANT:
423 case OT_LABELADDRESS:
424 // there are no intrinsic definitions of 0/1 or label addresses as functions
425 assert( false );
426 } // switch
427 } else {
428 varExpr->accept( *visitor );
429 output << "(";
430 genCommaList( applicationExpr->get_args().begin(), applicationExpr->get_args().end() );
431 output << ")";
432 } // if
433 } else {
434 applicationExpr->get_function()->accept( *visitor );
435 output << "(";
436 genCommaList( applicationExpr->get_args().begin(), applicationExpr->get_args().end() );
437 output << ")";
438 } // if
439 }
440
441 void CodeGenerator::postvisit( UntypedExpr * untypedExpr ) {
442 extension( untypedExpr );
443 if ( NameExpr * nameExpr = dynamic_cast< NameExpr* >( untypedExpr->get_function() ) ) {
444 OperatorInfo opInfo;
445 if ( operatorLookup( nameExpr->get_name(), opInfo ) ) {
446 std::list< Expression* >::iterator arg = untypedExpr->get_args().begin();
447 switch ( opInfo.type ) {
448 case OT_INDEX:
449 assert( untypedExpr->get_args().size() == 2 );
450 (*arg++)->accept( *visitor );
451 output << "[";
452 (*arg)->accept( *visitor );
453 output << "]";
454 break;
455
456 case OT_CALL:
457 assert( false );
458
459 case OT_CTOR:
460 case OT_DTOR:
461 if ( untypedExpr->get_args().size() == 1 ) {
462 // the expression fed into a single parameter constructor or destructor may contain side
463 // effects, so must still output this expression
464 output << "(";
465 (*arg++)->accept( *visitor );
466 output << ") /* " << opInfo.inputName << " */";
467 } else if ( untypedExpr->get_args().size() == 2 ) {
468 // intrinsic two parameter constructors are essentially bitwise assignment
469 output << "(";
470 (*arg++)->accept( *visitor );
471 output << opInfo.symbol;
472 (*arg)->accept( *visitor );
473 output << ") /* " << opInfo.inputName << " */";
474 } else {
475 // no constructors with 0 or more than 2 parameters
476 assertf( ! genC, "UntypedExpr constructor/destructor with 0 or more than 2 parameters." );
477 output << "(";
478 (*arg++)->accept( *visitor );
479 output << opInfo.symbol << "{ ";
480 genCommaList( arg, untypedExpr->get_args().end() );
481 output << "}) /* " << opInfo.inputName << " */";
482 } // if
483 break;
484
485 case OT_PREFIX:
486 case OT_PREFIXASSIGN:
487 case OT_LABELADDRESS:
488 assert( untypedExpr->get_args().size() == 1 );
489 output << "(";
490 output << opInfo.symbol;
491 (*arg)->accept( *visitor );
492 output << ")";
493 break;
494
495 case OT_POSTFIX:
496 case OT_POSTFIXASSIGN:
497 assert( untypedExpr->get_args().size() == 1 );
498 (*arg)->accept( *visitor );
499 output << opInfo.symbol;
500 break;
501
502 case OT_INFIX:
503 case OT_INFIXASSIGN:
504 assert( untypedExpr->get_args().size() == 2 );
505 output << "(";
506 (*arg++)->accept( *visitor );
507 output << opInfo.symbol;
508 (*arg)->accept( *visitor );
509 output << ")";
510 break;
511
512 case OT_CONSTANT:
513 // there are no intrinsic definitions of 0 or 1 as functions
514 assert( false );
515 } // switch
516 } else {
517 if ( nameExpr->get_name() == "..." ) { // case V1 ... V2 or case V1~V2
518 assert( untypedExpr->get_args().size() == 2 );
519 (*untypedExpr->get_args().begin())->accept( *visitor );
520 output << " ... ";
521 (*--untypedExpr->get_args().end())->accept( *visitor );
522 } else { // builtin routines
523 nameExpr->accept( *visitor );
524 output << "(";
525 genCommaList( untypedExpr->get_args().begin(), untypedExpr->get_args().end() );
526 output << ")";
527 } // if
528 } // if
529 } else {
530 untypedExpr->get_function()->accept( *visitor );
531 output << "(";
532 genCommaList( untypedExpr->get_args().begin(), untypedExpr->get_args().end() );
533 output << ")";
534 } // if
535 }
536
537 void CodeGenerator::postvisit( RangeExpr * rangeExpr ) {
538 rangeExpr->get_low()->accept( *visitor );
539 output << " ... ";
540 rangeExpr->get_high()->accept( *visitor );
541 }
542
543 void CodeGenerator::postvisit( NameExpr * nameExpr ) {
544 extension( nameExpr );
545 OperatorInfo opInfo;
546 if ( operatorLookup( nameExpr->get_name(), opInfo ) ) {
547 assert( opInfo.type == OT_CONSTANT );
548 output << opInfo.symbol;
549 } else {
550 output << nameExpr->get_name();
551 } // if
552 }
553
554 void CodeGenerator::postvisit( AddressExpr * addressExpr ) {
555 extension( addressExpr );
556 output << "(&";
557 addressExpr->arg->accept( *visitor );
558 output << ")";
559 }
560
561 void CodeGenerator::postvisit( LabelAddressExpr *addressExpr ) {
562 extension( addressExpr );
563 output << "(&&" << addressExpr->arg << ")";
564 }
565
566 void CodeGenerator::postvisit( CastExpr * castExpr ) {
567 extension( castExpr );
568 output << "(";
569 if ( castExpr->get_result()->isVoid() ) {
570 output << "(void)" ;
571 } else {
572 // at least one result type of cast.
573 // Note: previously, lvalue casts were skipped. Since it's now impossible for the user to write
574 // an lvalue cast, this has been taken out.
575 output << "(";
576 output << genType( castExpr->get_result(), "", pretty, genC );
577 output << ")";
578 } // if
579 castExpr->get_arg()->accept( *visitor );
580 output << ")";
581 }
582
583 void CodeGenerator::postvisit( VirtualCastExpr * castExpr ) {
584 assertf( ! genC, "VirtualCastExpr should not reach code generation." );
585 extension( castExpr );
586 output << "(virtual ";
587 castExpr->get_arg()->accept( *visitor );
588 output << ")";
589 }
590
591 void CodeGenerator::postvisit( UntypedMemberExpr * memberExpr ) {
592 assertf( ! genC, "UntypedMemberExpr should not reach code generation." );
593 extension( memberExpr );
594 memberExpr->get_aggregate()->accept( *visitor );
595 output << ".";
596 memberExpr->get_member()->accept( *visitor );
597 }
598
599 void CodeGenerator::postvisit( MemberExpr * memberExpr ) {
600 extension( memberExpr );
601 memberExpr->get_aggregate()->accept( *visitor );
602 output << "." << mangleName( memberExpr->get_member() );
603 }
604
605 void CodeGenerator::postvisit( VariableExpr * variableExpr ) {
606 extension( variableExpr );
607 OperatorInfo opInfo;
608 if ( variableExpr->get_var()->get_linkage() == LinkageSpec::Intrinsic && operatorLookup( variableExpr->get_var()->get_name(), opInfo ) && opInfo.type == OT_CONSTANT ) {
609 output << opInfo.symbol;
610 } else {
611 output << mangleName( variableExpr->get_var() );
612 } // if
613 }
614
615 void CodeGenerator::postvisit( ConstantExpr * constantExpr ) {
616 assert( constantExpr->get_constant() );
617 extension( constantExpr );
618 constantExpr->get_constant()->accept( *visitor );
619 }
620
621 void CodeGenerator::postvisit( SizeofExpr * sizeofExpr ) {
622 extension( sizeofExpr );
623 output << "sizeof(";
624 if ( sizeofExpr->get_isType() ) {
625 output << genType( sizeofExpr->get_type(), "", pretty, genC );
626 } else {
627 sizeofExpr->get_expr()->accept( *visitor );
628 } // if
629 output << ")";
630 }
631
632 void CodeGenerator::postvisit( AlignofExpr * alignofExpr ) {
633 // use GCC extension to avoid bumping std to C11
634 extension( alignofExpr );
635 output << "__alignof__(";
636 if ( alignofExpr->get_isType() ) {
637 output << genType( alignofExpr->get_type(), "", pretty, genC );
638 } else {
639 alignofExpr->get_expr()->accept( *visitor );
640 } // if
641 output << ")";
642 }
643
644 void CodeGenerator::postvisit( UntypedOffsetofExpr * offsetofExpr ) {
645 assertf( ! genC, "UntypedOffsetofExpr should not reach code generation." );
646 output << "offsetof(";
647 output << genType( offsetofExpr->get_type(), "", pretty, genC );
648 output << ", " << offsetofExpr->get_member();
649 output << ")";
650 }
651
652 void CodeGenerator::postvisit( OffsetofExpr * offsetofExpr ) {
653 // use GCC builtin
654 output << "__builtin_offsetof(";
655 output << genType( offsetofExpr->get_type(), "", pretty, genC );
656 output << ", " << mangleName( offsetofExpr->get_member() );
657 output << ")";
658 }
659
660 void CodeGenerator::postvisit( OffsetPackExpr * offsetPackExpr ) {
661 assertf( ! genC, "OffsetPackExpr should not reach code generation." );
662 output << "__CFA_offsetpack(" << genType( offsetPackExpr->get_type(), "", pretty, genC ) << ")";
663 }
664
665 void CodeGenerator::postvisit( LogicalExpr * logicalExpr ) {
666 extension( logicalExpr );
667 output << "(";
668 logicalExpr->get_arg1()->accept( *visitor );
669 if ( logicalExpr->get_isAnd() ) {
670 output << " && ";
671 } else {
672 output << " || ";
673 } // if
674 logicalExpr->get_arg2()->accept( *visitor );
675 output << ")";
676 }
677
678 void CodeGenerator::postvisit( ConditionalExpr * conditionalExpr ) {
679 extension( conditionalExpr );
680 output << "(";
681 conditionalExpr->get_arg1()->accept( *visitor );
682 output << " ? ";
683 conditionalExpr->get_arg2()->accept( *visitor );
684 output << " : ";
685 conditionalExpr->get_arg3()->accept( *visitor );
686 output << ")";
687 }
688
689 void CodeGenerator::postvisit( CommaExpr * commaExpr ) {
690 extension( commaExpr );
691 output << "(";
692 if ( genC ) {
693 // arg1 of a CommaExpr is never used, so it can be safely cast to void to reduce gcc warnings.
694 commaExpr->set_arg1( new CastExpr( commaExpr->get_arg1() ) );
695 }
696 commaExpr->get_arg1()->accept( *visitor );
697 output << " , ";
698 commaExpr->get_arg2()->accept( *visitor );
699 output << ")";
700 }
701
702 void CodeGenerator::postvisit( TupleAssignExpr * tupleExpr ) {
703 assertf( ! genC, "TupleAssignExpr should not reach code generation." );
704 tupleExpr->stmtExpr->accept( *visitor );
705 }
706
707 void CodeGenerator::postvisit( UntypedTupleExpr * tupleExpr ) {
708 assertf( ! genC, "UntypedTupleExpr should not reach code generation." );
709 extension( tupleExpr );
710 output << "[";
711 genCommaList( tupleExpr->get_exprs().begin(), tupleExpr->get_exprs().end() );
712 output << "]";
713 }
714
715 void CodeGenerator::postvisit( TupleExpr * tupleExpr ) {
716 assertf( ! genC, "TupleExpr should not reach code generation." );
717 extension( tupleExpr );
718 output << "[";
719 genCommaList( tupleExpr->get_exprs().begin(), tupleExpr->get_exprs().end() );
720 output << "]";
721 }
722
723 void CodeGenerator::postvisit( TupleIndexExpr * tupleExpr ) {
724 assertf( ! genC, "TupleIndexExpr should not reach code generation." );
725 extension( tupleExpr );
726 tupleExpr->get_tuple()->accept( *visitor );
727 output << "." << tupleExpr->get_index();
728 }
729
730 void CodeGenerator::postvisit( TypeExpr * typeExpr ) {
731 // if ( genC ) std::cerr << "typeexpr still exists: " << typeExpr << std::endl;
732 // assertf( ! genC, "TypeExpr should not reach code generation." );
733 if ( ! genC ) {
734 output<< genType( typeExpr->get_type(), "", pretty, genC );
735 }
736 }
737
738 void CodeGenerator::postvisit( AsmExpr * asmExpr ) {
739 if ( asmExpr->get_inout() ) {
740 output << "[ ";
741 asmExpr->get_inout()->accept( *visitor );
742 output << " ] ";
743 } // if
744 asmExpr->get_constraint()->accept( *visitor );
745 output << " ( ";
746 asmExpr->get_operand()->accept( *visitor );
747 output << " )";
748 }
749
750 void CodeGenerator::postvisit( CompoundLiteralExpr *compLitExpr ) {
751 assert( compLitExpr->get_result() && dynamic_cast< ListInit * > ( compLitExpr->get_initializer() ) );
752 output << "(" << genType( compLitExpr->get_result(), "", pretty, genC ) << ")";
753 compLitExpr->get_initializer()->accept( *visitor );
754 }
755
756 void CodeGenerator::postvisit( UniqueExpr * unqExpr ) {
757 assertf( ! genC, "Unique expressions should not reach code generation." );
758 output << "unq<" << unqExpr->get_id() << ">{ ";
759 unqExpr->get_expr()->accept( *visitor );
760 output << " }";
761 }
762
763 void CodeGenerator::postvisit( StmtExpr * stmtExpr ) {
764 std::list< Statement * > & stmts = stmtExpr->get_statements()->get_kids();
765 updateLocation( stmtExpr );
766 output << "({" << std::endl;
767 ++indent;
768 unsigned int numStmts = stmts.size();
769 unsigned int i = 0;
770 for ( Statement * stmt : stmts ) {
771 updateLocation( stmt );
772 output << indent << printLabels( stmt->get_labels() );
773 if ( i+1 == numStmts ) {
774 // last statement in a statement expression needs to be handled specially -
775 // cannot cast to void, otherwise the expression statement has no value
776 if ( ExprStmt * exprStmt = dynamic_cast< ExprStmt * >( stmt ) ) {
777 exprStmt->get_expr()->accept( *visitor );
778 output << ";" << endl;
779 ++i;
780 break;
781 }
782 }
783 stmt->accept( *visitor );
784 output << endl;
785 if ( wantSpacing( stmt ) ) {
786 output << endl;
787 } // if
788 ++i;
789 }
790 --indent;
791 output << indent << "})";
792 }
793
794 void CodeGenerator::postvisit( ConstructorExpr * expr ) {
795 assertf( ! genC, "Unique expressions should not reach code generation." );
796 expr->callExpr->accept( *visitor );
797 }
798
799 // *** Statements
800 void CodeGenerator::postvisit( CompoundStmt * compoundStmt ) {
801 std::list<Statement*> ks = compoundStmt->get_kids();
802 output << "{" << endl;
803
804 ++indent;
805
806 for ( std::list<Statement *>::iterator i = ks.begin(); i != ks.end(); i++ ) {
807 output << indent << printLabels( (*i)->get_labels() );
808 (*i)->accept( *visitor );
809
810 output << endl;
811 if ( wantSpacing( *i ) ) {
812 output << endl;
813 } // if
814 } // for
815 --indent;
816
817 output << indent << "}";
818 }
819
820 void CodeGenerator::postvisit( ExprStmt * exprStmt ) {
821 assert( exprStmt );
822 if ( genC ) {
823 // cast the top-level expression to void to reduce gcc warnings.
824 exprStmt->set_expr( new CastExpr( exprStmt->get_expr() ) );
825 }
826 exprStmt->get_expr()->accept( *visitor );
827 output << ";";
828 }
829
830 void CodeGenerator::postvisit( AsmStmt * asmStmt ) {
831 output << "asm ";
832 if ( asmStmt->get_voltile() ) output << "volatile ";
833 if ( ! asmStmt->get_gotolabels().empty() ) output << "goto ";
834 output << "( ";
835 if ( asmStmt->get_instruction() ) asmStmt->get_instruction()->accept( *visitor );
836 output << " : ";
837 genCommaList( asmStmt->get_output().begin(), asmStmt->get_output().end() );
838 output << " : ";
839 genCommaList( asmStmt->get_input().begin(), asmStmt->get_input().end() );
840 output << " : ";
841 genCommaList( asmStmt->get_clobber().begin(), asmStmt->get_clobber().end() );
842 if ( ! asmStmt->get_gotolabels().empty() ) {
843 output << " : ";
844 for ( std::list<Label>::iterator begin = asmStmt->get_gotolabels().begin();; ) {
845 output << *begin++;
846 if ( begin == asmStmt->get_gotolabels().end() ) break;
847 output << ", ";
848 } // for
849 } // if
850 output << " );" ;
851 }
852
853 void CodeGenerator::postvisit( AsmDecl * asmDecl ) {
854 output << "asm ";
855 AsmStmt * asmStmt = asmDecl->get_stmt();
856 output << "( ";
857 if ( asmStmt->get_instruction() ) asmStmt->get_instruction()->accept( *visitor );
858 output << " )" ;
859 }
860
861 void CodeGenerator::postvisit( IfStmt * ifStmt ) {
862 updateLocation( ifStmt );
863 output << "if ( ";
864 ifStmt->get_condition()->accept( *visitor );
865 output << " ) ";
866
867 ifStmt->get_thenPart()->accept( *visitor );
868
869 if ( ifStmt->get_elsePart() != 0) {
870 output << " else ";
871 ifStmt->get_elsePart()->accept( *visitor );
872 } // if
873 }
874
875 void CodeGenerator::postvisit( SwitchStmt * switchStmt ) {
876 updateLocation( switchStmt );
877 output << "switch ( " ;
878 switchStmt->get_condition()->accept( *visitor );
879 output << " ) ";
880
881 output << "{" << std::endl;
882 ++indent;
883 acceptAll( switchStmt->get_statements(), *visitor );
884 --indent;
885 output << indent << "}";
886 }
887
888 void CodeGenerator::postvisit( CaseStmt * caseStmt ) {
889 updateLocation( caseStmt );
890 if ( caseStmt->isDefault()) {
891 output << "default";
892 } else {
893 output << "case ";
894 caseStmt->get_condition()->accept( *visitor );
895 } // if
896 output << ":\n";
897
898 std::list<Statement *> sts = caseStmt->get_statements();
899
900 ++indent;
901 for ( std::list<Statement *>::iterator i = sts.begin(); i != sts.end(); i++) {
902 output << indent << printLabels( (*i)->get_labels() ) ;
903 (*i)->accept( *visitor );
904 output << endl;
905 } // for
906 --indent;
907 }
908
909 void CodeGenerator::postvisit( BranchStmt * branchStmt ) {
910 switch ( branchStmt->get_type()) {
911 case BranchStmt::Goto:
912 if ( ! branchStmt->get_target().empty() )
913 output << "goto " << branchStmt->get_target();
914 else {
915 if ( branchStmt->get_computedTarget() != 0 ) {
916 output << "goto *";
917 branchStmt->get_computedTarget()->accept( *visitor );
918 } // if
919 } // if
920 break;
921 case BranchStmt::Break:
922 output << "break";
923 break;
924 case BranchStmt::Continue:
925 output << "continue";
926 break;
927 } // switch
928 output << ";";
929 }
930
931 void CodeGenerator::postvisit( ReturnStmt * returnStmt ) {
932 output << "return ";
933 maybeAccept( returnStmt->get_expr(), *visitor );
934 output << ";";
935 }
936
937 void CodeGenerator::postvisit( ThrowStmt * throwStmt ) {
938 assertf( ! genC, "Throw statements should not reach code generation." );
939
940 output << ((throwStmt->get_kind() == ThrowStmt::Terminate) ?
941 "throw" : "throwResume");
942 if (throwStmt->get_expr()) {
943 output << " ";
944 throwStmt->get_expr()->accept( *visitor );
945 }
946 if (throwStmt->get_target()) {
947 output << " _At ";
948 throwStmt->get_target()->accept( *visitor );
949 }
950 output << ";";
951 }
952
953 void CodeGenerator::postvisit( WhileStmt * whileStmt ) {
954 if ( whileStmt->get_isDoWhile() ) {
955 output << "do" ;
956 } else {
957 output << "while (" ;
958 whileStmt->get_condition()->accept( *visitor );
959 output << ")";
960 } // if
961 output << " ";
962
963 output << CodeGenerator::printLabels( whileStmt->get_body()->get_labels() );
964 whileStmt->get_body()->accept( *visitor );
965
966 output << indent;
967
968 if ( whileStmt->get_isDoWhile() ) {
969 output << " while (" ;
970 whileStmt->get_condition()->accept( *visitor );
971 output << ");";
972 } // if
973 }
974
975 void CodeGenerator::postvisit( ForStmt * forStmt ) {
976 // initialization is always hoisted, so don't bother doing anything with that
977 output << "for (;";
978
979 if ( forStmt->get_condition() != 0 ) {
980 forStmt->get_condition()->accept( *visitor );
981 } // if
982 output << ";";
983
984 if ( forStmt->get_increment() != 0 ) {
985 // cast the top-level expression to void to reduce gcc warnings.
986 Expression * expr = new CastExpr( forStmt->get_increment() );
987 expr->accept( *visitor );
988 } // if
989 output << ") ";
990
991 if ( forStmt->get_body() != 0 ) {
992 output << CodeGenerator::printLabels( forStmt->get_body()->get_labels() );
993 forStmt->get_body()->accept( *visitor );
994 } // if
995 }
996
997 void CodeGenerator::postvisit( __attribute__((unused)) NullStmt * nullStmt ) {
998 //output << indent << CodeGenerator::printLabels( nullStmt->get_labels() );
999 output << "/* null statement */ ;";
1000 }
1001
1002 void CodeGenerator::postvisit( DeclStmt * declStmt ) {
1003 declStmt->get_decl()->accept( *visitor );
1004
1005 if ( doSemicolon( declStmt->get_decl() ) ) {
1006 output << ";";
1007 } // if
1008 }
1009
1010 void CodeGenerator::postvisit( ImplicitCtorDtorStmt * stmt ) {
1011 assertf( ! genC, "ImplicitCtorDtorStmts should not reach code generation." );
1012 stmt->callStmt->accept( *visitor );
1013 }
1014
1015 void CodeGenerator::handleStorageClass( DeclarationWithType * decl ) {
1016 if ( decl->get_storageClasses().any() ) {
1017 decl->get_storageClasses().print( output );
1018 } // if
1019 } // CodeGenerator::handleStorageClass
1020
1021 std::string genName( DeclarationWithType * decl ) {
1022 CodeGen::OperatorInfo opInfo;
1023 if ( operatorLookup( decl->get_name(), opInfo ) ) {
1024 return opInfo.outputName;
1025 } else {
1026 return decl->get_name();
1027 } // if
1028 }
1029} // namespace CodeGen
1030
1031// Local Variables: //
1032// tab-width: 4 //
1033// mode: c++ //
1034// compile-command: "make install" //
1035// End: //
Note: See TracBrowser for help on using the repository browser.