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"
2210e730a2SDan Gohman #include "llvm/CodeGen/MachineRegisterInfo.h"
2310e730a2SDan Gohman #include "llvm/CodeGen/SelectionDAG.h"
24b9073fb2SJF Bastien #include "llvm/IR/DiagnosticInfo.h"
25b9073fb2SJF Bastien #include "llvm/IR/DiagnosticPrinter.h"
2610e730a2SDan Gohman #include "llvm/IR/Function.h"
2710e730a2SDan Gohman #include "llvm/IR/Intrinsics.h"
2810e730a2SDan Gohman #include "llvm/Support/CommandLine.h"
2910e730a2SDan Gohman #include "llvm/Support/Debug.h"
3010e730a2SDan Gohman #include "llvm/Support/ErrorHandling.h"
3110e730a2SDan Gohman #include "llvm/Support/raw_ostream.h"
3210e730a2SDan Gohman #include "llvm/Target/TargetOptions.h"
33b9073fb2SJF Bastien 
3410e730a2SDan Gohman using namespace llvm;
3510e730a2SDan Gohman 
3610e730a2SDan Gohman #define DEBUG_TYPE "wasm-lower"
3710e730a2SDan Gohman 
38b9073fb2SJF Bastien namespace {
39b9073fb2SJF Bastien // Diagnostic information for unimplemented or unsupported feature reporting.
40b9073fb2SJF Bastien // FIXME copied from BPF and AMDGPU.
41b9073fb2SJF Bastien class DiagnosticInfoUnsupported : public DiagnosticInfo {
42b9073fb2SJF Bastien private:
43b9073fb2SJF Bastien   // Debug location where this diagnostic is triggered.
44b9073fb2SJF Bastien   DebugLoc DLoc;
45b9073fb2SJF Bastien   const Twine &Description;
46b9073fb2SJF Bastien   const Function &Fn;
47b9073fb2SJF Bastien   SDValue Value;
48b9073fb2SJF Bastien 
49b9073fb2SJF Bastien   static int KindID;
50b9073fb2SJF Bastien 
51b9073fb2SJF Bastien   static int getKindID() {
52b9073fb2SJF Bastien     if (KindID == 0)
53b9073fb2SJF Bastien       KindID = llvm::getNextAvailablePluginDiagnosticKind();
54b9073fb2SJF Bastien     return KindID;
55b9073fb2SJF Bastien   }
56b9073fb2SJF Bastien 
57b9073fb2SJF Bastien public:
58b9073fb2SJF Bastien   DiagnosticInfoUnsupported(SDLoc DLoc, const Function &Fn, const Twine &Desc,
59b9073fb2SJF Bastien                             SDValue Value)
60b9073fb2SJF Bastien       : DiagnosticInfo(getKindID(), DS_Error), DLoc(DLoc.getDebugLoc()),
61b9073fb2SJF Bastien         Description(Desc), Fn(Fn), Value(Value) {}
62b9073fb2SJF Bastien 
63b9073fb2SJF Bastien   void print(DiagnosticPrinter &DP) const override {
64b9073fb2SJF Bastien     std::string Str;
65b9073fb2SJF Bastien     raw_string_ostream OS(Str);
66b9073fb2SJF Bastien 
67b9073fb2SJF Bastien     if (DLoc) {
68b9073fb2SJF Bastien       auto DIL = DLoc.get();
69b9073fb2SJF Bastien       StringRef Filename = DIL->getFilename();
70b9073fb2SJF Bastien       unsigned Line = DIL->getLine();
71b9073fb2SJF Bastien       unsigned Column = DIL->getColumn();
72b9073fb2SJF Bastien       OS << Filename << ':' << Line << ':' << Column << ' ';
73b9073fb2SJF Bastien     }
74b9073fb2SJF Bastien 
75b9073fb2SJF Bastien     OS << "in function " << Fn.getName() << ' ' << *Fn.getFunctionType() << '\n'
76b9073fb2SJF Bastien        << Description;
77b9073fb2SJF Bastien     if (Value)
78b9073fb2SJF Bastien       Value->print(OS);
79b9073fb2SJF Bastien     OS << '\n';
80b9073fb2SJF Bastien     OS.flush();
81b9073fb2SJF Bastien     DP << Str;
82b9073fb2SJF Bastien   }
83b9073fb2SJF Bastien 
84b9073fb2SJF Bastien   static bool classof(const DiagnosticInfo *DI) {
85b9073fb2SJF Bastien     return DI->getKind() == getKindID();
86b9073fb2SJF Bastien   }
87b9073fb2SJF Bastien };
88b9073fb2SJF Bastien 
89b9073fb2SJF Bastien int DiagnosticInfoUnsupported::KindID = 0;
90b9073fb2SJF Bastien } // end anonymous namespace
91b9073fb2SJF Bastien 
9210e730a2SDan Gohman WebAssemblyTargetLowering::WebAssemblyTargetLowering(
9310e730a2SDan Gohman     const TargetMachine &TM, const WebAssemblySubtarget &STI)
94bfaf7e15SDan Gohman     : TargetLowering(TM), Subtarget(&STI) {
95bfaf7e15SDan Gohman   // WebAssembly does not produce floating-point exceptions on normal floating
96bfaf7e15SDan Gohman   // point operations.
97bfaf7e15SDan Gohman   setHasFloatingPointExceptions(false);
98489abd70SDan Gohman   // We don't know the microarchitecture here, so just reduce register pressure.
99489abd70SDan Gohman   setSchedulingPreference(Sched::RegPressure);
100b9073fb2SJF Bastien   // Tell ISel that we have a stack pointer.
101b9073fb2SJF Bastien   setStackPointerRegisterToSaveRestore(
102b9073fb2SJF Bastien       Subtarget->hasAddr64() ? WebAssembly::SP64 : WebAssembly::SP32);
103b9073fb2SJF Bastien   // Set up the register classes.
104b9073fb2SJF Bastien   addRegisterClass(MVT::i32, &WebAssembly::Int32RegClass);
105b9073fb2SJF Bastien   addRegisterClass(MVT::i64, &WebAssembly::Int64RegClass);
106b9073fb2SJF Bastien   addRegisterClass(MVT::f32, &WebAssembly::Float32RegClass);
107b9073fb2SJF Bastien   addRegisterClass(MVT::f64, &WebAssembly::Float64RegClass);
108b9073fb2SJF Bastien   // Compute derived properties from the register classes.
109b9073fb2SJF Bastien   computeRegisterProperties(Subtarget->getRegisterInfo());
110b9073fb2SJF Bastien 
111b9073fb2SJF Bastien   // FIXME: setOperationAction...
112bfaf7e15SDan Gohman }
11310e730a2SDan Gohman 
11410e730a2SDan Gohman //===----------------------------------------------------------------------===//
11510e730a2SDan Gohman // WebAssembly Lowering private implementation.
11610e730a2SDan Gohman //===----------------------------------------------------------------------===//
11710e730a2SDan Gohman 
11810e730a2SDan Gohman //===----------------------------------------------------------------------===//
11910e730a2SDan Gohman // Lowering Code
12010e730a2SDan Gohman //===----------------------------------------------------------------------===//
12110e730a2SDan Gohman 
122b9073fb2SJF Bastien static void fail(SDLoc DL, SelectionDAG &DAG, const char *msg) {
123b9073fb2SJF Bastien   MachineFunction &MF = DAG.getMachineFunction();
124b9073fb2SJF Bastien   DAG.getContext()->diagnose(
125b9073fb2SJF Bastien       DiagnosticInfoUnsupported(DL, *MF.getFunction(), msg, SDValue()));
126b9073fb2SJF Bastien }
127b9073fb2SJF Bastien 
128b9073fb2SJF Bastien bool WebAssemblyTargetLowering::CanLowerReturn(
129b9073fb2SJF Bastien     CallingConv::ID CallConv, MachineFunction &MF, bool IsVarArg,
130b9073fb2SJF Bastien     const SmallVectorImpl<ISD::OutputArg> &Outs, LLVMContext &Context) const {
131b9073fb2SJF Bastien   // WebAssembly can't currently handle returning tuples.
132b9073fb2SJF Bastien   return Outs.size() <= 1;
133b9073fb2SJF Bastien }
134b9073fb2SJF Bastien 
135b9073fb2SJF Bastien SDValue WebAssemblyTargetLowering::LowerReturn(
136b9073fb2SJF Bastien     SDValue Chain, CallingConv::ID CallConv, bool IsVarArg,
137b9073fb2SJF Bastien     const SmallVectorImpl<ISD::OutputArg> &Outs,
138b9073fb2SJF Bastien     const SmallVectorImpl<SDValue> &OutVals, SDLoc DL,
139b9073fb2SJF Bastien     SelectionDAG &DAG) const {
140b9073fb2SJF Bastien 
141b9073fb2SJF Bastien   assert(Outs.size() <= 1 && "WebAssembly can only return up to one value");
142b9073fb2SJF Bastien   if (CallConv != CallingConv::C)
143b9073fb2SJF Bastien     fail(DL, DAG, "WebAssembly doesn't support non-C calling conventions");
144600aee98SJF Bastien   if (IsVarArg)
145600aee98SJF Bastien     fail(DL, DAG, "WebAssembly doesn't support varargs yet");
146b9073fb2SJF Bastien 
147600aee98SJF Bastien   SmallVector<SDValue, 4> RetOps(1, Chain);
148600aee98SJF Bastien   RetOps.append(OutVals.begin(), OutVals.end());
149600aee98SJF Bastien   const SDValue Ops[] = {Chain, OutVals.front()};
150600aee98SJF Bastien   Chain = DAG.getNode(WebAssemblyISD::RETURN, DL, MVT::Other, Ops);
151b9073fb2SJF Bastien 
152b9073fb2SJF Bastien   return Chain;
153b9073fb2SJF Bastien }
154b9073fb2SJF Bastien 
155b9073fb2SJF Bastien SDValue WebAssemblyTargetLowering::LowerFormalArguments(
156b9073fb2SJF Bastien     SDValue Chain, CallingConv::ID CallConv, bool IsVarArg,
157b9073fb2SJF Bastien     const SmallVectorImpl<ISD::InputArg> &Ins, SDLoc DL, SelectionDAG &DAG,
158b9073fb2SJF Bastien     SmallVectorImpl<SDValue> &InVals) const {
159b9073fb2SJF Bastien   MachineFunction &MF = DAG.getMachineFunction();
160b9073fb2SJF Bastien 
161b9073fb2SJF Bastien   if (CallConv != CallingConv::C)
162b9073fb2SJF Bastien     fail(DL, DAG, "WebAssembly doesn't support non-C calling conventions");
163b9073fb2SJF Bastien   if (IsVarArg)
164b9073fb2SJF Bastien     fail(DL, DAG, "WebAssembly doesn't support varargs yet");
165b9073fb2SJF Bastien   if (MF.getFunction()->hasStructRetAttr())
166b9073fb2SJF Bastien     fail(DL, DAG, "WebAssembly doesn't support struct return yet");
167b9073fb2SJF Bastien 
168600aee98SJF Bastien   unsigned ArgNo = 0;
169600aee98SJF Bastien   for (const ISD::InputArg &In : Ins) {
170600aee98SJF Bastien     if (In.Flags.isZExt())
171600aee98SJF Bastien       fail(DL, DAG, "WebAssembly hasn't implemented zext arguments");
172600aee98SJF Bastien     if (In.Flags.isSExt())
173600aee98SJF Bastien       fail(DL, DAG, "WebAssembly hasn't implemented sext arguments");
174600aee98SJF Bastien     if (In.Flags.isInReg())
175600aee98SJF Bastien       fail(DL, DAG, "WebAssembly hasn't implemented inreg arguments");
176600aee98SJF Bastien     if (In.Flags.isSRet())
177600aee98SJF Bastien       fail(DL, DAG, "WebAssembly hasn't implemented sret arguments");
178600aee98SJF Bastien     if (In.Flags.isByVal())
179600aee98SJF Bastien       fail(DL, DAG, "WebAssembly hasn't implemented byval arguments");
180600aee98SJF Bastien     if (In.Flags.isInAlloca())
181600aee98SJF Bastien       fail(DL, DAG, "WebAssembly hasn't implemented inalloca arguments");
182600aee98SJF Bastien     if (In.Flags.isNest())
183600aee98SJF Bastien       fail(DL, DAG, "WebAssembly hasn't implemented nest arguments");
184600aee98SJF Bastien     if (In.Flags.isReturned())
185600aee98SJF Bastien       fail(DL, DAG, "WebAssembly hasn't implemented returned arguments");
186600aee98SJF Bastien     if (In.Flags.isInConsecutiveRegs())
187600aee98SJF Bastien       fail(DL, DAG, "WebAssembly hasn't implemented cons regs arguments");
188600aee98SJF Bastien     if (In.Flags.isInConsecutiveRegsLast())
189600aee98SJF Bastien       fail(DL, DAG, "WebAssembly hasn't implemented cons regs last arguments");
190600aee98SJF Bastien     if (In.Flags.isSplit())
191600aee98SJF Bastien       fail(DL, DAG, "WebAssembly hasn't implemented split arguments");
192600aee98SJF Bastien     if (In.VT != MVT::i32)
193600aee98SJF Bastien       fail(DL, DAG, "WebAssembly hasn't implemented non-i32 arguments");
194600aee98SJF Bastien     // FIXME Do something with In.getOrigAlign()?
195*d7fcc6f9SJF Bastien     InVals.push_back(
196*d7fcc6f9SJF Bastien         In.Used
197*d7fcc6f9SJF Bastien             ? DAG.getNode(WebAssemblyISD::ARGUMENT, DL, In.VT,
198*d7fcc6f9SJF Bastien                           DAG.getTargetConstant(ArgNo, DL, MVT::i32))
199*d7fcc6f9SJF Bastien             : DAG.getNode(ISD::UNDEF, DL, In.VT));
200*d7fcc6f9SJF Bastien     ++ArgNo;
201600aee98SJF Bastien   }
202b9073fb2SJF Bastien 
203b9073fb2SJF Bastien   return Chain;
204b9073fb2SJF Bastien }
205b9073fb2SJF Bastien 
20610e730a2SDan Gohman //===----------------------------------------------------------------------===//
20710e730a2SDan Gohman //  Other Lowering Code
20810e730a2SDan Gohman //===----------------------------------------------------------------------===//
20910e730a2SDan Gohman 
21010e730a2SDan Gohman //===----------------------------------------------------------------------===//
21110e730a2SDan Gohman //                          WebAssembly Optimization Hooks
21210e730a2SDan Gohman //===----------------------------------------------------------------------===//
21310e730a2SDan Gohman 
21410e730a2SDan Gohman MCSection *WebAssemblyTargetObjectFile::SelectSectionForGlobal(
21510e730a2SDan Gohman     const GlobalValue *GV, SectionKind Kind, Mangler &Mang,
21610e730a2SDan Gohman     const TargetMachine &TM) const {
21710e730a2SDan Gohman   return getDataSection();
21810e730a2SDan Gohman }
219