summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorZachary Turner <zturner@google.com>2018-11-09 16:29:19 +0000
committerZachary Turner <zturner@google.com>2018-11-09 16:29:19 +0000
commitd2ee4c6ddb065ef74d7e7e6aee7a3f8ada88ae7e (patch)
tree016c725b2e6dddb18d54a7fe0ee066d4bd88216c
parentd0c71609c52db321555672a7a827488d57b517ca (diff)
downloadbcm5719-llvm-d2ee4c6ddb065ef74d7e7e6aee7a3f8ada88ae7e.tar.gz
bcm5719-llvm-d2ee4c6ddb065ef74d7e7e6aee7a3f8ada88ae7e.zip
[NativePDB] Add support for bitfield records.
Bitfields are represented as LF_MEMBER records whose TypeIndex points to an LF_BITFIELD record that describes the bit width, bit offset, and underlying type of the bitfield. All we need to do is resolve these when resolving record types. llvm-svn: 346511
-rw-r--r--lldb/lit/SymbolFile/NativePDB/Inputs/bitfields.lldbinit5
-rw-r--r--lldb/lit/SymbolFile/NativePDB/bitfields.cpp61
-rw-r--r--lldb/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.cpp24
3 files changed, 86 insertions, 4 deletions
diff --git a/lldb/lit/SymbolFile/NativePDB/Inputs/bitfields.lldbinit b/lldb/lit/SymbolFile/NativePDB/Inputs/bitfields.lldbinit
new file mode 100644
index 00000000000..cf06c494e67
--- /dev/null
+++ b/lldb/lit/SymbolFile/NativePDB/Inputs/bitfields.lldbinit
@@ -0,0 +1,5 @@
+settings set auto-one-line-summaries false
+
+target variable -T TheStruct
+
+target modules dump ast
diff --git a/lldb/lit/SymbolFile/NativePDB/bitfields.cpp b/lldb/lit/SymbolFile/NativePDB/bitfields.cpp
new file mode 100644
index 00000000000..7f896ba8fbf
--- /dev/null
+++ b/lldb/lit/SymbolFile/NativePDB/bitfields.cpp
@@ -0,0 +1,61 @@
+// clang-format off
+// REQUIRES: lld
+
+// Test various interesting cases for AST reconstruction.
+// RUN: clang-cl /Z7 /GS- /GR- /std:c++latest -Xclang -fkeep-static-consts /c /Fo%t.obj -- %s
+// RUN: lld-link /DEBUG /nodefaultlib /entry:main /OUT:%t.exe /PDB:%t.pdb -- %t.obj
+// RUN: env LLDB_USE_NATIVE_PDB_READER=1 lldb -f %t.exe -s \
+// RUN: %p/Inputs/bitfields.lldbinit 2>&1 | FileCheck %s
+
+// Test trivial versions of each tag type.
+struct Struct {
+ int A : 5 = 6;
+ int B : 7 = 8;
+ unsigned C : 3 = 2;
+ unsigned D : 15 = 12345;
+ char E : 1 = 0;
+ char F : 2 = 1;
+ char G : 3 = 2;
+ // H should be at offset 0 of a new byte.
+ char H : 3 = 3;
+};
+
+constexpr Struct TheStruct;
+
+
+int main(int argc, char **argv) {
+ return TheStruct.A;
+}
+
+// CHECK: (lldb) target variable -T TheStruct
+// CHECK: (const Struct) TheStruct = {
+// CHECK: (int:5) A = 6
+// CHECK: (int:7) B = 8
+// CHECK: (unsigned int:3) C = 2
+// CHECK: (unsigned int:15) D = 12345
+// CHECK: (char:1) E = '\0'
+// CHECK: (char:2) F = '\x01'
+// CHECK: (char:3) G = '\x02'
+// CHECK: (char:3) H = '\x03'
+// CHECK: }
+//
+// CHECK: target modules dump ast
+// CHECK: Dumping clang ast for 1 modules.
+// CHECK: TranslationUnitDecl {{.*}}
+// CHECK: |-CXXRecordDecl {{.*}} struct Struct definition
+// CHECK: | |-FieldDecl {{.*}} A 'int'
+// CHECK: | | `-IntegerLiteral {{.*}} 'int' 5
+// CHECK: | |-FieldDecl {{.*}} B 'int'
+// CHECK: | | `-IntegerLiteral {{.*}} 'int' 7
+// CHECK: | |-FieldDecl {{.*}} C 'unsigned int'
+// CHECK: | | `-IntegerLiteral {{.*}} 'int' 3
+// CHECK: | |-FieldDecl {{.*}} D 'unsigned int'
+// CHECK: | | `-IntegerLiteral {{.*}} 'int' 15
+// CHECK: | |-FieldDecl {{.*}} E 'char'
+// CHECK: | | `-IntegerLiteral {{.*}} 'int' 1
+// CHECK: | |-FieldDecl {{.*}} F 'char'
+// CHECK: | | `-IntegerLiteral {{.*}} 'int' 2
+// CHECK: | |-FieldDecl {{.*}} G 'char'
+// CHECK: | | `-IntegerLiteral {{.*}} 'int' 3
+// CHECK: | `-FieldDecl {{.*}} H 'char'
+// CHECK: | `-IntegerLiteral {{.*}} 'int' 3
diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.cpp b/lldb/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.cpp
index 432ba9ecea7..dfca59d9881 100644
--- a/lldb/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.cpp
+++ b/lldb/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.cpp
@@ -123,17 +123,33 @@ Error UdtRecordCompleter::visitKnownMember(CVMemberRecord &cvr,
Error UdtRecordCompleter::visitKnownMember(CVMemberRecord &cvr,
DataMemberRecord &data_member) {
- TypeSP member_type = m_symbol_file.GetOrCreateType(data_member.Type);
- CompilerType complete_member_type = member_type->GetFullCompilerType();
+ uint64_t offset = data_member.FieldOffset * 8;
+ uint32_t bitfield_width = 0;
+
+ TypeSP member_type;
+ TpiStream &tpi = m_symbol_file.m_index->tpi();
+ TypeIndex ti(data_member.Type);
+ if (!ti.isSimple()) {
+ CVType cvt = tpi.getType(ti);
+ if (cvt.kind() == LF_BITFIELD) {
+ BitFieldRecord bfr;
+ llvm::cantFail(TypeDeserializer::deserializeAs<BitFieldRecord>(cvt, bfr));
+ offset += bfr.BitOffset;
+ bitfield_width = bfr.BitSize;
+ ti = bfr.Type;
+ }
+ }
+ member_type = m_symbol_file.GetOrCreateType(ti);
+ CompilerType complete_member_type = member_type->GetFullCompilerType();
lldb::AccessType access = TranslateMemberAccess(data_member.getAccess());
clang::FieldDecl *decl = ClangASTContext::AddFieldToRecordType(
- m_derived_ct, data_member.Name, complete_member_type, access, 0);
+ m_derived_ct, data_member.Name, complete_member_type, access,
+ bitfield_width);
// FIXME: Add a PdbSymUid namespace for field list members and update
// the m_uid_to_decl map with this decl.
- uint64_t offset = data_member.FieldOffset * 8;
m_layout.field_offsets.insert(std::make_pair(decl, offset));
return Error::success();
OpenPOWER on IntegriCloud