================ @@ -0,0 +1,2348 @@ +//===-- LVIRReader.cpp ----------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This implements the LVIRReader class. +// It supports LLVM text IR and bitcode format. +// +//===----------------------------------------------------------------------===// + +#include "llvm/DebugInfo/LogicalView/Readers/LVIRReader.h" +#include "llvm/CodeGen/DebugHandlerBase.h" +#include "llvm/DebugInfo/LogicalView/Core/LVLine.h" +#include "llvm/DebugInfo/LogicalView/Core/LVScope.h" +#include "llvm/DebugInfo/LogicalView/Core/LVSymbol.h" +#include "llvm/DebugInfo/LogicalView/Core/LVType.h" +#include "llvm/IR/DebugInfoMetadata.h" +#include "llvm/IR/Instructions.h" +#include "llvm/IR/IntrinsicInst.h" +#include "llvm/IR/Module.h" +#include "llvm/IRReader/IRReader.h" +#include "llvm/Object/Error.h" +#include "llvm/Object/IRObjectFile.h" +#include "llvm/Support/FormatAdapters.h" +#include "llvm/Support/FormatVariadic.h" +#include "llvm/Support/SourceMgr.h" + +using namespace llvm; +using namespace llvm::object; +using namespace llvm::logicalview; + +#define DEBUG_TYPE "IRReader" + +// Extra debug traces. Default is false +#define DEBUG_ALL + +// These flavours of DINodes are not handled: +// DW_TAG_APPLE_property = 19896 +// DW_TAG_atomic_type = 71 +// DW_TAG_common_block = 26 +// DW_TAG_file_type = 41 +// DW_TAG_friend = 42 +// DW_TAG_generic_subrange = 69 +// DW_TAG_immutable_type = 75 +// DW_TAG_module = 30 + +// Create a logical element and setup the following information: +// - Name, DWARF tag, line +// - Collect any file information +LVElement *LVIRReader::constructElement(const DINode *DN) { + dwarf::Tag Tag = DN->getTag(); + LVElement *Element = createElement(Tag); + if (Element) { + Element->setTag(Tag); + addMD(DN, Element); + + StringRef Name = getMDName(DN); + if (!Name.empty()) + Element->setName(Name); + + // Record any file information. + if (const DIFile *File = getMDFile(DN)) + getOrCreateSourceID(File); + } + + return Element; +} + +void LVIRReader::mapFortranLanguage(unsigned DWLang) { + switch (DWLang) { + case dwarf::DW_LANG_Fortran77: + case dwarf::DW_LANG_Fortran90: + case dwarf::DW_LANG_Fortran95: + case dwarf::DW_LANG_Fortran03: + case dwarf::DW_LANG_Fortran08: + case dwarf::DW_LANG_Fortran18: + LanguageIsFortran = true; + break; + default: + LanguageIsFortran = false; + } +} + +// Looking at IR generated with the '-gdwarf -gsplit-dwarf=split' the only +// difference is setting the 'DICompileUnit::splitDebugFilename' to the +// name of the split filename: "xxx.dwo". +bool LVIRReader::includeMinimalInlineScopes() const { + return getCUNode()->getEmissionKind() == DICompileUnit::LineTablesOnly; +} + +// For the given 'DIFile' generate an index 1-based to indicate the +// source file where the logical element is declared. +// In DWARF v4, the files are 1-indexed. +// In DWARF v5, the files are 0-indexed. +// The IR reader expects the indexes as 1-indexed. +// Each compile unit, keeps track of the last assigned index. +size_t LVIRReader::getOrCreateSourceID(const DIFile *File) { + if (!File) + return 0; + +#ifdef DEBUG_ALL + LLVM_DEBUG({ + dbgs() << "\n[getOrCreateSourceID] DIFile\n"; + File->dump(); + }); +#endif + + addMD(File, CompileUnit); + + LLVM_DEBUG({ + dbgs() << "Directory: '" << File->getDirectory() << "'\n"; + dbgs() << "Filename: '" << File->getFilename() << "'\n"; + }); + size_t FileIndex = 0; + LVCompileUnitFiles::iterator Iter = CompileUnitFiles.find(File); + if (Iter == CompileUnitFiles.cend()) { + FileIndex = getFileIndex(CompileUnit); + std::string Directory(File->getDirectory()); + if (Directory.empty()) + Directory = std::string(CompileUnit->getCompilationDirectory()); + + std::string FullName; + raw_string_ostream Out(FullName); + Out << Directory << "/" << llvm::sys::path::filename(File->getFilename()); + CompileUnit->addFilename(transformPath(FullName)); + CompileUnitFiles.emplace(File, ++FileIndex); + updateFileIndex(CompileUnit, FileIndex); + } else { + FileIndex = Iter->second; + } + + LLVM_DEBUG({ dbgs() << "FileIndex: " << FileIndex << "\n"; }); + return FileIndex; +} + +void LVIRReader::addSourceLine(LVElement *Element, unsigned Line, + const DIFile *File) { + if (Line == 0) + return; + + // After the scopes are created, the generic reader traverses the 'Children' + // and perform additional setting tasks (resolve types names, references, + // etc.). One of those tasks is select the correct string pool index based on + // the commmand line options: --attribute=filename or --attribute=pathname. + // As the 'Children' do not include logical lines, do that selection now, + // by calling 'setFilename' if the logical element is a line. + size_t FileID = getOrCreateSourceID(File); + if (Element->getIsLine()) + Element->setFilename(CompileUnit->getFilename(FileID)); + else + Element->setFilenameIndex(FileID); + Element->setLineNumber(Line); + + LLVM_DEBUG({ + dbgs() << "\n[addSourceLine]\n"; + File->dump(); + dbgs() << "FileIndex: " << Element->getFilenameIndex() << ", "; + dbgs() << "ID: " << Element->getID() << ", "; + dbgs() << "Kind: " << Element->kind() << ", "; + dbgs() << "Line: " << Element->getLineNumber() << ", "; + dbgs() << "Name: " << Element->getName() << "\n"; + }); +} + +void LVIRReader::addSourceLine(LVElement *Element, const DIGlobalVariable *G) { + assert(G); + addSourceLine(Element, G->getLine(), G->getFile()); +} + +void LVIRReader::addSourceLine(LVElement *Element, const DIImportedEntity *IE) { + assert(IE); + addSourceLine(Element, IE->getLine(), IE->getFile()); +} + +void LVIRReader::addSourceLine(LVElement *Element, const DILabel *L) { + assert(L); + addSourceLine(Element, L->getLine(), L->getFile()); +} + +void LVIRReader::addSourceLine(LVElement *Element, const DILocalVariable *V) { + assert(V); + addSourceLine(Element, V->getLine(), V->getFile()); +} + +void LVIRReader::addSourceLine(LVElement *Element, const DILocation *DL) { + assert(DL); + addSourceLine(Element, DL->getLine(), DL->getFile()); +} + +void LVIRReader::addSourceLine(LVElement *Element, const DIObjCProperty *Ty) { + assert(Ty); + addSourceLine(Element, Ty->getLine(), Ty->getFile()); +} + +void LVIRReader::addSourceLine(LVElement *Element, const DISubprogram *SP) { + assert(SP); + addSourceLine(Element, SP->getLine(), SP->getFile()); +} + +void LVIRReader::addSourceLine(LVElement *Element, const DIType *Ty) { + assert(Ty); + addSourceLine(Element, Ty->getLine(), Ty->getFile()); +} + +void LVIRReader::addConstantValue(LVElement *Element, + const DIExpression *DIExpr) { + std::optional<DIExpression::SignedOrUnsignedConstant> Constant = + DIExpr->isConstant(); + std::stringstream Stream; + if (DIExpression::SignedOrUnsignedConstant::SignedConstant == Constant) { ---------------- jmorse wrote:
Don't we need to check for whether the std::optional is empty before examining `Constant`? If it's guaranteed, best to assert that `Constant` isn't empty. https://github.com/llvm/llvm-project/pull/135440 _______________________________________________ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits