diff options
Diffstat (limited to 'llvm/lib/Target/WebAssembly/WebAssemblyISelDAGToDAG.cpp')
-rw-r--r-- | llvm/lib/Target/WebAssembly/WebAssemblyISelDAGToDAG.cpp | 38 |
1 files changed, 38 insertions, 0 deletions
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyISelDAGToDAG.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyISelDAGToDAG.cpp index b9154b09fbbc..f4bae59132e6 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyISelDAGToDAG.cpp +++ b/llvm/lib/Target/WebAssembly/WebAssemblyISelDAGToDAG.cpp @@ -13,7 +13,9 @@ #include "MCTargetDesc/WebAssemblyMCTargetDesc.h" #include "WebAssembly.h" +#include "WebAssemblyISelLowering.h" #include "WebAssemblyTargetMachine.h" +#include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/SelectionDAGISel.h" #include "llvm/IR/DiagnosticInfo.h" #include "llvm/IR/Function.h" // To access function attributes. @@ -46,20 +48,44 @@ public: return "WebAssembly Instruction Selection"; } + void checkForInvalidNodes(const Function &F) { + // This function will check for uses of ptrtoint on reference types and + // report a fatal error if these are found. + for (const BasicBlock &BB : F) { + for (const Instruction &I : BB) { + if (const PtrToIntInst *PTI = dyn_cast<const PtrToIntInst>(&I)) { + const Value *V = PTI->getPointerOperand(); + if (WebAssemblyTargetLowering::isFuncrefType(V->getType()) || + WebAssemblyTargetLowering::isExternrefType(V->getType())) + report_fatal_error("ptrtoint not allowed on reference types"); + } else if (const IntToPtrInst *ITP = dyn_cast<const IntToPtrInst>(&I)) { + if (WebAssemblyTargetLowering::isFuncrefType(ITP->getDestTy()) || + WebAssemblyTargetLowering::isExternrefType(ITP->getDestTy())) + report_fatal_error("inttoptr not allowed on reference types"); + } + } + } + } + bool runOnMachineFunction(MachineFunction &MF) override { LLVM_DEBUG(dbgs() << "********** ISelDAGToDAG **********\n" "********** Function: " << MF.getName() << '\n'); + checkForInvalidNodes(MF.getFunction()); + Subtarget = &MF.getSubtarget<WebAssemblySubtarget>(); return SelectionDAGISel::runOnMachineFunction(MF); } + void PreprocessISelDAG() override; + void Select(SDNode *Node) override; bool SelectInlineAsmMemoryOperand(const SDValue &Op, unsigned ConstraintID, std::vector<SDValue> &OutOps) override; + bool SelectExternRefAddr(const SDValue &Addr, const SDValue &Base); // Include the pieces autogenerated from the target description. #include "WebAssemblyGenDAGISel.inc" @@ -69,6 +95,18 @@ private: }; } // end anonymous namespace +void WebAssemblyDAGToDAGISel::PreprocessISelDAG() { + // Stack objects that should be allocated to locals are hoisted to WebAssembly + // locals when they are first used. However for those without uses, we hoist + // them here. It would be nice if there were some hook to do this when they + // are added to the MachineFrameInfo, but that's not the case right now. + MachineFrameInfo &FrameInfo = MF->getFrameInfo(); + for (int Idx = 0; Idx < FrameInfo.getObjectIndexEnd(); Idx++) + WebAssemblyFrameLowering::getLocalForStackObject(*MF, Idx); + + SelectionDAGISel::PreprocessISelDAG(); +} + void WebAssemblyDAGToDAGISel::Select(SDNode *Node) { // If we have a custom node, we already have selected! if (Node->isMachineOpcode()) { |