mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-26 04:32:44 +01:00
6523da3123
Originally landed in ddc2f1e3fb4 and reverted in d32deaab4d because of a Generic test objecting. That was fixed up in 013613964fd9. Original landing commit message follows: [DWARF] Location-less inlined variables should not have DW_TAG_variable Discussed in this thread: https://lists.llvm.org/pipermail/llvm-dev/2021-January/148139.html DwarfDebug::collectEntityInfo accidentally distinguishes between variable locations that never have a location specified, and variable locations that have an empty location specified. The latter leads to the creation of an empty variable referring to the abstract origin. Fix this by seeking a non-empty location before producing a concrete entity, to guarantee a DW_AT_location will be produced. Other loops in collectEntityInfo and endFunctionImpl take care of examining the retainedNodes collection and ensuring optimised-out variables are created. Differential Revision: https://reviews.llvm.org/D95617
158 lines
5.5 KiB
C++
158 lines
5.5 KiB
C++
//===- llvm/CodeGen/DbgEntityHistoryCalculator.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
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#ifndef LLVM_CODEGEN_DBGENTITYHISTORYCALCULATOR_H
|
|
#define LLVM_CODEGEN_DBGENTITYHISTORYCALCULATOR_H
|
|
|
|
#include "llvm/ADT/MapVector.h"
|
|
#include "llvm/ADT/PointerIntPair.h"
|
|
#include "llvm/ADT/SmallVector.h"
|
|
#include "llvm/CodeGen/LexicalScopes.h"
|
|
#include <utility>
|
|
|
|
namespace llvm {
|
|
|
|
class DILocalVariable;
|
|
class DILocation;
|
|
class DINode;
|
|
class MachineFunction;
|
|
class MachineInstr;
|
|
class TargetRegisterInfo;
|
|
|
|
/// Record instruction ordering so we can query their relative positions within
|
|
/// a function. Meta instructions are given the same ordinal as the preceding
|
|
/// non-meta instruction. Class state is invalid if MF is modified after
|
|
/// calling initialize.
|
|
class InstructionOrdering {
|
|
public:
|
|
void initialize(const MachineFunction &MF);
|
|
void clear() { InstNumberMap.clear(); }
|
|
|
|
/// Check if instruction \p A comes before \p B, where \p A and \p B both
|
|
/// belong to the MachineFunction passed to initialize().
|
|
bool isBefore(const MachineInstr *A, const MachineInstr *B) const;
|
|
|
|
private:
|
|
/// Each instruction is assigned an order number.
|
|
DenseMap<const MachineInstr *, unsigned> InstNumberMap;
|
|
};
|
|
|
|
/// For each user variable, keep a list of instruction ranges where this
|
|
/// variable is accessible. The variables are listed in order of appearance.
|
|
class DbgValueHistoryMap {
|
|
public:
|
|
/// Index in the entry vector.
|
|
typedef size_t EntryIndex;
|
|
|
|
/// Special value to indicate that an entry is valid until the end of the
|
|
/// function.
|
|
static const EntryIndex NoEntry = std::numeric_limits<EntryIndex>::max();
|
|
|
|
/// Specifies a change in a variable's debug value history.
|
|
///
|
|
/// There exist two types of entries:
|
|
///
|
|
/// * Debug value entry:
|
|
///
|
|
/// A new debug value becomes live. If the entry's \p EndIndex is \p NoEntry,
|
|
/// the value is valid until the end of the function. For other values, the
|
|
/// index points to the entry in the entry vector that ends this debug
|
|
/// value. The ending entry can either be an overlapping debug value, or
|
|
/// an instruction that clobbers the value.
|
|
///
|
|
/// * Clobbering entry:
|
|
///
|
|
/// This entry's instruction clobbers one or more preceding
|
|
/// register-described debug values that have their end index
|
|
/// set to this entry's position in the entry vector.
|
|
class Entry {
|
|
friend DbgValueHistoryMap;
|
|
|
|
public:
|
|
enum EntryKind { DbgValue, Clobber };
|
|
|
|
Entry(const MachineInstr *Instr, EntryKind Kind)
|
|
: Instr(Instr, Kind), EndIndex(NoEntry) {}
|
|
|
|
const MachineInstr *getInstr() const { return Instr.getPointer(); }
|
|
EntryIndex getEndIndex() const { return EndIndex; }
|
|
EntryKind getEntryKind() const { return Instr.getInt(); }
|
|
|
|
bool isClobber() const { return getEntryKind() == Clobber; }
|
|
bool isDbgValue() const { return getEntryKind() == DbgValue; }
|
|
bool isClosed() const { return EndIndex != NoEntry; }
|
|
|
|
void endEntry(EntryIndex EndIndex);
|
|
|
|
private:
|
|
PointerIntPair<const MachineInstr *, 1, EntryKind> Instr;
|
|
EntryIndex EndIndex;
|
|
};
|
|
using Entries = SmallVector<Entry, 4>;
|
|
using InlinedEntity = std::pair<const DINode *, const DILocation *>;
|
|
using EntriesMap = MapVector<InlinedEntity, Entries>;
|
|
|
|
private:
|
|
EntriesMap VarEntries;
|
|
|
|
public:
|
|
bool startDbgValue(InlinedEntity Var, const MachineInstr &MI,
|
|
EntryIndex &NewIndex);
|
|
EntryIndex startClobber(InlinedEntity Var, const MachineInstr &MI);
|
|
|
|
Entry &getEntry(InlinedEntity Var, EntryIndex Index) {
|
|
auto &Entries = VarEntries[Var];
|
|
return Entries[Index];
|
|
}
|
|
|
|
/// Test whether a vector of entries features any non-empty locations. It
|
|
/// could have no entries, or only DBG_VALUE $noreg entries.
|
|
bool hasNonEmptyLocation(const Entries &Entries) const;
|
|
|
|
/// Drop location ranges which exist entirely outside each variable's scope.
|
|
void trimLocationRanges(const MachineFunction &MF, LexicalScopes &LScopes,
|
|
const InstructionOrdering &Ordering);
|
|
bool empty() const { return VarEntries.empty(); }
|
|
void clear() { VarEntries.clear(); }
|
|
EntriesMap::const_iterator begin() const { return VarEntries.begin(); }
|
|
EntriesMap::const_iterator end() const { return VarEntries.end(); }
|
|
|
|
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
|
|
LLVM_DUMP_METHOD void dump() const;
|
|
#endif
|
|
};
|
|
|
|
/// For each inlined instance of a source-level label, keep the corresponding
|
|
/// DBG_LABEL instruction. The DBG_LABEL instruction could be used to generate
|
|
/// a temporary (assembler) label before it.
|
|
class DbgLabelInstrMap {
|
|
public:
|
|
using InlinedEntity = std::pair<const DINode *, const DILocation *>;
|
|
using InstrMap = MapVector<InlinedEntity, const MachineInstr *>;
|
|
|
|
private:
|
|
InstrMap LabelInstr;
|
|
|
|
public:
|
|
void addInstr(InlinedEntity Label, const MachineInstr &MI);
|
|
|
|
bool empty() const { return LabelInstr.empty(); }
|
|
void clear() { LabelInstr.clear(); }
|
|
InstrMap::const_iterator begin() const { return LabelInstr.begin(); }
|
|
InstrMap::const_iterator end() const { return LabelInstr.end(); }
|
|
};
|
|
|
|
void calculateDbgEntityHistory(const MachineFunction *MF,
|
|
const TargetRegisterInfo *TRI,
|
|
DbgValueHistoryMap &DbgValues,
|
|
DbgLabelInstrMap &DbgLabels);
|
|
|
|
} // end namespace llvm
|
|
|
|
#endif // LLVM_CODEGEN_DBGENTITYHISTORYCALCULATOR_H
|