1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-22 18:54:02 +01:00

[DebugInfo] Support DWARF v5 source code embedding extension

In DWARF v5 the Line Number Program Header is extensible, allowing values with
new content types. In this extension a content type is added,
DW_LNCT_LLVM_source, which contains the embedded source code of the file.

Add new optional attribute for !DIFile IR metadata called source which contains
source text. Use this to output the source to the DWARF line table of code
objects. Analogously extend METADATA_FILE in Bitcode and .file directive in ASM
to support optional source.

Teach llvm-dwarfdump and llvm-objdump about the new values. Update the output
format of llvm-dwarfdump to make room for the new attribute on file_names
entries, and support embedded sources for the -source option in llvm-objdump.

Differential Revision: https://reviews.llvm.org/D42765

llvm-svn: 325970
This commit is contained in:
Scott Linder 2018-02-23 23:01:06 +00:00
parent 636437d0bf
commit 03316a5291
51 changed files with 580 additions and 220 deletions

View File

@ -780,7 +780,7 @@ The following relocation types are supported:
DWARF DWARF
----- -----
Standard DWARF [DWARF]_ Version 2 sections can be generated. These contain Standard DWARF [DWARF]_ Version 5 sections can be generated. These contain
information that maps the code object executable code and data to the source information that maps the code object executable code and data to the source
language constructs. It can be used by tools such as debuggers and profilers. language constructs. It can be used by tools such as debuggers and profilers.
@ -836,10 +836,60 @@ Register Mapping
Source Text Source Text
~~~~~~~~~~~ ~~~~~~~~~~~
*This section is WIP.* Source text for online-compiled programs (e.g. those compiled by the OpenCL
runtime) may be embedded into the DWARF v5 line table using the ``clang
-gembed-source`` option, described in table :ref:`amdgpu-debug-options`.
.. TODO For example:
DWARF extension to include runtime generated source text.
``-gembed-source``
Enable the embedded source DWARF v5 extension.
``-gno-embed-source``
Disable the embedded source DWARF v5 extension.
.. table:: AMDGPU Debug Options
:name: amdgpu-debug-options
==================== ==================================================
Debug Flag Description
==================== ==================================================
-g[no-]embed-source Enable/disable embedding source text in DWARF
debug sections. Useful for environments where
source cannot be written to disk, such as
when performing online compilation.
==================== ==================================================
This option enables one extended content types in the DWARF v5 Line Number
Program Header, which is used to encode embedded source.
.. table:: AMDGPU DWARF Line Number Program Header Extended Content Types
:name: amdgpu-dwarf-extended-content-types
============================ ======================
Content Type Form
============================ ======================
``DW_LNCT_LLVM_source`` ``DW_FORM_line_strp``
============================ ======================
The source field will contain the UTF-8 encoded, null-terminated source text
with ``'\n'`` line endings. When the source field is present, consumers can use
the embedded source instead of attempting to discover the source on disk. When
the source field is absent, consumers can access the file to get the source
text.
The above content type appears in the ``file_name_entry_format`` field of the
line table prologue, and its corresponding value appear in the ``file_names``
field. The current encoding of the content type is documented in table
:ref:`amdgpu-dwarf-extended-content-types-encoding`
.. table:: AMDGPU DWARF Line Number Program Header Extended Content Types Encoding
:name: amdgpu-dwarf-extended-content-types-encoding
============================ ====================
Content Type Value
============================ ====================
``DW_LNCT_LLVM_source`` 0x2001
============================ ====================
.. _amdgpu-code-conventions: .. _amdgpu-code-conventions:

View File

@ -747,6 +747,9 @@ HANDLE_DW_LNCT(0x02, directory_index)
HANDLE_DW_LNCT(0x03, timestamp) HANDLE_DW_LNCT(0x03, timestamp)
HANDLE_DW_LNCT(0x04, size) HANDLE_DW_LNCT(0x04, size)
HANDLE_DW_LNCT(0x05, MD5) HANDLE_DW_LNCT(0x05, MD5)
// A vendor extension until http://dwarfstd.org/ShowIssue.php?issue=180201.1 is
// accepted and incorporated into the next DWARF standard.
HANDLE_DW_LNCT(0x2001, LLVM_source)
// DWARF v5 Macro information. // DWARF v5 Macro information.
HANDLE_DW_MACRO(0x01, define) HANDLE_DW_MACRO(0x01, define)

View File

@ -31,6 +31,7 @@ namespace llvm {
struct DILineInfo { struct DILineInfo {
std::string FileName; std::string FileName;
std::string FunctionName; std::string FunctionName;
Optional<StringRef> Source;
uint32_t Line = 0; uint32_t Line = 0;
uint32_t Column = 0; uint32_t Column = 0;
uint32_t StartLine = 0; uint32_t StartLine = 0;

View File

@ -10,6 +10,7 @@
#ifndef LLVM_DEBUGINFO_DWARFDEBUGLINE_H #ifndef LLVM_DEBUGINFO_DWARFDEBUGLINE_H
#define LLVM_DEBUGINFO_DWARFDEBUGLINE_H #define LLVM_DEBUGINFO_DWARFDEBUGLINE_H
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringRef.h"
#include "llvm/DebugInfo/DIContext.h" #include "llvm/DebugInfo/DIContext.h"
#include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h" #include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h"
@ -36,6 +37,25 @@ public:
uint64_t ModTime = 0; uint64_t ModTime = 0;
uint64_t Length = 0; uint64_t Length = 0;
MD5::MD5Result Checksum; MD5::MD5Result Checksum;
DWARFFormValue Source;
};
/// Tracks which optional content types are present in a DWARF file name
/// entry format.
struct ContentTypeTracker {
ContentTypeTracker() = default;
/// Whether filename entries provide a modification timestamp.
bool HasModTime = false;
/// Whether filename entries provide a file size.
bool HasLength = false;
/// For v5, whether filename entries provide an MD5 checksum.
bool HasMD5 = false;
/// For v5, whether filename entries provide source text.
bool HasSource = false;
/// Update tracked content types with \p ContentType.
void trackContentType(dwarf::LineNumberEntryFormat ContentType);
}; };
struct Prologue { struct Prologue {
@ -68,8 +88,8 @@ public:
uint8_t LineRange; uint8_t LineRange;
/// The number assigned to the first special opcode. /// The number assigned to the first special opcode.
uint8_t OpcodeBase; uint8_t OpcodeBase;
/// For v5, whether filename entries provide an MD5 checksum. /// This tracks which optional file format content types are present.
bool HasMD5; ContentTypeTracker ContentTypes;
std::vector<uint8_t> StandardOpcodeLengths; std::vector<uint8_t> StandardOpcodeLengths;
std::vector<DWARFFormValue> IncludeDirectories; std::vector<DWARFFormValue> IncludeDirectories;
std::vector<FileNameEntry> FileNames; std::vector<FileNameEntry> FileNames;
@ -239,6 +259,8 @@ public:
private: private:
uint32_t findRowInSeq(const DWARFDebugLine::Sequence &Seq, uint32_t findRowInSeq(const DWARFDebugLine::Sequence &Seq,
uint64_t Address) const; uint64_t Address) const;
Optional<StringRef> getSourceByIndex(uint64_t FileIndex,
DILineInfoSpecifier::FileLineInfoKind Kind) const;
}; };
const LineTable *getLineTable(uint32_t Offset) const; const LineTable *getLineTable(uint32_t Offset) const;

View File

@ -18,7 +18,7 @@
#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/MapVector.h" #include "llvm/ADT/MapVector.h"
#include "llvm/ADT/None.h" #include "llvm/ADT/Optional.h"
#include "llvm/ADT/SetVector.h" #include "llvm/ADT/SetVector.h"
#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringRef.h"
@ -141,10 +141,13 @@ namespace llvm {
/// Create a file descriptor to hold debugging information for a file. /// Create a file descriptor to hold debugging information for a file.
/// \param Filename File name. /// \param Filename File name.
/// \param Directory Directory. /// \param Directory Directory.
/// \param Checksum Checksum kind (e.g. CSK_MD5, CSK_SHA1, etc.) and value. /// \param Checksum Optional checksum kind (e.g. CSK_MD5, CSK_SHA1, etc.)
/// and value.
/// \param Source Optional source text.
DIFile * DIFile *
createFile(StringRef Filename, StringRef Directory, createFile(StringRef Filename, StringRef Directory,
Optional<DIFile::ChecksumInfo<StringRef>> Checksum = None); Optional<DIFile::ChecksumInfo<StringRef>> Checksum = None,
Optional<StringRef> Source = None);
/// Create debugging information entry for a macro. /// Create debugging information entry for a macro.
/// \param Parent Macro parent (could be nullptr). /// \param Parent Macro parent (could be nullptr).

View File

@ -455,6 +455,7 @@ public:
inline StringRef getFilename() const; inline StringRef getFilename() const;
inline StringRef getDirectory() const; inline StringRef getDirectory() const;
inline Optional<StringRef> getSource() const;
StringRef getName() const; StringRef getName() const;
DIScopeRef getScope() const; DIScopeRef getScope() const;
@ -532,42 +533,48 @@ public:
private: private:
Optional<ChecksumInfo<MDString *>> Checksum; Optional<ChecksumInfo<MDString *>> Checksum;
Optional<MDString *> Source;
DIFile(LLVMContext &C, StorageType Storage, DIFile(LLVMContext &C, StorageType Storage,
Optional<ChecksumInfo<MDString *>> CS, Optional<ChecksumInfo<MDString *>> CS, Optional<MDString *> Src,
ArrayRef<Metadata *> Ops) ArrayRef<Metadata *> Ops)
: DIScope(C, DIFileKind, Storage, dwarf::DW_TAG_file_type, Ops), : DIScope(C, DIFileKind, Storage, dwarf::DW_TAG_file_type, Ops),
Checksum(CS) {} Checksum(CS), Source(Src) {}
~DIFile() = default; ~DIFile() = default;
static DIFile *getImpl(LLVMContext &Context, StringRef Filename, static DIFile *getImpl(LLVMContext &Context, StringRef Filename,
StringRef Directory, StringRef Directory,
Optional<ChecksumInfo<StringRef>> CS, Optional<ChecksumInfo<StringRef>> CS,
Optional<StringRef> Source,
StorageType Storage, bool ShouldCreate = true) { StorageType Storage, bool ShouldCreate = true) {
Optional<ChecksumInfo<MDString *>> MDChecksum; Optional<ChecksumInfo<MDString *>> MDChecksum;
if (CS) if (CS)
MDChecksum.emplace(CS->Kind, getCanonicalMDString(Context, CS->Value)); MDChecksum.emplace(CS->Kind, getCanonicalMDString(Context, CS->Value));
return getImpl(Context, getCanonicalMDString(Context, Filename), return getImpl(Context, getCanonicalMDString(Context, Filename),
getCanonicalMDString(Context, Directory), MDChecksum, getCanonicalMDString(Context, Directory), MDChecksum,
Source ? Optional<MDString *>(getCanonicalMDString(Context, *Source)) : None,
Storage, ShouldCreate); Storage, ShouldCreate);
} }
static DIFile *getImpl(LLVMContext &Context, MDString *Filename, static DIFile *getImpl(LLVMContext &Context, MDString *Filename,
MDString *Directory, MDString *Directory,
Optional<ChecksumInfo<MDString *>> CS, Optional<ChecksumInfo<MDString *>> CS,
StorageType Storage, bool ShouldCreate = true); Optional<MDString *> Source, StorageType Storage,
bool ShouldCreate = true);
TempDIFile cloneImpl() const { TempDIFile cloneImpl() const {
return getTemporary(getContext(), getFilename(), getDirectory(), return getTemporary(getContext(), getFilename(), getDirectory(),
getChecksum()); getChecksum(), getSource());
} }
public: public:
DEFINE_MDNODE_GET(DIFile, (StringRef Filename, StringRef Directory, DEFINE_MDNODE_GET(DIFile, (StringRef Filename, StringRef Directory,
Optional<ChecksumInfo<StringRef>> CS = None), Optional<ChecksumInfo<StringRef>> CS = None,
(Filename, Directory, CS)) Optional<StringRef> Source = None),
(Filename, Directory, CS, Source))
DEFINE_MDNODE_GET(DIFile, (MDString * Filename, MDString *Directory, DEFINE_MDNODE_GET(DIFile, (MDString * Filename, MDString *Directory,
Optional<ChecksumInfo<MDString *>> CS = None), Optional<ChecksumInfo<MDString *>> CS = None,
(Filename, Directory, CS)) Optional<MDString *> Source = None),
(Filename, Directory, CS, Source))
TempDIFile clone() const { return cloneImpl(); } TempDIFile clone() const { return cloneImpl(); }
@ -579,10 +586,14 @@ public:
StringRefChecksum.emplace(Checksum->Kind, Checksum->Value->getString()); StringRefChecksum.emplace(Checksum->Kind, Checksum->Value->getString());
return StringRefChecksum; return StringRefChecksum;
} }
Optional<StringRef> getSource() const {
return Source ? Optional<StringRef>((*Source)->getString()) : None;
}
MDString *getRawFilename() const { return getOperandAs<MDString>(0); } MDString *getRawFilename() const { return getOperandAs<MDString>(0); }
MDString *getRawDirectory() const { return getOperandAs<MDString>(1); } MDString *getRawDirectory() const { return getOperandAs<MDString>(1); }
Optional<ChecksumInfo<MDString *>> getRawChecksum() const { return Checksum; } Optional<ChecksumInfo<MDString *>> getRawChecksum() const { return Checksum; }
Optional<MDString *> getRawSource() const { return Source; }
static StringRef getChecksumKindAsString(ChecksumKind CSKind); static StringRef getChecksumKindAsString(ChecksumKind CSKind);
static Optional<ChecksumKind> getChecksumKind(StringRef CSKindStr); static Optional<ChecksumKind> getChecksumKind(StringRef CSKindStr);
@ -604,6 +615,12 @@ StringRef DIScope::getDirectory() const {
return ""; return "";
} }
Optional<StringRef> DIScope::getSource() const {
if (auto *F = getFile())
return F->getSource();
return None;
}
/// Base class for types. /// Base class for types.
/// ///
/// TODO: Remove the hardcoded name and context, since many types don't use /// TODO: Remove the hardcoded name and context, since many types don't use
@ -1408,6 +1425,7 @@ public:
DIFile *getFile() const { return getScope()->getFile(); } DIFile *getFile() const { return getScope()->getFile(); }
StringRef getFilename() const { return getScope()->getFilename(); } StringRef getFilename() const { return getScope()->getFilename(); }
StringRef getDirectory() const { return getScope()->getDirectory(); } StringRef getDirectory() const { return getScope()->getDirectory(); }
Optional<StringRef> getSource() const { return getScope()->getSource(); }
/// Get the scope where this is inlined. /// Get the scope where this is inlined.
/// ///
@ -2177,6 +2195,12 @@ public:
return ""; return "";
} }
Optional<StringRef> getSource() const {
if (auto *F = getFile())
return F->getSource();
return None;
}
Metadata *getRawScope() const { return getOperand(0); } Metadata *getRawScope() const { return getOperand(0); }
MDString *getRawName() const { return getOperandAs<MDString>(1); } MDString *getRawName() const { return getOperandAs<MDString>(1); }
Metadata *getRawFile() const { return getOperand(2); } Metadata *getRawFile() const { return getOperand(2); }
@ -2624,6 +2648,12 @@ public:
return ""; return "";
} }
Optional<StringRef> getSource() const {
if (auto *F = getFile())
return F->getSource();
return None;
}
MDString *getRawName() const { return getOperandAs<MDString>(0); } MDString *getRawName() const { return getOperandAs<MDString>(0); }
Metadata *getRawFile() const { return getOperand(1); } Metadata *getRawFile() const { return getOperand(1); }
MDString *getRawGetterName() const { return getOperandAs<MDString>(2); } MDString *getRawGetterName() const { return getOperandAs<MDString>(2); }

View File

@ -11,6 +11,7 @@
#define LLVM_MC_MCCONTEXT_H #define LLVM_MC_MCCONTEXT_H
#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/SetVector.h" #include "llvm/ADT/SetVector.h"
#include "llvm/ADT/SmallString.h" #include "llvm/ADT/SmallString.h"
#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/SmallVector.h"
@ -496,7 +497,8 @@ namespace llvm {
/// Creates an entry in the dwarf file and directory tables. /// Creates an entry in the dwarf file and directory tables.
Expected<unsigned> getDwarfFile(StringRef Directory, StringRef FileName, Expected<unsigned> getDwarfFile(StringRef Directory, StringRef FileName,
unsigned FileNumber, unsigned FileNumber,
MD5::MD5Result *Checksum, unsigned CUID); MD5::MD5Result *Checksum,
Optional<StringRef> Source, unsigned CUID);
bool isValidDwarfFileNumber(unsigned FileNumber, unsigned CUID = 0); bool isValidDwarfFileNumber(unsigned FileNumber, unsigned CUID = 0);

View File

@ -16,6 +16,7 @@
#define LLVM_MC_MCDWARF_H #define LLVM_MC_MCDWARF_H
#include "llvm/ADT/MapVector.h" #include "llvm/ADT/MapVector.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringRef.h"
@ -48,7 +49,6 @@ class SourceMgr;
/// index 0 is not used and not a valid dwarf file number). /// index 0 is not used and not a valid dwarf file number).
struct MCDwarfFile { struct MCDwarfFile {
// \brief The base name of the file without its directory path. // \brief The base name of the file without its directory path.
// The StringRef references memory allocated in the MCContext.
std::string Name; std::string Name;
// \brief The index into the list of directory names for this file name. // \brief The index into the list of directory names for this file name.
@ -57,6 +57,10 @@ struct MCDwarfFile {
/// The MD5 checksum, if there is one. Non-owning pointer to data allocated /// The MD5 checksum, if there is one. Non-owning pointer to data allocated
/// in MCContext. /// in MCContext.
MD5::MD5Result *Checksum = nullptr; MD5::MD5Result *Checksum = nullptr;
/// The source code of the file. Non-owning reference to data allocated in
/// MCContext.
Optional<StringRef> Source;
}; };
/// \brief Instances of this class represent the information from a /// \brief Instances of this class represent the information from a
@ -211,11 +215,13 @@ struct MCDwarfLineTableHeader {
StringMap<unsigned> SourceIdMap; StringMap<unsigned> SourceIdMap;
StringRef CompilationDir; StringRef CompilationDir;
bool HasMD5 = false; bool HasMD5 = false;
bool HasSource = false;
MCDwarfLineTableHeader() = default; MCDwarfLineTableHeader() = default;
Expected<unsigned> tryGetFile(StringRef &Directory, StringRef &FileName, Expected<unsigned> tryGetFile(StringRef &Directory, StringRef &FileName,
MD5::MD5Result *Checksum, MD5::MD5Result *Checksum,
Optional<StringRef> &Source,
unsigned FileNumber = 0); unsigned FileNumber = 0);
std::pair<MCSymbol *, MCSymbol *> std::pair<MCSymbol *, MCSymbol *>
Emit(MCStreamer *MCOS, MCDwarfLineTableParams Params, Emit(MCStreamer *MCOS, MCDwarfLineTableParams Params,
@ -240,8 +246,8 @@ public:
} }
unsigned getFile(StringRef Directory, StringRef FileName, unsigned getFile(StringRef Directory, StringRef FileName,
MD5::MD5Result *Checksum) { MD5::MD5Result *Checksum, Optional<StringRef> Source) {
return cantFail(Header.tryGetFile(Directory, FileName, Checksum)); return cantFail(Header.tryGetFile(Directory, FileName, Checksum, Source));
} }
void Emit(MCStreamer &MCOS, MCDwarfLineTableParams Params) const; void Emit(MCStreamer &MCOS, MCDwarfLineTableParams Params) const;
@ -261,10 +267,13 @@ public:
Expected<unsigned> tryGetFile(StringRef &Directory, StringRef &FileName, Expected<unsigned> tryGetFile(StringRef &Directory, StringRef &FileName,
MD5::MD5Result *Checksum, MD5::MD5Result *Checksum,
Optional<StringRef> Source,
unsigned FileNumber = 0); unsigned FileNumber = 0);
unsigned getFile(StringRef &Directory, StringRef &FileName, unsigned getFile(StringRef &Directory, StringRef &FileName,
MD5::MD5Result *Checksum, unsigned FileNumber = 0) { MD5::MD5Result *Checksum, Optional<StringRef> &Source,
return cantFail(tryGetFile(Directory, FileName, Checksum, FileNumber)); unsigned FileNumber = 0) {
return cantFail(tryGetFile(Directory, FileName, Checksum, Source,
FileNumber));
} }
MCSymbol *getLabel() const { MCSymbol *getLabel() const {

View File

@ -16,6 +16,7 @@
#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringRef.h"
#include "llvm/MC/MCDirectives.h" #include "llvm/MC/MCDirectives.h"
@ -756,17 +757,22 @@ public:
unsigned EmitDwarfFileDirective(unsigned FileNo, StringRef Directory, unsigned EmitDwarfFileDirective(unsigned FileNo, StringRef Directory,
StringRef Filename, StringRef Filename,
MD5::MD5Result *Checksum = nullptr, MD5::MD5Result *Checksum = nullptr,
Optional<StringRef> Source = None,
unsigned CUID = 0) { unsigned CUID = 0) {
return cantFail( return cantFail(
tryEmitDwarfFileDirective(FileNo, Directory, Filename, Checksum, CUID)); tryEmitDwarfFileDirective(FileNo, Directory, Filename, Checksum,
Source, CUID));
} }
/// Associate a filename with a specified logical file number. Returns a /// Associate a filename with a specified logical file number.
/// StringError for any problem, or the file number. This implements the /// Also associate a directory, optional checksum, and optional source
/// DWARF2 '.file 4 "foo.c"' assembler directive. /// text with the logical file. This implements the DWARF2
/// '.file 4 "dir/foo.c"' assembler directive, and the DWARF5
/// '.file 4 "dir/foo.c" md5 "..." source "..."' assembler directive.
virtual Expected<unsigned> tryEmitDwarfFileDirective( virtual Expected<unsigned> tryEmitDwarfFileDirective(
unsigned FileNo, StringRef Directory, StringRef Filename, unsigned FileNo, StringRef Directory, StringRef Filename,
MD5::MD5Result *Checksum = nullptr, unsigned CUID = 0); MD5::MD5Result *Checksum = nullptr, Optional<StringRef> Source = None,
unsigned CUID = 0);
/// \brief This implements the DWARF2 '.loc fileno lineno ...' assembler /// \brief This implements the DWARF2 '.loc fileno lineno ...' assembler
/// directive. /// directive.

View File

@ -4243,9 +4243,10 @@ bool LLParser::ParseDISubroutineType(MDNode *&Result, bool IsDistinct) {
} }
/// ParseDIFileType: /// ParseDIFileType:
/// ::= !DIFileType(filename: "path/to/file", directory: "/path/to/dir" /// ::= !DIFileType(filename: "path/to/file", directory: "/path/to/dir",
/// checksumkind: CSK_MD5, /// checksumkind: CSK_MD5,
/// checksum: "000102030405060708090a0b0c0d0e0f") /// checksum: "000102030405060708090a0b0c0d0e0f",
/// source: "source file contents")
bool LLParser::ParseDIFile(MDNode *&Result, bool IsDistinct) { bool LLParser::ParseDIFile(MDNode *&Result, bool IsDistinct) {
// The default constructed value for checksumkind is required, but will never // The default constructed value for checksumkind is required, but will never
// be used, as the parser checks if the field was actually Seen before using // be used, as the parser checks if the field was actually Seen before using
@ -4254,7 +4255,8 @@ bool LLParser::ParseDIFile(MDNode *&Result, bool IsDistinct) {
REQUIRED(filename, MDStringField, ); \ REQUIRED(filename, MDStringField, ); \
REQUIRED(directory, MDStringField, ); \ REQUIRED(directory, MDStringField, ); \
OPTIONAL(checksumkind, ChecksumKindField, (DIFile::CSK_MD5)); \ OPTIONAL(checksumkind, ChecksumKindField, (DIFile::CSK_MD5)); \
OPTIONAL(checksum, MDStringField, ); OPTIONAL(checksum, MDStringField, ); \
OPTIONAL(source, MDStringField, );
PARSE_MD_FIELDS(); PARSE_MD_FIELDS();
#undef VISIT_MD_FIELDS #undef VISIT_MD_FIELDS
@ -4264,8 +4266,11 @@ bool LLParser::ParseDIFile(MDNode *&Result, bool IsDistinct) {
else if (checksumkind.Seen || checksum.Seen) else if (checksumkind.Seen || checksum.Seen)
return Lex.Error("'checksumkind' and 'checksum' must be provided together"); return Lex.Error("'checksumkind' and 'checksum' must be provided together");
Optional<MDString *> OptSource;
if (source.Seen)
OptSource = source.Val;
Result = GET_OR_DISTINCT(DIFile, (Context, filename.Val, directory.Val, Result = GET_OR_DISTINCT(DIFile, (Context, filename.Val, directory.Val,
OptChecksum)); OptChecksum, OptSource));
return false; return false;
} }

View File

@ -1350,7 +1350,7 @@ Error MetadataLoader::MetadataLoaderImpl::parseOneMetadata(
} }
case bitc::METADATA_FILE: { case bitc::METADATA_FILE: {
if (Record.size() != 3 && Record.size() != 5) if (Record.size() != 3 && Record.size() != 5 && Record.size() != 6)
return error("Invalid record"); return error("Invalid record");
IsDistinct = Record[0]; IsDistinct = Record[0];
@ -1360,14 +1360,15 @@ Error MetadataLoader::MetadataLoaderImpl::parseOneMetadata(
// and the old encoding for CSK_None in the ChecksumKind. The new // and the old encoding for CSK_None in the ChecksumKind. The new
// representation reserves the value 0 in the ChecksumKind to continue to // representation reserves the value 0 in the ChecksumKind to continue to
// encode None in a backwards-compatible way. // encode None in a backwards-compatible way.
if (Record.size() == 5 && Record[3] && Record[4]) if (Record.size() > 4 && Record[3] && Record[4])
Checksum.emplace(static_cast<DIFile::ChecksumKind>(Record[3]), Checksum.emplace(static_cast<DIFile::ChecksumKind>(Record[3]),
getMDString(Record[4])); getMDString(Record[4]));
MetadataList.assignValue( MetadataList.assignValue(
GET_OR_DISTINCT( GET_OR_DISTINCT(
DIFile, DIFile,
(Context, getMDString(Record[1]), getMDString(Record[2]), (Context, getMDString(Record[1]), getMDString(Record[2]), Checksum,
Checksum)), Record.size() > 5 ? Optional<MDString *>(getMDString(Record[5]))
: None)),
NextMetadataNo); NextMetadataNo);
NextMetadataNo++; NextMetadataNo++;
break; break;

View File

@ -1560,6 +1560,9 @@ void ModuleBitcodeWriter::writeDIFile(const DIFile *N,
Record.push_back(0); Record.push_back(0);
Record.push_back(VE.getMetadataOrNullID(nullptr)); Record.push_back(VE.getMetadataOrNullID(nullptr));
} }
auto Source = N->getRawSource();
if (Source)
Record.push_back(VE.getMetadataOrNullID(*Source));
Stream.EmitRecord(bitc::METADATA_FILE, Record, Abbrev); Stream.EmitRecord(bitc::METADATA_FILE, Record, Abbrev);
Record.clear(); Record.clear();

View File

@ -102,9 +102,10 @@ unsigned DwarfCompileUnit::getOrCreateSourceID(const DIFile *File) {
// extend .file to support this. // extend .file to support this.
unsigned CUID = Asm->OutStreamer->hasRawTextSupport() ? 0 : getUniqueID(); unsigned CUID = Asm->OutStreamer->hasRawTextSupport() ? 0 : getUniqueID();
if (!File) if (!File)
return Asm->OutStreamer->EmitDwarfFileDirective(0, "", "", nullptr, CUID); return Asm->OutStreamer->EmitDwarfFileDirective(0, "", "", nullptr, None, CUID);
return Asm->OutStreamer->EmitDwarfFileDirective( return Asm->OutStreamer->EmitDwarfFileDirective(
0, File->getDirectory(), File->getFilename(), getMD5AsBytes(File), CUID); 0, File->getDirectory(), File->getFilename(), getMD5AsBytes(File),
File->getSource(), CUID);
} }
DIE *DwarfCompileUnit::getOrCreateGlobalVariableDIE( DIE *DwarfCompileUnit::getOrCreateGlobalVariableDIE(

View File

@ -1384,7 +1384,7 @@ void DwarfDebug::endFunctionImpl(const MachineFunction *MF) {
void DwarfDebug::recordSourceLine(unsigned Line, unsigned Col, const MDNode *S, void DwarfDebug::recordSourceLine(unsigned Line, unsigned Col, const MDNode *S,
unsigned Flags) { unsigned Flags) {
StringRef Fn; StringRef Fn;
unsigned Src = 1; unsigned FileNo = 1;
unsigned Discriminator = 0; unsigned Discriminator = 0;
if (auto *Scope = cast_or_null<DIScope>(S)) { if (auto *Scope = cast_or_null<DIScope>(S)) {
Fn = Scope->getFilename(); Fn = Scope->getFilename();
@ -1393,10 +1393,10 @@ void DwarfDebug::recordSourceLine(unsigned Line, unsigned Col, const MDNode *S,
Discriminator = LBF->getDiscriminator(); Discriminator = LBF->getDiscriminator();
unsigned CUID = Asm->OutStreamer->getContext().getDwarfCompileUnitID(); unsigned CUID = Asm->OutStreamer->getContext().getDwarfCompileUnitID();
Src = static_cast<DwarfCompileUnit &>(*InfoHolder.getUnits()[CUID]) FileNo = static_cast<DwarfCompileUnit &>(*InfoHolder.getUnits()[CUID])
.getOrCreateSourceID(Scope->getFile()); .getOrCreateSourceID(Scope->getFile());
} }
Asm->OutStreamer->EmitDwarfLocDirective(Src, Line, Col, Flags, 0, Asm->OutStreamer->EmitDwarfLocDirective(FileNo, Line, Col, Flags, 0,
Discriminator, Fn); Discriminator, Fn);
} }

View File

@ -302,7 +302,9 @@ MD5::MD5Result *DwarfUnit::getMD5AsBytes(const DIFile *File) {
unsigned DwarfTypeUnit::getOrCreateSourceID(const DIFile *File) { unsigned DwarfTypeUnit::getOrCreateSourceID(const DIFile *File) {
return SplitLineTable return SplitLineTable
? SplitLineTable->getFile(File->getDirectory(), ? SplitLineTable->getFile(File->getDirectory(),
File->getFilename(), getMD5AsBytes(File)) File->getFilename(),
getMD5AsBytes(File),
File->getSource())
: getCU().getOrCreateSourceID(File); : getCU().getOrCreateSourceID(File);
} }

View File

@ -466,7 +466,9 @@ void DWARFContext::dump(
uint32_t offset = 0; uint32_t offset = 0;
uint32_t strOffset = 0; uint32_t strOffset = 0;
while (const char *s = strData.getCStr(&offset)) { while (const char *s = strData.getCStr(&offset)) {
OS << format("0x%8.8x: \"%s\"\n", strOffset, s); OS << format("0x%8.8x: \"", strOffset);
OS.write_escaped(s);
OS << "\"\n";
strOffset = offset; strOffset = offset;
} }
} }

View File

@ -8,6 +8,7 @@
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
#include "llvm/DebugInfo/DWARF/DWARFDebugLine.h" #include "llvm/DebugInfo/DWARF/DWARFDebugLine.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/SmallString.h" #include "llvm/ADT/SmallString.h"
#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringRef.h"
@ -40,6 +41,28 @@ using ContentDescriptors = SmallVector<ContentDescriptor, 4>;
} // end anonmyous namespace } // end anonmyous namespace
void DWARFDebugLine::ContentTypeTracker::trackContentType(
dwarf::LineNumberEntryFormat ContentType) {
switch (ContentType) {
case dwarf::DW_LNCT_timestamp:
HasModTime = true;
break;
case dwarf::DW_LNCT_size:
HasLength = true;
break;
case dwarf::DW_LNCT_MD5:
HasMD5 = true;
break;
case dwarf::DW_LNCT_LLVM_source:
HasSource = true;
break;
default:
// We only care about values we consider optional, and new values may be
// added in the vendor extension range, so we do not match exhaustively.
break;
}
}
DWARFDebugLine::Prologue::Prologue() { clear(); } DWARFDebugLine::Prologue::Prologue() { clear(); }
void DWARFDebugLine::Prologue::clear() { void DWARFDebugLine::Prologue::clear() {
@ -48,7 +71,7 @@ void DWARFDebugLine::Prologue::clear() {
MinInstLength = MaxOpsPerInst = DefaultIsStmt = LineBase = LineRange = 0; MinInstLength = MaxOpsPerInst = DefaultIsStmt = LineBase = LineRange = 0;
OpcodeBase = 0; OpcodeBase = 0;
FormParams = DWARFFormParams({0, 0, DWARF32}); FormParams = DWARFFormParams({0, 0, DWARF32});
HasMD5 = false; ContentTypes = ContentTypeTracker();
StandardOpcodeLengths.clear(); StandardOpcodeLengths.clear();
IncludeDirectories.clear(); IncludeDirectories.clear();
FileNames.clear(); FileNames.clear();
@ -85,36 +108,35 @@ void DWARFDebugLine::Prologue::dump(raw_ostream &OS,
} }
if (!FileNames.empty()) { if (!FileNames.empty()) {
if (HasMD5)
OS << " Dir MD5 Checksum File Name\n"
<< " ---- -------------------------------- -----------"
"---------------\n";
else
OS << " Dir Mod Time File Len File Name\n"
<< " ---- ---------- ---------- -----------"
"----------------\n";
// DWARF v5 starts file indexes at 0. // DWARF v5 starts file indexes at 0.
uint32_t FileBase = getVersion() >= 5 ? 0 : 1; uint32_t FileBase = getVersion() >= 5 ? 0 : 1;
for (uint32_t I = 0; I != FileNames.size(); ++I) { for (uint32_t I = 0; I != FileNames.size(); ++I) {
const FileNameEntry &FileEntry = FileNames[I]; const FileNameEntry &FileEntry = FileNames[I];
OS << format("file_names[%3u] %4" PRIu64 " ", I + FileBase, OS << format("file_names[%3u]:\n", I + FileBase);
FileEntry.DirIdx); OS << " name: ";
if (HasMD5)
OS << FileEntry.Checksum.digest();
else
OS << format("0x%8.8" PRIx64 " 0x%8.8" PRIx64, FileEntry.ModTime,
FileEntry.Length);
OS << ' ';
FileEntry.Name.dump(OS, DumpOptions); FileEntry.Name.dump(OS, DumpOptions);
OS << '\n'
<< format(" dir_index: %" PRIu64 "\n", FileEntry.DirIdx);
if (ContentTypes.HasMD5)
OS << " md5_checksum: " << FileEntry.Checksum.digest() << '\n';
if (ContentTypes.HasModTime)
OS << format(" mod_time: 0x%8.8" PRIx64 "\n", FileEntry.ModTime);
if (ContentTypes.HasLength)
OS << format(" length: 0x%8.8" PRIx64 "\n", FileEntry.Length);
if (ContentTypes.HasSource) {
OS << " source: ";
FileEntry.Source.dump(OS, DumpOptions);
OS << '\n'; OS << '\n';
} }
} }
} }
}
// Parse v2-v4 directory and file tables. // Parse v2-v4 directory and file tables.
static void static void
parseV2DirFileTables(const DWARFDataExtractor &DebugLineData, parseV2DirFileTables(const DWARFDataExtractor &DebugLineData,
uint32_t *OffsetPtr, uint64_t EndPrologueOffset, uint32_t *OffsetPtr, uint64_t EndPrologueOffset,
DWARFDebugLine::ContentTypeTracker &ContentTypes,
std::vector<DWARFFormValue> &IncludeDirectories, std::vector<DWARFFormValue> &IncludeDirectories,
std::vector<DWARFDebugLine::FileNameEntry> &FileNames) { std::vector<DWARFDebugLine::FileNameEntry> &FileNames) {
while (*OffsetPtr < EndPrologueOffset) { while (*OffsetPtr < EndPrologueOffset) {
@ -138,14 +160,18 @@ parseV2DirFileTables(const DWARFDataExtractor &DebugLineData,
FileEntry.Length = DebugLineData.getULEB128(OffsetPtr); FileEntry.Length = DebugLineData.getULEB128(OffsetPtr);
FileNames.push_back(FileEntry); FileNames.push_back(FileEntry);
} }
ContentTypes.HasModTime = true;
ContentTypes.HasLength = true;
} }
// Parse v5 directory/file entry content descriptions. // Parse v5 directory/file entry content descriptions.
// Returns the descriptors, or an empty vector if we did not find a path or // Returns the descriptors, or an empty vector if we did not find a path or
// ran off the end of the prologue. // ran off the end of the prologue.
static ContentDescriptors static ContentDescriptors
parseV5EntryFormat(const DWARFDataExtractor &DebugLineData, uint32_t *OffsetPtr, parseV5EntryFormat(const DWARFDataExtractor &DebugLineData, uint32_t
uint64_t EndPrologueOffset, bool *HasMD5) { *OffsetPtr, uint64_t EndPrologueOffset, DWARFDebugLine::ContentTypeTracker
*ContentTypes) {
ContentDescriptors Descriptors; ContentDescriptors Descriptors;
int FormatCount = DebugLineData.getU8(OffsetPtr); int FormatCount = DebugLineData.getU8(OffsetPtr);
bool HasPath = false; bool HasPath = false;
@ -158,8 +184,8 @@ parseV5EntryFormat(const DWARFDataExtractor &DebugLineData, uint32_t *OffsetPtr,
Descriptor.Form = dwarf::Form(DebugLineData.getULEB128(OffsetPtr)); Descriptor.Form = dwarf::Form(DebugLineData.getULEB128(OffsetPtr));
if (Descriptor.Type == dwarf::DW_LNCT_path) if (Descriptor.Type == dwarf::DW_LNCT_path)
HasPath = true; HasPath = true;
else if (Descriptor.Type == dwarf::DW_LNCT_MD5 && HasMD5) if (ContentTypes)
*HasMD5 = true; ContentTypes->trackContentType(Descriptor.Type);
Descriptors.push_back(Descriptor); Descriptors.push_back(Descriptor);
} }
return HasPath ? Descriptors : ContentDescriptors(); return HasPath ? Descriptors : ContentDescriptors();
@ -168,8 +194,9 @@ parseV5EntryFormat(const DWARFDataExtractor &DebugLineData, uint32_t *OffsetPtr,
static bool static bool
parseV5DirFileTables(const DWARFDataExtractor &DebugLineData, parseV5DirFileTables(const DWARFDataExtractor &DebugLineData,
uint32_t *OffsetPtr, uint64_t EndPrologueOffset, uint32_t *OffsetPtr, uint64_t EndPrologueOffset,
const DWARFFormParams &FormParams, const DWARFContext &Ctx, const DWARFFormParams &FormParams, const DWARFContext
const DWARFUnit *U, bool &HasMD5, &Ctx, const DWARFUnit *U,
DWARFDebugLine::ContentTypeTracker &ContentTypes,
std::vector<DWARFFormValue> &IncludeDirectories, std::vector<DWARFFormValue> &IncludeDirectories,
std::vector<DWARFDebugLine::FileNameEntry> &FileNames) { std::vector<DWARFDebugLine::FileNameEntry> &FileNames) {
// Get the directory entry description. // Get the directory entry description.
@ -200,7 +227,8 @@ parseV5DirFileTables(const DWARFDataExtractor &DebugLineData,
// Get the file entry description. // Get the file entry description.
ContentDescriptors FileDescriptors = ContentDescriptors FileDescriptors =
parseV5EntryFormat(DebugLineData, OffsetPtr, EndPrologueOffset, &HasMD5); parseV5EntryFormat(DebugLineData, OffsetPtr, EndPrologueOffset,
&ContentTypes);
if (FileDescriptors.empty()) if (FileDescriptors.empty())
return false; return false;
@ -218,6 +246,9 @@ parseV5DirFileTables(const DWARFDataExtractor &DebugLineData,
case DW_LNCT_path: case DW_LNCT_path:
FileEntry.Name = Value; FileEntry.Name = Value;
break; break;
case DW_LNCT_LLVM_source:
FileEntry.Source = Value;
break;
case DW_LNCT_directory_index: case DW_LNCT_directory_index:
FileEntry.DirIdx = Value.getAsUnsignedConstant().getValue(); FileEntry.DirIdx = Value.getAsUnsignedConstant().getValue();
break; break;
@ -285,8 +316,8 @@ bool DWARFDebugLine::Prologue::parse(const DWARFDataExtractor &DebugLineData,
if (getVersion() >= 5) { if (getVersion() >= 5) {
if (!parseV5DirFileTables(DebugLineData, OffsetPtr, EndPrologueOffset, if (!parseV5DirFileTables(DebugLineData, OffsetPtr, EndPrologueOffset,
FormParams, Ctx, U, HasMD5, IncludeDirectories, FormParams, Ctx, U, ContentTypes,
FileNames)) { IncludeDirectories, FileNames)) {
fprintf(stderr, fprintf(stderr,
"warning: parsing line table prologue at 0x%8.8" PRIx64 "warning: parsing line table prologue at 0x%8.8" PRIx64
" found an invalid directory or file table description at" " found an invalid directory or file table description at"
@ -295,7 +326,7 @@ bool DWARFDebugLine::Prologue::parse(const DWARFDataExtractor &DebugLineData,
} }
} else } else
parseV2DirFileTables(DebugLineData, OffsetPtr, EndPrologueOffset, parseV2DirFileTables(DebugLineData, OffsetPtr, EndPrologueOffset,
IncludeDirectories, FileNames); ContentTypes, IncludeDirectories, FileNames);
if (*OffsetPtr != EndPrologueOffset) { if (*OffsetPtr != EndPrologueOffset) {
fprintf(stderr, fprintf(stderr,
@ -912,6 +943,16 @@ bool DWARFDebugLine::LineTable::hasFileAtIndex(uint64_t FileIndex) const {
return FileIndex != 0 && FileIndex <= Prologue.FileNames.size(); return FileIndex != 0 && FileIndex <= Prologue.FileNames.size();
} }
Optional<StringRef> DWARFDebugLine::LineTable::getSourceByIndex(uint64_t FileIndex,
FileLineInfoKind Kind) const {
if (Kind == FileLineInfoKind::None || !hasFileAtIndex(FileIndex))
return None;
const FileNameEntry &Entry = Prologue.FileNames[FileIndex - 1];
if (Optional<const char *> source = Entry.Source.getAsCString())
return StringRef(*source);
return None;
}
bool DWARFDebugLine::LineTable::getFileNameByIndex(uint64_t FileIndex, bool DWARFDebugLine::LineTable::getFileNameByIndex(uint64_t FileIndex,
const char *CompDir, const char *CompDir,
FileLineInfoKind Kind, FileLineInfoKind Kind,
@ -963,5 +1004,6 @@ bool DWARFDebugLine::LineTable::getFileLineInfoForAddress(
Result.Line = Row.Line; Result.Line = Row.Line;
Result.Column = Row.Column; Result.Column = Row.Column;
Result.Discriminator = Row.Discriminator; Result.Discriminator = Row.Discriminator;
Result.Source = getSourceByIndex(Row.File, Kind);
return true; return true;
} }

View File

@ -1723,6 +1723,8 @@ static void writeDIFile(raw_ostream &Out, const DIFile *N, TypePrinting *,
// Print all values for checksum together, or not at all. // Print all values for checksum together, or not at all.
if (N->getChecksum()) if (N->getChecksum())
Printer.printChecksum(*N->getChecksum()); Printer.printChecksum(*N->getChecksum());
Printer.printString("source", N->getSource().getValueOr(StringRef()),
/* ShouldSkipEmpty */ true);
Out << ")"; Out << ")";
} }

View File

@ -14,6 +14,7 @@
#include "llvm/IR/DIBuilder.h" #include "llvm/IR/DIBuilder.h"
#include "llvm/IR/IRBuilder.h" #include "llvm/IR/IRBuilder.h"
#include "LLVMContextImpl.h" #include "LLVMContextImpl.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/STLExtras.h"
#include "llvm/BinaryFormat/Dwarf.h" #include "llvm/BinaryFormat/Dwarf.h"
#include "llvm/IR/Constants.h" #include "llvm/IR/Constants.h"
@ -204,8 +205,9 @@ DIImportedEntity *DIBuilder::createImportedDeclaration(DIScope *Context,
} }
DIFile *DIBuilder::createFile(StringRef Filename, StringRef Directory, DIFile *DIBuilder::createFile(StringRef Filename, StringRef Directory,
Optional<DIFile::ChecksumInfo<StringRef>> CS) { Optional<DIFile::ChecksumInfo<StringRef>> CS,
return DIFile::get(VMContext, Filename, Directory, CS); Optional<StringRef> Source) {
return DIFile::get(VMContext, Filename, Directory, CS, Source);
} }
DIMacro *DIBuilder::createMacro(DIMacroFile *Parent, unsigned LineNumber, DIMacro *DIBuilder::createMacro(DIMacroFile *Parent, unsigned LineNumber,

View File

@ -417,13 +417,16 @@ Optional<DIFile::ChecksumKind> DIFile::getChecksumKind(StringRef CSKindStr) {
DIFile *DIFile::getImpl(LLVMContext &Context, MDString *Filename, DIFile *DIFile::getImpl(LLVMContext &Context, MDString *Filename,
MDString *Directory, MDString *Directory,
Optional<DIFile::ChecksumInfo<MDString *>> CS, Optional<DIFile::ChecksumInfo<MDString *>> CS,
StorageType Storage, bool ShouldCreate) { Optional<MDString *> Source, StorageType Storage,
bool ShouldCreate) {
assert(isCanonical(Filename) && "Expected canonical MDString"); assert(isCanonical(Filename) && "Expected canonical MDString");
assert(isCanonical(Directory) && "Expected canonical MDString"); assert(isCanonical(Directory) && "Expected canonical MDString");
assert((!CS || isCanonical(CS->Value)) && "Expected canonical MDString"); assert((!CS || isCanonical(CS->Value)) && "Expected canonical MDString");
DEFINE_GETIMPL_LOOKUP(DIFile, (Filename, Directory, CS)); assert((!Source || isCanonical(*Source)) && "Expected canonical MDString");
Metadata *Ops[] = {Filename, Directory, CS ? CS->Value : nullptr}; DEFINE_GETIMPL_LOOKUP(DIFile, (Filename, Directory, CS, Source));
DEFINE_GETIMPL_STORE(DIFile, (CS), Ops); Metadata *Ops[] = {Filename, Directory, CS ? CS->Value : nullptr,
Source.getValueOr(nullptr)};
DEFINE_GETIMPL_STORE(DIFile, (CS, Source), Ops);
} }
DICompileUnit *DICompileUnit::getImpl( DICompileUnit *DICompileUnit::getImpl(

View File

@ -575,24 +575,28 @@ template <> struct MDNodeKeyImpl<DIFile> {
MDString *Filename; MDString *Filename;
MDString *Directory; MDString *Directory;
Optional<DIFile::ChecksumInfo<MDString *>> Checksum; Optional<DIFile::ChecksumInfo<MDString *>> Checksum;
Optional<MDString *> Source;
MDNodeKeyImpl(MDString *Filename, MDString *Directory, MDNodeKeyImpl(MDString *Filename, MDString *Directory,
Optional<DIFile::ChecksumInfo<MDString *>> Checksum) Optional<DIFile::ChecksumInfo<MDString *>> Checksum,
: Filename(Filename), Directory(Directory), Checksum(Checksum) {} Optional<MDString *> Source)
: Filename(Filename), Directory(Directory), Checksum(Checksum),
Source(Source) {}
MDNodeKeyImpl(const DIFile *N) MDNodeKeyImpl(const DIFile *N)
: Filename(N->getRawFilename()), Directory(N->getRawDirectory()), : Filename(N->getRawFilename()), Directory(N->getRawDirectory()),
Checksum(N->getRawChecksum()) {} Checksum(N->getRawChecksum()), Source(N->getRawSource()) {}
bool isKeyOf(const DIFile *RHS) const { bool isKeyOf(const DIFile *RHS) const {
return Filename == RHS->getRawFilename() && return Filename == RHS->getRawFilename() &&
Directory == RHS->getRawDirectory() && Directory == RHS->getRawDirectory() &&
Checksum == RHS->getRawChecksum(); Checksum == RHS->getRawChecksum() &&
Source == RHS->getRawSource();
} }
unsigned getHashValue() const { unsigned getHashValue() const {
if (Checksum) return hash_combine(
return hash_combine(Filename, Directory, Checksum->Kind, Checksum->Value); Filename, Directory, Checksum ? Checksum->Kind : 0,
return hash_combine(Filename, Directory); Checksum ? Checksum->Value : nullptr, Source.getValueOr(nullptr));
} }
}; };

View File

@ -7,6 +7,7 @@
// //
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallString.h" #include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringExtras.h"
@ -215,6 +216,7 @@ public:
StringRef Directory, StringRef Directory,
StringRef Filename, StringRef Filename,
MD5::MD5Result *Checksum = 0, MD5::MD5Result *Checksum = 0,
Optional<StringRef> Source = None,
unsigned CUID = 0) override; unsigned CUID = 0) override;
void EmitDwarfLocDirective(unsigned FileNo, unsigned Line, void EmitDwarfLocDirective(unsigned FileNo, unsigned Line,
unsigned Column, unsigned Flags, unsigned Column, unsigned Flags,
@ -1076,13 +1078,13 @@ void MCAsmStreamer::EmitFileDirective(StringRef Filename) {
Expected<unsigned> MCAsmStreamer::tryEmitDwarfFileDirective( Expected<unsigned> MCAsmStreamer::tryEmitDwarfFileDirective(
unsigned FileNo, StringRef Directory, StringRef Filename, unsigned FileNo, StringRef Directory, StringRef Filename,
MD5::MD5Result *Checksum, unsigned CUID) { MD5::MD5Result *Checksum, Optional<StringRef> Source, unsigned CUID) {
assert(CUID == 0); assert(CUID == 0);
MCDwarfLineTable &Table = getContext().getMCDwarfLineTable(CUID); MCDwarfLineTable &Table = getContext().getMCDwarfLineTable(CUID);
unsigned NumFiles = Table.getMCDwarfFiles().size(); unsigned NumFiles = Table.getMCDwarfFiles().size();
Expected<unsigned> FileNoOrErr = Expected<unsigned> FileNoOrErr =
Table.tryGetFile(Directory, Filename, Checksum, FileNo); Table.tryGetFile(Directory, Filename, Checksum, Source, FileNo);
if (!FileNoOrErr) if (!FileNoOrErr)
return FileNoOrErr.takeError(); return FileNoOrErr.takeError();
FileNo = FileNoOrErr.get(); FileNo = FileNoOrErr.get();
@ -1114,6 +1116,10 @@ Expected<unsigned> MCAsmStreamer::tryEmitDwarfFileDirective(
OS1 << " md5 "; OS1 << " md5 ";
PrintQuotedString(Checksum->digest(), OS1); PrintQuotedString(Checksum->digest(), OS1);
} }
if (Source) {
OS1 << " source ";
PrintQuotedString(*Source, OS1);
}
if (MCTargetStreamer *TS = getTargetStreamer()) { if (MCTargetStreamer *TS = getTargetStreamer()) {
TS->emitDwarfFileDirective(OS1.str()); TS->emitDwarfFileDirective(OS1.str());
} else { } else {

View File

@ -8,6 +8,7 @@
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
#include "llvm/MC/MCContext.h" #include "llvm/MC/MCContext.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/SmallString.h" #include "llvm/ADT/SmallString.h"
#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringMap.h"
@ -532,7 +533,7 @@ MCSubtargetInfo &MCContext::getSubtargetCopy(const MCSubtargetInfo &STI) {
// Dwarf Management // Dwarf Management
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
/// getDwarfFile - takes a file name an number to place in the dwarf file and /// getDwarfFile - takes a file name and number to place in the dwarf file and
/// directory tables. If the file number has already been allocated it is an /// directory tables. If the file number has already been allocated it is an
/// error and zero is returned and the client reports the error, else the /// error and zero is returned and the client reports the error, else the
/// allocated file number is returned. The file numbers may be in any order. /// allocated file number is returned. The file numbers may be in any order.
@ -540,9 +541,10 @@ Expected<unsigned> MCContext::getDwarfFile(StringRef Directory,
StringRef FileName, StringRef FileName,
unsigned FileNumber, unsigned FileNumber,
MD5::MD5Result *Checksum, MD5::MD5Result *Checksum,
Optional<StringRef> Source,
unsigned CUID) { unsigned CUID) {
MCDwarfLineTable &Table = MCDwarfLineTablesCUMap[CUID]; MCDwarfLineTable &Table = MCDwarfLineTablesCUMap[CUID];
return Table.tryGetFile(Directory, FileName, Checksum, FileNumber); return Table.tryGetFile(Directory, FileName, Checksum, Source, FileNumber);
} }
/// isValidDwarfFileNumber - takes a dwarf file number and returns true if it /// isValidDwarfFileNumber - takes a dwarf file number and returns true if it

View File

@ -11,7 +11,7 @@
#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/Hashing.h" #include "llvm/ADT/Hashing.h"
#include "llvm/ADT/None.h" #include "llvm/ADT/Optional.h"
#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallString.h" #include "llvm/ADT/SmallString.h"
#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/SmallVector.h"
@ -373,8 +373,13 @@ void MCDwarfLineTableHeader::emitV5FileDirTables(
// The file format, which is the inline null-terminated filename and a // The file format, which is the inline null-terminated filename and a
// directory index. We don't track file size/timestamp so don't emit them // directory index. We don't track file size/timestamp so don't emit them
// in the v5 table. Emit MD5 checksums if we have them. // in the v5 table. Emit MD5 checksums and source if we have them.
MCOS->EmitIntValue(HasMD5 ? 3 : 2, 1); uint64_t Entries = 2;
if (HasMD5)
Entries += 1;
if (HasSource)
Entries += 1;
MCOS->EmitIntValue(Entries, 1);
MCOS->EmitULEB128IntValue(dwarf::DW_LNCT_path); MCOS->EmitULEB128IntValue(dwarf::DW_LNCT_path);
MCOS->EmitULEB128IntValue(LineStr ? dwarf::DW_FORM_line_strp MCOS->EmitULEB128IntValue(LineStr ? dwarf::DW_FORM_line_strp
: dwarf::DW_FORM_string); : dwarf::DW_FORM_string);
@ -384,6 +389,11 @@ void MCDwarfLineTableHeader::emitV5FileDirTables(
MCOS->EmitULEB128IntValue(dwarf::DW_LNCT_MD5); MCOS->EmitULEB128IntValue(dwarf::DW_LNCT_MD5);
MCOS->EmitULEB128IntValue(dwarf::DW_FORM_data16); MCOS->EmitULEB128IntValue(dwarf::DW_FORM_data16);
} }
if (HasSource) {
MCOS->EmitULEB128IntValue(dwarf::DW_LNCT_LLVM_source);
MCOS->EmitULEB128IntValue(LineStr ? dwarf::DW_FORM_line_strp
: dwarf::DW_FORM_string);
}
// Then the list of file names. These start at 1. // Then the list of file names. These start at 1.
MCOS->EmitULEB128IntValue(MCDwarfFiles.size() - 1); MCOS->EmitULEB128IntValue(MCDwarfFiles.size() - 1);
for (unsigned i = 1; i < MCDwarfFiles.size(); ++i) { for (unsigned i = 1; i < MCDwarfFiles.size(); ++i) {
@ -401,6 +411,15 @@ void MCDwarfLineTableHeader::emitV5FileDirTables(
StringRef(reinterpret_cast<const char *>(Cksum->Bytes.data()), StringRef(reinterpret_cast<const char *>(Cksum->Bytes.data()),
Cksum->Bytes.size())); Cksum->Bytes.size()));
} }
if (HasSource) {
if (LineStr)
LineStr->emitRef(MCOS, MCDwarfFiles[i].Source.getValueOr(StringRef()));
else {
MCOS->EmitBytes(
MCDwarfFiles[i].Source.getValueOr(StringRef())); // Source and...
MCOS->EmitBytes(StringRef("\0", 1)); // its null terminator.
}
}
} }
} }
@ -500,13 +519,16 @@ void MCDwarfLineTable::EmitCU(MCObjectStreamer *MCOS,
Expected<unsigned> MCDwarfLineTable::tryGetFile(StringRef &Directory, Expected<unsigned> MCDwarfLineTable::tryGetFile(StringRef &Directory,
StringRef &FileName, StringRef &FileName,
MD5::MD5Result *Checksum, MD5::MD5Result *Checksum,
Optional<StringRef> Source,
unsigned FileNumber) { unsigned FileNumber) {
return Header.tryGetFile(Directory, FileName, Checksum, FileNumber); return Header.tryGetFile(Directory, FileName, Checksum, Source, FileNumber);
} }
Expected<unsigned> MCDwarfLineTableHeader::tryGetFile(StringRef &Directory, Expected<unsigned>
MCDwarfLineTableHeader::tryGetFile(StringRef &Directory,
StringRef &FileName, StringRef &FileName,
MD5::MD5Result *Checksum, MD5::MD5Result *Checksum,
Optional<StringRef> &Source,
unsigned FileNumber) { unsigned FileNumber) {
if (Directory == CompilationDir) if (Directory == CompilationDir)
Directory = ""; Directory = "";
@ -515,9 +537,11 @@ Expected<unsigned> MCDwarfLineTableHeader::tryGetFile(StringRef &Directory,
Directory = ""; Directory = "";
} }
assert(!FileName.empty()); assert(!FileName.empty());
// If any files have an MD5 checksum, they all must. // If any files have an MD5 checksum or embedded source, they all must.
if (MCDwarfFiles.empty()) if (MCDwarfFiles.empty()) {
HasMD5 = (Checksum != nullptr); HasMD5 = (Checksum != nullptr);
HasSource = (Source != None);
}
if (FileNumber == 0) { if (FileNumber == 0) {
// File numbers start with 1 and/or after any file numbers // File numbers start with 1 and/or after any file numbers
// allocated by inline-assembler .file directives. // allocated by inline-assembler .file directives.
@ -545,6 +569,10 @@ Expected<unsigned> MCDwarfLineTableHeader::tryGetFile(StringRef &Directory,
if (HasMD5 != (Checksum != nullptr)) if (HasMD5 != (Checksum != nullptr))
return make_error<StringError>("inconsistent use of MD5 checksums", return make_error<StringError>("inconsistent use of MD5 checksums",
inconvertibleErrorCode()); inconvertibleErrorCode());
// If any files have embedded source, they all must.
if (HasSource != (Source != None))
return make_error<StringError>("inconsistent use of embedded source",
inconvertibleErrorCode());
if (Directory.empty()) { if (Directory.empty()) {
// Separate the directory part from the basename of the FileName. // Separate the directory part from the basename of the FileName.
@ -582,6 +610,9 @@ Expected<unsigned> MCDwarfLineTableHeader::tryGetFile(StringRef &Directory,
File.Checksum = Checksum; File.Checksum = Checksum;
if (Checksum) if (Checksum)
HasMD5 = true; HasMD5 = true;
File.Source = Source;
if (Source)
HasSource = true;
// return the allocated FileNumber. // return the allocated FileNumber.
return FileNumber; return FileNumber;

View File

@ -3250,7 +3250,7 @@ bool AsmParser::parseDirectiveAlign(bool IsPow2, unsigned ValueSize) {
/// parseDirectiveFile /// parseDirectiveFile
/// ::= .file filename /// ::= .file filename
/// ::= .file number [directory] filename [md5 checksum] /// ::= .file number [directory] filename [md5 checksum] [source source-text]
bool AsmParser::parseDirectiveFile(SMLoc DirectiveLoc) { bool AsmParser::parseDirectiveFile(SMLoc DirectiveLoc) {
// FIXME: I'm not sure what this is. // FIXME: I'm not sure what this is.
int64_t FileNumber = -1; int64_t FileNumber = -1;
@ -3286,23 +3286,36 @@ bool AsmParser::parseDirectiveFile(SMLoc DirectiveLoc) {
} }
std::string Checksum; std::string Checksum;
if (!parseOptionalToken(AsmToken::EndOfStatement)) {
Optional<StringRef> Source;
bool HasSource = false;
std::string SourceString;
while (!parseOptionalToken(AsmToken::EndOfStatement)) {
StringRef Keyword; StringRef Keyword;
if (check(getTok().isNot(AsmToken::Identifier), if (check(getTok().isNot(AsmToken::Identifier),
"unexpected token in '.file' directive") || "unexpected token in '.file' directive") ||
parseIdentifier(Keyword) || parseIdentifier(Keyword))
check(Keyword != "md5", "unexpected token in '.file' directive"))
return true; return true;
if (getLexer().is(AsmToken::String) && if (Keyword == "md5") {
check(FileNumber == -1, "MD5 checksum specified, but no file number")) if (check(FileNumber == -1,
return true; "MD5 checksum specified, but no file number") ||
if (check(getTok().isNot(AsmToken::String), check(getTok().isNot(AsmToken::String),
"unexpected token in '.file' directive") || "unexpected token in '.file' directive") ||
parseEscapedString(Checksum) || parseEscapedString(Checksum) ||
check(Checksum.size() != 32, "invalid MD5 checksum specified") || check(Checksum.size() != 32, "invalid MD5 checksum specified"))
parseToken(AsmToken::EndOfStatement,
"unexpected token in '.file' directive"))
return true; return true;
} else if (Keyword == "source") {
HasSource = true;
if (check(FileNumber == -1,
"source specified, but no file number") ||
check(getTok().isNot(AsmToken::String),
"unexpected token in '.file' directive") ||
parseEscapedString(SourceString))
return true;
} else {
return TokError("unexpected token in '.file' directive");
}
} }
if (FileNumber == -1) if (FileNumber == -1)
@ -3316,13 +3329,18 @@ bool AsmParser::parseDirectiveFile(SMLoc DirectiveLoc) {
CKMem = (MD5::MD5Result *)Ctx.allocate(sizeof(MD5::MD5Result), 1); CKMem = (MD5::MD5Result *)Ctx.allocate(sizeof(MD5::MD5Result), 1);
memcpy(&CKMem->Bytes, Checksum.data(), 16); memcpy(&CKMem->Bytes, Checksum.data(), 16);
} }
if (HasSource) {
char *SourceBuf = static_cast<char *>(Ctx.allocate(SourceString.size()));
memcpy(SourceBuf, SourceString.data(), SourceString.size());
Source = StringRef(SourceBuf, SourceString.size());
}
// If there is -g option as well as debug info from directive file, // If there is -g option as well as debug info from directive file,
// we turn off -g option, directly use the existing debug info instead. // we turn off -g option, directly use the existing debug info instead.
if (getContext().getGenDwarfForAssembly()) if (getContext().getGenDwarfForAssembly())
getContext().setGenDwarfForAssembly(false); getContext().setGenDwarfForAssembly(false);
else { else {
Expected<unsigned> FileNumOrErr = getStreamer().tryEmitDwarfFileDirective( Expected<unsigned> FileNumOrErr = getStreamer().tryEmitDwarfFileDirective(
FileNumber, Directory, Filename, CKMem); FileNumber, Directory, Filename, CKMem, Source);
if (!FileNumOrErr) if (!FileNumOrErr)
return Error(DirectiveLoc, toString(FileNumOrErr.takeError())); return Error(DirectiveLoc, toString(FileNumOrErr.takeError()));
FileNumber = FileNumOrErr.get(); FileNumber = FileNumOrErr.get();

View File

@ -8,6 +8,7 @@
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
#include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCStreamer.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/SmallString.h" #include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Twine.h" #include "llvm/ADT/Twine.h"
@ -191,8 +192,11 @@ void MCStreamer::EmitZeros(uint64_t NumBytes) {
Expected<unsigned> Expected<unsigned>
MCStreamer::tryEmitDwarfFileDirective(unsigned FileNo, StringRef Directory, MCStreamer::tryEmitDwarfFileDirective(unsigned FileNo, StringRef Directory,
StringRef Filename, StringRef Filename,
MD5::MD5Result *Checksum, unsigned CUID) { MD5::MD5Result *Checksum,
return getContext().getDwarfFile(Directory, Filename, FileNo, Checksum, CUID); Optional<StringRef> Source,
unsigned CUID) {
return getContext().getDwarfFile(Directory, Filename, FileNo, Checksum,
Source, CUID);
} }
void MCStreamer::EmitDwarfLocDirective(unsigned FileNo, unsigned Line, void MCStreamer::EmitDwarfLocDirective(unsigned FileNo, unsigned Line,

View File

@ -1,8 +1,8 @@
; RUN: llvm-as < %s | llvm-dis | llvm-as | llvm-dis | FileCheck %s ; RUN: llvm-as < %s | llvm-dis | llvm-as | llvm-dis | FileCheck %s
; RUN: verify-uselistorder %s ; RUN: verify-uselistorder %s
; CHECK: !named = !{!0, !0, !1, !2, !3, !4, !5, !6, !7, !8, !8, !9, !10, !11, !12, !13, !14, !15, !16, !17, !18, !19, !20, !21, !22, !23, !24, !25, !26, !27, !27, !28, !29, !30, !31, !32, !33, !34, !35} ; CHECK: !named = !{!0, !0, !1, !2, !3, !4, !5, !6, !7, !8, !8, !9, !10, !11, !12, !13, !14, !15, !16, !17, !18, !19, !20, !21, !22, !23, !24, !25, !26, !27, !27, !28, !29, !30, !31, !32, !33, !34, !35, !36, !37}
!named = !{!0, !1, !2, !3, !4, !5, !6, !7, !8, !9, !10, !11, !12, !13, !14, !15, !16, !17, !18, !19, !20, !21, !22, !23, !24, !25, !26, !27, !28, !29, !30, !31, !32, !33, !34, !35, !36, !37, !38} !named = !{!0, !1, !2, !3, !4, !5, !6, !7, !8, !9, !10, !11, !12, !13, !14, !15, !16, !17, !18, !19, !20, !21, !22, !23, !24, !25, !26, !27, !28, !29, !30, !31, !32, !33, !34, !35, !36, !37, !38, !39, !40}
; CHECK: !0 = !DISubrange(count: 3) ; CHECK: !0 = !DISubrange(count: 3)
; CHECK-NEXT: !1 = !DISubrange(count: 3, lowerBound: 4) ; CHECK-NEXT: !1 = !DISubrange(count: 3, lowerBound: 4)
@ -89,3 +89,8 @@
!36 = !DICompositeType(tag: DW_TAG_variant_part, name: "A", scope: !16, size: 64, discriminator: !37) !36 = !DICompositeType(tag: DW_TAG_variant_part, name: "A", scope: !16, size: 64, discriminator: !37)
!37 = !DIDerivedType(tag: DW_TAG_member, scope: !36, baseType: !38, size: 64, align: 64, flags: DIFlagArtificial) !37 = !DIDerivedType(tag: DW_TAG_member, scope: !36, baseType: !38, size: 64, align: 64, flags: DIFlagArtificial)
!38 = !DIBasicType(name: "u64", size: 64, encoding: DW_ATE_unsigned) !38 = !DIBasicType(name: "u64", size: 64, encoding: DW_ATE_unsigned)
; CHECK-NEXT: !36 = !DIFile(filename: "file", directory: "dir", source: "int source() { }\0A")
; CHECK-NEXT: !37 = !DIFile(filename: "file", directory: "dir", checksumkind: CSK_MD5, checksum: "3a420e2646916a475e68de8d48f779f5", source: "int source() { }\0A")
!39 = !DIFile(filename: "file", directory: "dir", source: "int source() { }\0A")
!40 = !DIFile(filename: "file", directory: "dir", checksumkind: CSK_MD5, checksum: "3a420e2646916a475e68de8d48f779f5", source: "int source() { }\0A")

View File

@ -59,6 +59,8 @@ attributes #1 = { nounwind readnone }
!26 = !DILocation(line: 7, column: 17, scope: !2) !26 = !DILocation(line: 7, column: 17, scope: !2)
!27 = !DILocation(line: 9, column: 9, scope: !2) !27 = !DILocation(line: 9, column: 9, scope: !2)
; CHECK: file_names[ 1] 0 0x00000000 0x00000000 "testprog.c" ; CHECK: file_names[ 1]:
; CHECK-NEXT: name: "testprog.c"
; CHECK-NEXT: dir_index: 0
; CHECK: 0x0000000000000000 2 ; CHECK: 0x0000000000000000 2
; CHECK: 0x0000000000000028 7 ; CHECK: 0x0000000000000028 7

View File

@ -16,13 +16,21 @@
; ASM: .file 1 ".{{/|\\\\}}t1.h" md5 "11111111111111111111111111111111" ; ASM: .file 1 ".{{/|\\\\}}t1.h" md5 "11111111111111111111111111111111"
; ASM: .file 2 ".{{/|\\\\}}t2.h" md5 "22222222222222222222222222222222" ; ASM: .file 2 ".{{/|\\\\}}t2.h" md5 "22222222222222222222222222222222"
; OBJ-4: Dir Mod Time File Len File Name ; OBJ-4: file_names[ 1]:
; OBJ-4: file_names[ 1] 1 0x00000000 0x00000000 "t1.h" ; OBJ-4-NEXT: name: "t1.h"
; OBJ-4: file_names[ 2] 1 0x00000000 0x00000000 "t2.h" ; OBJ-4-NEXT: dir_index: 1
; OBJ-4: file_names[ 2]:
; OBJ-4-NEXT: name: "t2.h"
; OBJ-4-NEXT: dir_index: 1
; OBJ-5: Dir MD5 Checksum File Name ; OBJ-5: file_names[ 0]:
; OBJ-5: file_names[ 0] 1 11111111111111111111111111111111 "t1.h" ; OBJ-5-NEXT: name: "t1.h"
; OBJ-5: file_names[ 1] 1 22222222222222222222222222222222 "t2.h" ; OBJ-5-NEXT: dir_index: 1
; OBJ-5-NEXT: md5_checksum: 11111111111111111111111111111111
; OBJ-5: file_names[ 1]:
; OBJ-5-NEXT: name: "t2.h"
; OBJ-5-NEXT: dir_index: 1
; OBJ-5-NEXT: md5_checksum: 22222222222222222222222222222222
; ModuleID = 't.c' ; ModuleID = 't.c'
source_filename = "t.c" source_filename = "t.c"

View File

@ -15,7 +15,7 @@ target triple = "x86_64-unknown-linux-gnu"
!7 = !{!6} !7 = !{!6}
; The important part of the following check is that dir = #0. ; The important part of the following check is that dir = #0.
; Dir Mod Time File Len File Name ; CHECK: file_names[ 1]:
; ---- ---------- ---------- --------------------------- ; CHECK-NEXT: name: "empty.c"
; CHECK: file_names[ 1] 0 0x00000000 0x00000000 "empty.c" ; CHECK-NEXT: dir_index: 0
!5 = !{i32 1, !"Debug Info Version", i32 3} !5 = !{i32 1, !"Debug Info Version", i32 3}

View File

@ -13,7 +13,9 @@
; } ; }
; CHECK-NOT: failed to compute relocation ; CHECK-NOT: failed to compute relocation
; CHECK: file_names[ 1] 0 0x00000000 0x00000000 "dwarfdump-relocs.cl" ; CHECK: file_names[ 1]:
; CHECK-NEXT: name: "dwarfdump-relocs.cl"
; CHECK-NEXT: dir_index: 0
declare void @llvm.dbg.declare(metadata, metadata, metadata) declare void @llvm.dbg.declare(metadata, metadata, metadata)

View File

@ -11,13 +11,17 @@
; CHECK-NEXT: debug_line[{{.*}}] ; CHECK-NEXT: debug_line[{{.*}}]
; CHECK-NEXT: Line table prologue: ; CHECK-NEXT: Line table prologue:
; CHECK-NOT: include_directories ; CHECK-NOT: include_directories
; CHECK: file_names[ 1] 0 {{.*}} "a.cpp" ; CHECK: file_names[ 1]
; CHECK: name: "a.cpp"
; CHECK-NEXT: dir_index: 0
; CHECK-NOT: file_names ; CHECK-NOT: file_names
; CHECK: debug_line[{{.*}}] ; CHECK: debug_line[{{.*}}]
; CHECK-NEXT: Line table prologue: ; CHECK-NEXT: Line table prologue:
; CHECK-NOT: include_directories ; CHECK-NOT: include_directories
; CHECK: file_names[ 1] 0 {{.*}} "b.cpp" ; CHECK: file_names[ 1]
; CHECK: name: "b.cpp"
; CHECK-NEXT: dir_index: 0
; CHECK-NOT: file_names ; CHECK-NOT: file_names
; However, if a single line table is emitted and shared between CUs, the ; However, if a single line table is emitted and shared between CUs, the

View File

@ -28,11 +28,12 @@
; CHECK-NEXT: DW_MACINFO_end_file ; CHECK-NEXT: DW_MACINFO_end_file
; CHECK-LABEL: .debug_line contents: ; CHECK-LABEL: .debug_line contents:
; CHECK: Dir Mod Time File Len File Name ; CHECK: file_names[ 1]:
; CHECK: file_names[ 1] {{.*}}debug-macro.cpp ; CHECK: name: "debug-macro.cpp"
; CHECK: file_names[ 2] {{.*}}debug-macro.h ; CHECK: file_names[ 2]:
; CHECK: Dir Mod Time File Len File Name ; CHECK: name: "debug-macro.h"
; CHECK: file_names[ 1] {{.*}}debug-macro1.cpp ; CHECK: file_names[ 1]:
; CHECK: name: "debug-macro1.cpp"
!llvm.dbg.cu = !{!0, !16, !20} !llvm.dbg.cu = !{!0, !16, !20}
!llvm.module.flags = !{!13, !14} !llvm.module.flags = !{!13, !14}

View File

@ -144,6 +144,14 @@ LH_5_end:
# CHECK: include_directories[ 0] = .debug_str[0x00000028] = "Directory5a" # CHECK: include_directories[ 0] = .debug_str[0x00000028] = "Directory5a"
# CHECK: include_directories[ 1] = .debug_str[0x00000034] = "Directory5b" # CHECK: include_directories[ 1] = .debug_str[0x00000034] = "Directory5b"
# CHECK-NOT: include_directories # CHECK-NOT: include_directories
# CHECK: file_names[ 0] 0 0x00000051 0x00000052 "File5a" # CHECK: file_names[ 0]:
# CHECK: file_names[ 1] 1 0x00000053 0x00000054 "File5b" # CHECK-NEXT: name: "File5a"
# CHECK-NEXT: dir_index: 0
# CHECK-NEXT: mod_time: 0x00000051
# CHECK-NEXT: length: 0x00000052
# CHECK: file_names[ 1]:
# CHECK-NEXT: name: "File5b"
# CHECK-NEXT: dir_index: 1
# CHECK-NEXT: mod_time: 0x00000053
# CHECK-NEXT: length: 0x00000054
# CHECK-NOT: file_names # CHECK-NOT: file_names

View File

@ -258,8 +258,16 @@ LH_4_end:
# CHECK: include_directories[ 1] = "Directory4a" # CHECK: include_directories[ 1] = "Directory4a"
# CHECK: include_directories[ 2] = "Directory4b" # CHECK: include_directories[ 2] = "Directory4b"
# CHECK-NOT: include_directories # CHECK-NOT: include_directories
# CHECK: file_names[ 1] 1 0x00000041 0x00000042 "File4a" # CHECK: file_names[ 1]:
# CHECK: file_names[ 2] 0 0x00000043 0x00000044 "File4b" # CHECK-NEXT: name: "File4a"
# CHECK-NEXT: dir_index: 1
# CHECK-NEXT: mod_time: 0x00000041
# CHECK-NEXT: length: 0x00000042
# CHECK: file_names[ 2]:
# CHECK-NEXT: name: "File4b"
# CHECK-NEXT: dir_index: 0
# CHECK-NEXT: mod_time: 0x00000043
# CHECK-NEXT: length: 0x00000044
# CHECK-NOT: file_names # CHECK-NOT: file_names
# DWARF v5 line-table header. # DWARF v5 line-table header.
@ -329,9 +337,14 @@ LH_5_end:
# CHECK: include_directories[ 0] = .debug_str[0x00000045] = "Directory5a" # CHECK: include_directories[ 0] = .debug_str[0x00000045] = "Directory5a"
# CHECK: include_directories[ 1] = .debug_str[0x00000051] = "Directory5b" # CHECK: include_directories[ 1] = .debug_str[0x00000051] = "Directory5b"
# CHECK-NOT: include_directories # CHECK-NOT: include_directories
# CHECK: MD5 Checksum # CHECK: file_names[ 0]:
# CHECK: file_names[ 0] 0 00112233445566778899aabbccddeeff .debug_line_str[0x00000000] = "File5a" # CHECK-NEXT: name: .debug_line_str[0x00000000] = "File5a"
# CHECK: file_names[ 1] 1 ffeeddccbbaa99887766554433221100 .debug_line_str[0x00000007] = "File5b" # CHECK-NEXT: dir_index: 0
# CHECK-NEXT: md5_checksum: 00112233445566778899aabbccddeeff
# CHECK: file_names[ 1]:
# CHECK-NEXT: name: .debug_line_str[0x00000007] = "File5b"
# CHECK-NEXT: dir_index: 1
# CHECK-NEXT: md5_checksum: ffeeddccbbaa99887766554433221100
# CHECK-NOT: file_names # CHECK-NOT: file_names
.section .debug_line_str,"MS",@progbits,1 .section .debug_line_str,"MS",@progbits,1
@ -410,6 +423,14 @@ dwo_LH_5_end:
# CHECK: include_directories[ 0] = .debug_str[0x0000003d] = "DWODirectory5a" # CHECK: include_directories[ 0] = .debug_str[0x0000003d] = "DWODirectory5a"
# CHECK: include_directories[ 1] = .debug_str[0x0000004c] = "DWODirectory5b" # CHECK: include_directories[ 1] = .debug_str[0x0000004c] = "DWODirectory5b"
# CHECK-NOT: include_directories # CHECK-NOT: include_directories
# CHECK: file_names[ 0] 0 0x00000015 0x00000025 "DWOFile5a" # CHECK: file_names[ 0]:
# CHECK: file_names[ 1] 1 0x00000035 0x00000045 "DWOFile5b" # CHECK-NEXT: name: "DWOFile5a"
# CHECK-NEXT: dir_index: 0
# CHECK-NEXT: mod_time: 0x00000015
# CHECK-NEXT: length: 0x00000025
# CHECK: file_names[ 1]:
# CHECK-NEXT: name: "DWOFile5b"
# CHECK-NEXT: dir_index: 1
# CHECK-NEXT: mod_time: 0x00000035
# CHECK-NEXT: length: 0x00000045
# CHECK-NOT: file_names # CHECK-NOT: file_names

View File

@ -47,7 +47,8 @@ LH_1_end:
# PART1-NEXT: version: 4 # PART1-NEXT: version: 4
# PART1-NEXT: prologue_length: 0x00000028 # PART1-NEXT: prologue_length: 0x00000028
# PART1: include_directories[ 1] = "Directory1" # PART1: include_directories[ 1] = "Directory1"
# PART1: file_names[ 1] {{.*}} "File1" # PART1: file_names[ 1]
# PART1: name: "File1"
# Second line table. # Second line table.
LH_2_start: LH_2_start:
@ -93,5 +94,6 @@ LH_2_end:
# PART2-NEXT: prologue_length: 0x00000022 # PART2-NEXT: prologue_length: 0x00000022
# PART2-NOT: prologue: # PART2-NOT: prologue:
# PART2: include_directories[ 1] = "Dir2" # PART2: include_directories[ 1] = "Dir2"
# PART2: file_names[ 1] {{.*}} "File2" # PART2: file_names[ 1]
# PART2: name: "File2"
# PART2-NOT: prologue: # PART2-NOT: prologue:

View File

@ -94,7 +94,15 @@ ls_F2: .asciz "File2"
# CHECK: include_directories[ 0] = .debug_str[0x00000000] = "Directory1" # CHECK: include_directories[ 0] = .debug_str[0x00000000] = "Directory1"
# CHECK: include_directories[ 1] = .debug_str[0x0000000b] = "Directory2" # CHECK: include_directories[ 1] = .debug_str[0x0000000b] = "Directory2"
# CHECK-NOT: include_directories # CHECK-NOT: include_directories
# CHECK: file_names[ 0] 1 0x00000051 0x00000052 .debug_line_str[0x00000000] = "File1" # CHECK: file_names[ 0]:
# CHECK: file_names[ 1] 0 0x00000053 0x00000054 .debug_line_str[0x00000006] = "File2" # CHECK-NEXT: name: .debug_line_str[0x00000000] = "File1"
# CHECK-NEXT: dir_index: 1
# CHECK-NEXT: mod_time: 0x00000051
# CHECK-NEXT: length: 0x00000052
# CHECK: file_names[ 1]:
# CHECK-NEXT: name: .debug_line_str[0x00000006] = "File2"
# CHECK-NEXT: dir_index: 0
# CHECK-NEXT: mod_time: 0x00000053
# CHECK-NEXT: length: 0x00000054
# CHECK-NOT: file_names # CHECK-NOT: file_names
# CHECK: 0x0000000000000000 {{.*}} is_stmt end_sequence # CHECK: 0x0000000000000000 {{.*}} is_stmt end_sequence

View File

@ -122,8 +122,10 @@
; CHECK-LABEL: .debug_line contents: ; CHECK-LABEL: .debug_line contents:
; CHECK: Line table prologue ; CHECK: Line table prologue
; CHECK-NOT: file_names[ ; CHECK-NOT: file_names[
; SINGLE: file_names{{.*}} "bar.h" ; SINGLE: file_names[
; CHECK: file_names{{.*}} "bar.cpp" ; SINGLE-NEXT: name: "bar.h"
; CHECK: file_names[
; CHECK-NEXT: name: "bar.cpp"
; CHECK-NOT: file_names[ ; CHECK-NOT: file_names[
; FISSION: .debug_line.dwo contents: ; FISSION: .debug_line.dwo contents:
@ -133,8 +135,10 @@
; FISSION-NOT: standard_opcode_lengths ; FISSION-NOT: standard_opcode_lengths
; FISSION-NOT: include_directories ; FISSION-NOT: include_directories
; FISSION-NOT: file_names[ ; FISSION-NOT: file_names[
; FISSION: file_names{{.*}} "bar.h" ; FISSION: file_names[
; FISSION: file_names{{.*}} "bar.cpp" ; FISSION-NEXT: name: "bar.h"
; FISSION: file_names[
; FISSION-NEXT: name: "bar.cpp"
; FISSION-NOT: file_names[ ; FISSION-NOT: file_names[
; CHECK-LABEL: .debug_str contents: ; CHECK-LABEL: .debug_str contents:

View File

@ -27,11 +27,15 @@
; CHECK-NEXT: debug_line[{{.*}}] ; CHECK-NEXT: debug_line[{{.*}}]
; CHECK-NEXT: Line table prologue: ; CHECK-NEXT: Line table prologue:
; CHECK-NEXT: total_length: 0x00000038 ; CHECK-NEXT: total_length: 0x00000038
; CHECK: file_names[ 1] 0 0x00000000 0x00000000 "simple.c" ; CHECK: file_names[ 1]:
; CHECK-NEXT: name: "simple.c"
; CHECK-NEXT: dir_index: 0
; CHECK: debug_line[{{.*}}] ; CHECK: debug_line[{{.*}}]
; CHECK-NEXT: Line table prologue: ; CHECK-NEXT: Line table prologue:
; CHECK-NEXT: total_length: 0x00000039 ; CHECK-NEXT: total_length: 0x00000039
; CHECK: file_names[ 1] 0 0x00000000 0x00000000 "simple2.c" ; CHECK: file_names[ 1]:
; CHECK-NEXT: name: "simple2.c"
; CHECK-NEXT: dir_index: 0
; CHECK-NOT: file_names ; CHECK-NOT: file_names
; DWARF3: .debug_info contents: ; DWARF3: .debug_info contents:
@ -46,11 +50,15 @@
; DWARF3-NEXT: debug_line[{{.*}}] ; DWARF3-NEXT: debug_line[{{.*}}]
; DWARF3-NEXT: Line table prologue: ; DWARF3-NEXT: Line table prologue:
; DWARF3-NEXT: total_length: 0x00000038 ; DWARF3-NEXT: total_length: 0x00000038
; DWARF3: file_names[ 1] 0 0x00000000 0x00000000 "simple.c" ; DWARF3: file_names[ 1]:
; DWARF3-NEXT: name: "simple.c"
; DWARF3-NEXT: dir_index: 0
; DWARF3: debug_line[{{.*}}] ; DWARF3: debug_line[{{.*}}]
; DWARF3-NEXT: Line table prologue: ; DWARF3-NEXT: Line table prologue:
; DWARF3-NEXT: total_length: 0x00000039 ; DWARF3-NEXT: total_length: 0x00000039
; DWARF3: file_names[ 1] 0 0x00000000 0x00000000 "simple2.c" ; DWARF3: file_names[ 1]:
; DWARF3-NEXT: name: "simple2.c"
; DWARF3-NEXT: dir_index: 0
; DWARF3-NOT: file_names ; DWARF3-NOT: file_names
; PR15408 ; PR15408

View File

@ -22,6 +22,12 @@ TEST_MACINFO: DW_MACINFO_define - lineno: 3 macro: M2(x,y) ((x)+(y)* Value2)
TEST_MACINFO: DW_MACINFO_end_file TEST_MACINFO: DW_MACINFO_end_file
TEST_LINE: .debug_line contents: TEST_LINE: .debug_line contents:
TEST_LINE: file_names[ 1] 0 0x00000000 0x00000000 "dwarfdump-macro.cc" TEST_LINE: file_names[ 1]:
TEST_LINE: file_names[ 2] 1 0x00000000 0x00000000 "dwarfdump-macro-cmd.h" TEST_LINE-NEXT: name: "dwarfdump-macro.cc"
TEST_LINE: file_names[ 3] 0 0x00000000 0x00000000 "dwarfdump-macro.h" TEST_LINE-NEXT: dir_index: 0
TEST_LINE: file_names[ 2]:
TEST_LINE-NEXT: name: "dwarfdump-macro-cmd.h"
TEST_LINE-NEXT: dir_index: 1
TEST_LINE: file_names[ 3]:
TEST_LINE-NEXT: name: "dwarfdump-macro.h"
TEST_LINE-NEXT: dir_index: 0

View File

@ -147,14 +147,18 @@ entry:
; DW-LABEL: .debug_line contents: ; DW-LABEL: .debug_line contents:
; Check that we have the right things in the line table as well. ; Check that we have the right things in the line table as well.
; DWLW-LABEL: file_names[{{ *}}1]{{.*}} "bar.c" ; DWLW-LABEL: file_names[ 1]:
; DWLW-NEXT: name: "bar.c"
; DWLW: 2 0 1 0 0 is_stmt prologue_end ; DWLW: 2 0 1 0 0 is_stmt prologue_end
; DWLW-LABEL: file_names[{{ *}}1]{{.*}} "foo.c" ; DWLW-LABEL: file_names[ 1]:
; DWLW-NEXT: name: "foo.c"
; DWLW: 52 0 1 0 0 is_stmt prologue_end ; DWLW: 52 0 1 0 0 is_stmt prologue_end
; DWLW-NOT: prologue_end ; DWLW-NOT: prologue_end
; DWWL-LABEL: file_names[{{ *}}1]{{.*}} "foo.c" ; DWWL-LABEL: file_names[ 1]:
; DWWL-NEXT: name: "foo.c"
; DWWL: 52 0 1 0 0 is_stmt prologue_end ; DWWL: 52 0 1 0 0 is_stmt prologue_end
; DWWL-LABEL: file_names[{{ *}}1]{{.*}} "bar.c" ; DWWL-LABEL: file_names[ 1]:
; DWWL-NEXT: name: "bar.c"
; DWWL: 2 0 1 0 0 is_stmt prologue_end ; DWWL: 2 0 1 0 0 is_stmt prologue_end
; DWWL-NOT: prologue_end ; DWWL-NOT: prologue_end

View File

@ -55,7 +55,8 @@ b:
// DWARF-DL: version: [[DWVER]] // DWARF-DL: version: [[DWVER]]
// DWARF-DL-5: address_size: 4 // DWARF-DL-5: address_size: 4
// DWARF-DL-5: include_directories[ 0] = "" // DWARF-DL-5: include_directories[ 0] = ""
// DWARF-DL: file_names[ [[DWFILE]]] {{.*}} "<stdin>" // DWARF-DL: file_names[ [[DWFILE]]]:
// DWARF-DL: name: "<stdin>"
// DWARF-DL: 0x0000000000000000 17 0 1 0 0 is_stmt // DWARF-DL: 0x0000000000000000 17 0 1 0 0 is_stmt
// DWARF-DL-NEXT: 0x0000000000000004 17 0 1 0 0 is_stmt end_sequence // DWARF-DL-NEXT: 0x0000000000000004 17 0 1 0 0 is_stmt end_sequence
// DWARF-DL-NEXT: 0x0000000000000000 21 0 1 0 0 is_stmt // DWARF-DL-NEXT: 0x0000000000000000 21 0 1 0 0 is_stmt

View File

@ -13,9 +13,14 @@
# CHECK: include_directories[ 1] = .debug_line_str[0x[[DIR1:[0-9a-f]+]]] = "dir1" # CHECK: include_directories[ 1] = .debug_line_str[0x[[DIR1:[0-9a-f]+]]] = "dir1"
# CHECK: include_directories[ 2] = .debug_line_str[0x[[DIR2:[0-9a-f]+]]] = "dir2" # CHECK: include_directories[ 2] = .debug_line_str[0x[[DIR2:[0-9a-f]+]]] = "dir2"
# CHECK-NOT: include_directories # CHECK-NOT: include_directories
# CHECK: Dir MD5 Checksum File Name # CHECK: file_names[ 0]:
# CHECK: file_names[ 0] 1 00112233445566778899aabbccddeeff .debug_line_str[0x[[FILE1:[0-9a-f]+]]] = "foo" # CHECK-NEXT: name: .debug_line_str[0x[[FILE1:[0-9a-f]+]]] = "foo"
# CHECK: file_names[ 1] 2 ffeeddccbbaa99887766554433221100 .debug_line_str[0x[[FILE2:[0-9a-f]+]]] = "bar" # CHECK-NEXT: dir_index: 1
# CHECK-NEXT: md5_checksum: 00112233445566778899aabbccddeeff
# CHECK: file_names[ 1]:
# CHECK-NEXT: name: .debug_line_str[0x[[FILE2:[0-9a-f]+]]] = "bar"
# CHECK-NEXT: dir_index: 2
# CHECK-NEXT: md5_checksum: ffeeddccbbaa99887766554433221100
# CHECK: .debug_line_str contents: # CHECK: .debug_line_str contents:
# CHECK-NEXT: 0x[[DIR0]]: "" # CHECK-NEXT: 0x[[DIR0]]: ""

View File

@ -16,11 +16,15 @@ L1: leave
// We check that the source name "t.s" is picked up // We check that the source name "t.s" is picked up
// CHECK: include_directories[ 1] = "{{.*(/|\\\\)}}test{{(/|\\\\)}}MC{{(/|\\\\)}}MachO" // CHECK: include_directories[ 1] = "{{.*(/|\\\\)}}test{{(/|\\\\)}}MC{{(/|\\\\)}}MachO"
// CHECK: include_directories[ 2] = "inc" // CHECK: include_directories[ 2] = "inc"
// CHECK: Dir Mod Time File Len File Name // CHECK: file_names[ 1]:
// CHECK: ---- ---------- ---------- --------------------------- // CHECK-NEXT: name: "gen-dwarf-cpp.s"
// CHECK: file_names[ 1] 1 0x00000000 0x00000000 "gen-dwarf-cpp.s" // CHECK-NEXT: dir_index: 1
// CHECK: file_names[ 2] 0 0x00000000 0x00000000 "t.s" // CHECK: file_names[ 2]:
// CHECK: file_names[ 3] 2 0x00000000 0x00000000 "g.s" // CHECK-NEXT: name: "t.s"
// CHECK-NEXT: dir_index: 0
// CHECK: file_names[ 3]:
// CHECK-NEXT: name: "g.s"
// CHECK-NEXT: dir_index: 2
// CHECK-NOT: file_names // CHECK-NOT: file_names
// We check that the source line number 100 is picked up before the "movl" // We check that the source line number 100 is picked up before the "movl"

View File

@ -11,7 +11,9 @@
// rdar://12637628 // rdar://12637628
// We check that the source name "foo.S" is picked up // We check that the source name "foo.S" is picked up
// CHECK: Dir Mod Time File Len File Name // CHECK: file_names[ 1]:
// CHECK: ---- ---------- ---------- --------------------------- // CHECK-NEXT: name: "gen-dwarf-macro-cpp.s"
// CHECK: file_names[ 1] 1 0x00000000 0x00000000 "gen-dwarf-macro-cpp.s" // CHECK-NEXT: dir_index: 1
// CHECK: file_names[ 2] 0 0x00000000 0x00000000 "foo.S" // CHECK: file_names[ 2]:
// CHECK-NEXT: name: "foo.S"
// CHECK-NEXT: dir_index: 0

View File

@ -109,9 +109,9 @@ _x: .long 1
// CHECK: standard_opcode_lengths[DW_LNS_set_epilogue_begin] = 0 // CHECK: standard_opcode_lengths[DW_LNS_set_epilogue_begin] = 0
// CHECK: standard_opcode_lengths[DW_LNS_set_isa] = 1 // CHECK: standard_opcode_lengths[DW_LNS_set_isa] = 1
// We don't check include_directories as it has a temp path // We don't check include_directories as it has a temp path
// CHECK: Dir Mod Time File Len File Name // CHECK: file_names[ 1]:
// CHECK: ---- ---------- ---------- --------------------------- // CHECK-NEXT: name: "gen-dwarf.s"
// CHECK: file_names[ 1] 1 0x00000000 0x00000000 "gen-dwarf.s" // CHECK-NEXT: dir_index: 1
// CHECK: Address Line Column File ISA Discriminator Flags // CHECK: Address Line Column File ISA Discriminator Flags
// CHECK: ------------------ ------ ------ ------ --- ------------- ------------- // CHECK: ------------------ ------ ------ ------ --- ------------- -------------

View File

@ -153,18 +153,18 @@ CHECK-NEXT:[0x0000000100000f40, 0x0000000100000f84)
CHECK-NEXT:[0x0000000100000f90, 0x0000000100000fa9) CHECK-NEXT:[0x0000000100000f90, 0x0000000100000fa9)
CHECK: .debug_line contents: CHECK: .debug_line contents:
CHECK: Dir Mod Time File Len File Name CHECK: file_names[ 1]:
CHECK-NEXT: ---- ---------- ---------- --------------------------- CHECK-NEXT: name: "basic1.c"
CHECK-NEXT: file_names[ 1] 0 0x00000000 0x00000000 "basic1.c" CHECK-NEXT: dir_index: 0
CHECK: Address Line Column File ISA Discriminator Flags CHECK: Address Line Column File ISA Discriminator Flags
CHECK-NEXT: ------------------ ------ ------ ------ --- ------------- ------------- CHECK-NEXT: ------------------ ------ ------ ------ --- ------------- -------------
CHECK-NEXT: 0x0000000100000ea0 23 0 1 0 0 is_stmt CHECK-NEXT: 0x0000000100000ea0 23 0 1 0 0 is_stmt
CHECK-NEXT: 0x0000000100000eb6 24 0 1 0 0 is_stmt prologue_end CHECK-NEXT: 0x0000000100000eb6 24 0 1 0 0 is_stmt prologue_end
CHECK-NEXT: 0x0000000100000ec4 24 0 1 0 0 is_stmt end_sequence CHECK-NEXT: 0x0000000100000ec4 24 0 1 0 0 is_stmt end_sequence
CHECK: Dir Mod Time File Len File Name CHECK: file_names[ 1]:
CHECK-NEXT: ---- ---------- ---------- --------------------------- CHECK-NEXT: name: "basic2.c"
CHECK-NEXT: file_names[ 1] 0 0x00000000 0x00000000 "basic2.c" CHECK-NEXT: dir_index: 0
CHECK: Address Line Column File ISA Discriminator Flags CHECK: Address Line Column File ISA Discriminator Flags
CHECK-NEXT: ------------------ ------ ------ ------ --- ------------- ------------- CHECK-NEXT: ------------------ ------ ------ ------ --- ------------- -------------
CHECK-NEXT: 0x0000000100000ed0 19 0 1 0 0 is_stmt CHECK-NEXT: 0x0000000100000ed0 19 0 1 0 0 is_stmt
@ -174,9 +174,9 @@ CHECK-NEXT: 0x0000000100000f20 14 0 1 0 0 is_stmt
CHECK-NEXT: 0x0000000100000f24 15 0 1 0 0 is_stmt prologue_end CHECK-NEXT: 0x0000000100000f24 15 0 1 0 0 is_stmt prologue_end
CHECK-NEXT: 0x0000000100000f37 15 0 1 0 0 is_stmt end_sequence CHECK-NEXT: 0x0000000100000f37 15 0 1 0 0 is_stmt end_sequence
CHECK: Dir Mod Time File Len File Name CHECK: file_names[ 1]:
CHECK-NEXT: ---- ---------- ---------- --------------------------- CHECK-NEXT: name: "basic3.c"
CHECK-NEXT: file_names[ 1] 0 0x00000000 0x00000000 "basic3.c" CHECK-NEXT: dir_index: 0
CHECK: Address Line Column File ISA Discriminator Flags CHECK: Address Line Column File ISA Discriminator Flags
CHECK-NEXT: ------------------ ------ ------ ------ --- ------------- ------------- CHECK-NEXT: ------------------ ------ ------ ------ --- ------------- -------------
CHECK-NEXT: 0x0000000100000f40 16 0 1 0 0 is_stmt CHECK-NEXT: 0x0000000100000f40 16 0 1 0 0 is_stmt

View File

@ -138,9 +138,9 @@ CHECK-NEXT: Address Range Header: length = 0x0000002c, version = 0x0002, cu_offs
CHECK-NEXT: [0x0000000100000f90, 0x0000000100000fb4) CHECK-NEXT: [0x0000000100000f90, 0x0000000100000fb4)
CHECK: .debug_line contents: CHECK: .debug_line contents:
CHECK: Dir Mod Time File Len File Name CHECK: file_names[ 1]:
CHECK-NEXT: ---- ---------- ---------- --------------------------- CHECK-NEXT: name: "basic1.c"
CHECK-NEXT: file_names[ 1] 0 0x00000000 0x00000000 "basic1.c" CHECK-NEXT: dir_index: 0
CHECK: Address Line Column File ISA Discriminator Flags CHECK: Address Line Column File ISA Discriminator Flags
CHECK-NEXT: ------------------ ------ ------ ------ --- ------------- ------------- CHECK-NEXT: ------------------ ------ ------ ------ --- ------------- -------------
CHECK-NEXT: 0x0000000100000f40 26 0 1 0 0 is_stmt CHECK-NEXT: 0x0000000100000f40 26 0 1 0 0 is_stmt
@ -148,9 +148,9 @@ CHECK-NEXT: 0x0000000100000f44 27 10 1 0 0 is_stmt p
CHECK-NEXT: 0x0000000100000f49 27 3 1 0 0 CHECK-NEXT: 0x0000000100000f49 27 3 1 0 0
CHECK-NEXT: 0x0000000100000f4b 27 3 1 0 0 end_sequence CHECK-NEXT: 0x0000000100000f4b 27 3 1 0 0 end_sequence
CHECK: Dir Mod Time File Len File Name CHECK: file_names[ 1]:
CHECK-NEXT: ---- ---------- ---------- --------------------------- CHECK-NEXT: name: "basic2.c"
CHECK-NEXT: file_names[ 1] 0 0x00000000 0x00000000 "basic2.c" CHECK-NEXT: dir_index: 0
CHECK: Address Line Column File ISA Discriminator Flags CHECK: Address Line Column File ISA Discriminator Flags
CHECK-NEXT: ------------------ ------ ------ ------ --- ------------- ------------- CHECK-NEXT: ------------------ ------ ------ ------ --- ------------- -------------
CHECK-NEXT: 0x0000000100000f50 19 0 1 0 0 is_stmt CHECK-NEXT: 0x0000000100000f50 19 0 1 0 0 is_stmt
@ -164,9 +164,9 @@ CHECK-NEXT: 0x0000000100000f83 20 31 1 0 0
CHECK-NEXT: 0x0000000100000f85 20 3 1 0 0 CHECK-NEXT: 0x0000000100000f85 20 3 1 0 0
CHECK-NEXT: 0x0000000100000f87 20 3 1 0 0 end_sequence CHECK-NEXT: 0x0000000100000f87 20 3 1 0 0 end_sequence
CHECK: Dir Mod Time File Len File Name CHECK: file_names[ 1]:
CHECK-NEXT: ---- ---------- ---------- --------------------------- CHECK-NEXT: name: "basic3.c"
CHECK-NEXT: file_names[ 1] 0 0x00000000 0x00000000 "basic3.c" CHECK-NEXT: dir_index: 0
CHECK: Address Line Column File ISA Discriminator Flags CHECK: Address Line Column File ISA Discriminator Flags
CHECK-NEXT: ------------------ ------ ------ ------ --- ------------- ------------- CHECK-NEXT: ------------------ ------ ------ ------ --- ------------- -------------
CHECK-NEXT: 0x0000000100000f90 16 0 1 0 0 is_stmt CHECK-NEXT: 0x0000000100000f90 16 0 1 0 0 is_stmt

View File

@ -150,25 +150,25 @@ CHECK-NEXT: [0x0000000100000f90, 0x0000000100000fb4)
CHECK: .debug_line contents CHECK: .debug_line contents
CHECK: Dir Mod Time File Len File Name CHECK: file_names[ 1]:
CHECK-NEXT: ---- ---------- ---------- --------------------------- CHECK-NEXT: name: "basic1.c"
CHECK-NEXT: file_names[ 1] 0 0x00000000 0x00000000 "basic1.c" CHECK-NEXT: dir_index: 0
CHECK: 0x0000000100000f40 23 0 1 0 0 is_stmt CHECK: 0x0000000100000f40 23 0 1 0 0 is_stmt
CHECK: 0x0000000100000f44 24 0 1 0 0 is_stmt prologue_end CHECK: 0x0000000100000f44 24 0 1 0 0 is_stmt prologue_end
CHECK: 0x0000000100000f4b 24 0 1 0 0 is_stmt end_sequence CHECK: 0x0000000100000f4b 24 0 1 0 0 is_stmt end_sequence
CHECK: Dir Mod Time File Len File Name CHECK: file_names[ 1]:
CHECK-NEXT: ---- ---------- ---------- --------------------------- CHECK-NEXT: name: "basic2.c"
CHECK-NEXT: file_names[ 1] 0 0x00000000 0x00000000 "basic2.c" CHECK-NEXT: dir_index: 0
CHECK: 0x0000000100000f50 19 0 1 0 0 is_stmt CHECK: 0x0000000100000f50 19 0 1 0 0 is_stmt
CHECK: 0x0000000100000f54 20 0 1 0 0 is_stmt prologue_end CHECK: 0x0000000100000f54 20 0 1 0 0 is_stmt prologue_end
CHECK: 0x0000000100000f63 15 0 1 0 0 is_stmt CHECK: 0x0000000100000f63 15 0 1 0 0 is_stmt
CHECK: 0x0000000100000f72 20 0 1 0 0 is_stmt CHECK: 0x0000000100000f72 20 0 1 0 0 is_stmt
CHECK: 0x0000000100000f89 20 0 1 0 0 is_stmt end_sequence CHECK: 0x0000000100000f89 20 0 1 0 0 is_stmt end_sequence
CHECK: Dir Mod Time File Len File Name CHECK: file_names[ 1]:
CHECK-NEXT: ---- ---------- ---------- --------------------------- CHECK-NEXT: name: "basic3.c"
CHECK-NEXT: file_names[ 1] 0 0x00000000 0x00000000 "basic3.c" CHECK-NEXT: dir_index: 0
CHECK: 0x0000000100000f90 16 0 1 0 0 is_stmt CHECK: 0x0000000100000f90 16 0 1 0 0 is_stmt
CHECK: 0x0000000100000f94 12 0 1 0 0 is_stmt prologue_end CHECK: 0x0000000100000f94 12 0 1 0 0 is_stmt prologue_end
CHECK: 0x0000000100000f9a 17 0 1 0 0 is_stmt CHECK: 0x0000000100000f9a 17 0 1 0 0 is_stmt

View File

@ -408,7 +408,7 @@ protected:
std::unordered_map<std::string, std::vector<StringRef>> LineCache; std::unordered_map<std::string, std::vector<StringRef>> LineCache;
private: private:
bool cacheSource(const std::string& File); bool cacheSource(const DILineInfo& LineInfoFile);
public: public:
SourcePrinter() = default; SourcePrinter() = default;
@ -423,23 +423,29 @@ public:
StringRef Delimiter = "; "); StringRef Delimiter = "; ");
}; };
bool SourcePrinter::cacheSource(const std::string& File) { bool SourcePrinter::cacheSource(const DILineInfo &LineInfo) {
auto BufferOrError = MemoryBuffer::getFile(File); std::unique_ptr<MemoryBuffer> Buffer;
if (LineInfo.Source) {
Buffer = MemoryBuffer::getMemBuffer(*LineInfo.Source);
} else {
auto BufferOrError = MemoryBuffer::getFile(LineInfo.FileName);
if (!BufferOrError) if (!BufferOrError)
return false; return false;
Buffer = std::move(*BufferOrError);
}
// Chomp the file to get lines // Chomp the file to get lines
size_t BufferSize = (*BufferOrError)->getBufferSize(); size_t BufferSize = Buffer->getBufferSize();
const char *BufferStart = (*BufferOrError)->getBufferStart(); const char *BufferStart = Buffer->getBufferStart();
for (const char *Start = BufferStart, *End = BufferStart; for (const char *Start = BufferStart, *End = BufferStart;
End < BufferStart + BufferSize; End++) End < BufferStart + BufferSize; End++)
if (*End == '\n' || End == BufferStart + BufferSize - 1 || if (*End == '\n' || End == BufferStart + BufferSize - 1 ||
(*End == '\r' && *(End + 1) == '\n')) { (*End == '\r' && *(End + 1) == '\n')) {
LineCache[File].push_back(StringRef(Start, End - Start)); LineCache[LineInfo.FileName].push_back(StringRef(Start, End - Start));
if (*End == '\r') if (*End == '\r')
End++; End++;
Start = End + 1; Start = End + 1;
} }
SourceCache[File] = std::move(*BufferOrError); SourceCache[LineInfo.FileName] = std::move(Buffer);
return true; return true;
} }
@ -463,7 +469,7 @@ void SourcePrinter::printSourceLine(raw_ostream &OS, uint64_t Address,
OS << Delimiter << LineInfo.FileName << ":" << LineInfo.Line << "\n"; OS << Delimiter << LineInfo.FileName << ":" << LineInfo.Line << "\n";
if (PrintSource) { if (PrintSource) {
if (SourceCache.find(LineInfo.FileName) == SourceCache.end()) if (SourceCache.find(LineInfo.FileName) == SourceCache.end())
if (!cacheSource(LineInfo.FileName)) if (!cacheSource(LineInfo))
return; return;
auto FileBuffer = SourceCache.find(LineInfo.FileName); auto FileBuffer = SourceCache.find(LineInfo.FileName);
if (FileBuffer != SourceCache.end()) { if (FileBuffer != SourceCache.end()) {

View File

@ -1450,19 +1450,24 @@ TEST_F(DIFileTest, get) {
DIFile::ChecksumKind CSKind = DIFile::ChecksumKind::CSK_MD5; DIFile::ChecksumKind CSKind = DIFile::ChecksumKind::CSK_MD5;
StringRef ChecksumString = "000102030405060708090a0b0c0d0e0f"; StringRef ChecksumString = "000102030405060708090a0b0c0d0e0f";
DIFile::ChecksumInfo<StringRef> Checksum(CSKind, ChecksumString); DIFile::ChecksumInfo<StringRef> Checksum(CSKind, ChecksumString);
auto *N = DIFile::get(Context, Filename, Directory, Checksum); StringRef Source = "source";
auto *N = DIFile::get(Context, Filename, Directory, Checksum, Source);
EXPECT_EQ(dwarf::DW_TAG_file_type, N->getTag()); EXPECT_EQ(dwarf::DW_TAG_file_type, N->getTag());
EXPECT_EQ(Filename, N->getFilename()); EXPECT_EQ(Filename, N->getFilename());
EXPECT_EQ(Directory, N->getDirectory()); EXPECT_EQ(Directory, N->getDirectory());
EXPECT_EQ(Checksum, N->getChecksum()); EXPECT_EQ(Checksum, N->getChecksum());
EXPECT_EQ(N, DIFile::get(Context, Filename, Directory, Checksum)); EXPECT_EQ(Source, N->getSource());
EXPECT_EQ(N, DIFile::get(Context, Filename, Directory, Checksum, Source));
EXPECT_NE(N, DIFile::get(Context, "other", Directory, Checksum)); EXPECT_NE(N, DIFile::get(Context, "other", Directory, Checksum, Source));
EXPECT_NE(N, DIFile::get(Context, Filename, "other", Checksum)); EXPECT_NE(N, DIFile::get(Context, Filename, "other", Checksum, Source));
DIFile::ChecksumInfo<StringRef> OtherChecksum(DIFile::ChecksumKind::CSK_SHA1, ChecksumString); DIFile::ChecksumInfo<StringRef> OtherChecksum(DIFile::ChecksumKind::CSK_SHA1, ChecksumString);
EXPECT_NE( EXPECT_NE(
N, DIFile::get(Context, Filename, Directory, OtherChecksum)); N, DIFile::get(Context, Filename, Directory, OtherChecksum));
StringRef OtherSource = "other";
EXPECT_NE(N, DIFile::get(Context, Filename, Directory, Checksum, OtherSource));
EXPECT_NE(N, DIFile::get(Context, Filename, Directory, Checksum));
EXPECT_NE(N, DIFile::get(Context, Filename, Directory)); EXPECT_NE(N, DIFile::get(Context, Filename, Directory));
TempDIFile Temp = N->clone(); TempDIFile Temp = N->clone();