source: translator/CodeGen/CodeGenerator2.cc @ c11e31c

ADTaaron-thesisarm-ehast-experimentalcleanup-dtorsctordeferred_resndemanglerenumforall-pointer-decaygc_noraiijacob/cs343-translationjenkins-sandboxmemorynew-astnew-ast-unique-exprnew-envno_listpersistent-indexerpthread-emulationqualifiedEnumresolv-newstringwith_gc
Last change on this file since c11e31c was c11e31c, checked in by Peter A. Buhr <pabuhr@…>, 9 years ago

add inline and attribute qualifiers, cfa.y comment formatting, fix error message in isIntegralType

  • Property mode set to 100644
File size: 17.9 KB
Line 
1#include <algorithm>
2#include <iostream>
3#include <cassert>
4#include <list>
5
6#include "SynTree/Type.h"
7#include "SynTree/Declaration.h"
8#include "SynTree/Statement.h"
9#include "SynTree/Expression.h"
10#include "SynTree/Initializer.h"
11
12#include "utility.h"
13#include "UnimplementedError.h"
14
15#include "CodeGenerator2.h"
16#include "OperatorTable.h"
17#include "GenType.h"
18
19using namespace std;
20
21namespace CodeGen {
22    int CodeGenerator2::tabsize = 4;
23
24    CodeGenerator2::CodeGenerator2( std::ostream &os ) : cur_indent( 0 ), insideFunction( false ), before( os ), after() { }
25
26    CodeGenerator2::CodeGenerator2( std::ostream &os, std::string init, int indent, bool infunp )
27        : cur_indent( indent ), insideFunction( infunp ), before( os )
28    {
29        //before << std::string( init );
30    }
31
32    CodeGenerator2::CodeGenerator2( std::ostream &os, char *init, int indent, bool infunp )
33        : cur_indent( indent ), insideFunction( infunp ), before( os )
34    {
35        //before << std::string( init );
36    }
37
38    string mangleName( DeclarationWithType *decl ) {
39        if ( decl->get_mangleName() != "" ) {
40            return decl->get_mangleName();
41        } else {
42            return decl->get_name();
43        } // if
44    }
45 
46    //*** Declarations
47    void CodeGenerator2::visit( FunctionDecl *functionDecl ) {
48        handleStorageClass( functionDecl );
49        before << genType( functionDecl->get_functionType(), mangleName( functionDecl ) );
50
51        // how to get this to the Functype?
52        std::list< Declaration * > olds = functionDecl->get_oldDecls();
53        if ( ! olds.empty() ) {
54            before << " /* function has old declaration */";
55        } // if
56
57        // acceptAll( functionDecl->get_oldDecls(), *this );
58        if ( functionDecl->get_statements() ) {
59            functionDecl->get_statements()->accept(*this );
60        } // if
61    }
62
63    void CodeGenerator2::visit( ObjectDecl *objectDecl ) {
64        handleStorageClass( objectDecl );
65        before << genType( objectDecl->get_type(), mangleName( objectDecl ) );
66   
67        if ( objectDecl->get_init() ) {
68            before << " = ";
69            objectDecl->get_init()->accept( *this );
70        } // if
71        if ( objectDecl->get_bitfieldWidth() ) {
72            before << ":";
73            objectDecl->get_bitfieldWidth()->accept( *this );
74        } // if
75    }
76
77    void CodeGenerator2::handleAggregate( AggregateDecl *aggDecl ) {
78        if ( aggDecl->get_name() != "" )
79            before << aggDecl->get_name();
80   
81        std::list< Declaration * > &memb = aggDecl->get_members();
82
83        if ( ! memb.empty() ) {
84            before << endl << string( cur_indent, ' ' ) << "{" << endl;
85
86            cur_indent += CodeGenerator2::tabsize; 
87            for ( std::list< Declaration* >::iterator i = memb.begin(); i != memb.end();  i++) {
88                before << string( cur_indent, ' ' ); 
89                (*i)->accept(*this );
90                before << ";" << endl;
91            }
92
93            cur_indent -= CodeGenerator2::tabsize; 
94
95            before << string( cur_indent, ' ' ) << "}";
96        } // if
97    }
98
99    void CodeGenerator2::visit( StructDecl *structDecl ) {
100        before << "struct ";
101        handleAggregate( structDecl );
102    }
103
104    void CodeGenerator2::visit( UnionDecl *aggregateDecl ) {
105        before << "union ";
106        handleAggregate( aggregateDecl );
107    }
108 
109    void CodeGenerator2::visit( EnumDecl *aggDecl ) {
110        before << "enum ";
111
112        if ( aggDecl->get_name() != "" )
113            before << aggDecl->get_name();
114   
115        std::list< Declaration* > &memb = aggDecl->get_members();
116
117        if ( ! memb.empty() ) {
118            before << endl << "{" << endl;
119
120            cur_indent += CodeGenerator2::tabsize; 
121            for ( std::list< Declaration* >::iterator i = memb.begin(); i != memb.end();  i++) {
122                ObjectDecl *obj = dynamic_cast< ObjectDecl* >( *i );
123                assert( obj );
124                before << string( cur_indent, ' ' ) << mangleName( obj ); 
125                if ( obj->get_init() ) {
126                    before << " = ";
127                    obj->get_init()->accept(*this );
128                } // if
129                before << "," << endl;
130            }
131
132            cur_indent -= CodeGenerator2::tabsize; 
133
134            before << "}" << endl;
135        } // if
136    }
137 
138    void CodeGenerator2::visit( ContextDecl *aggregateDecl ) {}
139 
140    void CodeGenerator2::visit( TypedefDecl *typeDecl ) {
141        before << "typedef ";
142        before << genType( typeDecl->get_base(), typeDecl->get_name() );
143    }
144 
145    void CodeGenerator2::visit( TypeDecl *typeDecl ) {
146        // really, we should mutate this into something that isn't a TypeDecl but that requires large-scale changes,
147        // still to be done
148        before << "extern unsigned long " << typeDecl->get_name();
149        if ( typeDecl->get_base() ) {
150            before << " = sizeof( " << genType( typeDecl->get_base(), "" ) << " )";
151        } // if
152    }
153
154    void CodeGenerator2::visit( SingleInit *init ) {
155        init->get_value()->accept( *this );
156    }
157
158    void CodeGenerator2::visit( ListInit *init ) {
159        before << "{ ";
160        genCommaList( init->begin_initializers(), init->end_initializers() );
161        before << " }";
162    }
163
164    void CodeGenerator2::visit( Constant *constant ) { 
165        before << constant->get_value() ;
166    }
167
168    //*** Expressions
169    void CodeGenerator2::visit( ApplicationExpr *applicationExpr ) {
170        if ( VariableExpr *varExpr = dynamic_cast< VariableExpr* >( applicationExpr->get_function() ) ) {
171            OperatorInfo opInfo;
172            if ( varExpr->get_var()->get_linkage() == LinkageSpec::Intrinsic && operatorLookup( varExpr->get_var()->get_name(), opInfo ) ) {
173                std::list< Expression* >::iterator arg = applicationExpr->get_args().begin();
174                switch ( opInfo.type ) {
175                  case OT_PREFIXASSIGN:
176                  case OT_POSTFIXASSIGN:
177                  case OT_INFIXASSIGN:
178                    {
179                        assert( arg != applicationExpr->get_args().end() );
180                        if ( AddressExpr *addrExpr = dynamic_cast< AddressExpr * >( *arg ) ) {
181           
182                            *arg = addrExpr->get_arg();
183                        } else {
184                            UntypedExpr *newExpr = new UntypedExpr( new NameExpr( "*?" ) );
185                            newExpr->get_args().push_back( *arg );
186                            *arg = newExpr;
187                        } // if
188                        break;
189                    }
190         
191                  default:
192                    // do nothing
193                    ;
194                }
195       
196                switch ( opInfo.type ) {
197                  case OT_INDEX:
198                    assert( applicationExpr->get_args().size() == 2 );
199                    (*arg++)->accept( *this );
200                    before << "[";
201                    (*arg)->accept( *this );
202                    before << "]";
203                    break;
204         
205                  case OT_CALL:
206                    // there are no intrinsic definitions of the function call operator
207                    assert( false );
208                    break;
209         
210                  case OT_PREFIX:
211                  case OT_PREFIXASSIGN:
212                    assert( applicationExpr->get_args().size() == 1 );
213                    before << "(";
214                    before << opInfo.symbol;
215                    (*arg)->accept( *this );
216                    before << ")";
217                    break;
218         
219                  case OT_POSTFIX:
220                  case OT_POSTFIXASSIGN:
221                    assert( applicationExpr->get_args().size() == 1 );
222                    (*arg)->accept( *this );
223                    before << opInfo.symbol;
224                    break;
225
226                  case OT_INFIX:
227                  case OT_INFIXASSIGN:
228                    assert( applicationExpr->get_args().size() == 2 );
229                    before << "(";
230                    (*arg++)->accept( *this );
231                    before << opInfo.symbol;
232                    (*arg)->accept( *this );
233                    before << ")";
234                    break;
235         
236                  case OT_CONSTANT:
237                    // there are no intrinsic definitions of 0 or 1 as functions
238                    assert( false );
239                }
240            } else {
241                varExpr->accept( *this );
242                before << "(";
243                genCommaList( applicationExpr->get_args().begin(), applicationExpr->get_args().end() );
244                before << ")";
245            } // if
246        } else {
247            applicationExpr->get_function()->accept( *this );
248            before << "(";
249            genCommaList( applicationExpr->get_args().begin(), applicationExpr->get_args().end() );
250            before << ")";
251        } // if
252    }
253 
254    void CodeGenerator2::visit( UntypedExpr *untypedExpr ) {
255        if ( NameExpr *nameExpr = dynamic_cast< NameExpr* >( untypedExpr->get_function() ) ) {
256            OperatorInfo opInfo;
257            if ( operatorLookup( nameExpr->get_name(), opInfo ) ) {
258                std::list< Expression* >::iterator arg = untypedExpr->get_args().begin();
259                switch ( opInfo.type ) {
260                  case OT_INDEX:
261                    assert( untypedExpr->get_args().size() == 2 );
262                    (*arg++)->accept( *this );
263                    before << "[";
264                    (*arg)->accept( *this );
265                    before << "]";
266                    break;
267         
268                  case OT_CALL:
269                    assert( false );
270                    break;
271         
272                  case OT_PREFIX:
273                  case OT_PREFIXASSIGN:
274                    assert( untypedExpr->get_args().size() == 1 );
275                    before << "(";
276                    before << opInfo.symbol;
277                    (*arg)->accept( *this );
278                    before << ")";
279                    break;
280         
281                  case OT_POSTFIX:
282                  case OT_POSTFIXASSIGN:
283                    assert( untypedExpr->get_args().size() == 1 );
284                    (*arg)->accept( *this );
285                    before << opInfo.symbol;
286                    break;
287 
288                  case OT_INFIX:
289                  case OT_INFIXASSIGN:
290                    assert( untypedExpr->get_args().size() == 2 );
291                    before << "(";
292                    (*arg++)->accept( *this );
293                    before << opInfo.symbol;
294                    (*arg)->accept( *this );
295                    before << ")";
296                    break;
297         
298                  case OT_CONSTANT:
299                    // there are no intrinsic definitions of 0 or 1 as functions
300                    assert( false );
301                }
302            } else {
303                nameExpr->accept( *this );
304                before << "(";
305                genCommaList( untypedExpr->get_args().begin(), untypedExpr->get_args().end() );
306                before << ")";
307            } // if
308        } else {
309            untypedExpr->get_function()->accept( *this );
310            before << "(";
311            genCommaList( untypedExpr->get_args().begin(), untypedExpr->get_args().end() );
312            before << ")";
313        } // if
314    }
315 
316    void CodeGenerator2::visit( NameExpr *nameExpr ) {
317        OperatorInfo opInfo;
318        if ( operatorLookup( nameExpr->get_name(), opInfo ) ) {
319            assert( opInfo.type == OT_CONSTANT );
320            before << opInfo.symbol;
321        } else {
322            before << nameExpr->get_name();
323        } // if
324    }
325 
326    void CodeGenerator2::visit( AddressExpr *addressExpr ) {
327        before << "(&";
328        // this hack makes sure that we don't convert "constant_zero" to "0" if we're taking its address
329        if ( VariableExpr *variableExpr = dynamic_cast< VariableExpr* >( addressExpr->get_arg() ) ) {
330            before << mangleName( variableExpr->get_var() );
331        } else {
332            addressExpr->get_arg()->accept( *this );
333        } // if
334        before << ")";
335    }
336
337    void CodeGenerator2::visit( CastExpr *castExpr ) {
338        before << "((";
339        if ( castExpr->get_results().empty() ) {
340            before << "void" ;
341        } else {
342            before << genType( castExpr->get_results().front(), "" );
343        } // if
344        before << ")";
345        castExpr->get_arg()->accept( *this );
346        before << ")";
347    }
348 
349    void CodeGenerator2::visit( UntypedMemberExpr *memberExpr ) {
350        assert( false );
351    }
352 
353    void CodeGenerator2::visit( MemberExpr *memberExpr ) {
354        memberExpr->get_aggregate()->accept( *this );
355        before << "." << mangleName( memberExpr->get_member() );
356    }
357 
358    void CodeGenerator2::visit( VariableExpr *variableExpr ) {
359        OperatorInfo opInfo;
360        if ( variableExpr->get_var()->get_linkage() == LinkageSpec::Intrinsic && operatorLookup( variableExpr->get_var()->get_name(), opInfo ) && opInfo.type == OT_CONSTANT ) {
361            before << opInfo.symbol;
362        } else {
363            before << mangleName( variableExpr->get_var() );
364        } // if
365    }
366 
367    void CodeGenerator2::visit( ConstantExpr *constantExpr ) {
368        assert( constantExpr->get_constant() );
369        constantExpr->get_constant()->accept( *this );
370    }
371 
372    void CodeGenerator2::visit( SizeofExpr *sizeofExpr ) {
373        before << "sizeof(";
374        if ( sizeofExpr->get_isType() ) {
375            before << genType( sizeofExpr->get_type(), "" );
376        } else {
377            sizeofExpr->get_expr()->accept( *this );
378        } // if
379        before << ")";
380    }
381 
382    void CodeGenerator2::visit( LogicalExpr *logicalExpr ) {
383        before << "(";
384        logicalExpr->get_arg1()->accept( *this );
385        if ( logicalExpr->get_isAnd() ) {
386            before << " && ";
387        } else {
388            before << " || ";
389        } // if
390        logicalExpr->get_arg2()->accept( *this );
391        before << ")";
392    }
393 
394    void CodeGenerator2::visit( ConditionalExpr *conditionalExpr ) {
395        before << "(";
396        conditionalExpr->get_arg1()->accept( *this );
397        before << " ? ";
398        conditionalExpr->get_arg2()->accept( *this );
399        before << " : ";
400        conditionalExpr->get_arg3()->accept( *this );
401        before << ")";
402    }
403 
404    void CodeGenerator2::visit( CommaExpr *commaExpr ) {
405        before << "(";
406        commaExpr->get_arg1()->accept( *this );
407        before << " , ";
408        commaExpr->get_arg2()->accept( *this );
409        before << ")";
410    }
411 
412    void CodeGenerator2::visit( TupleExpr *tupleExpr ) {}
413 
414    void CodeGenerator2::visit( TypeExpr *typeExpr ) {}
415 
416 
417    //*** Statements
418    void CodeGenerator2::visit( CompoundStmt *compoundStmt ) {
419        std::list<Statement*> ks = compoundStmt->get_kids();
420
421        before << endl << string( cur_indent, ' ' ) << "{" << endl;
422
423        cur_indent += CodeGenerator2::tabsize; 
424
425        for ( std::list<Statement *>::iterator i = ks.begin(); i != ks.end();  i++) {
426            before << string( cur_indent, ' ' ) << printLabels( (*i)->get_labels() )  ;
427            (*i)->accept(*this );
428            shift_left();
429            before << endl;
430        }
431        cur_indent -= CodeGenerator2::tabsize; 
432
433        before << string( cur_indent, ' ' ) << "}" << endl;
434    }
435
436    void CodeGenerator2::visit( ExprStmt *exprStmt ) {
437        if ( exprStmt != 0 ) {
438            exprStmt->get_expr()->accept( *this );
439            shift_left();
440            before << ";" ;
441        } // if
442    }
443
444    void CodeGenerator2::visit( IfStmt *ifStmt ) {
445        before << "if (";
446        ifStmt->get_condition()->accept(*this );
447        after += ")\n";
448        shift_left(); 
449
450        cur_indent += CodeGenerator2::tabsize;
451        before << string( cur_indent, ' ' );
452        ifStmt->get_thenPart()->accept(*this );
453        cur_indent -= CodeGenerator2::tabsize; 
454        shift_left(); before << endl;
455
456        if ( ifStmt->get_elsePart() != 0) {
457            before << string( cur_indent, ' ' ) << " else " << endl ;
458
459            cur_indent += CodeGenerator2::tabsize; 
460            ifStmt->get_elsePart()->accept(*this );
461            cur_indent -= CodeGenerator2::tabsize; 
462        } // if
463    }
464
465    void CodeGenerator2::visit( SwitchStmt *switchStmt ) {
466        //before << /* "\r" << */ string( cur_indent, ' ' ) << CodeGenerator2::printLabels( switchStmt->get_labels() )
467        before << "switch (" ;
468        switchStmt->get_condition()->accept(*this );
469        after += ")\n";
470        shift_left();
471
472        before << string( cur_indent, ' ' ) << "{" << std::endl;
473        cur_indent += CodeGenerator2::tabsize;
474
475        std::list< Statement * > stmts = switchStmt->get_branches();
476        bool lastBreak = false; 
477
478        // horrible, horrible hack
479        if ( dynamic_cast<BranchStmt *>( stmts.back() ) != 0 ) {
480            lastBreak = true;
481            stmts.pop_back();
482        } // if
483        acceptAll( stmts, *this );
484        if ( lastBreak ) {
485            Statement *st = switchStmt->get_branches().back();
486            before << CodeGenerator2::printLabels( st->get_labels());
487            st->accept( *this );
488        } // if
489     
490        cur_indent -= CodeGenerator2::tabsize; 
491
492        before << /* "\r" << */ string( cur_indent, ' ' ) << "}" << endl ;
493    }
494
495    void CodeGenerator2::visit( CaseStmt *caseStmt ) {
496        before << string( cur_indent, ' ' );
497        if ( caseStmt->isDefault()) 
498            before << "default "  ;
499        else {
500            before << "case "  ;
501            caseStmt->get_condition()->accept(*this );
502        } // if
503        after += ":\n";
504        shift_left();
505
506        std::list<Statement *> sts = caseStmt->get_statements();
507
508        cur_indent += CodeGenerator2::tabsize;
509        for ( std::list<Statement *>::iterator i = sts.begin(); i != sts.end();  i++) {
510            before << /* "\r" << */ string( cur_indent, ' ' ) << printLabels( (*i)->get_labels() )  ;
511            (*i)->accept(*this );
512            shift_left();
513            before << ";" << endl;
514        }
515        cur_indent -= CodeGenerator2::tabsize;
516    }
517
518    void CodeGenerator2::visit( BranchStmt *branchStmt ) {
519        switch ( branchStmt->get_type()) {
520          case BranchStmt::Goto:
521            if ( ! branchStmt->get_target().empty() )
522                before << "goto " << branchStmt->get_target();
523            else { 
524                if ( branchStmt->get_computedTarget() != 0 ) {
525                    before << "goto *";
526                    branchStmt->get_computedTarget()->accept( *this );
527                } // if
528            } // if
529            break;
530          case BranchStmt::Break:
531            before << "break";
532            break;
533          case BranchStmt::Continue:
534            before << "continue";
535            break;
536        }
537        before << ";";
538    }
539
540
541    void CodeGenerator2::visit( ReturnStmt *returnStmt ) {
542        before << "return ";
543
544        // xxx -- check for null expression;
545        if ( returnStmt->get_expr() ) {
546            returnStmt->get_expr()->accept( *this );
547        } // if
548        after += ";";
549    }
550
551    void CodeGenerator2::visit( WhileStmt *whileStmt ) {
552        if ( whileStmt->get_isDoWhile() )
553            before << "do" ;
554        else {
555            before << "while(" ;
556            whileStmt->get_condition()->accept(*this );
557            after += ")";
558        } // if
559        after += "{\n";
560        shift_left();
561
562        whileStmt->get_body()->accept( *this );
563
564        before << /* "\r" << */ string( cur_indent, ' ' ) << "}" ;
565
566        if ( whileStmt->get_isDoWhile() ) {
567            before << " while(" ;
568            whileStmt->get_condition()->accept(*this );
569            after += ");";
570        } // if
571
572        after += "\n";
573    }
574
575    void CodeGenerator2::visit( ForStmt *forStmt ) {
576        before << "for (";
577
578        if ( forStmt->get_initialization() != 0 )
579            forStmt->get_initialization()->accept( *this );
580        else
581            before << ";";
582        shift_left();
583
584        if ( forStmt->get_condition() != 0 )
585            forStmt->get_condition()->accept( *this );
586        shift_left(); before << ";";
587
588        if ( forStmt->get_increment() != 0 )
589            forStmt->get_increment()->accept( *this );
590        shift_left(); before << ")" << endl;
591
592        if ( forStmt->get_body() != 0 ) {
593            cur_indent += CodeGenerator2::tabsize; 
594            before << string( cur_indent, ' ' ) << CodeGenerator2::printLabels( forStmt->get_body()->get_labels() );
595            forStmt->get_body()->accept( *this );
596            cur_indent -= CodeGenerator2::tabsize; 
597        } // if
598    }
599
600    void CodeGenerator2::visit( NullStmt *nullStmt ) {
601        //before << /* "\r" << */ string( cur_indent, ' ' ) << CodeGenerator2::printLabels( nullStmt->get_labels() );
602        before << "/* null statement */ ;";
603    }
604
605    void CodeGenerator2::visit( DeclStmt *declStmt ) {
606        declStmt->get_decl()->accept( *this );
607   
608        if ( doSemicolon( declStmt->get_decl() ) ) {
609            after += ";";
610        } // if
611        shift_left();
612    }
613
614    std::string CodeGenerator2::printLabels( std::list< Label > &l ) {
615        std::string str( "" );
616        l.unique();
617
618        for ( std::list< Label >::iterator i = l.begin(); i != l.end(); i++ )
619            str += *i + ": ";
620
621        return str;
622    }
623
624    void CodeGenerator2::shift_left() {
625        before << after;
626        after = "";
627    }
628
629    void CodeGenerator2::handleStorageClass( Declaration *decl ) {
630        switch ( decl->get_storageClass() ) {
631          case Declaration::NoStorageClass:
632            break;
633          case Declaration::Extern:
634            before << "extern ";
635            break;
636          case Declaration::Static:
637            before << "static ";
638            break;
639          case Declaration::Auto:
640            // silently drop storage class
641            break;
642          case Declaration::Register:
643            before << "register ";
644            break;
645          case Declaration::Inline:
646            before << "inline ";
647            break;
648          case Declaration::Fortran:
649            before << "fortran ";
650            break;
651        }
652    }
653} // namespace CodeGen
Note: See TracBrowser for help on using the repository browser.