Path: blob/main/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/DebugHandlerBase.cpp
35271 views
//===-- llvm/lib/CodeGen/AsmPrinter/DebugHandlerBase.cpp -------*- C++ -*--===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// Common functionality for different debug information format backends.9// LLVM currently supports DWARF and CodeView.10//11//===----------------------------------------------------------------------===//1213#include "llvm/CodeGen/DebugHandlerBase.h"14#include "llvm/CodeGen/AsmPrinter.h"15#include "llvm/CodeGen/MachineFunction.h"16#include "llvm/CodeGen/MachineInstr.h"17#include "llvm/CodeGen/MachineModuleInfo.h"18#include "llvm/CodeGen/TargetSubtargetInfo.h"19#include "llvm/IR/DebugInfo.h"20#include "llvm/IR/Module.h"21#include "llvm/MC/MCStreamer.h"22#include "llvm/Support/CommandLine.h"2324using namespace llvm;2526#define DEBUG_TYPE "dwarfdebug"2728/// If true, we drop variable location ranges which exist entirely outside the29/// variable's lexical scope instruction ranges.30static cl::opt<bool> TrimVarLocs("trim-var-locs", cl::Hidden, cl::init(true));3132std::optional<DbgVariableLocation>33DbgVariableLocation::extractFromMachineInstruction(34const MachineInstr &Instruction) {35DbgVariableLocation Location;36// Variables calculated from multiple locations can't be represented here.37if (Instruction.getNumDebugOperands() != 1)38return std::nullopt;39if (!Instruction.getDebugOperand(0).isReg())40return std::nullopt;41Location.Register = Instruction.getDebugOperand(0).getReg();42Location.FragmentInfo.reset();43// We only handle expressions generated by DIExpression::appendOffset,44// which doesn't require a full stack machine.45int64_t Offset = 0;46const DIExpression *DIExpr = Instruction.getDebugExpression();47auto Op = DIExpr->expr_op_begin();48// We can handle a DBG_VALUE_LIST iff it has exactly one location operand that49// appears exactly once at the start of the expression.50if (Instruction.isDebugValueList()) {51if (Instruction.getNumDebugOperands() == 1 &&52Op->getOp() == dwarf::DW_OP_LLVM_arg)53++Op;54else55return std::nullopt;56}57while (Op != DIExpr->expr_op_end()) {58switch (Op->getOp()) {59case dwarf::DW_OP_constu: {60int Value = Op->getArg(0);61++Op;62if (Op != DIExpr->expr_op_end()) {63switch (Op->getOp()) {64case dwarf::DW_OP_minus:65Offset -= Value;66break;67case dwarf::DW_OP_plus:68Offset += Value;69break;70default:71continue;72}73}74} break;75case dwarf::DW_OP_plus_uconst:76Offset += Op->getArg(0);77break;78case dwarf::DW_OP_LLVM_fragment:79Location.FragmentInfo = {Op->getArg(1), Op->getArg(0)};80break;81case dwarf::DW_OP_deref:82Location.LoadChain.push_back(Offset);83Offset = 0;84break;85default:86return std::nullopt;87}88++Op;89}9091// Do one final implicit DW_OP_deref if this was an indirect DBG_VALUE92// instruction.93// FIXME: Replace these with DIExpression.94if (Instruction.isIndirectDebugValue())95Location.LoadChain.push_back(Offset);9697return Location;98}99100DebugHandlerBase::DebugHandlerBase(AsmPrinter *A) : Asm(A), MMI(Asm->MMI) {}101102DebugHandlerBase::~DebugHandlerBase() = default;103104void DebugHandlerBase::beginModule(Module *M) {105if (M->debug_compile_units().empty())106Asm = nullptr;107}108109// Each LexicalScope has first instruction and last instruction to mark110// beginning and end of a scope respectively. Create an inverse map that list111// scopes starts (and ends) with an instruction. One instruction may start (or112// end) multiple scopes. Ignore scopes that are not reachable.113void DebugHandlerBase::identifyScopeMarkers() {114SmallVector<LexicalScope *, 4> WorkList;115WorkList.push_back(LScopes.getCurrentFunctionScope());116while (!WorkList.empty()) {117LexicalScope *S = WorkList.pop_back_val();118119const SmallVectorImpl<LexicalScope *> &Children = S->getChildren();120if (!Children.empty())121WorkList.append(Children.begin(), Children.end());122123if (S->isAbstractScope())124continue;125126for (const InsnRange &R : S->getRanges()) {127assert(R.first && "InsnRange does not have first instruction!");128assert(R.second && "InsnRange does not have second instruction!");129requestLabelBeforeInsn(R.first);130requestLabelAfterInsn(R.second);131}132}133}134135// Return Label preceding the instruction.136MCSymbol *DebugHandlerBase::getLabelBeforeInsn(const MachineInstr *MI) {137MCSymbol *Label = LabelsBeforeInsn.lookup(MI);138assert(Label && "Didn't insert label before instruction");139return Label;140}141142// Return Label immediately following the instruction.143MCSymbol *DebugHandlerBase::getLabelAfterInsn(const MachineInstr *MI) {144return LabelsAfterInsn.lookup(MI);145}146147/// If this type is derived from a base type then return base type size.148uint64_t DebugHandlerBase::getBaseTypeSize(const DIType *Ty) {149assert(Ty);150const DIDerivedType *DDTy = dyn_cast<DIDerivedType>(Ty);151if (!DDTy)152return Ty->getSizeInBits();153154unsigned Tag = DDTy->getTag();155156if (Tag != dwarf::DW_TAG_member && Tag != dwarf::DW_TAG_typedef &&157Tag != dwarf::DW_TAG_const_type && Tag != dwarf::DW_TAG_volatile_type &&158Tag != dwarf::DW_TAG_restrict_type && Tag != dwarf::DW_TAG_atomic_type &&159Tag != dwarf::DW_TAG_immutable_type &&160Tag != dwarf::DW_TAG_template_alias)161return DDTy->getSizeInBits();162163DIType *BaseType = DDTy->getBaseType();164165if (!BaseType)166return 0;167168// If this is a derived type, go ahead and get the base type, unless it's a169// reference then it's just the size of the field. Pointer types have no need170// of this since they're a different type of qualification on the type.171if (BaseType->getTag() == dwarf::DW_TAG_reference_type ||172BaseType->getTag() == dwarf::DW_TAG_rvalue_reference_type)173return Ty->getSizeInBits();174175return getBaseTypeSize(BaseType);176}177178bool DebugHandlerBase::isUnsignedDIType(const DIType *Ty) {179if (isa<DIStringType>(Ty)) {180// Some transformations (e.g. instcombine) may decide to turn a Fortran181// character object into an integer, and later ones (e.g. SROA) may182// further inject a constant integer in a llvm.dbg.value call to track183// the object's value. Here we trust the transformations are doing the184// right thing, and treat the constant as unsigned to preserve that value185// (i.e. avoid sign extension).186return true;187}188189if (auto *CTy = dyn_cast<DICompositeType>(Ty)) {190if (CTy->getTag() == dwarf::DW_TAG_enumeration_type) {191if (!(Ty = CTy->getBaseType()))192// FIXME: Enums without a fixed underlying type have unknown signedness193// here, leading to incorrectly emitted constants.194return false;195} else196// (Pieces of) aggregate types that get hacked apart by SROA may be197// represented by a constant. Encode them as unsigned bytes.198return true;199}200201if (auto *DTy = dyn_cast<DIDerivedType>(Ty)) {202dwarf::Tag T = (dwarf::Tag)Ty->getTag();203// Encode pointer constants as unsigned bytes. This is used at least for204// null pointer constant emission.205// FIXME: reference and rvalue_reference /probably/ shouldn't be allowed206// here, but accept them for now due to a bug in SROA producing bogus207// dbg.values.208if (T == dwarf::DW_TAG_pointer_type ||209T == dwarf::DW_TAG_ptr_to_member_type ||210T == dwarf::DW_TAG_reference_type ||211T == dwarf::DW_TAG_rvalue_reference_type)212return true;213assert(T == dwarf::DW_TAG_typedef || T == dwarf::DW_TAG_const_type ||214T == dwarf::DW_TAG_volatile_type ||215T == dwarf::DW_TAG_restrict_type || T == dwarf::DW_TAG_atomic_type ||216T == dwarf::DW_TAG_immutable_type ||217T == dwarf::DW_TAG_template_alias);218assert(DTy->getBaseType() && "Expected valid base type");219return isUnsignedDIType(DTy->getBaseType());220}221222auto *BTy = cast<DIBasicType>(Ty);223unsigned Encoding = BTy->getEncoding();224assert((Encoding == dwarf::DW_ATE_unsigned ||225Encoding == dwarf::DW_ATE_unsigned_char ||226Encoding == dwarf::DW_ATE_signed ||227Encoding == dwarf::DW_ATE_signed_char ||228Encoding == dwarf::DW_ATE_float || Encoding == dwarf::DW_ATE_UTF ||229Encoding == dwarf::DW_ATE_boolean ||230Encoding == dwarf::DW_ATE_complex_float ||231Encoding == dwarf::DW_ATE_signed_fixed ||232Encoding == dwarf::DW_ATE_unsigned_fixed ||233(Ty->getTag() == dwarf::DW_TAG_unspecified_type &&234Ty->getName() == "decltype(nullptr)")) &&235"Unsupported encoding");236return Encoding == dwarf::DW_ATE_unsigned ||237Encoding == dwarf::DW_ATE_unsigned_char ||238Encoding == dwarf::DW_ATE_UTF || Encoding == dwarf::DW_ATE_boolean ||239Encoding == llvm::dwarf::DW_ATE_unsigned_fixed ||240Ty->getTag() == dwarf::DW_TAG_unspecified_type;241}242243static bool hasDebugInfo(const MachineModuleInfo *MMI,244const MachineFunction *MF) {245if (!MMI->hasDebugInfo())246return false;247auto *SP = MF->getFunction().getSubprogram();248if (!SP)249return false;250assert(SP->getUnit());251auto EK = SP->getUnit()->getEmissionKind();252if (EK == DICompileUnit::NoDebug)253return false;254return true;255}256257void DebugHandlerBase::beginFunction(const MachineFunction *MF) {258PrevInstBB = nullptr;259260if (!Asm || !hasDebugInfo(MMI, MF)) {261skippedNonDebugFunction();262return;263}264265// Grab the lexical scopes for the function, if we don't have any of those266// then we're not going to be able to do anything.267LScopes.initialize(*MF);268if (LScopes.empty()) {269beginFunctionImpl(MF);270return;271}272273// Make sure that each lexical scope will have a begin/end label.274identifyScopeMarkers();275276// Calculate history for local variables.277assert(DbgValues.empty() && "DbgValues map wasn't cleaned!");278assert(DbgLabels.empty() && "DbgLabels map wasn't cleaned!");279calculateDbgEntityHistory(MF, Asm->MF->getSubtarget().getRegisterInfo(),280DbgValues, DbgLabels);281InstOrdering.initialize(*MF);282if (TrimVarLocs)283DbgValues.trimLocationRanges(*MF, LScopes, InstOrdering);284LLVM_DEBUG(DbgValues.dump(MF->getName()));285286// Request labels for the full history.287for (const auto &I : DbgValues) {288const auto &Entries = I.second;289if (Entries.empty())290continue;291292auto IsDescribedByReg = [](const MachineInstr *MI) {293return any_of(MI->debug_operands(),294[](auto &MO) { return MO.isReg() && MO.getReg(); });295};296297// The first mention of a function argument gets the CurrentFnBegin label,298// so arguments are visible when breaking at function entry.299//300// We do not change the label for values that are described by registers,301// as that could place them above their defining instructions. We should302// ideally not change the labels for constant debug values either, since303// doing that violates the ranges that are calculated in the history map.304// However, we currently do not emit debug values for constant arguments305// directly at the start of the function, so this code is still useful.306const DILocalVariable *DIVar =307Entries.front().getInstr()->getDebugVariable();308if (DIVar->isParameter() &&309getDISubprogram(DIVar->getScope())->describes(&MF->getFunction())) {310if (!IsDescribedByReg(Entries.front().getInstr()))311LabelsBeforeInsn[Entries.front().getInstr()] = Asm->getFunctionBegin();312if (Entries.front().getInstr()->getDebugExpression()->isFragment()) {313// Mark all non-overlapping initial fragments.314for (const auto *I = Entries.begin(); I != Entries.end(); ++I) {315if (!I->isDbgValue())316continue;317const DIExpression *Fragment = I->getInstr()->getDebugExpression();318if (std::any_of(Entries.begin(), I,319[&](DbgValueHistoryMap::Entry Pred) {320return Pred.isDbgValue() &&321Fragment->fragmentsOverlap(322Pred.getInstr()->getDebugExpression());323}))324break;325// The code that generates location lists for DWARF assumes that the326// entries' start labels are monotonically increasing, and since we327// don't change the label for fragments that are described by328// registers, we must bail out when encountering such a fragment.329if (IsDescribedByReg(I->getInstr()))330break;331LabelsBeforeInsn[I->getInstr()] = Asm->getFunctionBegin();332}333}334}335336for (const auto &Entry : Entries) {337if (Entry.isDbgValue())338requestLabelBeforeInsn(Entry.getInstr());339else340requestLabelAfterInsn(Entry.getInstr());341}342}343344// Ensure there is a symbol before DBG_LABEL.345for (const auto &I : DbgLabels) {346const MachineInstr *MI = I.second;347requestLabelBeforeInsn(MI);348}349350PrevInstLoc = DebugLoc();351PrevLabel = Asm->getFunctionBegin();352beginFunctionImpl(MF);353}354355void DebugHandlerBase::beginInstruction(const MachineInstr *MI) {356if (!Asm || !MMI->hasDebugInfo())357return;358359assert(CurMI == nullptr);360CurMI = MI;361362// Insert labels where requested.363DenseMap<const MachineInstr *, MCSymbol *>::iterator I =364LabelsBeforeInsn.find(MI);365366// No label needed.367if (I == LabelsBeforeInsn.end())368return;369370// Label already assigned.371if (I->second)372return;373374if (!PrevLabel) {375PrevLabel = MMI->getContext().createTempSymbol();376Asm->OutStreamer->emitLabel(PrevLabel);377}378I->second = PrevLabel;379}380381void DebugHandlerBase::endInstruction() {382if (!Asm || !MMI->hasDebugInfo())383return;384385assert(CurMI != nullptr);386// Don't create a new label after DBG_VALUE and other instructions that don't387// generate code.388if (!CurMI->isMetaInstruction()) {389PrevLabel = nullptr;390PrevInstBB = CurMI->getParent();391}392393DenseMap<const MachineInstr *, MCSymbol *>::iterator I =394LabelsAfterInsn.find(CurMI);395396// No label needed or label already assigned.397if (I == LabelsAfterInsn.end() || I->second) {398CurMI = nullptr;399return;400}401402// We need a label after this instruction. With basic block sections, just403// use the end symbol of the section if this is the last instruction of the404// section. This reduces the need for an additional label and also helps405// merging ranges.406if (CurMI->getParent()->isEndSection() && CurMI->getNextNode() == nullptr) {407PrevLabel = CurMI->getParent()->getEndSymbol();408} else if (!PrevLabel) {409PrevLabel = MMI->getContext().createTempSymbol();410Asm->OutStreamer->emitLabel(PrevLabel);411}412I->second = PrevLabel;413CurMI = nullptr;414}415416void DebugHandlerBase::endFunction(const MachineFunction *MF) {417if (Asm && hasDebugInfo(MMI, MF))418endFunctionImpl(MF);419DbgValues.clear();420DbgLabels.clear();421LabelsBeforeInsn.clear();422LabelsAfterInsn.clear();423InstOrdering.clear();424}425426void DebugHandlerBase::beginBasicBlockSection(const MachineBasicBlock &MBB) {427EpilogBeginBlock = nullptr;428if (!MBB.isEntryBlock())429PrevLabel = MBB.getSymbol();430}431432void DebugHandlerBase::endBasicBlockSection(const MachineBasicBlock &MBB) {433PrevLabel = nullptr;434}435436437