2009-05-15 17:23:25 +08:00
|
|
|
//===-- llvm/CodeGen/DwarfDebug.cpp - Dwarf Debug Framework ---------------===//
|
|
|
|
//
|
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
|
|
|
// This file contains support for writing dwarf debug info into asm files.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
2010-03-09 08:39:24 +08:00
|
|
|
|
2009-08-29 07:24:31 +08:00
|
|
|
#define DEBUG_TYPE "dwarfdebug"
|
2009-05-15 17:23:25 +08:00
|
|
|
#include "DwarfDebug.h"
|
2010-04-05 13:24:55 +08:00
|
|
|
#include "DIE.h"
|
2013-08-09 07:45:55 +08:00
|
|
|
#include "DIEHash.h"
|
2011-11-07 17:24:32 +08:00
|
|
|
#include "DwarfAccelTable.h"
|
2013-12-03 03:33:15 +08:00
|
|
|
#include "DwarfUnit.h"
|
2012-12-04 00:50:05 +08:00
|
|
|
#include "llvm/ADT/STLExtras.h"
|
|
|
|
#include "llvm/ADT/Statistic.h"
|
|
|
|
#include "llvm/ADT/StringExtras.h"
|
|
|
|
#include "llvm/ADT/Triple.h"
|
|
|
|
#include "llvm/CodeGen/MachineFunction.h"
|
|
|
|
#include "llvm/CodeGen/MachineModuleInfo.h"
|
2012-06-29 16:32:07 +08:00
|
|
|
#include "llvm/DIBuilder.h"
|
2012-12-04 00:50:05 +08:00
|
|
|
#include "llvm/DebugInfo.h"
|
2013-01-02 19:36:10 +08:00
|
|
|
#include "llvm/IR/Constants.h"
|
|
|
|
#include "llvm/IR/DataLayout.h"
|
|
|
|
#include "llvm/IR/Instructions.h"
|
|
|
|
#include "llvm/IR/Module.h"
|
2010-03-09 09:58:53 +08:00
|
|
|
#include "llvm/MC/MCAsmInfo.h"
|
2009-08-01 02:48:30 +08:00
|
|
|
#include "llvm/MC/MCSection.h"
|
2009-08-19 13:49:37 +08:00
|
|
|
#include "llvm/MC/MCStreamer.h"
|
2010-03-09 09:58:53 +08:00
|
|
|
#include "llvm/MC/MCSymbol.h"
|
2010-04-28 03:46:33 +08:00
|
|
|
#include "llvm/Support/CommandLine.h"
|
2009-10-13 14:47:08 +08:00
|
|
|
#include "llvm/Support/Debug.h"
|
2013-08-21 14:13:34 +08:00
|
|
|
#include "llvm/Support/Dwarf.h"
|
2009-10-13 14:47:08 +08:00
|
|
|
#include "llvm/Support/ErrorHandling.h"
|
2010-01-23 06:09:00 +08:00
|
|
|
#include "llvm/Support/FormattedStream.h"
|
2013-07-27 01:02:41 +08:00
|
|
|
#include "llvm/Support/MD5.h"
|
2010-11-30 02:16:10 +08:00
|
|
|
#include "llvm/Support/Path.h"
|
2012-12-04 00:50:05 +08:00
|
|
|
#include "llvm/Support/Timer.h"
|
|
|
|
#include "llvm/Support/ValueHandle.h"
|
|
|
|
#include "llvm/Target/TargetFrameLowering.h"
|
|
|
|
#include "llvm/Target/TargetLoweringObjectFile.h"
|
|
|
|
#include "llvm/Target/TargetMachine.h"
|
|
|
|
#include "llvm/Target/TargetOptions.h"
|
|
|
|
#include "llvm/Target/TargetRegisterInfo.h"
|
2009-05-15 17:23:25 +08:00
|
|
|
using namespace llvm;
|
|
|
|
|
2013-07-24 06:16:41 +08:00
|
|
|
static cl::opt<bool>
|
|
|
|
DisableDebugInfoPrinting("disable-debug-info-print", cl::Hidden,
|
|
|
|
cl::desc("Disable debug info printing"));
|
2010-04-28 03:46:33 +08:00
|
|
|
|
2013-07-24 06:16:41 +08:00
|
|
|
static cl::opt<bool> UnknownLocations(
|
|
|
|
"use-unknown-locations", cl::Hidden,
|
|
|
|
cl::desc("Make an absence of debug location information explicit."),
|
|
|
|
cl::init(false));
|
2010-05-07 09:08:53 +08:00
|
|
|
|
2013-11-19 17:04:36 +08:00
|
|
|
static cl::opt<bool> GenerateCUHash("generate-cu-hash", cl::Hidden,
|
|
|
|
cl::desc("Add the CU hash as the dwo_id."),
|
|
|
|
cl::init(false));
|
2013-08-13 09:21:55 +08:00
|
|
|
|
2013-09-13 08:35:05 +08:00
|
|
|
static cl::opt<bool>
|
|
|
|
GenerateGnuPubSections("generate-gnu-dwarf-pub-sections", cl::Hidden,
|
|
|
|
cl::desc("Generate GNU-style pubnames and pubtypes"),
|
|
|
|
cl::init(false));
|
|
|
|
|
2012-08-24 06:36:40 +08:00
|
|
|
namespace {
|
2013-07-24 06:16:41 +08:00
|
|
|
enum DefaultOnOff {
|
|
|
|
Default,
|
|
|
|
Enable,
|
|
|
|
Disable
|
|
|
|
};
|
2012-08-24 06:36:40 +08:00
|
|
|
}
|
2011-11-07 17:24:32 +08:00
|
|
|
|
2013-07-24 06:16:41 +08:00
|
|
|
static cl::opt<DefaultOnOff>
|
|
|
|
DwarfAccelTables("dwarf-accel-tables", cl::Hidden,
|
|
|
|
cl::desc("Output prototype dwarf accelerator tables."),
|
|
|
|
cl::values(clEnumVal(Default, "Default for platform"),
|
|
|
|
clEnumVal(Enable, "Enabled"),
|
|
|
|
clEnumVal(Disable, "Disabled"), clEnumValEnd),
|
|
|
|
cl::init(Default));
|
2012-08-24 06:36:40 +08:00
|
|
|
|
2013-07-24 06:16:41 +08:00
|
|
|
static cl::opt<DefaultOnOff>
|
|
|
|
SplitDwarf("split-dwarf", cl::Hidden,
|
2013-12-05 07:24:28 +08:00
|
|
|
cl::desc("Output DWARF5 split debug info."),
|
2013-07-24 06:16:41 +08:00
|
|
|
cl::values(clEnumVal(Default, "Default for platform"),
|
|
|
|
clEnumVal(Enable, "Enabled"),
|
|
|
|
clEnumVal(Disable, "Disabled"), clEnumValEnd),
|
|
|
|
cl::init(Default));
|
2012-11-13 06:22:20 +08:00
|
|
|
|
2013-08-20 05:07:38 +08:00
|
|
|
static cl::opt<DefaultOnOff>
|
2013-08-27 07:24:35 +08:00
|
|
|
DwarfPubSections("generate-dwarf-pub-sections", cl::Hidden,
|
|
|
|
cl::desc("Generate DWARF pubnames and pubtypes sections"),
|
|
|
|
cl::values(clEnumVal(Default, "Default for platform"),
|
|
|
|
clEnumVal(Enable, "Enabled"),
|
|
|
|
clEnumVal(Disable, "Disabled"), clEnumValEnd),
|
|
|
|
cl::init(Default));
|
2013-08-20 05:07:38 +08:00
|
|
|
|
2013-11-22 07:46:41 +08:00
|
|
|
static cl::opt<unsigned>
|
|
|
|
DwarfVersionNumber("dwarf-version", cl::Hidden,
|
2013-12-10 07:32:48 +08:00
|
|
|
cl::desc("Generate DWARF for dwarf version."), cl::init(0));
|
2013-11-22 07:46:41 +08:00
|
|
|
|
2013-12-20 12:16:18 +08:00
|
|
|
static cl::opt<bool>
|
|
|
|
DwarfCURanges("generate-dwarf-cu-ranges", cl::Hidden,
|
|
|
|
cl::desc("Generate DW_AT_ranges for compile units"),
|
|
|
|
cl::init(false));
|
|
|
|
|
2013-08-24 20:54:27 +08:00
|
|
|
static const char *const DWARFGroupName = "DWARF Emission";
|
|
|
|
static const char *const DbgTimerName = "DWARF Debug Writer";
|
2010-04-07 17:28:04 +08:00
|
|
|
|
2009-05-15 17:23:25 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
namespace llvm {
|
|
|
|
|
2013-10-09 03:07:44 +08:00
|
|
|
/// resolve - Look in the DwarfDebug map for the MDNode that
|
|
|
|
/// corresponds to the reference.
|
2013-11-19 17:04:36 +08:00
|
|
|
template <typename T> T DbgVariable::resolve(DIRef<T> Ref) const {
|
2013-10-09 03:07:44 +08:00
|
|
|
return DD->resolve(Ref);
|
|
|
|
}
|
|
|
|
|
2011-07-29 11:49:23 +08:00
|
|
|
DIType DbgVariable::getType() const {
|
2011-04-13 06:53:02 +08:00
|
|
|
DIType Ty = Var.getType();
|
|
|
|
// FIXME: isBlockByrefVariable should be reformulated in terms of complex
|
|
|
|
// addresses instead.
|
|
|
|
if (Var.isBlockByrefVariable()) {
|
|
|
|
/* Byref variables, in Blocks, are declared by the programmer as
|
|
|
|
"SomeType VarName;", but the compiler creates a
|
|
|
|
__Block_byref_x_VarName struct, and gives the variable VarName
|
|
|
|
either the struct, or a pointer to the struct, as its type. This
|
|
|
|
is necessary for various behind-the-scenes things the compiler
|
|
|
|
needs to do with by-reference variables in blocks.
|
2012-11-20 06:42:10 +08:00
|
|
|
|
2011-04-13 06:53:02 +08:00
|
|
|
However, as far as the original *programmer* is concerned, the
|
|
|
|
variable should still have type 'SomeType', as originally declared.
|
2012-11-20 06:42:10 +08:00
|
|
|
|
2011-04-13 06:53:02 +08:00
|
|
|
The following function dives into the __Block_byref_x_VarName
|
|
|
|
struct to find the original type of the variable. This will be
|
|
|
|
passed back to the code generating the type for the Debug
|
|
|
|
Information Entry for the variable 'VarName'. 'VarName' will then
|
|
|
|
have the original type 'SomeType' in its debug information.
|
2012-11-20 06:42:10 +08:00
|
|
|
|
2011-04-13 06:53:02 +08:00
|
|
|
The original type 'SomeType' will be the type of the field named
|
|
|
|
'VarName' inside the __Block_byref_x_VarName struct.
|
2012-11-20 06:42:10 +08:00
|
|
|
|
2011-04-13 06:53:02 +08:00
|
|
|
NOTE: In order for this to not completely fail on the debugger
|
|
|
|
side, the Debug Information Entry for the variable VarName needs to
|
|
|
|
have a DW_AT_location that tells the debugger how to unwind through
|
|
|
|
the pointers and __Block_byref_x_VarName struct to find the actual
|
|
|
|
value of the variable. The function addBlockByrefType does this. */
|
|
|
|
DIType subType = Ty;
|
2013-08-08 09:41:00 +08:00
|
|
|
uint16_t tag = Ty.getTag();
|
2012-11-20 06:42:10 +08:00
|
|
|
|
2013-09-05 03:53:21 +08:00
|
|
|
if (tag == dwarf::DW_TAG_pointer_type)
|
2013-10-09 03:07:44 +08:00
|
|
|
subType = resolve(DIDerivedType(Ty).getTypeDerivedFrom());
|
2012-11-20 06:42:10 +08:00
|
|
|
|
2013-09-05 03:53:21 +08:00
|
|
|
DIArray Elements = DICompositeType(subType).getTypeArray();
|
2011-04-13 06:53:02 +08:00
|
|
|
for (unsigned i = 0, N = Elements.getNumElements(); i < N; ++i) {
|
2013-11-19 07:57:26 +08:00
|
|
|
DIDerivedType DT(Elements.getElement(i));
|
2011-04-13 06:53:02 +08:00
|
|
|
if (getName() == DT.getName())
|
2013-10-09 03:07:44 +08:00
|
|
|
return (resolve(DT.getTypeDerivedFrom()));
|
2010-08-10 05:01:39 +08:00
|
|
|
}
|
|
|
|
}
|
2011-04-13 06:53:02 +08:00
|
|
|
return Ty;
|
|
|
|
}
|
2009-05-15 17:23:25 +08:00
|
|
|
|
2010-04-05 12:09:20 +08:00
|
|
|
} // end llvm namespace
|
2009-05-15 17:23:25 +08:00
|
|
|
|
2013-07-03 07:40:10 +08:00
|
|
|
/// Return Dwarf Version by checking module flags.
|
|
|
|
static unsigned getDwarfVersionFromModule(const Module *M) {
|
2013-07-17 07:21:16 +08:00
|
|
|
Value *Val = M->getModuleFlag("Dwarf Version");
|
|
|
|
if (!Val)
|
2013-09-05 06:21:24 +08:00
|
|
|
return dwarf::DWARF_VERSION;
|
2013-07-17 07:21:16 +08:00
|
|
|
return cast<ConstantInt>(Val)->getZExtValue();
|
2013-07-03 07:40:10 +08:00
|
|
|
}
|
|
|
|
|
2010-04-05 13:11:15 +08:00
|
|
|
DwarfDebug::DwarfDebug(AsmPrinter *A, Module *M)
|
2013-12-05 15:43:55 +08:00
|
|
|
: Asm(A), MMI(Asm->MMI), FirstCU(0), SourceIdMap(DIEValueAllocator),
|
2013-12-07 03:38:46 +08:00
|
|
|
PrevLabel(NULL), GlobalRangeCount(0),
|
2013-12-05 15:43:55 +08:00
|
|
|
InfoHolder(A, "info_string", DIEValueAllocator),
|
|
|
|
SkeletonHolder(A, "skel_string", DIEValueAllocator) {
|
2010-07-22 05:21:52 +08:00
|
|
|
|
2014-01-03 10:16:44 +08:00
|
|
|
DwarfInfoSectionSym = DwarfAbbrevSectionSym = DwarfStrSectionSym = 0;
|
2013-02-08 05:19:50 +08:00
|
|
|
DwarfDebugRangeSectionSym = DwarfDebugLocSectionSym = DwarfLineSectionSym = 0;
|
2013-04-07 11:43:09 +08:00
|
|
|
DwarfAddrSectionSym = 0;
|
2012-12-27 10:14:01 +08:00
|
|
|
DwarfAbbrevDWOSectionSym = DwarfStrDWOSectionSym = 0;
|
2010-05-26 07:40:22 +08:00
|
|
|
FunctionBeginSym = FunctionEndSym = 0;
|
2013-12-10 07:32:48 +08:00
|
|
|
CurFn = 0;
|
|
|
|
CurMI = 0;
|
2012-04-03 01:58:52 +08:00
|
|
|
|
2013-10-16 04:26:37 +08:00
|
|
|
// Turn on accelerator tables for Darwin by default, pubnames by
|
|
|
|
// default for non-Darwin, and handle split dwarf.
|
2013-04-27 09:07:52 +08:00
|
|
|
bool IsDarwin = Triple(A->getTargetTriple()).isOSDarwin();
|
2013-08-20 05:41:38 +08:00
|
|
|
|
|
|
|
if (DwarfAccelTables == Default)
|
|
|
|
HasDwarfAccelTables = IsDarwin;
|
|
|
|
else
|
2013-08-27 04:58:35 +08:00
|
|
|
HasDwarfAccelTables = DwarfAccelTables == Enable;
|
2012-08-24 06:36:36 +08:00
|
|
|
|
2012-12-11 03:51:21 +08:00
|
|
|
if (SplitDwarf == Default)
|
|
|
|
HasSplitDwarf = false;
|
2012-11-13 06:22:20 +08:00
|
|
|
else
|
2013-08-20 05:41:38 +08:00
|
|
|
HasSplitDwarf = SplitDwarf == Enable;
|
|
|
|
|
2013-08-27 07:24:35 +08:00
|
|
|
if (DwarfPubSections == Default)
|
|
|
|
HasDwarfPubSections = !IsDarwin;
|
2013-08-20 05:41:38 +08:00
|
|
|
else
|
2013-08-27 07:24:35 +08:00
|
|
|
HasDwarfPubSections = DwarfPubSections == Enable;
|
2013-08-20 05:07:38 +08:00
|
|
|
|
2013-11-22 07:46:41 +08:00
|
|
|
DwarfVersion = DwarfVersionNumber
|
|
|
|
? DwarfVersionNumber
|
|
|
|
: getDwarfVersionFromModule(MMI->getModule());
|
2013-07-03 07:40:10 +08:00
|
|
|
|
2010-06-18 23:56:31 +08:00
|
|
|
{
|
|
|
|
NamedRegionTimer T(DbgTimerName, DWARFGroupName, TimePassesIsEnabled);
|
2012-11-20 06:42:15 +08:00
|
|
|
beginModule();
|
2010-04-07 18:44:46 +08:00
|
|
|
}
|
2009-05-15 17:23:25 +08:00
|
|
|
}
|
|
|
|
|
2012-11-28 06:43:45 +08:00
|
|
|
// Switch to the specified MCSection and emit an assembler
|
|
|
|
// temporary label to it if SymbolStem is specified.
|
2012-11-21 08:34:35 +08:00
|
|
|
static MCSymbol *emitSectionSym(AsmPrinter *Asm, const MCSection *Section,
|
2011-11-07 17:18:38 +08:00
|
|
|
const char *SymbolStem = 0) {
|
|
|
|
Asm->OutStreamer.SwitchSection(Section);
|
2013-11-19 17:04:36 +08:00
|
|
|
if (!SymbolStem)
|
|
|
|
return 0;
|
2011-11-07 17:18:38 +08:00
|
|
|
|
|
|
|
MCSymbol *TmpSym = Asm->GetTempSymbol(SymbolStem);
|
|
|
|
Asm->OutStreamer.EmitLabel(TmpSym);
|
|
|
|
return TmpSym;
|
|
|
|
}
|
|
|
|
|
2013-12-06 02:06:10 +08:00
|
|
|
DwarfFile::~DwarfFile() {
|
2013-12-10 07:32:48 +08:00
|
|
|
for (SmallVectorImpl<DwarfUnit *>::iterator I = CUs.begin(), E = CUs.end();
|
|
|
|
I != E; ++I)
|
2013-11-23 09:17:34 +08:00
|
|
|
delete *I;
|
|
|
|
}
|
|
|
|
|
2013-12-06 02:06:10 +08:00
|
|
|
MCSymbol *DwarfFile::getStringPoolSym() {
|
2012-12-27 10:14:01 +08:00
|
|
|
return Asm->GetTempSymbol(StringPref);
|
2011-10-27 14:44:11 +08:00
|
|
|
}
|
|
|
|
|
2013-12-06 02:06:10 +08:00
|
|
|
MCSymbol *DwarfFile::getStringPoolEntry(StringRef Str) {
|
2013-11-19 17:04:36 +08:00
|
|
|
std::pair<MCSymbol *, unsigned> &Entry =
|
|
|
|
StringPool.GetOrCreateValue(Str).getValue();
|
|
|
|
if (Entry.first)
|
|
|
|
return Entry.first;
|
2010-03-13 10:17:42 +08:00
|
|
|
|
|
|
|
Entry.second = NextStringPoolNumber++;
|
2012-12-27 10:14:01 +08:00
|
|
|
return Entry.first = Asm->GetTempSymbol(StringPref, Entry.second);
|
2010-03-13 10:17:42 +08:00
|
|
|
}
|
|
|
|
|
2013-12-06 02:06:10 +08:00
|
|
|
unsigned DwarfFile::getStringPoolIndex(StringRef Str) {
|
2013-11-19 17:04:36 +08:00
|
|
|
std::pair<MCSymbol *, unsigned> &Entry =
|
|
|
|
StringPool.GetOrCreateValue(Str).getValue();
|
|
|
|
if (Entry.first)
|
|
|
|
return Entry.second;
|
2013-01-08 03:32:41 +08:00
|
|
|
|
|
|
|
Entry.second = NextStringPoolNumber++;
|
|
|
|
Entry.first = Asm->GetTempSymbol(StringPref, Entry.second);
|
|
|
|
return Entry.second;
|
|
|
|
}
|
|
|
|
|
2013-12-06 02:06:10 +08:00
|
|
|
unsigned DwarfFile::getAddrPoolIndex(const MCSymbol *Sym) {
|
2013-07-02 07:55:52 +08:00
|
|
|
return getAddrPoolIndex(MCSymbolRefExpr::Create(Sym, Asm->OutContext));
|
|
|
|
}
|
|
|
|
|
2013-12-06 02:06:10 +08:00
|
|
|
unsigned DwarfFile::getAddrPoolIndex(const MCExpr *Sym) {
|
2013-07-03 02:46:46 +08:00
|
|
|
std::pair<DenseMap<const MCExpr *, unsigned>::iterator, bool> P =
|
2013-06-29 02:47:19 +08:00
|
|
|
AddressPool.insert(std::make_pair(Sym, NextAddrPoolNumber));
|
2013-06-29 02:55:13 +08:00
|
|
|
if (P.second)
|
|
|
|
++NextAddrPoolNumber;
|
2013-06-29 02:47:19 +08:00
|
|
|
return P.first->second;
|
2013-01-16 07:56:56 +08:00
|
|
|
}
|
|
|
|
|
2012-11-28 06:43:45 +08:00
|
|
|
// Define a unique number for the abbreviation.
|
|
|
|
//
|
2013-12-06 02:06:10 +08:00
|
|
|
void DwarfFile::assignAbbrevNumber(DIEAbbrev &Abbrev) {
|
2009-05-15 17:23:25 +08:00
|
|
|
// Check the set for priors.
|
2013-12-05 15:43:55 +08:00
|
|
|
DIEAbbrev *InSet = AbbreviationsSet.GetOrInsertNode(&Abbrev);
|
2009-05-15 17:23:25 +08:00
|
|
|
|
|
|
|
// If it's newly added.
|
|
|
|
if (InSet == &Abbrev) {
|
|
|
|
// Add to abbreviation list.
|
2013-10-31 01:14:24 +08:00
|
|
|
Abbreviations.push_back(&Abbrev);
|
2009-05-15 17:23:25 +08:00
|
|
|
|
|
|
|
// Assign the vector position + 1 as its number.
|
2013-10-31 01:14:24 +08:00
|
|
|
Abbrev.setNumber(Abbreviations.size());
|
2009-05-15 17:23:25 +08:00
|
|
|
} else {
|
|
|
|
// Assign existing abbreviation number.
|
|
|
|
Abbrev.setNumber(InSet->getNumber());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-11-11 03:25:34 +08:00
|
|
|
static bool isObjCClass(StringRef Name) {
|
|
|
|
return Name.startswith("+") || Name.startswith("-");
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool hasObjCCategory(StringRef Name) {
|
2013-11-19 17:04:36 +08:00
|
|
|
if (!isObjCClass(Name))
|
|
|
|
return false;
|
2011-11-11 03:25:34 +08:00
|
|
|
|
2013-08-24 20:15:54 +08:00
|
|
|
return Name.find(") ") != StringRef::npos;
|
2011-11-11 03:25:34 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static void getObjCClassCategory(StringRef In, StringRef &Class,
|
|
|
|
StringRef &Category) {
|
|
|
|
if (!hasObjCCategory(In)) {
|
|
|
|
Class = In.slice(In.find('[') + 1, In.find(' '));
|
|
|
|
Category = "";
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
Class = In.slice(In.find('[') + 1, In.find('('));
|
|
|
|
Category = In.slice(In.find('[') + 1, In.find(' '));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
static StringRef getObjCMethodName(StringRef In) {
|
|
|
|
return In.slice(In.find(' ') + 1, In.find(']'));
|
|
|
|
}
|
|
|
|
|
2013-10-04 06:07:08 +08:00
|
|
|
// Helper for sorting sections into a stable output order.
|
|
|
|
static bool SectionSort(const MCSection *A, const MCSection *B) {
|
2013-11-19 17:04:36 +08:00
|
|
|
std::string LA = (A ? A->getLabelBeginName() : "");
|
|
|
|
std::string LB = (B ? B->getLabelBeginName() : "");
|
|
|
|
return LA < LB;
|
2013-10-04 06:07:08 +08:00
|
|
|
}
|
|
|
|
|
2011-11-11 03:25:34 +08:00
|
|
|
// Add the various names to the Dwarf accelerator table names.
|
2013-09-21 07:22:52 +08:00
|
|
|
// TODO: Determine whether or not we should add names for programs
|
|
|
|
// that do not have a DW_AT_name or DW_AT_linkage_name field - this
|
|
|
|
// is only slightly different than the lookup of non-standard ObjC names.
|
2013-12-10 07:32:48 +08:00
|
|
|
static void addSubprogramNames(DwarfUnit *TheU, DISubprogram SP, DIE *Die) {
|
2013-11-19 17:04:36 +08:00
|
|
|
if (!SP.isDefinition())
|
|
|
|
return;
|
2013-12-03 06:09:48 +08:00
|
|
|
TheU->addAccelName(SP.getName(), Die);
|
2011-11-11 03:25:34 +08:00
|
|
|
|
|
|
|
// If the linkage name is different than the name, go ahead and output
|
|
|
|
// that as well into the name table.
|
|
|
|
if (SP.getLinkageName() != "" && SP.getName() != SP.getLinkageName())
|
2013-12-03 06:09:48 +08:00
|
|
|
TheU->addAccelName(SP.getLinkageName(), Die);
|
2011-11-11 03:25:34 +08:00
|
|
|
|
|
|
|
// If this is an Objective-C selector name add it to the ObjC accelerator
|
|
|
|
// too.
|
|
|
|
if (isObjCClass(SP.getName())) {
|
|
|
|
StringRef Class, Category;
|
|
|
|
getObjCClassCategory(SP.getName(), Class, Category);
|
2013-12-03 06:09:48 +08:00
|
|
|
TheU->addAccelObjC(Class, Die);
|
2011-11-11 03:25:34 +08:00
|
|
|
if (Category != "")
|
2013-12-03 06:09:48 +08:00
|
|
|
TheU->addAccelObjC(Category, Die);
|
2011-11-11 03:25:34 +08:00
|
|
|
// Also add the base method name to the name table.
|
2013-12-03 06:09:48 +08:00
|
|
|
TheU->addAccelName(getObjCMethodName(SP.getName()), Die);
|
2011-11-11 03:25:34 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-09-10 03:05:21 +08:00
|
|
|
/// isSubprogramContext - Return true if Context is either a subprogram
|
|
|
|
/// or another context nested inside a subprogram.
|
|
|
|
bool DwarfDebug::isSubprogramContext(const MDNode *Context) {
|
|
|
|
if (!Context)
|
|
|
|
return false;
|
|
|
|
DIDescriptor D(Context);
|
|
|
|
if (D.isSubprogram())
|
|
|
|
return true;
|
|
|
|
if (D.isType())
|
2013-09-10 03:47:11 +08:00
|
|
|
return isSubprogramContext(resolve(DIType(Context).getContext()));
|
2013-09-10 03:05:21 +08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2012-11-28 06:43:45 +08:00
|
|
|
// Find DIE for the given subprogram and attach appropriate DW_AT_low_pc
|
|
|
|
// and DW_AT_high_pc attributes. If there are global variables in this
|
|
|
|
// scope then create and insert DIEs for these variables.
|
2013-12-10 07:57:44 +08:00
|
|
|
DIE *DwarfDebug::updateSubprogramScopeDIE(DwarfCompileUnit *SPCU,
|
|
|
|
DISubprogram SP) {
|
2013-11-16 07:13:08 +08:00
|
|
|
DIE *SPDie = SPCU->getDIE(SP);
|
2010-07-08 06:20:57 +08:00
|
|
|
|
2010-04-05 08:13:49 +08:00
|
|
|
assert(SPDie && "Unable to find subprogram DIE!");
|
2010-07-22 05:21:52 +08:00
|
|
|
|
2012-11-07 13:19:04 +08:00
|
|
|
// If we're updating an abstract DIE, then we will be adding the children and
|
|
|
|
// object pointer later on. But what we don't want to do is process the
|
|
|
|
// concrete DIE twice.
|
2013-11-16 07:13:08 +08:00
|
|
|
if (DIE *AbsSPDIE = AbstractSPDies.lookup(SP)) {
|
2012-11-07 13:19:04 +08:00
|
|
|
// Pick up abstract subprogram DIE.
|
2013-12-03 06:09:48 +08:00
|
|
|
SPDie =
|
|
|
|
SPCU->createAndAddDIE(dwarf::DW_TAG_subprogram, *SPCU->getUnitDie());
|
2013-10-12 07:58:05 +08:00
|
|
|
SPCU->addDIEEntry(SPDie, dwarf::DW_AT_abstract_origin, AbsSPDIE);
|
2012-11-07 12:42:18 +08:00
|
|
|
} else {
|
|
|
|
DISubprogram SPDecl = SP.getFunctionDeclaration();
|
|
|
|
if (!SPDecl.isSubprogram()) {
|
|
|
|
// There is not any need to generate specification DIE for a function
|
|
|
|
// defined at compile unit level. If a function is defined inside another
|
|
|
|
// function then gdb prefers the definition at top level and but does not
|
|
|
|
// expect specification DIE in parent function. So avoid creating
|
|
|
|
// specification DIE for a function defined inside a function.
|
2013-10-11 02:40:01 +08:00
|
|
|
DIScope SPContext = resolve(SP.getContext());
|
|
|
|
if (SP.isDefinition() && !SPContext.isCompileUnit() &&
|
2013-11-19 17:04:36 +08:00
|
|
|
!SPContext.isFile() && !isSubprogramContext(SPContext)) {
|
2012-11-07 12:42:18 +08:00
|
|
|
SPCU->addFlag(SPDie, dwarf::DW_AT_declaration);
|
|
|
|
|
|
|
|
// Add arguments.
|
|
|
|
DICompositeType SPTy = SP.getType();
|
|
|
|
DIArray Args = SPTy.getTypeArray();
|
2013-08-08 09:41:00 +08:00
|
|
|
uint16_t SPTag = SPTy.getTag();
|
2012-11-07 12:42:18 +08:00
|
|
|
if (SPTag == dwarf::DW_TAG_subroutine_type)
|
|
|
|
for (unsigned i = 1, N = Args.getNumElements(); i < N; ++i) {
|
2013-10-29 09:03:01 +08:00
|
|
|
DIE *Arg =
|
|
|
|
SPCU->createAndAddDIE(dwarf::DW_TAG_formal_parameter, *SPDie);
|
2013-11-19 07:57:26 +08:00
|
|
|
DIType ATy(Args.getElement(i));
|
2012-11-07 12:42:18 +08:00
|
|
|
SPCU->addType(Arg, ATy);
|
|
|
|
if (ATy.isArtificial())
|
|
|
|
SPCU->addFlag(Arg, dwarf::DW_AT_artificial);
|
|
|
|
if (ATy.isObjectPointer())
|
2013-10-12 07:58:05 +08:00
|
|
|
SPCU->addDIEEntry(SPDie, dwarf::DW_AT_object_pointer, Arg);
|
2012-11-07 12:42:18 +08:00
|
|
|
}
|
|
|
|
DIE *SPDeclDie = SPDie;
|
2013-12-03 06:09:48 +08:00
|
|
|
SPDie = SPCU->createAndAddDIE(dwarf::DW_TAG_subprogram,
|
|
|
|
*SPCU->getUnitDie());
|
2013-10-12 07:58:05 +08:00
|
|
|
SPCU->addDIEEntry(SPDie, dwarf::DW_AT_specification, SPDeclDie);
|
2012-11-07 12:42:18 +08:00
|
|
|
}
|
|
|
|
}
|
2010-07-08 06:20:57 +08:00
|
|
|
}
|
|
|
|
|
2013-12-05 01:55:41 +08:00
|
|
|
SPCU->addLabelAddress(SPDie, dwarf::DW_AT_low_pc, FunctionBeginSym);
|
|
|
|
SPCU->addLabelAddress(SPDie, dwarf::DW_AT_high_pc, FunctionEndSym);
|
2013-12-03 08:45:45 +08:00
|
|
|
|
2013-12-20 12:16:18 +08:00
|
|
|
// Add this range to the list of ranges for the CU.
|
|
|
|
RangeSpan Span(FunctionBeginSym, FunctionEndSym);
|
|
|
|
SPCU->addRange(llvm_move(Span));
|
|
|
|
|
2010-04-05 08:13:49 +08:00
|
|
|
const TargetRegisterInfo *RI = Asm->TM.getRegisterInfo();
|
|
|
|
MachineLocation Location(RI->getFrameRegister(*Asm->MF));
|
2011-04-13 06:53:02 +08:00
|
|
|
SPCU->addAddress(SPDie, dwarf::DW_AT_frame_base, Location);
|
2010-04-05 08:13:49 +08:00
|
|
|
|
2011-11-11 03:25:34 +08:00
|
|
|
// Add name to the name table, we do this here because we're guaranteed
|
|
|
|
// to have concrete versions of our DW_TAG_subprogram nodes.
|
|
|
|
addSubprogramNames(SPCU, SP, SPDie);
|
2012-11-20 06:42:10 +08:00
|
|
|
|
2010-04-05 08:13:49 +08:00
|
|
|
return SPDie;
|
2009-11-11 07:06:00 +08:00
|
|
|
}
|
|
|
|
|
2013-09-12 03:40:28 +08:00
|
|
|
/// Check whether we should create a DIE for the given Scope, return true
|
|
|
|
/// if we don't create a DIE (the corresponding DIE is null).
|
2013-09-11 02:40:41 +08:00
|
|
|
bool DwarfDebug::isLexicalScopeDIENull(LexicalScope *Scope) {
|
|
|
|
if (Scope->isAbstractScope())
|
|
|
|
return false;
|
|
|
|
|
2013-09-12 03:40:28 +08:00
|
|
|
// We don't create a DIE if there is no Range.
|
2013-09-11 02:40:41 +08:00
|
|
|
const SmallVectorImpl<InsnRange> &Ranges = Scope->getRanges();
|
|
|
|
if (Ranges.empty())
|
|
|
|
return true;
|
|
|
|
|
|
|
|
if (Ranges.size() > 1)
|
|
|
|
return false;
|
|
|
|
|
2013-09-12 03:40:28 +08:00
|
|
|
// We don't create a DIE if we have a single Range and the end label
|
|
|
|
// is null.
|
2013-09-11 02:40:41 +08:00
|
|
|
SmallVectorImpl<InsnRange>::const_iterator RI = Ranges.begin();
|
|
|
|
MCSymbol *End = getLabelAfterInsn(RI->second);
|
|
|
|
return !End;
|
|
|
|
}
|
|
|
|
|
2013-12-10 07:32:48 +08:00
|
|
|
static void addSectionLabel(AsmPrinter *Asm, DwarfUnit *U, DIE *D,
|
2013-12-05 08:36:17 +08:00
|
|
|
dwarf::Attribute A, const MCSymbol *L,
|
|
|
|
const MCSymbol *Sec) {
|
|
|
|
if (Asm->MAI->doesDwarfUseRelocationsAcrossSections())
|
|
|
|
U->addSectionLabel(D, A, L);
|
|
|
|
else
|
|
|
|
U->addSectionDelta(D, A, L, Sec);
|
|
|
|
}
|
|
|
|
|
2013-12-10 07:57:44 +08:00
|
|
|
void DwarfDebug::addScopeRangeList(DwarfCompileUnit *TheCU, DIE *ScopeDIE,
|
2013-12-03 08:45:59 +08:00
|
|
|
const SmallVectorImpl<InsnRange> &Range) {
|
|
|
|
// Emit offset in .debug_range as a relocatable label. emitDIE will handle
|
|
|
|
// emitting it appropriately.
|
2013-12-05 06:04:50 +08:00
|
|
|
MCSymbol *RangeSym = Asm->GetTempSymbol("debug_ranges", GlobalRangeCount++);
|
2013-12-05 08:36:17 +08:00
|
|
|
addSectionLabel(Asm, TheCU, ScopeDIE, dwarf::DW_AT_ranges, RangeSym,
|
|
|
|
DwarfDebugRangeSectionSym);
|
|
|
|
|
2013-12-05 06:04:50 +08:00
|
|
|
RangeSpanList List(RangeSym);
|
2013-12-03 08:45:59 +08:00
|
|
|
for (SmallVectorImpl<InsnRange>::const_iterator RI = Range.begin(),
|
|
|
|
RE = Range.end();
|
|
|
|
RI != RE; ++RI) {
|
|
|
|
RangeSpan Span(getLabelBeforeInsn(RI->first),
|
|
|
|
getLabelAfterInsn(RI->second));
|
2013-12-05 03:06:58 +08:00
|
|
|
List.addRange(llvm_move(Span));
|
2013-12-03 08:45:59 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Add the range list to the set of ranges to be emitted.
|
2013-12-05 03:06:58 +08:00
|
|
|
TheCU->addRangeList(llvm_move(List));
|
2013-12-03 08:45:59 +08:00
|
|
|
}
|
|
|
|
|
2012-11-28 06:43:45 +08:00
|
|
|
// Construct new DW_TAG_lexical_block for this scope and attach
|
|
|
|
// DW_AT_low_pc/DW_AT_high_pc labels.
|
2013-12-10 07:57:44 +08:00
|
|
|
DIE *DwarfDebug::constructLexicalScopeDIE(DwarfCompileUnit *TheCU,
|
2011-08-16 06:24:32 +08:00
|
|
|
LexicalScope *Scope) {
|
2013-09-11 02:40:41 +08:00
|
|
|
if (isLexicalScopeDIENull(Scope))
|
|
|
|
return 0;
|
|
|
|
|
2010-04-23 09:18:53 +08:00
|
|
|
DIE *ScopeDIE = new DIE(dwarf::DW_TAG_lexical_block);
|
|
|
|
if (Scope->isAbstractScope())
|
|
|
|
return ScopeDIE;
|
|
|
|
|
2013-12-03 08:45:45 +08:00
|
|
|
const SmallVectorImpl<InsnRange> &ScopeRanges = Scope->getRanges();
|
2013-12-03 08:45:59 +08:00
|
|
|
|
2013-07-03 09:57:28 +08:00
|
|
|
// If we have multiple ranges, emit them into the range section.
|
2013-12-03 08:45:45 +08:00
|
|
|
if (ScopeRanges.size() > 1) {
|
2013-12-03 08:45:59 +08:00
|
|
|
addScopeRangeList(TheCU, ScopeDIE, ScopeRanges);
|
2010-04-28 03:46:33 +08:00
|
|
|
return ScopeDIE;
|
|
|
|
}
|
|
|
|
|
2013-07-03 09:57:28 +08:00
|
|
|
// Construct the address range for this DIE.
|
2013-12-03 08:45:45 +08:00
|
|
|
SmallVectorImpl<InsnRange>::const_iterator RI = ScopeRanges.begin();
|
2013-01-16 07:56:56 +08:00
|
|
|
MCSymbol *Start = getLabelBeforeInsn(RI->first);
|
|
|
|
MCSymbol *End = getLabelAfterInsn(RI->second);
|
2013-09-11 02:40:41 +08:00
|
|
|
assert(End && "End label should not be null!");
|
2010-04-28 03:46:33 +08:00
|
|
|
|
|
|
|
assert(Start->isDefined() && "Invalid starting label for an inlined scope!");
|
|
|
|
assert(End->isDefined() && "Invalid end label for an inlined scope!");
|
2010-07-22 05:21:52 +08:00
|
|
|
|
2013-01-16 07:56:56 +08:00
|
|
|
TheCU->addLabelAddress(ScopeDIE, dwarf::DW_AT_low_pc, Start);
|
|
|
|
TheCU->addLabelAddress(ScopeDIE, dwarf::DW_AT_high_pc, End);
|
2009-11-11 07:06:00 +08:00
|
|
|
|
|
|
|
return ScopeDIE;
|
|
|
|
}
|
|
|
|
|
2012-11-28 06:43:45 +08:00
|
|
|
// This scope represents inlined body of a function. Construct DIE to
|
|
|
|
// represent this concrete inlined copy of the function.
|
2013-12-10 07:57:44 +08:00
|
|
|
DIE *DwarfDebug::constructInlinedScopeDIE(DwarfCompileUnit *TheCU,
|
2011-08-16 06:24:32 +08:00
|
|
|
LexicalScope *Scope) {
|
2013-12-03 08:45:45 +08:00
|
|
|
const SmallVectorImpl<InsnRange> &ScopeRanges = Scope->getRanges();
|
2013-12-05 05:20:15 +08:00
|
|
|
assert(!ScopeRanges.empty() &&
|
2011-10-27 06:55:33 +08:00
|
|
|
"LexicalScope does not have instruction markers!");
|
2010-04-28 03:46:33 +08:00
|
|
|
|
2011-07-27 08:34:13 +08:00
|
|
|
if (!Scope->getScopeNode())
|
|
|
|
return NULL;
|
|
|
|
DIScope DS(Scope->getScopeNode());
|
|
|
|
DISubprogram InlinedSP = getDISubprogram(DS);
|
2013-10-05 01:08:38 +08:00
|
|
|
DIE *OriginDIE = TheCU->getDIE(InlinedSP);
|
2011-07-27 08:34:13 +08:00
|
|
|
if (!OriginDIE) {
|
2012-10-31 01:51:02 +08:00
|
|
|
DEBUG(dbgs() << "Unable to find original DIE for an inlined subprogram.");
|
2011-07-27 08:34:13 +08:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2011-05-06 01:54:26 +08:00
|
|
|
DIE *ScopeDIE = new DIE(dwarf::DW_TAG_inlined_subroutine);
|
2013-10-12 07:58:05 +08:00
|
|
|
TheCU->addDIEEntry(ScopeDIE, dwarf::DW_AT_abstract_origin, OriginDIE);
|
2009-11-11 07:06:00 +08:00
|
|
|
|
2013-12-03 08:45:59 +08:00
|
|
|
// If we have multiple ranges, emit them into the range section.
|
|
|
|
if (ScopeRanges.size() > 1)
|
|
|
|
addScopeRangeList(TheCU, ScopeDIE, ScopeRanges);
|
|
|
|
else {
|
2013-12-03 08:45:45 +08:00
|
|
|
SmallVectorImpl<InsnRange>::const_iterator RI = ScopeRanges.begin();
|
2013-07-03 10:23:53 +08:00
|
|
|
MCSymbol *StartLabel = getLabelBeforeInsn(RI->first);
|
|
|
|
MCSymbol *EndLabel = getLabelAfterInsn(RI->second);
|
|
|
|
|
|
|
|
if (StartLabel == 0 || EndLabel == 0)
|
|
|
|
llvm_unreachable("Unexpected Start and End labels for an inlined scope!");
|
|
|
|
|
|
|
|
assert(StartLabel->isDefined() &&
|
|
|
|
"Invalid starting label for an inlined scope!");
|
|
|
|
assert(EndLabel->isDefined() && "Invalid end label for an inlined scope!");
|
|
|
|
|
2013-01-16 07:56:56 +08:00
|
|
|
TheCU->addLabelAddress(ScopeDIE, dwarf::DW_AT_low_pc, StartLabel);
|
|
|
|
TheCU->addLabelAddress(ScopeDIE, dwarf::DW_AT_high_pc, EndLabel);
|
2011-07-27 08:34:13 +08:00
|
|
|
}
|
2009-11-11 07:06:00 +08:00
|
|
|
|
|
|
|
InlinedSubprogramDIEs.insert(OriginDIE);
|
|
|
|
|
2013-07-03 10:23:53 +08:00
|
|
|
// Add the call site information to the DIE.
|
2009-11-11 07:06:00 +08:00
|
|
|
DILocation DL(Scope->getInlinedAt());
|
2013-10-22 01:28:37 +08:00
|
|
|
TheCU->addUInt(ScopeDIE, dwarf::DW_AT_call_file, None,
|
2013-03-07 09:42:00 +08:00
|
|
|
getOrCreateSourceID(DL.getFilename(), DL.getDirectory(),
|
|
|
|
TheCU->getUniqueID()));
|
2013-10-22 01:28:37 +08:00
|
|
|
TheCU->addUInt(ScopeDIE, dwarf::DW_AT_call_line, None, DL.getLineNumber());
|
2009-11-11 07:06:00 +08:00
|
|
|
|
2011-12-04 14:02:38 +08:00
|
|
|
// Add name to the name table, we do this here because we're guaranteed
|
|
|
|
// to have concrete versions of our DW_TAG_inlined_subprogram nodes.
|
|
|
|
addSubprogramNames(TheCU, InlinedSP, ScopeDIE);
|
2012-11-20 06:42:10 +08:00
|
|
|
|
2009-11-11 07:06:00 +08:00
|
|
|
return ScopeDIE;
|
|
|
|
}
|
|
|
|
|
2013-12-10 07:57:44 +08:00
|
|
|
DIE *DwarfDebug::createScopeChildrenDIE(DwarfCompileUnit *TheCU,
|
|
|
|
LexicalScope *Scope,
|
2013-11-19 17:04:36 +08:00
|
|
|
SmallVectorImpl<DIE *> &Children) {
|
|
|
|
DIE *ObjectPointer = NULL;
|
2011-03-02 06:58:55 +08:00
|
|
|
|
|
|
|
// Collect arguments for current function.
|
2011-08-11 04:55:27 +08:00
|
|
|
if (LScopes.isCurrentFunctionScope(Scope))
|
2011-03-02 06:58:55 +08:00
|
|
|
for (unsigned i = 0, N = CurrentFnArguments.size(); i < N; ++i)
|
|
|
|
if (DbgVariable *ArgDV = CurrentFnArguments[i])
|
2012-11-20 06:42:10 +08:00
|
|
|
if (DIE *Arg =
|
2013-11-19 17:04:36 +08:00
|
|
|
TheCU->constructVariableDIE(*ArgDV, Scope->isAbstractScope())) {
|
2011-03-02 06:58:55 +08:00
|
|
|
Children.push_back(Arg);
|
2013-11-19 17:04:36 +08:00
|
|
|
if (ArgDV->isObjectPointer())
|
|
|
|
ObjectPointer = Arg;
|
2012-09-13 07:36:19 +08:00
|
|
|
}
|
2011-03-02 06:58:55 +08:00
|
|
|
|
2011-10-03 23:49:16 +08:00
|
|
|
// Collect lexical scope children first.
|
2013-11-19 17:04:36 +08:00
|
|
|
const SmallVectorImpl<DbgVariable *> &Variables =
|
|
|
|
ScopeVariables.lookup(Scope);
|
2011-02-19 09:31:27 +08:00
|
|
|
for (unsigned i = 0, N = Variables.size(); i < N; ++i)
|
2013-11-19 17:04:36 +08:00
|
|
|
if (DIE *Variable = TheCU->constructVariableDIE(*Variables[i],
|
|
|
|
Scope->isAbstractScope())) {
|
2011-02-19 09:31:27 +08:00
|
|
|
Children.push_back(Variable);
|
2013-11-19 17:04:36 +08:00
|
|
|
if (Variables[i]->isObjectPointer())
|
|
|
|
ObjectPointer = Variable;
|
2012-09-22 06:18:52 +08:00
|
|
|
}
|
2013-07-03 12:24:43 +08:00
|
|
|
const SmallVectorImpl<LexicalScope *> &Scopes = Scope->getChildren();
|
2011-02-19 09:31:27 +08:00
|
|
|
for (unsigned j = 0, M = Scopes.size(); j < M; ++j)
|
2011-08-16 06:04:40 +08:00
|
|
|
if (DIE *Nested = constructScopeDIE(TheCU, Scopes[j]))
|
2011-02-19 09:31:27 +08:00
|
|
|
Children.push_back(Nested);
|
2013-09-11 02:40:41 +08:00
|
|
|
return ObjectPointer;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Construct a DIE for this scope.
|
2013-12-10 07:57:44 +08:00
|
|
|
DIE *DwarfDebug::constructScopeDIE(DwarfCompileUnit *TheCU,
|
|
|
|
LexicalScope *Scope) {
|
2013-09-11 02:40:41 +08:00
|
|
|
if (!Scope || !Scope->getScopeNode())
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
DIScope DS(Scope->getScopeNode());
|
|
|
|
|
|
|
|
SmallVector<DIE *, 8> Children;
|
|
|
|
DIE *ObjectPointer = NULL;
|
|
|
|
bool ChildrenCreated = false;
|
|
|
|
|
2013-09-12 03:40:28 +08:00
|
|
|
// We try to create the scope DIE first, then the children DIEs. This will
|
|
|
|
// avoid creating un-used children then removing them later when we find out
|
|
|
|
// the scope DIE is null.
|
2010-03-09 04:52:55 +08:00
|
|
|
DIE *ScopeDIE = NULL;
|
|
|
|
if (Scope->getInlinedAt())
|
2011-08-16 06:24:32 +08:00
|
|
|
ScopeDIE = constructInlinedScopeDIE(TheCU, Scope);
|
2010-03-09 04:52:55 +08:00
|
|
|
else if (DS.isSubprogram()) {
|
2010-06-29 04:53:04 +08:00
|
|
|
ProcessedSPNodes.insert(DS);
|
2010-07-08 06:20:57 +08:00
|
|
|
if (Scope->isAbstractScope()) {
|
2013-10-05 01:08:38 +08:00
|
|
|
ScopeDIE = TheCU->getDIE(DS);
|
2010-07-08 06:20:57 +08:00
|
|
|
// Note down abstract DIE.
|
|
|
|
if (ScopeDIE)
|
|
|
|
AbstractSPDies.insert(std::make_pair(DS, ScopeDIE));
|
2013-11-19 07:59:04 +08:00
|
|
|
} else
|
2013-11-16 07:13:08 +08:00
|
|
|
ScopeDIE = updateSubprogramScopeDIE(TheCU, DISubprogram(DS));
|
2013-11-19 07:59:04 +08:00
|
|
|
} else {
|
2013-09-12 03:40:28 +08:00
|
|
|
// Early exit when we know the scope DIE is going to be null.
|
2013-09-11 02:40:41 +08:00
|
|
|
if (isLexicalScopeDIENull(Scope))
|
|
|
|
return NULL;
|
2013-09-12 03:40:28 +08:00
|
|
|
|
|
|
|
// We create children here when we know the scope DIE is not going to be
|
|
|
|
// null and the children will be added to the scope DIE.
|
2013-09-11 02:40:41 +08:00
|
|
|
ObjectPointer = createScopeChildrenDIE(TheCU, Scope, Children);
|
|
|
|
ChildrenCreated = true;
|
2013-09-12 03:40:28 +08:00
|
|
|
|
2011-02-19 09:31:27 +08:00
|
|
|
// There is no need to emit empty lexical block DIE.
|
2013-05-07 07:33:07 +08:00
|
|
|
std::pair<ImportedEntityMap::const_iterator,
|
2013-11-19 17:04:36 +08:00
|
|
|
ImportedEntityMap::const_iterator> Range =
|
|
|
|
std::equal_range(
|
|
|
|
ScopesWithImportedEntities.begin(),
|
|
|
|
ScopesWithImportedEntities.end(),
|
|
|
|
std::pair<const MDNode *, const MDNode *>(DS, (const MDNode *)0),
|
|
|
|
less_first());
|
2013-05-07 07:33:07 +08:00
|
|
|
if (Children.empty() && Range.first == Range.second)
|
2011-02-19 09:31:27 +08:00
|
|
|
return NULL;
|
2011-08-16 06:24:32 +08:00
|
|
|
ScopeDIE = constructLexicalScopeDIE(TheCU, Scope);
|
2013-09-11 02:40:41 +08:00
|
|
|
assert(ScopeDIE && "Scope DIE should not be null.");
|
2013-06-25 07:20:02 +08:00
|
|
|
for (ImportedEntityMap::const_iterator i = Range.first; i != Range.second;
|
|
|
|
++i)
|
2013-05-08 14:01:38 +08:00
|
|
|
constructImportedEntityDIE(TheCU, i->second, ScopeDIE);
|
2009-11-11 07:06:00 +08:00
|
|
|
}
|
2012-11-20 06:42:10 +08:00
|
|
|
|
2013-08-24 19:55:49 +08:00
|
|
|
if (!ScopeDIE) {
|
2013-09-11 02:40:41 +08:00
|
|
|
assert(Children.empty() &&
|
|
|
|
"We create children only when the scope DIE is not null.");
|
2013-08-24 19:55:49 +08:00
|
|
|
return NULL;
|
|
|
|
}
|
2013-09-11 02:40:41 +08:00
|
|
|
if (!ChildrenCreated)
|
2013-09-12 03:40:28 +08:00
|
|
|
// We create children when the scope DIE is not null.
|
2013-09-11 02:40:41 +08:00
|
|
|
ObjectPointer = createScopeChildrenDIE(TheCU, Scope, Children);
|
2009-11-11 07:06:00 +08:00
|
|
|
|
2011-02-19 09:31:27 +08:00
|
|
|
// Add children
|
2013-07-03 12:17:25 +08:00
|
|
|
for (SmallVectorImpl<DIE *>::iterator I = Children.begin(),
|
2013-11-19 17:04:36 +08:00
|
|
|
E = Children.end();
|
|
|
|
I != E; ++I)
|
2011-02-19 09:31:27 +08:00
|
|
|
ScopeDIE->addChild(*I);
|
2009-11-24 09:14:22 +08:00
|
|
|
|
2012-09-13 07:36:19 +08:00
|
|
|
if (DS.isSubprogram() && ObjectPointer != NULL)
|
2013-10-12 07:58:05 +08:00
|
|
|
TheCU->addDIEEntry(ScopeDIE, dwarf::DW_AT_object_pointer, ObjectPointer);
|
2012-09-13 07:36:19 +08:00
|
|
|
|
2011-11-11 03:25:34 +08:00
|
|
|
return ScopeDIE;
|
2009-11-11 07:06:00 +08:00
|
|
|
}
|
|
|
|
|
2012-11-28 06:43:45 +08:00
|
|
|
// Look up the source id with the given directory and source file names.
|
|
|
|
// If none currently exists, create a new id and insert it in the
|
|
|
|
// SourceIds map. This can update DirectoryNames and SourceFileNames maps
|
|
|
|
// as well.
|
2013-11-19 17:04:36 +08:00
|
|
|
unsigned DwarfDebug::getOrCreateSourceID(StringRef FileName, StringRef DirName,
|
|
|
|
unsigned CUID) {
|
2013-03-07 09:42:00 +08:00
|
|
|
// If we use .loc in assembly, we can't separate .file entries according to
|
|
|
|
// compile units. Thus all files will belong to the default compile unit.
|
2013-10-06 00:42:21 +08:00
|
|
|
|
|
|
|
// FIXME: add a better feature test than hasRawTextSupport. Even better,
|
|
|
|
// extend .file to support this.
|
|
|
|
if (Asm->TM.hasMCUseLoc() && Asm->OutStreamer.hasRawTextSupport())
|
2013-03-07 09:42:00 +08:00
|
|
|
CUID = 0;
|
|
|
|
|
2010-09-17 04:57:49 +08:00
|
|
|
// If FE did not provide a file name, then assume stdin.
|
|
|
|
if (FileName.empty())
|
2013-03-07 09:42:00 +08:00
|
|
|
return getOrCreateSourceID("<stdin>", StringRef(), CUID);
|
2011-03-25 04:30:50 +08:00
|
|
|
|
2011-11-03 04:55:33 +08:00
|
|
|
// TODO: this might not belong here. See if we can factor this better.
|
|
|
|
if (DirName == CompilationDir)
|
|
|
|
DirName = "";
|
|
|
|
|
2013-03-07 09:42:00 +08:00
|
|
|
// FileIDCUMap stores the current ID for the given compile unit.
|
|
|
|
unsigned SrcId = FileIDCUMap[CUID] + 1;
|
2011-10-18 07:05:28 +08:00
|
|
|
|
2013-03-07 09:42:00 +08:00
|
|
|
// We look up the CUID/file/dir by concatenating them with a zero byte.
|
2012-03-11 22:56:26 +08:00
|
|
|
SmallString<128> NamePair;
|
2013-04-06 09:02:38 +08:00
|
|
|
NamePair += utostr(CUID);
|
2013-03-07 09:42:00 +08:00
|
|
|
NamePair += '\0';
|
2012-03-11 22:56:26 +08:00
|
|
|
NamePair += DirName;
|
|
|
|
NamePair += '\0'; // Zero bytes are not allowed in paths.
|
|
|
|
NamePair += FileName;
|
|
|
|
|
|
|
|
StringMapEntry<unsigned> &Ent = SourceIdMap.GetOrCreateValue(NamePair, SrcId);
|
|
|
|
if (Ent.getValue() != SrcId)
|
|
|
|
return Ent.getValue();
|
2009-05-15 17:23:25 +08:00
|
|
|
|
2013-03-07 09:42:00 +08:00
|
|
|
FileIDCUMap[CUID] = SrcId;
|
2010-11-18 10:04:25 +08:00
|
|
|
// Print out a .file directive to specify files for .loc directives.
|
2013-03-07 09:42:00 +08:00
|
|
|
Asm->OutStreamer.EmitDwarfFileDirective(SrcId, DirName, FileName, CUID);
|
2009-05-15 17:23:25 +08:00
|
|
|
|
2009-05-21 07:21:38 +08:00
|
|
|
return SrcId;
|
|
|
|
}
|
2009-05-15 17:23:25 +08:00
|
|
|
|
2013-12-10 07:32:48 +08:00
|
|
|
void DwarfDebug::addGnuPubAttributes(DwarfUnit *U, DIE *D) const {
|
2013-12-05 05:31:26 +08:00
|
|
|
if (!GenerateGnuPubSections)
|
|
|
|
return;
|
|
|
|
|
|
|
|
addSectionLabel(Asm, U, D, dwarf::DW_AT_GNU_pubnames,
|
|
|
|
Asm->GetTempSymbol("gnu_pubnames", U->getUniqueID()),
|
|
|
|
DwarfGnuPubNamesSectionSym);
|
|
|
|
|
|
|
|
addSectionLabel(Asm, U, D, dwarf::DW_AT_GNU_pubtypes,
|
|
|
|
Asm->GetTempSymbol("gnu_pubtypes", U->getUniqueID()),
|
|
|
|
DwarfGnuPubTypesSectionSym);
|
|
|
|
}
|
|
|
|
|
2013-12-10 07:57:44 +08:00
|
|
|
// Create new DwarfCompileUnit for the given metadata node with tag
|
2012-12-21 05:58:40 +08:00
|
|
|
// DW_TAG_compile_unit.
|
2013-12-10 07:57:44 +08:00
|
|
|
DwarfCompileUnit *DwarfDebug::constructDwarfCompileUnit(DICompileUnit DIUnit) {
|
2009-11-26 01:36:49 +08:00
|
|
|
StringRef FN = DIUnit.getFilename();
|
2011-11-03 04:55:33 +08:00
|
|
|
CompilationDir = DIUnit.getDirectory();
|
2009-05-15 17:23:25 +08:00
|
|
|
|
2009-05-21 07:21:38 +08:00
|
|
|
DIE *Die = new DIE(dwarf::DW_TAG_compile_unit);
|
2013-12-10 07:57:44 +08:00
|
|
|
DwarfCompileUnit *NewCU = new DwarfCompileUnit(
|
|
|
|
InfoHolder.getUnits().size(), Die, DIUnit, Asm, this, &InfoHolder);
|
2013-12-07 03:38:46 +08:00
|
|
|
InfoHolder.addUnit(NewCU);
|
|
|
|
|
2013-03-07 09:42:00 +08:00
|
|
|
FileIDCUMap[NewCU->getUniqueID()] = 0;
|
|
|
|
// Call this to emit a .file directive if it wasn't emitted for the source
|
|
|
|
// file this CU comes from yet.
|
|
|
|
getOrCreateSourceID(FN, CompilationDir, NewCU->getUniqueID());
|
|
|
|
|
2011-10-27 14:44:11 +08:00
|
|
|
NewCU->addString(Die, dwarf::DW_AT_producer, DIUnit.getProducer());
|
2011-04-13 06:53:02 +08:00
|
|
|
NewCU->addUInt(Die, dwarf::DW_AT_language, dwarf::DW_FORM_data2,
|
|
|
|
DIUnit.getLanguage());
|
2011-10-27 14:44:11 +08:00
|
|
|
NewCU->addString(Die, dwarf::DW_AT_name, FN);
|
2013-04-10 03:23:15 +08:00
|
|
|
|
2013-02-06 05:52:47 +08:00
|
|
|
// Define start line table label for each Compile Unit.
|
2013-11-19 17:04:36 +08:00
|
|
|
MCSymbol *LineTableStartSym =
|
|
|
|
Asm->GetTempSymbol("line_table_start", NewCU->getUniqueID());
|
2013-02-06 05:52:47 +08:00
|
|
|
Asm->OutStreamer.getContext().setMCLineTableSymbol(LineTableStartSym,
|
|
|
|
NewCU->getUniqueID());
|
|
|
|
|
2013-05-21 08:57:22 +08:00
|
|
|
// Use a single line table if we are using .loc and generating assembly.
|
|
|
|
bool UseTheFirstCU =
|
2013-10-06 00:42:21 +08:00
|
|
|
(Asm->TM.hasMCUseLoc() && Asm->OutStreamer.hasRawTextSupport()) ||
|
|
|
|
(NewCU->getUniqueID() == 0);
|
2013-05-21 08:57:22 +08:00
|
|
|
|
2013-04-10 03:23:15 +08:00
|
|
|
if (!useSplitDwarf()) {
|
2013-09-28 06:50:48 +08:00
|
|
|
// DW_AT_stmt_list is a offset of line number information for this
|
|
|
|
// compile unit in debug_line section. For split dwarf this is
|
|
|
|
// left in the skeleton CU and so not included.
|
|
|
|
// The line table entries are not always emitted in assembly, so it
|
|
|
|
// is not okay to use line_table_start here.
|
2013-04-10 03:23:15 +08:00
|
|
|
if (Asm->MAI->doesDwarfUseRelocationsAcrossSections())
|
2013-12-10 07:32:48 +08:00
|
|
|
NewCU->addSectionLabel(Die, dwarf::DW_AT_stmt_list,
|
|
|
|
UseTheFirstCU ? Asm->GetTempSymbol("section_line")
|
|
|
|
: LineTableStartSym);
|
2013-05-21 08:57:22 +08:00
|
|
|
else if (UseTheFirstCU)
|
2013-11-22 07:46:41 +08:00
|
|
|
NewCU->addSectionOffset(Die, dwarf::DW_AT_stmt_list, 0);
|
2013-04-10 03:23:15 +08:00
|
|
|
else
|
2013-12-10 07:32:48 +08:00
|
|
|
NewCU->addSectionDelta(Die, dwarf::DW_AT_stmt_list, LineTableStartSym,
|
|
|
|
DwarfLineSectionSym);
|
2009-05-15 17:23:25 +08:00
|
|
|
|
2013-09-28 06:50:48 +08:00
|
|
|
// If we're using split dwarf the compilation dir is going to be in the
|
|
|
|
// skeleton CU and so we don't need to duplicate it here.
|
|
|
|
if (!CompilationDir.empty())
|
|
|
|
NewCU->addString(Die, dwarf::DW_AT_comp_dir, CompilationDir);
|
2013-09-13 08:35:05 +08:00
|
|
|
|
2013-12-05 05:31:26 +08:00
|
|
|
addGnuPubAttributes(NewCU, Die);
|
2013-09-28 06:50:48 +08:00
|
|
|
}
|
2013-09-13 08:35:05 +08:00
|
|
|
|
2009-05-21 07:21:38 +08:00
|
|
|
if (DIUnit.isOptimized())
|
2012-08-24 09:14:27 +08:00
|
|
|
NewCU->addFlag(Die, dwarf::DW_AT_APPLE_optimized);
|
2009-05-15 17:23:25 +08:00
|
|
|
|
2009-11-26 01:36:49 +08:00
|
|
|
StringRef Flags = DIUnit.getFlags();
|
|
|
|
if (!Flags.empty())
|
2011-10-27 14:44:11 +08:00
|
|
|
NewCU->addString(Die, dwarf::DW_AT_APPLE_flags, Flags);
|
2012-11-20 06:42:10 +08:00
|
|
|
|
2011-10-18 07:27:36 +08:00
|
|
|
if (unsigned RVer = DIUnit.getRunTimeVersion())
|
2011-04-13 06:53:02 +08:00
|
|
|
NewCU->addUInt(Die, dwarf::DW_AT_APPLE_major_runtime_vers,
|
2013-11-19 17:04:36 +08:00
|
|
|
dwarf::DW_FORM_data1, RVer);
|
2009-05-15 17:23:25 +08:00
|
|
|
|
2010-05-11 06:49:55 +08:00
|
|
|
if (!FirstCU)
|
|
|
|
FirstCU = NewCU;
|
2013-02-05 15:31:55 +08:00
|
|
|
|
2014-01-03 05:03:28 +08:00
|
|
|
if (useSplitDwarf()) {
|
|
|
|
NewCU->initSection(Asm->getObjFileLowering().getDwarfInfoDWOSection(),
|
|
|
|
DwarfInfoDWOSectionSym);
|
2013-12-31 01:22:27 +08:00
|
|
|
NewCU->setSkeleton(constructSkeletonCU(NewCU));
|
2014-01-03 05:03:28 +08:00
|
|
|
} else
|
|
|
|
NewCU->initSection(Asm->getObjFileLowering().getDwarfInfoSection(),
|
|
|
|
DwarfInfoSectionSym);
|
2013-12-30 11:40:32 +08:00
|
|
|
|
2013-11-16 07:52:02 +08:00
|
|
|
CUMap.insert(std::make_pair(DIUnit, NewCU));
|
2013-10-30 06:57:10 +08:00
|
|
|
CUDieMap.insert(std::make_pair(Die, NewCU));
|
2011-08-17 06:09:43 +08:00
|
|
|
return NewCU;
|
2009-05-21 07:19:06 +08:00
|
|
|
}
|
2009-05-15 17:23:25 +08:00
|
|
|
|
2012-11-28 06:43:45 +08:00
|
|
|
// Construct subprogram DIE.
|
2013-12-10 07:57:44 +08:00
|
|
|
void DwarfDebug::constructSubprogramDIE(DwarfCompileUnit *TheCU,
|
|
|
|
const MDNode *N) {
|
2013-10-18 09:57:30 +08:00
|
|
|
// FIXME: We should only call this routine once, however, during LTO if a
|
|
|
|
// program is defined in multiple CUs we could end up calling it out of
|
|
|
|
// beginModule as we walk the CUs.
|
|
|
|
|
2013-12-10 07:57:44 +08:00
|
|
|
DwarfCompileUnit *&CURef = SPMap[N];
|
2013-10-18 09:57:30 +08:00
|
|
|
if (CURef)
|
|
|
|
return;
|
|
|
|
CURef = TheCU;
|
2011-11-05 03:00:29 +08:00
|
|
|
|
2009-08-29 07:24:31 +08:00
|
|
|
DISubprogram SP(N);
|
2009-05-21 07:21:38 +08:00
|
|
|
if (!SP.isDefinition())
|
|
|
|
// This is a method declaration which will be handled while constructing
|
|
|
|
// class type.
|
2009-06-26 09:49:18 +08:00
|
|
|
return;
|
2009-05-21 07:04:56 +08:00
|
|
|
|
2011-08-16 01:24:54 +08:00
|
|
|
DIE *SubprogramDie = TheCU->getOrCreateSubprogramDIE(SP);
|
2010-04-07 05:38:29 +08:00
|
|
|
|
2013-09-10 04:03:20 +08:00
|
|
|
// Expose as a global name.
|
2013-10-17 10:06:06 +08:00
|
|
|
TheCU->addGlobalName(SP.getName(), SubprogramDie, resolve(SP.getContext()));
|
2009-05-21 07:19:06 +08:00
|
|
|
}
|
2009-05-15 17:23:25 +08:00
|
|
|
|
2013-12-10 07:57:44 +08:00
|
|
|
void DwarfDebug::constructImportedEntityDIE(DwarfCompileUnit *TheCU,
|
2013-04-22 14:12:31 +08:00
|
|
|
const MDNode *N) {
|
2013-05-08 05:35:53 +08:00
|
|
|
DIImportedEntity Module(N);
|
2013-04-22 14:12:31 +08:00
|
|
|
if (!Module.Verify())
|
|
|
|
return;
|
2013-05-07 07:33:07 +08:00
|
|
|
if (DIE *D = TheCU->getOrCreateContextDIE(Module.getContext()))
|
2013-05-08 14:01:38 +08:00
|
|
|
constructImportedEntityDIE(TheCU, Module, D);
|
2013-05-07 07:33:07 +08:00
|
|
|
}
|
|
|
|
|
2013-12-10 07:57:44 +08:00
|
|
|
void DwarfDebug::constructImportedEntityDIE(DwarfCompileUnit *TheCU,
|
|
|
|
const MDNode *N, DIE *Context) {
|
2013-05-08 05:35:53 +08:00
|
|
|
DIImportedEntity Module(N);
|
2013-05-07 07:33:07 +08:00
|
|
|
if (!Module.Verify())
|
|
|
|
return;
|
2013-05-08 14:01:38 +08:00
|
|
|
return constructImportedEntityDIE(TheCU, Module, Context);
|
2013-05-07 07:33:07 +08:00
|
|
|
}
|
|
|
|
|
2013-12-10 07:57:44 +08:00
|
|
|
void DwarfDebug::constructImportedEntityDIE(DwarfCompileUnit *TheCU,
|
2013-05-08 05:35:53 +08:00
|
|
|
const DIImportedEntity &Module,
|
2013-05-07 07:33:07 +08:00
|
|
|
DIE *Context) {
|
|
|
|
assert(Module.Verify() &&
|
|
|
|
"Use one of the MDNode * overloads to handle invalid metadata");
|
|
|
|
assert(Context && "Should always have a context for an imported_module");
|
2013-05-08 05:35:53 +08:00
|
|
|
DIE *IMDie = new DIE(Module.getTag());
|
2013-04-22 14:12:31 +08:00
|
|
|
TheCU->insertDIE(Module, IMDie);
|
2013-05-08 05:35:53 +08:00
|
|
|
DIE *EntityDie;
|
|
|
|
DIDescriptor Entity = Module.getEntity();
|
|
|
|
if (Entity.isNameSpace())
|
|
|
|
EntityDie = TheCU->getOrCreateNameSpace(DINameSpace(Entity));
|
|
|
|
else if (Entity.isSubprogram())
|
|
|
|
EntityDie = TheCU->getOrCreateSubprogramDIE(DISubprogram(Entity));
|
2013-05-08 14:01:41 +08:00
|
|
|
else if (Entity.isType())
|
|
|
|
EntityDie = TheCU->getOrCreateTypeDIE(DIType(Entity));
|
2013-05-08 05:35:53 +08:00
|
|
|
else
|
2013-05-08 14:01:41 +08:00
|
|
|
EntityDie = TheCU->getDIE(Entity);
|
2013-04-22 14:12:31 +08:00
|
|
|
unsigned FileID = getOrCreateSourceID(Module.getContext().getFilename(),
|
|
|
|
Module.getContext().getDirectory(),
|
|
|
|
TheCU->getUniqueID());
|
2013-10-22 01:28:37 +08:00
|
|
|
TheCU->addUInt(IMDie, dwarf::DW_AT_decl_file, None, FileID);
|
|
|
|
TheCU->addUInt(IMDie, dwarf::DW_AT_decl_line, None, Module.getLineNumber());
|
2013-10-12 07:58:05 +08:00
|
|
|
TheCU->addDIEEntry(IMDie, dwarf::DW_AT_import, EntityDie);
|
2013-05-21 06:50:35 +08:00
|
|
|
StringRef Name = Module.getName();
|
|
|
|
if (!Name.empty())
|
|
|
|
TheCU->addString(IMDie, dwarf::DW_AT_name, Name);
|
2013-05-07 07:33:07 +08:00
|
|
|
Context->addChild(IMDie);
|
2013-04-22 14:12:31 +08:00
|
|
|
}
|
|
|
|
|
2012-11-28 06:43:45 +08:00
|
|
|
// Emit all Dwarf sections that should come prior to the content. Create
|
|
|
|
// global DIEs and emit initial debug info sections. This is invoked by
|
|
|
|
// the target AsmPrinter.
|
2012-11-20 06:42:15 +08:00
|
|
|
void DwarfDebug::beginModule() {
|
2010-04-28 03:46:33 +08:00
|
|
|
if (DisableDebugInfoPrinting)
|
|
|
|
return;
|
|
|
|
|
2012-11-20 06:42:15 +08:00
|
|
|
const Module *M = MMI->getModule();
|
|
|
|
|
2011-07-29 11:49:23 +08:00
|
|
|
// If module has named metadata anchors then use them, otherwise scan the
|
|
|
|
// module using debug info finder to collect debug info.
|
2011-05-04 00:45:22 +08:00
|
|
|
NamedMDNode *CU_Nodes = M->getNamedMetadata("llvm.dbg.cu");
|
2013-03-12 07:39:23 +08:00
|
|
|
if (!CU_Nodes)
|
2011-08-16 07:47:24 +08:00
|
|
|
return;
|
2013-09-06 02:48:31 +08:00
|
|
|
TypeIdentifierMap = generateDITypeIdentifierMap(CU_Nodes);
|
2010-04-05 10:19:28 +08:00
|
|
|
|
2013-03-12 07:39:23 +08:00
|
|
|
// Emit initial sections so we can reference labels later.
|
|
|
|
emitSectionLabels();
|
|
|
|
|
|
|
|
for (unsigned i = 0, e = CU_Nodes->getNumOperands(); i != e; ++i) {
|
|
|
|
DICompileUnit CUNode(CU_Nodes->getOperand(i));
|
2013-12-10 07:57:44 +08:00
|
|
|
DwarfCompileUnit *CU = constructDwarfCompileUnit(CUNode);
|
2013-05-08 05:35:53 +08:00
|
|
|
DIArray ImportedEntities = CUNode.getImportedEntities();
|
|
|
|
for (unsigned i = 0, e = ImportedEntities.getNumElements(); i != e; ++i)
|
2013-05-07 07:33:07 +08:00
|
|
|
ScopesWithImportedEntities.push_back(std::make_pair(
|
2013-05-08 05:35:53 +08:00
|
|
|
DIImportedEntity(ImportedEntities.getElement(i)).getContext(),
|
|
|
|
ImportedEntities.getElement(i)));
|
2013-05-07 07:33:07 +08:00
|
|
|
std::sort(ScopesWithImportedEntities.begin(),
|
2013-08-24 20:54:27 +08:00
|
|
|
ScopesWithImportedEntities.end(), less_first());
|
2013-03-12 07:39:23 +08:00
|
|
|
DIArray GVs = CUNode.getGlobalVariables();
|
|
|
|
for (unsigned i = 0, e = GVs.getNumElements(); i != e; ++i)
|
2013-11-18 05:55:13 +08:00
|
|
|
CU->createGlobalVariableDIE(DIGlobalVariable(GVs.getElement(i)));
|
2013-03-12 07:39:23 +08:00
|
|
|
DIArray SPs = CUNode.getSubprograms();
|
|
|
|
for (unsigned i = 0, e = SPs.getNumElements(); i != e; ++i)
|
|
|
|
constructSubprogramDIE(CU, SPs.getElement(i));
|
|
|
|
DIArray EnumTypes = CUNode.getEnumTypes();
|
|
|
|
for (unsigned i = 0, e = EnumTypes.getNumElements(); i != e; ++i)
|
|
|
|
CU->getOrCreateTypeDIE(EnumTypes.getElement(i));
|
|
|
|
DIArray RetainedTypes = CUNode.getRetainedTypes();
|
|
|
|
for (unsigned i = 0, e = RetainedTypes.getNumElements(); i != e; ++i)
|
|
|
|
CU->getOrCreateTypeDIE(RetainedTypes.getElement(i));
|
2013-04-22 14:12:31 +08:00
|
|
|
// Emit imported_modules last so that the relevant context is already
|
|
|
|
// available.
|
2013-05-08 05:35:53 +08:00
|
|
|
for (unsigned i = 0, e = ImportedEntities.getNumElements(); i != e; ++i)
|
|
|
|
constructImportedEntityDIE(CU, ImportedEntities.getElement(i));
|
2013-03-12 07:39:23 +08:00
|
|
|
}
|
2012-11-20 06:42:10 +08:00
|
|
|
|
2010-04-05 10:19:28 +08:00
|
|
|
// Tell MMI that we have debug info.
|
|
|
|
MMI->setDebugInfoAvailability(true);
|
2012-11-20 06:42:10 +08:00
|
|
|
|
2009-05-21 07:21:38 +08:00
|
|
|
// Prime section data.
|
2013-09-20 07:21:01 +08:00
|
|
|
SectionMap[Asm->getObjFileLowering().getTextSection()];
|
2009-05-21 07:21:38 +08:00
|
|
|
}
|
2009-05-15 17:23:25 +08:00
|
|
|
|
2012-11-22 08:59:49 +08:00
|
|
|
// Attach DW_AT_inline attribute with inlined subprogram DIEs.
|
|
|
|
void DwarfDebug::computeInlinedDIEs() {
|
|
|
|
// Attach DW_AT_inline attribute with inlined subprogram DIEs.
|
|
|
|
for (SmallPtrSet<DIE *, 4>::iterator AI = InlinedSubprogramDIEs.begin(),
|
2013-11-19 17:04:36 +08:00
|
|
|
AE = InlinedSubprogramDIEs.end();
|
|
|
|
AI != AE; ++AI) {
|
2012-11-22 08:59:49 +08:00
|
|
|
DIE *ISP = *AI;
|
2013-10-22 01:28:37 +08:00
|
|
|
FirstCU->addUInt(ISP, dwarf::DW_AT_inline, None, dwarf::DW_INL_inlined);
|
2012-11-22 08:59:49 +08:00
|
|
|
}
|
|
|
|
for (DenseMap<const MDNode *, DIE *>::iterator AI = AbstractSPDies.begin(),
|
2013-11-19 17:04:36 +08:00
|
|
|
AE = AbstractSPDies.end();
|
|
|
|
AI != AE; ++AI) {
|
2012-11-22 08:59:49 +08:00
|
|
|
DIE *ISP = AI->second;
|
|
|
|
if (InlinedSubprogramDIEs.count(ISP))
|
|
|
|
continue;
|
2013-10-22 01:28:37 +08:00
|
|
|
FirstCU->addUInt(ISP, dwarf::DW_AT_inline, None, dwarf::DW_INL_inlined);
|
2012-11-22 08:59:49 +08:00
|
|
|
}
|
|
|
|
}
|
2012-11-20 06:42:15 +08:00
|
|
|
|
2012-11-22 08:59:49 +08:00
|
|
|
// Collect info for variables that were optimized out.
|
|
|
|
void DwarfDebug::collectDeadVariables() {
|
2010-06-29 02:25:03 +08:00
|
|
|
const Module *M = MMI->getModule();
|
2010-07-22 05:21:52 +08:00
|
|
|
|
2011-08-17 06:09:43 +08:00
|
|
|
if (NamedMDNode *CU_Nodes = M->getNamedMetadata("llvm.dbg.cu")) {
|
|
|
|
for (unsigned i = 0, e = CU_Nodes->getNumOperands(); i != e; ++i) {
|
|
|
|
DICompileUnit TheCU(CU_Nodes->getOperand(i));
|
|
|
|
DIArray Subprograms = TheCU.getSubprograms();
|
|
|
|
for (unsigned i = 0, e = Subprograms.getNumElements(); i != e; ++i) {
|
2012-11-27 08:13:51 +08:00
|
|
|
DISubprogram SP(Subprograms.getElement(i));
|
2013-10-16 07:31:38 +08:00
|
|
|
if (ProcessedSPNodes.count(SP) != 0)
|
|
|
|
continue;
|
|
|
|
if (!SP.isSubprogram())
|
|
|
|
continue;
|
|
|
|
if (!SP.isDefinition())
|
|
|
|
continue;
|
2012-11-27 08:13:51 +08:00
|
|
|
DIArray Variables = SP.getVariables();
|
2013-10-16 07:31:38 +08:00
|
|
|
if (Variables.getNumElements() == 0)
|
|
|
|
continue;
|
2012-11-27 08:13:51 +08:00
|
|
|
|
|
|
|
// Construct subprogram DIE and add variables DIEs.
|
2013-12-10 07:57:44 +08:00
|
|
|
DwarfCompileUnit *SPCU =
|
|
|
|
static_cast<DwarfCompileUnit *>(CUMap.lookup(TheCU));
|
2012-11-27 08:13:51 +08:00
|
|
|
assert(SPCU && "Unable to find Compile Unit!");
|
2013-10-22 08:22:39 +08:00
|
|
|
// FIXME: See the comment in constructSubprogramDIE about duplicate
|
|
|
|
// subprogram DIEs.
|
|
|
|
constructSubprogramDIE(SPCU, SP);
|
|
|
|
DIE *SPDIE = SPCU->getDIE(SP);
|
2012-11-27 08:13:51 +08:00
|
|
|
for (unsigned vi = 0, ve = Variables.getNumElements(); vi != ve; ++vi) {
|
|
|
|
DIVariable DV(Variables.getElement(vi));
|
2013-10-16 07:31:38 +08:00
|
|
|
if (!DV.isVariable())
|
|
|
|
continue;
|
2013-10-05 09:43:03 +08:00
|
|
|
DbgVariable NewVar(DV, NULL, this);
|
2013-11-19 17:04:36 +08:00
|
|
|
if (DIE *VariableDIE = SPCU->constructVariableDIE(NewVar, false))
|
2013-10-16 07:31:38 +08:00
|
|
|
SPDIE->addChild(VariableDIE);
|
2012-11-27 08:13:51 +08:00
|
|
|
}
|
2010-06-29 02:25:03 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2012-11-22 08:59:49 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void DwarfDebug::finalizeModuleInfo() {
|
|
|
|
// Collect info for variables that were optimized out.
|
|
|
|
collectDeadVariables();
|
2009-05-15 17:23:25 +08:00
|
|
|
|
2009-11-11 07:06:00 +08:00
|
|
|
// Attach DW_AT_inline attribute with inlined subprogram DIEs.
|
2012-11-22 08:59:49 +08:00
|
|
|
computeInlinedDIEs();
|
2009-11-11 07:06:00 +08:00
|
|
|
|
2013-12-05 07:24:38 +08:00
|
|
|
// Handle anything that needs to be done on a per-unit basis after
|
|
|
|
// all other generation.
|
2013-12-10 07:32:48 +08:00
|
|
|
for (SmallVectorImpl<DwarfUnit *>::const_iterator I = getUnits().begin(),
|
|
|
|
E = getUnits().end();
|
2013-11-27 03:14:34 +08:00
|
|
|
I != E; ++I) {
|
2013-12-10 07:32:48 +08:00
|
|
|
DwarfUnit *TheU = *I;
|
2013-08-13 04:27:48 +08:00
|
|
|
// Emit DW_AT_containing_type attribute to connect types with their
|
|
|
|
// vtable holding type.
|
2013-12-03 06:09:48 +08:00
|
|
|
TheU->constructContainingTypeDIEs();
|
2013-08-13 04:27:48 +08:00
|
|
|
|
2013-12-20 12:16:18 +08:00
|
|
|
// Add CU specific attributes if we need to add any.
|
|
|
|
if (TheU->getUnitDie()->getTag() == dwarf::DW_TAG_compile_unit) {
|
|
|
|
// If we're splitting the dwarf out now that we've got the entire
|
2013-12-31 01:22:27 +08:00
|
|
|
// CU then add the dwo id to it.
|
|
|
|
DwarfCompileUnit *SkCU =
|
|
|
|
static_cast<DwarfCompileUnit *>(TheU->getSkeleton());
|
2013-12-20 12:16:18 +08:00
|
|
|
if (useSplitDwarf()) {
|
|
|
|
// This should be a unique identifier when we want to build .dwp files.
|
|
|
|
uint64_t ID = 0;
|
|
|
|
if (GenerateCUHash) {
|
|
|
|
DIEHash CUHash;
|
|
|
|
ID = CUHash.computeCUSignature(*TheU->getUnitDie());
|
|
|
|
}
|
|
|
|
TheU->addUInt(TheU->getUnitDie(), dwarf::DW_AT_GNU_dwo_id,
|
|
|
|
dwarf::DW_FORM_data8, ID);
|
|
|
|
SkCU->addUInt(SkCU->getUnitDie(), dwarf::DW_AT_GNU_dwo_id,
|
|
|
|
dwarf::DW_FORM_data8, ID);
|
2013-08-13 09:21:55 +08:00
|
|
|
}
|
2013-12-31 01:22:27 +08:00
|
|
|
|
|
|
|
// If we've requested ranges and have them emit a DW_AT_ranges attribute
|
2014-01-03 10:17:35 +08:00
|
|
|
// on the unit that will remain in the .o file, otherwise add a
|
|
|
|
// DW_AT_low_pc.
|
2013-12-31 01:22:27 +08:00
|
|
|
// FIXME: Also add a high pc if we can.
|
|
|
|
// FIXME: We should use ranges if we have multiple compile units.
|
|
|
|
DwarfCompileUnit *U = SkCU ? SkCU : static_cast<DwarfCompileUnit *>(TheU);
|
|
|
|
if (DwarfCURanges && TheU->getRanges().size())
|
|
|
|
addSectionLabel(Asm, U, U->getUnitDie(), dwarf::DW_AT_ranges,
|
|
|
|
Asm->GetTempSymbol("cu_ranges", U->getUniqueID()),
|
|
|
|
DwarfDebugRangeSectionSym);
|
|
|
|
else
|
2014-01-03 10:17:35 +08:00
|
|
|
U->addUInt(U->getUnitDie(), dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr,
|
|
|
|
0);
|
2013-08-13 04:27:48 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Compute DIE offsets and sizes.
|
2012-12-11 07:34:43 +08:00
|
|
|
InfoHolder.computeSizeAndOffsets();
|
|
|
|
if (useSplitDwarf())
|
|
|
|
SkeletonHolder.computeSizeAndOffsets();
|
2012-11-22 08:59:49 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void DwarfDebug::endSections() {
|
2013-11-19 17:04:36 +08:00
|
|
|
// Filter labels by section.
|
2013-10-03 16:54:43 +08:00
|
|
|
for (size_t n = 0; n < ArangeLabels.size(); n++) {
|
|
|
|
const SymbolCU &SCU = ArangeLabels[n];
|
2013-09-20 07:21:01 +08:00
|
|
|
if (SCU.Sym->isInSection()) {
|
|
|
|
// Make a note of this symbol and it's section.
|
|
|
|
const MCSection *Section = &SCU.Sym->getSection();
|
|
|
|
if (!Section->getKind().isMetadata())
|
|
|
|
SectionMap[Section].push_back(SCU);
|
|
|
|
} else {
|
|
|
|
// Some symbols (e.g. common/bss on mach-o) can have no section but still
|
|
|
|
// appear in the output. This sucks as we rely on sections to build
|
|
|
|
// arange spans. We can do it without, but it's icky.
|
|
|
|
SectionMap[NULL].push_back(SCU);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-10-04 06:07:08 +08:00
|
|
|
// Build a list of sections used.
|
|
|
|
std::vector<const MCSection *> Sections;
|
2013-09-20 07:21:01 +08:00
|
|
|
for (SectionMapType::iterator it = SectionMap.begin(); it != SectionMap.end();
|
|
|
|
it++) {
|
|
|
|
const MCSection *Section = it->first;
|
2013-10-04 06:07:08 +08:00
|
|
|
Sections.push_back(Section);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Sort the sections into order.
|
|
|
|
// This is only done to ensure consistent output order across different runs.
|
|
|
|
std::sort(Sections.begin(), Sections.end(), SectionSort);
|
|
|
|
|
|
|
|
// Add terminating symbols for each section.
|
2013-11-19 17:04:36 +08:00
|
|
|
for (unsigned ID = 0; ID < Sections.size(); ID++) {
|
2013-10-04 06:07:08 +08:00
|
|
|
const MCSection *Section = Sections[ID];
|
2013-09-20 07:21:01 +08:00
|
|
|
MCSymbol *Sym = NULL;
|
2009-05-15 17:23:25 +08:00
|
|
|
|
2013-09-20 07:21:01 +08:00
|
|
|
if (Section) {
|
2013-10-04 06:07:08 +08:00
|
|
|
// We can't call MCSection::getLabelEndName, as it's only safe to do so
|
2013-11-19 17:04:36 +08:00
|
|
|
// if we know the section name up-front. For user-created sections, the
|
|
|
|
// resulting
|
|
|
|
// label may not be valid to use as a label. (section names can use a
|
|
|
|
// greater
|
2013-10-04 06:07:08 +08:00
|
|
|
// set of characters on some systems)
|
|
|
|
Sym = Asm->GetTempSymbol("debug_end", ID);
|
2013-09-20 07:21:01 +08:00
|
|
|
Asm->OutStreamer.SwitchSection(Section);
|
|
|
|
Asm->OutStreamer.EmitLabel(Sym);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Insert a final terminator.
|
2013-10-03 16:54:43 +08:00
|
|
|
SectionMap[Section].push_back(SymbolCU(NULL, Sym));
|
2009-05-21 07:21:38 +08:00
|
|
|
}
|
2012-11-22 08:59:49 +08:00
|
|
|
}
|
2009-05-15 17:23:25 +08:00
|
|
|
|
2012-11-28 06:43:45 +08:00
|
|
|
// Emit all Dwarf sections that should come after the content.
|
2012-11-22 08:59:49 +08:00
|
|
|
void DwarfDebug::endModule() {
|
2013-12-03 23:10:23 +08:00
|
|
|
assert(CurFn == 0);
|
|
|
|
assert(CurMI == 0);
|
2012-11-22 08:59:49 +08:00
|
|
|
|
2013-11-19 17:04:36 +08:00
|
|
|
if (!FirstCU)
|
|
|
|
return;
|
2012-11-22 08:59:49 +08:00
|
|
|
|
|
|
|
// End any existing sections.
|
|
|
|
// TODO: Does this need to happen?
|
|
|
|
endSections();
|
|
|
|
|
|
|
|
// Finalize the debug info for the module.
|
|
|
|
finalizeModuleInfo();
|
2009-05-15 17:23:25 +08:00
|
|
|
|
2013-11-19 17:04:50 +08:00
|
|
|
emitDebugStr();
|
2013-09-21 07:22:52 +08:00
|
|
|
|
2013-11-19 17:04:50 +08:00
|
|
|
// Emit all the DIEs into a debug info section.
|
|
|
|
emitDebugInfo();
|
2012-11-27 08:41:54 +08:00
|
|
|
|
2013-11-19 17:04:50 +08:00
|
|
|
// Corresponding abbreviations into a abbrev section.
|
|
|
|
emitAbbreviations();
|
2012-11-28 06:43:42 +08:00
|
|
|
|
2013-11-19 17:04:50 +08:00
|
|
|
// Emit info into a debug loc section.
|
|
|
|
emitDebugLoc();
|
2012-11-28 06:43:42 +08:00
|
|
|
|
2013-11-19 17:04:50 +08:00
|
|
|
// Emit info into a debug aranges section.
|
|
|
|
emitDebugARanges();
|
2012-11-28 06:43:42 +08:00
|
|
|
|
2013-11-19 17:04:50 +08:00
|
|
|
// Emit info into a debug ranges section.
|
|
|
|
emitDebugRanges();
|
2012-11-28 06:43:42 +08:00
|
|
|
|
2013-11-19 17:04:50 +08:00
|
|
|
if (useSplitDwarf()) {
|
|
|
|
emitDebugStrDWO();
|
2012-12-01 07:59:06 +08:00
|
|
|
emitDebugInfoDWO();
|
2012-12-20 06:02:53 +08:00
|
|
|
emitDebugAbbrevDWO();
|
2013-01-16 07:56:56 +08:00
|
|
|
// Emit DWO addresses.
|
|
|
|
InfoHolder.emitAddresses(Asm->getObjFileLowering().getDwarfAddrSection());
|
2012-11-28 06:43:42 +08:00
|
|
|
}
|
2009-05-15 17:23:25 +08:00
|
|
|
|
2012-08-23 15:32:06 +08:00
|
|
|
// Emit info into the dwarf accelerator table sections.
|
2012-08-24 06:36:40 +08:00
|
|
|
if (useDwarfAccelTables()) {
|
2011-11-07 17:24:32 +08:00
|
|
|
emitAccelNames();
|
|
|
|
emitAccelObjC();
|
|
|
|
emitAccelNamespaces();
|
|
|
|
emitAccelTypes();
|
|
|
|
}
|
2012-11-20 06:42:10 +08:00
|
|
|
|
2013-08-30 08:40:17 +08:00
|
|
|
// Emit the pubnames and pubtypes sections if requested.
|
|
|
|
if (HasDwarfPubSections) {
|
2013-09-20 01:33:35 +08:00
|
|
|
emitDebugPubNames(GenerateGnuPubSections);
|
|
|
|
emitDebugPubTypes(GenerateGnuPubSections);
|
2013-08-30 08:40:17 +08:00
|
|
|
}
|
2009-11-24 09:14:22 +08:00
|
|
|
|
2010-08-03 01:32:15 +08:00
|
|
|
// clean up.
|
2011-08-17 06:09:43 +08:00
|
|
|
SPMap.clear();
|
2012-12-11 03:51:18 +08:00
|
|
|
|
2012-12-01 07:59:06 +08:00
|
|
|
// Reset these for the next Module if we have one.
|
|
|
|
FirstCU = NULL;
|
2009-05-21 07:21:38 +08:00
|
|
|
}
|
2009-05-15 17:23:25 +08:00
|
|
|
|
2012-11-28 06:43:45 +08:00
|
|
|
// Find abstract variable, if any, associated with Var.
|
2011-08-11 05:50:54 +08:00
|
|
|
DbgVariable *DwarfDebug::findAbstractVariable(DIVariable &DV,
|
2010-04-03 03:42:39 +08:00
|
|
|
DebugLoc ScopeLoc) {
|
2011-08-11 05:50:54 +08:00
|
|
|
LLVMContext &Ctx = DV->getContext();
|
|
|
|
// More then one inlined variable corresponds to one abstract variable.
|
|
|
|
DIVariable Var = cleanseInlinedVariable(DV, Ctx);
|
2010-05-08 02:11:54 +08:00
|
|
|
DbgVariable *AbsDbgVariable = AbstractVariables.lookup(Var);
|
2010-03-16 02:33:46 +08:00
|
|
|
if (AbsDbgVariable)
|
|
|
|
return AbsDbgVariable;
|
|
|
|
|
2011-08-11 04:55:27 +08:00
|
|
|
LexicalScope *Scope = LScopes.findAbstractScope(ScopeLoc.getScope(Ctx));
|
2010-03-16 02:33:46 +08:00
|
|
|
if (!Scope)
|
|
|
|
return NULL;
|
|
|
|
|
2013-10-05 09:43:03 +08:00
|
|
|
AbsDbgVariable = new DbgVariable(Var, NULL, this);
|
2011-08-11 04:55:27 +08:00
|
|
|
addScopeVariable(Scope, AbsDbgVariable);
|
2010-05-08 02:11:54 +08:00
|
|
|
AbstractVariables[Var] = AbsDbgVariable;
|
2010-03-16 02:33:46 +08:00
|
|
|
return AbsDbgVariable;
|
|
|
|
}
|
|
|
|
|
2012-11-28 06:43:45 +08:00
|
|
|
// If Var is a current function argument then add it to CurrentFnArguments list.
|
2013-12-03 23:10:23 +08:00
|
|
|
bool DwarfDebug::addCurrentFnArgument(DbgVariable *Var, LexicalScope *Scope) {
|
2011-08-11 04:55:27 +08:00
|
|
|
if (!LScopes.isCurrentFunctionScope(Scope))
|
2011-03-02 06:58:55 +08:00
|
|
|
return false;
|
|
|
|
DIVariable DV = Var->getVariable();
|
|
|
|
if (DV.getTag() != dwarf::DW_TAG_arg_variable)
|
|
|
|
return false;
|
|
|
|
unsigned ArgNo = DV.getArgNumber();
|
2012-11-20 06:42:10 +08:00
|
|
|
if (ArgNo == 0)
|
2011-03-02 06:58:55 +08:00
|
|
|
return false;
|
|
|
|
|
2011-03-04 04:02:02 +08:00
|
|
|
size_t Size = CurrentFnArguments.size();
|
|
|
|
if (Size == 0)
|
2013-12-03 23:10:23 +08:00
|
|
|
CurrentFnArguments.resize(CurFn->getFunction()->arg_size());
|
2011-03-04 05:49:41 +08:00
|
|
|
// llvm::Function argument size is not good indicator of how many
|
2011-03-04 04:08:10 +08:00
|
|
|
// arguments does the function have at source level.
|
|
|
|
if (ArgNo > Size)
|
2011-03-04 04:02:02 +08:00
|
|
|
CurrentFnArguments.resize(ArgNo * 2);
|
2011-03-02 06:58:55 +08:00
|
|
|
CurrentFnArguments[ArgNo - 1] = Var;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2012-11-28 06:43:45 +08:00
|
|
|
// Collect variable information from side table maintained by MMI.
|
2013-11-19 17:04:36 +08:00
|
|
|
void DwarfDebug::collectVariableInfoFromMMITable(
|
2013-12-03 23:10:23 +08:00
|
|
|
SmallPtrSet<const MDNode *, 16> &Processed) {
|
2009-10-06 09:26:37 +08:00
|
|
|
MachineModuleInfo::VariableDbgInfoMapTy &VMap = MMI->getVariableDbgInfo();
|
|
|
|
for (MachineModuleInfo::VariableDbgInfoMapTy::iterator VI = VMap.begin(),
|
2013-11-19 17:04:36 +08:00
|
|
|
VE = VMap.end();
|
|
|
|
VI != VE; ++VI) {
|
2010-05-08 04:54:48 +08:00
|
|
|
const MDNode *Var = VI->first;
|
2013-11-19 17:04:36 +08:00
|
|
|
if (!Var)
|
|
|
|
continue;
|
2010-05-15 05:01:35 +08:00
|
|
|
Processed.insert(Var);
|
2010-04-03 03:42:39 +08:00
|
|
|
DIVariable DV(Var);
|
|
|
|
const std::pair<unsigned, DebugLoc> &VP = VI->second;
|
|
|
|
|
2011-08-11 04:55:27 +08:00
|
|
|
LexicalScope *Scope = LScopes.findLexicalScope(VP.second);
|
2010-07-22 05:21:52 +08:00
|
|
|
|
2009-11-11 07:20:04 +08:00
|
|
|
// If variable scope is not found then skip this variable.
|
2010-04-03 03:42:39 +08:00
|
|
|
if (Scope == 0)
|
2009-11-11 07:20:04 +08:00
|
|
|
continue;
|
2009-11-11 07:06:00 +08:00
|
|
|
|
2010-05-21 00:36:41 +08:00
|
|
|
DbgVariable *AbsDbgVariable = findAbstractVariable(DV, VP.second);
|
2013-10-05 09:43:03 +08:00
|
|
|
DbgVariable *RegVar = new DbgVariable(DV, AbsDbgVariable, this);
|
2011-08-16 05:24:36 +08:00
|
|
|
RegVar->setFrameIndex(VP.first);
|
2013-12-03 23:10:23 +08:00
|
|
|
if (!addCurrentFnArgument(RegVar, Scope))
|
2011-08-11 04:55:27 +08:00
|
|
|
addScopeVariable(Scope, RegVar);
|
2011-08-16 03:01:20 +08:00
|
|
|
if (AbsDbgVariable)
|
2011-08-16 05:24:36 +08:00
|
|
|
AbsDbgVariable->setFrameIndex(VP.first);
|
2009-10-06 09:26:37 +08:00
|
|
|
}
|
2010-05-21 03:57:06 +08:00
|
|
|
}
|
|
|
|
|
2012-11-28 06:43:45 +08:00
|
|
|
// Return true if debug value, encoded by DBG_VALUE instruction, is in a
|
|
|
|
// defined reg.
|
2010-05-26 07:40:22 +08:00
|
|
|
static bool isDbgValueInDefinedReg(const MachineInstr *MI) {
|
2011-10-27 06:55:33 +08:00
|
|
|
assert(MI->isDebugValue() && "Invalid DBG_VALUE machine instruction!");
|
2013-11-19 17:04:36 +08:00
|
|
|
return MI->getNumOperands() == 3 && MI->getOperand(0).isReg() &&
|
|
|
|
MI->getOperand(0).getReg() &&
|
2013-07-10 04:28:37 +08:00
|
|
|
(MI->getOperand(1).isImm() ||
|
|
|
|
(MI->getOperand(1).isReg() && MI->getOperand(1).getReg() == 0U));
|
2010-05-26 07:40:22 +08:00
|
|
|
}
|
|
|
|
|
2012-11-28 06:43:45 +08:00
|
|
|
// Get .debug_loc entry for the instruction range starting at MI.
|
2012-11-20 06:42:10 +08:00
|
|
|
static DotDebugLocEntry getDebugLocEntry(AsmPrinter *Asm,
|
|
|
|
const MCSymbol *FLabel,
|
2011-07-09 01:09:57 +08:00
|
|
|
const MCSymbol *SLabel,
|
|
|
|
const MachineInstr *MI) {
|
2013-11-19 17:04:36 +08:00
|
|
|
const MDNode *Var = MI->getOperand(MI->getNumOperands() - 1).getMetadata();
|
2011-07-09 01:09:57 +08:00
|
|
|
|
2013-06-17 04:34:15 +08:00
|
|
|
assert(MI->getNumOperands() == 3);
|
2013-07-10 04:28:37 +08:00
|
|
|
if (MI->getOperand(0).isReg()) {
|
2011-07-09 01:09:57 +08:00
|
|
|
MachineLocation MLoc;
|
2013-07-10 04:28:37 +08:00
|
|
|
// If the second operand is an immediate, this is a
|
|
|
|
// register-indirect address.
|
|
|
|
if (!MI->getOperand(1).isImm())
|
2013-04-27 05:57:17 +08:00
|
|
|
MLoc.set(MI->getOperand(0).getReg());
|
|
|
|
else
|
|
|
|
MLoc.set(MI->getOperand(0).getReg(), MI->getOperand(1).getImm());
|
2011-07-09 01:09:57 +08:00
|
|
|
return DotDebugLocEntry(FLabel, SLabel, MLoc, Var);
|
|
|
|
}
|
|
|
|
if (MI->getOperand(0).isImm())
|
|
|
|
return DotDebugLocEntry(FLabel, SLabel, MI->getOperand(0).getImm());
|
|
|
|
if (MI->getOperand(0).isFPImm())
|
|
|
|
return DotDebugLocEntry(FLabel, SLabel, MI->getOperand(0).getFPImm());
|
|
|
|
if (MI->getOperand(0).isCImm())
|
|
|
|
return DotDebugLocEntry(FLabel, SLabel, MI->getOperand(0).getCImm());
|
|
|
|
|
2012-02-05 16:31:47 +08:00
|
|
|
llvm_unreachable("Unexpected 3 operand DBG_VALUE instruction!");
|
2011-07-09 01:09:57 +08:00
|
|
|
}
|
|
|
|
|
2012-11-28 06:43:45 +08:00
|
|
|
// Find variables for each lexical scope.
|
2010-07-22 05:21:52 +08:00
|
|
|
void
|
2013-12-03 23:10:23 +08:00
|
|
|
DwarfDebug::collectVariableInfo(SmallPtrSet<const MDNode *, 16> &Processed) {
|
2010-07-22 05:21:52 +08:00
|
|
|
|
2013-07-04 05:37:03 +08:00
|
|
|
// Grab the variable info that was squirreled away in the MMI side-table.
|
2013-12-03 23:10:23 +08:00
|
|
|
collectVariableInfoFromMMITable(Processed);
|
2010-03-16 02:33:46 +08:00
|
|
|
|
2013-11-19 17:04:36 +08:00
|
|
|
for (SmallVectorImpl<const MDNode *>::const_iterator
|
|
|
|
UVI = UserVariables.begin(),
|
|
|
|
UVE = UserVariables.end();
|
|
|
|
UVI != UVE; ++UVI) {
|
2011-03-26 10:19:36 +08:00
|
|
|
const MDNode *Var = *UVI;
|
|
|
|
if (Processed.count(Var))
|
2010-05-21 03:57:06 +08:00
|
|
|
continue;
|
2010-03-16 02:33:46 +08:00
|
|
|
|
2011-03-26 10:19:36 +08:00
|
|
|
// History contains relevant DBG_VALUE instructions for Var and instructions
|
|
|
|
// clobbering it.
|
2013-11-19 17:04:36 +08:00
|
|
|
SmallVectorImpl<const MachineInstr *> &History = DbgValues[Var];
|
2011-03-26 10:19:36 +08:00
|
|
|
if (History.empty())
|
|
|
|
continue;
|
|
|
|
const MachineInstr *MInsn = History.front();
|
2010-05-26 07:40:22 +08:00
|
|
|
|
2011-03-26 10:19:36 +08:00
|
|
|
DIVariable DV(Var);
|
2011-08-11 04:55:27 +08:00
|
|
|
LexicalScope *Scope = NULL;
|
2010-05-28 04:25:04 +08:00
|
|
|
if (DV.getTag() == dwarf::DW_TAG_arg_variable &&
|
2013-12-03 23:10:23 +08:00
|
|
|
DISubprogram(DV.getContext()).describes(CurFn->getFunction()))
|
2011-08-11 04:55:27 +08:00
|
|
|
Scope = LScopes.getCurrentFunctionScope();
|
2013-03-12 07:39:23 +08:00
|
|
|
else if (MDNode *IA = DV.getInlinedAt())
|
|
|
|
Scope = LScopes.findInlinedScope(DebugLoc::getFromDILocation(IA));
|
|
|
|
else
|
|
|
|
Scope = LScopes.findLexicalScope(cast<MDNode>(DV->getOperand(1)));
|
2010-05-21 03:57:06 +08:00
|
|
|
// If variable scope is not found then skip this variable.
|
2010-05-21 08:10:20 +08:00
|
|
|
if (!Scope)
|
2010-05-21 03:57:06 +08:00
|
|
|
continue;
|
|
|
|
|
|
|
|
Processed.insert(DV);
|
2011-03-26 10:19:36 +08:00
|
|
|
assert(MInsn->isDebugValue() && "History must begin with debug value");
|
2011-08-16 03:01:20 +08:00
|
|
|
DbgVariable *AbsVar = findAbstractVariable(DV, MInsn->getDebugLoc());
|
2013-10-05 09:43:03 +08:00
|
|
|
DbgVariable *RegVar = new DbgVariable(DV, AbsVar, this);
|
2013-12-03 23:10:23 +08:00
|
|
|
if (!addCurrentFnArgument(RegVar, Scope))
|
2011-08-11 04:55:27 +08:00
|
|
|
addScopeVariable(Scope, RegVar);
|
2011-08-16 03:01:20 +08:00
|
|
|
if (AbsVar)
|
2011-08-16 05:24:36 +08:00
|
|
|
AbsVar->setMInsn(MInsn);
|
2011-03-26 10:19:36 +08:00
|
|
|
|
2012-10-09 04:48:54 +08:00
|
|
|
// Simplify ranges that are fully coalesced.
|
2013-11-19 17:04:36 +08:00
|
|
|
if (History.size() <= 1 ||
|
|
|
|
(History.size() == 2 && MInsn->isIdenticalTo(History.back()))) {
|
2011-08-16 05:24:36 +08:00
|
|
|
RegVar->setMInsn(MInsn);
|
2010-05-26 07:40:22 +08:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2013-01-29 01:33:26 +08:00
|
|
|
// Handle multiple DBG_VALUE instructions describing one variable.
|
2011-03-26 10:19:36 +08:00
|
|
|
RegVar->setDotDebugLocOffset(DotDebugLocEntries.size());
|
2011-03-23 06:33:08 +08:00
|
|
|
|
2013-11-19 17:04:36 +08:00
|
|
|
for (SmallVectorImpl<const MachineInstr *>::const_iterator
|
|
|
|
HI = History.begin(),
|
|
|
|
HE = History.end();
|
|
|
|
HI != HE; ++HI) {
|
2011-03-26 10:19:36 +08:00
|
|
|
const MachineInstr *Begin = *HI;
|
|
|
|
assert(Begin->isDebugValue() && "Invalid History entry");
|
2011-03-23 06:33:08 +08:00
|
|
|
|
2011-06-02 07:00:17 +08:00
|
|
|
// Check if DBG_VALUE is truncating a range.
|
2013-11-19 17:04:36 +08:00
|
|
|
if (Begin->getNumOperands() > 1 && Begin->getOperand(0).isReg() &&
|
|
|
|
!Begin->getOperand(0).getReg())
|
2011-06-02 07:00:17 +08:00
|
|
|
continue;
|
|
|
|
|
2011-03-23 06:33:08 +08:00
|
|
|
// Compute the range for a register location.
|
2010-05-27 01:29:32 +08:00
|
|
|
const MCSymbol *FLabel = getLabelBeforeInsn(Begin);
|
2011-03-23 06:33:08 +08:00
|
|
|
const MCSymbol *SLabel = 0;
|
2010-08-05 06:07:27 +08:00
|
|
|
|
2011-03-26 10:19:36 +08:00
|
|
|
if (HI + 1 == HE)
|
|
|
|
// If Begin is the last instruction in History then its value is valid
|
2011-04-15 13:18:47 +08:00
|
|
|
// until the end of the function.
|
2011-03-23 06:33:08 +08:00
|
|
|
SLabel = FunctionEndSym;
|
2011-03-26 10:19:36 +08:00
|
|
|
else {
|
|
|
|
const MachineInstr *End = HI[1];
|
2012-11-20 06:42:10 +08:00
|
|
|
DEBUG(dbgs() << "DotDebugLoc Pair:\n"
|
2013-11-19 17:04:36 +08:00
|
|
|
<< "\t" << *Begin << "\t" << *End << "\n");
|
2011-03-26 10:19:36 +08:00
|
|
|
if (End->isDebugValue())
|
|
|
|
SLabel = getLabelBeforeInsn(End);
|
|
|
|
else {
|
|
|
|
// End is a normal instruction clobbering the range.
|
|
|
|
SLabel = getLabelAfterInsn(End);
|
|
|
|
assert(SLabel && "Forgot label after clobber instruction");
|
|
|
|
++HI;
|
|
|
|
}
|
|
|
|
}
|
2011-03-23 06:33:08 +08:00
|
|
|
|
2011-03-26 10:19:36 +08:00
|
|
|
// The value is valid until the next DBG_VALUE or clobber.
|
2013-11-19 17:04:36 +08:00
|
|
|
DotDebugLocEntries.push_back(
|
|
|
|
getDebugLocEntry(Asm, FLabel, SLabel, Begin));
|
2010-05-26 07:40:22 +08:00
|
|
|
}
|
|
|
|
DotDebugLocEntries.push_back(DotDebugLocEntry());
|
2010-03-16 02:33:46 +08:00
|
|
|
}
|
2010-05-15 05:01:35 +08:00
|
|
|
|
|
|
|
// Collect info for variables that were optimized out.
|
2011-08-20 07:28:12 +08:00
|
|
|
LexicalScope *FnScope = LScopes.getCurrentFunctionScope();
|
|
|
|
DIArray Variables = DISubprogram(FnScope->getScopeNode()).getVariables();
|
|
|
|
for (unsigned i = 0, e = Variables.getNumElements(); i != e; ++i) {
|
|
|
|
DIVariable DV(Variables.getElement(i));
|
2013-07-09 02:33:29 +08:00
|
|
|
if (!DV || !DV.isVariable() || !Processed.insert(DV))
|
2011-08-20 07:28:12 +08:00
|
|
|
continue;
|
|
|
|
if (LexicalScope *Scope = LScopes.findLexicalScope(DV.getContext()))
|
2013-10-05 09:43:03 +08:00
|
|
|
addScopeVariable(Scope, new DbgVariable(DV, NULL, this));
|
2010-05-15 05:01:35 +08:00
|
|
|
}
|
2010-05-26 07:40:22 +08:00
|
|
|
}
|
|
|
|
|
2012-11-28 06:43:45 +08:00
|
|
|
// Return Label preceding the instruction.
|
2013-01-16 07:56:56 +08:00
|
|
|
MCSymbol *DwarfDebug::getLabelBeforeInsn(const MachineInstr *MI) {
|
2011-03-26 10:19:36 +08:00
|
|
|
MCSymbol *Label = LabelsBeforeInsn.lookup(MI);
|
|
|
|
assert(Label && "Didn't insert label before instruction");
|
|
|
|
return Label;
|
2010-05-26 07:40:22 +08:00
|
|
|
}
|
2010-05-15 05:01:35 +08:00
|
|
|
|
2012-11-28 06:43:45 +08:00
|
|
|
// Return Label immediately following the instruction.
|
2013-01-16 07:56:56 +08:00
|
|
|
MCSymbol *DwarfDebug::getLabelAfterInsn(const MachineInstr *MI) {
|
2011-03-26 10:19:36 +08:00
|
|
|
return LabelsAfterInsn.lookup(MI);
|
2009-10-06 09:26:37 +08:00
|
|
|
}
|
|
|
|
|
2012-11-28 06:43:45 +08:00
|
|
|
// Process beginning of an instruction.
|
2010-10-27 01:49:02 +08:00
|
|
|
void DwarfDebug::beginInstruction(const MachineInstr *MI) {
|
2013-12-03 23:10:23 +08:00
|
|
|
assert(CurMI == 0);
|
|
|
|
CurMI = MI;
|
2011-03-26 01:20:59 +08:00
|
|
|
// Check if source location changes, but ignore DBG_VALUE locations.
|
|
|
|
if (!MI->isDebugValue()) {
|
|
|
|
DebugLoc DL = MI->getDebugLoc();
|
|
|
|
if (DL != PrevInstLoc && (!DL.isUnknown() || UnknownLocations)) {
|
2012-04-06 04:39:05 +08:00
|
|
|
unsigned Flags = 0;
|
2011-03-26 01:20:59 +08:00
|
|
|
PrevInstLoc = DL;
|
2011-05-12 03:22:19 +08:00
|
|
|
if (DL == PrologEndLoc) {
|
|
|
|
Flags |= DWARF2_FLAG_PROLOGUE_END;
|
|
|
|
PrologEndLoc = DebugLoc();
|
|
|
|
}
|
2012-04-06 04:39:05 +08:00
|
|
|
if (PrologEndLoc.isUnknown())
|
|
|
|
Flags |= DWARF2_FLAG_IS_STMT;
|
|
|
|
|
2011-03-26 01:20:59 +08:00
|
|
|
if (!DL.isUnknown()) {
|
|
|
|
const MDNode *Scope = DL.getScope(Asm->MF->getFunction()->getContext());
|
2011-05-12 03:22:19 +08:00
|
|
|
recordSourceLine(DL.getLine(), DL.getCol(), Scope, Flags);
|
2011-03-26 01:20:59 +08:00
|
|
|
} else
|
2011-05-12 03:22:19 +08:00
|
|
|
recordSourceLine(0, 0, 0, 0);
|
2011-03-26 01:20:59 +08:00
|
|
|
}
|
2010-05-27 03:37:24 +08:00
|
|
|
}
|
|
|
|
|
2011-03-26 01:20:59 +08:00
|
|
|
// Insert labels where requested.
|
2013-11-19 17:04:36 +08:00
|
|
|
DenseMap<const MachineInstr *, MCSymbol *>::iterator I =
|
|
|
|
LabelsBeforeInsn.find(MI);
|
2011-03-26 10:19:36 +08:00
|
|
|
|
|
|
|
// No label needed.
|
|
|
|
if (I == LabelsBeforeInsn.end())
|
|
|
|
return;
|
|
|
|
|
|
|
|
// Label already assigned.
|
|
|
|
if (I->second)
|
2010-03-30 01:20:31 +08:00
|
|
|
return;
|
2010-05-27 03:37:24 +08:00
|
|
|
|
2011-03-26 01:20:59 +08:00
|
|
|
if (!PrevLabel) {
|
2010-05-27 05:23:46 +08:00
|
|
|
PrevLabel = MMI->getContext().CreateTempSymbol();
|
|
|
|
Asm->OutStreamer.EmitLabel(PrevLabel);
|
2010-04-28 03:46:33 +08:00
|
|
|
}
|
2011-03-26 10:19:36 +08:00
|
|
|
I->second = PrevLabel;
|
2009-10-06 09:50:42 +08:00
|
|
|
}
|
|
|
|
|
2012-11-28 06:43:45 +08:00
|
|
|
// Process end of an instruction.
|
2013-12-03 23:10:23 +08:00
|
|
|
void DwarfDebug::endInstruction() {
|
|
|
|
assert(CurMI != 0);
|
2011-03-26 01:20:59 +08:00
|
|
|
// Don't create a new label after DBG_VALUE instructions.
|
|
|
|
// They don't generate code.
|
2013-12-03 23:10:23 +08:00
|
|
|
if (!CurMI->isDebugValue())
|
2011-03-26 01:20:59 +08:00
|
|
|
PrevLabel = 0;
|
|
|
|
|
2013-11-19 17:04:36 +08:00
|
|
|
DenseMap<const MachineInstr *, MCSymbol *>::iterator I =
|
2013-12-03 23:10:23 +08:00
|
|
|
LabelsAfterInsn.find(CurMI);
|
|
|
|
CurMI = 0;
|
2011-03-26 10:19:36 +08:00
|
|
|
|
|
|
|
// No label needed.
|
|
|
|
if (I == LabelsAfterInsn.end())
|
|
|
|
return;
|
|
|
|
|
|
|
|
// Label already assigned.
|
|
|
|
if (I->second)
|
2011-03-26 01:20:59 +08:00
|
|
|
return;
|
|
|
|
|
|
|
|
// We need a label after this instruction.
|
|
|
|
if (!PrevLabel) {
|
|
|
|
PrevLabel = MMI->getContext().CreateTempSymbol();
|
|
|
|
Asm->OutStreamer.EmitLabel(PrevLabel);
|
2010-04-09 00:50:29 +08:00
|
|
|
}
|
2011-03-26 10:19:36 +08:00
|
|
|
I->second = PrevLabel;
|
2009-11-11 07:06:00 +08:00
|
|
|
}
|
|
|
|
|
2012-11-28 06:43:45 +08:00
|
|
|
// Each LexicalScope has first instruction and last instruction to mark
|
|
|
|
// beginning and end of a scope respectively. Create an inverse map that list
|
|
|
|
// scopes starts (and ends) with an instruction. One instruction may start (or
|
|
|
|
// end) multiple scopes. Ignore scopes that are not reachable.
|
2010-04-09 02:43:56 +08:00
|
|
|
void DwarfDebug::identifyScopeMarkers() {
|
2011-08-11 04:55:27 +08:00
|
|
|
SmallVector<LexicalScope *, 4> WorkList;
|
|
|
|
WorkList.push_back(LScopes.getCurrentFunctionScope());
|
2010-01-20 10:05:23 +08:00
|
|
|
while (!WorkList.empty()) {
|
2011-08-11 04:55:27 +08:00
|
|
|
LexicalScope *S = WorkList.pop_back_val();
|
2010-07-22 05:21:52 +08:00
|
|
|
|
2013-07-03 12:24:43 +08:00
|
|
|
const SmallVectorImpl<LexicalScope *> &Children = S->getChildren();
|
2010-07-22 05:21:52 +08:00
|
|
|
if (!Children.empty())
|
2013-11-19 17:04:36 +08:00
|
|
|
for (SmallVectorImpl<LexicalScope *>::const_iterator
|
|
|
|
SI = Children.begin(),
|
|
|
|
SE = Children.end();
|
|
|
|
SI != SE; ++SI)
|
2010-01-20 10:05:23 +08:00
|
|
|
WorkList.push_back(*SI);
|
|
|
|
|
2009-11-11 07:06:00 +08:00
|
|
|
if (S->isAbstractScope())
|
|
|
|
continue;
|
2010-07-22 05:21:52 +08:00
|
|
|
|
2013-07-03 12:24:43 +08:00
|
|
|
const SmallVectorImpl<InsnRange> &Ranges = S->getRanges();
|
2010-04-28 03:46:33 +08:00
|
|
|
if (Ranges.empty())
|
|
|
|
continue;
|
2013-07-03 12:17:25 +08:00
|
|
|
for (SmallVectorImpl<InsnRange>::const_iterator RI = Ranges.begin(),
|
2013-11-19 17:04:36 +08:00
|
|
|
RE = Ranges.end();
|
|
|
|
RI != RE; ++RI) {
|
2011-08-11 04:55:27 +08:00
|
|
|
assert(RI->first && "InsnRange does not have first instruction!");
|
|
|
|
assert(RI->second && "InsnRange does not have second instruction!");
|
2011-03-26 10:19:36 +08:00
|
|
|
requestLabelBeforeInsn(RI->first);
|
|
|
|
requestLabelAfterInsn(RI->second);
|
2010-04-28 03:46:33 +08:00
|
|
|
}
|
2009-10-02 04:31:14 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-11-28 06:43:45 +08:00
|
|
|
// Get MDNode for DebugLoc's scope.
|
2011-05-10 06:14:49 +08:00
|
|
|
static MDNode *getScopeNode(DebugLoc DL, const LLVMContext &Ctx) {
|
|
|
|
if (MDNode *InlinedAt = DL.getInlinedAt(Ctx))
|
|
|
|
return getScopeNode(DebugLoc::getFromDILocation(InlinedAt), Ctx);
|
|
|
|
return DL.getScope(Ctx);
|
|
|
|
}
|
|
|
|
|
2012-11-28 06:43:45 +08:00
|
|
|
// Walk up the scope chain of given debug loc and find line number info
|
|
|
|
// for the function.
|
2011-05-12 03:22:19 +08:00
|
|
|
static DebugLoc getFnDebugLoc(DebugLoc DL, const LLVMContext &Ctx) {
|
|
|
|
const MDNode *Scope = getScopeNode(DL, Ctx);
|
|
|
|
DISubprogram SP = getDISubprogram(Scope);
|
2013-07-09 02:33:29 +08:00
|
|
|
if (SP.isSubprogram()) {
|
2012-04-03 08:43:49 +08:00
|
|
|
// Check for number of operands since the compatibility is
|
|
|
|
// cheap here.
|
2012-04-04 01:55:42 +08:00
|
|
|
if (SP->getNumOperands() > 19)
|
2012-04-03 08:43:49 +08:00
|
|
|
return DebugLoc::get(SP.getScopeLineNumber(), 0, SP);
|
|
|
|
else
|
|
|
|
return DebugLoc::get(SP.getLineNumber(), 0, SP);
|
|
|
|
}
|
|
|
|
|
2011-05-12 03:22:19 +08:00
|
|
|
return DebugLoc();
|
|
|
|
}
|
|
|
|
|
2012-11-28 06:43:45 +08:00
|
|
|
// Gather pre-function debug information. Assumes being called immediately
|
|
|
|
// after the function entry point has been emitted.
|
2010-01-27 07:18:02 +08:00
|
|
|
void DwarfDebug::beginFunction(const MachineFunction *MF) {
|
2013-12-03 23:10:23 +08:00
|
|
|
CurFn = MF;
|
2013-11-02 07:14:17 +08:00
|
|
|
|
|
|
|
// If there's no debug info for the function we're not going to do anything.
|
|
|
|
if (!MMI->hasDebugInfo())
|
|
|
|
return;
|
|
|
|
|
|
|
|
// Grab the lexical scopes for the function, if we don't have any of those
|
|
|
|
// then we're not going to be able to do anything.
|
2011-08-11 04:55:27 +08:00
|
|
|
LScopes.initialize(*MF);
|
2013-11-02 07:14:17 +08:00
|
|
|
if (LScopes.empty())
|
|
|
|
return;
|
|
|
|
|
|
|
|
assert(UserVariables.empty() && DbgValues.empty() && "Maps weren't cleaned");
|
|
|
|
|
|
|
|
// Make sure that each lexical scope will have a begin/end label.
|
2011-08-11 04:55:27 +08:00
|
|
|
identifyScopeMarkers();
|
2009-10-07 02:37:31 +08:00
|
|
|
|
2013-12-10 07:57:44 +08:00
|
|
|
// Set DwarfDwarfCompileUnitID in MCContext to the Compile Unit this function
|
2013-11-02 07:14:17 +08:00
|
|
|
// belongs to so that we add to the correct per-cu line table in the
|
|
|
|
// non-asm case.
|
2013-02-06 05:52:47 +08:00
|
|
|
LexicalScope *FnScope = LScopes.getCurrentFunctionScope();
|
2013-12-10 07:57:44 +08:00
|
|
|
DwarfCompileUnit *TheCU = SPMap.lookup(FnScope->getScopeNode());
|
2013-02-06 05:52:47 +08:00
|
|
|
assert(TheCU && "Unable to find compile unit!");
|
2013-10-06 00:42:21 +08:00
|
|
|
if (Asm->TM.hasMCUseLoc() && Asm->OutStreamer.hasRawTextSupport())
|
2013-05-21 08:57:22 +08:00
|
|
|
// Use a single line table if we are using .loc and generating assembly.
|
|
|
|
Asm->OutStreamer.getContext().setDwarfCompileUnitID(0);
|
|
|
|
else
|
|
|
|
Asm->OutStreamer.getContext().setDwarfCompileUnitID(TheCU->getUniqueID());
|
2013-02-06 05:52:47 +08:00
|
|
|
|
2013-11-02 07:14:17 +08:00
|
|
|
// Emit a label for the function so that we have a beginning address.
|
|
|
|
FunctionBeginSym = Asm->GetTempSymbol("func_begin", Asm->getFunctionNumber());
|
2009-05-21 07:21:38 +08:00
|
|
|
// Assumes in correct section after the entry point.
|
2010-04-28 03:46:33 +08:00
|
|
|
Asm->OutStreamer.EmitLabel(FunctionBeginSym);
|
2009-05-21 07:21:38 +08:00
|
|
|
|
2011-03-23 06:33:08 +08:00
|
|
|
const TargetRegisterInfo *TRI = Asm->TM.getRegisterInfo();
|
2012-11-28 06:43:45 +08:00
|
|
|
// LiveUserVar - Map physreg numbers to the MDNode they contain.
|
2013-11-02 07:14:17 +08:00
|
|
|
std::vector<const MDNode *> LiveUserVar(TRI->getNumRegs());
|
2011-03-23 06:33:08 +08:00
|
|
|
|
2013-11-02 07:14:17 +08:00
|
|
|
for (MachineFunction::const_iterator I = MF->begin(), E = MF->end(); I != E;
|
|
|
|
++I) {
|
2011-03-26 10:19:36 +08:00
|
|
|
bool AtBlockEntry = true;
|
2010-05-27 03:37:24 +08:00
|
|
|
for (MachineBasicBlock::const_iterator II = I->begin(), IE = I->end();
|
|
|
|
II != IE; ++II) {
|
|
|
|
const MachineInstr *MI = II;
|
2011-03-26 10:19:36 +08:00
|
|
|
|
2010-05-27 03:37:24 +08:00
|
|
|
if (MI->isDebugValue()) {
|
2011-10-27 06:55:33 +08:00
|
|
|
assert(MI->getNumOperands() > 1 && "Invalid machine instruction!");
|
2011-03-23 06:33:08 +08:00
|
|
|
|
2011-03-26 10:19:36 +08:00
|
|
|
// Keep track of user variables.
|
2011-03-23 06:33:08 +08:00
|
|
|
const MDNode *Var =
|
2013-11-02 07:14:17 +08:00
|
|
|
MI->getOperand(MI->getNumOperands() - 1).getMetadata();
|
2011-03-26 10:19:36 +08:00
|
|
|
|
|
|
|
// Variable is in a register, we need to check for clobbers.
|
2011-03-23 06:33:08 +08:00
|
|
|
if (isDbgValueInDefinedReg(MI))
|
|
|
|
LiveUserVar[MI->getOperand(0).getReg()] = Var;
|
|
|
|
|
2011-03-26 10:19:36 +08:00
|
|
|
// Check the history of this variable.
|
2013-11-02 07:14:17 +08:00
|
|
|
SmallVectorImpl<const MachineInstr *> &History = DbgValues[Var];
|
2011-03-26 10:19:36 +08:00
|
|
|
if (History.empty()) {
|
|
|
|
UserVariables.push_back(Var);
|
|
|
|
// The first mention of a function argument gets the FunctionBeginSym
|
|
|
|
// label, so arguments are visible when breaking at function entry.
|
|
|
|
DIVariable DV(Var);
|
2013-07-09 02:33:29 +08:00
|
|
|
if (DV.isVariable() && DV.getTag() == dwarf::DW_TAG_arg_variable &&
|
2013-11-19 07:57:26 +08:00
|
|
|
getDISubprogram(DV.getContext()).describes(MF->getFunction()))
|
2011-03-26 10:19:36 +08:00
|
|
|
LabelsBeforeInsn[MI] = FunctionBeginSym;
|
|
|
|
} else {
|
|
|
|
// We have seen this variable before. Try to coalesce DBG_VALUEs.
|
|
|
|
const MachineInstr *Prev = History.back();
|
|
|
|
if (Prev->isDebugValue()) {
|
|
|
|
// Coalesce identical entries at the end of History.
|
|
|
|
if (History.size() >= 2 &&
|
2011-07-07 08:14:27 +08:00
|
|
|
Prev->isIdenticalTo(History[History.size() - 2])) {
|
2012-10-09 04:48:49 +08:00
|
|
|
DEBUG(dbgs() << "Coalescing identical DBG_VALUE entries:\n"
|
2013-11-02 07:14:17 +08:00
|
|
|
<< "\t" << *Prev << "\t"
|
|
|
|
<< *History[History.size() - 2] << "\n");
|
2011-03-26 10:19:36 +08:00
|
|
|
History.pop_back();
|
2011-07-07 08:14:27 +08:00
|
|
|
}
|
2011-03-26 10:19:36 +08:00
|
|
|
|
|
|
|
// Terminate old register assignments that don't reach MI;
|
|
|
|
MachineFunction::const_iterator PrevMBB = Prev->getParent();
|
|
|
|
if (PrevMBB != I && (!AtBlockEntry || llvm::next(PrevMBB) != I) &&
|
|
|
|
isDbgValueInDefinedReg(Prev)) {
|
|
|
|
// Previous register assignment needs to terminate at the end of
|
|
|
|
// its basic block.
|
|
|
|
MachineBasicBlock::const_iterator LastMI =
|
2013-11-02 07:14:17 +08:00
|
|
|
PrevMBB->getLastNonDebugInstr();
|
2011-07-07 08:14:27 +08:00
|
|
|
if (LastMI == PrevMBB->end()) {
|
2011-03-26 10:19:36 +08:00
|
|
|
// Drop DBG_VALUE for empty range.
|
2012-10-09 04:48:49 +08:00
|
|
|
DEBUG(dbgs() << "Dropping DBG_VALUE for empty range:\n"
|
2013-11-02 07:14:17 +08:00
|
|
|
<< "\t" << *Prev << "\n");
|
2011-03-26 10:19:36 +08:00
|
|
|
History.pop_back();
|
2013-06-20 08:25:24 +08:00
|
|
|
} else if (llvm::next(PrevMBB) != PrevMBB->getParent()->end())
|
2011-03-26 10:19:36 +08:00
|
|
|
// Terminate after LastMI.
|
|
|
|
History.push_back(LastMI);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
History.push_back(MI);
|
2010-05-27 03:37:24 +08:00
|
|
|
} else {
|
2011-03-26 10:19:36 +08:00
|
|
|
// Not a DBG_VALUE instruction.
|
|
|
|
if (!MI->isLabel())
|
|
|
|
AtBlockEntry = false;
|
|
|
|
|
2012-10-05 04:46:14 +08:00
|
|
|
// First known non-DBG_VALUE and non-frame setup location marks
|
|
|
|
// the beginning of the function body.
|
|
|
|
if (!MI->getFlag(MachineInstr::FrameSetup) &&
|
|
|
|
(PrologEndLoc.isUnknown() && !MI->getDebugLoc().isUnknown()))
|
2011-05-12 03:22:19 +08:00
|
|
|
PrologEndLoc = MI->getDebugLoc();
|
|
|
|
|
2011-03-23 06:33:08 +08:00
|
|
|
// Check if the instruction clobbers any registers with debug vars.
|
|
|
|
for (MachineInstr::const_mop_iterator MOI = MI->operands_begin(),
|
2013-11-02 07:14:17 +08:00
|
|
|
MOE = MI->operands_end();
|
|
|
|
MOI != MOE; ++MOI) {
|
2011-03-23 06:33:08 +08:00
|
|
|
if (!MOI->isReg() || !MOI->isDef() || !MOI->getReg())
|
|
|
|
continue;
|
2013-11-02 07:14:17 +08:00
|
|
|
for (MCRegAliasIterator AI(MOI->getReg(), TRI, true); AI.isValid();
|
|
|
|
++AI) {
|
2012-06-02 07:28:30 +08:00
|
|
|
unsigned Reg = *AI;
|
2011-03-23 06:33:08 +08:00
|
|
|
const MDNode *Var = LiveUserVar[Reg];
|
|
|
|
if (!Var)
|
|
|
|
continue;
|
|
|
|
// Reg is now clobbered.
|
|
|
|
LiveUserVar[Reg] = 0;
|
|
|
|
|
|
|
|
// Was MD last defined by a DBG_VALUE referring to Reg?
|
2011-03-26 10:19:36 +08:00
|
|
|
DbgValueHistoryMap::iterator HistI = DbgValues.find(Var);
|
|
|
|
if (HistI == DbgValues.end())
|
|
|
|
continue;
|
2013-11-02 07:14:17 +08:00
|
|
|
SmallVectorImpl<const MachineInstr *> &History = HistI->second;
|
2011-03-26 10:19:36 +08:00
|
|
|
if (History.empty())
|
2011-03-23 06:33:08 +08:00
|
|
|
continue;
|
2011-03-26 10:19:36 +08:00
|
|
|
const MachineInstr *Prev = History.back();
|
|
|
|
// Sanity-check: Register assignments are terminated at the end of
|
|
|
|
// their block.
|
|
|
|
if (!Prev->isDebugValue() || Prev->getParent() != MI->getParent())
|
2011-03-23 06:33:08 +08:00
|
|
|
continue;
|
2011-03-26 10:19:36 +08:00
|
|
|
// Is the variable still in Reg?
|
|
|
|
if (!isDbgValueInDefinedReg(Prev) ||
|
|
|
|
Prev->getOperand(0).getReg() != Reg)
|
|
|
|
continue;
|
|
|
|
// Var is clobbered. Make sure the next instruction gets a label.
|
|
|
|
History.push_back(MI);
|
2011-03-23 06:33:08 +08:00
|
|
|
}
|
|
|
|
}
|
2010-05-27 03:37:24 +08:00
|
|
|
}
|
|
|
|
}
|
2011-03-26 10:19:36 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
for (DbgValueHistoryMap::iterator I = DbgValues.begin(), E = DbgValues.end();
|
|
|
|
I != E; ++I) {
|
2013-11-02 07:14:17 +08:00
|
|
|
SmallVectorImpl<const MachineInstr *> &History = I->second;
|
2011-03-26 10:19:36 +08:00
|
|
|
if (History.empty())
|
|
|
|
continue;
|
|
|
|
|
|
|
|
// Make sure the final register assignments are terminated.
|
|
|
|
const MachineInstr *Prev = History.back();
|
|
|
|
if (Prev->isDebugValue() && isDbgValueInDefinedReg(Prev)) {
|
|
|
|
const MachineBasicBlock *PrevMBB = Prev->getParent();
|
2012-11-20 06:42:10 +08:00
|
|
|
MachineBasicBlock::const_iterator LastMI =
|
2013-11-02 07:14:17 +08:00
|
|
|
PrevMBB->getLastNonDebugInstr();
|
2011-03-26 10:19:36 +08:00
|
|
|
if (LastMI == PrevMBB->end())
|
|
|
|
// Drop DBG_VALUE for empty range.
|
|
|
|
History.pop_back();
|
2013-06-20 08:25:24 +08:00
|
|
|
else if (PrevMBB != &PrevMBB->getParent()->back()) {
|
2011-03-26 10:19:36 +08:00
|
|
|
// Terminate after LastMI.
|
|
|
|
History.push_back(LastMI);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// Request labels for the full history.
|
|
|
|
for (unsigned i = 0, e = History.size(); i != e; ++i) {
|
|
|
|
const MachineInstr *MI = History[i];
|
|
|
|
if (MI->isDebugValue())
|
|
|
|
requestLabelBeforeInsn(MI);
|
|
|
|
else
|
|
|
|
requestLabelAfterInsn(MI);
|
|
|
|
}
|
|
|
|
}
|
2010-05-27 03:37:24 +08:00
|
|
|
|
2011-03-26 01:20:59 +08:00
|
|
|
PrevInstLoc = DebugLoc();
|
2010-05-27 03:37:24 +08:00
|
|
|
PrevLabel = FunctionBeginSym;
|
2011-05-12 03:22:19 +08:00
|
|
|
|
|
|
|
// Record beginning of function.
|
|
|
|
if (!PrologEndLoc.isUnknown()) {
|
2013-11-02 07:14:17 +08:00
|
|
|
DebugLoc FnStartDL =
|
|
|
|
getFnDebugLoc(PrologEndLoc, MF->getFunction()->getContext());
|
|
|
|
recordSourceLine(
|
|
|
|
FnStartDL.getLine(), FnStartDL.getCol(),
|
|
|
|
FnStartDL.getScope(MF->getFunction()->getContext()),
|
|
|
|
// We'd like to list the prologue as "not statements" but GDB behaves
|
|
|
|
// poorly if we do that. Revisit this with caution/GDB (7.5+) testing.
|
|
|
|
DWARF2_FLAG_IS_STMT);
|
2011-05-12 03:22:19 +08:00
|
|
|
}
|
2009-05-15 17:23:25 +08:00
|
|
|
}
|
|
|
|
|
2011-08-11 04:55:27 +08:00
|
|
|
void DwarfDebug::addScopeVariable(LexicalScope *LS, DbgVariable *Var) {
|
2013-06-05 13:39:59 +08:00
|
|
|
SmallVectorImpl<DbgVariable *> &Vars = ScopeVariables[LS];
|
|
|
|
DIVariable DV = Var->getVariable();
|
2013-06-07 05:04:51 +08:00
|
|
|
// Variables with positive arg numbers are parameters.
|
|
|
|
if (unsigned ArgNum = DV.getArgNumber()) {
|
|
|
|
// Keep all parameters in order at the start of the variable list to ensure
|
|
|
|
// function types are correct (no out-of-order parameters)
|
|
|
|
//
|
|
|
|
// This could be improved by only doing it for optimized builds (unoptimized
|
|
|
|
// builds have the right order to begin with), searching from the back (this
|
|
|
|
// would catch the unoptimized case quickly), or doing a binary search
|
|
|
|
// rather than linear search.
|
|
|
|
SmallVectorImpl<DbgVariable *>::iterator I = Vars.begin();
|
|
|
|
while (I != Vars.end()) {
|
|
|
|
unsigned CurNum = (*I)->getVariable().getArgNumber();
|
|
|
|
// A local (non-parameter) variable has been found, insert immediately
|
|
|
|
// before it.
|
|
|
|
if (CurNum == 0)
|
|
|
|
break;
|
|
|
|
// A later indexed parameter has been found, insert immediately before it.
|
2013-06-07 06:28:26 +08:00
|
|
|
if (CurNum > ArgNum)
|
2013-06-07 05:04:51 +08:00
|
|
|
break;
|
2013-06-07 06:28:26 +08:00
|
|
|
++I;
|
2013-06-05 13:39:59 +08:00
|
|
|
}
|
2013-06-07 05:04:51 +08:00
|
|
|
Vars.insert(I, Var);
|
|
|
|
return;
|
2013-06-05 13:39:59 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
Vars.push_back(Var);
|
2011-08-11 04:55:27 +08:00
|
|
|
}
|
|
|
|
|
2012-11-28 06:43:45 +08:00
|
|
|
// Gather and emit post-function debug information.
|
2013-12-03 21:15:54 +08:00
|
|
|
void DwarfDebug::endFunction(const MachineFunction *MF) {
|
2013-12-03 23:10:23 +08:00
|
|
|
// Every beginFunction(MF) call should be followed by an endFunction(MF) call,
|
|
|
|
// though the beginFunction may not be called at all.
|
|
|
|
// We should handle both cases.
|
|
|
|
if (CurFn == 0)
|
|
|
|
CurFn = MF;
|
|
|
|
else
|
|
|
|
assert(CurFn == MF);
|
|
|
|
assert(CurFn != 0);
|
|
|
|
|
|
|
|
if (!MMI->hasDebugInfo() || LScopes.empty()) {
|
|
|
|
CurFn = 0;
|
2013-11-19 17:04:36 +08:00
|
|
|
return;
|
2013-12-03 23:10:23 +08:00
|
|
|
}
|
2010-05-22 08:04:14 +08:00
|
|
|
|
2011-08-11 04:55:27 +08:00
|
|
|
// Define end label for subprogram.
|
2013-11-19 17:04:36 +08:00
|
|
|
FunctionEndSym = Asm->GetTempSymbol("func_end", Asm->getFunctionNumber());
|
2011-08-11 04:55:27 +08:00
|
|
|
// Assumes in correct section after the entry point.
|
|
|
|
Asm->OutStreamer.EmitLabel(FunctionEndSym);
|
2013-12-10 07:57:44 +08:00
|
|
|
// Set DwarfDwarfCompileUnitID in MCContext to default value.
|
2013-02-06 05:52:47 +08:00
|
|
|
Asm->OutStreamer.getContext().setDwarfCompileUnitID(0);
|
2012-11-20 06:42:10 +08:00
|
|
|
|
2011-08-11 04:55:27 +08:00
|
|
|
SmallPtrSet<const MDNode *, 16> ProcessedVars;
|
2013-12-03 23:10:23 +08:00
|
|
|
collectVariableInfo(ProcessedVars);
|
2012-11-20 06:42:10 +08:00
|
|
|
|
2011-08-16 06:04:40 +08:00
|
|
|
LexicalScope *FnScope = LScopes.getCurrentFunctionScope();
|
2013-12-10 07:57:44 +08:00
|
|
|
DwarfCompileUnit *TheCU = SPMap.lookup(FnScope->getScopeNode());
|
2011-10-27 06:55:33 +08:00
|
|
|
assert(TheCU && "Unable to find compile unit!");
|
2011-08-16 06:04:40 +08:00
|
|
|
|
2011-08-11 04:55:27 +08:00
|
|
|
// Construct abstract scopes.
|
2011-08-13 02:10:19 +08:00
|
|
|
ArrayRef<LexicalScope *> AList = LScopes.getAbstractScopesList();
|
|
|
|
for (unsigned i = 0, e = AList.size(); i != e; ++i) {
|
|
|
|
LexicalScope *AScope = AList[i];
|
|
|
|
DISubprogram SP(AScope->getScopeNode());
|
2013-07-09 02:33:29 +08:00
|
|
|
if (SP.isSubprogram()) {
|
2011-08-11 04:55:27 +08:00
|
|
|
// Collect info for variables that were optimized out.
|
2011-08-20 07:28:12 +08:00
|
|
|
DIArray Variables = SP.getVariables();
|
|
|
|
for (unsigned i = 0, e = Variables.getNumElements(); i != e; ++i) {
|
|
|
|
DIVariable DV(Variables.getElement(i));
|
2013-07-09 02:33:29 +08:00
|
|
|
if (!DV || !DV.isVariable() || !ProcessedVars.insert(DV))
|
2011-08-20 07:28:12 +08:00
|
|
|
continue;
|
2012-07-06 16:45:08 +08:00
|
|
|
// Check that DbgVariable for DV wasn't created earlier, when
|
|
|
|
// findAbstractVariable() was called for inlined instance of DV.
|
|
|
|
LLVMContext &Ctx = DV->getContext();
|
|
|
|
DIVariable CleanDV = cleanseInlinedVariable(DV, Ctx);
|
|
|
|
if (AbstractVariables.lookup(CleanDV))
|
|
|
|
continue;
|
2011-08-20 07:28:12 +08:00
|
|
|
if (LexicalScope *Scope = LScopes.findAbstractScope(DV.getContext()))
|
2013-10-05 09:43:03 +08:00
|
|
|
addScopeVariable(Scope, new DbgVariable(DV, NULL, this));
|
2010-06-26 06:07:34 +08:00
|
|
|
}
|
|
|
|
}
|
2011-08-13 02:10:19 +08:00
|
|
|
if (ProcessedSPNodes.count(AScope->getScopeNode()) == 0)
|
2013-05-30 01:16:59 +08:00
|
|
|
constructScopeDIE(TheCU, AScope);
|
2011-08-11 04:55:27 +08:00
|
|
|
}
|
2012-11-20 06:42:10 +08:00
|
|
|
|
2011-08-16 06:04:40 +08:00
|
|
|
DIE *CurFnDIE = constructScopeDIE(TheCU, FnScope);
|
2012-11-20 06:42:10 +08:00
|
|
|
|
2013-12-03 23:10:23 +08:00
|
|
|
if (!CurFn->getTarget().Options.DisableFramePointerElim(*CurFn))
|
2012-08-24 09:14:27 +08:00
|
|
|
TheCU->addFlag(CurFnDIE, dwarf::DW_AT_APPLE_omit_frame_ptr);
|
2011-08-16 06:04:40 +08:00
|
|
|
|
2009-05-21 07:21:38 +08:00
|
|
|
// Clear debug info
|
2013-11-19 17:04:36 +08:00
|
|
|
for (ScopeVariablesMap::iterator I = ScopeVariables.begin(),
|
|
|
|
E = ScopeVariables.end();
|
|
|
|
I != E; ++I)
|
2011-08-11 04:55:27 +08:00
|
|
|
DeleteContainerPointers(I->second);
|
|
|
|
ScopeVariables.clear();
|
2011-04-23 02:09:57 +08:00
|
|
|
DeleteContainerPointers(CurrentFnArguments);
|
2011-03-26 10:19:36 +08:00
|
|
|
UserVariables.clear();
|
|
|
|
DbgValues.clear();
|
2010-03-13 01:45:06 +08:00
|
|
|
AbstractVariables.clear();
|
2010-04-28 03:46:33 +08:00
|
|
|
LabelsBeforeInsn.clear();
|
|
|
|
LabelsAfterInsn.clear();
|
2010-04-17 07:33:45 +08:00
|
|
|
PrevLabel = NULL;
|
2013-12-03 23:10:23 +08:00
|
|
|
CurFn = 0;
|
2009-05-21 07:19:06 +08:00
|
|
|
}
|
2009-05-15 17:23:25 +08:00
|
|
|
|
2012-11-28 06:43:45 +08:00
|
|
|
// Register a source line with debug info. Returns the unique label that was
|
|
|
|
// emitted and which provides correspondence to the source line list.
|
2011-05-12 03:22:19 +08:00
|
|
|
void DwarfDebug::recordSourceLine(unsigned Line, unsigned Col, const MDNode *S,
|
|
|
|
unsigned Flags) {
|
2009-11-26 01:36:49 +08:00
|
|
|
StringRef Fn;
|
2011-03-25 04:30:50 +08:00
|
|
|
StringRef Dir;
|
2010-05-06 07:41:32 +08:00
|
|
|
unsigned Src = 1;
|
|
|
|
if (S) {
|
|
|
|
DIDescriptor Scope(S);
|
|
|
|
|
|
|
|
if (Scope.isCompileUnit()) {
|
|
|
|
DICompileUnit CU(S);
|
|
|
|
Fn = CU.getFilename();
|
2011-03-25 04:30:50 +08:00
|
|
|
Dir = CU.getDirectory();
|
2010-10-29 01:30:52 +08:00
|
|
|
} else if (Scope.isFile()) {
|
|
|
|
DIFile F(S);
|
|
|
|
Fn = F.getFilename();
|
2011-03-25 04:30:50 +08:00
|
|
|
Dir = F.getDirectory();
|
2010-05-06 07:41:32 +08:00
|
|
|
} else if (Scope.isSubprogram()) {
|
|
|
|
DISubprogram SP(S);
|
|
|
|
Fn = SP.getFilename();
|
2011-03-25 04:30:50 +08:00
|
|
|
Dir = SP.getDirectory();
|
2011-10-12 06:59:11 +08:00
|
|
|
} else if (Scope.isLexicalBlockFile()) {
|
|
|
|
DILexicalBlockFile DBF(S);
|
|
|
|
Fn = DBF.getFilename();
|
|
|
|
Dir = DBF.getDirectory();
|
2010-05-06 07:41:32 +08:00
|
|
|
} else if (Scope.isLexicalBlock()) {
|
|
|
|
DILexicalBlock DB(S);
|
|
|
|
Fn = DB.getFilename();
|
2011-03-25 04:30:50 +08:00
|
|
|
Dir = DB.getDirectory();
|
2010-05-06 07:41:32 +08:00
|
|
|
} else
|
2012-02-05 16:31:47 +08:00
|
|
|
llvm_unreachable("Unexpected scope info");
|
2010-05-06 07:41:32 +08:00
|
|
|
|
2013-11-19 17:04:36 +08:00
|
|
|
Src = getOrCreateSourceID(
|
|
|
|
Fn, Dir, Asm->OutStreamer.getContext().getDwarfCompileUnitID());
|
2010-05-06 07:41:32 +08:00
|
|
|
}
|
2011-07-29 11:49:23 +08:00
|
|
|
Asm->OutStreamer.EmitDwarfLocDirective(Src, Line, Col, Flags, 0, 0, Fn);
|
2009-05-15 17:23:25 +08:00
|
|
|
}
|
|
|
|
|
2009-05-21 07:22:40 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Emit Methods
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2013-10-30 06:57:10 +08:00
|
|
|
// Compute the size and offset of a DIE. The offset is relative to start of the
|
|
|
|
// CU. It returns the offset after laying out the DIE.
|
2013-12-06 02:06:10 +08:00
|
|
|
unsigned DwarfFile::computeSizeAndOffset(DIE *Die, unsigned Offset) {
|
2009-05-21 07:21:38 +08:00
|
|
|
// Get the children.
|
|
|
|
const std::vector<DIE *> &Children = Die->getChildren();
|
2009-05-15 17:23:25 +08:00
|
|
|
|
2009-05-21 07:21:38 +08:00
|
|
|
// Record the abbreviation.
|
2009-11-21 10:48:08 +08:00
|
|
|
assignAbbrevNumber(Die->getAbbrev());
|
2009-05-21 07:21:38 +08:00
|
|
|
|
|
|
|
// Get the abbreviation for this DIE.
|
2013-12-05 09:01:41 +08:00
|
|
|
const DIEAbbrev &Abbrev = Die->getAbbrev();
|
2009-05-21 07:21:38 +08:00
|
|
|
|
|
|
|
// Set DIE offset
|
|
|
|
Die->setOffset(Offset);
|
|
|
|
|
|
|
|
// Start the size with the size of abbreviation code.
|
2013-12-05 09:01:41 +08:00
|
|
|
Offset += MCAsmInfo::getULEB128Size(Die->getAbbrevNumber());
|
2009-05-21 07:21:38 +08:00
|
|
|
|
2013-11-19 17:04:36 +08:00
|
|
|
const SmallVectorImpl<DIEValue *> &Values = Die->getValues();
|
2013-12-05 09:01:41 +08:00
|
|
|
const SmallVectorImpl<DIEAbbrevData> &AbbrevData = Abbrev.getData();
|
2009-05-15 17:23:25 +08:00
|
|
|
|
2009-05-21 07:21:38 +08:00
|
|
|
// Size the DIE attribute values.
|
|
|
|
for (unsigned i = 0, N = Values.size(); i < N; ++i)
|
|
|
|
// Size attribute value.
|
2010-04-05 08:18:22 +08:00
|
|
|
Offset += Values[i]->SizeOf(Asm, AbbrevData[i].getForm());
|
2009-05-15 17:23:25 +08:00
|
|
|
|
2009-05-21 07:21:38 +08:00
|
|
|
// Size the DIE children if any.
|
|
|
|
if (!Children.empty()) {
|
2013-12-05 09:01:41 +08:00
|
|
|
assert(Abbrev.getChildrenFlag() == dwarf::DW_CHILDREN_yes &&
|
2009-05-21 07:21:38 +08:00
|
|
|
"Children flag not set");
|
2009-05-15 17:23:25 +08:00
|
|
|
|
2009-05-21 07:21:38 +08:00
|
|
|
for (unsigned j = 0, M = Children.size(); j < M; ++j)
|
2012-11-21 06:14:13 +08:00
|
|
|
Offset = computeSizeAndOffset(Children[j], Offset);
|
2009-05-15 17:23:25 +08:00
|
|
|
|
2009-05-21 07:21:38 +08:00
|
|
|
// End of children marker.
|
|
|
|
Offset += sizeof(int8_t);
|
|
|
|
}
|
2009-05-15 17:23:25 +08:00
|
|
|
|
2009-05-21 07:21:38 +08:00
|
|
|
Die->setSize(Offset - Die->getOffset());
|
|
|
|
return Offset;
|
2009-05-21 07:19:06 +08:00
|
|
|
}
|
2009-05-15 17:23:25 +08:00
|
|
|
|
2013-10-25 05:05:08 +08:00
|
|
|
// Compute the size and offset for each DIE.
|
2013-12-06 02:06:10 +08:00
|
|
|
void DwarfFile::computeSizeAndOffsets() {
|
2013-10-30 06:57:10 +08:00
|
|
|
// Offset from the first CU in the debug info section is 0 initially.
|
|
|
|
unsigned SecOffset = 0;
|
|
|
|
|
2013-10-25 05:05:08 +08:00
|
|
|
// Iterate over each compile unit and set the size and offsets for each
|
|
|
|
// DIE within each compile unit. All offsets are CU relative.
|
2013-12-10 07:32:48 +08:00
|
|
|
for (SmallVectorImpl<DwarfUnit *>::const_iterator I = CUs.begin(),
|
|
|
|
E = CUs.end();
|
2013-11-19 17:04:36 +08:00
|
|
|
I != E; ++I) {
|
2013-10-30 06:57:10 +08:00
|
|
|
(*I)->setDebugInfoOffset(SecOffset);
|
|
|
|
|
|
|
|
// CU-relative offset is reset to 0 here.
|
2013-11-19 17:04:36 +08:00
|
|
|
unsigned Offset = sizeof(int32_t) + // Length of Unit Info
|
2013-10-31 04:42:41 +08:00
|
|
|
(*I)->getHeaderSize(); // Unit-specific headers
|
2013-10-30 06:57:10 +08:00
|
|
|
|
|
|
|
// EndOffset here is CU-relative, after laying out
|
|
|
|
// all of the CU DIE.
|
2013-12-03 06:09:48 +08:00
|
|
|
unsigned EndOffset = computeSizeAndOffset((*I)->getUnitDie(), Offset);
|
2013-10-30 06:57:10 +08:00
|
|
|
SecOffset += EndOffset;
|
2010-05-11 06:49:55 +08:00
|
|
|
}
|
2009-05-21 07:19:06 +08:00
|
|
|
}
|
2009-05-15 17:23:25 +08:00
|
|
|
|
2012-11-28 06:43:45 +08:00
|
|
|
// Emit initial Dwarf sections with a label at the start of each one.
|
2012-11-21 08:34:35 +08:00
|
|
|
void DwarfDebug::emitSectionLabels() {
|
2009-08-19 13:49:37 +08:00
|
|
|
const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering();
|
2009-09-20 04:40:05 +08:00
|
|
|
|
2009-05-21 07:21:38 +08:00
|
|
|
// Dwarf sections base addresses.
|
2010-07-22 05:21:52 +08:00
|
|
|
DwarfInfoSectionSym =
|
2013-11-19 17:04:36 +08:00
|
|
|
emitSectionSym(Asm, TLOF.getDwarfInfoSection(), "section_info");
|
2013-12-31 01:22:27 +08:00
|
|
|
if (useSplitDwarf())
|
|
|
|
DwarfInfoDWOSectionSym =
|
|
|
|
emitSectionSym(Asm, TLOF.getDwarfInfoDWOSection(), "section_info_dwo");
|
2010-07-22 05:21:52 +08:00
|
|
|
DwarfAbbrevSectionSym =
|
2013-11-19 17:04:36 +08:00
|
|
|
emitSectionSym(Asm, TLOF.getDwarfAbbrevSection(), "section_abbrev");
|
2012-12-20 06:02:53 +08:00
|
|
|
if (useSplitDwarf())
|
2013-11-19 17:04:36 +08:00
|
|
|
DwarfAbbrevDWOSectionSym = emitSectionSym(
|
|
|
|
Asm, TLOF.getDwarfAbbrevDWOSection(), "section_abbrev_dwo");
|
2012-11-21 08:34:35 +08:00
|
|
|
emitSectionSym(Asm, TLOF.getDwarfARangesSection());
|
2010-07-22 05:21:52 +08:00
|
|
|
|
2010-04-05 06:59:04 +08:00
|
|
|
if (const MCSection *MacroInfo = TLOF.getDwarfMacroInfoSection())
|
2012-11-21 08:34:35 +08:00
|
|
|
emitSectionSym(Asm, MacroInfo);
|
2010-04-05 06:59:04 +08:00
|
|
|
|
2013-02-08 05:19:50 +08:00
|
|
|
DwarfLineSectionSym =
|
2013-11-19 17:04:36 +08:00
|
|
|
emitSectionSym(Asm, TLOF.getDwarfLineSection(), "section_line");
|
2012-11-21 08:34:35 +08:00
|
|
|
emitSectionSym(Asm, TLOF.getDwarfLocSection());
|
2013-09-24 04:55:35 +08:00
|
|
|
if (GenerateGnuPubSections) {
|
2013-10-01 07:14:16 +08:00
|
|
|
DwarfGnuPubNamesSectionSym =
|
|
|
|
emitSectionSym(Asm, TLOF.getDwarfGnuPubNamesSection());
|
|
|
|
DwarfGnuPubTypesSectionSym =
|
|
|
|
emitSectionSym(Asm, TLOF.getDwarfGnuPubTypesSection());
|
2013-09-24 04:55:35 +08:00
|
|
|
} else if (HasDwarfPubSections) {
|
|
|
|
emitSectionSym(Asm, TLOF.getDwarfPubNamesSection());
|
|
|
|
emitSectionSym(Asm, TLOF.getDwarfPubTypesSection());
|
2013-09-04 12:39:38 +08:00
|
|
|
}
|
2013-09-13 08:35:05 +08:00
|
|
|
|
2010-07-22 05:21:52 +08:00
|
|
|
DwarfStrSectionSym =
|
2013-11-19 17:04:36 +08:00
|
|
|
emitSectionSym(Asm, TLOF.getDwarfStrSection(), "info_string");
|
2013-04-07 11:43:09 +08:00
|
|
|
if (useSplitDwarf()) {
|
2012-12-27 10:14:01 +08:00
|
|
|
DwarfStrDWOSectionSym =
|
2013-11-19 17:04:36 +08:00
|
|
|
emitSectionSym(Asm, TLOF.getDwarfStrDWOSection(), "skel_string");
|
2013-04-07 11:43:09 +08:00
|
|
|
DwarfAddrSectionSym =
|
2013-11-19 17:04:36 +08:00
|
|
|
emitSectionSym(Asm, TLOF.getDwarfAddrSection(), "addr_sec");
|
2013-04-07 11:43:09 +08:00
|
|
|
}
|
2013-11-19 17:04:36 +08:00
|
|
|
DwarfDebugRangeSectionSym =
|
|
|
|
emitSectionSym(Asm, TLOF.getDwarfRangesSection(), "debug_range");
|
2009-05-15 17:23:25 +08:00
|
|
|
|
2013-11-19 17:04:36 +08:00
|
|
|
DwarfDebugLocSectionSym =
|
|
|
|
emitSectionSym(Asm, TLOF.getDwarfLocSection(), "section_debug_loc");
|
2009-05-21 07:04:56 +08:00
|
|
|
}
|
2009-05-15 17:23:25 +08:00
|
|
|
|
2012-11-28 06:43:45 +08:00
|
|
|
// Recursively emits a debug information entry.
|
2013-12-05 09:01:41 +08:00
|
|
|
void DwarfDebug::emitDIE(DIE *Die) {
|
2009-05-21 07:21:38 +08:00
|
|
|
// Get the abbreviation for this DIE.
|
2013-12-05 09:01:41 +08:00
|
|
|
const DIEAbbrev &Abbrev = Die->getAbbrev();
|
2009-05-21 07:04:56 +08:00
|
|
|
|
2009-05-21 07:21:38 +08:00
|
|
|
// Emit the code (index) for the abbreviation.
|
2010-04-05 02:52:31 +08:00
|
|
|
if (Asm->isVerbose())
|
2013-12-05 09:01:41 +08:00
|
|
|
Asm->OutStreamer.AddComment("Abbrev [" + Twine(Abbrev.getNumber()) +
|
|
|
|
"] 0x" + Twine::utohexstr(Die->getOffset()) +
|
|
|
|
":0x" + Twine::utohexstr(Die->getSize()) + " " +
|
|
|
|
dwarf::TagString(Abbrev.getTag()));
|
|
|
|
Asm->EmitULEB128(Abbrev.getNumber());
|
2009-05-21 07:04:56 +08:00
|
|
|
|
2013-11-19 17:04:36 +08:00
|
|
|
const SmallVectorImpl<DIEValue *> &Values = Die->getValues();
|
2013-12-05 09:01:41 +08:00
|
|
|
const SmallVectorImpl<DIEAbbrevData> &AbbrevData = Abbrev.getData();
|
2009-05-15 17:23:25 +08:00
|
|
|
|
2009-05-21 07:21:38 +08:00
|
|
|
// Emit the DIE attribute values.
|
|
|
|
for (unsigned i = 0, N = Values.size(); i < N; ++i) {
|
2013-10-22 01:28:37 +08:00
|
|
|
dwarf::Attribute Attr = AbbrevData[i].getAttribute();
|
|
|
|
dwarf::Form Form = AbbrevData[i].getForm();
|
2009-05-21 07:21:38 +08:00
|
|
|
assert(Form && "Too many attributes for DIE (check abbreviation)");
|
2009-05-15 17:23:25 +08:00
|
|
|
|
2010-04-05 02:52:31 +08:00
|
|
|
if (Asm->isVerbose())
|
2010-01-25 02:54:17 +08:00
|
|
|
Asm->OutStreamer.AddComment(dwarf::AttributeString(Attr));
|
2010-07-22 05:21:52 +08:00
|
|
|
|
2009-05-21 07:21:38 +08:00
|
|
|
switch (Attr) {
|
2013-10-30 06:57:10 +08:00
|
|
|
case dwarf::DW_AT_abstract_origin:
|
|
|
|
case dwarf::DW_AT_type:
|
|
|
|
case dwarf::DW_AT_friend:
|
|
|
|
case dwarf::DW_AT_specification:
|
|
|
|
case dwarf::DW_AT_import:
|
|
|
|
case dwarf::DW_AT_containing_type: {
|
|
|
|
DIEEntry *E = cast<DIEEntry>(Values[i]);
|
|
|
|
DIE *Origin = E->getEntry();
|
|
|
|
unsigned Addr = Origin->getOffset();
|
|
|
|
if (Form == dwarf::DW_FORM_ref_addr) {
|
|
|
|
assert(!useSplitDwarf() && "TODO: dwo files can't have relocations.");
|
|
|
|
// For DW_FORM_ref_addr, output the offset from beginning of debug info
|
|
|
|
// section. Origin->getOffset() returns the offset from start of the
|
|
|
|
// compile unit.
|
2013-12-10 07:57:44 +08:00
|
|
|
DwarfCompileUnit *CU = CUDieMap.lookup(Origin->getUnit());
|
2013-10-30 06:57:10 +08:00
|
|
|
assert(CU && "CUDie should belong to a CU.");
|
|
|
|
Addr += CU->getDebugInfoOffset();
|
|
|
|
if (Asm->MAI->doesDwarfUseRelocationsAcrossSections())
|
2013-12-07 06:14:48 +08:00
|
|
|
Asm->EmitLabelPlusOffset(CU->getSectionSym(), Addr,
|
2013-10-30 06:57:10 +08:00
|
|
|
DIEEntry::getRefAddrSize(Asm));
|
|
|
|
else
|
2013-12-07 06:14:48 +08:00
|
|
|
Asm->EmitLabelOffsetDifference(CU->getSectionSym(), Addr,
|
|
|
|
CU->getSectionSym(),
|
2013-10-30 07:14:15 +08:00
|
|
|
DIEEntry::getRefAddrSize(Asm));
|
2013-10-30 06:57:10 +08:00
|
|
|
} else {
|
2013-11-01 01:54:35 +08:00
|
|
|
// Make sure Origin belong to the same CU.
|
2013-11-20 07:08:21 +08:00
|
|
|
assert(Die->getUnit() == Origin->getUnit() &&
|
2013-11-01 01:54:35 +08:00
|
|
|
"The referenced DIE should belong to the same CU in ref4");
|
2013-10-30 06:57:10 +08:00
|
|
|
Asm->EmitInt32(Addr);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2010-05-26 07:40:22 +08:00
|
|
|
case dwarf::DW_AT_location: {
|
2012-06-22 09:25:12 +08:00
|
|
|
if (DIELabel *L = dyn_cast<DIELabel>(Values[i])) {
|
|
|
|
if (Asm->MAI->doesDwarfUseRelocationsAcrossSections())
|
2013-11-16 08:18:40 +08:00
|
|
|
Asm->EmitSectionOffset(L->getValue(), DwarfDebugLocSectionSym);
|
2012-06-22 09:25:12 +08:00
|
|
|
else
|
2013-07-03 02:46:26 +08:00
|
|
|
Asm->EmitLabelDifference(L->getValue(), DwarfDebugLocSectionSym, 4);
|
2012-06-22 09:25:12 +08:00
|
|
|
} else {
|
2010-05-26 07:40:22 +08:00
|
|
|
Values[i]->EmitValue(Asm, Form);
|
2012-06-22 09:25:12 +08:00
|
|
|
}
|
2010-05-26 07:40:22 +08:00
|
|
|
break;
|
2010-09-30 03:08:08 +08:00
|
|
|
}
|
|
|
|
case dwarf::DW_AT_accessibility: {
|
|
|
|
if (Asm->isVerbose()) {
|
|
|
|
DIEInteger *V = cast<DIEInteger>(Values[i]);
|
|
|
|
Asm->OutStreamer.AddComment(dwarf::AccessibilityString(V->getValue()));
|
|
|
|
}
|
|
|
|
Values[i]->EmitValue(Asm, Form);
|
|
|
|
break;
|
2010-05-26 07:40:22 +08:00
|
|
|
}
|
2009-05-21 07:21:38 +08:00
|
|
|
default:
|
|
|
|
// Emit an attribute using the defined form.
|
2010-04-05 08:13:49 +08:00
|
|
|
Values[i]->EmitValue(Asm, Form);
|
2009-05-21 07:21:38 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2009-05-15 17:23:25 +08:00
|
|
|
|
2009-05-21 07:21:38 +08:00
|
|
|
// Emit the DIE children if any.
|
2013-12-05 09:01:41 +08:00
|
|
|
if (Abbrev.getChildrenFlag() == dwarf::DW_CHILDREN_yes) {
|
2009-05-21 07:21:38 +08:00
|
|
|
const std::vector<DIE *> &Children = Die->getChildren();
|
2009-05-15 17:23:25 +08:00
|
|
|
|
2009-05-21 07:21:38 +08:00
|
|
|
for (unsigned j = 0, M = Children.size(); j < M; ++j)
|
2013-12-05 09:01:41 +08:00
|
|
|
emitDIE(Children[j]);
|
2009-05-15 17:23:25 +08:00
|
|
|
|
2013-12-05 05:51:05 +08:00
|
|
|
Asm->OutStreamer.AddComment("End Of Children Mark");
|
2010-03-10 07:52:58 +08:00
|
|
|
Asm->EmitInt8(0);
|
2009-05-21 07:19:06 +08:00
|
|
|
}
|
2009-05-21 07:21:38 +08:00
|
|
|
}
|
2009-05-15 17:23:25 +08:00
|
|
|
|
2012-12-15 08:04:07 +08:00
|
|
|
// Emit the various dwarf units to the unit section USection with
|
|
|
|
// the abbreviations going into ASection.
|
2013-12-07 06:14:48 +08:00
|
|
|
void DwarfFile::emitUnits(DwarfDebug *DD, const MCSection *ASection,
|
|
|
|
const MCSymbol *ASectionSym) {
|
2013-12-10 07:32:48 +08:00
|
|
|
for (SmallVectorImpl<DwarfUnit *>::iterator I = CUs.begin(), E = CUs.end();
|
|
|
|
I != E; ++I) {
|
|
|
|
DwarfUnit *TheU = *I;
|
2013-12-03 06:09:48 +08:00
|
|
|
DIE *Die = TheU->getUnitDie();
|
2013-12-07 06:14:48 +08:00
|
|
|
const MCSection *USection = TheU->getSection();
|
|
|
|
Asm->OutStreamer.SwitchSection(USection);
|
2010-07-22 05:21:52 +08:00
|
|
|
|
2010-05-11 06:49:55 +08:00
|
|
|
// Emit the compile units header.
|
2013-12-07 06:33:05 +08:00
|
|
|
Asm->OutStreamer.EmitLabel(TheU->getLabelBegin());
|
2010-07-22 05:21:52 +08:00
|
|
|
|
2010-05-11 06:49:55 +08:00
|
|
|
// Emit size of content not including length itself
|
2013-10-31 04:42:41 +08:00
|
|
|
Asm->OutStreamer.AddComment("Length of Unit");
|
2013-12-03 06:09:48 +08:00
|
|
|
Asm->EmitInt32(TheU->getHeaderSize() + Die->getSize());
|
2013-10-31 04:42:41 +08:00
|
|
|
|
2013-12-03 06:09:48 +08:00
|
|
|
TheU->emitHeader(ASection, ASectionSym);
|
2010-07-22 05:21:52 +08:00
|
|
|
|
2013-12-05 09:01:41 +08:00
|
|
|
DD->emitDIE(Die);
|
2013-12-07 06:33:05 +08:00
|
|
|
Asm->OutStreamer.EmitLabel(TheU->getLabelEnd());
|
2010-05-11 06:49:55 +08:00
|
|
|
}
|
2009-05-21 07:04:56 +08:00
|
|
|
}
|
2009-05-15 17:23:25 +08:00
|
|
|
|
2012-12-01 07:59:06 +08:00
|
|
|
// Emit the debug info section.
|
|
|
|
void DwarfDebug::emitDebugInfo() {
|
2013-12-06 02:06:10 +08:00
|
|
|
DwarfFile &Holder = useSplitDwarf() ? SkeletonHolder : InfoHolder;
|
2012-12-15 08:04:07 +08:00
|
|
|
|
2013-12-07 06:14:48 +08:00
|
|
|
Holder.emitUnits(this, Asm->getObjFileLowering().getDwarfAbbrevSection(),
|
2012-12-15 08:04:07 +08:00
|
|
|
DwarfAbbrevSectionSym);
|
2012-12-01 07:59:06 +08:00
|
|
|
}
|
|
|
|
|
2012-11-28 06:43:45 +08:00
|
|
|
// Emit the abbreviation section.
|
2012-11-21 07:30:11 +08:00
|
|
|
void DwarfDebug::emitAbbreviations() {
|
2013-12-06 02:06:10 +08:00
|
|
|
DwarfFile &Holder = useSplitDwarf() ? SkeletonHolder : InfoHolder;
|
2013-12-05 15:43:55 +08:00
|
|
|
|
|
|
|
Holder.emitAbbrevs(Asm->getObjFileLowering().getDwarfAbbrevSection());
|
2012-12-20 06:02:53 +08:00
|
|
|
}
|
|
|
|
|
2013-12-06 02:06:10 +08:00
|
|
|
void DwarfFile::emitAbbrevs(const MCSection *Section) {
|
2009-05-21 07:21:38 +08:00
|
|
|
// Check to see if it is worth the effort.
|
2013-12-05 15:43:55 +08:00
|
|
|
if (!Abbreviations.empty()) {
|
2009-05-21 07:21:38 +08:00
|
|
|
// Start the debug abbrev section.
|
2012-12-20 06:02:53 +08:00
|
|
|
Asm->OutStreamer.SwitchSection(Section);
|
2009-05-15 17:23:25 +08:00
|
|
|
|
2009-05-21 07:21:38 +08:00
|
|
|
// For each abbrevation.
|
2013-12-05 15:43:55 +08:00
|
|
|
for (unsigned i = 0, N = Abbreviations.size(); i < N; ++i) {
|
2009-05-21 07:21:38 +08:00
|
|
|
// Get abbreviation data
|
2013-12-05 15:43:55 +08:00
|
|
|
const DIEAbbrev *Abbrev = Abbreviations[i];
|
2009-05-15 17:23:25 +08:00
|
|
|
|
2009-05-21 07:21:38 +08:00
|
|
|
// Emit the abbrevations code (base 1 index.)
|
2010-04-05 03:09:29 +08:00
|
|
|
Asm->EmitULEB128(Abbrev->getNumber(), "Abbreviation Code");
|
2009-05-15 17:23:25 +08:00
|
|
|
|
2009-05-21 07:21:38 +08:00
|
|
|
// Emit the abbreviations data.
|
2010-04-05 08:13:49 +08:00
|
|
|
Abbrev->Emit(Asm);
|
2009-05-21 07:21:38 +08:00
|
|
|
}
|
2009-05-15 17:23:25 +08:00
|
|
|
|
2009-05-21 07:21:38 +08:00
|
|
|
// Mark end of abbreviations.
|
2010-04-05 03:09:29 +08:00
|
|
|
Asm->EmitULEB128(0, "EOM(3)");
|
2009-05-21 07:21:38 +08:00
|
|
|
}
|
|
|
|
}
|
2009-05-15 17:23:25 +08:00
|
|
|
|
2012-11-28 06:43:45 +08:00
|
|
|
// Emit the last address of the section and the end of the line matrix.
|
2009-11-21 10:48:08 +08:00
|
|
|
void DwarfDebug::emitEndOfLineMatrix(unsigned SectionEnd) {
|
2009-05-21 07:21:38 +08:00
|
|
|
// Define last address of section.
|
2010-03-10 07:52:58 +08:00
|
|
|
Asm->OutStreamer.AddComment("Extended Op");
|
|
|
|
Asm->EmitInt8(0);
|
2010-07-22 05:21:52 +08:00
|
|
|
|
2010-03-10 07:52:58 +08:00
|
|
|
Asm->OutStreamer.AddComment("Op size");
|
Revert the majority of the next patch in the address space series:
r165941: Resubmit the changes to llvm core to update the functions to
support different pointer sizes on a per address space basis.
Despite this commit log, this change primarily changed stuff outside of
VMCore, and those changes do not carry any tests for correctness (or
even plausibility), and we have consistently found questionable or flat
out incorrect cases in these changes. Most of them are probably correct,
but we need to devise a system that makes it more clear when we have
handled the address space concerns correctly, and ideally each pass that
gets updated would receive an accompanying test case that exercises that
pass specificaly w.r.t. alternate address spaces.
However, from this commit, I have retained the new C API entry points.
Those were an orthogonal change that probably should have been split
apart, but they seem entirely good.
In several places the changes were very obvious cleanups with no actual
multiple address space code added; these I have not reverted when
I spotted them.
In a few other places there were merge conflicts due to a cleaner
solution being implemented later, often not using address spaces at all.
In those cases, I've preserved the new code which isn't address space
dependent.
This is part of my ongoing effort to clean out the partial address space
code which carries high risk and low test coverage, and not likely to be
finished before the 3.2 release looms closer. Duncan and I would both
like to see the above issues addressed before we return to these
changes.
llvm-svn: 167222
2012-11-01 17:14:31 +08:00
|
|
|
Asm->EmitInt8(Asm->getDataLayout().getPointerSize() + 1);
|
2010-03-10 07:52:58 +08:00
|
|
|
Asm->OutStreamer.AddComment("DW_LNE_set_address");
|
|
|
|
Asm->EmitInt8(dwarf::DW_LNE_set_address);
|
|
|
|
|
|
|
|
Asm->OutStreamer.AddComment("Section end label");
|
2010-03-10 09:17:49 +08:00
|
|
|
|
2013-11-19 17:04:36 +08:00
|
|
|
Asm->OutStreamer.EmitSymbolValue(
|
|
|
|
Asm->GetTempSymbol("section_end", SectionEnd),
|
|
|
|
Asm->getDataLayout().getPointerSize());
|
2009-05-15 17:23:25 +08:00
|
|
|
|
2009-05-21 07:21:38 +08:00
|
|
|
// Mark end of matrix.
|
2010-03-10 07:52:58 +08:00
|
|
|
Asm->OutStreamer.AddComment("DW_LNE_end_sequence");
|
|
|
|
Asm->EmitInt8(0);
|
2010-01-23 06:09:00 +08:00
|
|
|
Asm->EmitInt8(1);
|
2010-01-23 07:18:42 +08:00
|
|
|
Asm->EmitInt8(1);
|
2009-05-21 07:21:38 +08:00
|
|
|
}
|
2009-05-15 17:23:25 +08:00
|
|
|
|
2012-11-28 06:43:45 +08:00
|
|
|
// Emit visible names into a hashed accelerator table section.
|
2011-11-07 17:24:32 +08:00
|
|
|
void DwarfDebug::emitAccelNames() {
|
2013-11-19 17:04:36 +08:00
|
|
|
DwarfAccelTable AT(
|
|
|
|
DwarfAccelTable::Atom(dwarf::DW_ATOM_die_offset, dwarf::DW_FORM_data4));
|
2013-12-10 07:32:48 +08:00
|
|
|
for (SmallVectorImpl<DwarfUnit *>::const_iterator I = getUnits().begin(),
|
|
|
|
E = getUnits().end();
|
2013-11-19 17:04:36 +08:00
|
|
|
I != E; ++I) {
|
2013-12-10 07:32:48 +08:00
|
|
|
DwarfUnit *TheU = *I;
|
2013-12-03 06:09:48 +08:00
|
|
|
const StringMap<std::vector<const DIE *> > &Names = TheU->getAccelNames();
|
2013-11-20 06:51:04 +08:00
|
|
|
for (StringMap<std::vector<const DIE *> >::const_iterator
|
|
|
|
GI = Names.begin(),
|
|
|
|
GE = Names.end();
|
2013-11-19 17:04:36 +08:00
|
|
|
GI != GE; ++GI) {
|
2013-05-12 02:24:28 +08:00
|
|
|
StringRef Name = GI->getKey();
|
2013-11-20 06:51:04 +08:00
|
|
|
const std::vector<const DIE *> &Entities = GI->second;
|
|
|
|
for (std::vector<const DIE *>::const_iterator DI = Entities.begin(),
|
|
|
|
DE = Entities.end();
|
2013-11-19 17:04:36 +08:00
|
|
|
DI != DE; ++DI)
|
2013-11-20 06:51:04 +08:00
|
|
|
AT.AddName(Name, *DI);
|
2011-11-07 17:24:32 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
AT.FinalizeTable(Asm, "Names");
|
|
|
|
Asm->OutStreamer.SwitchSection(
|
2013-11-19 17:04:36 +08:00
|
|
|
Asm->getObjFileLowering().getDwarfAccelNamesSection());
|
2011-11-07 17:24:32 +08:00
|
|
|
MCSymbol *SectionBegin = Asm->GetTempSymbol("names_begin");
|
|
|
|
Asm->OutStreamer.EmitLabel(SectionBegin);
|
|
|
|
|
|
|
|
// Emit the full data.
|
2012-12-21 05:58:36 +08:00
|
|
|
AT.Emit(Asm, SectionBegin, &InfoHolder);
|
2011-11-07 17:24:32 +08:00
|
|
|
}
|
|
|
|
|
2012-12-21 05:58:40 +08:00
|
|
|
// Emit objective C classes and categories into a hashed accelerator table
|
|
|
|
// section.
|
2011-11-07 17:24:32 +08:00
|
|
|
void DwarfDebug::emitAccelObjC() {
|
2013-11-19 17:04:36 +08:00
|
|
|
DwarfAccelTable AT(
|
|
|
|
DwarfAccelTable::Atom(dwarf::DW_ATOM_die_offset, dwarf::DW_FORM_data4));
|
2013-12-10 07:32:48 +08:00
|
|
|
for (SmallVectorImpl<DwarfUnit *>::const_iterator I = getUnits().begin(),
|
|
|
|
E = getUnits().end();
|
2013-11-19 17:04:36 +08:00
|
|
|
I != E; ++I) {
|
2013-12-10 07:32:48 +08:00
|
|
|
DwarfUnit *TheU = *I;
|
2013-12-03 06:09:48 +08:00
|
|
|
const StringMap<std::vector<const DIE *> > &Names = TheU->getAccelObjC();
|
2013-11-20 06:51:04 +08:00
|
|
|
for (StringMap<std::vector<const DIE *> >::const_iterator
|
|
|
|
GI = Names.begin(),
|
|
|
|
GE = Names.end();
|
2013-11-19 17:04:36 +08:00
|
|
|
GI != GE; ++GI) {
|
2013-05-12 02:24:28 +08:00
|
|
|
StringRef Name = GI->getKey();
|
2013-11-20 06:51:04 +08:00
|
|
|
const std::vector<const DIE *> &Entities = GI->second;
|
|
|
|
for (std::vector<const DIE *>::const_iterator DI = Entities.begin(),
|
|
|
|
DE = Entities.end();
|
2013-11-19 17:04:36 +08:00
|
|
|
DI != DE; ++DI)
|
2013-11-20 06:51:04 +08:00
|
|
|
AT.AddName(Name, *DI);
|
2011-11-07 17:24:32 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
AT.FinalizeTable(Asm, "ObjC");
|
2013-11-19 17:04:36 +08:00
|
|
|
Asm->OutStreamer.SwitchSection(
|
|
|
|
Asm->getObjFileLowering().getDwarfAccelObjCSection());
|
2011-11-07 17:24:32 +08:00
|
|
|
MCSymbol *SectionBegin = Asm->GetTempSymbol("objc_begin");
|
|
|
|
Asm->OutStreamer.EmitLabel(SectionBegin);
|
|
|
|
|
|
|
|
// Emit the full data.
|
2012-12-21 05:58:36 +08:00
|
|
|
AT.Emit(Asm, SectionBegin, &InfoHolder);
|
2011-11-07 17:24:32 +08:00
|
|
|
}
|
|
|
|
|
2012-11-28 06:43:45 +08:00
|
|
|
// Emit namespace dies into a hashed accelerator table.
|
2011-11-07 17:24:32 +08:00
|
|
|
void DwarfDebug::emitAccelNamespaces() {
|
2013-11-19 17:04:36 +08:00
|
|
|
DwarfAccelTable AT(
|
|
|
|
DwarfAccelTable::Atom(dwarf::DW_ATOM_die_offset, dwarf::DW_FORM_data4));
|
2013-12-10 07:32:48 +08:00
|
|
|
for (SmallVectorImpl<DwarfUnit *>::const_iterator I = getUnits().begin(),
|
|
|
|
E = getUnits().end();
|
2013-11-19 17:04:36 +08:00
|
|
|
I != E; ++I) {
|
2013-12-10 07:32:48 +08:00
|
|
|
DwarfUnit *TheU = *I;
|
2013-11-20 06:51:04 +08:00
|
|
|
const StringMap<std::vector<const DIE *> > &Names =
|
2013-12-03 06:09:48 +08:00
|
|
|
TheU->getAccelNamespace();
|
2013-11-20 06:51:04 +08:00
|
|
|
for (StringMap<std::vector<const DIE *> >::const_iterator
|
|
|
|
GI = Names.begin(),
|
|
|
|
GE = Names.end();
|
2013-11-19 17:04:36 +08:00
|
|
|
GI != GE; ++GI) {
|
2013-05-12 02:24:28 +08:00
|
|
|
StringRef Name = GI->getKey();
|
2013-11-20 06:51:04 +08:00
|
|
|
const std::vector<const DIE *> &Entities = GI->second;
|
|
|
|
for (std::vector<const DIE *>::const_iterator DI = Entities.begin(),
|
|
|
|
DE = Entities.end();
|
2013-11-19 17:04:36 +08:00
|
|
|
DI != DE; ++DI)
|
2013-11-20 06:51:04 +08:00
|
|
|
AT.AddName(Name, *DI);
|
2011-11-07 17:24:32 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
AT.FinalizeTable(Asm, "namespac");
|
2013-11-19 17:04:36 +08:00
|
|
|
Asm->OutStreamer.SwitchSection(
|
|
|
|
Asm->getObjFileLowering().getDwarfAccelNamespaceSection());
|
2011-11-07 17:24:32 +08:00
|
|
|
MCSymbol *SectionBegin = Asm->GetTempSymbol("namespac_begin");
|
|
|
|
Asm->OutStreamer.EmitLabel(SectionBegin);
|
|
|
|
|
|
|
|
// Emit the full data.
|
2012-12-21 05:58:36 +08:00
|
|
|
AT.Emit(Asm, SectionBegin, &InfoHolder);
|
2011-11-07 17:24:32 +08:00
|
|
|
}
|
|
|
|
|
2012-11-28 06:43:45 +08:00
|
|
|
// Emit type dies into a hashed accelerator table.
|
2011-11-07 17:24:32 +08:00
|
|
|
void DwarfDebug::emitAccelTypes() {
|
2012-01-06 12:35:23 +08:00
|
|
|
std::vector<DwarfAccelTable::Atom> Atoms;
|
2013-11-19 17:04:36 +08:00
|
|
|
Atoms.push_back(
|
|
|
|
DwarfAccelTable::Atom(dwarf::DW_ATOM_die_offset, dwarf::DW_FORM_data4));
|
|
|
|
Atoms.push_back(
|
|
|
|
DwarfAccelTable::Atom(dwarf::DW_ATOM_die_tag, dwarf::DW_FORM_data2));
|
|
|
|
Atoms.push_back(
|
|
|
|
DwarfAccelTable::Atom(dwarf::DW_ATOM_type_flags, dwarf::DW_FORM_data1));
|
2012-01-06 12:35:23 +08:00
|
|
|
DwarfAccelTable AT(Atoms);
|
2013-12-10 07:32:48 +08:00
|
|
|
for (SmallVectorImpl<DwarfUnit *>::const_iterator I = getUnits().begin(),
|
|
|
|
E = getUnits().end();
|
2013-11-19 17:04:36 +08:00
|
|
|
I != E; ++I) {
|
2013-12-10 07:32:48 +08:00
|
|
|
DwarfUnit *TheU = *I;
|
2013-11-20 06:51:04 +08:00
|
|
|
const StringMap<std::vector<std::pair<const DIE *, unsigned> > > &Names =
|
2013-12-03 06:09:48 +08:00
|
|
|
TheU->getAccelTypes();
|
2013-11-20 06:51:04 +08:00
|
|
|
for (StringMap<
|
|
|
|
std::vector<std::pair<const DIE *, unsigned> > >::const_iterator
|
2013-11-19 17:04:36 +08:00
|
|
|
GI = Names.begin(),
|
|
|
|
GE = Names.end();
|
|
|
|
GI != GE; ++GI) {
|
2013-05-12 02:24:28 +08:00
|
|
|
StringRef Name = GI->getKey();
|
2013-11-20 06:51:04 +08:00
|
|
|
const std::vector<std::pair<const DIE *, unsigned> > &Entities =
|
|
|
|
GI->second;
|
|
|
|
for (std::vector<std::pair<const DIE *, unsigned> >::const_iterator
|
2013-11-19 17:04:36 +08:00
|
|
|
DI = Entities.begin(),
|
|
|
|
DE = Entities.end();
|
|
|
|
DI != DE; ++DI)
|
2013-11-20 06:51:04 +08:00
|
|
|
AT.AddName(Name, DI->first, DI->second);
|
2011-11-07 17:24:32 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
AT.FinalizeTable(Asm, "types");
|
2013-11-19 17:04:36 +08:00
|
|
|
Asm->OutStreamer.SwitchSection(
|
|
|
|
Asm->getObjFileLowering().getDwarfAccelTypesSection());
|
2011-11-07 17:24:32 +08:00
|
|
|
MCSymbol *SectionBegin = Asm->GetTempSymbol("types_begin");
|
|
|
|
Asm->OutStreamer.EmitLabel(SectionBegin);
|
|
|
|
|
|
|
|
// Emit the full data.
|
2012-12-21 05:58:36 +08:00
|
|
|
AT.Emit(Asm, SectionBegin, &InfoHolder);
|
2011-11-07 17:24:32 +08:00
|
|
|
}
|
|
|
|
|
2013-09-13 08:35:05 +08:00
|
|
|
// Public name handling.
|
|
|
|
// The format for the various pubnames:
|
|
|
|
//
|
|
|
|
// dwarf pubnames - offset/name pairs where the offset is the offset into the CU
|
|
|
|
// for the DIE that is named.
|
|
|
|
//
|
|
|
|
// gnu pubnames - offset/index value/name tuples where the offset is the offset
|
|
|
|
// into the CU and the index value is computed according to the type of value
|
|
|
|
// for the DIE that is named.
|
|
|
|
//
|
|
|
|
// For type units the offset is the offset of the skeleton DIE. For split dwarf
|
|
|
|
// it's the offset within the debug_info/debug_types dwo section, however, the
|
|
|
|
// reference in the pubname header doesn't change.
|
|
|
|
|
|
|
|
/// computeIndexValue - Compute the gdb index value for the DIE and CU.
|
2013-12-10 07:32:48 +08:00
|
|
|
static dwarf::PubIndexEntryDescriptor computeIndexValue(DwarfUnit *CU,
|
2013-11-21 08:48:22 +08:00
|
|
|
const DIE *Die) {
|
2013-10-16 09:37:49 +08:00
|
|
|
dwarf::GDBIndexEntryLinkage Linkage = dwarf::GIEL_STATIC;
|
|
|
|
|
|
|
|
// We could have a specification DIE that has our most of our knowledge,
|
|
|
|
// look for that now.
|
|
|
|
DIEValue *SpecVal = Die->findAttribute(dwarf::DW_AT_specification);
|
|
|
|
if (SpecVal) {
|
|
|
|
DIE *SpecDIE = cast<DIEEntry>(SpecVal)->getEntry();
|
|
|
|
if (SpecDIE->findAttribute(dwarf::DW_AT_external))
|
|
|
|
Linkage = dwarf::GIEL_EXTERNAL;
|
|
|
|
} else if (Die->findAttribute(dwarf::DW_AT_external))
|
|
|
|
Linkage = dwarf::GIEL_EXTERNAL;
|
2013-09-13 08:35:05 +08:00
|
|
|
|
|
|
|
switch (Die->getTag()) {
|
|
|
|
case dwarf::DW_TAG_class_type:
|
|
|
|
case dwarf::DW_TAG_structure_type:
|
|
|
|
case dwarf::DW_TAG_union_type:
|
|
|
|
case dwarf::DW_TAG_enumeration_type:
|
2013-09-24 04:55:35 +08:00
|
|
|
return dwarf::PubIndexEntryDescriptor(
|
|
|
|
dwarf::GIEK_TYPE, CU->getLanguage() != dwarf::DW_LANG_C_plus_plus
|
|
|
|
? dwarf::GIEL_STATIC
|
|
|
|
: dwarf::GIEL_EXTERNAL);
|
2013-09-13 08:35:05 +08:00
|
|
|
case dwarf::DW_TAG_typedef:
|
|
|
|
case dwarf::DW_TAG_base_type:
|
|
|
|
case dwarf::DW_TAG_subrange_type:
|
2013-09-20 04:40:26 +08:00
|
|
|
return dwarf::PubIndexEntryDescriptor(dwarf::GIEK_TYPE, dwarf::GIEL_STATIC);
|
2013-09-13 08:35:05 +08:00
|
|
|
case dwarf::DW_TAG_namespace:
|
2013-09-20 04:40:26 +08:00
|
|
|
return dwarf::GIEK_TYPE;
|
2013-09-13 08:35:05 +08:00
|
|
|
case dwarf::DW_TAG_subprogram:
|
2013-09-24 06:59:14 +08:00
|
|
|
return dwarf::PubIndexEntryDescriptor(dwarf::GIEK_FUNCTION, Linkage);
|
2013-09-13 08:35:05 +08:00
|
|
|
case dwarf::DW_TAG_constant:
|
|
|
|
case dwarf::DW_TAG_variable:
|
2013-09-24 06:59:14 +08:00
|
|
|
return dwarf::PubIndexEntryDescriptor(dwarf::GIEK_VARIABLE, Linkage);
|
2013-09-13 08:35:05 +08:00
|
|
|
case dwarf::DW_TAG_enumerator:
|
2013-09-20 04:40:26 +08:00
|
|
|
return dwarf::PubIndexEntryDescriptor(dwarf::GIEK_VARIABLE,
|
|
|
|
dwarf::GIEL_STATIC);
|
2013-09-13 08:35:05 +08:00
|
|
|
default:
|
2013-09-20 04:40:26 +08:00
|
|
|
return dwarf::GIEK_NONE;
|
2013-09-13 08:35:05 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-09-10 04:03:17 +08:00
|
|
|
/// emitDebugPubNames - Emit visible names into a debug pubnames section.
|
2013-02-13 02:00:14 +08:00
|
|
|
///
|
2013-09-13 08:35:05 +08:00
|
|
|
void DwarfDebug::emitDebugPubNames(bool GnuStyle) {
|
|
|
|
const MCSection *PSec =
|
|
|
|
GnuStyle ? Asm->getObjFileLowering().getDwarfGnuPubNamesSection()
|
|
|
|
: Asm->getObjFileLowering().getDwarfPubNamesSection();
|
2013-02-13 02:00:14 +08:00
|
|
|
|
2013-12-07 03:38:49 +08:00
|
|
|
DwarfFile &Holder = useSplitDwarf() ? SkeletonHolder : InfoHolder;
|
2013-12-10 07:32:48 +08:00
|
|
|
const SmallVectorImpl<DwarfUnit *> &Units = Holder.getUnits();
|
2013-12-07 03:38:49 +08:00
|
|
|
for (unsigned i = 0; i != Units.size(); ++i) {
|
2013-12-10 07:32:48 +08:00
|
|
|
DwarfUnit *TheU = Units[i];
|
2013-12-03 06:09:48 +08:00
|
|
|
unsigned ID = TheU->getUniqueID();
|
2013-02-13 02:00:14 +08:00
|
|
|
|
|
|
|
// Start the dwarf pubnames section.
|
2013-09-11 05:49:37 +08:00
|
|
|
Asm->OutStreamer.SwitchSection(PSec);
|
2013-02-13 02:00:14 +08:00
|
|
|
|
2013-10-01 07:14:16 +08:00
|
|
|
// Emit a label so we can reference the beginning of this pubname section.
|
|
|
|
if (GnuStyle)
|
2013-12-05 01:55:41 +08:00
|
|
|
Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("gnu_pubnames", ID));
|
2013-10-01 07:14:16 +08:00
|
|
|
|
2013-09-13 08:35:05 +08:00
|
|
|
// Emit the header.
|
2013-02-13 02:00:14 +08:00
|
|
|
Asm->OutStreamer.AddComment("Length of Public Names Info");
|
2013-12-05 01:55:41 +08:00
|
|
|
MCSymbol *BeginLabel = Asm->GetTempSymbol("pubnames_begin", ID);
|
|
|
|
MCSymbol *EndLabel = Asm->GetTempSymbol("pubnames_end", ID);
|
|
|
|
Asm->EmitLabelDifference(EndLabel, BeginLabel, 4);
|
2013-02-13 02:00:14 +08:00
|
|
|
|
2013-12-05 01:55:41 +08:00
|
|
|
Asm->OutStreamer.EmitLabel(BeginLabel);
|
2013-02-13 02:00:14 +08:00
|
|
|
|
|
|
|
Asm->OutStreamer.AddComment("DWARF Version");
|
2013-08-21 14:13:34 +08:00
|
|
|
Asm->EmitInt16(dwarf::DW_PUBNAMES_VERSION);
|
2013-02-13 02:00:14 +08:00
|
|
|
|
|
|
|
Asm->OutStreamer.AddComment("Offset of Compilation Unit Info");
|
2013-12-07 06:33:05 +08:00
|
|
|
Asm->EmitSectionOffset(TheU->getLabelBegin(), TheU->getSectionSym());
|
2013-02-13 02:00:14 +08:00
|
|
|
|
|
|
|
Asm->OutStreamer.AddComment("Compilation Unit Length");
|
2013-12-07 06:33:05 +08:00
|
|
|
Asm->EmitLabelDifference(TheU->getLabelEnd(), TheU->getLabelBegin(), 4);
|
2013-02-13 02:00:14 +08:00
|
|
|
|
2013-09-13 08:35:05 +08:00
|
|
|
// Emit the pubnames for this compilation unit.
|
2013-12-07 03:38:49 +08:00
|
|
|
const StringMap<const DIE *> &Globals = getUnits()[ID]->getGlobalNames();
|
2013-11-21 08:48:22 +08:00
|
|
|
for (StringMap<const DIE *>::const_iterator GI = Globals.begin(),
|
|
|
|
GE = Globals.end();
|
2013-11-19 17:04:36 +08:00
|
|
|
GI != GE; ++GI) {
|
2013-02-13 02:00:14 +08:00
|
|
|
const char *Name = GI->getKeyData();
|
2013-11-21 08:48:22 +08:00
|
|
|
const DIE *Entity = GI->second;
|
2013-02-13 02:00:14 +08:00
|
|
|
|
|
|
|
Asm->OutStreamer.AddComment("DIE offset");
|
|
|
|
Asm->EmitInt32(Entity->getOffset());
|
|
|
|
|
2013-09-13 08:35:05 +08:00
|
|
|
if (GnuStyle) {
|
2013-12-03 06:09:48 +08:00
|
|
|
dwarf::PubIndexEntryDescriptor Desc = computeIndexValue(TheU, Entity);
|
2013-09-20 06:19:37 +08:00
|
|
|
Asm->OutStreamer.AddComment(
|
2013-09-20 08:33:15 +08:00
|
|
|
Twine("Kind: ") + dwarf::GDBIndexEntryKindString(Desc.Kind) + ", " +
|
2013-09-20 07:01:29 +08:00
|
|
|
dwarf::GDBIndexEntryLinkageString(Desc.Linkage));
|
2013-09-20 06:19:37 +08:00
|
|
|
Asm->EmitInt8(Desc.toBits());
|
2013-09-13 08:35:05 +08:00
|
|
|
}
|
|
|
|
|
2013-12-05 05:51:05 +08:00
|
|
|
Asm->OutStreamer.AddComment("External Name");
|
2013-11-19 17:04:36 +08:00
|
|
|
Asm->OutStreamer.EmitBytes(StringRef(Name, GI->getKeyLength() + 1));
|
2013-02-13 02:00:14 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
Asm->OutStreamer.AddComment("End Mark");
|
|
|
|
Asm->EmitInt32(0);
|
2013-12-05 01:55:41 +08:00
|
|
|
Asm->OutStreamer.EmitLabel(EndLabel);
|
2013-02-13 02:00:14 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-09-13 08:35:05 +08:00
|
|
|
void DwarfDebug::emitDebugPubTypes(bool GnuStyle) {
|
2013-09-24 04:55:35 +08:00
|
|
|
const MCSection *PSec =
|
|
|
|
GnuStyle ? Asm->getObjFileLowering().getDwarfGnuPubTypesSection()
|
|
|
|
: Asm->getObjFileLowering().getDwarfPubTypesSection();
|
2013-09-13 08:34:58 +08:00
|
|
|
|
2013-12-07 03:38:49 +08:00
|
|
|
DwarfFile &Holder = useSplitDwarf() ? SkeletonHolder : InfoHolder;
|
2013-12-10 07:32:48 +08:00
|
|
|
const SmallVectorImpl<DwarfUnit *> &Units = Holder.getUnits();
|
2013-12-07 03:38:49 +08:00
|
|
|
for (unsigned i = 0; i != Units.size(); ++i) {
|
2013-12-10 07:32:48 +08:00
|
|
|
DwarfUnit *TheU = Units[i];
|
2013-12-05 01:55:41 +08:00
|
|
|
unsigned ID = TheU->getUniqueID();
|
|
|
|
|
2011-11-07 17:18:35 +08:00
|
|
|
// Start the dwarf pubtypes section.
|
2013-09-13 08:34:58 +08:00
|
|
|
Asm->OutStreamer.SwitchSection(PSec);
|
2013-10-01 07:14:16 +08:00
|
|
|
|
|
|
|
// Emit a label so we can reference the beginning of this pubtype section.
|
|
|
|
if (GnuStyle)
|
2013-12-05 01:55:41 +08:00
|
|
|
Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("gnu_pubtypes", ID));
|
2013-10-01 07:14:16 +08:00
|
|
|
|
|
|
|
// Emit the header.
|
2010-05-11 06:49:55 +08:00
|
|
|
Asm->OutStreamer.AddComment("Length of Public Types Info");
|
2013-12-05 01:55:41 +08:00
|
|
|
MCSymbol *BeginLabel = Asm->GetTempSymbol("pubtypes_begin", ID);
|
|
|
|
MCSymbol *EndLabel = Asm->GetTempSymbol("pubtypes_end", ID);
|
|
|
|
Asm->EmitLabelDifference(EndLabel, BeginLabel, 4);
|
2010-07-22 05:21:52 +08:00
|
|
|
|
2013-12-05 01:55:41 +08:00
|
|
|
Asm->OutStreamer.EmitLabel(BeginLabel);
|
2010-07-22 05:21:52 +08:00
|
|
|
|
2013-12-05 05:51:05 +08:00
|
|
|
Asm->OutStreamer.AddComment("DWARF Version");
|
2013-08-21 14:13:34 +08:00
|
|
|
Asm->EmitInt16(dwarf::DW_PUBTYPES_VERSION);
|
2010-07-22 05:21:52 +08:00
|
|
|
|
2010-05-11 06:49:55 +08:00
|
|
|
Asm->OutStreamer.AddComment("Offset of Compilation Unit Info");
|
2013-12-07 06:33:05 +08:00
|
|
|
Asm->EmitSectionOffset(TheU->getLabelBegin(), TheU->getSectionSym());
|
2010-07-22 05:21:52 +08:00
|
|
|
|
2010-05-11 06:49:55 +08:00
|
|
|
Asm->OutStreamer.AddComment("Compilation Unit Length");
|
2013-12-07 06:33:05 +08:00
|
|
|
Asm->EmitLabelDifference(TheU->getLabelEnd(), TheU->getLabelBegin(), 4);
|
2010-07-22 05:21:52 +08:00
|
|
|
|
2013-10-01 07:14:16 +08:00
|
|
|
// Emit the pubtypes.
|
2013-12-07 03:38:49 +08:00
|
|
|
const StringMap<const DIE *> &Globals = getUnits()[ID]->getGlobalTypes();
|
2013-11-21 08:48:22 +08:00
|
|
|
for (StringMap<const DIE *>::const_iterator GI = Globals.begin(),
|
|
|
|
GE = Globals.end();
|
2013-09-13 08:34:58 +08:00
|
|
|
GI != GE; ++GI) {
|
2010-05-11 06:49:55 +08:00
|
|
|
const char *Name = GI->getKeyData();
|
2013-11-21 08:48:22 +08:00
|
|
|
const DIE *Entity = GI->second;
|
2010-07-22 05:21:52 +08:00
|
|
|
|
2013-12-05 05:51:05 +08:00
|
|
|
Asm->OutStreamer.AddComment("DIE offset");
|
2010-05-11 06:49:55 +08:00
|
|
|
Asm->EmitInt32(Entity->getOffset());
|
2010-07-22 05:21:52 +08:00
|
|
|
|
2013-09-13 08:35:05 +08:00
|
|
|
if (GnuStyle) {
|
2013-12-03 06:09:48 +08:00
|
|
|
dwarf::PubIndexEntryDescriptor Desc = computeIndexValue(TheU, Entity);
|
2013-09-20 06:19:37 +08:00
|
|
|
Asm->OutStreamer.AddComment(
|
2013-09-20 08:33:15 +08:00
|
|
|
Twine("Kind: ") + dwarf::GDBIndexEntryKindString(Desc.Kind) + ", " +
|
2013-09-20 07:01:29 +08:00
|
|
|
dwarf::GDBIndexEntryLinkageString(Desc.Linkage));
|
2013-09-20 06:19:37 +08:00
|
|
|
Asm->EmitInt8(Desc.toBits());
|
2013-09-13 08:35:05 +08:00
|
|
|
}
|
|
|
|
|
2013-12-05 05:51:05 +08:00
|
|
|
Asm->OutStreamer.AddComment("External Name");
|
2013-09-13 08:34:58 +08:00
|
|
|
|
2011-11-10 02:16:11 +08:00
|
|
|
// Emit the name with a terminating null byte.
|
2013-09-13 08:34:58 +08:00
|
|
|
Asm->OutStreamer.EmitBytes(StringRef(Name, GI->getKeyLength() + 1));
|
2010-05-11 06:49:55 +08:00
|
|
|
}
|
2010-07-22 05:21:52 +08:00
|
|
|
|
2010-05-11 06:49:55 +08:00
|
|
|
Asm->OutStreamer.AddComment("End Mark");
|
2010-07-22 05:21:52 +08:00
|
|
|
Asm->EmitInt32(0);
|
2013-12-05 01:55:41 +08:00
|
|
|
Asm->OutStreamer.EmitLabel(EndLabel);
|
2009-11-24 09:14:22 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-12-27 10:14:01 +08:00
|
|
|
// Emit strings into a string section.
|
2013-12-06 02:06:10 +08:00
|
|
|
void DwarfFile::emitStrings(const MCSection *StrSection,
|
2013-12-10 07:32:48 +08:00
|
|
|
const MCSection *OffsetSection = NULL,
|
|
|
|
const MCSymbol *StrSecSym = NULL) {
|
2012-12-27 10:14:01 +08:00
|
|
|
|
2013-11-19 17:04:36 +08:00
|
|
|
if (StringPool.empty())
|
|
|
|
return;
|
2010-07-22 05:21:52 +08:00
|
|
|
|
2010-03-10 07:38:23 +08:00
|
|
|
// Start the dwarf str section.
|
2013-01-08 03:32:41 +08:00
|
|
|
Asm->OutStreamer.SwitchSection(StrSection);
|
2009-05-15 17:23:25 +08:00
|
|
|
|
2010-03-13 10:17:42 +08:00
|
|
|
// Get all of the string pool entries and put them in an array by their ID so
|
|
|
|
// we can sort them.
|
2013-11-19 17:04:36 +08:00
|
|
|
SmallVector<
|
|
|
|
std::pair<unsigned, StringMapEntry<std::pair<MCSymbol *, unsigned> > *>,
|
|
|
|
64> Entries;
|
2010-07-22 05:21:52 +08:00
|
|
|
|
2013-11-19 17:04:36 +08:00
|
|
|
for (StringMap<std::pair<MCSymbol *, unsigned> >::iterator
|
|
|
|
I = StringPool.begin(),
|
|
|
|
E = StringPool.end();
|
2012-12-21 05:58:40 +08:00
|
|
|
I != E; ++I)
|
2010-03-13 10:17:42 +08:00
|
|
|
Entries.push_back(std::make_pair(I->second.second, &*I));
|
2010-07-22 05:21:52 +08:00
|
|
|
|
2010-03-13 10:17:42 +08:00
|
|
|
array_pod_sort(Entries.begin(), Entries.end());
|
2010-07-22 05:21:52 +08:00
|
|
|
|
2010-03-13 10:17:42 +08:00
|
|
|
for (unsigned i = 0, e = Entries.size(); i != e; ++i) {
|
2010-03-10 07:38:23 +08:00
|
|
|
// Emit a label for reference from debug information entries.
|
2010-03-13 10:17:42 +08:00
|
|
|
Asm->OutStreamer.EmitLabel(Entries[i].second->getValue().first);
|
2010-07-22 05:21:52 +08:00
|
|
|
|
2011-11-10 02:16:11 +08:00
|
|
|
// Emit the string itself with a terminating null byte.
|
2013-11-19 17:04:36 +08:00
|
|
|
Asm->OutStreamer.EmitBytes(
|
|
|
|
StringRef(Entries[i].second->getKeyData(),
|
|
|
|
Entries[i].second->getKeyLength() + 1));
|
2009-05-21 07:21:38 +08:00
|
|
|
}
|
2013-01-08 03:32:41 +08:00
|
|
|
|
|
|
|
// If we've got an offset section go ahead and emit that now as well.
|
|
|
|
if (OffsetSection) {
|
|
|
|
Asm->OutStreamer.SwitchSection(OffsetSection);
|
|
|
|
unsigned offset = 0;
|
2013-01-16 07:56:56 +08:00
|
|
|
unsigned size = 4; // FIXME: DWARF64 is 8.
|
2013-01-08 03:32:41 +08:00
|
|
|
for (unsigned i = 0, e = Entries.size(); i != e; ++i) {
|
2013-01-09 11:52:05 +08:00
|
|
|
Asm->OutStreamer.EmitIntValue(offset, size);
|
2013-01-08 03:32:41 +08:00
|
|
|
offset += Entries[i].second->getKeyLength() + 1;
|
|
|
|
}
|
|
|
|
}
|
2009-05-21 07:21:38 +08:00
|
|
|
}
|
2009-05-15 17:23:25 +08:00
|
|
|
|
2013-11-19 17:11:26 +08:00
|
|
|
// Emit addresses into the section given.
|
2013-12-06 02:06:10 +08:00
|
|
|
void DwarfFile::emitAddresses(const MCSection *AddrSection) {
|
2013-01-16 07:56:56 +08:00
|
|
|
|
2013-11-19 17:04:36 +08:00
|
|
|
if (AddressPool.empty())
|
|
|
|
return;
|
2013-01-16 07:56:56 +08:00
|
|
|
|
|
|
|
// Start the dwarf addr section.
|
|
|
|
Asm->OutStreamer.SwitchSection(AddrSection);
|
|
|
|
|
2013-07-09 01:51:28 +08:00
|
|
|
// Order the address pool entries by ID
|
2013-07-09 01:33:10 +08:00
|
|
|
SmallVector<const MCExpr *, 64> Entries(AddressPool.size());
|
2013-01-16 07:56:56 +08:00
|
|
|
|
2013-07-09 01:51:28 +08:00
|
|
|
for (DenseMap<const MCExpr *, unsigned>::iterator I = AddressPool.begin(),
|
|
|
|
E = AddressPool.end();
|
2013-01-16 07:56:56 +08:00
|
|
|
I != E; ++I)
|
2013-07-09 01:33:10 +08:00
|
|
|
Entries[I->second] = I->first;
|
2013-01-16 07:56:56 +08:00
|
|
|
|
|
|
|
for (unsigned i = 0, e = Entries.size(); i != e; ++i) {
|
2013-07-03 02:46:46 +08:00
|
|
|
// Emit an expression for reference from debug information entries.
|
2013-07-09 01:33:10 +08:00
|
|
|
if (const MCExpr *Expr = Entries[i])
|
2013-07-03 02:46:46 +08:00
|
|
|
Asm->OutStreamer.EmitValue(Expr, Asm->getDataLayout().getPointerSize());
|
2013-01-16 07:56:56 +08:00
|
|
|
else
|
|
|
|
Asm->OutStreamer.EmitIntValue(0, Asm->getDataLayout().getPointerSize());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-12-27 10:14:01 +08:00
|
|
|
// Emit visible names into a debug str section.
|
|
|
|
void DwarfDebug::emitDebugStr() {
|
2013-12-06 02:06:10 +08:00
|
|
|
DwarfFile &Holder = useSplitDwarf() ? SkeletonHolder : InfoHolder;
|
2012-12-27 10:14:01 +08:00
|
|
|
Holder.emitStrings(Asm->getObjFileLowering().getDwarfStrSection());
|
|
|
|
}
|
|
|
|
|
2013-07-03 05:36:07 +08:00
|
|
|
// Emit locations into the debug loc section.
|
2009-11-21 10:48:08 +08:00
|
|
|
void DwarfDebug::emitDebugLoc() {
|
2010-05-27 07:55:23 +08:00
|
|
|
if (DotDebugLocEntries.empty())
|
|
|
|
return;
|
|
|
|
|
2013-03-30 07:34:06 +08:00
|
|
|
for (SmallVectorImpl<DotDebugLocEntry>::iterator
|
2013-11-19 17:04:36 +08:00
|
|
|
I = DotDebugLocEntries.begin(),
|
|
|
|
E = DotDebugLocEntries.end();
|
2011-02-05 06:57:18 +08:00
|
|
|
I != E; ++I) {
|
|
|
|
DotDebugLocEntry &Entry = *I;
|
|
|
|
if (I + 1 != DotDebugLocEntries.end())
|
2013-11-19 17:04:36 +08:00
|
|
|
Entry.Merge(I + 1);
|
2011-02-05 06:57:18 +08:00
|
|
|
}
|
|
|
|
|
2011-03-17 06:16:39 +08:00
|
|
|
// Start the dwarf loc section.
|
2009-08-19 13:49:37 +08:00
|
|
|
Asm->OutStreamer.SwitchSection(
|
2013-11-19 17:04:36 +08:00
|
|
|
Asm->getObjFileLowering().getDwarfLocSection());
|
Revert the majority of the next patch in the address space series:
r165941: Resubmit the changes to llvm core to update the functions to
support different pointer sizes on a per address space basis.
Despite this commit log, this change primarily changed stuff outside of
VMCore, and those changes do not carry any tests for correctness (or
even plausibility), and we have consistently found questionable or flat
out incorrect cases in these changes. Most of them are probably correct,
but we need to devise a system that makes it more clear when we have
handled the address space concerns correctly, and ideally each pass that
gets updated would receive an accompanying test case that exercises that
pass specificaly w.r.t. alternate address spaces.
However, from this commit, I have retained the new C API entry points.
Those were an orthogonal change that probably should have been split
apart, but they seem entirely good.
In several places the changes were very obvious cleanups with no actual
multiple address space code added; these I have not reverted when
I spotted them.
In a few other places there were merge conflicts due to a cleaner
solution being implemented later, often not using address spaces at all.
In those cases, I've preserved the new code which isn't address space
dependent.
This is part of my ongoing effort to clean out the partial address space
code which carries high risk and low test coverage, and not likely to be
finished before the 3.2 release looms closer. Duncan and I would both
like to see the above issues addressed before we return to these
changes.
llvm-svn: 167222
2012-11-01 17:14:31 +08:00
|
|
|
unsigned char Size = Asm->getDataLayout().getPointerSize();
|
2010-05-27 07:55:23 +08:00
|
|
|
Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("debug_loc", 0));
|
|
|
|
unsigned index = 1;
|
2013-03-30 07:34:06 +08:00
|
|
|
for (SmallVectorImpl<DotDebugLocEntry>::iterator
|
2013-11-19 17:04:36 +08:00
|
|
|
I = DotDebugLocEntries.begin(),
|
|
|
|
E = DotDebugLocEntries.end();
|
2010-07-08 04:12:52 +08:00
|
|
|
I != E; ++I, ++index) {
|
2011-02-05 06:57:18 +08:00
|
|
|
DotDebugLocEntry &Entry = *I;
|
2013-11-19 17:04:36 +08:00
|
|
|
if (Entry.isMerged())
|
|
|
|
continue;
|
2010-05-26 07:40:22 +08:00
|
|
|
if (Entry.isEmpty()) {
|
2013-01-09 09:35:34 +08:00
|
|
|
Asm->OutStreamer.EmitIntValue(0, Size);
|
|
|
|
Asm->OutStreamer.EmitIntValue(0, Size);
|
2010-05-27 07:55:23 +08:00
|
|
|
Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("debug_loc", index));
|
2010-05-26 07:40:22 +08:00
|
|
|
} else {
|
2013-07-04 06:40:18 +08:00
|
|
|
Asm->OutStreamer.EmitSymbolValue(Entry.getBeginSym(), Size);
|
|
|
|
Asm->OutStreamer.EmitSymbolValue(Entry.getEndSym(), Size);
|
|
|
|
DIVariable DV(Entry.getVariable());
|
2011-05-28 06:05:41 +08:00
|
|
|
Asm->OutStreamer.AddComment("Loc expr size");
|
|
|
|
MCSymbol *begin = Asm->OutStreamer.getContext().CreateTempSymbol();
|
|
|
|
MCSymbol *end = Asm->OutStreamer.getContext().CreateTempSymbol();
|
|
|
|
Asm->EmitLabelDifference(end, begin, 2);
|
|
|
|
Asm->OutStreamer.EmitLabel(begin);
|
2011-07-09 00:49:43 +08:00
|
|
|
if (Entry.isInt()) {
|
2011-06-02 06:03:25 +08:00
|
|
|
DIBasicType BTy(DV.getType());
|
2013-11-19 17:04:36 +08:00
|
|
|
if (BTy.Verify() && (BTy.getEncoding() == dwarf::DW_ATE_signed ||
|
|
|
|
BTy.getEncoding() == dwarf::DW_ATE_signed_char)) {
|
2011-06-02 06:03:25 +08:00
|
|
|
Asm->OutStreamer.AddComment("DW_OP_consts");
|
|
|
|
Asm->EmitInt8(dwarf::DW_OP_consts);
|
2011-07-09 00:49:43 +08:00
|
|
|
Asm->EmitSLEB128(Entry.getInt());
|
2011-06-02 06:03:25 +08:00
|
|
|
} else {
|
|
|
|
Asm->OutStreamer.AddComment("DW_OP_constu");
|
|
|
|
Asm->EmitInt8(dwarf::DW_OP_constu);
|
2011-07-09 00:49:43 +08:00
|
|
|
Asm->EmitULEB128(Entry.getInt());
|
2011-06-02 06:03:25 +08:00
|
|
|
}
|
2011-07-09 00:49:43 +08:00
|
|
|
} else if (Entry.isLocation()) {
|
2013-07-04 06:40:21 +08:00
|
|
|
MachineLocation Loc = Entry.getLoc();
|
2012-11-20 06:42:10 +08:00
|
|
|
if (!DV.hasComplexAddress())
|
2011-07-09 00:49:43 +08:00
|
|
|
// Regular entry.
|
2013-07-04 06:40:21 +08:00
|
|
|
Asm->EmitDwarfRegOp(Loc, DV.isIndirect());
|
2011-07-09 00:49:43 +08:00
|
|
|
else {
|
|
|
|
// Complex address entry.
|
|
|
|
unsigned N = DV.getNumAddrElements();
|
|
|
|
unsigned i = 0;
|
|
|
|
if (N >= 2 && DV.getAddrElement(0) == DIBuilder::OpPlus) {
|
2013-07-04 06:40:21 +08:00
|
|
|
if (Loc.getOffset()) {
|
2011-07-09 00:49:43 +08:00
|
|
|
i = 2;
|
2013-07-04 06:40:21 +08:00
|
|
|
Asm->EmitDwarfRegOp(Loc, DV.isIndirect());
|
2011-07-09 00:49:43 +08:00
|
|
|
Asm->OutStreamer.AddComment("DW_OP_deref");
|
|
|
|
Asm->EmitInt8(dwarf::DW_OP_deref);
|
|
|
|
Asm->OutStreamer.AddComment("DW_OP_plus_uconst");
|
|
|
|
Asm->EmitInt8(dwarf::DW_OP_plus_uconst);
|
|
|
|
Asm->EmitSLEB128(DV.getAddrElement(1));
|
|
|
|
} else {
|
|
|
|
// If first address element is OpPlus then emit
|
|
|
|
// DW_OP_breg + Offset instead of DW_OP_reg + Offset.
|
2013-07-04 06:40:21 +08:00
|
|
|
MachineLocation TLoc(Loc.getReg(), DV.getAddrElement(1));
|
|
|
|
Asm->EmitDwarfRegOp(TLoc, DV.isIndirect());
|
2011-07-09 00:49:43 +08:00
|
|
|
i = 2;
|
|
|
|
}
|
2011-05-24 08:22:25 +08:00
|
|
|
} else {
|
2013-07-04 06:40:21 +08:00
|
|
|
Asm->EmitDwarfRegOp(Loc, DV.isIndirect());
|
2011-07-09 00:49:43 +08:00
|
|
|
}
|
2012-11-20 06:42:10 +08:00
|
|
|
|
2011-07-09 00:49:43 +08:00
|
|
|
// Emit remaining complex address elements.
|
|
|
|
for (; i < N; ++i) {
|
|
|
|
uint64_t Element = DV.getAddrElement(i);
|
|
|
|
if (Element == DIBuilder::OpPlus) {
|
|
|
|
Asm->EmitInt8(dwarf::DW_OP_plus_uconst);
|
|
|
|
Asm->EmitULEB128(DV.getAddrElement(++i));
|
2012-05-09 02:56:00 +08:00
|
|
|
} else if (Element == DIBuilder::OpDeref) {
|
2013-07-04 06:40:21 +08:00
|
|
|
if (!Loc.isReg())
|
2012-05-09 02:56:00 +08:00
|
|
|
Asm->EmitInt8(dwarf::DW_OP_deref);
|
|
|
|
} else
|
|
|
|
llvm_unreachable("unknown Opcode found in complex address");
|
2011-05-24 08:22:25 +08:00
|
|
|
}
|
2011-04-28 10:22:40 +08:00
|
|
|
}
|
|
|
|
}
|
2011-07-09 00:49:43 +08:00
|
|
|
// else ... ignore constant fp. There is not any good way to
|
|
|
|
// to represent them here in dwarf.
|
2011-05-28 06:05:41 +08:00
|
|
|
Asm->OutStreamer.EmitLabel(end);
|
2010-05-26 07:40:22 +08:00
|
|
|
}
|
|
|
|
}
|
2009-05-21 07:21:38 +08:00
|
|
|
}
|
2009-05-15 17:23:25 +08:00
|
|
|
|
2013-09-20 07:21:01 +08:00
|
|
|
struct SymbolCUSorter {
|
|
|
|
SymbolCUSorter(const MCStreamer &s) : Streamer(s) {}
|
|
|
|
const MCStreamer &Streamer;
|
|
|
|
|
2013-11-19 17:04:36 +08:00
|
|
|
bool operator()(const SymbolCU &A, const SymbolCU &B) {
|
2013-09-20 07:21:01 +08:00
|
|
|
unsigned IA = A.Sym ? Streamer.GetSymbolOrder(A.Sym) : 0;
|
|
|
|
unsigned IB = B.Sym ? Streamer.GetSymbolOrder(B.Sym) : 0;
|
|
|
|
|
|
|
|
// Symbols with no order assigned should be placed at the end.
|
|
|
|
// (e.g. section end labels)
|
|
|
|
if (IA == 0)
|
|
|
|
IA = (unsigned)(-1);
|
|
|
|
if (IB == 0)
|
|
|
|
IB = (unsigned)(-1);
|
|
|
|
return IA < IB;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2013-12-10 07:32:48 +08:00
|
|
|
static bool CUSort(const DwarfUnit *A, const DwarfUnit *B) {
|
2013-11-19 17:04:36 +08:00
|
|
|
return (A->getUniqueID() < B->getUniqueID());
|
2013-09-20 07:21:01 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
struct ArangeSpan {
|
|
|
|
const MCSymbol *Start, *End;
|
|
|
|
};
|
|
|
|
|
|
|
|
// Emit a debug aranges section, containing a CU lookup for any
|
|
|
|
// address we can tie back to a CU.
|
2012-11-21 08:34:35 +08:00
|
|
|
void DwarfDebug::emitDebugARanges() {
|
2009-05-21 07:21:38 +08:00
|
|
|
// Start the dwarf aranges section.
|
2013-11-19 17:04:36 +08:00
|
|
|
Asm->OutStreamer.SwitchSection(
|
|
|
|
Asm->getObjFileLowering().getDwarfARangesSection());
|
2013-09-20 07:21:01 +08:00
|
|
|
|
2013-12-10 07:57:44 +08:00
|
|
|
typedef DenseMap<DwarfCompileUnit *, std::vector<ArangeSpan> > SpansType;
|
2013-09-20 07:21:01 +08:00
|
|
|
|
|
|
|
SpansType Spans;
|
|
|
|
|
|
|
|
// Build a list of sections used.
|
|
|
|
std::vector<const MCSection *> Sections;
|
|
|
|
for (SectionMapType::iterator it = SectionMap.begin(); it != SectionMap.end();
|
|
|
|
it++) {
|
|
|
|
const MCSection *Section = it->first;
|
|
|
|
Sections.push_back(Section);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Sort the sections into order.
|
|
|
|
// This is only done to ensure consistent output order across different runs.
|
|
|
|
std::sort(Sections.begin(), Sections.end(), SectionSort);
|
|
|
|
|
|
|
|
// Build a set of address spans, sorted by CU.
|
2013-11-19 17:04:36 +08:00
|
|
|
for (size_t SecIdx = 0; SecIdx < Sections.size(); SecIdx++) {
|
2013-09-20 07:21:01 +08:00
|
|
|
const MCSection *Section = Sections[SecIdx];
|
|
|
|
SmallVector<SymbolCU, 8> &List = SectionMap[Section];
|
|
|
|
if (List.size() < 2)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
// Sort the symbols by offset within the section.
|
|
|
|
SymbolCUSorter sorter(Asm->OutStreamer);
|
|
|
|
std::sort(List.begin(), List.end(), sorter);
|
|
|
|
|
|
|
|
// If we have no section (e.g. common), just write out
|
|
|
|
// individual spans for each symbol.
|
|
|
|
if (Section == NULL) {
|
|
|
|
for (size_t n = 0; n < List.size(); n++) {
|
|
|
|
const SymbolCU &Cur = List[n];
|
|
|
|
|
|
|
|
ArangeSpan Span;
|
|
|
|
Span.Start = Cur.Sym;
|
|
|
|
Span.End = NULL;
|
|
|
|
if (Cur.CU)
|
|
|
|
Spans[Cur.CU].push_back(Span);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// Build spans between each label.
|
|
|
|
const MCSymbol *StartSym = List[0].Sym;
|
|
|
|
for (size_t n = 1; n < List.size(); n++) {
|
|
|
|
const SymbolCU &Prev = List[n - 1];
|
|
|
|
const SymbolCU &Cur = List[n];
|
|
|
|
|
|
|
|
// Try and build the longest span we can within the same CU.
|
|
|
|
if (Cur.CU != Prev.CU) {
|
|
|
|
ArangeSpan Span;
|
|
|
|
Span.Start = StartSym;
|
|
|
|
Span.End = Cur.Sym;
|
|
|
|
Spans[Prev.CU].push_back(Span);
|
|
|
|
StartSym = Cur.Sym;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned PtrSize = Asm->getDataLayout().getPointerSize();
|
|
|
|
|
|
|
|
// Build a list of CUs used.
|
2013-12-10 07:57:44 +08:00
|
|
|
std::vector<DwarfCompileUnit *> CUs;
|
2013-09-20 07:21:01 +08:00
|
|
|
for (SpansType::iterator it = Spans.begin(); it != Spans.end(); it++) {
|
2013-12-10 07:57:44 +08:00
|
|
|
DwarfCompileUnit *CU = it->first;
|
2013-09-20 07:21:01 +08:00
|
|
|
CUs.push_back(CU);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Sort the CU list (again, to ensure consistent output order).
|
|
|
|
std::sort(CUs.begin(), CUs.end(), CUSort);
|
|
|
|
|
|
|
|
// Emit an arange table for each CU we used.
|
2013-11-19 17:04:36 +08:00
|
|
|
for (size_t CUIdx = 0; CUIdx < CUs.size(); CUIdx++) {
|
2013-12-10 07:57:44 +08:00
|
|
|
DwarfCompileUnit *CU = CUs[CUIdx];
|
2013-09-20 07:21:01 +08:00
|
|
|
std::vector<ArangeSpan> &List = Spans[CU];
|
|
|
|
|
|
|
|
// Emit size of content not including length itself.
|
2013-11-19 17:04:36 +08:00
|
|
|
unsigned ContentSize =
|
|
|
|
sizeof(int16_t) + // DWARF ARange version number
|
|
|
|
sizeof(int32_t) + // Offset of CU in the .debug_info section
|
|
|
|
sizeof(int8_t) + // Pointer Size (in bytes)
|
|
|
|
sizeof(int8_t); // Segment Size (in bytes)
|
2013-09-20 07:21:01 +08:00
|
|
|
|
|
|
|
unsigned TupleSize = PtrSize * 2;
|
|
|
|
|
|
|
|
// 7.20 in the Dwarf specs requires the table to be aligned to a tuple.
|
|
|
|
unsigned Padding = 0;
|
|
|
|
while (((sizeof(int32_t) + ContentSize + Padding) % TupleSize) != 0)
|
|
|
|
Padding++;
|
|
|
|
|
|
|
|
ContentSize += Padding;
|
|
|
|
ContentSize += (List.size() + 1) * TupleSize;
|
|
|
|
|
|
|
|
// For each compile unit, write the list of spans it covers.
|
|
|
|
Asm->OutStreamer.AddComment("Length of ARange Set");
|
|
|
|
Asm->EmitInt32(ContentSize);
|
|
|
|
Asm->OutStreamer.AddComment("DWARF Arange version number");
|
|
|
|
Asm->EmitInt16(dwarf::DW_ARANGES_VERSION);
|
|
|
|
Asm->OutStreamer.AddComment("Offset Into Debug Info Section");
|
2013-12-31 01:22:27 +08:00
|
|
|
Asm->EmitSectionOffset(CU->getLocalLabelBegin(), CU->getLocalSectionSym());
|
2013-09-20 07:21:01 +08:00
|
|
|
Asm->OutStreamer.AddComment("Address Size (in bytes)");
|
|
|
|
Asm->EmitInt8(PtrSize);
|
|
|
|
Asm->OutStreamer.AddComment("Segment Size (in bytes)");
|
|
|
|
Asm->EmitInt8(0);
|
|
|
|
|
|
|
|
for (unsigned n = 0; n < Padding; n++)
|
|
|
|
Asm->EmitInt8(0xff);
|
|
|
|
|
|
|
|
for (unsigned n = 0; n < List.size(); n++) {
|
|
|
|
const ArangeSpan &Span = List[n];
|
|
|
|
Asm->EmitLabelReference(Span.Start, PtrSize);
|
|
|
|
|
|
|
|
// Calculate the size as being from the span start to it's end.
|
2013-09-24 01:56:20 +08:00
|
|
|
if (Span.End) {
|
2013-09-20 07:21:01 +08:00
|
|
|
Asm->EmitLabelDifference(Span.End, Span.Start, PtrSize);
|
2013-09-24 01:56:20 +08:00
|
|
|
} else {
|
|
|
|
// For symbols without an end marker (e.g. common), we
|
|
|
|
// write a single arange entry containing just that one symbol.
|
|
|
|
uint64_t Size = SymSize[Span.Start];
|
|
|
|
if (Size == 0)
|
|
|
|
Size = 1;
|
|
|
|
|
|
|
|
Asm->OutStreamer.EmitIntValue(Size, PtrSize);
|
|
|
|
}
|
2013-09-20 07:21:01 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
Asm->OutStreamer.AddComment("ARange terminator");
|
|
|
|
Asm->OutStreamer.EmitIntValue(0, PtrSize);
|
|
|
|
Asm->OutStreamer.EmitIntValue(0, PtrSize);
|
|
|
|
}
|
2009-05-21 07:04:56 +08:00
|
|
|
}
|
|
|
|
|
2012-11-28 06:43:45 +08:00
|
|
|
// Emit visible names into a debug ranges section.
|
2009-11-21 10:48:08 +08:00
|
|
|
void DwarfDebug::emitDebugRanges() {
|
2009-05-21 07:21:38 +08:00
|
|
|
// Start the dwarf ranges section.
|
2013-11-19 17:04:36 +08:00
|
|
|
Asm->OutStreamer.SwitchSection(
|
|
|
|
Asm->getObjFileLowering().getDwarfRangesSection());
|
2013-12-03 08:45:45 +08:00
|
|
|
|
|
|
|
// Size for our labels.
|
Revert the majority of the next patch in the address space series:
r165941: Resubmit the changes to llvm core to update the functions to
support different pointer sizes on a per address space basis.
Despite this commit log, this change primarily changed stuff outside of
VMCore, and those changes do not carry any tests for correctness (or
even plausibility), and we have consistently found questionable or flat
out incorrect cases in these changes. Most of them are probably correct,
but we need to devise a system that makes it more clear when we have
handled the address space concerns correctly, and ideally each pass that
gets updated would receive an accompanying test case that exercises that
pass specificaly w.r.t. alternate address spaces.
However, from this commit, I have retained the new C API entry points.
Those were an orthogonal change that probably should have been split
apart, but they seem entirely good.
In several places the changes were very obvious cleanups with no actual
multiple address space code added; these I have not reverted when
I spotted them.
In a few other places there were merge conflicts due to a cleaner
solution being implemented later, often not using address spaces at all.
In those cases, I've preserved the new code which isn't address space
dependent.
This is part of my ongoing effort to clean out the partial address space
code which carries high risk and low test coverage, and not likely to be
finished before the 3.2 release looms closer. Duncan and I would both
like to see the above issues addressed before we return to these
changes.
llvm-svn: 167222
2012-11-01 17:14:31 +08:00
|
|
|
unsigned char Size = Asm->getDataLayout().getPointerSize();
|
2013-12-03 08:45:45 +08:00
|
|
|
|
|
|
|
// Grab the specific ranges for the compile units in the module.
|
2013-12-10 07:57:44 +08:00
|
|
|
for (DenseMap<const MDNode *, DwarfCompileUnit *>::iterator I = CUMap.begin(),
|
|
|
|
E = CUMap.end();
|
2013-12-03 08:45:45 +08:00
|
|
|
I != E; ++I) {
|
2013-12-10 07:57:44 +08:00
|
|
|
DwarfCompileUnit *TheCU = I->second;
|
2013-12-03 08:45:45 +08:00
|
|
|
|
|
|
|
// Emit a symbol so we can find the beginning of our ranges.
|
2013-12-10 01:51:30 +08:00
|
|
|
Asm->OutStreamer.EmitLabel(TheCU->getLabelRange());
|
2013-12-03 08:45:45 +08:00
|
|
|
|
|
|
|
// Iterate over the misc ranges for the compile units in the module.
|
2013-12-05 03:06:58 +08:00
|
|
|
const SmallVectorImpl<RangeSpanList> &RangeLists = TheCU->getRangeLists();
|
2013-12-10 07:32:48 +08:00
|
|
|
for (SmallVectorImpl<RangeSpanList>::const_iterator I = RangeLists.begin(),
|
|
|
|
E = RangeLists.end();
|
2013-12-03 08:45:45 +08:00
|
|
|
I != E; ++I) {
|
2013-12-05 03:06:58 +08:00
|
|
|
const RangeSpanList &List = *I;
|
2013-12-03 08:45:45 +08:00
|
|
|
|
2013-12-05 06:04:50 +08:00
|
|
|
// Emit our symbol so we can find the beginning of the range.
|
|
|
|
Asm->OutStreamer.EmitLabel(List.getSym());
|
2013-12-03 08:45:45 +08:00
|
|
|
|
|
|
|
for (SmallVectorImpl<RangeSpan>::const_iterator
|
2013-12-05 03:06:58 +08:00
|
|
|
RI = List.getRanges().begin(),
|
|
|
|
RE = List.getRanges().end();
|
|
|
|
RI != RE; ++RI) {
|
|
|
|
const RangeSpan &Range = *RI;
|
2013-12-03 08:45:45 +08:00
|
|
|
const MCSymbol *Begin = Range.getStart();
|
|
|
|
const MCSymbol *End = Range.getEnd();
|
2013-12-20 12:34:22 +08:00
|
|
|
assert(Begin && "Range without a begin symbol?");
|
|
|
|
assert(End && "Range without an end symbol?");
|
|
|
|
Asm->OutStreamer.EmitSymbolValue(Begin, Size);
|
|
|
|
Asm->OutStreamer.EmitSymbolValue(End, Size);
|
2013-12-03 08:45:45 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// And terminate the list with two 0 values.
|
|
|
|
Asm->OutStreamer.EmitIntValue(0, Size);
|
2013-01-09 09:35:34 +08:00
|
|
|
Asm->OutStreamer.EmitIntValue(0, Size);
|
2013-12-03 08:45:45 +08:00
|
|
|
}
|
2013-12-20 12:16:18 +08:00
|
|
|
|
|
|
|
// Now emit a range for the CU itself.
|
|
|
|
if (DwarfCURanges) {
|
|
|
|
Asm->OutStreamer.EmitLabel(
|
|
|
|
Asm->GetTempSymbol("cu_ranges", TheCU->getUniqueID()));
|
|
|
|
const SmallVectorImpl<RangeSpan> &Ranges = TheCU->getRanges();
|
|
|
|
for (uint32_t i = 0, e = Ranges.size(); i != e; ++i) {
|
|
|
|
RangeSpan Range = Ranges[i];
|
|
|
|
const MCSymbol *Begin = Range.getStart();
|
|
|
|
const MCSymbol *End = Range.getEnd();
|
2013-12-20 12:34:22 +08:00
|
|
|
assert(Begin && "Range without a begin symbol?");
|
|
|
|
assert(End && "Range without an end symbol?");
|
|
|
|
Asm->OutStreamer.EmitSymbolValue(Begin, Size);
|
|
|
|
Asm->OutStreamer.EmitSymbolValue(End, Size);
|
2013-12-20 12:16:18 +08:00
|
|
|
}
|
|
|
|
// And terminate the list with two 0 values.
|
|
|
|
Asm->OutStreamer.EmitIntValue(0, Size);
|
|
|
|
Asm->OutStreamer.EmitIntValue(0, Size);
|
|
|
|
}
|
2010-04-17 07:33:45 +08:00
|
|
|
}
|
2009-05-21 07:21:38 +08:00
|
|
|
}
|
|
|
|
|
2012-12-12 03:42:09 +08:00
|
|
|
// DWARF5 Experimental Separate Dwarf emitters.
|
2012-12-01 07:59:06 +08:00
|
|
|
|
|
|
|
// This DIE has the following attributes: DW_AT_comp_dir, DW_AT_stmt_list,
|
|
|
|
// DW_AT_low_pc, DW_AT_high_pc, DW_AT_ranges, DW_AT_dwo_name, DW_AT_dwo_id,
|
2013-10-01 08:43:36 +08:00
|
|
|
// DW_AT_ranges_base, DW_AT_addr_base.
|
2013-12-10 08:40:03 +08:00
|
|
|
// TODO: Implement DW_AT_ranges_base.
|
2013-12-10 07:57:44 +08:00
|
|
|
DwarfCompileUnit *DwarfDebug::constructSkeletonCU(const DwarfCompileUnit *CU) {
|
2012-12-01 07:59:06 +08:00
|
|
|
|
|
|
|
DIE *Die = new DIE(dwarf::DW_TAG_compile_unit);
|
2013-12-10 07:57:44 +08:00
|
|
|
DwarfCompileUnit *NewCU = new DwarfCompileUnit(
|
|
|
|
CU->getUniqueID(), Die, CU->getNode(), Asm, this, &SkeletonHolder);
|
2013-12-10 01:51:30 +08:00
|
|
|
NewCU->initSection(Asm->getObjFileLowering().getDwarfInfoSection(),
|
|
|
|
DwarfInfoSectionSym);
|
2013-01-17 11:00:04 +08:00
|
|
|
|
2013-02-23 07:50:08 +08:00
|
|
|
NewCU->addLocalString(Die, dwarf::DW_AT_GNU_dwo_name,
|
2013-11-16 07:54:45 +08:00
|
|
|
CU->getNode().getSplitDebugFilename());
|
2012-12-01 07:59:06 +08:00
|
|
|
|
2013-04-22 15:51:08 +08:00
|
|
|
// Relocate to the beginning of the addr_base section, else 0 for the
|
|
|
|
// beginning of the one for this compile unit.
|
2013-04-07 11:43:09 +08:00
|
|
|
if (Asm->MAI->doesDwarfUseRelocationsAcrossSections())
|
2013-11-22 07:46:41 +08:00
|
|
|
NewCU->addSectionLabel(Die, dwarf::DW_AT_GNU_addr_base,
|
|
|
|
DwarfAddrSectionSym);
|
2013-04-07 11:43:09 +08:00
|
|
|
else
|
2013-11-22 07:46:41 +08:00
|
|
|
NewCU->addSectionOffset(Die, dwarf::DW_AT_GNU_addr_base, 0);
|
2012-12-01 07:59:06 +08:00
|
|
|
|
|
|
|
// DW_AT_stmt_list is a offset of line number information for this
|
|
|
|
// compile unit in debug_line section.
|
2013-04-07 11:43:09 +08:00
|
|
|
// FIXME: Should handle multiple compile units.
|
2012-12-01 07:59:06 +08:00
|
|
|
if (Asm->MAI->doesDwarfUseRelocationsAcrossSections())
|
2013-12-10 07:32:48 +08:00
|
|
|
NewCU->addSectionLabel(Die, dwarf::DW_AT_stmt_list, DwarfLineSectionSym);
|
2012-12-01 07:59:06 +08:00
|
|
|
else
|
2013-11-22 07:46:41 +08:00
|
|
|
NewCU->addSectionOffset(Die, dwarf::DW_AT_stmt_list, 0);
|
2012-12-01 07:59:06 +08:00
|
|
|
|
|
|
|
if (!CompilationDir.empty())
|
2013-01-08 03:32:41 +08:00
|
|
|
NewCU->addLocalString(Die, dwarf::DW_AT_comp_dir, CompilationDir);
|
2012-12-01 07:59:06 +08:00
|
|
|
|
2013-12-05 05:31:26 +08:00
|
|
|
addGnuPubAttributes(NewCU, Die);
|
2013-09-13 08:35:05 +08:00
|
|
|
|
2012-12-11 07:34:43 +08:00
|
|
|
SkeletonHolder.addUnit(NewCU);
|
|
|
|
|
2012-12-01 07:59:06 +08:00
|
|
|
return NewCU;
|
|
|
|
}
|
|
|
|
|
2012-12-12 03:42:09 +08:00
|
|
|
// Emit the .debug_info.dwo section for separated dwarf. This contains the
|
|
|
|
// compile units that would normally be in debug_info.
|
2012-12-01 07:59:06 +08:00
|
|
|
void DwarfDebug::emitDebugInfoDWO() {
|
2012-12-11 03:51:21 +08:00
|
|
|
assert(useSplitDwarf() && "No split dwarf debug info?");
|
2013-12-07 06:14:48 +08:00
|
|
|
InfoHolder.emitUnits(this,
|
2012-12-20 06:02:53 +08:00
|
|
|
Asm->getObjFileLowering().getDwarfAbbrevDWOSection(),
|
|
|
|
DwarfAbbrevDWOSectionSym);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Emit the .debug_abbrev.dwo section for separated dwarf. This contains the
|
|
|
|
// abbreviations for the .debug_info.dwo section.
|
|
|
|
void DwarfDebug::emitDebugAbbrevDWO() {
|
|
|
|
assert(useSplitDwarf() && "No split dwarf?");
|
2013-12-05 15:43:55 +08:00
|
|
|
InfoHolder.emitAbbrevs(Asm->getObjFileLowering().getDwarfAbbrevDWOSection());
|
2012-12-01 07:59:06 +08:00
|
|
|
}
|
2012-12-27 10:14:01 +08:00
|
|
|
|
|
|
|
// Emit the .debug_str.dwo section for separated dwarf. This contains the
|
|
|
|
// string section and is identical in format to traditional .debug_str
|
|
|
|
// sections.
|
|
|
|
void DwarfDebug::emitDebugStrDWO() {
|
|
|
|
assert(useSplitDwarf() && "No split dwarf?");
|
2013-11-19 17:04:36 +08:00
|
|
|
const MCSection *OffSec =
|
|
|
|
Asm->getObjFileLowering().getDwarfStrOffDWOSection();
|
2013-01-08 03:32:41 +08:00
|
|
|
const MCSymbol *StrSym = DwarfStrSectionSym;
|
|
|
|
InfoHolder.emitStrings(Asm->getObjFileLowering().getDwarfStrDWOSection(),
|
|
|
|
OffSec, StrSym);
|
2012-12-27 10:14:01 +08:00
|
|
|
}
|
2013-11-20 07:08:21 +08:00
|
|
|
|
2014-01-04 02:59:42 +08:00
|
|
|
void DwarfDebug::addDwarfTypeUnitType(uint16_t Language, StringRef Identifier,
|
|
|
|
DIE *RefDie, DICompositeType CTy) {
|
2013-12-18 07:32:35 +08:00
|
|
|
const DwarfTypeUnit *&TU = DwarfTypeUnits[CTy];
|
|
|
|
if (!TU) {
|
2013-11-20 07:08:21 +08:00
|
|
|
DIE *UnitDie = new DIE(dwarf::DW_TAG_type_unit);
|
2013-12-10 07:57:44 +08:00
|
|
|
DwarfTypeUnit *NewTU =
|
|
|
|
new DwarfTypeUnit(InfoHolder.getUnits().size(), UnitDie, Language, Asm,
|
|
|
|
this, &InfoHolder);
|
2013-12-18 07:32:35 +08:00
|
|
|
TU = NewTU;
|
2013-12-07 03:38:46 +08:00
|
|
|
InfoHolder.addUnit(NewTU);
|
|
|
|
|
2013-12-03 03:33:10 +08:00
|
|
|
NewTU->addUInt(UnitDie, dwarf::DW_AT_language, dwarf::DW_FORM_data2,
|
2013-12-03 02:44:29 +08:00
|
|
|
Language);
|
2013-11-20 07:08:21 +08:00
|
|
|
|
2013-12-03 03:33:10 +08:00
|
|
|
DIE *Die = NewTU->createTypeDIE(CTy);
|
2013-11-20 07:08:21 +08:00
|
|
|
|
2014-01-04 02:59:42 +08:00
|
|
|
MD5 Hash;
|
|
|
|
Hash.update(Identifier);
|
|
|
|
// ... take the least significant 8 bytes and return those. Our MD5
|
|
|
|
// implementation always returns its results in little endian, swap bytes
|
|
|
|
// appropriately.
|
|
|
|
MD5::MD5Result Result;
|
|
|
|
Hash.final(Result);
|
|
|
|
uint64_t Signature = *reinterpret_cast<support::ulittle64_t *>(Result + 8);
|
2013-12-14 05:33:40 +08:00
|
|
|
NewTU->setTypeSignature(Signature);
|
|
|
|
NewTU->setType(Die);
|
2013-11-20 07:08:21 +08:00
|
|
|
|
2013-12-07 06:14:48 +08:00
|
|
|
NewTU->initSection(
|
2013-12-14 05:33:40 +08:00
|
|
|
useSplitDwarf()
|
|
|
|
? Asm->getObjFileLowering().getDwarfTypesDWOSection(Signature)
|
|
|
|
: Asm->getObjFileLowering().getDwarfTypesSection(Signature));
|
2013-11-20 07:08:21 +08:00
|
|
|
}
|
|
|
|
|
2013-12-18 07:32:35 +08:00
|
|
|
CUMap.begin()->second->addDIETypeSignature(RefDie, *TU);
|
2013-11-20 07:08:21 +08:00
|
|
|
}
|