Home | History | Annotate | Download | only in MBlaze
      1 //===-- MBlazeFrameLowering.cpp - MBlaze Frame Information ---------------====//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 //
     10 // This file contains the MBlaze implementation of TargetFrameLowering class.
     11 //
     12 //===----------------------------------------------------------------------===//
     13 
     14 #define DEBUG_TYPE "mblaze-frame-lowering"
     15 
     16 #include "MBlazeFrameLowering.h"
     17 #include "InstPrinter/MBlazeInstPrinter.h"
     18 #include "MBlazeInstrInfo.h"
     19 #include "MBlazeMachineFunction.h"
     20 #include "llvm/CodeGen/MachineFrameInfo.h"
     21 #include "llvm/CodeGen/MachineFunction.h"
     22 #include "llvm/CodeGen/MachineInstrBuilder.h"
     23 #include "llvm/CodeGen/MachineModuleInfo.h"
     24 #include "llvm/CodeGen/MachineRegisterInfo.h"
     25 #include "llvm/IR/DataLayout.h"
     26 #include "llvm/IR/Function.h"
     27 #include "llvm/Support/CommandLine.h"
     28 #include "llvm/Support/Debug.h"
     29 #include "llvm/Support/ErrorHandling.h"
     30 #include "llvm/Support/raw_ostream.h"
     31 #include "llvm/Target/TargetOptions.h"
     32 
     33 using namespace llvm;
     34 
     35 static cl::opt<bool> MBDisableStackAdjust(
     36   "disable-mblaze-stack-adjust",
     37   cl::init(false),
     38   cl::desc("Disable MBlaze stack layout adjustment."),
     39   cl::Hidden);
     40 
     41 static void replaceFrameIndexes(MachineFunction &MF,
     42                                 SmallVector<std::pair<int,int64_t>, 16> &FR) {
     43   MachineFrameInfo *MFI = MF.getFrameInfo();
     44   MBlazeFunctionInfo *MBlazeFI = MF.getInfo<MBlazeFunctionInfo>();
     45   const SmallVector<std::pair<int,int64_t>, 16>::iterator FRB = FR.begin();
     46   const SmallVector<std::pair<int,int64_t>, 16>::iterator FRE = FR.end();
     47 
     48   SmallVector<std::pair<int,int64_t>, 16>::iterator FRI = FRB;
     49   for (; FRI != FRE; ++FRI) {
     50     MFI->RemoveStackObject(FRI->first);
     51     int NFI = MFI->CreateFixedObject(4, FRI->second, true);
     52     MBlazeFI->recordReplacement(FRI->first, NFI);
     53 
     54     for (MachineFunction::iterator MB=MF.begin(), ME=MF.end(); MB!=ME; ++MB) {
     55       MachineBasicBlock::iterator MBB = MB->begin();
     56       const MachineBasicBlock::iterator MBE = MB->end();
     57 
     58       for (; MBB != MBE; ++MBB) {
     59         MachineInstr::mop_iterator MIB = MBB->operands_begin();
     60         const MachineInstr::mop_iterator MIE = MBB->operands_end();
     61 
     62         for (MachineInstr::mop_iterator MII = MIB; MII != MIE; ++MII) {
     63           if (!MII->isFI() || MII->getIndex() != FRI->first) continue;
     64           DEBUG(dbgs() << "FOUND FI#" << MII->getIndex() << "\n");
     65           MII->setIndex(NFI);
     66         }
     67       }
     68     }
     69   }
     70 }
     71 
     72 //===----------------------------------------------------------------------===//
     73 //
     74 // Stack Frame Processing methods
     75 // +----------------------------+
     76 //
     77 // The stack is allocated decrementing the stack pointer on
     78 // the first instruction of a function prologue. Once decremented,
     79 // all stack references are are done through a positive offset
     80 // from the stack/frame pointer, so the stack is considered
     81 // to grow up.
     82 //
     83 //===----------------------------------------------------------------------===//
     84 
     85 static void analyzeFrameIndexes(MachineFunction &MF) {
     86   if (MBDisableStackAdjust) return;
     87 
     88   MachineFrameInfo *MFI = MF.getFrameInfo();
     89   MBlazeFunctionInfo *MBlazeFI = MF.getInfo<MBlazeFunctionInfo>();
     90   const MachineRegisterInfo &MRI = MF.getRegInfo();
     91 
     92   MachineRegisterInfo::livein_iterator LII = MRI.livein_begin();
     93   MachineRegisterInfo::livein_iterator LIE = MRI.livein_end();
     94   const SmallVector<int, 16> &LiveInFI = MBlazeFI->getLiveIn();
     95   SmallVector<MachineInstr*, 16> EraseInstr;
     96   SmallVector<std::pair<int,int64_t>, 16> FrameRelocate;
     97 
     98   MachineBasicBlock *MBB = MF.getBlockNumbered(0);
     99   MachineBasicBlock::iterator MIB = MBB->begin();
    100   MachineBasicBlock::iterator MIE = MBB->end();
    101 
    102   int StackAdjust = 0;
    103   int StackOffset = -28;
    104 
    105   // In this loop we are searching frame indexes that corrospond to incoming
    106   // arguments that are already in the stack. We look for instruction sequences
    107   // like the following:
    108   //
    109   //    LWI REG, FI1, 0
    110   //    ...
    111   //    SWI REG, FI2, 0
    112   //
    113   // As long as there are no defs of REG in the ... part, we can eliminate
    114   // the SWI instruction because the value has already been stored to the
    115   // stack by the caller. All we need to do is locate FI at the correct
    116   // stack location according to the calling convensions.
    117   //
    118   // Additionally, if the SWI operation kills the def of REG then we don't
    119   // need the LWI operation so we can erase it as well.
    120   for (unsigned i = 0, e = LiveInFI.size(); i < e; ++i) {
    121     for (MachineBasicBlock::iterator I=MIB; I != MIE; ++I) {
    122       if (I->getOpcode() != MBlaze::LWI || I->getNumOperands() != 3 ||
    123           !I->getOperand(1).isFI() || !I->getOperand(0).isReg() ||
    124           I->getOperand(1).getIndex() != LiveInFI[i]) continue;
    125 
    126       unsigned FIReg = I->getOperand(0).getReg();
    127       MachineBasicBlock::iterator SI = I;
    128       for (SI++; SI != MIE; ++SI) {
    129         if (!SI->getOperand(0).isReg() ||
    130             !SI->getOperand(1).isFI() ||
    131             SI->getOpcode() != MBlaze::SWI) continue;
    132 
    133         int FI = SI->getOperand(1).getIndex();
    134         if (SI->getOperand(0).getReg() != FIReg ||
    135             MFI->isFixedObjectIndex(FI) ||
    136             MFI->getObjectSize(FI) != 4) continue;
    137 
    138         if (SI->getOperand(0).isDef()) break;
    139 
    140         if (SI->getOperand(0).isKill()) {
    141           DEBUG(dbgs() << "LWI for FI#" << I->getOperand(1).getIndex()
    142                        << " removed\n");
    143           EraseInstr.push_back(I);
    144         }
    145 
    146         EraseInstr.push_back(SI);
    147         DEBUG(dbgs() << "SWI for FI#" << FI << " removed\n");
    148 
    149         FrameRelocate.push_back(std::make_pair(FI,StackOffset));
    150         DEBUG(dbgs() << "FI#" << FI << " relocated to " << StackOffset << "\n");
    151 
    152         StackOffset -= 4;
    153         StackAdjust += 4;
    154         break;
    155       }
    156     }
    157   }
    158 
    159   // In this loop we are searching for frame indexes that corrospond to
    160   // incoming arguments that are in registers. We look for instruction
    161   // sequences like the following:
    162   //
    163   //    ...  SWI REG, FI, 0
    164   //
    165   // As long as the ... part does not define REG and if REG is an incoming
    166   // parameter register then we know that, according to ABI convensions, the
    167   // caller has allocated stack space for it already.  Instead of allocating
    168   // stack space on our frame, we record the correct location in the callers
    169   // frame.
    170   for (MachineRegisterInfo::livein_iterator LI = LII; LI != LIE; ++LI) {
    171     for (MachineBasicBlock::iterator I=MIB; I != MIE; ++I) {
    172       if (I->definesRegister(LI->first))
    173         break;
    174 
    175       if (I->getOpcode() != MBlaze::SWI || I->getNumOperands() != 3 ||
    176           !I->getOperand(1).isFI() || !I->getOperand(0).isReg() ||
    177           I->getOperand(1).getIndex() < 0) continue;
    178 
    179       if (I->getOperand(0).getReg() == LI->first) {
    180         int FI = I->getOperand(1).getIndex();
    181         MBlazeFI->recordLiveIn(FI);
    182 
    183         int FILoc = 0;
    184         switch (LI->first) {
    185         default: llvm_unreachable("invalid incoming parameter!");
    186         case MBlaze::R5:  FILoc = -4; break;
    187         case MBlaze::R6:  FILoc = -8; break;
    188         case MBlaze::R7:  FILoc = -12; break;
    189         case MBlaze::R8:  FILoc = -16; break;
    190         case MBlaze::R9:  FILoc = -20; break;
    191         case MBlaze::R10: FILoc = -24; break;
    192         }
    193 
    194         StackAdjust += 4;
    195         FrameRelocate.push_back(std::make_pair(FI,FILoc));
    196         DEBUG(dbgs() << "FI#" << FI << " relocated to " << FILoc << "\n");
    197         break;
    198       }
    199     }
    200   }
    201 
    202   // Go ahead and erase all of the instructions that we determined were
    203   // no longer needed.
    204   for (int i = 0, e = EraseInstr.size(); i < e; ++i)
    205     MBB->erase(EraseInstr[i]);
    206 
    207   // Replace all of the frame indexes that we have relocated with new
    208   // fixed object frame indexes.
    209   replaceFrameIndexes(MF, FrameRelocate);
    210 }
    211 
    212 static void interruptFrameLayout(MachineFunction &MF) {
    213   const Function *F = MF.getFunction();
    214   CallingConv::ID CallConv = F->getCallingConv();
    215 
    216   // If this function is not using either the interrupt_handler
    217   // calling convention or the save_volatiles calling convention
    218   // then we don't need to do any additional frame layout.
    219   if (CallConv != CallingConv::MBLAZE_INTR &&
    220       CallConv != CallingConv::MBLAZE_SVOL)
    221       return;
    222 
    223   MachineFrameInfo *MFI = MF.getFrameInfo();
    224   const MachineRegisterInfo &MRI = MF.getRegInfo();
    225   const MBlazeInstrInfo &TII =
    226     *static_cast<const MBlazeInstrInfo*>(MF.getTarget().getInstrInfo());
    227 
    228   // Determine if the calling convention is the interrupt_handler
    229   // calling convention. Some pieces of the prologue and epilogue
    230   // only need to be emitted if we are lowering and interrupt handler.
    231   bool isIntr = CallConv == CallingConv::MBLAZE_INTR;
    232 
    233   // Determine where to put prologue and epilogue additions
    234   MachineBasicBlock &MENT   = MF.front();
    235   MachineBasicBlock &MEXT   = MF.back();
    236 
    237   MachineBasicBlock::iterator MENTI = MENT.begin();
    238   MachineBasicBlock::iterator MEXTI = prior(MEXT.end());
    239 
    240   DebugLoc ENTDL = MENTI != MENT.end() ? MENTI->getDebugLoc() : DebugLoc();
    241   DebugLoc EXTDL = MEXTI != MEXT.end() ? MEXTI->getDebugLoc() : DebugLoc();
    242 
    243   // Store the frame indexes generated during prologue additions for use
    244   // when we are generating the epilogue additions.
    245   SmallVector<int, 10> VFI;
    246 
    247   // Build the prologue SWI for R3 - R12 if needed. Note that R11 must
    248   // always have a SWI because it is used when processing RMSR.
    249   for (unsigned r = MBlaze::R3; r <= MBlaze::R12; ++r) {
    250     if (!MRI.isPhysRegUsed(r) && !(isIntr && r == MBlaze::R11)) continue;
    251 
    252     int FI = MFI->CreateStackObject(4,4,false,false);
    253     VFI.push_back(FI);
    254 
    255     BuildMI(MENT, MENTI, ENTDL, TII.get(MBlaze::SWI), r)
    256       .addFrameIndex(FI).addImm(0);
    257   }
    258 
    259   // Build the prologue SWI for R17, R18
    260   int R17FI = MFI->CreateStackObject(4,4,false,false);
    261   int R18FI = MFI->CreateStackObject(4,4,false,false);
    262 
    263   BuildMI(MENT, MENTI, ENTDL, TII.get(MBlaze::SWI), MBlaze::R17)
    264     .addFrameIndex(R17FI).addImm(0);
    265 
    266   BuildMI(MENT, MENTI, ENTDL, TII.get(MBlaze::SWI), MBlaze::R18)
    267     .addFrameIndex(R18FI).addImm(0);
    268 
    269   // Buid the prologue SWI and the epilogue LWI for RMSR if needed
    270   if (isIntr) {
    271     int MSRFI = MFI->CreateStackObject(4,4,false,false);
    272     BuildMI(MENT, MENTI, ENTDL, TII.get(MBlaze::MFS), MBlaze::R11)
    273       .addReg(MBlaze::RMSR);
    274     BuildMI(MENT, MENTI, ENTDL, TII.get(MBlaze::SWI), MBlaze::R11)
    275       .addFrameIndex(MSRFI).addImm(0);
    276 
    277     BuildMI(MEXT, MEXTI, EXTDL, TII.get(MBlaze::LWI), MBlaze::R11)
    278       .addFrameIndex(MSRFI).addImm(0);
    279     BuildMI(MEXT, MEXTI, EXTDL, TII.get(MBlaze::MTS), MBlaze::RMSR)
    280       .addReg(MBlaze::R11);
    281   }
    282 
    283   // Build the epilogue LWI for R17, R18
    284   BuildMI(MEXT, MEXTI, EXTDL, TII.get(MBlaze::LWI), MBlaze::R18)
    285     .addFrameIndex(R18FI).addImm(0);
    286 
    287   BuildMI(MEXT, MEXTI, EXTDL, TII.get(MBlaze::LWI), MBlaze::R17)
    288     .addFrameIndex(R17FI).addImm(0);
    289 
    290   // Build the epilogue LWI for R3 - R12 if needed
    291   for (unsigned r = MBlaze::R12, i = VFI.size(); r >= MBlaze::R3; --r) {
    292     if (!MRI.isPhysRegUsed(r)) continue;
    293     BuildMI(MEXT, MEXTI, EXTDL, TII.get(MBlaze::LWI), r)
    294       .addFrameIndex(VFI[--i]).addImm(0);
    295   }
    296 }
    297 
    298 static void determineFrameLayout(MachineFunction &MF) {
    299   MachineFrameInfo *MFI = MF.getFrameInfo();
    300   MBlazeFunctionInfo *MBlazeFI = MF.getInfo<MBlazeFunctionInfo>();
    301 
    302   // Replace the dummy '0' SPOffset by the negative offsets, as explained on
    303   // LowerFORMAL_ARGUMENTS. Leaving '0' for while is necessary to avoid
    304   // the approach done by calculateFrameObjectOffsets to the stack frame.
    305   MBlazeFI->adjustLoadArgsFI(MFI);
    306   MBlazeFI->adjustStoreVarArgsFI(MFI);
    307 
    308   // Get the number of bytes to allocate from the FrameInfo
    309   unsigned FrameSize = MFI->getStackSize();
    310   DEBUG(dbgs() << "Original Frame Size: " << FrameSize << "\n" );
    311 
    312   // Get the alignments provided by the target, and the maximum alignment
    313   // (if any) of the fixed frame objects.
    314   // unsigned MaxAlign = MFI->getMaxAlignment();
    315   unsigned TargetAlign = MF.getTarget().getFrameLowering()->getStackAlignment();
    316   unsigned AlignMask = TargetAlign - 1;
    317 
    318   // Make sure the frame is aligned.
    319   FrameSize = (FrameSize + AlignMask) & ~AlignMask;
    320   MFI->setStackSize(FrameSize);
    321   DEBUG(dbgs() << "Aligned Frame Size: " << FrameSize << "\n" );
    322 }
    323 
    324 int MBlazeFrameLowering::getFrameIndexOffset(const MachineFunction &MF, int FI)
    325   const {
    326   const MBlazeFunctionInfo *MBlazeFI = MF.getInfo<MBlazeFunctionInfo>();
    327   if (MBlazeFI->hasReplacement(FI))
    328     FI = MBlazeFI->getReplacement(FI);
    329   return TargetFrameLowering::getFrameIndexOffset(MF,FI);
    330 }
    331 
    332 // hasFP - Return true if the specified function should have a dedicated frame
    333 // pointer register.  This is true if the function has variable sized allocas or
    334 // if frame pointer elimination is disabled.
    335 bool MBlazeFrameLowering::hasFP(const MachineFunction &MF) const {
    336   const MachineFrameInfo *MFI = MF.getFrameInfo();
    337   return MF.getTarget().Options.DisableFramePointerElim(MF) ||
    338          MFI->hasVarSizedObjects();
    339 }
    340 
    341 void MBlazeFrameLowering::emitPrologue(MachineFunction &MF) const {
    342   MachineBasicBlock &MBB   = MF.front();
    343   MachineFrameInfo *MFI    = MF.getFrameInfo();
    344   const MBlazeInstrInfo &TII =
    345     *static_cast<const MBlazeInstrInfo*>(MF.getTarget().getInstrInfo());
    346   MBlazeFunctionInfo *MBlazeFI = MF.getInfo<MBlazeFunctionInfo>();
    347   MachineBasicBlock::iterator MBBI = MBB.begin();
    348   DebugLoc DL = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc();
    349 
    350   CallingConv::ID CallConv = MF.getFunction()->getCallingConv();
    351   bool requiresRA = CallConv == CallingConv::MBLAZE_INTR;
    352 
    353   // Determine the correct frame layout
    354   determineFrameLayout(MF);
    355 
    356   // Get the number of bytes to allocate from the FrameInfo.
    357   unsigned StackSize = MFI->getStackSize();
    358 
    359   // No need to allocate space on the stack.
    360   if (StackSize == 0 && !MFI->adjustsStack() && !requiresRA) return;
    361 
    362   int FPOffset = MBlazeFI->getFPStackOffset();
    363   int RAOffset = MBlazeFI->getRAStackOffset();
    364 
    365   // Adjust stack : addi R1, R1, -imm
    366   BuildMI(MBB, MBBI, DL, TII.get(MBlaze::ADDIK), MBlaze::R1)
    367       .addReg(MBlaze::R1).addImm(-StackSize);
    368 
    369   // swi  R15, R1, stack_loc
    370   if (MFI->adjustsStack() || requiresRA) {
    371     BuildMI(MBB, MBBI, DL, TII.get(MBlaze::SWI))
    372         .addReg(MBlaze::R15).addReg(MBlaze::R1).addImm(RAOffset);
    373   }
    374 
    375   if (hasFP(MF)) {
    376     // swi  R19, R1, stack_loc
    377     BuildMI(MBB, MBBI, DL, TII.get(MBlaze::SWI))
    378       .addReg(MBlaze::R19).addReg(MBlaze::R1).addImm(FPOffset);
    379 
    380     // add R19, R1, R0
    381     BuildMI(MBB, MBBI, DL, TII.get(MBlaze::ADD), MBlaze::R19)
    382       .addReg(MBlaze::R1).addReg(MBlaze::R0);
    383   }
    384 }
    385 
    386 void MBlazeFrameLowering::emitEpilogue(MachineFunction &MF,
    387                                    MachineBasicBlock &MBB) const {
    388   MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr();
    389   MachineFrameInfo *MFI            = MF.getFrameInfo();
    390   MBlazeFunctionInfo *MBlazeFI     = MF.getInfo<MBlazeFunctionInfo>();
    391   const MBlazeInstrInfo &TII =
    392     *static_cast<const MBlazeInstrInfo*>(MF.getTarget().getInstrInfo());
    393 
    394   DebugLoc dl = MBBI->getDebugLoc();
    395 
    396   CallingConv::ID CallConv = MF.getFunction()->getCallingConv();
    397   bool requiresRA = CallConv == CallingConv::MBLAZE_INTR;
    398 
    399   // Get the FI's where RA and FP are saved.
    400   int FPOffset = MBlazeFI->getFPStackOffset();
    401   int RAOffset = MBlazeFI->getRAStackOffset();
    402 
    403   if (hasFP(MF)) {
    404     // add R1, R19, R0
    405     BuildMI(MBB, MBBI, dl, TII.get(MBlaze::ADD), MBlaze::R1)
    406       .addReg(MBlaze::R19).addReg(MBlaze::R0);
    407 
    408     // lwi  R19, R1, stack_loc
    409     BuildMI(MBB, MBBI, dl, TII.get(MBlaze::LWI), MBlaze::R19)
    410       .addReg(MBlaze::R1).addImm(FPOffset);
    411   }
    412 
    413   // lwi R15, R1, stack_loc
    414   if (MFI->adjustsStack() || requiresRA) {
    415     BuildMI(MBB, MBBI, dl, TII.get(MBlaze::LWI), MBlaze::R15)
    416       .addReg(MBlaze::R1).addImm(RAOffset);
    417   }
    418 
    419   // Get the number of bytes from FrameInfo
    420   int StackSize = (int) MFI->getStackSize();
    421 
    422   // addi R1, R1, imm
    423   if (StackSize) {
    424     BuildMI(MBB, MBBI, dl, TII.get(MBlaze::ADDIK), MBlaze::R1)
    425       .addReg(MBlaze::R1).addImm(StackSize);
    426   }
    427 }
    428 
    429 // Eliminate ADJCALLSTACKDOWN/ADJCALLSTACKUP pseudo instructions
    430 void MBlazeFrameLowering::
    431 eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB,
    432                               MachineBasicBlock::iterator I) const {
    433   const MBlazeInstrInfo &TII =
    434     *static_cast<const MBlazeInstrInfo*>(MF.getTarget().getInstrInfo());
    435   if (!hasReservedCallFrame(MF)) {
    436     // If we have a frame pointer, turn the adjcallstackup instruction into a
    437     // 'addi r1, r1, -<amt>' and the adjcallstackdown instruction into
    438     // 'addi r1, r1, <amt>'
    439     MachineInstr *Old = I;
    440     int Amount = Old->getOperand(0).getImm() + 4;
    441     if (Amount != 0) {
    442       // We need to keep the stack aligned properly.  To do this, we round the
    443       // amount of space needed for the outgoing arguments up to the next
    444       // alignment boundary.
    445       unsigned Align = getStackAlignment();
    446       Amount = (Amount+Align-1)/Align*Align;
    447 
    448       MachineInstr *New;
    449       if (Old->getOpcode() == MBlaze::ADJCALLSTACKDOWN) {
    450         New = BuildMI(MF,Old->getDebugLoc(), TII.get(MBlaze::ADDIK),MBlaze::R1)
    451                 .addReg(MBlaze::R1).addImm(-Amount);
    452       } else {
    453         assert(Old->getOpcode() == MBlaze::ADJCALLSTACKUP);
    454         New = BuildMI(MF,Old->getDebugLoc(), TII.get(MBlaze::ADDIK),MBlaze::R1)
    455                 .addReg(MBlaze::R1).addImm(Amount);
    456       }
    457 
    458       // Replace the pseudo instruction with a new instruction...
    459       MBB.insert(I, New);
    460     }
    461   }
    462 
    463   // Simply discard ADJCALLSTACKDOWN, ADJCALLSTACKUP instructions.
    464   MBB.erase(I);
    465 }
    466 
    467 
    468 void MBlazeFrameLowering::
    469 processFunctionBeforeCalleeSavedScan(MachineFunction &MF,
    470                                      RegScavenger *RS) const {
    471   MachineFrameInfo *MFI = MF.getFrameInfo();
    472   MBlazeFunctionInfo *MBlazeFI = MF.getInfo<MBlazeFunctionInfo>();
    473   CallingConv::ID CallConv = MF.getFunction()->getCallingConv();
    474   bool requiresRA = CallConv == CallingConv::MBLAZE_INTR;
    475 
    476   if (MFI->adjustsStack() || requiresRA) {
    477     MBlazeFI->setRAStackOffset(0);
    478     MFI->CreateFixedObject(4,0,true);
    479   }
    480 
    481   if (hasFP(MF)) {
    482     MBlazeFI->setFPStackOffset(4);
    483     MFI->CreateFixedObject(4,4,true);
    484   }
    485 
    486   interruptFrameLayout(MF);
    487   analyzeFrameIndexes(MF);
    488 }
    489