Operating on contents of virtual registers

Hello,

I was facing some difficulty in implementing a transform and I was wondering if I could get some help please.

The transform needs to operate on the operands of certain instructions. For example, given an instruction, say “%10 = load i32* %9, align 4”, I have to record the value of %9 and process it. Of course, this is only possible at runtime and so I am instrumenting the code such that a particular function is invoked just before the instruction of interest is executed.

The problem that I am facing is in getting the value of the operands. As I understand, the operands could either be program variables (e.g. in “%6 = load i32* %old, align 4”) or one of the virtual registers (as in the first load instruction). For both cases, is it possible to extract the value/address of the operand (%9 or %old)? If yes, what should be the best function type to use so that I can pass this value as an argument to my function? For now, I am only concerned with load and store instructions and so (I suppose) I have to deal with pointers only.

An easy way that I can think of is to directly insert the LLVM IR (e.g. call void @my_function(%old)) but because I am using Module::getOrInsertFunction(), I have to have a function type. So alternatively, is there a way to insert direct LLVM instructions (without going through the type hierarchy)?

Thanks,
Ashay

Hello,
I was facing some difficulty in implementing a transform and I was wondering
if I could get some help please.
The transform needs to operate on the operands of certain instructions. For
example, given an instruction, say "%10 = load i32* %9, align 4", I have to
record the value of %9 and process it. Of course, this is only possible at
runtime and so I am instrumenting the code such that a particular function
is invoked just before the instruction of interest is executed.
The problem that I am facing is in getting the value of the operands. As I
understand, the operands could either be program variables (e.g. in "%6 =
load i32* %old, align 4") or one of the virtual registers (as in the first
load instruction). For both cases, is it possible to extract the
value/address of the operand (%9 or %old)?

Those are both the same case; names for instructions only exist for
the sake of readability.

If yes, what should be the best
function type to use so that I can pass this value as an argument to my
function? For now, I am only concerned with load and store instructions and
so (I suppose) I have to deal with pointers only.

If you only need pointers, just use i8* as the type of the argument,
and bitcast the value to i8*.

An easy way that I can think of is to directly insert the LLVM IR (e.g. call
void @my_function(%old)) but because I am using
Module::getOrInsertFunction(), I have to have a function type. So
alternatively, is there a way to insert direct LLVM instructions (without
going through the type hierarchy)?

Your approach of inserting a call is fine; making your own instruction
or intrinsic wouldn't make things any simpler. There aren't any
shortcuts here.

-Eli

Hi Eli,

Thanks for the reply. The problem is that getOperand() returns an llvm::Instruction (that refers to the definition of the operand). What I am trying to find out is how to get the value of the operand. When you refer to bitcasting to i8*, do you mean casting the return value from getOperand() itself?

Ashay

Hi Eli,
Thanks for the reply. The problem is that getOperand() returns an
llvm::Instruction (that refers to the definition of the operand). What I am
trying to find out is how to get the value of the operand. When you refer to
bitcasting to i8*, do you mean casting the return value from getOperand()
itself?
Ashay

I mean calling IRBuilder::CreateBitCast with the return value from getOperand().

-Eli

Thanks Eli, that worked!

For the record, I had to make one change though. I had to bitcast to i32* (instead of i8*) otherwise I was seeing errors like:

Instruction referencing instruction not embedded in a basic block!
%retval = alloca i32
= bitcast i32* %retval to i8*

and sometimes:
Instruction does not dominate all uses!

That makes me curious to ask, what does the choice of i32 or i8 depend on? Is it the architecture?

Ashay

Thanks Eli, that worked!
For the record, I had to make one change though. I had to bitcast to i32*
(instead of i8*) otherwise I was seeing errors like:
Instruction referencing instruction not embedded in a basic block!
%retval = alloca i32
<badref> = bitcast i32* %retval to i8*
and sometimes:
Instruction does not dominate all uses!
That makes me curious to ask, what does the choice of i32 or i8 depend on?
Is it the architecture?

A bitcast from i32* to i32* gets optimized out. :slight_smile: I think you're
missing a call to IRBuilder::SetInsertPoint.

-Eli