summaryrefslogtreecommitdiffstats
path: root/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
diff options
context:
space:
mode:
authorZachary Turner <zturner@google.com>2018-11-20 22:13:43 +0000
committerZachary Turner <zturner@google.com>2018-11-20 22:13:43 +0000
commitc68f895702958dda96bfc297a3bc491082c5269d (patch)
tree78ce4e99f44a5ce5e82ef0e5a77ae67e494958fa /llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
parent3826566c044e94f8c1e3d26c66f28a5545aab2bc (diff)
downloadbcm5719-llvm-c68f895702958dda96bfc297a3bc491082c5269d.tar.gz
bcm5719-llvm-c68f895702958dda96bfc297a3bc491082c5269d.zip
[CodeView] Add support for ref-qualified member functions.
When you have a member function with a ref-qualifier, for example: struct Foo { void Func() &; void Func2() &&; }; clang-cl was not emitting this information. Doing so is a bit awkward, because it's not a property of the LF_MFUNCTION type, which is what you'd expect. Instead, it's a property of the this pointer which is actually an LF_POINTER. This record has an attributes bitmask on it, and our handling of this bitmask was all wrong. We had some parts of the bitmask defined incorrectly, but importantly for this bug, we didn't know about these extra 2 bits that represent the ref qualifier at all. Differential Revision: https://reviews.llvm.org/D54667 llvm-svn: 347354
Diffstat (limited to 'llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp')
-rw-r--r--llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp66
1 files changed, 45 insertions, 21 deletions
diff --git a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
index 59056b0ff5d..6d43143253e 100644
--- a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
@@ -1882,27 +1882,22 @@ TypeIndex CodeViewDebug::lowerTypeMemberFunction(const DISubroutineType *Ty,
// Lower the containing class type.
TypeIndex ClassType = getTypeIndex(ClassTy);
- SmallVector<TypeIndex, 8> ReturnAndArgTypeIndices;
- for (DITypeRef ArgTypeRef : Ty->getTypeArray())
- ReturnAndArgTypeIndices.push_back(getTypeIndex(ArgTypeRef));
+ DITypeRefArray ReturnAndArgs = Ty->getTypeArray();
+
+ unsigned Index = 0;
+ SmallVector<TypeIndex, 8> ArgTypeIndices;
+ TypeIndex ReturnTypeIndex = getTypeIndex(ReturnAndArgs[Index++]);
- // MSVC uses type none for variadic argument.
- if (ReturnAndArgTypeIndices.size() > 1 &&
- ReturnAndArgTypeIndices.back() == TypeIndex::Void()) {
- ReturnAndArgTypeIndices.back() = TypeIndex::None();
- }
- TypeIndex ReturnTypeIndex = TypeIndex::Void();
- ArrayRef<TypeIndex> ArgTypeIndices = None;
- if (!ReturnAndArgTypeIndices.empty()) {
- auto ReturnAndArgTypesRef = makeArrayRef(ReturnAndArgTypeIndices);
- ReturnTypeIndex = ReturnAndArgTypesRef.front();
- ArgTypeIndices = ReturnAndArgTypesRef.drop_front();
- }
TypeIndex ThisTypeIndex;
- if (!IsStaticMethod && !ArgTypeIndices.empty()) {
- ThisTypeIndex = ArgTypeIndices.front();
- ArgTypeIndices = ArgTypeIndices.drop_front();
- }
+ if (!IsStaticMethod && ReturnAndArgs.size() > 1)
+ ThisTypeIndex = getTypeIndexForThisPtr(ReturnAndArgs[Index++], Ty);
+
+ while (Index < ReturnAndArgs.size())
+ ArgTypeIndices.push_back(getTypeIndex(ReturnAndArgs[Index++]));
+
+ // MSVC uses type none for variadic argument.
+ if (!ArgTypeIndices.empty() && ArgTypeIndices.back() == TypeIndex::Void())
+ ArgTypeIndices.back() = TypeIndex::None();
ArgListRecord ArgListRec(TypeRecordKind::ArgList, ArgTypeIndices);
TypeIndex ArgListIndex = TypeTable.writeLeafType(ArgListRec);
@@ -1992,8 +1987,8 @@ static ClassOptions getCommonClassOptions(const DICompositeType *Ty) {
CO |= ClassOptions::Nested;
// Put the Scoped flag on function-local types. MSVC puts this flag for enum
- // type only when it has an immediate function scope. Clang never puts enums
- // inside DILexicalBlock scopes. Enum types, as generated by clang, are
+ // type only when it has an immediate function scope. Clang never puts enums
+ // inside DILexicalBlock scopes. Enum types, as generated by clang, are
// always in function, class, or file scopes.
if (Ty->getTag() == dwarf::DW_TAG_enumeration_type) {
if (ImmediateScope && isa<DISubprogram>(ImmediateScope))
@@ -2449,6 +2444,35 @@ TypeIndex CodeViewDebug::getTypeIndex(DITypeRef TypeRef, DITypeRef ClassTyRef) {
return recordTypeIndexForDINode(Ty, TI, ClassTy);
}
+codeview::TypeIndex
+CodeViewDebug::getTypeIndexForThisPtr(DITypeRef TypeRef,
+ const DISubroutineType *SubroutineTy) {
+ const DIType *Ty = TypeRef.resolve();
+
+ PointerOptions Options = PointerOptions::None;
+ if (SubroutineTy->getFlags() & DINode::DIFlags::FlagLValueReference)
+ Options = PointerOptions::LValueRefThisPointer;
+ else if (SubroutineTy->getFlags() & DINode::DIFlags::FlagRValueReference)
+ Options = PointerOptions::RValueRefThisPointer;
+
+ // Check if we've already translated this type. If there is no ref qualifier
+ // on the function then we look up this pointer type with no associated class
+ // so that the TypeIndex for the this pointer can be shared with the type
+ // index for other pointers to this class type. If there is a ref qualifier
+ // then we lookup the pointer using the subroutine as the parent type.
+ const DIType *ParentTy = nullptr;
+ if (Options != PointerOptions::None)
+ ParentTy = SubroutineTy;
+
+ auto I = TypeIndices.find({Ty, SubroutineTy});
+ if (I != TypeIndices.end())
+ return I->second;
+
+ TypeLoweringScope S(*this);
+ TypeIndex TI = lowerTypePointer(cast<DIDerivedType>(Ty), Options);
+ return recordTypeIndexForDINode(Ty, TI, SubroutineTy);
+}
+
TypeIndex CodeViewDebug::getTypeIndexForReferenceTo(DITypeRef TypeRef) {
DIType *Ty = TypeRef.resolve();
PointerRecord PR(getTypeIndex(Ty),
OpenPOWER on IntegriCloud