blob: 8bd2c1b14ed3672bfaa9f1477107b09de9d57617 [file] [log] [blame]
Anton Korobeynikov33464912010-11-15 00:06:54 +00001//=======- MBlazeFrameInfo.cpp - MBlaze Frame Information ------*- C++ -*-====//
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 TargetFrameInfo class.
11//
12//===----------------------------------------------------------------------===//
13
Wesley Peckb4aec922010-12-29 19:46:28 +000014#define DEBUG_TYPE "mblaze-frame-info"
15
Anton Korobeynikov33464912010-11-15 00:06:54 +000016#include "MBlazeFrameInfo.h"
17#include "MBlazeInstrInfo.h"
18#include "MBlazeMachineFunction.h"
Wesley Peckeb133822010-12-12 20:52:31 +000019#include "InstPrinter/MBlazeInstPrinter.h"
Anton Korobeynikov33464912010-11-15 00:06:54 +000020#include "llvm/Function.h"
21#include "llvm/CodeGen/MachineFrameInfo.h"
22#include "llvm/CodeGen/MachineFunction.h"
23#include "llvm/CodeGen/MachineInstrBuilder.h"
24#include "llvm/CodeGen/MachineModuleInfo.h"
25#include "llvm/CodeGen/MachineRegisterInfo.h"
26#include "llvm/Target/TargetData.h"
27#include "llvm/Target/TargetOptions.h"
28#include "llvm/Support/CommandLine.h"
Wesley Peckb4aec922010-12-29 19:46:28 +000029#include "llvm/Support/Debug.h"
30#include "llvm/Support/ErrorHandling.h"
31#include "llvm/Support/raw_ostream.h"
Anton Korobeynikov33464912010-11-15 00:06:54 +000032
33using namespace llvm;
34
Wesley Peckeb133822010-12-12 20:52:31 +000035namespace llvm {
36 cl::opt<bool> DisableStackAdjust(
37 "disable-mblaze-stack-adjust",
38 cl::init(false),
39 cl::desc("Disable MBlaze stack layout adjustment."),
40 cl::Hidden);
41}
42
Anton Korobeynikov33464912010-11-15 00:06:54 +000043//===----------------------------------------------------------------------===//
44//
45// Stack Frame Processing methods
46// +----------------------------+
47//
48// The stack is allocated decrementing the stack pointer on
49// the first instruction of a function prologue. Once decremented,
50// all stack references are are done through a positive offset
51// from the stack/frame pointer, so the stack is considered
52// to grow up.
53//
54//===----------------------------------------------------------------------===//
55
Wesley Peckeb133822010-12-12 20:52:31 +000056static void analyzeFrameIndexes(MachineFunction &MF) {
57 if (DisableStackAdjust) return;
58
59 MachineFrameInfo *MFI = MF.getFrameInfo();
60 MBlazeFunctionInfo *MBlazeFI = MF.getInfo<MBlazeFunctionInfo>();
61 const MachineRegisterInfo &MRI = MF.getRegInfo();
62
63 MachineRegisterInfo::livein_iterator LII = MRI.livein_begin();
64 MachineRegisterInfo::livein_iterator LIE = MRI.livein_end();
65 const SmallVector<int, 16> &LiveInFI = MBlazeFI->getLiveIn();
66 SmallVector<MachineInstr*, 16> EraseInstr;
67
68 MachineBasicBlock *MBB = MF.getBlockNumbered(0);
69 MachineBasicBlock::iterator MIB = MBB->begin();
70 MachineBasicBlock::iterator MIE = MBB->end();
71
72 int StackAdjust = 0;
73 int StackOffset = -28;
Wesley Peckb4aec922010-12-29 19:46:28 +000074
75 // In this loop we are searching frame indexes that corrospond to incoming
76 // arguments that are already in the stack. We look for instruction sequences
77 // like the following:
78 //
79 // LWI REG, FI1, 0
80 // ...
81 // SWI REG, FI2, 0
82 //
83 // As long as there are no defs of REG in the ... part, we can eliminate
84 // the SWI instruction because the value has already been stored to the
85 // stack by the caller. All we need to do is locate FI at the correct
86 // stack location according to the calling convensions.
87 //
88 // Additionally, if the SWI operation kills the def of REG then we don't
89 // need the LWI operation so we can erase it as well.
90#if 1
Wesley Peckeb133822010-12-12 20:52:31 +000091 for (unsigned i = 0, e = LiveInFI.size(); i < e; ++i) {
92 for (MachineBasicBlock::iterator I=MIB; I != MIE; ++I) {
93 if (I->getOpcode() != MBlaze::LWI || I->getNumOperands() != 3 ||
94 !I->getOperand(1).isFI() || !I->getOperand(0).isReg() ||
95 I->getOperand(1).getIndex() != LiveInFI[i]) continue;
96
97 unsigned FIReg = I->getOperand(0).getReg();
98 MachineBasicBlock::iterator SI = I;
99 for (SI++; SI != MIE; ++SI) {
Wesley Peckb4aec922010-12-29 19:46:28 +0000100 if (!SI->getOperand(0).isReg() ||
101 !SI->getOperand(1).isFI() ||
102 SI->getOpcode() != MBlaze::SWI) continue;
Wesley Peckeb133822010-12-12 20:52:31 +0000103
104 int FI = SI->getOperand(1).getIndex();
Wesley Peckb4aec922010-12-29 19:46:28 +0000105 if (SI->getOperand(0).getReg() != FIReg ||
106 MFI->isFixedObjectIndex(FI) ||
107 MFI->getObjectSize(FI) != 4) continue;
108
Wesley Peckeb133822010-12-12 20:52:31 +0000109 if (SI->getOperand(0).isDef()) break;
110
Wesley Peckb4aec922010-12-29 19:46:28 +0000111 if (SI->getOperand(0).isKill()) {
112 DEBUG(dbgs() << "LWI for FI#" << I->getOperand(1).getIndex()
113 << " removed\n");
Wesley Peckeb133822010-12-12 20:52:31 +0000114 EraseInstr.push_back(I);
Wesley Peckb4aec922010-12-29 19:46:28 +0000115 }
116
Wesley Peckeb133822010-12-12 20:52:31 +0000117 EraseInstr.push_back(SI);
Wesley Peckb4aec922010-12-29 19:46:28 +0000118 DEBUG(dbgs() << "SWI for FI#" << FI << " removed\n");
119
Wesley Peckeb133822010-12-12 20:52:31 +0000120 MBlazeFI->recordLoadArgsFI(FI, StackOffset);
Wesley Peckb4aec922010-12-29 19:46:28 +0000121 DEBUG(dbgs() << "FI#" << FI << " relocated to " << StackOffset << "\n");
122
Wesley Peckeb133822010-12-12 20:52:31 +0000123 StackOffset -= 4;
124 StackAdjust += 4;
125 break;
126 }
127 }
128 }
Wesley Peckb4aec922010-12-29 19:46:28 +0000129#endif
Wesley Peckeb133822010-12-12 20:52:31 +0000130
Wesley Peckb4aec922010-12-29 19:46:28 +0000131 // In this loop we are searching for frame indexes that corrospond to
132 // incoming arguments that are in registers. We look for instruction
133 // sequences like the following:
134 //
135 // ... SWI REG, FI, 0
136 //
137 // As long as the ... part does not define REG and if REG is an incoming
138 // parameter register then we know that, according to ABI convensions, the
139 // caller has allocated stack space for it already. Instead of allocating
140 // stack space on our frame, we record the correct location in the callers
141 // frame.
142#if 1
143 for (MachineRegisterInfo::livein_iterator LI = LII; LI != LIE; ++LI) {
144 for (MachineBasicBlock::iterator I=MIB; I != MIE; ++I) {
145 if (I->definesRegister(LI->first))
146 break;
Wesley Peckeb133822010-12-12 20:52:31 +0000147
Wesley Peckb4aec922010-12-29 19:46:28 +0000148 if (I->getOpcode() != MBlaze::SWI || I->getNumOperands() != 3 ||
149 !I->getOperand(1).isFI() || !I->getOperand(0).isReg() ||
150 I->getOperand(1).getIndex() < 0) continue;
151
Wesley Peckeb133822010-12-12 20:52:31 +0000152 if (I->getOperand(0).getReg() == LI->first) {
Wesley Peckb4aec922010-12-29 19:46:28 +0000153 int FI = I->getOperand(1).getIndex();
154 MBlazeFI->recordLiveIn(FI);
155
156 int FILoc = 0;
157 switch (LI->first) {
158 default: llvm_unreachable("invalid incoming parameter!");
159 case MBlaze::R5: FILoc = -4; break;
160 case MBlaze::R6: FILoc = -8; break;
161 case MBlaze::R7: FILoc = -12; break;
162 case MBlaze::R8: FILoc = -16; break;
163 case MBlaze::R9: FILoc = -20; break;
164 case MBlaze::R10: FILoc = -24; break;
165 }
166
167 StackAdjust += 4;
168 MBlazeFI->recordLoadArgsFI(FI, FILoc);
169 DEBUG(dbgs() << "FI#" << FI << " relocated to " << FILoc << "\n");
Wesley Peckeb133822010-12-12 20:52:31 +0000170 break;
171 }
172 }
Wesley Peckeb133822010-12-12 20:52:31 +0000173 }
Wesley Peckb4aec922010-12-29 19:46:28 +0000174#endif
Wesley Peckeb133822010-12-12 20:52:31 +0000175
Wesley Peckb4aec922010-12-29 19:46:28 +0000176 // Go ahead and erase all of the instructions that we determined were
177 // no longer needed.
Wesley Peckeb133822010-12-12 20:52:31 +0000178 for (int i = 0, e = EraseInstr.size(); i < e; ++i)
179 MBB->erase(EraseInstr[i]);
180
Wesley Peckb4aec922010-12-29 19:46:28 +0000181 DEBUG(dbgs() << "Final stack adjustment: " << StackAdjust << "\n");
Wesley Peckeb133822010-12-12 20:52:31 +0000182 MBlazeFI->setStackAdjust(StackAdjust);
183}
184
Wesley Peckdc9d87a2010-12-15 20:27:28 +0000185static void interruptFrameLayout(MachineFunction &MF) {
186 const Function *F = MF.getFunction();
187 llvm::CallingConv::ID CallConv = F->getCallingConv();
188
189 // If this function is not using either the interrupt_handler
190 // calling convention or the save_volatiles calling convention
191 // then we don't need to do any additional frame layout.
192 if (CallConv != llvm::CallingConv::MBLAZE_INTR &&
193 CallConv != llvm::CallingConv::MBLAZE_SVOL)
194 return;
195
196 MachineFrameInfo *MFI = MF.getFrameInfo();
197 const MachineRegisterInfo &MRI = MF.getRegInfo();
198 const MBlazeInstrInfo &TII =
199 *static_cast<const MBlazeInstrInfo*>(MF.getTarget().getInstrInfo());
200
201 // Determine if the calling convention is the interrupt_handler
202 // calling convention. Some pieces of the prologue and epilogue
203 // only need to be emitted if we are lowering and interrupt handler.
204 bool isIntr = CallConv == llvm::CallingConv::MBLAZE_INTR;
205
206 // Determine where to put prologue and epilogue additions
207 MachineBasicBlock &MENT = MF.front();
208 MachineBasicBlock &MEXT = MF.back();
209
210 MachineBasicBlock::iterator MENTI = MENT.begin();
211 MachineBasicBlock::iterator MEXTI = prior(MEXT.end());
212
213 DebugLoc ENTDL = MENTI != MENT.end() ? MENTI->getDebugLoc() : DebugLoc();
214 DebugLoc EXTDL = MEXTI != MEXT.end() ? MEXTI->getDebugLoc() : DebugLoc();
215
216 // Store the frame indexes generated during prologue additions for use
217 // when we are generating the epilogue additions.
218 SmallVector<int, 10> VFI;
219
220 // Build the prologue SWI for R3 - R12 if needed. Note that R11 must
221 // always have a SWI because it is used when processing RMSR.
222 for (unsigned r = MBlaze::R3; r <= MBlaze::R12; ++r) {
223 if (!MRI.isPhysRegUsed(r) && !(isIntr && r == MBlaze::R11)) continue;
224
225 int FI = MFI->CreateStackObject(4,4,false,false);
226 VFI.push_back(FI);
227
228 BuildMI(MENT, MENTI, ENTDL, TII.get(MBlaze::SWI), r)
229 .addFrameIndex(FI).addImm(0);
230 }
231
232 // Build the prologue SWI for R17, R18
233 int R17FI = MFI->CreateStackObject(4,4,false,false);
234 int R18FI = MFI->CreateStackObject(4,4,false,false);
235
236 BuildMI(MENT, MENTI, ENTDL, TII.get(MBlaze::SWI), MBlaze::R17)
237 .addFrameIndex(R17FI).addImm(0);
238
239 BuildMI(MENT, MENTI, ENTDL, TII.get(MBlaze::SWI), MBlaze::R18)
240 .addFrameIndex(R18FI).addImm(0);
241
242 // Buid the prologue SWI and the epilogue LWI for RMSR if needed
243 if (isIntr) {
244 int MSRFI = MFI->CreateStackObject(4,4,false,false);
245 BuildMI(MENT, MENTI, ENTDL, TII.get(MBlaze::MFS), MBlaze::R11)
246 .addReg(MBlaze::RMSR);
247 BuildMI(MENT, MENTI, ENTDL, TII.get(MBlaze::SWI), MBlaze::R11)
248 .addFrameIndex(MSRFI).addImm(0);
249
250 BuildMI(MEXT, MEXTI, EXTDL, TII.get(MBlaze::LWI), MBlaze::R11)
251 .addFrameIndex(MSRFI).addImm(0);
252 BuildMI(MEXT, MEXTI, EXTDL, TII.get(MBlaze::MTS), MBlaze::RMSR)
253 .addReg(MBlaze::R11);
254 }
255
256 // Build the epilogue LWI for R17, R18
257 BuildMI(MEXT, MEXTI, EXTDL, TII.get(MBlaze::LWI), MBlaze::R18)
258 .addFrameIndex(R18FI).addImm(0);
259
260 BuildMI(MEXT, MEXTI, EXTDL, TII.get(MBlaze::LWI), MBlaze::R17)
261 .addFrameIndex(R17FI).addImm(0);
262
263 // Build the epilogue LWI for R3 - R12 if needed
264 for (unsigned r = MBlaze::R12, i = VFI.size(); r >= MBlaze::R3; --r) {
265 if (!MRI.isPhysRegUsed(r)) continue;
266 BuildMI(MEXT, MEXTI, EXTDL, TII.get(MBlaze::LWI), r)
267 .addFrameIndex(VFI[--i]).addImm(0);
268 }
269}
270
Wesley Peckeb133822010-12-12 20:52:31 +0000271static void determineFrameLayout(MachineFunction &MF) {
272 MachineFrameInfo *MFI = MF.getFrameInfo();
273 MBlazeFunctionInfo *MBlazeFI = MF.getInfo<MBlazeFunctionInfo>();
274
275 // Replace the dummy '0' SPOffset by the negative offsets, as explained on
276 // LowerFORMAL_ARGUMENTS. Leaving '0' for while is necessary to avoid
277 // the approach done by calculateFrameObjectOffsets to the stack frame.
278 MBlazeFI->adjustLoadArgsFI(MFI);
279 MBlazeFI->adjustStoreVarArgsFI(MFI);
280
281 // Get the number of bytes to allocate from the FrameInfo
282 unsigned FrameSize = MFI->getStackSize();
Wesley Peckb4aec922010-12-29 19:46:28 +0000283 DEBUG(dbgs() << "Original Frame Size: " << FrameSize << "\n" );
284
Wesley Peckeb133822010-12-12 20:52:31 +0000285 FrameSize -= MBlazeFI->getStackAdjust();
Wesley Peckb4aec922010-12-29 19:46:28 +0000286 DEBUG(dbgs() << "Adjusted Frame Size: " << FrameSize << "\n" );
Wesley Peckeb133822010-12-12 20:52:31 +0000287
288 // Get the alignments provided by the target, and the maximum alignment
289 // (if any) of the fixed frame objects.
290 // unsigned MaxAlign = MFI->getMaxAlignment();
291 unsigned TargetAlign = MF.getTarget().getFrameInfo()->getStackAlignment();
292 unsigned AlignMask = TargetAlign - 1;
293
294 // Make sure the frame is aligned.
295 FrameSize = (FrameSize + AlignMask) & ~AlignMask;
296 MFI->setStackSize(FrameSize);
Wesley Peckb4aec922010-12-29 19:46:28 +0000297 DEBUG(dbgs() << "Aligned Frame Size: " << FrameSize << "\n" );
Wesley Peckeb133822010-12-12 20:52:31 +0000298}
299
Anton Korobeynikovd0c38172010-11-18 21:19:35 +0000300// hasFP - Return true if the specified function should have a dedicated frame
301// pointer register. This is true if the function has variable sized allocas or
302// if frame pointer elimination is disabled.
303bool MBlazeFrameInfo::hasFP(const MachineFunction &MF) const {
304 const MachineFrameInfo *MFI = MF.getFrameInfo();
305 return DisableFramePointerElim(MF) || MFI->hasVarSizedObjects();
306}
307
Anton Korobeynikov33464912010-11-15 00:06:54 +0000308void MBlazeFrameInfo::emitPrologue(MachineFunction &MF) const {
309 MachineBasicBlock &MBB = MF.front();
310 MachineFrameInfo *MFI = MF.getFrameInfo();
Anton Korobeynikov33464912010-11-15 00:06:54 +0000311 const MBlazeInstrInfo &TII =
312 *static_cast<const MBlazeInstrInfo*>(MF.getTarget().getInstrInfo());
313 MBlazeFunctionInfo *MBlazeFI = MF.getInfo<MBlazeFunctionInfo>();
314 MachineBasicBlock::iterator MBBI = MBB.begin();
315 DebugLoc DL = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc();
316
Wesley Peckdc9d87a2010-12-15 20:27:28 +0000317 llvm::CallingConv::ID CallConv = MF.getFunction()->getCallingConv();
318 bool requiresRA = CallConv == llvm::CallingConv::MBLAZE_INTR;
319
Wesley Peckeb133822010-12-12 20:52:31 +0000320 // Determine the correct frame layout
321 determineFrameLayout(MF);
Anton Korobeynikov33464912010-11-15 00:06:54 +0000322
323 // Get the number of bytes to allocate from the FrameInfo.
324 unsigned StackSize = MFI->getStackSize();
325
326 // No need to allocate space on the stack.
Wesley Peckdc9d87a2010-12-15 20:27:28 +0000327 if (StackSize == 0 && !MFI->adjustsStack() && !requiresRA) return;
Anton Korobeynikov33464912010-11-15 00:06:54 +0000328
329 int FPOffset = MBlazeFI->getFPStackOffset();
330 int RAOffset = MBlazeFI->getRAStackOffset();
331
332 // Adjust stack : addi R1, R1, -imm
Wesley Pecka7c7b9d2010-12-12 22:02:31 +0000333 BuildMI(MBB, MBBI, DL, TII.get(MBlaze::ADDIK), MBlaze::R1)
Anton Korobeynikov33464912010-11-15 00:06:54 +0000334 .addReg(MBlaze::R1).addImm(-StackSize);
335
Anton Korobeynikov33464912010-11-15 00:06:54 +0000336 // swi R15, R1, stack_loc
Wesley Peckdc9d87a2010-12-15 20:27:28 +0000337 if (MFI->adjustsStack() || requiresRA) {
Anton Korobeynikov33464912010-11-15 00:06:54 +0000338 BuildMI(MBB, MBBI, DL, TII.get(MBlaze::SWI))
339 .addReg(MBlaze::R15).addReg(MBlaze::R1).addImm(RAOffset);
340 }
341
Anton Korobeynikovd0c38172010-11-18 21:19:35 +0000342 if (hasFP(MF)) {
Anton Korobeynikov33464912010-11-15 00:06:54 +0000343 // swi R19, R1, stack_loc
344 BuildMI(MBB, MBBI, DL, TII.get(MBlaze::SWI))
345 .addReg(MBlaze::R19).addReg(MBlaze::R1).addImm(FPOffset);
346
347 // add R19, R1, R0
348 BuildMI(MBB, MBBI, DL, TII.get(MBlaze::ADD), MBlaze::R19)
349 .addReg(MBlaze::R1).addReg(MBlaze::R0);
350 }
351}
352
353void MBlazeFrameInfo::emitEpilogue(MachineFunction &MF,
354 MachineBasicBlock &MBB) const {
355 MachineBasicBlock::iterator MBBI = prior(MBB.end());
356 MachineFrameInfo *MFI = MF.getFrameInfo();
Anton Korobeynikovd0c38172010-11-18 21:19:35 +0000357 MBlazeFunctionInfo *MBlazeFI = MF.getInfo<MBlazeFunctionInfo>();
Anton Korobeynikov33464912010-11-15 00:06:54 +0000358 const MBlazeInstrInfo &TII =
359 *static_cast<const MBlazeInstrInfo*>(MF.getTarget().getInstrInfo());
360
361 DebugLoc dl = MBBI->getDebugLoc();
362
Wesley Peckdc9d87a2010-12-15 20:27:28 +0000363 llvm::CallingConv::ID CallConv = MF.getFunction()->getCallingConv();
364 bool requiresRA = CallConv == llvm::CallingConv::MBLAZE_INTR;
365
Anton Korobeynikov33464912010-11-15 00:06:54 +0000366 // Get the FI's where RA and FP are saved.
367 int FPOffset = MBlazeFI->getFPStackOffset();
368 int RAOffset = MBlazeFI->getRAStackOffset();
369
Anton Korobeynikovd0c38172010-11-18 21:19:35 +0000370 if (hasFP(MF)) {
Anton Korobeynikov33464912010-11-15 00:06:54 +0000371 // add R1, R19, R0
372 BuildMI(MBB, MBBI, dl, TII.get(MBlaze::ADD), MBlaze::R1)
373 .addReg(MBlaze::R19).addReg(MBlaze::R0);
374
375 // lwi R19, R1, stack_loc
376 BuildMI(MBB, MBBI, dl, TII.get(MBlaze::LWI), MBlaze::R19)
377 .addReg(MBlaze::R1).addImm(FPOffset);
378 }
379
Anton Korobeynikov33464912010-11-15 00:06:54 +0000380 // lwi R15, R1, stack_loc
Wesley Peckdc9d87a2010-12-15 20:27:28 +0000381 if (MFI->adjustsStack() || requiresRA) {
Anton Korobeynikov33464912010-11-15 00:06:54 +0000382 BuildMI(MBB, MBBI, dl, TII.get(MBlaze::LWI), MBlaze::R15)
383 .addReg(MBlaze::R1).addImm(RAOffset);
384 }
385
386 // Get the number of bytes from FrameInfo
387 int StackSize = (int) MFI->getStackSize();
Anton Korobeynikov33464912010-11-15 00:06:54 +0000388
Anton Korobeynikov33464912010-11-15 00:06:54 +0000389 // addi R1, R1, imm
390 if (StackSize) {
Wesley Pecka7c7b9d2010-12-12 22:02:31 +0000391 BuildMI(MBB, MBBI, dl, TII.get(MBlaze::ADDIK), MBlaze::R1)
Anton Korobeynikov33464912010-11-15 00:06:54 +0000392 .addReg(MBlaze::R1).addImm(StackSize);
393 }
394}
Wesley Peck8397be02010-12-09 03:42:04 +0000395
396void MBlazeFrameInfo::processFunctionBeforeCalleeSavedScan(MachineFunction &MF, RegScavenger *RS)
397 const {
398 MachineFrameInfo *MFI = MF.getFrameInfo();
399 MBlazeFunctionInfo *MBlazeFI = MF.getInfo<MBlazeFunctionInfo>();
Wesley Peckdc9d87a2010-12-15 20:27:28 +0000400 llvm::CallingConv::ID CallConv = MF.getFunction()->getCallingConv();
401 bool requiresRA = CallConv == llvm::CallingConv::MBLAZE_INTR;
Wesley Peck8397be02010-12-09 03:42:04 +0000402
Wesley Peckdc9d87a2010-12-15 20:27:28 +0000403 if (MFI->adjustsStack() || requiresRA) {
Wesley Peck8397be02010-12-09 03:42:04 +0000404 MBlazeFI->setRAStackOffset(0);
405 MFI->CreateFixedObject(4,0,true);
406 }
407
408 if (hasFP(MF)) {
409 MBlazeFI->setFPStackOffset(4);
410 MFI->CreateFixedObject(4,4,true);
411 }
Wesley Peckeb133822010-12-12 20:52:31 +0000412
Wesley Peckdc9d87a2010-12-15 20:27:28 +0000413 interruptFrameLayout(MF);
Wesley Peckeb133822010-12-12 20:52:31 +0000414 analyzeFrameIndexes(MF);
Wesley Peck8397be02010-12-09 03:42:04 +0000415}