int cmm_pragma_autoblocks_off(); #include "../cmm/parser.h" #include "../cmm/exceptionstream.h" #include #include #include #ifndef CMM_MULTIMETHODS #error #endif int cmm_pragma_autoblocks_on(); struct outstream2_t : parser::outstream_t outstream2_t( std::ostream& out) : parser::outstream_t( out), hierprof_return( false), have_seen_hierprof_function( false) ; hierprof_return: bool; have_seen_hierprof_function: bool; private: outstream2_t( rhs: const & outstream2_t); outstream2_t& operator = ( rhs: const & outstream2_t); ; namespace parser output_node_: ( static retur: & const parser::return_t, static out: & outstream2_t) void if ( out.hierprof_return) // Modify output to contain hierprof macros. out.out << "{ " << "hierprof__stopclock( hierprof_fnref, hierprof_clock_gettimefreeze()); " ; retur.output( out); out.out << "}"; else retur.output( out); output_node_: ( static declname: & const parser::declarator_name_t, static out: & outstream2_t) void declname.output( out); if ( out.have_seen_hierprof_function) return; if ( declname.name->elements.size()==0) return; const parser::name_element_normal_t* nen = dynamic_cast( declname.name->elements[0]); std::cerr << "outputing name " << *nen << "\n"; if ( nen && (0 == strncmp( nen->begin, "hierprof_", 9))) out.have_seen_hierprof_function = true; std::cerr << "Found first hierprof_ function - will translate all subsequent function bodies\n"; output_node_: ( static fnbody: & const parser::fnbody_t, static out: & outstream2_t) void std::cerr << "output called for fnbody\n"; name: ->parser::declarator_name_t = fnbody.declterm->declarator->is_name(); if ( !name) // fn is anonymous, so we don't add profiling info. parser::scoped_change_t default_output( out.hierprof_return, false); fnbody.output( out); return; /* output beginning of function body - any constructor initialisers, and the opening '{'. */ if ( fnbody.initialisers) output_node( *fnbody.initialisers, out); out.out << "{ " //<< "static hierprof_ref_type hierprof_fnref=0; " //<< "if ( hierprof_fnref==0) hierprof_fnref=hierprof__initblock( \"" << "static hierprof_ref_type hierprof_fnref=hierprof_fnref=hierprof__initblock( \"" << name->output_compact_tostring( out) << "\"); " << "hierprof__startclock( hierprof_fnref, hierprof_clock_gettimefreeze()); " ; output_node( *fnbody.body->open, out); /* Output function body. We modify out so that any `return [];' in the function body will be converted to use hierprof_Return. */ parser::scoped_change_t hierprof_return( out.hierprof_return, true); for ( parser::compound_t::items_t::iterator it=fnbody.body->items.begin(); it!=fnbody.body->items.end(); ++it) output_node( **it, out); // Output end of function. parser::declarator_left_t* declleft = fnbody.declterm->get_declarator_left(); // If declleft is `void', then we know to use hierprof_VoidFnStop etc. if ( declleft && declleft->name && typeid( *declleft->name)!=typeid( parser::keyword_void)) out.out << "}"; else out.out << "} hierprof__stopclock( hierprof_fnref, hierprof_clock_gettimefreeze());"; // and now the closing '}': output_node( *fnbody.body->close, out); namespace usage: () void std::cout << "Params:\n" " -hierprof \n" " Adds calls to hierprof to specified source.\n" " -no-c++\n" " Parses as C, not C++.\n" " -immediate\n" " Transforms all functions, without waiting for\n" " first hierprof_ function to be seen\n" "\n"; main: ( argc: int, argv: ->->char) int try bool no_cplusplus = false; bool immediate = false; if ( argc==0) usage(); for ( int arg=1; arg=argc) throw std::runtime_error( "need 2 params after -hierprof"); infilename: std::string = argv[ arg+1]; outfilename: std::string = argv[ arg+2]; arg+=2; parser::lexer_t lexer( infilename, false, false, false, false, false, no_cplusplus); compunit: &parser::compilation_unit_t = parser::get_compilation_unit( lexer, true, false, false, false, true); std::ofstream outfile( outfilename.c_str()); if ( !outfile) throw std::runtime_error( "Couldn't open for writing"); outstream2_t out( outfile); out.have_seen_hierprof_function = immediate; outfile << "#line 1 \"" << infilename << "\"\n"; //outfile << "#include \"hierprof/hierprof.h\"\n"; //outfile << "#line 1 \"" << infilename << "\"\n"; std::cerr << "calling parser::output_node( compunit, out)\n"; parser::output_node( compunit, out); std::cerr << "called parser::output_node( compunit, out)\n"; else throw std::runtime_error( std::string("Unrecognised param `") + argv[arg] + "'"); return 0;; catch ( std::exception& e) std::cerr << e.what() << "\n"; return 1;