Inferno
0.2
|
00001 #include "tree/cpptree.hpp" 00002 #include "tree/sctree.hpp" 00003 #include "helpers/transformation.hpp" 00004 #include "tree/typeof.hpp" 00005 #include "common/trace.hpp" 00006 #include "common/read_args.hpp" 00007 #include "tree/type_db.hpp" 00008 #include "helpers/walk.hpp" 00009 #include "tree/misc.hpp" 00010 #include "tree/scope.hpp" 00011 #include "sort_decls.hpp" 00012 #include "render.hpp" 00013 #include "clang/Parse/DeclSpec.h" 00014 #include "uniquify_identifiers.hpp" 00015 00016 using namespace CPPTree; 00017 using namespace SCTree; 00018 00019 // Don't like the layout of rendered code? 00020 // Install "indent" on your UNIX box and pipe the output through iindent.sh 00021 00022 // TODO maybe reduce () by using a simplified scheme, ie divide operators into "high" and "low" 00023 // categories and elide on low(high()). Note that a full scheme makes code unreadable if 00024 // user does not have them memorised. Maybe just encode those priorities that are well known. 00025 00026 // TODO indent back to previous level at end of string 00027 #define ERROR_UNKNOWN(V) \ 00028 string( "\n#error " ) + \ 00029 string( V ) + \ 00030 string( " not supported in " ) + \ 00031 string( INFERNO_CURRENT_FUNCTION ) + \ 00032 string( "\n" ); 00033 00034 #define ERROR_UNSUPPORTED(P) \ 00035 ERROR_UNKNOWN( P ? typeid(*P).name() : "<NULL>" ); 00036 00037 00038 Render::Render( string of ) : 00039 outfile( of ) 00040 { 00041 } 00042 00043 00044 TreePtr<Node> Render::operator()( TreePtr<Node> context, TreePtr<Node> root ) 00045 { 00046 // Render can only work on a whole program 00047 ASSERT( context == root ); 00048 program = dynamic_pointer_cast<Program>(root); 00049 ASSERT( program ); 00050 AutoPush< TreePtr<Scope> > cs( scope_stack, program ); 00051 unique.clear(); 00052 unique.UniquifyScope( context ); 00053 00054 string s; 00055 00056 if( IsSystemC( root ) ) 00057 s += "#include \"isystemc.h\"\n\n"; 00058 00059 s += RenderDeclarationCollection( program, ";\n", true ); // gets the .hpp stuff directly 00060 00061 s += deferred_decls; // these could go in a .cpp file 00062 00063 if( outfile.empty() ) 00064 { 00065 puts( s.c_str() ); 00066 } 00067 else 00068 { 00069 FILE *fp = fopen( outfile.c_str(), "wt" ); 00070 ASSERT( fp )( "Cannot open output file \"%s\"", outfile.c_str() ); 00071 fputs( s.c_str(), fp ); 00072 fclose( fp ); 00073 } 00074 program = TreePtr<Program>(); 00075 return root; // no change 00076 } 00077 00078 00079 bool Render::IsSystemC( TreePtr<Node> root ) 00080 { 00081 Walk e(root); 00082 FOREACH( TreePtr<Node> n, e ) 00083 if( dynamic_pointer_cast<SCConstruct>(n) ) 00084 return true; 00085 return false; 00086 } 00087 00088 00089 string Render::RenderLiteral( TreePtr<Literal> sp ) 00090 { 00091 return Sanitise( *sp ); 00092 } 00093 00094 00095 string Render::RenderIdentifier( TreePtr<Identifier> id ) 00096 { 00097 string ids; 00098 if( id ) 00099 { 00100 if( TreePtr<SpecificIdentifier> ii = dynamic_pointer_cast<SpecificIdentifier>( id ) ) 00101 ids = unique[ii]; 00102 else 00103 ids = ERROR_UNSUPPORTED( (id) ); 00104 00105 TRACE( "%s\n", ids.c_str() ); 00106 } 00107 else 00108 { 00109 TRACE(); 00110 } 00111 return ids; 00112 } 00113 00114 00115 string Render::RenderScopePrefix( TreePtr<Identifier> id ) 00116 { 00117 TreePtr<Scope> scope = GetScope( program, id ); 00118 TRACE("%p %p %p\n", program.get(), scope.get(), scope_stack.top().get() ); 00119 if( scope == scope_stack.top() ) 00120 return string(); // local scope 00121 else if( scope == program ) 00122 return " ::"; 00123 else if( TreePtr<Enum> e = dynamic_pointer_cast<Enum>( scope ) ) // <- for enum 00124 return RenderScopePrefix( e->identifier ); // omit scope for the enum itself 00125 else if( TreePtr<Record> r = dynamic_pointer_cast<Record>( scope ) ) // <- for class, struct, union 00126 return RenderScopedIdentifier( r->identifier ) + "::"; 00127 else if( dynamic_pointer_cast<CallableParams>( scope ) || // <- this is for params 00128 dynamic_pointer_cast<Compound>( scope ) || // <- this is for locals in body 00129 dynamic_pointer_cast<CompoundExpression>( scope ) ) // <- this is for locals in body 00130 return string(); 00131 else 00132 return ERROR_UNSUPPORTED( scope ); 00133 } 00134 00135 00136 string Render::RenderScopedIdentifier( TreePtr<Identifier> id ) 00137 { 00138 string s = RenderScopePrefix( id ) + RenderIdentifier( id ); 00139 TRACE("Render scoped identifier %s\n", s.c_str() ); 00140 return s; 00141 } 00142 00143 00144 string Render::RenderIntegralType( TreePtr<Integral> type, string object ) 00145 { 00146 bool ds; 00147 unsigned width; 00148 TreePtr<SpecificInteger> ic = dynamic_pointer_cast<SpecificInteger>( type->width ); 00149 ASSERT(ic)("width must be integer"); 00150 width = ic->getLimitedValue(); 00151 00152 TRACE("width %d\n", width); 00153 00154 if( width == TypeDb::char_bits ) 00155 ds = TypeDb::char_default_signed; 00156 else 00157 ds = TypeDb::int_default_signed; 00158 00159 // Produce signed or unsigned if required 00160 // Note: literal strings can be converted to char * but not unsigned char * or signed char * 00161 string s; 00162 if( dynamic_pointer_cast< Signed >(type) && !ds ) 00163 s = "signed "; 00164 else if( dynamic_pointer_cast< Unsigned >(type) && ds ) 00165 s = "unsigned "; 00166 00167 // Fix the width 00168 bool bitfield = false; 00169 if( width == TypeDb::char_bits ) 00170 s += "char"; 00171 else if( width == TypeDb::integral_bits[clang::DeclSpec::TSW_unspecified] ) 00172 s += "int"; 00173 else if( width == TypeDb::integral_bits[clang::DeclSpec::TSW_short] ) 00174 s += "short"; 00175 else if( width == TypeDb::integral_bits[clang::DeclSpec::TSW_long] ) 00176 s += "long"; 00177 else if( width == TypeDb::integral_bits[clang::DeclSpec::TSW_longlong] ) 00178 s += "long long"; 00179 else // unmatched defaults to int for bitfields 00180 { 00181 s += "int"; 00182 bitfield = true; 00183 } 00184 00185 s += " " + object; 00186 00187 if( bitfield ) 00188 { 00189 char b[100]; 00190 sprintf(b, ":%d", width); 00191 s += b; 00192 } 00193 00194 return s; 00195 } 00196 00197 00198 string Render::RenderFloatingType( TreePtr<Floating> type ) 00199 { 00200 string s; 00201 TreePtr<SpecificFloatSemantics> sem = dynamic_pointer_cast<SpecificFloatSemantics>(type->semantics); 00202 ASSERT(sem); 00203 00204 if( &(const llvm::fltSemantics &)*sem == TypeDb::float_semantics ) 00205 s += "float"; 00206 else if( &(const llvm::fltSemantics &)*sem == TypeDb::double_semantics ) 00207 s += "double"; 00208 else if( &(const llvm::fltSemantics &)*sem == TypeDb::long_double_semantics ) 00209 s += "long double"; 00210 else 00211 ASSERT(0)("no builtin floating type has required semantics"); // TODO drop in a bit vector 00212 00213 return s; 00214 } 00215 00216 00217 string Render::RenderType( TreePtr<Type> type, string object, bool constant ) 00218 { 00219 string sobject; 00220 if( !object.empty() ) 00221 sobject = " " + object; 00222 00223 string const_str = constant?"const ":""; 00224 00225 TRACE(); 00226 if( TreePtr<Integral> i = dynamic_pointer_cast< Integral >(type) ) 00227 return const_str + RenderIntegralType( i, object ); 00228 if( TreePtr<Floating> f = dynamic_pointer_cast< Floating >(type) ) 00229 return const_str + RenderFloatingType( f ) + sobject; 00230 else if( dynamic_pointer_cast< Void >(type) ) 00231 return const_str + "void" + sobject; 00232 else if( dynamic_pointer_cast< Boolean >(type) ) 00233 return const_str + "bool" + sobject; 00234 else if( TreePtr<Constructor> c = dynamic_pointer_cast< Constructor >(type) ) 00235 return object + "(" + RenderDeclarationCollection(c, ", ", false) + ")" + const_str; 00236 else if( TreePtr<Destructor> f = dynamic_pointer_cast< Destructor >(type) ) 00237 return object + "()" + const_str; 00238 else if( TreePtr<Function> f = dynamic_pointer_cast< Function >(type) ) 00239 return RenderType( f->return_type, "(" + object + ")(" + RenderDeclarationCollection(f, ", ", false) + ")" + const_str ); 00240 else if( TreePtr<Process> f = dynamic_pointer_cast< Process >(type) ) 00241 return "void " + object + "()" + const_str; 00242 else if( TreePtr<Pointer> p = dynamic_pointer_cast< Pointer >(type) ) 00243 return RenderType( p->destination, const_str + "(*" + object + ")", false ); // TODO Pointer node to indicate constancy of pointed-to object - would go into this call to RenderType 00244 else if( TreePtr<Reference> r = dynamic_pointer_cast< Reference >(type) ) 00245 return RenderType( r->destination, const_str + "(&" + object + ")" ); 00246 else if( TreePtr<Array> a = dynamic_pointer_cast< Array >(type) ) 00247 return RenderType( a->element, object.empty() ? "[" + RenderExpression(a->size) + "]" : "(" + object + "[" + RenderExpression(a->size) + "])", constant ); 00248 else if( TreePtr<Typedef> t = dynamic_pointer_cast< Typedef >(type) ) 00249 return const_str + RenderIdentifier(t->identifier) + sobject; 00250 else if( TreePtr<SpecificTypeIdentifier> ti = dynamic_pointer_cast< SpecificTypeIdentifier >(type) ) 00251 return const_str + RenderScopedIdentifier(ti) + sobject; 00252 else if( shared_ptr<SCNamedIdentifier> sct = dynamic_pointer_cast< SCNamedIdentifier >(type) ) 00253 return const_str + sct->GetToken() + sobject; 00254 else if( dynamic_pointer_cast<Labeley>(type) ) 00255 return const_str + "void *" + object; 00256 else 00257 return ERROR_UNSUPPORTED(type); 00258 } 00259 00260 00261 // Insert escapes into a string so it can be put in source code 00262 // TODO use \n \r etc and let printable ascii through 00263 string Render::Sanitise( string s ) 00264 { 00265 string o; 00266 for( int i=0; i<s.size(); i++ ) 00267 { 00268 char c[10]; 00269 if( s[i] < ' ' ) 00270 o += SSPrintf( c, "\\x%02x", s[i] ); 00271 else 00272 o += s[i]; 00273 } 00274 return o; 00275 } 00276 00277 00278 string Render::RenderOperator( TreePtr<Operator> op, Sequence<Expression> &operands ) 00279 { 00280 ASSERT(op); 00281 if( dynamic_pointer_cast< MakeArray >(op) ) 00282 return "{ " + RenderOperandSequence( operands, ", ", false ) + " }"; 00283 else if( dynamic_pointer_cast< Multiplexor >(op) ) 00284 return RenderExpression( operands[0], true ) + " ? " + 00285 RenderExpression( operands[1], true ) + " : " + 00286 RenderExpression( operands[2], true ); 00287 else if( dynamic_pointer_cast< Subscript >(op) ) 00288 return RenderExpression( operands[0], true ) + "[" + 00289 RenderExpression( operands[1], false ) + "]"; 00290 #define INFIX(TOK, TEXT, NODE, BASE, CAT) \ 00291 else if( dynamic_pointer_cast<NODE>(op) ) \ 00292 return RenderExpression( operands[0], true ) +\ 00293 TEXT +\ 00294 RenderExpression( operands[1], true ); 00295 #define PREFIX(TOK, TEXT, NODE, BASE, CAT) \ 00296 else if( dynamic_pointer_cast<NODE>(op) ) \ 00297 return TEXT +\ 00298 RenderExpression( operands[0], true ); 00299 #define POSTFIX(TOK, TEXT, NODE, BASE, CAT) \ 00300 else if( dynamic_pointer_cast<NODE>(op) ) \ 00301 return RenderExpression( operands[0], true ) +\ 00302 TEXT; 00303 #include "tree/operator_db.inc" 00304 else 00305 return ERROR_UNSUPPORTED(op); 00306 } 00307 00308 00309 string Render::RenderCall( TreePtr<Call> call ) 00310 { 00311 string s; 00312 00313 // Render the expression that resolves to the function name unless this is 00314 // a constructor call in which case just the name of the thing being constructed. 00315 if( TreePtr<Expression> base = TypeOf::instance.IsConstructorCall( program, call ) ) 00316 s += RenderExpression( base, true ); 00317 else 00318 s += RenderExpression( call->callee, true ); 00319 00320 s += "("; 00321 00322 // If CallableParams, generate some arguments, resolving the order using the original function type 00323 TreePtr<Node> ctype = TypeOf::instance( program, call->callee ); 00324 ASSERT( ctype ); 00325 if( TreePtr<CallableParams> cp = dynamic_pointer_cast<CallableParams>(ctype) ) 00326 s += RenderMapInOrder( call, cp, ", ", false ); 00327 00328 s += ")"; 00329 return s; 00330 } 00331 00332 00333 string Render::RenderExpression( TreePtr<Initialiser> expression, bool bracketize_operator ) 00334 { 00335 TRACE("%p\n", expression.get()); 00336 00337 string before = bracketize_operator ? "(" : ""; 00338 string after = bracketize_operator ? ")" : ""; 00339 00340 if( dynamic_pointer_cast< Uninitialised >(expression) ) 00341 return string(); 00342 else if( TreePtr<CompoundExpression> ce = dynamic_pointer_cast< CompoundExpression >(expression) ) 00343 { 00344 AutoPush< TreePtr<Scope> > cs( scope_stack, ce ); 00345 string s = "({ "; 00346 s += RenderDeclarationCollection( ce, "; ", true ); // Must do this first to populate backing list 00347 s += RenderSequence( ce->statements, "; ", true ); 00348 return s + "})"; 00349 } 00350 else if( TreePtr<SpecificLabelIdentifier> li = dynamic_pointer_cast< SpecificLabelIdentifier >(expression) ) 00351 return before + 00352 "&&" + RenderIdentifier( li ) + // label-as-variable (GCC extension) 00353 after; 00354 else if( TreePtr<InstanceIdentifier> ii = dynamic_pointer_cast< InstanceIdentifier >(expression) ) 00355 return RenderScopedIdentifier( ii ); 00356 else if( TreePtr<SizeOf> pot = dynamic_pointer_cast< SizeOf >(expression) ) 00357 return before + 00358 "sizeof(" + RenderType( pot->operand, "" ) + ")" + 00359 after; 00360 else if( TreePtr<AlignOf> pot = dynamic_pointer_cast< AlignOf >(expression) ) 00361 return before + 00362 "alignof(" + RenderType( pot->operand, "" ) + ")" + 00363 after; 00364 else if( TreePtr<NonCommutativeOperator> nco = dynamic_pointer_cast< NonCommutativeOperator >(expression) ) 00365 return before + 00366 RenderOperator( nco, nco->operands ) + 00367 after; 00368 else if( TreePtr<CommutativeOperator> co = dynamic_pointer_cast< CommutativeOperator >(expression) ) 00369 { 00370 Sequence<Expression> seq_operands; 00371 // Operands are in collection, so move them to a container 00372 FOREACH( TreePtr<Expression> o, co->operands ) 00373 seq_operands.push_back( o ); 00374 return before + 00375 RenderOperator( co, seq_operands ) + 00376 after; 00377 } 00378 else if( TreePtr<Call> c = dynamic_pointer_cast< Call >(expression) ) 00379 return before + 00380 RenderCall( c ) + 00381 after; 00382 else if( TreePtr<New> n = dynamic_pointer_cast< New >(expression) ) 00383 return before + 00384 (dynamic_pointer_cast<Global>(n->global) ? "::" : "") + 00385 "new(" + RenderOperandSequence( n->placement_arguments, ", ", false ) + ") " + 00386 RenderType( n->type, "" ) + 00387 (n->constructor_arguments.empty() ? "" : "(" + RenderOperandSequence( n->constructor_arguments, ", ", false ) + ")" ) + 00388 after; 00389 else if( TreePtr<Delete> d = dynamic_pointer_cast< Delete >(expression) ) 00390 return before + 00391 (dynamic_pointer_cast<Global>(d->global) ? "::" : "") + 00392 "delete" + 00393 (dynamic_pointer_cast<DeleteArray>(d->array) ? "[]" : "") + 00394 " " + RenderExpression( d->pointer, true ) + 00395 after; 00396 else if( TreePtr<Lookup> a = dynamic_pointer_cast< Lookup >(expression) ) 00397 return before + 00398 RenderExpression( a->base, true ) + "." + 00399 RenderScopedIdentifier( a->member ) + 00400 after; 00401 else if( TreePtr<Cast> c = dynamic_pointer_cast< Cast >(expression) ) 00402 return before + 00403 "(" + RenderType( c->type, "" ) + ")" + 00404 RenderExpression( c->operand, false ) + 00405 after; 00406 else if( TreePtr<MakeRecord> ro = dynamic_pointer_cast< MakeRecord >(expression) ) 00407 return before + 00408 RenderMakeRecord( ro ) + 00409 after; 00410 else if( TreePtr<Literal> l = dynamic_pointer_cast< Literal >(expression) ) 00411 return before + 00412 RenderLiteral( l ) + 00413 after; 00414 else if( dynamic_pointer_cast< This >(expression) ) 00415 return before + 00416 "this" + 00417 after; 00418 else if( TreePtr<DeltaCount> dc = dynamic_pointer_cast<DeltaCount>(expression) ) 00419 return before + 00420 dc->GetToken() + "()" + 00421 after; 00422 else 00423 return ERROR_UNSUPPORTED(expression); 00424 } 00425 00426 00427 string Render::RenderMakeRecord( TreePtr<MakeRecord> ro ) 00428 { 00429 string s; 00430 00431 // Get the record 00432 TreePtr<TypeIdentifier> id = dynamic_pointer_cast<TypeIdentifier>(ro->type); 00433 ASSERT(id); 00434 TreePtr<Record> r = GetRecordDeclaration(program, id); 00435 00436 s += "("; 00437 s += RenderType( ro->type, "" ); 00438 s += "){ "; 00439 s += RenderMapInOrder( ro, r, ", ", false ); 00440 s += " }"; 00441 return s; 00442 } 00443 00444 00445 string Render::RenderMapInOrder( TreePtr<MapOperator> ro, 00446 TreePtr<Scope> r, 00447 string separator, 00448 bool separate_last ) 00449 { 00450 string s; 00451 00452 // Get a reference to the ordered list of members for this record from a backing list 00453 if( !backing_ordering.IsExist( r ) ) 00454 { 00455 TRACE("Needed to see ")(*r)(" before ")(*ro)(" so map may not match; sorting now\n"); 00456 backing_ordering[r] = SortDecls( r->members, true ); 00457 } 00458 ASSERT( backing_ordering.IsExist( r ) ); 00459 Sequence<Declaration> &sd = backing_ordering[r]; 00460 ASSERT( sd.size() == r->members.size() ); 00461 bool first = true; 00462 FOREACH( TreePtr<Declaration> d, sd ) 00463 { 00464 // We only care about instances... 00465 if( TreePtr<Instance> i = dynamic_pointer_cast<Instance>( d ) ) 00466 { 00467 // ...and not function instances 00468 if( !dynamic_pointer_cast<Callable>( i->type ) ) 00469 { 00470 // search init for matching member (TODO could avoid O(n^2) by exploiting the map) 00471 FOREACH( TreePtr<MapOperand> mi, ro->operands ) 00472 { 00473 if( i->identifier == mi->identifier ) 00474 { 00475 if( !first ) 00476 s += separator; 00477 s += RenderExpression( mi->value ); 00478 first = false; 00479 } 00480 } 00481 } 00482 } 00483 if( separate_last ) 00484 s += separator; 00485 } 00486 return s; 00487 } 00488 00489 00490 string Render::RenderAccess( TreePtr<AccessSpec> current_access ) 00491 { 00492 if( dynamic_pointer_cast<Public>( current_access ) ) 00493 return "public"; 00494 else if( dynamic_pointer_cast<Private>( current_access ) ) 00495 return "private"; 00496 else if( dynamic_pointer_cast<Protected>( current_access ) ) 00497 return "protected"; 00498 else 00499 return ERROR_UNKNOWN("current_access spec"); 00500 } 00501 00502 00503 string Render::RenderStorage( TreePtr<Instance> st ) 00504 { 00505 if( dynamic_pointer_cast<Program>( scope_stack.top() ) ) 00506 return ""; // at top-level scope, everything is set to static, but don't actually output the word 00507 else if( dynamic_pointer_cast<Static>( st ) ) 00508 return "static "; 00509 else if( dynamic_pointer_cast<Automatic>( st ) ) 00510 return "auto "; 00511 else if( dynamic_pointer_cast<Temporary>( st ) ) 00512 return "/*temp*/ "; 00513 else if( TreePtr<Field> no = dynamic_pointer_cast<Field>( st ) ) 00514 { 00515 TreePtr<Virtuality> v = no->virt; 00516 if( dynamic_pointer_cast<Virtual>( v ) ) 00517 return "virtual "; 00518 else if( dynamic_pointer_cast<NonVirtual>( v ) ) 00519 return ""; 00520 else 00521 return ERROR_UNKNOWN("virtualness"); 00522 } 00523 else 00524 return ERROR_UNKNOWN("storage class"); 00525 } 00526 00527 00528 void Render::ExtractInits( Sequence<Statement> &body, Sequence<Statement> &inits, Sequence<Statement> &remainder ) 00529 { 00530 FOREACH( TreePtr<Statement> s, body ) 00531 { 00532 if( TreePtr<Call> o = dynamic_pointer_cast< Call >(s) ) 00533 { 00534 if( TypeOf::instance.IsConstructorCall( program, o ) ) 00535 { 00536 inits.push_back(s); 00537 continue; 00538 } 00539 } 00540 remainder.push_back(s); 00541 } 00542 } 00543 00544 00545 string Render::RenderInstance( TreePtr<Instance> o, string sep, bool showtype, 00546 bool showstorage, bool showinit, bool showscope ) 00547 { 00548 string s; 00549 string name; 00550 bool constant=false; 00551 00552 ASSERT(o->type); 00553 00554 if( TreePtr<Static> st = dynamic_pointer_cast<Static>(o) ) 00555 if( dynamic_pointer_cast<Const>(st->constancy) ) 00556 constant = true; 00557 if( TreePtr<Field> f = dynamic_pointer_cast<Field>(o) ) 00558 if( dynamic_pointer_cast<Const>(f->constancy) ) 00559 constant = true; 00560 00561 if( showstorage ) 00562 { 00563 s += RenderStorage(o); 00564 } 00565 00566 if( showscope ) 00567 name += RenderScopePrefix(o->identifier); 00568 00569 TreePtr<Constructor> con = dynamic_pointer_cast<Constructor>(o->type); 00570 TreePtr<Destructor> de = dynamic_pointer_cast<Destructor>(o->type); 00571 if( con || de ) 00572 { 00573 TreePtr<Record> rec = dynamic_pointer_cast<Record>( GetScope( program, o->identifier ) ); 00574 ASSERT( rec ); 00575 name += (de ? "~" : ""); 00576 name += RenderIdentifier(rec->identifier); 00577 } 00578 else 00579 { 00580 name += RenderIdentifier(o->identifier); 00581 } 00582 00583 if( showtype ) 00584 s += RenderType( o->type, name, constant ); 00585 else 00586 s = name; 00587 00588 bool callable = dynamic_pointer_cast<Callable>(o->type); 00589 00590 // If object is really a module, bodge in a name as a constructor parameter 00591 // But not for fields - they need an init list, done in RenderDeclarationCollection() 00592 if( !dynamic_pointer_cast<Field>(o) ) 00593 if( TreePtr<TypeIdentifier> tid = dynamic_pointer_cast<TypeIdentifier>(o->type) ) 00594 if( TreePtr<Record> r = GetRecordDeclaration(program, tid) ) 00595 if( dynamic_pointer_cast<Module>(r) ) 00596 { 00597 s += "(\"" + RenderIdentifier(o->identifier) + "\")" + sep; 00598 return s; 00599 } 00600 00601 if( !showinit || dynamic_pointer_cast<Uninitialised>(o->initialiser) ) 00602 { 00603 // Don't render any initialiser 00604 s += sep; 00605 } 00606 else if( callable ) 00607 { 00608 // Establish the scope of the function 00609 AutoPush< TreePtr<Scope> > cs( scope_stack, GetScope( program, o->identifier ) ); 00610 00611 // Put the contents of the body into a Compound-like form even if there's only one 00612 // Statement there - this is because we will wrangle with them later 00613 Sequence<Statement> code; 00614 Collection<Declaration> members; 00615 if( TreePtr<Compound> comp = dynamic_pointer_cast<Compound>(o->initialiser) ) 00616 { 00617 members = comp->members; 00618 code = comp->statements; 00619 } 00620 else if( TreePtr<Statement> st = dynamic_pointer_cast<Statement>(o->initialiser) ) 00621 code.push_back( st ); 00622 else 00623 s += ERROR_UNSUPPORTED(o->initialiser); 00624 00625 // Seperate the statements into constructor initialisers and "other stuff" 00626 Sequence<Statement> inits; 00627 Sequence<Statement> remainder; 00628 ExtractInits( code, inits, remainder ); 00629 00630 // Render the constructor initialisers if there are any 00631 if( !inits.empty() ) 00632 { 00633 s += " : "; 00634 s += RenderSequence( inits, ", ", false, TreePtr<Public>(), true ); 00635 } 00636 00637 // Render the other stuff as a Compound so we always get {} in all cases 00638 TreePtr<Compound> r( new Compound ); 00639 r->members = members; 00640 r->statements = remainder; 00641 s += "\n" + RenderStatement(r, ""); 00642 } 00643 else 00644 { 00645 if( TreePtr<Expression> ei = dynamic_pointer_cast<Expression>( o->initialiser ) ) 00646 { 00647 // Render expression with an assignment 00648 AutoPush< TreePtr<Scope> > cs( scope_stack, GetScope( program, o->identifier ) ); 00649 s += " = " + RenderExpression(ei) + sep; 00650 } 00651 else 00652 { 00653 s += ERROR_UNSUPPORTED(o->initialiser); 00654 } 00655 } 00656 00657 return s; 00658 } 00659 00660 00661 // Non-const static objects in records and functions 00662 // get split into a part that goes into the record (main line of rendering) and 00663 // a part that goes separately (deferred_decls gets appended at the very end). 00664 // Do all functions, since SortDecls() ignores function bodies for dep analysis 00665 bool Render::ShouldSplitInstance( TreePtr<Instance> o ) 00666 { 00667 bool isfunc = !!dynamic_pointer_cast<Callable>( o->type ); 00668 bool isnumber = !!dynamic_pointer_cast<Numeric>( o->type ); 00669 if( TreePtr<TypeIdentifier> ti = dynamic_pointer_cast<TypeIdentifier>(o->type) ) 00670 if( dynamic_pointer_cast<Enum>( GetRecordDeclaration(program, ti) ) ) 00671 isnumber = 1; // enum is like a number 00672 bool split_var = false; 00673 if( TreePtr<Static> s = dynamic_pointer_cast<Static>(o) ) 00674 if( dynamic_pointer_cast<NonConst>(s->constancy) || !isnumber ) 00675 split_var = true; 00676 return ( dynamic_pointer_cast<Record>( scope_stack.top() ) && 00677 split_var ) || 00678 isfunc; 00679 } 00680 00681 00682 string Render::RenderDeclaration( TreePtr<Declaration> declaration, 00683 string sep, TreePtr<AccessSpec> *current_access, 00684 bool showtype, bool force_incomplete ) 00685 { 00686 TRACE(); 00687 string s; 00688 00689 TreePtr<AccessSpec> this_access; 00690 00691 // Decide access spec for this declaration (explicit if instance, otherwise force to Public) 00692 if( TreePtr<Field> f = dynamic_pointer_cast<Field>(declaration) ) 00693 this_access = f->access; 00694 else 00695 this_access = MakeTreePtr<Public>(); 00696 00697 // Now decide whether we actually need to render an access spec (ie has it changed?) 00698 if( current_access && // NULL means dont ever render access specs 00699 typeid(*this_access) != typeid(**current_access) ) // current_access spec must have changed 00700 { 00701 s += RenderAccess( this_access ) + ":\n"; 00702 *current_access = this_access; 00703 } 00704 00705 if( TreePtr<Instance> o = dynamic_pointer_cast<Instance>(declaration) ) 00706 { 00707 if( ShouldSplitInstance(o) ) 00708 { 00709 s += RenderInstance( o, sep, showtype, showtype, false, false ); 00710 { 00711 AutoPush< TreePtr<Scope> > cs( scope_stack, program ); 00712 deferred_decls += string("\n") + RenderInstance( o, sep, showtype, false, true, true ); 00713 } 00714 } 00715 else 00716 { 00717 // Otherwise, render everything directly using the default settings 00718 s += RenderInstance( o, sep, showtype, showtype, true, false ); 00719 } 00720 } 00721 else if( TreePtr<Typedef> t = dynamic_pointer_cast< Typedef >(declaration) ) 00722 { 00723 s += "typedef " + RenderType( t->type, RenderIdentifier(t->identifier) ) + sep; 00724 } 00725 else if( TreePtr<Record> r = dynamic_pointer_cast< Record >(declaration) ) 00726 { 00727 TreePtr<AccessSpec> a; 00728 bool showtype=true; 00729 string sep2=";\n"; 00730 shared_ptr<SCNamedRecord> scr = dynamic_pointer_cast< SCNamedRecord >(r); 00731 if( dynamic_pointer_cast< Class >(r) || scr ) 00732 { 00733 s += "class"; 00734 a = TreePtr<Private>(new Private); 00735 } 00736 else if( dynamic_pointer_cast< Struct >(r) ) 00737 { 00738 s += "struct"; 00739 a = TreePtr<Public>(new Public); 00740 } 00741 else if( dynamic_pointer_cast< Union >(r) ) 00742 { 00743 s += "union"; 00744 a = TreePtr<Public>(new Public); 00745 } 00746 else if( dynamic_pointer_cast< Enum >(r) ) 00747 { 00748 s += "enum"; 00749 a = TreePtr<Public>(new Public); 00750 sep2 = ",\n"; 00751 showtype = false; 00752 } 00753 else 00754 return ERROR_UNSUPPORTED(declaration); 00755 00756 // Name of the record 00757 s += " " + RenderIdentifier(r->identifier); 00758 00759 if( !force_incomplete ) 00760 { 00761 // Base classes 00762 if( TreePtr<InheritanceRecord> ir = dynamic_pointer_cast< InheritanceRecord >(declaration) ) 00763 { 00764 if( !ir->bases.empty() || scr ) 00765 { 00766 s += " : "; 00767 bool first=true; 00768 if( scr ) 00769 { 00770 first = false; 00771 s += "public " + scr->GetToken(); 00772 } 00773 FOREACH( TreePtr<Base> b, ir->bases ) 00774 { 00775 if( !first ) 00776 s += ", "; 00777 first=false; 00778 ASSERT( b ); 00779 s += RenderAccess(b->access) + " " /*+ RenderStorage(b->storage)*/ + RenderIdentifier(b->record); 00780 } 00781 } 00782 } 00783 00784 // Contents 00785 AutoPush< TreePtr<Scope> > cs( scope_stack, r ); 00786 s += "\n{\n" + 00787 RenderDeclarationCollection( r, sep2, true, a, showtype ) + 00788 "}"; 00789 } 00790 00791 s += ";\n"; 00792 } 00793 else if( TreePtr<Label> l = dynamic_pointer_cast<Label>(declaration) ) 00794 return RenderIdentifier(l->identifier) + ":;\n"; // need ; after a label in case last in compound block 00795 else 00796 s += ERROR_UNSUPPORTED(declaration); 00797 00798 TRACE(); 00799 return s; 00800 } 00801 00802 00803 string Render::RenderStatement( TreePtr<Statement> statement, string sep ) 00804 { 00805 TRACE(); 00806 if( !statement ) 00807 return sep; 00808 //printf( "%s %d things\n", typeid(*statement).name(), statement->Itemise().size() ); 00809 if( TreePtr<Declaration> d = dynamic_pointer_cast< Declaration >(statement) ) 00810 return RenderDeclaration( d, sep ); 00811 else if( TreePtr<Compound> c = dynamic_pointer_cast< Compound >(statement) ) 00812 { 00813 AutoPush< TreePtr<Scope> > cs( scope_stack, c ); 00814 string s = "{\n"; 00815 s += RenderDeclarationCollection( c, ";\n", true ); // Must do this first to populate backing list 00816 s += RenderSequence( c->statements, ";\n", true ); 00817 return s + "}\n"; 00818 } 00819 else if( TreePtr<Expression> e = dynamic_pointer_cast< Expression >(statement) ) 00820 return RenderExpression(e) + sep; 00821 else if( TreePtr<Return> es = dynamic_pointer_cast<Return>(statement) ) 00822 return "return " + RenderExpression(es->return_value) + sep; 00823 else if( TreePtr<Goto> g = dynamic_pointer_cast<Goto>(statement) ) 00824 { 00825 if( TreePtr<SpecificLabelIdentifier> li = dynamic_pointer_cast< SpecificLabelIdentifier >(g->destination) ) 00826 return "goto " + RenderIdentifier(li) + sep; // regular goto 00827 else 00828 return "goto *(" + RenderExpression(g->destination) + ")" + sep; // goto-a-variable (GCC extension) 00829 } 00830 else if( TreePtr<If> i = dynamic_pointer_cast<If>(statement) ) 00831 { 00832 string s; 00833 s += "if( " + RenderExpression(i->condition) + " )\n"; 00834 bool sub_if = !!dynamic_pointer_cast<If>(i->body); 00835 if( sub_if ) 00836 s += "{\n"; // Note: braces there to clarify else binding eg if(a) if(b) foo; else how_do_i_bind; 00837 s += RenderStatement(i->body, ";\n"); 00838 if( sub_if ) 00839 s += "}\n"; 00840 if( !dynamic_pointer_cast<Nop>(i->else_body) ) // Nop means no else clause 00841 s += "else\n" + 00842 RenderStatement(i->else_body, ";\n"); 00843 return s; 00844 } 00845 else if( TreePtr<While> w = dynamic_pointer_cast<While>(statement) ) 00846 return "while( " + RenderExpression(w->condition) + " )\n" + 00847 RenderStatement(w->body, ";\n"); 00848 else if( TreePtr<Do> d = dynamic_pointer_cast<Do>(statement) ) 00849 return "do\n" + 00850 RenderStatement(d->body, ";\n") + 00851 "while( " + RenderExpression(d->condition) + " )" + sep; 00852 else if( TreePtr<For> f = dynamic_pointer_cast<For>(statement) ) 00853 return "for( " + RenderStatement(f->initialisation, "") + "; " + RenderExpression(f->condition) + "; "+ RenderStatement(f->increment, "") + " )\n" + 00854 RenderStatement(f->body, ";\n"); 00855 else if( TreePtr<Switch> s = dynamic_pointer_cast<Switch>(statement) ) 00856 return "switch( " + RenderExpression(s->condition) + " )\n" + 00857 RenderStatement(s->body, ";\n"); 00858 else if( TreePtr<Case> c = dynamic_pointer_cast<Case>(statement) ) 00859 return "case " + RenderExpression(c->value) + ":;\n"; 00860 else if( TreePtr<RangeCase> rc = dynamic_pointer_cast<RangeCase>(statement) ) 00861 return "case " + RenderExpression(rc->value_lo) + " ... " + RenderExpression(rc->value_hi) + ":\n"; 00862 else if( dynamic_pointer_cast<Default>(statement) ) 00863 return "default:;\n"; 00864 else if( dynamic_pointer_cast<Continue>(statement) ) 00865 return "continue" + sep; 00866 else if( dynamic_pointer_cast<Break>(statement) ) 00867 return "break" + sep; 00868 else if( dynamic_pointer_cast<Nop>(statement) ) 00869 return sep; 00870 else if( TreePtr<WaitDynamic> c = dynamic_pointer_cast<WaitDynamic>(statement) ) 00871 return c->GetToken() + "( " + RenderExpression(c->event) + " );\n"; 00872 else if( TreePtr<WaitStatic> c = dynamic_pointer_cast<WaitStatic>(statement) ) 00873 return c->GetToken() + "();\n"; 00874 else if( TreePtr<WaitDelta> c = dynamic_pointer_cast<WaitDelta>(statement) ) 00875 return c->GetToken() + "(SC_ZERO_TIME);\n"; 00876 else if( TreePtr<NextTriggerDynamic> c = dynamic_pointer_cast<NextTriggerDynamic>(statement) ) 00877 return c->GetToken() + "( " + RenderExpression(c->event) + " );\n"; 00878 else if( TreePtr<NextTriggerStatic> c = dynamic_pointer_cast<NextTriggerStatic>(statement) ) 00879 return c->GetToken() + "();\n"; 00880 else if( TreePtr<NextTriggerDelta> c = dynamic_pointer_cast<NextTriggerDelta>(statement) ) 00881 return c->GetToken() + "(SC_ZERO_TIME);\n"; 00882 else if( TreePtr<TerminationFunction> tf = dynamic_pointer_cast<TerminationFunction>(statement) ) 00883 return tf->GetToken() + "( " + RenderExpression(tf->code) + " );\n"; 00884 else if( TreePtr<NotifyImmediate> n = dynamic_pointer_cast<NotifyImmediate>(statement) ) 00885 return RenderExpression( n->event, true ) + "." + n->GetToken() + "();\n"; 00886 else if( TreePtr<NotifyDelta> n = dynamic_pointer_cast<NotifyDelta>(statement) ) 00887 return RenderExpression( n->event, true ) + "." + n->GetToken() + "(SC_ZERO_TIME);\n"; 00888 else 00889 return ERROR_UNSUPPORTED(statement); 00890 } 00891 00892 00893 template< class ELEMENT > 00894 string Render::RenderSequence( Sequence<ELEMENT> spe, 00895 string separator, 00896 bool separate_last, 00897 TreePtr<AccessSpec> init_access, 00898 bool showtype ) 00899 { 00900 TRACE(); 00901 string s; 00902 for( int i=0; i<spe.size(); i++ ) 00903 { 00904 TRACE("%d %p\n", i, &i); 00905 string sep = (separate_last || i+1<spe.size()) ? separator : ""; 00906 TreePtr<ELEMENT> pe = spe[i]; 00907 if( TreePtr<Declaration> d = dynamic_pointer_cast< Declaration >(pe) ) 00908 s += RenderDeclaration( d, sep, init_access ? &init_access : NULL, showtype ); 00909 else if( TreePtr<Statement> st = dynamic_pointer_cast< Statement >(pe) ) 00910 s += RenderStatement( st, sep ); 00911 else 00912 s += ERROR_UNSUPPORTED(pe); 00913 } 00914 return s; 00915 } 00916 00917 00918 string Render::RenderOperandSequence( Sequence<Expression> spe, 00919 string separator, 00920 bool separate_last ) 00921 { 00922 TRACE(); 00923 string s; 00924 for( int i=0; i<spe.size(); i++ ) 00925 { 00926 TRACE("%d %p\n", i, &i); 00927 string sep = (separate_last || i+1<spe.size()) ? separator : ""; 00928 TreePtr<Expression> pe = spe[i]; 00929 s += RenderExpression( pe ) + sep; 00930 } 00931 return s; 00932 } 00933 00934 00935 string Render::RenderModuleCtor( TreePtr<Module> m, 00936 TreePtr<AccessSpec> *access ) 00937 { 00938 string s; 00939 00940 // SystemC module, we must produce a constructor in SC style, do this as inline 00941 if( !dynamic_pointer_cast<Public>(*access) ) 00942 { 00943 s += "public:\n"; 00944 *access = MakeTreePtr<Public>();// note that we left the access as public 00945 } 00946 s += "SC_CTOR( " + RenderIdentifier( m->identifier ) + " )"; 00947 int first = true; 00948 FOREACH( TreePtr<Declaration> pd, m->members ) 00949 { 00950 // Bodge an init list that names any fields we have that are modules 00951 // and initialises any fields with initialisers 00952 if( TreePtr<Field> f = dynamic_pointer_cast<Field>(pd) ) 00953 if( TreePtr<TypeIdentifier> tid = dynamic_pointer_cast<TypeIdentifier>(f->type) ) 00954 if( TreePtr<Record> r = GetRecordDeclaration(program, tid) ) 00955 if( dynamic_pointer_cast<Module>(r) ) 00956 { 00957 if( first ) 00958 s += " :"; 00959 else 00960 s += ","; 00961 string ids = RenderIdentifier(f->identifier); 00962 s += "\n" + ids + "(\"" + ids + "\")"; 00963 first = false; 00964 } 00965 00966 // TODO figure out what this does - it seems to look for function instances and then try to 00967 // init them as if they wew initable and their body was an expression. 00968 if( TreePtr<Field> i = dynamic_pointer_cast<Field>(pd) ) 00969 { 00970 TRACE("Got ")(*i)(" init is ")(*(i->initialiser))(" %d %d\n", 00971 (int)(bool)dynamic_pointer_cast<Callable>(i->type), 00972 (int)(bool)dynamic_pointer_cast<Uninitialised>(i->initialiser) ); 00973 00974 if( !dynamic_pointer_cast<Callable>(i->type) && !dynamic_pointer_cast<Uninitialised>(i->initialiser) ) 00975 { 00976 if( first ) 00977 s += " :"; 00978 else 00979 s += ","; 00980 string ids = RenderIdentifier(i->identifier); 00981 string inits = RenderExpression(i->initialiser); 00982 s += "\n" + ids + "(" + inits + ")"; 00983 i->initialiser = MakeTreePtr<Uninitialised>(); // TODO naughty, changing the tree 00984 first = false; 00985 } 00986 } 00987 } 00988 s += "\n{\n"; 00989 FOREACH( TreePtr<Declaration> pd, m->members ) 00990 if( TreePtr<Field> f = dynamic_pointer_cast<Field>(pd) ) 00991 if( TreePtr<Process> r = dynamic_pointer_cast<Process>(f->type) ) 00992 s += r->GetToken() + "(" + RenderIdentifier( f->identifier ) + ");\n"; 00993 s += "}\n"; 00994 00995 return s; 00996 } 00997 00998 00999 string Render::RenderDeclarationCollection( TreePtr<Scope> sd, 01000 string separator, 01001 bool separate_last, 01002 TreePtr<AccessSpec> init_access, 01003 bool showtype ) 01004 { 01005 TRACE(); 01006 01007 // Uncomment one of these to stress the sorter 01008 //sd = ReverseDecls( sd ); 01009 //sd = JumbleDecls( sd ); 01010 01011 Sequence<Declaration> sorted = SortDecls( sd->members, true ); 01012 backing_ordering[sd] = sorted; 01013 01014 // Emit an incomplete for each record 01015 string s; 01016 FOREACH( TreePtr<Declaration> pd, sorted ) //for( int i=0; i<sorted.size(); i++ ) 01017 if( TreePtr<Record> r = dynamic_pointer_cast<Record>(pd) ) // is a record 01018 if( !dynamic_pointer_cast<Enum>(r) ) // but not an enum 01019 s += RenderDeclaration( r, separator, init_access ? &init_access : NULL, showtype, true ); 01020 01021 // For SystemC modules, we generate a constructor based on the other decls in 01022 // the module. Nothing goes in the Inferno tree for a module constructor, since 01023 // it is an elaboration mechanism, not funcitonal. 01024 if( TreePtr<Module> m = dynamic_pointer_cast<Module>(sd) ) 01025 s += RenderModuleCtor( m, &init_access ); 01026 01027 // Emit the actual declarations, sorted for dependencies 01028 s += RenderSequence( sorted, separator, separate_last, init_access, showtype ); 01029 TRACE(); 01030 return s; 01031 } 01032