diff options
author | JF Bastien <jfb@google.com> | 2015-08-24 21:59:51 +0000 |
---|---|---|
committer | JF Bastien <jfb@google.com> | 2015-08-24 21:59:51 +0000 |
commit | d8a9d66d50a8c86721925eec6a1ab10a6c8d19be (patch) | |
tree | fc071951ef0fa1f7db8956d12c8036cad95a888a /llvm/lib/Target/WebAssembly | |
parent | d8879c85f68250baa6f2ebc463259201782e8460 (diff) | |
download | bcm5719-llvm-d8a9d66d50a8c86721925eec6a1ab10a6c8d19be.tar.gz bcm5719-llvm-d8a9d66d50a8c86721925eec6a1ab10a6c8d19be.zip |
call
llvm-svn: 245882
Diffstat (limited to 'llvm/lib/Target/WebAssembly')
7 files changed, 144 insertions, 8 deletions
diff --git a/llvm/lib/Target/WebAssembly/InstPrinter/WebAssemblyInstPrinter.cpp b/llvm/lib/Target/WebAssembly/InstPrinter/WebAssemblyInstPrinter.cpp index 0c5792c6b51..cbd2f7dc748 100644 --- a/llvm/lib/Target/WebAssembly/InstPrinter/WebAssemblyInstPrinter.cpp +++ b/llvm/lib/Target/WebAssembly/InstPrinter/WebAssemblyInstPrinter.cpp @@ -44,3 +44,16 @@ void WebAssemblyInstPrinter::printInst(const MCInst *MI, raw_ostream &OS, printInstruction(MI, OS); printAnnotation(OS, Annot); } + +void WebAssemblyInstPrinter::printOperand(const MCInst *MI, unsigned OpNo, + raw_ostream &O) { + const MCOperand &Op = MI->getOperand(OpNo); + if (Op.isReg()) + O << getRegisterName(Op.getReg()); + else if (Op.isImm()) + O << '#' << Op.getImm(); + else { + assert(Op.isExpr() && "unknown operand kind in printOperand"); + Op.getExpr()->print(O, &MAI); + } +} diff --git a/llvm/lib/Target/WebAssembly/InstPrinter/WebAssemblyInstPrinter.h b/llvm/lib/Target/WebAssembly/InstPrinter/WebAssemblyInstPrinter.h index 4c54a525577..80fe29d56f7 100644 --- a/llvm/lib/Target/WebAssembly/InstPrinter/WebAssemblyInstPrinter.h +++ b/llvm/lib/Target/WebAssembly/InstPrinter/WebAssemblyInstPrinter.h @@ -32,6 +32,9 @@ public: void printInst(const MCInst *MI, raw_ostream &OS, StringRef Annot, const MCSubtargetInfo &STI) override; + // Used by tblegen code. + void printOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O); + // Autogenerated by tblgen. void printInstruction(const MCInst *MI, raw_ostream &O); static const char *getRegisterName(unsigned RegNo); diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyISD.def b/llvm/lib/Target/WebAssembly/WebAssemblyISD.def new file mode 100644 index 00000000000..3b5d82eed9d --- /dev/null +++ b/llvm/lib/Target/WebAssembly/WebAssemblyISD.def @@ -0,0 +1,19 @@ +//- WebAssemblyISD.def - WebAssembly ISD ---------------------------*- C++ -*-// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// \brief This file describes the various WebAssembly ISD node types. +/// +//===----------------------------------------------------------------------===// + +// NOTE: NO INCLUDE GUARD DESIRED! + +HANDLE_NODETYPE(CALL) +HANDLE_NODETYPE(RETURN) +HANDLE_NODETYPE(ARGUMENT) diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp index dfeec770d5a..d9efc190b5b 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp +++ b/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp @@ -19,6 +19,7 @@ #include "WebAssemblyTargetMachine.h" #include "WebAssemblyTargetObjectFile.h" #include "llvm/CodeGen/Analysis.h" +#include "llvm/CodeGen/CallingConvLower.h" #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/SelectionDAG.h" #include "llvm/IR/DiagnosticInfo.h" @@ -164,9 +165,13 @@ MVT WebAssemblyTargetLowering::getScalarShiftAmountTy(const DataLayout &DL, const char * WebAssemblyTargetLowering::getTargetNodeName(unsigned Opcode) const { switch (static_cast<WebAssemblyISD::NodeType>(Opcode)) { - case WebAssemblyISD::FIRST_NUMBER: break; - case WebAssemblyISD::RETURN: return "WebAssemblyISD::RETURN"; - case WebAssemblyISD::ARGUMENT: return "WebAssemblyISD::ARGUMENT"; + case WebAssemblyISD::FIRST_NUMBER: + break; +#define HANDLE_NODETYPE(NODE) \ + case WebAssemblyISD::NODE: \ + return "WebAssemblyISD::" #NODE; +#include "WebAssemblyISD.def" +#undef HANDLE_NODETYPE } return nullptr; } @@ -185,6 +190,68 @@ static void fail(SDLoc DL, SelectionDAG &DAG, const char *msg) { DiagnosticInfoUnsupported(DL, *MF.getFunction(), msg, SDValue())); } +SDValue +WebAssemblyTargetLowering::LowerCall(CallLoweringInfo &CLI, + SmallVectorImpl<SDValue> &InVals) const { + SelectionDAG &DAG = CLI.DAG; + SDLoc DL = CLI.DL; + SDValue Chain = CLI.Chain; + SDValue Callee = CLI.Callee; + MachineFunction &MF = DAG.getMachineFunction(); + + CallingConv::ID CallConv = CLI.CallConv; + if (CallConv != CallingConv::C) + fail(DL, DAG, "WebAssembly doesn't support non-C calling conventions"); + if (CLI.IsTailCall || MF.getTarget().Options.GuaranteedTailCallOpt) + fail(DL, DAG, "WebAssembly doesn't support tail call yet"); + if (CLI.IsPatchPoint) + fail(DL, DAG, "WebAssembly doesn't support patch point yet"); + + SmallVectorImpl<ISD::OutputArg> &Outs = CLI.Outs; + SmallVectorImpl<SDValue> &OutVals = CLI.OutVals; + Type *retTy = CLI.RetTy; + bool IsStructRet = (Outs.empty()) ? false : Outs[0].Flags.isSRet(); + if (IsStructRet) + fail(DL, DAG, "WebAssembly doesn't support struct return yet"); + if (Outs.size() > 1) + fail(DL, DAG, "WebAssembly doesn't support more than 1 returned value yet"); + + SmallVectorImpl<ISD::InputArg> &Ins = CLI.Ins; + ArgListTy &Args = CLI.getArgs(); + bool IsVarArg = CLI.IsVarArg; + if (IsVarArg) + fail(DL, DAG, "WebAssembly doesn't support varargs yet"); + // Analyze operands of the call, assigning locations to each operand. + SmallVector<CCValAssign, 16> ArgLocs; + CCState CCInfo(CallConv, IsVarArg, MF, ArgLocs, *DAG.getContext()); + unsigned NumBytes = CCInfo.getNextStackOffset(); + + auto PtrVT = getPointerTy(MF.getDataLayout()); + auto Zero = DAG.getConstant(0, CLI.DL, PtrVT, true); + auto NB = DAG.getConstant(NumBytes, CLI.DL, PtrVT, true); + Chain = DAG.getCALLSEQ_START(Chain, NB, CLI.DL); + + SmallVector<SDValue, 16> Ops; + Ops.push_back(Chain); + Ops.push_back(CLI.Callee); + Ops.append(CLI.OutVals.begin(), CLI.OutVals.end()); + + SmallVector<EVT, 8> Tys; + for (const auto &In : CLI.Ins) + Tys.push_back(In.VT); + Tys.push_back(MVT::Other); + SDVTList TyList = CLI.DAG.getVTList(Tys); + SDValue Res = CLI.DAG.getNode(WebAssemblyISD::CALL, CLI.DL, TyList, Ops); + InVals.push_back(Res); + Chain = Res.getValue(1); + + // FIXME: handle CLI.RetSExt and CLI.RetZExt? + + Chain = CLI.DAG.getCALLSEQ_END(Chain, NB, Zero, SDValue(), CLI.DL); + + return Chain; +} + bool WebAssemblyTargetLowering::CanLowerReturn( CallingConv::ID CallConv, MachineFunction &MF, bool IsVarArg, const SmallVectorImpl<ISD::OutputArg> &Outs, LLVMContext &Context) const { diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.h b/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.h index ea845cd4031..d82bfa61555 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.h +++ b/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.h @@ -24,9 +24,9 @@ namespace WebAssemblyISD { enum NodeType : unsigned { FIRST_NUMBER = ISD::BUILTIN_OP_END, - RETURN, - ARGUMENT, - +#define HANDLE_NODETYPE(NODE) NODE, +#include "WebAssemblyISD.def" +#undef HANDLE_NODETYPE // add memory opcodes starting at ISD::FIRST_TARGET_MEMORY_OPCODE here... }; @@ -52,6 +52,9 @@ private: const char *getTargetNodeName(unsigned Opcode) const override; + SDValue LowerCall(CallLoweringInfo &CLI, + SmallVectorImpl<SDValue> &InVals) const override; + bool CanLowerReturn(CallingConv::ID CallConv, MachineFunction &MF, bool isVarArg, const SmallVectorImpl<ISD::OutputArg> &Outs, diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyInstrCall.td b/llvm/lib/Target/WebAssembly/WebAssemblyInstrCall.td index 6b5b6cd5417..3b9c015fb18 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyInstrCall.td +++ b/llvm/lib/Target/WebAssembly/WebAssemblyInstrCall.td @@ -12,6 +12,29 @@ /// //===----------------------------------------------------------------------===// +// The call sequence start/end LLVM-isms isn't useful to WebAssembly since it's +// a virtual ISA. + +// FIXME make noop? +//def : Pat<(WebAssemblycallseq_start timm), (i32 (IMPLICIT_DEF))>; +//def : Pat<(WebAssemblycallseq_end timm, timm), (i32 (IMPLICIT_DEF))>; + +def SDT_WebAssemblyCallSeqStart : SDCallSeqStart<[SDTCisVT<0, iPTR>]>; +def SDT_WebAssemblyCallSeqEnd : + SDCallSeqEnd<[SDTCisVT<0, iPTR>, SDTCisVT<1, iPTR>]>; +def WebAssemblycallseq_start : + SDNode<"ISD::CALLSEQ_START", SDT_WebAssemblyCallSeqStart, + [SDNPHasChain, SDNPOutGlue]>; +def WebAssemblycallseq_end : + SDNode<"ISD::CALLSEQ_END", SDT_WebAssemblyCallSeqEnd, + [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue]>; +def : Pseudo<(outs), (ins i64imm:$amt), + [(WebAssemblycallseq_start timm:$amt)], + "#ADJCALLSTACKDOWN $amt">; +def : Pseudo<(outs), (ins i64imm:$amt1, i64imm:$amt2), + [(WebAssemblycallseq_end timm:$amt1, timm:$amt2)], + "#ADJCALLSTACKUP $amt1 $amt2">; + /* * TODO(jfb): Add the following. * diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyInstrFormats.td b/llvm/lib/Target/WebAssembly/WebAssemblyInstrFormats.td index f4d16d39e64..9228be7dea3 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyInstrFormats.td +++ b/llvm/lib/Target/WebAssembly/WebAssemblyInstrFormats.td @@ -12,7 +12,7 @@ /// //===----------------------------------------------------------------------===// -// WebAssembly Instruction Format +// WebAssembly Instruction Format. class WebAssemblyInst<string cstr> : Instruction { field bits<0> Inst; // Instruction encoding. let Namespace = "WebAssembly"; @@ -20,7 +20,7 @@ class WebAssemblyInst<string cstr> : Instruction { let Constraints = cstr; } -// Normal instructions +// Normal instructions. class I<dag oops, dag iops, list<dag> pattern, string cstr = ""> : WebAssemblyInst<cstr> { dag OutOperandList = oops; @@ -28,6 +28,14 @@ class I<dag oops, dag iops, list<dag> pattern, string cstr = ""> let Pattern = pattern; } +// Pseudo instructions. +class Pseudo<dag oops, dag iops, list<dag> pattern, string asmstr, + string cstr = ""> + : I<oops, iops, pattern, cstr> { + let isPseudo = 1; + let AsmString = asmstr; +} + // Unary and binary instructions, for the local types that WebAssembly supports. multiclass UnaryInt<SDNode node> { def _I32 : I<(outs Int32:$dst), (ins Int32:$src), |