[llvm] r200449 - ARM IAS: support .movsp

Saleem Abdulrasool compnerd at compnerd.org
Wed Jan 29 20:46:25 PST 2014


Author: compnerd
Date: Wed Jan 29 22:46:24 2014
New Revision: 200449

URL: http://llvm.org/viewvc/llvm-project?rev=200449&view=rev
Log:
ARM IAS: support .movsp

.movsp is an ARM unwinding directive that indicates to the unwinder that a
register contains an offset from the current stack pointer.  If the offset is
unspecified, it defaults to zero.

Added:
    llvm/trunk/test/MC/ARM/eh-directive-movsp-diagnostics.s
    llvm/trunk/test/MC/ARM/eh-directive-movsp.s
Modified:
    llvm/trunk/include/llvm/MC/MCStreamer.h
    llvm/trunk/lib/Target/ARM/ARMAsmPrinter.cpp
    llvm/trunk/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
    llvm/trunk/lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp

Modified: llvm/trunk/include/llvm/MC/MCStreamer.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/MC/MCStreamer.h?rev=200449&r1=200448&r2=200449&view=diff
==============================================================================
--- llvm/trunk/include/llvm/MC/MCStreamer.h (original)
+++ llvm/trunk/include/llvm/MC/MCStreamer.h Wed Jan 29 22:46:24 2014
@@ -93,6 +93,7 @@ public:
   virtual void emitHandlerData() = 0;
   virtual void emitSetFP(unsigned FpReg, unsigned SpReg,
                          int64_t Offset = 0) = 0;
+  virtual void emitMovSP(unsigned Reg, int64_t Offset = 0) = 0;
   virtual void emitPad(int64_t Offset) = 0;
   virtual void emitRegSave(const SmallVectorImpl<unsigned> &RegList,
                            bool isVector) = 0;

Modified: llvm/trunk/lib/Target/ARM/ARMAsmPrinter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMAsmPrinter.cpp?rev=200449&r1=200448&r2=200449&view=diff
==============================================================================
--- llvm/trunk/lib/Target/ARM/ARMAsmPrinter.cpp (original)
+++ llvm/trunk/lib/Target/ARM/ARMAsmPrinter.cpp Wed Jan 29 22:46:24 2014
@@ -1091,11 +1091,11 @@ void ARMAsmPrinter::EmitUnwindingInstruc
         // instruction.
         ATS.emitPad(Offset);
       } else {
-        MI->dump();
-        llvm_unreachable("Unsupported opcode for unwinding information");
+        // Move of SP to a register.  Positive values correspond to an "add"
+        // instruction.
+        ATS.emitMovSP(DstReg, -Offset);
       }
     } else if (DstReg == ARM::SP) {
-      // FIXME: .movsp goes here
       MI->dump();
       llvm_unreachable("Unsupported opcode for unwinding information");
     }

Modified: llvm/trunk/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/AsmParser/ARMAsmParser.cpp?rev=200449&r1=200448&r2=200449&view=diff
==============================================================================
--- llvm/trunk/lib/Target/ARM/AsmParser/ARMAsmParser.cpp (original)
+++ llvm/trunk/lib/Target/ARM/AsmParser/ARMAsmParser.cpp Wed Jan 29 22:46:24 2014
@@ -127,7 +127,7 @@ class UnwindContext {
   int FPReg;
 
 public:
-  UnwindContext(MCAsmParser &P) : Parser(P), FPReg(-1) {}
+  UnwindContext(MCAsmParser &P) : Parser(P), FPReg(ARM::SP) {}
 
   bool hasFnStart() const { return !FnStartLocs.empty(); }
   bool cantUnwind() const { return !CantUnwindLocs.empty(); }
@@ -182,7 +182,7 @@ public:
     PersonalityLocs = Locs();
     HandlerDataLocs = Locs();
     PersonalityIndexLocs = Locs();
-    FPReg = -1;
+    FPReg = ARM::SP;
   }
 };
 
@@ -297,6 +297,7 @@ class ARMAsmParser : public MCTargetAsmP
   bool parseDirectivePersonalityIndex(SMLoc L);
   bool parseDirectiveUnwindRaw(SMLoc L);
   bool parseDirectiveTLSDescSeq(SMLoc L);
+  bool parseDirectiveMovSP(SMLoc L);
 
   StringRef splitMnemonic(StringRef Mnemonic, unsigned &PredicationCode,
                           bool &CarrySetting, unsigned &ProcessorIMod,
@@ -8087,6 +8088,8 @@ bool ARMAsmParser::ParseDirective(AsmTok
     return parseDirectiveUnwindRaw(DirectiveID.getLoc());
   else if (IDVal == ".tlsdescseq")
     return parseDirectiveTLSDescSeq(DirectiveID.getLoc());
+  else if (IDVal == ".movsp")
+    return parseDirectiveMovSP(DirectiveID.getLoc());
   return true;
 }
 
@@ -8616,7 +8619,7 @@ bool ARMAsmParser::parseDirectiveSetFP(S
   }
 
   // Consume comma
-  if (!Parser.getTok().is(AsmToken::Comma)) {
+  if (Parser.getTok().isNot(AsmToken::Comma)) {
     Error(Parser.getTok().getLoc(), "comma expected");
     return false;
   }
@@ -9028,6 +9031,69 @@ bool ARMAsmParser::parseDirectiveTLSDesc
   return false;
 }
 
+/// parseDirectiveMovSP
+///  ::= .movsp reg [, #offset]
+bool ARMAsmParser::parseDirectiveMovSP(SMLoc L) {
+  if (!UC.hasFnStart()) {
+    Parser.eatToEndOfStatement();
+    Error(L, ".fnstart must precede .movsp directives");
+    return false;
+  }
+  if (UC.getFPReg() != ARM::SP) {
+    Parser.eatToEndOfStatement();
+    Error(L, "unexpected .movsp directive");
+    return false;
+  }
+
+  SMLoc SPRegLoc = Parser.getTok().getLoc();
+  int SPReg = tryParseRegister();
+  if (SPReg == -1) {
+    Parser.eatToEndOfStatement();
+    Error(SPRegLoc, "register expected");
+    return false;
+  }
+
+  if (SPReg == ARM::SP || SPReg == ARM::PC) {
+    Parser.eatToEndOfStatement();
+    Error(SPRegLoc, "sp and pc are not permitted in .movsp directive");
+    return false;
+  }
+
+  int64_t Offset = 0;
+  if (Parser.getTok().is(AsmToken::Comma)) {
+    Parser.Lex();
+
+    if (Parser.getTok().isNot(AsmToken::Hash)) {
+      Error(Parser.getTok().getLoc(), "expected #constant");
+      Parser.eatToEndOfStatement();
+      return false;
+    }
+    Parser.Lex();
+
+    const MCExpr *OffsetExpr;
+    SMLoc OffsetLoc = Parser.getTok().getLoc();
+    if (Parser.parseExpression(OffsetExpr)) {
+      Parser.eatToEndOfStatement();
+      Error(OffsetLoc, "malformed offset expression");
+      return false;
+    }
+
+    const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(OffsetExpr);
+    if (!CE) {
+      Parser.eatToEndOfStatement();
+      Error(OffsetLoc, "offset must be an immediate constant");
+      return false;
+    }
+
+    Offset = CE->getValue();
+  }
+
+  getTargetStreamer().emitMovSP(SPReg, Offset);
+  UC.saveFPReg(SPReg);
+
+  return false;
+}
+
 /// Force static initialization.
 extern "C" void LLVMInitializeARMAsmParser() {
   RegisterMCAsmParser<ARMAsmParser> X(TheARMTarget);

Modified: llvm/trunk/lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp?rev=200449&r1=200448&r2=200449&view=diff
==============================================================================
--- llvm/trunk/lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp (original)
+++ llvm/trunk/lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp Wed Jan 29 22:46:24 2014
@@ -123,6 +123,7 @@ class ARMTargetAsmStreamer : public ARMT
   virtual void emitPersonalityIndex(unsigned Index);
   virtual void emitHandlerData();
   virtual void emitSetFP(unsigned FpReg, unsigned SpReg, int64_t Offset = 0);
+  virtual void emitMovSP(unsigned Reg, int64_t Offset = 0);
   virtual void emitPad(int64_t Offset);
   virtual void emitRegSave(const SmallVectorImpl<unsigned> &RegList,
                            bool isVector);
@@ -172,6 +173,16 @@ void ARMTargetAsmStreamer::emitSetFP(uns
     OS << ", #" << Offset;
   OS << '\n';
 }
+void ARMTargetAsmStreamer::emitMovSP(unsigned Reg, int64_t Offset) {
+  assert((Reg != ARM::SP && Reg != ARM::PC) &&
+         "the operand of .movsp cannot be either sp or pc");
+
+  OS << "\t.movsp\t";
+  InstPrinter.printRegName(OS, Reg);
+  if (Offset)
+    OS << ", #" << Offset;
+  OS << '\n';
+}
 void ARMTargetAsmStreamer::emitPad(int64_t Offset) {
   OS << "\t.pad\t#" << Offset << '\n';
 }
@@ -387,6 +398,7 @@ private:
   virtual void emitPersonalityIndex(unsigned Index);
   virtual void emitHandlerData();
   virtual void emitSetFP(unsigned FpReg, unsigned SpReg, int64_t Offset = 0);
+  virtual void emitMovSP(unsigned Reg, int64_t Offset = 0);
   virtual void emitPad(int64_t Offset);
   virtual void emitRegSave(const SmallVectorImpl<unsigned> &RegList,
                            bool isVector);
@@ -448,6 +460,7 @@ public:
   void emitPersonalityIndex(unsigned index);
   void emitHandlerData();
   void emitSetFP(unsigned NewFpReg, unsigned NewSpReg, int64_t Offset = 0);
+  void emitMovSP(unsigned Reg, int64_t Offset = 0);
   void emitPad(int64_t Offset);
   void emitRegSave(const SmallVectorImpl<unsigned> &RegList, bool isVector);
   void emitUnwindRaw(int64_t Offset, const SmallVectorImpl<uint8_t> &Opcodes);
@@ -657,6 +670,9 @@ void ARMTargetELFStreamer::emitSetFP(uns
                                      int64_t Offset) {
   getStreamer().emitSetFP(FpReg, SpReg, Offset);
 }
+void ARMTargetELFStreamer::emitMovSP(unsigned Reg, int64_t Offset) {
+  getStreamer().emitMovSP(Reg, Offset);
+}
 void ARMTargetELFStreamer::emitPad(int64_t Offset) {
   getStreamer().emitPad(Offset);
 }
@@ -1203,6 +1219,20 @@ void ARMELFStreamer::emitSetFP(unsigned
     FPOffset += Offset;
 }
 
+void ARMELFStreamer::emitMovSP(unsigned Reg, int64_t Offset) {
+  assert((Reg != ARM::SP && Reg != ARM::PC) &&
+         "the operand of .movsp cannot be either sp or pc");
+  assert(FPReg == ARM::SP && "current FP must be SP");
+
+  FlushPendingOffset();
+
+  FPReg = Reg;
+  FPOffset = SPOffset + Offset;
+
+  const MCRegisterInfo *MRI = getContext().getRegisterInfo();
+  UnwindOpAsm.EmitSetSP(MRI->getEncodingValue(FPReg));
+}
+
 void ARMELFStreamer::emitPad(int64_t Offset) {
   // Track the change of the $sp offset
   SPOffset -= Offset;

Added: llvm/trunk/test/MC/ARM/eh-directive-movsp-diagnostics.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/ARM/eh-directive-movsp-diagnostics.s?rev=200449&view=auto
==============================================================================
--- llvm/trunk/test/MC/ARM/eh-directive-movsp-diagnostics.s (added)
+++ llvm/trunk/test/MC/ARM/eh-directive-movsp-diagnostics.s Wed Jan 29 22:46:24 2014
@@ -0,0 +1,102 @@
+@ RUN: not llvm-mc -triple armv7-eabi -filetype asm -o /dev/null 2>&1 %s \
+@ RUN:  | FileCheck %s
+
+	.syntax unified
+	.thumb
+
+	.global false_start
+	.type false_start,%function
+	.thumb_func
+false_start:
+	.movsp r7
+
+@ CHECK: error: .fnstart must precede .movsp directive
+@ CHECK: 	.movsp r7
+@ CHECK:        ^
+
+	.global beyond_saving
+	.type beyond_saving,%function
+	.thumb_func
+beyond_saving:
+	.fnstart
+	.setfp r11, sp, #8
+	add r11, sp, #8
+	.movsp r7
+	mov r7, r11
+	.fnend
+
+@ CHECK: error: unexpected .movsp directive
+@ CHECK: 	.movsp r7
+@ CHECK:        ^
+
+
+	.global sp_invalid
+	.type sp_invalid,%function
+	.thumb_func
+sp_invalid:
+	.fnstart
+	.movsp r13
+	mov sp, sp
+	.fnend
+
+@ CHECK: error: sp and pc are not permitted in .movsp directive
+@ CHECK: 	.movsp r13
+@ CHECK:               ^
+
+
+	.global pc_invalid
+	.type pc_invalid,%function
+	.thumb_func
+pc_invalid:
+	.fnstart
+	.movsp r15
+	mov sp, pc
+	.fnend
+
+@ CHECK: error: sp and pc are not permitted in .movsp directive
+@ CHECK: 	.movsp r15
+@ CHECK:               ^
+
+
+	.global constant_required
+	.type constant_required,%function
+	.thumb_func
+constant_required:
+	.fnstart
+	.movsp r11,
+	mov sp, r11
+	.fnend
+
+@ CHECK: error: expected #constant
+@ CHECK: 	.movsp r11,
+@ CHECK:                   ^
+
+
+	.global constant_constant
+	.type constant_constant,%function
+	.thumb_func
+constant_constant:
+	.fnstart
+	.movsp r11, #constant
+	mov sp, r11
+	.fnend
+
+@ CHECK: error: offset must be an immediate constant
+@ CHECK: 	.movsp r11, #constant
+@ CHECK:                     ^
+
+
+	.arm
+
+	.global register_required
+	.type register_required,%function
+register_required:
+	.fnstart
+	.movsp #42
+	mov sp, #42
+	.fnend
+
+@ CHECK: error: register expected
+@ CHECK: 	.movsp #42
+@ CHECK:               ^
+

Added: llvm/trunk/test/MC/ARM/eh-directive-movsp.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/ARM/eh-directive-movsp.s?rev=200449&view=auto
==============================================================================
--- llvm/trunk/test/MC/ARM/eh-directive-movsp.s (added)
+++ llvm/trunk/test/MC/ARM/eh-directive-movsp.s Wed Jan 29 22:46:24 2014
@@ -0,0 +1,44 @@
+@ RUN: llvm-mc -triple armv7-eabi -filetype obj -o - %s | llvm-readobj -s -sd \
+@ RUN:   | FileCheck %s
+
+	.syntax unified
+	.thumb
+
+	.section .duplicate
+
+	.global duplicate
+	.type duplicate,%function
+duplicate:
+	.fnstart
+	.setfp sp, sp, #8
+	add sp, sp, #8
+	.movsp r11
+	mov r11, sp
+	.fnend
+
+@ CHECK: Section {
+@ CHECK:   Name: .ARM.exidx.duplicate
+@ CHECK:   SectionData (
+@ CHECK:     0000: 00000000 B09B9B80
+@ CHECK:   )
+@ CHECK: }
+
+
+	.section .squash
+
+	.global squash
+	.type squash,%function
+squash:
+	.fnstart
+	.movsp ip
+	mov ip, sp
+	.save {fp, ip, lr}
+	stmfd sp!, {fp, ip, lr}
+	.fnend
+
+@ CHECK: Section {
+@ CHECK:   Name: .ARM.exidx.squash
+@ CHECK:   SectionData (
+@ CHECK:     0000: 00000000 9C808580
+@ CHECK:   )
+@ CHECK: }





More information about the llvm-commits mailing list