[llvm] r252997 - [WebAssembly] Inline asm support.
Dan Gohman via llvm-commits
llvm-commits at lists.llvm.org
Tue Nov 17 07:09:01 PST 2015
We do have __builtin functions for all instructions not accessible through
plain C syntax, so inline asm will almost never be needed. However, inline
asm is a useful tool for writing certain kinds of testcases, both for LLVM
itself and for the underlying platform.
Dan
On Mon, Nov 16, 2015 at 4:51 PM, JF Bastien <jfb at chromium.org> wrote:
> (catching up on email post-vacation)
>
> 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.
>
> On Thu, Nov 12, 2015 at 5:42 PM, Dan Gohman via llvm-commits <
> llvm-commits at lists.llvm.org> wrote:
>
>> Author: djg
>> Date: Thu Nov 12 19:42:29 2015
>> New Revision: 252997
>>
>> URL: http://llvm.org/viewvc/llvm-project?rev=252997&view=rev
>> Log:
>> [WebAssembly] Inline asm support.
>>
>> Added:
>> llvm/trunk/test/CodeGen/WebAssembly/inline-asm.ll
>> Modified:
>> llvm/trunk/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp
>> llvm/trunk/lib/Target/WebAssembly/WebAssemblyISelDAGToDAG.cpp
>> llvm/trunk/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp
>> llvm/trunk/lib/Target/WebAssembly/WebAssemblyISelLowering.h
>>
>> Modified: llvm/trunk/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp
>> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp?rev=252997&r1=252996&r2=252997&view=diff
>>
>> ==============================================================================
>> --- llvm/trunk/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp (original)
>> +++ llvm/trunk/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp Thu Nov
>> 12 19:42:29 2015
>> @@ -77,6 +77,12 @@ private:
>> void EmitFunctionBodyStart() override;
>> void EmitInstruction(const MachineInstr *MI) override;
>> void EmitEndOfAsmFile(Module &M) override;
>> + bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
>> + unsigned AsmVariant, const char *ExtraCode,
>> + raw_ostream &OS) override;
>> + bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
>> + unsigned AsmVariant, const char *ExtraCode,
>> + raw_ostream &OS) override;
>>
>> std::string getRegTypeName(unsigned RegNo) const;
>> const char *toString(MVT VT) const;
>> @@ -275,6 +281,41 @@ void WebAssemblyAsmPrinter::EmitEndOfAsm
>> OutStreamer->EmitRawText(Text.substr(0, Text.size() - 1));
>> }
>>
>> +bool WebAssemblyAsmPrinter::PrintAsmOperand(const MachineInstr *MI,
>> + unsigned OpNo, unsigned
>> AsmVariant,
>> + const char *ExtraCode,
>> + raw_ostream &OS) {
>> + if (AsmVariant != 0)
>> + report_fatal_error("There are no defined alternate asm variants");
>> +
>> + if (!ExtraCode) {
>> + const MachineOperand &MO = MI->getOperand(OpNo);
>> + if (MO.isImm())
>> + OS << MO.getImm();
>> + else
>> + OS << regToString(MO);
>> + return false;
>> + }
>> +
>> + return AsmPrinter::PrintAsmOperand(MI, OpNo, AsmVariant, ExtraCode,
>> OS);
>> +}
>> +
>> +bool WebAssemblyAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
>> + unsigned OpNo,
>> + unsigned AsmVariant,
>> + const char *ExtraCode,
>> + raw_ostream &OS) {
>> + if (AsmVariant != 0)
>> + report_fatal_error("There are no defined alternate asm variants");
>> +
>> + if (!ExtraCode) {
>> + OS << regToString(MI->getOperand(OpNo));
>> + return false;
>> + }
>> +
>> + return AsmPrinter::PrintAsmMemoryOperand(MI, OpNo, AsmVariant,
>> ExtraCode, OS);
>> +}
>> +
>> // Force static initialization.
>> extern "C" void LLVMInitializeWebAssemblyAsmPrinter() {
>> RegisterAsmPrinter<WebAssemblyAsmPrinter> X(TheWebAssemblyTarget32);
>>
>> Modified: llvm/trunk/lib/Target/WebAssembly/WebAssemblyISelDAGToDAG.cpp
>> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/WebAssembly/WebAssemblyISelDAGToDAG.cpp?rev=252997&r1=252996&r2=252997&view=diff
>>
>> ==============================================================================
>> --- llvm/trunk/lib/Target/WebAssembly/WebAssemblyISelDAGToDAG.cpp
>> (original)
>> +++ llvm/trunk/lib/Target/WebAssembly/WebAssemblyISelDAGToDAG.cpp Thu Nov
>> 12 19:42:29 2015
>> @@ -56,6 +56,9 @@ public:
>>
>> SDNode *Select(SDNode *Node) override;
>>
>> + bool SelectInlineAsmMemoryOperand(const SDValue &Op, unsigned
>> ConstraintID,
>> + std::vector<SDValue> &OutOps)
>> override;
>> +
>> // Include the pieces autogenerated from the target description.
>> #include "WebAssemblyGenDAGISel.inc"
>>
>> @@ -101,6 +104,22 @@ SDNode *WebAssemblyDAGToDAGISel::Select(
>> return ResNode;
>> }
>>
>> +bool WebAssemblyDAGToDAGISel::SelectInlineAsmMemoryOperand(
>> + const SDValue &Op, unsigned ConstraintID, std::vector<SDValue>
>> &OutOps) {
>> + switch (ConstraintID) {
>> + case InlineAsm::Constraint_i:
>> + case InlineAsm::Constraint_m:
>> + // We just support simple memory operands that just have a single
>> address
>> + // operand and need no special handling.
>> + OutOps.push_back(Op);
>> + return false;
>> + default:
>> + break;
>> + }
>> +
>> + return true;
>> +}
>> +
>> /// This pass converts a legalized DAG into a WebAssembly-specific DAG,
>> ready
>> /// for instruction scheduling.
>> FunctionPass *llvm::createWebAssemblyISelDag(WebAssemblyTargetMachine
>> &TM,
>>
>> Modified: llvm/trunk/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp
>> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp?rev=252997&r1=252996&r2=252997&view=diff
>>
>> ==============================================================================
>> --- llvm/trunk/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp
>> (original)
>> +++ llvm/trunk/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp Thu Nov
>> 12 19:42:29 2015
>> @@ -211,6 +211,23 @@ WebAssemblyTargetLowering::getTargetNode
>> return nullptr;
>> }
>>
>> +std::pair<unsigned, const TargetRegisterClass *>
>> +WebAssemblyTargetLowering::getRegForInlineAsmConstraint(
>> + const TargetRegisterInfo *TRI, StringRef Constraint, MVT VT) const {
>> + // First, see if this is a constraint that directly corresponds to a
>> + // WebAssembly register class.
>> + if (Constraint.size() == 1) {
>> + switch (Constraint[0]) {
>> + case 'r':
>> + return std::make_pair(0U, &WebAssembly::I32RegClass);
>> + default:
>> + break;
>> + }
>> + }
>> +
>> + return TargetLowering::getRegForInlineAsmConstraint(TRI, Constraint,
>> VT);
>> +}
>> +
>>
>> //===----------------------------------------------------------------------===//
>> // WebAssembly Lowering private implementation.
>>
>> //===----------------------------------------------------------------------===//
>>
>> Modified: llvm/trunk/lib/Target/WebAssembly/WebAssemblyISelLowering.h
>> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/WebAssembly/WebAssemblyISelLowering.h?rev=252997&r1=252996&r2=252997&view=diff
>>
>> ==============================================================================
>> --- llvm/trunk/lib/Target/WebAssembly/WebAssemblyISelLowering.h (original)
>> +++ llvm/trunk/lib/Target/WebAssembly/WebAssemblyISelLowering.h Thu Nov
>> 12 19:42:29 2015
>> @@ -49,6 +49,9 @@ private:
>> bool isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const
>> override;
>> MVT getScalarShiftAmountTy(const DataLayout &DL, EVT) const override;
>> const char *getTargetNodeName(unsigned Opcode) const override;
>> + std::pair<unsigned, const TargetRegisterClass *>
>> + getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI,
>> + StringRef Constraint, MVT VT) const
>> override;
>>
>> SDValue LowerCall(CallLoweringInfo &CLI,
>> SmallVectorImpl<SDValue> &InVals) const override;
>>
>> Added: llvm/trunk/test/CodeGen/WebAssembly/inline-asm.ll
>> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/WebAssembly/inline-asm.ll?rev=252997&view=auto
>>
>> ==============================================================================
>> --- llvm/trunk/test/CodeGen/WebAssembly/inline-asm.ll (added)
>> +++ llvm/trunk/test/CodeGen/WebAssembly/inline-asm.ll Thu Nov 12 19:42:29
>> 2015
>> @@ -0,0 +1,53 @@
>> +; RUN: llc < %s -asm-verbose=false | FileCheck %s
>> +
>> +; Test basic inline assembly.
>> +
>> +target datalayout = "e-p:32:32-i64:64-n32:64-S128"
>> +target triple = "wasm32-unknown-unknown"
>> +
>> +; CHECK-LABEL: foo:
>> +; CHECK-NEXT: .param i32{{$}}
>> +; CHECK-NEXT: .result i32{{$}}
>> +; CHECK-NEXT: .local i32, i32{{$}}
>> +; CHECK-NEXT: #APP{{$}}
>> +; CHECK-NEXT: 1 = aaa(0){{$}}
>> +; CHECK-NEXT: #NO_APP{{$}}
>> +; CHECK-NEXT: return (get_local 1){{$}}
>> +define i32 @foo(i32 %r) {
>> +entry:
>> + %0 = tail call i32 asm sideeffect "$0 = aaa($1)", "=r,r"(i32 %r) #0,
>> !srcloc !0
>> + ret i32 %0
>> +}
>> +
>> +; CHECK-LABEL: bar:
>> +; CHECK-NEXT: .param i32{{$}}
>> +; CHECK-NEXT: .param i32{{$}}
>> +; CHECK-NEXT: .local i32, i32{{$}}
>> +; CHECK-NEXT: #APP{{$}}
>> +; CHECK-NEXT: 1 = bbb(0){{$}}
>> +; CHECK-NEXT: #NO_APP{{$}}
>> +; CHECK-NEXT: return{{$}}
>> +define void @bar(i32* %r, i32* %s) {
>> +entry:
>> + tail call void asm sideeffect "$0 = bbb($1)", "=*m,*m"(i32* %s, i32*
>> %r) #0, !srcloc !1
>> + ret void
>> +}
>> +
>> +; CHECK-LABEL: imm:
>> +; CHECK-NEXT: .result i32{{$}}
>> +; CHECK-NEXT: .local i32{{$}}
>> +; CHECK-NEXT: #APP{{$}}
>> +; CHECK-NEXT: 0 = ccc(42){{$}}
>> +; CHECK-NEXT: #NO_APP{{$}}
>> +; CHECK-NEXT: return (get_local 0){{$}}
>> +define i32 @imm() {
>> +entry:
>> + %0 = tail call i32 asm sideeffect "$0 = ccc($1)", "=r,i"(i32 42) #0,
>> !srcloc !2
>> + ret i32 %0
>> +}
>> +
>> +attributes #0 = { nounwind }
>> +
>> +!0 = !{i32 47}
>> +!1 = !{i32 145}
>> +!2 = !{i32 231}
>>
>>
>> _______________________________________________
>> llvm-commits mailing list
>> llvm-commits at lists.llvm.org
>> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits
>>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20151117/94e08147/attachment.html>
More information about the llvm-commits
mailing list