source: src/CodeGen/CodeGenerator.cc@ 9857e8d

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 9857e8d was 9857e8d, checked in by Rob Schluntz <rschlunt@…>, 8 years ago

Convert CodeGenerator to PassVisitor

  • Property mode set to 100644
File size: 31.7 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 assert( false );
477 } // if
478 break;
479
480 case OT_PREFIX:
481 case OT_PREFIXASSIGN:
482 case OT_LABELADDRESS:
483 assert( untypedExpr->get_args().size() == 1 );
484 output << "(";
485 output << opInfo.symbol;
486 (*arg)->accept( *visitor );
487 output << ")";
488 break;
489
490 case OT_POSTFIX:
491 case OT_POSTFIXASSIGN:
492 assert( untypedExpr->get_args().size() == 1 );
493 (*arg)->accept( *visitor );
494 output << opInfo.symbol;
495 break;
496
497 case OT_INFIX:
498 case OT_INFIXASSIGN:
499 assert( untypedExpr->get_args().size() == 2 );
500 output << "(";
501 (*arg++)->accept( *visitor );
502 output << opInfo.symbol;
503 (*arg)->accept( *visitor );
504 output << ")";
505 break;
506
507 case OT_CONSTANT:
508 // there are no intrinsic definitions of 0 or 1 as functions
509 assert( false );
510 } // switch
511 } else {
512 if ( nameExpr->get_name() == "..." ) { // case V1 ... V2 or case V1~V2
513 assert( untypedExpr->get_args().size() == 2 );
514 (*untypedExpr->get_args().begin())->accept( *visitor );
515 output << " ... ";
516 (*--untypedExpr->get_args().end())->accept( *visitor );
517 } else { // builtin routines
518 nameExpr->accept( *visitor );
519 output << "(";
520 genCommaList( untypedExpr->get_args().begin(), untypedExpr->get_args().end() );
521 output << ")";
522 } // if
523 } // if
524 } else {
525 untypedExpr->get_function()->accept( *visitor );
526 output << "(";
527 genCommaList( untypedExpr->get_args().begin(), untypedExpr->get_args().end() );
528 output << ")";
529 } // if
530 }
531
532 void CodeGenerator::postvisit( RangeExpr * rangeExpr ) {
533 rangeExpr->get_low()->accept( *visitor );
534 output << " ... ";
535 rangeExpr->get_high()->accept( *visitor );
536 }
537
538 void CodeGenerator::postvisit( NameExpr * nameExpr ) {
539 extension( nameExpr );
540 OperatorInfo opInfo;
541 if ( operatorLookup( nameExpr->get_name(), opInfo ) ) {
542 assert( opInfo.type == OT_CONSTANT );
543 output << opInfo.symbol;
544 } else {
545 output << nameExpr->get_name();
546 } // if
547 }
548
549 void CodeGenerator::postvisit( AddressExpr * addressExpr ) {
550 extension( addressExpr );
551 output << "(&";
552 addressExpr->arg->accept( *visitor );
553 output << ")";
554 }
555
556 void CodeGenerator::postvisit( LabelAddressExpr *addressExpr ) {
557 extension( addressExpr );
558 output << "(&&" << addressExpr->arg << ")";
559 }
560
561 void CodeGenerator::postvisit( CastExpr * castExpr ) {
562 extension( castExpr );
563 output << "(";
564 if ( castExpr->get_result()->isVoid() ) {
565 output << "(void)" ;
566 } else {
567 // at least one result type of cast.
568 // Note: previously, lvalue casts were skipped. Since it's now impossible for the user to write
569 // an lvalue cast, this has been taken out.
570 output << "(";
571 output << genType( castExpr->get_result(), "", pretty, genC );
572 output << ")";
573 } // if
574 castExpr->get_arg()->accept( *visitor );
575 output << ")";
576 }
577
578 void CodeGenerator::postvisit( VirtualCastExpr * castExpr ) {
579 assertf( ! genC, "VirtualCastExpr should not reach code generation." );
580 extension( castExpr );
581 output << "(virtual ";
582 castExpr->get_arg()->accept( *visitor );
583 output << ")";
584 }
585
586 void CodeGenerator::postvisit( UntypedMemberExpr * memberExpr ) {
587 assertf( ! genC, "UntypedMemberExpr should not reach code generation." );
588 extension( memberExpr );
589 memberExpr->get_aggregate()->accept( *visitor );
590 output << ".";
591 memberExpr->get_member()->accept( *visitor );
592 }
593
594 void CodeGenerator::postvisit( MemberExpr * memberExpr ) {
595 extension( memberExpr );
596 memberExpr->get_aggregate()->accept( *visitor );
597 output << "." << mangleName( memberExpr->get_member() );
598 }
599
600 void CodeGenerator::postvisit( VariableExpr * variableExpr ) {
601 extension( variableExpr );
602 OperatorInfo opInfo;
603 if ( variableExpr->get_var()->get_linkage() == LinkageSpec::Intrinsic && operatorLookup( variableExpr->get_var()->get_name(), opInfo ) && opInfo.type == OT_CONSTANT ) {
604 output << opInfo.symbol;
605 } else {
606 output << mangleName( variableExpr->get_var() );
607 } // if
608 }
609
610 void CodeGenerator::postvisit( ConstantExpr * constantExpr ) {
611 assert( constantExpr->get_constant() );
612 extension( constantExpr );
613 constantExpr->get_constant()->accept( *visitor );
614 }
615
616 void CodeGenerator::postvisit( SizeofExpr * sizeofExpr ) {
617 extension( sizeofExpr );
618 output << "sizeof(";
619 if ( sizeofExpr->get_isType() ) {
620 output << genType( sizeofExpr->get_type(), "", pretty, genC );
621 } else {
622 sizeofExpr->get_expr()->accept( *visitor );
623 } // if
624 output << ")";
625 }
626
627 void CodeGenerator::postvisit( AlignofExpr * alignofExpr ) {
628 // use GCC extension to avoid bumping std to C11
629 extension( alignofExpr );
630 output << "__alignof__(";
631 if ( alignofExpr->get_isType() ) {
632 output << genType( alignofExpr->get_type(), "", pretty, genC );
633 } else {
634 alignofExpr->get_expr()->accept( *visitor );
635 } // if
636 output << ")";
637 }
638
639 void CodeGenerator::postvisit( UntypedOffsetofExpr * offsetofExpr ) {
640 assertf( ! genC, "UntypedOffsetofExpr should not reach code generation." );
641 output << "offsetof(";
642 output << genType( offsetofExpr->get_type(), "", pretty, genC );
643 output << ", " << offsetofExpr->get_member();
644 output << ")";
645 }
646
647 void CodeGenerator::postvisit( OffsetofExpr * offsetofExpr ) {
648 // use GCC builtin
649 output << "__builtin_offsetof(";
650 output << genType( offsetofExpr->get_type(), "", pretty, genC );
651 output << ", " << mangleName( offsetofExpr->get_member() );
652 output << ")";
653 }
654
655 void CodeGenerator::postvisit( OffsetPackExpr * offsetPackExpr ) {
656 assertf( ! genC, "OffsetPackExpr should not reach code generation." );
657 output << "__CFA_offsetpack(" << genType( offsetPackExpr->get_type(), "", pretty, genC ) << ")";
658 }
659
660 void CodeGenerator::postvisit( LogicalExpr * logicalExpr ) {
661 extension( logicalExpr );
662 output << "(";
663 logicalExpr->get_arg1()->accept( *visitor );
664 if ( logicalExpr->get_isAnd() ) {
665 output << " && ";
666 } else {
667 output << " || ";
668 } // if
669 logicalExpr->get_arg2()->accept( *visitor );
670 output << ")";
671 }
672
673 void CodeGenerator::postvisit( ConditionalExpr * conditionalExpr ) {
674 extension( conditionalExpr );
675 output << "(";
676 conditionalExpr->get_arg1()->accept( *visitor );
677 output << " ? ";
678 conditionalExpr->get_arg2()->accept( *visitor );
679 output << " : ";
680 conditionalExpr->get_arg3()->accept( *visitor );
681 output << ")";
682 }
683
684 void CodeGenerator::postvisit( CommaExpr * commaExpr ) {
685 extension( commaExpr );
686 output << "(";
687 if ( genC ) {
688 // arg1 of a CommaExpr is never used, so it can be safely cast to void to reduce gcc warnings.
689 commaExpr->set_arg1( new CastExpr( commaExpr->get_arg1() ) );
690 }
691 commaExpr->get_arg1()->accept( *visitor );
692 output << " , ";
693 commaExpr->get_arg2()->accept( *visitor );
694 output << ")";
695 }
696
697 void CodeGenerator::postvisit( TupleAssignExpr * tupleExpr ) {
698 assertf( ! genC, "TupleAssignExpr should not reach code generation." );
699 tupleExpr->stmtExpr->accept( *visitor );
700 }
701
702 void CodeGenerator::postvisit( UntypedTupleExpr * tupleExpr ) {
703 assertf( ! genC, "UntypedTupleExpr should not reach code generation." );
704 extension( tupleExpr );
705 output << "[";
706 genCommaList( tupleExpr->get_exprs().begin(), tupleExpr->get_exprs().end() );
707 output << "]";
708 }
709
710 void CodeGenerator::postvisit( TupleExpr * tupleExpr ) {
711 assertf( ! genC, "TupleExpr should not reach code generation." );
712 extension( tupleExpr );
713 output << "[";
714 genCommaList( tupleExpr->get_exprs().begin(), tupleExpr->get_exprs().end() );
715 output << "]";
716 }
717
718 void CodeGenerator::postvisit( TupleIndexExpr * tupleExpr ) {
719 assertf( ! genC, "TupleIndexExpr should not reach code generation." );
720 extension( tupleExpr );
721 tupleExpr->get_tuple()->accept( *visitor );
722 output << "." << tupleExpr->get_index();
723 }
724
725 void CodeGenerator::postvisit( TypeExpr * typeExpr ) {
726 // if ( genC ) std::cerr << "typeexpr still exists: " << typeExpr << std::endl;
727 // assertf( ! genC, "TypeExpr should not reach code generation." );
728 if ( ! genC ) {
729 output<< genType( typeExpr->get_type(), "", pretty, genC );
730 }
731 }
732
733 void CodeGenerator::postvisit( AsmExpr * asmExpr ) {
734 if ( asmExpr->get_inout() ) {
735 output << "[ ";
736 asmExpr->get_inout()->accept( *visitor );
737 output << " ] ";
738 } // if
739 asmExpr->get_constraint()->accept( *visitor );
740 output << " ( ";
741 asmExpr->get_operand()->accept( *visitor );
742 output << " )";
743 }
744
745 void CodeGenerator::postvisit( CompoundLiteralExpr *compLitExpr ) {
746 assert( compLitExpr->get_result() && dynamic_cast< ListInit * > ( compLitExpr->get_initializer() ) );
747 output << "(" << genType( compLitExpr->get_result(), "", pretty, genC ) << ")";
748 compLitExpr->get_initializer()->accept( *visitor );
749 }
750
751 void CodeGenerator::postvisit( UniqueExpr * unqExpr ) {
752 assertf( ! genC, "Unique expressions should not reach code generation." );
753 output << "unq<" << unqExpr->get_id() << ">{ ";
754 unqExpr->get_expr()->accept( *visitor );
755 output << " }";
756 }
757
758 void CodeGenerator::postvisit( StmtExpr * stmtExpr ) {
759 std::list< Statement * > & stmts = stmtExpr->get_statements()->get_kids();
760 updateLocation( stmtExpr );
761 output << "({" << std::endl;
762 ++indent;
763 unsigned int numStmts = stmts.size();
764 unsigned int i = 0;
765 for ( Statement * stmt : stmts ) {
766 updateLocation( stmt );
767 output << indent << printLabels( stmt->get_labels() );
768 if ( i+1 == numStmts ) {
769 // last statement in a statement expression needs to be handled specially -
770 // cannot cast to void, otherwise the expression statement has no value
771 if ( ExprStmt * exprStmt = dynamic_cast< ExprStmt * >( stmt ) ) {
772 exprStmt->get_expr()->accept( *visitor );
773 output << ";" << endl;
774 ++i;
775 break;
776 }
777 }
778 stmt->accept( *visitor );
779 output << endl;
780 if ( wantSpacing( stmt ) ) {
781 output << endl;
782 } // if
783 ++i;
784 }
785 --indent;
786 output << indent << "})";
787 }
788
789 // *** Statements
790 void CodeGenerator::postvisit( CompoundStmt * compoundStmt ) {
791 std::list<Statement*> ks = compoundStmt->get_kids();
792 output << "{" << endl;
793
794 ++indent;
795
796 for ( std::list<Statement *>::iterator i = ks.begin(); i != ks.end(); i++ ) {
797 output << indent << printLabels( (*i)->get_labels() );
798 (*i)->accept( *visitor );
799
800 output << endl;
801 if ( wantSpacing( *i ) ) {
802 output << endl;
803 } // if
804 } // for
805 --indent;
806
807 output << indent << "}";
808 }
809
810 void CodeGenerator::postvisit( ExprStmt * exprStmt ) {
811 assert( exprStmt );
812 if ( genC ) {
813 // cast the top-level expression to void to reduce gcc warnings.
814 exprStmt->set_expr( new CastExpr( exprStmt->get_expr() ) );
815 }
816 exprStmt->get_expr()->accept( *visitor );
817 output << ";";
818 }
819
820 void CodeGenerator::postvisit( AsmStmt * asmStmt ) {
821 output << "asm ";
822 if ( asmStmt->get_voltile() ) output << "volatile ";
823 if ( ! asmStmt->get_gotolabels().empty() ) output << "goto ";
824 output << "( ";
825 if ( asmStmt->get_instruction() ) asmStmt->get_instruction()->accept( *visitor );
826 output << " : ";
827 genCommaList( asmStmt->get_output().begin(), asmStmt->get_output().end() );
828 output << " : ";
829 genCommaList( asmStmt->get_input().begin(), asmStmt->get_input().end() );
830 output << " : ";
831 genCommaList( asmStmt->get_clobber().begin(), asmStmt->get_clobber().end() );
832 if ( ! asmStmt->get_gotolabels().empty() ) {
833 output << " : ";
834 for ( std::list<Label>::iterator begin = asmStmt->get_gotolabels().begin();; ) {
835 output << *begin++;
836 if ( begin == asmStmt->get_gotolabels().end() ) break;
837 output << ", ";
838 } // for
839 } // if
840 output << " );" ;
841 }
842
843 void CodeGenerator::postvisit( AsmDecl * asmDecl ) {
844 output << "asm ";
845 AsmStmt * asmStmt = asmDecl->get_stmt();
846 output << "( ";
847 if ( asmStmt->get_instruction() ) asmStmt->get_instruction()->accept( *visitor );
848 output << " )" ;
849 }
850
851 void CodeGenerator::postvisit( IfStmt * ifStmt ) {
852 updateLocation( ifStmt );
853 output << "if ( ";
854 ifStmt->get_condition()->accept( *visitor );
855 output << " ) ";
856
857 ifStmt->get_thenPart()->accept( *visitor );
858
859 if ( ifStmt->get_elsePart() != 0) {
860 output << " else ";
861 ifStmt->get_elsePart()->accept( *visitor );
862 } // if
863 }
864
865 void CodeGenerator::postvisit( SwitchStmt * switchStmt ) {
866 updateLocation( switchStmt );
867 output << "switch ( " ;
868 switchStmt->get_condition()->accept( *visitor );
869 output << " ) ";
870
871 output << "{" << std::endl;
872 ++indent;
873 acceptAll( switchStmt->get_statements(), *visitor );
874 --indent;
875 output << indent << "}";
876 }
877
878 void CodeGenerator::postvisit( CaseStmt * caseStmt ) {
879 updateLocation( caseStmt );
880 if ( caseStmt->isDefault()) {
881 output << "default";
882 } else {
883 output << "case ";
884 caseStmt->get_condition()->accept( *visitor );
885 } // if
886 output << ":\n";
887
888 std::list<Statement *> sts = caseStmt->get_statements();
889
890 ++indent;
891 for ( std::list<Statement *>::iterator i = sts.begin(); i != sts.end(); i++) {
892 output << indent << printLabels( (*i)->get_labels() ) ;
893 (*i)->accept( *visitor );
894 output << endl;
895 } // for
896 --indent;
897 }
898
899 void CodeGenerator::postvisit( BranchStmt * branchStmt ) {
900 switch ( branchStmt->get_type()) {
901 case BranchStmt::Goto:
902 if ( ! branchStmt->get_target().empty() )
903 output << "goto " << branchStmt->get_target();
904 else {
905 if ( branchStmt->get_computedTarget() != 0 ) {
906 output << "goto *";
907 branchStmt->get_computedTarget()->accept( *visitor );
908 } // if
909 } // if
910 break;
911 case BranchStmt::Break:
912 output << "break";
913 break;
914 case BranchStmt::Continue:
915 output << "continue";
916 break;
917 } // switch
918 output << ";";
919 }
920
921 void CodeGenerator::postvisit( ReturnStmt * returnStmt ) {
922 output << "return ";
923 maybeAccept( returnStmt->get_expr(), *visitor );
924 output << ";";
925 }
926
927 void CodeGenerator::postvisit( ThrowStmt * throwStmt ) {
928 assertf( ! genC, "Throw statements should not reach code generation." );
929
930 output << ((throwStmt->get_kind() == ThrowStmt::Terminate) ?
931 "throw" : "throwResume");
932 if (throwStmt->get_expr()) {
933 output << " ";
934 throwStmt->get_expr()->accept( *visitor );
935 }
936 if (throwStmt->get_target()) {
937 output << " _At ";
938 throwStmt->get_target()->accept( *visitor );
939 }
940 output << ";";
941 }
942
943 void CodeGenerator::postvisit( WhileStmt * whileStmt ) {
944 if ( whileStmt->get_isDoWhile() ) {
945 output << "do" ;
946 } else {
947 output << "while (" ;
948 whileStmt->get_condition()->accept( *visitor );
949 output << ")";
950 } // if
951 output << " ";
952
953 output << CodeGenerator::printLabels( whileStmt->get_body()->get_labels() );
954 whileStmt->get_body()->accept( *visitor );
955
956 output << indent;
957
958 if ( whileStmt->get_isDoWhile() ) {
959 output << " while (" ;
960 whileStmt->get_condition()->accept( *visitor );
961 output << ");";
962 } // if
963 }
964
965 void CodeGenerator::postvisit( ForStmt * forStmt ) {
966 // initialization is always hoisted, so don't bother doing anything with that
967 output << "for (;";
968
969 if ( forStmt->get_condition() != 0 ) {
970 forStmt->get_condition()->accept( *visitor );
971 } // if
972 output << ";";
973
974 if ( forStmt->get_increment() != 0 ) {
975 // cast the top-level expression to void to reduce gcc warnings.
976 Expression * expr = new CastExpr( forStmt->get_increment() );
977 expr->accept( *visitor );
978 } // if
979 output << ") ";
980
981 if ( forStmt->get_body() != 0 ) {
982 output << CodeGenerator::printLabels( forStmt->get_body()->get_labels() );
983 forStmt->get_body()->accept( *visitor );
984 } // if
985 }
986
987 void CodeGenerator::postvisit( __attribute__((unused)) NullStmt * nullStmt ) {
988 //output << indent << CodeGenerator::printLabels( nullStmt->get_labels() );
989 output << "/* null statement */ ;";
990 }
991
992 void CodeGenerator::postvisit( DeclStmt * declStmt ) {
993 declStmt->get_decl()->accept( *visitor );
994
995 if ( doSemicolon( declStmt->get_decl() ) ) {
996 output << ";";
997 } // if
998 }
999
1000 void CodeGenerator::postvisit( ImplicitCtorDtorStmt * stmt ) {
1001 assertf( ! genC, "ImplicitCtorDtorStmts should not reach code generation." );
1002 stmt->callStmt->accept( *visitor );
1003 }
1004
1005 void CodeGenerator::handleStorageClass( DeclarationWithType * decl ) {
1006 if ( decl->get_storageClasses().any() ) {
1007 decl->get_storageClasses().print( output );
1008 } // if
1009 } // CodeGenerator::handleStorageClass
1010
1011 std::string genName( DeclarationWithType * decl ) {
1012 CodeGen::OperatorInfo opInfo;
1013 if ( operatorLookup( decl->get_name(), opInfo ) ) {
1014 return opInfo.outputName;
1015 } else {
1016 return decl->get_name();
1017 } // if
1018 }
1019} // namespace CodeGen
1020
1021// Local Variables: //
1022// tab-width: 4 //
1023// mode: c++ //
1024// compile-command: "make install" //
1025// End: //
Note: See TracBrowser for help on using the repository browser.