Aarch64: Build MachineInstruction for "ADR Xd, ."

Hi,

In AArch64, the PC is not a general purpose register.
However, there are other methods to read the current value of the PC to a register.

According to [1], you can read the PC value via the ADR instruction:
ADR Xd, .

Here, the dot (".") means “here”. So a label at the current location.

The question is now, how to build an LLVM MachineInstruction with that?
Something like this:

Register PcReg = MRI.createVirtualRegister(&AArch64::GPR64RegClass);

BuildMI(bb, bb.instr_begin(),
DebugLoc(), TII.get(AArch64::ADR))
.addReg(PcReg)

.addLabel(".");

However, I am struggling in adding a label for the current location as the second operand.

Best,
Max

[1] https://developer.arm.com/architectures/learn-the-architecture/armv8-a-instruction-set-architecture/registers-in-aarch64-other-registers

Hi Max,

Register PcReg = MRI.createVirtualRegister(&AArch64::GPR64RegClass);
BuildMI(bb, bb.instr_begin(),
  DebugLoc(), TII.get(AArch64::ADR))
   .addReg(PcReg)
   .addLabel(".");

However, I am struggling in adding a label for the current location as the second operand.

If you literally just want the current address then ".addImm(0)" will
do it. You need a label if some other part of the program needs to
refer back to that location. In that case I think you'll need a pseudo
that gets converted to a label and an ADR by AArch64AsmPrinter.cpp.
Something like

  case AArch64::ADRAnchor: {
    MCSymbol *Label = MF->getContext().createTempSymbol();
    MCExpr *LabelE = MCSymbolRefExpr::create(Label, MF->getContext());

    OutStreamer->emitLabel(Label);
    EmitToStreamer(OutStreamer, MCInstBuilder(AArch64::ADR)
        .addReg(DestReg)
        .addExpr(LabelE)));
  }

And then of course you have to work out how to tell the other code
about this temporary label you created.

Cheers.

Tim.