source: src/CodeGen/CodeGenerator.cc@ 70c2df8

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 70c2df8 was daf1af8, checked in by Andrew Beach <ajbeach@…>, 8 years ago

Added a new ThrowStmt node to the Syntax Tree.

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