llvm-project/llvm/lib/CodeGen/SelectionDAG/SDNodeDbgValue.h

167 lines
5.3 KiB
C
Raw Normal View History

//===-- llvm/CodeGen/SDNodeDbgValue.h - SelectionDAG dbg_value --*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file declares the SDDbgValue class.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_LIB_CODEGEN_SELECTIONDAG_SDNODEDBGVALUE_H
#define LLVM_LIB_CODEGEN_SELECTIONDAG_SDNODEDBGVALUE_H
#include "llvm/IR/DebugLoc.h"
#include "llvm/Support/DataTypes.h"
#include <utility>
namespace llvm {
class DIVariable;
class DIExpression;
class SDNode;
class Value;
class raw_ostream;
2017-10-25 01:23:40 +08:00
/// Holds the information from a dbg_value node through SDISel.
/// We do not use SDValue here to avoid including its header.
class SDDbgValue {
public:
enum DbgValueKind {
2017-10-25 01:23:40 +08:00
SDNODE = 0, ///< Value is the result of an expression.
CONST = 1, ///< Value is a constant.
[SelectionDAG] Improve selection of DBG_VALUE using a PHI node result Summary: When building the selection DAG at ISel all PHI nodes are selected and lowered to Machine Instruction PHI nodes before we start to create any SDNodes. So there are no SDNodes for values produced by the PHI nodes. In the past when selecting a dbg.value intrinsic that uses the value produced by a PHI node we have been handling such dbg.value intrinsics as "dangling debug info". I.e. we have not created a SDDbgValue node directly, because there is no existing SDNode for the PHI result, instead we deferred the creationg of a SDDbgValue until we found the first use of the PHI result. The old solution had a couple of flaws. The position of the selected DBG_VALUE instruction would end up quite late in a basic block, and for example not directly after the PHI node as in the LLVM IR input. And in case there were no use at all in the basic block the dbg.value could be dropped completely. This patch introduces a new VREG kind of SDDbgValue nodes. It is similar to a SDNODE kind of node, but it refers directly to a virtual register and not a SDNode. When we do selection for a dbg.value that is using the result of a PHI node we can do a lookup of the virtual register directly (as it already is determined for the PHI node) and create a SDDbgValue node immediately instead of delaying the selection until we find a use. This should fix a problem with losing debug info at ISel as seen in PR37234 (https://bugs.llvm.org/show_bug.cgi?id=37234). It does not resolve PR37234 completely, because the debug info is dropped later on in the BranchFolder (see D46184). Reviewers: #debug-info, aprantl Reviewed By: #debug-info, aprantl Subscribers: rnk, gbedwell, aprantl, JDevlieghere, llvm-commits Differential Revision: https://reviews.llvm.org/D46129 llvm-svn: 331182
2018-04-30 22:37:39 +08:00
FRAMEIX = 2, ///< Value is contents of a stack location.
VREG = 3 ///< Value is a virtual register.
};
private:
union {
struct {
2017-10-25 01:23:40 +08:00
SDNode *Node; ///< Valid for expressions.
unsigned ResNo; ///< Valid for expressions.
} s;
2017-10-25 01:23:40 +08:00
const Value *Const; ///< Valid for constants.
unsigned FrameIx; ///< Valid for stack objects.
[SelectionDAG] Improve selection of DBG_VALUE using a PHI node result Summary: When building the selection DAG at ISel all PHI nodes are selected and lowered to Machine Instruction PHI nodes before we start to create any SDNodes. So there are no SDNodes for values produced by the PHI nodes. In the past when selecting a dbg.value intrinsic that uses the value produced by a PHI node we have been handling such dbg.value intrinsics as "dangling debug info". I.e. we have not created a SDDbgValue node directly, because there is no existing SDNode for the PHI result, instead we deferred the creationg of a SDDbgValue until we found the first use of the PHI result. The old solution had a couple of flaws. The position of the selected DBG_VALUE instruction would end up quite late in a basic block, and for example not directly after the PHI node as in the LLVM IR input. And in case there were no use at all in the basic block the dbg.value could be dropped completely. This patch introduces a new VREG kind of SDDbgValue nodes. It is similar to a SDNODE kind of node, but it refers directly to a virtual register and not a SDNode. When we do selection for a dbg.value that is using the result of a PHI node we can do a lookup of the virtual register directly (as it already is determined for the PHI node) and create a SDDbgValue node immediately instead of delaying the selection until we find a use. This should fix a problem with losing debug info at ISel as seen in PR37234 (https://bugs.llvm.org/show_bug.cgi?id=37234). It does not resolve PR37234 completely, because the debug info is dropped later on in the BranchFolder (see D46184). Reviewers: #debug-info, aprantl Reviewed By: #debug-info, aprantl Subscribers: rnk, gbedwell, aprantl, JDevlieghere, llvm-commits Differential Revision: https://reviews.llvm.org/D46129 llvm-svn: 331182
2018-04-30 22:37:39 +08:00
unsigned VReg; ///< Valid for registers.
} u;
DIVariable *Var;
DIExpression *Expr;
DebugLoc DL;
unsigned Order;
enum DbgValueKind kind;
bool IsIndirect;
bool Invalid = false;
bool Emitted = false;
public:
2017-10-25 01:23:40 +08:00
/// Constructor for non-constants.
SDDbgValue(DIVariable *Var, DIExpression *Expr, SDNode *N, unsigned R,
bool indir, DebugLoc dl, unsigned O)
: Var(Var), Expr(Expr), DL(std::move(dl)), Order(O), IsIndirect(indir) {
kind = SDNODE;
u.s.Node = N;
u.s.ResNo = R;
}
2017-10-25 01:23:40 +08:00
/// Constructor for constants.
SDDbgValue(DIVariable *Var, DIExpression *Expr, const Value *C, DebugLoc dl,
unsigned O)
: Var(Var), Expr(Expr), DL(std::move(dl)), Order(O), IsIndirect(false) {
kind = CONST;
u.Const = C;
}
[DebugInfo] LowerDbgDeclare: Add derefs when handling CallInst users LowerDbgDeclare inserts a dbg.value before each use of an address described by a dbg.declare. When inserting a dbg.value before a CallInst use, however, it fails to append DW_OP_deref to the DIExpression. The DW_OP_deref is needed to reflect the fact that a dbg.value describes a source variable directly (as opposed to a dbg.declare, which relies on pointer indirection). This patch adds in the DW_OP_deref where needed. This results in the correct values being shown during a debug session for a program compiled with ASan and optimizations (see https://reviews.llvm.org/D49520). Note that ConvertDebugDeclareToDebugValue is already correct -- no changes there were needed. One complication is that SelectionDAG is unable to distinguish between direct and indirect frame-index (FRAMEIX) SDDbgValues. This patch also fixes this long-standing issue in order to not regress integration tests relying on the incorrect assumption that all frame-index SDDbgValues are indirect. This is a necessary fix: the newly-added DW_OP_derefs cannot be lowered properly otherwise. Basically the fix prevents a direct SDDbgValue with DIExpression(DW_OP_deref) from being dereferenced twice by a debugger. There were a handful of tests relying on this incorrect "FRAMEIX => indirect" assumption which actually had incorrect DW_AT_locations: these are all fixed up in this patch. Testing: - check-llvm, and an end-to-end test using lldb to debug an optimized program. - Existing unit tests for DIExpression::appendToStack fully cover the new DIExpression::append utility. - check-debuginfo (the debug info integration tests) Differential Revision: https://reviews.llvm.org/D49454 llvm-svn: 338069
2018-07-27 04:56:53 +08:00
/// Constructor for virtual registers and frame indices.
SDDbgValue(DIVariable *Var, DIExpression *Expr, unsigned VRegOrFrameIdx,
bool IsIndirect, DebugLoc DL, unsigned Order,
enum DbgValueKind Kind)
: Var(Var), Expr(Expr), DL(DL), Order(Order), IsIndirect(IsIndirect) {
assert((Kind == VREG || Kind == FRAMEIX) &&
"Invalid SDDbgValue constructor");
kind = Kind;
if (kind == VREG)
u.VReg = VRegOrFrameIdx;
else
u.FrameIx = VRegOrFrameIdx;
[SelectionDAG] Improve selection of DBG_VALUE using a PHI node result Summary: When building the selection DAG at ISel all PHI nodes are selected and lowered to Machine Instruction PHI nodes before we start to create any SDNodes. So there are no SDNodes for values produced by the PHI nodes. In the past when selecting a dbg.value intrinsic that uses the value produced by a PHI node we have been handling such dbg.value intrinsics as "dangling debug info". I.e. we have not created a SDDbgValue node directly, because there is no existing SDNode for the PHI result, instead we deferred the creationg of a SDDbgValue until we found the first use of the PHI result. The old solution had a couple of flaws. The position of the selected DBG_VALUE instruction would end up quite late in a basic block, and for example not directly after the PHI node as in the LLVM IR input. And in case there were no use at all in the basic block the dbg.value could be dropped completely. This patch introduces a new VREG kind of SDDbgValue nodes. It is similar to a SDNODE kind of node, but it refers directly to a virtual register and not a SDNode. When we do selection for a dbg.value that is using the result of a PHI node we can do a lookup of the virtual register directly (as it already is determined for the PHI node) and create a SDDbgValue node immediately instead of delaying the selection until we find a use. This should fix a problem with losing debug info at ISel as seen in PR37234 (https://bugs.llvm.org/show_bug.cgi?id=37234). It does not resolve PR37234 completely, because the debug info is dropped later on in the BranchFolder (see D46184). Reviewers: #debug-info, aprantl Reviewed By: #debug-info, aprantl Subscribers: rnk, gbedwell, aprantl, JDevlieghere, llvm-commits Differential Revision: https://reviews.llvm.org/D46129 llvm-svn: 331182
2018-04-30 22:37:39 +08:00
}
2017-10-25 01:23:40 +08:00
/// Returns the kind.
DbgValueKind getKind() const { return kind; }
2017-10-25 01:23:40 +08:00
/// Returns the DIVariable pointer for the variable.
DIVariable *getVariable() const { return Var; }
Move the complex address expression out of DIVariable and into an extra argument of the llvm.dbg.declare/llvm.dbg.value intrinsics. Previously, DIVariable was a variable-length field that has an optional reference to a Metadata array consisting of a variable number of complex address expressions. In the case of OpPiece expressions this is wasting a lot of storage in IR, because when an aggregate type is, e.g., SROA'd into all of its n individual members, the IR will contain n copies of the DIVariable, all alike, only differing in the complex address reference at the end. By making the complex address into an extra argument of the dbg.value/dbg.declare intrinsics, all of the pieces can reference the same variable and the complex address expressions can be uniqued across the CU, too. Down the road, this will allow us to move other flags, such as "indirection" out of the DIVariable, too. The new intrinsics look like this: declare void @llvm.dbg.declare(metadata %storage, metadata %var, metadata %expr) declare void @llvm.dbg.value(metadata %storage, i64 %offset, metadata %var, metadata %expr) This patch adds a new LLVM-local tag to DIExpressions, so we can detect and pretty-print DIExpression metadata nodes. What this patch doesn't do: This patch does not touch the "Indirect" field in DIVariable; but moving that into the expression would be a natural next step. http://reviews.llvm.org/D4919 rdar://problem/17994491 Thanks to dblaikie and dexonsmith for reviewing this patch! Note: I accidentally committed a bogus older version of this patch previously. llvm-svn: 218787
2014-10-02 02:55:02 +08:00
2017-10-25 01:23:40 +08:00
/// Returns the DIExpression pointer for the expression.
DIExpression *getExpression() const { return Expr; }
2017-10-25 01:23:40 +08:00
/// Returns the SDNode* for a register ref
SDNode *getSDNode() const { assert (kind==SDNODE); return u.s.Node; }
2017-10-25 01:23:40 +08:00
/// Returns the ResNo for a register ref
unsigned getResNo() const { assert (kind==SDNODE); return u.s.ResNo; }
2017-10-25 01:23:40 +08:00
/// Returns the Value* for a constant
const Value *getConst() const { assert (kind==CONST); return u.Const; }
2017-10-25 01:23:40 +08:00
/// Returns the FrameIx for a stack object
unsigned getFrameIx() const { assert (kind==FRAMEIX); return u.FrameIx; }
[SelectionDAG] Improve selection of DBG_VALUE using a PHI node result Summary: When building the selection DAG at ISel all PHI nodes are selected and lowered to Machine Instruction PHI nodes before we start to create any SDNodes. So there are no SDNodes for values produced by the PHI nodes. In the past when selecting a dbg.value intrinsic that uses the value produced by a PHI node we have been handling such dbg.value intrinsics as "dangling debug info". I.e. we have not created a SDDbgValue node directly, because there is no existing SDNode for the PHI result, instead we deferred the creationg of a SDDbgValue until we found the first use of the PHI result. The old solution had a couple of flaws. The position of the selected DBG_VALUE instruction would end up quite late in a basic block, and for example not directly after the PHI node as in the LLVM IR input. And in case there were no use at all in the basic block the dbg.value could be dropped completely. This patch introduces a new VREG kind of SDDbgValue nodes. It is similar to a SDNODE kind of node, but it refers directly to a virtual register and not a SDNode. When we do selection for a dbg.value that is using the result of a PHI node we can do a lookup of the virtual register directly (as it already is determined for the PHI node) and create a SDDbgValue node immediately instead of delaying the selection until we find a use. This should fix a problem with losing debug info at ISel as seen in PR37234 (https://bugs.llvm.org/show_bug.cgi?id=37234). It does not resolve PR37234 completely, because the debug info is dropped later on in the BranchFolder (see D46184). Reviewers: #debug-info, aprantl Reviewed By: #debug-info, aprantl Subscribers: rnk, gbedwell, aprantl, JDevlieghere, llvm-commits Differential Revision: https://reviews.llvm.org/D46129 llvm-svn: 331182
2018-04-30 22:37:39 +08:00
/// Returns the Virtual Register for a VReg
unsigned getVReg() const { assert (kind==VREG); return u.VReg; }
2017-10-25 01:23:40 +08:00
/// Returns whether this is an indirect value.
bool isIndirect() const { return IsIndirect; }
2017-10-25 01:23:40 +08:00
/// Returns the DebugLoc.
DebugLoc getDebugLoc() const { return DL; }
2017-10-25 01:23:40 +08:00
/// Returns the SDNodeOrder. This is the order of the preceding node in the
/// input.
unsigned getOrder() const { return Order; }
2017-10-25 01:23:40 +08:00
/// setIsInvalidated / isInvalidated - Setter / getter of the "Invalidated"
/// property. A SDDbgValue is invalid if the SDNode that produces the value is
/// deleted.
void setIsInvalidated() { Invalid = true; }
bool isInvalidated() const { return Invalid; }
/// setIsEmitted / isEmitted - Getter/Setter for flag indicating that this
/// SDDbgValue has been emitted to an MBB.
void setIsEmitted() { Emitted = true; }
bool isEmitted() const { return Emitted; }
/// clearIsEmitted - Reset Emitted flag, for certain special cases where
/// dbg.addr is emitted twice.
void clearIsEmitted() { Emitted = false; }
LLVM_DUMP_METHOD void dump() const;
LLVM_DUMP_METHOD void print(raw_ostream &OS) const;
};
/// Holds the information from a dbg_label node through SDISel.
/// We do not use SDValue here to avoid including its header.
class SDDbgLabel {
MDNode *Label;
DebugLoc DL;
unsigned Order;
public:
SDDbgLabel(MDNode *Label, DebugLoc dl, unsigned O)
: Label(Label), DL(std::move(dl)), Order(O) {}
/// Returns the MDNode pointer for the label.
MDNode *getLabel() const { return Label; }
/// Returns the DebugLoc.
DebugLoc getDebugLoc() const { return DL; }
/// Returns the SDNodeOrder. This is the order of the preceding node in the
/// input.
unsigned getOrder() const { return Order; }
};
} // end llvm namespace
#endif