Example #1
0
//
// Returns of float, double and complex need to be handled with a helper
// function.
//
static bool fixupFPReturnAndCall(Function &F, Module *M,
                                 const MipsTargetMachine &TM) {
  bool Modified = false;
  LLVMContext &C = M->getContext();
  Type *MyVoid = Type::getVoidTy(C);
  for (auto &BB: F)
    for (auto &I: BB) {
      if (const ReturnInst *RI = dyn_cast<ReturnInst>(&I)) {
        Value *RVal = RI->getReturnValue();
        if (!RVal) continue;
        //
        // If there is a return value and it needs a helper function,
        // figure out which one and add a call before the actual
        // return to this helper. The purpose of the helper is to move
        // floating point values from their soft float return mapping to
        // where they would have been mapped to in floating point registers.
        //
        Type *T = RVal->getType();
        FPReturnVariant RV = whichFPReturnVariant(T);
        if (RV == NoFPRet) continue;
        static const char *const Helper[NoFPRet] = {
          "__mips16_ret_sf", "__mips16_ret_df", "__mips16_ret_sc",
          "__mips16_ret_dc"
        };
        const char *Name = Helper[RV];
        AttributeList A;
        Value *Params[] = {RVal};
        Modified = true;
        //
        // These helper functions have a different calling ABI so
        // this __Mips16RetHelper indicates that so that later
        // during call setup, the proper call lowering to the helper
        // functions will take place.
        //
        A = A.addAttribute(C, AttributeList::FunctionIndex,
                           "__Mips16RetHelper");
        A = A.addAttribute(C, AttributeList::FunctionIndex,
                           Attribute::ReadNone);
        A = A.addAttribute(C, AttributeList::FunctionIndex,
                           Attribute::NoInline);
        Value *F = (M->getOrInsertFunction(Name, A, MyVoid, T));
        CallInst::Create(F, Params, "", &I);
      } else if (const CallInst *CI = dyn_cast<CallInst>(&I)) {
        FunctionType *FT = CI->getFunctionType();
        Function *F_ =  CI->getCalledFunction();
        if (needsFPReturnHelper(*FT) &&
            !(F_ && isIntrinsicInline(F_))) {
          Modified=true;
          F.addFnAttr("saveS2");
        }
        if (F_ && !isIntrinsicInline(F_)) {
          // pic mode calls are handled by already defined
          // helper functions
          if (needsFPReturnHelper(*F_)) {
            Modified=true;
            F.addFnAttr("saveS2");
          }
          if (!TM.isPositionIndependent()) {
            if (needsFPHelperFromSig(*F_)) {
              assureFPCallStub(*F_, M, TM);
              Modified=true;
            }
          }
        }
      }
    }
  return Modified;
}