const Function *PatmosInstrInfo::getCallee(const MachineInstr *MI) const
{
  const Function *F = NULL;

  if (MI->isBundle()) {
    MachineBasicBlock::const_instr_iterator it = MI;

    while ((++it)->isBundledWithPred()) {
      if (!it->isCall()) continue;
      if (F) return NULL;
      F = getCallee(it);
      if (!F) return NULL;
    }

    return F;
  }

  // get target
  const MachineOperand &MO(MI->getOperand(2));

  // try to find the target of the call
  if (MO.isGlobal()) {
    // is the global value a function?
    F = dyn_cast<Function>(MO.getGlobal());
  }
  else if (MO.isSymbol()) {
    // find the function in the current module
    const Module &M = *MI->getParent()->getParent()->getFunction()->getParent();

    F = dyn_cast_or_null<Function>(M.getNamedValue(MO.getSymbolName()));
  }

  return F;
}
bool PatmosInstrInfo::getCallees(const MachineInstr *MI,
                                 SmallSet<const Function*,2> &Callees) const
{
  if (MI->isBundle()) {
    MachineBasicBlock::const_instr_iterator it = MI;
    bool safe = true;

    while ((++it)->isBundledWithPred()) {
      if (!it->isCall() && !it->isInlineAsm()) continue;
      safe = getCallees(it, Callees) && safe;
    }
    return safe;
  }

  if (MI->isCall()) {
    const Function *F = getCallee(MI);
    if (F) {
      Callees.insert(F);
      return true;
    } else {
      // Could be an indirect call..
      return false;
    }
  }
  else if (MI->isInlineAsm()) {
    // We can skip the first operand as this should be the asm string.
    for (unsigned int i = 1; i < MI->getNumOperands(); i++) {
      const MachineOperand &MO(MI->getOperand(i));
      const Function *F = NULL;

      // try to find the target of the call
      if (MO.isGlobal()) {
        // is the global value a function?
        F = dyn_cast_or_null<Function>(MO.getGlobal());
      }
      else if (MO.isSymbol()) {
        // find the function in the current module
        const Module &M =
                  *MI->getParent()->getParent()->getFunction()->getParent();

        F = dyn_cast_or_null<Function>(M.getNamedValue(MO.getSymbolName()));
      }
      if (F) {
        // We are assuming here that if inline-asm uses a function reference
        // as operand, then it is probably used for a call.
        Callees.insert(F);
      }
    }

    // TODO for now we assume that inline asm does not contain CALLR and
    //      that all callees are passed as asm operands. We should do a check
    //      similar to hasCall() here.
    return true;
  }
  else {
    // No other instruction should do a call.
    return true;
  }
}
Example #3
0
void LanaiAsmPrinter::EmitInstruction(const MachineInstr *MI) {
  MachineBasicBlock::const_instr_iterator I = MI->getIterator();
  MachineBasicBlock::const_instr_iterator E = MI->getParent()->instr_end();

  do {
    if (I->isCall()) {
      emitCallInstruction(&*I);
      continue;
    }

    customEmitInstruction(&*I);
  } while ((++I != E) && I->isInsideBundle());
}