Fix pr4091: Add support for "m" constraint in ARM inline assembly.
authorBob Wilson <bob.wilson@apple.com>
Tue, 19 May 2009 05:53:42 +0000 (05:53 +0000)
committerBob Wilson <bob.wilson@apple.com>
Tue, 19 May 2009 05:53:42 +0000 (05:53 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@72105 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/ARM/ARMISelDAGToDAG.cpp
lib/Target/ARM/AsmPrinter/ARMAsmPrinter.cpp
test/CodeGen/ARM/2009-05-18-InlineAsmMem.ll [new file with mode: 0644]

index 3bc5ae91467dd49ff1abd4abbe535f93178f29de..ca3a9cb4032921a640f03d7fd70db5321b4c37fd 100644 (file)
@@ -89,6 +89,13 @@ public:
   
   // Include the pieces autogenerated from the target description.
 #include "ARMGenDAGISel.inc"
+
+private:
+    /// SelectInlineAsmMemoryOperand - Implement addressing mode selection for
+    /// inline asm expressions.
+    virtual bool SelectInlineAsmMemoryOperand(const SDValue &Op,
+                                              char ConstraintCode,
+                                              std::vector<SDValue> &OutOps);
 };
 }
 
@@ -881,6 +888,21 @@ SDNode *ARMDAGToDAGISel::Select(SDValue Op) {
   return SelectCode(Op);
 }
 
+bool ARMDAGToDAGISel::
+SelectInlineAsmMemoryOperand(const SDValue &Op, char ConstraintCode,
+                             std::vector<SDValue> &OutOps) {
+  assert(ConstraintCode == 'm' && "unexpected asm memory constraint");
+
+  SDValue Base, Offset, Opc;
+  if (!SelectAddrMode2(Op, Op, Base, Offset, Opc))
+    return true;
+  
+  OutOps.push_back(Base);
+  OutOps.push_back(Offset);
+  OutOps.push_back(Opc);
+  return false;
+}
+
 /// createARMISelDag - This pass converts a legalized DAG into a
 /// ARM-specific DAG, ready for instruction scheduling.
 ///
index 062423a04e64c1b45139b500df3d698cd66aac13..bfe9a0117197c646bf80fceba6a853750344489e 100644 (file)
@@ -124,6 +124,9 @@ namespace {
 
     virtual bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
                                  unsigned AsmVariant, const char *ExtraCode);
+    virtual bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
+                                       unsigned AsmVariant,
+                                       const char *ExtraCode);
 
     void printModuleLevelGV(const GlobalVariable* GVar);
     bool printInstruction(const MachineInstr *MI);  // autogenerated.
@@ -769,6 +772,15 @@ bool ARMAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
   return false;
 }
 
+bool ARMAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
+                                          unsigned OpNo, unsigned AsmVariant,
+                                          const char *ExtraCode) {
+  if (ExtraCode && ExtraCode[0])
+    return true; // Unknown modifier.
+  printAddrMode2Operand(MI, OpNo);
+  return false;
+}
+
 void ARMAsmPrinter::printMachineInstruction(const MachineInstr *MI) {
   ++EmittedInsts;
 
diff --git a/test/CodeGen/ARM/2009-05-18-InlineAsmMem.ll b/test/CodeGen/ARM/2009-05-18-InlineAsmMem.ll
new file mode 100644 (file)
index 0000000..f942c9f
--- /dev/null
@@ -0,0 +1,7 @@
+; RUN: llvm-as < %s | llc -march=arm | grep swp
+; PR4091
+
+define void @foo(i32 %i, i32* %p) nounwind {
+       %asmtmp = call i32 asm sideeffect "swp $0, $2, $3", "=&r,=*m,r,*m,~{memory}"(i32* %p, i32 %i, i32* %p) nounwind
+       ret void
+}