[PATCH] Fix inline assembly that switches between ARM and Thumb modes

Greg Fitzgerald garious at gmail.com
Mon Dec 16 13:35:15 PST 2013


  This patch restores the ARM mode by [only] injecting any missing .arm/.thumb directives after parsing.  It will ensure the mapping symbols are generated and that any code following the inline assembly is encoded correctly.

  Jim, is this what you had in mind?

Hi rengolin, grosbach, aemerson,

http://llvm-reviews.chandlerc.com/D2255

CHANGE SINCE LAST DIFF
  http://llvm-reviews.chandlerc.com/D2255?vs=6069&id=6130#toc

Files:
  include/llvm/MC/MCTargetAsmParser.h
  lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp
  lib/Target/ARM/AsmParser/ARMAsmParser.cpp
  test/CodeGen/ARM/inlineasm-switch-mode.ll

Index: include/llvm/MC/MCTargetAsmParser.h
===================================================================
--- include/llvm/MC/MCTargetAsmParser.h
+++ include/llvm/MC/MCTargetAsmParser.h
@@ -183,6 +183,8 @@
   }
 
   virtual void onLabelParsed(MCSymbol *Symbol) { };
+
+  virtual bool finalizeInlineAsm() { return true; }
 };
 
 } // End llvm namespace
Index: lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp
===================================================================
--- lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp
+++ lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp
@@ -33,6 +33,7 @@
 #include "llvm/Support/TargetRegistry.h"
 #include "llvm/Support/raw_ostream.h"
 #include "llvm/Target/TargetMachine.h"
+#include "llvm/Target/TargetSubtargetInfo.h"
 using namespace llvm;
 
 namespace {
@@ -114,14 +115,12 @@
                                                   OutContext, OutStreamer,
                                                   *MAI));
 
-  // FIXME: It would be nice if we can avoid createing a new instance of
-  // MCSubtargetInfo here given TargetSubtargetInfo is available. However,
-  // we have to watch out for asm directives which can change subtarget
-  // state. e.g. .code 16, .code 32.
-  OwningPtr<MCSubtargetInfo>
-    STI(TM.getTarget().createMCSubtargetInfo(TM.getTargetTriple(),
-                                             TM.getTargetCPU(),
-                                             TM.getTargetFeatureString()));
+  // Reuse the existing Subtarget, because the AsmParser will
+  // modify it.  For example, when switching between ARM and
+  // Thumb mode.
+  const MCSubtargetInfo* STC = TM.getSubtargetImpl();
+  MCSubtargetInfo* STI = const_cast<MCSubtargetInfo*>(STC);
+
   OwningPtr<MCTargetAsmParser>
     TAP(TM.getTarget().createMCAsmParser(*STI, *Parser, *MII));
   if (!TAP)
@@ -135,6 +134,10 @@
                         /*NoFinalize*/ true);
   if (Res && !HasDiagHandler)
     report_fatal_error("Error parsing inline asm\n");
+
+  // Give the target parser the opportunity to restore system state.
+  // For example, restore ARM mode.
+  TAP.get()->finalizeInlineAsm();
 }
 
 static void EmitMSInlineAsmStr(const char *AsmStr, const MachineInstr *MI,
Index: lib/Target/ARM/AsmParser/ARMAsmParser.cpp
===================================================================
--- lib/Target/ARM/AsmParser/ARMAsmParser.cpp
+++ lib/Target/ARM/AsmParser/ARMAsmParser.cpp
@@ -79,6 +79,9 @@
 
   bool NextSymbolIsThumb;
 
+  // Was this parser initialized in thumb mode?
+  bool WasThumb;
+
   struct {
     ARMCC::CondCodes Cond;    // Condition for IT block.
     unsigned Mask:4;          // Condition mask for instructions.
@@ -277,6 +280,8 @@
     ITState.CurPosition = ~0U;
 
     NextSymbolIsThumb = false;
+
+    WasThumb = isThumb();
   }
 
   // Implementation of the MCTargetAsmParser interface:
@@ -295,6 +300,12 @@
                                bool MatchingInlineAsm);
   void onLabelParsed(MCSymbol *Symbol);
 
+  bool emitMode(bool WantThumb, SMLoc L);
+
+  bool finalizeInlineAsm() {
+    return emitMode(WasThumb, Parser.getTok().getLoc());
+  }
+
 };
 } // end anonymous namespace
 
@@ -7876,6 +7887,26 @@
   }
 }
 
+bool ARMAsmParser::emitMode(bool WantThumb, SMLoc L) {
+  if (WantThumb) {
+    if (!hasThumb())
+      return Error(L, "target does not support Thumb mode");
+
+    if (!isThumb())
+      SwitchMode();
+    getParser().getStreamer().EmitAssemblerFlag(MCAF_Code16);
+  } else {
+    if (!hasARM())
+      return Error(L, "target does not support ARM mode");
+
+    if (isThumb())
+      SwitchMode();
+    getParser().getStreamer().EmitAssemblerFlag(MCAF_Code32);
+  }
+
+  return false;
+}
+
 /// parseDirectiveThumbFunc
 ///  ::= .thumbfunc symbol_name
 bool ARMAsmParser::parseDirectiveThumbFunc(SMLoc L) {
@@ -7946,23 +7977,7 @@
     return Error(Parser.getTok().getLoc(), "unexpected token in directive");
   Parser.Lex();
 
-  if (Val == 16) {
-    if (!hasThumb())
-      return Error(L, "target does not support Thumb mode");
-
-    if (!isThumb())
-      SwitchMode();
-    getParser().getStreamer().EmitAssemblerFlag(MCAF_Code16);
-  } else {
-    if (!hasARM())
-      return Error(L, "target does not support ARM mode");
-
-    if (isThumb())
-      SwitchMode();
-    getParser().getStreamer().EmitAssemblerFlag(MCAF_Code32);
-  }
-
-  return false;
+  return emitMode(Val == 16, L);
 }
 
 /// parseDirectiveReq
Index: test/CodeGen/ARM/inlineasm-switch-mode.ll
===================================================================
--- /dev/null
+++ test/CodeGen/ARM/inlineasm-switch-mode.ll
@@ -0,0 +1,12 @@
+;RUN:  llc -mtriple=thumbv7-linux-gnueabi -filetype=obj < %s | llvm-objdump -arch=thumb -d - | FileCheck %s
+
+target triple = "thumbv7--linux-gnueabi"
+
+define hidden void @bah(i8* %start) #0 align 2 {
+  %1 = ptrtoint i8* %start to i32
+  %2 = tail call i32 asm sideeffect "@ Enter ARM Mode  \0A\09adr r3, 1f \0A\09bx  r3 \0A\09.align 2 \0A\09.code 32 \0A1:  push {r7} \0A\09mov r7, $4 \0A\09svc 0x0 \0A\09pop {r7} \0A\09@ Enter THUMB Mode\0A\09adr r3, 2f+1 \0A\09bx  r3 \0A\09.code 16 \0A2: \0A\09", "={r0},{r0},{r1},{r2},r,~{r3}"(i32 %1, i32 %1, i32 0, i32 983042) #3
+  ret void
+}
+; CHECK: $a
+; CHECK-NEXT: 04 70
+; CHECK-NEXT: 2d e5
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D2255.7.patch
Type: text/x-patch
Size: 5251 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20131216/547249c4/attachment.bin>


More information about the llvm-commits mailing list