source: src/CodeGen/CodeGenerator.cc@ df75fe97

ADT arm-eh ast-experimental enum forall-pointer-decay jacob/cs343-translation jenkins-sandbox new-ast new-ast-unique-expr pthread-emulation qualifiedEnum
Last change on this file since df75fe97 was de8d7fb1, checked in by Peter A. Buhr <pabuhr@…>, 6 years ago

do not generate anonymous name for bit field with empty declarator

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