Inferno  0.2
inferno.cpp
Go to the documentation of this file.
00001 #include "tree/cpptree.hpp"
00002 #include "tree/sctree.hpp"
00003 #include "parse/parse.hpp"  
00004 #include "render/render.hpp"
00005 #include "render/graph.hpp"
00006 #include "common/read_args.hpp"
00007 #include "common/hit_count.hpp"
00008 #include "helpers/walk.hpp"
00009 #include "sr/search_replace.hpp"
00010 #include "sr/soft_patterns.hpp"
00011 #include "tree/validate.hpp"
00012 #include "steps/split_instance_declarations.hpp"
00013 #include "steps/generate_implicit_casts.hpp"
00014 #include "steps/generate_stacks.hpp"
00015 #include "steps/slave_test.hpp"
00016 #include "steps/lower_control_flow.hpp"
00017 #include "steps/clean_up.hpp"
00018 #include "steps/state_out.hpp"
00019 #include "steps/fall_out.hpp"
00020 #include "steps/systemc_detection.hpp"
00021 #include "steps/to_sc_method.hpp"
00022 #include "render/doc_graphs.hpp"
00023 
00024 using namespace Steps;
00025 
00026 void SelfTest();
00027     // Build a vector of transformations, in the order that we will run them
00028     // (ordered by hand for now, until the auto sequencer is ready)
00029 void BuildSequence( vector< shared_ptr<Transformation> > *sequence )
00030 {
00031     ASSERT( sequence );
00032     // SystemC detection, converts implicit SystemC to explicit. Always at the top
00033     // because we never want to process implicit SystemC.
00034     sequence->push_back( shared_ptr<Transformation>( new DetectAllSCTypes ) );
00035 
00036     { // establish what is locally uncombable
00037         sequence->push_back( shared_ptr<Transformation>( new DetectUncombableSwitch ) );
00038         sequence->push_back( shared_ptr<Transformation>( new MakeAllForUncombable ) );
00039         sequence->push_back( shared_ptr<Transformation>( new DetectCombableFor ) );
00040         sequence->push_back( shared_ptr<Transformation>( new MakeAllBreakUncombable ) );
00041         sequence->push_back( shared_ptr<Transformation>( new CleanupCompoundMulti ) );    // for DetectCombableBreak
00042         sequence->push_back( shared_ptr<Transformation>( new DetectCombableBreak ) );
00043     }    
00044     { // Construct lowerings
00045         { // function call lowering (and function merging)
00046             sequence->push_back( shared_ptr<Transformation>( new ExtractCallParams ) ); 
00047             sequence->push_back( shared_ptr<Transformation>( new ExplicitiseReturn ) );
00048             sequence->push_back( shared_ptr<Transformation>( new ReturnViaTemp ) );
00049             sequence->push_back( shared_ptr<Transformation>( new AddLinkAddress ) );
00050             sequence->push_back( shared_ptr<Transformation>( new ParamsViaTemps ) );
00051             sequence->push_back( shared_ptr<Transformation>( new SplitInstanceDeclarations ) ); 
00052             sequence->push_back( shared_ptr<Transformation>( new MoveInstanceDeclarations ) ); 
00053             sequence->push_back( shared_ptr<Transformation>( new AutosToModule ) );
00054             sequence->push_back( shared_ptr<Transformation>( new GenerateStacks ) );
00055             sequence->push_back( shared_ptr<Transformation>( new MergeFunctions ) );
00056         }
00057 
00058         sequence->push_back( shared_ptr<Transformation>( new BreakToGoto ) ); 
00059         sequence->push_back( shared_ptr<Transformation>( new ForToWhile ) ); 
00060         sequence->push_back( shared_ptr<Transformation>( new WhileToDo ) ); 
00061         sequence->push_back( shared_ptr<Transformation>( new DoToIfGoto ) ); 
00062         
00063         sequence->push_back( shared_ptr<Transformation>( new LogicalAndToIf ) ); 
00064         sequence->push_back( shared_ptr<Transformation>( new LogicalOrToIf ) ); 
00065         sequence->push_back( shared_ptr<Transformation>( new MultiplexorToIf ) ); 
00066         sequence->push_back( shared_ptr<Transformation>( new SwitchToIfGoto ) );
00067         sequence->push_back( shared_ptr<Transformation>( new SplitInstanceDeclarations ) );  
00068         sequence->push_back( shared_ptr<Transformation>( new IfToIfGoto ) ); 
00069         // All remaining uncomables at the top level and in SUSP style
00070     }    
00071     { // Initial treatment of gotos and labels
00072         sequence->push_back( shared_ptr<Transformation>( new NormaliseConditionalGotos ) );
00073         sequence->push_back( shared_ptr<Transformation>( new CompactGotos ) ); // maybe put these after the label cleanups
00074     }        
00075     { // big round of cleaning up
00076         sequence->push_back( shared_ptr<Transformation>( new ReduceVoidCompoundExpression ) ); 
00077         //for( int i=0; i<2; i++ )
00078         // Ineffectual gotos, unused and duplicate labels result from compound tidy-up after construct lowering, but if not 
00079         // removed before AddGotoBeforeLabel, they will generate spurious states. We also remove dead code which can be exposed by
00080         // removal of unused labels - we must repeat because dead code removal can generate unused labels.
00081         sequence->push_back( shared_ptr<Transformation>( new CleanupCompoundExpression ) ); // TODO only safe in SSP, so don't call this a cleanup!
00082         for( int i=0; i<2; i++ )
00083         {
00084             sequence->push_back( shared_ptr<Transformation>( new CleanupCompoundMulti ) );
00085             sequence->push_back( shared_ptr<Transformation>( new CleanupCompoundSingle ) ); 
00086             sequence->push_back( shared_ptr<Transformation>( new CleanupNop ) ); 
00087             sequence->push_back( shared_ptr<Transformation>( new CleanupUnusedLabels ) ); 
00088             sequence->push_back( shared_ptr<Transformation>( new CleanupDuplicateLabels ) );
00089             sequence->push_back( shared_ptr<Transformation>( new CleanupIneffectualLabels ) ); 
00090             sequence->push_back( shared_ptr<Transformation>( new CleanUpDeadCode ) ); 
00091         }
00092     }    
00093     { // transition to normalised lmap style
00094         sequence->push_back( shared_ptr<Transformation>( new GotoAfterWait ) );     
00095         sequence->push_back( shared_ptr<Transformation>( new AddGotoBeforeLabel ) );         
00096         //sequence->push_back( shared_ptr<Transformation>( new EnsureBootstrap ) );     
00097         sequence->push_back( shared_ptr<Transformation>( new EnsureResetYield ) );
00098         sequence->push_back( shared_ptr<Transformation>( new CleanupCompoundMulti ) );
00099         sequence->push_back( shared_ptr<Transformation>( new AddStateLabelVar ) ); 
00100         sequence->push_back( shared_ptr<Transformation>( new PlaceLabelsInArray ) );  
00101  #if 1
00102         sequence->push_back( shared_ptr<Transformation>( new LabelTypeToEnum ) ); 
00103  #else
00104         for( int i=0; i<2; i++ )
00105         {
00106             sequence->push_back( shared_ptr<Transformation>( new LabelVarsToEnum ) ); 
00107             sequence->push_back( shared_ptr<Transformation>( new SwapSubscriptMultiplex ) );        
00108         }
00109 #endif        
00110         sequence->push_back( shared_ptr<Transformation>( new CleanupCompoundMulti ) );
00111     }    
00112     { // creating fallthrough machine
00113         for( int i=0; i<5; i++ )
00114         {
00115             sequence->push_back( shared_ptr<Transformation>( new ApplyCombGotoPolicy ) );
00116             sequence->push_back( shared_ptr<Transformation>( new ApplyYieldGotoPolicy ) );
00117         }
00118         sequence->push_back( shared_ptr<Transformation>( new ApplyBottomPolicy ) );
00119         sequence->push_back( shared_ptr<Transformation>( new ApplyLabelPolicy ) );
00120         sequence->push_back( shared_ptr<Transformation>( new CleanupDuplicateLabels ) );
00121         sequence->push_back( shared_ptr<Transformation>( new ApplyTopPolicy ) );
00122         sequence->push_back( shared_ptr<Transformation>( new DetectSuperLoop(false) ) );
00123         sequence->push_back( shared_ptr<Transformation>( new DetectSuperLoop(true) ) );
00124         sequence->push_back( shared_ptr<Transformation>( new CleanupUnusedVariables ) );
00125     }
00126     { // optimsing fall though machine
00127         sequence->push_back( shared_ptr<Transformation>( new LoopRotation ) );
00128     }
00129     { // transition to event driven style
00130         sequence->push_back( shared_ptr<Transformation>( new InsertInferredYield ) );
00131         sequence->push_back( shared_ptr<Transformation>( new AutosToModule ) );
00132         sequence->push_back( shared_ptr<Transformation>( new TempsAndStaticsToModule ) ); // TODO why?
00133         sequence->push_back( shared_ptr<Transformation>( new DeclsToModule ) );
00134         sequence->push_back( shared_ptr<Transformation>( new ThreadToMethod ) );
00135         sequence->push_back( shared_ptr<Transformation>( new ExplicitiseReturns ) );   // TODO move this into Verilog phase?
00136         sequence->push_back( shared_ptr<Transformation>( new CleanupNestedIf ) );      // and this
00137     }
00138     { // final cleanups
00139         for( int i=0; i<2; i++ )
00140         {
00141             sequence->push_back( shared_ptr<Transformation>( new CleanupUnusedLabels ) ); 
00142             sequence->push_back( shared_ptr<Transformation>( new CleanupDuplicateLabels ) );
00143             sequence->push_back( shared_ptr<Transformation>( new CleanupIneffectualLabels ) ); 
00144             sequence->push_back( shared_ptr<Transformation>( new CleanUpDeadCode ) ); 
00145         }
00146     }
00147 }
00148 
00149 
00150 int main( int argc, char *argv[] )
00151 {
00152     // Check the command line arguments 
00153     ReadArgs( argc, argv );
00154     HitCount::instance.Check();
00155     Tracer::Enable( ReadArgs::trace );
00156     HitCount::instance.SetStep(-1);
00157     HitCount::Enable( ReadArgs::trace_hits );
00158 
00159     // Do self-tests (unit tests) if requested
00160     if( ReadArgs::selftest )
00161         SelfTest();
00162     
00163     // Build documentation graphs if requested
00164     if( ReadArgs::documentation_graphs )
00165         GenerateDocumentationGraphs();
00166     
00167     // get the transformations, in sequence, in a vector
00168     vector< shared_ptr<Transformation> > sequence;
00169     BuildSequence( &sequence );
00170     
00171     // If a pattern graph was requested, generate it now
00172     if( ReadArgs::pattern_graph != -1 )
00173     {
00174         ASSERT( ReadArgs::pattern_graph >= 0 )("Negative step number is silly\n");
00175         ASSERT( ReadArgs::pattern_graph < sequence.size() )("There are only %d steps at present\n", sequence.size() );
00176         Graph g( ReadArgs::outfile );
00177         g( sequence[ReadArgs::pattern_graph].get() );
00178     }        
00179     
00180     // If there was no input program then there's nothing more to do
00181     if( ReadArgs::infile.empty() )
00182         return 0;
00183 
00184     // Parse the input program
00185     TreePtr<Node> program = TreePtr<Node>();
00186     Parse p(ReadArgs::infile);
00187     p( program, &program );
00188  
00189     if( ReadArgs::runonlyenable )
00190     {
00191         // Apply only the transformation requested
00192         shared_ptr<Transformation> t = sequence[ReadArgs::runonlystep];
00193         fprintf(stderr, "Step %d: %s\n", ReadArgs::runonlystep, string( *t ).c_str() ); 
00194         TRACE("Step %d: %s\n", ReadArgs::runonlystep, string( *t ).c_str() ); // TODO trace should print to stderr too
00195         HitCount::instance.SetStep(ReadArgs::runonlystep);
00196         CompareReplace::SetMaxReps( ReadArgs::repetitions, ReadArgs::rep_error );
00197         (*t)( &program );
00198     }
00199     else
00200     {
00201         // Apply the transformation steps in order, but quit early if requested to
00202         int i=0;
00203         FOREACH( shared_ptr<Transformation> t, sequence )
00204         {
00205             if( ReadArgs::quitafter-- == 0 )
00206                 break;
00207             fprintf(stderr, "Step %d: %s\n", i, string( *t ).c_str() ); 
00208             Tracer::Enable( ReadArgs::trace && (!ReadArgs::quitenable || ReadArgs::quitafter==0) ); 
00209             HitCount::Enable( ReadArgs::trace_hits && (!ReadArgs::quitenable || ReadArgs::quitafter==0) ); 
00210             if( (!ReadArgs::quitenable || ReadArgs::quitafter==0) )
00211                 CompareReplace::SetMaxReps( ReadArgs::repetitions, ReadArgs::rep_error );
00212             else
00213                 CompareReplace::SetMaxReps( 100, true );
00214             HitCount::instance.SetStep(i);
00215             (*t)( &program );
00216             i++;
00217         }
00218     }
00219         
00220     // Output either C source code or a graph, as requested
00221     Tracer::Enable( ReadArgs::trace );
00222     HitCount::Enable( ReadArgs::trace_hits );
00223     HitCount::instance.SetStep(-1);
00224     if( ReadArgs::trace_hits )
00225         HitCount::instance.Dump();    
00226     else if(ReadArgs::intermediate_graph)
00227     {
00228         Graph g( ReadArgs::outfile );
00229         g( &program );    
00230     }
00231     else    
00232     {
00233         Render r( ReadArgs::outfile );
00234         r( &program );     
00235     }
00236             
00237     return 0;
00238 }
00239 
00240 void SelfTest()
00241 
00242 {
00243     SearchReplace::Test();
00244     CommonTest();
00245     GenericsTest();
00246 }
00247 
00248 // TODO Split Compare out of CompareReplace. 
00249 // TODO Make Filter a functor. 
00250 // TODO Consider merging Filter into Transformation.
00251 // TODO Produce base class for builder nodes: TransformTo?
00252 // TODO Consider multi-terminus Stuff and multi-root (StarStuff)
00253