source: src/CodeGen/CodeGenerator.cc@ fac84be

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

add support for constructor/destructor attribute priority and set priority for library constructors to high

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