I'm working with LLVM and I want to recreate a piece of IR with the API:
declare void @fun(i32* inreg, i32 inreg)
But I can't seem to get it to actually do it.
My current attempt is:
Function* fun = cast<Function>(M.getOrInsertFunction("fun",type));
((fun -> getAttributes()).getParamAttributes(0)).addAttribute(c,0,Attribute::InReg);
((fun -> getAttributes()).getParamAttributes(1)).addAttribute(c,0,Attribute::InReg);
This code literally doesn't do anything after line 1, lines 2 and 3 are completely ignored and all I get in the IR output is:
declare void @fun(i32* , i32 )
How do I get it to work correctly?
Managing function attributes in LLVM is quite inconvenient as attributes are packed into immutable and global sets. Assigning an attribute to a function argument actually means replacing the set representing all function and argument attributes with a new one.
Fortunately, there are at least helper functions that makes that job a bit easier. I suggest using llvm::Function::addAttribute()
method.
Function* fun = cast<Function>(M.getOrInsertFunction("fun", type));
fun->addAttribute(1, Attribute::InReg);
fun->addAttribute(2, Attribute::InReg);
Keep in mind that index 0 represents function attributes, argument attributes starts from index 1.
There are three problems with your code snippet.
First, the index of the first parameter is 1, not 0. So you should be using indices 1 and 2, not 0 and 1.
Second, addAttribute()
does not modify its receiver, it instead returns a new set. So the proper way to change attributes would be to do:
fun->setAttributes(fun->getAttributes().addAttribute(1, ...));
And finally, there's a shorthand for the above, which is just to do:
fun->addAttribute(1, ...);