From 446d9a74d9457c477d018d32893a457f6eb316b2 Mon Sep 17 00:00:00 2001 From: Daniel Sanders Date: Tue, 22 Sep 2015 10:50:09 +0000 Subject: [PATCH] [mips][ias] Implement .cpreturn directive. Summary: Based on a patch by David Chisnall. I've modified the original patch as follows: * Moved the expansion to the TargetStreamers so that the directive isn't expanded when emitting assembly. * Fixed an operand order bug. * Changed the move instructions from DADDu to OR to match recent changes to GAS. Reviewers: vkalintiris Subscribers: llvm-commits, emaste, seanbruno, theraven Differential Revision: http://reviews.llvm.org/D13017 llvm-svn: 248258 --- lib/Target/Mips/AsmParser/MipsAsmParser.cpp | 16 ++++++++++ .../Mips/MCTargetDesc/MipsTargetStreamer.cpp | 32 +++++++++++++++++++ lib/Target/Mips/MipsTargetStreamer.h | 6 ++++ test/MC/Mips/cpsetup.s | 19 +++++++++++ 4 files changed, 73 insertions(+) diff --git a/lib/Target/Mips/AsmParser/MipsAsmParser.cpp b/lib/Target/Mips/AsmParser/MipsAsmParser.cpp index d6994c6b5dc..4470baf8bff 100644 --- a/lib/Target/Mips/AsmParser/MipsAsmParser.cpp +++ b/lib/Target/Mips/AsmParser/MipsAsmParser.cpp @@ -118,6 +118,9 @@ class MipsAsmParser : public MCTargetAsmParser { bool IsPicEnabled; bool IsCpRestoreSet; int CpRestoreOffset; + unsigned CpSaveLocation; + /// If true, then CpSaveLocation is a register, otherwise it's an offset. + bool CpSaveLocationIsRegister; // Print a warning along with its fix-it message at the given range. void printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg, @@ -240,6 +243,7 @@ class MipsAsmParser : public MCTargetAsmParser { bool parseDirectiveCpLoad(SMLoc Loc); bool parseDirectiveCpRestore(SMLoc Loc); bool parseDirectiveCPSetup(); + bool parseDirectiveCPReturn(); bool parseDirectiveNaN(); bool parseDirectiveSet(); bool parseDirectiveOption(); @@ -4964,11 +4968,20 @@ bool MipsAsmParser::parseDirectiveCPSetup() { } const MCSymbolRefExpr *Ref = static_cast(Expr); + CpSaveLocation = Save; + CpSaveLocationIsRegister = SaveIsReg; + getTargetStreamer().emitDirectiveCpsetup(FuncReg, Save, Ref->getSymbol(), SaveIsReg); return false; } +bool MipsAsmParser::parseDirectiveCPReturn() { + getTargetStreamer().emitDirectiveCpreturn(CpSaveLocation, + CpSaveLocationIsRegister); + return false; +} + bool MipsAsmParser::parseDirectiveNaN() { MCAsmParser &Parser = getParser(); if (getLexer().isNot(AsmToken::EndOfStatement)) { @@ -5686,6 +5699,9 @@ bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) { if (IDVal == ".cpsetup") return parseDirectiveCPSetup(); + if (IDVal == ".cpreturn") + return parseDirectiveCPReturn(); + if (IDVal == ".module") return parseDirectiveModule(); diff --git a/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp b/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp index 4e865663fc0..994126e83b6 100644 --- a/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp +++ b/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp @@ -96,6 +96,8 @@ void MipsTargetStreamer::emitDirectiveCpRestore( void MipsTargetStreamer::emitDirectiveCpsetup(unsigned RegNo, int RegOrOffset, const MCSymbol &Sym, bool IsReg) { } +void MipsTargetStreamer::emitDirectiveCpreturn(unsigned SaveLocation, + bool SaveLocationIsRegister) {} void MipsTargetStreamer::emitDirectiveModuleFP() {} @@ -387,6 +389,12 @@ void MipsTargetAsmStreamer::emitDirectiveCpsetup(unsigned RegNo, forbidModuleDirective(); } +void MipsTargetAsmStreamer::emitDirectiveCpreturn(unsigned SaveLocation, + bool SaveLocationIsRegister) { + OS << "\t.cpreturn"; + forbidModuleDirective(); +} + void MipsTargetAsmStreamer::emitDirectiveModuleFP() { OS << "\t.module\tfp="; OS << ABIFlagsSection.getFpABIString(ABIFlagsSection.getFpABI()) << "\n"; @@ -838,6 +846,30 @@ void MipsTargetELFStreamer::emitDirectiveCpsetup(unsigned RegNo, forbidModuleDirective(); } +void MipsTargetELFStreamer::emitDirectiveCpreturn(unsigned SaveLocation, + bool SaveLocationIsRegister) { + // Only N32 and N64 emit anything for .cpreturn iff PIC is set. + if (!Pic || !(getABI().IsN32() || getABI().IsN64())) + return; + + MCInst Inst; + // Either restore the old $gp from a register or on the stack + if (SaveLocationIsRegister) { + Inst.setOpcode(Mips::OR); + Inst.addOperand(MCOperand::createReg(Mips::GP)); + Inst.addOperand(MCOperand::createReg(SaveLocation)); + Inst.addOperand(MCOperand::createReg(Mips::ZERO)); + } else { + Inst.setOpcode(Mips::LD); + Inst.addOperand(MCOperand::createReg(Mips::GP)); + Inst.addOperand(MCOperand::createReg(Mips::SP)); + Inst.addOperand(MCOperand::createImm(SaveLocation)); + } + getStreamer().EmitInstruction(Inst, STI); + + forbidModuleDirective(); +} + void MipsTargetELFStreamer::emitMipsAbiFlags() { MCAssembler &MCA = getStreamer().getAssembler(); MCContext &Context = MCA.getContext(); diff --git a/lib/Target/Mips/MipsTargetStreamer.h b/lib/Target/Mips/MipsTargetStreamer.h index 9e6136d673b..b3222f5d89e 100644 --- a/lib/Target/Mips/MipsTargetStreamer.h +++ b/lib/Target/Mips/MipsTargetStreamer.h @@ -82,6 +82,8 @@ public: int Offset); virtual void emitDirectiveCpsetup(unsigned RegNo, int RegOrOffset, const MCSymbol &Sym, bool IsReg); + virtual void emitDirectiveCpreturn(unsigned SaveLocation, + bool SaveLocationIsRegister); // FP abiflags directives virtual void emitDirectiveModuleFP(); @@ -195,6 +197,8 @@ public: int Offset) override; void emitDirectiveCpsetup(unsigned RegNo, int RegOrOffset, const MCSymbol &Sym, bool IsReg) override; + void emitDirectiveCpreturn(unsigned SaveLocation, + bool SaveLocationIsRegister) override; // FP abiflags directives void emitDirectiveModuleFP() override; @@ -246,6 +250,8 @@ public: int Offset) override; void emitDirectiveCpsetup(unsigned RegNo, int RegOrOffset, const MCSymbol &Sym, bool IsReg) override; + void emitDirectiveCpreturn(unsigned SaveLocation, + bool SaveLocationIsRegister) override; void emitMipsAbiFlags(); }; diff --git a/test/MC/Mips/cpsetup.s b/test/MC/Mips/cpsetup.s index 6b20562b0c5..95d84d95d85 100644 --- a/test/MC/Mips/cpsetup.s +++ b/test/MC/Mips/cpsetup.s @@ -24,6 +24,8 @@ t1: .cpsetup $25, 8, __cerror nop + .cpreturn + nop # ALL-LABEL: t1: @@ -45,9 +47,16 @@ t1: # ALL-NEXT: nop +# ASM-NEXT: .cpreturn +# NXX-NEXT: ld $gp, 8($sp) + +# ALL-NEXT: nop + t2: .cpsetup $25, $2, __cerror nop + .cpreturn + nop # ALL-LABEL: t2: @@ -69,6 +78,11 @@ t2: # ALL-NEXT: nop +# ASM-NEXT: .cpreturn +# NXX-NEXT: move $gp, $2 + +# ALL-NEXT: nop + # .cpsetup with local labels (PR22518): # The '1:' label isn't emitted in all cases but we still want a label to match @@ -115,6 +129,8 @@ t4: nop .cpsetup $25, 8, __cerror nop + .cpreturn + nop # Testing that .cpsetup expands to nothing in this case # by checking that the next instruction after the first @@ -122,12 +138,15 @@ t4: # ALL-LABEL: t4: +# NXX-NEXT: nop # NXX-NEXT: nop # NXX-NEXT: nop # ASM-NEXT: nop # ASM-NEXT: .cpsetup $25, 8, __cerror # ASM-NEXT: nop +# ASM-NEXT: .cpreturn +# ASM-NEXT: nop # Test that we accept constant expressions. .option pic2