Search code examples
c++compiler-constructionllvmllvm-ir

How to verify if LLVM "ret" instruction returns void?


I have the following snippet of code:

static LLVMContext TempContext;
Type * RetTy = Type::getVoidTy(TempContext)
for (Instruction *I : ListOfInstructions) {
  if (isa<ReturnInst>(I)) {
    RetTy = I->getOperand(0)->getType();
    break
  }
}

Where I am trying to capture the RetTy of a instruction, void or not, so I can use it on

getOrInsertFunction("TempF", FunctionType::get(RetTy, ArgsTys,false));

This code works as long as the ret instruction is not a ret void.

I tried to add a second if to check the void case, but this does not seem to work, and execution stops on the in the FunctionType::get(...) function, printing a back trace.

for (Instruction *I : ListOfInstructions) {
  if (isa<ReturnInst>(I)) {
    if ( I->getOperand(0)->getType() != Type::getVoidTy(TempContext)) {
      RetTy = I->getOperand(0)->getType();
      break
    }
  }
}                                            

Note that removing the for loop all together works and execution continues, as the function FunctionType::get(...) handles the initialized Type * RetTy = Type::getVoidTy(TempContext) "void" value for RetTy just fine. But then I can't capture when a llvm function returns non-void values.


How do I know when an instruction I is a return instruction and it is returning Void in LLVM IR?


Solution

  • The problem with your current code is that ret void does not have an operand, so calling getOperand(0) accesses invalid data.

    Replacing your if with:

    if (ReturnInst *ri = dyn_cast<ReturnInst>(I))
    {
      if (ri->getNumOperands() == 0)
      {
        errs() << "VOID: " << *ri << "\n";
      }
      else
      {
        errs() << "NON-VOID: " << *ri << "\n";
      }
    }
    

    Now, this code will output VOID: ret void, having correctly detected the instruction.

    As an alternative, you could retrieve the return type for the function using any instruction by relying on instructions being contained by a function I->getFunction()->getReturnType(); however, this would assume that the function is well-formed and its ReturnInst matches its type and the instruction is part of a function.