X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FTarget%2FWebAssembly%2FWebAssemblyISelLowering.cpp;h=2485df1ab5d20db2ab86effbf60f083fd94f4de5;hb=66e256e46ec68ed425d0bf0b067a3bf003915a09;hp=dbfe00e95ed005c0401fb0ca68bc1418de2c8fb7;hpb=0426ad40b56741117d00e780b07607f120ee1d01;p=oota-llvm.git diff --git a/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp b/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp index dbfe00e95ed..2485df1ab5d 100644 --- a/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp +++ b/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp @@ -32,15 +32,15 @@ #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 { +// TODO: This code is copied from BPF and AMDGPU; consider factoring it out +// and sharing code. +class DiagnosticInfoUnsupported final : public DiagnosticInfo { private: // Debug location where this diagnostic is triggered. DebugLoc DLoc; @@ -115,6 +115,7 @@ WebAssemblyTargetLowering::WebAssemblyTargetLowering( computeRegisterProperties(Subtarget->getRegisterInfo()); setOperationAction(ISD::GlobalAddress, MVTPtr, Custom); + setOperationAction(ISD::ExternalSymbol, MVTPtr, Custom); setOperationAction(ISD::JumpTable, MVTPtr, Custom); for (auto T : {MVT::f32, MVT::f64}) { @@ -129,8 +130,8 @@ WebAssemblyTargetLowering::WebAssemblyTargetLowering( setOperationAction(Op, T, Expand); // Note supported floating-point library function operators that otherwise // default to expand. - for (auto Op : {ISD::FCEIL, ISD::FFLOOR, ISD::FTRUNC, ISD::FNEARBYINT, - ISD::FRINT}) + for (auto Op : + {ISD::FCEIL, ISD::FFLOOR, ISD::FTRUNC, ISD::FNEARBYINT, ISD::FRINT}) setOperationAction(Op, T, Legal); // Support minnan and maxnan, which otherwise default to expand. setOperationAction(ISD::FMINNAN, T, Legal); @@ -139,11 +140,11 @@ WebAssemblyTargetLowering::WebAssemblyTargetLowering( for (auto T : {MVT::i32, MVT::i64}) { // Expand unavailable integer operations. - for (auto Op : {ISD::BSWAP, ISD::ROTL, ISD::ROTR, - ISD::SMUL_LOHI, ISD::UMUL_LOHI, - ISD::MULHS, ISD::MULHU, ISD::SDIVREM, ISD::UDIVREM, - ISD::SHL_PARTS, ISD::SRA_PARTS, ISD::SRL_PARTS, - ISD::ADDC, ISD::ADDE, ISD::SUBC, ISD::SUBE}) { + for (auto Op : + {ISD::BSWAP, ISD::ROTL, ISD::ROTR, ISD::SMUL_LOHI, ISD::UMUL_LOHI, + ISD::MULHS, ISD::MULHU, ISD::SDIVREM, ISD::UDIVREM, ISD::SHL_PARTS, + ISD::SRA_PARTS, ISD::SRL_PARTS, ISD::ADDC, ISD::ADDE, ISD::SUBC, + ISD::SUBE}) { setOperationAction(Op, T, Expand); } } @@ -186,13 +187,13 @@ FastISel *WebAssemblyTargetLowering::createFastISel( } bool WebAssemblyTargetLowering::isOffsetFoldingLegal( - const GlobalAddressSDNode *GA) const { + const GlobalAddressSDNode * /*GA*/) const { // The WebAssembly target doesn't support folding offsets into global // addresses. return false; } -MVT WebAssemblyTargetLowering::getScalarShiftAmountTy(const DataLayout &DL, +MVT WebAssemblyTargetLowering::getScalarShiftAmountTy(const DataLayout & /*DL*/, EVT VT) const { return VT.getSimpleVT(); } @@ -219,7 +220,11 @@ WebAssemblyTargetLowering::getRegForInlineAsmConstraint( if (Constraint.size() == 1) { switch (Constraint[0]) { case 'r': - return std::make_pair(0U, &WebAssembly::I32RegClass); + if (VT == MVT::i32) + return std::make_pair(0U, &WebAssembly::I32RegClass); + if (VT == MVT::i64) + return std::make_pair(0U, &WebAssembly::I64RegClass); + break; default: break; } @@ -262,8 +267,7 @@ WebAssemblyTargetLowering::LowerCall(CallLoweringInfo &CLI, MachineFunction &MF = DAG.getMachineFunction(); CallingConv::ID CallConv = CLI.CallConv; - if (CallConv != CallingConv::C && - CallConv != CallingConv::Fast && + if (CallConv != CallingConv::C && CallConv != CallingConv::Fast && CallConv != CallingConv::Cold) fail(DL, DAG, "WebAssembly doesn't support language-specific or target-specific " @@ -325,8 +329,9 @@ WebAssemblyTargetLowering::LowerCall(CallLoweringInfo &CLI, } bool WebAssemblyTargetLowering::CanLowerReturn( - CallingConv::ID CallConv, MachineFunction &MF, bool IsVarArg, - const SmallVectorImpl &Outs, LLVMContext &Context) const { + CallingConv::ID /*CallConv*/, MachineFunction & /*MF*/, bool /*IsVarArg*/, + const SmallVectorImpl &Outs, + LLVMContext & /*Context*/) const { // WebAssembly can't currently handle returning tuples. return Outs.size() <= 1; } @@ -348,12 +353,10 @@ SDValue WebAssemblyTargetLowering::LowerReturn( // Record the number and types of the return values. for (const ISD::OutputArg &Out : Outs) { - if (Out.Flags.isByVal()) - fail(DL, DAG, "WebAssembly hasn't implemented byval results"); + assert(!Out.Flags.isByVal() && "byval is not valid for return values"); + assert(!Out.Flags.isNest() && "nest is not valid for return values"); if (Out.Flags.isInAlloca()) fail(DL, DAG, "WebAssembly hasn't implemented inalloca results"); - if (Out.Flags.isNest()) - fail(DL, DAG, "WebAssembly hasn't implemented nest results"); if (Out.Flags.isInConsecutiveRegs()) fail(DL, DAG, "WebAssembly hasn't implemented cons regs results"); if (Out.Flags.isInConsecutiveRegsLast()) @@ -376,6 +379,10 @@ SDValue WebAssemblyTargetLowering::LowerFormalArguments( if (IsVarArg) fail(DL, DAG, "WebAssembly doesn't support varargs yet"); + // Set up the incoming ARGUMENTS value, which serves to represent the liveness + // of the incoming values before they're represented by virtual registers. + MF.getRegInfo().addLiveIn(WebAssembly::ARGUMENTS); + for (const ISD::InputArg &In : Ins) { if (In.Flags.isByVal()) fail(DL, DAG, "WebAssembly hasn't implemented byval arguments"); @@ -387,7 +394,8 @@ SDValue WebAssemblyTargetLowering::LowerFormalArguments( 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"); - // FIXME Do something with In.getOrigAlign()? + // Ignore In.getOrigAlign() because all our arguments are passed in + // registers. InVals.push_back( In.Used ? DAG.getNode(WebAssemblyISD::ARGUMENT, DL, In.VT, @@ -413,6 +421,8 @@ SDValue WebAssemblyTargetLowering::LowerOperation(SDValue Op, return SDValue(); case ISD::GlobalAddress: return LowerGlobalAddress(Op, DAG); + case ISD::ExternalSymbol: + return LowerExternalSymbol(Op, DAG); case ISD::JumpTable: return LowerJumpTable(Op, DAG); case ISD::BR_JT: @@ -434,11 +444,22 @@ SDValue WebAssemblyTargetLowering::LowerGlobalAddress(SDValue Op, DAG.getTargetGlobalAddress(GA->getGlobal(), DL, VT)); } +SDValue +WebAssemblyTargetLowering::LowerExternalSymbol(SDValue Op, + SelectionDAG &DAG) const { + SDLoc DL(Op); + const auto *ES = cast(Op); + EVT VT = Op.getValueType(); + assert(ES->getTargetFlags() == 0 && "WebAssembly doesn't set target flags"); + return DAG.getNode(WebAssemblyISD::Wrapper, DL, VT, + DAG.getTargetExternalSymbol(ES->getSymbol(), VT)); +} + SDValue WebAssemblyTargetLowering::LowerJumpTable(SDValue Op, SelectionDAG &DAG) const { // There's no need for a Wrapper node because we always incorporate a jump - // table operand into a SWITCH instruction, rather than ever materializing - // it in a register. + // table operand into a TABLESWITCH instruction, rather than ever + // materializing it in a register. const JumpTableSDNode *JT = cast(Op); return DAG.getTargetJumpTable(JT->getIndex(), Op.getValueType(), JT->getTargetFlags()); @@ -468,7 +489,7 @@ SDValue WebAssemblyTargetLowering::LowerBR_JT(SDValue Op, for (auto MBB : MBBs) Ops.push_back(DAG.getBasicBlock(MBB)); - return DAG.getNode(WebAssemblyISD::SWITCH, DL, MVT::Other, Ops); + return DAG.getNode(WebAssemblyISD::TABLESWITCH, DL, MVT::Other, Ops); } //===----------------------------------------------------------------------===// @@ -476,8 +497,8 @@ SDValue WebAssemblyTargetLowering::LowerBR_JT(SDValue Op, //===----------------------------------------------------------------------===// MCSection *WebAssemblyTargetObjectFile::SelectSectionForGlobal( - const GlobalValue *GV, SectionKind Kind, Mangler &Mang, - const TargetMachine &TM) const { + const GlobalValue *GV, SectionKind /*Kind*/, Mangler & /*Mang*/, + const TargetMachine & /*TM*/) const { // TODO: Be more sophisticated than this. return isa(GV) ? getTextSection() : getDataSection(); }