diff options
Diffstat (limited to 'llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp')
-rw-r--r-- | llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp | 52 |
1 files changed, 42 insertions, 10 deletions
diff --git a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp index 9a3e32f..058a0e8 100644 --- a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp @@ -1268,6 +1268,7 @@ TypeIndex CodeViewDebug::lowerType(const DIType *Ty, const DIType *ClassTy) { return lowerTypePointer(cast<DIDerivedType>(Ty)); case dwarf::DW_TAG_ptr_to_member_type: return lowerTypeMemberPointer(cast<DIDerivedType>(Ty)); + case dwarf::DW_TAG_restrict_type: case dwarf::DW_TAG_const_type: case dwarf::DW_TAG_volatile_type: // TODO: add support for DW_TAG_atomic_type here @@ -1452,12 +1453,13 @@ TypeIndex CodeViewDebug::lowerTypeBasic(const DIBasicType *Ty) { return TypeIndex(STK); } -TypeIndex CodeViewDebug::lowerTypePointer(const DIDerivedType *Ty) { +TypeIndex CodeViewDebug::lowerTypePointer(const DIDerivedType *Ty, + PointerOptions PO) { TypeIndex PointeeTI = getTypeIndex(Ty->getBaseType()); - // Pointers to simple types can use SimpleTypeMode, rather than having a - // dedicated pointer type record. - if (PointeeTI.isSimple() && + // Pointers to simple types without any options can use SimpleTypeMode, rather + // than having a dedicated pointer type record. + if (PointeeTI.isSimple() && PO == PointerOptions::None && PointeeTI.getSimpleMode() == SimpleTypeMode::Direct && Ty->getTag() == dwarf::DW_TAG_pointer_type) { SimpleTypeMode Mode = Ty->getSizeInBits() == 64 @@ -1481,10 +1483,7 @@ TypeIndex CodeViewDebug::lowerTypePointer(const DIDerivedType *Ty) { PM = PointerMode::RValueReference; break; } - // FIXME: MSVC folds qualifiers into PointerOptions in the context of a method - // 'this' pointer, but not normal contexts. Figure out what we're supposed to - // do. - PointerOptions PO = PointerOptions::None; + PointerRecord PR(PointeeTI, PK, PM, PO, Ty->getSizeInBits() / 8); return TypeTable.writeLeafType(PR); } @@ -1522,7 +1521,8 @@ translatePtrToMemberRep(unsigned SizeInBytes, bool IsPMF, unsigned Flags) { llvm_unreachable("invalid ptr to member representation"); } -TypeIndex CodeViewDebug::lowerTypeMemberPointer(const DIDerivedType *Ty) { +TypeIndex CodeViewDebug::lowerTypeMemberPointer(const DIDerivedType *Ty, + PointerOptions PO) { assert(Ty->getTag() == dwarf::DW_TAG_ptr_to_member_type); TypeIndex ClassTI = getTypeIndex(Ty->getClassType()); TypeIndex PointeeTI = getTypeIndex(Ty->getBaseType(), Ty->getClassType()); @@ -1531,7 +1531,7 @@ TypeIndex CodeViewDebug::lowerTypeMemberPointer(const DIDerivedType *Ty) { bool IsPMF = isa<DISubroutineType>(Ty->getBaseType()); PointerMode PM = IsPMF ? PointerMode::PointerToMemberFunction : PointerMode::PointerToDataMember; - PointerOptions PO = PointerOptions::None; // FIXME + assert(Ty->getSizeInBits() / 8 <= 0xff && "pointer size too big"); uint8_t SizeInBytes = Ty->getSizeInBits() / 8; MemberPointerInfo MPI( @@ -1556,6 +1556,7 @@ static CallingConvention dwarfCCToCodeView(unsigned DwarfCC) { TypeIndex CodeViewDebug::lowerTypeModifier(const DIDerivedType *Ty) { ModifierOptions Mods = ModifierOptions::None; + PointerOptions PO = PointerOptions::None; bool IsModifier = true; const DIType *BaseTy = Ty; while (IsModifier && BaseTy) { @@ -1563,9 +1564,16 @@ TypeIndex CodeViewDebug::lowerTypeModifier(const DIDerivedType *Ty) { switch (BaseTy->getTag()) { case dwarf::DW_TAG_const_type: Mods |= ModifierOptions::Const; + PO |= PointerOptions::Const; break; case dwarf::DW_TAG_volatile_type: Mods |= ModifierOptions::Volatile; + PO |= PointerOptions::Volatile; + break; + case dwarf::DW_TAG_restrict_type: + // Only pointer types be marked with __restrict. There is no known flag + // for __restrict in LF_MODIFIER records. + PO |= PointerOptions::Restrict; break; default: IsModifier = false; @@ -1574,7 +1582,31 @@ TypeIndex CodeViewDebug::lowerTypeModifier(const DIDerivedType *Ty) { if (IsModifier) BaseTy = cast<DIDerivedType>(BaseTy)->getBaseType().resolve(); } + + // Check if the inner type will use an LF_POINTER record. If so, the + // qualifiers will go in the LF_POINTER record. This comes up for types like + // 'int *const' and 'int *__restrict', not the more common cases like 'const + // char *'. + if (BaseTy) { + switch (BaseTy->getTag()) { + case dwarf::DW_TAG_pointer_type: + case dwarf::DW_TAG_reference_type: + case dwarf::DW_TAG_rvalue_reference_type: + return lowerTypePointer(cast<DIDerivedType>(BaseTy), PO); + case dwarf::DW_TAG_ptr_to_member_type: + return lowerTypeMemberPointer(cast<DIDerivedType>(BaseTy), PO); + default: + break; + } + } + TypeIndex ModifiedTI = getTypeIndex(BaseTy); + + // Return the base type index if there aren't any modifiers. For example, the + // metadata could contain restrict wrappers around non-pointer types. + if (Mods == ModifierOptions::None) + return ModifiedTI; + ModifierRecord MR(ModifiedTI, Mods); return TypeTable.writeLeafType(MR); } |