diff options
Diffstat (limited to 'llvm/lib/Target/WebAssembly/WebAssemblyISelDAGToDAG.cpp')
-rw-r--r-- | llvm/lib/Target/WebAssembly/WebAssemblyISelDAGToDAG.cpp | 76 |
1 files changed, 47 insertions, 29 deletions
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyISelDAGToDAG.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyISelDAGToDAG.cpp index 531a07b829c85..d1a696f854f8b 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyISelDAGToDAG.cpp +++ b/llvm/lib/Target/WebAssembly/WebAssemblyISelDAGToDAG.cpp @@ -53,11 +53,6 @@ public: Subtarget = &MF.getSubtarget<WebAssemblySubtarget>(); - // Wasm64 is not fully supported right now (and is not specified) - if (Subtarget->hasAddr64()) - report_fatal_error( - "64-bit WebAssembly (wasm64) is not currently supported"); - return SelectionDAGISel::runOnMachineFunction(MF); } @@ -82,6 +77,13 @@ void WebAssemblyDAGToDAGISel::Select(SDNode *Node) { return; } + MVT PtrVT = TLI->getPointerTy(CurDAG->getDataLayout()); + auto GlobalGetIns = PtrVT == MVT::i64 ? WebAssembly::GLOBAL_GET_I64 + : WebAssembly::GLOBAL_GET_I32; + auto ConstIns = + PtrVT == MVT::i64 ? WebAssembly::CONST_I64 : WebAssembly::CONST_I32; + auto AddIns = PtrVT == MVT::i64 ? WebAssembly::ADD_I64 : WebAssembly::ADD_I32; + // Few custom selection stuff. SDLoc DL(Node); MachineFunction &MF = CurDAG->getMachineFunction(); @@ -145,20 +147,16 @@ void WebAssemblyDAGToDAGISel::Select(SDNode *Node) { false); } - MVT PtrVT = TLI->getPointerTy(CurDAG->getDataLayout()); - assert(PtrVT == MVT::i32 && "only wasm32 is supported for now"); - SDValue TLSBaseSym = CurDAG->getTargetExternalSymbol("__tls_base", PtrVT); SDValue TLSOffsetSym = CurDAG->getTargetGlobalAddress( GA->getGlobal(), DL, PtrVT, GA->getOffset(), 0); - MachineSDNode *TLSBase = CurDAG->getMachineNode(WebAssembly::GLOBAL_GET_I32, - DL, MVT::i32, TLSBaseSym); - MachineSDNode *TLSOffset = CurDAG->getMachineNode( - WebAssembly::CONST_I32, DL, MVT::i32, TLSOffsetSym); - MachineSDNode *TLSAddress = - CurDAG->getMachineNode(WebAssembly::ADD_I32, DL, MVT::i32, - SDValue(TLSBase, 0), SDValue(TLSOffset, 0)); + MachineSDNode *TLSBase = + CurDAG->getMachineNode(GlobalGetIns, DL, PtrVT, TLSBaseSym); + MachineSDNode *TLSOffset = + CurDAG->getMachineNode(ConstIns, DL, PtrVT, TLSOffsetSym); + MachineSDNode *TLSAddress = CurDAG->getMachineNode( + AddIns, DL, PtrVT, SDValue(TLSBase, 0), SDValue(TLSOffset, 0)); ReplaceNode(Node, TLSAddress); return; } @@ -167,22 +165,16 @@ void WebAssemblyDAGToDAGISel::Select(SDNode *Node) { unsigned IntNo = cast<ConstantSDNode>(Node->getOperand(0))->getZExtValue(); switch (IntNo) { case Intrinsic::wasm_tls_size: { - MVT PtrVT = TLI->getPointerTy(CurDAG->getDataLayout()); - assert(PtrVT == MVT::i32 && "only wasm32 is supported for now"); - MachineSDNode *TLSSize = CurDAG->getMachineNode( - WebAssembly::GLOBAL_GET_I32, DL, PtrVT, - CurDAG->getTargetExternalSymbol("__tls_size", MVT::i32)); + GlobalGetIns, DL, PtrVT, + CurDAG->getTargetExternalSymbol("__tls_size", PtrVT)); ReplaceNode(Node, TLSSize); return; } case Intrinsic::wasm_tls_align: { - MVT PtrVT = TLI->getPointerTy(CurDAG->getDataLayout()); - assert(PtrVT == MVT::i32 && "only wasm32 is supported for now"); - MachineSDNode *TLSAlign = CurDAG->getMachineNode( - WebAssembly::GLOBAL_GET_I32, DL, PtrVT, - CurDAG->getTargetExternalSymbol("__tls_align", MVT::i32)); + GlobalGetIns, DL, PtrVT, + CurDAG->getTargetExternalSymbol("__tls_align", PtrVT)); ReplaceNode(Node, TLSAlign); return; } @@ -193,11 +185,8 @@ void WebAssemblyDAGToDAGISel::Select(SDNode *Node) { unsigned IntNo = cast<ConstantSDNode>(Node->getOperand(1))->getZExtValue(); switch (IntNo) { case Intrinsic::wasm_tls_base: { - MVT PtrVT = TLI->getPointerTy(CurDAG->getDataLayout()); - assert(PtrVT == MVT::i32 && "only wasm32 is supported for now"); - MachineSDNode *TLSBase = CurDAG->getMachineNode( - WebAssembly::GLOBAL_GET_I32, DL, MVT::i32, MVT::Other, + GlobalGetIns, DL, PtrVT, MVT::Other, CurDAG->getTargetExternalSymbol("__tls_base", PtrVT), Node->getOperand(0)); ReplaceNode(Node, TLSBase); @@ -206,6 +195,35 @@ void WebAssemblyDAGToDAGISel::Select(SDNode *Node) { } break; } + case WebAssemblyISD::CALL: + case WebAssemblyISD::RET_CALL: { + // CALL has both variable operands and variable results, but ISel only + // supports one or the other. Split calls into two nodes glued together, one + // for the operands and one for the results. These two nodes will be + // recombined in a custom inserter hook into a single MachineInstr. + SmallVector<SDValue, 16> Ops; + for (size_t i = 1; i < Node->getNumOperands(); ++i) { + SDValue Op = Node->getOperand(i); + if (i == 1 && Op->getOpcode() == WebAssemblyISD::Wrapper) + Op = Op->getOperand(0); + Ops.push_back(Op); + } + + // Add the chain last + Ops.push_back(Node->getOperand(0)); + MachineSDNode *CallParams = + CurDAG->getMachineNode(WebAssembly::CALL_PARAMS, DL, MVT::Glue, Ops); + + unsigned Results = Node->getOpcode() == WebAssemblyISD::CALL + ? WebAssembly::CALL_RESULTS + : WebAssembly::RET_CALL_RESULTS; + + SDValue Link(CallParams, 0); + MachineSDNode *CallResults = + CurDAG->getMachineNode(Results, DL, Node->getVTList(), Link); + ReplaceNode(Node, CallResults); + return; + } default: break; |