source: src/CodeGen/CodeGenerator.cc @ 8135d4c

ADTaaron-thesisarm-ehast-experimentalcleanup-dtorsdeferred_resndemanglerenumforall-pointer-decayjacob/cs343-translationjenkins-sandboxnew-astnew-ast-unique-exprnew-envno_listpersistent-indexerpthread-emulationqualifiedEnumresolv-newwith_gc
Last change on this file since 8135d4c was 8135d4c, checked in by Rob Schluntz <rschlunt@…>, 7 years ago

Merge branch 'master' into references

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