diff options
Diffstat (limited to 'lib/CodeGen/AsmPrinter/DwarfUnit.cpp')
| -rw-r--r-- | lib/CodeGen/AsmPrinter/DwarfUnit.cpp | 234 | 
1 files changed, 184 insertions, 50 deletions
| diff --git a/lib/CodeGen/AsmPrinter/DwarfUnit.cpp b/lib/CodeGen/AsmPrinter/DwarfUnit.cpp index 911e46235781..43b835b2c4aa 100644 --- a/lib/CodeGen/AsmPrinter/DwarfUnit.cpp +++ b/lib/CodeGen/AsmPrinter/DwarfUnit.cpp @@ -19,10 +19,10 @@  #include "llvm/ADT/APFloat.h"  #include "llvm/ADT/APInt.h"  #include "llvm/ADT/None.h" +#include "llvm/ADT/StringExtras.h"  #include "llvm/ADT/iterator_range.h"  #include "llvm/CodeGen/MachineFunction.h"  #include "llvm/CodeGen/MachineOperand.h" -#include "llvm/CodeGen/TargetLoweringObjectFile.h"  #include "llvm/CodeGen/TargetRegisterInfo.h"  #include "llvm/CodeGen/TargetSubtargetInfo.h"  #include "llvm/IR/Constants.h" @@ -30,12 +30,14 @@  #include "llvm/IR/GlobalValue.h"  #include "llvm/IR/Metadata.h"  #include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCContext.h"  #include "llvm/MC/MCDwarf.h"  #include "llvm/MC/MCSection.h"  #include "llvm/MC/MCStreamer.h"  #include "llvm/MC/MachineLocation.h"  #include "llvm/Support/Casting.h"  #include "llvm/Support/CommandLine.h" +#include "llvm/Target/TargetLoweringObjectFile.h"  #include <cassert>  #include <cstdint>  #include <string> @@ -45,11 +47,6 @@ using namespace llvm;  #define DEBUG_TYPE "dwarfdebug" -static cl::opt<bool> -GenerateDwarfTypeUnits("generate-type-units", cl::Hidden, -                       cl::desc("Generate DWARF4 type units."), -                       cl::init(false)); -  DIEDwarfExpression::DIEDwarfExpression(const AsmPrinter &AP, DwarfUnit &DU,                                         DIELoc &DIE)      : DwarfExpression(AP.getDwarfVersion()), AP(AP), DU(DU), @@ -83,8 +80,6 @@ DwarfTypeUnit::DwarfTypeUnit(DwarfCompileUnit &CU, AsmPrinter *A,                               MCDwarfDwoLineTable *SplitLineTable)      : DwarfUnit(dwarf::DW_TAG_type_unit, CU.getCUNode(), A, DW, DWU), CU(CU),        SplitLineTable(SplitLineTable) { -  if (SplitLineTable) -    addSectionOffset(getUnitDie(), dwarf::DW_AT_stmt_list, 0);  }  DwarfUnit::~DwarfUnit() { @@ -185,7 +180,7 @@ bool DwarfUnit::isShareableAcrossCUs(const DINode *D) const {      return false;    return (isa<DIType>(D) ||            (isa<DISubprogram>(D) && !cast<DISubprogram>(D)->isDefinition())) && -         !GenerateDwarfTypeUnits; +         !DD->generateTypeUnits();  }  DIE *DwarfUnit::getDIE(const DINode *D) const { @@ -239,9 +234,28 @@ void DwarfUnit::addSInt(DIELoc &Die, Optional<dwarf::Form> Form,  void DwarfUnit::addString(DIE &Die, dwarf::Attribute Attribute,                            StringRef String) { -  Die.addValue(DIEValueAllocator, Attribute, -               isDwoUnit() ? dwarf::DW_FORM_GNU_str_index : dwarf::DW_FORM_strp, -               DIEString(DU->getStringPool().getEntry(*Asm, String))); +  if (DD->useInlineStrings()) { +    Die.addValue(DIEValueAllocator, Attribute, dwarf::DW_FORM_string, +                 new (DIEValueAllocator) +                     DIEInlineString(String, DIEValueAllocator)); +    return; +  } +  auto StringPoolEntry = DU->getStringPool().getEntry(*Asm, String); +  dwarf::Form IxForm = +      isDwoUnit() ? dwarf::DW_FORM_GNU_str_index : dwarf::DW_FORM_strp; +  // For DWARF v5 and beyond, use the smallest strx? form possible. +  if (useSegmentedStringOffsetsTable()) { +    IxForm = dwarf::DW_FORM_strx1; +    unsigned Index = StringPoolEntry.getIndex(); +    if (Index > 0xffffff) +      IxForm = dwarf::DW_FORM_strx4; +    else if (Index > 0xffff) +      IxForm = dwarf::DW_FORM_strx3; +    else if (Index > 0xff) +      IxForm = dwarf::DW_FORM_strx2; +  } +  Die.addValue(DIEValueAllocator, Attribute, IxForm, +               DIEString(StringPoolEntry));  }  DIEValueList::value_iterator DwarfUnit::addLabel(DIEValueList &Die, @@ -263,9 +277,33 @@ void DwarfUnit::addSectionOffset(DIE &Die, dwarf::Attribute Attribute,      addUInt(Die, Attribute, dwarf::DW_FORM_data4, Integer);  } -unsigned DwarfTypeUnit::getOrCreateSourceID(StringRef FileName, StringRef DirName) { -  return SplitLineTable ? SplitLineTable->getFile(DirName, FileName) -                        : getCU().getOrCreateSourceID(FileName, DirName); +MD5::MD5Result *DwarfUnit::getMD5AsBytes(const DIFile *File) const { +  assert(File); +  if (DD->getDwarfVersion() < 5) +    return nullptr; +  Optional<DIFile::ChecksumInfo<StringRef>> Checksum = File->getChecksum(); +  if (!Checksum || Checksum->Kind != DIFile::CSK_MD5) +    return nullptr; + +  // Convert the string checksum to an MD5Result for the streamer. +  // The verifier validates the checksum so we assume it's okay. +  // An MD5 checksum is 16 bytes. +  std::string ChecksumString = fromHex(Checksum->Value); +  void *CKMem = Asm->OutStreamer->getContext().allocate(16, 1); +  memcpy(CKMem, ChecksumString.data(), 16); +  return reinterpret_cast<MD5::MD5Result *>(CKMem); +} + +unsigned DwarfTypeUnit::getOrCreateSourceID(const DIFile *File) { +  if (!SplitLineTable) +    return getCU().getOrCreateSourceID(File); +  if (!UsedLineTable) { +    UsedLineTable = true; +    // This is a split type unit that needs a line table. +    addSectionOffset(getUnitDie(), dwarf::DW_AT_stmt_list, 0); +  } +  return SplitLineTable->getFile(File->getDirectory(), File->getFilename(), +                                 getMD5AsBytes(File), File->getSource());  }  void DwarfUnit::addOpAddress(DIELoc &Die, const MCSymbol *Sym) { @@ -335,12 +373,11 @@ void DwarfUnit::addBlock(DIE &Die, dwarf::Attribute Attribute,    Die.addValue(DIEValueAllocator, Attribute, Block->BestForm(), Block);  } -void DwarfUnit::addSourceLine(DIE &Die, unsigned Line, StringRef File, -                              StringRef Directory) { +void DwarfUnit::addSourceLine(DIE &Die, unsigned Line, const DIFile *File) {    if (Line == 0)      return; -  unsigned FileID = getOrCreateSourceID(File, Directory); +  unsigned FileID = getOrCreateSourceID(File);    assert(FileID && "Invalid file id");    addUInt(Die, dwarf::DW_AT_decl_file, None, FileID);    addUInt(Die, dwarf::DW_AT_decl_line, None, Line); @@ -349,32 +386,31 @@ void DwarfUnit::addSourceLine(DIE &Die, unsigned Line, StringRef File,  void DwarfUnit::addSourceLine(DIE &Die, const DILocalVariable *V) {    assert(V); -  addSourceLine(Die, V->getLine(), V->getScope()->getFilename(), -                V->getScope()->getDirectory()); +  addSourceLine(Die, V->getLine(), V->getFile());  }  void DwarfUnit::addSourceLine(DIE &Die, const DIGlobalVariable *G) {    assert(G); -  addSourceLine(Die, G->getLine(), G->getFilename(), G->getDirectory()); +  addSourceLine(Die, G->getLine(), G->getFile());  }  void DwarfUnit::addSourceLine(DIE &Die, const DISubprogram *SP) {    assert(SP); -  addSourceLine(Die, SP->getLine(), SP->getFilename(), SP->getDirectory()); +  addSourceLine(Die, SP->getLine(), SP->getFile());  }  void DwarfUnit::addSourceLine(DIE &Die, const DIType *Ty) {    assert(Ty); -  addSourceLine(Die, Ty->getLine(), Ty->getFilename(), Ty->getDirectory()); +  addSourceLine(Die, Ty->getLine(), Ty->getFile());  }  void DwarfUnit::addSourceLine(DIE &Die, const DIObjCProperty *Ty) {    assert(Ty); -  addSourceLine(Die, Ty->getLine(), Ty->getFilename(), Ty->getDirectory()); +  addSourceLine(Die, Ty->getLine(), Ty->getFile());  }  /* Byref variables, in Blocks, are declared by the programmer as "SomeType @@ -727,7 +763,7 @@ DIE *DwarfUnit::getOrCreateTypeDIE(const MDNode *TyNode) {    else if (auto *STy = dyn_cast<DISubroutineType>(Ty))      constructTypeDIE(TyDIE, STy);    else if (auto *CTy = dyn_cast<DICompositeType>(Ty)) { -    if (GenerateDwarfTypeUnits && !Ty->isForwardDecl()) +    if (DD->generateTypeUnits() && !Ty->isForwardDecl())        if (MDString *TypeId = CTy->getRawIdentifier()) {          DD->addDwarfTypeUnitType(getCU(), TypeId->getString(), TyDIE, CTy);          // Skip updating the accelerator tables since this is not the full type. @@ -917,9 +953,24 @@ void DwarfUnit::constructTypeDIE(DIE &Buffer, const DICompositeType *CTy) {    case dwarf::DW_TAG_enumeration_type:      constructEnumTypeDIE(Buffer, CTy);      break; +  case dwarf::DW_TAG_variant_part:    case dwarf::DW_TAG_structure_type:    case dwarf::DW_TAG_union_type:    case dwarf::DW_TAG_class_type: { +    // Emit the discriminator for a variant part. +    DIDerivedType *Discriminator = nullptr; +    if (Tag == dwarf::DW_TAG_variant_part) { +      Discriminator = CTy->getDiscriminator(); +      if (Discriminator) { +        // DWARF says: +        //    If the variant part has a discriminant, the discriminant is +        //    represented by a separate debugging information entry which is +        //    a child of the variant part entry. +        DIE &DiscMember = constructMemberDIE(Buffer, Discriminator); +        addDIEEntry(Buffer, dwarf::DW_AT_discr, DiscMember); +      } +    } +      // Add elements to structure type.      DINodeArray Elements = CTy->getElements();      for (const auto *Element : Elements) { @@ -933,6 +984,18 @@ void DwarfUnit::constructTypeDIE(DIE &Buffer, const DICompositeType *CTy) {            addType(ElemDie, resolve(DDTy->getBaseType()), dwarf::DW_AT_friend);          } else if (DDTy->isStaticMember()) {            getOrCreateStaticMemberDIE(DDTy); +        } else if (Tag == dwarf::DW_TAG_variant_part) { +          // When emitting a variant part, wrap each member in +          // DW_TAG_variant. +          DIE &Variant = createAndAddDIE(dwarf::DW_TAG_variant, Buffer); +          if (const ConstantInt *CI = +              dyn_cast_or_null<ConstantInt>(DDTy->getDiscriminantValue())) { +            if (isUnsignedDIType(DD, resolve(Discriminator->getBaseType()))) +              addUInt(Variant, dwarf::DW_AT_discr_value, None, CI->getZExtValue()); +            else +              addSInt(Variant, dwarf::DW_AT_discr_value, None, CI->getSExtValue()); +          } +          constructMemberDIE(Variant, DDTy);          } else {            constructMemberDIE(Buffer, DDTy);          } @@ -952,6 +1015,11 @@ void DwarfUnit::constructTypeDIE(DIE &Buffer, const DICompositeType *CTy) {          if (unsigned PropertyAttributes = Property->getAttributes())            addUInt(ElemDie, dwarf::DW_AT_APPLE_property_attribute, None,                    PropertyAttributes); +      } else if (auto *Composite = dyn_cast<DICompositeType>(Element)) { +        if (Composite->getTag() == dwarf::DW_TAG_variant_part) { +          DIE &VariantPart = createAndAddDIE(Composite->getTag(), Buffer); +          constructTypeDIE(VariantPart, Composite); +        }        }      } @@ -975,6 +1043,15 @@ void DwarfUnit::constructTypeDIE(DIE &Buffer, const DICompositeType *CTy) {          Tag == dwarf::DW_TAG_structure_type || Tag == dwarf::DW_TAG_union_type)        addTemplateParams(Buffer, CTy->getTemplateParams()); +    // Add the type's non-standard calling convention. +    uint8_t CC = 0; +    if (CTy->isTypePassByValue()) +      CC = dwarf::DW_CC_pass_by_value; +    else if (CTy->isTypePassByReference()) +      CC = dwarf::DW_CC_pass_by_reference; +    if (CC) +      addUInt(Buffer, dwarf::DW_AT_calling_convention, dwarf::DW_FORM_data1, +              CC);      break;    }    default: @@ -1152,9 +1229,8 @@ bool DwarfUnit::applySubprogramDefinitionAttributes(const DISubprogram *SP,      // Look at the Decl's linkage name only if we emitted it.      if (DD->useAllLinkageNames())        DeclLinkageName = SPDecl->getLinkageName(); -    unsigned DeclID = -        getOrCreateSourceID(SPDecl->getFilename(), SPDecl->getDirectory()); -    unsigned DefID = getOrCreateSourceID(SP->getFilename(), SP->getDirectory()); +    unsigned DeclID = getOrCreateSourceID(SPDecl->getFile()); +    unsigned DefID = getOrCreateSourceID(SP->getFile());      if (DeclID != DefID)        addUInt(SPDie, dwarf::DW_AT_decl_file, None, DefID); @@ -1304,14 +1380,17 @@ void DwarfUnit::constructSubrangeDIE(DIE &Buffer, const DISubrange *SR,    // DW_AT_lower_bound and DW_AT_count attributes.    int64_t LowerBound = SR->getLowerBound();    int64_t DefaultLowerBound = getDefaultLowerBound(); -  int64_t Count = SR->getCount(); +  int64_t Count = -1; +  if (auto *CI = SR->getCount().dyn_cast<ConstantInt*>()) +    Count = CI->getSExtValue();    if (DefaultLowerBound == -1 || LowerBound != DefaultLowerBound)      addUInt(DW_Subrange, dwarf::DW_AT_lower_bound, None, LowerBound); -  if (Count != -1) -    // FIXME: An unbounded array should reference the expression that defines -    // the array. +  if (auto *CV = SR->getCount().dyn_cast<DIVariable*>()) { +    if (auto *CountVarDIE = getDIE(CV)) +      addDIEEntry(DW_Subrange, dwarf::DW_AT_count, *CountVarDIE); +  } else if (Count != -1)      addUInt(DW_Subrange, dwarf::DW_AT_count, None, Count);  } @@ -1320,16 +1399,49 @@ DIE *DwarfUnit::getIndexTyDie() {      return IndexTyDie;    // Construct an integer type to use for indexes.    IndexTyDie = &createAndAddDIE(dwarf::DW_TAG_base_type, getUnitDie()); -  addString(*IndexTyDie, dwarf::DW_AT_name, "sizetype"); +  StringRef Name = "__ARRAY_SIZE_TYPE__"; +  addString(*IndexTyDie, dwarf::DW_AT_name, Name);    addUInt(*IndexTyDie, dwarf::DW_AT_byte_size, None, sizeof(int64_t));    addUInt(*IndexTyDie, dwarf::DW_AT_encoding, dwarf::DW_FORM_data1,            dwarf::DW_ATE_unsigned); +  DD->addAccelType(Name, *IndexTyDie, /*Flags*/ 0);    return IndexTyDie;  } +/// Returns true if the vector's size differs from the sum of sizes of elements +/// the user specified.  This can occur if the vector has been rounded up to +/// fit memory alignment constraints. +static bool hasVectorBeenPadded(const DICompositeType *CTy) { +  assert(CTy && CTy->isVector() && "Composite type is not a vector"); +  const uint64_t ActualSize = CTy->getSizeInBits(); + +  // Obtain the size of each element in the vector. +  DIType *BaseTy = CTy->getBaseType().resolve(); +  assert(BaseTy && "Unknown vector element type."); +  const uint64_t ElementSize = BaseTy->getSizeInBits(); + +  // Locate the number of elements in the vector. +  const DINodeArray Elements = CTy->getElements(); +  assert(Elements.size() == 1 && +         Elements[0]->getTag() == dwarf::DW_TAG_subrange_type && +         "Invalid vector element array, expected one element of type subrange"); +  const auto Subrange = cast<DISubrange>(Elements[0]); +  const auto CI = Subrange->getCount().get<ConstantInt *>(); +  const int32_t NumVecElements = CI->getSExtValue(); + +  // Ensure we found the element count and that the actual size is wide +  // enough to contain the requested size. +  assert(ActualSize >= (NumVecElements * ElementSize) && "Invalid vector size"); +  return ActualSize != (NumVecElements * ElementSize); +} +  void DwarfUnit::constructArrayTypeDIE(DIE &Buffer, const DICompositeType *CTy) { -  if (CTy->isVector()) +  if (CTy->isVector()) {      addFlag(Buffer, dwarf::DW_AT_GNU_vector); +    if (hasVectorBeenPadded(CTy)) +      addUInt(Buffer, dwarf::DW_AT_byte_size, None, +              CTy->getSizeInBits() / CHAR_BIT); +  }    // Emit the element type.    addType(Buffer, resolve(CTy->getBaseType())); @@ -1350,6 +1462,15 @@ void DwarfUnit::constructArrayTypeDIE(DIE &Buffer, const DICompositeType *CTy) {  }  void DwarfUnit::constructEnumTypeDIE(DIE &Buffer, const DICompositeType *CTy) { +  const DIType *DTy = resolve(CTy->getBaseType()); +  bool IsUnsigned = DTy && isUnsignedDIType(DD, DTy); +  if (DTy) { +    if (DD->getDwarfVersion() >= 3) +      addType(Buffer, DTy); +    if (DD->getDwarfVersion() >= 4 && (CTy->getFlags() & DINode::FlagFixedEnum)) +      addFlag(Buffer, dwarf::DW_AT_enum_class); +  } +    DINodeArray Elements = CTy->getElements();    // Add enumerators to enumeration type. @@ -1359,16 +1480,10 @@ void DwarfUnit::constructEnumTypeDIE(DIE &Buffer, const DICompositeType *CTy) {        DIE &Enumerator = createAndAddDIE(dwarf::DW_TAG_enumerator, Buffer);        StringRef Name = Enum->getName();        addString(Enumerator, dwarf::DW_AT_name, Name); -      int64_t Value = Enum->getValue(); -      addSInt(Enumerator, dwarf::DW_AT_const_value, dwarf::DW_FORM_sdata, -              Value); +      auto Value = static_cast<uint64_t>(Enum->getValue()); +      addConstantValue(Enumerator, IsUnsigned, Value);      }    } -  const DIType *DTy = resolve(CTy->getBaseType()); -  if (DTy) { -    addType(Buffer, DTy); -    addFlag(Buffer, dwarf::DW_AT_enum_class); -  }  }  void DwarfUnit::constructContainingTypeDIEs() { @@ -1385,13 +1500,14 @@ void DwarfUnit::constructContainingTypeDIEs() {    }  } -void DwarfUnit::constructMemberDIE(DIE &Buffer, const DIDerivedType *DT) { +DIE &DwarfUnit::constructMemberDIE(DIE &Buffer, const DIDerivedType *DT) {    DIE &MemberDie = createAndAddDIE(DT->getTag(), Buffer);    StringRef Name = DT->getName();    if (!Name.empty())      addString(MemberDie, dwarf::DW_AT_name, Name); -  addType(MemberDie, resolve(DT->getBaseType())); +  if (DIType *Resolved = resolve(DT->getBaseType())) +    addType(MemberDie, Resolved);    addSourceLine(MemberDie, DT); @@ -1489,6 +1605,8 @@ void DwarfUnit::constructMemberDIE(DIE &Buffer, const DIDerivedType *DT) {    if (DT->isArtificial())      addFlag(MemberDie, dwarf::DW_AT_artificial); + +  return MemberDie;  }  DIE *DwarfUnit::getOrCreateStaticMemberDIE(const DIDerivedType *DT) { @@ -1541,18 +1659,18 @@ DIE *DwarfUnit::getOrCreateStaticMemberDIE(const DIDerivedType *DT) {  void DwarfUnit::emitCommonHeader(bool UseOffsets, dwarf::UnitType UT) {    // Emit size of content not including length itself    Asm->OutStreamer->AddComment("Length of Unit"); -  Asm->EmitInt32(getHeaderSize() + getUnitDie().getSize()); +  Asm->emitInt32(getHeaderSize() + getUnitDie().getSize());    Asm->OutStreamer->AddComment("DWARF version number");    unsigned Version = DD->getDwarfVersion(); -  Asm->EmitInt16(Version); +  Asm->emitInt16(Version);    // DWARF v5 reorders the address size and adds a unit type.    if (Version >= 5) {      Asm->OutStreamer->AddComment("DWARF Unit Type"); -    Asm->EmitInt8(UT); +    Asm->emitInt8(UT);      Asm->OutStreamer->AddComment("Address Size (in bytes)"); -    Asm->EmitInt8(Asm->MAI->getCodePointerSize()); +    Asm->emitInt8(Asm->MAI->getCodePointerSize());    }    // We share one abbreviations table across all units so it's always at the @@ -1561,14 +1679,14 @@ void DwarfUnit::emitCommonHeader(bool UseOffsets, dwarf::UnitType UT) {    Asm->OutStreamer->AddComment("Offset Into Abbrev. Section");    const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering();    if (UseOffsets) -    Asm->EmitInt32(0); +    Asm->emitInt32(0);    else      Asm->emitDwarfSymbolReference(          TLOF.getDwarfAbbrevSection()->getBeginSymbol(), false);    if (Version <= 4) {      Asm->OutStreamer->AddComment("Address Size (in bytes)"); -    Asm->EmitInt8(Asm->MAI->getCodePointerSize()); +    Asm->emitInt8(Asm->MAI->getCodePointerSize());    }  } @@ -1627,3 +1745,19 @@ const MCSymbol *DwarfUnit::getCrossSectionRelativeBaseAddress() const {      return nullptr;    return getSection()->getBeginSymbol();  } + +void DwarfUnit::addStringOffsetsStart() { +  const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering(); +  addSectionLabel(getUnitDie(), dwarf::DW_AT_str_offsets_base, +                  DU->getStringOffsetsStartSym(), +                  TLOF.getDwarfStrOffSection()->getBeginSymbol()); +} + +void DwarfUnit::addRnglistsBase() { +  assert(DD->getDwarfVersion() >= 5 && +         "DW_AT_rnglists_base requires DWARF version 5 or later"); +  const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering(); +  addSectionLabel(getUnitDie(), dwarf::DW_AT_rnglists_base, +                  DU->getRnglistsTableBaseSym(), +                  TLOF.getDwarfRnglistsSection()->getBeginSymbol()); +} | 
