From a2afaca93280247206f426539050fcaa1c1887d3 Mon Sep 17 00:00:00 2001 From: Orlando Cazalet-Hyams Date: Thu, 4 Jul 2024 00:08:06 +0100 Subject: [PATCH 1/2] [NFC] Add fragment-getting functions to DbgRecord Patch [1/x] to fix structured bindings debug info in SROA. Copy getFragment and getFragmentOrEntireVariable from DbgVariableIntrinsic. Move FragmentInfo out of DIExpression and DebugInfoMetadata.h into a new file DbgVariableFragmentInfo.h so it can be included into DebugProgramInstruction.h without pulling in other includes and classes. These functions will be used in subsequent patches. Move FragmentInfo out of DIExpression --- .../include/llvm/IR/DbgVariableFragmentInfo.h | 45 +++++++++++++++++++ llvm/include/llvm/IR/DebugInfoMetadata.h | 25 +---------- .../include/llvm/IR/DebugProgramInstruction.h | 14 ++++++ llvm/lib/IR/DebugProgramInstruction.cpp | 4 ++ 4 files changed, 65 insertions(+), 23 deletions(-) create mode 100644 llvm/include/llvm/IR/DbgVariableFragmentInfo.h diff --git a/llvm/include/llvm/IR/DbgVariableFragmentInfo.h b/llvm/include/llvm/IR/DbgVariableFragmentInfo.h new file mode 100644 index 0000000000000..40326d5792f9f --- /dev/null +++ b/llvm/include/llvm/IR/DbgVariableFragmentInfo.h @@ -0,0 +1,45 @@ +//===- llvm/IR/DbgVariableFragmentInfo.h ------------------------*- 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 +// +//===----------------------------------------------------------------------===// +// +// Helper struct to describe a fragment of a debug variable. +// +//===----------------------------------------------------------------------===// +#ifndef LLVM_IR_DBGVARIABLEFRAGMENTINFO_H +#define LLVM_IR_DBGVARIABLEFRAGMENTINFO_H + +#include + +namespace llvm { +struct DbgVariableFragmentInfo { + DbgVariableFragmentInfo() = default; + DbgVariableFragmentInfo(uint64_t SizeInBits, uint64_t OffsetInBits) + : SizeInBits(SizeInBits), OffsetInBits(OffsetInBits) {} + uint64_t SizeInBits; + uint64_t OffsetInBits; + /// Return the index of the first bit of the fragment. + uint64_t startInBits() const { return OffsetInBits; } + /// Return the index of the bit after the end of the fragment, e.g. for + /// fragment offset=16 and size=32 return their sum, 48. + uint64_t endInBits() const { return OffsetInBits + SizeInBits; } + + /// Returns a zero-sized fragment if A and B don't intersect. + static DbgVariableFragmentInfo intersect(DbgVariableFragmentInfo A, + DbgVariableFragmentInfo B) { + // Don't use std::max or min to avoid including . + uint64_t StartInBits = + A.OffsetInBits > B.OffsetInBits ? A.OffsetInBits : B.OffsetInBits; + uint64_t EndInBits = + A.endInBits() < B.endInBits() ? A.endInBits() : B.endInBits(); + if (EndInBits <= StartInBits) + return {0, 0}; + return DbgVariableFragmentInfo(EndInBits - StartInBits, StartInBits); + } +}; +} // end namespace llvm + +#endif // LLVM_IR_DBGVARIABLEFRAGMENTINFO_H diff --git a/llvm/include/llvm/IR/DebugInfoMetadata.h b/llvm/include/llvm/IR/DebugInfoMetadata.h index 524945862e8d4..d953ce46efb30 100644 --- a/llvm/include/llvm/IR/DebugInfoMetadata.h +++ b/llvm/include/llvm/IR/DebugInfoMetadata.h @@ -21,6 +21,7 @@ #include "llvm/ADT/StringRef.h" #include "llvm/ADT/iterator_range.h" #include "llvm/IR/Constants.h" +#include "llvm/IR/DbgVariableFragmentInfo.h" #include "llvm/IR/Metadata.h" #include "llvm/IR/PseudoProbe.h" #include "llvm/Support/Casting.h" @@ -2886,29 +2887,7 @@ class DIExpression : public MDNode { /// Return whether there is exactly one operator and it is a DW_OP_deref; bool isDeref() const; - /// Holds the characteristics of one fragment of a larger variable. - struct FragmentInfo { - FragmentInfo() = default; - FragmentInfo(uint64_t SizeInBits, uint64_t OffsetInBits) - : SizeInBits(SizeInBits), OffsetInBits(OffsetInBits) {} - uint64_t SizeInBits; - uint64_t OffsetInBits; - /// Return the index of the first bit of the fragment. - uint64_t startInBits() const { return OffsetInBits; } - /// Return the index of the bit after the end of the fragment, e.g. for - /// fragment offset=16 and size=32 return their sum, 48. - uint64_t endInBits() const { return OffsetInBits + SizeInBits; } - - /// Returns a zero-sized fragment if A and B don't intersect. - static DIExpression::FragmentInfo intersect(DIExpression::FragmentInfo A, - DIExpression::FragmentInfo B) { - uint64_t StartInBits = std::max(A.OffsetInBits, B.OffsetInBits); - uint64_t EndInBits = std::min(A.endInBits(), B.endInBits()); - if (EndInBits <= StartInBits) - return {0, 0}; - return DIExpression::FragmentInfo(EndInBits - StartInBits, StartInBits); - } - }; + using FragmentInfo = DbgVariableFragmentInfo; /// Return the number of bits that have an active value, i.e. those that /// aren't known to be zero/sign (depending on the type of Var) and which diff --git a/llvm/include/llvm/IR/DebugProgramInstruction.h b/llvm/include/llvm/IR/DebugProgramInstruction.h index ed8081a3cad19..fd93dd9b89f7c 100644 --- a/llvm/include/llvm/IR/DebugProgramInstruction.h +++ b/llvm/include/llvm/IR/DebugProgramInstruction.h @@ -50,6 +50,7 @@ #include "llvm/ADT/ilist.h" #include "llvm/ADT/ilist_node.h" #include "llvm/ADT/iterator.h" +#include "llvm/IR/DbgVariableFragmentInfo.h" #include "llvm/IR/DebugLoc.h" #include "llvm/IR/Instruction.h" #include "llvm/IR/SymbolTableListTraits.h" @@ -460,6 +461,19 @@ class DbgVariableRecord : public DbgRecord, protected DebugValueUser { resetDebugValue(0, NewLocation); } + std::optional getFragment() const; + /// Get the FragmentInfo for the variable if it exists, otherwise return a + /// FragmentInfo that covers the entire variable if the variable size is + /// known, otherwise return a zero-sized fragment. + DbgVariableFragmentInfo getFragmentOrEntireVariable() const { + DbgVariableFragmentInfo VariableSlice(0, 0); + // Get the fragment or variable size, or zero. + if (auto Sz = getFragmentSizeInBits()) + VariableSlice.SizeInBits = *Sz; + if (auto Frag = getFragment()) + VariableSlice.OffsetInBits = Frag->OffsetInBits; + return VariableSlice; + } /// Get the size (in bits) of the variable, or fragment of the variable that /// is described. std::optional getFragmentSizeInBits() const; diff --git a/llvm/lib/IR/DebugProgramInstruction.cpp b/llvm/lib/IR/DebugProgramInstruction.cpp index 9a4926c81dca2..1711fd6943517 100644 --- a/llvm/lib/IR/DebugProgramInstruction.cpp +++ b/llvm/lib/IR/DebugProgramInstruction.cpp @@ -371,6 +371,10 @@ bool DbgVariableRecord::isKillLocation() const { any_of(location_ops(), [](Value *V) { return isa(V); }); } +std::optional DbgVariableRecord::getFragment() const { + return getExpression()->getFragmentInfo(); +} + std::optional DbgVariableRecord::getFragmentSizeInBits() const { if (auto Fragment = getExpression()->getFragmentInfo()) return Fragment->SizeInBits; From 18addf43d6af023ccf1adbacbe02f72ddd7e3072 Mon Sep 17 00:00:00 2001 From: Orlando Cazalet-Hyams Date: Mon, 8 Jul 2024 09:10:59 +0100 Subject: [PATCH 2/2] Update llvm/include/llvm/IR/DebugProgramInstruction.h Co-authored-by: Stephen Tozer --- llvm/include/llvm/IR/DebugProgramInstruction.h | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/llvm/include/llvm/IR/DebugProgramInstruction.h b/llvm/include/llvm/IR/DebugProgramInstruction.h index fd93dd9b89f7c..734a637a4a0ee 100644 --- a/llvm/include/llvm/IR/DebugProgramInstruction.h +++ b/llvm/include/llvm/IR/DebugProgramInstruction.h @@ -466,13 +466,11 @@ class DbgVariableRecord : public DbgRecord, protected DebugValueUser { /// FragmentInfo that covers the entire variable if the variable size is /// known, otherwise return a zero-sized fragment. DbgVariableFragmentInfo getFragmentOrEntireVariable() const { - DbgVariableFragmentInfo VariableSlice(0, 0); - // Get the fragment or variable size, or zero. - if (auto Sz = getFragmentSizeInBits()) - VariableSlice.SizeInBits = *Sz; if (auto Frag = getFragment()) - VariableSlice.OffsetInBits = Frag->OffsetInBits; - return VariableSlice; + return *Frag; + if (auto Sz = getVariable()->getSizeInBits()) + return {*Sz, 0}; + return {0, 0}; } /// Get the size (in bits) of the variable, or fragment of the variable that /// is described.