Beispiel #1
0
static bool needsFPHelperFromSig(Function &F) {
  return needsFPStubFromParams(F) || needsFPReturnHelper(F);
}
Beispiel #2
0
//
// Returns of float, double and complex need to be handled with a helper
// function.
//
static bool fixupFPReturnAndCall
  (Function &F, Module *M,  const MipsSubtarget &Subtarget) {
  bool Modified = false;
  LLVMContext &C = M->getContext();
  Type *MyVoid = Type::getVoidTy(C);
  for (Function::iterator BB = F.begin(), E = F.end(); BB != E; ++BB)
    for (BasicBlock::iterator I = BB->begin(), E = BB->end();
         I != E; ++I) {
      Instruction &Inst = *I;
      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* Helper[NoFPRet] =
          {"__mips16_ret_sf", "__mips16_ret_df", "__mips16_ret_sc",
           "__mips16_ret_dc"};
        const char *Name = Helper[RV];
        AttributeSet 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, AttributeSet::FunctionIndex,
                           "__Mips16RetHelper");
        A = A.addAttribute(C, AttributeSet::FunctionIndex,
                           Attribute::ReadNone);
        A = A.addAttribute(C, AttributeSet::FunctionIndex,
                           Attribute::NoInline);
        Value *F = (M->getOrInsertFunction(Name, A, MyVoid, T, NULL));
        CallInst::Create(F, Params, "", &Inst );
      } else if (const CallInst *CI = dyn_cast<CallInst>(I)) {
          const Value* V = CI->getCalledValue();
          const Type* T = 0;
          if (V) T = V->getType();
          const PointerType *PFT=0;
          if (T) PFT = dyn_cast<PointerType>(T);
          const FunctionType *FT=0;
          if (PFT) FT = dyn_cast<FunctionType>(PFT->getElementType());
          Function *F_ =  CI->getCalledFunction();
          if (FT && 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 (Subtarget.getRelocationModel() != Reloc::PIC_ ) {
              if (needsFPHelperFromSig(*F_)) {
                assureFPCallStub(*F_, M, Subtarget);
                Modified=true;
              }
            }
          }
      }
    }
  return Modified;
}