#include //===- various headers - Existing GCC code --------------------------------===// // // No changes required //===----------------------------------------------------------------------===// enum cdi_direction { CDI_DOMINATORS, CDI_POSTDOMINATORS }; struct basic_block_def { }; typedef basic_block_def *basic_block; struct function { }; function *cfun; class gimple_opt_pass { public: virtual unsigned int execute(function *) = 0; }; //===- dominance.h - Refactored version -----------------------------------===// // // Allow passing function as an additional parameter (with default value), so // that dominaince.c does not directly use cfun any more. //===----------------------------------------------------------------------===// // We will need cfun to be in scope. Alternatively, we can put a 3-argument // overload of domainted_by_p in another header, where cfun is available. extern function *cfun; bool dominated_by_p(cdi_direction, basic_block, basic_block, function *fun = cfun) { (void)fun; printf("\t4-argument overload\n"); return false; } //===- old_pass.c - This pass uses cfun -----------------------------------===// // // We don't need to change anything here //===----------------------------------------------------------------------===// class old_pass : public gimple_opt_pass { public: virtual unsigned int execute(function *); }; void old_pass_do_stuff() { basic_block bb1 = 0, bb2 = 0; // ... if (dominated_by_p(CDI_DOMINATORS, bb1, bb2)) { // ... } } unsigned int old_pass::execute(function *fun) { printf("running old_pass::execute\n"); cfun = fun; old_pass_do_stuff(); printf("finished old_pass::execute\n"); return 0; } //===- dom_info_mixin.h - Header file for the new API ---------------------===// // // dom_info_mixin template provides helper methods for manipulating // dominance information of the function currently being compiled //===----------------------------------------------------------------------===// template class dom_info_mixin { protected: bool dominated_by_p(cdi_direction dir, basic_block bb1, basic_block bb2) const { printf("\tdom_info_mixin: using m_this_fn ... -> "); return ::dominated_by_p(dir, bb1, bb2, static_cast(this)->m_this_fn); } }; // protection against unintended use of cfun (see new_pass_do_other_stuff) bool dominated_by_p(cdi_direction dir, basic_block bb1, basic_block bb2); //===- new_pass.cc - Example pass which uses the new API ------------------===// // // new_pass stores a pointer to current function in m_this_fn (so we get rid // of the global shared state - at least some part of it) and uses small // accessor methods, so we don't have to write "m_this_fn" every time. //===----------------------------------------------------------------------===// class new_pass : public gimple_opt_pass, public dom_info_mixin { public: friend class dom_info_mixin; // or just make m_this_fn public virtual unsigned int execute(function *); private: void do_stuff(); function *m_this_fn; }; static void new_pass_do_other_stuff(); unsigned int new_pass::execute(function *fun) { printf("running new_pass::execute\n"); m_this_fn = fun; do_stuff(); new_pass_do_other_stuff(); printf("finished new_pass::execute\n"); return 0; } void new_pass::do_stuff() { basic_block bb1 = 0, bb2 = 0; // ... if (dominated_by_p(CDI_DOMINATORS, bb1, bb2)) { // ... } } static void new_pass_do_other_stuff() { #if 0 basic_block bb1 = 0, bb2 = 0; // ... // error: call of overloaded ‘dominated_by_p(cdi_direction, basic_block_def*&, basic_block_def*&)’ is ambiguous if (dominated_by_p(CDI_DOMINATORS, bb1, bb2)) { // ... } #endif } int main() { function fun; old_pass old_pass_instance; old_pass_instance.execute(&fun); new_pass new_pass_instance; new_pass_instance.execute(&fun); return 0; }