110e730a2SDan Gohman //=- WebAssemblyISelLowering.cpp - WebAssembly DAG Lowering Implementation -==//
210e730a2SDan Gohman //
310e730a2SDan Gohman //                     The LLVM Compiler Infrastructure
410e730a2SDan Gohman //
510e730a2SDan Gohman // This file is distributed under the University of Illinois Open Source
610e730a2SDan Gohman // License. See LICENSE.TXT for details.
710e730a2SDan Gohman //
810e730a2SDan Gohman //===----------------------------------------------------------------------===//
910e730a2SDan Gohman ///
1010e730a2SDan Gohman /// \file
1110e730a2SDan Gohman /// \brief This file implements the WebAssemblyTargetLowering class.
1210e730a2SDan Gohman ///
1310e730a2SDan Gohman //===----------------------------------------------------------------------===//
1410e730a2SDan Gohman 
1510e730a2SDan Gohman #include "WebAssemblyISelLowering.h"
1610e730a2SDan Gohman #include "MCTargetDesc/WebAssemblyMCTargetDesc.h"
1710e730a2SDan Gohman #include "WebAssemblyMachineFunctionInfo.h"
1810e730a2SDan Gohman #include "WebAssemblySubtarget.h"
1910e730a2SDan Gohman #include "WebAssemblyTargetMachine.h"
2010e730a2SDan Gohman #include "WebAssemblyTargetObjectFile.h"
2110e730a2SDan Gohman #include "llvm/CodeGen/Analysis.h"
22af111db8SJF Bastien #include "llvm/CodeGen/CallingConvLower.h"
2310e730a2SDan Gohman #include "llvm/CodeGen/MachineRegisterInfo.h"
2410e730a2SDan Gohman #include "llvm/CodeGen/SelectionDAG.h"
25b9073fb2SJF Bastien #include "llvm/IR/DiagnosticInfo.h"
26b9073fb2SJF Bastien #include "llvm/IR/DiagnosticPrinter.h"
2710e730a2SDan Gohman #include "llvm/IR/Function.h"
2810e730a2SDan Gohman #include "llvm/IR/Intrinsics.h"
2910e730a2SDan Gohman #include "llvm/Support/CommandLine.h"
3010e730a2SDan Gohman #include "llvm/Support/Debug.h"
3110e730a2SDan Gohman #include "llvm/Support/ErrorHandling.h"
3210e730a2SDan Gohman #include "llvm/Support/raw_ostream.h"
3310e730a2SDan Gohman #include "llvm/Target/TargetOptions.h"
34b9073fb2SJF Bastien 
3510e730a2SDan Gohman using namespace llvm;
3610e730a2SDan Gohman 
3710e730a2SDan Gohman #define DEBUG_TYPE "wasm-lower"
3810e730a2SDan Gohman 
39b9073fb2SJF Bastien namespace {
40b9073fb2SJF Bastien // Diagnostic information for unimplemented or unsupported feature reporting.
41b9073fb2SJF Bastien // FIXME copied from BPF and AMDGPU.
42b9073fb2SJF Bastien class DiagnosticInfoUnsupported : public DiagnosticInfo {
43b9073fb2SJF Bastien private:
44b9073fb2SJF Bastien   // Debug location where this diagnostic is triggered.
45b9073fb2SJF Bastien   DebugLoc DLoc;
46b9073fb2SJF Bastien   const Twine &Description;
47b9073fb2SJF Bastien   const Function &Fn;
48b9073fb2SJF Bastien   SDValue Value;
49b9073fb2SJF Bastien 
50b9073fb2SJF Bastien   static int KindID;
51b9073fb2SJF Bastien 
52b9073fb2SJF Bastien   static int getKindID() {
53b9073fb2SJF Bastien     if (KindID == 0)
54b9073fb2SJF Bastien       KindID = llvm::getNextAvailablePluginDiagnosticKind();
55b9073fb2SJF Bastien     return KindID;
56b9073fb2SJF Bastien   }
57b9073fb2SJF Bastien 
58b9073fb2SJF Bastien public:
59b9073fb2SJF Bastien   DiagnosticInfoUnsupported(SDLoc DLoc, const Function &Fn, const Twine &Desc,
60b9073fb2SJF Bastien                             SDValue Value)
61b9073fb2SJF Bastien       : DiagnosticInfo(getKindID(), DS_Error), DLoc(DLoc.getDebugLoc()),
62b9073fb2SJF Bastien         Description(Desc), Fn(Fn), Value(Value) {}
63b9073fb2SJF Bastien 
64b9073fb2SJF Bastien   void print(DiagnosticPrinter &DP) const override {
65b9073fb2SJF Bastien     std::string Str;
66b9073fb2SJF Bastien     raw_string_ostream OS(Str);
67b9073fb2SJF Bastien 
68b9073fb2SJF Bastien     if (DLoc) {
69b9073fb2SJF Bastien       auto DIL = DLoc.get();
70b9073fb2SJF Bastien       StringRef Filename = DIL->getFilename();
71b9073fb2SJF Bastien       unsigned Line = DIL->getLine();
72b9073fb2SJF Bastien       unsigned Column = DIL->getColumn();
73b9073fb2SJF Bastien       OS << Filename << ':' << Line << ':' << Column << ' ';
74b9073fb2SJF Bastien     }
75b9073fb2SJF Bastien 
76b9073fb2SJF Bastien     OS << "in function " << Fn.getName() << ' ' << *Fn.getFunctionType() << '\n'
77b9073fb2SJF Bastien        << Description;
78b9073fb2SJF Bastien     if (Value)
79b9073fb2SJF Bastien       Value->print(OS);
80b9073fb2SJF Bastien     OS << '\n';
81b9073fb2SJF Bastien     OS.flush();
82b9073fb2SJF Bastien     DP << Str;
83b9073fb2SJF Bastien   }
84b9073fb2SJF Bastien 
85b9073fb2SJF Bastien   static bool classof(const DiagnosticInfo *DI) {
86b9073fb2SJF Bastien     return DI->getKind() == getKindID();
87b9073fb2SJF Bastien   }
88b9073fb2SJF Bastien };
89b9073fb2SJF Bastien 
90b9073fb2SJF Bastien int DiagnosticInfoUnsupported::KindID = 0;
91b9073fb2SJF Bastien } // end anonymous namespace
92b9073fb2SJF Bastien 
9310e730a2SDan Gohman WebAssemblyTargetLowering::WebAssemblyTargetLowering(
9410e730a2SDan Gohman     const TargetMachine &TM, const WebAssemblySubtarget &STI)
95bfaf7e15SDan Gohman     : TargetLowering(TM), Subtarget(&STI) {
96af111db8SJF Bastien   auto MVTPtr = Subtarget->hasAddr64() ? MVT::i64 : MVT::i32;
97af111db8SJF Bastien 
9871d29aceSJF Bastien   // Booleans always contain 0 or 1.
9971d29aceSJF Bastien   setBooleanContents(ZeroOrOneBooleanContent);
100bfaf7e15SDan Gohman   // WebAssembly does not produce floating-point exceptions on normal floating
101bfaf7e15SDan Gohman   // point operations.
102bfaf7e15SDan Gohman   setHasFloatingPointExceptions(false);
103489abd70SDan Gohman   // We don't know the microarchitecture here, so just reduce register pressure.
104489abd70SDan Gohman   setSchedulingPreference(Sched::RegPressure);
105b9073fb2SJF Bastien   // Tell ISel that we have a stack pointer.
106b9073fb2SJF Bastien   setStackPointerRegisterToSaveRestore(
107b9073fb2SJF Bastien       Subtarget->hasAddr64() ? WebAssembly::SP64 : WebAssembly::SP32);
108b9073fb2SJF Bastien   // Set up the register classes.
109b9073fb2SJF Bastien   addRegisterClass(MVT::i32, &WebAssembly::Int32RegClass);
110b9073fb2SJF Bastien   addRegisterClass(MVT::i64, &WebAssembly::Int64RegClass);
111b9073fb2SJF Bastien   addRegisterClass(MVT::f32, &WebAssembly::Float32RegClass);
112b9073fb2SJF Bastien   addRegisterClass(MVT::f64, &WebAssembly::Float64RegClass);
113b9073fb2SJF Bastien   // Compute derived properties from the register classes.
114b9073fb2SJF Bastien   computeRegisterProperties(Subtarget->getRegisterInfo());
115b9073fb2SJF Bastien 
116af111db8SJF Bastien   setOperationAction(ISD::GlobalAddress, MVTPtr, Custom);
117af111db8SJF Bastien 
118da06bce8SJF Bastien   for (auto T : {MVT::f32, MVT::f64}) {
119da06bce8SJF Bastien     // Don't expand the floating-point types to constant pools.
120da06bce8SJF Bastien     setOperationAction(ISD::ConstantFP, T, Legal);
121da06bce8SJF Bastien     // Expand floating-point comparisons.
122da06bce8SJF Bastien     for (auto CC : {ISD::SETO, ISD::SETUO, ISD::SETUEQ, ISD::SETONE,
123da06bce8SJF Bastien                     ISD::SETULT, ISD::SETULE, ISD::SETUGT, ISD::SETUGE})
124da06bce8SJF Bastien       setCondCodeAction(CC, T, Expand);
12532907a6bSDan Gohman     // Expand floating-point library function operators.
126896e53faSDan Gohman     for (auto Op : {ISD::FSIN, ISD::FCOS, ISD::FSINCOS, ISD::FPOWI, ISD::FPOW})
12732907a6bSDan Gohman       setOperationAction(Op, T, Expand);
128896e53faSDan Gohman     // Note supported floating-point library function operators that otherwise
129896e53faSDan Gohman     // default to expand.
130896e53faSDan Gohman     for (auto Op : {ISD::FCEIL, ISD::FFLOOR, ISD::FTRUNC, ISD::FNEARBYINT,
131896e53faSDan Gohman                     ISD::FRINT})
132896e53faSDan Gohman       setOperationAction(Op, T, Legal);
133da06bce8SJF Bastien   }
13432907a6bSDan Gohman 
13532907a6bSDan Gohman   for (auto T : {MVT::i32, MVT::i64}) {
13632907a6bSDan Gohman     // Expand unavailable integer operations.
13732907a6bSDan Gohman     for (auto Op : {ISD::BSWAP, ISD::ROTL, ISD::ROTR,
13832907a6bSDan Gohman                     ISD::SMUL_LOHI, ISD::UMUL_LOHI,
13932907a6bSDan Gohman                     ISD::MULHS, ISD::MULHU, ISD::SDIVREM, ISD::UDIVREM,
14032907a6bSDan Gohman                     ISD::SHL_PARTS, ISD::SRA_PARTS, ISD::SRL_PARTS,
14132907a6bSDan Gohman                     ISD::ADDC, ISD::ADDE, ISD::SUBC, ISD::SUBE}) {
14232907a6bSDan Gohman       setOperationAction(Op, T, Expand);
14332907a6bSDan Gohman     }
14432907a6bSDan Gohman   }
14532907a6bSDan Gohman 
14632907a6bSDan Gohman   // As a special case, these operators use the type to mean the type to
14732907a6bSDan Gohman   // sign-extend from.
14832907a6bSDan Gohman   for (auto T : {MVT::i1, MVT::i8, MVT::i16})
14932907a6bSDan Gohman     setOperationAction(ISD::SIGN_EXTEND_INREG, T, Expand);
15032907a6bSDan Gohman 
15132907a6bSDan Gohman   // Dynamic stack allocation: use the default expansion.
15232907a6bSDan Gohman   setOperationAction(ISD::STACKSAVE, MVT::Other, Expand);
15332907a6bSDan Gohman   setOperationAction(ISD::STACKRESTORE, MVT::Other, Expand);
1542683a553SDan Gohman   setOperationAction(ISD::DYNAMIC_STACKALLOC, MVTPtr, Expand);
15573ff6afaSJF Bastien 
15673ff6afaSJF Bastien   // WebAssembly doesn't have:
15773ff6afaSJF Bastien   //  - Floating-point extending loads.
15873ff6afaSJF Bastien   //  - Floating-point truncating stores.
15973ff6afaSJF Bastien   //  - i1 extending loads.
16073ff6afaSJF Bastien   setLoadExtAction(ISD::EXTLOAD, MVT::f32, MVT::f64, Expand);
16173ff6afaSJF Bastien   setTruncStoreAction(MVT::f64, MVT::f32, Expand);
16273ff6afaSJF Bastien   for (auto T : MVT::integer_valuetypes())
16373ff6afaSJF Bastien     for (auto Ext : {ISD::EXTLOAD, ISD::ZEXTLOAD, ISD::SEXTLOAD})
16473ff6afaSJF Bastien       setLoadExtAction(Ext, T, MVT::i1, Promote);
165bfaf7e15SDan Gohman }
16610e730a2SDan Gohman 
1677b63484bSDan Gohman FastISel *WebAssemblyTargetLowering::createFastISel(
1687b63484bSDan Gohman     FunctionLoweringInfo &FuncInfo, const TargetLibraryInfo *LibInfo) const {
1697b63484bSDan Gohman   return WebAssembly::createFastISel(FuncInfo, LibInfo);
1707b63484bSDan Gohman }
1717b63484bSDan Gohman 
172af111db8SJF Bastien bool WebAssemblyTargetLowering::isOffsetFoldingLegal(
173af111db8SJF Bastien     const GlobalAddressSDNode *GA) const {
174af111db8SJF Bastien   // The WebAssembly target doesn't support folding offsets into global
175af111db8SJF Bastien   // addresses.
176af111db8SJF Bastien   return false;
177af111db8SJF Bastien }
178af111db8SJF Bastien 
179fda53373SJF Bastien MVT WebAssemblyTargetLowering::getScalarShiftAmountTy(const DataLayout &DL,
180fda53373SJF Bastien                                                       EVT VT) const {
181fda53373SJF Bastien   return VT.getSimpleVT();
182fda53373SJF Bastien }
183fda53373SJF Bastien 
184480c8408SJF Bastien const char *
185480c8408SJF Bastien WebAssemblyTargetLowering::getTargetNodeName(unsigned Opcode) const {
186480c8408SJF Bastien   switch (static_cast<WebAssemblyISD::NodeType>(Opcode)) {
187af111db8SJF Bastien   case WebAssemblyISD::FIRST_NUMBER:
188af111db8SJF Bastien     break;
189af111db8SJF Bastien #define HANDLE_NODETYPE(NODE)                                                  \
190af111db8SJF Bastien   case WebAssemblyISD::NODE:                                                   \
191af111db8SJF Bastien     return "WebAssemblyISD::" #NODE;
192af111db8SJF Bastien #include "WebAssemblyISD.def"
193af111db8SJF Bastien #undef HANDLE_NODETYPE
194480c8408SJF Bastien   }
195480c8408SJF Bastien   return nullptr;
196480c8408SJF Bastien }
197480c8408SJF Bastien 
19810e730a2SDan Gohman //===----------------------------------------------------------------------===//
19910e730a2SDan Gohman // WebAssembly Lowering private implementation.
20010e730a2SDan Gohman //===----------------------------------------------------------------------===//
20110e730a2SDan Gohman 
20210e730a2SDan Gohman //===----------------------------------------------------------------------===//
20310e730a2SDan Gohman // Lowering Code
20410e730a2SDan Gohman //===----------------------------------------------------------------------===//
20510e730a2SDan Gohman 
206b9073fb2SJF Bastien static void fail(SDLoc DL, SelectionDAG &DAG, const char *msg) {
207b9073fb2SJF Bastien   MachineFunction &MF = DAG.getMachineFunction();
208b9073fb2SJF Bastien   DAG.getContext()->diagnose(
209b9073fb2SJF Bastien       DiagnosticInfoUnsupported(DL, *MF.getFunction(), msg, SDValue()));
210b9073fb2SJF Bastien }
211b9073fb2SJF Bastien 
212d8a9d66dSJF Bastien SDValue
213d8a9d66dSJF Bastien WebAssemblyTargetLowering::LowerCall(CallLoweringInfo &CLI,
214d8a9d66dSJF Bastien                                      SmallVectorImpl<SDValue> &InVals) const {
215d8a9d66dSJF Bastien   SelectionDAG &DAG = CLI.DAG;
216d8a9d66dSJF Bastien   SDLoc DL = CLI.DL;
217d8a9d66dSJF Bastien   SDValue Chain = CLI.Chain;
218d8a9d66dSJF Bastien   SDValue Callee = CLI.Callee;
219d8a9d66dSJF Bastien   MachineFunction &MF = DAG.getMachineFunction();
220d8a9d66dSJF Bastien 
221d8a9d66dSJF Bastien   CallingConv::ID CallConv = CLI.CallConv;
222d8a9d66dSJF Bastien   if (CallConv != CallingConv::C)
223d8a9d66dSJF Bastien     fail(DL, DAG, "WebAssembly doesn't support non-C calling conventions");
224d8a9d66dSJF Bastien   if (CLI.IsTailCall || MF.getTarget().Options.GuaranteedTailCallOpt)
225d8a9d66dSJF Bastien     fail(DL, DAG, "WebAssembly doesn't support tail call yet");
226d8a9d66dSJF Bastien   if (CLI.IsPatchPoint)
227d8a9d66dSJF Bastien     fail(DL, DAG, "WebAssembly doesn't support patch point yet");
228d8a9d66dSJF Bastien 
229d8a9d66dSJF Bastien   SmallVectorImpl<ISD::OutputArg> &Outs = CLI.Outs;
230d8a9d66dSJF Bastien   SmallVectorImpl<SDValue> &OutVals = CLI.OutVals;
231e590b33bSDan Gohman 
232d8a9d66dSJF Bastien   bool IsStructRet = (Outs.empty()) ? false : Outs[0].Flags.isSRet();
233d8a9d66dSJF Bastien   if (IsStructRet)
234d8a9d66dSJF Bastien     fail(DL, DAG, "WebAssembly doesn't support struct return yet");
235d8a9d66dSJF Bastien 
236d8a9d66dSJF Bastien   SmallVectorImpl<ISD::InputArg> &Ins = CLI.Ins;
237e590b33bSDan Gohman   if (Ins.size() > 1)
238e590b33bSDan Gohman     fail(DL, DAG, "WebAssembly doesn't support more than 1 returned value yet");
239e590b33bSDan Gohman 
240d8a9d66dSJF Bastien   bool IsVarArg = CLI.IsVarArg;
241d8a9d66dSJF Bastien   if (IsVarArg)
242d8a9d66dSJF Bastien     fail(DL, DAG, "WebAssembly doesn't support varargs yet");
243e590b33bSDan Gohman 
244d8a9d66dSJF Bastien   // Analyze operands of the call, assigning locations to each operand.
245d8a9d66dSJF Bastien   SmallVector<CCValAssign, 16> ArgLocs;
246d8a9d66dSJF Bastien   CCState CCInfo(CallConv, IsVarArg, MF, ArgLocs, *DAG.getContext());
247d8a9d66dSJF Bastien   unsigned NumBytes = CCInfo.getNextStackOffset();
248d8a9d66dSJF Bastien 
249d8a9d66dSJF Bastien   auto PtrVT = getPointerTy(MF.getDataLayout());
250af111db8SJF Bastien   auto Zero = DAG.getConstant(0, DL, PtrVT, true);
251af111db8SJF Bastien   auto NB = DAG.getConstant(NumBytes, DL, PtrVT, true);
252af111db8SJF Bastien   Chain = DAG.getCALLSEQ_START(Chain, NB, DL);
253d8a9d66dSJF Bastien 
254d8a9d66dSJF Bastien   SmallVector<SDValue, 16> Ops;
255d8a9d66dSJF Bastien   Ops.push_back(Chain);
256af111db8SJF Bastien   Ops.push_back(Callee);
257af111db8SJF Bastien   Ops.append(OutVals.begin(), OutVals.end());
258d8a9d66dSJF Bastien 
259d8a9d66dSJF Bastien   SmallVector<EVT, 8> Tys;
260af111db8SJF Bastien   for (const auto &In : Ins)
261d8a9d66dSJF Bastien     Tys.push_back(In.VT);
262d8a9d66dSJF Bastien   Tys.push_back(MVT::Other);
263af111db8SJF Bastien   SDVTList TyList = DAG.getVTList(Tys);
264*f71abef7SDan Gohman   SDValue Res =
265*f71abef7SDan Gohman       DAG.getNode(Ins.empty() ? WebAssemblyISD::CALL0 : WebAssemblyISD::CALL1,
266*f71abef7SDan Gohman                   DL, TyList, Ops);
267af111db8SJF Bastien   if (Ins.empty()) {
268af111db8SJF Bastien     Chain = Res;
269af111db8SJF Bastien   } else {
270d8a9d66dSJF Bastien     InVals.push_back(Res);
271d8a9d66dSJF Bastien     Chain = Res.getValue(1);
272af111db8SJF Bastien   }
273d8a9d66dSJF Bastien 
274d8a9d66dSJF Bastien   // FIXME: handle CLI.RetSExt and CLI.RetZExt?
275d8a9d66dSJF Bastien 
276af111db8SJF Bastien   Chain = DAG.getCALLSEQ_END(Chain, NB, Zero, SDValue(), DL);
277d8a9d66dSJF Bastien 
278d8a9d66dSJF Bastien   return Chain;
279d8a9d66dSJF Bastien }
280d8a9d66dSJF Bastien 
281b9073fb2SJF Bastien bool WebAssemblyTargetLowering::CanLowerReturn(
282b9073fb2SJF Bastien     CallingConv::ID CallConv, MachineFunction &MF, bool IsVarArg,
283b9073fb2SJF Bastien     const SmallVectorImpl<ISD::OutputArg> &Outs, LLVMContext &Context) const {
284b9073fb2SJF Bastien   // WebAssembly can't currently handle returning tuples.
285b9073fb2SJF Bastien   return Outs.size() <= 1;
286b9073fb2SJF Bastien }
287b9073fb2SJF Bastien 
288b9073fb2SJF Bastien SDValue WebAssemblyTargetLowering::LowerReturn(
289b9073fb2SJF Bastien     SDValue Chain, CallingConv::ID CallConv, bool IsVarArg,
290b9073fb2SJF Bastien     const SmallVectorImpl<ISD::OutputArg> &Outs,
291b9073fb2SJF Bastien     const SmallVectorImpl<SDValue> &OutVals, SDLoc DL,
292b9073fb2SJF Bastien     SelectionDAG &DAG) const {
293b9073fb2SJF Bastien 
294b9073fb2SJF Bastien   assert(Outs.size() <= 1 && "WebAssembly can only return up to one value");
295b9073fb2SJF Bastien   if (CallConv != CallingConv::C)
296b9073fb2SJF Bastien     fail(DL, DAG, "WebAssembly doesn't support non-C calling conventions");
297600aee98SJF Bastien   if (IsVarArg)
298600aee98SJF Bastien     fail(DL, DAG, "WebAssembly doesn't support varargs yet");
299b9073fb2SJF Bastien 
300600aee98SJF Bastien   SmallVector<SDValue, 4> RetOps(1, Chain);
301600aee98SJF Bastien   RetOps.append(OutVals.begin(), OutVals.end());
3024a2d5604SJF Bastien   Chain = DAG.getNode(WebAssemblyISD::RETURN, DL, MVT::Other, RetOps);
303b9073fb2SJF Bastien 
304b9073fb2SJF Bastien   return Chain;
305b9073fb2SJF Bastien }
306b9073fb2SJF Bastien 
307b9073fb2SJF Bastien SDValue WebAssemblyTargetLowering::LowerFormalArguments(
308b9073fb2SJF Bastien     SDValue Chain, CallingConv::ID CallConv, bool IsVarArg,
309b9073fb2SJF Bastien     const SmallVectorImpl<ISD::InputArg> &Ins, SDLoc DL, SelectionDAG &DAG,
310b9073fb2SJF Bastien     SmallVectorImpl<SDValue> &InVals) const {
311b9073fb2SJF Bastien   MachineFunction &MF = DAG.getMachineFunction();
312b9073fb2SJF Bastien 
313b9073fb2SJF Bastien   if (CallConv != CallingConv::C)
314b9073fb2SJF Bastien     fail(DL, DAG, "WebAssembly doesn't support non-C calling conventions");
315b9073fb2SJF Bastien   if (IsVarArg)
316b9073fb2SJF Bastien     fail(DL, DAG, "WebAssembly doesn't support varargs yet");
317b9073fb2SJF Bastien   if (MF.getFunction()->hasStructRetAttr())
318b9073fb2SJF Bastien     fail(DL, DAG, "WebAssembly doesn't support struct return yet");
319b9073fb2SJF Bastien 
320600aee98SJF Bastien   unsigned ArgNo = 0;
321600aee98SJF Bastien   for (const ISD::InputArg &In : Ins) {
322600aee98SJF Bastien     if (In.Flags.isZExt())
323600aee98SJF Bastien       fail(DL, DAG, "WebAssembly hasn't implemented zext arguments");
324600aee98SJF Bastien     if (In.Flags.isSExt())
325600aee98SJF Bastien       fail(DL, DAG, "WebAssembly hasn't implemented sext arguments");
326600aee98SJF Bastien     if (In.Flags.isInReg())
327600aee98SJF Bastien       fail(DL, DAG, "WebAssembly hasn't implemented inreg arguments");
328600aee98SJF Bastien     if (In.Flags.isSRet())
329600aee98SJF Bastien       fail(DL, DAG, "WebAssembly hasn't implemented sret arguments");
330600aee98SJF Bastien     if (In.Flags.isByVal())
331600aee98SJF Bastien       fail(DL, DAG, "WebAssembly hasn't implemented byval arguments");
332600aee98SJF Bastien     if (In.Flags.isInAlloca())
333600aee98SJF Bastien       fail(DL, DAG, "WebAssembly hasn't implemented inalloca arguments");
334600aee98SJF Bastien     if (In.Flags.isNest())
335600aee98SJF Bastien       fail(DL, DAG, "WebAssembly hasn't implemented nest arguments");
336600aee98SJF Bastien     if (In.Flags.isReturned())
337600aee98SJF Bastien       fail(DL, DAG, "WebAssembly hasn't implemented returned arguments");
338600aee98SJF Bastien     if (In.Flags.isInConsecutiveRegs())
339600aee98SJF Bastien       fail(DL, DAG, "WebAssembly hasn't implemented cons regs arguments");
340600aee98SJF Bastien     if (In.Flags.isInConsecutiveRegsLast())
341600aee98SJF Bastien       fail(DL, DAG, "WebAssembly hasn't implemented cons regs last arguments");
342600aee98SJF Bastien     if (In.Flags.isSplit())
343600aee98SJF Bastien       fail(DL, DAG, "WebAssembly hasn't implemented split arguments");
344600aee98SJF Bastien     // FIXME Do something with In.getOrigAlign()?
345d7fcc6f9SJF Bastien     InVals.push_back(
346d7fcc6f9SJF Bastien         In.Used
347d7fcc6f9SJF Bastien             ? DAG.getNode(WebAssemblyISD::ARGUMENT, DL, In.VT,
348d7fcc6f9SJF Bastien                           DAG.getTargetConstant(ArgNo, DL, MVT::i32))
349d7fcc6f9SJF Bastien             : DAG.getNode(ISD::UNDEF, DL, In.VT));
350d7fcc6f9SJF Bastien     ++ArgNo;
351600aee98SJF Bastien   }
352b9073fb2SJF Bastien 
353b9073fb2SJF Bastien   return Chain;
354b9073fb2SJF Bastien }
355b9073fb2SJF Bastien 
35610e730a2SDan Gohman //===----------------------------------------------------------------------===//
357af111db8SJF Bastien //  Custom lowering hooks.
35810e730a2SDan Gohman //===----------------------------------------------------------------------===//
35910e730a2SDan Gohman 
360af111db8SJF Bastien SDValue WebAssemblyTargetLowering::LowerOperation(SDValue Op,
361af111db8SJF Bastien                                                   SelectionDAG &DAG) const {
362af111db8SJF Bastien   switch (Op.getOpcode()) {
363af111db8SJF Bastien   default:
364af111db8SJF Bastien     llvm_unreachable("unimplemented operation lowering");
365af111db8SJF Bastien     return SDValue();
366af111db8SJF Bastien   case ISD::GlobalAddress:
367af111db8SJF Bastien     return LowerGlobalAddress(Op, DAG);
368af111db8SJF Bastien   }
369af111db8SJF Bastien }
370af111db8SJF Bastien 
371af111db8SJF Bastien SDValue WebAssemblyTargetLowering::LowerGlobalAddress(SDValue Op,
372af111db8SJF Bastien                                                       SelectionDAG &DAG) const {
373af111db8SJF Bastien   SDLoc DL(Op);
374af111db8SJF Bastien   const auto *GA = cast<GlobalAddressSDNode>(Op);
375af111db8SJF Bastien   EVT VT = Op.getValueType();
376af111db8SJF Bastien   assert(GA->getOffset() == 0 &&
377af111db8SJF Bastien          "offsets on global addresses are forbidden by isOffsetFoldingLegal");
378af111db8SJF Bastien   assert(GA->getTargetFlags() == 0 && "WebAssembly doesn't set target flags");
379af111db8SJF Bastien   if (GA->getAddressSpace() != 0)
380af111db8SJF Bastien     fail(DL, DAG, "WebAssembly only expects the 0 address space");
381af111db8SJF Bastien   return DAG.getNode(WebAssemblyISD::Wrapper, DL, VT,
382af111db8SJF Bastien                      DAG.getTargetGlobalAddress(GA->getGlobal(), DL, VT));
383af111db8SJF Bastien }
384af111db8SJF Bastien 
38510e730a2SDan Gohman //===----------------------------------------------------------------------===//
38610e730a2SDan Gohman //                          WebAssembly Optimization Hooks
38710e730a2SDan Gohman //===----------------------------------------------------------------------===//
38810e730a2SDan Gohman 
38910e730a2SDan Gohman MCSection *WebAssemblyTargetObjectFile::SelectSectionForGlobal(
39010e730a2SDan Gohman     const GlobalValue *GV, SectionKind Kind, Mangler &Mang,
39110e730a2SDan Gohman     const TargetMachine &TM) const {
39210e730a2SDan Gohman   return getDataSection();
39310e730a2SDan Gohman }
394