2009-05-15 08:11:17 +08:00
|
|
|
//===--- lib/CodeGen/DIE.cpp - DWARF Info Entries -------------------------===//
|
|
|
|
//
|
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
|
|
|
// Data structures for DWARF info entries.
|
2013-01-08 06:40:45 +08:00
|
|
|
//
|
2009-05-15 08:11:17 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2015-01-06 05:29:41 +08:00
|
|
|
#include "llvm/CodeGen/DIE.h"
|
2014-10-04 23:49:50 +08:00
|
|
|
#include "DwarfCompileUnit.h"
|
2013-07-03 07:40:10 +08:00
|
|
|
#include "DwarfDebug.h"
|
2013-12-18 07:32:35 +08:00
|
|
|
#include "DwarfUnit.h"
|
2010-01-17 15:46:39 +08:00
|
|
|
#include "llvm/ADT/Twine.h"
|
2009-05-15 08:11:17 +08:00
|
|
|
#include "llvm/CodeGen/AsmPrinter.h"
|
2013-01-02 19:36:10 +08:00
|
|
|
#include "llvm/IR/DataLayout.h"
|
2009-08-23 04:48:53 +08:00
|
|
|
#include "llvm/MC/MCAsmInfo.h"
|
2014-10-21 08:25:49 +08:00
|
|
|
#include "llvm/MC/MCContext.h"
|
2010-01-20 15:41:15 +08:00
|
|
|
#include "llvm/MC/MCStreamer.h"
|
2010-01-17 02:50:28 +08:00
|
|
|
#include "llvm/MC/MCSymbol.h"
|
2009-12-24 08:27:55 +08:00
|
|
|
#include "llvm/Support/Debug.h"
|
2009-07-12 04:10:48 +08:00
|
|
|
#include "llvm/Support/ErrorHandling.h"
|
2009-08-23 09:01:17 +08:00
|
|
|
#include "llvm/Support/Format.h"
|
2010-01-23 06:09:00 +08:00
|
|
|
#include "llvm/Support/FormattedStream.h"
|
2014-02-22 22:00:39 +08:00
|
|
|
#include "llvm/Support/LEB128.h"
|
2013-07-27 01:02:41 +08:00
|
|
|
#include "llvm/Support/MD5.h"
|
2015-03-24 03:32:43 +08:00
|
|
|
#include "llvm/Support/raw_ostream.h"
|
2009-05-15 08:11:17 +08:00
|
|
|
using namespace llvm;
|
|
|
|
|
2017-04-21 03:16:51 +08:00
|
|
|
#define DEBUG_TYPE "dwarfdebug"
|
|
|
|
|
2009-05-15 08:11:17 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// DIEAbbrevData Implementation
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
/// Profile - Used to gather unique data for the abbreviation folding set.
|
|
|
|
///
|
|
|
|
void DIEAbbrevData::Profile(FoldingSetNodeID &ID) const {
|
2013-10-22 03:18:31 +08:00
|
|
|
// Explicitly cast to an integer type for which FoldingSetNodeID has
|
|
|
|
// overloads. Otherwise MSVC 2010 thinks this call is ambiguous.
|
|
|
|
ID.AddInteger(unsigned(Attribute));
|
|
|
|
ID.AddInteger(unsigned(Form));
|
2017-03-02 06:13:42 +08:00
|
|
|
if (Form == dwarf::DW_FORM_implicit_const)
|
|
|
|
ID.AddInteger(Value);
|
2009-05-15 08:11:17 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// DIEAbbrev Implementation
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
/// Profile - Used to gather unique data for the abbreviation folding set.
|
|
|
|
///
|
|
|
|
void DIEAbbrev::Profile(FoldingSetNodeID &ID) const {
|
2013-10-22 03:18:31 +08:00
|
|
|
ID.AddInteger(unsigned(Tag));
|
2014-03-05 09:44:58 +08:00
|
|
|
ID.AddInteger(unsigned(Children));
|
2009-05-15 08:11:17 +08:00
|
|
|
|
|
|
|
// For each attribute description.
|
|
|
|
for (unsigned i = 0, N = Data.size(); i < N; ++i)
|
|
|
|
Data[i].Profile(ID);
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Emit - Print the abbreviation using the specified asm printer.
|
|
|
|
///
|
2015-03-04 10:30:08 +08:00
|
|
|
void DIEAbbrev::Emit(const AsmPrinter *AP) const {
|
2009-05-15 08:11:17 +08:00
|
|
|
// Emit its Dwarf tag type.
|
2016-10-05 13:59:29 +08:00
|
|
|
AP->EmitULEB128(Tag, dwarf::TagString(Tag).data());
|
2009-05-15 08:11:17 +08:00
|
|
|
|
|
|
|
// Emit whether it has children DIEs.
|
2016-10-05 13:59:29 +08:00
|
|
|
AP->EmitULEB128((unsigned)Children, dwarf::ChildrenString(Children).data());
|
2009-05-15 08:11:17 +08:00
|
|
|
|
|
|
|
// For each attribute description.
|
|
|
|
for (unsigned i = 0, N = Data.size(); i < N; ++i) {
|
|
|
|
const DIEAbbrevData &AttrData = Data[i];
|
|
|
|
|
|
|
|
// Emit attribute type.
|
2010-04-05 08:13:49 +08:00
|
|
|
AP->EmitULEB128(AttrData.getAttribute(),
|
2016-10-05 13:59:29 +08:00
|
|
|
dwarf::AttributeString(AttrData.getAttribute()).data());
|
2009-05-15 08:11:17 +08:00
|
|
|
|
|
|
|
// Emit form type.
|
2017-04-21 03:16:51 +08:00
|
|
|
#ifndef NDEBUG
|
|
|
|
// Could be an assertion, but this way we can see the failing form code
|
|
|
|
// easily, which helps track down where it came from.
|
|
|
|
if (!dwarf::isValidFormForVersion(AttrData.getForm(),
|
|
|
|
AP->getDwarfVersion())) {
|
|
|
|
DEBUG(dbgs() << "Invalid form " << format("0x%x", AttrData.getForm())
|
|
|
|
<< " for DWARF version " << AP->getDwarfVersion() << "\n");
|
|
|
|
llvm_unreachable("Invalid form for specified DWARF version");
|
|
|
|
}
|
|
|
|
#endif
|
2010-04-05 08:13:49 +08:00
|
|
|
AP->EmitULEB128(AttrData.getForm(),
|
2016-10-05 13:59:29 +08:00
|
|
|
dwarf::FormEncodingString(AttrData.getForm()).data());
|
2017-01-11 05:18:26 +08:00
|
|
|
|
|
|
|
// Emit value for DW_FORM_implicit_const.
|
2017-04-21 03:16:51 +08:00
|
|
|
if (AttrData.getForm() == dwarf::DW_FORM_implicit_const)
|
2017-01-11 05:18:26 +08:00
|
|
|
AP->EmitSLEB128(AttrData.getValue());
|
2009-05-15 08:11:17 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Mark end of abbreviation.
|
2010-04-05 08:13:49 +08:00
|
|
|
AP->EmitULEB128(0, "EOM(1)");
|
|
|
|
AP->EmitULEB128(0, "EOM(2)");
|
2009-05-15 08:11:17 +08:00
|
|
|
}
|
|
|
|
|
2015-11-24 10:21:43 +08:00
|
|
|
LLVM_DUMP_METHOD
|
2009-08-23 09:01:17 +08:00
|
|
|
void DIEAbbrev::print(raw_ostream &O) {
|
2009-05-15 08:11:17 +08:00
|
|
|
O << "Abbreviation @"
|
2009-08-23 09:01:17 +08:00
|
|
|
<< format("0x%lx", (long)(intptr_t)this)
|
2009-05-15 08:11:17 +08:00
|
|
|
<< " "
|
|
|
|
<< dwarf::TagString(Tag)
|
|
|
|
<< " "
|
2014-03-05 09:44:58 +08:00
|
|
|
<< dwarf::ChildrenString(Children)
|
2009-08-23 09:01:17 +08:00
|
|
|
<< '\n';
|
2009-05-15 08:11:17 +08:00
|
|
|
|
|
|
|
for (unsigned i = 0, N = Data.size(); i < N; ++i) {
|
|
|
|
O << " "
|
|
|
|
<< dwarf::AttributeString(Data[i].getAttribute())
|
|
|
|
<< " "
|
2017-03-02 06:13:42 +08:00
|
|
|
<< dwarf::FormEncodingString(Data[i].getForm());
|
|
|
|
|
|
|
|
if (Data[i].getForm() == dwarf::DW_FORM_implicit_const)
|
|
|
|
O << " " << Data[i].getValue();
|
|
|
|
|
|
|
|
O << '\n';
|
2009-05-15 08:11:17 +08:00
|
|
|
}
|
|
|
|
}
|
2015-11-24 10:21:43 +08:00
|
|
|
|
2017-01-28 10:02:38 +08:00
|
|
|
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
|
|
|
|
LLVM_DUMP_METHOD void DIEAbbrev::dump() {
|
|
|
|
print(dbgs());
|
|
|
|
}
|
|
|
|
#endif
|
2009-05-15 08:11:17 +08:00
|
|
|
|
Make a DWARF generator so we can unit test DWARF APIs with gtest.
The only tests we have for the DWARF parser are the tests that use llvm-dwarfdump and expect output from textual dumps.
More DWARF parser modification are coming in the next few weeks and I wanted to add tests that can verify that we can encode and decode all form types, as well as test some other basic DWARF APIs where we ask DIE objects for their children and siblings.
DwarfGenerator.cpp was added in the lib/CodeGen directory. This file contains the code necessary to easily create DWARF for tests:
dwarfgen::Generator DG;
Triple Triple("x86_64--");
bool success = DG.init(Triple, Version);
if (!success)
return;
dwarfgen::CompileUnit &CU = DG.addCompileUnit();
dwarfgen::DIE CUDie = CU.getUnitDIE();
CUDie.addAttribute(DW_AT_name, DW_FORM_strp, "/tmp/main.c");
CUDie.addAttribute(DW_AT_language, DW_FORM_data2, DW_LANG_C);
dwarfgen::DIE SubprogramDie = CUDie.addChild(DW_TAG_subprogram);
SubprogramDie.addAttribute(DW_AT_name, DW_FORM_strp, "main");
SubprogramDie.addAttribute(DW_AT_low_pc, DW_FORM_addr, 0x1000U);
SubprogramDie.addAttribute(DW_AT_high_pc, DW_FORM_addr, 0x2000U);
dwarfgen::DIE IntDie = CUDie.addChild(DW_TAG_base_type);
IntDie.addAttribute(DW_AT_name, DW_FORM_strp, "int");
IntDie.addAttribute(DW_AT_encoding, DW_FORM_data1, DW_ATE_signed);
IntDie.addAttribute(DW_AT_byte_size, DW_FORM_data1, 4);
dwarfgen::DIE ArgcDie = SubprogramDie.addChild(DW_TAG_formal_parameter);
ArgcDie.addAttribute(DW_AT_name, DW_FORM_strp, "argc");
// ArgcDie.addAttribute(DW_AT_type, DW_FORM_ref4, IntDie);
ArgcDie.addAttribute(DW_AT_type, DW_FORM_ref_addr, IntDie);
StringRef FileBytes = DG.generate();
MemoryBufferRef FileBuffer(FileBytes, "dwarf");
auto Obj = object::ObjectFile::createObjectFile(FileBuffer);
EXPECT_TRUE((bool)Obj);
DWARFContextInMemory DwarfContext(*Obj.get());
This code is backed by the AsmPrinter code that emits DWARF for the actual compiler.
While adding unit tests it was discovered that DIEValue that used DIEEntry as their values had bugs where DW_FORM_ref1, DW_FORM_ref2, DW_FORM_ref8, and DW_FORM_ref_udata forms were not supported. These are all now supported. Added support for DW_FORM_string so we can emit inlined C strings.
Centralized the code to unique abbreviations into a new DIEAbbrevSet class and made both the dwarfgen::Generator and the llvm::DwarfFile classes use the new class.
Fixed comments in the llvm::DIE class so that the Offset is known to be the compile/type unit offset.
DIEInteger now supports more DW_FORM values.
There are also unit tests that cover:
Encoding and decoding all form types and values
Encoding and decoding all reference types (DW_FORM_ref1, DW_FORM_ref2, DW_FORM_ref4, DW_FORM_ref8, DW_FORM_ref_udata, DW_FORM_ref_addr) including cross compile unit references with that go forward one compile unit and backward on compile unit.
Differential Revision: https://reviews.llvm.org/D27326
llvm-svn: 289010
2016-12-08 09:03:48 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// DIEAbbrevSet Implementation
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
DIEAbbrevSet::~DIEAbbrevSet() {
|
|
|
|
for (DIEAbbrev *Abbrev : Abbreviations)
|
|
|
|
Abbrev->~DIEAbbrev();
|
|
|
|
}
|
|
|
|
|
|
|
|
DIEAbbrev &DIEAbbrevSet::uniqueAbbreviation(DIE &Die) {
|
|
|
|
|
|
|
|
FoldingSetNodeID ID;
|
|
|
|
DIEAbbrev Abbrev = Die.generateAbbrev();
|
|
|
|
Abbrev.Profile(ID);
|
|
|
|
|
|
|
|
void *InsertPos;
|
|
|
|
if (DIEAbbrev *Existing =
|
|
|
|
AbbreviationsSet.FindNodeOrInsertPos(ID, InsertPos)) {
|
|
|
|
Die.setAbbrevNumber(Existing->getNumber());
|
|
|
|
return *Existing;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Move the abbreviation to the heap and assign a number.
|
|
|
|
DIEAbbrev *New = new (Alloc) DIEAbbrev(std::move(Abbrev));
|
|
|
|
Abbreviations.push_back(New);
|
|
|
|
New->setNumber(Abbreviations.size());
|
|
|
|
Die.setAbbrevNumber(Abbreviations.size());
|
|
|
|
|
|
|
|
// Store it for lookup.
|
|
|
|
AbbreviationsSet.InsertNode(New, InsertPos);
|
|
|
|
return *New;
|
|
|
|
}
|
|
|
|
|
|
|
|
void DIEAbbrevSet::Emit(const AsmPrinter *AP, MCSection *Section) const {
|
|
|
|
if (!Abbreviations.empty()) {
|
|
|
|
// Start the debug abbrev section.
|
|
|
|
AP->OutStreamer->SwitchSection(Section);
|
|
|
|
AP->emitDwarfAbbrevs(Abbreviations);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// DIE Implementation
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2016-12-02 02:56:29 +08:00
|
|
|
DIE *DIE::getParent() const {
|
|
|
|
return Owner.dyn_cast<DIE*>();
|
|
|
|
}
|
|
|
|
|
2015-05-28 06:31:41 +08:00
|
|
|
DIEAbbrev DIE::generateAbbrev() const {
|
|
|
|
DIEAbbrev Abbrev(Tag, hasChildren());
|
2015-08-03 04:42:45 +08:00
|
|
|
for (const DIEValue &V : values())
|
2017-01-11 05:18:26 +08:00
|
|
|
if (V.getForm() == dwarf::DW_FORM_implicit_const)
|
|
|
|
Abbrev.AddImplicitConstAttribute(V.getAttribute(),
|
|
|
|
V.getDIEInteger().getValue());
|
|
|
|
else
|
|
|
|
Abbrev.AddAttribute(V.getAttribute(), V.getForm());
|
2015-05-28 06:31:41 +08:00
|
|
|
return Abbrev;
|
|
|
|
}
|
|
|
|
|
2016-12-02 02:56:29 +08:00
|
|
|
unsigned DIE::getDebugSectionOffset() const {
|
|
|
|
const DIEUnit *Unit = getUnit();
|
|
|
|
assert(Unit && "DIE must be owned by a DIEUnit to get its absolute offset");
|
2016-12-02 03:10:10 +08:00
|
|
|
return Unit->getDebugSectionOffset() + getOffset();
|
2013-11-01 01:54:35 +08:00
|
|
|
}
|
|
|
|
|
2016-12-02 02:56:29 +08:00
|
|
|
const DIE *DIE::getUnitDie() const {
|
2013-10-30 06:57:10 +08:00
|
|
|
const DIE *p = this;
|
|
|
|
while (p) {
|
2013-11-20 07:08:21 +08:00
|
|
|
if (p->getTag() == dwarf::DW_TAG_compile_unit ||
|
|
|
|
p->getTag() == dwarf::DW_TAG_type_unit)
|
2013-10-30 06:57:10 +08:00
|
|
|
return p;
|
|
|
|
p = p->getParent();
|
|
|
|
}
|
2014-04-24 14:44:33 +08:00
|
|
|
return nullptr;
|
2013-10-30 06:57:10 +08:00
|
|
|
}
|
|
|
|
|
2016-12-02 02:56:29 +08:00
|
|
|
const DIEUnit *DIE::getUnit() const {
|
|
|
|
const DIE *UnitDie = getUnitDie();
|
|
|
|
if (UnitDie)
|
|
|
|
return UnitDie->Owner.dyn_cast<DIEUnit*>();
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
Reapply "AsmPrinter: Change DIEValue to be stored by value"
This reverts commit r238350, effectively reapplying r238349 after fixing
(all?) the problems, all somehow related to how I was using
`AlignedArrayCharUnion<>` inside `DIEValue`:
- MSVC can only handle `sizeof()` on types, not values. Change the
assert.
- GCC doesn't know the `is_trivially_copyable` type trait. Instead of
asserting it, add destructors.
- Call placement new even when constructing POD (i.e., the pointers).
- Instead of copying the char buffer, copy the casted classes.
I've left in a couple of `static_assert`s that I think both MSVC and GCC
know how to handle. If the bots disagree with me, I'll remove them.
- Check that the constructed type is either standard layout or a
pointer. This protects against a programming error: we really want
the "small" `DIEValue`s to be small and simple, so don't
accidentally change them not to be.
- Similarly, check that the size of the buffer is no bigger than a
`uint64_t` or a pointer. (I thought checking against
`sizeof(uint64_t)` would be good enough, but Chandler suggested that
pointers might sometimes be bigger than that in the context of
sanitizers.)
I've also committed r238359 in the meantime, which introduces a
DIEValue.def to simplify dispatching between the various types (thanks
to a review comment by David Blaikie). Without that, this commit would
be almost unintelligible.
Here's the original commit message:
--
Change `DIEValue` to be stored/passed/etc. by value, instead of
reference. It's now a discriminated union, with a `Val` field storing
the actual type. The classes that used to inherit from `DIEValue` no
longer do. There are two categories of these:
- Small values fit in a single pointer and are stored by value.
- Large values require auxiliary storage, and are stored by reference.
The only non-mechanical change is to tools/dsymutil/DwarfLinker.cpp. It
was relying on `DIEInteger`s being passed around by reference, so I
replaced that assumption with a `PatchLocation` type that stores a safe
reference to where the `DIEInteger` lives instead.
This commit causes a temporary regression in memory usage, since I've
left merging `DIEAbbrevData` into `DIEValue` for a follow-up commit. I
measured an increase from 845 MB to 879 MB, around 3.9%. The follow-up
drops it lower than the starting point, and I've only recently brought
the memory this low anyway, so I'm committing these changes separately
to keep them incremental. (I also considered swapping the commits, but
the other one first would cause a lot more code churn.)
(I'm looking at `llc` memory usage on `verify-uselistorder.lto.opt.bc`;
see r236629 for details.)
--
llvm-svn: 238362
2015-05-28 06:14:58 +08:00
|
|
|
DIEValue DIE::findAttribute(dwarf::Attribute Attribute) const {
|
2013-08-07 09:18:33 +08:00
|
|
|
// Iterate through all the attributes until we find the one we're
|
|
|
|
// looking for, if we can't find it return NULL.
|
2015-05-28 06:44:06 +08:00
|
|
|
for (const auto &V : values())
|
|
|
|
if (V.getAttribute() == Attribute)
|
|
|
|
return V;
|
Reapply "AsmPrinter: Change DIEValue to be stored by value"
This reverts commit r238350, effectively reapplying r238349 after fixing
(all?) the problems, all somehow related to how I was using
`AlignedArrayCharUnion<>` inside `DIEValue`:
- MSVC can only handle `sizeof()` on types, not values. Change the
assert.
- GCC doesn't know the `is_trivially_copyable` type trait. Instead of
asserting it, add destructors.
- Call placement new even when constructing POD (i.e., the pointers).
- Instead of copying the char buffer, copy the casted classes.
I've left in a couple of `static_assert`s that I think both MSVC and GCC
know how to handle. If the bots disagree with me, I'll remove them.
- Check that the constructed type is either standard layout or a
pointer. This protects against a programming error: we really want
the "small" `DIEValue`s to be small and simple, so don't
accidentally change them not to be.
- Similarly, check that the size of the buffer is no bigger than a
`uint64_t` or a pointer. (I thought checking against
`sizeof(uint64_t)` would be good enough, but Chandler suggested that
pointers might sometimes be bigger than that in the context of
sanitizers.)
I've also committed r238359 in the meantime, which introduces a
DIEValue.def to simplify dispatching between the various types (thanks
to a review comment by David Blaikie). Without that, this commit would
be almost unintelligible.
Here's the original commit message:
--
Change `DIEValue` to be stored/passed/etc. by value, instead of
reference. It's now a discriminated union, with a `Val` field storing
the actual type. The classes that used to inherit from `DIEValue` no
longer do. There are two categories of these:
- Small values fit in a single pointer and are stored by value.
- Large values require auxiliary storage, and are stored by reference.
The only non-mechanical change is to tools/dsymutil/DwarfLinker.cpp. It
was relying on `DIEInteger`s being passed around by reference, so I
replaced that assumption with a `PatchLocation` type that stores a safe
reference to where the `DIEInteger` lives instead.
This commit causes a temporary regression in memory usage, since I've
left merging `DIEAbbrevData` into `DIEValue` for a follow-up commit. I
measured an increase from 845 MB to 879 MB, around 3.9%. The follow-up
drops it lower than the starting point, and I've only recently brought
the memory this low anyway, so I'm committing these changes separately
to keep them incremental. (I also considered swapping the commits, but
the other one first would cause a lot more code churn.)
(I'm looking at `llc` memory usage on `verify-uselistorder.lto.opt.bc`;
see r236629 for details.)
--
llvm-svn: 238362
2015-05-28 06:14:58 +08:00
|
|
|
return DIEValue();
|
2013-08-07 09:18:33 +08:00
|
|
|
}
|
|
|
|
|
2015-11-24 10:21:43 +08:00
|
|
|
LLVM_DUMP_METHOD
|
2015-08-03 04:46:49 +08:00
|
|
|
static void printValues(raw_ostream &O, const DIEValueList &Values,
|
|
|
|
StringRef Type, unsigned Size, unsigned IndentCount) {
|
|
|
|
O << Type << ": Size: " << Size << "\n";
|
|
|
|
|
|
|
|
unsigned I = 0;
|
2009-05-15 08:11:17 +08:00
|
|
|
const std::string Indent(IndentCount, ' ');
|
2015-08-03 04:46:49 +08:00
|
|
|
for (const auto &V : Values.values()) {
|
|
|
|
O << Indent;
|
|
|
|
O << "Blk[" << I++ << "]";
|
|
|
|
O << " " << dwarf::FormEncodingString(V.getForm()) << " ";
|
|
|
|
V.print(O);
|
|
|
|
O << "\n";
|
2009-05-15 08:11:17 +08:00
|
|
|
}
|
2015-08-03 04:46:49 +08:00
|
|
|
}
|
|
|
|
|
2015-11-24 10:21:43 +08:00
|
|
|
LLVM_DUMP_METHOD
|
2015-08-03 04:46:49 +08:00
|
|
|
void DIE::print(raw_ostream &O, unsigned IndentCount) const {
|
|
|
|
const std::string Indent(IndentCount, ' ');
|
|
|
|
O << Indent << "Die: " << format("0x%lx", (long)(intptr_t) this)
|
|
|
|
<< ", Offset: " << Offset << ", Size: " << Size << "\n";
|
|
|
|
|
|
|
|
O << Indent << dwarf::TagString(getTag()) << " "
|
|
|
|
<< dwarf::ChildrenString(hasChildren()) << "\n";
|
2009-05-15 08:11:17 +08:00
|
|
|
|
|
|
|
IndentCount += 2;
|
2015-08-03 04:42:45 +08:00
|
|
|
for (const auto &V : values()) {
|
2009-05-15 08:11:17 +08:00
|
|
|
O << Indent;
|
2015-08-03 04:46:49 +08:00
|
|
|
O << dwarf::AttributeString(V.getAttribute());
|
2015-06-26 07:46:41 +08:00
|
|
|
O << " " << dwarf::FormEncodingString(V.getForm()) << " ";
|
|
|
|
V.print(O);
|
2009-05-15 08:11:17 +08:00
|
|
|
O << "\n";
|
|
|
|
}
|
|
|
|
IndentCount -= 2;
|
|
|
|
|
2015-06-26 07:52:10 +08:00
|
|
|
for (const auto &Child : children())
|
|
|
|
Child.print(O, IndentCount + 4);
|
2009-05-15 08:11:17 +08:00
|
|
|
|
2015-08-03 04:46:49 +08:00
|
|
|
O << "\n";
|
2009-05-15 08:11:17 +08:00
|
|
|
}
|
|
|
|
|
2017-01-28 10:02:38 +08:00
|
|
|
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
|
|
|
|
LLVM_DUMP_METHOD void DIE::dump() {
|
2009-12-24 08:27:55 +08:00
|
|
|
print(dbgs());
|
2009-05-15 08:11:17 +08:00
|
|
|
}
|
2017-01-28 10:02:38 +08:00
|
|
|
#endif
|
2009-05-15 08:11:17 +08:00
|
|
|
|
Make a DWARF generator so we can unit test DWARF APIs with gtest.
The only tests we have for the DWARF parser are the tests that use llvm-dwarfdump and expect output from textual dumps.
More DWARF parser modification are coming in the next few weeks and I wanted to add tests that can verify that we can encode and decode all form types, as well as test some other basic DWARF APIs where we ask DIE objects for their children and siblings.
DwarfGenerator.cpp was added in the lib/CodeGen directory. This file contains the code necessary to easily create DWARF for tests:
dwarfgen::Generator DG;
Triple Triple("x86_64--");
bool success = DG.init(Triple, Version);
if (!success)
return;
dwarfgen::CompileUnit &CU = DG.addCompileUnit();
dwarfgen::DIE CUDie = CU.getUnitDIE();
CUDie.addAttribute(DW_AT_name, DW_FORM_strp, "/tmp/main.c");
CUDie.addAttribute(DW_AT_language, DW_FORM_data2, DW_LANG_C);
dwarfgen::DIE SubprogramDie = CUDie.addChild(DW_TAG_subprogram);
SubprogramDie.addAttribute(DW_AT_name, DW_FORM_strp, "main");
SubprogramDie.addAttribute(DW_AT_low_pc, DW_FORM_addr, 0x1000U);
SubprogramDie.addAttribute(DW_AT_high_pc, DW_FORM_addr, 0x2000U);
dwarfgen::DIE IntDie = CUDie.addChild(DW_TAG_base_type);
IntDie.addAttribute(DW_AT_name, DW_FORM_strp, "int");
IntDie.addAttribute(DW_AT_encoding, DW_FORM_data1, DW_ATE_signed);
IntDie.addAttribute(DW_AT_byte_size, DW_FORM_data1, 4);
dwarfgen::DIE ArgcDie = SubprogramDie.addChild(DW_TAG_formal_parameter);
ArgcDie.addAttribute(DW_AT_name, DW_FORM_strp, "argc");
// ArgcDie.addAttribute(DW_AT_type, DW_FORM_ref4, IntDie);
ArgcDie.addAttribute(DW_AT_type, DW_FORM_ref_addr, IntDie);
StringRef FileBytes = DG.generate();
MemoryBufferRef FileBuffer(FileBytes, "dwarf");
auto Obj = object::ObjectFile::createObjectFile(FileBuffer);
EXPECT_TRUE((bool)Obj);
DWARFContextInMemory DwarfContext(*Obj.get());
This code is backed by the AsmPrinter code that emits DWARF for the actual compiler.
While adding unit tests it was discovered that DIEValue that used DIEEntry as their values had bugs where DW_FORM_ref1, DW_FORM_ref2, DW_FORM_ref8, and DW_FORM_ref_udata forms were not supported. These are all now supported. Added support for DW_FORM_string so we can emit inlined C strings.
Centralized the code to unique abbreviations into a new DIEAbbrevSet class and made both the dwarfgen::Generator and the llvm::DwarfFile classes use the new class.
Fixed comments in the llvm::DIE class so that the Offset is known to be the compile/type unit offset.
DIEInteger now supports more DW_FORM values.
There are also unit tests that cover:
Encoding and decoding all form types and values
Encoding and decoding all reference types (DW_FORM_ref1, DW_FORM_ref2, DW_FORM_ref4, DW_FORM_ref8, DW_FORM_ref_udata, DW_FORM_ref_addr) including cross compile unit references with that go forward one compile unit and backward on compile unit.
Differential Revision: https://reviews.llvm.org/D27326
llvm-svn: 289010
2016-12-08 09:03:48 +08:00
|
|
|
unsigned DIE::computeOffsetsAndAbbrevs(const AsmPrinter *AP,
|
|
|
|
DIEAbbrevSet &AbbrevSet,
|
|
|
|
unsigned CUOffset) {
|
|
|
|
// Unique the abbreviation and fill in the abbreviation number so this DIE
|
|
|
|
// can be emitted.
|
|
|
|
const DIEAbbrev &Abbrev = AbbrevSet.uniqueAbbreviation(*this);
|
|
|
|
|
|
|
|
// Set compile/type unit relative offset of this DIE.
|
|
|
|
setOffset(CUOffset);
|
|
|
|
|
|
|
|
// Add the byte size of the abbreviation code.
|
|
|
|
CUOffset += getULEB128Size(getAbbrevNumber());
|
|
|
|
|
|
|
|
// Add the byte size of all the DIE attribute values.
|
|
|
|
for (const auto &V : values())
|
|
|
|
CUOffset += V.SizeOf(AP);
|
|
|
|
|
|
|
|
// Let the children compute their offsets and abbreviation numbers.
|
|
|
|
if (hasChildren()) {
|
|
|
|
(void)Abbrev;
|
|
|
|
assert(Abbrev.hasChildren() && "Children flag not set");
|
|
|
|
|
|
|
|
for (auto &Child : children())
|
|
|
|
CUOffset = Child.computeOffsetsAndAbbrevs(AP, AbbrevSet, CUOffset);
|
|
|
|
|
|
|
|
// Each child chain is terminated with a zero byte, adjust the offset.
|
|
|
|
CUOffset += sizeof(int8_t);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Compute the byte size of this DIE and all of its children correctly. This
|
|
|
|
// is needed so that top level DIE can help the compile unit set its length
|
|
|
|
// correctly.
|
|
|
|
setSize(CUOffset - getOffset());
|
|
|
|
return CUOffset;
|
|
|
|
}
|
|
|
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// DIEUnit Implementation
|
|
|
|
//===----------------------------------------------------------------------===//
|
2016-12-02 02:56:29 +08:00
|
|
|
DIEUnit::DIEUnit(uint16_t V, uint8_t A, dwarf::Tag UnitTag)
|
|
|
|
: Die(UnitTag), Section(nullptr), Offset(0), Length(0), Version(V),
|
|
|
|
AddrSize(A)
|
|
|
|
{
|
2016-12-02 05:59:09 +08:00
|
|
|
Die.Owner = this;
|
2016-12-02 02:56:29 +08:00
|
|
|
assert((UnitTag == dwarf::DW_TAG_compile_unit ||
|
|
|
|
UnitTag == dwarf::DW_TAG_type_unit ||
|
|
|
|
UnitTag == dwarf::DW_TAG_partial_unit) && "expected a unit TAG");
|
|
|
|
}
|
|
|
|
|
2015-06-25 02:48:11 +08:00
|
|
|
void DIEValue::EmitValue(const AsmPrinter *AP) const {
|
2015-05-23 09:45:07 +08:00
|
|
|
switch (Ty) {
|
Reapply "AsmPrinter: Change DIEValue to be stored by value"
This reverts commit r238350, effectively reapplying r238349 after fixing
(all?) the problems, all somehow related to how I was using
`AlignedArrayCharUnion<>` inside `DIEValue`:
- MSVC can only handle `sizeof()` on types, not values. Change the
assert.
- GCC doesn't know the `is_trivially_copyable` type trait. Instead of
asserting it, add destructors.
- Call placement new even when constructing POD (i.e., the pointers).
- Instead of copying the char buffer, copy the casted classes.
I've left in a couple of `static_assert`s that I think both MSVC and GCC
know how to handle. If the bots disagree with me, I'll remove them.
- Check that the constructed type is either standard layout or a
pointer. This protects against a programming error: we really want
the "small" `DIEValue`s to be small and simple, so don't
accidentally change them not to be.
- Similarly, check that the size of the buffer is no bigger than a
`uint64_t` or a pointer. (I thought checking against
`sizeof(uint64_t)` would be good enough, but Chandler suggested that
pointers might sometimes be bigger than that in the context of
sanitizers.)
I've also committed r238359 in the meantime, which introduces a
DIEValue.def to simplify dispatching between the various types (thanks
to a review comment by David Blaikie). Without that, this commit would
be almost unintelligible.
Here's the original commit message:
--
Change `DIEValue` to be stored/passed/etc. by value, instead of
reference. It's now a discriminated union, with a `Val` field storing
the actual type. The classes that used to inherit from `DIEValue` no
longer do. There are two categories of these:
- Small values fit in a single pointer and are stored by value.
- Large values require auxiliary storage, and are stored by reference.
The only non-mechanical change is to tools/dsymutil/DwarfLinker.cpp. It
was relying on `DIEInteger`s being passed around by reference, so I
replaced that assumption with a `PatchLocation` type that stores a safe
reference to where the `DIEInteger` lives instead.
This commit causes a temporary regression in memory usage, since I've
left merging `DIEAbbrevData` into `DIEValue` for a follow-up commit. I
measured an increase from 845 MB to 879 MB, around 3.9%. The follow-up
drops it lower than the starting point, and I've only recently brought
the memory this low anyway, so I'm committing these changes separately
to keep them incremental. (I also considered swapping the commits, but
the other one first would cause a lot more code churn.)
(I'm looking at `llc` memory usage on `verify-uselistorder.lto.opt.bc`;
see r236629 for details.)
--
llvm-svn: 238362
2015-05-28 06:14:58 +08:00
|
|
|
case isNone:
|
|
|
|
llvm_unreachable("Expected valid DIEValue");
|
2015-05-28 05:15:43 +08:00
|
|
|
#define HANDLE_DIEVALUE(T) \
|
|
|
|
case is##T: \
|
Reapply "AsmPrinter: Change DIEValue to be stored by value"
This reverts commit r238350, effectively reapplying r238349 after fixing
(all?) the problems, all somehow related to how I was using
`AlignedArrayCharUnion<>` inside `DIEValue`:
- MSVC can only handle `sizeof()` on types, not values. Change the
assert.
- GCC doesn't know the `is_trivially_copyable` type trait. Instead of
asserting it, add destructors.
- Call placement new even when constructing POD (i.e., the pointers).
- Instead of copying the char buffer, copy the casted classes.
I've left in a couple of `static_assert`s that I think both MSVC and GCC
know how to handle. If the bots disagree with me, I'll remove them.
- Check that the constructed type is either standard layout or a
pointer. This protects against a programming error: we really want
the "small" `DIEValue`s to be small and simple, so don't
accidentally change them not to be.
- Similarly, check that the size of the buffer is no bigger than a
`uint64_t` or a pointer. (I thought checking against
`sizeof(uint64_t)` would be good enough, but Chandler suggested that
pointers might sometimes be bigger than that in the context of
sanitizers.)
I've also committed r238359 in the meantime, which introduces a
DIEValue.def to simplify dispatching between the various types (thanks
to a review comment by David Blaikie). Without that, this commit would
be almost unintelligible.
Here's the original commit message:
--
Change `DIEValue` to be stored/passed/etc. by value, instead of
reference. It's now a discriminated union, with a `Val` field storing
the actual type. The classes that used to inherit from `DIEValue` no
longer do. There are two categories of these:
- Small values fit in a single pointer and are stored by value.
- Large values require auxiliary storage, and are stored by reference.
The only non-mechanical change is to tools/dsymutil/DwarfLinker.cpp. It
was relying on `DIEInteger`s being passed around by reference, so I
replaced that assumption with a `PatchLocation` type that stores a safe
reference to where the `DIEInteger` lives instead.
This commit causes a temporary regression in memory usage, since I've
left merging `DIEAbbrevData` into `DIEValue` for a follow-up commit. I
measured an increase from 845 MB to 879 MB, around 3.9%. The follow-up
drops it lower than the starting point, and I've only recently brought
the memory this low anyway, so I'm committing these changes separately
to keep them incremental. (I also considered swapping the commits, but
the other one first would cause a lot more code churn.)
(I'm looking at `llc` memory usage on `verify-uselistorder.lto.opt.bc`;
see r236629 for details.)
--
llvm-svn: 238362
2015-05-28 06:14:58 +08:00
|
|
|
getDIE##T().EmitValue(AP, Form); \
|
2015-05-23 09:45:07 +08:00
|
|
|
break;
|
2015-05-28 05:15:43 +08:00
|
|
|
#include "llvm/CodeGen/DIEValue.def"
|
2015-05-23 09:45:07 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-06-25 02:48:11 +08:00
|
|
|
unsigned DIEValue::SizeOf(const AsmPrinter *AP) const {
|
2015-05-23 09:45:07 +08:00
|
|
|
switch (Ty) {
|
Reapply "AsmPrinter: Change DIEValue to be stored by value"
This reverts commit r238350, effectively reapplying r238349 after fixing
(all?) the problems, all somehow related to how I was using
`AlignedArrayCharUnion<>` inside `DIEValue`:
- MSVC can only handle `sizeof()` on types, not values. Change the
assert.
- GCC doesn't know the `is_trivially_copyable` type trait. Instead of
asserting it, add destructors.
- Call placement new even when constructing POD (i.e., the pointers).
- Instead of copying the char buffer, copy the casted classes.
I've left in a couple of `static_assert`s that I think both MSVC and GCC
know how to handle. If the bots disagree with me, I'll remove them.
- Check that the constructed type is either standard layout or a
pointer. This protects against a programming error: we really want
the "small" `DIEValue`s to be small and simple, so don't
accidentally change them not to be.
- Similarly, check that the size of the buffer is no bigger than a
`uint64_t` or a pointer. (I thought checking against
`sizeof(uint64_t)` would be good enough, but Chandler suggested that
pointers might sometimes be bigger than that in the context of
sanitizers.)
I've also committed r238359 in the meantime, which introduces a
DIEValue.def to simplify dispatching between the various types (thanks
to a review comment by David Blaikie). Without that, this commit would
be almost unintelligible.
Here's the original commit message:
--
Change `DIEValue` to be stored/passed/etc. by value, instead of
reference. It's now a discriminated union, with a `Val` field storing
the actual type. The classes that used to inherit from `DIEValue` no
longer do. There are two categories of these:
- Small values fit in a single pointer and are stored by value.
- Large values require auxiliary storage, and are stored by reference.
The only non-mechanical change is to tools/dsymutil/DwarfLinker.cpp. It
was relying on `DIEInteger`s being passed around by reference, so I
replaced that assumption with a `PatchLocation` type that stores a safe
reference to where the `DIEInteger` lives instead.
This commit causes a temporary regression in memory usage, since I've
left merging `DIEAbbrevData` into `DIEValue` for a follow-up commit. I
measured an increase from 845 MB to 879 MB, around 3.9%. The follow-up
drops it lower than the starting point, and I've only recently brought
the memory this low anyway, so I'm committing these changes separately
to keep them incremental. (I also considered swapping the commits, but
the other one first would cause a lot more code churn.)
(I'm looking at `llc` memory usage on `verify-uselistorder.lto.opt.bc`;
see r236629 for details.)
--
llvm-svn: 238362
2015-05-28 06:14:58 +08:00
|
|
|
case isNone:
|
|
|
|
llvm_unreachable("Expected valid DIEValue");
|
2015-05-28 05:15:43 +08:00
|
|
|
#define HANDLE_DIEVALUE(T) \
|
|
|
|
case is##T: \
|
Reapply "AsmPrinter: Change DIEValue to be stored by value"
This reverts commit r238350, effectively reapplying r238349 after fixing
(all?) the problems, all somehow related to how I was using
`AlignedArrayCharUnion<>` inside `DIEValue`:
- MSVC can only handle `sizeof()` on types, not values. Change the
assert.
- GCC doesn't know the `is_trivially_copyable` type trait. Instead of
asserting it, add destructors.
- Call placement new even when constructing POD (i.e., the pointers).
- Instead of copying the char buffer, copy the casted classes.
I've left in a couple of `static_assert`s that I think both MSVC and GCC
know how to handle. If the bots disagree with me, I'll remove them.
- Check that the constructed type is either standard layout or a
pointer. This protects against a programming error: we really want
the "small" `DIEValue`s to be small and simple, so don't
accidentally change them not to be.
- Similarly, check that the size of the buffer is no bigger than a
`uint64_t` or a pointer. (I thought checking against
`sizeof(uint64_t)` would be good enough, but Chandler suggested that
pointers might sometimes be bigger than that in the context of
sanitizers.)
I've also committed r238359 in the meantime, which introduces a
DIEValue.def to simplify dispatching between the various types (thanks
to a review comment by David Blaikie). Without that, this commit would
be almost unintelligible.
Here's the original commit message:
--
Change `DIEValue` to be stored/passed/etc. by value, instead of
reference. It's now a discriminated union, with a `Val` field storing
the actual type. The classes that used to inherit from `DIEValue` no
longer do. There are two categories of these:
- Small values fit in a single pointer and are stored by value.
- Large values require auxiliary storage, and are stored by reference.
The only non-mechanical change is to tools/dsymutil/DwarfLinker.cpp. It
was relying on `DIEInteger`s being passed around by reference, so I
replaced that assumption with a `PatchLocation` type that stores a safe
reference to where the `DIEInteger` lives instead.
This commit causes a temporary regression in memory usage, since I've
left merging `DIEAbbrevData` into `DIEValue` for a follow-up commit. I
measured an increase from 845 MB to 879 MB, around 3.9%. The follow-up
drops it lower than the starting point, and I've only recently brought
the memory this low anyway, so I'm committing these changes separately
to keep them incremental. (I also considered swapping the commits, but
the other one first would cause a lot more code churn.)
(I'm looking at `llc` memory usage on `verify-uselistorder.lto.opt.bc`;
see r236629 for details.)
--
llvm-svn: 238362
2015-05-28 06:14:58 +08:00
|
|
|
return getDIE##T().SizeOf(AP, Form);
|
2015-05-28 05:15:43 +08:00
|
|
|
#include "llvm/CodeGen/DIEValue.def"
|
2015-05-23 09:45:07 +08:00
|
|
|
}
|
2015-05-23 22:46:49 +08:00
|
|
|
llvm_unreachable("Unknown DIE kind");
|
2015-05-23 09:45:07 +08:00
|
|
|
}
|
2009-05-15 08:11:17 +08:00
|
|
|
|
2015-11-24 10:21:43 +08:00
|
|
|
LLVM_DUMP_METHOD
|
2015-05-23 09:45:07 +08:00
|
|
|
void DIEValue::print(raw_ostream &O) const {
|
|
|
|
switch (Ty) {
|
Reapply "AsmPrinter: Change DIEValue to be stored by value"
This reverts commit r238350, effectively reapplying r238349 after fixing
(all?) the problems, all somehow related to how I was using
`AlignedArrayCharUnion<>` inside `DIEValue`:
- MSVC can only handle `sizeof()` on types, not values. Change the
assert.
- GCC doesn't know the `is_trivially_copyable` type trait. Instead of
asserting it, add destructors.
- Call placement new even when constructing POD (i.e., the pointers).
- Instead of copying the char buffer, copy the casted classes.
I've left in a couple of `static_assert`s that I think both MSVC and GCC
know how to handle. If the bots disagree with me, I'll remove them.
- Check that the constructed type is either standard layout or a
pointer. This protects against a programming error: we really want
the "small" `DIEValue`s to be small and simple, so don't
accidentally change them not to be.
- Similarly, check that the size of the buffer is no bigger than a
`uint64_t` or a pointer. (I thought checking against
`sizeof(uint64_t)` would be good enough, but Chandler suggested that
pointers might sometimes be bigger than that in the context of
sanitizers.)
I've also committed r238359 in the meantime, which introduces a
DIEValue.def to simplify dispatching between the various types (thanks
to a review comment by David Blaikie). Without that, this commit would
be almost unintelligible.
Here's the original commit message:
--
Change `DIEValue` to be stored/passed/etc. by value, instead of
reference. It's now a discriminated union, with a `Val` field storing
the actual type. The classes that used to inherit from `DIEValue` no
longer do. There are two categories of these:
- Small values fit in a single pointer and are stored by value.
- Large values require auxiliary storage, and are stored by reference.
The only non-mechanical change is to tools/dsymutil/DwarfLinker.cpp. It
was relying on `DIEInteger`s being passed around by reference, so I
replaced that assumption with a `PatchLocation` type that stores a safe
reference to where the `DIEInteger` lives instead.
This commit causes a temporary regression in memory usage, since I've
left merging `DIEAbbrevData` into `DIEValue` for a follow-up commit. I
measured an increase from 845 MB to 879 MB, around 3.9%. The follow-up
drops it lower than the starting point, and I've only recently brought
the memory this low anyway, so I'm committing these changes separately
to keep them incremental. (I also considered swapping the commits, but
the other one first would cause a lot more code churn.)
(I'm looking at `llc` memory usage on `verify-uselistorder.lto.opt.bc`;
see r236629 for details.)
--
llvm-svn: 238362
2015-05-28 06:14:58 +08:00
|
|
|
case isNone:
|
|
|
|
llvm_unreachable("Expected valid DIEValue");
|
2015-05-28 05:15:43 +08:00
|
|
|
#define HANDLE_DIEVALUE(T) \
|
|
|
|
case is##T: \
|
Reapply "AsmPrinter: Change DIEValue to be stored by value"
This reverts commit r238350, effectively reapplying r238349 after fixing
(all?) the problems, all somehow related to how I was using
`AlignedArrayCharUnion<>` inside `DIEValue`:
- MSVC can only handle `sizeof()` on types, not values. Change the
assert.
- GCC doesn't know the `is_trivially_copyable` type trait. Instead of
asserting it, add destructors.
- Call placement new even when constructing POD (i.e., the pointers).
- Instead of copying the char buffer, copy the casted classes.
I've left in a couple of `static_assert`s that I think both MSVC and GCC
know how to handle. If the bots disagree with me, I'll remove them.
- Check that the constructed type is either standard layout or a
pointer. This protects against a programming error: we really want
the "small" `DIEValue`s to be small and simple, so don't
accidentally change them not to be.
- Similarly, check that the size of the buffer is no bigger than a
`uint64_t` or a pointer. (I thought checking against
`sizeof(uint64_t)` would be good enough, but Chandler suggested that
pointers might sometimes be bigger than that in the context of
sanitizers.)
I've also committed r238359 in the meantime, which introduces a
DIEValue.def to simplify dispatching between the various types (thanks
to a review comment by David Blaikie). Without that, this commit would
be almost unintelligible.
Here's the original commit message:
--
Change `DIEValue` to be stored/passed/etc. by value, instead of
reference. It's now a discriminated union, with a `Val` field storing
the actual type. The classes that used to inherit from `DIEValue` no
longer do. There are two categories of these:
- Small values fit in a single pointer and are stored by value.
- Large values require auxiliary storage, and are stored by reference.
The only non-mechanical change is to tools/dsymutil/DwarfLinker.cpp. It
was relying on `DIEInteger`s being passed around by reference, so I
replaced that assumption with a `PatchLocation` type that stores a safe
reference to where the `DIEInteger` lives instead.
This commit causes a temporary regression in memory usage, since I've
left merging `DIEAbbrevData` into `DIEValue` for a follow-up commit. I
measured an increase from 845 MB to 879 MB, around 3.9%. The follow-up
drops it lower than the starting point, and I've only recently brought
the memory this low anyway, so I'm committing these changes separately
to keep them incremental. (I also considered swapping the commits, but
the other one first would cause a lot more code churn.)
(I'm looking at `llc` memory usage on `verify-uselistorder.lto.opt.bc`;
see r236629 for details.)
--
llvm-svn: 238362
2015-05-28 06:14:58 +08:00
|
|
|
getDIE##T().print(O); \
|
2015-05-23 09:45:07 +08:00
|
|
|
break;
|
2015-05-28 05:15:43 +08:00
|
|
|
#include "llvm/CodeGen/DIEValue.def"
|
2015-05-23 09:45:07 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-01-28 10:02:38 +08:00
|
|
|
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
|
|
|
|
LLVM_DUMP_METHOD void DIEValue::dump() const {
|
2009-12-24 08:27:55 +08:00
|
|
|
print(dbgs());
|
2009-05-15 08:11:17 +08:00
|
|
|
}
|
2017-01-28 10:02:38 +08:00
|
|
|
#endif
|
2009-05-15 08:11:17 +08:00
|
|
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// DIEInteger Implementation
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
/// EmitValue - Emit integer of appropriate size.
|
|
|
|
///
|
Reapply "AsmPrinter: Change DIEValue to be stored by value"
This reverts commit r238350, effectively reapplying r238349 after fixing
(all?) the problems, all somehow related to how I was using
`AlignedArrayCharUnion<>` inside `DIEValue`:
- MSVC can only handle `sizeof()` on types, not values. Change the
assert.
- GCC doesn't know the `is_trivially_copyable` type trait. Instead of
asserting it, add destructors.
- Call placement new even when constructing POD (i.e., the pointers).
- Instead of copying the char buffer, copy the casted classes.
I've left in a couple of `static_assert`s that I think both MSVC and GCC
know how to handle. If the bots disagree with me, I'll remove them.
- Check that the constructed type is either standard layout or a
pointer. This protects against a programming error: we really want
the "small" `DIEValue`s to be small and simple, so don't
accidentally change them not to be.
- Similarly, check that the size of the buffer is no bigger than a
`uint64_t` or a pointer. (I thought checking against
`sizeof(uint64_t)` would be good enough, but Chandler suggested that
pointers might sometimes be bigger than that in the context of
sanitizers.)
I've also committed r238359 in the meantime, which introduces a
DIEValue.def to simplify dispatching between the various types (thanks
to a review comment by David Blaikie). Without that, this commit would
be almost unintelligible.
Here's the original commit message:
--
Change `DIEValue` to be stored/passed/etc. by value, instead of
reference. It's now a discriminated union, with a `Val` field storing
the actual type. The classes that used to inherit from `DIEValue` no
longer do. There are two categories of these:
- Small values fit in a single pointer and are stored by value.
- Large values require auxiliary storage, and are stored by reference.
The only non-mechanical change is to tools/dsymutil/DwarfLinker.cpp. It
was relying on `DIEInteger`s being passed around by reference, so I
replaced that assumption with a `PatchLocation` type that stores a safe
reference to where the `DIEInteger` lives instead.
This commit causes a temporary regression in memory usage, since I've
left merging `DIEAbbrevData` into `DIEValue` for a follow-up commit. I
measured an increase from 845 MB to 879 MB, around 3.9%. The follow-up
drops it lower than the starting point, and I've only recently brought
the memory this low anyway, so I'm committing these changes separately
to keep them incremental. (I also considered swapping the commits, but
the other one first would cause a lot more code churn.)
(I'm looking at `llc` memory usage on `verify-uselistorder.lto.opt.bc`;
see r236629 for details.)
--
llvm-svn: 238362
2015-05-28 06:14:58 +08:00
|
|
|
void DIEInteger::EmitValue(const AsmPrinter *Asm, dwarf::Form Form) const {
|
2009-05-15 08:11:17 +08:00
|
|
|
switch (Form) {
|
2017-01-11 05:18:26 +08:00
|
|
|
case dwarf::DW_FORM_implicit_const:
|
2012-08-24 09:14:27 +08:00
|
|
|
case dwarf::DW_FORM_flag_present:
|
|
|
|
// Emit something to keep the lines and comments in sync.
|
|
|
|
// FIXME: Is there a better way to do this?
|
2015-04-25 03:11:51 +08:00
|
|
|
Asm->OutStreamer->AddBlankLine();
|
2012-08-24 09:14:27 +08:00
|
|
|
return;
|
Make a DWARF generator so we can unit test DWARF APIs with gtest.
The only tests we have for the DWARF parser are the tests that use llvm-dwarfdump and expect output from textual dumps.
More DWARF parser modification are coming in the next few weeks and I wanted to add tests that can verify that we can encode and decode all form types, as well as test some other basic DWARF APIs where we ask DIE objects for their children and siblings.
DwarfGenerator.cpp was added in the lib/CodeGen directory. This file contains the code necessary to easily create DWARF for tests:
dwarfgen::Generator DG;
Triple Triple("x86_64--");
bool success = DG.init(Triple, Version);
if (!success)
return;
dwarfgen::CompileUnit &CU = DG.addCompileUnit();
dwarfgen::DIE CUDie = CU.getUnitDIE();
CUDie.addAttribute(DW_AT_name, DW_FORM_strp, "/tmp/main.c");
CUDie.addAttribute(DW_AT_language, DW_FORM_data2, DW_LANG_C);
dwarfgen::DIE SubprogramDie = CUDie.addChild(DW_TAG_subprogram);
SubprogramDie.addAttribute(DW_AT_name, DW_FORM_strp, "main");
SubprogramDie.addAttribute(DW_AT_low_pc, DW_FORM_addr, 0x1000U);
SubprogramDie.addAttribute(DW_AT_high_pc, DW_FORM_addr, 0x2000U);
dwarfgen::DIE IntDie = CUDie.addChild(DW_TAG_base_type);
IntDie.addAttribute(DW_AT_name, DW_FORM_strp, "int");
IntDie.addAttribute(DW_AT_encoding, DW_FORM_data1, DW_ATE_signed);
IntDie.addAttribute(DW_AT_byte_size, DW_FORM_data1, 4);
dwarfgen::DIE ArgcDie = SubprogramDie.addChild(DW_TAG_formal_parameter);
ArgcDie.addAttribute(DW_AT_name, DW_FORM_strp, "argc");
// ArgcDie.addAttribute(DW_AT_type, DW_FORM_ref4, IntDie);
ArgcDie.addAttribute(DW_AT_type, DW_FORM_ref_addr, IntDie);
StringRef FileBytes = DG.generate();
MemoryBufferRef FileBuffer(FileBytes, "dwarf");
auto Obj = object::ObjectFile::createObjectFile(FileBuffer);
EXPECT_TRUE((bool)Obj);
DWARFContextInMemory DwarfContext(*Obj.get());
This code is backed by the AsmPrinter code that emits DWARF for the actual compiler.
While adding unit tests it was discovered that DIEValue that used DIEEntry as their values had bugs where DW_FORM_ref1, DW_FORM_ref2, DW_FORM_ref8, and DW_FORM_ref_udata forms were not supported. These are all now supported. Added support for DW_FORM_string so we can emit inlined C strings.
Centralized the code to unique abbreviations into a new DIEAbbrevSet class and made both the dwarfgen::Generator and the llvm::DwarfFile classes use the new class.
Fixed comments in the llvm::DIE class so that the Offset is known to be the compile/type unit offset.
DIEInteger now supports more DW_FORM values.
There are also unit tests that cover:
Encoding and decoding all form types and values
Encoding and decoding all reference types (DW_FORM_ref1, DW_FORM_ref2, DW_FORM_ref4, DW_FORM_ref8, DW_FORM_ref_udata, DW_FORM_ref_addr) including cross compile unit references with that go forward one compile unit and backward on compile unit.
Differential Revision: https://reviews.llvm.org/D27326
llvm-svn: 289010
2016-12-08 09:03:48 +08:00
|
|
|
case dwarf::DW_FORM_flag:
|
|
|
|
case dwarf::DW_FORM_ref1:
|
|
|
|
case dwarf::DW_FORM_data1:
|
2017-03-07 06:20:03 +08:00
|
|
|
case dwarf::DW_FORM_strx1:
|
|
|
|
case dwarf::DW_FORM_addrx1:
|
Make a DWARF generator so we can unit test DWARF APIs with gtest.
The only tests we have for the DWARF parser are the tests that use llvm-dwarfdump and expect output from textual dumps.
More DWARF parser modification are coming in the next few weeks and I wanted to add tests that can verify that we can encode and decode all form types, as well as test some other basic DWARF APIs where we ask DIE objects for their children and siblings.
DwarfGenerator.cpp was added in the lib/CodeGen directory. This file contains the code necessary to easily create DWARF for tests:
dwarfgen::Generator DG;
Triple Triple("x86_64--");
bool success = DG.init(Triple, Version);
if (!success)
return;
dwarfgen::CompileUnit &CU = DG.addCompileUnit();
dwarfgen::DIE CUDie = CU.getUnitDIE();
CUDie.addAttribute(DW_AT_name, DW_FORM_strp, "/tmp/main.c");
CUDie.addAttribute(DW_AT_language, DW_FORM_data2, DW_LANG_C);
dwarfgen::DIE SubprogramDie = CUDie.addChild(DW_TAG_subprogram);
SubprogramDie.addAttribute(DW_AT_name, DW_FORM_strp, "main");
SubprogramDie.addAttribute(DW_AT_low_pc, DW_FORM_addr, 0x1000U);
SubprogramDie.addAttribute(DW_AT_high_pc, DW_FORM_addr, 0x2000U);
dwarfgen::DIE IntDie = CUDie.addChild(DW_TAG_base_type);
IntDie.addAttribute(DW_AT_name, DW_FORM_strp, "int");
IntDie.addAttribute(DW_AT_encoding, DW_FORM_data1, DW_ATE_signed);
IntDie.addAttribute(DW_AT_byte_size, DW_FORM_data1, 4);
dwarfgen::DIE ArgcDie = SubprogramDie.addChild(DW_TAG_formal_parameter);
ArgcDie.addAttribute(DW_AT_name, DW_FORM_strp, "argc");
// ArgcDie.addAttribute(DW_AT_type, DW_FORM_ref4, IntDie);
ArgcDie.addAttribute(DW_AT_type, DW_FORM_ref_addr, IntDie);
StringRef FileBytes = DG.generate();
MemoryBufferRef FileBuffer(FileBytes, "dwarf");
auto Obj = object::ObjectFile::createObjectFile(FileBuffer);
EXPECT_TRUE((bool)Obj);
DWARFContextInMemory DwarfContext(*Obj.get());
This code is backed by the AsmPrinter code that emits DWARF for the actual compiler.
While adding unit tests it was discovered that DIEValue that used DIEEntry as their values had bugs where DW_FORM_ref1, DW_FORM_ref2, DW_FORM_ref8, and DW_FORM_ref_udata forms were not supported. These are all now supported. Added support for DW_FORM_string so we can emit inlined C strings.
Centralized the code to unique abbreviations into a new DIEAbbrevSet class and made both the dwarfgen::Generator and the llvm::DwarfFile classes use the new class.
Fixed comments in the llvm::DIE class so that the Offset is known to be the compile/type unit offset.
DIEInteger now supports more DW_FORM values.
There are also unit tests that cover:
Encoding and decoding all form types and values
Encoding and decoding all reference types (DW_FORM_ref1, DW_FORM_ref2, DW_FORM_ref4, DW_FORM_ref8, DW_FORM_ref_udata, DW_FORM_ref_addr) including cross compile unit references with that go forward one compile unit and backward on compile unit.
Differential Revision: https://reviews.llvm.org/D27326
llvm-svn: 289010
2016-12-08 09:03:48 +08:00
|
|
|
case dwarf::DW_FORM_ref2:
|
|
|
|
case dwarf::DW_FORM_data2:
|
2017-03-07 06:20:03 +08:00
|
|
|
case dwarf::DW_FORM_strx2:
|
|
|
|
case dwarf::DW_FORM_addrx2:
|
Make a DWARF generator so we can unit test DWARF APIs with gtest.
The only tests we have for the DWARF parser are the tests that use llvm-dwarfdump and expect output from textual dumps.
More DWARF parser modification are coming in the next few weeks and I wanted to add tests that can verify that we can encode and decode all form types, as well as test some other basic DWARF APIs where we ask DIE objects for their children and siblings.
DwarfGenerator.cpp was added in the lib/CodeGen directory. This file contains the code necessary to easily create DWARF for tests:
dwarfgen::Generator DG;
Triple Triple("x86_64--");
bool success = DG.init(Triple, Version);
if (!success)
return;
dwarfgen::CompileUnit &CU = DG.addCompileUnit();
dwarfgen::DIE CUDie = CU.getUnitDIE();
CUDie.addAttribute(DW_AT_name, DW_FORM_strp, "/tmp/main.c");
CUDie.addAttribute(DW_AT_language, DW_FORM_data2, DW_LANG_C);
dwarfgen::DIE SubprogramDie = CUDie.addChild(DW_TAG_subprogram);
SubprogramDie.addAttribute(DW_AT_name, DW_FORM_strp, "main");
SubprogramDie.addAttribute(DW_AT_low_pc, DW_FORM_addr, 0x1000U);
SubprogramDie.addAttribute(DW_AT_high_pc, DW_FORM_addr, 0x2000U);
dwarfgen::DIE IntDie = CUDie.addChild(DW_TAG_base_type);
IntDie.addAttribute(DW_AT_name, DW_FORM_strp, "int");
IntDie.addAttribute(DW_AT_encoding, DW_FORM_data1, DW_ATE_signed);
IntDie.addAttribute(DW_AT_byte_size, DW_FORM_data1, 4);
dwarfgen::DIE ArgcDie = SubprogramDie.addChild(DW_TAG_formal_parameter);
ArgcDie.addAttribute(DW_AT_name, DW_FORM_strp, "argc");
// ArgcDie.addAttribute(DW_AT_type, DW_FORM_ref4, IntDie);
ArgcDie.addAttribute(DW_AT_type, DW_FORM_ref_addr, IntDie);
StringRef FileBytes = DG.generate();
MemoryBufferRef FileBuffer(FileBytes, "dwarf");
auto Obj = object::ObjectFile::createObjectFile(FileBuffer);
EXPECT_TRUE((bool)Obj);
DWARFContextInMemory DwarfContext(*Obj.get());
This code is backed by the AsmPrinter code that emits DWARF for the actual compiler.
While adding unit tests it was discovered that DIEValue that used DIEEntry as their values had bugs where DW_FORM_ref1, DW_FORM_ref2, DW_FORM_ref8, and DW_FORM_ref_udata forms were not supported. These are all now supported. Added support for DW_FORM_string so we can emit inlined C strings.
Centralized the code to unique abbreviations into a new DIEAbbrevSet class and made both the dwarfgen::Generator and the llvm::DwarfFile classes use the new class.
Fixed comments in the llvm::DIE class so that the Offset is known to be the compile/type unit offset.
DIEInteger now supports more DW_FORM values.
There are also unit tests that cover:
Encoding and decoding all form types and values
Encoding and decoding all reference types (DW_FORM_ref1, DW_FORM_ref2, DW_FORM_ref4, DW_FORM_ref8, DW_FORM_ref_udata, DW_FORM_ref_addr) including cross compile unit references with that go forward one compile unit and backward on compile unit.
Differential Revision: https://reviews.llvm.org/D27326
llvm-svn: 289010
2016-12-08 09:03:48 +08:00
|
|
|
case dwarf::DW_FORM_strp:
|
|
|
|
case dwarf::DW_FORM_ref4:
|
|
|
|
case dwarf::DW_FORM_data4:
|
2017-03-07 06:20:03 +08:00
|
|
|
case dwarf::DW_FORM_ref_sup4:
|
|
|
|
case dwarf::DW_FORM_strx4:
|
|
|
|
case dwarf::DW_FORM_addrx4:
|
Make a DWARF generator so we can unit test DWARF APIs with gtest.
The only tests we have for the DWARF parser are the tests that use llvm-dwarfdump and expect output from textual dumps.
More DWARF parser modification are coming in the next few weeks and I wanted to add tests that can verify that we can encode and decode all form types, as well as test some other basic DWARF APIs where we ask DIE objects for their children and siblings.
DwarfGenerator.cpp was added in the lib/CodeGen directory. This file contains the code necessary to easily create DWARF for tests:
dwarfgen::Generator DG;
Triple Triple("x86_64--");
bool success = DG.init(Triple, Version);
if (!success)
return;
dwarfgen::CompileUnit &CU = DG.addCompileUnit();
dwarfgen::DIE CUDie = CU.getUnitDIE();
CUDie.addAttribute(DW_AT_name, DW_FORM_strp, "/tmp/main.c");
CUDie.addAttribute(DW_AT_language, DW_FORM_data2, DW_LANG_C);
dwarfgen::DIE SubprogramDie = CUDie.addChild(DW_TAG_subprogram);
SubprogramDie.addAttribute(DW_AT_name, DW_FORM_strp, "main");
SubprogramDie.addAttribute(DW_AT_low_pc, DW_FORM_addr, 0x1000U);
SubprogramDie.addAttribute(DW_AT_high_pc, DW_FORM_addr, 0x2000U);
dwarfgen::DIE IntDie = CUDie.addChild(DW_TAG_base_type);
IntDie.addAttribute(DW_AT_name, DW_FORM_strp, "int");
IntDie.addAttribute(DW_AT_encoding, DW_FORM_data1, DW_ATE_signed);
IntDie.addAttribute(DW_AT_byte_size, DW_FORM_data1, 4);
dwarfgen::DIE ArgcDie = SubprogramDie.addChild(DW_TAG_formal_parameter);
ArgcDie.addAttribute(DW_AT_name, DW_FORM_strp, "argc");
// ArgcDie.addAttribute(DW_AT_type, DW_FORM_ref4, IntDie);
ArgcDie.addAttribute(DW_AT_type, DW_FORM_ref_addr, IntDie);
StringRef FileBytes = DG.generate();
MemoryBufferRef FileBuffer(FileBytes, "dwarf");
auto Obj = object::ObjectFile::createObjectFile(FileBuffer);
EXPECT_TRUE((bool)Obj);
DWARFContextInMemory DwarfContext(*Obj.get());
This code is backed by the AsmPrinter code that emits DWARF for the actual compiler.
While adding unit tests it was discovered that DIEValue that used DIEEntry as their values had bugs where DW_FORM_ref1, DW_FORM_ref2, DW_FORM_ref8, and DW_FORM_ref_udata forms were not supported. These are all now supported. Added support for DW_FORM_string so we can emit inlined C strings.
Centralized the code to unique abbreviations into a new DIEAbbrevSet class and made both the dwarfgen::Generator and the llvm::DwarfFile classes use the new class.
Fixed comments in the llvm::DIE class so that the Offset is known to be the compile/type unit offset.
DIEInteger now supports more DW_FORM values.
There are also unit tests that cover:
Encoding and decoding all form types and values
Encoding and decoding all reference types (DW_FORM_ref1, DW_FORM_ref2, DW_FORM_ref4, DW_FORM_ref8, DW_FORM_ref_udata, DW_FORM_ref_addr) including cross compile unit references with that go forward one compile unit and backward on compile unit.
Differential Revision: https://reviews.llvm.org/D27326
llvm-svn: 289010
2016-12-08 09:03:48 +08:00
|
|
|
case dwarf::DW_FORM_ref8:
|
|
|
|
case dwarf::DW_FORM_ref_sig8:
|
|
|
|
case dwarf::DW_FORM_data8:
|
2017-03-07 06:20:03 +08:00
|
|
|
case dwarf::DW_FORM_ref_sup8:
|
Make a DWARF generator so we can unit test DWARF APIs with gtest.
The only tests we have for the DWARF parser are the tests that use llvm-dwarfdump and expect output from textual dumps.
More DWARF parser modification are coming in the next few weeks and I wanted to add tests that can verify that we can encode and decode all form types, as well as test some other basic DWARF APIs where we ask DIE objects for their children and siblings.
DwarfGenerator.cpp was added in the lib/CodeGen directory. This file contains the code necessary to easily create DWARF for tests:
dwarfgen::Generator DG;
Triple Triple("x86_64--");
bool success = DG.init(Triple, Version);
if (!success)
return;
dwarfgen::CompileUnit &CU = DG.addCompileUnit();
dwarfgen::DIE CUDie = CU.getUnitDIE();
CUDie.addAttribute(DW_AT_name, DW_FORM_strp, "/tmp/main.c");
CUDie.addAttribute(DW_AT_language, DW_FORM_data2, DW_LANG_C);
dwarfgen::DIE SubprogramDie = CUDie.addChild(DW_TAG_subprogram);
SubprogramDie.addAttribute(DW_AT_name, DW_FORM_strp, "main");
SubprogramDie.addAttribute(DW_AT_low_pc, DW_FORM_addr, 0x1000U);
SubprogramDie.addAttribute(DW_AT_high_pc, DW_FORM_addr, 0x2000U);
dwarfgen::DIE IntDie = CUDie.addChild(DW_TAG_base_type);
IntDie.addAttribute(DW_AT_name, DW_FORM_strp, "int");
IntDie.addAttribute(DW_AT_encoding, DW_FORM_data1, DW_ATE_signed);
IntDie.addAttribute(DW_AT_byte_size, DW_FORM_data1, 4);
dwarfgen::DIE ArgcDie = SubprogramDie.addChild(DW_TAG_formal_parameter);
ArgcDie.addAttribute(DW_AT_name, DW_FORM_strp, "argc");
// ArgcDie.addAttribute(DW_AT_type, DW_FORM_ref4, IntDie);
ArgcDie.addAttribute(DW_AT_type, DW_FORM_ref_addr, IntDie);
StringRef FileBytes = DG.generate();
MemoryBufferRef FileBuffer(FileBytes, "dwarf");
auto Obj = object::ObjectFile::createObjectFile(FileBuffer);
EXPECT_TRUE((bool)Obj);
DWARFContextInMemory DwarfContext(*Obj.get());
This code is backed by the AsmPrinter code that emits DWARF for the actual compiler.
While adding unit tests it was discovered that DIEValue that used DIEEntry as their values had bugs where DW_FORM_ref1, DW_FORM_ref2, DW_FORM_ref8, and DW_FORM_ref_udata forms were not supported. These are all now supported. Added support for DW_FORM_string so we can emit inlined C strings.
Centralized the code to unique abbreviations into a new DIEAbbrevSet class and made both the dwarfgen::Generator and the llvm::DwarfFile classes use the new class.
Fixed comments in the llvm::DIE class so that the Offset is known to be the compile/type unit offset.
DIEInteger now supports more DW_FORM values.
There are also unit tests that cover:
Encoding and decoding all form types and values
Encoding and decoding all reference types (DW_FORM_ref1, DW_FORM_ref2, DW_FORM_ref4, DW_FORM_ref8, DW_FORM_ref_udata, DW_FORM_ref_addr) including cross compile unit references with that go forward one compile unit and backward on compile unit.
Differential Revision: https://reviews.llvm.org/D27326
llvm-svn: 289010
2016-12-08 09:03:48 +08:00
|
|
|
case dwarf::DW_FORM_GNU_ref_alt:
|
|
|
|
case dwarf::DW_FORM_GNU_strp_alt:
|
|
|
|
case dwarf::DW_FORM_line_strp:
|
|
|
|
case dwarf::DW_FORM_sec_offset:
|
|
|
|
case dwarf::DW_FORM_strp_sup:
|
2012-09-11 07:34:03 +08:00
|
|
|
case dwarf::DW_FORM_addr:
|
2015-03-05 06:07:36 +08:00
|
|
|
case dwarf::DW_FORM_ref_addr:
|
Make a DWARF generator so we can unit test DWARF APIs with gtest.
The only tests we have for the DWARF parser are the tests that use llvm-dwarfdump and expect output from textual dumps.
More DWARF parser modification are coming in the next few weeks and I wanted to add tests that can verify that we can encode and decode all form types, as well as test some other basic DWARF APIs where we ask DIE objects for their children and siblings.
DwarfGenerator.cpp was added in the lib/CodeGen directory. This file contains the code necessary to easily create DWARF for tests:
dwarfgen::Generator DG;
Triple Triple("x86_64--");
bool success = DG.init(Triple, Version);
if (!success)
return;
dwarfgen::CompileUnit &CU = DG.addCompileUnit();
dwarfgen::DIE CUDie = CU.getUnitDIE();
CUDie.addAttribute(DW_AT_name, DW_FORM_strp, "/tmp/main.c");
CUDie.addAttribute(DW_AT_language, DW_FORM_data2, DW_LANG_C);
dwarfgen::DIE SubprogramDie = CUDie.addChild(DW_TAG_subprogram);
SubprogramDie.addAttribute(DW_AT_name, DW_FORM_strp, "main");
SubprogramDie.addAttribute(DW_AT_low_pc, DW_FORM_addr, 0x1000U);
SubprogramDie.addAttribute(DW_AT_high_pc, DW_FORM_addr, 0x2000U);
dwarfgen::DIE IntDie = CUDie.addChild(DW_TAG_base_type);
IntDie.addAttribute(DW_AT_name, DW_FORM_strp, "int");
IntDie.addAttribute(DW_AT_encoding, DW_FORM_data1, DW_ATE_signed);
IntDie.addAttribute(DW_AT_byte_size, DW_FORM_data1, 4);
dwarfgen::DIE ArgcDie = SubprogramDie.addChild(DW_TAG_formal_parameter);
ArgcDie.addAttribute(DW_AT_name, DW_FORM_strp, "argc");
// ArgcDie.addAttribute(DW_AT_type, DW_FORM_ref4, IntDie);
ArgcDie.addAttribute(DW_AT_type, DW_FORM_ref_addr, IntDie);
StringRef FileBytes = DG.generate();
MemoryBufferRef FileBuffer(FileBytes, "dwarf");
auto Obj = object::ObjectFile::createObjectFile(FileBuffer);
EXPECT_TRUE((bool)Obj);
DWARFContextInMemory DwarfContext(*Obj.get());
This code is backed by the AsmPrinter code that emits DWARF for the actual compiler.
While adding unit tests it was discovered that DIEValue that used DIEEntry as their values had bugs where DW_FORM_ref1, DW_FORM_ref2, DW_FORM_ref8, and DW_FORM_ref_udata forms were not supported. These are all now supported. Added support for DW_FORM_string so we can emit inlined C strings.
Centralized the code to unique abbreviations into a new DIEAbbrevSet class and made both the dwarfgen::Generator and the llvm::DwarfFile classes use the new class.
Fixed comments in the llvm::DIE class so that the Offset is known to be the compile/type unit offset.
DIEInteger now supports more DW_FORM values.
There are also unit tests that cover:
Encoding and decoding all form types and values
Encoding and decoding all reference types (DW_FORM_ref1, DW_FORM_ref2, DW_FORM_ref4, DW_FORM_ref8, DW_FORM_ref_udata, DW_FORM_ref_addr) including cross compile unit references with that go forward one compile unit and backward on compile unit.
Differential Revision: https://reviews.llvm.org/D27326
llvm-svn: 289010
2016-12-08 09:03:48 +08:00
|
|
|
Asm->OutStreamer->EmitIntValue(Integer, SizeOf(Asm, Form));
|
|
|
|
return;
|
|
|
|
case dwarf::DW_FORM_GNU_str_index:
|
|
|
|
case dwarf::DW_FORM_GNU_addr_index:
|
|
|
|
case dwarf::DW_FORM_ref_udata:
|
|
|
|
case dwarf::DW_FORM_udata:
|
|
|
|
Asm->EmitULEB128(Integer);
|
|
|
|
return;
|
|
|
|
case dwarf::DW_FORM_sdata:
|
|
|
|
Asm->EmitSLEB128(Integer);
|
|
|
|
return;
|
2009-07-15 00:55:14 +08:00
|
|
|
default: llvm_unreachable("DIE Value form not supported yet");
|
2009-05-15 08:11:17 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// SizeOf - Determine size of integer value in bytes.
|
|
|
|
///
|
Reapply "AsmPrinter: Change DIEValue to be stored by value"
This reverts commit r238350, effectively reapplying r238349 after fixing
(all?) the problems, all somehow related to how I was using
`AlignedArrayCharUnion<>` inside `DIEValue`:
- MSVC can only handle `sizeof()` on types, not values. Change the
assert.
- GCC doesn't know the `is_trivially_copyable` type trait. Instead of
asserting it, add destructors.
- Call placement new even when constructing POD (i.e., the pointers).
- Instead of copying the char buffer, copy the casted classes.
I've left in a couple of `static_assert`s that I think both MSVC and GCC
know how to handle. If the bots disagree with me, I'll remove them.
- Check that the constructed type is either standard layout or a
pointer. This protects against a programming error: we really want
the "small" `DIEValue`s to be small and simple, so don't
accidentally change them not to be.
- Similarly, check that the size of the buffer is no bigger than a
`uint64_t` or a pointer. (I thought checking against
`sizeof(uint64_t)` would be good enough, but Chandler suggested that
pointers might sometimes be bigger than that in the context of
sanitizers.)
I've also committed r238359 in the meantime, which introduces a
DIEValue.def to simplify dispatching between the various types (thanks
to a review comment by David Blaikie). Without that, this commit would
be almost unintelligible.
Here's the original commit message:
--
Change `DIEValue` to be stored/passed/etc. by value, instead of
reference. It's now a discriminated union, with a `Val` field storing
the actual type. The classes that used to inherit from `DIEValue` no
longer do. There are two categories of these:
- Small values fit in a single pointer and are stored by value.
- Large values require auxiliary storage, and are stored by reference.
The only non-mechanical change is to tools/dsymutil/DwarfLinker.cpp. It
was relying on `DIEInteger`s being passed around by reference, so I
replaced that assumption with a `PatchLocation` type that stores a safe
reference to where the `DIEInteger` lives instead.
This commit causes a temporary regression in memory usage, since I've
left merging `DIEAbbrevData` into `DIEValue` for a follow-up commit. I
measured an increase from 845 MB to 879 MB, around 3.9%. The follow-up
drops it lower than the starting point, and I've only recently brought
the memory this low anyway, so I'm committing these changes separately
to keep them incremental. (I also considered swapping the commits, but
the other one first would cause a lot more code churn.)
(I'm looking at `llc` memory usage on `verify-uselistorder.lto.opt.bc`;
see r236629 for details.)
--
llvm-svn: 238362
2015-05-28 06:14:58 +08:00
|
|
|
unsigned DIEInteger::SizeOf(const AsmPrinter *AP, dwarf::Form Form) const {
|
2009-05-15 08:11:17 +08:00
|
|
|
switch (Form) {
|
2017-03-02 07:59:11 +08:00
|
|
|
case dwarf::DW_FORM_implicit_const:
|
|
|
|
case dwarf::DW_FORM_flag_present:
|
|
|
|
return 0;
|
|
|
|
case dwarf::DW_FORM_flag:
|
|
|
|
case dwarf::DW_FORM_ref1:
|
|
|
|
case dwarf::DW_FORM_data1:
|
2017-03-07 06:20:03 +08:00
|
|
|
case dwarf::DW_FORM_strx1:
|
|
|
|
case dwarf::DW_FORM_addrx1:
|
2017-03-02 07:59:11 +08:00
|
|
|
return sizeof(int8_t);
|
|
|
|
case dwarf::DW_FORM_ref2:
|
|
|
|
case dwarf::DW_FORM_data2:
|
2017-03-07 06:20:03 +08:00
|
|
|
case dwarf::DW_FORM_strx2:
|
|
|
|
case dwarf::DW_FORM_addrx2:
|
2017-03-02 07:59:11 +08:00
|
|
|
return sizeof(int16_t);
|
|
|
|
case dwarf::DW_FORM_ref4:
|
|
|
|
case dwarf::DW_FORM_data4:
|
2017-03-07 06:20:03 +08:00
|
|
|
case dwarf::DW_FORM_ref_sup4:
|
|
|
|
case dwarf::DW_FORM_strx4:
|
|
|
|
case dwarf::DW_FORM_addrx4:
|
2017-03-02 07:59:11 +08:00
|
|
|
return sizeof(int32_t);
|
|
|
|
case dwarf::DW_FORM_ref8:
|
|
|
|
case dwarf::DW_FORM_ref_sig8:
|
|
|
|
case dwarf::DW_FORM_data8:
|
2017-03-07 06:20:03 +08:00
|
|
|
case dwarf::DW_FORM_ref_sup8:
|
2017-03-02 07:59:11 +08:00
|
|
|
return sizeof(int64_t);
|
2015-03-05 06:07:36 +08:00
|
|
|
case dwarf::DW_FORM_ref_addr:
|
2016-11-24 07:30:37 +08:00
|
|
|
if (AP->getDwarfVersion() == 2)
|
2015-07-16 13:59:25 +08:00
|
|
|
return AP->getPointerSize();
|
Make a DWARF generator so we can unit test DWARF APIs with gtest.
The only tests we have for the DWARF parser are the tests that use llvm-dwarfdump and expect output from textual dumps.
More DWARF parser modification are coming in the next few weeks and I wanted to add tests that can verify that we can encode and decode all form types, as well as test some other basic DWARF APIs where we ask DIE objects for their children and siblings.
DwarfGenerator.cpp was added in the lib/CodeGen directory. This file contains the code necessary to easily create DWARF for tests:
dwarfgen::Generator DG;
Triple Triple("x86_64--");
bool success = DG.init(Triple, Version);
if (!success)
return;
dwarfgen::CompileUnit &CU = DG.addCompileUnit();
dwarfgen::DIE CUDie = CU.getUnitDIE();
CUDie.addAttribute(DW_AT_name, DW_FORM_strp, "/tmp/main.c");
CUDie.addAttribute(DW_AT_language, DW_FORM_data2, DW_LANG_C);
dwarfgen::DIE SubprogramDie = CUDie.addChild(DW_TAG_subprogram);
SubprogramDie.addAttribute(DW_AT_name, DW_FORM_strp, "main");
SubprogramDie.addAttribute(DW_AT_low_pc, DW_FORM_addr, 0x1000U);
SubprogramDie.addAttribute(DW_AT_high_pc, DW_FORM_addr, 0x2000U);
dwarfgen::DIE IntDie = CUDie.addChild(DW_TAG_base_type);
IntDie.addAttribute(DW_AT_name, DW_FORM_strp, "int");
IntDie.addAttribute(DW_AT_encoding, DW_FORM_data1, DW_ATE_signed);
IntDie.addAttribute(DW_AT_byte_size, DW_FORM_data1, 4);
dwarfgen::DIE ArgcDie = SubprogramDie.addChild(DW_TAG_formal_parameter);
ArgcDie.addAttribute(DW_AT_name, DW_FORM_strp, "argc");
// ArgcDie.addAttribute(DW_AT_type, DW_FORM_ref4, IntDie);
ArgcDie.addAttribute(DW_AT_type, DW_FORM_ref_addr, IntDie);
StringRef FileBytes = DG.generate();
MemoryBufferRef FileBuffer(FileBytes, "dwarf");
auto Obj = object::ObjectFile::createObjectFile(FileBuffer);
EXPECT_TRUE((bool)Obj);
DWARFContextInMemory DwarfContext(*Obj.get());
This code is backed by the AsmPrinter code that emits DWARF for the actual compiler.
While adding unit tests it was discovered that DIEValue that used DIEEntry as their values had bugs where DW_FORM_ref1, DW_FORM_ref2, DW_FORM_ref8, and DW_FORM_ref_udata forms were not supported. These are all now supported. Added support for DW_FORM_string so we can emit inlined C strings.
Centralized the code to unique abbreviations into a new DIEAbbrevSet class and made both the dwarfgen::Generator and the llvm::DwarfFile classes use the new class.
Fixed comments in the llvm::DIE class so that the Offset is known to be the compile/type unit offset.
DIEInteger now supports more DW_FORM values.
There are also unit tests that cover:
Encoding and decoding all form types and values
Encoding and decoding all reference types (DW_FORM_ref1, DW_FORM_ref2, DW_FORM_ref4, DW_FORM_ref8, DW_FORM_ref_udata, DW_FORM_ref_addr) including cross compile unit references with that go forward one compile unit and backward on compile unit.
Differential Revision: https://reviews.llvm.org/D27326
llvm-svn: 289010
2016-12-08 09:03:48 +08:00
|
|
|
LLVM_FALLTHROUGH;
|
|
|
|
case dwarf::DW_FORM_strp:
|
|
|
|
case dwarf::DW_FORM_GNU_ref_alt:
|
|
|
|
case dwarf::DW_FORM_GNU_strp_alt:
|
|
|
|
case dwarf::DW_FORM_line_strp:
|
|
|
|
case dwarf::DW_FORM_sec_offset:
|
|
|
|
case dwarf::DW_FORM_strp_sup:
|
|
|
|
switch (AP->OutStreamer->getContext().getDwarfFormat()) {
|
|
|
|
case dwarf::DWARF32:
|
|
|
|
return 4;
|
|
|
|
case dwarf::DWARF64:
|
|
|
|
return 8;
|
|
|
|
}
|
|
|
|
llvm_unreachable("Invalid DWARF format");
|
|
|
|
case dwarf::DW_FORM_GNU_str_index:
|
|
|
|
case dwarf::DW_FORM_GNU_addr_index:
|
|
|
|
case dwarf::DW_FORM_ref_udata:
|
|
|
|
case dwarf::DW_FORM_udata:
|
|
|
|
return getULEB128Size(Integer);
|
|
|
|
case dwarf::DW_FORM_sdata:
|
|
|
|
return getSLEB128Size(Integer);
|
|
|
|
case dwarf::DW_FORM_addr:
|
|
|
|
return AP->getPointerSize();
|
2012-01-21 05:51:11 +08:00
|
|
|
default: llvm_unreachable("DIE Value form not supported yet");
|
2009-05-15 08:11:17 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-11-24 10:21:43 +08:00
|
|
|
LLVM_DUMP_METHOD
|
Reapply "AsmPrinter: Change DIEValue to be stored by value"
This reverts commit r238350, effectively reapplying r238349 after fixing
(all?) the problems, all somehow related to how I was using
`AlignedArrayCharUnion<>` inside `DIEValue`:
- MSVC can only handle `sizeof()` on types, not values. Change the
assert.
- GCC doesn't know the `is_trivially_copyable` type trait. Instead of
asserting it, add destructors.
- Call placement new even when constructing POD (i.e., the pointers).
- Instead of copying the char buffer, copy the casted classes.
I've left in a couple of `static_assert`s that I think both MSVC and GCC
know how to handle. If the bots disagree with me, I'll remove them.
- Check that the constructed type is either standard layout or a
pointer. This protects against a programming error: we really want
the "small" `DIEValue`s to be small and simple, so don't
accidentally change them not to be.
- Similarly, check that the size of the buffer is no bigger than a
`uint64_t` or a pointer. (I thought checking against
`sizeof(uint64_t)` would be good enough, but Chandler suggested that
pointers might sometimes be bigger than that in the context of
sanitizers.)
I've also committed r238359 in the meantime, which introduces a
DIEValue.def to simplify dispatching between the various types (thanks
to a review comment by David Blaikie). Without that, this commit would
be almost unintelligible.
Here's the original commit message:
--
Change `DIEValue` to be stored/passed/etc. by value, instead of
reference. It's now a discriminated union, with a `Val` field storing
the actual type. The classes that used to inherit from `DIEValue` no
longer do. There are two categories of these:
- Small values fit in a single pointer and are stored by value.
- Large values require auxiliary storage, and are stored by reference.
The only non-mechanical change is to tools/dsymutil/DwarfLinker.cpp. It
was relying on `DIEInteger`s being passed around by reference, so I
replaced that assumption with a `PatchLocation` type that stores a safe
reference to where the `DIEInteger` lives instead.
This commit causes a temporary regression in memory usage, since I've
left merging `DIEAbbrevData` into `DIEValue` for a follow-up commit. I
measured an increase from 845 MB to 879 MB, around 3.9%. The follow-up
drops it lower than the starting point, and I've only recently brought
the memory this low anyway, so I'm committing these changes separately
to keep them incremental. (I also considered swapping the commits, but
the other one first would cause a lot more code churn.)
(I'm looking at `llc` memory usage on `verify-uselistorder.lto.opt.bc`;
see r236629 for details.)
--
llvm-svn: 238362
2015-05-28 06:14:58 +08:00
|
|
|
void DIEInteger::print(raw_ostream &O) const {
|
2011-11-05 16:57:40 +08:00
|
|
|
O << "Int: " << (int64_t)Integer << " 0x";
|
|
|
|
O.write_hex(Integer);
|
2009-05-15 08:11:17 +08:00
|
|
|
}
|
|
|
|
|
2013-07-03 02:46:26 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// DIEExpr Implementation
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
/// EmitValue - Emit expression value.
|
|
|
|
///
|
Reapply "AsmPrinter: Change DIEValue to be stored by value"
This reverts commit r238350, effectively reapplying r238349 after fixing
(all?) the problems, all somehow related to how I was using
`AlignedArrayCharUnion<>` inside `DIEValue`:
- MSVC can only handle `sizeof()` on types, not values. Change the
assert.
- GCC doesn't know the `is_trivially_copyable` type trait. Instead of
asserting it, add destructors.
- Call placement new even when constructing POD (i.e., the pointers).
- Instead of copying the char buffer, copy the casted classes.
I've left in a couple of `static_assert`s that I think both MSVC and GCC
know how to handle. If the bots disagree with me, I'll remove them.
- Check that the constructed type is either standard layout or a
pointer. This protects against a programming error: we really want
the "small" `DIEValue`s to be small and simple, so don't
accidentally change them not to be.
- Similarly, check that the size of the buffer is no bigger than a
`uint64_t` or a pointer. (I thought checking against
`sizeof(uint64_t)` would be good enough, but Chandler suggested that
pointers might sometimes be bigger than that in the context of
sanitizers.)
I've also committed r238359 in the meantime, which introduces a
DIEValue.def to simplify dispatching between the various types (thanks
to a review comment by David Blaikie). Without that, this commit would
be almost unintelligible.
Here's the original commit message:
--
Change `DIEValue` to be stored/passed/etc. by value, instead of
reference. It's now a discriminated union, with a `Val` field storing
the actual type. The classes that used to inherit from `DIEValue` no
longer do. There are two categories of these:
- Small values fit in a single pointer and are stored by value.
- Large values require auxiliary storage, and are stored by reference.
The only non-mechanical change is to tools/dsymutil/DwarfLinker.cpp. It
was relying on `DIEInteger`s being passed around by reference, so I
replaced that assumption with a `PatchLocation` type that stores a safe
reference to where the `DIEInteger` lives instead.
This commit causes a temporary regression in memory usage, since I've
left merging `DIEAbbrevData` into `DIEValue` for a follow-up commit. I
measured an increase from 845 MB to 879 MB, around 3.9%. The follow-up
drops it lower than the starting point, and I've only recently brought
the memory this low anyway, so I'm committing these changes separately
to keep them incremental. (I also considered swapping the commits, but
the other one first would cause a lot more code churn.)
(I'm looking at `llc` memory usage on `verify-uselistorder.lto.opt.bc`;
see r236629 for details.)
--
llvm-svn: 238362
2015-05-28 06:14:58 +08:00
|
|
|
void DIEExpr::EmitValue(const AsmPrinter *AP, dwarf::Form Form) const {
|
2017-02-09 03:03:46 +08:00
|
|
|
AP->EmitDebugThreadLocal(Expr, SizeOf(AP, Form));
|
2013-07-03 02:46:26 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/// SizeOf - Determine size of expression value in bytes.
|
|
|
|
///
|
Reapply "AsmPrinter: Change DIEValue to be stored by value"
This reverts commit r238350, effectively reapplying r238349 after fixing
(all?) the problems, all somehow related to how I was using
`AlignedArrayCharUnion<>` inside `DIEValue`:
- MSVC can only handle `sizeof()` on types, not values. Change the
assert.
- GCC doesn't know the `is_trivially_copyable` type trait. Instead of
asserting it, add destructors.
- Call placement new even when constructing POD (i.e., the pointers).
- Instead of copying the char buffer, copy the casted classes.
I've left in a couple of `static_assert`s that I think both MSVC and GCC
know how to handle. If the bots disagree with me, I'll remove them.
- Check that the constructed type is either standard layout or a
pointer. This protects against a programming error: we really want
the "small" `DIEValue`s to be small and simple, so don't
accidentally change them not to be.
- Similarly, check that the size of the buffer is no bigger than a
`uint64_t` or a pointer. (I thought checking against
`sizeof(uint64_t)` would be good enough, but Chandler suggested that
pointers might sometimes be bigger than that in the context of
sanitizers.)
I've also committed r238359 in the meantime, which introduces a
DIEValue.def to simplify dispatching between the various types (thanks
to a review comment by David Blaikie). Without that, this commit would
be almost unintelligible.
Here's the original commit message:
--
Change `DIEValue` to be stored/passed/etc. by value, instead of
reference. It's now a discriminated union, with a `Val` field storing
the actual type. The classes that used to inherit from `DIEValue` no
longer do. There are two categories of these:
- Small values fit in a single pointer and are stored by value.
- Large values require auxiliary storage, and are stored by reference.
The only non-mechanical change is to tools/dsymutil/DwarfLinker.cpp. It
was relying on `DIEInteger`s being passed around by reference, so I
replaced that assumption with a `PatchLocation` type that stores a safe
reference to where the `DIEInteger` lives instead.
This commit causes a temporary regression in memory usage, since I've
left merging `DIEAbbrevData` into `DIEValue` for a follow-up commit. I
measured an increase from 845 MB to 879 MB, around 3.9%. The follow-up
drops it lower than the starting point, and I've only recently brought
the memory this low anyway, so I'm committing these changes separately
to keep them incremental. (I also considered swapping the commits, but
the other one first would cause a lot more code churn.)
(I'm looking at `llc` memory usage on `verify-uselistorder.lto.opt.bc`;
see r236629 for details.)
--
llvm-svn: 238362
2015-05-28 06:14:58 +08:00
|
|
|
unsigned DIEExpr::SizeOf(const AsmPrinter *AP, dwarf::Form Form) const {
|
2013-07-03 02:46:26 +08:00
|
|
|
if (Form == dwarf::DW_FORM_data4) return 4;
|
|
|
|
if (Form == dwarf::DW_FORM_sec_offset) return 4;
|
|
|
|
if (Form == dwarf::DW_FORM_strp) return 4;
|
2015-07-16 13:59:25 +08:00
|
|
|
return AP->getPointerSize();
|
2013-07-03 02:46:26 +08:00
|
|
|
}
|
|
|
|
|
2015-11-24 10:21:43 +08:00
|
|
|
LLVM_DUMP_METHOD
|
Reapply "AsmPrinter: Change DIEValue to be stored by value"
This reverts commit r238350, effectively reapplying r238349 after fixing
(all?) the problems, all somehow related to how I was using
`AlignedArrayCharUnion<>` inside `DIEValue`:
- MSVC can only handle `sizeof()` on types, not values. Change the
assert.
- GCC doesn't know the `is_trivially_copyable` type trait. Instead of
asserting it, add destructors.
- Call placement new even when constructing POD (i.e., the pointers).
- Instead of copying the char buffer, copy the casted classes.
I've left in a couple of `static_assert`s that I think both MSVC and GCC
know how to handle. If the bots disagree with me, I'll remove them.
- Check that the constructed type is either standard layout or a
pointer. This protects against a programming error: we really want
the "small" `DIEValue`s to be small and simple, so don't
accidentally change them not to be.
- Similarly, check that the size of the buffer is no bigger than a
`uint64_t` or a pointer. (I thought checking against
`sizeof(uint64_t)` would be good enough, but Chandler suggested that
pointers might sometimes be bigger than that in the context of
sanitizers.)
I've also committed r238359 in the meantime, which introduces a
DIEValue.def to simplify dispatching between the various types (thanks
to a review comment by David Blaikie). Without that, this commit would
be almost unintelligible.
Here's the original commit message:
--
Change `DIEValue` to be stored/passed/etc. by value, instead of
reference. It's now a discriminated union, with a `Val` field storing
the actual type. The classes that used to inherit from `DIEValue` no
longer do. There are two categories of these:
- Small values fit in a single pointer and are stored by value.
- Large values require auxiliary storage, and are stored by reference.
The only non-mechanical change is to tools/dsymutil/DwarfLinker.cpp. It
was relying on `DIEInteger`s being passed around by reference, so I
replaced that assumption with a `PatchLocation` type that stores a safe
reference to where the `DIEInteger` lives instead.
This commit causes a temporary regression in memory usage, since I've
left merging `DIEAbbrevData` into `DIEValue` for a follow-up commit. I
measured an increase from 845 MB to 879 MB, around 3.9%. The follow-up
drops it lower than the starting point, and I've only recently brought
the memory this low anyway, so I'm committing these changes separately
to keep them incremental. (I also considered swapping the commits, but
the other one first would cause a lot more code churn.)
(I'm looking at `llc` memory usage on `verify-uselistorder.lto.opt.bc`;
see r236629 for details.)
--
llvm-svn: 238362
2015-05-28 06:14:58 +08:00
|
|
|
void DIEExpr::print(raw_ostream &O) const { O << "Expr: " << *Expr; }
|
2013-07-03 02:46:26 +08:00
|
|
|
|
2009-05-15 08:11:17 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
2010-03-09 06:31:46 +08:00
|
|
|
// DIELabel Implementation
|
2009-05-15 08:11:17 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
/// EmitValue - Emit label value.
|
|
|
|
///
|
Reapply "AsmPrinter: Change DIEValue to be stored by value"
This reverts commit r238350, effectively reapplying r238349 after fixing
(all?) the problems, all somehow related to how I was using
`AlignedArrayCharUnion<>` inside `DIEValue`:
- MSVC can only handle `sizeof()` on types, not values. Change the
assert.
- GCC doesn't know the `is_trivially_copyable` type trait. Instead of
asserting it, add destructors.
- Call placement new even when constructing POD (i.e., the pointers).
- Instead of copying the char buffer, copy the casted classes.
I've left in a couple of `static_assert`s that I think both MSVC and GCC
know how to handle. If the bots disagree with me, I'll remove them.
- Check that the constructed type is either standard layout or a
pointer. This protects against a programming error: we really want
the "small" `DIEValue`s to be small and simple, so don't
accidentally change them not to be.
- Similarly, check that the size of the buffer is no bigger than a
`uint64_t` or a pointer. (I thought checking against
`sizeof(uint64_t)` would be good enough, but Chandler suggested that
pointers might sometimes be bigger than that in the context of
sanitizers.)
I've also committed r238359 in the meantime, which introduces a
DIEValue.def to simplify dispatching between the various types (thanks
to a review comment by David Blaikie). Without that, this commit would
be almost unintelligible.
Here's the original commit message:
--
Change `DIEValue` to be stored/passed/etc. by value, instead of
reference. It's now a discriminated union, with a `Val` field storing
the actual type. The classes that used to inherit from `DIEValue` no
longer do. There are two categories of these:
- Small values fit in a single pointer and are stored by value.
- Large values require auxiliary storage, and are stored by reference.
The only non-mechanical change is to tools/dsymutil/DwarfLinker.cpp. It
was relying on `DIEInteger`s being passed around by reference, so I
replaced that assumption with a `PatchLocation` type that stores a safe
reference to where the `DIEInteger` lives instead.
This commit causes a temporary regression in memory usage, since I've
left merging `DIEAbbrevData` into `DIEValue` for a follow-up commit. I
measured an increase from 845 MB to 879 MB, around 3.9%. The follow-up
drops it lower than the starting point, and I've only recently brought
the memory this low anyway, so I'm committing these changes separately
to keep them incremental. (I also considered swapping the commits, but
the other one first would cause a lot more code churn.)
(I'm looking at `llc` memory usage on `verify-uselistorder.lto.opt.bc`;
see r236629 for details.)
--
llvm-svn: 238362
2015-05-28 06:14:58 +08:00
|
|
|
void DIELabel::EmitValue(const AsmPrinter *AP, dwarf::Form Form) const {
|
2013-10-22 01:28:37 +08:00
|
|
|
AP->EmitLabelReference(Label, SizeOf(AP, Form),
|
|
|
|
Form == dwarf::DW_FORM_strp ||
|
|
|
|
Form == dwarf::DW_FORM_sec_offset ||
|
2017-01-02 11:00:19 +08:00
|
|
|
Form == dwarf::DW_FORM_ref_addr ||
|
|
|
|
Form == dwarf::DW_FORM_data4);
|
2009-05-15 08:11:17 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/// SizeOf - Determine size of label value in bytes.
|
|
|
|
///
|
Reapply "AsmPrinter: Change DIEValue to be stored by value"
This reverts commit r238350, effectively reapplying r238349 after fixing
(all?) the problems, all somehow related to how I was using
`AlignedArrayCharUnion<>` inside `DIEValue`:
- MSVC can only handle `sizeof()` on types, not values. Change the
assert.
- GCC doesn't know the `is_trivially_copyable` type trait. Instead of
asserting it, add destructors.
- Call placement new even when constructing POD (i.e., the pointers).
- Instead of copying the char buffer, copy the casted classes.
I've left in a couple of `static_assert`s that I think both MSVC and GCC
know how to handle. If the bots disagree with me, I'll remove them.
- Check that the constructed type is either standard layout or a
pointer. This protects against a programming error: we really want
the "small" `DIEValue`s to be small and simple, so don't
accidentally change them not to be.
- Similarly, check that the size of the buffer is no bigger than a
`uint64_t` or a pointer. (I thought checking against
`sizeof(uint64_t)` would be good enough, but Chandler suggested that
pointers might sometimes be bigger than that in the context of
sanitizers.)
I've also committed r238359 in the meantime, which introduces a
DIEValue.def to simplify dispatching between the various types (thanks
to a review comment by David Blaikie). Without that, this commit would
be almost unintelligible.
Here's the original commit message:
--
Change `DIEValue` to be stored/passed/etc. by value, instead of
reference. It's now a discriminated union, with a `Val` field storing
the actual type. The classes that used to inherit from `DIEValue` no
longer do. There are two categories of these:
- Small values fit in a single pointer and are stored by value.
- Large values require auxiliary storage, and are stored by reference.
The only non-mechanical change is to tools/dsymutil/DwarfLinker.cpp. It
was relying on `DIEInteger`s being passed around by reference, so I
replaced that assumption with a `PatchLocation` type that stores a safe
reference to where the `DIEInteger` lives instead.
This commit causes a temporary regression in memory usage, since I've
left merging `DIEAbbrevData` into `DIEValue` for a follow-up commit. I
measured an increase from 845 MB to 879 MB, around 3.9%. The follow-up
drops it lower than the starting point, and I've only recently brought
the memory this low anyway, so I'm committing these changes separately
to keep them incremental. (I also considered swapping the commits, but
the other one first would cause a lot more code churn.)
(I'm looking at `llc` memory usage on `verify-uselistorder.lto.opt.bc`;
see r236629 for details.)
--
llvm-svn: 238362
2015-05-28 06:14:58 +08:00
|
|
|
unsigned DIELabel::SizeOf(const AsmPrinter *AP, dwarf::Form Form) const {
|
2009-05-15 08:11:17 +08:00
|
|
|
if (Form == dwarf::DW_FORM_data4) return 4;
|
2013-01-17 11:00:04 +08:00
|
|
|
if (Form == dwarf::DW_FORM_sec_offset) return 4;
|
2011-10-27 14:44:11 +08:00
|
|
|
if (Form == dwarf::DW_FORM_strp) return 4;
|
2017-04-18 01:41:25 +08:00
|
|
|
return AP->MAI->getCodePointerSize();
|
2009-05-15 08:11:17 +08:00
|
|
|
}
|
|
|
|
|
2015-11-24 10:21:43 +08:00
|
|
|
LLVM_DUMP_METHOD
|
Reapply "AsmPrinter: Change DIEValue to be stored by value"
This reverts commit r238350, effectively reapplying r238349 after fixing
(all?) the problems, all somehow related to how I was using
`AlignedArrayCharUnion<>` inside `DIEValue`:
- MSVC can only handle `sizeof()` on types, not values. Change the
assert.
- GCC doesn't know the `is_trivially_copyable` type trait. Instead of
asserting it, add destructors.
- Call placement new even when constructing POD (i.e., the pointers).
- Instead of copying the char buffer, copy the casted classes.
I've left in a couple of `static_assert`s that I think both MSVC and GCC
know how to handle. If the bots disagree with me, I'll remove them.
- Check that the constructed type is either standard layout or a
pointer. This protects against a programming error: we really want
the "small" `DIEValue`s to be small and simple, so don't
accidentally change them not to be.
- Similarly, check that the size of the buffer is no bigger than a
`uint64_t` or a pointer. (I thought checking against
`sizeof(uint64_t)` would be good enough, but Chandler suggested that
pointers might sometimes be bigger than that in the context of
sanitizers.)
I've also committed r238359 in the meantime, which introduces a
DIEValue.def to simplify dispatching between the various types (thanks
to a review comment by David Blaikie). Without that, this commit would
be almost unintelligible.
Here's the original commit message:
--
Change `DIEValue` to be stored/passed/etc. by value, instead of
reference. It's now a discriminated union, with a `Val` field storing
the actual type. The classes that used to inherit from `DIEValue` no
longer do. There are two categories of these:
- Small values fit in a single pointer and are stored by value.
- Large values require auxiliary storage, and are stored by reference.
The only non-mechanical change is to tools/dsymutil/DwarfLinker.cpp. It
was relying on `DIEInteger`s being passed around by reference, so I
replaced that assumption with a `PatchLocation` type that stores a safe
reference to where the `DIEInteger` lives instead.
This commit causes a temporary regression in memory usage, since I've
left merging `DIEAbbrevData` into `DIEValue` for a follow-up commit. I
measured an increase from 845 MB to 879 MB, around 3.9%. The follow-up
drops it lower than the starting point, and I've only recently brought
the memory this low anyway, so I'm committing these changes separately
to keep them incremental. (I also considered swapping the commits, but
the other one first would cause a lot more code churn.)
(I'm looking at `llc` memory usage on `verify-uselistorder.lto.opt.bc`;
see r236629 for details.)
--
llvm-svn: 238362
2015-05-28 06:14:58 +08:00
|
|
|
void DIELabel::print(raw_ostream &O) const { O << "Lbl: " << Label->getName(); }
|
2009-05-15 08:11:17 +08:00
|
|
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// DIEDelta Implementation
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
/// EmitValue - Emit delta value.
|
|
|
|
///
|
Reapply "AsmPrinter: Change DIEValue to be stored by value"
This reverts commit r238350, effectively reapplying r238349 after fixing
(all?) the problems, all somehow related to how I was using
`AlignedArrayCharUnion<>` inside `DIEValue`:
- MSVC can only handle `sizeof()` on types, not values. Change the
assert.
- GCC doesn't know the `is_trivially_copyable` type trait. Instead of
asserting it, add destructors.
- Call placement new even when constructing POD (i.e., the pointers).
- Instead of copying the char buffer, copy the casted classes.
I've left in a couple of `static_assert`s that I think both MSVC and GCC
know how to handle. If the bots disagree with me, I'll remove them.
- Check that the constructed type is either standard layout or a
pointer. This protects against a programming error: we really want
the "small" `DIEValue`s to be small and simple, so don't
accidentally change them not to be.
- Similarly, check that the size of the buffer is no bigger than a
`uint64_t` or a pointer. (I thought checking against
`sizeof(uint64_t)` would be good enough, but Chandler suggested that
pointers might sometimes be bigger than that in the context of
sanitizers.)
I've also committed r238359 in the meantime, which introduces a
DIEValue.def to simplify dispatching between the various types (thanks
to a review comment by David Blaikie). Without that, this commit would
be almost unintelligible.
Here's the original commit message:
--
Change `DIEValue` to be stored/passed/etc. by value, instead of
reference. It's now a discriminated union, with a `Val` field storing
the actual type. The classes that used to inherit from `DIEValue` no
longer do. There are two categories of these:
- Small values fit in a single pointer and are stored by value.
- Large values require auxiliary storage, and are stored by reference.
The only non-mechanical change is to tools/dsymutil/DwarfLinker.cpp. It
was relying on `DIEInteger`s being passed around by reference, so I
replaced that assumption with a `PatchLocation` type that stores a safe
reference to where the `DIEInteger` lives instead.
This commit causes a temporary regression in memory usage, since I've
left merging `DIEAbbrevData` into `DIEValue` for a follow-up commit. I
measured an increase from 845 MB to 879 MB, around 3.9%. The follow-up
drops it lower than the starting point, and I've only recently brought
the memory this low anyway, so I'm committing these changes separately
to keep them incremental. (I also considered swapping the commits, but
the other one first would cause a lot more code churn.)
(I'm looking at `llc` memory usage on `verify-uselistorder.lto.opt.bc`;
see r236629 for details.)
--
llvm-svn: 238362
2015-05-28 06:14:58 +08:00
|
|
|
void DIEDelta::EmitValue(const AsmPrinter *AP, dwarf::Form Form) const {
|
2010-04-05 08:18:22 +08:00
|
|
|
AP->EmitLabelDifference(LabelHi, LabelLo, SizeOf(AP, Form));
|
2009-05-15 08:11:17 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/// SizeOf - Determine size of delta value in bytes.
|
|
|
|
///
|
Reapply "AsmPrinter: Change DIEValue to be stored by value"
This reverts commit r238350, effectively reapplying r238349 after fixing
(all?) the problems, all somehow related to how I was using
`AlignedArrayCharUnion<>` inside `DIEValue`:
- MSVC can only handle `sizeof()` on types, not values. Change the
assert.
- GCC doesn't know the `is_trivially_copyable` type trait. Instead of
asserting it, add destructors.
- Call placement new even when constructing POD (i.e., the pointers).
- Instead of copying the char buffer, copy the casted classes.
I've left in a couple of `static_assert`s that I think both MSVC and GCC
know how to handle. If the bots disagree with me, I'll remove them.
- Check that the constructed type is either standard layout or a
pointer. This protects against a programming error: we really want
the "small" `DIEValue`s to be small and simple, so don't
accidentally change them not to be.
- Similarly, check that the size of the buffer is no bigger than a
`uint64_t` or a pointer. (I thought checking against
`sizeof(uint64_t)` would be good enough, but Chandler suggested that
pointers might sometimes be bigger than that in the context of
sanitizers.)
I've also committed r238359 in the meantime, which introduces a
DIEValue.def to simplify dispatching between the various types (thanks
to a review comment by David Blaikie). Without that, this commit would
be almost unintelligible.
Here's the original commit message:
--
Change `DIEValue` to be stored/passed/etc. by value, instead of
reference. It's now a discriminated union, with a `Val` field storing
the actual type. The classes that used to inherit from `DIEValue` no
longer do. There are two categories of these:
- Small values fit in a single pointer and are stored by value.
- Large values require auxiliary storage, and are stored by reference.
The only non-mechanical change is to tools/dsymutil/DwarfLinker.cpp. It
was relying on `DIEInteger`s being passed around by reference, so I
replaced that assumption with a `PatchLocation` type that stores a safe
reference to where the `DIEInteger` lives instead.
This commit causes a temporary regression in memory usage, since I've
left merging `DIEAbbrevData` into `DIEValue` for a follow-up commit. I
measured an increase from 845 MB to 879 MB, around 3.9%. The follow-up
drops it lower than the starting point, and I've only recently brought
the memory this low anyway, so I'm committing these changes separately
to keep them incremental. (I also considered swapping the commits, but
the other one first would cause a lot more code churn.)
(I'm looking at `llc` memory usage on `verify-uselistorder.lto.opt.bc`;
see r236629 for details.)
--
llvm-svn: 238362
2015-05-28 06:14:58 +08:00
|
|
|
unsigned DIEDelta::SizeOf(const AsmPrinter *AP, dwarf::Form Form) const {
|
2009-05-15 08:11:17 +08:00
|
|
|
if (Form == dwarf::DW_FORM_data4) return 4;
|
2013-11-22 07:46:41 +08:00
|
|
|
if (Form == dwarf::DW_FORM_sec_offset) return 4;
|
2011-10-27 14:44:11 +08:00
|
|
|
if (Form == dwarf::DW_FORM_strp) return 4;
|
2017-04-18 01:41:25 +08:00
|
|
|
return AP->MAI->getCodePointerSize();
|
2009-05-15 08:11:17 +08:00
|
|
|
}
|
|
|
|
|
2015-11-24 10:21:43 +08:00
|
|
|
LLVM_DUMP_METHOD
|
Reapply "AsmPrinter: Change DIEValue to be stored by value"
This reverts commit r238350, effectively reapplying r238349 after fixing
(all?) the problems, all somehow related to how I was using
`AlignedArrayCharUnion<>` inside `DIEValue`:
- MSVC can only handle `sizeof()` on types, not values. Change the
assert.
- GCC doesn't know the `is_trivially_copyable` type trait. Instead of
asserting it, add destructors.
- Call placement new even when constructing POD (i.e., the pointers).
- Instead of copying the char buffer, copy the casted classes.
I've left in a couple of `static_assert`s that I think both MSVC and GCC
know how to handle. If the bots disagree with me, I'll remove them.
- Check that the constructed type is either standard layout or a
pointer. This protects against a programming error: we really want
the "small" `DIEValue`s to be small and simple, so don't
accidentally change them not to be.
- Similarly, check that the size of the buffer is no bigger than a
`uint64_t` or a pointer. (I thought checking against
`sizeof(uint64_t)` would be good enough, but Chandler suggested that
pointers might sometimes be bigger than that in the context of
sanitizers.)
I've also committed r238359 in the meantime, which introduces a
DIEValue.def to simplify dispatching between the various types (thanks
to a review comment by David Blaikie). Without that, this commit would
be almost unintelligible.
Here's the original commit message:
--
Change `DIEValue` to be stored/passed/etc. by value, instead of
reference. It's now a discriminated union, with a `Val` field storing
the actual type. The classes that used to inherit from `DIEValue` no
longer do. There are two categories of these:
- Small values fit in a single pointer and are stored by value.
- Large values require auxiliary storage, and are stored by reference.
The only non-mechanical change is to tools/dsymutil/DwarfLinker.cpp. It
was relying on `DIEInteger`s being passed around by reference, so I
replaced that assumption with a `PatchLocation` type that stores a safe
reference to where the `DIEInteger` lives instead.
This commit causes a temporary regression in memory usage, since I've
left merging `DIEAbbrevData` into `DIEValue` for a follow-up commit. I
measured an increase from 845 MB to 879 MB, around 3.9%. The follow-up
drops it lower than the starting point, and I've only recently brought
the memory this low anyway, so I'm committing these changes separately
to keep them incremental. (I also considered swapping the commits, but
the other one first would cause a lot more code churn.)
(I'm looking at `llc` memory usage on `verify-uselistorder.lto.opt.bc`;
see r236629 for details.)
--
llvm-svn: 238362
2015-05-28 06:14:58 +08:00
|
|
|
void DIEDelta::print(raw_ostream &O) const {
|
2010-03-09 06:23:36 +08:00
|
|
|
O << "Del: " << LabelHi->getName() << "-" << LabelLo->getName();
|
2009-05-15 08:11:17 +08:00
|
|
|
}
|
|
|
|
|
2013-07-27 01:02:41 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// DIEString Implementation
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
/// EmitValue - Emit string value.
|
|
|
|
///
|
Reapply "AsmPrinter: Change DIEValue to be stored by value"
This reverts commit r238350, effectively reapplying r238349 after fixing
(all?) the problems, all somehow related to how I was using
`AlignedArrayCharUnion<>` inside `DIEValue`:
- MSVC can only handle `sizeof()` on types, not values. Change the
assert.
- GCC doesn't know the `is_trivially_copyable` type trait. Instead of
asserting it, add destructors.
- Call placement new even when constructing POD (i.e., the pointers).
- Instead of copying the char buffer, copy the casted classes.
I've left in a couple of `static_assert`s that I think both MSVC and GCC
know how to handle. If the bots disagree with me, I'll remove them.
- Check that the constructed type is either standard layout or a
pointer. This protects against a programming error: we really want
the "small" `DIEValue`s to be small and simple, so don't
accidentally change them not to be.
- Similarly, check that the size of the buffer is no bigger than a
`uint64_t` or a pointer. (I thought checking against
`sizeof(uint64_t)` would be good enough, but Chandler suggested that
pointers might sometimes be bigger than that in the context of
sanitizers.)
I've also committed r238359 in the meantime, which introduces a
DIEValue.def to simplify dispatching between the various types (thanks
to a review comment by David Blaikie). Without that, this commit would
be almost unintelligible.
Here's the original commit message:
--
Change `DIEValue` to be stored/passed/etc. by value, instead of
reference. It's now a discriminated union, with a `Val` field storing
the actual type. The classes that used to inherit from `DIEValue` no
longer do. There are two categories of these:
- Small values fit in a single pointer and are stored by value.
- Large values require auxiliary storage, and are stored by reference.
The only non-mechanical change is to tools/dsymutil/DwarfLinker.cpp. It
was relying on `DIEInteger`s being passed around by reference, so I
replaced that assumption with a `PatchLocation` type that stores a safe
reference to where the `DIEInteger` lives instead.
This commit causes a temporary regression in memory usage, since I've
left merging `DIEAbbrevData` into `DIEValue` for a follow-up commit. I
measured an increase from 845 MB to 879 MB, around 3.9%. The follow-up
drops it lower than the starting point, and I've only recently brought
the memory this low anyway, so I'm committing these changes separately
to keep them incremental. (I also considered swapping the commits, but
the other one first would cause a lot more code churn.)
(I'm looking at `llc` memory usage on `verify-uselistorder.lto.opt.bc`;
see r236629 for details.)
--
llvm-svn: 238362
2015-05-28 06:14:58 +08:00
|
|
|
void DIEString::EmitValue(const AsmPrinter *AP, dwarf::Form Form) const {
|
2015-05-25 00:40:47 +08:00
|
|
|
assert(
|
|
|
|
(Form == dwarf::DW_FORM_strp || Form == dwarf::DW_FORM_GNU_str_index) &&
|
|
|
|
"Expected valid string form");
|
|
|
|
|
|
|
|
// Index of string in symbol table.
|
|
|
|
if (Form == dwarf::DW_FORM_GNU_str_index) {
|
|
|
|
DIEInteger(S.getIndex()).EmitValue(AP, Form);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Relocatable symbol.
|
|
|
|
assert(Form == dwarf::DW_FORM_strp);
|
|
|
|
if (AP->MAI->doesDwarfUseRelocationsAcrossSections()) {
|
|
|
|
DIELabel(S.getSymbol()).EmitValue(AP, Form);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Offset into symbol table.
|
|
|
|
DIEInteger(S.getOffset()).EmitValue(AP, Form);
|
2013-07-27 01:02:41 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/// SizeOf - Determine size of delta value in bytes.
|
|
|
|
///
|
Reapply "AsmPrinter: Change DIEValue to be stored by value"
This reverts commit r238350, effectively reapplying r238349 after fixing
(all?) the problems, all somehow related to how I was using
`AlignedArrayCharUnion<>` inside `DIEValue`:
- MSVC can only handle `sizeof()` on types, not values. Change the
assert.
- GCC doesn't know the `is_trivially_copyable` type trait. Instead of
asserting it, add destructors.
- Call placement new even when constructing POD (i.e., the pointers).
- Instead of copying the char buffer, copy the casted classes.
I've left in a couple of `static_assert`s that I think both MSVC and GCC
know how to handle. If the bots disagree with me, I'll remove them.
- Check that the constructed type is either standard layout or a
pointer. This protects against a programming error: we really want
the "small" `DIEValue`s to be small and simple, so don't
accidentally change them not to be.
- Similarly, check that the size of the buffer is no bigger than a
`uint64_t` or a pointer. (I thought checking against
`sizeof(uint64_t)` would be good enough, but Chandler suggested that
pointers might sometimes be bigger than that in the context of
sanitizers.)
I've also committed r238359 in the meantime, which introduces a
DIEValue.def to simplify dispatching between the various types (thanks
to a review comment by David Blaikie). Without that, this commit would
be almost unintelligible.
Here's the original commit message:
--
Change `DIEValue` to be stored/passed/etc. by value, instead of
reference. It's now a discriminated union, with a `Val` field storing
the actual type. The classes that used to inherit from `DIEValue` no
longer do. There are two categories of these:
- Small values fit in a single pointer and are stored by value.
- Large values require auxiliary storage, and are stored by reference.
The only non-mechanical change is to tools/dsymutil/DwarfLinker.cpp. It
was relying on `DIEInteger`s being passed around by reference, so I
replaced that assumption with a `PatchLocation` type that stores a safe
reference to where the `DIEInteger` lives instead.
This commit causes a temporary regression in memory usage, since I've
left merging `DIEAbbrevData` into `DIEValue` for a follow-up commit. I
measured an increase from 845 MB to 879 MB, around 3.9%. The follow-up
drops it lower than the starting point, and I've only recently brought
the memory this low anyway, so I'm committing these changes separately
to keep them incremental. (I also considered swapping the commits, but
the other one first would cause a lot more code churn.)
(I'm looking at `llc` memory usage on `verify-uselistorder.lto.opt.bc`;
see r236629 for details.)
--
llvm-svn: 238362
2015-05-28 06:14:58 +08:00
|
|
|
unsigned DIEString::SizeOf(const AsmPrinter *AP, dwarf::Form Form) const {
|
2015-05-25 00:40:47 +08:00
|
|
|
assert(
|
|
|
|
(Form == dwarf::DW_FORM_strp || Form == dwarf::DW_FORM_GNU_str_index) &&
|
|
|
|
"Expected valid string form");
|
|
|
|
|
|
|
|
// Index of string in symbol table.
|
|
|
|
if (Form == dwarf::DW_FORM_GNU_str_index)
|
|
|
|
return DIEInteger(S.getIndex()).SizeOf(AP, Form);
|
|
|
|
|
|
|
|
// Relocatable symbol.
|
|
|
|
if (AP->MAI->doesDwarfUseRelocationsAcrossSections())
|
|
|
|
return DIELabel(S.getSymbol()).SizeOf(AP, Form);
|
|
|
|
|
|
|
|
// Offset into symbol table.
|
|
|
|
return DIEInteger(S.getOffset()).SizeOf(AP, Form);
|
2013-07-27 01:02:41 +08:00
|
|
|
}
|
|
|
|
|
2015-11-24 10:21:43 +08:00
|
|
|
LLVM_DUMP_METHOD
|
Reapply "AsmPrinter: Change DIEValue to be stored by value"
This reverts commit r238350, effectively reapplying r238349 after fixing
(all?) the problems, all somehow related to how I was using
`AlignedArrayCharUnion<>` inside `DIEValue`:
- MSVC can only handle `sizeof()` on types, not values. Change the
assert.
- GCC doesn't know the `is_trivially_copyable` type trait. Instead of
asserting it, add destructors.
- Call placement new even when constructing POD (i.e., the pointers).
- Instead of copying the char buffer, copy the casted classes.
I've left in a couple of `static_assert`s that I think both MSVC and GCC
know how to handle. If the bots disagree with me, I'll remove them.
- Check that the constructed type is either standard layout or a
pointer. This protects against a programming error: we really want
the "small" `DIEValue`s to be small and simple, so don't
accidentally change them not to be.
- Similarly, check that the size of the buffer is no bigger than a
`uint64_t` or a pointer. (I thought checking against
`sizeof(uint64_t)` would be good enough, but Chandler suggested that
pointers might sometimes be bigger than that in the context of
sanitizers.)
I've also committed r238359 in the meantime, which introduces a
DIEValue.def to simplify dispatching between the various types (thanks
to a review comment by David Blaikie). Without that, this commit would
be almost unintelligible.
Here's the original commit message:
--
Change `DIEValue` to be stored/passed/etc. by value, instead of
reference. It's now a discriminated union, with a `Val` field storing
the actual type. The classes that used to inherit from `DIEValue` no
longer do. There are two categories of these:
- Small values fit in a single pointer and are stored by value.
- Large values require auxiliary storage, and are stored by reference.
The only non-mechanical change is to tools/dsymutil/DwarfLinker.cpp. It
was relying on `DIEInteger`s being passed around by reference, so I
replaced that assumption with a `PatchLocation` type that stores a safe
reference to where the `DIEInteger` lives instead.
This commit causes a temporary regression in memory usage, since I've
left merging `DIEAbbrevData` into `DIEValue` for a follow-up commit. I
measured an increase from 845 MB to 879 MB, around 3.9%. The follow-up
drops it lower than the starting point, and I've only recently brought
the memory this low anyway, so I'm committing these changes separately
to keep them incremental. (I also considered swapping the commits, but
the other one first would cause a lot more code churn.)
(I'm looking at `llc` memory usage on `verify-uselistorder.lto.opt.bc`;
see r236629 for details.)
--
llvm-svn: 238362
2015-05-28 06:14:58 +08:00
|
|
|
void DIEString::print(raw_ostream &O) const {
|
2015-05-25 00:40:47 +08:00
|
|
|
O << "String: " << S.getString();
|
2013-07-27 01:02:41 +08:00
|
|
|
}
|
|
|
|
|
Make a DWARF generator so we can unit test DWARF APIs with gtest.
The only tests we have for the DWARF parser are the tests that use llvm-dwarfdump and expect output from textual dumps.
More DWARF parser modification are coming in the next few weeks and I wanted to add tests that can verify that we can encode and decode all form types, as well as test some other basic DWARF APIs where we ask DIE objects for their children and siblings.
DwarfGenerator.cpp was added in the lib/CodeGen directory. This file contains the code necessary to easily create DWARF for tests:
dwarfgen::Generator DG;
Triple Triple("x86_64--");
bool success = DG.init(Triple, Version);
if (!success)
return;
dwarfgen::CompileUnit &CU = DG.addCompileUnit();
dwarfgen::DIE CUDie = CU.getUnitDIE();
CUDie.addAttribute(DW_AT_name, DW_FORM_strp, "/tmp/main.c");
CUDie.addAttribute(DW_AT_language, DW_FORM_data2, DW_LANG_C);
dwarfgen::DIE SubprogramDie = CUDie.addChild(DW_TAG_subprogram);
SubprogramDie.addAttribute(DW_AT_name, DW_FORM_strp, "main");
SubprogramDie.addAttribute(DW_AT_low_pc, DW_FORM_addr, 0x1000U);
SubprogramDie.addAttribute(DW_AT_high_pc, DW_FORM_addr, 0x2000U);
dwarfgen::DIE IntDie = CUDie.addChild(DW_TAG_base_type);
IntDie.addAttribute(DW_AT_name, DW_FORM_strp, "int");
IntDie.addAttribute(DW_AT_encoding, DW_FORM_data1, DW_ATE_signed);
IntDie.addAttribute(DW_AT_byte_size, DW_FORM_data1, 4);
dwarfgen::DIE ArgcDie = SubprogramDie.addChild(DW_TAG_formal_parameter);
ArgcDie.addAttribute(DW_AT_name, DW_FORM_strp, "argc");
// ArgcDie.addAttribute(DW_AT_type, DW_FORM_ref4, IntDie);
ArgcDie.addAttribute(DW_AT_type, DW_FORM_ref_addr, IntDie);
StringRef FileBytes = DG.generate();
MemoryBufferRef FileBuffer(FileBytes, "dwarf");
auto Obj = object::ObjectFile::createObjectFile(FileBuffer);
EXPECT_TRUE((bool)Obj);
DWARFContextInMemory DwarfContext(*Obj.get());
This code is backed by the AsmPrinter code that emits DWARF for the actual compiler.
While adding unit tests it was discovered that DIEValue that used DIEEntry as their values had bugs where DW_FORM_ref1, DW_FORM_ref2, DW_FORM_ref8, and DW_FORM_ref_udata forms were not supported. These are all now supported. Added support for DW_FORM_string so we can emit inlined C strings.
Centralized the code to unique abbreviations into a new DIEAbbrevSet class and made both the dwarfgen::Generator and the llvm::DwarfFile classes use the new class.
Fixed comments in the llvm::DIE class so that the Offset is known to be the compile/type unit offset.
DIEInteger now supports more DW_FORM values.
There are also unit tests that cover:
Encoding and decoding all form types and values
Encoding and decoding all reference types (DW_FORM_ref1, DW_FORM_ref2, DW_FORM_ref4, DW_FORM_ref8, DW_FORM_ref_udata, DW_FORM_ref_addr) including cross compile unit references with that go forward one compile unit and backward on compile unit.
Differential Revision: https://reviews.llvm.org/D27326
llvm-svn: 289010
2016-12-08 09:03:48 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// DIEInlineString Implementation
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
void DIEInlineString::EmitValue(const AsmPrinter *AP, dwarf::Form Form) const {
|
|
|
|
if (Form == dwarf::DW_FORM_string) {
|
|
|
|
for (char ch : S)
|
|
|
|
AP->EmitInt8(ch);
|
|
|
|
AP->EmitInt8(0);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
llvm_unreachable("Expected valid string form");
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned DIEInlineString::SizeOf(const AsmPrinter *AP, dwarf::Form Form) const {
|
|
|
|
// Emit string bytes + NULL byte.
|
|
|
|
return S.size() + 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
LLVM_DUMP_METHOD
|
|
|
|
void DIEInlineString::print(raw_ostream &O) const {
|
2016-12-09 21:33:41 +08:00
|
|
|
O << "InlineString: " << S;
|
Make a DWARF generator so we can unit test DWARF APIs with gtest.
The only tests we have for the DWARF parser are the tests that use llvm-dwarfdump and expect output from textual dumps.
More DWARF parser modification are coming in the next few weeks and I wanted to add tests that can verify that we can encode and decode all form types, as well as test some other basic DWARF APIs where we ask DIE objects for their children and siblings.
DwarfGenerator.cpp was added in the lib/CodeGen directory. This file contains the code necessary to easily create DWARF for tests:
dwarfgen::Generator DG;
Triple Triple("x86_64--");
bool success = DG.init(Triple, Version);
if (!success)
return;
dwarfgen::CompileUnit &CU = DG.addCompileUnit();
dwarfgen::DIE CUDie = CU.getUnitDIE();
CUDie.addAttribute(DW_AT_name, DW_FORM_strp, "/tmp/main.c");
CUDie.addAttribute(DW_AT_language, DW_FORM_data2, DW_LANG_C);
dwarfgen::DIE SubprogramDie = CUDie.addChild(DW_TAG_subprogram);
SubprogramDie.addAttribute(DW_AT_name, DW_FORM_strp, "main");
SubprogramDie.addAttribute(DW_AT_low_pc, DW_FORM_addr, 0x1000U);
SubprogramDie.addAttribute(DW_AT_high_pc, DW_FORM_addr, 0x2000U);
dwarfgen::DIE IntDie = CUDie.addChild(DW_TAG_base_type);
IntDie.addAttribute(DW_AT_name, DW_FORM_strp, "int");
IntDie.addAttribute(DW_AT_encoding, DW_FORM_data1, DW_ATE_signed);
IntDie.addAttribute(DW_AT_byte_size, DW_FORM_data1, 4);
dwarfgen::DIE ArgcDie = SubprogramDie.addChild(DW_TAG_formal_parameter);
ArgcDie.addAttribute(DW_AT_name, DW_FORM_strp, "argc");
// ArgcDie.addAttribute(DW_AT_type, DW_FORM_ref4, IntDie);
ArgcDie.addAttribute(DW_AT_type, DW_FORM_ref_addr, IntDie);
StringRef FileBytes = DG.generate();
MemoryBufferRef FileBuffer(FileBytes, "dwarf");
auto Obj = object::ObjectFile::createObjectFile(FileBuffer);
EXPECT_TRUE((bool)Obj);
DWARFContextInMemory DwarfContext(*Obj.get());
This code is backed by the AsmPrinter code that emits DWARF for the actual compiler.
While adding unit tests it was discovered that DIEValue that used DIEEntry as their values had bugs where DW_FORM_ref1, DW_FORM_ref2, DW_FORM_ref8, and DW_FORM_ref_udata forms were not supported. These are all now supported. Added support for DW_FORM_string so we can emit inlined C strings.
Centralized the code to unique abbreviations into a new DIEAbbrevSet class and made both the dwarfgen::Generator and the llvm::DwarfFile classes use the new class.
Fixed comments in the llvm::DIE class so that the Offset is known to be the compile/type unit offset.
DIEInteger now supports more DW_FORM values.
There are also unit tests that cover:
Encoding and decoding all form types and values
Encoding and decoding all reference types (DW_FORM_ref1, DW_FORM_ref2, DW_FORM_ref4, DW_FORM_ref8, DW_FORM_ref_udata, DW_FORM_ref_addr) including cross compile unit references with that go forward one compile unit and backward on compile unit.
Differential Revision: https://reviews.llvm.org/D27326
llvm-svn: 289010
2016-12-08 09:03:48 +08:00
|
|
|
}
|
|
|
|
|
2009-05-15 08:11:17 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// DIEEntry Implementation
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
/// EmitValue - Emit debug information entry offset.
|
|
|
|
///
|
Reapply "AsmPrinter: Change DIEValue to be stored by value"
This reverts commit r238350, effectively reapplying r238349 after fixing
(all?) the problems, all somehow related to how I was using
`AlignedArrayCharUnion<>` inside `DIEValue`:
- MSVC can only handle `sizeof()` on types, not values. Change the
assert.
- GCC doesn't know the `is_trivially_copyable` type trait. Instead of
asserting it, add destructors.
- Call placement new even when constructing POD (i.e., the pointers).
- Instead of copying the char buffer, copy the casted classes.
I've left in a couple of `static_assert`s that I think both MSVC and GCC
know how to handle. If the bots disagree with me, I'll remove them.
- Check that the constructed type is either standard layout or a
pointer. This protects against a programming error: we really want
the "small" `DIEValue`s to be small and simple, so don't
accidentally change them not to be.
- Similarly, check that the size of the buffer is no bigger than a
`uint64_t` or a pointer. (I thought checking against
`sizeof(uint64_t)` would be good enough, but Chandler suggested that
pointers might sometimes be bigger than that in the context of
sanitizers.)
I've also committed r238359 in the meantime, which introduces a
DIEValue.def to simplify dispatching between the various types (thanks
to a review comment by David Blaikie). Without that, this commit would
be almost unintelligible.
Here's the original commit message:
--
Change `DIEValue` to be stored/passed/etc. by value, instead of
reference. It's now a discriminated union, with a `Val` field storing
the actual type. The classes that used to inherit from `DIEValue` no
longer do. There are two categories of these:
- Small values fit in a single pointer and are stored by value.
- Large values require auxiliary storage, and are stored by reference.
The only non-mechanical change is to tools/dsymutil/DwarfLinker.cpp. It
was relying on `DIEInteger`s being passed around by reference, so I
replaced that assumption with a `PatchLocation` type that stores a safe
reference to where the `DIEInteger` lives instead.
This commit causes a temporary regression in memory usage, since I've
left merging `DIEAbbrevData` into `DIEValue` for a follow-up commit. I
measured an increase from 845 MB to 879 MB, around 3.9%. The follow-up
drops it lower than the starting point, and I've only recently brought
the memory this low anyway, so I'm committing these changes separately
to keep them incremental. (I also considered swapping the commits, but
the other one first would cause a lot more code churn.)
(I'm looking at `llc` memory usage on `verify-uselistorder.lto.opt.bc`;
see r236629 for details.)
--
llvm-svn: 238362
2015-05-28 06:14:58 +08:00
|
|
|
void DIEEntry::EmitValue(const AsmPrinter *AP, dwarf::Form Form) const {
|
2014-03-06 08:00:56 +08:00
|
|
|
|
Make a DWARF generator so we can unit test DWARF APIs with gtest.
The only tests we have for the DWARF parser are the tests that use llvm-dwarfdump and expect output from textual dumps.
More DWARF parser modification are coming in the next few weeks and I wanted to add tests that can verify that we can encode and decode all form types, as well as test some other basic DWARF APIs where we ask DIE objects for their children and siblings.
DwarfGenerator.cpp was added in the lib/CodeGen directory. This file contains the code necessary to easily create DWARF for tests:
dwarfgen::Generator DG;
Triple Triple("x86_64--");
bool success = DG.init(Triple, Version);
if (!success)
return;
dwarfgen::CompileUnit &CU = DG.addCompileUnit();
dwarfgen::DIE CUDie = CU.getUnitDIE();
CUDie.addAttribute(DW_AT_name, DW_FORM_strp, "/tmp/main.c");
CUDie.addAttribute(DW_AT_language, DW_FORM_data2, DW_LANG_C);
dwarfgen::DIE SubprogramDie = CUDie.addChild(DW_TAG_subprogram);
SubprogramDie.addAttribute(DW_AT_name, DW_FORM_strp, "main");
SubprogramDie.addAttribute(DW_AT_low_pc, DW_FORM_addr, 0x1000U);
SubprogramDie.addAttribute(DW_AT_high_pc, DW_FORM_addr, 0x2000U);
dwarfgen::DIE IntDie = CUDie.addChild(DW_TAG_base_type);
IntDie.addAttribute(DW_AT_name, DW_FORM_strp, "int");
IntDie.addAttribute(DW_AT_encoding, DW_FORM_data1, DW_ATE_signed);
IntDie.addAttribute(DW_AT_byte_size, DW_FORM_data1, 4);
dwarfgen::DIE ArgcDie = SubprogramDie.addChild(DW_TAG_formal_parameter);
ArgcDie.addAttribute(DW_AT_name, DW_FORM_strp, "argc");
// ArgcDie.addAttribute(DW_AT_type, DW_FORM_ref4, IntDie);
ArgcDie.addAttribute(DW_AT_type, DW_FORM_ref_addr, IntDie);
StringRef FileBytes = DG.generate();
MemoryBufferRef FileBuffer(FileBytes, "dwarf");
auto Obj = object::ObjectFile::createObjectFile(FileBuffer);
EXPECT_TRUE((bool)Obj);
DWARFContextInMemory DwarfContext(*Obj.get());
This code is backed by the AsmPrinter code that emits DWARF for the actual compiler.
While adding unit tests it was discovered that DIEValue that used DIEEntry as their values had bugs where DW_FORM_ref1, DW_FORM_ref2, DW_FORM_ref8, and DW_FORM_ref_udata forms were not supported. These are all now supported. Added support for DW_FORM_string so we can emit inlined C strings.
Centralized the code to unique abbreviations into a new DIEAbbrevSet class and made both the dwarfgen::Generator and the llvm::DwarfFile classes use the new class.
Fixed comments in the llvm::DIE class so that the Offset is known to be the compile/type unit offset.
DIEInteger now supports more DW_FORM values.
There are also unit tests that cover:
Encoding and decoding all form types and values
Encoding and decoding all reference types (DW_FORM_ref1, DW_FORM_ref2, DW_FORM_ref4, DW_FORM_ref8, DW_FORM_ref_udata, DW_FORM_ref_addr) including cross compile unit references with that go forward one compile unit and backward on compile unit.
Differential Revision: https://reviews.llvm.org/D27326
llvm-svn: 289010
2016-12-08 09:03:48 +08:00
|
|
|
switch (Form) {
|
|
|
|
case dwarf::DW_FORM_ref1:
|
|
|
|
case dwarf::DW_FORM_ref2:
|
|
|
|
case dwarf::DW_FORM_ref4:
|
|
|
|
case dwarf::DW_FORM_ref8:
|
|
|
|
AP->OutStreamer->EmitIntValue(Entry->getOffset(), SizeOf(AP, Form));
|
|
|
|
return;
|
|
|
|
|
|
|
|
case dwarf::DW_FORM_ref_udata:
|
|
|
|
AP->EmitULEB128(Entry->getOffset());
|
|
|
|
return;
|
|
|
|
|
|
|
|
case dwarf::DW_FORM_ref_addr: {
|
2016-12-02 02:56:29 +08:00
|
|
|
// Get the absolute offset for this DIE within the debug info/types section.
|
|
|
|
unsigned Addr = Entry->getDebugSectionOffset();
|
2017-04-22 15:53:44 +08:00
|
|
|
if (const MCSymbol *SectionSym =
|
|
|
|
Entry->getUnit()->getCrossSectionRelativeBaseAddress()) {
|
|
|
|
AP->EmitLabelPlusOffset(SectionSym, Addr, SizeOf(AP, Form), true);
|
|
|
|
return;
|
Make a DWARF generator so we can unit test DWARF APIs with gtest.
The only tests we have for the DWARF parser are the tests that use llvm-dwarfdump and expect output from textual dumps.
More DWARF parser modification are coming in the next few weeks and I wanted to add tests that can verify that we can encode and decode all form types, as well as test some other basic DWARF APIs where we ask DIE objects for their children and siblings.
DwarfGenerator.cpp was added in the lib/CodeGen directory. This file contains the code necessary to easily create DWARF for tests:
dwarfgen::Generator DG;
Triple Triple("x86_64--");
bool success = DG.init(Triple, Version);
if (!success)
return;
dwarfgen::CompileUnit &CU = DG.addCompileUnit();
dwarfgen::DIE CUDie = CU.getUnitDIE();
CUDie.addAttribute(DW_AT_name, DW_FORM_strp, "/tmp/main.c");
CUDie.addAttribute(DW_AT_language, DW_FORM_data2, DW_LANG_C);
dwarfgen::DIE SubprogramDie = CUDie.addChild(DW_TAG_subprogram);
SubprogramDie.addAttribute(DW_AT_name, DW_FORM_strp, "main");
SubprogramDie.addAttribute(DW_AT_low_pc, DW_FORM_addr, 0x1000U);
SubprogramDie.addAttribute(DW_AT_high_pc, DW_FORM_addr, 0x2000U);
dwarfgen::DIE IntDie = CUDie.addChild(DW_TAG_base_type);
IntDie.addAttribute(DW_AT_name, DW_FORM_strp, "int");
IntDie.addAttribute(DW_AT_encoding, DW_FORM_data1, DW_ATE_signed);
IntDie.addAttribute(DW_AT_byte_size, DW_FORM_data1, 4);
dwarfgen::DIE ArgcDie = SubprogramDie.addChild(DW_TAG_formal_parameter);
ArgcDie.addAttribute(DW_AT_name, DW_FORM_strp, "argc");
// ArgcDie.addAttribute(DW_AT_type, DW_FORM_ref4, IntDie);
ArgcDie.addAttribute(DW_AT_type, DW_FORM_ref_addr, IntDie);
StringRef FileBytes = DG.generate();
MemoryBufferRef FileBuffer(FileBytes, "dwarf");
auto Obj = object::ObjectFile::createObjectFile(FileBuffer);
EXPECT_TRUE((bool)Obj);
DWARFContextInMemory DwarfContext(*Obj.get());
This code is backed by the AsmPrinter code that emits DWARF for the actual compiler.
While adding unit tests it was discovered that DIEValue that used DIEEntry as their values had bugs where DW_FORM_ref1, DW_FORM_ref2, DW_FORM_ref8, and DW_FORM_ref_udata forms were not supported. These are all now supported. Added support for DW_FORM_string so we can emit inlined C strings.
Centralized the code to unique abbreviations into a new DIEAbbrevSet class and made both the dwarfgen::Generator and the llvm::DwarfFile classes use the new class.
Fixed comments in the llvm::DIE class so that the Offset is known to be the compile/type unit offset.
DIEInteger now supports more DW_FORM values.
There are also unit tests that cover:
Encoding and decoding all form types and values
Encoding and decoding all reference types (DW_FORM_ref1, DW_FORM_ref2, DW_FORM_ref4, DW_FORM_ref8, DW_FORM_ref_udata, DW_FORM_ref_addr) including cross compile unit references with that go forward one compile unit and backward on compile unit.
Differential Revision: https://reviews.llvm.org/D27326
llvm-svn: 289010
2016-12-08 09:03:48 +08:00
|
|
|
}
|
2017-04-22 15:53:44 +08:00
|
|
|
|
Make a DWARF generator so we can unit test DWARF APIs with gtest.
The only tests we have for the DWARF parser are the tests that use llvm-dwarfdump and expect output from textual dumps.
More DWARF parser modification are coming in the next few weeks and I wanted to add tests that can verify that we can encode and decode all form types, as well as test some other basic DWARF APIs where we ask DIE objects for their children and siblings.
DwarfGenerator.cpp was added in the lib/CodeGen directory. This file contains the code necessary to easily create DWARF for tests:
dwarfgen::Generator DG;
Triple Triple("x86_64--");
bool success = DG.init(Triple, Version);
if (!success)
return;
dwarfgen::CompileUnit &CU = DG.addCompileUnit();
dwarfgen::DIE CUDie = CU.getUnitDIE();
CUDie.addAttribute(DW_AT_name, DW_FORM_strp, "/tmp/main.c");
CUDie.addAttribute(DW_AT_language, DW_FORM_data2, DW_LANG_C);
dwarfgen::DIE SubprogramDie = CUDie.addChild(DW_TAG_subprogram);
SubprogramDie.addAttribute(DW_AT_name, DW_FORM_strp, "main");
SubprogramDie.addAttribute(DW_AT_low_pc, DW_FORM_addr, 0x1000U);
SubprogramDie.addAttribute(DW_AT_high_pc, DW_FORM_addr, 0x2000U);
dwarfgen::DIE IntDie = CUDie.addChild(DW_TAG_base_type);
IntDie.addAttribute(DW_AT_name, DW_FORM_strp, "int");
IntDie.addAttribute(DW_AT_encoding, DW_FORM_data1, DW_ATE_signed);
IntDie.addAttribute(DW_AT_byte_size, DW_FORM_data1, 4);
dwarfgen::DIE ArgcDie = SubprogramDie.addChild(DW_TAG_formal_parameter);
ArgcDie.addAttribute(DW_AT_name, DW_FORM_strp, "argc");
// ArgcDie.addAttribute(DW_AT_type, DW_FORM_ref4, IntDie);
ArgcDie.addAttribute(DW_AT_type, DW_FORM_ref_addr, IntDie);
StringRef FileBytes = DG.generate();
MemoryBufferRef FileBuffer(FileBytes, "dwarf");
auto Obj = object::ObjectFile::createObjectFile(FileBuffer);
EXPECT_TRUE((bool)Obj);
DWARFContextInMemory DwarfContext(*Obj.get());
This code is backed by the AsmPrinter code that emits DWARF for the actual compiler.
While adding unit tests it was discovered that DIEValue that used DIEEntry as their values had bugs where DW_FORM_ref1, DW_FORM_ref2, DW_FORM_ref8, and DW_FORM_ref_udata forms were not supported. These are all now supported. Added support for DW_FORM_string so we can emit inlined C strings.
Centralized the code to unique abbreviations into a new DIEAbbrevSet class and made both the dwarfgen::Generator and the llvm::DwarfFile classes use the new class.
Fixed comments in the llvm::DIE class so that the Offset is known to be the compile/type unit offset.
DIEInteger now supports more DW_FORM values.
There are also unit tests that cover:
Encoding and decoding all form types and values
Encoding and decoding all reference types (DW_FORM_ref1, DW_FORM_ref2, DW_FORM_ref4, DW_FORM_ref8, DW_FORM_ref_udata, DW_FORM_ref_addr) including cross compile unit references with that go forward one compile unit and backward on compile unit.
Differential Revision: https://reviews.llvm.org/D27326
llvm-svn: 289010
2016-12-08 09:03:48 +08:00
|
|
|
AP->OutStreamer->EmitIntValue(Addr, SizeOf(AP, Form));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
llvm_unreachable("Improper form for DIE reference");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned DIEEntry::SizeOf(const AsmPrinter *AP, dwarf::Form Form) const {
|
|
|
|
switch (Form) {
|
|
|
|
case dwarf::DW_FORM_ref1:
|
|
|
|
return 1;
|
|
|
|
case dwarf::DW_FORM_ref2:
|
|
|
|
return 2;
|
|
|
|
case dwarf::DW_FORM_ref4:
|
|
|
|
return 4;
|
|
|
|
case dwarf::DW_FORM_ref8:
|
|
|
|
return 8;
|
|
|
|
case dwarf::DW_FORM_ref_udata:
|
|
|
|
return getULEB128Size(Entry->getOffset());
|
|
|
|
case dwarf::DW_FORM_ref_addr:
|
|
|
|
if (AP->getDwarfVersion() == 2)
|
2017-04-18 01:41:25 +08:00
|
|
|
return AP->MAI->getCodePointerSize();
|
Make a DWARF generator so we can unit test DWARF APIs with gtest.
The only tests we have for the DWARF parser are the tests that use llvm-dwarfdump and expect output from textual dumps.
More DWARF parser modification are coming in the next few weeks and I wanted to add tests that can verify that we can encode and decode all form types, as well as test some other basic DWARF APIs where we ask DIE objects for their children and siblings.
DwarfGenerator.cpp was added in the lib/CodeGen directory. This file contains the code necessary to easily create DWARF for tests:
dwarfgen::Generator DG;
Triple Triple("x86_64--");
bool success = DG.init(Triple, Version);
if (!success)
return;
dwarfgen::CompileUnit &CU = DG.addCompileUnit();
dwarfgen::DIE CUDie = CU.getUnitDIE();
CUDie.addAttribute(DW_AT_name, DW_FORM_strp, "/tmp/main.c");
CUDie.addAttribute(DW_AT_language, DW_FORM_data2, DW_LANG_C);
dwarfgen::DIE SubprogramDie = CUDie.addChild(DW_TAG_subprogram);
SubprogramDie.addAttribute(DW_AT_name, DW_FORM_strp, "main");
SubprogramDie.addAttribute(DW_AT_low_pc, DW_FORM_addr, 0x1000U);
SubprogramDie.addAttribute(DW_AT_high_pc, DW_FORM_addr, 0x2000U);
dwarfgen::DIE IntDie = CUDie.addChild(DW_TAG_base_type);
IntDie.addAttribute(DW_AT_name, DW_FORM_strp, "int");
IntDie.addAttribute(DW_AT_encoding, DW_FORM_data1, DW_ATE_signed);
IntDie.addAttribute(DW_AT_byte_size, DW_FORM_data1, 4);
dwarfgen::DIE ArgcDie = SubprogramDie.addChild(DW_TAG_formal_parameter);
ArgcDie.addAttribute(DW_AT_name, DW_FORM_strp, "argc");
// ArgcDie.addAttribute(DW_AT_type, DW_FORM_ref4, IntDie);
ArgcDie.addAttribute(DW_AT_type, DW_FORM_ref_addr, IntDie);
StringRef FileBytes = DG.generate();
MemoryBufferRef FileBuffer(FileBytes, "dwarf");
auto Obj = object::ObjectFile::createObjectFile(FileBuffer);
EXPECT_TRUE((bool)Obj);
DWARFContextInMemory DwarfContext(*Obj.get());
This code is backed by the AsmPrinter code that emits DWARF for the actual compiler.
While adding unit tests it was discovered that DIEValue that used DIEEntry as their values had bugs where DW_FORM_ref1, DW_FORM_ref2, DW_FORM_ref8, and DW_FORM_ref_udata forms were not supported. These are all now supported. Added support for DW_FORM_string so we can emit inlined C strings.
Centralized the code to unique abbreviations into a new DIEAbbrevSet class and made both the dwarfgen::Generator and the llvm::DwarfFile classes use the new class.
Fixed comments in the llvm::DIE class so that the Offset is known to be the compile/type unit offset.
DIEInteger now supports more DW_FORM values.
There are also unit tests that cover:
Encoding and decoding all form types and values
Encoding and decoding all reference types (DW_FORM_ref1, DW_FORM_ref2, DW_FORM_ref4, DW_FORM_ref8, DW_FORM_ref_udata, DW_FORM_ref_addr) including cross compile unit references with that go forward one compile unit and backward on compile unit.
Differential Revision: https://reviews.llvm.org/D27326
llvm-svn: 289010
2016-12-08 09:03:48 +08:00
|
|
|
switch (AP->OutStreamer->getContext().getDwarfFormat()) {
|
|
|
|
case dwarf::DWARF32:
|
|
|
|
return 4;
|
|
|
|
case dwarf::DWARF64:
|
|
|
|
return 8;
|
|
|
|
}
|
|
|
|
llvm_unreachable("Invalid DWARF format");
|
|
|
|
|
|
|
|
default:
|
|
|
|
llvm_unreachable("Improper form for DIE reference");
|
|
|
|
}
|
2013-07-03 07:40:10 +08:00
|
|
|
}
|
|
|
|
|
2015-11-24 10:21:43 +08:00
|
|
|
LLVM_DUMP_METHOD
|
Reapply "AsmPrinter: Change DIEValue to be stored by value"
This reverts commit r238350, effectively reapplying r238349 after fixing
(all?) the problems, all somehow related to how I was using
`AlignedArrayCharUnion<>` inside `DIEValue`:
- MSVC can only handle `sizeof()` on types, not values. Change the
assert.
- GCC doesn't know the `is_trivially_copyable` type trait. Instead of
asserting it, add destructors.
- Call placement new even when constructing POD (i.e., the pointers).
- Instead of copying the char buffer, copy the casted classes.
I've left in a couple of `static_assert`s that I think both MSVC and GCC
know how to handle. If the bots disagree with me, I'll remove them.
- Check that the constructed type is either standard layout or a
pointer. This protects against a programming error: we really want
the "small" `DIEValue`s to be small and simple, so don't
accidentally change them not to be.
- Similarly, check that the size of the buffer is no bigger than a
`uint64_t` or a pointer. (I thought checking against
`sizeof(uint64_t)` would be good enough, but Chandler suggested that
pointers might sometimes be bigger than that in the context of
sanitizers.)
I've also committed r238359 in the meantime, which introduces a
DIEValue.def to simplify dispatching between the various types (thanks
to a review comment by David Blaikie). Without that, this commit would
be almost unintelligible.
Here's the original commit message:
--
Change `DIEValue` to be stored/passed/etc. by value, instead of
reference. It's now a discriminated union, with a `Val` field storing
the actual type. The classes that used to inherit from `DIEValue` no
longer do. There are two categories of these:
- Small values fit in a single pointer and are stored by value.
- Large values require auxiliary storage, and are stored by reference.
The only non-mechanical change is to tools/dsymutil/DwarfLinker.cpp. It
was relying on `DIEInteger`s being passed around by reference, so I
replaced that assumption with a `PatchLocation` type that stores a safe
reference to where the `DIEInteger` lives instead.
This commit causes a temporary regression in memory usage, since I've
left merging `DIEAbbrevData` into `DIEValue` for a follow-up commit. I
measured an increase from 845 MB to 879 MB, around 3.9%. The follow-up
drops it lower than the starting point, and I've only recently brought
the memory this low anyway, so I'm committing these changes separately
to keep them incremental. (I also considered swapping the commits, but
the other one first would cause a lot more code churn.)
(I'm looking at `llc` memory usage on `verify-uselistorder.lto.opt.bc`;
see r236629 for details.)
--
llvm-svn: 238362
2015-05-28 06:14:58 +08:00
|
|
|
void DIEEntry::print(raw_ostream &O) const {
|
2014-04-26 03:33:43 +08:00
|
|
|
O << format("Die: 0x%lx", (long)(intptr_t)&Entry);
|
2009-05-15 08:11:17 +08:00
|
|
|
}
|
|
|
|
|
2014-02-16 16:46:55 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// DIELoc Implementation
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
/// ComputeSize - calculate the size of the location expression.
|
|
|
|
///
|
2015-03-04 10:30:08 +08:00
|
|
|
unsigned DIELoc::ComputeSize(const AsmPrinter *AP) const {
|
2014-02-28 02:36:10 +08:00
|
|
|
if (!Size) {
|
2015-08-03 04:42:45 +08:00
|
|
|
for (const auto &V : values())
|
2015-06-25 02:48:11 +08:00
|
|
|
Size += V.SizeOf(AP);
|
2014-02-28 02:36:10 +08:00
|
|
|
}
|
2014-02-16 16:46:55 +08:00
|
|
|
|
2014-02-28 02:36:10 +08:00
|
|
|
return Size;
|
2014-02-16 16:46:55 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/// EmitValue - Emit location data.
|
|
|
|
///
|
Reapply "AsmPrinter: Change DIEValue to be stored by value"
This reverts commit r238350, effectively reapplying r238349 after fixing
(all?) the problems, all somehow related to how I was using
`AlignedArrayCharUnion<>` inside `DIEValue`:
- MSVC can only handle `sizeof()` on types, not values. Change the
assert.
- GCC doesn't know the `is_trivially_copyable` type trait. Instead of
asserting it, add destructors.
- Call placement new even when constructing POD (i.e., the pointers).
- Instead of copying the char buffer, copy the casted classes.
I've left in a couple of `static_assert`s that I think both MSVC and GCC
know how to handle. If the bots disagree with me, I'll remove them.
- Check that the constructed type is either standard layout or a
pointer. This protects against a programming error: we really want
the "small" `DIEValue`s to be small and simple, so don't
accidentally change them not to be.
- Similarly, check that the size of the buffer is no bigger than a
`uint64_t` or a pointer. (I thought checking against
`sizeof(uint64_t)` would be good enough, but Chandler suggested that
pointers might sometimes be bigger than that in the context of
sanitizers.)
I've also committed r238359 in the meantime, which introduces a
DIEValue.def to simplify dispatching between the various types (thanks
to a review comment by David Blaikie). Without that, this commit would
be almost unintelligible.
Here's the original commit message:
--
Change `DIEValue` to be stored/passed/etc. by value, instead of
reference. It's now a discriminated union, with a `Val` field storing
the actual type. The classes that used to inherit from `DIEValue` no
longer do. There are two categories of these:
- Small values fit in a single pointer and are stored by value.
- Large values require auxiliary storage, and are stored by reference.
The only non-mechanical change is to tools/dsymutil/DwarfLinker.cpp. It
was relying on `DIEInteger`s being passed around by reference, so I
replaced that assumption with a `PatchLocation` type that stores a safe
reference to where the `DIEInteger` lives instead.
This commit causes a temporary regression in memory usage, since I've
left merging `DIEAbbrevData` into `DIEValue` for a follow-up commit. I
measured an increase from 845 MB to 879 MB, around 3.9%. The follow-up
drops it lower than the starting point, and I've only recently brought
the memory this low anyway, so I'm committing these changes separately
to keep them incremental. (I also considered swapping the commits, but
the other one first would cause a lot more code churn.)
(I'm looking at `llc` memory usage on `verify-uselistorder.lto.opt.bc`;
see r236629 for details.)
--
llvm-svn: 238362
2015-05-28 06:14:58 +08:00
|
|
|
void DIELoc::EmitValue(const AsmPrinter *Asm, dwarf::Form Form) const {
|
2014-02-16 16:46:55 +08:00
|
|
|
switch (Form) {
|
|
|
|
default: llvm_unreachable("Improper form for block");
|
|
|
|
case dwarf::DW_FORM_block1: Asm->EmitInt8(Size); break;
|
|
|
|
case dwarf::DW_FORM_block2: Asm->EmitInt16(Size); break;
|
|
|
|
case dwarf::DW_FORM_block4: Asm->EmitInt32(Size); break;
|
|
|
|
case dwarf::DW_FORM_block:
|
|
|
|
case dwarf::DW_FORM_exprloc:
|
|
|
|
Asm->EmitULEB128(Size); break;
|
|
|
|
}
|
|
|
|
|
2015-08-03 04:42:45 +08:00
|
|
|
for (const auto &V : values())
|
2015-06-25 02:48:11 +08:00
|
|
|
V.EmitValue(Asm);
|
2014-02-16 16:46:55 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/// SizeOf - Determine size of location data in bytes.
|
|
|
|
///
|
Reapply "AsmPrinter: Change DIEValue to be stored by value"
This reverts commit r238350, effectively reapplying r238349 after fixing
(all?) the problems, all somehow related to how I was using
`AlignedArrayCharUnion<>` inside `DIEValue`:
- MSVC can only handle `sizeof()` on types, not values. Change the
assert.
- GCC doesn't know the `is_trivially_copyable` type trait. Instead of
asserting it, add destructors.
- Call placement new even when constructing POD (i.e., the pointers).
- Instead of copying the char buffer, copy the casted classes.
I've left in a couple of `static_assert`s that I think both MSVC and GCC
know how to handle. If the bots disagree with me, I'll remove them.
- Check that the constructed type is either standard layout or a
pointer. This protects against a programming error: we really want
the "small" `DIEValue`s to be small and simple, so don't
accidentally change them not to be.
- Similarly, check that the size of the buffer is no bigger than a
`uint64_t` or a pointer. (I thought checking against
`sizeof(uint64_t)` would be good enough, but Chandler suggested that
pointers might sometimes be bigger than that in the context of
sanitizers.)
I've also committed r238359 in the meantime, which introduces a
DIEValue.def to simplify dispatching between the various types (thanks
to a review comment by David Blaikie). Without that, this commit would
be almost unintelligible.
Here's the original commit message:
--
Change `DIEValue` to be stored/passed/etc. by value, instead of
reference. It's now a discriminated union, with a `Val` field storing
the actual type. The classes that used to inherit from `DIEValue` no
longer do. There are two categories of these:
- Small values fit in a single pointer and are stored by value.
- Large values require auxiliary storage, and are stored by reference.
The only non-mechanical change is to tools/dsymutil/DwarfLinker.cpp. It
was relying on `DIEInteger`s being passed around by reference, so I
replaced that assumption with a `PatchLocation` type that stores a safe
reference to where the `DIEInteger` lives instead.
This commit causes a temporary regression in memory usage, since I've
left merging `DIEAbbrevData` into `DIEValue` for a follow-up commit. I
measured an increase from 845 MB to 879 MB, around 3.9%. The follow-up
drops it lower than the starting point, and I've only recently brought
the memory this low anyway, so I'm committing these changes separately
to keep them incremental. (I also considered swapping the commits, but
the other one first would cause a lot more code churn.)
(I'm looking at `llc` memory usage on `verify-uselistorder.lto.opt.bc`;
see r236629 for details.)
--
llvm-svn: 238362
2015-05-28 06:14:58 +08:00
|
|
|
unsigned DIELoc::SizeOf(const AsmPrinter *AP, dwarf::Form Form) const {
|
2014-02-16 16:46:55 +08:00
|
|
|
switch (Form) {
|
|
|
|
case dwarf::DW_FORM_block1: return Size + sizeof(int8_t);
|
|
|
|
case dwarf::DW_FORM_block2: return Size + sizeof(int16_t);
|
|
|
|
case dwarf::DW_FORM_block4: return Size + sizeof(int32_t);
|
|
|
|
case dwarf::DW_FORM_block:
|
|
|
|
case dwarf::DW_FORM_exprloc:
|
2014-02-22 22:00:39 +08:00
|
|
|
return Size + getULEB128Size(Size);
|
2014-02-16 16:46:55 +08:00
|
|
|
default: llvm_unreachable("Improper form for block");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-11-24 10:21:43 +08:00
|
|
|
LLVM_DUMP_METHOD
|
Reapply "AsmPrinter: Change DIEValue to be stored by value"
This reverts commit r238350, effectively reapplying r238349 after fixing
(all?) the problems, all somehow related to how I was using
`AlignedArrayCharUnion<>` inside `DIEValue`:
- MSVC can only handle `sizeof()` on types, not values. Change the
assert.
- GCC doesn't know the `is_trivially_copyable` type trait. Instead of
asserting it, add destructors.
- Call placement new even when constructing POD (i.e., the pointers).
- Instead of copying the char buffer, copy the casted classes.
I've left in a couple of `static_assert`s that I think both MSVC and GCC
know how to handle. If the bots disagree with me, I'll remove them.
- Check that the constructed type is either standard layout or a
pointer. This protects against a programming error: we really want
the "small" `DIEValue`s to be small and simple, so don't
accidentally change them not to be.
- Similarly, check that the size of the buffer is no bigger than a
`uint64_t` or a pointer. (I thought checking against
`sizeof(uint64_t)` would be good enough, but Chandler suggested that
pointers might sometimes be bigger than that in the context of
sanitizers.)
I've also committed r238359 in the meantime, which introduces a
DIEValue.def to simplify dispatching between the various types (thanks
to a review comment by David Blaikie). Without that, this commit would
be almost unintelligible.
Here's the original commit message:
--
Change `DIEValue` to be stored/passed/etc. by value, instead of
reference. It's now a discriminated union, with a `Val` field storing
the actual type. The classes that used to inherit from `DIEValue` no
longer do. There are two categories of these:
- Small values fit in a single pointer and are stored by value.
- Large values require auxiliary storage, and are stored by reference.
The only non-mechanical change is to tools/dsymutil/DwarfLinker.cpp. It
was relying on `DIEInteger`s being passed around by reference, so I
replaced that assumption with a `PatchLocation` type that stores a safe
reference to where the `DIEInteger` lives instead.
This commit causes a temporary regression in memory usage, since I've
left merging `DIEAbbrevData` into `DIEValue` for a follow-up commit. I
measured an increase from 845 MB to 879 MB, around 3.9%. The follow-up
drops it lower than the starting point, and I've only recently brought
the memory this low anyway, so I'm committing these changes separately
to keep them incremental. (I also considered swapping the commits, but
the other one first would cause a lot more code churn.)
(I'm looking at `llc` memory usage on `verify-uselistorder.lto.opt.bc`;
see r236629 for details.)
--
llvm-svn: 238362
2015-05-28 06:14:58 +08:00
|
|
|
void DIELoc::print(raw_ostream &O) const {
|
2015-08-03 04:46:49 +08:00
|
|
|
printValues(O, *this, "ExprLoc", Size, 5);
|
2014-02-16 16:46:55 +08:00
|
|
|
}
|
|
|
|
|
2009-05-15 08:11:17 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// DIEBlock Implementation
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
/// ComputeSize - calculate the size of the block.
|
|
|
|
///
|
2015-03-04 10:30:08 +08:00
|
|
|
unsigned DIEBlock::ComputeSize(const AsmPrinter *AP) const {
|
2014-02-28 02:36:10 +08:00
|
|
|
if (!Size) {
|
2015-08-03 04:42:45 +08:00
|
|
|
for (const auto &V : values())
|
2015-06-25 02:48:11 +08:00
|
|
|
Size += V.SizeOf(AP);
|
2014-02-28 02:36:10 +08:00
|
|
|
}
|
2009-05-15 08:11:17 +08:00
|
|
|
|
2014-02-28 02:36:10 +08:00
|
|
|
return Size;
|
2009-05-15 08:11:17 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/// EmitValue - Emit block data.
|
|
|
|
///
|
Reapply "AsmPrinter: Change DIEValue to be stored by value"
This reverts commit r238350, effectively reapplying r238349 after fixing
(all?) the problems, all somehow related to how I was using
`AlignedArrayCharUnion<>` inside `DIEValue`:
- MSVC can only handle `sizeof()` on types, not values. Change the
assert.
- GCC doesn't know the `is_trivially_copyable` type trait. Instead of
asserting it, add destructors.
- Call placement new even when constructing POD (i.e., the pointers).
- Instead of copying the char buffer, copy the casted classes.
I've left in a couple of `static_assert`s that I think both MSVC and GCC
know how to handle. If the bots disagree with me, I'll remove them.
- Check that the constructed type is either standard layout or a
pointer. This protects against a programming error: we really want
the "small" `DIEValue`s to be small and simple, so don't
accidentally change them not to be.
- Similarly, check that the size of the buffer is no bigger than a
`uint64_t` or a pointer. (I thought checking against
`sizeof(uint64_t)` would be good enough, but Chandler suggested that
pointers might sometimes be bigger than that in the context of
sanitizers.)
I've also committed r238359 in the meantime, which introduces a
DIEValue.def to simplify dispatching between the various types (thanks
to a review comment by David Blaikie). Without that, this commit would
be almost unintelligible.
Here's the original commit message:
--
Change `DIEValue` to be stored/passed/etc. by value, instead of
reference. It's now a discriminated union, with a `Val` field storing
the actual type. The classes that used to inherit from `DIEValue` no
longer do. There are two categories of these:
- Small values fit in a single pointer and are stored by value.
- Large values require auxiliary storage, and are stored by reference.
The only non-mechanical change is to tools/dsymutil/DwarfLinker.cpp. It
was relying on `DIEInteger`s being passed around by reference, so I
replaced that assumption with a `PatchLocation` type that stores a safe
reference to where the `DIEInteger` lives instead.
This commit causes a temporary regression in memory usage, since I've
left merging `DIEAbbrevData` into `DIEValue` for a follow-up commit. I
measured an increase from 845 MB to 879 MB, around 3.9%. The follow-up
drops it lower than the starting point, and I've only recently brought
the memory this low anyway, so I'm committing these changes separately
to keep them incremental. (I also considered swapping the commits, but
the other one first would cause a lot more code churn.)
(I'm looking at `llc` memory usage on `verify-uselistorder.lto.opt.bc`;
see r236629 for details.)
--
llvm-svn: 238362
2015-05-28 06:14:58 +08:00
|
|
|
void DIEBlock::EmitValue(const AsmPrinter *Asm, dwarf::Form Form) const {
|
2009-05-15 08:11:17 +08:00
|
|
|
switch (Form) {
|
2012-02-05 16:31:47 +08:00
|
|
|
default: llvm_unreachable("Improper form for block");
|
2010-04-05 03:09:29 +08:00
|
|
|
case dwarf::DW_FORM_block1: Asm->EmitInt8(Size); break;
|
|
|
|
case dwarf::DW_FORM_block2: Asm->EmitInt16(Size); break;
|
|
|
|
case dwarf::DW_FORM_block4: Asm->EmitInt32(Size); break;
|
|
|
|
case dwarf::DW_FORM_block: Asm->EmitULEB128(Size); break;
|
2009-05-15 08:11:17 +08:00
|
|
|
}
|
|
|
|
|
2015-08-03 04:42:45 +08:00
|
|
|
for (const auto &V : values())
|
2015-06-25 02:48:11 +08:00
|
|
|
V.EmitValue(Asm);
|
2009-05-15 08:11:17 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/// SizeOf - Determine size of block data in bytes.
|
|
|
|
///
|
Reapply "AsmPrinter: Change DIEValue to be stored by value"
This reverts commit r238350, effectively reapplying r238349 after fixing
(all?) the problems, all somehow related to how I was using
`AlignedArrayCharUnion<>` inside `DIEValue`:
- MSVC can only handle `sizeof()` on types, not values. Change the
assert.
- GCC doesn't know the `is_trivially_copyable` type trait. Instead of
asserting it, add destructors.
- Call placement new even when constructing POD (i.e., the pointers).
- Instead of copying the char buffer, copy the casted classes.
I've left in a couple of `static_assert`s that I think both MSVC and GCC
know how to handle. If the bots disagree with me, I'll remove them.
- Check that the constructed type is either standard layout or a
pointer. This protects against a programming error: we really want
the "small" `DIEValue`s to be small and simple, so don't
accidentally change them not to be.
- Similarly, check that the size of the buffer is no bigger than a
`uint64_t` or a pointer. (I thought checking against
`sizeof(uint64_t)` would be good enough, but Chandler suggested that
pointers might sometimes be bigger than that in the context of
sanitizers.)
I've also committed r238359 in the meantime, which introduces a
DIEValue.def to simplify dispatching between the various types (thanks
to a review comment by David Blaikie). Without that, this commit would
be almost unintelligible.
Here's the original commit message:
--
Change `DIEValue` to be stored/passed/etc. by value, instead of
reference. It's now a discriminated union, with a `Val` field storing
the actual type. The classes that used to inherit from `DIEValue` no
longer do. There are two categories of these:
- Small values fit in a single pointer and are stored by value.
- Large values require auxiliary storage, and are stored by reference.
The only non-mechanical change is to tools/dsymutil/DwarfLinker.cpp. It
was relying on `DIEInteger`s being passed around by reference, so I
replaced that assumption with a `PatchLocation` type that stores a safe
reference to where the `DIEInteger` lives instead.
This commit causes a temporary regression in memory usage, since I've
left merging `DIEAbbrevData` into `DIEValue` for a follow-up commit. I
measured an increase from 845 MB to 879 MB, around 3.9%. The follow-up
drops it lower than the starting point, and I've only recently brought
the memory this low anyway, so I'm committing these changes separately
to keep them incremental. (I also considered swapping the commits, but
the other one first would cause a lot more code churn.)
(I'm looking at `llc` memory usage on `verify-uselistorder.lto.opt.bc`;
see r236629 for details.)
--
llvm-svn: 238362
2015-05-28 06:14:58 +08:00
|
|
|
unsigned DIEBlock::SizeOf(const AsmPrinter *AP, dwarf::Form Form) const {
|
2009-05-15 08:11:17 +08:00
|
|
|
switch (Form) {
|
|
|
|
case dwarf::DW_FORM_block1: return Size + sizeof(int8_t);
|
|
|
|
case dwarf::DW_FORM_block2: return Size + sizeof(int16_t);
|
|
|
|
case dwarf::DW_FORM_block4: return Size + sizeof(int32_t);
|
2014-02-22 22:00:39 +08:00
|
|
|
case dwarf::DW_FORM_block: return Size + getULEB128Size(Size);
|
2012-01-21 05:51:11 +08:00
|
|
|
default: llvm_unreachable("Improper form for block");
|
2009-05-15 08:11:17 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-11-24 10:21:43 +08:00
|
|
|
LLVM_DUMP_METHOD
|
Reapply "AsmPrinter: Change DIEValue to be stored by value"
This reverts commit r238350, effectively reapplying r238349 after fixing
(all?) the problems, all somehow related to how I was using
`AlignedArrayCharUnion<>` inside `DIEValue`:
- MSVC can only handle `sizeof()` on types, not values. Change the
assert.
- GCC doesn't know the `is_trivially_copyable` type trait. Instead of
asserting it, add destructors.
- Call placement new even when constructing POD (i.e., the pointers).
- Instead of copying the char buffer, copy the casted classes.
I've left in a couple of `static_assert`s that I think both MSVC and GCC
know how to handle. If the bots disagree with me, I'll remove them.
- Check that the constructed type is either standard layout or a
pointer. This protects against a programming error: we really want
the "small" `DIEValue`s to be small and simple, so don't
accidentally change them not to be.
- Similarly, check that the size of the buffer is no bigger than a
`uint64_t` or a pointer. (I thought checking against
`sizeof(uint64_t)` would be good enough, but Chandler suggested that
pointers might sometimes be bigger than that in the context of
sanitizers.)
I've also committed r238359 in the meantime, which introduces a
DIEValue.def to simplify dispatching between the various types (thanks
to a review comment by David Blaikie). Without that, this commit would
be almost unintelligible.
Here's the original commit message:
--
Change `DIEValue` to be stored/passed/etc. by value, instead of
reference. It's now a discriminated union, with a `Val` field storing
the actual type. The classes that used to inherit from `DIEValue` no
longer do. There are two categories of these:
- Small values fit in a single pointer and are stored by value.
- Large values require auxiliary storage, and are stored by reference.
The only non-mechanical change is to tools/dsymutil/DwarfLinker.cpp. It
was relying on `DIEInteger`s being passed around by reference, so I
replaced that assumption with a `PatchLocation` type that stores a safe
reference to where the `DIEInteger` lives instead.
This commit causes a temporary regression in memory usage, since I've
left merging `DIEAbbrevData` into `DIEValue` for a follow-up commit. I
measured an increase from 845 MB to 879 MB, around 3.9%. The follow-up
drops it lower than the starting point, and I've only recently brought
the memory this low anyway, so I'm committing these changes separately
to keep them incremental. (I also considered swapping the commits, but
the other one first would cause a lot more code churn.)
(I'm looking at `llc` memory usage on `verify-uselistorder.lto.opt.bc`;
see r236629 for details.)
--
llvm-svn: 238362
2015-05-28 06:14:58 +08:00
|
|
|
void DIEBlock::print(raw_ostream &O) const {
|
2015-08-03 04:46:49 +08:00
|
|
|
printValues(O, *this, "Blk", Size, 5);
|
2009-05-15 08:11:17 +08:00
|
|
|
}
|
2014-03-06 06:41:20 +08:00
|
|
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// DIELocList Implementation
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
Reapply "AsmPrinter: Change DIEValue to be stored by value"
This reverts commit r238350, effectively reapplying r238349 after fixing
(all?) the problems, all somehow related to how I was using
`AlignedArrayCharUnion<>` inside `DIEValue`:
- MSVC can only handle `sizeof()` on types, not values. Change the
assert.
- GCC doesn't know the `is_trivially_copyable` type trait. Instead of
asserting it, add destructors.
- Call placement new even when constructing POD (i.e., the pointers).
- Instead of copying the char buffer, copy the casted classes.
I've left in a couple of `static_assert`s that I think both MSVC and GCC
know how to handle. If the bots disagree with me, I'll remove them.
- Check that the constructed type is either standard layout or a
pointer. This protects against a programming error: we really want
the "small" `DIEValue`s to be small and simple, so don't
accidentally change them not to be.
- Similarly, check that the size of the buffer is no bigger than a
`uint64_t` or a pointer. (I thought checking against
`sizeof(uint64_t)` would be good enough, but Chandler suggested that
pointers might sometimes be bigger than that in the context of
sanitizers.)
I've also committed r238359 in the meantime, which introduces a
DIEValue.def to simplify dispatching between the various types (thanks
to a review comment by David Blaikie). Without that, this commit would
be almost unintelligible.
Here's the original commit message:
--
Change `DIEValue` to be stored/passed/etc. by value, instead of
reference. It's now a discriminated union, with a `Val` field storing
the actual type. The classes that used to inherit from `DIEValue` no
longer do. There are two categories of these:
- Small values fit in a single pointer and are stored by value.
- Large values require auxiliary storage, and are stored by reference.
The only non-mechanical change is to tools/dsymutil/DwarfLinker.cpp. It
was relying on `DIEInteger`s being passed around by reference, so I
replaced that assumption with a `PatchLocation` type that stores a safe
reference to where the `DIEInteger` lives instead.
This commit causes a temporary regression in memory usage, since I've
left merging `DIEAbbrevData` into `DIEValue` for a follow-up commit. I
measured an increase from 845 MB to 879 MB, around 3.9%. The follow-up
drops it lower than the starting point, and I've only recently brought
the memory this low anyway, so I'm committing these changes separately
to keep them incremental. (I also considered swapping the commits, but
the other one first would cause a lot more code churn.)
(I'm looking at `llc` memory usage on `verify-uselistorder.lto.opt.bc`;
see r236629 for details.)
--
llvm-svn: 238362
2015-05-28 06:14:58 +08:00
|
|
|
unsigned DIELocList::SizeOf(const AsmPrinter *AP, dwarf::Form Form) const {
|
2014-03-06 06:41:20 +08:00
|
|
|
if (Form == dwarf::DW_FORM_data4)
|
|
|
|
return 4;
|
|
|
|
if (Form == dwarf::DW_FORM_sec_offset)
|
|
|
|
return 4;
|
2017-04-18 01:41:25 +08:00
|
|
|
return AP->MAI->getCodePointerSize();
|
2014-03-06 06:41:20 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/// EmitValue - Emit label value.
|
|
|
|
///
|
Reapply "AsmPrinter: Change DIEValue to be stored by value"
This reverts commit r238350, effectively reapplying r238349 after fixing
(all?) the problems, all somehow related to how I was using
`AlignedArrayCharUnion<>` inside `DIEValue`:
- MSVC can only handle `sizeof()` on types, not values. Change the
assert.
- GCC doesn't know the `is_trivially_copyable` type trait. Instead of
asserting it, add destructors.
- Call placement new even when constructing POD (i.e., the pointers).
- Instead of copying the char buffer, copy the casted classes.
I've left in a couple of `static_assert`s that I think both MSVC and GCC
know how to handle. If the bots disagree with me, I'll remove them.
- Check that the constructed type is either standard layout or a
pointer. This protects against a programming error: we really want
the "small" `DIEValue`s to be small and simple, so don't
accidentally change them not to be.
- Similarly, check that the size of the buffer is no bigger than a
`uint64_t` or a pointer. (I thought checking against
`sizeof(uint64_t)` would be good enough, but Chandler suggested that
pointers might sometimes be bigger than that in the context of
sanitizers.)
I've also committed r238359 in the meantime, which introduces a
DIEValue.def to simplify dispatching between the various types (thanks
to a review comment by David Blaikie). Without that, this commit would
be almost unintelligible.
Here's the original commit message:
--
Change `DIEValue` to be stored/passed/etc. by value, instead of
reference. It's now a discriminated union, with a `Val` field storing
the actual type. The classes that used to inherit from `DIEValue` no
longer do. There are two categories of these:
- Small values fit in a single pointer and are stored by value.
- Large values require auxiliary storage, and are stored by reference.
The only non-mechanical change is to tools/dsymutil/DwarfLinker.cpp. It
was relying on `DIEInteger`s being passed around by reference, so I
replaced that assumption with a `PatchLocation` type that stores a safe
reference to where the `DIEInteger` lives instead.
This commit causes a temporary regression in memory usage, since I've
left merging `DIEAbbrevData` into `DIEValue` for a follow-up commit. I
measured an increase from 845 MB to 879 MB, around 3.9%. The follow-up
drops it lower than the starting point, and I've only recently brought
the memory this low anyway, so I'm committing these changes separately
to keep them incremental. (I also considered swapping the commits, but
the other one first would cause a lot more code churn.)
(I'm looking at `llc` memory usage on `verify-uselistorder.lto.opt.bc`;
see r236629 for details.)
--
llvm-svn: 238362
2015-05-28 06:14:58 +08:00
|
|
|
void DIELocList::EmitValue(const AsmPrinter *AP, dwarf::Form Form) const {
|
2014-03-25 09:44:02 +08:00
|
|
|
DwarfDebug *DD = AP->getDwarfDebug();
|
AsmPrinter: Create a unified .debug_loc stream
This commit removes `DebugLocList` and replaces it with
`DebugLocStream`.
- `DebugLocEntry` no longer contains its byte/comment streams.
- The `DebugLocEntry` list for a variable/inlined-at pair is allocated
on the stack, and released right after `DebugLocEntry::finalize()`
(possible because of the refactoring in r231023). Now, only one
list is in memory at a time now.
- There's a single unified stream for the `.debug_loc` section that
persists, stored in the new `DebugLocStream` data structure.
The last point is important: this collapses the nested `SmallVector<>`s
from `DebugLocList` into unified streams. We previously had something
like the following:
vec<tuple<Label, CU,
vec<tuple<BeginSym, EndSym,
vec<Value>,
vec<char>,
vec<string>>>>>
A `SmallVector` can avoid allocations, but is statically fairly large
for a vector: three pointers plus the size of the small storage, which
is the number of elements in small mode times the element size).
Nesting these is expensive, since an inner vector's size contributes to
the element size of an outer one. (Nesting any vector is expensive...)
In the old data structure, the outer vector's *element* size was 632B,
excluding allocation costs for when the middle and inner vectors
exceeded their small sizes. 312B of this was for the "three" pointers
in the vector-tree beneath it. If you assume 1M functions with an
average of 10 variable/inlined-at pairs each (in an LTO scenario),
that's almost 6GB (besides inner allocations), with almost 3GB for the
"three" pointers.
This came up in a heap profile a little while ago of a `clang -flto -g`
bootstrap, with `DwarfDebug::collectVariableInfo()` using something like
10-15% of the total memory.
With this commit, we have:
tuple<vec<tuple<Label, CU, Offset>>,
vec<tuple<BeginSym, EndSym, Offset, Offset>>,
vec<char>,
vec<string>>
The offsets are used to create `ArrayRef` slices of adjacent
`SmallVector`s. This reduces the number of vectors to four (unrelated
to the number of variable/inlined-at pairs), and caps the number of
allocations at the same number.
Besides saving memory and limiting allocations, this is NFC.
I don't know my way around this code very well yet, but I wonder if we
could go further: why stream to a side-table, instead of directly to the
output stream?
llvm-svn: 235229
2015-04-18 05:34:47 +08:00
|
|
|
MCSymbol *Label = DD->getDebugLocs().getList(Index).Label;
|
2015-06-17 07:22:02 +08:00
|
|
|
AP->emitDwarfSymbolReference(Label, /*ForceOffset*/ DD->useSplitDwarf());
|
2014-03-06 06:41:20 +08:00
|
|
|
}
|
|
|
|
|
2015-11-24 10:21:43 +08:00
|
|
|
LLVM_DUMP_METHOD
|
Reapply "AsmPrinter: Change DIEValue to be stored by value"
This reverts commit r238350, effectively reapplying r238349 after fixing
(all?) the problems, all somehow related to how I was using
`AlignedArrayCharUnion<>` inside `DIEValue`:
- MSVC can only handle `sizeof()` on types, not values. Change the
assert.
- GCC doesn't know the `is_trivially_copyable` type trait. Instead of
asserting it, add destructors.
- Call placement new even when constructing POD (i.e., the pointers).
- Instead of copying the char buffer, copy the casted classes.
I've left in a couple of `static_assert`s that I think both MSVC and GCC
know how to handle. If the bots disagree with me, I'll remove them.
- Check that the constructed type is either standard layout or a
pointer. This protects against a programming error: we really want
the "small" `DIEValue`s to be small and simple, so don't
accidentally change them not to be.
- Similarly, check that the size of the buffer is no bigger than a
`uint64_t` or a pointer. (I thought checking against
`sizeof(uint64_t)` would be good enough, but Chandler suggested that
pointers might sometimes be bigger than that in the context of
sanitizers.)
I've also committed r238359 in the meantime, which introduces a
DIEValue.def to simplify dispatching between the various types (thanks
to a review comment by David Blaikie). Without that, this commit would
be almost unintelligible.
Here's the original commit message:
--
Change `DIEValue` to be stored/passed/etc. by value, instead of
reference. It's now a discriminated union, with a `Val` field storing
the actual type. The classes that used to inherit from `DIEValue` no
longer do. There are two categories of these:
- Small values fit in a single pointer and are stored by value.
- Large values require auxiliary storage, and are stored by reference.
The only non-mechanical change is to tools/dsymutil/DwarfLinker.cpp. It
was relying on `DIEInteger`s being passed around by reference, so I
replaced that assumption with a `PatchLocation` type that stores a safe
reference to where the `DIEInteger` lives instead.
This commit causes a temporary regression in memory usage, since I've
left merging `DIEAbbrevData` into `DIEValue` for a follow-up commit. I
measured an increase from 845 MB to 879 MB, around 3.9%. The follow-up
drops it lower than the starting point, and I've only recently brought
the memory this low anyway, so I'm committing these changes separately
to keep them incremental. (I also considered swapping the commits, but
the other one first would cause a lot more code churn.)
(I'm looking at `llc` memory usage on `verify-uselistorder.lto.opt.bc`;
see r236629 for details.)
--
llvm-svn: 238362
2015-05-28 06:14:58 +08:00
|
|
|
void DIELocList::print(raw_ostream &O) const { O << "LocList: " << Index; }
|