// 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);
};
}
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.
///
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.
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;
--- /dev/null
+; 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
+}