source: src/CodeGen/CodeGenerator.cc@ 3265399

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 with_gc
Last change on this file since 3265399 was 593370c, checked in by Rob Schluntz <rschlunt@…>, 7 years ago

Modify codgen to put struct/union attributes in the correct position

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