How to place function calls around certain inline assembly

Hello All,

in the past two days I’ve been trying implementing a MachineFunctionPass that recognizes certain inline assemly by reading its asm string, and place function calls before and after them. I chose MachineFunctionPass instead of FunctionPass because I believe inline asm is target-related and lives better with MachineFunction.

Here is my attempt, other necessary code to invoke the pass is omitted.

bool myPass::runOnMachineFunction(MachineFunction &MF){
  for(MachineBasicBlock &MBB:MF)
    for(auto I=MBB.begin(), E=MBB.end(); I!=E; ++I){
      MachineInst *MI= &*I; 
      if (MI->isInlineAsm()){
      LLVM_DEBUG(dbgs() << "found an inlined asm with " <<MI->getNumOperands()<<"operands\n" );
      ExternalSymbolSDNode op1 = cast<ExternalSymbolSDNode>(MI->getOperand(1));
      StringRef asmstr(op1.getSymbol());
      LLVM_DEBUG(dbgs()<<asmstr);
       }
    }
}

However, this code hardly compile and always triggers Coredump by printing. I believe this is caused by a wrong casting from MachineOperand to ExternalSymbolSDNode.
The document that I refer to is this doxgen page that says the #1 operand of inlineAsm node is a ExternalSymbolSDNode which has a pointer to the asm string. Also this page that says I can use getSymbol to obtain a const char* pointing to the asm string.

The source code I test is the following RISCV code

int fesetenv(const unsigned *envp)
{
    unsigned fscr = *envp;
    asm volatile("fscsr %0" :: "r"(fcsr));
    return 0;
}

I’ve tried llc --print-after-isel and see that the asm is converted to

INLINEASM&“fscsr $0” [sideeffect] [attdialect], $0;[reguse:GPR], %1;gpr, !8 

I’ve also tried --view-isel-dag and see that the inlineasm node do have a #1 operand TargetExternalSymbol ‘fscsr $0’.

The infomation is there but I cannot retrieve it. Do you have any advices Thanks!

best, zhaozhaozhao

That’s referring to the SelectionDAG representation, earlier in CodeGen. As you’re writing a MachineFunction pass what you have is a MachineOperand, so you should be able to call getSymbol directly on it (I think it’s still a symbol).

Indeed! in MachineFunctionPass the node is converted to MI and therefore the asm string literal becomes the #0 operand instead of the #1.
Now I use the following code to retrieve the asm string;

bool myPass::runOnMachineFunction(MachineFunction &MF){
  for(MachineBasicBlock &MBB:MF)
    for(auto I=MBB.begin(), E=MBB.end(); I!=E; ++I){
      MachineInst *MI= &*I; 
      if(MI->isInlineAsm()){
      auto op = MI->getOperand(0);
      StringRef asm_str(op.getSymbolName());
      auto opcode_str = asm_str.split({" "}).first;
      LLVM_DEBUG(dbgs() << opcode_str << "\n"); // prints fscsr
      }
  return false
}