On 2011-08-09 16:48, John Criswell wrote:> On 8/9/11 6:49 AM, Bjorn Reese wrote: >> I have an optimization pass (FunctionPass) where I need to add global >> constructors. >> >> For cleaness sake I decided to add these in my own module. My module >> is created in my FunctionPass constructor: > > This is not how I would do it. A FunctionPass has doInitialization() > and doFinalization() methods that you can implement thatcan operate on > the whole module. They are designed for exactly the situation you > describe: your pass does some sort of local transform, but there's some > global modifications it needs to do (add global constructors, add > function prototypes, etc).Doesn't doIntialization() run once for each translation unit (module)? I only want to generate my global constructors once for the whole program. They are generated from a scripting language, which is parsed in the optimization pass.
On 8/9/11 9:15 AM, Bjorn Reese wrote:> On 2011-08-09 16:48, John Criswell wrote: >> On 8/9/11 6:49 AM, Bjorn Reese wrote: >>> I have an optimization pass (FunctionPass) where I need to add global >>> constructors. >>> >>> For cleaness sake I decided to add these in my own module. My module >>> is created in my FunctionPass constructor: >> This is not how I would do it. A FunctionPass has doInitialization() >> and doFinalization() methods that you can implement thatcan operate on >> the whole module. They are designed for exactly the situation you >> describe: your pass does some sort of local transform, but there's some >> global modifications it needs to do (add global constructors, add >> function prototypes, etc). > Doesn't doIntialization() run once for each translation unit (module)?It is run once per LLVM module. An LLVM module can either be a single translation unit or multiple translation units linked together (i.e., LLVM can link multiple LLVM modules together into one large module).> > I only want to generate my global constructors once for the whole > program. They are generated from a scripting language, which is parsed > in the optimization pass.I'm not familiar with how your languages organizes compilation units, but from the sounds of it, it seems like you're saying that you want to add the global ctor once after the compilation units are linked into a single LLVM bitcode file. In that case, you either delay running your FunctionPass until you have the whole bitcode file, or you create a ModulePass that is only executed once the whole-program bitcode is generated. -- John T.> _______________________________________________ > LLVM Developers mailing list > LLVMdev at cs.uiuc.edu http://llvm.cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
On 2011-08-09 20:59, John Criswell wrote:> On 8/9/11 9:15 AM, Bjorn Reese wrote: >> I only want to generate my global constructors once for the whole >> program. They are generated from a scripting language, which is parsed >> in the optimization pass. > > I'm not familiar with how your languages organizes compilation units, > but from the sounds of it, it seems like you're saying that you want to > add the global ctor once after the compilation units are linked into a > single LLVM bitcode file.I guess that what I am after is the ability to add a translation unit during the optimization phase. This translation unit does not itself have to be optimized. I am using the optimization pass to instrument another C/C++ program with debugging code (think "DTrace for programs", except that the instrumentation is static, not dynamic.) The instrumentation is controlled by a script. For example: @begin { print("This is executed before main()"); } @enter:Foo { print("This is executed when entering Foo()"); } The @enter code is injected at the beginning of Foo(), so this code is put into the current module. My own module contains the @begin code, along with all global functions, global variables, and build-in functions that are generated from the script.> In that case, you either delay running your FunctionPass until you have > the whole bitcode file, or you create a ModulePass that is only executed > once the whole-program bitcode is generated.I have considered adding a ModulePass but got confused by the description of analysis groups (which I assume I need to use in order to make sure that my ModulePass and FunctionPass are run together.) I am currently generating my code in the FunctionPass constructor, which works just fine, except I do not know how to get my module passed on to the linker.