in an IR pass: access the instruction pointer/BB address

Hi,

I looked through the documentation and source and am unable to find a way:

in an IR pass on basic blocks

  for (auto &F : M)
    for (auto &BB : F) {
       ....
    }

I want to access the current address of the basic block. It does not
need to be the exact address of the BB, a few instructions down of that
BB is fine as well.

basically the same that I could do with an "leaq (%rip), %rdx"
instruction on intel x64.

I want to then use this address as a "Value *" type and continue using
it in IRB.CreateStore() etc.

The sanatizer seems to call a function which then uses GET_CALLER_PC,
but that costs speed and complicates my IR code...

Is that possible? Even if its not portable on anything else than intel
x64 that would be enough.
Thanks a lot!

Regards,
Marc

Hi Marc,

I want to access the current address of the basic block. It does not
need to be the exact address of the BB, a few instructions down of that
BB is fine as well.

I think you want BlockAddress:
https://llvm.org/doxygen/classllvm_1_1BlockAddress.html. It's an
instance of Constant and therefore also Value, and doesn't need to be
inserted as an instruction.

basically the same that I could do with an "leaq (%rip), %rdx"
instruction on intel x64.

That's slightly different, and I don't think there is an intrinsic for
the current PC. You could use inline assembly to get it though, since
you don't care about portability.

Cheers.

Tim.

Hi Tim,

Hi Marc,

I want to access the current address of the basic block. It does not
need to be the exact address of the BB, a few instructions down of that
BB is fine as well.

I think you want BlockAddress:
https://llvm.org/doxygen/classllvm_1_1BlockAddress.html. It's an
instance of Constant and therefore also Value, and doesn't need to be
inserted as an instruction.

I thought this is a relative address within the function and not
complete address and thats why I dismissed it.

If it is an absolute value - how do I put that into an IRB.CreateStore()
as the value to write? My various attempts compiled the pass crashed
when using it :wink:

basically the same that I could do with an "leaq (%rip), %rdx"
instruction on intel x64.

That's slightly different, and I don't think there is an intrinsic for
the current PC. You could use inline assembly to get it though, since
you don't care about portability.

I thought about that too, but then stumbled into the next problem:
How would I get it into a free, unused register? That is kinda the great
stuff about the llvm IR, that it optimizes it as good as possible.

If I have to do "push rdx; lea (%rip), %rdx;" (do stuff) "pop rdx" that
a) needs unnecessary instructions and b) then I have the problem that I
have the value I want in rdx, but how would I access that register with
IR ... and writing the whole functionality in inline assembly is not as
effective as IR, and speed is essential ...

I would then rather do something like
IR.CreateCall(...)
and in that call set a global variable with GET_CALLER_PC, return and go
on ... at least this is portable and should have a similar speed as a
full inline assembly. (if that is that easy. I am not an llvm guru. by
far. rather mostly clueless :wink: but its part of a bigger endeavor that
needs a small plugin in llvm)

Regards,
Marc

I thought this is a relative address within the function and not
complete address and thats why I dismissed it.

It's the complete address. The way it's written includes the function
because the block name might be duplicated in multiple functions.

If it is an absolute value - how do I put that into an IRB.CreateStore()
as the value to write? My various attempts compiled the pass crashed
when using it :wink:

It should just be something like "IRB.CreateStore(BlockAddress::get(F,
BB), Ptr)". Could you show us some simple IR that crashes? Or the C++
code and assertion failure if it was a compile-time issue.

>> basically the same that I could do with an "leaq (%rip), %rdx"
>> instruction on intel x64.
>
> That's slightly different, and I don't think there is an intrinsic for
> the current PC. You could use inline assembly to get it though, since
> you don't care about portability.

I thought about that too, but then stumbled into the next problem:
How would I get it into a free, unused register? That is kinda the great
stuff about the llvm IR, that it optimizes it as good as possible.

If I have to do "push rdx; lea (%rip), %rdx;" (do stuff) "pop rdx" that
a) needs unnecessary instructions and b) then I have the problem that I
have the value I want in rdx, but how would I access that register with
IR ... and writing the whole functionality in inline assembly is not as
effective as IR, and speed is essential ...

Inline assembly lets you specify input and output values. In IR you'd
write something like

    %pc = call i64 asm "leaq (%rip), $0", "=r"()

which you'd create by calling an InlineAsm object. The two strings map
to the operands of InlineAsm::get in the natural way.

Cheers.

Tim.