Adding the inreg attribute to LLVM IR function par

2019-07-18 18:45发布

问题:

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?

回答1:

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.



回答2:

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, ...);