void MipsSERegisterInfo::eliminateFI(MachineBasicBlock::iterator II, unsigned OpNo, int FrameIndex, uint64_t StackSize, int64_t SPOffset) const { MachineInstr &MI = *II; MachineFunction &MF = *MI.getParent()->getParent(); MachineFrameInfo *MFI = MF.getFrameInfo(); MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>(); const std::vector<CalleeSavedInfo> &CSI = MFI->getCalleeSavedInfo(); int MinCSFI = 0; int MaxCSFI = -1; if (CSI.size()) { MinCSFI = CSI[0].getFrameIdx(); MaxCSFI = CSI[CSI.size() - 1].getFrameIdx(); } bool EhDataRegFI = MipsFI->isEhDataRegFI(FrameIndex); // The following stack frame objects are always referenced relative to $sp: // 1. Outgoing arguments. // 2. Pointer to dynamically allocated stack space. // 3. Locations for callee-saved registers. // 4. Locations for eh data registers. // Everything else is referenced relative to whatever register // getFrameRegister() returns. unsigned FrameReg; if ((FrameIndex >= MinCSFI && FrameIndex <= MaxCSFI) || EhDataRegFI) FrameReg = Subtarget.isABI_N64() ? Mips::SP_64 : Mips::SP; else FrameReg = getFrameRegister(MF); // Calculate final offset. // - There is no need to change the offset if the frame object is one of the // following: an outgoing argument, pointer to a dynamically allocated // stack space or a $gp restore location, // - If the frame object is any of the following, its offset must be adjusted // by adding the size of the stack: // incoming argument, callee-saved register location or local variable. bool IsKill = false; int64_t Offset; Offset = SPOffset + (int64_t)StackSize; Offset += MI.getOperand(OpNo + 1).getImm(); DEBUG(errs() << "Offset : " << Offset << "\n" << "<--------->\n"); if (!MI.isDebugValue()) { // Make sure Offset fits within the field available. // For MSA instructions, this is a 10-bit signed immediate (scaled by // element size), otherwise it is a 16-bit signed immediate. unsigned OffsetBitSize = getLoadStoreOffsetSizeInBits(MI.getOpcode()); unsigned OffsetAlign = getLoadStoreOffsetAlign(MI.getOpcode()); if (OffsetBitSize < 16 && isInt<16>(Offset) && (!isIntN(OffsetBitSize, Offset) || OffsetToAlignment(Offset, OffsetAlign) != 0)) { // If we have an offset that needs to fit into a signed n-bit immediate // (where n < 16) and doesn't, but does fit into 16-bits then use an ADDiu MachineBasicBlock &MBB = *MI.getParent(); DebugLoc DL = II->getDebugLoc(); unsigned ADDiu = Subtarget.isABI_N64() ? Mips::DADDiu : Mips::ADDiu; const TargetRegisterClass *RC = Subtarget.isABI_N64() ? &Mips::GPR64RegClass : &Mips::GPR32RegClass; MachineRegisterInfo &RegInfo = MBB.getParent()->getRegInfo(); unsigned Reg = RegInfo.createVirtualRegister(RC); const MipsSEInstrInfo &TII = *static_cast<const MipsSEInstrInfo *>( MBB.getParent()->getTarget().getInstrInfo()); BuildMI(MBB, II, DL, TII.get(ADDiu), Reg).addReg(FrameReg).addImm(Offset); FrameReg = Reg; Offset = 0; IsKill = true; } else if (!isInt<16>(Offset)) { // Otherwise split the offset into 16-bit pieces and add it in multiple // instructions. MachineBasicBlock &MBB = *MI.getParent(); DebugLoc DL = II->getDebugLoc(); unsigned ADDu = Subtarget.isABI_N64() ? Mips::DADDu : Mips::ADDu; unsigned NewImm = 0; const MipsSEInstrInfo &TII = *static_cast<const MipsSEInstrInfo *>( MBB.getParent()->getTarget().getInstrInfo()); unsigned Reg = TII.loadImmediate(Offset, MBB, II, DL, OffsetBitSize == 16 ? &NewImm : nullptr); BuildMI(MBB, II, DL, TII.get(ADDu), Reg).addReg(FrameReg) .addReg(Reg, RegState::Kill); FrameReg = Reg; Offset = SignExtend64<16>(NewImm); IsKill = true; } } MI.getOperand(OpNo).ChangeToRegister(FrameReg, false, false, IsKill); MI.getOperand(OpNo + 1).ChangeToImmediate(Offset); }
// FrameIndex represent objects inside a abstract stack. // We must replace FrameIndex with an stack/frame pointer // direct reference. void MipsRegisterInfo:: eliminateFrameIndex(MachineBasicBlock::iterator II, int SPAdj, RegScavenger *RS) const { MachineInstr &MI = *II; MachineFunction &MF = *MI.getParent()->getParent(); MachineFrameInfo *MFI = MF.getFrameInfo(); MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>(); unsigned i = 0; while (!MI.getOperand(i).isFI()) { ++i; assert(i < MI.getNumOperands() && "Instr doesn't have FrameIndex operand!"); } DEBUG(errs() << "\nFunction : " << MF.getFunction()->getName() << "\n"; errs() << "<--------->\n" << MI); int FrameIndex = MI.getOperand(i).getIndex(); uint64_t stackSize = MF.getFrameInfo()->getStackSize(); int64_t spOffset = MF.getFrameInfo()->getObjectOffset(FrameIndex); DEBUG(errs() << "FrameIndex : " << FrameIndex << "\n" << "spOffset : " << spOffset << "\n" << "stackSize : " << stackSize << "\n"); const std::vector<CalleeSavedInfo> &CSI = MFI->getCalleeSavedInfo(); int MinCSFI = 0; int MaxCSFI = -1; if (CSI.size()) { MinCSFI = CSI[0].getFrameIdx(); MaxCSFI = CSI[CSI.size() - 1].getFrameIdx(); } // The following stack frame objects are always referenced relative to $sp: // 1. Outgoing arguments. // 2. Pointer to dynamically allocated stack space. // 3. Locations for callee-saved registers. // Everything else is referenced relative to whatever register // getFrameRegister() returns. unsigned FrameReg; if (MipsFI->isOutArgFI(FrameIndex) || MipsFI->isDynAllocFI(FrameIndex) || (FrameIndex >= MinCSFI && FrameIndex <= MaxCSFI)) FrameReg = Subtarget.isABI_N64() ? Mips::SP_64 : Mips::SP; else FrameReg = getFrameRegister(MF); // Calculate final offset. // - There is no need to change the offset if the frame object is one of the // following: an outgoing argument, pointer to a dynamically allocated // stack space or a $gp restore location, // - If the frame object is any of the following, its offset must be adjusted // by adding the size of the stack: // incoming argument, callee-saved register location or local variable. int64_t Offset; if (MipsFI->isOutArgFI(FrameIndex) || MipsFI->isGPFI(FrameIndex) || MipsFI->isDynAllocFI(FrameIndex)) Offset = spOffset; else Offset = spOffset + (int64_t)stackSize; Offset += MI.getOperand(i+1).getImm(); DEBUG(errs() << "Offset : " << Offset << "\n" << "<--------->\n"); // If MI is not a debug value, make sure Offset fits in the 16-bit immediate // field. if (!MI.isDebugValue() && !isInt<16>(Offset)) { MachineBasicBlock &MBB = *MI.getParent(); DebugLoc DL = II->getDebugLoc(); MipsAnalyzeImmediate AnalyzeImm; unsigned Size = Subtarget.isABI_N64() ? 64 : 32; unsigned LUi = Subtarget.isABI_N64() ? Mips::LUi64 : Mips::LUi; unsigned ADDu = Subtarget.isABI_N64() ? Mips::DADDu : Mips::ADDu; unsigned ZEROReg = Subtarget.isABI_N64() ? Mips::ZERO_64 : Mips::ZERO; unsigned ATReg = Subtarget.isABI_N64() ? Mips::AT_64 : Mips::AT; const MipsAnalyzeImmediate::InstSeq &Seq = AnalyzeImm.Analyze(Offset, Size, true /* LastInstrIsADDiu */); MipsAnalyzeImmediate::InstSeq::const_iterator Inst = Seq.begin(); // FIXME: change this when mips goes MC". BuildMI(MBB, II, DL, TII.get(Mips::NOAT)); // The first instruction can be a LUi, which is different from other // instructions (ADDiu, ORI and SLL) in that it does not have a register // operand. if (Inst->Opc == LUi) BuildMI(MBB, II, DL, TII.get(LUi), ATReg) .addImm(SignExtend64<16>(Inst->ImmOpnd)); else BuildMI(MBB, II, DL, TII.get(Inst->Opc), ATReg).addReg(ZEROReg) .addImm(SignExtend64<16>(Inst->ImmOpnd)); // Build the remaining instructions in Seq except for the last one. for (++Inst; Inst != Seq.end() - 1; ++Inst) BuildMI(MBB, II, DL, TII.get(Inst->Opc), ATReg).addReg(ATReg) .addImm(SignExtend64<16>(Inst->ImmOpnd)); BuildMI(MBB, II, DL, TII.get(ADDu), ATReg).addReg(FrameReg).addReg(ATReg); FrameReg = ATReg; Offset = SignExtend64<16>(Inst->ImmOpnd); BuildMI(MBB, ++II, MI.getDebugLoc(), TII.get(Mips::ATMACRO)); } MI.getOperand(i).ChangeToRegister(FrameReg, false); MI.getOperand(i+1).ChangeToImmediate(Offset); }
void MipsFrameLowering::emitPrologue(MachineFunction &MF) const { MachineBasicBlock &MBB = MF.front(); MachineFrameInfo *MFI = MF.getFrameInfo(); MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>(); const MipsRegisterInfo *RegInfo = static_cast<const MipsRegisterInfo*>(MF.getTarget().getRegisterInfo()); const MipsInstrInfo &TII = *static_cast<const MipsInstrInfo*>(MF.getTarget().getInstrInfo()); MachineBasicBlock::iterator MBBI = MBB.begin(); DebugLoc dl = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc(); bool isPIC = (MF.getTarget().getRelocationModel() == Reloc::PIC_); unsigned NewReg = 0; int NewImm = 0; bool ATUsed; // First, compute final stack size. unsigned RegSize = STI.isGP32bit() ? 4 : 8; unsigned StackAlign = getStackAlignment(); unsigned LocalVarAreaOffset = MipsFI->needGPSaveRestore() ? (MFI->getObjectOffset(MipsFI->getGPFI()) + RegSize) : MipsFI->getMaxCallFrameSize(); unsigned StackSize = AlignOffset(LocalVarAreaOffset, StackAlign) + AlignOffset(MFI->getStackSize(), StackAlign); // Update stack size MFI->setStackSize(StackSize); BuildMI(MBB, MBBI, dl, TII.get(Mips::NOREORDER)); // TODO: check need from GP here. if (isPIC && STI.isABI_O32()) BuildMI(MBB, MBBI, dl, TII.get(Mips::CPLOAD)) .addReg(RegInfo->getPICCallReg()); BuildMI(MBB, MBBI, dl, TII.get(Mips::NOMACRO)); // No need to allocate space on the stack. if (StackSize == 0 && !MFI->adjustsStack()) return; // Adjust stack : addi sp, sp, (-imm) ATUsed = expandRegLargeImmPair(Mips::SP, -StackSize, NewReg, NewImm, MBB, MBBI); BuildMI(MBB, MBBI, dl, TII.get(Mips::ADDiu), Mips::SP) .addReg(NewReg).addImm(NewImm); // FIXME: change this when mips goes MC". if (ATUsed) BuildMI(MBB, MBBI, dl, TII.get(Mips::ATMACRO)); // Find the instruction past the last instruction that saves a callee-saved // register to the stack. const std::vector<CalleeSavedInfo> &CSI = MFI->getCalleeSavedInfo(); for (unsigned i = 0; i < CSI.size(); ++i) ++MBBI; // if framepointer enabled, set it to point to the stack pointer. if (hasFP(MF)) // Insert instruction "move $fp, $sp" at this location. BuildMI(MBB, MBBI, dl, TII.get(Mips::ADDu), Mips::FP) .addReg(Mips::SP).addReg(Mips::ZERO); // Restore GP from the saved stack location if (MipsFI->needGPSaveRestore()) BuildMI(MBB, MBBI, dl, TII.get(Mips::CPRESTORE)) .addImm(MFI->getObjectOffset(MipsFI->getGPFI())); // EH Frame infomation. MachineModuleInfo &MMI = MF.getMMI(); std::vector<MachineMove> &Moves = MMI.getFrameMoves(); MCSymbol *FrameLabel = MMI.getContext().CreateTempSymbol(); BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::PROLOG_LABEL)).addSym(FrameLabel); if (hasFP(MF)) { MachineLocation SPDst(Mips::FP); MachineLocation SPSrc(Mips::SP); Moves.push_back(MachineMove(FrameLabel, SPDst, SPSrc)); } if (StackSize) { MachineLocation SPDst(MachineLocation::VirtualFP); MachineLocation SPSrc(MachineLocation::VirtualFP, -StackSize); Moves.push_back(MachineMove(FrameLabel, SPDst, SPSrc)); } for (std::vector<CalleeSavedInfo>::const_iterator I = CSI.begin(), E = CSI.end(); I != E; ++I) { int64_t Offset = MFI->getObjectOffset(I->getFrameIdx()); MachineLocation CSDst(MachineLocation::VirtualFP, Offset); MachineLocation CSSrc(I->getReg()); Moves.push_back(MachineMove(FrameLabel, CSDst, CSSrc)); } }
void MipsSEFrameLowering::emitPrologue(MachineFunction &MF) const { MachineBasicBlock &MBB = MF.front(); MachineFrameInfo *MFI = MF.getFrameInfo(); MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>(); const MipsSEInstrInfo &TII = *static_cast<const MipsSEInstrInfo*>(MF.getTarget().getInstrInfo()); const MipsRegisterInfo &RegInfo = *static_cast<const MipsRegisterInfo*>(MF.getTarget().getRegisterInfo()); MachineBasicBlock::iterator MBBI = MBB.begin(); DebugLoc dl = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc(); unsigned SP = STI.isABI_N64() ? Mips::SP_64 : Mips::SP; unsigned FP = STI.isABI_N64() ? Mips::FP_64 : Mips::FP; unsigned ZERO = STI.isABI_N64() ? Mips::ZERO_64 : Mips::ZERO; unsigned ADDu = STI.isABI_N64() ? Mips::DADDu : Mips::ADDu; // First, compute final stack size. uint64_t StackSize = MFI->getStackSize(); // No need to allocate space on the stack. if (StackSize == 0 && !MFI->adjustsStack()) return; MachineModuleInfo &MMI = MF.getMMI(); const MCRegisterInfo *MRI = MMI.getContext().getRegisterInfo(); MachineLocation DstML, SrcML; // Adjust stack. TII.adjustStackPtr(SP, -StackSize, MBB, MBBI); // emit ".cfi_def_cfa_offset StackSize" MCSymbol *AdjustSPLabel = MMI.getContext().CreateTempSymbol(); BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::PROLOG_LABEL)).addSym(AdjustSPLabel); MMI.addFrameInst( MCCFIInstruction::createDefCfaOffset(AdjustSPLabel, -StackSize)); const std::vector<CalleeSavedInfo> &CSI = MFI->getCalleeSavedInfo(); if (CSI.size()) { // Find the instruction past the last instruction that saves a callee-saved // register to the stack. for (unsigned i = 0; i < CSI.size(); ++i) ++MBBI; // Iterate over list of callee-saved registers and emit .cfi_offset // directives. MCSymbol *CSLabel = MMI.getContext().CreateTempSymbol(); BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::PROLOG_LABEL)).addSym(CSLabel); for (std::vector<CalleeSavedInfo>::const_iterator I = CSI.begin(), E = CSI.end(); I != E; ++I) { int64_t Offset = MFI->getObjectOffset(I->getFrameIdx()); unsigned Reg = I->getReg(); // If Reg is a double precision register, emit two cfa_offsets, // one for each of the paired single precision registers. if (Mips::AFGR64RegClass.contains(Reg)) { unsigned Reg0 = MRI->getDwarfRegNum(RegInfo.getSubReg(Reg, Mips::sub_fpeven), true); unsigned Reg1 = MRI->getDwarfRegNum(RegInfo.getSubReg(Reg, Mips::sub_fpodd), true); if (!STI.isLittle()) std::swap(Reg0, Reg1); MMI.addFrameInst( MCCFIInstruction::createOffset(CSLabel, Reg0, Offset)); MMI.addFrameInst( MCCFIInstruction::createOffset(CSLabel, Reg1, Offset + 4)); } else { // Reg is either in GPR32 or FGR32. MMI.addFrameInst(MCCFIInstruction::createOffset( CSLabel, MRI->getDwarfRegNum(Reg, 1), Offset)); } } } if (MipsFI->callsEhReturn()) { const TargetRegisterClass *RC = STI.isABI_N64() ? &Mips::GPR64RegClass : &Mips::GPR32RegClass; // Insert instructions that spill eh data registers. for (int I = 0; I < 4; ++I) { if (!MBB.isLiveIn(ehDataReg(I))) MBB.addLiveIn(ehDataReg(I)); TII.storeRegToStackSlot(MBB, MBBI, ehDataReg(I), false, MipsFI->getEhDataRegFI(I), RC, &RegInfo); } // Emit .cfi_offset directives for eh data registers. MCSymbol *CSLabel2 = MMI.getContext().CreateTempSymbol(); BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::PROLOG_LABEL)).addSym(CSLabel2); for (int I = 0; I < 4; ++I) { int64_t Offset = MFI->getObjectOffset(MipsFI->getEhDataRegFI(I)); unsigned Reg = MRI->getDwarfRegNum(ehDataReg(I), true); MMI.addFrameInst(MCCFIInstruction::createOffset(CSLabel2, Reg, Offset)); } } // if framepointer enabled, set it to point to the stack pointer. if (hasFP(MF)) { // Insert instruction "move $fp, $sp" at this location. BuildMI(MBB, MBBI, dl, TII.get(ADDu), FP).addReg(SP).addReg(ZERO); // emit ".cfi_def_cfa_register $fp" MCSymbol *SetFPLabel = MMI.getContext().CreateTempSymbol(); BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::PROLOG_LABEL)).addSym(SetFPLabel); MMI.addFrameInst(MCCFIInstruction::createDefCfaRegister( SetFPLabel, MRI->getDwarfRegNum(FP, true))); } }
void MipsFrameInfo::adjustMipsStackFrame(MachineFunction &MF) const { MachineFrameInfo *MFI = MF.getFrameInfo(); MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>(); const std::vector<CalleeSavedInfo> &CSI = MFI->getCalleeSavedInfo(); unsigned StackAlign = MF.getTarget().getFrameInfo()->getStackAlignment(); unsigned RegSize = STI.isGP32bit() ? 4 : 8; bool HasGP = MipsFI->needGPSaveRestore(); // Min and Max CSI FrameIndex. int MinCSFI = -1, MaxCSFI = -1; // See the description at MipsMachineFunction.h int TopCPUSavedRegOff = -1, TopFPUSavedRegOff = -1; // Replace the dummy '0' SPOffset by the negative offsets, as explained on // LowerFormalArguments. Leaving '0' for while is necessary to avoid the // approach done by calculateFrameObjectOffsets to the stack frame. MipsFI->adjustLoadArgsFI(MFI); MipsFI->adjustStoreVarArgsFI(MFI); // It happens that the default stack frame allocation order does not directly // map to the convention used for mips. So we must fix it. We move the callee // save register slots after the local variables area, as described in the // stack frame above. unsigned CalleeSavedAreaSize = 0; if (!CSI.empty()) { MinCSFI = CSI[0].getFrameIdx(); MaxCSFI = CSI[CSI.size()-1].getFrameIdx(); } for (unsigned i = 0, e = CSI.size(); i != e; ++i) CalleeSavedAreaSize += MFI->getObjectAlignment(CSI[i].getFrameIdx()); unsigned StackOffset = HasGP ? (MipsFI->getGPStackOffset()+RegSize) : (STI.isABI_O32() ? 16 : 0); // Adjust local variables. They should come on the stack right // after the arguments. int LastOffsetFI = -1; for (int i = 0, e = MFI->getObjectIndexEnd(); i != e; ++i) { if (i >= MinCSFI && i <= MaxCSFI) continue; if (MFI->isDeadObjectIndex(i)) continue; unsigned Offset = StackOffset + MFI->getObjectOffset(i) - CalleeSavedAreaSize; if (LastOffsetFI == -1) LastOffsetFI = i; if (Offset > MFI->getObjectOffset(LastOffsetFI)) LastOffsetFI = i; MFI->setObjectOffset(i, Offset); } // Adjust CPU Callee Saved Registers Area. Registers RA and FP must // be saved in this CPU Area. This whole area must be aligned to the // default Stack Alignment requirements. if (LastOffsetFI >= 0) StackOffset = MFI->getObjectOffset(LastOffsetFI)+ MFI->getObjectSize(LastOffsetFI); StackOffset = ((StackOffset+StackAlign-1)/StackAlign*StackAlign); for (unsigned i = 0, e = CSI.size(); i != e ; ++i) { unsigned Reg = CSI[i].getReg(); if (!Mips::CPURegsRegisterClass->contains(Reg)) break; MFI->setObjectOffset(CSI[i].getFrameIdx(), StackOffset); TopCPUSavedRegOff = StackOffset; StackOffset += MFI->getObjectAlignment(CSI[i].getFrameIdx()); } // Stack locations for FP and RA. If only one of them is used, // the space must be allocated for both, otherwise no space at all. if (hasFP(MF) || MFI->adjustsStack()) { // FP stack location MFI->setObjectOffset(MFI->CreateStackObject(RegSize, RegSize, true), StackOffset); MipsFI->setFPStackOffset(StackOffset); TopCPUSavedRegOff = StackOffset; StackOffset += RegSize; // SP stack location MFI->setObjectOffset(MFI->CreateStackObject(RegSize, RegSize, true), StackOffset); MipsFI->setRAStackOffset(StackOffset); StackOffset += RegSize; if (MFI->adjustsStack()) TopCPUSavedRegOff += RegSize; } StackOffset = ((StackOffset+StackAlign-1)/StackAlign*StackAlign); // Adjust FPU Callee Saved Registers Area. This Area must be // aligned to the default Stack Alignment requirements. for (unsigned i = 0, e = CSI.size(); i != e; ++i) { unsigned Reg = CSI[i].getReg(); if (Mips::CPURegsRegisterClass->contains(Reg)) continue; MFI->setObjectOffset(CSI[i].getFrameIdx(), StackOffset); TopFPUSavedRegOff = StackOffset; StackOffset += MFI->getObjectAlignment(CSI[i].getFrameIdx()); } StackOffset = ((StackOffset+StackAlign-1)/StackAlign*StackAlign); // Update frame info MFI->setStackSize(StackOffset); // Recalculate the final tops offset. The final values must be '0' // if there isn't a callee saved register for CPU or FPU, otherwise // a negative offset is needed. if (TopCPUSavedRegOff >= 0) MipsFI->setCPUTopSavedRegOff(TopCPUSavedRegOff-StackOffset); if (TopFPUSavedRegOff >= 0) MipsFI->setFPUTopSavedRegOff(TopFPUSavedRegOff-StackOffset); }
void MipsFrameLowering::emitPrologue(MachineFunction &MF) const { MachineBasicBlock &MBB = MF.front(); MachineFrameInfo *MFI = MF.getFrameInfo(); MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>(); const MipsRegisterInfo *RegInfo = static_cast<const MipsRegisterInfo*>(MF.getTarget().getRegisterInfo()); const MipsInstrInfo &TII = *static_cast<const MipsInstrInfo*>(MF.getTarget().getInstrInfo()); MachineBasicBlock::iterator MBBI = MBB.begin(); DebugLoc dl = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc(); bool isPIC = (MF.getTarget().getRelocationModel() == Reloc::PIC_); unsigned NewReg = 0; int NewImm = 0; bool ATUsed; // Get the right frame order for Mips. adjustMipsStackFrame(MF); // Get the number of bytes to allocate from the FrameInfo. unsigned StackSize = MFI->getStackSize(); // No need to allocate space on the stack. if (StackSize == 0 && !MFI->adjustsStack()) return; int FPOffset = MipsFI->getFPStackOffset(); int RAOffset = MipsFI->getRAStackOffset(); BuildMI(MBB, MBBI, dl, TII.get(Mips::NOREORDER)); // TODO: check need from GP here. if (isPIC && STI.isABI_O32()) BuildMI(MBB, MBBI, dl, TII.get(Mips::CPLOAD)) .addReg(RegInfo->getPICCallReg()); BuildMI(MBB, MBBI, dl, TII.get(Mips::NOMACRO)); // Adjust stack : addi sp, sp, (-imm) ATUsed = expandRegLargeImmPair(Mips::SP, -StackSize, NewReg, NewImm, MBB, MBBI); BuildMI(MBB, MBBI, dl, TII.get(Mips::ADDiu), Mips::SP) .addReg(NewReg).addImm(NewImm); // FIXME: change this when mips goes MC". if (ATUsed) BuildMI(MBB, MBBI, dl, TII.get(Mips::ATMACRO)); // Save the return address only if the function isnt a leaf one. // sw $ra, stack_loc($sp) if (MFI->adjustsStack()) { expandRegLargeImmPair(Mips::SP, RAOffset, NewReg, NewImm, MBB, MBBI); BuildMI(MBB, MBBI, dl, TII.get(Mips::SW)) .addReg(Mips::RA).addImm(NewImm).addReg(NewReg); // FIXME: change this when mips goes MC". if (ATUsed) BuildMI(MBB, MBBI, dl, TII.get(Mips::ATMACRO)); } // if framepointer enabled, save it and set it // to point to the stack pointer if (hasFP(MF)) { // sw $fp,stack_loc($sp) expandRegLargeImmPair(Mips::SP, FPOffset, NewReg, NewImm, MBB, MBBI); BuildMI(MBB, MBBI, dl, TII.get(Mips::SW)) .addReg(Mips::FP).addImm(NewImm).addReg(NewReg); // FIXME: change this when mips goes MC". if (ATUsed) BuildMI(MBB, MBBI, dl, TII.get(Mips::ATMACRO)); // move $fp, $sp BuildMI(MBB, MBBI, dl, TII.get(Mips::ADDu), Mips::FP) .addReg(Mips::SP).addReg(Mips::ZERO); } // Restore GP from the saved stack location if (MipsFI->needGPSaveRestore()) BuildMI(MBB, MBBI, dl, TII.get(Mips::CPRESTORE)) .addImm(MipsFI->getGPStackOffset()); }
void MipsSEFrameLowering::emitInterruptPrologueStub( MachineFunction &MF, MachineBasicBlock &MBB) const { MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>(); MachineBasicBlock::iterator MBBI = MBB.begin(); DebugLoc DL = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc(); // Report an error the target doesn't support Mips32r2 or later. // The epilogue relies on the use of the "ehb" to clear execution // hazards. Pre R2 Mips relies on an implementation defined number // of "ssnop"s to clear the execution hazard. Support for ssnop hazard // clearing is not provided so reject that configuration. if (!STI.hasMips32r2()) report_fatal_error( "\"interrupt\" attribute is not supported on pre-MIPS32R2 or " "MIPS16 targets."); // The GP register contains the "user" value, so we cannot perform // any gp relative loads until we restore the "kernel" or "system" gp // value. Until support is written we shall only accept the static // relocation model. if ((STI.getRelocationModel() != Reloc::Static)) report_fatal_error("\"interrupt\" attribute is only supported for the " "static relocation model on MIPS at the present time."); if (!STI.isABI_O32() || STI.hasMips64()) report_fatal_error("\"interrupt\" attribute is only supported for the " "O32 ABI on MIPS32R2+ at the present time."); // Perform ISR handling like GCC StringRef IntKind = MF.getFunction()->getFnAttribute("interrupt").getValueAsString(); const TargetRegisterClass *PtrRC = &Mips::GPR32RegClass; // EIC interrupt handling needs to read the Cause register to disable // interrupts. if (IntKind == "eic") { // Coprocessor registers are always live per se. MBB.addLiveIn(Mips::COP013); BuildMI(MBB, MBBI, DL, STI.getInstrInfo()->get(Mips::MFC0), Mips::K0) .addReg(Mips::COP013) .addImm(0) .setMIFlag(MachineInstr::FrameSetup); BuildMI(MBB, MBBI, DL, STI.getInstrInfo()->get(Mips::EXT), Mips::K0) .addReg(Mips::K0) .addImm(10) .addImm(6) .setMIFlag(MachineInstr::FrameSetup); } // Fetch and spill EPC MBB.addLiveIn(Mips::COP014); BuildMI(MBB, MBBI, DL, STI.getInstrInfo()->get(Mips::MFC0), Mips::K1) .addReg(Mips::COP014) .addImm(0) .setMIFlag(MachineInstr::FrameSetup); STI.getInstrInfo()->storeRegToStack(MBB, MBBI, Mips::K1, false, MipsFI->getISRRegFI(0), PtrRC, STI.getRegisterInfo(), 0); // Fetch and Spill Status MBB.addLiveIn(Mips::COP012); BuildMI(MBB, MBBI, DL, STI.getInstrInfo()->get(Mips::MFC0), Mips::K1) .addReg(Mips::COP012) .addImm(0) .setMIFlag(MachineInstr::FrameSetup); STI.getInstrInfo()->storeRegToStack(MBB, MBBI, Mips::K1, false, MipsFI->getISRRegFI(1), PtrRC, STI.getRegisterInfo(), 0); // Build the configuration for disabling lower priority interrupts. Non EIC // interrupts need to be masked off with zero, EIC from the Cause register. unsigned InsPosition = 8; unsigned InsSize = 0; unsigned SrcReg = Mips::ZERO; // If the interrupt we're tied to is the EIC, switch the source for the // masking off interrupts to the cause register. if (IntKind == "eic") { SrcReg = Mips::K0; InsPosition = 10; InsSize = 6; } else InsSize = StringSwitch<unsigned>(IntKind) .Case("sw0", 1) .Case("sw1", 2) .Case("hw0", 3) .Case("hw1", 4) .Case("hw2", 5) .Case("hw3", 6) .Case("hw4", 7) .Case("hw5", 8) .Default(0); assert(InsSize != 0 && "Unknown interrupt type!"); BuildMI(MBB, MBBI, DL, STI.getInstrInfo()->get(Mips::INS), Mips::K1) .addReg(SrcReg) .addImm(InsPosition) .addImm(InsSize) .addReg(Mips::K1) .setMIFlag(MachineInstr::FrameSetup); // Mask off KSU, ERL, EXL BuildMI(MBB, MBBI, DL, STI.getInstrInfo()->get(Mips::INS), Mips::K1) .addReg(Mips::ZERO) .addImm(1) .addImm(4) .addReg(Mips::K1) .setMIFlag(MachineInstr::FrameSetup); // Disable the FPU as we are not spilling those register sets. if (!STI.useSoftFloat()) BuildMI(MBB, MBBI, DL, STI.getInstrInfo()->get(Mips::INS), Mips::K1) .addReg(Mips::ZERO) .addImm(29) .addImm(1) .addReg(Mips::K1) .setMIFlag(MachineInstr::FrameSetup); // Set the new status BuildMI(MBB, MBBI, DL, STI.getInstrInfo()->get(Mips::MTC0), Mips::COP012) .addReg(Mips::K1) .addImm(0) .setMIFlag(MachineInstr::FrameSetup); }
// Insert instructions to initialize the global base register in the // first MBB of the function. When the ABI is O32 and the relocation model is // PIC, the necessary instructions are emitted later to prevent optimization // passes from moving them. void MipsDAGToDAGISel::InitGlobalBaseReg(MachineFunction &MF) { MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>(); if (!MipsFI->globalBaseRegSet()) return; MachineBasicBlock &MBB = MF.front(); MachineBasicBlock::iterator I = MBB.begin(); MachineRegisterInfo &RegInfo = MF.getRegInfo(); const TargetInstrInfo &TII = *MF.getTarget().getInstrInfo(); DebugLoc DL = I != MBB.end() ? I->getDebugLoc() : DebugLoc(); unsigned V0, V1, V2, GlobalBaseReg = MipsFI->getGlobalBaseReg(); const TargetRegisterClass *RC; if (Subtarget.isABI_N64()) RC = (const TargetRegisterClass*)&Mips::CPU64RegsRegClass; else if (Subtarget.inMips16Mode()) RC = (const TargetRegisterClass*)&Mips::CPU16RegsRegClass; else RC = (const TargetRegisterClass*)&Mips::CPURegsRegClass; V0 = RegInfo.createVirtualRegister(RC); V1 = RegInfo.createVirtualRegister(RC); V2 = RegInfo.createVirtualRegister(RC); if (Subtarget.isABI_N64()) { MF.getRegInfo().addLiveIn(Mips::T9_64); MBB.addLiveIn(Mips::T9_64); // lui $v0, %hi(%neg(%gp_rel(fname))) // daddu $v1, $v0, $t9 // daddiu $globalbasereg, $v1, %lo(%neg(%gp_rel(fname))) const GlobalValue *FName = MF.getFunction(); BuildMI(MBB, I, DL, TII.get(Mips::LUi64), V0) .addGlobalAddress(FName, 0, MipsII::MO_GPOFF_HI); BuildMI(MBB, I, DL, TII.get(Mips::DADDu), V1).addReg(V0) .addReg(Mips::T9_64); BuildMI(MBB, I, DL, TII.get(Mips::DADDiu), GlobalBaseReg).addReg(V1) .addGlobalAddress(FName, 0, MipsII::MO_GPOFF_LO); return; } if (Subtarget.inMips16Mode()) { BuildMI(MBB, I, DL, TII.get(Mips::LiRxImmX16), V0) .addExternalSymbol("_gp_disp", MipsII::MO_ABS_HI); BuildMI(MBB, I, DL, TII.get(Mips::AddiuRxPcImmX16), V1) .addExternalSymbol("_gp_disp", MipsII::MO_ABS_LO); BuildMI(MBB, I, DL, TII.get(Mips::SllX16), V2).addReg(V0).addImm(16); BuildMI(MBB, I, DL, TII.get(Mips::AdduRxRyRz16), GlobalBaseReg) .addReg(V1).addReg(V2); return; } if (MF.getTarget().getRelocationModel() == Reloc::Static) { // Set global register to __gnu_local_gp. // // lui $v0, %hi(__gnu_local_gp) // addiu $globalbasereg, $v0, %lo(__gnu_local_gp) BuildMI(MBB, I, DL, TII.get(Mips::LUi), V0) .addExternalSymbol("__gnu_local_gp", MipsII::MO_ABS_HI); BuildMI(MBB, I, DL, TII.get(Mips::ADDiu), GlobalBaseReg).addReg(V0) .addExternalSymbol("__gnu_local_gp", MipsII::MO_ABS_LO); return; } MF.getRegInfo().addLiveIn(Mips::T9); MBB.addLiveIn(Mips::T9); if (Subtarget.isABI_N32()) { // lui $v0, %hi(%neg(%gp_rel(fname))) // addu $v1, $v0, $t9 // addiu $globalbasereg, $v1, %lo(%neg(%gp_rel(fname))) const GlobalValue *FName = MF.getFunction(); BuildMI(MBB, I, DL, TII.get(Mips::LUi), V0) .addGlobalAddress(FName, 0, MipsII::MO_GPOFF_HI); BuildMI(MBB, I, DL, TII.get(Mips::ADDu), V1).addReg(V0).addReg(Mips::T9); BuildMI(MBB, I, DL, TII.get(Mips::ADDiu), GlobalBaseReg).addReg(V1) .addGlobalAddress(FName, 0, MipsII::MO_GPOFF_LO); return; } assert(Subtarget.isABI_O32()); // For O32 ABI, the following instruction sequence is emitted to initialize // the global base register: // // 0. lui $2, %hi(_gp_disp) // 1. addiu $2, $2, %lo(_gp_disp) // 2. addu $globalbasereg, $2, $t9 // // We emit only the last instruction here. // // GNU linker requires that the first two instructions appear at the beginning // of a function and no instructions be inserted before or between them. // The two instructions are emitted during lowering to MC layer in order to // avoid any reordering. // // Register $2 (Mips::V0) is added to the list of live-in registers to ensure // the value instruction 1 (addiu) defines is valid when instruction 2 (addu) // reads it. MF.getRegInfo().addLiveIn(Mips::V0); MBB.addLiveIn(Mips::V0); BuildMI(MBB, I, DL, TII.get(Mips::ADDu), GlobalBaseReg) .addReg(Mips::V0).addReg(Mips::T9); }
void Mips16TargetLowering:: getOpndList(SmallVectorImpl<SDValue> &Ops, std::deque< std::pair<unsigned, SDValue> > &RegsToPass, bool IsPICCall, bool GlobalOrExternal, bool InternalLinkage, bool IsCallReloc, CallLoweringInfo &CLI, SDValue Callee, SDValue Chain) const { SelectionDAG &DAG = CLI.DAG; MachineFunction &MF = DAG.getMachineFunction(); MipsFunctionInfo *FuncInfo = MF.getInfo<MipsFunctionInfo>(); const char* Mips16HelperFunction = nullptr; bool NeedMips16Helper = false; if (Subtarget.inMips16HardFloat()) { // // currently we don't have symbols tagged with the mips16 or mips32 // qualifier so we will assume that we don't know what kind it is. // and generate the helper // bool LookupHelper = true; if (ExternalSymbolSDNode *S = dyn_cast<ExternalSymbolSDNode>(CLI.Callee)) { Mips16Libcall Find = { RTLIB::UNKNOWN_LIBCALL, S->getSymbol() }; if (std::binary_search(std::begin(HardFloatLibCalls), std::end(HardFloatLibCalls), Find)) LookupHelper = false; else { const char *Symbol = S->getSymbol(); Mips16IntrinsicHelperType IntrinsicFind = { Symbol, "" }; const Mips16HardFloatInfo::FuncSignature *Signature = Mips16HardFloatInfo::findFuncSignature(Symbol); if (!IsPICCall && (Signature && (FuncInfo->StubsNeeded.find(Symbol) == FuncInfo->StubsNeeded.end()))) { FuncInfo->StubsNeeded[Symbol] = Signature; // // S2 is normally saved if the stub is for a function which // returns a float or double value and is not otherwise. This is // because more work is required after the function the stub // is calling completes, and so the stub cannot directly return // and the stub has no stack space to store the return address so // S2 is used for that purpose. // In order to take advantage of not saving S2, we need to also // optimize the call in the stub and this requires some further // functionality in MipsAsmPrinter which we don't have yet. // So for now we always save S2. The optimization will be done // in a follow-on patch. // if (1 || (Signature->RetSig != Mips16HardFloatInfo::NoFPRet)) FuncInfo->setSaveS2(); } // one more look at list of intrinsics const Mips16IntrinsicHelperType *Helper = std::lower_bound(std::begin(Mips16IntrinsicHelper), std::end(Mips16IntrinsicHelper), IntrinsicFind); if (Helper != std::end(Mips16IntrinsicHelper) && *Helper == IntrinsicFind) { Mips16HelperFunction = Helper->Helper; NeedMips16Helper = true; LookupHelper = false; } } } else if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(CLI.Callee)) { Mips16Libcall Find = { RTLIB::UNKNOWN_LIBCALL, G->getGlobal()->getName().data() }; if (std::binary_search(std::begin(HardFloatLibCalls), std::end(HardFloatLibCalls), Find)) LookupHelper = false; } if (LookupHelper) Mips16HelperFunction = getMips16HelperFunction(CLI.RetTy, CLI.getArgs(), NeedMips16Helper); } SDValue JumpTarget = Callee; // T9 should contain the address of the callee function if // -relocation-model=pic or it is an indirect call. if (IsPICCall || !GlobalOrExternal) { unsigned V0Reg = Mips::V0; if (NeedMips16Helper) { RegsToPass.push_front(std::make_pair(V0Reg, Callee)); JumpTarget = DAG.getExternalSymbol(Mips16HelperFunction, getPointerTy()); ExternalSymbolSDNode *S = cast<ExternalSymbolSDNode>(JumpTarget); JumpTarget = getAddrGlobal(S, CLI.DL, JumpTarget.getValueType(), DAG, MipsII::MO_GOT, Chain, FuncInfo->callPtrInfo(S->getSymbol())); } else RegsToPass.push_front(std::make_pair((unsigned)Mips::T9, Callee)); } Ops.push_back(JumpTarget); MipsTargetLowering::getOpndList(Ops, RegsToPass, IsPICCall, GlobalOrExternal, InternalLinkage, IsCallReloc, CLI, Callee, Chain); }
void MipsFrameLowering::emitPrologue(MachineFunction &MF) const { MachineBasicBlock &MBB = MF.front(); MachineFrameInfo *MFI = MF.getFrameInfo(); MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>(); const MipsRegisterInfo *RegInfo = static_cast<const MipsRegisterInfo*>(MF.getTarget().getRegisterInfo()); const MipsInstrInfo &TII = *static_cast<const MipsInstrInfo*>(MF.getTarget().getInstrInfo()); MachineBasicBlock::iterator MBBI = MBB.begin(); DebugLoc dl = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc(); unsigned SP = STI.isABI_N64() ? Mips::SP_64 : Mips::SP; unsigned FP = STI.isABI_N64() ? Mips::FP_64 : Mips::FP; unsigned ZERO = STI.isABI_N64() ? Mips::ZERO_64 : Mips::ZERO; unsigned ADDu = STI.isABI_N64() ? Mips::DADDu : Mips::ADDu; unsigned ADDiu = STI.isABI_N64() ? Mips::DADDiu : Mips::ADDiu; // First, compute final stack size. unsigned StackAlign = getStackAlignment(); uint64_t StackSize = RoundUpToAlignment(MFI->getStackSize(), StackAlign); if (MipsFI->globalBaseRegSet()) StackSize += MFI->getObjectOffset(MipsFI->getGlobalRegFI()) + StackAlign; else StackSize += RoundUpToAlignment(MipsFI->getMaxCallFrameSize(), StackAlign); // Update stack size MFI->setStackSize(StackSize); // No need to allocate space on the stack. if (StackSize == 0 && !MFI->adjustsStack()) return; MachineModuleInfo &MMI = MF.getMMI(); std::vector<MachineMove> &Moves = MMI.getFrameMoves(); MachineLocation DstML, SrcML; // Adjust stack. if (isInt<16>(-StackSize)) // addi sp, sp, (-stacksize) BuildMI(MBB, MBBI, dl, TII.get(ADDiu), SP).addReg(SP).addImm(-StackSize); else { // Expand immediate that doesn't fit in 16-bit. unsigned ATReg = STI.isABI_N64() ? Mips::AT_64 : Mips::AT; MF.getInfo<MipsFunctionInfo>()->setEmitNOAT(); Mips::loadImmediate(-StackSize, STI.isABI_N64(), TII, MBB, MBBI, dl, false, 0); BuildMI(MBB, MBBI, dl, TII.get(ADDu), SP).addReg(SP).addReg(ATReg); } // emit ".cfi_def_cfa_offset StackSize" MCSymbol *AdjustSPLabel = MMI.getContext().CreateTempSymbol(); BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::PROLOG_LABEL)).addSym(AdjustSPLabel); DstML = MachineLocation(MachineLocation::VirtualFP); SrcML = MachineLocation(MachineLocation::VirtualFP, -StackSize); Moves.push_back(MachineMove(AdjustSPLabel, DstML, SrcML)); const std::vector<CalleeSavedInfo> &CSI = MFI->getCalleeSavedInfo(); if (CSI.size()) { // Find the instruction past the last instruction that saves a callee-saved // register to the stack. for (unsigned i = 0; i < CSI.size(); ++i) ++MBBI; // Iterate over list of callee-saved registers and emit .cfi_offset // directives. MCSymbol *CSLabel = MMI.getContext().CreateTempSymbol(); BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::PROLOG_LABEL)).addSym(CSLabel); for (std::vector<CalleeSavedInfo>::const_iterator I = CSI.begin(), E = CSI.end(); I != E; ++I) { int64_t Offset = MFI->getObjectOffset(I->getFrameIdx()); unsigned Reg = I->getReg(); // If Reg is a double precision register, emit two cfa_offsets, // one for each of the paired single precision registers. if (Mips::AFGR64RegClass.contains(Reg)) { MachineLocation DstML0(MachineLocation::VirtualFP, Offset); MachineLocation DstML1(MachineLocation::VirtualFP, Offset + 4); MachineLocation SrcML0(RegInfo->getSubReg(Reg, Mips::sub_fpeven)); MachineLocation SrcML1(RegInfo->getSubReg(Reg, Mips::sub_fpodd)); if (!STI.isLittle()) std::swap(SrcML0, SrcML1); Moves.push_back(MachineMove(CSLabel, DstML0, SrcML0)); Moves.push_back(MachineMove(CSLabel, DstML1, SrcML1)); } else { // Reg is either in CPURegs or FGR32. DstML = MachineLocation(MachineLocation::VirtualFP, Offset); SrcML = MachineLocation(Reg); Moves.push_back(MachineMove(CSLabel, DstML, SrcML)); } } } // if framepointer enabled, set it to point to the stack pointer. if (hasFP(MF)) { // Insert instruction "move $fp, $sp" at this location. BuildMI(MBB, MBBI, dl, TII.get(ADDu), FP).addReg(SP).addReg(ZERO); // emit ".cfi_def_cfa_register $fp" MCSymbol *SetFPLabel = MMI.getContext().CreateTempSymbol(); BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::PROLOG_LABEL)).addSym(SetFPLabel); DstML = MachineLocation(FP); SrcML = MachineLocation(MachineLocation::VirtualFP); Moves.push_back(MachineMove(SetFPLabel, DstML, SrcML)); } }
// Insert instructions to initialize the global base register in the // first MBB of the function. When the ABI is O32 and the relocation model is // PIC, the necessary instructions are emitted later to prevent optimization // passes from moving them. void MipsDAGToDAGISel::InitGlobalBaseReg(MachineFunction &MF) { MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>(); if (!MipsFI->globalBaseRegSet()) return; MachineBasicBlock &MBB = MF.front(); MachineBasicBlock::iterator I = MBB.begin(); MachineRegisterInfo &RegInfo = MF.getRegInfo(); const TargetInstrInfo &TII = *MF.getTarget().getInstrInfo(); DebugLoc DL = I != MBB.end() ? I->getDebugLoc() : DebugLoc(); unsigned V0, V1, GlobalBaseReg = MipsFI->getGlobalBaseReg(); bool FixGlobalBaseReg = MipsFI->globalBaseRegFixed(); if (Subtarget.isABI_O32() && FixGlobalBaseReg) // $gp is the global base register. V0 = V1 = GlobalBaseReg; else { const TargetRegisterClass *RC; RC = Subtarget.isABI_N64() ? Mips::CPU64RegsRegisterClass : Mips::CPURegsRegisterClass; V0 = RegInfo.createVirtualRegister(RC); V1 = RegInfo.createVirtualRegister(RC); } if (Subtarget.isABI_N64()) { MF.getRegInfo().addLiveIn(Mips::T9_64); MBB.addLiveIn(Mips::T9_64); // lui $v0, %hi(%neg(%gp_rel(fname))) // daddu $v1, $v0, $t9 // daddiu $globalbasereg, $v1, %lo(%neg(%gp_rel(fname))) const GlobalValue *FName = MF.getFunction(); BuildMI(MBB, I, DL, TII.get(Mips::LUi64), V0) .addGlobalAddress(FName, 0, MipsII::MO_GPOFF_HI); BuildMI(MBB, I, DL, TII.get(Mips::DADDu), V1).addReg(V0).addReg(Mips::T9_64); BuildMI(MBB, I, DL, TII.get(Mips::DADDiu), GlobalBaseReg).addReg(V1) .addGlobalAddress(FName, 0, MipsII::MO_GPOFF_LO); } else if (MF.getTarget().getRelocationModel() == Reloc::Static) { // Set global register to __gnu_local_gp. // // lui $v0, %hi(__gnu_local_gp) // addiu $globalbasereg, $v0, %lo(__gnu_local_gp) BuildMI(MBB, I, DL, TII.get(Mips::LUi), V0) .addExternalSymbol("__gnu_local_gp", MipsII::MO_ABS_HI); BuildMI(MBB, I, DL, TII.get(Mips::ADDiu), GlobalBaseReg).addReg(V0) .addExternalSymbol("__gnu_local_gp", MipsII::MO_ABS_LO); } else { MF.getRegInfo().addLiveIn(Mips::T9); MBB.addLiveIn(Mips::T9); if (Subtarget.isABI_N32()) { // lui $v0, %hi(%neg(%gp_rel(fname))) // addu $v1, $v0, $t9 // addiu $globalbasereg, $v1, %lo(%neg(%gp_rel(fname))) const GlobalValue *FName = MF.getFunction(); BuildMI(MBB, I, DL, TII.get(Mips::LUi), V0) .addGlobalAddress(FName, 0, MipsII::MO_GPOFF_HI); BuildMI(MBB, I, DL, TII.get(Mips::ADDu), V1).addReg(V0).addReg(Mips::T9); BuildMI(MBB, I, DL, TII.get(Mips::ADDiu), GlobalBaseReg).addReg(V1) .addGlobalAddress(FName, 0, MipsII::MO_GPOFF_LO); } else if (!MipsFI->globalBaseRegFixed()) { assert(Subtarget.isABI_O32()); BuildMI(MBB, I, DL, TII.get(Mips::SETGP2), GlobalBaseReg) .addReg(Mips::T9); } } }
void MipsSERegisterInfo::eliminateFI(MachineBasicBlock::iterator II, unsigned OpNo, int FrameIndex, uint64_t StackSize, int64_t SPOffset) const { MachineInstr &MI = *II; MachineFunction &MF = *MI.getParent()->getParent(); MachineFrameInfo *MFI = MF.getFrameInfo(); MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>(); const std::vector<CalleeSavedInfo> &CSI = MFI->getCalleeSavedInfo(); int MinCSFI = 0; int MaxCSFI = -1; if (CSI.size()) { MinCSFI = CSI[0].getFrameIdx(); MaxCSFI = CSI[CSI.size() - 1].getFrameIdx(); } bool EhDataRegFI = MipsFI->isEhDataRegFI(FrameIndex); // The following stack frame objects are always referenced relative to $sp: // 1. Outgoing arguments. // 2. Pointer to dynamically allocated stack space. // 3. Locations for callee-saved registers. // 4. Locations for eh data registers. // Everything else is referenced relative to whatever register // getFrameRegister() returns. unsigned FrameReg; if ((FrameIndex >= MinCSFI && FrameIndex <= MaxCSFI) || EhDataRegFI) FrameReg = Subtarget.isABI_N64() ? Mips::SP_64 : Mips::SP; else FrameReg = getFrameRegister(MF); // Calculate final offset. // - There is no need to change the offset if the frame object is one of the // following: an outgoing argument, pointer to a dynamically allocated // stack space or a $gp restore location, // - If the frame object is any of the following, its offset must be adjusted // by adding the size of the stack: // incoming argument, callee-saved register location or local variable. bool IsKill = false; int64_t Offset; Offset = SPOffset + (int64_t)StackSize; Offset += MI.getOperand(OpNo + 1).getImm(); DEBUG(errs() << "Offset : " << Offset << "\n" << "<--------->\n"); // If MI is not a debug value, make sure Offset fits in the 16-bit immediate // field. if (!MI.isDebugValue() && !isInt<16>(Offset)) { MachineBasicBlock &MBB = *MI.getParent(); DebugLoc DL = II->getDebugLoc(); unsigned ADDu = Subtarget.isABI_N64() ? Mips::DADDu : Mips::ADDu; unsigned NewImm; unsigned Reg = TII.loadImmediate(Offset, MBB, II, DL, &NewImm); BuildMI(MBB, II, DL, TII.get(ADDu), Reg).addReg(FrameReg) .addReg(Reg, RegState::Kill); FrameReg = Reg; Offset = SignExtend64<16>(NewImm); IsKill = true; } MI.getOperand(OpNo).ChangeToRegister(FrameReg, false, false, IsKill); MI.getOperand(OpNo + 1).ChangeToImmediate(Offset); }
void Mips16TargetLowering:: getOpndList(SmallVectorImpl<SDValue> &Ops, std::deque< std::pair<unsigned, SDValue> > &RegsToPass, bool IsPICCall, bool GlobalOrExternal, bool InternalLinkage, CallLoweringInfo &CLI, SDValue Callee, SDValue Chain) const { SelectionDAG &DAG = CLI.DAG; MachineFunction &MF = DAG.getMachineFunction(); MipsFunctionInfo *FuncInfo = MF.getInfo<MipsFunctionInfo>(); const char* Mips16HelperFunction = 0; bool NeedMips16Helper = false; if (Subtarget->inMips16HardFloat()) { // // currently we don't have symbols tagged with the mips16 or mips32 // qualifier so we will assume that we don't know what kind it is. // and generate the helper // bool LookupHelper = true; if (ExternalSymbolSDNode *S = dyn_cast<ExternalSymbolSDNode>(CLI.Callee)) { Mips16Libcall Find = { RTLIB::UNKNOWN_LIBCALL, S->getSymbol() }; if (std::binary_search(HardFloatLibCalls, array_endof(HardFloatLibCalls), Find)) LookupHelper = false; else { Mips16IntrinsicHelperType IntrinsicFind = {S->getSymbol(), ""}; // one more look at list of intrinsics if (std::binary_search(Mips16IntrinsicHelper, array_endof(Mips16IntrinsicHelper), IntrinsicFind)) { const Mips16IntrinsicHelperType *h =(std::find(Mips16IntrinsicHelper, array_endof(Mips16IntrinsicHelper), IntrinsicFind)); Mips16HelperFunction = h->Helper; NeedMips16Helper = true; LookupHelper = false; } } } else if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(CLI.Callee)) { Mips16Libcall Find = { RTLIB::UNKNOWN_LIBCALL, G->getGlobal()->getName().data() }; if (std::binary_search(HardFloatLibCalls, array_endof(HardFloatLibCalls), Find)) LookupHelper = false; } if (LookupHelper) Mips16HelperFunction = getMips16HelperFunction(CLI.RetTy, CLI.Args, NeedMips16Helper); } SDValue JumpTarget = Callee; // T9 should contain the address of the callee function if // -reloction-model=pic or it is an indirect call. if (IsPICCall || !GlobalOrExternal) { unsigned V0Reg = Mips::V0; if (NeedMips16Helper) { RegsToPass.push_front(std::make_pair(V0Reg, Callee)); JumpTarget = DAG.getExternalSymbol(Mips16HelperFunction, getPointerTy()); ExternalSymbolSDNode *S = cast<ExternalSymbolSDNode>(JumpTarget); JumpTarget = getAddrGlobal(S, JumpTarget.getValueType(), DAG, MipsII::MO_GOT, Chain, FuncInfo->callPtrInfo(S->getSymbol())); } else RegsToPass.push_front(std::make_pair((unsigned)Mips::T9, Callee)); } Ops.push_back(JumpTarget); MipsTargetLowering::getOpndList(Ops, RegsToPass, IsPICCall, GlobalOrExternal, InternalLinkage, CLI, Callee, Chain); }
void MipsFrameLowering::emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const { MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr(); MachineFrameInfo *MFI = MF.getFrameInfo(); MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>(); const MipsInstrInfo &TII = *static_cast<const MipsInstrInfo*>(MF.getTarget().getInstrInfo()); DebugLoc dl = MBBI->getDebugLoc(); // Get the number of bytes from FrameInfo int NumBytes = (int) MFI->getStackSize(); // Get the FI's where RA and FP are saved. int FPOffset = MipsFI->getFPStackOffset(); int RAOffset = MipsFI->getRAStackOffset(); unsigned NewReg = 0; int NewImm = 0; bool ATUsed = false; // if framepointer enabled, restore it and restore the // stack pointer if (hasFP(MF)) { // move $sp, $fp BuildMI(MBB, MBBI, dl, TII.get(Mips::ADDu), Mips::SP) .addReg(Mips::FP).addReg(Mips::ZERO); // lw $fp,stack_loc($sp) ATUsed = expandRegLargeImmPair(Mips::SP, FPOffset, NewReg, NewImm, MBB, MBBI); BuildMI(MBB, MBBI, dl, TII.get(Mips::LW), Mips::FP) .addImm(NewImm).addReg(NewReg); // FIXME: change this when mips goes MC". if (ATUsed) BuildMI(MBB, MBBI, dl, TII.get(Mips::ATMACRO)); } // Restore the return address only if the function isnt a leaf one. // lw $ra, stack_loc($sp) if (MFI->adjustsStack()) { expandRegLargeImmPair(Mips::SP, RAOffset, NewReg, NewImm, MBB, MBBI); BuildMI(MBB, MBBI, dl, TII.get(Mips::LW), Mips::RA) .addImm(NewImm).addReg(NewReg); // FIXME: change this when mips goes MC". if (ATUsed) BuildMI(MBB, MBBI, dl, TII.get(Mips::ATMACRO)); } // adjust stack : insert addi sp, sp, (imm) if (NumBytes) { expandRegLargeImmPair(Mips::SP, NumBytes, NewReg, NewImm, MBB, MBBI); BuildMI(MBB, MBBI, dl, TII.get(Mips::ADDiu), Mips::SP) .addReg(NewReg).addImm(NewImm); // FIXME: change this when mips goes MC". if (ATUsed) BuildMI(MBB, MBBI, dl, TII.get(Mips::ATMACRO)); } }
void MipsSEDAGToDAGISel::initGlobalBaseReg(MachineFunction &MF) { MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>(); if (!MipsFI->globalBaseRegSet()) return; MachineBasicBlock &MBB = MF.front(); MachineBasicBlock::iterator I = MBB.begin(); MachineRegisterInfo &RegInfo = MF.getRegInfo(); const TargetInstrInfo &TII = *Subtarget->getInstrInfo(); DebugLoc DL; unsigned V0, V1, GlobalBaseReg = MipsFI->getGlobalBaseReg(); const TargetRegisterClass *RC; const MipsABIInfo &ABI = static_cast<const MipsTargetMachine &>(TM).getABI(); RC = (ABI.IsN64()) ? &Mips::GPR64RegClass : &Mips::GPR32RegClass; V0 = RegInfo.createVirtualRegister(RC); V1 = RegInfo.createVirtualRegister(RC); if (ABI.IsN64()) { MF.getRegInfo().addLiveIn(Mips::T9_64); MBB.addLiveIn(Mips::T9_64); // lui $v0, %hi(%neg(%gp_rel(fname))) // daddu $v1, $v0, $t9 // daddiu $globalbasereg, $v1, %lo(%neg(%gp_rel(fname))) const GlobalValue *FName = MF.getFunction(); BuildMI(MBB, I, DL, TII.get(Mips::LUi64), V0) .addGlobalAddress(FName, 0, MipsII::MO_GPOFF_HI); BuildMI(MBB, I, DL, TII.get(Mips::DADDu), V1).addReg(V0) .addReg(Mips::T9_64); BuildMI(MBB, I, DL, TII.get(Mips::DADDiu), GlobalBaseReg).addReg(V1) .addGlobalAddress(FName, 0, MipsII::MO_GPOFF_LO); return; } if (!MF.getTarget().isPositionIndependent()) { // Set global register to __gnu_local_gp. // // lui $v0, %hi(__gnu_local_gp) // addiu $globalbasereg, $v0, %lo(__gnu_local_gp) BuildMI(MBB, I, DL, TII.get(Mips::LUi), V0) .addExternalSymbol("__gnu_local_gp", MipsII::MO_ABS_HI); BuildMI(MBB, I, DL, TII.get(Mips::ADDiu), GlobalBaseReg).addReg(V0) .addExternalSymbol("__gnu_local_gp", MipsII::MO_ABS_LO); return; } MF.getRegInfo().addLiveIn(Mips::T9); MBB.addLiveIn(Mips::T9); if (ABI.IsN32()) { // lui $v0, %hi(%neg(%gp_rel(fname))) // addu $v1, $v0, $t9 // addiu $globalbasereg, $v1, %lo(%neg(%gp_rel(fname))) const GlobalValue *FName = MF.getFunction(); BuildMI(MBB, I, DL, TII.get(Mips::LUi), V0) .addGlobalAddress(FName, 0, MipsII::MO_GPOFF_HI); BuildMI(MBB, I, DL, TII.get(Mips::ADDu), V1).addReg(V0).addReg(Mips::T9); BuildMI(MBB, I, DL, TII.get(Mips::ADDiu), GlobalBaseReg).addReg(V1) .addGlobalAddress(FName, 0, MipsII::MO_GPOFF_LO); return; } assert(ABI.IsO32()); // For O32 ABI, the following instruction sequence is emitted to initialize // the global base register: // // 0. lui $2, %hi(_gp_disp) // 1. addiu $2, $2, %lo(_gp_disp) // 2. addu $globalbasereg, $2, $t9 // // We emit only the last instruction here. // // GNU linker requires that the first two instructions appear at the beginning // of a function and no instructions be inserted before or between them. // The two instructions are emitted during lowering to MC layer in order to // avoid any reordering. // // Register $2 (Mips::V0) is added to the list of live-in registers to ensure // the value instruction 1 (addiu) defines is valid when instruction 2 (addu) // reads it. MF.getRegInfo().addLiveIn(Mips::V0); MBB.addLiveIn(Mips::V0); BuildMI(MBB, I, DL, TII.get(Mips::ADDu), GlobalBaseReg) .addReg(Mips::V0).addReg(Mips::T9); }
void MipsSEFrameLowering::emitPrologue(MachineFunction &MF, MachineBasicBlock &MBB) const { assert(&MF.front() == &MBB && "Shrink-wrapping not yet supported"); MachineFrameInfo *MFI = MF.getFrameInfo(); MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>(); const MipsSEInstrInfo &TII = *static_cast<const MipsSEInstrInfo *>(STI.getInstrInfo()); const MipsRegisterInfo &RegInfo = *static_cast<const MipsRegisterInfo *>(STI.getRegisterInfo()); MachineBasicBlock::iterator MBBI = MBB.begin(); DebugLoc dl; MipsABIInfo ABI = STI.getABI(); unsigned SP = ABI.GetStackPtr(); unsigned FP = ABI.GetFramePtr(); unsigned ZERO = ABI.GetNullPtr(); unsigned MOVE = ABI.GetGPRMoveOp(); unsigned ADDiu = ABI.GetPtrAddiuOp(); unsigned AND = ABI.IsN64() ? Mips::AND64 : Mips::AND; const TargetRegisterClass *RC = ABI.ArePtrs64bit() ? &Mips::GPR64RegClass : &Mips::GPR32RegClass; // First, compute final stack size. uint64_t StackSize = MFI->getStackSize(); // No need to allocate space on the stack. if (StackSize == 0 && !MFI->adjustsStack()) return; MachineModuleInfo &MMI = MF.getMMI(); const MCRegisterInfo *MRI = MMI.getContext().getRegisterInfo(); MachineLocation DstML, SrcML; // Adjust stack. TII.adjustStackPtr(SP, -StackSize, MBB, MBBI); // emit ".cfi_def_cfa_offset StackSize" unsigned CFIIndex = MMI.addFrameInst( MCCFIInstruction::createDefCfaOffset(nullptr, -StackSize)); BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION)) .addCFIIndex(CFIIndex); if (MF.getFunction()->hasFnAttribute("interrupt")) emitInterruptPrologueStub(MF, MBB); const std::vector<CalleeSavedInfo> &CSI = MFI->getCalleeSavedInfo(); if (CSI.size()) { // Find the instruction past the last instruction that saves a callee-saved // register to the stack. for (unsigned i = 0; i < CSI.size(); ++i) ++MBBI; // Iterate over list of callee-saved registers and emit .cfi_offset // directives. for (std::vector<CalleeSavedInfo>::const_iterator I = CSI.begin(), E = CSI.end(); I != E; ++I) { int64_t Offset = MFI->getObjectOffset(I->getFrameIdx()); unsigned Reg = I->getReg(); // If Reg is a double precision register, emit two cfa_offsets, // one for each of the paired single precision registers. if (Mips::AFGR64RegClass.contains(Reg)) { unsigned Reg0 = MRI->getDwarfRegNum(RegInfo.getSubReg(Reg, Mips::sub_lo), true); unsigned Reg1 = MRI->getDwarfRegNum(RegInfo.getSubReg(Reg, Mips::sub_hi), true); if (!STI.isLittle()) std::swap(Reg0, Reg1); unsigned CFIIndex = MMI.addFrameInst( MCCFIInstruction::createOffset(nullptr, Reg0, Offset)); BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION)) .addCFIIndex(CFIIndex); CFIIndex = MMI.addFrameInst( MCCFIInstruction::createOffset(nullptr, Reg1, Offset + 4)); BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION)) .addCFIIndex(CFIIndex); } else if (Mips::FGR64RegClass.contains(Reg)) { unsigned Reg0 = MRI->getDwarfRegNum(Reg, true); unsigned Reg1 = MRI->getDwarfRegNum(Reg, true) + 1; if (!STI.isLittle()) std::swap(Reg0, Reg1); unsigned CFIIndex = MMI.addFrameInst( MCCFIInstruction::createOffset(nullptr, Reg0, Offset)); BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION)) .addCFIIndex(CFIIndex); CFIIndex = MMI.addFrameInst( MCCFIInstruction::createOffset(nullptr, Reg1, Offset + 4)); BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION)) .addCFIIndex(CFIIndex); } else { // Reg is either in GPR32 or FGR32. unsigned CFIIndex = MMI.addFrameInst(MCCFIInstruction::createOffset( nullptr, MRI->getDwarfRegNum(Reg, 1), Offset)); BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION)) .addCFIIndex(CFIIndex); } } } if (MipsFI->callsEhReturn()) { // Insert instructions that spill eh data registers. for (int I = 0; I < 4; ++I) { if (!MBB.isLiveIn(ABI.GetEhDataReg(I))) MBB.addLiveIn(ABI.GetEhDataReg(I)); TII.storeRegToStackSlot(MBB, MBBI, ABI.GetEhDataReg(I), false, MipsFI->getEhDataRegFI(I), RC, &RegInfo); } // Emit .cfi_offset directives for eh data registers. for (int I = 0; I < 4; ++I) { int64_t Offset = MFI->getObjectOffset(MipsFI->getEhDataRegFI(I)); unsigned Reg = MRI->getDwarfRegNum(ABI.GetEhDataReg(I), true); unsigned CFIIndex = MMI.addFrameInst( MCCFIInstruction::createOffset(nullptr, Reg, Offset)); BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION)) .addCFIIndex(CFIIndex); } } // if framepointer enabled, set it to point to the stack pointer. if (hasFP(MF)) { // Insert instruction "move $fp, $sp" at this location. BuildMI(MBB, MBBI, dl, TII.get(MOVE), FP).addReg(SP).addReg(ZERO) .setMIFlag(MachineInstr::FrameSetup); // emit ".cfi_def_cfa_register $fp" unsigned CFIIndex = MMI.addFrameInst(MCCFIInstruction::createDefCfaRegister( nullptr, MRI->getDwarfRegNum(FP, true))); BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION)) .addCFIIndex(CFIIndex); if (RegInfo.needsStackRealignment(MF)) { // addiu $Reg, $zero, -MaxAlignment // andi $sp, $sp, $Reg unsigned VR = MF.getRegInfo().createVirtualRegister(RC); assert(isInt<16>(MFI->getMaxAlignment()) && "Function's alignment size requirement is not supported."); int MaxAlign = - (signed) MFI->getMaxAlignment(); BuildMI(MBB, MBBI, dl, TII.get(ADDiu), VR).addReg(ZERO) .addImm(MaxAlign); BuildMI(MBB, MBBI, dl, TII.get(AND), SP).addReg(SP).addReg(VR); if (hasBP(MF)) { // move $s7, $sp unsigned BP = STI.isABI_N64() ? Mips::S7_64 : Mips::S7; BuildMI(MBB, MBBI, dl, TII.get(MOVE), BP) .addReg(SP) .addReg(ZERO); } } } }
void MipsFrameLowering::emitPrologue(MachineFunction &MF) const { MachineBasicBlock &MBB = MF.front(); MachineFrameInfo *MFI = MF.getFrameInfo(); MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>(); const MipsRegisterInfo *RegInfo = static_cast<const MipsRegisterInfo*>(MF.getTarget().getRegisterInfo()); const MipsInstrInfo &TII = *static_cast<const MipsInstrInfo*>(MF.getTarget().getInstrInfo()); MachineBasicBlock::iterator MBBI = MBB.begin(); DebugLoc dl = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc(); bool isPIC = (MF.getTarget().getRelocationModel() == Reloc::PIC_); unsigned SP = STI.isABI_N64() ? Mips::SP_64 : Mips::SP; unsigned FP = STI.isABI_N64() ? Mips::FP_64 : Mips::FP; unsigned ZERO = STI.isABI_N64() ? Mips::ZERO_64 : Mips::ZERO; unsigned ADDu = STI.isABI_N64() ? Mips::DADDu : Mips::ADDu; unsigned ADDiu = STI.isABI_N64() ? Mips::DADDiu : Mips::ADDiu; // First, compute final stack size. unsigned RegSize = STI.isGP32bit() ? 4 : 8; unsigned StackAlign = getStackAlignment(); unsigned LocalVarAreaOffset = MipsFI->needGPSaveRestore() ? (MFI->getObjectOffset(MipsFI->getGPFI()) + RegSize) : MipsFI->getMaxCallFrameSize(); uint64_t StackSize = RoundUpToAlignment(LocalVarAreaOffset, StackAlign) + RoundUpToAlignment(MFI->getStackSize(), StackAlign); // Update stack size MFI->setStackSize(StackSize); // Emit instructions that set the global base register if the target ABI is // O32. if (isPIC && MipsFI->globalBaseRegSet() && STI.isABI_O32() && !MipsFI->globalBaseRegFixed()) { // See MipsInstrInfo.td for explanation. MachineBasicBlock *NewEntry = MF.CreateMachineBasicBlock(); MF.insert(&MBB, NewEntry); NewEntry->addSuccessor(&MBB); // Copy live in registers. for (MachineBasicBlock::livein_iterator R = MBB.livein_begin(); R != MBB.livein_end(); ++R) NewEntry->addLiveIn(*R); BuildMI(*NewEntry, NewEntry->begin(), dl, TII.get(Mips:: SETGP01), Mips::V0); } // No need to allocate space on the stack. if (StackSize == 0 && !MFI->adjustsStack()) return; MachineModuleInfo &MMI = MF.getMMI(); std::vector<MachineMove> &Moves = MMI.getFrameMoves(); MachineLocation DstML, SrcML; // Adjust stack. if (isInt<16>(-StackSize)) // addi sp, sp, (-stacksize) BuildMI(MBB, MBBI, dl, TII.get(ADDiu), SP).addReg(SP).addImm(-StackSize); else { // Expand immediate that doesn't fit in 16-bit. MipsFI->setEmitNOAT(); expandLargeImm(SP, -StackSize, STI.isABI_N64(), TII, MBB, MBBI, dl); } // emit ".cfi_def_cfa_offset StackSize" MCSymbol *AdjustSPLabel = MMI.getContext().CreateTempSymbol(); BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::PROLOG_LABEL)).addSym(AdjustSPLabel); DstML = MachineLocation(MachineLocation::VirtualFP); SrcML = MachineLocation(MachineLocation::VirtualFP, -StackSize); Moves.push_back(MachineMove(AdjustSPLabel, DstML, SrcML)); const std::vector<CalleeSavedInfo> &CSI = MFI->getCalleeSavedInfo(); if (CSI.size()) { // Find the instruction past the last instruction that saves a callee-saved // register to the stack. for (unsigned i = 0; i < CSI.size(); ++i) ++MBBI; // Iterate over list of callee-saved registers and emit .cfi_offset // directives. MCSymbol *CSLabel = MMI.getContext().CreateTempSymbol(); BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::PROLOG_LABEL)).addSym(CSLabel); for (std::vector<CalleeSavedInfo>::const_iterator I = CSI.begin(), E = CSI.end(); I != E; ++I) { int64_t Offset = MFI->getObjectOffset(I->getFrameIdx()); unsigned Reg = I->getReg(); // If Reg is a double precision register, emit two cfa_offsets, // one for each of the paired single precision registers. if (Mips::AFGR64RegisterClass->contains(Reg)) { const uint16_t *SubRegs = RegInfo->getSubRegisters(Reg); MachineLocation DstML0(MachineLocation::VirtualFP, Offset); MachineLocation DstML1(MachineLocation::VirtualFP, Offset + 4); MachineLocation SrcML0(*SubRegs); MachineLocation SrcML1(*(SubRegs + 1)); if (!STI.isLittle()) std::swap(SrcML0, SrcML1); Moves.push_back(MachineMove(CSLabel, DstML0, SrcML0)); Moves.push_back(MachineMove(CSLabel, DstML1, SrcML1)); } else { // Reg is either in CPURegs or FGR32. DstML = MachineLocation(MachineLocation::VirtualFP, Offset); SrcML = MachineLocation(Reg); Moves.push_back(MachineMove(CSLabel, DstML, SrcML)); } } } // if framepointer enabled, set it to point to the stack pointer. if (hasFP(MF)) { // Insert instruction "move $fp, $sp" at this location. BuildMI(MBB, MBBI, dl, TII.get(ADDu), FP).addReg(SP).addReg(ZERO); // emit ".cfi_def_cfa_register $fp" MCSymbol *SetFPLabel = MMI.getContext().CreateTempSymbol(); BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::PROLOG_LABEL)).addSym(SetFPLabel); DstML = MachineLocation(FP); SrcML = MachineLocation(MachineLocation::VirtualFP); Moves.push_back(MachineMove(SetFPLabel, DstML, SrcML)); } // Restore GP from the saved stack location if (MipsFI->needGPSaveRestore()) { unsigned Offset = MFI->getObjectOffset(MipsFI->getGPFI()); BuildMI(MBB, MBBI, dl, TII.get(Mips::CPRESTORE)).addImm(Offset) .addReg(Mips::GP); } }
void MipsFrameLowering::emitPrologue(MachineFunction &MF) const { MachineBasicBlock &MBB = MF.front(); MachineFrameInfo *MFI = MF.getFrameInfo(); MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>(); const MipsRegisterInfo *RegInfo = static_cast<const MipsRegisterInfo*>(MF.getTarget().getRegisterInfo()); const MipsInstrInfo &TII = *static_cast<const MipsInstrInfo*>(MF.getTarget().getInstrInfo()); MachineBasicBlock::iterator MBBI = MBB.begin(); DebugLoc dl = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc(); bool isPIC = (MF.getTarget().getRelocationModel() == Reloc::PIC_); unsigned NewReg = 0; int NewImm = 0; bool ATUsed; unsigned GP = STI.isABI_N64() ? Mips::GP_64 : Mips::GP; unsigned T9 = STI.isABI_N64() ? Mips::T9_64 : Mips::T9; unsigned SP = STI.isABI_N64() ? Mips::SP_64 : Mips::SP; unsigned FP = STI.isABI_N64() ? Mips::FP_64 : Mips::FP; unsigned ZERO = STI.isABI_N64() ? Mips::ZERO_64 : Mips::ZERO; unsigned ADDu = STI.isABI_N64() ? Mips::DADDu : Mips::ADDu; unsigned ADDiu = STI.isABI_N64() ? Mips::DADDiu : Mips::ADDiu; unsigned LUi = STI.isABI_N64() ? Mips::LUi64 : Mips::LUi; // First, compute final stack size. unsigned RegSize = STI.isGP32bit() ? 4 : 8; unsigned StackAlign = getStackAlignment(); unsigned LocalVarAreaOffset = MipsFI->needGPSaveRestore() ? (MFI->getObjectOffset(MipsFI->getGPFI()) + RegSize) : MipsFI->getMaxCallFrameSize(); unsigned StackSize = AlignOffset(LocalVarAreaOffset, StackAlign) + AlignOffset(MFI->getStackSize(), StackAlign); // Update stack size MFI->setStackSize(StackSize); BuildMI(MBB, MBBI, dl, TII.get(Mips::NOREORDER)); BuildMI(MBB, MBBI, dl, TII.get(Mips::NOMACRO)); // Emit instructions that set $gp using the the value of $t9. // O32 uses the directive .cpload while N32/64 requires three instructions to // do this. // TODO: Do not emit these instructions if no instructions use $gp. if (isPIC && STI.isABI_O32()) BuildMI(MBB, llvm::prior(MBBI), dl, TII.get(Mips::CPLOAD)) .addReg(RegInfo->getPICCallReg()); else if (STI.isABI_N64() || (isPIC && STI.isABI_N32())) { // lui $28,%hi(%neg(%gp_rel(fname))) // addu $28,$28,$25 // addiu $28,$28,%lo(%neg(%gp_rel(fname))) const GlobalValue *FName = MF.getFunction(); BuildMI(MBB, MBBI, dl, TII.get(LUi), GP) .addGlobalAddress(FName, 0, MipsII::MO_GPOFF_HI); BuildMI(MBB, MBBI, dl, TII.get(ADDu), GP).addReg(GP).addReg(T9); BuildMI(MBB, MBBI, dl, TII.get(ADDiu), GP).addReg(GP) .addGlobalAddress(FName, 0, MipsII::MO_GPOFF_LO); } // No need to allocate space on the stack. if (StackSize == 0 && !MFI->adjustsStack()) return; MachineModuleInfo &MMI = MF.getMMI(); std::vector<MachineMove> &Moves = MMI.getFrameMoves(); MachineLocation DstML, SrcML; // Adjust stack : addi sp, sp, (-imm) ATUsed = expandRegLargeImmPair(SP, -StackSize, NewReg, NewImm, MBB, MBBI); BuildMI(MBB, MBBI, dl, TII.get(ADDiu), SP).addReg(NewReg).addImm(NewImm); // FIXME: change this when mips goes MC". if (ATUsed) BuildMI(MBB, MBBI, dl, TII.get(Mips::ATMACRO)); // emit ".cfi_def_cfa_offset StackSize" MCSymbol *AdjustSPLabel = MMI.getContext().CreateTempSymbol(); BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::PROLOG_LABEL)).addSym(AdjustSPLabel); DstML = MachineLocation(MachineLocation::VirtualFP); SrcML = MachineLocation(MachineLocation::VirtualFP, -StackSize); Moves.push_back(MachineMove(AdjustSPLabel, DstML, SrcML)); const std::vector<CalleeSavedInfo> &CSI = MFI->getCalleeSavedInfo(); if (CSI.size()) { // Find the instruction past the last instruction that saves a callee-saved // register to the stack. for (unsigned i = 0; i < CSI.size(); ++i) ++MBBI; // Iterate over list of callee-saved registers and emit .cfi_offset // directives. MCSymbol *CSLabel = MMI.getContext().CreateTempSymbol(); BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::PROLOG_LABEL)).addSym(CSLabel); for (std::vector<CalleeSavedInfo>::const_iterator I = CSI.begin(), E = CSI.end(); I != E; ++I) { int64_t Offset = MFI->getObjectOffset(I->getFrameIdx()); unsigned Reg = I->getReg(); // If Reg is a double precision register, emit two cfa_offsets, // one for each of the paired single precision registers. if (Mips::AFGR64RegisterClass->contains(Reg)) { const unsigned *SubRegs = RegInfo->getSubRegisters(Reg); MachineLocation DstML0(MachineLocation::VirtualFP, Offset); MachineLocation DstML1(MachineLocation::VirtualFP, Offset + 4); MachineLocation SrcML0(*SubRegs); MachineLocation SrcML1(*(SubRegs + 1)); if (!STI.isLittle()) std::swap(SrcML0, SrcML1); Moves.push_back(MachineMove(CSLabel, DstML0, SrcML0)); Moves.push_back(MachineMove(CSLabel, DstML1, SrcML1)); } else { // Reg is either in CPURegs or FGR32. DstML = MachineLocation(MachineLocation::VirtualFP, Offset); SrcML = MachineLocation(Reg); Moves.push_back(MachineMove(CSLabel, DstML, SrcML)); } } } // if framepointer enabled, set it to point to the stack pointer. if (hasFP(MF)) { // Insert instruction "move $fp, $sp" at this location. BuildMI(MBB, MBBI, dl, TII.get(ADDu), FP).addReg(SP).addReg(ZERO); // emit ".cfi_def_cfa_register $fp" MCSymbol *SetFPLabel = MMI.getContext().CreateTempSymbol(); BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::PROLOG_LABEL)).addSym(SetFPLabel); DstML = MachineLocation(FP); SrcML = MachineLocation(MachineLocation::VirtualFP); Moves.push_back(MachineMove(SetFPLabel, DstML, SrcML)); } // Restore GP from the saved stack location if (MipsFI->needGPSaveRestore()) { unsigned Offset = MFI->getObjectOffset(MipsFI->getGPFI()); BuildMI(MBB, MBBI, dl, TII.get(Mips::CPRESTORE)).addImm(Offset); if (Offset >= 0x8000) { BuildMI(MBB, llvm::prior(MBBI), dl, TII.get(Mips::MACRO)); BuildMI(MBB, MBBI, dl, TII.get(Mips::NOMACRO)); } } }