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