2011/2/28 John Criswell <criswell at illinois.edu>:> On 2/28/11 6:31 AM, Gabriel Rodríguez wrote: > > Hi all, > > I am trying to extend a FunctionType to include new parameters. In > particular, I want to > ensure that the main function has been declared with both argsc and argsv. > However > there seems to be no easy way to accomplish this: > llvm::Function::getFunctionType() returns a > a reference to a const object, while modifying only the argument list yields > an error during verification > since the function type does not match its arguments. Is there any approach > that I am missing or > a simple workaround to this problem? > > If I understand correctly, you are trying to add a parameter to the main() > function, correct? > > If so, then you can't just modify the existing main() function. Instead, > you have to create a new function with an empty function body with the new > parameter and then clone the body of the old main() function into the new > main() function.I don't think a full clone is necessary, since he wants to replace the function. He only needs to create the new function and splice in the body of the old one. Gabriel: look at Function::getBasicBlockList() and iplist<>::splice(iterator, iplist). Something like Function *NewF = Function::Create(NewFnType, OldF->getLinkage()); NewF->getBasicBlockList().splice(NewF->begin(), OldF->getBasicBlockList()); NewF->takeName(OldF); OldF->eraseFromParent(); is probably what you're looking for. (Note: completely untested)
On 2/28/11 10:04 AM, Frits van Bommel wrote:> 2011/2/28 John Criswell<criswell at illinois.edu>: >> On 2/28/11 6:31 AM, Gabriel Rodríguez wrote: >> >> Hi all, >> >> I am trying to extend a FunctionType to include new parameters. In >> particular, I want to >> ensure that the main function has been declared with both argsc and argsv. >> However >> there seems to be no easy way to accomplish this: >> llvm::Function::getFunctionType() returns a >> a reference to a const object, while modifying only the argument list yields >> an error during verification >> since the function type does not match its arguments. Is there any approach >> that I am missing or >> a simple workaround to this problem? >> >> If I understand correctly, you are trying to add a parameter to the main() >> function, correct? >> >> If so, then you can't just modify the existing main() function. Instead, >> you have to create a new function with an empty function body with the new >> parameter and then clone the body of the old main() function into the new >> main() function. > I don't think a full clone is necessary, since he wants to replace the > function. He only needs to create the new function and splice in the > body of the old one.That is exactly what MakeFunctionClone() does. It creates a new function and uses CloneFunctionInto() to create a copy of the instructions in the old function in the new function. The old function can be removed afterward if desired. I'm not sure if the code below would work. I don't see a mechanism that updates instructions that use the old function's arguments to use the new function's arguments.> Gabriel: look at Function::getBasicBlockList() and > iplist<>::splice(iterator, iplist). Something like > Function *NewF = Function::Create(NewFnType, OldF->getLinkage()); > NewF->getBasicBlockList().splice(NewF->begin(), OldF->getBasicBlockList()); > NewF->takeName(OldF); > OldF->eraseFromParent(); > is probably what you're looking for. > (Note: completely untested)-- John T.
On Mon, Feb 28, 2011 at 5:04 PM, Frits van Bommel <fvbommel at gmail.com> wrote:> Gabriel: look at Function::getBasicBlockList() and > iplist<>::splice(iterator, iplist). Something like > Function *NewF = Function::Create(NewFnType, OldF->getLinkage()); > NewF->getBasicBlockList().splice(NewF->begin(), OldF->getBasicBlockList()); > NewF->takeName(OldF); > OldF->eraseFromParent(); > is probably what you're looking for. > (Note: completely untested)Well, of course you may want to also make sure no uses of the old function remain before erasing it. Since we're talking about main(), *probably* the only uses you have to worry about are blockaddresses. You probably should still check for other uses though, just in case the program is doing something weird (and not supported by the C & C++ standards IIRC).
On Mon, Feb 28, 2011 at 5:10 PM, John Criswell <criswell at illinois.edu> wrote:> On 2/28/11 10:04 AM, Frits van Bommel wrote: >> I don't think a full clone is necessary, since he wants to replace the >> function. He only needs to create the new function and splice in the >> body of the old one. > > That is exactly what MakeFunctionClone() does. It creates a new function > and uses CloneFunctionInto() to create a copy of the instructions in the old > function in the new function. The old function can be removed afterward if > desired.I'm pretty sure MakeFunctionClone() actually *copies* basic blocks + instructions instead of moving them over. Splicing the basic block list into the new function should be much more efficient, especially for large functions; it's probably constant-time operation and shouldn't allocate any memory.> I'm not sure if the code below would work. I don't see a mechanism that > updates instructions that use the old function's arguments to use the new > function's arguments.He's adding explicit argc and argv arguments to main(), implying the old function didn't have any arguments. But for a general function it'd be easy enough to call replaceAllUsesWith() on each old argument, since there's no need to worry about preserving the integrity of the old function.>> Gabriel: look at Function::getBasicBlockList() and >> iplist<>::splice(iterator, iplist). Something like >> Function *NewF = Function::Create(NewFnType, OldF->getLinkage()); >> NewF->getBasicBlockList().splice(NewF->begin(), >> OldF->getBasicBlockList()); >> NewF->takeName(OldF); >> OldF->eraseFromParent(); >> is probably what you're looking for. >> (Note: completely untested)And I did put a disclaimer about correctness :). Reading MakeFunctionClone() though, I do see some other things that I missed: * A Module* argument to Function::Create (necessitating an empty "" name argument) so it gets inserted in the module. * Copying function attributes. * Copying the calling convention.