[mips][ias] Fix O32 .cprestore directive when inside .set noat region and offset is in range.
Summary:
This expands on r269179 to fix an additional case that was not covered by our
tests. The assembler temporary is not needed when the .cprestore offset fits
inside a simm16 and it is not an error to use it inside a '.set noat' in this
case.
Reviewers: emaste, seanbruno, sdardis
Subscribers: dsanders, sdardis, llvm-commits
Differential Revision: http://reviews.llvm.org/D20199
llvm-svn: 269295
diff --git a/llvm/lib/Target/Mips/MipsTargetStreamer.h b/llvm/lib/Target/Mips/MipsTargetStreamer.h
index c0b3c44..d418f80 100644
--- a/llvm/lib/Target/Mips/MipsTargetStreamer.h
+++ b/llvm/lib/Target/Mips/MipsTargetStreamer.h
@@ -122,9 +122,18 @@
void emitEmptyDelaySlot(bool hasShortDelaySlot, SMLoc IDLoc,
const MCSubtargetInfo *STI);
void emitNop(SMLoc IDLoc, const MCSubtargetInfo *STI);
+
+ /// Emit a store instruction with an offset. If the offset is out of range
+ /// then it will be synthesized using the assembler temporary.
+ ///
+ /// GetATReg() is a callback that can be used to obtain the current assembler
+ /// temporary and is only called when the assembler temporary is required. It
+ /// must handle the case where no assembler temporary is available (typically
+ /// by reporting an error).
void emitStoreWithImmOffset(unsigned Opcode, unsigned SrcReg,
- unsigned BaseReg, int64_t Offset, unsigned ATReg,
- SMLoc IDLoc, const MCSubtargetInfo *STI);
+ unsigned BaseReg, int64_t Offset,
+ std::function<unsigned()> GetATReg, SMLoc IDLoc,
+ const MCSubtargetInfo *STI);
void emitStoreWithSymOffset(unsigned Opcode, unsigned SrcReg,
unsigned BaseReg, MCOperand &HiOperand,
MCOperand &LoOperand, unsigned ATReg, SMLoc IDLoc,
@@ -237,6 +246,14 @@
// PIC support
void emitDirectiveCpLoad(unsigned RegNo) override;
+
+ /// Emit a .cprestore directive. If the offset is out of range then it will
+ /// be synthesized using the assembler temporary.
+ ///
+ /// GetATReg() is a callback that can be used to obtain the current assembler
+ /// temporary and is only called when the assembler temporary is required. It
+ /// must handle the case where no assembler temporary is available (typically
+ /// by reporting an error).
bool emitDirectiveCpRestore(int Offset, std::function<unsigned()> GetATReg,
SMLoc IDLoc, const MCSubtargetInfo *STI) override;
void emitDirectiveCpsetup(unsigned RegNo, int RegOrOffset,