X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FTarget%2FWebAssembly%2FWebAssemblyISelLowering.cpp;h=639e19a52dc2a7c9349e20e447d501547c2d1ab3;hb=3f2cb5c959754a99ebe7fe9611e8788afd2da8e8;hp=4eec02efbd941bca7260fe4da8502c7d29ff183f;hpb=44bc052f4d866f4e5885a22d23ed9ccef77e30df;p=oota-llvm.git diff --git a/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp b/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp index 4eec02efbd9..639e19a52dc 100644 --- a/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp +++ b/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp @@ -21,6 +21,8 @@ #include "llvm/CodeGen/Analysis.h" #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/SelectionDAG.h" +#include "llvm/IR/DiagnosticInfo.h" +#include "llvm/IR/DiagnosticPrinter.h" #include "llvm/IR/Function.h" #include "llvm/IR/Intrinsics.h" #include "llvm/Support/CommandLine.h" @@ -28,16 +30,85 @@ #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Target/TargetOptions.h" + using namespace llvm; #define DEBUG_TYPE "wasm-lower" +namespace { +// Diagnostic information for unimplemented or unsupported feature reporting. +// FIXME copied from BPF and AMDGPU. +class DiagnosticInfoUnsupported : public DiagnosticInfo { +private: + // Debug location where this diagnostic is triggered. + DebugLoc DLoc; + const Twine &Description; + const Function &Fn; + SDValue Value; + + static int KindID; + + static int getKindID() { + if (KindID == 0) + KindID = llvm::getNextAvailablePluginDiagnosticKind(); + return KindID; + } + +public: + DiagnosticInfoUnsupported(SDLoc DLoc, const Function &Fn, const Twine &Desc, + SDValue Value) + : DiagnosticInfo(getKindID(), DS_Error), DLoc(DLoc.getDebugLoc()), + Description(Desc), Fn(Fn), Value(Value) {} + + void print(DiagnosticPrinter &DP) const override { + std::string Str; + raw_string_ostream OS(Str); + + if (DLoc) { + auto DIL = DLoc.get(); + StringRef Filename = DIL->getFilename(); + unsigned Line = DIL->getLine(); + unsigned Column = DIL->getColumn(); + OS << Filename << ':' << Line << ':' << Column << ' '; + } + + OS << "in function " << Fn.getName() << ' ' << *Fn.getFunctionType() << '\n' + << Description; + if (Value) + Value->print(OS); + OS << '\n'; + OS.flush(); + DP << Str; + } + + static bool classof(const DiagnosticInfo *DI) { + return DI->getKind() == getKindID(); + } +}; + +int DiagnosticInfoUnsupported::KindID = 0; +} // end anonymous namespace + WebAssemblyTargetLowering::WebAssemblyTargetLowering( const TargetMachine &TM, const WebAssemblySubtarget &STI) : TargetLowering(TM), Subtarget(&STI) { // WebAssembly does not produce floating-point exceptions on normal floating // point operations. setHasFloatingPointExceptions(false); + // We don't know the microarchitecture here, so just reduce register pressure. + setSchedulingPreference(Sched::RegPressure); + // Tell ISel that we have a stack pointer. + setStackPointerRegisterToSaveRestore( + Subtarget->hasAddr64() ? WebAssembly::SP64 : WebAssembly::SP32); + // Set up the register classes. + addRegisterClass(MVT::i32, &WebAssembly::Int32RegClass); + addRegisterClass(MVT::i64, &WebAssembly::Int64RegClass); + addRegisterClass(MVT::f32, &WebAssembly::Float32RegClass); + addRegisterClass(MVT::f64, &WebAssembly::Float64RegClass); + // Compute derived properties from the register classes. + computeRegisterProperties(Subtarget->getRegisterInfo()); + + // FIXME: setOperationAction... } //===----------------------------------------------------------------------===// @@ -48,6 +119,88 @@ WebAssemblyTargetLowering::WebAssemblyTargetLowering( // Lowering Code //===----------------------------------------------------------------------===// +static void fail(SDLoc DL, SelectionDAG &DAG, const char *msg) { + MachineFunction &MF = DAG.getMachineFunction(); + DAG.getContext()->diagnose( + DiagnosticInfoUnsupported(DL, *MF.getFunction(), msg, SDValue())); +} + +bool WebAssemblyTargetLowering::CanLowerReturn( + CallingConv::ID CallConv, MachineFunction &MF, bool IsVarArg, + const SmallVectorImpl &Outs, LLVMContext &Context) const { + // WebAssembly can't currently handle returning tuples. + return Outs.size() <= 1; +} + +SDValue WebAssemblyTargetLowering::LowerReturn( + SDValue Chain, CallingConv::ID CallConv, bool IsVarArg, + const SmallVectorImpl &Outs, + const SmallVectorImpl &OutVals, SDLoc DL, + SelectionDAG &DAG) const { + + assert(Outs.size() <= 1 && "WebAssembly can only return up to one value"); + if (CallConv != CallingConv::C) + fail(DL, DAG, "WebAssembly doesn't support non-C calling conventions"); + if (IsVarArg) + fail(DL, DAG, "WebAssembly doesn't support varargs yet"); + + SmallVector RetOps(1, Chain); + RetOps.append(OutVals.begin(), OutVals.end()); + const SDValue Ops[] = {Chain, OutVals.front()}; + Chain = DAG.getNode(WebAssemblyISD::RETURN, DL, MVT::Other, Ops); + + return Chain; +} + +SDValue WebAssemblyTargetLowering::LowerFormalArguments( + SDValue Chain, CallingConv::ID CallConv, bool IsVarArg, + const SmallVectorImpl &Ins, SDLoc DL, SelectionDAG &DAG, + SmallVectorImpl &InVals) const { + MachineFunction &MF = DAG.getMachineFunction(); + + if (CallConv != CallingConv::C) + fail(DL, DAG, "WebAssembly doesn't support non-C calling conventions"); + if (IsVarArg) + fail(DL, DAG, "WebAssembly doesn't support varargs yet"); + if (MF.getFunction()->hasStructRetAttr()) + fail(DL, DAG, "WebAssembly doesn't support struct return yet"); + + unsigned ArgNo = 0; + for (const ISD::InputArg &In : Ins) { + if (In.Flags.isZExt()) + fail(DL, DAG, "WebAssembly hasn't implemented zext arguments"); + if (In.Flags.isSExt()) + fail(DL, DAG, "WebAssembly hasn't implemented sext arguments"); + if (In.Flags.isInReg()) + fail(DL, DAG, "WebAssembly hasn't implemented inreg arguments"); + if (In.Flags.isSRet()) + fail(DL, DAG, "WebAssembly hasn't implemented sret arguments"); + if (In.Flags.isByVal()) + fail(DL, DAG, "WebAssembly hasn't implemented byval arguments"); + if (In.Flags.isInAlloca()) + fail(DL, DAG, "WebAssembly hasn't implemented inalloca arguments"); + if (In.Flags.isNest()) + fail(DL, DAG, "WebAssembly hasn't implemented nest arguments"); + if (In.Flags.isReturned()) + fail(DL, DAG, "WebAssembly hasn't implemented returned arguments"); + if (In.Flags.isInConsecutiveRegs()) + fail(DL, DAG, "WebAssembly hasn't implemented cons regs arguments"); + if (In.Flags.isInConsecutiveRegsLast()) + fail(DL, DAG, "WebAssembly hasn't implemented cons regs last arguments"); + if (In.Flags.isSplit()) + fail(DL, DAG, "WebAssembly hasn't implemented split arguments"); + if (In.VT != MVT::i32) + fail(DL, DAG, "WebAssembly hasn't implemented non-i32 arguments"); + if (!In.Used) + fail(DL, DAG, "WebAssembly hasn't implemented unused arguments"); + // FIXME Do something with In.getOrigAlign()? + InVals.push_back(DAG.getNode(WebAssemblyISD::ARGUMENT, DL, In.VT, + DAG.getTargetConstant(ArgNo++, DL, MVT::i32))); + } + + return Chain; +} + //===----------------------------------------------------------------------===// // Other Lowering Code //===----------------------------------------------------------------------===//