<div dir="ltr">(catching up on email post-vacation)<div><br></div><div>I'm a bit confused about this: the code looks like what I'd expect, but I thought we weren't going to do inline asm. Could you clarify the usecase? I thought we'd do calls to the embedders / syscalls through extern C functions, so I'm not sure I get the use for inline asm.</div></div><div class="gmail_extra"><br><div class="gmail_quote">On Thu, Nov 12, 2015 at 5:42 PM, Dan Gohman via llvm-commits <span dir="ltr"><<a href="mailto:llvm-commits@lists.llvm.org" target="_blank">llvm-commits@lists.llvm.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: djg<br>
Date: Thu Nov 12 19:42:29 2015<br>
New Revision: 252997<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=252997&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project?rev=252997&view=rev</a><br>
Log:<br>
[WebAssembly] Inline asm support.<br>
<br>
Added:<br>
    llvm/trunk/test/CodeGen/WebAssembly/inline-asm.ll<br>
Modified:<br>
    llvm/trunk/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp<br>
    llvm/trunk/lib/Target/WebAssembly/WebAssemblyISelDAGToDAG.cpp<br>
    llvm/trunk/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp<br>
    llvm/trunk/lib/Target/WebAssembly/WebAssemblyISelLowering.h<br>
<br>
Modified: llvm/trunk/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp?rev=252997&r1=252996&r2=252997&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp?rev=252997&r1=252996&r2=252997&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp (original)<br>
+++ llvm/trunk/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp Thu Nov 12 19:42:29 2015<br>
@@ -77,6 +77,12 @@ private:<br>
   void EmitFunctionBodyStart() override;<br>
   void EmitInstruction(const MachineInstr *MI) override;<br>
   void EmitEndOfAsmFile(Module &M) override;<br>
+  bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,<br>
+                       unsigned AsmVariant, const char *ExtraCode,<br>
+                       raw_ostream &OS) override;<br>
+  bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,<br>
+                             unsigned AsmVariant, const char *ExtraCode,<br>
+                             raw_ostream &OS) override;<br>
<br>
   std::string getRegTypeName(unsigned RegNo) const;<br>
   const char *toString(MVT VT) const;<br>
@@ -275,6 +281,41 @@ void WebAssemblyAsmPrinter::EmitEndOfAsm<br>
     OutStreamer->EmitRawText(Text.substr(0, Text.size() - 1));<br>
 }<br>
<br>
+bool WebAssemblyAsmPrinter::PrintAsmOperand(const MachineInstr *MI,<br>
+                                            unsigned OpNo, unsigned AsmVariant,<br>
+                                            const char *ExtraCode,<br>
+                                            raw_ostream &OS) {<br>
+  if (AsmVariant != 0)<br>
+    report_fatal_error("There are no defined alternate asm variants");<br>
+<br>
+  if (!ExtraCode) {<br>
+    const MachineOperand &MO = MI->getOperand(OpNo);<br>
+    if (MO.isImm())<br>
+      OS << MO.getImm();<br>
+    else<br>
+      OS << regToString(MO);<br>
+    return false;<br>
+  }<br>
+<br>
+  return AsmPrinter::PrintAsmOperand(MI, OpNo, AsmVariant, ExtraCode, OS);<br>
+}<br>
+<br>
+bool WebAssemblyAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,<br>
+                                                  unsigned OpNo,<br>
+                                                  unsigned AsmVariant,<br>
+                                                  const char *ExtraCode,<br>
+                                                  raw_ostream &OS) {<br>
+  if (AsmVariant != 0)<br>
+    report_fatal_error("There are no defined alternate asm variants");<br>
+<br>
+  if (!ExtraCode) {<br>
+    OS << regToString(MI->getOperand(OpNo));<br>
+    return false;<br>
+  }<br>
+<br>
+  return AsmPrinter::PrintAsmMemoryOperand(MI, OpNo, AsmVariant, ExtraCode, OS);<br>
+}<br>
+<br>
 // Force static initialization.<br>
 extern "C" void LLVMInitializeWebAssemblyAsmPrinter() {<br>
   RegisterAsmPrinter<WebAssemblyAsmPrinter> X(TheWebAssemblyTarget32);<br>
<br>
Modified: llvm/trunk/lib/Target/WebAssembly/WebAssemblyISelDAGToDAG.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/WebAssembly/WebAssemblyISelDAGToDAG.cpp?rev=252997&r1=252996&r2=252997&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/WebAssembly/WebAssemblyISelDAGToDAG.cpp?rev=252997&r1=252996&r2=252997&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/Target/WebAssembly/WebAssemblyISelDAGToDAG.cpp (original)<br>
+++ llvm/trunk/lib/Target/WebAssembly/WebAssemblyISelDAGToDAG.cpp Thu Nov 12 19:42:29 2015<br>
@@ -56,6 +56,9 @@ public:<br>
<br>
   SDNode *Select(SDNode *Node) override;<br>
<br>
+  bool SelectInlineAsmMemoryOperand(const SDValue &Op, unsigned ConstraintID,<br>
+                                    std::vector<SDValue> &OutOps) override;<br>
+<br>
 // Include the pieces autogenerated from the target description.<br>
 #include "WebAssemblyGenDAGISel.inc"<br>
<br>
@@ -101,6 +104,22 @@ SDNode *WebAssemblyDAGToDAGISel::Select(<br>
   return ResNode;<br>
 }<br>
<br>
+bool WebAssemblyDAGToDAGISel::SelectInlineAsmMemoryOperand(<br>
+    const SDValue &Op, unsigned ConstraintID, std::vector<SDValue> &OutOps) {<br>
+  switch (ConstraintID) {<br>
+  case InlineAsm::Constraint_i:<br>
+  case InlineAsm::Constraint_m:<br>
+    // We just support simple memory operands that just have a single address<br>
+    // operand and need no special handling.<br>
+    OutOps.push_back(Op);<br>
+    return false;<br>
+  default:<br>
+    break;<br>
+  }<br>
+<br>
+  return true;<br>
+}<br>
+<br>
 /// This pass converts a legalized DAG into a WebAssembly-specific DAG, ready<br>
 /// for instruction scheduling.<br>
 FunctionPass *llvm::createWebAssemblyISelDag(WebAssemblyTargetMachine &TM,<br>
<br>
Modified: llvm/trunk/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp?rev=252997&r1=252996&r2=252997&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp?rev=252997&r1=252996&r2=252997&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp (original)<br>
+++ llvm/trunk/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp Thu Nov 12 19:42:29 2015<br>
@@ -211,6 +211,23 @@ WebAssemblyTargetLowering::getTargetNode<br>
   return nullptr;<br>
 }<br>
<br>
+std::pair<unsigned, const TargetRegisterClass *><br>
+WebAssemblyTargetLowering::getRegForInlineAsmConstraint(<br>
+    const TargetRegisterInfo *TRI, StringRef Constraint, MVT VT) const {<br>
+  // First, see if this is a constraint that directly corresponds to a<br>
+  // WebAssembly register class.<br>
+  if (Constraint.size() == 1) {<br>
+    switch (Constraint[0]) {<br>
+    case 'r':<br>
+      return std::make_pair(0U, &WebAssembly::I32RegClass);<br>
+    default:<br>
+      break;<br>
+    }<br>
+  }<br>
+<br>
+  return TargetLowering::getRegForInlineAsmConstraint(TRI, Constraint, VT);<br>
+}<br>
+<br>
 //===----------------------------------------------------------------------===//<br>
 // WebAssembly Lowering private implementation.<br>
 //===----------------------------------------------------------------------===//<br>
<br>
Modified: llvm/trunk/lib/Target/WebAssembly/WebAssemblyISelLowering.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/WebAssembly/WebAssemblyISelLowering.h?rev=252997&r1=252996&r2=252997&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/WebAssembly/WebAssemblyISelLowering.h?rev=252997&r1=252996&r2=252997&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/Target/WebAssembly/WebAssemblyISelLowering.h (original)<br>
+++ llvm/trunk/lib/Target/WebAssembly/WebAssemblyISelLowering.h Thu Nov 12 19:42:29 2015<br>
@@ -49,6 +49,9 @@ private:<br>
   bool isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const override;<br>
   MVT getScalarShiftAmountTy(const DataLayout &DL, EVT) const override;<br>
   const char *getTargetNodeName(unsigned Opcode) const override;<br>
+  std::pair<unsigned, const TargetRegisterClass *><br>
+  getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI,<br>
+                               StringRef Constraint, MVT VT) const override;<br>
<br>
   SDValue LowerCall(CallLoweringInfo &CLI,<br>
                     SmallVectorImpl<SDValue> &InVals) const override;<br>
<br>
Added: llvm/trunk/test/CodeGen/WebAssembly/inline-asm.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/WebAssembly/inline-asm.ll?rev=252997&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/WebAssembly/inline-asm.ll?rev=252997&view=auto</a><br>
==============================================================================<br>
--- llvm/trunk/test/CodeGen/WebAssembly/inline-asm.ll (added)<br>
+++ llvm/trunk/test/CodeGen/WebAssembly/inline-asm.ll Thu Nov 12 19:42:29 2015<br>
@@ -0,0 +1,53 @@<br>
+; RUN: llc < %s -asm-verbose=false | FileCheck %s<br>
+<br>
+; Test basic inline assembly.<br>
+<br>
+target datalayout = "e-p:32:32-i64:64-n32:64-S128"<br>
+target triple = "wasm32-unknown-unknown"<br>
+<br>
+; CHECK-LABEL: foo:<br>
+; CHECK-NEXT: .param i32{{$}}<br>
+; CHECK-NEXT: .result i32{{$}}<br>
+; CHECK-NEXT: .local i32, i32{{$}}<br>
+; CHECK-NEXT: #APP{{$}}<br>
+; CHECK-NEXT: 1 = aaa(0){{$}}<br>
+; CHECK-NEXT: #NO_APP{{$}}<br>
+; CHECK-NEXT: return (get_local 1){{$}}<br>
+define i32 @foo(i32 %r) {<br>
+entry:<br>
+  %0 = tail call i32 asm sideeffect "$0 = aaa($1)", "=r,r"(i32 %r) #0, !srcloc !0<br>
+  ret i32 %0<br>
+}<br>
+<br>
+; CHECK-LABEL: bar:<br>
+; CHECK-NEXT: .param i32{{$}}<br>
+; CHECK-NEXT: .param i32{{$}}<br>
+; CHECK-NEXT: .local i32, i32{{$}}<br>
+; CHECK-NEXT: #APP{{$}}<br>
+; CHECK-NEXT: 1 = bbb(0){{$}}<br>
+; CHECK-NEXT: #NO_APP{{$}}<br>
+; CHECK-NEXT: return{{$}}<br>
+define void @bar(i32* %r, i32* %s) {<br>
+entry:<br>
+  tail call void asm sideeffect "$0 = bbb($1)", "=*m,*m"(i32* %s, i32* %r) #0, !srcloc !1<br>
+  ret void<br>
+}<br>
+<br>
+; CHECK-LABEL: imm:<br>
+; CHECK-NEXT: .result i32{{$}}<br>
+; CHECK-NEXT: .local i32{{$}}<br>
+; CHECK-NEXT: #APP{{$}}<br>
+; CHECK-NEXT: 0 = ccc(42){{$}}<br>
+; CHECK-NEXT: #NO_APP{{$}}<br>
+; CHECK-NEXT: return (get_local 0){{$}}<br>
+define i32 @imm() {<br>
+entry:<br>
+  %0 = tail call i32 asm sideeffect "$0 = ccc($1)", "=r,i"(i32 42) #0, !srcloc !2<br>
+  ret i32 %0<br>
+}<br>
+<br>
+attributes #0 = { nounwind }<br>
+<br>
+!0 = !{i32 47}<br>
+!1 = !{i32 145}<br>
+!2 = !{i32 231}<br>
<br>
<br>
_______________________________________________<br>
llvm-commits mailing list<br>
<a href="mailto:llvm-commits@lists.llvm.org">llvm-commits@lists.llvm.org</a><br>
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits</a><br>
</blockquote></div><br></div>