How to create and insert a call MachineInstr?

Hi all,
I am working on a project which needs to create and insert a MachineInstr which calls a function. But I don’t know how to build it. The function has been declared in IR.

I have used BuildMI to build a MachineInstr. But it seems that a call MachineInstr only has one parameter which is a register(%physreg44?). Therefore how can I set the callee function and the arguments of the function?

Thanks a lot,

Will

Hi Will,

I have used BuildMI to build a MachineInstr. But it seems that a call
MachineInstr only has one parameter which is a
register(%physreg44<imp-use>?).

This depends on the target, but calls normally have a few operands:

  + The callee (a register or a global address or something).
  + A regmask indicating which registers the call preserves.
  + A list of imp-uses and imp-defs for the registers used to pass and
return parameters.

If you writie a .ll file that makes a call you should be able to see
all these components in the generated MIR.

Therefore how can I set the callee function and the arguments of the function?

For a direct call, you'd normally use MachineInstrBuilder's
addGlobalAddress to set the callee. You have to emit separate moves
and stores before the call to put the arguments in the correct
registers and stack slots. Be careful not to clobber live registers!

We can probably give a few more details (like the call instruction to
use, and which registers pass parameters; maybe some extra quirks) if
we know the actual target you're compiling for, but the outline above
won't change significantly.

Cheers.

Tim.

Thanks for your help! I’m much more clear about this problem.

Will

Hi Tim,
I’m sorry to bother you again. Since I have met the problem, how to check used registers and avoid clobbering live registers, which you mentioned in the email.

I am working in the function X86InstrInfo::storeRegToStackSlot, which is in lib/Target/X86/X86InstrInfo.cpp.

And I have an extra problem, may I use MOV64mr and two addReg to set two registers as its arguments? I want to use content of one register as the address to be stored, and content of the other register as the source.

Thanks a lot!

Will

Hi Will,

I'm sorry to bother you again. Since I have met the problem, how to check
used registers and avoid clobbering live registers, which you mentioned in
the email.

The easiest way to do it would be to run before register allocation.
Then the allocator itself would handle that for you. If that's not an
option then I think there are two options:

  + Save and restore the registers manually. You'd emit push & pop
instructions surrounding your actual call to do that.
  + Call a (probably assembly) stub that saves *all* the registers
before calling your actual function.

I am working in the function X86InstrInfo::storeRegToStackSlot, which is in
lib/Target/X86/X86InstrInfo.cpp.

I could see that working too, though you'd have to reserve a stack
slot to do it.

And I have an extra problem, may I use MOV64mr and two addReg to set two
registers as its arguments? I want to use content of one register as the
address to be stored, and content of the other register as the source.

Unfortunately x86 addressing modes are more complicated than that, and
you always need all the operands in LLVM. They're defined in
X86InstrInfo.td (look for X86MemOperand), but in outline the arguments
for a memory address ("base + scale reg * index + offset in some
segment") are:

  + A base register
  + An immediate scale for the index register
  + An index register.
  + An immediate total offset.
  + A segment register (or 0 for default by the looks of it).

So for just a register you'd want
".addReg(MyReg).addImm(1).addReg(0).addImm(0).addReg(0)". The llvm-mc
utility can be useful for experiments here (it's what I used):

$ echo "movq %rbx, (%rax)" | llvm-mc -show-inst
.section __TEXT,__text,regular,pure_instructions
movq %rbx, (%rax) ## <MCInst #1486 MOV64mr
                                        ## <MCOperand Reg:106>
                                        ## <MCOperand Imm:1>
                                        ## <MCOperand Reg:0>
                                        ## <MCOperand Imm:0>
                                        ## <MCOperand Reg:0>
                                        ## <MCOperand Reg:108>>

If you fiddle about with the various addressing-modes you can see how
each affects the LLVM instruction.

Cheers.

Tim.