15ffd83dbSDimitry Andric //===-- WebAssemblyDebugFixup.cpp - Debug Fixup ------------------===// 25ffd83dbSDimitry Andric // 35ffd83dbSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 45ffd83dbSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 55ffd83dbSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 65ffd83dbSDimitry Andric // 75ffd83dbSDimitry Andric //===----------------------------------------------------------------------===// 85ffd83dbSDimitry Andric /// 95ffd83dbSDimitry Andric /// \file 105ffd83dbSDimitry Andric /// Several prior passes may "stackify" registers, here we ensure any references 115ffd83dbSDimitry Andric /// in such registers in debug_value instructions become stack relative also. 125ffd83dbSDimitry Andric /// This is done in a separate pass such that not all previous passes need to 135ffd83dbSDimitry Andric /// track stack depth when values get stackified. 145ffd83dbSDimitry Andric /// 155ffd83dbSDimitry Andric //===----------------------------------------------------------------------===// 165ffd83dbSDimitry Andric 175ffd83dbSDimitry Andric #include "MCTargetDesc/WebAssemblyMCTargetDesc.h" 18*fe6060f1SDimitry Andric #include "Utils/WebAssemblyUtilities.h" 195ffd83dbSDimitry Andric #include "WebAssembly.h" 205ffd83dbSDimitry Andric #include "WebAssemblyMachineFunctionInfo.h" 215ffd83dbSDimitry Andric #include "WebAssemblySubtarget.h" 225ffd83dbSDimitry Andric #include "llvm/ADT/SCCIterator.h" 235ffd83dbSDimitry Andric #include "llvm/CodeGen/MachineFrameInfo.h" 245ffd83dbSDimitry Andric #include "llvm/CodeGen/MachineFunction.h" 255ffd83dbSDimitry Andric #include "llvm/CodeGen/MachineInstrBuilder.h" 265ffd83dbSDimitry Andric #include "llvm/CodeGen/MachineLoopInfo.h" 275ffd83dbSDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h" 285ffd83dbSDimitry Andric #include "llvm/CodeGen/Passes.h" 295ffd83dbSDimitry Andric #include "llvm/Support/Debug.h" 305ffd83dbSDimitry Andric #include "llvm/Support/raw_ostream.h" 315ffd83dbSDimitry Andric using namespace llvm; 325ffd83dbSDimitry Andric 335ffd83dbSDimitry Andric #define DEBUG_TYPE "wasm-debug-fixup" 345ffd83dbSDimitry Andric 355ffd83dbSDimitry Andric namespace { 365ffd83dbSDimitry Andric class WebAssemblyDebugFixup final : public MachineFunctionPass { 375ffd83dbSDimitry Andric StringRef getPassName() const override { return "WebAssembly Debug Fixup"; } 385ffd83dbSDimitry Andric 395ffd83dbSDimitry Andric void getAnalysisUsage(AnalysisUsage &AU) const override { 405ffd83dbSDimitry Andric AU.setPreservesCFG(); 415ffd83dbSDimitry Andric MachineFunctionPass::getAnalysisUsage(AU); 425ffd83dbSDimitry Andric } 435ffd83dbSDimitry Andric 445ffd83dbSDimitry Andric bool runOnMachineFunction(MachineFunction &MF) override; 455ffd83dbSDimitry Andric 465ffd83dbSDimitry Andric public: 475ffd83dbSDimitry Andric static char ID; // Pass identification, replacement for typeid 485ffd83dbSDimitry Andric WebAssemblyDebugFixup() : MachineFunctionPass(ID) {} 495ffd83dbSDimitry Andric }; 505ffd83dbSDimitry Andric } // end anonymous namespace 515ffd83dbSDimitry Andric 525ffd83dbSDimitry Andric char WebAssemblyDebugFixup::ID = 0; 535ffd83dbSDimitry Andric INITIALIZE_PASS( 545ffd83dbSDimitry Andric WebAssemblyDebugFixup, DEBUG_TYPE, 555ffd83dbSDimitry Andric "Ensures debug_value's that have been stackified become stack relative", 565ffd83dbSDimitry Andric false, false) 575ffd83dbSDimitry Andric 585ffd83dbSDimitry Andric FunctionPass *llvm::createWebAssemblyDebugFixup() { 595ffd83dbSDimitry Andric return new WebAssemblyDebugFixup(); 605ffd83dbSDimitry Andric } 615ffd83dbSDimitry Andric 625ffd83dbSDimitry Andric bool WebAssemblyDebugFixup::runOnMachineFunction(MachineFunction &MF) { 635ffd83dbSDimitry Andric LLVM_DEBUG(dbgs() << "********** Debug Fixup **********\n" 645ffd83dbSDimitry Andric "********** Function: " 655ffd83dbSDimitry Andric << MF.getName() << '\n'); 665ffd83dbSDimitry Andric 675ffd83dbSDimitry Andric WebAssemblyFunctionInfo &MFI = *MF.getInfo<WebAssemblyFunctionInfo>(); 685ffd83dbSDimitry Andric const auto *TII = MF.getSubtarget<WebAssemblySubtarget>().getInstrInfo(); 695ffd83dbSDimitry Andric 705ffd83dbSDimitry Andric struct StackElem { 715ffd83dbSDimitry Andric unsigned Reg; 725ffd83dbSDimitry Andric MachineInstr *DebugValue; 735ffd83dbSDimitry Andric }; 745ffd83dbSDimitry Andric std::vector<StackElem> Stack; 755ffd83dbSDimitry Andric for (MachineBasicBlock &MBB : MF) { 765ffd83dbSDimitry Andric // We may insert into this list. 775ffd83dbSDimitry Andric for (auto MII = MBB.begin(); MII != MBB.end(); ++MII) { 785ffd83dbSDimitry Andric MachineInstr &MI = *MII; 795ffd83dbSDimitry Andric if (MI.isDebugValue()) { 805ffd83dbSDimitry Andric auto &MO = MI.getOperand(0); 815ffd83dbSDimitry Andric // Also check if not a $noreg: likely a DBG_VALUE we just inserted. 825ffd83dbSDimitry Andric if (MO.isReg() && MO.getReg().isValid() && 835ffd83dbSDimitry Andric MFI.isVRegStackified(MO.getReg())) { 845ffd83dbSDimitry Andric // Found a DBG_VALUE with a stackified register we will 855ffd83dbSDimitry Andric // change into a stack operand. 865ffd83dbSDimitry Andric // Search for register rather than assume it is on top (which it 875ffd83dbSDimitry Andric // typically is if it appears right after the def), since 885ffd83dbSDimitry Andric // DBG_VALUE's may shift under some circumstances. 895ffd83dbSDimitry Andric for (auto &Elem : reverse(Stack)) { 905ffd83dbSDimitry Andric if (MO.getReg() == Elem.Reg) { 915ffd83dbSDimitry Andric auto Depth = static_cast<unsigned>(&Elem - &Stack[0]); 925ffd83dbSDimitry Andric LLVM_DEBUG(dbgs() << "Debug Value VReg " << MO.getReg() 935ffd83dbSDimitry Andric << " -> Stack Relative " << Depth << "\n"); 945ffd83dbSDimitry Andric MO.ChangeToTargetIndex(WebAssembly::TI_OPERAND_STACK, Depth); 955ffd83dbSDimitry Andric // Save the DBG_VALUE instruction that defined this stackified 965ffd83dbSDimitry Andric // variable since later we need it to construct another one on 975ffd83dbSDimitry Andric // pop. 985ffd83dbSDimitry Andric Elem.DebugValue = &MI; 995ffd83dbSDimitry Andric break; 1005ffd83dbSDimitry Andric } 1015ffd83dbSDimitry Andric } 1025ffd83dbSDimitry Andric // If the Reg was not found, we have a DBG_VALUE outside of its 1035ffd83dbSDimitry Andric // def-use range, and we leave it unmodified as reg, which means 1045ffd83dbSDimitry Andric // it will be culled later. 1055ffd83dbSDimitry Andric } 1065ffd83dbSDimitry Andric } else { 1075ffd83dbSDimitry Andric // Track stack depth. 1085ffd83dbSDimitry Andric for (MachineOperand &MO : reverse(MI.explicit_uses())) { 1095ffd83dbSDimitry Andric if (MO.isReg() && MFI.isVRegStackified(MO.getReg())) { 1105ffd83dbSDimitry Andric auto Prev = Stack.back(); 1115ffd83dbSDimitry Andric Stack.pop_back(); 1125ffd83dbSDimitry Andric assert(Prev.Reg == MO.getReg() && 1135ffd83dbSDimitry Andric "WebAssemblyDebugFixup: Pop: Register not matched!"); 114*fe6060f1SDimitry Andric // We should not put a DBG_VALUE after a terminator; debug ranges 115*fe6060f1SDimitry Andric // are terminated at the end of a BB anyway. 116*fe6060f1SDimitry Andric if (Prev.DebugValue && !MI.isTerminator()) { 1175ffd83dbSDimitry Andric // This stackified reg is a variable that started life at 1185ffd83dbSDimitry Andric // Prev.DebugValue, so now that we're popping it we must insert 1195ffd83dbSDimitry Andric // a $noreg DBG_VALUE for the variable to end it, right after 1205ffd83dbSDimitry Andric // the current instruction. 1215ffd83dbSDimitry Andric BuildMI(*Prev.DebugValue->getParent(), std::next(MII), 122*fe6060f1SDimitry Andric Prev.DebugValue->getDebugLoc(), 123*fe6060f1SDimitry Andric TII->get(WebAssembly::DBG_VALUE), false, Register(), 124*fe6060f1SDimitry Andric Prev.DebugValue->getOperand(2).getMetadata(), 1255ffd83dbSDimitry Andric Prev.DebugValue->getOperand(3).getMetadata()); 1265ffd83dbSDimitry Andric } 1275ffd83dbSDimitry Andric } 1285ffd83dbSDimitry Andric } 1295ffd83dbSDimitry Andric for (MachineOperand &MO : MI.defs()) { 1305ffd83dbSDimitry Andric if (MO.isReg() && MFI.isVRegStackified(MO.getReg())) { 1315ffd83dbSDimitry Andric Stack.push_back({MO.getReg(), nullptr}); 1325ffd83dbSDimitry Andric } 1335ffd83dbSDimitry Andric } 1345ffd83dbSDimitry Andric } 1355ffd83dbSDimitry Andric } 1365ffd83dbSDimitry Andric assert(Stack.empty() && 1375ffd83dbSDimitry Andric "WebAssemblyDebugFixup: Stack not empty at end of basic block!"); 1385ffd83dbSDimitry Andric } 1395ffd83dbSDimitry Andric 1405ffd83dbSDimitry Andric return true; 1415ffd83dbSDimitry Andric } 142