summaryrefslogtreecommitdiffstats
path: root/llvm/lib/CodeGen
diff options
context:
space:
mode:
authorReid Kleckner <rnk@google.com>2018-02-27 22:08:15 +0000
committerReid Kleckner <rnk@google.com>2018-02-27 22:08:15 +0000
commit3acdc6773444b0dea84a69e99024e07ebabc0c98 (patch)
tree179123044f6994a794b3c6f7b2bf89ec2c5a458b /llvm/lib/CodeGen
parent10ab103a58441518780ab8ecdcd7f167aa2f6cbe (diff)
downloadbcm5719-llvm-3acdc6773444b0dea84a69e99024e07ebabc0c98.tar.gz
bcm5719-llvm-3acdc6773444b0dea84a69e99024e07ebabc0c98.zip
[CodeView] Lower __restrict and other pointer qualifiers correctly
Qualifiers on a pointer or reference type may apply to either the pointee or the pointer itself. Consider 'const char *' and 'char * const'. In the first example, the pointee data may not be modified without casts, and in the second example, the pointer may not be updated to point to new data. In the general case, qualifiers are applied to types with LF_MODIFIER records, which support the usual const and volatile qualifiers as well as the __unaligned extension qualifier. However, LF_POINTER records, which are used for pointers, references, and member pointers, have flags for qualifiers applying to the *pointer*. In fact, this is the only way to represent the restrict qualifier, which can only apply to pointers, and cannot qualify regular data types. This patch causes LLVM to correctly fold 'const' and 'volatile' pointer qualifiers into the pointer record, as well as adding support for '__restrict' qualifiers in the same place. Based on a patch from Aaron Smith Differential Revision: https://reviews.llvm.org/D43060 llvm-svn: 326260
Diffstat (limited to 'llvm/lib/CodeGen')
-rw-r--r--llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp52
-rw-r--r--llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h8
2 files changed, 48 insertions, 12 deletions
diff --git a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
index 9a3e32f9417..058a0e89c5f 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);
}
diff --git a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h
index 69e93640d7e..62fc4eaba7e 100644
--- a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h
+++ b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h
@@ -283,8 +283,12 @@ class LLVM_LIBRARY_VISIBILITY CodeViewDebug : public DebugHandlerBase {
codeview::TypeIndex lowerTypeAlias(const DIDerivedType *Ty);
codeview::TypeIndex lowerTypeArray(const DICompositeType *Ty);
codeview::TypeIndex lowerTypeBasic(const DIBasicType *Ty);
- codeview::TypeIndex lowerTypePointer(const DIDerivedType *Ty);
- codeview::TypeIndex lowerTypeMemberPointer(const DIDerivedType *Ty);
+ codeview::TypeIndex lowerTypePointer(
+ const DIDerivedType *Ty,
+ codeview::PointerOptions PO = codeview::PointerOptions::None);
+ codeview::TypeIndex lowerTypeMemberPointer(
+ const DIDerivedType *Ty,
+ codeview::PointerOptions PO = codeview::PointerOptions::None);
codeview::TypeIndex lowerTypeModifier(const DIDerivedType *Ty);
codeview::TypeIndex lowerTypeFunction(const DISubroutineType *Ty);
codeview::TypeIndex lowerTypeVFTableShape(const DIDerivedType *Ty);
OpenPOWER on IntegriCloud