Inferno
0.2
|
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