source: src/CodeGen/CodeGenerator.cc @ 8bafacc

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

New system for formating generated code in CodeGenerator?.

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