static void createFPFnStub(Function *F, Module *M, FPParamVariant PV, const MipsSubtarget &Subtarget ) { bool PicMode = Subtarget.getRelocationModel() == Reloc::PIC_; bool LE = Subtarget.isLittle(); LLVMContext &Context = M->getContext(); std::string Name = F->getName(); std::string SectionName = ".mips16.fn." + Name; std::string StubName = "__fn_stub_" + Name; std::string LocalName = "$$__fn_local_" + Name; Function *FStub = Function::Create (F->getFunctionType(), Function::InternalLinkage, StubName, M); FStub->addFnAttr("mips16_fp_stub"); FStub->addFnAttr(llvm::Attribute::Naked); FStub->addFnAttr(llvm::Attribute::NoUnwind); FStub->addFnAttr(llvm::Attribute::NoInline); FStub->addFnAttr("nomips16"); FStub->setSection(SectionName); BasicBlock *BB = BasicBlock::Create(Context, "entry", FStub); InlineAsmHelper IAH(Context, BB); if (PicMode) { IAH.Out(".set noreorder"); IAH.Out(".cpload $$25"); IAH.Out(".set reorder"); IAH.Out(".reloc 0,R_MIPS_NONE," + Name); IAH.Out("la $$25," + LocalName); } else { IAH.Out("la $$25," + Name); } swapFPIntParams(PV, M, IAH, LE, false); IAH.Out("jr $$25"); IAH.Out(LocalName + " = " + Name); new UnreachableInst(FStub->getContext(), BB); }
// // 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)) { // pic mode calls are handled by already defined // helper functions if (Subtarget.getRelocationModel() != Reloc::PIC_ ) { Function *F_ = CI->getCalledFunction(); if (F_ && !isIntrinsicInline(F_) && needsFPHelperFromSig(*F_)) { assureFPCallStub(*F_, M, Subtarget); Modified=true; } } } } return Modified; }
// For llc. Set a group of ELF header flags void MipsELFStreamer::emitELFHeaderFlagsCG(const MipsSubtarget &Subtarget) { if (hasRawTextSupport()) return; // Update e_header flags MCAssembler& MCA = getAssembler(); unsigned EFlags = MCA.getELFHeaderEFlags(); // TODO: Need to add -mabicalls and -mno-abicalls flags. // Currently we assume that -mabicalls is the default. EFlags |= ELF::EF_MIPS_CPIC; if (Subtarget.inMips16Mode()) EFlags |= ELF::EF_MIPS_ARCH_ASE_M16; else EFlags |= ELF::EF_MIPS_NOREORDER; // Architecture if (Subtarget.hasMips64r2()) EFlags |= ELF::EF_MIPS_ARCH_64R2; else if (Subtarget.hasMips64()) EFlags |= ELF::EF_MIPS_ARCH_64; else if (Subtarget.hasMips32r2()) EFlags |= ELF::EF_MIPS_ARCH_32R2; else EFlags |= ELF::EF_MIPS_ARCH_32; if (Subtarget.inMicroMipsMode()) EFlags |= ELF::EF_MIPS_MICROMIPS; // ABI if (Subtarget.isABI_O32()) EFlags |= ELF::EF_MIPS_ABI_O32; // Relocation Model Reloc::Model RM = Subtarget.getRelocationModel(); if (RM == Reloc::PIC_ || RM == Reloc::Default) EFlags |= ELF::EF_MIPS_PIC; else if (RM == Reloc::Static) ; // Do nothing for Reloc::Static else llvm_unreachable("Unsupported relocation model for e_flags"); MCA.setELFHeaderEFlags(EFlags); }
MipsSEInstrInfo::MipsSEInstrInfo(const MipsSubtarget &STI) : MipsInstrInfo(STI, STI.getRelocationModel() == Reloc::PIC_ ? Mips::B : Mips::J), RI() {}
// // Make sure that we know we already need a stub for this function. // Having called needsFPHelperFromSig // static void assureFPCallStub(Function &F, Module *M, const MipsSubtarget &Subtarget){ // for now we only need them for static relocation if (Subtarget.getRelocationModel() == Reloc::PIC_) return; LLVMContext &Context = M->getContext(); bool LE = Subtarget.isLittle(); std::string Name = F.getName(); std::string SectionName = ".mips16.call.fp." + Name; std::string StubName = "__call_stub_fp_" + Name; // // see if we already have the stub // Function *FStub = M->getFunction(StubName); if (FStub && !FStub->isDeclaration()) return; FStub = Function::Create(F.getFunctionType(), Function::InternalLinkage, StubName, M); FStub->addFnAttr("mips16_fp_stub"); FStub->addFnAttr(llvm::Attribute::Naked); FStub->addFnAttr(llvm::Attribute::NoInline); FStub->addFnAttr(llvm::Attribute::NoUnwind); FStub->addFnAttr("nomips16"); FStub->setSection(SectionName); BasicBlock *BB = BasicBlock::Create(Context, "entry", FStub); InlineAsmHelper IAH(Context, BB); IAH.Out(".set reorder"); FPReturnVariant RV = whichFPReturnVariant(FStub->getReturnType()); FPParamVariant PV = whichFPParamVariantNeeded(F); swapFPIntParams(PV, M, IAH, LE, true); if (RV != NoFPRet) { IAH.Out("move $$18, $$31"); IAH.Out("jal " + Name); } else { IAH.Out("lui $$25,%hi(" + Name + ")"); IAH.Out("addiu $$25,$$25,%lo(" + Name + ")" ); } switch (RV) { case FRet: IAH.Out("mfc1 $$2,$$f0"); break; case DRet: if (LE) { IAH.Out("mfc1 $$2,$$f0"); IAH.Out("mfc1 $$3,$$f1"); } else { IAH.Out("mfc1 $$3,$$f0"); IAH.Out("mfc1 $$2,$$f1"); } break; case CFRet: if (LE) { IAH.Out("mfc1 $$2,$$f0"); IAH.Out("mfc1 $$3,$$f2"); } else { IAH.Out("mfc1 $$3,$$f0"); IAH.Out("mfc1 $$3,$$f2"); } break; case CDRet: if (LE) { IAH.Out("mfc1 $$4,$$f2"); IAH.Out("mfc1 $$5,$$f3"); IAH.Out("mfc1 $$2,$$f0"); IAH.Out("mfc1 $$3,$$f1"); } else { IAH.Out("mfc1 $$5,$$f2"); IAH.Out("mfc1 $$4,$$f3"); IAH.Out("mfc1 $$3,$$f0"); IAH.Out("mfc1 $$2,$$f1"); } break; case NoFPRet: break; } if (RV != NoFPRet) IAH.Out("jr $$18"); else IAH.Out("jr $$25"); new UnreachableInst(Context, BB); }