LLVM: lib/Target/ARC/ARCFrameLowering.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

22

23#define DEBUG_TYPE "arc-frame-lowering"

24

25using namespace llvm;

26

29 cl::desc("Use arc callee save/restore functions"),

31

33 "__st_r13_to_r15", "__st_r13_to_r16", "__st_r13_to_r17", "__st_r13_to_r18",

34 "__st_r13_to_r19", "__st_r13_to_r20", "__st_r13_to_r21", "__st_r13_to_r22",

35 "__st_r13_to_r23", "__st_r13_to_r24", "__st_r13_to_r25",

36};

37

39 "__ld_r13_to_r15", "__ld_r13_to_r16", "__ld_r13_to_r17", "__ld_r13_to_r18",

40 "__ld_r13_to_r19", "__ld_r13_to_r20", "__ld_r13_to_r21", "__ld_r13_to_r22",

41 "__ld_r13_to_r23", "__ld_r13_to_r24", "__ld_r13_to_r25",

42};

43

47 int Amount, int StackPtr) {

48 unsigned AdjOp;

49 if (!Amount)

50 return;

51 bool Positive;

52 unsigned AbsAmount;

53 if (Amount < 0) {

54 AbsAmount = -Amount;

55 Positive = false;

56 } else {

57 AbsAmount = Amount;

58 Positive = true;

59 }

60

61 LLVM_DEBUG(dbgs() << "Internal: adjust stack by: " << Amount << ","

62 << AbsAmount << "\n");

63

64 assert((AbsAmount % 4 == 0) && "Stack adjustments must be 4-byte aligned.");

66 AdjOp = Positive ? ARC::ADD_rru6 : ARC::SUB_rru6;

68 AdjOp = Positive ? ARC::ADD_rrs12 : ARC::SUB_rrs12;

69 else

70 AdjOp = Positive ? ARC::ADD_rrlimm : ARC::SUB_rrlimm;

71

75}

76

78 unsigned Last = 0;

79 for (auto Reg : CSI) {

80 assert(Reg.getReg() >= ARC::R13 && Reg.getReg() <= ARC::R25 &&

81 "Unexpected callee saved reg.");

84 }

86}

87

93 SavedRegs.set(ARC::BLINK);

94}

95

96void ARCFrameLowering::adjustStackToMatchRecords(

98 bool Allocate) const {

101

102 if (Allocate) {

103

104

105 ScalarAlloc = -ScalarAlloc;

106 }

107

109 ScalarAlloc, ARC::SP);

110}

111

112

113

114

123

124

129 unsigned StackSlotsUsedByFunclet = 0;

130 bool SavedBlink = false;

131 unsigned AlreadyAdjusted = 0;

133

135 unsigned VarArgsBytes = MFI.getObjectSize(AFI->getVarArgsFrameIndex());

136 unsigned Opc = ARC::SUB_rrlimm;

138 Opc = ARC::SUB_rru6;

139 else if (isInt<12>(VarArgsBytes))

140 Opc = ARC::SUB_rrs12;

143 .addImm(VarArgsBytes);

144 }

152 AlreadyAdjusted += 4;

153 }

156

157 StackSlotsUsedByFunclet = Last - ARC::R12;

162 .addImm(4 * StackSlotsUsedByFunclet);

166 AlreadyAdjusted += 4 * (StackSlotsUsedByFunclet + 1);

167 SavedBlink = true;

168 }

169

170 if (MFI.hasCalls() && !SavedBlink) {

173 AlreadyAdjusted += 4;

174 }

175 if (AFI->MaxCallStackReq > 0)

177

179 << (MFI.getStackSize() - AlreadyAdjusted) << "\n");

181 -(MFI.getStackSize() - AlreadyAdjusted), ARC::SP);

182

187 : ARC::ADD_rrlimm),

188 ARC::FP)

191 }

192

193

194

195

196

202

203 int CurOffset = -4;

206 nullptr, MRI->getDwarfRegNum(ARC::FP, true), CurOffset));

210 CurOffset -= 4;

211 }

212

215 nullptr, MRI->getDwarfRegNum(ARC::BLINK, true), CurOffset));

219 }

220

221 for (const auto &Entry : CSI) {

223 int FI = Entry.getFrameIdx();

224

225 if ((hasFP(MF) && Reg == ARC::FP) || (MFI.hasCalls() && Reg == ARC::BLINK))

226 continue;

232 }

233}

234

235

236

237

246 bool SavedBlink = false;

247 unsigned AmountAboveFunclet = 0;

248

249

250

251

253 unsigned Opc = ARC::SUB_rrlimm;

255 Opc = ARC::SUB_rru6;

259 AmountAboveFunclet += 4;

260 }

261

262

265 unsigned StackSlotsUsedByFunclet = 0;

266

268

269 StackSlotsUsedByFunclet = Last - ARC::R12;

270 AmountAboveFunclet += 4 * (StackSlotsUsedByFunclet + 1);

271 SavedBlink = true;

272 }

273

274 if (MFI.hasCalls() && !SavedBlink) {

275 AmountAboveFunclet += 4;

276 SavedBlink = true;

277 }

278

279

280 if (unsigned MoveAmount = StackSize - AmountAboveFunclet) {

281 unsigned Opc = ARC::ADD_rrlimm;

283 Opc = ARC::ADD_rru6;

285 Opc = ARC::ADD_rrs12;

288 .addImm(StackSize - AmountAboveFunclet);

289 }

290

291 if (StackSlotsUsedByFunclet) {

292

296 unsigned Opc = ARC::ADD_rrlimm;

297 if (isUInt<6>(4 * StackSlotsUsedByFunclet))

298 Opc = ARC::ADD_rru6;

299 else if (isInt<12>(4 * StackSlotsUsedByFunclet))

300 Opc = ARC::ADD_rrs12;

303 .addImm(4 * (StackSlotsUsedByFunclet));

304 }

305

306 if (SavedBlink) {

308 }

309

316 }

317

318

320

322 unsigned VarArgsBytes = MFI.getObjectSize(AFI->getVarArgsFrameIndex());

323 unsigned Opc = ARC::ADD_rrlimm;

325 Opc = ARC::ADD_rru6;

326 else if (isInt<12>(VarArgsBytes))

327 Opc = ARC::ADD_rrs12;

331 .addImm(VarArgsBytes);

332 }

333}

334

335static std::vector::iterator

336getSavedReg(std::vector &V, unsigned reg) {

337 for (auto I = V.begin(), E = V.end(); I != E; ++I) {

338 if (reg == I->getReg())

339 return I;

340 }

341 return V.end();

342}

343

346 std::vector &CSI) const {

347

348

349

350 int CurOffset = -4;

354

356 LLVM_DEBUG(dbgs() << "Creating fixed object (" << StackObj << ") for FP at "

357 << CurOffset << "\n");

358 (void)StackObj;

359 CurOffset -= 4;

360 }

362

364 LLVM_DEBUG(dbgs() << "Creating fixed object (" << StackObj

365 << ") for BLINK at " << CurOffset << "\n");

366 (void)StackObj;

367 CurOffset -= 4;

368 }

369

370

371 for (unsigned Which = Last; Which > ARC::R12; Which--) {

373 if (RegI == CSI.end() || RegI->getFrameIdx() == 0) {

374

375

377 if (RegI != CSI.end())

378 RegI->setFrameIdx(FI);

379 } else

381 CurOffset -= 4;

382 }

383 for (auto &I : CSI) {

384 if (I.getReg() > ARC::R12)

385 continue;

386 if (I.getFrameIdx() == 0) {

388 LLVM_DEBUG(dbgs() << "Creating fixed object (" << I.getFrameIdx()

389 << ") for other register at " << CurOffset << "\n");

390 } else {

392 LLVM_DEBUG(dbgs() << "Updating fixed object (" << I.getFrameIdx()

393 << ") for other register at " << CurOffset << "\n");

394 }

395 CurOffset -= 4;

396 }

397 return true;

398}

399

403 LLVM_DEBUG(dbgs() << "Spill callee saved registers: "

404 << MBB.getParent()->getName() << "\n");

405

408

409

410

411

412 return true;

413 }

414 return false;

415}

416

420 LLVM_DEBUG(dbgs() << "Restore callee saved registers: "

421 << MBB.getParent()->getName() << "\n");

422

425

426 return true;

427 }

428 return false;

429}

430

431

435 LLVM_DEBUG(dbgs() << "Process function before frame finalized: "

436 << MF.getName() << "\n");

442 RegInfo->getSpillAlign(*RC));

443 RS->addScavengingFrameIndex(RegScavFI);

444 LLVM_DEBUG(dbgs() << "Created scavenging index RegScavFI=" << RegScavFI

445 << "\n");

446 }

447}

448

451 unsigned Reg, int NumBytes, bool IsAdd,

453 unsigned Opc;

455 Opc = IsAdd ? ARC::ADD_rru6 : ARC::SUB_rru6;

457 Opc = IsAdd ? ARC::ADD_rrs12 : ARC::SUB_rrs12;

458 else

459 Opc = IsAdd ? ARC::ADD_rrlimm : ARC::SUB_rrlimm;

460

464}

465

475 if (hasFP(MF)) {

476 if (Amt > AFI->MaxCallStackReq && Old.getOpcode() == ARC::ADJCALLSTACKDOWN)

477 AFI->MaxCallStackReq = Amt;

478 } else {

479 if (Amt != 0) {

481 Old.getOpcode() == ARC::ADJCALLSTACKUP) &&

482 "Unknown Frame Pseudo.");

483 bool IsAdd = (Old.getOpcode() == ARC::ADJCALLSTACKUP);

485 }

486 }

487 return MBB.erase(I);

488}

489

495 RegInfo->hasStackRealignment(MF);

496 return HasFP;

497}

unsigned const MachineRegisterInfo * MRI

assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")

const TargetInstrInfo & TII

static const char * load_funclet_name[]

Definition ARCFrameLowering.cpp:38

static void emitRegUpdate(MachineBasicBlock &MBB, MachineBasicBlock::iterator &MBBI, DebugLoc dl, unsigned Reg, int NumBytes, bool IsAdd, const ARCInstrInfo *TII)

Definition ARCFrameLowering.cpp:449

static const char * store_funclet_name[]

Definition ARCFrameLowering.cpp:32

static void generateStackAdjustment(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, const ARCInstrInfo &TII, DebugLoc dl, int Amount, int StackPtr)

Definition ARCFrameLowering.cpp:44

static std::vector< CalleeSavedInfo >::iterator getSavedReg(std::vector< CalleeSavedInfo > &V, unsigned reg)

Definition ARCFrameLowering.cpp:336

static cl::opt< bool > UseSaveRestoreFunclet("arc-save-restore-funclet", cl::Hidden, cl::desc("Use arc callee save/restore functions"), cl::init(true))

static unsigned determineLastCalleeSave(ArrayRef< CalleeSavedInfo > CSI)

Definition ARCFrameLowering.cpp:77

MachineBasicBlock MachineBasicBlock::iterator MBBI

static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")

Register const TargetRegisterInfo * TRI

This file declares the machine register scavenger class.

bool restoreCalleeSavedRegisters(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, MutableArrayRef< CalleeSavedInfo > CSI, const TargetRegisterInfo *TRI) const override

restoreCalleeSavedRegisters - Issues instruction(s) to restore all callee saved registers and returns...

Definition ARCFrameLowering.cpp:417

void processFunctionBeforeFrameFinalized(MachineFunction &MF, RegScavenger *RS) const override

processFunctionBeforeFrameFinalized - This method is called immediately before the specified function...

Definition ARCFrameLowering.cpp:432

bool hasFPImpl(const MachineFunction &MF) const override

Definition ARCFrameLowering.cpp:490

MachineBasicBlock::iterator eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator I) const override

This method is called during prolog/epilog code insertion to eliminate call frame setup and destroy p...

Definition ARCFrameLowering.cpp:466

void determineCalleeSaves(MachineFunction &MF, BitVector &SavedRegs, RegScavenger *RS) const override

Add explicit callee save registers.

Definition ARCFrameLowering.cpp:88

void emitPrologue(MachineFunction &MF, MachineBasicBlock &MBB) const override

Insert Prologue into the function.

Definition ARCFrameLowering.cpp:115

void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const override

Insert Epilogue into the function.

Definition ARCFrameLowering.cpp:238

bool spillCalleeSavedRegisters(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, ArrayRef< CalleeSavedInfo > CSI, const TargetRegisterInfo *TRI) const override

spillCalleeSavedRegisters - Issues instruction(s) to spill all callee saved registers and returns tru...

Definition ARCFrameLowering.cpp:400

bool assignCalleeSavedSpillSlots(llvm::MachineFunction &, const llvm::TargetRegisterInfo *, std::vector< llvm::CalleeSavedInfo > &) const override

assignCalleeSavedSpillSlots - Allows target to override spill slot assignment logic.

Definition ARCFrameLowering.cpp:344

ARCFunctionInfo - This class is derived from MachineFunction private ARC target-specific information ...

const ARCInstrInfo * getInstrInfo() const override

ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...

bool isVarArg() const

isVarArg - Return true if this function takes a variable number of arguments.

static MCCFIInstruction createOffset(MCSymbol *L, unsigned Register, int64_t Offset, SMLoc Loc={})

.cfi_offset Previous value of Register is saved at offset Offset from CFA.

static MCCFIInstruction cfiDefCfaOffset(MCSymbol *L, int64_t Offset, SMLoc Loc={})

.cfi_def_cfa_offset modifies a rule for computing CFA.

Context object for machine code objects.

MCRegisterInfo base class - We assume that the target defines a static array of MCRegisterDesc object...

Wrapper class representing physical registers. Should be passed by value.

MachineInstrBundleIterator< MachineInstr > iterator

The MachineFrameInfo class represents an abstract stack frame until prolog/epilog code is inserted.

bool hasVarSizedObjects() const

This method may be called any time after instruction selection is complete to determine if the stack ...

uint64_t getStackSize() const

Return the number of bytes that must be allocated to hold all of the fixed size frame objects.

bool hasCalls() const

Return true if the current function has any function calls.

bool isFrameAddressTaken() const

This method may be called any time after instruction selection is complete to determine if there is a...

void setObjectOffset(int ObjectIdx, int64_t SPOffset)

Set the stack frame offset of the specified object.

LLVM_ABI int CreateSpillStackObject(uint64_t Size, Align Alignment)

Create a new statically sized stack object that represents a spill slot, returning a nonnegative iden...

int64_t getObjectSize(int ObjectIdx) const

Return the size of the specified object.

const std::vector< CalleeSavedInfo > & getCalleeSavedInfo() const

Returns a reference to call saved info vector for the current function.

bool hasStackObjects() const

Return true if there are any stack objects in this function.

LLVM_ABI int CreateFixedSpillStackObject(uint64_t Size, int64_t SPOffset, bool IsImmutable=false)

Create a spill slot at a fixed location on the stack.

int64_t getObjectOffset(int ObjectIdx) const

Return the assigned stack offset of the specified object from the incoming stack pointer.

void setStackSize(uint64_t Size)

Set the size of the stack.

unsigned addFrameInst(const MCCFIInstruction &Inst)

const TargetSubtargetInfo & getSubtarget() const

getSubtarget - Return the subtarget for which this machine code is being compiled.

StringRef getName() const

getName - Return the name of the corresponding LLVM function.

MachineFrameInfo & getFrameInfo()

getFrameInfo - Return the frame info object for the current function.

MCContext & getContext() const

Function & getFunction()

Return the LLVM function that this machine code represents.

Ty * getInfo()

getInfo - Keep track of various per-function pieces of information for backends that would like to do...

const TargetMachine & getTarget() const

getTarget - Return the target machine this machine code is compiled with

const MachineInstrBuilder & addExternalSymbol(const char *FnName, unsigned TargetFlags=0) const

const MachineInstrBuilder & addCFIIndex(unsigned CFIIndex) const

const MachineInstrBuilder & addImm(int64_t Val) const

Add a new immediate operand.

const MachineInstrBuilder & addReg(Register RegNo, unsigned flags=0, unsigned SubReg=0) const

Add a new virtual register operand.

const MachineInstrBuilder & setMIFlags(unsigned Flags) const

Representation of each machine instruction.

unsigned getOpcode() const

Returns the opcode of this MachineInstr.

const DebugLoc & getDebugLoc() const

Returns the debug location id of this MachineInstr.

const MachineOperand & getOperand(unsigned i) const

MutableArrayRef - Represent a mutable reference to an array (0 or more elements consecutively in memo...

bool hasFP(const MachineFunction &MF) const

hasFP - Return true if the specified function should have a dedicated frame pointer register.

virtual void determineCalleeSaves(MachineFunction &MF, BitVector &SavedRegs, RegScavenger *RS=nullptr) const

This method determines which of the registers reported by TargetRegisterInfo::getCalleeSavedRegs() sh...

LLVM_ABI bool DisableFramePointerElim(const MachineFunction &MF) const

DisableFramePointerElim - This returns true if frame pointer elimination optimization should be disab...

TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...

virtual const TargetRegisterInfo * getRegisterInfo() const =0

Return the target's register information.

@ Implicit

Not emitted register (e.g. carry, or temporary result).

@ Define

Register definition.

@ Kill

The last use of a register.

initializer< Ty > init(const Ty &Val)

This is an optimization pass for GlobalISel generic memory operations.

MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)

Builder interface. Specify how to create the initial instruction itself.

constexpr bool isInt(int64_t x)

Checks if an integer fits into the given bit width.

LLVM_ABI raw_ostream & dbgs()

dbgs() - This returns a reference to a raw_ostream for debugging messages.

constexpr bool isUInt(uint64_t x)

Checks if an unsigned integer fits into the given bit width.