source: src/CodeGen/CodeGenerator.cpp@ c3c9325

Last change on this file since c3c9325 was 0139351, checked in by Andrew Beach <ajbeach@…>, 18 months ago

Add support for printing multiple returns. Mostly useful for early code dumps.

  • Property mode set to 100644
File size: 34.4 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.cpp --
8//
9// Author : Andrew Beach
10// Created On : Tue Oct 17 15:54:00 2023
11// Last Modified By : Andrew Beach
12// Last Modified On : Wed Oct 25 18:28:00 2023
13// Update Count : 0
14//
15
16#include "CodeGenerator.hpp"
17
18#include "AST/Print.hpp"
19#include "OperatorTable.h" // for OperatorInfo, operatorLookup
20#include "CodeGen/GenType.h" // for genType
21#include "Common/ToString.hpp" // for toString
22#include "Common/UniqueName.h" // for UniqueName
23
24namespace CodeGen {
25
26int CodeGenerator::tabsize = 4;
27
28// The kinds of statements that should be followed by whitespace.
29static bool wantSpacing( ast::Stmt const * stmt ) {
30 return dynamic_cast<ast::IfStmt const *>( stmt )
31 || dynamic_cast<ast::CompoundStmt const *>( stmt )
32 || dynamic_cast<ast::WhileDoStmt const *>( stmt )
33 || dynamic_cast<ast::ForStmt const *>( stmt )
34 || dynamic_cast<ast::SwitchStmt const *>( stmt );
35}
36
37void CodeGenerator::extension( ast::Expr const * expr ) {
38 if ( expr->extension ) output << "__extension__ ";
39}
40
41void CodeGenerator::extension( ast::Decl const * decl ) {
42 if ( decl->extension ) output << "__extension__ ";
43}
44
45void CodeGenerator::asmName( ast::DeclWithType const * decl ) {
46 if ( auto asmName = decl->asmName.as<ast::ConstantExpr>() ) {
47 output << " asm ( " << asmName->rep << " )";
48 }
49}
50
51CodeGenerator::LabelPrinter & CodeGenerator::LabelPrinter::operator()(
52 std::vector<ast::Label> const & l ) {
53 labels = &l;
54 return *this;
55}
56
57std::ostream & CodeGenerator::LabelPrinter::operator()( std::ostream & output ) const {
58 const std::vector<ast::Label> & labels = *this->labels;
59 for ( const ast::Label & label : labels ) {
60 output << label.name + ": ";
61 this->cg.genAttributes( label.attributes );
62 }
63 return output;
64}
65
66// Using updateLocation at the beginning of a node and endl within a node
67// should become the method of formating.
68void CodeGenerator::updateLocation( CodeLocation const & to ) {
69 // Skip if linemarks shouldn't appear or if location is unset.
70 if ( !options.lineMarks || to.isUnset() ) return;
71
72 if ( currentLocation.followedBy( to, 0 ) ) {
73 return;
74 } else if ( currentLocation.followedBy( to, 1 ) ) {
75 output << "\n" << indent;
76 currentLocation.first_line += 1;
77 } else if ( currentLocation.followedBy( to, 2 ) ) {
78 output << "\n\n" << indent;
79 currentLocation.first_line += 2;
80 } else {
81 output << "\n# " << to.first_line << " \"" << to.filename
82 << "\"\n" << indent;
83 currentLocation = to;
84 }
85 output << std::flush;
86}
87
88void CodeGenerator::updateLocation( ast::ParseNode const * to ) {
89 updateLocation( to->location );
90}
91
92std::ostream & CodeGenerator::LineEnder::operator()( std::ostream & os ) const {
93 os << "\n" << std::flush;
94 cg.currentLocation.first_line++;
95 return os;
96}
97
98CodeGenerator::CodeGenerator( std::ostream & os, const Options & options ) :
99 indent( 0, CodeGenerator::tabsize ), output( os ),
100 options( options ), printLabels( *this ), endl( *this )
101{}
102
103std::string CodeGenerator::mangleName( ast::DeclWithType const * decl ) {
104 if ( !options.pretty && decl->linkage.is_mangled && decl->mangleName != "" ) {
105 return decl->scopedMangleName();
106 } else {
107 return decl->name;
108 }
109}
110
111void CodeGenerator::genAttributes(
112 const std::vector<ast::ptr<ast::Attribute>> & attributes ) {
113 if ( attributes.empty() ) return;
114 output << "__attribute__ ((";
115 for ( auto attr = attributes.begin() ;; ) {
116 output << (*attr)->name;
117 if ( !(*attr)->params.empty() ) {
118 output << "(";
119 genCommaList( (*attr)->params );
120 output << ")";
121 }
122 if ( ++attr == attributes.end() ) break;
123 output << ",";
124 }
125 output << ")) ";
126}
127
128void CodeGenerator::previsit( ast::Node const * ) {
129 // All traversal is manual.
130 // TODO: Which means the ast::Pass is just providing a default no visit?
131 visit_children = false;
132}
133
134void CodeGenerator::previsit( ast::ParseNode const * node ) {
135 previsit( (ast::Node const *)node );
136 updateLocation( node );
137}
138
139void CodeGenerator::postvisit( ast::Node const * node ) {
140 std::stringstream ss;
141 ast::print( ss, node );
142 assertf( false, "Unhandled node reached in CodeGenerator: %s", ss.str().c_str() );
143}
144
145void CodeGenerator::previsit( ast::Expr const * expr ) {
146 previsit( (ast::ParseNode const *)expr );
147 GuardAction( [this, expr](){
148 if ( options.printExprTypes && expr->result ) {
149 output << " /* " << genType( expr->result, "", options ) << " */ ";
150 }
151 } );
152}
153
154void CodeGenerator::postvisit( ast::FunctionDecl const * decl ) {
155 // Deleted decls should never be used, so don't print them in C.
156 if ( decl->isDeleted && options.genC ) return;
157 extension( decl );
158 genAttributes( decl->attributes );
159
160 handleStorageClass( decl );
161 ast::print( output, decl->funcSpec );
162
163 Options subOptions = options;
164 subOptions.anonymousUnused = decl->stmts;
165
166 std::ostringstream acc;
167 ast::Pass<CodeGenerator> subCG( acc, subOptions );
168 // Add the forall clause.
169 // TODO: These probably should be removed by now and the assert used.
170 if ( !decl->type_params.empty() ) {
171 assertf( !options.genC, "FunctionDecl forall should not reach code generation." );
172 acc << "forall(";
173 subCG.core.genCommaList( decl->type_params );
174 acc << ")" << std::endl;
175 }
176
177 acc << mangleName( decl );
178
179 if ( 0 == decl->params.size() ) {
180 if ( decl->type->isVarArgs ) {
181 acc << "()";
182 } else {
183 acc << "(void)";
184 }
185 } else {
186 acc << "(";
187 subCG.core.genCommaList( decl->params );
188 if ( decl->type->isVarArgs ) {
189 acc << ", ...";
190 }
191 acc << ")";
192 }
193
194 if ( 1 == decl->returns.size() ) {
195 ast::ptr<ast::Type> const & type = decl->returns[0]->get_type();
196 output << genTypeNoAttr( type, acc.str(), subOptions );
197 } else if ( 0 == decl->returns.size() ) {
198 output << "void " + acc.str();
199 } else {
200 assertf( !options.genC, "Multi-return should not reach code generation." );
201 ast::ptr<ast::Type> type = new ast::TupleType( copy( decl->type->returns ) );
202 output << genTypeNoAttr( type, acc.str(), subOptions );
203 }
204
205 asmName( decl );
206
207 if ( decl->stmts ) {
208 decl->stmts->accept( *visitor );
209 }
210 if ( decl->isDeleted ) {
211 output << " = void";
212 }
213}
214
215ast::ObjectDecl const * CodeGenerator::postvisit(
216 ast::ObjectDecl const * decl ) {
217 // Deleted decls should never be used, so don't print them in C.
218 if ( decl->isDeleted && options.genC ) return decl;
219
220 // GCC allows an empty declarator (no name) for bit-fields and C
221 // states: 6.7.2.1 Structure and union specifiers, point 4, page 113:
222 // If the (bit field) value is zero, the declaration shall have no
223 // declarator. For anything else, the anonymous name refers to the
224 // anonymous object for plan9 inheritance.
225 if ( decl->name.empty() && options.genC && !decl->bitfieldWidth ) {
226 // TODO: Should this be changed in a pervious pass?
227 auto mutDecl = ast::mutate( decl );
228 // Only generate an anonymous name when generating C code,
229 // otherwise it clutters the output too much.
230 static UniqueName name = { "__anonymous_object" };
231 mutDecl->name = name.newName();
232 // Stops unused parameter warnings.
233 if ( options.anonymousUnused ) {
234 mutDecl->attributes.push_back( new ast::Attribute( "unused" ) );
235 }
236 decl = mutDecl;
237 }
238
239 extension( decl );
240 genAttributes( decl->attributes );
241
242 handleStorageClass( decl );
243 output << genType( decl->type, mangleName( decl ),
244 Options( options.pretty, options.genC, false, false ) );
245
246 asmName( decl );
247
248 if ( decl->init ) {
249 output << " = ";
250 decl->init->accept( *visitor );
251 }
252 if ( decl->isDeleted ) {
253 output << " = void";
254 }
255
256 if ( decl->bitfieldWidth ) {
257 output << ":";
258 decl->bitfieldWidth->accept( *visitor );
259 }
260 return decl;
261}
262
263void CodeGenerator::handleStorageClass( ast::DeclWithType const * decl ) {
264 if ( decl->storage.any() ) {
265 ast::print( output, decl->storage );
266 }
267}
268
269void CodeGenerator::handleAggregate(
270 ast::AggregateDecl const * decl, std::string const & kind ) {
271 if ( !decl->params.empty() && !options.genC ) {
272 output << "forall(";
273 genCommaList( decl->params );
274 output << ")\n" << indent << std::flush;
275 }
276
277 output << kind;
278 genAttributes( decl->attributes );
279 output << decl->name;
280
281 if ( decl->body ) {
282 auto & members = decl->members;
283 output << " {" << endl;
284
285 ++indent;
286 for ( auto & member : members ) {
287 output << indent;
288 member->accept( *visitor );
289 output << ";" << endl;
290 }
291 --indent;
292
293 output << indent << "}";
294 }
295}
296
297void CodeGenerator::postvisit( ast::StructDecl const * decl ) {
298 extension( decl );
299 handleAggregate( decl, "struct " );
300}
301
302void CodeGenerator::postvisit( ast::UnionDecl const * decl ) {
303 extension( decl );
304 handleAggregate( decl, "union " );
305}
306
307template<typename pass_type>
308inline void genEnumInitializer( ast::Pass<pass_type> * visitor,
309 ast::Type const * baseType, std::ostream & output,
310 ast::Init const * init, long long * curVal, Options options ) {
311 auto baseTypeAsBasic = dynamic_cast<ast::BasicType const *>( baseType );
312 // Value is provided.
313 if ( init ) {
314 output << " = (" << genType( baseType, "", options ) << ")";
315 init->accept( *visitor );
316 // If it is an integral type and initilizer offered,
317 // need to update the curVal.
318 if ( baseTypeAsBasic && baseTypeAsBasic->isInteger() ) {
319 ast::Expr const * expr = ((ast::SingleInit const *)(init))->value;
320 // Unwrap introduced cast.
321 while ( auto temp = dynamic_cast<ast::CastExpr const *>( expr ) ) {
322 expr = temp->arg;
323 }
324 *curVal = ((ast::ConstantExpr const *)(expr))->intValue() + 1;
325 }
326 // Generate next value from previous value.
327 } else if ( baseTypeAsBasic && baseTypeAsBasic->isInteger() ) {
328 output << " = (" << genType( baseType, "", options ) << ")";
329 output << (*curVal)++;
330 }
331}
332
333void CodeGenerator::postvisit( ast::EnumDecl const * decl ) {
334 extension( decl );
335 auto members = decl->members;
336 // if ( decl->base && !members.empty() ) {
337 // long long curVal = 0;
338 // for ( auto member : members ) {
339 // auto obj = member.strict_as<ast::ObjectDecl>();
340 // output << "static ";
341 // output << genType( decl->base, mangleName( obj ), options );
342 // genEnumInitializer( visitor, decl->base, output, obj->init, &curVal, options );
343 // output << ";" << endl;
344 // }
345 // } else {
346 output << "enum ";
347 genAttributes( decl->attributes );
348
349 output << decl->name;
350
351 if ( !members.empty() ) {
352 output << " {" << endl;
353
354 ++indent;
355 for ( auto member : members ) {
356 auto obj = member.strict_as<ast::ObjectDecl>();
357 output << indent << mangleName( obj );
358 if ( !decl->base && obj->init ) {
359 output << " = ";
360 obj->init->accept( *visitor );
361 }
362 output << "," << endl;
363 }
364 --indent;
365
366 output << indent << "}";
367 }
368 // }
369}
370
371void CodeGenerator::postvisit( ast::TraitDecl const * decl ) {
372 assertf( !options.genC, "TraitDecls should not reach code generation." );
373 extension( decl );
374 handleAggregate( decl, "trait " );
375}
376
377void CodeGenerator::postvisit( ast::TypedefDecl const * decl ) {
378 assertf( !options.genC, "Typedefs should not reach code generation." );
379 output << "typedef " << genType( decl->base, decl->name, options ) << endl;
380}
381
382void CodeGenerator::postvisit( ast::TypeDecl const * decl ) {
383 assertf( !options.genC, "TypeDecls should not reach code generation." );
384 output << decl->genTypeString() << " " << decl->name;
385 if ( decl->sized ) {
386 output << " | sized(" << decl->name << ")";
387 }
388 if ( !decl->assertions.empty() ) {
389 output << " | { ";
390 for ( ast::DeclWithType const * assert : decl->assertions ) {
391 assert->accept( *visitor );
392 output << "; ";
393 }
394 output << " }";
395 }
396}
397
398void CodeGenerator::postvisit( ast::StaticAssertDecl const * decl ) {
399 output << "_Static_assert(";
400 decl->cond->accept( *visitor );
401 output << ", ";
402 decl->msg->accept( *visitor );
403 output << ")";
404}
405
406void CodeGenerator::postvisit( ast::Designation const * designation ) {
407 auto designators = designation->designators;
408 if ( 0 == designators.size() ) return;
409 for ( ast::ptr<ast::Expr> const & des : designators ) {
410 // If the expression is a NameExpr or VariableExpr, then it is a field.
411 if ( des.as<ast::NameExpr>() || des.as<ast::VariableExpr>() ) {
412 output << ".";
413 des->accept( *visitor );
414 // Otherwise, it is a ConstantExpr or CastExpr, then it is an index.
415 } else {
416 output << "[";
417 des->accept( *visitor );
418 output << "]";
419 }
420 }
421 output << " = ";
422}
423
424void CodeGenerator::postvisit( ast::SingleInit const * init ) {
425 init->value->accept( *visitor );
426}
427
428void CodeGenerator::postvisit( ast::ListInit const * init ) {
429 auto initBegin = init->initializers.begin();
430 auto initEnd = init->initializers.end();
431 auto desigBegin = init->designations.begin();
432 auto desigEnd = init->designations.end();
433
434 output << "{ ";
435 if ( initBegin != initEnd ) while (true) {
436 (*desigBegin)->accept( *visitor );
437 (*initBegin)->accept( *visitor );
438 ++initBegin, ++desigBegin;
439 if ( initBegin == initEnd ) break;
440 output << ", ";
441 }
442 output << " }";
443 assertf( initBegin == initEnd && desigBegin == desigEnd,
444 "Initializers and designators not the same length. %s", toCString( init ) );
445}
446
447void CodeGenerator::postvisit( ast::ConstructorInit const * init ) {
448 assertf( !options.genC, "ConstructorInit nodes should not reach code generation." );
449 // This isn't actual code, but labels the constructor/destructor pairs.
450 output << "<ctorinit>{" << endl << ++indent << "ctor: ";
451 if ( init->ctor ) init->ctor->accept( *visitor );
452 output << ", " << endl << indent << "dtor: ";
453 if ( init->dtor ) init->dtor->accept( *visitor );
454 output << endl << --indent << "}";
455}
456
457void CodeGenerator::postvisit( ast::ApplicationExpr const * expr ) {
458 extension( expr );
459 if ( auto var = expr->func.as<ast::VariableExpr>() ) {
460 const OperatorInfo * opInfo;
461 if ( var->var->linkage == ast::Linkage::Intrinsic &&
462 ( opInfo = operatorLookup( var->var->name ) ) ) {
463 auto arg = expr->args.begin();
464 switch ( opInfo->type ) {
465 case OT_INDEX:
466 assert( 2 == expr->args.size() );
467 (*arg++)->accept( *visitor );
468 output << "[";
469 (*arg)->accept( *visitor );
470 output << "]";
471 break;
472
473 // There are no intrinsic definitions of the function call operator.
474 case OT_CALL:
475 assert( false );
476 break;
477
478 case OT_CTOR:
479 case OT_DTOR:
480 // No-op constructor, but run the internal expression.
481 if ( 1 == expr->args.size() ) {
482 output << "(";
483 (*arg++)->accept( *visitor );
484 output << ") /* " << opInfo->inputName << " */";
485 // These are all implemented as some form of assignment.
486 } else if ( 2 == expr->args.size() ) {
487 output << "(";
488 (*arg++)->accept( *visitor );
489 output << opInfo->symbol;
490 (*arg)->accept( *visitor );
491 output << ") /* " << opInfo->inputName << " */";
492 // No constructors with 0 or more than 2 parameters.
493 } else {
494 assert( false );
495 }
496 break;
497
498 case OT_PREFIX:
499 case OT_PREFIXASSIGN:
500 assert( 1 == expr->args.size() );
501 output << "(" << opInfo->symbol;
502 (*arg)->accept( *visitor );
503 output << ")";
504 break;
505
506 case OT_POSTFIX:
507 case OT_POSTFIXASSIGN:
508 assert( 1 == expr->args.size() );
509 (*arg)->accept( *visitor );
510 output << opInfo->symbol;
511 break;
512
513 case OT_INFIX:
514 case OT_INFIXASSIGN:
515 assert( 2 == expr->args.size() );
516 output << "(";
517 (*arg++)->accept( *visitor );
518 output << opInfo->symbol;
519 (*arg)->accept( *visitor );
520 output << ")";
521 break;
522
523 // There are no intrinsic definitions of 0/1 or label address
524 // as function.
525 case OT_CONSTANT:
526 case OT_LABELADDRESS:
527 assert( false );
528 }
529 // TODO: This is a work-around to make it a constant until a proper
530 // constexpr solution is created.
531 } else if ( var->var->linkage == ast::Linkage::BuiltinCFA &&
532 var->var->name == "intptr" ) {
533 output << "((void*)";
534 auto arg = expr->args.begin();
535 (*arg++)->accept( *visitor );
536 output << ")";
537 } else {
538 var->accept( *visitor );
539 output << "(";
540 genCommaList( expr->args );
541 output << ")";
542 }
543 } else {
544 expr->func->accept( *visitor );
545 output << "(";
546 genCommaList( expr->args );
547 output << ")";
548 }
549}
550
551void CodeGenerator::postvisit( ast::UntypedExpr const * expr ) {
552 extension( expr );
553 if ( auto name = expr->func.as<ast::NameExpr>() ) {
554 if ( const OperatorInfo * opInfo = operatorLookup( name->name ) ) {
555 auto arg = expr->args.begin();
556 switch ( opInfo->type ) {
557 case OT_INDEX:
558 assert( 2 == expr->args.size() );
559 (*arg++)->accept( *visitor );
560 output << "[";
561 (*arg)->accept( *visitor );
562 output << "]";
563 break;
564
565 case OT_CALL:
566 assert( false );
567
568 case OT_CTOR:
569 case OT_DTOR:
570 // No-op constructor, but run the internal expression.
571 if ( 1 == expr->args.size() ) {
572 output << "(";
573 (*arg++)->accept( *visitor );
574 output << ")";
575 // These are all implemented as some form of assignment.
576 } else if ( 2 == expr->args.size() ) {
577 output << "(";
578 (*arg++)->accept( *visitor );
579 output << opInfo->symbol;
580 (*arg)->accept( *visitor );
581 output << ") /* " << opInfo->inputName << " */";
582 // No constructors with 0 or more than 2 parameters.
583 } else {
584 assertf( !options.genC, "UntypedExpr constructor/destructor with 0 or more than 2 parameters." );
585 output << "(";
586 (*arg++)->accept( *visitor );
587 output << opInfo->symbol << "{ ";
588 genCommaList( arg, expr->args.end() );
589 output << "}) /* " << opInfo->inputName << " */";
590 }
591 break;
592
593 case OT_PREFIX:
594 case OT_PREFIXASSIGN:
595 case OT_LABELADDRESS:
596 assert( 1 == expr->args.size() );
597 output << "(" << opInfo->symbol;
598 (*arg)->accept( *visitor );
599 output << ")";
600 break;
601
602 case OT_POSTFIX:
603 case OT_POSTFIXASSIGN:
604 assert( 1 == expr->args.size() );
605 (*arg)->accept( *visitor );
606 output << opInfo->symbol;
607 break;
608
609 case OT_INFIX:
610 case OT_INFIXASSIGN:
611 assert( 2 == expr->args.size() );
612 output << "(";
613 (*arg++)->accept( *visitor );
614 output << opInfo->symbol;
615 (*arg)->accept( *visitor );
616 output << ")";
617 break;
618
619 // There are no intrinsic definitions of 0/1 or label address
620 // as function.
621 case OT_CONSTANT:
622 assert( false );
623 }
624 // builtin routines
625 } else {
626 name->accept( *visitor );
627 output << "(";
628 genCommaList( expr->args );
629 output << ")";
630 }
631 } else {
632 expr->func->accept( *visitor );
633 output << "(";
634 genCommaList( expr->args );
635 output << ")";
636 }
637}
638
639void CodeGenerator::postvisit( ast::RangeExpr const * expr ) {
640 expr->low->accept( *visitor );
641 output << " ... ";
642 expr->high->accept( *visitor );
643}
644
645void CodeGenerator::postvisit( ast::NameExpr const * expr ) {
646 extension( expr );
647 if ( const OperatorInfo * opInfo = operatorLookup( expr->name ) ) {
648 if ( OT_CONSTANT == opInfo->type ) {
649 output << opInfo->symbol;
650 } else {
651 output << opInfo->outputName;
652 }
653 } else {
654 output << expr->name;
655 }
656}
657
658void CodeGenerator::postvisit( ast::DimensionExpr const * expr ) {
659 extension( expr );
660 output << "/*non-type*/" << expr->name;
661}
662
663void CodeGenerator::postvisit( ast::AddressExpr const * expr ) {
664 extension( expr );
665 output << "(&";
666 expr->arg->accept( *visitor );
667 output << ")";
668}
669
670void CodeGenerator::postvisit( ast::LabelAddressExpr const * expr ) {
671 extension( expr );
672 output << "(&&" << expr->arg << ")";
673}
674
675void CodeGenerator::postvisit( ast::CastExpr const * expr ) {
676 extension( expr );
677 output << "(";
678 if ( expr->result->isVoid() ) {
679 output << "(void)";
680 } else {
681 output << "(";
682 output << genType( expr->result, "", options );
683 output << ")";
684 }
685 expr->arg->accept( *visitor );
686 output << ")";
687}
688
689void CodeGenerator::postvisit( ast::KeywordCastExpr const * expr ) {
690 assertf( !options.genC, "KeywordCastExpr should not reach code generation." );
691 extension( expr );
692 output << "((" << expr->targetString() << " &)";
693 expr->arg->accept( *visitor );
694 output << ")";
695}
696
697void CodeGenerator::postvisit( ast::VirtualCastExpr const * expr ) {
698 assertf( !options.genC, "VirtualCastExpr should not reach code generation." );
699 extension( expr );
700 // TODO: Is this busted?
701 output << "(virtual ";
702 expr->arg->accept( *visitor );
703 output << ")";
704}
705
706void CodeGenerator::postvisit( ast::UntypedMemberExpr const * expr ) {
707 assertf( !options.genC, "UntypedMemberExpr should not reach code generation." );
708 extension( expr );
709 expr->aggregate->accept( *visitor );
710 output << ".";
711 expr->member->accept( *visitor );
712}
713
714void CodeGenerator::postvisit( ast::MemberExpr const * expr ) {
715 extension( expr );
716 expr->aggregate->accept( *visitor );
717 output << "." << mangleName( expr->member );
718}
719
720void CodeGenerator::postvisit( ast::VariableExpr const * expr ) {
721 extension( expr );
722 const OperatorInfo * opInfo;
723 if ( dynamic_cast<ast::ZeroType const *>( expr->var->get_type() ) ) {
724 output << "0";
725 } else if ( expr->var->linkage == ast::Linkage::Intrinsic
726 && ( opInfo = operatorLookup( expr->var->name ) )
727 && opInfo->type == OT_CONSTANT ) {
728 output << opInfo->symbol;
729 } else {
730 output << mangleName( expr->var );
731 }
732}
733
734void CodeGenerator::postvisit( ast::ConstantExpr const * expr ) {
735 extension( expr );
736 output << expr->rep;
737}
738
739void CodeGenerator::postvisit( ast::SizeofExpr const * expr ) {
740 extension( expr );
741 output << "sizeof(";
742 if ( expr->type ) {
743 output << genType( expr->type, "", options );
744 } else {
745 expr->expr->accept( *visitor );
746 }
747 output << ")";
748}
749
750void CodeGenerator::postvisit( ast::AlignofExpr const * expr ) {
751 // Using the GCC extension to avoid changing the std to C11.
752 extension( expr );
753 output << "__alignof__(";
754 if ( expr->type ) {
755 output << genType( expr->type, "", options );
756 } else {
757 expr->expr->accept( *visitor );
758 }
759 output << ")";
760}
761
762void CodeGenerator::postvisit( ast::UntypedOffsetofExpr const * expr ) {
763 assertf( !options.genC, "UntypedOffsetofExpr should not reach code generation." );
764 output << "offsetof(";
765 output << genType( expr->type, "", options );
766 output << ", " << expr->member;
767 output << ")";
768}
769
770void CodeGenerator::postvisit( ast::OffsetofExpr const * expr ) {
771 // Use GCC builtin
772 output << "__builtin_offsetof(";
773 output << genType( expr->type, "", options );
774 output << ", " << mangleName( expr->member );
775 output << ")";
776}
777
778void CodeGenerator::postvisit( ast::OffsetPackExpr const * expr ) {
779 assertf( !options.genC, "OffsetPackExpr should not reach code generation." );
780 output << "__CFA_offsetpack(" << genType( expr->type, "", options ) << ")";
781}
782
783void CodeGenerator::postvisit( ast::LogicalExpr const * expr ) {
784 extension( expr );
785 output << "(";
786 expr->arg1->accept( *visitor );
787 output << ( ( expr->isAnd ) ? " && " : " || " );
788 expr->arg2->accept( *visitor );
789 output << ")";
790}
791
792void CodeGenerator::postvisit( ast::ConditionalExpr const * expr ) {
793 extension( expr );
794 output << "(";
795 expr->arg1->accept( *visitor );
796 output << " ? ";
797 expr->arg2->accept( *visitor );
798 output << " : ";
799 expr->arg3->accept( *visitor );
800 output << ")";
801}
802
803void CodeGenerator::postvisit( ast::CommaExpr const * expr ) {
804 extension( expr );
805 output << "(";
806 if ( options.genC ) {
807 // arg1 of a comma expression is never used, so it can be safely cast
808 // to void to reduce gcc warnings.
809 ast::ptr<ast::Expr> arg1 = new ast::CastExpr( expr->location, expr->arg1 );
810 arg1->accept( *visitor );
811 } else {
812 expr->arg1->accept( *visitor );
813 }
814 output << " , ";
815 expr->arg2->accept( *visitor );
816 output << ")";
817}
818
819void CodeGenerator::postvisit( ast::TupleAssignExpr const * expr ) {
820 assertf( !options.genC, "TupleAssignExpr should not reach code generation." );
821 expr->stmtExpr->accept( *visitor );
822}
823
824void CodeGenerator::postvisit( ast::UntypedTupleExpr const * expr ) {
825 assertf( !options.genC, "UntypedTupleExpr should not reach code generation." );
826 extension( expr );
827 output << "[";
828 genCommaList( expr->exprs );
829 output << "]";
830}
831
832void CodeGenerator::postvisit( ast::TupleExpr const * expr ) {
833 assertf( !options.genC, "TupleExpr should not reach code generation." );
834 extension( expr );
835 output << "[";
836 genCommaList( expr->exprs );
837 output << "]";
838}
839
840void CodeGenerator::postvisit( ast::TupleIndexExpr const * expr ) {
841 assertf( !options.genC, "TupleIndexExpr should not reach code generation." );
842 extension( expr );
843 expr->tuple->accept( *visitor );
844 output << "." << expr->index;
845}
846
847void CodeGenerator::postvisit( ast::TypeExpr const * expr ) {
848 // TODO: Should there be an assertion there?
849 if ( !options.genC ) {
850 output << genType( expr->type, "", options );
851 }
852}
853
854void CodeGenerator::postvisit( ast::AsmExpr const * expr ) {
855 if ( !expr->inout.empty() ) {
856 output << "[ " << expr->inout << " ] ";
857 }
858 expr->constraint->accept( *visitor );
859 output << " ( ";
860 expr->operand->accept( *visitor );
861 output << " )";
862}
863
864void CodeGenerator::postvisit( ast::CompoundLiteralExpr const * expr ) {
865 //assert( expr->result && dynamic_cast<ast::ListInit const *>( expr->init ) );
866 assert( expr->result && expr->init.as<ast::ListInit>() );
867 output << "(" << genType( expr->result, "", options ) << ")";
868 expr->init->accept( *visitor );
869}
870
871void CodeGenerator::postvisit( ast::UniqueExpr const * expr ) {
872 assertf( !options.genC, "UniqueExpr should not reach code generation." );
873 output << "unq<" << expr->id << ">{ ";
874 expr->expr->accept( *visitor );
875 output << " }";
876}
877
878void CodeGenerator::postvisit( ast::StmtExpr const * expr ) {
879 auto stmts = expr->stmts->kids;
880 output << "({" << endl;
881 ++indent;
882 unsigned int numStmts = stmts.size();
883 unsigned int i = 0;
884 for ( ast::ptr<ast::Stmt> const & stmt : stmts ) {
885 output << indent << printLabels( stmt->labels );
886 if ( i + 1 == numStmts ) {
887 // Last statement in a statement expression needs to be handled
888 // specially - cannot cast to void, otherwise the expression
889 // statement has no value.
890 if ( ast::ExprStmt const * exprStmt = stmt.as<ast::ExprStmt>() ) {
891 exprStmt->expr->accept( *visitor );
892 output << ";" << endl;
893 ++i;
894 break;
895 }
896 }
897 stmt->accept( *visitor );
898 output << endl;
899 if ( wantSpacing( stmt ) ) output << endl;
900 ++i;
901 }
902 --indent;
903 output << indent << "})";
904}
905
906void CodeGenerator::postvisit( ast::ConstructorExpr const * expr ) {
907 assertf( !options.genC, "ConstructorExpr should not reach code generation." );
908 expr->callExpr->accept( *visitor );
909}
910
911void CodeGenerator::postvisit( ast::DeletedExpr const * expr ) {
912 assertf( !options.genC, "DeletedExpr should not reach code generation." );
913 expr->expr->accept( *visitor );
914}
915
916void CodeGenerator::postvisit( ast::DefaultArgExpr const * expr ) {
917 assertf( !options.genC, "DefaultArgExpr should not reach code generation." );
918 expr->expr->accept( *visitor );
919}
920
921void CodeGenerator::postvisit( ast::GenericExpr const * expr ) {
922 assertf( !options.genC, "GenericExpr should not reach code generation." );
923 output << "_Generic(";
924 expr->control->accept( *visitor );
925 output << ", ";
926 unsigned int numAssocs = expr->associations.size();
927 unsigned int i = 0;
928 for ( const ast::GenericExpr::Association & assoc : expr->associations ) {
929 if ( nullptr == assoc.type ) {
930 output << "default: ";
931 } else {
932 output << genType( assoc.type, "", options ) << ": ";
933 }
934 assoc.expr->accept( *visitor );
935 ++i;
936 if ( i != numAssocs ) output << ", ";
937 }
938 output << ")";
939}
940
941void CodeGenerator::postvisit( ast::CompoundStmt const * stmt ) {
942 output << "{" << endl;
943
944 ++indent;
945 for ( auto kid : stmt->kids ) {
946 output << indent << printLabels( kid->labels );
947 kid->accept( *visitor );
948 output << endl;
949 if ( wantSpacing( kid ) ) output << endl;
950 }
951 --indent;
952
953 output << indent << "}";
954}
955
956void CodeGenerator::postvisit( ast::ExprStmt const * stmt ) {
957 assert( stmt );
958 // Cast the top-level expression to void to reduce gcc warnings.
959 if ( options.genC ) {
960 ast::ptr<ast::Expr> expr = new ast::CastExpr( stmt->location, stmt->expr );
961 expr->accept( *visitor );
962 } else {
963 stmt->expr->accept( *visitor );
964 }
965 output << ";";
966}
967
968void CodeGenerator::postvisit( ast::AsmStmt const * stmt ) {
969 output << "asm ";
970 if ( stmt->isVolatile ) output << "volatile ";
971 if ( !stmt->gotoLabels.empty() ) output << "goto ";
972 output << "( ";
973 if ( stmt->instruction ) stmt->instruction->accept( *visitor );
974 output << " : ";
975 genCommaList( stmt->output );
976 output << " : ";
977 genCommaList( stmt->input );
978 output << " : ";
979 genCommaList( stmt->clobber );
980 if ( !stmt->gotoLabels.empty() ) {
981 output << " : ";
982 auto it = stmt->gotoLabels.begin();
983 while (true) {
984 output << *it++;
985 if ( stmt->gotoLabels.end() == it ) break;
986 output << ", ";
987 }
988 }
989 output << " );";
990}
991
992void CodeGenerator::postvisit( ast::AsmDecl const * decl ) {
993 output << "asm ";
994 ast::AsmStmt const * stmt = decl->stmt;
995 output << "( ";
996 if ( stmt->instruction ) stmt->instruction->accept( *visitor );
997 output << " )";
998}
999
1000void CodeGenerator::postvisit( ast::DirectiveDecl const * decl ) {
1001 // endl prevents spaces before the directive.
1002 output << endl << decl->stmt->directive;
1003}
1004
1005void CodeGenerator::postvisit( ast::DirectiveStmt const * stmt ) {
1006 // endl prevents spaces before the directive.
1007 output << endl << stmt->directive;
1008}
1009
1010void CodeGenerator::postvisit( ast::IfStmt const * stmt ) {
1011 output << "if ( ";
1012 stmt->cond->accept( *visitor );
1013 output << " ) ";
1014
1015 stmt->then->accept( *visitor );
1016
1017 if ( nullptr != stmt->else_ ) {
1018 output << " else ";
1019 stmt->else_->accept( *visitor );
1020 }
1021}
1022
1023void CodeGenerator::postvisit( ast::SwitchStmt const * stmt ) {
1024 output << "switch ( ";
1025 stmt->cond->accept( *visitor );
1026 output << " ) ";
1027
1028 output << "{" << endl;
1029 ++indent;
1030 for ( auto node : stmt->cases ) {
1031 node->accept( *visitor );
1032 }
1033 --indent;
1034 output << indent << "}";
1035}
1036
1037void CodeGenerator::postvisit( ast::CaseClause const * clause ) {
1038 updateLocation( clause );
1039 output << indent;
1040 if ( clause->isDefault() ) {
1041 output << "default";
1042 } else {
1043 output << "case ";
1044 clause->cond->accept( *visitor );
1045 }
1046 output << ":" << endl;
1047
1048 ++indent;
1049 for ( auto stmt : clause->stmts ) {
1050 output << indent << printLabels( stmt->labels ) ;
1051 stmt->accept( *visitor );
1052 output << endl;
1053 }
1054 --indent;
1055}
1056
1057void CodeGenerator::postvisit( ast::BranchStmt const * stmt ) {
1058 switch ( stmt->kind ) {
1059 case ast::BranchStmt::Goto:
1060 if ( !stmt->target.empty() ) {
1061 output << "goto " << stmt->target;
1062 } else if ( nullptr != stmt->computedTarget ) {
1063 output << "goto *";
1064 stmt->computedTarget->accept( *visitor );
1065 }
1066 break;
1067 case ast::BranchStmt::Break:
1068 output << "break";
1069 break;
1070 case ast::BranchStmt::Continue:
1071 output << "continue";
1072 break;
1073 case ast::BranchStmt::FallThrough:
1074 case ast::BranchStmt::FallThroughDefault:
1075 assertf( !options.genC, "fallthru should not reach code generation." );
1076 output << "fallthru";
1077 break;
1078 default:
1079 assertf( false, "Bad BranchStmt value." );
1080 }
1081 // Print branch target for labelled break/continue/fallthru in debug mode.
1082 if ( !options.genC && stmt->kind != ast::BranchStmt::Goto ) {
1083 if ( !stmt->target.empty() ) {
1084 output << " " << stmt->target;
1085 } else if ( stmt->kind == ast::BranchStmt::FallThrough ) {
1086 output << " default";
1087 }
1088 }
1089 output << ";";
1090}
1091
1092void CodeGenerator::postvisit( ast::ReturnStmt const * stmt ) {
1093 output << "return ";
1094 if ( stmt->expr ) stmt->expr->accept( *visitor );
1095 output << ";";
1096}
1097
1098void CodeGenerator::postvisit( ast::ThrowStmt const * stmt ) {
1099 assertf( !options.genC, "ThrowStmt should not reach code generation." );
1100
1101 output << ((stmt->kind == ast::Terminate) ? "throw" : "throwResume");
1102 if ( stmt->expr ) {
1103 output << " ";
1104 stmt->expr->accept( *visitor );
1105 }
1106 if ( stmt->target ) {
1107 output << " _At ";
1108 stmt->target->accept( *visitor );
1109 }
1110 output << ";";
1111}
1112
1113void CodeGenerator::postvisit( ast::CatchClause const * stmt ) {
1114 assertf( !options.genC, "CatchClause should not reach code generation." );
1115
1116 output << ((stmt->kind == ast::Terminate) ? "catch" : "catchResume");
1117 output << "( ";
1118 stmt->decl->accept( *visitor );
1119 if ( stmt->cond ) {
1120 output << " ; ";
1121 stmt->cond->accept( *visitor );
1122 }
1123 output << " ) ";
1124 stmt->body->accept( *visitor );
1125}
1126
1127void CodeGenerator::postvisit( ast::WaitForStmt const * stmt ) {
1128 assertf( !options.genC, "WaitforStmt should not reach code generation." );
1129
1130 bool first = true;
1131 for ( ast::ptr<ast::WaitForClause> const & clause : stmt->clauses ) {
1132 if (first) { output << "or "; first = false; }
1133 if ( clause->when_cond ) {
1134 output << "when(";
1135 clause->when_cond->accept( *visitor );
1136 output << ") ";
1137 }
1138 output << "waitfor(";
1139 clause->target->accept( *visitor );
1140 for ( ast::ptr<ast::Expr> const & expr : clause->target_args ) {
1141 output << ",";
1142 expr->accept( *visitor );
1143 }
1144 output << ") ";
1145 clause->stmt->accept( *visitor );
1146 }
1147
1148 if ( stmt->timeout_stmt ) {
1149 output << "or ";
1150 if ( stmt->timeout_cond ) {
1151 output << "when(";
1152 stmt->timeout_cond->accept( *visitor );
1153 output << ") ";
1154 }
1155 output << "timeout(";
1156 stmt->timeout_time->accept( *visitor );
1157 output << ") ";
1158 stmt->timeout_stmt->accept( *visitor );
1159 }
1160
1161 if ( stmt->else_stmt ) {
1162 output << "or ";
1163 if ( stmt->else_cond ) {
1164 output << "when(";
1165 stmt->else_cond->accept( *visitor );
1166 output << ")";
1167 }
1168 output << "else ";
1169 stmt->else_stmt->accept( *visitor );
1170 }
1171}
1172
1173void CodeGenerator::postvisit( ast::WithStmt const * stmt ) {
1174 assertf( !options.genC, "WithStmt should not reach code generation." );
1175
1176 output << "with ( ";
1177 genCommaList( stmt->exprs );
1178 output << " ) ";
1179 stmt->stmt->accept( *visitor );
1180}
1181
1182void CodeGenerator::postvisit( ast::WhileDoStmt const * stmt ) {
1183 if ( stmt->isDoWhile ) {
1184 output << "do";
1185 } else {
1186 output << "while (";
1187 stmt->cond->accept( *visitor );
1188 output << ")";
1189 }
1190 output << " ";
1191
1192 output << CodeGenerator::printLabels( stmt->body->labels );
1193 stmt->body->accept( *visitor );
1194
1195 output << indent;
1196
1197 if ( stmt->isDoWhile ) {
1198 output << " while (";
1199 stmt->cond->accept( *visitor );
1200 output << ");";
1201 }
1202}
1203
1204void CodeGenerator::postvisit( ast::ForStmt const * stmt ) {
1205 // Initializer is always hoised so don't generate it.
1206 // TODO: Do an assertion check?
1207 output << "for (;";
1208
1209 if ( nullptr != stmt->cond ) {
1210 stmt->cond->accept( *visitor );
1211 }
1212 output << ";";
1213
1214 if ( nullptr != stmt->inc ) {
1215 // cast the top-level expression to void to reduce gcc warnings.
1216 ast::Expr * expr = new ast::CastExpr( stmt->inc );
1217 expr->accept( *visitor );
1218 }
1219 output << ") ";
1220
1221 if ( nullptr != stmt->body ) {
1222 output << printLabels( stmt->body->labels );
1223 stmt->body->accept( *visitor );
1224 }
1225}
1226
1227void CodeGenerator::postvisit( ast::NullStmt const * ) {
1228 output << "/* null statement */ ;";
1229}
1230
1231void CodeGenerator::postvisit( ast::DeclStmt const * stmt ) {
1232 stmt->decl->accept( *visitor );
1233
1234 if ( doSemicolon( stmt->decl ) ) output << ";";
1235}
1236
1237void CodeGenerator::postvisit( ast::ImplicitCtorDtorStmt const * stmt ) {
1238 assertf( !options.genC, "ImplicitCtorCtorStmt should not reach code generation." );
1239 stmt->callStmt->accept( *visitor );
1240}
1241
1242void CodeGenerator::postvisit( ast::MutexStmt const * stmt ) {
1243 assertf( !options.genC, "MutexStmt should not reach code generation." );
1244 // TODO: But this isn't what a mutex statement looks like.
1245 stmt->stmt->accept( *visitor );
1246}
1247
1248std::string genName( ast::DeclWithType const * decl ) {
1249 if ( const OperatorInfo * opInfo = operatorLookup( decl->name ) ) {
1250 return opInfo->outputName;
1251 } else {
1252 return decl->name;
1253 }
1254}
1255
1256} // namespace CodeGen
Note: See TracBrowser for help on using the repository browser.