diff --git a/llvm/lib/CodeGen/LiveDebugValues/InstrRefBasedImpl.h b/llvm/lib/CodeGen/LiveDebugValues/InstrRefBasedImpl.h --- a/llvm/lib/CodeGen/LiveDebugValues/InstrRefBasedImpl.h +++ b/llvm/lib/CodeGen/LiveDebugValues/InstrRefBasedImpl.h @@ -199,26 +199,35 @@ /// the value, and Boolean of whether or not it's indirect. class DbgValueProperties { public: - DbgValueProperties(const DIExpression *DIExpr, bool Indirect) - : DIExpr(DIExpr), Indirect(Indirect) {} + DbgValueProperties(const DIExpression *DIExpr, bool Indirect, bool IsVariadic) + : DIExpr(DIExpr), Indirect(Indirect), IsVariadic(IsVariadic) {} /// Extract properties from an existing DBG_VALUE instruction. DbgValueProperties(const MachineInstr &MI) { assert(MI.isDebugValue()); + assert(MI.getDebugExpression()->getNumLocationOperands() == 0 || + MI.isDebugValueList() || MI.isUndefDebugValue()); + IsVariadic = MI.isDebugValueList(); DIExpr = MI.getDebugExpression(); - Indirect = MI.getOperand(1).isImm(); + Indirect = MI.isDebugOffsetImm(); } bool operator==(const DbgValueProperties &Other) const { - return std::tie(DIExpr, Indirect) == std::tie(Other.DIExpr, Other.Indirect); + return std::tie(DIExpr, Indirect, IsVariadic) == + std::tie(Other.DIExpr, Other.Indirect, Other.IsVariadic); } bool operator!=(const DbgValueProperties &Other) const { return !(*this == Other); } + unsigned getLocationOpCount() const { + return IsVariadic ? DIExpr->getNumLocationOperands() : 1; + } + const DIExpression *DIExpr; bool Indirect; + bool IsVariadic; }; /// Class recording the (high level) _value_ of a variable. Identifies either @@ -704,7 +713,7 @@ public: VLocTracker(const OverlapMap &O, const DIExpression *EmptyExpr) - : OverlappingFragments(O), EmptyProperties(EmptyExpr, false) {} + : OverlappingFragments(O), EmptyProperties(EmptyExpr, false, false) {} void defVar(const MachineInstr &MI, const DbgValueProperties &Properties, Optional ID) { diff --git a/llvm/lib/CodeGen/LiveDebugValues/InstrRefBasedImpl.cpp b/llvm/lib/CodeGen/LiveDebugValues/InstrRefBasedImpl.cpp --- a/llvm/lib/CodeGen/LiveDebugValues/InstrRefBasedImpl.cpp +++ b/llvm/lib/CodeGen/LiveDebugValues/InstrRefBasedImpl.cpp @@ -440,6 +440,10 @@ if (!ShouldEmitDebugEntryValues) return false; + // We don't currently emit entry values for DBG_VALUE_LISTs. + if (Prop.IsVariadic) + return false; + // Is the variable appropriate for entry values (i.e., is a parameter). if (!isEntryValueVariable(Var, Prop.DIExpr)) return false; @@ -454,7 +458,8 @@ Register Reg = MTracker->LocIdxToLocID[Num.getLoc()]; MachineOperand MO = MachineOperand::CreateReg(Reg, false); - PendingDbgValues.push_back(emitMOLoc(MO, Var, {NewExpr, Prop.Indirect})); + PendingDbgValues.push_back( + emitMOLoc(MO, Var, {NewExpr, Prop.Indirect, Prop.IsVariadic})); return true; } @@ -464,7 +469,7 @@ MI.getDebugLoc()->getInlinedAt()); DbgValueProperties Properties(MI); - const MachineOperand &MO = MI.getOperand(0); + const MachineOperand &MO = MI.getDebugOperand(0); // Ignore non-register locations, we don't transfer those. if (!MO.isReg() || MO.getReg() == 0) { @@ -848,13 +853,38 @@ DebugLoc DL = DILocation::get(Var.getVariable()->getContext(), 0, 0, Var.getVariable()->getScope(), const_cast(Var.getInlinedAt())); - auto MIB = BuildMI(MF, DL, TII.get(TargetOpcode::DBG_VALUE)); + + const MCInstrDesc &Desc = Properties.IsVariadic + ? TII.get(TargetOpcode::DBG_VALUE_LIST) + : TII.get(TargetOpcode::DBG_VALUE); + + auto GetRegOp = [](unsigned Reg) -> MachineOperand { + return MachineOperand::CreateReg( + /* Reg */ Reg, /* isDef */ false, /* isImp */ false, + /* isKill */ false, /* isDead */ false, + /* isUndef */ false, /* isEarlyClobber */ false, + /* SubReg */ 0, /* isDebug */ true); + }; + + SmallVector MOs; + + auto EmitUndef = [&]() { + MOs.clear(); + MOs.assign(Properties.getLocationOpCount(), GetRegOp(0)); + return BuildMI(MF, DL, Desc, false, MOs, Var.getVariable(), + Properties.DIExpr); + }; + + // Only 1 location is currently supported. + if (Properties.IsVariadic && Properties.getLocationOpCount() != 1) + return EmitUndef(); + + bool Indirect = Properties.Indirect; const DIExpression *Expr = Properties.DIExpr; if (!MLoc) { // No location -> DBG_VALUE $noreg - MIB.addReg(0); - MIB.addReg(0); + return EmitUndef(); } else if (LocIdxToLocID[*MLoc] >= NumRegs) { unsigned LocID = LocIdxToLocID[*MLoc]; SpillLocationNo SpillID = locIDToSpill(LocID); @@ -871,7 +901,7 @@ if (Offset == 0) { const SpillLoc &Spill = SpillLocs[SpillID.id()]; unsigned Base = Spill.SpillBase; - MIB.addReg(Base); + MOs.push_back(GetRegOp(Base)); // There are several ways we can dereference things, and several inputs // to consider: @@ -910,7 +940,6 @@ Expr = TRI.prependOffsetExpression( Expr, DIExpression::ApplyOffset | DIExpression::DerefAfter, Spill.SpillOffset); - MIB.addImm(0); } else if (UseDerefSize) { // We're loading a value off the stack that's not the same size as the // variable. Add / subtract stack offset, explicitly deref with a size, @@ -920,7 +949,6 @@ Expr = DIExpression::prependOpcodes(Expr, Ops, true); unsigned Flags = DIExpression::StackValue | DIExpression::ApplyOffset; Expr = TRI.prependOffsetExpression(Expr, Flags, Spill.SpillOffset); - MIB.addReg(0); } else if (Expr->isComplex()) { // A variable with no size ambiguity, but with extra elements in it's // expression. Manually dereference the stack location. @@ -928,34 +956,26 @@ Expr = TRI.prependOffsetExpression( Expr, DIExpression::ApplyOffset | DIExpression::DerefAfter, Spill.SpillOffset); - MIB.addReg(0); } else { // A plain value that has been spilt to the stack, with no further // context. Request a location expression, marking the DBG_VALUE as // IsIndirect. Expr = TRI.prependOffsetExpression(Expr, DIExpression::ApplyOffset, Spill.SpillOffset); - MIB.addImm(0); + Indirect = true; } } else { // This is a stack location with a weird subregister offset: emit an undef // DBG_VALUE instead. - MIB.addReg(0); - MIB.addReg(0); + return EmitUndef(); } } else { // Non-empty, non-stack slot, must be a plain register. unsigned LocID = LocIdxToLocID[*MLoc]; - MIB.addReg(LocID); - if (Properties.Indirect) - MIB.addImm(0); - else - MIB.addReg(0); + MOs.push_back(GetRegOp(LocID)); } - MIB.addMetadata(Var.getVariable()); - MIB.addMetadata(Expr); - return MIB; + return BuildMI(MF, DL, Desc, Indirect, MOs, Var.getVariable(), Expr); } /// Default construct and initialize the pass. @@ -1050,7 +1070,7 @@ return true; } - const MachineOperand &MO = MI.getOperand(0); + const MachineOperand &MO = MI.getDebugOperand(0); // MLocTracker needs to know that this register is read, even if it's only // read by a debug inst. @@ -1068,9 +1088,8 @@ VTracker->defVar(MI, Properties, MTracker->readReg(MO.getReg())); else VTracker->defVar(MI, Properties, None); - } else if (MI.getOperand(0).isImm() || MI.getOperand(0).isFPImm() || - MI.getOperand(0).isCImm()) { - VTracker->defVar(MI, MI.getOperand(0)); + } else if (MO.isImm() || MO.isFPImm() || MO.isCImm()) { + VTracker->defVar(MI, MO); } } @@ -1254,7 +1273,7 @@ // it. The rest of this LiveDebugValues implementation acts exactly the same // for DBG_INSTR_REFs as DBG_VALUEs (just, the former can refer to values that // aren't immediately available). - DbgValueProperties Properties(Expr, false); + DbgValueProperties Properties(Expr, false, false); if (VTracker) VTracker->defVar(MI, Properties, NewID); @@ -1294,7 +1313,7 @@ // later instruction in this block, this is a block-local use-before-def. if (!FoundLoc && NewID && NewID->getBlock() == CurBB && NewID->getInst() > CurInst) - TTracker->addUseBeforeDef(V, {MI.getDebugExpression(), false}, *NewID); + TTracker->addUseBeforeDef(V, {MI.getDebugExpression(), false, false}, *NewID); // Produce a DBG_VALUE representing what this DBG_INSTR_REF meant. // This DBG_VALUE is potentially a $noreg / undefined location, if @@ -2647,7 +2666,7 @@ // Initialize all values to start as NoVals. This signifies "it's live // through, but we don't know what it is". - DbgValueProperties EmptyProperties(EmptyExpr, false); + DbgValueProperties EmptyProperties(EmptyExpr, false, false); for (unsigned int I = 0; I < NumBlocks; ++I) { DbgValue EmptyDbgValue(I, EmptyProperties, DbgValue::NoVal); LiveIns.push_back(EmptyDbgValue);