static void createFPFnStub(Function *F, Module *M, FPParamVariant PV, const MipsTargetMachine &TM) { bool PicMode = TM.getRelocationModel() == Reloc::PIC_; bool LE = TM.isLittleEndian(); 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); }
static void createFPFnStub(Function *F, Module *M, FPParamVariant PV, const MipsTargetMachine &TM) { bool PicMode = TM.isPositionIndependent(); bool LE = TM.isLittleEndian(); 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); std::string AsmText; if (PicMode) { AsmText += ".set noreorder\n"; AsmText += ".cpload $$25\n"; AsmText += ".set reorder\n"; AsmText += ".reloc 0, R_MIPS_NONE, " + Name + "\n"; AsmText += "la $$25, " + LocalName + "\n"; } else AsmText += "la $$25, " + Name + "\n"; AsmText += swapFPIntParams(PV, M, LE, false); AsmText += "jr $$25\n"; AsmText += LocalName + " = " + Name + "\n"; EmitInlineAsm(Context, BB, AsmText); new UnreachableInst(FStub->getContext(), BB); }
// // Make sure that we know we already need a stub for this function. // Having called needsFPHelperFromSig // static void assureFPCallStub(Function &F, Module *M, const MipsTargetMachine &TM) { // for now we only need them for static relocation if (TM.isPositionIndependent()) return; LLVMContext &Context = M->getContext(); bool LE = TM.isLittleEndian(); 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); FPReturnVariant RV = whichFPReturnVariant(FStub->getReturnType()); FPParamVariant PV = whichFPParamVariantNeeded(F); std::string AsmText; AsmText += ".set reorder\n"; AsmText += swapFPIntParams(PV, M, LE, true); if (RV != NoFPRet) { AsmText += "move $$18, $$31\n"; AsmText += "jal " + Name + "\n"; } else { AsmText += "lui $$25, %hi(" + Name + ")\n"; AsmText += "addiu $$25, $$25, %lo(" + Name + ")\n"; } switch (RV) { case FRet: AsmText += "mfc1 $$2, $$f0\n"; break; case DRet: if (LE) { AsmText += "mfc1 $$2, $$f0\n"; AsmText += "mfc1 $$3, $$f1\n"; } else { AsmText += "mfc1 $$3, $$f0\n"; AsmText += "mfc1 $$2, $$f1\n"; } break; case CFRet: if (LE) { AsmText += "mfc1 $$2, $$f0\n"; AsmText += "mfc1 $$3, $$f2\n"; } else { AsmText += "mfc1 $$3, $$f0\n"; AsmText += "mfc1 $$3, $$f2\n"; } break; case CDRet: if (LE) { AsmText += "mfc1 $$4, $$f2\n"; AsmText += "mfc1 $$5, $$f3\n"; AsmText += "mfc1 $$2, $$f0\n"; AsmText += "mfc1 $$3, $$f1\n"; } else { AsmText += "mfc1 $$5, $$f2\n"; AsmText += "mfc1 $$4, $$f3\n"; AsmText += "mfc1 $$3, $$f0\n"; AsmText += "mfc1 $$2, $$f1\n"; } break; case NoFPRet: break; } if (RV != NoFPRet) AsmText += "jr $$18\n"; else AsmText += "jr $$25\n"; EmitInlineAsm(Context, BB, AsmText); new UnreachableInst(Context, BB); }