diff options
author | Kate Stone <katherine.stone@apple.com> | 2016-09-06 20:57:50 +0000 |
---|---|---|
committer | Kate Stone <katherine.stone@apple.com> | 2016-09-06 20:57:50 +0000 |
commit | b9c1b51e45b845debb76d8658edabca70ca56079 (patch) | |
tree | dfcb5a13ef2b014202340f47036da383eaee74aa /lldb/source/Symbol | |
parent | d5aa73376966339caad04013510626ec2e42c760 (diff) | |
download | bcm5719-llvm-b9c1b51e45b845debb76d8658edabca70ca56079.tar.gz bcm5719-llvm-b9c1b51e45b845debb76d8658edabca70ca56079.zip |
*** This commit represents a complete reformatting of the LLDB source code
*** to conform to clang-format’s LLVM style. This kind of mass change has
*** two obvious implications:
Firstly, merging this particular commit into a downstream fork may be a huge
effort. Alternatively, it may be worth merging all changes up to this commit,
performing the same reformatting operation locally, and then discarding the
merge for this particular commit. The commands used to accomplish this
reformatting were as follows (with current working directory as the root of
the repository):
find . \( -iname "*.c" -or -iname "*.cpp" -or -iname "*.h" -or -iname "*.mm" \) -exec clang-format -i {} +
find . -iname "*.py" -exec autopep8 --in-place --aggressive --aggressive {} + ;
The version of clang-format used was 3.9.0, and autopep8 was 1.2.4.
Secondly, “blame” style tools will generally point to this commit instead of
a meaningful prior commit. There are alternatives available that will attempt
to look through this change and find the appropriate prior commit. YMMV.
llvm-svn: 280751
Diffstat (limited to 'lldb/source/Symbol')
37 files changed, 24766 insertions, 28024 deletions
diff --git a/lldb/source/Symbol/ArmUnwindInfo.cpp b/lldb/source/Symbol/ArmUnwindInfo.cpp index 95207cbe320..19951498c1d 100644 --- a/lldb/source/Symbol/ArmUnwindInfo.cpp +++ b/lldb/source/Symbol/ArmUnwindInfo.cpp @@ -9,13 +9,13 @@ #include <vector> +#include "Utility/ARM_DWARF_Registers.h" #include "lldb/Core/Module.h" #include "lldb/Core/Section.h" #include "lldb/Host/Endian.h" #include "lldb/Symbol/ArmUnwindInfo.h" #include "lldb/Symbol/SymbolVendor.h" #include "lldb/Symbol/UnwindPlan.h" -#include "Utility/ARM_DWARF_Registers.h" /* * Unwind information reader and parser for the ARM exception handling ABI @@ -31,415 +31,341 @@ using namespace lldb; using namespace lldb_private; // Converts a prel31 avlue to lldb::addr_t with sign extension -static addr_t -Prel31ToAddr(uint32_t prel31) -{ - addr_t res = prel31; - if (prel31 & (1<<30)) - res |= 0xffffffff80000000ULL; - return res; +static addr_t Prel31ToAddr(uint32_t prel31) { + addr_t res = prel31; + if (prel31 & (1 << 30)) + res |= 0xffffffff80000000ULL; + return res; } -ArmUnwindInfo::ArmExidxEntry::ArmExidxEntry(uint32_t f, lldb::addr_t a, uint32_t d) : - file_address(f), address(a), data(d) -{ -} +ArmUnwindInfo::ArmExidxEntry::ArmExidxEntry(uint32_t f, lldb::addr_t a, + uint32_t d) + : file_address(f), address(a), data(d) {} -bool -ArmUnwindInfo::ArmExidxEntry::operator<(const ArmExidxEntry& other) const -{ - return address < other.address; +bool ArmUnwindInfo::ArmExidxEntry::operator<(const ArmExidxEntry &other) const { + return address < other.address; } -ArmUnwindInfo::ArmUnwindInfo(const ObjectFile& objfile, - SectionSP& arm_exidx, - SectionSP& arm_extab) : - m_byte_order(objfile.GetByteOrder()), - m_arm_exidx_sp(arm_exidx), - m_arm_extab_sp(arm_extab) -{ - objfile.ReadSectionData(arm_exidx.get(), m_arm_exidx_data); - objfile.ReadSectionData(arm_extab.get(), m_arm_extab_data); - - addr_t exidx_base_addr = m_arm_exidx_sp->GetFileAddress(); - - offset_t offset = 0; - while (m_arm_exidx_data.ValidOffset(offset)) - { - lldb::addr_t file_addr = exidx_base_addr + offset; - lldb::addr_t addr = exidx_base_addr + - (addr_t)offset + - Prel31ToAddr(m_arm_exidx_data.GetU32(&offset)); - uint32_t data = m_arm_exidx_data.GetU32(&offset); - m_exidx_entries.emplace_back(file_addr, addr, data); - } - - // Sort the entries in the exidx section. The entries should be sorted inside the section but - // some old compiler isn't sorted them. - std::sort(m_exidx_entries.begin(), m_exidx_entries.end()); +ArmUnwindInfo::ArmUnwindInfo(const ObjectFile &objfile, SectionSP &arm_exidx, + SectionSP &arm_extab) + : m_byte_order(objfile.GetByteOrder()), m_arm_exidx_sp(arm_exidx), + m_arm_extab_sp(arm_extab) { + objfile.ReadSectionData(arm_exidx.get(), m_arm_exidx_data); + objfile.ReadSectionData(arm_extab.get(), m_arm_extab_data); + + addr_t exidx_base_addr = m_arm_exidx_sp->GetFileAddress(); + + offset_t offset = 0; + while (m_arm_exidx_data.ValidOffset(offset)) { + lldb::addr_t file_addr = exidx_base_addr + offset; + lldb::addr_t addr = exidx_base_addr + (addr_t)offset + + Prel31ToAddr(m_arm_exidx_data.GetU32(&offset)); + uint32_t data = m_arm_exidx_data.GetU32(&offset); + m_exidx_entries.emplace_back(file_addr, addr, data); + } + + // Sort the entries in the exidx section. The entries should be sorted inside + // the section but + // some old compiler isn't sorted them. + std::sort(m_exidx_entries.begin(), m_exidx_entries.end()); } -ArmUnwindInfo::~ArmUnwindInfo() -{ -} +ArmUnwindInfo::~ArmUnwindInfo() {} // Read a byte from the unwind instruction stream with the given offset. -// Custom function is required because have to red in order of significance within their containing +// Custom function is required because have to red in order of significance +// within their containing // word (most significant byte first) and in increasing word address order. -uint8_t -ArmUnwindInfo::GetByteAtOffset(const uint32_t* data, uint16_t offset) const -{ - uint32_t value = data[offset / 4]; - if (m_byte_order != endian::InlHostByteOrder()) - value = llvm::ByteSwap_32(value); - return (value >> ((3 - (offset % 4)) * 8)) & 0xff; +uint8_t ArmUnwindInfo::GetByteAtOffset(const uint32_t *data, + uint16_t offset) const { + uint32_t value = data[offset / 4]; + if (m_byte_order != endian::InlHostByteOrder()) + value = llvm::ByteSwap_32(value); + return (value >> ((3 - (offset % 4)) * 8)) & 0xff; } -uint64_t -ArmUnwindInfo::GetULEB128(const uint32_t* data, uint16_t& offset, uint16_t max_offset) const -{ - uint64_t result = 0; - uint8_t shift = 0; - while (offset < max_offset) - { - uint8_t byte = GetByteAtOffset(data, offset++); - result |= (uint64_t)(byte & 0x7f) << shift; - if ((byte & 0x80) == 0) - break; - shift += 7; - } - return result; +uint64_t ArmUnwindInfo::GetULEB128(const uint32_t *data, uint16_t &offset, + uint16_t max_offset) const { + uint64_t result = 0; + uint8_t shift = 0; + while (offset < max_offset) { + uint8_t byte = GetByteAtOffset(data, offset++); + result |= (uint64_t)(byte & 0x7f) << shift; + if ((byte & 0x80) == 0) + break; + shift += 7; + } + return result; } -bool -ArmUnwindInfo::GetUnwindPlan(Target &target, const Address& addr, UnwindPlan& unwind_plan) -{ - const uint32_t* data = (const uint32_t*)GetExceptionHandlingTableEntry(addr); - if (data == nullptr) - return false; // No unwind information for the function - - if (data[0] == 0x1) - return false; // EXIDX_CANTUNWIND - - uint16_t byte_count = 0; - uint16_t byte_offset = 0; - if (data[0] & 0x80000000) - { - switch ((data[0] >> 24) & 0x0f) - { - case 0: - byte_count = 4; - byte_offset = 1; - break; - case 1: - case 2: - byte_count = 4 * ((data[0] >> 16) & 0xff) + 4; - byte_offset = 2; - break; - default: - // Unhandled personality routine index - return false; - } - } - else - { - byte_count = 4 * ((data[1] >> 24) & 0xff) + 8; - byte_offset = 5; +bool ArmUnwindInfo::GetUnwindPlan(Target &target, const Address &addr, + UnwindPlan &unwind_plan) { + const uint32_t *data = (const uint32_t *)GetExceptionHandlingTableEntry(addr); + if (data == nullptr) + return false; // No unwind information for the function + + if (data[0] == 0x1) + return false; // EXIDX_CANTUNWIND + + uint16_t byte_count = 0; + uint16_t byte_offset = 0; + if (data[0] & 0x80000000) { + switch ((data[0] >> 24) & 0x0f) { + case 0: + byte_count = 4; + byte_offset = 1; + break; + case 1: + case 2: + byte_count = 4 * ((data[0] >> 16) & 0xff) + 4; + byte_offset = 2; + break; + default: + // Unhandled personality routine index + return false; } - - uint8_t vsp_reg = dwarf_sp; - int32_t vsp = 0; - std::vector<std::pair<uint32_t, int32_t>> register_offsets; // register -> (offset from vsp_reg) - - while (byte_offset < byte_count) - { - uint8_t byte1 = GetByteAtOffset(data, byte_offset++); - if ((byte1&0xc0) == 0x00) - { - // 00xxxxxx - // vsp = vsp + (xxxxxx << 2) + 4. Covers range 0x04-0x100 inclusive - vsp += ((byte1 & 0x3f) << 2) + 4; - } - else if ((byte1&0xc0) == 0x40) - { - // 01xxxxxx - // vsp = vsp – (xxxxxx << 2) - 4. Covers range 0x04-0x100 inclusive - vsp -= ((byte1 & 0x3f) << 2) + 4; - } - else if ((byte1&0xf0) == 0x80) - { - if (byte_offset >= byte_count) - return false; - - uint8_t byte2 = GetByteAtOffset(data, byte_offset++); - if (byte1 == 0x80 && byte2 == 0) - { - // 10000000 00000000 - // Refuse to unwind (for example, out of a cleanup) (see remark a) - return false; - } - else - { - // 1000iiii iiiiiiii (i not all 0) - // Pop up to 12 integer registers under masks {r15-r12}, {r11-r4} (see remark b) - uint16_t regs = ((byte1&0x0f) << 8) | byte2; - for (uint8_t i = 0; i < 12; ++i) - { - if (regs & (1<<i)) - { - register_offsets.emplace_back(dwarf_r4 + i, vsp); - vsp += 4; - } - } - } - } - else if ((byte1&0xff) == 0x9d) - { - // 10011101 - // Reserved as prefix for ARM register to register moves - return false; - } - else if ((byte1&0xff) == 0x9f) - { - // 10011111 - // Reserved as prefix for Intel Wireless MMX register to register moves - return false; - } - else if ((byte1&0xf0) == 0x90) - { - // 1001nnnn (nnnn != 13,15) - // Set vsp = r[nnnn] - vsp_reg = dwarf_r0 + (byte1&0x0f); - } - else if ((byte1&0xf8) == 0xa0) - { - // 10100nnn - // Pop r4-r[4+nnn] - uint8_t n = byte1&0x7; - for (uint8_t i = 0; i <= n; ++i) - { - register_offsets.emplace_back(dwarf_r4 + i, vsp); - vsp += 4; - } - } - else if ((byte1&0xf8) == 0xa8) - { - // 10101nnn - // Pop r4-r[4+nnn], r14 - uint8_t n = byte1&0x7; - for (uint8_t i = 0; i <= n; ++i) - { - register_offsets.emplace_back(dwarf_r4 + i, vsp); - vsp += 4; - } - - register_offsets.emplace_back(dwarf_lr, vsp); - vsp += 4; - } - else if ((byte1&0xff) == 0xb0) - { - // 10110000 - // Finish (see remark c) - break; - } - else if ((byte1&0xff) == 0xb1) - { - if (byte_offset >= byte_count) - return false; - - uint8_t byte2 = GetByteAtOffset(data, byte_offset++); - if ((byte2&0xff) == 0x00) - { - // 10110001 00000000 - // Spare (see remark f) - return false; - } - else if ((byte2&0xf0) == 0x00) - { - // 10110001 0000iiii (i not all 0) - // Pop integer registers under mask {r3, r2, r1, r0} - for (uint8_t i = 0; i < 4; ++i) - { - if (byte2 & (1<<i)) - { - register_offsets.emplace_back(dwarf_r0 + i, vsp); - vsp += 4; - } - } - } - else - { - // 10110001 xxxxyyyy - // Spare (xxxx != 0000) - return false; - } - } - else if ((byte1&0xff) == 0xb2) - { - // 10110010 uleb128 - // vsp = vsp + 0x204+ (uleb128 << 2) - uint64_t uleb128 = GetULEB128(data, byte_offset, byte_count); - vsp += 0x204 + (uleb128 << 2); - } - else if ((byte1&0xff) == 0xb3) - { - // 10110011 sssscccc - // Pop VFP double-precision registers D[ssss]-D[ssss+cccc] saved (as if) by FSTMFDX (see remark d) - if (byte_offset >= byte_count) - return false; - - uint8_t byte2 = GetByteAtOffset(data, byte_offset++); - uint8_t s = (byte2&0xf0) >> 4; - uint8_t c = (byte2&0x0f) >> 0; - for (uint8_t i = 0; i <= c; ++i) - { - register_offsets.emplace_back(dwarf_d0 + s + i, vsp); - vsp += 8; - } + } else { + byte_count = 4 * ((data[1] >> 24) & 0xff) + 8; + byte_offset = 5; + } + + uint8_t vsp_reg = dwarf_sp; + int32_t vsp = 0; + std::vector<std::pair<uint32_t, int32_t>> + register_offsets; // register -> (offset from vsp_reg) + + while (byte_offset < byte_count) { + uint8_t byte1 = GetByteAtOffset(data, byte_offset++); + if ((byte1 & 0xc0) == 0x00) { + // 00xxxxxx + // vsp = vsp + (xxxxxx << 2) + 4. Covers range 0x04-0x100 inclusive + vsp += ((byte1 & 0x3f) << 2) + 4; + } else if ((byte1 & 0xc0) == 0x40) { + // 01xxxxxx + // vsp = vsp – (xxxxxx << 2) - 4. Covers range 0x04-0x100 inclusive + vsp -= ((byte1 & 0x3f) << 2) + 4; + } else if ((byte1 & 0xf0) == 0x80) { + if (byte_offset >= byte_count) + return false; + + uint8_t byte2 = GetByteAtOffset(data, byte_offset++); + if (byte1 == 0x80 && byte2 == 0) { + // 10000000 00000000 + // Refuse to unwind (for example, out of a cleanup) (see remark a) + return false; + } else { + // 1000iiii iiiiiiii (i not all 0) + // Pop up to 12 integer registers under masks {r15-r12}, {r11-r4} (see + // remark b) + uint16_t regs = ((byte1 & 0x0f) << 8) | byte2; + for (uint8_t i = 0; i < 12; ++i) { + if (regs & (1 << i)) { + register_offsets.emplace_back(dwarf_r4 + i, vsp); vsp += 4; + } } - else if ((byte1&0xfc) == 0xb4) - { - // 101101nn - // Spare (was Pop FPA) - return false; - } - else if ((byte1&0xf8) == 0xb8) - { - // 10111nnn - // Pop VFP double-precision registers D[8]-D[8+nnn] saved (as if) by FSTMFDX (see remark d) - uint8_t n = byte1&0x07; - for (uint8_t i = 0; i <= n; ++i) - { - register_offsets.emplace_back(dwarf_d8 + i, vsp); - vsp += 8; - } + } + } else if ((byte1 & 0xff) == 0x9d) { + // 10011101 + // Reserved as prefix for ARM register to register moves + return false; + } else if ((byte1 & 0xff) == 0x9f) { + // 10011111 + // Reserved as prefix for Intel Wireless MMX register to register moves + return false; + } else if ((byte1 & 0xf0) == 0x90) { + // 1001nnnn (nnnn != 13,15) + // Set vsp = r[nnnn] + vsp_reg = dwarf_r0 + (byte1 & 0x0f); + } else if ((byte1 & 0xf8) == 0xa0) { + // 10100nnn + // Pop r4-r[4+nnn] + uint8_t n = byte1 & 0x7; + for (uint8_t i = 0; i <= n; ++i) { + register_offsets.emplace_back(dwarf_r4 + i, vsp); + vsp += 4; + } + } else if ((byte1 & 0xf8) == 0xa8) { + // 10101nnn + // Pop r4-r[4+nnn], r14 + uint8_t n = byte1 & 0x7; + for (uint8_t i = 0; i <= n; ++i) { + register_offsets.emplace_back(dwarf_r4 + i, vsp); + vsp += 4; + } + + register_offsets.emplace_back(dwarf_lr, vsp); + vsp += 4; + } else if ((byte1 & 0xff) == 0xb0) { + // 10110000 + // Finish (see remark c) + break; + } else if ((byte1 & 0xff) == 0xb1) { + if (byte_offset >= byte_count) + return false; + + uint8_t byte2 = GetByteAtOffset(data, byte_offset++); + if ((byte2 & 0xff) == 0x00) { + // 10110001 00000000 + // Spare (see remark f) + return false; + } else if ((byte2 & 0xf0) == 0x00) { + // 10110001 0000iiii (i not all 0) + // Pop integer registers under mask {r3, r2, r1, r0} + for (uint8_t i = 0; i < 4; ++i) { + if (byte2 & (1 << i)) { + register_offsets.emplace_back(dwarf_r0 + i, vsp); vsp += 4; + } } - else if ((byte1&0xf8) == 0xc0) - { - // 11000nnn (nnn != 6,7) - // Intel Wireless MMX pop wR[10]-wR[10+nnn] - - // 11000110 sssscccc - // Intel Wireless MMX pop wR[ssss]-wR[ssss+cccc] (see remark e) - - // 11000111 00000000 - // Spare - - // 11000111 0000iiii - // Intel Wireless MMX pop wCGR registers under mask {wCGR3,2,1,0} - - // 11000111 xxxxyyyy - // Spare (xxxx != 0000) - - return false; - } - else if ((byte1&0xff) == 0xc8) - { - // 11001000 sssscccc - // Pop VFP double precision registers D[16+ssss]-D[16+ssss+cccc] saved (as if) by FSTMFDD (see remarks d,e) - if (byte_offset >= byte_count) - return false; - - uint8_t byte2 = GetByteAtOffset(data, byte_offset++); - uint8_t s = (byte2&0xf0) >> 4; - uint8_t c = (byte2&0x0f) >> 0; - for (uint8_t i = 0; i <= c; ++i) - { - register_offsets.emplace_back(dwarf_d16 + s + i, vsp); - vsp += 8; - } - } - else if ((byte1&0xff) == 0xc9) - { - // 11001001 sssscccc - // Pop VFP double precision registers D[ssss]-D[ssss+cccc] saved (as if) by FSTMFDD (see remark d) - if (byte_offset >= byte_count) - return false; - - uint8_t byte2 = GetByteAtOffset(data, byte_offset++); - uint8_t s = (byte2&0xf0) >> 4; - uint8_t c = (byte2&0x0f) >> 0; - for (uint8_t i = 0; i <= c; ++i) - { - register_offsets.emplace_back(dwarf_d0 + s + i, vsp); - vsp += 8; - } - } - else if ((byte1&0xf8) == 0xc8) - { - // 11001yyy - // Spare (yyy != 000, 001) - return false; - } - else if ((byte1&0xf8) == 0xc0) - { - // 11010nnn - // Pop VFP double-precision registers D[8]-D[8+nnn] saved (as if) by FSTMFDD (see remark d) - uint8_t n = byte1&0x07; - for (uint8_t i = 0; i <= n; ++i) - { - register_offsets.emplace_back(dwarf_d8 + i, vsp); - vsp += 8; - } - } - else if ((byte1&0xc0) == 0xc0) - { - // 11xxxyyy Spare (xxx != 000, 001, 010) - return false; - } - else - { - return false; - } - } - - UnwindPlan::RowSP row = std::make_shared<UnwindPlan::Row>(); - row->SetOffset(0); - row->GetCFAValue().SetIsRegisterPlusOffset(vsp_reg, vsp); - - bool have_location_for_pc = false; - for (const auto& offset : register_offsets) - { - have_location_for_pc |= offset.first == dwarf_pc; - row->SetRegisterLocationToAtCFAPlusOffset(offset.first, offset.second - vsp, true); - } - - if (!have_location_for_pc) - { - UnwindPlan::Row::RegisterLocation lr_location; - if (row->GetRegisterInfo(dwarf_lr, lr_location)) - row->SetRegisterInfo(dwarf_pc, lr_location); - else - row->SetRegisterLocationToRegister(dwarf_pc, dwarf_lr, false); + } else { + // 10110001 xxxxyyyy + // Spare (xxxx != 0000) + return false; + } + } else if ((byte1 & 0xff) == 0xb2) { + // 10110010 uleb128 + // vsp = vsp + 0x204+ (uleb128 << 2) + uint64_t uleb128 = GetULEB128(data, byte_offset, byte_count); + vsp += 0x204 + (uleb128 << 2); + } else if ((byte1 & 0xff) == 0xb3) { + // 10110011 sssscccc + // Pop VFP double-precision registers D[ssss]-D[ssss+cccc] saved (as if) + // by FSTMFDX (see remark d) + if (byte_offset >= byte_count) + return false; + + uint8_t byte2 = GetByteAtOffset(data, byte_offset++); + uint8_t s = (byte2 & 0xf0) >> 4; + uint8_t c = (byte2 & 0x0f) >> 0; + for (uint8_t i = 0; i <= c; ++i) { + register_offsets.emplace_back(dwarf_d0 + s + i, vsp); + vsp += 8; + } + vsp += 4; + } else if ((byte1 & 0xfc) == 0xb4) { + // 101101nn + // Spare (was Pop FPA) + return false; + } else if ((byte1 & 0xf8) == 0xb8) { + // 10111nnn + // Pop VFP double-precision registers D[8]-D[8+nnn] saved (as if) by + // FSTMFDX (see remark d) + uint8_t n = byte1 & 0x07; + for (uint8_t i = 0; i <= n; ++i) { + register_offsets.emplace_back(dwarf_d8 + i, vsp); + vsp += 8; + } + vsp += 4; + } else if ((byte1 & 0xf8) == 0xc0) { + // 11000nnn (nnn != 6,7) + // Intel Wireless MMX pop wR[10]-wR[10+nnn] + + // 11000110 sssscccc + // Intel Wireless MMX pop wR[ssss]-wR[ssss+cccc] (see remark e) + + // 11000111 00000000 + // Spare + + // 11000111 0000iiii + // Intel Wireless MMX pop wCGR registers under mask {wCGR3,2,1,0} + + // 11000111 xxxxyyyy + // Spare (xxxx != 0000) + + return false; + } else if ((byte1 & 0xff) == 0xc8) { + // 11001000 sssscccc + // Pop VFP double precision registers D[16+ssss]-D[16+ssss+cccc] saved (as + // if) by FSTMFDD (see remarks d,e) + if (byte_offset >= byte_count) + return false; + + uint8_t byte2 = GetByteAtOffset(data, byte_offset++); + uint8_t s = (byte2 & 0xf0) >> 4; + uint8_t c = (byte2 & 0x0f) >> 0; + for (uint8_t i = 0; i <= c; ++i) { + register_offsets.emplace_back(dwarf_d16 + s + i, vsp); + vsp += 8; + } + } else if ((byte1 & 0xff) == 0xc9) { + // 11001001 sssscccc + // Pop VFP double precision registers D[ssss]-D[ssss+cccc] saved (as if) + // by FSTMFDD (see remark d) + if (byte_offset >= byte_count) + return false; + + uint8_t byte2 = GetByteAtOffset(data, byte_offset++); + uint8_t s = (byte2 & 0xf0) >> 4; + uint8_t c = (byte2 & 0x0f) >> 0; + for (uint8_t i = 0; i <= c; ++i) { + register_offsets.emplace_back(dwarf_d0 + s + i, vsp); + vsp += 8; + } + } else if ((byte1 & 0xf8) == 0xc8) { + // 11001yyy + // Spare (yyy != 000, 001) + return false; + } else if ((byte1 & 0xf8) == 0xc0) { + // 11010nnn + // Pop VFP double-precision registers D[8]-D[8+nnn] saved (as if) by + // FSTMFDD (see remark d) + uint8_t n = byte1 & 0x07; + for (uint8_t i = 0; i <= n; ++i) { + register_offsets.emplace_back(dwarf_d8 + i, vsp); + vsp += 8; + } + } else if ((byte1 & 0xc0) == 0xc0) { + // 11xxxyyy Spare (xxx != 000, 001, 010) + return false; + } else { + return false; } + } + + UnwindPlan::RowSP row = std::make_shared<UnwindPlan::Row>(); + row->SetOffset(0); + row->GetCFAValue().SetIsRegisterPlusOffset(vsp_reg, vsp); + + bool have_location_for_pc = false; + for (const auto &offset : register_offsets) { + have_location_for_pc |= offset.first == dwarf_pc; + row->SetRegisterLocationToAtCFAPlusOffset(offset.first, offset.second - vsp, + true); + } + + if (!have_location_for_pc) { + UnwindPlan::Row::RegisterLocation lr_location; + if (row->GetRegisterInfo(dwarf_lr, lr_location)) + row->SetRegisterInfo(dwarf_pc, lr_location); + else + row->SetRegisterLocationToRegister(dwarf_pc, dwarf_lr, false); + } - unwind_plan.AppendRow(row); - unwind_plan.SetSourceName ("ARM.exidx unwind info"); - unwind_plan.SetSourcedFromCompiler (eLazyBoolYes); - unwind_plan.SetUnwindPlanValidAtAllInstructions (eLazyBoolNo); - unwind_plan.SetRegisterKind (eRegisterKindDWARF); + unwind_plan.AppendRow(row); + unwind_plan.SetSourceName("ARM.exidx unwind info"); + unwind_plan.SetSourcedFromCompiler(eLazyBoolYes); + unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolNo); + unwind_plan.SetRegisterKind(eRegisterKindDWARF); - return true; + return true; } -const uint8_t* -ArmUnwindInfo::GetExceptionHandlingTableEntry(const Address& addr) -{ - auto it = std::upper_bound(m_exidx_entries.begin(), - m_exidx_entries.end(), - ArmExidxEntry{0, addr.GetFileAddress(), 0}); - if (it == m_exidx_entries.begin()) - return nullptr; - --it; +const uint8_t * +ArmUnwindInfo::GetExceptionHandlingTableEntry(const Address &addr) { + auto it = std::upper_bound(m_exidx_entries.begin(), m_exidx_entries.end(), + ArmExidxEntry{0, addr.GetFileAddress(), 0}); + if (it == m_exidx_entries.begin()) + return nullptr; + --it; - if (it->data == 0x1) - return nullptr; // EXIDX_CANTUNWIND + if (it->data == 0x1) + return nullptr; // EXIDX_CANTUNWIND - if (it->data & 0x80000000) - return (const uint8_t*)&it->data; + if (it->data & 0x80000000) + return (const uint8_t *)&it->data; - addr_t data_file_addr = it->file_address + 4 + Prel31ToAddr(it->data); - return m_arm_extab_data.GetDataStart() + (data_file_addr - m_arm_extab_sp->GetFileAddress()); + addr_t data_file_addr = it->file_address + 4 + Prel31ToAddr(it->data); + return m_arm_extab_data.GetDataStart() + + (data_file_addr - m_arm_extab_sp->GetFileAddress()); } diff --git a/lldb/source/Symbol/Block.cpp b/lldb/source/Symbol/Block.cpp index 9d50c5cb7c9..6c4c28d1f7f 100644 --- a/lldb/source/Symbol/Block.cpp +++ b/lldb/source/Symbol/Block.cpp @@ -20,628 +20,486 @@ using namespace lldb; using namespace lldb_private; -Block::Block(lldb::user_id_t uid) : - UserID(uid), - m_parent_scope (nullptr), - m_children (), - m_ranges (), - m_inlineInfoSP (), - m_variable_list_sp (), - m_parsed_block_info (false), - m_parsed_block_variables (false), - m_parsed_child_blocks (false) -{ -} - -Block::~Block () -{ -} - -void -Block::GetDescription(Stream *s, Function *function, lldb::DescriptionLevel level, Target *target) const -{ - *s << "id = " << ((const UserID&)*this); - - size_t num_ranges = m_ranges.GetSize(); - if (num_ranges > 0) - { - - addr_t base_addr = LLDB_INVALID_ADDRESS; - if (target) - base_addr = function->GetAddressRange().GetBaseAddress().GetLoadAddress(target); - if (base_addr == LLDB_INVALID_ADDRESS) - base_addr = function->GetAddressRange().GetBaseAddress().GetFileAddress(); - - s->Printf(", range%s = ", num_ranges > 1 ? "s" : ""); - for (size_t i=0; i<num_ranges; ++i) - { - const Range &range = m_ranges.GetEntryRef(i); - s->AddressRange(base_addr + range.GetRangeBase(), base_addr + range.GetRangeEnd(), 4); - } - } - - if (m_inlineInfoSP.get() != nullptr) - { - bool show_fullpaths = (level == eDescriptionLevelVerbose); - m_inlineInfoSP->Dump(s, show_fullpaths); +Block::Block(lldb::user_id_t uid) + : UserID(uid), m_parent_scope(nullptr), m_children(), m_ranges(), + m_inlineInfoSP(), m_variable_list_sp(), m_parsed_block_info(false), + m_parsed_block_variables(false), m_parsed_child_blocks(false) {} + +Block::~Block() {} + +void Block::GetDescription(Stream *s, Function *function, + lldb::DescriptionLevel level, Target *target) const { + *s << "id = " << ((const UserID &)*this); + + size_t num_ranges = m_ranges.GetSize(); + if (num_ranges > 0) { + + addr_t base_addr = LLDB_INVALID_ADDRESS; + if (target) + base_addr = + function->GetAddressRange().GetBaseAddress().GetLoadAddress(target); + if (base_addr == LLDB_INVALID_ADDRESS) + base_addr = function->GetAddressRange().GetBaseAddress().GetFileAddress(); + + s->Printf(", range%s = ", num_ranges > 1 ? "s" : ""); + for (size_t i = 0; i < num_ranges; ++i) { + const Range &range = m_ranges.GetEntryRef(i); + s->AddressRange(base_addr + range.GetRangeBase(), + base_addr + range.GetRangeEnd(), 4); } -} - -void -Block::Dump(Stream *s, addr_t base_addr, int32_t depth, bool show_context) const -{ - if (depth < 0) - { - Block *parent = GetParent(); - if (parent) - { - // We have a depth that is less than zero, print our parent blocks - // first - parent->Dump(s, base_addr, depth + 1, show_context); - } + } + + if (m_inlineInfoSP.get() != nullptr) { + bool show_fullpaths = (level == eDescriptionLevelVerbose); + m_inlineInfoSP->Dump(s, show_fullpaths); + } +} + +void Block::Dump(Stream *s, addr_t base_addr, int32_t depth, + bool show_context) const { + if (depth < 0) { + Block *parent = GetParent(); + if (parent) { + // We have a depth that is less than zero, print our parent blocks + // first + parent->Dump(s, base_addr, depth + 1, show_context); } + } + + s->Printf("%p: ", static_cast<const void *>(this)); + s->Indent(); + *s << "Block" << static_cast<const UserID &>(*this); + const Block *parent_block = GetParent(); + if (parent_block) { + s->Printf(", parent = {0x%8.8" PRIx64 "}", parent_block->GetID()); + } + if (m_inlineInfoSP.get() != nullptr) { + bool show_fullpaths = false; + m_inlineInfoSP->Dump(s, show_fullpaths); + } + + if (!m_ranges.IsEmpty()) { + *s << ", ranges ="; - s->Printf("%p: ", static_cast<const void*>(this)); - s->Indent(); - *s << "Block" << static_cast<const UserID&>(*this); - const Block* parent_block = GetParent(); - if (parent_block) - { - s->Printf(", parent = {0x%8.8" PRIx64 "}", parent_block->GetID()); - } - if (m_inlineInfoSP.get() != nullptr) - { - bool show_fullpaths = false; - m_inlineInfoSP->Dump(s, show_fullpaths); - } - - if (!m_ranges.IsEmpty()) - { - *s << ", ranges ="; - - size_t num_ranges = m_ranges.GetSize(); - for (size_t i=0; i<num_ranges; ++i) - { - const Range &range = m_ranges.GetEntryRef(i); - if (parent_block != nullptr && parent_block->Contains(range) == false) - *s << '!'; - else - *s << ' '; - s->AddressRange(base_addr + range.GetRangeBase(), base_addr + range.GetRangeEnd(), 4); - } + size_t num_ranges = m_ranges.GetSize(); + for (size_t i = 0; i < num_ranges; ++i) { + const Range &range = m_ranges.GetEntryRef(i); + if (parent_block != nullptr && parent_block->Contains(range) == false) + *s << '!'; + else + *s << ' '; + s->AddressRange(base_addr + range.GetRangeBase(), + base_addr + range.GetRangeEnd(), 4); } - s->EOL(); + } + s->EOL(); - if (depth > 0) - { - s->IndentMore(); + if (depth > 0) { + s->IndentMore(); - if (m_variable_list_sp.get()) - { - m_variable_list_sp->Dump(s, show_context); - } - - collection::const_iterator pos, end = m_children.end(); - for (pos = m_children.begin(); pos != end; ++pos) - (*pos)->Dump(s, base_addr, depth - 1, show_context); - - s->IndentLess(); + if (m_variable_list_sp.get()) { + m_variable_list_sp->Dump(s, show_context); } -} - - -Block * -Block::FindBlockByID (user_id_t block_id) -{ - if (block_id == GetID()) - return this; - - Block *matching_block = nullptr; collection::const_iterator pos, end = m_children.end(); for (pos = m_children.begin(); pos != end; ++pos) - { - matching_block = (*pos)->FindBlockByID (block_id); - if (matching_block) - break; - } - return matching_block; -} - -void -Block::CalculateSymbolContext (SymbolContext* sc) -{ - if (m_parent_scope) - m_parent_scope->CalculateSymbolContext(sc); - sc->block = this; -} + (*pos)->Dump(s, base_addr, depth - 1, show_context); -lldb::ModuleSP -Block::CalculateSymbolContextModule () -{ - if (m_parent_scope) - return m_parent_scope->CalculateSymbolContextModule (); - return lldb::ModuleSP(); + s->IndentLess(); + } } -CompileUnit * -Block::CalculateSymbolContextCompileUnit () -{ - if (m_parent_scope) - return m_parent_scope->CalculateSymbolContextCompileUnit (); - return nullptr; -} +Block *Block::FindBlockByID(user_id_t block_id) { + if (block_id == GetID()) + return this; -Function * -Block::CalculateSymbolContextFunction () -{ - if (m_parent_scope) - return m_parent_scope->CalculateSymbolContextFunction (); - return nullptr; + Block *matching_block = nullptr; + collection::const_iterator pos, end = m_children.end(); + for (pos = m_children.begin(); pos != end; ++pos) { + matching_block = (*pos)->FindBlockByID(block_id); + if (matching_block) + break; + } + return matching_block; } -Block * -Block::CalculateSymbolContextBlock () -{ - return this; +void Block::CalculateSymbolContext(SymbolContext *sc) { + if (m_parent_scope) + m_parent_scope->CalculateSymbolContext(sc); + sc->block = this; } -void -Block::DumpSymbolContext(Stream *s) -{ - Function *function = CalculateSymbolContextFunction(); - if (function) - function->DumpSymbolContext(s); - s->Printf(", Block{0x%8.8" PRIx64 "}", GetID()); -} - -void -Block::DumpAddressRanges (Stream *s, lldb::addr_t base_addr) -{ - if (!m_ranges.IsEmpty()) - { - size_t num_ranges = m_ranges.GetSize(); - for (size_t i=0; i<num_ranges; ++i) - { - const Range &range = m_ranges.GetEntryRef(i); - s->AddressRange(base_addr + range.GetRangeBase(), base_addr + range.GetRangeEnd(), 4); - } - } +lldb::ModuleSP Block::CalculateSymbolContextModule() { + if (m_parent_scope) + return m_parent_scope->CalculateSymbolContextModule(); + return lldb::ModuleSP(); } -bool -Block::Contains (addr_t range_offset) const -{ - return m_ranges.FindEntryThatContains(range_offset) != nullptr; -} - -bool -Block::Contains (const Block *block) const -{ - if (this == block) - return false; // This block doesn't contain itself... - - // Walk the parent chain for "block" and see if any if them match this block - const Block *block_parent; - for (block_parent = block->GetParent(); - block_parent != nullptr; - block_parent = block_parent->GetParent()) - { - if (this == block_parent) - return true; // One of the parents of "block" is this object! - } - return false; +CompileUnit *Block::CalculateSymbolContextCompileUnit() { + if (m_parent_scope) + return m_parent_scope->CalculateSymbolContextCompileUnit(); + return nullptr; } -bool -Block::Contains (const Range& range) const -{ - return m_ranges.FindEntryThatContains (range) != nullptr; +Function *Block::CalculateSymbolContextFunction() { + if (m_parent_scope) + return m_parent_scope->CalculateSymbolContextFunction(); + return nullptr; } -Block * -Block::GetParent () const -{ - if (m_parent_scope) - return m_parent_scope->CalculateSymbolContextBlock(); - return nullptr; -} +Block *Block::CalculateSymbolContextBlock() { return this; } -Block * -Block::GetContainingInlinedBlock () -{ - if (GetInlinedFunctionInfo()) - return this; - return GetInlinedParent (); +void Block::DumpSymbolContext(Stream *s) { + Function *function = CalculateSymbolContextFunction(); + if (function) + function->DumpSymbolContext(s); + s->Printf(", Block{0x%8.8" PRIx64 "}", GetID()); } -Block * -Block::GetInlinedParent () -{ - Block *parent_block = GetParent (); - if (parent_block) - { - if (parent_block->GetInlinedFunctionInfo()) - return parent_block; - else - return parent_block->GetInlinedParent(); +void Block::DumpAddressRanges(Stream *s, lldb::addr_t base_addr) { + if (!m_ranges.IsEmpty()) { + size_t num_ranges = m_ranges.GetSize(); + for (size_t i = 0; i < num_ranges; ++i) { + const Range &range = m_ranges.GetEntryRef(i); + s->AddressRange(base_addr + range.GetRangeBase(), + base_addr + range.GetRangeEnd(), 4); } - return nullptr; + } } - -bool -Block::GetRangeContainingOffset (const addr_t offset, Range &range) -{ - const Range *range_ptr = m_ranges.FindEntryThatContains (offset); - if (range_ptr) - { - range = *range_ptr; - return true; - } - range.Clear(); - return false; +bool Block::Contains(addr_t range_offset) const { + return m_ranges.FindEntryThatContains(range_offset) != nullptr; } +bool Block::Contains(const Block *block) const { + if (this == block) + return false; // This block doesn't contain itself... -bool -Block::GetRangeContainingAddress (const Address& addr, AddressRange &range) -{ - Function *function = CalculateSymbolContextFunction(); - if (function) - { - const AddressRange &func_range = function->GetAddressRange(); - if (addr.GetSection() == func_range.GetBaseAddress().GetSection()) - { - const addr_t addr_offset = addr.GetOffset(); - const addr_t func_offset = func_range.GetBaseAddress().GetOffset(); - if (addr_offset >= func_offset && addr_offset < func_offset + func_range.GetByteSize()) - { - addr_t offset = addr_offset - func_offset; - - const Range *range_ptr = m_ranges.FindEntryThatContains (offset); - - if (range_ptr) - { - range.GetBaseAddress() = func_range.GetBaseAddress(); - range.GetBaseAddress().SetOffset(func_offset + range_ptr->GetRangeBase()); - range.SetByteSize(range_ptr->GetByteSize()); - return true; - } - } - } - } - range.Clear(); - return false; + // Walk the parent chain for "block" and see if any if them match this block + const Block *block_parent; + for (block_parent = block->GetParent(); block_parent != nullptr; + block_parent = block_parent->GetParent()) { + if (this == block_parent) + return true; // One of the parents of "block" is this object! + } + return false; } -bool -Block::GetRangeContainingLoadAddress (lldb::addr_t load_addr, Target &target, AddressRange &range) -{ - Address load_address; - load_address.SetLoadAddress(load_addr, &target); - AddressRange containing_range; - return GetRangeContainingAddress(load_address, containing_range); +bool Block::Contains(const Range &range) const { + return m_ranges.FindEntryThatContains(range) != nullptr; } +Block *Block::GetParent() const { + if (m_parent_scope) + return m_parent_scope->CalculateSymbolContextBlock(); + return nullptr; +} -uint32_t -Block::GetRangeIndexContainingAddress (const Address& addr) -{ - Function *function = CalculateSymbolContextFunction(); - if (function) - { - const AddressRange &func_range = function->GetAddressRange(); - if (addr.GetSection() == func_range.GetBaseAddress().GetSection()) - { - const addr_t addr_offset = addr.GetOffset(); - const addr_t func_offset = func_range.GetBaseAddress().GetOffset(); - if (addr_offset >= func_offset && addr_offset < func_offset + func_range.GetByteSize()) - { - addr_t offset = addr_offset - func_offset; - return m_ranges.FindEntryIndexThatContains (offset); - } +Block *Block::GetContainingInlinedBlock() { + if (GetInlinedFunctionInfo()) + return this; + return GetInlinedParent(); +} + +Block *Block::GetInlinedParent() { + Block *parent_block = GetParent(); + if (parent_block) { + if (parent_block->GetInlinedFunctionInfo()) + return parent_block; + else + return parent_block->GetInlinedParent(); + } + return nullptr; +} + +bool Block::GetRangeContainingOffset(const addr_t offset, Range &range) { + const Range *range_ptr = m_ranges.FindEntryThatContains(offset); + if (range_ptr) { + range = *range_ptr; + return true; + } + range.Clear(); + return false; +} + +bool Block::GetRangeContainingAddress(const Address &addr, + AddressRange &range) { + Function *function = CalculateSymbolContextFunction(); + if (function) { + const AddressRange &func_range = function->GetAddressRange(); + if (addr.GetSection() == func_range.GetBaseAddress().GetSection()) { + const addr_t addr_offset = addr.GetOffset(); + const addr_t func_offset = func_range.GetBaseAddress().GetOffset(); + if (addr_offset >= func_offset && + addr_offset < func_offset + func_range.GetByteSize()) { + addr_t offset = addr_offset - func_offset; + + const Range *range_ptr = m_ranges.FindEntryThatContains(offset); + + if (range_ptr) { + range.GetBaseAddress() = func_range.GetBaseAddress(); + range.GetBaseAddress().SetOffset(func_offset + + range_ptr->GetRangeBase()); + range.SetByteSize(range_ptr->GetByteSize()); + return true; } + } } - return UINT32_MAX; -} - -bool -Block::GetRangeAtIndex (uint32_t range_idx, AddressRange &range) -{ - if (range_idx < m_ranges.GetSize()) - { - Function *function = CalculateSymbolContextFunction(); - if (function) - { - const Range &vm_range = m_ranges.GetEntryRef(range_idx); - range.GetBaseAddress() = function->GetAddressRange().GetBaseAddress(); - range.GetBaseAddress().Slide(vm_range.GetRangeBase ()); - range.SetByteSize (vm_range.GetByteSize()); - return true; - } + } + range.Clear(); + return false; +} + +bool Block::GetRangeContainingLoadAddress(lldb::addr_t load_addr, + Target &target, AddressRange &range) { + Address load_address; + load_address.SetLoadAddress(load_addr, &target); + AddressRange containing_range; + return GetRangeContainingAddress(load_address, containing_range); +} + +uint32_t Block::GetRangeIndexContainingAddress(const Address &addr) { + Function *function = CalculateSymbolContextFunction(); + if (function) { + const AddressRange &func_range = function->GetAddressRange(); + if (addr.GetSection() == func_range.GetBaseAddress().GetSection()) { + const addr_t addr_offset = addr.GetOffset(); + const addr_t func_offset = func_range.GetBaseAddress().GetOffset(); + if (addr_offset >= func_offset && + addr_offset < func_offset + func_range.GetByteSize()) { + addr_t offset = addr_offset - func_offset; + return m_ranges.FindEntryIndexThatContains(offset); + } } - return false; + } + return UINT32_MAX; } -bool -Block::GetStartAddress (Address &addr) -{ - if (m_ranges.IsEmpty()) - return false; - +bool Block::GetRangeAtIndex(uint32_t range_idx, AddressRange &range) { + if (range_idx < m_ranges.GetSize()) { Function *function = CalculateSymbolContextFunction(); - if (function) - { - addr = function->GetAddressRange().GetBaseAddress(); - addr.Slide(m_ranges.GetEntryRef(0).GetRangeBase ()); - return true; + if (function) { + const Range &vm_range = m_ranges.GetEntryRef(range_idx); + range.GetBaseAddress() = function->GetAddressRange().GetBaseAddress(); + range.GetBaseAddress().Slide(vm_range.GetRangeBase()); + range.SetByteSize(vm_range.GetByteSize()); + return true; } - return false; + } + return false; } -void -Block::FinalizeRanges () -{ - m_ranges.Sort(); - m_ranges.CombineConsecutiveRanges (); -} - -void -Block::AddRange (const Range& range) -{ - Block *parent_block = GetParent (); - if (parent_block && !parent_block->Contains(range)) - { - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_SYMBOLS)); - if (log) - { - ModuleSP module_sp (m_parent_scope->CalculateSymbolContextModule()); - Function *function = m_parent_scope->CalculateSymbolContextFunction(); - const addr_t function_file_addr = function->GetAddressRange().GetBaseAddress().GetFileAddress(); - const addr_t block_start_addr = function_file_addr + range.GetRangeBase (); - const addr_t block_end_addr = function_file_addr + range.GetRangeEnd (); - Type *func_type = function->GetType(); - - const Declaration &func_decl = func_type->GetDeclaration(); - if (func_decl.GetLine()) - { - log->Printf ("warning: %s:%u block {0x%8.8" PRIx64 "} has range[%u] [0x%" PRIx64 " - 0x%" PRIx64 ") which is not contained in parent block {0x%8.8" PRIx64 "} in function {0x%8.8" PRIx64 "} from %s", - func_decl.GetFile().GetPath().c_str(), - func_decl.GetLine(), - GetID(), - (uint32_t)m_ranges.GetSize(), - block_start_addr, - block_end_addr, - parent_block->GetID(), - function->GetID(), - module_sp->GetFileSpec().GetPath().c_str()); - } - else - { - log->Printf ("warning: block {0x%8.8" PRIx64 "} has range[%u] [0x%" PRIx64 " - 0x%" PRIx64 ") which is not contained in parent block {0x%8.8" PRIx64 "} in function {0x%8.8" PRIx64 "} from %s", - GetID(), - (uint32_t)m_ranges.GetSize(), - block_start_addr, - block_end_addr, - parent_block->GetID(), - function->GetID(), - module_sp->GetFileSpec().GetPath().c_str()); - } - } - parent_block->AddRange (range); +bool Block::GetStartAddress(Address &addr) { + if (m_ranges.IsEmpty()) + return false; + + Function *function = CalculateSymbolContextFunction(); + if (function) { + addr = function->GetAddressRange().GetBaseAddress(); + addr.Slide(m_ranges.GetEntryRef(0).GetRangeBase()); + return true; + } + return false; +} + +void Block::FinalizeRanges() { + m_ranges.Sort(); + m_ranges.CombineConsecutiveRanges(); +} + +void Block::AddRange(const Range &range) { + Block *parent_block = GetParent(); + if (parent_block && !parent_block->Contains(range)) { + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_SYMBOLS)); + if (log) { + ModuleSP module_sp(m_parent_scope->CalculateSymbolContextModule()); + Function *function = m_parent_scope->CalculateSymbolContextFunction(); + const addr_t function_file_addr = + function->GetAddressRange().GetBaseAddress().GetFileAddress(); + const addr_t block_start_addr = function_file_addr + range.GetRangeBase(); + const addr_t block_end_addr = function_file_addr + range.GetRangeEnd(); + Type *func_type = function->GetType(); + + const Declaration &func_decl = func_type->GetDeclaration(); + if (func_decl.GetLine()) { + log->Printf("warning: %s:%u block {0x%8.8" PRIx64 + "} has range[%u] [0x%" PRIx64 " - 0x%" PRIx64 + ") which is not contained in parent block {0x%8.8" PRIx64 + "} in function {0x%8.8" PRIx64 "} from %s", + func_decl.GetFile().GetPath().c_str(), func_decl.GetLine(), + GetID(), (uint32_t)m_ranges.GetSize(), block_start_addr, + block_end_addr, parent_block->GetID(), function->GetID(), + module_sp->GetFileSpec().GetPath().c_str()); + } else { + log->Printf("warning: block {0x%8.8" PRIx64 + "} has range[%u] [0x%" PRIx64 " - 0x%" PRIx64 + ") which is not contained in parent block {0x%8.8" PRIx64 + "} in function {0x%8.8" PRIx64 "} from %s", + GetID(), (uint32_t)m_ranges.GetSize(), block_start_addr, + block_end_addr, parent_block->GetID(), function->GetID(), + module_sp->GetFileSpec().GetPath().c_str()); + } } - m_ranges.Append(range); + parent_block->AddRange(range); + } + m_ranges.Append(range); } // Return the current number of bytes that this object occupies in memory -size_t -Block::MemorySize() const -{ - size_t mem_size = sizeof(Block) + m_ranges.GetSize() * sizeof(Range); - if (m_inlineInfoSP.get()) - mem_size += m_inlineInfoSP->MemorySize(); - if (m_variable_list_sp.get()) - mem_size += m_variable_list_sp->MemorySize(); - return mem_size; - -} - -void -Block::AddChild(const BlockSP &child_block_sp) -{ - if (child_block_sp) - { - child_block_sp->SetParentScope (this); - m_children.push_back (child_block_sp); +size_t Block::MemorySize() const { + size_t mem_size = sizeof(Block) + m_ranges.GetSize() * sizeof(Range); + if (m_inlineInfoSP.get()) + mem_size += m_inlineInfoSP->MemorySize(); + if (m_variable_list_sp.get()) + mem_size += m_variable_list_sp->MemorySize(); + return mem_size; +} + +void Block::AddChild(const BlockSP &child_block_sp) { + if (child_block_sp) { + child_block_sp->SetParentScope(this); + m_children.push_back(child_block_sp); + } +} + +void Block::SetInlinedFunctionInfo(const char *name, const char *mangled, + const Declaration *decl_ptr, + const Declaration *call_decl_ptr) { + m_inlineInfoSP.reset( + new InlineFunctionInfo(name, mangled, decl_ptr, call_decl_ptr)); +} + +VariableListSP Block::GetBlockVariableList(bool can_create) { + if (m_parsed_block_variables == false) { + if (m_variable_list_sp.get() == nullptr && can_create) { + m_parsed_block_variables = true; + SymbolContext sc; + CalculateSymbolContext(&sc); + assert(sc.module_sp); + sc.module_sp->GetSymbolVendor()->ParseVariablesForContext(sc); } + } + return m_variable_list_sp; } -void -Block::SetInlinedFunctionInfo(const char *name, const char *mangled, const Declaration *decl_ptr, const Declaration *call_decl_ptr) -{ - m_inlineInfoSP.reset(new InlineFunctionInfo(name, mangled, decl_ptr, call_decl_ptr)); -} +uint32_t +Block::AppendBlockVariables(bool can_create, bool get_child_block_variables, + bool stop_if_child_block_is_inlined_function, + const std::function<bool(Variable *)> &filter, + VariableList *variable_list) { + uint32_t num_variables_added = 0; + VariableList *block_var_list = GetBlockVariableList(can_create).get(); + if (block_var_list) { + for (size_t i = 0; i < block_var_list->GetSize(); ++i) { + VariableSP variable = block_var_list->GetVariableAtIndex(i); + if (filter(variable.get())) { + num_variables_added++; + variable_list->AddVariable(variable); + } + } + } + if (get_child_block_variables) { + collection::const_iterator pos, end = m_children.end(); + for (pos = m_children.begin(); pos != end; ++pos) { + Block *child_block = pos->get(); + if (stop_if_child_block_is_inlined_function == false || + child_block->GetInlinedFunctionInfo() == nullptr) { + num_variables_added += child_block->AppendBlockVariables( + can_create, get_child_block_variables, + stop_if_child_block_is_inlined_function, filter, variable_list); + } + } + } + return num_variables_added; +} + +uint32_t Block::AppendVariables(bool can_create, bool get_parent_variables, + bool stop_if_block_is_inlined_function, + const std::function<bool(Variable *)> &filter, + VariableList *variable_list) { + uint32_t num_variables_added = 0; + VariableListSP variable_list_sp(GetBlockVariableList(can_create)); + + bool is_inlined_function = GetInlinedFunctionInfo() != nullptr; + if (variable_list_sp) { + for (size_t i = 0; i < variable_list_sp->GetSize(); ++i) { + VariableSP variable = variable_list_sp->GetVariableAtIndex(i); + if (filter(variable.get())) { + num_variables_added++; + variable_list->AddVariable(variable); + } + } + } + if (get_parent_variables) { + if (stop_if_block_is_inlined_function && is_inlined_function) + return num_variables_added; -VariableListSP -Block::GetBlockVariableList (bool can_create) -{ - if (m_parsed_block_variables == false) - { - if (m_variable_list_sp.get() == nullptr && can_create) - { - m_parsed_block_variables = true; - SymbolContext sc; - CalculateSymbolContext(&sc); - assert(sc.module_sp); - sc.module_sp->GetSymbolVendor()->ParseVariablesForContext(sc); - } - } - return m_variable_list_sp; + Block *parent_block = GetParent(); + if (parent_block) + num_variables_added += parent_block->AppendVariables( + can_create, get_parent_variables, stop_if_block_is_inlined_function, + filter, variable_list); + } + return num_variables_added; } -uint32_t -Block::AppendBlockVariables (bool can_create, - bool get_child_block_variables, - bool stop_if_child_block_is_inlined_function, - const std::function<bool(Variable*)>& filter, - VariableList *variable_list) -{ - uint32_t num_variables_added = 0; - VariableList *block_var_list = GetBlockVariableList (can_create).get(); - if (block_var_list) - { - for (size_t i = 0; i < block_var_list->GetSize(); ++i) - { - VariableSP variable = block_var_list->GetVariableAtIndex(i); - if (filter(variable.get())) - { - num_variables_added++; - variable_list->AddVariable(variable); - } - } - } +CompilerDeclContext Block::GetDeclContext() { + ModuleSP module_sp = CalculateSymbolContextModule(); - if (get_child_block_variables) - { - collection::const_iterator pos, end = m_children.end(); - for (pos = m_children.begin(); pos != end; ++pos) - { - Block *child_block = pos->get(); - if (stop_if_child_block_is_inlined_function == false || - child_block->GetInlinedFunctionInfo() == nullptr) - { - num_variables_added += child_block->AppendBlockVariables (can_create, - get_child_block_variables, - stop_if_child_block_is_inlined_function, - filter, - variable_list); - } - } - } - return num_variables_added; -} + if (module_sp) { + SymbolVendor *sym_vendor = module_sp->GetSymbolVendor(); -uint32_t -Block::AppendVariables -( - bool can_create, - bool get_parent_variables, - bool stop_if_block_is_inlined_function, - const std::function<bool(Variable*)>& filter, - VariableList *variable_list -) -{ - uint32_t num_variables_added = 0; - VariableListSP variable_list_sp(GetBlockVariableList(can_create)); - - bool is_inlined_function = GetInlinedFunctionInfo() != nullptr; - if (variable_list_sp) - { - for (size_t i = 0; i < variable_list_sp->GetSize(); ++i) - { - VariableSP variable = variable_list_sp->GetVariableAtIndex(i); - if (filter(variable.get())) - { - num_variables_added++; - variable_list->AddVariable(variable); - } - } - } + if (sym_vendor) { + SymbolFile *sym_file = sym_vendor->GetSymbolFile(); - if (get_parent_variables) - { - if (stop_if_block_is_inlined_function && is_inlined_function) - return num_variables_added; - - Block* parent_block = GetParent(); - if (parent_block) - num_variables_added += parent_block->AppendVariables(can_create, - get_parent_variables, - stop_if_block_is_inlined_function, - filter, - variable_list); - } - return num_variables_added; -} - -CompilerDeclContext -Block::GetDeclContext() -{ - ModuleSP module_sp = CalculateSymbolContextModule (); - - if (module_sp) - { - SymbolVendor *sym_vendor = module_sp->GetSymbolVendor(); - - if (sym_vendor) - { - SymbolFile *sym_file = sym_vendor->GetSymbolFile(); - - if (sym_file) - return sym_file->GetDeclContextForUID (GetID()); - } - } - return CompilerDeclContext(); -} - -void -Block::SetBlockInfoHasBeenParsed (bool b, bool set_children) -{ - m_parsed_block_info = b; - if (set_children) - { - m_parsed_child_blocks = true; - collection::const_iterator pos, end = m_children.end(); - for (pos = m_children.begin(); pos != end; ++pos) - (*pos)->SetBlockInfoHasBeenParsed (b, true); + if (sym_file) + return sym_file->GetDeclContextForUID(GetID()); } + } + return CompilerDeclContext(); } -void -Block::SetDidParseVariables (bool b, bool set_children) -{ - m_parsed_block_variables = b; - if (set_children) - { - collection::const_iterator pos, end = m_children.end(); - for (pos = m_children.begin(); pos != end; ++pos) - (*pos)->SetDidParseVariables (b, true); - } +void Block::SetBlockInfoHasBeenParsed(bool b, bool set_children) { + m_parsed_block_info = b; + if (set_children) { + m_parsed_child_blocks = true; + collection::const_iterator pos, end = m_children.end(); + for (pos = m_children.begin(); pos != end; ++pos) + (*pos)->SetBlockInfoHasBeenParsed(b, true); + } } +void Block::SetDidParseVariables(bool b, bool set_children) { + m_parsed_block_variables = b; + if (set_children) { + collection::const_iterator pos, end = m_children.end(); + for (pos = m_children.begin(); pos != end; ++pos) + (*pos)->SetDidParseVariables(b, true); + } +} -Block * -Block::GetSibling() const -{ - if (m_parent_scope) - { - Block *parent_block = GetParent(); - if (parent_block) - return parent_block->GetSiblingForChild (this); - } - return nullptr; +Block *Block::GetSibling() const { + if (m_parent_scope) { + Block *parent_block = GetParent(); + if (parent_block) + return parent_block->GetSiblingForChild(this); + } + return nullptr; } // A parent of child blocks can be asked to find a sibling block given // one of its child blocks -Block * -Block::GetSiblingForChild (const Block *child_block) const -{ - if (!m_children.empty()) - { - collection::const_iterator pos, end = m_children.end(); - for (pos = m_children.begin(); pos != end; ++pos) - { - if (pos->get() == child_block) - { - if (++pos != end) - return pos->get(); - break; - } - } +Block *Block::GetSiblingForChild(const Block *child_block) const { + if (!m_children.empty()) { + collection::const_iterator pos, end = m_children.end(); + for (pos = m_children.begin(); pos != end; ++pos) { + if (pos->get() == child_block) { + if (++pos != end) + return pos->get(); + break; + } } - return nullptr; + } + return nullptr; } - diff --git a/lldb/source/Symbol/ClangASTContext.cpp b/lldb/source/Symbol/ClangASTContext.cpp index 21cfeffdb18..e7fda6d4e8a 100644 --- a/lldb/source/Symbol/ClangASTContext.cpp +++ b/lldb/source/Symbol/ClangASTContext.cpp @@ -17,7 +17,7 @@ // Other libraries and framework includes -// Clang headers like to use NDEBUG inside of them to enable/disable debug +// Clang headers like to use NDEBUG inside of them to enable/disable debug // related features using "#ifndef NDEBUG" preprocessor blocks to do one thing // or another. This is bad because it means that if clang was built in release // mode, it assumes that you are building in release mode which is not always @@ -103,2350 +103,2072 @@ using namespace lldb_private; using namespace llvm; using namespace clang; -namespace -{ - static inline bool ClangASTContextSupportsLanguage (lldb::LanguageType language) - { - return language == eLanguageTypeUnknown || // Clang is the default type system - Language::LanguageIsC(language) || - Language::LanguageIsCPlusPlus(language) || - Language::LanguageIsObjC(language) || - Language::LanguageIsPascal(language) || - // Use Clang for Rust until there is a proper language plugin for it - language == eLanguageTypeRust || - language == eLanguageTypeExtRenderScript; - } +namespace { +static inline bool +ClangASTContextSupportsLanguage(lldb::LanguageType language) { + return language == eLanguageTypeUnknown || // Clang is the default type system + Language::LanguageIsC(language) || + Language::LanguageIsCPlusPlus(language) || + Language::LanguageIsObjC(language) || + Language::LanguageIsPascal(language) || + // Use Clang for Rust until there is a proper language plugin for it + language == eLanguageTypeRust || + language == eLanguageTypeExtRenderScript; +} } -typedef lldb_private::ThreadSafeDenseMap<clang::ASTContext *, ClangASTContext*> ClangASTMap; +typedef lldb_private::ThreadSafeDenseMap<clang::ASTContext *, ClangASTContext *> + ClangASTMap; -static ClangASTMap & -GetASTMap() -{ - static ClangASTMap *g_map_ptr = nullptr; - static std::once_flag g_once_flag; - std::call_once(g_once_flag, []() { - g_map_ptr = new ClangASTMap(); // leaked on purpose to avoid spins - }); - return *g_map_ptr; +static ClangASTMap &GetASTMap() { + static ClangASTMap *g_map_ptr = nullptr; + static std::once_flag g_once_flag; + std::call_once(g_once_flag, []() { + g_map_ptr = new ClangASTMap(); // leaked on purpose to avoid spins + }); + return *g_map_ptr; } -static bool -IsOperator(const char *name, clang::OverloadedOperatorKind &op_kind) -{ - if (name == nullptr || name[0] == '\0') - return false; +static bool IsOperator(const char *name, + clang::OverloadedOperatorKind &op_kind) { + if (name == nullptr || name[0] == '\0') + return false; #define OPERATOR_PREFIX "operator" #define OPERATOR_PREFIX_LENGTH (sizeof(OPERATOR_PREFIX) - 1) - const char *post_op_name = nullptr; + const char *post_op_name = nullptr; - bool no_space = true; + bool no_space = true; - if (::strncmp(name, OPERATOR_PREFIX, OPERATOR_PREFIX_LENGTH)) - return false; + if (::strncmp(name, OPERATOR_PREFIX, OPERATOR_PREFIX_LENGTH)) + return false; - post_op_name = name + OPERATOR_PREFIX_LENGTH; + post_op_name = name + OPERATOR_PREFIX_LENGTH; - if (post_op_name[0] == ' ') - { - post_op_name++; - no_space = false; - } + if (post_op_name[0] == ' ') { + post_op_name++; + no_space = false; + } #undef OPERATOR_PREFIX #undef OPERATOR_PREFIX_LENGTH - // This is an operator, set the overloaded operator kind to invalid - // in case this is a conversion operator... - op_kind = clang::NUM_OVERLOADED_OPERATORS; - - switch (post_op_name[0]) - { - default: - if (no_space) - return false; - break; - case 'n': - if (no_space) - return false; - if (strcmp(post_op_name, "new") == 0) - op_kind = clang::OO_New; - else if (strcmp(post_op_name, "new[]") == 0) - op_kind = clang::OO_Array_New; - break; - - case 'd': - if (no_space) - return false; - if (strcmp(post_op_name, "delete") == 0) - op_kind = clang::OO_Delete; - else if (strcmp(post_op_name, "delete[]") == 0) - op_kind = clang::OO_Array_Delete; - break; - - case '+': - if (post_op_name[1] == '\0') - op_kind = clang::OO_Plus; - else if (post_op_name[2] == '\0') - { - if (post_op_name[1] == '=') - op_kind = clang::OO_PlusEqual; - else if (post_op_name[1] == '+') - op_kind = clang::OO_PlusPlus; - } - break; - - case '-': - if (post_op_name[1] == '\0') - op_kind = clang::OO_Minus; - else if (post_op_name[2] == '\0') - { - switch (post_op_name[1]) - { - case '=': - op_kind = clang::OO_MinusEqual; - break; - case '-': - op_kind = clang::OO_MinusMinus; - break; - case '>': - op_kind = clang::OO_Arrow; - break; - } - } - else if (post_op_name[3] == '\0') - { - if (post_op_name[2] == '*') - op_kind = clang::OO_ArrowStar; - break; - } - break; + // This is an operator, set the overloaded operator kind to invalid + // in case this is a conversion operator... + op_kind = clang::NUM_OVERLOADED_OPERATORS; + + switch (post_op_name[0]) { + default: + if (no_space) + return false; + break; + case 'n': + if (no_space) + return false; + if (strcmp(post_op_name, "new") == 0) + op_kind = clang::OO_New; + else if (strcmp(post_op_name, "new[]") == 0) + op_kind = clang::OO_Array_New; + break; + + case 'd': + if (no_space) + return false; + if (strcmp(post_op_name, "delete") == 0) + op_kind = clang::OO_Delete; + else if (strcmp(post_op_name, "delete[]") == 0) + op_kind = clang::OO_Array_Delete; + break; + + case '+': + if (post_op_name[1] == '\0') + op_kind = clang::OO_Plus; + else if (post_op_name[2] == '\0') { + if (post_op_name[1] == '=') + op_kind = clang::OO_PlusEqual; + else if (post_op_name[1] == '+') + op_kind = clang::OO_PlusPlus; + } + break; + + case '-': + if (post_op_name[1] == '\0') + op_kind = clang::OO_Minus; + else if (post_op_name[2] == '\0') { + switch (post_op_name[1]) { + case '=': + op_kind = clang::OO_MinusEqual; + break; + case '-': + op_kind = clang::OO_MinusMinus; + break; + case '>': + op_kind = clang::OO_Arrow; + break; + } + } else if (post_op_name[3] == '\0') { + if (post_op_name[2] == '*') + op_kind = clang::OO_ArrowStar; + break; + } + break; + + case '*': + if (post_op_name[1] == '\0') + op_kind = clang::OO_Star; + else if (post_op_name[1] == '=' && post_op_name[2] == '\0') + op_kind = clang::OO_StarEqual; + break; + + case '/': + if (post_op_name[1] == '\0') + op_kind = clang::OO_Slash; + else if (post_op_name[1] == '=' && post_op_name[2] == '\0') + op_kind = clang::OO_SlashEqual; + break; + + case '%': + if (post_op_name[1] == '\0') + op_kind = clang::OO_Percent; + else if (post_op_name[1] == '=' && post_op_name[2] == '\0') + op_kind = clang::OO_PercentEqual; + break; + + case '^': + if (post_op_name[1] == '\0') + op_kind = clang::OO_Caret; + else if (post_op_name[1] == '=' && post_op_name[2] == '\0') + op_kind = clang::OO_CaretEqual; + break; + + case '&': + if (post_op_name[1] == '\0') + op_kind = clang::OO_Amp; + else if (post_op_name[2] == '\0') { + switch (post_op_name[1]) { + case '=': + op_kind = clang::OO_AmpEqual; + break; + case '&': + op_kind = clang::OO_AmpAmp; + break; + } + } + break; - case '*': - if (post_op_name[1] == '\0') - op_kind = clang::OO_Star; - else if (post_op_name[1] == '=' && post_op_name[2] == '\0') - op_kind = clang::OO_StarEqual; - break; + case '|': + if (post_op_name[1] == '\0') + op_kind = clang::OO_Pipe; + else if (post_op_name[2] == '\0') { + switch (post_op_name[1]) { + case '=': + op_kind = clang::OO_PipeEqual; + break; + case '|': + op_kind = clang::OO_PipePipe; + break; + } + } + break; + + case '~': + if (post_op_name[1] == '\0') + op_kind = clang::OO_Tilde; + break; + + case '!': + if (post_op_name[1] == '\0') + op_kind = clang::OO_Exclaim; + else if (post_op_name[1] == '=' && post_op_name[2] == '\0') + op_kind = clang::OO_ExclaimEqual; + break; + + case '=': + if (post_op_name[1] == '\0') + op_kind = clang::OO_Equal; + else if (post_op_name[1] == '=' && post_op_name[2] == '\0') + op_kind = clang::OO_EqualEqual; + break; + + case '<': + if (post_op_name[1] == '\0') + op_kind = clang::OO_Less; + else if (post_op_name[2] == '\0') { + switch (post_op_name[1]) { + case '<': + op_kind = clang::OO_LessLess; + break; + case '=': + op_kind = clang::OO_LessEqual; + break; + } + } else if (post_op_name[3] == '\0') { + if (post_op_name[2] == '=') + op_kind = clang::OO_LessLessEqual; + } + break; + + case '>': + if (post_op_name[1] == '\0') + op_kind = clang::OO_Greater; + else if (post_op_name[2] == '\0') { + switch (post_op_name[1]) { + case '>': + op_kind = clang::OO_GreaterGreater; + break; + case '=': + op_kind = clang::OO_GreaterEqual; + break; + } + } else if (post_op_name[1] == '>' && post_op_name[2] == '=' && + post_op_name[3] == '\0') { + op_kind = clang::OO_GreaterGreaterEqual; + } + break; - case '/': - if (post_op_name[1] == '\0') - op_kind = clang::OO_Slash; - else if (post_op_name[1] == '=' && post_op_name[2] == '\0') - op_kind = clang::OO_SlashEqual; - break; + case ',': + if (post_op_name[1] == '\0') + op_kind = clang::OO_Comma; + break; - case '%': - if (post_op_name[1] == '\0') - op_kind = clang::OO_Percent; - else if (post_op_name[1] == '=' && post_op_name[2] == '\0') - op_kind = clang::OO_PercentEqual; - break; + case '(': + if (post_op_name[1] == ')' && post_op_name[2] == '\0') + op_kind = clang::OO_Call; + break; - case '^': - if (post_op_name[1] == '\0') - op_kind = clang::OO_Caret; - else if (post_op_name[1] == '=' && post_op_name[2] == '\0') - op_kind = clang::OO_CaretEqual; - break; + case '[': + if (post_op_name[1] == ']' && post_op_name[2] == '\0') + op_kind = clang::OO_Subscript; + break; + } - case '&': - if (post_op_name[1] == '\0') - op_kind = clang::OO_Amp; - else if (post_op_name[2] == '\0') - { - switch (post_op_name[1]) - { - case '=': - op_kind = clang::OO_AmpEqual; - break; - case '&': - op_kind = clang::OO_AmpAmp; - break; - } - } - break; + return true; +} - case '|': - if (post_op_name[1] == '\0') - op_kind = clang::OO_Pipe; - else if (post_op_name[2] == '\0') - { - switch (post_op_name[1]) - { - case '=': - op_kind = clang::OO_PipeEqual; - break; - case '|': - op_kind = clang::OO_PipePipe; - break; - } - } - break; +clang::AccessSpecifier +ClangASTContext::ConvertAccessTypeToAccessSpecifier(AccessType access) { + switch (access) { + default: + break; + case eAccessNone: + return AS_none; + case eAccessPublic: + return AS_public; + case eAccessPrivate: + return AS_private; + case eAccessProtected: + return AS_protected; + } + return AS_none; +} + +static void ParseLangArgs(LangOptions &Opts, InputKind IK, const char *triple) { + // FIXME: Cleanup per-file based stuff. + + // Set some properties which depend solely on the input kind; it would be nice + // to move these to the language standard, and have the driver resolve the + // input kind + language standard. + if (IK == IK_Asm) { + Opts.AsmPreprocessor = 1; + } else if (IK == IK_ObjC || IK == IK_ObjCXX || IK == IK_PreprocessedObjC || + IK == IK_PreprocessedObjCXX) { + Opts.ObjC1 = Opts.ObjC2 = 1; + } + + LangStandard::Kind LangStd = LangStandard::lang_unspecified; + + if (LangStd == LangStandard::lang_unspecified) { + // Based on the base language, pick one. + switch (IK) { + case IK_None: + case IK_AST: + case IK_LLVM_IR: + case IK_RenderScript: + assert(!"Invalid input kind!"); + case IK_OpenCL: + LangStd = LangStandard::lang_opencl; + break; + case IK_CUDA: + case IK_PreprocessedCuda: + LangStd = LangStandard::lang_cuda; + break; + case IK_Asm: + case IK_C: + case IK_PreprocessedC: + case IK_ObjC: + case IK_PreprocessedObjC: + LangStd = LangStandard::lang_gnu99; + break; + case IK_CXX: + case IK_PreprocessedCXX: + case IK_ObjCXX: + case IK_PreprocessedObjCXX: + LangStd = LangStandard::lang_gnucxx98; + break; + } + } + + const LangStandard &Std = LangStandard::getLangStandardForKind(LangStd); + Opts.LineComment = Std.hasLineComments(); + Opts.C99 = Std.isC99(); + Opts.CPlusPlus = Std.isCPlusPlus(); + Opts.CPlusPlus11 = Std.isCPlusPlus11(); + Opts.Digraphs = Std.hasDigraphs(); + Opts.GNUMode = Std.isGNUMode(); + Opts.GNUInline = !Std.isC99(); + Opts.HexFloats = Std.hasHexFloats(); + Opts.ImplicitInt = Std.hasImplicitInt(); + + Opts.WChar = true; + + // OpenCL has some additional defaults. + if (LangStd == LangStandard::lang_opencl) { + Opts.OpenCL = 1; + Opts.AltiVec = 1; + Opts.CXXOperatorNames = 1; + Opts.LaxVectorConversions = 1; + } + + // OpenCL and C++ both have bool, true, false keywords. + Opts.Bool = Opts.OpenCL || Opts.CPlusPlus; + + // if (Opts.CPlusPlus) + // Opts.CXXOperatorNames = !Args.hasArg(OPT_fno_operator_names); + // + // if (Args.hasArg(OPT_fobjc_gc_only)) + // Opts.setGCMode(LangOptions::GCOnly); + // else if (Args.hasArg(OPT_fobjc_gc)) + // Opts.setGCMode(LangOptions::HybridGC); + // + // if (Args.hasArg(OPT_print_ivar_layout)) + // Opts.ObjCGCBitmapPrint = 1; + // + // if (Args.hasArg(OPT_faltivec)) + // Opts.AltiVec = 1; + // + // if (Args.hasArg(OPT_pthread)) + // Opts.POSIXThreads = 1; + // + // llvm::StringRef Vis = getLastArgValue(Args, OPT_fvisibility, + // "default"); + // if (Vis == "default") + Opts.setValueVisibilityMode(DefaultVisibility); + // else if (Vis == "hidden") + // Opts.setVisibilityMode(LangOptions::Hidden); + // else if (Vis == "protected") + // Opts.setVisibilityMode(LangOptions::Protected); + // else + // Diags.Report(diag::err_drv_invalid_value) + // << Args.getLastArg(OPT_fvisibility)->getAsString(Args) << Vis; + + // Opts.OverflowChecking = Args.hasArg(OPT_ftrapv); + + // Mimicing gcc's behavior, trigraphs are only enabled if -trigraphs + // is specified, or -std is set to a conforming mode. + Opts.Trigraphs = !Opts.GNUMode; + // if (Args.hasArg(OPT_trigraphs)) + // Opts.Trigraphs = 1; + // + // Opts.DollarIdents = Args.hasFlag(OPT_fdollars_in_identifiers, + // OPT_fno_dollars_in_identifiers, + // !Opts.AsmPreprocessor); + // Opts.PascalStrings = Args.hasArg(OPT_fpascal_strings); + // Opts.Microsoft = Args.hasArg(OPT_fms_extensions); + // Opts.WritableStrings = Args.hasArg(OPT_fwritable_strings); + // if (Args.hasArg(OPT_fno_lax_vector_conversions)) + // Opts.LaxVectorConversions = 0; + // Opts.Exceptions = Args.hasArg(OPT_fexceptions); + // Opts.RTTI = !Args.hasArg(OPT_fno_rtti); + // Opts.Blocks = Args.hasArg(OPT_fblocks); + Opts.CharIsSigned = ArchSpec(triple).CharIsSignedByDefault(); + // Opts.ShortWChar = Args.hasArg(OPT_fshort_wchar); + // Opts.Freestanding = Args.hasArg(OPT_ffreestanding); + // Opts.NoBuiltin = Args.hasArg(OPT_fno_builtin) || Opts.Freestanding; + // Opts.AssumeSaneOperatorNew = + // !Args.hasArg(OPT_fno_assume_sane_operator_new); + // Opts.HeinousExtensions = Args.hasArg(OPT_fheinous_gnu_extensions); + // Opts.AccessControl = Args.hasArg(OPT_faccess_control); + // Opts.ElideConstructors = !Args.hasArg(OPT_fno_elide_constructors); + // Opts.MathErrno = !Args.hasArg(OPT_fno_math_errno); + // Opts.InstantiationDepth = getLastArgIntValue(Args, OPT_ftemplate_depth, + // 99, + // Diags); + // Opts.NeXTRuntime = !Args.hasArg(OPT_fgnu_runtime); + // Opts.ObjCConstantStringClass = getLastArgValue(Args, + // OPT_fconstant_string_class); + // Opts.ObjCNonFragileABI = Args.hasArg(OPT_fobjc_nonfragile_abi); + // Opts.CatchUndefined = Args.hasArg(OPT_fcatch_undefined_behavior); + // Opts.EmitAllDecls = Args.hasArg(OPT_femit_all_decls); + // Opts.PICLevel = getLastArgIntValue(Args, OPT_pic_level, 0, Diags); + // Opts.Static = Args.hasArg(OPT_static_define); + Opts.OptimizeSize = 0; + + // FIXME: Eliminate this dependency. + // unsigned Opt = + // Args.hasArg(OPT_Os) ? 2 : getLastArgIntValue(Args, OPT_O, 0, Diags); + // Opts.Optimize = Opt != 0; + unsigned Opt = 0; + + // This is the __NO_INLINE__ define, which just depends on things like the + // optimization level and -fno-inline, not actually whether the backend has + // inlining enabled. + // + // FIXME: This is affected by other options (-fno-inline). + Opts.NoInlineDefine = !Opt; + + // unsigned SSP = getLastArgIntValue(Args, OPT_stack_protector, 0, Diags); + // switch (SSP) { + // default: + // Diags.Report(diag::err_drv_invalid_value) + // << Args.getLastArg(OPT_stack_protector)->getAsString(Args) << + // SSP; + // break; + // case 0: Opts.setStackProtectorMode(LangOptions::SSPOff); break; + // case 1: Opts.setStackProtectorMode(LangOptions::SSPOn); break; + // case 2: Opts.setStackProtectorMode(LangOptions::SSPReq); break; + // } +} + +ClangASTContext::ClangASTContext(const char *target_triple) + : TypeSystem(TypeSystem::eKindClang), m_target_triple(), m_ast_ap(), + m_language_options_ap(), m_source_manager_ap(), m_diagnostics_engine_ap(), + m_target_options_rp(), m_target_info_ap(), m_identifier_table_ap(), + m_selector_table_ap(), m_builtins_ap(), m_callback_tag_decl(nullptr), + m_callback_objc_decl(nullptr), m_callback_baton(nullptr), + m_pointer_byte_size(0), m_ast_owned(false) { + if (target_triple && target_triple[0]) + SetTargetTriple(target_triple); +} - case '~': - if (post_op_name[1] == '\0') - op_kind = clang::OO_Tilde; - break; +//---------------------------------------------------------------------- +// Destructor +//---------------------------------------------------------------------- +ClangASTContext::~ClangASTContext() { Finalize(); } + +ConstString ClangASTContext::GetPluginNameStatic() { + return ConstString("clang"); +} + +ConstString ClangASTContext::GetPluginName() { + return ClangASTContext::GetPluginNameStatic(); +} + +uint32_t ClangASTContext::GetPluginVersion() { return 1; } + +lldb::TypeSystemSP ClangASTContext::CreateInstance(lldb::LanguageType language, + lldb_private::Module *module, + Target *target) { + if (ClangASTContextSupportsLanguage(language)) { + ArchSpec arch; + if (module) + arch = module->GetArchitecture(); + else if (target) + arch = target->GetArchitecture(); + + if (arch.IsValid()) { + ArchSpec fixed_arch = arch; + // LLVM wants this to be set to iOS or MacOSX; if we're working on + // a bare-boards type image, change the triple for llvm's benefit. + if (fixed_arch.GetTriple().getVendor() == llvm::Triple::Apple && + fixed_arch.GetTriple().getOS() == llvm::Triple::UnknownOS) { + if (fixed_arch.GetTriple().getArch() == llvm::Triple::arm || + fixed_arch.GetTriple().getArch() == llvm::Triple::aarch64 || + fixed_arch.GetTriple().getArch() == llvm::Triple::thumb) { + fixed_arch.GetTriple().setOS(llvm::Triple::IOS); + } else { + fixed_arch.GetTriple().setOS(llvm::Triple::MacOSX); + } + } - case '!': - if (post_op_name[1] == '\0') - op_kind = clang::OO_Exclaim; - else if (post_op_name[1] == '=' && post_op_name[2] == '\0') - op_kind = clang::OO_ExclaimEqual; - break; + if (module) { + std::shared_ptr<ClangASTContext> ast_sp(new ClangASTContext); + if (ast_sp) { + ast_sp->SetArchitecture(fixed_arch); + } + return ast_sp; + } else if (target && target->IsValid()) { + std::shared_ptr<ClangASTContextForExpressions> ast_sp( + new ClangASTContextForExpressions(*target)); + if (ast_sp) { + ast_sp->SetArchitecture(fixed_arch); + ast_sp->m_scratch_ast_source_ap.reset( + new ClangASTSource(target->shared_from_this())); + ast_sp->m_scratch_ast_source_ap->InstallASTContext( + ast_sp->getASTContext()); + llvm::IntrusiveRefCntPtr<clang::ExternalASTSource> proxy_ast_source( + ast_sp->m_scratch_ast_source_ap->CreateProxy()); + ast_sp->SetExternalSource(proxy_ast_source); + return ast_sp; + } + } + } + } + return lldb::TypeSystemSP(); +} - case '=': - if (post_op_name[1] == '\0') - op_kind = clang::OO_Equal; - else if (post_op_name[1] == '=' && post_op_name[2] == '\0') - op_kind = clang::OO_EqualEqual; - break; +void ClangASTContext::EnumerateSupportedLanguages( + std::set<lldb::LanguageType> &languages_for_types, + std::set<lldb::LanguageType> &languages_for_expressions) { + static std::vector<lldb::LanguageType> s_supported_languages_for_types( + {lldb::eLanguageTypeC89, lldb::eLanguageTypeC, lldb::eLanguageTypeC11, + lldb::eLanguageTypeC_plus_plus, lldb::eLanguageTypeC99, + lldb::eLanguageTypeObjC, lldb::eLanguageTypeObjC_plus_plus, + lldb::eLanguageTypeC_plus_plus_03, lldb::eLanguageTypeC_plus_plus_11, + lldb::eLanguageTypeC11, lldb::eLanguageTypeC_plus_plus_14}); - case '<': - if (post_op_name[1] == '\0') - op_kind = clang::OO_Less; - else if (post_op_name[2] == '\0') - { - switch (post_op_name[1]) - { - case '<': - op_kind = clang::OO_LessLess; - break; - case '=': - op_kind = clang::OO_LessEqual; - break; - } - } - else if (post_op_name[3] == '\0') - { - if (post_op_name[2] == '=') - op_kind = clang::OO_LessLessEqual; - } - break; + static std::vector<lldb::LanguageType> s_supported_languages_for_expressions( + {lldb::eLanguageTypeC_plus_plus, lldb::eLanguageTypeObjC_plus_plus, + lldb::eLanguageTypeC_plus_plus_03, lldb::eLanguageTypeC_plus_plus_11, + lldb::eLanguageTypeC_plus_plus_14}); - case '>': - if (post_op_name[1] == '\0') - op_kind = clang::OO_Greater; - else if (post_op_name[2] == '\0') - { - switch (post_op_name[1]) - { - case '>': - op_kind = clang::OO_GreaterGreater; - break; - case '=': - op_kind = clang::OO_GreaterEqual; - break; - } - } - else if (post_op_name[1] == '>' && post_op_name[2] == '=' && post_op_name[3] == '\0') - { - op_kind = clang::OO_GreaterGreaterEqual; - } - break; + languages_for_types.insert(s_supported_languages_for_types.begin(), + s_supported_languages_for_types.end()); + languages_for_expressions.insert( + s_supported_languages_for_expressions.begin(), + s_supported_languages_for_expressions.end()); +} - case ',': - if (post_op_name[1] == '\0') - op_kind = clang::OO_Comma; - break; +void ClangASTContext::Initialize() { + PluginManager::RegisterPlugin(GetPluginNameStatic(), + "clang base AST context plug-in", + CreateInstance, EnumerateSupportedLanguages); +} - case '(': - if (post_op_name[1] == ')' && post_op_name[2] == '\0') - op_kind = clang::OO_Call; - break; +void ClangASTContext::Terminate() { + PluginManager::UnregisterPlugin(CreateInstance); +} - case '[': - if (post_op_name[1] == ']' && post_op_name[2] == '\0') - op_kind = clang::OO_Subscript; - break; - } +void ClangASTContext::Finalize() { + if (m_ast_ap.get()) { + GetASTMap().Erase(m_ast_ap.get()); + if (!m_ast_owned) + m_ast_ap.release(); + } - return true; + m_builtins_ap.reset(); + m_selector_table_ap.reset(); + m_identifier_table_ap.reset(); + m_target_info_ap.reset(); + m_target_options_rp.reset(); + m_diagnostics_engine_ap.reset(); + m_source_manager_ap.reset(); + m_language_options_ap.reset(); + m_ast_ap.reset(); + m_scratch_ast_source_ap.reset(); } -clang::AccessSpecifier -ClangASTContext::ConvertAccessTypeToAccessSpecifier (AccessType access) -{ - switch (access) - { - default: break; - case eAccessNone: return AS_none; - case eAccessPublic: return AS_public; - case eAccessPrivate: return AS_private; - case eAccessProtected: return AS_protected; - } - return AS_none; +void ClangASTContext::Clear() { + m_ast_ap.reset(); + m_language_options_ap.reset(); + m_source_manager_ap.reset(); + m_diagnostics_engine_ap.reset(); + m_target_options_rp.reset(); + m_target_info_ap.reset(); + m_identifier_table_ap.reset(); + m_selector_table_ap.reset(); + m_builtins_ap.reset(); + m_pointer_byte_size = 0; } -static void -ParseLangArgs (LangOptions &Opts, InputKind IK, const char* triple) -{ - // FIXME: Cleanup per-file based stuff. - - // Set some properties which depend solely on the input kind; it would be nice - // to move these to the language standard, and have the driver resolve the - // input kind + language standard. - if (IK == IK_Asm) { - Opts.AsmPreprocessor = 1; - } else if (IK == IK_ObjC || - IK == IK_ObjCXX || - IK == IK_PreprocessedObjC || - IK == IK_PreprocessedObjCXX) { - Opts.ObjC1 = Opts.ObjC2 = 1; - } - - LangStandard::Kind LangStd = LangStandard::lang_unspecified; - - if (LangStd == LangStandard::lang_unspecified) { - // Based on the base language, pick one. - switch (IK) { - case IK_None: - case IK_AST: - case IK_LLVM_IR: - case IK_RenderScript: - assert (!"Invalid input kind!"); - case IK_OpenCL: - LangStd = LangStandard::lang_opencl; - break; - case IK_CUDA: - case IK_PreprocessedCuda: - LangStd = LangStandard::lang_cuda; - break; - case IK_Asm: - case IK_C: - case IK_PreprocessedC: - case IK_ObjC: - case IK_PreprocessedObjC: - LangStd = LangStandard::lang_gnu99; - break; - case IK_CXX: - case IK_PreprocessedCXX: - case IK_ObjCXX: - case IK_PreprocessedObjCXX: - LangStd = LangStandard::lang_gnucxx98; - break; - } - } - - const LangStandard &Std = LangStandard::getLangStandardForKind(LangStd); - Opts.LineComment = Std.hasLineComments(); - Opts.C99 = Std.isC99(); - Opts.CPlusPlus = Std.isCPlusPlus(); - Opts.CPlusPlus11 = Std.isCPlusPlus11(); - Opts.Digraphs = Std.hasDigraphs(); - Opts.GNUMode = Std.isGNUMode(); - Opts.GNUInline = !Std.isC99(); - Opts.HexFloats = Std.hasHexFloats(); - Opts.ImplicitInt = Std.hasImplicitInt(); - - Opts.WChar = true; - - // OpenCL has some additional defaults. - if (LangStd == LangStandard::lang_opencl) { - Opts.OpenCL = 1; - Opts.AltiVec = 1; - Opts.CXXOperatorNames = 1; - Opts.LaxVectorConversions = 1; - } - - // OpenCL and C++ both have bool, true, false keywords. - Opts.Bool = Opts.OpenCL || Opts.CPlusPlus; - -// if (Opts.CPlusPlus) -// Opts.CXXOperatorNames = !Args.hasArg(OPT_fno_operator_names); -// -// if (Args.hasArg(OPT_fobjc_gc_only)) -// Opts.setGCMode(LangOptions::GCOnly); -// else if (Args.hasArg(OPT_fobjc_gc)) -// Opts.setGCMode(LangOptions::HybridGC); -// -// if (Args.hasArg(OPT_print_ivar_layout)) -// Opts.ObjCGCBitmapPrint = 1; -// -// if (Args.hasArg(OPT_faltivec)) -// Opts.AltiVec = 1; -// -// if (Args.hasArg(OPT_pthread)) -// Opts.POSIXThreads = 1; -// -// llvm::StringRef Vis = getLastArgValue(Args, OPT_fvisibility, -// "default"); -// if (Vis == "default") - Opts.setValueVisibilityMode(DefaultVisibility); -// else if (Vis == "hidden") -// Opts.setVisibilityMode(LangOptions::Hidden); -// else if (Vis == "protected") -// Opts.setVisibilityMode(LangOptions::Protected); -// else -// Diags.Report(diag::err_drv_invalid_value) -// << Args.getLastArg(OPT_fvisibility)->getAsString(Args) << Vis; - -// Opts.OverflowChecking = Args.hasArg(OPT_ftrapv); - - // Mimicing gcc's behavior, trigraphs are only enabled if -trigraphs - // is specified, or -std is set to a conforming mode. - Opts.Trigraphs = !Opts.GNUMode; -// if (Args.hasArg(OPT_trigraphs)) -// Opts.Trigraphs = 1; -// -// Opts.DollarIdents = Args.hasFlag(OPT_fdollars_in_identifiers, -// OPT_fno_dollars_in_identifiers, -// !Opts.AsmPreprocessor); -// Opts.PascalStrings = Args.hasArg(OPT_fpascal_strings); -// Opts.Microsoft = Args.hasArg(OPT_fms_extensions); -// Opts.WritableStrings = Args.hasArg(OPT_fwritable_strings); -// if (Args.hasArg(OPT_fno_lax_vector_conversions)) -// Opts.LaxVectorConversions = 0; -// Opts.Exceptions = Args.hasArg(OPT_fexceptions); -// Opts.RTTI = !Args.hasArg(OPT_fno_rtti); -// Opts.Blocks = Args.hasArg(OPT_fblocks); - Opts.CharIsSigned = ArchSpec(triple).CharIsSignedByDefault(); -// Opts.ShortWChar = Args.hasArg(OPT_fshort_wchar); -// Opts.Freestanding = Args.hasArg(OPT_ffreestanding); -// Opts.NoBuiltin = Args.hasArg(OPT_fno_builtin) || Opts.Freestanding; -// Opts.AssumeSaneOperatorNew = !Args.hasArg(OPT_fno_assume_sane_operator_new); -// Opts.HeinousExtensions = Args.hasArg(OPT_fheinous_gnu_extensions); -// Opts.AccessControl = Args.hasArg(OPT_faccess_control); -// Opts.ElideConstructors = !Args.hasArg(OPT_fno_elide_constructors); -// Opts.MathErrno = !Args.hasArg(OPT_fno_math_errno); -// Opts.InstantiationDepth = getLastArgIntValue(Args, OPT_ftemplate_depth, 99, -// Diags); -// Opts.NeXTRuntime = !Args.hasArg(OPT_fgnu_runtime); -// Opts.ObjCConstantStringClass = getLastArgValue(Args, -// OPT_fconstant_string_class); -// Opts.ObjCNonFragileABI = Args.hasArg(OPT_fobjc_nonfragile_abi); -// Opts.CatchUndefined = Args.hasArg(OPT_fcatch_undefined_behavior); -// Opts.EmitAllDecls = Args.hasArg(OPT_femit_all_decls); -// Opts.PICLevel = getLastArgIntValue(Args, OPT_pic_level, 0, Diags); -// Opts.Static = Args.hasArg(OPT_static_define); - Opts.OptimizeSize = 0; - - // FIXME: Eliminate this dependency. -// unsigned Opt = -// Args.hasArg(OPT_Os) ? 2 : getLastArgIntValue(Args, OPT_O, 0, Diags); -// Opts.Optimize = Opt != 0; - unsigned Opt = 0; - - // This is the __NO_INLINE__ define, which just depends on things like the - // optimization level and -fno-inline, not actually whether the backend has - // inlining enabled. - // - // FIXME: This is affected by other options (-fno-inline). - Opts.NoInlineDefine = !Opt; - -// unsigned SSP = getLastArgIntValue(Args, OPT_stack_protector, 0, Diags); -// switch (SSP) { -// default: -// Diags.Report(diag::err_drv_invalid_value) -// << Args.getLastArg(OPT_stack_protector)->getAsString(Args) << SSP; -// break; -// case 0: Opts.setStackProtectorMode(LangOptions::SSPOff); break; -// case 1: Opts.setStackProtectorMode(LangOptions::SSPOn); break; -// case 2: Opts.setStackProtectorMode(LangOptions::SSPReq); break; -// } -} - - -ClangASTContext::ClangASTContext (const char *target_triple) : - TypeSystem (TypeSystem::eKindClang), - m_target_triple (), - m_ast_ap (), - m_language_options_ap (), - m_source_manager_ap (), - m_diagnostics_engine_ap (), - m_target_options_rp (), - m_target_info_ap (), - m_identifier_table_ap (), - m_selector_table_ap (), - m_builtins_ap (), - m_callback_tag_decl (nullptr), - m_callback_objc_decl (nullptr), - m_callback_baton (nullptr), - m_pointer_byte_size (0), - m_ast_owned (false) -{ - if (target_triple && target_triple[0]) - SetTargetTriple (target_triple); +const char *ClangASTContext::GetTargetTriple() { + return m_target_triple.c_str(); } -//---------------------------------------------------------------------- -// Destructor -//---------------------------------------------------------------------- -ClangASTContext::~ClangASTContext() -{ - Finalize(); +void ClangASTContext::SetTargetTriple(const char *target_triple) { + Clear(); + m_target_triple.assign(target_triple); } -ConstString -ClangASTContext::GetPluginNameStatic() -{ - return ConstString("clang"); +void ClangASTContext::SetArchitecture(const ArchSpec &arch) { + SetTargetTriple(arch.GetTriple().str().c_str()); } -ConstString -ClangASTContext::GetPluginName() -{ - return ClangASTContext::GetPluginNameStatic(); +bool ClangASTContext::HasExternalSource() { + ASTContext *ast = getASTContext(); + if (ast) + return ast->getExternalSource() != nullptr; + return false; } -uint32_t -ClangASTContext::GetPluginVersion() -{ - return 1; +void ClangASTContext::SetExternalSource( + llvm::IntrusiveRefCntPtr<ExternalASTSource> &ast_source_ap) { + ASTContext *ast = getASTContext(); + if (ast) { + ast->setExternalSource(ast_source_ap); + ast->getTranslationUnitDecl()->setHasExternalLexicalStorage(true); + // ast->getTranslationUnitDecl()->setHasExternalVisibleStorage(true); + } } -lldb::TypeSystemSP -ClangASTContext::CreateInstance (lldb::LanguageType language, - lldb_private::Module *module, - Target *target) -{ - if (ClangASTContextSupportsLanguage(language)) - { - ArchSpec arch; - if (module) - arch = module->GetArchitecture(); - else if (target) - arch = target->GetArchitecture(); - - if (arch.IsValid()) - { - ArchSpec fixed_arch = arch; - // LLVM wants this to be set to iOS or MacOSX; if we're working on - // a bare-boards type image, change the triple for llvm's benefit. - if (fixed_arch.GetTriple().getVendor() == llvm::Triple::Apple && - fixed_arch.GetTriple().getOS() == llvm::Triple::UnknownOS) - { - if (fixed_arch.GetTriple().getArch() == llvm::Triple::arm || - fixed_arch.GetTriple().getArch() == llvm::Triple::aarch64 || - fixed_arch.GetTriple().getArch() == llvm::Triple::thumb) - { - fixed_arch.GetTriple().setOS(llvm::Triple::IOS); - } - else - { - fixed_arch.GetTriple().setOS(llvm::Triple::MacOSX); - } - } +void ClangASTContext::RemoveExternalSource() { + ASTContext *ast = getASTContext(); - if (module) - { - std::shared_ptr<ClangASTContext> ast_sp(new ClangASTContext); - if (ast_sp) - { - ast_sp->SetArchitecture (fixed_arch); - } - return ast_sp; - } - else if (target && target->IsValid()) - { - std::shared_ptr<ClangASTContextForExpressions> ast_sp(new ClangASTContextForExpressions(*target)); - if (ast_sp) - { - ast_sp->SetArchitecture(fixed_arch); - ast_sp->m_scratch_ast_source_ap.reset (new ClangASTSource(target->shared_from_this())); - ast_sp->m_scratch_ast_source_ap->InstallASTContext(ast_sp->getASTContext()); - llvm::IntrusiveRefCntPtr<clang::ExternalASTSource> proxy_ast_source(ast_sp->m_scratch_ast_source_ap->CreateProxy()); - ast_sp->SetExternalSource(proxy_ast_source); - return ast_sp; - } - } - } - } - return lldb::TypeSystemSP(); -} - -void -ClangASTContext::EnumerateSupportedLanguages(std::set<lldb::LanguageType> &languages_for_types, std::set<lldb::LanguageType> &languages_for_expressions) -{ - static std::vector<lldb::LanguageType> s_supported_languages_for_types({ - lldb::eLanguageTypeC89, - lldb::eLanguageTypeC, - lldb::eLanguageTypeC11, - lldb::eLanguageTypeC_plus_plus, - lldb::eLanguageTypeC99, - lldb::eLanguageTypeObjC, - lldb::eLanguageTypeObjC_plus_plus, - lldb::eLanguageTypeC_plus_plus_03, - lldb::eLanguageTypeC_plus_plus_11, - lldb::eLanguageTypeC11, - lldb::eLanguageTypeC_plus_plus_14}); - - static std::vector<lldb::LanguageType> s_supported_languages_for_expressions({ - lldb::eLanguageTypeC_plus_plus, - lldb::eLanguageTypeObjC_plus_plus, - lldb::eLanguageTypeC_plus_plus_03, - lldb::eLanguageTypeC_plus_plus_11, - lldb::eLanguageTypeC_plus_plus_14}); - - languages_for_types.insert(s_supported_languages_for_types.begin(), s_supported_languages_for_types.end()); - languages_for_expressions.insert(s_supported_languages_for_expressions.begin(), s_supported_languages_for_expressions.end()); -} - - -void -ClangASTContext::Initialize() -{ - PluginManager::RegisterPlugin (GetPluginNameStatic(), - "clang base AST context plug-in", - CreateInstance, - EnumerateSupportedLanguages); -} - -void -ClangASTContext::Terminate() -{ - PluginManager::UnregisterPlugin (CreateInstance); -} - -void -ClangASTContext::Finalize() -{ - if (m_ast_ap.get()) - { - GetASTMap().Erase(m_ast_ap.get()); - if (!m_ast_owned) - m_ast_ap.release(); - } - - m_builtins_ap.reset(); - m_selector_table_ap.reset(); - m_identifier_table_ap.reset(); - m_target_info_ap.reset(); - m_target_options_rp.reset(); - m_diagnostics_engine_ap.reset(); - m_source_manager_ap.reset(); - m_language_options_ap.reset(); - m_ast_ap.reset(); - m_scratch_ast_source_ap.reset(); -} - -void -ClangASTContext::Clear() -{ - m_ast_ap.reset(); - m_language_options_ap.reset(); - m_source_manager_ap.reset(); - m_diagnostics_engine_ap.reset(); - m_target_options_rp.reset(); - m_target_info_ap.reset(); - m_identifier_table_ap.reset(); - m_selector_table_ap.reset(); - m_builtins_ap.reset(); - m_pointer_byte_size = 0; -} - -const char * -ClangASTContext::GetTargetTriple () -{ - return m_target_triple.c_str(); -} - -void -ClangASTContext::SetTargetTriple (const char *target_triple) -{ - Clear(); - m_target_triple.assign(target_triple); -} - -void -ClangASTContext::SetArchitecture (const ArchSpec &arch) -{ - SetTargetTriple(arch.GetTriple().str().c_str()); -} - -bool -ClangASTContext::HasExternalSource () -{ - ASTContext *ast = getASTContext(); - if (ast) - return ast->getExternalSource () != nullptr; - return false; + if (ast) { + llvm::IntrusiveRefCntPtr<ExternalASTSource> empty_ast_source_ap; + ast->setExternalSource(empty_ast_source_ap); + ast->getTranslationUnitDecl()->setHasExternalLexicalStorage(false); + // ast->getTranslationUnitDecl()->setHasExternalVisibleStorage(false); + } } -void -ClangASTContext::SetExternalSource (llvm::IntrusiveRefCntPtr<ExternalASTSource> &ast_source_ap) -{ - ASTContext *ast = getASTContext(); - if (ast) - { - ast->setExternalSource (ast_source_ap); - ast->getTranslationUnitDecl()->setHasExternalLexicalStorage(true); - //ast->getTranslationUnitDecl()->setHasExternalVisibleStorage(true); - } +void ClangASTContext::setASTContext(clang::ASTContext *ast_ctx) { + if (!m_ast_owned) { + m_ast_ap.release(); + } + m_ast_owned = false; + m_ast_ap.reset(ast_ctx); + GetASTMap().Insert(ast_ctx, this); } -void -ClangASTContext::RemoveExternalSource () -{ - ASTContext *ast = getASTContext(); - - if (ast) - { - llvm::IntrusiveRefCntPtr<ExternalASTSource> empty_ast_source_ap; - ast->setExternalSource (empty_ast_source_ap); - ast->getTranslationUnitDecl()->setHasExternalLexicalStorage(false); - //ast->getTranslationUnitDecl()->setHasExternalVisibleStorage(false); - } -} - -void -ClangASTContext::setASTContext(clang::ASTContext *ast_ctx) -{ - if (!m_ast_owned) { - m_ast_ap.release(); - } - m_ast_owned = false; - m_ast_ap.reset(ast_ctx); - GetASTMap().Insert(ast_ctx, this); -} - -ASTContext * -ClangASTContext::getASTContext() -{ - if (m_ast_ap.get() == nullptr) - { - m_ast_owned = true; - m_ast_ap.reset(new ASTContext (*getLanguageOptions(), - *getSourceManager(), - *getIdentifierTable(), - *getSelectorTable(), - *getBuiltinContext())); - - m_ast_ap->getDiagnostics().setClient(getDiagnosticConsumer(), false); - - // This can be NULL if we don't know anything about the architecture or if the - // target for an architecture isn't enabled in the llvm/clang that we built - TargetInfo *target_info = getTargetInfo(); - if (target_info) - m_ast_ap->InitBuiltinTypes(*target_info); - - if ((m_callback_tag_decl || m_callback_objc_decl) && m_callback_baton) - { - m_ast_ap->getTranslationUnitDecl()->setHasExternalLexicalStorage(); - //m_ast_ap->getTranslationUnitDecl()->setHasExternalVisibleStorage(); - } - - GetASTMap().Insert(m_ast_ap.get(), this); +ASTContext *ClangASTContext::getASTContext() { + if (m_ast_ap.get() == nullptr) { + m_ast_owned = true; + m_ast_ap.reset(new ASTContext(*getLanguageOptions(), *getSourceManager(), + *getIdentifierTable(), *getSelectorTable(), + *getBuiltinContext())); + + m_ast_ap->getDiagnostics().setClient(getDiagnosticConsumer(), false); - llvm::IntrusiveRefCntPtr<clang::ExternalASTSource> ast_source_ap (new ClangExternalASTSourceCallbacks (ClangASTContext::CompleteTagDecl, - ClangASTContext::CompleteObjCInterfaceDecl, - nullptr, - ClangASTContext::LayoutRecordType, - this)); - SetExternalSource (ast_source_ap); + // This can be NULL if we don't know anything about the architecture or if + // the + // target for an architecture isn't enabled in the llvm/clang that we built + TargetInfo *target_info = getTargetInfo(); + if (target_info) + m_ast_ap->InitBuiltinTypes(*target_info); + + if ((m_callback_tag_decl || m_callback_objc_decl) && m_callback_baton) { + m_ast_ap->getTranslationUnitDecl()->setHasExternalLexicalStorage(); + // m_ast_ap->getTranslationUnitDecl()->setHasExternalVisibleStorage(); } - return m_ast_ap.get(); + + GetASTMap().Insert(m_ast_ap.get(), this); + + llvm::IntrusiveRefCntPtr<clang::ExternalASTSource> ast_source_ap( + new ClangExternalASTSourceCallbacks( + ClangASTContext::CompleteTagDecl, + ClangASTContext::CompleteObjCInterfaceDecl, nullptr, + ClangASTContext::LayoutRecordType, this)); + SetExternalSource(ast_source_ap); + } + return m_ast_ap.get(); } -ClangASTContext* -ClangASTContext::GetASTContext (clang::ASTContext* ast) -{ - ClangASTContext *clang_ast = GetASTMap().Lookup(ast); - return clang_ast; +ClangASTContext *ClangASTContext::GetASTContext(clang::ASTContext *ast) { + ClangASTContext *clang_ast = GetASTMap().Lookup(ast); + return clang_ast; } -Builtin::Context * -ClangASTContext::getBuiltinContext() -{ - if (m_builtins_ap.get() == nullptr) - m_builtins_ap.reset (new Builtin::Context()); - return m_builtins_ap.get(); +Builtin::Context *ClangASTContext::getBuiltinContext() { + if (m_builtins_ap.get() == nullptr) + m_builtins_ap.reset(new Builtin::Context()); + return m_builtins_ap.get(); } -IdentifierTable * -ClangASTContext::getIdentifierTable() -{ - if (m_identifier_table_ap.get() == nullptr) - m_identifier_table_ap.reset(new IdentifierTable (*ClangASTContext::getLanguageOptions(), nullptr)); - return m_identifier_table_ap.get(); +IdentifierTable *ClangASTContext::getIdentifierTable() { + if (m_identifier_table_ap.get() == nullptr) + m_identifier_table_ap.reset( + new IdentifierTable(*ClangASTContext::getLanguageOptions(), nullptr)); + return m_identifier_table_ap.get(); } -LangOptions * -ClangASTContext::getLanguageOptions() -{ - if (m_language_options_ap.get() == nullptr) - { - m_language_options_ap.reset(new LangOptions()); - ParseLangArgs(*m_language_options_ap, IK_ObjCXX, GetTargetTriple()); -// InitializeLangOptions(*m_language_options_ap, IK_ObjCXX); - } - return m_language_options_ap.get(); +LangOptions *ClangASTContext::getLanguageOptions() { + if (m_language_options_ap.get() == nullptr) { + m_language_options_ap.reset(new LangOptions()); + ParseLangArgs(*m_language_options_ap, IK_ObjCXX, GetTargetTriple()); + // InitializeLangOptions(*m_language_options_ap, IK_ObjCXX); + } + return m_language_options_ap.get(); } -SelectorTable * -ClangASTContext::getSelectorTable() -{ - if (m_selector_table_ap.get() == nullptr) - m_selector_table_ap.reset (new SelectorTable()); - return m_selector_table_ap.get(); +SelectorTable *ClangASTContext::getSelectorTable() { + if (m_selector_table_ap.get() == nullptr) + m_selector_table_ap.reset(new SelectorTable()); + return m_selector_table_ap.get(); } -clang::FileManager * -ClangASTContext::getFileManager() -{ - if (m_file_manager_ap.get() == nullptr) - { - clang::FileSystemOptions file_system_options; - m_file_manager_ap.reset(new clang::FileManager(file_system_options)); - } - return m_file_manager_ap.get(); +clang::FileManager *ClangASTContext::getFileManager() { + if (m_file_manager_ap.get() == nullptr) { + clang::FileSystemOptions file_system_options; + m_file_manager_ap.reset(new clang::FileManager(file_system_options)); + } + return m_file_manager_ap.get(); } -clang::SourceManager * -ClangASTContext::getSourceManager() -{ - if (m_source_manager_ap.get() == nullptr) - m_source_manager_ap.reset(new clang::SourceManager(*getDiagnosticsEngine(), *getFileManager())); - return m_source_manager_ap.get(); +clang::SourceManager *ClangASTContext::getSourceManager() { + if (m_source_manager_ap.get() == nullptr) + m_source_manager_ap.reset( + new clang::SourceManager(*getDiagnosticsEngine(), *getFileManager())); + return m_source_manager_ap.get(); } -clang::DiagnosticsEngine * -ClangASTContext::getDiagnosticsEngine() -{ - if (m_diagnostics_engine_ap.get() == nullptr) - { - llvm::IntrusiveRefCntPtr<DiagnosticIDs> diag_id_sp(new DiagnosticIDs()); - m_diagnostics_engine_ap.reset(new DiagnosticsEngine(diag_id_sp, new DiagnosticOptions())); - } - return m_diagnostics_engine_ap.get(); +clang::DiagnosticsEngine *ClangASTContext::getDiagnosticsEngine() { + if (m_diagnostics_engine_ap.get() == nullptr) { + llvm::IntrusiveRefCntPtr<DiagnosticIDs> diag_id_sp(new DiagnosticIDs()); + m_diagnostics_engine_ap.reset( + new DiagnosticsEngine(diag_id_sp, new DiagnosticOptions())); + } + return m_diagnostics_engine_ap.get(); } -clang::MangleContext * -ClangASTContext::getMangleContext() -{ - if (m_mangle_ctx_ap.get() == nullptr) - m_mangle_ctx_ap.reset (getASTContext()->createMangleContext()); - return m_mangle_ctx_ap.get(); +clang::MangleContext *ClangASTContext::getMangleContext() { + if (m_mangle_ctx_ap.get() == nullptr) + m_mangle_ctx_ap.reset(getASTContext()->createMangleContext()); + return m_mangle_ctx_ap.get(); } -class NullDiagnosticConsumer : public DiagnosticConsumer -{ +class NullDiagnosticConsumer : public DiagnosticConsumer { public: - NullDiagnosticConsumer () - { - m_log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS); - } - - void - HandleDiagnostic(DiagnosticsEngine::Level DiagLevel, const clang::Diagnostic &info) - { - if (m_log) - { - llvm::SmallVector<char, 32> diag_str(10); - info.FormatDiagnostic(diag_str); - diag_str.push_back('\0'); - m_log->Printf("Compiler diagnostic: %s\n", diag_str.data()); - } - } - - DiagnosticConsumer *clone (DiagnosticsEngine &Diags) const - { - return new NullDiagnosticConsumer (); + NullDiagnosticConsumer() { + m_log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS); + } + + void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel, + const clang::Diagnostic &info) { + if (m_log) { + llvm::SmallVector<char, 32> diag_str(10); + info.FormatDiagnostic(diag_str); + diag_str.push_back('\0'); + m_log->Printf("Compiler diagnostic: %s\n", diag_str.data()); } + } + + DiagnosticConsumer *clone(DiagnosticsEngine &Diags) const { + return new NullDiagnosticConsumer(); + } + private: - Log * m_log; + Log *m_log; }; -DiagnosticConsumer * -ClangASTContext::getDiagnosticConsumer() -{ - if (m_diagnostic_consumer_ap.get() == nullptr) - m_diagnostic_consumer_ap.reset(new NullDiagnosticConsumer); - - return m_diagnostic_consumer_ap.get(); -} +DiagnosticConsumer *ClangASTContext::getDiagnosticConsumer() { + if (m_diagnostic_consumer_ap.get() == nullptr) + m_diagnostic_consumer_ap.reset(new NullDiagnosticConsumer); -std::shared_ptr<clang::TargetOptions> & -ClangASTContext::getTargetOptions() { - if (m_target_options_rp.get() == nullptr && !m_target_triple.empty()) - { - m_target_options_rp = std::make_shared<clang::TargetOptions>(); - if (m_target_options_rp.get() != nullptr) - m_target_options_rp->Triple = m_target_triple; - } - return m_target_options_rp; + return m_diagnostic_consumer_ap.get(); } +std::shared_ptr<clang::TargetOptions> &ClangASTContext::getTargetOptions() { + if (m_target_options_rp.get() == nullptr && !m_target_triple.empty()) { + m_target_options_rp = std::make_shared<clang::TargetOptions>(); + if (m_target_options_rp.get() != nullptr) + m_target_options_rp->Triple = m_target_triple; + } + return m_target_options_rp; +} -TargetInfo * -ClangASTContext::getTargetInfo() -{ - // target_triple should be something like "x86_64-apple-macosx" - if (m_target_info_ap.get() == nullptr && !m_target_triple.empty()) - m_target_info_ap.reset (TargetInfo::CreateTargetInfo(*getDiagnosticsEngine(), getTargetOptions())); - return m_target_info_ap.get(); +TargetInfo *ClangASTContext::getTargetInfo() { + // target_triple should be something like "x86_64-apple-macosx" + if (m_target_info_ap.get() == nullptr && !m_target_triple.empty()) + m_target_info_ap.reset(TargetInfo::CreateTargetInfo(*getDiagnosticsEngine(), + getTargetOptions())); + return m_target_info_ap.get(); } #pragma mark Basic Types -static inline bool -QualTypeMatchesBitSize(const uint64_t bit_size, ASTContext *ast, QualType qual_type) -{ - uint64_t qual_type_bit_size = ast->getTypeSize(qual_type); - if (qual_type_bit_size == bit_size) - return true; - return false; +static inline bool QualTypeMatchesBitSize(const uint64_t bit_size, + ASTContext *ast, QualType qual_type) { + uint64_t qual_type_bit_size = ast->getTypeSize(qual_type); + if (qual_type_bit_size == bit_size) + return true; + return false; } CompilerType -ClangASTContext::GetBuiltinTypeForEncodingAndBitSize (Encoding encoding, size_t bit_size) -{ - return ClangASTContext::GetBuiltinTypeForEncodingAndBitSize (getASTContext(), encoding, bit_size); +ClangASTContext::GetBuiltinTypeForEncodingAndBitSize(Encoding encoding, + size_t bit_size) { + return ClangASTContext::GetBuiltinTypeForEncodingAndBitSize( + getASTContext(), encoding, bit_size); } -CompilerType -ClangASTContext::GetBuiltinTypeForEncodingAndBitSize (ASTContext *ast, Encoding encoding, uint32_t bit_size) -{ - if (!ast) - return CompilerType(); - switch (encoding) - { - case eEncodingInvalid: - if (QualTypeMatchesBitSize (bit_size, ast, ast->VoidPtrTy)) - return CompilerType (ast, ast->VoidPtrTy); - break; - - case eEncodingUint: - if (QualTypeMatchesBitSize (bit_size, ast, ast->UnsignedCharTy)) - return CompilerType (ast, ast->UnsignedCharTy); - if (QualTypeMatchesBitSize (bit_size, ast, ast->UnsignedShortTy)) - return CompilerType (ast, ast->UnsignedShortTy); - if (QualTypeMatchesBitSize (bit_size, ast, ast->UnsignedIntTy)) - return CompilerType (ast, ast->UnsignedIntTy); - if (QualTypeMatchesBitSize (bit_size, ast, ast->UnsignedLongTy)) - return CompilerType (ast, ast->UnsignedLongTy); - if (QualTypeMatchesBitSize (bit_size, ast, ast->UnsignedLongLongTy)) - return CompilerType (ast, ast->UnsignedLongLongTy); - if (QualTypeMatchesBitSize (bit_size, ast, ast->UnsignedInt128Ty)) - return CompilerType (ast, ast->UnsignedInt128Ty); - break; - - case eEncodingSint: - if (QualTypeMatchesBitSize (bit_size, ast, ast->SignedCharTy)) - return CompilerType (ast, ast->SignedCharTy); - if (QualTypeMatchesBitSize (bit_size, ast, ast->ShortTy)) - return CompilerType (ast, ast->ShortTy); - if (QualTypeMatchesBitSize (bit_size, ast, ast->IntTy)) - return CompilerType (ast, ast->IntTy); - if (QualTypeMatchesBitSize (bit_size, ast, ast->LongTy)) - return CompilerType (ast, ast->LongTy); - if (QualTypeMatchesBitSize (bit_size, ast, ast->LongLongTy)) - return CompilerType (ast, ast->LongLongTy); - if (QualTypeMatchesBitSize (bit_size, ast, ast->Int128Ty)) - return CompilerType (ast, ast->Int128Ty); - break; - - case eEncodingIEEE754: - if (QualTypeMatchesBitSize (bit_size, ast, ast->FloatTy)) - return CompilerType (ast, ast->FloatTy); - if (QualTypeMatchesBitSize (bit_size, ast, ast->DoubleTy)) - return CompilerType (ast, ast->DoubleTy); - if (QualTypeMatchesBitSize (bit_size, ast, ast->LongDoubleTy)) - return CompilerType (ast, ast->LongDoubleTy); - if (QualTypeMatchesBitSize (bit_size, ast, ast->HalfTy)) - return CompilerType (ast, ast->HalfTy); - break; - - case eEncodingVector: - // Sanity check that bit_size is a multiple of 8's. - if (bit_size && !(bit_size & 0x7u)) - return CompilerType (ast, ast->getExtVectorType (ast->UnsignedCharTy, bit_size/8)); - break; - } - +CompilerType ClangASTContext::GetBuiltinTypeForEncodingAndBitSize( + ASTContext *ast, Encoding encoding, uint32_t bit_size) { + if (!ast) return CompilerType(); + switch (encoding) { + case eEncodingInvalid: + if (QualTypeMatchesBitSize(bit_size, ast, ast->VoidPtrTy)) + return CompilerType(ast, ast->VoidPtrTy); + break; + + case eEncodingUint: + if (QualTypeMatchesBitSize(bit_size, ast, ast->UnsignedCharTy)) + return CompilerType(ast, ast->UnsignedCharTy); + if (QualTypeMatchesBitSize(bit_size, ast, ast->UnsignedShortTy)) + return CompilerType(ast, ast->UnsignedShortTy); + if (QualTypeMatchesBitSize(bit_size, ast, ast->UnsignedIntTy)) + return CompilerType(ast, ast->UnsignedIntTy); + if (QualTypeMatchesBitSize(bit_size, ast, ast->UnsignedLongTy)) + return CompilerType(ast, ast->UnsignedLongTy); + if (QualTypeMatchesBitSize(bit_size, ast, ast->UnsignedLongLongTy)) + return CompilerType(ast, ast->UnsignedLongLongTy); + if (QualTypeMatchesBitSize(bit_size, ast, ast->UnsignedInt128Ty)) + return CompilerType(ast, ast->UnsignedInt128Ty); + break; + + case eEncodingSint: + if (QualTypeMatchesBitSize(bit_size, ast, ast->SignedCharTy)) + return CompilerType(ast, ast->SignedCharTy); + if (QualTypeMatchesBitSize(bit_size, ast, ast->ShortTy)) + return CompilerType(ast, ast->ShortTy); + if (QualTypeMatchesBitSize(bit_size, ast, ast->IntTy)) + return CompilerType(ast, ast->IntTy); + if (QualTypeMatchesBitSize(bit_size, ast, ast->LongTy)) + return CompilerType(ast, ast->LongTy); + if (QualTypeMatchesBitSize(bit_size, ast, ast->LongLongTy)) + return CompilerType(ast, ast->LongLongTy); + if (QualTypeMatchesBitSize(bit_size, ast, ast->Int128Ty)) + return CompilerType(ast, ast->Int128Ty); + break; + + case eEncodingIEEE754: + if (QualTypeMatchesBitSize(bit_size, ast, ast->FloatTy)) + return CompilerType(ast, ast->FloatTy); + if (QualTypeMatchesBitSize(bit_size, ast, ast->DoubleTy)) + return CompilerType(ast, ast->DoubleTy); + if (QualTypeMatchesBitSize(bit_size, ast, ast->LongDoubleTy)) + return CompilerType(ast, ast->LongDoubleTy); + if (QualTypeMatchesBitSize(bit_size, ast, ast->HalfTy)) + return CompilerType(ast, ast->HalfTy); + break; + + case eEncodingVector: + // Sanity check that bit_size is a multiple of 8's. + if (bit_size && !(bit_size & 0x7u)) + return CompilerType( + ast, ast->getExtVectorType(ast->UnsignedCharTy, bit_size / 8)); + break; + } + + return CompilerType(); } - - lldb::BasicType -ClangASTContext::GetBasicTypeEnumeration (const ConstString &name) -{ - if (name) - { - typedef UniqueCStringMap<lldb::BasicType> TypeNameToBasicTypeMap; - static TypeNameToBasicTypeMap g_type_map; - static std::once_flag g_once_flag; - std::call_once(g_once_flag, [](){ - // "void" - g_type_map.Append(ConstString("void").GetCString(), eBasicTypeVoid); - - // "char" - g_type_map.Append(ConstString("char").GetCString(), eBasicTypeChar); - g_type_map.Append(ConstString("signed char").GetCString(), eBasicTypeSignedChar); - g_type_map.Append(ConstString("unsigned char").GetCString(), eBasicTypeUnsignedChar); - g_type_map.Append(ConstString("wchar_t").GetCString(), eBasicTypeWChar); - g_type_map.Append(ConstString("signed wchar_t").GetCString(), eBasicTypeSignedWChar); - g_type_map.Append(ConstString("unsigned wchar_t").GetCString(), eBasicTypeUnsignedWChar); - // "short" - g_type_map.Append(ConstString("short").GetCString(), eBasicTypeShort); - g_type_map.Append(ConstString("short int").GetCString(), eBasicTypeShort); - g_type_map.Append(ConstString("unsigned short").GetCString(), eBasicTypeUnsignedShort); - g_type_map.Append(ConstString("unsigned short int").GetCString(), eBasicTypeUnsignedShort); - - // "int" - g_type_map.Append(ConstString("int").GetCString(), eBasicTypeInt); - g_type_map.Append(ConstString("signed int").GetCString(), eBasicTypeInt); - g_type_map.Append(ConstString("unsigned int").GetCString(), eBasicTypeUnsignedInt); - g_type_map.Append(ConstString("unsigned").GetCString(), eBasicTypeUnsignedInt); - - // "long" - g_type_map.Append(ConstString("long").GetCString(), eBasicTypeLong); - g_type_map.Append(ConstString("long int").GetCString(), eBasicTypeLong); - g_type_map.Append(ConstString("unsigned long").GetCString(), eBasicTypeUnsignedLong); - g_type_map.Append(ConstString("unsigned long int").GetCString(), eBasicTypeUnsignedLong); - - // "long long" - g_type_map.Append(ConstString("long long").GetCString(), eBasicTypeLongLong); - g_type_map.Append(ConstString("long long int").GetCString(), eBasicTypeLongLong); - g_type_map.Append(ConstString("unsigned long long").GetCString(), eBasicTypeUnsignedLongLong); - g_type_map.Append(ConstString("unsigned long long int").GetCString(), eBasicTypeUnsignedLongLong); - - // "int128" - g_type_map.Append(ConstString("__int128_t").GetCString(), eBasicTypeInt128); - g_type_map.Append(ConstString("__uint128_t").GetCString(), eBasicTypeUnsignedInt128); - - // Miscellaneous - g_type_map.Append(ConstString("bool").GetCString(), eBasicTypeBool); - g_type_map.Append(ConstString("float").GetCString(), eBasicTypeFloat); - g_type_map.Append(ConstString("double").GetCString(), eBasicTypeDouble); - g_type_map.Append(ConstString("long double").GetCString(), eBasicTypeLongDouble); - g_type_map.Append(ConstString("id").GetCString(), eBasicTypeObjCID); - g_type_map.Append(ConstString("SEL").GetCString(), eBasicTypeObjCSel); - g_type_map.Append(ConstString("nullptr").GetCString(), eBasicTypeNullPtr); - g_type_map.Sort(); - }); - - return g_type_map.Find(name.GetCString(), eBasicTypeInvalid); - } - return eBasicTypeInvalid; -} +ClangASTContext::GetBasicTypeEnumeration(const ConstString &name) { + if (name) { + typedef UniqueCStringMap<lldb::BasicType> TypeNameToBasicTypeMap; + static TypeNameToBasicTypeMap g_type_map; + static std::once_flag g_once_flag; + std::call_once(g_once_flag, []() { + // "void" + g_type_map.Append(ConstString("void").GetCString(), eBasicTypeVoid); + + // "char" + g_type_map.Append(ConstString("char").GetCString(), eBasicTypeChar); + g_type_map.Append(ConstString("signed char").GetCString(), + eBasicTypeSignedChar); + g_type_map.Append(ConstString("unsigned char").GetCString(), + eBasicTypeUnsignedChar); + g_type_map.Append(ConstString("wchar_t").GetCString(), eBasicTypeWChar); + g_type_map.Append(ConstString("signed wchar_t").GetCString(), + eBasicTypeSignedWChar); + g_type_map.Append(ConstString("unsigned wchar_t").GetCString(), + eBasicTypeUnsignedWChar); + // "short" + g_type_map.Append(ConstString("short").GetCString(), eBasicTypeShort); + g_type_map.Append(ConstString("short int").GetCString(), eBasicTypeShort); + g_type_map.Append(ConstString("unsigned short").GetCString(), + eBasicTypeUnsignedShort); + g_type_map.Append(ConstString("unsigned short int").GetCString(), + eBasicTypeUnsignedShort); + + // "int" + g_type_map.Append(ConstString("int").GetCString(), eBasicTypeInt); + g_type_map.Append(ConstString("signed int").GetCString(), eBasicTypeInt); + g_type_map.Append(ConstString("unsigned int").GetCString(), + eBasicTypeUnsignedInt); + g_type_map.Append(ConstString("unsigned").GetCString(), + eBasicTypeUnsignedInt); + + // "long" + g_type_map.Append(ConstString("long").GetCString(), eBasicTypeLong); + g_type_map.Append(ConstString("long int").GetCString(), eBasicTypeLong); + g_type_map.Append(ConstString("unsigned long").GetCString(), + eBasicTypeUnsignedLong); + g_type_map.Append(ConstString("unsigned long int").GetCString(), + eBasicTypeUnsignedLong); + + // "long long" + g_type_map.Append(ConstString("long long").GetCString(), + eBasicTypeLongLong); + g_type_map.Append(ConstString("long long int").GetCString(), + eBasicTypeLongLong); + g_type_map.Append(ConstString("unsigned long long").GetCString(), + eBasicTypeUnsignedLongLong); + g_type_map.Append(ConstString("unsigned long long int").GetCString(), + eBasicTypeUnsignedLongLong); + + // "int128" + g_type_map.Append(ConstString("__int128_t").GetCString(), + eBasicTypeInt128); + g_type_map.Append(ConstString("__uint128_t").GetCString(), + eBasicTypeUnsignedInt128); + + // Miscellaneous + g_type_map.Append(ConstString("bool").GetCString(), eBasicTypeBool); + g_type_map.Append(ConstString("float").GetCString(), eBasicTypeFloat); + g_type_map.Append(ConstString("double").GetCString(), eBasicTypeDouble); + g_type_map.Append(ConstString("long double").GetCString(), + eBasicTypeLongDouble); + g_type_map.Append(ConstString("id").GetCString(), eBasicTypeObjCID); + g_type_map.Append(ConstString("SEL").GetCString(), eBasicTypeObjCSel); + g_type_map.Append(ConstString("nullptr").GetCString(), eBasicTypeNullPtr); + g_type_map.Sort(); + }); -CompilerType -ClangASTContext::GetBasicType (ASTContext *ast, const ConstString &name) -{ - if (ast) - { - lldb::BasicType basic_type = ClangASTContext::GetBasicTypeEnumeration (name); - return ClangASTContext::GetBasicType (ast, basic_type); - } - return CompilerType(); + return g_type_map.Find(name.GetCString(), eBasicTypeInvalid); + } + return eBasicTypeInvalid; } -uint32_t -ClangASTContext::GetPointerByteSize () -{ - if (m_pointer_byte_size == 0) - m_pointer_byte_size = GetBasicType(lldb::eBasicTypeVoid).GetPointerType().GetByteSize(nullptr); - return m_pointer_byte_size; +CompilerType ClangASTContext::GetBasicType(ASTContext *ast, + const ConstString &name) { + if (ast) { + lldb::BasicType basic_type = ClangASTContext::GetBasicTypeEnumeration(name); + return ClangASTContext::GetBasicType(ast, basic_type); + } + return CompilerType(); } -CompilerType -ClangASTContext::GetBasicType (lldb::BasicType basic_type) -{ - return GetBasicType (getASTContext(), basic_type); +uint32_t ClangASTContext::GetPointerByteSize() { + if (m_pointer_byte_size == 0) + m_pointer_byte_size = GetBasicType(lldb::eBasicTypeVoid) + .GetPointerType() + .GetByteSize(nullptr); + return m_pointer_byte_size; } -CompilerType -ClangASTContext::GetBasicType (ASTContext *ast, lldb::BasicType basic_type) -{ - if (!ast) - return CompilerType(); - lldb::opaque_compiler_type_t clang_type = GetOpaqueCompilerType(ast, basic_type); - - if (clang_type) - return CompilerType(GetASTContext(ast), clang_type); - return CompilerType(); +CompilerType ClangASTContext::GetBasicType(lldb::BasicType basic_type) { + return GetBasicType(getASTContext(), basic_type); } +CompilerType ClangASTContext::GetBasicType(ASTContext *ast, + lldb::BasicType basic_type) { + if (!ast) + return CompilerType(); + lldb::opaque_compiler_type_t clang_type = + GetOpaqueCompilerType(ast, basic_type); -CompilerType -ClangASTContext::GetBuiltinTypeForDWARFEncodingAndBitSize (const char *type_name, uint32_t dw_ate, uint32_t bit_size) -{ - ASTContext *ast = getASTContext(); - -#define streq(a,b) strcmp(a,b) == 0 - assert (ast != nullptr); - if (ast) - { - switch (dw_ate) - { - default: - break; - - case DW_ATE_address: - if (QualTypeMatchesBitSize (bit_size, ast, ast->VoidPtrTy)) - return CompilerType (ast, ast->VoidPtrTy); - break; - - case DW_ATE_boolean: - if (QualTypeMatchesBitSize (bit_size, ast, ast->BoolTy)) - return CompilerType (ast, ast->BoolTy); - if (QualTypeMatchesBitSize (bit_size, ast, ast->UnsignedCharTy)) - return CompilerType (ast, ast->UnsignedCharTy); - if (QualTypeMatchesBitSize (bit_size, ast, ast->UnsignedShortTy)) - return CompilerType (ast, ast->UnsignedShortTy); - if (QualTypeMatchesBitSize (bit_size, ast, ast->UnsignedIntTy)) - return CompilerType (ast, ast->UnsignedIntTy); - break; - - case DW_ATE_lo_user: - // This has been seen to mean DW_AT_complex_integer - if (type_name) - { - if (::strstr(type_name, "complex")) - { - CompilerType complex_int_clang_type = GetBuiltinTypeForDWARFEncodingAndBitSize ("int", DW_ATE_signed, bit_size/2); - return CompilerType(ast, ast->getComplexType(ClangUtil::GetQualType(complex_int_clang_type))); - } - } - break; - - case DW_ATE_complex_float: - if (QualTypeMatchesBitSize (bit_size, ast, ast->FloatComplexTy)) - return CompilerType (ast, ast->FloatComplexTy); - else if (QualTypeMatchesBitSize (bit_size, ast, ast->DoubleComplexTy)) - return CompilerType (ast, ast->DoubleComplexTy); - else if (QualTypeMatchesBitSize (bit_size, ast, ast->LongDoubleComplexTy)) - return CompilerType (ast, ast->LongDoubleComplexTy); - else - { - CompilerType complex_float_clang_type = GetBuiltinTypeForDWARFEncodingAndBitSize ("float", DW_ATE_float, bit_size/2); - return CompilerType(ast, ast->getComplexType(ClangUtil::GetQualType(complex_float_clang_type))); - } - break; - - case DW_ATE_float: - if (streq(type_name, "float") && QualTypeMatchesBitSize (bit_size, ast, ast->FloatTy)) - return CompilerType (ast, ast->FloatTy); - if (streq(type_name, "double") && QualTypeMatchesBitSize (bit_size, ast, ast->DoubleTy)) - return CompilerType (ast, ast->DoubleTy); - if (streq(type_name, "long double") && QualTypeMatchesBitSize (bit_size, ast, ast->LongDoubleTy)) - return CompilerType (ast, ast->LongDoubleTy); - // Fall back to not requiring a name match - if (QualTypeMatchesBitSize (bit_size, ast, ast->FloatTy)) - return CompilerType (ast, ast->FloatTy); - if (QualTypeMatchesBitSize (bit_size, ast, ast->DoubleTy)) - return CompilerType (ast, ast->DoubleTy); - if (QualTypeMatchesBitSize (bit_size, ast, ast->LongDoubleTy)) - return CompilerType (ast, ast->LongDoubleTy); - if (QualTypeMatchesBitSize (bit_size, ast, ast->HalfTy)) - return CompilerType (ast, ast->HalfTy); - break; - - case DW_ATE_signed: - if (type_name) - { - if (streq(type_name, "wchar_t") && - QualTypeMatchesBitSize (bit_size, ast, ast->WCharTy) && - (getTargetInfo() && TargetInfo::isTypeSigned (getTargetInfo()->getWCharType()))) - return CompilerType (ast, ast->WCharTy); - if (streq(type_name, "void") && - QualTypeMatchesBitSize (bit_size, ast, ast->VoidTy)) - return CompilerType (ast, ast->VoidTy); - if (strstr(type_name, "long long") && - QualTypeMatchesBitSize (bit_size, ast, ast->LongLongTy)) - return CompilerType (ast, ast->LongLongTy); - if (strstr(type_name, "long") && - QualTypeMatchesBitSize (bit_size, ast, ast->LongTy)) - return CompilerType (ast, ast->LongTy); - if (strstr(type_name, "short") && - QualTypeMatchesBitSize (bit_size, ast, ast->ShortTy)) - return CompilerType (ast, ast->ShortTy); - if (strstr(type_name, "char")) - { - if (QualTypeMatchesBitSize (bit_size, ast, ast->CharTy)) - return CompilerType (ast, ast->CharTy); - if (QualTypeMatchesBitSize (bit_size, ast, ast->SignedCharTy)) - return CompilerType (ast, ast->SignedCharTy); - } - if (strstr(type_name, "int")) - { - if (QualTypeMatchesBitSize (bit_size, ast, ast->IntTy)) - return CompilerType (ast, ast->IntTy); - if (QualTypeMatchesBitSize (bit_size, ast, ast->Int128Ty)) - return CompilerType (ast, ast->Int128Ty); - } - } - // We weren't able to match up a type name, just search by size - if (QualTypeMatchesBitSize (bit_size, ast, ast->CharTy)) - return CompilerType (ast, ast->CharTy); - if (QualTypeMatchesBitSize (bit_size, ast, ast->ShortTy)) - return CompilerType (ast, ast->ShortTy); - if (QualTypeMatchesBitSize (bit_size, ast, ast->IntTy)) - return CompilerType (ast, ast->IntTy); - if (QualTypeMatchesBitSize (bit_size, ast, ast->LongTy)) - return CompilerType (ast, ast->LongTy); - if (QualTypeMatchesBitSize (bit_size, ast, ast->LongLongTy)) - return CompilerType (ast, ast->LongLongTy); - if (QualTypeMatchesBitSize (bit_size, ast, ast->Int128Ty)) - return CompilerType (ast, ast->Int128Ty); - break; + if (clang_type) + return CompilerType(GetASTContext(ast), clang_type); + return CompilerType(); +} - case DW_ATE_signed_char: - if (ast->getLangOpts().CharIsSigned && type_name && streq(type_name, "char")) - { - if (QualTypeMatchesBitSize (bit_size, ast, ast->CharTy)) - return CompilerType (ast, ast->CharTy); - } - if (QualTypeMatchesBitSize (bit_size, ast, ast->SignedCharTy)) - return CompilerType (ast, ast->SignedCharTy); - break; - - case DW_ATE_unsigned: - if (type_name) - { - if (streq(type_name, "wchar_t")) - { - if (QualTypeMatchesBitSize (bit_size, ast, ast->WCharTy)) - { - if (!(getTargetInfo() && TargetInfo::isTypeSigned (getTargetInfo()->getWCharType()))) - return CompilerType (ast, ast->WCharTy); - } - } - if (strstr(type_name, "long long")) - { - if (QualTypeMatchesBitSize (bit_size, ast, ast->UnsignedLongLongTy)) - return CompilerType (ast, ast->UnsignedLongLongTy); - } - else if (strstr(type_name, "long")) - { - if (QualTypeMatchesBitSize (bit_size, ast, ast->UnsignedLongTy)) - return CompilerType (ast, ast->UnsignedLongTy); - } - else if (strstr(type_name, "short")) - { - if (QualTypeMatchesBitSize (bit_size, ast, ast->UnsignedShortTy)) - return CompilerType (ast, ast->UnsignedShortTy); - } - else if (strstr(type_name, "char")) - { - if (QualTypeMatchesBitSize (bit_size, ast, ast->UnsignedCharTy)) - return CompilerType (ast, ast->UnsignedCharTy); - } - else if (strstr(type_name, "int")) - { - if (QualTypeMatchesBitSize (bit_size, ast, ast->UnsignedIntTy)) - return CompilerType (ast, ast->UnsignedIntTy); - if (QualTypeMatchesBitSize (bit_size, ast, ast->UnsignedInt128Ty)) - return CompilerType (ast, ast->UnsignedInt128Ty); - } - } - // We weren't able to match up a type name, just search by size - if (QualTypeMatchesBitSize (bit_size, ast, ast->UnsignedCharTy)) - return CompilerType (ast, ast->UnsignedCharTy); - if (QualTypeMatchesBitSize (bit_size, ast, ast->UnsignedShortTy)) - return CompilerType (ast, ast->UnsignedShortTy); - if (QualTypeMatchesBitSize (bit_size, ast, ast->UnsignedIntTy)) - return CompilerType (ast, ast->UnsignedIntTy); - if (QualTypeMatchesBitSize (bit_size, ast, ast->UnsignedLongTy)) - return CompilerType (ast, ast->UnsignedLongTy); - if (QualTypeMatchesBitSize (bit_size, ast, ast->UnsignedLongLongTy)) - return CompilerType (ast, ast->UnsignedLongLongTy); - if (QualTypeMatchesBitSize (bit_size, ast, ast->UnsignedInt128Ty)) - return CompilerType (ast, ast->UnsignedInt128Ty); - break; +CompilerType ClangASTContext::GetBuiltinTypeForDWARFEncodingAndBitSize( + const char *type_name, uint32_t dw_ate, uint32_t bit_size) { + ASTContext *ast = getASTContext(); - case DW_ATE_unsigned_char: - if (!ast->getLangOpts().CharIsSigned && type_name && streq(type_name, "char")) - { - if (QualTypeMatchesBitSize (bit_size, ast, ast->CharTy)) - return CompilerType (ast, ast->CharTy); - } - if (QualTypeMatchesBitSize (bit_size, ast, ast->UnsignedCharTy)) - return CompilerType (ast, ast->UnsignedCharTy); - if (QualTypeMatchesBitSize (bit_size, ast, ast->UnsignedShortTy)) - return CompilerType (ast, ast->UnsignedShortTy); - break; - - case DW_ATE_imaginary_float: - break; - - case DW_ATE_UTF: - if (type_name) - { - if (streq(type_name, "char16_t")) - { - return CompilerType (ast, ast->Char16Ty); - } - else if (streq(type_name, "char32_t")) - { - return CompilerType (ast, ast->Char32Ty); - } - } - break; +#define streq(a, b) strcmp(a, b) == 0 + assert(ast != nullptr); + if (ast) { + switch (dw_ate) { + default: + break; + + case DW_ATE_address: + if (QualTypeMatchesBitSize(bit_size, ast, ast->VoidPtrTy)) + return CompilerType(ast, ast->VoidPtrTy); + break; + + case DW_ATE_boolean: + if (QualTypeMatchesBitSize(bit_size, ast, ast->BoolTy)) + return CompilerType(ast, ast->BoolTy); + if (QualTypeMatchesBitSize(bit_size, ast, ast->UnsignedCharTy)) + return CompilerType(ast, ast->UnsignedCharTy); + if (QualTypeMatchesBitSize(bit_size, ast, ast->UnsignedShortTy)) + return CompilerType(ast, ast->UnsignedShortTy); + if (QualTypeMatchesBitSize(bit_size, ast, ast->UnsignedIntTy)) + return CompilerType(ast, ast->UnsignedIntTy); + break; + + case DW_ATE_lo_user: + // This has been seen to mean DW_AT_complex_integer + if (type_name) { + if (::strstr(type_name, "complex")) { + CompilerType complex_int_clang_type = + GetBuiltinTypeForDWARFEncodingAndBitSize("int", DW_ATE_signed, + bit_size / 2); + return CompilerType(ast, ast->getComplexType(ClangUtil::GetQualType( + complex_int_clang_type))); } + } + break; + + case DW_ATE_complex_float: + if (QualTypeMatchesBitSize(bit_size, ast, ast->FloatComplexTy)) + return CompilerType(ast, ast->FloatComplexTy); + else if (QualTypeMatchesBitSize(bit_size, ast, ast->DoubleComplexTy)) + return CompilerType(ast, ast->DoubleComplexTy); + else if (QualTypeMatchesBitSize(bit_size, ast, ast->LongDoubleComplexTy)) + return CompilerType(ast, ast->LongDoubleComplexTy); + else { + CompilerType complex_float_clang_type = + GetBuiltinTypeForDWARFEncodingAndBitSize("float", DW_ATE_float, + bit_size / 2); + return CompilerType(ast, ast->getComplexType(ClangUtil::GetQualType( + complex_float_clang_type))); + } + break; + + case DW_ATE_float: + if (streq(type_name, "float") && + QualTypeMatchesBitSize(bit_size, ast, ast->FloatTy)) + return CompilerType(ast, ast->FloatTy); + if (streq(type_name, "double") && + QualTypeMatchesBitSize(bit_size, ast, ast->DoubleTy)) + return CompilerType(ast, ast->DoubleTy); + if (streq(type_name, "long double") && + QualTypeMatchesBitSize(bit_size, ast, ast->LongDoubleTy)) + return CompilerType(ast, ast->LongDoubleTy); + // Fall back to not requiring a name match + if (QualTypeMatchesBitSize(bit_size, ast, ast->FloatTy)) + return CompilerType(ast, ast->FloatTy); + if (QualTypeMatchesBitSize(bit_size, ast, ast->DoubleTy)) + return CompilerType(ast, ast->DoubleTy); + if (QualTypeMatchesBitSize(bit_size, ast, ast->LongDoubleTy)) + return CompilerType(ast, ast->LongDoubleTy); + if (QualTypeMatchesBitSize(bit_size, ast, ast->HalfTy)) + return CompilerType(ast, ast->HalfTy); + break; + + case DW_ATE_signed: + if (type_name) { + if (streq(type_name, "wchar_t") && + QualTypeMatchesBitSize(bit_size, ast, ast->WCharTy) && + (getTargetInfo() && + TargetInfo::isTypeSigned(getTargetInfo()->getWCharType()))) + return CompilerType(ast, ast->WCharTy); + if (streq(type_name, "void") && + QualTypeMatchesBitSize(bit_size, ast, ast->VoidTy)) + return CompilerType(ast, ast->VoidTy); + if (strstr(type_name, "long long") && + QualTypeMatchesBitSize(bit_size, ast, ast->LongLongTy)) + return CompilerType(ast, ast->LongLongTy); + if (strstr(type_name, "long") && + QualTypeMatchesBitSize(bit_size, ast, ast->LongTy)) + return CompilerType(ast, ast->LongTy); + if (strstr(type_name, "short") && + QualTypeMatchesBitSize(bit_size, ast, ast->ShortTy)) + return CompilerType(ast, ast->ShortTy); + if (strstr(type_name, "char")) { + if (QualTypeMatchesBitSize(bit_size, ast, ast->CharTy)) + return CompilerType(ast, ast->CharTy); + if (QualTypeMatchesBitSize(bit_size, ast, ast->SignedCharTy)) + return CompilerType(ast, ast->SignedCharTy); + } + if (strstr(type_name, "int")) { + if (QualTypeMatchesBitSize(bit_size, ast, ast->IntTy)) + return CompilerType(ast, ast->IntTy); + if (QualTypeMatchesBitSize(bit_size, ast, ast->Int128Ty)) + return CompilerType(ast, ast->Int128Ty); + } + } + // We weren't able to match up a type name, just search by size + if (QualTypeMatchesBitSize(bit_size, ast, ast->CharTy)) + return CompilerType(ast, ast->CharTy); + if (QualTypeMatchesBitSize(bit_size, ast, ast->ShortTy)) + return CompilerType(ast, ast->ShortTy); + if (QualTypeMatchesBitSize(bit_size, ast, ast->IntTy)) + return CompilerType(ast, ast->IntTy); + if (QualTypeMatchesBitSize(bit_size, ast, ast->LongTy)) + return CompilerType(ast, ast->LongTy); + if (QualTypeMatchesBitSize(bit_size, ast, ast->LongLongTy)) + return CompilerType(ast, ast->LongLongTy); + if (QualTypeMatchesBitSize(bit_size, ast, ast->Int128Ty)) + return CompilerType(ast, ast->Int128Ty); + break; + + case DW_ATE_signed_char: + if (ast->getLangOpts().CharIsSigned && type_name && + streq(type_name, "char")) { + if (QualTypeMatchesBitSize(bit_size, ast, ast->CharTy)) + return CompilerType(ast, ast->CharTy); + } + if (QualTypeMatchesBitSize(bit_size, ast, ast->SignedCharTy)) + return CompilerType(ast, ast->SignedCharTy); + break; + + case DW_ATE_unsigned: + if (type_name) { + if (streq(type_name, "wchar_t")) { + if (QualTypeMatchesBitSize(bit_size, ast, ast->WCharTy)) { + if (!(getTargetInfo() && + TargetInfo::isTypeSigned(getTargetInfo()->getWCharType()))) + return CompilerType(ast, ast->WCharTy); + } + } + if (strstr(type_name, "long long")) { + if (QualTypeMatchesBitSize(bit_size, ast, ast->UnsignedLongLongTy)) + return CompilerType(ast, ast->UnsignedLongLongTy); + } else if (strstr(type_name, "long")) { + if (QualTypeMatchesBitSize(bit_size, ast, ast->UnsignedLongTy)) + return CompilerType(ast, ast->UnsignedLongTy); + } else if (strstr(type_name, "short")) { + if (QualTypeMatchesBitSize(bit_size, ast, ast->UnsignedShortTy)) + return CompilerType(ast, ast->UnsignedShortTy); + } else if (strstr(type_name, "char")) { + if (QualTypeMatchesBitSize(bit_size, ast, ast->UnsignedCharTy)) + return CompilerType(ast, ast->UnsignedCharTy); + } else if (strstr(type_name, "int")) { + if (QualTypeMatchesBitSize(bit_size, ast, ast->UnsignedIntTy)) + return CompilerType(ast, ast->UnsignedIntTy); + if (QualTypeMatchesBitSize(bit_size, ast, ast->UnsignedInt128Ty)) + return CompilerType(ast, ast->UnsignedInt128Ty); + } + } + // We weren't able to match up a type name, just search by size + if (QualTypeMatchesBitSize(bit_size, ast, ast->UnsignedCharTy)) + return CompilerType(ast, ast->UnsignedCharTy); + if (QualTypeMatchesBitSize(bit_size, ast, ast->UnsignedShortTy)) + return CompilerType(ast, ast->UnsignedShortTy); + if (QualTypeMatchesBitSize(bit_size, ast, ast->UnsignedIntTy)) + return CompilerType(ast, ast->UnsignedIntTy); + if (QualTypeMatchesBitSize(bit_size, ast, ast->UnsignedLongTy)) + return CompilerType(ast, ast->UnsignedLongTy); + if (QualTypeMatchesBitSize(bit_size, ast, ast->UnsignedLongLongTy)) + return CompilerType(ast, ast->UnsignedLongLongTy); + if (QualTypeMatchesBitSize(bit_size, ast, ast->UnsignedInt128Ty)) + return CompilerType(ast, ast->UnsignedInt128Ty); + break; + + case DW_ATE_unsigned_char: + if (!ast->getLangOpts().CharIsSigned && type_name && + streq(type_name, "char")) { + if (QualTypeMatchesBitSize(bit_size, ast, ast->CharTy)) + return CompilerType(ast, ast->CharTy); + } + if (QualTypeMatchesBitSize(bit_size, ast, ast->UnsignedCharTy)) + return CompilerType(ast, ast->UnsignedCharTy); + if (QualTypeMatchesBitSize(bit_size, ast, ast->UnsignedShortTy)) + return CompilerType(ast, ast->UnsignedShortTy); + break; + + case DW_ATE_imaginary_float: + break; + + case DW_ATE_UTF: + if (type_name) { + if (streq(type_name, "char16_t")) { + return CompilerType(ast, ast->Char16Ty); + } else if (streq(type_name, "char32_t")) { + return CompilerType(ast, ast->Char32Ty); + } + } + break; } - // This assert should fire for anything that we don't catch above so we know - // to fix any issues we run into. - if (type_name) - { - Host::SystemLog (Host::eSystemLogError, "error: need to add support for DW_TAG_base_type '%s' encoded with DW_ATE = 0x%x, bit_size = %u\n", type_name, dw_ate, bit_size); - } - else - { - Host::SystemLog (Host::eSystemLogError, "error: need to add support for DW_TAG_base_type encoded with DW_ATE = 0x%x, bit_size = %u\n", dw_ate, bit_size); - } - return CompilerType (); + } + // This assert should fire for anything that we don't catch above so we know + // to fix any issues we run into. + if (type_name) { + Host::SystemLog(Host::eSystemLogError, "error: need to add support for " + "DW_TAG_base_type '%s' encoded with " + "DW_ATE = 0x%x, bit_size = %u\n", + type_name, dw_ate, bit_size); + } else { + Host::SystemLog(Host::eSystemLogError, "error: need to add support for " + "DW_TAG_base_type encoded with " + "DW_ATE = 0x%x, bit_size = %u\n", + dw_ate, bit_size); + } + return CompilerType(); } -CompilerType -ClangASTContext::GetUnknownAnyType(clang::ASTContext *ast) -{ - if (ast) - return CompilerType (ast, ast->UnknownAnyTy); - return CompilerType(); +CompilerType ClangASTContext::GetUnknownAnyType(clang::ASTContext *ast) { + if (ast) + return CompilerType(ast, ast->UnknownAnyTy); + return CompilerType(); } -CompilerType -ClangASTContext::GetCStringType (bool is_const) -{ - ASTContext *ast = getASTContext(); - QualType char_type(ast->CharTy); - - if (is_const) - char_type.addConst(); - - return CompilerType (ast, ast->getPointerType(char_type)); +CompilerType ClangASTContext::GetCStringType(bool is_const) { + ASTContext *ast = getASTContext(); + QualType char_type(ast->CharTy); + + if (is_const) + char_type.addConst(); + + return CompilerType(ast, ast->getPointerType(char_type)); } clang::DeclContext * -ClangASTContext::GetTranslationUnitDecl (clang::ASTContext *ast) -{ - return ast->getTranslationUnitDecl(); -} - -clang::Decl * -ClangASTContext::CopyDecl (ASTContext *dst_ast, - ASTContext *src_ast, - clang::Decl *source_decl) -{ - FileSystemOptions file_system_options; - FileManager file_manager (file_system_options); - ASTImporter importer(*dst_ast, file_manager, - *src_ast, file_manager, - false); - - return importer.Import(source_decl); -} - -bool -ClangASTContext::AreTypesSame (CompilerType type1, - CompilerType type2, - bool ignore_qualifiers) -{ - ClangASTContext *ast = llvm::dyn_cast_or_null<ClangASTContext>(type1.GetTypeSystem()); - if (!ast || ast != type2.GetTypeSystem()) - return false; - - if (type1.GetOpaqueQualType() == type2.GetOpaqueQualType()) - return true; +ClangASTContext::GetTranslationUnitDecl(clang::ASTContext *ast) { + return ast->getTranslationUnitDecl(); +} - QualType type1_qual = ClangUtil::GetQualType(type1); - QualType type2_qual = ClangUtil::GetQualType(type2); +clang::Decl *ClangASTContext::CopyDecl(ASTContext *dst_ast, ASTContext *src_ast, + clang::Decl *source_decl) { + FileSystemOptions file_system_options; + FileManager file_manager(file_system_options); + ASTImporter importer(*dst_ast, file_manager, *src_ast, file_manager, false); - if (ignore_qualifiers) - { - type1_qual = type1_qual.getUnqualifiedType(); - type2_qual = type2_qual.getUnqualifiedType(); - } - - return ast->getASTContext()->hasSameType (type1_qual, type2_qual); + return importer.Import(source_decl); } -CompilerType -ClangASTContext::GetTypeForDecl (clang::NamedDecl *decl) -{ - if (clang::ObjCInterfaceDecl *interface_decl = llvm::dyn_cast<clang::ObjCInterfaceDecl>(decl)) - return GetTypeForDecl(interface_decl); - if (clang::TagDecl *tag_decl = llvm::dyn_cast<clang::TagDecl>(decl)) - return GetTypeForDecl(tag_decl); - return CompilerType(); +bool ClangASTContext::AreTypesSame(CompilerType type1, CompilerType type2, + bool ignore_qualifiers) { + ClangASTContext *ast = + llvm::dyn_cast_or_null<ClangASTContext>(type1.GetTypeSystem()); + if (!ast || ast != type2.GetTypeSystem()) + return false; + + if (type1.GetOpaqueQualType() == type2.GetOpaqueQualType()) + return true; + + QualType type1_qual = ClangUtil::GetQualType(type1); + QualType type2_qual = ClangUtil::GetQualType(type2); + + if (ignore_qualifiers) { + type1_qual = type1_qual.getUnqualifiedType(); + type2_qual = type2_qual.getUnqualifiedType(); + } + + return ast->getASTContext()->hasSameType(type1_qual, type2_qual); } +CompilerType ClangASTContext::GetTypeForDecl(clang::NamedDecl *decl) { + if (clang::ObjCInterfaceDecl *interface_decl = + llvm::dyn_cast<clang::ObjCInterfaceDecl>(decl)) + return GetTypeForDecl(interface_decl); + if (clang::TagDecl *tag_decl = llvm::dyn_cast<clang::TagDecl>(decl)) + return GetTypeForDecl(tag_decl); + return CompilerType(); +} -CompilerType -ClangASTContext::GetTypeForDecl (TagDecl *decl) -{ - // No need to call the getASTContext() accessor (which can create the AST - // if it isn't created yet, because we can't have created a decl in this - // AST if our AST didn't already exist... - ASTContext *ast = &decl->getASTContext(); - if (ast) - return CompilerType (ast, ast->getTagDeclType(decl)); - return CompilerType(); +CompilerType ClangASTContext::GetTypeForDecl(TagDecl *decl) { + // No need to call the getASTContext() accessor (which can create the AST + // if it isn't created yet, because we can't have created a decl in this + // AST if our AST didn't already exist... + ASTContext *ast = &decl->getASTContext(); + if (ast) + return CompilerType(ast, ast->getTagDeclType(decl)); + return CompilerType(); } -CompilerType -ClangASTContext::GetTypeForDecl (ObjCInterfaceDecl *decl) -{ - // No need to call the getASTContext() accessor (which can create the AST - // if it isn't created yet, because we can't have created a decl in this - // AST if our AST didn't already exist... - ASTContext *ast = &decl->getASTContext(); - if (ast) - return CompilerType (ast, ast->getObjCInterfaceType(decl)); - return CompilerType(); +CompilerType ClangASTContext::GetTypeForDecl(ObjCInterfaceDecl *decl) { + // No need to call the getASTContext() accessor (which can create the AST + // if it isn't created yet, because we can't have created a decl in this + // AST if our AST didn't already exist... + ASTContext *ast = &decl->getASTContext(); + if (ast) + return CompilerType(ast, ast->getObjCInterfaceType(decl)); + return CompilerType(); } #pragma mark Structure, Unions, Classes -CompilerType -ClangASTContext::CreateRecordType (DeclContext *decl_ctx, - AccessType access_type, - const char *name, - int kind, - LanguageType language, - ClangASTMetadata *metadata) -{ - ASTContext *ast = getASTContext(); - assert (ast != nullptr); - - if (decl_ctx == nullptr) - decl_ctx = ast->getTranslationUnitDecl(); - - - if (language == eLanguageTypeObjC || language == eLanguageTypeObjC_plus_plus) - { - bool isForwardDecl = true; - bool isInternal = false; - return CreateObjCClass (name, decl_ctx, isForwardDecl, isInternal, metadata); - } - - // NOTE: Eventually CXXRecordDecl will be merged back into RecordDecl and - // we will need to update this code. I was told to currently always use - // the CXXRecordDecl class since we often don't know from debug information - // if something is struct or a class, so we default to always use the more - // complete definition just in case. - - bool is_anonymous = (!name) || (!name[0]); - - CXXRecordDecl *decl = CXXRecordDecl::Create (*ast, - (TagDecl::TagKind)kind, - decl_ctx, - SourceLocation(), - SourceLocation(), - is_anonymous ? nullptr : &ast->Idents.get(name)); - - if (is_anonymous) - decl->setAnonymousStructOrUnion(true); - - if (decl) - { - if (metadata) - SetMetadata(ast, decl, *metadata); +CompilerType ClangASTContext::CreateRecordType(DeclContext *decl_ctx, + AccessType access_type, + const char *name, int kind, + LanguageType language, + ClangASTMetadata *metadata) { + ASTContext *ast = getASTContext(); + assert(ast != nullptr); - if (access_type != eAccessNone) - decl->setAccess (ConvertAccessTypeToAccessSpecifier (access_type)); - - if (decl_ctx) - decl_ctx->addDecl (decl); + if (decl_ctx == nullptr) + decl_ctx = ast->getTranslationUnitDecl(); - return CompilerType(ast, ast->getTagDeclType(decl)); - } - return CompilerType(); -} + if (language == eLanguageTypeObjC || + language == eLanguageTypeObjC_plus_plus) { + bool isForwardDecl = true; + bool isInternal = false; + return CreateObjCClass(name, decl_ctx, isForwardDecl, isInternal, metadata); + } -static TemplateParameterList * -CreateTemplateParameterList (ASTContext *ast, - const ClangASTContext::TemplateParameterInfos &template_param_infos, - llvm::SmallVector<NamedDecl *, 8> &template_param_decls) -{ - const bool parameter_pack = false; - const bool is_typename = false; - const unsigned depth = 0; - const size_t num_template_params = template_param_infos.GetSize(); - for (size_t i=0; i<num_template_params; ++i) - { - const char *name = template_param_infos.names[i]; - - IdentifierInfo *identifier_info = nullptr; - if (name && name[0]) - identifier_info = &ast->Idents.get(name); - if (template_param_infos.args[i].getKind() == TemplateArgument::Integral) - { - template_param_decls.push_back (NonTypeTemplateParmDecl::Create (*ast, - ast->getTranslationUnitDecl(), // Is this the right decl context?, SourceLocation StartLoc, - SourceLocation(), - SourceLocation(), - depth, - i, - identifier_info, - template_param_infos.args[i].getIntegralType(), - parameter_pack, - nullptr)); - - } - else - { - template_param_decls.push_back (TemplateTypeParmDecl::Create (*ast, - ast->getTranslationUnitDecl(), // Is this the right decl context? - SourceLocation(), - SourceLocation(), - depth, - i, - identifier_info, - is_typename, - parameter_pack)); - } - } + // NOTE: Eventually CXXRecordDecl will be merged back into RecordDecl and + // we will need to update this code. I was told to currently always use + // the CXXRecordDecl class since we often don't know from debug information + // if something is struct or a class, so we default to always use the more + // complete definition just in case. + + bool is_anonymous = (!name) || (!name[0]); + + CXXRecordDecl *decl = CXXRecordDecl::Create( + *ast, (TagDecl::TagKind)kind, decl_ctx, SourceLocation(), + SourceLocation(), is_anonymous ? nullptr : &ast->Idents.get(name)); + + if (is_anonymous) + decl->setAnonymousStructOrUnion(true); - clang::Expr *const requires_clause = nullptr; // TODO: Concepts - TemplateParameterList *template_param_list = TemplateParameterList::Create (*ast, - SourceLocation(), - SourceLocation(), - template_param_decls, - SourceLocation(), - requires_clause); - return template_param_list; + if (decl) { + if (metadata) + SetMetadata(ast, decl, *metadata); + + if (access_type != eAccessNone) + decl->setAccess(ConvertAccessTypeToAccessSpecifier(access_type)); + + if (decl_ctx) + decl_ctx->addDecl(decl); + + return CompilerType(ast, ast->getTagDeclType(decl)); + } + return CompilerType(); } -clang::FunctionTemplateDecl * -ClangASTContext::CreateFunctionTemplateDecl (clang::DeclContext *decl_ctx, - clang::FunctionDecl *func_decl, - const char *name, - const TemplateParameterInfos &template_param_infos) -{ -// /// \brief Create a function template node. - ASTContext *ast = getASTContext(); - - llvm::SmallVector<NamedDecl *, 8> template_param_decls; - - TemplateParameterList *template_param_list = CreateTemplateParameterList (ast, - template_param_infos, - template_param_decls); - FunctionTemplateDecl *func_tmpl_decl = FunctionTemplateDecl::Create (*ast, - decl_ctx, - func_decl->getLocation(), - func_decl->getDeclName(), - template_param_list, - func_decl); - - for (size_t i=0, template_param_decl_count = template_param_decls.size(); - i < template_param_decl_count; - ++i) - { - // TODO: verify which decl context we should put template_param_decls into.. - template_param_decls[i]->setDeclContext (func_decl); - } - - return func_tmpl_decl; -} - -void -ClangASTContext::CreateFunctionTemplateSpecializationInfo (FunctionDecl *func_decl, - clang::FunctionTemplateDecl *func_tmpl_decl, - const TemplateParameterInfos &infos) -{ - TemplateArgumentList template_args (TemplateArgumentList::OnStack, infos.args); - - func_decl->setFunctionTemplateSpecialization (func_tmpl_decl, - &template_args, - nullptr); -} - - -ClassTemplateDecl * -ClangASTContext::CreateClassTemplateDecl (DeclContext *decl_ctx, - lldb::AccessType access_type, - const char *class_name, - int kind, - const TemplateParameterInfos &template_param_infos) -{ - ASTContext *ast = getASTContext(); - - ClassTemplateDecl *class_template_decl = nullptr; - if (decl_ctx == nullptr) - decl_ctx = ast->getTranslationUnitDecl(); - - IdentifierInfo &identifier_info = ast->Idents.get(class_name); - DeclarationName decl_name (&identifier_info); +static TemplateParameterList *CreateTemplateParameterList( + ASTContext *ast, + const ClangASTContext::TemplateParameterInfos &template_param_infos, + llvm::SmallVector<NamedDecl *, 8> &template_param_decls) { + const bool parameter_pack = false; + const bool is_typename = false; + const unsigned depth = 0; + const size_t num_template_params = template_param_infos.GetSize(); + for (size_t i = 0; i < num_template_params; ++i) { + const char *name = template_param_infos.names[i]; + + IdentifierInfo *identifier_info = nullptr; + if (name && name[0]) + identifier_info = &ast->Idents.get(name); + if (template_param_infos.args[i].getKind() == TemplateArgument::Integral) { + template_param_decls.push_back(NonTypeTemplateParmDecl::Create( + *ast, + ast->getTranslationUnitDecl(), // Is this the right decl context?, + // SourceLocation StartLoc, + SourceLocation(), SourceLocation(), depth, i, identifier_info, + template_param_infos.args[i].getIntegralType(), parameter_pack, + nullptr)); + + } else { + template_param_decls.push_back(TemplateTypeParmDecl::Create( + *ast, + ast->getTranslationUnitDecl(), // Is this the right decl context? + SourceLocation(), SourceLocation(), depth, i, identifier_info, + is_typename, parameter_pack)); + } + } + + clang::Expr *const requires_clause = nullptr; // TODO: Concepts + TemplateParameterList *template_param_list = TemplateParameterList::Create( + *ast, SourceLocation(), SourceLocation(), template_param_decls, + SourceLocation(), requires_clause); + return template_param_list; +} + +clang::FunctionTemplateDecl *ClangASTContext::CreateFunctionTemplateDecl( + clang::DeclContext *decl_ctx, clang::FunctionDecl *func_decl, + const char *name, const TemplateParameterInfos &template_param_infos) { + // /// \brief Create a function template node. + ASTContext *ast = getASTContext(); + + llvm::SmallVector<NamedDecl *, 8> template_param_decls; + + TemplateParameterList *template_param_list = CreateTemplateParameterList( + ast, template_param_infos, template_param_decls); + FunctionTemplateDecl *func_tmpl_decl = FunctionTemplateDecl::Create( + *ast, decl_ctx, func_decl->getLocation(), func_decl->getDeclName(), + template_param_list, func_decl); + + for (size_t i = 0, template_param_decl_count = template_param_decls.size(); + i < template_param_decl_count; ++i) { + // TODO: verify which decl context we should put template_param_decls into.. + template_param_decls[i]->setDeclContext(func_decl); + } + + return func_tmpl_decl; +} + +void ClangASTContext::CreateFunctionTemplateSpecializationInfo( + FunctionDecl *func_decl, clang::FunctionTemplateDecl *func_tmpl_decl, + const TemplateParameterInfos &infos) { + TemplateArgumentList template_args(TemplateArgumentList::OnStack, infos.args); + + func_decl->setFunctionTemplateSpecialization(func_tmpl_decl, &template_args, + nullptr); +} - clang::DeclContext::lookup_result result = decl_ctx->lookup(decl_name); - - for (NamedDecl *decl : result) - { - class_template_decl = dyn_cast<clang::ClassTemplateDecl>(decl); - if (class_template_decl) - return class_template_decl; - } - - llvm::SmallVector<NamedDecl *, 8> template_param_decls; - - TemplateParameterList *template_param_list = CreateTemplateParameterList (ast, - template_param_infos, - template_param_decls); - - CXXRecordDecl *template_cxx_decl = CXXRecordDecl::Create (*ast, - (TagDecl::TagKind)kind, - decl_ctx, // What decl context do we use here? TU? The actual decl context? - SourceLocation(), - SourceLocation(), - &identifier_info); - - for (size_t i=0, template_param_decl_count = template_param_decls.size(); - i < template_param_decl_count; - ++i) - { - template_param_decls[i]->setDeclContext (template_cxx_decl); - } - - // With templated classes, we say that a class is templated with - // specializations, but that the bare class has no functions. - //template_cxx_decl->startDefinition(); - //template_cxx_decl->completeDefinition(); - - class_template_decl = ClassTemplateDecl::Create (*ast, - decl_ctx, // What decl context do we use here? TU? The actual decl context? - SourceLocation(), - decl_name, - template_param_list, - template_cxx_decl, - nullptr); - +ClassTemplateDecl *ClangASTContext::CreateClassTemplateDecl( + DeclContext *decl_ctx, lldb::AccessType access_type, const char *class_name, + int kind, const TemplateParameterInfos &template_param_infos) { + ASTContext *ast = getASTContext(); + + ClassTemplateDecl *class_template_decl = nullptr; + if (decl_ctx == nullptr) + decl_ctx = ast->getTranslationUnitDecl(); + + IdentifierInfo &identifier_info = ast->Idents.get(class_name); + DeclarationName decl_name(&identifier_info); + + clang::DeclContext::lookup_result result = decl_ctx->lookup(decl_name); + + for (NamedDecl *decl : result) { + class_template_decl = dyn_cast<clang::ClassTemplateDecl>(decl); if (class_template_decl) - { - if (access_type != eAccessNone) - class_template_decl->setAccess (ConvertAccessTypeToAccessSpecifier (access_type)); - - //if (TagDecl *ctx_tag_decl = dyn_cast<TagDecl>(decl_ctx)) - // CompleteTagDeclarationDefinition(GetTypeForDecl(ctx_tag_decl)); - - decl_ctx->addDecl (class_template_decl); - + return class_template_decl; + } + + llvm::SmallVector<NamedDecl *, 8> template_param_decls; + + TemplateParameterList *template_param_list = CreateTemplateParameterList( + ast, template_param_infos, template_param_decls); + + CXXRecordDecl *template_cxx_decl = CXXRecordDecl::Create( + *ast, (TagDecl::TagKind)kind, + decl_ctx, // What decl context do we use here? TU? The actual decl + // context? + SourceLocation(), SourceLocation(), &identifier_info); + + for (size_t i = 0, template_param_decl_count = template_param_decls.size(); + i < template_param_decl_count; ++i) { + template_param_decls[i]->setDeclContext(template_cxx_decl); + } + + // With templated classes, we say that a class is templated with + // specializations, but that the bare class has no functions. + // template_cxx_decl->startDefinition(); + // template_cxx_decl->completeDefinition(); + + class_template_decl = ClassTemplateDecl::Create( + *ast, + decl_ctx, // What decl context do we use here? TU? The actual decl + // context? + SourceLocation(), decl_name, template_param_list, template_cxx_decl, + nullptr); + + if (class_template_decl) { + if (access_type != eAccessNone) + class_template_decl->setAccess( + ConvertAccessTypeToAccessSpecifier(access_type)); + + // if (TagDecl *ctx_tag_decl = dyn_cast<TagDecl>(decl_ctx)) + // CompleteTagDeclarationDefinition(GetTypeForDecl(ctx_tag_decl)); + + decl_ctx->addDecl(class_template_decl); + #ifdef LLDB_CONFIGURATION_DEBUG - VerifyDecl(class_template_decl); + VerifyDecl(class_template_decl); #endif - } + } - return class_template_decl; + return class_template_decl; } - ClassTemplateSpecializationDecl * -ClangASTContext::CreateClassTemplateSpecializationDecl (DeclContext *decl_ctx, - ClassTemplateDecl *class_template_decl, - int kind, - const TemplateParameterInfos &template_param_infos) -{ - ASTContext *ast = getASTContext(); - ClassTemplateSpecializationDecl *class_template_specialization_decl = ClassTemplateSpecializationDecl::Create (*ast, - (TagDecl::TagKind)kind, - decl_ctx, - SourceLocation(), - SourceLocation(), - class_template_decl, - template_param_infos.args, - nullptr); - - class_template_specialization_decl->setSpecializationKind(TSK_ExplicitSpecialization); - - return class_template_specialization_decl; -} +ClangASTContext::CreateClassTemplateSpecializationDecl( + DeclContext *decl_ctx, ClassTemplateDecl *class_template_decl, int kind, + const TemplateParameterInfos &template_param_infos) { + ASTContext *ast = getASTContext(); + ClassTemplateSpecializationDecl *class_template_specialization_decl = + ClassTemplateSpecializationDecl::Create( + *ast, (TagDecl::TagKind)kind, decl_ctx, SourceLocation(), + SourceLocation(), class_template_decl, template_param_infos.args, + nullptr); -CompilerType -ClangASTContext::CreateClassTemplateSpecializationType (ClassTemplateSpecializationDecl *class_template_specialization_decl) -{ - if (class_template_specialization_decl) - { - ASTContext *ast = getASTContext(); - if (ast) - return CompilerType(ast, ast->getTagDeclType(class_template_specialization_decl)); - } - return CompilerType(); + class_template_specialization_decl->setSpecializationKind( + TSK_ExplicitSpecialization); + + return class_template_specialization_decl; } -static inline bool -check_op_param(bool is_method, clang::OverloadedOperatorKind op_kind, bool unary, bool binary, uint32_t num_params) -{ - // Special-case call since it can take any number of operands - if(op_kind == OO_Call) - return true; - - // The parameter count doesn't include "this" - if (is_method) - ++num_params; - if (num_params == 1) - return unary; - if (num_params == 2) - return binary; - else +CompilerType ClangASTContext::CreateClassTemplateSpecializationType( + ClassTemplateSpecializationDecl *class_template_specialization_decl) { + if (class_template_specialization_decl) { + ASTContext *ast = getASTContext(); + if (ast) + return CompilerType( + ast, ast->getTagDeclType(class_template_specialization_decl)); + } + return CompilerType(); +} + +static inline bool check_op_param(bool is_method, + clang::OverloadedOperatorKind op_kind, + bool unary, bool binary, + uint32_t num_params) { + // Special-case call since it can take any number of operands + if (op_kind == OO_Call) + return true; + + // The parameter count doesn't include "this" + if (is_method) + ++num_params; + if (num_params == 1) + return unary; + if (num_params == 2) + return binary; + else return false; } -bool -ClangASTContext::CheckOverloadedOperatorKindParameterCount(bool is_method, clang::OverloadedOperatorKind op_kind, - uint32_t num_params) -{ - switch (op_kind) - { - default: - break; - // C++ standard allows any number of arguments to new/delete - case OO_New: - case OO_Array_New: - case OO_Delete: - case OO_Array_Delete: - return true; - } +bool ClangASTContext::CheckOverloadedOperatorKindParameterCount( + bool is_method, clang::OverloadedOperatorKind op_kind, + uint32_t num_params) { + switch (op_kind) { + default: + break; + // C++ standard allows any number of arguments to new/delete + case OO_New: + case OO_Array_New: + case OO_Delete: + case OO_Array_Delete: + return true; + } -#define OVERLOADED_OPERATOR(Name, Spelling, Token, Unary, Binary, MemberOnly) \ - case OO_##Name: \ - return check_op_param(is_method, op_kind, Unary, Binary, num_params); - switch (op_kind) - { +#define OVERLOADED_OPERATOR(Name, Spelling, Token, Unary, Binary, MemberOnly) \ + case OO_##Name: \ + return check_op_param(is_method, op_kind, Unary, Binary, num_params); + switch (op_kind) { #include "clang/Basic/OperatorKinds.def" - default: break; - } - return false; + default: + break; + } + return false; } clang::AccessSpecifier -ClangASTContext::UnifyAccessSpecifiers (clang::AccessSpecifier lhs, clang::AccessSpecifier rhs) -{ - // Make the access equal to the stricter of the field and the nested field's access - if (lhs == AS_none || rhs == AS_none) - return AS_none; - if (lhs == AS_private || rhs == AS_private) - return AS_private; - if (lhs == AS_protected || rhs == AS_protected) - return AS_protected; - return AS_public; +ClangASTContext::UnifyAccessSpecifiers(clang::AccessSpecifier lhs, + clang::AccessSpecifier rhs) { + // Make the access equal to the stricter of the field and the nested field's + // access + if (lhs == AS_none || rhs == AS_none) + return AS_none; + if (lhs == AS_private || rhs == AS_private) + return AS_private; + if (lhs == AS_protected || rhs == AS_protected) + return AS_protected; + return AS_public; } -bool -ClangASTContext::FieldIsBitfield (FieldDecl* field, uint32_t& bitfield_bit_size) -{ - return FieldIsBitfield(getASTContext(), field, bitfield_bit_size); +bool ClangASTContext::FieldIsBitfield(FieldDecl *field, + uint32_t &bitfield_bit_size) { + return FieldIsBitfield(getASTContext(), field, bitfield_bit_size); } -bool -ClangASTContext::FieldIsBitfield -( - ASTContext *ast, - FieldDecl* field, - uint32_t& bitfield_bit_size -) -{ - if (ast == nullptr || field == nullptr) - return false; +bool ClangASTContext::FieldIsBitfield(ASTContext *ast, FieldDecl *field, + uint32_t &bitfield_bit_size) { + if (ast == nullptr || field == nullptr) + return false; - if (field->isBitField()) - { - Expr* bit_width_expr = field->getBitWidth(); - if (bit_width_expr) - { - llvm::APSInt bit_width_apsint; - if (bit_width_expr->isIntegerConstantExpr(bit_width_apsint, *ast)) - { - bitfield_bit_size = bit_width_apsint.getLimitedValue(UINT32_MAX); - return true; - } - } + if (field->isBitField()) { + Expr *bit_width_expr = field->getBitWidth(); + if (bit_width_expr) { + llvm::APSInt bit_width_apsint; + if (bit_width_expr->isIntegerConstantExpr(bit_width_apsint, *ast)) { + bitfield_bit_size = bit_width_apsint.getLimitedValue(UINT32_MAX); + return true; + } } - return false; + } + return false; } -bool -ClangASTContext::RecordHasFields (const RecordDecl *record_decl) -{ - if (record_decl == nullptr) - return false; +bool ClangASTContext::RecordHasFields(const RecordDecl *record_decl) { + if (record_decl == nullptr) + return false; - if (!record_decl->field_empty()) - return true; + if (!record_decl->field_empty()) + return true; - // No fields, lets check this is a CXX record and check the base classes - const CXXRecordDecl *cxx_record_decl = dyn_cast<CXXRecordDecl>(record_decl); - if (cxx_record_decl) - { - CXXRecordDecl::base_class_const_iterator base_class, base_class_end; - for (base_class = cxx_record_decl->bases_begin(), base_class_end = cxx_record_decl->bases_end(); - base_class != base_class_end; - ++base_class) - { - const CXXRecordDecl *base_class_decl = cast<CXXRecordDecl>(base_class->getType()->getAs<RecordType>()->getDecl()); - if (RecordHasFields(base_class_decl)) - return true; - } + // No fields, lets check this is a CXX record and check the base classes + const CXXRecordDecl *cxx_record_decl = dyn_cast<CXXRecordDecl>(record_decl); + if (cxx_record_decl) { + CXXRecordDecl::base_class_const_iterator base_class, base_class_end; + for (base_class = cxx_record_decl->bases_begin(), + base_class_end = cxx_record_decl->bases_end(); + base_class != base_class_end; ++base_class) { + const CXXRecordDecl *base_class_decl = cast<CXXRecordDecl>( + base_class->getType()->getAs<RecordType>()->getDecl()); + if (RecordHasFields(base_class_decl)) + return true; } - return false; + } + return false; } #pragma mark Objective C Classes -CompilerType -ClangASTContext::CreateObjCClass -( - const char *name, - DeclContext *decl_ctx, - bool isForwardDecl, - bool isInternal, - ClangASTMetadata *metadata -) -{ - ASTContext *ast = getASTContext(); - assert (ast != nullptr); - assert (name && name[0]); - if (decl_ctx == nullptr) - decl_ctx = ast->getTranslationUnitDecl(); - - ObjCInterfaceDecl *decl = ObjCInterfaceDecl::Create (*ast, - decl_ctx, - SourceLocation(), - &ast->Idents.get(name), - nullptr, - nullptr, - SourceLocation(), - /*isForwardDecl,*/ - isInternal); - - if (decl && metadata) - SetMetadata(ast, decl, *metadata); - - return CompilerType (ast, ast->getObjCInterfaceType(decl)); +CompilerType ClangASTContext::CreateObjCClass(const char *name, + DeclContext *decl_ctx, + bool isForwardDecl, + bool isInternal, + ClangASTMetadata *metadata) { + ASTContext *ast = getASTContext(); + assert(ast != nullptr); + assert(name && name[0]); + if (decl_ctx == nullptr) + decl_ctx = ast->getTranslationUnitDecl(); + + ObjCInterfaceDecl *decl = ObjCInterfaceDecl::Create( + *ast, decl_ctx, SourceLocation(), &ast->Idents.get(name), nullptr, + nullptr, SourceLocation(), + /*isForwardDecl,*/ + isInternal); + + if (decl && metadata) + SetMetadata(ast, decl, *metadata); + + return CompilerType(ast, ast->getObjCInterfaceType(decl)); } -static inline bool -BaseSpecifierIsEmpty (const CXXBaseSpecifier *b) -{ - return ClangASTContext::RecordHasFields(b->getType()->getAsCXXRecordDecl()) == false; +static inline bool BaseSpecifierIsEmpty(const CXXBaseSpecifier *b) { + return ClangASTContext::RecordHasFields(b->getType()->getAsCXXRecordDecl()) == + false; } uint32_t -ClangASTContext::GetNumBaseClasses (const CXXRecordDecl *cxx_record_decl, bool omit_empty_base_classes) -{ - uint32_t num_bases = 0; - if (cxx_record_decl) - { - if (omit_empty_base_classes) - { - CXXRecordDecl::base_class_const_iterator base_class, base_class_end; - for (base_class = cxx_record_decl->bases_begin(), base_class_end = cxx_record_decl->bases_end(); - base_class != base_class_end; - ++base_class) - { - // Skip empty base classes - if (omit_empty_base_classes) - { - if (BaseSpecifierIsEmpty (base_class)) - continue; - } - ++num_bases; - } +ClangASTContext::GetNumBaseClasses(const CXXRecordDecl *cxx_record_decl, + bool omit_empty_base_classes) { + uint32_t num_bases = 0; + if (cxx_record_decl) { + if (omit_empty_base_classes) { + CXXRecordDecl::base_class_const_iterator base_class, base_class_end; + for (base_class = cxx_record_decl->bases_begin(), + base_class_end = cxx_record_decl->bases_end(); + base_class != base_class_end; ++base_class) { + // Skip empty base classes + if (omit_empty_base_classes) { + if (BaseSpecifierIsEmpty(base_class)) + continue; } - else - num_bases = cxx_record_decl->getNumBases(); - } - return num_bases; + ++num_bases; + } + } else + num_bases = cxx_record_decl->getNumBases(); + } + return num_bases; } - #pragma mark Namespace Declarations NamespaceDecl * -ClangASTContext::GetUniqueNamespaceDeclaration (const char *name, DeclContext *decl_ctx) -{ - NamespaceDecl *namespace_decl = nullptr; - ASTContext *ast = getASTContext(); - TranslationUnitDecl *translation_unit_decl = ast->getTranslationUnitDecl (); - if (decl_ctx == nullptr) - decl_ctx = translation_unit_decl; - - if (name) - { - IdentifierInfo &identifier_info = ast->Idents.get(name); - DeclarationName decl_name (&identifier_info); - clang::DeclContext::lookup_result result = decl_ctx->lookup(decl_name); - for (NamedDecl *decl : result) - { - namespace_decl = dyn_cast<clang::NamespaceDecl>(decl); - if (namespace_decl) - return namespace_decl; - } - - namespace_decl = NamespaceDecl::Create(*ast, - decl_ctx, - false, - SourceLocation(), - SourceLocation(), - &identifier_info, - nullptr); - - decl_ctx->addDecl (namespace_decl); - } - else - { - if (decl_ctx == translation_unit_decl) - { - namespace_decl = translation_unit_decl->getAnonymousNamespace(); - if (namespace_decl) - return namespace_decl; - - namespace_decl = NamespaceDecl::Create(*ast, - decl_ctx, - false, - SourceLocation(), - SourceLocation(), - nullptr, - nullptr); - translation_unit_decl->setAnonymousNamespace (namespace_decl); - translation_unit_decl->addDecl (namespace_decl); - assert (namespace_decl == translation_unit_decl->getAnonymousNamespace()); - } - else - { - NamespaceDecl *parent_namespace_decl = cast<NamespaceDecl>(decl_ctx); - if (parent_namespace_decl) - { - namespace_decl = parent_namespace_decl->getAnonymousNamespace(); - if (namespace_decl) - return namespace_decl; - namespace_decl = NamespaceDecl::Create(*ast, - decl_ctx, - false, - SourceLocation(), - SourceLocation(), - nullptr, - nullptr); - parent_namespace_decl->setAnonymousNamespace (namespace_decl); - parent_namespace_decl->addDecl (namespace_decl); - assert (namespace_decl == parent_namespace_decl->getAnonymousNamespace()); - } - else - { - // BAD!!! - } - } - } +ClangASTContext::GetUniqueNamespaceDeclaration(const char *name, + DeclContext *decl_ctx) { + NamespaceDecl *namespace_decl = nullptr; + ASTContext *ast = getASTContext(); + TranslationUnitDecl *translation_unit_decl = ast->getTranslationUnitDecl(); + if (decl_ctx == nullptr) + decl_ctx = translation_unit_decl; + + if (name) { + IdentifierInfo &identifier_info = ast->Idents.get(name); + DeclarationName decl_name(&identifier_info); + clang::DeclContext::lookup_result result = decl_ctx->lookup(decl_name); + for (NamedDecl *decl : result) { + namespace_decl = dyn_cast<clang::NamespaceDecl>(decl); + if (namespace_decl) + return namespace_decl; + } + + namespace_decl = + NamespaceDecl::Create(*ast, decl_ctx, false, SourceLocation(), + SourceLocation(), &identifier_info, nullptr); + + decl_ctx->addDecl(namespace_decl); + } else { + if (decl_ctx == translation_unit_decl) { + namespace_decl = translation_unit_decl->getAnonymousNamespace(); + if (namespace_decl) + return namespace_decl; + + namespace_decl = + NamespaceDecl::Create(*ast, decl_ctx, false, SourceLocation(), + SourceLocation(), nullptr, nullptr); + translation_unit_decl->setAnonymousNamespace(namespace_decl); + translation_unit_decl->addDecl(namespace_decl); + assert(namespace_decl == translation_unit_decl->getAnonymousNamespace()); + } else { + NamespaceDecl *parent_namespace_decl = cast<NamespaceDecl>(decl_ctx); + if (parent_namespace_decl) { + namespace_decl = parent_namespace_decl->getAnonymousNamespace(); + if (namespace_decl) + return namespace_decl; + namespace_decl = + NamespaceDecl::Create(*ast, decl_ctx, false, SourceLocation(), + SourceLocation(), nullptr, nullptr); + parent_namespace_decl->setAnonymousNamespace(namespace_decl); + parent_namespace_decl->addDecl(namespace_decl); + assert(namespace_decl == + parent_namespace_decl->getAnonymousNamespace()); + } else { + // BAD!!! + } + } + } #ifdef LLDB_CONFIGURATION_DEBUG - VerifyDecl(namespace_decl); + VerifyDecl(namespace_decl); #endif - return namespace_decl; + return namespace_decl; } -NamespaceDecl * -ClangASTContext::GetUniqueNamespaceDeclaration (clang::ASTContext *ast, - const char *name, - clang::DeclContext *decl_ctx) -{ - ClangASTContext *ast_ctx = ClangASTContext::GetASTContext(ast); - if (ast_ctx == nullptr) - return nullptr; +NamespaceDecl *ClangASTContext::GetUniqueNamespaceDeclaration( + clang::ASTContext *ast, const char *name, clang::DeclContext *decl_ctx) { + ClangASTContext *ast_ctx = ClangASTContext::GetASTContext(ast); + if (ast_ctx == nullptr) + return nullptr; - return ast_ctx->GetUniqueNamespaceDeclaration(name, decl_ctx); + return ast_ctx->GetUniqueNamespaceDeclaration(name, decl_ctx); } clang::BlockDecl * -ClangASTContext::CreateBlockDeclaration (clang::DeclContext *ctx) -{ - if (ctx != nullptr) - { - clang::BlockDecl *decl = clang::BlockDecl::Create(*getASTContext(), ctx, clang::SourceLocation()); - ctx->addDecl(decl); - return decl; - } +ClangASTContext::CreateBlockDeclaration(clang::DeclContext *ctx) { + if (ctx != nullptr) { + clang::BlockDecl *decl = clang::BlockDecl::Create(*getASTContext(), ctx, + clang::SourceLocation()); + ctx->addDecl(decl); + return decl; + } + return nullptr; +} + +clang::DeclContext *FindLCABetweenDecls(clang::DeclContext *left, + clang::DeclContext *right, + clang::DeclContext *root) { + if (root == nullptr) return nullptr; -} - -clang::DeclContext * -FindLCABetweenDecls(clang::DeclContext *left, clang::DeclContext *right, clang::DeclContext *root) -{ - if (root == nullptr) - return nullptr; - std::set<clang::DeclContext *> path_left; - for (clang::DeclContext *d = left; d != nullptr; d = d->getParent()) - path_left.insert(d); + std::set<clang::DeclContext *> path_left; + for (clang::DeclContext *d = left; d != nullptr; d = d->getParent()) + path_left.insert(d); - for (clang::DeclContext *d = right; d != nullptr; d = d->getParent()) - if (path_left.find(d) != path_left.end()) - return d; + for (clang::DeclContext *d = right; d != nullptr; d = d->getParent()) + if (path_left.find(d) != path_left.end()) + return d; - return nullptr; + return nullptr; } -clang::UsingDirectiveDecl * -ClangASTContext::CreateUsingDirectiveDeclaration (clang::DeclContext *decl_ctx, clang::NamespaceDecl *ns_decl) -{ - if (decl_ctx != nullptr && ns_decl != nullptr) - { - clang::TranslationUnitDecl *translation_unit = (clang::TranslationUnitDecl *)GetTranslationUnitDecl(getASTContext()); - clang::UsingDirectiveDecl *using_decl = clang::UsingDirectiveDecl::Create(*getASTContext(), - decl_ctx, - clang::SourceLocation(), - clang::SourceLocation(), - clang::NestedNameSpecifierLoc(), - clang::SourceLocation(), - ns_decl, - FindLCABetweenDecls(decl_ctx, ns_decl, translation_unit)); - decl_ctx->addDecl(using_decl); - return using_decl; - } - return nullptr; +clang::UsingDirectiveDecl *ClangASTContext::CreateUsingDirectiveDeclaration( + clang::DeclContext *decl_ctx, clang::NamespaceDecl *ns_decl) { + if (decl_ctx != nullptr && ns_decl != nullptr) { + clang::TranslationUnitDecl *translation_unit = + (clang::TranslationUnitDecl *)GetTranslationUnitDecl(getASTContext()); + clang::UsingDirectiveDecl *using_decl = clang::UsingDirectiveDecl::Create( + *getASTContext(), decl_ctx, clang::SourceLocation(), + clang::SourceLocation(), clang::NestedNameSpecifierLoc(), + clang::SourceLocation(), ns_decl, + FindLCABetweenDecls(decl_ctx, ns_decl, translation_unit)); + decl_ctx->addDecl(using_decl); + return using_decl; + } + return nullptr; } clang::UsingDecl * -ClangASTContext::CreateUsingDeclaration (clang::DeclContext *current_decl_ctx, clang::NamedDecl *target) -{ - if (current_decl_ctx != nullptr && target != nullptr) - { - clang::UsingDecl *using_decl = clang::UsingDecl::Create(*getASTContext(), - current_decl_ctx, - clang::SourceLocation(), - clang::NestedNameSpecifierLoc(), - clang::DeclarationNameInfo(), - false); - clang::UsingShadowDecl *shadow_decl = clang::UsingShadowDecl::Create(*getASTContext(), - current_decl_ctx, - clang::SourceLocation(), - using_decl, - target); - using_decl->addShadowDecl(shadow_decl); - current_decl_ctx->addDecl(using_decl); - return using_decl; - } - return nullptr; -} - -clang::VarDecl * -ClangASTContext::CreateVariableDeclaration (clang::DeclContext *decl_context, const char *name, clang::QualType type) -{ - if (decl_context != nullptr) - { - clang::VarDecl *var_decl = clang::VarDecl::Create(*getASTContext(), - decl_context, - clang::SourceLocation(), - clang::SourceLocation(), - name && name[0] ? &getASTContext()->Idents.getOwn(name) : nullptr, - type, - nullptr, - clang::SC_None); - var_decl->setAccess(clang::AS_public); - decl_context->addDecl(var_decl); - return var_decl; - } - return nullptr; +ClangASTContext::CreateUsingDeclaration(clang::DeclContext *current_decl_ctx, + clang::NamedDecl *target) { + if (current_decl_ctx != nullptr && target != nullptr) { + clang::UsingDecl *using_decl = clang::UsingDecl::Create( + *getASTContext(), current_decl_ctx, clang::SourceLocation(), + clang::NestedNameSpecifierLoc(), clang::DeclarationNameInfo(), false); + clang::UsingShadowDecl *shadow_decl = clang::UsingShadowDecl::Create( + *getASTContext(), current_decl_ctx, clang::SourceLocation(), using_decl, + target); + using_decl->addShadowDecl(shadow_decl); + current_decl_ctx->addDecl(using_decl); + return using_decl; + } + return nullptr; +} + +clang::VarDecl *ClangASTContext::CreateVariableDeclaration( + clang::DeclContext *decl_context, const char *name, clang::QualType type) { + if (decl_context != nullptr) { + clang::VarDecl *var_decl = clang::VarDecl::Create( + *getASTContext(), decl_context, clang::SourceLocation(), + clang::SourceLocation(), + name && name[0] ? &getASTContext()->Idents.getOwn(name) : nullptr, type, + nullptr, clang::SC_None); + var_decl->setAccess(clang::AS_public); + decl_context->addDecl(var_decl); + return var_decl; + } + return nullptr; } lldb::opaque_compiler_type_t -ClangASTContext::GetOpaqueCompilerType(clang::ASTContext *ast, lldb::BasicType basic_type) -{ - switch (basic_type) - { - case eBasicTypeVoid: - return ast->VoidTy.getAsOpaquePtr(); - case eBasicTypeChar: - return ast->CharTy.getAsOpaquePtr(); - case eBasicTypeSignedChar: - return ast->SignedCharTy.getAsOpaquePtr(); - case eBasicTypeUnsignedChar: - return ast->UnsignedCharTy.getAsOpaquePtr(); - case eBasicTypeWChar: - return ast->getWCharType().getAsOpaquePtr(); - case eBasicTypeSignedWChar: - return ast->getSignedWCharType().getAsOpaquePtr(); - case eBasicTypeUnsignedWChar: - return ast->getUnsignedWCharType().getAsOpaquePtr(); - case eBasicTypeChar16: - return ast->Char16Ty.getAsOpaquePtr(); - case eBasicTypeChar32: - return ast->Char32Ty.getAsOpaquePtr(); - case eBasicTypeShort: - return ast->ShortTy.getAsOpaquePtr(); - case eBasicTypeUnsignedShort: - return ast->UnsignedShortTy.getAsOpaquePtr(); - case eBasicTypeInt: - return ast->IntTy.getAsOpaquePtr(); - case eBasicTypeUnsignedInt: - return ast->UnsignedIntTy.getAsOpaquePtr(); - case eBasicTypeLong: - return ast->LongTy.getAsOpaquePtr(); - case eBasicTypeUnsignedLong: - return ast->UnsignedLongTy.getAsOpaquePtr(); - case eBasicTypeLongLong: - return ast->LongLongTy.getAsOpaquePtr(); - case eBasicTypeUnsignedLongLong: - return ast->UnsignedLongLongTy.getAsOpaquePtr(); - case eBasicTypeInt128: - return ast->Int128Ty.getAsOpaquePtr(); - case eBasicTypeUnsignedInt128: - return ast->UnsignedInt128Ty.getAsOpaquePtr(); - case eBasicTypeBool: - return ast->BoolTy.getAsOpaquePtr(); - case eBasicTypeHalf: - return ast->HalfTy.getAsOpaquePtr(); - case eBasicTypeFloat: - return ast->FloatTy.getAsOpaquePtr(); - case eBasicTypeDouble: - return ast->DoubleTy.getAsOpaquePtr(); - case eBasicTypeLongDouble: - return ast->LongDoubleTy.getAsOpaquePtr(); - case eBasicTypeFloatComplex: - return ast->FloatComplexTy.getAsOpaquePtr(); - case eBasicTypeDoubleComplex: - return ast->DoubleComplexTy.getAsOpaquePtr(); - case eBasicTypeLongDoubleComplex: - return ast->LongDoubleComplexTy.getAsOpaquePtr(); - case eBasicTypeObjCID: - return ast->getObjCIdType().getAsOpaquePtr(); - case eBasicTypeObjCClass: - return ast->getObjCClassType().getAsOpaquePtr(); - case eBasicTypeObjCSel: - return ast->getObjCSelType().getAsOpaquePtr(); - case eBasicTypeNullPtr: - return ast->NullPtrTy.getAsOpaquePtr(); - default: - return nullptr; - } +ClangASTContext::GetOpaqueCompilerType(clang::ASTContext *ast, + lldb::BasicType basic_type) { + switch (basic_type) { + case eBasicTypeVoid: + return ast->VoidTy.getAsOpaquePtr(); + case eBasicTypeChar: + return ast->CharTy.getAsOpaquePtr(); + case eBasicTypeSignedChar: + return ast->SignedCharTy.getAsOpaquePtr(); + case eBasicTypeUnsignedChar: + return ast->UnsignedCharTy.getAsOpaquePtr(); + case eBasicTypeWChar: + return ast->getWCharType().getAsOpaquePtr(); + case eBasicTypeSignedWChar: + return ast->getSignedWCharType().getAsOpaquePtr(); + case eBasicTypeUnsignedWChar: + return ast->getUnsignedWCharType().getAsOpaquePtr(); + case eBasicTypeChar16: + return ast->Char16Ty.getAsOpaquePtr(); + case eBasicTypeChar32: + return ast->Char32Ty.getAsOpaquePtr(); + case eBasicTypeShort: + return ast->ShortTy.getAsOpaquePtr(); + case eBasicTypeUnsignedShort: + return ast->UnsignedShortTy.getAsOpaquePtr(); + case eBasicTypeInt: + return ast->IntTy.getAsOpaquePtr(); + case eBasicTypeUnsignedInt: + return ast->UnsignedIntTy.getAsOpaquePtr(); + case eBasicTypeLong: + return ast->LongTy.getAsOpaquePtr(); + case eBasicTypeUnsignedLong: + return ast->UnsignedLongTy.getAsOpaquePtr(); + case eBasicTypeLongLong: + return ast->LongLongTy.getAsOpaquePtr(); + case eBasicTypeUnsignedLongLong: + return ast->UnsignedLongLongTy.getAsOpaquePtr(); + case eBasicTypeInt128: + return ast->Int128Ty.getAsOpaquePtr(); + case eBasicTypeUnsignedInt128: + return ast->UnsignedInt128Ty.getAsOpaquePtr(); + case eBasicTypeBool: + return ast->BoolTy.getAsOpaquePtr(); + case eBasicTypeHalf: + return ast->HalfTy.getAsOpaquePtr(); + case eBasicTypeFloat: + return ast->FloatTy.getAsOpaquePtr(); + case eBasicTypeDouble: + return ast->DoubleTy.getAsOpaquePtr(); + case eBasicTypeLongDouble: + return ast->LongDoubleTy.getAsOpaquePtr(); + case eBasicTypeFloatComplex: + return ast->FloatComplexTy.getAsOpaquePtr(); + case eBasicTypeDoubleComplex: + return ast->DoubleComplexTy.getAsOpaquePtr(); + case eBasicTypeLongDoubleComplex: + return ast->LongDoubleComplexTy.getAsOpaquePtr(); + case eBasicTypeObjCID: + return ast->getObjCIdType().getAsOpaquePtr(); + case eBasicTypeObjCClass: + return ast->getObjCClassType().getAsOpaquePtr(); + case eBasicTypeObjCSel: + return ast->getObjCSelType().getAsOpaquePtr(); + case eBasicTypeNullPtr: + return ast->NullPtrTy.getAsOpaquePtr(); + default: + return nullptr; + } } #pragma mark Function Types clang::DeclarationName -ClangASTContext::GetDeclarationName(const char *name, const CompilerType &function_clang_type) -{ - if (!name || !name[0]) - return clang::DeclarationName(); +ClangASTContext::GetDeclarationName(const char *name, + const CompilerType &function_clang_type) { + if (!name || !name[0]) + return clang::DeclarationName(); + + clang::OverloadedOperatorKind op_kind = clang::NUM_OVERLOADED_OPERATORS; + if (!IsOperator(name, op_kind) || op_kind == clang::NUM_OVERLOADED_OPERATORS) + return DeclarationName(&getASTContext()->Idents.get( + name)); // Not operator, but a regular function. + + // Check the number of operator parameters. Sometimes we have + // seen bad DWARF that doesn't correctly describe operators and + // if we try to create a method and add it to the class, clang + // will assert and crash, so we need to make sure things are + // acceptable. + clang::QualType method_qual_type(ClangUtil::GetQualType(function_clang_type)); + const clang::FunctionProtoType *function_type = + llvm::dyn_cast<clang::FunctionProtoType>(method_qual_type.getTypePtr()); + if (function_type == nullptr) + return clang::DeclarationName(); + + const bool is_method = false; + const unsigned int num_params = function_type->getNumParams(); + if (!ClangASTContext::CheckOverloadedOperatorKindParameterCount( + is_method, op_kind, num_params)) + return clang::DeclarationName(); + + return getASTContext()->DeclarationNames.getCXXOperatorName(op_kind); +} + +FunctionDecl *ClangASTContext::CreateFunctionDeclaration( + DeclContext *decl_ctx, const char *name, + const CompilerType &function_clang_type, int storage, bool is_inline) { + FunctionDecl *func_decl = nullptr; + ASTContext *ast = getASTContext(); + if (decl_ctx == nullptr) + decl_ctx = ast->getTranslationUnitDecl(); + + const bool hasWrittenPrototype = true; + const bool isConstexprSpecified = false; + + clang::DeclarationName declarationName = + GetDeclarationName(name, function_clang_type); + func_decl = FunctionDecl::Create( + *ast, decl_ctx, SourceLocation(), SourceLocation(), declarationName, + ClangUtil::GetQualType(function_clang_type), nullptr, + (clang::StorageClass)storage, is_inline, hasWrittenPrototype, + isConstexprSpecified); + if (func_decl) + decl_ctx->addDecl(func_decl); - clang::OverloadedOperatorKind op_kind = clang::NUM_OVERLOADED_OPERATORS; - if (!IsOperator(name, op_kind) || op_kind == clang::NUM_OVERLOADED_OPERATORS) - return DeclarationName(&getASTContext()->Idents.get(name)); // Not operator, but a regular function. - - // Check the number of operator parameters. Sometimes we have - // seen bad DWARF that doesn't correctly describe operators and - // if we try to create a method and add it to the class, clang - // will assert and crash, so we need to make sure things are - // acceptable. - clang::QualType method_qual_type(ClangUtil::GetQualType(function_clang_type)); - const clang::FunctionProtoType *function_type = - llvm::dyn_cast<clang::FunctionProtoType>(method_qual_type.getTypePtr()); - if (function_type == nullptr) - return clang::DeclarationName(); - - const bool is_method = false; - const unsigned int num_params = function_type->getNumParams(); - if (!ClangASTContext::CheckOverloadedOperatorKindParameterCount(is_method, op_kind, num_params)) - return clang::DeclarationName(); - - return getASTContext()->DeclarationNames.getCXXOperatorName(op_kind); -} - -FunctionDecl * -ClangASTContext::CreateFunctionDeclaration (DeclContext *decl_ctx, - const char *name, - const CompilerType &function_clang_type, - int storage, - bool is_inline) -{ - FunctionDecl *func_decl = nullptr; - ASTContext *ast = getASTContext(); - if (decl_ctx == nullptr) - decl_ctx = ast->getTranslationUnitDecl(); - - - const bool hasWrittenPrototype = true; - const bool isConstexprSpecified = false; - - clang::DeclarationName declarationName = GetDeclarationName(name, function_clang_type); - func_decl = FunctionDecl::Create(*ast, decl_ctx, SourceLocation(), SourceLocation(), declarationName, - ClangUtil::GetQualType(function_clang_type), nullptr, (clang::StorageClass)storage, - is_inline, hasWrittenPrototype, isConstexprSpecified); - if (func_decl) - decl_ctx->addDecl (func_decl); - #ifdef LLDB_CONFIGURATION_DEBUG - VerifyDecl(func_decl); + VerifyDecl(func_decl); #endif - - return func_decl; + + return func_decl; +} + +CompilerType ClangASTContext::CreateFunctionType( + ASTContext *ast, const CompilerType &result_type, const CompilerType *args, + unsigned num_args, bool is_variadic, unsigned type_quals) { + if (ast == nullptr) + return CompilerType(); // invalid AST + + if (!result_type || !ClangUtil::IsClangType(result_type)) + return CompilerType(); // invalid return type + + std::vector<QualType> qual_type_args; + if (num_args > 0 && args == nullptr) + return CompilerType(); // invalid argument array passed in + + // Verify that all arguments are valid and the right type + for (unsigned i = 0; i < num_args; ++i) { + if (args[i]) { + // Make sure we have a clang type in args[i] and not a type from another + // language whose name might match + const bool is_clang_type = ClangUtil::IsClangType(args[i]); + lldbassert(is_clang_type); + if (is_clang_type) + qual_type_args.push_back(ClangUtil::GetQualType(args[i])); + else + return CompilerType(); // invalid argument type (must be a clang type) + } else + return CompilerType(); // invalid argument type (empty) + } + + // TODO: Detect calling convention in DWARF? + FunctionProtoType::ExtProtoInfo proto_info; + proto_info.Variadic = is_variadic; + proto_info.ExceptionSpec = EST_None; + proto_info.TypeQuals = type_quals; + proto_info.RefQualifier = RQ_None; + + return CompilerType(ast, + ast->getFunctionType(ClangUtil::GetQualType(result_type), + qual_type_args, proto_info)); +} + +ParmVarDecl *ClangASTContext::CreateParameterDeclaration( + const char *name, const CompilerType ¶m_type, int storage) { + ASTContext *ast = getASTContext(); + assert(ast != nullptr); + return ParmVarDecl::Create(*ast, ast->getTranslationUnitDecl(), + SourceLocation(), SourceLocation(), + name && name[0] ? &ast->Idents.get(name) : nullptr, + ClangUtil::GetQualType(param_type), nullptr, + (clang::StorageClass)storage, nullptr); +} + +void ClangASTContext::SetFunctionParameters(FunctionDecl *function_decl, + ParmVarDecl **params, + unsigned num_params) { + if (function_decl) + function_decl->setParams(ArrayRef<ParmVarDecl *>(params, num_params)); } CompilerType -ClangASTContext::CreateFunctionType (ASTContext *ast, - const CompilerType& result_type, - const CompilerType *args, - unsigned num_args, - bool is_variadic, - unsigned type_quals) -{ - if (ast == nullptr) - return CompilerType(); // invalid AST - - if (!result_type || !ClangUtil::IsClangType(result_type)) - return CompilerType(); // invalid return type - - std::vector<QualType> qual_type_args; - if (num_args > 0 && args == nullptr) - return CompilerType(); // invalid argument array passed in - - // Verify that all arguments are valid and the right type - for (unsigned i=0; i<num_args; ++i) - { - if (args[i]) - { - // Make sure we have a clang type in args[i] and not a type from another - // language whose name might match - const bool is_clang_type = ClangUtil::IsClangType(args[i]); - lldbassert(is_clang_type); - if (is_clang_type) - qual_type_args.push_back(ClangUtil::GetQualType(args[i])); - else - return CompilerType(); // invalid argument type (must be a clang type) - } - else - return CompilerType(); // invalid argument type (empty) - } +ClangASTContext::CreateBlockPointerType(const CompilerType &function_type) { + QualType block_type = m_ast_ap->getBlockPointerType( + clang::QualType::getFromOpaquePtr(function_type.GetOpaqueQualType())); - // TODO: Detect calling convention in DWARF? - FunctionProtoType::ExtProtoInfo proto_info; - proto_info.Variadic = is_variadic; - proto_info.ExceptionSpec = EST_None; - proto_info.TypeQuals = type_quals; - proto_info.RefQualifier = RQ_None; - - return CompilerType(ast, ast->getFunctionType(ClangUtil::GetQualType(result_type), qual_type_args, proto_info)); + return CompilerType(this, block_type.getAsOpaquePtr()); } -ParmVarDecl * -ClangASTContext::CreateParameterDeclaration (const char *name, const CompilerType ¶m_type, int storage) -{ - ASTContext *ast = getASTContext(); - assert (ast != nullptr); - return ParmVarDecl::Create(*ast, ast->getTranslationUnitDecl(), SourceLocation(), SourceLocation(), - name && name[0] ? &ast->Idents.get(name) : nullptr, ClangUtil::GetQualType(param_type), - nullptr, (clang::StorageClass)storage, nullptr); -} +#pragma mark Array Types -void -ClangASTContext::SetFunctionParameters (FunctionDecl *function_decl, ParmVarDecl **params, unsigned num_params) -{ - if (function_decl) - function_decl->setParams (ArrayRef<ParmVarDecl*>(params, num_params)); -} +CompilerType ClangASTContext::CreateArrayType(const CompilerType &element_type, + size_t element_count, + bool is_vector) { + if (element_type.IsValid()) { + ASTContext *ast = getASTContext(); + assert(ast != nullptr); + + if (is_vector) { + return CompilerType( + ast, ast->getExtVectorType(ClangUtil::GetQualType(element_type), + element_count)); + } else { + + llvm::APInt ap_element_count(64, element_count); + if (element_count == 0) { + return CompilerType(ast, ast->getIncompleteArrayType( + ClangUtil::GetQualType(element_type), + clang::ArrayType::Normal, 0)); + } else { + return CompilerType( + ast, ast->getConstantArrayType(ClangUtil::GetQualType(element_type), + ap_element_count, + clang::ArrayType::Normal, 0)); + } + } + } + return CompilerType(); +} + +CompilerType ClangASTContext::CreateStructForIdentifier( + const ConstString &type_name, + const std::initializer_list<std::pair<const char *, CompilerType>> + &type_fields, + bool packed) { + CompilerType type; + if (!type_name.IsEmpty() && + (type = GetTypeForIdentifier<clang::CXXRecordDecl>(type_name)) + .IsValid()) { + lldbassert("Trying to create a type for an existing name"); + return type; + } + + type = CreateRecordType(nullptr, lldb::eAccessPublic, type_name.GetCString(), + clang::TTK_Struct, lldb::eLanguageTypeC); + StartTagDeclarationDefinition(type); + for (const auto &field : type_fields) + AddFieldToRecordType(type, field.first, field.second, lldb::eAccessPublic, + 0); + if (packed) + SetIsPacked(type); + CompleteTagDeclarationDefinition(type); + return type; +} + +CompilerType ClangASTContext::GetOrCreateStructForIdentifier( + const ConstString &type_name, + const std::initializer_list<std::pair<const char *, CompilerType>> + &type_fields, + bool packed) { + CompilerType type; + if ((type = GetTypeForIdentifier<clang::CXXRecordDecl>(type_name)).IsValid()) + return type; -CompilerType -ClangASTContext::CreateBlockPointerType (const CompilerType &function_type) -{ - QualType block_type = m_ast_ap->getBlockPointerType(clang::QualType::getFromOpaquePtr(function_type.GetOpaqueQualType())); - - return CompilerType (this, block_type.getAsOpaquePtr()); + return CreateStructForIdentifier(type_name, type_fields, packed); } -#pragma mark Array Types - -CompilerType -ClangASTContext::CreateArrayType (const CompilerType &element_type, - size_t element_count, - bool is_vector) -{ - if (element_type.IsValid()) - { - ASTContext *ast = getASTContext(); - assert (ast != nullptr); - - if (is_vector) - { - return CompilerType(ast, ast->getExtVectorType(ClangUtil::GetQualType(element_type), element_count)); - } - else - { - - llvm::APInt ap_element_count (64, element_count); - if (element_count == 0) - { - return CompilerType(ast, ast->getIncompleteArrayType(ClangUtil::GetQualType(element_type), - clang::ArrayType::Normal, 0)); - } - else - { - return CompilerType(ast, ast->getConstantArrayType(ClangUtil::GetQualType(element_type), - ap_element_count, clang::ArrayType::Normal, 0)); - } - } - } - return CompilerType(); -} +#pragma mark Enumeration Types CompilerType -ClangASTContext::CreateStructForIdentifier (const ConstString &type_name, - const std::initializer_list< std::pair < const char *, CompilerType > >& type_fields, - bool packed) -{ - CompilerType type; - if (!type_name.IsEmpty() && (type = GetTypeForIdentifier<clang::CXXRecordDecl>(type_name)).IsValid()) - { - lldbassert("Trying to create a type for an existing name"); - return type; - } - - type = CreateRecordType(nullptr, lldb::eAccessPublic, type_name.GetCString(), clang::TTK_Struct, lldb::eLanguageTypeC); - StartTagDeclarationDefinition(type); - for (const auto& field : type_fields) - AddFieldToRecordType(type, field.first, field.second, lldb::eAccessPublic, 0); - if (packed) - SetIsPacked(type); - CompleteTagDeclarationDefinition(type); - return type; -} +ClangASTContext::CreateEnumerationType(const char *name, DeclContext *decl_ctx, + const Declaration &decl, + const CompilerType &integer_clang_type) { + // TODO: Do something intelligent with the Declaration object passed in + // like maybe filling in the SourceLocation with it... + ASTContext *ast = getASTContext(); -CompilerType -ClangASTContext::GetOrCreateStructForIdentifier (const ConstString &type_name, - const std::initializer_list< std::pair < const char *, CompilerType > >& type_fields, - bool packed) -{ - CompilerType type; - if ((type = GetTypeForIdentifier<clang::CXXRecordDecl>(type_name)).IsValid()) - return type; + // TODO: ask about these... + // const bool IsScoped = false; + // const bool IsFixed = false; - return CreateStructForIdentifier (type_name, - type_fields, - packed); -} + EnumDecl *enum_decl = EnumDecl::Create( + *ast, decl_ctx, SourceLocation(), SourceLocation(), + name && name[0] ? &ast->Idents.get(name) : nullptr, nullptr, + false, // IsScoped + false, // IsScopedUsingClassTag + false); // IsFixed -#pragma mark Enumeration Types + if (enum_decl) { + // TODO: check if we should be setting the promotion type too? + enum_decl->setIntegerType(ClangUtil::GetQualType(integer_clang_type)); -CompilerType -ClangASTContext::CreateEnumerationType -( - const char *name, - DeclContext *decl_ctx, - const Declaration &decl, - const CompilerType &integer_clang_type - ) -{ - // TODO: Do something intelligent with the Declaration object passed in - // like maybe filling in the SourceLocation with it... - ASTContext *ast = getASTContext(); - - // TODO: ask about these... - // const bool IsScoped = false; - // const bool IsFixed = false; - - EnumDecl *enum_decl = EnumDecl::Create (*ast, - decl_ctx, - SourceLocation(), - SourceLocation(), - name && name[0] ? &ast->Idents.get(name) : nullptr, - nullptr, - false, // IsScoped - false, // IsScopedUsingClassTag - false); // IsFixed - - - if (enum_decl) - { - // TODO: check if we should be setting the promotion type too? - enum_decl->setIntegerType(ClangUtil::GetQualType(integer_clang_type)); + enum_decl->setAccess(AS_public); // TODO respect what's in the debug info - enum_decl->setAccess(AS_public); // TODO respect what's in the debug info - - return CompilerType (ast, ast->getTagDeclType(enum_decl)); - } - return CompilerType(); + return CompilerType(ast, ast->getTagDeclType(enum_decl)); + } + return CompilerType(); } // Disable this for now since I can't seem to get a nicely formatted float @@ -2455,8 +2177,10 @@ ClangASTContext::CreateEnumerationType // would like to get perfect string values for any kind of float semantics // so we can support remote targets. The code below also requires a patch to // llvm::APInt. -//bool -//ClangASTContext::ConvertFloatValueToString (ASTContext *ast, lldb::opaque_compiler_type_t clang_type, const uint8_t* bytes, size_t byte_size, int apint_byte_order, std::string &float_str) +// bool +// ClangASTContext::ConvertFloatValueToString (ASTContext *ast, +// lldb::opaque_compiler_type_t clang_type, const uint8_t* bytes, size_t +// byte_size, int apint_byte_order, std::string &float_str) //{ // uint32_t count = 0; // bool is_complex = false; @@ -2469,14 +2193,16 @@ ClangASTContext::CreateEnumerationType // uint32_t i; // for (i=0; i<count; i++) // { -// APInt ap_int(num_bits_per_float, bytes + i * num_bytes_per_float, (APInt::ByteOrder)apint_byte_order); +// APInt ap_int(num_bits_per_float, bytes + i * num_bytes_per_float, +// (APInt::ByteOrder)apint_byte_order); // bool is_ieee = false; // APFloat ap_float(ap_int, is_ieee); // char s[1024]; // unsigned int hex_digits = 0; // bool upper_case = false; // -// if (ap_float.convertToHexString(s, hex_digits, upper_case, APFloat::rmNearestTiesToEven) > 0) +// if (ap_float.convertToHexString(s, hex_digits, upper_case, +// APFloat::rmNearestTiesToEven) > 0) // { // if (i > 0) // float_str.append(", "); @@ -2490,2051 +2216,2116 @@ ClangASTContext::CreateEnumerationType // return false; //} -CompilerType -ClangASTContext::GetIntTypeFromBitSize (clang::ASTContext *ast, - size_t bit_size, bool is_signed) -{ - if (ast) - { - if (is_signed) - { - if (bit_size == ast->getTypeSize(ast->SignedCharTy)) - return CompilerType(ast, ast->SignedCharTy); - - if (bit_size == ast->getTypeSize(ast->ShortTy)) - return CompilerType(ast, ast->ShortTy); - - if (bit_size == ast->getTypeSize(ast->IntTy)) - return CompilerType(ast, ast->IntTy); - - if (bit_size == ast->getTypeSize(ast->LongTy)) - return CompilerType(ast, ast->LongTy); - - if (bit_size == ast->getTypeSize(ast->LongLongTy)) - return CompilerType(ast, ast->LongLongTy); - - if (bit_size == ast->getTypeSize(ast->Int128Ty)) - return CompilerType(ast, ast->Int128Ty); +CompilerType ClangASTContext::GetIntTypeFromBitSize(clang::ASTContext *ast, + size_t bit_size, + bool is_signed) { + if (ast) { + if (is_signed) { + if (bit_size == ast->getTypeSize(ast->SignedCharTy)) + return CompilerType(ast, ast->SignedCharTy); + + if (bit_size == ast->getTypeSize(ast->ShortTy)) + return CompilerType(ast, ast->ShortTy); + + if (bit_size == ast->getTypeSize(ast->IntTy)) + return CompilerType(ast, ast->IntTy); + + if (bit_size == ast->getTypeSize(ast->LongTy)) + return CompilerType(ast, ast->LongTy); + + if (bit_size == ast->getTypeSize(ast->LongLongTy)) + return CompilerType(ast, ast->LongLongTy); + + if (bit_size == ast->getTypeSize(ast->Int128Ty)) + return CompilerType(ast, ast->Int128Ty); + } else { + if (bit_size == ast->getTypeSize(ast->UnsignedCharTy)) + return CompilerType(ast, ast->UnsignedCharTy); + + if (bit_size == ast->getTypeSize(ast->UnsignedShortTy)) + return CompilerType(ast, ast->UnsignedShortTy); + + if (bit_size == ast->getTypeSize(ast->UnsignedIntTy)) + return CompilerType(ast, ast->UnsignedIntTy); + + if (bit_size == ast->getTypeSize(ast->UnsignedLongTy)) + return CompilerType(ast, ast->UnsignedLongTy); + + if (bit_size == ast->getTypeSize(ast->UnsignedLongLongTy)) + return CompilerType(ast, ast->UnsignedLongLongTy); + + if (bit_size == ast->getTypeSize(ast->UnsignedInt128Ty)) + return CompilerType(ast, ast->UnsignedInt128Ty); + } + } + return CompilerType(); +} + +CompilerType ClangASTContext::GetPointerSizedIntType(clang::ASTContext *ast, + bool is_signed) { + if (ast) + return GetIntTypeFromBitSize(ast, ast->getTypeSize(ast->VoidPtrTy), + is_signed); + return CompilerType(); +} + +void ClangASTContext::DumpDeclContextHiearchy(clang::DeclContext *decl_ctx) { + if (decl_ctx) { + DumpDeclContextHiearchy(decl_ctx->getParent()); + + clang::NamedDecl *named_decl = llvm::dyn_cast<clang::NamedDecl>(decl_ctx); + if (named_decl) { + printf("%20s: %s\n", decl_ctx->getDeclKindName(), + named_decl->getDeclName().getAsString().c_str()); + } else { + printf("%20s\n", decl_ctx->getDeclKindName()); + } + } +} + +void ClangASTContext::DumpDeclHiearchy(clang::Decl *decl) { + if (decl == nullptr) + return; + DumpDeclContextHiearchy(decl->getDeclContext()); + + clang::RecordDecl *record_decl = llvm::dyn_cast<clang::RecordDecl>(decl); + if (record_decl) { + printf("%20s: %s%s\n", decl->getDeclKindName(), + record_decl->getDeclName().getAsString().c_str(), + record_decl->isInjectedClassName() ? " (injected class name)" : ""); + + } else { + clang::NamedDecl *named_decl = llvm::dyn_cast<clang::NamedDecl>(decl); + if (named_decl) { + printf("%20s: %s\n", decl->getDeclKindName(), + named_decl->getDeclName().getAsString().c_str()); + } else { + printf("%20s\n", decl->getDeclKindName()); + } + } +} + +bool ClangASTContext::DeclsAreEquivalent(clang::Decl *lhs_decl, + clang::Decl *rhs_decl) { + if (lhs_decl && rhs_decl) { + //---------------------------------------------------------------------- + // Make sure the decl kinds match first + //---------------------------------------------------------------------- + const clang::Decl::Kind lhs_decl_kind = lhs_decl->getKind(); + const clang::Decl::Kind rhs_decl_kind = rhs_decl->getKind(); + + if (lhs_decl_kind == rhs_decl_kind) { + //------------------------------------------------------------------ + // Now check that the decl contexts kinds are all equivalent + // before we have to check any names of the decl contexts... + //------------------------------------------------------------------ + clang::DeclContext *lhs_decl_ctx = lhs_decl->getDeclContext(); + clang::DeclContext *rhs_decl_ctx = rhs_decl->getDeclContext(); + if (lhs_decl_ctx && rhs_decl_ctx) { + while (1) { + if (lhs_decl_ctx && rhs_decl_ctx) { + const clang::Decl::Kind lhs_decl_ctx_kind = + lhs_decl_ctx->getDeclKind(); + const clang::Decl::Kind rhs_decl_ctx_kind = + rhs_decl_ctx->getDeclKind(); + if (lhs_decl_ctx_kind == rhs_decl_ctx_kind) { + lhs_decl_ctx = lhs_decl_ctx->getParent(); + rhs_decl_ctx = rhs_decl_ctx->getParent(); + + if (lhs_decl_ctx == nullptr && rhs_decl_ctx == nullptr) + break; + } else + return false; + } else + return false; } - else - { - if (bit_size == ast->getTypeSize(ast->UnsignedCharTy)) - return CompilerType(ast, ast->UnsignedCharTy); - - if (bit_size == ast->getTypeSize(ast->UnsignedShortTy)) - return CompilerType(ast, ast->UnsignedShortTy); - - if (bit_size == ast->getTypeSize(ast->UnsignedIntTy)) - return CompilerType(ast, ast->UnsignedIntTy); - - if (bit_size == ast->getTypeSize(ast->UnsignedLongTy)) - return CompilerType(ast, ast->UnsignedLongTy); - - if (bit_size == ast->getTypeSize(ast->UnsignedLongLongTy)) - return CompilerType(ast, ast->UnsignedLongLongTy); - - if (bit_size == ast->getTypeSize(ast->UnsignedInt128Ty)) - return CompilerType(ast, ast->UnsignedInt128Ty); + + //-------------------------------------------------------------- + // Now make sure the name of the decls match + //-------------------------------------------------------------- + clang::NamedDecl *lhs_named_decl = + llvm::dyn_cast<clang::NamedDecl>(lhs_decl); + clang::NamedDecl *rhs_named_decl = + llvm::dyn_cast<clang::NamedDecl>(rhs_decl); + if (lhs_named_decl && rhs_named_decl) { + clang::DeclarationName lhs_decl_name = lhs_named_decl->getDeclName(); + clang::DeclarationName rhs_decl_name = rhs_named_decl->getDeclName(); + if (lhs_decl_name.getNameKind() == rhs_decl_name.getNameKind()) { + if (lhs_decl_name.getAsString() != rhs_decl_name.getAsString()) + return false; + } else + return false; + } else + return false; + + //-------------------------------------------------------------- + // We know that the decl context kinds all match, so now we need + // to make sure the names match as well + //-------------------------------------------------------------- + lhs_decl_ctx = lhs_decl->getDeclContext(); + rhs_decl_ctx = rhs_decl->getDeclContext(); + while (1) { + switch (lhs_decl_ctx->getDeclKind()) { + case clang::Decl::TranslationUnit: + // We don't care about the translation unit names + return true; + default: { + clang::NamedDecl *lhs_named_decl = + llvm::dyn_cast<clang::NamedDecl>(lhs_decl_ctx); + clang::NamedDecl *rhs_named_decl = + llvm::dyn_cast<clang::NamedDecl>(rhs_decl_ctx); + if (lhs_named_decl && rhs_named_decl) { + clang::DeclarationName lhs_decl_name = + lhs_named_decl->getDeclName(); + clang::DeclarationName rhs_decl_name = + rhs_named_decl->getDeclName(); + if (lhs_decl_name.getNameKind() == rhs_decl_name.getNameKind()) { + if (lhs_decl_name.getAsString() != rhs_decl_name.getAsString()) + return false; + } else + return false; + } else + return false; + } break; + } + lhs_decl_ctx = lhs_decl_ctx->getParent(); + rhs_decl_ctx = rhs_decl_ctx->getParent(); } + } } - return CompilerType(); + } + return false; } +bool ClangASTContext::GetCompleteDecl(clang::ASTContext *ast, + clang::Decl *decl) { + if (!decl) + return false; -CompilerType -ClangASTContext::GetPointerSizedIntType (clang::ASTContext *ast, bool is_signed) -{ - if (ast) - return GetIntTypeFromBitSize(ast, ast->getTypeSize(ast->VoidPtrTy), is_signed); - return CompilerType(); -} + ExternalASTSource *ast_source = ast->getExternalSource(); -void -ClangASTContext::DumpDeclContextHiearchy (clang::DeclContext *decl_ctx) -{ - if (decl_ctx) - { - DumpDeclContextHiearchy (decl_ctx->getParent()); + if (!ast_source) + return false; - clang::NamedDecl *named_decl = llvm::dyn_cast<clang::NamedDecl>(decl_ctx); - if (named_decl) - { - printf ("%20s: %s\n", decl_ctx->getDeclKindName(), named_decl->getDeclName().getAsString().c_str()); - } - else - { - printf ("%20s\n", decl_ctx->getDeclKindName()); - } - } -} + if (clang::TagDecl *tag_decl = llvm::dyn_cast<clang::TagDecl>(decl)) { + if (tag_decl->isCompleteDefinition()) + return true; -void -ClangASTContext::DumpDeclHiearchy (clang::Decl *decl) -{ - if (decl == nullptr) - return; - DumpDeclContextHiearchy(decl->getDeclContext()); + if (!tag_decl->hasExternalLexicalStorage()) + return false; - clang::RecordDecl *record_decl = llvm::dyn_cast<clang::RecordDecl>(decl); - if (record_decl) - { - printf ("%20s: %s%s\n", decl->getDeclKindName(), record_decl->getDeclName().getAsString().c_str(), record_decl->isInjectedClassName() ? " (injected class name)" : ""); + ast_source->CompleteType(tag_decl); - } - else - { - clang::NamedDecl *named_decl = llvm::dyn_cast<clang::NamedDecl>(decl); - if (named_decl) - { - printf ("%20s: %s\n", decl->getDeclKindName(), named_decl->getDeclName().getAsString().c_str()); - } - else - { - printf ("%20s\n", decl->getDeclKindName()); - } - } -} + return !tag_decl->getTypeForDecl()->isIncompleteType(); + } else if (clang::ObjCInterfaceDecl *objc_interface_decl = + llvm::dyn_cast<clang::ObjCInterfaceDecl>(decl)) { + if (objc_interface_decl->getDefinition()) + return true; -bool -ClangASTContext::DeclsAreEquivalent (clang::Decl *lhs_decl, clang::Decl *rhs_decl) -{ - if (lhs_decl && rhs_decl) - { - //---------------------------------------------------------------------- - // Make sure the decl kinds match first - //---------------------------------------------------------------------- - const clang::Decl::Kind lhs_decl_kind = lhs_decl->getKind(); - const clang::Decl::Kind rhs_decl_kind = rhs_decl->getKind(); - - if (lhs_decl_kind == rhs_decl_kind) - { - //------------------------------------------------------------------ - // Now check that the decl contexts kinds are all equivalent - // before we have to check any names of the decl contexts... - //------------------------------------------------------------------ - clang::DeclContext *lhs_decl_ctx = lhs_decl->getDeclContext(); - clang::DeclContext *rhs_decl_ctx = rhs_decl->getDeclContext(); - if (lhs_decl_ctx && rhs_decl_ctx) - { - while (1) - { - if (lhs_decl_ctx && rhs_decl_ctx) - { - const clang::Decl::Kind lhs_decl_ctx_kind = lhs_decl_ctx->getDeclKind(); - const clang::Decl::Kind rhs_decl_ctx_kind = rhs_decl_ctx->getDeclKind(); - if (lhs_decl_ctx_kind == rhs_decl_ctx_kind) - { - lhs_decl_ctx = lhs_decl_ctx->getParent(); - rhs_decl_ctx = rhs_decl_ctx->getParent(); - - if (lhs_decl_ctx == nullptr && rhs_decl_ctx == nullptr) - break; - } - else - return false; - } - else - return false; - } + if (!objc_interface_decl->hasExternalLexicalStorage()) + return false; - //-------------------------------------------------------------- - // Now make sure the name of the decls match - //-------------------------------------------------------------- - clang::NamedDecl *lhs_named_decl = llvm::dyn_cast<clang::NamedDecl>(lhs_decl); - clang::NamedDecl *rhs_named_decl = llvm::dyn_cast<clang::NamedDecl>(rhs_decl); - if (lhs_named_decl && rhs_named_decl) - { - clang::DeclarationName lhs_decl_name = lhs_named_decl->getDeclName(); - clang::DeclarationName rhs_decl_name = rhs_named_decl->getDeclName(); - if (lhs_decl_name.getNameKind() == rhs_decl_name.getNameKind()) - { - if (lhs_decl_name.getAsString() != rhs_decl_name.getAsString()) - return false; - } - else - return false; - } - else - return false; - - //-------------------------------------------------------------- - // We know that the decl context kinds all match, so now we need - // to make sure the names match as well - //-------------------------------------------------------------- - lhs_decl_ctx = lhs_decl->getDeclContext(); - rhs_decl_ctx = rhs_decl->getDeclContext(); - while (1) - { - switch (lhs_decl_ctx->getDeclKind()) - { - case clang::Decl::TranslationUnit: - // We don't care about the translation unit names - return true; - default: - { - clang::NamedDecl *lhs_named_decl = llvm::dyn_cast<clang::NamedDecl>(lhs_decl_ctx); - clang::NamedDecl *rhs_named_decl = llvm::dyn_cast<clang::NamedDecl>(rhs_decl_ctx); - if (lhs_named_decl && rhs_named_decl) - { - clang::DeclarationName lhs_decl_name = lhs_named_decl->getDeclName(); - clang::DeclarationName rhs_decl_name = rhs_named_decl->getDeclName(); - if (lhs_decl_name.getNameKind() == rhs_decl_name.getNameKind()) - { - if (lhs_decl_name.getAsString() != rhs_decl_name.getAsString()) - return false; - } - else - return false; - } - else - return false; - } - break; + ast_source->CompleteType(objc_interface_decl); - } - lhs_decl_ctx = lhs_decl_ctx->getParent(); - rhs_decl_ctx = rhs_decl_ctx->getParent(); - } - } - } - } + return !objc_interface_decl->getTypeForDecl()->isIncompleteType(); + } else { return false; -} -bool -ClangASTContext::GetCompleteDecl (clang::ASTContext *ast, - clang::Decl *decl) -{ - if (!decl) - return false; - - ExternalASTSource *ast_source = ast->getExternalSource(); - - if (!ast_source) - return false; - - if (clang::TagDecl *tag_decl = llvm::dyn_cast<clang::TagDecl>(decl)) - { - if (tag_decl->isCompleteDefinition()) - return true; - - if (!tag_decl->hasExternalLexicalStorage()) - return false; - - ast_source->CompleteType(tag_decl); - - return !tag_decl->getTypeForDecl()->isIncompleteType(); - } - else if (clang::ObjCInterfaceDecl *objc_interface_decl = llvm::dyn_cast<clang::ObjCInterfaceDecl>(decl)) - { - if (objc_interface_decl->getDefinition()) - return true; - - if (!objc_interface_decl->hasExternalLexicalStorage()) - return false; - - ast_source->CompleteType(objc_interface_decl); - - return !objc_interface_decl->getTypeForDecl()->isIncompleteType(); - } - else - { - return false; - } + } } -void -ClangASTContext::SetMetadataAsUserID (const void *object, - user_id_t user_id) -{ - ClangASTMetadata meta_data; - meta_data.SetUserID (user_id); - SetMetadata (object, meta_data); +void ClangASTContext::SetMetadataAsUserID(const void *object, + user_id_t user_id) { + ClangASTMetadata meta_data; + meta_data.SetUserID(user_id); + SetMetadata(object, meta_data); } -void -ClangASTContext::SetMetadata (clang::ASTContext *ast, - const void *object, - ClangASTMetadata &metadata) -{ - ClangExternalASTSourceCommon *external_source = - ClangExternalASTSourceCommon::Lookup(ast->getExternalSource()); - - if (external_source) - external_source->SetMetadata(object, metadata); -} +void ClangASTContext::SetMetadata(clang::ASTContext *ast, const void *object, + ClangASTMetadata &metadata) { + ClangExternalASTSourceCommon *external_source = + ClangExternalASTSourceCommon::Lookup(ast->getExternalSource()); -ClangASTMetadata * -ClangASTContext::GetMetadata (clang::ASTContext *ast, - const void *object) -{ - ClangExternalASTSourceCommon *external_source = - ClangExternalASTSourceCommon::Lookup(ast->getExternalSource()); - - if (external_source && external_source->HasMetadata(object)) - return external_source->GetMetadata(object); - else - return nullptr; + if (external_source) + external_source->SetMetadata(object, metadata); } -clang::DeclContext * -ClangASTContext::GetAsDeclContext (clang::CXXMethodDecl *cxx_method_decl) -{ - return llvm::dyn_cast<clang::DeclContext>(cxx_method_decl); +ClangASTMetadata *ClangASTContext::GetMetadata(clang::ASTContext *ast, + const void *object) { + ClangExternalASTSourceCommon *external_source = + ClangExternalASTSourceCommon::Lookup(ast->getExternalSource()); + + if (external_source && external_source->HasMetadata(object)) + return external_source->GetMetadata(object); + else + return nullptr; } clang::DeclContext * -ClangASTContext::GetAsDeclContext (clang::ObjCMethodDecl *objc_method_decl) -{ - return llvm::dyn_cast<clang::DeclContext>(objc_method_decl); +ClangASTContext::GetAsDeclContext(clang::CXXMethodDecl *cxx_method_decl) { + return llvm::dyn_cast<clang::DeclContext>(cxx_method_decl); } -bool -ClangASTContext::SetTagTypeKind (clang::QualType tag_qual_type, int kind) const -{ - const clang::Type *clang_type = tag_qual_type.getTypePtr(); - if (clang_type) - { - const clang::TagType *tag_type = llvm::dyn_cast<clang::TagType>(clang_type); - if (tag_type) - { - clang::TagDecl *tag_decl = llvm::dyn_cast<clang::TagDecl>(tag_type->getDecl()); - if (tag_decl) - { - tag_decl->setTagKind ((clang::TagDecl::TagKind)kind); - return true; - } - } +clang::DeclContext * +ClangASTContext::GetAsDeclContext(clang::ObjCMethodDecl *objc_method_decl) { + return llvm::dyn_cast<clang::DeclContext>(objc_method_decl); +} + +bool ClangASTContext::SetTagTypeKind(clang::QualType tag_qual_type, + int kind) const { + const clang::Type *clang_type = tag_qual_type.getTypePtr(); + if (clang_type) { + const clang::TagType *tag_type = llvm::dyn_cast<clang::TagType>(clang_type); + if (tag_type) { + clang::TagDecl *tag_decl = + llvm::dyn_cast<clang::TagDecl>(tag_type->getDecl()); + if (tag_decl) { + tag_decl->setTagKind((clang::TagDecl::TagKind)kind); + return true; + } } - return false; + } + return false; } - -bool -ClangASTContext::SetDefaultAccessForRecordFields (clang::RecordDecl* record_decl, - int default_accessibility, - int *assigned_accessibilities, - size_t num_assigned_accessibilities) -{ - if (record_decl) - { - uint32_t field_idx; - clang::RecordDecl::field_iterator field, field_end; - for (field = record_decl->field_begin(), field_end = record_decl->field_end(), field_idx = 0; - field != field_end; - ++field, ++field_idx) - { - // If no accessibility was assigned, assign the correct one - if (field_idx < num_assigned_accessibilities && assigned_accessibilities[field_idx] == clang::AS_none) - field->setAccess ((clang::AccessSpecifier)default_accessibility); - } - return true; +bool ClangASTContext::SetDefaultAccessForRecordFields( + clang::RecordDecl *record_decl, int default_accessibility, + int *assigned_accessibilities, size_t num_assigned_accessibilities) { + if (record_decl) { + uint32_t field_idx; + clang::RecordDecl::field_iterator field, field_end; + for (field = record_decl->field_begin(), + field_end = record_decl->field_end(), field_idx = 0; + field != field_end; ++field, ++field_idx) { + // If no accessibility was assigned, assign the correct one + if (field_idx < num_assigned_accessibilities && + assigned_accessibilities[field_idx] == clang::AS_none) + field->setAccess((clang::AccessSpecifier)default_accessibility); } - return false; + return true; + } + return false; } clang::DeclContext * -ClangASTContext::GetDeclContextForType (const CompilerType& type) -{ - return GetDeclContextForType(ClangUtil::GetQualType(type)); +ClangASTContext::GetDeclContextForType(const CompilerType &type) { + return GetDeclContextForType(ClangUtil::GetQualType(type)); } clang::DeclContext * -ClangASTContext::GetDeclContextForType (clang::QualType type) -{ - if (type.isNull()) - return nullptr; - - clang::QualType qual_type = type.getCanonicalType(); - const clang::Type::TypeClass type_class = qual_type->getTypeClass(); - switch (type_class) - { - case clang::Type::ObjCInterface: return llvm::cast<clang::ObjCObjectType>(qual_type.getTypePtr())->getInterface(); - case clang::Type::ObjCObjectPointer: return GetDeclContextForType (llvm::cast<clang::ObjCObjectPointerType>(qual_type.getTypePtr())->getPointeeType()); - case clang::Type::Record: return llvm::cast<clang::RecordType>(qual_type)->getDecl(); - case clang::Type::Enum: return llvm::cast<clang::EnumType>(qual_type)->getDecl(); - case clang::Type::Typedef: return GetDeclContextForType (llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType()); - case clang::Type::Auto: return GetDeclContextForType (llvm::cast<clang::AutoType>(qual_type)->getDeducedType()); - case clang::Type::Elaborated: return GetDeclContextForType (llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType()); - case clang::Type::Paren: return GetDeclContextForType (llvm::cast<clang::ParenType>(qual_type)->desugar()); - default: - break; - } - // No DeclContext in this type... +ClangASTContext::GetDeclContextForType(clang::QualType type) { + if (type.isNull()) return nullptr; -} -static bool -GetCompleteQualType (clang::ASTContext *ast, clang::QualType qual_type, bool allow_completion = true) -{ - const clang::Type::TypeClass type_class = qual_type->getTypeClass(); - switch (type_class) - { - case clang::Type::ConstantArray: - case clang::Type::IncompleteArray: - case clang::Type::VariableArray: - { - const clang::ArrayType *array_type = llvm::dyn_cast<clang::ArrayType>(qual_type.getTypePtr()); - - if (array_type) - return GetCompleteQualType (ast, array_type->getElementType(), allow_completion); - } - break; - case clang::Type::Record: - { - clang::CXXRecordDecl *cxx_record_decl = qual_type->getAsCXXRecordDecl(); - if (cxx_record_decl) - { - if (cxx_record_decl->hasExternalLexicalStorage()) - { - const bool is_complete = cxx_record_decl->isCompleteDefinition(); - const bool fields_loaded = cxx_record_decl->hasLoadedFieldsFromExternalStorage(); - if (is_complete && fields_loaded) - return true; - - if (!allow_completion) - return false; - - // Call the field_begin() accessor to for it to use the external source - // to load the fields... - clang::ExternalASTSource *external_ast_source = ast->getExternalSource(); - if (external_ast_source) - { - external_ast_source->CompleteType(cxx_record_decl); - if (cxx_record_decl->isCompleteDefinition()) - { - cxx_record_decl->field_begin(); - cxx_record_decl->setHasLoadedFieldsFromExternalStorage (true); - } - } - } - } - const clang::TagType *tag_type = llvm::cast<clang::TagType>(qual_type.getTypePtr()); - return !tag_type->isIncompleteType(); + clang::QualType qual_type = type.getCanonicalType(); + const clang::Type::TypeClass type_class = qual_type->getTypeClass(); + switch (type_class) { + case clang::Type::ObjCInterface: + return llvm::cast<clang::ObjCObjectType>(qual_type.getTypePtr()) + ->getInterface(); + case clang::Type::ObjCObjectPointer: + return GetDeclContextForType( + llvm::cast<clang::ObjCObjectPointerType>(qual_type.getTypePtr()) + ->getPointeeType()); + case clang::Type::Record: + return llvm::cast<clang::RecordType>(qual_type)->getDecl(); + case clang::Type::Enum: + return llvm::cast<clang::EnumType>(qual_type)->getDecl(); + case clang::Type::Typedef: + return GetDeclContextForType(llvm::cast<clang::TypedefType>(qual_type) + ->getDecl() + ->getUnderlyingType()); + case clang::Type::Auto: + return GetDeclContextForType( + llvm::cast<clang::AutoType>(qual_type)->getDeducedType()); + case clang::Type::Elaborated: + return GetDeclContextForType( + llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType()); + case clang::Type::Paren: + return GetDeclContextForType( + llvm::cast<clang::ParenType>(qual_type)->desugar()); + default: + break; + } + // No DeclContext in this type... + return nullptr; +} + +static bool GetCompleteQualType(clang::ASTContext *ast, + clang::QualType qual_type, + bool allow_completion = true) { + const clang::Type::TypeClass type_class = qual_type->getTypeClass(); + switch (type_class) { + case clang::Type::ConstantArray: + case clang::Type::IncompleteArray: + case clang::Type::VariableArray: { + const clang::ArrayType *array_type = + llvm::dyn_cast<clang::ArrayType>(qual_type.getTypePtr()); + + if (array_type) + return GetCompleteQualType(ast, array_type->getElementType(), + allow_completion); + } break; + case clang::Type::Record: { + clang::CXXRecordDecl *cxx_record_decl = qual_type->getAsCXXRecordDecl(); + if (cxx_record_decl) { + if (cxx_record_decl->hasExternalLexicalStorage()) { + const bool is_complete = cxx_record_decl->isCompleteDefinition(); + const bool fields_loaded = + cxx_record_decl->hasLoadedFieldsFromExternalStorage(); + if (is_complete && fields_loaded) + return true; + + if (!allow_completion) + return false; + + // Call the field_begin() accessor to for it to use the external source + // to load the fields... + clang::ExternalASTSource *external_ast_source = + ast->getExternalSource(); + if (external_ast_source) { + external_ast_source->CompleteType(cxx_record_decl); + if (cxx_record_decl->isCompleteDefinition()) { + cxx_record_decl->field_begin(); + cxx_record_decl->setHasLoadedFieldsFromExternalStorage(true); + } + } + } + } + const clang::TagType *tag_type = + llvm::cast<clang::TagType>(qual_type.getTypePtr()); + return !tag_type->isIncompleteType(); + } break; + + case clang::Type::Enum: { + const clang::TagType *tag_type = + llvm::dyn_cast<clang::TagType>(qual_type.getTypePtr()); + if (tag_type) { + clang::TagDecl *tag_decl = tag_type->getDecl(); + if (tag_decl) { + if (tag_decl->getDefinition()) + return true; + + if (!allow_completion) + return false; + + if (tag_decl->hasExternalLexicalStorage()) { + if (ast) { + clang::ExternalASTSource *external_ast_source = + ast->getExternalSource(); + if (external_ast_source) { + external_ast_source->CompleteType(tag_decl); + return !tag_type->isIncompleteType(); } - break; + } + } + return false; + } + } - case clang::Type::Enum: - { - const clang::TagType *tag_type = llvm::dyn_cast<clang::TagType>(qual_type.getTypePtr()); - if (tag_type) - { - clang::TagDecl *tag_decl = tag_type->getDecl(); - if (tag_decl) - { - if (tag_decl->getDefinition()) - return true; - - if (!allow_completion) - return false; - - if (tag_decl->hasExternalLexicalStorage()) - { - if (ast) - { - clang::ExternalASTSource *external_ast_source = ast->getExternalSource(); - if (external_ast_source) - { - external_ast_source->CompleteType(tag_decl); - return !tag_type->isIncompleteType(); - } - } - } - return false; - } - } - - } - break; - case clang::Type::ObjCObject: - case clang::Type::ObjCInterface: - { - const clang::ObjCObjectType *objc_class_type = llvm::dyn_cast<clang::ObjCObjectType>(qual_type); - if (objc_class_type) - { - clang::ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface(); - // We currently can't complete objective C types through the newly added ASTContext - // because it only supports TagDecl objects right now... - if (class_interface_decl) - { - if (class_interface_decl->getDefinition()) - return true; - - if (!allow_completion) - return false; - - if (class_interface_decl->hasExternalLexicalStorage()) - { - if (ast) - { - clang::ExternalASTSource *external_ast_source = ast->getExternalSource(); - if (external_ast_source) - { - external_ast_source->CompleteType (class_interface_decl); - return !objc_class_type->isIncompleteType(); - } - } - } - return false; - } - } + } break; + case clang::Type::ObjCObject: + case clang::Type::ObjCInterface: { + const clang::ObjCObjectType *objc_class_type = + llvm::dyn_cast<clang::ObjCObjectType>(qual_type); + if (objc_class_type) { + clang::ObjCInterfaceDecl *class_interface_decl = + objc_class_type->getInterface(); + // We currently can't complete objective C types through the newly added + // ASTContext + // because it only supports TagDecl objects right now... + if (class_interface_decl) { + if (class_interface_decl->getDefinition()) + return true; + + if (!allow_completion) + return false; + + if (class_interface_decl->hasExternalLexicalStorage()) { + if (ast) { + clang::ExternalASTSource *external_ast_source = + ast->getExternalSource(); + if (external_ast_source) { + external_ast_source->CompleteType(class_interface_decl); + return !objc_class_type->isIncompleteType(); } - break; - - case clang::Type::Typedef: - return GetCompleteQualType (ast, llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType(), allow_completion); - - case clang::Type::Auto: - return GetCompleteQualType (ast, llvm::cast<clang::AutoType>(qual_type)->getDeducedType(), allow_completion); - - case clang::Type::Elaborated: - return GetCompleteQualType (ast, llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType(), allow_completion); - - case clang::Type::Paren: - return GetCompleteQualType (ast, llvm::cast<clang::ParenType>(qual_type)->desugar(), allow_completion); - - case clang::Type::Attributed: - return GetCompleteQualType (ast, llvm::cast<clang::AttributedType>(qual_type)->getModifiedType(), allow_completion); - - default: - break; + } + } + return false; + } } - - return true; + } break; + + case clang::Type::Typedef: + return GetCompleteQualType(ast, llvm::cast<clang::TypedefType>(qual_type) + ->getDecl() + ->getUnderlyingType(), + allow_completion); + + case clang::Type::Auto: + return GetCompleteQualType( + ast, llvm::cast<clang::AutoType>(qual_type)->getDeducedType(), + allow_completion); + + case clang::Type::Elaborated: + return GetCompleteQualType( + ast, llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType(), + allow_completion); + + case clang::Type::Paren: + return GetCompleteQualType( + ast, llvm::cast<clang::ParenType>(qual_type)->desugar(), + allow_completion); + + case clang::Type::Attributed: + return GetCompleteQualType( + ast, llvm::cast<clang::AttributedType>(qual_type)->getModifiedType(), + allow_completion); + + default: + break; + } + + return true; } static clang::ObjCIvarDecl::AccessControl -ConvertAccessTypeToObjCIvarAccessControl (AccessType access) -{ - switch (access) - { - case eAccessNone: return clang::ObjCIvarDecl::None; - case eAccessPublic: return clang::ObjCIvarDecl::Public; - case eAccessPrivate: return clang::ObjCIvarDecl::Private; - case eAccessProtected: return clang::ObjCIvarDecl::Protected; - case eAccessPackage: return clang::ObjCIvarDecl::Package; - } +ConvertAccessTypeToObjCIvarAccessControl(AccessType access) { + switch (access) { + case eAccessNone: return clang::ObjCIvarDecl::None; + case eAccessPublic: + return clang::ObjCIvarDecl::Public; + case eAccessPrivate: + return clang::ObjCIvarDecl::Private; + case eAccessProtected: + return clang::ObjCIvarDecl::Protected; + case eAccessPackage: + return clang::ObjCIvarDecl::Package; + } + return clang::ObjCIvarDecl::None; } - //---------------------------------------------------------------------- // Tests //---------------------------------------------------------------------- -bool -ClangASTContext::IsAggregateType (lldb::opaque_compiler_type_t type) -{ - clang::QualType qual_type (GetCanonicalQualType(type)); - - const clang::Type::TypeClass type_class = qual_type->getTypeClass(); - switch (type_class) - { - case clang::Type::IncompleteArray: - case clang::Type::VariableArray: - case clang::Type::ConstantArray: - case clang::Type::ExtVector: - case clang::Type::Vector: - case clang::Type::Record: - case clang::Type::ObjCObject: - case clang::Type::ObjCInterface: - return true; - case clang::Type::Auto: - return IsAggregateType(llvm::cast<clang::AutoType>(qual_type)->getDeducedType().getAsOpaquePtr()); - case clang::Type::Elaborated: - return IsAggregateType(llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType().getAsOpaquePtr()); - case clang::Type::Typedef: - return IsAggregateType(llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType().getAsOpaquePtr()); - case clang::Type::Paren: - return IsAggregateType(llvm::cast<clang::ParenType>(qual_type)->desugar().getAsOpaquePtr()); - default: - break; - } - // The clang type does have a value - return false; -} - -bool -ClangASTContext::IsAnonymousType (lldb::opaque_compiler_type_t type) -{ - clang::QualType qual_type (GetCanonicalQualType(type)); - - const clang::Type::TypeClass type_class = qual_type->getTypeClass(); - switch (type_class) - { - case clang::Type::Record: - { - if (const clang::RecordType *record_type = llvm::dyn_cast_or_null<clang::RecordType>(qual_type.getTypePtrOrNull())) - { - if (const clang::RecordDecl *record_decl = record_type->getDecl()) - { - return record_decl->isAnonymousStructOrUnion(); - } - } - break; - } - case clang::Type::Auto: - return IsAnonymousType(llvm::cast<clang::AutoType>(qual_type)->getDeducedType().getAsOpaquePtr()); - case clang::Type::Elaborated: - return IsAnonymousType(llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType().getAsOpaquePtr()); - case clang::Type::Typedef: - return IsAnonymousType(llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType().getAsOpaquePtr()); - case clang::Type::Paren: - return IsAnonymousType(llvm::cast<clang::ParenType>(qual_type)->desugar().getAsOpaquePtr()); - default: - break; - } - // The clang type does have a value - return false; -} - -bool -ClangASTContext::IsArrayType (lldb::opaque_compiler_type_t type, - CompilerType *element_type_ptr, - uint64_t *size, - bool *is_incomplete) -{ - clang::QualType qual_type (GetCanonicalQualType(type)); - - const clang::Type::TypeClass type_class = qual_type->getTypeClass(); - switch (type_class) - { - default: - break; - - case clang::Type::ConstantArray: - if (element_type_ptr) - element_type_ptr->SetCompilerType (getASTContext(), llvm::cast<clang::ConstantArrayType>(qual_type)->getElementType()); - if (size) - *size = llvm::cast<clang::ConstantArrayType>(qual_type)->getSize().getLimitedValue(ULLONG_MAX); - if (is_incomplete) - *is_incomplete = false; - return true; - - case clang::Type::IncompleteArray: - if (element_type_ptr) - element_type_ptr->SetCompilerType (getASTContext(), llvm::cast<clang::IncompleteArrayType>(qual_type)->getElementType()); - if (size) - *size = 0; - if (is_incomplete) - *is_incomplete = true; - return true; +bool ClangASTContext::IsAggregateType(lldb::opaque_compiler_type_t type) { + clang::QualType qual_type(GetCanonicalQualType(type)); + + const clang::Type::TypeClass type_class = qual_type->getTypeClass(); + switch (type_class) { + case clang::Type::IncompleteArray: + case clang::Type::VariableArray: + case clang::Type::ConstantArray: + case clang::Type::ExtVector: + case clang::Type::Vector: + case clang::Type::Record: + case clang::Type::ObjCObject: + case clang::Type::ObjCInterface: + return true; + case clang::Type::Auto: + return IsAggregateType(llvm::cast<clang::AutoType>(qual_type) + ->getDeducedType() + .getAsOpaquePtr()); + case clang::Type::Elaborated: + return IsAggregateType(llvm::cast<clang::ElaboratedType>(qual_type) + ->getNamedType() + .getAsOpaquePtr()); + case clang::Type::Typedef: + return IsAggregateType(llvm::cast<clang::TypedefType>(qual_type) + ->getDecl() + ->getUnderlyingType() + .getAsOpaquePtr()); + case clang::Type::Paren: + return IsAggregateType( + llvm::cast<clang::ParenType>(qual_type)->desugar().getAsOpaquePtr()); + default: + break; + } + // The clang type does have a value + return false; +} + +bool ClangASTContext::IsAnonymousType(lldb::opaque_compiler_type_t type) { + clang::QualType qual_type(GetCanonicalQualType(type)); + + const clang::Type::TypeClass type_class = qual_type->getTypeClass(); + switch (type_class) { + case clang::Type::Record: { + if (const clang::RecordType *record_type = + llvm::dyn_cast_or_null<clang::RecordType>( + qual_type.getTypePtrOrNull())) { + if (const clang::RecordDecl *record_decl = record_type->getDecl()) { + return record_decl->isAnonymousStructOrUnion(); + } + } + break; + } + case clang::Type::Auto: + return IsAnonymousType(llvm::cast<clang::AutoType>(qual_type) + ->getDeducedType() + .getAsOpaquePtr()); + case clang::Type::Elaborated: + return IsAnonymousType(llvm::cast<clang::ElaboratedType>(qual_type) + ->getNamedType() + .getAsOpaquePtr()); + case clang::Type::Typedef: + return IsAnonymousType(llvm::cast<clang::TypedefType>(qual_type) + ->getDecl() + ->getUnderlyingType() + .getAsOpaquePtr()); + case clang::Type::Paren: + return IsAnonymousType( + llvm::cast<clang::ParenType>(qual_type)->desugar().getAsOpaquePtr()); + default: + break; + } + // The clang type does have a value + return false; +} + +bool ClangASTContext::IsArrayType(lldb::opaque_compiler_type_t type, + CompilerType *element_type_ptr, + uint64_t *size, bool *is_incomplete) { + clang::QualType qual_type(GetCanonicalQualType(type)); + + const clang::Type::TypeClass type_class = qual_type->getTypeClass(); + switch (type_class) { + default: + break; + + case clang::Type::ConstantArray: + if (element_type_ptr) + element_type_ptr->SetCompilerType( + getASTContext(), + llvm::cast<clang::ConstantArrayType>(qual_type)->getElementType()); + if (size) + *size = llvm::cast<clang::ConstantArrayType>(qual_type) + ->getSize() + .getLimitedValue(ULLONG_MAX); + if (is_incomplete) + *is_incomplete = false; + return true; - case clang::Type::VariableArray: - if (element_type_ptr) - element_type_ptr->SetCompilerType (getASTContext(), llvm::cast<clang::VariableArrayType>(qual_type)->getElementType()); - if (size) - *size = 0; - if (is_incomplete) - *is_incomplete = false; - return true; + case clang::Type::IncompleteArray: + if (element_type_ptr) + element_type_ptr->SetCompilerType( + getASTContext(), + llvm::cast<clang::IncompleteArrayType>(qual_type)->getElementType()); + if (size) + *size = 0; + if (is_incomplete) + *is_incomplete = true; + return true; - case clang::Type::DependentSizedArray: - if (element_type_ptr) - element_type_ptr->SetCompilerType (getASTContext(), llvm::cast<clang::DependentSizedArrayType>(qual_type)->getElementType()); - if (size) - *size = 0; - if (is_incomplete) - *is_incomplete = false; - return true; + case clang::Type::VariableArray: + if (element_type_ptr) + element_type_ptr->SetCompilerType( + getASTContext(), + llvm::cast<clang::VariableArrayType>(qual_type)->getElementType()); + if (size) + *size = 0; + if (is_incomplete) + *is_incomplete = false; + return true; - case clang::Type::Typedef: - return IsArrayType(llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType().getAsOpaquePtr(), - element_type_ptr, - size, - is_incomplete); - case clang::Type::Auto: - return IsArrayType(llvm::cast<clang::AutoType>(qual_type)->getDeducedType().getAsOpaquePtr(), - element_type_ptr, - size, - is_incomplete); - case clang::Type::Elaborated: - return IsArrayType(llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType().getAsOpaquePtr(), - element_type_ptr, - size, - is_incomplete); - case clang::Type::Paren: - return IsArrayType(llvm::cast<clang::ParenType>(qual_type)->desugar().getAsOpaquePtr(), - element_type_ptr, - size, - is_incomplete); - } + case clang::Type::DependentSizedArray: if (element_type_ptr) - element_type_ptr->Clear(); + element_type_ptr->SetCompilerType( + getASTContext(), llvm::cast<clang::DependentSizedArrayType>(qual_type) + ->getElementType()); if (size) - *size = 0; + *size = 0; if (is_incomplete) - *is_incomplete = false; - return false; -} + *is_incomplete = false; + return true; -bool -ClangASTContext::IsVectorType (lldb::opaque_compiler_type_t type, - CompilerType *element_type, - uint64_t *size) -{ - clang::QualType qual_type (GetCanonicalQualType(type)); - - const clang::Type::TypeClass type_class = qual_type->getTypeClass(); - switch (type_class) - { - case clang::Type::Vector: - { - const clang::VectorType *vector_type = qual_type->getAs<clang::VectorType>(); - if (vector_type) - { - if (size) - *size = vector_type->getNumElements(); - if (element_type) - *element_type = CompilerType(getASTContext(), vector_type->getElementType()); - } - return true; - } - break; - case clang::Type::ExtVector: - { - const clang::ExtVectorType *ext_vector_type = qual_type->getAs<clang::ExtVectorType>(); - if (ext_vector_type) - { - if (size) - *size = ext_vector_type->getNumElements(); - if (element_type) - *element_type = CompilerType(getASTContext(), ext_vector_type->getElementType()); - } - return true; - } - default: - break; + case clang::Type::Typedef: + return IsArrayType(llvm::cast<clang::TypedefType>(qual_type) + ->getDecl() + ->getUnderlyingType() + .getAsOpaquePtr(), + element_type_ptr, size, is_incomplete); + case clang::Type::Auto: + return IsArrayType(llvm::cast<clang::AutoType>(qual_type) + ->getDeducedType() + .getAsOpaquePtr(), + element_type_ptr, size, is_incomplete); + case clang::Type::Elaborated: + return IsArrayType(llvm::cast<clang::ElaboratedType>(qual_type) + ->getNamedType() + .getAsOpaquePtr(), + element_type_ptr, size, is_incomplete); + case clang::Type::Paren: + return IsArrayType( + llvm::cast<clang::ParenType>(qual_type)->desugar().getAsOpaquePtr(), + element_type_ptr, size, is_incomplete); + } + if (element_type_ptr) + element_type_ptr->Clear(); + if (size) + *size = 0; + if (is_incomplete) + *is_incomplete = false; + return false; +} + +bool ClangASTContext::IsVectorType(lldb::opaque_compiler_type_t type, + CompilerType *element_type, uint64_t *size) { + clang::QualType qual_type(GetCanonicalQualType(type)); + + const clang::Type::TypeClass type_class = qual_type->getTypeClass(); + switch (type_class) { + case clang::Type::Vector: { + const clang::VectorType *vector_type = + qual_type->getAs<clang::VectorType>(); + if (vector_type) { + if (size) + *size = vector_type->getNumElements(); + if (element_type) + *element_type = + CompilerType(getASTContext(), vector_type->getElementType()); } + return true; + } break; + case clang::Type::ExtVector: { + const clang::ExtVectorType *ext_vector_type = + qual_type->getAs<clang::ExtVectorType>(); + if (ext_vector_type) { + if (size) + *size = ext_vector_type->getNumElements(); + if (element_type) + *element_type = + CompilerType(getASTContext(), ext_vector_type->getElementType()); + } + return true; + } + default: + break; + } + return false; +} + +bool ClangASTContext::IsRuntimeGeneratedType( + lldb::opaque_compiler_type_t type) { + clang::DeclContext *decl_ctx = ClangASTContext::GetASTContext(getASTContext()) + ->GetDeclContextForType(GetQualType(type)); + if (!decl_ctx) return false; -} -bool -ClangASTContext::IsRuntimeGeneratedType (lldb::opaque_compiler_type_t type) -{ - clang::DeclContext* decl_ctx = ClangASTContext::GetASTContext(getASTContext())->GetDeclContextForType(GetQualType(type)); - if (!decl_ctx) - return false; - - if (!llvm::isa<clang::ObjCInterfaceDecl>(decl_ctx)) - return false; - - clang::ObjCInterfaceDecl *result_iface_decl = llvm::dyn_cast<clang::ObjCInterfaceDecl>(decl_ctx); - - ClangASTMetadata* ast_metadata = ClangASTContext::GetMetadata(getASTContext(), result_iface_decl); - if (!ast_metadata) - return false; - return (ast_metadata->GetISAPtr() != 0); -} + if (!llvm::isa<clang::ObjCInterfaceDecl>(decl_ctx)) + return false; + + clang::ObjCInterfaceDecl *result_iface_decl = + llvm::dyn_cast<clang::ObjCInterfaceDecl>(decl_ctx); -bool -ClangASTContext::IsCharType (lldb::opaque_compiler_type_t type) -{ - return GetQualType(type).getUnqualifiedType()->isCharType(); + ClangASTMetadata *ast_metadata = + ClangASTContext::GetMetadata(getASTContext(), result_iface_decl); + if (!ast_metadata) + return false; + return (ast_metadata->GetISAPtr() != 0); } +bool ClangASTContext::IsCharType(lldb::opaque_compiler_type_t type) { + return GetQualType(type).getUnqualifiedType()->isCharType(); +} -bool -ClangASTContext::IsCompleteType (lldb::opaque_compiler_type_t type) -{ - const bool allow_completion = false; - return GetCompleteQualType (getASTContext(), GetQualType(type), allow_completion); +bool ClangASTContext::IsCompleteType(lldb::opaque_compiler_type_t type) { + const bool allow_completion = false; + return GetCompleteQualType(getASTContext(), GetQualType(type), + allow_completion); } -bool -ClangASTContext::IsConst(lldb::opaque_compiler_type_t type) -{ - return GetQualType(type).isConstQualified(); +bool ClangASTContext::IsConst(lldb::opaque_compiler_type_t type) { + return GetQualType(type).isConstQualified(); } -bool -ClangASTContext::IsCStringType (lldb::opaque_compiler_type_t type, uint32_t &length) -{ - CompilerType pointee_or_element_clang_type; - length = 0; - Flags type_flags (GetTypeInfo (type, &pointee_or_element_clang_type)); - - if (!pointee_or_element_clang_type.IsValid()) - return false; - - if (type_flags.AnySet (eTypeIsArray | eTypeIsPointer)) - { - if (pointee_or_element_clang_type.IsCharType()) - { - if (type_flags.Test (eTypeIsArray)) - { - // We know the size of the array and it could be a C string - // since it is an array of characters - length = llvm::cast<clang::ConstantArrayType>(GetCanonicalQualType(type).getTypePtr())->getSize().getLimitedValue(); - } - return true; - - } - } +bool ClangASTContext::IsCStringType(lldb::opaque_compiler_type_t type, + uint32_t &length) { + CompilerType pointee_or_element_clang_type; + length = 0; + Flags type_flags(GetTypeInfo(type, &pointee_or_element_clang_type)); + + if (!pointee_or_element_clang_type.IsValid()) return false; -} -bool -ClangASTContext::IsFunctionType (lldb::opaque_compiler_type_t type, bool *is_variadic_ptr) -{ - if (type) - { - clang::QualType qual_type (GetCanonicalQualType(type)); - - if (qual_type->isFunctionType()) - { - if (is_variadic_ptr) - { - const clang::FunctionProtoType *function_proto_type = llvm::dyn_cast<clang::FunctionProtoType>(qual_type.getTypePtr()); - if (function_proto_type) - *is_variadic_ptr = function_proto_type->isVariadic(); - else - *is_variadic_ptr = false; - } - return true; - } - - const clang::Type::TypeClass type_class = qual_type->getTypeClass(); - switch (type_class) - { - default: - break; - case clang::Type::Typedef: - return IsFunctionType(llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType().getAsOpaquePtr(), nullptr); - case clang::Type::Auto: - return IsFunctionType(llvm::cast<clang::AutoType>(qual_type)->getDeducedType().getAsOpaquePtr(), nullptr); - case clang::Type::Elaborated: - return IsFunctionType(llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType().getAsOpaquePtr(), nullptr); - case clang::Type::Paren: - return IsFunctionType(llvm::cast<clang::ParenType>(qual_type)->desugar().getAsOpaquePtr(), nullptr); - case clang::Type::LValueReference: - case clang::Type::RValueReference: - { - const clang::ReferenceType *reference_type = llvm::cast<clang::ReferenceType>(qual_type.getTypePtr()); - if (reference_type) - return IsFunctionType(reference_type->getPointeeType().getAsOpaquePtr(), nullptr); - } - break; - } + if (type_flags.AnySet(eTypeIsArray | eTypeIsPointer)) { + if (pointee_or_element_clang_type.IsCharType()) { + if (type_flags.Test(eTypeIsArray)) { + // We know the size of the array and it could be a C string + // since it is an array of characters + length = llvm::cast<clang::ConstantArrayType>( + GetCanonicalQualType(type).getTypePtr()) + ->getSize() + .getLimitedValue(); + } + return true; + } + } + return false; +} + +bool ClangASTContext::IsFunctionType(lldb::opaque_compiler_type_t type, + bool *is_variadic_ptr) { + if (type) { + clang::QualType qual_type(GetCanonicalQualType(type)); + + if (qual_type->isFunctionType()) { + if (is_variadic_ptr) { + const clang::FunctionProtoType *function_proto_type = + llvm::dyn_cast<clang::FunctionProtoType>(qual_type.getTypePtr()); + if (function_proto_type) + *is_variadic_ptr = function_proto_type->isVariadic(); + else + *is_variadic_ptr = false; + } + return true; } - return false; + + const clang::Type::TypeClass type_class = qual_type->getTypeClass(); + switch (type_class) { + default: + break; + case clang::Type::Typedef: + return IsFunctionType(llvm::cast<clang::TypedefType>(qual_type) + ->getDecl() + ->getUnderlyingType() + .getAsOpaquePtr(), + nullptr); + case clang::Type::Auto: + return IsFunctionType(llvm::cast<clang::AutoType>(qual_type) + ->getDeducedType() + .getAsOpaquePtr(), + nullptr); + case clang::Type::Elaborated: + return IsFunctionType(llvm::cast<clang::ElaboratedType>(qual_type) + ->getNamedType() + .getAsOpaquePtr(), + nullptr); + case clang::Type::Paren: + return IsFunctionType( + llvm::cast<clang::ParenType>(qual_type)->desugar().getAsOpaquePtr(), + nullptr); + case clang::Type::LValueReference: + case clang::Type::RValueReference: { + const clang::ReferenceType *reference_type = + llvm::cast<clang::ReferenceType>(qual_type.getTypePtr()); + if (reference_type) + return IsFunctionType(reference_type->getPointeeType().getAsOpaquePtr(), + nullptr); + } break; + } + } + return false; } // Used to detect "Homogeneous Floating-point Aggregates" uint32_t -ClangASTContext::IsHomogeneousAggregate (lldb::opaque_compiler_type_t type, CompilerType* base_type_ptr) -{ - if (!type) - return 0; - - clang::QualType qual_type(GetCanonicalQualType(type)); - const clang::Type::TypeClass type_class = qual_type->getTypeClass(); - switch (type_class) - { - case clang::Type::Record: - if (GetCompleteType (type)) - { - const clang::CXXRecordDecl *cxx_record_decl = qual_type->getAsCXXRecordDecl(); - if (cxx_record_decl) - { - if (cxx_record_decl->getNumBases() || - cxx_record_decl->isDynamicClass()) - return 0; - } - const clang::RecordType *record_type = llvm::cast<clang::RecordType>(qual_type.getTypePtr()); - if (record_type) - { - const clang::RecordDecl *record_decl = record_type->getDecl(); - if (record_decl) - { - // We are looking for a structure that contains only floating point types - clang::RecordDecl::field_iterator field_pos, field_end = record_decl->field_end(); - uint32_t num_fields = 0; - bool is_hva = false; - bool is_hfa = false; - clang::QualType base_qual_type; - uint64_t base_bitwidth = 0; - for (field_pos = record_decl->field_begin(); field_pos != field_end; ++field_pos) - { - clang::QualType field_qual_type = field_pos->getType(); - uint64_t field_bitwidth = getASTContext()->getTypeSize (qual_type); - if (field_qual_type->isFloatingType()) - { - if (field_qual_type->isComplexType()) - return 0; - else - { - if (num_fields == 0) - base_qual_type = field_qual_type; - else - { - if (is_hva) - return 0; - is_hfa = true; - if (field_qual_type.getTypePtr() != base_qual_type.getTypePtr()) - return 0; - } - } - } - else if (field_qual_type->isVectorType() || field_qual_type->isExtVectorType()) - { - if (num_fields == 0) - { - base_qual_type = field_qual_type; - base_bitwidth = field_bitwidth; - } - else - { - if (is_hfa) - return 0; - is_hva = true; - if (base_bitwidth != field_bitwidth) - return 0; - if (field_qual_type.getTypePtr() != base_qual_type.getTypePtr()) - return 0; - } - } - else - return 0; - ++num_fields; - } - if (base_type_ptr) - *base_type_ptr = CompilerType (getASTContext(), base_qual_type); - return num_fields; - } - } - } - break; - - case clang::Type::Typedef: - return IsHomogeneousAggregate(llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType().getAsOpaquePtr(), base_type_ptr); - - case clang::Type::Auto: - return IsHomogeneousAggregate(llvm::cast<clang::AutoType>(qual_type)->getDeducedType().getAsOpaquePtr(), base_type_ptr); - - case clang::Type::Elaborated: - return IsHomogeneousAggregate(llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType().getAsOpaquePtr(), base_type_ptr); - default: - break; - } +ClangASTContext::IsHomogeneousAggregate(lldb::opaque_compiler_type_t type, + CompilerType *base_type_ptr) { + if (!type) return 0; -} -size_t -ClangASTContext::GetNumberOfFunctionArguments (lldb::opaque_compiler_type_t type) -{ - if (type) - { - clang::QualType qual_type (GetCanonicalQualType(type)); - const clang::FunctionProtoType* func = llvm::dyn_cast<clang::FunctionProtoType>(qual_type.getTypePtr()); - if (func) - return func->getNumParams(); - } - return 0; + clang::QualType qual_type(GetCanonicalQualType(type)); + const clang::Type::TypeClass type_class = qual_type->getTypeClass(); + switch (type_class) { + case clang::Type::Record: + if (GetCompleteType(type)) { + const clang::CXXRecordDecl *cxx_record_decl = + qual_type->getAsCXXRecordDecl(); + if (cxx_record_decl) { + if (cxx_record_decl->getNumBases() || cxx_record_decl->isDynamicClass()) + return 0; + } + const clang::RecordType *record_type = + llvm::cast<clang::RecordType>(qual_type.getTypePtr()); + if (record_type) { + const clang::RecordDecl *record_decl = record_type->getDecl(); + if (record_decl) { + // We are looking for a structure that contains only floating point + // types + clang::RecordDecl::field_iterator field_pos, + field_end = record_decl->field_end(); + uint32_t num_fields = 0; + bool is_hva = false; + bool is_hfa = false; + clang::QualType base_qual_type; + uint64_t base_bitwidth = 0; + for (field_pos = record_decl->field_begin(); field_pos != field_end; + ++field_pos) { + clang::QualType field_qual_type = field_pos->getType(); + uint64_t field_bitwidth = getASTContext()->getTypeSize(qual_type); + if (field_qual_type->isFloatingType()) { + if (field_qual_type->isComplexType()) + return 0; + else { + if (num_fields == 0) + base_qual_type = field_qual_type; + else { + if (is_hva) + return 0; + is_hfa = true; + if (field_qual_type.getTypePtr() != + base_qual_type.getTypePtr()) + return 0; + } + } + } else if (field_qual_type->isVectorType() || + field_qual_type->isExtVectorType()) { + if (num_fields == 0) { + base_qual_type = field_qual_type; + base_bitwidth = field_bitwidth; + } else { + if (is_hfa) + return 0; + is_hva = true; + if (base_bitwidth != field_bitwidth) + return 0; + if (field_qual_type.getTypePtr() != base_qual_type.getTypePtr()) + return 0; + } + } else + return 0; + ++num_fields; + } + if (base_type_ptr) + *base_type_ptr = CompilerType(getASTContext(), base_qual_type); + return num_fields; + } + } + } + break; + + case clang::Type::Typedef: + return IsHomogeneousAggregate(llvm::cast<clang::TypedefType>(qual_type) + ->getDecl() + ->getUnderlyingType() + .getAsOpaquePtr(), + base_type_ptr); + + case clang::Type::Auto: + return IsHomogeneousAggregate(llvm::cast<clang::AutoType>(qual_type) + ->getDeducedType() + .getAsOpaquePtr(), + base_type_ptr); + + case clang::Type::Elaborated: + return IsHomogeneousAggregate(llvm::cast<clang::ElaboratedType>(qual_type) + ->getNamedType() + .getAsOpaquePtr(), + base_type_ptr); + default: + break; + } + return 0; +} + +size_t ClangASTContext::GetNumberOfFunctionArguments( + lldb::opaque_compiler_type_t type) { + if (type) { + clang::QualType qual_type(GetCanonicalQualType(type)); + const clang::FunctionProtoType *func = + llvm::dyn_cast<clang::FunctionProtoType>(qual_type.getTypePtr()); + if (func) + return func->getNumParams(); + } + return 0; } CompilerType -ClangASTContext::GetFunctionArgumentAtIndex (lldb::opaque_compiler_type_t type, const size_t index) -{ - if (type) - { - clang::QualType qual_type (GetQualType(type)); - const clang::FunctionProtoType* func = llvm::dyn_cast<clang::FunctionProtoType>(qual_type.getTypePtr()); - if (func) - { - if (index < func->getNumParams()) - return CompilerType(getASTContext(), func->getParamType(index)); - } +ClangASTContext::GetFunctionArgumentAtIndex(lldb::opaque_compiler_type_t type, + const size_t index) { + if (type) { + clang::QualType qual_type(GetQualType(type)); + const clang::FunctionProtoType *func = + llvm::dyn_cast<clang::FunctionProtoType>(qual_type.getTypePtr()); + if (func) { + if (index < func->getNumParams()) + return CompilerType(getASTContext(), func->getParamType(index)); } - return CompilerType(); + } + return CompilerType(); } -bool -ClangASTContext::IsFunctionPointerType (lldb::opaque_compiler_type_t type) -{ - if (type) - { - clang::QualType qual_type (GetCanonicalQualType(type)); - - if (qual_type->isFunctionPointerType()) - return true; - - const clang::Type::TypeClass type_class = qual_type->getTypeClass(); - switch (type_class) - { - default: - break; - case clang::Type::Typedef: - return IsFunctionPointerType (llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType().getAsOpaquePtr()); - case clang::Type::Auto: - return IsFunctionPointerType (llvm::cast<clang::AutoType>(qual_type)->getDeducedType().getAsOpaquePtr()); - case clang::Type::Elaborated: - return IsFunctionPointerType (llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType().getAsOpaquePtr()); - case clang::Type::Paren: - return IsFunctionPointerType (llvm::cast<clang::ParenType>(qual_type)->desugar().getAsOpaquePtr()); - - case clang::Type::LValueReference: - case clang::Type::RValueReference: - { - const clang::ReferenceType *reference_type = llvm::cast<clang::ReferenceType>(qual_type.getTypePtr()); - if (reference_type) - return IsFunctionPointerType(reference_type->getPointeeType().getAsOpaquePtr()); - } - break; - } - } - return false; - -} - -bool -ClangASTContext::IsBlockPointerType (lldb::opaque_compiler_type_t type, CompilerType *function_pointer_type_ptr) -{ - if (type) - { - clang::QualType qual_type (GetCanonicalQualType(type)); - - if (qual_type->isBlockPointerType()) - { - if (function_pointer_type_ptr) - { - const clang::BlockPointerType *block_pointer_type = qual_type->getAs<clang::BlockPointerType>(); - QualType pointee_type = block_pointer_type->getPointeeType(); - QualType function_pointer_type = m_ast_ap->getPointerType(pointee_type); - *function_pointer_type_ptr = CompilerType (getASTContext(), function_pointer_type); - } - return true; - } - - const clang::Type::TypeClass type_class = qual_type->getTypeClass(); - switch (type_class) - { - default: - break; - case clang::Type::Typedef: - return IsBlockPointerType (llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType().getAsOpaquePtr(), function_pointer_type_ptr); - case clang::Type::Auto: - return IsBlockPointerType (llvm::cast<clang::AutoType>(qual_type)->getDeducedType().getAsOpaquePtr(), function_pointer_type_ptr); - case clang::Type::Elaborated: - return IsBlockPointerType (llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType().getAsOpaquePtr(), function_pointer_type_ptr); - case clang::Type::Paren: - return IsBlockPointerType (llvm::cast<clang::ParenType>(qual_type)->desugar().getAsOpaquePtr(), function_pointer_type_ptr); - - case clang::Type::LValueReference: - case clang::Type::RValueReference: - { - const clang::ReferenceType *reference_type = llvm::cast<clang::ReferenceType>(qual_type.getTypePtr()); - if (reference_type) - return IsBlockPointerType(reference_type->getPointeeType().getAsOpaquePtr(), function_pointer_type_ptr); - } - break; - } +bool ClangASTContext::IsFunctionPointerType(lldb::opaque_compiler_type_t type) { + if (type) { + clang::QualType qual_type(GetCanonicalQualType(type)); + + if (qual_type->isFunctionPointerType()) + return true; + + const clang::Type::TypeClass type_class = qual_type->getTypeClass(); + switch (type_class) { + default: + break; + case clang::Type::Typedef: + return IsFunctionPointerType(llvm::cast<clang::TypedefType>(qual_type) + ->getDecl() + ->getUnderlyingType() + .getAsOpaquePtr()); + case clang::Type::Auto: + return IsFunctionPointerType(llvm::cast<clang::AutoType>(qual_type) + ->getDeducedType() + .getAsOpaquePtr()); + case clang::Type::Elaborated: + return IsFunctionPointerType(llvm::cast<clang::ElaboratedType>(qual_type) + ->getNamedType() + .getAsOpaquePtr()); + case clang::Type::Paren: + return IsFunctionPointerType( + llvm::cast<clang::ParenType>(qual_type)->desugar().getAsOpaquePtr()); + + case clang::Type::LValueReference: + case clang::Type::RValueReference: { + const clang::ReferenceType *reference_type = + llvm::cast<clang::ReferenceType>(qual_type.getTypePtr()); + if (reference_type) + return IsFunctionPointerType( + reference_type->getPointeeType().getAsOpaquePtr()); + } break; + } + } + return false; +} + +bool ClangASTContext::IsBlockPointerType( + lldb::opaque_compiler_type_t type, + CompilerType *function_pointer_type_ptr) { + if (type) { + clang::QualType qual_type(GetCanonicalQualType(type)); + + if (qual_type->isBlockPointerType()) { + if (function_pointer_type_ptr) { + const clang::BlockPointerType *block_pointer_type = + qual_type->getAs<clang::BlockPointerType>(); + QualType pointee_type = block_pointer_type->getPointeeType(); + QualType function_pointer_type = m_ast_ap->getPointerType(pointee_type); + *function_pointer_type_ptr = + CompilerType(getASTContext(), function_pointer_type); + } + return true; } + + const clang::Type::TypeClass type_class = qual_type->getTypeClass(); + switch (type_class) { + default: + break; + case clang::Type::Typedef: + return IsBlockPointerType(llvm::cast<clang::TypedefType>(qual_type) + ->getDecl() + ->getUnderlyingType() + .getAsOpaquePtr(), + function_pointer_type_ptr); + case clang::Type::Auto: + return IsBlockPointerType(llvm::cast<clang::AutoType>(qual_type) + ->getDeducedType() + .getAsOpaquePtr(), + function_pointer_type_ptr); + case clang::Type::Elaborated: + return IsBlockPointerType(llvm::cast<clang::ElaboratedType>(qual_type) + ->getNamedType() + .getAsOpaquePtr(), + function_pointer_type_ptr); + case clang::Type::Paren: + return IsBlockPointerType( + llvm::cast<clang::ParenType>(qual_type)->desugar().getAsOpaquePtr(), + function_pointer_type_ptr); + + case clang::Type::LValueReference: + case clang::Type::RValueReference: { + const clang::ReferenceType *reference_type = + llvm::cast<clang::ReferenceType>(qual_type.getTypePtr()); + if (reference_type) + return IsBlockPointerType( + reference_type->getPointeeType().getAsOpaquePtr(), + function_pointer_type_ptr); + } break; + } + } + return false; +} + +bool ClangASTContext::IsIntegerType(lldb::opaque_compiler_type_t type, + bool &is_signed) { + if (!type) return false; -} -bool -ClangASTContext::IsIntegerType (lldb::opaque_compiler_type_t type, bool &is_signed) -{ - if (!type) - return false; - - clang::QualType qual_type (GetCanonicalQualType(type)); - const clang::BuiltinType *builtin_type = llvm::dyn_cast<clang::BuiltinType>(qual_type->getCanonicalTypeInternal()); - - if (builtin_type) - { - if (builtin_type->isInteger()) - { - is_signed = builtin_type->isSignedInteger(); - return true; - } + clang::QualType qual_type(GetCanonicalQualType(type)); + const clang::BuiltinType *builtin_type = + llvm::dyn_cast<clang::BuiltinType>(qual_type->getCanonicalTypeInternal()); + + if (builtin_type) { + if (builtin_type->isInteger()) { + is_signed = builtin_type->isSignedInteger(); + return true; } - - return false; + } + + return false; } -bool -ClangASTContext::IsEnumerationType(lldb::opaque_compiler_type_t type, bool &is_signed) -{ - if (type) - { - const clang::EnumType *enum_type = llvm::dyn_cast<clang::EnumType>(GetCanonicalQualType(type)->getCanonicalTypeInternal()); +bool ClangASTContext::IsEnumerationType(lldb::opaque_compiler_type_t type, + bool &is_signed) { + if (type) { + const clang::EnumType *enum_type = llvm::dyn_cast<clang::EnumType>( + GetCanonicalQualType(type)->getCanonicalTypeInternal()); - if (enum_type) - { - IsIntegerType(enum_type->getDecl()->getIntegerType().getAsOpaquePtr(), is_signed); - return true; - } + if (enum_type) { + IsIntegerType(enum_type->getDecl()->getIntegerType().getAsOpaquePtr(), + is_signed); + return true; } + } - return false; + return false; } -bool -ClangASTContext::IsPointerType (lldb::opaque_compiler_type_t type, CompilerType *pointee_type) -{ - if (type) - { - clang::QualType qual_type (GetCanonicalQualType(type)); - const clang::Type::TypeClass type_class = qual_type->getTypeClass(); - switch (type_class) - { - case clang::Type::Builtin: - switch (llvm::cast<clang::BuiltinType>(qual_type)->getKind()) - { - default: - break; - case clang::BuiltinType::ObjCId: - case clang::BuiltinType::ObjCClass: - return true; - } - return false; - case clang::Type::ObjCObjectPointer: - if (pointee_type) - pointee_type->SetCompilerType (getASTContext(), llvm::cast<clang::ObjCObjectPointerType>(qual_type)->getPointeeType()); - return true; - case clang::Type::BlockPointer: - if (pointee_type) - pointee_type->SetCompilerType (getASTContext(), llvm::cast<clang::BlockPointerType>(qual_type)->getPointeeType()); - return true; - case clang::Type::Pointer: - if (pointee_type) - pointee_type->SetCompilerType (getASTContext(), llvm::cast<clang::PointerType>(qual_type)->getPointeeType()); - return true; - case clang::Type::MemberPointer: - if (pointee_type) - pointee_type->SetCompilerType (getASTContext(), llvm::cast<clang::MemberPointerType>(qual_type)->getPointeeType()); - return true; - case clang::Type::Typedef: - return IsPointerType (llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType().getAsOpaquePtr(), pointee_type); - case clang::Type::Auto: - return IsPointerType (llvm::cast<clang::AutoType>(qual_type)->getDeducedType().getAsOpaquePtr(), pointee_type); - case clang::Type::Elaborated: - return IsPointerType (llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType().getAsOpaquePtr(), pointee_type); - case clang::Type::Paren: - return IsPointerType (llvm::cast<clang::ParenType>(qual_type)->desugar().getAsOpaquePtr(), pointee_type); - default: - break; - } +bool ClangASTContext::IsPointerType(lldb::opaque_compiler_type_t type, + CompilerType *pointee_type) { + if (type) { + clang::QualType qual_type(GetCanonicalQualType(type)); + const clang::Type::TypeClass type_class = qual_type->getTypeClass(); + switch (type_class) { + case clang::Type::Builtin: + switch (llvm::cast<clang::BuiltinType>(qual_type)->getKind()) { + default: + break; + case clang::BuiltinType::ObjCId: + case clang::BuiltinType::ObjCClass: + return true; + } + return false; + case clang::Type::ObjCObjectPointer: + if (pointee_type) + pointee_type->SetCompilerType( + getASTContext(), llvm::cast<clang::ObjCObjectPointerType>(qual_type) + ->getPointeeType()); + return true; + case clang::Type::BlockPointer: + if (pointee_type) + pointee_type->SetCompilerType( + getASTContext(), + llvm::cast<clang::BlockPointerType>(qual_type)->getPointeeType()); + return true; + case clang::Type::Pointer: + if (pointee_type) + pointee_type->SetCompilerType( + getASTContext(), + llvm::cast<clang::PointerType>(qual_type)->getPointeeType()); + return true; + case clang::Type::MemberPointer: + if (pointee_type) + pointee_type->SetCompilerType( + getASTContext(), + llvm::cast<clang::MemberPointerType>(qual_type)->getPointeeType()); + return true; + case clang::Type::Typedef: + return IsPointerType(llvm::cast<clang::TypedefType>(qual_type) + ->getDecl() + ->getUnderlyingType() + .getAsOpaquePtr(), + pointee_type); + case clang::Type::Auto: + return IsPointerType(llvm::cast<clang::AutoType>(qual_type) + ->getDeducedType() + .getAsOpaquePtr(), + pointee_type); + case clang::Type::Elaborated: + return IsPointerType(llvm::cast<clang::ElaboratedType>(qual_type) + ->getNamedType() + .getAsOpaquePtr(), + pointee_type); + case clang::Type::Paren: + return IsPointerType( + llvm::cast<clang::ParenType>(qual_type)->desugar().getAsOpaquePtr(), + pointee_type); + default: + break; } - if (pointee_type) - pointee_type->Clear(); - return false; + } + if (pointee_type) + pointee_type->Clear(); + return false; } - -bool -ClangASTContext::IsPointerOrReferenceType (lldb::opaque_compiler_type_t type, CompilerType *pointee_type) -{ - if (type) - { - clang::QualType qual_type (GetCanonicalQualType(type)); - const clang::Type::TypeClass type_class = qual_type->getTypeClass(); - switch (type_class) - { - case clang::Type::Builtin: - switch (llvm::cast<clang::BuiltinType>(qual_type)->getKind()) - { - default: - break; - case clang::BuiltinType::ObjCId: - case clang::BuiltinType::ObjCClass: - return true; - } - return false; - case clang::Type::ObjCObjectPointer: - if (pointee_type) - pointee_type->SetCompilerType(getASTContext(), llvm::cast<clang::ObjCObjectPointerType>(qual_type)->getPointeeType()); - return true; - case clang::Type::BlockPointer: - if (pointee_type) - pointee_type->SetCompilerType(getASTContext(), llvm::cast<clang::BlockPointerType>(qual_type)->getPointeeType()); - return true; - case clang::Type::Pointer: - if (pointee_type) - pointee_type->SetCompilerType(getASTContext(), llvm::cast<clang::PointerType>(qual_type)->getPointeeType()); - return true; - case clang::Type::MemberPointer: - if (pointee_type) - pointee_type->SetCompilerType(getASTContext(), llvm::cast<clang::MemberPointerType>(qual_type)->getPointeeType()); - return true; - case clang::Type::LValueReference: - if (pointee_type) - pointee_type->SetCompilerType(getASTContext(), llvm::cast<clang::LValueReferenceType>(qual_type)->desugar()); - return true; - case clang::Type::RValueReference: - if (pointee_type) - pointee_type->SetCompilerType(getASTContext(), llvm::cast<clang::RValueReferenceType>(qual_type)->desugar()); - return true; - case clang::Type::Typedef: - return IsPointerOrReferenceType(llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType().getAsOpaquePtr(), pointee_type); - case clang::Type::Auto: - return IsPointerOrReferenceType(llvm::cast<clang::AutoType>(qual_type)->getDeducedType().getAsOpaquePtr(), pointee_type); - case clang::Type::Elaborated: - return IsPointerOrReferenceType(llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType().getAsOpaquePtr(), pointee_type); - case clang::Type::Paren: - return IsPointerOrReferenceType(llvm::cast<clang::ParenType>(qual_type)->desugar().getAsOpaquePtr(), pointee_type); - default: - break; - } +bool ClangASTContext::IsPointerOrReferenceType( + lldb::opaque_compiler_type_t type, CompilerType *pointee_type) { + if (type) { + clang::QualType qual_type(GetCanonicalQualType(type)); + const clang::Type::TypeClass type_class = qual_type->getTypeClass(); + switch (type_class) { + case clang::Type::Builtin: + switch (llvm::cast<clang::BuiltinType>(qual_type)->getKind()) { + default: + break; + case clang::BuiltinType::ObjCId: + case clang::BuiltinType::ObjCClass: + return true; + } + return false; + case clang::Type::ObjCObjectPointer: + if (pointee_type) + pointee_type->SetCompilerType( + getASTContext(), llvm::cast<clang::ObjCObjectPointerType>(qual_type) + ->getPointeeType()); + return true; + case clang::Type::BlockPointer: + if (pointee_type) + pointee_type->SetCompilerType( + getASTContext(), + llvm::cast<clang::BlockPointerType>(qual_type)->getPointeeType()); + return true; + case clang::Type::Pointer: + if (pointee_type) + pointee_type->SetCompilerType( + getASTContext(), + llvm::cast<clang::PointerType>(qual_type)->getPointeeType()); + return true; + case clang::Type::MemberPointer: + if (pointee_type) + pointee_type->SetCompilerType( + getASTContext(), + llvm::cast<clang::MemberPointerType>(qual_type)->getPointeeType()); + return true; + case clang::Type::LValueReference: + if (pointee_type) + pointee_type->SetCompilerType( + getASTContext(), + llvm::cast<clang::LValueReferenceType>(qual_type)->desugar()); + return true; + case clang::Type::RValueReference: + if (pointee_type) + pointee_type->SetCompilerType( + getASTContext(), + llvm::cast<clang::RValueReferenceType>(qual_type)->desugar()); + return true; + case clang::Type::Typedef: + return IsPointerOrReferenceType(llvm::cast<clang::TypedefType>(qual_type) + ->getDecl() + ->getUnderlyingType() + .getAsOpaquePtr(), + pointee_type); + case clang::Type::Auto: + return IsPointerOrReferenceType(llvm::cast<clang::AutoType>(qual_type) + ->getDeducedType() + .getAsOpaquePtr(), + pointee_type); + case clang::Type::Elaborated: + return IsPointerOrReferenceType( + llvm::cast<clang::ElaboratedType>(qual_type) + ->getNamedType() + .getAsOpaquePtr(), + pointee_type); + case clang::Type::Paren: + return IsPointerOrReferenceType( + llvm::cast<clang::ParenType>(qual_type)->desugar().getAsOpaquePtr(), + pointee_type); + default: + break; } - if (pointee_type) - pointee_type->Clear(); - return false; + } + if (pointee_type) + pointee_type->Clear(); + return false; } +bool ClangASTContext::IsReferenceType(lldb::opaque_compiler_type_t type, + CompilerType *pointee_type, + bool *is_rvalue) { + if (type) { + clang::QualType qual_type(GetCanonicalQualType(type)); + const clang::Type::TypeClass type_class = qual_type->getTypeClass(); -bool -ClangASTContext::IsReferenceType (lldb::opaque_compiler_type_t type, CompilerType *pointee_type, bool* is_rvalue) -{ - if (type) - { - clang::QualType qual_type (GetCanonicalQualType(type)); - const clang::Type::TypeClass type_class = qual_type->getTypeClass(); - - switch (type_class) - { - case clang::Type::LValueReference: - if (pointee_type) - pointee_type->SetCompilerType(getASTContext(), llvm::cast<clang::LValueReferenceType>(qual_type)->desugar()); - if (is_rvalue) - *is_rvalue = false; - return true; - case clang::Type::RValueReference: - if (pointee_type) - pointee_type->SetCompilerType(getASTContext(), llvm::cast<clang::RValueReferenceType>(qual_type)->desugar()); - if (is_rvalue) - *is_rvalue = true; - return true; - case clang::Type::Typedef: - return IsReferenceType (llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType().getAsOpaquePtr(), pointee_type, is_rvalue); - case clang::Type::Auto: - return IsReferenceType (llvm::cast<clang::AutoType>(qual_type)->getDeducedType().getAsOpaquePtr(), pointee_type, is_rvalue); - case clang::Type::Elaborated: - return IsReferenceType (llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType().getAsOpaquePtr(), pointee_type, is_rvalue); - case clang::Type::Paren: - return IsReferenceType (llvm::cast<clang::ParenType>(qual_type)->desugar().getAsOpaquePtr(), pointee_type, is_rvalue); - - default: - break; - } + switch (type_class) { + case clang::Type::LValueReference: + if (pointee_type) + pointee_type->SetCompilerType( + getASTContext(), + llvm::cast<clang::LValueReferenceType>(qual_type)->desugar()); + if (is_rvalue) + *is_rvalue = false; + return true; + case clang::Type::RValueReference: + if (pointee_type) + pointee_type->SetCompilerType( + getASTContext(), + llvm::cast<clang::RValueReferenceType>(qual_type)->desugar()); + if (is_rvalue) + *is_rvalue = true; + return true; + case clang::Type::Typedef: + return IsReferenceType(llvm::cast<clang::TypedefType>(qual_type) + ->getDecl() + ->getUnderlyingType() + .getAsOpaquePtr(), + pointee_type, is_rvalue); + case clang::Type::Auto: + return IsReferenceType(llvm::cast<clang::AutoType>(qual_type) + ->getDeducedType() + .getAsOpaquePtr(), + pointee_type, is_rvalue); + case clang::Type::Elaborated: + return IsReferenceType(llvm::cast<clang::ElaboratedType>(qual_type) + ->getNamedType() + .getAsOpaquePtr(), + pointee_type, is_rvalue); + case clang::Type::Paren: + return IsReferenceType( + llvm::cast<clang::ParenType>(qual_type)->desugar().getAsOpaquePtr(), + pointee_type, is_rvalue); + + default: + break; } - if (pointee_type) - pointee_type->Clear(); - return false; + } + if (pointee_type) + pointee_type->Clear(); + return false; } -bool -ClangASTContext::IsFloatingPointType (lldb::opaque_compiler_type_t type, uint32_t &count, bool &is_complex) -{ - if (type) - { - clang::QualType qual_type (GetCanonicalQualType(type)); - - if (const clang::BuiltinType *BT = llvm::dyn_cast<clang::BuiltinType>(qual_type->getCanonicalTypeInternal())) - { - clang::BuiltinType::Kind kind = BT->getKind(); - if (kind >= clang::BuiltinType::Float && kind <= clang::BuiltinType::LongDouble) - { - count = 1; - is_complex = false; - return true; - } - } - else if (const clang::ComplexType *CT = llvm::dyn_cast<clang::ComplexType>(qual_type->getCanonicalTypeInternal())) - { - if (IsFloatingPointType (CT->getElementType().getAsOpaquePtr(), count, is_complex)) - { - count = 2; - is_complex = true; - return true; - } - } - else if (const clang::VectorType *VT = llvm::dyn_cast<clang::VectorType>(qual_type->getCanonicalTypeInternal())) - { - if (IsFloatingPointType (VT->getElementType().getAsOpaquePtr(), count, is_complex)) - { - count = VT->getNumElements(); - is_complex = false; - return true; - } - } +bool ClangASTContext::IsFloatingPointType(lldb::opaque_compiler_type_t type, + uint32_t &count, bool &is_complex) { + if (type) { + clang::QualType qual_type(GetCanonicalQualType(type)); + + if (const clang::BuiltinType *BT = llvm::dyn_cast<clang::BuiltinType>( + qual_type->getCanonicalTypeInternal())) { + clang::BuiltinType::Kind kind = BT->getKind(); + if (kind >= clang::BuiltinType::Float && + kind <= clang::BuiltinType::LongDouble) { + count = 1; + is_complex = false; + return true; + } + } else if (const clang::ComplexType *CT = + llvm::dyn_cast<clang::ComplexType>( + qual_type->getCanonicalTypeInternal())) { + if (IsFloatingPointType(CT->getElementType().getAsOpaquePtr(), count, + is_complex)) { + count = 2; + is_complex = true; + return true; + } + } else if (const clang::VectorType *VT = llvm::dyn_cast<clang::VectorType>( + qual_type->getCanonicalTypeInternal())) { + if (IsFloatingPointType(VT->getElementType().getAsOpaquePtr(), count, + is_complex)) { + count = VT->getNumElements(); + is_complex = false; + return true; + } } - count = 0; - is_complex = false; - return false; + } + count = 0; + is_complex = false; + return false; } +bool ClangASTContext::IsDefined(lldb::opaque_compiler_type_t type) { + if (!type) + return false; -bool -ClangASTContext::IsDefined(lldb::opaque_compiler_type_t type) -{ - if (!type) - return false; - - clang::QualType qual_type(GetQualType(type)); - const clang::TagType *tag_type = llvm::dyn_cast<clang::TagType>(qual_type.getTypePtr()); - if (tag_type) - { - clang::TagDecl *tag_decl = tag_type->getDecl(); - if (tag_decl) - return tag_decl->isCompleteDefinition(); - return false; - } - else - { - const clang::ObjCObjectType *objc_class_type = llvm::dyn_cast<clang::ObjCObjectType>(qual_type); - if (objc_class_type) - { - clang::ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface(); - if (class_interface_decl) - return class_interface_decl->getDefinition() != nullptr; - return false; - } + clang::QualType qual_type(GetQualType(type)); + const clang::TagType *tag_type = + llvm::dyn_cast<clang::TagType>(qual_type.getTypePtr()); + if (tag_type) { + clang::TagDecl *tag_decl = tag_type->getDecl(); + if (tag_decl) + return tag_decl->isCompleteDefinition(); + return false; + } else { + const clang::ObjCObjectType *objc_class_type = + llvm::dyn_cast<clang::ObjCObjectType>(qual_type); + if (objc_class_type) { + clang::ObjCInterfaceDecl *class_interface_decl = + objc_class_type->getInterface(); + if (class_interface_decl) + return class_interface_decl->getDefinition() != nullptr; + return false; } - return true; + } + return true; } -bool -ClangASTContext::IsObjCClassType (const CompilerType& type) -{ - if (type) - { - clang::QualType qual_type(ClangUtil::GetCanonicalQualType(type)); +bool ClangASTContext::IsObjCClassType(const CompilerType &type) { + if (type) { + clang::QualType qual_type(ClangUtil::GetCanonicalQualType(type)); - const clang::ObjCObjectPointerType *obj_pointer_type = llvm::dyn_cast<clang::ObjCObjectPointerType>(qual_type); - - if (obj_pointer_type) - return obj_pointer_type->isObjCClassType(); - } - return false; + const clang::ObjCObjectPointerType *obj_pointer_type = + llvm::dyn_cast<clang::ObjCObjectPointerType>(qual_type); + + if (obj_pointer_type) + return obj_pointer_type->isObjCClassType(); + } + return false; +} + +bool ClangASTContext::IsObjCObjectOrInterfaceType(const CompilerType &type) { + if (ClangUtil::IsClangType(type)) + return ClangUtil::GetCanonicalQualType(type)->isObjCObjectOrInterfaceType(); + return false; } -bool -ClangASTContext::IsObjCObjectOrInterfaceType (const CompilerType& type) -{ - if (ClangUtil::IsClangType(type)) - return ClangUtil::GetCanonicalQualType(type)->isObjCObjectOrInterfaceType(); +bool ClangASTContext::IsClassType(lldb::opaque_compiler_type_t type) { + if (!type) return false; + clang::QualType qual_type(GetCanonicalQualType(type)); + const clang::Type::TypeClass type_class = qual_type->getTypeClass(); + return (type_class == clang::Type::Record); } -bool -ClangASTContext::IsClassType(lldb::opaque_compiler_type_t type) -{ - if (!type) - return false; - clang::QualType qual_type(GetCanonicalQualType(type)); - const clang::Type::TypeClass type_class = qual_type->getTypeClass(); - return (type_class == clang::Type::Record); +bool ClangASTContext::IsEnumType(lldb::opaque_compiler_type_t type) { + if (!type) + return false; + clang::QualType qual_type(GetCanonicalQualType(type)); + const clang::Type::TypeClass type_class = qual_type->getTypeClass(); + return (type_class == clang::Type::Enum); } -bool -ClangASTContext::IsEnumType(lldb::opaque_compiler_type_t type) -{ - if (!type) - return false; +bool ClangASTContext::IsPolymorphicClass(lldb::opaque_compiler_type_t type) { + if (type) { clang::QualType qual_type(GetCanonicalQualType(type)); const clang::Type::TypeClass type_class = qual_type->getTypeClass(); - return (type_class == clang::Type::Enum); -} - -bool -ClangASTContext::IsPolymorphicClass(lldb::opaque_compiler_type_t type) -{ - if (type) - { - clang::QualType qual_type(GetCanonicalQualType(type)); - const clang::Type::TypeClass type_class = qual_type->getTypeClass(); - switch (type_class) - { - case clang::Type::Record: - if (GetCompleteType(type)) - { - const clang::RecordType *record_type = llvm::cast<clang::RecordType>(qual_type.getTypePtr()); - const clang::RecordDecl *record_decl = record_type->getDecl(); - if (record_decl) - { - const clang::CXXRecordDecl *cxx_record_decl = llvm::dyn_cast<clang::CXXRecordDecl>(record_decl); - if (cxx_record_decl) - return cxx_record_decl->isPolymorphic(); - } - } - break; - - default: - break; + switch (type_class) { + case clang::Type::Record: + if (GetCompleteType(type)) { + const clang::RecordType *record_type = + llvm::cast<clang::RecordType>(qual_type.getTypePtr()); + const clang::RecordDecl *record_decl = record_type->getDecl(); + if (record_decl) { + const clang::CXXRecordDecl *cxx_record_decl = + llvm::dyn_cast<clang::CXXRecordDecl>(record_decl); + if (cxx_record_decl) + return cxx_record_decl->isPolymorphic(); } + } + break; + + default: + break; } - return false; + } + return false; } -bool -ClangASTContext::IsPossibleDynamicType (lldb::opaque_compiler_type_t type, CompilerType *dynamic_pointee_type, - bool check_cplusplus, - bool check_objc) -{ - clang::QualType pointee_qual_type; - if (type) - { - clang::QualType qual_type (GetCanonicalQualType(type)); - bool success = false; - const clang::Type::TypeClass type_class = qual_type->getTypeClass(); - switch (type_class) - { - case clang::Type::Builtin: - if (check_objc && llvm::cast<clang::BuiltinType>(qual_type)->getKind() == clang::BuiltinType::ObjCId) - { - if (dynamic_pointee_type) - dynamic_pointee_type->SetCompilerType(this, type); - return true; - } - break; - - case clang::Type::ObjCObjectPointer: - if (check_objc) - { - if (auto objc_pointee_type = qual_type->getPointeeType().getTypePtrOrNull()) - { - if (auto objc_object_type = llvm::dyn_cast_or_null<clang::ObjCObjectType>(objc_pointee_type)) - { - if (objc_object_type->isObjCClass()) - return false; - } - } - if (dynamic_pointee_type) - dynamic_pointee_type->SetCompilerType(getASTContext(), llvm::cast<clang::ObjCObjectPointerType>(qual_type)->getPointeeType()); - return true; - } - break; - - case clang::Type::Pointer: - pointee_qual_type = llvm::cast<clang::PointerType>(qual_type)->getPointeeType(); - success = true; - break; - - case clang::Type::LValueReference: - case clang::Type::RValueReference: - pointee_qual_type = llvm::cast<clang::ReferenceType>(qual_type)->getPointeeType(); - success = true; - break; - - case clang::Type::Typedef: - return IsPossibleDynamicType (llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType().getAsOpaquePtr(), - dynamic_pointee_type, - check_cplusplus, - check_objc); - - case clang::Type::Auto: - return IsPossibleDynamicType (llvm::cast<clang::AutoType>(qual_type)->getDeducedType().getAsOpaquePtr(), - dynamic_pointee_type, - check_cplusplus, - check_objc); - - case clang::Type::Elaborated: - return IsPossibleDynamicType (llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType().getAsOpaquePtr(), - dynamic_pointee_type, - check_cplusplus, - check_objc); - - case clang::Type::Paren: - return IsPossibleDynamicType (llvm::cast<clang::ParenType>(qual_type)->desugar().getAsOpaquePtr(), - dynamic_pointee_type, - check_cplusplus, - check_objc); - default: - break; +bool ClangASTContext::IsPossibleDynamicType(lldb::opaque_compiler_type_t type, + CompilerType *dynamic_pointee_type, + bool check_cplusplus, + bool check_objc) { + clang::QualType pointee_qual_type; + if (type) { + clang::QualType qual_type(GetCanonicalQualType(type)); + bool success = false; + const clang::Type::TypeClass type_class = qual_type->getTypeClass(); + switch (type_class) { + case clang::Type::Builtin: + if (check_objc && + llvm::cast<clang::BuiltinType>(qual_type)->getKind() == + clang::BuiltinType::ObjCId) { + if (dynamic_pointee_type) + dynamic_pointee_type->SetCompilerType(this, type); + return true; + } + break; + + case clang::Type::ObjCObjectPointer: + if (check_objc) { + if (auto objc_pointee_type = + qual_type->getPointeeType().getTypePtrOrNull()) { + if (auto objc_object_type = + llvm::dyn_cast_or_null<clang::ObjCObjectType>( + objc_pointee_type)) { + if (objc_object_type->isObjCClass()) + return false; + } } - - if (success) - { - // Check to make sure what we are pointing too is a possible dynamic C++ type - // We currently accept any "void *" (in case we have a class that has been - // watered down to an opaque pointer) and virtual C++ classes. - const clang::Type::TypeClass pointee_type_class = pointee_qual_type.getCanonicalType()->getTypeClass(); - switch (pointee_type_class) - { - case clang::Type::Builtin: - switch (llvm::cast<clang::BuiltinType>(pointee_qual_type)->getKind()) - { - case clang::BuiltinType::UnknownAny: - case clang::BuiltinType::Void: - if (dynamic_pointee_type) - dynamic_pointee_type->SetCompilerType(getASTContext(), pointee_qual_type); - return true; - default: - break; - } - break; - - case clang::Type::Record: - if (check_cplusplus) - { - clang::CXXRecordDecl *cxx_record_decl = pointee_qual_type->getAsCXXRecordDecl(); - if (cxx_record_decl) - { - bool is_complete = cxx_record_decl->isCompleteDefinition(); - - if (is_complete) - success = cxx_record_decl->isDynamicClass(); - else - { - ClangASTMetadata *metadata = ClangASTContext::GetMetadata (getASTContext(), cxx_record_decl); - if (metadata) - success = metadata->GetIsDynamicCXXType(); - else - { - is_complete = CompilerType(getASTContext(), pointee_qual_type).GetCompleteType(); - if (is_complete) - success = cxx_record_decl->isDynamicClass(); - else - success = false; - } - } - - if (success) - { - if (dynamic_pointee_type) - dynamic_pointee_type->SetCompilerType(getASTContext(), pointee_qual_type); - return true; - } - } - } - break; - - case clang::Type::ObjCObject: - case clang::Type::ObjCInterface: - if (check_objc) - { - if (dynamic_pointee_type) - dynamic_pointee_type->SetCompilerType(getASTContext(), pointee_qual_type); - return true; - } - break; - - default: - break; + if (dynamic_pointee_type) + dynamic_pointee_type->SetCompilerType( + getASTContext(), + llvm::cast<clang::ObjCObjectPointerType>(qual_type) + ->getPointeeType()); + return true; + } + break; + + case clang::Type::Pointer: + pointee_qual_type = + llvm::cast<clang::PointerType>(qual_type)->getPointeeType(); + success = true; + break; + + case clang::Type::LValueReference: + case clang::Type::RValueReference: + pointee_qual_type = + llvm::cast<clang::ReferenceType>(qual_type)->getPointeeType(); + success = true; + break; + + case clang::Type::Typedef: + return IsPossibleDynamicType(llvm::cast<clang::TypedefType>(qual_type) + ->getDecl() + ->getUnderlyingType() + .getAsOpaquePtr(), + dynamic_pointee_type, check_cplusplus, + check_objc); + + case clang::Type::Auto: + return IsPossibleDynamicType(llvm::cast<clang::AutoType>(qual_type) + ->getDeducedType() + .getAsOpaquePtr(), + dynamic_pointee_type, check_cplusplus, + check_objc); + + case clang::Type::Elaborated: + return IsPossibleDynamicType(llvm::cast<clang::ElaboratedType>(qual_type) + ->getNamedType() + .getAsOpaquePtr(), + dynamic_pointee_type, check_cplusplus, + check_objc); + + case clang::Type::Paren: + return IsPossibleDynamicType( + llvm::cast<clang::ParenType>(qual_type)->desugar().getAsOpaquePtr(), + dynamic_pointee_type, check_cplusplus, check_objc); + default: + break; + } + + if (success) { + // Check to make sure what we are pointing too is a possible dynamic C++ + // type + // We currently accept any "void *" (in case we have a class that has been + // watered down to an opaque pointer) and virtual C++ classes. + const clang::Type::TypeClass pointee_type_class = + pointee_qual_type.getCanonicalType()->getTypeClass(); + switch (pointee_type_class) { + case clang::Type::Builtin: + switch (llvm::cast<clang::BuiltinType>(pointee_qual_type)->getKind()) { + case clang::BuiltinType::UnknownAny: + case clang::BuiltinType::Void: + if (dynamic_pointee_type) + dynamic_pointee_type->SetCompilerType(getASTContext(), + pointee_qual_type); + return true; + default: + break; + } + break; + + case clang::Type::Record: + if (check_cplusplus) { + clang::CXXRecordDecl *cxx_record_decl = + pointee_qual_type->getAsCXXRecordDecl(); + if (cxx_record_decl) { + bool is_complete = cxx_record_decl->isCompleteDefinition(); + + if (is_complete) + success = cxx_record_decl->isDynamicClass(); + else { + ClangASTMetadata *metadata = ClangASTContext::GetMetadata( + getASTContext(), cxx_record_decl); + if (metadata) + success = metadata->GetIsDynamicCXXType(); + else { + is_complete = CompilerType(getASTContext(), pointee_qual_type) + .GetCompleteType(); + if (is_complete) + success = cxx_record_decl->isDynamicClass(); + else + success = false; + } + } + + if (success) { + if (dynamic_pointee_type) + dynamic_pointee_type->SetCompilerType(getASTContext(), + pointee_qual_type); + return true; } + } + } + break; + + case clang::Type::ObjCObject: + case clang::Type::ObjCInterface: + if (check_objc) { + if (dynamic_pointee_type) + dynamic_pointee_type->SetCompilerType(getASTContext(), + pointee_qual_type); + return true; } + break; + + default: + break; + } } - if (dynamic_pointee_type) - dynamic_pointee_type->Clear(); - return false; + } + if (dynamic_pointee_type) + dynamic_pointee_type->Clear(); + return false; } +bool ClangASTContext::IsScalarType(lldb::opaque_compiler_type_t type) { + if (!type) + return false; -bool -ClangASTContext::IsScalarType (lldb::opaque_compiler_type_t type) -{ - if (!type) - return false; - - return (GetTypeInfo (type, nullptr) & eTypeIsScalar) != 0; + return (GetTypeInfo(type, nullptr) & eTypeIsScalar) != 0; } -bool -ClangASTContext::IsTypedefType (lldb::opaque_compiler_type_t type) -{ - if (!type) - return false; - return GetQualType(type)->getTypeClass() == clang::Type::Typedef; +bool ClangASTContext::IsTypedefType(lldb::opaque_compiler_type_t type) { + if (!type) + return false; + return GetQualType(type)->getTypeClass() == clang::Type::Typedef; } -bool -ClangASTContext::IsVoidType (lldb::opaque_compiler_type_t type) -{ - if (!type) - return false; - return GetCanonicalQualType(type)->isVoidType(); -} - -bool -ClangASTContext::SupportsLanguage (lldb::LanguageType language) -{ - return ClangASTContextSupportsLanguage(language); -} - -bool -ClangASTContext::GetCXXClassName (const CompilerType& type, std::string &class_name) -{ - if (type) - { - clang::QualType qual_type(ClangUtil::GetCanonicalQualType(type)); - if (!qual_type.isNull()) - { - clang::CXXRecordDecl *cxx_record_decl = qual_type->getAsCXXRecordDecl(); - if (cxx_record_decl) - { - class_name.assign(cxx_record_decl->getIdentifier()->getNameStart()); - return true; - } - } - } - class_name.clear(); +bool ClangASTContext::IsVoidType(lldb::opaque_compiler_type_t type) { + if (!type) return false; + return GetCanonicalQualType(type)->isVoidType(); } +bool ClangASTContext::SupportsLanguage(lldb::LanguageType language) { + return ClangASTContextSupportsLanguage(language); +} -bool -ClangASTContext::IsCXXClassType (const CompilerType& type) -{ - if (!type) - return false; - +bool ClangASTContext::GetCXXClassName(const CompilerType &type, + std::string &class_name) { + if (type) { clang::QualType qual_type(ClangUtil::GetCanonicalQualType(type)); - if (!qual_type.isNull() && qual_type->getAsCXXRecordDecl() != nullptr) + if (!qual_type.isNull()) { + clang::CXXRecordDecl *cxx_record_decl = qual_type->getAsCXXRecordDecl(); + if (cxx_record_decl) { + class_name.assign(cxx_record_decl->getIdentifier()->getNameStart()); return true; + } + } + } + class_name.clear(); + return false; +} + +bool ClangASTContext::IsCXXClassType(const CompilerType &type) { + if (!type) return false; + + clang::QualType qual_type(ClangUtil::GetCanonicalQualType(type)); + if (!qual_type.isNull() && qual_type->getAsCXXRecordDecl() != nullptr) + return true; + return false; } -bool -ClangASTContext::IsBeingDefined (lldb::opaque_compiler_type_t type) -{ - if (!type) - return false; - clang::QualType qual_type (GetCanonicalQualType(type)); - const clang::TagType *tag_type = llvm::dyn_cast<clang::TagType>(qual_type); - if (tag_type) - return tag_type->isBeingDefined(); +bool ClangASTContext::IsBeingDefined(lldb::opaque_compiler_type_t type) { + if (!type) return false; + clang::QualType qual_type(GetCanonicalQualType(type)); + const clang::TagType *tag_type = llvm::dyn_cast<clang::TagType>(qual_type); + if (tag_type) + return tag_type->isBeingDefined(); + return false; } -bool -ClangASTContext::IsObjCObjectPointerType (const CompilerType& type, CompilerType *class_type_ptr) -{ - if (!type) - return false; +bool ClangASTContext::IsObjCObjectPointerType(const CompilerType &type, + CompilerType *class_type_ptr) { + if (!type) + return false; - clang::QualType qual_type(ClangUtil::GetCanonicalQualType(type)); + clang::QualType qual_type(ClangUtil::GetCanonicalQualType(type)); - if (!qual_type.isNull() && qual_type->isObjCObjectPointerType()) - { - if (class_type_ptr) - { - if (!qual_type->isObjCClassType() && - !qual_type->isObjCIdType()) - { - const clang::ObjCObjectPointerType *obj_pointer_type = llvm::dyn_cast<clang::ObjCObjectPointerType>(qual_type); - if (obj_pointer_type == nullptr) - class_type_ptr->Clear(); - else - class_type_ptr->SetCompilerType (type.GetTypeSystem(), clang::QualType(obj_pointer_type->getInterfaceType(), 0).getAsOpaquePtr()); - } - } - return true; + if (!qual_type.isNull() && qual_type->isObjCObjectPointerType()) { + if (class_type_ptr) { + if (!qual_type->isObjCClassType() && !qual_type->isObjCIdType()) { + const clang::ObjCObjectPointerType *obj_pointer_type = + llvm::dyn_cast<clang::ObjCObjectPointerType>(qual_type); + if (obj_pointer_type == nullptr) + class_type_ptr->Clear(); + else + class_type_ptr->SetCompilerType( + type.GetTypeSystem(), + clang::QualType(obj_pointer_type->getInterfaceType(), 0) + .getAsOpaquePtr()); + } } - if (class_type_ptr) - class_type_ptr->Clear(); - return false; + return true; + } + if (class_type_ptr) + class_type_ptr->Clear(); + return false; } -bool -ClangASTContext::GetObjCClassName (const CompilerType& type, std::string &class_name) -{ - if (!type) - return false; +bool ClangASTContext::GetObjCClassName(const CompilerType &type, + std::string &class_name) { + if (!type) + return false; - clang::QualType qual_type(ClangUtil::GetCanonicalQualType(type)); + clang::QualType qual_type(ClangUtil::GetCanonicalQualType(type)); - const clang::ObjCObjectType *object_type = llvm::dyn_cast<clang::ObjCObjectType>(qual_type); - if (object_type) - { - const clang::ObjCInterfaceDecl *interface = object_type->getInterface(); - if (interface) - { - class_name = interface->getNameAsString(); - return true; - } + const clang::ObjCObjectType *object_type = + llvm::dyn_cast<clang::ObjCObjectType>(qual_type); + if (object_type) { + const clang::ObjCInterfaceDecl *interface = object_type->getInterface(); + if (interface) { + class_name = interface->getNameAsString(); + return true; } - return false; + } + return false; } - //---------------------------------------------------------------------- // Type Completion //---------------------------------------------------------------------- -bool -ClangASTContext::GetCompleteType (lldb::opaque_compiler_type_t type) -{ - if (!type) - return false; - const bool allow_completion = true; - return GetCompleteQualType (getASTContext(), GetQualType(type), allow_completion); +bool ClangASTContext::GetCompleteType(lldb::opaque_compiler_type_t type) { + if (!type) + return false; + const bool allow_completion = true; + return GetCompleteQualType(getASTContext(), GetQualType(type), + allow_completion); } -ConstString -ClangASTContext::GetTypeName (lldb::opaque_compiler_type_t type) -{ - std::string type_name; - if (type) - { - clang::PrintingPolicy printing_policy (getASTContext()->getPrintingPolicy()); - clang::QualType qual_type(GetQualType(type)); - printing_policy.SuppressTagKeyword = true; - const clang::TypedefType *typedef_type = qual_type->getAs<clang::TypedefType>(); - if (typedef_type) - { - const clang::TypedefNameDecl *typedef_decl = typedef_type->getDecl(); - type_name = typedef_decl->getQualifiedNameAsString(); - } - else - { - type_name = qual_type.getAsString(printing_policy); - } +ConstString ClangASTContext::GetTypeName(lldb::opaque_compiler_type_t type) { + std::string type_name; + if (type) { + clang::PrintingPolicy printing_policy(getASTContext()->getPrintingPolicy()); + clang::QualType qual_type(GetQualType(type)); + printing_policy.SuppressTagKeyword = true; + const clang::TypedefType *typedef_type = + qual_type->getAs<clang::TypedefType>(); + if (typedef_type) { + const clang::TypedefNameDecl *typedef_decl = typedef_type->getDecl(); + type_name = typedef_decl->getQualifiedNameAsString(); + } else { + type_name = qual_type.getAsString(printing_policy); } - return ConstString(type_name); + } + return ConstString(type_name); } uint32_t -ClangASTContext::GetTypeInfo (lldb::opaque_compiler_type_t type, CompilerType *pointee_or_element_clang_type) -{ - if (!type) - return 0; - - if (pointee_or_element_clang_type) - pointee_or_element_clang_type->Clear(); - - clang::QualType qual_type (GetQualType(type)); - - const clang::Type::TypeClass type_class = qual_type->getTypeClass(); - switch (type_class) - { - case clang::Type::Builtin: - { - const clang::BuiltinType *builtin_type = llvm::dyn_cast<clang::BuiltinType>(qual_type->getCanonicalTypeInternal()); - - uint32_t builtin_type_flags = eTypeIsBuiltIn | eTypeHasValue; - switch (builtin_type->getKind()) - { - case clang::BuiltinType::ObjCId: - case clang::BuiltinType::ObjCClass: - if (pointee_or_element_clang_type) - pointee_or_element_clang_type->SetCompilerType(getASTContext(), getASTContext()->ObjCBuiltinClassTy); - builtin_type_flags |= eTypeIsPointer | eTypeIsObjC; - break; - - case clang::BuiltinType::ObjCSel: - if (pointee_or_element_clang_type) - pointee_or_element_clang_type->SetCompilerType(getASTContext(), getASTContext()->CharTy); - builtin_type_flags |= eTypeIsPointer | eTypeIsObjC; - break; - - case clang::BuiltinType::Bool: - case clang::BuiltinType::Char_U: - case clang::BuiltinType::UChar: - case clang::BuiltinType::WChar_U: - case clang::BuiltinType::Char16: - case clang::BuiltinType::Char32: - case clang::BuiltinType::UShort: - case clang::BuiltinType::UInt: - case clang::BuiltinType::ULong: - case clang::BuiltinType::ULongLong: - case clang::BuiltinType::UInt128: - case clang::BuiltinType::Char_S: - case clang::BuiltinType::SChar: - case clang::BuiltinType::WChar_S: - case clang::BuiltinType::Short: - case clang::BuiltinType::Int: - case clang::BuiltinType::Long: - case clang::BuiltinType::LongLong: - case clang::BuiltinType::Int128: - case clang::BuiltinType::Float: - case clang::BuiltinType::Double: - case clang::BuiltinType::LongDouble: - builtin_type_flags |= eTypeIsScalar; - if (builtin_type->isInteger()) - { - builtin_type_flags |= eTypeIsInteger; - if (builtin_type->isSignedInteger()) - builtin_type_flags |= eTypeIsSigned; - } - else if (builtin_type->isFloatingPoint()) - builtin_type_flags |= eTypeIsFloat; - break; - default: - break; - } - return builtin_type_flags; - } - - case clang::Type::BlockPointer: - if (pointee_or_element_clang_type) - pointee_or_element_clang_type->SetCompilerType(getASTContext(), qual_type->getPointeeType()); - return eTypeIsPointer | eTypeHasChildren | eTypeIsBlock; - - case clang::Type::Complex: - { - uint32_t complex_type_flags = eTypeIsBuiltIn | eTypeHasValue | eTypeIsComplex; - const clang::ComplexType *complex_type = llvm::dyn_cast<clang::ComplexType>(qual_type->getCanonicalTypeInternal()); - if (complex_type) - { - clang::QualType complex_element_type (complex_type->getElementType()); - if (complex_element_type->isIntegerType()) - complex_type_flags |= eTypeIsFloat; - else if (complex_element_type->isFloatingType()) - complex_type_flags |= eTypeIsInteger; - } - return complex_type_flags; - } - break; - - case clang::Type::ConstantArray: - case clang::Type::DependentSizedArray: - case clang::Type::IncompleteArray: - case clang::Type::VariableArray: - if (pointee_or_element_clang_type) - pointee_or_element_clang_type->SetCompilerType(getASTContext(), llvm::cast<clang::ArrayType>(qual_type.getTypePtr())->getElementType()); - return eTypeHasChildren | eTypeIsArray; - - case clang::Type::DependentName: return 0; - case clang::Type::DependentSizedExtVector: return eTypeHasChildren | eTypeIsVector; - case clang::Type::DependentTemplateSpecialization: return eTypeIsTemplate; - case clang::Type::Decltype: return 0; - - case clang::Type::Enum: - if (pointee_or_element_clang_type) - pointee_or_element_clang_type->SetCompilerType(getASTContext(), llvm::cast<clang::EnumType>(qual_type)->getDecl()->getIntegerType()); - return eTypeIsEnumeration | eTypeHasValue; - - case clang::Type::Auto: - return CompilerType (getASTContext(), llvm::cast<clang::AutoType>(qual_type)->getDeducedType()).GetTypeInfo (pointee_or_element_clang_type); - case clang::Type::Elaborated: - return CompilerType (getASTContext(), llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType()).GetTypeInfo (pointee_or_element_clang_type); - case clang::Type::Paren: - return CompilerType (getASTContext(), llvm::cast<clang::ParenType>(qual_type)->desugar()).GetTypeInfo (pointee_or_element_clang_type); - - case clang::Type::FunctionProto: return eTypeIsFuncPrototype | eTypeHasValue; - case clang::Type::FunctionNoProto: return eTypeIsFuncPrototype | eTypeHasValue; - case clang::Type::InjectedClassName: return 0; - - case clang::Type::LValueReference: - case clang::Type::RValueReference: - if (pointee_or_element_clang_type) - pointee_or_element_clang_type->SetCompilerType(getASTContext(), llvm::cast<clang::ReferenceType>(qual_type.getTypePtr())->getPointeeType()); - return eTypeHasChildren | eTypeIsReference | eTypeHasValue; - - case clang::Type::MemberPointer: return eTypeIsPointer | eTypeIsMember | eTypeHasValue; - - case clang::Type::ObjCObjectPointer: - if (pointee_or_element_clang_type) - pointee_or_element_clang_type->SetCompilerType(getASTContext(), qual_type->getPointeeType()); - return eTypeHasChildren | eTypeIsObjC | eTypeIsClass | eTypeIsPointer | eTypeHasValue; - - case clang::Type::ObjCObject: return eTypeHasChildren | eTypeIsObjC | eTypeIsClass; - case clang::Type::ObjCInterface: return eTypeHasChildren | eTypeIsObjC | eTypeIsClass; - - case clang::Type::Pointer: - if (pointee_or_element_clang_type) - pointee_or_element_clang_type->SetCompilerType(getASTContext(), qual_type->getPointeeType()); - return eTypeHasChildren | eTypeIsPointer | eTypeHasValue; - - case clang::Type::Record: - if (qual_type->getAsCXXRecordDecl()) - return eTypeHasChildren | eTypeIsClass | eTypeIsCPlusPlus; - else - return eTypeHasChildren | eTypeIsStructUnion; - break; - case clang::Type::SubstTemplateTypeParm: return eTypeIsTemplate; - case clang::Type::TemplateTypeParm: return eTypeIsTemplate; - case clang::Type::TemplateSpecialization: return eTypeIsTemplate; - - case clang::Type::Typedef: - return eTypeIsTypedef | CompilerType (getASTContext(), llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType()).GetTypeInfo (pointee_or_element_clang_type); - case clang::Type::TypeOfExpr: return 0; - case clang::Type::TypeOf: return 0; - case clang::Type::UnresolvedUsing: return 0; - - case clang::Type::ExtVector: - case clang::Type::Vector: - { - uint32_t vector_type_flags = eTypeHasChildren | eTypeIsVector; - const clang::VectorType *vector_type = llvm::dyn_cast<clang::VectorType>(qual_type->getCanonicalTypeInternal()); - if (vector_type) - { - if (vector_type->isIntegerType()) - vector_type_flags |= eTypeIsFloat; - else if (vector_type->isFloatingType()) - vector_type_flags |= eTypeIsInteger; - } - return vector_type_flags; - } - default: return 0; +ClangASTContext::GetTypeInfo(lldb::opaque_compiler_type_t type, + CompilerType *pointee_or_element_clang_type) { + if (!type) + return 0; + + if (pointee_or_element_clang_type) + pointee_or_element_clang_type->Clear(); + + clang::QualType qual_type(GetQualType(type)); + + const clang::Type::TypeClass type_class = qual_type->getTypeClass(); + switch (type_class) { + case clang::Type::Builtin: { + const clang::BuiltinType *builtin_type = llvm::dyn_cast<clang::BuiltinType>( + qual_type->getCanonicalTypeInternal()); + + uint32_t builtin_type_flags = eTypeIsBuiltIn | eTypeHasValue; + switch (builtin_type->getKind()) { + case clang::BuiltinType::ObjCId: + case clang::BuiltinType::ObjCClass: + if (pointee_or_element_clang_type) + pointee_or_element_clang_type->SetCompilerType( + getASTContext(), getASTContext()->ObjCBuiltinClassTy); + builtin_type_flags |= eTypeIsPointer | eTypeIsObjC; + break; + + case clang::BuiltinType::ObjCSel: + if (pointee_or_element_clang_type) + pointee_or_element_clang_type->SetCompilerType(getASTContext(), + getASTContext()->CharTy); + builtin_type_flags |= eTypeIsPointer | eTypeIsObjC; + break; + + case clang::BuiltinType::Bool: + case clang::BuiltinType::Char_U: + case clang::BuiltinType::UChar: + case clang::BuiltinType::WChar_U: + case clang::BuiltinType::Char16: + case clang::BuiltinType::Char32: + case clang::BuiltinType::UShort: + case clang::BuiltinType::UInt: + case clang::BuiltinType::ULong: + case clang::BuiltinType::ULongLong: + case clang::BuiltinType::UInt128: + case clang::BuiltinType::Char_S: + case clang::BuiltinType::SChar: + case clang::BuiltinType::WChar_S: + case clang::BuiltinType::Short: + case clang::BuiltinType::Int: + case clang::BuiltinType::Long: + case clang::BuiltinType::LongLong: + case clang::BuiltinType::Int128: + case clang::BuiltinType::Float: + case clang::BuiltinType::Double: + case clang::BuiltinType::LongDouble: + builtin_type_flags |= eTypeIsScalar; + if (builtin_type->isInteger()) { + builtin_type_flags |= eTypeIsInteger; + if (builtin_type->isSignedInteger()) + builtin_type_flags |= eTypeIsSigned; + } else if (builtin_type->isFloatingPoint()) + builtin_type_flags |= eTypeIsFloat; + break; + default: + break; } + return builtin_type_flags; + } + + case clang::Type::BlockPointer: + if (pointee_or_element_clang_type) + pointee_or_element_clang_type->SetCompilerType( + getASTContext(), qual_type->getPointeeType()); + return eTypeIsPointer | eTypeHasChildren | eTypeIsBlock; + + case clang::Type::Complex: { + uint32_t complex_type_flags = + eTypeIsBuiltIn | eTypeHasValue | eTypeIsComplex; + const clang::ComplexType *complex_type = llvm::dyn_cast<clang::ComplexType>( + qual_type->getCanonicalTypeInternal()); + if (complex_type) { + clang::QualType complex_element_type(complex_type->getElementType()); + if (complex_element_type->isIntegerType()) + complex_type_flags |= eTypeIsFloat; + else if (complex_element_type->isFloatingType()) + complex_type_flags |= eTypeIsInteger; + } + return complex_type_flags; + } break; + + case clang::Type::ConstantArray: + case clang::Type::DependentSizedArray: + case clang::Type::IncompleteArray: + case clang::Type::VariableArray: + if (pointee_or_element_clang_type) + pointee_or_element_clang_type->SetCompilerType( + getASTContext(), llvm::cast<clang::ArrayType>(qual_type.getTypePtr()) + ->getElementType()); + return eTypeHasChildren | eTypeIsArray; + + case clang::Type::DependentName: + return 0; + case clang::Type::DependentSizedExtVector: + return eTypeHasChildren | eTypeIsVector; + case clang::Type::DependentTemplateSpecialization: + return eTypeIsTemplate; + case clang::Type::Decltype: return 0; -} + case clang::Type::Enum: + if (pointee_or_element_clang_type) + pointee_or_element_clang_type->SetCompilerType( + getASTContext(), + llvm::cast<clang::EnumType>(qual_type)->getDecl()->getIntegerType()); + return eTypeIsEnumeration | eTypeHasValue; + + case clang::Type::Auto: + return CompilerType( + getASTContext(), + llvm::cast<clang::AutoType>(qual_type)->getDeducedType()) + .GetTypeInfo(pointee_or_element_clang_type); + case clang::Type::Elaborated: + return CompilerType( + getASTContext(), + llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType()) + .GetTypeInfo(pointee_or_element_clang_type); + case clang::Type::Paren: + return CompilerType(getASTContext(), + llvm::cast<clang::ParenType>(qual_type)->desugar()) + .GetTypeInfo(pointee_or_element_clang_type); + + case clang::Type::FunctionProto: + return eTypeIsFuncPrototype | eTypeHasValue; + case clang::Type::FunctionNoProto: + return eTypeIsFuncPrototype | eTypeHasValue; + case clang::Type::InjectedClassName: + return 0; + case clang::Type::LValueReference: + case clang::Type::RValueReference: + if (pointee_or_element_clang_type) + pointee_or_element_clang_type->SetCompilerType( + getASTContext(), + llvm::cast<clang::ReferenceType>(qual_type.getTypePtr()) + ->getPointeeType()); + return eTypeHasChildren | eTypeIsReference | eTypeHasValue; -lldb::LanguageType -ClangASTContext::GetMinimumLanguage (lldb::opaque_compiler_type_t type) -{ - if (!type) - return lldb::eLanguageTypeC; - - // If the type is a reference, then resolve it to what it refers to first: - clang::QualType qual_type (GetCanonicalQualType(type).getNonReferenceType()); - if (qual_type->isAnyPointerType()) - { - if (qual_type->isObjCObjectPointerType()) - return lldb::eLanguageTypeObjC; - - clang::QualType pointee_type (qual_type->getPointeeType()); - if (pointee_type->getPointeeCXXRecordDecl() != nullptr) - return lldb::eLanguageTypeC_plus_plus; - if (pointee_type->isObjCObjectOrInterfaceType()) - return lldb::eLanguageTypeObjC; - if (pointee_type->isObjCClassType()) - return lldb::eLanguageTypeObjC; - if (pointee_type.getTypePtr() == getASTContext()->ObjCBuiltinIdTy.getTypePtr()) - return lldb::eLanguageTypeObjC; - } + case clang::Type::MemberPointer: + return eTypeIsPointer | eTypeIsMember | eTypeHasValue; + + case clang::Type::ObjCObjectPointer: + if (pointee_or_element_clang_type) + pointee_or_element_clang_type->SetCompilerType( + getASTContext(), qual_type->getPointeeType()); + return eTypeHasChildren | eTypeIsObjC | eTypeIsClass | eTypeIsPointer | + eTypeHasValue; + + case clang::Type::ObjCObject: + return eTypeHasChildren | eTypeIsObjC | eTypeIsClass; + case clang::Type::ObjCInterface: + return eTypeHasChildren | eTypeIsObjC | eTypeIsClass; + + case clang::Type::Pointer: + if (pointee_or_element_clang_type) + pointee_or_element_clang_type->SetCompilerType( + getASTContext(), qual_type->getPointeeType()); + return eTypeHasChildren | eTypeIsPointer | eTypeHasValue; + + case clang::Type::Record: + if (qual_type->getAsCXXRecordDecl()) + return eTypeHasChildren | eTypeIsClass | eTypeIsCPlusPlus; else - { - if (qual_type->isObjCObjectOrInterfaceType()) - return lldb::eLanguageTypeObjC; - if (qual_type->getAsCXXRecordDecl()) - return lldb::eLanguageTypeC_plus_plus; - switch (qual_type->getTypeClass()) - { - default: - break; - case clang::Type::Builtin: - switch (llvm::cast<clang::BuiltinType>(qual_type)->getKind()) - { - default: - case clang::BuiltinType::Void: - case clang::BuiltinType::Bool: - case clang::BuiltinType::Char_U: - case clang::BuiltinType::UChar: - case clang::BuiltinType::WChar_U: - case clang::BuiltinType::Char16: - case clang::BuiltinType::Char32: - case clang::BuiltinType::UShort: - case clang::BuiltinType::UInt: - case clang::BuiltinType::ULong: - case clang::BuiltinType::ULongLong: - case clang::BuiltinType::UInt128: - case clang::BuiltinType::Char_S: - case clang::BuiltinType::SChar: - case clang::BuiltinType::WChar_S: - case clang::BuiltinType::Short: - case clang::BuiltinType::Int: - case clang::BuiltinType::Long: - case clang::BuiltinType::LongLong: - case clang::BuiltinType::Int128: - case clang::BuiltinType::Float: - case clang::BuiltinType::Double: - case clang::BuiltinType::LongDouble: - break; - - case clang::BuiltinType::NullPtr: - return eLanguageTypeC_plus_plus; - - case clang::BuiltinType::ObjCId: - case clang::BuiltinType::ObjCClass: - case clang::BuiltinType::ObjCSel: - return eLanguageTypeObjC; - - case clang::BuiltinType::Dependent: - case clang::BuiltinType::Overload: - case clang::BuiltinType::BoundMember: - case clang::BuiltinType::UnknownAny: - break; - } - break; - case clang::Type::Typedef: - return CompilerType(getASTContext(), llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType()).GetMinimumLanguage(); - } - } + return eTypeHasChildren | eTypeIsStructUnion; + break; + case clang::Type::SubstTemplateTypeParm: + return eTypeIsTemplate; + case clang::Type::TemplateTypeParm: + return eTypeIsTemplate; + case clang::Type::TemplateSpecialization: + return eTypeIsTemplate; + + case clang::Type::Typedef: + return eTypeIsTypedef | + CompilerType(getASTContext(), + llvm::cast<clang::TypedefType>(qual_type) + ->getDecl() + ->getUnderlyingType()) + .GetTypeInfo(pointee_or_element_clang_type); + case clang::Type::TypeOfExpr: + return 0; + case clang::Type::TypeOf: + return 0; + case clang::Type::UnresolvedUsing: + return 0; + + case clang::Type::ExtVector: + case clang::Type::Vector: { + uint32_t vector_type_flags = eTypeHasChildren | eTypeIsVector; + const clang::VectorType *vector_type = llvm::dyn_cast<clang::VectorType>( + qual_type->getCanonicalTypeInternal()); + if (vector_type) { + if (vector_type->isIntegerType()) + vector_type_flags |= eTypeIsFloat; + else if (vector_type->isFloatingType()) + vector_type_flags |= eTypeIsInteger; + } + return vector_type_flags; + } + default: + return 0; + } + return 0; +} + +lldb::LanguageType +ClangASTContext::GetMinimumLanguage(lldb::opaque_compiler_type_t type) { + if (!type) return lldb::eLanguageTypeC; + + // If the type is a reference, then resolve it to what it refers to first: + clang::QualType qual_type(GetCanonicalQualType(type).getNonReferenceType()); + if (qual_type->isAnyPointerType()) { + if (qual_type->isObjCObjectPointerType()) + return lldb::eLanguageTypeObjC; + + clang::QualType pointee_type(qual_type->getPointeeType()); + if (pointee_type->getPointeeCXXRecordDecl() != nullptr) + return lldb::eLanguageTypeC_plus_plus; + if (pointee_type->isObjCObjectOrInterfaceType()) + return lldb::eLanguageTypeObjC; + if (pointee_type->isObjCClassType()) + return lldb::eLanguageTypeObjC; + if (pointee_type.getTypePtr() == + getASTContext()->ObjCBuiltinIdTy.getTypePtr()) + return lldb::eLanguageTypeObjC; + } else { + if (qual_type->isObjCObjectOrInterfaceType()) + return lldb::eLanguageTypeObjC; + if (qual_type->getAsCXXRecordDecl()) + return lldb::eLanguageTypeC_plus_plus; + switch (qual_type->getTypeClass()) { + default: + break; + case clang::Type::Builtin: + switch (llvm::cast<clang::BuiltinType>(qual_type)->getKind()) { + default: + case clang::BuiltinType::Void: + case clang::BuiltinType::Bool: + case clang::BuiltinType::Char_U: + case clang::BuiltinType::UChar: + case clang::BuiltinType::WChar_U: + case clang::BuiltinType::Char16: + case clang::BuiltinType::Char32: + case clang::BuiltinType::UShort: + case clang::BuiltinType::UInt: + case clang::BuiltinType::ULong: + case clang::BuiltinType::ULongLong: + case clang::BuiltinType::UInt128: + case clang::BuiltinType::Char_S: + case clang::BuiltinType::SChar: + case clang::BuiltinType::WChar_S: + case clang::BuiltinType::Short: + case clang::BuiltinType::Int: + case clang::BuiltinType::Long: + case clang::BuiltinType::LongLong: + case clang::BuiltinType::Int128: + case clang::BuiltinType::Float: + case clang::BuiltinType::Double: + case clang::BuiltinType::LongDouble: + break; + + case clang::BuiltinType::NullPtr: + return eLanguageTypeC_plus_plus; + + case clang::BuiltinType::ObjCId: + case clang::BuiltinType::ObjCClass: + case clang::BuiltinType::ObjCSel: + return eLanguageTypeObjC; + + case clang::BuiltinType::Dependent: + case clang::BuiltinType::Overload: + case clang::BuiltinType::BoundMember: + case clang::BuiltinType::UnknownAny: + break; + } + break; + case clang::Type::Typedef: + return CompilerType(getASTContext(), + llvm::cast<clang::TypedefType>(qual_type) + ->getDecl() + ->getUnderlyingType()) + .GetMinimumLanguage(); + } + } + return lldb::eLanguageTypeC; } lldb::TypeClass -ClangASTContext::GetTypeClass (lldb::opaque_compiler_type_t type) -{ - if (!type) - return lldb::eTypeClassInvalid; - - clang::QualType qual_type(GetQualType(type)); - - switch (qual_type->getTypeClass()) - { - case clang::Type::UnaryTransform: break; - case clang::Type::FunctionNoProto: return lldb::eTypeClassFunction; - case clang::Type::FunctionProto: return lldb::eTypeClassFunction; - case clang::Type::IncompleteArray: return lldb::eTypeClassArray; - case clang::Type::VariableArray: return lldb::eTypeClassArray; - case clang::Type::ConstantArray: return lldb::eTypeClassArray; - case clang::Type::DependentSizedArray: return lldb::eTypeClassArray; - case clang::Type::DependentSizedExtVector: return lldb::eTypeClassVector; - case clang::Type::ExtVector: return lldb::eTypeClassVector; - case clang::Type::Vector: return lldb::eTypeClassVector; - case clang::Type::Builtin: return lldb::eTypeClassBuiltin; - case clang::Type::ObjCObjectPointer: return lldb::eTypeClassObjCObjectPointer; - case clang::Type::BlockPointer: return lldb::eTypeClassBlockPointer; - case clang::Type::Pointer: return lldb::eTypeClassPointer; - case clang::Type::LValueReference: return lldb::eTypeClassReference; - case clang::Type::RValueReference: return lldb::eTypeClassReference; - case clang::Type::MemberPointer: return lldb::eTypeClassMemberPointer; - case clang::Type::Complex: - if (qual_type->isComplexType()) - return lldb::eTypeClassComplexFloat; - else - return lldb::eTypeClassComplexInteger; - case clang::Type::ObjCObject: return lldb::eTypeClassObjCObject; - case clang::Type::ObjCInterface: return lldb::eTypeClassObjCInterface; - case clang::Type::Record: - { - const clang::RecordType *record_type = llvm::cast<clang::RecordType>(qual_type.getTypePtr()); - const clang::RecordDecl *record_decl = record_type->getDecl(); - if (record_decl->isUnion()) - return lldb::eTypeClassUnion; - else if (record_decl->isStruct()) - return lldb::eTypeClassStruct; - else - return lldb::eTypeClassClass; - } - break; - case clang::Type::Enum: return lldb::eTypeClassEnumeration; - case clang::Type::Typedef: return lldb::eTypeClassTypedef; - case clang::Type::UnresolvedUsing: break; - case clang::Type::Paren: - return CompilerType(getASTContext(), llvm::cast<clang::ParenType>(qual_type)->desugar()).GetTypeClass(); - case clang::Type::Auto: - return CompilerType(getASTContext(), llvm::cast<clang::AutoType>(qual_type)->getDeducedType()).GetTypeClass(); - case clang::Type::Elaborated: - return CompilerType(getASTContext(), llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType()).GetTypeClass(); - - case clang::Type::Attributed: break; - case clang::Type::TemplateTypeParm: break; - case clang::Type::SubstTemplateTypeParm: break; - case clang::Type::SubstTemplateTypeParmPack:break; - case clang::Type::InjectedClassName: break; - case clang::Type::DependentName: break; - case clang::Type::DependentTemplateSpecialization: break; - case clang::Type::PackExpansion: break; - - case clang::Type::TypeOfExpr: break; - case clang::Type::TypeOf: break; - case clang::Type::Decltype: break; - case clang::Type::TemplateSpecialization: break; - case clang::Type::Atomic: break; - case clang::Type::Pipe: break; - - // pointer type decayed from an array or function type. - case clang::Type::Decayed: break; - case clang::Type::Adjusted: break; - } - // We don't know hot to display this type... - return lldb::eTypeClassOther; - -} - -unsigned -ClangASTContext::GetTypeQualifiers(lldb::opaque_compiler_type_t type) -{ - if (type) - return GetQualType(type).getQualifiers().getCVRQualifiers(); - return 0; +ClangASTContext::GetTypeClass(lldb::opaque_compiler_type_t type) { + if (!type) + return lldb::eTypeClassInvalid; + + clang::QualType qual_type(GetQualType(type)); + + switch (qual_type->getTypeClass()) { + case clang::Type::UnaryTransform: + break; + case clang::Type::FunctionNoProto: + return lldb::eTypeClassFunction; + case clang::Type::FunctionProto: + return lldb::eTypeClassFunction; + case clang::Type::IncompleteArray: + return lldb::eTypeClassArray; + case clang::Type::VariableArray: + return lldb::eTypeClassArray; + case clang::Type::ConstantArray: + return lldb::eTypeClassArray; + case clang::Type::DependentSizedArray: + return lldb::eTypeClassArray; + case clang::Type::DependentSizedExtVector: + return lldb::eTypeClassVector; + case clang::Type::ExtVector: + return lldb::eTypeClassVector; + case clang::Type::Vector: + return lldb::eTypeClassVector; + case clang::Type::Builtin: + return lldb::eTypeClassBuiltin; + case clang::Type::ObjCObjectPointer: + return lldb::eTypeClassObjCObjectPointer; + case clang::Type::BlockPointer: + return lldb::eTypeClassBlockPointer; + case clang::Type::Pointer: + return lldb::eTypeClassPointer; + case clang::Type::LValueReference: + return lldb::eTypeClassReference; + case clang::Type::RValueReference: + return lldb::eTypeClassReference; + case clang::Type::MemberPointer: + return lldb::eTypeClassMemberPointer; + case clang::Type::Complex: + if (qual_type->isComplexType()) + return lldb::eTypeClassComplexFloat; + else + return lldb::eTypeClassComplexInteger; + case clang::Type::ObjCObject: + return lldb::eTypeClassObjCObject; + case clang::Type::ObjCInterface: + return lldb::eTypeClassObjCInterface; + case clang::Type::Record: { + const clang::RecordType *record_type = + llvm::cast<clang::RecordType>(qual_type.getTypePtr()); + const clang::RecordDecl *record_decl = record_type->getDecl(); + if (record_decl->isUnion()) + return lldb::eTypeClassUnion; + else if (record_decl->isStruct()) + return lldb::eTypeClassStruct; + else + return lldb::eTypeClassClass; + } break; + case clang::Type::Enum: + return lldb::eTypeClassEnumeration; + case clang::Type::Typedef: + return lldb::eTypeClassTypedef; + case clang::Type::UnresolvedUsing: + break; + case clang::Type::Paren: + return CompilerType(getASTContext(), + llvm::cast<clang::ParenType>(qual_type)->desugar()) + .GetTypeClass(); + case clang::Type::Auto: + return CompilerType( + getASTContext(), + llvm::cast<clang::AutoType>(qual_type)->getDeducedType()) + .GetTypeClass(); + case clang::Type::Elaborated: + return CompilerType( + getASTContext(), + llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType()) + .GetTypeClass(); + + case clang::Type::Attributed: + break; + case clang::Type::TemplateTypeParm: + break; + case clang::Type::SubstTemplateTypeParm: + break; + case clang::Type::SubstTemplateTypeParmPack: + break; + case clang::Type::InjectedClassName: + break; + case clang::Type::DependentName: + break; + case clang::Type::DependentTemplateSpecialization: + break; + case clang::Type::PackExpansion: + break; + + case clang::Type::TypeOfExpr: + break; + case clang::Type::TypeOf: + break; + case clang::Type::Decltype: + break; + case clang::Type::TemplateSpecialization: + break; + case clang::Type::Atomic: + break; + case clang::Type::Pipe: + break; + + // pointer type decayed from an array or function type. + case clang::Type::Decayed: + break; + case clang::Type::Adjusted: + break; + } + // We don't know hot to display this type... + return lldb::eTypeClassOther; +} + +unsigned ClangASTContext::GetTypeQualifiers(lldb::opaque_compiler_type_t type) { + if (type) + return GetQualType(type).getQualifiers().getCVRQualifiers(); + return 0; } //---------------------------------------------------------------------- @@ -4542,1707 +4333,1822 @@ ClangASTContext::GetTypeQualifiers(lldb::opaque_compiler_type_t type) //---------------------------------------------------------------------- CompilerType -ClangASTContext::GetArrayElementType (lldb::opaque_compiler_type_t type, uint64_t *stride) -{ - if (type) - { - clang::QualType qual_type(GetCanonicalQualType(type)); - - const clang::Type *array_eletype = qual_type.getTypePtr()->getArrayElementTypeNoTypeQual(); - - if (!array_eletype) - return CompilerType(); - - CompilerType element_type (getASTContext(), array_eletype->getCanonicalTypeUnqualified()); - - // TODO: the real stride will be >= this value.. find the real one! - if (stride) - *stride = element_type.GetByteSize(nullptr); - - return element_type; - - } - return CompilerType(); -} +ClangASTContext::GetArrayElementType(lldb::opaque_compiler_type_t type, + uint64_t *stride) { + if (type) { + clang::QualType qual_type(GetCanonicalQualType(type)); -CompilerType -ClangASTContext::GetArrayType (lldb::opaque_compiler_type_t type, uint64_t size) -{ - if (type) - { - clang::QualType qual_type(GetCanonicalQualType(type)); - if (clang::ASTContext *ast_ctx = getASTContext()) - { - if (size != 0) - return CompilerType (ast_ctx, ast_ctx->getConstantArrayType(qual_type, llvm::APInt(64, size), clang::ArrayType::ArraySizeModifier::Normal, 0)); - else - return CompilerType (ast_ctx, ast_ctx->getIncompleteArrayType(qual_type, clang::ArrayType::ArraySizeModifier::Normal, 0)); - } - } - - return CompilerType(); -} + const clang::Type *array_eletype = + qual_type.getTypePtr()->getArrayElementTypeNoTypeQual(); -CompilerType -ClangASTContext::GetCanonicalType (lldb::opaque_compiler_type_t type) -{ - if (type) - return CompilerType (getASTContext(), GetCanonicalQualType(type)); - return CompilerType(); + if (!array_eletype) + return CompilerType(); + + CompilerType element_type(getASTContext(), + array_eletype->getCanonicalTypeUnqualified()); + + // TODO: the real stride will be >= this value.. find the real one! + if (stride) + *stride = element_type.GetByteSize(nullptr); + + return element_type; + } + return CompilerType(); } -static clang::QualType -GetFullyUnqualifiedType_Impl (clang::ASTContext *ast, clang::QualType qual_type) -{ - if (qual_type->isPointerType()) - qual_type = ast->getPointerType(GetFullyUnqualifiedType_Impl(ast, qual_type->getPointeeType())); - else - qual_type = qual_type.getUnqualifiedType(); - qual_type.removeLocalConst(); - qual_type.removeLocalRestrict(); - qual_type.removeLocalVolatile(); - return qual_type; +CompilerType ClangASTContext::GetArrayType(lldb::opaque_compiler_type_t type, + uint64_t size) { + if (type) { + clang::QualType qual_type(GetCanonicalQualType(type)); + if (clang::ASTContext *ast_ctx = getASTContext()) { + if (size != 0) + return CompilerType( + ast_ctx, ast_ctx->getConstantArrayType( + qual_type, llvm::APInt(64, size), + clang::ArrayType::ArraySizeModifier::Normal, 0)); + else + return CompilerType( + ast_ctx, + ast_ctx->getIncompleteArrayType( + qual_type, clang::ArrayType::ArraySizeModifier::Normal, 0)); + } + } + + return CompilerType(); } CompilerType -ClangASTContext::GetFullyUnqualifiedType (lldb::opaque_compiler_type_t type) -{ - if (type) - return CompilerType(getASTContext(), GetFullyUnqualifiedType_Impl(getASTContext(), GetQualType(type))); - return CompilerType(); +ClangASTContext::GetCanonicalType(lldb::opaque_compiler_type_t type) { + if (type) + return CompilerType(getASTContext(), GetCanonicalQualType(type)); + return CompilerType(); } - -int -ClangASTContext::GetFunctionArgumentCount (lldb::opaque_compiler_type_t type) -{ - if (type) - { - const clang::FunctionProtoType* func = llvm::dyn_cast<clang::FunctionProtoType>(GetCanonicalQualType(type)); - if (func) - return func->getNumParams(); - } - return -1; +static clang::QualType GetFullyUnqualifiedType_Impl(clang::ASTContext *ast, + clang::QualType qual_type) { + if (qual_type->isPointerType()) + qual_type = ast->getPointerType( + GetFullyUnqualifiedType_Impl(ast, qual_type->getPointeeType())); + else + qual_type = qual_type.getUnqualifiedType(); + qual_type.removeLocalConst(); + qual_type.removeLocalRestrict(); + qual_type.removeLocalVolatile(); + return qual_type; } CompilerType -ClangASTContext::GetFunctionArgumentTypeAtIndex (lldb::opaque_compiler_type_t type, size_t idx) -{ - if (type) - { - const clang::FunctionProtoType* func = llvm::dyn_cast<clang::FunctionProtoType>(GetQualType(type)); - if (func) - { - const uint32_t num_args = func->getNumParams(); - if (idx < num_args) - return CompilerType(getASTContext(), func->getParamType(idx)); - } - } - return CompilerType(); +ClangASTContext::GetFullyUnqualifiedType(lldb::opaque_compiler_type_t type) { + if (type) + return CompilerType( + getASTContext(), + GetFullyUnqualifiedType_Impl(getASTContext(), GetQualType(type))); + return CompilerType(); +} + +int ClangASTContext::GetFunctionArgumentCount( + lldb::opaque_compiler_type_t type) { + if (type) { + const clang::FunctionProtoType *func = + llvm::dyn_cast<clang::FunctionProtoType>(GetCanonicalQualType(type)); + if (func) + return func->getNumParams(); + } + return -1; +} + +CompilerType ClangASTContext::GetFunctionArgumentTypeAtIndex( + lldb::opaque_compiler_type_t type, size_t idx) { + if (type) { + const clang::FunctionProtoType *func = + llvm::dyn_cast<clang::FunctionProtoType>(GetQualType(type)); + if (func) { + const uint32_t num_args = func->getNumParams(); + if (idx < num_args) + return CompilerType(getASTContext(), func->getParamType(idx)); + } + } + return CompilerType(); } CompilerType -ClangASTContext::GetFunctionReturnType (lldb::opaque_compiler_type_t type) -{ - if (type) - { - clang::QualType qual_type(GetQualType(type)); - const clang::FunctionProtoType* func = llvm::dyn_cast<clang::FunctionProtoType>(qual_type.getTypePtr()); - if (func) - return CompilerType(getASTContext(), func->getReturnType()); - } - return CompilerType(); +ClangASTContext::GetFunctionReturnType(lldb::opaque_compiler_type_t type) { + if (type) { + clang::QualType qual_type(GetQualType(type)); + const clang::FunctionProtoType *func = + llvm::dyn_cast<clang::FunctionProtoType>(qual_type.getTypePtr()); + if (func) + return CompilerType(getASTContext(), func->getReturnType()); + } + return CompilerType(); } size_t -ClangASTContext::GetNumMemberFunctions (lldb::opaque_compiler_type_t type) -{ - size_t num_functions = 0; - if (type) - { - clang::QualType qual_type(GetCanonicalQualType(type)); - switch (qual_type->getTypeClass()) { - case clang::Type::Record: - if (GetCompleteQualType (getASTContext(), qual_type)) - { - const clang::RecordType *record_type = llvm::cast<clang::RecordType>(qual_type.getTypePtr()); - const clang::RecordDecl *record_decl = record_type->getDecl(); - assert(record_decl); - const clang::CXXRecordDecl *cxx_record_decl = llvm::dyn_cast<clang::CXXRecordDecl>(record_decl); - if (cxx_record_decl) - num_functions = std::distance(cxx_record_decl->method_begin(), cxx_record_decl->method_end()); - } - break; - - case clang::Type::ObjCObjectPointer: - if (GetCompleteType(type)) - { - const clang::ObjCObjectPointerType *objc_class_type = qual_type->getAsObjCInterfacePointerType(); - if (objc_class_type) - { - clang::ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterfaceDecl(); - if (class_interface_decl) - num_functions = std::distance(class_interface_decl->meth_begin(), class_interface_decl->meth_end()); - } - } - break; - - case clang::Type::ObjCObject: - case clang::Type::ObjCInterface: - if (GetCompleteType(type)) - { - const clang::ObjCObjectType *objc_class_type = llvm::dyn_cast<clang::ObjCObjectType>(qual_type.getTypePtr()); - if (objc_class_type) - { - clang::ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface(); - if (class_interface_decl) - num_functions = std::distance(class_interface_decl->meth_begin(), class_interface_decl->meth_end()); - } - } - break; - - - case clang::Type::Typedef: - return CompilerType (getASTContext(), llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType()).GetNumMemberFunctions(); - - case clang::Type::Auto: - return CompilerType (getASTContext(), llvm::cast<clang::AutoType>(qual_type)->getDeducedType()).GetNumMemberFunctions(); - - case clang::Type::Elaborated: - return CompilerType (getASTContext(), llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType()).GetNumMemberFunctions(); - - case clang::Type::Paren: - return CompilerType (getASTContext(), llvm::cast<clang::ParenType>(qual_type)->desugar()).GetNumMemberFunctions(); - - default: - break; +ClangASTContext::GetNumMemberFunctions(lldb::opaque_compiler_type_t type) { + size_t num_functions = 0; + if (type) { + clang::QualType qual_type(GetCanonicalQualType(type)); + switch (qual_type->getTypeClass()) { + case clang::Type::Record: + if (GetCompleteQualType(getASTContext(), qual_type)) { + const clang::RecordType *record_type = + llvm::cast<clang::RecordType>(qual_type.getTypePtr()); + const clang::RecordDecl *record_decl = record_type->getDecl(); + assert(record_decl); + const clang::CXXRecordDecl *cxx_record_decl = + llvm::dyn_cast<clang::CXXRecordDecl>(record_decl); + if (cxx_record_decl) + num_functions = std::distance(cxx_record_decl->method_begin(), + cxx_record_decl->method_end()); + } + break; + + case clang::Type::ObjCObjectPointer: + if (GetCompleteType(type)) { + const clang::ObjCObjectPointerType *objc_class_type = + qual_type->getAsObjCInterfacePointerType(); + if (objc_class_type) { + clang::ObjCInterfaceDecl *class_interface_decl = + objc_class_type->getInterfaceDecl(); + if (class_interface_decl) + num_functions = std::distance(class_interface_decl->meth_begin(), + class_interface_decl->meth_end()); + } + } + break; + + case clang::Type::ObjCObject: + case clang::Type::ObjCInterface: + if (GetCompleteType(type)) { + const clang::ObjCObjectType *objc_class_type = + llvm::dyn_cast<clang::ObjCObjectType>(qual_type.getTypePtr()); + if (objc_class_type) { + clang::ObjCInterfaceDecl *class_interface_decl = + objc_class_type->getInterface(); + if (class_interface_decl) + num_functions = std::distance(class_interface_decl->meth_begin(), + class_interface_decl->meth_end()); } + } + break; + + case clang::Type::Typedef: + return CompilerType(getASTContext(), + llvm::cast<clang::TypedefType>(qual_type) + ->getDecl() + ->getUnderlyingType()) + .GetNumMemberFunctions(); + + case clang::Type::Auto: + return CompilerType( + getASTContext(), + llvm::cast<clang::AutoType>(qual_type)->getDeducedType()) + .GetNumMemberFunctions(); + + case clang::Type::Elaborated: + return CompilerType( + getASTContext(), + llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType()) + .GetNumMemberFunctions(); + + case clang::Type::Paren: + return CompilerType(getASTContext(), + llvm::cast<clang::ParenType>(qual_type)->desugar()) + .GetNumMemberFunctions(); + + default: + break; } - return num_functions; + } + return num_functions; } TypeMemberFunctionImpl -ClangASTContext::GetMemberFunctionAtIndex (lldb::opaque_compiler_type_t type, size_t idx) -{ - std::string name; - MemberFunctionKind kind(MemberFunctionKind::eMemberFunctionKindUnknown); - CompilerType clang_type; - CompilerDecl clang_decl; - if (type) - { - clang::QualType qual_type(GetCanonicalQualType(type)); - switch (qual_type->getTypeClass()) { - case clang::Type::Record: - if (GetCompleteQualType (getASTContext(), qual_type)) - { - const clang::RecordType *record_type = llvm::cast<clang::RecordType>(qual_type.getTypePtr()); - const clang::RecordDecl *record_decl = record_type->getDecl(); - assert(record_decl); - const clang::CXXRecordDecl *cxx_record_decl = llvm::dyn_cast<clang::CXXRecordDecl>(record_decl); - if (cxx_record_decl) - { - auto method_iter = cxx_record_decl->method_begin(); - auto method_end = cxx_record_decl->method_end(); - if (idx < static_cast<size_t>(std::distance(method_iter, method_end))) - { - std::advance(method_iter, idx); - clang::CXXMethodDecl *cxx_method_decl = method_iter->getCanonicalDecl(); - if (cxx_method_decl) - { - name = cxx_method_decl->getDeclName().getAsString(); - if (cxx_method_decl->isStatic()) - kind = lldb::eMemberFunctionKindStaticMethod; - else if (llvm::isa<clang::CXXConstructorDecl>(cxx_method_decl)) - kind = lldb::eMemberFunctionKindConstructor; - else if (llvm::isa<clang::CXXDestructorDecl>(cxx_method_decl)) - kind = lldb::eMemberFunctionKindDestructor; - else - kind = lldb::eMemberFunctionKindInstanceMethod; - clang_type = CompilerType(this, cxx_method_decl->getType().getAsOpaquePtr()); - clang_decl = CompilerDecl(this, cxx_method_decl); - } - } - } - } - break; - - case clang::Type::ObjCObjectPointer: - if (GetCompleteType(type)) - { - const clang::ObjCObjectPointerType *objc_class_type = qual_type->getAsObjCInterfacePointerType(); - if (objc_class_type) - { - clang::ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterfaceDecl(); - if (class_interface_decl) - { - auto method_iter = class_interface_decl->meth_begin(); - auto method_end = class_interface_decl->meth_end(); - if (idx < static_cast<size_t>(std::distance(method_iter, method_end))) - { - std::advance(method_iter, idx); - clang::ObjCMethodDecl *objc_method_decl = method_iter->getCanonicalDecl(); - if (objc_method_decl) - { - clang_decl = CompilerDecl(this, objc_method_decl); - name = objc_method_decl->getSelector().getAsString(); - if (objc_method_decl->isClassMethod()) - kind = lldb::eMemberFunctionKindStaticMethod; - else - kind = lldb::eMemberFunctionKindInstanceMethod; - } - } - } - } - } - break; - - case clang::Type::ObjCObject: - case clang::Type::ObjCInterface: - if (GetCompleteType(type)) - { - const clang::ObjCObjectType *objc_class_type = llvm::dyn_cast<clang::ObjCObjectType>(qual_type.getTypePtr()); - if (objc_class_type) - { - clang::ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface(); - if (class_interface_decl) - { - auto method_iter = class_interface_decl->meth_begin(); - auto method_end = class_interface_decl->meth_end(); - if (idx < static_cast<size_t>(std::distance(method_iter, method_end))) - { - std::advance(method_iter, idx); - clang::ObjCMethodDecl *objc_method_decl = method_iter->getCanonicalDecl(); - if (objc_method_decl) - { - clang_decl = CompilerDecl(this, objc_method_decl); - name = objc_method_decl->getSelector().getAsString(); - if (objc_method_decl->isClassMethod()) - kind = lldb::eMemberFunctionKindStaticMethod; - else - kind = lldb::eMemberFunctionKindInstanceMethod; - } - } - } - } - } - break; - - case clang::Type::Typedef: - return GetMemberFunctionAtIndex(llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType().getAsOpaquePtr(), idx); - - case clang::Type::Auto: - return GetMemberFunctionAtIndex(llvm::cast<clang::AutoType>(qual_type)->getDeducedType().getAsOpaquePtr(), idx); - - case clang::Type::Elaborated: - return GetMemberFunctionAtIndex(llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType().getAsOpaquePtr(), idx); - - case clang::Type::Paren: - return GetMemberFunctionAtIndex(llvm::cast<clang::ParenType>(qual_type)->desugar().getAsOpaquePtr(), idx); - - default: - break; +ClangASTContext::GetMemberFunctionAtIndex(lldb::opaque_compiler_type_t type, + size_t idx) { + std::string name; + MemberFunctionKind kind(MemberFunctionKind::eMemberFunctionKindUnknown); + CompilerType clang_type; + CompilerDecl clang_decl; + if (type) { + clang::QualType qual_type(GetCanonicalQualType(type)); + switch (qual_type->getTypeClass()) { + case clang::Type::Record: + if (GetCompleteQualType(getASTContext(), qual_type)) { + const clang::RecordType *record_type = + llvm::cast<clang::RecordType>(qual_type.getTypePtr()); + const clang::RecordDecl *record_decl = record_type->getDecl(); + assert(record_decl); + const clang::CXXRecordDecl *cxx_record_decl = + llvm::dyn_cast<clang::CXXRecordDecl>(record_decl); + if (cxx_record_decl) { + auto method_iter = cxx_record_decl->method_begin(); + auto method_end = cxx_record_decl->method_end(); + if (idx < + static_cast<size_t>(std::distance(method_iter, method_end))) { + std::advance(method_iter, idx); + clang::CXXMethodDecl *cxx_method_decl = + method_iter->getCanonicalDecl(); + if (cxx_method_decl) { + name = cxx_method_decl->getDeclName().getAsString(); + if (cxx_method_decl->isStatic()) + kind = lldb::eMemberFunctionKindStaticMethod; + else if (llvm::isa<clang::CXXConstructorDecl>(cxx_method_decl)) + kind = lldb::eMemberFunctionKindConstructor; + else if (llvm::isa<clang::CXXDestructorDecl>(cxx_method_decl)) + kind = lldb::eMemberFunctionKindDestructor; + else + kind = lldb::eMemberFunctionKindInstanceMethod; + clang_type = CompilerType( + this, cxx_method_decl->getType().getAsOpaquePtr()); + clang_decl = CompilerDecl(this, cxx_method_decl); + } + } } + } + break; + + case clang::Type::ObjCObjectPointer: + if (GetCompleteType(type)) { + const clang::ObjCObjectPointerType *objc_class_type = + qual_type->getAsObjCInterfacePointerType(); + if (objc_class_type) { + clang::ObjCInterfaceDecl *class_interface_decl = + objc_class_type->getInterfaceDecl(); + if (class_interface_decl) { + auto method_iter = class_interface_decl->meth_begin(); + auto method_end = class_interface_decl->meth_end(); + if (idx < + static_cast<size_t>(std::distance(method_iter, method_end))) { + std::advance(method_iter, idx); + clang::ObjCMethodDecl *objc_method_decl = + method_iter->getCanonicalDecl(); + if (objc_method_decl) { + clang_decl = CompilerDecl(this, objc_method_decl); + name = objc_method_decl->getSelector().getAsString(); + if (objc_method_decl->isClassMethod()) + kind = lldb::eMemberFunctionKindStaticMethod; + else + kind = lldb::eMemberFunctionKindInstanceMethod; + } + } + } + } + } + break; + + case clang::Type::ObjCObject: + case clang::Type::ObjCInterface: + if (GetCompleteType(type)) { + const clang::ObjCObjectType *objc_class_type = + llvm::dyn_cast<clang::ObjCObjectType>(qual_type.getTypePtr()); + if (objc_class_type) { + clang::ObjCInterfaceDecl *class_interface_decl = + objc_class_type->getInterface(); + if (class_interface_decl) { + auto method_iter = class_interface_decl->meth_begin(); + auto method_end = class_interface_decl->meth_end(); + if (idx < + static_cast<size_t>(std::distance(method_iter, method_end))) { + std::advance(method_iter, idx); + clang::ObjCMethodDecl *objc_method_decl = + method_iter->getCanonicalDecl(); + if (objc_method_decl) { + clang_decl = CompilerDecl(this, objc_method_decl); + name = objc_method_decl->getSelector().getAsString(); + if (objc_method_decl->isClassMethod()) + kind = lldb::eMemberFunctionKindStaticMethod; + else + kind = lldb::eMemberFunctionKindInstanceMethod; + } + } + } + } + } + break; + + case clang::Type::Typedef: + return GetMemberFunctionAtIndex(llvm::cast<clang::TypedefType>(qual_type) + ->getDecl() + ->getUnderlyingType() + .getAsOpaquePtr(), + idx); + + case clang::Type::Auto: + return GetMemberFunctionAtIndex(llvm::cast<clang::AutoType>(qual_type) + ->getDeducedType() + .getAsOpaquePtr(), + idx); + + case clang::Type::Elaborated: + return GetMemberFunctionAtIndex( + llvm::cast<clang::ElaboratedType>(qual_type) + ->getNamedType() + .getAsOpaquePtr(), + idx); + + case clang::Type::Paren: + return GetMemberFunctionAtIndex( + llvm::cast<clang::ParenType>(qual_type)->desugar().getAsOpaquePtr(), + idx); + + default: + break; } - - if (kind == eMemberFunctionKindUnknown) - return TypeMemberFunctionImpl(); - else - return TypeMemberFunctionImpl(clang_type, clang_decl, name, kind); + } + + if (kind == eMemberFunctionKindUnknown) + return TypeMemberFunctionImpl(); + else + return TypeMemberFunctionImpl(clang_type, clang_decl, name, kind); } CompilerType -ClangASTContext::GetNonReferenceType (lldb::opaque_compiler_type_t type) -{ - if (type) - return CompilerType(getASTContext(), GetQualType(type).getNonReferenceType()); - return CompilerType(); +ClangASTContext::GetNonReferenceType(lldb::opaque_compiler_type_t type) { + if (type) + return CompilerType(getASTContext(), + GetQualType(type).getNonReferenceType()); + return CompilerType(); +} + +CompilerType ClangASTContext::CreateTypedefType( + const CompilerType &type, const char *typedef_name, + const CompilerDeclContext &compiler_decl_ctx) { + if (type && typedef_name && typedef_name[0]) { + ClangASTContext *ast = + llvm::dyn_cast<ClangASTContext>(type.GetTypeSystem()); + if (!ast) + return CompilerType(); + clang::ASTContext *clang_ast = ast->getASTContext(); + clang::QualType qual_type(ClangUtil::GetQualType(type)); + + clang::DeclContext *decl_ctx = + ClangASTContext::DeclContextGetAsDeclContext(compiler_decl_ctx); + if (decl_ctx == nullptr) + decl_ctx = ast->getASTContext()->getTranslationUnitDecl(); + + clang::TypedefDecl *decl = clang::TypedefDecl::Create( + *clang_ast, decl_ctx, clang::SourceLocation(), clang::SourceLocation(), + &clang_ast->Idents.get(typedef_name), + clang_ast->getTrivialTypeSourceInfo(qual_type)); + + decl->setAccess(clang::AS_public); // TODO respect proper access specifier + + // Get a uniqued clang::QualType for the typedef decl type + return CompilerType(clang_ast, clang_ast->getTypedefType(decl)); + } + return CompilerType(); } CompilerType -ClangASTContext::CreateTypedefType (const CompilerType& type, - const char *typedef_name, - const CompilerDeclContext &compiler_decl_ctx) -{ - if (type && typedef_name && typedef_name[0]) - { - ClangASTContext *ast = llvm::dyn_cast<ClangASTContext>(type.GetTypeSystem()); - if (!ast) - return CompilerType(); - clang::ASTContext* clang_ast = ast->getASTContext(); - clang::QualType qual_type(ClangUtil::GetQualType(type)); - - clang::DeclContext *decl_ctx = ClangASTContext::DeclContextGetAsDeclContext(compiler_decl_ctx); - if (decl_ctx == nullptr) - decl_ctx = ast->getASTContext()->getTranslationUnitDecl(); - - clang::TypedefDecl *decl = clang::TypedefDecl::Create (*clang_ast, - decl_ctx, - clang::SourceLocation(), - clang::SourceLocation(), - &clang_ast->Idents.get(typedef_name), - clang_ast->getTrivialTypeSourceInfo(qual_type)); - - decl->setAccess(clang::AS_public); // TODO respect proper access specifier - - // Get a uniqued clang::QualType for the typedef decl type - return CompilerType (clang_ast, clang_ast->getTypedefType (decl)); - } - return CompilerType(); - +ClangASTContext::GetPointeeType(lldb::opaque_compiler_type_t type) { + if (type) { + clang::QualType qual_type(GetQualType(type)); + return CompilerType(getASTContext(), + qual_type.getTypePtr()->getPointeeType()); + } + return CompilerType(); } CompilerType -ClangASTContext::GetPointeeType (lldb::opaque_compiler_type_t type) -{ - if (type) - { - clang::QualType qual_type(GetQualType(type)); - return CompilerType (getASTContext(), qual_type.getTypePtr()->getPointeeType()); +ClangASTContext::GetPointerType(lldb::opaque_compiler_type_t type) { + if (type) { + clang::QualType qual_type(GetQualType(type)); + + const clang::Type::TypeClass type_class = qual_type->getTypeClass(); + switch (type_class) { + case clang::Type::ObjCObject: + case clang::Type::ObjCInterface: + return CompilerType(getASTContext(), + getASTContext()->getObjCObjectPointerType(qual_type)); + + default: + return CompilerType(getASTContext(), + getASTContext()->getPointerType(qual_type)); } - return CompilerType(); + } + return CompilerType(); } CompilerType -ClangASTContext::GetPointerType (lldb::opaque_compiler_type_t type) -{ - if (type) - { - clang::QualType qual_type (GetQualType(type)); - - const clang::Type::TypeClass type_class = qual_type->getTypeClass(); - switch (type_class) - { - case clang::Type::ObjCObject: - case clang::Type::ObjCInterface: - return CompilerType(getASTContext(), getASTContext()->getObjCObjectPointerType(qual_type)); - - default: - return CompilerType(getASTContext(), getASTContext()->getPointerType(qual_type)); - } - } +ClangASTContext::GetLValueReferenceType(lldb::opaque_compiler_type_t type) { + if (type) + return CompilerType(this, getASTContext() + ->getLValueReferenceType(GetQualType(type)) + .getAsOpaquePtr()); + else return CompilerType(); } - CompilerType -ClangASTContext::GetLValueReferenceType (lldb::opaque_compiler_type_t type) -{ - if (type) - return CompilerType(this, getASTContext()->getLValueReferenceType(GetQualType(type)).getAsOpaquePtr()); - else - return CompilerType(); +ClangASTContext::GetRValueReferenceType(lldb::opaque_compiler_type_t type) { + if (type) + return CompilerType(this, getASTContext() + ->getRValueReferenceType(GetQualType(type)) + .getAsOpaquePtr()); + else + return CompilerType(); } CompilerType -ClangASTContext::GetRValueReferenceType (lldb::opaque_compiler_type_t type) -{ - if (type) - return CompilerType(this, getASTContext()->getRValueReferenceType(GetQualType(type)).getAsOpaquePtr()); - else - return CompilerType(); +ClangASTContext::AddConstModifier(lldb::opaque_compiler_type_t type) { + if (type) { + clang::QualType result(GetQualType(type)); + result.addConst(); + return CompilerType(this, result.getAsOpaquePtr()); + } + return CompilerType(); } CompilerType -ClangASTContext::AddConstModifier (lldb::opaque_compiler_type_t type) -{ - if (type) - { - clang::QualType result(GetQualType(type)); - result.addConst(); - return CompilerType (this, result.getAsOpaquePtr()); - } - return CompilerType(); +ClangASTContext::AddVolatileModifier(lldb::opaque_compiler_type_t type) { + if (type) { + clang::QualType result(GetQualType(type)); + result.addVolatile(); + return CompilerType(this, result.getAsOpaquePtr()); + } + return CompilerType(); } CompilerType -ClangASTContext::AddVolatileModifier (lldb::opaque_compiler_type_t type) -{ - if (type) - { - clang::QualType result(GetQualType(type)); - result.addVolatile(); - return CompilerType (this, result.getAsOpaquePtr()); - } - return CompilerType(); - +ClangASTContext::AddRestrictModifier(lldb::opaque_compiler_type_t type) { + if (type) { + clang::QualType result(GetQualType(type)); + result.addRestrict(); + return CompilerType(this, result.getAsOpaquePtr()); + } + return CompilerType(); } CompilerType -ClangASTContext::AddRestrictModifier (lldb::opaque_compiler_type_t type) -{ - if (type) - { - clang::QualType result(GetQualType(type)); - result.addRestrict(); - return CompilerType (this, result.getAsOpaquePtr()); - } - return CompilerType(); - -} +ClangASTContext::CreateTypedef(lldb::opaque_compiler_type_t type, + const char *typedef_name, + const CompilerDeclContext &compiler_decl_ctx) { + if (type) { + clang::ASTContext *clang_ast = getASTContext(); + clang::QualType qual_type(GetQualType(type)); -CompilerType -ClangASTContext::CreateTypedef (lldb::opaque_compiler_type_t type, const char *typedef_name, const CompilerDeclContext &compiler_decl_ctx) -{ - if (type) - { - clang::ASTContext* clang_ast = getASTContext(); - clang::QualType qual_type (GetQualType(type)); - - clang::DeclContext *decl_ctx = ClangASTContext::DeclContextGetAsDeclContext(compiler_decl_ctx); - if (decl_ctx == nullptr) - decl_ctx = getASTContext()->getTranslationUnitDecl(); - - clang::TypedefDecl *decl = clang::TypedefDecl::Create (*clang_ast, - decl_ctx, - clang::SourceLocation(), - clang::SourceLocation(), - &clang_ast->Idents.get(typedef_name), - clang_ast->getTrivialTypeSourceInfo(qual_type)); - - clang::TagDecl *tdecl = nullptr; - if (!qual_type.isNull()) - { - if (const clang::RecordType *rt = qual_type->getAs<clang::RecordType>()) - tdecl = rt->getDecl(); - if (const clang::EnumType *et = qual_type->getAs<clang::EnumType>()) - tdecl = et->getDecl(); - } + clang::DeclContext *decl_ctx = + ClangASTContext::DeclContextGetAsDeclContext(compiler_decl_ctx); + if (decl_ctx == nullptr) + decl_ctx = getASTContext()->getTranslationUnitDecl(); - // Check whether this declaration is an anonymous struct, union, or enum, hidden behind a typedef. If so, we - // try to check whether we have a typedef tag to attach to the original record declaration - if (tdecl && !tdecl->getIdentifier() && !tdecl->getTypedefNameForAnonDecl()) - tdecl->setTypedefNameForAnonDecl(decl); + clang::TypedefDecl *decl = clang::TypedefDecl::Create( + *clang_ast, decl_ctx, clang::SourceLocation(), clang::SourceLocation(), + &clang_ast->Idents.get(typedef_name), + clang_ast->getTrivialTypeSourceInfo(qual_type)); - decl->setAccess(clang::AS_public); // TODO respect proper access specifier + clang::TagDecl *tdecl = nullptr; + if (!qual_type.isNull()) { + if (const clang::RecordType *rt = qual_type->getAs<clang::RecordType>()) + tdecl = rt->getDecl(); + if (const clang::EnumType *et = qual_type->getAs<clang::EnumType>()) + tdecl = et->getDecl(); + } - // Get a uniqued clang::QualType for the typedef decl type - return CompilerType (this, clang_ast->getTypedefType (decl).getAsOpaquePtr()); + // Check whether this declaration is an anonymous struct, union, or enum, + // hidden behind a typedef. If so, we + // try to check whether we have a typedef tag to attach to the original + // record declaration + if (tdecl && !tdecl->getIdentifier() && !tdecl->getTypedefNameForAnonDecl()) + tdecl->setTypedefNameForAnonDecl(decl); - } - return CompilerType(); + decl->setAccess(clang::AS_public); // TODO respect proper access specifier + // Get a uniqued clang::QualType for the typedef decl type + return CompilerType(this, clang_ast->getTypedefType(decl).getAsOpaquePtr()); + } + return CompilerType(); } CompilerType -ClangASTContext::GetTypedefedType (lldb::opaque_compiler_type_t type) -{ - if (type) - { - const clang::TypedefType *typedef_type = llvm::dyn_cast<clang::TypedefType>(GetQualType(type)); - if (typedef_type) - return CompilerType (getASTContext(), typedef_type->getDecl()->getUnderlyingType()); - } - return CompilerType(); +ClangASTContext::GetTypedefedType(lldb::opaque_compiler_type_t type) { + if (type) { + const clang::TypedefType *typedef_type = + llvm::dyn_cast<clang::TypedefType>(GetQualType(type)); + if (typedef_type) + return CompilerType(getASTContext(), + typedef_type->getDecl()->getUnderlyingType()); + } + return CompilerType(); } - //---------------------------------------------------------------------- // Create related types using the current type's AST //---------------------------------------------------------------------- -CompilerType -ClangASTContext::GetBasicTypeFromAST (lldb::BasicType basic_type) -{ - return ClangASTContext::GetBasicType(getASTContext(), basic_type); +CompilerType ClangASTContext::GetBasicTypeFromAST(lldb::BasicType basic_type) { + return ClangASTContext::GetBasicType(getASTContext(), basic_type); } //---------------------------------------------------------------------- // Exploring the type //---------------------------------------------------------------------- -uint64_t -ClangASTContext::GetBitSize (lldb::opaque_compiler_type_t type, ExecutionContextScope *exe_scope) -{ - if (GetCompleteType (type)) - { - clang::QualType qual_type(GetCanonicalQualType(type)); - const clang::Type::TypeClass type_class = qual_type->getTypeClass(); - switch (type_class) - { - case clang::Type::Record: - if (GetCompleteType(type)) - return getASTContext()->getTypeSize(qual_type); - else - return 0; - break; - - case clang::Type::ObjCInterface: - case clang::Type::ObjCObject: - { - ExecutionContext exe_ctx (exe_scope); - Process *process = exe_ctx.GetProcessPtr(); - if (process) - { - ObjCLanguageRuntime *objc_runtime = process->GetObjCLanguageRuntime(); - if (objc_runtime) - { - uint64_t bit_size = 0; - if (objc_runtime->GetTypeBitSize(CompilerType(getASTContext(), qual_type), bit_size)) - return bit_size; - } - } - else - { - static bool g_printed = false; - if (!g_printed) - { - StreamString s; - DumpTypeDescription(type, &s); - - llvm::outs() << "warning: trying to determine the size of type "; - llvm::outs() << s.GetString() << "\n"; - llvm::outs() << "without a valid ExecutionContext. this is not reliable. please file a bug against LLDB.\n"; - llvm::outs() << "backtrace:\n"; - llvm::sys::PrintStackTrace(llvm::outs()); - llvm::outs() << "\n"; - g_printed = true; - } - } - } - LLVM_FALLTHROUGH; - default: - const uint32_t bit_size = getASTContext()->getTypeSize (qual_type); - if (bit_size == 0) - { - if (qual_type->isIncompleteArrayType()) - return getASTContext()->getTypeSize (qual_type->getArrayElementTypeNoTypeQual()->getCanonicalTypeUnqualified()); - } - if (qual_type->isObjCObjectOrInterfaceType()) - return bit_size + getASTContext()->getTypeSize(getASTContext()->ObjCBuiltinClassTy); - return bit_size; +uint64_t ClangASTContext::GetBitSize(lldb::opaque_compiler_type_t type, + ExecutionContextScope *exe_scope) { + if (GetCompleteType(type)) { + clang::QualType qual_type(GetCanonicalQualType(type)); + const clang::Type::TypeClass type_class = qual_type->getTypeClass(); + switch (type_class) { + case clang::Type::Record: + if (GetCompleteType(type)) + return getASTContext()->getTypeSize(qual_type); + else + return 0; + break; + + case clang::Type::ObjCInterface: + case clang::Type::ObjCObject: { + ExecutionContext exe_ctx(exe_scope); + Process *process = exe_ctx.GetProcessPtr(); + if (process) { + ObjCLanguageRuntime *objc_runtime = process->GetObjCLanguageRuntime(); + if (objc_runtime) { + uint64_t bit_size = 0; + if (objc_runtime->GetTypeBitSize( + CompilerType(getASTContext(), qual_type), bit_size)) + return bit_size; + } + } else { + static bool g_printed = false; + if (!g_printed) { + StreamString s; + DumpTypeDescription(type, &s); + + llvm::outs() << "warning: trying to determine the size of type "; + llvm::outs() << s.GetString() << "\n"; + llvm::outs() << "without a valid ExecutionContext. this is not " + "reliable. please file a bug against LLDB.\n"; + llvm::outs() << "backtrace:\n"; + llvm::sys::PrintStackTrace(llvm::outs()); + llvm::outs() << "\n"; + g_printed = true; } + } } - return 0; -} + LLVM_FALLTHROUGH; + default: + const uint32_t bit_size = getASTContext()->getTypeSize(qual_type); + if (bit_size == 0) { + if (qual_type->isIncompleteArrayType()) + return getASTContext()->getTypeSize( + qual_type->getArrayElementTypeNoTypeQual() + ->getCanonicalTypeUnqualified()); + } + if (qual_type->isObjCObjectOrInterfaceType()) + return bit_size + + getASTContext()->getTypeSize( + getASTContext()->ObjCBuiltinClassTy); + return bit_size; + } + } + return 0; +} + +size_t ClangASTContext::GetTypeBitAlign(lldb::opaque_compiler_type_t type) { + if (GetCompleteType(type)) + return getASTContext()->getTypeAlign(GetQualType(type)); + return 0; +} + +lldb::Encoding ClangASTContext::GetEncoding(lldb::opaque_compiler_type_t type, + uint64_t &count) { + if (!type) + return lldb::eEncodingInvalid; -size_t -ClangASTContext::GetTypeBitAlign (lldb::opaque_compiler_type_t type) -{ - if (GetCompleteType(type)) - return getASTContext()->getTypeAlign(GetQualType(type)); - return 0; + count = 1; + clang::QualType qual_type(GetCanonicalQualType(type)); + + switch (qual_type->getTypeClass()) { + case clang::Type::UnaryTransform: + break; + + case clang::Type::FunctionNoProto: + case clang::Type::FunctionProto: + break; + + case clang::Type::IncompleteArray: + case clang::Type::VariableArray: + break; + + case clang::Type::ConstantArray: + break; + + case clang::Type::ExtVector: + case clang::Type::Vector: + // TODO: Set this to more than one??? + break; + + case clang::Type::Builtin: + switch (llvm::cast<clang::BuiltinType>(qual_type)->getKind()) { + case clang::BuiltinType::Void: + break; + + case clang::BuiltinType::Bool: + case clang::BuiltinType::Char_S: + case clang::BuiltinType::SChar: + case clang::BuiltinType::WChar_S: + case clang::BuiltinType::Char16: + case clang::BuiltinType::Char32: + case clang::BuiltinType::Short: + case clang::BuiltinType::Int: + case clang::BuiltinType::Long: + case clang::BuiltinType::LongLong: + case clang::BuiltinType::Int128: + return lldb::eEncodingSint; + + case clang::BuiltinType::Char_U: + case clang::BuiltinType::UChar: + case clang::BuiltinType::WChar_U: + case clang::BuiltinType::UShort: + case clang::BuiltinType::UInt: + case clang::BuiltinType::ULong: + case clang::BuiltinType::ULongLong: + case clang::BuiltinType::UInt128: + return lldb::eEncodingUint; + + case clang::BuiltinType::Half: + case clang::BuiltinType::Float: + case clang::BuiltinType::Float128: + case clang::BuiltinType::Double: + case clang::BuiltinType::LongDouble: + return lldb::eEncodingIEEE754; + + case clang::BuiltinType::ObjCClass: + case clang::BuiltinType::ObjCId: + case clang::BuiltinType::ObjCSel: + return lldb::eEncodingUint; + + case clang::BuiltinType::NullPtr: + return lldb::eEncodingUint; + + case clang::BuiltinType::Kind::ARCUnbridgedCast: + case clang::BuiltinType::Kind::BoundMember: + case clang::BuiltinType::Kind::BuiltinFn: + case clang::BuiltinType::Kind::Dependent: + case clang::BuiltinType::Kind::OCLClkEvent: + case clang::BuiltinType::Kind::OCLEvent: + case clang::BuiltinType::Kind::OCLImage1dRO: + case clang::BuiltinType::Kind::OCLImage1dWO: + case clang::BuiltinType::Kind::OCLImage1dRW: + case clang::BuiltinType::Kind::OCLImage1dArrayRO: + case clang::BuiltinType::Kind::OCLImage1dArrayWO: + case clang::BuiltinType::Kind::OCLImage1dArrayRW: + case clang::BuiltinType::Kind::OCLImage1dBufferRO: + case clang::BuiltinType::Kind::OCLImage1dBufferWO: + case clang::BuiltinType::Kind::OCLImage1dBufferRW: + case clang::BuiltinType::Kind::OCLImage2dRO: + case clang::BuiltinType::Kind::OCLImage2dWO: + case clang::BuiltinType::Kind::OCLImage2dRW: + case clang::BuiltinType::Kind::OCLImage2dArrayRO: + case clang::BuiltinType::Kind::OCLImage2dArrayWO: + case clang::BuiltinType::Kind::OCLImage2dArrayRW: + case clang::BuiltinType::Kind::OCLImage2dArrayDepthRO: + case clang::BuiltinType::Kind::OCLImage2dArrayDepthWO: + case clang::BuiltinType::Kind::OCLImage2dArrayDepthRW: + case clang::BuiltinType::Kind::OCLImage2dArrayMSAARO: + case clang::BuiltinType::Kind::OCLImage2dArrayMSAAWO: + case clang::BuiltinType::Kind::OCLImage2dArrayMSAARW: + case clang::BuiltinType::Kind::OCLImage2dArrayMSAADepthRO: + case clang::BuiltinType::Kind::OCLImage2dArrayMSAADepthWO: + case clang::BuiltinType::Kind::OCLImage2dArrayMSAADepthRW: + case clang::BuiltinType::Kind::OCLImage2dDepthRO: + case clang::BuiltinType::Kind::OCLImage2dDepthWO: + case clang::BuiltinType::Kind::OCLImage2dDepthRW: + case clang::BuiltinType::Kind::OCLImage2dMSAARO: + case clang::BuiltinType::Kind::OCLImage2dMSAAWO: + case clang::BuiltinType::Kind::OCLImage2dMSAARW: + case clang::BuiltinType::Kind::OCLImage2dMSAADepthRO: + case clang::BuiltinType::Kind::OCLImage2dMSAADepthWO: + case clang::BuiltinType::Kind::OCLImage2dMSAADepthRW: + case clang::BuiltinType::Kind::OCLImage3dRO: + case clang::BuiltinType::Kind::OCLImage3dWO: + case clang::BuiltinType::Kind::OCLImage3dRW: + case clang::BuiltinType::Kind::OCLQueue: + case clang::BuiltinType::Kind::OCLNDRange: + case clang::BuiltinType::Kind::OCLReserveID: + case clang::BuiltinType::Kind::OCLSampler: + case clang::BuiltinType::Kind::OMPArraySection: + case clang::BuiltinType::Kind::Overload: + case clang::BuiltinType::Kind::PseudoObject: + case clang::BuiltinType::Kind::UnknownAny: + break; + } + break; + // All pointer types are represented as unsigned integer encodings. + // We may nee to add a eEncodingPointer if we ever need to know the + // difference + case clang::Type::ObjCObjectPointer: + case clang::Type::BlockPointer: + case clang::Type::Pointer: + case clang::Type::LValueReference: + case clang::Type::RValueReference: + case clang::Type::MemberPointer: + return lldb::eEncodingUint; + case clang::Type::Complex: { + lldb::Encoding encoding = lldb::eEncodingIEEE754; + if (qual_type->isComplexType()) + encoding = lldb::eEncodingIEEE754; + else { + const clang::ComplexType *complex_type = + qual_type->getAsComplexIntegerType(); + if (complex_type) + encoding = CompilerType(getASTContext(), complex_type->getElementType()) + .GetEncoding(count); + else + encoding = lldb::eEncodingSint; + } + count = 2; + return encoding; + } + + case clang::Type::ObjCInterface: + break; + case clang::Type::Record: + break; + case clang::Type::Enum: + return lldb::eEncodingSint; + case clang::Type::Typedef: + return CompilerType(getASTContext(), + llvm::cast<clang::TypedefType>(qual_type) + ->getDecl() + ->getUnderlyingType()) + .GetEncoding(count); + + case clang::Type::Auto: + return CompilerType( + getASTContext(), + llvm::cast<clang::AutoType>(qual_type)->getDeducedType()) + .GetEncoding(count); + + case clang::Type::Elaborated: + return CompilerType( + getASTContext(), + llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType()) + .GetEncoding(count); + + case clang::Type::Paren: + return CompilerType(getASTContext(), + llvm::cast<clang::ParenType>(qual_type)->desugar()) + .GetEncoding(count); + + case clang::Type::DependentSizedArray: + case clang::Type::DependentSizedExtVector: + case clang::Type::UnresolvedUsing: + case clang::Type::Attributed: + case clang::Type::TemplateTypeParm: + case clang::Type::SubstTemplateTypeParm: + case clang::Type::SubstTemplateTypeParmPack: + case clang::Type::InjectedClassName: + case clang::Type::DependentName: + case clang::Type::DependentTemplateSpecialization: + case clang::Type::PackExpansion: + case clang::Type::ObjCObject: + + case clang::Type::TypeOfExpr: + case clang::Type::TypeOf: + case clang::Type::Decltype: + case clang::Type::TemplateSpecialization: + case clang::Type::Atomic: + case clang::Type::Adjusted: + case clang::Type::Pipe: + break; + + // pointer type decayed from an array or function type. + case clang::Type::Decayed: + break; + } + count = 0; + return lldb::eEncodingInvalid; +} + +lldb::Format ClangASTContext::GetFormat(lldb::opaque_compiler_type_t type) { + if (!type) + return lldb::eFormatDefault; + + clang::QualType qual_type(GetCanonicalQualType(type)); + + switch (qual_type->getTypeClass()) { + case clang::Type::UnaryTransform: + break; + + case clang::Type::FunctionNoProto: + case clang::Type::FunctionProto: + break; + + case clang::Type::IncompleteArray: + case clang::Type::VariableArray: + break; + + case clang::Type::ConstantArray: + return lldb::eFormatVoid; // no value + + case clang::Type::ExtVector: + case clang::Type::Vector: + break; + + case clang::Type::Builtin: + switch (llvm::cast<clang::BuiltinType>(qual_type)->getKind()) { + // default: assert(0 && "Unknown builtin type!"); + case clang::BuiltinType::UnknownAny: + case clang::BuiltinType::Void: + case clang::BuiltinType::BoundMember: + break; + + case clang::BuiltinType::Bool: + return lldb::eFormatBoolean; + case clang::BuiltinType::Char_S: + case clang::BuiltinType::SChar: + case clang::BuiltinType::WChar_S: + case clang::BuiltinType::Char_U: + case clang::BuiltinType::UChar: + case clang::BuiltinType::WChar_U: + return lldb::eFormatChar; + case clang::BuiltinType::Char16: + return lldb::eFormatUnicode16; + case clang::BuiltinType::Char32: + return lldb::eFormatUnicode32; + case clang::BuiltinType::UShort: + return lldb::eFormatUnsigned; + case clang::BuiltinType::Short: + return lldb::eFormatDecimal; + case clang::BuiltinType::UInt: + return lldb::eFormatUnsigned; + case clang::BuiltinType::Int: + return lldb::eFormatDecimal; + case clang::BuiltinType::ULong: + return lldb::eFormatUnsigned; + case clang::BuiltinType::Long: + return lldb::eFormatDecimal; + case clang::BuiltinType::ULongLong: + return lldb::eFormatUnsigned; + case clang::BuiltinType::LongLong: + return lldb::eFormatDecimal; + case clang::BuiltinType::UInt128: + return lldb::eFormatUnsigned; + case clang::BuiltinType::Int128: + return lldb::eFormatDecimal; + case clang::BuiltinType::Half: + case clang::BuiltinType::Float: + case clang::BuiltinType::Double: + case clang::BuiltinType::LongDouble: + return lldb::eFormatFloat; + default: + return lldb::eFormatHex; + } + break; + case clang::Type::ObjCObjectPointer: + return lldb::eFormatHex; + case clang::Type::BlockPointer: + return lldb::eFormatHex; + case clang::Type::Pointer: + return lldb::eFormatHex; + case clang::Type::LValueReference: + case clang::Type::RValueReference: + return lldb::eFormatHex; + case clang::Type::MemberPointer: + break; + case clang::Type::Complex: { + if (qual_type->isComplexType()) + return lldb::eFormatComplex; + else + return lldb::eFormatComplexInteger; + } + case clang::Type::ObjCInterface: + break; + case clang::Type::Record: + break; + case clang::Type::Enum: + return lldb::eFormatEnum; + case clang::Type::Typedef: + return CompilerType(getASTContext(), + llvm::cast<clang::TypedefType>(qual_type) + ->getDecl() + ->getUnderlyingType()) + .GetFormat(); + case clang::Type::Auto: + return CompilerType(getASTContext(), + llvm::cast<clang::AutoType>(qual_type)->desugar()) + .GetFormat(); + case clang::Type::Paren: + return CompilerType(getASTContext(), + llvm::cast<clang::ParenType>(qual_type)->desugar()) + .GetFormat(); + case clang::Type::Elaborated: + return CompilerType( + getASTContext(), + llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType()) + .GetFormat(); + case clang::Type::DependentSizedArray: + case clang::Type::DependentSizedExtVector: + case clang::Type::UnresolvedUsing: + case clang::Type::Attributed: + case clang::Type::TemplateTypeParm: + case clang::Type::SubstTemplateTypeParm: + case clang::Type::SubstTemplateTypeParmPack: + case clang::Type::InjectedClassName: + case clang::Type::DependentName: + case clang::Type::DependentTemplateSpecialization: + case clang::Type::PackExpansion: + case clang::Type::ObjCObject: + + case clang::Type::TypeOfExpr: + case clang::Type::TypeOf: + case clang::Type::Decltype: + case clang::Type::TemplateSpecialization: + case clang::Type::Atomic: + case clang::Type::Adjusted: + case clang::Type::Pipe: + break; + + // pointer type decayed from an array or function type. + case clang::Type::Decayed: + break; + } + // We don't know hot to display this type... + return lldb::eFormatBytes; +} + +static bool ObjCDeclHasIVars(clang::ObjCInterfaceDecl *class_interface_decl, + bool check_superclass) { + while (class_interface_decl) { + if (class_interface_decl->ivar_size() > 0) + return true; + + if (check_superclass) + class_interface_decl = class_interface_decl->getSuperClass(); + else + break; + } + return false; } +uint32_t ClangASTContext::GetNumChildren(lldb::opaque_compiler_type_t type, + bool omit_empty_base_classes) { + if (!type) + return 0; -lldb::Encoding -ClangASTContext::GetEncoding (lldb::opaque_compiler_type_t type, uint64_t &count) -{ - if (!type) - return lldb::eEncodingInvalid; - - count = 1; - clang::QualType qual_type(GetCanonicalQualType(type)); - - switch (qual_type->getTypeClass()) - { - case clang::Type::UnaryTransform: - break; - - case clang::Type::FunctionNoProto: - case clang::Type::FunctionProto: - break; - - case clang::Type::IncompleteArray: - case clang::Type::VariableArray: - break; - - case clang::Type::ConstantArray: - break; - - case clang::Type::ExtVector: - case clang::Type::Vector: - // TODO: Set this to more than one??? - break; - - case clang::Type::Builtin: - switch (llvm::cast<clang::BuiltinType>(qual_type)->getKind()) - { - case clang::BuiltinType::Void: - break; - - case clang::BuiltinType::Bool: - case clang::BuiltinType::Char_S: - case clang::BuiltinType::SChar: - case clang::BuiltinType::WChar_S: - case clang::BuiltinType::Char16: - case clang::BuiltinType::Char32: - case clang::BuiltinType::Short: - case clang::BuiltinType::Int: - case clang::BuiltinType::Long: - case clang::BuiltinType::LongLong: - case clang::BuiltinType::Int128: - return lldb::eEncodingSint; - - case clang::BuiltinType::Char_U: - case clang::BuiltinType::UChar: - case clang::BuiltinType::WChar_U: - case clang::BuiltinType::UShort: - case clang::BuiltinType::UInt: - case clang::BuiltinType::ULong: - case clang::BuiltinType::ULongLong: - case clang::BuiltinType::UInt128: - return lldb::eEncodingUint; - - case clang::BuiltinType::Half: - case clang::BuiltinType::Float: - case clang::BuiltinType::Float128: - case clang::BuiltinType::Double: - case clang::BuiltinType::LongDouble: - return lldb::eEncodingIEEE754; - - case clang::BuiltinType::ObjCClass: - case clang::BuiltinType::ObjCId: - case clang::BuiltinType::ObjCSel: - return lldb::eEncodingUint; - - case clang::BuiltinType::NullPtr: - return lldb::eEncodingUint; - - case clang::BuiltinType::Kind::ARCUnbridgedCast: - case clang::BuiltinType::Kind::BoundMember: - case clang::BuiltinType::Kind::BuiltinFn: - case clang::BuiltinType::Kind::Dependent: - case clang::BuiltinType::Kind::OCLClkEvent: - case clang::BuiltinType::Kind::OCLEvent: - case clang::BuiltinType::Kind::OCLImage1dRO: - case clang::BuiltinType::Kind::OCLImage1dWO: - case clang::BuiltinType::Kind::OCLImage1dRW: - case clang::BuiltinType::Kind::OCLImage1dArrayRO: - case clang::BuiltinType::Kind::OCLImage1dArrayWO: - case clang::BuiltinType::Kind::OCLImage1dArrayRW: - case clang::BuiltinType::Kind::OCLImage1dBufferRO: - case clang::BuiltinType::Kind::OCLImage1dBufferWO: - case clang::BuiltinType::Kind::OCLImage1dBufferRW: - case clang::BuiltinType::Kind::OCLImage2dRO: - case clang::BuiltinType::Kind::OCLImage2dWO: - case clang::BuiltinType::Kind::OCLImage2dRW: - case clang::BuiltinType::Kind::OCLImage2dArrayRO: - case clang::BuiltinType::Kind::OCLImage2dArrayWO: - case clang::BuiltinType::Kind::OCLImage2dArrayRW: - case clang::BuiltinType::Kind::OCLImage2dArrayDepthRO: - case clang::BuiltinType::Kind::OCLImage2dArrayDepthWO: - case clang::BuiltinType::Kind::OCLImage2dArrayDepthRW: - case clang::BuiltinType::Kind::OCLImage2dArrayMSAARO: - case clang::BuiltinType::Kind::OCLImage2dArrayMSAAWO: - case clang::BuiltinType::Kind::OCLImage2dArrayMSAARW: - case clang::BuiltinType::Kind::OCLImage2dArrayMSAADepthRO: - case clang::BuiltinType::Kind::OCLImage2dArrayMSAADepthWO: - case clang::BuiltinType::Kind::OCLImage2dArrayMSAADepthRW: - case clang::BuiltinType::Kind::OCLImage2dDepthRO: - case clang::BuiltinType::Kind::OCLImage2dDepthWO: - case clang::BuiltinType::Kind::OCLImage2dDepthRW: - case clang::BuiltinType::Kind::OCLImage2dMSAARO: - case clang::BuiltinType::Kind::OCLImage2dMSAAWO: - case clang::BuiltinType::Kind::OCLImage2dMSAARW: - case clang::BuiltinType::Kind::OCLImage2dMSAADepthRO: - case clang::BuiltinType::Kind::OCLImage2dMSAADepthWO: - case clang::BuiltinType::Kind::OCLImage2dMSAADepthRW: - case clang::BuiltinType::Kind::OCLImage3dRO: - case clang::BuiltinType::Kind::OCLImage3dWO: - case clang::BuiltinType::Kind::OCLImage3dRW: - case clang::BuiltinType::Kind::OCLQueue: - case clang::BuiltinType::Kind::OCLNDRange: - case clang::BuiltinType::Kind::OCLReserveID: - case clang::BuiltinType::Kind::OCLSampler: - case clang::BuiltinType::Kind::OMPArraySection: - case clang::BuiltinType::Kind::Overload: - case clang::BuiltinType::Kind::PseudoObject: - case clang::BuiltinType::Kind::UnknownAny: - break; - } - break; - // All pointer types are represented as unsigned integer encodings. - // We may nee to add a eEncodingPointer if we ever need to know the - // difference - case clang::Type::ObjCObjectPointer: - case clang::Type::BlockPointer: - case clang::Type::Pointer: - case clang::Type::LValueReference: - case clang::Type::RValueReference: - case clang::Type::MemberPointer: return lldb::eEncodingUint; - case clang::Type::Complex: - { - lldb::Encoding encoding = lldb::eEncodingIEEE754; - if (qual_type->isComplexType()) - encoding = lldb::eEncodingIEEE754; - else - { - const clang::ComplexType *complex_type = qual_type->getAsComplexIntegerType(); - if (complex_type) - encoding = CompilerType(getASTContext(), complex_type->getElementType()).GetEncoding(count); - else - encoding = lldb::eEncodingSint; - } - count = 2; - return encoding; - } - - case clang::Type::ObjCInterface: break; - case clang::Type::Record: break; - case clang::Type::Enum: return lldb::eEncodingSint; - case clang::Type::Typedef: - return CompilerType(getASTContext(), llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType()).GetEncoding(count); - - case clang::Type::Auto: - return CompilerType(getASTContext(), llvm::cast<clang::AutoType>(qual_type)->getDeducedType()).GetEncoding(count); - - case clang::Type::Elaborated: - return CompilerType(getASTContext(), llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType()).GetEncoding(count); - - case clang::Type::Paren: - return CompilerType(getASTContext(), llvm::cast<clang::ParenType>(qual_type)->desugar()).GetEncoding(count); - - case clang::Type::DependentSizedArray: - case clang::Type::DependentSizedExtVector: - case clang::Type::UnresolvedUsing: - case clang::Type::Attributed: - case clang::Type::TemplateTypeParm: - case clang::Type::SubstTemplateTypeParm: - case clang::Type::SubstTemplateTypeParmPack: - case clang::Type::InjectedClassName: - case clang::Type::DependentName: - case clang::Type::DependentTemplateSpecialization: - case clang::Type::PackExpansion: - case clang::Type::ObjCObject: - - case clang::Type::TypeOfExpr: - case clang::Type::TypeOf: - case clang::Type::Decltype: - case clang::Type::TemplateSpecialization: - case clang::Type::Atomic: - case clang::Type::Adjusted: - case clang::Type::Pipe: - break; + uint32_t num_children = 0; + clang::QualType qual_type(GetQualType(type)); + const clang::Type::TypeClass type_class = qual_type->getTypeClass(); + switch (type_class) { + case clang::Type::Builtin: + switch (llvm::cast<clang::BuiltinType>(qual_type)->getKind()) { + case clang::BuiltinType::ObjCId: // child is Class + case clang::BuiltinType::ObjCClass: // child is Class + num_children = 1; + break; - // pointer type decayed from an array or function type. - case clang::Type::Decayed: - break; + default: + break; } - count = 0; - return lldb::eEncodingInvalid; -} + break; -lldb::Format -ClangASTContext::GetFormat (lldb::opaque_compiler_type_t type) -{ - if (!type) - return lldb::eFormatDefault; - - clang::QualType qual_type(GetCanonicalQualType(type)); - - switch (qual_type->getTypeClass()) - { - case clang::Type::UnaryTransform: - break; - - case clang::Type::FunctionNoProto: - case clang::Type::FunctionProto: - break; - - case clang::Type::IncompleteArray: - case clang::Type::VariableArray: - break; - - case clang::Type::ConstantArray: - return lldb::eFormatVoid; // no value - - case clang::Type::ExtVector: - case clang::Type::Vector: - break; - - case clang::Type::Builtin: - switch (llvm::cast<clang::BuiltinType>(qual_type)->getKind()) - { - //default: assert(0 && "Unknown builtin type!"); - case clang::BuiltinType::UnknownAny: - case clang::BuiltinType::Void: - case clang::BuiltinType::BoundMember: - break; - - case clang::BuiltinType::Bool: return lldb::eFormatBoolean; - case clang::BuiltinType::Char_S: - case clang::BuiltinType::SChar: - case clang::BuiltinType::WChar_S: - case clang::BuiltinType::Char_U: - case clang::BuiltinType::UChar: - case clang::BuiltinType::WChar_U: return lldb::eFormatChar; - case clang::BuiltinType::Char16: return lldb::eFormatUnicode16; - case clang::BuiltinType::Char32: return lldb::eFormatUnicode32; - case clang::BuiltinType::UShort: return lldb::eFormatUnsigned; - case clang::BuiltinType::Short: return lldb::eFormatDecimal; - case clang::BuiltinType::UInt: return lldb::eFormatUnsigned; - case clang::BuiltinType::Int: return lldb::eFormatDecimal; - case clang::BuiltinType::ULong: return lldb::eFormatUnsigned; - case clang::BuiltinType::Long: return lldb::eFormatDecimal; - case clang::BuiltinType::ULongLong: return lldb::eFormatUnsigned; - case clang::BuiltinType::LongLong: return lldb::eFormatDecimal; - case clang::BuiltinType::UInt128: return lldb::eFormatUnsigned; - case clang::BuiltinType::Int128: return lldb::eFormatDecimal; - case clang::BuiltinType::Half: - case clang::BuiltinType::Float: - case clang::BuiltinType::Double: - case clang::BuiltinType::LongDouble: return lldb::eFormatFloat; - default: - return lldb::eFormatHex; + case clang::Type::Complex: + return 0; + + case clang::Type::Record: + if (GetCompleteQualType(getASTContext(), qual_type)) { + const clang::RecordType *record_type = + llvm::cast<clang::RecordType>(qual_type.getTypePtr()); + const clang::RecordDecl *record_decl = record_type->getDecl(); + assert(record_decl); + const clang::CXXRecordDecl *cxx_record_decl = + llvm::dyn_cast<clang::CXXRecordDecl>(record_decl); + if (cxx_record_decl) { + if (omit_empty_base_classes) { + // Check each base classes to see if it or any of its + // base classes contain any fields. This can help + // limit the noise in variable views by not having to + // show base classes that contain no members. + clang::CXXRecordDecl::base_class_const_iterator base_class, + base_class_end; + for (base_class = cxx_record_decl->bases_begin(), + base_class_end = cxx_record_decl->bases_end(); + base_class != base_class_end; ++base_class) { + const clang::CXXRecordDecl *base_class_decl = + llvm::cast<clang::CXXRecordDecl>( + base_class->getType() + ->getAs<clang::RecordType>() + ->getDecl()); + + // Skip empty base classes + if (ClangASTContext::RecordHasFields(base_class_decl) == false) + continue; + + num_children++; + } + } else { + // Include all base classes + num_children += cxx_record_decl->getNumBases(); } - break; - case clang::Type::ObjCObjectPointer: return lldb::eFormatHex; - case clang::Type::BlockPointer: return lldb::eFormatHex; - case clang::Type::Pointer: return lldb::eFormatHex; - case clang::Type::LValueReference: - case clang::Type::RValueReference: return lldb::eFormatHex; - case clang::Type::MemberPointer: break; - case clang::Type::Complex: - { - if (qual_type->isComplexType()) - return lldb::eFormatComplex; - else - return lldb::eFormatComplexInteger; + } + clang::RecordDecl::field_iterator field, field_end; + for (field = record_decl->field_begin(), + field_end = record_decl->field_end(); + field != field_end; ++field) + ++num_children; + } + break; + + case clang::Type::ObjCObject: + case clang::Type::ObjCInterface: + if (GetCompleteQualType(getASTContext(), qual_type)) { + const clang::ObjCObjectType *objc_class_type = + llvm::dyn_cast<clang::ObjCObjectType>(qual_type.getTypePtr()); + assert(objc_class_type); + if (objc_class_type) { + clang::ObjCInterfaceDecl *class_interface_decl = + objc_class_type->getInterface(); + + if (class_interface_decl) { + + clang::ObjCInterfaceDecl *superclass_interface_decl = + class_interface_decl->getSuperClass(); + if (superclass_interface_decl) { + if (omit_empty_base_classes) { + if (ObjCDeclHasIVars(superclass_interface_decl, true)) + ++num_children; + } else + ++num_children; + } + + num_children += class_interface_decl->ivar_size(); } - case clang::Type::ObjCInterface: break; - case clang::Type::Record: break; - case clang::Type::Enum: return lldb::eFormatEnum; - case clang::Type::Typedef: - return CompilerType (getASTContext(), llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType()).GetFormat(); - case clang::Type::Auto: - return CompilerType (getASTContext(), llvm::cast<clang::AutoType>(qual_type)->desugar()).GetFormat(); - case clang::Type::Paren: - return CompilerType (getASTContext(), llvm::cast<clang::ParenType>(qual_type)->desugar()).GetFormat(); - case clang::Type::Elaborated: - return CompilerType (getASTContext(), llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType()).GetFormat(); - case clang::Type::DependentSizedArray: - case clang::Type::DependentSizedExtVector: - case clang::Type::UnresolvedUsing: - case clang::Type::Attributed: - case clang::Type::TemplateTypeParm: - case clang::Type::SubstTemplateTypeParm: - case clang::Type::SubstTemplateTypeParmPack: - case clang::Type::InjectedClassName: - case clang::Type::DependentName: - case clang::Type::DependentTemplateSpecialization: - case clang::Type::PackExpansion: - case clang::Type::ObjCObject: - - case clang::Type::TypeOfExpr: - case clang::Type::TypeOf: - case clang::Type::Decltype: - case clang::Type::TemplateSpecialization: - case clang::Type::Atomic: - case clang::Type::Adjusted: - case clang::Type::Pipe: - break; - - // pointer type decayed from an array or function type. - case clang::Type::Decayed: - break; - } - // We don't know hot to display this type... - return lldb::eFormatBytes; -} - -static bool -ObjCDeclHasIVars (clang::ObjCInterfaceDecl *class_interface_decl, bool check_superclass) -{ - while (class_interface_decl) - { - if (class_interface_decl->ivar_size() > 0) - return true; - - if (check_superclass) - class_interface_decl = class_interface_decl->getSuperClass(); - else - break; - } - return false; + } + } + break; + + case clang::Type::ObjCObjectPointer: { + const clang::ObjCObjectPointerType *pointer_type = + llvm::cast<clang::ObjCObjectPointerType>(qual_type.getTypePtr()); + clang::QualType pointee_type = pointer_type->getPointeeType(); + uint32_t num_pointee_children = + CompilerType(getASTContext(), pointee_type) + .GetNumChildren(omit_empty_base_classes); + // If this type points to a simple type, then it has 1 child + if (num_pointee_children == 0) + num_children = 1; + else + num_children = num_pointee_children; + } break; + + case clang::Type::Vector: + case clang::Type::ExtVector: + num_children = + llvm::cast<clang::VectorType>(qual_type.getTypePtr())->getNumElements(); + break; + + case clang::Type::ConstantArray: + num_children = llvm::cast<clang::ConstantArrayType>(qual_type.getTypePtr()) + ->getSize() + .getLimitedValue(); + break; + + case clang::Type::Pointer: { + const clang::PointerType *pointer_type = + llvm::cast<clang::PointerType>(qual_type.getTypePtr()); + clang::QualType pointee_type(pointer_type->getPointeeType()); + uint32_t num_pointee_children = + CompilerType(getASTContext(), pointee_type) + .GetNumChildren(omit_empty_base_classes); + if (num_pointee_children == 0) { + // We have a pointer to a pointee type that claims it has no children. + // We will want to look at + num_children = GetNumPointeeChildren(pointee_type); + } else + num_children = num_pointee_children; + } break; + + case clang::Type::LValueReference: + case clang::Type::RValueReference: { + const clang::ReferenceType *reference_type = + llvm::cast<clang::ReferenceType>(qual_type.getTypePtr()); + clang::QualType pointee_type = reference_type->getPointeeType(); + uint32_t num_pointee_children = + CompilerType(getASTContext(), pointee_type) + .GetNumChildren(omit_empty_base_classes); + // If this type points to a simple type, then it has 1 child + if (num_pointee_children == 0) + num_children = 1; + else + num_children = num_pointee_children; + } break; + + case clang::Type::Typedef: + num_children = + CompilerType(getASTContext(), llvm::cast<clang::TypedefType>(qual_type) + ->getDecl() + ->getUnderlyingType()) + .GetNumChildren(omit_empty_base_classes); + break; + + case clang::Type::Auto: + num_children = + CompilerType(getASTContext(), + llvm::cast<clang::AutoType>(qual_type)->getDeducedType()) + .GetNumChildren(omit_empty_base_classes); + break; + + case clang::Type::Elaborated: + num_children = + CompilerType( + getASTContext(), + llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType()) + .GetNumChildren(omit_empty_base_classes); + break; + + case clang::Type::Paren: + num_children = + CompilerType(getASTContext(), + llvm::cast<clang::ParenType>(qual_type)->desugar()) + .GetNumChildren(omit_empty_base_classes); + break; + default: + break; + } + return num_children; +} + +CompilerType ClangASTContext::GetBuiltinTypeByName(const ConstString &name) { + return GetBasicType(GetBasicTypeEnumeration(name)); } -uint32_t -ClangASTContext::GetNumChildren (lldb::opaque_compiler_type_t type, bool omit_empty_base_classes) -{ - if (!type) - return 0; - - uint32_t num_children = 0; +lldb::BasicType +ClangASTContext::GetBasicTypeEnumeration(lldb::opaque_compiler_type_t type) { + if (type) { clang::QualType qual_type(GetQualType(type)); const clang::Type::TypeClass type_class = qual_type->getTypeClass(); - switch (type_class) - { - case clang::Type::Builtin: - switch (llvm::cast<clang::BuiltinType>(qual_type)->getKind()) - { - case clang::BuiltinType::ObjCId: // child is Class - case clang::BuiltinType::ObjCClass: // child is Class - num_children = 1; - break; - - default: - break; - } - break; - - case clang::Type::Complex: return 0; - - case clang::Type::Record: - if (GetCompleteQualType (getASTContext(), qual_type)) - { - const clang::RecordType *record_type = llvm::cast<clang::RecordType>(qual_type.getTypePtr()); - const clang::RecordDecl *record_decl = record_type->getDecl(); - assert(record_decl); - const clang::CXXRecordDecl *cxx_record_decl = llvm::dyn_cast<clang::CXXRecordDecl>(record_decl); - if (cxx_record_decl) - { - if (omit_empty_base_classes) - { - // Check each base classes to see if it or any of its - // base classes contain any fields. This can help - // limit the noise in variable views by not having to - // show base classes that contain no members. - clang::CXXRecordDecl::base_class_const_iterator base_class, base_class_end; - for (base_class = cxx_record_decl->bases_begin(), base_class_end = cxx_record_decl->bases_end(); - base_class != base_class_end; - ++base_class) - { - const clang::CXXRecordDecl *base_class_decl = llvm::cast<clang::CXXRecordDecl>(base_class->getType()->getAs<clang::RecordType>()->getDecl()); - - // Skip empty base classes - if (ClangASTContext::RecordHasFields(base_class_decl) == false) - continue; - - num_children++; - } - } - else - { - // Include all base classes - num_children += cxx_record_decl->getNumBases(); - } - - } - clang::RecordDecl::field_iterator field, field_end; - for (field = record_decl->field_begin(), field_end = record_decl->field_end(); field != field_end; ++field) - ++num_children; - } - break; - - case clang::Type::ObjCObject: - case clang::Type::ObjCInterface: - if (GetCompleteQualType (getASTContext(), qual_type)) - { - const clang::ObjCObjectType *objc_class_type = llvm::dyn_cast<clang::ObjCObjectType>(qual_type.getTypePtr()); - assert (objc_class_type); - if (objc_class_type) - { - clang::ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface(); - - if (class_interface_decl) - { - - clang::ObjCInterfaceDecl *superclass_interface_decl = class_interface_decl->getSuperClass(); - if (superclass_interface_decl) - { - if (omit_empty_base_classes) - { - if (ObjCDeclHasIVars (superclass_interface_decl, true)) - ++num_children; - } - else - ++num_children; - } - - num_children += class_interface_decl->ivar_size(); - } - } - } - break; - - case clang::Type::ObjCObjectPointer: - { - const clang::ObjCObjectPointerType *pointer_type = llvm::cast<clang::ObjCObjectPointerType>(qual_type.getTypePtr()); - clang::QualType pointee_type = pointer_type->getPointeeType(); - uint32_t num_pointee_children = CompilerType (getASTContext(),pointee_type).GetNumChildren (omit_empty_base_classes); - // If this type points to a simple type, then it has 1 child - if (num_pointee_children == 0) - num_children = 1; - else - num_children = num_pointee_children; - } - break; - - case clang::Type::Vector: - case clang::Type::ExtVector: - num_children = llvm::cast<clang::VectorType>(qual_type.getTypePtr())->getNumElements(); - break; - - case clang::Type::ConstantArray: - num_children = llvm::cast<clang::ConstantArrayType>(qual_type.getTypePtr())->getSize().getLimitedValue(); - break; - - case clang::Type::Pointer: - { - const clang::PointerType *pointer_type = llvm::cast<clang::PointerType>(qual_type.getTypePtr()); - clang::QualType pointee_type (pointer_type->getPointeeType()); - uint32_t num_pointee_children = CompilerType (getASTContext(),pointee_type).GetNumChildren (omit_empty_base_classes); - if (num_pointee_children == 0) - { - // We have a pointer to a pointee type that claims it has no children. - // We will want to look at - num_children = GetNumPointeeChildren (pointee_type); - } - else - num_children = num_pointee_children; - } - break; - - case clang::Type::LValueReference: - case clang::Type::RValueReference: - { - const clang::ReferenceType *reference_type = llvm::cast<clang::ReferenceType>(qual_type.getTypePtr()); - clang::QualType pointee_type = reference_type->getPointeeType(); - uint32_t num_pointee_children = CompilerType (getASTContext(), pointee_type).GetNumChildren (omit_empty_base_classes); - // If this type points to a simple type, then it has 1 child - if (num_pointee_children == 0) - num_children = 1; - else - num_children = num_pointee_children; - } - break; - - - case clang::Type::Typedef: - num_children = CompilerType (getASTContext(), llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType()).GetNumChildren (omit_empty_base_classes); - break; - - case clang::Type::Auto: - num_children = CompilerType (getASTContext(), llvm::cast<clang::AutoType>(qual_type)->getDeducedType()).GetNumChildren (omit_empty_base_classes); - break; - - case clang::Type::Elaborated: - num_children = CompilerType (getASTContext(), llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType()).GetNumChildren (omit_empty_base_classes); - break; - - case clang::Type::Paren: - num_children = CompilerType (getASTContext(), llvm::cast<clang::ParenType>(qual_type)->desugar()).GetNumChildren (omit_empty_base_classes); - break; - default: - break; - } - return num_children; + if (type_class == clang::Type::Builtin) { + switch (llvm::cast<clang::BuiltinType>(qual_type)->getKind()) { + case clang::BuiltinType::Void: + return eBasicTypeVoid; + case clang::BuiltinType::Bool: + return eBasicTypeBool; + case clang::BuiltinType::Char_S: + return eBasicTypeSignedChar; + case clang::BuiltinType::Char_U: + return eBasicTypeUnsignedChar; + case clang::BuiltinType::Char16: + return eBasicTypeChar16; + case clang::BuiltinType::Char32: + return eBasicTypeChar32; + case clang::BuiltinType::UChar: + return eBasicTypeUnsignedChar; + case clang::BuiltinType::SChar: + return eBasicTypeSignedChar; + case clang::BuiltinType::WChar_S: + return eBasicTypeSignedWChar; + case clang::BuiltinType::WChar_U: + return eBasicTypeUnsignedWChar; + case clang::BuiltinType::Short: + return eBasicTypeShort; + case clang::BuiltinType::UShort: + return eBasicTypeUnsignedShort; + case clang::BuiltinType::Int: + return eBasicTypeInt; + case clang::BuiltinType::UInt: + return eBasicTypeUnsignedInt; + case clang::BuiltinType::Long: + return eBasicTypeLong; + case clang::BuiltinType::ULong: + return eBasicTypeUnsignedLong; + case clang::BuiltinType::LongLong: + return eBasicTypeLongLong; + case clang::BuiltinType::ULongLong: + return eBasicTypeUnsignedLongLong; + case clang::BuiltinType::Int128: + return eBasicTypeInt128; + case clang::BuiltinType::UInt128: + return eBasicTypeUnsignedInt128; + + case clang::BuiltinType::Half: + return eBasicTypeHalf; + case clang::BuiltinType::Float: + return eBasicTypeFloat; + case clang::BuiltinType::Double: + return eBasicTypeDouble; + case clang::BuiltinType::LongDouble: + return eBasicTypeLongDouble; + + case clang::BuiltinType::NullPtr: + return eBasicTypeNullPtr; + case clang::BuiltinType::ObjCId: + return eBasicTypeObjCID; + case clang::BuiltinType::ObjCClass: + return eBasicTypeObjCClass; + case clang::BuiltinType::ObjCSel: + return eBasicTypeObjCSel; + default: + return eBasicTypeOther; + } + } + } + return eBasicTypeInvalid; +} + +void ClangASTContext::ForEachEnumerator( + lldb::opaque_compiler_type_t type, + std::function<bool(const CompilerType &integer_type, + const ConstString &name, + const llvm::APSInt &value)> const &callback) { + const clang::EnumType *enum_type = + llvm::dyn_cast<clang::EnumType>(GetCanonicalQualType(type)); + if (enum_type) { + const clang::EnumDecl *enum_decl = enum_type->getDecl(); + if (enum_decl) { + CompilerType integer_type(this, + enum_decl->getIntegerType().getAsOpaquePtr()); + + clang::EnumDecl::enumerator_iterator enum_pos, enum_end_pos; + for (enum_pos = enum_decl->enumerator_begin(), + enum_end_pos = enum_decl->enumerator_end(); + enum_pos != enum_end_pos; ++enum_pos) { + ConstString name(enum_pos->getNameAsString().c_str()); + if (!callback(integer_type, name, enum_pos->getInitVal())) + break; + } + } + } } -CompilerType -ClangASTContext::GetBuiltinTypeByName (const ConstString &name) -{ - return GetBasicType(GetBasicTypeEnumeration(name)); -} +#pragma mark Aggregate Types -lldb::BasicType -ClangASTContext::GetBasicTypeEnumeration (lldb::opaque_compiler_type_t type) -{ - if (type) - { - clang::QualType qual_type(GetQualType(type)); - const clang::Type::TypeClass type_class = qual_type->getTypeClass(); - if (type_class == clang::Type::Builtin) - { - switch (llvm::cast<clang::BuiltinType>(qual_type)->getKind()) - { - case clang::BuiltinType::Void: return eBasicTypeVoid; - case clang::BuiltinType::Bool: return eBasicTypeBool; - case clang::BuiltinType::Char_S: return eBasicTypeSignedChar; - case clang::BuiltinType::Char_U: return eBasicTypeUnsignedChar; - case clang::BuiltinType::Char16: return eBasicTypeChar16; - case clang::BuiltinType::Char32: return eBasicTypeChar32; - case clang::BuiltinType::UChar: return eBasicTypeUnsignedChar; - case clang::BuiltinType::SChar: return eBasicTypeSignedChar; - case clang::BuiltinType::WChar_S: return eBasicTypeSignedWChar; - case clang::BuiltinType::WChar_U: return eBasicTypeUnsignedWChar; - case clang::BuiltinType::Short: return eBasicTypeShort; - case clang::BuiltinType::UShort: return eBasicTypeUnsignedShort; - case clang::BuiltinType::Int: return eBasicTypeInt; - case clang::BuiltinType::UInt: return eBasicTypeUnsignedInt; - case clang::BuiltinType::Long: return eBasicTypeLong; - case clang::BuiltinType::ULong: return eBasicTypeUnsignedLong; - case clang::BuiltinType::LongLong: return eBasicTypeLongLong; - case clang::BuiltinType::ULongLong: return eBasicTypeUnsignedLongLong; - case clang::BuiltinType::Int128: return eBasicTypeInt128; - case clang::BuiltinType::UInt128: return eBasicTypeUnsignedInt128; - - case clang::BuiltinType::Half: return eBasicTypeHalf; - case clang::BuiltinType::Float: return eBasicTypeFloat; - case clang::BuiltinType::Double: return eBasicTypeDouble; - case clang::BuiltinType::LongDouble:return eBasicTypeLongDouble; - - case clang::BuiltinType::NullPtr: return eBasicTypeNullPtr; - case clang::BuiltinType::ObjCId: return eBasicTypeObjCID; - case clang::BuiltinType::ObjCClass: return eBasicTypeObjCClass; - case clang::BuiltinType::ObjCSel: return eBasicTypeObjCSel; - default: - return eBasicTypeOther; - } - } - } - return eBasicTypeInvalid; -} - -void -ClangASTContext::ForEachEnumerator (lldb::opaque_compiler_type_t type, std::function <bool (const CompilerType &integer_type, const ConstString &name, const llvm::APSInt &value)> const &callback) -{ - const clang::EnumType *enum_type = llvm::dyn_cast<clang::EnumType>(GetCanonicalQualType(type)); - if (enum_type) - { - const clang::EnumDecl *enum_decl = enum_type->getDecl(); - if (enum_decl) - { - CompilerType integer_type(this, enum_decl->getIntegerType().getAsOpaquePtr()); - - clang::EnumDecl::enumerator_iterator enum_pos, enum_end_pos; - for (enum_pos = enum_decl->enumerator_begin(), enum_end_pos = enum_decl->enumerator_end(); enum_pos != enum_end_pos; ++enum_pos) - { - ConstString name(enum_pos->getNameAsString().c_str()); - if (!callback (integer_type, name, enum_pos->getInitVal())) - break; - } - } - } -} +uint32_t ClangASTContext::GetNumFields(lldb::opaque_compiler_type_t type) { + if (!type) + return 0; + uint32_t count = 0; + clang::QualType qual_type(GetCanonicalQualType(type)); + const clang::Type::TypeClass type_class = qual_type->getTypeClass(); + switch (type_class) { + case clang::Type::Record: + if (GetCompleteType(type)) { + const clang::RecordType *record_type = + llvm::dyn_cast<clang::RecordType>(qual_type.getTypePtr()); + if (record_type) { + clang::RecordDecl *record_decl = record_type->getDecl(); + if (record_decl) { + uint32_t field_idx = 0; + clang::RecordDecl::field_iterator field, field_end; + for (field = record_decl->field_begin(), + field_end = record_decl->field_end(); + field != field_end; ++field) + ++field_idx; + count = field_idx; + } + } + } + break; + + case clang::Type::Typedef: + count = + CompilerType(getASTContext(), llvm::cast<clang::TypedefType>(qual_type) + ->getDecl() + ->getUnderlyingType()) + .GetNumFields(); + break; + + case clang::Type::Auto: + count = + CompilerType(getASTContext(), + llvm::cast<clang::AutoType>(qual_type)->getDeducedType()) + .GetNumFields(); + break; + + case clang::Type::Elaborated: + count = CompilerType( + getASTContext(), + llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType()) + .GetNumFields(); + break; + + case clang::Type::Paren: + count = CompilerType(getASTContext(), + llvm::cast<clang::ParenType>(qual_type)->desugar()) + .GetNumFields(); + break; + + case clang::Type::ObjCObjectPointer: + if (GetCompleteType(type)) { + const clang::ObjCObjectPointerType *objc_class_type = + qual_type->getAsObjCInterfacePointerType(); + if (objc_class_type) { + clang::ObjCInterfaceDecl *class_interface_decl = + objc_class_type->getInterfaceDecl(); -#pragma mark Aggregate Types + if (class_interface_decl) + count = class_interface_decl->ivar_size(); + } + } + break; -uint32_t -ClangASTContext::GetNumFields (lldb::opaque_compiler_type_t type) -{ - if (!type) - return 0; - - uint32_t count = 0; - clang::QualType qual_type(GetCanonicalQualType(type)); - const clang::Type::TypeClass type_class = qual_type->getTypeClass(); - switch (type_class) - { - case clang::Type::Record: - if (GetCompleteType(type)) - { - const clang::RecordType *record_type = llvm::dyn_cast<clang::RecordType>(qual_type.getTypePtr()); - if (record_type) - { - clang::RecordDecl *record_decl = record_type->getDecl(); - if (record_decl) - { - uint32_t field_idx = 0; - clang::RecordDecl::field_iterator field, field_end; - for (field = record_decl->field_begin(), field_end = record_decl->field_end(); field != field_end; ++field) - ++field_idx; - count = field_idx; - } - } - } - break; - - case clang::Type::Typedef: - count = CompilerType (getASTContext(), llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType()).GetNumFields(); - break; + case clang::Type::ObjCObject: + case clang::Type::ObjCInterface: + if (GetCompleteType(type)) { + const clang::ObjCObjectType *objc_class_type = + llvm::dyn_cast<clang::ObjCObjectType>(qual_type.getTypePtr()); + if (objc_class_type) { + clang::ObjCInterfaceDecl *class_interface_decl = + objc_class_type->getInterface(); - case clang::Type::Auto: - count = CompilerType (getASTContext(), llvm::cast<clang::AutoType>(qual_type)->getDeducedType()).GetNumFields(); - break; - - case clang::Type::Elaborated: - count = CompilerType (getASTContext(), llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType()).GetNumFields(); - break; - - case clang::Type::Paren: - count = CompilerType (getASTContext(), llvm::cast<clang::ParenType>(qual_type)->desugar()).GetNumFields(); - break; - - case clang::Type::ObjCObjectPointer: - if (GetCompleteType(type)) - { - const clang::ObjCObjectPointerType *objc_class_type = qual_type->getAsObjCInterfacePointerType(); - if (objc_class_type) - { - clang::ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterfaceDecl(); - - if (class_interface_decl) - count = class_interface_decl->ivar_size(); - } - } - break; - - case clang::Type::ObjCObject: - case clang::Type::ObjCInterface: - if (GetCompleteType(type)) - { - const clang::ObjCObjectType *objc_class_type = llvm::dyn_cast<clang::ObjCObjectType>(qual_type.getTypePtr()); - if (objc_class_type) - { - clang::ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface(); - - if (class_interface_decl) - count = class_interface_decl->ivar_size(); - } - } - break; - - default: - break; + if (class_interface_decl) + count = class_interface_decl->ivar_size(); + } } - return count; + break; + + default: + break; + } + return count; } static lldb::opaque_compiler_type_t -GetObjCFieldAtIndex (clang::ASTContext *ast, - clang::ObjCInterfaceDecl *class_interface_decl, - size_t idx, - std::string& name, - uint64_t *bit_offset_ptr, - uint32_t *bitfield_bit_size_ptr, - bool *is_bitfield_ptr) -{ - if (class_interface_decl) - { - if (idx < (class_interface_decl->ivar_size())) - { - clang::ObjCInterfaceDecl::ivar_iterator ivar_pos, ivar_end = class_interface_decl->ivar_end(); - uint32_t ivar_idx = 0; - - for (ivar_pos = class_interface_decl->ivar_begin(); ivar_pos != ivar_end; ++ivar_pos, ++ivar_idx) - { - if (ivar_idx == idx) - { - const clang::ObjCIvarDecl* ivar_decl = *ivar_pos; - - clang::QualType ivar_qual_type(ivar_decl->getType()); - - name.assign(ivar_decl->getNameAsString()); - - if (bit_offset_ptr) - { - const clang::ASTRecordLayout &interface_layout = ast->getASTObjCInterfaceLayout(class_interface_decl); - *bit_offset_ptr = interface_layout.getFieldOffset (ivar_idx); - } - - const bool is_bitfield = ivar_pos->isBitField(); - - if (bitfield_bit_size_ptr) - { - *bitfield_bit_size_ptr = 0; - - if (is_bitfield && ast) - { - clang::Expr *bitfield_bit_size_expr = ivar_pos->getBitWidth(); - llvm::APSInt bitfield_apsint; - if (bitfield_bit_size_expr && bitfield_bit_size_expr->EvaluateAsInt(bitfield_apsint, *ast)) - { - *bitfield_bit_size_ptr = bitfield_apsint.getLimitedValue(); - } - } - } - if (is_bitfield_ptr) - *is_bitfield_ptr = is_bitfield; - - return ivar_qual_type.getAsOpaquePtr(); - } +GetObjCFieldAtIndex(clang::ASTContext *ast, + clang::ObjCInterfaceDecl *class_interface_decl, size_t idx, + std::string &name, uint64_t *bit_offset_ptr, + uint32_t *bitfield_bit_size_ptr, bool *is_bitfield_ptr) { + if (class_interface_decl) { + if (idx < (class_interface_decl->ivar_size())) { + clang::ObjCInterfaceDecl::ivar_iterator ivar_pos, + ivar_end = class_interface_decl->ivar_end(); + uint32_t ivar_idx = 0; + + for (ivar_pos = class_interface_decl->ivar_begin(); ivar_pos != ivar_end; + ++ivar_pos, ++ivar_idx) { + if (ivar_idx == idx) { + const clang::ObjCIvarDecl *ivar_decl = *ivar_pos; + + clang::QualType ivar_qual_type(ivar_decl->getType()); + + name.assign(ivar_decl->getNameAsString()); + + if (bit_offset_ptr) { + const clang::ASTRecordLayout &interface_layout = + ast->getASTObjCInterfaceLayout(class_interface_decl); + *bit_offset_ptr = interface_layout.getFieldOffset(ivar_idx); + } + + const bool is_bitfield = ivar_pos->isBitField(); + + if (bitfield_bit_size_ptr) { + *bitfield_bit_size_ptr = 0; + + if (is_bitfield && ast) { + clang::Expr *bitfield_bit_size_expr = ivar_pos->getBitWidth(); + llvm::APSInt bitfield_apsint; + if (bitfield_bit_size_expr && + bitfield_bit_size_expr->EvaluateAsInt(bitfield_apsint, + *ast)) { + *bitfield_bit_size_ptr = bitfield_apsint.getLimitedValue(); + } } + } + if (is_bitfield_ptr) + *is_bitfield_ptr = is_bitfield; + + return ivar_qual_type.getAsOpaquePtr(); } + } } - return nullptr; + } + return nullptr; } -CompilerType -ClangASTContext::GetFieldAtIndex (lldb::opaque_compiler_type_t type, size_t idx, - std::string& name, - uint64_t *bit_offset_ptr, - uint32_t *bitfield_bit_size_ptr, - bool *is_bitfield_ptr) -{ - if (!type) - return CompilerType(); - - clang::QualType qual_type(GetCanonicalQualType(type)); - const clang::Type::TypeClass type_class = qual_type->getTypeClass(); - switch (type_class) - { - case clang::Type::Record: - if (GetCompleteType(type)) - { - const clang::RecordType *record_type = llvm::cast<clang::RecordType>(qual_type.getTypePtr()); - const clang::RecordDecl *record_decl = record_type->getDecl(); - uint32_t field_idx = 0; - clang::RecordDecl::field_iterator field, field_end; - for (field = record_decl->field_begin(), field_end = record_decl->field_end(); field != field_end; ++field, ++field_idx) - { - if (idx == field_idx) - { - // Print the member type if requested - // Print the member name and equal sign - name.assign(field->getNameAsString()); - - // Figure out the type byte size (field_type_info.first) and - // alignment (field_type_info.second) from the AST context. - if (bit_offset_ptr) - { - const clang::ASTRecordLayout &record_layout = getASTContext()->getASTRecordLayout(record_decl); - *bit_offset_ptr = record_layout.getFieldOffset (field_idx); - } - - const bool is_bitfield = field->isBitField(); - - if (bitfield_bit_size_ptr) - { - *bitfield_bit_size_ptr = 0; - - if (is_bitfield) - { - clang::Expr *bitfield_bit_size_expr = field->getBitWidth(); - llvm::APSInt bitfield_apsint; - if (bitfield_bit_size_expr && bitfield_bit_size_expr->EvaluateAsInt(bitfield_apsint, *getASTContext())) - { - *bitfield_bit_size_ptr = bitfield_apsint.getLimitedValue(); - } - } - } - if (is_bitfield_ptr) - *is_bitfield_ptr = is_bitfield; - - return CompilerType (getASTContext(), field->getType()); - } - } - } - break; - - case clang::Type::ObjCObjectPointer: - if (GetCompleteType(type)) - { - const clang::ObjCObjectPointerType *objc_class_type = qual_type->getAsObjCInterfacePointerType(); - if (objc_class_type) - { - clang::ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterfaceDecl(); - return CompilerType (this, GetObjCFieldAtIndex(getASTContext(), class_interface_decl, idx, name, bit_offset_ptr, bitfield_bit_size_ptr, is_bitfield_ptr)); - } - } - break; - - case clang::Type::ObjCObject: - case clang::Type::ObjCInterface: - if (GetCompleteType(type)) - { - const clang::ObjCObjectType *objc_class_type = llvm::dyn_cast<clang::ObjCObjectType>(qual_type.getTypePtr()); - assert (objc_class_type); - if (objc_class_type) - { - clang::ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface(); - return CompilerType (this, GetObjCFieldAtIndex(getASTContext(), class_interface_decl, idx, name, bit_offset_ptr, bitfield_bit_size_ptr, is_bitfield_ptr)); - } - } - break; - - - case clang::Type::Typedef: - return CompilerType (getASTContext(), llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType()). - GetFieldAtIndex (idx, - name, - bit_offset_ptr, - bitfield_bit_size_ptr, - is_bitfield_ptr); - - case clang::Type::Auto: - return CompilerType (getASTContext(), llvm::cast<clang::AutoType>(qual_type)->getDeducedType()). - GetFieldAtIndex (idx, - name, - bit_offset_ptr, - bitfield_bit_size_ptr, - is_bitfield_ptr); - - case clang::Type::Elaborated: - return CompilerType (getASTContext(), llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType()). - GetFieldAtIndex (idx, - name, - bit_offset_ptr, - bitfield_bit_size_ptr, - is_bitfield_ptr); - - case clang::Type::Paren: - return CompilerType (getASTContext(), llvm::cast<clang::ParenType>(qual_type)->desugar()). - GetFieldAtIndex (idx, - name, - bit_offset_ptr, - bitfield_bit_size_ptr, - is_bitfield_ptr); - - default: - break; - } +CompilerType ClangASTContext::GetFieldAtIndex(lldb::opaque_compiler_type_t type, + size_t idx, std::string &name, + uint64_t *bit_offset_ptr, + uint32_t *bitfield_bit_size_ptr, + bool *is_bitfield_ptr) { + if (!type) return CompilerType(); -} -uint32_t -ClangASTContext::GetNumDirectBaseClasses (lldb::opaque_compiler_type_t type) -{ - uint32_t count = 0; - clang::QualType qual_type(GetCanonicalQualType(type)); - const clang::Type::TypeClass type_class = qual_type->getTypeClass(); - switch (type_class) - { - case clang::Type::Record: - if (GetCompleteType(type)) - { - const clang::CXXRecordDecl *cxx_record_decl = qual_type->getAsCXXRecordDecl(); - if (cxx_record_decl) - count = cxx_record_decl->getNumBases(); + clang::QualType qual_type(GetCanonicalQualType(type)); + const clang::Type::TypeClass type_class = qual_type->getTypeClass(); + switch (type_class) { + case clang::Type::Record: + if (GetCompleteType(type)) { + const clang::RecordType *record_type = + llvm::cast<clang::RecordType>(qual_type.getTypePtr()); + const clang::RecordDecl *record_decl = record_type->getDecl(); + uint32_t field_idx = 0; + clang::RecordDecl::field_iterator field, field_end; + for (field = record_decl->field_begin(), + field_end = record_decl->field_end(); + field != field_end; ++field, ++field_idx) { + if (idx == field_idx) { + // Print the member type if requested + // Print the member name and equal sign + name.assign(field->getNameAsString()); + + // Figure out the type byte size (field_type_info.first) and + // alignment (field_type_info.second) from the AST context. + if (bit_offset_ptr) { + const clang::ASTRecordLayout &record_layout = + getASTContext()->getASTRecordLayout(record_decl); + *bit_offset_ptr = record_layout.getFieldOffset(field_idx); + } + + const bool is_bitfield = field->isBitField(); + + if (bitfield_bit_size_ptr) { + *bitfield_bit_size_ptr = 0; + + if (is_bitfield) { + clang::Expr *bitfield_bit_size_expr = field->getBitWidth(); + llvm::APSInt bitfield_apsint; + if (bitfield_bit_size_expr && + bitfield_bit_size_expr->EvaluateAsInt(bitfield_apsint, + *getASTContext())) { + *bitfield_bit_size_ptr = bitfield_apsint.getLimitedValue(); + } } - break; - - case clang::Type::ObjCObjectPointer: - count = GetPointeeType(type).GetNumDirectBaseClasses(); - break; - - case clang::Type::ObjCObject: - if (GetCompleteType(type)) - { - const clang::ObjCObjectType *objc_class_type = qual_type->getAsObjCQualifiedInterfaceType(); - if (objc_class_type) - { - clang::ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface(); - - if (class_interface_decl && class_interface_decl->getSuperClass()) - count = 1; - } - } - break; - case clang::Type::ObjCInterface: - if (GetCompleteType(type)) - { - const clang::ObjCInterfaceType *objc_interface_type = qual_type->getAs<clang::ObjCInterfaceType>(); - if (objc_interface_type) - { - clang::ObjCInterfaceDecl *class_interface_decl = objc_interface_type->getInterface(); - - if (class_interface_decl && class_interface_decl->getSuperClass()) - count = 1; - } - } - break; - - - case clang::Type::Typedef: - count = GetNumDirectBaseClasses(llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType().getAsOpaquePtr()); - break; - - case clang::Type::Auto: - count = GetNumDirectBaseClasses(llvm::cast<clang::AutoType>(qual_type)->getDeducedType().getAsOpaquePtr()); - break; - - case clang::Type::Elaborated: - count = GetNumDirectBaseClasses(llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType().getAsOpaquePtr()); - break; - - case clang::Type::Paren: - return GetNumDirectBaseClasses(llvm::cast<clang::ParenType>(qual_type)->desugar().getAsOpaquePtr()); - - default: - break; - } - return count; + } + if (is_bitfield_ptr) + *is_bitfield_ptr = is_bitfield; + return CompilerType(getASTContext(), field->getType()); + } + } + } + break; + + case clang::Type::ObjCObjectPointer: + if (GetCompleteType(type)) { + const clang::ObjCObjectPointerType *objc_class_type = + qual_type->getAsObjCInterfacePointerType(); + if (objc_class_type) { + clang::ObjCInterfaceDecl *class_interface_decl = + objc_class_type->getInterfaceDecl(); + return CompilerType( + this, GetObjCFieldAtIndex(getASTContext(), class_interface_decl, + idx, name, bit_offset_ptr, + bitfield_bit_size_ptr, is_bitfield_ptr)); + } + } + break; + + case clang::Type::ObjCObject: + case clang::Type::ObjCInterface: + if (GetCompleteType(type)) { + const clang::ObjCObjectType *objc_class_type = + llvm::dyn_cast<clang::ObjCObjectType>(qual_type.getTypePtr()); + assert(objc_class_type); + if (objc_class_type) { + clang::ObjCInterfaceDecl *class_interface_decl = + objc_class_type->getInterface(); + return CompilerType( + this, GetObjCFieldAtIndex(getASTContext(), class_interface_decl, + idx, name, bit_offset_ptr, + bitfield_bit_size_ptr, is_bitfield_ptr)); + } + } + break; + + case clang::Type::Typedef: + return CompilerType(getASTContext(), + llvm::cast<clang::TypedefType>(qual_type) + ->getDecl() + ->getUnderlyingType()) + .GetFieldAtIndex(idx, name, bit_offset_ptr, bitfield_bit_size_ptr, + is_bitfield_ptr); + + case clang::Type::Auto: + return CompilerType( + getASTContext(), + llvm::cast<clang::AutoType>(qual_type)->getDeducedType()) + .GetFieldAtIndex(idx, name, bit_offset_ptr, bitfield_bit_size_ptr, + is_bitfield_ptr); + + case clang::Type::Elaborated: + return CompilerType( + getASTContext(), + llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType()) + .GetFieldAtIndex(idx, name, bit_offset_ptr, bitfield_bit_size_ptr, + is_bitfield_ptr); + + case clang::Type::Paren: + return CompilerType(getASTContext(), + llvm::cast<clang::ParenType>(qual_type)->desugar()) + .GetFieldAtIndex(idx, name, bit_offset_ptr, bitfield_bit_size_ptr, + is_bitfield_ptr); + + default: + break; + } + return CompilerType(); } uint32_t -ClangASTContext::GetNumVirtualBaseClasses (lldb::opaque_compiler_type_t type) -{ - uint32_t count = 0; - clang::QualType qual_type(GetCanonicalQualType(type)); - const clang::Type::TypeClass type_class = qual_type->getTypeClass(); - switch (type_class) - { - case clang::Type::Record: - if (GetCompleteType(type)) - { - const clang::CXXRecordDecl *cxx_record_decl = qual_type->getAsCXXRecordDecl(); - if (cxx_record_decl) - count = cxx_record_decl->getNumVBases(); - } - break; - - case clang::Type::Typedef: - count = GetNumVirtualBaseClasses(llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType().getAsOpaquePtr()); - break; - - case clang::Type::Auto: - count = GetNumVirtualBaseClasses(llvm::cast<clang::AutoType>(qual_type)->getDeducedType().getAsOpaquePtr()); - break; - - case clang::Type::Elaborated: - count = GetNumVirtualBaseClasses(llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType().getAsOpaquePtr()); - break; - - case clang::Type::Paren: - count = GetNumVirtualBaseClasses(llvm::cast<clang::ParenType>(qual_type)->desugar().getAsOpaquePtr()); - break; - - default: - break; - } - return count; - +ClangASTContext::GetNumDirectBaseClasses(lldb::opaque_compiler_type_t type) { + uint32_t count = 0; + clang::QualType qual_type(GetCanonicalQualType(type)); + const clang::Type::TypeClass type_class = qual_type->getTypeClass(); + switch (type_class) { + case clang::Type::Record: + if (GetCompleteType(type)) { + const clang::CXXRecordDecl *cxx_record_decl = + qual_type->getAsCXXRecordDecl(); + if (cxx_record_decl) + count = cxx_record_decl->getNumBases(); + } + break; + + case clang::Type::ObjCObjectPointer: + count = GetPointeeType(type).GetNumDirectBaseClasses(); + break; + + case clang::Type::ObjCObject: + if (GetCompleteType(type)) { + const clang::ObjCObjectType *objc_class_type = + qual_type->getAsObjCQualifiedInterfaceType(); + if (objc_class_type) { + clang::ObjCInterfaceDecl *class_interface_decl = + objc_class_type->getInterface(); + + if (class_interface_decl && class_interface_decl->getSuperClass()) + count = 1; + } + } + break; + case clang::Type::ObjCInterface: + if (GetCompleteType(type)) { + const clang::ObjCInterfaceType *objc_interface_type = + qual_type->getAs<clang::ObjCInterfaceType>(); + if (objc_interface_type) { + clang::ObjCInterfaceDecl *class_interface_decl = + objc_interface_type->getInterface(); + + if (class_interface_decl && class_interface_decl->getSuperClass()) + count = 1; + } + } + break; + + case clang::Type::Typedef: + count = GetNumDirectBaseClasses(llvm::cast<clang::TypedefType>(qual_type) + ->getDecl() + ->getUnderlyingType() + .getAsOpaquePtr()); + break; + + case clang::Type::Auto: + count = GetNumDirectBaseClasses(llvm::cast<clang::AutoType>(qual_type) + ->getDeducedType() + .getAsOpaquePtr()); + break; + + case clang::Type::Elaborated: + count = GetNumDirectBaseClasses(llvm::cast<clang::ElaboratedType>(qual_type) + ->getNamedType() + .getAsOpaquePtr()); + break; + + case clang::Type::Paren: + return GetNumDirectBaseClasses( + llvm::cast<clang::ParenType>(qual_type)->desugar().getAsOpaquePtr()); + + default: + break; + } + return count; } -CompilerType -ClangASTContext::GetDirectBaseClassAtIndex (lldb::opaque_compiler_type_t type, size_t idx, uint32_t *bit_offset_ptr) -{ - clang::QualType qual_type(GetCanonicalQualType(type)); - const clang::Type::TypeClass type_class = qual_type->getTypeClass(); - switch (type_class) - { - case clang::Type::Record: - if (GetCompleteType(type)) - { - const clang::CXXRecordDecl *cxx_record_decl = qual_type->getAsCXXRecordDecl(); - if (cxx_record_decl) - { - uint32_t curr_idx = 0; - clang::CXXRecordDecl::base_class_const_iterator base_class, base_class_end; - for (base_class = cxx_record_decl->bases_begin(), base_class_end = cxx_record_decl->bases_end(); - base_class != base_class_end; - ++base_class, ++curr_idx) - { - if (curr_idx == idx) - { - if (bit_offset_ptr) - { - const clang::ASTRecordLayout &record_layout = getASTContext()->getASTRecordLayout(cxx_record_decl); - const clang::CXXRecordDecl *base_class_decl = llvm::cast<clang::CXXRecordDecl>(base_class->getType()->getAs<clang::RecordType>()->getDecl()); - if (base_class->isVirtual()) - *bit_offset_ptr = record_layout.getVBaseClassOffset(base_class_decl).getQuantity() * 8; - else - *bit_offset_ptr = record_layout.getBaseClassOffset(base_class_decl).getQuantity() * 8; - } - return CompilerType (this, base_class->getType().getAsOpaquePtr()); - } - } - } - } - break; - - case clang::Type::ObjCObjectPointer: - return GetPointeeType(type).GetDirectBaseClassAtIndex(idx, bit_offset_ptr); - - case clang::Type::ObjCObject: - if (idx == 0 && GetCompleteType(type)) - { - const clang::ObjCObjectType *objc_class_type = qual_type->getAsObjCQualifiedInterfaceType(); - if (objc_class_type) - { - clang::ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface(); - - if (class_interface_decl) - { - clang::ObjCInterfaceDecl *superclass_interface_decl = class_interface_decl->getSuperClass(); - if (superclass_interface_decl) - { - if (bit_offset_ptr) - *bit_offset_ptr = 0; - return CompilerType (getASTContext(), getASTContext()->getObjCInterfaceType(superclass_interface_decl)); - } - } - } +uint32_t +ClangASTContext::GetNumVirtualBaseClasses(lldb::opaque_compiler_type_t type) { + uint32_t count = 0; + clang::QualType qual_type(GetCanonicalQualType(type)); + const clang::Type::TypeClass type_class = qual_type->getTypeClass(); + switch (type_class) { + case clang::Type::Record: + if (GetCompleteType(type)) { + const clang::CXXRecordDecl *cxx_record_decl = + qual_type->getAsCXXRecordDecl(); + if (cxx_record_decl) + count = cxx_record_decl->getNumVBases(); + } + break; + + case clang::Type::Typedef: + count = GetNumVirtualBaseClasses(llvm::cast<clang::TypedefType>(qual_type) + ->getDecl() + ->getUnderlyingType() + .getAsOpaquePtr()); + break; + + case clang::Type::Auto: + count = GetNumVirtualBaseClasses(llvm::cast<clang::AutoType>(qual_type) + ->getDeducedType() + .getAsOpaquePtr()); + break; + + case clang::Type::Elaborated: + count = + GetNumVirtualBaseClasses(llvm::cast<clang::ElaboratedType>(qual_type) + ->getNamedType() + .getAsOpaquePtr()); + break; + + case clang::Type::Paren: + count = GetNumVirtualBaseClasses( + llvm::cast<clang::ParenType>(qual_type)->desugar().getAsOpaquePtr()); + break; + + default: + break; + } + return count; +} + +CompilerType ClangASTContext::GetDirectBaseClassAtIndex( + lldb::opaque_compiler_type_t type, size_t idx, uint32_t *bit_offset_ptr) { + clang::QualType qual_type(GetCanonicalQualType(type)); + const clang::Type::TypeClass type_class = qual_type->getTypeClass(); + switch (type_class) { + case clang::Type::Record: + if (GetCompleteType(type)) { + const clang::CXXRecordDecl *cxx_record_decl = + qual_type->getAsCXXRecordDecl(); + if (cxx_record_decl) { + uint32_t curr_idx = 0; + clang::CXXRecordDecl::base_class_const_iterator base_class, + base_class_end; + for (base_class = cxx_record_decl->bases_begin(), + base_class_end = cxx_record_decl->bases_end(); + base_class != base_class_end; ++base_class, ++curr_idx) { + if (curr_idx == idx) { + if (bit_offset_ptr) { + const clang::ASTRecordLayout &record_layout = + getASTContext()->getASTRecordLayout(cxx_record_decl); + const clang::CXXRecordDecl *base_class_decl = + llvm::cast<clang::CXXRecordDecl>( + base_class->getType() + ->getAs<clang::RecordType>() + ->getDecl()); + if (base_class->isVirtual()) + *bit_offset_ptr = + record_layout.getVBaseClassOffset(base_class_decl) + .getQuantity() * + 8; + else + *bit_offset_ptr = + record_layout.getBaseClassOffset(base_class_decl) + .getQuantity() * + 8; } - break; - case clang::Type::ObjCInterface: - if (idx == 0 && GetCompleteType(type)) - { - const clang::ObjCObjectType *objc_interface_type = qual_type->getAs<clang::ObjCInterfaceType>(); - if (objc_interface_type) - { - clang::ObjCInterfaceDecl *class_interface_decl = objc_interface_type->getInterface(); - - if (class_interface_decl) - { - clang::ObjCInterfaceDecl *superclass_interface_decl = class_interface_decl->getSuperClass(); - if (superclass_interface_decl) - { - if (bit_offset_ptr) - *bit_offset_ptr = 0; - return CompilerType (getASTContext(), getASTContext()->getObjCInterfaceType(superclass_interface_decl)); - } - } - } + return CompilerType(this, base_class->getType().getAsOpaquePtr()); + } + } + } + } + break; + + case clang::Type::ObjCObjectPointer: + return GetPointeeType(type).GetDirectBaseClassAtIndex(idx, bit_offset_ptr); + + case clang::Type::ObjCObject: + if (idx == 0 && GetCompleteType(type)) { + const clang::ObjCObjectType *objc_class_type = + qual_type->getAsObjCQualifiedInterfaceType(); + if (objc_class_type) { + clang::ObjCInterfaceDecl *class_interface_decl = + objc_class_type->getInterface(); + + if (class_interface_decl) { + clang::ObjCInterfaceDecl *superclass_interface_decl = + class_interface_decl->getSuperClass(); + if (superclass_interface_decl) { + if (bit_offset_ptr) + *bit_offset_ptr = 0; + return CompilerType(getASTContext(), + getASTContext()->getObjCInterfaceType( + superclass_interface_decl)); + } + } + } + } + break; + case clang::Type::ObjCInterface: + if (idx == 0 && GetCompleteType(type)) { + const clang::ObjCObjectType *objc_interface_type = + qual_type->getAs<clang::ObjCInterfaceType>(); + if (objc_interface_type) { + clang::ObjCInterfaceDecl *class_interface_decl = + objc_interface_type->getInterface(); + + if (class_interface_decl) { + clang::ObjCInterfaceDecl *superclass_interface_decl = + class_interface_decl->getSuperClass(); + if (superclass_interface_decl) { + if (bit_offset_ptr) + *bit_offset_ptr = 0; + return CompilerType(getASTContext(), + getASTContext()->getObjCInterfaceType( + superclass_interface_decl)); + } + } + } + } + break; + + case clang::Type::Typedef: + return GetDirectBaseClassAtIndex(llvm::cast<clang::TypedefType>(qual_type) + ->getDecl() + ->getUnderlyingType() + .getAsOpaquePtr(), + idx, bit_offset_ptr); + + case clang::Type::Auto: + return GetDirectBaseClassAtIndex(llvm::cast<clang::AutoType>(qual_type) + ->getDeducedType() + .getAsOpaquePtr(), + idx, bit_offset_ptr); + + case clang::Type::Elaborated: + return GetDirectBaseClassAtIndex( + llvm::cast<clang::ElaboratedType>(qual_type) + ->getNamedType() + .getAsOpaquePtr(), + idx, bit_offset_ptr); + + case clang::Type::Paren: + return GetDirectBaseClassAtIndex( + llvm::cast<clang::ParenType>(qual_type)->desugar().getAsOpaquePtr(), + idx, bit_offset_ptr); + + default: + break; + } + return CompilerType(); +} + +CompilerType ClangASTContext::GetVirtualBaseClassAtIndex( + lldb::opaque_compiler_type_t type, size_t idx, uint32_t *bit_offset_ptr) { + clang::QualType qual_type(GetCanonicalQualType(type)); + const clang::Type::TypeClass type_class = qual_type->getTypeClass(); + switch (type_class) { + case clang::Type::Record: + if (GetCompleteType(type)) { + const clang::CXXRecordDecl *cxx_record_decl = + qual_type->getAsCXXRecordDecl(); + if (cxx_record_decl) { + uint32_t curr_idx = 0; + clang::CXXRecordDecl::base_class_const_iterator base_class, + base_class_end; + for (base_class = cxx_record_decl->vbases_begin(), + base_class_end = cxx_record_decl->vbases_end(); + base_class != base_class_end; ++base_class, ++curr_idx) { + if (curr_idx == idx) { + if (bit_offset_ptr) { + const clang::ASTRecordLayout &record_layout = + getASTContext()->getASTRecordLayout(cxx_record_decl); + const clang::CXXRecordDecl *base_class_decl = + llvm::cast<clang::CXXRecordDecl>( + base_class->getType() + ->getAs<clang::RecordType>() + ->getDecl()); + *bit_offset_ptr = + record_layout.getVBaseClassOffset(base_class_decl) + .getQuantity() * + 8; } - break; - - - case clang::Type::Typedef: - return GetDirectBaseClassAtIndex (llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType().getAsOpaquePtr(), idx, bit_offset_ptr); - - case clang::Type::Auto: - return GetDirectBaseClassAtIndex (llvm::cast<clang::AutoType>(qual_type)->getDeducedType().getAsOpaquePtr(), idx, bit_offset_ptr); - - case clang::Type::Elaborated: - return GetDirectBaseClassAtIndex (llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType().getAsOpaquePtr(), idx, bit_offset_ptr); - - case clang::Type::Paren: - return GetDirectBaseClassAtIndex (llvm::cast<clang::ParenType>(qual_type)->desugar().getAsOpaquePtr(), idx, bit_offset_ptr); - - default: - break; + return CompilerType(this, base_class->getType().getAsOpaquePtr()); + } + } + } } - return CompilerType(); -} + break; -CompilerType -ClangASTContext::GetVirtualBaseClassAtIndex (lldb::opaque_compiler_type_t type, - size_t idx, - uint32_t *bit_offset_ptr) -{ - clang::QualType qual_type(GetCanonicalQualType(type)); - const clang::Type::TypeClass type_class = qual_type->getTypeClass(); - switch (type_class) - { - case clang::Type::Record: - if (GetCompleteType(type)) - { - const clang::CXXRecordDecl *cxx_record_decl = qual_type->getAsCXXRecordDecl(); - if (cxx_record_decl) - { - uint32_t curr_idx = 0; - clang::CXXRecordDecl::base_class_const_iterator base_class, base_class_end; - for (base_class = cxx_record_decl->vbases_begin(), base_class_end = cxx_record_decl->vbases_end(); - base_class != base_class_end; - ++base_class, ++curr_idx) - { - if (curr_idx == idx) - { - if (bit_offset_ptr) - { - const clang::ASTRecordLayout &record_layout = getASTContext()->getASTRecordLayout(cxx_record_decl); - const clang::CXXRecordDecl *base_class_decl = llvm::cast<clang::CXXRecordDecl>(base_class->getType()->getAs<clang::RecordType>()->getDecl()); - *bit_offset_ptr = record_layout.getVBaseClassOffset(base_class_decl).getQuantity() * 8; + case clang::Type::Typedef: + return GetVirtualBaseClassAtIndex(llvm::cast<clang::TypedefType>(qual_type) + ->getDecl() + ->getUnderlyingType() + .getAsOpaquePtr(), + idx, bit_offset_ptr); - } - return CompilerType (this, base_class->getType().getAsOpaquePtr()); - } - } - } - } - break; + case clang::Type::Auto: + return GetVirtualBaseClassAtIndex(llvm::cast<clang::AutoType>(qual_type) + ->getDeducedType() + .getAsOpaquePtr(), + idx, bit_offset_ptr); - case clang::Type::Typedef: - return GetVirtualBaseClassAtIndex (llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType().getAsOpaquePtr(), idx, bit_offset_ptr); - - case clang::Type::Auto: - return GetVirtualBaseClassAtIndex (llvm::cast<clang::AutoType>(qual_type)->getDeducedType().getAsOpaquePtr(), idx, bit_offset_ptr); - - case clang::Type::Elaborated: - return GetVirtualBaseClassAtIndex (llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType().getAsOpaquePtr(), idx, bit_offset_ptr); + case clang::Type::Elaborated: + return GetVirtualBaseClassAtIndex( + llvm::cast<clang::ElaboratedType>(qual_type) + ->getNamedType() + .getAsOpaquePtr(), + idx, bit_offset_ptr); - case clang::Type::Paren: - return GetVirtualBaseClassAtIndex(llvm::cast<clang::ParenType>(qual_type)->desugar().getAsOpaquePtr(), idx, - bit_offset_ptr); - - default: - break; - } - return CompilerType(); + case clang::Type::Paren: + return GetVirtualBaseClassAtIndex( + llvm::cast<clang::ParenType>(qual_type)->desugar().getAsOpaquePtr(), + idx, bit_offset_ptr); + default: + break; + } + return CompilerType(); } // If a pointer to a pointee type (the clang_type arg) says that it has no @@ -6250,776 +6156,757 @@ ClangASTContext::GetVirtualBaseClassAtIndex (lldb::opaque_compiler_type_t type, // different result. For example, an "int *" has one child that is an integer, // but a function pointer doesn't have any children. Likewise if a Record type // claims it has no children, then there really is nothing to show. -uint32_t -ClangASTContext::GetNumPointeeChildren (clang::QualType type) -{ - if (type.isNull()) - return 0; - - clang::QualType qual_type(type.getCanonicalType()); - const clang::Type::TypeClass type_class = qual_type->getTypeClass(); - switch (type_class) - { - case clang::Type::Builtin: - switch (llvm::cast<clang::BuiltinType>(qual_type)->getKind()) - { - case clang::BuiltinType::UnknownAny: - case clang::BuiltinType::Void: - case clang::BuiltinType::NullPtr: - case clang::BuiltinType::OCLEvent: - case clang::BuiltinType::OCLImage1dRO: - case clang::BuiltinType::OCLImage1dWO: - case clang::BuiltinType::OCLImage1dRW: - case clang::BuiltinType::OCLImage1dArrayRO: - case clang::BuiltinType::OCLImage1dArrayWO: - case clang::BuiltinType::OCLImage1dArrayRW: - case clang::BuiltinType::OCLImage1dBufferRO: - case clang::BuiltinType::OCLImage1dBufferWO: - case clang::BuiltinType::OCLImage1dBufferRW: - case clang::BuiltinType::OCLImage2dRO: - case clang::BuiltinType::OCLImage2dWO: - case clang::BuiltinType::OCLImage2dRW: - case clang::BuiltinType::OCLImage2dArrayRO: - case clang::BuiltinType::OCLImage2dArrayWO: - case clang::BuiltinType::OCLImage2dArrayRW: - case clang::BuiltinType::OCLImage3dRO: - case clang::BuiltinType::OCLImage3dWO: - case clang::BuiltinType::OCLImage3dRW: - case clang::BuiltinType::OCLSampler: - return 0; - case clang::BuiltinType::Bool: - case clang::BuiltinType::Char_U: - case clang::BuiltinType::UChar: - case clang::BuiltinType::WChar_U: - case clang::BuiltinType::Char16: - case clang::BuiltinType::Char32: - case clang::BuiltinType::UShort: - case clang::BuiltinType::UInt: - case clang::BuiltinType::ULong: - case clang::BuiltinType::ULongLong: - case clang::BuiltinType::UInt128: - case clang::BuiltinType::Char_S: - case clang::BuiltinType::SChar: - case clang::BuiltinType::WChar_S: - case clang::BuiltinType::Short: - case clang::BuiltinType::Int: - case clang::BuiltinType::Long: - case clang::BuiltinType::LongLong: - case clang::BuiltinType::Int128: - case clang::BuiltinType::Float: - case clang::BuiltinType::Double: - case clang::BuiltinType::LongDouble: - case clang::BuiltinType::Dependent: - case clang::BuiltinType::Overload: - case clang::BuiltinType::ObjCId: - case clang::BuiltinType::ObjCClass: - case clang::BuiltinType::ObjCSel: - case clang::BuiltinType::BoundMember: - case clang::BuiltinType::Half: - case clang::BuiltinType::ARCUnbridgedCast: - case clang::BuiltinType::PseudoObject: - case clang::BuiltinType::BuiltinFn: - case clang::BuiltinType::OMPArraySection: - return 1; - default: - return 0; - } - break; - - case clang::Type::Complex: return 1; - case clang::Type::Pointer: return 1; - case clang::Type::BlockPointer: return 0; // If block pointers don't have debug info, then no children for them - case clang::Type::LValueReference: return 1; - case clang::Type::RValueReference: return 1; - case clang::Type::MemberPointer: return 0; - case clang::Type::ConstantArray: return 0; - case clang::Type::IncompleteArray: return 0; - case clang::Type::VariableArray: return 0; - case clang::Type::DependentSizedArray: return 0; - case clang::Type::DependentSizedExtVector: return 0; - case clang::Type::Vector: return 0; - case clang::Type::ExtVector: return 0; - case clang::Type::FunctionProto: return 0; // When we function pointers, they have no children... - case clang::Type::FunctionNoProto: return 0; // When we function pointers, they have no children... - case clang::Type::UnresolvedUsing: return 0; - case clang::Type::Paren: return GetNumPointeeChildren (llvm::cast<clang::ParenType>(qual_type)->desugar()); - case clang::Type::Typedef: return GetNumPointeeChildren (llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType()); - case clang::Type::Auto: return GetNumPointeeChildren (llvm::cast<clang::AutoType>(qual_type)->getDeducedType()); - case clang::Type::Elaborated: return GetNumPointeeChildren (llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType()); - case clang::Type::TypeOfExpr: return 0; - case clang::Type::TypeOf: return 0; - case clang::Type::Decltype: return 0; - case clang::Type::Record: return 0; - case clang::Type::Enum: return 1; - case clang::Type::TemplateTypeParm: return 1; - case clang::Type::SubstTemplateTypeParm: return 1; - case clang::Type::TemplateSpecialization: return 1; - case clang::Type::InjectedClassName: return 0; - case clang::Type::DependentName: return 1; - case clang::Type::DependentTemplateSpecialization: return 1; - case clang::Type::ObjCObject: return 0; - case clang::Type::ObjCInterface: return 0; - case clang::Type::ObjCObjectPointer: return 1; - default: - break; - } +uint32_t ClangASTContext::GetNumPointeeChildren(clang::QualType type) { + if (type.isNull()) return 0; -} + clang::QualType qual_type(type.getCanonicalType()); + const clang::Type::TypeClass type_class = qual_type->getTypeClass(); + switch (type_class) { + case clang::Type::Builtin: + switch (llvm::cast<clang::BuiltinType>(qual_type)->getKind()) { + case clang::BuiltinType::UnknownAny: + case clang::BuiltinType::Void: + case clang::BuiltinType::NullPtr: + case clang::BuiltinType::OCLEvent: + case clang::BuiltinType::OCLImage1dRO: + case clang::BuiltinType::OCLImage1dWO: + case clang::BuiltinType::OCLImage1dRW: + case clang::BuiltinType::OCLImage1dArrayRO: + case clang::BuiltinType::OCLImage1dArrayWO: + case clang::BuiltinType::OCLImage1dArrayRW: + case clang::BuiltinType::OCLImage1dBufferRO: + case clang::BuiltinType::OCLImage1dBufferWO: + case clang::BuiltinType::OCLImage1dBufferRW: + case clang::BuiltinType::OCLImage2dRO: + case clang::BuiltinType::OCLImage2dWO: + case clang::BuiltinType::OCLImage2dRW: + case clang::BuiltinType::OCLImage2dArrayRO: + case clang::BuiltinType::OCLImage2dArrayWO: + case clang::BuiltinType::OCLImage2dArrayRW: + case clang::BuiltinType::OCLImage3dRO: + case clang::BuiltinType::OCLImage3dWO: + case clang::BuiltinType::OCLImage3dRW: + case clang::BuiltinType::OCLSampler: + return 0; + case clang::BuiltinType::Bool: + case clang::BuiltinType::Char_U: + case clang::BuiltinType::UChar: + case clang::BuiltinType::WChar_U: + case clang::BuiltinType::Char16: + case clang::BuiltinType::Char32: + case clang::BuiltinType::UShort: + case clang::BuiltinType::UInt: + case clang::BuiltinType::ULong: + case clang::BuiltinType::ULongLong: + case clang::BuiltinType::UInt128: + case clang::BuiltinType::Char_S: + case clang::BuiltinType::SChar: + case clang::BuiltinType::WChar_S: + case clang::BuiltinType::Short: + case clang::BuiltinType::Int: + case clang::BuiltinType::Long: + case clang::BuiltinType::LongLong: + case clang::BuiltinType::Int128: + case clang::BuiltinType::Float: + case clang::BuiltinType::Double: + case clang::BuiltinType::LongDouble: + case clang::BuiltinType::Dependent: + case clang::BuiltinType::Overload: + case clang::BuiltinType::ObjCId: + case clang::BuiltinType::ObjCClass: + case clang::BuiltinType::ObjCSel: + case clang::BuiltinType::BoundMember: + case clang::BuiltinType::Half: + case clang::BuiltinType::ARCUnbridgedCast: + case clang::BuiltinType::PseudoObject: + case clang::BuiltinType::BuiltinFn: + case clang::BuiltinType::OMPArraySection: + return 1; + default: + return 0; + } + break; -CompilerType -ClangASTContext::GetChildCompilerTypeAtIndex (lldb::opaque_compiler_type_t type, - ExecutionContext *exe_ctx, - size_t idx, - bool transparent_pointers, - bool omit_empty_base_classes, - bool ignore_array_bounds, - std::string& child_name, - uint32_t &child_byte_size, - int32_t &child_byte_offset, - uint32_t &child_bitfield_bit_size, - uint32_t &child_bitfield_bit_offset, - bool &child_is_base_class, - bool &child_is_deref_of_parent, - ValueObject *valobj, - uint64_t &language_flags) -{ - if (!type) - return CompilerType(); - - clang::QualType parent_qual_type(GetCanonicalQualType(type)); - const clang::Type::TypeClass parent_type_class = parent_qual_type->getTypeClass(); - child_bitfield_bit_size = 0; - child_bitfield_bit_offset = 0; - child_is_base_class = false; - language_flags = 0; - - const bool idx_is_valid = idx < GetNumChildren (type, omit_empty_base_classes); - uint32_t bit_offset; - switch (parent_type_class) - { - case clang::Type::Builtin: - if (idx_is_valid) - { - switch (llvm::cast<clang::BuiltinType>(parent_qual_type)->getKind()) - { - case clang::BuiltinType::ObjCId: - case clang::BuiltinType::ObjCClass: - child_name = "isa"; - child_byte_size = getASTContext()->getTypeSize(getASTContext()->ObjCBuiltinClassTy) / CHAR_BIT; - return CompilerType (getASTContext(), getASTContext()->ObjCBuiltinClassTy); - - default: - break; - } - } - break; - - case clang::Type::Record: - if (idx_is_valid && GetCompleteType(type)) - { - const clang::RecordType *record_type = llvm::cast<clang::RecordType>(parent_qual_type.getTypePtr()); - const clang::RecordDecl *record_decl = record_type->getDecl(); - assert(record_decl); - const clang::ASTRecordLayout &record_layout = getASTContext()->getASTRecordLayout(record_decl); - uint32_t child_idx = 0; - - const clang::CXXRecordDecl *cxx_record_decl = llvm::dyn_cast<clang::CXXRecordDecl>(record_decl); - if (cxx_record_decl) - { - // We might have base classes to print out first - clang::CXXRecordDecl::base_class_const_iterator base_class, base_class_end; - for (base_class = cxx_record_decl->bases_begin(), base_class_end = cxx_record_decl->bases_end(); - base_class != base_class_end; - ++base_class) - { - const clang::CXXRecordDecl *base_class_decl = nullptr; - - // Skip empty base classes - if (omit_empty_base_classes) - { - base_class_decl = llvm::cast<clang::CXXRecordDecl>(base_class->getType()->getAs<clang::RecordType>()->getDecl()); - if (ClangASTContext::RecordHasFields(base_class_decl) == false) - continue; - } - - if (idx == child_idx) - { - if (base_class_decl == nullptr) - base_class_decl = llvm::cast<clang::CXXRecordDecl>(base_class->getType()->getAs<clang::RecordType>()->getDecl()); - - - if (base_class->isVirtual()) - { - bool handled = false; - if (valobj) - { - Error err; - AddressType addr_type = eAddressTypeInvalid; - lldb::addr_t vtable_ptr_addr = valobj->GetCPPVTableAddress(addr_type); - - if (vtable_ptr_addr != LLDB_INVALID_ADDRESS && addr_type == eAddressTypeLoad) - { - - ExecutionContext exe_ctx (valobj->GetExecutionContextRef()); - Process *process = exe_ctx.GetProcessPtr(); - if (process) - { - clang::VTableContextBase *vtable_ctx = getASTContext()->getVTableContext(); - if (vtable_ctx) - { - if (vtable_ctx->isMicrosoft()) - { - clang::MicrosoftVTableContext *msoft_vtable_ctx = static_cast<clang::MicrosoftVTableContext *>(vtable_ctx); - - if (vtable_ptr_addr) - { - const lldb::addr_t vbtable_ptr_addr = vtable_ptr_addr + record_layout.getVBPtrOffset().getQuantity(); - - const lldb::addr_t vbtable_ptr = process->ReadPointerFromMemory(vbtable_ptr_addr, err); - if (vbtable_ptr != LLDB_INVALID_ADDRESS) - { - // Get the index into the virtual base table. The index is the index in uint32_t from vbtable_ptr - const unsigned vbtable_index = msoft_vtable_ctx->getVBTableIndex(cxx_record_decl, base_class_decl); - const lldb::addr_t base_offset_addr = vbtable_ptr + vbtable_index * 4; - const uint32_t base_offset = process->ReadUnsignedIntegerFromMemory(base_offset_addr, 4, UINT32_MAX, err); - if (base_offset != UINT32_MAX) - { - handled = true; - bit_offset = base_offset * 8; - } - } - } - } - else - { - clang::ItaniumVTableContext *itanium_vtable_ctx = static_cast<clang::ItaniumVTableContext *>(vtable_ctx); - if (vtable_ptr_addr) - { - const lldb::addr_t vtable_ptr = process->ReadPointerFromMemory(vtable_ptr_addr, err); - if (vtable_ptr != LLDB_INVALID_ADDRESS) - { - clang::CharUnits base_offset_offset = itanium_vtable_ctx->getVirtualBaseOffsetOffset(cxx_record_decl, base_class_decl); - const lldb::addr_t base_offset_addr = vtable_ptr + base_offset_offset.getQuantity(); - const uint32_t base_offset_size = process->GetAddressByteSize(); - const uint64_t base_offset = process->ReadUnsignedIntegerFromMemory(base_offset_addr, base_offset_size, UINT32_MAX, err); - if (base_offset < UINT32_MAX) - { - handled = true; - bit_offset = base_offset * 8; - } - } - } - } - } - } - } - - } - if (!handled) - bit_offset = record_layout.getVBaseClassOffset(base_class_decl).getQuantity() * 8; - } - else - bit_offset = record_layout.getBaseClassOffset(base_class_decl).getQuantity() * 8; - - // Base classes should be a multiple of 8 bits in size - child_byte_offset = bit_offset/8; - CompilerType base_class_clang_type(getASTContext(), base_class->getType()); - child_name = base_class_clang_type.GetTypeName().AsCString(""); - uint64_t base_class_clang_type_bit_size = base_class_clang_type.GetBitSize(exe_ctx ? exe_ctx->GetBestExecutionContextScope() : NULL); - - // Base classes bit sizes should be a multiple of 8 bits in size - assert (base_class_clang_type_bit_size % 8 == 0); - child_byte_size = base_class_clang_type_bit_size / 8; - child_is_base_class = true; - return base_class_clang_type; - } - // We don't increment the child index in the for loop since we might - // be skipping empty base classes - ++child_idx; - } - } - // Make sure index is in range... - uint32_t field_idx = 0; - clang::RecordDecl::field_iterator field, field_end; - for (field = record_decl->field_begin(), field_end = record_decl->field_end(); field != field_end; ++field, ++field_idx, ++child_idx) - { - if (idx == child_idx) - { - // Print the member type if requested - // Print the member name and equal sign - child_name.assign(field->getNameAsString().c_str()); - - // Figure out the type byte size (field_type_info.first) and - // alignment (field_type_info.second) from the AST context. - CompilerType field_clang_type (getASTContext(), field->getType()); - assert(field_idx < record_layout.getFieldCount()); - child_byte_size = field_clang_type.GetByteSize(exe_ctx ? exe_ctx->GetBestExecutionContextScope() : NULL); - const uint32_t child_bit_size = child_byte_size * 8; - - // Figure out the field offset within the current struct/union/class type - bit_offset = record_layout.getFieldOffset (field_idx); - if (ClangASTContext::FieldIsBitfield (getASTContext(), *field, child_bitfield_bit_size)) - { - child_bitfield_bit_offset = bit_offset % child_bit_size; - const uint32_t child_bit_offset = bit_offset - child_bitfield_bit_offset; - child_byte_offset = child_bit_offset / 8; - } - else - { - child_byte_offset = bit_offset / 8; - } - - return field_clang_type; - } - } - } - break; - - case clang::Type::ObjCObject: - case clang::Type::ObjCInterface: - if (idx_is_valid && GetCompleteType(type)) - { - const clang::ObjCObjectType *objc_class_type = llvm::dyn_cast<clang::ObjCObjectType>(parent_qual_type.getTypePtr()); - assert (objc_class_type); - if (objc_class_type) - { - uint32_t child_idx = 0; - clang::ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface(); - - if (class_interface_decl) - { - - const clang::ASTRecordLayout &interface_layout = getASTContext()->getASTObjCInterfaceLayout(class_interface_decl); - clang::ObjCInterfaceDecl *superclass_interface_decl = class_interface_decl->getSuperClass(); - if (superclass_interface_decl) - { - if (omit_empty_base_classes) - { - CompilerType base_class_clang_type (getASTContext(), getASTContext()->getObjCInterfaceType(superclass_interface_decl)); - if (base_class_clang_type.GetNumChildren(omit_empty_base_classes) > 0) - { - if (idx == 0) - { - clang::QualType ivar_qual_type(getASTContext()->getObjCInterfaceType(superclass_interface_decl)); - - - child_name.assign(superclass_interface_decl->getNameAsString().c_str()); - - clang::TypeInfo ivar_type_info = getASTContext()->getTypeInfo(ivar_qual_type.getTypePtr()); - - child_byte_size = ivar_type_info.Width / 8; - child_byte_offset = 0; - child_is_base_class = true; - - return CompilerType (getASTContext(), ivar_qual_type); - } - - ++child_idx; - } + case clang::Type::Complex: + return 1; + case clang::Type::Pointer: + return 1; + case clang::Type::BlockPointer: + return 0; // If block pointers don't have debug info, then no children for + // them + case clang::Type::LValueReference: + return 1; + case clang::Type::RValueReference: + return 1; + case clang::Type::MemberPointer: + return 0; + case clang::Type::ConstantArray: + return 0; + case clang::Type::IncompleteArray: + return 0; + case clang::Type::VariableArray: + return 0; + case clang::Type::DependentSizedArray: + return 0; + case clang::Type::DependentSizedExtVector: + return 0; + case clang::Type::Vector: + return 0; + case clang::Type::ExtVector: + return 0; + case clang::Type::FunctionProto: + return 0; // When we function pointers, they have no children... + case clang::Type::FunctionNoProto: + return 0; // When we function pointers, they have no children... + case clang::Type::UnresolvedUsing: + return 0; + case clang::Type::Paren: + return GetNumPointeeChildren( + llvm::cast<clang::ParenType>(qual_type)->desugar()); + case clang::Type::Typedef: + return GetNumPointeeChildren(llvm::cast<clang::TypedefType>(qual_type) + ->getDecl() + ->getUnderlyingType()); + case clang::Type::Auto: + return GetNumPointeeChildren( + llvm::cast<clang::AutoType>(qual_type)->getDeducedType()); + case clang::Type::Elaborated: + return GetNumPointeeChildren( + llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType()); + case clang::Type::TypeOfExpr: + return 0; + case clang::Type::TypeOf: + return 0; + case clang::Type::Decltype: + return 0; + case clang::Type::Record: + return 0; + case clang::Type::Enum: + return 1; + case clang::Type::TemplateTypeParm: + return 1; + case clang::Type::SubstTemplateTypeParm: + return 1; + case clang::Type::TemplateSpecialization: + return 1; + case clang::Type::InjectedClassName: + return 0; + case clang::Type::DependentName: + return 1; + case clang::Type::DependentTemplateSpecialization: + return 1; + case clang::Type::ObjCObject: + return 0; + case clang::Type::ObjCInterface: + return 0; + case clang::Type::ObjCObjectPointer: + return 1; + default: + break; + } + return 0; +} + +CompilerType ClangASTContext::GetChildCompilerTypeAtIndex( + lldb::opaque_compiler_type_t type, ExecutionContext *exe_ctx, size_t idx, + bool transparent_pointers, bool omit_empty_base_classes, + bool ignore_array_bounds, std::string &child_name, + uint32_t &child_byte_size, int32_t &child_byte_offset, + uint32_t &child_bitfield_bit_size, uint32_t &child_bitfield_bit_offset, + bool &child_is_base_class, bool &child_is_deref_of_parent, + ValueObject *valobj, uint64_t &language_flags) { + if (!type) + return CompilerType(); + + clang::QualType parent_qual_type(GetCanonicalQualType(type)); + const clang::Type::TypeClass parent_type_class = + parent_qual_type->getTypeClass(); + child_bitfield_bit_size = 0; + child_bitfield_bit_offset = 0; + child_is_base_class = false; + language_flags = 0; + + const bool idx_is_valid = idx < GetNumChildren(type, omit_empty_base_classes); + uint32_t bit_offset; + switch (parent_type_class) { + case clang::Type::Builtin: + if (idx_is_valid) { + switch (llvm::cast<clang::BuiltinType>(parent_qual_type)->getKind()) { + case clang::BuiltinType::ObjCId: + case clang::BuiltinType::ObjCClass: + child_name = "isa"; + child_byte_size = + getASTContext()->getTypeSize(getASTContext()->ObjCBuiltinClassTy) / + CHAR_BIT; + return CompilerType(getASTContext(), + getASTContext()->ObjCBuiltinClassTy); + + default: + break; + } + } + break; + + case clang::Type::Record: + if (idx_is_valid && GetCompleteType(type)) { + const clang::RecordType *record_type = + llvm::cast<clang::RecordType>(parent_qual_type.getTypePtr()); + const clang::RecordDecl *record_decl = record_type->getDecl(); + assert(record_decl); + const clang::ASTRecordLayout &record_layout = + getASTContext()->getASTRecordLayout(record_decl); + uint32_t child_idx = 0; + + const clang::CXXRecordDecl *cxx_record_decl = + llvm::dyn_cast<clang::CXXRecordDecl>(record_decl); + if (cxx_record_decl) { + // We might have base classes to print out first + clang::CXXRecordDecl::base_class_const_iterator base_class, + base_class_end; + for (base_class = cxx_record_decl->bases_begin(), + base_class_end = cxx_record_decl->bases_end(); + base_class != base_class_end; ++base_class) { + const clang::CXXRecordDecl *base_class_decl = nullptr; + + // Skip empty base classes + if (omit_empty_base_classes) { + base_class_decl = llvm::cast<clang::CXXRecordDecl>( + base_class->getType()->getAs<clang::RecordType>()->getDecl()); + if (ClangASTContext::RecordHasFields(base_class_decl) == false) + continue; + } + + if (idx == child_idx) { + if (base_class_decl == nullptr) + base_class_decl = llvm::cast<clang::CXXRecordDecl>( + base_class->getType()->getAs<clang::RecordType>()->getDecl()); + + if (base_class->isVirtual()) { + bool handled = false; + if (valobj) { + Error err; + AddressType addr_type = eAddressTypeInvalid; + lldb::addr_t vtable_ptr_addr = + valobj->GetCPPVTableAddress(addr_type); + + if (vtable_ptr_addr != LLDB_INVALID_ADDRESS && + addr_type == eAddressTypeLoad) { + + ExecutionContext exe_ctx(valobj->GetExecutionContextRef()); + Process *process = exe_ctx.GetProcessPtr(); + if (process) { + clang::VTableContextBase *vtable_ctx = + getASTContext()->getVTableContext(); + if (vtable_ctx) { + if (vtable_ctx->isMicrosoft()) { + clang::MicrosoftVTableContext *msoft_vtable_ctx = + static_cast<clang::MicrosoftVTableContext *>( + vtable_ctx); + + if (vtable_ptr_addr) { + const lldb::addr_t vbtable_ptr_addr = + vtable_ptr_addr + + record_layout.getVBPtrOffset().getQuantity(); + + const lldb::addr_t vbtable_ptr = + process->ReadPointerFromMemory(vbtable_ptr_addr, + err); + if (vbtable_ptr != LLDB_INVALID_ADDRESS) { + // Get the index into the virtual base table. The + // index is the index in uint32_t from vbtable_ptr + const unsigned vbtable_index = + msoft_vtable_ctx->getVBTableIndex( + cxx_record_decl, base_class_decl); + const lldb::addr_t base_offset_addr = + vbtable_ptr + vbtable_index * 4; + const uint32_t base_offset = + process->ReadUnsignedIntegerFromMemory( + base_offset_addr, 4, UINT32_MAX, err); + if (base_offset != UINT32_MAX) { + handled = true; + bit_offset = base_offset * 8; } - else - ++child_idx; + } } - - const uint32_t superclass_idx = child_idx; - - if (idx < (child_idx + class_interface_decl->ivar_size())) - { - clang::ObjCInterfaceDecl::ivar_iterator ivar_pos, ivar_end = class_interface_decl->ivar_end(); - - for (ivar_pos = class_interface_decl->ivar_begin(); ivar_pos != ivar_end; ++ivar_pos) - { - if (child_idx == idx) - { - clang::ObjCIvarDecl* ivar_decl = *ivar_pos; - - clang::QualType ivar_qual_type(ivar_decl->getType()); - - child_name.assign(ivar_decl->getNameAsString().c_str()); - - clang::TypeInfo ivar_type_info = getASTContext()->getTypeInfo(ivar_qual_type.getTypePtr()); - - child_byte_size = ivar_type_info.Width / 8; - - // Figure out the field offset within the current struct/union/class type - // For ObjC objects, we can't trust the bit offset we get from the Clang AST, since - // that doesn't account for the space taken up by unbacked properties, or from - // the changing size of base classes that are newer than this class. - // So if we have a process around that we can ask about this object, do so. - child_byte_offset = LLDB_INVALID_IVAR_OFFSET; - Process *process = nullptr; - if (exe_ctx) - process = exe_ctx->GetProcessPtr(); - if (process) - { - ObjCLanguageRuntime *objc_runtime = process->GetObjCLanguageRuntime(); - if (objc_runtime != nullptr) - { - CompilerType parent_ast_type (getASTContext(), parent_qual_type); - child_byte_offset = objc_runtime->GetByteOffsetForIvar (parent_ast_type, ivar_decl->getNameAsString().c_str()); - } - } - - // Setting this to UINT32_MAX to make sure we don't compute it twice... - bit_offset = UINT32_MAX; - - if (child_byte_offset == static_cast<int32_t>(LLDB_INVALID_IVAR_OFFSET)) - { - bit_offset = interface_layout.getFieldOffset (child_idx - superclass_idx); - child_byte_offset = bit_offset / 8; - } - - // Note, the ObjC Ivar Byte offset is just that, it doesn't account for the bit offset - // of a bitfield within its containing object. So regardless of where we get the byte - // offset from, we still need to get the bit offset for bitfields from the layout. - - if (ClangASTContext::FieldIsBitfield (getASTContext(), ivar_decl, child_bitfield_bit_size)) - { - if (bit_offset == UINT32_MAX) - bit_offset = interface_layout.getFieldOffset (child_idx - superclass_idx); - - child_bitfield_bit_offset = bit_offset % 8; - } - return CompilerType (getASTContext(), ivar_qual_type); - } - ++child_idx; + } else { + clang::ItaniumVTableContext *itanium_vtable_ctx = + static_cast<clang::ItaniumVTableContext *>( + vtable_ctx); + if (vtable_ptr_addr) { + const lldb::addr_t vtable_ptr = + process->ReadPointerFromMemory(vtable_ptr_addr, + err); + if (vtable_ptr != LLDB_INVALID_ADDRESS) { + clang::CharUnits base_offset_offset = + itanium_vtable_ctx->getVirtualBaseOffsetOffset( + cxx_record_decl, base_class_decl); + const lldb::addr_t base_offset_addr = + vtable_ptr + base_offset_offset.getQuantity(); + const uint32_t base_offset_size = + process->GetAddressByteSize(); + const uint64_t base_offset = + process->ReadUnsignedIntegerFromMemory( + base_offset_addr, base_offset_size, + UINT32_MAX, err); + if (base_offset < UINT32_MAX) { + handled = true; + bit_offset = base_offset * 8; } + } } + } } + } } - } - break; - - case clang::Type::ObjCObjectPointer: - if (idx_is_valid) - { - CompilerType pointee_clang_type (GetPointeeType(type)); - - if (transparent_pointers && pointee_clang_type.IsAggregateType()) - { - child_is_deref_of_parent = false; - bool tmp_child_is_deref_of_parent = false; - return pointee_clang_type.GetChildCompilerTypeAtIndex (exe_ctx, - idx, - transparent_pointers, - omit_empty_base_classes, - ignore_array_bounds, - child_name, - child_byte_size, - child_byte_offset, - child_bitfield_bit_size, - child_bitfield_bit_offset, - child_is_base_class, - tmp_child_is_deref_of_parent, - valobj, - language_flags); - } - else - { - child_is_deref_of_parent = true; - const char *parent_name = valobj ? valobj->GetName().GetCString() : NULL; - if (parent_name) - { - child_name.assign(1, '*'); - child_name += parent_name; - } - - // We have a pointer to an simple type - if (idx == 0 && pointee_clang_type.GetCompleteType()) - { - child_byte_size = pointee_clang_type.GetByteSize(exe_ctx ? exe_ctx->GetBestExecutionContextScope() : NULL); - child_byte_offset = 0; - return pointee_clang_type; - } - } - } - break; - - case clang::Type::Vector: - case clang::Type::ExtVector: - if (idx_is_valid) - { - const clang::VectorType *array = llvm::cast<clang::VectorType>(parent_qual_type.getTypePtr()); - if (array) - { - CompilerType element_type (getASTContext(), array->getElementType()); - if (element_type.GetCompleteType()) - { - char element_name[64]; - ::snprintf (element_name, sizeof (element_name), "[%" PRIu64 "]", static_cast<uint64_t>(idx)); - child_name.assign(element_name); - child_byte_size = element_type.GetByteSize(exe_ctx ? exe_ctx->GetBestExecutionContextScope() : NULL); - child_byte_offset = (int32_t)idx * (int32_t)child_byte_size; - return element_type; - } - } - } - break; - - case clang::Type::ConstantArray: - case clang::Type::IncompleteArray: - if (ignore_array_bounds || idx_is_valid) - { - const clang::ArrayType *array = GetQualType(type)->getAsArrayTypeUnsafe(); - if (array) - { - CompilerType element_type (getASTContext(), array->getElementType()); - if (element_type.GetCompleteType()) - { - char element_name[64]; - ::snprintf (element_name, sizeof (element_name), "[%" PRIu64 "]", static_cast<uint64_t>(idx)); - child_name.assign(element_name); - child_byte_size = element_type.GetByteSize(exe_ctx ? exe_ctx->GetBestExecutionContextScope() : NULL); - child_byte_offset = (int32_t)idx * (int32_t)child_byte_size; - return element_type; - } - } - } - break; - - - case clang::Type::Pointer: - if (idx_is_valid) - { - CompilerType pointee_clang_type (GetPointeeType(type)); - - // Don't dereference "void *" pointers - if (pointee_clang_type.IsVoidType()) - return CompilerType(); - - if (transparent_pointers && pointee_clang_type.IsAggregateType ()) - { - child_is_deref_of_parent = false; - bool tmp_child_is_deref_of_parent = false; - return pointee_clang_type.GetChildCompilerTypeAtIndex (exe_ctx, - idx, - transparent_pointers, - omit_empty_base_classes, - ignore_array_bounds, - child_name, - child_byte_size, - child_byte_offset, - child_bitfield_bit_size, - child_bitfield_bit_offset, - child_is_base_class, - tmp_child_is_deref_of_parent, - valobj, - language_flags); + } + if (!handled) + bit_offset = record_layout.getVBaseClassOffset(base_class_decl) + .getQuantity() * + 8; + } else + bit_offset = record_layout.getBaseClassOffset(base_class_decl) + .getQuantity() * + 8; + + // Base classes should be a multiple of 8 bits in size + child_byte_offset = bit_offset / 8; + CompilerType base_class_clang_type(getASTContext(), + base_class->getType()); + child_name = base_class_clang_type.GetTypeName().AsCString(""); + uint64_t base_class_clang_type_bit_size = + base_class_clang_type.GetBitSize( + exe_ctx ? exe_ctx->GetBestExecutionContextScope() : NULL); + + // Base classes bit sizes should be a multiple of 8 bits in size + assert(base_class_clang_type_bit_size % 8 == 0); + child_byte_size = base_class_clang_type_bit_size / 8; + child_is_base_class = true; + return base_class_clang_type; + } + // We don't increment the child index in the for loop since we might + // be skipping empty base classes + ++child_idx; + } + } + // Make sure index is in range... + uint32_t field_idx = 0; + clang::RecordDecl::field_iterator field, field_end; + for (field = record_decl->field_begin(), + field_end = record_decl->field_end(); + field != field_end; ++field, ++field_idx, ++child_idx) { + if (idx == child_idx) { + // Print the member type if requested + // Print the member name and equal sign + child_name.assign(field->getNameAsString().c_str()); + + // Figure out the type byte size (field_type_info.first) and + // alignment (field_type_info.second) from the AST context. + CompilerType field_clang_type(getASTContext(), field->getType()); + assert(field_idx < record_layout.getFieldCount()); + child_byte_size = field_clang_type.GetByteSize( + exe_ctx ? exe_ctx->GetBestExecutionContextScope() : NULL); + const uint32_t child_bit_size = child_byte_size * 8; + + // Figure out the field offset within the current struct/union/class + // type + bit_offset = record_layout.getFieldOffset(field_idx); + if (ClangASTContext::FieldIsBitfield(getASTContext(), *field, + child_bitfield_bit_size)) { + child_bitfield_bit_offset = bit_offset % child_bit_size; + const uint32_t child_bit_offset = + bit_offset - child_bitfield_bit_offset; + child_byte_offset = child_bit_offset / 8; + } else { + child_byte_offset = bit_offset / 8; + } + + return field_clang_type; + } + } + } + break; + + case clang::Type::ObjCObject: + case clang::Type::ObjCInterface: + if (idx_is_valid && GetCompleteType(type)) { + const clang::ObjCObjectType *objc_class_type = + llvm::dyn_cast<clang::ObjCObjectType>(parent_qual_type.getTypePtr()); + assert(objc_class_type); + if (objc_class_type) { + uint32_t child_idx = 0; + clang::ObjCInterfaceDecl *class_interface_decl = + objc_class_type->getInterface(); + + if (class_interface_decl) { + + const clang::ASTRecordLayout &interface_layout = + getASTContext()->getASTObjCInterfaceLayout(class_interface_decl); + clang::ObjCInterfaceDecl *superclass_interface_decl = + class_interface_decl->getSuperClass(); + if (superclass_interface_decl) { + if (omit_empty_base_classes) { + CompilerType base_class_clang_type( + getASTContext(), getASTContext()->getObjCInterfaceType( + superclass_interface_decl)); + if (base_class_clang_type.GetNumChildren( + omit_empty_base_classes) > 0) { + if (idx == 0) { + clang::QualType ivar_qual_type( + getASTContext()->getObjCInterfaceType( + superclass_interface_decl)); + + child_name.assign( + superclass_interface_decl->getNameAsString().c_str()); + + clang::TypeInfo ivar_type_info = + getASTContext()->getTypeInfo(ivar_qual_type.getTypePtr()); + + child_byte_size = ivar_type_info.Width / 8; + child_byte_offset = 0; + child_is_base_class = true; + + return CompilerType(getASTContext(), ivar_qual_type); } - else - { - child_is_deref_of_parent = true; - - const char *parent_name = valobj ? valobj->GetName().GetCString() : NULL; - if (parent_name) - { - child_name.assign(1, '*'); - child_name += parent_name; - } - - // We have a pointer to an simple type - if (idx == 0) - { - child_byte_size = pointee_clang_type.GetByteSize(exe_ctx ? exe_ctx->GetBestExecutionContextScope() : NULL); - child_byte_offset = 0; - return pointee_clang_type; - } + + ++child_idx; + } + } else + ++child_idx; + } + + const uint32_t superclass_idx = child_idx; + + if (idx < (child_idx + class_interface_decl->ivar_size())) { + clang::ObjCInterfaceDecl::ivar_iterator ivar_pos, + ivar_end = class_interface_decl->ivar_end(); + + for (ivar_pos = class_interface_decl->ivar_begin(); + ivar_pos != ivar_end; ++ivar_pos) { + if (child_idx == idx) { + clang::ObjCIvarDecl *ivar_decl = *ivar_pos; + + clang::QualType ivar_qual_type(ivar_decl->getType()); + + child_name.assign(ivar_decl->getNameAsString().c_str()); + + clang::TypeInfo ivar_type_info = + getASTContext()->getTypeInfo(ivar_qual_type.getTypePtr()); + + child_byte_size = ivar_type_info.Width / 8; + + // Figure out the field offset within the current + // struct/union/class type + // For ObjC objects, we can't trust the bit offset we get from + // the Clang AST, since + // that doesn't account for the space taken up by unbacked + // properties, or from + // the changing size of base classes that are newer than this + // class. + // So if we have a process around that we can ask about this + // object, do so. + child_byte_offset = LLDB_INVALID_IVAR_OFFSET; + Process *process = nullptr; + if (exe_ctx) + process = exe_ctx->GetProcessPtr(); + if (process) { + ObjCLanguageRuntime *objc_runtime = + process->GetObjCLanguageRuntime(); + if (objc_runtime != nullptr) { + CompilerType parent_ast_type(getASTContext(), + parent_qual_type); + child_byte_offset = objc_runtime->GetByteOffsetForIvar( + parent_ast_type, ivar_decl->getNameAsString().c_str()); + } } - } - break; - - case clang::Type::LValueReference: - case clang::Type::RValueReference: - if (idx_is_valid) - { - const clang::ReferenceType *reference_type = llvm::cast<clang::ReferenceType>(parent_qual_type.getTypePtr()); - CompilerType pointee_clang_type (getASTContext(), reference_type->getPointeeType()); - if (transparent_pointers && pointee_clang_type.IsAggregateType ()) - { - child_is_deref_of_parent = false; - bool tmp_child_is_deref_of_parent = false; - return pointee_clang_type.GetChildCompilerTypeAtIndex (exe_ctx, - idx, - transparent_pointers, - omit_empty_base_classes, - ignore_array_bounds, - child_name, - child_byte_size, - child_byte_offset, - child_bitfield_bit_size, - child_bitfield_bit_offset, - child_is_base_class, - tmp_child_is_deref_of_parent, - valobj, - language_flags); + + // Setting this to UINT32_MAX to make sure we don't compute it + // twice... + bit_offset = UINT32_MAX; + + if (child_byte_offset == + static_cast<int32_t>(LLDB_INVALID_IVAR_OFFSET)) { + bit_offset = interface_layout.getFieldOffset(child_idx - + superclass_idx); + child_byte_offset = bit_offset / 8; } - else - { - const char *parent_name = valobj ? valobj->GetName().GetCString() : NULL; - if (parent_name) - { - child_name.assign(1, '&'); - child_name += parent_name; - } - - // We have a pointer to an simple type - if (idx == 0) - { - child_byte_size = pointee_clang_type.GetByteSize(exe_ctx ? exe_ctx->GetBestExecutionContextScope() : NULL); - child_byte_offset = 0; - return pointee_clang_type; - } + + // Note, the ObjC Ivar Byte offset is just that, it doesn't + // account for the bit offset + // of a bitfield within its containing object. So regardless of + // where we get the byte + // offset from, we still need to get the bit offset for + // bitfields from the layout. + + if (ClangASTContext::FieldIsBitfield(getASTContext(), ivar_decl, + child_bitfield_bit_size)) { + if (bit_offset == UINT32_MAX) + bit_offset = interface_layout.getFieldOffset( + child_idx - superclass_idx); + + child_bitfield_bit_offset = bit_offset % 8; } + return CompilerType(getASTContext(), ivar_qual_type); + } + ++child_idx; } - break; - - case clang::Type::Typedef: - { - CompilerType typedefed_clang_type (getASTContext(), llvm::cast<clang::TypedefType>(parent_qual_type)->getDecl()->getUnderlyingType()); - return typedefed_clang_type.GetChildCompilerTypeAtIndex (exe_ctx, - idx, - transparent_pointers, - omit_empty_base_classes, - ignore_array_bounds, - child_name, - child_byte_size, - child_byte_offset, - child_bitfield_bit_size, - child_bitfield_bit_offset, - child_is_base_class, - child_is_deref_of_parent, - valobj, - language_flags); + } } - break; - - case clang::Type::Auto: - { - CompilerType elaborated_clang_type (getASTContext(), llvm::cast<clang::AutoType>(parent_qual_type)->getDeducedType()); - return elaborated_clang_type.GetChildCompilerTypeAtIndex (exe_ctx, - idx, - transparent_pointers, - omit_empty_base_classes, - ignore_array_bounds, - child_name, - child_byte_size, - child_byte_offset, - child_bitfield_bit_size, - child_bitfield_bit_offset, - child_is_base_class, - child_is_deref_of_parent, - valobj, - language_flags); + } + } + break; + + case clang::Type::ObjCObjectPointer: + if (idx_is_valid) { + CompilerType pointee_clang_type(GetPointeeType(type)); + + if (transparent_pointers && pointee_clang_type.IsAggregateType()) { + child_is_deref_of_parent = false; + bool tmp_child_is_deref_of_parent = false; + return pointee_clang_type.GetChildCompilerTypeAtIndex( + exe_ctx, idx, transparent_pointers, omit_empty_base_classes, + ignore_array_bounds, child_name, child_byte_size, child_byte_offset, + child_bitfield_bit_size, child_bitfield_bit_offset, + child_is_base_class, tmp_child_is_deref_of_parent, valobj, + language_flags); + } else { + child_is_deref_of_parent = true; + const char *parent_name = + valobj ? valobj->GetName().GetCString() : NULL; + if (parent_name) { + child_name.assign(1, '*'); + child_name += parent_name; } - - case clang::Type::Elaborated: - { - CompilerType elaborated_clang_type (getASTContext(), llvm::cast<clang::ElaboratedType>(parent_qual_type)->getNamedType()); - return elaborated_clang_type.GetChildCompilerTypeAtIndex (exe_ctx, - idx, - transparent_pointers, - omit_empty_base_classes, - ignore_array_bounds, - child_name, - child_byte_size, - child_byte_offset, - child_bitfield_bit_size, - child_bitfield_bit_offset, - child_is_base_class, - child_is_deref_of_parent, - valobj, - language_flags); + + // We have a pointer to an simple type + if (idx == 0 && pointee_clang_type.GetCompleteType()) { + child_byte_size = pointee_clang_type.GetByteSize( + exe_ctx ? exe_ctx->GetBestExecutionContextScope() : NULL); + child_byte_offset = 0; + return pointee_clang_type; } - - case clang::Type::Paren: - { - CompilerType paren_clang_type (getASTContext(), llvm::cast<clang::ParenType>(parent_qual_type)->desugar()); - return paren_clang_type.GetChildCompilerTypeAtIndex (exe_ctx, - idx, - transparent_pointers, - omit_empty_base_classes, - ignore_array_bounds, - child_name, - child_byte_size, - child_byte_offset, - child_bitfield_bit_size, - child_bitfield_bit_offset, - child_is_base_class, - child_is_deref_of_parent, - valobj, - language_flags); + } + } + break; + + case clang::Type::Vector: + case clang::Type::ExtVector: + if (idx_is_valid) { + const clang::VectorType *array = + llvm::cast<clang::VectorType>(parent_qual_type.getTypePtr()); + if (array) { + CompilerType element_type(getASTContext(), array->getElementType()); + if (element_type.GetCompleteType()) { + char element_name[64]; + ::snprintf(element_name, sizeof(element_name), "[%" PRIu64 "]", + static_cast<uint64_t>(idx)); + child_name.assign(element_name); + child_byte_size = element_type.GetByteSize( + exe_ctx ? exe_ctx->GetBestExecutionContextScope() : NULL); + child_byte_offset = (int32_t)idx * (int32_t)child_byte_size; + return element_type; } - - - default: - break; + } + } + break; + + case clang::Type::ConstantArray: + case clang::Type::IncompleteArray: + if (ignore_array_bounds || idx_is_valid) { + const clang::ArrayType *array = GetQualType(type)->getAsArrayTypeUnsafe(); + if (array) { + CompilerType element_type(getASTContext(), array->getElementType()); + if (element_type.GetCompleteType()) { + char element_name[64]; + ::snprintf(element_name, sizeof(element_name), "[%" PRIu64 "]", + static_cast<uint64_t>(idx)); + child_name.assign(element_name); + child_byte_size = element_type.GetByteSize( + exe_ctx ? exe_ctx->GetBestExecutionContextScope() : NULL); + child_byte_offset = (int32_t)idx * (int32_t)child_byte_size; + return element_type; + } + } } - return CompilerType(); -} + break; -static uint32_t -GetIndexForRecordBase -( - const clang::RecordDecl *record_decl, - const clang::CXXBaseSpecifier *base_spec, - bool omit_empty_base_classes - ) -{ - uint32_t child_idx = 0; - - const clang::CXXRecordDecl *cxx_record_decl = llvm::dyn_cast<clang::CXXRecordDecl>(record_decl); - - // const char *super_name = record_decl->getNameAsCString(); - // const char *base_name = base_spec->getType()->getAs<clang::RecordType>()->getDecl()->getNameAsCString(); - // printf ("GetIndexForRecordChild (%s, %s)\n", super_name, base_name); - // - if (cxx_record_decl) - { - clang::CXXRecordDecl::base_class_const_iterator base_class, base_class_end; - for (base_class = cxx_record_decl->bases_begin(), base_class_end = cxx_record_decl->bases_end(); - base_class != base_class_end; - ++base_class) - { - if (omit_empty_base_classes) - { - if (BaseSpecifierIsEmpty (base_class)) - continue; - } - - // printf ("GetIndexForRecordChild (%s, %s) base[%u] = %s\n", super_name, base_name, - // child_idx, - // base_class->getType()->getAs<clang::RecordType>()->getDecl()->getNameAsCString()); - // - // - if (base_class == base_spec) - return child_idx; - ++child_idx; + case clang::Type::Pointer: + if (idx_is_valid) { + CompilerType pointee_clang_type(GetPointeeType(type)); + + // Don't dereference "void *" pointers + if (pointee_clang_type.IsVoidType()) + return CompilerType(); + + if (transparent_pointers && pointee_clang_type.IsAggregateType()) { + child_is_deref_of_parent = false; + bool tmp_child_is_deref_of_parent = false; + return pointee_clang_type.GetChildCompilerTypeAtIndex( + exe_ctx, idx, transparent_pointers, omit_empty_base_classes, + ignore_array_bounds, child_name, child_byte_size, child_byte_offset, + child_bitfield_bit_size, child_bitfield_bit_offset, + child_is_base_class, tmp_child_is_deref_of_parent, valobj, + language_flags); + } else { + child_is_deref_of_parent = true; + + const char *parent_name = + valobj ? valobj->GetName().GetCString() : NULL; + if (parent_name) { + child_name.assign(1, '*'); + child_name += parent_name; } - } - - return UINT32_MAX; -} + // We have a pointer to an simple type + if (idx == 0) { + child_byte_size = pointee_clang_type.GetByteSize( + exe_ctx ? exe_ctx->GetBestExecutionContextScope() : NULL); + child_byte_offset = 0; + return pointee_clang_type; + } + } + } + break; + + case clang::Type::LValueReference: + case clang::Type::RValueReference: + if (idx_is_valid) { + const clang::ReferenceType *reference_type = + llvm::cast<clang::ReferenceType>(parent_qual_type.getTypePtr()); + CompilerType pointee_clang_type(getASTContext(), + reference_type->getPointeeType()); + if (transparent_pointers && pointee_clang_type.IsAggregateType()) { + child_is_deref_of_parent = false; + bool tmp_child_is_deref_of_parent = false; + return pointee_clang_type.GetChildCompilerTypeAtIndex( + exe_ctx, idx, transparent_pointers, omit_empty_base_classes, + ignore_array_bounds, child_name, child_byte_size, child_byte_offset, + child_bitfield_bit_size, child_bitfield_bit_offset, + child_is_base_class, tmp_child_is_deref_of_parent, valobj, + language_flags); + } else { + const char *parent_name = + valobj ? valobj->GetName().GetCString() : NULL; + if (parent_name) { + child_name.assign(1, '&'); + child_name += parent_name; + } -static uint32_t -GetIndexForRecordChild (const clang::RecordDecl *record_decl, - clang::NamedDecl *canonical_decl, - bool omit_empty_base_classes) -{ - uint32_t child_idx = ClangASTContext::GetNumBaseClasses (llvm::dyn_cast<clang::CXXRecordDecl>(record_decl), - omit_empty_base_classes); - - clang::RecordDecl::field_iterator field, field_end; - for (field = record_decl->field_begin(), field_end = record_decl->field_end(); - field != field_end; - ++field, ++child_idx) - { - if (field->getCanonicalDecl() == canonical_decl) - return child_idx; - } - - return UINT32_MAX; + // We have a pointer to an simple type + if (idx == 0) { + child_byte_size = pointee_clang_type.GetByteSize( + exe_ctx ? exe_ctx->GetBestExecutionContextScope() : NULL); + child_byte_offset = 0; + return pointee_clang_type; + } + } + } + break; + + case clang::Type::Typedef: { + CompilerType typedefed_clang_type( + getASTContext(), llvm::cast<clang::TypedefType>(parent_qual_type) + ->getDecl() + ->getUnderlyingType()); + return typedefed_clang_type.GetChildCompilerTypeAtIndex( + exe_ctx, idx, transparent_pointers, omit_empty_base_classes, + ignore_array_bounds, child_name, child_byte_size, child_byte_offset, + child_bitfield_bit_size, child_bitfield_bit_offset, child_is_base_class, + child_is_deref_of_parent, valobj, language_flags); + } break; + + case clang::Type::Auto: { + CompilerType elaborated_clang_type( + getASTContext(), + llvm::cast<clang::AutoType>(parent_qual_type)->getDeducedType()); + return elaborated_clang_type.GetChildCompilerTypeAtIndex( + exe_ctx, idx, transparent_pointers, omit_empty_base_classes, + ignore_array_bounds, child_name, child_byte_size, child_byte_offset, + child_bitfield_bit_size, child_bitfield_bit_offset, child_is_base_class, + child_is_deref_of_parent, valobj, language_flags); + } + + case clang::Type::Elaborated: { + CompilerType elaborated_clang_type( + getASTContext(), + llvm::cast<clang::ElaboratedType>(parent_qual_type)->getNamedType()); + return elaborated_clang_type.GetChildCompilerTypeAtIndex( + exe_ctx, idx, transparent_pointers, omit_empty_base_classes, + ignore_array_bounds, child_name, child_byte_size, child_byte_offset, + child_bitfield_bit_size, child_bitfield_bit_offset, child_is_base_class, + child_is_deref_of_parent, valobj, language_flags); + } + + case clang::Type::Paren: { + CompilerType paren_clang_type( + getASTContext(), + llvm::cast<clang::ParenType>(parent_qual_type)->desugar()); + return paren_clang_type.GetChildCompilerTypeAtIndex( + exe_ctx, idx, transparent_pointers, omit_empty_base_classes, + ignore_array_bounds, child_name, child_byte_size, child_byte_offset, + child_bitfield_bit_size, child_bitfield_bit_offset, child_is_base_class, + child_is_deref_of_parent, valobj, language_flags); + } + + default: + break; + } + return CompilerType(); +} + +static uint32_t GetIndexForRecordBase(const clang::RecordDecl *record_decl, + const clang::CXXBaseSpecifier *base_spec, + bool omit_empty_base_classes) { + uint32_t child_idx = 0; + + const clang::CXXRecordDecl *cxx_record_decl = + llvm::dyn_cast<clang::CXXRecordDecl>(record_decl); + + // const char *super_name = record_decl->getNameAsCString(); + // const char *base_name = + // base_spec->getType()->getAs<clang::RecordType>()->getDecl()->getNameAsCString(); + // printf ("GetIndexForRecordChild (%s, %s)\n", super_name, base_name); + // + if (cxx_record_decl) { + clang::CXXRecordDecl::base_class_const_iterator base_class, base_class_end; + for (base_class = cxx_record_decl->bases_begin(), + base_class_end = cxx_record_decl->bases_end(); + base_class != base_class_end; ++base_class) { + if (omit_empty_base_classes) { + if (BaseSpecifierIsEmpty(base_class)) + continue; + } + + // printf ("GetIndexForRecordChild (%s, %s) base[%u] = %s\n", + // super_name, base_name, + // child_idx, + // base_class->getType()->getAs<clang::RecordType>()->getDecl()->getNameAsCString()); + // + // + if (base_class == base_spec) + return child_idx; + ++child_idx; + } + } + + return UINT32_MAX; +} + +static uint32_t GetIndexForRecordChild(const clang::RecordDecl *record_decl, + clang::NamedDecl *canonical_decl, + bool omit_empty_base_classes) { + uint32_t child_idx = ClangASTContext::GetNumBaseClasses( + llvm::dyn_cast<clang::CXXRecordDecl>(record_decl), + omit_empty_base_classes); + + clang::RecordDecl::field_iterator field, field_end; + for (field = record_decl->field_begin(), field_end = record_decl->field_end(); + field != field_end; ++field, ++child_idx) { + if (field->getCanonicalDecl() == canonical_decl) + return child_idx; + } + + return UINT32_MAX; } // Look for a child member (doesn't include base classes, but it does include @@ -7046,2859 +6933,2849 @@ GetIndexForRecordChild (const clang::RecordDecl *record_decl, // If we have a clang type that describes "class C", and we wanted to looked // "m_b" in it: // -// With omit_empty_base_classes == false we would get an integer array back with: +// With omit_empty_base_classes == false we would get an integer array back +// with: // { 1, 1 } // The first index 1 is the child index for "class A" within class C // The second index 1 is the child index for "m_b" within class A // // With omit_empty_base_classes == true we would get an integer array back with: // { 0, 1 } -// The first index 0 is the child index for "class A" within class C (since class B doesn't have any members it doesn't count) +// The first index 0 is the child index for "class A" within class C (since +// class B doesn't have any members it doesn't count) // The second index 1 is the child index for "m_b" within class A -size_t -ClangASTContext::GetIndexOfChildMemberWithName (lldb::opaque_compiler_type_t type, const char *name, - bool omit_empty_base_classes, - std::vector<uint32_t>& child_indexes) -{ - if (type && name && name[0]) - { - clang::QualType qual_type(GetCanonicalQualType(type)); - const clang::Type::TypeClass type_class = qual_type->getTypeClass(); - switch (type_class) - { - case clang::Type::Record: - if (GetCompleteType(type)) - { - const clang::RecordType *record_type = llvm::cast<clang::RecordType>(qual_type.getTypePtr()); - const clang::RecordDecl *record_decl = record_type->getDecl(); - - assert(record_decl); - uint32_t child_idx = 0; - - const clang::CXXRecordDecl *cxx_record_decl = llvm::dyn_cast<clang::CXXRecordDecl>(record_decl); - - // Try and find a field that matches NAME - clang::RecordDecl::field_iterator field, field_end; - llvm::StringRef name_sref(name); - for (field = record_decl->field_begin(), field_end = record_decl->field_end(); - field != field_end; - ++field, ++child_idx) - { - llvm::StringRef field_name = field->getName(); - if (field_name.empty()) - { - CompilerType field_type(getASTContext(),field->getType()); - child_indexes.push_back(child_idx); - if (field_type.GetIndexOfChildMemberWithName(name, omit_empty_base_classes, child_indexes)) - return child_indexes.size(); - child_indexes.pop_back(); - - } - else if (field_name.equals (name_sref)) - { - // We have to add on the number of base classes to this index! - child_indexes.push_back (child_idx + ClangASTContext::GetNumBaseClasses (cxx_record_decl, omit_empty_base_classes)); - return child_indexes.size(); - } - } - - if (cxx_record_decl) - { - const clang::RecordDecl *parent_record_decl = cxx_record_decl; - - //printf ("parent = %s\n", parent_record_decl->getNameAsCString()); - - //const Decl *root_cdecl = cxx_record_decl->getCanonicalDecl(); - // Didn't find things easily, lets let clang do its thang... - clang::IdentifierInfo & ident_ref = getASTContext()->Idents.get(name_sref); - clang::DeclarationName decl_name(&ident_ref); - - clang::CXXBasePaths paths; - if (cxx_record_decl->lookupInBases([decl_name](const clang::CXXBaseSpecifier *specifier, clang::CXXBasePath &path) { - return clang::CXXRecordDecl::FindOrdinaryMember(specifier, path, decl_name); - }, - paths)) - { - clang::CXXBasePaths::const_paths_iterator path, path_end = paths.end(); - for (path = paths.begin(); path != path_end; ++path) - { - const size_t num_path_elements = path->size(); - for (size_t e=0; e<num_path_elements; ++e) - { - clang::CXXBasePathElement elem = (*path)[e]; - - child_idx = GetIndexForRecordBase (parent_record_decl, elem.Base, omit_empty_base_classes); - if (child_idx == UINT32_MAX) - { - child_indexes.clear(); - return 0; - } - else - { - child_indexes.push_back (child_idx); - parent_record_decl = llvm::cast<clang::RecordDecl>(elem.Base->getType()->getAs<clang::RecordType>()->getDecl()); - } - } - for (clang::NamedDecl *path_decl : path->Decls) - { - child_idx = GetIndexForRecordChild (parent_record_decl, path_decl, omit_empty_base_classes); - if (child_idx == UINT32_MAX) - { - child_indexes.clear(); - return 0; - } - else - { - child_indexes.push_back (child_idx); - } - } - } - return child_indexes.size(); - } - } - +size_t ClangASTContext::GetIndexOfChildMemberWithName( + lldb::opaque_compiler_type_t type, const char *name, + bool omit_empty_base_classes, std::vector<uint32_t> &child_indexes) { + if (type && name && name[0]) { + clang::QualType qual_type(GetCanonicalQualType(type)); + const clang::Type::TypeClass type_class = qual_type->getTypeClass(); + switch (type_class) { + case clang::Type::Record: + if (GetCompleteType(type)) { + const clang::RecordType *record_type = + llvm::cast<clang::RecordType>(qual_type.getTypePtr()); + const clang::RecordDecl *record_decl = record_type->getDecl(); + + assert(record_decl); + uint32_t child_idx = 0; + + const clang::CXXRecordDecl *cxx_record_decl = + llvm::dyn_cast<clang::CXXRecordDecl>(record_decl); + + // Try and find a field that matches NAME + clang::RecordDecl::field_iterator field, field_end; + llvm::StringRef name_sref(name); + for (field = record_decl->field_begin(), + field_end = record_decl->field_end(); + field != field_end; ++field, ++child_idx) { + llvm::StringRef field_name = field->getName(); + if (field_name.empty()) { + CompilerType field_type(getASTContext(), field->getType()); + child_indexes.push_back(child_idx); + if (field_type.GetIndexOfChildMemberWithName( + name, omit_empty_base_classes, child_indexes)) + return child_indexes.size(); + child_indexes.pop_back(); + + } else if (field_name.equals(name_sref)) { + // We have to add on the number of base classes to this index! + child_indexes.push_back( + child_idx + ClangASTContext::GetNumBaseClasses( + cxx_record_decl, omit_empty_base_classes)); + return child_indexes.size(); + } + } + + if (cxx_record_decl) { + const clang::RecordDecl *parent_record_decl = cxx_record_decl; + + // printf ("parent = %s\n", parent_record_decl->getNameAsCString()); + + // const Decl *root_cdecl = cxx_record_decl->getCanonicalDecl(); + // Didn't find things easily, lets let clang do its thang... + clang::IdentifierInfo &ident_ref = + getASTContext()->Idents.get(name_sref); + clang::DeclarationName decl_name(&ident_ref); + + clang::CXXBasePaths paths; + if (cxx_record_decl->lookupInBases( + [decl_name](const clang::CXXBaseSpecifier *specifier, + clang::CXXBasePath &path) { + return clang::CXXRecordDecl::FindOrdinaryMember( + specifier, path, decl_name); + }, + paths)) { + clang::CXXBasePaths::const_paths_iterator path, + path_end = paths.end(); + for (path = paths.begin(); path != path_end; ++path) { + const size_t num_path_elements = path->size(); + for (size_t e = 0; e < num_path_elements; ++e) { + clang::CXXBasePathElement elem = (*path)[e]; + + child_idx = GetIndexForRecordBase(parent_record_decl, elem.Base, + omit_empty_base_classes); + if (child_idx == UINT32_MAX) { + child_indexes.clear(); + return 0; + } else { + child_indexes.push_back(child_idx); + parent_record_decl = llvm::cast<clang::RecordDecl>( + elem.Base->getType() + ->getAs<clang::RecordType>() + ->getDecl()); } - break; - - case clang::Type::ObjCObject: - case clang::Type::ObjCInterface: - if (GetCompleteType(type)) - { - llvm::StringRef name_sref(name); - const clang::ObjCObjectType *objc_class_type = llvm::dyn_cast<clang::ObjCObjectType>(qual_type.getTypePtr()); - assert (objc_class_type); - if (objc_class_type) - { - uint32_t child_idx = 0; - clang::ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface(); - - if (class_interface_decl) - { - clang::ObjCInterfaceDecl::ivar_iterator ivar_pos, ivar_end = class_interface_decl->ivar_end(); - clang::ObjCInterfaceDecl *superclass_interface_decl = class_interface_decl->getSuperClass(); - - for (ivar_pos = class_interface_decl->ivar_begin(); ivar_pos != ivar_end; ++ivar_pos, ++child_idx) - { - const clang::ObjCIvarDecl* ivar_decl = *ivar_pos; - - if (ivar_decl->getName().equals (name_sref)) - { - if ((!omit_empty_base_classes && superclass_interface_decl) || - ( omit_empty_base_classes && ObjCDeclHasIVars (superclass_interface_decl, true))) - ++child_idx; - - child_indexes.push_back (child_idx); - return child_indexes.size(); - } - } - - if (superclass_interface_decl) - { - // The super class index is always zero for ObjC classes, - // so we push it onto the child indexes in case we find - // an ivar in our superclass... - child_indexes.push_back (0); - - CompilerType superclass_clang_type (getASTContext(), getASTContext()->getObjCInterfaceType(superclass_interface_decl)); - if (superclass_clang_type.GetIndexOfChildMemberWithName (name, - omit_empty_base_classes, - child_indexes)) - { - // We did find an ivar in a superclass so just - // return the results! - return child_indexes.size(); - } - - // We didn't find an ivar matching "name" in our - // superclass, pop the superclass zero index that - // we pushed on above. - child_indexes.pop_back(); - } - } - } + } + for (clang::NamedDecl *path_decl : path->Decls) { + child_idx = GetIndexForRecordChild( + parent_record_decl, path_decl, omit_empty_base_classes); + if (child_idx == UINT32_MAX) { + child_indexes.clear(); + return 0; + } else { + child_indexes.push_back(child_idx); } - break; - - case clang::Type::ObjCObjectPointer: - { - CompilerType objc_object_clang_type (getASTContext(), llvm::cast<clang::ObjCObjectPointerType>(qual_type.getTypePtr())->getPointeeType()); - return objc_object_clang_type.GetIndexOfChildMemberWithName (name, - omit_empty_base_classes, - child_indexes); + } } - break; - - - case clang::Type::ConstantArray: - { - // const clang::ConstantArrayType *array = llvm::cast<clang::ConstantArrayType>(parent_qual_type.getTypePtr()); - // const uint64_t element_count = array->getSize().getLimitedValue(); - // - // if (idx < element_count) - // { - // std::pair<uint64_t, unsigned> field_type_info = ast->getTypeInfo(array->getElementType()); - // - // char element_name[32]; - // ::snprintf (element_name, sizeof (element_name), "%s[%u]", parent_name ? parent_name : "", idx); - // - // child_name.assign(element_name); - // assert(field_type_info.first % 8 == 0); - // child_byte_size = field_type_info.first / 8; - // child_byte_offset = idx * child_byte_size; - // return array->getElementType().getAsOpaquePtr(); - // } - } - break; - - // case clang::Type::MemberPointerType: - // { - // MemberPointerType *mem_ptr_type = llvm::cast<MemberPointerType>(qual_type.getTypePtr()); - // clang::QualType pointee_type = mem_ptr_type->getPointeeType(); - // - // if (ClangASTContext::IsAggregateType (pointee_type.getAsOpaquePtr())) - // { - // return GetIndexOfChildWithName (ast, - // mem_ptr_type->getPointeeType().getAsOpaquePtr(), - // name); - // } - // } - // break; - // - case clang::Type::LValueReference: - case clang::Type::RValueReference: - { - const clang::ReferenceType *reference_type = llvm::cast<clang::ReferenceType>(qual_type.getTypePtr()); - clang::QualType pointee_type(reference_type->getPointeeType()); - CompilerType pointee_clang_type (getASTContext(), pointee_type); - - if (pointee_clang_type.IsAggregateType ()) - { - return pointee_clang_type.GetIndexOfChildMemberWithName (name, - omit_empty_base_classes, - child_indexes); - } + return child_indexes.size(); + } + } + } + break; + + case clang::Type::ObjCObject: + case clang::Type::ObjCInterface: + if (GetCompleteType(type)) { + llvm::StringRef name_sref(name); + const clang::ObjCObjectType *objc_class_type = + llvm::dyn_cast<clang::ObjCObjectType>(qual_type.getTypePtr()); + assert(objc_class_type); + if (objc_class_type) { + uint32_t child_idx = 0; + clang::ObjCInterfaceDecl *class_interface_decl = + objc_class_type->getInterface(); + + if (class_interface_decl) { + clang::ObjCInterfaceDecl::ivar_iterator ivar_pos, + ivar_end = class_interface_decl->ivar_end(); + clang::ObjCInterfaceDecl *superclass_interface_decl = + class_interface_decl->getSuperClass(); + + for (ivar_pos = class_interface_decl->ivar_begin(); + ivar_pos != ivar_end; ++ivar_pos, ++child_idx) { + const clang::ObjCIvarDecl *ivar_decl = *ivar_pos; + + if (ivar_decl->getName().equals(name_sref)) { + if ((!omit_empty_base_classes && superclass_interface_decl) || + (omit_empty_base_classes && + ObjCDeclHasIVars(superclass_interface_decl, true))) + ++child_idx; + + child_indexes.push_back(child_idx); + return child_indexes.size(); + } } - break; - - case clang::Type::Pointer: - { - CompilerType pointee_clang_type (GetPointeeType(type)); - - if (pointee_clang_type.IsAggregateType ()) - { - return pointee_clang_type.GetIndexOfChildMemberWithName (name, - omit_empty_base_classes, - child_indexes); - } + + if (superclass_interface_decl) { + // The super class index is always zero for ObjC classes, + // so we push it onto the child indexes in case we find + // an ivar in our superclass... + child_indexes.push_back(0); + + CompilerType superclass_clang_type( + getASTContext(), getASTContext()->getObjCInterfaceType( + superclass_interface_decl)); + if (superclass_clang_type.GetIndexOfChildMemberWithName( + name, omit_empty_base_classes, child_indexes)) { + // We did find an ivar in a superclass so just + // return the results! + return child_indexes.size(); + } + + // We didn't find an ivar matching "name" in our + // superclass, pop the superclass zero index that + // we pushed on above. + child_indexes.pop_back(); } - break; - - case clang::Type::Typedef: - return CompilerType (getASTContext(), llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType()).GetIndexOfChildMemberWithName (name, - omit_empty_base_classes, - child_indexes); - - case clang::Type::Auto: - return CompilerType (getASTContext(), llvm::cast<clang::AutoType>(qual_type)->getDeducedType()).GetIndexOfChildMemberWithName (name, - omit_empty_base_classes, - child_indexes); - - case clang::Type::Elaborated: - return CompilerType (getASTContext(), llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType()).GetIndexOfChildMemberWithName (name, - omit_empty_base_classes, - child_indexes); - - case clang::Type::Paren: - return CompilerType (getASTContext(), llvm::cast<clang::ParenType>(qual_type)->desugar()).GetIndexOfChildMemberWithName (name, - omit_empty_base_classes, - child_indexes); - - default: - break; + } } + } + break; + + case clang::Type::ObjCObjectPointer: { + CompilerType objc_object_clang_type( + getASTContext(), + llvm::cast<clang::ObjCObjectPointerType>(qual_type.getTypePtr()) + ->getPointeeType()); + return objc_object_clang_type.GetIndexOfChildMemberWithName( + name, omit_empty_base_classes, child_indexes); + } break; + + case clang::Type::ConstantArray: { + // const clang::ConstantArrayType *array = + // llvm::cast<clang::ConstantArrayType>(parent_qual_type.getTypePtr()); + // const uint64_t element_count = + // array->getSize().getLimitedValue(); + // + // if (idx < element_count) + // { + // std::pair<uint64_t, unsigned> field_type_info = + // ast->getTypeInfo(array->getElementType()); + // + // char element_name[32]; + // ::snprintf (element_name, sizeof (element_name), + // "%s[%u]", parent_name ? parent_name : "", idx); + // + // child_name.assign(element_name); + // assert(field_type_info.first % 8 == 0); + // child_byte_size = field_type_info.first / 8; + // child_byte_offset = idx * child_byte_size; + // return array->getElementType().getAsOpaquePtr(); + // } + } break; + + // case clang::Type::MemberPointerType: + // { + // MemberPointerType *mem_ptr_type = + // llvm::cast<MemberPointerType>(qual_type.getTypePtr()); + // clang::QualType pointee_type = + // mem_ptr_type->getPointeeType(); + // + // if (ClangASTContext::IsAggregateType + // (pointee_type.getAsOpaquePtr())) + // { + // return GetIndexOfChildWithName (ast, + // mem_ptr_type->getPointeeType().getAsOpaquePtr(), + // name); + // } + // } + // break; + // + case clang::Type::LValueReference: + case clang::Type::RValueReference: { + const clang::ReferenceType *reference_type = + llvm::cast<clang::ReferenceType>(qual_type.getTypePtr()); + clang::QualType pointee_type(reference_type->getPointeeType()); + CompilerType pointee_clang_type(getASTContext(), pointee_type); + + if (pointee_clang_type.IsAggregateType()) { + return pointee_clang_type.GetIndexOfChildMemberWithName( + name, omit_empty_base_classes, child_indexes); + } + } break; + + case clang::Type::Pointer: { + CompilerType pointee_clang_type(GetPointeeType(type)); + + if (pointee_clang_type.IsAggregateType()) { + return pointee_clang_type.GetIndexOfChildMemberWithName( + name, omit_empty_base_classes, child_indexes); + } + } break; + + case clang::Type::Typedef: + return CompilerType(getASTContext(), + llvm::cast<clang::TypedefType>(qual_type) + ->getDecl() + ->getUnderlyingType()) + .GetIndexOfChildMemberWithName(name, omit_empty_base_classes, + child_indexes); + + case clang::Type::Auto: + return CompilerType( + getASTContext(), + llvm::cast<clang::AutoType>(qual_type)->getDeducedType()) + .GetIndexOfChildMemberWithName(name, omit_empty_base_classes, + child_indexes); + + case clang::Type::Elaborated: + return CompilerType( + getASTContext(), + llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType()) + .GetIndexOfChildMemberWithName(name, omit_empty_base_classes, + child_indexes); + + case clang::Type::Paren: + return CompilerType(getASTContext(), + llvm::cast<clang::ParenType>(qual_type)->desugar()) + .GetIndexOfChildMemberWithName(name, omit_empty_base_classes, + child_indexes); + + default: + break; } - return 0; + } + return 0; } - // Get the index of the child of "clang_type" whose name matches. This function // doesn't descend into the children, but only looks one level deep and name // matches can include base class names. uint32_t -ClangASTContext::GetIndexOfChildWithName (lldb::opaque_compiler_type_t type, const char *name, bool omit_empty_base_classes) -{ - if (type && name && name[0]) - { - clang::QualType qual_type(GetCanonicalQualType(type)); - - const clang::Type::TypeClass type_class = qual_type->getTypeClass(); - - switch (type_class) - { - case clang::Type::Record: - if (GetCompleteType(type)) - { - const clang::RecordType *record_type = llvm::cast<clang::RecordType>(qual_type.getTypePtr()); - const clang::RecordDecl *record_decl = record_type->getDecl(); - - assert(record_decl); - uint32_t child_idx = 0; - - const clang::CXXRecordDecl *cxx_record_decl = llvm::dyn_cast<clang::CXXRecordDecl>(record_decl); - - if (cxx_record_decl) - { - clang::CXXRecordDecl::base_class_const_iterator base_class, base_class_end; - for (base_class = cxx_record_decl->bases_begin(), base_class_end = cxx_record_decl->bases_end(); - base_class != base_class_end; - ++base_class) - { - // Skip empty base classes - clang::CXXRecordDecl *base_class_decl = llvm::cast<clang::CXXRecordDecl>(base_class->getType()->getAs<clang::RecordType>()->getDecl()); - if (omit_empty_base_classes && ClangASTContext::RecordHasFields(base_class_decl) == false) - continue; - - CompilerType base_class_clang_type (getASTContext(), base_class->getType()); - std::string base_class_type_name (base_class_clang_type.GetTypeName().AsCString("")); - if (base_class_type_name.compare (name) == 0) - return child_idx; - ++child_idx; - } - } - - // Try and find a field that matches NAME - clang::RecordDecl::field_iterator field, field_end; - llvm::StringRef name_sref(name); - for (field = record_decl->field_begin(), field_end = record_decl->field_end(); - field != field_end; - ++field, ++child_idx) - { - if (field->getName().equals (name_sref)) - return child_idx; - } - - } - break; - - case clang::Type::ObjCObject: - case clang::Type::ObjCInterface: - if (GetCompleteType(type)) - { - llvm::StringRef name_sref(name); - const clang::ObjCObjectType *objc_class_type = llvm::dyn_cast<clang::ObjCObjectType>(qual_type.getTypePtr()); - assert (objc_class_type); - if (objc_class_type) - { - uint32_t child_idx = 0; - clang::ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface(); - - if (class_interface_decl) - { - clang::ObjCInterfaceDecl::ivar_iterator ivar_pos, ivar_end = class_interface_decl->ivar_end(); - clang::ObjCInterfaceDecl *superclass_interface_decl = class_interface_decl->getSuperClass(); - - for (ivar_pos = class_interface_decl->ivar_begin(); ivar_pos != ivar_end; ++ivar_pos, ++child_idx) - { - const clang::ObjCIvarDecl* ivar_decl = *ivar_pos; - - if (ivar_decl->getName().equals (name_sref)) - { - if ((!omit_empty_base_classes && superclass_interface_decl) || - ( omit_empty_base_classes && ObjCDeclHasIVars (superclass_interface_decl, true))) - ++child_idx; - - return child_idx; - } - } - - if (superclass_interface_decl) - { - if (superclass_interface_decl->getName().equals (name_sref)) - return 0; - } - } - } - } - break; - - case clang::Type::ObjCObjectPointer: - { - CompilerType pointee_clang_type (getASTContext(), llvm::cast<clang::ObjCObjectPointerType>(qual_type.getTypePtr())->getPointeeType()); - return pointee_clang_type.GetIndexOfChildWithName (name, omit_empty_base_classes); - } - break; - - case clang::Type::ConstantArray: - { - // const clang::ConstantArrayType *array = llvm::cast<clang::ConstantArrayType>(parent_qual_type.getTypePtr()); - // const uint64_t element_count = array->getSize().getLimitedValue(); - // - // if (idx < element_count) - // { - // std::pair<uint64_t, unsigned> field_type_info = ast->getTypeInfo(array->getElementType()); - // - // char element_name[32]; - // ::snprintf (element_name, sizeof (element_name), "%s[%u]", parent_name ? parent_name : "", idx); - // - // child_name.assign(element_name); - // assert(field_type_info.first % 8 == 0); - // child_byte_size = field_type_info.first / 8; - // child_byte_offset = idx * child_byte_size; - // return array->getElementType().getAsOpaquePtr(); - // } - } - break; - - // case clang::Type::MemberPointerType: - // { - // MemberPointerType *mem_ptr_type = llvm::cast<MemberPointerType>(qual_type.getTypePtr()); - // clang::QualType pointee_type = mem_ptr_type->getPointeeType(); - // - // if (ClangASTContext::IsAggregateType (pointee_type.getAsOpaquePtr())) - // { - // return GetIndexOfChildWithName (ast, - // mem_ptr_type->getPointeeType().getAsOpaquePtr(), - // name); - // } - // } - // break; - // - case clang::Type::LValueReference: - case clang::Type::RValueReference: - { - const clang::ReferenceType *reference_type = llvm::cast<clang::ReferenceType>(qual_type.getTypePtr()); - CompilerType pointee_type (getASTContext(), reference_type->getPointeeType()); - - if (pointee_type.IsAggregateType ()) - { - return pointee_type.GetIndexOfChildWithName (name, omit_empty_base_classes); - } - } - break; - - case clang::Type::Pointer: - { - const clang::PointerType *pointer_type = llvm::cast<clang::PointerType>(qual_type.getTypePtr()); - CompilerType pointee_type (getASTContext(), pointer_type->getPointeeType()); - - if (pointee_type.IsAggregateType ()) - { - return pointee_type.GetIndexOfChildWithName (name, omit_empty_base_classes); - } - else - { - // if (parent_name) - // { - // child_name.assign(1, '*'); - // child_name += parent_name; - // } - // - // // We have a pointer to an simple type - // if (idx == 0) - // { - // std::pair<uint64_t, unsigned> clang_type_info = ast->getTypeInfo(pointee_type); - // assert(clang_type_info.first % 8 == 0); - // child_byte_size = clang_type_info.first / 8; - // child_byte_offset = 0; - // return pointee_type.getAsOpaquePtr(); - // } - } - } - break; +ClangASTContext::GetIndexOfChildWithName(lldb::opaque_compiler_type_t type, + const char *name, + bool omit_empty_base_classes) { + if (type && name && name[0]) { + clang::QualType qual_type(GetCanonicalQualType(type)); - case clang::Type::Auto: - return CompilerType (getASTContext(), llvm::cast<clang::AutoType>(qual_type)->getDeducedType()).GetIndexOfChildWithName (name, omit_empty_base_classes); - - case clang::Type::Elaborated: - return CompilerType (getASTContext(), llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType()).GetIndexOfChildWithName (name, omit_empty_base_classes); - - case clang::Type::Paren: - return CompilerType (getASTContext(), llvm::cast<clang::ParenType>(qual_type)->desugar()).GetIndexOfChildWithName (name, omit_empty_base_classes); - - case clang::Type::Typedef: - return CompilerType (getASTContext(), llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType()).GetIndexOfChildWithName (name, omit_empty_base_classes); - - default: - break; + const clang::Type::TypeClass type_class = qual_type->getTypeClass(); + + switch (type_class) { + case clang::Type::Record: + if (GetCompleteType(type)) { + const clang::RecordType *record_type = + llvm::cast<clang::RecordType>(qual_type.getTypePtr()); + const clang::RecordDecl *record_decl = record_type->getDecl(); + + assert(record_decl); + uint32_t child_idx = 0; + + const clang::CXXRecordDecl *cxx_record_decl = + llvm::dyn_cast<clang::CXXRecordDecl>(record_decl); + + if (cxx_record_decl) { + clang::CXXRecordDecl::base_class_const_iterator base_class, + base_class_end; + for (base_class = cxx_record_decl->bases_begin(), + base_class_end = cxx_record_decl->bases_end(); + base_class != base_class_end; ++base_class) { + // Skip empty base classes + clang::CXXRecordDecl *base_class_decl = + llvm::cast<clang::CXXRecordDecl>( + base_class->getType() + ->getAs<clang::RecordType>() + ->getDecl()); + if (omit_empty_base_classes && + ClangASTContext::RecordHasFields(base_class_decl) == false) + continue; + + CompilerType base_class_clang_type(getASTContext(), + base_class->getType()); + std::string base_class_type_name( + base_class_clang_type.GetTypeName().AsCString("")); + if (base_class_type_name.compare(name) == 0) + return child_idx; + ++child_idx; + } } - } - return UINT32_MAX; -} + // Try and find a field that matches NAME + clang::RecordDecl::field_iterator field, field_end; + llvm::StringRef name_sref(name); + for (field = record_decl->field_begin(), + field_end = record_decl->field_end(); + field != field_end; ++field, ++child_idx) { + if (field->getName().equals(name_sref)) + return child_idx; + } + } + break; + + case clang::Type::ObjCObject: + case clang::Type::ObjCInterface: + if (GetCompleteType(type)) { + llvm::StringRef name_sref(name); + const clang::ObjCObjectType *objc_class_type = + llvm::dyn_cast<clang::ObjCObjectType>(qual_type.getTypePtr()); + assert(objc_class_type); + if (objc_class_type) { + uint32_t child_idx = 0; + clang::ObjCInterfaceDecl *class_interface_decl = + objc_class_type->getInterface(); + + if (class_interface_decl) { + clang::ObjCInterfaceDecl::ivar_iterator ivar_pos, + ivar_end = class_interface_decl->ivar_end(); + clang::ObjCInterfaceDecl *superclass_interface_decl = + class_interface_decl->getSuperClass(); + + for (ivar_pos = class_interface_decl->ivar_begin(); + ivar_pos != ivar_end; ++ivar_pos, ++child_idx) { + const clang::ObjCIvarDecl *ivar_decl = *ivar_pos; + + if (ivar_decl->getName().equals(name_sref)) { + if ((!omit_empty_base_classes && superclass_interface_decl) || + (omit_empty_base_classes && + ObjCDeclHasIVars(superclass_interface_decl, true))) + ++child_idx; -size_t -ClangASTContext::GetNumTemplateArguments (lldb::opaque_compiler_type_t type) -{ - if (!type) - return 0; + return child_idx; + } + } - clang::QualType qual_type (GetCanonicalQualType(type)); - const clang::Type::TypeClass type_class = qual_type->getTypeClass(); - switch (type_class) - { - case clang::Type::Record: - if (GetCompleteType(type)) - { - const clang::CXXRecordDecl *cxx_record_decl = qual_type->getAsCXXRecordDecl(); - if (cxx_record_decl) - { - const clang::ClassTemplateSpecializationDecl *template_decl = llvm::dyn_cast<clang::ClassTemplateSpecializationDecl>(cxx_record_decl); - if (template_decl) - return template_decl->getTemplateArgs().size(); - } + if (superclass_interface_decl) { + if (superclass_interface_decl->getName().equals(name_sref)) + return 0; } - break; - - case clang::Type::Typedef: - return (CompilerType (getASTContext(), llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType())).GetNumTemplateArguments(); - - case clang::Type::Auto: - return (CompilerType (getASTContext(), llvm::cast<clang::AutoType>(qual_type)->getDeducedType())).GetNumTemplateArguments(); - - case clang::Type::Elaborated: - return (CompilerType (getASTContext(), llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType())).GetNumTemplateArguments(); - - case clang::Type::Paren: - return (CompilerType (getASTContext(), llvm::cast<clang::ParenType>(qual_type)->desugar())).GetNumTemplateArguments(); - - default: - break; - } + } + } + } + break; + + case clang::Type::ObjCObjectPointer: { + CompilerType pointee_clang_type( + getASTContext(), + llvm::cast<clang::ObjCObjectPointerType>(qual_type.getTypePtr()) + ->getPointeeType()); + return pointee_clang_type.GetIndexOfChildWithName( + name, omit_empty_base_classes); + } break; + + case clang::Type::ConstantArray: { + // const clang::ConstantArrayType *array = + // llvm::cast<clang::ConstantArrayType>(parent_qual_type.getTypePtr()); + // const uint64_t element_count = + // array->getSize().getLimitedValue(); + // + // if (idx < element_count) + // { + // std::pair<uint64_t, unsigned> field_type_info = + // ast->getTypeInfo(array->getElementType()); + // + // char element_name[32]; + // ::snprintf (element_name, sizeof (element_name), + // "%s[%u]", parent_name ? parent_name : "", idx); + // + // child_name.assign(element_name); + // assert(field_type_info.first % 8 == 0); + // child_byte_size = field_type_info.first / 8; + // child_byte_offset = idx * child_byte_size; + // return array->getElementType().getAsOpaquePtr(); + // } + } break; + + // case clang::Type::MemberPointerType: + // { + // MemberPointerType *mem_ptr_type = + // llvm::cast<MemberPointerType>(qual_type.getTypePtr()); + // clang::QualType pointee_type = + // mem_ptr_type->getPointeeType(); + // + // if (ClangASTContext::IsAggregateType + // (pointee_type.getAsOpaquePtr())) + // { + // return GetIndexOfChildWithName (ast, + // mem_ptr_type->getPointeeType().getAsOpaquePtr(), + // name); + // } + // } + // break; + // + case clang::Type::LValueReference: + case clang::Type::RValueReference: { + const clang::ReferenceType *reference_type = + llvm::cast<clang::ReferenceType>(qual_type.getTypePtr()); + CompilerType pointee_type(getASTContext(), + reference_type->getPointeeType()); + + if (pointee_type.IsAggregateType()) { + return pointee_type.GetIndexOfChildWithName(name, + omit_empty_base_classes); + } + } break; + + case clang::Type::Pointer: { + const clang::PointerType *pointer_type = + llvm::cast<clang::PointerType>(qual_type.getTypePtr()); + CompilerType pointee_type(getASTContext(), + pointer_type->getPointeeType()); + + if (pointee_type.IsAggregateType()) { + return pointee_type.GetIndexOfChildWithName(name, + omit_empty_base_classes); + } else { + // if (parent_name) + // { + // child_name.assign(1, '*'); + // child_name += parent_name; + // } + // + // // We have a pointer to an simple type + // if (idx == 0) + // { + // std::pair<uint64_t, unsigned> clang_type_info + // = ast->getTypeInfo(pointee_type); + // assert(clang_type_info.first % 8 == 0); + // child_byte_size = clang_type_info.first / 8; + // child_byte_offset = 0; + // return pointee_type.getAsOpaquePtr(); + // } + } + } break; + + case clang::Type::Auto: + return CompilerType( + getASTContext(), + llvm::cast<clang::AutoType>(qual_type)->getDeducedType()) + .GetIndexOfChildWithName(name, omit_empty_base_classes); + + case clang::Type::Elaborated: + return CompilerType( + getASTContext(), + llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType()) + .GetIndexOfChildWithName(name, omit_empty_base_classes); + + case clang::Type::Paren: + return CompilerType(getASTContext(), + llvm::cast<clang::ParenType>(qual_type)->desugar()) + .GetIndexOfChildWithName(name, omit_empty_base_classes); + + case clang::Type::Typedef: + return CompilerType(getASTContext(), + llvm::cast<clang::TypedefType>(qual_type) + ->getDecl() + ->getUnderlyingType()) + .GetIndexOfChildWithName(name, omit_empty_base_classes); - return 0; + default: + break; + } + } + return UINT32_MAX; } -CompilerType -ClangASTContext::GetTemplateArgument (lldb::opaque_compiler_type_t type, size_t arg_idx, lldb::TemplateArgumentKind &kind) -{ - if (!type) - return CompilerType(); +size_t +ClangASTContext::GetNumTemplateArguments(lldb::opaque_compiler_type_t type) { + if (!type) + return 0; - clang::QualType qual_type (GetCanonicalQualType(type)); - const clang::Type::TypeClass type_class = qual_type->getTypeClass(); - switch (type_class) - { - case clang::Type::Record: - if (GetCompleteType(type)) - { - const clang::CXXRecordDecl *cxx_record_decl = qual_type->getAsCXXRecordDecl(); - if (cxx_record_decl) - { - const clang::ClassTemplateSpecializationDecl *template_decl = llvm::dyn_cast<clang::ClassTemplateSpecializationDecl>(cxx_record_decl); - if (template_decl && arg_idx < template_decl->getTemplateArgs().size()) - { - const clang::TemplateArgument &template_arg = template_decl->getTemplateArgs()[arg_idx]; - switch (template_arg.getKind()) - { - case clang::TemplateArgument::Null: - kind = eTemplateArgumentKindNull; - return CompilerType(); - - case clang::TemplateArgument::Type: - kind = eTemplateArgumentKindType; - return CompilerType(getASTContext(), template_arg.getAsType()); - - case clang::TemplateArgument::Declaration: - kind = eTemplateArgumentKindDeclaration; - return CompilerType(); - - case clang::TemplateArgument::Integral: - kind = eTemplateArgumentKindIntegral; - return CompilerType(getASTContext(), template_arg.getIntegralType()); - - case clang::TemplateArgument::Template: - kind = eTemplateArgumentKindTemplate; - return CompilerType(); - - case clang::TemplateArgument::TemplateExpansion: - kind = eTemplateArgumentKindTemplateExpansion; - return CompilerType(); - - case clang::TemplateArgument::Expression: - kind = eTemplateArgumentKindExpression; - return CompilerType(); - - case clang::TemplateArgument::Pack: - kind = eTemplateArgumentKindPack; - return CompilerType(); - - default: - assert (!"Unhandled clang::TemplateArgument::ArgKind"); - break; - } - } - } - } - break; - - case clang::Type::Typedef: - return (CompilerType (getASTContext(), llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType())).GetTemplateArgument(arg_idx, kind); - - case clang::Type::Auto: - return (CompilerType (getASTContext(), llvm::cast<clang::AutoType>(qual_type)->getDeducedType())).GetTemplateArgument(arg_idx, kind); - - case clang::Type::Elaborated: - return (CompilerType (getASTContext(), llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType())).GetTemplateArgument(arg_idx, kind); - - case clang::Type::Paren: - return (CompilerType (getASTContext(), llvm::cast<clang::ParenType>(qual_type)->desugar())).GetTemplateArgument(arg_idx, kind); - - default: - break; - } - kind = eTemplateArgumentKindNull; - return CompilerType (); + clang::QualType qual_type(GetCanonicalQualType(type)); + const clang::Type::TypeClass type_class = qual_type->getTypeClass(); + switch (type_class) { + case clang::Type::Record: + if (GetCompleteType(type)) { + const clang::CXXRecordDecl *cxx_record_decl = + qual_type->getAsCXXRecordDecl(); + if (cxx_record_decl) { + const clang::ClassTemplateSpecializationDecl *template_decl = + llvm::dyn_cast<clang::ClassTemplateSpecializationDecl>( + cxx_record_decl); + if (template_decl) + return template_decl->getTemplateArgs().size(); + } + } + break; + + case clang::Type::Typedef: + return (CompilerType(getASTContext(), + llvm::cast<clang::TypedefType>(qual_type) + ->getDecl() + ->getUnderlyingType())) + .GetNumTemplateArguments(); + + case clang::Type::Auto: + return (CompilerType( + getASTContext(), + llvm::cast<clang::AutoType>(qual_type)->getDeducedType())) + .GetNumTemplateArguments(); + + case clang::Type::Elaborated: + return (CompilerType( + getASTContext(), + llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType())) + .GetNumTemplateArguments(); + + case clang::Type::Paren: + return (CompilerType(getASTContext(), + llvm::cast<clang::ParenType>(qual_type)->desugar())) + .GetNumTemplateArguments(); + + default: + break; + } + + return 0; } CompilerType -ClangASTContext::GetTypeForFormatters (void* type) -{ - if (type) - return ClangUtil::RemoveFastQualifiers(CompilerType(this, type)); +ClangASTContext::GetTemplateArgument(lldb::opaque_compiler_type_t type, + size_t arg_idx, + lldb::TemplateArgumentKind &kind) { + if (!type) return CompilerType(); -} -clang::EnumDecl * -ClangASTContext::GetAsEnumDecl (const CompilerType& type) -{ - const clang::EnumType *enutype = llvm::dyn_cast<clang::EnumType>(ClangUtil::GetCanonicalQualType(type)); - if (enutype) - return enutype->getDecl(); - return NULL; -} + clang::QualType qual_type(GetCanonicalQualType(type)); + const clang::Type::TypeClass type_class = qual_type->getTypeClass(); + switch (type_class) { + case clang::Type::Record: + if (GetCompleteType(type)) { + const clang::CXXRecordDecl *cxx_record_decl = + qual_type->getAsCXXRecordDecl(); + if (cxx_record_decl) { + const clang::ClassTemplateSpecializationDecl *template_decl = + llvm::dyn_cast<clang::ClassTemplateSpecializationDecl>( + cxx_record_decl); + if (template_decl && + arg_idx < template_decl->getTemplateArgs().size()) { + const clang::TemplateArgument &template_arg = + template_decl->getTemplateArgs()[arg_idx]; + switch (template_arg.getKind()) { + case clang::TemplateArgument::Null: + kind = eTemplateArgumentKindNull; + return CompilerType(); -clang::RecordDecl * -ClangASTContext::GetAsRecordDecl (const CompilerType& type) -{ - const clang::RecordType *record_type = llvm::dyn_cast<clang::RecordType>(ClangUtil::GetCanonicalQualType(type)); - if (record_type) - return record_type->getDecl(); - return nullptr; -} + case clang::TemplateArgument::Type: + kind = eTemplateArgumentKindType; + return CompilerType(getASTContext(), template_arg.getAsType()); -clang::TagDecl * -ClangASTContext::GetAsTagDecl (const CompilerType& type) -{ - clang::QualType qual_type = ClangUtil::GetCanonicalQualType(type); - if (qual_type.isNull()) - return nullptr; - else - return qual_type->getAsTagDecl(); + case clang::TemplateArgument::Declaration: + kind = eTemplateArgumentKindDeclaration; + return CompilerType(); + + case clang::TemplateArgument::Integral: + kind = eTemplateArgumentKindIntegral; + return CompilerType(getASTContext(), + template_arg.getIntegralType()); + + case clang::TemplateArgument::Template: + kind = eTemplateArgumentKindTemplate; + return CompilerType(); + + case clang::TemplateArgument::TemplateExpansion: + kind = eTemplateArgumentKindTemplateExpansion; + return CompilerType(); + + case clang::TemplateArgument::Expression: + kind = eTemplateArgumentKindExpression; + return CompilerType(); + + case clang::TemplateArgument::Pack: + kind = eTemplateArgumentKindPack; + return CompilerType(); + + default: + assert(!"Unhandled clang::TemplateArgument::ArgKind"); + break; + } + } + } + } + break; + + case clang::Type::Typedef: + return (CompilerType(getASTContext(), + llvm::cast<clang::TypedefType>(qual_type) + ->getDecl() + ->getUnderlyingType())) + .GetTemplateArgument(arg_idx, kind); + + case clang::Type::Auto: + return (CompilerType( + getASTContext(), + llvm::cast<clang::AutoType>(qual_type)->getDeducedType())) + .GetTemplateArgument(arg_idx, kind); + + case clang::Type::Elaborated: + return (CompilerType( + getASTContext(), + llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType())) + .GetTemplateArgument(arg_idx, kind); + + case clang::Type::Paren: + return (CompilerType(getASTContext(), + llvm::cast<clang::ParenType>(qual_type)->desugar())) + .GetTemplateArgument(arg_idx, kind); + + default: + break; + } + kind = eTemplateArgumentKindNull; + return CompilerType(); +} + +CompilerType ClangASTContext::GetTypeForFormatters(void *type) { + if (type) + return ClangUtil::RemoveFastQualifiers(CompilerType(this, type)); + return CompilerType(); +} + +clang::EnumDecl *ClangASTContext::GetAsEnumDecl(const CompilerType &type) { + const clang::EnumType *enutype = + llvm::dyn_cast<clang::EnumType>(ClangUtil::GetCanonicalQualType(type)); + if (enutype) + return enutype->getDecl(); + return NULL; +} + +clang::RecordDecl *ClangASTContext::GetAsRecordDecl(const CompilerType &type) { + const clang::RecordType *record_type = + llvm::dyn_cast<clang::RecordType>(ClangUtil::GetCanonicalQualType(type)); + if (record_type) + return record_type->getDecl(); + return nullptr; +} + +clang::TagDecl *ClangASTContext::GetAsTagDecl(const CompilerType &type) { + clang::QualType qual_type = ClangUtil::GetCanonicalQualType(type); + if (qual_type.isNull()) + return nullptr; + else + return qual_type->getAsTagDecl(); } clang::CXXRecordDecl * -ClangASTContext::GetAsCXXRecordDecl (lldb::opaque_compiler_type_t type) -{ - return GetCanonicalQualType(type)->getAsCXXRecordDecl(); +ClangASTContext::GetAsCXXRecordDecl(lldb::opaque_compiler_type_t type) { + return GetCanonicalQualType(type)->getAsCXXRecordDecl(); } clang::ObjCInterfaceDecl * -ClangASTContext::GetAsObjCInterfaceDecl (const CompilerType& type) -{ - const clang::ObjCObjectType *objc_class_type = - llvm::dyn_cast<clang::ObjCObjectType>(ClangUtil::GetCanonicalQualType(type)); - if (objc_class_type) - return objc_class_type->getInterface(); +ClangASTContext::GetAsObjCInterfaceDecl(const CompilerType &type) { + const clang::ObjCObjectType *objc_class_type = + llvm::dyn_cast<clang::ObjCObjectType>( + ClangUtil::GetCanonicalQualType(type)); + if (objc_class_type) + return objc_class_type->getInterface(); + return nullptr; +} + +clang::FieldDecl *ClangASTContext::AddFieldToRecordType( + const CompilerType &type, const char *name, + const CompilerType &field_clang_type, AccessType access, + uint32_t bitfield_bit_size) { + if (!type.IsValid() || !field_clang_type.IsValid()) return nullptr; -} + ClangASTContext *ast = + llvm::dyn_cast_or_null<ClangASTContext>(type.GetTypeSystem()); + if (!ast) + return nullptr; + clang::ASTContext *clang_ast = ast->getASTContext(); + + clang::FieldDecl *field = nullptr; + + clang::Expr *bit_width = nullptr; + if (bitfield_bit_size != 0) { + llvm::APInt bitfield_bit_size_apint( + clang_ast->getTypeSize(clang_ast->IntTy), bitfield_bit_size); + bit_width = new (*clang_ast) + clang::IntegerLiteral(*clang_ast, bitfield_bit_size_apint, + clang_ast->IntTy, clang::SourceLocation()); + } + + clang::RecordDecl *record_decl = ast->GetAsRecordDecl(type); + if (record_decl) { + field = clang::FieldDecl::Create( + *clang_ast, record_decl, clang::SourceLocation(), + clang::SourceLocation(), + name ? &clang_ast->Idents.get(name) : nullptr, // Identifier + ClangUtil::GetQualType(field_clang_type), // Field type + nullptr, // TInfo * + bit_width, // BitWidth + false, // Mutable + clang::ICIS_NoInit); // HasInit + + if (!name) { + // Determine whether this field corresponds to an anonymous + // struct or union. + if (const clang::TagType *TagT = + field->getType()->getAs<clang::TagType>()) { + if (clang::RecordDecl *Rec = + llvm::dyn_cast<clang::RecordDecl>(TagT->getDecl())) + if (!Rec->getDeclName()) { + Rec->setAnonymousStructOrUnion(true); + field->setImplicit(); + } + } + } + + if (field) { + field->setAccess( + ClangASTContext::ConvertAccessTypeToAccessSpecifier(access)); + + record_decl->addDecl(field); -clang::FieldDecl * -ClangASTContext::AddFieldToRecordType (const CompilerType& type, const char *name, - const CompilerType &field_clang_type, - AccessType access, - uint32_t bitfield_bit_size) -{ - if (!type.IsValid() || !field_clang_type.IsValid()) - return nullptr; - ClangASTContext *ast = llvm::dyn_cast_or_null<ClangASTContext>(type.GetTypeSystem()); - if (!ast) - return nullptr; - clang::ASTContext* clang_ast = ast->getASTContext(); - - clang::FieldDecl *field = nullptr; - - clang::Expr *bit_width = nullptr; - if (bitfield_bit_size != 0) - { - llvm::APInt bitfield_bit_size_apint(clang_ast->getTypeSize(clang_ast->IntTy), bitfield_bit_size); - bit_width = new (*clang_ast)clang::IntegerLiteral (*clang_ast, bitfield_bit_size_apint, clang_ast->IntTy, clang::SourceLocation()); - } - - clang::RecordDecl *record_decl = ast->GetAsRecordDecl (type); - if (record_decl) - { - field = clang::FieldDecl::Create(*clang_ast, record_decl, clang::SourceLocation(), clang::SourceLocation(), - name ? &clang_ast->Idents.get(name) : nullptr, // Identifier - ClangUtil::GetQualType(field_clang_type), // Field type - nullptr, // TInfo * - bit_width, // BitWidth - false, // Mutable - clang::ICIS_NoInit); // HasInit - - if (!name) - { - // Determine whether this field corresponds to an anonymous - // struct or union. - if (const clang::TagType *TagT = field->getType()->getAs<clang::TagType>()) { - if (clang::RecordDecl *Rec = llvm::dyn_cast<clang::RecordDecl>(TagT->getDecl())) - if (!Rec->getDeclName()) { - Rec->setAnonymousStructOrUnion(true); - field->setImplicit(); - - } - } - } - - if (field) - { - field->setAccess (ClangASTContext::ConvertAccessTypeToAccessSpecifier (access)); - - record_decl->addDecl(field); - #ifdef LLDB_CONFIGURATION_DEBUG - VerifyDecl(field); + VerifyDecl(field); #endif - } } - else - { - clang::ObjCInterfaceDecl *class_interface_decl = ast->GetAsObjCInterfaceDecl (type); - - if (class_interface_decl) - { - const bool is_synthesized = false; - - field_clang_type.GetCompleteType(); - - field = clang::ObjCIvarDecl::Create( - *clang_ast, class_interface_decl, clang::SourceLocation(), clang::SourceLocation(), - name ? &clang_ast->Idents.get(name) : nullptr, // Identifier - ClangUtil::GetQualType(field_clang_type), // Field type - nullptr, // TypeSourceInfo * - ConvertAccessTypeToObjCIvarAccessControl(access), bit_width, is_synthesized); - - if (field) - { - class_interface_decl->addDecl(field); - + } else { + clang::ObjCInterfaceDecl *class_interface_decl = + ast->GetAsObjCInterfaceDecl(type); + + if (class_interface_decl) { + const bool is_synthesized = false; + + field_clang_type.GetCompleteType(); + + field = clang::ObjCIvarDecl::Create( + *clang_ast, class_interface_decl, clang::SourceLocation(), + clang::SourceLocation(), + name ? &clang_ast->Idents.get(name) : nullptr, // Identifier + ClangUtil::GetQualType(field_clang_type), // Field type + nullptr, // TypeSourceInfo * + ConvertAccessTypeToObjCIvarAccessControl(access), bit_width, + is_synthesized); + + if (field) { + class_interface_decl->addDecl(field); + #ifdef LLDB_CONFIGURATION_DEBUG - VerifyDecl(field); + VerifyDecl(field); #endif - } + } + } + } + return field; +} + +void ClangASTContext::BuildIndirectFields(const CompilerType &type) { + if (!type) + return; + + ClangASTContext *ast = llvm::dyn_cast<ClangASTContext>(type.GetTypeSystem()); + if (!ast) + return; + + clang::RecordDecl *record_decl = ast->GetAsRecordDecl(type); + + if (!record_decl) + return; + + typedef llvm::SmallVector<clang::IndirectFieldDecl *, 1> IndirectFieldVector; + + IndirectFieldVector indirect_fields; + clang::RecordDecl::field_iterator field_pos; + clang::RecordDecl::field_iterator field_end_pos = record_decl->field_end(); + clang::RecordDecl::field_iterator last_field_pos = field_end_pos; + for (field_pos = record_decl->field_begin(); field_pos != field_end_pos; + last_field_pos = field_pos++) { + if (field_pos->isAnonymousStructOrUnion()) { + clang::QualType field_qual_type = field_pos->getType(); + + const clang::RecordType *field_record_type = + field_qual_type->getAs<clang::RecordType>(); + + if (!field_record_type) + continue; + + clang::RecordDecl *field_record_decl = field_record_type->getDecl(); + + if (!field_record_decl) + continue; + + for (clang::RecordDecl::decl_iterator + di = field_record_decl->decls_begin(), + de = field_record_decl->decls_end(); + di != de; ++di) { + if (clang::FieldDecl *nested_field_decl = + llvm::dyn_cast<clang::FieldDecl>(*di)) { + clang::NamedDecl **chain = + new (*ast->getASTContext()) clang::NamedDecl *[2]; + chain[0] = *field_pos; + chain[1] = nested_field_decl; + clang::IndirectFieldDecl *indirect_field = + clang::IndirectFieldDecl::Create( + *ast->getASTContext(), record_decl, clang::SourceLocation(), + nested_field_decl->getIdentifier(), + nested_field_decl->getType(), {chain, 2}); + + indirect_field->setImplicit(); + + indirect_field->setAccess(ClangASTContext::UnifyAccessSpecifiers( + field_pos->getAccess(), nested_field_decl->getAccess())); + + indirect_fields.push_back(indirect_field); + } else if (clang::IndirectFieldDecl *nested_indirect_field_decl = + llvm::dyn_cast<clang::IndirectFieldDecl>(*di)) { + size_t nested_chain_size = + nested_indirect_field_decl->getChainingSize(); + clang::NamedDecl **chain = new (*ast->getASTContext()) + clang::NamedDecl *[nested_chain_size + 1]; + chain[0] = *field_pos; + + int chain_index = 1; + for (clang::IndirectFieldDecl::chain_iterator + nci = nested_indirect_field_decl->chain_begin(), + nce = nested_indirect_field_decl->chain_end(); + nci < nce; ++nci) { + chain[chain_index] = *nci; + chain_index++; + } + + clang::IndirectFieldDecl *indirect_field = + clang::IndirectFieldDecl::Create( + *ast->getASTContext(), record_decl, clang::SourceLocation(), + nested_indirect_field_decl->getIdentifier(), + nested_indirect_field_decl->getType(), + {chain, nested_chain_size + 1}); + + indirect_field->setImplicit(); + + indirect_field->setAccess(ClangASTContext::UnifyAccessSpecifiers( + field_pos->getAccess(), nested_indirect_field_decl->getAccess())); + + indirect_fields.push_back(indirect_field); } + } } - return field; + } + + // Check the last field to see if it has an incomplete array type as its + // last member and if it does, the tell the record decl about it + if (last_field_pos != field_end_pos) { + if (last_field_pos->getType()->isIncompleteArrayType()) + record_decl->hasFlexibleArrayMember(); + } + + for (IndirectFieldVector::iterator ifi = indirect_fields.begin(), + ife = indirect_fields.end(); + ifi < ife; ++ifi) { + record_decl->addDecl(*ifi); + } } -void -ClangASTContext::BuildIndirectFields (const CompilerType& type) -{ - if (!type) - return; +void ClangASTContext::SetIsPacked(const CompilerType &type) { + if (type) { + ClangASTContext *ast = + llvm::dyn_cast<ClangASTContext>(type.GetTypeSystem()); + if (ast) { + clang::RecordDecl *record_decl = GetAsRecordDecl(type); - ClangASTContext *ast = llvm::dyn_cast<ClangASTContext>(type.GetTypeSystem()); - if (!ast) + if (!record_decl) return; - clang::RecordDecl *record_decl = ast->GetAsRecordDecl(type); - - if (!record_decl) - return; - - typedef llvm::SmallVector <clang::IndirectFieldDecl *, 1> IndirectFieldVector; - - IndirectFieldVector indirect_fields; - clang::RecordDecl::field_iterator field_pos; - clang::RecordDecl::field_iterator field_end_pos = record_decl->field_end(); - clang::RecordDecl::field_iterator last_field_pos = field_end_pos; - for (field_pos = record_decl->field_begin(); field_pos != field_end_pos; last_field_pos = field_pos++) - { - if (field_pos->isAnonymousStructOrUnion()) - { - clang::QualType field_qual_type = field_pos->getType(); - - const clang::RecordType *field_record_type = field_qual_type->getAs<clang::RecordType>(); - - if (!field_record_type) - continue; - - clang::RecordDecl *field_record_decl = field_record_type->getDecl(); - - if (!field_record_decl) - continue; - - for (clang::RecordDecl::decl_iterator di = field_record_decl->decls_begin(), de = field_record_decl->decls_end(); - di != de; - ++di) - { - if (clang::FieldDecl *nested_field_decl = llvm::dyn_cast<clang::FieldDecl>(*di)) - { - clang::NamedDecl **chain = new (*ast->getASTContext()) clang::NamedDecl*[2]; - chain[0] = *field_pos; - chain[1] = nested_field_decl; - clang::IndirectFieldDecl *indirect_field = clang::IndirectFieldDecl::Create(*ast->getASTContext(), - record_decl, - clang::SourceLocation(), - nested_field_decl->getIdentifier(), - nested_field_decl->getType(), - {chain, 2}); - - indirect_field->setImplicit(); - - indirect_field->setAccess(ClangASTContext::UnifyAccessSpecifiers(field_pos->getAccess(), - nested_field_decl->getAccess())); - - indirect_fields.push_back(indirect_field); - } - else if (clang::IndirectFieldDecl *nested_indirect_field_decl = llvm::dyn_cast<clang::IndirectFieldDecl>(*di)) - { - size_t nested_chain_size = nested_indirect_field_decl->getChainingSize(); - clang::NamedDecl **chain = new (*ast->getASTContext()) clang::NamedDecl*[nested_chain_size + 1]; - chain[0] = *field_pos; - - int chain_index = 1; - for (clang::IndirectFieldDecl::chain_iterator nci = nested_indirect_field_decl->chain_begin(), - nce = nested_indirect_field_decl->chain_end(); - nci < nce; - ++nci) - { - chain[chain_index] = *nci; - chain_index++; - } - - clang::IndirectFieldDecl *indirect_field = clang::IndirectFieldDecl::Create(*ast->getASTContext(), - record_decl, - clang::SourceLocation(), - nested_indirect_field_decl->getIdentifier(), - nested_indirect_field_decl->getType(), - {chain, nested_chain_size + 1}); - - indirect_field->setImplicit(); - - indirect_field->setAccess(ClangASTContext::UnifyAccessSpecifiers(field_pos->getAccess(), - nested_indirect_field_decl->getAccess())); - - indirect_fields.push_back(indirect_field); - } - } - } - } - - // Check the last field to see if it has an incomplete array type as its - // last member and if it does, the tell the record decl about it - if (last_field_pos != field_end_pos) - { - if (last_field_pos->getType()->isIncompleteArrayType()) - record_decl->hasFlexibleArrayMember(); - } - - for (IndirectFieldVector::iterator ifi = indirect_fields.begin(), ife = indirect_fields.end(); - ifi < ife; - ++ifi) - { - record_decl->addDecl(*ifi); - } -} - -void -ClangASTContext::SetIsPacked (const CompilerType& type) -{ - if (type) - { - ClangASTContext *ast = llvm::dyn_cast<ClangASTContext>(type.GetTypeSystem()); - if (ast) - { - clang::RecordDecl *record_decl = GetAsRecordDecl(type); - - if (!record_decl) - return; - - record_decl->addAttr(clang::PackedAttr::CreateImplicit(*ast->getASTContext())); - } + record_decl->addAttr( + clang::PackedAttr::CreateImplicit(*ast->getASTContext())); } + } } -clang::VarDecl * -ClangASTContext::AddVariableToRecordType (const CompilerType& type, const char *name, - const CompilerType &var_type, - AccessType access) -{ - clang::VarDecl *var_decl = nullptr; - - if (!type.IsValid() || !var_type.IsValid()) - return nullptr; - ClangASTContext *ast = llvm::dyn_cast<ClangASTContext>(type.GetTypeSystem()); - if (!ast) - return nullptr; - - clang::RecordDecl *record_decl = ast->GetAsRecordDecl (type); - if (record_decl) - { - var_decl = - clang::VarDecl::Create(*ast->getASTContext(), // ASTContext & - record_decl, // DeclContext * - clang::SourceLocation(), // clang::SourceLocation StartLoc - clang::SourceLocation(), // clang::SourceLocation IdLoc - name ? &ast->getASTContext()->Idents.get(name) : nullptr, // clang::IdentifierInfo * - ClangUtil::GetQualType(var_type), // Variable clang::QualType - nullptr, // TypeSourceInfo * - clang::SC_Static); // StorageClass - if (var_decl) - { - var_decl->setAccess(ClangASTContext::ConvertAccessTypeToAccessSpecifier (access)); - record_decl->addDecl(var_decl); - +clang::VarDecl *ClangASTContext::AddVariableToRecordType( + const CompilerType &type, const char *name, const CompilerType &var_type, + AccessType access) { + clang::VarDecl *var_decl = nullptr; + + if (!type.IsValid() || !var_type.IsValid()) + return nullptr; + ClangASTContext *ast = llvm::dyn_cast<ClangASTContext>(type.GetTypeSystem()); + if (!ast) + return nullptr; + + clang::RecordDecl *record_decl = ast->GetAsRecordDecl(type); + if (record_decl) { + var_decl = clang::VarDecl::Create( + *ast->getASTContext(), // ASTContext & + record_decl, // DeclContext * + clang::SourceLocation(), // clang::SourceLocation StartLoc + clang::SourceLocation(), // clang::SourceLocation IdLoc + name ? &ast->getASTContext()->Idents.get(name) + : nullptr, // clang::IdentifierInfo * + ClangUtil::GetQualType(var_type), // Variable clang::QualType + nullptr, // TypeSourceInfo * + clang::SC_Static); // StorageClass + if (var_decl) { + var_decl->setAccess( + ClangASTContext::ConvertAccessTypeToAccessSpecifier(access)); + record_decl->addDecl(var_decl); + #ifdef LLDB_CONFIGURATION_DEBUG - VerifyDecl(var_decl); + VerifyDecl(var_decl); #endif - } } - return var_decl; + } + return var_decl; } +clang::CXXMethodDecl *ClangASTContext::AddMethodToCXXRecordType( + lldb::opaque_compiler_type_t type, const char *name, + const CompilerType &method_clang_type, lldb::AccessType access, + bool is_virtual, bool is_static, bool is_inline, bool is_explicit, + bool is_attr_used, bool is_artificial) { + if (!type || !method_clang_type.IsValid() || name == nullptr || + name[0] == '\0') + return nullptr; + + clang::QualType record_qual_type(GetCanonicalQualType(type)); + + clang::CXXRecordDecl *cxx_record_decl = + record_qual_type->getAsCXXRecordDecl(); + + if (cxx_record_decl == nullptr) + return nullptr; + + clang::QualType method_qual_type(ClangUtil::GetQualType(method_clang_type)); + + clang::CXXMethodDecl *cxx_method_decl = nullptr; + + clang::DeclarationName decl_name(&getASTContext()->Idents.get(name)); + + const clang::FunctionType *function_type = + llvm::dyn_cast<clang::FunctionType>(method_qual_type.getTypePtr()); + + if (function_type == nullptr) + return nullptr; + + const clang::FunctionProtoType *method_function_prototype( + llvm::dyn_cast<clang::FunctionProtoType>(function_type)); + + if (!method_function_prototype) + return nullptr; + + unsigned int num_params = method_function_prototype->getNumParams(); + + clang::CXXDestructorDecl *cxx_dtor_decl(nullptr); + clang::CXXConstructorDecl *cxx_ctor_decl(nullptr); + + if (is_artificial) + return nullptr; // skip everything artificial + + if (name[0] == '~') { + cxx_dtor_decl = clang::CXXDestructorDecl::Create( + *getASTContext(), cxx_record_decl, clang::SourceLocation(), + clang::DeclarationNameInfo( + getASTContext()->DeclarationNames.getCXXDestructorName( + getASTContext()->getCanonicalType(record_qual_type)), + clang::SourceLocation()), + method_qual_type, nullptr, is_inline, is_artificial); + cxx_method_decl = cxx_dtor_decl; + } else if (decl_name == cxx_record_decl->getDeclName()) { + cxx_ctor_decl = clang::CXXConstructorDecl::Create( + *getASTContext(), cxx_record_decl, clang::SourceLocation(), + clang::DeclarationNameInfo( + getASTContext()->DeclarationNames.getCXXConstructorName( + getASTContext()->getCanonicalType(record_qual_type)), + clang::SourceLocation()), + method_qual_type, + nullptr, // TypeSourceInfo * + is_explicit, is_inline, is_artificial, false /*is_constexpr*/); + cxx_method_decl = cxx_ctor_decl; + } else { + clang::StorageClass SC = is_static ? clang::SC_Static : clang::SC_None; + clang::OverloadedOperatorKind op_kind = clang::NUM_OVERLOADED_OPERATORS; + + if (IsOperator(name, op_kind)) { + if (op_kind != clang::NUM_OVERLOADED_OPERATORS) { + // Check the number of operator parameters. Sometimes we have + // seen bad DWARF that doesn't correctly describe operators and + // if we try to create a method and add it to the class, clang + // will assert and crash, so we need to make sure things are + // acceptable. + const bool is_method = true; + if (!ClangASTContext::CheckOverloadedOperatorKindParameterCount( + is_method, op_kind, num_params)) + return nullptr; + cxx_method_decl = clang::CXXMethodDecl::Create( + *getASTContext(), cxx_record_decl, clang::SourceLocation(), + clang::DeclarationNameInfo( + getASTContext()->DeclarationNames.getCXXOperatorName(op_kind), + clang::SourceLocation()), + method_qual_type, + nullptr, // TypeSourceInfo * + SC, is_inline, false /*is_constexpr*/, clang::SourceLocation()); + } else if (num_params == 0) { + // Conversion operators don't take params... + cxx_method_decl = clang::CXXConversionDecl::Create( + *getASTContext(), cxx_record_decl, clang::SourceLocation(), + clang::DeclarationNameInfo( + getASTContext()->DeclarationNames.getCXXConversionFunctionName( + getASTContext()->getCanonicalType( + function_type->getReturnType())), + clang::SourceLocation()), + method_qual_type, + nullptr, // TypeSourceInfo * + is_inline, is_explicit, false /*is_constexpr*/, + clang::SourceLocation()); + } + } + + if (cxx_method_decl == nullptr) { + cxx_method_decl = clang::CXXMethodDecl::Create( + *getASTContext(), cxx_record_decl, clang::SourceLocation(), + clang::DeclarationNameInfo(decl_name, clang::SourceLocation()), + method_qual_type, + nullptr, // TypeSourceInfo * + SC, is_inline, false /*is_constexpr*/, clang::SourceLocation()); + } + } + + clang::AccessSpecifier access_specifier = + ClangASTContext::ConvertAccessTypeToAccessSpecifier(access); + + cxx_method_decl->setAccess(access_specifier); + cxx_method_decl->setVirtualAsWritten(is_virtual); + + if (is_attr_used) + cxx_method_decl->addAttr(clang::UsedAttr::CreateImplicit(*getASTContext())); + + // Populate the method decl with parameter decls + + llvm::SmallVector<clang::ParmVarDecl *, 12> params; + + for (unsigned param_index = 0; param_index < num_params; ++param_index) { + params.push_back(clang::ParmVarDecl::Create( + *getASTContext(), cxx_method_decl, clang::SourceLocation(), + clang::SourceLocation(), + nullptr, // anonymous + method_function_prototype->getParamType(param_index), nullptr, + clang::SC_None, nullptr)); + } + + cxx_method_decl->setParams(llvm::ArrayRef<clang::ParmVarDecl *>(params)); + + cxx_record_decl->addDecl(cxx_method_decl); + + // Sometimes the debug info will mention a constructor (default/copy/move), + // destructor, or assignment operator (copy/move) but there won't be any + // version of this in the code. So we check if the function was artificially + // generated and if it is trivial and this lets the compiler/backend know + // that it can inline the IR for these when it needs to and we can avoid a + // "missing function" error when running expressions. + + if (is_artificial) { + if (cxx_ctor_decl && ((cxx_ctor_decl->isDefaultConstructor() && + cxx_record_decl->hasTrivialDefaultConstructor()) || + (cxx_ctor_decl->isCopyConstructor() && + cxx_record_decl->hasTrivialCopyConstructor()) || + (cxx_ctor_decl->isMoveConstructor() && + cxx_record_decl->hasTrivialMoveConstructor()))) { + cxx_ctor_decl->setDefaulted(); + cxx_ctor_decl->setTrivial(true); + } else if (cxx_dtor_decl) { + if (cxx_record_decl->hasTrivialDestructor()) { + cxx_dtor_decl->setDefaulted(); + cxx_dtor_decl->setTrivial(true); + } + } else if ((cxx_method_decl->isCopyAssignmentOperator() && + cxx_record_decl->hasTrivialCopyAssignment()) || + (cxx_method_decl->isMoveAssignmentOperator() && + cxx_record_decl->hasTrivialMoveAssignment())) { + cxx_method_decl->setDefaulted(); + cxx_method_decl->setTrivial(true); + } + } -clang::CXXMethodDecl * -ClangASTContext::AddMethodToCXXRecordType (lldb::opaque_compiler_type_t type, const char *name, - const CompilerType &method_clang_type, - lldb::AccessType access, - bool is_virtual, - bool is_static, - bool is_inline, - bool is_explicit, - bool is_attr_used, - bool is_artificial) -{ - if (!type || !method_clang_type.IsValid() || name == nullptr || name[0] == '\0') - return nullptr; - - clang::QualType record_qual_type(GetCanonicalQualType(type)); - - clang::CXXRecordDecl *cxx_record_decl = record_qual_type->getAsCXXRecordDecl(); - - if (cxx_record_decl == nullptr) - return nullptr; - - clang::QualType method_qual_type(ClangUtil::GetQualType(method_clang_type)); - - clang::CXXMethodDecl *cxx_method_decl = nullptr; - - clang::DeclarationName decl_name (&getASTContext()->Idents.get(name)); - - const clang::FunctionType *function_type = llvm::dyn_cast<clang::FunctionType>(method_qual_type.getTypePtr()); - - if (function_type == nullptr) - return nullptr; - - const clang::FunctionProtoType *method_function_prototype (llvm::dyn_cast<clang::FunctionProtoType>(function_type)); - - if (!method_function_prototype) - return nullptr; - - unsigned int num_params = method_function_prototype->getNumParams(); - - clang::CXXDestructorDecl *cxx_dtor_decl(nullptr); - clang::CXXConstructorDecl *cxx_ctor_decl(nullptr); - - if (is_artificial) - return nullptr; // skip everything artificial - - if (name[0] == '~') - { - cxx_dtor_decl = clang::CXXDestructorDecl::Create (*getASTContext(), - cxx_record_decl, - clang::SourceLocation(), - clang::DeclarationNameInfo (getASTContext()->DeclarationNames.getCXXDestructorName (getASTContext()->getCanonicalType (record_qual_type)), clang::SourceLocation()), - method_qual_type, - nullptr, - is_inline, - is_artificial); - cxx_method_decl = cxx_dtor_decl; - } - else if (decl_name == cxx_record_decl->getDeclName()) - { - cxx_ctor_decl = clang::CXXConstructorDecl::Create (*getASTContext(), - cxx_record_decl, - clang::SourceLocation(), - clang::DeclarationNameInfo (getASTContext()->DeclarationNames.getCXXConstructorName (getASTContext()->getCanonicalType (record_qual_type)), clang::SourceLocation()), - method_qual_type, - nullptr, // TypeSourceInfo * - is_explicit, - is_inline, - is_artificial, - false /*is_constexpr*/); - cxx_method_decl = cxx_ctor_decl; - } - else - { - clang::StorageClass SC = is_static ? clang::SC_Static : clang::SC_None; - clang::OverloadedOperatorKind op_kind = clang::NUM_OVERLOADED_OPERATORS; - - if (IsOperator (name, op_kind)) - { - if (op_kind != clang::NUM_OVERLOADED_OPERATORS) - { - // Check the number of operator parameters. Sometimes we have - // seen bad DWARF that doesn't correctly describe operators and - // if we try to create a method and add it to the class, clang - // will assert and crash, so we need to make sure things are - // acceptable. - const bool is_method = true; - if (!ClangASTContext::CheckOverloadedOperatorKindParameterCount(is_method, op_kind, num_params)) - return nullptr; - cxx_method_decl = clang::CXXMethodDecl::Create (*getASTContext(), - cxx_record_decl, - clang::SourceLocation(), - clang::DeclarationNameInfo (getASTContext()->DeclarationNames.getCXXOperatorName (op_kind), clang::SourceLocation()), - method_qual_type, - nullptr, // TypeSourceInfo * - SC, - is_inline, - false /*is_constexpr*/, - clang::SourceLocation()); - } - else if (num_params == 0) - { - // Conversion operators don't take params... - cxx_method_decl = clang::CXXConversionDecl::Create (*getASTContext(), - cxx_record_decl, - clang::SourceLocation(), - clang::DeclarationNameInfo (getASTContext()->DeclarationNames.getCXXConversionFunctionName (getASTContext()->getCanonicalType (function_type->getReturnType())), clang::SourceLocation()), - method_qual_type, - nullptr, // TypeSourceInfo * - is_inline, - is_explicit, - false /*is_constexpr*/, - clang::SourceLocation()); - } - } - - if (cxx_method_decl == nullptr) - { - cxx_method_decl = clang::CXXMethodDecl::Create (*getASTContext(), - cxx_record_decl, - clang::SourceLocation(), - clang::DeclarationNameInfo (decl_name, clang::SourceLocation()), - method_qual_type, - nullptr, // TypeSourceInfo * - SC, - is_inline, - false /*is_constexpr*/, - clang::SourceLocation()); - } - } - - clang::AccessSpecifier access_specifier = ClangASTContext::ConvertAccessTypeToAccessSpecifier (access); - - cxx_method_decl->setAccess (access_specifier); - cxx_method_decl->setVirtualAsWritten (is_virtual); - - if (is_attr_used) - cxx_method_decl->addAttr(clang::UsedAttr::CreateImplicit(*getASTContext())); - - // Populate the method decl with parameter decls - - llvm::SmallVector<clang::ParmVarDecl *, 12> params; - - for (unsigned param_index = 0; - param_index < num_params; - ++param_index) - { - params.push_back (clang::ParmVarDecl::Create (*getASTContext(), - cxx_method_decl, - clang::SourceLocation(), - clang::SourceLocation(), - nullptr, // anonymous - method_function_prototype->getParamType(param_index), - nullptr, - clang::SC_None, - nullptr)); - } - - cxx_method_decl->setParams (llvm::ArrayRef<clang::ParmVarDecl*>(params)); - - cxx_record_decl->addDecl (cxx_method_decl); - - // Sometimes the debug info will mention a constructor (default/copy/move), - // destructor, or assignment operator (copy/move) but there won't be any - // version of this in the code. So we check if the function was artificially - // generated and if it is trivial and this lets the compiler/backend know - // that it can inline the IR for these when it needs to and we can avoid a - // "missing function" error when running expressions. - - if (is_artificial) - { - if (cxx_ctor_decl && - ((cxx_ctor_decl->isDefaultConstructor() && cxx_record_decl->hasTrivialDefaultConstructor ()) || - (cxx_ctor_decl->isCopyConstructor() && cxx_record_decl->hasTrivialCopyConstructor ()) || - (cxx_ctor_decl->isMoveConstructor() && cxx_record_decl->hasTrivialMoveConstructor ()) )) - { - cxx_ctor_decl->setDefaulted(); - cxx_ctor_decl->setTrivial(true); - } - else if (cxx_dtor_decl) - { - if (cxx_record_decl->hasTrivialDestructor()) - { - cxx_dtor_decl->setDefaulted(); - cxx_dtor_decl->setTrivial(true); - } - } - else if ((cxx_method_decl->isCopyAssignmentOperator() && cxx_record_decl->hasTrivialCopyAssignment()) || - (cxx_method_decl->isMoveAssignmentOperator() && cxx_record_decl->hasTrivialMoveAssignment())) - { - cxx_method_decl->setDefaulted(); - cxx_method_decl->setTrivial(true); - } - } - #ifdef LLDB_CONFIGURATION_DEBUG - VerifyDecl(cxx_method_decl); + VerifyDecl(cxx_method_decl); #endif - - // printf ("decl->isPolymorphic() = %i\n", cxx_record_decl->isPolymorphic()); - // printf ("decl->isAggregate() = %i\n", cxx_record_decl->isAggregate()); - // printf ("decl->isPOD() = %i\n", cxx_record_decl->isPOD()); - // printf ("decl->isEmpty() = %i\n", cxx_record_decl->isEmpty()); - // printf ("decl->isAbstract() = %i\n", cxx_record_decl->isAbstract()); - // printf ("decl->hasTrivialConstructor() = %i\n", cxx_record_decl->hasTrivialConstructor()); - // printf ("decl->hasTrivialCopyConstructor() = %i\n", cxx_record_decl->hasTrivialCopyConstructor()); - // printf ("decl->hasTrivialCopyAssignment() = %i\n", cxx_record_decl->hasTrivialCopyAssignment()); - // printf ("decl->hasTrivialDestructor() = %i\n", cxx_record_decl->hasTrivialDestructor()); - return cxx_method_decl; -} + // printf ("decl->isPolymorphic() = %i\n", + // cxx_record_decl->isPolymorphic()); + // printf ("decl->isAggregate() = %i\n", + // cxx_record_decl->isAggregate()); + // printf ("decl->isPOD() = %i\n", + // cxx_record_decl->isPOD()); + // printf ("decl->isEmpty() = %i\n", + // cxx_record_decl->isEmpty()); + // printf ("decl->isAbstract() = %i\n", + // cxx_record_decl->isAbstract()); + // printf ("decl->hasTrivialConstructor() = %i\n", + // cxx_record_decl->hasTrivialConstructor()); + // printf ("decl->hasTrivialCopyConstructor() = %i\n", + // cxx_record_decl->hasTrivialCopyConstructor()); + // printf ("decl->hasTrivialCopyAssignment() = %i\n", + // cxx_record_decl->hasTrivialCopyAssignment()); + // printf ("decl->hasTrivialDestructor() = %i\n", + // cxx_record_decl->hasTrivialDestructor()); + return cxx_method_decl; +} #pragma mark C++ Base Classes clang::CXXBaseSpecifier * -ClangASTContext::CreateBaseClassSpecifier (lldb::opaque_compiler_type_t type, AccessType access, bool is_virtual, bool base_of_class) -{ - if (type) - return new clang::CXXBaseSpecifier (clang::SourceRange(), - is_virtual, - base_of_class, - ClangASTContext::ConvertAccessTypeToAccessSpecifier (access), - getASTContext()->getTrivialTypeSourceInfo (GetQualType(type)), - clang::SourceLocation()); - return nullptr; -} - -void -ClangASTContext::DeleteBaseClassSpecifiers (clang::CXXBaseSpecifier **base_classes, unsigned num_base_classes) -{ - for (unsigned i=0; i<num_base_classes; ++i) - { - delete base_classes[i]; - base_classes[i] = nullptr; - } -} +ClangASTContext::CreateBaseClassSpecifier(lldb::opaque_compiler_type_t type, + AccessType access, bool is_virtual, + bool base_of_class) { + if (type) + return new clang::CXXBaseSpecifier( + clang::SourceRange(), is_virtual, base_of_class, + ClangASTContext::ConvertAccessTypeToAccessSpecifier(access), + getASTContext()->getTrivialTypeSourceInfo(GetQualType(type)), + clang::SourceLocation()); + return nullptr; +} + +void ClangASTContext::DeleteBaseClassSpecifiers( + clang::CXXBaseSpecifier **base_classes, unsigned num_base_classes) { + for (unsigned i = 0; i < num_base_classes; ++i) { + delete base_classes[i]; + base_classes[i] = nullptr; + } +} + +bool ClangASTContext::SetBaseClassesForClassType( + lldb::opaque_compiler_type_t type, + clang::CXXBaseSpecifier const *const *base_classes, + unsigned num_base_classes) { + if (type) { + clang::CXXRecordDecl *cxx_record_decl = GetAsCXXRecordDecl(type); + if (cxx_record_decl) { + cxx_record_decl->setBases(base_classes, num_base_classes); + return true; + } + } + return false; +} + +bool ClangASTContext::SetObjCSuperClass( + const CompilerType &type, const CompilerType &superclass_clang_type) { + ClangASTContext *ast = + llvm::dyn_cast_or_null<ClangASTContext>(type.GetTypeSystem()); + if (!ast) + return false; + clang::ASTContext *clang_ast = ast->getASTContext(); + + if (type && superclass_clang_type.IsValid() && + superclass_clang_type.GetTypeSystem() == type.GetTypeSystem()) { + clang::ObjCInterfaceDecl *class_interface_decl = + GetAsObjCInterfaceDecl(type); + clang::ObjCInterfaceDecl *super_interface_decl = + GetAsObjCInterfaceDecl(superclass_clang_type); + if (class_interface_decl && super_interface_decl) { + class_interface_decl->setSuperClass(clang_ast->getTrivialTypeSourceInfo( + clang_ast->getObjCInterfaceType(super_interface_decl))); + return true; + } + } + return false; +} + +bool ClangASTContext::AddObjCClassProperty( + const CompilerType &type, const char *property_name, + const CompilerType &property_clang_type, clang::ObjCIvarDecl *ivar_decl, + const char *property_setter_name, const char *property_getter_name, + uint32_t property_attributes, ClangASTMetadata *metadata) { + if (!type || !property_clang_type.IsValid() || property_name == nullptr || + property_name[0] == '\0') + return false; + ClangASTContext *ast = llvm::dyn_cast<ClangASTContext>(type.GetTypeSystem()); + if (!ast) + return false; + clang::ASTContext *clang_ast = ast->getASTContext(); + + clang::ObjCInterfaceDecl *class_interface_decl = GetAsObjCInterfaceDecl(type); + + if (class_interface_decl) { + CompilerType property_clang_type_to_access; + + if (property_clang_type.IsValid()) + property_clang_type_to_access = property_clang_type; + else if (ivar_decl) + property_clang_type_to_access = + CompilerType(clang_ast, ivar_decl->getType()); + + if (class_interface_decl && property_clang_type_to_access.IsValid()) { + clang::TypeSourceInfo *prop_type_source; + if (ivar_decl) + prop_type_source = + clang_ast->getTrivialTypeSourceInfo(ivar_decl->getType()); + else + prop_type_source = clang_ast->getTrivialTypeSourceInfo( + ClangUtil::GetQualType(property_clang_type)); + + clang::ObjCPropertyDecl *property_decl = clang::ObjCPropertyDecl::Create( + *clang_ast, class_interface_decl, + clang::SourceLocation(), // Source Location + &clang_ast->Idents.get(property_name), + clang::SourceLocation(), // Source Location for AT + clang::SourceLocation(), // Source location for ( + ivar_decl ? ivar_decl->getType() + : ClangUtil::GetQualType(property_clang_type), + prop_type_source); + + if (property_decl) { + if (metadata) + ClangASTContext::SetMetadata(clang_ast, property_decl, *metadata); + + class_interface_decl->addDecl(property_decl); + + clang::Selector setter_sel, getter_sel; + + if (property_setter_name != nullptr) { + std::string property_setter_no_colon( + property_setter_name, strlen(property_setter_name) - 1); + clang::IdentifierInfo *setter_ident = + &clang_ast->Idents.get(property_setter_no_colon.c_str()); + setter_sel = clang_ast->Selectors.getSelector(1, &setter_ident); + } else if (!(property_attributes & DW_APPLE_PROPERTY_readonly)) { + std::string setter_sel_string("set"); + setter_sel_string.push_back(::toupper(property_name[0])); + setter_sel_string.append(&property_name[1]); + clang::IdentifierInfo *setter_ident = + &clang_ast->Idents.get(setter_sel_string.c_str()); + setter_sel = clang_ast->Selectors.getSelector(1, &setter_ident); + } + property_decl->setSetterName(setter_sel); + property_decl->setPropertyAttributes( + clang::ObjCPropertyDecl::OBJC_PR_setter); + + if (property_getter_name != nullptr) { + clang::IdentifierInfo *getter_ident = + &clang_ast->Idents.get(property_getter_name); + getter_sel = clang_ast->Selectors.getSelector(0, &getter_ident); + } else { + clang::IdentifierInfo *getter_ident = + &clang_ast->Idents.get(property_name); + getter_sel = clang_ast->Selectors.getSelector(0, &getter_ident); + } + property_decl->setGetterName(getter_sel); + property_decl->setPropertyAttributes( + clang::ObjCPropertyDecl::OBJC_PR_getter); + + if (ivar_decl) + property_decl->setPropertyIvarDecl(ivar_decl); + + if (property_attributes & DW_APPLE_PROPERTY_readonly) + property_decl->setPropertyAttributes( + clang::ObjCPropertyDecl::OBJC_PR_readonly); + if (property_attributes & DW_APPLE_PROPERTY_readwrite) + property_decl->setPropertyAttributes( + clang::ObjCPropertyDecl::OBJC_PR_readwrite); + if (property_attributes & DW_APPLE_PROPERTY_assign) + property_decl->setPropertyAttributes( + clang::ObjCPropertyDecl::OBJC_PR_assign); + if (property_attributes & DW_APPLE_PROPERTY_retain) + property_decl->setPropertyAttributes( + clang::ObjCPropertyDecl::OBJC_PR_retain); + if (property_attributes & DW_APPLE_PROPERTY_copy) + property_decl->setPropertyAttributes( + clang::ObjCPropertyDecl::OBJC_PR_copy); + if (property_attributes & DW_APPLE_PROPERTY_nonatomic) + property_decl->setPropertyAttributes( + clang::ObjCPropertyDecl::OBJC_PR_nonatomic); + if (property_attributes & clang::ObjCPropertyDecl::OBJC_PR_nullability) + property_decl->setPropertyAttributes( + clang::ObjCPropertyDecl::OBJC_PR_nullability); + if (property_attributes & + clang::ObjCPropertyDecl::OBJC_PR_null_resettable) + property_decl->setPropertyAttributes( + clang::ObjCPropertyDecl::OBJC_PR_null_resettable); + if (property_attributes & clang::ObjCPropertyDecl::OBJC_PR_class) + property_decl->setPropertyAttributes( + clang::ObjCPropertyDecl::OBJC_PR_class); + + const bool isInstance = + (property_attributes & clang::ObjCPropertyDecl::OBJC_PR_class) == 0; + + if (!getter_sel.isNull() && + !(isInstance + ? class_interface_decl->lookupInstanceMethod(getter_sel) + : class_interface_decl->lookupClassMethod(getter_sel))) { + const bool isVariadic = false; + const bool isSynthesized = false; + const bool isImplicitlyDeclared = true; + const bool isDefined = false; + const clang::ObjCMethodDecl::ImplementationControl impControl = + clang::ObjCMethodDecl::None; + const bool HasRelatedResultType = false; + + clang::ObjCMethodDecl *getter = clang::ObjCMethodDecl::Create( + *clang_ast, clang::SourceLocation(), clang::SourceLocation(), + getter_sel, ClangUtil::GetQualType(property_clang_type_to_access), + nullptr, class_interface_decl, isInstance, isVariadic, + isSynthesized, isImplicitlyDeclared, isDefined, impControl, + HasRelatedResultType); + + if (getter && metadata) + ClangASTContext::SetMetadata(clang_ast, getter, *metadata); + + if (getter) { + getter->setMethodParams(*clang_ast, + llvm::ArrayRef<clang::ParmVarDecl *>(), + llvm::ArrayRef<clang::SourceLocation>()); + + class_interface_decl->addDecl(getter); + } + } -bool -ClangASTContext::SetBaseClassesForClassType (lldb::opaque_compiler_type_t type, clang::CXXBaseSpecifier const * const *base_classes, - unsigned num_base_classes) -{ - if (type) - { - clang::CXXRecordDecl *cxx_record_decl = GetAsCXXRecordDecl(type); - if (cxx_record_decl) - { - cxx_record_decl->setBases(base_classes, num_base_classes); - return true; + if (!setter_sel.isNull() && + !(isInstance + ? class_interface_decl->lookupInstanceMethod(setter_sel) + : class_interface_decl->lookupClassMethod(setter_sel))) { + clang::QualType result_type = clang_ast->VoidTy; + const bool isVariadic = false; + const bool isSynthesized = false; + const bool isImplicitlyDeclared = true; + const bool isDefined = false; + const clang::ObjCMethodDecl::ImplementationControl impControl = + clang::ObjCMethodDecl::None; + const bool HasRelatedResultType = false; + + clang::ObjCMethodDecl *setter = clang::ObjCMethodDecl::Create( + *clang_ast, clang::SourceLocation(), clang::SourceLocation(), + setter_sel, result_type, nullptr, class_interface_decl, + isInstance, isVariadic, isSynthesized, isImplicitlyDeclared, + isDefined, impControl, HasRelatedResultType); + + if (setter && metadata) + ClangASTContext::SetMetadata(clang_ast, setter, *metadata); + + llvm::SmallVector<clang::ParmVarDecl *, 1> params; + + params.push_back(clang::ParmVarDecl::Create( + *clang_ast, setter, clang::SourceLocation(), + clang::SourceLocation(), + nullptr, // anonymous + ClangUtil::GetQualType(property_clang_type_to_access), nullptr, + clang::SC_Auto, nullptr)); + + if (setter) { + setter->setMethodParams( + *clang_ast, llvm::ArrayRef<clang::ParmVarDecl *>(params), + llvm::ArrayRef<clang::SourceLocation>()); + + class_interface_decl->addDecl(setter); + } } + + return true; + } } - return false; + } + return false; } -bool -ClangASTContext::SetObjCSuperClass (const CompilerType& type, const CompilerType &superclass_clang_type) -{ - ClangASTContext *ast = llvm::dyn_cast_or_null<ClangASTContext>(type.GetTypeSystem()); - if (!ast) - return false; - clang::ASTContext* clang_ast = ast->getASTContext(); - - if (type && superclass_clang_type.IsValid() && superclass_clang_type.GetTypeSystem() == type.GetTypeSystem()) - { - clang::ObjCInterfaceDecl *class_interface_decl = GetAsObjCInterfaceDecl (type); - clang::ObjCInterfaceDecl *super_interface_decl = GetAsObjCInterfaceDecl (superclass_clang_type); - if (class_interface_decl && super_interface_decl) - { - class_interface_decl->setSuperClass(clang_ast->getTrivialTypeSourceInfo(clang_ast->getObjCInterfaceType(super_interface_decl))); - return true; - } - } - return false; +bool ClangASTContext::IsObjCClassTypeAndHasIVars(const CompilerType &type, + bool check_superclass) { + clang::ObjCInterfaceDecl *class_interface_decl = GetAsObjCInterfaceDecl(type); + if (class_interface_decl) + return ObjCDeclHasIVars(class_interface_decl, check_superclass); + return false; } -bool -ClangASTContext::AddObjCClassProperty (const CompilerType& type, - const char *property_name, - const CompilerType &property_clang_type, - clang::ObjCIvarDecl *ivar_decl, - const char *property_setter_name, - const char *property_getter_name, - uint32_t property_attributes, - ClangASTMetadata *metadata) -{ - if (!type || !property_clang_type.IsValid() || property_name == nullptr || property_name[0] == '\0') - return false; - ClangASTContext *ast = llvm::dyn_cast<ClangASTContext>(type.GetTypeSystem()); - if (!ast) - return false; - clang::ASTContext* clang_ast = ast->getASTContext(); - - clang::ObjCInterfaceDecl *class_interface_decl = GetAsObjCInterfaceDecl (type); - - if (class_interface_decl) - { - CompilerType property_clang_type_to_access; - - if (property_clang_type.IsValid()) - property_clang_type_to_access = property_clang_type; - else if (ivar_decl) - property_clang_type_to_access = CompilerType (clang_ast, ivar_decl->getType()); - - if (class_interface_decl && property_clang_type_to_access.IsValid()) - { - clang::TypeSourceInfo *prop_type_source; - if (ivar_decl) - prop_type_source = clang_ast->getTrivialTypeSourceInfo (ivar_decl->getType()); - else - prop_type_source = clang_ast->getTrivialTypeSourceInfo(ClangUtil::GetQualType(property_clang_type)); - - clang::ObjCPropertyDecl *property_decl = clang::ObjCPropertyDecl::Create( - *clang_ast, class_interface_decl, - clang::SourceLocation(), // Source Location - &clang_ast->Idents.get(property_name), - clang::SourceLocation(), // Source Location for AT - clang::SourceLocation(), // Source location for ( - ivar_decl ? ivar_decl->getType() : ClangUtil::GetQualType(property_clang_type), prop_type_source); - - if (property_decl) - { - if (metadata) - ClangASTContext::SetMetadata(clang_ast, property_decl, *metadata); - - class_interface_decl->addDecl (property_decl); - - clang::Selector setter_sel, getter_sel; - - if (property_setter_name != nullptr) - { - std::string property_setter_no_colon(property_setter_name, strlen(property_setter_name) - 1); - clang::IdentifierInfo *setter_ident = &clang_ast->Idents.get(property_setter_no_colon.c_str()); - setter_sel = clang_ast->Selectors.getSelector(1, &setter_ident); - } - else if (!(property_attributes & DW_APPLE_PROPERTY_readonly)) - { - std::string setter_sel_string("set"); - setter_sel_string.push_back(::toupper(property_name[0])); - setter_sel_string.append(&property_name[1]); - clang::IdentifierInfo *setter_ident = &clang_ast->Idents.get(setter_sel_string.c_str()); - setter_sel = clang_ast->Selectors.getSelector(1, &setter_ident); - } - property_decl->setSetterName(setter_sel); - property_decl->setPropertyAttributes (clang::ObjCPropertyDecl::OBJC_PR_setter); - - if (property_getter_name != nullptr) - { - clang::IdentifierInfo *getter_ident = &clang_ast->Idents.get(property_getter_name); - getter_sel = clang_ast->Selectors.getSelector(0, &getter_ident); - } - else - { - clang::IdentifierInfo *getter_ident = &clang_ast->Idents.get(property_name); - getter_sel = clang_ast->Selectors.getSelector(0, &getter_ident); - } - property_decl->setGetterName(getter_sel); - property_decl->setPropertyAttributes (clang::ObjCPropertyDecl::OBJC_PR_getter); - - if (ivar_decl) - property_decl->setPropertyIvarDecl (ivar_decl); - - if (property_attributes & DW_APPLE_PROPERTY_readonly) - property_decl->setPropertyAttributes (clang::ObjCPropertyDecl::OBJC_PR_readonly); - if (property_attributes & DW_APPLE_PROPERTY_readwrite) - property_decl->setPropertyAttributes (clang::ObjCPropertyDecl::OBJC_PR_readwrite); - if (property_attributes & DW_APPLE_PROPERTY_assign) - property_decl->setPropertyAttributes (clang::ObjCPropertyDecl::OBJC_PR_assign); - if (property_attributes & DW_APPLE_PROPERTY_retain) - property_decl->setPropertyAttributes (clang::ObjCPropertyDecl::OBJC_PR_retain); - if (property_attributes & DW_APPLE_PROPERTY_copy) - property_decl->setPropertyAttributes (clang::ObjCPropertyDecl::OBJC_PR_copy); - if (property_attributes & DW_APPLE_PROPERTY_nonatomic) - property_decl->setPropertyAttributes (clang::ObjCPropertyDecl::OBJC_PR_nonatomic); - if (property_attributes & clang::ObjCPropertyDecl::OBJC_PR_nullability) - property_decl->setPropertyAttributes(clang::ObjCPropertyDecl::OBJC_PR_nullability); - if (property_attributes & clang::ObjCPropertyDecl::OBJC_PR_null_resettable) - property_decl->setPropertyAttributes(clang::ObjCPropertyDecl::OBJC_PR_null_resettable); - if (property_attributes & clang::ObjCPropertyDecl::OBJC_PR_class) - property_decl->setPropertyAttributes(clang::ObjCPropertyDecl::OBJC_PR_class); - - const bool isInstance = (property_attributes & clang::ObjCPropertyDecl::OBJC_PR_class) == 0; - - if (!getter_sel.isNull() && - !(isInstance ? class_interface_decl->lookupInstanceMethod(getter_sel) - : class_interface_decl->lookupClassMethod(getter_sel))) - { - const bool isVariadic = false; - const bool isSynthesized = false; - const bool isImplicitlyDeclared = true; - const bool isDefined = false; - const clang::ObjCMethodDecl::ImplementationControl impControl = clang::ObjCMethodDecl::None; - const bool HasRelatedResultType = false; - - clang::ObjCMethodDecl *getter = clang::ObjCMethodDecl::Create( - *clang_ast, clang::SourceLocation(), clang::SourceLocation(), getter_sel, - ClangUtil::GetQualType(property_clang_type_to_access), nullptr, class_interface_decl, - isInstance, isVariadic, isSynthesized, isImplicitlyDeclared, isDefined, impControl, - HasRelatedResultType); - - if (getter && metadata) - ClangASTContext::SetMetadata(clang_ast, getter, *metadata); - - if (getter) - { - getter->setMethodParams(*clang_ast, llvm::ArrayRef<clang::ParmVarDecl*>(), llvm::ArrayRef<clang::SourceLocation>()); - - class_interface_decl->addDecl(getter); - } - } +clang::ObjCMethodDecl *ClangASTContext::AddMethodToObjCObjectType( + const CompilerType &type, + const char *name, // the full symbol name as seen in the symbol table + // (lldb::opaque_compiler_type_t type, "-[NString + // stringWithCString:]") + const CompilerType &method_clang_type, lldb::AccessType access, + bool is_artificial, bool is_variadic) { + if (!type || !method_clang_type.IsValid()) + return nullptr; - if (!setter_sel.isNull() && - !(isInstance ? class_interface_decl->lookupInstanceMethod(setter_sel) - : class_interface_decl->lookupClassMethod(setter_sel))) - { - clang::QualType result_type = clang_ast->VoidTy; - const bool isVariadic = false; - const bool isSynthesized = false; - const bool isImplicitlyDeclared = true; - const bool isDefined = false; - const clang::ObjCMethodDecl::ImplementationControl impControl = clang::ObjCMethodDecl::None; - const bool HasRelatedResultType = false; - - clang::ObjCMethodDecl *setter = clang::ObjCMethodDecl::Create (*clang_ast, - clang::SourceLocation(), - clang::SourceLocation(), - setter_sel, - result_type, - nullptr, - class_interface_decl, - isInstance, - isVariadic, - isSynthesized, - isImplicitlyDeclared, - isDefined, - impControl, - HasRelatedResultType); - - if (setter && metadata) - ClangASTContext::SetMetadata(clang_ast, setter, *metadata); - - llvm::SmallVector<clang::ParmVarDecl *, 1> params; - - params.push_back(clang::ParmVarDecl::Create( - *clang_ast, setter, clang::SourceLocation(), clang::SourceLocation(), - nullptr, // anonymous - ClangUtil::GetQualType(property_clang_type_to_access), nullptr, clang::SC_Auto, nullptr)); - - if (setter) - { - setter->setMethodParams(*clang_ast, llvm::ArrayRef<clang::ParmVarDecl*>(params), llvm::ArrayRef<clang::SourceLocation>()); - - class_interface_decl->addDecl(setter); - } - } - - return true; - } - } - } - return false; -} + clang::ObjCInterfaceDecl *class_interface_decl = GetAsObjCInterfaceDecl(type); -bool -ClangASTContext::IsObjCClassTypeAndHasIVars (const CompilerType& type, bool check_superclass) -{ - clang::ObjCInterfaceDecl *class_interface_decl = GetAsObjCInterfaceDecl (type); - if (class_interface_decl) - return ObjCDeclHasIVars (class_interface_decl, check_superclass); - return false; -} + if (class_interface_decl == nullptr) + return nullptr; + ClangASTContext *lldb_ast = + llvm::dyn_cast<ClangASTContext>(type.GetTypeSystem()); + if (lldb_ast == nullptr) + return nullptr; + clang::ASTContext *ast = lldb_ast->getASTContext(); + const char *selector_start = ::strchr(name, ' '); + if (selector_start == nullptr) + return nullptr; -clang::ObjCMethodDecl * -ClangASTContext::AddMethodToObjCObjectType (const CompilerType& type, - const char *name, // the full symbol name as seen in the symbol table (lldb::opaque_compiler_type_t type, "-[NString stringWithCString:]") - const CompilerType &method_clang_type, - lldb::AccessType access, - bool is_artificial, - bool is_variadic) -{ - if (!type || !method_clang_type.IsValid()) - return nullptr; - - clang::ObjCInterfaceDecl *class_interface_decl = GetAsObjCInterfaceDecl(type); - - if (class_interface_decl == nullptr) - return nullptr; - ClangASTContext *lldb_ast = llvm::dyn_cast<ClangASTContext>(type.GetTypeSystem()); - if (lldb_ast == nullptr) - return nullptr; - clang::ASTContext *ast = lldb_ast->getASTContext(); - - const char *selector_start = ::strchr (name, ' '); - if (selector_start == nullptr) - return nullptr; - - selector_start++; - llvm::SmallVector<clang::IdentifierInfo *, 12> selector_idents; - - size_t len = 0; - const char *start; - //printf ("name = '%s'\n", name); - - unsigned num_selectors_with_args = 0; - for (start = selector_start; - start && *start != '\0' && *start != ']'; - start += len) - { - len = ::strcspn(start, ":]"); - bool has_arg = (start[len] == ':'); - if (has_arg) - ++num_selectors_with_args; - selector_idents.push_back (&ast->Idents.get (llvm::StringRef (start, len))); - if (has_arg) - len += 1; - } - - - if (selector_idents.size() == 0) - return nullptr; - - clang::Selector method_selector = ast->Selectors.getSelector (num_selectors_with_args ? selector_idents.size() : 0, - selector_idents.data()); - - clang::QualType method_qual_type(ClangUtil::GetQualType(method_clang_type)); - - // Populate the method decl with parameter decls - const clang::Type *method_type(method_qual_type.getTypePtr()); - - if (method_type == nullptr) - return nullptr; - - const clang::FunctionProtoType *method_function_prototype (llvm::dyn_cast<clang::FunctionProtoType>(method_type)); - - if (!method_function_prototype) - return nullptr; - - - bool is_synthesized = false; - bool is_defined = false; - clang::ObjCMethodDecl::ImplementationControl imp_control = clang::ObjCMethodDecl::None; - - const unsigned num_args = method_function_prototype->getNumParams(); - - if (num_args != num_selectors_with_args) - return nullptr; // some debug information is corrupt. We are not going to deal with it. - - clang::ObjCMethodDecl *objc_method_decl = clang::ObjCMethodDecl::Create( - *ast, - clang::SourceLocation(), // beginLoc, - clang::SourceLocation(), // endLoc, - method_selector, method_function_prototype->getReturnType(), - nullptr, // TypeSourceInfo *ResultTInfo, - ClangASTContext::GetASTContext(ast)->GetDeclContextForType(ClangUtil::GetQualType(type)), name[0] == '-', - is_variadic, is_synthesized, - true, // is_implicitly_declared; we force this to true because we don't have source locations - is_defined, imp_control, false /*has_related_result_type*/); - - if (objc_method_decl == nullptr) - return nullptr; - - if (num_args > 0) - { - llvm::SmallVector<clang::ParmVarDecl *, 12> params; - - for (unsigned param_index = 0; param_index < num_args; ++param_index) - { - params.push_back (clang::ParmVarDecl::Create (*ast, - objc_method_decl, - clang::SourceLocation(), - clang::SourceLocation(), - nullptr, // anonymous - method_function_prototype->getParamType(param_index), - nullptr, - clang::SC_Auto, - nullptr)); - } - - objc_method_decl->setMethodParams(*ast, llvm::ArrayRef<clang::ParmVarDecl*>(params), llvm::ArrayRef<clang::SourceLocation>()); + selector_start++; + llvm::SmallVector<clang::IdentifierInfo *, 12> selector_idents; + + size_t len = 0; + const char *start; + // printf ("name = '%s'\n", name); + + unsigned num_selectors_with_args = 0; + for (start = selector_start; start && *start != '\0' && *start != ']'; + start += len) { + len = ::strcspn(start, ":]"); + bool has_arg = (start[len] == ':'); + if (has_arg) + ++num_selectors_with_args; + selector_idents.push_back(&ast->Idents.get(llvm::StringRef(start, len))); + if (has_arg) + len += 1; + } + + if (selector_idents.size() == 0) + return nullptr; + + clang::Selector method_selector = ast->Selectors.getSelector( + num_selectors_with_args ? selector_idents.size() : 0, + selector_idents.data()); + + clang::QualType method_qual_type(ClangUtil::GetQualType(method_clang_type)); + + // Populate the method decl with parameter decls + const clang::Type *method_type(method_qual_type.getTypePtr()); + + if (method_type == nullptr) + return nullptr; + + const clang::FunctionProtoType *method_function_prototype( + llvm::dyn_cast<clang::FunctionProtoType>(method_type)); + + if (!method_function_prototype) + return nullptr; + + bool is_synthesized = false; + bool is_defined = false; + clang::ObjCMethodDecl::ImplementationControl imp_control = + clang::ObjCMethodDecl::None; + + const unsigned num_args = method_function_prototype->getNumParams(); + + if (num_args != num_selectors_with_args) + return nullptr; // some debug information is corrupt. We are not going to + // deal with it. + + clang::ObjCMethodDecl *objc_method_decl = clang::ObjCMethodDecl::Create( + *ast, + clang::SourceLocation(), // beginLoc, + clang::SourceLocation(), // endLoc, + method_selector, method_function_prototype->getReturnType(), + nullptr, // TypeSourceInfo *ResultTInfo, + ClangASTContext::GetASTContext(ast)->GetDeclContextForType( + ClangUtil::GetQualType(type)), + name[0] == '-', is_variadic, is_synthesized, + true, // is_implicitly_declared; we force this to true because we don't + // have source locations + is_defined, imp_control, false /*has_related_result_type*/); + + if (objc_method_decl == nullptr) + return nullptr; + + if (num_args > 0) { + llvm::SmallVector<clang::ParmVarDecl *, 12> params; + + for (unsigned param_index = 0; param_index < num_args; ++param_index) { + params.push_back(clang::ParmVarDecl::Create( + *ast, objc_method_decl, clang::SourceLocation(), + clang::SourceLocation(), + nullptr, // anonymous + method_function_prototype->getParamType(param_index), nullptr, + clang::SC_Auto, nullptr)); } - - class_interface_decl->addDecl (objc_method_decl); - + + objc_method_decl->setMethodParams( + *ast, llvm::ArrayRef<clang::ParmVarDecl *>(params), + llvm::ArrayRef<clang::SourceLocation>()); + } + + class_interface_decl->addDecl(objc_method_decl); + #ifdef LLDB_CONFIGURATION_DEBUG - VerifyDecl(objc_method_decl); + VerifyDecl(objc_method_decl); #endif - - return objc_method_decl; + + return objc_method_decl; } -bool -ClangASTContext::GetHasExternalStorage (const CompilerType &type) -{ - if (ClangUtil::IsClangType(type)) - return false; +bool ClangASTContext::GetHasExternalStorage(const CompilerType &type) { + if (ClangUtil::IsClangType(type)) + return false; - clang::QualType qual_type(ClangUtil::GetCanonicalQualType(type)); + clang::QualType qual_type(ClangUtil::GetCanonicalQualType(type)); - const clang::Type::TypeClass type_class = qual_type->getTypeClass(); - switch (type_class) - { - case clang::Type::Record: - { - clang::CXXRecordDecl *cxx_record_decl = qual_type->getAsCXXRecordDecl(); - if (cxx_record_decl) - return cxx_record_decl->hasExternalLexicalStorage () || cxx_record_decl->hasExternalVisibleStorage(); - } - break; + const clang::Type::TypeClass type_class = qual_type->getTypeClass(); + switch (type_class) { + case clang::Type::Record: { + clang::CXXRecordDecl *cxx_record_decl = qual_type->getAsCXXRecordDecl(); + if (cxx_record_decl) + return cxx_record_decl->hasExternalLexicalStorage() || + cxx_record_decl->hasExternalVisibleStorage(); + } break; - case clang::Type::Enum: - { - clang::EnumDecl *enum_decl = llvm::cast<clang::EnumType>(qual_type)->getDecl(); - if (enum_decl) - return enum_decl->hasExternalLexicalStorage () || enum_decl->hasExternalVisibleStorage(); - } - break; + case clang::Type::Enum: { + clang::EnumDecl *enum_decl = + llvm::cast<clang::EnumType>(qual_type)->getDecl(); + if (enum_decl) + return enum_decl->hasExternalLexicalStorage() || + enum_decl->hasExternalVisibleStorage(); + } break; - case clang::Type::ObjCObject: - case clang::Type::ObjCInterface: - { - const clang::ObjCObjectType *objc_class_type = llvm::dyn_cast<clang::ObjCObjectType>(qual_type.getTypePtr()); - assert (objc_class_type); - if (objc_class_type) - { - clang::ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface(); - - if (class_interface_decl) - return class_interface_decl->hasExternalLexicalStorage () || class_interface_decl->hasExternalVisibleStorage (); - } - } - break; + case clang::Type::ObjCObject: + case clang::Type::ObjCInterface: { + const clang::ObjCObjectType *objc_class_type = + llvm::dyn_cast<clang::ObjCObjectType>(qual_type.getTypePtr()); + assert(objc_class_type); + if (objc_class_type) { + clang::ObjCInterfaceDecl *class_interface_decl = + objc_class_type->getInterface(); + + if (class_interface_decl) + return class_interface_decl->hasExternalLexicalStorage() || + class_interface_decl->hasExternalVisibleStorage(); + } + } break; + + case clang::Type::Typedef: + return GetHasExternalStorage(CompilerType( + type.GetTypeSystem(), llvm::cast<clang::TypedefType>(qual_type) + ->getDecl() + ->getUnderlyingType() + .getAsOpaquePtr())); + + case clang::Type::Auto: + return GetHasExternalStorage(CompilerType( + type.GetTypeSystem(), llvm::cast<clang::AutoType>(qual_type) + ->getDeducedType() + .getAsOpaquePtr())); + + case clang::Type::Elaborated: + return GetHasExternalStorage(CompilerType( + type.GetTypeSystem(), llvm::cast<clang::ElaboratedType>(qual_type) + ->getNamedType() + .getAsOpaquePtr())); + + case clang::Type::Paren: + return GetHasExternalStorage(CompilerType( + type.GetTypeSystem(), + llvm::cast<clang::ParenType>(qual_type)->desugar().getAsOpaquePtr())); + + default: + break; + } + return false; +} + +bool ClangASTContext::SetHasExternalStorage(lldb::opaque_compiler_type_t type, + bool has_extern) { + if (!type) + return false; - case clang::Type::Typedef: - return GetHasExternalStorage (CompilerType(type.GetTypeSystem(), llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType().getAsOpaquePtr())); + clang::QualType qual_type(GetCanonicalQualType(type)); - case clang::Type::Auto: - return GetHasExternalStorage (CompilerType(type.GetTypeSystem(), llvm::cast<clang::AutoType>(qual_type)->getDeducedType().getAsOpaquePtr())); - - case clang::Type::Elaborated: - return GetHasExternalStorage (CompilerType(type.GetTypeSystem(), llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType().getAsOpaquePtr())); + const clang::Type::TypeClass type_class = qual_type->getTypeClass(); + switch (type_class) { + case clang::Type::Record: { + clang::CXXRecordDecl *cxx_record_decl = qual_type->getAsCXXRecordDecl(); + if (cxx_record_decl) { + cxx_record_decl->setHasExternalLexicalStorage(has_extern); + cxx_record_decl->setHasExternalVisibleStorage(has_extern); + return true; + } + } break; - case clang::Type::Paren: - return GetHasExternalStorage (CompilerType(type.GetTypeSystem(), llvm::cast<clang::ParenType>(qual_type)->desugar().getAsOpaquePtr())); + case clang::Type::Enum: { + clang::EnumDecl *enum_decl = + llvm::cast<clang::EnumType>(qual_type)->getDecl(); + if (enum_decl) { + enum_decl->setHasExternalLexicalStorage(has_extern); + enum_decl->setHasExternalVisibleStorage(has_extern); + return true; + } + } break; - default: - break; + case clang::Type::ObjCObject: + case clang::Type::ObjCInterface: { + const clang::ObjCObjectType *objc_class_type = + llvm::dyn_cast<clang::ObjCObjectType>(qual_type.getTypePtr()); + assert(objc_class_type); + if (objc_class_type) { + clang::ObjCInterfaceDecl *class_interface_decl = + objc_class_type->getInterface(); + + if (class_interface_decl) { + class_interface_decl->setHasExternalLexicalStorage(has_extern); + class_interface_decl->setHasExternalVisibleStorage(has_extern); + return true; + } } - return false; -} + } break; + case clang::Type::Typedef: + return SetHasExternalStorage(llvm::cast<clang::TypedefType>(qual_type) + ->getDecl() + ->getUnderlyingType() + .getAsOpaquePtr(), + has_extern); -bool -ClangASTContext::SetHasExternalStorage (lldb::opaque_compiler_type_t type, bool has_extern) -{ - if (!type) - return false; - - clang::QualType qual_type (GetCanonicalQualType(type)); - - const clang::Type::TypeClass type_class = qual_type->getTypeClass(); - switch (type_class) - { - case clang::Type::Record: - { - clang::CXXRecordDecl *cxx_record_decl = qual_type->getAsCXXRecordDecl(); - if (cxx_record_decl) - { - cxx_record_decl->setHasExternalLexicalStorage (has_extern); - cxx_record_decl->setHasExternalVisibleStorage (has_extern); - return true; - } - } - break; - - case clang::Type::Enum: - { - clang::EnumDecl *enum_decl = llvm::cast<clang::EnumType>(qual_type)->getDecl(); - if (enum_decl) - { - enum_decl->setHasExternalLexicalStorage (has_extern); - enum_decl->setHasExternalVisibleStorage (has_extern); - return true; - } - } - break; - - case clang::Type::ObjCObject: - case clang::Type::ObjCInterface: - { - const clang::ObjCObjectType *objc_class_type = llvm::dyn_cast<clang::ObjCObjectType>(qual_type.getTypePtr()); - assert (objc_class_type); - if (objc_class_type) - { - clang::ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface(); - - if (class_interface_decl) - { - class_interface_decl->setHasExternalLexicalStorage (has_extern); - class_interface_decl->setHasExternalVisibleStorage (has_extern); - return true; - } - } - } - break; - - case clang::Type::Typedef: - return SetHasExternalStorage(llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType().getAsOpaquePtr(), has_extern); - - case clang::Type::Auto: - return SetHasExternalStorage (llvm::cast<clang::AutoType>(qual_type)->getDeducedType().getAsOpaquePtr(), has_extern); - - case clang::Type::Elaborated: - return SetHasExternalStorage (llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType().getAsOpaquePtr(), has_extern); - - case clang::Type::Paren: - return SetHasExternalStorage (llvm::cast<clang::ParenType>(qual_type)->desugar().getAsOpaquePtr(), has_extern); - - default: - break; - } - return false; -} + case clang::Type::Auto: + return SetHasExternalStorage(llvm::cast<clang::AutoType>(qual_type) + ->getDeducedType() + .getAsOpaquePtr(), + has_extern); + + case clang::Type::Elaborated: + return SetHasExternalStorage(llvm::cast<clang::ElaboratedType>(qual_type) + ->getNamedType() + .getAsOpaquePtr(), + has_extern); + + case clang::Type::Paren: + return SetHasExternalStorage( + llvm::cast<clang::ParenType>(qual_type)->desugar().getAsOpaquePtr(), + has_extern); + default: + break; + } + return false; +} #pragma mark TagDecl -bool -ClangASTContext::StartTagDeclarationDefinition (const CompilerType &type) -{ - clang::QualType qual_type(ClangUtil::GetQualType(type)); - if (!qual_type.isNull()) - { - const clang::TagType *tag_type = qual_type->getAs<clang::TagType>(); - if (tag_type) - { - clang::TagDecl *tag_decl = tag_type->getDecl(); - if (tag_decl) - { - tag_decl->startDefinition(); - return true; - } - } - - const clang::ObjCObjectType *object_type = qual_type->getAs<clang::ObjCObjectType>(); - if (object_type) - { - clang::ObjCInterfaceDecl *interface_decl = object_type->getInterface(); - if (interface_decl) - { - interface_decl->startDefinition(); - return true; - } - } +bool ClangASTContext::StartTagDeclarationDefinition(const CompilerType &type) { + clang::QualType qual_type(ClangUtil::GetQualType(type)); + if (!qual_type.isNull()) { + const clang::TagType *tag_type = qual_type->getAs<clang::TagType>(); + if (tag_type) { + clang::TagDecl *tag_decl = tag_type->getDecl(); + if (tag_decl) { + tag_decl->startDefinition(); + return true; + } } - return false; -} -bool -ClangASTContext::CompleteTagDeclarationDefinition (const CompilerType& type) -{ - clang::QualType qual_type(ClangUtil::GetQualType(type)); - if (!qual_type.isNull()) - { - // Make sure we use the same methodology as ClangASTContext::StartTagDeclarationDefinition() - // as to how we start/end the definition. Previously we were calling - const clang::TagType *tag_type = qual_type->getAs<clang::TagType>(); - if (tag_type) - { - clang::TagDecl *tag_decl = tag_type->getDecl(); - if (tag_decl) - { - clang::CXXRecordDecl *cxx_record_decl = llvm::dyn_cast_or_null<clang::CXXRecordDecl>(tag_decl); - - if (cxx_record_decl) - { - if (!cxx_record_decl->isCompleteDefinition()) - cxx_record_decl->completeDefinition(); - cxx_record_decl->setHasLoadedFieldsFromExternalStorage(true); - cxx_record_decl->setHasExternalLexicalStorage (false); - cxx_record_decl->setHasExternalVisibleStorage (false); - return true; - } - } + const clang::ObjCObjectType *object_type = + qual_type->getAs<clang::ObjCObjectType>(); + if (object_type) { + clang::ObjCInterfaceDecl *interface_decl = object_type->getInterface(); + if (interface_decl) { + interface_decl->startDefinition(); + return true; + } + } + } + return false; +} + +bool ClangASTContext::CompleteTagDeclarationDefinition( + const CompilerType &type) { + clang::QualType qual_type(ClangUtil::GetQualType(type)); + if (!qual_type.isNull()) { + // Make sure we use the same methodology as + // ClangASTContext::StartTagDeclarationDefinition() + // as to how we start/end the definition. Previously we were calling + const clang::TagType *tag_type = qual_type->getAs<clang::TagType>(); + if (tag_type) { + clang::TagDecl *tag_decl = tag_type->getDecl(); + if (tag_decl) { + clang::CXXRecordDecl *cxx_record_decl = + llvm::dyn_cast_or_null<clang::CXXRecordDecl>(tag_decl); + + if (cxx_record_decl) { + if (!cxx_record_decl->isCompleteDefinition()) + cxx_record_decl->completeDefinition(); + cxx_record_decl->setHasLoadedFieldsFromExternalStorage(true); + cxx_record_decl->setHasExternalLexicalStorage(false); + cxx_record_decl->setHasExternalVisibleStorage(false); + return true; } + } + } - const clang::EnumType *enutype = qual_type->getAs<clang::EnumType>(); - - if (enutype) - { - clang::EnumDecl *enum_decl = enutype->getDecl(); - - if (enum_decl) - { - if (!enum_decl->isCompleteDefinition()) - { - ClangASTContext *lldb_ast = llvm::dyn_cast<ClangASTContext>(type.GetTypeSystem()); - if (lldb_ast == nullptr) - return false; - clang::ASTContext *ast = lldb_ast->getASTContext(); - - /// TODO This really needs to be fixed. - - QualType integer_type(enum_decl->getIntegerType()); - if (!integer_type.isNull()) - { - unsigned NumPositiveBits = 1; - unsigned NumNegativeBits = 0; - - clang::QualType promotion_qual_type; - // If the enum integer type is less than an integer in bit width, - // then we must promote it to an integer size. - if (ast->getTypeSize(enum_decl->getIntegerType()) < ast->getTypeSize(ast->IntTy)) - { - if (enum_decl->getIntegerType()->isSignedIntegerType()) - promotion_qual_type = ast->IntTy; - else - promotion_qual_type = ast->UnsignedIntTy; - } - else - promotion_qual_type = enum_decl->getIntegerType(); - - enum_decl->completeDefinition(enum_decl->getIntegerType(), promotion_qual_type, NumPositiveBits, NumNegativeBits); - } - } - return true; - } + const clang::EnumType *enutype = qual_type->getAs<clang::EnumType>(); + + if (enutype) { + clang::EnumDecl *enum_decl = enutype->getDecl(); + + if (enum_decl) { + if (!enum_decl->isCompleteDefinition()) { + ClangASTContext *lldb_ast = + llvm::dyn_cast<ClangASTContext>(type.GetTypeSystem()); + if (lldb_ast == nullptr) + return false; + clang::ASTContext *ast = lldb_ast->getASTContext(); + + /// TODO This really needs to be fixed. + + QualType integer_type(enum_decl->getIntegerType()); + if (!integer_type.isNull()) { + unsigned NumPositiveBits = 1; + unsigned NumNegativeBits = 0; + + clang::QualType promotion_qual_type; + // If the enum integer type is less than an integer in bit width, + // then we must promote it to an integer size. + if (ast->getTypeSize(enum_decl->getIntegerType()) < + ast->getTypeSize(ast->IntTy)) { + if (enum_decl->getIntegerType()->isSignedIntegerType()) + promotion_qual_type = ast->IntTy; + else + promotion_qual_type = ast->UnsignedIntTy; + } else + promotion_qual_type = enum_decl->getIntegerType(); + + enum_decl->completeDefinition(enum_decl->getIntegerType(), + promotion_qual_type, NumPositiveBits, + NumNegativeBits); + } } + return true; + } } - return false; + } + return false; } -bool -ClangASTContext::AddEnumerationValueToEnumerationType (lldb::opaque_compiler_type_t type, - const CompilerType &enumerator_clang_type, - const Declaration &decl, - const char *name, - int64_t enum_value, - uint32_t enum_value_bit_size) -{ - if (type && enumerator_clang_type.IsValid() && name && name[0]) - { - clang::QualType enum_qual_type (GetCanonicalQualType(type)); - - bool is_signed = false; - enumerator_clang_type.IsIntegerType (is_signed); - const clang::Type *clang_type = enum_qual_type.getTypePtr(); - if (clang_type) - { - const clang::EnumType *enutype = llvm::dyn_cast<clang::EnumType>(clang_type); - - if (enutype) - { - llvm::APSInt enum_llvm_apsint(enum_value_bit_size, is_signed); - enum_llvm_apsint = enum_value; - clang::EnumConstantDecl *enumerator_decl = clang::EnumConstantDecl::Create( - *getASTContext(), enutype->getDecl(), clang::SourceLocation(), - name ? &getASTContext()->Idents.get(name) : nullptr, // Identifier - ClangUtil::GetQualType(enumerator_clang_type), nullptr, enum_llvm_apsint); - - if (enumerator_decl) - { - enutype->getDecl()->addDecl(enumerator_decl); - +bool ClangASTContext::AddEnumerationValueToEnumerationType( + lldb::opaque_compiler_type_t type, + const CompilerType &enumerator_clang_type, const Declaration &decl, + const char *name, int64_t enum_value, uint32_t enum_value_bit_size) { + if (type && enumerator_clang_type.IsValid() && name && name[0]) { + clang::QualType enum_qual_type(GetCanonicalQualType(type)); + + bool is_signed = false; + enumerator_clang_type.IsIntegerType(is_signed); + const clang::Type *clang_type = enum_qual_type.getTypePtr(); + if (clang_type) { + const clang::EnumType *enutype = + llvm::dyn_cast<clang::EnumType>(clang_type); + + if (enutype) { + llvm::APSInt enum_llvm_apsint(enum_value_bit_size, is_signed); + enum_llvm_apsint = enum_value; + clang::EnumConstantDecl *enumerator_decl = + clang::EnumConstantDecl::Create( + *getASTContext(), enutype->getDecl(), clang::SourceLocation(), + name ? &getASTContext()->Idents.get(name) + : nullptr, // Identifier + ClangUtil::GetQualType(enumerator_clang_type), + nullptr, enum_llvm_apsint); + + if (enumerator_decl) { + enutype->getDecl()->addDecl(enumerator_decl); + #ifdef LLDB_CONFIGURATION_DEBUG - VerifyDecl(enumerator_decl); + VerifyDecl(enumerator_decl); #endif - - return true; - } - } + + return true; } + } } - return false; + } + return false; } CompilerType -ClangASTContext::GetEnumerationIntegerType (lldb::opaque_compiler_type_t type) -{ - clang::QualType enum_qual_type (GetCanonicalQualType(type)); - const clang::Type *clang_type = enum_qual_type.getTypePtr(); - if (clang_type) - { - const clang::EnumType *enutype = llvm::dyn_cast<clang::EnumType>(clang_type); - if (enutype) - { - clang::EnumDecl *enum_decl = enutype->getDecl(); - if (enum_decl) - return CompilerType (getASTContext(), enum_decl->getIntegerType()); - } +ClangASTContext::GetEnumerationIntegerType(lldb::opaque_compiler_type_t type) { + clang::QualType enum_qual_type(GetCanonicalQualType(type)); + const clang::Type *clang_type = enum_qual_type.getTypePtr(); + if (clang_type) { + const clang::EnumType *enutype = + llvm::dyn_cast<clang::EnumType>(clang_type); + if (enutype) { + clang::EnumDecl *enum_decl = enutype->getDecl(); + if (enum_decl) + return CompilerType(getASTContext(), enum_decl->getIntegerType()); } - return CompilerType(); + } + return CompilerType(); } CompilerType -ClangASTContext::CreateMemberPointerType (const CompilerType& type, const CompilerType &pointee_type) -{ - if (type && pointee_type.IsValid() && type.GetTypeSystem() == pointee_type.GetTypeSystem()) - { - ClangASTContext *ast = llvm::dyn_cast<ClangASTContext>(type.GetTypeSystem()); - if (!ast) - return CompilerType(); - return CompilerType(ast->getASTContext(), - ast->getASTContext()->getMemberPointerType(ClangUtil::GetQualType(pointee_type), - ClangUtil::GetQualType(type).getTypePtr())); - } - return CompilerType(); +ClangASTContext::CreateMemberPointerType(const CompilerType &type, + const CompilerType &pointee_type) { + if (type && pointee_type.IsValid() && + type.GetTypeSystem() == pointee_type.GetTypeSystem()) { + ClangASTContext *ast = + llvm::dyn_cast<ClangASTContext>(type.GetTypeSystem()); + if (!ast) + return CompilerType(); + return CompilerType(ast->getASTContext(), + ast->getASTContext()->getMemberPointerType( + ClangUtil::GetQualType(pointee_type), + ClangUtil::GetQualType(type).getTypePtr())); + } + return CompilerType(); } - size_t -ClangASTContext::ConvertStringToFloatValue (lldb::opaque_compiler_type_t type, const char *s, uint8_t *dst, size_t dst_size) -{ - if (type) - { - clang::QualType qual_type (GetCanonicalQualType(type)); - uint32_t count = 0; - bool is_complex = false; - if (IsFloatingPointType (type, count, is_complex)) - { - // TODO: handle complex and vector types - if (count != 1) - return false; - - llvm::StringRef s_sref(s); - llvm::APFloat ap_float(getASTContext()->getFloatTypeSemantics(qual_type), s_sref); - - const uint64_t bit_size = getASTContext()->getTypeSize (qual_type); - const uint64_t byte_size = bit_size / 8; - if (dst_size >= byte_size) - { - Scalar scalar = ap_float.bitcastToAPInt().zextOrTrunc(llvm::NextPowerOf2(byte_size) * 8); - lldb_private::Error get_data_error; - if (scalar.GetAsMemoryData(dst, byte_size, lldb_private::endian::InlHostByteOrder(), get_data_error)) - return byte_size; - } - } - } - return 0; -} +ClangASTContext::ConvertStringToFloatValue(lldb::opaque_compiler_type_t type, + const char *s, uint8_t *dst, + size_t dst_size) { + if (type) { + clang::QualType qual_type(GetCanonicalQualType(type)); + uint32_t count = 0; + bool is_complex = false; + if (IsFloatingPointType(type, count, is_complex)) { + // TODO: handle complex and vector types + if (count != 1) + return false; + llvm::StringRef s_sref(s); + llvm::APFloat ap_float(getASTContext()->getFloatTypeSemantics(qual_type), + s_sref); + const uint64_t bit_size = getASTContext()->getTypeSize(qual_type); + const uint64_t byte_size = bit_size / 8; + if (dst_size >= byte_size) { + Scalar scalar = ap_float.bitcastToAPInt().zextOrTrunc( + llvm::NextPowerOf2(byte_size) * 8); + lldb_private::Error get_data_error; + if (scalar.GetAsMemoryData(dst, byte_size, + lldb_private::endian::InlHostByteOrder(), + get_data_error)) + return byte_size; + } + } + } + return 0; +} //---------------------------------------------------------------------- // Dumping types //---------------------------------------------------------------------- #define DEPTH_INCREMENT 2 -void -ClangASTContext::DumpValue (lldb::opaque_compiler_type_t type, ExecutionContext *exe_ctx, - Stream *s, - lldb::Format format, - const lldb_private::DataExtractor &data, - lldb::offset_t data_byte_offset, - size_t data_byte_size, - uint32_t bitfield_bit_size, - uint32_t bitfield_bit_offset, - bool show_types, - bool show_summary, - bool verbose, - uint32_t depth) -{ - if (!type) - return; - +void ClangASTContext::DumpValue( + lldb::opaque_compiler_type_t type, ExecutionContext *exe_ctx, Stream *s, + lldb::Format format, const lldb_private::DataExtractor &data, + lldb::offset_t data_byte_offset, size_t data_byte_size, + uint32_t bitfield_bit_size, uint32_t bitfield_bit_offset, bool show_types, + bool show_summary, bool verbose, uint32_t depth) { + if (!type) + return; + + clang::QualType qual_type(GetQualType(type)); + switch (qual_type->getTypeClass()) { + case clang::Type::Record: + if (GetCompleteType(type)) { + const clang::RecordType *record_type = + llvm::cast<clang::RecordType>(qual_type.getTypePtr()); + const clang::RecordDecl *record_decl = record_type->getDecl(); + assert(record_decl); + uint32_t field_bit_offset = 0; + uint32_t field_byte_offset = 0; + const clang::ASTRecordLayout &record_layout = + getASTContext()->getASTRecordLayout(record_decl); + uint32_t child_idx = 0; + + const clang::CXXRecordDecl *cxx_record_decl = + llvm::dyn_cast<clang::CXXRecordDecl>(record_decl); + if (cxx_record_decl) { + // We might have base classes to print out first + clang::CXXRecordDecl::base_class_const_iterator base_class, + base_class_end; + for (base_class = cxx_record_decl->bases_begin(), + base_class_end = cxx_record_decl->bases_end(); + base_class != base_class_end; ++base_class) { + const clang::CXXRecordDecl *base_class_decl = + llvm::cast<clang::CXXRecordDecl>( + base_class->getType()->getAs<clang::RecordType>()->getDecl()); + + // Skip empty base classes + if (verbose == false && + ClangASTContext::RecordHasFields(base_class_decl) == false) + continue; + + if (base_class->isVirtual()) + field_bit_offset = + record_layout.getVBaseClassOffset(base_class_decl) + .getQuantity() * + 8; + else + field_bit_offset = record_layout.getBaseClassOffset(base_class_decl) + .getQuantity() * + 8; + field_byte_offset = field_bit_offset / 8; + assert(field_bit_offset % 8 == 0); + if (child_idx == 0) + s->PutChar('{'); + else + s->PutChar(','); + + clang::QualType base_class_qual_type = base_class->getType(); + std::string base_class_type_name(base_class_qual_type.getAsString()); + + // Indent and print the base class type name + s->Printf("\n%*s%s ", depth + DEPTH_INCREMENT, "", + base_class_type_name.c_str()); + + clang::TypeInfo base_class_type_info = + getASTContext()->getTypeInfo(base_class_qual_type); + + // Dump the value of the member + CompilerType base_clang_type(getASTContext(), base_class_qual_type); + base_clang_type.DumpValue( + exe_ctx, + s, // Stream to dump to + base_clang_type + .GetFormat(), // The format with which to display the member + data, // Data buffer containing all bytes for this type + data_byte_offset + field_byte_offset, // Offset into "data" where + // to grab value from + base_class_type_info.Width / 8, // Size of this type in bytes + 0, // Bitfield bit size + 0, // Bitfield bit offset + show_types, // Boolean indicating if we should show the variable + // types + show_summary, // Boolean indicating if we should show a summary + // for the current type + verbose, // Verbose output? + depth + DEPTH_INCREMENT); // Scope depth for any types that have + // children + + ++child_idx; + } + } + uint32_t field_idx = 0; + clang::RecordDecl::field_iterator field, field_end; + for (field = record_decl->field_begin(), + field_end = record_decl->field_end(); + field != field_end; ++field, ++field_idx, ++child_idx) { + // Print the starting squiggly bracket (if this is the + // first member) or comma (for member 2 and beyond) for + // the struct/union/class member. + if (child_idx == 0) + s->PutChar('{'); + else + s->PutChar(','); + + // Indent + s->Printf("\n%*s", depth + DEPTH_INCREMENT, ""); + + clang::QualType field_type = field->getType(); + // Print the member type if requested + // Figure out the type byte size (field_type_info.first) and + // alignment (field_type_info.second) from the AST context. + clang::TypeInfo field_type_info = + getASTContext()->getTypeInfo(field_type); + assert(field_idx < record_layout.getFieldCount()); + // Figure out the field offset within the current struct/union/class + // type + field_bit_offset = record_layout.getFieldOffset(field_idx); + field_byte_offset = field_bit_offset / 8; + uint32_t field_bitfield_bit_size = 0; + uint32_t field_bitfield_bit_offset = 0; + if (ClangASTContext::FieldIsBitfield(getASTContext(), *field, + field_bitfield_bit_size)) + field_bitfield_bit_offset = field_bit_offset % 8; + + if (show_types) { + std::string field_type_name(field_type.getAsString()); + if (field_bitfield_bit_size > 0) + s->Printf("(%s:%u) ", field_type_name.c_str(), + field_bitfield_bit_size); + else + s->Printf("(%s) ", field_type_name.c_str()); + } + // Print the member name and equal sign + s->Printf("%s = ", field->getNameAsString().c_str()); + + // Dump the value of the member + CompilerType field_clang_type(getASTContext(), field_type); + field_clang_type.DumpValue( + exe_ctx, + s, // Stream to dump to + field_clang_type + .GetFormat(), // The format with which to display the member + data, // Data buffer containing all bytes for this type + data_byte_offset + field_byte_offset, // Offset into "data" where to + // grab value from + field_type_info.Width / 8, // Size of this type in bytes + field_bitfield_bit_size, // Bitfield bit size + field_bitfield_bit_offset, // Bitfield bit offset + show_types, // Boolean indicating if we should show the variable + // types + show_summary, // Boolean indicating if we should show a summary for + // the current type + verbose, // Verbose output? + depth + DEPTH_INCREMENT); // Scope depth for any types that have + // children + } + + // Indent the trailing squiggly bracket + if (child_idx > 0) + s->Printf("\n%*s}", depth, ""); + } + return; + + case clang::Type::Enum: + if (GetCompleteType(type)) { + const clang::EnumType *enutype = + llvm::cast<clang::EnumType>(qual_type.getTypePtr()); + const clang::EnumDecl *enum_decl = enutype->getDecl(); + assert(enum_decl); + clang::EnumDecl::enumerator_iterator enum_pos, enum_end_pos; + lldb::offset_t offset = data_byte_offset; + const int64_t enum_value = data.GetMaxU64Bitfield( + &offset, data_byte_size, bitfield_bit_size, bitfield_bit_offset); + for (enum_pos = enum_decl->enumerator_begin(), + enum_end_pos = enum_decl->enumerator_end(); + enum_pos != enum_end_pos; ++enum_pos) { + if (enum_pos->getInitVal() == enum_value) { + s->Printf("%s", enum_pos->getNameAsString().c_str()); + return; + } + } + // If we have gotten here we didn't get find the enumerator in the + // enum decl, so just print the integer. + s->Printf("%" PRIi64, enum_value); + } + return; + + case clang::Type::ConstantArray: { + const clang::ConstantArrayType *array = + llvm::cast<clang::ConstantArrayType>(qual_type.getTypePtr()); + bool is_array_of_characters = false; + clang::QualType element_qual_type = array->getElementType(); + + const clang::Type *canonical_type = + element_qual_type->getCanonicalTypeInternal().getTypePtr(); + if (canonical_type) + is_array_of_characters = canonical_type->isCharType(); + + const uint64_t element_count = array->getSize().getLimitedValue(); + + clang::TypeInfo field_type_info = + getASTContext()->getTypeInfo(element_qual_type); + + uint32_t element_idx = 0; + uint32_t element_offset = 0; + uint64_t element_byte_size = field_type_info.Width / 8; + uint32_t element_stride = element_byte_size; + + if (is_array_of_characters) { + s->PutChar('"'); + data.Dump(s, data_byte_offset, lldb::eFormatChar, element_byte_size, + element_count, UINT32_MAX, LLDB_INVALID_ADDRESS, 0, 0); + s->PutChar('"'); + return; + } else { + CompilerType element_clang_type(getASTContext(), element_qual_type); + lldb::Format element_format = element_clang_type.GetFormat(); + + for (element_idx = 0; element_idx < element_count; ++element_idx) { + // Print the starting squiggly bracket (if this is the + // first member) or comman (for member 2 and beyong) for + // the struct/union/class member. + if (element_idx == 0) + s->PutChar('{'); + else + s->PutChar(','); + + // Indent and print the index + s->Printf("\n%*s[%u] ", depth + DEPTH_INCREMENT, "", element_idx); + + // Figure out the field offset within the current struct/union/class + // type + element_offset = element_idx * element_stride; + + // Dump the value of the member + element_clang_type.DumpValue( + exe_ctx, + s, // Stream to dump to + element_format, // The format with which to display the element + data, // Data buffer containing all bytes for this type + data_byte_offset + + element_offset, // Offset into "data" where to grab value from + element_byte_size, // Size of this type in bytes + 0, // Bitfield bit size + 0, // Bitfield bit offset + show_types, // Boolean indicating if we should show the variable + // types + show_summary, // Boolean indicating if we should show a summary for + // the current type + verbose, // Verbose output? + depth + DEPTH_INCREMENT); // Scope depth for any types that have + // children + } + + // Indent the trailing squiggly bracket + if (element_idx > 0) + s->Printf("\n%*s}", depth, ""); + } + } + return; + + case clang::Type::Typedef: { + clang::QualType typedef_qual_type = + llvm::cast<clang::TypedefType>(qual_type) + ->getDecl() + ->getUnderlyingType(); + + CompilerType typedef_clang_type(getASTContext(), typedef_qual_type); + lldb::Format typedef_format = typedef_clang_type.GetFormat(); + clang::TypeInfo typedef_type_info = + getASTContext()->getTypeInfo(typedef_qual_type); + uint64_t typedef_byte_size = typedef_type_info.Width / 8; + + return typedef_clang_type.DumpValue( + exe_ctx, + s, // Stream to dump to + typedef_format, // The format with which to display the element + data, // Data buffer containing all bytes for this type + data_byte_offset, // Offset into "data" where to grab value from + typedef_byte_size, // Size of this type in bytes + bitfield_bit_size, // Bitfield bit size + bitfield_bit_offset, // Bitfield bit offset + show_types, // Boolean indicating if we should show the variable types + show_summary, // Boolean indicating if we should show a summary for the + // current type + verbose, // Verbose output? + depth); // Scope depth for any types that have children + } break; + + case clang::Type::Auto: { + clang::QualType elaborated_qual_type = + llvm::cast<clang::AutoType>(qual_type)->getDeducedType(); + CompilerType elaborated_clang_type(getASTContext(), elaborated_qual_type); + lldb::Format elaborated_format = elaborated_clang_type.GetFormat(); + clang::TypeInfo elaborated_type_info = + getASTContext()->getTypeInfo(elaborated_qual_type); + uint64_t elaborated_byte_size = elaborated_type_info.Width / 8; + + return elaborated_clang_type.DumpValue( + exe_ctx, + s, // Stream to dump to + elaborated_format, // The format with which to display the element + data, // Data buffer containing all bytes for this type + data_byte_offset, // Offset into "data" where to grab value from + elaborated_byte_size, // Size of this type in bytes + bitfield_bit_size, // Bitfield bit size + bitfield_bit_offset, // Bitfield bit offset + show_types, // Boolean indicating if we should show the variable types + show_summary, // Boolean indicating if we should show a summary for the + // current type + verbose, // Verbose output? + depth); // Scope depth for any types that have children + } break; + + case clang::Type::Elaborated: { + clang::QualType elaborated_qual_type = + llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType(); + CompilerType elaborated_clang_type(getASTContext(), elaborated_qual_type); + lldb::Format elaborated_format = elaborated_clang_type.GetFormat(); + clang::TypeInfo elaborated_type_info = + getASTContext()->getTypeInfo(elaborated_qual_type); + uint64_t elaborated_byte_size = elaborated_type_info.Width / 8; + + return elaborated_clang_type.DumpValue( + exe_ctx, + s, // Stream to dump to + elaborated_format, // The format with which to display the element + data, // Data buffer containing all bytes for this type + data_byte_offset, // Offset into "data" where to grab value from + elaborated_byte_size, // Size of this type in bytes + bitfield_bit_size, // Bitfield bit size + bitfield_bit_offset, // Bitfield bit offset + show_types, // Boolean indicating if we should show the variable types + show_summary, // Boolean indicating if we should show a summary for the + // current type + verbose, // Verbose output? + depth); // Scope depth for any types that have children + } break; + + case clang::Type::Paren: { + clang::QualType desugar_qual_type = + llvm::cast<clang::ParenType>(qual_type)->desugar(); + CompilerType desugar_clang_type(getASTContext(), desugar_qual_type); + + lldb::Format desugar_format = desugar_clang_type.GetFormat(); + clang::TypeInfo desugar_type_info = + getASTContext()->getTypeInfo(desugar_qual_type); + uint64_t desugar_byte_size = desugar_type_info.Width / 8; + + return desugar_clang_type.DumpValue( + exe_ctx, + s, // Stream to dump to + desugar_format, // The format with which to display the element + data, // Data buffer containing all bytes for this type + data_byte_offset, // Offset into "data" where to grab value from + desugar_byte_size, // Size of this type in bytes + bitfield_bit_size, // Bitfield bit size + bitfield_bit_offset, // Bitfield bit offset + show_types, // Boolean indicating if we should show the variable types + show_summary, // Boolean indicating if we should show a summary for the + // current type + verbose, // Verbose output? + depth); // Scope depth for any types that have children + } break; + + default: + // We are down to a scalar type that we just need to display. + data.Dump(s, data_byte_offset, format, data_byte_size, 1, UINT32_MAX, + LLDB_INVALID_ADDRESS, bitfield_bit_size, bitfield_bit_offset); + + if (show_summary) + DumpSummary(type, exe_ctx, s, data, data_byte_offset, data_byte_size); + break; + } +} + +bool ClangASTContext::DumpTypeValue( + lldb::opaque_compiler_type_t type, Stream *s, lldb::Format format, + const lldb_private::DataExtractor &data, lldb::offset_t byte_offset, + size_t byte_size, uint32_t bitfield_bit_size, uint32_t bitfield_bit_offset, + ExecutionContextScope *exe_scope) { + if (!type) + return false; + if (IsAggregateType(type)) { + return false; + } else { clang::QualType qual_type(GetQualType(type)); - switch (qual_type->getTypeClass()) - { - case clang::Type::Record: - if (GetCompleteType(type)) - { - const clang::RecordType *record_type = llvm::cast<clang::RecordType>(qual_type.getTypePtr()); - const clang::RecordDecl *record_decl = record_type->getDecl(); - assert(record_decl); - uint32_t field_bit_offset = 0; - uint32_t field_byte_offset = 0; - const clang::ASTRecordLayout &record_layout = getASTContext()->getASTRecordLayout(record_decl); - uint32_t child_idx = 0; - - const clang::CXXRecordDecl *cxx_record_decl = llvm::dyn_cast<clang::CXXRecordDecl>(record_decl); - if (cxx_record_decl) - { - // We might have base classes to print out first - clang::CXXRecordDecl::base_class_const_iterator base_class, base_class_end; - for (base_class = cxx_record_decl->bases_begin(), base_class_end = cxx_record_decl->bases_end(); - base_class != base_class_end; - ++base_class) - { - const clang::CXXRecordDecl *base_class_decl = llvm::cast<clang::CXXRecordDecl>(base_class->getType()->getAs<clang::RecordType>()->getDecl()); - - // Skip empty base classes - if (verbose == false && ClangASTContext::RecordHasFields(base_class_decl) == false) - continue; - - if (base_class->isVirtual()) - field_bit_offset = record_layout.getVBaseClassOffset(base_class_decl).getQuantity() * 8; - else - field_bit_offset = record_layout.getBaseClassOffset(base_class_decl).getQuantity() * 8; - field_byte_offset = field_bit_offset / 8; - assert (field_bit_offset % 8 == 0); - if (child_idx == 0) - s->PutChar('{'); - else - s->PutChar(','); - - clang::QualType base_class_qual_type = base_class->getType(); - std::string base_class_type_name(base_class_qual_type.getAsString()); - - // Indent and print the base class type name - s->Printf("\n%*s%s ", depth + DEPTH_INCREMENT, "", base_class_type_name.c_str()); - - clang::TypeInfo base_class_type_info = getASTContext()->getTypeInfo(base_class_qual_type); - - // Dump the value of the member - CompilerType base_clang_type(getASTContext(), base_class_qual_type); - base_clang_type.DumpValue (exe_ctx, - s, // Stream to dump to - base_clang_type.GetFormat(), // The format with which to display the member - data, // Data buffer containing all bytes for this type - data_byte_offset + field_byte_offset,// Offset into "data" where to grab value from - base_class_type_info.Width / 8, // Size of this type in bytes - 0, // Bitfield bit size - 0, // Bitfield bit offset - show_types, // Boolean indicating if we should show the variable types - show_summary, // Boolean indicating if we should show a summary for the current type - verbose, // Verbose output? - depth + DEPTH_INCREMENT); // Scope depth for any types that have children - - ++child_idx; - } - } - uint32_t field_idx = 0; - clang::RecordDecl::field_iterator field, field_end; - for (field = record_decl->field_begin(), field_end = record_decl->field_end(); field != field_end; ++field, ++field_idx, ++child_idx) - { - // Print the starting squiggly bracket (if this is the - // first member) or comma (for member 2 and beyond) for - // the struct/union/class member. - if (child_idx == 0) - s->PutChar('{'); - else - s->PutChar(','); - - // Indent - s->Printf("\n%*s", depth + DEPTH_INCREMENT, ""); - - clang::QualType field_type = field->getType(); - // Print the member type if requested - // Figure out the type byte size (field_type_info.first) and - // alignment (field_type_info.second) from the AST context. - clang::TypeInfo field_type_info = getASTContext()->getTypeInfo(field_type); - assert(field_idx < record_layout.getFieldCount()); - // Figure out the field offset within the current struct/union/class type - field_bit_offset = record_layout.getFieldOffset (field_idx); - field_byte_offset = field_bit_offset / 8; - uint32_t field_bitfield_bit_size = 0; - uint32_t field_bitfield_bit_offset = 0; - if (ClangASTContext::FieldIsBitfield (getASTContext(), *field, field_bitfield_bit_size)) - field_bitfield_bit_offset = field_bit_offset % 8; - - if (show_types) - { - std::string field_type_name(field_type.getAsString()); - if (field_bitfield_bit_size > 0) - s->Printf("(%s:%u) ", field_type_name.c_str(), field_bitfield_bit_size); - else - s->Printf("(%s) ", field_type_name.c_str()); - } - // Print the member name and equal sign - s->Printf("%s = ", field->getNameAsString().c_str()); - - - // Dump the value of the member - CompilerType field_clang_type (getASTContext(), field_type); - field_clang_type.DumpValue (exe_ctx, - s, // Stream to dump to - field_clang_type.GetFormat(), // The format with which to display the member - data, // Data buffer containing all bytes for this type - data_byte_offset + field_byte_offset,// Offset into "data" where to grab value from - field_type_info.Width / 8, // Size of this type in bytes - field_bitfield_bit_size, // Bitfield bit size - field_bitfield_bit_offset, // Bitfield bit offset - show_types, // Boolean indicating if we should show the variable types - show_summary, // Boolean indicating if we should show a summary for the current type - verbose, // Verbose output? - depth + DEPTH_INCREMENT); // Scope depth for any types that have children - } - - // Indent the trailing squiggly bracket - if (child_idx > 0) - s->Printf("\n%*s}", depth, ""); - } - return; - - case clang::Type::Enum: - if (GetCompleteType(type)) - { - const clang::EnumType *enutype = llvm::cast<clang::EnumType>(qual_type.getTypePtr()); - const clang::EnumDecl *enum_decl = enutype->getDecl(); - assert(enum_decl); - clang::EnumDecl::enumerator_iterator enum_pos, enum_end_pos; - lldb::offset_t offset = data_byte_offset; - const int64_t enum_value = data.GetMaxU64Bitfield(&offset, data_byte_size, bitfield_bit_size, bitfield_bit_offset); - for (enum_pos = enum_decl->enumerator_begin(), enum_end_pos = enum_decl->enumerator_end(); enum_pos != enum_end_pos; ++enum_pos) - { - if (enum_pos->getInitVal() == enum_value) - { - s->Printf("%s", enum_pos->getNameAsString().c_str()); - return; - } - } - // If we have gotten here we didn't get find the enumerator in the - // enum decl, so just print the integer. - s->Printf("%" PRIi64, enum_value); + + const clang::Type::TypeClass type_class = qual_type->getTypeClass(); + switch (type_class) { + case clang::Type::Typedef: { + clang::QualType typedef_qual_type = + llvm::cast<clang::TypedefType>(qual_type) + ->getDecl() + ->getUnderlyingType(); + CompilerType typedef_clang_type(getASTContext(), typedef_qual_type); + if (format == eFormatDefault) + format = typedef_clang_type.GetFormat(); + clang::TypeInfo typedef_type_info = + getASTContext()->getTypeInfo(typedef_qual_type); + uint64_t typedef_byte_size = typedef_type_info.Width / 8; + + return typedef_clang_type.DumpTypeValue( + s, + format, // The format with which to display the element + data, // Data buffer containing all bytes for this type + byte_offset, // Offset into "data" where to grab value from + typedef_byte_size, // Size of this type in bytes + bitfield_bit_size, // Size in bits of a bitfield value, if zero don't + // treat as a bitfield + bitfield_bit_offset, // Offset in bits of a bitfield value if + // bitfield_bit_size != 0 + exe_scope); + } break; + + case clang::Type::Enum: + // If our format is enum or default, show the enumeration value as + // its enumeration string value, else just display it as requested. + if ((format == eFormatEnum || format == eFormatDefault) && + GetCompleteType(type)) { + const clang::EnumType *enutype = + llvm::cast<clang::EnumType>(qual_type.getTypePtr()); + const clang::EnumDecl *enum_decl = enutype->getDecl(); + assert(enum_decl); + clang::EnumDecl::enumerator_iterator enum_pos, enum_end_pos; + const bool is_signed = qual_type->isSignedIntegerOrEnumerationType(); + lldb::offset_t offset = byte_offset; + if (is_signed) { + const int64_t enum_svalue = data.GetMaxS64Bitfield( + &offset, byte_size, bitfield_bit_size, bitfield_bit_offset); + for (enum_pos = enum_decl->enumerator_begin(), + enum_end_pos = enum_decl->enumerator_end(); + enum_pos != enum_end_pos; ++enum_pos) { + if (enum_pos->getInitVal().getSExtValue() == enum_svalue) { + s->PutCString(enum_pos->getNameAsString().c_str()); + return true; } - return; - - case clang::Type::ConstantArray: - { - const clang::ConstantArrayType *array = llvm::cast<clang::ConstantArrayType>(qual_type.getTypePtr()); - bool is_array_of_characters = false; - clang::QualType element_qual_type = array->getElementType(); - - const clang::Type *canonical_type = element_qual_type->getCanonicalTypeInternal().getTypePtr(); - if (canonical_type) - is_array_of_characters = canonical_type->isCharType(); - - const uint64_t element_count = array->getSize().getLimitedValue(); - - clang::TypeInfo field_type_info = getASTContext()->getTypeInfo(element_qual_type); - - uint32_t element_idx = 0; - uint32_t element_offset = 0; - uint64_t element_byte_size = field_type_info.Width / 8; - uint32_t element_stride = element_byte_size; - - if (is_array_of_characters) - { - s->PutChar('"'); - data.Dump(s, data_byte_offset, lldb::eFormatChar, element_byte_size, element_count, UINT32_MAX, LLDB_INVALID_ADDRESS, 0, 0); - s->PutChar('"'); - return; + } + // If we have gotten here we didn't get find the enumerator in the + // enum decl, so just print the integer. + s->Printf("%" PRIi64, enum_svalue); + } else { + const uint64_t enum_uvalue = data.GetMaxU64Bitfield( + &offset, byte_size, bitfield_bit_size, bitfield_bit_offset); + for (enum_pos = enum_decl->enumerator_begin(), + enum_end_pos = enum_decl->enumerator_end(); + enum_pos != enum_end_pos; ++enum_pos) { + if (enum_pos->getInitVal().getZExtValue() == enum_uvalue) { + s->PutCString(enum_pos->getNameAsString().c_str()); + return true; } - else - { - CompilerType element_clang_type(getASTContext(), element_qual_type); - lldb::Format element_format = element_clang_type.GetFormat(); - - for (element_idx = 0; element_idx < element_count; ++element_idx) - { - // Print the starting squiggly bracket (if this is the - // first member) or comman (for member 2 and beyong) for - // the struct/union/class member. - if (element_idx == 0) - s->PutChar('{'); - else - s->PutChar(','); - - // Indent and print the index - s->Printf("\n%*s[%u] ", depth + DEPTH_INCREMENT, "", element_idx); - - // Figure out the field offset within the current struct/union/class type - element_offset = element_idx * element_stride; - - // Dump the value of the member - element_clang_type.DumpValue (exe_ctx, - s, // Stream to dump to - element_format, // The format with which to display the element - data, // Data buffer containing all bytes for this type - data_byte_offset + element_offset,// Offset into "data" where to grab value from - element_byte_size, // Size of this type in bytes - 0, // Bitfield bit size - 0, // Bitfield bit offset - show_types, // Boolean indicating if we should show the variable types - show_summary, // Boolean indicating if we should show a summary for the current type - verbose, // Verbose output? - depth + DEPTH_INCREMENT); // Scope depth for any types that have children - } - - // Indent the trailing squiggly bracket - if (element_idx > 0) - s->Printf("\n%*s}", depth, ""); - } - } - return; - - case clang::Type::Typedef: - { - clang::QualType typedef_qual_type = llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType(); - - CompilerType typedef_clang_type (getASTContext(), typedef_qual_type); - lldb::Format typedef_format = typedef_clang_type.GetFormat(); - clang::TypeInfo typedef_type_info = getASTContext()->getTypeInfo(typedef_qual_type); - uint64_t typedef_byte_size = typedef_type_info.Width / 8; - - return typedef_clang_type.DumpValue (exe_ctx, - s, // Stream to dump to - typedef_format, // The format with which to display the element - data, // Data buffer containing all bytes for this type - data_byte_offset, // Offset into "data" where to grab value from - typedef_byte_size, // Size of this type in bytes - bitfield_bit_size, // Bitfield bit size - bitfield_bit_offset,// Bitfield bit offset - show_types, // Boolean indicating if we should show the variable types - show_summary, // Boolean indicating if we should show a summary for the current type - verbose, // Verbose output? - depth); // Scope depth for any types that have children + } + // If we have gotten here we didn't get find the enumerator in the + // enum decl, so just print the integer. + s->Printf("%" PRIu64, enum_uvalue); } - break; - - case clang::Type::Auto: - { - clang::QualType elaborated_qual_type = llvm::cast<clang::AutoType>(qual_type)->getDeducedType(); - CompilerType elaborated_clang_type (getASTContext(), elaborated_qual_type); - lldb::Format elaborated_format = elaborated_clang_type.GetFormat(); - clang::TypeInfo elaborated_type_info = getASTContext()->getTypeInfo(elaborated_qual_type); - uint64_t elaborated_byte_size = elaborated_type_info.Width / 8; - - return elaborated_clang_type.DumpValue (exe_ctx, - s, // Stream to dump to - elaborated_format, // The format with which to display the element - data, // Data buffer containing all bytes for this type - data_byte_offset, // Offset into "data" where to grab value from - elaborated_byte_size, // Size of this type in bytes - bitfield_bit_size, // Bitfield bit size - bitfield_bit_offset,// Bitfield bit offset - show_types, // Boolean indicating if we should show the variable types - show_summary, // Boolean indicating if we should show a summary for the current type - verbose, // Verbose output? - depth); // Scope depth for any types that have children + return true; + } + // format was not enum, just fall through and dump the value as + // requested.... + LLVM_FALLTHROUGH; + + default: + // We are down to a scalar type that we just need to display. + { + uint32_t item_count = 1; + // A few formats, we might need to modify our size and count for + // depending + // on how we are trying to display the value... + switch (format) { + default: + case eFormatBoolean: + case eFormatBinary: + case eFormatComplex: + case eFormatCString: // NULL terminated C strings + case eFormatDecimal: + case eFormatEnum: + case eFormatHex: + case eFormatHexUppercase: + case eFormatFloat: + case eFormatOctal: + case eFormatOSType: + case eFormatUnsigned: + case eFormatPointer: + case eFormatVectorOfChar: + case eFormatVectorOfSInt8: + case eFormatVectorOfUInt8: + case eFormatVectorOfSInt16: + case eFormatVectorOfUInt16: + case eFormatVectorOfSInt32: + case eFormatVectorOfUInt32: + case eFormatVectorOfSInt64: + case eFormatVectorOfUInt64: + case eFormatVectorOfFloat32: + case eFormatVectorOfFloat64: + case eFormatVectorOfUInt128: + break; + + case eFormatChar: + case eFormatCharPrintable: + case eFormatCharArray: + case eFormatBytes: + case eFormatBytesWithASCII: + item_count = byte_size; + byte_size = 1; + break; + + case eFormatUnicode16: + item_count = byte_size / 2; + byte_size = 2; + break; + + case eFormatUnicode32: + item_count = byte_size / 4; + byte_size = 4; + break; } + return data.Dump(s, byte_offset, format, byte_size, item_count, + UINT32_MAX, LLDB_INVALID_ADDRESS, bitfield_bit_size, + bitfield_bit_offset, exe_scope); + } + break; + } + } + return 0; +} + +void ClangASTContext::DumpSummary(lldb::opaque_compiler_type_t type, + ExecutionContext *exe_ctx, Stream *s, + const lldb_private::DataExtractor &data, + lldb::offset_t data_byte_offset, + size_t data_byte_size) { + uint32_t length = 0; + if (IsCStringType(type, length)) { + if (exe_ctx) { + Process *process = exe_ctx->GetProcessPtr(); + if (process) { + lldb::offset_t offset = data_byte_offset; + lldb::addr_t pointer_address = data.GetMaxU64(&offset, data_byte_size); + std::vector<uint8_t> buf; + if (length > 0) + buf.resize(length); + else + buf.resize(256); + + lldb_private::DataExtractor cstr_data(&buf.front(), buf.size(), + process->GetByteOrder(), 4); + buf.back() = '\0'; + size_t bytes_read; + size_t total_cstr_len = 0; + Error error; + while ((bytes_read = process->ReadMemory(pointer_address, &buf.front(), + buf.size(), error)) > 0) { + const size_t len = strlen((const char *)&buf.front()); + if (len == 0) break; - - case clang::Type::Elaborated: - { - clang::QualType elaborated_qual_type = llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType(); - CompilerType elaborated_clang_type (getASTContext(), elaborated_qual_type); - lldb::Format elaborated_format = elaborated_clang_type.GetFormat(); - clang::TypeInfo elaborated_type_info = getASTContext()->getTypeInfo(elaborated_qual_type); - uint64_t elaborated_byte_size = elaborated_type_info.Width / 8; - - return elaborated_clang_type.DumpValue (exe_ctx, - s, // Stream to dump to - elaborated_format, // The format with which to display the element - data, // Data buffer containing all bytes for this type - data_byte_offset, // Offset into "data" where to grab value from - elaborated_byte_size, // Size of this type in bytes - bitfield_bit_size, // Bitfield bit size - bitfield_bit_offset,// Bitfield bit offset - show_types, // Boolean indicating if we should show the variable types - show_summary, // Boolean indicating if we should show a summary for the current type - verbose, // Verbose output? - depth); // Scope depth for any types that have children - } + if (total_cstr_len == 0) + s->PutCString(" \""); + cstr_data.Dump(s, 0, lldb::eFormatChar, 1, len, UINT32_MAX, + LLDB_INVALID_ADDRESS, 0, 0); + total_cstr_len += len; + if (len < buf.size()) break; - - case clang::Type::Paren: - { - clang::QualType desugar_qual_type = llvm::cast<clang::ParenType>(qual_type)->desugar(); - CompilerType desugar_clang_type (getASTContext(), desugar_qual_type); - - lldb::Format desugar_format = desugar_clang_type.GetFormat(); - clang::TypeInfo desugar_type_info = getASTContext()->getTypeInfo(desugar_qual_type); - uint64_t desugar_byte_size = desugar_type_info.Width / 8; - - return desugar_clang_type.DumpValue (exe_ctx, - s, // Stream to dump to - desugar_format, // The format with which to display the element - data, // Data buffer containing all bytes for this type - data_byte_offset, // Offset into "data" where to grab value from - desugar_byte_size, // Size of this type in bytes - bitfield_bit_size, // Bitfield bit size - bitfield_bit_offset,// Bitfield bit offset - show_types, // Boolean indicating if we should show the variable types - show_summary, // Boolean indicating if we should show a summary for the current type - verbose, // Verbose output? - depth); // Scope depth for any types that have children + pointer_address += total_cstr_len; } - break; - - default: - // We are down to a scalar type that we just need to display. - data.Dump(s, - data_byte_offset, - format, - data_byte_size, - 1, - UINT32_MAX, - LLDB_INVALID_ADDRESS, - bitfield_bit_size, - bitfield_bit_offset); - - if (show_summary) - DumpSummary (type, exe_ctx, s, data, data_byte_offset, data_byte_size); - break; + if (total_cstr_len > 0) + s->PutChar('"'); + } } + } } - - - -bool -ClangASTContext::DumpTypeValue (lldb::opaque_compiler_type_t type, Stream *s, - lldb::Format format, - const lldb_private::DataExtractor &data, - lldb::offset_t byte_offset, - size_t byte_size, - uint32_t bitfield_bit_size, - uint32_t bitfield_bit_offset, - ExecutionContextScope *exe_scope) -{ - if (!type) - return false; - if (IsAggregateType(type)) - { - return false; - } - else - { - clang::QualType qual_type(GetQualType(type)); - - const clang::Type::TypeClass type_class = qual_type->getTypeClass(); - switch (type_class) - { - case clang::Type::Typedef: - { - clang::QualType typedef_qual_type = llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType(); - CompilerType typedef_clang_type (getASTContext(), typedef_qual_type); - if (format == eFormatDefault) - format = typedef_clang_type.GetFormat(); - clang::TypeInfo typedef_type_info = getASTContext()->getTypeInfo(typedef_qual_type); - uint64_t typedef_byte_size = typedef_type_info.Width / 8; - - return typedef_clang_type.DumpTypeValue (s, - format, // The format with which to display the element - data, // Data buffer containing all bytes for this type - byte_offset, // Offset into "data" where to grab value from - typedef_byte_size, // Size of this type in bytes - bitfield_bit_size, // Size in bits of a bitfield value, if zero don't treat as a bitfield - bitfield_bit_offset, // Offset in bits of a bitfield value if bitfield_bit_size != 0 - exe_scope); - } - break; - - case clang::Type::Enum: - // If our format is enum or default, show the enumeration value as - // its enumeration string value, else just display it as requested. - if ((format == eFormatEnum || format == eFormatDefault) && GetCompleteType(type)) - { - const clang::EnumType *enutype = llvm::cast<clang::EnumType>(qual_type.getTypePtr()); - const clang::EnumDecl *enum_decl = enutype->getDecl(); - assert(enum_decl); - clang::EnumDecl::enumerator_iterator enum_pos, enum_end_pos; - const bool is_signed = qual_type->isSignedIntegerOrEnumerationType(); - lldb::offset_t offset = byte_offset; - if (is_signed) - { - const int64_t enum_svalue = data.GetMaxS64Bitfield (&offset, byte_size, bitfield_bit_size, bitfield_bit_offset); - for (enum_pos = enum_decl->enumerator_begin(), enum_end_pos = enum_decl->enumerator_end(); enum_pos != enum_end_pos; ++enum_pos) - { - if (enum_pos->getInitVal().getSExtValue() == enum_svalue) - { - s->PutCString (enum_pos->getNameAsString().c_str()); - return true; - } - } - // If we have gotten here we didn't get find the enumerator in the - // enum decl, so just print the integer. - s->Printf("%" PRIi64, enum_svalue); - } - else - { - const uint64_t enum_uvalue = data.GetMaxU64Bitfield (&offset, byte_size, bitfield_bit_size, bitfield_bit_offset); - for (enum_pos = enum_decl->enumerator_begin(), enum_end_pos = enum_decl->enumerator_end(); enum_pos != enum_end_pos; ++enum_pos) - { - if (enum_pos->getInitVal().getZExtValue() == enum_uvalue) - { - s->PutCString (enum_pos->getNameAsString().c_str()); - return true; - } - } - // If we have gotten here we didn't get find the enumerator in the - // enum decl, so just print the integer. - s->Printf("%" PRIu64, enum_uvalue); - } - return true; - } - // format was not enum, just fall through and dump the value as requested.... - LLVM_FALLTHROUGH; - - default: - // We are down to a scalar type that we just need to display. - { - uint32_t item_count = 1; - // A few formats, we might need to modify our size and count for depending - // on how we are trying to display the value... - switch (format) - { - default: - case eFormatBoolean: - case eFormatBinary: - case eFormatComplex: - case eFormatCString: // NULL terminated C strings - case eFormatDecimal: - case eFormatEnum: - case eFormatHex: - case eFormatHexUppercase: - case eFormatFloat: - case eFormatOctal: - case eFormatOSType: - case eFormatUnsigned: - case eFormatPointer: - case eFormatVectorOfChar: - case eFormatVectorOfSInt8: - case eFormatVectorOfUInt8: - case eFormatVectorOfSInt16: - case eFormatVectorOfUInt16: - case eFormatVectorOfSInt32: - case eFormatVectorOfUInt32: - case eFormatVectorOfSInt64: - case eFormatVectorOfUInt64: - case eFormatVectorOfFloat32: - case eFormatVectorOfFloat64: - case eFormatVectorOfUInt128: - break; - - case eFormatChar: - case eFormatCharPrintable: - case eFormatCharArray: - case eFormatBytes: - case eFormatBytesWithASCII: - item_count = byte_size; - byte_size = 1; - break; - - case eFormatUnicode16: - item_count = byte_size / 2; - byte_size = 2; - break; - - case eFormatUnicode32: - item_count = byte_size / 4; - byte_size = 4; - break; - } - return data.Dump (s, - byte_offset, - format, - byte_size, - item_count, - UINT32_MAX, - LLDB_INVALID_ADDRESS, - bitfield_bit_size, - bitfield_bit_offset, - exe_scope); - } - break; - } - } - return 0; +void ClangASTContext::DumpTypeDescription(lldb::opaque_compiler_type_t type) { + StreamFile s(stdout, false); + DumpTypeDescription(type, &s); + ClangASTMetadata *metadata = + ClangASTContext::GetMetadata(getASTContext(), type); + if (metadata) { + metadata->Dump(&s); + } } +void ClangASTContext::DumpTypeDescription(lldb::opaque_compiler_type_t type, + Stream *s) { + if (type) { + clang::QualType qual_type(GetQualType(type)); + llvm::SmallVector<char, 1024> buf; + llvm::raw_svector_ostream llvm_ostrm(buf); -void -ClangASTContext::DumpSummary (lldb::opaque_compiler_type_t type, ExecutionContext *exe_ctx, - Stream *s, - const lldb_private::DataExtractor &data, - lldb::offset_t data_byte_offset, - size_t data_byte_size) -{ - uint32_t length = 0; - if (IsCStringType (type, length)) - { - if (exe_ctx) - { - Process *process = exe_ctx->GetProcessPtr(); - if (process) - { - lldb::offset_t offset = data_byte_offset; - lldb::addr_t pointer_address = data.GetMaxU64(&offset, data_byte_size); - std::vector<uint8_t> buf; - if (length > 0) - buf.resize (length); - else - buf.resize (256); - - lldb_private::DataExtractor cstr_data(&buf.front(), buf.size(), process->GetByteOrder(), 4); - buf.back() = '\0'; - size_t bytes_read; - size_t total_cstr_len = 0; - Error error; - while ((bytes_read = process->ReadMemory (pointer_address, &buf.front(), buf.size(), error)) > 0) - { - const size_t len = strlen((const char *)&buf.front()); - if (len == 0) - break; - if (total_cstr_len == 0) - s->PutCString (" \""); - cstr_data.Dump(s, 0, lldb::eFormatChar, 1, len, UINT32_MAX, LLDB_INVALID_ADDRESS, 0, 0); - total_cstr_len += len; - if (len < buf.size()) - break; - pointer_address += total_cstr_len; - } - if (total_cstr_len > 0) - s->PutChar ('"'); - } + const clang::Type::TypeClass type_class = qual_type->getTypeClass(); + switch (type_class) { + case clang::Type::ObjCObject: + case clang::Type::ObjCInterface: { + GetCompleteType(type); + + const clang::ObjCObjectType *objc_class_type = + llvm::dyn_cast<clang::ObjCObjectType>(qual_type.getTypePtr()); + assert(objc_class_type); + if (objc_class_type) { + clang::ObjCInterfaceDecl *class_interface_decl = + objc_class_type->getInterface(); + if (class_interface_decl) { + clang::PrintingPolicy policy = getASTContext()->getPrintingPolicy(); + class_interface_decl->print(llvm_ostrm, policy, s->GetIndentLevel()); + } + } + } break; + + case clang::Type::Typedef: { + const clang::TypedefType *typedef_type = + qual_type->getAs<clang::TypedefType>(); + if (typedef_type) { + const clang::TypedefNameDecl *typedef_decl = typedef_type->getDecl(); + std::string clang_typedef_name( + typedef_decl->getQualifiedNameAsString()); + if (!clang_typedef_name.empty()) { + s->PutCString("typedef "); + s->PutCString(clang_typedef_name.c_str()); } + } + } break; + + case clang::Type::Auto: + CompilerType(getASTContext(), + llvm::cast<clang::AutoType>(qual_type)->getDeducedType()) + .DumpTypeDescription(s); + return; + + case clang::Type::Elaborated: + CompilerType(getASTContext(), + llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType()) + .DumpTypeDescription(s); + return; + + case clang::Type::Paren: + CompilerType(getASTContext(), + llvm::cast<clang::ParenType>(qual_type)->desugar()) + .DumpTypeDescription(s); + return; + + case clang::Type::Record: { + GetCompleteType(type); + + const clang::RecordType *record_type = + llvm::cast<clang::RecordType>(qual_type.getTypePtr()); + const clang::RecordDecl *record_decl = record_type->getDecl(); + const clang::CXXRecordDecl *cxx_record_decl = + llvm::dyn_cast<clang::CXXRecordDecl>(record_decl); + + if (cxx_record_decl) + cxx_record_decl->print(llvm_ostrm, getASTContext()->getPrintingPolicy(), + s->GetIndentLevel()); + else + record_decl->print(llvm_ostrm, getASTContext()->getPrintingPolicy(), + s->GetIndentLevel()); + } break; + + default: { + const clang::TagType *tag_type = + llvm::dyn_cast<clang::TagType>(qual_type.getTypePtr()); + if (tag_type) { + clang::TagDecl *tag_decl = tag_type->getDecl(); + if (tag_decl) + tag_decl->print(llvm_ostrm, 0); + } else { + std::string clang_type_name(qual_type.getAsString()); + if (!clang_type_name.empty()) + s->PutCString(clang_type_name.c_str()); + } } -} - -void -ClangASTContext::DumpTypeDescription (lldb::opaque_compiler_type_t type) -{ - StreamFile s (stdout, false); - DumpTypeDescription (type, &s); - ClangASTMetadata *metadata = ClangASTContext::GetMetadata (getASTContext(), type); - if (metadata) - { - metadata->Dump (&s); } -} -void -ClangASTContext::DumpTypeDescription (lldb::opaque_compiler_type_t type, Stream *s) -{ - if (type) - { - clang::QualType qual_type(GetQualType(type)); - - llvm::SmallVector<char, 1024> buf; - llvm::raw_svector_ostream llvm_ostrm (buf); - - const clang::Type::TypeClass type_class = qual_type->getTypeClass(); - switch (type_class) - { - case clang::Type::ObjCObject: - case clang::Type::ObjCInterface: - { - GetCompleteType(type); - - const clang::ObjCObjectType *objc_class_type = llvm::dyn_cast<clang::ObjCObjectType>(qual_type.getTypePtr()); - assert (objc_class_type); - if (objc_class_type) - { - clang::ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface(); - if (class_interface_decl) - { - clang::PrintingPolicy policy = getASTContext()->getPrintingPolicy(); - class_interface_decl->print(llvm_ostrm, policy, s->GetIndentLevel()); - } - } - } - break; - - case clang::Type::Typedef: - { - const clang::TypedefType *typedef_type = qual_type->getAs<clang::TypedefType>(); - if (typedef_type) - { - const clang::TypedefNameDecl *typedef_decl = typedef_type->getDecl(); - std::string clang_typedef_name (typedef_decl->getQualifiedNameAsString()); - if (!clang_typedef_name.empty()) - { - s->PutCString ("typedef "); - s->PutCString (clang_typedef_name.c_str()); - } - } - } - break; - - case clang::Type::Auto: - CompilerType (getASTContext(), llvm::cast<clang::AutoType>(qual_type)->getDeducedType()).DumpTypeDescription(s); - return; - - case clang::Type::Elaborated: - CompilerType (getASTContext(), llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType()).DumpTypeDescription(s); - return; - - case clang::Type::Paren: - CompilerType (getASTContext(), llvm::cast<clang::ParenType>(qual_type)->desugar()).DumpTypeDescription(s); - return; - - case clang::Type::Record: - { - GetCompleteType(type); - - const clang::RecordType *record_type = llvm::cast<clang::RecordType>(qual_type.getTypePtr()); - const clang::RecordDecl *record_decl = record_type->getDecl(); - const clang::CXXRecordDecl *cxx_record_decl = llvm::dyn_cast<clang::CXXRecordDecl>(record_decl); - - if (cxx_record_decl) - cxx_record_decl->print(llvm_ostrm, getASTContext()->getPrintingPolicy(), s->GetIndentLevel()); - else - record_decl->print(llvm_ostrm, getASTContext()->getPrintingPolicy(), s->GetIndentLevel()); - } - break; - - default: - { - const clang::TagType *tag_type = llvm::dyn_cast<clang::TagType>(qual_type.getTypePtr()); - if (tag_type) - { - clang::TagDecl *tag_decl = tag_type->getDecl(); - if (tag_decl) - tag_decl->print(llvm_ostrm, 0); - } - else - { - std::string clang_type_name(qual_type.getAsString()); - if (!clang_type_name.empty()) - s->PutCString (clang_type_name.c_str()); - } - } - } - - if (buf.size() > 0) - { - s->Write (buf.data(), buf.size()); - } + if (buf.size() > 0) { + s->Write(buf.data(), buf.size()); } + } } -void -ClangASTContext::DumpTypeName (const CompilerType &type) -{ - if (ClangUtil::IsClangType(type)) - { - clang::QualType qual_type(ClangUtil::GetCanonicalQualType(ClangUtil::RemoveFastQualifiers(type))); - - const clang::Type::TypeClass type_class = qual_type->getTypeClass(); - switch (type_class) - { - case clang::Type::Record: - { - const clang::CXXRecordDecl *cxx_record_decl = qual_type->getAsCXXRecordDecl(); - if (cxx_record_decl) - printf("class %s", cxx_record_decl->getName().str().c_str()); - } - break; - - case clang::Type::Enum: - { - clang::EnumDecl *enum_decl = llvm::cast<clang::EnumType>(qual_type)->getDecl(); - if (enum_decl) - { - printf("enum %s", enum_decl->getName().str().c_str()); - } - } - break; - - case clang::Type::ObjCObject: - case clang::Type::ObjCInterface: - { - const clang::ObjCObjectType *objc_class_type = llvm::dyn_cast<clang::ObjCObjectType>(qual_type); - if (objc_class_type) - { - clang::ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface(); - // We currently can't complete objective C types through the newly added ASTContext - // because it only supports TagDecl objects right now... - if (class_interface_decl) - printf("@class %s", class_interface_decl->getName().str().c_str()); - } - } - break; +void ClangASTContext::DumpTypeName(const CompilerType &type) { + if (ClangUtil::IsClangType(type)) { + clang::QualType qual_type( + ClangUtil::GetCanonicalQualType(ClangUtil::RemoveFastQualifiers(type))); + const clang::Type::TypeClass type_class = qual_type->getTypeClass(); + switch (type_class) { + case clang::Type::Record: { + const clang::CXXRecordDecl *cxx_record_decl = + qual_type->getAsCXXRecordDecl(); + if (cxx_record_decl) + printf("class %s", cxx_record_decl->getName().str().c_str()); + } break; + + case clang::Type::Enum: { + clang::EnumDecl *enum_decl = + llvm::cast<clang::EnumType>(qual_type)->getDecl(); + if (enum_decl) { + printf("enum %s", enum_decl->getName().str().c_str()); + } + } break; + + case clang::Type::ObjCObject: + case clang::Type::ObjCInterface: { + const clang::ObjCObjectType *objc_class_type = + llvm::dyn_cast<clang::ObjCObjectType>(qual_type); + if (objc_class_type) { + clang::ObjCInterfaceDecl *class_interface_decl = + objc_class_type->getInterface(); + // We currently can't complete objective C types through the newly added + // ASTContext + // because it only supports TagDecl objects right now... + if (class_interface_decl) + printf("@class %s", class_interface_decl->getName().str().c_str()); + } + } break; + + case clang::Type::Typedef: + printf("typedef %s", llvm::cast<clang::TypedefType>(qual_type) + ->getDecl() + ->getName() + .str() + .c_str()); + break; + + case clang::Type::Auto: + printf("auto "); + return DumpTypeName(CompilerType(type.GetTypeSystem(), + llvm::cast<clang::AutoType>(qual_type) + ->getDeducedType() + .getAsOpaquePtr())); + + case clang::Type::Elaborated: + printf("elaborated "); + return DumpTypeName(CompilerType( + type.GetTypeSystem(), llvm::cast<clang::ElaboratedType>(qual_type) + ->getNamedType() + .getAsOpaquePtr())); + + case clang::Type::Paren: + printf("paren "); + return DumpTypeName(CompilerType( + type.GetTypeSystem(), + llvm::cast<clang::ParenType>(qual_type)->desugar().getAsOpaquePtr())); - case clang::Type::Typedef: - printf("typedef %s", llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getName().str().c_str()); - break; - - case clang::Type::Auto: - printf("auto "); - return DumpTypeName (CompilerType (type.GetTypeSystem(), llvm::cast<clang::AutoType>(qual_type)->getDeducedType().getAsOpaquePtr())); - - case clang::Type::Elaborated: - printf("elaborated "); - return DumpTypeName (CompilerType (type.GetTypeSystem(), llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType().getAsOpaquePtr())); - - case clang::Type::Paren: - printf("paren "); - return DumpTypeName (CompilerType (type.GetTypeSystem(), llvm::cast<clang::ParenType>(qual_type)->desugar().getAsOpaquePtr())); - - default: - printf("ClangASTContext::DumpTypeName() type_class = %u", type_class); - break; - } + default: + printf("ClangASTContext::DumpTypeName() type_class = %u", type_class); + break; } - + } } +clang::ClassTemplateDecl *ClangASTContext::ParseClassTemplateDecl( + clang::DeclContext *decl_ctx, lldb::AccessType access_type, + const char *parent_name, int tag_decl_kind, + const ClangASTContext::TemplateParameterInfos &template_param_infos) { + if (template_param_infos.IsValid()) { + std::string template_basename(parent_name); + template_basename.erase(template_basename.find('<')); - -clang::ClassTemplateDecl * -ClangASTContext::ParseClassTemplateDecl (clang::DeclContext *decl_ctx, - lldb::AccessType access_type, - const char *parent_name, - int tag_decl_kind, - const ClangASTContext::TemplateParameterInfos &template_param_infos) -{ - if (template_param_infos.IsValid()) - { - std::string template_basename(parent_name); - template_basename.erase (template_basename.find('<')); - - return CreateClassTemplateDecl (decl_ctx, - access_type, - template_basename.c_str(), - tag_decl_kind, - template_param_infos); - } - return NULL; + return CreateClassTemplateDecl(decl_ctx, access_type, + template_basename.c_str(), tag_decl_kind, + template_param_infos); + } + return NULL; } -void -ClangASTContext::CompleteTagDecl (void *baton, clang::TagDecl *decl) -{ - ClangASTContext *ast = (ClangASTContext *)baton; - SymbolFile *sym_file = ast->GetSymbolFile(); - if (sym_file) - { - CompilerType clang_type = GetTypeForDecl (decl); - if (clang_type) - sym_file->CompleteType (clang_type); - } +void ClangASTContext::CompleteTagDecl(void *baton, clang::TagDecl *decl) { + ClangASTContext *ast = (ClangASTContext *)baton; + SymbolFile *sym_file = ast->GetSymbolFile(); + if (sym_file) { + CompilerType clang_type = GetTypeForDecl(decl); + if (clang_type) + sym_file->CompleteType(clang_type); + } } -void -ClangASTContext::CompleteObjCInterfaceDecl (void *baton, clang::ObjCInterfaceDecl *decl) -{ - ClangASTContext *ast = (ClangASTContext *)baton; - SymbolFile *sym_file = ast->GetSymbolFile(); - if (sym_file) - { - CompilerType clang_type = GetTypeForDecl (decl); - if (clang_type) - sym_file->CompleteType (clang_type); - } +void ClangASTContext::CompleteObjCInterfaceDecl( + void *baton, clang::ObjCInterfaceDecl *decl) { + ClangASTContext *ast = (ClangASTContext *)baton; + SymbolFile *sym_file = ast->GetSymbolFile(); + if (sym_file) { + CompilerType clang_type = GetTypeForDecl(decl); + if (clang_type) + sym_file->CompleteType(clang_type); + } } -DWARFASTParser * -ClangASTContext::GetDWARFParser() -{ - if (!m_dwarf_ast_parser_ap) - m_dwarf_ast_parser_ap.reset(new DWARFASTParserClang(*this)); - return m_dwarf_ast_parser_ap.get(); +DWARFASTParser *ClangASTContext::GetDWARFParser() { + if (!m_dwarf_ast_parser_ap) + m_dwarf_ast_parser_ap.reset(new DWARFASTParserClang(*this)); + return m_dwarf_ast_parser_ap.get(); } -PDBASTParser * -ClangASTContext::GetPDBParser() -{ - if (!m_pdb_ast_parser_ap) - m_pdb_ast_parser_ap.reset(new PDBASTParser(*this)); - return m_pdb_ast_parser_ap.get(); +PDBASTParser *ClangASTContext::GetPDBParser() { + if (!m_pdb_ast_parser_ap) + m_pdb_ast_parser_ap.reset(new PDBASTParser(*this)); + return m_pdb_ast_parser_ap.get(); } -bool -ClangASTContext::LayoutRecordType(void *baton, - const clang::RecordDecl *record_decl, - uint64_t &bit_size, - uint64_t &alignment, - llvm::DenseMap<const clang::FieldDecl *, uint64_t> &field_offsets, - llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> &base_offsets, - llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> &vbase_offsets) -{ - ClangASTContext *ast = (ClangASTContext *)baton; - DWARFASTParserClang *dwarf_ast_parser = (DWARFASTParserClang *)ast->GetDWARFParser(); - return dwarf_ast_parser->GetClangASTImporter().LayoutRecordType(record_decl, bit_size, alignment, field_offsets, - base_offsets, vbase_offsets); +bool ClangASTContext::LayoutRecordType( + void *baton, const clang::RecordDecl *record_decl, uint64_t &bit_size, + uint64_t &alignment, + llvm::DenseMap<const clang::FieldDecl *, uint64_t> &field_offsets, + llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> + &base_offsets, + llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> + &vbase_offsets) { + ClangASTContext *ast = (ClangASTContext *)baton; + DWARFASTParserClang *dwarf_ast_parser = + (DWARFASTParserClang *)ast->GetDWARFParser(); + return dwarf_ast_parser->GetClangASTImporter().LayoutRecordType( + record_decl, bit_size, alignment, field_offsets, base_offsets, + vbase_offsets); } //---------------------------------------------------------------------- // CompilerDecl override functions //---------------------------------------------------------------------- -ConstString -ClangASTContext::DeclGetName (void *opaque_decl) -{ - if (opaque_decl) - { - clang::NamedDecl *nd = llvm::dyn_cast<NamedDecl>((clang::Decl*)opaque_decl); - if (nd != nullptr) - return ConstString(nd->getDeclName().getAsString()); - } - return ConstString(); -} - -ConstString -ClangASTContext::DeclGetMangledName (void *opaque_decl) -{ - if (opaque_decl) - { - clang::NamedDecl *nd = llvm::dyn_cast<clang::NamedDecl>((clang::Decl*)opaque_decl); - if (nd != nullptr && !llvm::isa<clang::ObjCMethodDecl>(nd)) - { - clang::MangleContext *mc = getMangleContext(); - if (mc && mc->shouldMangleCXXName(nd)) - { - llvm::SmallVector<char, 1024> buf; - llvm::raw_svector_ostream llvm_ostrm (buf); - if (llvm::isa<clang::CXXConstructorDecl>(nd)) - { - mc->mangleCXXCtor(llvm::dyn_cast<clang::CXXConstructorDecl>(nd), Ctor_Complete, llvm_ostrm); - } - else if (llvm::isa<clang::CXXDestructorDecl>(nd)) - { - mc->mangleCXXDtor(llvm::dyn_cast<clang::CXXDestructorDecl>(nd), Dtor_Complete, llvm_ostrm); - } - else - { - mc->mangleName(nd, llvm_ostrm); - } - if (buf.size() > 0) - return ConstString(buf.data(), buf.size()); - } +ConstString ClangASTContext::DeclGetName(void *opaque_decl) { + if (opaque_decl) { + clang::NamedDecl *nd = + llvm::dyn_cast<NamedDecl>((clang::Decl *)opaque_decl); + if (nd != nullptr) + return ConstString(nd->getDeclName().getAsString()); + } + return ConstString(); +} + +ConstString ClangASTContext::DeclGetMangledName(void *opaque_decl) { + if (opaque_decl) { + clang::NamedDecl *nd = + llvm::dyn_cast<clang::NamedDecl>((clang::Decl *)opaque_decl); + if (nd != nullptr && !llvm::isa<clang::ObjCMethodDecl>(nd)) { + clang::MangleContext *mc = getMangleContext(); + if (mc && mc->shouldMangleCXXName(nd)) { + llvm::SmallVector<char, 1024> buf; + llvm::raw_svector_ostream llvm_ostrm(buf); + if (llvm::isa<clang::CXXConstructorDecl>(nd)) { + mc->mangleCXXCtor(llvm::dyn_cast<clang::CXXConstructorDecl>(nd), + Ctor_Complete, llvm_ostrm); + } else if (llvm::isa<clang::CXXDestructorDecl>(nd)) { + mc->mangleCXXDtor(llvm::dyn_cast<clang::CXXDestructorDecl>(nd), + Dtor_Complete, llvm_ostrm); + } else { + mc->mangleName(nd, llvm_ostrm); } + if (buf.size() > 0) + return ConstString(buf.data(), buf.size()); + } } - return ConstString(); + } + return ConstString(); } -CompilerDeclContext -ClangASTContext::DeclGetDeclContext (void *opaque_decl) -{ - if (opaque_decl) - return CompilerDeclContext(this, ((clang::Decl*)opaque_decl)->getDeclContext()); - else - return CompilerDeclContext(); +CompilerDeclContext ClangASTContext::DeclGetDeclContext(void *opaque_decl) { + if (opaque_decl) + return CompilerDeclContext(this, + ((clang::Decl *)opaque_decl)->getDeclContext()); + else + return CompilerDeclContext(); } -CompilerType -ClangASTContext::DeclGetFunctionReturnType(void *opaque_decl) -{ - if (clang::FunctionDecl *func_decl = llvm::dyn_cast<clang::FunctionDecl>((clang::Decl*)opaque_decl)) - return CompilerType(this, func_decl->getReturnType().getAsOpaquePtr()); - if (clang::ObjCMethodDecl *objc_method = llvm::dyn_cast<clang::ObjCMethodDecl>((clang::Decl*)opaque_decl)) - return CompilerType(this, objc_method->getReturnType().getAsOpaquePtr()); - else - return CompilerType(); +CompilerType ClangASTContext::DeclGetFunctionReturnType(void *opaque_decl) { + if (clang::FunctionDecl *func_decl = + llvm::dyn_cast<clang::FunctionDecl>((clang::Decl *)opaque_decl)) + return CompilerType(this, func_decl->getReturnType().getAsOpaquePtr()); + if (clang::ObjCMethodDecl *objc_method = + llvm::dyn_cast<clang::ObjCMethodDecl>((clang::Decl *)opaque_decl)) + return CompilerType(this, objc_method->getReturnType().getAsOpaquePtr()); + else + return CompilerType(); } -size_t -ClangASTContext::DeclGetFunctionNumArguments(void *opaque_decl) -{ - if (clang::FunctionDecl *func_decl = llvm::dyn_cast<clang::FunctionDecl>((clang::Decl*)opaque_decl)) - return func_decl->param_size(); - if (clang::ObjCMethodDecl *objc_method = llvm::dyn_cast<clang::ObjCMethodDecl>((clang::Decl*)opaque_decl)) - return objc_method->param_size(); - else - return 0; +size_t ClangASTContext::DeclGetFunctionNumArguments(void *opaque_decl) { + if (clang::FunctionDecl *func_decl = + llvm::dyn_cast<clang::FunctionDecl>((clang::Decl *)opaque_decl)) + return func_decl->param_size(); + if (clang::ObjCMethodDecl *objc_method = + llvm::dyn_cast<clang::ObjCMethodDecl>((clang::Decl *)opaque_decl)) + return objc_method->param_size(); + else + return 0; } -CompilerType -ClangASTContext::DeclGetFunctionArgumentType (void *opaque_decl, size_t idx) -{ - if (clang::FunctionDecl *func_decl = llvm::dyn_cast<clang::FunctionDecl>((clang::Decl*)opaque_decl)) - { - if (idx < func_decl->param_size()) - { - ParmVarDecl *var_decl = func_decl->getParamDecl(idx); - if (var_decl) - return CompilerType(this, var_decl->getOriginalType().getAsOpaquePtr()); - } - } - else if (clang::ObjCMethodDecl *objc_method = llvm::dyn_cast<clang::ObjCMethodDecl>((clang::Decl*)opaque_decl)) - { - if (idx < objc_method->param_size()) - return CompilerType(this, objc_method->parameters()[idx]->getOriginalType().getAsOpaquePtr()); +CompilerType ClangASTContext::DeclGetFunctionArgumentType(void *opaque_decl, + size_t idx) { + if (clang::FunctionDecl *func_decl = + llvm::dyn_cast<clang::FunctionDecl>((clang::Decl *)opaque_decl)) { + if (idx < func_decl->param_size()) { + ParmVarDecl *var_decl = func_decl->getParamDecl(idx); + if (var_decl) + return CompilerType(this, var_decl->getOriginalType().getAsOpaquePtr()); } - return CompilerType(); + } else if (clang::ObjCMethodDecl *objc_method = + llvm::dyn_cast<clang::ObjCMethodDecl>( + (clang::Decl *)opaque_decl)) { + if (idx < objc_method->param_size()) + return CompilerType( + this, + objc_method->parameters()[idx]->getOriginalType().getAsOpaquePtr()); + } + return CompilerType(); } //---------------------------------------------------------------------- // CompilerDeclContext functions //---------------------------------------------------------------------- -std::vector<CompilerDecl> -ClangASTContext::DeclContextFindDeclByName(void *opaque_decl_ctx, - ConstString name, - const bool ignore_using_decls) -{ - std::vector<CompilerDecl> found_decls; - if (opaque_decl_ctx) - { - DeclContext *root_decl_ctx = (DeclContext *)opaque_decl_ctx; - std::set<DeclContext *> searched; - std::multimap<DeclContext *, DeclContext *> search_queue; - SymbolFile *symbol_file = GetSymbolFile(); - - for (clang::DeclContext *decl_context = root_decl_ctx; decl_context != nullptr && found_decls.empty(); decl_context = decl_context->getParent()) - { - search_queue.insert(std::make_pair(decl_context, decl_context)); - - for (auto it = search_queue.find(decl_context); it != search_queue.end(); it++) - { - if (!searched.insert(it->second).second) - continue; - symbol_file->ParseDeclsForContext(CompilerDeclContext(this, it->second)); - - for (clang::Decl *child : it->second->decls()) - { - if (clang::UsingDirectiveDecl *ud = llvm::dyn_cast<clang::UsingDirectiveDecl>(child)) - { - if (ignore_using_decls) - continue; - clang::DeclContext *from = ud->getCommonAncestor(); - if (searched.find(ud->getNominatedNamespace()) == searched.end()) - search_queue.insert(std::make_pair(from, ud->getNominatedNamespace())); - } - else if (clang::UsingDecl *ud = llvm::dyn_cast<clang::UsingDecl>(child)) - { - if (ignore_using_decls) - continue; - for (clang::UsingShadowDecl *usd : ud->shadows()) - { - clang::Decl *target = usd->getTargetDecl(); - if (clang::NamedDecl *nd = llvm::dyn_cast<clang::NamedDecl>(target)) - { - IdentifierInfo *ii = nd->getIdentifier(); - if (ii != nullptr && ii->getName().equals(name.AsCString(nullptr))) - found_decls.push_back(CompilerDecl(this, nd)); - } - } - } - else if (clang::NamedDecl *nd = llvm::dyn_cast<clang::NamedDecl>(child)) - { - IdentifierInfo *ii = nd->getIdentifier(); - if (ii != nullptr && ii->getName().equals(name.AsCString(nullptr))) - found_decls.push_back(CompilerDecl(this, nd)); - } - } +std::vector<CompilerDecl> ClangASTContext::DeclContextFindDeclByName( + void *opaque_decl_ctx, ConstString name, const bool ignore_using_decls) { + std::vector<CompilerDecl> found_decls; + if (opaque_decl_ctx) { + DeclContext *root_decl_ctx = (DeclContext *)opaque_decl_ctx; + std::set<DeclContext *> searched; + std::multimap<DeclContext *, DeclContext *> search_queue; + SymbolFile *symbol_file = GetSymbolFile(); + + for (clang::DeclContext *decl_context = root_decl_ctx; + decl_context != nullptr && found_decls.empty(); + decl_context = decl_context->getParent()) { + search_queue.insert(std::make_pair(decl_context, decl_context)); + + for (auto it = search_queue.find(decl_context); it != search_queue.end(); + it++) { + if (!searched.insert(it->second).second) + continue; + symbol_file->ParseDeclsForContext( + CompilerDeclContext(this, it->second)); + + for (clang::Decl *child : it->second->decls()) { + if (clang::UsingDirectiveDecl *ud = + llvm::dyn_cast<clang::UsingDirectiveDecl>(child)) { + if (ignore_using_decls) + continue; + clang::DeclContext *from = ud->getCommonAncestor(); + if (searched.find(ud->getNominatedNamespace()) == searched.end()) + search_queue.insert( + std::make_pair(from, ud->getNominatedNamespace())); + } else if (clang::UsingDecl *ud = + llvm::dyn_cast<clang::UsingDecl>(child)) { + if (ignore_using_decls) + continue; + for (clang::UsingShadowDecl *usd : ud->shadows()) { + clang::Decl *target = usd->getTargetDecl(); + if (clang::NamedDecl *nd = + llvm::dyn_cast<clang::NamedDecl>(target)) { + IdentifierInfo *ii = nd->getIdentifier(); + if (ii != nullptr && + ii->getName().equals(name.AsCString(nullptr))) + found_decls.push_back(CompilerDecl(this, nd)); + } } + } else if (clang::NamedDecl *nd = + llvm::dyn_cast<clang::NamedDecl>(child)) { + IdentifierInfo *ii = nd->getIdentifier(); + if (ii != nullptr && ii->getName().equals(name.AsCString(nullptr))) + found_decls.push_back(CompilerDecl(this, nd)); + } } + } } - return found_decls; + } + return found_decls; } // Look for child_decl_ctx's lookup scope in frame_decl_ctx and its parents, -// and return the number of levels it took to find it, or LLDB_INVALID_DECL_LEVEL -// if not found. If the decl was imported via a using declaration, its name and/or -// type, if set, will be used to check that the decl found in the scope is a match. +// and return the number of levels it took to find it, or +// LLDB_INVALID_DECL_LEVEL +// if not found. If the decl was imported via a using declaration, its name +// and/or +// type, if set, will be used to check that the decl found in the scope is a +// match. // -// The optional name is required by languages (like C++) to handle using declarations +// The optional name is required by languages (like C++) to handle using +// declarations // like: // // void poo(); @@ -9927,288 +9804,269 @@ ClangASTContext::DeclContextFindDeclByName(void *opaque_decl_ctx, // } // // NOTE: Because file statics are at the TranslationUnit along with globals, a -// function at file scope will return the same level as a function at global scope. -// Ideally we'd like to treat the file scope as an additional scope just below the -// global scope. More work needs to be done to recognise that, if the decl we're -// trying to look up is static, we should compare its source file with that of the +// function at file scope will return the same level as a function at global +// scope. +// Ideally we'd like to treat the file scope as an additional scope just below +// the +// global scope. More work needs to be done to recognise that, if the decl +// we're +// trying to look up is static, we should compare its source file with that of +// the // current scope and return a lower number for it. -uint32_t -ClangASTContext::CountDeclLevels (clang::DeclContext *frame_decl_ctx, - clang::DeclContext *child_decl_ctx, - ConstString *child_name, - CompilerType *child_type) -{ - if (frame_decl_ctx) - { - std::set<DeclContext *> searched; - std::multimap<DeclContext *, DeclContext *> search_queue; - SymbolFile *symbol_file = GetSymbolFile(); - - // Get the lookup scope for the decl we're trying to find. - clang::DeclContext *parent_decl_ctx = child_decl_ctx->getParent(); - - // Look for it in our scope's decl context and its parents. - uint32_t level = 0; - for (clang::DeclContext *decl_ctx = frame_decl_ctx; decl_ctx != nullptr; decl_ctx = decl_ctx->getParent()) - { - if (!decl_ctx->isLookupContext()) - continue; - if (decl_ctx == parent_decl_ctx) - // Found it! - return level; - search_queue.insert(std::make_pair(decl_ctx, decl_ctx)); - for (auto it = search_queue.find(decl_ctx); it != search_queue.end(); it++) - { - if (searched.find(it->second) != searched.end()) +uint32_t ClangASTContext::CountDeclLevels(clang::DeclContext *frame_decl_ctx, + clang::DeclContext *child_decl_ctx, + ConstString *child_name, + CompilerType *child_type) { + if (frame_decl_ctx) { + std::set<DeclContext *> searched; + std::multimap<DeclContext *, DeclContext *> search_queue; + SymbolFile *symbol_file = GetSymbolFile(); + + // Get the lookup scope for the decl we're trying to find. + clang::DeclContext *parent_decl_ctx = child_decl_ctx->getParent(); + + // Look for it in our scope's decl context and its parents. + uint32_t level = 0; + for (clang::DeclContext *decl_ctx = frame_decl_ctx; decl_ctx != nullptr; + decl_ctx = decl_ctx->getParent()) { + if (!decl_ctx->isLookupContext()) + continue; + if (decl_ctx == parent_decl_ctx) + // Found it! + return level; + search_queue.insert(std::make_pair(decl_ctx, decl_ctx)); + for (auto it = search_queue.find(decl_ctx); it != search_queue.end(); + it++) { + if (searched.find(it->second) != searched.end()) + continue; + + // Currently DWARF has one shared translation unit for all Decls at top + // level, so this + // would erroneously find using statements anywhere. So don't look at + // the top-level + // translation unit. + // TODO fix this and add a testcase that depends on it. + + if (llvm::isa<clang::TranslationUnitDecl>(it->second)) + continue; + + searched.insert(it->second); + symbol_file->ParseDeclsForContext( + CompilerDeclContext(this, it->second)); + + for (clang::Decl *child : it->second->decls()) { + if (clang::UsingDirectiveDecl *ud = + llvm::dyn_cast<clang::UsingDirectiveDecl>(child)) { + clang::DeclContext *ns = ud->getNominatedNamespace(); + if (ns == parent_decl_ctx) + // Found it! + return level; + clang::DeclContext *from = ud->getCommonAncestor(); + if (searched.find(ns) == searched.end()) + search_queue.insert(std::make_pair(from, ns)); + } else if (child_name) { + if (clang::UsingDecl *ud = + llvm::dyn_cast<clang::UsingDecl>(child)) { + for (clang::UsingShadowDecl *usd : ud->shadows()) { + clang::Decl *target = usd->getTargetDecl(); + clang::NamedDecl *nd = llvm::dyn_cast<clang::NamedDecl>(target); + if (!nd) + continue; + // Check names. + IdentifierInfo *ii = nd->getIdentifier(); + if (ii == nullptr || + !ii->getName().equals(child_name->AsCString(nullptr))) + continue; + // Check types, if one was provided. + if (child_type) { + CompilerType clang_type = ClangASTContext::GetTypeForDecl(nd); + if (!AreTypesSame(clang_type, *child_type, + /*ignore_qualifiers=*/true)) continue; - - // Currently DWARF has one shared translation unit for all Decls at top level, so this - // would erroneously find using statements anywhere. So don't look at the top-level - // translation unit. - // TODO fix this and add a testcase that depends on it. - - if (llvm::isa<clang::TranslationUnitDecl>(it->second)) - continue; - - searched.insert(it->second); - symbol_file->ParseDeclsForContext(CompilerDeclContext(this, it->second)); - - for (clang::Decl *child : it->second->decls()) - { - if (clang::UsingDirectiveDecl *ud = llvm::dyn_cast<clang::UsingDirectiveDecl>(child)) - { - clang::DeclContext *ns = ud->getNominatedNamespace(); - if (ns == parent_decl_ctx) - // Found it! - return level; - clang::DeclContext *from = ud->getCommonAncestor(); - if (searched.find(ns) == searched.end()) - search_queue.insert(std::make_pair(from, ns)); - } - else if (child_name) - { - if (clang::UsingDecl *ud = llvm::dyn_cast<clang::UsingDecl>(child)) - { - for (clang::UsingShadowDecl *usd : ud->shadows()) - { - clang::Decl *target = usd->getTargetDecl(); - clang::NamedDecl *nd = llvm::dyn_cast<clang::NamedDecl>(target); - if (!nd) - continue; - // Check names. - IdentifierInfo *ii = nd->getIdentifier(); - if (ii == nullptr || !ii->getName().equals(child_name->AsCString(nullptr))) - continue; - // Check types, if one was provided. - if (child_type) - { - CompilerType clang_type = ClangASTContext::GetTypeForDecl(nd); - if (!AreTypesSame(clang_type, *child_type, /*ignore_qualifiers=*/true)) - continue; - } - // Found it! - return level; - } - } - } } + // Found it! + return level; + } } - ++level; + } } + } + ++level; } - return LLDB_INVALID_DECL_LEVEL; + } + return LLDB_INVALID_DECL_LEVEL; } -bool -ClangASTContext::DeclContextIsStructUnionOrClass (void *opaque_decl_ctx) -{ - if (opaque_decl_ctx) - return ((clang::DeclContext *)opaque_decl_ctx)->isRecord(); - else - return false; +bool ClangASTContext::DeclContextIsStructUnionOrClass(void *opaque_decl_ctx) { + if (opaque_decl_ctx) + return ((clang::DeclContext *)opaque_decl_ctx)->isRecord(); + else + return false; } -ConstString -ClangASTContext::DeclContextGetName (void *opaque_decl_ctx) -{ - if (opaque_decl_ctx) - { - clang::NamedDecl *named_decl = llvm::dyn_cast<clang::NamedDecl>((clang::DeclContext *)opaque_decl_ctx); - if (named_decl) - return ConstString(named_decl->getName()); - } - return ConstString(); +ConstString ClangASTContext::DeclContextGetName(void *opaque_decl_ctx) { + if (opaque_decl_ctx) { + clang::NamedDecl *named_decl = + llvm::dyn_cast<clang::NamedDecl>((clang::DeclContext *)opaque_decl_ctx); + if (named_decl) + return ConstString(named_decl->getName()); + } + return ConstString(); } ConstString -ClangASTContext::DeclContextGetScopeQualifiedName (void *opaque_decl_ctx) -{ - if (opaque_decl_ctx) - { - clang::NamedDecl *named_decl = llvm::dyn_cast<clang::NamedDecl>((clang::DeclContext *)opaque_decl_ctx); - if (named_decl) - return ConstString(llvm::StringRef(named_decl->getQualifiedNameAsString())); - } - return ConstString(); -} - -bool -ClangASTContext::DeclContextIsClassMethod (void *opaque_decl_ctx, - lldb::LanguageType *language_ptr, - bool *is_instance_method_ptr, - ConstString *language_object_name_ptr) -{ - if (opaque_decl_ctx) - { - clang::DeclContext *decl_ctx = (clang::DeclContext *)opaque_decl_ctx; - if (ObjCMethodDecl *objc_method = llvm::dyn_cast<clang::ObjCMethodDecl>(decl_ctx)) - { - if (is_instance_method_ptr) - *is_instance_method_ptr = objc_method->isInstanceMethod(); - if (language_ptr) - *language_ptr = eLanguageTypeObjC; - if (language_object_name_ptr) - language_object_name_ptr->SetCString("self"); - return true; - } - else if (CXXMethodDecl *cxx_method = llvm::dyn_cast<clang::CXXMethodDecl>(decl_ctx)) - { - if (is_instance_method_ptr) - *is_instance_method_ptr = cxx_method->isInstance(); - if (language_ptr) - *language_ptr = eLanguageTypeC_plus_plus; - if (language_object_name_ptr) - language_object_name_ptr->SetCString("this"); - return true; - } - else if (clang::FunctionDecl *function_decl = llvm::dyn_cast<clang::FunctionDecl>(decl_ctx)) - { - ClangASTMetadata *metadata = GetMetadata (&decl_ctx->getParentASTContext(), function_decl); - if (metadata && metadata->HasObjectPtr()) - { - if (is_instance_method_ptr) - *is_instance_method_ptr = true; - if (language_ptr) - *language_ptr = eLanguageTypeObjC; - if (language_object_name_ptr) - language_object_name_ptr->SetCString (metadata->GetObjectPtrName()); - return true; - } - } +ClangASTContext::DeclContextGetScopeQualifiedName(void *opaque_decl_ctx) { + if (opaque_decl_ctx) { + clang::NamedDecl *named_decl = + llvm::dyn_cast<clang::NamedDecl>((clang::DeclContext *)opaque_decl_ctx); + if (named_decl) + return ConstString( + llvm::StringRef(named_decl->getQualifiedNameAsString())); + } + return ConstString(); +} + +bool ClangASTContext::DeclContextIsClassMethod( + void *opaque_decl_ctx, lldb::LanguageType *language_ptr, + bool *is_instance_method_ptr, ConstString *language_object_name_ptr) { + if (opaque_decl_ctx) { + clang::DeclContext *decl_ctx = (clang::DeclContext *)opaque_decl_ctx; + if (ObjCMethodDecl *objc_method = + llvm::dyn_cast<clang::ObjCMethodDecl>(decl_ctx)) { + if (is_instance_method_ptr) + *is_instance_method_ptr = objc_method->isInstanceMethod(); + if (language_ptr) + *language_ptr = eLanguageTypeObjC; + if (language_object_name_ptr) + language_object_name_ptr->SetCString("self"); + return true; + } else if (CXXMethodDecl *cxx_method = + llvm::dyn_cast<clang::CXXMethodDecl>(decl_ctx)) { + if (is_instance_method_ptr) + *is_instance_method_ptr = cxx_method->isInstance(); + if (language_ptr) + *language_ptr = eLanguageTypeC_plus_plus; + if (language_object_name_ptr) + language_object_name_ptr->SetCString("this"); + return true; + } else if (clang::FunctionDecl *function_decl = + llvm::dyn_cast<clang::FunctionDecl>(decl_ctx)) { + ClangASTMetadata *metadata = + GetMetadata(&decl_ctx->getParentASTContext(), function_decl); + if (metadata && metadata->HasObjectPtr()) { + if (is_instance_method_ptr) + *is_instance_method_ptr = true; + if (language_ptr) + *language_ptr = eLanguageTypeObjC; + if (language_object_name_ptr) + language_object_name_ptr->SetCString(metadata->GetObjectPtrName()); + return true; + } } - return false; + } + return false; } clang::DeclContext * -ClangASTContext::DeclContextGetAsDeclContext (const CompilerDeclContext &dc) -{ - if (dc.IsClang()) - return (clang::DeclContext *)dc.GetOpaqueDeclContext(); - return nullptr; +ClangASTContext::DeclContextGetAsDeclContext(const CompilerDeclContext &dc) { + if (dc.IsClang()) + return (clang::DeclContext *)dc.GetOpaqueDeclContext(); + return nullptr; } - ObjCMethodDecl * -ClangASTContext::DeclContextGetAsObjCMethodDecl (const CompilerDeclContext &dc) -{ - if (dc.IsClang()) - return llvm::dyn_cast<clang::ObjCMethodDecl>((clang::DeclContext *)dc.GetOpaqueDeclContext()); - return nullptr; +ClangASTContext::DeclContextGetAsObjCMethodDecl(const CompilerDeclContext &dc) { + if (dc.IsClang()) + return llvm::dyn_cast<clang::ObjCMethodDecl>( + (clang::DeclContext *)dc.GetOpaqueDeclContext()); + return nullptr; } CXXMethodDecl * -ClangASTContext::DeclContextGetAsCXXMethodDecl (const CompilerDeclContext &dc) -{ - if (dc.IsClang()) - return llvm::dyn_cast<clang::CXXMethodDecl>((clang::DeclContext *)dc.GetOpaqueDeclContext()); - return nullptr; +ClangASTContext::DeclContextGetAsCXXMethodDecl(const CompilerDeclContext &dc) { + if (dc.IsClang()) + return llvm::dyn_cast<clang::CXXMethodDecl>( + (clang::DeclContext *)dc.GetOpaqueDeclContext()); + return nullptr; } clang::FunctionDecl * -ClangASTContext::DeclContextGetAsFunctionDecl (const CompilerDeclContext &dc) -{ - if (dc.IsClang()) - return llvm::dyn_cast<clang::FunctionDecl>((clang::DeclContext *)dc.GetOpaqueDeclContext()); - return nullptr; +ClangASTContext::DeclContextGetAsFunctionDecl(const CompilerDeclContext &dc) { + if (dc.IsClang()) + return llvm::dyn_cast<clang::FunctionDecl>( + (clang::DeclContext *)dc.GetOpaqueDeclContext()); + return nullptr; } clang::NamespaceDecl * -ClangASTContext::DeclContextGetAsNamespaceDecl (const CompilerDeclContext &dc) -{ - if (dc.IsClang()) - return llvm::dyn_cast<clang::NamespaceDecl>((clang::DeclContext *)dc.GetOpaqueDeclContext()); - return nullptr; +ClangASTContext::DeclContextGetAsNamespaceDecl(const CompilerDeclContext &dc) { + if (dc.IsClang()) + return llvm::dyn_cast<clang::NamespaceDecl>( + (clang::DeclContext *)dc.GetOpaqueDeclContext()); + return nullptr; } ClangASTMetadata * -ClangASTContext::DeclContextGetMetaData (const CompilerDeclContext &dc, const void *object) -{ - clang::ASTContext *ast = DeclContextGetClangASTContext (dc); - if (ast) - return ClangASTContext::GetMetadata (ast, object); - return nullptr; +ClangASTContext::DeclContextGetMetaData(const CompilerDeclContext &dc, + const void *object) { + clang::ASTContext *ast = DeclContextGetClangASTContext(dc); + if (ast) + return ClangASTContext::GetMetadata(ast, object); + return nullptr; } clang::ASTContext * -ClangASTContext::DeclContextGetClangASTContext (const CompilerDeclContext &dc) -{ - ClangASTContext *ast = llvm::dyn_cast_or_null<ClangASTContext>(dc.GetTypeSystem()); - if (ast) - return ast->getASTContext(); +ClangASTContext::DeclContextGetClangASTContext(const CompilerDeclContext &dc) { + ClangASTContext *ast = + llvm::dyn_cast_or_null<ClangASTContext>(dc.GetTypeSystem()); + if (ast) + return ast->getASTContext(); + return nullptr; +} + +ClangASTContextForExpressions::ClangASTContextForExpressions(Target &target) + : ClangASTContext(target.GetArchitecture().GetTriple().getTriple().c_str()), + m_target_wp(target.shared_from_this()), + m_persistent_variables(new ClangPersistentVariables) {} + +UserExpression *ClangASTContextForExpressions::GetUserExpression( + const char *expr, const char *expr_prefix, lldb::LanguageType language, + Expression::ResultType desired_type, + const EvaluateExpressionOptions &options) { + TargetSP target_sp = m_target_wp.lock(); + if (!target_sp) return nullptr; + + return new ClangUserExpression(*target_sp.get(), expr, expr_prefix, language, + desired_type, options); } -ClangASTContextForExpressions::ClangASTContextForExpressions (Target &target) : - ClangASTContext (target.GetArchitecture().GetTriple().getTriple().c_str()), - m_target_wp(target.shared_from_this()), - m_persistent_variables (new ClangPersistentVariables) -{ -} - -UserExpression * -ClangASTContextForExpressions::GetUserExpression (const char *expr, - const char *expr_prefix, - lldb::LanguageType language, - Expression::ResultType desired_type, - const EvaluateExpressionOptions &options) -{ - TargetSP target_sp = m_target_wp.lock(); - if (!target_sp) - return nullptr; - - return new ClangUserExpression(*target_sp.get(), expr, expr_prefix, language, desired_type, options); -} - -FunctionCaller * -ClangASTContextForExpressions::GetFunctionCaller (const CompilerType &return_type, - const Address& function_address, - const ValueList &arg_value_list, - const char *name) -{ - TargetSP target_sp = m_target_wp.lock(); - if (!target_sp) - return nullptr; - - Process *process = target_sp->GetProcessSP().get(); - if (!process) - return nullptr; - - return new ClangFunctionCaller (*process, return_type, function_address, arg_value_list, name); +FunctionCaller *ClangASTContextForExpressions::GetFunctionCaller( + const CompilerType &return_type, const Address &function_address, + const ValueList &arg_value_list, const char *name) { + TargetSP target_sp = m_target_wp.lock(); + if (!target_sp) + return nullptr; + + Process *process = target_sp->GetProcessSP().get(); + if (!process) + return nullptr; + + return new ClangFunctionCaller(*process, return_type, function_address, + arg_value_list, name); } UtilityFunction * -ClangASTContextForExpressions::GetUtilityFunction (const char *text, - const char *name) -{ - TargetSP target_sp = m_target_wp.lock(); - if (!target_sp) - return nullptr; - - return new ClangUtilityFunction(*target_sp.get(), text, name); +ClangASTContextForExpressions::GetUtilityFunction(const char *text, + const char *name) { + TargetSP target_sp = m_target_wp.lock(); + if (!target_sp) + return nullptr; + + return new ClangUtilityFunction(*target_sp.get(), text, name); } PersistentExpressionState * -ClangASTContextForExpressions::GetPersistentExpressionState () -{ - return m_persistent_variables.get(); +ClangASTContextForExpressions::GetPersistentExpressionState() { + return m_persistent_variables.get(); } diff --git a/lldb/source/Symbol/ClangASTImporter.cpp b/lldb/source/Symbol/ClangASTImporter.cpp index 6be10602d99..c0e8fea1f3b 100644 --- a/lldb/source/Symbol/ClangASTImporter.cpp +++ b/lldb/source/Symbol/ClangASTImporter.cpp @@ -22,1192 +22,1096 @@ using namespace lldb_private; using namespace clang; -ClangASTMetrics::Counters ClangASTMetrics::global_counters = { 0, 0, 0, 0, 0, 0 }; -ClangASTMetrics::Counters ClangASTMetrics::local_counters = { 0, 0, 0, 0, 0, 0 }; - -void ClangASTMetrics::DumpCounters (Log *log, ClangASTMetrics::Counters &counters) -{ - log->Printf(" Number of visible Decl queries by name : %" PRIu64, counters.m_visible_query_count); - log->Printf(" Number of lexical Decl queries : %" PRIu64, counters.m_lexical_query_count); - log->Printf(" Number of imports initiated by LLDB : %" PRIu64, counters.m_lldb_import_count); - log->Printf(" Number of imports conducted by Clang : %" PRIu64, counters.m_clang_import_count); - log->Printf(" Number of Decls completed : %" PRIu64, counters.m_decls_completed_count); - log->Printf(" Number of records laid out : %" PRIu64, counters.m_record_layout_count); +ClangASTMetrics::Counters ClangASTMetrics::global_counters = {0, 0, 0, 0, 0, 0}; +ClangASTMetrics::Counters ClangASTMetrics::local_counters = {0, 0, 0, 0, 0, 0}; + +void ClangASTMetrics::DumpCounters(Log *log, + ClangASTMetrics::Counters &counters) { + log->Printf(" Number of visible Decl queries by name : %" PRIu64, + counters.m_visible_query_count); + log->Printf(" Number of lexical Decl queries : %" PRIu64, + counters.m_lexical_query_count); + log->Printf(" Number of imports initiated by LLDB : %" PRIu64, + counters.m_lldb_import_count); + log->Printf(" Number of imports conducted by Clang : %" PRIu64, + counters.m_clang_import_count); + log->Printf(" Number of Decls completed : %" PRIu64, + counters.m_decls_completed_count); + log->Printf(" Number of records laid out : %" PRIu64, + counters.m_record_layout_count); } -void ClangASTMetrics::DumpCounters (Log *log) -{ - if (!log) - return; - - log->Printf("== ClangASTMetrics output =="); - log->Printf("-- Global metrics --"); - DumpCounters (log, global_counters); - log->Printf("-- Local metrics --"); - DumpCounters (log, local_counters); +void ClangASTMetrics::DumpCounters(Log *log) { + if (!log) + return; + + log->Printf("== ClangASTMetrics output =="); + log->Printf("-- Global metrics --"); + DumpCounters(log, global_counters); + log->Printf("-- Local metrics --"); + DumpCounters(log, local_counters); } -clang::QualType -ClangASTImporter::CopyType (clang::ASTContext *dst_ast, - clang::ASTContext *src_ast, - clang::QualType type) -{ - MinionSP minion_sp (GetMinion(dst_ast, src_ast)); - - if (minion_sp) - return minion_sp->Import(type); - - return QualType(); +clang::QualType ClangASTImporter::CopyType(clang::ASTContext *dst_ast, + clang::ASTContext *src_ast, + clang::QualType type) { + MinionSP minion_sp(GetMinion(dst_ast, src_ast)); + + if (minion_sp) + return minion_sp->Import(type); + + return QualType(); } lldb::opaque_compiler_type_t -ClangASTImporter::CopyType (clang::ASTContext *dst_ast, - clang::ASTContext *src_ast, - lldb::opaque_compiler_type_t type) -{ - return CopyType (dst_ast, src_ast, QualType::getFromOpaquePtr(type)).getAsOpaquePtr(); +ClangASTImporter::CopyType(clang::ASTContext *dst_ast, + clang::ASTContext *src_ast, + lldb::opaque_compiler_type_t type) { + return CopyType(dst_ast, src_ast, QualType::getFromOpaquePtr(type)) + .getAsOpaquePtr(); } -CompilerType -ClangASTImporter::CopyType (ClangASTContext &dst_ast, - const CompilerType &src_type) -{ - clang::ASTContext *dst_clang_ast = dst_ast.getASTContext(); - if (dst_clang_ast) - { - ClangASTContext *src_ast = llvm::dyn_cast_or_null<ClangASTContext>(src_type.GetTypeSystem()); - if (src_ast) - { - clang::ASTContext *src_clang_ast = src_ast->getASTContext(); - if (src_clang_ast) - { - lldb::opaque_compiler_type_t dst_clang_type = CopyType(dst_clang_ast, - src_clang_ast, - src_type.GetOpaqueQualType()); - - if (dst_clang_type) - return CompilerType(&dst_ast, dst_clang_type); - } - } +CompilerType ClangASTImporter::CopyType(ClangASTContext &dst_ast, + const CompilerType &src_type) { + clang::ASTContext *dst_clang_ast = dst_ast.getASTContext(); + if (dst_clang_ast) { + ClangASTContext *src_ast = + llvm::dyn_cast_or_null<ClangASTContext>(src_type.GetTypeSystem()); + if (src_ast) { + clang::ASTContext *src_clang_ast = src_ast->getASTContext(); + if (src_clang_ast) { + lldb::opaque_compiler_type_t dst_clang_type = CopyType( + dst_clang_ast, src_clang_ast, src_type.GetOpaqueQualType()); + + if (dst_clang_type) + return CompilerType(&dst_ast, dst_clang_type); + } } - return CompilerType(); + } + return CompilerType(); } -clang::Decl * -ClangASTImporter::CopyDecl (clang::ASTContext *dst_ast, - clang::ASTContext *src_ast, - clang::Decl *decl) -{ - MinionSP minion_sp; - - minion_sp = GetMinion(dst_ast, src_ast); - - if (minion_sp) - { - clang::Decl *result = minion_sp->Import(decl); - - if (!result) - { - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); - - if (log) - { - lldb::user_id_t user_id = LLDB_INVALID_UID; - ClangASTMetadata *metadata = GetDeclMetadata(decl); - if (metadata) - user_id = metadata->GetUserID(); - - if (NamedDecl *named_decl = dyn_cast<NamedDecl>(decl)) - log->Printf(" [ClangASTImporter] WARNING: Failed to import a %s '%s', metadata 0x%" PRIx64, - decl->getDeclKindName(), - named_decl->getNameAsString().c_str(), - user_id); - else - log->Printf(" [ClangASTImporter] WARNING: Failed to import a %s, metadata 0x%" PRIx64, - decl->getDeclKindName(), - user_id); - } - } - - return result; +clang::Decl *ClangASTImporter::CopyDecl(clang::ASTContext *dst_ast, + clang::ASTContext *src_ast, + clang::Decl *decl) { + MinionSP minion_sp; + + minion_sp = GetMinion(dst_ast, src_ast); + + if (minion_sp) { + clang::Decl *result = minion_sp->Import(decl); + + if (!result) { + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); + + if (log) { + lldb::user_id_t user_id = LLDB_INVALID_UID; + ClangASTMetadata *metadata = GetDeclMetadata(decl); + if (metadata) + user_id = metadata->GetUserID(); + + if (NamedDecl *named_decl = dyn_cast<NamedDecl>(decl)) + log->Printf(" [ClangASTImporter] WARNING: Failed to import a %s " + "'%s', metadata 0x%" PRIx64, + decl->getDeclKindName(), + named_decl->getNameAsString().c_str(), user_id); + else + log->Printf(" [ClangASTImporter] WARNING: Failed to import a %s, " + "metadata 0x%" PRIx64, + decl->getDeclKindName(), user_id); + } } - - return nullptr; + + return result; + } + + return nullptr; } -class DeclContextOverride -{ +class DeclContextOverride { private: - struct Backup - { - clang::DeclContext *decl_context; - clang::DeclContext *lexical_decl_context; - }; - - std::map<clang::Decl *, Backup> m_backups; - - void OverrideOne(clang::Decl *decl) - { - if (m_backups.find(decl) != m_backups.end()) - { - return; - } - - m_backups[decl] = { decl->getDeclContext(), decl->getLexicalDeclContext() }; - - decl->setDeclContext(decl->getASTContext().getTranslationUnitDecl()); - decl->setLexicalDeclContext(decl->getASTContext().getTranslationUnitDecl()); + struct Backup { + clang::DeclContext *decl_context; + clang::DeclContext *lexical_decl_context; + }; + + std::map<clang::Decl *, Backup> m_backups; + + void OverrideOne(clang::Decl *decl) { + if (m_backups.find(decl) != m_backups.end()) { + return; } - - bool ChainPassesThrough(clang::Decl *decl, - clang::DeclContext *base, - clang::DeclContext *(clang::Decl::*contextFromDecl)(), - clang::DeclContext *(clang::DeclContext::*contextFromContext)()) - { - for (DeclContext *decl_ctx = (decl->*contextFromDecl)(); - decl_ctx; - decl_ctx = (decl_ctx->*contextFromContext)()) - { - if (decl_ctx == base) - { - return true; - } - } - - return false; + + m_backups[decl] = {decl->getDeclContext(), decl->getLexicalDeclContext()}; + + decl->setDeclContext(decl->getASTContext().getTranslationUnitDecl()); + decl->setLexicalDeclContext(decl->getASTContext().getTranslationUnitDecl()); + } + + bool ChainPassesThrough( + clang::Decl *decl, clang::DeclContext *base, + clang::DeclContext *(clang::Decl::*contextFromDecl)(), + clang::DeclContext *(clang::DeclContext::*contextFromContext)()) { + for (DeclContext *decl_ctx = (decl->*contextFromDecl)(); decl_ctx; + decl_ctx = (decl_ctx->*contextFromContext)()) { + if (decl_ctx == base) { + return true; + } } - - clang::Decl *GetEscapedChild(clang::Decl *decl, clang::DeclContext *base = nullptr) - { - if (base) - { - // decl's DeclContext chains must pass through base. - - if (!ChainPassesThrough(decl, base, &clang::Decl::getDeclContext, &clang::DeclContext::getParent) || - !ChainPassesThrough(decl, base, &clang::Decl::getLexicalDeclContext, &clang::DeclContext::getLexicalParent)) - { - return decl; - } - } - else - { - base = clang::dyn_cast<clang::DeclContext>(decl); - - if (!base) - { - return nullptr; - } - } - - if (clang::DeclContext *context = clang::dyn_cast<clang::DeclContext>(decl)) - { - for (clang::Decl *decl : context->decls()) - { - if (clang::Decl *escaped_child = GetEscapedChild(decl)) - { - return escaped_child; - } - } - } - + + return false; + } + + clang::Decl *GetEscapedChild(clang::Decl *decl, + clang::DeclContext *base = nullptr) { + if (base) { + // decl's DeclContext chains must pass through base. + + if (!ChainPassesThrough(decl, base, &clang::Decl::getDeclContext, + &clang::DeclContext::getParent) || + !ChainPassesThrough(decl, base, &clang::Decl::getLexicalDeclContext, + &clang::DeclContext::getLexicalParent)) { + return decl; + } + } else { + base = clang::dyn_cast<clang::DeclContext>(decl); + + if (!base) { return nullptr; + } } - - void Override(clang::Decl *decl) - { - if (clang::Decl *escaped_child = GetEscapedChild(decl)) - { - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); - - if (log) - log->Printf(" [ClangASTImporter] DeclContextOverride couldn't override (%sDecl*)%p - its child (%sDecl*)%p escapes", - decl->getDeclKindName(), static_cast<void*>(decl), - escaped_child->getDeclKindName(), static_cast<void*>(escaped_child)); - lldbassert(0 && "Couldn't override!"); + + if (clang::DeclContext *context = + clang::dyn_cast<clang::DeclContext>(decl)) { + for (clang::Decl *decl : context->decls()) { + if (clang::Decl *escaped_child = GetEscapedChild(decl)) { + return escaped_child; } - - OverrideOne(decl); + } } - -public: - DeclContextOverride() - { + + return nullptr; + } + + void Override(clang::Decl *decl) { + if (clang::Decl *escaped_child = GetEscapedChild(decl)) { + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); + + if (log) + log->Printf(" [ClangASTImporter] DeclContextOverride couldn't " + "override (%sDecl*)%p - its child (%sDecl*)%p escapes", + decl->getDeclKindName(), static_cast<void *>(decl), + escaped_child->getDeclKindName(), + static_cast<void *>(escaped_child)); + lldbassert(0 && "Couldn't override!"); } - - void OverrideAllDeclsFromContainingFunction(clang::Decl *decl) - { - for (DeclContext *decl_context = decl->getLexicalDeclContext(); - decl_context; - decl_context = decl_context->getLexicalParent()) - { - DeclContext *redecl_context = decl_context->getRedeclContext(); - - if (llvm::isa<FunctionDecl>(redecl_context) && - llvm::isa<TranslationUnitDecl>(redecl_context->getLexicalParent())) - { - for (clang::Decl *child_decl : decl_context->decls()) - { - Override(child_decl); - } - } + + OverrideOne(decl); + } + +public: + DeclContextOverride() {} + + void OverrideAllDeclsFromContainingFunction(clang::Decl *decl) { + for (DeclContext *decl_context = decl->getLexicalDeclContext(); + decl_context; decl_context = decl_context->getLexicalParent()) { + DeclContext *redecl_context = decl_context->getRedeclContext(); + + if (llvm::isa<FunctionDecl>(redecl_context) && + llvm::isa<TranslationUnitDecl>(redecl_context->getLexicalParent())) { + for (clang::Decl *child_decl : decl_context->decls()) { + Override(child_decl); } + } } - - ~DeclContextOverride() - { - for (const std::pair<clang::Decl *, Backup> &backup : m_backups) - { - backup.first->setDeclContext(backup.second.decl_context); - backup.first->setLexicalDeclContext(backup.second.lexical_decl_context); - } + } + + ~DeclContextOverride() { + for (const std::pair<clang::Decl *, Backup> &backup : m_backups) { + backup.first->setDeclContext(backup.second.decl_context); + backup.first->setLexicalDeclContext(backup.second.lexical_decl_context); } + } }; lldb::opaque_compiler_type_t -ClangASTImporter::DeportType (clang::ASTContext *dst_ctx, - clang::ASTContext *src_ctx, - lldb::opaque_compiler_type_t type) -{ - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); - - if (log) - log->Printf(" [ClangASTImporter] DeportType called on (%sType*)0x%llx from (ASTContext*)%p to (ASTContext*)%p", - QualType::getFromOpaquePtr(type)->getTypeClassName(), (unsigned long long)type, - static_cast<void*>(src_ctx), - static_cast<void*>(dst_ctx)); - - MinionSP minion_sp (GetMinion (dst_ctx, src_ctx)); - - if (!minion_sp) - return nullptr; - - std::set<NamedDecl *> decls_to_deport; - std::set<NamedDecl *> decls_already_deported; - - DeclContextOverride decl_context_override; - - if (const clang::TagType *tag_type = clang::QualType::getFromOpaquePtr(type)->getAs<TagType>()) - { - decl_context_override.OverrideAllDeclsFromContainingFunction(tag_type->getDecl()); - } - - minion_sp->InitDeportWorkQueues(&decls_to_deport, - &decls_already_deported); - - lldb::opaque_compiler_type_t result = CopyType(dst_ctx, src_ctx, type); - - minion_sp->ExecuteDeportWorkQueues(); - - if (!result) - return nullptr; - - return result; +ClangASTImporter::DeportType(clang::ASTContext *dst_ctx, + clang::ASTContext *src_ctx, + lldb::opaque_compiler_type_t type) { + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); -} - -clang::Decl * -ClangASTImporter::DeportDecl (clang::ASTContext *dst_ctx, - clang::ASTContext *src_ctx, - clang::Decl *decl) -{ - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + if (log) + log->Printf(" [ClangASTImporter] DeportType called on (%sType*)0x%llx " + "from (ASTContext*)%p to (ASTContext*)%p", + QualType::getFromOpaquePtr(type)->getTypeClassName(), + (unsigned long long)type, static_cast<void *>(src_ctx), + static_cast<void *>(dst_ctx)); - if (log) - log->Printf(" [ClangASTImporter] DeportDecl called on (%sDecl*)%p from (ASTContext*)%p to (ASTContext*)%p", - decl->getDeclKindName(), static_cast<void*>(decl), - static_cast<void*>(src_ctx), - static_cast<void*>(dst_ctx)); + MinionSP minion_sp(GetMinion(dst_ctx, src_ctx)); - MinionSP minion_sp (GetMinion (dst_ctx, src_ctx)); + if (!minion_sp) + return nullptr; - if (!minion_sp) - return nullptr; + std::set<NamedDecl *> decls_to_deport; + std::set<NamedDecl *> decls_already_deported; - std::set<NamedDecl *> decls_to_deport; - std::set<NamedDecl *> decls_already_deported; - - DeclContextOverride decl_context_override; - - decl_context_override.OverrideAllDeclsFromContainingFunction(decl); + DeclContextOverride decl_context_override; - minion_sp->InitDeportWorkQueues(&decls_to_deport, - &decls_already_deported); + if (const clang::TagType *tag_type = + clang::QualType::getFromOpaquePtr(type)->getAs<TagType>()) { + decl_context_override.OverrideAllDeclsFromContainingFunction( + tag_type->getDecl()); + } - clang::Decl *result = CopyDecl(dst_ctx, src_ctx, decl); + minion_sp->InitDeportWorkQueues(&decls_to_deport, &decls_already_deported); - minion_sp->ExecuteDeportWorkQueues(); + lldb::opaque_compiler_type_t result = CopyType(dst_ctx, src_ctx, type); - if (!result) - return nullptr; + minion_sp->ExecuteDeportWorkQueues(); - if (log) - log->Printf(" [ClangASTImporter] DeportDecl deported (%sDecl*)%p to (%sDecl*)%p", - decl->getDeclKindName(), static_cast<void*>(decl), - result->getDeclKindName(), static_cast<void*>(result)); + if (!result) + return nullptr; - return result; + return result; } -bool -ClangASTImporter::CanImport(const CompilerType &type) -{ - if (!ClangUtil::IsClangType(type)) - return false; +clang::Decl *ClangASTImporter::DeportDecl(clang::ASTContext *dst_ctx, + clang::ASTContext *src_ctx, + clang::Decl *decl) { + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); - // TODO: remove external completion BOOL - // CompleteAndFetchChildren should get the Decl out and check for the - - clang::QualType qual_type(ClangUtil::GetCanonicalQualType(ClangUtil::RemoveFastQualifiers(type))); - - const clang::Type::TypeClass type_class = qual_type->getTypeClass(); - switch (type_class) - { - case clang::Type::Record: - { - const clang::CXXRecordDecl *cxx_record_decl = qual_type->getAsCXXRecordDecl(); - if (cxx_record_decl) - { - if (ResolveDeclOrigin(cxx_record_decl, NULL, NULL)) - return true; - } - } - break; + if (log) + log->Printf(" [ClangASTImporter] DeportDecl called on (%sDecl*)%p from " + "(ASTContext*)%p to (ASTContext*)%p", + decl->getDeclKindName(), static_cast<void *>(decl), + static_cast<void *>(src_ctx), static_cast<void *>(dst_ctx)); - case clang::Type::Enum: - { - clang::EnumDecl *enum_decl = llvm::cast<clang::EnumType>(qual_type)->getDecl(); - if (enum_decl) - { - if (ResolveDeclOrigin(enum_decl, NULL, NULL)) - return true; - } - } - break; + MinionSP minion_sp(GetMinion(dst_ctx, src_ctx)); - case clang::Type::ObjCObject: - case clang::Type::ObjCInterface: - { - const clang::ObjCObjectType *objc_class_type = llvm::dyn_cast<clang::ObjCObjectType>(qual_type); - if (objc_class_type) - { - clang::ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface(); - // We currently can't complete objective C types through the newly added ASTContext - // because it only supports TagDecl objects right now... - if (class_interface_decl) - { - if (ResolveDeclOrigin(class_interface_decl, NULL, NULL)) - return true; - } - } - } - break; + if (!minion_sp) + return nullptr; - case clang::Type::Typedef: - return CanImport(CompilerType( - type.GetTypeSystem(), - llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType().getAsOpaquePtr())); + std::set<NamedDecl *> decls_to_deport; + std::set<NamedDecl *> decls_already_deported; - case clang::Type::Auto: - return CanImport(CompilerType(type.GetTypeSystem(), - llvm::cast<clang::AutoType>(qual_type)->getDeducedType().getAsOpaquePtr())); + DeclContextOverride decl_context_override; - case clang::Type::Elaborated: - return CanImport(CompilerType( - type.GetTypeSystem(), llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType().getAsOpaquePtr())); + decl_context_override.OverrideAllDeclsFromContainingFunction(decl); - case clang::Type::Paren: - return CanImport(CompilerType(type.GetTypeSystem(), - llvm::cast<clang::ParenType>(qual_type)->desugar().getAsOpaquePtr())); + minion_sp->InitDeportWorkQueues(&decls_to_deport, &decls_already_deported); - default: - break; - } + clang::Decl *result = CopyDecl(dst_ctx, src_ctx, decl); - return false; -} + minion_sp->ExecuteDeportWorkQueues(); -bool -ClangASTImporter::Import(const CompilerType &type) -{ - if (!ClangUtil::IsClangType(type)) - return false; - // TODO: remove external completion BOOL - // CompleteAndFetchChildren should get the Decl out and check for the - - clang::QualType qual_type(ClangUtil::GetCanonicalQualType(ClangUtil::RemoveFastQualifiers(type))); - - const clang::Type::TypeClass type_class = qual_type->getTypeClass(); - switch (type_class) - { - case clang::Type::Record: - { - const clang::CXXRecordDecl *cxx_record_decl = qual_type->getAsCXXRecordDecl(); - if (cxx_record_decl) - { - if (ResolveDeclOrigin(cxx_record_decl, NULL, NULL)) - return CompleteAndFetchChildren(qual_type); - } - } - break; + if (!result) + return nullptr; - case clang::Type::Enum: - { - clang::EnumDecl *enum_decl = llvm::cast<clang::EnumType>(qual_type)->getDecl(); - if (enum_decl) - { - if (ResolveDeclOrigin(enum_decl, NULL, NULL)) - return CompleteAndFetchChildren(qual_type); - } - } - break; + if (log) + log->Printf( + " [ClangASTImporter] DeportDecl deported (%sDecl*)%p to (%sDecl*)%p", + decl->getDeclKindName(), static_cast<void *>(decl), + result->getDeclKindName(), static_cast<void *>(result)); - case clang::Type::ObjCObject: - case clang::Type::ObjCInterface: - { - const clang::ObjCObjectType *objc_class_type = llvm::dyn_cast<clang::ObjCObjectType>(qual_type); - if (objc_class_type) - { - clang::ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface(); - // We currently can't complete objective C types through the newly added ASTContext - // because it only supports TagDecl objects right now... - if (class_interface_decl) - { - if (ResolveDeclOrigin(class_interface_decl, NULL, NULL)) - return CompleteAndFetchChildren(qual_type); - } - } - } - break; + return result; +} - case clang::Type::Typedef: - return Import(CompilerType( - type.GetTypeSystem(), - llvm::cast<clang::TypedefType>(qual_type)->getDecl()->getUnderlyingType().getAsOpaquePtr())); +bool ClangASTImporter::CanImport(const CompilerType &type) { + if (!ClangUtil::IsClangType(type)) + return false; - case clang::Type::Auto: - return Import(CompilerType(type.GetTypeSystem(), - llvm::cast<clang::AutoType>(qual_type)->getDeducedType().getAsOpaquePtr())); + // TODO: remove external completion BOOL + // CompleteAndFetchChildren should get the Decl out and check for the - case clang::Type::Elaborated: - return Import(CompilerType(type.GetTypeSystem(), - llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType().getAsOpaquePtr())); + clang::QualType qual_type( + ClangUtil::GetCanonicalQualType(ClangUtil::RemoveFastQualifiers(type))); - case clang::Type::Paren: - return Import(CompilerType(type.GetTypeSystem(), - llvm::cast<clang::ParenType>(qual_type)->desugar().getAsOpaquePtr())); + const clang::Type::TypeClass type_class = qual_type->getTypeClass(); + switch (type_class) { + case clang::Type::Record: { + const clang::CXXRecordDecl *cxx_record_decl = + qual_type->getAsCXXRecordDecl(); + if (cxx_record_decl) { + if (ResolveDeclOrigin(cxx_record_decl, NULL, NULL)) + return true; + } + } break; - default: - break; + case clang::Type::Enum: { + clang::EnumDecl *enum_decl = + llvm::cast<clang::EnumType>(qual_type)->getDecl(); + if (enum_decl) { + if (ResolveDeclOrigin(enum_decl, NULL, NULL)) + return true; } - return false; + } break; + + case clang::Type::ObjCObject: + case clang::Type::ObjCInterface: { + const clang::ObjCObjectType *objc_class_type = + llvm::dyn_cast<clang::ObjCObjectType>(qual_type); + if (objc_class_type) { + clang::ObjCInterfaceDecl *class_interface_decl = + objc_class_type->getInterface(); + // We currently can't complete objective C types through the newly added + // ASTContext + // because it only supports TagDecl objects right now... + if (class_interface_decl) { + if (ResolveDeclOrigin(class_interface_decl, NULL, NULL)) + return true; + } + } + } break; + + case clang::Type::Typedef: + return CanImport(CompilerType(type.GetTypeSystem(), + llvm::cast<clang::TypedefType>(qual_type) + ->getDecl() + ->getUnderlyingType() + .getAsOpaquePtr())); + + case clang::Type::Auto: + return CanImport(CompilerType(type.GetTypeSystem(), + llvm::cast<clang::AutoType>(qual_type) + ->getDeducedType() + .getAsOpaquePtr())); + + case clang::Type::Elaborated: + return CanImport(CompilerType(type.GetTypeSystem(), + llvm::cast<clang::ElaboratedType>(qual_type) + ->getNamedType() + .getAsOpaquePtr())); + + case clang::Type::Paren: + return CanImport(CompilerType( + type.GetTypeSystem(), + llvm::cast<clang::ParenType>(qual_type)->desugar().getAsOpaquePtr())); + + default: + break; + } + + return false; } -bool -ClangASTImporter::CompleteType(const CompilerType &compiler_type) -{ - if (!CanImport(compiler_type)) - return false; - - if (Import(compiler_type)) - { - ClangASTContext::CompleteTagDeclarationDefinition(compiler_type); - return true; +bool ClangASTImporter::Import(const CompilerType &type) { + if (!ClangUtil::IsClangType(type)) + return false; + // TODO: remove external completion BOOL + // CompleteAndFetchChildren should get the Decl out and check for the + + clang::QualType qual_type( + ClangUtil::GetCanonicalQualType(ClangUtil::RemoveFastQualifiers(type))); + + const clang::Type::TypeClass type_class = qual_type->getTypeClass(); + switch (type_class) { + case clang::Type::Record: { + const clang::CXXRecordDecl *cxx_record_decl = + qual_type->getAsCXXRecordDecl(); + if (cxx_record_decl) { + if (ResolveDeclOrigin(cxx_record_decl, NULL, NULL)) + return CompleteAndFetchChildren(qual_type); } + } break; + + case clang::Type::Enum: { + clang::EnumDecl *enum_decl = + llvm::cast<clang::EnumType>(qual_type)->getDecl(); + if (enum_decl) { + if (ResolveDeclOrigin(enum_decl, NULL, NULL)) + return CompleteAndFetchChildren(qual_type); + } + } break; + + case clang::Type::ObjCObject: + case clang::Type::ObjCInterface: { + const clang::ObjCObjectType *objc_class_type = + llvm::dyn_cast<clang::ObjCObjectType>(qual_type); + if (objc_class_type) { + clang::ObjCInterfaceDecl *class_interface_decl = + objc_class_type->getInterface(); + // We currently can't complete objective C types through the newly added + // ASTContext + // because it only supports TagDecl objects right now... + if (class_interface_decl) { + if (ResolveDeclOrigin(class_interface_decl, NULL, NULL)) + return CompleteAndFetchChildren(qual_type); + } + } + } break; + + case clang::Type::Typedef: + return Import(CompilerType(type.GetTypeSystem(), + llvm::cast<clang::TypedefType>(qual_type) + ->getDecl() + ->getUnderlyingType() + .getAsOpaquePtr())); + + case clang::Type::Auto: + return Import(CompilerType(type.GetTypeSystem(), + llvm::cast<clang::AutoType>(qual_type) + ->getDeducedType() + .getAsOpaquePtr())); + + case clang::Type::Elaborated: + return Import(CompilerType(type.GetTypeSystem(), + llvm::cast<clang::ElaboratedType>(qual_type) + ->getNamedType() + .getAsOpaquePtr())); + + case clang::Type::Paren: + return Import(CompilerType( + type.GetTypeSystem(), + llvm::cast<clang::ParenType>(qual_type)->desugar().getAsOpaquePtr())); + + default: + break; + } + return false; +} - ClangASTContext::SetHasExternalStorage(compiler_type.GetOpaqueQualType(), false); +bool ClangASTImporter::CompleteType(const CompilerType &compiler_type) { + if (!CanImport(compiler_type)) return false; + + if (Import(compiler_type)) { + ClangASTContext::CompleteTagDeclarationDefinition(compiler_type); + return true; + } + + ClangASTContext::SetHasExternalStorage(compiler_type.GetOpaqueQualType(), + false); + return false; } -bool -ClangASTImporter::LayoutRecordType(const clang::RecordDecl *record_decl, uint64_t &bit_size, uint64_t &alignment, - llvm::DenseMap<const clang::FieldDecl *, uint64_t> &field_offsets, - llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> &base_offsets, - llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> &vbase_offsets) -{ - RecordDeclToLayoutMap::iterator pos = m_record_decl_to_layout_map.find(record_decl); - bool success = false; - base_offsets.clear(); - vbase_offsets.clear(); - if (pos != m_record_decl_to_layout_map.end()) - { - bit_size = pos->second.bit_size; - alignment = pos->second.alignment; - field_offsets.swap(pos->second.field_offsets); - base_offsets.swap(pos->second.base_offsets); - vbase_offsets.swap(pos->second.vbase_offsets); - m_record_decl_to_layout_map.erase(pos); - success = true; - } - else - { - bit_size = 0; - alignment = 0; - field_offsets.clear(); - } - return success; +bool ClangASTImporter::LayoutRecordType( + const clang::RecordDecl *record_decl, uint64_t &bit_size, + uint64_t &alignment, + llvm::DenseMap<const clang::FieldDecl *, uint64_t> &field_offsets, + llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> + &base_offsets, + llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> + &vbase_offsets) { + RecordDeclToLayoutMap::iterator pos = + m_record_decl_to_layout_map.find(record_decl); + bool success = false; + base_offsets.clear(); + vbase_offsets.clear(); + if (pos != m_record_decl_to_layout_map.end()) { + bit_size = pos->second.bit_size; + alignment = pos->second.alignment; + field_offsets.swap(pos->second.field_offsets); + base_offsets.swap(pos->second.base_offsets); + vbase_offsets.swap(pos->second.vbase_offsets); + m_record_decl_to_layout_map.erase(pos); + success = true; + } else { + bit_size = 0; + alignment = 0; + field_offsets.clear(); + } + return success; } -void -ClangASTImporter::InsertRecordDecl(clang::RecordDecl *decl, const LayoutInfo &layout) -{ - m_record_decl_to_layout_map.insert(std::make_pair(decl, layout)); +void ClangASTImporter::InsertRecordDecl(clang::RecordDecl *decl, + const LayoutInfo &layout) { + m_record_decl_to_layout_map.insert(std::make_pair(decl, layout)); } -void -ClangASTImporter::CompleteDecl (clang::Decl *decl) -{ - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); +void ClangASTImporter::CompleteDecl(clang::Decl *decl) { + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); - if (log) - log->Printf(" [ClangASTImporter] CompleteDecl called on (%sDecl*)%p", - decl->getDeclKindName(), static_cast<void*>(decl)); - - if (ObjCInterfaceDecl *interface_decl = dyn_cast<ObjCInterfaceDecl>(decl)) - { - if (!interface_decl->getDefinition()) - { - interface_decl->startDefinition(); - CompleteObjCInterfaceDecl(interface_decl); - } - } - else if (ObjCProtocolDecl *protocol_decl = dyn_cast<ObjCProtocolDecl>(decl)) - { - if (!protocol_decl->getDefinition()) - protocol_decl->startDefinition(); - } - else if (TagDecl *tag_decl = dyn_cast<TagDecl>(decl)) - { - if (!tag_decl->getDefinition() && !tag_decl->isBeingDefined()) - { - tag_decl->startDefinition(); - CompleteTagDecl(tag_decl); - tag_decl->setCompleteDefinition(true); - } + if (log) + log->Printf(" [ClangASTImporter] CompleteDecl called on (%sDecl*)%p", + decl->getDeclKindName(), static_cast<void *>(decl)); + + if (ObjCInterfaceDecl *interface_decl = dyn_cast<ObjCInterfaceDecl>(decl)) { + if (!interface_decl->getDefinition()) { + interface_decl->startDefinition(); + CompleteObjCInterfaceDecl(interface_decl); } - else - { - assert (0 && "CompleteDecl called on a Decl that can't be completed"); + } else if (ObjCProtocolDecl *protocol_decl = + dyn_cast<ObjCProtocolDecl>(decl)) { + if (!protocol_decl->getDefinition()) + protocol_decl->startDefinition(); + } else if (TagDecl *tag_decl = dyn_cast<TagDecl>(decl)) { + if (!tag_decl->getDefinition() && !tag_decl->isBeingDefined()) { + tag_decl->startDefinition(); + CompleteTagDecl(tag_decl); + tag_decl->setCompleteDefinition(true); } + } else { + assert(0 && "CompleteDecl called on a Decl that can't be completed"); + } } -bool -ClangASTImporter::CompleteTagDecl (clang::TagDecl *decl) -{ - ClangASTMetrics::RegisterDeclCompletion(); - - DeclOrigin decl_origin = GetDeclOrigin(decl); - - if (!decl_origin.Valid()) - return false; - - if (!ClangASTContext::GetCompleteDecl(decl_origin.ctx, decl_origin.decl)) - return false; - - MinionSP minion_sp (GetMinion(&decl->getASTContext(), decl_origin.ctx)); - - if (minion_sp) - minion_sp->ImportDefinitionTo(decl, decl_origin.decl); - - return true; -} +bool ClangASTImporter::CompleteTagDecl(clang::TagDecl *decl) { + ClangASTMetrics::RegisterDeclCompletion(); -bool -ClangASTImporter::CompleteTagDeclWithOrigin(clang::TagDecl *decl, clang::TagDecl *origin_decl) -{ - ClangASTMetrics::RegisterDeclCompletion(); + DeclOrigin decl_origin = GetDeclOrigin(decl); - clang::ASTContext *origin_ast_ctx = &origin_decl->getASTContext(); - - if (!ClangASTContext::GetCompleteDecl(origin_ast_ctx, origin_decl)) - return false; - - MinionSP minion_sp (GetMinion(&decl->getASTContext(), origin_ast_ctx)); - - if (minion_sp) - minion_sp->ImportDefinitionTo(decl, origin_decl); - - ASTContextMetadataSP context_md = GetContextMetadata(&decl->getASTContext()); - - OriginMap &origins = context_md->m_origins; - - origins[decl] = DeclOrigin(origin_ast_ctx, origin_decl); - - return true; + if (!decl_origin.Valid()) + return false; + + if (!ClangASTContext::GetCompleteDecl(decl_origin.ctx, decl_origin.decl)) + return false; + + MinionSP minion_sp(GetMinion(&decl->getASTContext(), decl_origin.ctx)); + + if (minion_sp) + minion_sp->ImportDefinitionTo(decl, decl_origin.decl); + + return true; } -bool -ClangASTImporter::CompleteObjCInterfaceDecl (clang::ObjCInterfaceDecl *interface_decl) -{ - ClangASTMetrics::RegisterDeclCompletion(); - - DeclOrigin decl_origin = GetDeclOrigin(interface_decl); - - if (!decl_origin.Valid()) - return false; - - if (!ClangASTContext::GetCompleteDecl(decl_origin.ctx, decl_origin.decl)) - return false; - - MinionSP minion_sp (GetMinion(&interface_decl->getASTContext(), decl_origin.ctx)); - - if (minion_sp) - minion_sp->ImportDefinitionTo(interface_decl, decl_origin.decl); +bool ClangASTImporter::CompleteTagDeclWithOrigin(clang::TagDecl *decl, + clang::TagDecl *origin_decl) { + ClangASTMetrics::RegisterDeclCompletion(); - if (ObjCInterfaceDecl *super_class = interface_decl->getSuperClass()) - RequireCompleteType(clang::QualType(super_class->getTypeForDecl(), 0)); + clang::ASTContext *origin_ast_ctx = &origin_decl->getASTContext(); - return true; + if (!ClangASTContext::GetCompleteDecl(origin_ast_ctx, origin_decl)) + return false; + + MinionSP minion_sp(GetMinion(&decl->getASTContext(), origin_ast_ctx)); + + if (minion_sp) + minion_sp->ImportDefinitionTo(decl, origin_decl); + + ASTContextMetadataSP context_md = GetContextMetadata(&decl->getASTContext()); + + OriginMap &origins = context_md->m_origins; + + origins[decl] = DeclOrigin(origin_ast_ctx, origin_decl); + + return true; } -bool -ClangASTImporter::CompleteAndFetchChildren (clang::QualType type) -{ - if (!RequireCompleteType(type)) - return false; +bool ClangASTImporter::CompleteObjCInterfaceDecl( + clang::ObjCInterfaceDecl *interface_decl) { + ClangASTMetrics::RegisterDeclCompletion(); - if (const TagType *tag_type = type->getAs<TagType>()) - { - TagDecl *tag_decl = tag_type->getDecl(); + DeclOrigin decl_origin = GetDeclOrigin(interface_decl); - DeclOrigin decl_origin = GetDeclOrigin(tag_decl); + if (!decl_origin.Valid()) + return false; - if (!decl_origin.Valid()) - return false; + if (!ClangASTContext::GetCompleteDecl(decl_origin.ctx, decl_origin.decl)) + return false; - MinionSP minion_sp (GetMinion(&tag_decl->getASTContext(), decl_origin.ctx)); + MinionSP minion_sp( + GetMinion(&interface_decl->getASTContext(), decl_origin.ctx)); - TagDecl *origin_tag_decl = llvm::dyn_cast<TagDecl>(decl_origin.decl); + if (minion_sp) + minion_sp->ImportDefinitionTo(interface_decl, decl_origin.decl); - for (Decl *origin_child_decl : origin_tag_decl->decls()) - { - minion_sp->Import(origin_child_decl); - } + if (ObjCInterfaceDecl *super_class = interface_decl->getSuperClass()) + RequireCompleteType(clang::QualType(super_class->getTypeForDecl(), 0)); - if (RecordDecl *record_decl = dyn_cast<RecordDecl>(origin_tag_decl)) - { - record_decl->setHasLoadedFieldsFromExternalStorage(true); - } + return true; +} - return true; - } +bool ClangASTImporter::CompleteAndFetchChildren(clang::QualType type) { + if (!RequireCompleteType(type)) + return false; - if (const ObjCObjectType *objc_object_type = type->getAs<ObjCObjectType>()) - { - if (ObjCInterfaceDecl *objc_interface_decl = objc_object_type->getInterface()) - { - DeclOrigin decl_origin = GetDeclOrigin(objc_interface_decl); + if (const TagType *tag_type = type->getAs<TagType>()) { + TagDecl *tag_decl = tag_type->getDecl(); - if (!decl_origin.Valid()) - return false; + DeclOrigin decl_origin = GetDeclOrigin(tag_decl); - MinionSP minion_sp (GetMinion(&objc_interface_decl->getASTContext(), decl_origin.ctx)); + if (!decl_origin.Valid()) + return false; - ObjCInterfaceDecl *origin_interface_decl = llvm::dyn_cast<ObjCInterfaceDecl>(decl_origin.decl); + MinionSP minion_sp(GetMinion(&tag_decl->getASTContext(), decl_origin.ctx)); - for (Decl *origin_child_decl : origin_interface_decl->decls()) - { - minion_sp->Import(origin_child_decl); - } + TagDecl *origin_tag_decl = llvm::dyn_cast<TagDecl>(decl_origin.decl); - return true; - } - else - { - return false; - } + for (Decl *origin_child_decl : origin_tag_decl->decls()) { + minion_sp->Import(origin_child_decl); } - + + if (RecordDecl *record_decl = dyn_cast<RecordDecl>(origin_tag_decl)) { + record_decl->setHasLoadedFieldsFromExternalStorage(true); + } + return true; -} + } + if (const ObjCObjectType *objc_object_type = type->getAs<ObjCObjectType>()) { + if (ObjCInterfaceDecl *objc_interface_decl = + objc_object_type->getInterface()) { + DeclOrigin decl_origin = GetDeclOrigin(objc_interface_decl); -bool -ClangASTImporter::RequireCompleteType (clang::QualType type) -{ - if (type.isNull()) + if (!decl_origin.Valid()) return false; - - if (const TagType *tag_type = type->getAs<TagType>()) - { - TagDecl *tag_decl = tag_type->getDecl(); - if (tag_decl->getDefinition() || tag_decl->isBeingDefined()) - return true; + MinionSP minion_sp( + GetMinion(&objc_interface_decl->getASTContext(), decl_origin.ctx)); - return CompleteTagDecl(tag_decl); - } - if (const ObjCObjectType *objc_object_type = type->getAs<ObjCObjectType>()) - { - if (ObjCInterfaceDecl *objc_interface_decl = objc_object_type->getInterface()) - return CompleteObjCInterfaceDecl(objc_interface_decl); - else - return false; - } - if (const ArrayType *array_type = type->getAsArrayTypeUnsafe()) - { - return RequireCompleteType(array_type->getElementType()); - } - if (const AtomicType *atomic_type = type->getAs<AtomicType>()) - { - return RequireCompleteType(atomic_type->getPointeeType()); + ObjCInterfaceDecl *origin_interface_decl = + llvm::dyn_cast<ObjCInterfaceDecl>(decl_origin.decl); + + for (Decl *origin_child_decl : origin_interface_decl->decls()) { + minion_sp->Import(origin_child_decl); + } + + return true; + } else { + return false; } - - return true; -} + } -ClangASTMetadata * -ClangASTImporter::GetDeclMetadata (const clang::Decl *decl) -{ - DeclOrigin decl_origin = GetDeclOrigin(decl); - - if (decl_origin.Valid()) - return ClangASTContext::GetMetadata(decl_origin.ctx, decl_origin.decl); - else - return ClangASTContext::GetMetadata(&decl->getASTContext(), decl); + return true; } -ClangASTImporter::DeclOrigin -ClangASTImporter::GetDeclOrigin(const clang::Decl *decl) -{ - ASTContextMetadataSP context_md = GetContextMetadata(&decl->getASTContext()); - - OriginMap &origins = context_md->m_origins; - - OriginMap::iterator iter = origins.find(decl); - - if (iter != origins.end()) - return iter->second; +bool ClangASTImporter::RequireCompleteType(clang::QualType type) { + if (type.isNull()) + return false; + + if (const TagType *tag_type = type->getAs<TagType>()) { + TagDecl *tag_decl = tag_type->getDecl(); + + if (tag_decl->getDefinition() || tag_decl->isBeingDefined()) + return true; + + return CompleteTagDecl(tag_decl); + } + if (const ObjCObjectType *objc_object_type = type->getAs<ObjCObjectType>()) { + if (ObjCInterfaceDecl *objc_interface_decl = + objc_object_type->getInterface()) + return CompleteObjCInterfaceDecl(objc_interface_decl); else - return DeclOrigin(); + return false; + } + if (const ArrayType *array_type = type->getAsArrayTypeUnsafe()) { + return RequireCompleteType(array_type->getElementType()); + } + if (const AtomicType *atomic_type = type->getAs<AtomicType>()) { + return RequireCompleteType(atomic_type->getPointeeType()); + } + + return true; } -void -ClangASTImporter::SetDeclOrigin (const clang::Decl *decl, clang::Decl *original_decl) -{ - ASTContextMetadataSP context_md = GetContextMetadata(&decl->getASTContext()); - - OriginMap &origins = context_md->m_origins; - - OriginMap::iterator iter = origins.find(decl); - - if (iter != origins.end()) - { - iter->second.decl = original_decl; - iter->second.ctx = &original_decl->getASTContext(); - } - else - { - origins[decl] = DeclOrigin(&original_decl->getASTContext(), original_decl); - } +ClangASTMetadata *ClangASTImporter::GetDeclMetadata(const clang::Decl *decl) { + DeclOrigin decl_origin = GetDeclOrigin(decl); + + if (decl_origin.Valid()) + return ClangASTContext::GetMetadata(decl_origin.ctx, decl_origin.decl); + else + return ClangASTContext::GetMetadata(&decl->getASTContext(), decl); } -void -ClangASTImporter::RegisterNamespaceMap(const clang::NamespaceDecl *decl, - NamespaceMapSP &namespace_map) -{ - ASTContextMetadataSP context_md = GetContextMetadata(&decl->getASTContext()); - - context_md->m_namespace_maps[decl] = namespace_map; +ClangASTImporter::DeclOrigin +ClangASTImporter::GetDeclOrigin(const clang::Decl *decl) { + ASTContextMetadataSP context_md = GetContextMetadata(&decl->getASTContext()); + + OriginMap &origins = context_md->m_origins; + + OriginMap::iterator iter = origins.find(decl); + + if (iter != origins.end()) + return iter->second; + else + return DeclOrigin(); } -ClangASTImporter::NamespaceMapSP -ClangASTImporter::GetNamespaceMap(const clang::NamespaceDecl *decl) -{ - ASTContextMetadataSP context_md = GetContextMetadata(&decl->getASTContext()); - - NamespaceMetaMap &namespace_maps = context_md->m_namespace_maps; - - NamespaceMetaMap::iterator iter = namespace_maps.find(decl); - - if (iter != namespace_maps.end()) - return iter->second; - else - return NamespaceMapSP(); +void ClangASTImporter::SetDeclOrigin(const clang::Decl *decl, + clang::Decl *original_decl) { + ASTContextMetadataSP context_md = GetContextMetadata(&decl->getASTContext()); + + OriginMap &origins = context_md->m_origins; + + OriginMap::iterator iter = origins.find(decl); + + if (iter != origins.end()) { + iter->second.decl = original_decl; + iter->second.ctx = &original_decl->getASTContext(); + } else { + origins[decl] = DeclOrigin(&original_decl->getASTContext(), original_decl); + } } -void -ClangASTImporter::BuildNamespaceMap(const clang::NamespaceDecl *decl) -{ - assert (decl); - ASTContextMetadataSP context_md = GetContextMetadata(&decl->getASTContext()); - - const DeclContext *parent_context = decl->getDeclContext(); - const NamespaceDecl *parent_namespace = dyn_cast<NamespaceDecl>(parent_context); - NamespaceMapSP parent_map; - - if (parent_namespace) - parent_map = GetNamespaceMap(parent_namespace); - - NamespaceMapSP new_map; - - new_map.reset(new NamespaceMap); - - if (context_md->m_map_completer) - { - std::string namespace_string = decl->getDeclName().getAsString(); - - context_md->m_map_completer->CompleteNamespaceMap (new_map, ConstString(namespace_string.c_str()), parent_map); - } - - context_md->m_namespace_maps[decl] = new_map; +void ClangASTImporter::RegisterNamespaceMap(const clang::NamespaceDecl *decl, + NamespaceMapSP &namespace_map) { + ASTContextMetadataSP context_md = GetContextMetadata(&decl->getASTContext()); + + context_md->m_namespace_maps[decl] = namespace_map; } -void -ClangASTImporter::ForgetDestination (clang::ASTContext *dst_ast) -{ - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); +ClangASTImporter::NamespaceMapSP +ClangASTImporter::GetNamespaceMap(const clang::NamespaceDecl *decl) { + ASTContextMetadataSP context_md = GetContextMetadata(&decl->getASTContext()); - if (log) - log->Printf(" [ClangASTImporter] Forgetting destination (ASTContext*)%p", - static_cast<void*>(dst_ast)); + NamespaceMetaMap &namespace_maps = context_md->m_namespace_maps; + + NamespaceMetaMap::iterator iter = namespace_maps.find(decl); - m_metadata_map.erase(dst_ast); + if (iter != namespace_maps.end()) + return iter->second; + else + return NamespaceMapSP(); } -void -ClangASTImporter::ForgetSource (clang::ASTContext *dst_ast, clang::ASTContext *src_ast) -{ - ASTContextMetadataSP md = MaybeGetContextMetadata (dst_ast); +void ClangASTImporter::BuildNamespaceMap(const clang::NamespaceDecl *decl) { + assert(decl); + ASTContextMetadataSP context_md = GetContextMetadata(&decl->getASTContext()); - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + const DeclContext *parent_context = decl->getDeclContext(); + const NamespaceDecl *parent_namespace = + dyn_cast<NamespaceDecl>(parent_context); + NamespaceMapSP parent_map; - if (log) - log->Printf(" [ClangASTImporter] Forgetting source->dest (ASTContext*)%p->(ASTContext*)%p", - static_cast<void*>(src_ast), static_cast<void*>(dst_ast)); + if (parent_namespace) + parent_map = GetNamespaceMap(parent_namespace); - if (!md) - return; + NamespaceMapSP new_map; - md->m_minions.erase(src_ast); + new_map.reset(new NamespaceMap); - for (OriginMap::iterator iter = md->m_origins.begin(); - iter != md->m_origins.end(); - ) - { - if (iter->second.ctx == src_ast) - md->m_origins.erase(iter++); - else - ++iter; - } + if (context_md->m_map_completer) { + std::string namespace_string = decl->getDeclName().getAsString(); + + context_md->m_map_completer->CompleteNamespaceMap( + new_map, ConstString(namespace_string.c_str()), parent_map); + } + + context_md->m_namespace_maps[decl] = new_map; } -ClangASTImporter::MapCompleter::~MapCompleter () -{ - return; +void ClangASTImporter::ForgetDestination(clang::ASTContext *dst_ast) { + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); + + if (log) + log->Printf(" [ClangASTImporter] Forgetting destination (ASTContext*)%p", + static_cast<void *>(dst_ast)); + + m_metadata_map.erase(dst_ast); } -void -ClangASTImporter::Minion::InitDeportWorkQueues (std::set<clang::NamedDecl *> *decls_to_deport, - std::set<clang::NamedDecl *> *decls_already_deported) -{ - assert(!m_decls_to_deport); - assert(!m_decls_already_deported); - - m_decls_to_deport = decls_to_deport; - m_decls_already_deported = decls_already_deported; +void ClangASTImporter::ForgetSource(clang::ASTContext *dst_ast, + clang::ASTContext *src_ast) { + ASTContextMetadataSP md = MaybeGetContextMetadata(dst_ast); + + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); + + if (log) + log->Printf(" [ClangASTImporter] Forgetting source->dest " + "(ASTContext*)%p->(ASTContext*)%p", + static_cast<void *>(src_ast), static_cast<void *>(dst_ast)); + + if (!md) + return; + + md->m_minions.erase(src_ast); + + for (OriginMap::iterator iter = md->m_origins.begin(); + iter != md->m_origins.end();) { + if (iter->second.ctx == src_ast) + md->m_origins.erase(iter++); + else + ++iter; + } } -void -ClangASTImporter::Minion::ExecuteDeportWorkQueues () -{ - assert(m_decls_to_deport); - assert(m_decls_already_deported); - - ASTContextMetadataSP to_context_md = m_master.GetContextMetadata(&getToContext()); - - while (!m_decls_to_deport->empty()) - { - NamedDecl *decl = *m_decls_to_deport->begin(); - - m_decls_already_deported->insert(decl); - m_decls_to_deport->erase(decl); - - DeclOrigin &origin = to_context_md->m_origins[decl]; - UNUSED_IF_ASSERT_DISABLED(origin); - - assert (origin.ctx == m_source_ctx); // otherwise we should never have added this - // because it doesn't need to be deported - - Decl *original_decl = to_context_md->m_origins[decl].decl; - - ClangASTContext::GetCompleteDecl (m_source_ctx, original_decl); - - if (TagDecl *tag_decl = dyn_cast<TagDecl>(decl)) - { - if (TagDecl *original_tag_decl = dyn_cast<TagDecl>(original_decl)) - { - if (original_tag_decl->isCompleteDefinition()) - { - ImportDefinitionTo(tag_decl, original_tag_decl); - tag_decl->setCompleteDefinition(true); - } - } - - tag_decl->setHasExternalLexicalStorage(false); - tag_decl->setHasExternalVisibleStorage(false); - } - else if (ObjCContainerDecl *container_decl = dyn_cast<ObjCContainerDecl>(decl)) - { - container_decl->setHasExternalLexicalStorage(false); - container_decl->setHasExternalVisibleStorage(false); - } - - to_context_md->m_origins.erase(decl); - } - - m_decls_to_deport = nullptr; - m_decls_already_deported = nullptr; +ClangASTImporter::MapCompleter::~MapCompleter() { return; } + +void ClangASTImporter::Minion::InitDeportWorkQueues( + std::set<clang::NamedDecl *> *decls_to_deport, + std::set<clang::NamedDecl *> *decls_already_deported) { + assert(!m_decls_to_deport); + assert(!m_decls_already_deported); + + m_decls_to_deport = decls_to_deport; + m_decls_already_deported = decls_already_deported; } -void -ClangASTImporter::Minion::ImportDefinitionTo (clang::Decl *to, clang::Decl *from) -{ - ASTImporter::Imported(from, to); +void ClangASTImporter::Minion::ExecuteDeportWorkQueues() { + assert(m_decls_to_deport); + assert(m_decls_already_deported); - /* - if (to_objc_interface) - to_objc_interface->startDefinition(); - - CXXRecordDecl *to_cxx_record = dyn_cast<CXXRecordDecl>(to); - - if (to_cxx_record) - to_cxx_record->startDefinition(); - */ - - ImportDefinition(from); - - if (clang::TagDecl *to_tag = dyn_cast<clang::TagDecl>(to)) - { - if (clang::TagDecl *from_tag = dyn_cast<clang::TagDecl>(from)) - { - to_tag->setCompleteDefinition(from_tag->isCompleteDefinition()); - } - } - - // If we're dealing with an Objective-C class, ensure that the inheritance has - // been set up correctly. The ASTImporter may not do this correctly if the - // class was originally sourced from symbols. - - if (ObjCInterfaceDecl *to_objc_interface = dyn_cast<ObjCInterfaceDecl>(to)) - { - do - { - ObjCInterfaceDecl *to_superclass = to_objc_interface->getSuperClass(); - - if (to_superclass) - break; // we're not going to override it if it's set - - ObjCInterfaceDecl *from_objc_interface = dyn_cast<ObjCInterfaceDecl>(from); - - if (!from_objc_interface) - break; - - ObjCInterfaceDecl *from_superclass = from_objc_interface->getSuperClass(); - - if (!from_superclass) - break; - - Decl *imported_from_superclass_decl = Import(from_superclass); - - if (!imported_from_superclass_decl) - break; - - ObjCInterfaceDecl *imported_from_superclass = dyn_cast<ObjCInterfaceDecl>(imported_from_superclass_decl); - - if (!imported_from_superclass) - break; - - if (!to_objc_interface->hasDefinition()) - to_objc_interface->startDefinition(); - - to_objc_interface->setSuperClass( - m_source_ctx->getTrivialTypeSourceInfo(m_source_ctx->getObjCInterfaceType(imported_from_superclass))); + ASTContextMetadataSP to_context_md = + m_master.GetContextMetadata(&getToContext()); + + while (!m_decls_to_deport->empty()) { + NamedDecl *decl = *m_decls_to_deport->begin(); + + m_decls_already_deported->insert(decl); + m_decls_to_deport->erase(decl); + + DeclOrigin &origin = to_context_md->m_origins[decl]; + UNUSED_IF_ASSERT_DISABLED(origin); + + assert(origin.ctx == + m_source_ctx); // otherwise we should never have added this + // because it doesn't need to be deported + + Decl *original_decl = to_context_md->m_origins[decl].decl; + + ClangASTContext::GetCompleteDecl(m_source_ctx, original_decl); + + if (TagDecl *tag_decl = dyn_cast<TagDecl>(decl)) { + if (TagDecl *original_tag_decl = dyn_cast<TagDecl>(original_decl)) { + if (original_tag_decl->isCompleteDefinition()) { + ImportDefinitionTo(tag_decl, original_tag_decl); + tag_decl->setCompleteDefinition(true); } - while (0); + } + + tag_decl->setHasExternalLexicalStorage(false); + tag_decl->setHasExternalVisibleStorage(false); + } else if (ObjCContainerDecl *container_decl = + dyn_cast<ObjCContainerDecl>(decl)) { + container_decl->setHasExternalLexicalStorage(false); + container_decl->setHasExternalVisibleStorage(false); } + + to_context_md->m_origins.erase(decl); + } + + m_decls_to_deport = nullptr; + m_decls_already_deported = nullptr; } -clang::Decl * -ClangASTImporter::Minion::Imported (clang::Decl *from, clang::Decl *to) -{ - ClangASTMetrics::RegisterClangImport(); +void ClangASTImporter::Minion::ImportDefinitionTo(clang::Decl *to, + clang::Decl *from) { + ASTImporter::Imported(from, to); - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + /* + if (to_objc_interface) + to_objc_interface->startDefinition(); - lldb::user_id_t user_id = LLDB_INVALID_UID; - ClangASTMetadata *metadata = m_master.GetDeclMetadata(from); - if (metadata) - user_id = metadata->GetUserID(); - - if (log) - { - if (NamedDecl *from_named_decl = dyn_cast<clang::NamedDecl>(from)) - { - std::string name_string; - llvm::raw_string_ostream name_stream(name_string); - from_named_decl->printName(name_stream); - name_stream.flush(); - - log->Printf(" [ClangASTImporter] Imported (%sDecl*)%p, named %s (from (Decl*)%p), metadata 0x%" PRIx64, - from->getDeclKindName(), static_cast<void*>(to), - name_string.c_str(), static_cast<void*>(from), - user_id); - } - else - { - log->Printf(" [ClangASTImporter] Imported (%sDecl*)%p (from (Decl*)%p), metadata 0x%" PRIx64, - from->getDeclKindName(), static_cast<void*>(to), - static_cast<void*>(from), user_id); - } + CXXRecordDecl *to_cxx_record = dyn_cast<CXXRecordDecl>(to); + + if (to_cxx_record) + to_cxx_record->startDefinition(); + */ + + ImportDefinition(from); + + if (clang::TagDecl *to_tag = dyn_cast<clang::TagDecl>(to)) { + if (clang::TagDecl *from_tag = dyn_cast<clang::TagDecl>(from)) { + to_tag->setCompleteDefinition(from_tag->isCompleteDefinition()); } + } - ASTContextMetadataSP to_context_md = m_master.GetContextMetadata(&to->getASTContext()); - ASTContextMetadataSP from_context_md = m_master.MaybeGetContextMetadata(m_source_ctx); - - if (from_context_md) - { - OriginMap &origins = from_context_md->m_origins; - - OriginMap::iterator origin_iter = origins.find(from); - - if (origin_iter != origins.end()) - { - if (to_context_md->m_origins.find(to) == to_context_md->m_origins.end() || - user_id != LLDB_INVALID_UID) - { - if (origin_iter->second.ctx != &to->getASTContext()) - to_context_md->m_origins[to] = origin_iter->second; - } - - MinionSP direct_completer = m_master.GetMinion(&to->getASTContext(), origin_iter->second.ctx); - - if (direct_completer.get() != this) - direct_completer->ASTImporter::Imported(origin_iter->second.decl, to); - - if (log) - log->Printf(" [ClangASTImporter] Propagated origin (Decl*)%p/(ASTContext*)%p from (ASTContext*)%p to (ASTContext*)%p", - static_cast<void*>(origin_iter->second.decl), - static_cast<void*>(origin_iter->second.ctx), - static_cast<void*>(&from->getASTContext()), - static_cast<void*>(&to->getASTContext())); - } - else - { - if (m_decls_to_deport && m_decls_already_deported) - { - if (isa<TagDecl>(to) || isa<ObjCInterfaceDecl>(to)) - { - RecordDecl *from_record_decl = dyn_cast<RecordDecl>(from); - if (from_record_decl == nullptr || from_record_decl->isInjectedClassName() == false) - { - NamedDecl *to_named_decl = dyn_cast<NamedDecl>(to); - - if (!m_decls_already_deported->count(to_named_decl)) - m_decls_to_deport->insert(to_named_decl); - } - } - } - - if (to_context_md->m_origins.find(to) == to_context_md->m_origins.end() || - user_id != LLDB_INVALID_UID) - { - to_context_md->m_origins[to] = DeclOrigin(m_source_ctx, from); - } - - if (log) - log->Printf(" [ClangASTImporter] Decl has no origin information in (ASTContext*)%p", - static_cast<void*>(&from->getASTContext())); - } + // If we're dealing with an Objective-C class, ensure that the inheritance has + // been set up correctly. The ASTImporter may not do this correctly if the + // class was originally sourced from symbols. - if (clang::NamespaceDecl *to_namespace = dyn_cast<clang::NamespaceDecl>(to)) - { - clang::NamespaceDecl *from_namespace = dyn_cast<clang::NamespaceDecl>(from); + if (ObjCInterfaceDecl *to_objc_interface = dyn_cast<ObjCInterfaceDecl>(to)) { + do { + ObjCInterfaceDecl *to_superclass = to_objc_interface->getSuperClass(); - NamespaceMetaMap &namespace_maps = from_context_md->m_namespace_maps; + if (to_superclass) + break; // we're not going to override it if it's set - NamespaceMetaMap::iterator namespace_map_iter = namespace_maps.find(from_namespace); + ObjCInterfaceDecl *from_objc_interface = + dyn_cast<ObjCInterfaceDecl>(from); - if (namespace_map_iter != namespace_maps.end()) - to_context_md->m_namespace_maps[to_namespace] = namespace_map_iter->second; - } + if (!from_objc_interface) + break; + + ObjCInterfaceDecl *from_superclass = from_objc_interface->getSuperClass(); + + if (!from_superclass) + break; + + Decl *imported_from_superclass_decl = Import(from_superclass); + + if (!imported_from_superclass_decl) + break; + + ObjCInterfaceDecl *imported_from_superclass = + dyn_cast<ObjCInterfaceDecl>(imported_from_superclass_decl); + + if (!imported_from_superclass) + break; + + if (!to_objc_interface->hasDefinition()) + to_objc_interface->startDefinition(); + + to_objc_interface->setSuperClass(m_source_ctx->getTrivialTypeSourceInfo( + m_source_ctx->getObjCInterfaceType(imported_from_superclass))); + } while (0); + } +} + +clang::Decl *ClangASTImporter::Minion::Imported(clang::Decl *from, + clang::Decl *to) { + ClangASTMetrics::RegisterClangImport(); + + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); + + lldb::user_id_t user_id = LLDB_INVALID_UID; + ClangASTMetadata *metadata = m_master.GetDeclMetadata(from); + if (metadata) + user_id = metadata->GetUserID(); + + if (log) { + if (NamedDecl *from_named_decl = dyn_cast<clang::NamedDecl>(from)) { + std::string name_string; + llvm::raw_string_ostream name_stream(name_string); + from_named_decl->printName(name_stream); + name_stream.flush(); + + log->Printf(" [ClangASTImporter] Imported (%sDecl*)%p, named %s (from " + "(Decl*)%p), metadata 0x%" PRIx64, + from->getDeclKindName(), static_cast<void *>(to), + name_string.c_str(), static_cast<void *>(from), user_id); + } else { + log->Printf(" [ClangASTImporter] Imported (%sDecl*)%p (from " + "(Decl*)%p), metadata 0x%" PRIx64, + from->getDeclKindName(), static_cast<void *>(to), + static_cast<void *>(from), user_id); } - else - { - to_context_md->m_origins[to] = DeclOrigin (m_source_ctx, from); - - if (log) - log->Printf(" [ClangASTImporter] Sourced origin (Decl*)%p/(ASTContext*)%p into (ASTContext*)%p", - static_cast<void*>(from), - static_cast<void*>(m_source_ctx), - static_cast<void*>(&to->getASTContext())); + } + + ASTContextMetadataSP to_context_md = + m_master.GetContextMetadata(&to->getASTContext()); + ASTContextMetadataSP from_context_md = + m_master.MaybeGetContextMetadata(m_source_ctx); + + if (from_context_md) { + OriginMap &origins = from_context_md->m_origins; + + OriginMap::iterator origin_iter = origins.find(from); + + if (origin_iter != origins.end()) { + if (to_context_md->m_origins.find(to) == to_context_md->m_origins.end() || + user_id != LLDB_INVALID_UID) { + if (origin_iter->second.ctx != &to->getASTContext()) + to_context_md->m_origins[to] = origin_iter->second; + } + + MinionSP direct_completer = + m_master.GetMinion(&to->getASTContext(), origin_iter->second.ctx); + + if (direct_completer.get() != this) + direct_completer->ASTImporter::Imported(origin_iter->second.decl, to); + + if (log) + log->Printf(" [ClangASTImporter] Propagated origin " + "(Decl*)%p/(ASTContext*)%p from (ASTContext*)%p to " + "(ASTContext*)%p", + static_cast<void *>(origin_iter->second.decl), + static_cast<void *>(origin_iter->second.ctx), + static_cast<void *>(&from->getASTContext()), + static_cast<void *>(&to->getASTContext())); + } else { + if (m_decls_to_deport && m_decls_already_deported) { + if (isa<TagDecl>(to) || isa<ObjCInterfaceDecl>(to)) { + RecordDecl *from_record_decl = dyn_cast<RecordDecl>(from); + if (from_record_decl == nullptr || + from_record_decl->isInjectedClassName() == false) { + NamedDecl *to_named_decl = dyn_cast<NamedDecl>(to); + + if (!m_decls_already_deported->count(to_named_decl)) + m_decls_to_deport->insert(to_named_decl); + } + } + } + + if (to_context_md->m_origins.find(to) == to_context_md->m_origins.end() || + user_id != LLDB_INVALID_UID) { + to_context_md->m_origins[to] = DeclOrigin(m_source_ctx, from); + } + + if (log) + log->Printf(" [ClangASTImporter] Decl has no origin information in " + "(ASTContext*)%p", + static_cast<void *>(&from->getASTContext())); } - if (TagDecl *from_tag_decl = dyn_cast<TagDecl>(from)) - { - TagDecl *to_tag_decl = dyn_cast<TagDecl>(to); + if (clang::NamespaceDecl *to_namespace = + dyn_cast<clang::NamespaceDecl>(to)) { + clang::NamespaceDecl *from_namespace = + dyn_cast<clang::NamespaceDecl>(from); - to_tag_decl->setHasExternalLexicalStorage(); - to_tag_decl->setMustBuildLookupTable(); + NamespaceMetaMap &namespace_maps = from_context_md->m_namespace_maps; - if (log) - log->Printf(" [ClangASTImporter] To is a TagDecl - attributes %s%s [%s->%s]", - (to_tag_decl->hasExternalLexicalStorage() ? " Lexical" : ""), - (to_tag_decl->hasExternalVisibleStorage() ? " Visible" : ""), - (from_tag_decl->isCompleteDefinition() ? "complete" : "incomplete"), - (to_tag_decl->isCompleteDefinition() ? "complete" : "incomplete")); + NamespaceMetaMap::iterator namespace_map_iter = + namespace_maps.find(from_namespace); + + if (namespace_map_iter != namespace_maps.end()) + to_context_md->m_namespace_maps[to_namespace] = + namespace_map_iter->second; } + } else { + to_context_md->m_origins[to] = DeclOrigin(m_source_ctx, from); - if (isa<NamespaceDecl>(from)) - { - NamespaceDecl *to_namespace_decl = dyn_cast<NamespaceDecl>(to); + if (log) + log->Printf(" [ClangASTImporter] Sourced origin " + "(Decl*)%p/(ASTContext*)%p into (ASTContext*)%p", + static_cast<void *>(from), static_cast<void *>(m_source_ctx), + static_cast<void *>(&to->getASTContext())); + } - m_master.BuildNamespaceMap(to_namespace_decl); + if (TagDecl *from_tag_decl = dyn_cast<TagDecl>(from)) { + TagDecl *to_tag_decl = dyn_cast<TagDecl>(to); - to_namespace_decl->setHasExternalVisibleStorage(); - } + to_tag_decl->setHasExternalLexicalStorage(); + to_tag_decl->setMustBuildLookupTable(); - if (isa<ObjCContainerDecl>(from)) - { - ObjCContainerDecl *to_container_decl = dyn_cast<ObjCContainerDecl>(to); - - to_container_decl->setHasExternalLexicalStorage(); - to_container_decl->setHasExternalVisibleStorage(); - - /*to_interface_decl->setExternallyCompleted();*/ - - if (log) - { - if (ObjCInterfaceDecl *to_interface_decl = llvm::dyn_cast<ObjCInterfaceDecl>(to_container_decl)) - { - log->Printf(" [ClangASTImporter] To is an ObjCInterfaceDecl - attributes %s%s%s", - (to_interface_decl->hasExternalLexicalStorage() ? " Lexical" : ""), - (to_interface_decl->hasExternalVisibleStorage() ? " Visible" : ""), - (to_interface_decl->hasDefinition() ? " HasDefinition" : "")); - } - else - { - log->Printf(" [ClangASTImporter] To is an %sDecl - attributes %s%s", - ((Decl*)to_container_decl)->getDeclKindName(), - (to_container_decl->hasExternalLexicalStorage() ? " Lexical" : ""), - (to_container_decl->hasExternalVisibleStorage() ? " Visible" : "")); - } - } + if (log) + log->Printf( + " [ClangASTImporter] To is a TagDecl - attributes %s%s [%s->%s]", + (to_tag_decl->hasExternalLexicalStorage() ? " Lexical" : ""), + (to_tag_decl->hasExternalVisibleStorage() ? " Visible" : ""), + (from_tag_decl->isCompleteDefinition() ? "complete" : "incomplete"), + (to_tag_decl->isCompleteDefinition() ? "complete" : "incomplete")); + } + + if (isa<NamespaceDecl>(from)) { + NamespaceDecl *to_namespace_decl = dyn_cast<NamespaceDecl>(to); + + m_master.BuildNamespaceMap(to_namespace_decl); + + to_namespace_decl->setHasExternalVisibleStorage(); + } + + if (isa<ObjCContainerDecl>(from)) { + ObjCContainerDecl *to_container_decl = dyn_cast<ObjCContainerDecl>(to); + + to_container_decl->setHasExternalLexicalStorage(); + to_container_decl->setHasExternalVisibleStorage(); + + /*to_interface_decl->setExternallyCompleted();*/ + + if (log) { + if (ObjCInterfaceDecl *to_interface_decl = + llvm::dyn_cast<ObjCInterfaceDecl>(to_container_decl)) { + log->Printf( + " [ClangASTImporter] To is an ObjCInterfaceDecl - attributes " + "%s%s%s", + (to_interface_decl->hasExternalLexicalStorage() ? " Lexical" : ""), + (to_interface_decl->hasExternalVisibleStorage() ? " Visible" : ""), + (to_interface_decl->hasDefinition() ? " HasDefinition" : "")); + } else { + log->Printf( + " [ClangASTImporter] To is an %sDecl - attributes %s%s", + ((Decl *)to_container_decl)->getDeclKindName(), + (to_container_decl->hasExternalLexicalStorage() ? " Lexical" : ""), + (to_container_decl->hasExternalVisibleStorage() ? " Visible" : "")); + } } + } - return clang::ASTImporter::Imported(from, to); + return clang::ASTImporter::Imported(from, to); } -clang::Decl *ClangASTImporter::Minion::GetOriginalDecl (clang::Decl *To) -{ - ASTContextMetadataSP to_context_md = m_master.GetContextMetadata(&To->getASTContext()); - - if (!to_context_md) - return nullptr; - - OriginMap::iterator iter = to_context_md->m_origins.find(To); - - if (iter == to_context_md->m_origins.end()) - return nullptr; - - return const_cast<clang::Decl*>(iter->second.decl); +clang::Decl *ClangASTImporter::Minion::GetOriginalDecl(clang::Decl *To) { + ASTContextMetadataSP to_context_md = + m_master.GetContextMetadata(&To->getASTContext()); + + if (!to_context_md) + return nullptr; + + OriginMap::iterator iter = to_context_md->m_origins.find(To); + + if (iter == to_context_md->m_origins.end()) + return nullptr; + + return const_cast<clang::Decl *>(iter->second.decl); } diff --git a/lldb/source/Symbol/ClangExternalASTSourceCallbacks.cpp b/lldb/source/Symbol/ClangExternalASTSourceCallbacks.cpp index 6c804f4d969..e39baea8ead 100644 --- a/lldb/source/Symbol/ClangExternalASTSourceCallbacks.cpp +++ b/lldb/source/Symbol/ClangExternalASTSourceCallbacks.cpp @@ -13,7 +13,7 @@ // C++ Includes // Other libraries and framework includes -// Clang headers like to use NDEBUG inside of them to enable/disable debug +// Clang headers like to use NDEBUG inside of them to enable/disable debug // related features using "#ifndef NDEBUG" preprocessor blocks to do one thing // or another. This is bad because it means that if clang was built in release // mode, it assumes that you are building in release mode which is not always @@ -46,131 +46,145 @@ using namespace clang; using namespace lldb_private; -bool -ClangExternalASTSourceCallbacks::FindExternalVisibleDeclsByName -( +bool ClangExternalASTSourceCallbacks::FindExternalVisibleDeclsByName( const clang::DeclContext *decl_ctx, - clang::DeclarationName clang_decl_name -) -{ - if (m_callback_find_by_name) - { - llvm::SmallVector <clang::NamedDecl *, 3> results; - - m_callback_find_by_name (m_callback_baton, decl_ctx, clang_decl_name, &results); - - SetExternalVisibleDeclsForName(decl_ctx, clang_decl_name, results); - - return (results.size() != 0); - } - - std::string decl_name (clang_decl_name.getAsString()); - - switch (clang_decl_name.getNameKind()) { - // Normal identifiers. - case clang::DeclarationName::Identifier: - //printf ("ClangExternalASTSourceCallbacks::FindExternalVisibleDeclsByName(decl_ctx = %p, decl_name = { kind = \"Identifier\", name = \"%s\")\n", decl_ctx, decl_name.c_str()); - if (clang_decl_name.getAsIdentifierInfo()->getBuiltinID() != 0) - { - SetNoExternalVisibleDeclsForName(decl_ctx, clang_decl_name); - return false; - } - break; - - case clang::DeclarationName::ObjCZeroArgSelector: - //printf ("ClangExternalASTSourceCallbacks::FindExternalVisibleDeclsByName(decl_ctx = %p, decl_name = { kind = \"ObjCZeroArgSelector\", name = \"%s\")\n", decl_ctx, decl_name.c_str()); - SetNoExternalVisibleDeclsForName(decl_ctx, clang_decl_name); - return false; - - case clang::DeclarationName::ObjCOneArgSelector: - //printf ("ClangExternalASTSourceCallbacks::FindExternalVisibleDeclsByName(decl_ctx = %p, decl_name = { kind = \"ObjCOneArgSelector\", name = \"%s\")\n", decl_ctx, decl_name.c_str()); - SetNoExternalVisibleDeclsForName(decl_ctx, clang_decl_name); - return false; - - case clang::DeclarationName::ObjCMultiArgSelector: - //printf ("ClangExternalASTSourceCallbacks::FindExternalVisibleDeclsByName(decl_ctx = %p, decl_name = { kind = \"ObjCMultiArgSelector\", name = \"%s\")\n", decl_ctx, decl_name.c_str()); - SetNoExternalVisibleDeclsForName(decl_ctx, clang_decl_name); - return false; - - case clang::DeclarationName::CXXConstructorName: - //printf ("ClangExternalASTSourceCallbacks::FindExternalVisibleDeclsByName(decl_ctx = %p, decl_name = { kind = \"CXXConstructorName\", name = \"%s\")\n", decl_ctx, decl_name.c_str()); - SetNoExternalVisibleDeclsForName(decl_ctx, clang_decl_name); - return false; - - - case clang::DeclarationName::CXXDestructorName: - //printf ("ClangExternalASTSourceCallbacks::FindExternalVisibleDeclsByName(decl_ctx = %p, decl_name = { kind = \"CXXDestructorName\", name = \"%s\")\n", decl_ctx, decl_name.c_str()); - SetNoExternalVisibleDeclsForName(decl_ctx, clang_decl_name); - return false; - - case clang::DeclarationName::CXXConversionFunctionName: - //printf ("ClangExternalASTSourceCallbacks::FindExternalVisibleDeclsByName(decl_ctx = %p, decl_name = { kind = \"CXXConversionFunctionName\", name = \"%s\")\n", decl_ctx, decl_name.c_str()); - SetNoExternalVisibleDeclsForName(decl_ctx, clang_decl_name); - return false; - - case clang::DeclarationName::CXXOperatorName: - //printf ("ClangExternalASTSourceCallbacks::FindExternalVisibleDeclsByName(decl_ctx = %p, decl_name = { kind = \"CXXOperatorName\", name = \"%s\")\n", decl_ctx, decl_name.c_str()); - SetNoExternalVisibleDeclsForName(decl_ctx, clang_decl_name); - return false; - - case clang::DeclarationName::CXXLiteralOperatorName: - //printf ("ClangExternalASTSourceCallbacks::FindExternalVisibleDeclsByName(decl_ctx = %p, decl_name = { kind = \"CXXLiteralOperatorName\", name = \"%s\")\n", decl_ctx, decl_name.c_str()); - SetNoExternalVisibleDeclsForName(decl_ctx, clang_decl_name); - return false; - - case clang::DeclarationName::CXXUsingDirective: - //printf ("ClangExternalASTSourceCallbacks::FindExternalVisibleDeclsByName(decl_ctx = %p, decl_name = { kind = \"CXXUsingDirective\", name = \"%s\")\n", decl_ctx, decl_name.c_str()); - SetNoExternalVisibleDeclsForName(decl_ctx, clang_decl_name); - return false; + clang::DeclarationName clang_decl_name) { + if (m_callback_find_by_name) { + llvm::SmallVector<clang::NamedDecl *, 3> results; + + m_callback_find_by_name(m_callback_baton, decl_ctx, clang_decl_name, + &results); + + SetExternalVisibleDeclsForName(decl_ctx, clang_decl_name, results); + + return (results.size() != 0); + } + + std::string decl_name(clang_decl_name.getAsString()); + + switch (clang_decl_name.getNameKind()) { + // Normal identifiers. + case clang::DeclarationName::Identifier: + // printf + // ("ClangExternalASTSourceCallbacks::FindExternalVisibleDeclsByName(decl_ctx + // = %p, decl_name = { kind = \"Identifier\", name = \"%s\")\n", decl_ctx, + // decl_name.c_str()); + if (clang_decl_name.getAsIdentifierInfo()->getBuiltinID() != 0) { + SetNoExternalVisibleDeclsForName(decl_ctx, clang_decl_name); + return false; } + break; + + case clang::DeclarationName::ObjCZeroArgSelector: + // printf + // ("ClangExternalASTSourceCallbacks::FindExternalVisibleDeclsByName(decl_ctx + // = %p, decl_name = { kind = \"ObjCZeroArgSelector\", name = \"%s\")\n", + // decl_ctx, decl_name.c_str()); + SetNoExternalVisibleDeclsForName(decl_ctx, clang_decl_name); + return false; + + case clang::DeclarationName::ObjCOneArgSelector: + // printf + // ("ClangExternalASTSourceCallbacks::FindExternalVisibleDeclsByName(decl_ctx + // = %p, decl_name = { kind = \"ObjCOneArgSelector\", name = \"%s\")\n", + // decl_ctx, decl_name.c_str()); + SetNoExternalVisibleDeclsForName(decl_ctx, clang_decl_name); + return false; + + case clang::DeclarationName::ObjCMultiArgSelector: + // printf + // ("ClangExternalASTSourceCallbacks::FindExternalVisibleDeclsByName(decl_ctx + // = %p, decl_name = { kind = \"ObjCMultiArgSelector\", name = \"%s\")\n", + // decl_ctx, decl_name.c_str()); + SetNoExternalVisibleDeclsForName(decl_ctx, clang_decl_name); + return false; + + case clang::DeclarationName::CXXConstructorName: + // printf + // ("ClangExternalASTSourceCallbacks::FindExternalVisibleDeclsByName(decl_ctx + // = %p, decl_name = { kind = \"CXXConstructorName\", name = \"%s\")\n", + // decl_ctx, decl_name.c_str()); + SetNoExternalVisibleDeclsForName(decl_ctx, clang_decl_name); + return false; + + case clang::DeclarationName::CXXDestructorName: + // printf + // ("ClangExternalASTSourceCallbacks::FindExternalVisibleDeclsByName(decl_ctx + // = %p, decl_name = { kind = \"CXXDestructorName\", name = \"%s\")\n", + // decl_ctx, decl_name.c_str()); + SetNoExternalVisibleDeclsForName(decl_ctx, clang_decl_name); + return false; + + case clang::DeclarationName::CXXConversionFunctionName: + // printf + // ("ClangExternalASTSourceCallbacks::FindExternalVisibleDeclsByName(decl_ctx + // = %p, decl_name = { kind = \"CXXConversionFunctionName\", name = + // \"%s\")\n", decl_ctx, decl_name.c_str()); + SetNoExternalVisibleDeclsForName(decl_ctx, clang_decl_name); + return false; + case clang::DeclarationName::CXXOperatorName: + // printf + // ("ClangExternalASTSourceCallbacks::FindExternalVisibleDeclsByName(decl_ctx + // = %p, decl_name = { kind = \"CXXOperatorName\", name = \"%s\")\n", + // decl_ctx, decl_name.c_str()); SetNoExternalVisibleDeclsForName(decl_ctx, clang_decl_name); return false; + + case clang::DeclarationName::CXXLiteralOperatorName: + // printf + // ("ClangExternalASTSourceCallbacks::FindExternalVisibleDeclsByName(decl_ctx + // = %p, decl_name = { kind = \"CXXLiteralOperatorName\", name = \"%s\")\n", + // decl_ctx, decl_name.c_str()); + SetNoExternalVisibleDeclsForName(decl_ctx, clang_decl_name); + return false; + + case clang::DeclarationName::CXXUsingDirective: + // printf + // ("ClangExternalASTSourceCallbacks::FindExternalVisibleDeclsByName(decl_ctx + // = %p, decl_name = { kind = \"CXXUsingDirective\", name = \"%s\")\n", + // decl_ctx, decl_name.c_str()); + SetNoExternalVisibleDeclsForName(decl_ctx, clang_decl_name); + return false; + } + + SetNoExternalVisibleDeclsForName(decl_ctx, clang_decl_name); + return false; } -void -ClangExternalASTSourceCallbacks::CompleteType (TagDecl *tag_decl) -{ - if (m_callback_tag_decl) - m_callback_tag_decl (m_callback_baton, tag_decl); +void ClangExternalASTSourceCallbacks::CompleteType(TagDecl *tag_decl) { + if (m_callback_tag_decl) + m_callback_tag_decl(m_callback_baton, tag_decl); } -void -ClangExternalASTSourceCallbacks::CompleteType (ObjCInterfaceDecl *objc_decl) -{ - if (m_callback_objc_decl) - m_callback_objc_decl (m_callback_baton, objc_decl); +void ClangExternalASTSourceCallbacks::CompleteType( + ObjCInterfaceDecl *objc_decl) { + if (m_callback_objc_decl) + m_callback_objc_decl(m_callback_baton, objc_decl); } -bool -ClangExternalASTSourceCallbacks::layoutRecordType( +bool ClangExternalASTSourceCallbacks::layoutRecordType( const clang::RecordDecl *Record, uint64_t &Size, uint64_t &Alignment, llvm::DenseMap<const clang::FieldDecl *, uint64_t> &FieldOffsets, llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> &BaseOffsets, - llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> &VirtualBaseOffsets) -{ - if (m_callback_layout_record_type) - return m_callback_layout_record_type(m_callback_baton, - Record, - Size, - Alignment, - FieldOffsets, - BaseOffsets, - VirtualBaseOffsets); - - return false; + llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> + &VirtualBaseOffsets) { + if (m_callback_layout_record_type) + return m_callback_layout_record_type(m_callback_baton, Record, Size, + Alignment, FieldOffsets, BaseOffsets, + VirtualBaseOffsets); + + return false; } -void -ClangExternalASTSourceCallbacks::FindExternalLexicalDecls (const clang::DeclContext *decl_ctx, - llvm::function_ref<bool(clang::Decl::Kind)> IsKindWeWant, - llvm::SmallVectorImpl<clang::Decl *> &decls) -{ - if (m_callback_tag_decl && decl_ctx) - { - clang::TagDecl *tag_decl = llvm::dyn_cast<clang::TagDecl>(const_cast<clang::DeclContext *>(decl_ctx)); - if (tag_decl) - CompleteType(tag_decl); - } +void ClangExternalASTSourceCallbacks::FindExternalLexicalDecls( + const clang::DeclContext *decl_ctx, + llvm::function_ref<bool(clang::Decl::Kind)> IsKindWeWant, + llvm::SmallVectorImpl<clang::Decl *> &decls) { + if (m_callback_tag_decl && decl_ctx) { + clang::TagDecl *tag_decl = llvm::dyn_cast<clang::TagDecl>( + const_cast<clang::DeclContext *>(decl_ctx)); + if (tag_decl) + CompleteType(tag_decl); + } } - diff --git a/lldb/source/Symbol/ClangExternalASTSourceCommon.cpp b/lldb/source/Symbol/ClangExternalASTSourceCommon.cpp index 77aea1eafc4..69263fa67da 100644 --- a/lldb/source/Symbol/ClangExternalASTSourceCommon.cpp +++ b/lldb/source/Symbol/ClangExternalASTSourceCommon.cpp @@ -14,94 +14,79 @@ using namespace lldb_private; uint64_t g_TotalSizeOfMetadata = 0; -typedef llvm::DenseMap<clang::ExternalASTSource *, ClangExternalASTSourceCommon *> ASTSourceMap; +typedef llvm::DenseMap<clang::ExternalASTSource *, + ClangExternalASTSourceCommon *> + ASTSourceMap; -static ASTSourceMap &GetSourceMap() -{ - // Intentionally leaked to avoid problems with global destructors. - static ASTSourceMap *s_source_map = new ASTSourceMap; - return *s_source_map; +static ASTSourceMap &GetSourceMap() { + // Intentionally leaked to avoid problems with global destructors. + static ASTSourceMap *s_source_map = new ASTSourceMap; + return *s_source_map; } ClangExternalASTSourceCommon * -ClangExternalASTSourceCommon::Lookup(clang::ExternalASTSource *source) -{ - ASTSourceMap &source_map = GetSourceMap(); - - ASTSourceMap::iterator iter = source_map.find(source); - - if (iter != source_map.end()) - { - return iter->second; - } - else - { - return nullptr; - } +ClangExternalASTSourceCommon::Lookup(clang::ExternalASTSource *source) { + ASTSourceMap &source_map = GetSourceMap(); + + ASTSourceMap::iterator iter = source_map.find(source); + + if (iter != source_map.end()) { + return iter->second; + } else { + return nullptr; + } } -ClangExternalASTSourceCommon::ClangExternalASTSourceCommon() : clang::ExternalASTSource() -{ - g_TotalSizeOfMetadata += m_metadata.size(); - GetSourceMap()[this] = this; +ClangExternalASTSourceCommon::ClangExternalASTSourceCommon() + : clang::ExternalASTSource() { + g_TotalSizeOfMetadata += m_metadata.size(); + GetSourceMap()[this] = this; } -ClangExternalASTSourceCommon::~ClangExternalASTSourceCommon() -{ - GetSourceMap().erase(this); - g_TotalSizeOfMetadata -= m_metadata.size(); +ClangExternalASTSourceCommon::~ClangExternalASTSourceCommon() { + GetSourceMap().erase(this); + g_TotalSizeOfMetadata -= m_metadata.size(); } ClangASTMetadata * -ClangExternalASTSourceCommon::GetMetadata (const void *object) -{ - if (HasMetadata (object)) - return &m_metadata[object]; - else - return nullptr; +ClangExternalASTSourceCommon::GetMetadata(const void *object) { + if (HasMetadata(object)) + return &m_metadata[object]; + else + return nullptr; } -void -ClangExternalASTSourceCommon::SetMetadata (const void *object, ClangASTMetadata &metadata) -{ - uint64_t orig_size = m_metadata.size(); - m_metadata[object] = metadata; - uint64_t new_size = m_metadata.size(); - g_TotalSizeOfMetadata += (new_size - orig_size); +void ClangExternalASTSourceCommon::SetMetadata(const void *object, + ClangASTMetadata &metadata) { + uint64_t orig_size = m_metadata.size(); + m_metadata[object] = metadata; + uint64_t new_size = m_metadata.size(); + g_TotalSizeOfMetadata += (new_size - orig_size); } -bool -ClangExternalASTSourceCommon::HasMetadata (const void *object) -{ - return m_metadata.find(object) != m_metadata.end(); +bool ClangExternalASTSourceCommon::HasMetadata(const void *object) { + return m_metadata.find(object) != m_metadata.end(); } -void -ClangASTMetadata::Dump (Stream *s) -{ - lldb::user_id_t uid = GetUserID (); - - if (uid != LLDB_INVALID_UID) - { - s->Printf ("uid=0x%" PRIx64, uid); - } - - uint64_t isa_ptr = GetISAPtr (); - if (isa_ptr != 0) - { - s->Printf ("isa_ptr=0x%" PRIx64, isa_ptr); - } - - const char *obj_ptr_name = GetObjectPtrName(); - if (obj_ptr_name) - { - s->Printf ("obj_ptr_name=\"%s\" ", obj_ptr_name); - } - - if (m_is_dynamic_cxx) - { - s->Printf ("is_dynamic_cxx=%i ", m_is_dynamic_cxx); - } - s->EOL(); -} +void ClangASTMetadata::Dump(Stream *s) { + lldb::user_id_t uid = GetUserID(); + + if (uid != LLDB_INVALID_UID) { + s->Printf("uid=0x%" PRIx64, uid); + } + uint64_t isa_ptr = GetISAPtr(); + if (isa_ptr != 0) { + s->Printf("isa_ptr=0x%" PRIx64, isa_ptr); + } + + const char *obj_ptr_name = GetObjectPtrName(); + if (obj_ptr_name) { + s->Printf("obj_ptr_name=\"%s\" ", obj_ptr_name); + } + + if (m_is_dynamic_cxx) { + s->Printf("is_dynamic_cxx=%i ", m_is_dynamic_cxx); + } + s->EOL(); +} diff --git a/lldb/source/Symbol/ClangUtil.cpp b/lldb/source/Symbol/ClangUtil.cpp index 76d621e9ce4..7a67df48ee6 100644 --- a/lldb/source/Symbol/ClangUtil.cpp +++ b/lldb/source/Symbol/ClangUtil.cpp @@ -15,44 +15,36 @@ using namespace clang; using namespace lldb_private; -bool -ClangUtil::IsClangType(const CompilerType &ct) -{ - if (llvm::dyn_cast_or_null<ClangASTContext>(ct.GetTypeSystem()) == nullptr) - return false; +bool ClangUtil::IsClangType(const CompilerType &ct) { + if (llvm::dyn_cast_or_null<ClangASTContext>(ct.GetTypeSystem()) == nullptr) + return false; - if (!ct.GetOpaqueQualType()) - return false; + if (!ct.GetOpaqueQualType()) + return false; - return true; + return true; } -QualType -ClangUtil::GetQualType(const CompilerType &ct) -{ - // Make sure we have a clang type before making a clang::QualType - if (!IsClangType(ct)) - return QualType(); +QualType ClangUtil::GetQualType(const CompilerType &ct) { + // Make sure we have a clang type before making a clang::QualType + if (!IsClangType(ct)) + return QualType(); - return QualType::getFromOpaquePtr(ct.GetOpaqueQualType()); + return QualType::getFromOpaquePtr(ct.GetOpaqueQualType()); } -QualType -ClangUtil::GetCanonicalQualType(const CompilerType &ct) -{ - if (!IsClangType(ct)) - return QualType(); +QualType ClangUtil::GetCanonicalQualType(const CompilerType &ct) { + if (!IsClangType(ct)) + return QualType(); - return GetQualType(ct).getCanonicalType(); + return GetQualType(ct).getCanonicalType(); } -CompilerType -ClangUtil::RemoveFastQualifiers(const CompilerType &ct) -{ - if (!IsClangType(ct)) - return ct; +CompilerType ClangUtil::RemoveFastQualifiers(const CompilerType &ct) { + if (!IsClangType(ct)) + return ct; - QualType qual_type(GetQualType(ct)); - qual_type.removeLocalFastQualifiers(); - return CompilerType(ct.GetTypeSystem(), qual_type.getAsOpaquePtr()); + QualType qual_type(GetQualType(ct)); + qual_type.removeLocalFastQualifiers(); + return CompilerType(ct.GetTypeSystem(), qual_type.getAsOpaquePtr()); } diff --git a/lldb/source/Symbol/CompactUnwindInfo.cpp b/lldb/source/Symbol/CompactUnwindInfo.cpp index 105c3c242c0..e3da6f17cfa 100644 --- a/lldb/source/Symbol/CompactUnwindInfo.cpp +++ b/lldb/source/Symbol/CompactUnwindInfo.cpp @@ -7,7 +7,6 @@ // //===----------------------------------------------------------------------===// - // C Includes // C++ Includes #include <algorithm> @@ -30,125 +29,114 @@ using namespace lldb; using namespace lldb_private; - namespace lldb_private { - // Constants from <mach-o/compact_unwind_encoding.h> - - FLAGS_ANONYMOUS_ENUM() - { - UNWIND_IS_NOT_FUNCTION_START = 0x80000000, - UNWIND_HAS_LSDA = 0x40000000, - UNWIND_PERSONALITY_MASK = 0x30000000, - }; - - FLAGS_ANONYMOUS_ENUM() - { - UNWIND_X86_MODE_MASK = 0x0F000000, - UNWIND_X86_MODE_EBP_FRAME = 0x01000000, - UNWIND_X86_MODE_STACK_IMMD = 0x02000000, - UNWIND_X86_MODE_STACK_IND = 0x03000000, - UNWIND_X86_MODE_DWARF = 0x04000000, - - UNWIND_X86_EBP_FRAME_REGISTERS = 0x00007FFF, - UNWIND_X86_EBP_FRAME_OFFSET = 0x00FF0000, - - UNWIND_X86_FRAMELESS_STACK_SIZE = 0x00FF0000, - UNWIND_X86_FRAMELESS_STACK_ADJUST = 0x0000E000, - UNWIND_X86_FRAMELESS_STACK_REG_COUNT = 0x00001C00, - UNWIND_X86_FRAMELESS_STACK_REG_PERMUTATION = 0x000003FF, - - UNWIND_X86_DWARF_SECTION_OFFSET = 0x00FFFFFF, - }; - - enum - { - UNWIND_X86_REG_NONE = 0, - UNWIND_X86_REG_EBX = 1, - UNWIND_X86_REG_ECX = 2, - UNWIND_X86_REG_EDX = 3, - UNWIND_X86_REG_EDI = 4, - UNWIND_X86_REG_ESI = 5, - UNWIND_X86_REG_EBP = 6, - }; - - FLAGS_ANONYMOUS_ENUM() - { - UNWIND_X86_64_MODE_MASK = 0x0F000000, - UNWIND_X86_64_MODE_RBP_FRAME = 0x01000000, - UNWIND_X86_64_MODE_STACK_IMMD = 0x02000000, - UNWIND_X86_64_MODE_STACK_IND = 0x03000000, - UNWIND_X86_64_MODE_DWARF = 0x04000000, - - UNWIND_X86_64_RBP_FRAME_REGISTERS = 0x00007FFF, - UNWIND_X86_64_RBP_FRAME_OFFSET = 0x00FF0000, - - UNWIND_X86_64_FRAMELESS_STACK_SIZE = 0x00FF0000, - UNWIND_X86_64_FRAMELESS_STACK_ADJUST = 0x0000E000, - UNWIND_X86_64_FRAMELESS_STACK_REG_COUNT = 0x00001C00, - UNWIND_X86_64_FRAMELESS_STACK_REG_PERMUTATION = 0x000003FF, - - UNWIND_X86_64_DWARF_SECTION_OFFSET = 0x00FFFFFF, - }; - - enum - { - UNWIND_X86_64_REG_NONE = 0, - UNWIND_X86_64_REG_RBX = 1, - UNWIND_X86_64_REG_R12 = 2, - UNWIND_X86_64_REG_R13 = 3, - UNWIND_X86_64_REG_R14 = 4, - UNWIND_X86_64_REG_R15 = 5, - UNWIND_X86_64_REG_RBP = 6, - }; - - FLAGS_ANONYMOUS_ENUM() - { - UNWIND_ARM64_MODE_MASK = 0x0F000000, - UNWIND_ARM64_MODE_FRAMELESS = 0x02000000, - UNWIND_ARM64_MODE_DWARF = 0x03000000, - UNWIND_ARM64_MODE_FRAME = 0x04000000, - - UNWIND_ARM64_FRAME_X19_X20_PAIR = 0x00000001, - UNWIND_ARM64_FRAME_X21_X22_PAIR = 0x00000002, - UNWIND_ARM64_FRAME_X23_X24_PAIR = 0x00000004, - UNWIND_ARM64_FRAME_X25_X26_PAIR = 0x00000008, - UNWIND_ARM64_FRAME_X27_X28_PAIR = 0x00000010, - UNWIND_ARM64_FRAME_D8_D9_PAIR = 0x00000100, - UNWIND_ARM64_FRAME_D10_D11_PAIR = 0x00000200, - UNWIND_ARM64_FRAME_D12_D13_PAIR = 0x00000400, - UNWIND_ARM64_FRAME_D14_D15_PAIR = 0x00000800, - - UNWIND_ARM64_FRAMELESS_STACK_SIZE_MASK = 0x00FFF000, - UNWIND_ARM64_DWARF_SECTION_OFFSET = 0x00FFFFFF, - }; - - FLAGS_ANONYMOUS_ENUM() - { - UNWIND_ARM_MODE_MASK = 0x0F000000, - UNWIND_ARM_MODE_FRAME = 0x01000000, - UNWIND_ARM_MODE_FRAME_D = 0x02000000, - UNWIND_ARM_MODE_DWARF = 0x04000000, - - UNWIND_ARM_FRAME_STACK_ADJUST_MASK = 0x00C00000, - - UNWIND_ARM_FRAME_FIRST_PUSH_R4 = 0x00000001, - UNWIND_ARM_FRAME_FIRST_PUSH_R5 = 0x00000002, - UNWIND_ARM_FRAME_FIRST_PUSH_R6 = 0x00000004, - - UNWIND_ARM_FRAME_SECOND_PUSH_R8 = 0x00000008, - UNWIND_ARM_FRAME_SECOND_PUSH_R9 = 0x00000010, - UNWIND_ARM_FRAME_SECOND_PUSH_R10 = 0x00000020, - UNWIND_ARM_FRAME_SECOND_PUSH_R11 = 0x00000040, - UNWIND_ARM_FRAME_SECOND_PUSH_R12 = 0x00000080, - - UNWIND_ARM_FRAME_D_REG_COUNT_MASK = 0x00000700, - - UNWIND_ARM_DWARF_SECTION_OFFSET = 0x00FFFFFF, - }; +// Constants from <mach-o/compact_unwind_encoding.h> -} +FLAGS_ANONYMOUS_ENUM(){ + UNWIND_IS_NOT_FUNCTION_START = 0x80000000, UNWIND_HAS_LSDA = 0x40000000, + UNWIND_PERSONALITY_MASK = 0x30000000, +}; + +FLAGS_ANONYMOUS_ENUM(){ + UNWIND_X86_MODE_MASK = 0x0F000000, + UNWIND_X86_MODE_EBP_FRAME = 0x01000000, + UNWIND_X86_MODE_STACK_IMMD = 0x02000000, + UNWIND_X86_MODE_STACK_IND = 0x03000000, + UNWIND_X86_MODE_DWARF = 0x04000000, + + UNWIND_X86_EBP_FRAME_REGISTERS = 0x00007FFF, + UNWIND_X86_EBP_FRAME_OFFSET = 0x00FF0000, + + UNWIND_X86_FRAMELESS_STACK_SIZE = 0x00FF0000, + UNWIND_X86_FRAMELESS_STACK_ADJUST = 0x0000E000, + UNWIND_X86_FRAMELESS_STACK_REG_COUNT = 0x00001C00, + UNWIND_X86_FRAMELESS_STACK_REG_PERMUTATION = 0x000003FF, + + UNWIND_X86_DWARF_SECTION_OFFSET = 0x00FFFFFF, +}; + +enum { + UNWIND_X86_REG_NONE = 0, + UNWIND_X86_REG_EBX = 1, + UNWIND_X86_REG_ECX = 2, + UNWIND_X86_REG_EDX = 3, + UNWIND_X86_REG_EDI = 4, + UNWIND_X86_REG_ESI = 5, + UNWIND_X86_REG_EBP = 6, +}; + +FLAGS_ANONYMOUS_ENUM(){ + UNWIND_X86_64_MODE_MASK = 0x0F000000, + UNWIND_X86_64_MODE_RBP_FRAME = 0x01000000, + UNWIND_X86_64_MODE_STACK_IMMD = 0x02000000, + UNWIND_X86_64_MODE_STACK_IND = 0x03000000, + UNWIND_X86_64_MODE_DWARF = 0x04000000, + + UNWIND_X86_64_RBP_FRAME_REGISTERS = 0x00007FFF, + UNWIND_X86_64_RBP_FRAME_OFFSET = 0x00FF0000, + + UNWIND_X86_64_FRAMELESS_STACK_SIZE = 0x00FF0000, + UNWIND_X86_64_FRAMELESS_STACK_ADJUST = 0x0000E000, + UNWIND_X86_64_FRAMELESS_STACK_REG_COUNT = 0x00001C00, + UNWIND_X86_64_FRAMELESS_STACK_REG_PERMUTATION = 0x000003FF, + + UNWIND_X86_64_DWARF_SECTION_OFFSET = 0x00FFFFFF, +}; + +enum { + UNWIND_X86_64_REG_NONE = 0, + UNWIND_X86_64_REG_RBX = 1, + UNWIND_X86_64_REG_R12 = 2, + UNWIND_X86_64_REG_R13 = 3, + UNWIND_X86_64_REG_R14 = 4, + UNWIND_X86_64_REG_R15 = 5, + UNWIND_X86_64_REG_RBP = 6, +}; + +FLAGS_ANONYMOUS_ENUM(){ + UNWIND_ARM64_MODE_MASK = 0x0F000000, + UNWIND_ARM64_MODE_FRAMELESS = 0x02000000, + UNWIND_ARM64_MODE_DWARF = 0x03000000, + UNWIND_ARM64_MODE_FRAME = 0x04000000, + + UNWIND_ARM64_FRAME_X19_X20_PAIR = 0x00000001, + UNWIND_ARM64_FRAME_X21_X22_PAIR = 0x00000002, + UNWIND_ARM64_FRAME_X23_X24_PAIR = 0x00000004, + UNWIND_ARM64_FRAME_X25_X26_PAIR = 0x00000008, + UNWIND_ARM64_FRAME_X27_X28_PAIR = 0x00000010, + UNWIND_ARM64_FRAME_D8_D9_PAIR = 0x00000100, + UNWIND_ARM64_FRAME_D10_D11_PAIR = 0x00000200, + UNWIND_ARM64_FRAME_D12_D13_PAIR = 0x00000400, + UNWIND_ARM64_FRAME_D14_D15_PAIR = 0x00000800, + + UNWIND_ARM64_FRAMELESS_STACK_SIZE_MASK = 0x00FFF000, + UNWIND_ARM64_DWARF_SECTION_OFFSET = 0x00FFFFFF, +}; + +FLAGS_ANONYMOUS_ENUM(){ + UNWIND_ARM_MODE_MASK = 0x0F000000, + UNWIND_ARM_MODE_FRAME = 0x01000000, + UNWIND_ARM_MODE_FRAME_D = 0x02000000, + UNWIND_ARM_MODE_DWARF = 0x04000000, + + UNWIND_ARM_FRAME_STACK_ADJUST_MASK = 0x00C00000, + UNWIND_ARM_FRAME_FIRST_PUSH_R4 = 0x00000001, + UNWIND_ARM_FRAME_FIRST_PUSH_R5 = 0x00000002, + UNWIND_ARM_FRAME_FIRST_PUSH_R6 = 0x00000004, + + UNWIND_ARM_FRAME_SECOND_PUSH_R8 = 0x00000008, + UNWIND_ARM_FRAME_SECOND_PUSH_R9 = 0x00000010, + UNWIND_ARM_FRAME_SECOND_PUSH_R10 = 0x00000020, + UNWIND_ARM_FRAME_SECOND_PUSH_R11 = 0x00000040, + UNWIND_ARM_FRAME_SECOND_PUSH_R12 = 0x00000080, + + UNWIND_ARM_FRAME_D_REG_COUNT_MASK = 0x00000700, + + UNWIND_ARM_DWARF_SECTION_OFFSET = 0x00FFFFFF, +}; +} #ifndef UNWIND_SECOND_LEVEL_REGULAR #define UNWIND_SECOND_LEVEL_REGULAR 2 @@ -159,1515 +147,1481 @@ namespace lldb_private { #endif #ifndef UNWIND_INFO_COMPRESSED_ENTRY_FUNC_OFFSET -#define UNWIND_INFO_COMPRESSED_ENTRY_FUNC_OFFSET(entry) (entry & 0x00FFFFFF) +#define UNWIND_INFO_COMPRESSED_ENTRY_FUNC_OFFSET(entry) (entry & 0x00FFFFFF) #endif #ifndef UNWIND_INFO_COMPRESSED_ENTRY_ENCODING_INDEX -#define UNWIND_INFO_COMPRESSED_ENTRY_ENCODING_INDEX(entry) ((entry >> 24) & 0xFF) +#define UNWIND_INFO_COMPRESSED_ENTRY_ENCODING_INDEX(entry) \ + ((entry >> 24) & 0xFF) #endif -#define EXTRACT_BITS(value, mask) \ - ( (value >> llvm::countTrailingZeros(static_cast<uint32_t>(mask), llvm::ZB_Width)) & \ - (((1 << llvm::countPopulation(static_cast<uint32_t>(mask))))-1) ) - - +#define EXTRACT_BITS(value, mask) \ + ((value >> \ + llvm::countTrailingZeros(static_cast<uint32_t>(mask), llvm::ZB_Width)) & \ + (((1 << llvm::countPopulation(static_cast<uint32_t>(mask)))) - 1)) //---------------------- // constructor //---------------------- CompactUnwindInfo::CompactUnwindInfo(ObjectFile &objfile, SectionSP §ion_sp) - : m_objfile(objfile), - m_section_sp(section_sp), - m_section_contents_if_encrypted(), - m_mutex(), - m_indexes(), - m_indexes_computed(eLazyBoolCalculate), - m_unwindinfo_data(), - m_unwindinfo_data_computed(false), - m_unwind_header() -{ -} + : m_objfile(objfile), m_section_sp(section_sp), + m_section_contents_if_encrypted(), m_mutex(), m_indexes(), + m_indexes_computed(eLazyBoolCalculate), m_unwindinfo_data(), + m_unwindinfo_data_computed(false), m_unwind_header() {} //---------------------- // destructor //---------------------- -CompactUnwindInfo::~CompactUnwindInfo() -{ -} - -bool -CompactUnwindInfo::GetUnwindPlan (Target &target, Address addr, UnwindPlan& unwind_plan) -{ - if (!IsValid (target.GetProcessSP())) - { - return false; - } - FunctionInfo function_info; - if (GetCompactUnwindInfoForFunction (target, addr, function_info)) - { - // shortcut return for functions that have no compact unwind - if (function_info.encoding == 0) - return false; - - ArchSpec arch; - if (m_objfile.GetArchitecture (arch)) - { +CompactUnwindInfo::~CompactUnwindInfo() {} - Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND)); - if (log && log->GetVerbose()) - { - StreamString strm; - addr.Dump (&strm, NULL, Address::DumpStyle::DumpStyleResolvedDescriptionNoFunctionArguments, Address::DumpStyle::DumpStyleFileAddress, arch.GetAddressByteSize()); - log->Printf ("Got compact unwind encoding 0x%x for function %s", function_info.encoding, strm.GetData()); - } - - if (function_info.valid_range_offset_start != 0 && function_info.valid_range_offset_end != 0) - { - SectionList *sl = m_objfile.GetSectionList (); - if (sl) - { - addr_t func_range_start_file_addr = - function_info.valid_range_offset_start + m_objfile.GetHeaderAddress().GetFileAddress(); - AddressRange func_range (func_range_start_file_addr, - function_info.valid_range_offset_end - function_info.valid_range_offset_start, - sl); - unwind_plan.SetPlanValidAddressRange (func_range); - } - } - - if (arch.GetTriple().getArch() == llvm::Triple::x86_64) - { - return CreateUnwindPlan_x86_64 (target, function_info, unwind_plan, addr); - } - if (arch.GetTriple().getArch() == llvm::Triple::aarch64) - { - return CreateUnwindPlan_arm64 (target, function_info, unwind_plan, addr); - } - if (arch.GetTriple().getArch() == llvm::Triple::x86) - { - return CreateUnwindPlan_i386 (target, function_info, unwind_plan, addr); - } - if (arch.GetTriple().getArch() == llvm::Triple::arm || arch.GetTriple().getArch() == llvm::Triple::thumb) - { - return CreateUnwindPlan_armv7 (target, function_info, unwind_plan, addr); - } +bool CompactUnwindInfo::GetUnwindPlan(Target &target, Address addr, + UnwindPlan &unwind_plan) { + if (!IsValid(target.GetProcessSP())) { + return false; + } + FunctionInfo function_info; + if (GetCompactUnwindInfoForFunction(target, addr, function_info)) { + // shortcut return for functions that have no compact unwind + if (function_info.encoding == 0) + return false; + + ArchSpec arch; + if (m_objfile.GetArchitecture(arch)) { + + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_UNWIND)); + if (log && log->GetVerbose()) { + StreamString strm; + addr.Dump( + &strm, NULL, + Address::DumpStyle::DumpStyleResolvedDescriptionNoFunctionArguments, + Address::DumpStyle::DumpStyleFileAddress, + arch.GetAddressByteSize()); + log->Printf("Got compact unwind encoding 0x%x for function %s", + function_info.encoding, strm.GetData()); + } + + if (function_info.valid_range_offset_start != 0 && + function_info.valid_range_offset_end != 0) { + SectionList *sl = m_objfile.GetSectionList(); + if (sl) { + addr_t func_range_start_file_addr = + function_info.valid_range_offset_start + + m_objfile.GetHeaderAddress().GetFileAddress(); + AddressRange func_range(func_range_start_file_addr, + function_info.valid_range_offset_end - + function_info.valid_range_offset_start, + sl); + unwind_plan.SetPlanValidAddressRange(func_range); } + } + + if (arch.GetTriple().getArch() == llvm::Triple::x86_64) { + return CreateUnwindPlan_x86_64(target, function_info, unwind_plan, + addr); + } + if (arch.GetTriple().getArch() == llvm::Triple::aarch64) { + return CreateUnwindPlan_arm64(target, function_info, unwind_plan, addr); + } + if (arch.GetTriple().getArch() == llvm::Triple::x86) { + return CreateUnwindPlan_i386(target, function_info, unwind_plan, addr); + } + if (arch.GetTriple().getArch() == llvm::Triple::arm || + arch.GetTriple().getArch() == llvm::Triple::thumb) { + return CreateUnwindPlan_armv7(target, function_info, unwind_plan, addr); + } } - return false; + } + return false; } -bool -CompactUnwindInfo::IsValid (const ProcessSP &process_sp) -{ - if (m_section_sp.get() == nullptr) - return false; +bool CompactUnwindInfo::IsValid(const ProcessSP &process_sp) { + if (m_section_sp.get() == nullptr) + return false; - if (m_indexes_computed == eLazyBoolYes && m_unwindinfo_data_computed) - return true; + if (m_indexes_computed == eLazyBoolYes && m_unwindinfo_data_computed) + return true; - ScanIndex (process_sp); + ScanIndex(process_sp); - return m_indexes_computed == eLazyBoolYes && m_unwindinfo_data_computed; + return m_indexes_computed == eLazyBoolYes && m_unwindinfo_data_computed; } -void -CompactUnwindInfo::ScanIndex (const ProcessSP &process_sp) -{ - std::lock_guard<std::mutex> guard(m_mutex); - if (m_indexes_computed == eLazyBoolYes && m_unwindinfo_data_computed) - return; - - // We can't read the index for some reason. - if (m_indexes_computed == eLazyBoolNo) - { +void CompactUnwindInfo::ScanIndex(const ProcessSP &process_sp) { + std::lock_guard<std::mutex> guard(m_mutex); + if (m_indexes_computed == eLazyBoolYes && m_unwindinfo_data_computed) + return; + + // We can't read the index for some reason. + if (m_indexes_computed == eLazyBoolNo) { + return; + } + + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_UNWIND)); + if (log) + m_objfile.GetModule()->LogMessage( + log, "Reading compact unwind first-level indexes"); + + if (m_unwindinfo_data_computed == false) { + if (m_section_sp->IsEncrypted()) { + // Can't get section contents of a protected/encrypted section until we + // have a live + // process and can read them out of memory. + if (process_sp.get() == nullptr) return; + m_section_contents_if_encrypted.reset( + new DataBufferHeap(m_section_sp->GetByteSize(), 0)); + Error error; + if (process_sp->ReadMemory( + m_section_sp->GetLoadBaseAddress(&process_sp->GetTarget()), + m_section_contents_if_encrypted->GetBytes(), + m_section_sp->GetByteSize(), + error) == m_section_sp->GetByteSize() && + error.Success()) { + m_unwindinfo_data.SetAddressByteSize( + process_sp->GetTarget().GetArchitecture().GetAddressByteSize()); + m_unwindinfo_data.SetByteOrder( + process_sp->GetTarget().GetArchitecture().GetByteOrder()); + m_unwindinfo_data.SetData(m_section_contents_if_encrypted, 0); + } + } else { + m_objfile.ReadSectionData(m_section_sp.get(), m_unwindinfo_data); } + if (m_unwindinfo_data.GetByteSize() != m_section_sp->GetByteSize()) + return; + m_unwindinfo_data_computed = true; + } - Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND)); - if (log) - m_objfile.GetModule()->LogMessage(log, "Reading compact unwind first-level indexes"); - - if (m_unwindinfo_data_computed == false) - { - if (m_section_sp->IsEncrypted()) - { - // Can't get section contents of a protected/encrypted section until we have a live - // process and can read them out of memory. - if (process_sp.get() == nullptr) - return; - m_section_contents_if_encrypted.reset (new DataBufferHeap (m_section_sp->GetByteSize(), 0)); - Error error; - if (process_sp->ReadMemory ( - m_section_sp->GetLoadBaseAddress (&process_sp->GetTarget()), - m_section_contents_if_encrypted->GetBytes(), - m_section_sp->GetByteSize(), error) == m_section_sp->GetByteSize() && error.Success()) - { - m_unwindinfo_data.SetAddressByteSize (process_sp->GetTarget().GetArchitecture().GetAddressByteSize()); - m_unwindinfo_data.SetByteOrder (process_sp->GetTarget().GetArchitecture().GetByteOrder()); - m_unwindinfo_data.SetData (m_section_contents_if_encrypted, 0); - } - } - else - { - m_objfile.ReadSectionData (m_section_sp.get(), m_unwindinfo_data); - } - if (m_unwindinfo_data.GetByteSize() != m_section_sp->GetByteSize()) - return; - m_unwindinfo_data_computed = true; - } + if (m_unwindinfo_data.GetByteSize() > 0) { + offset_t offset = 0; - if (m_unwindinfo_data.GetByteSize() > 0) - { - offset_t offset = 0; - - // struct unwind_info_section_header - // { - // uint32_t version; // UNWIND_SECTION_VERSION - // uint32_t commonEncodingsArraySectionOffset; - // uint32_t commonEncodingsArrayCount; - // uint32_t personalityArraySectionOffset; - // uint32_t personalityArrayCount; - // uint32_t indexSectionOffset; - // uint32_t indexCount; - - m_unwind_header.version = m_unwindinfo_data.GetU32(&offset); - m_unwind_header.common_encodings_array_offset = m_unwindinfo_data.GetU32(&offset); - m_unwind_header.common_encodings_array_count = m_unwindinfo_data.GetU32(&offset); - m_unwind_header.personality_array_offset = m_unwindinfo_data.GetU32(&offset); - m_unwind_header.personality_array_count = m_unwindinfo_data.GetU32(&offset); - uint32_t indexSectionOffset = m_unwindinfo_data.GetU32(&offset); - - uint32_t indexCount = m_unwindinfo_data.GetU32(&offset); - - if (m_unwind_header.common_encodings_array_offset > m_unwindinfo_data.GetByteSize() - || m_unwind_header.personality_array_offset > m_unwindinfo_data.GetByteSize() - || indexSectionOffset > m_unwindinfo_data.GetByteSize() - || offset > m_unwindinfo_data.GetByteSize()) - { - Host::SystemLog (Host::eSystemLogError, - "error: Invalid offset encountered in compact unwind info, skipping\n"); - // don't trust anything from this compact_unwind section if it looks - // blatantly invalid data in the header. - m_indexes_computed = eLazyBoolNo; - return; - } + // struct unwind_info_section_header + // { + // uint32_t version; // UNWIND_SECTION_VERSION + // uint32_t commonEncodingsArraySectionOffset; + // uint32_t commonEncodingsArrayCount; + // uint32_t personalityArraySectionOffset; + // uint32_t personalityArrayCount; + // uint32_t indexSectionOffset; + // uint32_t indexCount; + + m_unwind_header.version = m_unwindinfo_data.GetU32(&offset); + m_unwind_header.common_encodings_array_offset = + m_unwindinfo_data.GetU32(&offset); + m_unwind_header.common_encodings_array_count = + m_unwindinfo_data.GetU32(&offset); + m_unwind_header.personality_array_offset = + m_unwindinfo_data.GetU32(&offset); + m_unwind_header.personality_array_count = m_unwindinfo_data.GetU32(&offset); + uint32_t indexSectionOffset = m_unwindinfo_data.GetU32(&offset); + + uint32_t indexCount = m_unwindinfo_data.GetU32(&offset); + + if (m_unwind_header.common_encodings_array_offset > + m_unwindinfo_data.GetByteSize() || + m_unwind_header.personality_array_offset > + m_unwindinfo_data.GetByteSize() || + indexSectionOffset > m_unwindinfo_data.GetByteSize() || + offset > m_unwindinfo_data.GetByteSize()) { + Host::SystemLog(Host::eSystemLogError, "error: Invalid offset " + "encountered in compact unwind " + "info, skipping\n"); + // don't trust anything from this compact_unwind section if it looks + // blatantly invalid data in the header. + m_indexes_computed = eLazyBoolNo; + return; + } - // Parse the basic information from the indexes - // We wait to scan the second level page info until it's needed - - // struct unwind_info_section_header_index_entry - // { - // uint32_t functionOffset; - // uint32_t secondLevelPagesSectionOffset; - // uint32_t lsdaIndexArraySectionOffset; - // }; - - bool clear_address_zeroth_bit = false; - ArchSpec arch; - if (m_objfile.GetArchitecture (arch)) - { - if (arch.GetTriple().getArch() == llvm::Triple::arm || arch.GetTriple().getArch() == llvm::Triple::thumb) - clear_address_zeroth_bit = true; - } + // Parse the basic information from the indexes + // We wait to scan the second level page info until it's needed - offset = indexSectionOffset; - for (uint32_t idx = 0; idx < indexCount; idx++) - { - uint32_t function_offset = m_unwindinfo_data.GetU32(&offset); // functionOffset - uint32_t second_level_offset = m_unwindinfo_data.GetU32(&offset); // secondLevelPagesSectionOffset - uint32_t lsda_offset = m_unwindinfo_data.GetU32(&offset); // lsdaIndexArraySectionOffset + // struct unwind_info_section_header_index_entry + // { + // uint32_t functionOffset; + // uint32_t secondLevelPagesSectionOffset; + // uint32_t lsdaIndexArraySectionOffset; + // }; + + bool clear_address_zeroth_bit = false; + ArchSpec arch; + if (m_objfile.GetArchitecture(arch)) { + if (arch.GetTriple().getArch() == llvm::Triple::arm || + arch.GetTriple().getArch() == llvm::Triple::thumb) + clear_address_zeroth_bit = true; + } - if (second_level_offset > m_section_sp->GetByteSize() || lsda_offset > m_section_sp->GetByteSize()) - { - m_indexes_computed = eLazyBoolNo; - } + offset = indexSectionOffset; + for (uint32_t idx = 0; idx < indexCount; idx++) { + uint32_t function_offset = + m_unwindinfo_data.GetU32(&offset); // functionOffset + uint32_t second_level_offset = + m_unwindinfo_data.GetU32(&offset); // secondLevelPagesSectionOffset + uint32_t lsda_offset = + m_unwindinfo_data.GetU32(&offset); // lsdaIndexArraySectionOffset + + if (second_level_offset > m_section_sp->GetByteSize() || + lsda_offset > m_section_sp->GetByteSize()) { + m_indexes_computed = eLazyBoolNo; + } - if (clear_address_zeroth_bit) - function_offset &= ~1ull; + if (clear_address_zeroth_bit) + function_offset &= ~1ull; - UnwindIndex this_index; - this_index.function_offset = function_offset; - this_index.second_level = second_level_offset; - this_index.lsda_array_start = lsda_offset; + UnwindIndex this_index; + this_index.function_offset = function_offset; + this_index.second_level = second_level_offset; + this_index.lsda_array_start = lsda_offset; - if (m_indexes.size() > 0) - { - m_indexes[m_indexes.size() - 1].lsda_array_end = lsda_offset; - } + if (m_indexes.size() > 0) { + m_indexes[m_indexes.size() - 1].lsda_array_end = lsda_offset; + } - if (second_level_offset == 0) - { - this_index.sentinal_entry = true; - } + if (second_level_offset == 0) { + this_index.sentinal_entry = true; + } - m_indexes.push_back (this_index); - } - m_indexes_computed = eLazyBoolYes; - } - else - { - m_indexes_computed = eLazyBoolNo; + m_indexes.push_back(this_index); } + m_indexes_computed = eLazyBoolYes; + } else { + m_indexes_computed = eLazyBoolNo; + } } -uint32_t -CompactUnwindInfo::GetLSDAForFunctionOffset (uint32_t lsda_offset, uint32_t lsda_count, uint32_t function_offset) -{ - // struct unwind_info_section_header_lsda_index_entry - // { - // uint32_t functionOffset; - // uint32_t lsdaOffset; - // }; - - offset_t first_entry = lsda_offset; - uint32_t low = 0; - uint32_t high = lsda_count; - while (low < high) - { - uint32_t mid = (low + high) / 2; - offset_t offset = first_entry + (mid * 8); - uint32_t mid_func_offset = m_unwindinfo_data.GetU32(&offset); // functionOffset - uint32_t mid_lsda_offset = m_unwindinfo_data.GetU32(&offset); // lsdaOffset - if (mid_func_offset == function_offset) - { - return mid_lsda_offset; - } - if (mid_func_offset < function_offset) - { - low = mid + 1; - } - else - { - high = mid; - } +uint32_t CompactUnwindInfo::GetLSDAForFunctionOffset(uint32_t lsda_offset, + uint32_t lsda_count, + uint32_t function_offset) { + // struct unwind_info_section_header_lsda_index_entry + // { + // uint32_t functionOffset; + // uint32_t lsdaOffset; + // }; + + offset_t first_entry = lsda_offset; + uint32_t low = 0; + uint32_t high = lsda_count; + while (low < high) { + uint32_t mid = (low + high) / 2; + offset_t offset = first_entry + (mid * 8); + uint32_t mid_func_offset = + m_unwindinfo_data.GetU32(&offset); // functionOffset + uint32_t mid_lsda_offset = m_unwindinfo_data.GetU32(&offset); // lsdaOffset + if (mid_func_offset == function_offset) { + return mid_lsda_offset; } - return 0; + if (mid_func_offset < function_offset) { + low = mid + 1; + } else { + high = mid; + } + } + return 0; } -lldb::offset_t -CompactUnwindInfo::BinarySearchRegularSecondPage (uint32_t entry_page_offset, uint32_t entry_count, uint32_t function_offset, uint32_t *entry_func_start_offset, uint32_t *entry_func_end_offset) -{ - // typedef uint32_t compact_unwind_encoding_t; - // struct unwind_info_regular_second_level_entry - // { - // uint32_t functionOffset; - // compact_unwind_encoding_t encoding; - - offset_t first_entry = entry_page_offset; - - uint32_t low = 0; - uint32_t high = entry_count; - uint32_t last = high - 1; - while (low < high) - { - uint32_t mid = (low + high) / 2; - offset_t offset = first_entry + (mid * 8); - uint32_t mid_func_offset = m_unwindinfo_data.GetU32(&offset); // functionOffset - uint32_t next_func_offset = 0; - if (mid < last) - { - offset = first_entry + ((mid + 1) * 8); - next_func_offset = m_unwindinfo_data.GetU32(&offset); // functionOffset - } - if (mid_func_offset <= function_offset) - { - if (mid == last || (next_func_offset > function_offset)) - { - if (entry_func_start_offset) - *entry_func_start_offset = mid_func_offset; - if (mid != last && entry_func_end_offset) - *entry_func_end_offset = next_func_offset; - return first_entry + (mid * 8); - } - else - { - low = mid + 1; - } - } - else - { - high = mid; - } +lldb::offset_t CompactUnwindInfo::BinarySearchRegularSecondPage( + uint32_t entry_page_offset, uint32_t entry_count, uint32_t function_offset, + uint32_t *entry_func_start_offset, uint32_t *entry_func_end_offset) { + // typedef uint32_t compact_unwind_encoding_t; + // struct unwind_info_regular_second_level_entry + // { + // uint32_t functionOffset; + // compact_unwind_encoding_t encoding; + + offset_t first_entry = entry_page_offset; + + uint32_t low = 0; + uint32_t high = entry_count; + uint32_t last = high - 1; + while (low < high) { + uint32_t mid = (low + high) / 2; + offset_t offset = first_entry + (mid * 8); + uint32_t mid_func_offset = + m_unwindinfo_data.GetU32(&offset); // functionOffset + uint32_t next_func_offset = 0; + if (mid < last) { + offset = first_entry + ((mid + 1) * 8); + next_func_offset = m_unwindinfo_data.GetU32(&offset); // functionOffset } - return LLDB_INVALID_OFFSET; + if (mid_func_offset <= function_offset) { + if (mid == last || (next_func_offset > function_offset)) { + if (entry_func_start_offset) + *entry_func_start_offset = mid_func_offset; + if (mid != last && entry_func_end_offset) + *entry_func_end_offset = next_func_offset; + return first_entry + (mid * 8); + } else { + low = mid + 1; + } + } else { + high = mid; + } + } + return LLDB_INVALID_OFFSET; } -uint32_t -CompactUnwindInfo::BinarySearchCompressedSecondPage (uint32_t entry_page_offset, uint32_t entry_count, uint32_t function_offset_to_find, uint32_t function_offset_base, uint32_t *entry_func_start_offset, uint32_t *entry_func_end_offset) -{ - offset_t first_entry = entry_page_offset; - - uint32_t low = 0; - uint32_t high = entry_count; - uint32_t last = high - 1; - while (low < high) - { - uint32_t mid = (low + high) / 2; - offset_t offset = first_entry + (mid * 4); - uint32_t entry = m_unwindinfo_data.GetU32(&offset); // entry - uint32_t mid_func_offset = UNWIND_INFO_COMPRESSED_ENTRY_FUNC_OFFSET (entry); - mid_func_offset += function_offset_base; - uint32_t next_func_offset = 0; - if (mid < last) - { - offset = first_entry + ((mid + 1) * 4); - uint32_t next_entry = m_unwindinfo_data.GetU32(&offset); // entry - next_func_offset = UNWIND_INFO_COMPRESSED_ENTRY_FUNC_OFFSET (next_entry); - next_func_offset += function_offset_base; - } - if (mid_func_offset <= function_offset_to_find) - { - if (mid == last || (next_func_offset > function_offset_to_find)) - { - if (entry_func_start_offset) - *entry_func_start_offset = mid_func_offset; - if (mid != last && entry_func_end_offset) - *entry_func_end_offset = next_func_offset; - return UNWIND_INFO_COMPRESSED_ENTRY_ENCODING_INDEX (entry); - } - else - { - low = mid + 1; - } - } - else - { - high = mid; - } +uint32_t CompactUnwindInfo::BinarySearchCompressedSecondPage( + uint32_t entry_page_offset, uint32_t entry_count, + uint32_t function_offset_to_find, uint32_t function_offset_base, + uint32_t *entry_func_start_offset, uint32_t *entry_func_end_offset) { + offset_t first_entry = entry_page_offset; + + uint32_t low = 0; + uint32_t high = entry_count; + uint32_t last = high - 1; + while (low < high) { + uint32_t mid = (low + high) / 2; + offset_t offset = first_entry + (mid * 4); + uint32_t entry = m_unwindinfo_data.GetU32(&offset); // entry + uint32_t mid_func_offset = UNWIND_INFO_COMPRESSED_ENTRY_FUNC_OFFSET(entry); + mid_func_offset += function_offset_base; + uint32_t next_func_offset = 0; + if (mid < last) { + offset = first_entry + ((mid + 1) * 4); + uint32_t next_entry = m_unwindinfo_data.GetU32(&offset); // entry + next_func_offset = UNWIND_INFO_COMPRESSED_ENTRY_FUNC_OFFSET(next_entry); + next_func_offset += function_offset_base; + } + if (mid_func_offset <= function_offset_to_find) { + if (mid == last || (next_func_offset > function_offset_to_find)) { + if (entry_func_start_offset) + *entry_func_start_offset = mid_func_offset; + if (mid != last && entry_func_end_offset) + *entry_func_end_offset = next_func_offset; + return UNWIND_INFO_COMPRESSED_ENTRY_ENCODING_INDEX(entry); + } else { + low = mid + 1; + } + } else { + high = mid; } + } - return UINT32_MAX; + return UINT32_MAX; } -bool -CompactUnwindInfo::GetCompactUnwindInfoForFunction (Target &target, Address address, FunctionInfo &unwind_info) -{ - unwind_info.encoding = 0; - unwind_info.lsda_address.Clear(); - unwind_info.personality_ptr_address.Clear(); +bool CompactUnwindInfo::GetCompactUnwindInfoForFunction( + Target &target, Address address, FunctionInfo &unwind_info) { + unwind_info.encoding = 0; + unwind_info.lsda_address.Clear(); + unwind_info.personality_ptr_address.Clear(); - if (!IsValid (target.GetProcessSP())) - return false; + if (!IsValid(target.GetProcessSP())) + return false; - addr_t text_section_file_address = LLDB_INVALID_ADDRESS; - SectionList *sl = m_objfile.GetSectionList (); - if (sl) - { - SectionSP text_sect = sl->FindSectionByType (eSectionTypeCode, true); - if (text_sect.get()) - { - text_section_file_address = text_sect->GetFileAddress(); - } + addr_t text_section_file_address = LLDB_INVALID_ADDRESS; + SectionList *sl = m_objfile.GetSectionList(); + if (sl) { + SectionSP text_sect = sl->FindSectionByType(eSectionTypeCode, true); + if (text_sect.get()) { + text_section_file_address = text_sect->GetFileAddress(); } - if (text_section_file_address == LLDB_INVALID_ADDRESS) - return false; + } + if (text_section_file_address == LLDB_INVALID_ADDRESS) + return false; - addr_t function_offset = address.GetFileAddress() - m_objfile.GetHeaderAddress().GetFileAddress(); + addr_t function_offset = + address.GetFileAddress() - m_objfile.GetHeaderAddress().GetFileAddress(); - UnwindIndex key; - key.function_offset = function_offset; + UnwindIndex key; + key.function_offset = function_offset; - std::vector<UnwindIndex>::const_iterator it; - it = std::lower_bound (m_indexes.begin(), m_indexes.end(), key); - if (it == m_indexes.end()) - { - return false; - } + std::vector<UnwindIndex>::const_iterator it; + it = std::lower_bound(m_indexes.begin(), m_indexes.end(), key); + if (it == m_indexes.end()) { + return false; + } - if (it->function_offset != key.function_offset) - { - if (it != m_indexes.begin()) - --it; - } + if (it->function_offset != key.function_offset) { + if (it != m_indexes.begin()) + --it; + } - if (it->sentinal_entry == true) - { - return false; - } + if (it->sentinal_entry == true) { + return false; + } + + auto next_it = it + 1; + if (next_it != m_indexes.end()) { + // initialize the function offset end range to be the start of the + // next index offset. If we find an entry which is at the end of + // the index table, this will establish the range end. + unwind_info.valid_range_offset_end = next_it->function_offset; + } + + offset_t second_page_offset = it->second_level; + offset_t lsda_array_start = it->lsda_array_start; + offset_t lsda_array_count = (it->lsda_array_end - it->lsda_array_start) / 8; + + offset_t offset = second_page_offset; + uint32_t kind = m_unwindinfo_data.GetU32( + &offset); // UNWIND_SECOND_LEVEL_REGULAR or UNWIND_SECOND_LEVEL_COMPRESSED + + if (kind == UNWIND_SECOND_LEVEL_REGULAR) { + // struct unwind_info_regular_second_level_page_header + // { + // uint32_t kind; // UNWIND_SECOND_LEVEL_REGULAR + // uint16_t entryPageOffset; + // uint16_t entryCount; - auto next_it = it + 1; - if (next_it != m_indexes.end()) - { - // initialize the function offset end range to be the start of the - // next index offset. If we find an entry which is at the end of - // the index table, this will establish the range end. - unwind_info.valid_range_offset_end = next_it->function_offset; - } + // typedef uint32_t compact_unwind_encoding_t; + // struct unwind_info_regular_second_level_entry + // { + // uint32_t functionOffset; + // compact_unwind_encoding_t encoding; - offset_t second_page_offset = it->second_level; - offset_t lsda_array_start = it->lsda_array_start; - offset_t lsda_array_count = (it->lsda_array_end - it->lsda_array_start) / 8; - - offset_t offset = second_page_offset; - uint32_t kind = m_unwindinfo_data.GetU32(&offset); // UNWIND_SECOND_LEVEL_REGULAR or UNWIND_SECOND_LEVEL_COMPRESSED - - if (kind == UNWIND_SECOND_LEVEL_REGULAR) - { - // struct unwind_info_regular_second_level_page_header - // { - // uint32_t kind; // UNWIND_SECOND_LEVEL_REGULAR - // uint16_t entryPageOffset; - // uint16_t entryCount; - - // typedef uint32_t compact_unwind_encoding_t; - // struct unwind_info_regular_second_level_entry - // { - // uint32_t functionOffset; - // compact_unwind_encoding_t encoding; - - uint16_t entry_page_offset = m_unwindinfo_data.GetU16(&offset); // entryPageOffset - uint16_t entry_count = m_unwindinfo_data.GetU16(&offset); // entryCount - - offset_t entry_offset = BinarySearchRegularSecondPage (second_page_offset + entry_page_offset, entry_count, function_offset, &unwind_info.valid_range_offset_start, &unwind_info.valid_range_offset_end); - if (entry_offset == LLDB_INVALID_OFFSET) - { - return false; - } - entry_offset += 4; // skip over functionOffset - unwind_info.encoding = m_unwindinfo_data.GetU32(&entry_offset); // encoding - if (unwind_info.encoding & UNWIND_HAS_LSDA) - { - SectionList *sl = m_objfile.GetSectionList (); - if (sl) - { - uint32_t lsda_offset = GetLSDAForFunctionOffset (lsda_array_start, lsda_array_count, function_offset); - addr_t objfile_header_file_address = m_objfile.GetHeaderAddress().GetFileAddress(); - unwind_info.lsda_address.ResolveAddressUsingFileSections (objfile_header_file_address + lsda_offset, sl); - } - } - if (unwind_info.encoding & UNWIND_PERSONALITY_MASK) - { - uint32_t personality_index = EXTRACT_BITS (unwind_info.encoding, UNWIND_PERSONALITY_MASK); - - if (personality_index > 0) - { - personality_index--; - if (personality_index < m_unwind_header.personality_array_count) - { - offset_t offset = m_unwind_header.personality_array_offset; - offset += 4 * personality_index; - SectionList *sl = m_objfile.GetSectionList (); - if (sl) - { - uint32_t personality_offset = m_unwindinfo_data.GetU32(&offset); - addr_t objfile_header_file_address = m_objfile.GetHeaderAddress().GetFileAddress(); - unwind_info.personality_ptr_address.ResolveAddressUsingFileSections (objfile_header_file_address + personality_offset, sl); - } - } - } - } - return true; - } - else if (kind == UNWIND_SECOND_LEVEL_COMPRESSED) - { - // struct unwind_info_compressed_second_level_page_header - // { - // uint32_t kind; // UNWIND_SECOND_LEVEL_COMPRESSED - // uint16_t entryPageOffset; // offset from this 2nd lvl page idx to array of entries - // // (an entry has a function offset and index into the encodings) - // // NB function offset from the entry in the compressed page - // // must be added to the index's functionOffset value. - // uint16_t entryCount; - // uint16_t encodingsPageOffset; // offset from this 2nd lvl page idx to array of encodings - // uint16_t encodingsCount; - - uint16_t entry_page_offset = m_unwindinfo_data.GetU16(&offset); // entryPageOffset - uint16_t entry_count = m_unwindinfo_data.GetU16(&offset); // entryCount - uint16_t encodings_page_offset = m_unwindinfo_data.GetU16(&offset); // encodingsPageOffset - uint16_t encodings_count = m_unwindinfo_data.GetU16(&offset); // encodingsCount - - uint32_t encoding_index = BinarySearchCompressedSecondPage (second_page_offset + entry_page_offset, entry_count, function_offset, it->function_offset, &unwind_info.valid_range_offset_start, &unwind_info.valid_range_offset_end); - if (encoding_index == UINT32_MAX || encoding_index >= encodings_count + m_unwind_header.common_encodings_array_count) - { - return false; - } - uint32_t encoding = 0; - if (encoding_index < m_unwind_header.common_encodings_array_count) - { - offset = m_unwind_header.common_encodings_array_offset + (encoding_index * sizeof (uint32_t)); - encoding = m_unwindinfo_data.GetU32(&offset); // encoding entry from the commonEncodingsArray - } - else - { - uint32_t page_specific_entry_index = encoding_index - m_unwind_header.common_encodings_array_count; - offset = second_page_offset + encodings_page_offset + (page_specific_entry_index * sizeof (uint32_t)); - encoding = m_unwindinfo_data.GetU32(&offset); // encoding entry from the page-specific encoding array - } - if (encoding == 0) - return false; + uint16_t entry_page_offset = + m_unwindinfo_data.GetU16(&offset); // entryPageOffset + uint16_t entry_count = m_unwindinfo_data.GetU16(&offset); // entryCount - unwind_info.encoding = encoding; - if (unwind_info.encoding & UNWIND_HAS_LSDA) - { - SectionList *sl = m_objfile.GetSectionList (); - if (sl) - { - uint32_t lsda_offset = GetLSDAForFunctionOffset (lsda_array_start, lsda_array_count, function_offset); - addr_t objfile_header_file_address = m_objfile.GetHeaderAddress().GetFileAddress(); - unwind_info.lsda_address.ResolveAddressUsingFileSections (objfile_header_file_address + lsda_offset, sl); - } + offset_t entry_offset = BinarySearchRegularSecondPage( + second_page_offset + entry_page_offset, entry_count, function_offset, + &unwind_info.valid_range_offset_start, + &unwind_info.valid_range_offset_end); + if (entry_offset == LLDB_INVALID_OFFSET) { + return false; + } + entry_offset += 4; // skip over functionOffset + unwind_info.encoding = m_unwindinfo_data.GetU32(&entry_offset); // encoding + if (unwind_info.encoding & UNWIND_HAS_LSDA) { + SectionList *sl = m_objfile.GetSectionList(); + if (sl) { + uint32_t lsda_offset = GetLSDAForFunctionOffset( + lsda_array_start, lsda_array_count, function_offset); + addr_t objfile_header_file_address = + m_objfile.GetHeaderAddress().GetFileAddress(); + unwind_info.lsda_address.ResolveAddressUsingFileSections( + objfile_header_file_address + lsda_offset, sl); + } + } + if (unwind_info.encoding & UNWIND_PERSONALITY_MASK) { + uint32_t personality_index = + EXTRACT_BITS(unwind_info.encoding, UNWIND_PERSONALITY_MASK); + + if (personality_index > 0) { + personality_index--; + if (personality_index < m_unwind_header.personality_array_count) { + offset_t offset = m_unwind_header.personality_array_offset; + offset += 4 * personality_index; + SectionList *sl = m_objfile.GetSectionList(); + if (sl) { + uint32_t personality_offset = m_unwindinfo_data.GetU32(&offset); + addr_t objfile_header_file_address = + m_objfile.GetHeaderAddress().GetFileAddress(); + unwind_info.personality_ptr_address.ResolveAddressUsingFileSections( + objfile_header_file_address + personality_offset, sl); + } } - if (unwind_info.encoding & UNWIND_PERSONALITY_MASK) - { - uint32_t personality_index = EXTRACT_BITS (unwind_info.encoding, UNWIND_PERSONALITY_MASK); - - if (personality_index > 0) - { - personality_index--; - if (personality_index < m_unwind_header.personality_array_count) - { - offset_t offset = m_unwind_header.personality_array_offset; - offset += 4 * personality_index; - SectionList *sl = m_objfile.GetSectionList (); - if (sl) - { - uint32_t personality_offset = m_unwindinfo_data.GetU32(&offset); - addr_t objfile_header_file_address = m_objfile.GetHeaderAddress().GetFileAddress(); - unwind_info.personality_ptr_address.ResolveAddressUsingFileSections (objfile_header_file_address + personality_offset, sl); - } - } - } + } + } + return true; + } else if (kind == UNWIND_SECOND_LEVEL_COMPRESSED) { + // struct unwind_info_compressed_second_level_page_header + // { + // uint32_t kind; // UNWIND_SECOND_LEVEL_COMPRESSED + // uint16_t entryPageOffset; // offset from this 2nd lvl page + // idx to array of entries + // // (an entry has a function + // offset and index into the + // encodings) + // // NB function offset from the + // entry in the compressed page + // // must be added to the index's + // functionOffset value. + // uint16_t entryCount; + // uint16_t encodingsPageOffset; // offset from this 2nd lvl page + // idx to array of encodings + // uint16_t encodingsCount; + + uint16_t entry_page_offset = + m_unwindinfo_data.GetU16(&offset); // entryPageOffset + uint16_t entry_count = m_unwindinfo_data.GetU16(&offset); // entryCount + uint16_t encodings_page_offset = + m_unwindinfo_data.GetU16(&offset); // encodingsPageOffset + uint16_t encodings_count = + m_unwindinfo_data.GetU16(&offset); // encodingsCount + + uint32_t encoding_index = BinarySearchCompressedSecondPage( + second_page_offset + entry_page_offset, entry_count, function_offset, + it->function_offset, &unwind_info.valid_range_offset_start, + &unwind_info.valid_range_offset_end); + if (encoding_index == UINT32_MAX || + encoding_index >= + encodings_count + m_unwind_header.common_encodings_array_count) { + return false; + } + uint32_t encoding = 0; + if (encoding_index < m_unwind_header.common_encodings_array_count) { + offset = m_unwind_header.common_encodings_array_offset + + (encoding_index * sizeof(uint32_t)); + encoding = m_unwindinfo_data.GetU32( + &offset); // encoding entry from the commonEncodingsArray + } else { + uint32_t page_specific_entry_index = + encoding_index - m_unwind_header.common_encodings_array_count; + offset = second_page_offset + encodings_page_offset + + (page_specific_entry_index * sizeof(uint32_t)); + encoding = m_unwindinfo_data.GetU32( + &offset); // encoding entry from the page-specific encoding array + } + if (encoding == 0) + return false; + + unwind_info.encoding = encoding; + if (unwind_info.encoding & UNWIND_HAS_LSDA) { + SectionList *sl = m_objfile.GetSectionList(); + if (sl) { + uint32_t lsda_offset = GetLSDAForFunctionOffset( + lsda_array_start, lsda_array_count, function_offset); + addr_t objfile_header_file_address = + m_objfile.GetHeaderAddress().GetFileAddress(); + unwind_info.lsda_address.ResolveAddressUsingFileSections( + objfile_header_file_address + lsda_offset, sl); + } + } + if (unwind_info.encoding & UNWIND_PERSONALITY_MASK) { + uint32_t personality_index = + EXTRACT_BITS(unwind_info.encoding, UNWIND_PERSONALITY_MASK); + + if (personality_index > 0) { + personality_index--; + if (personality_index < m_unwind_header.personality_array_count) { + offset_t offset = m_unwind_header.personality_array_offset; + offset += 4 * personality_index; + SectionList *sl = m_objfile.GetSectionList(); + if (sl) { + uint32_t personality_offset = m_unwindinfo_data.GetU32(&offset); + addr_t objfile_header_file_address = + m_objfile.GetHeaderAddress().GetFileAddress(); + unwind_info.personality_ptr_address.ResolveAddressUsingFileSections( + objfile_header_file_address + personality_offset, sl); + } } - return true; + } } - return false; + return true; + } + return false; } enum x86_64_eh_regnum { - rax = 0, - rdx = 1, - rcx = 2, - rbx = 3, - rsi = 4, - rdi = 5, - rbp = 6, - rsp = 7, - r8 = 8, - r9 = 9, - r10 = 10, - r11 = 11, - r12 = 12, - r13 = 13, - r14 = 14, - r15 = 15, - rip = 16 // this is officially the Return Address register number, but close enough + rax = 0, + rdx = 1, + rcx = 2, + rbx = 3, + rsi = 4, + rdi = 5, + rbp = 6, + rsp = 7, + r8 = 8, + r9 = 9, + r10 = 10, + r11 = 11, + r12 = 12, + r13 = 13, + r14 = 14, + r15 = 15, + rip = 16 // this is officially the Return Address register number, but close + // enough }; // Convert the compact_unwind_info.h register numbering scheme // to eRegisterKindEHFrame (eh_frame) register numbering scheme. -uint32_t -translate_to_eh_frame_regnum_x86_64 (uint32_t unwind_regno) -{ - switch (unwind_regno) - { - case UNWIND_X86_64_REG_RBX: - return x86_64_eh_regnum::rbx; - case UNWIND_X86_64_REG_R12: - return x86_64_eh_regnum::r12; - case UNWIND_X86_64_REG_R13: - return x86_64_eh_regnum::r13; - case UNWIND_X86_64_REG_R14: - return x86_64_eh_regnum::r14; - case UNWIND_X86_64_REG_R15: - return x86_64_eh_regnum::r15; - case UNWIND_X86_64_REG_RBP: - return x86_64_eh_regnum::rbp; - default: - return LLDB_INVALID_REGNUM; - } +uint32_t translate_to_eh_frame_regnum_x86_64(uint32_t unwind_regno) { + switch (unwind_regno) { + case UNWIND_X86_64_REG_RBX: + return x86_64_eh_regnum::rbx; + case UNWIND_X86_64_REG_R12: + return x86_64_eh_regnum::r12; + case UNWIND_X86_64_REG_R13: + return x86_64_eh_regnum::r13; + case UNWIND_X86_64_REG_R14: + return x86_64_eh_regnum::r14; + case UNWIND_X86_64_REG_R15: + return x86_64_eh_regnum::r15; + case UNWIND_X86_64_REG_RBP: + return x86_64_eh_regnum::rbp; + default: + return LLDB_INVALID_REGNUM; + } } -bool -CompactUnwindInfo::CreateUnwindPlan_x86_64 (Target &target, FunctionInfo &function_info, UnwindPlan &unwind_plan, Address pc_or_function_start) -{ - unwind_plan.SetSourceName ("compact unwind info"); - unwind_plan.SetSourcedFromCompiler (eLazyBoolYes); - unwind_plan.SetUnwindPlanValidAtAllInstructions (eLazyBoolNo); - unwind_plan.SetRegisterKind (eRegisterKindEHFrame); - - unwind_plan.SetLSDAAddress (function_info.lsda_address); - unwind_plan.SetPersonalityFunctionPtr (function_info.personality_ptr_address); - - UnwindPlan::RowSP row (new UnwindPlan::Row); - - const int wordsize = 8; - int mode = function_info.encoding & UNWIND_X86_64_MODE_MASK; - switch (mode) - { - case UNWIND_X86_64_MODE_RBP_FRAME: - { - row->GetCFAValue().SetIsRegisterPlusOffset ( - translate_to_eh_frame_regnum_x86_64 (UNWIND_X86_64_REG_RBP), - 2 * wordsize); - row->SetOffset (0); - row->SetRegisterLocationToAtCFAPlusOffset (x86_64_eh_regnum::rbp, wordsize * -2, true); - row->SetRegisterLocationToAtCFAPlusOffset (x86_64_eh_regnum::rip, wordsize * -1, true); - row->SetRegisterLocationToIsCFAPlusOffset (x86_64_eh_regnum::rsp, 0, true); - - uint32_t saved_registers_offset = EXTRACT_BITS (function_info.encoding, UNWIND_X86_64_RBP_FRAME_OFFSET); - - uint32_t saved_registers_locations = EXTRACT_BITS (function_info.encoding, UNWIND_X86_64_RBP_FRAME_REGISTERS); - - saved_registers_offset += 2; - - for (int i = 0; i < 5; i++) - { - uint32_t regnum = saved_registers_locations & 0x7; - switch (regnum) - { - case UNWIND_X86_64_REG_NONE: - break; - case UNWIND_X86_64_REG_RBX: - case UNWIND_X86_64_REG_R12: - case UNWIND_X86_64_REG_R13: - case UNWIND_X86_64_REG_R14: - case UNWIND_X86_64_REG_R15: - row->SetRegisterLocationToAtCFAPlusOffset (translate_to_eh_frame_regnum_x86_64 (regnum), wordsize * -saved_registers_offset, true); - break; - } - saved_registers_offset--; - saved_registers_locations >>= 3; - } - unwind_plan.AppendRow (row); - return true; - } +bool CompactUnwindInfo::CreateUnwindPlan_x86_64(Target &target, + FunctionInfo &function_info, + UnwindPlan &unwind_plan, + Address pc_or_function_start) { + unwind_plan.SetSourceName("compact unwind info"); + unwind_plan.SetSourcedFromCompiler(eLazyBoolYes); + unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolNo); + unwind_plan.SetRegisterKind(eRegisterKindEHFrame); + + unwind_plan.SetLSDAAddress(function_info.lsda_address); + unwind_plan.SetPersonalityFunctionPtr(function_info.personality_ptr_address); + + UnwindPlan::RowSP row(new UnwindPlan::Row); + + const int wordsize = 8; + int mode = function_info.encoding & UNWIND_X86_64_MODE_MASK; + switch (mode) { + case UNWIND_X86_64_MODE_RBP_FRAME: { + row->GetCFAValue().SetIsRegisterPlusOffset( + translate_to_eh_frame_regnum_x86_64(UNWIND_X86_64_REG_RBP), + 2 * wordsize); + row->SetOffset(0); + row->SetRegisterLocationToAtCFAPlusOffset(x86_64_eh_regnum::rbp, + wordsize * -2, true); + row->SetRegisterLocationToAtCFAPlusOffset(x86_64_eh_regnum::rip, + wordsize * -1, true); + row->SetRegisterLocationToIsCFAPlusOffset(x86_64_eh_regnum::rsp, 0, true); + + uint32_t saved_registers_offset = + EXTRACT_BITS(function_info.encoding, UNWIND_X86_64_RBP_FRAME_OFFSET); + + uint32_t saved_registers_locations = + EXTRACT_BITS(function_info.encoding, UNWIND_X86_64_RBP_FRAME_REGISTERS); + + saved_registers_offset += 2; + + for (int i = 0; i < 5; i++) { + uint32_t regnum = saved_registers_locations & 0x7; + switch (regnum) { + case UNWIND_X86_64_REG_NONE: + break; + case UNWIND_X86_64_REG_RBX: + case UNWIND_X86_64_REG_R12: + case UNWIND_X86_64_REG_R13: + case UNWIND_X86_64_REG_R14: + case UNWIND_X86_64_REG_R15: + row->SetRegisterLocationToAtCFAPlusOffset( + translate_to_eh_frame_regnum_x86_64(regnum), + wordsize * -saved_registers_offset, true); break; + } + saved_registers_offset--; + saved_registers_locations >>= 3; + } + unwind_plan.AppendRow(row); + return true; + } break; - case UNWIND_X86_64_MODE_STACK_IND: - { - // The clang in Xcode 6 is emitting incorrect compact unwind encodings for this - // style of unwind. It was fixed in llvm r217020. - // The clang in Xcode 7 has this fixed. + case UNWIND_X86_64_MODE_STACK_IND: { + // The clang in Xcode 6 is emitting incorrect compact unwind encodings for + // this + // style of unwind. It was fixed in llvm r217020. + // The clang in Xcode 7 has this fixed. + return false; + } break; + + case UNWIND_X86_64_MODE_STACK_IMMD: { + uint32_t stack_size = EXTRACT_BITS(function_info.encoding, + UNWIND_X86_64_FRAMELESS_STACK_SIZE); + uint32_t register_count = EXTRACT_BITS( + function_info.encoding, UNWIND_X86_64_FRAMELESS_STACK_REG_COUNT); + uint32_t permutation = EXTRACT_BITS( + function_info.encoding, UNWIND_X86_64_FRAMELESS_STACK_REG_PERMUTATION); + + if (mode == UNWIND_X86_64_MODE_STACK_IND && + function_info.valid_range_offset_start != 0) { + uint32_t stack_adjust = EXTRACT_BITS( + function_info.encoding, UNWIND_X86_64_FRAMELESS_STACK_ADJUST); + + // offset into the function instructions; 0 == beginning of first + // instruction + uint32_t offset_to_subl_insn = EXTRACT_BITS( + function_info.encoding, UNWIND_X86_64_FRAMELESS_STACK_SIZE); + + SectionList *sl = m_objfile.GetSectionList(); + if (sl) { + ProcessSP process_sp = target.GetProcessSP(); + if (process_sp) { + Address subl_payload_addr(function_info.valid_range_offset_start, sl); + subl_payload_addr.Slide(offset_to_subl_insn); + Error error; + uint64_t large_stack_size = process_sp->ReadUnsignedIntegerFromMemory( + subl_payload_addr.GetLoadAddress(&target), 4, 0, error); + if (large_stack_size != 0 && error.Success()) { + // Got the large stack frame size correctly - use it + stack_size = large_stack_size + (stack_adjust * wordsize); + } else { return false; + } + } else { + return false; } - break; - - case UNWIND_X86_64_MODE_STACK_IMMD: - { - uint32_t stack_size = EXTRACT_BITS (function_info.encoding, UNWIND_X86_64_FRAMELESS_STACK_SIZE); - uint32_t register_count = EXTRACT_BITS (function_info.encoding, UNWIND_X86_64_FRAMELESS_STACK_REG_COUNT); - uint32_t permutation = EXTRACT_BITS (function_info.encoding, UNWIND_X86_64_FRAMELESS_STACK_REG_PERMUTATION); - - if (mode == UNWIND_X86_64_MODE_STACK_IND && function_info.valid_range_offset_start != 0) - { - uint32_t stack_adjust = EXTRACT_BITS (function_info.encoding, UNWIND_X86_64_FRAMELESS_STACK_ADJUST); - - // offset into the function instructions; 0 == beginning of first instruction - uint32_t offset_to_subl_insn = EXTRACT_BITS (function_info.encoding, UNWIND_X86_64_FRAMELESS_STACK_SIZE); - - SectionList *sl = m_objfile.GetSectionList (); - if (sl) - { - ProcessSP process_sp = target.GetProcessSP(); - if (process_sp) - { - Address subl_payload_addr (function_info.valid_range_offset_start, sl); - subl_payload_addr.Slide (offset_to_subl_insn); - Error error; - uint64_t large_stack_size = process_sp->ReadUnsignedIntegerFromMemory (subl_payload_addr.GetLoadAddress (&target), - 4, 0, error); - if (large_stack_size != 0 && error.Success ()) - { - // Got the large stack frame size correctly - use it - stack_size = large_stack_size + (stack_adjust * wordsize); - } - else - { - return false; - } - } - else - { - return false; - } - } - else - { - return false; - } - } + } else { + return false; + } + } - int32_t offset = mode == UNWIND_X86_64_MODE_STACK_IND ? stack_size : stack_size * wordsize; - row->GetCFAValue().SetIsRegisterPlusOffset (x86_64_eh_regnum::rsp, offset); - - row->SetOffset (0); - row->SetRegisterLocationToAtCFAPlusOffset (x86_64_eh_regnum::rip, wordsize * -1, true); - row->SetRegisterLocationToIsCFAPlusOffset (x86_64_eh_regnum::rsp, 0, true); - - if (register_count > 0) - { - - // We need to include (up to) 6 registers in 10 bits. - // That would be 18 bits if we just used 3 bits per reg to indicate - // the order they're saved on the stack. - // - // This is done with Lehmer code permutation, e.g. see - // http://stackoverflow.com/questions/1506078/fast-permutation-number-permutation-mapping-algorithms - int permunreg[6] = {0, 0, 0, 0, 0, 0}; - - // This decodes the variable-base number in the 10 bits - // and gives us the Lehmer code sequence which can then - // be decoded. - - switch (register_count) - { - case 6: - permunreg[0] = permutation/120; // 120 == 5! - permutation -= (permunreg[0]*120); - permunreg[1] = permutation/24; // 24 == 4! - permutation -= (permunreg[1]*24); - permunreg[2] = permutation/6; // 6 == 3! - permutation -= (permunreg[2]*6); - permunreg[3] = permutation/2; // 2 == 2! - permutation -= (permunreg[3]*2); - permunreg[4] = permutation; // 1 == 1! - permunreg[5] = 0; - break; - case 5: - permunreg[0] = permutation/120; - permutation -= (permunreg[0]*120); - permunreg[1] = permutation/24; - permutation -= (permunreg[1]*24); - permunreg[2] = permutation/6; - permutation -= (permunreg[2]*6); - permunreg[3] = permutation/2; - permutation -= (permunreg[3]*2); - permunreg[4] = permutation; - break; - case 4: - permunreg[0] = permutation/60; - permutation -= (permunreg[0]*60); - permunreg[1] = permutation/12; - permutation -= (permunreg[1]*12); - permunreg[2] = permutation/3; - permutation -= (permunreg[2]*3); - permunreg[3] = permutation; - break; - case 3: - permunreg[0] = permutation/20; - permutation -= (permunreg[0]*20); - permunreg[1] = permutation/4; - permutation -= (permunreg[1]*4); - permunreg[2] = permutation; - break; - case 2: - permunreg[0] = permutation/5; - permutation -= (permunreg[0]*5); - permunreg[1] = permutation; - break; - case 1: - permunreg[0] = permutation; - break; - } - - // Decode the Lehmer code for this permutation of - // the registers v. http://en.wikipedia.org/wiki/Lehmer_code - - int registers[6] = { UNWIND_X86_64_REG_NONE, UNWIND_X86_64_REG_NONE, UNWIND_X86_64_REG_NONE, UNWIND_X86_64_REG_NONE, UNWIND_X86_64_REG_NONE, UNWIND_X86_64_REG_NONE }; - bool used[7] = { false, false, false, false, false, false, false }; - for (uint32_t i = 0; i < register_count; i++) - { - int renum = 0; - for (int j = 1; j < 7; j++) - { - if (used[j] == false) - { - if (renum == permunreg[i]) - { - registers[i] = j; - used[j] = true; - break; - } - renum++; - } - } - } - - uint32_t saved_registers_offset = 1; - saved_registers_offset++; - - for (int i = (sizeof (registers) / sizeof (int)) - 1; i >= 0; i--) - { - switch (registers[i]) - { - case UNWIND_X86_64_REG_NONE: - break; - case UNWIND_X86_64_REG_RBX: - case UNWIND_X86_64_REG_R12: - case UNWIND_X86_64_REG_R13: - case UNWIND_X86_64_REG_R14: - case UNWIND_X86_64_REG_R15: - case UNWIND_X86_64_REG_RBP: - row->SetRegisterLocationToAtCFAPlusOffset (translate_to_eh_frame_regnum_x86_64 (registers[i]), wordsize * -saved_registers_offset, true); - saved_registers_offset++; - break; - } - } + int32_t offset = mode == UNWIND_X86_64_MODE_STACK_IND + ? stack_size + : stack_size * wordsize; + row->GetCFAValue().SetIsRegisterPlusOffset(x86_64_eh_regnum::rsp, offset); + + row->SetOffset(0); + row->SetRegisterLocationToAtCFAPlusOffset(x86_64_eh_regnum::rip, + wordsize * -1, true); + row->SetRegisterLocationToIsCFAPlusOffset(x86_64_eh_regnum::rsp, 0, true); + + if (register_count > 0) { + + // We need to include (up to) 6 registers in 10 bits. + // That would be 18 bits if we just used 3 bits per reg to indicate + // the order they're saved on the stack. + // + // This is done with Lehmer code permutation, e.g. see + // http://stackoverflow.com/questions/1506078/fast-permutation-number-permutation-mapping-algorithms + int permunreg[6] = {0, 0, 0, 0, 0, 0}; + + // This decodes the variable-base number in the 10 bits + // and gives us the Lehmer code sequence which can then + // be decoded. + + switch (register_count) { + case 6: + permunreg[0] = permutation / 120; // 120 == 5! + permutation -= (permunreg[0] * 120); + permunreg[1] = permutation / 24; // 24 == 4! + permutation -= (permunreg[1] * 24); + permunreg[2] = permutation / 6; // 6 == 3! + permutation -= (permunreg[2] * 6); + permunreg[3] = permutation / 2; // 2 == 2! + permutation -= (permunreg[3] * 2); + permunreg[4] = permutation; // 1 == 1! + permunreg[5] = 0; + break; + case 5: + permunreg[0] = permutation / 120; + permutation -= (permunreg[0] * 120); + permunreg[1] = permutation / 24; + permutation -= (permunreg[1] * 24); + permunreg[2] = permutation / 6; + permutation -= (permunreg[2] * 6); + permunreg[3] = permutation / 2; + permutation -= (permunreg[3] * 2); + permunreg[4] = permutation; + break; + case 4: + permunreg[0] = permutation / 60; + permutation -= (permunreg[0] * 60); + permunreg[1] = permutation / 12; + permutation -= (permunreg[1] * 12); + permunreg[2] = permutation / 3; + permutation -= (permunreg[2] * 3); + permunreg[3] = permutation; + break; + case 3: + permunreg[0] = permutation / 20; + permutation -= (permunreg[0] * 20); + permunreg[1] = permutation / 4; + permutation -= (permunreg[1] * 4); + permunreg[2] = permutation; + break; + case 2: + permunreg[0] = permutation / 5; + permutation -= (permunreg[0] * 5); + permunreg[1] = permutation; + break; + case 1: + permunreg[0] = permutation; + break; + } + + // Decode the Lehmer code for this permutation of + // the registers v. http://en.wikipedia.org/wiki/Lehmer_code + + int registers[6] = {UNWIND_X86_64_REG_NONE, UNWIND_X86_64_REG_NONE, + UNWIND_X86_64_REG_NONE, UNWIND_X86_64_REG_NONE, + UNWIND_X86_64_REG_NONE, UNWIND_X86_64_REG_NONE}; + bool used[7] = {false, false, false, false, false, false, false}; + for (uint32_t i = 0; i < register_count; i++) { + int renum = 0; + for (int j = 1; j < 7; j++) { + if (used[j] == false) { + if (renum == permunreg[i]) { + registers[i] = j; + used[j] = true; + break; } - unwind_plan.AppendRow (row); - return true; + renum++; + } } - break; + } - case UNWIND_X86_64_MODE_DWARF: - { - return false; - } - break; + uint32_t saved_registers_offset = 1; + saved_registers_offset++; - case 0: - { - return false; + for (int i = (sizeof(registers) / sizeof(int)) - 1; i >= 0; i--) { + switch (registers[i]) { + case UNWIND_X86_64_REG_NONE: + break; + case UNWIND_X86_64_REG_RBX: + case UNWIND_X86_64_REG_R12: + case UNWIND_X86_64_REG_R13: + case UNWIND_X86_64_REG_R14: + case UNWIND_X86_64_REG_R15: + case UNWIND_X86_64_REG_RBP: + row->SetRegisterLocationToAtCFAPlusOffset( + translate_to_eh_frame_regnum_x86_64(registers[i]), + wordsize * -saved_registers_offset, true); + saved_registers_offset++; + break; } - break; + } } + unwind_plan.AppendRow(row); + return true; + } break; + + case UNWIND_X86_64_MODE_DWARF: { + return false; + } break; + + case 0: { return false; + } break; + } + return false; } enum i386_eh_regnum { - eax = 0, - ecx = 1, - edx = 2, - ebx = 3, - ebp = 4, - esp = 5, - esi = 6, - edi = 7, - eip = 8 // this is officially the Return Address register number, but close enough + eax = 0, + ecx = 1, + edx = 2, + ebx = 3, + ebp = 4, + esp = 5, + esi = 6, + edi = 7, + eip = 8 // this is officially the Return Address register number, but close + // enough }; // Convert the compact_unwind_info.h register numbering scheme // to eRegisterKindEHFrame (eh_frame) register numbering scheme. -uint32_t -translate_to_eh_frame_regnum_i386 (uint32_t unwind_regno) -{ - switch (unwind_regno) - { - case UNWIND_X86_REG_EBX: - return i386_eh_regnum::ebx; - case UNWIND_X86_REG_ECX: - return i386_eh_regnum::ecx; - case UNWIND_X86_REG_EDX: - return i386_eh_regnum::edx; - case UNWIND_X86_REG_EDI: - return i386_eh_regnum::edi; - case UNWIND_X86_REG_ESI: - return i386_eh_regnum::esi; - case UNWIND_X86_REG_EBP: - return i386_eh_regnum::ebp; - default: - return LLDB_INVALID_REGNUM; - } +uint32_t translate_to_eh_frame_regnum_i386(uint32_t unwind_regno) { + switch (unwind_regno) { + case UNWIND_X86_REG_EBX: + return i386_eh_regnum::ebx; + case UNWIND_X86_REG_ECX: + return i386_eh_regnum::ecx; + case UNWIND_X86_REG_EDX: + return i386_eh_regnum::edx; + case UNWIND_X86_REG_EDI: + return i386_eh_regnum::edi; + case UNWIND_X86_REG_ESI: + return i386_eh_regnum::esi; + case UNWIND_X86_REG_EBP: + return i386_eh_regnum::ebp; + default: + return LLDB_INVALID_REGNUM; + } } - -bool -CompactUnwindInfo::CreateUnwindPlan_i386 (Target &target, FunctionInfo &function_info, UnwindPlan &unwind_plan, Address pc_or_function_start) -{ - unwind_plan.SetSourceName ("compact unwind info"); - unwind_plan.SetSourcedFromCompiler (eLazyBoolYes); - unwind_plan.SetUnwindPlanValidAtAllInstructions (eLazyBoolNo); - unwind_plan.SetRegisterKind (eRegisterKindEHFrame); - - unwind_plan.SetLSDAAddress (function_info.lsda_address); - unwind_plan.SetPersonalityFunctionPtr (function_info.personality_ptr_address); - - UnwindPlan::RowSP row (new UnwindPlan::Row); - - const int wordsize = 4; - int mode = function_info.encoding & UNWIND_X86_MODE_MASK; - switch (mode) - { - case UNWIND_X86_MODE_EBP_FRAME: - { - row->GetCFAValue().SetIsRegisterPlusOffset ( - translate_to_eh_frame_regnum_i386 (UNWIND_X86_REG_EBP), 2 * wordsize); - row->SetOffset (0); - row->SetRegisterLocationToAtCFAPlusOffset (i386_eh_regnum::ebp, wordsize * -2, true); - row->SetRegisterLocationToAtCFAPlusOffset (i386_eh_regnum::eip, wordsize * -1, true); - row->SetRegisterLocationToIsCFAPlusOffset (i386_eh_regnum::esp, 0, true); - - uint32_t saved_registers_offset = EXTRACT_BITS (function_info.encoding, UNWIND_X86_EBP_FRAME_OFFSET); - - uint32_t saved_registers_locations = EXTRACT_BITS (function_info.encoding, UNWIND_X86_EBP_FRAME_REGISTERS); - - saved_registers_offset += 2; - - for (int i = 0; i < 5; i++) - { - uint32_t regnum = saved_registers_locations & 0x7; - switch (regnum) - { - case UNWIND_X86_REG_NONE: - break; - case UNWIND_X86_REG_EBX: - case UNWIND_X86_REG_ECX: - case UNWIND_X86_REG_EDX: - case UNWIND_X86_REG_EDI: - case UNWIND_X86_REG_ESI: - row->SetRegisterLocationToAtCFAPlusOffset (translate_to_eh_frame_regnum_i386 (regnum), wordsize * -saved_registers_offset, true); - break; - } - saved_registers_offset--; - saved_registers_locations >>= 3; - } - unwind_plan.AppendRow (row); - return true; - } +bool CompactUnwindInfo::CreateUnwindPlan_i386(Target &target, + FunctionInfo &function_info, + UnwindPlan &unwind_plan, + Address pc_or_function_start) { + unwind_plan.SetSourceName("compact unwind info"); + unwind_plan.SetSourcedFromCompiler(eLazyBoolYes); + unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolNo); + unwind_plan.SetRegisterKind(eRegisterKindEHFrame); + + unwind_plan.SetLSDAAddress(function_info.lsda_address); + unwind_plan.SetPersonalityFunctionPtr(function_info.personality_ptr_address); + + UnwindPlan::RowSP row(new UnwindPlan::Row); + + const int wordsize = 4; + int mode = function_info.encoding & UNWIND_X86_MODE_MASK; + switch (mode) { + case UNWIND_X86_MODE_EBP_FRAME: { + row->GetCFAValue().SetIsRegisterPlusOffset( + translate_to_eh_frame_regnum_i386(UNWIND_X86_REG_EBP), 2 * wordsize); + row->SetOffset(0); + row->SetRegisterLocationToAtCFAPlusOffset(i386_eh_regnum::ebp, + wordsize * -2, true); + row->SetRegisterLocationToAtCFAPlusOffset(i386_eh_regnum::eip, + wordsize * -1, true); + row->SetRegisterLocationToIsCFAPlusOffset(i386_eh_regnum::esp, 0, true); + + uint32_t saved_registers_offset = + EXTRACT_BITS(function_info.encoding, UNWIND_X86_EBP_FRAME_OFFSET); + + uint32_t saved_registers_locations = + EXTRACT_BITS(function_info.encoding, UNWIND_X86_EBP_FRAME_REGISTERS); + + saved_registers_offset += 2; + + for (int i = 0; i < 5; i++) { + uint32_t regnum = saved_registers_locations & 0x7; + switch (regnum) { + case UNWIND_X86_REG_NONE: break; + case UNWIND_X86_REG_EBX: + case UNWIND_X86_REG_ECX: + case UNWIND_X86_REG_EDX: + case UNWIND_X86_REG_EDI: + case UNWIND_X86_REG_ESI: + row->SetRegisterLocationToAtCFAPlusOffset( + translate_to_eh_frame_regnum_i386(regnum), + wordsize * -saved_registers_offset, true); + break; + } + saved_registers_offset--; + saved_registers_locations >>= 3; + } + unwind_plan.AppendRow(row); + return true; + } break; + + case UNWIND_X86_MODE_STACK_IND: + case UNWIND_X86_MODE_STACK_IMMD: { + uint32_t stack_size = + EXTRACT_BITS(function_info.encoding, UNWIND_X86_FRAMELESS_STACK_SIZE); + uint32_t register_count = EXTRACT_BITS( + function_info.encoding, UNWIND_X86_FRAMELESS_STACK_REG_COUNT); + uint32_t permutation = EXTRACT_BITS( + function_info.encoding, UNWIND_X86_FRAMELESS_STACK_REG_PERMUTATION); + + if (mode == UNWIND_X86_MODE_STACK_IND && + function_info.valid_range_offset_start != 0) { + uint32_t stack_adjust = EXTRACT_BITS(function_info.encoding, + UNWIND_X86_FRAMELESS_STACK_ADJUST); + + // offset into the function instructions; 0 == beginning of first + // instruction + uint32_t offset_to_subl_insn = + EXTRACT_BITS(function_info.encoding, UNWIND_X86_FRAMELESS_STACK_SIZE); + + SectionList *sl = m_objfile.GetSectionList(); + if (sl) { + ProcessSP process_sp = target.GetProcessSP(); + if (process_sp) { + Address subl_payload_addr(function_info.valid_range_offset_start, sl); + subl_payload_addr.Slide(offset_to_subl_insn); + Error error; + uint64_t large_stack_size = process_sp->ReadUnsignedIntegerFromMemory( + subl_payload_addr.GetLoadAddress(&target), 4, 0, error); + if (large_stack_size != 0 && error.Success()) { + // Got the large stack frame size correctly - use it + stack_size = large_stack_size + (stack_adjust * wordsize); + } else { + return false; + } + } else { + return false; + } + } else { + return false; + } + } - case UNWIND_X86_MODE_STACK_IND: - case UNWIND_X86_MODE_STACK_IMMD: - { - uint32_t stack_size = EXTRACT_BITS (function_info.encoding, UNWIND_X86_FRAMELESS_STACK_SIZE); - uint32_t register_count = EXTRACT_BITS (function_info.encoding, UNWIND_X86_FRAMELESS_STACK_REG_COUNT); - uint32_t permutation = EXTRACT_BITS (function_info.encoding, UNWIND_X86_FRAMELESS_STACK_REG_PERMUTATION); - - if (mode == UNWIND_X86_MODE_STACK_IND && function_info.valid_range_offset_start != 0) - { - uint32_t stack_adjust = EXTRACT_BITS (function_info.encoding, UNWIND_X86_FRAMELESS_STACK_ADJUST); - - // offset into the function instructions; 0 == beginning of first instruction - uint32_t offset_to_subl_insn = EXTRACT_BITS (function_info.encoding, UNWIND_X86_FRAMELESS_STACK_SIZE); - - SectionList *sl = m_objfile.GetSectionList (); - if (sl) - { - ProcessSP process_sp = target.GetProcessSP(); - if (process_sp) - { - Address subl_payload_addr (function_info.valid_range_offset_start, sl); - subl_payload_addr.Slide (offset_to_subl_insn); - Error error; - uint64_t large_stack_size = process_sp->ReadUnsignedIntegerFromMemory (subl_payload_addr.GetLoadAddress (&target), - 4, 0, error); - if (large_stack_size != 0 && error.Success ()) - { - // Got the large stack frame size correctly - use it - stack_size = large_stack_size + (stack_adjust * wordsize); - } - else - { - return false; - } - } - else - { - return false; - } - } - else - { - return false; - } - } - - int32_t offset = mode == UNWIND_X86_MODE_STACK_IND ? stack_size : stack_size * wordsize; - row->GetCFAValue().SetIsRegisterPlusOffset (i386_eh_regnum::esp, offset); - row->SetOffset (0); - row->SetRegisterLocationToAtCFAPlusOffset (i386_eh_regnum::eip, wordsize * -1, true); - row->SetRegisterLocationToIsCFAPlusOffset (i386_eh_regnum::esp, 0, true); - - if (register_count > 0) - { - - // We need to include (up to) 6 registers in 10 bits. - // That would be 18 bits if we just used 3 bits per reg to indicate - // the order they're saved on the stack. - // - // This is done with Lehmer code permutation, e.g. see - // http://stackoverflow.com/questions/1506078/fast-permutation-number-permutation-mapping-algorithms - int permunreg[6] = {0, 0, 0, 0, 0, 0}; - - // This decodes the variable-base number in the 10 bits - // and gives us the Lehmer code sequence which can then - // be decoded. - - switch (register_count) - { - case 6: - permunreg[0] = permutation/120; // 120 == 5! - permutation -= (permunreg[0]*120); - permunreg[1] = permutation/24; // 24 == 4! - permutation -= (permunreg[1]*24); - permunreg[2] = permutation/6; // 6 == 3! - permutation -= (permunreg[2]*6); - permunreg[3] = permutation/2; // 2 == 2! - permutation -= (permunreg[3]*2); - permunreg[4] = permutation; // 1 == 1! - permunreg[5] = 0; - break; - case 5: - permunreg[0] = permutation/120; - permutation -= (permunreg[0]*120); - permunreg[1] = permutation/24; - permutation -= (permunreg[1]*24); - permunreg[2] = permutation/6; - permutation -= (permunreg[2]*6); - permunreg[3] = permutation/2; - permutation -= (permunreg[3]*2); - permunreg[4] = permutation; - break; - case 4: - permunreg[0] = permutation/60; - permutation -= (permunreg[0]*60); - permunreg[1] = permutation/12; - permutation -= (permunreg[1]*12); - permunreg[2] = permutation/3; - permutation -= (permunreg[2]*3); - permunreg[3] = permutation; - break; - case 3: - permunreg[0] = permutation/20; - permutation -= (permunreg[0]*20); - permunreg[1] = permutation/4; - permutation -= (permunreg[1]*4); - permunreg[2] = permutation; - break; - case 2: - permunreg[0] = permutation/5; - permutation -= (permunreg[0]*5); - permunreg[1] = permutation; - break; - case 1: - permunreg[0] = permutation; - break; - } - - // Decode the Lehmer code for this permutation of - // the registers v. http://en.wikipedia.org/wiki/Lehmer_code - - int registers[6] = { UNWIND_X86_REG_NONE, UNWIND_X86_REG_NONE, UNWIND_X86_REG_NONE, UNWIND_X86_REG_NONE, UNWIND_X86_REG_NONE, UNWIND_X86_REG_NONE }; - bool used[7] = { false, false, false, false, false, false, false }; - for (uint32_t i = 0; i < register_count; i++) - { - int renum = 0; - for (int j = 1; j < 7; j++) - { - if (used[j] == false) - { - if (renum == permunreg[i]) - { - registers[i] = j; - used[j] = true; - break; - } - renum++; - } - } - } - - uint32_t saved_registers_offset = 1; - saved_registers_offset++; - - for (int i = (sizeof (registers) / sizeof (int)) - 1; i >= 0; i--) - { - switch (registers[i]) - { - case UNWIND_X86_REG_NONE: - break; - case UNWIND_X86_REG_EBX: - case UNWIND_X86_REG_ECX: - case UNWIND_X86_REG_EDX: - case UNWIND_X86_REG_EDI: - case UNWIND_X86_REG_ESI: - case UNWIND_X86_REG_EBP: - row->SetRegisterLocationToAtCFAPlusOffset (translate_to_eh_frame_regnum_i386 (registers[i]), wordsize * -saved_registers_offset, true); - saved_registers_offset++; - break; - } - } + int32_t offset = + mode == UNWIND_X86_MODE_STACK_IND ? stack_size : stack_size * wordsize; + row->GetCFAValue().SetIsRegisterPlusOffset(i386_eh_regnum::esp, offset); + row->SetOffset(0); + row->SetRegisterLocationToAtCFAPlusOffset(i386_eh_regnum::eip, + wordsize * -1, true); + row->SetRegisterLocationToIsCFAPlusOffset(i386_eh_regnum::esp, 0, true); + + if (register_count > 0) { + + // We need to include (up to) 6 registers in 10 bits. + // That would be 18 bits if we just used 3 bits per reg to indicate + // the order they're saved on the stack. + // + // This is done with Lehmer code permutation, e.g. see + // http://stackoverflow.com/questions/1506078/fast-permutation-number-permutation-mapping-algorithms + int permunreg[6] = {0, 0, 0, 0, 0, 0}; + + // This decodes the variable-base number in the 10 bits + // and gives us the Lehmer code sequence which can then + // be decoded. + + switch (register_count) { + case 6: + permunreg[0] = permutation / 120; // 120 == 5! + permutation -= (permunreg[0] * 120); + permunreg[1] = permutation / 24; // 24 == 4! + permutation -= (permunreg[1] * 24); + permunreg[2] = permutation / 6; // 6 == 3! + permutation -= (permunreg[2] * 6); + permunreg[3] = permutation / 2; // 2 == 2! + permutation -= (permunreg[3] * 2); + permunreg[4] = permutation; // 1 == 1! + permunreg[5] = 0; + break; + case 5: + permunreg[0] = permutation / 120; + permutation -= (permunreg[0] * 120); + permunreg[1] = permutation / 24; + permutation -= (permunreg[1] * 24); + permunreg[2] = permutation / 6; + permutation -= (permunreg[2] * 6); + permunreg[3] = permutation / 2; + permutation -= (permunreg[3] * 2); + permunreg[4] = permutation; + break; + case 4: + permunreg[0] = permutation / 60; + permutation -= (permunreg[0] * 60); + permunreg[1] = permutation / 12; + permutation -= (permunreg[1] * 12); + permunreg[2] = permutation / 3; + permutation -= (permunreg[2] * 3); + permunreg[3] = permutation; + break; + case 3: + permunreg[0] = permutation / 20; + permutation -= (permunreg[0] * 20); + permunreg[1] = permutation / 4; + permutation -= (permunreg[1] * 4); + permunreg[2] = permutation; + break; + case 2: + permunreg[0] = permutation / 5; + permutation -= (permunreg[0] * 5); + permunreg[1] = permutation; + break; + case 1: + permunreg[0] = permutation; + break; + } + + // Decode the Lehmer code for this permutation of + // the registers v. http://en.wikipedia.org/wiki/Lehmer_code + + int registers[6] = {UNWIND_X86_REG_NONE, UNWIND_X86_REG_NONE, + UNWIND_X86_REG_NONE, UNWIND_X86_REG_NONE, + UNWIND_X86_REG_NONE, UNWIND_X86_REG_NONE}; + bool used[7] = {false, false, false, false, false, false, false}; + for (uint32_t i = 0; i < register_count; i++) { + int renum = 0; + for (int j = 1; j < 7; j++) { + if (used[j] == false) { + if (renum == permunreg[i]) { + registers[i] = j; + used[j] = true; + break; } - - unwind_plan.AppendRow (row); - return true; + renum++; + } } - break; + } - case UNWIND_X86_MODE_DWARF: - { - return false; + uint32_t saved_registers_offset = 1; + saved_registers_offset++; + + for (int i = (sizeof(registers) / sizeof(int)) - 1; i >= 0; i--) { + switch (registers[i]) { + case UNWIND_X86_REG_NONE: + break; + case UNWIND_X86_REG_EBX: + case UNWIND_X86_REG_ECX: + case UNWIND_X86_REG_EDX: + case UNWIND_X86_REG_EDI: + case UNWIND_X86_REG_ESI: + case UNWIND_X86_REG_EBP: + row->SetRegisterLocationToAtCFAPlusOffset( + translate_to_eh_frame_regnum_i386(registers[i]), + wordsize * -saved_registers_offset, true); + saved_registers_offset++; + break; } - break; + } } - return false; -} + unwind_plan.AppendRow(row); + return true; + } break; + case UNWIND_X86_MODE_DWARF: { + return false; + } break; + } + return false; +} -// DWARF register numbers from "DWARF for the ARM 64-bit Architecture (AArch64)" doc by ARM +// DWARF register numbers from "DWARF for the ARM 64-bit Architecture (AArch64)" +// doc by ARM enum arm64_eh_regnum { - x19 = 19, - x20 = 20, - x21 = 21, - x22 = 22, - x23 = 23, - x24 = 24, - x25 = 25, - x26 = 26, - x27 = 27, - x28 = 28, - - fp = 29, - ra = 30, - sp = 31, - pc = 32, - - // Compact unwind encodes d8-d15 but we don't have eh_frame / dwarf reg #'s for the 64-bit - // fp regs. Normally in DWARF it's context sensitive - so it knows it is fetching a - // 32- or 64-bit quantity from reg v8 to indicate s0 or d0 - but the unwinder is operating - // at a lower level and we'd try to fetch 128 bits if we were told that v8 were stored on - // the stack... - v8 = 72, - v9 = 73, - v10 = 74, - v11 = 75, - v12 = 76, - v13 = 77, - v14 = 78, - v15 = 79, + x19 = 19, + x20 = 20, + x21 = 21, + x22 = 22, + x23 = 23, + x24 = 24, + x25 = 25, + x26 = 26, + x27 = 27, + x28 = 28, + + fp = 29, + ra = 30, + sp = 31, + pc = 32, + + // Compact unwind encodes d8-d15 but we don't have eh_frame / dwarf reg #'s + // for the 64-bit + // fp regs. Normally in DWARF it's context sensitive - so it knows it is + // fetching a + // 32- or 64-bit quantity from reg v8 to indicate s0 or d0 - but the unwinder + // is operating + // at a lower level and we'd try to fetch 128 bits if we were told that v8 + // were stored on + // the stack... + v8 = 72, + v9 = 73, + v10 = 74, + v11 = 75, + v12 = 76, + v13 = 77, + v14 = 78, + v15 = 79, }; enum arm_eh_regnum { - arm_r0 = 0, - arm_r1 = 1, - arm_r2 = 2, - arm_r3 = 3, - arm_r4 = 4, - arm_r5 = 5, - arm_r6 = 6, - arm_r7 = 7, - arm_r8 = 8, - arm_r9 = 9, - arm_r10 = 10, - arm_r11 = 11, - arm_r12 = 12, - - arm_sp = 13, - arm_lr = 14, - arm_pc = 15, - - arm_d0 = 256, - arm_d1 = 257, - arm_d2 = 258, - arm_d3 = 259, - arm_d4 = 260, - arm_d5 = 261, - arm_d6 = 262, - arm_d7 = 263, - arm_d8 = 264, - arm_d9 = 265, - arm_d10 = 266, - arm_d11 = 267, - arm_d12 = 268, - arm_d13 = 269, - arm_d14 = 270, + arm_r0 = 0, + arm_r1 = 1, + arm_r2 = 2, + arm_r3 = 3, + arm_r4 = 4, + arm_r5 = 5, + arm_r6 = 6, + arm_r7 = 7, + arm_r8 = 8, + arm_r9 = 9, + arm_r10 = 10, + arm_r11 = 11, + arm_r12 = 12, + + arm_sp = 13, + arm_lr = 14, + arm_pc = 15, + + arm_d0 = 256, + arm_d1 = 257, + arm_d2 = 258, + arm_d3 = 259, + arm_d4 = 260, + arm_d5 = 261, + arm_d6 = 262, + arm_d7 = 263, + arm_d8 = 264, + arm_d9 = 265, + arm_d10 = 266, + arm_d11 = 267, + arm_d12 = 268, + arm_d13 = 269, + arm_d14 = 270, }; +bool CompactUnwindInfo::CreateUnwindPlan_arm64(Target &target, + FunctionInfo &function_info, + UnwindPlan &unwind_plan, + Address pc_or_function_start) { + unwind_plan.SetSourceName("compact unwind info"); + unwind_plan.SetSourcedFromCompiler(eLazyBoolYes); + unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolNo); + unwind_plan.SetRegisterKind(eRegisterKindEHFrame); + unwind_plan.SetLSDAAddress(function_info.lsda_address); + unwind_plan.SetPersonalityFunctionPtr(function_info.personality_ptr_address); -bool -CompactUnwindInfo::CreateUnwindPlan_arm64 (Target &target, FunctionInfo &function_info, UnwindPlan &unwind_plan, Address pc_or_function_start) -{ - unwind_plan.SetSourceName ("compact unwind info"); - unwind_plan.SetSourcedFromCompiler (eLazyBoolYes); - unwind_plan.SetUnwindPlanValidAtAllInstructions (eLazyBoolNo); - unwind_plan.SetRegisterKind (eRegisterKindEHFrame); - - unwind_plan.SetLSDAAddress (function_info.lsda_address); - unwind_plan.SetPersonalityFunctionPtr (function_info.personality_ptr_address); - - UnwindPlan::RowSP row (new UnwindPlan::Row); - - const int wordsize = 8; - int mode = function_info.encoding & UNWIND_ARM64_MODE_MASK; - - if (mode == UNWIND_ARM64_MODE_DWARF) - return false; - - if (mode == UNWIND_ARM64_MODE_FRAMELESS) - { - row->SetOffset (0); - - uint32_t stack_size = (EXTRACT_BITS (function_info.encoding, UNWIND_ARM64_FRAMELESS_STACK_SIZE_MASK)) * 16; - - // Our previous Call Frame Address is the stack pointer plus the stack size - row->GetCFAValue().SetIsRegisterPlusOffset (arm64_eh_regnum::sp, stack_size); - - // Our previous PC is in the LR - row->SetRegisterLocationToRegister(arm64_eh_regnum::pc, arm64_eh_regnum::ra, true); - - unwind_plan.AppendRow (row); - return true; - } - - // Should not be possible - if (mode != UNWIND_ARM64_MODE_FRAME) - return false; - - - // mode == UNWIND_ARM64_MODE_FRAME - - row->GetCFAValue().SetIsRegisterPlusOffset (arm64_eh_regnum::fp , 2 * wordsize); - row->SetOffset (0); - row->SetRegisterLocationToAtCFAPlusOffset (arm64_eh_regnum::fp, wordsize * -2, true); - row->SetRegisterLocationToAtCFAPlusOffset (arm64_eh_regnum::pc, wordsize * -1, true); - row->SetRegisterLocationToIsCFAPlusOffset (arm64_eh_regnum::sp, 0, true); + UnwindPlan::RowSP row(new UnwindPlan::Row); - int reg_pairs_saved_count = 1; + const int wordsize = 8; + int mode = function_info.encoding & UNWIND_ARM64_MODE_MASK; - uint32_t saved_register_bits = function_info.encoding & 0xfff; - - if (saved_register_bits & UNWIND_ARM64_FRAME_X19_X20_PAIR) - { - int cfa_offset = reg_pairs_saved_count * -2 * wordsize; - cfa_offset -= wordsize; - row->SetRegisterLocationToAtCFAPlusOffset (arm64_eh_regnum::x19, cfa_offset, true); - cfa_offset -= wordsize; - row->SetRegisterLocationToAtCFAPlusOffset (arm64_eh_regnum::x20, cfa_offset, true); - reg_pairs_saved_count++; - } - - if (saved_register_bits & UNWIND_ARM64_FRAME_X21_X22_PAIR) - { - int cfa_offset = reg_pairs_saved_count * -2 * wordsize; - cfa_offset -= wordsize; - row->SetRegisterLocationToAtCFAPlusOffset (arm64_eh_regnum::x21, cfa_offset, true); - cfa_offset -= wordsize; - row->SetRegisterLocationToAtCFAPlusOffset (arm64_eh_regnum::x22, cfa_offset, true); - reg_pairs_saved_count++; - } + if (mode == UNWIND_ARM64_MODE_DWARF) + return false; - if (saved_register_bits & UNWIND_ARM64_FRAME_X23_X24_PAIR) - { - int cfa_offset = reg_pairs_saved_count * -2 * wordsize; - cfa_offset -= wordsize; - row->SetRegisterLocationToAtCFAPlusOffset (arm64_eh_regnum::x23, cfa_offset, true); - cfa_offset -= wordsize; - row->SetRegisterLocationToAtCFAPlusOffset (arm64_eh_regnum::x24, cfa_offset, true); - reg_pairs_saved_count++; - } + if (mode == UNWIND_ARM64_MODE_FRAMELESS) { + row->SetOffset(0); - if (saved_register_bits & UNWIND_ARM64_FRAME_X25_X26_PAIR) - { - int cfa_offset = reg_pairs_saved_count * -2 * wordsize; - cfa_offset -= wordsize; - row->SetRegisterLocationToAtCFAPlusOffset (arm64_eh_regnum::x25, cfa_offset, true); - cfa_offset -= wordsize; - row->SetRegisterLocationToAtCFAPlusOffset (arm64_eh_regnum::x26, cfa_offset, true); - reg_pairs_saved_count++; - } + uint32_t stack_size = + (EXTRACT_BITS(function_info.encoding, + UNWIND_ARM64_FRAMELESS_STACK_SIZE_MASK)) * + 16; - if (saved_register_bits & UNWIND_ARM64_FRAME_X27_X28_PAIR) - { - int cfa_offset = reg_pairs_saved_count * -2 * wordsize; - cfa_offset -= wordsize; - row->SetRegisterLocationToAtCFAPlusOffset (arm64_eh_regnum::x27, cfa_offset, true); - cfa_offset -= wordsize; - row->SetRegisterLocationToAtCFAPlusOffset (arm64_eh_regnum::x28, cfa_offset, true); - reg_pairs_saved_count++; - } + // Our previous Call Frame Address is the stack pointer plus the stack size + row->GetCFAValue().SetIsRegisterPlusOffset(arm64_eh_regnum::sp, stack_size); - // If we use the v8-v15 regnums here, the unwinder will try to grab 128 bits off the stack; - // not sure if we have a good way to represent the 64-bitness of these saves. + // Our previous PC is in the LR + row->SetRegisterLocationToRegister(arm64_eh_regnum::pc, arm64_eh_regnum::ra, + true); - if (saved_register_bits & UNWIND_ARM64_FRAME_D8_D9_PAIR) - { - reg_pairs_saved_count++; - } - if (saved_register_bits & UNWIND_ARM64_FRAME_D10_D11_PAIR) - { - reg_pairs_saved_count++; - } - if (saved_register_bits & UNWIND_ARM64_FRAME_D12_D13_PAIR) - { - reg_pairs_saved_count++; - } - if (saved_register_bits & UNWIND_ARM64_FRAME_D14_D15_PAIR) - { - reg_pairs_saved_count++; - } - - unwind_plan.AppendRow (row); + unwind_plan.AppendRow(row); return true; -} - -bool -CompactUnwindInfo::CreateUnwindPlan_armv7 (Target &target, FunctionInfo &function_info, UnwindPlan &unwind_plan, Address pc_or_function_start) -{ - unwind_plan.SetSourceName ("compact unwind info"); - unwind_plan.SetSourcedFromCompiler (eLazyBoolYes); - unwind_plan.SetUnwindPlanValidAtAllInstructions (eLazyBoolNo); - unwind_plan.SetRegisterKind (eRegisterKindEHFrame); - - unwind_plan.SetLSDAAddress (function_info.lsda_address); - unwind_plan.SetPersonalityFunctionPtr (function_info.personality_ptr_address); - - UnwindPlan::RowSP row (new UnwindPlan::Row); + } - const int wordsize = 4; - int mode = function_info.encoding & UNWIND_ARM_MODE_MASK; - - if (mode == UNWIND_ARM_MODE_DWARF) - return false; - - uint32_t stack_adjust = (EXTRACT_BITS (function_info.encoding, UNWIND_ARM_FRAME_STACK_ADJUST_MASK)) * wordsize; - - row->GetCFAValue().SetIsRegisterPlusOffset (arm_r7 , (2 * wordsize) + stack_adjust); - row->SetOffset (0); - row->SetRegisterLocationToAtCFAPlusOffset (arm_r7, (wordsize * -2) - stack_adjust, true); - row->SetRegisterLocationToAtCFAPlusOffset (arm_pc, (wordsize * -1) - stack_adjust, true); - row->SetRegisterLocationToIsCFAPlusOffset (arm_sp, 0, true); - - int cfa_offset = -stack_adjust - (2 * wordsize); - - uint32_t saved_register_bits = function_info.encoding & 0xff; - - if (saved_register_bits & UNWIND_ARM_FRAME_FIRST_PUSH_R6) - { - cfa_offset -= wordsize; - row->SetRegisterLocationToAtCFAPlusOffset (arm_r6, cfa_offset, true); - } - - if (saved_register_bits & UNWIND_ARM_FRAME_FIRST_PUSH_R5) - { - cfa_offset -= wordsize; - row->SetRegisterLocationToAtCFAPlusOffset (arm_r5, cfa_offset, true); - } - - if (saved_register_bits & UNWIND_ARM_FRAME_FIRST_PUSH_R4) - { - cfa_offset -= wordsize; - row->SetRegisterLocationToAtCFAPlusOffset (arm_r4, cfa_offset, true); - } + // Should not be possible + if (mode != UNWIND_ARM64_MODE_FRAME) + return false; - if (saved_register_bits & UNWIND_ARM_FRAME_SECOND_PUSH_R12) - { - cfa_offset -= wordsize; - row->SetRegisterLocationToAtCFAPlusOffset (arm_r12, cfa_offset, true); - } + // mode == UNWIND_ARM64_MODE_FRAME + + row->GetCFAValue().SetIsRegisterPlusOffset(arm64_eh_regnum::fp, 2 * wordsize); + row->SetOffset(0); + row->SetRegisterLocationToAtCFAPlusOffset(arm64_eh_regnum::fp, wordsize * -2, + true); + row->SetRegisterLocationToAtCFAPlusOffset(arm64_eh_regnum::pc, wordsize * -1, + true); + row->SetRegisterLocationToIsCFAPlusOffset(arm64_eh_regnum::sp, 0, true); + + int reg_pairs_saved_count = 1; + + uint32_t saved_register_bits = function_info.encoding & 0xfff; + + if (saved_register_bits & UNWIND_ARM64_FRAME_X19_X20_PAIR) { + int cfa_offset = reg_pairs_saved_count * -2 * wordsize; + cfa_offset -= wordsize; + row->SetRegisterLocationToAtCFAPlusOffset(arm64_eh_regnum::x19, cfa_offset, + true); + cfa_offset -= wordsize; + row->SetRegisterLocationToAtCFAPlusOffset(arm64_eh_regnum::x20, cfa_offset, + true); + reg_pairs_saved_count++; + } + + if (saved_register_bits & UNWIND_ARM64_FRAME_X21_X22_PAIR) { + int cfa_offset = reg_pairs_saved_count * -2 * wordsize; + cfa_offset -= wordsize; + row->SetRegisterLocationToAtCFAPlusOffset(arm64_eh_regnum::x21, cfa_offset, + true); + cfa_offset -= wordsize; + row->SetRegisterLocationToAtCFAPlusOffset(arm64_eh_regnum::x22, cfa_offset, + true); + reg_pairs_saved_count++; + } + + if (saved_register_bits & UNWIND_ARM64_FRAME_X23_X24_PAIR) { + int cfa_offset = reg_pairs_saved_count * -2 * wordsize; + cfa_offset -= wordsize; + row->SetRegisterLocationToAtCFAPlusOffset(arm64_eh_regnum::x23, cfa_offset, + true); + cfa_offset -= wordsize; + row->SetRegisterLocationToAtCFAPlusOffset(arm64_eh_regnum::x24, cfa_offset, + true); + reg_pairs_saved_count++; + } + + if (saved_register_bits & UNWIND_ARM64_FRAME_X25_X26_PAIR) { + int cfa_offset = reg_pairs_saved_count * -2 * wordsize; + cfa_offset -= wordsize; + row->SetRegisterLocationToAtCFAPlusOffset(arm64_eh_regnum::x25, cfa_offset, + true); + cfa_offset -= wordsize; + row->SetRegisterLocationToAtCFAPlusOffset(arm64_eh_regnum::x26, cfa_offset, + true); + reg_pairs_saved_count++; + } + + if (saved_register_bits & UNWIND_ARM64_FRAME_X27_X28_PAIR) { + int cfa_offset = reg_pairs_saved_count * -2 * wordsize; + cfa_offset -= wordsize; + row->SetRegisterLocationToAtCFAPlusOffset(arm64_eh_regnum::x27, cfa_offset, + true); + cfa_offset -= wordsize; + row->SetRegisterLocationToAtCFAPlusOffset(arm64_eh_regnum::x28, cfa_offset, + true); + reg_pairs_saved_count++; + } + + // If we use the v8-v15 regnums here, the unwinder will try to grab 128 bits + // off the stack; + // not sure if we have a good way to represent the 64-bitness of these saves. + + if (saved_register_bits & UNWIND_ARM64_FRAME_D8_D9_PAIR) { + reg_pairs_saved_count++; + } + if (saved_register_bits & UNWIND_ARM64_FRAME_D10_D11_PAIR) { + reg_pairs_saved_count++; + } + if (saved_register_bits & UNWIND_ARM64_FRAME_D12_D13_PAIR) { + reg_pairs_saved_count++; + } + if (saved_register_bits & UNWIND_ARM64_FRAME_D14_D15_PAIR) { + reg_pairs_saved_count++; + } + + unwind_plan.AppendRow(row); + return true; +} - if (saved_register_bits & UNWIND_ARM_FRAME_SECOND_PUSH_R11) - { - cfa_offset -= wordsize; - row->SetRegisterLocationToAtCFAPlusOffset (arm_r11, cfa_offset, true); - } +bool CompactUnwindInfo::CreateUnwindPlan_armv7(Target &target, + FunctionInfo &function_info, + UnwindPlan &unwind_plan, + Address pc_or_function_start) { + unwind_plan.SetSourceName("compact unwind info"); + unwind_plan.SetSourcedFromCompiler(eLazyBoolYes); + unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolNo); + unwind_plan.SetRegisterKind(eRegisterKindEHFrame); - if (saved_register_bits & UNWIND_ARM_FRAME_SECOND_PUSH_R10) - { - cfa_offset -= wordsize; - row->SetRegisterLocationToAtCFAPlusOffset (arm_r10, cfa_offset, true); - } + unwind_plan.SetLSDAAddress(function_info.lsda_address); + unwind_plan.SetPersonalityFunctionPtr(function_info.personality_ptr_address); - if (saved_register_bits & UNWIND_ARM_FRAME_SECOND_PUSH_R9) - { - cfa_offset -= wordsize; - row->SetRegisterLocationToAtCFAPlusOffset (arm_r9, cfa_offset, true); - } + UnwindPlan::RowSP row(new UnwindPlan::Row); - if (saved_register_bits & UNWIND_ARM_FRAME_SECOND_PUSH_R8) - { - cfa_offset -= wordsize; - row->SetRegisterLocationToAtCFAPlusOffset (arm_r8, cfa_offset, true); - } + const int wordsize = 4; + int mode = function_info.encoding & UNWIND_ARM_MODE_MASK; + if (mode == UNWIND_ARM_MODE_DWARF) + return false; - if (mode == UNWIND_ARM_MODE_FRAME_D) - { - uint32_t d_reg_bits = EXTRACT_BITS (function_info.encoding, UNWIND_ARM_FRAME_D_REG_COUNT_MASK); - switch (d_reg_bits) - { - case 0: - // vpush {d8} - cfa_offset -= 8; - row->SetRegisterLocationToAtCFAPlusOffset (arm_d8, cfa_offset, true); - break; - case 1: - // vpush {d10} - // vpush {d8} - cfa_offset -= 8; - row->SetRegisterLocationToAtCFAPlusOffset (arm_d10, cfa_offset, true); - cfa_offset -= 8; - row->SetRegisterLocationToAtCFAPlusOffset (arm_d8, cfa_offset, true); - break; - case 2: - // vpush {d12} - // vpush {d10} - // vpush {d8} - cfa_offset -= 8; - row->SetRegisterLocationToAtCFAPlusOffset (arm_d12, cfa_offset, true); - cfa_offset -= 8; - row->SetRegisterLocationToAtCFAPlusOffset (arm_d10, cfa_offset, true); - cfa_offset -= 8; - row->SetRegisterLocationToAtCFAPlusOffset (arm_d8, cfa_offset, true); - break; - case 3: - // vpush {d14} - // vpush {d12} - // vpush {d10} - // vpush {d8} - cfa_offset -= 8; - row->SetRegisterLocationToAtCFAPlusOffset (arm_d14, cfa_offset, true); - cfa_offset -= 8; - row->SetRegisterLocationToAtCFAPlusOffset (arm_d12, cfa_offset, true); - cfa_offset -= 8; - row->SetRegisterLocationToAtCFAPlusOffset (arm_d10, cfa_offset, true); - cfa_offset -= 8; - row->SetRegisterLocationToAtCFAPlusOffset (arm_d8, cfa_offset, true); - break; - case 4: - // vpush {d14} - // vpush {d12} - // sp = (sp - 24) & (-16); - // vst {d8, d9, d10} - cfa_offset -= 8; - row->SetRegisterLocationToAtCFAPlusOffset (arm_d14, cfa_offset, true); - cfa_offset -= 8; - row->SetRegisterLocationToAtCFAPlusOffset (arm_d12, cfa_offset, true); - - // FIXME we don't have a way to represent reg saves at an specific alignment short of - // coming up with some DWARF location description. - - break; - case 5: - // vpush {d14} - // sp = (sp - 40) & (-16); - // vst {d8, d9, d10, d11} - // vst {d12} - - cfa_offset -= 8; - row->SetRegisterLocationToAtCFAPlusOffset (arm_d14, cfa_offset, true); - - // FIXME we don't have a way to represent reg saves at an specific alignment short of - // coming up with some DWARF location description. - - break; - case 6: - // sp = (sp - 56) & (-16); - // vst {d8, d9, d10, d11} - // vst {d12, d13, d14} - - // FIXME we don't have a way to represent reg saves at an specific alignment short of - // coming up with some DWARF location description. - - break; - case 7: - // sp = (sp - 64) & (-16); - // vst {d8, d9, d10, d11} - // vst {d12, d13, d14, d15} - - // FIXME we don't have a way to represent reg saves at an specific alignment short of - // coming up with some DWARF location description. - - break; - } + uint32_t stack_adjust = (EXTRACT_BITS(function_info.encoding, + UNWIND_ARM_FRAME_STACK_ADJUST_MASK)) * + wordsize; + + row->GetCFAValue().SetIsRegisterPlusOffset(arm_r7, + (2 * wordsize) + stack_adjust); + row->SetOffset(0); + row->SetRegisterLocationToAtCFAPlusOffset( + arm_r7, (wordsize * -2) - stack_adjust, true); + row->SetRegisterLocationToAtCFAPlusOffset( + arm_pc, (wordsize * -1) - stack_adjust, true); + row->SetRegisterLocationToIsCFAPlusOffset(arm_sp, 0, true); + + int cfa_offset = -stack_adjust - (2 * wordsize); + + uint32_t saved_register_bits = function_info.encoding & 0xff; + + if (saved_register_bits & UNWIND_ARM_FRAME_FIRST_PUSH_R6) { + cfa_offset -= wordsize; + row->SetRegisterLocationToAtCFAPlusOffset(arm_r6, cfa_offset, true); + } + + if (saved_register_bits & UNWIND_ARM_FRAME_FIRST_PUSH_R5) { + cfa_offset -= wordsize; + row->SetRegisterLocationToAtCFAPlusOffset(arm_r5, cfa_offset, true); + } + + if (saved_register_bits & UNWIND_ARM_FRAME_FIRST_PUSH_R4) { + cfa_offset -= wordsize; + row->SetRegisterLocationToAtCFAPlusOffset(arm_r4, cfa_offset, true); + } + + if (saved_register_bits & UNWIND_ARM_FRAME_SECOND_PUSH_R12) { + cfa_offset -= wordsize; + row->SetRegisterLocationToAtCFAPlusOffset(arm_r12, cfa_offset, true); + } + + if (saved_register_bits & UNWIND_ARM_FRAME_SECOND_PUSH_R11) { + cfa_offset -= wordsize; + row->SetRegisterLocationToAtCFAPlusOffset(arm_r11, cfa_offset, true); + } + + if (saved_register_bits & UNWIND_ARM_FRAME_SECOND_PUSH_R10) { + cfa_offset -= wordsize; + row->SetRegisterLocationToAtCFAPlusOffset(arm_r10, cfa_offset, true); + } + + if (saved_register_bits & UNWIND_ARM_FRAME_SECOND_PUSH_R9) { + cfa_offset -= wordsize; + row->SetRegisterLocationToAtCFAPlusOffset(arm_r9, cfa_offset, true); + } + + if (saved_register_bits & UNWIND_ARM_FRAME_SECOND_PUSH_R8) { + cfa_offset -= wordsize; + row->SetRegisterLocationToAtCFAPlusOffset(arm_r8, cfa_offset, true); + } + + if (mode == UNWIND_ARM_MODE_FRAME_D) { + uint32_t d_reg_bits = + EXTRACT_BITS(function_info.encoding, UNWIND_ARM_FRAME_D_REG_COUNT_MASK); + switch (d_reg_bits) { + case 0: + // vpush {d8} + cfa_offset -= 8; + row->SetRegisterLocationToAtCFAPlusOffset(arm_d8, cfa_offset, true); + break; + case 1: + // vpush {d10} + // vpush {d8} + cfa_offset -= 8; + row->SetRegisterLocationToAtCFAPlusOffset(arm_d10, cfa_offset, true); + cfa_offset -= 8; + row->SetRegisterLocationToAtCFAPlusOffset(arm_d8, cfa_offset, true); + break; + case 2: + // vpush {d12} + // vpush {d10} + // vpush {d8} + cfa_offset -= 8; + row->SetRegisterLocationToAtCFAPlusOffset(arm_d12, cfa_offset, true); + cfa_offset -= 8; + row->SetRegisterLocationToAtCFAPlusOffset(arm_d10, cfa_offset, true); + cfa_offset -= 8; + row->SetRegisterLocationToAtCFAPlusOffset(arm_d8, cfa_offset, true); + break; + case 3: + // vpush {d14} + // vpush {d12} + // vpush {d10} + // vpush {d8} + cfa_offset -= 8; + row->SetRegisterLocationToAtCFAPlusOffset(arm_d14, cfa_offset, true); + cfa_offset -= 8; + row->SetRegisterLocationToAtCFAPlusOffset(arm_d12, cfa_offset, true); + cfa_offset -= 8; + row->SetRegisterLocationToAtCFAPlusOffset(arm_d10, cfa_offset, true); + cfa_offset -= 8; + row->SetRegisterLocationToAtCFAPlusOffset(arm_d8, cfa_offset, true); + break; + case 4: + // vpush {d14} + // vpush {d12} + // sp = (sp - 24) & (-16); + // vst {d8, d9, d10} + cfa_offset -= 8; + row->SetRegisterLocationToAtCFAPlusOffset(arm_d14, cfa_offset, true); + cfa_offset -= 8; + row->SetRegisterLocationToAtCFAPlusOffset(arm_d12, cfa_offset, true); + + // FIXME we don't have a way to represent reg saves at an specific + // alignment short of + // coming up with some DWARF location description. + + break; + case 5: + // vpush {d14} + // sp = (sp - 40) & (-16); + // vst {d8, d9, d10, d11} + // vst {d12} + + cfa_offset -= 8; + row->SetRegisterLocationToAtCFAPlusOffset(arm_d14, cfa_offset, true); + + // FIXME we don't have a way to represent reg saves at an specific + // alignment short of + // coming up with some DWARF location description. + + break; + case 6: + // sp = (sp - 56) & (-16); + // vst {d8, d9, d10, d11} + // vst {d12, d13, d14} + + // FIXME we don't have a way to represent reg saves at an specific + // alignment short of + // coming up with some DWARF location description. + + break; + case 7: + // sp = (sp - 64) & (-16); + // vst {d8, d9, d10, d11} + // vst {d12, d13, d14, d15} + + // FIXME we don't have a way to represent reg saves at an specific + // alignment short of + // coming up with some DWARF location description. + + break; } + } - unwind_plan.AppendRow (row); - return true; + unwind_plan.AppendRow(row); + return true; } - - diff --git a/lldb/source/Symbol/CompileUnit.cpp b/lldb/source/Symbol/CompileUnit.cpp index 259a450b716..8ba83d43880 100644 --- a/lldb/source/Symbol/CompileUnit.cpp +++ b/lldb/source/Symbol/CompileUnit.cpp @@ -17,143 +17,104 @@ using namespace lldb; using namespace lldb_private; -CompileUnit::CompileUnit(const lldb::ModuleSP &module_sp, void *user_data, const char *pathname, - const lldb::user_id_t cu_sym_id, lldb::LanguageType language, +CompileUnit::CompileUnit(const lldb::ModuleSP &module_sp, void *user_data, + const char *pathname, const lldb::user_id_t cu_sym_id, + lldb::LanguageType language, lldb_private::LazyBool is_optimized) - : ModuleChild(module_sp), - FileSpec(pathname, false), - UserID(cu_sym_id), - m_user_data(user_data), - m_language(language), - m_flags(0), - m_functions(), - m_support_files(), - m_line_table_ap(), - m_variables(), - m_is_optimized(is_optimized) -{ - if (language != eLanguageTypeUnknown) - m_flags.Set(flagsParsedLanguage); - assert(module_sp); + : ModuleChild(module_sp), FileSpec(pathname, false), UserID(cu_sym_id), + m_user_data(user_data), m_language(language), m_flags(0), m_functions(), + m_support_files(), m_line_table_ap(), m_variables(), + m_is_optimized(is_optimized) { + if (language != eLanguageTypeUnknown) + m_flags.Set(flagsParsedLanguage); + assert(module_sp); } -CompileUnit::CompileUnit(const lldb::ModuleSP &module_sp, void *user_data, const FileSpec &fspec, - const lldb::user_id_t cu_sym_id, lldb::LanguageType language, +CompileUnit::CompileUnit(const lldb::ModuleSP &module_sp, void *user_data, + const FileSpec &fspec, const lldb::user_id_t cu_sym_id, + lldb::LanguageType language, lldb_private::LazyBool is_optimized) - : ModuleChild(module_sp), - FileSpec(fspec), - UserID(cu_sym_id), - m_user_data(user_data), - m_language(language), - m_flags(0), - m_functions(), - m_support_files(), - m_line_table_ap(), - m_variables(), - m_is_optimized(is_optimized) -{ - if (language != eLanguageTypeUnknown) - m_flags.Set(flagsParsedLanguage); - assert(module_sp); + : ModuleChild(module_sp), FileSpec(fspec), UserID(cu_sym_id), + m_user_data(user_data), m_language(language), m_flags(0), m_functions(), + m_support_files(), m_line_table_ap(), m_variables(), + m_is_optimized(is_optimized) { + if (language != eLanguageTypeUnknown) + m_flags.Set(flagsParsedLanguage); + assert(module_sp); } -CompileUnit::~CompileUnit () -{ -} +CompileUnit::~CompileUnit() {} -void -CompileUnit::CalculateSymbolContext(SymbolContext* sc) -{ - sc->comp_unit = this; - GetModule()->CalculateSymbolContext(sc); +void CompileUnit::CalculateSymbolContext(SymbolContext *sc) { + sc->comp_unit = this; + GetModule()->CalculateSymbolContext(sc); } -ModuleSP -CompileUnit::CalculateSymbolContextModule () -{ - return GetModule(); -} +ModuleSP CompileUnit::CalculateSymbolContextModule() { return GetModule(); } -CompileUnit * -CompileUnit::CalculateSymbolContextCompileUnit () -{ - return this; -} +CompileUnit *CompileUnit::CalculateSymbolContextCompileUnit() { return this; } -void -CompileUnit::DumpSymbolContext(Stream *s) -{ - GetModule()->DumpSymbolContext(s); - s->Printf(", CompileUnit{0x%8.8" PRIx64 "}", GetID()); +void CompileUnit::DumpSymbolContext(Stream *s) { + GetModule()->DumpSymbolContext(s); + s->Printf(", CompileUnit{0x%8.8" PRIx64 "}", GetID()); } - -void -CompileUnit::GetDescription(Stream *s, lldb::DescriptionLevel level) const -{ - const char* language = Language::GetNameForLanguageType(m_language); - *s << "id = " << (const UserID&)*this << ", file = \"" << (const FileSpec&)*this << "\", language = \"" << language << '"'; +void CompileUnit::GetDescription(Stream *s, + lldb::DescriptionLevel level) const { + const char *language = Language::GetNameForLanguageType(m_language); + *s << "id = " << (const UserID &)*this << ", file = \"" + << (const FileSpec &)*this << "\", language = \"" << language << '"'; } - //---------------------------------------------------------------------- // Dump the current contents of this object. No functions that cause on // demand parsing of functions, globals, statics are called, so this // is a good function to call to get an idea of the current contents of // the CompileUnit object. //---------------------------------------------------------------------- -void -CompileUnit::Dump(Stream *s, bool show_context) const -{ - const char* language = Language::GetNameForLanguageType(m_language); - - s->Printf("%p: ", static_cast<const void*>(this)); - s->Indent(); - *s << "CompileUnit" << static_cast<const UserID&>(*this) - << ", language = \"" << language - << "\", file = '" << static_cast<const FileSpec&>(*this) << "'\n"; - -// m_types.Dump(s); - - if (m_variables.get()) - { - s->IndentMore(); - m_variables->Dump(s, show_context); - s->IndentLess(); +void CompileUnit::Dump(Stream *s, bool show_context) const { + const char *language = Language::GetNameForLanguageType(m_language); + + s->Printf("%p: ", static_cast<const void *>(this)); + s->Indent(); + *s << "CompileUnit" << static_cast<const UserID &>(*this) << ", language = \"" + << language << "\", file = '" << static_cast<const FileSpec &>(*this) + << "'\n"; + + // m_types.Dump(s); + + if (m_variables.get()) { + s->IndentMore(); + m_variables->Dump(s, show_context); + s->IndentLess(); + } + + if (!m_functions.empty()) { + s->IndentMore(); + std::vector<FunctionSP>::const_iterator pos; + std::vector<FunctionSP>::const_iterator end = m_functions.end(); + for (pos = m_functions.begin(); pos != end; ++pos) { + (*pos)->Dump(s, show_context); } - if (!m_functions.empty()) - { - s->IndentMore(); - std::vector<FunctionSP>::const_iterator pos; - std::vector<FunctionSP>::const_iterator end = m_functions.end(); - for (pos = m_functions.begin(); pos != end; ++pos) - { - (*pos)->Dump(s, show_context); - } - - s->IndentLess(); - s->EOL(); - } + s->IndentLess(); + s->EOL(); + } } //---------------------------------------------------------------------- // Add a function to this compile unit //---------------------------------------------------------------------- -void -CompileUnit::AddFunction(FunctionSP& funcSP) -{ - // TODO: order these by address - m_functions.push_back(funcSP); +void CompileUnit::AddFunction(FunctionSP &funcSP) { + // TODO: order these by address + m_functions.push_back(funcSP); } -FunctionSP -CompileUnit::GetFunctionAtIndex (size_t idx) -{ - FunctionSP funcSP; - if (idx < m_functions.size()) - funcSP = m_functions[idx]; - return funcSP; +FunctionSP CompileUnit::GetFunctionAtIndex(size_t idx) { + FunctionSP funcSP; + if (idx < m_functions.size()) + funcSP = m_functions[idx]; + return funcSP; } //---------------------------------------------------------------------- @@ -180,8 +141,8 @@ CompileUnit::GetFunctionAtIndex (size_t idx) // parsed by the SymbolFile parser plug-ins and registered with each // Module). //---------------------------------------------------------------------- -//void -//CompileUnit::FindFunctions(const Mangled::Tokens& tokens) +// void +// CompileUnit::FindFunctions(const Mangled::Tokens& tokens) //{ // if (!m_functions.empty()) // { @@ -193,7 +154,8 @@ CompileUnit::GetFunctionAtIndex (size_t idx) // const ConstString& demangled = (*pos)->Mangled().Demangled(); // if (demangled) // { -// const Mangled::Tokens& func_tokens = (*pos)->Mangled().GetTokens(); +// const Mangled::Tokens& func_tokens = +// (*pos)->Mangled().GetTokens(); // if (func_tokens.MatchesQuery (tokens)) // s << "demangled MATCH found: " << demangled << "\n"; // } @@ -201,338 +163,272 @@ CompileUnit::GetFunctionAtIndex (size_t idx) // } //} -FunctionSP -CompileUnit::FindFunctionByUID (lldb::user_id_t func_uid) -{ - FunctionSP funcSP; - if (!m_functions.empty()) - { - std::vector<FunctionSP>::const_iterator pos; - std::vector<FunctionSP>::const_iterator end = m_functions.end(); - for (pos = m_functions.begin(); pos != end; ++pos) - { - if ((*pos)->GetID() == func_uid) - { - funcSP = *pos; - break; - } - } - } - return funcSP; -} - - -lldb::LanguageType -CompileUnit::GetLanguage() -{ - if (m_language == eLanguageTypeUnknown) - { - if (m_flags.IsClear(flagsParsedLanguage)) - { - m_flags.Set(flagsParsedLanguage); - SymbolVendor* symbol_vendor = GetModule()->GetSymbolVendor(); - if (symbol_vendor) - { - SymbolContext sc; - CalculateSymbolContext(&sc); - m_language = symbol_vendor->ParseCompileUnitLanguage(sc); - } - } +FunctionSP CompileUnit::FindFunctionByUID(lldb::user_id_t func_uid) { + FunctionSP funcSP; + if (!m_functions.empty()) { + std::vector<FunctionSP>::const_iterator pos; + std::vector<FunctionSP>::const_iterator end = m_functions.end(); + for (pos = m_functions.begin(); pos != end; ++pos) { + if ((*pos)->GetID() == func_uid) { + funcSP = *pos; + break; + } } - return m_language; + } + return funcSP; } -LineTable* -CompileUnit::GetLineTable() -{ - if (m_line_table_ap.get() == nullptr) - { - if (m_flags.IsClear(flagsParsedLineTable)) - { - m_flags.Set(flagsParsedLineTable); - SymbolVendor* symbol_vendor = GetModule()->GetSymbolVendor(); - if (symbol_vendor) - { - SymbolContext sc; - CalculateSymbolContext(&sc); - symbol_vendor->ParseCompileUnitLineTable(sc); - } - } +lldb::LanguageType CompileUnit::GetLanguage() { + if (m_language == eLanguageTypeUnknown) { + if (m_flags.IsClear(flagsParsedLanguage)) { + m_flags.Set(flagsParsedLanguage); + SymbolVendor *symbol_vendor = GetModule()->GetSymbolVendor(); + if (symbol_vendor) { + SymbolContext sc; + CalculateSymbolContext(&sc); + m_language = symbol_vendor->ParseCompileUnitLanguage(sc); + } } - return m_line_table_ap.get(); + } + return m_language; } -void -CompileUnit::SetLineTable(LineTable* line_table) -{ - if (line_table == nullptr) - m_flags.Clear(flagsParsedLineTable); - else - m_flags.Set(flagsParsedLineTable); - m_line_table_ap.reset(line_table); -} - -DebugMacros* -CompileUnit::GetDebugMacros() -{ - if (m_debug_macros_sp.get() == nullptr) - { - if (m_flags.IsClear(flagsParsedDebugMacros)) - { - m_flags.Set(flagsParsedDebugMacros); - SymbolVendor* symbol_vendor = GetModule()->GetSymbolVendor(); - if (symbol_vendor) - { - SymbolContext sc; - CalculateSymbolContext(&sc); - symbol_vendor->ParseCompileUnitDebugMacros(sc); - } - } +LineTable *CompileUnit::GetLineTable() { + if (m_line_table_ap.get() == nullptr) { + if (m_flags.IsClear(flagsParsedLineTable)) { + m_flags.Set(flagsParsedLineTable); + SymbolVendor *symbol_vendor = GetModule()->GetSymbolVendor(); + if (symbol_vendor) { + SymbolContext sc; + CalculateSymbolContext(&sc); + symbol_vendor->ParseCompileUnitLineTable(sc); + } } - - return m_debug_macros_sp.get(); + } + return m_line_table_ap.get(); } -void -CompileUnit::SetDebugMacros(const DebugMacrosSP &debug_macros_sp) -{ - if (debug_macros_sp.get() == nullptr) - m_flags.Clear(flagsParsedDebugMacros); - else - m_flags.Set(flagsParsedDebugMacros); - m_debug_macros_sp = debug_macros_sp; +void CompileUnit::SetLineTable(LineTable *line_table) { + if (line_table == nullptr) + m_flags.Clear(flagsParsedLineTable); + else + m_flags.Set(flagsParsedLineTable); + m_line_table_ap.reset(line_table); } -VariableListSP -CompileUnit::GetVariableList(bool can_create) -{ - if (m_variables.get() == nullptr && can_create) - { +DebugMacros *CompileUnit::GetDebugMacros() { + if (m_debug_macros_sp.get() == nullptr) { + if (m_flags.IsClear(flagsParsedDebugMacros)) { + m_flags.Set(flagsParsedDebugMacros); + SymbolVendor *symbol_vendor = GetModule()->GetSymbolVendor(); + if (symbol_vendor) { SymbolContext sc; CalculateSymbolContext(&sc); - assert(sc.module_sp); - sc.module_sp->GetSymbolVendor()->ParseVariablesForContext(sc); + symbol_vendor->ParseCompileUnitDebugMacros(sc); + } } + } - return m_variables; + return m_debug_macros_sp.get(); } -uint32_t -CompileUnit::FindLineEntry (uint32_t start_idx, uint32_t line, const FileSpec* file_spec_ptr, bool exact, LineEntry *line_entry_ptr) -{ - uint32_t file_idx = 0; - - if (file_spec_ptr) - { - file_idx = GetSupportFiles().FindFileIndex (1, *file_spec_ptr, true); - if (file_idx == UINT32_MAX) - return UINT32_MAX; - } - else - { - // All the line table entries actually point to the version of the Compile - // Unit that is in the support files (the one at 0 was artificially added.) - // So prefer the one further on in the support files if it exists... - FileSpecList &support_files = GetSupportFiles(); - const bool full = true; - file_idx = support_files.FindFileIndex (1, support_files.GetFileSpecAtIndex(0), full); - if (file_idx == UINT32_MAX) - file_idx = 0; - } - LineTable *line_table = GetLineTable(); - if (line_table) - return line_table->FindLineEntryIndexByFileIndex (start_idx, file_idx, line, exact, line_entry_ptr); - return UINT32_MAX; +void CompileUnit::SetDebugMacros(const DebugMacrosSP &debug_macros_sp) { + if (debug_macros_sp.get() == nullptr) + m_flags.Clear(flagsParsedDebugMacros); + else + m_flags.Set(flagsParsedDebugMacros); + m_debug_macros_sp = debug_macros_sp; } +VariableListSP CompileUnit::GetVariableList(bool can_create) { + if (m_variables.get() == nullptr && can_create) { + SymbolContext sc; + CalculateSymbolContext(&sc); + assert(sc.module_sp); + sc.module_sp->GetSymbolVendor()->ParseVariablesForContext(sc); + } + return m_variables; +} +uint32_t CompileUnit::FindLineEntry(uint32_t start_idx, uint32_t line, + const FileSpec *file_spec_ptr, bool exact, + LineEntry *line_entry_ptr) { + uint32_t file_idx = 0; + + if (file_spec_ptr) { + file_idx = GetSupportFiles().FindFileIndex(1, *file_spec_ptr, true); + if (file_idx == UINT32_MAX) + return UINT32_MAX; + } else { + // All the line table entries actually point to the version of the Compile + // Unit that is in the support files (the one at 0 was artificially added.) + // So prefer the one further on in the support files if it exists... + FileSpecList &support_files = GetSupportFiles(); + const bool full = true; + file_idx = support_files.FindFileIndex( + 1, support_files.GetFileSpecAtIndex(0), full); + if (file_idx == UINT32_MAX) + file_idx = 0; + } + LineTable *line_table = GetLineTable(); + if (line_table) + return line_table->FindLineEntryIndexByFileIndex(start_idx, file_idx, line, + exact, line_entry_ptr); + return UINT32_MAX; +} -uint32_t -CompileUnit::ResolveSymbolContext -( - const FileSpec& file_spec, - uint32_t line, - bool check_inlines, - bool exact, - uint32_t resolve_scope, - SymbolContextList &sc_list -) -{ - // First find all of the file indexes that match our "file_spec". If - // "file_spec" has an empty directory, then only compare the basenames - // when finding file indexes - std::vector<uint32_t> file_indexes; - const bool full_match = (bool)file_spec.GetDirectory(); - const bool remove_backup_dots = true; - bool file_spec_matches_cu_file_spec = FileSpec::Equal(file_spec, *this, full_match, remove_backup_dots); - - // If we are not looking for inlined functions and our file spec doesn't - // match then we are done... - if (file_spec_matches_cu_file_spec == false && check_inlines == false) - return 0; - - uint32_t file_idx = GetSupportFiles().FindFileIndex (1, file_spec, true, remove_backup_dots); - while (file_idx != UINT32_MAX) - { - file_indexes.push_back (file_idx); - file_idx = GetSupportFiles().FindFileIndex (file_idx + 1, file_spec, true, remove_backup_dots); - } - - const size_t num_file_indexes = file_indexes.size(); - if (num_file_indexes == 0) - return 0; - - const uint32_t prev_size = sc_list.GetSize(); - - SymbolContext sc(GetModule()); - sc.comp_unit = this; - - - if (line != 0) - { - LineTable *line_table = sc.comp_unit->GetLineTable(); - - if (line_table != nullptr) - { - uint32_t found_line; - uint32_t line_idx; - - if (num_file_indexes == 1) - { - // We only have a single support file that matches, so use - // the line table function that searches for a line entries - // that match a single support file index - LineEntry line_entry; - line_idx = line_table->FindLineEntryIndexByFileIndex (0, file_indexes.front(), line, exact, &line_entry); - - // If "exact == true", then "found_line" will be the same - // as "line". If "exact == false", the "found_line" will be the - // closest line entry with a line number greater than "line" and - // we will use this for our subsequent line exact matches below. - found_line = line_entry.line; - - while (line_idx != UINT32_MAX) - { - // If they only asked for the line entry, then we're done, we can just copy that over. - // But if they wanted more than just the line number, fill it in. - if (resolve_scope == eSymbolContextLineEntry) - { - sc.line_entry = line_entry; - } - else - { - line_entry.range.GetBaseAddress().CalculateSymbolContext(&sc, resolve_scope); - } - - sc_list.Append(sc); - line_idx = line_table->FindLineEntryIndexByFileIndex (line_idx + 1, file_indexes.front(), found_line, true, &line_entry); - } - } - else - { - // We found multiple support files that match "file_spec" so use - // the line table function that searches for a line entries - // that match a multiple support file indexes. - LineEntry line_entry; - line_idx = line_table->FindLineEntryIndexByFileIndex (0, file_indexes, line, exact, &line_entry); - - // If "exact == true", then "found_line" will be the same - // as "line". If "exact == false", the "found_line" will be the - // closest line entry with a line number greater than "line" and - // we will use this for our subsequent line exact matches below. - found_line = line_entry.line; - - while (line_idx != UINT32_MAX) - { - if (resolve_scope == eSymbolContextLineEntry) - { - sc.line_entry = line_entry; - } - else - { - line_entry.range.GetBaseAddress().CalculateSymbolContext(&sc, resolve_scope); - } - - sc_list.Append(sc); - line_idx = line_table->FindLineEntryIndexByFileIndex (line_idx + 1, file_indexes, found_line, true, &line_entry); - } - } +uint32_t CompileUnit::ResolveSymbolContext(const FileSpec &file_spec, + uint32_t line, bool check_inlines, + bool exact, uint32_t resolve_scope, + SymbolContextList &sc_list) { + // First find all of the file indexes that match our "file_spec". If + // "file_spec" has an empty directory, then only compare the basenames + // when finding file indexes + std::vector<uint32_t> file_indexes; + const bool full_match = (bool)file_spec.GetDirectory(); + const bool remove_backup_dots = true; + bool file_spec_matches_cu_file_spec = + FileSpec::Equal(file_spec, *this, full_match, remove_backup_dots); + + // If we are not looking for inlined functions and our file spec doesn't + // match then we are done... + if (file_spec_matches_cu_file_spec == false && check_inlines == false) + return 0; + + uint32_t file_idx = + GetSupportFiles().FindFileIndex(1, file_spec, true, remove_backup_dots); + while (file_idx != UINT32_MAX) { + file_indexes.push_back(file_idx); + file_idx = GetSupportFiles().FindFileIndex(file_idx + 1, file_spec, true, + remove_backup_dots); + } + + const size_t num_file_indexes = file_indexes.size(); + if (num_file_indexes == 0) + return 0; + + const uint32_t prev_size = sc_list.GetSize(); + + SymbolContext sc(GetModule()); + sc.comp_unit = this; + + if (line != 0) { + LineTable *line_table = sc.comp_unit->GetLineTable(); + + if (line_table != nullptr) { + uint32_t found_line; + uint32_t line_idx; + + if (num_file_indexes == 1) { + // We only have a single support file that matches, so use + // the line table function that searches for a line entries + // that match a single support file index + LineEntry line_entry; + line_idx = line_table->FindLineEntryIndexByFileIndex( + 0, file_indexes.front(), line, exact, &line_entry); + + // If "exact == true", then "found_line" will be the same + // as "line". If "exact == false", the "found_line" will be the + // closest line entry with a line number greater than "line" and + // we will use this for our subsequent line exact matches below. + found_line = line_entry.line; + + while (line_idx != UINT32_MAX) { + // If they only asked for the line entry, then we're done, we can just + // copy that over. + // But if they wanted more than just the line number, fill it in. + if (resolve_scope == eSymbolContextLineEntry) { + sc.line_entry = line_entry; + } else { + line_entry.range.GetBaseAddress().CalculateSymbolContext( + &sc, resolve_scope); + } + + sc_list.Append(sc); + line_idx = line_table->FindLineEntryIndexByFileIndex( + line_idx + 1, file_indexes.front(), found_line, true, + &line_entry); } + } else { + // We found multiple support files that match "file_spec" so use + // the line table function that searches for a line entries + // that match a multiple support file indexes. + LineEntry line_entry; + line_idx = line_table->FindLineEntryIndexByFileIndex( + 0, file_indexes, line, exact, &line_entry); + + // If "exact == true", then "found_line" will be the same + // as "line". If "exact == false", the "found_line" will be the + // closest line entry with a line number greater than "line" and + // we will use this for our subsequent line exact matches below. + found_line = line_entry.line; + + while (line_idx != UINT32_MAX) { + if (resolve_scope == eSymbolContextLineEntry) { + sc.line_entry = line_entry; + } else { + line_entry.range.GetBaseAddress().CalculateSymbolContext( + &sc, resolve_scope); + } + + sc_list.Append(sc); + line_idx = line_table->FindLineEntryIndexByFileIndex( + line_idx + 1, file_indexes, found_line, true, &line_entry); + } + } } - else if (file_spec_matches_cu_file_spec && !check_inlines) - { - // only append the context if we aren't looking for inline call sites - // by file and line and if the file spec matches that of the compile unit - sc_list.Append(sc); - } - return sc_list.GetSize() - prev_size; + } else if (file_spec_matches_cu_file_spec && !check_inlines) { + // only append the context if we aren't looking for inline call sites + // by file and line and if the file spec matches that of the compile unit + sc_list.Append(sc); + } + return sc_list.GetSize() - prev_size; } -bool -CompileUnit::GetIsOptimized () -{ - if (m_is_optimized == eLazyBoolCalculate) - { - m_is_optimized = eLazyBoolNo; - if (SymbolVendor *symbol_vendor = GetModule()->GetSymbolVendor()) - { - SymbolContext sc; - CalculateSymbolContext(&sc); - if (symbol_vendor->ParseCompileUnitIsOptimized(sc)) - m_is_optimized = eLazyBoolYes; - } +bool CompileUnit::GetIsOptimized() { + if (m_is_optimized == eLazyBoolCalculate) { + m_is_optimized = eLazyBoolNo; + if (SymbolVendor *symbol_vendor = GetModule()->GetSymbolVendor()) { + SymbolContext sc; + CalculateSymbolContext(&sc); + if (symbol_vendor->ParseCompileUnitIsOptimized(sc)) + m_is_optimized = eLazyBoolYes; } - return m_is_optimized; + } + return m_is_optimized; } -void -CompileUnit::SetVariableList(VariableListSP &variables) -{ - m_variables = variables; +void CompileUnit::SetVariableList(VariableListSP &variables) { + m_variables = variables; } -const std::vector<ConstString> & -CompileUnit::GetImportedModules () -{ - if (m_imported_modules.empty() && - m_flags.IsClear(flagsParsedImportedModules)) - { - m_flags.Set(flagsParsedImportedModules); - if (SymbolVendor *symbol_vendor = GetModule()->GetSymbolVendor()) - { - SymbolContext sc; - CalculateSymbolContext(&sc); - symbol_vendor->ParseImportedModules(sc, m_imported_modules); - } +const std::vector<ConstString> &CompileUnit::GetImportedModules() { + if (m_imported_modules.empty() && + m_flags.IsClear(flagsParsedImportedModules)) { + m_flags.Set(flagsParsedImportedModules); + if (SymbolVendor *symbol_vendor = GetModule()->GetSymbolVendor()) { + SymbolContext sc; + CalculateSymbolContext(&sc); + symbol_vendor->ParseImportedModules(sc, m_imported_modules); } - return m_imported_modules; + } + return m_imported_modules; } -FileSpecList& -CompileUnit::GetSupportFiles () -{ - if (m_support_files.GetSize() == 0) - { - if (m_flags.IsClear(flagsParsedSupportFiles)) - { - m_flags.Set(flagsParsedSupportFiles); - SymbolVendor* symbol_vendor = GetModule()->GetSymbolVendor(); - if (symbol_vendor) - { - SymbolContext sc; - CalculateSymbolContext(&sc); - symbol_vendor->ParseCompileUnitSupportFiles(sc, m_support_files); - } - } +FileSpecList &CompileUnit::GetSupportFiles() { + if (m_support_files.GetSize() == 0) { + if (m_flags.IsClear(flagsParsedSupportFiles)) { + m_flags.Set(flagsParsedSupportFiles); + SymbolVendor *symbol_vendor = GetModule()->GetSymbolVendor(); + if (symbol_vendor) { + SymbolContext sc; + CalculateSymbolContext(&sc); + symbol_vendor->ParseCompileUnitSupportFiles(sc, m_support_files); + } } - return m_support_files; -} - -void * -CompileUnit::GetUserData () const -{ - return m_user_data; + } + return m_support_files; } - +void *CompileUnit::GetUserData() const { return m_user_data; } diff --git a/lldb/source/Symbol/CompilerDecl.cpp b/lldb/source/Symbol/CompilerDecl.cpp index 98eef060df0..2b632c5eb5d 100644 --- a/lldb/source/Symbol/CompilerDecl.cpp +++ b/lldb/source/Symbol/CompilerDecl.cpp @@ -13,58 +13,42 @@ using namespace lldb_private; -bool -CompilerDecl::IsClang () const -{ - return IsValid() && m_type_system->getKind() == TypeSystem::eKindClang; +bool CompilerDecl::IsClang() const { + return IsValid() && m_type_system->getKind() == TypeSystem::eKindClang; } -ConstString -CompilerDecl::GetName() const -{ - return m_type_system->DeclGetName(m_opaque_decl); +ConstString CompilerDecl::GetName() const { + return m_type_system->DeclGetName(m_opaque_decl); } -ConstString -CompilerDecl::GetMangledName () const -{ - return m_type_system->DeclGetMangledName(m_opaque_decl); +ConstString CompilerDecl::GetMangledName() const { + return m_type_system->DeclGetMangledName(m_opaque_decl); } -CompilerDeclContext -CompilerDecl::GetDeclContext() const -{ - return m_type_system->DeclGetDeclContext(m_opaque_decl); +CompilerDeclContext CompilerDecl::GetDeclContext() const { + return m_type_system->DeclGetDeclContext(m_opaque_decl); } -CompilerType -CompilerDecl::GetFunctionReturnType() const -{ - return m_type_system->DeclGetFunctionReturnType(m_opaque_decl); +CompilerType CompilerDecl::GetFunctionReturnType() const { + return m_type_system->DeclGetFunctionReturnType(m_opaque_decl); } -size_t -CompilerDecl::GetNumFunctionArguments() const -{ - return m_type_system->DeclGetFunctionNumArguments(m_opaque_decl); +size_t CompilerDecl::GetNumFunctionArguments() const { + return m_type_system->DeclGetFunctionNumArguments(m_opaque_decl); } -CompilerType -CompilerDecl::GetFunctionArgumentType (size_t arg_idx) const -{ - return m_type_system->DeclGetFunctionArgumentType(m_opaque_decl, arg_idx); +CompilerType CompilerDecl::GetFunctionArgumentType(size_t arg_idx) const { + return m_type_system->DeclGetFunctionArgumentType(m_opaque_decl, arg_idx); } -bool -lldb_private::operator == (const lldb_private::CompilerDecl &lhs, const lldb_private::CompilerDecl &rhs) -{ - return lhs.GetTypeSystem() == rhs.GetTypeSystem() && lhs.GetOpaqueDecl() == rhs.GetOpaqueDecl(); +bool lldb_private::operator==(const lldb_private::CompilerDecl &lhs, + const lldb_private::CompilerDecl &rhs) { + return lhs.GetTypeSystem() == rhs.GetTypeSystem() && + lhs.GetOpaqueDecl() == rhs.GetOpaqueDecl(); } - -bool -lldb_private::operator != (const lldb_private::CompilerDecl &lhs, const lldb_private::CompilerDecl &rhs) -{ - return lhs.GetTypeSystem() != rhs.GetTypeSystem() || lhs.GetOpaqueDecl() != rhs.GetOpaqueDecl(); +bool lldb_private::operator!=(const lldb_private::CompilerDecl &lhs, + const lldb_private::CompilerDecl &rhs) { + return lhs.GetTypeSystem() != rhs.GetTypeSystem() || + lhs.GetOpaqueDecl() != rhs.GetOpaqueDecl(); } - diff --git a/lldb/source/Symbol/CompilerDeclContext.cpp b/lldb/source/Symbol/CompilerDeclContext.cpp index 10a70d97f23..43a83bbca77 100644 --- a/lldb/source/Symbol/CompilerDeclContext.cpp +++ b/lldb/source/Symbol/CompilerDeclContext.cpp @@ -15,71 +15,59 @@ using namespace lldb_private; std::vector<CompilerDecl> -CompilerDeclContext::FindDeclByName (ConstString name, const bool ignore_using_decls) -{ - if (IsValid()) - return m_type_system->DeclContextFindDeclByName( - m_opaque_decl_ctx, name, ignore_using_decls); - else - return std::vector<CompilerDecl>(); +CompilerDeclContext::FindDeclByName(ConstString name, + const bool ignore_using_decls) { + if (IsValid()) + return m_type_system->DeclContextFindDeclByName(m_opaque_decl_ctx, name, + ignore_using_decls); + else + return std::vector<CompilerDecl>(); } -bool -CompilerDeclContext::IsClang () const -{ - return IsValid() && m_type_system->getKind() == TypeSystem::eKindClang; +bool CompilerDeclContext::IsClang() const { + return IsValid() && m_type_system->getKind() == TypeSystem::eKindClang; } -ConstString -CompilerDeclContext::GetName () const -{ - if (IsValid()) - return m_type_system->DeclContextGetName(m_opaque_decl_ctx); - else - return ConstString(); +ConstString CompilerDeclContext::GetName() const { + if (IsValid()) + return m_type_system->DeclContextGetName(m_opaque_decl_ctx); + else + return ConstString(); } -ConstString -CompilerDeclContext::GetScopeQualifiedName () const -{ - if (IsValid()) - return m_type_system->DeclContextGetScopeQualifiedName(m_opaque_decl_ctx); - else - return ConstString(); +ConstString CompilerDeclContext::GetScopeQualifiedName() const { + if (IsValid()) + return m_type_system->DeclContextGetScopeQualifiedName(m_opaque_decl_ctx); + else + return ConstString(); } -bool -CompilerDeclContext::IsStructUnionOrClass () const -{ - if (IsValid()) - return m_type_system->DeclContextIsStructUnionOrClass(m_opaque_decl_ctx); - else - return false; +bool CompilerDeclContext::IsStructUnionOrClass() const { + if (IsValid()) + return m_type_system->DeclContextIsStructUnionOrClass(m_opaque_decl_ctx); + else + return false; } -bool -CompilerDeclContext::IsClassMethod (lldb::LanguageType *language_ptr, - bool *is_instance_method_ptr, - ConstString *language_object_name_ptr) -{ - if (IsValid()) - return m_type_system->DeclContextIsClassMethod (m_opaque_decl_ctx, - language_ptr, - is_instance_method_ptr, - language_object_name_ptr); - else - return false; +bool CompilerDeclContext::IsClassMethod(lldb::LanguageType *language_ptr, + bool *is_instance_method_ptr, + ConstString *language_object_name_ptr) { + if (IsValid()) + return m_type_system->DeclContextIsClassMethod( + m_opaque_decl_ctx, language_ptr, is_instance_method_ptr, + language_object_name_ptr); + else + return false; } -bool -lldb_private::operator == (const lldb_private::CompilerDeclContext &lhs, const lldb_private::CompilerDeclContext &rhs) -{ - return lhs.GetTypeSystem() == rhs.GetTypeSystem() && lhs.GetOpaqueDeclContext() == rhs.GetOpaqueDeclContext(); +bool lldb_private::operator==(const lldb_private::CompilerDeclContext &lhs, + const lldb_private::CompilerDeclContext &rhs) { + return lhs.GetTypeSystem() == rhs.GetTypeSystem() && + lhs.GetOpaqueDeclContext() == rhs.GetOpaqueDeclContext(); } - -bool -lldb_private::operator != (const lldb_private::CompilerDeclContext &lhs, const lldb_private::CompilerDeclContext &rhs) -{ - return lhs.GetTypeSystem() != rhs.GetTypeSystem() || lhs.GetOpaqueDeclContext() != rhs.GetOpaqueDeclContext(); +bool lldb_private::operator!=(const lldb_private::CompilerDeclContext &lhs, + const lldb_private::CompilerDeclContext &rhs) { + return lhs.GetTypeSystem() != rhs.GetTypeSystem() || + lhs.GetOpaqueDeclContext() != rhs.GetOpaqueDeclContext(); } diff --git a/lldb/source/Symbol/CompilerType.cpp b/lldb/source/Symbol/CompilerType.cpp index ef788d06eff..2684db980aa 100644 --- a/lldb/source/Symbol/CompilerType.cpp +++ b/lldb/source/Symbol/CompilerType.cpp @@ -29,614 +29,465 @@ using namespace lldb; using namespace lldb_private; -CompilerType::CompilerType (TypeSystem *type_system, - lldb::opaque_compiler_type_t type) : - m_type (type), - m_type_system (type_system) -{ -} - -CompilerType::CompilerType (clang::ASTContext *ast, - clang::QualType qual_type) : - m_type (qual_type.getAsOpaquePtr()), - m_type_system (ClangASTContext::GetASTContext(ast)) -{ +CompilerType::CompilerType(TypeSystem *type_system, + lldb::opaque_compiler_type_t type) + : m_type(type), m_type_system(type_system) {} + +CompilerType::CompilerType(clang::ASTContext *ast, clang::QualType qual_type) + : m_type(qual_type.getAsOpaquePtr()), + m_type_system(ClangASTContext::GetASTContext(ast)) { #ifdef LLDB_CONFIGURATION_DEBUG - if (m_type) - assert(m_type_system != nullptr); + if (m_type) + assert(m_type_system != nullptr); #endif } -CompilerType::~CompilerType() -{ -} +CompilerType::~CompilerType() {} //---------------------------------------------------------------------- // Tests //---------------------------------------------------------------------- -bool -CompilerType::IsAggregateType () const -{ - if (IsValid()) - return m_type_system->IsAggregateType(m_type); - return false; +bool CompilerType::IsAggregateType() const { + if (IsValid()) + return m_type_system->IsAggregateType(m_type); + return false; } -bool -CompilerType::IsAnonymousType () const -{ - if (IsValid()) - return m_type_system->IsAnonymousType(m_type); - return false; +bool CompilerType::IsAnonymousType() const { + if (IsValid()) + return m_type_system->IsAnonymousType(m_type); + return false; } -bool -CompilerType::IsArrayType (CompilerType *element_type_ptr, - uint64_t *size, - bool *is_incomplete) const -{ - if (IsValid()) - return m_type_system->IsArrayType(m_type, element_type_ptr, size, is_incomplete); - - if (element_type_ptr) - element_type_ptr->Clear(); - if (size) - *size = 0; - if (is_incomplete) - *is_incomplete = false; - return false; -} +bool CompilerType::IsArrayType(CompilerType *element_type_ptr, uint64_t *size, + bool *is_incomplete) const { + if (IsValid()) + return m_type_system->IsArrayType(m_type, element_type_ptr, size, + is_incomplete); -bool -CompilerType::IsVectorType (CompilerType *element_type, - uint64_t *size) const -{ - if (IsValid()) - return m_type_system->IsVectorType(m_type, element_type, size); - return false; + if (element_type_ptr) + element_type_ptr->Clear(); + if (size) + *size = 0; + if (is_incomplete) + *is_incomplete = false; + return false; } -bool -CompilerType::IsRuntimeGeneratedType () const -{ - if (IsValid()) - return m_type_system->IsRuntimeGeneratedType(m_type); - return false; +bool CompilerType::IsVectorType(CompilerType *element_type, + uint64_t *size) const { + if (IsValid()) + return m_type_system->IsVectorType(m_type, element_type, size); + return false; } -bool -CompilerType::IsCharType () const -{ - if (IsValid()) - return m_type_system->IsCharType(m_type); - return false; +bool CompilerType::IsRuntimeGeneratedType() const { + if (IsValid()) + return m_type_system->IsRuntimeGeneratedType(m_type); + return false; } +bool CompilerType::IsCharType() const { + if (IsValid()) + return m_type_system->IsCharType(m_type); + return false; +} -bool -CompilerType::IsCompleteType () const -{ - if (IsValid()) - return m_type_system->IsCompleteType(m_type); - return false; +bool CompilerType::IsCompleteType() const { + if (IsValid()) + return m_type_system->IsCompleteType(m_type); + return false; } -bool -CompilerType::IsConst() const -{ - if (IsValid()) - return m_type_system->IsConst(m_type); - return false; +bool CompilerType::IsConst() const { + if (IsValid()) + return m_type_system->IsConst(m_type); + return false; } -bool -CompilerType::IsCStringType (uint32_t &length) const -{ - if (IsValid()) - return m_type_system->IsCStringType(m_type, length); - return false; +bool CompilerType::IsCStringType(uint32_t &length) const { + if (IsValid()) + return m_type_system->IsCStringType(m_type, length); + return false; } -bool -CompilerType::IsFunctionType (bool *is_variadic_ptr) const -{ - if (IsValid()) - return m_type_system->IsFunctionType(m_type, is_variadic_ptr); - return false; +bool CompilerType::IsFunctionType(bool *is_variadic_ptr) const { + if (IsValid()) + return m_type_system->IsFunctionType(m_type, is_variadic_ptr); + return false; } // Used to detect "Homogeneous Floating-point Aggregates" uint32_t -CompilerType::IsHomogeneousAggregate (CompilerType* base_type_ptr) const -{ - if (IsValid()) - return m_type_system->IsHomogeneousAggregate(m_type, base_type_ptr); - return 0; +CompilerType::IsHomogeneousAggregate(CompilerType *base_type_ptr) const { + if (IsValid()) + return m_type_system->IsHomogeneousAggregate(m_type, base_type_ptr); + return 0; } -size_t -CompilerType::GetNumberOfFunctionArguments () const -{ - if (IsValid()) - return m_type_system->GetNumberOfFunctionArguments(m_type); - return 0; +size_t CompilerType::GetNumberOfFunctionArguments() const { + if (IsValid()) + return m_type_system->GetNumberOfFunctionArguments(m_type); + return 0; } CompilerType -CompilerType::GetFunctionArgumentAtIndex (const size_t index) const -{ - if (IsValid()) - return m_type_system->GetFunctionArgumentAtIndex(m_type, index); - return CompilerType(); +CompilerType::GetFunctionArgumentAtIndex(const size_t index) const { + if (IsValid()) + return m_type_system->GetFunctionArgumentAtIndex(m_type, index); + return CompilerType(); } -bool -CompilerType::IsFunctionPointerType () const -{ - if (IsValid()) - return m_type_system->IsFunctionPointerType(m_type); - return false; +bool CompilerType::IsFunctionPointerType() const { + if (IsValid()) + return m_type_system->IsFunctionPointerType(m_type); + return false; } -bool -CompilerType::IsBlockPointerType (CompilerType *function_pointer_type_ptr) const -{ - if (IsValid()) - return m_type_system->IsBlockPointerType(m_type, function_pointer_type_ptr); - return 0; +bool CompilerType::IsBlockPointerType( + CompilerType *function_pointer_type_ptr) const { + if (IsValid()) + return m_type_system->IsBlockPointerType(m_type, function_pointer_type_ptr); + return 0; } -bool -CompilerType::IsIntegerType (bool &is_signed) const -{ - if (IsValid()) - return m_type_system->IsIntegerType(m_type, is_signed); - return false; +bool CompilerType::IsIntegerType(bool &is_signed) const { + if (IsValid()) + return m_type_system->IsIntegerType(m_type, is_signed); + return false; } -bool -CompilerType::IsEnumerationType (bool &is_signed) const -{ - if (IsValid()) - return m_type_system->IsEnumerationType(m_type, is_signed); - return false; +bool CompilerType::IsEnumerationType(bool &is_signed) const { + if (IsValid()) + return m_type_system->IsEnumerationType(m_type, is_signed); + return false; } -bool -CompilerType::IsIntegerOrEnumerationType (bool &is_signed) const -{ - return IsIntegerType(is_signed) || IsEnumerationType(is_signed); +bool CompilerType::IsIntegerOrEnumerationType(bool &is_signed) const { + return IsIntegerType(is_signed) || IsEnumerationType(is_signed); } -bool -CompilerType::IsPointerType (CompilerType *pointee_type) const -{ - if (IsValid()) - { - return m_type_system->IsPointerType(m_type, pointee_type); - } - if (pointee_type) - pointee_type->Clear(); - return false; +bool CompilerType::IsPointerType(CompilerType *pointee_type) const { + if (IsValid()) { + return m_type_system->IsPointerType(m_type, pointee_type); + } + if (pointee_type) + pointee_type->Clear(); + return false; } - -bool -CompilerType::IsPointerOrReferenceType (CompilerType *pointee_type) const -{ - if (IsValid()) - { - return m_type_system->IsPointerOrReferenceType(m_type, pointee_type); - } - if (pointee_type) - pointee_type->Clear(); - return false; +bool CompilerType::IsPointerOrReferenceType(CompilerType *pointee_type) const { + if (IsValid()) { + return m_type_system->IsPointerOrReferenceType(m_type, pointee_type); + } + if (pointee_type) + pointee_type->Clear(); + return false; } +bool CompilerType::IsReferenceType(CompilerType *pointee_type, + bool *is_rvalue) const { + if (IsValid()) { + return m_type_system->IsReferenceType(m_type, pointee_type, is_rvalue); + } + if (pointee_type) + pointee_type->Clear(); + return false; +} -bool -CompilerType::IsReferenceType (CompilerType *pointee_type, bool* is_rvalue) const -{ - if (IsValid()) - { - return m_type_system->IsReferenceType(m_type, pointee_type, is_rvalue); - } - if (pointee_type) - pointee_type->Clear(); - return false; +bool CompilerType::ShouldTreatScalarValueAsAddress() const { + if (IsValid()) + return m_type_system->ShouldTreatScalarValueAsAddress(m_type); + return false; } -bool -CompilerType::ShouldTreatScalarValueAsAddress () const -{ - if (IsValid()) - return m_type_system->ShouldTreatScalarValueAsAddress(m_type); - return false; +bool CompilerType::IsFloatingPointType(uint32_t &count, + bool &is_complex) const { + if (IsValid()) { + return m_type_system->IsFloatingPointType(m_type, count, is_complex); + } + count = 0; + is_complex = false; + return false; } -bool -CompilerType::IsFloatingPointType (uint32_t &count, bool &is_complex) const -{ - if (IsValid()) - { - return m_type_system->IsFloatingPointType(m_type, count, is_complex); - } - count = 0; - is_complex = false; - return false; +bool CompilerType::IsDefined() const { + if (IsValid()) + return m_type_system->IsDefined(m_type); + return true; } +bool CompilerType::IsPolymorphicClass() const { + if (IsValid()) { + return m_type_system->IsPolymorphicClass(m_type); + } + return false; +} -bool -CompilerType::IsDefined() const -{ - if (IsValid()) - return m_type_system->IsDefined(m_type); - return true; +bool CompilerType::IsPossibleDynamicType(CompilerType *dynamic_pointee_type, + bool check_cplusplus, + bool check_objc) const { + if (IsValid()) + return m_type_system->IsPossibleDynamicType(m_type, dynamic_pointee_type, + check_cplusplus, check_objc); + return false; } -bool -CompilerType::IsPolymorphicClass () const -{ - if (IsValid()) - { - return m_type_system->IsPolymorphicClass(m_type); - } +bool CompilerType::IsScalarType() const { + if (!IsValid()) return false; + + return m_type_system->IsScalarType(m_type); } -bool -CompilerType::IsPossibleDynamicType (CompilerType *dynamic_pointee_type, - bool check_cplusplus, - bool check_objc) const -{ - if (IsValid()) - return m_type_system->IsPossibleDynamicType(m_type, dynamic_pointee_type, check_cplusplus, check_objc); +bool CompilerType::IsTypedefType() const { + if (!IsValid()) return false; + return m_type_system->IsTypedefType(m_type); } - -bool -CompilerType::IsScalarType () const -{ - if (!IsValid()) - return false; - - return m_type_system->IsScalarType(m_type); +bool CompilerType::IsVoidType() const { + if (!IsValid()) + return false; + return m_type_system->IsVoidType(m_type); } -bool -CompilerType::IsTypedefType () const -{ - if (!IsValid()) - return false; - return m_type_system->IsTypedefType(m_type); -} +bool CompilerType::IsPointerToScalarType() const { + if (!IsValid()) + return false; -bool -CompilerType::IsVoidType () const -{ - if (!IsValid()) - return false; - return m_type_system->IsVoidType(m_type); + return IsPointerType() && GetPointeeType().IsScalarType(); } -bool -CompilerType::IsPointerToScalarType () const -{ - if (!IsValid()) - return false; - - return IsPointerType() && GetPointeeType().IsScalarType(); +bool CompilerType::IsArrayOfScalarType() const { + CompilerType element_type; + if (IsArrayType(&element_type, nullptr, nullptr)) + return element_type.IsScalarType(); + return false; } -bool -CompilerType::IsArrayOfScalarType () const -{ - CompilerType element_type; - if (IsArrayType(&element_type, nullptr, nullptr)) - return element_type.IsScalarType(); +bool CompilerType::IsBeingDefined() const { + if (!IsValid()) return false; -} - -bool -CompilerType::IsBeingDefined () const -{ - if (!IsValid()) - return false; - return m_type_system->IsBeingDefined(m_type); + return m_type_system->IsBeingDefined(m_type); } //---------------------------------------------------------------------- // Type Completion //---------------------------------------------------------------------- -bool -CompilerType::GetCompleteType () const -{ - if (!IsValid()) - return false; - return m_type_system->GetCompleteType(m_type); +bool CompilerType::GetCompleteType() const { + if (!IsValid()) + return false; + return m_type_system->GetCompleteType(m_type); } //---------------------------------------------------------------------- // AST related queries //---------------------------------------------------------------------- -size_t -CompilerType::GetPointerByteSize () const -{ - if (m_type_system) - return m_type_system->GetPointerByteSize(); - return 0; +size_t CompilerType::GetPointerByteSize() const { + if (m_type_system) + return m_type_system->GetPointerByteSize(); + return 0; } -ConstString -CompilerType::GetConstQualifiedTypeName () const -{ - return GetConstTypeName (); +ConstString CompilerType::GetConstQualifiedTypeName() const { + return GetConstTypeName(); } -ConstString -CompilerType::GetConstTypeName () const -{ - if (IsValid()) - { - ConstString type_name (GetTypeName()); - if (type_name) - return type_name; - } - return ConstString("<invalid>"); +ConstString CompilerType::GetConstTypeName() const { + if (IsValid()) { + ConstString type_name(GetTypeName()); + if (type_name) + return type_name; + } + return ConstString("<invalid>"); } -ConstString -CompilerType::GetTypeName () const -{ - if (IsValid()) - { - return m_type_system->GetTypeName(m_type); - } - return ConstString("<invalid>"); +ConstString CompilerType::GetTypeName() const { + if (IsValid()) { + return m_type_system->GetTypeName(m_type); + } + return ConstString("<invalid>"); } -ConstString -CompilerType::GetDisplayTypeName () const -{ - return GetTypeName(); -} +ConstString CompilerType::GetDisplayTypeName() const { return GetTypeName(); } -uint32_t -CompilerType::GetTypeInfo (CompilerType *pointee_or_element_compiler_type) const -{ - if (!IsValid()) - return 0; - - return m_type_system->GetTypeInfo(m_type, pointee_or_element_compiler_type); -} +uint32_t CompilerType::GetTypeInfo( + CompilerType *pointee_or_element_compiler_type) const { + if (!IsValid()) + return 0; + return m_type_system->GetTypeInfo(m_type, pointee_or_element_compiler_type); +} +lldb::LanguageType CompilerType::GetMinimumLanguage() { + if (!IsValid()) + return lldb::eLanguageTypeC; -lldb::LanguageType -CompilerType::GetMinimumLanguage () -{ - if (!IsValid()) - return lldb::eLanguageTypeC; - - return m_type_system->GetMinimumLanguage(m_type); + return m_type_system->GetMinimumLanguage(m_type); } -lldb::TypeClass -CompilerType::GetTypeClass () const -{ - if (!IsValid()) - return lldb::eTypeClassInvalid; - - return m_type_system->GetTypeClass(m_type); - +lldb::TypeClass CompilerType::GetTypeClass() const { + if (!IsValid()) + return lldb::eTypeClassInvalid; + + return m_type_system->GetTypeClass(m_type); } -void -CompilerType::SetCompilerType (TypeSystem* type_system, lldb::opaque_compiler_type_t type) -{ - m_type_system = type_system; - m_type = type; +void CompilerType::SetCompilerType(TypeSystem *type_system, + lldb::opaque_compiler_type_t type) { + m_type_system = type_system; + m_type = type; } -void -CompilerType::SetCompilerType (clang::ASTContext *ast, clang::QualType qual_type) -{ - m_type_system = ClangASTContext::GetASTContext(ast); - m_type = qual_type.getAsOpaquePtr(); +void CompilerType::SetCompilerType(clang::ASTContext *ast, + clang::QualType qual_type) { + m_type_system = ClangASTContext::GetASTContext(ast); + m_type = qual_type.getAsOpaquePtr(); } -unsigned -CompilerType::GetTypeQualifiers() const -{ - if (IsValid()) - return m_type_system->GetTypeQualifiers(m_type); - return 0; +unsigned CompilerType::GetTypeQualifiers() const { + if (IsValid()) + return m_type_system->GetTypeQualifiers(m_type); + return 0; } //---------------------------------------------------------------------- // Creating related types //---------------------------------------------------------------------- -CompilerType -CompilerType::GetArrayElementType (uint64_t *stride) const -{ - if (IsValid()) - { - return m_type_system->GetArrayElementType(m_type, stride); - } - return CompilerType(); +CompilerType CompilerType::GetArrayElementType(uint64_t *stride) const { + if (IsValid()) { + return m_type_system->GetArrayElementType(m_type, stride); + } + return CompilerType(); } -CompilerType -CompilerType::GetArrayType (uint64_t size) const -{ - if (IsValid()) - { - return m_type_system->GetArrayType(m_type, size); - } - return CompilerType(); +CompilerType CompilerType::GetArrayType(uint64_t size) const { + if (IsValid()) { + return m_type_system->GetArrayType(m_type, size); + } + return CompilerType(); } -CompilerType -CompilerType::GetCanonicalType () const -{ - if (IsValid()) - return m_type_system->GetCanonicalType(m_type); - return CompilerType(); +CompilerType CompilerType::GetCanonicalType() const { + if (IsValid()) + return m_type_system->GetCanonicalType(m_type); + return CompilerType(); } -CompilerType -CompilerType::GetFullyUnqualifiedType () const -{ - if (IsValid()) - return m_type_system->GetFullyUnqualifiedType(m_type); - return CompilerType(); +CompilerType CompilerType::GetFullyUnqualifiedType() const { + if (IsValid()) + return m_type_system->GetFullyUnqualifiedType(m_type); + return CompilerType(); } - -int -CompilerType::GetFunctionArgumentCount () const -{ - if (IsValid()) - { - return m_type_system->GetFunctionArgumentCount(m_type); - } - return -1; +int CompilerType::GetFunctionArgumentCount() const { + if (IsValid()) { + return m_type_system->GetFunctionArgumentCount(m_type); + } + return -1; } -CompilerType -CompilerType::GetFunctionArgumentTypeAtIndex (size_t idx) const -{ - if (IsValid()) - { - return m_type_system->GetFunctionArgumentTypeAtIndex(m_type, idx); - } - return CompilerType(); +CompilerType CompilerType::GetFunctionArgumentTypeAtIndex(size_t idx) const { + if (IsValid()) { + return m_type_system->GetFunctionArgumentTypeAtIndex(m_type, idx); + } + return CompilerType(); } -CompilerType -CompilerType::GetFunctionReturnType () const -{ - if (IsValid()) - { - return m_type_system->GetFunctionReturnType(m_type); - } - return CompilerType(); +CompilerType CompilerType::GetFunctionReturnType() const { + if (IsValid()) { + return m_type_system->GetFunctionReturnType(m_type); + } + return CompilerType(); } -size_t -CompilerType::GetNumMemberFunctions () const -{ - if (IsValid()) - { - return m_type_system->GetNumMemberFunctions(m_type); - } - return 0; +size_t CompilerType::GetNumMemberFunctions() const { + if (IsValid()) { + return m_type_system->GetNumMemberFunctions(m_type); + } + return 0; } -TypeMemberFunctionImpl -CompilerType::GetMemberFunctionAtIndex (size_t idx) -{ - if (IsValid()) - { - return m_type_system->GetMemberFunctionAtIndex(m_type, idx); - } - return TypeMemberFunctionImpl(); +TypeMemberFunctionImpl CompilerType::GetMemberFunctionAtIndex(size_t idx) { + if (IsValid()) { + return m_type_system->GetMemberFunctionAtIndex(m_type, idx); + } + return TypeMemberFunctionImpl(); } -CompilerType -CompilerType::GetNonReferenceType () const -{ - if (IsValid()) - return m_type_system->GetNonReferenceType(m_type); - return CompilerType(); +CompilerType CompilerType::GetNonReferenceType() const { + if (IsValid()) + return m_type_system->GetNonReferenceType(m_type); + return CompilerType(); } -CompilerType -CompilerType::GetPointeeType () const -{ - if (IsValid()) - { - return m_type_system->GetPointeeType(m_type); - } - return CompilerType(); +CompilerType CompilerType::GetPointeeType() const { + if (IsValid()) { + return m_type_system->GetPointeeType(m_type); + } + return CompilerType(); } -CompilerType -CompilerType::GetPointerType () const -{ - if (IsValid()) - { - return m_type_system->GetPointerType(m_type); - } - return CompilerType(); +CompilerType CompilerType::GetPointerType() const { + if (IsValid()) { + return m_type_system->GetPointerType(m_type); + } + return CompilerType(); } -CompilerType -CompilerType::GetLValueReferenceType () const -{ - if (IsValid()) - return m_type_system->GetLValueReferenceType(m_type); - else - return CompilerType(); +CompilerType CompilerType::GetLValueReferenceType() const { + if (IsValid()) + return m_type_system->GetLValueReferenceType(m_type); + else + return CompilerType(); } -CompilerType -CompilerType::GetRValueReferenceType () const -{ - if (IsValid()) - return m_type_system->GetRValueReferenceType(m_type); - else - return CompilerType(); +CompilerType CompilerType::GetRValueReferenceType() const { + if (IsValid()) + return m_type_system->GetRValueReferenceType(m_type); + else + return CompilerType(); } -CompilerType -CompilerType::AddConstModifier () const -{ - if (IsValid()) - return m_type_system->AddConstModifier(m_type); - else - return CompilerType(); +CompilerType CompilerType::AddConstModifier() const { + if (IsValid()) + return m_type_system->AddConstModifier(m_type); + else + return CompilerType(); } -CompilerType -CompilerType::AddVolatileModifier () const -{ - if (IsValid()) - return m_type_system->AddVolatileModifier(m_type); - else - return CompilerType(); +CompilerType CompilerType::AddVolatileModifier() const { + if (IsValid()) + return m_type_system->AddVolatileModifier(m_type); + else + return CompilerType(); } -CompilerType -CompilerType::AddRestrictModifier () const -{ - if (IsValid()) - return m_type_system->AddRestrictModifier(m_type); - else - return CompilerType(); +CompilerType CompilerType::AddRestrictModifier() const { + if (IsValid()) + return m_type_system->AddRestrictModifier(m_type); + else + return CompilerType(); } CompilerType -CompilerType::CreateTypedef (const char *name, const CompilerDeclContext &decl_ctx) const -{ - if (IsValid()) - return m_type_system->CreateTypedef(m_type, name, decl_ctx); - else - return CompilerType(); +CompilerType::CreateTypedef(const char *name, + const CompilerDeclContext &decl_ctx) const { + if (IsValid()) + return m_type_system->CreateTypedef(m_type, name, decl_ctx); + else + return CompilerType(); } -CompilerType -CompilerType::GetTypedefedType () const -{ - if (IsValid()) - return m_type_system->GetTypedefedType(m_type); - else - return CompilerType(); +CompilerType CompilerType::GetTypedefedType() const { + if (IsValid()) + return m_type_system->GetTypedefedType(m_type); + else + return CompilerType(); } //---------------------------------------------------------------------- @@ -644,192 +495,146 @@ CompilerType::GetTypedefedType () const //---------------------------------------------------------------------- CompilerType -CompilerType::GetBasicTypeFromAST (lldb::BasicType basic_type) const -{ - if (IsValid()) - return m_type_system->GetBasicTypeFromAST(basic_type); - return CompilerType(); +CompilerType::GetBasicTypeFromAST(lldb::BasicType basic_type) const { + if (IsValid()) + return m_type_system->GetBasicTypeFromAST(basic_type); + return CompilerType(); } //---------------------------------------------------------------------- // Exploring the type //---------------------------------------------------------------------- -uint64_t -CompilerType::GetBitSize (ExecutionContextScope *exe_scope) const -{ - if (IsValid()) - { - return m_type_system->GetBitSize(m_type, exe_scope); - } - return 0; +uint64_t CompilerType::GetBitSize(ExecutionContextScope *exe_scope) const { + if (IsValid()) { + return m_type_system->GetBitSize(m_type, exe_scope); + } + return 0; } -uint64_t -CompilerType::GetByteSize (ExecutionContextScope *exe_scope) const -{ - return (GetBitSize (exe_scope) + 7) / 8; +uint64_t CompilerType::GetByteSize(ExecutionContextScope *exe_scope) const { + return (GetBitSize(exe_scope) + 7) / 8; } - -size_t -CompilerType::GetTypeBitAlign () const -{ - if (IsValid()) - return m_type_system->GetTypeBitAlign(m_type); - return 0; +size_t CompilerType::GetTypeBitAlign() const { + if (IsValid()) + return m_type_system->GetTypeBitAlign(m_type); + return 0; } +lldb::Encoding CompilerType::GetEncoding(uint64_t &count) const { + if (!IsValid()) + return lldb::eEncodingInvalid; -lldb::Encoding -CompilerType::GetEncoding (uint64_t &count) const -{ - if (!IsValid()) - return lldb::eEncodingInvalid; - - return m_type_system->GetEncoding(m_type, count); -} - -lldb::Format -CompilerType::GetFormat () const -{ - if (!IsValid()) - return lldb::eFormatDefault; - - return m_type_system->GetFormat(m_type); + return m_type_system->GetEncoding(m_type, count); } -uint32_t -CompilerType::GetNumChildren (bool omit_empty_base_classes) const -{ - if (!IsValid()) - return 0; - return m_type_system->GetNumChildren(m_type, omit_empty_base_classes); -} +lldb::Format CompilerType::GetFormat() const { + if (!IsValid()) + return lldb::eFormatDefault; -lldb::BasicType -CompilerType::GetBasicTypeEnumeration () const -{ - if (IsValid()) - return m_type_system->GetBasicTypeEnumeration(m_type); - return eBasicTypeInvalid; + return m_type_system->GetFormat(m_type); } -void -CompilerType::ForEachEnumerator (std::function <bool (const CompilerType &integer_type, const ConstString &name, const llvm::APSInt &value)> const &callback) const -{ - if (IsValid()) - return m_type_system->ForEachEnumerator (m_type, callback); -} - - -uint32_t -CompilerType::GetNumFields () const -{ - if (!IsValid()) - return 0; - return m_type_system->GetNumFields(m_type); +uint32_t CompilerType::GetNumChildren(bool omit_empty_base_classes) const { + if (!IsValid()) + return 0; + return m_type_system->GetNumChildren(m_type, omit_empty_base_classes); } -CompilerType -CompilerType::GetFieldAtIndex (size_t idx, - std::string& name, - uint64_t *bit_offset_ptr, - uint32_t *bitfield_bit_size_ptr, - bool *is_bitfield_ptr) const -{ - if (!IsValid()) - return CompilerType(); - return m_type_system->GetFieldAtIndex(m_type, idx, name, bit_offset_ptr, bitfield_bit_size_ptr, is_bitfield_ptr); +lldb::BasicType CompilerType::GetBasicTypeEnumeration() const { + if (IsValid()) + return m_type_system->GetBasicTypeEnumeration(m_type); + return eBasicTypeInvalid; } -uint32_t -CompilerType::GetNumDirectBaseClasses () const -{ - if (IsValid()) - return m_type_system->GetNumDirectBaseClasses (m_type); - return 0; +void CompilerType::ForEachEnumerator( + std::function<bool(const CompilerType &integer_type, + const ConstString &name, + const llvm::APSInt &value)> const &callback) const { + if (IsValid()) + return m_type_system->ForEachEnumerator(m_type, callback); } -uint32_t -CompilerType::GetNumVirtualBaseClasses () const -{ - if (IsValid()) - return m_type_system->GetNumVirtualBaseClasses (m_type); +uint32_t CompilerType::GetNumFields() const { + if (!IsValid()) return 0; + return m_type_system->GetNumFields(m_type); } -CompilerType -CompilerType::GetDirectBaseClassAtIndex (size_t idx, uint32_t *bit_offset_ptr) const -{ - if (IsValid()) - return m_type_system->GetDirectBaseClassAtIndex (m_type, idx, bit_offset_ptr); +CompilerType CompilerType::GetFieldAtIndex(size_t idx, std::string &name, + uint64_t *bit_offset_ptr, + uint32_t *bitfield_bit_size_ptr, + bool *is_bitfield_ptr) const { + if (!IsValid()) return CompilerType(); + return m_type_system->GetFieldAtIndex(m_type, idx, name, bit_offset_ptr, + bitfield_bit_size_ptr, is_bitfield_ptr); } -CompilerType -CompilerType::GetVirtualBaseClassAtIndex (size_t idx, uint32_t *bit_offset_ptr) const -{ - if (IsValid()) - return m_type_system->GetVirtualBaseClassAtIndex (m_type, idx, bit_offset_ptr); - return CompilerType(); +uint32_t CompilerType::GetNumDirectBaseClasses() const { + if (IsValid()) + return m_type_system->GetNumDirectBaseClasses(m_type); + return 0; } -uint32_t -CompilerType::GetIndexOfFieldWithName (const char* name, - CompilerType* field_compiler_type_ptr, - uint64_t *bit_offset_ptr, - uint32_t *bitfield_bit_size_ptr, - bool *is_bitfield_ptr) const -{ - unsigned count = GetNumFields(); - std::string field_name; - for (unsigned index = 0; index < count; index++) - { - CompilerType field_compiler_type (GetFieldAtIndex(index, field_name, bit_offset_ptr, bitfield_bit_size_ptr, is_bitfield_ptr)); - if (strcmp(field_name.c_str(), name) == 0) - { - if (field_compiler_type_ptr) - *field_compiler_type_ptr = field_compiler_type; - return index; - } - } - return UINT32_MAX; +uint32_t CompilerType::GetNumVirtualBaseClasses() const { + if (IsValid()) + return m_type_system->GetNumVirtualBaseClasses(m_type); + return 0; } +CompilerType +CompilerType::GetDirectBaseClassAtIndex(size_t idx, + uint32_t *bit_offset_ptr) const { + if (IsValid()) + return m_type_system->GetDirectBaseClassAtIndex(m_type, idx, + bit_offset_ptr); + return CompilerType(); +} CompilerType -CompilerType::GetChildCompilerTypeAtIndex (ExecutionContext *exe_ctx, - size_t idx, - bool transparent_pointers, - bool omit_empty_base_classes, - bool ignore_array_bounds, - std::string& child_name, - uint32_t &child_byte_size, - int32_t &child_byte_offset, - uint32_t &child_bitfield_bit_size, - uint32_t &child_bitfield_bit_offset, - bool &child_is_base_class, - bool &child_is_deref_of_parent, - ValueObject *valobj, - uint64_t &language_flags) const -{ - if (!IsValid()) - return CompilerType(); - return m_type_system->GetChildCompilerTypeAtIndex(m_type, - exe_ctx, - idx, - transparent_pointers, - omit_empty_base_classes, - ignore_array_bounds, - child_name, - child_byte_size, - child_byte_offset, - child_bitfield_bit_size, - child_bitfield_bit_offset, - child_is_base_class, - child_is_deref_of_parent, - valobj, - language_flags); +CompilerType::GetVirtualBaseClassAtIndex(size_t idx, + uint32_t *bit_offset_ptr) const { + if (IsValid()) + return m_type_system->GetVirtualBaseClassAtIndex(m_type, idx, + bit_offset_ptr); + return CompilerType(); +} + +uint32_t CompilerType::GetIndexOfFieldWithName( + const char *name, CompilerType *field_compiler_type_ptr, + uint64_t *bit_offset_ptr, uint32_t *bitfield_bit_size_ptr, + bool *is_bitfield_ptr) const { + unsigned count = GetNumFields(); + std::string field_name; + for (unsigned index = 0; index < count; index++) { + CompilerType field_compiler_type( + GetFieldAtIndex(index, field_name, bit_offset_ptr, + bitfield_bit_size_ptr, is_bitfield_ptr)); + if (strcmp(field_name.c_str(), name) == 0) { + if (field_compiler_type_ptr) + *field_compiler_type_ptr = field_compiler_type; + return index; + } + } + return UINT32_MAX; +} + +CompilerType CompilerType::GetChildCompilerTypeAtIndex( + ExecutionContext *exe_ctx, size_t idx, bool transparent_pointers, + bool omit_empty_base_classes, bool ignore_array_bounds, + std::string &child_name, uint32_t &child_byte_size, + int32_t &child_byte_offset, uint32_t &child_bitfield_bit_size, + uint32_t &child_bitfield_bit_offset, bool &child_is_base_class, + bool &child_is_deref_of_parent, ValueObject *valobj, + uint64_t &language_flags) const { + if (!IsValid()) + return CompilerType(); + return m_type_system->GetChildCompilerTypeAtIndex( + m_type, exe_ctx, idx, transparent_pointers, omit_empty_base_classes, + ignore_array_bounds, child_name, child_byte_size, child_byte_offset, + child_bitfield_bit_size, child_bitfield_bit_offset, child_is_base_class, + child_is_deref_of_parent, valobj, language_flags); } // Look for a child member (doesn't include base classes, but it does include @@ -856,71 +661,60 @@ CompilerType::GetChildCompilerTypeAtIndex (ExecutionContext *exe_ctx, // If we have a clang type that describes "class C", and we wanted to looked // "m_b" in it: // -// With omit_empty_base_classes == false we would get an integer array back with: +// With omit_empty_base_classes == false we would get an integer array back +// with: // { 1, 1 } // The first index 1 is the child index for "class A" within class C // The second index 1 is the child index for "m_b" within class A // // With omit_empty_base_classes == true we would get an integer array back with: // { 0, 1 } -// The first index 0 is the child index for "class A" within class C (since class B doesn't have any members it doesn't count) +// The first index 0 is the child index for "class A" within class C (since +// class B doesn't have any members it doesn't count) // The second index 1 is the child index for "m_b" within class A -size_t -CompilerType::GetIndexOfChildMemberWithName (const char *name, - bool omit_empty_base_classes, - std::vector<uint32_t>& child_indexes) const -{ - if (IsValid() && name && name[0]) - { - return m_type_system->GetIndexOfChildMemberWithName(m_type, name, omit_empty_base_classes, child_indexes); - } - return 0; +size_t CompilerType::GetIndexOfChildMemberWithName( + const char *name, bool omit_empty_base_classes, + std::vector<uint32_t> &child_indexes) const { + if (IsValid() && name && name[0]) { + return m_type_system->GetIndexOfChildMemberWithName( + m_type, name, omit_empty_base_classes, child_indexes); + } + return 0; } -size_t -CompilerType::GetNumTemplateArguments () const -{ - if (IsValid()) - { - return m_type_system->GetNumTemplateArguments(m_type); - } - return 0; +size_t CompilerType::GetNumTemplateArguments() const { + if (IsValid()) { + return m_type_system->GetNumTemplateArguments(m_type); + } + return 0; } CompilerType -CompilerType::GetTemplateArgument (size_t idx, - lldb::TemplateArgumentKind &kind) const -{ - if (IsValid()) - { - return m_type_system->GetTemplateArgument(m_type, idx, kind); - } - return CompilerType(); +CompilerType::GetTemplateArgument(size_t idx, + lldb::TemplateArgumentKind &kind) const { + if (IsValid()) { + return m_type_system->GetTemplateArgument(m_type, idx, kind); + } + return CompilerType(); } -CompilerType -CompilerType::GetTypeForFormatters () const -{ - if (IsValid()) - return m_type_system->GetTypeForFormatters(m_type); - return CompilerType(); +CompilerType CompilerType::GetTypeForFormatters() const { + if (IsValid()) + return m_type_system->GetTypeForFormatters(m_type); + return CompilerType(); } -LazyBool -CompilerType::ShouldPrintAsOneLiner (ValueObject* valobj) const -{ - if (IsValid()) - return m_type_system->ShouldPrintAsOneLiner(m_type, valobj); - return eLazyBoolCalculate; +LazyBool CompilerType::ShouldPrintAsOneLiner(ValueObject *valobj) const { + if (IsValid()) + return m_type_system->ShouldPrintAsOneLiner(m_type, valobj); + return eLazyBoolCalculate; } -bool -CompilerType::IsMeaninglessWithoutDynamicResolution () const -{ - if (IsValid()) - return m_type_system->IsMeaninglessWithoutDynamicResolution(m_type); - return false; +bool CompilerType::IsMeaninglessWithoutDynamicResolution() const { + if (IsValid()) + return m_type_system->IsMeaninglessWithoutDynamicResolution(m_type); + return false; } // Get the index of the child of "clang_type" whose name matches. This function @@ -928,423 +722,351 @@ CompilerType::IsMeaninglessWithoutDynamicResolution () const // matches can include base class names. uint32_t -CompilerType::GetIndexOfChildWithName (const char *name, bool omit_empty_base_classes) const -{ - if (IsValid() && name && name[0]) - { - return m_type_system->GetIndexOfChildWithName(m_type, name, omit_empty_base_classes); - } - return UINT32_MAX; +CompilerType::GetIndexOfChildWithName(const char *name, + bool omit_empty_base_classes) const { + if (IsValid() && name && name[0]) { + return m_type_system->GetIndexOfChildWithName(m_type, name, + omit_empty_base_classes); + } + return UINT32_MAX; } -size_t -CompilerType::ConvertStringToFloatValue (const char *s, uint8_t *dst, size_t dst_size) const -{ - if (IsValid()) - return m_type_system->ConvertStringToFloatValue(m_type, s, dst, dst_size); - return 0; +size_t CompilerType::ConvertStringToFloatValue(const char *s, uint8_t *dst, + size_t dst_size) const { + if (IsValid()) + return m_type_system->ConvertStringToFloatValue(m_type, s, dst, dst_size); + return 0; } - - //---------------------------------------------------------------------- // Dumping types //---------------------------------------------------------------------- #define DEPTH_INCREMENT 2 -void -CompilerType::DumpValue (ExecutionContext *exe_ctx, - Stream *s, - lldb::Format format, - const lldb_private::DataExtractor &data, - lldb::offset_t data_byte_offset, - size_t data_byte_size, - uint32_t bitfield_bit_size, - uint32_t bitfield_bit_offset, - bool show_types, - bool show_summary, - bool verbose, - uint32_t depth) -{ - if (!IsValid()) - return; - m_type_system->DumpValue(m_type, exe_ctx, s, format, data, data_byte_offset, data_byte_size, bitfield_bit_size, bitfield_bit_offset, show_types, show_summary, verbose, depth); -} - - - - -bool -CompilerType::DumpTypeValue (Stream *s, +void CompilerType::DumpValue(ExecutionContext *exe_ctx, Stream *s, lldb::Format format, const lldb_private::DataExtractor &data, - lldb::offset_t byte_offset, - size_t byte_size, - uint32_t bitfield_bit_size, - uint32_t bitfield_bit_offset, - ExecutionContextScope *exe_scope) -{ - if (!IsValid()) - return false; - return m_type_system->DumpTypeValue(m_type, s, format, data, byte_offset, byte_size, bitfield_bit_size, bitfield_bit_offset, exe_scope); + lldb::offset_t data_byte_offset, + size_t data_byte_size, uint32_t bitfield_bit_size, + uint32_t bitfield_bit_offset, bool show_types, + bool show_summary, bool verbose, uint32_t depth) { + if (!IsValid()) + return; + m_type_system->DumpValue(m_type, exe_ctx, s, format, data, data_byte_offset, + data_byte_size, bitfield_bit_size, + bitfield_bit_offset, show_types, show_summary, + verbose, depth); +} + +bool CompilerType::DumpTypeValue(Stream *s, lldb::Format format, + const lldb_private::DataExtractor &data, + lldb::offset_t byte_offset, size_t byte_size, + uint32_t bitfield_bit_size, + uint32_t bitfield_bit_offset, + ExecutionContextScope *exe_scope) { + if (!IsValid()) + return false; + return m_type_system->DumpTypeValue(m_type, s, format, data, byte_offset, + byte_size, bitfield_bit_size, + bitfield_bit_offset, exe_scope); } - - -void -CompilerType::DumpSummary (ExecutionContext *exe_ctx, - Stream *s, - const lldb_private::DataExtractor &data, - lldb::offset_t data_byte_offset, - size_t data_byte_size) -{ - if (IsValid()) - m_type_system->DumpSummary(m_type, exe_ctx, s, data, data_byte_offset, data_byte_size); +void CompilerType::DumpSummary(ExecutionContext *exe_ctx, Stream *s, + const lldb_private::DataExtractor &data, + lldb::offset_t data_byte_offset, + size_t data_byte_size) { + if (IsValid()) + m_type_system->DumpSummary(m_type, exe_ctx, s, data, data_byte_offset, + data_byte_size); } -void -CompilerType::DumpTypeDescription () const -{ - if (IsValid()) - m_type_system->DumpTypeDescription(m_type); +void CompilerType::DumpTypeDescription() const { + if (IsValid()) + m_type_system->DumpTypeDescription(m_type); } -void -CompilerType::DumpTypeDescription (Stream *s) const -{ - if (IsValid()) - { - m_type_system->DumpTypeDescription(m_type, s); - } +void CompilerType::DumpTypeDescription(Stream *s) const { + if (IsValid()) { + m_type_system->DumpTypeDescription(m_type, s); + } } -bool -CompilerType::GetValueAsScalar (const lldb_private::DataExtractor &data, - lldb::offset_t data_byte_offset, - size_t data_byte_size, - Scalar &value) const -{ - if (!IsValid()) - return false; - - if (IsAggregateType ()) - { - return false; // Aggregate types don't have scalar values - } - else - { - uint64_t count = 0; - lldb::Encoding encoding = GetEncoding (count); - - if (encoding == lldb::eEncodingInvalid || count != 1) - return false; - - const uint64_t byte_size = GetByteSize(nullptr); - lldb::offset_t offset = data_byte_offset; - switch (encoding) - { - case lldb::eEncodingInvalid: - break; - case lldb::eEncodingVector: - break; - case lldb::eEncodingUint: - if (byte_size <= sizeof(unsigned long long)) - { - uint64_t uval64 = data.GetMaxU64 (&offset, byte_size); - if (byte_size <= sizeof(unsigned int)) - { - value = (unsigned int)uval64; - return true; - } - else if (byte_size <= sizeof(unsigned long)) - { - value = (unsigned long)uval64; - return true; - } - else if (byte_size <= sizeof(unsigned long long)) - { - value = (unsigned long long )uval64; - return true; - } - else - value.Clear(); - } - break; - - case lldb::eEncodingSint: - if (byte_size <= sizeof(long long)) - { - int64_t sval64 = data.GetMaxS64 (&offset, byte_size); - if (byte_size <= sizeof(int)) - { - value = (int)sval64; - return true; - } - else if (byte_size <= sizeof(long)) - { - value = (long)sval64; - return true; - } - else if (byte_size <= sizeof(long long)) - { - value = (long long )sval64; - return true; - } - else - value.Clear(); - } - break; - - case lldb::eEncodingIEEE754: - if (byte_size <= sizeof(long double)) - { - uint32_t u32; - uint64_t u64; - if (byte_size == sizeof(float)) - { - if (sizeof(float) == sizeof(uint32_t)) - { - u32 = data.GetU32(&offset); - value = *((float *)&u32); - return true; - } - else if (sizeof(float) == sizeof(uint64_t)) - { - u64 = data.GetU64(&offset); - value = *((float *)&u64); - return true; - } - } - else - if (byte_size == sizeof(double)) - { - if (sizeof(double) == sizeof(uint32_t)) - { - u32 = data.GetU32(&offset); - value = *((double *)&u32); - return true; - } - else if (sizeof(double) == sizeof(uint64_t)) - { - u64 = data.GetU64(&offset); - value = *((double *)&u64); - return true; - } - } - else - if (byte_size == sizeof(long double)) - { - if (sizeof(long double) == sizeof(uint32_t)) - { - u32 = data.GetU32(&offset); - value = *((long double *)&u32); - return true; - } - else if (sizeof(long double) == sizeof(uint64_t)) - { - u64 = data.GetU64(&offset); - value = *((long double *)&u64); - return true; - } - } - } - break; +bool CompilerType::GetValueAsScalar(const lldb_private::DataExtractor &data, + lldb::offset_t data_byte_offset, + size_t data_byte_size, + Scalar &value) const { + if (!IsValid()) + return false; + + if (IsAggregateType()) { + return false; // Aggregate types don't have scalar values + } else { + uint64_t count = 0; + lldb::Encoding encoding = GetEncoding(count); + + if (encoding == lldb::eEncodingInvalid || count != 1) + return false; + + const uint64_t byte_size = GetByteSize(nullptr); + lldb::offset_t offset = data_byte_offset; + switch (encoding) { + case lldb::eEncodingInvalid: + break; + case lldb::eEncodingVector: + break; + case lldb::eEncodingUint: + if (byte_size <= sizeof(unsigned long long)) { + uint64_t uval64 = data.GetMaxU64(&offset, byte_size); + if (byte_size <= sizeof(unsigned int)) { + value = (unsigned int)uval64; + return true; + } else if (byte_size <= sizeof(unsigned long)) { + value = (unsigned long)uval64; + return true; + } else if (byte_size <= sizeof(unsigned long long)) { + value = (unsigned long long)uval64; + return true; + } else + value.Clear(); + } + break; + + case lldb::eEncodingSint: + if (byte_size <= sizeof(long long)) { + int64_t sval64 = data.GetMaxS64(&offset, byte_size); + if (byte_size <= sizeof(int)) { + value = (int)sval64; + return true; + } else if (byte_size <= sizeof(long)) { + value = (long)sval64; + return true; + } else if (byte_size <= sizeof(long long)) { + value = (long long)sval64; + return true; + } else + value.Clear(); + } + break; + + case lldb::eEncodingIEEE754: + if (byte_size <= sizeof(long double)) { + uint32_t u32; + uint64_t u64; + if (byte_size == sizeof(float)) { + if (sizeof(float) == sizeof(uint32_t)) { + u32 = data.GetU32(&offset); + value = *((float *)&u32); + return true; + } else if (sizeof(float) == sizeof(uint64_t)) { + u64 = data.GetU64(&offset); + value = *((float *)&u64); + return true; + } + } else if (byte_size == sizeof(double)) { + if (sizeof(double) == sizeof(uint32_t)) { + u32 = data.GetU32(&offset); + value = *((double *)&u32); + return true; + } else if (sizeof(double) == sizeof(uint64_t)) { + u64 = data.GetU64(&offset); + value = *((double *)&u64); + return true; + } + } else if (byte_size == sizeof(long double)) { + if (sizeof(long double) == sizeof(uint32_t)) { + u32 = data.GetU32(&offset); + value = *((long double *)&u32); + return true; + } else if (sizeof(long double) == sizeof(uint64_t)) { + u64 = data.GetU64(&offset); + value = *((long double *)&u64); + return true; + } } + } + break; } - return false; + } + return false; } -bool -CompilerType::SetValueFromScalar (const Scalar &value, Stream &strm) -{ - if (!IsValid()) - return false; +bool CompilerType::SetValueFromScalar(const Scalar &value, Stream &strm) { + if (!IsValid()) + return false; - // Aggregate types don't have scalar values - if (!IsAggregateType ()) - { - strm.GetFlags().Set(Stream::eBinary); - uint64_t count = 0; - lldb::Encoding encoding = GetEncoding (count); - - if (encoding == lldb::eEncodingInvalid || count != 1) - return false; - - const uint64_t bit_width = GetBitSize(nullptr); - // This function doesn't currently handle non-byte aligned assignments - if ((bit_width % 8) != 0) - return false; - - const uint64_t byte_size = (bit_width + 7 ) / 8; - switch (encoding) - { - case lldb::eEncodingInvalid: - break; - case lldb::eEncodingVector: - break; - case lldb::eEncodingUint: - switch (byte_size) - { - case 1: strm.PutHex8(value.UInt()); return true; - case 2: strm.PutHex16(value.UInt()); return true; - case 4: strm.PutHex32(value.UInt()); return true; - case 8: strm.PutHex64(value.ULongLong()); return true; - default: - break; - } - break; - - case lldb::eEncodingSint: - switch (byte_size) - { - case 1: strm.PutHex8(value.SInt()); return true; - case 2: strm.PutHex16(value.SInt()); return true; - case 4: strm.PutHex32(value.SInt()); return true; - case 8: strm.PutHex64(value.SLongLong()); return true; - default: - break; - } - break; - - case lldb::eEncodingIEEE754: - if (byte_size <= sizeof(long double)) - { - if (byte_size == sizeof(float)) - { - strm.PutFloat(value.Float()); - return true; - } - else - if (byte_size == sizeof(double)) - { - strm.PutDouble(value.Double()); - return true; - } - else - if (byte_size == sizeof(long double)) - { - strm.PutDouble(value.LongDouble()); - return true; - } - } - break; + // Aggregate types don't have scalar values + if (!IsAggregateType()) { + strm.GetFlags().Set(Stream::eBinary); + uint64_t count = 0; + lldb::Encoding encoding = GetEncoding(count); + + if (encoding == lldb::eEncodingInvalid || count != 1) + return false; + + const uint64_t bit_width = GetBitSize(nullptr); + // This function doesn't currently handle non-byte aligned assignments + if ((bit_width % 8) != 0) + return false; + + const uint64_t byte_size = (bit_width + 7) / 8; + switch (encoding) { + case lldb::eEncodingInvalid: + break; + case lldb::eEncodingVector: + break; + case lldb::eEncodingUint: + switch (byte_size) { + case 1: + strm.PutHex8(value.UInt()); + return true; + case 2: + strm.PutHex16(value.UInt()); + return true; + case 4: + strm.PutHex32(value.UInt()); + return true; + case 8: + strm.PutHex64(value.ULongLong()); + return true; + default: + break; + } + break; + + case lldb::eEncodingSint: + switch (byte_size) { + case 1: + strm.PutHex8(value.SInt()); + return true; + case 2: + strm.PutHex16(value.SInt()); + return true; + case 4: + strm.PutHex32(value.SInt()); + return true; + case 8: + strm.PutHex64(value.SLongLong()); + return true; + default: + break; + } + break; + + case lldb::eEncodingIEEE754: + if (byte_size <= sizeof(long double)) { + if (byte_size == sizeof(float)) { + strm.PutFloat(value.Float()); + return true; + } else if (byte_size == sizeof(double)) { + strm.PutDouble(value.Double()); + return true; + } else if (byte_size == sizeof(long double)) { + strm.PutDouble(value.LongDouble()); + return true; } + } + break; } - return false; + } + return false; } -bool -CompilerType::ReadFromMemory (lldb_private::ExecutionContext *exe_ctx, - lldb::addr_t addr, - AddressType address_type, - lldb_private::DataExtractor &data) -{ - if (!IsValid()) - return false; - - // Can't convert a file address to anything valid without more - // context (which Module it came from) - if (address_type == eAddressTypeFile) - return false; - - if (!GetCompleteType()) - return false; - - const uint64_t byte_size = GetByteSize(exe_ctx ? exe_ctx->GetBestExecutionContextScope() : NULL); - if (data.GetByteSize() < byte_size) - { - lldb::DataBufferSP data_sp(new DataBufferHeap (byte_size, '\0')); - data.SetData(data_sp); - } - - uint8_t* dst = const_cast<uint8_t*>(data.PeekData(0, byte_size)); - if (dst != nullptr) - { - if (address_type == eAddressTypeHost) - { - if (addr == 0) - return false; - // The address is an address in this process, so just copy it - memcpy (dst, (uint8_t*)nullptr + addr, byte_size); - return true; - } - else - { - Process *process = nullptr; - if (exe_ctx) - process = exe_ctx->GetProcessPtr(); - if (process) - { - Error error; - return process->ReadMemory(addr, dst, byte_size, error) == byte_size; - } - } - } +bool CompilerType::ReadFromMemory(lldb_private::ExecutionContext *exe_ctx, + lldb::addr_t addr, AddressType address_type, + lldb_private::DataExtractor &data) { + if (!IsValid()) return false; -} -bool -CompilerType::WriteToMemory (lldb_private::ExecutionContext *exe_ctx, - lldb::addr_t addr, - AddressType address_type, - StreamString &new_value) -{ - if (!IsValid()) - return false; - - // Can't convert a file address to anything valid without more - // context (which Module it came from) - if (address_type == eAddressTypeFile) - return false; - - if (!GetCompleteType()) + // Can't convert a file address to anything valid without more + // context (which Module it came from) + if (address_type == eAddressTypeFile) + return false; + + if (!GetCompleteType()) + return false; + + const uint64_t byte_size = + GetByteSize(exe_ctx ? exe_ctx->GetBestExecutionContextScope() : NULL); + if (data.GetByteSize() < byte_size) { + lldb::DataBufferSP data_sp(new DataBufferHeap(byte_size, '\0')); + data.SetData(data_sp); + } + + uint8_t *dst = const_cast<uint8_t *>(data.PeekData(0, byte_size)); + if (dst != nullptr) { + if (address_type == eAddressTypeHost) { + if (addr == 0) return false; - - const uint64_t byte_size = GetByteSize(exe_ctx ? exe_ctx->GetBestExecutionContextScope() : NULL); - - if (byte_size > 0) - { - if (address_type == eAddressTypeHost) - { - // The address is an address in this process, so just copy it - memcpy ((void *)addr, new_value.GetData(), byte_size); - return true; - } - else - { - Process *process = nullptr; - if (exe_ctx) - process = exe_ctx->GetProcessPtr(); - if (process) - { - Error error; - return process->WriteMemory(addr, new_value.GetData(), byte_size, error) == byte_size; - } - } + // The address is an address in this process, so just copy it + memcpy(dst, (uint8_t *)nullptr + addr, byte_size); + return true; + } else { + Process *process = nullptr; + if (exe_ctx) + process = exe_ctx->GetProcessPtr(); + if (process) { + Error error; + return process->ReadMemory(addr, dst, byte_size, error) == byte_size; + } } + } + return false; +} + +bool CompilerType::WriteToMemory(lldb_private::ExecutionContext *exe_ctx, + lldb::addr_t addr, AddressType address_type, + StreamString &new_value) { + if (!IsValid()) + return false; + + // Can't convert a file address to anything valid without more + // context (which Module it came from) + if (address_type == eAddressTypeFile) + return false; + + if (!GetCompleteType()) return false; + + const uint64_t byte_size = + GetByteSize(exe_ctx ? exe_ctx->GetBestExecutionContextScope() : NULL); + + if (byte_size > 0) { + if (address_type == eAddressTypeHost) { + // The address is an address in this process, so just copy it + memcpy((void *)addr, new_value.GetData(), byte_size); + return true; + } else { + Process *process = nullptr; + if (exe_ctx) + process = exe_ctx->GetProcessPtr(); + if (process) { + Error error; + return process->WriteMemory(addr, new_value.GetData(), byte_size, + error) == byte_size; + } + } + } + return false; } -//clang::CXXRecordDecl * -//CompilerType::GetAsCXXRecordDecl (lldb::opaque_compiler_type_t opaque_compiler_qual_type) +// clang::CXXRecordDecl * +// CompilerType::GetAsCXXRecordDecl (lldb::opaque_compiler_type_t +// opaque_compiler_qual_type) //{ // if (opaque_compiler_qual_type) -// return clang::QualType::getFromOpaquePtr(opaque_compiler_qual_type)->getAsCXXRecordDecl(); +// return +// clang::QualType::getFromOpaquePtr(opaque_compiler_qual_type)->getAsCXXRecordDecl(); // return NULL; //} -bool -lldb_private::operator == (const lldb_private::CompilerType &lhs, const lldb_private::CompilerType &rhs) -{ - return lhs.GetTypeSystem() == rhs.GetTypeSystem() && lhs.GetOpaqueQualType() == rhs.GetOpaqueQualType(); +bool lldb_private::operator==(const lldb_private::CompilerType &lhs, + const lldb_private::CompilerType &rhs) { + return lhs.GetTypeSystem() == rhs.GetTypeSystem() && + lhs.GetOpaqueQualType() == rhs.GetOpaqueQualType(); } - -bool -lldb_private::operator != (const lldb_private::CompilerType &lhs, const lldb_private::CompilerType &rhs) -{ - return lhs.GetTypeSystem() != rhs.GetTypeSystem() || lhs.GetOpaqueQualType() != rhs.GetOpaqueQualType(); +bool lldb_private::operator!=(const lldb_private::CompilerType &lhs, + const lldb_private::CompilerType &rhs) { + return lhs.GetTypeSystem() != rhs.GetTypeSystem() || + lhs.GetOpaqueQualType() != rhs.GetOpaqueQualType(); } - - - diff --git a/lldb/source/Symbol/DWARFCallFrameInfo.cpp b/lldb/source/Symbol/DWARFCallFrameInfo.cpp index 5318327318e..9504ea18423 100644 --- a/lldb/source/Symbol/DWARFCallFrameInfo.cpp +++ b/lldb/source/Symbol/DWARFCallFrameInfo.cpp @@ -7,16 +7,15 @@ // //===----------------------------------------------------------------------===// - // C Includes // C++ Includes #include <list> -#include "lldb/Core/Log.h" -#include "lldb/Core/Section.h" #include "lldb/Core/ArchSpec.h" +#include "lldb/Core/Log.h" #include "lldb/Core/Module.h" #include "lldb/Core/Section.h" +#include "lldb/Core/Section.h" #include "lldb/Core/Timer.h" #include "lldb/Host/Host.h" #include "lldb/Symbol/DWARFCallFrameInfo.h" @@ -28,920 +27,913 @@ using namespace lldb; using namespace lldb_private; -DWARFCallFrameInfo::DWARFCallFrameInfo(ObjectFile& objfile, SectionSP& section_sp, lldb::RegisterKind reg_kind, bool is_eh_frame) : - m_objfile (objfile), - m_section_sp (section_sp), - m_reg_kind (reg_kind), // The flavor of registers that the CFI data uses (enum RegisterKind) - m_flags (), - m_cie_map (), - m_cfi_data (), - m_cfi_data_initialized (false), - m_fde_index (), - m_fde_index_initialized (false), - m_is_eh_frame (is_eh_frame) -{ -} +DWARFCallFrameInfo::DWARFCallFrameInfo(ObjectFile &objfile, + SectionSP §ion_sp, + lldb::RegisterKind reg_kind, + bool is_eh_frame) + : m_objfile(objfile), m_section_sp(section_sp), + m_reg_kind(reg_kind), // The flavor of registers that the CFI data uses + // (enum RegisterKind) + m_flags(), m_cie_map(), m_cfi_data(), m_cfi_data_initialized(false), + m_fde_index(), m_fde_index_initialized(false), + m_is_eh_frame(is_eh_frame) {} + +DWARFCallFrameInfo::~DWARFCallFrameInfo() {} + +bool DWARFCallFrameInfo::GetUnwindPlan(Address addr, UnwindPlan &unwind_plan) { + FDEEntryMap::Entry fde_entry; + + // Make sure that the Address we're searching for is the same object file + // as this DWARFCallFrameInfo, we only store File offsets in m_fde_index. + ModuleSP module_sp = addr.GetModule(); + if (module_sp.get() == nullptr || module_sp->GetObjectFile() == nullptr || + module_sp->GetObjectFile() != &m_objfile) + return false; -DWARFCallFrameInfo::~DWARFCallFrameInfo() -{ + if (GetFDEEntryByFileAddress(addr.GetFileAddress(), fde_entry) == false) + return false; + return FDEToUnwindPlan(fde_entry.data, addr, unwind_plan); } +bool DWARFCallFrameInfo::GetAddressRange(Address addr, AddressRange &range) { -bool -DWARFCallFrameInfo::GetUnwindPlan (Address addr, UnwindPlan& unwind_plan) -{ - FDEEntryMap::Entry fde_entry; - - // Make sure that the Address we're searching for is the same object file - // as this DWARFCallFrameInfo, we only store File offsets in m_fde_index. - ModuleSP module_sp = addr.GetModule(); - if (module_sp.get() == nullptr || module_sp->GetObjectFile() == nullptr || module_sp->GetObjectFile() != &m_objfile) - return false; + // Make sure that the Address we're searching for is the same object file + // as this DWARFCallFrameInfo, we only store File offsets in m_fde_index. + ModuleSP module_sp = addr.GetModule(); + if (module_sp.get() == nullptr || module_sp->GetObjectFile() == nullptr || + module_sp->GetObjectFile() != &m_objfile) + return false; - if (GetFDEEntryByFileAddress (addr.GetFileAddress(), fde_entry) == false) - return false; - return FDEToUnwindPlan (fde_entry.data, addr, unwind_plan); -} + if (m_section_sp.get() == nullptr || m_section_sp->IsEncrypted()) + return false; + GetFDEIndex(); + FDEEntryMap::Entry *fde_entry = + m_fde_index.FindEntryThatContains(addr.GetFileAddress()); + if (!fde_entry) + return false; -bool -DWARFCallFrameInfo::GetAddressRange (Address addr, AddressRange &range) -{ - - // Make sure that the Address we're searching for is the same object file - // as this DWARFCallFrameInfo, we only store File offsets in m_fde_index. - ModuleSP module_sp = addr.GetModule(); - if (module_sp.get() == nullptr || module_sp->GetObjectFile() == nullptr || module_sp->GetObjectFile() != &m_objfile) - return false; - - if (m_section_sp.get() == nullptr || m_section_sp->IsEncrypted()) - return false; - GetFDEIndex(); - FDEEntryMap::Entry *fde_entry = m_fde_index.FindEntryThatContains (addr.GetFileAddress()); - if (!fde_entry) - return false; - - range = AddressRange(fde_entry->base, fde_entry->size, m_objfile.GetSectionList()); - return true; + range = AddressRange(fde_entry->base, fde_entry->size, + m_objfile.GetSectionList()); + return true; } -bool -DWARFCallFrameInfo::GetFDEEntryByFileAddress (addr_t file_addr, FDEEntryMap::Entry &fde_entry) -{ - if (m_section_sp.get() == nullptr || m_section_sp->IsEncrypted()) - return false; +bool DWARFCallFrameInfo::GetFDEEntryByFileAddress( + addr_t file_addr, FDEEntryMap::Entry &fde_entry) { + if (m_section_sp.get() == nullptr || m_section_sp->IsEncrypted()) + return false; - GetFDEIndex(); + GetFDEIndex(); - if (m_fde_index.IsEmpty()) - return false; + if (m_fde_index.IsEmpty()) + return false; - FDEEntryMap::Entry *fde = m_fde_index.FindEntryThatContains (file_addr); + FDEEntryMap::Entry *fde = m_fde_index.FindEntryThatContains(file_addr); - if (fde == nullptr) - return false; + if (fde == nullptr) + return false; - fde_entry = *fde; - return true; + fde_entry = *fde; + return true; } -void -DWARFCallFrameInfo::GetFunctionAddressAndSizeVector (FunctionAddressAndSizeVector &function_info) -{ - GetFDEIndex(); - const size_t count = m_fde_index.GetSize(); - function_info.Clear(); - if (count > 0) - function_info.Reserve(count); - for (size_t i = 0; i < count; ++i) - { - const FDEEntryMap::Entry *func_offset_data_entry = m_fde_index.GetEntryAtIndex (i); - if (func_offset_data_entry) - { - FunctionAddressAndSizeVector::Entry function_offset_entry (func_offset_data_entry->base, func_offset_data_entry->size); - function_info.Append (function_offset_entry); - } +void DWARFCallFrameInfo::GetFunctionAddressAndSizeVector( + FunctionAddressAndSizeVector &function_info) { + GetFDEIndex(); + const size_t count = m_fde_index.GetSize(); + function_info.Clear(); + if (count > 0) + function_info.Reserve(count); + for (size_t i = 0; i < count; ++i) { + const FDEEntryMap::Entry *func_offset_data_entry = + m_fde_index.GetEntryAtIndex(i); + if (func_offset_data_entry) { + FunctionAddressAndSizeVector::Entry function_offset_entry( + func_offset_data_entry->base, func_offset_data_entry->size); + function_info.Append(function_offset_entry); } + } } -const DWARFCallFrameInfo::CIE* -DWARFCallFrameInfo::GetCIE(dw_offset_t cie_offset) -{ - cie_map_t::iterator pos = m_cie_map.find(cie_offset); +const DWARFCallFrameInfo::CIE * +DWARFCallFrameInfo::GetCIE(dw_offset_t cie_offset) { + cie_map_t::iterator pos = m_cie_map.find(cie_offset); - if (pos != m_cie_map.end()) - { - // Parse and cache the CIE - if (pos->second.get() == nullptr) - pos->second = ParseCIE (cie_offset); + if (pos != m_cie_map.end()) { + // Parse and cache the CIE + if (pos->second.get() == nullptr) + pos->second = ParseCIE(cie_offset); - return pos->second.get(); - } - return nullptr; + return pos->second.get(); + } + return nullptr; } DWARFCallFrameInfo::CIESP -DWARFCallFrameInfo::ParseCIE (const dw_offset_t cie_offset) -{ - CIESP cie_sp(new CIE(cie_offset)); - lldb::offset_t offset = cie_offset; - if (m_cfi_data_initialized == false) - GetCFIData(); - uint32_t length = m_cfi_data.GetU32(&offset); - dw_offset_t cie_id, end_offset; - bool is_64bit = (length == UINT32_MAX); - if (is_64bit) { - length = m_cfi_data.GetU64(&offset); - cie_id = m_cfi_data.GetU64(&offset); - end_offset = cie_offset + length + 12; - } else { - cie_id = m_cfi_data.GetU32(&offset); - end_offset = cie_offset + length + 4; +DWARFCallFrameInfo::ParseCIE(const dw_offset_t cie_offset) { + CIESP cie_sp(new CIE(cie_offset)); + lldb::offset_t offset = cie_offset; + if (m_cfi_data_initialized == false) + GetCFIData(); + uint32_t length = m_cfi_data.GetU32(&offset); + dw_offset_t cie_id, end_offset; + bool is_64bit = (length == UINT32_MAX); + if (is_64bit) { + length = m_cfi_data.GetU64(&offset); + cie_id = m_cfi_data.GetU64(&offset); + end_offset = cie_offset + length + 12; + } else { + cie_id = m_cfi_data.GetU32(&offset); + end_offset = cie_offset + length + 4; + } + if (length > 0 && ((!m_is_eh_frame && cie_id == UINT32_MAX) || + (m_is_eh_frame && cie_id == 0ul))) { + size_t i; + // cie.offset = cie_offset; + // cie.length = length; + // cie.cieID = cieID; + cie_sp->ptr_encoding = DW_EH_PE_absptr; // default + cie_sp->version = m_cfi_data.GetU8(&offset); + + for (i = 0; i < CFI_AUG_MAX_SIZE; ++i) { + cie_sp->augmentation[i] = m_cfi_data.GetU8(&offset); + if (cie_sp->augmentation[i] == '\0') { + // Zero out remaining bytes in augmentation string + for (size_t j = i + 1; j < CFI_AUG_MAX_SIZE; ++j) + cie_sp->augmentation[j] = '\0'; + + break; + } } - if (length > 0 && ((!m_is_eh_frame && cie_id == UINT32_MAX) || (m_is_eh_frame && cie_id == 0ul))) - { - size_t i; - // cie.offset = cie_offset; - // cie.length = length; - // cie.cieID = cieID; - cie_sp->ptr_encoding = DW_EH_PE_absptr; // default - cie_sp->version = m_cfi_data.GetU8(&offset); - - for (i=0; i<CFI_AUG_MAX_SIZE; ++i) - { - cie_sp->augmentation[i] = m_cfi_data.GetU8(&offset); - if (cie_sp->augmentation[i] == '\0') - { - // Zero out remaining bytes in augmentation string - for (size_t j = i+1; j<CFI_AUG_MAX_SIZE; ++j) - cie_sp->augmentation[j] = '\0'; - break; - } - } - - if (i == CFI_AUG_MAX_SIZE && cie_sp->augmentation[CFI_AUG_MAX_SIZE-1] != '\0') - { - Host::SystemLog (Host::eSystemLogError, "CIE parse error: CIE augmentation string was too large for the fixed sized buffer of %d bytes.\n", CFI_AUG_MAX_SIZE); - return cie_sp; - } - cie_sp->code_align = (uint32_t)m_cfi_data.GetULEB128(&offset); - cie_sp->data_align = (int32_t)m_cfi_data.GetSLEB128(&offset); - cie_sp->return_addr_reg_num = m_cfi_data.GetU8(&offset); + if (i == CFI_AUG_MAX_SIZE && + cie_sp->augmentation[CFI_AUG_MAX_SIZE - 1] != '\0') { + Host::SystemLog(Host::eSystemLogError, + "CIE parse error: CIE augmentation string was too large " + "for the fixed sized buffer of %d bytes.\n", + CFI_AUG_MAX_SIZE); + return cie_sp; + } + cie_sp->code_align = (uint32_t)m_cfi_data.GetULEB128(&offset); + cie_sp->data_align = (int32_t)m_cfi_data.GetSLEB128(&offset); + cie_sp->return_addr_reg_num = m_cfi_data.GetU8(&offset); + + if (cie_sp->augmentation[0]) { + // Get the length of the eh_frame augmentation data + // which starts with a ULEB128 length in bytes + const size_t aug_data_len = (size_t)m_cfi_data.GetULEB128(&offset); + const size_t aug_data_end = offset + aug_data_len; + const size_t aug_str_len = strlen(cie_sp->augmentation); + // A 'z' may be present as the first character of the string. + // If present, the Augmentation Data field shall be present. + // The contents of the Augmentation Data shall be interpreted + // according to other characters in the Augmentation String. + if (cie_sp->augmentation[0] == 'z') { + // Extract the Augmentation Data + size_t aug_str_idx = 0; + for (aug_str_idx = 1; aug_str_idx < aug_str_len; aug_str_idx++) { + char aug = cie_sp->augmentation[aug_str_idx]; + switch (aug) { + case 'L': + // Indicates the presence of one argument in the + // Augmentation Data of the CIE, and a corresponding + // argument in the Augmentation Data of the FDE. The + // argument in the Augmentation Data of the CIE is + // 1-byte and represents the pointer encoding used + // for the argument in the Augmentation Data of the + // FDE, which is the address of a language-specific + // data area (LSDA). The size of the LSDA pointer is + // specified by the pointer encoding used. + cie_sp->lsda_addr_encoding = m_cfi_data.GetU8(&offset); + break; - if (cie_sp->augmentation[0]) - { - // Get the length of the eh_frame augmentation data - // which starts with a ULEB128 length in bytes - const size_t aug_data_len = (size_t)m_cfi_data.GetULEB128(&offset); - const size_t aug_data_end = offset + aug_data_len; - const size_t aug_str_len = strlen(cie_sp->augmentation); - // A 'z' may be present as the first character of the string. - // If present, the Augmentation Data field shall be present. - // The contents of the Augmentation Data shall be interpreted - // according to other characters in the Augmentation String. - if (cie_sp->augmentation[0] == 'z') - { - // Extract the Augmentation Data - size_t aug_str_idx = 0; - for (aug_str_idx = 1; aug_str_idx < aug_str_len; aug_str_idx++) - { - char aug = cie_sp->augmentation[aug_str_idx]; - switch (aug) - { - case 'L': - // Indicates the presence of one argument in the - // Augmentation Data of the CIE, and a corresponding - // argument in the Augmentation Data of the FDE. The - // argument in the Augmentation Data of the CIE is - // 1-byte and represents the pointer encoding used - // for the argument in the Augmentation Data of the - // FDE, which is the address of a language-specific - // data area (LSDA). The size of the LSDA pointer is - // specified by the pointer encoding used. - cie_sp->lsda_addr_encoding = m_cfi_data.GetU8(&offset); - break; - - case 'P': - // Indicates the presence of two arguments in the - // Augmentation Data of the CIE. The first argument - // is 1-byte and represents the pointer encoding - // used for the second argument, which is the - // address of a personality routine handler. The - // size of the personality routine pointer is - // specified by the pointer encoding used. - // - // The address of the personality function will - // be stored at this location. Pre-execution, it - // will be all zero's so don't read it until we're - // trying to do an unwind & the reloc has been - // resolved. - { - uint8_t arg_ptr_encoding = m_cfi_data.GetU8(&offset); - const lldb::addr_t pc_rel_addr = m_section_sp->GetFileAddress(); - cie_sp->personality_loc = m_cfi_data.GetGNUEHPointer(&offset, arg_ptr_encoding, pc_rel_addr, LLDB_INVALID_ADDRESS, LLDB_INVALID_ADDRESS); - } - break; - - case 'R': - // A 'R' may be present at any position after the - // first character of the string. The Augmentation - // Data shall include a 1 byte argument that - // represents the pointer encoding for the address - // pointers used in the FDE. - // Example: 0x1B == DW_EH_PE_pcrel | DW_EH_PE_sdata4 - cie_sp->ptr_encoding = m_cfi_data.GetU8(&offset); - break; - } - } - } - else if (strcmp(cie_sp->augmentation, "eh") == 0) + case 'P': + // Indicates the presence of two arguments in the + // Augmentation Data of the CIE. The first argument + // is 1-byte and represents the pointer encoding + // used for the second argument, which is the + // address of a personality routine handler. The + // size of the personality routine pointer is + // specified by the pointer encoding used. + // + // The address of the personality function will + // be stored at this location. Pre-execution, it + // will be all zero's so don't read it until we're + // trying to do an unwind & the reloc has been + // resolved. { - // If the Augmentation string has the value "eh", then - // the EH Data field shall be present + uint8_t arg_ptr_encoding = m_cfi_data.GetU8(&offset); + const lldb::addr_t pc_rel_addr = m_section_sp->GetFileAddress(); + cie_sp->personality_loc = m_cfi_data.GetGNUEHPointer( + &offset, arg_ptr_encoding, pc_rel_addr, LLDB_INVALID_ADDRESS, + LLDB_INVALID_ADDRESS); } + break; - // Set the offset to be the end of the augmentation data just in case - // we didn't understand any of the data. - offset = (uint32_t)aug_data_end; - } - - if (end_offset > offset) - { - cie_sp->inst_offset = offset; - cie_sp->inst_length = end_offset - offset; + case 'R': + // A 'R' may be present at any position after the + // first character of the string. The Augmentation + // Data shall include a 1 byte argument that + // represents the pointer encoding for the address + // pointers used in the FDE. + // Example: 0x1B == DW_EH_PE_pcrel | DW_EH_PE_sdata4 + cie_sp->ptr_encoding = m_cfi_data.GetU8(&offset); + break; + } } - while (offset < end_offset) - { - uint8_t inst = m_cfi_data.GetU8(&offset); - uint8_t primary_opcode = inst & 0xC0; - uint8_t extended_opcode = inst & 0x3F; + } else if (strcmp(cie_sp->augmentation, "eh") == 0) { + // If the Augmentation string has the value "eh", then + // the EH Data field shall be present + } + + // Set the offset to be the end of the augmentation data just in case + // we didn't understand any of the data. + offset = (uint32_t)aug_data_end; + } - if (!HandleCommonDwarfOpcode(primary_opcode, extended_opcode, cie_sp->data_align, offset, cie_sp->initial_row)) - break; // Stop if we hit an unrecognized opcode - } + if (end_offset > offset) { + cie_sp->inst_offset = offset; + cie_sp->inst_length = end_offset - offset; + } + while (offset < end_offset) { + uint8_t inst = m_cfi_data.GetU8(&offset); + uint8_t primary_opcode = inst & 0xC0; + uint8_t extended_opcode = inst & 0x3F; + + if (!HandleCommonDwarfOpcode(primary_opcode, extended_opcode, + cie_sp->data_align, offset, + cie_sp->initial_row)) + break; // Stop if we hit an unrecognized opcode } + } - return cie_sp; + return cie_sp; } -void -DWARFCallFrameInfo::GetCFIData() -{ - if (m_cfi_data_initialized == false) - { - Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND)); - if (log) - m_objfile.GetModule()->LogMessage(log, "Reading EH frame info"); - m_objfile.ReadSectionData (m_section_sp.get(), m_cfi_data); - m_cfi_data_initialized = true; - } +void DWARFCallFrameInfo::GetCFIData() { + if (m_cfi_data_initialized == false) { + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_UNWIND)); + if (log) + m_objfile.GetModule()->LogMessage(log, "Reading EH frame info"); + m_objfile.ReadSectionData(m_section_sp.get(), m_cfi_data); + m_cfi_data_initialized = true; + } } -// Scan through the eh_frame or debug_frame section looking for FDEs and noting the start/end addresses -// of the functions and a pointer back to the function's FDE for later expansion. +// Scan through the eh_frame or debug_frame section looking for FDEs and noting +// the start/end addresses +// of the functions and a pointer back to the function's FDE for later +// expansion. // Internalize CIEs as we come across them. -void -DWARFCallFrameInfo::GetFDEIndex () -{ - if (m_section_sp.get() == nullptr || m_section_sp->IsEncrypted()) - return; - - if (m_fde_index_initialized) - return; - - std::lock_guard<std::mutex> guard(m_fde_index_mutex); +void DWARFCallFrameInfo::GetFDEIndex() { + if (m_section_sp.get() == nullptr || m_section_sp->IsEncrypted()) + return; + + if (m_fde_index_initialized) + return; + + std::lock_guard<std::mutex> guard(m_fde_index_mutex); + + if (m_fde_index_initialized) // if two threads hit the locker + return; + + Timer scoped_timer(LLVM_PRETTY_FUNCTION, "%s - %s", LLVM_PRETTY_FUNCTION, + m_objfile.GetFileSpec().GetFilename().AsCString("")); + + bool clear_address_zeroth_bit = false; + ArchSpec arch; + if (m_objfile.GetArchitecture(arch)) { + if (arch.GetTriple().getArch() == llvm::Triple::arm || + arch.GetTriple().getArch() == llvm::Triple::thumb) + clear_address_zeroth_bit = true; + } + + lldb::offset_t offset = 0; + if (m_cfi_data_initialized == false) + GetCFIData(); + while (m_cfi_data.ValidOffsetForDataOfSize(offset, 8)) { + const dw_offset_t current_entry = offset; + dw_offset_t cie_id, next_entry, cie_offset; + uint32_t len = m_cfi_data.GetU32(&offset); + bool is_64bit = (len == UINT32_MAX); + if (is_64bit) { + len = m_cfi_data.GetU64(&offset); + cie_id = m_cfi_data.GetU64(&offset); + next_entry = current_entry + len + 12; + cie_offset = current_entry + 12 - cie_id; + } else { + cie_id = m_cfi_data.GetU32(&offset); + next_entry = current_entry + len + 4; + cie_offset = current_entry + 4 - cie_id; + } - if (m_fde_index_initialized) // if two threads hit the locker - return; + if (next_entry > m_cfi_data.GetByteSize() + 1) { + Host::SystemLog(Host::eSystemLogError, "error: Invalid fde/cie next " + "entry offset of 0x%x found in " + "cie/fde at 0x%x\n", + next_entry, current_entry); + // Don't trust anything in this eh_frame section if we find blatantly + // invalid data. + m_fde_index.Clear(); + m_fde_index_initialized = true; + return; + } + if (cie_offset > m_cfi_data.GetByteSize()) { + Host::SystemLog( + Host::eSystemLogError, + "error: Invalid cie offset of 0x%x found in cie/fde at 0x%x\n", + cie_offset, current_entry); + // Don't trust anything in this eh_frame section if we find blatantly + // invalid data. + m_fde_index.Clear(); + m_fde_index_initialized = true; + return; + } - Timer scoped_timer (LLVM_PRETTY_FUNCTION, "%s - %s", LLVM_PRETTY_FUNCTION, m_objfile.GetFileSpec().GetFilename().AsCString("")); + if (cie_id == 0 || cie_id == UINT32_MAX || len == 0) { + m_cie_map[current_entry] = ParseCIE(current_entry); + offset = next_entry; + continue; + } - bool clear_address_zeroth_bit = false; - ArchSpec arch; - if (m_objfile.GetArchitecture (arch)) - { - if (arch.GetTriple().getArch() == llvm::Triple::arm || arch.GetTriple().getArch() == llvm::Triple::thumb) - clear_address_zeroth_bit = true; + const CIE *cie = GetCIE(cie_offset); + if (cie) { + const lldb::addr_t pc_rel_addr = m_section_sp->GetFileAddress(); + const lldb::addr_t text_addr = LLDB_INVALID_ADDRESS; + const lldb::addr_t data_addr = LLDB_INVALID_ADDRESS; + + lldb::addr_t addr = m_cfi_data.GetGNUEHPointer( + &offset, cie->ptr_encoding, pc_rel_addr, text_addr, data_addr); + if (clear_address_zeroth_bit) + addr &= ~1ull; + + lldb::addr_t length = m_cfi_data.GetGNUEHPointer( + &offset, cie->ptr_encoding & DW_EH_PE_MASK_ENCODING, pc_rel_addr, + text_addr, data_addr); + FDEEntryMap::Entry fde(addr, length, current_entry); + m_fde_index.Append(fde); + } else { + Host::SystemLog(Host::eSystemLogError, "error: unable to find CIE at " + "0x%8.8x for cie_id = 0x%8.8x for " + "entry at 0x%8.8x.\n", + cie_offset, cie_id, current_entry); } + offset = next_entry; + } + m_fde_index.Sort(); + m_fde_index_initialized = true; +} - lldb::offset_t offset = 0; - if (m_cfi_data_initialized == false) - GetCFIData(); - while (m_cfi_data.ValidOffsetForDataOfSize (offset, 8)) - { - const dw_offset_t current_entry = offset; - dw_offset_t cie_id, next_entry, cie_offset; - uint32_t len = m_cfi_data.GetU32 (&offset); - bool is_64bit = (len == UINT32_MAX); - if (is_64bit) { - len = m_cfi_data.GetU64 (&offset); - cie_id = m_cfi_data.GetU64 (&offset); - next_entry = current_entry + len + 12; - cie_offset = current_entry + 12 - cie_id; - } else { - cie_id = m_cfi_data.GetU32 (&offset); - next_entry = current_entry + len + 4; - cie_offset = current_entry + 4 - cie_id; +bool DWARFCallFrameInfo::FDEToUnwindPlan(dw_offset_t dwarf_offset, + Address startaddr, + UnwindPlan &unwind_plan) { + Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_UNWIND); + lldb::offset_t offset = dwarf_offset; + lldb::offset_t current_entry = offset; + + if (m_section_sp.get() == nullptr || m_section_sp->IsEncrypted()) + return false; + + if (m_cfi_data_initialized == false) + GetCFIData(); + + uint32_t length = m_cfi_data.GetU32(&offset); + dw_offset_t cie_offset; + bool is_64bit = (length == UINT32_MAX); + if (is_64bit) { + length = m_cfi_data.GetU64(&offset); + cie_offset = m_cfi_data.GetU64(&offset); + } else { + cie_offset = m_cfi_data.GetU32(&offset); + } + + assert(cie_offset != 0 && cie_offset != UINT32_MAX); + + // Translate the CIE_id from the eh_frame format, which + // is relative to the FDE offset, into a __eh_frame section + // offset + if (m_is_eh_frame) { + unwind_plan.SetSourceName("eh_frame CFI"); + cie_offset = current_entry + (is_64bit ? 12 : 4) - cie_offset; + unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolNo); + } else { + unwind_plan.SetSourceName("DWARF CFI"); + // In theory the debug_frame info should be valid at all call sites + // ("asynchronous unwind info" as it is sometimes called) but in practice + // gcc et al all emit call frame info for the prologue and call sites, but + // not for the epilogue or all the other locations during the function + // reliably. + unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolNo); + } + unwind_plan.SetSourcedFromCompiler(eLazyBoolYes); + + const CIE *cie = GetCIE(cie_offset); + assert(cie != nullptr); + + const dw_offset_t end_offset = current_entry + length + (is_64bit ? 12 : 4); + + const lldb::addr_t pc_rel_addr = m_section_sp->GetFileAddress(); + const lldb::addr_t text_addr = LLDB_INVALID_ADDRESS; + const lldb::addr_t data_addr = LLDB_INVALID_ADDRESS; + lldb::addr_t range_base = m_cfi_data.GetGNUEHPointer( + &offset, cie->ptr_encoding, pc_rel_addr, text_addr, data_addr); + lldb::addr_t range_len = m_cfi_data.GetGNUEHPointer( + &offset, cie->ptr_encoding & DW_EH_PE_MASK_ENCODING, pc_rel_addr, + text_addr, data_addr); + AddressRange range(range_base, m_objfile.GetAddressByteSize(), + m_objfile.GetSectionList()); + range.SetByteSize(range_len); + + addr_t lsda_data_file_address = LLDB_INVALID_ADDRESS; + + if (cie->augmentation[0] == 'z') { + uint32_t aug_data_len = (uint32_t)m_cfi_data.GetULEB128(&offset); + if (aug_data_len != 0 && cie->lsda_addr_encoding != DW_EH_PE_omit) { + offset_t saved_offset = offset; + lsda_data_file_address = m_cfi_data.GetGNUEHPointer( + &offset, cie->lsda_addr_encoding, pc_rel_addr, text_addr, data_addr); + if (offset - saved_offset != aug_data_len) { + // There is more in the augmentation region than we know how to process; + // don't read anything. + lsda_data_file_address = LLDB_INVALID_ADDRESS; + } + offset = saved_offset; + } + offset += aug_data_len; + } + Address lsda_data; + Address personality_function_ptr; + + if (lsda_data_file_address != LLDB_INVALID_ADDRESS && + cie->personality_loc != LLDB_INVALID_ADDRESS) { + m_objfile.GetModule()->ResolveFileAddress(lsda_data_file_address, + lsda_data); + m_objfile.GetModule()->ResolveFileAddress(cie->personality_loc, + personality_function_ptr); + } + + if (lsda_data.IsValid() && personality_function_ptr.IsValid()) { + unwind_plan.SetLSDAAddress(lsda_data); + unwind_plan.SetPersonalityFunctionPtr(personality_function_ptr); + } + + uint32_t code_align = cie->code_align; + int32_t data_align = cie->data_align; + + unwind_plan.SetPlanValidAddressRange(range); + UnwindPlan::Row *cie_initial_row = new UnwindPlan::Row; + *cie_initial_row = cie->initial_row; + UnwindPlan::RowSP row(cie_initial_row); + + unwind_plan.SetRegisterKind(m_reg_kind); + unwind_plan.SetReturnAddressRegister(cie->return_addr_reg_num); + + std::vector<UnwindPlan::RowSP> stack; + + UnwindPlan::Row::RegisterLocation reg_location; + while (m_cfi_data.ValidOffset(offset) && offset < end_offset) { + uint8_t inst = m_cfi_data.GetU8(&offset); + uint8_t primary_opcode = inst & 0xC0; + uint8_t extended_opcode = inst & 0x3F; + + if (!HandleCommonDwarfOpcode(primary_opcode, extended_opcode, data_align, + offset, *row)) { + if (primary_opcode) { + switch (primary_opcode) { + case DW_CFA_advance_loc: // (Row Creation Instruction) + { // 0x40 - high 2 bits are 0x1, lower 6 bits are delta + // takes a single argument that represents a constant delta. The + // required action is to create a new table row with a location + // value that is computed by taking the current entry's location + // value and adding (delta * code_align). All other + // values in the new row are initially identical to the current row. + unwind_plan.AppendRow(row); + UnwindPlan::Row *newrow = new UnwindPlan::Row; + *newrow = *row.get(); + row.reset(newrow); + row->SlideOffset(extended_opcode * code_align); + break; } - if (next_entry > m_cfi_data.GetByteSize() + 1) + case DW_CFA_restore: { // 0xC0 - high 2 bits are 0x3, lower 6 bits are + // register + // takes a single argument that represents a register number. The + // required action is to change the rule for the indicated register + // to the rule assigned it by the initial_instructions in the CIE. + uint32_t reg_num = extended_opcode; + // We only keep enough register locations around to + // unwind what is in our thread, and these are organized + // by the register index in that state, so we need to convert our + // eh_frame register number from the EH frame info, to a register + // index + + if (unwind_plan.IsValidRowIndex(0) && + unwind_plan.GetRowAtIndex(0)->GetRegisterInfo(reg_num, + reg_location)) + row->SetRegisterInfo(reg_num, reg_location); + break; + } + } + } else { + switch (extended_opcode) { + case DW_CFA_set_loc: // 0x1 (Row Creation Instruction) { - Host::SystemLog (Host::eSystemLogError, - "error: Invalid fde/cie next entry offset of 0x%x found in cie/fde at 0x%x\n", - next_entry, - current_entry); - // Don't trust anything in this eh_frame section if we find blatantly - // invalid data. - m_fde_index.Clear(); - m_fde_index_initialized = true; - return; + // DW_CFA_set_loc takes a single argument that represents an address. + // The required action is to create a new table row using the + // specified address as the location. All other values in the new row + // are initially identical to the current row. The new location value + // should always be greater than the current one. + unwind_plan.AppendRow(row); + UnwindPlan::Row *newrow = new UnwindPlan::Row; + *newrow = *row.get(); + row.reset(newrow); + row->SetOffset(m_cfi_data.GetPointer(&offset) - + startaddr.GetFileAddress()); + break; } - if (cie_offset > m_cfi_data.GetByteSize()) + + case DW_CFA_advance_loc1: // 0x2 (Row Creation Instruction) { - Host::SystemLog (Host::eSystemLogError, - "error: Invalid cie offset of 0x%x found in cie/fde at 0x%x\n", - cie_offset, - current_entry); - // Don't trust anything in this eh_frame section if we find blatantly - // invalid data. - m_fde_index.Clear(); - m_fde_index_initialized = true; - return; + // takes a single uword argument that represents a constant delta. + // This instruction is identical to DW_CFA_advance_loc except for the + // encoding and size of the delta argument. + unwind_plan.AppendRow(row); + UnwindPlan::Row *newrow = new UnwindPlan::Row; + *newrow = *row.get(); + row.reset(newrow); + row->SlideOffset(m_cfi_data.GetU8(&offset) * code_align); + break; } - if (cie_id == 0 || cie_id == UINT32_MAX || len == 0) + case DW_CFA_advance_loc2: // 0x3 (Row Creation Instruction) { - m_cie_map[current_entry] = ParseCIE (current_entry); - offset = next_entry; - continue; + // takes a single uword argument that represents a constant delta. + // This instruction is identical to DW_CFA_advance_loc except for the + // encoding and size of the delta argument. + unwind_plan.AppendRow(row); + UnwindPlan::Row *newrow = new UnwindPlan::Row; + *newrow = *row.get(); + row.reset(newrow); + row->SlideOffset(m_cfi_data.GetU16(&offset) * code_align); + break; } - const CIE *cie = GetCIE (cie_offset); - if (cie) + case DW_CFA_advance_loc4: // 0x4 (Row Creation Instruction) { - const lldb::addr_t pc_rel_addr = m_section_sp->GetFileAddress(); - const lldb::addr_t text_addr = LLDB_INVALID_ADDRESS; - const lldb::addr_t data_addr = LLDB_INVALID_ADDRESS; + // takes a single uword argument that represents a constant delta. + // This instruction is identical to DW_CFA_advance_loc except for the + // encoding and size of the delta argument. + unwind_plan.AppendRow(row); + UnwindPlan::Row *newrow = new UnwindPlan::Row; + *newrow = *row.get(); + row.reset(newrow); + row->SlideOffset(m_cfi_data.GetU32(&offset) * code_align); + break; + } - lldb::addr_t addr = m_cfi_data.GetGNUEHPointer(&offset, cie->ptr_encoding, pc_rel_addr, text_addr, data_addr); - if (clear_address_zeroth_bit) - addr &= ~1ull; + case DW_CFA_restore_extended: // 0x6 + { + // takes a single unsigned LEB128 argument that represents a register + // number. This instruction is identical to DW_CFA_restore except for + // the encoding and size of the register argument. + uint32_t reg_num = (uint32_t)m_cfi_data.GetULEB128(&offset); + if (unwind_plan.IsValidRowIndex(0) && + unwind_plan.GetRowAtIndex(0)->GetRegisterInfo(reg_num, + reg_location)) + row->SetRegisterInfo(reg_num, reg_location); + break; + } - lldb::addr_t length = m_cfi_data.GetGNUEHPointer(&offset, cie->ptr_encoding & DW_EH_PE_MASK_ENCODING, pc_rel_addr, text_addr, data_addr); - FDEEntryMap::Entry fde (addr, length, current_entry); - m_fde_index.Append(fde); + case DW_CFA_remember_state: // 0xA + { + // These instructions define a stack of information. Encountering the + // DW_CFA_remember_state instruction means to save the rules for every + // register on the current row on the stack. Encountering the + // DW_CFA_restore_state instruction means to pop the set of rules off + // the stack and place them in the current row. (This operation is + // useful for compilers that move epilogue code into the body of a + // function.) + stack.push_back(row); + UnwindPlan::Row *newrow = new UnwindPlan::Row; + *newrow = *row.get(); + row.reset(newrow); + break; } - else + + case DW_CFA_restore_state: // 0xB { - Host::SystemLog (Host::eSystemLogError, - "error: unable to find CIE at 0x%8.8x for cie_id = 0x%8.8x for entry at 0x%8.8x.\n", - cie_offset, - cie_id, - current_entry); + // These instructions define a stack of information. Encountering the + // DW_CFA_remember_state instruction means to save the rules for every + // register on the current row on the stack. Encountering the + // DW_CFA_restore_state instruction means to pop the set of rules off + // the stack and place them in the current row. (This operation is + // useful for compilers that move epilogue code into the body of a + // function.) + if (stack.empty()) { + if (log) + log->Printf("DWARFCallFrameInfo::%s(dwarf_offset: %" PRIx32 + ", startaddr: %" PRIx64 + " encountered DW_CFA_restore_state but state stack " + "is empty. Corrupt unwind info?", + __FUNCTION__, dwarf_offset, + startaddr.GetFileAddress()); + break; + } + lldb::addr_t offset = row->GetOffset(); + row = stack.back(); + stack.pop_back(); + row->SetOffset(offset); + break; } - offset = next_entry; - } - m_fde_index.Sort(); - m_fde_index_initialized = true; -} -bool -DWARFCallFrameInfo::FDEToUnwindPlan (dw_offset_t dwarf_offset, Address startaddr, UnwindPlan& unwind_plan) -{ - Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_UNWIND); - lldb::offset_t offset = dwarf_offset; - lldb::offset_t current_entry = offset; + case DW_CFA_GNU_args_size: // 0x2e + { + // The DW_CFA_GNU_args_size instruction takes an unsigned LEB128 + // operand + // representing an argument size. This instruction specifies the total + // of + // the size of the arguments which have been pushed onto the stack. + + // TODO: Figure out how we should handle this. + m_cfi_data.GetULEB128(&offset); + break; + } - if (m_section_sp.get() == nullptr || m_section_sp->IsEncrypted()) - return false; + case DW_CFA_val_offset: // 0x14 + case DW_CFA_val_offset_sf: // 0x15 + default: + break; + } + } + } + } + unwind_plan.AppendRow(row); - if (m_cfi_data_initialized == false) - GetCFIData(); + return true; +} - uint32_t length = m_cfi_data.GetU32 (&offset); - dw_offset_t cie_offset; - bool is_64bit = (length == UINT32_MAX); - if (is_64bit) { - length = m_cfi_data.GetU64 (&offset); - cie_offset = m_cfi_data.GetU64 (&offset); - } else { - cie_offset = m_cfi_data.GetU32 (&offset); +bool DWARFCallFrameInfo::HandleCommonDwarfOpcode(uint8_t primary_opcode, + uint8_t extended_opcode, + int32_t data_align, + lldb::offset_t &offset, + UnwindPlan::Row &row) { + UnwindPlan::Row::RegisterLocation reg_location; + + if (primary_opcode) { + switch (primary_opcode) { + case DW_CFA_offset: { // 0x80 - high 2 bits are 0x2, lower 6 bits are + // register + // takes two arguments: an unsigned LEB128 constant representing a + // factored offset and a register number. The required action is to + // change the rule for the register indicated by the register number + // to be an offset(N) rule with a value of + // (N = factored offset * data_align). + uint8_t reg_num = extended_opcode; + int32_t op_offset = (int32_t)m_cfi_data.GetULEB128(&offset) * data_align; + reg_location.SetAtCFAPlusOffset(op_offset); + row.SetRegisterInfo(reg_num, reg_location); + return true; } + } + } else { + switch (extended_opcode) { + case DW_CFA_nop: // 0x0 + return true; - assert (cie_offset != 0 && cie_offset != UINT32_MAX); - - // Translate the CIE_id from the eh_frame format, which - // is relative to the FDE offset, into a __eh_frame section - // offset - if (m_is_eh_frame) + case DW_CFA_offset_extended: // 0x5 { - unwind_plan.SetSourceName ("eh_frame CFI"); - cie_offset = current_entry + (is_64bit ? 12 : 4) - cie_offset; - unwind_plan.SetUnwindPlanValidAtAllInstructions (eLazyBoolNo); + // takes two unsigned LEB128 arguments representing a register number + // and a factored offset. This instruction is identical to DW_CFA_offset + // except for the encoding and size of the register argument. + uint32_t reg_num = (uint32_t)m_cfi_data.GetULEB128(&offset); + int32_t op_offset = (int32_t)m_cfi_data.GetULEB128(&offset) * data_align; + UnwindPlan::Row::RegisterLocation reg_location; + reg_location.SetAtCFAPlusOffset(op_offset); + row.SetRegisterInfo(reg_num, reg_location); + return true; } - else + + case DW_CFA_undefined: // 0x7 { - unwind_plan.SetSourceName ("DWARF CFI"); - // In theory the debug_frame info should be valid at all call sites - // ("asynchronous unwind info" as it is sometimes called) but in practice - // gcc et al all emit call frame info for the prologue and call sites, but - // not for the epilogue or all the other locations during the function reliably. - unwind_plan.SetUnwindPlanValidAtAllInstructions (eLazyBoolNo); + // takes a single unsigned LEB128 argument that represents a register + // number. The required action is to set the rule for the specified + // register to undefined. + uint32_t reg_num = (uint32_t)m_cfi_data.GetULEB128(&offset); + UnwindPlan::Row::RegisterLocation reg_location; + reg_location.SetUndefined(); + row.SetRegisterInfo(reg_num, reg_location); + return true; } - unwind_plan.SetSourcedFromCompiler (eLazyBoolYes); - - const CIE *cie = GetCIE (cie_offset); - assert (cie != nullptr); - - const dw_offset_t end_offset = current_entry + length + (is_64bit ? 12 : 4); - const lldb::addr_t pc_rel_addr = m_section_sp->GetFileAddress(); - const lldb::addr_t text_addr = LLDB_INVALID_ADDRESS; - const lldb::addr_t data_addr = LLDB_INVALID_ADDRESS; - lldb::addr_t range_base = m_cfi_data.GetGNUEHPointer(&offset, cie->ptr_encoding, pc_rel_addr, text_addr, data_addr); - lldb::addr_t range_len = m_cfi_data.GetGNUEHPointer(&offset, cie->ptr_encoding & DW_EH_PE_MASK_ENCODING, pc_rel_addr, text_addr, data_addr); - AddressRange range (range_base, m_objfile.GetAddressByteSize(), m_objfile.GetSectionList()); - range.SetByteSize (range_len); - - addr_t lsda_data_file_address = LLDB_INVALID_ADDRESS; - - if (cie->augmentation[0] == 'z') + case DW_CFA_same_value: // 0x8 { - uint32_t aug_data_len = (uint32_t)m_cfi_data.GetULEB128(&offset); - if (aug_data_len != 0 && cie->lsda_addr_encoding != DW_EH_PE_omit) - { - offset_t saved_offset = offset; - lsda_data_file_address = m_cfi_data.GetGNUEHPointer(&offset, cie->lsda_addr_encoding, pc_rel_addr, text_addr, data_addr); - if (offset - saved_offset != aug_data_len) - { - // There is more in the augmentation region than we know how to process; - // don't read anything. - lsda_data_file_address = LLDB_INVALID_ADDRESS; - } - offset = saved_offset; - } - offset += aug_data_len; + // takes a single unsigned LEB128 argument that represents a register + // number. The required action is to set the rule for the specified + // register to same value. + uint32_t reg_num = (uint32_t)m_cfi_data.GetULEB128(&offset); + UnwindPlan::Row::RegisterLocation reg_location; + reg_location.SetSame(); + row.SetRegisterInfo(reg_num, reg_location); + return true; } - Address lsda_data; - Address personality_function_ptr; - if (lsda_data_file_address != LLDB_INVALID_ADDRESS && cie->personality_loc != LLDB_INVALID_ADDRESS) + case DW_CFA_register: // 0x9 { - m_objfile.GetModule()->ResolveFileAddress (lsda_data_file_address, lsda_data); - m_objfile.GetModule()->ResolveFileAddress (cie->personality_loc, personality_function_ptr); + // takes two unsigned LEB128 arguments representing register numbers. + // The required action is to set the rule for the first register to be + // the second register. + uint32_t reg_num = (uint32_t)m_cfi_data.GetULEB128(&offset); + uint32_t other_reg_num = (uint32_t)m_cfi_data.GetULEB128(&offset); + UnwindPlan::Row::RegisterLocation reg_location; + reg_location.SetInRegister(other_reg_num); + row.SetRegisterInfo(reg_num, reg_location); + return true; } - if (lsda_data.IsValid() && personality_function_ptr.IsValid()) + case DW_CFA_def_cfa: // 0xC (CFA Definition Instruction) { - unwind_plan.SetLSDAAddress (lsda_data); - unwind_plan.SetPersonalityFunctionPtr (personality_function_ptr); + // Takes two unsigned LEB128 operands representing a register + // number and a (non-factored) offset. The required action + // is to define the current CFA rule to use the provided + // register and offset. + uint32_t reg_num = (uint32_t)m_cfi_data.GetULEB128(&offset); + int32_t op_offset = (int32_t)m_cfi_data.GetULEB128(&offset); + row.GetCFAValue().SetIsRegisterPlusOffset(reg_num, op_offset); + return true; } - uint32_t code_align = cie->code_align; - int32_t data_align = cie->data_align; - - unwind_plan.SetPlanValidAddressRange (range); - UnwindPlan::Row *cie_initial_row = new UnwindPlan::Row; - *cie_initial_row = cie->initial_row; - UnwindPlan::RowSP row(cie_initial_row); - - unwind_plan.SetRegisterKind (m_reg_kind); - unwind_plan.SetReturnAddressRegister (cie->return_addr_reg_num); - - std::vector<UnwindPlan::RowSP> stack; - - UnwindPlan::Row::RegisterLocation reg_location; - while (m_cfi_data.ValidOffset(offset) && offset < end_offset) + case DW_CFA_def_cfa_register: // 0xD (CFA Definition Instruction) { - uint8_t inst = m_cfi_data.GetU8(&offset); - uint8_t primary_opcode = inst & 0xC0; - uint8_t extended_opcode = inst & 0x3F; - - if (!HandleCommonDwarfOpcode(primary_opcode, extended_opcode, data_align, offset, *row)) - { - if (primary_opcode) - { - switch (primary_opcode) - { - case DW_CFA_advance_loc : // (Row Creation Instruction) - { // 0x40 - high 2 bits are 0x1, lower 6 bits are delta - // takes a single argument that represents a constant delta. The - // required action is to create a new table row with a location - // value that is computed by taking the current entry's location - // value and adding (delta * code_align). All other - // values in the new row are initially identical to the current row. - unwind_plan.AppendRow(row); - UnwindPlan::Row *newrow = new UnwindPlan::Row; - *newrow = *row.get(); - row.reset (newrow); - row->SlideOffset(extended_opcode * code_align); - break; - } - - case DW_CFA_restore : - { // 0xC0 - high 2 bits are 0x3, lower 6 bits are register - // takes a single argument that represents a register number. The - // required action is to change the rule for the indicated register - // to the rule assigned it by the initial_instructions in the CIE. - uint32_t reg_num = extended_opcode; - // We only keep enough register locations around to - // unwind what is in our thread, and these are organized - // by the register index in that state, so we need to convert our - // eh_frame register number from the EH frame info, to a register index - - if (unwind_plan.IsValidRowIndex(0) && unwind_plan.GetRowAtIndex(0)->GetRegisterInfo(reg_num, reg_location)) - row->SetRegisterInfo (reg_num, reg_location); - break; - } - } - } - else - { - switch (extended_opcode) - { - case DW_CFA_set_loc : // 0x1 (Row Creation Instruction) - { - // DW_CFA_set_loc takes a single argument that represents an address. - // The required action is to create a new table row using the - // specified address as the location. All other values in the new row - // are initially identical to the current row. The new location value - // should always be greater than the current one. - unwind_plan.AppendRow(row); - UnwindPlan::Row *newrow = new UnwindPlan::Row; - *newrow = *row.get(); - row.reset (newrow); - row->SetOffset(m_cfi_data.GetPointer(&offset) - startaddr.GetFileAddress()); - break; - } - - case DW_CFA_advance_loc1 : // 0x2 (Row Creation Instruction) - { - // takes a single uword argument that represents a constant delta. - // This instruction is identical to DW_CFA_advance_loc except for the - // encoding and size of the delta argument. - unwind_plan.AppendRow(row); - UnwindPlan::Row *newrow = new UnwindPlan::Row; - *newrow = *row.get(); - row.reset (newrow); - row->SlideOffset (m_cfi_data.GetU8(&offset) * code_align); - break; - } - - case DW_CFA_advance_loc2 : // 0x3 (Row Creation Instruction) - { - // takes a single uword argument that represents a constant delta. - // This instruction is identical to DW_CFA_advance_loc except for the - // encoding and size of the delta argument. - unwind_plan.AppendRow(row); - UnwindPlan::Row *newrow = new UnwindPlan::Row; - *newrow = *row.get(); - row.reset (newrow); - row->SlideOffset (m_cfi_data.GetU16(&offset) * code_align); - break; - } - - case DW_CFA_advance_loc4 : // 0x4 (Row Creation Instruction) - { - // takes a single uword argument that represents a constant delta. - // This instruction is identical to DW_CFA_advance_loc except for the - // encoding and size of the delta argument. - unwind_plan.AppendRow(row); - UnwindPlan::Row *newrow = new UnwindPlan::Row; - *newrow = *row.get(); - row.reset (newrow); - row->SlideOffset (m_cfi_data.GetU32(&offset) * code_align); - break; - } - - case DW_CFA_restore_extended : // 0x6 - { - // takes a single unsigned LEB128 argument that represents a register - // number. This instruction is identical to DW_CFA_restore except for - // the encoding and size of the register argument. - uint32_t reg_num = (uint32_t)m_cfi_data.GetULEB128(&offset); - if (unwind_plan.IsValidRowIndex(0) && unwind_plan.GetRowAtIndex(0)->GetRegisterInfo(reg_num, reg_location)) - row->SetRegisterInfo (reg_num, reg_location); - break; - } - - case DW_CFA_remember_state : // 0xA - { - // These instructions define a stack of information. Encountering the - // DW_CFA_remember_state instruction means to save the rules for every - // register on the current row on the stack. Encountering the - // DW_CFA_restore_state instruction means to pop the set of rules off - // the stack and place them in the current row. (This operation is - // useful for compilers that move epilogue code into the body of a - // function.) - stack.push_back (row); - UnwindPlan::Row *newrow = new UnwindPlan::Row; - *newrow = *row.get(); - row.reset (newrow); - break; - } - - case DW_CFA_restore_state : // 0xB - { - // These instructions define a stack of information. Encountering the - // DW_CFA_remember_state instruction means to save the rules for every - // register on the current row on the stack. Encountering the - // DW_CFA_restore_state instruction means to pop the set of rules off - // the stack and place them in the current row. (This operation is - // useful for compilers that move epilogue code into the body of a - // function.) - if (stack.empty()) - { - if (log) - log->Printf( - "DWARFCallFrameInfo::%s(dwarf_offset: %" PRIx32 ", startaddr: %" PRIx64 - " encountered DW_CFA_restore_state but state stack is empty. Corrupt unwind info?", - __FUNCTION__, dwarf_offset, startaddr.GetFileAddress()); - break; - } - lldb::addr_t offset = row->GetOffset (); - row = stack.back (); - stack.pop_back (); - row->SetOffset (offset); - break; - } - - case DW_CFA_GNU_args_size: // 0x2e - { - // The DW_CFA_GNU_args_size instruction takes an unsigned LEB128 operand - // representing an argument size. This instruction specifies the total of - // the size of the arguments which have been pushed onto the stack. - - // TODO: Figure out how we should handle this. - m_cfi_data.GetULEB128(&offset); - break; - } - - case DW_CFA_val_offset : // 0x14 - case DW_CFA_val_offset_sf : // 0x15 - default: - break; - } - } - } + // takes a single unsigned LEB128 argument representing a register + // number. The required action is to define the current CFA rule to + // use the provided register (but to keep the old offset). + uint32_t reg_num = (uint32_t)m_cfi_data.GetULEB128(&offset); + row.GetCFAValue().SetIsRegisterPlusOffset(reg_num, + row.GetCFAValue().GetOffset()); + return true; } - unwind_plan.AppendRow(row); - - return true; -} - -bool -DWARFCallFrameInfo::HandleCommonDwarfOpcode(uint8_t primary_opcode, - uint8_t extended_opcode, - int32_t data_align, - lldb::offset_t& offset, - UnwindPlan::Row& row) -{ - UnwindPlan::Row::RegisterLocation reg_location; - if (primary_opcode) + case DW_CFA_def_cfa_offset: // 0xE (CFA Definition Instruction) { - switch (primary_opcode) - { - case DW_CFA_offset: - { // 0x80 - high 2 bits are 0x2, lower 6 bits are register - // takes two arguments: an unsigned LEB128 constant representing a - // factored offset and a register number. The required action is to - // change the rule for the register indicated by the register number - // to be an offset(N) rule with a value of - // (N = factored offset * data_align). - uint8_t reg_num = extended_opcode; - int32_t op_offset = (int32_t)m_cfi_data.GetULEB128(&offset) * data_align; - reg_location.SetAtCFAPlusOffset(op_offset); - row.SetRegisterInfo(reg_num, reg_location); - return true; - } - } + // Takes a single unsigned LEB128 operand representing a + // (non-factored) offset. The required action is to define + // the current CFA rule to use the provided offset (but + // to keep the old register). + int32_t op_offset = (int32_t)m_cfi_data.GetULEB128(&offset); + row.GetCFAValue().SetIsRegisterPlusOffset( + row.GetCFAValue().GetRegisterNumber(), op_offset); + return true; } - else - { - switch (extended_opcode) - { - case DW_CFA_nop : // 0x0 - return true; - - case DW_CFA_offset_extended : // 0x5 - { - // takes two unsigned LEB128 arguments representing a register number - // and a factored offset. This instruction is identical to DW_CFA_offset - // except for the encoding and size of the register argument. - uint32_t reg_num = (uint32_t)m_cfi_data.GetULEB128(&offset); - int32_t op_offset = (int32_t)m_cfi_data.GetULEB128(&offset) * data_align; - UnwindPlan::Row::RegisterLocation reg_location; - reg_location.SetAtCFAPlusOffset(op_offset); - row.SetRegisterInfo(reg_num, reg_location); - return true; - } - - case DW_CFA_undefined : // 0x7 - { - // takes a single unsigned LEB128 argument that represents a register - // number. The required action is to set the rule for the specified - // register to undefined. - uint32_t reg_num = (uint32_t)m_cfi_data.GetULEB128(&offset); - UnwindPlan::Row::RegisterLocation reg_location; - reg_location.SetUndefined(); - row.SetRegisterInfo(reg_num, reg_location); - return true; - } - - case DW_CFA_same_value : // 0x8 - { - // takes a single unsigned LEB128 argument that represents a register - // number. The required action is to set the rule for the specified - // register to same value. - uint32_t reg_num = (uint32_t)m_cfi_data.GetULEB128(&offset); - UnwindPlan::Row::RegisterLocation reg_location; - reg_location.SetSame(); - row.SetRegisterInfo (reg_num, reg_location); - return true; - } - - case DW_CFA_register : // 0x9 - { - // takes two unsigned LEB128 arguments representing register numbers. - // The required action is to set the rule for the first register to be - // the second register. - uint32_t reg_num = (uint32_t)m_cfi_data.GetULEB128(&offset); - uint32_t other_reg_num = (uint32_t)m_cfi_data.GetULEB128(&offset); - UnwindPlan::Row::RegisterLocation reg_location; - reg_location.SetInRegister(other_reg_num); - row.SetRegisterInfo (reg_num, reg_location); - return true; - } - - case DW_CFA_def_cfa : // 0xC (CFA Definition Instruction) - { - // Takes two unsigned LEB128 operands representing a register - // number and a (non-factored) offset. The required action - // is to define the current CFA rule to use the provided - // register and offset. - uint32_t reg_num = (uint32_t)m_cfi_data.GetULEB128(&offset); - int32_t op_offset = (int32_t)m_cfi_data.GetULEB128(&offset); - row.GetCFAValue().SetIsRegisterPlusOffset (reg_num, op_offset); - return true; - } - - case DW_CFA_def_cfa_register : // 0xD (CFA Definition Instruction) - { - // takes a single unsigned LEB128 argument representing a register - // number. The required action is to define the current CFA rule to - // use the provided register (but to keep the old offset). - uint32_t reg_num = (uint32_t)m_cfi_data.GetULEB128(&offset); - row.GetCFAValue().SetIsRegisterPlusOffset (reg_num, row.GetCFAValue().GetOffset()); - return true; - } - - case DW_CFA_def_cfa_offset : // 0xE (CFA Definition Instruction) - { - // Takes a single unsigned LEB128 operand representing a - // (non-factored) offset. The required action is to define - // the current CFA rule to use the provided offset (but - // to keep the old register). - int32_t op_offset = (int32_t)m_cfi_data.GetULEB128(&offset); - row.GetCFAValue().SetIsRegisterPlusOffset(row.GetCFAValue().GetRegisterNumber(), op_offset); - return true; - } - case DW_CFA_def_cfa_expression : // 0xF (CFA Definition Instruction) - { - size_t block_len = (size_t)m_cfi_data.GetULEB128(&offset); - const uint8_t *block_data = static_cast<const uint8_t*>(m_cfi_data.GetData(&offset, block_len)); - row.GetCFAValue().SetIsDWARFExpression(block_data, block_len); - return true; - } + case DW_CFA_def_cfa_expression: // 0xF (CFA Definition Instruction) + { + size_t block_len = (size_t)m_cfi_data.GetULEB128(&offset); + const uint8_t *block_data = + static_cast<const uint8_t *>(m_cfi_data.GetData(&offset, block_len)); + row.GetCFAValue().SetIsDWARFExpression(block_data, block_len); + return true; + } - case DW_CFA_expression : // 0x10 - { - // Takes two operands: an unsigned LEB128 value representing - // a register number, and a DW_FORM_block value representing a DWARF - // expression. The required action is to change the rule for the - // register indicated by the register number to be an expression(E) - // rule where E is the DWARF expression. That is, the DWARF - // expression computes the address. The value of the CFA is - // pushed on the DWARF evaluation stack prior to execution of - // the DWARF expression. - uint32_t reg_num = (uint32_t)m_cfi_data.GetULEB128(&offset); - uint32_t block_len = (uint32_t)m_cfi_data.GetULEB128(&offset); - const uint8_t *block_data = static_cast<const uint8_t*>(m_cfi_data.GetData(&offset, block_len)); - UnwindPlan::Row::RegisterLocation reg_location; - reg_location.SetAtDWARFExpression(block_data, block_len); - row.SetRegisterInfo(reg_num, reg_location); - return true; - } + case DW_CFA_expression: // 0x10 + { + // Takes two operands: an unsigned LEB128 value representing + // a register number, and a DW_FORM_block value representing a DWARF + // expression. The required action is to change the rule for the + // register indicated by the register number to be an expression(E) + // rule where E is the DWARF expression. That is, the DWARF + // expression computes the address. The value of the CFA is + // pushed on the DWARF evaluation stack prior to execution of + // the DWARF expression. + uint32_t reg_num = (uint32_t)m_cfi_data.GetULEB128(&offset); + uint32_t block_len = (uint32_t)m_cfi_data.GetULEB128(&offset); + const uint8_t *block_data = + static_cast<const uint8_t *>(m_cfi_data.GetData(&offset, block_len)); + UnwindPlan::Row::RegisterLocation reg_location; + reg_location.SetAtDWARFExpression(block_data, block_len); + row.SetRegisterInfo(reg_num, reg_location); + return true; + } - case DW_CFA_offset_extended_sf : // 0x11 - { - // takes two operands: an unsigned LEB128 value representing a - // register number and a signed LEB128 factored offset. This - // instruction is identical to DW_CFA_offset_extended except - //that the second operand is signed and factored. - uint32_t reg_num = (uint32_t)m_cfi_data.GetULEB128(&offset); - int32_t op_offset = (int32_t)m_cfi_data.GetSLEB128(&offset) * data_align; - UnwindPlan::Row::RegisterLocation reg_location; - reg_location.SetAtCFAPlusOffset(op_offset); - row.SetRegisterInfo(reg_num, reg_location); - return true; - } + case DW_CFA_offset_extended_sf: // 0x11 + { + // takes two operands: an unsigned LEB128 value representing a + // register number and a signed LEB128 factored offset. This + // instruction is identical to DW_CFA_offset_extended except + // that the second operand is signed and factored. + uint32_t reg_num = (uint32_t)m_cfi_data.GetULEB128(&offset); + int32_t op_offset = (int32_t)m_cfi_data.GetSLEB128(&offset) * data_align; + UnwindPlan::Row::RegisterLocation reg_location; + reg_location.SetAtCFAPlusOffset(op_offset); + row.SetRegisterInfo(reg_num, reg_location); + return true; + } - case DW_CFA_def_cfa_sf : // 0x12 (CFA Definition Instruction) - { - // Takes two operands: an unsigned LEB128 value representing - // a register number and a signed LEB128 factored offset. - // This instruction is identical to DW_CFA_def_cfa except - // that the second operand is signed and factored. - uint32_t reg_num = (uint32_t)m_cfi_data.GetULEB128(&offset); - int32_t op_offset = (int32_t)m_cfi_data.GetSLEB128(&offset) * data_align; - row.GetCFAValue().SetIsRegisterPlusOffset (reg_num, op_offset); - return true; - } + case DW_CFA_def_cfa_sf: // 0x12 (CFA Definition Instruction) + { + // Takes two operands: an unsigned LEB128 value representing + // a register number and a signed LEB128 factored offset. + // This instruction is identical to DW_CFA_def_cfa except + // that the second operand is signed and factored. + uint32_t reg_num = (uint32_t)m_cfi_data.GetULEB128(&offset); + int32_t op_offset = (int32_t)m_cfi_data.GetSLEB128(&offset) * data_align; + row.GetCFAValue().SetIsRegisterPlusOffset(reg_num, op_offset); + return true; + } - case DW_CFA_def_cfa_offset_sf : // 0x13 (CFA Definition Instruction) - { - // takes a signed LEB128 operand representing a factored - // offset. This instruction is identical to DW_CFA_def_cfa_offset - // except that the operand is signed and factored. - int32_t op_offset = (int32_t)m_cfi_data.GetSLEB128(&offset) * data_align; - uint32_t cfa_regnum = row.GetCFAValue().GetRegisterNumber(); - row.GetCFAValue().SetIsRegisterPlusOffset(cfa_regnum, op_offset); - return true; - } + case DW_CFA_def_cfa_offset_sf: // 0x13 (CFA Definition Instruction) + { + // takes a signed LEB128 operand representing a factored + // offset. This instruction is identical to DW_CFA_def_cfa_offset + // except that the operand is signed and factored. + int32_t op_offset = (int32_t)m_cfi_data.GetSLEB128(&offset) * data_align; + uint32_t cfa_regnum = row.GetCFAValue().GetRegisterNumber(); + row.GetCFAValue().SetIsRegisterPlusOffset(cfa_regnum, op_offset); + return true; + } - case DW_CFA_val_expression : // 0x16 - { - // takes two operands: an unsigned LEB128 value representing a register - // number, and a DW_FORM_block value representing a DWARF expression. - // The required action is to change the rule for the register indicated - // by the register number to be a val_expression(E) rule where E is the - // DWARF expression. That is, the DWARF expression computes the value of - // the given register. The value of the CFA is pushed on the DWARF - // evaluation stack prior to execution of the DWARF expression. - uint32_t reg_num = (uint32_t)m_cfi_data.GetULEB128(&offset); - uint32_t block_len = (uint32_t)m_cfi_data.GetULEB128(&offset); - const uint8_t* block_data = (const uint8_t*)m_cfi_data.GetData(&offset, block_len); -//#if defined(__i386__) || defined(__x86_64__) -// // The EH frame info for EIP and RIP contains code that looks for traps to -// // be a specific type and increments the PC. -// // For i386: -// // DW_CFA_val_expression where: -// // eip = DW_OP_breg6(+28), DW_OP_deref, DW_OP_dup, DW_OP_plus_uconst(0x34), -// // DW_OP_deref, DW_OP_swap, DW_OP_plus_uconst(0), DW_OP_deref, -// // DW_OP_dup, DW_OP_lit3, DW_OP_ne, DW_OP_swap, DW_OP_lit4, DW_OP_ne, -// // DW_OP_and, DW_OP_plus -// // This basically does a: -// // eip = ucontenxt.mcontext32->gpr.eip; -// // if (ucontenxt.mcontext32->exc.trapno != 3 && ucontenxt.mcontext32->exc.trapno != 4) -// // eip++; -// // -// // For x86_64: -// // DW_CFA_val_expression where: -// // rip = DW_OP_breg3(+48), DW_OP_deref, DW_OP_dup, DW_OP_plus_uconst(0x90), DW_OP_deref, -// // DW_OP_swap, DW_OP_plus_uconst(0), DW_OP_deref_size(4), DW_OP_dup, DW_OP_lit3, -// // DW_OP_ne, DW_OP_swap, DW_OP_lit4, DW_OP_ne, DW_OP_and, DW_OP_plus -// // This basically does a: -// // rip = ucontenxt.mcontext64->gpr.rip; -// // if (ucontenxt.mcontext64->exc.trapno != 3 && ucontenxt.mcontext64->exc.trapno != 4) -// // rip++; -// // The trap comparisons and increments are not needed as it hoses up the unwound PC which -// // is expected to point at least past the instruction that causes the fault/trap. So we -// // take it out by trimming the expression right at the first "DW_OP_swap" opcodes -// if (block_data != NULL && thread->GetPCRegNum(Thread::GCC) == reg_num) -// { -// if (thread->Is64Bit()) -// { -// if (block_len > 9 && block_data[8] == DW_OP_swap && block_data[9] == DW_OP_plus_uconst) -// block_len = 8; -// } -// else -// { -// if (block_len > 8 && block_data[7] == DW_OP_swap && block_data[8] == DW_OP_plus_uconst) -// block_len = 7; -// } -// } -//#endif - reg_location.SetIsDWARFExpression(block_data, block_len); - row.SetRegisterInfo (reg_num, reg_location); - return true; - } - } + case DW_CFA_val_expression: // 0x16 + { + // takes two operands: an unsigned LEB128 value representing a register + // number, and a DW_FORM_block value representing a DWARF expression. + // The required action is to change the rule for the register indicated + // by the register number to be a val_expression(E) rule where E is the + // DWARF expression. That is, the DWARF expression computes the value of + // the given register. The value of the CFA is pushed on the DWARF + // evaluation stack prior to execution of the DWARF expression. + uint32_t reg_num = (uint32_t)m_cfi_data.GetULEB128(&offset); + uint32_t block_len = (uint32_t)m_cfi_data.GetULEB128(&offset); + const uint8_t *block_data = + (const uint8_t *)m_cfi_data.GetData(&offset, block_len); + //#if defined(__i386__) || defined(__x86_64__) + // // The EH frame info for EIP and RIP contains code that + // looks for traps to + // // be a specific type and increments the PC. + // // For i386: + // // DW_CFA_val_expression where: + // // eip = DW_OP_breg6(+28), DW_OP_deref, DW_OP_dup, + // DW_OP_plus_uconst(0x34), + // // DW_OP_deref, DW_OP_swap, DW_OP_plus_uconst(0), + // DW_OP_deref, + // // DW_OP_dup, DW_OP_lit3, DW_OP_ne, DW_OP_swap, + // DW_OP_lit4, DW_OP_ne, + // // DW_OP_and, DW_OP_plus + // // This basically does a: + // // eip = ucontenxt.mcontext32->gpr.eip; + // // if (ucontenxt.mcontext32->exc.trapno != 3 && + // ucontenxt.mcontext32->exc.trapno != 4) + // // eip++; + // // + // // For x86_64: + // // DW_CFA_val_expression where: + // // rip = DW_OP_breg3(+48), DW_OP_deref, DW_OP_dup, + // DW_OP_plus_uconst(0x90), DW_OP_deref, + // // DW_OP_swap, DW_OP_plus_uconst(0), + // DW_OP_deref_size(4), DW_OP_dup, DW_OP_lit3, + // // DW_OP_ne, DW_OP_swap, DW_OP_lit4, DW_OP_ne, + // DW_OP_and, DW_OP_plus + // // This basically does a: + // // rip = ucontenxt.mcontext64->gpr.rip; + // // if (ucontenxt.mcontext64->exc.trapno != 3 && + // ucontenxt.mcontext64->exc.trapno != 4) + // // rip++; + // // The trap comparisons and increments are not needed as + // it hoses up the unwound PC which + // // is expected to point at least past the instruction that + // causes the fault/trap. So we + // // take it out by trimming the expression right at the + // first "DW_OP_swap" opcodes + // if (block_data != NULL && thread->GetPCRegNum(Thread::GCC) + // == reg_num) + // { + // if (thread->Is64Bit()) + // { + // if (block_len > 9 && block_data[8] == DW_OP_swap + // && block_data[9] == DW_OP_plus_uconst) + // block_len = 8; + // } + // else + // { + // if (block_len > 8 && block_data[7] == DW_OP_swap + // && block_data[8] == DW_OP_plus_uconst) + // block_len = 7; + // } + // } + //#endif + reg_location.SetIsDWARFExpression(block_data, block_len); + row.SetRegisterInfo(reg_num, reg_location); + return true; } - return false; + } + } + return false; } -void -DWARFCallFrameInfo::ForEachFDEEntries( - const std::function<bool(lldb::addr_t, uint32_t, dw_offset_t)>& callback) -{ - GetFDEIndex(); +void DWARFCallFrameInfo::ForEachFDEEntries( + const std::function<bool(lldb::addr_t, uint32_t, dw_offset_t)> &callback) { + GetFDEIndex(); - for (size_t i = 0, c = m_fde_index.GetSize(); i < c; ++i) - { - const FDEEntryMap::Entry& entry = m_fde_index.GetEntryRef(i); - if (!callback(entry.base, entry.size, entry.data)) - break; - } + for (size_t i = 0, c = m_fde_index.GetSize(); i < c; ++i) { + const FDEEntryMap::Entry &entry = m_fde_index.GetEntryRef(i); + if (!callback(entry.base, entry.size, entry.data)) + break; + } } diff --git a/lldb/source/Symbol/DebugMacros.cpp b/lldb/source/Symbol/DebugMacros.cpp index 88a28ba75e6..22576ee1ce2 100644 --- a/lldb/source/Symbol/DebugMacros.cpp +++ b/lldb/source/Symbol/DebugMacros.cpp @@ -13,53 +13,42 @@ using namespace lldb_private; -DebugMacroEntry::DebugMacroEntry(EntryType type, - uint32_t line, - uint32_t debug_line_file_idx, - const char *str) - : m_type(type), - m_line(line), - m_debug_line_file_idx(debug_line_file_idx), - m_str(str) -{ } +DebugMacroEntry::DebugMacroEntry(EntryType type, uint32_t line, + uint32_t debug_line_file_idx, const char *str) + : m_type(type), m_line(line), m_debug_line_file_idx(debug_line_file_idx), + m_str(str) {} DebugMacroEntry::DebugMacroEntry(EntryType type, const DebugMacrosSP &debug_macros_sp) - : m_type(type), m_line(0), m_debug_line_file_idx(0), m_debug_macros_sp(debug_macros_sp) -{ } + : m_type(type), m_line(0), m_debug_line_file_idx(0), + m_debug_macros_sp(debug_macros_sp) {} -const FileSpec& -DebugMacroEntry::GetFileSpec(CompileUnit *comp_unit) const -{ - return comp_unit->GetSupportFiles().GetFileSpecAtIndex(m_debug_line_file_idx); +const FileSpec &DebugMacroEntry::GetFileSpec(CompileUnit *comp_unit) const { + return comp_unit->GetSupportFiles().GetFileSpecAtIndex(m_debug_line_file_idx); } -DebugMacroEntry -DebugMacroEntry::CreateDefineEntry(uint32_t line, const char *str) -{ - return DebugMacroEntry(DebugMacroEntry::DEFINE, line, 0, str); +DebugMacroEntry DebugMacroEntry::CreateDefineEntry(uint32_t line, + const char *str) { + return DebugMacroEntry(DebugMacroEntry::DEFINE, line, 0, str); } -DebugMacroEntry -DebugMacroEntry::CreateUndefEntry(uint32_t line, const char *str) -{ - return DebugMacroEntry(DebugMacroEntry::UNDEF, line, 0, str); +DebugMacroEntry DebugMacroEntry::CreateUndefEntry(uint32_t line, + const char *str) { + return DebugMacroEntry(DebugMacroEntry::UNDEF, line, 0, str); } DebugMacroEntry -DebugMacroEntry::CreateStartFileEntry(uint32_t line, uint32_t debug_line_file_idx) -{ - return DebugMacroEntry(DebugMacroEntry::START_FILE, line, debug_line_file_idx, nullptr); +DebugMacroEntry::CreateStartFileEntry(uint32_t line, + uint32_t debug_line_file_idx) { + return DebugMacroEntry(DebugMacroEntry::START_FILE, line, debug_line_file_idx, + nullptr); } -DebugMacroEntry -DebugMacroEntry::CreateEndFileEntry() -{ - return DebugMacroEntry(DebugMacroEntry::END_FILE, 0, 0, nullptr); +DebugMacroEntry DebugMacroEntry::CreateEndFileEntry() { + return DebugMacroEntry(DebugMacroEntry::END_FILE, 0, 0, nullptr); } DebugMacroEntry -DebugMacroEntry::CreateIndirectEntry(const DebugMacrosSP &debug_macros_sp) -{ - return DebugMacroEntry(DebugMacroEntry::INDIRECT, debug_macros_sp); +DebugMacroEntry::CreateIndirectEntry(const DebugMacrosSP &debug_macros_sp) { + return DebugMacroEntry(DebugMacroEntry::INDIRECT, debug_macros_sp); } diff --git a/lldb/source/Symbol/Declaration.cpp b/lldb/source/Symbol/Declaration.cpp index c72ca045b6c..5d1dbdee143 100644 --- a/lldb/source/Symbol/Declaration.cpp +++ b/lldb/source/Symbol/Declaration.cpp @@ -12,106 +12,86 @@ using namespace lldb_private; -void -Declaration::Dump(Stream *s, bool show_fullpaths) const -{ - if (m_file) - { - *s << ", decl = "; - if (show_fullpaths) - *s << m_file; - else - *s << m_file.GetFilename(); - if (m_line > 0) - s->Printf(":%u", m_line); -#ifdef LLDB_ENABLE_DECLARATION_COLUMNS - if (m_column > 0) - s->Printf(":%u", m_column); -#endif - } +void Declaration::Dump(Stream *s, bool show_fullpaths) const { + if (m_file) { + *s << ", decl = "; + if (show_fullpaths) + *s << m_file; else - { - if (m_line > 0) - { - s->Printf(", line = %u", m_line); + *s << m_file.GetFilename(); + if (m_line > 0) + s->Printf(":%u", m_line); #ifdef LLDB_ENABLE_DECLARATION_COLUMNS - if (m_column > 0) - s->Printf(":%u", m_column); + if (m_column > 0) + s->Printf(":%u", m_column); #endif - } + } else { + if (m_line > 0) { + s->Printf(", line = %u", m_line); #ifdef LLDB_ENABLE_DECLARATION_COLUMNS - else if (m_column > 0) - s->Printf(", column = %u", m_column); + if (m_column > 0) + s->Printf(":%u", m_column); #endif } +#ifdef LLDB_ENABLE_DECLARATION_COLUMNS + else if (m_column > 0) + s->Printf(", column = %u", m_column); +#endif + } } -bool -Declaration::DumpStopContext (Stream *s, bool show_fullpaths) const -{ - if (m_file) - { - if (show_fullpaths || s->GetVerbose()) - *s << m_file; - else - m_file.GetFilename().Dump(s); +bool Declaration::DumpStopContext(Stream *s, bool show_fullpaths) const { + if (m_file) { + if (show_fullpaths || s->GetVerbose()) + *s << m_file; + else + m_file.GetFilename().Dump(s); - if (m_line > 0) - s->Printf(":%u", m_line); + if (m_line > 0) + s->Printf(":%u", m_line); #ifdef LLDB_ENABLE_DECLARATION_COLUMNS - if (m_column > 0) - s->Printf(":%u", m_column); + if (m_column > 0) + s->Printf(":%u", m_column); #endif - return true; - } - else if (m_line > 0) - { - s->Printf(" line %u", m_line); + return true; + } else if (m_line > 0) { + s->Printf(" line %u", m_line); #ifdef LLDB_ENABLE_DECLARATION_COLUMNS - if (m_column > 0) - s->Printf(":%u", m_column); + if (m_column > 0) + s->Printf(":%u", m_column); #endif - return true; - } - return false; + return true; + } + return false; } -size_t -Declaration::MemorySize() const -{ - return sizeof(Declaration); -} +size_t Declaration::MemorySize() const { return sizeof(Declaration); } -int -Declaration::Compare(const Declaration& a, const Declaration& b) -{ - int result = FileSpec::Compare(a.m_file, b.m_file, true); - if (result) - return result; - if (a.m_line < b.m_line) - return -1; - else if (a.m_line > b.m_line) - return 1; +int Declaration::Compare(const Declaration &a, const Declaration &b) { + int result = FileSpec::Compare(a.m_file, b.m_file, true); + if (result) + return result; + if (a.m_line < b.m_line) + return -1; + else if (a.m_line > b.m_line) + return 1; #ifdef LLDB_ENABLE_DECLARATION_COLUMNS - if (a.m_column < b.m_column) - return -1; - else if (a.m_column > b.m_column) - return 1; + if (a.m_column < b.m_column) + return -1; + else if (a.m_column > b.m_column) + return 1; #endif - return 0; + return 0; } -bool -lldb_private::operator == (const Declaration &lhs, const Declaration &rhs) -{ +bool lldb_private::operator==(const Declaration &lhs, const Declaration &rhs) { #ifdef LLDB_ENABLE_DECLARATION_COLUMNS - if (lhs.GetColumn () == rhs.GetColumn ()) - if (lhs.GetLine () == rhs.GetLine ()) - return lhs.GetFile() == rhs.GetFile(); + if (lhs.GetColumn() == rhs.GetColumn()) + if (lhs.GetLine() == rhs.GetLine()) + return lhs.GetFile() == rhs.GetFile(); #else - if (lhs.GetLine () == rhs.GetLine ()) - return FileSpec::Equal(lhs.GetFile(),rhs.GetFile(), true, true); + if (lhs.GetLine() == rhs.GetLine()) + return FileSpec::Equal(lhs.GetFile(), rhs.GetFile(), true, true); #endif - return false; + return false; } - diff --git a/lldb/source/Symbol/FuncUnwinders.cpp b/lldb/source/Symbol/FuncUnwinders.cpp index 2fa41b84cb2..0abd8a25b5d 100644 --- a/lldb/source/Symbol/FuncUnwinders.cpp +++ b/lldb/source/Symbol/FuncUnwinders.cpp @@ -7,20 +7,20 @@ // //===----------------------------------------------------------------------===// -#include "lldb/Core/AddressRange.h" -#include "lldb/Core/Address.h" #include "lldb/Symbol/FuncUnwinders.h" +#include "lldb/Core/Address.h" +#include "lldb/Core/AddressRange.h" #include "lldb/Symbol/ArmUnwindInfo.h" -#include "lldb/Symbol/DWARFCallFrameInfo.h" #include "lldb/Symbol/CompactUnwindInfo.h" +#include "lldb/Symbol/DWARFCallFrameInfo.h" #include "lldb/Symbol/ObjectFile.h" #include "lldb/Symbol/UnwindPlan.h" #include "lldb/Symbol/UnwindTable.h" #include "lldb/Target/ABI.h" #include "lldb/Target/ExecutionContext.h" #include "lldb/Target/Process.h" -#include "lldb/Target/Thread.h" #include "lldb/Target/Target.h" +#include "lldb/Target/Thread.h" #include "lldb/Target/UnwindAssembly.h" #include "lldb/Utility/RegisterNumber.h" @@ -32,421 +32,390 @@ using namespace lldb_private; //------------------------------------------------ FuncUnwinders::FuncUnwinders(UnwindTable &unwind_table, AddressRange range) - : m_unwind_table(unwind_table), - m_range(range), - m_mutex(), - m_unwind_plan_assembly_sp(), - m_unwind_plan_eh_frame_sp(), - m_unwind_plan_eh_frame_augmented_sp(), - m_unwind_plan_compact_unwind(), - m_unwind_plan_arm_unwind_sp(), - m_unwind_plan_fast_sp(), + : m_unwind_table(unwind_table), m_range(range), m_mutex(), + m_unwind_plan_assembly_sp(), m_unwind_plan_eh_frame_sp(), + m_unwind_plan_eh_frame_augmented_sp(), m_unwind_plan_compact_unwind(), + m_unwind_plan_arm_unwind_sp(), m_unwind_plan_fast_sp(), m_unwind_plan_arch_default_sp(), m_unwind_plan_arch_default_at_func_entry_sp(), - m_tried_unwind_plan_assembly(false), - m_tried_unwind_plan_eh_frame(false), + m_tried_unwind_plan_assembly(false), m_tried_unwind_plan_eh_frame(false), m_tried_unwind_plan_eh_frame_augmented(false), m_tried_unwind_plan_compact_unwind(false), - m_tried_unwind_plan_arm_unwind(false), - m_tried_unwind_fast(false), + m_tried_unwind_plan_arm_unwind(false), m_tried_unwind_fast(false), m_tried_unwind_arch_default(false), m_tried_unwind_arch_default_at_func_entry(false), - m_first_non_prologue_insn() -{ -} + m_first_non_prologue_insn() {} //------------------------------------------------ /// destructor //------------------------------------------------ -FuncUnwinders::~FuncUnwinders () -{ -} +FuncUnwinders::~FuncUnwinders() {} -UnwindPlanSP -FuncUnwinders::GetUnwindPlanAtCallSite (Target &target, int current_offset) -{ - std::lock_guard<std::recursive_mutex> guard(m_mutex); +UnwindPlanSP FuncUnwinders::GetUnwindPlanAtCallSite(Target &target, + int current_offset) { + std::lock_guard<std::recursive_mutex> guard(m_mutex); - UnwindPlanSP unwind_plan_sp = GetEHFrameUnwindPlan (target, current_offset); - if (unwind_plan_sp) - return unwind_plan_sp; + UnwindPlanSP unwind_plan_sp = GetEHFrameUnwindPlan(target, current_offset); + if (unwind_plan_sp) + return unwind_plan_sp; - unwind_plan_sp = GetCompactUnwindUnwindPlan (target, current_offset); - if (unwind_plan_sp) - return unwind_plan_sp; + unwind_plan_sp = GetCompactUnwindUnwindPlan(target, current_offset); + if (unwind_plan_sp) + return unwind_plan_sp; - unwind_plan_sp = GetArmUnwindUnwindPlan (target, current_offset); - if (unwind_plan_sp) - return unwind_plan_sp; + unwind_plan_sp = GetArmUnwindUnwindPlan(target, current_offset); + if (unwind_plan_sp) + return unwind_plan_sp; - return nullptr; + return nullptr; } -UnwindPlanSP -FuncUnwinders::GetCompactUnwindUnwindPlan (Target &target, int current_offset) -{ - if (m_unwind_plan_compact_unwind.size() > 0) - return m_unwind_plan_compact_unwind[0]; // FIXME support multiple compact unwind plans for one func - if (m_tried_unwind_plan_compact_unwind) - return UnwindPlanSP(); - - std::lock_guard<std::recursive_mutex> guard(m_mutex); - m_tried_unwind_plan_compact_unwind = true; - if (m_range.GetBaseAddress().IsValid()) - { - Address current_pc (m_range.GetBaseAddress ()); - if (current_offset != -1) - current_pc.SetOffset (current_pc.GetOffset() + current_offset); - CompactUnwindInfo *compact_unwind = m_unwind_table.GetCompactUnwindInfo(); - if (compact_unwind) - { - UnwindPlanSP unwind_plan_sp (new UnwindPlan (lldb::eRegisterKindGeneric)); - if (compact_unwind->GetUnwindPlan (target, current_pc, *unwind_plan_sp)) - { - m_unwind_plan_compact_unwind.push_back (unwind_plan_sp); - return m_unwind_plan_compact_unwind[0]; // FIXME support multiple compact unwind plans for one func - } - } - } +UnwindPlanSP FuncUnwinders::GetCompactUnwindUnwindPlan(Target &target, + int current_offset) { + if (m_unwind_plan_compact_unwind.size() > 0) + return m_unwind_plan_compact_unwind[0]; // FIXME support multiple compact + // unwind plans for one func + if (m_tried_unwind_plan_compact_unwind) return UnwindPlanSP(); -} -UnwindPlanSP -FuncUnwinders::GetEHFrameUnwindPlan (Target &target, int current_offset) -{ - if (m_unwind_plan_eh_frame_sp.get() || m_tried_unwind_plan_eh_frame) - return m_unwind_plan_eh_frame_sp; - - std::lock_guard<std::recursive_mutex> guard(m_mutex); - m_tried_unwind_plan_eh_frame = true; - if (m_range.GetBaseAddress().IsValid()) - { - Address current_pc (m_range.GetBaseAddress ()); - if (current_offset != -1) - current_pc.SetOffset (current_pc.GetOffset() + current_offset); - DWARFCallFrameInfo *eh_frame = m_unwind_table.GetEHFrameInfo(); - if (eh_frame) - { - m_unwind_plan_eh_frame_sp.reset (new UnwindPlan (lldb::eRegisterKindGeneric)); - if (!eh_frame->GetUnwindPlan (current_pc, *m_unwind_plan_eh_frame_sp)) - m_unwind_plan_eh_frame_sp.reset(); - } + std::lock_guard<std::recursive_mutex> guard(m_mutex); + m_tried_unwind_plan_compact_unwind = true; + if (m_range.GetBaseAddress().IsValid()) { + Address current_pc(m_range.GetBaseAddress()); + if (current_offset != -1) + current_pc.SetOffset(current_pc.GetOffset() + current_offset); + CompactUnwindInfo *compact_unwind = m_unwind_table.GetCompactUnwindInfo(); + if (compact_unwind) { + UnwindPlanSP unwind_plan_sp(new UnwindPlan(lldb::eRegisterKindGeneric)); + if (compact_unwind->GetUnwindPlan(target, current_pc, *unwind_plan_sp)) { + m_unwind_plan_compact_unwind.push_back(unwind_plan_sp); + return m_unwind_plan_compact_unwind[0]; // FIXME support multiple + // compact unwind plans for one + // func + } } - return m_unwind_plan_eh_frame_sp; + } + return UnwindPlanSP(); } -UnwindPlanSP -FuncUnwinders::GetArmUnwindUnwindPlan (Target &target, int current_offset) -{ - if (m_unwind_plan_arm_unwind_sp.get() || m_tried_unwind_plan_arm_unwind) - return m_unwind_plan_arm_unwind_sp; - - std::lock_guard<std::recursive_mutex> guard(m_mutex); - m_tried_unwind_plan_arm_unwind = true; - if (m_range.GetBaseAddress().IsValid()) - { - Address current_pc (m_range.GetBaseAddress ()); - if (current_offset != -1) - current_pc.SetOffset (current_pc.GetOffset() + current_offset); - ArmUnwindInfo *arm_unwind_info = m_unwind_table.GetArmUnwindInfo(); - if (arm_unwind_info) - { - m_unwind_plan_arm_unwind_sp.reset (new UnwindPlan (lldb::eRegisterKindGeneric)); - if (!arm_unwind_info->GetUnwindPlan (target, current_pc, *m_unwind_plan_arm_unwind_sp)) - m_unwind_plan_arm_unwind_sp.reset(); - } +UnwindPlanSP FuncUnwinders::GetEHFrameUnwindPlan(Target &target, + int current_offset) { + if (m_unwind_plan_eh_frame_sp.get() || m_tried_unwind_plan_eh_frame) + return m_unwind_plan_eh_frame_sp; + + std::lock_guard<std::recursive_mutex> guard(m_mutex); + m_tried_unwind_plan_eh_frame = true; + if (m_range.GetBaseAddress().IsValid()) { + Address current_pc(m_range.GetBaseAddress()); + if (current_offset != -1) + current_pc.SetOffset(current_pc.GetOffset() + current_offset); + DWARFCallFrameInfo *eh_frame = m_unwind_table.GetEHFrameInfo(); + if (eh_frame) { + m_unwind_plan_eh_frame_sp.reset( + new UnwindPlan(lldb::eRegisterKindGeneric)); + if (!eh_frame->GetUnwindPlan(current_pc, *m_unwind_plan_eh_frame_sp)) + m_unwind_plan_eh_frame_sp.reset(); } - return m_unwind_plan_arm_unwind_sp; + } + return m_unwind_plan_eh_frame_sp; } -UnwindPlanSP -FuncUnwinders::GetEHFrameAugmentedUnwindPlan (Target &target, Thread &thread, int current_offset) -{ - if (m_unwind_plan_eh_frame_augmented_sp.get() || m_tried_unwind_plan_eh_frame_augmented) - return m_unwind_plan_eh_frame_augmented_sp; - - // Only supported on x86 architectures where we get eh_frame from the compiler that describes - // the prologue instructions perfectly, and sometimes the epilogue instructions too. - if (target.GetArchitecture().GetCore() != ArchSpec::eCore_x86_32_i386 - && target.GetArchitecture().GetCore() != ArchSpec::eCore_x86_64_x86_64 - && target.GetArchitecture().GetCore() != ArchSpec::eCore_x86_64_x86_64h) - { - m_tried_unwind_plan_eh_frame_augmented = true; - return m_unwind_plan_eh_frame_augmented_sp; +UnwindPlanSP FuncUnwinders::GetArmUnwindUnwindPlan(Target &target, + int current_offset) { + if (m_unwind_plan_arm_unwind_sp.get() || m_tried_unwind_plan_arm_unwind) + return m_unwind_plan_arm_unwind_sp; + + std::lock_guard<std::recursive_mutex> guard(m_mutex); + m_tried_unwind_plan_arm_unwind = true; + if (m_range.GetBaseAddress().IsValid()) { + Address current_pc(m_range.GetBaseAddress()); + if (current_offset != -1) + current_pc.SetOffset(current_pc.GetOffset() + current_offset); + ArmUnwindInfo *arm_unwind_info = m_unwind_table.GetArmUnwindInfo(); + if (arm_unwind_info) { + m_unwind_plan_arm_unwind_sp.reset( + new UnwindPlan(lldb::eRegisterKindGeneric)); + if (!arm_unwind_info->GetUnwindPlan(target, current_pc, + *m_unwind_plan_arm_unwind_sp)) + m_unwind_plan_arm_unwind_sp.reset(); } + } + return m_unwind_plan_arm_unwind_sp; +} + +UnwindPlanSP FuncUnwinders::GetEHFrameAugmentedUnwindPlan(Target &target, + Thread &thread, + int current_offset) { + if (m_unwind_plan_eh_frame_augmented_sp.get() || + m_tried_unwind_plan_eh_frame_augmented) + return m_unwind_plan_eh_frame_augmented_sp; - std::lock_guard<std::recursive_mutex> guard(m_mutex); + // Only supported on x86 architectures where we get eh_frame from the compiler + // that describes + // the prologue instructions perfectly, and sometimes the epilogue + // instructions too. + if (target.GetArchitecture().GetCore() != ArchSpec::eCore_x86_32_i386 && + target.GetArchitecture().GetCore() != ArchSpec::eCore_x86_64_x86_64 && + target.GetArchitecture().GetCore() != ArchSpec::eCore_x86_64_x86_64h) { m_tried_unwind_plan_eh_frame_augmented = true; + return m_unwind_plan_eh_frame_augmented_sp; + } - UnwindPlanSP eh_frame_plan = GetEHFrameUnwindPlan (target, current_offset); - if (!eh_frame_plan) - return m_unwind_plan_eh_frame_augmented_sp; + std::lock_guard<std::recursive_mutex> guard(m_mutex); + m_tried_unwind_plan_eh_frame_augmented = true; - m_unwind_plan_eh_frame_augmented_sp.reset(new UnwindPlan(*eh_frame_plan)); + UnwindPlanSP eh_frame_plan = GetEHFrameUnwindPlan(target, current_offset); + if (!eh_frame_plan) + return m_unwind_plan_eh_frame_augmented_sp; - // Augment the eh_frame instructions with epilogue descriptions if necessary so the - // UnwindPlan can be used at any instruction in the function. + m_unwind_plan_eh_frame_augmented_sp.reset(new UnwindPlan(*eh_frame_plan)); - UnwindAssemblySP assembly_profiler_sp (GetUnwindAssemblyProfiler(target)); - if (assembly_profiler_sp) - { - if (!assembly_profiler_sp->AugmentUnwindPlanFromCallSite (m_range, thread, *m_unwind_plan_eh_frame_augmented_sp)) - { - m_unwind_plan_eh_frame_augmented_sp.reset(); - } - } - else - { - m_unwind_plan_eh_frame_augmented_sp.reset(); + // Augment the eh_frame instructions with epilogue descriptions if necessary + // so the + // UnwindPlan can be used at any instruction in the function. + + UnwindAssemblySP assembly_profiler_sp(GetUnwindAssemblyProfiler(target)); + if (assembly_profiler_sp) { + if (!assembly_profiler_sp->AugmentUnwindPlanFromCallSite( + m_range, thread, *m_unwind_plan_eh_frame_augmented_sp)) { + m_unwind_plan_eh_frame_augmented_sp.reset(); } - return m_unwind_plan_eh_frame_augmented_sp; + } else { + m_unwind_plan_eh_frame_augmented_sp.reset(); + } + return m_unwind_plan_eh_frame_augmented_sp; } +UnwindPlanSP FuncUnwinders::GetAssemblyUnwindPlan(Target &target, + Thread &thread, + int current_offset) { + if (m_unwind_plan_assembly_sp.get() || m_tried_unwind_plan_assembly || + m_unwind_table.GetAllowAssemblyEmulationUnwindPlans() == false) { + return m_unwind_plan_assembly_sp; + } -UnwindPlanSP -FuncUnwinders::GetAssemblyUnwindPlan (Target &target, Thread &thread, int current_offset) -{ - if (m_unwind_plan_assembly_sp.get() - || m_tried_unwind_plan_assembly - || m_unwind_table.GetAllowAssemblyEmulationUnwindPlans () == false) - { - return m_unwind_plan_assembly_sp; - } + std::lock_guard<std::recursive_mutex> guard(m_mutex); + m_tried_unwind_plan_assembly = true; - std::lock_guard<std::recursive_mutex> guard(m_mutex); - m_tried_unwind_plan_assembly = true; - - UnwindAssemblySP assembly_profiler_sp (GetUnwindAssemblyProfiler(target)); - if (assembly_profiler_sp) - { - m_unwind_plan_assembly_sp.reset (new UnwindPlan (lldb::eRegisterKindGeneric)); - if (!assembly_profiler_sp->GetNonCallSiteUnwindPlanFromAssembly (m_range, thread, *m_unwind_plan_assembly_sp)) - { - m_unwind_plan_assembly_sp.reset(); - } + UnwindAssemblySP assembly_profiler_sp(GetUnwindAssemblyProfiler(target)); + if (assembly_profiler_sp) { + m_unwind_plan_assembly_sp.reset(new UnwindPlan(lldb::eRegisterKindGeneric)); + if (!assembly_profiler_sp->GetNonCallSiteUnwindPlanFromAssembly( + m_range, thread, *m_unwind_plan_assembly_sp)) { + m_unwind_plan_assembly_sp.reset(); } - return m_unwind_plan_assembly_sp; + } + return m_unwind_plan_assembly_sp; } // This method compares the pc unwind rule in the first row of two UnwindPlans. -// If they have the same way of getting the pc value (e.g. "CFA - 8" + "CFA is sp"), +// If they have the same way of getting the pc value (e.g. "CFA - 8" + "CFA is +// sp"), // then it will return LazyBoolTrue. -LazyBool -FuncUnwinders::CompareUnwindPlansForIdenticalInitialPCLocation (Thread& thread, const UnwindPlanSP &a, const UnwindPlanSP &b) -{ - LazyBool plans_are_identical = eLazyBoolCalculate; - - RegisterNumber pc_reg (thread, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC); - uint32_t pc_reg_lldb_regnum = pc_reg.GetAsKind (eRegisterKindLLDB); - - if (a.get() && b.get()) - { - UnwindPlan::RowSP a_first_row = a->GetRowAtIndex (0); - UnwindPlan::RowSP b_first_row = b->GetRowAtIndex (0); - - if (a_first_row.get() && b_first_row.get()) - { - UnwindPlan::Row::RegisterLocation a_pc_regloc; - UnwindPlan::Row::RegisterLocation b_pc_regloc; - - a_first_row->GetRegisterInfo (pc_reg_lldb_regnum, a_pc_regloc); - b_first_row->GetRegisterInfo (pc_reg_lldb_regnum, b_pc_regloc); - - plans_are_identical = eLazyBoolYes; - - if (a_first_row->GetCFAValue() != b_first_row->GetCFAValue()) - { - plans_are_identical = eLazyBoolNo; - } - if (a_pc_regloc != b_pc_regloc) - { - plans_are_identical = eLazyBoolNo; - } - } - } - return plans_are_identical; -} +LazyBool FuncUnwinders::CompareUnwindPlansForIdenticalInitialPCLocation( + Thread &thread, const UnwindPlanSP &a, const UnwindPlanSP &b) { + LazyBool plans_are_identical = eLazyBoolCalculate; -UnwindPlanSP -FuncUnwinders::GetUnwindPlanAtNonCallSite (Target& target, Thread& thread, int current_offset) -{ - UnwindPlanSP eh_frame_sp = GetEHFrameUnwindPlan (target, current_offset); - UnwindPlanSP arch_default_at_entry_sp = GetUnwindPlanArchitectureDefaultAtFunctionEntry (thread); - UnwindPlanSP arch_default_sp = GetUnwindPlanArchitectureDefault (thread); - UnwindPlanSP assembly_sp = GetAssemblyUnwindPlan (target, thread, current_offset); - - // This point of this code is to detect when a function is using a non-standard ABI, and the eh_frame - // correctly describes that alternate ABI. This is addressing a specific situation on x86_64 linux - // systems where one function in a library pushes a value on the stack and jumps to another function. - // So using an assembly instruction based unwind will not work when you're in the second function - - // the stack has been modified in a non-ABI way. But we have eh_frame that correctly describes how to - // unwind from this location. So we're looking to see if the initial pc register save location from - // the eh_frame is different from the assembly unwind, the arch default unwind, and the arch default at - // initial function entry. - // - // We may have eh_frame that describes the entire function -- or we may have eh_frame that only describes - // the unwind after the prologue has executed -- so we need to check both the arch default (once the prologue - // has executed) and the arch default at initial function entry. And we may be running on a target where - // we have only some of the assembly/arch default unwind plans available. - - if (CompareUnwindPlansForIdenticalInitialPCLocation (thread, eh_frame_sp, arch_default_at_entry_sp) == eLazyBoolNo - && CompareUnwindPlansForIdenticalInitialPCLocation (thread, eh_frame_sp, arch_default_sp) == eLazyBoolNo - && CompareUnwindPlansForIdenticalInitialPCLocation (thread, assembly_sp, arch_default_sp) == eLazyBoolNo) - { - return eh_frame_sp; - } + RegisterNumber pc_reg(thread, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC); + uint32_t pc_reg_lldb_regnum = pc_reg.GetAsKind(eRegisterKindLLDB); + + if (a.get() && b.get()) { + UnwindPlan::RowSP a_first_row = a->GetRowAtIndex(0); + UnwindPlan::RowSP b_first_row = b->GetRowAtIndex(0); + + if (a_first_row.get() && b_first_row.get()) { + UnwindPlan::Row::RegisterLocation a_pc_regloc; + UnwindPlan::Row::RegisterLocation b_pc_regloc; + + a_first_row->GetRegisterInfo(pc_reg_lldb_regnum, a_pc_regloc); + b_first_row->GetRegisterInfo(pc_reg_lldb_regnum, b_pc_regloc); - UnwindPlanSP eh_frame_augmented_sp = GetEHFrameAugmentedUnwindPlan (target, thread, current_offset); - if (eh_frame_augmented_sp) - { - return eh_frame_augmented_sp; + plans_are_identical = eLazyBoolYes; + + if (a_first_row->GetCFAValue() != b_first_row->GetCFAValue()) { + plans_are_identical = eLazyBoolNo; + } + if (a_pc_regloc != b_pc_regloc) { + plans_are_identical = eLazyBoolNo; + } } + } + return plans_are_identical; +} - return assembly_sp; +UnwindPlanSP FuncUnwinders::GetUnwindPlanAtNonCallSite(Target &target, + Thread &thread, + int current_offset) { + UnwindPlanSP eh_frame_sp = GetEHFrameUnwindPlan(target, current_offset); + UnwindPlanSP arch_default_at_entry_sp = + GetUnwindPlanArchitectureDefaultAtFunctionEntry(thread); + UnwindPlanSP arch_default_sp = GetUnwindPlanArchitectureDefault(thread); + UnwindPlanSP assembly_sp = + GetAssemblyUnwindPlan(target, thread, current_offset); + + // This point of this code is to detect when a function is using a + // non-standard ABI, and the eh_frame + // correctly describes that alternate ABI. This is addressing a specific + // situation on x86_64 linux + // systems where one function in a library pushes a value on the stack and + // jumps to another function. + // So using an assembly instruction based unwind will not work when you're in + // the second function - + // the stack has been modified in a non-ABI way. But we have eh_frame that + // correctly describes how to + // unwind from this location. So we're looking to see if the initial pc + // register save location from + // the eh_frame is different from the assembly unwind, the arch default + // unwind, and the arch default at + // initial function entry. + // + // We may have eh_frame that describes the entire function -- or we may have + // eh_frame that only describes + // the unwind after the prologue has executed -- so we need to check both the + // arch default (once the prologue + // has executed) and the arch default at initial function entry. And we may + // be running on a target where + // we have only some of the assembly/arch default unwind plans available. + + if (CompareUnwindPlansForIdenticalInitialPCLocation( + thread, eh_frame_sp, arch_default_at_entry_sp) == eLazyBoolNo && + CompareUnwindPlansForIdenticalInitialPCLocation( + thread, eh_frame_sp, arch_default_sp) == eLazyBoolNo && + CompareUnwindPlansForIdenticalInitialPCLocation( + thread, assembly_sp, arch_default_sp) == eLazyBoolNo) { + return eh_frame_sp; + } + + UnwindPlanSP eh_frame_augmented_sp = + GetEHFrameAugmentedUnwindPlan(target, thread, current_offset); + if (eh_frame_augmented_sp) { + return eh_frame_augmented_sp; + } + + return assembly_sp; } -UnwindPlanSP -FuncUnwinders::GetUnwindPlanFastUnwind (Target& target, Thread& thread) -{ - if (m_unwind_plan_fast_sp.get() || m_tried_unwind_fast) - return m_unwind_plan_fast_sp; - - std::lock_guard<std::recursive_mutex> guard(m_mutex); - m_tried_unwind_fast = true; - - UnwindAssemblySP assembly_profiler_sp (GetUnwindAssemblyProfiler(target)); - if (assembly_profiler_sp) - { - m_unwind_plan_fast_sp.reset (new UnwindPlan (lldb::eRegisterKindGeneric)); - if (!assembly_profiler_sp->GetFastUnwindPlan (m_range, thread, *m_unwind_plan_fast_sp)) - { - m_unwind_plan_fast_sp.reset(); - } - } +UnwindPlanSP FuncUnwinders::GetUnwindPlanFastUnwind(Target &target, + Thread &thread) { + if (m_unwind_plan_fast_sp.get() || m_tried_unwind_fast) return m_unwind_plan_fast_sp; -} -UnwindPlanSP -FuncUnwinders::GetUnwindPlanArchitectureDefault (Thread& thread) -{ - if (m_unwind_plan_arch_default_sp.get() || m_tried_unwind_arch_default) - return m_unwind_plan_arch_default_sp; - - std::lock_guard<std::recursive_mutex> guard(m_mutex); - m_tried_unwind_arch_default = true; - - Address current_pc; - ProcessSP process_sp (thread.CalculateProcess()); - if (process_sp) - { - ABI *abi = process_sp->GetABI().get(); - if (abi) - { - m_unwind_plan_arch_default_sp.reset (new UnwindPlan (lldb::eRegisterKindGeneric)); - if (!abi->CreateDefaultUnwindPlan(*m_unwind_plan_arch_default_sp)) - { - m_unwind_plan_arch_default_sp.reset(); - } - } + std::lock_guard<std::recursive_mutex> guard(m_mutex); + m_tried_unwind_fast = true; + + UnwindAssemblySP assembly_profiler_sp(GetUnwindAssemblyProfiler(target)); + if (assembly_profiler_sp) { + m_unwind_plan_fast_sp.reset(new UnwindPlan(lldb::eRegisterKindGeneric)); + if (!assembly_profiler_sp->GetFastUnwindPlan(m_range, thread, + *m_unwind_plan_fast_sp)) { + m_unwind_plan_fast_sp.reset(); } + } + return m_unwind_plan_fast_sp; +} +UnwindPlanSP FuncUnwinders::GetUnwindPlanArchitectureDefault(Thread &thread) { + if (m_unwind_plan_arch_default_sp.get() || m_tried_unwind_arch_default) return m_unwind_plan_arch_default_sp; -} -UnwindPlanSP -FuncUnwinders::GetUnwindPlanArchitectureDefaultAtFunctionEntry (Thread& thread) -{ - if (m_unwind_plan_arch_default_at_func_entry_sp.get() || m_tried_unwind_arch_default_at_func_entry) - return m_unwind_plan_arch_default_at_func_entry_sp; - - std::lock_guard<std::recursive_mutex> guard(m_mutex); - m_tried_unwind_arch_default_at_func_entry = true; - - Address current_pc; - ProcessSP process_sp (thread.CalculateProcess()); - if (process_sp) - { - ABI *abi = process_sp->GetABI().get(); - if (abi) - { - m_unwind_plan_arch_default_at_func_entry_sp.reset (new UnwindPlan (lldb::eRegisterKindGeneric)); - if (!abi->CreateFunctionEntryUnwindPlan(*m_unwind_plan_arch_default_at_func_entry_sp)) - { - m_unwind_plan_arch_default_at_func_entry_sp.reset(); - } - } + std::lock_guard<std::recursive_mutex> guard(m_mutex); + m_tried_unwind_arch_default = true; + + Address current_pc; + ProcessSP process_sp(thread.CalculateProcess()); + if (process_sp) { + ABI *abi = process_sp->GetABI().get(); + if (abi) { + m_unwind_plan_arch_default_sp.reset( + new UnwindPlan(lldb::eRegisterKindGeneric)); + if (!abi->CreateDefaultUnwindPlan(*m_unwind_plan_arch_default_sp)) { + m_unwind_plan_arch_default_sp.reset(); + } } + } - return m_unwind_plan_arch_default_at_func_entry_sp; + return m_unwind_plan_arch_default_sp; } +UnwindPlanSP +FuncUnwinders::GetUnwindPlanArchitectureDefaultAtFunctionEntry(Thread &thread) { + if (m_unwind_plan_arch_default_at_func_entry_sp.get() || + m_tried_unwind_arch_default_at_func_entry) + return m_unwind_plan_arch_default_at_func_entry_sp; + + std::lock_guard<std::recursive_mutex> guard(m_mutex); + m_tried_unwind_arch_default_at_func_entry = true; + + Address current_pc; + ProcessSP process_sp(thread.CalculateProcess()); + if (process_sp) { + ABI *abi = process_sp->GetABI().get(); + if (abi) { + m_unwind_plan_arch_default_at_func_entry_sp.reset( + new UnwindPlan(lldb::eRegisterKindGeneric)); + if (!abi->CreateFunctionEntryUnwindPlan( + *m_unwind_plan_arch_default_at_func_entry_sp)) { + m_unwind_plan_arch_default_at_func_entry_sp.reset(); + } + } + } -Address& -FuncUnwinders::GetFirstNonPrologueInsn (Target& target) -{ - if (m_first_non_prologue_insn.IsValid()) - return m_first_non_prologue_insn; + return m_unwind_plan_arch_default_at_func_entry_sp; +} - std::lock_guard<std::recursive_mutex> guard(m_mutex); - ExecutionContext exe_ctx (target.shared_from_this(), false); - UnwindAssemblySP assembly_profiler_sp (GetUnwindAssemblyProfiler(target)); - if (assembly_profiler_sp) - assembly_profiler_sp->FirstNonPrologueInsn (m_range, exe_ctx, m_first_non_prologue_insn); +Address &FuncUnwinders::GetFirstNonPrologueInsn(Target &target) { + if (m_first_non_prologue_insn.IsValid()) return m_first_non_prologue_insn; + + std::lock_guard<std::recursive_mutex> guard(m_mutex); + ExecutionContext exe_ctx(target.shared_from_this(), false); + UnwindAssemblySP assembly_profiler_sp(GetUnwindAssemblyProfiler(target)); + if (assembly_profiler_sp) + assembly_profiler_sp->FirstNonPrologueInsn(m_range, exe_ctx, + m_first_non_prologue_insn); + return m_first_non_prologue_insn; } -const Address& -FuncUnwinders::GetFunctionStartAddress () const -{ - return m_range.GetBaseAddress(); +const Address &FuncUnwinders::GetFunctionStartAddress() const { + return m_range.GetBaseAddress(); } lldb::UnwindAssemblySP -FuncUnwinders::GetUnwindAssemblyProfiler (Target& target) -{ - UnwindAssemblySP assembly_profiler_sp; - ArchSpec arch; - if (m_unwind_table.GetArchitecture (arch)) - { - arch.MergeFrom (target.GetArchitecture ()); - assembly_profiler_sp = UnwindAssembly::FindPlugin (arch); - } - return assembly_profiler_sp; +FuncUnwinders::GetUnwindAssemblyProfiler(Target &target) { + UnwindAssemblySP assembly_profiler_sp; + ArchSpec arch; + if (m_unwind_table.GetArchitecture(arch)) { + arch.MergeFrom(target.GetArchitecture()); + assembly_profiler_sp = UnwindAssembly::FindPlugin(arch); + } + return assembly_profiler_sp; } -Address -FuncUnwinders::GetLSDAAddress (Target &target) -{ - Address lsda_addr; - - UnwindPlanSP unwind_plan_sp = GetEHFrameUnwindPlan (target, -1); - if (unwind_plan_sp.get() == nullptr) - { - unwind_plan_sp = GetCompactUnwindUnwindPlan (target, -1); - } - if (unwind_plan_sp.get() && unwind_plan_sp->GetLSDAAddress().IsValid()) - { - lsda_addr = unwind_plan_sp->GetLSDAAddress(); - } - return lsda_addr; +Address FuncUnwinders::GetLSDAAddress(Target &target) { + Address lsda_addr; + + UnwindPlanSP unwind_plan_sp = GetEHFrameUnwindPlan(target, -1); + if (unwind_plan_sp.get() == nullptr) { + unwind_plan_sp = GetCompactUnwindUnwindPlan(target, -1); + } + if (unwind_plan_sp.get() && unwind_plan_sp->GetLSDAAddress().IsValid()) { + lsda_addr = unwind_plan_sp->GetLSDAAddress(); + } + return lsda_addr; } +Address FuncUnwinders::GetPersonalityRoutinePtrAddress(Target &target) { + Address personality_addr; -Address -FuncUnwinders::GetPersonalityRoutinePtrAddress (Target &target) -{ - Address personality_addr; - - UnwindPlanSP unwind_plan_sp = GetEHFrameUnwindPlan (target, -1); - if (unwind_plan_sp.get() == nullptr) - { - unwind_plan_sp = GetCompactUnwindUnwindPlan (target, -1); - } - if (unwind_plan_sp.get() && unwind_plan_sp->GetPersonalityFunctionPtr().IsValid()) - { - personality_addr = unwind_plan_sp->GetPersonalityFunctionPtr(); - } + UnwindPlanSP unwind_plan_sp = GetEHFrameUnwindPlan(target, -1); + if (unwind_plan_sp.get() == nullptr) { + unwind_plan_sp = GetCompactUnwindUnwindPlan(target, -1); + } + if (unwind_plan_sp.get() && + unwind_plan_sp->GetPersonalityFunctionPtr().IsValid()) { + personality_addr = unwind_plan_sp->GetPersonalityFunctionPtr(); + } - return personality_addr; + return personality_addr; } diff --git a/lldb/source/Symbol/Function.cpp b/lldb/source/Symbol/Function.cpp index 598af270bdd..06f8ad56bde 100644 --- a/lldb/source/Symbol/Function.cpp +++ b/lldb/source/Symbol/Function.cpp @@ -12,8 +12,8 @@ #include "lldb/Core/Module.h" #include "lldb/Core/Section.h" #include "lldb/Host/Host.h" -#include "lldb/Symbol/CompilerType.h" #include "lldb/Symbol/CompileUnit.h" +#include "lldb/Symbol/CompilerType.h" #include "lldb/Symbol/LineTable.h" #include "lldb/Symbol/SymbolFile.h" #include "lldb/Symbol/SymbolVendor.h" @@ -28,685 +28,508 @@ using namespace lldb_private; // It is designed to contain the name, linkage name, and declaration // location. //---------------------------------------------------------------------- -FunctionInfo::FunctionInfo (const char *name, const Declaration *decl_ptr) : - m_name(name), - m_declaration(decl_ptr) -{ +FunctionInfo::FunctionInfo(const char *name, const Declaration *decl_ptr) + : m_name(name), m_declaration(decl_ptr) {} + +FunctionInfo::FunctionInfo(const ConstString &name, const Declaration *decl_ptr) + : m_name(name), m_declaration(decl_ptr) {} + +FunctionInfo::~FunctionInfo() {} + +void FunctionInfo::Dump(Stream *s, bool show_fullpaths) const { + if (m_name) + *s << ", name = \"" << m_name << "\""; + m_declaration.Dump(s, show_fullpaths); } +int FunctionInfo::Compare(const FunctionInfo &a, const FunctionInfo &b) { + int result = ConstString::Compare(a.GetName(), b.GetName()); + if (result) + return result; -FunctionInfo::FunctionInfo (const ConstString& name, const Declaration *decl_ptr) : - m_name(name), - m_declaration(decl_ptr) -{ + return Declaration::Compare(a.m_declaration, b.m_declaration); } +Declaration &FunctionInfo::GetDeclaration() { return m_declaration; } -FunctionInfo::~FunctionInfo() -{ +const Declaration &FunctionInfo::GetDeclaration() const { + return m_declaration; } -void -FunctionInfo::Dump(Stream *s, bool show_fullpaths) const -{ - if (m_name) - *s << ", name = \"" << m_name << "\""; - m_declaration.Dump(s, show_fullpaths); +ConstString FunctionInfo::GetName() const { return m_name; } + +size_t FunctionInfo::MemorySize() const { + return m_name.MemorySize() + m_declaration.MemorySize(); } +InlineFunctionInfo::InlineFunctionInfo(const char *name, const char *mangled, + const Declaration *decl_ptr, + const Declaration *call_decl_ptr) + : FunctionInfo(name, decl_ptr), m_mangled(ConstString(mangled), true), + m_call_decl(call_decl_ptr) {} -int -FunctionInfo::Compare(const FunctionInfo& a, const FunctionInfo& b) -{ - int result = ConstString::Compare(a.GetName(), b.GetName()); - if (result) - return result; +InlineFunctionInfo::InlineFunctionInfo(const ConstString &name, + const Mangled &mangled, + const Declaration *decl_ptr, + const Declaration *call_decl_ptr) + : FunctionInfo(name, decl_ptr), m_mangled(mangled), + m_call_decl(call_decl_ptr) {} - return Declaration::Compare(a.m_declaration, b.m_declaration); -} +InlineFunctionInfo::~InlineFunctionInfo() {} +int InlineFunctionInfo::Compare(const InlineFunctionInfo &a, + const InlineFunctionInfo &b) { -Declaration& -FunctionInfo::GetDeclaration() -{ - return m_declaration; + int result = FunctionInfo::Compare(a, b); + if (result) + return result; + // only compare the mangled names if both have them + return Mangled::Compare(a.m_mangled, a.m_mangled); } -const Declaration& -FunctionInfo::GetDeclaration() const -{ - return m_declaration; +void InlineFunctionInfo::Dump(Stream *s, bool show_fullpaths) const { + FunctionInfo::Dump(s, show_fullpaths); + if (m_mangled) + m_mangled.Dump(s); } -ConstString -FunctionInfo::GetName() const -{ - return m_name; +void InlineFunctionInfo::DumpStopContext(Stream *s, + LanguageType language) const { + // s->Indent("[inlined] "); + s->Indent(); + if (m_mangled) + s->PutCString(m_mangled.GetName(language).AsCString()); + else + s->PutCString(m_name.AsCString()); } -size_t -FunctionInfo::MemorySize() const -{ - return m_name.MemorySize() + m_declaration.MemorySize(); +ConstString InlineFunctionInfo::GetName(LanguageType language) const { + if (m_mangled) + return m_mangled.GetName(language); + return m_name; } - -InlineFunctionInfo::InlineFunctionInfo -( - const char *name, - const char *mangled, - const Declaration *decl_ptr, - const Declaration *call_decl_ptr -) : - FunctionInfo(name, decl_ptr), - m_mangled(ConstString(mangled), true), - m_call_decl (call_decl_ptr) -{ +ConstString InlineFunctionInfo::GetDisplayName(LanguageType language) const { + if (m_mangled) + return m_mangled.GetDisplayDemangledName(language); + return m_name; } -InlineFunctionInfo::InlineFunctionInfo -( - const ConstString& name, - const Mangled &mangled, - const Declaration *decl_ptr, - const Declaration *call_decl_ptr -) : - FunctionInfo(name, decl_ptr), - m_mangled(mangled), - m_call_decl (call_decl_ptr) -{ -} +Declaration &InlineFunctionInfo::GetCallSite() { return m_call_decl; } -InlineFunctionInfo::~InlineFunctionInfo() -{ +const Declaration &InlineFunctionInfo::GetCallSite() const { + return m_call_decl; } -int -InlineFunctionInfo::Compare(const InlineFunctionInfo& a, const InlineFunctionInfo& b) -{ +Mangled &InlineFunctionInfo::GetMangled() { return m_mangled; } - int result = FunctionInfo::Compare(a, b); - if (result) - return result; - // only compare the mangled names if both have them - return Mangled::Compare(a.m_mangled, a.m_mangled); -} +const Mangled &InlineFunctionInfo::GetMangled() const { return m_mangled; } -void -InlineFunctionInfo::Dump(Stream *s, bool show_fullpaths) const -{ - FunctionInfo::Dump(s, show_fullpaths); - if (m_mangled) - m_mangled.Dump(s); +size_t InlineFunctionInfo::MemorySize() const { + return FunctionInfo::MemorySize() + m_mangled.MemorySize(); } -void -InlineFunctionInfo::DumpStopContext (Stream *s, LanguageType language) const -{ -// s->Indent("[inlined] "); - s->Indent(); - if (m_mangled) - s->PutCString (m_mangled.GetName(language).AsCString()); - else - s->PutCString (m_name.AsCString()); +//---------------------------------------------------------------------- +// +//---------------------------------------------------------------------- +Function::Function(CompileUnit *comp_unit, lldb::user_id_t func_uid, + lldb::user_id_t type_uid, const Mangled &mangled, Type *type, + const AddressRange &range) + : UserID(func_uid), m_comp_unit(comp_unit), m_type_uid(type_uid), + m_type(type), m_mangled(mangled), m_block(func_uid), m_range(range), + m_frame_base(nullptr), m_flags(), m_prologue_byte_size(0) { + m_block.SetParentScope(this); + assert(comp_unit != nullptr); +} + +Function::Function(CompileUnit *comp_unit, lldb::user_id_t func_uid, + lldb::user_id_t type_uid, const char *mangled, Type *type, + const AddressRange &range) + : UserID(func_uid), m_comp_unit(comp_unit), m_type_uid(type_uid), + m_type(type), m_mangled(ConstString(mangled), true), m_block(func_uid), + m_range(range), m_frame_base(nullptr), m_flags(), + m_prologue_byte_size(0) { + m_block.SetParentScope(this); + assert(comp_unit != nullptr); +} + +Function::~Function() {} + +void Function::GetStartLineSourceInfo(FileSpec &source_file, + uint32_t &line_no) { + line_no = 0; + source_file.Clear(); + + if (m_comp_unit == nullptr) + return; + + if (m_type != nullptr && m_type->GetDeclaration().GetLine() != 0) { + source_file = m_type->GetDeclaration().GetFile(); + line_no = m_type->GetDeclaration().GetLine(); + } else { + LineTable *line_table = m_comp_unit->GetLineTable(); + if (line_table == nullptr) + return; + + LineEntry line_entry; + if (line_table->FindLineEntryByAddress(GetAddressRange().GetBaseAddress(), + line_entry, nullptr)) { + line_no = line_entry.line; + source_file = line_entry.file; + } + } +} + +void Function::GetEndLineSourceInfo(FileSpec &source_file, uint32_t &line_no) { + line_no = 0; + source_file.Clear(); + + // The -1 is kind of cheesy, but I want to get the last line entry for the + // given function, not the + // first entry of the next. + Address scratch_addr(GetAddressRange().GetBaseAddress()); + scratch_addr.SetOffset(scratch_addr.GetOffset() + + GetAddressRange().GetByteSize() - 1); + + LineTable *line_table = m_comp_unit->GetLineTable(); + if (line_table == nullptr) + return; + + LineEntry line_entry; + if (line_table->FindLineEntryByAddress(scratch_addr, line_entry, nullptr)) { + line_no = line_entry.line; + source_file = line_entry.file; + } +} + +Block &Function::GetBlock(bool can_create) { + if (!m_block.BlockInfoHasBeenParsed() && can_create) { + SymbolContext sc; + CalculateSymbolContext(&sc); + if (sc.module_sp) { + sc.module_sp->GetSymbolVendor()->ParseFunctionBlocks(sc); + } else { + Host::SystemLog(Host::eSystemLogError, "error: unable to find module " + "shared pointer for function '%s' " + "in %s\n", + GetName().GetCString(), m_comp_unit->GetPath().c_str()); + } + m_block.SetBlockInfoHasBeenParsed(true, true); + } + return m_block; } +CompileUnit *Function::GetCompileUnit() { return m_comp_unit; } -ConstString -InlineFunctionInfo::GetName (LanguageType language) const -{ - if (m_mangled) - return m_mangled.GetName(language); - return m_name; -} +const CompileUnit *Function::GetCompileUnit() const { return m_comp_unit; } + +void Function::GetDescription(Stream *s, lldb::DescriptionLevel level, + Target *target) { + Type *func_type = GetType(); + const char *name = func_type ? func_type->GetName().AsCString() : "<unknown>"; + + *s << "id = " << (const UserID &)*this << ", name = \"" << name + << "\", range = "; -ConstString -InlineFunctionInfo::GetDisplayName (LanguageType language) const -{ - if (m_mangled) - return m_mangled.GetDisplayDemangledName(language); - return m_name; + Address::DumpStyle fallback_style; + if (level == eDescriptionLevelVerbose) + fallback_style = Address::DumpStyleModuleWithFileAddress; + else + fallback_style = Address::DumpStyleFileAddress; + GetAddressRange().Dump(s, target, Address::DumpStyleLoadAddress, + fallback_style); } -Declaration & -InlineFunctionInfo::GetCallSite () -{ - return m_call_decl; +void Function::Dump(Stream *s, bool show_context) const { + s->Printf("%p: ", static_cast<const void *>(this)); + s->Indent(); + *s << "Function" << static_cast<const UserID &>(*this); + + m_mangled.Dump(s); + + if (m_type) + s->Printf(", type = %p", static_cast<void *>(m_type)); + else if (m_type_uid != LLDB_INVALID_UID) + s->Printf(", type_uid = 0x%8.8" PRIx64, m_type_uid); + + s->EOL(); + // Dump the root object + if (m_block.BlockInfoHasBeenParsed()) + m_block.Dump(s, m_range.GetBaseAddress().GetFileAddress(), INT_MAX, + show_context); } -const Declaration & -InlineFunctionInfo::GetCallSite () const -{ - return m_call_decl; +void Function::CalculateSymbolContext(SymbolContext *sc) { + sc->function = this; + m_comp_unit->CalculateSymbolContext(sc); } +ModuleSP Function::CalculateSymbolContextModule() { + SectionSP section_sp(m_range.GetBaseAddress().GetSection()); + if (section_sp) + return section_sp->GetModule(); -Mangled& -InlineFunctionInfo::GetMangled() -{ - return m_mangled; + return this->GetCompileUnit()->GetModule(); } -const Mangled& -InlineFunctionInfo::GetMangled() const -{ - return m_mangled; +CompileUnit *Function::CalculateSymbolContextCompileUnit() { + return this->GetCompileUnit(); } -size_t -InlineFunctionInfo::MemorySize() const -{ - return FunctionInfo::MemorySize() + m_mangled.MemorySize(); -} +Function *Function::CalculateSymbolContextFunction() { return this; } -//---------------------------------------------------------------------- -// -//---------------------------------------------------------------------- -Function::Function -( - CompileUnit *comp_unit, - lldb::user_id_t func_uid, - lldb::user_id_t type_uid, - const Mangled &mangled, - Type * type, - const AddressRange& range -) : - UserID (func_uid), - m_comp_unit (comp_unit), - m_type_uid (type_uid), - m_type (type), - m_mangled (mangled), - m_block (func_uid), - m_range (range), - m_frame_base (nullptr), - m_flags (), - m_prologue_byte_size (0) -{ - m_block.SetParentScope(this); - assert(comp_unit != nullptr); -} - -Function::Function -( - CompileUnit *comp_unit, - lldb::user_id_t func_uid, - lldb::user_id_t type_uid, - const char *mangled, - Type *type, - const AddressRange &range -) : - UserID (func_uid), - m_comp_unit (comp_unit), - m_type_uid (type_uid), - m_type (type), - m_mangled (ConstString(mangled), true), - m_block (func_uid), - m_range (range), - m_frame_base (nullptr), - m_flags (), - m_prologue_byte_size (0) -{ - m_block.SetParentScope(this); - assert(comp_unit != nullptr); -} - - -Function::~Function() -{ -} - -void -Function::GetStartLineSourceInfo (FileSpec &source_file, uint32_t &line_no) -{ - line_no = 0; - source_file.Clear(); - - if (m_comp_unit == nullptr) - return; - - if (m_type != nullptr && m_type->GetDeclaration().GetLine() != 0) - { - source_file = m_type->GetDeclaration().GetFile(); - line_no = m_type->GetDeclaration().GetLine(); - } - else - { - LineTable *line_table = m_comp_unit->GetLineTable(); - if (line_table == nullptr) - return; - - LineEntry line_entry; - if (line_table->FindLineEntryByAddress (GetAddressRange().GetBaseAddress(), line_entry, nullptr)) - { - line_no = line_entry.line; - source_file = line_entry.file; - } - } +lldb::DisassemblerSP Function::GetInstructions(const ExecutionContext &exe_ctx, + const char *flavor, + bool prefer_file_cache) { + ModuleSP module_sp(GetAddressRange().GetBaseAddress().GetModule()); + if (module_sp) { + const bool prefer_file_cache = false; + return Disassembler::DisassembleRange(module_sp->GetArchitecture(), nullptr, + flavor, exe_ctx, GetAddressRange(), + prefer_file_cache); + } + return lldb::DisassemblerSP(); } -void -Function::GetEndLineSourceInfo (FileSpec &source_file, uint32_t &line_no) -{ - line_no = 0; - source_file.Clear(); - - // The -1 is kind of cheesy, but I want to get the last line entry for the given function, not the - // first entry of the next. - Address scratch_addr(GetAddressRange().GetBaseAddress()); - scratch_addr.SetOffset (scratch_addr.GetOffset() + GetAddressRange().GetByteSize() - 1); - - LineTable *line_table = m_comp_unit->GetLineTable(); - if (line_table == nullptr) - return; - - LineEntry line_entry; - if (line_table->FindLineEntryByAddress (scratch_addr, line_entry, nullptr)) - { - line_no = line_entry.line; - source_file = line_entry.file; - } +bool Function::GetDisassembly(const ExecutionContext &exe_ctx, + const char *flavor, bool prefer_file_cache, + Stream &strm) { + lldb::DisassemblerSP disassembler_sp = + GetInstructions(exe_ctx, flavor, prefer_file_cache); + if (disassembler_sp) { + const bool show_address = true; + const bool show_bytes = false; + disassembler_sp->GetInstructionList().Dump(&strm, show_address, show_bytes, + &exe_ctx); + return true; + } + return false; } -Block & -Function::GetBlock (bool can_create) -{ - if (!m_block.BlockInfoHasBeenParsed() && can_create) - { - SymbolContext sc; - CalculateSymbolContext(&sc); - if (sc.module_sp) - { - sc.module_sp->GetSymbolVendor()->ParseFunctionBlocks(sc); - } - else - { - Host::SystemLog (Host::eSystemLogError, - "error: unable to find module shared pointer for function '%s' in %s\n", - GetName().GetCString(), - m_comp_unit->GetPath().c_str()); - } - m_block.SetBlockInfoHasBeenParsed (true, true); - } - return m_block; +// Symbol * +// Function::CalculateSymbolContextSymbol () +//{ +// return // TODO: find the symbol for the function??? +//} + +void Function::DumpSymbolContext(Stream *s) { + m_comp_unit->DumpSymbolContext(s); + s->Printf(", Function{0x%8.8" PRIx64 "}", GetID()); } -CompileUnit* -Function::GetCompileUnit() -{ - return m_comp_unit; +size_t Function::MemorySize() const { + size_t mem_size = sizeof(Function) + m_block.MemorySize(); + return mem_size; } -const CompileUnit* -Function::GetCompileUnit() const -{ - return m_comp_unit; +bool Function::GetIsOptimized() { + bool result = false; + + // Currently optimization is only indicted by the + // vendor extension DW_AT_APPLE_optimized which + // is set on a compile unit level. + if (m_comp_unit) { + result = m_comp_unit->GetIsOptimized(); + } + return result; } +bool Function::IsTopLevelFunction() { + bool result = false; + + if (Language *language = Language::FindPlugin(GetLanguage())) + result = language->IsTopLevelFunction(*this); -void -Function::GetDescription(Stream *s, lldb::DescriptionLevel level, Target *target) -{ - Type* func_type = GetType(); - const char *name = func_type ? func_type->GetName().AsCString() : "<unknown>"; - - *s << "id = " << (const UserID&)*this << ", name = \"" << name << "\", range = "; - - Address::DumpStyle fallback_style; - if (level == eDescriptionLevelVerbose) - fallback_style = Address::DumpStyleModuleWithFileAddress; - else - fallback_style = Address::DumpStyleFileAddress; - GetAddressRange().Dump(s, target, Address::DumpStyleLoadAddress, fallback_style); + return result; } -void -Function::Dump(Stream *s, bool show_context) const -{ - s->Printf("%p: ", static_cast<const void*>(this)); - s->Indent(); - *s << "Function" << static_cast<const UserID&>(*this); +ConstString Function::GetDisplayName() const { + if (!m_mangled) + return ConstString(); + return m_mangled.GetDisplayDemangledName(GetLanguage()); +} - m_mangled.Dump(s); +CompilerDeclContext Function::GetDeclContext() { + ModuleSP module_sp = CalculateSymbolContextModule(); - if (m_type) - s->Printf(", type = %p", static_cast<void*>(m_type)); - else if (m_type_uid != LLDB_INVALID_UID) - s->Printf(", type_uid = 0x%8.8" PRIx64, m_type_uid); - - s->EOL(); - // Dump the root object - if (m_block.BlockInfoHasBeenParsed ()) - m_block.Dump(s, m_range.GetBaseAddress().GetFileAddress(), INT_MAX, show_context); -} - - -void -Function::CalculateSymbolContext(SymbolContext* sc) -{ - sc->function = this; - m_comp_unit->CalculateSymbolContext(sc); -} - -ModuleSP -Function::CalculateSymbolContextModule () -{ - SectionSP section_sp (m_range.GetBaseAddress().GetSection()); - if (section_sp) - return section_sp->GetModule(); - - return this->GetCompileUnit()->GetModule(); -} - -CompileUnit * -Function::CalculateSymbolContextCompileUnit () -{ - return this->GetCompileUnit(); -} - -Function * -Function::CalculateSymbolContextFunction () -{ - return this; -} - -lldb::DisassemblerSP -Function::GetInstructions (const ExecutionContext &exe_ctx, - const char *flavor, - bool prefer_file_cache) -{ - ModuleSP module_sp (GetAddressRange().GetBaseAddress().GetModule()); - if (module_sp) - { - const bool prefer_file_cache = false; - return Disassembler::DisassembleRange (module_sp->GetArchitecture(), - nullptr, - flavor, - exe_ctx, - GetAddressRange(), - prefer_file_cache); - } - return lldb::DisassemblerSP(); -} - -bool -Function::GetDisassembly (const ExecutionContext &exe_ctx, - const char *flavor, - bool prefer_file_cache, - Stream &strm) -{ - lldb::DisassemblerSP disassembler_sp = GetInstructions (exe_ctx, flavor, prefer_file_cache); - if (disassembler_sp) - { - const bool show_address = true; - const bool show_bytes = false; - disassembler_sp->GetInstructionList().Dump (&strm, show_address, show_bytes, &exe_ctx); - return true; + if (module_sp) { + SymbolVendor *sym_vendor = module_sp->GetSymbolVendor(); + + if (sym_vendor) { + SymbolFile *sym_file = sym_vendor->GetSymbolFile(); + + if (sym_file) + return sym_file->GetDeclContextForUID(GetID()); } - return false; + } + return CompilerDeclContext(); } +Type *Function::GetType() { + if (m_type == nullptr) { + SymbolContext sc; -//Symbol * -//Function::CalculateSymbolContextSymbol () -//{ -// return // TODO: find the symbol for the function??? -//} + CalculateSymbolContext(&sc); + if (!sc.module_sp) + return nullptr; -void -Function::DumpSymbolContext(Stream *s) -{ - m_comp_unit->DumpSymbolContext(s); - s->Printf(", Function{0x%8.8" PRIx64 "}", GetID()); -} + SymbolVendor *sym_vendor = sc.module_sp->GetSymbolVendor(); -size_t -Function::MemorySize () const -{ - size_t mem_size = sizeof(Function) + m_block.MemorySize(); - return mem_size; -} + if (sym_vendor == nullptr) + return nullptr; -bool -Function::GetIsOptimized () -{ - bool result = false; + SymbolFile *sym_file = sym_vendor->GetSymbolFile(); - // Currently optimization is only indicted by the - // vendor extension DW_AT_APPLE_optimized which - // is set on a compile unit level. - if (m_comp_unit) - { - result = m_comp_unit->GetIsOptimized(); - } - return result; -} + if (sym_file == nullptr) + return nullptr; -bool -Function::IsTopLevelFunction () -{ - bool result = false; - - if (Language* language = Language::FindPlugin(GetLanguage())) - result = language->IsTopLevelFunction(*this); - - return result; + m_type = sym_file->ResolveTypeUID(m_type_uid); + } + return m_type; } -ConstString -Function::GetDisplayName () const -{ - if (!m_mangled) - return ConstString(); - return m_mangled.GetDisplayDemangledName(GetLanguage()); +const Type *Function::GetType() const { return m_type; } + +CompilerType Function::GetCompilerType() { + Type *function_type = GetType(); + if (function_type) + return function_type->GetFullCompilerType(); + return CompilerType(); } -CompilerDeclContext -Function::GetDeclContext() -{ - ModuleSP module_sp = CalculateSymbolContextModule (); +uint32_t Function::GetPrologueByteSize() { + if (m_prologue_byte_size == 0 && + m_flags.IsClear(flagsCalculatedPrologueSize)) { + m_flags.Set(flagsCalculatedPrologueSize); + LineTable *line_table = m_comp_unit->GetLineTable(); + uint32_t prologue_end_line_idx = 0; + + if (line_table) { + LineEntry first_line_entry; + uint32_t first_line_entry_idx = UINT32_MAX; + if (line_table->FindLineEntryByAddress(GetAddressRange().GetBaseAddress(), + first_line_entry, + &first_line_entry_idx)) { + // Make sure the first line entry isn't already the end of the prologue + addr_t prologue_end_file_addr = LLDB_INVALID_ADDRESS; + addr_t line_zero_end_file_addr = LLDB_INVALID_ADDRESS; + + if (first_line_entry.is_prologue_end) { + prologue_end_file_addr = + first_line_entry.range.GetBaseAddress().GetFileAddress(); + prologue_end_line_idx = first_line_entry_idx; + } else { + // Check the first few instructions and look for one that has + // is_prologue_end set to true. + const uint32_t last_line_entry_idx = first_line_entry_idx + 6; + for (uint32_t idx = first_line_entry_idx + 1; + idx < last_line_entry_idx; ++idx) { + LineEntry line_entry; + if (line_table->GetLineEntryAtIndex(idx, line_entry)) { + if (line_entry.is_prologue_end) { + prologue_end_file_addr = + line_entry.range.GetBaseAddress().GetFileAddress(); + prologue_end_line_idx = idx; + break; + } + } + } + } - if (module_sp) - { - SymbolVendor *sym_vendor = module_sp->GetSymbolVendor(); + // If we didn't find the end of the prologue in the line tables, + // then just use the end address of the first line table entry + if (prologue_end_file_addr == LLDB_INVALID_ADDRESS) { + // Check the first few instructions and look for one that has + // a line number that's different than the first entry. + uint32_t last_line_entry_idx = first_line_entry_idx + 6; + for (uint32_t idx = first_line_entry_idx + 1; + idx < last_line_entry_idx; ++idx) { + LineEntry line_entry; + if (line_table->GetLineEntryAtIndex(idx, line_entry)) { + if (line_entry.line != first_line_entry.line) { + prologue_end_file_addr = + line_entry.range.GetBaseAddress().GetFileAddress(); + prologue_end_line_idx = idx; + break; + } + } + } + + if (prologue_end_file_addr == LLDB_INVALID_ADDRESS) { + prologue_end_file_addr = + first_line_entry.range.GetBaseAddress().GetFileAddress() + + first_line_entry.range.GetByteSize(); + prologue_end_line_idx = first_line_entry_idx; + } + } - if (sym_vendor) - { - SymbolFile *sym_file = sym_vendor->GetSymbolFile(); + const addr_t func_start_file_addr = + m_range.GetBaseAddress().GetFileAddress(); + const addr_t func_end_file_addr = + func_start_file_addr + m_range.GetByteSize(); + + // Now calculate the offset to pass the subsequent line 0 entries. + uint32_t first_non_zero_line = prologue_end_line_idx; + while (1) { + LineEntry line_entry; + if (line_table->GetLineEntryAtIndex(first_non_zero_line, + line_entry)) { + if (line_entry.line != 0) + break; + } + if (line_entry.range.GetBaseAddress().GetFileAddress() >= + func_end_file_addr) + break; + + first_non_zero_line++; + } - if (sym_file) - return sym_file->GetDeclContextForUID (GetID()); + if (first_non_zero_line > prologue_end_line_idx) { + LineEntry first_non_zero_entry; + if (line_table->GetLineEntryAtIndex(first_non_zero_line, + first_non_zero_entry)) { + line_zero_end_file_addr = + first_non_zero_entry.range.GetBaseAddress().GetFileAddress(); + } } - } - return CompilerDeclContext(); -} - -Type* -Function::GetType() -{ - if (m_type == nullptr) - { - SymbolContext sc; - - CalculateSymbolContext (&sc); - - if (!sc.module_sp) - return nullptr; - - SymbolVendor *sym_vendor = sc.module_sp->GetSymbolVendor(); - - if (sym_vendor == nullptr) - return nullptr; - - SymbolFile *sym_file = sym_vendor->GetSymbolFile(); - - if (sym_file == nullptr) - return nullptr; - - m_type = sym_file->ResolveTypeUID(m_type_uid); - } - return m_type; -} - -const Type* -Function::GetType() const -{ - return m_type; -} - -CompilerType -Function::GetCompilerType() -{ - Type *function_type = GetType(); - if (function_type) - return function_type->GetFullCompilerType (); - return CompilerType(); -} - -uint32_t -Function::GetPrologueByteSize () -{ - if (m_prologue_byte_size == 0 && m_flags.IsClear(flagsCalculatedPrologueSize)) - { - m_flags.Set(flagsCalculatedPrologueSize); - LineTable* line_table = m_comp_unit->GetLineTable (); - uint32_t prologue_end_line_idx = 0; - - if (line_table) - { - LineEntry first_line_entry; - uint32_t first_line_entry_idx = UINT32_MAX; - if (line_table->FindLineEntryByAddress(GetAddressRange().GetBaseAddress(), first_line_entry, &first_line_entry_idx)) - { - // Make sure the first line entry isn't already the end of the prologue - addr_t prologue_end_file_addr = LLDB_INVALID_ADDRESS; - addr_t line_zero_end_file_addr = LLDB_INVALID_ADDRESS; - - if (first_line_entry.is_prologue_end) - { - prologue_end_file_addr = first_line_entry.range.GetBaseAddress().GetFileAddress(); - prologue_end_line_idx = first_line_entry_idx; - } - else - { - // Check the first few instructions and look for one that has - // is_prologue_end set to true. - const uint32_t last_line_entry_idx = first_line_entry_idx + 6; - for (uint32_t idx = first_line_entry_idx + 1; idx < last_line_entry_idx; ++idx) - { - LineEntry line_entry; - if (line_table->GetLineEntryAtIndex (idx, line_entry)) - { - if (line_entry.is_prologue_end) - { - prologue_end_file_addr = line_entry.range.GetBaseAddress().GetFileAddress(); - prologue_end_line_idx = idx; - break; - } - } - } - } - - // If we didn't find the end of the prologue in the line tables, - // then just use the end address of the first line table entry - if (prologue_end_file_addr == LLDB_INVALID_ADDRESS) - { - // Check the first few instructions and look for one that has - // a line number that's different than the first entry. - uint32_t last_line_entry_idx = first_line_entry_idx + 6; - for (uint32_t idx = first_line_entry_idx + 1; idx < last_line_entry_idx; ++idx) - { - LineEntry line_entry; - if (line_table->GetLineEntryAtIndex (idx, line_entry)) - { - if (line_entry.line != first_line_entry.line) - { - prologue_end_file_addr = line_entry.range.GetBaseAddress().GetFileAddress(); - prologue_end_line_idx = idx; - break; - } - } - } - - if (prologue_end_file_addr == LLDB_INVALID_ADDRESS) - { - prologue_end_file_addr = first_line_entry.range.GetBaseAddress().GetFileAddress() + first_line_entry.range.GetByteSize(); - prologue_end_line_idx = first_line_entry_idx; - } - } - - const addr_t func_start_file_addr = m_range.GetBaseAddress().GetFileAddress(); - const addr_t func_end_file_addr = func_start_file_addr + m_range.GetByteSize(); - - // Now calculate the offset to pass the subsequent line 0 entries. - uint32_t first_non_zero_line = prologue_end_line_idx; - while (1) - { - LineEntry line_entry; - if (line_table->GetLineEntryAtIndex(first_non_zero_line, line_entry)) - { - if (line_entry.line != 0) - break; - } - if (line_entry.range.GetBaseAddress().GetFileAddress() >= func_end_file_addr) - break; - - first_non_zero_line++; - } - - if (first_non_zero_line > prologue_end_line_idx) - { - LineEntry first_non_zero_entry; - if (line_table->GetLineEntryAtIndex(first_non_zero_line, first_non_zero_entry)) - { - line_zero_end_file_addr = first_non_zero_entry.range.GetBaseAddress().GetFileAddress(); - } - } - - // Verify that this prologue end file address in the function's - // address range just to be sure - if (func_start_file_addr < prologue_end_file_addr && prologue_end_file_addr < func_end_file_addr) - { - m_prologue_byte_size = prologue_end_file_addr - func_start_file_addr; - } - - if (prologue_end_file_addr < line_zero_end_file_addr && line_zero_end_file_addr < func_end_file_addr) - { - m_prologue_byte_size += line_zero_end_file_addr - prologue_end_file_addr; - } - } + + // Verify that this prologue end file address in the function's + // address range just to be sure + if (func_start_file_addr < prologue_end_file_addr && + prologue_end_file_addr < func_end_file_addr) { + m_prologue_byte_size = prologue_end_file_addr - func_start_file_addr; + } + + if (prologue_end_file_addr < line_zero_end_file_addr && + line_zero_end_file_addr < func_end_file_addr) { + m_prologue_byte_size += + line_zero_end_file_addr - prologue_end_file_addr; } + } } - - return m_prologue_byte_size; -} + } -lldb::LanguageType -Function::GetLanguage() const -{ - if (m_comp_unit) - return m_comp_unit->GetLanguage(); - else - return lldb::eLanguageTypeUnknown; + return m_prologue_byte_size; } -ConstString -Function::GetName() const -{ - LanguageType language = lldb::eLanguageTypeUnknown; - if (m_comp_unit) - language = m_comp_unit->GetLanguage(); - return m_mangled.GetName(language); +lldb::LanguageType Function::GetLanguage() const { + if (m_comp_unit) + return m_comp_unit->GetLanguage(); + else + return lldb::eLanguageTypeUnknown; } -ConstString -Function::GetNameNoArguments() const -{ - LanguageType language = lldb::eLanguageTypeUnknown; - if (m_comp_unit) - language = m_comp_unit->GetLanguage(); - return m_mangled.GetName(language, Mangled::ePreferDemangledWithoutArguments); +ConstString Function::GetName() const { + LanguageType language = lldb::eLanguageTypeUnknown; + if (m_comp_unit) + language = m_comp_unit->GetLanguage(); + return m_mangled.GetName(language); } - - +ConstString Function::GetNameNoArguments() const { + LanguageType language = lldb::eLanguageTypeUnknown; + if (m_comp_unit) + language = m_comp_unit->GetLanguage(); + return m_mangled.GetName(language, Mangled::ePreferDemangledWithoutArguments); +} diff --git a/lldb/source/Symbol/GoASTContext.cpp b/lldb/source/Symbol/GoASTContext.cpp index faca778f069..0c69007f4e0 100644 --- a/lldb/source/Symbol/GoASTContext.cpp +++ b/lldb/source/Symbol/GoASTContext.cpp @@ -18,9 +18,9 @@ #include "lldb/Core/ValueObject.h" #include "lldb/DataFormatters/StringPrinter.h" #include "lldb/Symbol/CompilerType.h" +#include "lldb/Symbol/GoASTContext.h" #include "lldb/Symbol/ObjectFile.h" #include "lldb/Symbol/SymbolFile.h" -#include "lldb/Symbol/GoASTContext.h" #include "lldb/Symbol/Type.h" #include "lldb/Target/ExecutionContext.h" #include "lldb/Target/Target.h" @@ -30,781 +30,610 @@ using namespace lldb; -namespace lldb_private -{ +namespace lldb_private { class GoArray; class GoFunction; class GoStruct; -class GoType -{ - public: - enum - { - KIND_BOOL = 1, - KIND_INT = 2, - KIND_INT8 = 3, - KIND_INT16 = 4, - KIND_INT32 = 5, - KIND_INT64 = 6, - KIND_UINT = 7, - KIND_UINT8 = 8, - KIND_UINT16 = 9, - KIND_UINT32 = 10, - KIND_UINT64 = 11, - KIND_UINTPTR = 12, - KIND_FLOAT32 = 13, - KIND_FLOAT64 = 14, - KIND_COMPLEX64 = 15, - KIND_COMPLEX128 = 16, - KIND_ARRAY = 17, - KIND_CHAN = 18, - KIND_FUNC = 19, - KIND_INTERFACE = 20, - KIND_MAP = 21, - KIND_PTR = 22, - KIND_SLICE = 23, - KIND_STRING = 24, - KIND_STRUCT = 25, - KIND_UNSAFEPOINTER = 26, - KIND_LLDB_VOID, // Extension for LLDB, not used by go runtime. - KIND_MASK = (1 << 5) - 1, - KIND_DIRECT_IFACE = 1 << 5 - }; - GoType(int kind, const ConstString &name) - : m_kind(kind & KIND_MASK) - , m_name(name) - { - if (m_kind == KIND_FUNC) - m_kind = KIND_FUNC; - } - virtual ~GoType() {} - - int - GetGoKind() const - { - return m_kind; - } - const ConstString & - GetName() const - { - return m_name; - } - virtual CompilerType - GetElementType() const - { - return CompilerType(); - } - - bool - IsTypedef() const - { - switch (m_kind) - { - case KIND_CHAN: - case KIND_MAP: - case KIND_INTERFACE: - return true; - default: - return false; - } +class GoType { +public: + enum { + KIND_BOOL = 1, + KIND_INT = 2, + KIND_INT8 = 3, + KIND_INT16 = 4, + KIND_INT32 = 5, + KIND_INT64 = 6, + KIND_UINT = 7, + KIND_UINT8 = 8, + KIND_UINT16 = 9, + KIND_UINT32 = 10, + KIND_UINT64 = 11, + KIND_UINTPTR = 12, + KIND_FLOAT32 = 13, + KIND_FLOAT64 = 14, + KIND_COMPLEX64 = 15, + KIND_COMPLEX128 = 16, + KIND_ARRAY = 17, + KIND_CHAN = 18, + KIND_FUNC = 19, + KIND_INTERFACE = 20, + KIND_MAP = 21, + KIND_PTR = 22, + KIND_SLICE = 23, + KIND_STRING = 24, + KIND_STRUCT = 25, + KIND_UNSAFEPOINTER = 26, + KIND_LLDB_VOID, // Extension for LLDB, not used by go runtime. + KIND_MASK = (1 << 5) - 1, + KIND_DIRECT_IFACE = 1 << 5 + }; + GoType(int kind, const ConstString &name) + : m_kind(kind & KIND_MASK), m_name(name) { + if (m_kind == KIND_FUNC) + m_kind = KIND_FUNC; + } + virtual ~GoType() {} + + int GetGoKind() const { return m_kind; } + const ConstString &GetName() const { return m_name; } + virtual CompilerType GetElementType() const { return CompilerType(); } + + bool IsTypedef() const { + switch (m_kind) { + case KIND_CHAN: + case KIND_MAP: + case KIND_INTERFACE: + return true; + default: + return false; } + } - GoArray *GetArray(); - GoFunction *GetFunction(); - GoStruct *GetStruct(); + GoArray *GetArray(); + GoFunction *GetFunction(); + GoStruct *GetStruct(); - private: - int m_kind; - ConstString m_name; - GoType(const GoType &) = delete; - const GoType &operator=(const GoType &) = delete; +private: + int m_kind; + ConstString m_name; + GoType(const GoType &) = delete; + const GoType &operator=(const GoType &) = delete; }; -class GoElem : public GoType -{ - public: - GoElem(int kind, const ConstString &name, const CompilerType &elem) - : GoType(kind, name) - , m_elem(elem) - { - } - virtual CompilerType - GetElementType() const - { - return m_elem; - } +class GoElem : public GoType { +public: + GoElem(int kind, const ConstString &name, const CompilerType &elem) + : GoType(kind, name), m_elem(elem) {} + virtual CompilerType GetElementType() const { return m_elem; } - private: - // TODO: should we store this differently? - CompilerType m_elem; +private: + // TODO: should we store this differently? + CompilerType m_elem; - GoElem(const GoElem &) = delete; - const GoElem &operator=(const GoElem &) = delete; + GoElem(const GoElem &) = delete; + const GoElem &operator=(const GoElem &) = delete; }; -class GoArray : public GoElem -{ - public: - GoArray(const ConstString &name, uint64_t length, const CompilerType &elem) - : GoElem(KIND_ARRAY, name, elem) - , m_length(length) - { - } +class GoArray : public GoElem { +public: + GoArray(const ConstString &name, uint64_t length, const CompilerType &elem) + : GoElem(KIND_ARRAY, name, elem), m_length(length) {} - uint64_t - GetLength() const - { - return m_length; - } + uint64_t GetLength() const { return m_length; } - private: - uint64_t m_length; - GoArray(const GoArray &) = delete; - const GoArray &operator=(const GoArray &) = delete; +private: + uint64_t m_length; + GoArray(const GoArray &) = delete; + const GoArray &operator=(const GoArray &) = delete; }; -class GoFunction : public GoType -{ - public: - GoFunction(const ConstString &name, bool is_variadic) - : GoType(KIND_FUNC, name) - , m_is_variadic(is_variadic) - { - } +class GoFunction : public GoType { +public: + GoFunction(const ConstString &name, bool is_variadic) + : GoType(KIND_FUNC, name), m_is_variadic(is_variadic) {} - bool - IsVariadic() const - { - return m_is_variadic; - } + bool IsVariadic() const { return m_is_variadic; } - private: - bool m_is_variadic; - GoFunction(const GoFunction &) = delete; - const GoFunction &operator=(const GoFunction &) = delete; +private: + bool m_is_variadic; + GoFunction(const GoFunction &) = delete; + const GoFunction &operator=(const GoFunction &) = delete; }; -class GoStruct : public GoType -{ - public: - struct Field - { - Field(const ConstString &name, const CompilerType &type, uint64_t offset) - : m_name(name) - , m_type(type) - , m_byte_offset(offset) - { - } - ConstString m_name; - CompilerType m_type; - uint64_t m_byte_offset; - }; - - GoStruct(int kind, const ConstString &name, int64_t byte_size) - : GoType(kind == 0 ? KIND_STRUCT : kind, name), m_is_complete(false), m_byte_size(byte_size) - { - } +class GoStruct : public GoType { +public: + struct Field { + Field(const ConstString &name, const CompilerType &type, uint64_t offset) + : m_name(name), m_type(type), m_byte_offset(offset) {} + ConstString m_name; + CompilerType m_type; + uint64_t m_byte_offset; + }; - uint32_t - GetNumFields() const - { - return m_fields.size(); - } + GoStruct(int kind, const ConstString &name, int64_t byte_size) + : GoType(kind == 0 ? KIND_STRUCT : kind, name), m_is_complete(false), + m_byte_size(byte_size) {} - const Field * - GetField(uint32_t i) const - { - if (i < m_fields.size()) - return &m_fields[i]; - return nullptr; - } + uint32_t GetNumFields() const { return m_fields.size(); } - void - AddField(const ConstString &name, const CompilerType &type, uint64_t offset) - { - m_fields.push_back(Field(name, type, offset)); - } + const Field *GetField(uint32_t i) const { + if (i < m_fields.size()) + return &m_fields[i]; + return nullptr; + } - bool - IsComplete() const - { - return m_is_complete; - } + void AddField(const ConstString &name, const CompilerType &type, + uint64_t offset) { + m_fields.push_back(Field(name, type, offset)); + } - void - SetComplete() - { - m_is_complete = true; - } + bool IsComplete() const { return m_is_complete; } - int64_t - GetByteSize() const - { - return m_byte_size; - } + void SetComplete() { m_is_complete = true; } - private: - bool m_is_complete; - int64_t m_byte_size; - std::vector<Field> m_fields; + int64_t GetByteSize() const { return m_byte_size; } - GoStruct(const GoStruct &) = delete; - const GoStruct &operator=(const GoStruct &) = delete; +private: + bool m_is_complete; + int64_t m_byte_size; + std::vector<Field> m_fields; + + GoStruct(const GoStruct &) = delete; + const GoStruct &operator=(const GoStruct &) = delete; }; -GoArray * -GoType::GetArray() -{ - if (m_kind == KIND_ARRAY) - { - return static_cast<GoArray *>(this); - } - return nullptr; +GoArray *GoType::GetArray() { + if (m_kind == KIND_ARRAY) { + return static_cast<GoArray *>(this); + } + return nullptr; } -GoFunction * -GoType::GetFunction() -{ - if (m_kind == KIND_FUNC) - { - return static_cast<GoFunction *>(this); - } - return nullptr; +GoFunction *GoType::GetFunction() { + if (m_kind == KIND_FUNC) { + return static_cast<GoFunction *>(this); + } + return nullptr; } -GoStruct * -GoType::GetStruct() -{ - switch (m_kind) - { - case KIND_STRING: - case KIND_STRUCT: - case KIND_SLICE: - return static_cast<GoStruct *>(this); - } - return nullptr; +GoStruct *GoType::GetStruct() { + switch (m_kind) { + case KIND_STRING: + case KIND_STRUCT: + case KIND_SLICE: + return static_cast<GoStruct *>(this); + } + return nullptr; } } // namespace lldb_private using namespace lldb_private; GoASTContext::GoASTContext() - : TypeSystem(eKindGo) - , m_pointer_byte_size(0) - , m_int_byte_size(0) - , m_types(new TypeMap) -{ -} -GoASTContext::~GoASTContext() -{ -} + : TypeSystem(eKindGo), m_pointer_byte_size(0), m_int_byte_size(0), + m_types(new TypeMap) {} +GoASTContext::~GoASTContext() {} //------------------------------------------------------------------ // PluginInterface functions //------------------------------------------------------------------ -ConstString -GoASTContext::GetPluginNameStatic() -{ - return ConstString("go"); -} +ConstString GoASTContext::GetPluginNameStatic() { return ConstString("go"); } -ConstString -GoASTContext::GetPluginName() -{ - return GoASTContext::GetPluginNameStatic(); +ConstString GoASTContext::GetPluginName() { + return GoASTContext::GetPluginNameStatic(); } -uint32_t -GoASTContext::GetPluginVersion() -{ - return 1; -} +uint32_t GoASTContext::GetPluginVersion() { return 1; } -lldb::TypeSystemSP -GoASTContext::CreateInstance (lldb::LanguageType language, Module *module, Target *target) -{ - if (language == eLanguageTypeGo) - { - ArchSpec arch; - std::shared_ptr<GoASTContext> go_ast_sp; - if (module) - { - arch = module->GetArchitecture(); - go_ast_sp = std::shared_ptr<GoASTContext>(new GoASTContext); - } - else if (target) - { - arch = target->GetArchitecture(); - go_ast_sp = std::shared_ptr<GoASTContextForExpr>(new GoASTContextForExpr(target->shared_from_this())); - } +lldb::TypeSystemSP GoASTContext::CreateInstance(lldb::LanguageType language, + Module *module, + Target *target) { + if (language == eLanguageTypeGo) { + ArchSpec arch; + std::shared_ptr<GoASTContext> go_ast_sp; + if (module) { + arch = module->GetArchitecture(); + go_ast_sp = std::shared_ptr<GoASTContext>(new GoASTContext); + } else if (target) { + arch = target->GetArchitecture(); + go_ast_sp = std::shared_ptr<GoASTContextForExpr>( + new GoASTContextForExpr(target->shared_from_this())); + } - if (arch.IsValid()) - { - go_ast_sp->SetAddressByteSize(arch.GetAddressByteSize()); - return go_ast_sp; - } + if (arch.IsValid()) { + go_ast_sp->SetAddressByteSize(arch.GetAddressByteSize()); + return go_ast_sp; } - return lldb::TypeSystemSP(); + } + return lldb::TypeSystemSP(); } -void -GoASTContext::EnumerateSupportedLanguages(std::set<lldb::LanguageType> &languages_for_types, std::set<lldb::LanguageType> &languages_for_expressions) -{ - static std::vector<lldb::LanguageType> s_supported_languages_for_types({ - lldb::eLanguageTypeGo}); - - static std::vector<lldb::LanguageType> s_supported_languages_for_expressions({}); - - languages_for_types.insert(s_supported_languages_for_types.begin(), s_supported_languages_for_types.end()); - languages_for_expressions.insert(s_supported_languages_for_expressions.begin(), s_supported_languages_for_expressions.end()); -} +void GoASTContext::EnumerateSupportedLanguages( + std::set<lldb::LanguageType> &languages_for_types, + std::set<lldb::LanguageType> &languages_for_expressions) { + static std::vector<lldb::LanguageType> s_supported_languages_for_types( + {lldb::eLanguageTypeGo}); + static std::vector<lldb::LanguageType> s_supported_languages_for_expressions( + {}); -void -GoASTContext::Initialize() -{ - PluginManager::RegisterPlugin (GetPluginNameStatic(), - "AST context plug-in", - CreateInstance, - EnumerateSupportedLanguages); + languages_for_types.insert(s_supported_languages_for_types.begin(), + s_supported_languages_for_types.end()); + languages_for_expressions.insert( + s_supported_languages_for_expressions.begin(), + s_supported_languages_for_expressions.end()); } -void -GoASTContext::Terminate() -{ - PluginManager::UnregisterPlugin (CreateInstance); +void GoASTContext::Initialize() { + PluginManager::RegisterPlugin(GetPluginNameStatic(), "AST context plug-in", + CreateInstance, EnumerateSupportedLanguages); } +void GoASTContext::Terminate() { + PluginManager::UnregisterPlugin(CreateInstance); +} //---------------------------------------------------------------------- // Tests //---------------------------------------------------------------------- -bool -GoASTContext::IsArrayType(lldb::opaque_compiler_type_t type, CompilerType *element_type, uint64_t *size, bool *is_incomplete) -{ - if (element_type) - element_type->Clear(); +bool GoASTContext::IsArrayType(lldb::opaque_compiler_type_t type, + CompilerType *element_type, uint64_t *size, + bool *is_incomplete) { + if (element_type) + element_type->Clear(); + if (size) + *size = 0; + if (is_incomplete) + *is_incomplete = false; + GoArray *array = static_cast<GoType *>(type)->GetArray(); + if (array) { if (size) - *size = 0; - if (is_incomplete) - *is_incomplete = false; - GoArray *array = static_cast<GoType *>(type)->GetArray(); - if (array) - { - if (size) - *size = array->GetLength(); - if (element_type) - *element_type = array->GetElementType(); - return true; - } - return false; -} - -bool -GoASTContext::IsVectorType(lldb::opaque_compiler_type_t type, CompilerType *element_type, uint64_t *size) -{ + *size = array->GetLength(); if (element_type) - element_type->Clear(); - if (size) - *size = 0; - return false; + *element_type = array->GetElementType(); + return true; + } + return false; } -bool -GoASTContext::IsAggregateType(lldb::opaque_compiler_type_t type) -{ - int kind = static_cast<GoType *>(type)->GetGoKind(); - if (kind < GoType::KIND_ARRAY) - return false; - if (kind == GoType::KIND_PTR) - return false; - if (kind == GoType::KIND_CHAN) - return false; - if (kind == GoType::KIND_MAP) - return false; - if (kind == GoType::KIND_STRING) - return false; - if (kind == GoType::KIND_UNSAFEPOINTER) - return false; - return true; +bool GoASTContext::IsVectorType(lldb::opaque_compiler_type_t type, + CompilerType *element_type, uint64_t *size) { + if (element_type) + element_type->Clear(); + if (size) + *size = 0; + return false; } -bool -GoASTContext::IsBeingDefined(lldb::opaque_compiler_type_t type) -{ +bool GoASTContext::IsAggregateType(lldb::opaque_compiler_type_t type) { + int kind = static_cast<GoType *>(type)->GetGoKind(); + if (kind < GoType::KIND_ARRAY) + return false; + if (kind == GoType::KIND_PTR) + return false; + if (kind == GoType::KIND_CHAN) + return false; + if (kind == GoType::KIND_MAP) + return false; + if (kind == GoType::KIND_STRING) return false; + if (kind == GoType::KIND_UNSAFEPOINTER) + return false; + return true; } -bool -GoASTContext::IsCharType(lldb::opaque_compiler_type_t type) -{ - // Go's DWARF doesn't distinguish between rune and int32. - return false; +bool GoASTContext::IsBeingDefined(lldb::opaque_compiler_type_t type) { + return false; } -bool -GoASTContext::IsCompleteType(lldb::opaque_compiler_type_t type) -{ - if (!type) - return false; - GoType *t = static_cast<GoType *>(type); - if (GoStruct *s = t->GetStruct()) - return s->IsComplete(); - if (t->IsTypedef() || t->GetGoKind() == GoType::KIND_PTR) - return t->GetElementType().IsCompleteType(); - return true; +bool GoASTContext::IsCharType(lldb::opaque_compiler_type_t type) { + // Go's DWARF doesn't distinguish between rune and int32. + return false; } -bool -GoASTContext::IsConst(lldb::opaque_compiler_type_t type) -{ +bool GoASTContext::IsCompleteType(lldb::opaque_compiler_type_t type) { + if (!type) return false; + GoType *t = static_cast<GoType *>(type); + if (GoStruct *s = t->GetStruct()) + return s->IsComplete(); + if (t->IsTypedef() || t->GetGoKind() == GoType::KIND_PTR) + return t->GetElementType().IsCompleteType(); + return true; } -bool -GoASTContext::IsCStringType(lldb::opaque_compiler_type_t type, uint32_t &length) -{ - return false; +bool GoASTContext::IsConst(lldb::opaque_compiler_type_t type) { return false; } + +bool GoASTContext::IsCStringType(lldb::opaque_compiler_type_t type, + uint32_t &length) { + return false; } -bool -GoASTContext::IsDefined(lldb::opaque_compiler_type_t type) -{ - return type != nullptr; +bool GoASTContext::IsDefined(lldb::opaque_compiler_type_t type) { + return type != nullptr; } -bool -GoASTContext::IsFloatingPointType(lldb::opaque_compiler_type_t type, uint32_t &count, bool &is_complex) -{ - int kind = static_cast<GoType *>(type)->GetGoKind(); - if (kind >= GoType::KIND_FLOAT32 && kind <= GoType::KIND_COMPLEX128) - { - if (kind >= GoType::KIND_COMPLEX64) - { - is_complex = true; - count = 2; - } - else - { - is_complex = false; - count = 1; - } - return true; +bool GoASTContext::IsFloatingPointType(lldb::opaque_compiler_type_t type, + uint32_t &count, bool &is_complex) { + int kind = static_cast<GoType *>(type)->GetGoKind(); + if (kind >= GoType::KIND_FLOAT32 && kind <= GoType::KIND_COMPLEX128) { + if (kind >= GoType::KIND_COMPLEX64) { + is_complex = true; + count = 2; + } else { + is_complex = false; + count = 1; } - count = 0; - is_complex = false; - return false; + return true; + } + count = 0; + is_complex = false; + return false; } -bool -GoASTContext::IsFunctionType(lldb::opaque_compiler_type_t type, bool *is_variadic_ptr) -{ - GoFunction *func = static_cast<GoType *>(type)->GetFunction(); - if (func) - { - if (is_variadic_ptr) - *is_variadic_ptr = func->IsVariadic(); - return true; - } +bool GoASTContext::IsFunctionType(lldb::opaque_compiler_type_t type, + bool *is_variadic_ptr) { + GoFunction *func = static_cast<GoType *>(type)->GetFunction(); + if (func) { if (is_variadic_ptr) - *is_variadic_ptr = false; - return false; + *is_variadic_ptr = func->IsVariadic(); + return true; + } + if (is_variadic_ptr) + *is_variadic_ptr = false; + return false; } -uint32_t -GoASTContext::IsHomogeneousAggregate(lldb::opaque_compiler_type_t type, CompilerType *base_type_ptr) -{ - return false; +uint32_t GoASTContext::IsHomogeneousAggregate(lldb::opaque_compiler_type_t type, + CompilerType *base_type_ptr) { + return false; } size_t -GoASTContext::GetNumberOfFunctionArguments(lldb::opaque_compiler_type_t type) -{ - return 0; +GoASTContext::GetNumberOfFunctionArguments(lldb::opaque_compiler_type_t type) { + return 0; } CompilerType -GoASTContext::GetFunctionArgumentAtIndex(lldb::opaque_compiler_type_t type, const size_t index) -{ - return CompilerType(); +GoASTContext::GetFunctionArgumentAtIndex(lldb::opaque_compiler_type_t type, + const size_t index) { + return CompilerType(); } -bool -GoASTContext::IsFunctionPointerType(lldb::opaque_compiler_type_t type) -{ - return IsFunctionType(type); +bool GoASTContext::IsFunctionPointerType(lldb::opaque_compiler_type_t type) { + return IsFunctionType(type); } -bool -GoASTContext::IsBlockPointerType (lldb::opaque_compiler_type_t type, CompilerType *function_pointer_type_ptr) -{ - return false; +bool GoASTContext::IsBlockPointerType(lldb::opaque_compiler_type_t type, + CompilerType *function_pointer_type_ptr) { + return false; } -bool -GoASTContext::IsIntegerType(lldb::opaque_compiler_type_t type, bool &is_signed) -{ - is_signed = false; - // TODO: Is bool an integer? - if (type) - { - int kind = static_cast<GoType *>(type)->GetGoKind(); - if (kind <= GoType::KIND_UINTPTR) - { - is_signed = (kind != GoType::KIND_BOOL) & (kind <= GoType::KIND_INT64); - return true; - } +bool GoASTContext::IsIntegerType(lldb::opaque_compiler_type_t type, + bool &is_signed) { + is_signed = false; + // TODO: Is bool an integer? + if (type) { + int kind = static_cast<GoType *>(type)->GetGoKind(); + if (kind <= GoType::KIND_UINTPTR) { + is_signed = (kind != GoType::KIND_BOOL) & (kind <= GoType::KIND_INT64); + return true; } - return false; + } + return false; } -bool -GoASTContext::IsPolymorphicClass(lldb::opaque_compiler_type_t type) -{ - return false; +bool GoASTContext::IsPolymorphicClass(lldb::opaque_compiler_type_t type) { + return false; } -bool -GoASTContext::IsPossibleDynamicType(lldb::opaque_compiler_type_t type, - CompilerType *target_type, // Can pass NULL - bool check_cplusplus, bool check_objc) -{ - if (target_type) - target_type->Clear(); - if (type) - return static_cast<GoType *>(type)->GetGoKind() == GoType::KIND_INTERFACE; - return false; +bool GoASTContext::IsPossibleDynamicType( + lldb::opaque_compiler_type_t type, + CompilerType *target_type, // Can pass NULL + bool check_cplusplus, bool check_objc) { + if (target_type) + target_type->Clear(); + if (type) + return static_cast<GoType *>(type)->GetGoKind() == GoType::KIND_INTERFACE; + return false; } -bool -GoASTContext::IsRuntimeGeneratedType(lldb::opaque_compiler_type_t type) -{ - return false; +bool GoASTContext::IsRuntimeGeneratedType(lldb::opaque_compiler_type_t type) { + return false; } -bool -GoASTContext::IsPointerType(lldb::opaque_compiler_type_t type, CompilerType *pointee_type) -{ - if (!type) - return false; - GoType *t = static_cast<GoType *>(type); - if (pointee_type) - { - *pointee_type = t->GetElementType(); - } - switch (t->GetGoKind()) - { - case GoType::KIND_PTR: - case GoType::KIND_UNSAFEPOINTER: - case GoType::KIND_CHAN: - case GoType::KIND_MAP: - // TODO: is function a pointer? - return true; - default: - return false; - } +bool GoASTContext::IsPointerType(lldb::opaque_compiler_type_t type, + CompilerType *pointee_type) { + if (!type) + return false; + GoType *t = static_cast<GoType *>(type); + if (pointee_type) { + *pointee_type = t->GetElementType(); + } + switch (t->GetGoKind()) { + case GoType::KIND_PTR: + case GoType::KIND_UNSAFEPOINTER: + case GoType::KIND_CHAN: + case GoType::KIND_MAP: + // TODO: is function a pointer? + return true; + default: + return false; + } } -bool -GoASTContext::IsPointerOrReferenceType(lldb::opaque_compiler_type_t type, CompilerType *pointee_type) -{ - return IsPointerType(type, pointee_type); +bool GoASTContext::IsPointerOrReferenceType(lldb::opaque_compiler_type_t type, + CompilerType *pointee_type) { + return IsPointerType(type, pointee_type); } -bool -GoASTContext::IsReferenceType(lldb::opaque_compiler_type_t type, CompilerType *pointee_type, bool *is_rvalue) -{ - return false; +bool GoASTContext::IsReferenceType(lldb::opaque_compiler_type_t type, + CompilerType *pointee_type, + bool *is_rvalue) { + return false; } -bool -GoASTContext::IsScalarType(lldb::opaque_compiler_type_t type) -{ - return !IsAggregateType(type); +bool GoASTContext::IsScalarType(lldb::opaque_compiler_type_t type) { + return !IsAggregateType(type); } -bool -GoASTContext::IsTypedefType(lldb::opaque_compiler_type_t type) -{ - if (type) - return static_cast<GoType *>(type)->IsTypedef(); - return false; +bool GoASTContext::IsTypedefType(lldb::opaque_compiler_type_t type) { + if (type) + return static_cast<GoType *>(type)->IsTypedef(); + return false; } -bool -GoASTContext::IsVoidType(lldb::opaque_compiler_type_t type) -{ - if (!type) - return false; - return static_cast<GoType *>(type)->GetGoKind() == GoType::KIND_LLDB_VOID; +bool GoASTContext::IsVoidType(lldb::opaque_compiler_type_t type) { + if (!type) + return false; + return static_cast<GoType *>(type)->GetGoKind() == GoType::KIND_LLDB_VOID; } -bool -GoASTContext::SupportsLanguage (lldb::LanguageType language) -{ - return language == eLanguageTypeGo; +bool GoASTContext::SupportsLanguage(lldb::LanguageType language) { + return language == eLanguageTypeGo; } //---------------------------------------------------------------------- // Type Completion //---------------------------------------------------------------------- -bool -GoASTContext::GetCompleteType(lldb::opaque_compiler_type_t type) -{ - if (!type) - return false; - GoType *t = static_cast<GoType *>(type); - if (t->IsTypedef() || t->GetGoKind() == GoType::KIND_PTR || t->GetArray()) - return t->GetElementType().GetCompleteType(); - if (GoStruct *s = t->GetStruct()) - { - if (s->IsComplete()) - return true; - CompilerType compiler_type(this, s); - SymbolFile *symbols = GetSymbolFile(); - return symbols && symbols->CompleteType(compiler_type); - } - return true; +bool GoASTContext::GetCompleteType(lldb::opaque_compiler_type_t type) { + if (!type) + return false; + GoType *t = static_cast<GoType *>(type); + if (t->IsTypedef() || t->GetGoKind() == GoType::KIND_PTR || t->GetArray()) + return t->GetElementType().GetCompleteType(); + if (GoStruct *s = t->GetStruct()) { + if (s->IsComplete()) + return true; + CompilerType compiler_type(this, s); + SymbolFile *symbols = GetSymbolFile(); + return symbols && symbols->CompleteType(compiler_type); + } + return true; } //---------------------------------------------------------------------- // AST related queries //---------------------------------------------------------------------- -uint32_t -GoASTContext::GetPointerByteSize() -{ - return m_pointer_byte_size; -} +uint32_t GoASTContext::GetPointerByteSize() { return m_pointer_byte_size; } //---------------------------------------------------------------------- // Accessors //---------------------------------------------------------------------- -ConstString -GoASTContext::GetTypeName(lldb::opaque_compiler_type_t type) -{ - if (type) - return static_cast<GoType *>(type)->GetName(); - return ConstString(); +ConstString GoASTContext::GetTypeName(lldb::opaque_compiler_type_t type) { + if (type) + return static_cast<GoType *>(type)->GetName(); + return ConstString(); } uint32_t -GoASTContext::GetTypeInfo(lldb::opaque_compiler_type_t type, CompilerType *pointee_or_element_compiler_type) -{ - if (pointee_or_element_compiler_type) - pointee_or_element_compiler_type->Clear(); - if (!type) - return 0; - GoType *t = static_cast<GoType *>(type); - if (pointee_or_element_compiler_type) - *pointee_or_element_compiler_type = t->GetElementType(); - int kind = t->GetGoKind(); - if (kind == GoType::KIND_ARRAY) - return eTypeHasChildren | eTypeIsArray; - if (kind < GoType::KIND_ARRAY) - { - uint32_t builtin_type_flags = eTypeIsBuiltIn | eTypeHasValue; - if (kind < GoType::KIND_FLOAT32) - { - builtin_type_flags |= eTypeIsInteger | eTypeIsScalar; - if (kind >= GoType::KIND_INT && kind <= GoType::KIND_INT64) - builtin_type_flags |= eTypeIsSigned; - } - else - { - builtin_type_flags |= eTypeIsFloat; - if (kind < GoType::KIND_COMPLEX64) - builtin_type_flags |= eTypeIsComplex; - else - builtin_type_flags |= eTypeIsScalar; - } - return builtin_type_flags; +GoASTContext::GetTypeInfo(lldb::opaque_compiler_type_t type, + CompilerType *pointee_or_element_compiler_type) { + if (pointee_or_element_compiler_type) + pointee_or_element_compiler_type->Clear(); + if (!type) + return 0; + GoType *t = static_cast<GoType *>(type); + if (pointee_or_element_compiler_type) + *pointee_or_element_compiler_type = t->GetElementType(); + int kind = t->GetGoKind(); + if (kind == GoType::KIND_ARRAY) + return eTypeHasChildren | eTypeIsArray; + if (kind < GoType::KIND_ARRAY) { + uint32_t builtin_type_flags = eTypeIsBuiltIn | eTypeHasValue; + if (kind < GoType::KIND_FLOAT32) { + builtin_type_flags |= eTypeIsInteger | eTypeIsScalar; + if (kind >= GoType::KIND_INT && kind <= GoType::KIND_INT64) + builtin_type_flags |= eTypeIsSigned; + } else { + builtin_type_flags |= eTypeIsFloat; + if (kind < GoType::KIND_COMPLEX64) + builtin_type_flags |= eTypeIsComplex; + else + builtin_type_flags |= eTypeIsScalar; } - if (kind == GoType::KIND_STRING) - return eTypeHasValue | eTypeIsBuiltIn; - if (kind == GoType::KIND_FUNC) - return eTypeIsFuncPrototype | eTypeHasValue; - if (IsPointerType(type)) - return eTypeIsPointer | eTypeHasValue | eTypeHasChildren; - if (kind == GoType::KIND_LLDB_VOID) - return 0; - return eTypeHasChildren | eTypeIsStructUnion; -} - -lldb::TypeClass -GoASTContext::GetTypeClass(lldb::opaque_compiler_type_t type) -{ - if (!type) - return eTypeClassInvalid; - int kind = static_cast<GoType *>(type)->GetGoKind(); - if (kind == GoType::KIND_FUNC) - return eTypeClassFunction; - if (IsPointerType(type)) - return eTypeClassPointer; - if (kind < GoType::KIND_COMPLEX64) - return eTypeClassBuiltin; - if (kind <= GoType::KIND_COMPLEX128) - return eTypeClassComplexFloat; - if (kind == GoType::KIND_LLDB_VOID) - return eTypeClassInvalid; - return eTypeClassStruct; + return builtin_type_flags; + } + if (kind == GoType::KIND_STRING) + return eTypeHasValue | eTypeIsBuiltIn; + if (kind == GoType::KIND_FUNC) + return eTypeIsFuncPrototype | eTypeHasValue; + if (IsPointerType(type)) + return eTypeIsPointer | eTypeHasValue | eTypeHasChildren; + if (kind == GoType::KIND_LLDB_VOID) + return 0; + return eTypeHasChildren | eTypeIsStructUnion; +} + +lldb::TypeClass GoASTContext::GetTypeClass(lldb::opaque_compiler_type_t type) { + if (!type) + return eTypeClassInvalid; + int kind = static_cast<GoType *>(type)->GetGoKind(); + if (kind == GoType::KIND_FUNC) + return eTypeClassFunction; + if (IsPointerType(type)) + return eTypeClassPointer; + if (kind < GoType::KIND_COMPLEX64) + return eTypeClassBuiltin; + if (kind <= GoType::KIND_COMPLEX128) + return eTypeClassComplexFloat; + if (kind == GoType::KIND_LLDB_VOID) + return eTypeClassInvalid; + return eTypeClassStruct; } lldb::BasicType -GoASTContext::GetBasicTypeEnumeration(lldb::opaque_compiler_type_t type) -{ - ConstString name = GetTypeName(type); - if (name) - { - typedef UniqueCStringMap<lldb::BasicType> TypeNameToBasicTypeMap; - static TypeNameToBasicTypeMap g_type_map; - static std::once_flag g_once_flag; - std::call_once(g_once_flag, [](){ - // "void" - g_type_map.Append(ConstString("void").GetCString(), eBasicTypeVoid); - // "int" - g_type_map.Append(ConstString("int").GetCString(), eBasicTypeInt); - g_type_map.Append(ConstString("uint").GetCString(), eBasicTypeUnsignedInt); - - // Miscellaneous - g_type_map.Append(ConstString("bool").GetCString(), eBasicTypeBool); - - // Others. Should these map to C types? - g_type_map.Append(ConstString("byte").GetCString(), eBasicTypeOther); - g_type_map.Append(ConstString("uint8").GetCString(), eBasicTypeOther); - g_type_map.Append(ConstString("uint16").GetCString(), eBasicTypeOther); - g_type_map.Append(ConstString("uint32").GetCString(), eBasicTypeOther); - g_type_map.Append(ConstString("uint64").GetCString(), eBasicTypeOther); - g_type_map.Append(ConstString("int8").GetCString(), eBasicTypeOther); - g_type_map.Append(ConstString("int16").GetCString(), eBasicTypeOther); - g_type_map.Append(ConstString("int32").GetCString(), eBasicTypeOther); - g_type_map.Append(ConstString("int64").GetCString(), eBasicTypeOther); - g_type_map.Append(ConstString("float32").GetCString(), eBasicTypeOther); - g_type_map.Append(ConstString("float64").GetCString(), eBasicTypeOther); - g_type_map.Append(ConstString("uintptr").GetCString(), eBasicTypeOther); - - g_type_map.Sort(); - }); - - return g_type_map.Find(name.GetCString(), eBasicTypeInvalid); - } - return eBasicTypeInvalid; +GoASTContext::GetBasicTypeEnumeration(lldb::opaque_compiler_type_t type) { + ConstString name = GetTypeName(type); + if (name) { + typedef UniqueCStringMap<lldb::BasicType> TypeNameToBasicTypeMap; + static TypeNameToBasicTypeMap g_type_map; + static std::once_flag g_once_flag; + std::call_once(g_once_flag, []() { + // "void" + g_type_map.Append(ConstString("void").GetCString(), eBasicTypeVoid); + // "int" + g_type_map.Append(ConstString("int").GetCString(), eBasicTypeInt); + g_type_map.Append(ConstString("uint").GetCString(), + eBasicTypeUnsignedInt); + + // Miscellaneous + g_type_map.Append(ConstString("bool").GetCString(), eBasicTypeBool); + + // Others. Should these map to C types? + g_type_map.Append(ConstString("byte").GetCString(), eBasicTypeOther); + g_type_map.Append(ConstString("uint8").GetCString(), eBasicTypeOther); + g_type_map.Append(ConstString("uint16").GetCString(), eBasicTypeOther); + g_type_map.Append(ConstString("uint32").GetCString(), eBasicTypeOther); + g_type_map.Append(ConstString("uint64").GetCString(), eBasicTypeOther); + g_type_map.Append(ConstString("int8").GetCString(), eBasicTypeOther); + g_type_map.Append(ConstString("int16").GetCString(), eBasicTypeOther); + g_type_map.Append(ConstString("int32").GetCString(), eBasicTypeOther); + g_type_map.Append(ConstString("int64").GetCString(), eBasicTypeOther); + g_type_map.Append(ConstString("float32").GetCString(), eBasicTypeOther); + g_type_map.Append(ConstString("float64").GetCString(), eBasicTypeOther); + g_type_map.Append(ConstString("uintptr").GetCString(), eBasicTypeOther); + + g_type_map.Sort(); + }); + + return g_type_map.Find(name.GetCString(), eBasicTypeInvalid); + } + return eBasicTypeInvalid; } lldb::LanguageType -GoASTContext::GetMinimumLanguage(lldb::opaque_compiler_type_t type) -{ - return lldb::eLanguageTypeGo; +GoASTContext::GetMinimumLanguage(lldb::opaque_compiler_type_t type) { + return lldb::eLanguageTypeGo; } -unsigned -GoASTContext::GetTypeQualifiers(lldb::opaque_compiler_type_t type) -{ - return 0; +unsigned GoASTContext::GetTypeQualifiers(lldb::opaque_compiler_type_t type) { + return 0; } //---------------------------------------------------------------------- @@ -812,853 +641,806 @@ GoASTContext::GetTypeQualifiers(lldb::opaque_compiler_type_t type) //---------------------------------------------------------------------- CompilerType -GoASTContext::GetArrayElementType(lldb::opaque_compiler_type_t type, uint64_t *stride) -{ - GoArray *array = static_cast<GoType *>(type)->GetArray(); - if (array) - { - if (stride) - { - *stride = array->GetElementType().GetByteSize(nullptr); - } - return array->GetElementType(); +GoASTContext::GetArrayElementType(lldb::opaque_compiler_type_t type, + uint64_t *stride) { + GoArray *array = static_cast<GoType *>(type)->GetArray(); + if (array) { + if (stride) { + *stride = array->GetElementType().GetByteSize(nullptr); } - return CompilerType(); + return array->GetElementType(); + } + return CompilerType(); } -CompilerType -GoASTContext::GetCanonicalType(lldb::opaque_compiler_type_t type) -{ - GoType *t = static_cast<GoType *>(type); - if (t->IsTypedef()) - return t->GetElementType(); - return CompilerType(this, type); +CompilerType GoASTContext::GetCanonicalType(lldb::opaque_compiler_type_t type) { + GoType *t = static_cast<GoType *>(type); + if (t->IsTypedef()) + return t->GetElementType(); + return CompilerType(this, type); } CompilerType -GoASTContext::GetFullyUnqualifiedType(lldb::opaque_compiler_type_t type) -{ - return CompilerType(this, type); +GoASTContext::GetFullyUnqualifiedType(lldb::opaque_compiler_type_t type) { + return CompilerType(this, type); } -// Returns -1 if this isn't a function of if the function doesn't have a prototype +// Returns -1 if this isn't a function of if the function doesn't have a +// prototype // Returns a value >= 0 if there is a prototype. -int -GoASTContext::GetFunctionArgumentCount(lldb::opaque_compiler_type_t type) -{ - return GetNumberOfFunctionArguments(type); +int GoASTContext::GetFunctionArgumentCount(lldb::opaque_compiler_type_t type) { + return GetNumberOfFunctionArguments(type); } CompilerType -GoASTContext::GetFunctionArgumentTypeAtIndex(lldb::opaque_compiler_type_t type, size_t idx) -{ - return GetFunctionArgumentAtIndex(type, idx); +GoASTContext::GetFunctionArgumentTypeAtIndex(lldb::opaque_compiler_type_t type, + size_t idx) { + return GetFunctionArgumentAtIndex(type, idx); } CompilerType -GoASTContext::GetFunctionReturnType(lldb::opaque_compiler_type_t type) -{ - CompilerType result; - if (type) - { - GoType *t = static_cast<GoType *>(type); - if (t->GetGoKind() == GoType::KIND_FUNC) - result = t->GetElementType(); - } - return result; +GoASTContext::GetFunctionReturnType(lldb::opaque_compiler_type_t type) { + CompilerType result; + if (type) { + GoType *t = static_cast<GoType *>(type); + if (t->GetGoKind() == GoType::KIND_FUNC) + result = t->GetElementType(); + } + return result; } -size_t -GoASTContext::GetNumMemberFunctions(lldb::opaque_compiler_type_t type) -{ - return 0; +size_t GoASTContext::GetNumMemberFunctions(lldb::opaque_compiler_type_t type) { + return 0; } TypeMemberFunctionImpl -GoASTContext::GetMemberFunctionAtIndex(lldb::opaque_compiler_type_t type, size_t idx) -{ - return TypeMemberFunctionImpl(); +GoASTContext::GetMemberFunctionAtIndex(lldb::opaque_compiler_type_t type, + size_t idx) { + return TypeMemberFunctionImpl(); } CompilerType -GoASTContext::GetNonReferenceType(lldb::opaque_compiler_type_t type) -{ - return CompilerType(this, type); +GoASTContext::GetNonReferenceType(lldb::opaque_compiler_type_t type) { + return CompilerType(this, type); } -CompilerType -GoASTContext::GetPointeeType(lldb::opaque_compiler_type_t type) -{ - if (!type) - return CompilerType(); - return static_cast<GoType *>(type)->GetElementType(); +CompilerType GoASTContext::GetPointeeType(lldb::opaque_compiler_type_t type) { + if (!type) + return CompilerType(); + return static_cast<GoType *>(type)->GetElementType(); } -CompilerType -GoASTContext::GetPointerType(lldb::opaque_compiler_type_t type) -{ - if (!type) - return CompilerType(); - ConstString type_name = GetTypeName(type); - ConstString pointer_name(std::string("*") + type_name.GetCString()); - GoType *pointer = (*m_types)[pointer_name].get(); - if (pointer == nullptr) - { - pointer = new GoElem(GoType::KIND_PTR, pointer_name, CompilerType(this, type)); - (*m_types)[pointer_name].reset(pointer); - } - return CompilerType(this, pointer); +CompilerType GoASTContext::GetPointerType(lldb::opaque_compiler_type_t type) { + if (!type) + return CompilerType(); + ConstString type_name = GetTypeName(type); + ConstString pointer_name(std::string("*") + type_name.GetCString()); + GoType *pointer = (*m_types)[pointer_name].get(); + if (pointer == nullptr) { + pointer = + new GoElem(GoType::KIND_PTR, pointer_name, CompilerType(this, type)); + (*m_types)[pointer_name].reset(pointer); + } + return CompilerType(this, pointer); } // If the current object represents a typedef type, get the underlying type -CompilerType -GoASTContext::GetTypedefedType(lldb::opaque_compiler_type_t type) -{ - if (IsTypedefType(type)) - return static_cast<GoType *>(type)->GetElementType(); - return CompilerType(); +CompilerType GoASTContext::GetTypedefedType(lldb::opaque_compiler_type_t type) { + if (IsTypedefType(type)) + return static_cast<GoType *>(type)->GetElementType(); + return CompilerType(); } //---------------------------------------------------------------------- // Create related types using the current type's AST //---------------------------------------------------------------------- -CompilerType -GoASTContext::GetBasicTypeFromAST(lldb::BasicType basic_type) -{ - return CompilerType(); +CompilerType GoASTContext::GetBasicTypeFromAST(lldb::BasicType basic_type) { + return CompilerType(); } CompilerType -GoASTContext::GetBuiltinTypeForEncodingAndBitSize (lldb::Encoding encoding, - size_t bit_size) -{ - return CompilerType(); +GoASTContext::GetBuiltinTypeForEncodingAndBitSize(lldb::Encoding encoding, + size_t bit_size) { + return CompilerType(); } - //---------------------------------------------------------------------- // Exploring the type //---------------------------------------------------------------------- -uint64_t -GoASTContext::GetBitSize(lldb::opaque_compiler_type_t type, ExecutionContextScope *exe_scope) -{ - if (!type) - return 0; - if (!GetCompleteType(type)) - return 0; - GoType *t = static_cast<GoType *>(type); - GoArray *array = nullptr; - switch (t->GetGoKind()) - { - case GoType::KIND_BOOL: - case GoType::KIND_INT8: - case GoType::KIND_UINT8: - return 8; - case GoType::KIND_INT16: - case GoType::KIND_UINT16: - return 16; - case GoType::KIND_INT32: - case GoType::KIND_UINT32: - case GoType::KIND_FLOAT32: - return 32; - case GoType::KIND_INT64: - case GoType::KIND_UINT64: - case GoType::KIND_FLOAT64: - case GoType::KIND_COMPLEX64: - return 64; - case GoType::KIND_COMPLEX128: - return 128; - case GoType::KIND_INT: - case GoType::KIND_UINT: - return m_int_byte_size * 8; - case GoType::KIND_UINTPTR: - case GoType::KIND_FUNC: // I assume this is a pointer? - case GoType::KIND_CHAN: - case GoType::KIND_PTR: - case GoType::KIND_UNSAFEPOINTER: - case GoType::KIND_MAP: - return m_pointer_byte_size * 8; - case GoType::KIND_ARRAY: - array = t->GetArray(); - return array->GetLength() * array->GetElementType().GetBitSize(exe_scope); - case GoType::KIND_INTERFACE: - return t->GetElementType().GetBitSize(exe_scope); - case GoType::KIND_SLICE: - case GoType::KIND_STRING: - case GoType::KIND_STRUCT: - return t->GetStruct()->GetByteSize() * 8; - default: - assert(false); - } +uint64_t GoASTContext::GetBitSize(lldb::opaque_compiler_type_t type, + ExecutionContextScope *exe_scope) { + if (!type) return 0; -} - -lldb::Encoding -GoASTContext::GetEncoding(lldb::opaque_compiler_type_t type, uint64_t &count) -{ - count = 1; - bool is_signed; - if (IsIntegerType(type, is_signed)) - return is_signed ? lldb::eEncodingSint : eEncodingUint; - bool is_complex; - uint32_t complex_count; - if (IsFloatingPointType(type, complex_count, is_complex)) - { - count = complex_count; - return eEncodingIEEE754; - } - if (IsPointerType(type)) - return eEncodingUint; - return eEncodingInvalid; -} - -lldb::Format -GoASTContext::GetFormat(lldb::opaque_compiler_type_t type) -{ - if (!type) - return eFormatDefault; - switch (static_cast<GoType *>(type)->GetGoKind()) - { - case GoType::KIND_BOOL: - return eFormatBoolean; - case GoType::KIND_INT: - case GoType::KIND_INT8: - case GoType::KIND_INT16: - case GoType::KIND_INT32: - case GoType::KIND_INT64: - return eFormatDecimal; - case GoType::KIND_UINT: - case GoType::KIND_UINT8: - case GoType::KIND_UINT16: - case GoType::KIND_UINT32: - case GoType::KIND_UINT64: - return eFormatUnsigned; - case GoType::KIND_FLOAT32: - case GoType::KIND_FLOAT64: - return eFormatFloat; - case GoType::KIND_COMPLEX64: - case GoType::KIND_COMPLEX128: - return eFormatComplexFloat; - case GoType::KIND_UINTPTR: - case GoType::KIND_CHAN: - case GoType::KIND_PTR: - case GoType::KIND_MAP: - case GoType::KIND_UNSAFEPOINTER: - return eFormatHex; - case GoType::KIND_STRING: - return eFormatCString; - case GoType::KIND_ARRAY: - case GoType::KIND_INTERFACE: - case GoType::KIND_SLICE: - case GoType::KIND_STRUCT: - default: - // Don't know how to display this. - return eFormatBytes; - } -} - -size_t -GoASTContext::GetTypeBitAlign(lldb::opaque_compiler_type_t type) -{ + if (!GetCompleteType(type)) return 0; -} - -uint32_t -GoASTContext::GetNumChildren(lldb::opaque_compiler_type_t type, bool omit_empty_base_classes) -{ - if (!type || !GetCompleteType(type)) - return 0; - GoType *t = static_cast<GoType *>(type); - if (t->GetGoKind() == GoType::KIND_PTR) - { - CompilerType elem = t->GetElementType(); - if (elem.IsAggregateType()) - return elem.GetNumChildren(omit_empty_base_classes); - return 1; - } - else if (GoArray *array = t->GetArray()) - { - return array->GetLength(); - } - else if (t->IsTypedef()) - { - return t->GetElementType().GetNumChildren(omit_empty_base_classes); - } + GoType *t = static_cast<GoType *>(type); + GoArray *array = nullptr; + switch (t->GetGoKind()) { + case GoType::KIND_BOOL: + case GoType::KIND_INT8: + case GoType::KIND_UINT8: + return 8; + case GoType::KIND_INT16: + case GoType::KIND_UINT16: + return 16; + case GoType::KIND_INT32: + case GoType::KIND_UINT32: + case GoType::KIND_FLOAT32: + return 32; + case GoType::KIND_INT64: + case GoType::KIND_UINT64: + case GoType::KIND_FLOAT64: + case GoType::KIND_COMPLEX64: + return 64; + case GoType::KIND_COMPLEX128: + return 128; + case GoType::KIND_INT: + case GoType::KIND_UINT: + return m_int_byte_size * 8; + case GoType::KIND_UINTPTR: + case GoType::KIND_FUNC: // I assume this is a pointer? + case GoType::KIND_CHAN: + case GoType::KIND_PTR: + case GoType::KIND_UNSAFEPOINTER: + case GoType::KIND_MAP: + return m_pointer_byte_size * 8; + case GoType::KIND_ARRAY: + array = t->GetArray(); + return array->GetLength() * array->GetElementType().GetBitSize(exe_scope); + case GoType::KIND_INTERFACE: + return t->GetElementType().GetBitSize(exe_scope); + case GoType::KIND_SLICE: + case GoType::KIND_STRING: + case GoType::KIND_STRUCT: + return t->GetStruct()->GetByteSize() * 8; + default: + assert(false); + } + return 0; +} + +lldb::Encoding GoASTContext::GetEncoding(lldb::opaque_compiler_type_t type, + uint64_t &count) { + count = 1; + bool is_signed; + if (IsIntegerType(type, is_signed)) + return is_signed ? lldb::eEncodingSint : eEncodingUint; + bool is_complex; + uint32_t complex_count; + if (IsFloatingPointType(type, complex_count, is_complex)) { + count = complex_count; + return eEncodingIEEE754; + } + if (IsPointerType(type)) + return eEncodingUint; + return eEncodingInvalid; +} + +lldb::Format GoASTContext::GetFormat(lldb::opaque_compiler_type_t type) { + if (!type) + return eFormatDefault; + switch (static_cast<GoType *>(type)->GetGoKind()) { + case GoType::KIND_BOOL: + return eFormatBoolean; + case GoType::KIND_INT: + case GoType::KIND_INT8: + case GoType::KIND_INT16: + case GoType::KIND_INT32: + case GoType::KIND_INT64: + return eFormatDecimal; + case GoType::KIND_UINT: + case GoType::KIND_UINT8: + case GoType::KIND_UINT16: + case GoType::KIND_UINT32: + case GoType::KIND_UINT64: + return eFormatUnsigned; + case GoType::KIND_FLOAT32: + case GoType::KIND_FLOAT64: + return eFormatFloat; + case GoType::KIND_COMPLEX64: + case GoType::KIND_COMPLEX128: + return eFormatComplexFloat; + case GoType::KIND_UINTPTR: + case GoType::KIND_CHAN: + case GoType::KIND_PTR: + case GoType::KIND_MAP: + case GoType::KIND_UNSAFEPOINTER: + return eFormatHex; + case GoType::KIND_STRING: + return eFormatCString; + case GoType::KIND_ARRAY: + case GoType::KIND_INTERFACE: + case GoType::KIND_SLICE: + case GoType::KIND_STRUCT: + default: + // Don't know how to display this. + return eFormatBytes; + } +} + +size_t GoASTContext::GetTypeBitAlign(lldb::opaque_compiler_type_t type) { + return 0; +} + +uint32_t GoASTContext::GetNumChildren(lldb::opaque_compiler_type_t type, + bool omit_empty_base_classes) { + if (!type || !GetCompleteType(type)) + return 0; + GoType *t = static_cast<GoType *>(type); + if (t->GetGoKind() == GoType::KIND_PTR) { + CompilerType elem = t->GetElementType(); + if (elem.IsAggregateType()) + return elem.GetNumChildren(omit_empty_base_classes); + return 1; + } else if (GoArray *array = t->GetArray()) { + return array->GetLength(); + } else if (t->IsTypedef()) { + return t->GetElementType().GetNumChildren(omit_empty_base_classes); + } - return GetNumFields(type); + return GetNumFields(type); } -uint32_t -GoASTContext::GetNumFields(lldb::opaque_compiler_type_t type) -{ - if (!type || !GetCompleteType(type)) - return 0; - GoType *t = static_cast<GoType *>(type); - if (t->IsTypedef()) - return t->GetElementType().GetNumFields(); - GoStruct *s = t->GetStruct(); - if (s) - return s->GetNumFields(); +uint32_t GoASTContext::GetNumFields(lldb::opaque_compiler_type_t type) { + if (!type || !GetCompleteType(type)) return 0; -} - -CompilerType -GoASTContext::GetFieldAtIndex(lldb::opaque_compiler_type_t type, size_t idx, std::string &name, uint64_t *bit_offset_ptr, - uint32_t *bitfield_bit_size_ptr, bool *is_bitfield_ptr) -{ - if (bit_offset_ptr) - *bit_offset_ptr = 0; - if (bitfield_bit_size_ptr) - *bitfield_bit_size_ptr = 0; - if (is_bitfield_ptr) - *is_bitfield_ptr = false; - - if (!type || !GetCompleteType(type)) - return CompilerType(); + GoType *t = static_cast<GoType *>(type); + if (t->IsTypedef()) + return t->GetElementType().GetNumFields(); + GoStruct *s = t->GetStruct(); + if (s) + return s->GetNumFields(); + return 0; +} + +CompilerType GoASTContext::GetFieldAtIndex(lldb::opaque_compiler_type_t type, + size_t idx, std::string &name, + uint64_t *bit_offset_ptr, + uint32_t *bitfield_bit_size_ptr, + bool *is_bitfield_ptr) { + if (bit_offset_ptr) + *bit_offset_ptr = 0; + if (bitfield_bit_size_ptr) + *bitfield_bit_size_ptr = 0; + if (is_bitfield_ptr) + *is_bitfield_ptr = false; + + if (!type || !GetCompleteType(type)) + return CompilerType(); - GoType *t = static_cast<GoType *>(type); - if (t->IsTypedef()) - return t->GetElementType().GetFieldAtIndex(idx, name, bit_offset_ptr, bitfield_bit_size_ptr, is_bitfield_ptr); - - GoStruct *s = t->GetStruct(); - if (s) - { - const auto *field = s->GetField(idx); - if (field) - { - name = field->m_name.GetStringRef(); - if (bit_offset_ptr) - *bit_offset_ptr = field->m_byte_offset * 8; - return field->m_type; - } + GoType *t = static_cast<GoType *>(type); + if (t->IsTypedef()) + return t->GetElementType().GetFieldAtIndex( + idx, name, bit_offset_ptr, bitfield_bit_size_ptr, is_bitfield_ptr); + + GoStruct *s = t->GetStruct(); + if (s) { + const auto *field = s->GetField(idx); + if (field) { + name = field->m_name.GetStringRef(); + if (bit_offset_ptr) + *bit_offset_ptr = field->m_byte_offset * 8; + return field->m_type; } + } + return CompilerType(); +} + +CompilerType GoASTContext::GetChildCompilerTypeAtIndex( + lldb::opaque_compiler_type_t type, ExecutionContext *exe_ctx, size_t idx, + bool transparent_pointers, bool omit_empty_base_classes, + bool ignore_array_bounds, std::string &child_name, + uint32_t &child_byte_size, int32_t &child_byte_offset, + uint32_t &child_bitfield_bit_size, uint32_t &child_bitfield_bit_offset, + bool &child_is_base_class, bool &child_is_deref_of_parent, + ValueObject *valobj, uint64_t &language_flags) { + child_name.clear(); + child_byte_size = 0; + child_byte_offset = 0; + child_bitfield_bit_size = 0; + child_bitfield_bit_offset = 0; + child_is_base_class = false; + child_is_deref_of_parent = false; + language_flags = 0; + + if (!type || !GetCompleteType(type)) return CompilerType(); -} -CompilerType -GoASTContext::GetChildCompilerTypeAtIndex(lldb::opaque_compiler_type_t type, ExecutionContext *exe_ctx, size_t idx, bool transparent_pointers, - bool omit_empty_base_classes, bool ignore_array_bounds, std::string &child_name, - uint32_t &child_byte_size, int32_t &child_byte_offset, - uint32_t &child_bitfield_bit_size, uint32_t &child_bitfield_bit_offset, - bool &child_is_base_class, bool &child_is_deref_of_parent, ValueObject *valobj, uint64_t &language_flags) -{ - child_name.clear(); - child_byte_size = 0; - child_byte_offset = 0; - child_bitfield_bit_size = 0; - child_bitfield_bit_offset = 0; - child_is_base_class = false; - child_is_deref_of_parent = false; - language_flags = 0; - - if (!type || !GetCompleteType(type)) - return CompilerType(); - - GoType *t = static_cast<GoType *>(type); - if (t->GetStruct()) - { - uint64_t bit_offset; - CompilerType ret = GetFieldAtIndex(type, idx, child_name, &bit_offset, nullptr, nullptr); - child_byte_size = ret.GetByteSize(exe_ctx ? exe_ctx->GetBestExecutionContextScope() : nullptr); - child_byte_offset = bit_offset / 8; - return ret; - } - else if (t->GetGoKind() == GoType::KIND_PTR) - { - CompilerType pointee = t->GetElementType(); - if (!pointee.IsValid() || pointee.IsVoidType()) - return CompilerType(); - if (transparent_pointers && pointee.IsAggregateType()) - { - bool tmp_child_is_deref_of_parent = false; - return pointee.GetChildCompilerTypeAtIndex(exe_ctx, idx, transparent_pointers, omit_empty_base_classes, - ignore_array_bounds, child_name, child_byte_size, child_byte_offset, - child_bitfield_bit_size, child_bitfield_bit_offset, - child_is_base_class, tmp_child_is_deref_of_parent, valobj, language_flags); - } - else - { - child_is_deref_of_parent = true; - const char *parent_name = valobj ? valobj->GetName().GetCString() : NULL; - if (parent_name) - { - child_name.assign(1, '*'); - child_name += parent_name; - } - - // We have a pointer to an simple type - if (idx == 0 && pointee.GetCompleteType()) - { - child_byte_size = pointee.GetByteSize(exe_ctx ? exe_ctx->GetBestExecutionContextScope() : NULL); - child_byte_offset = 0; - return pointee; - } - } - } - else if (GoArray *a = t->GetArray()) - { - if (ignore_array_bounds || idx < a->GetLength()) - { - CompilerType element_type = a->GetElementType(); - if (element_type.GetCompleteType()) - { - char element_name[64]; - ::snprintf(element_name, sizeof(element_name), "[%zu]", idx); - child_name.assign(element_name); - child_byte_size = element_type.GetByteSize(exe_ctx ? exe_ctx->GetBestExecutionContextScope() : NULL); - child_byte_offset = (int32_t)idx * (int32_t)child_byte_size; - return element_type; - } - } + GoType *t = static_cast<GoType *>(type); + if (t->GetStruct()) { + uint64_t bit_offset; + CompilerType ret = + GetFieldAtIndex(type, idx, child_name, &bit_offset, nullptr, nullptr); + child_byte_size = ret.GetByteSize( + exe_ctx ? exe_ctx->GetBestExecutionContextScope() : nullptr); + child_byte_offset = bit_offset / 8; + return ret; + } else if (t->GetGoKind() == GoType::KIND_PTR) { + CompilerType pointee = t->GetElementType(); + if (!pointee.IsValid() || pointee.IsVoidType()) + return CompilerType(); + if (transparent_pointers && pointee.IsAggregateType()) { + bool tmp_child_is_deref_of_parent = false; + return pointee.GetChildCompilerTypeAtIndex( + exe_ctx, idx, transparent_pointers, omit_empty_base_classes, + ignore_array_bounds, child_name, child_byte_size, child_byte_offset, + child_bitfield_bit_size, child_bitfield_bit_offset, + child_is_base_class, tmp_child_is_deref_of_parent, valobj, + language_flags); + } else { + child_is_deref_of_parent = true; + const char *parent_name = valobj ? valobj->GetName().GetCString() : NULL; + if (parent_name) { + child_name.assign(1, '*'); + child_name += parent_name; + } + + // We have a pointer to an simple type + if (idx == 0 && pointee.GetCompleteType()) { + child_byte_size = pointee.GetByteSize( + exe_ctx ? exe_ctx->GetBestExecutionContextScope() : NULL); + child_byte_offset = 0; + return pointee; + } } - else if (t->IsTypedef()) - { - return t->GetElementType().GetChildCompilerTypeAtIndex( - exe_ctx, idx, transparent_pointers, omit_empty_base_classes, ignore_array_bounds, child_name, - child_byte_size, child_byte_offset, child_bitfield_bit_size, child_bitfield_bit_offset, child_is_base_class, - child_is_deref_of_parent, valobj, language_flags); + } else if (GoArray *a = t->GetArray()) { + if (ignore_array_bounds || idx < a->GetLength()) { + CompilerType element_type = a->GetElementType(); + if (element_type.GetCompleteType()) { + char element_name[64]; + ::snprintf(element_name, sizeof(element_name), "[%zu]", idx); + child_name.assign(element_name); + child_byte_size = element_type.GetByteSize( + exe_ctx ? exe_ctx->GetBestExecutionContextScope() : NULL); + child_byte_offset = (int32_t)idx * (int32_t)child_byte_size; + return element_type; + } } - return CompilerType(); + } else if (t->IsTypedef()) { + return t->GetElementType().GetChildCompilerTypeAtIndex( + exe_ctx, idx, transparent_pointers, omit_empty_base_classes, + ignore_array_bounds, child_name, child_byte_size, child_byte_offset, + child_bitfield_bit_size, child_bitfield_bit_offset, child_is_base_class, + child_is_deref_of_parent, valobj, language_flags); + } + return CompilerType(); } // Lookup a child given a name. This function will match base class names // and member member names in "clang_type" only, not descendants. uint32_t -GoASTContext::GetIndexOfChildWithName(lldb::opaque_compiler_type_t type, const char *name, bool omit_empty_base_classes) -{ - if (!type || !GetCompleteType(type)) - return UINT_MAX; +GoASTContext::GetIndexOfChildWithName(lldb::opaque_compiler_type_t type, + const char *name, + bool omit_empty_base_classes) { + if (!type || !GetCompleteType(type)) + return UINT_MAX; - GoType *t = static_cast<GoType *>(type); - GoStruct *s = t->GetStruct(); - if (s) - { - for (uint32_t i = 0; i < s->GetNumFields(); ++i) - { - const GoStruct::Field *f = s->GetField(i); - if (f->m_name.GetStringRef() == name) - return i; - } - } - else if (t->GetGoKind() == GoType::KIND_PTR || t->IsTypedef()) - { - return t->GetElementType().GetIndexOfChildWithName(name, omit_empty_base_classes); + GoType *t = static_cast<GoType *>(type); + GoStruct *s = t->GetStruct(); + if (s) { + for (uint32_t i = 0; i < s->GetNumFields(); ++i) { + const GoStruct::Field *f = s->GetField(i); + if (f->m_name.GetStringRef() == name) + return i; } - return UINT_MAX; + } else if (t->GetGoKind() == GoType::KIND_PTR || t->IsTypedef()) { + return t->GetElementType().GetIndexOfChildWithName(name, + omit_empty_base_classes); + } + return UINT_MAX; } // Lookup a child member given a name. This function will match member names // only and will descend into "clang_type" children in search for the first // member in this class, or any base class that matches "name". -// TODO: Return all matches for a given name by returning a vector<vector<uint32_t>> +// TODO: Return all matches for a given name by returning a +// vector<vector<uint32_t>> // so we catch all names that match a given child name, not just the first. -size_t -GoASTContext::GetIndexOfChildMemberWithName(lldb::opaque_compiler_type_t type, const char *name, bool omit_empty_base_classes, - std::vector<uint32_t> &child_indexes) -{ - uint32_t index = GetIndexOfChildWithName(type, name, omit_empty_base_classes); - if (index == UINT_MAX) - return 0; - child_indexes.push_back(index); - return 1; +size_t GoASTContext::GetIndexOfChildMemberWithName( + lldb::opaque_compiler_type_t type, const char *name, + bool omit_empty_base_classes, std::vector<uint32_t> &child_indexes) { + uint32_t index = GetIndexOfChildWithName(type, name, omit_empty_base_classes); + if (index == UINT_MAX) + return 0; + child_indexes.push_back(index); + return 1; } // Converts "s" to a floating point value and place resulting floating // point bytes in the "dst" buffer. size_t -GoASTContext::ConvertStringToFloatValue(lldb::opaque_compiler_type_t type, const char *s, uint8_t *dst, size_t dst_size) -{ - assert(false); - return 0; +GoASTContext::ConvertStringToFloatValue(lldb::opaque_compiler_type_t type, + const char *s, uint8_t *dst, + size_t dst_size) { + assert(false); + return 0; } //---------------------------------------------------------------------- // Dumping types //---------------------------------------------------------------------- #define DEPTH_INCREMENT 2 -void -GoASTContext::DumpValue(lldb::opaque_compiler_type_t type, ExecutionContext *exe_ctx, Stream *s, lldb::Format format, - const DataExtractor &data, lldb::offset_t data_byte_offset, size_t data_byte_size, - uint32_t bitfield_bit_size, uint32_t bitfield_bit_offset, bool show_types, bool show_summary, - bool verbose, uint32_t depth) -{ - if (IsTypedefType(type)) - type = GetTypedefedType(type).GetOpaqueQualType(); - if (!type) - return; - GoType *t = static_cast<GoType *>(type); - - if (GoStruct *st = t->GetStruct()) - { - if (GetCompleteType(type)) - { - uint32_t field_idx = 0; - for (auto* field = st->GetField(field_idx); field != nullptr; field_idx++) - { - // Print the starting squiggly bracket (if this is the - // first member) or comma (for member 2 and beyond) for - // the struct/union/class member. - if (field_idx == 0) - s->PutChar('{'); - else - s->PutChar(','); - - // Indent - s->Printf("\n%*s", depth + DEPTH_INCREMENT, ""); - - // Print the member type if requested - if (show_types) - { - ConstString field_type_name = field->m_type.GetTypeName(); - s->Printf("(%s) ", field_type_name.AsCString()); - } - // Print the member name and equal sign - s->Printf("%s = ", field->m_name.AsCString()); - - - // Dump the value of the member - CompilerType field_type = field->m_type; - field_type.DumpValue (exe_ctx, - s, // Stream to dump to - field_type.GetFormat(), // The format with which to display the member - data, // Data buffer containing all bytes for this type - data_byte_offset + field->m_byte_offset,// Offset into "data" where to grab value from - field->m_type.GetByteSize(exe_ctx->GetBestExecutionContextScope()), // Size of this type in bytes - 0, // Bitfield bit size - 0, // Bitfield bit offset - show_types, // Boolean indicating if we should show the variable types - show_summary, // Boolean indicating if we should show a summary for the current type - verbose, // Verbose output? - depth + DEPTH_INCREMENT); // Scope depth for any types that have children - } - - // Indent the trailing squiggly bracket - if (field_idx > 0) - s->Printf("\n%*s}", depth, ""); - - } - } - - if (GoArray *a = t->GetArray()) { - CompilerType element_clang_type = a->GetElementType(); - lldb::Format element_format = element_clang_type.GetFormat(); - uint32_t element_byte_size = element_clang_type.GetByteSize(exe_ctx->GetBestExecutionContextScope()); - - uint64_t element_idx; - for (element_idx = 0; element_idx < a->GetLength(); ++element_idx) - { - // Print the starting squiggly bracket (if this is the - // first member) or comman (for member 2 and beyong) for - // the struct/union/class member. - if (element_idx == 0) - s->PutChar('{'); - else - s->PutChar(','); - - // Indent and print the index - s->Printf("\n%*s[%" PRIu64 "] ", depth + DEPTH_INCREMENT, "", element_idx); - - // Figure out the field offset within the current struct/union/class type - uint64_t element_offset = element_idx * element_byte_size; - - // Dump the value of the member - element_clang_type.DumpValue (exe_ctx, - s, // Stream to dump to - element_format, // The format with which to display the element - data, // Data buffer containing all bytes for this type - data_byte_offset + element_offset,// Offset into "data" where to grab value from - element_byte_size, // Size of this type in bytes - 0, // Bitfield bit size - 0, // Bitfield bit offset - show_types, // Boolean indicating if we should show the variable types - show_summary, // Boolean indicating if we should show a summary for the current type - verbose, // Verbose output? - depth + DEPTH_INCREMENT); // Scope depth for any types that have children +void GoASTContext::DumpValue(lldb::opaque_compiler_type_t type, + ExecutionContext *exe_ctx, Stream *s, + lldb::Format format, const DataExtractor &data, + lldb::offset_t data_byte_offset, + size_t data_byte_size, uint32_t bitfield_bit_size, + uint32_t bitfield_bit_offset, bool show_types, + bool show_summary, bool verbose, uint32_t depth) { + if (IsTypedefType(type)) + type = GetTypedefedType(type).GetOpaqueQualType(); + if (!type) + return; + GoType *t = static_cast<GoType *>(type); + + if (GoStruct *st = t->GetStruct()) { + if (GetCompleteType(type)) { + uint32_t field_idx = 0; + for (auto *field = st->GetField(field_idx); field != nullptr; + field_idx++) { + // Print the starting squiggly bracket (if this is the + // first member) or comma (for member 2 and beyond) for + // the struct/union/class member. + if (field_idx == 0) + s->PutChar('{'); + else + s->PutChar(','); + + // Indent + s->Printf("\n%*s", depth + DEPTH_INCREMENT, ""); + + // Print the member type if requested + if (show_types) { + ConstString field_type_name = field->m_type.GetTypeName(); + s->Printf("(%s) ", field_type_name.AsCString()); } - - // Indent the trailing squiggly bracket - if (element_idx > 0) - s->Printf("\n%*s}", depth, ""); + // Print the member name and equal sign + s->Printf("%s = ", field->m_name.AsCString()); + + // Dump the value of the member + CompilerType field_type = field->m_type; + field_type.DumpValue( + exe_ctx, + s, // Stream to dump to + field_type + .GetFormat(), // The format with which to display the member + data, // Data buffer containing all bytes for this type + data_byte_offset + field->m_byte_offset, // Offset into "data" where + // to grab value from + field->m_type.GetByteSize( + exe_ctx->GetBestExecutionContextScope()), // Size of this type + // in bytes + 0, // Bitfield bit size + 0, // Bitfield bit offset + show_types, // Boolean indicating if we should show the variable + // types + show_summary, // Boolean indicating if we should show a summary for + // the current type + verbose, // Verbose output? + depth + DEPTH_INCREMENT); // Scope depth for any types that have + // children + } + + // Indent the trailing squiggly bracket + if (field_idx > 0) + s->Printf("\n%*s}", depth, ""); } - - if (show_summary) - DumpSummary (type, exe_ctx, s, data, data_byte_offset, data_byte_size); -} - -bool -GoASTContext::DumpTypeValue(lldb::opaque_compiler_type_t type, Stream *s, lldb::Format format, const DataExtractor &data, - lldb::offset_t byte_offset, size_t byte_size, uint32_t bitfield_bit_size, - uint32_t bitfield_bit_offset, ExecutionContextScope *exe_scope) -{ - if (!type) - return false; - if (IsAggregateType(type)) - { - return false; + } + + if (GoArray *a = t->GetArray()) { + CompilerType element_clang_type = a->GetElementType(); + lldb::Format element_format = element_clang_type.GetFormat(); + uint32_t element_byte_size = + element_clang_type.GetByteSize(exe_ctx->GetBestExecutionContextScope()); + + uint64_t element_idx; + for (element_idx = 0; element_idx < a->GetLength(); ++element_idx) { + // Print the starting squiggly bracket (if this is the + // first member) or comman (for member 2 and beyong) for + // the struct/union/class member. + if (element_idx == 0) + s->PutChar('{'); + else + s->PutChar(','); + + // Indent and print the index + s->Printf("\n%*s[%" PRIu64 "] ", depth + DEPTH_INCREMENT, "", + element_idx); + + // Figure out the field offset within the current struct/union/class type + uint64_t element_offset = element_idx * element_byte_size; + + // Dump the value of the member + element_clang_type.DumpValue( + exe_ctx, + s, // Stream to dump to + element_format, // The format with which to display the element + data, // Data buffer containing all bytes for this type + data_byte_offset + + element_offset, // Offset into "data" where to grab value from + element_byte_size, // Size of this type in bytes + 0, // Bitfield bit size + 0, // Bitfield bit offset + show_types, // Boolean indicating if we should show the variable types + show_summary, // Boolean indicating if we should show a summary for + // the current type + verbose, // Verbose output? + depth + + DEPTH_INCREMENT); // Scope depth for any types that have children } - else - { - GoType *t = static_cast<GoType *>(type); - if (t->IsTypedef()) - { - CompilerType typedef_compiler_type = t->GetElementType(); - if (format == eFormatDefault) - format = typedef_compiler_type.GetFormat(); - uint64_t typedef_byte_size = typedef_compiler_type.GetByteSize(exe_scope); - - return typedef_compiler_type.DumpTypeValue( - s, - format, // The format with which to display the element - data, // Data buffer containing all bytes for this type - byte_offset, // Offset into "data" where to grab value from - typedef_byte_size, // Size of this type in bytes - bitfield_bit_size, // Size in bits of a bitfield value, if zero don't treat as a bitfield - bitfield_bit_offset, // Offset in bits of a bitfield value if bitfield_bit_size != 0 - exe_scope); - } - uint32_t item_count = 1; - // A few formats, we might need to modify our size and count for depending - // on how we are trying to display the value... - switch (format) - { - default: - case eFormatBoolean: - case eFormatBinary: - case eFormatComplex: - case eFormatCString: // NULL terminated C strings - case eFormatDecimal: - case eFormatEnum: - case eFormatHex: - case eFormatHexUppercase: - case eFormatFloat: - case eFormatOctal: - case eFormatOSType: - case eFormatUnsigned: - case eFormatPointer: - case eFormatVectorOfChar: - case eFormatVectorOfSInt8: - case eFormatVectorOfUInt8: - case eFormatVectorOfSInt16: - case eFormatVectorOfUInt16: - case eFormatVectorOfSInt32: - case eFormatVectorOfUInt32: - case eFormatVectorOfSInt64: - case eFormatVectorOfUInt64: - case eFormatVectorOfFloat32: - case eFormatVectorOfFloat64: - case eFormatVectorOfUInt128: - break; - - case eFormatChar: - case eFormatCharPrintable: - case eFormatCharArray: - case eFormatBytes: - case eFormatBytesWithASCII: - item_count = byte_size; - byte_size = 1; - break; - - case eFormatUnicode16: - item_count = byte_size / 2; - byte_size = 2; - break; - - case eFormatUnicode32: - item_count = byte_size / 4; - byte_size = 4; - break; - } - return data.Dump(s, byte_offset, format, byte_size, item_count, UINT32_MAX, LLDB_INVALID_ADDRESS, - bitfield_bit_size, bitfield_bit_offset, exe_scope); - } - return 0; -} + // Indent the trailing squiggly bracket + if (element_idx > 0) + s->Printf("\n%*s}", depth, ""); + } -void -GoASTContext::DumpSummary(lldb::opaque_compiler_type_t type, ExecutionContext *exe_ctx, Stream *s, const DataExtractor &data, - lldb::offset_t data_offset, size_t data_byte_size) -{ - if (type && GoType::KIND_STRING == static_cast<GoType *>(type)->GetGoKind()) - { - // TODO(ribrdb): read length and data - } + if (show_summary) + DumpSummary(type, exe_ctx, s, data, data_byte_offset, data_byte_size); } -void -GoASTContext::DumpTypeDescription(lldb::opaque_compiler_type_t type) -{ - // Dump to stdout - StreamFile s (stdout, false); - DumpTypeDescription (type, &s); -} +bool GoASTContext::DumpTypeValue(lldb::opaque_compiler_type_t type, Stream *s, + lldb::Format format, const DataExtractor &data, + lldb::offset_t byte_offset, size_t byte_size, + uint32_t bitfield_bit_size, + uint32_t bitfield_bit_offset, + ExecutionContextScope *exe_scope) { + if (!type) + return false; + if (IsAggregateType(type)) { + return false; + } else { + GoType *t = static_cast<GoType *>(type); + if (t->IsTypedef()) { + CompilerType typedef_compiler_type = t->GetElementType(); + if (format == eFormatDefault) + format = typedef_compiler_type.GetFormat(); + uint64_t typedef_byte_size = typedef_compiler_type.GetByteSize(exe_scope); + + return typedef_compiler_type.DumpTypeValue( + s, + format, // The format with which to display the element + data, // Data buffer containing all bytes for this type + byte_offset, // Offset into "data" where to grab value from + typedef_byte_size, // Size of this type in bytes + bitfield_bit_size, // Size in bits of a bitfield value, if zero don't + // treat as a bitfield + bitfield_bit_offset, // Offset in bits of a bitfield value if + // bitfield_bit_size != 0 + exe_scope); + } -void -GoASTContext::DumpTypeDescription(lldb::opaque_compiler_type_t type, Stream *s) -{ - if (!type) + uint32_t item_count = 1; + // A few formats, we might need to modify our size and count for depending + // on how we are trying to display the value... + switch (format) { + default: + case eFormatBoolean: + case eFormatBinary: + case eFormatComplex: + case eFormatCString: // NULL terminated C strings + case eFormatDecimal: + case eFormatEnum: + case eFormatHex: + case eFormatHexUppercase: + case eFormatFloat: + case eFormatOctal: + case eFormatOSType: + case eFormatUnsigned: + case eFormatPointer: + case eFormatVectorOfChar: + case eFormatVectorOfSInt8: + case eFormatVectorOfUInt8: + case eFormatVectorOfSInt16: + case eFormatVectorOfUInt16: + case eFormatVectorOfSInt32: + case eFormatVectorOfUInt32: + case eFormatVectorOfSInt64: + case eFormatVectorOfUInt64: + case eFormatVectorOfFloat32: + case eFormatVectorOfFloat64: + case eFormatVectorOfUInt128: + break; + + case eFormatChar: + case eFormatCharPrintable: + case eFormatCharArray: + case eFormatBytes: + case eFormatBytesWithASCII: + item_count = byte_size; + byte_size = 1; + break; + + case eFormatUnicode16: + item_count = byte_size / 2; + byte_size = 2; + break; + + case eFormatUnicode32: + item_count = byte_size / 4; + byte_size = 4; + break; + } + return data.Dump(s, byte_offset, format, byte_size, item_count, UINT32_MAX, + LLDB_INVALID_ADDRESS, bitfield_bit_size, + bitfield_bit_offset, exe_scope); + } + return 0; +} + +void GoASTContext::DumpSummary(lldb::opaque_compiler_type_t type, + ExecutionContext *exe_ctx, Stream *s, + const DataExtractor &data, + lldb::offset_t data_offset, + size_t data_byte_size) { + if (type && GoType::KIND_STRING == static_cast<GoType *>(type)->GetGoKind()) { + // TODO(ribrdb): read length and data + } +} + +void GoASTContext::DumpTypeDescription(lldb::opaque_compiler_type_t type) { + // Dump to stdout + StreamFile s(stdout, false); + DumpTypeDescription(type, &s); +} + +void GoASTContext::DumpTypeDescription(lldb::opaque_compiler_type_t type, + Stream *s) { + if (!type) + return; + ConstString name = GetTypeName(type); + GoType *t = static_cast<GoType *>(type); + + if (GoStruct *st = t->GetStruct()) { + if (GetCompleteType(type)) { + if (NULL == strchr(name.AsCString(), '{')) + s->Printf("type %s ", name.AsCString()); + s->PutCString("struct {"); + if (st->GetNumFields() == 0) { + s->PutChar('}'); return; - ConstString name = GetTypeName(type); - GoType *t = static_cast<GoType *>(type); - - if (GoStruct *st = t->GetStruct()) - { - if (GetCompleteType(type)) - { - if (NULL == strchr(name.AsCString(), '{')) - s->Printf("type %s ", name.AsCString()); - s->PutCString("struct {"); - if (st->GetNumFields() == 0) { - s->PutChar('}'); - return; - } - s->IndentMore(); - uint32_t field_idx = 0; - for (auto* field = st->GetField(field_idx); field != nullptr; field_idx++) - { - s->PutChar('\n'); - s->Indent(); - s->Printf("%s %s", field->m_name.AsCString(), field->m_type.GetTypeName().AsCString()); - } - s->IndentLess(); - s->PutChar('\n'); - s->Indent("}"); - return; - } + } + s->IndentMore(); + uint32_t field_idx = 0; + for (auto *field = st->GetField(field_idx); field != nullptr; + field_idx++) { + s->PutChar('\n'); + s->Indent(); + s->Printf("%s %s", field->m_name.AsCString(), + field->m_type.GetTypeName().AsCString()); + } + s->IndentLess(); + s->PutChar('\n'); + s->Indent("}"); + return; } + } - s->PutCString(name.AsCString()); + s->PutCString(name.AsCString()); } -CompilerType -GoASTContext::CreateArrayType(const ConstString &name, const CompilerType &element_type, uint64_t length) -{ - GoType *type = new GoArray(name, length, element_type); - (*m_types)[name].reset(type); - return CompilerType(this, type); +CompilerType GoASTContext::CreateArrayType(const ConstString &name, + const CompilerType &element_type, + uint64_t length) { + GoType *type = new GoArray(name, length, element_type); + (*m_types)[name].reset(type); + return CompilerType(this, type); } -CompilerType -GoASTContext::CreateBaseType(int go_kind, const lldb_private::ConstString &name, uint64_t byte_size) -{ - if (go_kind == GoType::KIND_UINT || go_kind == GoType::KIND_INT) - m_int_byte_size = byte_size; - GoType *type = new GoType(go_kind, name); - (*m_types)[name].reset(type); - return CompilerType(this, type); +CompilerType GoASTContext::CreateBaseType(int go_kind, + const lldb_private::ConstString &name, + uint64_t byte_size) { + if (go_kind == GoType::KIND_UINT || go_kind == GoType::KIND_INT) + m_int_byte_size = byte_size; + GoType *type = new GoType(go_kind, name); + (*m_types)[name].reset(type); + return CompilerType(this, type); } -CompilerType -GoASTContext::CreateTypedefType(int kind, const ConstString &name, CompilerType impl) -{ - GoType *type = new GoElem(kind, name, impl); - (*m_types)[name].reset(type); - return CompilerType(this, type); +CompilerType GoASTContext::CreateTypedefType(int kind, const ConstString &name, + CompilerType impl) { + GoType *type = new GoElem(kind, name, impl); + (*m_types)[name].reset(type); + return CompilerType(this, type); } CompilerType -GoASTContext::CreateVoidType(const lldb_private::ConstString &name) -{ - GoType *type = new GoType(GoType::KIND_LLDB_VOID, name); - (*m_types)[name].reset(type); - return CompilerType(this, type); +GoASTContext::CreateVoidType(const lldb_private::ConstString &name) { + GoType *type = new GoType(GoType::KIND_LLDB_VOID, name); + (*m_types)[name].reset(type); + return CompilerType(this, type); } CompilerType -GoASTContext::CreateStructType(int kind, const lldb_private::ConstString &name, uint32_t byte_size) -{ - GoType *type = new GoStruct(kind, name, byte_size); - (*m_types)[name].reset(type); - return CompilerType(this, type); -} - -void -GoASTContext::AddFieldToStruct(const lldb_private::CompilerType &struct_type, const lldb_private::ConstString &name, - const lldb_private::CompilerType &field_type, uint32_t byte_offset) -{ - if (!struct_type) - return; - GoASTContext *ast = llvm::dyn_cast_or_null<GoASTContext>(struct_type.GetTypeSystem()); - if (!ast) - return; - GoType *type = static_cast<GoType *>(struct_type.GetOpaqueQualType()); - if (GoStruct *s = type->GetStruct()) - s->AddField(name, field_type, byte_offset); -} - -void -GoASTContext::CompleteStructType(const lldb_private::CompilerType &struct_type) -{ - if (!struct_type) - return; - GoASTContext *ast = llvm::dyn_cast_or_null<GoASTContext>(struct_type.GetTypeSystem()); - if (!ast) - return; - GoType *type = static_cast<GoType *>(struct_type.GetOpaqueQualType()); - if (GoStruct *s = type->GetStruct()) - s->SetComplete(); +GoASTContext::CreateStructType(int kind, const lldb_private::ConstString &name, + uint32_t byte_size) { + GoType *type = new GoStruct(kind, name, byte_size); + (*m_types)[name].reset(type); + return CompilerType(this, type); +} + +void GoASTContext::AddFieldToStruct( + const lldb_private::CompilerType &struct_type, + const lldb_private::ConstString &name, + const lldb_private::CompilerType &field_type, uint32_t byte_offset) { + if (!struct_type) + return; + GoASTContext *ast = + llvm::dyn_cast_or_null<GoASTContext>(struct_type.GetTypeSystem()); + if (!ast) + return; + GoType *type = static_cast<GoType *>(struct_type.GetOpaqueQualType()); + if (GoStruct *s = type->GetStruct()) + s->AddField(name, field_type, byte_offset); +} + +void GoASTContext::CompleteStructType( + const lldb_private::CompilerType &struct_type) { + if (!struct_type) + return; + GoASTContext *ast = + llvm::dyn_cast_or_null<GoASTContext>(struct_type.GetTypeSystem()); + if (!ast) + return; + GoType *type = static_cast<GoType *>(struct_type.GetOpaqueQualType()); + if (GoStruct *s = type->GetStruct()) + s->SetComplete(); } CompilerType -GoASTContext::CreateFunctionType(const lldb_private::ConstString &name, CompilerType *params, size_t params_count, - bool is_variadic) -{ - GoType *type = new GoFunction(name, is_variadic); - (*m_types)[name].reset(type); - return CompilerType(this, type); +GoASTContext::CreateFunctionType(const lldb_private::ConstString &name, + CompilerType *params, size_t params_count, + bool is_variadic) { + GoType *type = new GoFunction(name, is_variadic); + (*m_types)[name].reset(type); + return CompilerType(this, type); } -bool -GoASTContext::IsGoString(const lldb_private::CompilerType &type) -{ - if (!type.IsValid() || !llvm::dyn_cast_or_null<GoASTContext>(type.GetTypeSystem())) - return false; - return GoType::KIND_STRING == static_cast<GoType *>(type.GetOpaqueQualType())->GetGoKind(); +bool GoASTContext::IsGoString(const lldb_private::CompilerType &type) { + if (!type.IsValid() || + !llvm::dyn_cast_or_null<GoASTContext>(type.GetTypeSystem())) + return false; + return GoType::KIND_STRING == + static_cast<GoType *>(type.GetOpaqueQualType())->GetGoKind(); } -bool -GoASTContext::IsGoSlice(const lldb_private::CompilerType &type) -{ - if (!type.IsValid() || !llvm::dyn_cast_or_null<GoASTContext>(type.GetTypeSystem())) - return false; - return GoType::KIND_SLICE == static_cast<GoType *>(type.GetOpaqueQualType())->GetGoKind(); +bool GoASTContext::IsGoSlice(const lldb_private::CompilerType &type) { + if (!type.IsValid() || + !llvm::dyn_cast_or_null<GoASTContext>(type.GetTypeSystem())) + return false; + return GoType::KIND_SLICE == + static_cast<GoType *>(type.GetOpaqueQualType())->GetGoKind(); } -bool -GoASTContext::IsGoInterface(const lldb_private::CompilerType &type) -{ - if (!type.IsValid() || !llvm::dyn_cast_or_null<GoASTContext>(type.GetTypeSystem())) - return false; - return GoType::KIND_INTERFACE == static_cast<GoType *>(type.GetOpaqueQualType())->GetGoKind(); +bool GoASTContext::IsGoInterface(const lldb_private::CompilerType &type) { + if (!type.IsValid() || + !llvm::dyn_cast_or_null<GoASTContext>(type.GetTypeSystem())) + return false; + return GoType::KIND_INTERFACE == + static_cast<GoType *>(type.GetOpaqueQualType())->GetGoKind(); } -bool -GoASTContext::IsPointerKind(uint8_t kind) -{ - return (kind & GoType::KIND_MASK) == GoType::KIND_PTR; +bool GoASTContext::IsPointerKind(uint8_t kind) { + return (kind & GoType::KIND_MASK) == GoType::KIND_PTR; } -bool -GoASTContext::IsDirectIface(uint8_t kind) -{ - return (kind & GoType::KIND_DIRECT_IFACE) == GoType::KIND_DIRECT_IFACE; +bool GoASTContext::IsDirectIface(uint8_t kind) { + return (kind & GoType::KIND_DIRECT_IFACE) == GoType::KIND_DIRECT_IFACE; } -DWARFASTParser * -GoASTContext::GetDWARFParser() -{ - if (!m_dwarf_ast_parser_ap) - m_dwarf_ast_parser_ap.reset(new DWARFASTParserGo(*this)); - return m_dwarf_ast_parser_ap.get(); +DWARFASTParser *GoASTContext::GetDWARFParser() { + if (!m_dwarf_ast_parser_ap) + m_dwarf_ast_parser_ap.reset(new DWARFASTParserGo(*this)); + return m_dwarf_ast_parser_ap.get(); } -UserExpression * -GoASTContextForExpr::GetUserExpression(const char *expr, const char *expr_prefix, lldb::LanguageType language, - Expression::ResultType desired_type, const EvaluateExpressionOptions &options) -{ - TargetSP target = m_target_wp.lock(); - if (target) - return new GoUserExpression(*target, expr, expr_prefix, language, desired_type, options); - return nullptr; +UserExpression *GoASTContextForExpr::GetUserExpression( + const char *expr, const char *expr_prefix, lldb::LanguageType language, + Expression::ResultType desired_type, + const EvaluateExpressionOptions &options) { + TargetSP target = m_target_wp.lock(); + if (target) + return new GoUserExpression(*target, expr, expr_prefix, language, + desired_type, options); + return nullptr; } diff --git a/lldb/source/Symbol/JavaASTContext.cpp b/lldb/source/Symbol/JavaASTContext.cpp index 45cda8d5112..79073a65367 100644 --- a/lldb/source/Symbol/JavaASTContext.cpp +++ b/lldb/source/Symbol/JavaASTContext.cpp @@ -28,1534 +28,1306 @@ using namespace lldb; using namespace lldb_private; -namespace lldb_private -{ +namespace lldb_private { -class JavaASTContext::JavaType -{ +class JavaASTContext::JavaType { public: - enum LLVMCastKind - { - eKindPrimitive, - eKindObject, - eKindReference, - eKindArray, - kNumKinds - }; + enum LLVMCastKind { + eKindPrimitive, + eKindObject, + eKindReference, + eKindArray, + kNumKinds + }; - JavaType(LLVMCastKind kind) : m_kind(kind) {} + JavaType(LLVMCastKind kind) : m_kind(kind) {} - virtual ~JavaType() = default; + virtual ~JavaType() = default; - virtual ConstString - GetName() = 0; + virtual ConstString GetName() = 0; - virtual void - Dump(Stream *s) = 0; + virtual void Dump(Stream *s) = 0; - virtual bool - IsCompleteType() = 0; + virtual bool IsCompleteType() = 0; - LLVMCastKind - getKind() const - { - return m_kind; - } + LLVMCastKind getKind() const { return m_kind; } private: - LLVMCastKind m_kind; + LLVMCastKind m_kind; }; } // end of namespace lldb_private -namespace -{ +namespace { -class JavaPrimitiveType : public JavaASTContext::JavaType -{ +class JavaPrimitiveType : public JavaASTContext::JavaType { public: - enum TypeKind - { - eTypeByte, - eTypeShort, - eTypeInt, - eTypeLong, - eTypeFloat, - eTypeDouble, - eTypeBoolean, - eTypeChar, - }; - - JavaPrimitiveType(TypeKind type_kind) : JavaType(JavaType::eKindPrimitive), m_type_kind(type_kind) {} - - ConstString - GetName() override - { - switch (m_type_kind) - { - case eTypeByte: - return ConstString("byte"); - case eTypeShort: - return ConstString("short"); - case eTypeInt: - return ConstString("int"); - case eTypeLong: - return ConstString("long"); - case eTypeFloat: - return ConstString("float"); - case eTypeDouble: - return ConstString("double"); - case eTypeBoolean: - return ConstString("boolean"); - case eTypeChar: - return ConstString("char"); - } - return ConstString(); + enum TypeKind { + eTypeByte, + eTypeShort, + eTypeInt, + eTypeLong, + eTypeFloat, + eTypeDouble, + eTypeBoolean, + eTypeChar, + }; + + JavaPrimitiveType(TypeKind type_kind) + : JavaType(JavaType::eKindPrimitive), m_type_kind(type_kind) {} + + ConstString GetName() override { + switch (m_type_kind) { + case eTypeByte: + return ConstString("byte"); + case eTypeShort: + return ConstString("short"); + case eTypeInt: + return ConstString("int"); + case eTypeLong: + return ConstString("long"); + case eTypeFloat: + return ConstString("float"); + case eTypeDouble: + return ConstString("double"); + case eTypeBoolean: + return ConstString("boolean"); + case eTypeChar: + return ConstString("char"); } + return ConstString(); + } - TypeKind - GetTypeKind() - { - return m_type_kind; - } + TypeKind GetTypeKind() { return m_type_kind; } - void - Dump(Stream *s) override - { - s->Printf("%s\n", GetName().GetCString()); - } + void Dump(Stream *s) override { s->Printf("%s\n", GetName().GetCString()); } - bool - IsCompleteType() override - { - return true; - } + bool IsCompleteType() override { return true; } - static bool - classof(const JavaType *jt) - { - return jt->getKind() == JavaType::eKindPrimitive; - } + static bool classof(const JavaType *jt) { + return jt->getKind() == JavaType::eKindPrimitive; + } private: - const TypeKind m_type_kind; + const TypeKind m_type_kind; }; -class JavaDynamicType : public JavaASTContext::JavaType -{ +class JavaDynamicType : public JavaASTContext::JavaType { public: - JavaDynamicType(LLVMCastKind kind, const ConstString &linkage_name) : - JavaType(kind), - m_linkage_name(linkage_name), - m_dynamic_type_id(nullptr) - { - } + JavaDynamicType(LLVMCastKind kind, const ConstString &linkage_name) + : JavaType(kind), m_linkage_name(linkage_name), + m_dynamic_type_id(nullptr) {} - ConstString - GetLinkageName() const - { - return m_linkage_name; - } + ConstString GetLinkageName() const { return m_linkage_name; } - void - SetDynamicTypeId(const DWARFExpression &type_id) - { - m_dynamic_type_id = type_id; - } + void SetDynamicTypeId(const DWARFExpression &type_id) { + m_dynamic_type_id = type_id; + } - uint64_t - CalculateDynamicTypeId(ExecutionContext *exe_ctx, ValueObject &value_obj) - { - if (!m_dynamic_type_id.IsValid()) - return UINT64_MAX; - - Value obj_load_address = value_obj.GetValue(); - obj_load_address.ResolveValue(exe_ctx); - obj_load_address.SetValueType(Value::eValueTypeLoadAddress); - - Value result; - if (m_dynamic_type_id.Evaluate(exe_ctx->GetBestExecutionContextScope(), nullptr, nullptr, 0, &obj_load_address, - nullptr, result, nullptr)) - { - Error error; - - lldb::addr_t type_id_addr = result.GetScalar().UInt(); - lldb::ProcessSP process_sp = exe_ctx->GetProcessSP(); - if (process_sp) - return process_sp->ReadUnsignedIntegerFromMemory(type_id_addr, process_sp->GetAddressByteSize(), - UINT64_MAX, error); - } - - return UINT64_MAX; - } + uint64_t CalculateDynamicTypeId(ExecutionContext *exe_ctx, + ValueObject &value_obj) { + if (!m_dynamic_type_id.IsValid()) + return UINT64_MAX; -public: - ConstString m_linkage_name; - DWARFExpression m_dynamic_type_id; -}; + Value obj_load_address = value_obj.GetValue(); + obj_load_address.ResolveValue(exe_ctx); + obj_load_address.SetValueType(Value::eValueTypeLoadAddress); -class JavaObjectType : public JavaDynamicType -{ -public: - struct Field - { - ConstString m_name; - CompilerType m_type; - uint32_t m_offset; - }; - - JavaObjectType(const ConstString &name, const ConstString &linkage_name, uint32_t byte_size) - : JavaDynamicType(JavaType::eKindObject, linkage_name), - m_name(name), - m_byte_size(byte_size), - m_base_class_offset(0), - m_is_complete(false) - { - } + Value result; + if (m_dynamic_type_id.Evaluate(exe_ctx->GetBestExecutionContextScope(), + nullptr, nullptr, 0, &obj_load_address, + nullptr, result, nullptr)) { + Error error; - ConstString - GetName() override - { - return m_name; + lldb::addr_t type_id_addr = result.GetScalar().UInt(); + lldb::ProcessSP process_sp = exe_ctx->GetProcessSP(); + if (process_sp) + return process_sp->ReadUnsignedIntegerFromMemory( + type_id_addr, process_sp->GetAddressByteSize(), UINT64_MAX, error); } - uint32_t - GetByteSize() const - { - return m_byte_size; - } + return UINT64_MAX; + } - uint32_t - GetNumFields() - { - return m_fields.size(); - } +public: + ConstString m_linkage_name; + DWARFExpression m_dynamic_type_id; +}; - void - Dump(Stream *s) override - { - if (m_base_class.IsValid()) - s->Printf("%s : %s\n", GetName().GetCString(), m_base_class.GetTypeName().GetCString()); - else - s->Printf("%s\n", GetName().GetCString()); - - s->IndentMore(); - for (const Field &f : m_fields) - s->Printf("%s %s\n", f.m_type.GetTypeName().GetCString(), f.m_name.GetCString()); - s->IndentLess(); - } +class JavaObjectType : public JavaDynamicType { +public: + struct Field { + ConstString m_name; + CompilerType m_type; + uint32_t m_offset; + }; - Field * - GetFieldAtIndex(size_t idx) - { - if (idx < m_fields.size()) - return &m_fields[idx]; - return nullptr; - } + JavaObjectType(const ConstString &name, const ConstString &linkage_name, + uint32_t byte_size) + : JavaDynamicType(JavaType::eKindObject, linkage_name), m_name(name), + m_byte_size(byte_size), m_base_class_offset(0), m_is_complete(false) {} - CompilerType - GetBaseClass() - { - return m_base_class; - } + ConstString GetName() override { return m_name; } - uint32_t - GetBaseClassOffset() - { - return m_base_class_offset; - } + uint32_t GetByteSize() const { return m_byte_size; } - uint32_t - GetNumInterfaces() - { - return m_interfaces.size(); - } + uint32_t GetNumFields() { return m_fields.size(); } - CompilerType - GetInterfaceAtIndex(uint32_t idx) - { - if (m_interfaces.size() < idx) - return m_interfaces[idx]; - return CompilerType(); - } + void Dump(Stream *s) override { + if (m_base_class.IsValid()) + s->Printf("%s : %s\n", GetName().GetCString(), + m_base_class.GetTypeName().GetCString()); + else + s->Printf("%s\n", GetName().GetCString()); - bool - IsCompleteType() override - { - return m_is_complete; - } + s->IndentMore(); + for (const Field &f : m_fields) + s->Printf("%s %s\n", f.m_type.GetTypeName().GetCString(), + f.m_name.GetCString()); + s->IndentLess(); + } - void - SetCompleteType(bool is_complete) - { - m_is_complete = is_complete; - if (m_byte_size == 0) - { - // Try to calcualte the size of the object based on it's values - for (const Field &field : m_fields) - { - uint32_t field_end = field.m_offset + field.m_type.GetByteSize(nullptr); - if (field_end > m_byte_size) - m_byte_size = field_end; - } - } - } + Field *GetFieldAtIndex(size_t idx) { + if (idx < m_fields.size()) + return &m_fields[idx]; + return nullptr; + } - void - AddBaseClass(const CompilerType &type, uint32_t offset) - { - // TODO: Check if type is an interface and add it to the interface list in that case - m_base_class = type; - m_base_class_offset = offset; - } + CompilerType GetBaseClass() { return m_base_class; } - void - AddField(const ConstString &name, const CompilerType &type, uint32_t offset) - { - m_fields.push_back({name, type, offset}); - } + uint32_t GetBaseClassOffset() { return m_base_class_offset; } - static bool - classof(const JavaType *jt) - { - return jt->getKind() == JavaType::eKindObject; - } + uint32_t GetNumInterfaces() { return m_interfaces.size(); } + + CompilerType GetInterfaceAtIndex(uint32_t idx) { + if (m_interfaces.size() < idx) + return m_interfaces[idx]; + return CompilerType(); + } + + bool IsCompleteType() override { return m_is_complete; } + + void SetCompleteType(bool is_complete) { + m_is_complete = is_complete; + if (m_byte_size == 0) { + // Try to calcualte the size of the object based on it's values + for (const Field &field : m_fields) { + uint32_t field_end = field.m_offset + field.m_type.GetByteSize(nullptr); + if (field_end > m_byte_size) + m_byte_size = field_end; + } + } + } + + void AddBaseClass(const CompilerType &type, uint32_t offset) { + // TODO: Check if type is an interface and add it to the interface list in + // that case + m_base_class = type; + m_base_class_offset = offset; + } + + void AddField(const ConstString &name, const CompilerType &type, + uint32_t offset) { + m_fields.push_back({name, type, offset}); + } + + static bool classof(const JavaType *jt) { + return jt->getKind() == JavaType::eKindObject; + } private: - ConstString m_name; - uint32_t m_byte_size; - CompilerType m_base_class; - uint32_t m_base_class_offset; - std::vector<CompilerType> m_interfaces; - std::vector<Field> m_fields; - bool m_is_complete; + ConstString m_name; + uint32_t m_byte_size; + CompilerType m_base_class; + uint32_t m_base_class_offset; + std::vector<CompilerType> m_interfaces; + std::vector<Field> m_fields; + bool m_is_complete; }; -class JavaReferenceType : public JavaASTContext::JavaType -{ +class JavaReferenceType : public JavaASTContext::JavaType { public: - JavaReferenceType(CompilerType pointee_type) : JavaType(JavaType::eKindReference), m_pointee_type(pointee_type) {} + JavaReferenceType(CompilerType pointee_type) + : JavaType(JavaType::eKindReference), m_pointee_type(pointee_type) {} - static bool - classof(const JavaType *jt) - { - return jt->getKind() == JavaType::eKindReference; - } + static bool classof(const JavaType *jt) { + return jt->getKind() == JavaType::eKindReference; + } - CompilerType - GetPointeeType() - { - return m_pointee_type; - } + CompilerType GetPointeeType() { return m_pointee_type; } - ConstString - GetName() override - { - ConstString pointee_type_name = static_cast<JavaType *>(GetPointeeType().GetOpaqueQualType())->GetName(); - return ConstString(std::string(pointee_type_name.AsCString()) + "&"); - } + ConstString GetName() override { + ConstString pointee_type_name = + static_cast<JavaType *>(GetPointeeType().GetOpaqueQualType()) + ->GetName(); + return ConstString(std::string(pointee_type_name.AsCString()) + "&"); + } - void - Dump(Stream *s) override - { - static_cast<JavaType *>(m_pointee_type.GetOpaqueQualType())->Dump(s); - } + void Dump(Stream *s) override { + static_cast<JavaType *>(m_pointee_type.GetOpaqueQualType())->Dump(s); + } - bool - IsCompleteType() override - { - return m_pointee_type.IsCompleteType(); - } + bool IsCompleteType() override { return m_pointee_type.IsCompleteType(); } private: - CompilerType m_pointee_type; + CompilerType m_pointee_type; }; -class JavaArrayType : public JavaDynamicType -{ +class JavaArrayType : public JavaDynamicType { public: - JavaArrayType(const ConstString& linkage_name, CompilerType element_type, const DWARFExpression &length_expression, - lldb::addr_t data_offset) - : JavaDynamicType(JavaType::eKindArray, linkage_name), - m_element_type(element_type), - m_length_expression(length_expression), - m_data_offset(data_offset) - { - } - - static bool - classof(const JavaType *jt) - { - return jt->getKind() == JavaType::eKindArray; - } - - CompilerType - GetElementType() - { - return m_element_type; - } - - ConstString - GetName() override - { - ConstString element_type_name = static_cast<JavaType *>(GetElementType().GetOpaqueQualType())->GetName(); - return ConstString(std::string(element_type_name.AsCString()) + "[]"); - } - - void - Dump(Stream *s) override - { - s->Printf("%s\n", GetName().GetCString()); - } - - bool - IsCompleteType() override - { - return m_length_expression.IsValid(); - } + JavaArrayType(const ConstString &linkage_name, CompilerType element_type, + const DWARFExpression &length_expression, + lldb::addr_t data_offset) + : JavaDynamicType(JavaType::eKindArray, linkage_name), + m_element_type(element_type), m_length_expression(length_expression), + m_data_offset(data_offset) {} + + static bool classof(const JavaType *jt) { + return jt->getKind() == JavaType::eKindArray; + } + + CompilerType GetElementType() { return m_element_type; } + + ConstString GetName() override { + ConstString element_type_name = + static_cast<JavaType *>(GetElementType().GetOpaqueQualType()) + ->GetName(); + return ConstString(std::string(element_type_name.AsCString()) + "[]"); + } + + void Dump(Stream *s) override { s->Printf("%s\n", GetName().GetCString()); } + + bool IsCompleteType() override { return m_length_expression.IsValid(); } + + uint32_t GetNumElements(ValueObject *value_obj) { + if (!m_length_expression.IsValid()) + return UINT32_MAX; + + Error error; + ValueObjectSP address_obj = value_obj->AddressOf(error); + if (error.Fail()) + return UINT32_MAX; + + Value obj_load_address = address_obj->GetValue(); + obj_load_address.SetValueType(Value::eValueTypeLoadAddress); + + Value result; + ExecutionContextScope *exec_ctx_scope = value_obj->GetExecutionContextRef() + .Lock(true) + .GetBestExecutionContextScope(); + if (m_length_expression.Evaluate(exec_ctx_scope, nullptr, nullptr, 0, + nullptr, &obj_load_address, result, + nullptr)) + return result.GetScalar().UInt(); - uint32_t - GetNumElements(ValueObject *value_obj) - { - if (!m_length_expression.IsValid()) - return UINT32_MAX; - - Error error; - ValueObjectSP address_obj = value_obj->AddressOf(error); - if (error.Fail()) - return UINT32_MAX; - - Value obj_load_address = address_obj->GetValue(); - obj_load_address.SetValueType(Value::eValueTypeLoadAddress); - - Value result; - ExecutionContextScope* exec_ctx_scope = value_obj->GetExecutionContextRef().Lock(true).GetBestExecutionContextScope(); - if (m_length_expression.Evaluate(exec_ctx_scope, nullptr, nullptr, 0, nullptr, &obj_load_address, result, nullptr)) - return result.GetScalar().UInt(); - - return UINT32_MAX; - } + return UINT32_MAX; + } - uint64_t - GetElementOffset(size_t idx) - { - return m_data_offset + idx * m_element_type.GetByteSize(nullptr); - } + uint64_t GetElementOffset(size_t idx) { + return m_data_offset + idx * m_element_type.GetByteSize(nullptr); + } private: - CompilerType m_element_type; - DWARFExpression m_length_expression; - lldb::addr_t m_data_offset; + CompilerType m_element_type; + DWARFExpression m_length_expression; + lldb::addr_t m_data_offset; }; } // end of anonymous namespace -ConstString -JavaASTContext::GetPluginNameStatic() -{ - return ConstString("java"); +ConstString JavaASTContext::GetPluginNameStatic() { + return ConstString("java"); } -ConstString -JavaASTContext::GetPluginName() -{ - return JavaASTContext::GetPluginNameStatic(); +ConstString JavaASTContext::GetPluginName() { + return JavaASTContext::GetPluginNameStatic(); } -uint32_t -JavaASTContext::GetPluginVersion() -{ - return 1; -} - -lldb::TypeSystemSP -JavaASTContext::CreateInstance(lldb::LanguageType language, Module *module, Target *target) -{ - if (language == eLanguageTypeJava) - { - if (module) - return std::make_shared<JavaASTContext>(module->GetArchitecture()); - if (target) - return std::make_shared<JavaASTContext>(target->GetArchitecture()); - assert(false && "Either a module or a target has to be specifed to create a JavaASTContext"); - } - return lldb::TypeSystemSP(); +uint32_t JavaASTContext::GetPluginVersion() { return 1; } + +lldb::TypeSystemSP JavaASTContext::CreateInstance(lldb::LanguageType language, + Module *module, + Target *target) { + if (language == eLanguageTypeJava) { + if (module) + return std::make_shared<JavaASTContext>(module->GetArchitecture()); + if (target) + return std::make_shared<JavaASTContext>(target->GetArchitecture()); + assert(false && "Either a module or a target has to be specifed to create " + "a JavaASTContext"); + } + return lldb::TypeSystemSP(); } -void -JavaASTContext::EnumerateSupportedLanguages(std::set<lldb::LanguageType> &languages_for_types, - std::set<lldb::LanguageType> &languages_for_expressions) -{ - static std::vector<lldb::LanguageType> s_languages_for_types({lldb::eLanguageTypeJava}); - static std::vector<lldb::LanguageType> s_languages_for_expressions({}); +void JavaASTContext::EnumerateSupportedLanguages( + std::set<lldb::LanguageType> &languages_for_types, + std::set<lldb::LanguageType> &languages_for_expressions) { + static std::vector<lldb::LanguageType> s_languages_for_types( + {lldb::eLanguageTypeJava}); + static std::vector<lldb::LanguageType> s_languages_for_expressions({}); - languages_for_types.insert(s_languages_for_types.begin(), s_languages_for_types.end()); - languages_for_expressions.insert(s_languages_for_expressions.begin(), s_languages_for_expressions.end()); + languages_for_types.insert(s_languages_for_types.begin(), + s_languages_for_types.end()); + languages_for_expressions.insert(s_languages_for_expressions.begin(), + s_languages_for_expressions.end()); } -void -JavaASTContext::Initialize() -{ - PluginManager::RegisterPlugin(GetPluginNameStatic(), "AST context plug-in", CreateInstance, - EnumerateSupportedLanguages); +void JavaASTContext::Initialize() { + PluginManager::RegisterPlugin(GetPluginNameStatic(), "AST context plug-in", + CreateInstance, EnumerateSupportedLanguages); } -void -JavaASTContext::Terminate() -{ - PluginManager::UnregisterPlugin(CreateInstance); +void JavaASTContext::Terminate() { + PluginManager::UnregisterPlugin(CreateInstance); } JavaASTContext::JavaASTContext(const ArchSpec &arch) - : TypeSystem(eKindJava), m_pointer_byte_size(arch.GetAddressByteSize()) -{ + : TypeSystem(eKindJava), m_pointer_byte_size(arch.GetAddressByteSize()) {} + +JavaASTContext::~JavaASTContext() {} + +uint32_t JavaASTContext::GetPointerByteSize() { return m_pointer_byte_size; } + +DWARFASTParser *JavaASTContext::GetDWARFParser() { + if (!m_dwarf_ast_parser_ap) + m_dwarf_ast_parser_ap.reset(new DWARFASTParserJava(*this)); + return m_dwarf_ast_parser_ap.get(); } -JavaASTContext::~JavaASTContext() -{ +ConstString JavaASTContext::DeclGetName(void *opaque_decl) { + return ConstString(); } -uint32_t -JavaASTContext::GetPointerByteSize() -{ - return m_pointer_byte_size; +std::vector<CompilerDecl> JavaASTContext::DeclContextFindDeclByName( + void *opaque_decl_ctx, ConstString name, const bool ignore_imported_decls) { + return std::vector<CompilerDecl>(); } -DWARFASTParser * -JavaASTContext::GetDWARFParser() -{ - if (!m_dwarf_ast_parser_ap) - m_dwarf_ast_parser_ap.reset(new DWARFASTParserJava(*this)); - return m_dwarf_ast_parser_ap.get(); +bool JavaASTContext::DeclContextIsStructUnionOrClass(void *opaque_decl_ctx) { + return false; } -ConstString -JavaASTContext::DeclGetName(void *opaque_decl) -{ - return ConstString(); +ConstString JavaASTContext::DeclContextGetName(void *opaque_decl_ctx) { + return ConstString(); } -std::vector<CompilerDecl> -JavaASTContext::DeclContextFindDeclByName(void *opaque_decl_ctx, ConstString name, const bool ignore_imported_decls) -{ - return std::vector<CompilerDecl>(); +bool JavaASTContext::DeclContextIsClassMethod( + void *opaque_decl_ctx, lldb::LanguageType *language_ptr, + bool *is_instance_method_ptr, ConstString *language_object_name_ptr) { + return false; } -bool -JavaASTContext::DeclContextIsStructUnionOrClass(void *opaque_decl_ctx) -{ - return false; +bool JavaASTContext::IsArrayType(lldb::opaque_compiler_type_t type, + CompilerType *element_type, uint64_t *size, + bool *is_incomplete) { + if (element_type) + element_type->Clear(); + if (size) + *size = 0; + if (is_incomplete) + *is_incomplete = false; + + if (JavaArrayType *array = + llvm::dyn_cast<JavaArrayType>(static_cast<JavaType *>(type))) { + if (element_type) + *element_type = array->GetElementType(); + return true; + } + return false; } -ConstString -JavaASTContext::DeclContextGetName(void *opaque_decl_ctx) -{ - return ConstString(); +bool JavaASTContext::IsAggregateType(lldb::opaque_compiler_type_t type) { + return llvm::isa<JavaObjectType>(static_cast<JavaType *>(type)); } -bool -JavaASTContext::DeclContextIsClassMethod(void *opaque_decl_ctx, lldb::LanguageType *language_ptr, - bool *is_instance_method_ptr, ConstString *language_object_name_ptr) -{ - return false; +bool JavaASTContext::IsCharType(lldb::opaque_compiler_type_t type) { + if (JavaPrimitiveType *ptype = + llvm::dyn_cast<JavaPrimitiveType>(static_cast<JavaType *>(type))) + return ptype->GetTypeKind() == JavaPrimitiveType::eTypeChar; + return false; } -bool -JavaASTContext::IsArrayType(lldb::opaque_compiler_type_t type, CompilerType *element_type, uint64_t *size, - bool *is_incomplete) -{ - if (element_type) - element_type->Clear(); - if (size) - *size = 0; - if (is_incomplete) - *is_incomplete = false; - - if (JavaArrayType *array = llvm::dyn_cast<JavaArrayType>(static_cast<JavaType *>(type))) - { - if (element_type) - *element_type = array->GetElementType(); - return true; - } - return false; -} - -bool -JavaASTContext::IsAggregateType(lldb::opaque_compiler_type_t type) -{ - return llvm::isa<JavaObjectType>(static_cast<JavaType *>(type)); -} - -bool -JavaASTContext::IsCharType(lldb::opaque_compiler_type_t type) -{ - if (JavaPrimitiveType *ptype = llvm::dyn_cast<JavaPrimitiveType>(static_cast<JavaType *>(type))) - return ptype->GetTypeKind() == JavaPrimitiveType::eTypeChar; - return false; -} - -bool -JavaASTContext::IsFloatingPointType(lldb::opaque_compiler_type_t type, uint32_t &count, bool &is_complex) -{ - is_complex = true; - - if (JavaPrimitiveType *ptype = llvm::dyn_cast<JavaPrimitiveType>(static_cast<JavaType *>(type))) - { - switch (ptype->GetTypeKind()) - { - case JavaPrimitiveType::eTypeFloat: - case JavaPrimitiveType::eTypeDouble: - count = 1; - return true; - default: - break; - } +bool JavaASTContext::IsFloatingPointType(lldb::opaque_compiler_type_t type, + uint32_t &count, bool &is_complex) { + is_complex = true; + + if (JavaPrimitiveType *ptype = + llvm::dyn_cast<JavaPrimitiveType>(static_cast<JavaType *>(type))) { + switch (ptype->GetTypeKind()) { + case JavaPrimitiveType::eTypeFloat: + case JavaPrimitiveType::eTypeDouble: + count = 1; + return true; + default: + break; } + } - count = 0; - return false; + count = 0; + return false; } -bool -JavaASTContext::IsFunctionType(lldb::opaque_compiler_type_t type, bool *is_variadic_ptr) -{ - if (is_variadic_ptr) - *is_variadic_ptr = false; - return false; +bool JavaASTContext::IsFunctionType(lldb::opaque_compiler_type_t type, + bool *is_variadic_ptr) { + if (is_variadic_ptr) + *is_variadic_ptr = false; + return false; } -size_t -JavaASTContext::GetNumberOfFunctionArguments(lldb::opaque_compiler_type_t type) -{ - return 0; +size_t JavaASTContext::GetNumberOfFunctionArguments( + lldb::opaque_compiler_type_t type) { + return 0; } CompilerType -JavaASTContext::GetFunctionArgumentAtIndex(lldb::opaque_compiler_type_t type, const size_t index) -{ - return CompilerType(); +JavaASTContext::GetFunctionArgumentAtIndex(lldb::opaque_compiler_type_t type, + const size_t index) { + return CompilerType(); } -bool -JavaASTContext::IsFunctionPointerType(lldb::opaque_compiler_type_t type) -{ - return false; -} - -bool -JavaASTContext::IsBlockPointerType (lldb::opaque_compiler_type_t type, CompilerType *function_pointer_type_ptr) -{ - return false; -} - -bool -JavaASTContext::IsIntegerType(lldb::opaque_compiler_type_t type, bool &is_signed) -{ - if (JavaPrimitiveType *ptype = llvm::dyn_cast<JavaPrimitiveType>(static_cast<JavaType *>(type))) - { - switch (ptype->GetTypeKind()) - { - case JavaPrimitiveType::eTypeByte: - case JavaPrimitiveType::eTypeShort: - case JavaPrimitiveType::eTypeInt: - case JavaPrimitiveType::eTypeLong: - is_signed = true; - return true; - default: - break; - } - } +bool JavaASTContext::IsFunctionPointerType(lldb::opaque_compiler_type_t type) { + return false; +} - is_signed = false; - return false; +bool JavaASTContext::IsBlockPointerType( + lldb::opaque_compiler_type_t type, + CompilerType *function_pointer_type_ptr) { + return false; } -bool -JavaASTContext::IsPossibleDynamicType(lldb::opaque_compiler_type_t type, CompilerType *target_type, - bool check_cplusplus, bool check_objc) -{ - return llvm::isa<JavaReferenceType>(static_cast<JavaType *>(type)); +bool JavaASTContext::IsIntegerType(lldb::opaque_compiler_type_t type, + bool &is_signed) { + if (JavaPrimitiveType *ptype = + llvm::dyn_cast<JavaPrimitiveType>(static_cast<JavaType *>(type))) { + switch (ptype->GetTypeKind()) { + case JavaPrimitiveType::eTypeByte: + case JavaPrimitiveType::eTypeShort: + case JavaPrimitiveType::eTypeInt: + case JavaPrimitiveType::eTypeLong: + is_signed = true; + return true; + default: + break; + } + } + + is_signed = false; + return false; } -bool -JavaASTContext::IsPointerType(lldb::opaque_compiler_type_t type, CompilerType *pointee_type) -{ - if (pointee_type) - pointee_type->Clear(); - return false; +bool JavaASTContext::IsPossibleDynamicType(lldb::opaque_compiler_type_t type, + CompilerType *target_type, + bool check_cplusplus, + bool check_objc) { + return llvm::isa<JavaReferenceType>(static_cast<JavaType *>(type)); } -bool -JavaASTContext::IsReferenceType(lldb::opaque_compiler_type_t type, CompilerType *pointee_type, bool *is_rvalue) -{ - if (is_rvalue) - *is_rvalue = false; +bool JavaASTContext::IsPointerType(lldb::opaque_compiler_type_t type, + CompilerType *pointee_type) { + if (pointee_type) + pointee_type->Clear(); + return false; +} - if (JavaReferenceType *ref = llvm::dyn_cast<JavaReferenceType>(static_cast<JavaType *>(type))) - { - if (pointee_type) - *pointee_type = ref->GetPointeeType(); - return true; - } +bool JavaASTContext::IsReferenceType(lldb::opaque_compiler_type_t type, + CompilerType *pointee_type, + bool *is_rvalue) { + if (is_rvalue) + *is_rvalue = false; + if (JavaReferenceType *ref = + llvm::dyn_cast<JavaReferenceType>(static_cast<JavaType *>(type))) { if (pointee_type) - pointee_type->Clear(); - return false; + *pointee_type = ref->GetPointeeType(); + return true; + } + + if (pointee_type) + pointee_type->Clear(); + return false; } -bool -JavaASTContext::IsScalarType(lldb::opaque_compiler_type_t type) -{ - return llvm::isa<JavaReferenceType>(static_cast<JavaType *>(type)) || - llvm::isa<JavaPrimitiveType>(static_cast<JavaType *>(type)); +bool JavaASTContext::IsScalarType(lldb::opaque_compiler_type_t type) { + return llvm::isa<JavaReferenceType>(static_cast<JavaType *>(type)) || + llvm::isa<JavaPrimitiveType>(static_cast<JavaType *>(type)); } -bool -JavaASTContext::IsVoidType(lldb::opaque_compiler_type_t type) -{ - return false; // TODO: Implement if we introduce the void type +bool JavaASTContext::IsVoidType(lldb::opaque_compiler_type_t type) { + return false; // TODO: Implement if we introduce the void type } -bool -JavaASTContext::SupportsLanguage(lldb::LanguageType language) -{ - return language == lldb::eLanguageTypeJava; +bool JavaASTContext::SupportsLanguage(lldb::LanguageType language) { + return language == lldb::eLanguageTypeJava; } -bool -JavaASTContext::IsRuntimeGeneratedType(lldb::opaque_compiler_type_t type) -{ - return true; +bool JavaASTContext::IsRuntimeGeneratedType(lldb::opaque_compiler_type_t type) { + return true; } -bool -JavaASTContext::IsPointerOrReferenceType(lldb::opaque_compiler_type_t type, CompilerType *pointee_type) -{ - return IsPointerType(type, pointee_type) || IsReferenceType(type, pointee_type); +bool JavaASTContext::IsPointerOrReferenceType(lldb::opaque_compiler_type_t type, + CompilerType *pointee_type) { + return IsPointerType(type, pointee_type) || + IsReferenceType(type, pointee_type); } -bool -JavaASTContext::IsCStringType(lldb::opaque_compiler_type_t type, uint32_t &length) -{ - return false; // TODO: Implement it if we need it for string literals +bool JavaASTContext::IsCStringType(lldb::opaque_compiler_type_t type, + uint32_t &length) { + return false; // TODO: Implement it if we need it for string literals } -bool -JavaASTContext::IsTypedefType(lldb::opaque_compiler_type_t type) -{ - return false; +bool JavaASTContext::IsTypedefType(lldb::opaque_compiler_type_t type) { + return false; } -bool -JavaASTContext::IsVectorType(lldb::opaque_compiler_type_t type, CompilerType *element_type, uint64_t *size) -{ - if (element_type) - element_type->Clear(); - if (size) - *size = 0; - return false; +bool JavaASTContext::IsVectorType(lldb::opaque_compiler_type_t type, + CompilerType *element_type, uint64_t *size) { + if (element_type) + element_type->Clear(); + if (size) + *size = 0; + return false; } -bool -JavaASTContext::IsPolymorphicClass(lldb::opaque_compiler_type_t type) -{ - return llvm::isa<JavaObjectType>(static_cast<JavaType *>(type)); +bool JavaASTContext::IsPolymorphicClass(lldb::opaque_compiler_type_t type) { + return llvm::isa<JavaObjectType>(static_cast<JavaType *>(type)); } uint32_t -JavaASTContext::IsHomogeneousAggregate(lldb::opaque_compiler_type_t type, CompilerType *base_type_ptr) -{ - return false; +JavaASTContext::IsHomogeneousAggregate(lldb::opaque_compiler_type_t type, + CompilerType *base_type_ptr) { + return false; } -bool -JavaASTContext::IsCompleteType(lldb::opaque_compiler_type_t type) -{ - return static_cast<JavaType *>(type)->IsCompleteType(); +bool JavaASTContext::IsCompleteType(lldb::opaque_compiler_type_t type) { + return static_cast<JavaType *>(type)->IsCompleteType(); } -bool -JavaASTContext::IsConst(lldb::opaque_compiler_type_t type) -{ - return false; +bool JavaASTContext::IsConst(lldb::opaque_compiler_type_t type) { + return false; } -bool -JavaASTContext::IsBeingDefined(lldb::opaque_compiler_type_t type) -{ - return false; +bool JavaASTContext::IsBeingDefined(lldb::opaque_compiler_type_t type) { + return false; } -bool -JavaASTContext::IsDefined(lldb::opaque_compiler_type_t type) -{ - return type != nullptr; +bool JavaASTContext::IsDefined(lldb::opaque_compiler_type_t type) { + return type != nullptr; } -bool -JavaASTContext::GetCompleteType(lldb::opaque_compiler_type_t type) -{ - if (IsCompleteType(type)) - return true; +bool JavaASTContext::GetCompleteType(lldb::opaque_compiler_type_t type) { + if (IsCompleteType(type)) + return true; - if (JavaArrayType *array = llvm::dyn_cast<JavaArrayType>(static_cast<JavaType *>(type))) - return GetCompleteType(array->GetElementType().GetOpaqueQualType()); + if (JavaArrayType *array = + llvm::dyn_cast<JavaArrayType>(static_cast<JavaType *>(type))) + return GetCompleteType(array->GetElementType().GetOpaqueQualType()); - if (JavaReferenceType *reference = llvm::dyn_cast<JavaReferenceType>(static_cast<JavaType *>(type))) - return GetCompleteType(reference->GetPointeeType().GetOpaqueQualType()); + if (JavaReferenceType *reference = + llvm::dyn_cast<JavaReferenceType>(static_cast<JavaType *>(type))) + return GetCompleteType(reference->GetPointeeType().GetOpaqueQualType()); - if (llvm::isa<JavaObjectType>(static_cast<JavaType *>(type))) - { - SymbolFile *symbol_file = GetSymbolFile(); - if (!symbol_file) - return false; + if (llvm::isa<JavaObjectType>(static_cast<JavaType *>(type))) { + SymbolFile *symbol_file = GetSymbolFile(); + if (!symbol_file) + return false; - CompilerType object_type(this, type); - return symbol_file->CompleteType(object_type); - } - return false; + CompilerType object_type(this, type); + return symbol_file->CompleteType(object_type); + } + return false; } -ConstString -JavaASTContext::GetTypeName(lldb::opaque_compiler_type_t type) -{ - if (type) - return static_cast<JavaType *>(type)->GetName(); - return ConstString(); +ConstString JavaASTContext::GetTypeName(lldb::opaque_compiler_type_t type) { + if (type) + return static_cast<JavaType *>(type)->GetName(); + return ConstString(); } uint32_t -JavaASTContext::GetTypeInfo(lldb::opaque_compiler_type_t type, CompilerType *pointee_or_element_compiler_type) -{ - if (pointee_or_element_compiler_type) - pointee_or_element_compiler_type->Clear(); - if (!type) - return 0; - - if (IsReferenceType(type, pointee_or_element_compiler_type)) - return eTypeHasChildren | eTypeHasValue | eTypeIsReference; - if (IsArrayType(type, pointee_or_element_compiler_type, nullptr, nullptr)) - return eTypeHasChildren | eTypeIsArray; - if (llvm::isa<JavaObjectType>(static_cast<JavaType *>(type))) - return eTypeHasChildren | eTypeIsClass; - - if (JavaPrimitiveType *ptype = llvm::dyn_cast<JavaPrimitiveType>(static_cast<JavaType *>(type))) - { - switch (ptype->GetTypeKind()) - { - case JavaPrimitiveType::eTypeByte: - case JavaPrimitiveType::eTypeShort: - case JavaPrimitiveType::eTypeInt: - case JavaPrimitiveType::eTypeLong: - return eTypeHasValue | eTypeIsBuiltIn | eTypeIsScalar | eTypeIsInteger | eTypeIsSigned; - case JavaPrimitiveType::eTypeFloat: - case JavaPrimitiveType::eTypeDouble: - return eTypeHasValue | eTypeIsBuiltIn | eTypeIsScalar | eTypeIsFloat | eTypeIsSigned; - case JavaPrimitiveType::eTypeBoolean: - return eTypeHasValue | eTypeIsBuiltIn | eTypeIsScalar; - case JavaPrimitiveType::eTypeChar: - return eTypeHasValue | eTypeIsBuiltIn | eTypeIsScalar; - } - } +JavaASTContext::GetTypeInfo(lldb::opaque_compiler_type_t type, + CompilerType *pointee_or_element_compiler_type) { + if (pointee_or_element_compiler_type) + pointee_or_element_compiler_type->Clear(); + if (!type) return 0; + + if (IsReferenceType(type, pointee_or_element_compiler_type)) + return eTypeHasChildren | eTypeHasValue | eTypeIsReference; + if (IsArrayType(type, pointee_or_element_compiler_type, nullptr, nullptr)) + return eTypeHasChildren | eTypeIsArray; + if (llvm::isa<JavaObjectType>(static_cast<JavaType *>(type))) + return eTypeHasChildren | eTypeIsClass; + + if (JavaPrimitiveType *ptype = + llvm::dyn_cast<JavaPrimitiveType>(static_cast<JavaType *>(type))) { + switch (ptype->GetTypeKind()) { + case JavaPrimitiveType::eTypeByte: + case JavaPrimitiveType::eTypeShort: + case JavaPrimitiveType::eTypeInt: + case JavaPrimitiveType::eTypeLong: + return eTypeHasValue | eTypeIsBuiltIn | eTypeIsScalar | eTypeIsInteger | + eTypeIsSigned; + case JavaPrimitiveType::eTypeFloat: + case JavaPrimitiveType::eTypeDouble: + return eTypeHasValue | eTypeIsBuiltIn | eTypeIsScalar | eTypeIsFloat | + eTypeIsSigned; + case JavaPrimitiveType::eTypeBoolean: + return eTypeHasValue | eTypeIsBuiltIn | eTypeIsScalar; + case JavaPrimitiveType::eTypeChar: + return eTypeHasValue | eTypeIsBuiltIn | eTypeIsScalar; + } + } + return 0; } lldb::TypeClass -JavaASTContext::GetTypeClass(lldb::opaque_compiler_type_t type) -{ - if (!type) - return eTypeClassInvalid; - if (llvm::isa<JavaReferenceType>(static_cast<JavaType *>(type))) - return eTypeClassReference; - if (llvm::isa<JavaArrayType>(static_cast<JavaType *>(type))) - return eTypeClassArray; - if (llvm::isa<JavaObjectType>(static_cast<JavaType *>(type))) - return eTypeClassClass; - if (llvm::isa<JavaPrimitiveType>(static_cast<JavaType *>(type))) - return eTypeClassBuiltin; - assert(false && "Java type with unhandled type class"); +JavaASTContext::GetTypeClass(lldb::opaque_compiler_type_t type) { + if (!type) return eTypeClassInvalid; + if (llvm::isa<JavaReferenceType>(static_cast<JavaType *>(type))) + return eTypeClassReference; + if (llvm::isa<JavaArrayType>(static_cast<JavaType *>(type))) + return eTypeClassArray; + if (llvm::isa<JavaObjectType>(static_cast<JavaType *>(type))) + return eTypeClassClass; + if (llvm::isa<JavaPrimitiveType>(static_cast<JavaType *>(type))) + return eTypeClassBuiltin; + assert(false && "Java type with unhandled type class"); + return eTypeClassInvalid; } lldb::LanguageType -JavaASTContext::GetMinimumLanguage(lldb::opaque_compiler_type_t type) -{ - return lldb::eLanguageTypeJava; +JavaASTContext::GetMinimumLanguage(lldb::opaque_compiler_type_t type) { + return lldb::eLanguageTypeJava; } CompilerType -JavaASTContext::GetArrayElementType(lldb::opaque_compiler_type_t type, uint64_t *stride) -{ - if (stride) - *stride = 0; - - CompilerType element_type; - if (IsArrayType(type, &element_type, nullptr, nullptr)) - return element_type; - return CompilerType(); +JavaASTContext::GetArrayElementType(lldb::opaque_compiler_type_t type, + uint64_t *stride) { + if (stride) + *stride = 0; + + CompilerType element_type; + if (IsArrayType(type, &element_type, nullptr, nullptr)) + return element_type; + return CompilerType(); } -CompilerType -JavaASTContext::GetPointeeType(lldb::opaque_compiler_type_t type) -{ - CompilerType pointee_type; - if (IsPointerType(type, &pointee_type)) - return pointee_type; - return CompilerType(); +CompilerType JavaASTContext::GetPointeeType(lldb::opaque_compiler_type_t type) { + CompilerType pointee_type; + if (IsPointerType(type, &pointee_type)) + return pointee_type; + return CompilerType(); } -CompilerType -JavaASTContext::GetPointerType(lldb::opaque_compiler_type_t type) -{ - return CompilerType(); // No pointer types in java +CompilerType JavaASTContext::GetPointerType(lldb::opaque_compiler_type_t type) { + return CompilerType(); // No pointer types in java } CompilerType -JavaASTContext::GetCanonicalType(lldb::opaque_compiler_type_t type) -{ - return CompilerType(this, type); +JavaASTContext::GetCanonicalType(lldb::opaque_compiler_type_t type) { + return CompilerType(this, type); } CompilerType -JavaASTContext::GetFullyUnqualifiedType(lldb::opaque_compiler_type_t type) -{ - return CompilerType(this, type); +JavaASTContext::GetFullyUnqualifiedType(lldb::opaque_compiler_type_t type) { + return CompilerType(this, type); } CompilerType -JavaASTContext::GetNonReferenceType(lldb::opaque_compiler_type_t type) -{ - CompilerType pointee_type; - if (IsReferenceType(type, &pointee_type)) - return pointee_type; - return CompilerType(this, type); +JavaASTContext::GetNonReferenceType(lldb::opaque_compiler_type_t type) { + CompilerType pointee_type; + if (IsReferenceType(type, &pointee_type)) + return pointee_type; + return CompilerType(this, type); } CompilerType -JavaASTContext::GetTypedefedType(lldb::opaque_compiler_type_t type) -{ - return CompilerType(); +JavaASTContext::GetTypedefedType(lldb::opaque_compiler_type_t type) { + return CompilerType(); } -CompilerType -JavaASTContext::GetBasicTypeFromAST(lldb::BasicType basic_type) -{ - return CompilerType(); +CompilerType JavaASTContext::GetBasicTypeFromAST(lldb::BasicType basic_type) { + return CompilerType(); } CompilerType -JavaASTContext::GetBuiltinTypeForEncodingAndBitSize(lldb::Encoding encoding, size_t bit_size) -{ - return CompilerType(); +JavaASTContext::GetBuiltinTypeForEncodingAndBitSize(lldb::Encoding encoding, + size_t bit_size) { + return CompilerType(); } -size_t -JavaASTContext::GetTypeBitAlign(lldb::opaque_compiler_type_t type) -{ - return 0; +size_t JavaASTContext::GetTypeBitAlign(lldb::opaque_compiler_type_t type) { + return 0; } lldb::BasicType -JavaASTContext::GetBasicTypeEnumeration(lldb::opaque_compiler_type_t type) -{ - if (JavaPrimitiveType *ptype = llvm::dyn_cast<JavaPrimitiveType>(static_cast<JavaType *>(type))) - { - switch (ptype->GetTypeKind()) - { - case JavaPrimitiveType::eTypeByte: - return eBasicTypeOther; - case JavaPrimitiveType::eTypeShort: - return eBasicTypeShort; - case JavaPrimitiveType::eTypeInt: - return eBasicTypeInt; - case JavaPrimitiveType::eTypeLong: - return eBasicTypeLong; - case JavaPrimitiveType::eTypeFloat: - return eBasicTypeFloat; - case JavaPrimitiveType::eTypeDouble: - return eBasicTypeDouble; - case JavaPrimitiveType::eTypeBoolean: - return eBasicTypeBool; - case JavaPrimitiveType::eTypeChar: - return eBasicTypeChar; - } - } - return eBasicTypeInvalid; -} - -uint64_t -JavaASTContext::GetBitSize(lldb::opaque_compiler_type_t type, ExecutionContextScope *exe_scope) -{ - if (JavaPrimitiveType *ptype = llvm::dyn_cast<JavaPrimitiveType>(static_cast<JavaType *>(type))) - { - switch (ptype->GetTypeKind()) - { - case JavaPrimitiveType::eTypeByte: - return 8; - case JavaPrimitiveType::eTypeShort: - return 16; - case JavaPrimitiveType::eTypeInt: - return 32; - case JavaPrimitiveType::eTypeLong: - return 64; - case JavaPrimitiveType::eTypeFloat: - return 32; - case JavaPrimitiveType::eTypeDouble: - return 64; - case JavaPrimitiveType::eTypeBoolean: - return 1; - case JavaPrimitiveType::eTypeChar: - return 16; - } - } - else if (llvm::isa<JavaReferenceType>(static_cast<JavaType *>(type))) - { - return 32; // References are always 4 byte long in java - } - else if (llvm::isa<JavaArrayType>(static_cast<JavaType *>(type))) - { - return 64; - } - else if (JavaObjectType *obj = llvm::dyn_cast<JavaObjectType>(static_cast<JavaType *>(type))) - { - return obj->GetByteSize() * 8; - } - return 0; -} - -lldb::Encoding -JavaASTContext::GetEncoding(lldb::opaque_compiler_type_t type, uint64_t &count) -{ - count = 1; - - if (JavaPrimitiveType *ptype = llvm::dyn_cast<JavaPrimitiveType>(static_cast<JavaType *>(type))) - { - switch (ptype->GetTypeKind()) - { - case JavaPrimitiveType::eTypeByte: - case JavaPrimitiveType::eTypeShort: - case JavaPrimitiveType::eTypeInt: - case JavaPrimitiveType::eTypeLong: - return eEncodingSint; - case JavaPrimitiveType::eTypeFloat: - case JavaPrimitiveType::eTypeDouble: - return eEncodingIEEE754; - case JavaPrimitiveType::eTypeBoolean: - case JavaPrimitiveType::eTypeChar: - return eEncodingUint; - } - } - if (IsReferenceType(type)) - return eEncodingUint; - return eEncodingInvalid; -} - -lldb::Format -JavaASTContext::GetFormat(lldb::opaque_compiler_type_t type) -{ - if (JavaPrimitiveType *ptype = llvm::dyn_cast<JavaPrimitiveType>(static_cast<JavaType *>(type))) - { - switch (ptype->GetTypeKind()) - { - case JavaPrimitiveType::eTypeByte: - case JavaPrimitiveType::eTypeShort: - case JavaPrimitiveType::eTypeInt: - case JavaPrimitiveType::eTypeLong: - return eFormatDecimal; - case JavaPrimitiveType::eTypeFloat: - case JavaPrimitiveType::eTypeDouble: - return eFormatFloat; - case JavaPrimitiveType::eTypeBoolean: - return eFormatBoolean; - case JavaPrimitiveType::eTypeChar: - return eFormatUnicode16; - } - } - if (IsReferenceType(type)) - return eFormatHex; - return eFormatDefault; -} - -unsigned -JavaASTContext::GetTypeQualifiers(lldb::opaque_compiler_type_t type) -{ - return 0; +JavaASTContext::GetBasicTypeEnumeration(lldb::opaque_compiler_type_t type) { + if (JavaPrimitiveType *ptype = + llvm::dyn_cast<JavaPrimitiveType>(static_cast<JavaType *>(type))) { + switch (ptype->GetTypeKind()) { + case JavaPrimitiveType::eTypeByte: + return eBasicTypeOther; + case JavaPrimitiveType::eTypeShort: + return eBasicTypeShort; + case JavaPrimitiveType::eTypeInt: + return eBasicTypeInt; + case JavaPrimitiveType::eTypeLong: + return eBasicTypeLong; + case JavaPrimitiveType::eTypeFloat: + return eBasicTypeFloat; + case JavaPrimitiveType::eTypeDouble: + return eBasicTypeDouble; + case JavaPrimitiveType::eTypeBoolean: + return eBasicTypeBool; + case JavaPrimitiveType::eTypeChar: + return eBasicTypeChar; + } + } + return eBasicTypeInvalid; +} + +uint64_t JavaASTContext::GetBitSize(lldb::opaque_compiler_type_t type, + ExecutionContextScope *exe_scope) { + if (JavaPrimitiveType *ptype = + llvm::dyn_cast<JavaPrimitiveType>(static_cast<JavaType *>(type))) { + switch (ptype->GetTypeKind()) { + case JavaPrimitiveType::eTypeByte: + return 8; + case JavaPrimitiveType::eTypeShort: + return 16; + case JavaPrimitiveType::eTypeInt: + return 32; + case JavaPrimitiveType::eTypeLong: + return 64; + case JavaPrimitiveType::eTypeFloat: + return 32; + case JavaPrimitiveType::eTypeDouble: + return 64; + case JavaPrimitiveType::eTypeBoolean: + return 1; + case JavaPrimitiveType::eTypeChar: + return 16; + } + } else if (llvm::isa<JavaReferenceType>(static_cast<JavaType *>(type))) { + return 32; // References are always 4 byte long in java + } else if (llvm::isa<JavaArrayType>(static_cast<JavaType *>(type))) { + return 64; + } else if (JavaObjectType *obj = llvm::dyn_cast<JavaObjectType>( + static_cast<JavaType *>(type))) { + return obj->GetByteSize() * 8; + } + return 0; +} + +lldb::Encoding JavaASTContext::GetEncoding(lldb::opaque_compiler_type_t type, + uint64_t &count) { + count = 1; + + if (JavaPrimitiveType *ptype = + llvm::dyn_cast<JavaPrimitiveType>(static_cast<JavaType *>(type))) { + switch (ptype->GetTypeKind()) { + case JavaPrimitiveType::eTypeByte: + case JavaPrimitiveType::eTypeShort: + case JavaPrimitiveType::eTypeInt: + case JavaPrimitiveType::eTypeLong: + return eEncodingSint; + case JavaPrimitiveType::eTypeFloat: + case JavaPrimitiveType::eTypeDouble: + return eEncodingIEEE754; + case JavaPrimitiveType::eTypeBoolean: + case JavaPrimitiveType::eTypeChar: + return eEncodingUint; + } + } + if (IsReferenceType(type)) + return eEncodingUint; + return eEncodingInvalid; +} + +lldb::Format JavaASTContext::GetFormat(lldb::opaque_compiler_type_t type) { + if (JavaPrimitiveType *ptype = + llvm::dyn_cast<JavaPrimitiveType>(static_cast<JavaType *>(type))) { + switch (ptype->GetTypeKind()) { + case JavaPrimitiveType::eTypeByte: + case JavaPrimitiveType::eTypeShort: + case JavaPrimitiveType::eTypeInt: + case JavaPrimitiveType::eTypeLong: + return eFormatDecimal; + case JavaPrimitiveType::eTypeFloat: + case JavaPrimitiveType::eTypeDouble: + return eFormatFloat; + case JavaPrimitiveType::eTypeBoolean: + return eFormatBoolean; + case JavaPrimitiveType::eTypeChar: + return eFormatUnicode16; + } + } + if (IsReferenceType(type)) + return eFormatHex; + return eFormatDefault; +} + +unsigned JavaASTContext::GetTypeQualifiers(lldb::opaque_compiler_type_t type) { + return 0; } size_t -JavaASTContext::ConvertStringToFloatValue(lldb::opaque_compiler_type_t type, const char *s, uint8_t *dst, - size_t dst_size) -{ - assert(false && "Not implemented"); - return 0; +JavaASTContext::ConvertStringToFloatValue(lldb::opaque_compiler_type_t type, + const char *s, uint8_t *dst, + size_t dst_size) { + assert(false && "Not implemented"); + return 0; } size_t -JavaASTContext::GetNumTemplateArguments(lldb::opaque_compiler_type_t type) -{ - return 0; +JavaASTContext::GetNumTemplateArguments(lldb::opaque_compiler_type_t type) { + return 0; } CompilerType -JavaASTContext::GetTemplateArgument(lldb::opaque_compiler_type_t type, size_t idx, lldb::TemplateArgumentKind &kind) -{ - return CompilerType(); +JavaASTContext::GetTemplateArgument(lldb::opaque_compiler_type_t type, + size_t idx, + lldb::TemplateArgumentKind &kind) { + return CompilerType(); } -uint32_t -JavaASTContext::GetNumFields(lldb::opaque_compiler_type_t type) -{ - if (JavaObjectType *obj = llvm::dyn_cast<JavaObjectType>(static_cast<JavaType *>(type))) - { - GetCompleteType(type); - return obj->GetNumFields(); - } - return 0; -} +uint32_t JavaASTContext::GetNumFields(lldb::opaque_compiler_type_t type) { + if (JavaObjectType *obj = + llvm::dyn_cast<JavaObjectType>(static_cast<JavaType *>(type))) { + GetCompleteType(type); + return obj->GetNumFields(); + } + return 0; +} + +CompilerType JavaASTContext::GetFieldAtIndex(lldb::opaque_compiler_type_t type, + size_t idx, std::string &name, + uint64_t *bit_offset_ptr, + uint32_t *bitfield_bit_size_ptr, + bool *is_bitfield_ptr) { + if (bit_offset_ptr) + *bit_offset_ptr = 0; + if (bitfield_bit_size_ptr) + *bitfield_bit_size_ptr = 0; + if (is_bitfield_ptr) + *is_bitfield_ptr = false; + + if (JavaObjectType *obj = + llvm::dyn_cast<JavaObjectType>(static_cast<JavaType *>(type))) { + GetCompleteType(type); -CompilerType -JavaASTContext::GetFieldAtIndex(lldb::opaque_compiler_type_t type, size_t idx, std::string &name, - uint64_t *bit_offset_ptr, uint32_t *bitfield_bit_size_ptr, bool *is_bitfield_ptr) -{ + JavaObjectType::Field *field = obj->GetFieldAtIndex(idx); + if (!field) + return CompilerType(); + name = field->m_name.AsCString(); if (bit_offset_ptr) - *bit_offset_ptr = 0; - if (bitfield_bit_size_ptr) - *bitfield_bit_size_ptr = 0; - if (is_bitfield_ptr) - *is_bitfield_ptr = false; - - if (JavaObjectType *obj = llvm::dyn_cast<JavaObjectType>(static_cast<JavaType *>(type))) - { - GetCompleteType(type); - - JavaObjectType::Field *field = obj->GetFieldAtIndex(idx); - if (!field) - return CompilerType(); - name = field->m_name.AsCString(); - if (bit_offset_ptr) - *bit_offset_ptr = field->m_offset * 8; - return field->m_type; - } - return CompilerType(); + *bit_offset_ptr = field->m_offset * 8; + return field->m_type; + } + return CompilerType(); } -uint32_t -JavaASTContext::GetNumChildren(lldb::opaque_compiler_type_t type, bool omit_empty_base_classes) -{ - GetCompleteType(type); +uint32_t JavaASTContext::GetNumChildren(lldb::opaque_compiler_type_t type, + bool omit_empty_base_classes) { + GetCompleteType(type); - if (JavaReferenceType *ref = llvm::dyn_cast<JavaReferenceType>(static_cast<JavaType *>(type))) - return ref->GetPointeeType().GetNumChildren(omit_empty_base_classes); + if (JavaReferenceType *ref = + llvm::dyn_cast<JavaReferenceType>(static_cast<JavaType *>(type))) + return ref->GetPointeeType().GetNumChildren(omit_empty_base_classes); - if (llvm::isa<JavaObjectType>(static_cast<JavaType *>(type))) - return GetNumFields(type) + GetNumDirectBaseClasses(type); + if (llvm::isa<JavaObjectType>(static_cast<JavaType *>(type))) + return GetNumFields(type) + GetNumDirectBaseClasses(type); - return 0; + return 0; } uint32_t -JavaASTContext::GetNumDirectBaseClasses(lldb::opaque_compiler_type_t type) -{ - if (JavaObjectType *obj = llvm::dyn_cast<JavaObjectType>(static_cast<JavaType *>(type))) - { - GetCompleteType(type); - return obj->GetNumInterfaces() + (obj->GetBaseClass() ? 1 : 0); - } - return 0; +JavaASTContext::GetNumDirectBaseClasses(lldb::opaque_compiler_type_t type) { + if (JavaObjectType *obj = + llvm::dyn_cast<JavaObjectType>(static_cast<JavaType *>(type))) { + GetCompleteType(type); + return obj->GetNumInterfaces() + (obj->GetBaseClass() ? 1 : 0); + } + return 0; } uint32_t -JavaASTContext::GetNumVirtualBaseClasses(lldb::opaque_compiler_type_t type) -{ - if (JavaObjectType *obj = llvm::dyn_cast<JavaObjectType>(static_cast<JavaType *>(type))) - { - GetCompleteType(type); - return obj->GetNumInterfaces(); - } - return 0; +JavaASTContext::GetNumVirtualBaseClasses(lldb::opaque_compiler_type_t type) { + if (JavaObjectType *obj = + llvm::dyn_cast<JavaObjectType>(static_cast<JavaType *>(type))) { + GetCompleteType(type); + return obj->GetNumInterfaces(); + } + return 0; } -CompilerType -JavaASTContext::GetDirectBaseClassAtIndex(lldb::opaque_compiler_type_t type, size_t idx, uint32_t *bit_offset_ptr) -{ - if (JavaObjectType *obj = llvm::dyn_cast<JavaObjectType>(static_cast<JavaType *>(type))) - { - GetCompleteType(type); - - if (CompilerType base_class = obj->GetBaseClass()) - { - if (idx == 0) - return base_class; - else - --idx; - } - return obj->GetInterfaceAtIndex(idx); +CompilerType JavaASTContext::GetDirectBaseClassAtIndex( + lldb::opaque_compiler_type_t type, size_t idx, uint32_t *bit_offset_ptr) { + if (JavaObjectType *obj = + llvm::dyn_cast<JavaObjectType>(static_cast<JavaType *>(type))) { + GetCompleteType(type); + + if (CompilerType base_class = obj->GetBaseClass()) { + if (idx == 0) + return base_class; + else + --idx; } - return CompilerType(); + return obj->GetInterfaceAtIndex(idx); + } + return CompilerType(); } -CompilerType -JavaASTContext::GetVirtualBaseClassAtIndex(lldb::opaque_compiler_type_t type, size_t idx, uint32_t *bit_offset_ptr) -{ - if (JavaObjectType *obj = llvm::dyn_cast<JavaObjectType>(static_cast<JavaType *>(type))) - { - GetCompleteType(type); - return obj->GetInterfaceAtIndex(idx); - } - return CompilerType(); +CompilerType JavaASTContext::GetVirtualBaseClassAtIndex( + lldb::opaque_compiler_type_t type, size_t idx, uint32_t *bit_offset_ptr) { + if (JavaObjectType *obj = + llvm::dyn_cast<JavaObjectType>(static_cast<JavaType *>(type))) { + GetCompleteType(type); + return obj->GetInterfaceAtIndex(idx); + } + return CompilerType(); } -void -JavaASTContext::DumpValue(lldb::opaque_compiler_type_t type, ExecutionContext *exe_ctx, Stream *s, lldb::Format format, - const DataExtractor &data, lldb::offset_t data_offset, size_t data_byte_size, - uint32_t bitfield_bit_size, uint32_t bitfield_bit_offset, bool show_types, bool show_summary, - bool verbose, uint32_t depth) -{ - assert(false && "Not implemented"); -} - -bool -JavaASTContext::DumpTypeValue(lldb::opaque_compiler_type_t type, Stream *s, lldb::Format format, - const DataExtractor &data, lldb::offset_t data_offset, size_t data_byte_size, - uint32_t bitfield_bit_size, uint32_t bitfield_bit_offset, - ExecutionContextScope *exe_scope) -{ - if (IsScalarType(type)) - { - return data.Dump(s, data_offset, format, data_byte_size, - 1, // count - UINT32_MAX, LLDB_INVALID_ADDRESS, bitfield_bit_size, bitfield_bit_offset, exe_scope); - } - return false; +void JavaASTContext::DumpValue( + lldb::opaque_compiler_type_t type, ExecutionContext *exe_ctx, Stream *s, + lldb::Format format, const DataExtractor &data, lldb::offset_t data_offset, + size_t data_byte_size, uint32_t bitfield_bit_size, + uint32_t bitfield_bit_offset, bool show_types, bool show_summary, + bool verbose, uint32_t depth) { + assert(false && "Not implemented"); } -void -JavaASTContext::DumpTypeDescription(lldb::opaque_compiler_type_t type) -{ - StreamFile s(stdout, false); - DumpTypeDescription(type, &s); +bool JavaASTContext::DumpTypeValue( + lldb::opaque_compiler_type_t type, Stream *s, lldb::Format format, + const DataExtractor &data, lldb::offset_t data_offset, + size_t data_byte_size, uint32_t bitfield_bit_size, + uint32_t bitfield_bit_offset, ExecutionContextScope *exe_scope) { + if (IsScalarType(type)) { + return data.Dump(s, data_offset, format, data_byte_size, + 1, // count + UINT32_MAX, LLDB_INVALID_ADDRESS, bitfield_bit_size, + bitfield_bit_offset, exe_scope); + } + return false; } -void -JavaASTContext::DumpTypeDescription(lldb::opaque_compiler_type_t type, Stream *s) -{ - static_cast<JavaType *>(type)->Dump(s); +void JavaASTContext::DumpTypeDescription(lldb::opaque_compiler_type_t type) { + StreamFile s(stdout, false); + DumpTypeDescription(type, &s); } -void -JavaASTContext::DumpSummary(lldb::opaque_compiler_type_t type, ExecutionContext *exe_ctx, Stream *s, - const DataExtractor &data, lldb::offset_t data_offset, size_t data_byte_size) -{ - assert(false && "Not implemented"); +void JavaASTContext::DumpTypeDescription(lldb::opaque_compiler_type_t type, + Stream *s) { + static_cast<JavaType *>(type)->Dump(s); } -int -JavaASTContext::GetFunctionArgumentCount(lldb::opaque_compiler_type_t type) -{ - return 0; +void JavaASTContext::DumpSummary(lldb::opaque_compiler_type_t type, + ExecutionContext *exe_ctx, Stream *s, + const DataExtractor &data, + lldb::offset_t data_offset, + size_t data_byte_size) { + assert(false && "Not implemented"); } -CompilerType -JavaASTContext::GetFunctionArgumentTypeAtIndex(lldb::opaque_compiler_type_t type, size_t idx) -{ - return CompilerType(); +int JavaASTContext::GetFunctionArgumentCount( + lldb::opaque_compiler_type_t type) { + return 0; +} + +CompilerType JavaASTContext::GetFunctionArgumentTypeAtIndex( + lldb::opaque_compiler_type_t type, size_t idx) { + return CompilerType(); } CompilerType -JavaASTContext::GetFunctionReturnType(lldb::opaque_compiler_type_t type) -{ - return CompilerType(); +JavaASTContext::GetFunctionReturnType(lldb::opaque_compiler_type_t type) { + return CompilerType(); } size_t -JavaASTContext::GetNumMemberFunctions(lldb::opaque_compiler_type_t type) -{ - return 0; +JavaASTContext::GetNumMemberFunctions(lldb::opaque_compiler_type_t type) { + return 0; } TypeMemberFunctionImpl -JavaASTContext::GetMemberFunctionAtIndex(lldb::opaque_compiler_type_t type, size_t idx) -{ - return TypeMemberFunctionImpl(); -} +JavaASTContext::GetMemberFunctionAtIndex(lldb::opaque_compiler_type_t type, + size_t idx) { + return TypeMemberFunctionImpl(); +} + +CompilerType JavaASTContext::GetChildCompilerTypeAtIndex( + lldb::opaque_compiler_type_t type, ExecutionContext *exe_ctx, size_t idx, + bool transparent_pointers, bool omit_empty_base_classes, + bool ignore_array_bounds, std::string &child_name, + uint32_t &child_byte_size, int32_t &child_byte_offset, + uint32_t &child_bitfield_bit_size, uint32_t &child_bitfield_bit_offset, + bool &child_is_base_class, bool &child_is_deref_of_parent, + ValueObject *valobj, uint64_t &language_flags) { + child_name.clear(); + child_byte_size = 0; + child_byte_offset = 0; + child_bitfield_bit_size = 0; + child_bitfield_bit_offset = 0; + child_is_base_class = false; + child_is_deref_of_parent = false; + language_flags = 0; + + ExecutionContextScope *exec_ctx_scope = + exe_ctx ? exe_ctx->GetBestExecutionContextScope() : nullptr; + + if (JavaObjectType *obj = + llvm::dyn_cast<JavaObjectType>(static_cast<JavaType *>(type))) { + GetCompleteType(type); -CompilerType -JavaASTContext::GetChildCompilerTypeAtIndex(lldb::opaque_compiler_type_t type, ExecutionContext *exe_ctx, size_t idx, - bool transparent_pointers, bool omit_empty_base_classes, - bool ignore_array_bounds, std::string &child_name, - uint32_t &child_byte_size, int32_t &child_byte_offset, - uint32_t &child_bitfield_bit_size, uint32_t &child_bitfield_bit_offset, - bool &child_is_base_class, bool &child_is_deref_of_parent, - ValueObject *valobj, uint64_t &language_flags) -{ - child_name.clear(); - child_byte_size = 0; + if (CompilerType base_class = obj->GetBaseClass()) { + if (idx == 0) { + JavaType *base_class_type = + static_cast<JavaType *>(base_class.GetOpaqueQualType()); + child_name = base_class_type->GetName().GetCString(); + child_byte_size = base_class.GetByteSize( + exe_ctx ? exe_ctx->GetBestExecutionContextScope() : nullptr); + child_byte_offset = obj->GetBaseClassOffset(); + child_is_base_class = true; + return base_class; + } + idx -= 1; + } + + JavaObjectType::Field *field = obj->GetFieldAtIndex(idx); + if (!field) + return CompilerType(); + + child_name = field->m_name.AsCString(); + child_byte_size = field->m_type.GetByteSize(exec_ctx_scope); + child_byte_offset = field->m_offset; + return field->m_type; + } else if (JavaReferenceType *ref = llvm::dyn_cast<JavaReferenceType>( + static_cast<JavaType *>(type))) { + CompilerType pointee_type = ref->GetPointeeType(); + + if (transparent_pointers) + return pointee_type.GetChildCompilerTypeAtIndex( + exe_ctx, idx, transparent_pointers, omit_empty_base_classes, + ignore_array_bounds, child_name, child_byte_size, child_byte_offset, + child_bitfield_bit_size, child_bitfield_bit_offset, + child_is_base_class, child_is_deref_of_parent, valobj, + language_flags); + + if (idx != 0) + return CompilerType(); + + if (valobj && valobj->GetName()) + child_name = valobj->GetName().GetCString(); + child_is_deref_of_parent = true; child_byte_offset = 0; - child_bitfield_bit_size = 0; - child_bitfield_bit_offset = 0; - child_is_base_class = false; - child_is_deref_of_parent = false; - language_flags = 0; - - ExecutionContextScope *exec_ctx_scope = exe_ctx ? exe_ctx->GetBestExecutionContextScope() : nullptr; - - if (JavaObjectType *obj = llvm::dyn_cast<JavaObjectType>(static_cast<JavaType *>(type))) - { - GetCompleteType(type); - - if (CompilerType base_class = obj->GetBaseClass()) - { - if (idx == 0) - { - JavaType *base_class_type = static_cast<JavaType *>(base_class.GetOpaqueQualType()); - child_name = base_class_type->GetName().GetCString(); - child_byte_size = base_class.GetByteSize(exe_ctx ? exe_ctx->GetBestExecutionContextScope() : nullptr); - child_byte_offset = obj->GetBaseClassOffset(); - child_is_base_class = true; - return base_class; - } - idx -= 1; - } - - JavaObjectType::Field *field = obj->GetFieldAtIndex(idx); - if (!field) - return CompilerType(); - - child_name = field->m_name.AsCString(); - child_byte_size = field->m_type.GetByteSize(exec_ctx_scope); - child_byte_offset = field->m_offset; - return field->m_type; - } - else if (JavaReferenceType *ref = llvm::dyn_cast<JavaReferenceType>(static_cast<JavaType *>(type))) - { - CompilerType pointee_type = ref->GetPointeeType(); - - if (transparent_pointers) - return pointee_type.GetChildCompilerTypeAtIndex( - exe_ctx, idx, transparent_pointers, omit_empty_base_classes, ignore_array_bounds, child_name, - child_byte_size, child_byte_offset, child_bitfield_bit_size, child_bitfield_bit_offset, - child_is_base_class, child_is_deref_of_parent, valobj, language_flags); - - if (idx != 0) - return CompilerType(); - - if (valobj && valobj->GetName()) - child_name = valobj->GetName().GetCString(); - child_is_deref_of_parent = true; - child_byte_offset = 0; - child_byte_size = pointee_type.GetByteSize(exec_ctx_scope); - return pointee_type; - } - return CompilerType(); + child_byte_size = pointee_type.GetByteSize(exec_ctx_scope); + return pointee_type; + } + return CompilerType(); } uint32_t -JavaASTContext::GetIndexOfChildWithName(lldb::opaque_compiler_type_t type, const char *name, - bool omit_empty_base_classes) -{ - if (JavaObjectType *obj = llvm::dyn_cast<JavaObjectType>(static_cast<JavaType *>(type))) - { - GetCompleteType(type); - - uint32_t index_offset = 0; - if (CompilerType base_class = obj->GetBaseClass()) - { - if (base_class.GetTypeName() == ConstString(name)) - return 0; - index_offset = 1; - } - for (uint32_t i = 0; i < obj->GetNumFields(); ++i) - { - if (obj->GetFieldAtIndex(i)->m_name == ConstString(name)) - return i + index_offset; - } - } - else if (JavaReferenceType *ref = llvm::dyn_cast<JavaReferenceType>(static_cast<JavaType *>(type))) - { - return GetIndexOfChildWithName(ref->GetPointeeType().GetOpaqueQualType(), name, omit_empty_base_classes); - } - return UINT_MAX; -} +JavaASTContext::GetIndexOfChildWithName(lldb::opaque_compiler_type_t type, + const char *name, + bool omit_empty_base_classes) { + if (JavaObjectType *obj = + llvm::dyn_cast<JavaObjectType>(static_cast<JavaType *>(type))) { + GetCompleteType(type); -size_t -JavaASTContext::GetIndexOfChildMemberWithName(lldb::opaque_compiler_type_t type, const char *name, - bool omit_empty_base_classes, std::vector<uint32_t> &child_indexes) -{ - child_indexes.clear(); - - if (JavaObjectType *obj = llvm::dyn_cast<JavaObjectType>(static_cast<JavaType *>(type))) - { - GetCompleteType(type); - - uint32_t index_offset = 0; - if (CompilerType base_class = obj->GetBaseClass()) - { - if (GetIndexOfChildMemberWithName(base_class.GetOpaqueQualType(), name, omit_empty_base_classes, - child_indexes) != 0) - { - child_indexes.insert(child_indexes.begin(), 0); - return child_indexes.size(); - } - index_offset = 1; - } - - for (uint32_t i = 0; i < obj->GetNumFields(); ++i) - { - if (obj->GetFieldAtIndex(i)->m_name == ConstString(name)) - { - child_indexes.push_back(i + index_offset); - return child_indexes.size(); - } - } + uint32_t index_offset = 0; + if (CompilerType base_class = obj->GetBaseClass()) { + if (base_class.GetTypeName() == ConstString(name)) + return 0; + index_offset = 1; } - else if (JavaReferenceType *ref = llvm::dyn_cast<JavaReferenceType>(static_cast<JavaType *>(type))) - { - return GetIndexOfChildMemberWithName(ref->GetPointeeType().GetOpaqueQualType(), name, omit_empty_base_classes, - child_indexes); + for (uint32_t i = 0; i < obj->GetNumFields(); ++i) { + if (obj->GetFieldAtIndex(i)->m_name == ConstString(name)) + return i + index_offset; } - return 0; -} - -CompilerType -JavaASTContext::GetLValueReferenceType(lldb::opaque_compiler_type_t type) -{ - return CreateReferenceType(CompilerType(this, type)); + } else if (JavaReferenceType *ref = llvm::dyn_cast<JavaReferenceType>( + static_cast<JavaType *>(type))) { + return GetIndexOfChildWithName(ref->GetPointeeType().GetOpaqueQualType(), + name, omit_empty_base_classes); + } + return UINT_MAX; } -ConstString -JavaASTContext::DeclContextGetScopeQualifiedName(lldb::opaque_compiler_type_t opaque_decl_ctx) -{ - return GetTypeName(opaque_decl_ctx); -} +size_t JavaASTContext::GetIndexOfChildMemberWithName( + lldb::opaque_compiler_type_t type, const char *name, + bool omit_empty_base_classes, std::vector<uint32_t> &child_indexes) { + child_indexes.clear(); -static void -AddPrimitiveType(JavaASTContext::JavaTypeMap &type_map, JavaPrimitiveType::TypeKind type_kind) -{ - JavaPrimitiveType *type = new JavaPrimitiveType(type_kind); - type_map.emplace(type->GetName(), std::unique_ptr<JavaASTContext::JavaType>(type)); -} + if (JavaObjectType *obj = + llvm::dyn_cast<JavaObjectType>(static_cast<JavaType *>(type))) { + GetCompleteType(type); -CompilerType -JavaASTContext::CreateBaseType(const ConstString &name) -{ - if (m_base_type_map.empty()) - { - AddPrimitiveType(m_base_type_map, JavaPrimitiveType::eTypeByte); - AddPrimitiveType(m_base_type_map, JavaPrimitiveType::eTypeShort); - AddPrimitiveType(m_base_type_map, JavaPrimitiveType::eTypeInt); - AddPrimitiveType(m_base_type_map, JavaPrimitiveType::eTypeLong); - AddPrimitiveType(m_base_type_map, JavaPrimitiveType::eTypeFloat); - AddPrimitiveType(m_base_type_map, JavaPrimitiveType::eTypeDouble); - AddPrimitiveType(m_base_type_map, JavaPrimitiveType::eTypeBoolean); - AddPrimitiveType(m_base_type_map, JavaPrimitiveType::eTypeChar); + uint32_t index_offset = 0; + if (CompilerType base_class = obj->GetBaseClass()) { + if (GetIndexOfChildMemberWithName(base_class.GetOpaqueQualType(), name, + omit_empty_base_classes, + child_indexes) != 0) { + child_indexes.insert(child_indexes.begin(), 0); + return child_indexes.size(); + } + index_offset = 1; } - auto it = m_base_type_map.find(name); - if (it != m_base_type_map.end()) - return CompilerType(this, it->second.get()); - return CompilerType(); -} -CompilerType -JavaASTContext::CreateObjectType(const ConstString &name, const ConstString &linkage_name, uint32_t byte_size) -{ - auto it = m_object_type_map.find(name); - if (it == m_object_type_map.end()) - { - std::unique_ptr<JavaType> object_type(new JavaObjectType(name, linkage_name, byte_size)); - it = m_object_type_map.emplace(name, std::move(object_type)).first; + for (uint32_t i = 0; i < obj->GetNumFields(); ++i) { + if (obj->GetFieldAtIndex(i)->m_name == ConstString(name)) { + child_indexes.push_back(i + index_offset); + return child_indexes.size(); + } } - return CompilerType(this, it->second.get()); + } else if (JavaReferenceType *ref = llvm::dyn_cast<JavaReferenceType>( + static_cast<JavaType *>(type))) { + return GetIndexOfChildMemberWithName( + ref->GetPointeeType().GetOpaqueQualType(), name, + omit_empty_base_classes, child_indexes); + } + return 0; } CompilerType -JavaASTContext::CreateArrayType(const ConstString &linkage_name, const CompilerType &element_type, - const DWARFExpression &length_expression, const lldb::addr_t data_offset) -{ - ConstString name = element_type.GetTypeName(); - auto it = m_array_type_map.find(name); - if (it == m_array_type_map.end()) - { - std::unique_ptr<JavaType> array_type(new JavaArrayType(linkage_name, element_type, length_expression, - data_offset)); - it = m_array_type_map.emplace(name, std::move(array_type)).first; - } +JavaASTContext::GetLValueReferenceType(lldb::opaque_compiler_type_t type) { + return CreateReferenceType(CompilerType(this, type)); +} + +ConstString JavaASTContext::DeclContextGetScopeQualifiedName( + lldb::opaque_compiler_type_t opaque_decl_ctx) { + return GetTypeName(opaque_decl_ctx); +} + +static void AddPrimitiveType(JavaASTContext::JavaTypeMap &type_map, + JavaPrimitiveType::TypeKind type_kind) { + JavaPrimitiveType *type = new JavaPrimitiveType(type_kind); + type_map.emplace(type->GetName(), + std::unique_ptr<JavaASTContext::JavaType>(type)); +} + +CompilerType JavaASTContext::CreateBaseType(const ConstString &name) { + if (m_base_type_map.empty()) { + AddPrimitiveType(m_base_type_map, JavaPrimitiveType::eTypeByte); + AddPrimitiveType(m_base_type_map, JavaPrimitiveType::eTypeShort); + AddPrimitiveType(m_base_type_map, JavaPrimitiveType::eTypeInt); + AddPrimitiveType(m_base_type_map, JavaPrimitiveType::eTypeLong); + AddPrimitiveType(m_base_type_map, JavaPrimitiveType::eTypeFloat); + AddPrimitiveType(m_base_type_map, JavaPrimitiveType::eTypeDouble); + AddPrimitiveType(m_base_type_map, JavaPrimitiveType::eTypeBoolean); + AddPrimitiveType(m_base_type_map, JavaPrimitiveType::eTypeChar); + } + auto it = m_base_type_map.find(name); + if (it != m_base_type_map.end()) return CompilerType(this, it->second.get()); + return CompilerType(); +} + +CompilerType JavaASTContext::CreateObjectType(const ConstString &name, + const ConstString &linkage_name, + uint32_t byte_size) { + auto it = m_object_type_map.find(name); + if (it == m_object_type_map.end()) { + std::unique_ptr<JavaType> object_type( + new JavaObjectType(name, linkage_name, byte_size)); + it = m_object_type_map.emplace(name, std::move(object_type)).first; + } + return CompilerType(this, it->second.get()); +} + +CompilerType JavaASTContext::CreateArrayType( + const ConstString &linkage_name, const CompilerType &element_type, + const DWARFExpression &length_expression, const lldb::addr_t data_offset) { + ConstString name = element_type.GetTypeName(); + auto it = m_array_type_map.find(name); + if (it == m_array_type_map.end()) { + std::unique_ptr<JavaType> array_type(new JavaArrayType( + linkage_name, element_type, length_expression, data_offset)); + it = m_array_type_map.emplace(name, std::move(array_type)).first; + } + return CompilerType(this, it->second.get()); } CompilerType -JavaASTContext::CreateReferenceType(const CompilerType &pointee_type) -{ - ConstString name = pointee_type.GetTypeName(); - auto it = m_reference_type_map.find(name); - if (it == m_reference_type_map.end()) - it = m_reference_type_map.emplace(name, std::unique_ptr<JavaType>(new JavaReferenceType(pointee_type))).first; - return CompilerType(this, it->second.get()); -} - -void -JavaASTContext::CompleteObjectType(const CompilerType &object_type) -{ - JavaObjectType *obj = llvm::dyn_cast<JavaObjectType>(static_cast<JavaType *>(object_type.GetOpaqueQualType())); - assert(obj && "JavaASTContext::CompleteObjectType called with not a JavaObjectType"); - obj->SetCompleteType(true); -} - -void -JavaASTContext::AddBaseClassToObject(const CompilerType &object_type, const CompilerType &member_type, - uint32_t member_offset) -{ - JavaObjectType *obj = llvm::dyn_cast<JavaObjectType>(static_cast<JavaType *>(object_type.GetOpaqueQualType())); - assert(obj && "JavaASTContext::AddMemberToObject called with not a JavaObjectType"); - obj->AddBaseClass(member_type, member_offset); -} - -void -JavaASTContext::AddMemberToObject(const CompilerType &object_type, const ConstString &name, - const CompilerType &member_type, uint32_t member_offset) -{ - JavaObjectType *obj = llvm::dyn_cast<JavaObjectType>(static_cast<JavaType *>(object_type.GetOpaqueQualType())); - assert(obj && "JavaASTContext::AddMemberToObject called with not a JavaObjectType"); - obj->AddField(name, member_type, member_offset); -} - -void -JavaASTContext::SetDynamicTypeId(const CompilerType &type, const DWARFExpression &type_id) -{ - JavaObjectType *obj = llvm::dyn_cast<JavaObjectType>(static_cast<JavaType *>(type.GetOpaqueQualType())); - assert(obj && "JavaASTContext::SetDynamicTypeId called with not a JavaObjectType"); - obj->SetDynamicTypeId(type_id); -} - -uint64_t -JavaASTContext::CalculateDynamicTypeId(ExecutionContext *exe_ctx, const CompilerType &type, ValueObject &in_value) -{ - if (JavaObjectType *obj = llvm::dyn_cast<JavaObjectType>(static_cast<JavaType *>(type.GetOpaqueQualType()))) - return obj->CalculateDynamicTypeId(exe_ctx, in_value); - if (JavaArrayType *arr = llvm::dyn_cast<JavaArrayType>(static_cast<JavaType *>(type.GetOpaqueQualType()))) - return arr->CalculateDynamicTypeId(exe_ctx, in_value); - return UINT64_MAX; -} - -uint32_t -JavaASTContext::CalculateArraySize(const CompilerType &type, ValueObject &in_value) -{ - if (JavaArrayType *arr = llvm::dyn_cast<JavaArrayType>(static_cast<JavaType *>(type.GetOpaqueQualType()))) - return arr->GetNumElements(&in_value); - return UINT32_MAX; -} - -uint64_t -JavaASTContext::CalculateArrayElementOffset(const CompilerType &type, size_t index) -{ - if (JavaArrayType *arr = llvm::dyn_cast<JavaArrayType>(static_cast<JavaType *>(type.GetOpaqueQualType()))) - return arr->GetElementOffset(index); - return UINT64_MAX; -} - -ConstString -JavaASTContext::GetLinkageName(const CompilerType &type) -{ - if (JavaObjectType *obj = llvm::dyn_cast<JavaObjectType>(static_cast<JavaType *>(type.GetOpaqueQualType()))) - return obj->GetLinkageName(); - return ConstString(); +JavaASTContext::CreateReferenceType(const CompilerType &pointee_type) { + ConstString name = pointee_type.GetTypeName(); + auto it = m_reference_type_map.find(name); + if (it == m_reference_type_map.end()) + it = m_reference_type_map + .emplace(name, std::unique_ptr<JavaType>( + new JavaReferenceType(pointee_type))) + .first; + return CompilerType(this, it->second.get()); +} + +void JavaASTContext::CompleteObjectType(const CompilerType &object_type) { + JavaObjectType *obj = llvm::dyn_cast<JavaObjectType>( + static_cast<JavaType *>(object_type.GetOpaqueQualType())); + assert(obj && + "JavaASTContext::CompleteObjectType called with not a JavaObjectType"); + obj->SetCompleteType(true); +} + +void JavaASTContext::AddBaseClassToObject(const CompilerType &object_type, + const CompilerType &member_type, + uint32_t member_offset) { + JavaObjectType *obj = llvm::dyn_cast<JavaObjectType>( + static_cast<JavaType *>(object_type.GetOpaqueQualType())); + assert(obj && + "JavaASTContext::AddMemberToObject called with not a JavaObjectType"); + obj->AddBaseClass(member_type, member_offset); +} + +void JavaASTContext::AddMemberToObject(const CompilerType &object_type, + const ConstString &name, + const CompilerType &member_type, + uint32_t member_offset) { + JavaObjectType *obj = llvm::dyn_cast<JavaObjectType>( + static_cast<JavaType *>(object_type.GetOpaqueQualType())); + assert(obj && + "JavaASTContext::AddMemberToObject called with not a JavaObjectType"); + obj->AddField(name, member_type, member_offset); +} + +void JavaASTContext::SetDynamicTypeId(const CompilerType &type, + const DWARFExpression &type_id) { + JavaObjectType *obj = llvm::dyn_cast<JavaObjectType>( + static_cast<JavaType *>(type.GetOpaqueQualType())); + assert(obj && + "JavaASTContext::SetDynamicTypeId called with not a JavaObjectType"); + obj->SetDynamicTypeId(type_id); +} + +uint64_t JavaASTContext::CalculateDynamicTypeId(ExecutionContext *exe_ctx, + const CompilerType &type, + ValueObject &in_value) { + if (JavaObjectType *obj = llvm::dyn_cast<JavaObjectType>( + static_cast<JavaType *>(type.GetOpaqueQualType()))) + return obj->CalculateDynamicTypeId(exe_ctx, in_value); + if (JavaArrayType *arr = llvm::dyn_cast<JavaArrayType>( + static_cast<JavaType *>(type.GetOpaqueQualType()))) + return arr->CalculateDynamicTypeId(exe_ctx, in_value); + return UINT64_MAX; +} + +uint32_t JavaASTContext::CalculateArraySize(const CompilerType &type, + ValueObject &in_value) { + if (JavaArrayType *arr = llvm::dyn_cast<JavaArrayType>( + static_cast<JavaType *>(type.GetOpaqueQualType()))) + return arr->GetNumElements(&in_value); + return UINT32_MAX; +} + +uint64_t JavaASTContext::CalculateArrayElementOffset(const CompilerType &type, + size_t index) { + if (JavaArrayType *arr = llvm::dyn_cast<JavaArrayType>( + static_cast<JavaType *>(type.GetOpaqueQualType()))) + return arr->GetElementOffset(index); + return UINT64_MAX; +} + +ConstString JavaASTContext::GetLinkageName(const CompilerType &type) { + if (JavaObjectType *obj = llvm::dyn_cast<JavaObjectType>( + static_cast<JavaType *>(type.GetOpaqueQualType()))) + return obj->GetLinkageName(); + return ConstString(); } diff --git a/lldb/source/Symbol/LineEntry.cpp b/lldb/source/Symbol/LineEntry.cpp index 9b3a043f6ca..691afdf5ed0 100644 --- a/lldb/source/Symbol/LineEntry.cpp +++ b/lldb/source/Symbol/LineEntry.cpp @@ -14,286 +14,229 @@ using namespace lldb_private; -LineEntry::LineEntry() : - range(), - file(), - line(LLDB_INVALID_LINE_NUMBER), - column(0), - is_start_of_statement(0), - is_start_of_basic_block(0), - is_prologue_end(0), - is_epilogue_begin(0), - is_terminal_entry(0) -{ +LineEntry::LineEntry() + : range(), file(), line(LLDB_INVALID_LINE_NUMBER), column(0), + is_start_of_statement(0), is_start_of_basic_block(0), is_prologue_end(0), + is_epilogue_begin(0), is_terminal_entry(0) {} + +LineEntry::LineEntry(const lldb::SectionSP §ion_sp, + lldb::addr_t section_offset, lldb::addr_t byte_size, + const FileSpec &_file, uint32_t _line, uint16_t _column, + bool _is_start_of_statement, bool _is_start_of_basic_block, + bool _is_prologue_end, bool _is_epilogue_begin, + bool _is_terminal_entry) + : range(section_sp, section_offset, byte_size), file(_file), + original_file(_file), line(_line), column(_column), + is_start_of_statement(_is_start_of_statement), + is_start_of_basic_block(_is_start_of_basic_block), + is_prologue_end(_is_prologue_end), is_epilogue_begin(_is_epilogue_begin), + is_terminal_entry(_is_terminal_entry) {} + +void LineEntry::Clear() { + range.Clear(); + file.Clear(); + original_file.Clear(); + line = LLDB_INVALID_LINE_NUMBER; + column = 0; + is_start_of_statement = 0; + is_start_of_basic_block = 0; + is_prologue_end = 0; + is_epilogue_begin = 0; + is_terminal_entry = 0; } -LineEntry::LineEntry -( - const lldb::SectionSP §ion_sp, - lldb::addr_t section_offset, - lldb::addr_t byte_size, - const FileSpec &_file, - uint32_t _line, - uint16_t _column, - bool _is_start_of_statement, - bool _is_start_of_basic_block, - bool _is_prologue_end, - bool _is_epilogue_begin, - bool _is_terminal_entry -) : - range(section_sp, section_offset, byte_size), - file(_file), - original_file(_file), - line(_line), - column(_column), - is_start_of_statement(_is_start_of_statement), - is_start_of_basic_block(_is_start_of_basic_block), - is_prologue_end(_is_prologue_end), - is_epilogue_begin(_is_epilogue_begin), - is_terminal_entry(_is_terminal_entry) -{ +bool LineEntry::IsValid() const { + return range.GetBaseAddress().IsValid() && line != LLDB_INVALID_LINE_NUMBER; } -void -LineEntry::Clear() -{ - range.Clear(); - file.Clear(); - original_file.Clear(); - line = LLDB_INVALID_LINE_NUMBER; - column = 0; - is_start_of_statement = 0; - is_start_of_basic_block = 0; - is_prologue_end = 0; - is_epilogue_begin = 0; - is_terminal_entry = 0; -} +bool LineEntry::DumpStopContext(Stream *s, bool show_fullpaths) const { + bool result = false; + if (file) { + if (show_fullpaths) + file.Dump(s); + else + file.GetFilename().Dump(s); + if (line) + s->PutChar(':'); + result = true; + } + if (line) + s->Printf("%u", line); + else + result = false; + + return result; +} -bool -LineEntry::IsValid() const -{ - return range.GetBaseAddress().IsValid() && line != LLDB_INVALID_LINE_NUMBER; +bool LineEntry::Dump(Stream *s, Target *target, bool show_file, + Address::DumpStyle style, + Address::DumpStyle fallback_style, bool show_range) const { + if (show_range) { + // Show address range + if (!range.Dump(s, target, style, fallback_style)) + return false; + } else { + // Show address only + if (!range.GetBaseAddress().Dump(s, target, style, fallback_style)) + return false; + } + if (show_file) + *s << ", file = " << file; + if (line) + s->Printf(", line = %u", line); + if (column) + s->Printf(", column = %u", column); + if (is_start_of_statement) + *s << ", is_start_of_statement = TRUE"; + + if (is_start_of_basic_block) + *s << ", is_start_of_basic_block = TRUE"; + + if (is_prologue_end) + *s << ", is_prologue_end = TRUE"; + + if (is_epilogue_begin) + *s << ", is_epilogue_begin = TRUE"; + + if (is_terminal_entry) + *s << ", is_terminal_entry = TRUE"; + return true; } -bool -LineEntry::DumpStopContext(Stream *s, bool show_fullpaths) const -{ - bool result = false; - if (file) - { - if (show_fullpaths) - file.Dump (s); - else - file.GetFilename().Dump (s); - - if (line) - s->PutChar(':'); - result = true; +bool LineEntry::GetDescription(Stream *s, lldb::DescriptionLevel level, + CompileUnit *cu, Target *target, + bool show_address_only) const { + + if (level == lldb::eDescriptionLevelBrief || + level == lldb::eDescriptionLevelFull) { + if (show_address_only) { + range.GetBaseAddress().Dump(s, target, Address::DumpStyleLoadAddress, + Address::DumpStyleFileAddress); + } else { + range.Dump(s, target, Address::DumpStyleLoadAddress, + Address::DumpStyleFileAddress); } - if (line) - s->Printf ("%u", line); - else - result = false; - return result; -} + *s << ": " << file; -bool -LineEntry::Dump -( - Stream *s, - Target *target, - bool show_file, - Address::DumpStyle style, - Address::DumpStyle fallback_style, - bool show_range -) const -{ - if (show_range) - { - // Show address range - if (!range.Dump(s, target, style, fallback_style)) - return false; - } - else - { - // Show address only - if (!range.GetBaseAddress().Dump(s, - target, - style, - fallback_style)) - return false; + if (line) { + s->Printf(":%u", line); + if (column) + s->Printf(":%u", column); } - if (show_file) - *s << ", file = " << file; - if (line) - s->Printf(", line = %u", line); - if (column) - s->Printf(", column = %u", column); - if (is_start_of_statement) + + if (level == lldb::eDescriptionLevelFull) { + if (is_start_of_statement) *s << ", is_start_of_statement = TRUE"; - if (is_start_of_basic_block) + if (is_start_of_basic_block) *s << ", is_start_of_basic_block = TRUE"; - if (is_prologue_end) + if (is_prologue_end) *s << ", is_prologue_end = TRUE"; - if (is_epilogue_begin) + if (is_epilogue_begin) *s << ", is_epilogue_begin = TRUE"; - if (is_terminal_entry) + if (is_terminal_entry) *s << ", is_terminal_entry = TRUE"; - return true; -} - -bool -LineEntry::GetDescription (Stream *s, lldb::DescriptionLevel level, CompileUnit* cu, Target *target, bool show_address_only) const -{ - - if (level == lldb::eDescriptionLevelBrief || level == lldb::eDescriptionLevelFull) - { - if (show_address_only) - { - range.GetBaseAddress().Dump(s, target, Address::DumpStyleLoadAddress, Address::DumpStyleFileAddress); - } - else - { - range.Dump(s, target, Address::DumpStyleLoadAddress, Address::DumpStyleFileAddress); - } - - *s << ": " << file; - - if (line) - { - s->Printf(":%u", line); - if (column) - s->Printf(":%u", column); - } - - - if (level == lldb::eDescriptionLevelFull) - { - if (is_start_of_statement) - *s << ", is_start_of_statement = TRUE"; - - if (is_start_of_basic_block) - *s << ", is_start_of_basic_block = TRUE"; - - if (is_prologue_end) - *s << ", is_prologue_end = TRUE"; - - if (is_epilogue_begin) - *s << ", is_epilogue_begin = TRUE"; - - if (is_terminal_entry) - *s << ", is_terminal_entry = TRUE"; - } - else - { - if (is_terminal_entry) - s->EOL(); - } - } - else - { - return Dump (s, target, true, Address::DumpStyleLoadAddress, Address::DumpStyleModuleWithFileAddress, true); + } else { + if (is_terminal_entry) + s->EOL(); } - return true; + } else { + return Dump(s, target, true, Address::DumpStyleLoadAddress, + Address::DumpStyleModuleWithFileAddress, true); + } + return true; } - -bool -lldb_private::operator< (const LineEntry& a, const LineEntry& b) -{ - return LineEntry::Compare (a, b) < 0; +bool lldb_private::operator<(const LineEntry &a, const LineEntry &b) { + return LineEntry::Compare(a, b) < 0; } -int -LineEntry::Compare (const LineEntry& a, const LineEntry& b) -{ - int result = Address::CompareFileAddress (a.range.GetBaseAddress(), b.range.GetBaseAddress()); - if (result != 0) - return result; - - const lldb::addr_t a_byte_size = a.range.GetByteSize(); - const lldb::addr_t b_byte_size = b.range.GetByteSize(); - - if (a_byte_size < b_byte_size) - return -1; - if (a_byte_size > b_byte_size) - return +1; - - // Check for an end sequence entry mismatch after we have determined - // that the address values are equal. If one of the items is an end - // sequence, we don't care about the line, file, or column info. - if (a.is_terminal_entry > b.is_terminal_entry) - return -1; - if (a.is_terminal_entry < b.is_terminal_entry) - return +1; - - if (a.line < b.line) - return -1; - if (a.line > b.line) - return +1; - - if (a.column < b.column) - return -1; - if (a.column > b.column) - return +1; - - return FileSpec::Compare (a.file, b.file, true); +int LineEntry::Compare(const LineEntry &a, const LineEntry &b) { + int result = Address::CompareFileAddress(a.range.GetBaseAddress(), + b.range.GetBaseAddress()); + if (result != 0) + return result; + + const lldb::addr_t a_byte_size = a.range.GetByteSize(); + const lldb::addr_t b_byte_size = b.range.GetByteSize(); + + if (a_byte_size < b_byte_size) + return -1; + if (a_byte_size > b_byte_size) + return +1; + + // Check for an end sequence entry mismatch after we have determined + // that the address values are equal. If one of the items is an end + // sequence, we don't care about the line, file, or column info. + if (a.is_terminal_entry > b.is_terminal_entry) + return -1; + if (a.is_terminal_entry < b.is_terminal_entry) + return +1; + + if (a.line < b.line) + return -1; + if (a.line > b.line) + return +1; + + if (a.column < b.column) + return -1; + if (a.column > b.column) + return +1; + + return FileSpec::Compare(a.file, b.file, true); } -AddressRange -LineEntry::GetSameLineContiguousAddressRange () const -{ - // Add each LineEntry's range to complete_line_range until we find - // a different file / line number. - AddressRange complete_line_range = range; - - while (true) - { - SymbolContext next_line_sc; - Address range_end (complete_line_range.GetBaseAddress()); - range_end.Slide (complete_line_range.GetByteSize()); - range_end.CalculateSymbolContext (&next_line_sc, lldb::eSymbolContextLineEntry); - - if (next_line_sc.line_entry.IsValid() - && next_line_sc.line_entry.range.GetByteSize() > 0 - && original_file == next_line_sc.line_entry.original_file) - { - // Include any line 0 entries - they indicate that this is compiler-generated code - // that does not correspond to user source code. - if (next_line_sc.line_entry.line == 0) - { - complete_line_range.SetByteSize (complete_line_range.GetByteSize() + next_line_sc.line_entry.range.GetByteSize()); - continue; - } - - if (line == next_line_sc.line_entry.line) - { - // next_line_sc is the same file & line as this LineEntry, so extend our - // AddressRange by its size and continue to see if there are more LineEntries - // that we can combine. - complete_line_range.SetByteSize (complete_line_range.GetByteSize() + next_line_sc.line_entry.range.GetByteSize()); - continue; - } - } - break; +AddressRange LineEntry::GetSameLineContiguousAddressRange() const { + // Add each LineEntry's range to complete_line_range until we find + // a different file / line number. + AddressRange complete_line_range = range; + + while (true) { + SymbolContext next_line_sc; + Address range_end(complete_line_range.GetBaseAddress()); + range_end.Slide(complete_line_range.GetByteSize()); + range_end.CalculateSymbolContext(&next_line_sc, + lldb::eSymbolContextLineEntry); + + if (next_line_sc.line_entry.IsValid() && + next_line_sc.line_entry.range.GetByteSize() > 0 && + original_file == next_line_sc.line_entry.original_file) { + // Include any line 0 entries - they indicate that this is + // compiler-generated code + // that does not correspond to user source code. + if (next_line_sc.line_entry.line == 0) { + complete_line_range.SetByteSize( + complete_line_range.GetByteSize() + + next_line_sc.line_entry.range.GetByteSize()); + continue; + } + + if (line == next_line_sc.line_entry.line) { + // next_line_sc is the same file & line as this LineEntry, so extend our + // AddressRange by its size and continue to see if there are more + // LineEntries + // that we can combine. + complete_line_range.SetByteSize( + complete_line_range.GetByteSize() + + next_line_sc.line_entry.range.GetByteSize()); + continue; + } } - return complete_line_range; + break; + } + return complete_line_range; } -void -LineEntry::ApplyFileMappings(lldb::TargetSP target_sp) -{ - if (target_sp) - { - // Apply any file remappings to our file - FileSpec new_file_spec; - if (target_sp->GetSourcePathMap().FindFile(original_file, new_file_spec)) - file = new_file_spec; - } +void LineEntry::ApplyFileMappings(lldb::TargetSP target_sp) { + if (target_sp) { + // Apply any file remappings to our file + FileSpec new_file_spec; + if (target_sp->GetSourcePathMap().FindFile(original_file, new_file_spec)) + file = new_file_spec; + } } diff --git a/lldb/source/Symbol/LineTable.cpp b/lldb/source/Symbol/LineTable.cpp index 6b4dea773d1..02ab0c12611 100644 --- a/lldb/source/Symbol/LineTable.cpp +++ b/lldb/source/Symbol/LineTable.cpp @@ -7,12 +7,12 @@ // //===----------------------------------------------------------------------===// +#include "lldb/Symbol/LineTable.h" #include "lldb/Core/Address.h" #include "lldb/Core/Module.h" #include "lldb/Core/Section.h" #include "lldb/Core/Stream.h" #include "lldb/Symbol/CompileUnit.h" -#include "lldb/Symbol/LineTable.h" #include <algorithm> using namespace lldb; @@ -21,594 +21,522 @@ using namespace lldb_private; //---------------------------------------------------------------------- // LineTable constructor //---------------------------------------------------------------------- -LineTable::LineTable(CompileUnit* comp_unit) : - m_comp_unit(comp_unit), - m_entries() -{ -} +LineTable::LineTable(CompileUnit *comp_unit) + : m_comp_unit(comp_unit), m_entries() {} //---------------------------------------------------------------------- // Destructor //---------------------------------------------------------------------- -LineTable::~LineTable() -{ +LineTable::~LineTable() {} + +void LineTable::InsertLineEntry(lldb::addr_t file_addr, uint32_t line, + uint16_t column, uint16_t file_idx, + bool is_start_of_statement, + bool is_start_of_basic_block, + bool is_prologue_end, bool is_epilogue_begin, + bool is_terminal_entry) { + Entry entry(file_addr, line, column, file_idx, is_start_of_statement, + is_start_of_basic_block, is_prologue_end, is_epilogue_begin, + is_terminal_entry); + + entry_collection::iterator begin_pos = m_entries.begin(); + entry_collection::iterator end_pos = m_entries.end(); + LineTable::Entry::LessThanBinaryPredicate less_than_bp(this); + entry_collection::iterator pos = + upper_bound(begin_pos, end_pos, entry, less_than_bp); + + // Stream s(stdout); + // s << "\n\nBefore:\n"; + // Dump (&s, Address::DumpStyleFileAddress); + m_entries.insert(pos, entry); + // s << "After:\n"; + // Dump (&s, Address::DumpStyleFileAddress); } -void -LineTable::InsertLineEntry -( - lldb::addr_t file_addr, - uint32_t line, - uint16_t column, - uint16_t file_idx, - bool is_start_of_statement, - bool is_start_of_basic_block, - bool is_prologue_end, - bool is_epilogue_begin, - bool is_terminal_entry -) -{ - Entry entry(file_addr, line, column, file_idx, is_start_of_statement, is_start_of_basic_block, is_prologue_end, is_epilogue_begin, is_terminal_entry); - - entry_collection::iterator begin_pos = m_entries.begin(); - entry_collection::iterator end_pos = m_entries.end(); - LineTable::Entry::LessThanBinaryPredicate less_than_bp(this); - entry_collection::iterator pos = upper_bound(begin_pos, end_pos, entry, less_than_bp); - -// Stream s(stdout); -// s << "\n\nBefore:\n"; -// Dump (&s, Address::DumpStyleFileAddress); - m_entries.insert(pos, entry); -// s << "After:\n"; -// Dump (&s, Address::DumpStyleFileAddress); -} +LineSequence::LineSequence() {} -LineSequence::LineSequence() -{ -} +void LineTable::LineSequenceImpl::Clear() { m_entries.clear(); } -void -LineTable::LineSequenceImpl::Clear() -{ - m_entries.clear(); +LineSequence *LineTable::CreateLineSequenceContainer() { + return new LineTable::LineSequenceImpl(); } -LineSequence* LineTable::CreateLineSequenceContainer () -{ - return new LineTable::LineSequenceImpl(); +void LineTable::AppendLineEntryToSequence( + LineSequence *sequence, lldb::addr_t file_addr, uint32_t line, + uint16_t column, uint16_t file_idx, bool is_start_of_statement, + bool is_start_of_basic_block, bool is_prologue_end, bool is_epilogue_begin, + bool is_terminal_entry) { + assert(sequence != nullptr); + LineSequenceImpl *seq = reinterpret_cast<LineSequenceImpl *>(sequence); + Entry entry(file_addr, line, column, file_idx, is_start_of_statement, + is_start_of_basic_block, is_prologue_end, is_epilogue_begin, + is_terminal_entry); + entry_collection &entries = seq->m_entries; + // Replace the last entry if the address is the same, otherwise append it. If + // we have multiple + // line entries at the same address, this indicates illegal DWARF so this + // "fixes" the line table + // to be correct. If not fixed this can cause a line entry's address that when + // resolved back to + // a symbol context, could resolve to a different line entry. We really want a + // 1 to 1 mapping + // here to avoid these kinds of inconsistencies. We will need tor revisit this + // if the DWARF line + // tables are updated to allow multiple entries at the same address legally. + if (!entries.empty() && entries.back().file_addr == file_addr) { + // GCC don't use the is_prologue_end flag to mark the first instruction + // after the prologue. + // Instead of it it is issuing a line table entry for the first instruction + // of the prologue + // and one for the first instruction after the prologue. If the size of the + // prologue is 0 + // instruction then the 2 line entry will have the same file address. + // Removing it will remove + // our ability to properly detect the location of the end of prologe so we + // set the prologue_end + // flag to preserve this information (setting the prologue_end flag for an + // entry what is after + // the prologue end don't have any effect) + entry.is_prologue_end = entry.file_idx == entries.back().file_idx; + entries.back() = entry; + } else + entries.push_back(entry); } -void -LineTable::AppendLineEntryToSequence -( - LineSequence* sequence, - lldb::addr_t file_addr, - uint32_t line, - uint16_t column, - uint16_t file_idx, - bool is_start_of_statement, - bool is_start_of_basic_block, - bool is_prologue_end, - bool is_epilogue_begin, - bool is_terminal_entry -) -{ - assert(sequence != nullptr); - LineSequenceImpl* seq = reinterpret_cast<LineSequenceImpl*>(sequence); - Entry entry(file_addr, line, column, file_idx, is_start_of_statement, is_start_of_basic_block, is_prologue_end, is_epilogue_begin, is_terminal_entry); - entry_collection &entries = seq->m_entries; - // Replace the last entry if the address is the same, otherwise append it. If we have multiple - // line entries at the same address, this indicates illegal DWARF so this "fixes" the line table - // to be correct. If not fixed this can cause a line entry's address that when resolved back to - // a symbol context, could resolve to a different line entry. We really want a 1 to 1 mapping - // here to avoid these kinds of inconsistencies. We will need tor revisit this if the DWARF line - // tables are updated to allow multiple entries at the same address legally. - if (!entries.empty() && entries.back().file_addr == file_addr) - { - // GCC don't use the is_prologue_end flag to mark the first instruction after the prologue. - // Instead of it it is issuing a line table entry for the first instruction of the prologue - // and one for the first instruction after the prologue. If the size of the prologue is 0 - // instruction then the 2 line entry will have the same file address. Removing it will remove - // our ability to properly detect the location of the end of prologe so we set the prologue_end - // flag to preserve this information (setting the prologue_end flag for an entry what is after - // the prologue end don't have any effect) - entry.is_prologue_end = entry.file_idx == entries.back().file_idx; - entries.back() = entry; - } - else - entries.push_back (entry); -} - -void -LineTable::InsertSequence (LineSequence* sequence) -{ - assert(sequence != nullptr); - LineSequenceImpl* seq = reinterpret_cast<LineSequenceImpl*>(sequence); - if (seq->m_entries.empty()) - return; - Entry& entry = seq->m_entries.front(); - - // If the first entry address in this sequence is greater than or equal to - // the address of the last item in our entry collection, just append. - if (m_entries.empty() || !Entry::EntryAddressLessThan(entry, m_entries.back())) - { - m_entries.insert(m_entries.end(), - seq->m_entries.begin(), - seq->m_entries.end()); - return; - } - - // Otherwise, find where this belongs in the collection - entry_collection::iterator begin_pos = m_entries.begin(); - entry_collection::iterator end_pos = m_entries.end(); - LineTable::Entry::LessThanBinaryPredicate less_than_bp(this); - entry_collection::iterator pos = upper_bound(begin_pos, end_pos, entry, less_than_bp); - - // We should never insert a sequence in the middle of another sequence - if (pos != begin_pos) { - while (pos < end_pos && !((pos - 1)->is_terminal_entry)) - pos++; - } +void LineTable::InsertSequence(LineSequence *sequence) { + assert(sequence != nullptr); + LineSequenceImpl *seq = reinterpret_cast<LineSequenceImpl *>(sequence); + if (seq->m_entries.empty()) + return; + Entry &entry = seq->m_entries.front(); + + // If the first entry address in this sequence is greater than or equal to + // the address of the last item in our entry collection, just append. + if (m_entries.empty() || + !Entry::EntryAddressLessThan(entry, m_entries.back())) { + m_entries.insert(m_entries.end(), seq->m_entries.begin(), + seq->m_entries.end()); + return; + } + + // Otherwise, find where this belongs in the collection + entry_collection::iterator begin_pos = m_entries.begin(); + entry_collection::iterator end_pos = m_entries.end(); + LineTable::Entry::LessThanBinaryPredicate less_than_bp(this); + entry_collection::iterator pos = + upper_bound(begin_pos, end_pos, entry, less_than_bp); + + // We should never insert a sequence in the middle of another sequence + if (pos != begin_pos) { + while (pos < end_pos && !((pos - 1)->is_terminal_entry)) + pos++; + } #ifdef LLDB_CONFIGURATION_DEBUG - // If we aren't inserting at the beginning, the previous entry should - // terminate a sequence. - if (pos != begin_pos) - { - entry_collection::iterator prev_pos = pos - 1; - assert(prev_pos->is_terminal_entry); - } + // If we aren't inserting at the beginning, the previous entry should + // terminate a sequence. + if (pos != begin_pos) { + entry_collection::iterator prev_pos = pos - 1; + assert(prev_pos->is_terminal_entry); + } #endif - m_entries.insert(pos, seq->m_entries.begin(), seq->m_entries.end()); + m_entries.insert(pos, seq->m_entries.begin(), seq->m_entries.end()); } //---------------------------------------------------------------------- -LineTable::Entry::LessThanBinaryPredicate::LessThanBinaryPredicate(LineTable *line_table) : - m_line_table (line_table) -{ -} - -bool -LineTable::Entry::LessThanBinaryPredicate::operator() (const LineTable::Entry& a, const LineTable::Entry& b) const -{ - #define LT_COMPARE(a,b) if (a != b) return a < b - LT_COMPARE (a.file_addr, b.file_addr); - // b and a reversed on purpose below. - LT_COMPARE (b.is_terminal_entry, a.is_terminal_entry); - LT_COMPARE (a.line, b.line); - LT_COMPARE (a.column, b.column); - LT_COMPARE (a.is_start_of_statement, b.is_start_of_statement); - LT_COMPARE (a.is_start_of_basic_block, b.is_start_of_basic_block); - // b and a reversed on purpose below. - LT_COMPARE (b.is_prologue_end, a.is_prologue_end); - LT_COMPARE (a.is_epilogue_begin, b.is_epilogue_begin); - LT_COMPARE (a.file_idx, b.file_idx); - return false; - #undef LT_COMPARE +LineTable::Entry::LessThanBinaryPredicate::LessThanBinaryPredicate( + LineTable *line_table) + : m_line_table(line_table) {} + +bool LineTable::Entry::LessThanBinaryPredicate:: +operator()(const LineTable::Entry &a, const LineTable::Entry &b) const { +#define LT_COMPARE(a, b) \ + if (a != b) \ + return a < b + LT_COMPARE(a.file_addr, b.file_addr); + // b and a reversed on purpose below. + LT_COMPARE(b.is_terminal_entry, a.is_terminal_entry); + LT_COMPARE(a.line, b.line); + LT_COMPARE(a.column, b.column); + LT_COMPARE(a.is_start_of_statement, b.is_start_of_statement); + LT_COMPARE(a.is_start_of_basic_block, b.is_start_of_basic_block); + // b and a reversed on purpose below. + LT_COMPARE(b.is_prologue_end, a.is_prologue_end); + LT_COMPARE(a.is_epilogue_begin, b.is_epilogue_begin); + LT_COMPARE(a.file_idx, b.file_idx); + return false; +#undef LT_COMPARE } +uint32_t LineTable::GetSize() const { return m_entries.size(); } - -uint32_t -LineTable::GetSize() const -{ - return m_entries.size(); +bool LineTable::GetLineEntryAtIndex(uint32_t idx, LineEntry &line_entry) { + if (idx < m_entries.size()) { + ConvertEntryAtIndexToLineEntry(idx, line_entry); + return true; + } + line_entry.Clear(); + return false; } -bool -LineTable::GetLineEntryAtIndex(uint32_t idx, LineEntry& line_entry) -{ - if (idx < m_entries.size()) - { - ConvertEntryAtIndexToLineEntry (idx, line_entry); - return true; - } - line_entry.Clear(); - return false; -} +bool LineTable::FindLineEntryByAddress(const Address &so_addr, + LineEntry &line_entry, + uint32_t *index_ptr) { + if (index_ptr != nullptr) + *index_ptr = UINT32_MAX; + + bool success = false; + + if (so_addr.GetModule().get() == m_comp_unit->GetModule().get()) { + Entry search_entry; + search_entry.file_addr = so_addr.GetFileAddress(); + if (search_entry.file_addr != LLDB_INVALID_ADDRESS) { + entry_collection::const_iterator begin_pos = m_entries.begin(); + entry_collection::const_iterator end_pos = m_entries.end(); + entry_collection::const_iterator pos = lower_bound( + begin_pos, end_pos, search_entry, Entry::EntryAddressLessThan); + if (pos != end_pos) { + if (pos != begin_pos) { + if (pos->file_addr != search_entry.file_addr) + --pos; + else if (pos->file_addr == search_entry.file_addr) { + // If this is a termination entry, it shouldn't match since + // entries with the "is_terminal_entry" member set to true + // are termination entries that define the range for the + // previous entry. + if (pos->is_terminal_entry) { + // The matching entry is a terminal entry, so we skip + // ahead to the next entry to see if there is another + // entry following this one whose section/offset matches. + ++pos; + if (pos != end_pos) { + if (pos->file_addr != search_entry.file_addr) + pos = end_pos; + } + } -bool -LineTable::FindLineEntryByAddress (const Address &so_addr, LineEntry& line_entry, uint32_t *index_ptr) -{ - if (index_ptr != nullptr ) - *index_ptr = UINT32_MAX; - - bool success = false; - - if (so_addr.GetModule().get() == m_comp_unit->GetModule().get()) - { - Entry search_entry; - search_entry.file_addr = so_addr.GetFileAddress(); - if (search_entry.file_addr != LLDB_INVALID_ADDRESS) - { - entry_collection::const_iterator begin_pos = m_entries.begin(); - entry_collection::const_iterator end_pos = m_entries.end(); - entry_collection::const_iterator pos = lower_bound(begin_pos, end_pos, search_entry, Entry::EntryAddressLessThan); - if (pos != end_pos) - { - if (pos != begin_pos) - { - if (pos->file_addr != search_entry.file_addr) - --pos; - else if (pos->file_addr == search_entry.file_addr) - { - // If this is a termination entry, it shouldn't match since - // entries with the "is_terminal_entry" member set to true - // are termination entries that define the range for the - // previous entry. - if (pos->is_terminal_entry) - { - // The matching entry is a terminal entry, so we skip - // ahead to the next entry to see if there is another - // entry following this one whose section/offset matches. - ++pos; - if (pos != end_pos) - { - if (pos->file_addr != search_entry.file_addr) - pos = end_pos; - } - } - - if (pos != end_pos) - { - // While in the same section/offset backup to find the first - // line entry that matches the address in case there are - // multiple - while (pos != begin_pos) - { - entry_collection::const_iterator prev_pos = pos - 1; - if (prev_pos->file_addr == search_entry.file_addr && - prev_pos->is_terminal_entry == false) - --pos; - else - break; - } - } - } - - } - - // Make sure we have a valid match and that the match isn't a terminating - // entry for a previous line... - if (pos != end_pos && pos->is_terminal_entry == false) - { - uint32_t match_idx = std::distance (begin_pos, pos); - success = ConvertEntryAtIndexToLineEntry(match_idx, line_entry); - if (index_ptr != nullptr && success) - *index_ptr = match_idx; - } + if (pos != end_pos) { + // While in the same section/offset backup to find the first + // line entry that matches the address in case there are + // multiple + while (pos != begin_pos) { + entry_collection::const_iterator prev_pos = pos - 1; + if (prev_pos->file_addr == search_entry.file_addr && + prev_pos->is_terminal_entry == false) + --pos; + else + break; + } } + } } - } - return success; -} - -bool -LineTable::ConvertEntryAtIndexToLineEntry (uint32_t idx, LineEntry &line_entry) -{ - if (idx < m_entries.size()) - { - const Entry& entry = m_entries[idx]; - ModuleSP module_sp (m_comp_unit->GetModule()); - if (module_sp && module_sp->ResolveFileAddress(entry.file_addr, line_entry.range.GetBaseAddress())) - { - if (!entry.is_terminal_entry && idx + 1 < m_entries.size()) - line_entry.range.SetByteSize(m_entries[idx+1].file_addr - entry.file_addr); - else - line_entry.range.SetByteSize(0); - - line_entry.file = m_comp_unit->GetSupportFiles().GetFileSpecAtIndex (entry.file_idx); - line_entry.original_file = m_comp_unit->GetSupportFiles().GetFileSpecAtIndex(entry.file_idx); - line_entry.line = entry.line; - line_entry.column = entry.column; - line_entry.is_start_of_statement = entry.is_start_of_statement; - line_entry.is_start_of_basic_block = entry.is_start_of_basic_block; - line_entry.is_prologue_end = entry.is_prologue_end; - line_entry.is_epilogue_begin = entry.is_epilogue_begin; - line_entry.is_terminal_entry = entry.is_terminal_entry; - return true; + // Make sure we have a valid match and that the match isn't a + // terminating + // entry for a previous line... + if (pos != end_pos && pos->is_terminal_entry == false) { + uint32_t match_idx = std::distance(begin_pos, pos); + success = ConvertEntryAtIndexToLineEntry(match_idx, line_entry); + if (index_ptr != nullptr && success) + *index_ptr = match_idx; } + } } - return false; + } + return success; } -uint32_t -LineTable::FindLineEntryIndexByFileIndex -( - uint32_t start_idx, - const std::vector<uint32_t> &file_indexes, - uint32_t line, - bool exact, - LineEntry* line_entry_ptr -) -{ - - const size_t count = m_entries.size(); - std::vector<uint32_t>::const_iterator begin_pos = file_indexes.begin(); - std::vector<uint32_t>::const_iterator end_pos = file_indexes.end(); - size_t best_match = UINT32_MAX; - - for (size_t idx = start_idx; idx < count; ++idx) - { - // Skip line table rows that terminate the previous row (is_terminal_entry is non-zero) - if (m_entries[idx].is_terminal_entry) - continue; - - if (find (begin_pos, end_pos, m_entries[idx].file_idx) == end_pos) - continue; - - // Exact match always wins. Otherwise try to find the closest line > the desired - // line. - // FIXME: Maybe want to find the line closest before and the line closest after and - // if they're not in the same function, don't return a match. - - if (m_entries[idx].line < line) - { - continue; - } - else if (m_entries[idx].line == line) - { - if (line_entry_ptr) - ConvertEntryAtIndexToLineEntry (idx, *line_entry_ptr); - return idx; - } - else if (!exact) - { - if (best_match == UINT32_MAX) - best_match = idx; - else if (m_entries[idx].line < m_entries[best_match].line) - best_match = idx; - } +bool LineTable::ConvertEntryAtIndexToLineEntry(uint32_t idx, + LineEntry &line_entry) { + if (idx < m_entries.size()) { + const Entry &entry = m_entries[idx]; + ModuleSP module_sp(m_comp_unit->GetModule()); + if (module_sp && + module_sp->ResolveFileAddress(entry.file_addr, + line_entry.range.GetBaseAddress())) { + if (!entry.is_terminal_entry && idx + 1 < m_entries.size()) + line_entry.range.SetByteSize(m_entries[idx + 1].file_addr - + entry.file_addr); + else + line_entry.range.SetByteSize(0); + + line_entry.file = + m_comp_unit->GetSupportFiles().GetFileSpecAtIndex(entry.file_idx); + line_entry.original_file = + m_comp_unit->GetSupportFiles().GetFileSpecAtIndex(entry.file_idx); + line_entry.line = entry.line; + line_entry.column = entry.column; + line_entry.is_start_of_statement = entry.is_start_of_statement; + line_entry.is_start_of_basic_block = entry.is_start_of_basic_block; + line_entry.is_prologue_end = entry.is_prologue_end; + line_entry.is_epilogue_begin = entry.is_epilogue_begin; + line_entry.is_terminal_entry = entry.is_terminal_entry; + return true; } - - if (best_match != UINT32_MAX) - { - if (line_entry_ptr) - ConvertEntryAtIndexToLineEntry (best_match, *line_entry_ptr); - return best_match; - } - return UINT32_MAX; + } + return false; } -uint32_t -LineTable::FindLineEntryIndexByFileIndex (uint32_t start_idx, uint32_t file_idx, uint32_t line, bool exact, LineEntry* line_entry_ptr) -{ - const size_t count = m_entries.size(); - size_t best_match = UINT32_MAX; - - for (size_t idx = start_idx; idx < count; ++idx) - { - // Skip line table rows that terminate the previous row (is_terminal_entry is non-zero) - if (m_entries[idx].is_terminal_entry) - continue; - - if (m_entries[idx].file_idx != file_idx) - continue; - - // Exact match always wins. Otherwise try to find the closest line > the desired - // line. - // FIXME: Maybe want to find the line closest before and the line closest after and - // if they're not in the same function, don't return a match. - - if (m_entries[idx].line < line) - { - continue; - } - else if (m_entries[idx].line == line) - { - if (line_entry_ptr) - ConvertEntryAtIndexToLineEntry (idx, *line_entry_ptr); - return idx; - } - else if (!exact) - { - if (best_match == UINT32_MAX) - best_match = idx; - else if (m_entries[idx].line < m_entries[best_match].line) - best_match = idx; - } - } - - if (best_match != UINT32_MAX) - { - if (line_entry_ptr) - ConvertEntryAtIndexToLineEntry (best_match, *line_entry_ptr); - return best_match; +uint32_t LineTable::FindLineEntryIndexByFileIndex( + uint32_t start_idx, const std::vector<uint32_t> &file_indexes, + uint32_t line, bool exact, LineEntry *line_entry_ptr) { + + const size_t count = m_entries.size(); + std::vector<uint32_t>::const_iterator begin_pos = file_indexes.begin(); + std::vector<uint32_t>::const_iterator end_pos = file_indexes.end(); + size_t best_match = UINT32_MAX; + + for (size_t idx = start_idx; idx < count; ++idx) { + // Skip line table rows that terminate the previous row (is_terminal_entry + // is non-zero) + if (m_entries[idx].is_terminal_entry) + continue; + + if (find(begin_pos, end_pos, m_entries[idx].file_idx) == end_pos) + continue; + + // Exact match always wins. Otherwise try to find the closest line > the + // desired + // line. + // FIXME: Maybe want to find the line closest before and the line closest + // after and + // if they're not in the same function, don't return a match. + + if (m_entries[idx].line < line) { + continue; + } else if (m_entries[idx].line == line) { + if (line_entry_ptr) + ConvertEntryAtIndexToLineEntry(idx, *line_entry_ptr); + return idx; + } else if (!exact) { + if (best_match == UINT32_MAX) + best_match = idx; + else if (m_entries[idx].line < m_entries[best_match].line) + best_match = idx; } - return UINT32_MAX; + } + + if (best_match != UINT32_MAX) { + if (line_entry_ptr) + ConvertEntryAtIndexToLineEntry(best_match, *line_entry_ptr); + return best_match; + } + return UINT32_MAX; } -size_t -LineTable::FineLineEntriesForFileIndex (uint32_t file_idx, - bool append, - SymbolContextList &sc_list) -{ - - if (!append) - sc_list.Clear(); - - size_t num_added = 0; - const size_t count = m_entries.size(); - if (count > 0) - { - SymbolContext sc (m_comp_unit); - - for (size_t idx = 0; idx < count; ++idx) - { - // Skip line table rows that terminate the previous row (is_terminal_entry is non-zero) - if (m_entries[idx].is_terminal_entry) - continue; - - if (m_entries[idx].file_idx == file_idx) - { - if (ConvertEntryAtIndexToLineEntry (idx, sc.line_entry)) - { - ++num_added; - sc_list.Append(sc); - } - } - } +uint32_t LineTable::FindLineEntryIndexByFileIndex(uint32_t start_idx, + uint32_t file_idx, + uint32_t line, bool exact, + LineEntry *line_entry_ptr) { + const size_t count = m_entries.size(); + size_t best_match = UINT32_MAX; + + for (size_t idx = start_idx; idx < count; ++idx) { + // Skip line table rows that terminate the previous row (is_terminal_entry + // is non-zero) + if (m_entries[idx].is_terminal_entry) + continue; + + if (m_entries[idx].file_idx != file_idx) + continue; + + // Exact match always wins. Otherwise try to find the closest line > the + // desired + // line. + // FIXME: Maybe want to find the line closest before and the line closest + // after and + // if they're not in the same function, don't return a match. + + if (m_entries[idx].line < line) { + continue; + } else if (m_entries[idx].line == line) { + if (line_entry_ptr) + ConvertEntryAtIndexToLineEntry(idx, *line_entry_ptr); + return idx; + } else if (!exact) { + if (best_match == UINT32_MAX) + best_match = idx; + else if (m_entries[idx].line < m_entries[best_match].line) + best_match = idx; } - return num_added; + } + + if (best_match != UINT32_MAX) { + if (line_entry_ptr) + ConvertEntryAtIndexToLineEntry(best_match, *line_entry_ptr); + return best_match; + } + return UINT32_MAX; } +size_t LineTable::FineLineEntriesForFileIndex(uint32_t file_idx, bool append, + SymbolContextList &sc_list) { -void -LineTable::Dump (Stream *s, Target *target, Address::DumpStyle style, Address::DumpStyle fallback_style, bool show_line_ranges) -{ - const size_t count = m_entries.size(); - LineEntry line_entry; - FileSpec prev_file; - for (size_t idx = 0; idx < count; ++idx) - { - ConvertEntryAtIndexToLineEntry (idx, line_entry); - line_entry.Dump (s, target, prev_file != line_entry.original_file, style, fallback_style, show_line_ranges); - s->EOL(); - prev_file = line_entry.original_file; - } -} + if (!append) + sc_list.Clear(); + size_t num_added = 0; + const size_t count = m_entries.size(); + if (count > 0) { + SymbolContext sc(m_comp_unit); -void -LineTable::GetDescription (Stream *s, Target *target, DescriptionLevel level) -{ - const size_t count = m_entries.size(); - LineEntry line_entry; - for (size_t idx = 0; idx < count; ++idx) - { - ConvertEntryAtIndexToLineEntry (idx, line_entry); - line_entry.GetDescription (s, level, m_comp_unit, target, true); - s->EOL(); - } -} + for (size_t idx = 0; idx < count; ++idx) { + // Skip line table rows that terminate the previous row (is_terminal_entry + // is non-zero) + if (m_entries[idx].is_terminal_entry) + continue; -size_t -LineTable::GetContiguousFileAddressRanges (FileAddressRanges &file_ranges, bool append) -{ - if (!append) - file_ranges.Clear(); - const size_t initial_count = file_ranges.GetSize(); - - const size_t count = m_entries.size(); - LineEntry line_entry; - FileAddressRanges::Entry range (LLDB_INVALID_ADDRESS, 0); - for (size_t idx = 0; idx < count; ++idx) - { - const Entry& entry = m_entries[idx]; - - if (entry.is_terminal_entry) - { - if (range.GetRangeBase() != LLDB_INVALID_ADDRESS) - { - range.SetRangeEnd(entry.file_addr); - file_ranges.Append(range); - range.Clear(LLDB_INVALID_ADDRESS); - } - } - else if (range.GetRangeBase() == LLDB_INVALID_ADDRESS) - { - range.SetRangeBase(entry.file_addr); + if (m_entries[idx].file_idx == file_idx) { + if (ConvertEntryAtIndexToLineEntry(idx, sc.line_entry)) { + ++num_added; + sc_list.Append(sc); } + } } - return file_ranges.GetSize() - initial_count; + } + return num_added; } -LineTable * -LineTable::LinkLineTable (const FileRangeMap &file_range_map) -{ - std::unique_ptr<LineTable> line_table_ap (new LineTable (m_comp_unit)); - LineSequenceImpl sequence; - const size_t count = m_entries.size(); - LineEntry line_entry; - const FileRangeMap::Entry *file_range_entry = nullptr; - const FileRangeMap::Entry *prev_file_range_entry = nullptr; - lldb::addr_t prev_file_addr = LLDB_INVALID_ADDRESS; - bool prev_entry_was_linked = false; - bool range_changed = false; - for (size_t idx = 0; idx < count; ++idx) - { - const Entry& entry = m_entries[idx]; - - const bool end_sequence = entry.is_terminal_entry; - const lldb::addr_t lookup_file_addr = entry.file_addr - (end_sequence ? 1 : 0); - if (file_range_entry == nullptr || !file_range_entry->Contains(lookup_file_addr)) - { - prev_file_range_entry = file_range_entry; - file_range_entry = file_range_map.FindEntryThatContains(lookup_file_addr); - range_changed = true; - } +void LineTable::Dump(Stream *s, Target *target, Address::DumpStyle style, + Address::DumpStyle fallback_style, bool show_line_ranges) { + const size_t count = m_entries.size(); + LineEntry line_entry; + FileSpec prev_file; + for (size_t idx = 0; idx < count; ++idx) { + ConvertEntryAtIndexToLineEntry(idx, line_entry); + line_entry.Dump(s, target, prev_file != line_entry.original_file, style, + fallback_style, show_line_ranges); + s->EOL(); + prev_file = line_entry.original_file; + } +} - lldb::addr_t prev_end_entry_linked_file_addr = LLDB_INVALID_ADDRESS; - lldb::addr_t entry_linked_file_addr = LLDB_INVALID_ADDRESS; - - bool terminate_previous_entry = false; - if (file_range_entry) - { - entry_linked_file_addr = entry.file_addr - file_range_entry->GetRangeBase() + file_range_entry->data; - // Determine if we need to terminate the previous entry when the previous - // entry was not contiguous with this one after being linked. - if (range_changed && prev_file_range_entry) - { - prev_end_entry_linked_file_addr = std::min<lldb::addr_t>(entry.file_addr, prev_file_range_entry->GetRangeEnd()) - prev_file_range_entry->GetRangeBase() + prev_file_range_entry->data; - if (prev_end_entry_linked_file_addr != entry_linked_file_addr) - terminate_previous_entry = prev_entry_was_linked; - } - } - else if (prev_entry_was_linked) - { - // This entry doesn't have a remapping and it needs to be removed. - // Watch out in case we need to terminate a previous entry needs to - // be terminated now that one line entry in a sequence is not longer valid. - if (!sequence.m_entries.empty() && - !sequence.m_entries.back().is_terminal_entry) - { - terminate_previous_entry = true; - } - } - - if (terminate_previous_entry && !sequence.m_entries.empty()) - { - assert (prev_file_addr != LLDB_INVALID_ADDRESS); - sequence.m_entries.push_back(sequence.m_entries.back()); - if (prev_end_entry_linked_file_addr == LLDB_INVALID_ADDRESS) - prev_end_entry_linked_file_addr = std::min<lldb::addr_t>(entry.file_addr,prev_file_range_entry->GetRangeEnd()) - prev_file_range_entry->GetRangeBase() + prev_file_range_entry->data; - sequence.m_entries.back().file_addr = prev_end_entry_linked_file_addr; - sequence.m_entries.back().is_terminal_entry = true; - - // Append the sequence since we just terminated the previous one - line_table_ap->InsertSequence (&sequence); - sequence.Clear(); - } - - // Now link the current entry - if (file_range_entry) - { - // This entry has an address remapping and it needs to have its address relinked - sequence.m_entries.push_back(entry); - sequence.m_entries.back().file_addr = entry_linked_file_addr; - } +void LineTable::GetDescription(Stream *s, Target *target, + DescriptionLevel level) { + const size_t count = m_entries.size(); + LineEntry line_entry; + for (size_t idx = 0; idx < count; ++idx) { + ConvertEntryAtIndexToLineEntry(idx, line_entry); + line_entry.GetDescription(s, level, m_comp_unit, target, true); + s->EOL(); + } +} - // If we have items in the sequence and the last entry is a terminal entry, - // insert this sequence into our new line table. - if (!sequence.m_entries.empty() && sequence.m_entries.back().is_terminal_entry) - { - line_table_ap->InsertSequence (&sequence); - sequence.Clear(); - prev_entry_was_linked = false; - } - else - { - prev_entry_was_linked = file_range_entry != nullptr; - } - prev_file_addr = entry.file_addr; - range_changed = false; +size_t LineTable::GetContiguousFileAddressRanges(FileAddressRanges &file_ranges, + bool append) { + if (!append) + file_ranges.Clear(); + const size_t initial_count = file_ranges.GetSize(); + + const size_t count = m_entries.size(); + LineEntry line_entry; + FileAddressRanges::Entry range(LLDB_INVALID_ADDRESS, 0); + for (size_t idx = 0; idx < count; ++idx) { + const Entry &entry = m_entries[idx]; + + if (entry.is_terminal_entry) { + if (range.GetRangeBase() != LLDB_INVALID_ADDRESS) { + range.SetRangeEnd(entry.file_addr); + file_ranges.Append(range); + range.Clear(LLDB_INVALID_ADDRESS); + } + } else if (range.GetRangeBase() == LLDB_INVALID_ADDRESS) { + range.SetRangeBase(entry.file_addr); } - if (line_table_ap->m_entries.empty()) - return nullptr; - return line_table_ap.release(); + } + return file_ranges.GetSize() - initial_count; } +LineTable *LineTable::LinkLineTable(const FileRangeMap &file_range_map) { + std::unique_ptr<LineTable> line_table_ap(new LineTable(m_comp_unit)); + LineSequenceImpl sequence; + const size_t count = m_entries.size(); + LineEntry line_entry; + const FileRangeMap::Entry *file_range_entry = nullptr; + const FileRangeMap::Entry *prev_file_range_entry = nullptr; + lldb::addr_t prev_file_addr = LLDB_INVALID_ADDRESS; + bool prev_entry_was_linked = false; + bool range_changed = false; + for (size_t idx = 0; idx < count; ++idx) { + const Entry &entry = m_entries[idx]; + + const bool end_sequence = entry.is_terminal_entry; + const lldb::addr_t lookup_file_addr = + entry.file_addr - (end_sequence ? 1 : 0); + if (file_range_entry == nullptr || + !file_range_entry->Contains(lookup_file_addr)) { + prev_file_range_entry = file_range_entry; + file_range_entry = file_range_map.FindEntryThatContains(lookup_file_addr); + range_changed = true; + } + lldb::addr_t prev_end_entry_linked_file_addr = LLDB_INVALID_ADDRESS; + lldb::addr_t entry_linked_file_addr = LLDB_INVALID_ADDRESS; + + bool terminate_previous_entry = false; + if (file_range_entry) { + entry_linked_file_addr = entry.file_addr - + file_range_entry->GetRangeBase() + + file_range_entry->data; + // Determine if we need to terminate the previous entry when the previous + // entry was not contiguous with this one after being linked. + if (range_changed && prev_file_range_entry) { + prev_end_entry_linked_file_addr = + std::min<lldb::addr_t>(entry.file_addr, + prev_file_range_entry->GetRangeEnd()) - + prev_file_range_entry->GetRangeBase() + prev_file_range_entry->data; + if (prev_end_entry_linked_file_addr != entry_linked_file_addr) + terminate_previous_entry = prev_entry_was_linked; + } + } else if (prev_entry_was_linked) { + // This entry doesn't have a remapping and it needs to be removed. + // Watch out in case we need to terminate a previous entry needs to + // be terminated now that one line entry in a sequence is not longer + // valid. + if (!sequence.m_entries.empty() && + !sequence.m_entries.back().is_terminal_entry) { + terminate_previous_entry = true; + } + } + if (terminate_previous_entry && !sequence.m_entries.empty()) { + assert(prev_file_addr != LLDB_INVALID_ADDRESS); + sequence.m_entries.push_back(sequence.m_entries.back()); + if (prev_end_entry_linked_file_addr == LLDB_INVALID_ADDRESS) + prev_end_entry_linked_file_addr = + std::min<lldb::addr_t>(entry.file_addr, + prev_file_range_entry->GetRangeEnd()) - + prev_file_range_entry->GetRangeBase() + prev_file_range_entry->data; + sequence.m_entries.back().file_addr = prev_end_entry_linked_file_addr; + sequence.m_entries.back().is_terminal_entry = true; + + // Append the sequence since we just terminated the previous one + line_table_ap->InsertSequence(&sequence); + sequence.Clear(); + } + // Now link the current entry + if (file_range_entry) { + // This entry has an address remapping and it needs to have its address + // relinked + sequence.m_entries.push_back(entry); + sequence.m_entries.back().file_addr = entry_linked_file_addr; + } + + // If we have items in the sequence and the last entry is a terminal entry, + // insert this sequence into our new line table. + if (!sequence.m_entries.empty() && + sequence.m_entries.back().is_terminal_entry) { + line_table_ap->InsertSequence(&sequence); + sequence.Clear(); + prev_entry_was_linked = false; + } else { + prev_entry_was_linked = file_range_entry != nullptr; + } + prev_file_addr = entry.file_addr; + range_changed = false; + } + if (line_table_ap->m_entries.empty()) + return nullptr; + return line_table_ap.release(); +} diff --git a/lldb/source/Symbol/OCamlASTContext.cpp b/lldb/source/Symbol/OCamlASTContext.cpp index 1f2f57a2af9..8176fa18fb5 100644 --- a/lldb/source/Symbol/OCamlASTContext.cpp +++ b/lldb/source/Symbol/OCamlASTContext.cpp @@ -1,4 +1,5 @@ -//===-- OCamlASTContext.cpp ----------------------------------------*- C++ -*-===// +//===-- OCamlASTContext.cpp ----------------------------------------*- C++ +//-*-===// // // The LLVM Compiler Infrastructure // @@ -7,6 +8,7 @@ // //===----------------------------------------------------------------------===// +#include "lldb/Symbol/OCamlASTContext.h" #include "lldb/Core/Log.h" #include "lldb/Core/Module.h" #include "lldb/Core/PluginManager.h" @@ -14,7 +16,6 @@ #include "lldb/Core/ValueObject.h" #include "lldb/Symbol/ObjectFile.h" #include "lldb/Symbol/SymbolFile.h" -#include "lldb/Symbol/OCamlASTContext.h" #include "lldb/Symbol/Type.h" #include "lldb/Target/ExecutionContext.h" #include "lldb/Target/Target.h" @@ -24,471 +25,371 @@ using namespace lldb; using namespace lldb_private; -namespace lldb_private -{ - class OCamlASTContext::OCamlType - { - public: - enum LLVMCastKind - { - eKindPrimitive, - eKindObject, - eKindReference, - eKindArray, - kNumKinds - }; +namespace lldb_private { +class OCamlASTContext::OCamlType { +public: + enum LLVMCastKind { + eKindPrimitive, + eKindObject, + eKindReference, + eKindArray, + kNumKinds + }; - OCamlType(LLVMCastKind kind) : m_kind(kind) {} + OCamlType(LLVMCastKind kind) : m_kind(kind) {} - virtual ~OCamlType() = default; + virtual ~OCamlType() = default; - virtual ConstString - GetName() = 0; + virtual ConstString GetName() = 0; - virtual void - Dump(Stream *s) = 0; + virtual void Dump(Stream *s) = 0; - virtual bool - IsCompleteType() = 0; + virtual bool IsCompleteType() = 0; - LLVMCastKind - getKind() const - { - return m_kind; - } + LLVMCastKind getKind() const { return m_kind; } - private: - LLVMCastKind m_kind; - }; +private: + LLVMCastKind m_kind; +}; } // end of namespace lldb_private -namespace -{ - - class OCamlPrimitiveType : public OCamlASTContext::OCamlType - { - public: - enum TypeKind - { - eTypeInt, - }; - - OCamlPrimitiveType(TypeKind type_kind, uint32_t byte_size) : OCamlType(OCamlType::eKindPrimitive), m_type_kind(type_kind), m_type(ConstString()), m_byte_size(byte_size) {} - - OCamlPrimitiveType(TypeKind type_kind, ConstString s, uint32_t byte_size) : OCamlType(OCamlType::eKindPrimitive), m_type_kind(type_kind), m_type(s), m_byte_size(byte_size) {} - - ConstString - GetName() override - { - switch (m_type_kind) - { - case eTypeInt: - return m_type; - } - return ConstString(); - } - - TypeKind - GetTypeKind() - { - return m_type_kind; - } - - void - Dump(Stream *s) override - { - s->Printf("%s\n", GetName().GetCString()); - } - - bool - IsCompleteType() override - { - return true; - } - - static bool - classof(const OCamlType *ot) - { - return ot->getKind() == OCamlType::eKindPrimitive; - } - - uint64_t - GetByteSize() const - { - return m_byte_size; - } - - private: - const TypeKind m_type_kind; - const ConstString m_type; - uint64_t m_byte_size; - }; +namespace { + +class OCamlPrimitiveType : public OCamlASTContext::OCamlType { +public: + enum TypeKind { + eTypeInt, + }; + + OCamlPrimitiveType(TypeKind type_kind, uint32_t byte_size) + : OCamlType(OCamlType::eKindPrimitive), m_type_kind(type_kind), + m_type(ConstString()), m_byte_size(byte_size) {} + + OCamlPrimitiveType(TypeKind type_kind, ConstString s, uint32_t byte_size) + : OCamlType(OCamlType::eKindPrimitive), m_type_kind(type_kind), m_type(s), + m_byte_size(byte_size) {} + + ConstString GetName() override { + switch (m_type_kind) { + case eTypeInt: + return m_type; + } + return ConstString(); + } + + TypeKind GetTypeKind() { return m_type_kind; } + + void Dump(Stream *s) override { s->Printf("%s\n", GetName().GetCString()); } + + bool IsCompleteType() override { return true; } + + static bool classof(const OCamlType *ot) { + return ot->getKind() == OCamlType::eKindPrimitive; + } + + uint64_t GetByteSize() const { return m_byte_size; } + +private: + const TypeKind m_type_kind; + const ConstString m_type; + uint64_t m_byte_size; +}; } OCamlASTContext::OCamlASTContext() - : TypeSystem(eKindOCaml), - m_pointer_byte_size(0) -{ -} + : TypeSystem(eKindOCaml), m_pointer_byte_size(0) {} -OCamlASTContext::~OCamlASTContext() -{ -} +OCamlASTContext::~OCamlASTContext() {} -ConstString -OCamlASTContext::GetPluginNameStatic() -{ - return ConstString("ocaml"); +ConstString OCamlASTContext::GetPluginNameStatic() { + return ConstString("ocaml"); } -ConstString -OCamlASTContext::GetPluginName() -{ - return OCamlASTContext::GetPluginNameStatic(); +ConstString OCamlASTContext::GetPluginName() { + return OCamlASTContext::GetPluginNameStatic(); } -uint32_t -OCamlASTContext::GetPluginVersion() -{ - return 1; -} - -lldb::TypeSystemSP -OCamlASTContext::CreateInstance (lldb::LanguageType language, Module *module, Target *target) -{ - Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_LANGUAGE)); - - if (language == lldb::eLanguageTypeOCaml) - { - std::shared_ptr<OCamlASTContext> ocaml_ast_sp; - ArchSpec arch; - - if (module) - { - arch = module->GetArchitecture(); - - ObjectFile *objfile = module->GetObjectFile(); - ArchSpec object_arch; - - if (!objfile || !objfile->GetArchitecture(object_arch)) - return lldb::TypeSystemSP(); - - ocaml_ast_sp = std::shared_ptr<OCamlASTContext>(new OCamlASTContext); - - if (log) { - log->Printf ("((Module*)%p) [%s]->GetOCamlASTContext() = %p", - (void *)module, - module->GetFileSpec().GetFilename().AsCString("<anonymous>"), - (void *)ocaml_ast_sp.get()); - } - - } else if (target) { - arch = target->GetArchitecture(); - ocaml_ast_sp = std::shared_ptr<OCamlASTContextForExpr>(new OCamlASTContextForExpr(target->shared_from_this())); - - if (log) - { - log->Printf ("((Target*)%p)->GetOCamlASTContext() = %p", - (void *)target, - (void *)ocaml_ast_sp.get()); - } - } - - if (arch.IsValid()) { - ocaml_ast_sp->SetAddressByteSize(arch.GetAddressByteSize()); - return ocaml_ast_sp; - } +uint32_t OCamlASTContext::GetPluginVersion() { return 1; } + +lldb::TypeSystemSP OCamlASTContext::CreateInstance(lldb::LanguageType language, + Module *module, + Target *target) { + Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_LANGUAGE)); + + if (language == lldb::eLanguageTypeOCaml) { + std::shared_ptr<OCamlASTContext> ocaml_ast_sp; + ArchSpec arch; + + if (module) { + arch = module->GetArchitecture(); + + ObjectFile *objfile = module->GetObjectFile(); + ArchSpec object_arch; + + if (!objfile || !objfile->GetArchitecture(object_arch)) + return lldb::TypeSystemSP(); + + ocaml_ast_sp = std::shared_ptr<OCamlASTContext>(new OCamlASTContext); + + if (log) { + log->Printf( + "((Module*)%p) [%s]->GetOCamlASTContext() = %p", (void *)module, + module->GetFileSpec().GetFilename().AsCString("<anonymous>"), + (void *)ocaml_ast_sp.get()); + } + + } else if (target) { + arch = target->GetArchitecture(); + ocaml_ast_sp = std::shared_ptr<OCamlASTContextForExpr>( + new OCamlASTContextForExpr(target->shared_from_this())); + + if (log) { + log->Printf("((Target*)%p)->GetOCamlASTContext() = %p", (void *)target, + (void *)ocaml_ast_sp.get()); + } } - return lldb::TypeSystemSP(); + if (arch.IsValid()) { + ocaml_ast_sp->SetAddressByteSize(arch.GetAddressByteSize()); + return ocaml_ast_sp; + } + } + + return lldb::TypeSystemSP(); } -void -OCamlASTContext::EnumerateSupportedLanguages -(std::set<lldb::LanguageType> &languages_for_types, - std::set<lldb::LanguageType> &languages_for_expressions) -{ - static std::vector<lldb::LanguageType> s_supported_languages_for_types({lldb::eLanguageTypeOCaml}); - static std::vector<lldb::LanguageType> s_supported_languages_for_expressions({}); +void OCamlASTContext::EnumerateSupportedLanguages( + std::set<lldb::LanguageType> &languages_for_types, + std::set<lldb::LanguageType> &languages_for_expressions) { + static std::vector<lldb::LanguageType> s_supported_languages_for_types( + {lldb::eLanguageTypeOCaml}); + static std::vector<lldb::LanguageType> s_supported_languages_for_expressions( + {}); - languages_for_types.insert(s_supported_languages_for_types.begin(), s_supported_languages_for_types.end()); - languages_for_expressions.insert(s_supported_languages_for_expressions.begin(), s_supported_languages_for_expressions.end()); + languages_for_types.insert(s_supported_languages_for_types.begin(), + s_supported_languages_for_types.end()); + languages_for_expressions.insert( + s_supported_languages_for_expressions.begin(), + s_supported_languages_for_expressions.end()); } -void -OCamlASTContext::Initialize() -{ - PluginManager::RegisterPlugin (GetPluginNameStatic(), - "OCaml AST context plug-in", - CreateInstance, - EnumerateSupportedLanguages); +void OCamlASTContext::Initialize() { + PluginManager::RegisterPlugin(GetPluginNameStatic(), + "OCaml AST context plug-in", CreateInstance, + EnumerateSupportedLanguages); } -void -OCamlASTContext::Terminate() -{ - PluginManager::UnregisterPlugin (CreateInstance); +void OCamlASTContext::Terminate() { + PluginManager::UnregisterPlugin(CreateInstance); } -DWARFASTParser * -OCamlASTContext::GetDWARFParser() -{ - if (!m_dwarf_ast_parser_ap) { - m_dwarf_ast_parser_ap.reset(new DWARFASTParserOCaml(*this)); - } +DWARFASTParser *OCamlASTContext::GetDWARFParser() { + if (!m_dwarf_ast_parser_ap) { + m_dwarf_ast_parser_ap.reset(new DWARFASTParserOCaml(*this)); + } - return m_dwarf_ast_parser_ap.get(); + return m_dwarf_ast_parser_ap.get(); } -bool -OCamlASTContext::IsArrayType(lldb::opaque_compiler_type_t type, - CompilerType *element_type, uint64_t *size, - bool *is_incomplete) -{ - return false; +bool OCamlASTContext::IsArrayType(lldb::opaque_compiler_type_t type, + CompilerType *element_type, uint64_t *size, + bool *is_incomplete) { + return false; } -bool -OCamlASTContext::IsVectorType(lldb::opaque_compiler_type_t type, CompilerType *element_type, uint64_t *size) -{ - return false; +bool OCamlASTContext::IsVectorType(lldb::opaque_compiler_type_t type, + CompilerType *element_type, uint64_t *size) { + return false; } -bool -OCamlASTContext::IsAggregateType(lldb::opaque_compiler_type_t type) -{ - return false; +bool OCamlASTContext::IsAggregateType(lldb::opaque_compiler_type_t type) { + return false; } -bool -OCamlASTContext::IsBeingDefined(lldb::opaque_compiler_type_t type) -{ - return false; +bool OCamlASTContext::IsBeingDefined(lldb::opaque_compiler_type_t type) { + return false; } -bool -OCamlASTContext::IsCharType(lldb::opaque_compiler_type_t type) -{ - return false; +bool OCamlASTContext::IsCharType(lldb::opaque_compiler_type_t type) { + return false; } -bool -OCamlASTContext::IsCompleteType(lldb::opaque_compiler_type_t type) -{ - return static_cast<OCamlPrimitiveType *>(type)->IsCompleteType(); +bool OCamlASTContext::IsCompleteType(lldb::opaque_compiler_type_t type) { + return static_cast<OCamlPrimitiveType *>(type)->IsCompleteType(); } -bool -OCamlASTContext::IsConst(lldb::opaque_compiler_type_t type) -{ - return false; +bool OCamlASTContext::IsConst(lldb::opaque_compiler_type_t type) { + return false; } -bool -OCamlASTContext::IsCStringType(lldb::opaque_compiler_type_t type, uint32_t &length) -{ - return false; +bool OCamlASTContext::IsCStringType(lldb::opaque_compiler_type_t type, + uint32_t &length) { + return false; } -bool -OCamlASTContext::IsDefined(lldb::opaque_compiler_type_t type) -{ - return type != nullptr; +bool OCamlASTContext::IsDefined(lldb::opaque_compiler_type_t type) { + return type != nullptr; } -bool -OCamlASTContext::IsFloatingPointType(lldb::opaque_compiler_type_t type, uint32_t &count, bool &is_complex) -{ - return false; +bool OCamlASTContext::IsFloatingPointType(lldb::opaque_compiler_type_t type, + uint32_t &count, bool &is_complex) { + return false; } -bool -OCamlASTContext::IsFunctionType(lldb::opaque_compiler_type_t type, bool *is_variadic_ptr) -{ - return false; +bool OCamlASTContext::IsFunctionType(lldb::opaque_compiler_type_t type, + bool *is_variadic_ptr) { + return false; } uint32_t -OCamlASTContext::IsHomogeneousAggregate(lldb::opaque_compiler_type_t type, CompilerType *base_type_ptr) -{ - return false; +OCamlASTContext::IsHomogeneousAggregate(lldb::opaque_compiler_type_t type, + CompilerType *base_type_ptr) { + return false; } -size_t -OCamlASTContext::GetNumberOfFunctionArguments(lldb::opaque_compiler_type_t type) -{ - return 0; +size_t OCamlASTContext::GetNumberOfFunctionArguments( + lldb::opaque_compiler_type_t type) { + return 0; } CompilerType -OCamlASTContext::GetFunctionArgumentAtIndex(lldb::opaque_compiler_type_t type, const size_t index) -{ - return CompilerType(); +OCamlASTContext::GetFunctionArgumentAtIndex(lldb::opaque_compiler_type_t type, + const size_t index) { + return CompilerType(); } -bool -OCamlASTContext::IsFunctionPointerType(lldb::opaque_compiler_type_t type) -{ - return IsFunctionType(type); +bool OCamlASTContext::IsFunctionPointerType(lldb::opaque_compiler_type_t type) { + return IsFunctionType(type); } -bool -OCamlASTContext::IsBlockPointerType (lldb::opaque_compiler_type_t type, CompilerType *function_pointer_type_ptr) -{ - return false; +bool OCamlASTContext::IsBlockPointerType( + lldb::opaque_compiler_type_t type, + CompilerType *function_pointer_type_ptr) { + return false; } -bool -OCamlASTContext::IsIntegerType(lldb::opaque_compiler_type_t type, bool &is_signed) -{ - if (OCamlPrimitiveType *ptype = llvm::dyn_cast<OCamlPrimitiveType>(static_cast<OCamlType *>(type))) - { - switch (ptype->GetTypeKind()) - { - case OCamlPrimitiveType::eTypeInt: - is_signed = true; - return true; - } +bool OCamlASTContext::IsIntegerType(lldb::opaque_compiler_type_t type, + bool &is_signed) { + if (OCamlPrimitiveType *ptype = + llvm::dyn_cast<OCamlPrimitiveType>(static_cast<OCamlType *>(type))) { + switch (ptype->GetTypeKind()) { + case OCamlPrimitiveType::eTypeInt: + is_signed = true; + return true; } + } - is_signed = false; - return false; + is_signed = false; + return false; } -bool -OCamlASTContext::IsPolymorphicClass(lldb::opaque_compiler_type_t type) -{ - return false; +bool OCamlASTContext::IsPolymorphicClass(lldb::opaque_compiler_type_t type) { + return false; } -bool -OCamlASTContext::IsPossibleDynamicType(lldb::opaque_compiler_type_t type, - CompilerType *target_type, - bool check_cplusplus, bool check_objc) -{ - return false; +bool OCamlASTContext::IsPossibleDynamicType(lldb::opaque_compiler_type_t type, + CompilerType *target_type, + bool check_cplusplus, + bool check_objc) { + return false; } -bool -OCamlASTContext::IsRuntimeGeneratedType(lldb::opaque_compiler_type_t type) -{ - return false; +bool OCamlASTContext::IsRuntimeGeneratedType( + lldb::opaque_compiler_type_t type) { + return false; } -bool -OCamlASTContext::IsPointerType(lldb::opaque_compiler_type_t type, CompilerType *pointee_type) -{ - if (pointee_type) - pointee_type->Clear(); - return false; +bool OCamlASTContext::IsPointerType(lldb::opaque_compiler_type_t type, + CompilerType *pointee_type) { + if (pointee_type) + pointee_type->Clear(); + return false; } -bool -OCamlASTContext::IsPointerOrReferenceType(lldb::opaque_compiler_type_t type, CompilerType *pointee_type) -{ - return IsPointerType(type, pointee_type); +bool OCamlASTContext::IsPointerOrReferenceType( + lldb::opaque_compiler_type_t type, CompilerType *pointee_type) { + return IsPointerType(type, pointee_type); } -bool -OCamlASTContext::IsReferenceType(lldb::opaque_compiler_type_t type, CompilerType *pointee_type, bool *is_rvalue) -{ - return false; +bool OCamlASTContext::IsReferenceType(lldb::opaque_compiler_type_t type, + CompilerType *pointee_type, + bool *is_rvalue) { + return false; } -bool -OCamlASTContext::IsScalarType(lldb::opaque_compiler_type_t type) -{ - return llvm::isa<OCamlPrimitiveType>(static_cast<OCamlType *>(type)); +bool OCamlASTContext::IsScalarType(lldb::opaque_compiler_type_t type) { + return llvm::isa<OCamlPrimitiveType>(static_cast<OCamlType *>(type)); } -bool -OCamlASTContext::IsTypedefType(lldb::opaque_compiler_type_t type) -{ - return false; +bool OCamlASTContext::IsTypedefType(lldb::opaque_compiler_type_t type) { + return false; } -bool -OCamlASTContext::IsVoidType(lldb::opaque_compiler_type_t type) -{ - return false; +bool OCamlASTContext::IsVoidType(lldb::opaque_compiler_type_t type) { + return false; } -bool -OCamlASTContext::SupportsLanguage (lldb::LanguageType language) -{ - return language == lldb::eLanguageTypeOCaml; +bool OCamlASTContext::SupportsLanguage(lldb::LanguageType language) { + return language == lldb::eLanguageTypeOCaml; } -bool -OCamlASTContext::GetCompleteType(lldb::opaque_compiler_type_t type) -{ - if (IsCompleteType(type)) - return true; +bool OCamlASTContext::GetCompleteType(lldb::opaque_compiler_type_t type) { + if (IsCompleteType(type)) + return true; - return false; + return false; } -uint32_t -OCamlASTContext::GetPointerByteSize() -{ - return m_pointer_byte_size; -} +uint32_t OCamlASTContext::GetPointerByteSize() { return m_pointer_byte_size; } -ConstString -OCamlASTContext::GetTypeName(lldb::opaque_compiler_type_t type) -{ - if (type) - return static_cast<OCamlPrimitiveType *>(type)->GetName(); +ConstString OCamlASTContext::GetTypeName(lldb::opaque_compiler_type_t type) { + if (type) + return static_cast<OCamlPrimitiveType *>(type)->GetName(); - return ConstString(); + return ConstString(); } uint32_t -OCamlASTContext::GetTypeInfo(lldb::opaque_compiler_type_t type, CompilerType *pointee_or_element_compiler_type) -{ - if (pointee_or_element_compiler_type) - pointee_or_element_compiler_type->Clear(); - if (!type) - return 0; - - if (OCamlPrimitiveType *ptype = llvm::dyn_cast<OCamlPrimitiveType>(static_cast<OCamlType *>(type))) - { - switch (ptype->GetTypeKind()) - { - case OCamlPrimitiveType::eTypeInt: - return eTypeHasValue | eTypeIsBuiltIn | eTypeIsScalar | eTypeIsInteger | eTypeIsSigned; - } +OCamlASTContext::GetTypeInfo(lldb::opaque_compiler_type_t type, + CompilerType *pointee_or_element_compiler_type) { + if (pointee_or_element_compiler_type) + pointee_or_element_compiler_type->Clear(); + if (!type) + return 0; + + if (OCamlPrimitiveType *ptype = + llvm::dyn_cast<OCamlPrimitiveType>(static_cast<OCamlType *>(type))) { + switch (ptype->GetTypeKind()) { + case OCamlPrimitiveType::eTypeInt: + return eTypeHasValue | eTypeIsBuiltIn | eTypeIsScalar | eTypeIsInteger | + eTypeIsSigned; } + } - return 0; + return 0; } lldb::TypeClass -OCamlASTContext::GetTypeClass(lldb::opaque_compiler_type_t type) -{ - if (llvm::isa<OCamlPrimitiveType>(static_cast<OCamlType *>(type))) - return eTypeClassBuiltin; +OCamlASTContext::GetTypeClass(lldb::opaque_compiler_type_t type) { + if (llvm::isa<OCamlPrimitiveType>(static_cast<OCamlType *>(type))) + return eTypeClassBuiltin; - return lldb::eTypeClassInvalid; + return lldb::eTypeClassInvalid; } lldb::BasicType -OCamlASTContext::GetBasicTypeEnumeration(lldb::opaque_compiler_type_t type) -{ - return lldb::eBasicTypeInvalid; +OCamlASTContext::GetBasicTypeEnumeration(lldb::opaque_compiler_type_t type) { + return lldb::eBasicTypeInvalid; } lldb::LanguageType -OCamlASTContext::GetMinimumLanguage(lldb::opaque_compiler_type_t type) -{ - return lldb::eLanguageTypeOCaml; +OCamlASTContext::GetMinimumLanguage(lldb::opaque_compiler_type_t type) { + return lldb::eLanguageTypeOCaml; } -unsigned -OCamlASTContext::GetTypeQualifiers(lldb::opaque_compiler_type_t type) -{ - return 0; +unsigned OCamlASTContext::GetTypeQualifiers(lldb::opaque_compiler_type_t type) { + return 0; } //---------------------------------------------------------------------- @@ -496,300 +397,273 @@ OCamlASTContext::GetTypeQualifiers(lldb::opaque_compiler_type_t type) //---------------------------------------------------------------------- CompilerType -OCamlASTContext::GetArrayElementType(lldb::opaque_compiler_type_t type, uint64_t *stride) -{ - return CompilerType(); +OCamlASTContext::GetArrayElementType(lldb::opaque_compiler_type_t type, + uint64_t *stride) { + return CompilerType(); } CompilerType -OCamlASTContext::GetCanonicalType(lldb::opaque_compiler_type_t type) -{ - return CompilerType(this, type); +OCamlASTContext::GetCanonicalType(lldb::opaque_compiler_type_t type) { + return CompilerType(this, type); } CompilerType -OCamlASTContext::GetFullyUnqualifiedType(lldb::opaque_compiler_type_t type) -{ - return CompilerType(this, type); +OCamlASTContext::GetFullyUnqualifiedType(lldb::opaque_compiler_type_t type) { + return CompilerType(this, type); } -int -OCamlASTContext::GetFunctionArgumentCount(lldb::opaque_compiler_type_t type) -{ - return GetNumberOfFunctionArguments(type); +int OCamlASTContext::GetFunctionArgumentCount( + lldb::opaque_compiler_type_t type) { + return GetNumberOfFunctionArguments(type); } -CompilerType -OCamlASTContext::GetFunctionArgumentTypeAtIndex(lldb::opaque_compiler_type_t type, size_t idx) -{ - return GetFunctionArgumentAtIndex(type, idx); +CompilerType OCamlASTContext::GetFunctionArgumentTypeAtIndex( + lldb::opaque_compiler_type_t type, size_t idx) { + return GetFunctionArgumentAtIndex(type, idx); } CompilerType -OCamlASTContext::GetFunctionReturnType(lldb::opaque_compiler_type_t type) -{ - return CompilerType(); +OCamlASTContext::GetFunctionReturnType(lldb::opaque_compiler_type_t type) { + return CompilerType(); } size_t -OCamlASTContext::GetNumMemberFunctions(lldb::opaque_compiler_type_t type) -{ - return 0; +OCamlASTContext::GetNumMemberFunctions(lldb::opaque_compiler_type_t type) { + return 0; } TypeMemberFunctionImpl -OCamlASTContext::GetMemberFunctionAtIndex(lldb::opaque_compiler_type_t type, size_t idx) -{ - return TypeMemberFunctionImpl(); +OCamlASTContext::GetMemberFunctionAtIndex(lldb::opaque_compiler_type_t type, + size_t idx) { + return TypeMemberFunctionImpl(); } CompilerType -OCamlASTContext::GetNonReferenceType(lldb::opaque_compiler_type_t type) -{ - return CompilerType(this, type); +OCamlASTContext::GetNonReferenceType(lldb::opaque_compiler_type_t type) { + return CompilerType(this, type); } CompilerType -OCamlASTContext::GetPointeeType(lldb::opaque_compiler_type_t type) -{ - return CompilerType(); +OCamlASTContext::GetPointeeType(lldb::opaque_compiler_type_t type) { + return CompilerType(); } CompilerType -OCamlASTContext::GetPointerType(lldb::opaque_compiler_type_t type) -{ - return CompilerType(); +OCamlASTContext::GetPointerType(lldb::opaque_compiler_type_t type) { + return CompilerType(); } CompilerType -OCamlASTContext::GetTypedefedType(lldb::opaque_compiler_type_t type) -{ - return CompilerType(); +OCamlASTContext::GetTypedefedType(lldb::opaque_compiler_type_t type) { + return CompilerType(); } -CompilerType -OCamlASTContext::GetBasicTypeFromAST(lldb::BasicType basic_type) -{ - return CompilerType(); +CompilerType OCamlASTContext::GetBasicTypeFromAST(lldb::BasicType basic_type) { + return CompilerType(); } CompilerType -OCamlASTContext::GetBuiltinTypeForEncodingAndBitSize (lldb::Encoding encoding, - size_t bit_size) -{ - return CompilerType(); -} - -uint64_t -OCamlASTContext::GetBitSize(lldb::opaque_compiler_type_t type, ExecutionContextScope *exe_scope) -{ - if (OCamlPrimitiveType *ptype = llvm::dyn_cast<OCamlPrimitiveType>(static_cast<OCamlType *>(type))) - { - switch (ptype->GetTypeKind()) - { - case OCamlPrimitiveType::eTypeInt: - return ptype->GetByteSize() * 8; - } +OCamlASTContext::GetBuiltinTypeForEncodingAndBitSize(lldb::Encoding encoding, + size_t bit_size) { + return CompilerType(); +} + +uint64_t OCamlASTContext::GetBitSize(lldb::opaque_compiler_type_t type, + ExecutionContextScope *exe_scope) { + if (OCamlPrimitiveType *ptype = + llvm::dyn_cast<OCamlPrimitiveType>(static_cast<OCamlType *>(type))) { + switch (ptype->GetTypeKind()) { + case OCamlPrimitiveType::eTypeInt: + return ptype->GetByteSize() * 8; } - return 0; + } + return 0; } -lldb::Encoding -OCamlASTContext::GetEncoding(lldb::opaque_compiler_type_t type, uint64_t &count) -{ - count = 1; - bool is_signed; - if (IsIntegerType(type, is_signed)) - return is_signed ? lldb::eEncodingSint : lldb::eEncodingUint; - bool is_complex; - uint32_t complex_count; - if (IsFloatingPointType(type, complex_count, is_complex)) - { - count = complex_count; - return lldb::eEncodingIEEE754; - } - if (IsPointerType(type)) - return lldb::eEncodingUint; - return lldb::eEncodingInvalid; +lldb::Encoding OCamlASTContext::GetEncoding(lldb::opaque_compiler_type_t type, + uint64_t &count) { + count = 1; + bool is_signed; + if (IsIntegerType(type, is_signed)) + return is_signed ? lldb::eEncodingSint : lldb::eEncodingUint; + bool is_complex; + uint32_t complex_count; + if (IsFloatingPointType(type, complex_count, is_complex)) { + count = complex_count; + return lldb::eEncodingIEEE754; + } + if (IsPointerType(type)) + return lldb::eEncodingUint; + return lldb::eEncodingInvalid; } -lldb::Format -OCamlASTContext::GetFormat(lldb::opaque_compiler_type_t type) -{ - if (!type) - return lldb::eFormatDefault; - return lldb::eFormatBytes; +lldb::Format OCamlASTContext::GetFormat(lldb::opaque_compiler_type_t type) { + if (!type) + return lldb::eFormatDefault; + return lldb::eFormatBytes; } -size_t -OCamlASTContext::GetTypeBitAlign(lldb::opaque_compiler_type_t type) -{ - return 0; +size_t OCamlASTContext::GetTypeBitAlign(lldb::opaque_compiler_type_t type) { + return 0; } -uint32_t -OCamlASTContext::GetNumChildren(lldb::opaque_compiler_type_t type, bool omit_empty_base_classes) -{ - if (!type || !GetCompleteType(type)) - return 0; +uint32_t OCamlASTContext::GetNumChildren(lldb::opaque_compiler_type_t type, + bool omit_empty_base_classes) { + if (!type || !GetCompleteType(type)) + return 0; - return GetNumFields(type); + return GetNumFields(type); } -uint32_t -OCamlASTContext::GetNumFields(lldb::opaque_compiler_type_t type) -{ - if (!type || !GetCompleteType(type)) - return 0; +uint32_t OCamlASTContext::GetNumFields(lldb::opaque_compiler_type_t type) { + if (!type || !GetCompleteType(type)) return 0; -} - -CompilerType -OCamlASTContext::GetFieldAtIndex(lldb::opaque_compiler_type_t type, size_t idx, - std::string &name, uint64_t *bit_offset_ptr, - uint32_t *bitfield_bit_size_ptr, bool *is_bitfield_ptr) -{ - if (bit_offset_ptr) - *bit_offset_ptr = 0; - if (bitfield_bit_size_ptr) - *bitfield_bit_size_ptr = 0; - if (is_bitfield_ptr) - *is_bitfield_ptr = false; - - if (!type || !GetCompleteType(type)) - return CompilerType(); - + return 0; +} + +CompilerType OCamlASTContext::GetFieldAtIndex(lldb::opaque_compiler_type_t type, + size_t idx, std::string &name, + uint64_t *bit_offset_ptr, + uint32_t *bitfield_bit_size_ptr, + bool *is_bitfield_ptr) { + if (bit_offset_ptr) + *bit_offset_ptr = 0; + if (bitfield_bit_size_ptr) + *bitfield_bit_size_ptr = 0; + if (is_bitfield_ptr) + *is_bitfield_ptr = false; + + if (!type || !GetCompleteType(type)) return CompilerType(); -} - -CompilerType -OCamlASTContext::GetChildCompilerTypeAtIndex(lldb::opaque_compiler_type_t type, ExecutionContext *exe_ctx, size_t idx, - bool transparent_pointers, bool omit_empty_base_classes, - bool ignore_array_bounds, std::string &child_name, - uint32_t &child_byte_size, int32_t &child_byte_offset, - uint32_t &child_bitfield_bit_size, uint32_t &child_bitfield_bit_offset, - bool &child_is_base_class, bool &child_is_deref_of_parent, ValueObject *valobj, - uint64_t &language_flags) -{ - child_name.clear(); - child_byte_size = 0; - child_byte_offset = 0; - child_bitfield_bit_size = 0; - child_bitfield_bit_offset = 0; - child_is_base_class = false; - child_is_deref_of_parent = false; - language_flags = 0; - - if (!type || !GetCompleteType(type)) - return CompilerType(); + return CompilerType(); +} + +CompilerType OCamlASTContext::GetChildCompilerTypeAtIndex( + lldb::opaque_compiler_type_t type, ExecutionContext *exe_ctx, size_t idx, + bool transparent_pointers, bool omit_empty_base_classes, + bool ignore_array_bounds, std::string &child_name, + uint32_t &child_byte_size, int32_t &child_byte_offset, + uint32_t &child_bitfield_bit_size, uint32_t &child_bitfield_bit_offset, + bool &child_is_base_class, bool &child_is_deref_of_parent, + ValueObject *valobj, uint64_t &language_flags) { + child_name.clear(); + child_byte_size = 0; + child_byte_offset = 0; + child_bitfield_bit_size = 0; + child_bitfield_bit_offset = 0; + child_is_base_class = false; + child_is_deref_of_parent = false; + language_flags = 0; + + if (!type || !GetCompleteType(type)) return CompilerType(); + + return CompilerType(); } uint32_t -OCamlASTContext::GetIndexOfChildWithName(lldb::opaque_compiler_type_t type, const char *name, bool omit_empty_base_classes) -{ - if (!type || !GetCompleteType(type)) - return UINT_MAX; - +OCamlASTContext::GetIndexOfChildWithName(lldb::opaque_compiler_type_t type, + const char *name, + bool omit_empty_base_classes) { + if (!type || !GetCompleteType(type)) return UINT_MAX; + + return UINT_MAX; } -size_t -OCamlASTContext::GetIndexOfChildMemberWithName(lldb::opaque_compiler_type_t type, const char *name, - bool omit_empty_base_classes, std::vector<uint32_t> &child_indexes) -{ - uint32_t index = GetIndexOfChildWithName(type, name, omit_empty_base_classes); - if (index == UINT_MAX) - return 0; - child_indexes.push_back(index); - return 1; +size_t OCamlASTContext::GetIndexOfChildMemberWithName( + lldb::opaque_compiler_type_t type, const char *name, + bool omit_empty_base_classes, std::vector<uint32_t> &child_indexes) { + uint32_t index = GetIndexOfChildWithName(type, name, omit_empty_base_classes); + if (index == UINT_MAX) + return 0; + child_indexes.push_back(index); + return 1; } size_t -OCamlASTContext::ConvertStringToFloatValue(lldb::opaque_compiler_type_t type, const char *s, uint8_t *dst, size_t dst_size) -{ - assert(false); - return 0; +OCamlASTContext::ConvertStringToFloatValue(lldb::opaque_compiler_type_t type, + const char *s, uint8_t *dst, + size_t dst_size) { + assert(false); + return 0; } //---------------------------------------------------------------------- // Dumping types //---------------------------------------------------------------------- -void -OCamlASTContext::DumpValue(lldb::opaque_compiler_type_t type, ExecutionContext *exe_ctx, Stream *s, lldb::Format format, - const DataExtractor &data, lldb::offset_t data_byte_offset, size_t data_byte_size, - uint32_t bitfield_bit_size, uint32_t bitfield_bit_offset, bool show_types, bool show_summary, - bool verbose, uint32_t depth) -{ - if (!type) { - s->Printf("no type\n"); - return; - } +void OCamlASTContext::DumpValue( + lldb::opaque_compiler_type_t type, ExecutionContext *exe_ctx, Stream *s, + lldb::Format format, const DataExtractor &data, + lldb::offset_t data_byte_offset, size_t data_byte_size, + uint32_t bitfield_bit_size, uint32_t bitfield_bit_offset, bool show_types, + bool show_summary, bool verbose, uint32_t depth) { + if (!type) { + s->Printf("no type\n"); + return; + } + + s->Printf("no value\n"); + + if (show_summary) + DumpSummary(type, exe_ctx, s, data, data_byte_offset, data_byte_size); +} + +bool OCamlASTContext::DumpTypeValue( + lldb::opaque_compiler_type_t type, Stream *s, lldb::Format format, + const DataExtractor &data, lldb::offset_t byte_offset, size_t byte_size, + uint32_t bitfield_bit_size, uint32_t bitfield_bit_offset, + ExecutionContextScope *exe_scope) { + if (!type) { + s->Printf("no type value\n"); + return false; + } - s->Printf("no value\n"); + if (IsScalarType(type)) { + return data.Dump(s, byte_offset, format, byte_size, 1, UINT64_MAX, + LLDB_INVALID_ADDRESS, bitfield_bit_size, + bitfield_bit_offset, exe_scope); + } - if (show_summary) - DumpSummary (type, exe_ctx, s, data, data_byte_offset, data_byte_size); + return false; } -bool -OCamlASTContext::DumpTypeValue(lldb::opaque_compiler_type_t type, Stream *s, - lldb::Format format, const DataExtractor &data, - lldb::offset_t byte_offset, size_t byte_size, uint32_t bitfield_bit_size, - uint32_t bitfield_bit_offset, ExecutionContextScope *exe_scope) -{ - if (!type) { - s->Printf("no type value\n"); - return false; - } - - if (IsScalarType(type)) - { - return - data.Dump(s, byte_offset, format, byte_size, 1, UINT64_MAX, - LLDB_INVALID_ADDRESS, bitfield_bit_size, bitfield_bit_offset, exe_scope); - } - - return false; +void OCamlASTContext::DumpSummary(lldb::opaque_compiler_type_t type, + ExecutionContext *exe_ctx, Stream *s, + const DataExtractor &data, + lldb::offset_t data_offset, + size_t data_byte_size) { + s->Printf("no summary\n"); } -void -OCamlASTContext::DumpSummary(lldb::opaque_compiler_type_t type, ExecutionContext *exe_ctx, Stream *s, - const DataExtractor &data, lldb::offset_t data_offset, size_t data_byte_size) -{ - s->Printf("no summary\n"); +void OCamlASTContext::DumpTypeDescription(lldb::opaque_compiler_type_t type) { + StreamFile s(stdout, false); + DumpTypeDescription(type, &s); } -void -OCamlASTContext::DumpTypeDescription(lldb::opaque_compiler_type_t type) -{ - StreamFile s(stdout, false); - DumpTypeDescription(type, &s); +void OCamlASTContext::DumpTypeDescription(lldb::opaque_compiler_type_t type, + Stream *s) { + static_cast<OCamlType *>(type)->Dump(s); } -void -OCamlASTContext::DumpTypeDescription(lldb::opaque_compiler_type_t type, Stream *s) -{ - static_cast<OCamlType *>(type)->Dump(s); -} - -CompilerType -OCamlASTContext::CreateBaseType(const ConstString &name, uint64_t byte_size) -{ - if (m_base_type_map.empty()) - { - OCamlPrimitiveType *type = new OCamlPrimitiveType(OCamlPrimitiveType::eTypeInt, ConstString("ocaml_int"), byte_size); - m_base_type_map.emplace(type->GetName(), std::unique_ptr<OCamlASTContext::OCamlType>(type)); - } +CompilerType OCamlASTContext::CreateBaseType(const ConstString &name, + uint64_t byte_size) { + if (m_base_type_map.empty()) { + OCamlPrimitiveType *type = new OCamlPrimitiveType( + OCamlPrimitiveType::eTypeInt, ConstString("ocaml_int"), byte_size); + m_base_type_map.emplace(type->GetName(), + std::unique_ptr<OCamlASTContext::OCamlType>(type)); + } - auto it = m_base_type_map.find(name); - if (it == m_base_type_map.end()) - { - OCamlPrimitiveType *type = new OCamlPrimitiveType(OCamlPrimitiveType::eTypeInt, name, byte_size); - it = m_base_type_map.emplace(name, std::unique_ptr<OCamlASTContext::OCamlType>(type)).first; - } + auto it = m_base_type_map.find(name); + if (it == m_base_type_map.end()) { + OCamlPrimitiveType *type = + new OCamlPrimitiveType(OCamlPrimitiveType::eTypeInt, name, byte_size); + it = m_base_type_map + .emplace(name, std::unique_ptr<OCamlASTContext::OCamlType>(type)) + .first; + } - return CompilerType(this, it->second.get()); + return CompilerType(this, it->second.get()); } - diff --git a/lldb/source/Symbol/ObjectFile.cpp b/lldb/source/Symbol/ObjectFile.cpp index 18da7ef2d81..fd233ccd81c 100644 --- a/lldb/source/Symbol/ObjectFile.cpp +++ b/lldb/source/Symbol/ObjectFile.cpp @@ -7,7 +7,8 @@ // //===----------------------------------------------------------------------===// -#include "lldb/lldb-private.h" +#include "lldb/Symbol/ObjectFile.h" +#include "Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.h" #include "lldb/Core/DataBuffer.h" #include "lldb/Core/DataBufferHeap.h" #include "lldb/Core/Log.h" @@ -17,653 +18,632 @@ #include "lldb/Core/RegularExpression.h" #include "lldb/Core/Section.h" #include "lldb/Core/Timer.h" -#include "lldb/Symbol/ObjectFile.h" #include "lldb/Symbol/ObjectContainer.h" #include "lldb/Symbol/SymbolFile.h" #include "lldb/Target/Process.h" -#include "Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.h" +#include "lldb/lldb-private.h" using namespace lldb; using namespace lldb_private; ObjectFileSP -ObjectFile::FindPlugin (const lldb::ModuleSP &module_sp, - const FileSpec* file, - lldb::offset_t file_offset, - lldb::offset_t file_size, - DataBufferSP &data_sp, - lldb::offset_t &data_offset) -{ - ObjectFileSP object_file_sp; - - if (module_sp) - { - Timer scoped_timer (LLVM_PRETTY_FUNCTION, - "ObjectFile::FindPlugin (module = %s, file = %p, file_offset = 0x%8.8" PRIx64 ", file_size = 0x%8.8" PRIx64 ")", - module_sp->GetFileSpec().GetPath().c_str(), - static_cast<const void*>(file), - static_cast<uint64_t>(file_offset), - static_cast<uint64_t>(file_size)); - if (file) - { - FileSpec archive_file; - ObjectContainerCreateInstance create_object_container_callback; - - const bool file_exists = file->Exists(); - if (!data_sp) - { - // We have an object name which most likely means we have - // a .o file in a static archive (.a file). Try and see if - // we have a cached archive first without reading any data - // first - if (file_exists && module_sp->GetObjectName()) - { - for (uint32_t idx = 0; (create_object_container_callback = PluginManager::GetObjectContainerCreateCallbackAtIndex(idx)) != nullptr; ++idx) - { - std::unique_ptr<ObjectContainer> object_container_ap(create_object_container_callback(module_sp, data_sp, data_offset, file, file_offset, file_size)); - - if (object_container_ap.get()) - object_file_sp = object_container_ap->GetObjectFile(file); - - if (object_file_sp.get()) - return object_file_sp; - } - } - // Ok, we didn't find any containers that have a named object, now - // lets read the first 512 bytes from the file so the object file - // and object container plug-ins can use these bytes to see if they - // can parse this file. - if (file_size > 0) - { - data_sp = file->ReadFileContents(file_offset, std::min<size_t>(512, file_size)); - data_offset = 0; - } - } +ObjectFile::FindPlugin(const lldb::ModuleSP &module_sp, const FileSpec *file, + lldb::offset_t file_offset, lldb::offset_t file_size, + DataBufferSP &data_sp, lldb::offset_t &data_offset) { + ObjectFileSP object_file_sp; + + if (module_sp) { + Timer scoped_timer( + LLVM_PRETTY_FUNCTION, + "ObjectFile::FindPlugin (module = %s, file = %p, file_offset = " + "0x%8.8" PRIx64 ", file_size = 0x%8.8" PRIx64 ")", + module_sp->GetFileSpec().GetPath().c_str(), + static_cast<const void *>(file), static_cast<uint64_t>(file_offset), + static_cast<uint64_t>(file_size)); + if (file) { + FileSpec archive_file; + ObjectContainerCreateInstance create_object_container_callback; + + const bool file_exists = file->Exists(); + if (!data_sp) { + // We have an object name which most likely means we have + // a .o file in a static archive (.a file). Try and see if + // we have a cached archive first without reading any data + // first + if (file_exists && module_sp->GetObjectName()) { + for (uint32_t idx = 0; + (create_object_container_callback = + PluginManager::GetObjectContainerCreateCallbackAtIndex( + idx)) != nullptr; + ++idx) { + std::unique_ptr<ObjectContainer> object_container_ap( + create_object_container_callback(module_sp, data_sp, + data_offset, file, file_offset, + file_size)); + + if (object_container_ap.get()) + object_file_sp = object_container_ap->GetObjectFile(file); - if (!data_sp || data_sp->GetByteSize() == 0) - { - // Check for archive file with format "/path/to/archive.a(object.o)" - char path_with_object[PATH_MAX*2]; - module_sp->GetFileSpec().GetPath(path_with_object, sizeof(path_with_object)); - - ConstString archive_object; - const bool must_exist = true; - if (ObjectFile::SplitArchivePathWithObject (path_with_object, archive_file, archive_object, must_exist)) - { - file_size = archive_file.GetByteSize(); - if (file_size > 0) - { - file = &archive_file; - module_sp->SetFileSpecAndObjectName (archive_file, archive_object); - // Check if this is a object container by iterating through all object - // container plugin instances and then trying to get an object file - // from the container plugins since we had a name. Also, don't read - // ANY data in case there is data cached in the container plug-ins - // (like BSD archives caching the contained objects within an file). - for (uint32_t idx = 0; (create_object_container_callback = PluginManager::GetObjectContainerCreateCallbackAtIndex(idx)) != nullptr; ++idx) - { - std::unique_ptr<ObjectContainer> object_container_ap(create_object_container_callback(module_sp, data_sp, data_offset, file, file_offset, file_size)); - - if (object_container_ap.get()) - object_file_sp = object_container_ap->GetObjectFile(file); - - if (object_file_sp.get()) - return object_file_sp; - } - // We failed to find any cached object files in the container - // plug-ins, so lets read the first 512 bytes and try again below... - data_sp = archive_file.ReadFileContents(file_offset, 512); - } - } - } - - if (data_sp && data_sp->GetByteSize() > 0) - { - // Check if this is a normal object file by iterating through - // all object file plugin instances. - ObjectFileCreateInstance create_object_file_callback; - for (uint32_t idx = 0; (create_object_file_callback = PluginManager::GetObjectFileCreateCallbackAtIndex(idx)) != nullptr; ++idx) - { - object_file_sp.reset (create_object_file_callback(module_sp, data_sp, data_offset, file, file_offset, file_size)); - if (object_file_sp.get()) - return object_file_sp; - } - - // Check if this is a object container by iterating through - // all object container plugin instances and then trying to get - // an object file from the container. - for (uint32_t idx = 0; (create_object_container_callback = PluginManager::GetObjectContainerCreateCallbackAtIndex(idx)) != nullptr; ++idx) - { - std::unique_ptr<ObjectContainer> object_container_ap(create_object_container_callback(module_sp, data_sp, data_offset, file, file_offset, file_size)); - - if (object_container_ap.get()) - object_file_sp = object_container_ap->GetObjectFile(file); - - if (object_file_sp.get()) - return object_file_sp; - } + if (object_file_sp.get()) + return object_file_sp; + } + } + // Ok, we didn't find any containers that have a named object, now + // lets read the first 512 bytes from the file so the object file + // and object container plug-ins can use these bytes to see if they + // can parse this file. + if (file_size > 0) { + data_sp = file->ReadFileContents(file_offset, + std::min<size_t>(512, file_size)); + data_offset = 0; + } + } + + if (!data_sp || data_sp->GetByteSize() == 0) { + // Check for archive file with format "/path/to/archive.a(object.o)" + char path_with_object[PATH_MAX * 2]; + module_sp->GetFileSpec().GetPath(path_with_object, + sizeof(path_with_object)); + + ConstString archive_object; + const bool must_exist = true; + if (ObjectFile::SplitArchivePathWithObject( + path_with_object, archive_file, archive_object, must_exist)) { + file_size = archive_file.GetByteSize(); + if (file_size > 0) { + file = &archive_file; + module_sp->SetFileSpecAndObjectName(archive_file, archive_object); + // Check if this is a object container by iterating through all + // object + // container plugin instances and then trying to get an object file + // from the container plugins since we had a name. Also, don't read + // ANY data in case there is data cached in the container plug-ins + // (like BSD archives caching the contained objects within an file). + for (uint32_t idx = 0; + (create_object_container_callback = + PluginManager::GetObjectContainerCreateCallbackAtIndex( + idx)) != nullptr; + ++idx) { + std::unique_ptr<ObjectContainer> object_container_ap( + create_object_container_callback(module_sp, data_sp, + data_offset, file, + file_offset, file_size)); + + if (object_container_ap.get()) + object_file_sp = object_container_ap->GetObjectFile(file); + + if (object_file_sp.get()) + return object_file_sp; } + // We failed to find any cached object files in the container + // plug-ins, so lets read the first 512 bytes and try again below... + data_sp = archive_file.ReadFileContents(file_offset, 512); + } } - } - // We didn't find it, so clear our shared pointer in case it - // contains anything and return an empty shared pointer - object_file_sp.reset(); - return object_file_sp; -} - -ObjectFileSP -ObjectFile::FindPlugin (const lldb::ModuleSP &module_sp, - const ProcessSP &process_sp, - lldb::addr_t header_addr, - DataBufferSP &data_sp) -{ - ObjectFileSP object_file_sp; - - if (module_sp) - { - Timer scoped_timer (LLVM_PRETTY_FUNCTION, - "ObjectFile::FindPlugin (module = %s, process = %p, header_addr = 0x%" PRIx64 ")", - module_sp->GetFileSpec().GetPath().c_str(), - static_cast<void*>(process_sp.get()), header_addr); - uint32_t idx; + } + if (data_sp && data_sp->GetByteSize() > 0) { // Check if this is a normal object file by iterating through // all object file plugin instances. - ObjectFileCreateMemoryInstance create_callback; - for (idx = 0; (create_callback = PluginManager::GetObjectFileCreateMemoryCallbackAtIndex(idx)) != nullptr; ++idx) - { - object_file_sp.reset (create_callback(module_sp, data_sp, process_sp, header_addr)); - if (object_file_sp.get()) - return object_file_sp; + ObjectFileCreateInstance create_object_file_callback; + for (uint32_t idx = 0; + (create_object_file_callback = + PluginManager::GetObjectFileCreateCallbackAtIndex(idx)) != + nullptr; + ++idx) { + object_file_sp.reset(create_object_file_callback( + module_sp, data_sp, data_offset, file, file_offset, file_size)); + if (object_file_sp.get()) + return object_file_sp; } - } - - // We didn't find it, so clear our shared pointer in case it - // contains anything and return an empty shared pointer - object_file_sp.reset(); - return object_file_sp; -} -size_t -ObjectFile::GetModuleSpecifications (const FileSpec &file, - lldb::offset_t file_offset, - lldb::offset_t file_size, - ModuleSpecList &specs) -{ - DataBufferSP data_sp (file.ReadFileContents(file_offset, 512)); - if (data_sp) - { - if (file_size == 0) - { - const lldb::offset_t actual_file_size = file.GetByteSize(); - if (actual_file_size > file_offset) - file_size = actual_file_size - file_offset; + // Check if this is a object container by iterating through + // all object container plugin instances and then trying to get + // an object file from the container. + for (uint32_t idx = 0; + (create_object_container_callback = + PluginManager::GetObjectContainerCreateCallbackAtIndex( + idx)) != nullptr; + ++idx) { + std::unique_ptr<ObjectContainer> object_container_ap( + create_object_container_callback(module_sp, data_sp, data_offset, + file, file_offset, file_size)); + + if (object_container_ap.get()) + object_file_sp = object_container_ap->GetObjectFile(file); + + if (object_file_sp.get()) + return object_file_sp; } - return ObjectFile::GetModuleSpecifications (file, // file spec - data_sp, // data bytes - 0, // data offset - file_offset,// file offset - file_size, // file length - specs); + } } - return 0; + } + // We didn't find it, so clear our shared pointer in case it + // contains anything and return an empty shared pointer + object_file_sp.reset(); + return object_file_sp; } -size_t -ObjectFile::GetModuleSpecifications (const lldb_private::FileSpec& file, - lldb::DataBufferSP& data_sp, - lldb::offset_t data_offset, - lldb::offset_t file_offset, - lldb::offset_t file_size, - lldb_private::ModuleSpecList &specs) -{ - const size_t initial_count = specs.GetSize(); - ObjectFileGetModuleSpecifications callback; - uint32_t i; - // Try the ObjectFile plug-ins - for (i = 0; (callback = PluginManager::GetObjectFileGetModuleSpecificationsCallbackAtIndex(i)) != nullptr; ++i) - { - if (callback (file, data_sp, data_offset, file_offset, file_size, specs) > 0) - return specs.GetSize() - initial_count; +ObjectFileSP ObjectFile::FindPlugin(const lldb::ModuleSP &module_sp, + const ProcessSP &process_sp, + lldb::addr_t header_addr, + DataBufferSP &data_sp) { + ObjectFileSP object_file_sp; + + if (module_sp) { + Timer scoped_timer(LLVM_PRETTY_FUNCTION, "ObjectFile::FindPlugin (module = " + "%s, process = %p, header_addr = " + "0x%" PRIx64 ")", + module_sp->GetFileSpec().GetPath().c_str(), + static_cast<void *>(process_sp.get()), header_addr); + uint32_t idx; + + // Check if this is a normal object file by iterating through + // all object file plugin instances. + ObjectFileCreateMemoryInstance create_callback; + for (idx = 0; + (create_callback = + PluginManager::GetObjectFileCreateMemoryCallbackAtIndex(idx)) != + nullptr; + ++idx) { + object_file_sp.reset( + create_callback(module_sp, data_sp, process_sp, header_addr)); + if (object_file_sp.get()) + return object_file_sp; } + } - // Try the ObjectContainer plug-ins - for (i = 0; (callback = PluginManager::GetObjectContainerGetModuleSpecificationsCallbackAtIndex(i)) != nullptr; ++i) - { - if (callback (file, data_sp, data_offset, file_offset, file_size, specs) > 0) - return specs.GetSize() - initial_count; - } - return 0; + // We didn't find it, so clear our shared pointer in case it + // contains anything and return an empty shared pointer + object_file_sp.reset(); + return object_file_sp; } -ObjectFile::ObjectFile (const lldb::ModuleSP &module_sp, - const FileSpec *file_spec_ptr, - lldb::offset_t file_offset, - lldb::offset_t length, - const lldb::DataBufferSP& data_sp, - lldb::offset_t data_offset) : - ModuleChild (module_sp), - m_file (), // This file could be different from the original module's file - m_type (eTypeInvalid), - m_strata (eStrataInvalid), - m_file_offset (file_offset), - m_length (length), - m_data (), - m_unwind_table (*this), - m_process_wp(), - m_memory_addr (LLDB_INVALID_ADDRESS), - m_sections_ap(), - m_symtab_ap (), - m_synthetic_symbol_idx (0) -{ - if (file_spec_ptr) - m_file = *file_spec_ptr; - if (data_sp) - m_data.SetData (data_sp, data_offset, length); - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT)); - if (log) - log->Printf ("%p ObjectFile::ObjectFile() module = %p (%s), file = %s, file_offset = 0x%8.8" PRIx64 ", size = %" PRIu64, - static_cast<void*>(this), - static_cast<void*>(module_sp.get()), - module_sp->GetSpecificationDescription().c_str(), - m_file ? m_file.GetPath().c_str() : "<NULL>", - m_file_offset, m_length); +size_t ObjectFile::GetModuleSpecifications(const FileSpec &file, + lldb::offset_t file_offset, + lldb::offset_t file_size, + ModuleSpecList &specs) { + DataBufferSP data_sp(file.ReadFileContents(file_offset, 512)); + if (data_sp) { + if (file_size == 0) { + const lldb::offset_t actual_file_size = file.GetByteSize(); + if (actual_file_size > file_offset) + file_size = actual_file_size - file_offset; + } + return ObjectFile::GetModuleSpecifications(file, // file spec + data_sp, // data bytes + 0, // data offset + file_offset, // file offset + file_size, // file length + specs); + } + return 0; } - -ObjectFile::ObjectFile (const lldb::ModuleSP &module_sp, - const ProcessSP &process_sp, - lldb::addr_t header_addr, - DataBufferSP& header_data_sp) : - ModuleChild (module_sp), - m_file (), - m_type (eTypeInvalid), - m_strata (eStrataInvalid), - m_file_offset (0), - m_length (0), - m_data (), - m_unwind_table (*this), - m_process_wp (process_sp), - m_memory_addr (header_addr), - m_sections_ap(), - m_symtab_ap (), - m_synthetic_symbol_idx (0) -{ - if (header_data_sp) - m_data.SetData (header_data_sp, 0, header_data_sp->GetByteSize()); - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT)); - if (log) - log->Printf ("%p ObjectFile::ObjectFile() module = %p (%s), process = %p, header_addr = 0x%" PRIx64, - static_cast<void*>(this), - static_cast<void*>(module_sp.get()), - module_sp->GetSpecificationDescription().c_str(), - static_cast<void*>(process_sp.get()), m_memory_addr); +size_t ObjectFile::GetModuleSpecifications( + const lldb_private::FileSpec &file, lldb::DataBufferSP &data_sp, + lldb::offset_t data_offset, lldb::offset_t file_offset, + lldb::offset_t file_size, lldb_private::ModuleSpecList &specs) { + const size_t initial_count = specs.GetSize(); + ObjectFileGetModuleSpecifications callback; + uint32_t i; + // Try the ObjectFile plug-ins + for (i = 0; + (callback = + PluginManager::GetObjectFileGetModuleSpecificationsCallbackAtIndex( + i)) != nullptr; + ++i) { + if (callback(file, data_sp, data_offset, file_offset, file_size, specs) > 0) + return specs.GetSize() - initial_count; + } + + // Try the ObjectContainer plug-ins + for (i = 0; + (callback = PluginManager:: + GetObjectContainerGetModuleSpecificationsCallbackAtIndex(i)) != + nullptr; + ++i) { + if (callback(file, data_sp, data_offset, file_offset, file_size, specs) > 0) + return specs.GetSize() - initial_count; + } + return 0; } +ObjectFile::ObjectFile(const lldb::ModuleSP &module_sp, + const FileSpec *file_spec_ptr, + lldb::offset_t file_offset, lldb::offset_t length, + const lldb::DataBufferSP &data_sp, + lldb::offset_t data_offset) + : ModuleChild(module_sp), + m_file(), // This file could be different from the original module's file + m_type(eTypeInvalid), m_strata(eStrataInvalid), + m_file_offset(file_offset), m_length(length), m_data(), + m_unwind_table(*this), m_process_wp(), + m_memory_addr(LLDB_INVALID_ADDRESS), m_sections_ap(), m_symtab_ap(), + m_synthetic_symbol_idx(0) { + if (file_spec_ptr) + m_file = *file_spec_ptr; + if (data_sp) + m_data.SetData(data_sp, data_offset, length); + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_OBJECT)); + if (log) + log->Printf("%p ObjectFile::ObjectFile() module = %p (%s), file = %s, " + "file_offset = 0x%8.8" PRIx64 ", size = %" PRIu64, + static_cast<void *>(this), static_cast<void *>(module_sp.get()), + module_sp->GetSpecificationDescription().c_str(), + m_file ? m_file.GetPath().c_str() : "<NULL>", m_file_offset, + m_length); +} -ObjectFile::~ObjectFile() -{ - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT)); - if (log) - log->Printf ("%p ObjectFile::~ObjectFile ()\n", - static_cast<void*>(this)); +ObjectFile::ObjectFile(const lldb::ModuleSP &module_sp, + const ProcessSP &process_sp, lldb::addr_t header_addr, + DataBufferSP &header_data_sp) + : ModuleChild(module_sp), m_file(), m_type(eTypeInvalid), + m_strata(eStrataInvalid), m_file_offset(0), m_length(0), m_data(), + m_unwind_table(*this), m_process_wp(process_sp), + m_memory_addr(header_addr), m_sections_ap(), m_symtab_ap(), + m_synthetic_symbol_idx(0) { + if (header_data_sp) + m_data.SetData(header_data_sp, 0, header_data_sp->GetByteSize()); + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_OBJECT)); + if (log) + log->Printf("%p ObjectFile::ObjectFile() module = %p (%s), process = %p, " + "header_addr = 0x%" PRIx64, + static_cast<void *>(this), static_cast<void *>(module_sp.get()), + module_sp->GetSpecificationDescription().c_str(), + static_cast<void *>(process_sp.get()), m_memory_addr); } -bool -ObjectFile::SetModulesArchitecture (const ArchSpec &new_arch) -{ - ModuleSP module_sp (GetModule()); - if (module_sp) - return module_sp->SetArchitecture (new_arch); - return false; +ObjectFile::~ObjectFile() { + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_OBJECT)); + if (log) + log->Printf("%p ObjectFile::~ObjectFile ()\n", static_cast<void *>(this)); } -AddressClass -ObjectFile::GetAddressClass (addr_t file_addr) -{ - Symtab *symtab = GetSymtab(); - if (symtab) - { - Symbol *symbol = symtab->FindSymbolContainingFileAddress(file_addr); - if (symbol) - { - if (symbol->ValueIsAddress()) - { - const SectionSP section_sp (symbol->GetAddressRef().GetSection()); - if (section_sp) - { - const SectionType section_type = section_sp->GetType(); - switch (section_type) - { - case eSectionTypeInvalid: - return eAddressClassUnknown; - case eSectionTypeCode: - return eAddressClassCode; - case eSectionTypeContainer: - return eAddressClassUnknown; - case eSectionTypeData: - case eSectionTypeDataCString: - case eSectionTypeDataCStringPointers: - case eSectionTypeDataSymbolAddress: - case eSectionTypeData4: - case eSectionTypeData8: - case eSectionTypeData16: - case eSectionTypeDataPointers: - case eSectionTypeZeroFill: - case eSectionTypeDataObjCMessageRefs: - case eSectionTypeDataObjCCFStrings: - case eSectionTypeGoSymtab: - return eAddressClassData; - case eSectionTypeDebug: - case eSectionTypeDWARFDebugAbbrev: - case eSectionTypeDWARFDebugAddr: - case eSectionTypeDWARFDebugAranges: - case eSectionTypeDWARFDebugFrame: - case eSectionTypeDWARFDebugInfo: - case eSectionTypeDWARFDebugLine: - case eSectionTypeDWARFDebugLoc: - case eSectionTypeDWARFDebugMacInfo: - case eSectionTypeDWARFDebugMacro: - case eSectionTypeDWARFDebugPubNames: - case eSectionTypeDWARFDebugPubTypes: - case eSectionTypeDWARFDebugRanges: - case eSectionTypeDWARFDebugStr: - case eSectionTypeDWARFDebugStrOffsets: - case eSectionTypeDWARFAppleNames: - case eSectionTypeDWARFAppleTypes: - case eSectionTypeDWARFAppleNamespaces: - case eSectionTypeDWARFAppleObjC: - return eAddressClassDebug; - case eSectionTypeEHFrame: - case eSectionTypeARMexidx: - case eSectionTypeARMextab: - case eSectionTypeCompactUnwind: - return eAddressClassRuntime; - case eSectionTypeELFSymbolTable: - case eSectionTypeELFDynamicSymbols: - case eSectionTypeELFRelocationEntries: - case eSectionTypeELFDynamicLinkInfo: - case eSectionTypeOther: - return eAddressClassUnknown; - case eSectionTypeAbsoluteAddress: - // In case of absolute sections decide the address class based on the symbol - // type because the section type isn't specify if it is a code or a data - // section. - break; - } - } - } +bool ObjectFile::SetModulesArchitecture(const ArchSpec &new_arch) { + ModuleSP module_sp(GetModule()); + if (module_sp) + return module_sp->SetArchitecture(new_arch); + return false; +} - const SymbolType symbol_type = symbol->GetType(); - switch (symbol_type) - { - case eSymbolTypeAny: return eAddressClassUnknown; - case eSymbolTypeAbsolute: return eAddressClassUnknown; - case eSymbolTypeCode: return eAddressClassCode; - case eSymbolTypeTrampoline: return eAddressClassCode; - case eSymbolTypeResolver: return eAddressClassCode; - case eSymbolTypeData: return eAddressClassData; - case eSymbolTypeRuntime: return eAddressClassRuntime; - case eSymbolTypeException: return eAddressClassRuntime; - case eSymbolTypeSourceFile: return eAddressClassDebug; - case eSymbolTypeHeaderFile: return eAddressClassDebug; - case eSymbolTypeObjectFile: return eAddressClassDebug; - case eSymbolTypeCommonBlock: return eAddressClassDebug; - case eSymbolTypeBlock: return eAddressClassDebug; - case eSymbolTypeLocal: return eAddressClassData; - case eSymbolTypeParam: return eAddressClassData; - case eSymbolTypeVariable: return eAddressClassData; - case eSymbolTypeVariableType: return eAddressClassDebug; - case eSymbolTypeLineEntry: return eAddressClassDebug; - case eSymbolTypeLineHeader: return eAddressClassDebug; - case eSymbolTypeScopeBegin: return eAddressClassDebug; - case eSymbolTypeScopeEnd: return eAddressClassDebug; - case eSymbolTypeAdditional: return eAddressClassUnknown; - case eSymbolTypeCompiler: return eAddressClassDebug; - case eSymbolTypeInstrumentation:return eAddressClassDebug; - case eSymbolTypeUndefined: return eAddressClassUnknown; - case eSymbolTypeObjCClass: return eAddressClassRuntime; - case eSymbolTypeObjCMetaClass: return eAddressClassRuntime; - case eSymbolTypeObjCIVar: return eAddressClassRuntime; - case eSymbolTypeReExported: return eAddressClassRuntime; - } +AddressClass ObjectFile::GetAddressClass(addr_t file_addr) { + Symtab *symtab = GetSymtab(); + if (symtab) { + Symbol *symbol = symtab->FindSymbolContainingFileAddress(file_addr); + if (symbol) { + if (symbol->ValueIsAddress()) { + const SectionSP section_sp(symbol->GetAddressRef().GetSection()); + if (section_sp) { + const SectionType section_type = section_sp->GetType(); + switch (section_type) { + case eSectionTypeInvalid: + return eAddressClassUnknown; + case eSectionTypeCode: + return eAddressClassCode; + case eSectionTypeContainer: + return eAddressClassUnknown; + case eSectionTypeData: + case eSectionTypeDataCString: + case eSectionTypeDataCStringPointers: + case eSectionTypeDataSymbolAddress: + case eSectionTypeData4: + case eSectionTypeData8: + case eSectionTypeData16: + case eSectionTypeDataPointers: + case eSectionTypeZeroFill: + case eSectionTypeDataObjCMessageRefs: + case eSectionTypeDataObjCCFStrings: + case eSectionTypeGoSymtab: + return eAddressClassData; + case eSectionTypeDebug: + case eSectionTypeDWARFDebugAbbrev: + case eSectionTypeDWARFDebugAddr: + case eSectionTypeDWARFDebugAranges: + case eSectionTypeDWARFDebugFrame: + case eSectionTypeDWARFDebugInfo: + case eSectionTypeDWARFDebugLine: + case eSectionTypeDWARFDebugLoc: + case eSectionTypeDWARFDebugMacInfo: + case eSectionTypeDWARFDebugMacro: + case eSectionTypeDWARFDebugPubNames: + case eSectionTypeDWARFDebugPubTypes: + case eSectionTypeDWARFDebugRanges: + case eSectionTypeDWARFDebugStr: + case eSectionTypeDWARFDebugStrOffsets: + case eSectionTypeDWARFAppleNames: + case eSectionTypeDWARFAppleTypes: + case eSectionTypeDWARFAppleNamespaces: + case eSectionTypeDWARFAppleObjC: + return eAddressClassDebug; + case eSectionTypeEHFrame: + case eSectionTypeARMexidx: + case eSectionTypeARMextab: + case eSectionTypeCompactUnwind: + return eAddressClassRuntime; + case eSectionTypeELFSymbolTable: + case eSectionTypeELFDynamicSymbols: + case eSectionTypeELFRelocationEntries: + case eSectionTypeELFDynamicLinkInfo: + case eSectionTypeOther: + return eAddressClassUnknown; + case eSectionTypeAbsoluteAddress: + // In case of absolute sections decide the address class based on + // the symbol + // type because the section type isn't specify if it is a code or a + // data + // section. + break; + } } + } + + const SymbolType symbol_type = symbol->GetType(); + switch (symbol_type) { + case eSymbolTypeAny: + return eAddressClassUnknown; + case eSymbolTypeAbsolute: + return eAddressClassUnknown; + case eSymbolTypeCode: + return eAddressClassCode; + case eSymbolTypeTrampoline: + return eAddressClassCode; + case eSymbolTypeResolver: + return eAddressClassCode; + case eSymbolTypeData: + return eAddressClassData; + case eSymbolTypeRuntime: + return eAddressClassRuntime; + case eSymbolTypeException: + return eAddressClassRuntime; + case eSymbolTypeSourceFile: + return eAddressClassDebug; + case eSymbolTypeHeaderFile: + return eAddressClassDebug; + case eSymbolTypeObjectFile: + return eAddressClassDebug; + case eSymbolTypeCommonBlock: + return eAddressClassDebug; + case eSymbolTypeBlock: + return eAddressClassDebug; + case eSymbolTypeLocal: + return eAddressClassData; + case eSymbolTypeParam: + return eAddressClassData; + case eSymbolTypeVariable: + return eAddressClassData; + case eSymbolTypeVariableType: + return eAddressClassDebug; + case eSymbolTypeLineEntry: + return eAddressClassDebug; + case eSymbolTypeLineHeader: + return eAddressClassDebug; + case eSymbolTypeScopeBegin: + return eAddressClassDebug; + case eSymbolTypeScopeEnd: + return eAddressClassDebug; + case eSymbolTypeAdditional: + return eAddressClassUnknown; + case eSymbolTypeCompiler: + return eAddressClassDebug; + case eSymbolTypeInstrumentation: + return eAddressClassDebug; + case eSymbolTypeUndefined: + return eAddressClassUnknown; + case eSymbolTypeObjCClass: + return eAddressClassRuntime; + case eSymbolTypeObjCMetaClass: + return eAddressClassRuntime; + case eSymbolTypeObjCIVar: + return eAddressClassRuntime; + case eSymbolTypeReExported: + return eAddressClassRuntime; + } } - return eAddressClassUnknown; + } + return eAddressClassUnknown; } -DataBufferSP -ObjectFile::ReadMemory (const ProcessSP &process_sp, lldb::addr_t addr, size_t byte_size) -{ - DataBufferSP data_sp; - if (process_sp) - { - std::unique_ptr<DataBufferHeap> data_ap (new DataBufferHeap (byte_size, 0)); - Error error; - const size_t bytes_read = process_sp->ReadMemory (addr, - data_ap->GetBytes(), - data_ap->GetByteSize(), - error); - if (bytes_read == byte_size) - data_sp.reset (data_ap.release()); - } - return data_sp; +DataBufferSP ObjectFile::ReadMemory(const ProcessSP &process_sp, + lldb::addr_t addr, size_t byte_size) { + DataBufferSP data_sp; + if (process_sp) { + std::unique_ptr<DataBufferHeap> data_ap(new DataBufferHeap(byte_size, 0)); + Error error; + const size_t bytes_read = process_sp->ReadMemory( + addr, data_ap->GetBytes(), data_ap->GetByteSize(), error); + if (bytes_read == byte_size) + data_sp.reset(data_ap.release()); + } + return data_sp; } -size_t -ObjectFile::GetData (lldb::offset_t offset, size_t length, DataExtractor &data) const -{ - // The entire file has already been mmap'ed into m_data, so just copy from there - // as the back mmap buffer will be shared with shared pointers. - return data.SetData (m_data, offset, length); +size_t ObjectFile::GetData(lldb::offset_t offset, size_t length, + DataExtractor &data) const { + // The entire file has already been mmap'ed into m_data, so just copy from + // there + // as the back mmap buffer will be shared with shared pointers. + return data.SetData(m_data, offset, length); } -size_t -ObjectFile::CopyData (lldb::offset_t offset, size_t length, void *dst) const -{ - // The entire file has already been mmap'ed into m_data, so just copy from there - // Note that the data remains in target byte order. - return m_data.CopyData (offset, length, dst); +size_t ObjectFile::CopyData(lldb::offset_t offset, size_t length, + void *dst) const { + // The entire file has already been mmap'ed into m_data, so just copy from + // there + // Note that the data remains in target byte order. + return m_data.CopyData(offset, length, dst); } - -size_t -ObjectFile::ReadSectionData (const Section *section, lldb::offset_t section_offset, void *dst, size_t dst_len) const -{ - assert(section); - section_offset *= section->GetTargetByteSize(); - - // If some other objectfile owns this data, pass this to them. - if (section->GetObjectFile() != this) - return section->GetObjectFile()->ReadSectionData (section, section_offset, dst, dst_len); - - if (IsInMemory()) - { - ProcessSP process_sp (m_process_wp.lock()); - if (process_sp) - { - Error error; - const addr_t base_load_addr = section->GetLoadBaseAddress (&process_sp->GetTarget()); - if (base_load_addr != LLDB_INVALID_ADDRESS) - return process_sp->ReadMemory (base_load_addr + section_offset, dst, dst_len, error); - } +size_t ObjectFile::ReadSectionData(const Section *section, + lldb::offset_t section_offset, void *dst, + size_t dst_len) const { + assert(section); + section_offset *= section->GetTargetByteSize(); + + // If some other objectfile owns this data, pass this to them. + if (section->GetObjectFile() != this) + return section->GetObjectFile()->ReadSectionData(section, section_offset, + dst, dst_len); + + if (IsInMemory()) { + ProcessSP process_sp(m_process_wp.lock()); + if (process_sp) { + Error error; + const addr_t base_load_addr = + section->GetLoadBaseAddress(&process_sp->GetTarget()); + if (base_load_addr != LLDB_INVALID_ADDRESS) + return process_sp->ReadMemory(base_load_addr + section_offset, dst, + dst_len, error); } - else - { - const lldb::offset_t section_file_size = section->GetFileSize(); - if (section_offset < section_file_size) - { - const size_t section_bytes_left = section_file_size - section_offset; - size_t section_dst_len = dst_len; - if (section_dst_len > section_bytes_left) - section_dst_len = section_bytes_left; - return CopyData (section->GetFileOffset() + section_offset, section_dst_len, dst); - } - else - { - if (section->GetType() == eSectionTypeZeroFill) - { - const uint64_t section_size = section->GetByteSize(); - const uint64_t section_bytes_left = section_size - section_offset; - uint64_t section_dst_len = dst_len; - if (section_dst_len > section_bytes_left) - section_dst_len = section_bytes_left; - memset(dst, 0, section_dst_len); - return section_dst_len; - } - } + } else { + const lldb::offset_t section_file_size = section->GetFileSize(); + if (section_offset < section_file_size) { + const size_t section_bytes_left = section_file_size - section_offset; + size_t section_dst_len = dst_len; + if (section_dst_len > section_bytes_left) + section_dst_len = section_bytes_left; + return CopyData(section->GetFileOffset() + section_offset, + section_dst_len, dst); + } else { + if (section->GetType() == eSectionTypeZeroFill) { + const uint64_t section_size = section->GetByteSize(); + const uint64_t section_bytes_left = section_size - section_offset; + uint64_t section_dst_len = dst_len; + if (section_dst_len > section_bytes_left) + section_dst_len = section_bytes_left; + memset(dst, 0, section_dst_len); + return section_dst_len; + } } - return 0; + } + return 0; } //---------------------------------------------------------------------- // Get the section data the file on disk //---------------------------------------------------------------------- -size_t -ObjectFile::ReadSectionData (const Section *section, DataExtractor& section_data) const -{ - // If some other objectfile owns this data, pass this to them. - if (section->GetObjectFile() != this) - return section->GetObjectFile()->ReadSectionData (section, section_data); - - if (IsInMemory()) - { - ProcessSP process_sp (m_process_wp.lock()); - if (process_sp) - { - const addr_t base_load_addr = section->GetLoadBaseAddress (&process_sp->GetTarget()); - if (base_load_addr != LLDB_INVALID_ADDRESS) - { - DataBufferSP data_sp (ReadMemory (process_sp, base_load_addr, section->GetByteSize())); - if (data_sp) - { - section_data.SetData (data_sp, 0, data_sp->GetByteSize()); - section_data.SetByteOrder (process_sp->GetByteOrder()); - section_data.SetAddressByteSize (process_sp->GetAddressByteSize()); - return section_data.GetByteSize(); - } - } +size_t ObjectFile::ReadSectionData(const Section *section, + DataExtractor §ion_data) const { + // If some other objectfile owns this data, pass this to them. + if (section->GetObjectFile() != this) + return section->GetObjectFile()->ReadSectionData(section, section_data); + + if (IsInMemory()) { + ProcessSP process_sp(m_process_wp.lock()); + if (process_sp) { + const addr_t base_load_addr = + section->GetLoadBaseAddress(&process_sp->GetTarget()); + if (base_load_addr != LLDB_INVALID_ADDRESS) { + DataBufferSP data_sp( + ReadMemory(process_sp, base_load_addr, section->GetByteSize())); + if (data_sp) { + section_data.SetData(data_sp, 0, data_sp->GetByteSize()); + section_data.SetByteOrder(process_sp->GetByteOrder()); + section_data.SetAddressByteSize(process_sp->GetAddressByteSize()); + return section_data.GetByteSize(); } - return GetData(section->GetFileOffset(), section->GetFileSize(), section_data); - } - else - { - // The object file now contains a full mmap'ed copy of the object file data, so just use this - return MemoryMapSectionData (section, section_data); + } } + return GetData(section->GetFileOffset(), section->GetFileSize(), + section_data); + } else { + // The object file now contains a full mmap'ed copy of the object file data, + // so just use this + return MemoryMapSectionData(section, section_data); + } } -size_t -ObjectFile::MemoryMapSectionData (const Section *section, DataExtractor& section_data) const -{ - // If some other objectfile owns this data, pass this to them. - if (section->GetObjectFile() != this) - return section->GetObjectFile()->MemoryMapSectionData (section, section_data); - - if (IsInMemory()) - { - return ReadSectionData (section, section_data); - } - else - { - // The object file now contains a full mmap'ed copy of the object file data, so just use this - return GetData(section->GetFileOffset(), section->GetFileSize(), section_data); - } +size_t ObjectFile::MemoryMapSectionData(const Section *section, + DataExtractor §ion_data) const { + // If some other objectfile owns this data, pass this to them. + if (section->GetObjectFile() != this) + return section->GetObjectFile()->MemoryMapSectionData(section, + section_data); + + if (IsInMemory()) { + return ReadSectionData(section, section_data); + } else { + // The object file now contains a full mmap'ed copy of the object file data, + // so just use this + return GetData(section->GetFileOffset(), section->GetFileSize(), + section_data); + } } - -bool -ObjectFile::SplitArchivePathWithObject (const char *path_with_object, FileSpec &archive_file, ConstString &archive_object, bool must_exist) -{ - RegularExpression g_object_regex("(.*)\\(([^\\)]+)\\)$"); - RegularExpression::Match regex_match(2); - if (g_object_regex.Execute (path_with_object, ®ex_match)) - { - std::string path; - std::string obj; - if (regex_match.GetMatchAtIndex (path_with_object, 1, path) && - regex_match.GetMatchAtIndex (path_with_object, 2, obj)) - { - archive_file.SetFile (path.c_str(), false); - archive_object.SetCString(obj.c_str()); - if (must_exist && !archive_file.Exists()) - return false; - return true; - } +bool ObjectFile::SplitArchivePathWithObject(const char *path_with_object, + FileSpec &archive_file, + ConstString &archive_object, + bool must_exist) { + RegularExpression g_object_regex("(.*)\\(([^\\)]+)\\)$"); + RegularExpression::Match regex_match(2); + if (g_object_regex.Execute(path_with_object, ®ex_match)) { + std::string path; + std::string obj; + if (regex_match.GetMatchAtIndex(path_with_object, 1, path) && + regex_match.GetMatchAtIndex(path_with_object, 2, obj)) { + archive_file.SetFile(path.c_str(), false); + archive_object.SetCString(obj.c_str()); + if (must_exist && !archive_file.Exists()) + return false; + return true; } - return false; + } + return false; } -void -ObjectFile::ClearSymtab () -{ - ModuleSP module_sp(GetModule()); - if (module_sp) - { - std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex()); - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT)); - if (log) - log->Printf ("%p ObjectFile::ClearSymtab () symtab = %p", - static_cast<void*>(this), - static_cast<void*>(m_symtab_ap.get())); - m_symtab_ap.reset(); - } +void ObjectFile::ClearSymtab() { + ModuleSP module_sp(GetModule()); + if (module_sp) { + std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex()); + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_OBJECT)); + if (log) + log->Printf("%p ObjectFile::ClearSymtab () symtab = %p", + static_cast<void *>(this), + static_cast<void *>(m_symtab_ap.get())); + m_symtab_ap.reset(); + } } -SectionList * -ObjectFile::GetSectionList(bool update_module_section_list) -{ - if (m_sections_ap.get() == nullptr) - { - if (update_module_section_list) - { - ModuleSP module_sp(GetModule()); - if (module_sp) - { - std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex()); - CreateSections(*module_sp->GetUnifiedSectionList()); - } - } - else - { - SectionList unified_section_list; - CreateSections(unified_section_list); - } +SectionList *ObjectFile::GetSectionList(bool update_module_section_list) { + if (m_sections_ap.get() == nullptr) { + if (update_module_section_list) { + ModuleSP module_sp(GetModule()); + if (module_sp) { + std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex()); + CreateSections(*module_sp->GetUnifiedSectionList()); + } + } else { + SectionList unified_section_list; + CreateSections(unified_section_list); } - return m_sections_ap.get(); + } + return m_sections_ap.get(); } lldb::SymbolType -ObjectFile::GetSymbolTypeFromName (llvm::StringRef name, - lldb::SymbolType symbol_type_hint) -{ - if (!name.empty()) - { - if (name.startswith("_OBJC_")) - { - // ObjC - if (name.startswith("_OBJC_CLASS_$_")) - return lldb::eSymbolTypeObjCClass; - if (name.startswith("_OBJC_METACLASS_$_")) - return lldb::eSymbolTypeObjCMetaClass; - if (name.startswith("_OBJC_IVAR_$_")) - return lldb::eSymbolTypeObjCIVar; - } - else if (name.startswith(".objc_class_name_")) - { - // ObjC v1 - return lldb::eSymbolTypeObjCClass; - } +ObjectFile::GetSymbolTypeFromName(llvm::StringRef name, + lldb::SymbolType symbol_type_hint) { + if (!name.empty()) { + if (name.startswith("_OBJC_")) { + // ObjC + if (name.startswith("_OBJC_CLASS_$_")) + return lldb::eSymbolTypeObjCClass; + if (name.startswith("_OBJC_METACLASS_$_")) + return lldb::eSymbolTypeObjCMetaClass; + if (name.startswith("_OBJC_IVAR_$_")) + return lldb::eSymbolTypeObjCIVar; + } else if (name.startswith(".objc_class_name_")) { + // ObjC v1 + return lldb::eSymbolTypeObjCClass; } - return symbol_type_hint; + } + return symbol_type_hint; } -ConstString -ObjectFile::GetNextSyntheticSymbolName() -{ - StreamString ss; - ConstString file_name = GetModule()->GetFileSpec().GetFilename(); - ss.Printf("___lldb_unnamed_symbol%u$$%s", ++m_synthetic_symbol_idx, file_name.GetCString()); - return ConstString(ss.GetData()); +ConstString ObjectFile::GetNextSyntheticSymbolName() { + StreamString ss; + ConstString file_name = GetModule()->GetFileSpec().GetFilename(); + ss.Printf("___lldb_unnamed_symbol%u$$%s", ++m_synthetic_symbol_idx, + file_name.GetCString()); + return ConstString(ss.GetData()); } - diff --git a/lldb/source/Symbol/Symbol.cpp b/lldb/source/Symbol/Symbol.cpp index 1fa792c9729..623930c1d53 100644 --- a/lldb/source/Symbol/Symbol.cpp +++ b/lldb/source/Symbol/Symbol.cpp @@ -13,453 +13,338 @@ #include "lldb/Core/ModuleSpec.h" #include "lldb/Core/Section.h" #include "lldb/Core/Stream.h" +#include "lldb/Symbol/Function.h" #include "lldb/Symbol/ObjectFile.h" +#include "lldb/Symbol/SymbolVendor.h" #include "lldb/Symbol/Symtab.h" -#include "lldb/Symbol/Function.h" #include "lldb/Target/Process.h" #include "lldb/Target/Target.h" -#include "lldb/Symbol/SymbolVendor.h" using namespace lldb; using namespace lldb_private; - -Symbol::Symbol() : - SymbolContextScope (), - m_uid (UINT32_MAX), - m_type_data (0), - m_type_data_resolved (false), - m_is_synthetic (false), - m_is_debug (false), - m_is_external (false), - m_size_is_sibling (false), - m_size_is_synthesized (false), - m_size_is_valid (false), - m_demangled_is_synthesized (false), - m_contains_linker_annotations (false), - m_type (eSymbolTypeInvalid), - m_mangled (), - m_addr_range (), - m_flags () -{ -} - -Symbol::Symbol -( - uint32_t symID, - const char *name, - bool name_is_mangled, - SymbolType type, - bool external, - bool is_debug, - bool is_trampoline, - bool is_artificial, - const lldb::SectionSP §ion_sp, - addr_t offset, - addr_t size, - bool size_is_valid, - bool contains_linker_annotations, - uint32_t flags -) : - SymbolContextScope (), - m_uid (symID), - m_type_data (0), - m_type_data_resolved (false), - m_is_synthetic (is_artificial), - m_is_debug (is_debug), - m_is_external (external), - m_size_is_sibling (false), - m_size_is_synthesized (false), - m_size_is_valid (size_is_valid || size > 0), - m_demangled_is_synthesized (false), - m_contains_linker_annotations (contains_linker_annotations), - m_type (type), - m_mangled (ConstString(name), name_is_mangled), - m_addr_range (section_sp, offset, size), - m_flags (flags) -{ -} - -Symbol::Symbol -( - uint32_t symID, - const Mangled &mangled, - SymbolType type, - bool external, - bool is_debug, - bool is_trampoline, - bool is_artificial, - const AddressRange &range, - bool size_is_valid, - bool contains_linker_annotations, - uint32_t flags -) : - SymbolContextScope (), - m_uid (symID), - m_type_data (0), - m_type_data_resolved (false), - m_is_synthetic (is_artificial), - m_is_debug (is_debug), - m_is_external (external), - m_size_is_sibling (false), - m_size_is_synthesized (false), - m_size_is_valid (size_is_valid || range.GetByteSize() > 0), - m_demangled_is_synthesized (false), - m_contains_linker_annotations (contains_linker_annotations), - m_type (type), - m_mangled (mangled), - m_addr_range (range), - m_flags (flags) -{ -} - -Symbol::Symbol(const Symbol& rhs): - SymbolContextScope (rhs), - m_uid (rhs.m_uid), - m_type_data (rhs.m_type_data), - m_type_data_resolved (rhs.m_type_data_resolved), - m_is_synthetic (rhs.m_is_synthetic), - m_is_debug (rhs.m_is_debug), - m_is_external (rhs.m_is_external), - m_size_is_sibling (rhs.m_size_is_sibling), - m_size_is_synthesized (false), - m_size_is_valid (rhs.m_size_is_valid), - m_demangled_is_synthesized (rhs.m_demangled_is_synthesized), - m_contains_linker_annotations (rhs.m_contains_linker_annotations), - m_type (rhs.m_type), - m_mangled (rhs.m_mangled), - m_addr_range (rhs.m_addr_range), - m_flags (rhs.m_flags) -{ -} - -const Symbol& -Symbol::operator= (const Symbol& rhs) -{ - if (this != &rhs) - { - SymbolContextScope::operator= (rhs); - m_uid = rhs.m_uid; - m_type_data = rhs.m_type_data; - m_type_data_resolved = rhs.m_type_data_resolved; - m_is_synthetic = rhs.m_is_synthetic; - m_is_debug = rhs.m_is_debug; - m_is_external = rhs.m_is_external; - m_size_is_sibling = rhs.m_size_is_sibling; - m_size_is_synthesized = rhs.m_size_is_sibling; - m_size_is_valid = rhs.m_size_is_valid; - m_demangled_is_synthesized = rhs.m_demangled_is_synthesized; - m_contains_linker_annotations = rhs.m_contains_linker_annotations; - m_type = rhs.m_type; - m_mangled = rhs.m_mangled; - m_addr_range = rhs.m_addr_range; - m_flags = rhs.m_flags; - } - return *this; -} - -void -Symbol::Clear() -{ - m_uid = UINT32_MAX; - m_mangled.Clear(); - m_type_data = 0; - m_type_data_resolved = false; - m_is_synthetic = false; - m_is_debug = false; - m_is_external = false; - m_size_is_sibling = false; - m_size_is_synthesized = false; - m_size_is_valid = false; - m_demangled_is_synthesized = false; - m_contains_linker_annotations = false; - m_type = eSymbolTypeInvalid; - m_flags = 0; - m_addr_range.Clear(); -} - -bool -Symbol::ValueIsAddress() const -{ - return m_addr_range.GetBaseAddress().GetSection().get() != nullptr; -} - -ConstString -Symbol::GetDisplayName () const -{ - if (!m_mangled) - return ConstString(); - return m_mangled.GetDisplayDemangledName(GetLanguage()); -} - -ConstString -Symbol::GetReExportedSymbolName() const -{ - if (m_type == eSymbolTypeReExported) - { - // For eSymbolTypeReExported, the "const char *" from a ConstString - // is used as the offset in the address range base address. We can - // then make this back into a string that is the re-exported name. - intptr_t str_ptr = m_addr_range.GetBaseAddress().GetOffset(); - if (str_ptr != 0) - return ConstString((const char *)str_ptr); - else - return GetName(); - } +Symbol::Symbol() + : SymbolContextScope(), m_uid(UINT32_MAX), m_type_data(0), + m_type_data_resolved(false), m_is_synthetic(false), m_is_debug(false), + m_is_external(false), m_size_is_sibling(false), + m_size_is_synthesized(false), m_size_is_valid(false), + m_demangled_is_synthesized(false), m_contains_linker_annotations(false), + m_type(eSymbolTypeInvalid), m_mangled(), m_addr_range(), m_flags() {} + +Symbol::Symbol(uint32_t symID, const char *name, bool name_is_mangled, + SymbolType type, bool external, bool is_debug, + bool is_trampoline, bool is_artificial, + const lldb::SectionSP §ion_sp, addr_t offset, addr_t size, + bool size_is_valid, bool contains_linker_annotations, + uint32_t flags) + : SymbolContextScope(), m_uid(symID), m_type_data(0), + m_type_data_resolved(false), m_is_synthetic(is_artificial), + m_is_debug(is_debug), m_is_external(external), m_size_is_sibling(false), + m_size_is_synthesized(false), m_size_is_valid(size_is_valid || size > 0), + m_demangled_is_synthesized(false), + m_contains_linker_annotations(contains_linker_annotations), m_type(type), + m_mangled(ConstString(name), name_is_mangled), + m_addr_range(section_sp, offset, size), m_flags(flags) {} + +Symbol::Symbol(uint32_t symID, const Mangled &mangled, SymbolType type, + bool external, bool is_debug, bool is_trampoline, + bool is_artificial, const AddressRange &range, + bool size_is_valid, bool contains_linker_annotations, + uint32_t flags) + : SymbolContextScope(), m_uid(symID), m_type_data(0), + m_type_data_resolved(false), m_is_synthetic(is_artificial), + m_is_debug(is_debug), m_is_external(external), m_size_is_sibling(false), + m_size_is_synthesized(false), + m_size_is_valid(size_is_valid || range.GetByteSize() > 0), + m_demangled_is_synthesized(false), + m_contains_linker_annotations(contains_linker_annotations), m_type(type), + m_mangled(mangled), m_addr_range(range), m_flags(flags) {} + +Symbol::Symbol(const Symbol &rhs) + : SymbolContextScope(rhs), m_uid(rhs.m_uid), m_type_data(rhs.m_type_data), + m_type_data_resolved(rhs.m_type_data_resolved), + m_is_synthetic(rhs.m_is_synthetic), m_is_debug(rhs.m_is_debug), + m_is_external(rhs.m_is_external), + m_size_is_sibling(rhs.m_size_is_sibling), m_size_is_synthesized(false), + m_size_is_valid(rhs.m_size_is_valid), + m_demangled_is_synthesized(rhs.m_demangled_is_synthesized), + m_contains_linker_annotations(rhs.m_contains_linker_annotations), + m_type(rhs.m_type), m_mangled(rhs.m_mangled), + m_addr_range(rhs.m_addr_range), m_flags(rhs.m_flags) {} + +const Symbol &Symbol::operator=(const Symbol &rhs) { + if (this != &rhs) { + SymbolContextScope::operator=(rhs); + m_uid = rhs.m_uid; + m_type_data = rhs.m_type_data; + m_type_data_resolved = rhs.m_type_data_resolved; + m_is_synthetic = rhs.m_is_synthetic; + m_is_debug = rhs.m_is_debug; + m_is_external = rhs.m_is_external; + m_size_is_sibling = rhs.m_size_is_sibling; + m_size_is_synthesized = rhs.m_size_is_sibling; + m_size_is_valid = rhs.m_size_is_valid; + m_demangled_is_synthesized = rhs.m_demangled_is_synthesized; + m_contains_linker_annotations = rhs.m_contains_linker_annotations; + m_type = rhs.m_type; + m_mangled = rhs.m_mangled; + m_addr_range = rhs.m_addr_range; + m_flags = rhs.m_flags; + } + return *this; +} + +void Symbol::Clear() { + m_uid = UINT32_MAX; + m_mangled.Clear(); + m_type_data = 0; + m_type_data_resolved = false; + m_is_synthetic = false; + m_is_debug = false; + m_is_external = false; + m_size_is_sibling = false; + m_size_is_synthesized = false; + m_size_is_valid = false; + m_demangled_is_synthesized = false; + m_contains_linker_annotations = false; + m_type = eSymbolTypeInvalid; + m_flags = 0; + m_addr_range.Clear(); +} + +bool Symbol::ValueIsAddress() const { + return m_addr_range.GetBaseAddress().GetSection().get() != nullptr; +} + +ConstString Symbol::GetDisplayName() const { + if (!m_mangled) return ConstString(); + return m_mangled.GetDisplayDemangledName(GetLanguage()); } -FileSpec -Symbol::GetReExportedSymbolSharedLibrary() const -{ - if (m_type == eSymbolTypeReExported) - { - // For eSymbolTypeReExported, the "const char *" from a ConstString - // is used as the offset in the address range base address. We can - // then make this back into a string that is the re-exported name. - intptr_t str_ptr = m_addr_range.GetByteSize(); - if (str_ptr != 0) - return FileSpec((const char *)str_ptr, false); - } - return FileSpec(); -} - -void -Symbol::SetReExportedSymbolName(const ConstString &name) -{ - SetType (eSymbolTypeReExported); +ConstString Symbol::GetReExportedSymbolName() const { + if (m_type == eSymbolTypeReExported) { // For eSymbolTypeReExported, the "const char *" from a ConstString - // is used as the offset in the address range base address. - m_addr_range.GetBaseAddress().SetOffset((uintptr_t)name.GetCString()); -} - -bool -Symbol::SetReExportedSymbolSharedLibrary(const FileSpec &fspec) -{ - if (m_type == eSymbolTypeReExported) - { - // For eSymbolTypeReExported, the "const char *" from a ConstString - // is used as the offset in the address range base address. - m_addr_range.SetByteSize((uintptr_t)ConstString(fspec.GetPath().c_str()).GetCString()); - return true; - } - return false; - -} - -uint32_t -Symbol::GetSiblingIndex() const -{ - return m_size_is_sibling ? m_addr_range.GetByteSize() : UINT32_MAX; + // is used as the offset in the address range base address. We can + // then make this back into a string that is the re-exported name. + intptr_t str_ptr = m_addr_range.GetBaseAddress().GetOffset(); + if (str_ptr != 0) + return ConstString((const char *)str_ptr); + else + return GetName(); + } + return ConstString(); } -bool -Symbol::IsTrampoline () const -{ - return m_type == eSymbolTypeTrampoline; +FileSpec Symbol::GetReExportedSymbolSharedLibrary() const { + if (m_type == eSymbolTypeReExported) { + // For eSymbolTypeReExported, the "const char *" from a ConstString + // is used as the offset in the address range base address. We can + // then make this back into a string that is the re-exported name. + intptr_t str_ptr = m_addr_range.GetByteSize(); + if (str_ptr != 0) + return FileSpec((const char *)str_ptr, false); + } + return FileSpec(); } -bool -Symbol::IsIndirect () const -{ - return m_type == eSymbolTypeResolver; +void Symbol::SetReExportedSymbolName(const ConstString &name) { + SetType(eSymbolTypeReExported); + // For eSymbolTypeReExported, the "const char *" from a ConstString + // is used as the offset in the address range base address. + m_addr_range.GetBaseAddress().SetOffset((uintptr_t)name.GetCString()); } -void -Symbol::GetDescription (Stream *s, lldb::DescriptionLevel level, Target *target) const -{ - s->Printf("id = {0x%8.8x}", m_uid); - - if (m_addr_range.GetBaseAddress().GetSection()) - { - if (ValueIsAddress()) - { - const lldb::addr_t byte_size = GetByteSize(); - if (byte_size > 0) - { - s->PutCString (", range = "); - m_addr_range.Dump(s, target, Address::DumpStyleLoadAddress, Address::DumpStyleFileAddress); - } - else - { - s->PutCString (", address = "); - m_addr_range.GetBaseAddress().Dump(s, target, Address::DumpStyleLoadAddress, Address::DumpStyleFileAddress); - } - } - else - s->Printf (", value = 0x%16.16" PRIx64, m_addr_range.GetBaseAddress().GetOffset()); - } +bool Symbol::SetReExportedSymbolSharedLibrary(const FileSpec &fspec) { + if (m_type == eSymbolTypeReExported) { + // For eSymbolTypeReExported, the "const char *" from a ConstString + // is used as the offset in the address range base address. + m_addr_range.SetByteSize( + (uintptr_t)ConstString(fspec.GetPath().c_str()).GetCString()); + return true; + } + return false; +} + +uint32_t Symbol::GetSiblingIndex() const { + return m_size_is_sibling ? m_addr_range.GetByteSize() : UINT32_MAX; +} + +bool Symbol::IsTrampoline() const { return m_type == eSymbolTypeTrampoline; } + +bool Symbol::IsIndirect() const { return m_type == eSymbolTypeResolver; } + +void Symbol::GetDescription(Stream *s, lldb::DescriptionLevel level, + Target *target) const { + s->Printf("id = {0x%8.8x}", m_uid); + + if (m_addr_range.GetBaseAddress().GetSection()) { + if (ValueIsAddress()) { + const lldb::addr_t byte_size = GetByteSize(); + if (byte_size > 0) { + s->PutCString(", range = "); + m_addr_range.Dump(s, target, Address::DumpStyleLoadAddress, + Address::DumpStyleFileAddress); + } else { + s->PutCString(", address = "); + m_addr_range.GetBaseAddress().Dump(s, target, + Address::DumpStyleLoadAddress, + Address::DumpStyleFileAddress); + } + } else + s->Printf(", value = 0x%16.16" PRIx64, + m_addr_range.GetBaseAddress().GetOffset()); + } else { + if (m_size_is_sibling) + s->Printf(", sibling = %5" PRIu64, + m_addr_range.GetBaseAddress().GetOffset()); else - { - if (m_size_is_sibling) - s->Printf (", sibling = %5" PRIu64, m_addr_range.GetBaseAddress().GetOffset()); - else - s->Printf (", value = 0x%16.16" PRIx64, m_addr_range.GetBaseAddress().GetOffset()); - } - ConstString demangled = m_mangled.GetDemangledName(GetLanguage()); - if (demangled) - s->Printf(", name=\"%s\"", demangled.AsCString()); - if (m_mangled.GetMangledName()) - s->Printf(", mangled=\"%s\"", m_mangled.GetMangledName().AsCString()); - -} - -void -Symbol::Dump(Stream *s, Target *target, uint32_t index) const -{ - s->Printf("[%5u] %6u %c%c%c %-15s ", - index, - GetID(), - m_is_debug ? 'D' : ' ', - m_is_synthetic ? 'S' : ' ', - m_is_external ? 'X' : ' ', - GetTypeAsString()); - - // Make sure the size of the symbol is up to date before dumping - GetByteSize(); - - ConstString name = m_mangled.GetName(GetLanguage()); - if (ValueIsAddress()) - { - if (!m_addr_range.GetBaseAddress().Dump(s, nullptr, Address::DumpStyleFileAddress)) - s->Printf("%*s", 18, ""); - - s->PutChar(' '); - - if (!m_addr_range.GetBaseAddress().Dump(s, target, Address::DumpStyleLoadAddress)) - s->Printf("%*s", 18, ""); - - const char *format = m_size_is_sibling ? - " Sibling -> [%5llu] 0x%8.8x %s\n": - " 0x%16.16" PRIx64 " 0x%8.8x %s\n"; - s->Printf( format, - GetByteSize(), - m_flags, - name.AsCString("")); - } - else if (m_type == eSymbolTypeReExported) - { - s->Printf (" 0x%8.8x %s", - m_flags, - name.AsCString("")); - - ConstString reexport_name = GetReExportedSymbolName(); - intptr_t shlib = m_addr_range.GetByteSize(); - if (shlib) - s->Printf(" -> %s`%s\n", (const char *)shlib, reexport_name.GetCString()); - else - s->Printf(" -> %s\n", reexport_name.GetCString()); - } + s->Printf(", value = 0x%16.16" PRIx64, + m_addr_range.GetBaseAddress().GetOffset()); + } + ConstString demangled = m_mangled.GetDemangledName(GetLanguage()); + if (demangled) + s->Printf(", name=\"%s\"", demangled.AsCString()); + if (m_mangled.GetMangledName()) + s->Printf(", mangled=\"%s\"", m_mangled.GetMangledName().AsCString()); +} + +void Symbol::Dump(Stream *s, Target *target, uint32_t index) const { + s->Printf("[%5u] %6u %c%c%c %-15s ", index, GetID(), m_is_debug ? 'D' : ' ', + m_is_synthetic ? 'S' : ' ', m_is_external ? 'X' : ' ', + GetTypeAsString()); + + // Make sure the size of the symbol is up to date before dumping + GetByteSize(); + + ConstString name = m_mangled.GetName(GetLanguage()); + if (ValueIsAddress()) { + if (!m_addr_range.GetBaseAddress().Dump(s, nullptr, + Address::DumpStyleFileAddress)) + s->Printf("%*s", 18, ""); + + s->PutChar(' '); + + if (!m_addr_range.GetBaseAddress().Dump(s, target, + Address::DumpStyleLoadAddress)) + s->Printf("%*s", 18, ""); + + const char *format = m_size_is_sibling ? " Sibling -> [%5llu] 0x%8.8x %s\n" + : " 0x%16.16" PRIx64 " 0x%8.8x %s\n"; + s->Printf(format, GetByteSize(), m_flags, name.AsCString("")); + } else if (m_type == eSymbolTypeReExported) { + s->Printf( + " 0x%8.8x %s", + m_flags, name.AsCString("")); + + ConstString reexport_name = GetReExportedSymbolName(); + intptr_t shlib = m_addr_range.GetByteSize(); + if (shlib) + s->Printf(" -> %s`%s\n", (const char *)shlib, reexport_name.GetCString()); else - { - const char *format = m_size_is_sibling ? - "0x%16.16" PRIx64 " Sibling -> [%5llu] 0x%8.8x %s\n": - "0x%16.16" PRIx64 " 0x%16.16" PRIx64 " 0x%8.8x %s\n"; - s->Printf( format, - m_addr_range.GetBaseAddress().GetOffset(), - GetByteSize(), - m_flags, - name.AsCString("")); - } -} - -uint32_t -Symbol::GetPrologueByteSize () -{ - if (m_type == eSymbolTypeCode || m_type == eSymbolTypeResolver) - { - if (!m_type_data_resolved) - { - m_type_data_resolved = true; - - const Address &base_address = m_addr_range.GetBaseAddress(); - Function *function = base_address.CalculateSymbolContextFunction(); - if (function) - { - // Functions have line entries which can also potentially have end of prologue information. - // So if this symbol points to a function, use the prologue information from there. - m_type_data = function->GetPrologueByteSize(); - } - else - { - ModuleSP module_sp (base_address.GetModule()); - SymbolContext sc; - if (module_sp) - { - uint32_t resolved_flags = module_sp->ResolveSymbolContextForAddress (base_address, - eSymbolContextLineEntry, - sc); - if (resolved_flags & eSymbolContextLineEntry) - { - // Default to the end of the first line entry. - m_type_data = sc.line_entry.range.GetByteSize(); - - // Set address for next line. - Address addr (base_address); - addr.Slide (m_type_data); - - // Check the first few instructions and look for one that has a line number that is - // different than the first entry. This is also done in Function::GetPrologueByteSize(). - uint16_t total_offset = m_type_data; - for (int idx = 0; idx < 6; ++idx) - { - SymbolContext sc_temp; - resolved_flags = module_sp->ResolveSymbolContextForAddress (addr, eSymbolContextLineEntry, sc_temp); - // Make sure we got line number information... - if (!(resolved_flags & eSymbolContextLineEntry)) - break; - - // If this line number is different than our first one, use it and we're done. - if (sc_temp.line_entry.line != sc.line_entry.line) - { - m_type_data = total_offset; - break; - } - - // Slide addr up to the next line address. - addr.Slide (sc_temp.line_entry.range.GetByteSize()); - total_offset += sc_temp.line_entry.range.GetByteSize(); - // If we've gone too far, bail out. - if (total_offset >= m_addr_range.GetByteSize()) - break; - } - - // Sanity check - this may be a function in the middle of code that has debug information, but - // not for this symbol. So the line entries surrounding us won't lie inside our function. - // In that case, the line entry will be bigger than we are, so we do that quick check and - // if that is true, we just return 0. - if (m_type_data >= m_addr_range.GetByteSize()) - m_type_data = 0; - } - else - { - // TODO: expose something in Process to figure out the - // size of a function prologue. - m_type_data = 0; - } - } + s->Printf(" -> %s\n", reexport_name.GetCString()); + } else { + const char *format = + m_size_is_sibling + ? "0x%16.16" PRIx64 + " Sibling -> [%5llu] 0x%8.8x %s\n" + : "0x%16.16" PRIx64 " 0x%16.16" PRIx64 + " 0x%8.8x %s\n"; + s->Printf(format, m_addr_range.GetBaseAddress().GetOffset(), GetByteSize(), + m_flags, name.AsCString("")); + } +} + +uint32_t Symbol::GetPrologueByteSize() { + if (m_type == eSymbolTypeCode || m_type == eSymbolTypeResolver) { + if (!m_type_data_resolved) { + m_type_data_resolved = true; + + const Address &base_address = m_addr_range.GetBaseAddress(); + Function *function = base_address.CalculateSymbolContextFunction(); + if (function) { + // Functions have line entries which can also potentially have end of + // prologue information. + // So if this symbol points to a function, use the prologue information + // from there. + m_type_data = function->GetPrologueByteSize(); + } else { + ModuleSP module_sp(base_address.GetModule()); + SymbolContext sc; + if (module_sp) { + uint32_t resolved_flags = module_sp->ResolveSymbolContextForAddress( + base_address, eSymbolContextLineEntry, sc); + if (resolved_flags & eSymbolContextLineEntry) { + // Default to the end of the first line entry. + m_type_data = sc.line_entry.range.GetByteSize(); + + // Set address for next line. + Address addr(base_address); + addr.Slide(m_type_data); + + // Check the first few instructions and look for one that has a line + // number that is + // different than the first entry. This is also done in + // Function::GetPrologueByteSize(). + uint16_t total_offset = m_type_data; + for (int idx = 0; idx < 6; ++idx) { + SymbolContext sc_temp; + resolved_flags = module_sp->ResolveSymbolContextForAddress( + addr, eSymbolContextLineEntry, sc_temp); + // Make sure we got line number information... + if (!(resolved_flags & eSymbolContextLineEntry)) + break; + + // If this line number is different than our first one, use it and + // we're done. + if (sc_temp.line_entry.line != sc.line_entry.line) { + m_type_data = total_offset; + break; + } + + // Slide addr up to the next line address. + addr.Slide(sc_temp.line_entry.range.GetByteSize()); + total_offset += sc_temp.line_entry.range.GetByteSize(); + // If we've gone too far, bail out. + if (total_offset >= m_addr_range.GetByteSize()) + break; } + + // Sanity check - this may be a function in the middle of code that + // has debug information, but + // not for this symbol. So the line entries surrounding us won't + // lie inside our function. + // In that case, the line entry will be bigger than we are, so we do + // that quick check and + // if that is true, we just return 0. + if (m_type_data >= m_addr_range.GetByteSize()) + m_type_data = 0; + } else { + // TODO: expose something in Process to figure out the + // size of a function prologue. + m_type_data = 0; + } } - return m_type_data; + } } - return 0; + return m_type_data; + } + return 0; } -bool -Symbol::Compare(const ConstString& name, SymbolType type) const -{ - if (type == eSymbolTypeAny || m_type == type) - return m_mangled.GetMangledName() == name || m_mangled.GetDemangledName(GetLanguage()) == name; - return false; +bool Symbol::Compare(const ConstString &name, SymbolType type) const { + if (type == eSymbolTypeAny || m_type == type) + return m_mangled.GetMangledName() == name || + m_mangled.GetDemangledName(GetLanguage()) == name; + return false; } -#define ENUM_TO_CSTRING(x) case eSymbolType##x: return #x; +#define ENUM_TO_CSTRING(x) \ + case eSymbolType##x: \ + return #x; -const char * -Symbol::GetTypeAsString() const -{ - switch (m_type) - { +const char *Symbol::GetTypeAsString() const { + switch (m_type) { ENUM_TO_CSTRING(Invalid); ENUM_TO_CSTRING(Absolute); ENUM_TO_CSTRING(Code); @@ -489,258 +374,200 @@ Symbol::GetTypeAsString() const ENUM_TO_CSTRING(ObjCMetaClass); ENUM_TO_CSTRING(ObjCIVar); ENUM_TO_CSTRING(ReExported); - default: - break; - } - return "<unknown SymbolType>"; + default: + break; + } + return "<unknown SymbolType>"; } -void -Symbol::CalculateSymbolContext (SymbolContext *sc) -{ - // Symbols can reconstruct the symbol and the module in the symbol context - sc->symbol = this; - if (ValueIsAddress()) - sc->module_sp = GetAddressRef().GetModule(); - else - sc->module_sp.reset(); +void Symbol::CalculateSymbolContext(SymbolContext *sc) { + // Symbols can reconstruct the symbol and the module in the symbol context + sc->symbol = this; + if (ValueIsAddress()) + sc->module_sp = GetAddressRef().GetModule(); + else + sc->module_sp.reset(); } -ModuleSP -Symbol::CalculateSymbolContextModule () -{ - if (ValueIsAddress()) - return GetAddressRef().GetModule(); - return ModuleSP(); +ModuleSP Symbol::CalculateSymbolContextModule() { + if (ValueIsAddress()) + return GetAddressRef().GetModule(); + return ModuleSP(); } -Symbol * -Symbol::CalculateSymbolContextSymbol () -{ - return this; -} +Symbol *Symbol::CalculateSymbolContextSymbol() { return this; } -void -Symbol::DumpSymbolContext (Stream *s) -{ - bool dumped_module = false; - if (ValueIsAddress()) - { - ModuleSP module_sp (GetAddressRef().GetModule()); - if (module_sp) - { - dumped_module = true; - module_sp->DumpSymbolContext(s); - } +void Symbol::DumpSymbolContext(Stream *s) { + bool dumped_module = false; + if (ValueIsAddress()) { + ModuleSP module_sp(GetAddressRef().GetModule()); + if (module_sp) { + dumped_module = true; + module_sp->DumpSymbolContext(s); } - if (dumped_module) - s->PutCString(", "); - - s->Printf("Symbol{0x%8.8x}", GetID()); -} - -lldb::addr_t -Symbol::GetByteSize () const -{ - return m_addr_range.GetByteSize(); -} - - -Symbol * -Symbol::ResolveReExportedSymbolInModuleSpec (Target &target, - ConstString &reexport_name, - ModuleSpec &module_spec, - ModuleList &seen_modules) const -{ - ModuleSP module_sp; - if (module_spec.GetFileSpec()) - { - // Try searching for the module file spec first using the full path - module_sp = target.GetImages().FindFirstModule(module_spec); - if (!module_sp) - { - // Next try and find the module by basename in case environment - // variables or other runtime trickery causes shared libraries - // to be loaded from alternate paths - module_spec.GetFileSpec().GetDirectory().Clear(); - module_sp = target.GetImages().FindFirstModule(module_spec); - } + } + if (dumped_module) + s->PutCString(", "); + + s->Printf("Symbol{0x%8.8x}", GetID()); +} + +lldb::addr_t Symbol::GetByteSize() const { return m_addr_range.GetByteSize(); } + +Symbol *Symbol::ResolveReExportedSymbolInModuleSpec( + Target &target, ConstString &reexport_name, ModuleSpec &module_spec, + ModuleList &seen_modules) const { + ModuleSP module_sp; + if (module_spec.GetFileSpec()) { + // Try searching for the module file spec first using the full path + module_sp = target.GetImages().FindFirstModule(module_spec); + if (!module_sp) { + // Next try and find the module by basename in case environment + // variables or other runtime trickery causes shared libraries + // to be loaded from alternate paths + module_spec.GetFileSpec().GetDirectory().Clear(); + module_sp = target.GetImages().FindFirstModule(module_spec); } - - if (module_sp) - { - // There should not be cycles in the reexport list, but we don't want to crash if there are so make sure - // we haven't seen this before: - if (!seen_modules.AppendIfNeeded(module_sp)) - return nullptr; - - lldb_private::SymbolContextList sc_list; - module_sp->FindSymbolsWithNameAndType(reexport_name, eSymbolTypeAny, sc_list); - const size_t num_scs = sc_list.GetSize(); - if (num_scs > 0) - { - for (size_t i=0; i<num_scs; ++i) - { - lldb_private::SymbolContext sc; - if (sc_list.GetContextAtIndex(i, sc)) - { - if (sc.symbol->IsExternal()) - return sc.symbol; - } - } - } - // If we didn't find the symbol in this module, it may be because this module re-exports some - // whole other library. We have to search those as well: - seen_modules.Append(module_sp); - - FileSpecList reexported_libraries = module_sp->GetObjectFile()->GetReExportedLibraries(); - size_t num_reexported_libraries = reexported_libraries.GetSize(); - for (size_t idx = 0; idx < num_reexported_libraries; idx++) - { - ModuleSpec reexported_module_spec; - reexported_module_spec.GetFileSpec() = reexported_libraries.GetFileSpecAtIndex(idx); - Symbol *result_symbol = ResolveReExportedSymbolInModuleSpec(target, - reexport_name, - reexported_module_spec, - seen_modules); - if (result_symbol) - return result_symbol; + } + + if (module_sp) { + // There should not be cycles in the reexport list, but we don't want to + // crash if there are so make sure + // we haven't seen this before: + if (!seen_modules.AppendIfNeeded(module_sp)) + return nullptr; + + lldb_private::SymbolContextList sc_list; + module_sp->FindSymbolsWithNameAndType(reexport_name, eSymbolTypeAny, + sc_list); + const size_t num_scs = sc_list.GetSize(); + if (num_scs > 0) { + for (size_t i = 0; i < num_scs; ++i) { + lldb_private::SymbolContext sc; + if (sc_list.GetContextAtIndex(i, sc)) { + if (sc.symbol->IsExternal()) + return sc.symbol; } + } } - return nullptr; -} - -Symbol * -Symbol::ResolveReExportedSymbol (Target &target) const -{ - ConstString reexport_name (GetReExportedSymbolName()); - if (reexport_name) - { - ModuleSpec module_spec; - ModuleList seen_modules; - module_spec.GetFileSpec() = GetReExportedSymbolSharedLibrary(); - if (module_spec.GetFileSpec()) - { - return ResolveReExportedSymbolInModuleSpec(target, reexport_name, module_spec, seen_modules); - } + // If we didn't find the symbol in this module, it may be because this + // module re-exports some + // whole other library. We have to search those as well: + seen_modules.Append(module_sp); + + FileSpecList reexported_libraries = + module_sp->GetObjectFile()->GetReExportedLibraries(); + size_t num_reexported_libraries = reexported_libraries.GetSize(); + for (size_t idx = 0; idx < num_reexported_libraries; idx++) { + ModuleSpec reexported_module_spec; + reexported_module_spec.GetFileSpec() = + reexported_libraries.GetFileSpecAtIndex(idx); + Symbol *result_symbol = ResolveReExportedSymbolInModuleSpec( + target, reexport_name, reexported_module_spec, seen_modules); + if (result_symbol) + return result_symbol; + } + } + return nullptr; +} + +Symbol *Symbol::ResolveReExportedSymbol(Target &target) const { + ConstString reexport_name(GetReExportedSymbolName()); + if (reexport_name) { + ModuleSpec module_spec; + ModuleList seen_modules; + module_spec.GetFileSpec() = GetReExportedSymbolSharedLibrary(); + if (module_spec.GetFileSpec()) { + return ResolveReExportedSymbolInModuleSpec(target, reexport_name, + module_spec, seen_modules); } - return nullptr; + } + return nullptr; } -lldb::addr_t -Symbol::GetFileAddress () const -{ - if (ValueIsAddress()) - return GetAddressRef().GetFileAddress(); - else - return LLDB_INVALID_ADDRESS; +lldb::addr_t Symbol::GetFileAddress() const { + if (ValueIsAddress()) + return GetAddressRef().GetFileAddress(); + else + return LLDB_INVALID_ADDRESS; } -lldb::addr_t -Symbol::GetLoadAddress (Target *target) const -{ - if (ValueIsAddress()) - return GetAddressRef().GetLoadAddress(target); - else - return LLDB_INVALID_ADDRESS; +lldb::addr_t Symbol::GetLoadAddress(Target *target) const { + if (ValueIsAddress()) + return GetAddressRef().GetLoadAddress(target); + else + return LLDB_INVALID_ADDRESS; } -ConstString -Symbol::GetName () const -{ - return m_mangled.GetName(GetLanguage()); -} +ConstString Symbol::GetName() const { return m_mangled.GetName(GetLanguage()); } -ConstString -Symbol::GetNameNoArguments () const -{ - return m_mangled.GetName(GetLanguage(), Mangled::ePreferDemangledWithoutArguments); +ConstString Symbol::GetNameNoArguments() const { + return m_mangled.GetName(GetLanguage(), + Mangled::ePreferDemangledWithoutArguments); } +lldb::addr_t Symbol::ResolveCallableAddress(Target &target) const { + if (GetType() == lldb::eSymbolTypeUndefined) + return LLDB_INVALID_ADDRESS; -lldb::addr_t -Symbol::ResolveCallableAddress(Target &target) const -{ - if (GetType() == lldb::eSymbolTypeUndefined) - return LLDB_INVALID_ADDRESS; - - Address func_so_addr; - - bool is_indirect = IsIndirect(); - if (GetType() == eSymbolTypeReExported) - { - Symbol *reexported_symbol = ResolveReExportedSymbol(target); - if (reexported_symbol) - { - func_so_addr = reexported_symbol->GetAddress(); - is_indirect = reexported_symbol->IsIndirect(); - } - } - else - { - func_so_addr = GetAddress(); - is_indirect = IsIndirect(); - } + Address func_so_addr; - if (func_so_addr.IsValid()) - { - if (!target.GetProcessSP() && is_indirect) - { - // can't resolve indirect symbols without calling a function... - return LLDB_INVALID_ADDRESS; - } - - lldb::addr_t load_addr = func_so_addr.GetCallableLoadAddress (&target, is_indirect); - - if (load_addr != LLDB_INVALID_ADDRESS) - { - return load_addr; - } + bool is_indirect = IsIndirect(); + if (GetType() == eSymbolTypeReExported) { + Symbol *reexported_symbol = ResolveReExportedSymbol(target); + if (reexported_symbol) { + func_so_addr = reexported_symbol->GetAddress(); + is_indirect = reexported_symbol->IsIndirect(); + } + } else { + func_so_addr = GetAddress(); + is_indirect = IsIndirect(); + } + + if (func_so_addr.IsValid()) { + if (!target.GetProcessSP() && is_indirect) { + // can't resolve indirect symbols without calling a function... + return LLDB_INVALID_ADDRESS; } - - return LLDB_INVALID_ADDRESS; -} + lldb::addr_t load_addr = + func_so_addr.GetCallableLoadAddress(&target, is_indirect); -lldb::DisassemblerSP -Symbol::GetInstructions (const ExecutionContext &exe_ctx, - const char *flavor, - bool prefer_file_cache) -{ - ModuleSP module_sp (m_addr_range.GetBaseAddress().GetModule()); - if (module_sp) - { - const bool prefer_file_cache = false; - return Disassembler::DisassembleRange (module_sp->GetArchitecture(), - nullptr, - flavor, - exe_ctx, - m_addr_range, - prefer_file_cache); + if (load_addr != LLDB_INVALID_ADDRESS) { + return load_addr; } - return lldb::DisassemblerSP(); + } + + return LLDB_INVALID_ADDRESS; } -bool -Symbol::GetDisassembly (const ExecutionContext &exe_ctx, - const char *flavor, - bool prefer_file_cache, - Stream &strm) -{ - lldb::DisassemblerSP disassembler_sp = GetInstructions (exe_ctx, flavor, prefer_file_cache); - if (disassembler_sp) - { - const bool show_address = true; - const bool show_bytes = false; - disassembler_sp->GetInstructionList().Dump (&strm, show_address, show_bytes, &exe_ctx); - return true; - } - return false; +lldb::DisassemblerSP Symbol::GetInstructions(const ExecutionContext &exe_ctx, + const char *flavor, + bool prefer_file_cache) { + ModuleSP module_sp(m_addr_range.GetBaseAddress().GetModule()); + if (module_sp) { + const bool prefer_file_cache = false; + return Disassembler::DisassembleRange(module_sp->GetArchitecture(), nullptr, + flavor, exe_ctx, m_addr_range, + prefer_file_cache); + } + return lldb::DisassemblerSP(); } -bool -Symbol::ContainsFileAddress (lldb::addr_t file_addr) const -{ - return m_addr_range.ContainsFileAddress(file_addr); +bool Symbol::GetDisassembly(const ExecutionContext &exe_ctx, const char *flavor, + bool prefer_file_cache, Stream &strm) { + lldb::DisassemblerSP disassembler_sp = + GetInstructions(exe_ctx, flavor, prefer_file_cache); + if (disassembler_sp) { + const bool show_address = true; + const bool show_bytes = false; + disassembler_sp->GetInstructionList().Dump(&strm, show_address, show_bytes, + &exe_ctx); + return true; + } + return false; } +bool Symbol::ContainsFileAddress(lldb::addr_t file_addr) const { + return m_addr_range.ContainsFileAddress(file_addr); +} diff --git a/lldb/source/Symbol/SymbolContext.cpp b/lldb/source/Symbol/SymbolContext.cpp index 1e55ce652e0..2fa30b78dd5 100644 --- a/lldb/source/Symbol/SymbolContext.cpp +++ b/lldb/source/Symbol/SymbolContext.cpp @@ -27,907 +27,777 @@ using namespace lldb; using namespace lldb_private; -SymbolContext::SymbolContext() : - target_sp (), - module_sp (), - comp_unit (nullptr), - function (nullptr), - block (nullptr), - line_entry (), - symbol (nullptr), - variable (nullptr) -{ +SymbolContext::SymbolContext() + : target_sp(), module_sp(), comp_unit(nullptr), function(nullptr), + block(nullptr), line_entry(), symbol(nullptr), variable(nullptr) {} + +SymbolContext::SymbolContext(const ModuleSP &m, CompileUnit *cu, Function *f, + Block *b, LineEntry *le, Symbol *s) + : target_sp(), module_sp(m), comp_unit(cu), function(f), block(b), + line_entry(), symbol(s), variable(nullptr) { + if (le) + line_entry = *le; } -SymbolContext::SymbolContext(const ModuleSP& m, CompileUnit *cu, Function *f, Block *b, LineEntry *le, Symbol *s) : - target_sp (), - module_sp (m), - comp_unit (cu), - function (f), - block (b), - line_entry (), - symbol (s), - variable (nullptr) -{ - if (le) - line_entry = *le; +SymbolContext::SymbolContext(const TargetSP &t, const ModuleSP &m, + CompileUnit *cu, Function *f, Block *b, + LineEntry *le, Symbol *s) + : target_sp(t), module_sp(m), comp_unit(cu), function(f), block(b), + line_entry(), symbol(s), variable(nullptr) { + if (le) + line_entry = *le; } -SymbolContext::SymbolContext(const TargetSP &t, const ModuleSP& m, CompileUnit *cu, Function *f, Block *b, LineEntry *le, Symbol *s) : - target_sp (t), - module_sp (m), - comp_unit (cu), - function (f), - block (b), - line_entry (), - symbol (s), - variable (nullptr) -{ - if (le) - line_entry = *le; -} +SymbolContext::SymbolContext(const SymbolContext &rhs) + : target_sp(rhs.target_sp), module_sp(rhs.module_sp), + comp_unit(rhs.comp_unit), function(rhs.function), block(rhs.block), + line_entry(rhs.line_entry), symbol(rhs.symbol), variable(rhs.variable) {} -SymbolContext::SymbolContext(const SymbolContext& rhs) : - target_sp (rhs.target_sp), - module_sp (rhs.module_sp), - comp_unit (rhs.comp_unit), - function (rhs.function), - block (rhs.block), - line_entry (rhs.line_entry), - symbol (rhs.symbol), - variable (rhs.variable) -{ +SymbolContext::SymbolContext(SymbolContextScope *sc_scope) + : target_sp(), module_sp(), comp_unit(nullptr), function(nullptr), + block(nullptr), line_entry(), symbol(nullptr), variable(nullptr) { + sc_scope->CalculateSymbolContext(this); } - -SymbolContext::SymbolContext (SymbolContextScope *sc_scope) : - target_sp (), - module_sp (), - comp_unit (nullptr), - function (nullptr), - block (nullptr), - line_entry (), - symbol (nullptr), - variable (nullptr) -{ - sc_scope->CalculateSymbolContext (this); +SymbolContext::~SymbolContext() {} + +const SymbolContext &SymbolContext::operator=(const SymbolContext &rhs) { + if (this != &rhs) { + target_sp = rhs.target_sp; + module_sp = rhs.module_sp; + comp_unit = rhs.comp_unit; + function = rhs.function; + block = rhs.block; + line_entry = rhs.line_entry; + symbol = rhs.symbol; + variable = rhs.variable; + } + return *this; } -SymbolContext::~SymbolContext () -{ +void SymbolContext::Clear(bool clear_target) { + if (clear_target) + target_sp.reset(); + module_sp.reset(); + comp_unit = nullptr; + function = nullptr; + block = nullptr; + line_entry.Clear(); + symbol = nullptr; + variable = nullptr; } -const SymbolContext& -SymbolContext::operator= (const SymbolContext& rhs) -{ - if (this != &rhs) - { - target_sp = rhs.target_sp; - module_sp = rhs.module_sp; - comp_unit = rhs.comp_unit; - function = rhs.function; - block = rhs.block; - line_entry = rhs.line_entry; - symbol = rhs.symbol; - variable = rhs.variable; - } - return *this; -} - -void -SymbolContext::Clear(bool clear_target) -{ - if (clear_target) - target_sp.reset(); - module_sp.reset(); - comp_unit = nullptr; - function = nullptr; - block = nullptr; - line_entry.Clear(); - symbol = nullptr; - variable = nullptr; -} - -bool -SymbolContext::DumpStopContext ( - Stream *s, - ExecutionContextScope *exe_scope, - const Address &addr, - bool show_fullpaths, - bool show_module, - bool show_inlined_frames, - bool show_function_arguments, - bool show_function_name -) const -{ - bool dumped_something = false; - if (show_module && module_sp) - { - if (show_fullpaths) - *s << module_sp->GetFileSpec(); - else - *s << module_sp->GetFileSpec().GetFilename(); - s->PutChar('`'); +bool SymbolContext::DumpStopContext(Stream *s, ExecutionContextScope *exe_scope, + const Address &addr, bool show_fullpaths, + bool show_module, bool show_inlined_frames, + bool show_function_arguments, + bool show_function_name) const { + bool dumped_something = false; + if (show_module && module_sp) { + if (show_fullpaths) + *s << module_sp->GetFileSpec(); + else + *s << module_sp->GetFileSpec().GetFilename(); + s->PutChar('`'); + dumped_something = true; + } + + if (function != nullptr) { + SymbolContext inline_parent_sc; + Address inline_parent_addr; + if (show_function_name == false) { + s->Printf("<"); + dumped_something = true; + } else { + ConstString name; + if (show_function_arguments == false) + name = function->GetNameNoArguments(); + if (!name) + name = function->GetName(); + if (name) + name.Dump(s); + } + + if (addr.IsValid()) { + const addr_t function_offset = + addr.GetOffset() - + function->GetAddressRange().GetBaseAddress().GetOffset(); + if (show_function_name == false) { + // Print +offset even if offset is 0 dumped_something = true; - } - - if (function != nullptr) - { - SymbolContext inline_parent_sc; - Address inline_parent_addr; - if (show_function_name == false) - { - s->Printf("<"); - dumped_something = true; - } - else - { - ConstString name; - if (show_function_arguments == false) - name = function->GetNameNoArguments(); - if (!name) - name = function->GetName(); - if (name) - name.Dump(s); - } - - if (addr.IsValid()) - { - const addr_t function_offset = addr.GetOffset() - function->GetAddressRange().GetBaseAddress().GetOffset(); - if (show_function_name == false) - { - // Print +offset even if offset is 0 - dumped_something = true; - s->Printf("+%" PRIu64 ">", function_offset); - } - else if (function_offset) - { - dumped_something = true; - s->Printf(" + %" PRIu64, function_offset); - } - } - - if (GetParentOfInlinedScope (addr, inline_parent_sc, inline_parent_addr)) - { - dumped_something = true; - Block *inlined_block = block->GetContainingInlinedBlock(); - const InlineFunctionInfo* inlined_block_info = inlined_block->GetInlinedFunctionInfo(); - s->Printf (" [inlined] %s", inlined_block_info->GetName(function->GetLanguage()).GetCString()); - - lldb_private::AddressRange block_range; - if (inlined_block->GetRangeContainingAddress(addr, block_range)) - { - const addr_t inlined_function_offset = addr.GetOffset() - block_range.GetBaseAddress().GetOffset(); - if (inlined_function_offset) - { - s->Printf(" + %" PRIu64, inlined_function_offset); - } - } - const Declaration &call_site = inlined_block_info->GetCallSite(); - if (call_site.IsValid()) - { - s->PutCString(" at "); - call_site.DumpStopContext (s, show_fullpaths); - } - if (show_inlined_frames) - { - s->EOL(); - s->Indent(); - const bool show_function_name = true; - return inline_parent_sc.DumpStopContext (s, exe_scope, inline_parent_addr, show_fullpaths, show_module, show_inlined_frames, show_function_arguments, show_function_name); - } - } - else - { - if (line_entry.IsValid()) - { - dumped_something = true; - s->PutCString(" at "); - if (line_entry.DumpStopContext(s, show_fullpaths)) - dumped_something = true; - } - } - } - else if (symbol != nullptr) - { - if (show_function_name == false) - { - s->Printf("<"); - dumped_something = true; - } - else if (symbol->GetName()) - { - dumped_something = true; - if (symbol->GetType() == eSymbolTypeTrampoline) - s->PutCString("symbol stub for: "); - symbol->GetName().Dump(s); - } - - if (addr.IsValid() && symbol->ValueIsAddress()) - { - const addr_t symbol_offset = addr.GetOffset() - symbol->GetAddressRef().GetOffset(); - if (show_function_name == false) - { - // Print +offset even if offset is 0 - dumped_something = true; - s->Printf("+%" PRIu64 ">", symbol_offset); - } - else if (symbol_offset) - { - dumped_something = true; - s->Printf(" + %" PRIu64, symbol_offset); - } + s->Printf("+%" PRIu64 ">", function_offset); + } else if (function_offset) { + dumped_something = true; + s->Printf(" + %" PRIu64, function_offset); + } + } + + if (GetParentOfInlinedScope(addr, inline_parent_sc, inline_parent_addr)) { + dumped_something = true; + Block *inlined_block = block->GetContainingInlinedBlock(); + const InlineFunctionInfo *inlined_block_info = + inlined_block->GetInlinedFunctionInfo(); + s->Printf( + " [inlined] %s", + inlined_block_info->GetName(function->GetLanguage()).GetCString()); + + lldb_private::AddressRange block_range; + if (inlined_block->GetRangeContainingAddress(addr, block_range)) { + const addr_t inlined_function_offset = + addr.GetOffset() - block_range.GetBaseAddress().GetOffset(); + if (inlined_function_offset) { + s->Printf(" + %" PRIu64, inlined_function_offset); } - } - else if (addr.IsValid()) - { - addr.Dump(s, exe_scope, Address::DumpStyleModuleWithFileAddress); + } + const Declaration &call_site = inlined_block_info->GetCallSite(); + if (call_site.IsValid()) { + s->PutCString(" at "); + call_site.DumpStopContext(s, show_fullpaths); + } + if (show_inlined_frames) { + s->EOL(); + s->Indent(); + const bool show_function_name = true; + return inline_parent_sc.DumpStopContext( + s, exe_scope, inline_parent_addr, show_fullpaths, show_module, + show_inlined_frames, show_function_arguments, show_function_name); + } + } else { + if (line_entry.IsValid()) { dumped_something = true; - } - return dumped_something; + s->PutCString(" at "); + if (line_entry.DumpStopContext(s, show_fullpaths)) + dumped_something = true; + } + } + } else if (symbol != nullptr) { + if (show_function_name == false) { + s->Printf("<"); + dumped_something = true; + } else if (symbol->GetName()) { + dumped_something = true; + if (symbol->GetType() == eSymbolTypeTrampoline) + s->PutCString("symbol stub for: "); + symbol->GetName().Dump(s); + } + + if (addr.IsValid() && symbol->ValueIsAddress()) { + const addr_t symbol_offset = + addr.GetOffset() - symbol->GetAddressRef().GetOffset(); + if (show_function_name == false) { + // Print +offset even if offset is 0 + dumped_something = true; + s->Printf("+%" PRIu64 ">", symbol_offset); + } else if (symbol_offset) { + dumped_something = true; + s->Printf(" + %" PRIu64, symbol_offset); + } + } + } else if (addr.IsValid()) { + addr.Dump(s, exe_scope, Address::DumpStyleModuleWithFileAddress); + dumped_something = true; + } + return dumped_something; } -void -SymbolContext::GetDescription(Stream *s, lldb::DescriptionLevel level, Target *target) const -{ - if (module_sp) - { - s->Indent(" Module: file = \""); - module_sp->GetFileSpec().Dump(s); - *s << '"'; - if (module_sp->GetArchitecture().IsValid()) - s->Printf (", arch = \"%s\"", module_sp->GetArchitecture().GetArchitectureName()); - s->EOL(); - } - - if (comp_unit != nullptr) - { - s->Indent("CompileUnit: "); - comp_unit->GetDescription (s, level); - s->EOL(); - } - - if (function != nullptr) - { - s->Indent(" Function: "); - function->GetDescription (s, level, target); - s->EOL(); - - Type *func_type = function->GetType(); - if (func_type) - { - s->Indent(" FuncType: "); - func_type->GetDescription (s, level, false); - s->EOL(); - } - } +void SymbolContext::GetDescription(Stream *s, lldb::DescriptionLevel level, + Target *target) const { + if (module_sp) { + s->Indent(" Module: file = \""); + module_sp->GetFileSpec().Dump(s); + *s << '"'; + if (module_sp->GetArchitecture().IsValid()) + s->Printf(", arch = \"%s\"", + module_sp->GetArchitecture().GetArchitectureName()); + s->EOL(); + } - if (block != nullptr) - { - std::vector<Block *> blocks; - blocks.push_back (block); - Block *parent_block = block->GetParent(); - - while (parent_block) - { - blocks.push_back (parent_block); - parent_block = parent_block->GetParent(); - } - std::vector<Block *>::reverse_iterator pos; - std::vector<Block *>::reverse_iterator begin = blocks.rbegin(); - std::vector<Block *>::reverse_iterator end = blocks.rend(); - for (pos = begin; pos != end; ++pos) - { - if (pos == begin) - s->Indent(" Blocks: "); - else - s->Indent(" "); - (*pos)->GetDescription(s, function, level, target); - s->EOL(); - } - } + if (comp_unit != nullptr) { + s->Indent("CompileUnit: "); + comp_unit->GetDescription(s, level); + s->EOL(); + } - if (line_entry.IsValid()) - { - s->Indent(" LineEntry: "); - line_entry.GetDescription (s, level, comp_unit, target, false); - s->EOL(); - } + if (function != nullptr) { + s->Indent(" Function: "); + function->GetDescription(s, level, target); + s->EOL(); - if (symbol != nullptr) - { - s->Indent(" Symbol: "); - symbol->GetDescription(s, level, target); - s->EOL(); - } + Type *func_type = function->GetType(); + if (func_type) { + s->Indent(" FuncType: "); + func_type->GetDescription(s, level, false); + s->EOL(); + } + } + + if (block != nullptr) { + std::vector<Block *> blocks; + blocks.push_back(block); + Block *parent_block = block->GetParent(); + + while (parent_block) { + blocks.push_back(parent_block); + parent_block = parent_block->GetParent(); + } + std::vector<Block *>::reverse_iterator pos; + std::vector<Block *>::reverse_iterator begin = blocks.rbegin(); + std::vector<Block *>::reverse_iterator end = blocks.rend(); + for (pos = begin; pos != end; ++pos) { + if (pos == begin) + s->Indent(" Blocks: "); + else + s->Indent(" "); + (*pos)->GetDescription(s, function, level, target); + s->EOL(); + } + } + + if (line_entry.IsValid()) { + s->Indent(" LineEntry: "); + line_entry.GetDescription(s, level, comp_unit, target, false); + s->EOL(); + } - if (variable != nullptr) - { - s->Indent(" Variable: "); + if (symbol != nullptr) { + s->Indent(" Symbol: "); + symbol->GetDescription(s, level, target); + s->EOL(); + } - s->Printf("id = {0x%8.8" PRIx64 "}, ", variable->GetID()); + if (variable != nullptr) { + s->Indent(" Variable: "); - switch (variable->GetScope()) - { - case eValueTypeVariableGlobal: - s->PutCString("kind = global, "); - break; + s->Printf("id = {0x%8.8" PRIx64 "}, ", variable->GetID()); - case eValueTypeVariableStatic: - s->PutCString("kind = static, "); - break; + switch (variable->GetScope()) { + case eValueTypeVariableGlobal: + s->PutCString("kind = global, "); + break; - case eValueTypeVariableArgument: - s->PutCString("kind = argument, "); - break; + case eValueTypeVariableStatic: + s->PutCString("kind = static, "); + break; - case eValueTypeVariableLocal: - s->PutCString("kind = local, "); - break; + case eValueTypeVariableArgument: + s->PutCString("kind = argument, "); + break; - case eValueTypeVariableThreadLocal: - s->PutCString("kind = thread local, "); - break; + case eValueTypeVariableLocal: + s->PutCString("kind = local, "); + break; - default: - break; - } + case eValueTypeVariableThreadLocal: + s->PutCString("kind = thread local, "); + break; - s->Printf ("name = \"%s\"\n", variable->GetName().GetCString()); + default: + break; } + + s->Printf("name = \"%s\"\n", variable->GetName().GetCString()); + } } -uint32_t -SymbolContext::GetResolvedMask () const -{ - uint32_t resolved_mask = 0; - if (target_sp) resolved_mask |= eSymbolContextTarget; - if (module_sp) resolved_mask |= eSymbolContextModule; - if (comp_unit) resolved_mask |= eSymbolContextCompUnit; - if (function) resolved_mask |= eSymbolContextFunction; - if (block) resolved_mask |= eSymbolContextBlock; - if (line_entry.IsValid()) resolved_mask |= eSymbolContextLineEntry; - if (symbol) resolved_mask |= eSymbolContextSymbol; - if (variable) resolved_mask |= eSymbolContextVariable; - return resolved_mask; +uint32_t SymbolContext::GetResolvedMask() const { + uint32_t resolved_mask = 0; + if (target_sp) + resolved_mask |= eSymbolContextTarget; + if (module_sp) + resolved_mask |= eSymbolContextModule; + if (comp_unit) + resolved_mask |= eSymbolContextCompUnit; + if (function) + resolved_mask |= eSymbolContextFunction; + if (block) + resolved_mask |= eSymbolContextBlock; + if (line_entry.IsValid()) + resolved_mask |= eSymbolContextLineEntry; + if (symbol) + resolved_mask |= eSymbolContextSymbol; + if (variable) + resolved_mask |= eSymbolContextVariable; + return resolved_mask; } -void -SymbolContext::Dump(Stream *s, Target *target) const -{ - *s << this << ": "; - s->Indent(); - s->PutCString("SymbolContext"); - s->IndentMore(); +void SymbolContext::Dump(Stream *s, Target *target) const { + *s << this << ": "; + s->Indent(); + s->PutCString("SymbolContext"); + s->IndentMore(); + s->EOL(); + s->IndentMore(); + s->Indent(); + *s << "Module = " << module_sp.get() << ' '; + if (module_sp) + module_sp->GetFileSpec().Dump(s); + s->EOL(); + s->Indent(); + *s << "CompileUnit = " << comp_unit; + if (comp_unit != nullptr) + *s << " {0x" << comp_unit->GetID() << "} " + << *(static_cast<FileSpec *>(comp_unit)); + s->EOL(); + s->Indent(); + *s << "Function = " << function; + if (function != nullptr) { + *s << " {0x" << function->GetID() << "} " << function->GetType()->GetName() + << ", address-range = "; + function->GetAddressRange().Dump(s, target, Address::DumpStyleLoadAddress, + Address::DumpStyleModuleWithFileAddress); s->EOL(); - s->IndentMore(); s->Indent(); - *s << "Module = " << module_sp.get() << ' '; - if (module_sp) - module_sp->GetFileSpec().Dump(s); + Type *func_type = function->GetType(); + if (func_type) { + *s << " Type = "; + func_type->Dump(s, false); + } + } + s->EOL(); + s->Indent(); + *s << "Block = " << block; + if (block != nullptr) + *s << " {0x" << block->GetID() << '}'; + // Dump the block and pass it a negative depth to we print all the parent + // blocks + // if (block != NULL) + // block->Dump(s, function->GetFileAddress(), INT_MIN); + s->EOL(); + s->Indent(); + *s << "LineEntry = "; + line_entry.Dump(s, target, true, Address::DumpStyleLoadAddress, + Address::DumpStyleModuleWithFileAddress, true); + s->EOL(); + s->Indent(); + *s << "Symbol = " << symbol; + if (symbol != nullptr && symbol->GetMangled()) + *s << ' ' << symbol->GetName().AsCString(); + s->EOL(); + *s << "Variable = " << variable; + if (variable != nullptr) { + *s << " {0x" << variable->GetID() << "} " << variable->GetType()->GetName(); s->EOL(); - s->Indent(); - *s << "CompileUnit = " << comp_unit; - if (comp_unit != nullptr) - *s << " {0x" << comp_unit->GetID() << "} " << *(static_cast<FileSpec*> (comp_unit)); - s->EOL(); - s->Indent(); - *s << "Function = " << function; - if (function != nullptr) - { - *s << " {0x" << function->GetID() << "} " << function->GetType()->GetName() << ", address-range = "; - function->GetAddressRange().Dump(s, target, Address::DumpStyleLoadAddress, Address::DumpStyleModuleWithFileAddress); - s->EOL(); - s->Indent(); - Type* func_type = function->GetType(); - if (func_type) - { - *s << " Type = "; - func_type->Dump (s, false); - } - } - s->EOL(); - s->Indent(); - *s << "Block = " << block; - if (block != nullptr) - *s << " {0x" << block->GetID() << '}'; - // Dump the block and pass it a negative depth to we print all the parent blocks - //if (block != NULL) - // block->Dump(s, function->GetFileAddress(), INT_MIN); - s->EOL(); - s->Indent(); - *s << "LineEntry = "; - line_entry.Dump (s, target, true, Address::DumpStyleLoadAddress, Address::DumpStyleModuleWithFileAddress, true); - s->EOL(); - s->Indent(); - *s << "Symbol = " << symbol; - if (symbol != nullptr && symbol->GetMangled()) - *s << ' ' << symbol->GetName().AsCString(); - s->EOL(); - *s << "Variable = " << variable; - if (variable != nullptr) - { - *s << " {0x" << variable->GetID() << "} " << variable->GetType()->GetName(); - s->EOL(); - } - s->IndentLess(); - s->IndentLess(); + } + s->IndentLess(); + s->IndentLess(); } -bool -lldb_private::operator== (const SymbolContext& lhs, const SymbolContext& rhs) -{ - return lhs.function == rhs.function - && lhs.symbol == rhs.symbol - && lhs.module_sp.get() == rhs.module_sp.get() - && lhs.comp_unit == rhs.comp_unit - && lhs.target_sp.get() == rhs.target_sp.get() - && LineEntry::Compare(lhs.line_entry, rhs.line_entry) == 0 - && lhs.variable == rhs.variable; +bool lldb_private::operator==(const SymbolContext &lhs, + const SymbolContext &rhs) { + return lhs.function == rhs.function && lhs.symbol == rhs.symbol && + lhs.module_sp.get() == rhs.module_sp.get() && + lhs.comp_unit == rhs.comp_unit && + lhs.target_sp.get() == rhs.target_sp.get() && + LineEntry::Compare(lhs.line_entry, rhs.line_entry) == 0 && + lhs.variable == rhs.variable; } -bool -lldb_private::operator!= (const SymbolContext& lhs, const SymbolContext& rhs) -{ - return lhs.function != rhs.function - || lhs.symbol != rhs.symbol - || lhs.module_sp.get() != rhs.module_sp.get() - || lhs.comp_unit != rhs.comp_unit - || lhs.target_sp.get() != rhs.target_sp.get() - || LineEntry::Compare(lhs.line_entry, rhs.line_entry) != 0 - || lhs.variable != rhs.variable; +bool lldb_private::operator!=(const SymbolContext &lhs, + const SymbolContext &rhs) { + return lhs.function != rhs.function || lhs.symbol != rhs.symbol || + lhs.module_sp.get() != rhs.module_sp.get() || + lhs.comp_unit != rhs.comp_unit || + lhs.target_sp.get() != rhs.target_sp.get() || + LineEntry::Compare(lhs.line_entry, rhs.line_entry) != 0 || + lhs.variable != rhs.variable; } -bool -SymbolContext::GetAddressRange (uint32_t scope, - uint32_t range_idx, - bool use_inline_block_range, - AddressRange &range) const -{ - if ((scope & eSymbolContextLineEntry) && line_entry.IsValid()) - { - range = line_entry.range; +bool SymbolContext::GetAddressRange(uint32_t scope, uint32_t range_idx, + bool use_inline_block_range, + AddressRange &range) const { + if ((scope & eSymbolContextLineEntry) && line_entry.IsValid()) { + range = line_entry.range; + return true; + } + + if ((scope & eSymbolContextBlock) && (block != nullptr)) { + if (use_inline_block_range) { + Block *inline_block = block->GetContainingInlinedBlock(); + if (inline_block) + return inline_block->GetRangeAtIndex(range_idx, range); + } else { + return block->GetRangeAtIndex(range_idx, range); + } + } + + if ((scope & eSymbolContextFunction) && (function != nullptr)) { + if (range_idx == 0) { + range = function->GetAddressRange(); + return true; + } + } + + if ((scope & eSymbolContextSymbol) && (symbol != nullptr)) { + if (range_idx == 0) { + if (symbol->ValueIsAddress()) { + range.GetBaseAddress() = symbol->GetAddressRef(); + range.SetByteSize(symbol->GetByteSize()); return true; + } } - - if ((scope & eSymbolContextBlock) && (block != nullptr)) - { - if (use_inline_block_range) - { - Block *inline_block = block->GetContainingInlinedBlock(); - if (inline_block) - return inline_block->GetRangeAtIndex (range_idx, range); - } - else - { - return block->GetRangeAtIndex (range_idx, range); - } - } - - if ((scope & eSymbolContextFunction) && (function != nullptr)) - { - if (range_idx == 0) - { - range = function->GetAddressRange(); - return true; - } - } - - if ((scope & eSymbolContextSymbol) && (symbol != nullptr)) - { - if (range_idx == 0) - { - if (symbol->ValueIsAddress()) - { - range.GetBaseAddress() = symbol->GetAddressRef(); - range.SetByteSize (symbol->GetByteSize()); - return true; - } - } - } - range.Clear(); - return false; + } + range.Clear(); + return false; } -LanguageType -SymbolContext::GetLanguage () const -{ - LanguageType lang; - if (function && - (lang = function->GetLanguage()) != eLanguageTypeUnknown) - { - return lang; - } - else if (variable && - (lang = variable->GetLanguage()) != eLanguageTypeUnknown) - { - return lang; - } - else if (symbol && - (lang = symbol->GetLanguage()) != eLanguageTypeUnknown) - { - return lang; - } - else if (comp_unit && - (lang = comp_unit->GetLanguage()) != eLanguageTypeUnknown) - { - return lang; - } - else if (symbol) - { - // If all else fails, try to guess the language from the name. - return symbol->GetMangled().GuessLanguage(); - } - return eLanguageTypeUnknown; +LanguageType SymbolContext::GetLanguage() const { + LanguageType lang; + if (function && (lang = function->GetLanguage()) != eLanguageTypeUnknown) { + return lang; + } else if (variable && + (lang = variable->GetLanguage()) != eLanguageTypeUnknown) { + return lang; + } else if (symbol && (lang = symbol->GetLanguage()) != eLanguageTypeUnknown) { + return lang; + } else if (comp_unit && + (lang = comp_unit->GetLanguage()) != eLanguageTypeUnknown) { + return lang; + } else if (symbol) { + // If all else fails, try to guess the language from the name. + return symbol->GetMangled().GuessLanguage(); + } + return eLanguageTypeUnknown; } -bool -SymbolContext::GetParentOfInlinedScope (const Address &curr_frame_pc, - SymbolContext &next_frame_sc, - Address &next_frame_pc) const -{ - next_frame_sc.Clear(false); - next_frame_pc.Clear(); - - if (block) - { - //const addr_t curr_frame_file_addr = curr_frame_pc.GetFileAddress(); - - // In order to get the parent of an inlined function we first need to - // see if we are in an inlined block as "this->block" could be an - // inlined block, or a parent of "block" could be. So lets check if - // this block or one of this blocks parents is an inlined function. - Block *curr_inlined_block = block->GetContainingInlinedBlock(); - if (curr_inlined_block) - { - // "this->block" is contained in an inline function block, so to - // get the scope above the inlined block, we get the parent of the - // inlined block itself - Block *next_frame_block = curr_inlined_block->GetParent(); - // Now calculate the symbol context of the containing block - next_frame_block->CalculateSymbolContext (&next_frame_sc); - - // If we get here we weren't able to find the return line entry using the nesting of the blocks and - // the line table. So just use the call site info from our inlined block. - - AddressRange range; - if (curr_inlined_block->GetRangeContainingAddress (curr_frame_pc, range)) - { - // To see there this new frame block it, we need to look at the - // call site information from - const InlineFunctionInfo* curr_inlined_block_inlined_info = curr_inlined_block->GetInlinedFunctionInfo(); - next_frame_pc = range.GetBaseAddress(); - next_frame_sc.line_entry.range.GetBaseAddress() = next_frame_pc; - next_frame_sc.line_entry.file = curr_inlined_block_inlined_info->GetCallSite().GetFile(); - next_frame_sc.line_entry.original_file = curr_inlined_block_inlined_info->GetCallSite().GetFile(); - next_frame_sc.line_entry.line = curr_inlined_block_inlined_info->GetCallSite().GetLine(); - next_frame_sc.line_entry.column = curr_inlined_block_inlined_info->GetCallSite().GetColumn(); - return true; - } - else - { - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_SYMBOLS)); - - if (log) - { - log->Printf ("warning: inlined block 0x%8.8" PRIx64 " doesn't have a range that contains file address 0x%" PRIx64, - curr_inlined_block->GetID(), curr_frame_pc.GetFileAddress()); - } +bool SymbolContext::GetParentOfInlinedScope(const Address &curr_frame_pc, + SymbolContext &next_frame_sc, + Address &next_frame_pc) const { + next_frame_sc.Clear(false); + next_frame_pc.Clear(); + + if (block) { + // const addr_t curr_frame_file_addr = curr_frame_pc.GetFileAddress(); + + // In order to get the parent of an inlined function we first need to + // see if we are in an inlined block as "this->block" could be an + // inlined block, or a parent of "block" could be. So lets check if + // this block or one of this blocks parents is an inlined function. + Block *curr_inlined_block = block->GetContainingInlinedBlock(); + if (curr_inlined_block) { + // "this->block" is contained in an inline function block, so to + // get the scope above the inlined block, we get the parent of the + // inlined block itself + Block *next_frame_block = curr_inlined_block->GetParent(); + // Now calculate the symbol context of the containing block + next_frame_block->CalculateSymbolContext(&next_frame_sc); + + // If we get here we weren't able to find the return line entry using the + // nesting of the blocks and + // the line table. So just use the call site info from our inlined block. + + AddressRange range; + if (curr_inlined_block->GetRangeContainingAddress(curr_frame_pc, range)) { + // To see there this new frame block it, we need to look at the + // call site information from + const InlineFunctionInfo *curr_inlined_block_inlined_info = + curr_inlined_block->GetInlinedFunctionInfo(); + next_frame_pc = range.GetBaseAddress(); + next_frame_sc.line_entry.range.GetBaseAddress() = next_frame_pc; + next_frame_sc.line_entry.file = + curr_inlined_block_inlined_info->GetCallSite().GetFile(); + next_frame_sc.line_entry.original_file = + curr_inlined_block_inlined_info->GetCallSite().GetFile(); + next_frame_sc.line_entry.line = + curr_inlined_block_inlined_info->GetCallSite().GetLine(); + next_frame_sc.line_entry.column = + curr_inlined_block_inlined_info->GetCallSite().GetColumn(); + return true; + } else { + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_SYMBOLS)); + + if (log) { + log->Printf( + "warning: inlined block 0x%8.8" PRIx64 + " doesn't have a range that contains file address 0x%" PRIx64, + curr_inlined_block->GetID(), curr_frame_pc.GetFileAddress()); + } #ifdef LLDB_CONFIGURATION_DEBUG - else - { - ObjectFile *objfile = NULL; - if (module_sp) - { - SymbolVendor *symbol_vendor = module_sp->GetSymbolVendor(); - if (symbol_vendor) - { - SymbolFile *symbol_file = symbol_vendor->GetSymbolFile(); - if (symbol_file) - objfile = symbol_file->GetObjectFile(); - } - } - if (objfile) - { - Host::SystemLog (Host::eSystemLogWarning, - "warning: inlined block 0x%8.8" PRIx64 " doesn't have a range that contains file address 0x%" PRIx64 " in %s\n", - curr_inlined_block->GetID(), - curr_frame_pc.GetFileAddress(), - objfile->GetFileSpec().GetPath().c_str()); - } - else - { - Host::SystemLog (Host::eSystemLogWarning, - "warning: inlined block 0x%8.8" PRIx64 " doesn't have a range that contains file address 0x%" PRIx64 "\n", - curr_inlined_block->GetID(), - curr_frame_pc.GetFileAddress()); - } - } -#endif + else { + ObjectFile *objfile = NULL; + if (module_sp) { + SymbolVendor *symbol_vendor = module_sp->GetSymbolVendor(); + if (symbol_vendor) { + SymbolFile *symbol_file = symbol_vendor->GetSymbolFile(); + if (symbol_file) + objfile = symbol_file->GetObjectFile(); } + } + if (objfile) { + Host::SystemLog( + Host::eSystemLogWarning, + "warning: inlined block 0x%8.8" PRIx64 + " doesn't have a range that contains file address 0x%" PRIx64 + " in %s\n", + curr_inlined_block->GetID(), curr_frame_pc.GetFileAddress(), + objfile->GetFileSpec().GetPath().c_str()); + } else { + Host::SystemLog( + Host::eSystemLogWarning, + "warning: inlined block 0x%8.8" PRIx64 + " doesn't have a range that contains file address 0x%" PRIx64 + "\n", + curr_inlined_block->GetID(), curr_frame_pc.GetFileAddress()); + } } +#endif + } } - - return false; -} + } -Block * -SymbolContext::GetFunctionBlock () -{ - if (function) - { - if (block) - { - // If this symbol context has a block, check to see if this block - // is itself, or is contained within a block with inlined function - // information. If so, then the inlined block is the block that - // defines the function. - Block *inlined_block = block->GetContainingInlinedBlock(); - if (inlined_block) - return inlined_block; - - // The block in this symbol context is not inside an inlined - // block, so the block that defines the function is the function's - // top level block, which is returned below. - } - - // There is no block information in this symbol context, so we must - // assume that the block that is desired is the top level block of - // the function itself. - return &function->GetBlock(true); - } - return nullptr; + return false; } -bool -SymbolContext::GetFunctionMethodInfo (lldb::LanguageType &language, - bool &is_instance_method, - ConstString &language_object_name) +Block *SymbolContext::GetFunctionBlock() { + if (function) { + if (block) { + // If this symbol context has a block, check to see if this block + // is itself, or is contained within a block with inlined function + // information. If so, then the inlined block is the block that + // defines the function. + Block *inlined_block = block->GetContainingInlinedBlock(); + if (inlined_block) + return inlined_block; + + // The block in this symbol context is not inside an inlined + // block, so the block that defines the function is the function's + // top level block, which is returned below. + } + + // There is no block information in this symbol context, so we must + // assume that the block that is desired is the top level block of + // the function itself. + return &function->GetBlock(true); + } + return nullptr; +} +bool SymbolContext::GetFunctionMethodInfo(lldb::LanguageType &language, + bool &is_instance_method, + ConstString &language_object_name) { - Block *function_block = GetFunctionBlock(); - if (function_block) - { - CompilerDeclContext decl_ctx = function_block->GetDeclContext(); - if (decl_ctx) - return decl_ctx.IsClassMethod(&language, &is_instance_method, &language_object_name); - } - return false; + Block *function_block = GetFunctionBlock(); + if (function_block) { + CompilerDeclContext decl_ctx = function_block->GetDeclContext(); + if (decl_ctx) + return decl_ctx.IsClassMethod(&language, &is_instance_method, + &language_object_name); + } + return false; } -void -SymbolContext::SortTypeList(TypeMap &type_map, TypeList &type_list) const -{ - Block * curr_block = block; - bool isInlinedblock = false; - if (curr_block != nullptr && curr_block->GetContainingInlinedBlock() != nullptr) - isInlinedblock = true; - - //---------------------------------------------------------------------- - // Find all types that match the current block if we have one and put - // them first in the list. Keep iterating up through all blocks. - //---------------------------------------------------------------------- - while (curr_block != nullptr && !isInlinedblock) - { - type_map.ForEach([curr_block, &type_list](const lldb::TypeSP& type_sp) -> bool { - SymbolContextScope *scs = type_sp->GetSymbolContextScope(); - if (scs && curr_block == scs->CalculateSymbolContextBlock()) - type_list.Insert(type_sp); - return true; // Keep iterating - }); - - // Remove any entries that are now in "type_list" from "type_map" - // since we can't remove from type_map while iterating - type_list.ForEach([&type_map](const lldb::TypeSP& type_sp) -> bool { - type_map.Remove(type_sp); - return true; // Keep iterating - }); - curr_block = curr_block->GetParent(); - } - //---------------------------------------------------------------------- - // Find all types that match the current function, if we have onem, and - // put them next in the list. - //---------------------------------------------------------------------- - if (function != nullptr && !type_map.Empty()) - { - const size_t old_type_list_size = type_list.GetSize(); - type_map.ForEach([this, &type_list](const lldb::TypeSP& type_sp) -> bool { - SymbolContextScope *scs = type_sp->GetSymbolContextScope(); - if (scs && function == scs->CalculateSymbolContextFunction()) - type_list.Insert(type_sp); - return true; // Keep iterating - }); - - // Remove any entries that are now in "type_list" from "type_map" - // since we can't remove from type_map while iterating - const size_t new_type_list_size = type_list.GetSize(); - if (new_type_list_size > old_type_list_size) - { - for (size_t i=old_type_list_size; i<new_type_list_size; ++i) - type_map.Remove(type_list.GetTypeAtIndex(i)); - } - } - //---------------------------------------------------------------------- - // Find all types that match the current compile unit, if we have one, - // and put them next in the list. - //---------------------------------------------------------------------- - if (comp_unit != nullptr && !type_map.Empty()) - { - const size_t old_type_list_size = type_list.GetSize(); - - type_map.ForEach([this, &type_list](const lldb::TypeSP& type_sp) -> bool { - SymbolContextScope *scs = type_sp->GetSymbolContextScope(); - if (scs && comp_unit == scs->CalculateSymbolContextCompileUnit()) - type_list.Insert(type_sp); - return true; // Keep iterating - }); - - // Remove any entries that are now in "type_list" from "type_map" - // since we can't remove from type_map while iterating - const size_t new_type_list_size = type_list.GetSize(); - if (new_type_list_size > old_type_list_size) - { - for (size_t i=old_type_list_size; i<new_type_list_size; ++i) - type_map.Remove(type_list.GetTypeAtIndex(i)); - } - } - //---------------------------------------------------------------------- - // Find all types that match the current module, if we have one, and put - // them next in the list. - //---------------------------------------------------------------------- - if (module_sp && !type_map.Empty()) - { - const size_t old_type_list_size = type_list.GetSize(); - type_map.ForEach([this, &type_list](const lldb::TypeSP& type_sp) -> bool { - SymbolContextScope *scs = type_sp->GetSymbolContextScope(); - if (scs && module_sp == scs->CalculateSymbolContextModule()) - type_list.Insert(type_sp); - return true; // Keep iterating - }); - // Remove any entries that are now in "type_list" from "type_map" - // since we can't remove from type_map while iterating - const size_t new_type_list_size = type_list.GetSize(); - if (new_type_list_size > old_type_list_size) - { - for (size_t i=old_type_list_size; i<new_type_list_size; ++i) - type_map.Remove(type_list.GetTypeAtIndex(i)); - } - } - //---------------------------------------------------------------------- - // Any types that are left get copied into the list an any order. - //---------------------------------------------------------------------- - if (!type_map.Empty()) - { - type_map.ForEach([&type_list](const lldb::TypeSP& type_sp) -> bool { +void SymbolContext::SortTypeList(TypeMap &type_map, TypeList &type_list) const { + Block *curr_block = block; + bool isInlinedblock = false; + if (curr_block != nullptr && + curr_block->GetContainingInlinedBlock() != nullptr) + isInlinedblock = true; + + //---------------------------------------------------------------------- + // Find all types that match the current block if we have one and put + // them first in the list. Keep iterating up through all blocks. + //---------------------------------------------------------------------- + while (curr_block != nullptr && !isInlinedblock) { + type_map.ForEach( + [curr_block, &type_list](const lldb::TypeSP &type_sp) -> bool { + SymbolContextScope *scs = type_sp->GetSymbolContextScope(); + if (scs && curr_block == scs->CalculateSymbolContextBlock()) type_list.Insert(type_sp); - return true; // Keep iterating + return true; // Keep iterating }); - } + + // Remove any entries that are now in "type_list" from "type_map" + // since we can't remove from type_map while iterating + type_list.ForEach([&type_map](const lldb::TypeSP &type_sp) -> bool { + type_map.Remove(type_sp); + return true; // Keep iterating + }); + curr_block = curr_block->GetParent(); + } + //---------------------------------------------------------------------- + // Find all types that match the current function, if we have onem, and + // put them next in the list. + //---------------------------------------------------------------------- + if (function != nullptr && !type_map.Empty()) { + const size_t old_type_list_size = type_list.GetSize(); + type_map.ForEach([this, &type_list](const lldb::TypeSP &type_sp) -> bool { + SymbolContextScope *scs = type_sp->GetSymbolContextScope(); + if (scs && function == scs->CalculateSymbolContextFunction()) + type_list.Insert(type_sp); + return true; // Keep iterating + }); + + // Remove any entries that are now in "type_list" from "type_map" + // since we can't remove from type_map while iterating + const size_t new_type_list_size = type_list.GetSize(); + if (new_type_list_size > old_type_list_size) { + for (size_t i = old_type_list_size; i < new_type_list_size; ++i) + type_map.Remove(type_list.GetTypeAtIndex(i)); + } + } + //---------------------------------------------------------------------- + // Find all types that match the current compile unit, if we have one, + // and put them next in the list. + //---------------------------------------------------------------------- + if (comp_unit != nullptr && !type_map.Empty()) { + const size_t old_type_list_size = type_list.GetSize(); + + type_map.ForEach([this, &type_list](const lldb::TypeSP &type_sp) -> bool { + SymbolContextScope *scs = type_sp->GetSymbolContextScope(); + if (scs && comp_unit == scs->CalculateSymbolContextCompileUnit()) + type_list.Insert(type_sp); + return true; // Keep iterating + }); + + // Remove any entries that are now in "type_list" from "type_map" + // since we can't remove from type_map while iterating + const size_t new_type_list_size = type_list.GetSize(); + if (new_type_list_size > old_type_list_size) { + for (size_t i = old_type_list_size; i < new_type_list_size; ++i) + type_map.Remove(type_list.GetTypeAtIndex(i)); + } + } + //---------------------------------------------------------------------- + // Find all types that match the current module, if we have one, and put + // them next in the list. + //---------------------------------------------------------------------- + if (module_sp && !type_map.Empty()) { + const size_t old_type_list_size = type_list.GetSize(); + type_map.ForEach([this, &type_list](const lldb::TypeSP &type_sp) -> bool { + SymbolContextScope *scs = type_sp->GetSymbolContextScope(); + if (scs && module_sp == scs->CalculateSymbolContextModule()) + type_list.Insert(type_sp); + return true; // Keep iterating + }); + // Remove any entries that are now in "type_list" from "type_map" + // since we can't remove from type_map while iterating + const size_t new_type_list_size = type_list.GetSize(); + if (new_type_list_size > old_type_list_size) { + for (size_t i = old_type_list_size; i < new_type_list_size; ++i) + type_map.Remove(type_list.GetTypeAtIndex(i)); + } + } + //---------------------------------------------------------------------- + // Any types that are left get copied into the list an any order. + //---------------------------------------------------------------------- + if (!type_map.Empty()) { + type_map.ForEach([&type_list](const lldb::TypeSP &type_sp) -> bool { + type_list.Insert(type_sp); + return true; // Keep iterating + }); + } } ConstString -SymbolContext::GetFunctionName (Mangled::NamePreference preference) const -{ - if (function) - { - if (block) - { - Block *inlined_block = block->GetContainingInlinedBlock(); - - if (inlined_block) - { - const InlineFunctionInfo *inline_info = inlined_block->GetInlinedFunctionInfo(); - if (inline_info) - return inline_info->GetName(function->GetLanguage()); - } - } - return function->GetMangled().GetName(function->GetLanguage(), preference); - } - else if (symbol && symbol->ValueIsAddress()) - { - return symbol->GetMangled().GetName(symbol->GetLanguage(), preference); - } - else - { - // No function, return an empty string. - return ConstString(); - } +SymbolContext::GetFunctionName(Mangled::NamePreference preference) const { + if (function) { + if (block) { + Block *inlined_block = block->GetContainingInlinedBlock(); + + if (inlined_block) { + const InlineFunctionInfo *inline_info = + inlined_block->GetInlinedFunctionInfo(); + if (inline_info) + return inline_info->GetName(function->GetLanguage()); + } + } + return function->GetMangled().GetName(function->GetLanguage(), preference); + } else if (symbol && symbol->ValueIsAddress()) { + return symbol->GetMangled().GetName(symbol->GetLanguage(), preference); + } else { + // No function, return an empty string. + return ConstString(); + } } -LineEntry -SymbolContext::GetFunctionStartLineEntry () const -{ - LineEntry line_entry; - Address start_addr; - if (block) - { - Block *inlined_block = block->GetContainingInlinedBlock(); - if (inlined_block) - { - if (inlined_block->GetStartAddress (start_addr)) - { - if (start_addr.CalculateSymbolContextLineEntry (line_entry)) - return line_entry; - } - return LineEntry(); - } - } - - if (function) - { - if (function->GetAddressRange().GetBaseAddress().CalculateSymbolContextLineEntry(line_entry)) - return line_entry; - } - return LineEntry(); +LineEntry SymbolContext::GetFunctionStartLineEntry() const { + LineEntry line_entry; + Address start_addr; + if (block) { + Block *inlined_block = block->GetContainingInlinedBlock(); + if (inlined_block) { + if (inlined_block->GetStartAddress(start_addr)) { + if (start_addr.CalculateSymbolContextLineEntry(line_entry)) + return line_entry; + } + return LineEntry(); + } + } + + if (function) { + if (function->GetAddressRange() + .GetBaseAddress() + .CalculateSymbolContextLineEntry(line_entry)) + return line_entry; + } + return LineEntry(); } -bool -SymbolContext::GetAddressRangeFromHereToEndLine(uint32_t end_line, AddressRange &range, Error &error) -{ - if (!line_entry.IsValid()) - { - error.SetErrorString("Symbol context has no line table."); - return false; - } - - range = line_entry.range; - if (line_entry.line > end_line) - { - error.SetErrorStringWithFormat("end line option %d must be after the current line: %d", - end_line, - line_entry.line); - return false; - } +bool SymbolContext::GetAddressRangeFromHereToEndLine(uint32_t end_line, + AddressRange &range, + Error &error) { + if (!line_entry.IsValid()) { + error.SetErrorString("Symbol context has no line table."); + return false; + } - uint32_t line_index = 0; - bool found = false; - while (1) - { - LineEntry this_line; - line_index = comp_unit->FindLineEntry(line_index, line_entry.line, nullptr, false, &this_line); - if (line_index == UINT32_MAX) - break; - if (LineEntry::Compare(this_line, line_entry) == 0) - { - found = true; - break; - } - } - - LineEntry end_entry; - if (!found) - { - // Can't find the index of the SymbolContext's line entry in the SymbolContext's CompUnit. - error.SetErrorString("Can't find the current line entry in the CompUnit - can't process " - "the end-line option"); - return false; - } - - line_index = comp_unit->FindLineEntry(line_index, end_line, nullptr, false, &end_entry); + range = line_entry.range; + if (line_entry.line > end_line) { + error.SetErrorStringWithFormat( + "end line option %d must be after the current line: %d", end_line, + line_entry.line); + return false; + } + + uint32_t line_index = 0; + bool found = false; + while (1) { + LineEntry this_line; + line_index = comp_unit->FindLineEntry(line_index, line_entry.line, nullptr, + false, &this_line); if (line_index == UINT32_MAX) - { - error.SetErrorStringWithFormat("could not find a line table entry corresponding " - "to end line number %d", - end_line); - return false; - } - - Block *func_block = GetFunctionBlock(); - if (func_block && func_block->GetRangeIndexContainingAddress(end_entry.range.GetBaseAddress()) == UINT32_MAX) - { - error.SetErrorStringWithFormat("end line number %d is not contained within the current function.", - end_line); - return false; - } - - lldb::addr_t range_size = end_entry.range.GetBaseAddress().GetFileAddress() - - range.GetBaseAddress().GetFileAddress(); - range.SetByteSize(range_size); - return true; -} - + break; + if (LineEntry::Compare(this_line, line_entry) == 0) { + found = true; + break; + } + } + + LineEntry end_entry; + if (!found) { + // Can't find the index of the SymbolContext's line entry in the + // SymbolContext's CompUnit. + error.SetErrorString( + "Can't find the current line entry in the CompUnit - can't process " + "the end-line option"); + return false; + } + + line_index = comp_unit->FindLineEntry(line_index, end_line, nullptr, false, + &end_entry); + if (line_index == UINT32_MAX) { + error.SetErrorStringWithFormat( + "could not find a line table entry corresponding " + "to end line number %d", + end_line); + return false; + } + + Block *func_block = GetFunctionBlock(); + if (func_block && + func_block->GetRangeIndexContainingAddress( + end_entry.range.GetBaseAddress()) == UINT32_MAX) { + error.SetErrorStringWithFormat( + "end line number %d is not contained within the current function.", + end_line); + return false; + } + lldb::addr_t range_size = end_entry.range.GetBaseAddress().GetFileAddress() - + range.GetBaseAddress().GetFileAddress(); + range.SetByteSize(range_size); + return true; +} //---------------------------------------------------------------------- // @@ -935,310 +805,263 @@ SymbolContext::GetAddressRangeFromHereToEndLine(uint32_t end_line, AddressRange // //---------------------------------------------------------------------- -SymbolContextSpecifier::SymbolContextSpecifier (const TargetSP &target_sp) : - m_target_sp (target_sp), - m_module_spec (), - m_module_sp (), - m_file_spec_ap (), - m_start_line (0), - m_end_line (0), - m_function_spec (), - m_class_name (), - m_address_range_ap (), - m_type (eNothingSpecified) -{ -} - -SymbolContextSpecifier::~SymbolContextSpecifier() -{ +SymbolContextSpecifier::SymbolContextSpecifier(const TargetSP &target_sp) + : m_target_sp(target_sp), m_module_spec(), m_module_sp(), m_file_spec_ap(), + m_start_line(0), m_end_line(0), m_function_spec(), m_class_name(), + m_address_range_ap(), m_type(eNothingSpecified) {} + +SymbolContextSpecifier::~SymbolContextSpecifier() {} + +bool SymbolContextSpecifier::AddLineSpecification(uint32_t line_no, + SpecificationType type) { + bool return_value = true; + switch (type) { + case eNothingSpecified: + Clear(); + break; + case eLineStartSpecified: + m_start_line = line_no; + m_type |= eLineStartSpecified; + break; + case eLineEndSpecified: + m_end_line = line_no; + m_type |= eLineEndSpecified; + break; + default: + return_value = false; + break; + } + return return_value; } -bool -SymbolContextSpecifier::AddLineSpecification (uint32_t line_no, SpecificationType type) -{ - bool return_value = true; - switch (type) - { - case eNothingSpecified: - Clear(); - break; - case eLineStartSpecified: - m_start_line = line_no; - m_type |= eLineStartSpecified; - break; - case eLineEndSpecified: - m_end_line = line_no; - m_type |= eLineEndSpecified; - break; - default: - return_value = false; - break; - } - return return_value; +bool SymbolContextSpecifier::AddSpecification(const char *spec_string, + SpecificationType type) { + bool return_value = true; + switch (type) { + case eNothingSpecified: + Clear(); + break; + case eModuleSpecified: { + // See if we can find the Module, if so stick it in the SymbolContext. + FileSpec module_file_spec(spec_string, false); + ModuleSpec module_spec(module_file_spec); + lldb::ModuleSP module_sp( + m_target_sp->GetImages().FindFirstModule(module_spec)); + m_type |= eModuleSpecified; + if (module_sp) + m_module_sp = module_sp; + else + m_module_spec.assign(spec_string); + } break; + case eFileSpecified: + // CompUnits can't necessarily be resolved here, since an inlined function + // might show up in + // a number of CompUnits. Instead we just convert to a FileSpec and store + // it away. + m_file_spec_ap.reset(new FileSpec(spec_string, false)); + m_type |= eFileSpecified; + break; + case eLineStartSpecified: + m_start_line = StringConvert::ToSInt32(spec_string, 0, 0, &return_value); + if (return_value) + m_type |= eLineStartSpecified; + break; + case eLineEndSpecified: + m_end_line = StringConvert::ToSInt32(spec_string, 0, 0, &return_value); + if (return_value) + m_type |= eLineEndSpecified; + break; + case eFunctionSpecified: + m_function_spec.assign(spec_string); + m_type |= eFunctionSpecified; + break; + case eClassOrNamespaceSpecified: + Clear(); + m_class_name.assign(spec_string); + m_type = eClassOrNamespaceSpecified; + break; + case eAddressRangeSpecified: + // Not specified yet... + break; + } + + return return_value; } -bool -SymbolContextSpecifier::AddSpecification (const char *spec_string, SpecificationType type) -{ - bool return_value = true; - switch (type) - { - case eNothingSpecified: - Clear(); - break; - case eModuleSpecified: - { - // See if we can find the Module, if so stick it in the SymbolContext. - FileSpec module_file_spec(spec_string, false); - ModuleSpec module_spec (module_file_spec); - lldb::ModuleSP module_sp (m_target_sp->GetImages().FindFirstModule (module_spec)); - m_type |= eModuleSpecified; - if (module_sp) - m_module_sp = module_sp; - else - m_module_spec.assign (spec_string); - } - break; - case eFileSpecified: - // CompUnits can't necessarily be resolved here, since an inlined function might show up in - // a number of CompUnits. Instead we just convert to a FileSpec and store it away. - m_file_spec_ap.reset (new FileSpec (spec_string, false)); - m_type |= eFileSpecified; - break; - case eLineStartSpecified: - m_start_line = StringConvert::ToSInt32(spec_string, 0, 0, &return_value); - if (return_value) - m_type |= eLineStartSpecified; - break; - case eLineEndSpecified: - m_end_line = StringConvert::ToSInt32(spec_string, 0, 0, &return_value); - if (return_value) - m_type |= eLineEndSpecified; - break; - case eFunctionSpecified: - m_function_spec.assign(spec_string); - m_type |= eFunctionSpecified; - break; - case eClassOrNamespaceSpecified: - Clear(); - m_class_name.assign (spec_string); - m_type = eClassOrNamespaceSpecified; - break; - case eAddressRangeSpecified: - // Not specified yet... - break; - } - - return return_value; -} +void SymbolContextSpecifier::Clear() { + m_module_spec.clear(); + m_file_spec_ap.reset(); + m_function_spec.clear(); + m_class_name.clear(); + m_start_line = 0; + m_end_line = 0; + m_address_range_ap.reset(); -void -SymbolContextSpecifier::Clear() -{ - m_module_spec.clear(); - m_file_spec_ap.reset(); - m_function_spec.clear(); - m_class_name.clear(); - m_start_line = 0; - m_end_line = 0; - m_address_range_ap.reset(); - - m_type = eNothingSpecified; + m_type = eNothingSpecified; } -bool -SymbolContextSpecifier::SymbolContextMatches(SymbolContext &sc) -{ - if (m_type == eNothingSpecified) - return true; - - if (m_target_sp.get() != sc.target_sp.get()) +bool SymbolContextSpecifier::SymbolContextMatches(SymbolContext &sc) { + if (m_type == eNothingSpecified) + return true; + + if (m_target_sp.get() != sc.target_sp.get()) + return false; + + if (m_type & eModuleSpecified) { + if (sc.module_sp) { + if (m_module_sp.get() != nullptr) { + if (m_module_sp.get() != sc.module_sp.get()) + return false; + } else { + FileSpec module_file_spec(m_module_spec.c_str(), false); + if (!FileSpec::Equal(module_file_spec, sc.module_sp->GetFileSpec(), + false)) + return false; + } + } + } + if (m_type & eFileSpecified) { + if (m_file_spec_ap.get()) { + // If we don't have a block or a comp_unit, then we aren't going to match + // a source file. + if (sc.block == nullptr && sc.comp_unit == nullptr) return false; - - if (m_type & eModuleSpecified) - { - if (sc.module_sp) - { - if (m_module_sp.get() != nullptr) - { - if (m_module_sp.get() != sc.module_sp.get()) - return false; - } - else - { - FileSpec module_file_spec (m_module_spec.c_str(), false); - if (!FileSpec::Equal (module_file_spec, sc.module_sp->GetFileSpec(), false)) - return false; - } - } - } - if (m_type & eFileSpecified) - { - if (m_file_spec_ap.get()) - { - // If we don't have a block or a comp_unit, then we aren't going to match a source file. - if (sc.block == nullptr && sc.comp_unit == nullptr) - return false; - - // Check if the block is present, and if so is it inlined: - bool was_inlined = false; - if (sc.block != nullptr) - { - const InlineFunctionInfo *inline_info = sc.block->GetInlinedFunctionInfo(); - if (inline_info != nullptr) - { - was_inlined = true; - if (!FileSpec::Equal (inline_info->GetDeclaration().GetFile(), *(m_file_spec_ap.get()), false)) - return false; - } - } - - // Next check the comp unit, but only if the SymbolContext was not inlined. - if (!was_inlined && sc.comp_unit != nullptr) - { - if (!FileSpec::Equal (*(sc.comp_unit), *(m_file_spec_ap.get()), false)) - return false; - } - } - } - if (m_type & eLineStartSpecified - || m_type & eLineEndSpecified) - { - if (sc.line_entry.line < m_start_line || sc.line_entry.line > m_end_line) + + // Check if the block is present, and if so is it inlined: + bool was_inlined = false; + if (sc.block != nullptr) { + const InlineFunctionInfo *inline_info = + sc.block->GetInlinedFunctionInfo(); + if (inline_info != nullptr) { + was_inlined = true; + if (!FileSpec::Equal(inline_info->GetDeclaration().GetFile(), + *(m_file_spec_ap.get()), false)) return false; - } - - if (m_type & eFunctionSpecified) - { - // First check the current block, and if it is inlined, get the inlined function name: - bool was_inlined = false; - ConstString func_name(m_function_spec.c_str()); - - if (sc.block != nullptr) - { - const InlineFunctionInfo *inline_info = sc.block->GetInlinedFunctionInfo(); - if (inline_info != nullptr) - { - was_inlined = true; - const Mangled &name = inline_info->GetMangled(); - if (!name.NameMatches (func_name, sc.function->GetLanguage())) - return false; - } - } - // If it wasn't inlined, check the name in the function or symbol: - if (!was_inlined) - { - if (sc.function != nullptr) - { - if (!sc.function->GetMangled().NameMatches(func_name, sc.function->GetLanguage())) - return false; - } - else if (sc.symbol != nullptr) - { - if (!sc.symbol->GetMangled().NameMatches(func_name, sc.symbol->GetLanguage())) - return false; - } } - - - } - - return true; + } + + // Next check the comp unit, but only if the SymbolContext was not + // inlined. + if (!was_inlined && sc.comp_unit != nullptr) { + if (!FileSpec::Equal(*(sc.comp_unit), *(m_file_spec_ap.get()), false)) + return false; + } + } + } + if (m_type & eLineStartSpecified || m_type & eLineEndSpecified) { + if (sc.line_entry.line < m_start_line || sc.line_entry.line > m_end_line) + return false; + } + + if (m_type & eFunctionSpecified) { + // First check the current block, and if it is inlined, get the inlined + // function name: + bool was_inlined = false; + ConstString func_name(m_function_spec.c_str()); + + if (sc.block != nullptr) { + const InlineFunctionInfo *inline_info = + sc.block->GetInlinedFunctionInfo(); + if (inline_info != nullptr) { + was_inlined = true; + const Mangled &name = inline_info->GetMangled(); + if (!name.NameMatches(func_name, sc.function->GetLanguage())) + return false; + } + } + // If it wasn't inlined, check the name in the function or symbol: + if (!was_inlined) { + if (sc.function != nullptr) { + if (!sc.function->GetMangled().NameMatches(func_name, + sc.function->GetLanguage())) + return false; + } else if (sc.symbol != nullptr) { + if (!sc.symbol->GetMangled().NameMatches(func_name, + sc.symbol->GetLanguage())) + return false; + } + } + } + + return true; } -bool -SymbolContextSpecifier::AddressMatches(lldb::addr_t addr) -{ - if (m_type & eAddressRangeSpecified) - { - - } - else - { - Address match_address (addr, nullptr); - SymbolContext sc; - m_target_sp->GetImages().ResolveSymbolContextForAddress(match_address, eSymbolContextEverything, sc); - return SymbolContextMatches(sc); - } - return true; +bool SymbolContextSpecifier::AddressMatches(lldb::addr_t addr) { + if (m_type & eAddressRangeSpecified) { + + } else { + Address match_address(addr, nullptr); + SymbolContext sc; + m_target_sp->GetImages().ResolveSymbolContextForAddress( + match_address, eSymbolContextEverything, sc); + return SymbolContextMatches(sc); + } + return true; } -void -SymbolContextSpecifier::GetDescription (Stream *s, lldb::DescriptionLevel level) const -{ - char path_str[PATH_MAX + 1]; +void SymbolContextSpecifier::GetDescription( + Stream *s, lldb::DescriptionLevel level) const { + char path_str[PATH_MAX + 1]; - if (m_type == eNothingSpecified) - { - s->Printf ("Nothing specified.\n"); - } - - if (m_type == eModuleSpecified) - { - s->Indent(); - if (m_module_sp) - { - m_module_sp->GetFileSpec().GetPath (path_str, PATH_MAX); - s->Printf ("Module: %s\n", path_str); - } - else - s->Printf ("Module: %s\n", m_module_spec.c_str()); - } - - if (m_type == eFileSpecified && m_file_spec_ap.get() != nullptr) - { - m_file_spec_ap->GetPath (path_str, PATH_MAX); - s->Indent(); - s->Printf ("File: %s", path_str); - if (m_type == eLineStartSpecified) - { - s->Printf (" from line %" PRIu64 "", (uint64_t)m_start_line); - if (m_type == eLineEndSpecified) - s->Printf ("to line %" PRIu64 "", (uint64_t)m_end_line); - else - s->Printf ("to end"); - } - else if (m_type == eLineEndSpecified) - { - s->Printf (" from start to line %" PRIu64 "", (uint64_t)m_end_line); - } - s->Printf (".\n"); - } - - if (m_type == eLineStartSpecified) - { - s->Indent(); - s->Printf ("From line %" PRIu64 "", (uint64_t)m_start_line); - if (m_type == eLineEndSpecified) - s->Printf ("to line %" PRIu64 "", (uint64_t)m_end_line); - else - s->Printf ("to end"); - s->Printf (".\n"); - } - else if (m_type == eLineEndSpecified) - { - s->Printf ("From start to line %" PRIu64 ".\n", (uint64_t)m_end_line); - } - - if (m_type == eFunctionSpecified) - { - s->Indent(); - s->Printf ("Function: %s.\n", m_function_spec.c_str()); - } - - if (m_type == eClassOrNamespaceSpecified) - { - s->Indent(); - s->Printf ("Class name: %s.\n", m_class_name.c_str()); - } - - if (m_type == eAddressRangeSpecified && m_address_range_ap.get() != nullptr) - { - s->Indent(); - s->PutCString ("Address range: "); - m_address_range_ap->Dump (s, m_target_sp.get(), Address::DumpStyleLoadAddress, Address::DumpStyleFileAddress); - s->PutCString ("\n"); - } + if (m_type == eNothingSpecified) { + s->Printf("Nothing specified.\n"); + } + + if (m_type == eModuleSpecified) { + s->Indent(); + if (m_module_sp) { + m_module_sp->GetFileSpec().GetPath(path_str, PATH_MAX); + s->Printf("Module: %s\n", path_str); + } else + s->Printf("Module: %s\n", m_module_spec.c_str()); + } + + if (m_type == eFileSpecified && m_file_spec_ap.get() != nullptr) { + m_file_spec_ap->GetPath(path_str, PATH_MAX); + s->Indent(); + s->Printf("File: %s", path_str); + if (m_type == eLineStartSpecified) { + s->Printf(" from line %" PRIu64 "", (uint64_t)m_start_line); + if (m_type == eLineEndSpecified) + s->Printf("to line %" PRIu64 "", (uint64_t)m_end_line); + else + s->Printf("to end"); + } else if (m_type == eLineEndSpecified) { + s->Printf(" from start to line %" PRIu64 "", (uint64_t)m_end_line); + } + s->Printf(".\n"); + } + + if (m_type == eLineStartSpecified) { + s->Indent(); + s->Printf("From line %" PRIu64 "", (uint64_t)m_start_line); + if (m_type == eLineEndSpecified) + s->Printf("to line %" PRIu64 "", (uint64_t)m_end_line); + else + s->Printf("to end"); + s->Printf(".\n"); + } else if (m_type == eLineEndSpecified) { + s->Printf("From start to line %" PRIu64 ".\n", (uint64_t)m_end_line); + } + + if (m_type == eFunctionSpecified) { + s->Indent(); + s->Printf("Function: %s.\n", m_function_spec.c_str()); + } + + if (m_type == eClassOrNamespaceSpecified) { + s->Indent(); + s->Printf("Class name: %s.\n", m_class_name.c_str()); + } + + if (m_type == eAddressRangeSpecified && m_address_range_ap.get() != nullptr) { + s->Indent(); + s->PutCString("Address range: "); + m_address_range_ap->Dump(s, m_target_sp.get(), + Address::DumpStyleLoadAddress, + Address::DumpStyleFileAddress); + s->PutCString("\n"); + } } //---------------------------------------------------------------------- @@ -1247,241 +1070,180 @@ SymbolContextSpecifier::GetDescription (Stream *s, lldb::DescriptionLevel level) // //---------------------------------------------------------------------- +SymbolContextList::SymbolContextList() : m_symbol_contexts() {} -SymbolContextList::SymbolContextList() : - m_symbol_contexts() -{ -} - -SymbolContextList::~SymbolContextList() -{ -} +SymbolContextList::~SymbolContextList() {} -void -SymbolContextList::Append(const SymbolContext& sc) -{ - m_symbol_contexts.push_back(sc); +void SymbolContextList::Append(const SymbolContext &sc) { + m_symbol_contexts.push_back(sc); } -void -SymbolContextList::Append (const SymbolContextList& sc_list) -{ - collection::const_iterator pos, end = sc_list.m_symbol_contexts.end(); - for (pos = sc_list.m_symbol_contexts.begin(); pos != end; ++pos) - m_symbol_contexts.push_back (*pos); +void SymbolContextList::Append(const SymbolContextList &sc_list) { + collection::const_iterator pos, end = sc_list.m_symbol_contexts.end(); + for (pos = sc_list.m_symbol_contexts.begin(); pos != end; ++pos) + m_symbol_contexts.push_back(*pos); } - -uint32_t -SymbolContextList::AppendIfUnique (const SymbolContextList& sc_list, bool merge_symbol_into_function) -{ - uint32_t unique_sc_add_count = 0; - collection::const_iterator pos, end = sc_list.m_symbol_contexts.end(); - for (pos = sc_list.m_symbol_contexts.begin(); pos != end; ++pos) - { - if (AppendIfUnique (*pos, merge_symbol_into_function)) - ++unique_sc_add_count; - } - return unique_sc_add_count; +uint32_t SymbolContextList::AppendIfUnique(const SymbolContextList &sc_list, + bool merge_symbol_into_function) { + uint32_t unique_sc_add_count = 0; + collection::const_iterator pos, end = sc_list.m_symbol_contexts.end(); + for (pos = sc_list.m_symbol_contexts.begin(); pos != end; ++pos) { + if (AppendIfUnique(*pos, merge_symbol_into_function)) + ++unique_sc_add_count; + } + return unique_sc_add_count; } -bool -SymbolContextList::AppendIfUnique (const SymbolContext& sc, bool merge_symbol_into_function) -{ - collection::iterator pos, end = m_symbol_contexts.end(); - for (pos = m_symbol_contexts.begin(); pos != end; ++pos) - { - if (*pos == sc) - return false; - } - if (merge_symbol_into_function - && sc.symbol != nullptr - && sc.comp_unit == nullptr - && sc.function == nullptr - && sc.block == nullptr - && sc.line_entry.IsValid() == false) - { - if (sc.symbol->ValueIsAddress()) - { - for (pos = m_symbol_contexts.begin(); pos != end; ++pos) - { - // Don't merge symbols into inlined function symbol contexts - if (pos->block && pos->block->GetContainingInlinedBlock()) - continue; - - if (pos->function) - { - if (pos->function->GetAddressRange().GetBaseAddress() == sc.symbol->GetAddressRef()) - { - // Do we already have a function with this symbol? - if (pos->symbol == sc.symbol) - return false; - if (pos->symbol == nullptr) - { - pos->symbol = sc.symbol; - return false; - } - } - } +bool SymbolContextList::AppendIfUnique(const SymbolContext &sc, + bool merge_symbol_into_function) { + collection::iterator pos, end = m_symbol_contexts.end(); + for (pos = m_symbol_contexts.begin(); pos != end; ++pos) { + if (*pos == sc) + return false; + } + if (merge_symbol_into_function && sc.symbol != nullptr && + sc.comp_unit == nullptr && sc.function == nullptr && + sc.block == nullptr && sc.line_entry.IsValid() == false) { + if (sc.symbol->ValueIsAddress()) { + for (pos = m_symbol_contexts.begin(); pos != end; ++pos) { + // Don't merge symbols into inlined function symbol contexts + if (pos->block && pos->block->GetContainingInlinedBlock()) + continue; + + if (pos->function) { + if (pos->function->GetAddressRange().GetBaseAddress() == + sc.symbol->GetAddressRef()) { + // Do we already have a function with this symbol? + if (pos->symbol == sc.symbol) + return false; + if (pos->symbol == nullptr) { + pos->symbol = sc.symbol; + return false; } + } } + } } - m_symbol_contexts.push_back(sc); - return true; + } + m_symbol_contexts.push_back(sc); + return true; } -bool -SymbolContextList::MergeSymbolContextIntoFunctionContext (const SymbolContext& symbol_sc, - uint32_t start_idx, - uint32_t stop_idx) -{ - if (symbol_sc.symbol != nullptr - && symbol_sc.comp_unit == nullptr - && symbol_sc.function == nullptr - && symbol_sc.block == nullptr - && symbol_sc.line_entry.IsValid() == false) - { - if (symbol_sc.symbol->ValueIsAddress()) - { - const size_t end = std::min<size_t>(m_symbol_contexts.size(), stop_idx); - for (size_t i=start_idx; i<end; ++i) - { - const SymbolContext &function_sc = m_symbol_contexts[i]; - // Don't merge symbols into inlined function symbol contexts - if (function_sc.block && function_sc.block->GetContainingInlinedBlock()) - continue; - - if (function_sc.function) - { - if (function_sc.function->GetAddressRange().GetBaseAddress() == symbol_sc.symbol->GetAddressRef()) - { - // Do we already have a function with this symbol? - if (function_sc.symbol == symbol_sc.symbol) - return true; // Already have a symbol context with this symbol, return true - - if (function_sc.symbol == nullptr) - { - // We successfully merged this symbol into an existing symbol context - m_symbol_contexts[i].symbol = symbol_sc.symbol; - return true; - } - } - } +bool SymbolContextList::MergeSymbolContextIntoFunctionContext( + const SymbolContext &symbol_sc, uint32_t start_idx, uint32_t stop_idx) { + if (symbol_sc.symbol != nullptr && symbol_sc.comp_unit == nullptr && + symbol_sc.function == nullptr && symbol_sc.block == nullptr && + symbol_sc.line_entry.IsValid() == false) { + if (symbol_sc.symbol->ValueIsAddress()) { + const size_t end = std::min<size_t>(m_symbol_contexts.size(), stop_idx); + for (size_t i = start_idx; i < end; ++i) { + const SymbolContext &function_sc = m_symbol_contexts[i]; + // Don't merge symbols into inlined function symbol contexts + if (function_sc.block && function_sc.block->GetContainingInlinedBlock()) + continue; + + if (function_sc.function) { + if (function_sc.function->GetAddressRange().GetBaseAddress() == + symbol_sc.symbol->GetAddressRef()) { + // Do we already have a function with this symbol? + if (function_sc.symbol == symbol_sc.symbol) + return true; // Already have a symbol context with this symbol, + // return true + + if (function_sc.symbol == nullptr) { + // We successfully merged this symbol into an existing symbol + // context + m_symbol_contexts[i].symbol = symbol_sc.symbol; + return true; } + } } + } } - return false; + } + return false; } -void -SymbolContextList::Clear() -{ - m_symbol_contexts.clear(); -} +void SymbolContextList::Clear() { m_symbol_contexts.clear(); } -void -SymbolContextList::Dump(Stream *s, Target *target) const -{ +void SymbolContextList::Dump(Stream *s, Target *target) const { - *s << this << ": "; - s->Indent(); - s->PutCString("SymbolContextList"); - s->EOL(); - s->IndentMore(); + *s << this << ": "; + s->Indent(); + s->PutCString("SymbolContextList"); + s->EOL(); + s->IndentMore(); - collection::const_iterator pos, end = m_symbol_contexts.end(); - for (pos = m_symbol_contexts.begin(); pos != end; ++pos) - { - //pos->Dump(s, target); - pos->GetDescription(s, eDescriptionLevelVerbose, target); - } - s->IndentLess(); + collection::const_iterator pos, end = m_symbol_contexts.end(); + for (pos = m_symbol_contexts.begin(); pos != end; ++pos) { + // pos->Dump(s, target); + pos->GetDescription(s, eDescriptionLevelVerbose, target); + } + s->IndentLess(); } -bool -SymbolContextList::GetContextAtIndex(size_t idx, SymbolContext& sc) const -{ - if (idx < m_symbol_contexts.size()) - { - sc = m_symbol_contexts[idx]; - return true; - } - return false; +bool SymbolContextList::GetContextAtIndex(size_t idx, SymbolContext &sc) const { + if (idx < m_symbol_contexts.size()) { + sc = m_symbol_contexts[idx]; + return true; + } + return false; } -bool -SymbolContextList::GetLastContext(SymbolContext& sc) const -{ - if (!m_symbol_contexts.empty()) - { - sc = m_symbol_contexts.back(); - return true; - } - return false; +bool SymbolContextList::GetLastContext(SymbolContext &sc) const { + if (!m_symbol_contexts.empty()) { + sc = m_symbol_contexts.back(); + return true; + } + return false; } -bool -SymbolContextList::RemoveContextAtIndex (size_t idx) -{ - if (idx < m_symbol_contexts.size()) - { - m_symbol_contexts.erase(m_symbol_contexts.begin() + idx); - return true; - } - return false; +bool SymbolContextList::RemoveContextAtIndex(size_t idx) { + if (idx < m_symbol_contexts.size()) { + m_symbol_contexts.erase(m_symbol_contexts.begin() + idx); + return true; + } + return false; } -uint32_t -SymbolContextList::GetSize() const -{ - return m_symbol_contexts.size(); -} +uint32_t SymbolContextList::GetSize() const { return m_symbol_contexts.size(); } -uint32_t -SymbolContextList::NumLineEntriesWithLine (uint32_t line) const -{ - uint32_t match_count = 0; - const size_t size = m_symbol_contexts.size(); - for (size_t idx = 0; idx<size; ++idx) - { - if (m_symbol_contexts[idx].line_entry.line == line) - ++match_count; - } - return match_count; +uint32_t SymbolContextList::NumLineEntriesWithLine(uint32_t line) const { + uint32_t match_count = 0; + const size_t size = m_symbol_contexts.size(); + for (size_t idx = 0; idx < size; ++idx) { + if (m_symbol_contexts[idx].line_entry.line == line) + ++match_count; + } + return match_count; } -void -SymbolContextList::GetDescription(Stream *s, - lldb::DescriptionLevel level, - Target *target) const -{ - const size_t size = m_symbol_contexts.size(); - for (size_t idx = 0; idx<size; ++idx) - m_symbol_contexts[idx].GetDescription (s, level, target); +void SymbolContextList::GetDescription(Stream *s, lldb::DescriptionLevel level, + Target *target) const { + const size_t size = m_symbol_contexts.size(); + for (size_t idx = 0; idx < size; ++idx) + m_symbol_contexts[idx].GetDescription(s, level, target); } -bool -lldb_private::operator== (const SymbolContextList& lhs, const SymbolContextList& rhs) -{ - const uint32_t size = lhs.GetSize(); - if (size != rhs.GetSize()) - return false; - - SymbolContext lhs_sc; - SymbolContext rhs_sc; - for (uint32_t i=0; i<size; ++i) - { - lhs.GetContextAtIndex(i, lhs_sc); - rhs.GetContextAtIndex(i, rhs_sc); - if (lhs_sc != rhs_sc) - return false; - } - return true; -} +bool lldb_private::operator==(const SymbolContextList &lhs, + const SymbolContextList &rhs) { + const uint32_t size = lhs.GetSize(); + if (size != rhs.GetSize()) + return false; -bool -lldb_private::operator!= (const SymbolContextList& lhs, const SymbolContextList& rhs) -{ - return !(lhs == rhs); + SymbolContext lhs_sc; + SymbolContext rhs_sc; + for (uint32_t i = 0; i < size; ++i) { + lhs.GetContextAtIndex(i, lhs_sc); + rhs.GetContextAtIndex(i, rhs_sc); + if (lhs_sc != rhs_sc) + return false; + } + return true; } +bool lldb_private::operator!=(const SymbolContextList &lhs, + const SymbolContextList &rhs) { + return !(lhs == rhs); +} diff --git a/lldb/source/Symbol/SymbolFile.cpp b/lldb/source/Symbol/SymbolFile.cpp index 808dfd3d06d..8d8b606b572 100644 --- a/lldb/source/Symbol/SymbolFile.cpp +++ b/lldb/source/Symbol/SymbolFile.cpp @@ -9,7 +9,6 @@ #include "lldb/Symbol/SymbolFile.h" -#include "lldb/lldb-private.h" #include "lldb/Core/Log.h" #include "lldb/Core/Module.h" #include "lldb/Core/PluginManager.h" @@ -18,141 +17,136 @@ #include "lldb/Symbol/TypeMap.h" #include "lldb/Symbol/TypeSystem.h" #include "lldb/Symbol/VariableList.h" +#include "lldb/lldb-private.h" using namespace lldb_private; -SymbolFile* -SymbolFile::FindPlugin (ObjectFile* obj_file) -{ - std::unique_ptr<SymbolFile> best_symfile_ap; - if (obj_file != nullptr) - { - - // We need to test the abilities of this section list. So create what it would - // be with this new obj_file. - lldb::ModuleSP module_sp(obj_file->GetModule()); - if (module_sp) - { - // Default to the main module section list. - ObjectFile *module_obj_file = module_sp->GetObjectFile(); - if (module_obj_file != obj_file) - { - // Make sure the main object file's sections are created - module_obj_file->GetSectionList(); - obj_file->CreateSections (*module_sp->GetUnifiedSectionList()); - } - } +SymbolFile *SymbolFile::FindPlugin(ObjectFile *obj_file) { + std::unique_ptr<SymbolFile> best_symfile_ap; + if (obj_file != nullptr) { + + // We need to test the abilities of this section list. So create what it + // would + // be with this new obj_file. + lldb::ModuleSP module_sp(obj_file->GetModule()); + if (module_sp) { + // Default to the main module section list. + ObjectFile *module_obj_file = module_sp->GetObjectFile(); + if (module_obj_file != obj_file) { + // Make sure the main object file's sections are created + module_obj_file->GetSectionList(); + obj_file->CreateSections(*module_sp->GetUnifiedSectionList()); + } + } - // TODO: Load any plug-ins in the appropriate plug-in search paths and - // iterate over all of them to find the best one for the job. - - uint32_t best_symfile_abilities = 0; - - SymbolFileCreateInstance create_callback; - for (uint32_t idx = 0; (create_callback = PluginManager::GetSymbolFileCreateCallbackAtIndex(idx)) != nullptr; ++idx) - { - std::unique_ptr<SymbolFile> curr_symfile_ap(create_callback(obj_file)); - - if (curr_symfile_ap.get()) - { - const uint32_t sym_file_abilities = curr_symfile_ap->GetAbilities(); - if (sym_file_abilities > best_symfile_abilities) - { - best_symfile_abilities = sym_file_abilities; - best_symfile_ap.reset (curr_symfile_ap.release()); - // If any symbol file parser has all of the abilities, then - // we should just stop looking. - if ((kAllAbilities & sym_file_abilities) == kAllAbilities) - break; - } - } - } - if (best_symfile_ap.get()) - { - // Let the winning symbol file parser initialize itself more - // completely now that it has been chosen - best_symfile_ap->InitializeObject(); + // TODO: Load any plug-ins in the appropriate plug-in search paths and + // iterate over all of them to find the best one for the job. + + uint32_t best_symfile_abilities = 0; + + SymbolFileCreateInstance create_callback; + for (uint32_t idx = 0; + (create_callback = PluginManager::GetSymbolFileCreateCallbackAtIndex( + idx)) != nullptr; + ++idx) { + std::unique_ptr<SymbolFile> curr_symfile_ap(create_callback(obj_file)); + + if (curr_symfile_ap.get()) { + const uint32_t sym_file_abilities = curr_symfile_ap->GetAbilities(); + if (sym_file_abilities > best_symfile_abilities) { + best_symfile_abilities = sym_file_abilities; + best_symfile_ap.reset(curr_symfile_ap.release()); + // If any symbol file parser has all of the abilities, then + // we should just stop looking. + if ((kAllAbilities & sym_file_abilities) == kAllAbilities) + break; } + } } - return best_symfile_ap.release(); + if (best_symfile_ap.get()) { + // Let the winning symbol file parser initialize itself more + // completely now that it has been chosen + best_symfile_ap->InitializeObject(); + } + } + return best_symfile_ap.release(); } -TypeList * -SymbolFile::GetTypeList () -{ - if (m_obj_file) - return m_obj_file->GetModule()->GetTypeList(); - return nullptr; +TypeList *SymbolFile::GetTypeList() { + if (m_obj_file) + return m_obj_file->GetModule()->GetTypeList(); + return nullptr; } -TypeSystem * -SymbolFile::GetTypeSystemForLanguage (lldb::LanguageType language) -{ - TypeSystem *type_system = m_obj_file->GetModule()->GetTypeSystemForLanguage(language); - if (type_system) - type_system->SetSymbolFile(this); - return type_system; +TypeSystem *SymbolFile::GetTypeSystemForLanguage(lldb::LanguageType language) { + TypeSystem *type_system = + m_obj_file->GetModule()->GetTypeSystemForLanguage(language); + if (type_system) + type_system->SetSymbolFile(this); + return type_system; } -uint32_t -SymbolFile::ResolveSymbolContext (const FileSpec& file_spec, uint32_t line, bool check_inlines, uint32_t resolve_scope, SymbolContextList& sc_list) -{ - return 0; +uint32_t SymbolFile::ResolveSymbolContext(const FileSpec &file_spec, + uint32_t line, bool check_inlines, + uint32_t resolve_scope, + SymbolContextList &sc_list) { + return 0; } - -uint32_t -SymbolFile::FindGlobalVariables (const ConstString &name, const CompilerDeclContext *parent_decl_ctx, bool append, uint32_t max_matches, VariableList& variables) -{ - if (!append) - variables.Clear(); - return 0; +uint32_t SymbolFile::FindGlobalVariables( + const ConstString &name, const CompilerDeclContext *parent_decl_ctx, + bool append, uint32_t max_matches, VariableList &variables) { + if (!append) + variables.Clear(); + return 0; } - -uint32_t -SymbolFile::FindGlobalVariables (const RegularExpression& regex, bool append, uint32_t max_matches, VariableList& variables) -{ - if (!append) - variables.Clear(); - return 0; +uint32_t SymbolFile::FindGlobalVariables(const RegularExpression ®ex, + bool append, uint32_t max_matches, + VariableList &variables) { + if (!append) + variables.Clear(); + return 0; } -uint32_t -SymbolFile::FindFunctions (const ConstString &name, const CompilerDeclContext *parent_decl_ctx, uint32_t name_type_mask, bool include_inlines, bool append, SymbolContextList& sc_list) -{ - if (!append) - sc_list.Clear(); - return 0; +uint32_t SymbolFile::FindFunctions(const ConstString &name, + const CompilerDeclContext *parent_decl_ctx, + uint32_t name_type_mask, + bool include_inlines, bool append, + SymbolContextList &sc_list) { + if (!append) + sc_list.Clear(); + return 0; } -uint32_t -SymbolFile::FindFunctions (const RegularExpression& regex, bool include_inlines, bool append, SymbolContextList& sc_list) -{ - if (!append) - sc_list.Clear(); - return 0; +uint32_t SymbolFile::FindFunctions(const RegularExpression ®ex, + bool include_inlines, bool append, + SymbolContextList &sc_list) { + if (!append) + sc_list.Clear(); + return 0; } -void -SymbolFile::GetMangledNamesForFunction(const std::string &scope_qualified_name, std::vector<ConstString> &mangled_names) -{ - return; +void SymbolFile::GetMangledNamesForFunction( + const std::string &scope_qualified_name, + std::vector<ConstString> &mangled_names) { + return; } -uint32_t -SymbolFile::FindTypes (const SymbolContext& sc, const ConstString &name, const CompilerDeclContext *parent_decl_ctx, bool append, uint32_t max_matches, llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files, TypeMap& types) -{ - if (!append) - types.Clear(); - return 0; +uint32_t SymbolFile::FindTypes( + const SymbolContext &sc, const ConstString &name, + const CompilerDeclContext *parent_decl_ctx, bool append, + uint32_t max_matches, + llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files, + TypeMap &types) { + if (!append) + types.Clear(); + return 0; } - -size_t -SymbolFile::FindTypes (const std::vector<CompilerContext> &context, bool append, TypeMap& types) -{ - if (!append) - types.Clear(); - return 0; +size_t SymbolFile::FindTypes(const std::vector<CompilerContext> &context, + bool append, TypeMap &types) { + if (!append) + types.Clear(); + return 0; } diff --git a/lldb/source/Symbol/SymbolVendor.cpp b/lldb/source/Symbol/SymbolVendor.cpp index c569943b346..f47bfd0e837 100644 --- a/lldb/source/Symbol/SymbolVendor.cpp +++ b/lldb/source/Symbol/SymbolVendor.cpp @@ -23,7 +23,6 @@ using namespace lldb; using namespace lldb_private; - //---------------------------------------------------------------------- // FindPlugin // @@ -31,547 +30,455 @@ using namespace lldb_private; // vendors to allow for complex debug information file setups, and to // also allow for finding separate debug information files. //---------------------------------------------------------------------- -SymbolVendor* -SymbolVendor::FindPlugin (const lldb::ModuleSP &module_sp, lldb_private::Stream *feedback_strm) -{ - std::unique_ptr<SymbolVendor> instance_ap; - SymbolVendorCreateInstance create_callback; - - for (size_t idx = 0; (create_callback = PluginManager::GetSymbolVendorCreateCallbackAtIndex(idx)) != nullptr; ++idx) - { - instance_ap.reset(create_callback(module_sp, feedback_strm)); - - if (instance_ap.get()) - { - return instance_ap.release(); - } - } - // The default implementation just tries to create debug information using the - // file representation for the module. - instance_ap.reset(new SymbolVendor(module_sp)); - if (instance_ap.get()) - { - ObjectFile *objfile = module_sp->GetObjectFile(); - if (objfile) - instance_ap->AddSymbolFileRepresentation(objfile->shared_from_this()); - } - return instance_ap.release(); +SymbolVendor *SymbolVendor::FindPlugin(const lldb::ModuleSP &module_sp, + lldb_private::Stream *feedback_strm) { + std::unique_ptr<SymbolVendor> instance_ap; + SymbolVendorCreateInstance create_callback; + + for (size_t idx = 0; + (create_callback = PluginManager::GetSymbolVendorCreateCallbackAtIndex( + idx)) != nullptr; + ++idx) { + instance_ap.reset(create_callback(module_sp, feedback_strm)); + + if (instance_ap.get()) { + return instance_ap.release(); + } + } + // The default implementation just tries to create debug information using the + // file representation for the module. + instance_ap.reset(new SymbolVendor(module_sp)); + if (instance_ap.get()) { + ObjectFile *objfile = module_sp->GetObjectFile(); + if (objfile) + instance_ap->AddSymbolFileRepresentation(objfile->shared_from_this()); + } + return instance_ap.release(); } //---------------------------------------------------------------------- // SymbolVendor constructor //---------------------------------------------------------------------- -SymbolVendor::SymbolVendor(const lldb::ModuleSP &module_sp) : - ModuleChild (module_sp), - m_type_list(), - m_compile_units(), - m_sym_file_ap() -{ -} +SymbolVendor::SymbolVendor(const lldb::ModuleSP &module_sp) + : ModuleChild(module_sp), m_type_list(), m_compile_units(), + m_sym_file_ap() {} //---------------------------------------------------------------------- // Destructor //---------------------------------------------------------------------- -SymbolVendor::~SymbolVendor() -{ -} +SymbolVendor::~SymbolVendor() {} //---------------------------------------------------------------------- // Add a representation given an object file. //---------------------------------------------------------------------- -void -SymbolVendor::AddSymbolFileRepresentation(const ObjectFileSP &objfile_sp) -{ - ModuleSP module_sp(GetModule()); - if (module_sp) - { - std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex()); - if (objfile_sp) - { - m_objfile_sp = objfile_sp; - m_sym_file_ap.reset(SymbolFile::FindPlugin(objfile_sp.get())); - } - } +void SymbolVendor::AddSymbolFileRepresentation(const ObjectFileSP &objfile_sp) { + ModuleSP module_sp(GetModule()); + if (module_sp) { + std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex()); + if (objfile_sp) { + m_objfile_sp = objfile_sp; + m_sym_file_ap.reset(SymbolFile::FindPlugin(objfile_sp.get())); + } + } +} + +bool SymbolVendor::SetCompileUnitAtIndex(size_t idx, const CompUnitSP &cu_sp) { + ModuleSP module_sp(GetModule()); + if (module_sp) { + std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex()); + const size_t num_compile_units = GetNumCompileUnits(); + if (idx < num_compile_units) { + // Fire off an assertion if this compile unit already exists for now. + // The partial parsing should take care of only setting the compile + // unit once, so if this assertion fails, we need to make sure that + // we don't have a race condition, or have a second parse of the same + // compile unit. + assert(m_compile_units[idx].get() == nullptr); + m_compile_units[idx] = cu_sp; + return true; + } else { + // This should NOT happen, and if it does, we want to crash and know + // about it + assert(idx < num_compile_units); + } + } + return false; +} + +size_t SymbolVendor::GetNumCompileUnits() { + ModuleSP module_sp(GetModule()); + if (module_sp) { + std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex()); + if (m_compile_units.empty()) { + if (m_sym_file_ap.get()) { + // Resize our array of compile unit shared pointers -- which will + // each remain NULL until someone asks for the actual compile unit + // information. When this happens, the symbol file will be asked + // to parse this compile unit information. + m_compile_units.resize(m_sym_file_ap->GetNumCompileUnits()); + } + } + } + return m_compile_units.size(); } -bool -SymbolVendor::SetCompileUnitAtIndex (size_t idx, const CompUnitSP &cu_sp) -{ - ModuleSP module_sp(GetModule()); - if (module_sp) - { - std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex()); - const size_t num_compile_units = GetNumCompileUnits(); - if (idx < num_compile_units) - { - // Fire off an assertion if this compile unit already exists for now. - // The partial parsing should take care of only setting the compile - // unit once, so if this assertion fails, we need to make sure that - // we don't have a race condition, or have a second parse of the same - // compile unit. - assert(m_compile_units[idx].get() == nullptr); - m_compile_units[idx] = cu_sp; - return true; - } - else - { - // This should NOT happen, and if it does, we want to crash and know - // about it - assert (idx < num_compile_units); - } - } - return false; -} - -size_t -SymbolVendor::GetNumCompileUnits() -{ - ModuleSP module_sp(GetModule()); - if (module_sp) - { - std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex()); - if (m_compile_units.empty()) - { - if (m_sym_file_ap.get()) - { - // Resize our array of compile unit shared pointers -- which will - // each remain NULL until someone asks for the actual compile unit - // information. When this happens, the symbol file will be asked - // to parse this compile unit information. - m_compile_units.resize(m_sym_file_ap->GetNumCompileUnits()); - } - } - } - return m_compile_units.size(); +lldb::LanguageType +SymbolVendor::ParseCompileUnitLanguage(const SymbolContext &sc) { + ModuleSP module_sp(GetModule()); + if (module_sp) { + std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex()); + if (m_sym_file_ap.get()) + return m_sym_file_ap->ParseCompileUnitLanguage(sc); + } + return eLanguageTypeUnknown; } -lldb::LanguageType -SymbolVendor::ParseCompileUnitLanguage (const SymbolContext& sc) -{ - ModuleSP module_sp(GetModule()); - if (module_sp) - { - std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex()); - if (m_sym_file_ap.get()) - return m_sym_file_ap->ParseCompileUnitLanguage(sc); - } - return eLanguageTypeUnknown; +size_t SymbolVendor::ParseCompileUnitFunctions(const SymbolContext &sc) { + ModuleSP module_sp(GetModule()); + if (module_sp) { + std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex()); + if (m_sym_file_ap.get()) + return m_sym_file_ap->ParseCompileUnitFunctions(sc); + } + return 0; } +bool SymbolVendor::ParseCompileUnitLineTable(const SymbolContext &sc) { + ModuleSP module_sp(GetModule()); + if (module_sp) { + std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex()); + if (m_sym_file_ap.get()) + return m_sym_file_ap->ParseCompileUnitLineTable(sc); + } + return false; +} -size_t -SymbolVendor::ParseCompileUnitFunctions (const SymbolContext &sc) -{ - ModuleSP module_sp(GetModule()); - if (module_sp) - { - std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex()); - if (m_sym_file_ap.get()) - return m_sym_file_ap->ParseCompileUnitFunctions(sc); - } - return 0; -} - -bool -SymbolVendor::ParseCompileUnitLineTable (const SymbolContext &sc) -{ - ModuleSP module_sp(GetModule()); - if (module_sp) - { - std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex()); - if (m_sym_file_ap.get()) - return m_sym_file_ap->ParseCompileUnitLineTable(sc); - } - return false; -} - -bool -SymbolVendor::ParseCompileUnitDebugMacros (const SymbolContext &sc) -{ - ModuleSP module_sp(GetModule()); - if (module_sp) - { - std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex()); - if (m_sym_file_ap.get()) - return m_sym_file_ap->ParseCompileUnitDebugMacros(sc); - } - return false; -} -bool -SymbolVendor::ParseCompileUnitSupportFiles (const SymbolContext& sc, FileSpecList& support_files) -{ - ModuleSP module_sp(GetModule()); - if (module_sp) - { - std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex()); - if (m_sym_file_ap.get()) - return m_sym_file_ap->ParseCompileUnitSupportFiles(sc, support_files); - } - return false; -} - -bool -SymbolVendor::ParseCompileUnitIsOptimized(const SymbolContext &sc) -{ - ModuleSP module_sp(GetModule()); - if (module_sp) - { - std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex()); - if (m_sym_file_ap.get()) - return m_sym_file_ap->ParseCompileUnitIsOptimized(sc); - } - return false; -} - -bool -SymbolVendor::ParseImportedModules(const SymbolContext &sc, std::vector<ConstString> &imported_modules) -{ - ModuleSP module_sp(GetModule()); - if (module_sp) - { - std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex()); - if (m_sym_file_ap.get()) - return m_sym_file_ap->ParseImportedModules(sc, imported_modules); - } - return false; - -} - -size_t -SymbolVendor::ParseFunctionBlocks (const SymbolContext &sc) -{ - ModuleSP module_sp(GetModule()); - if (module_sp) - { - std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex()); - if (m_sym_file_ap.get()) - return m_sym_file_ap->ParseFunctionBlocks(sc); - } - return 0; -} - -size_t -SymbolVendor::ParseTypes (const SymbolContext &sc) -{ - ModuleSP module_sp(GetModule()); - if (module_sp) - { - std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex()); - if (m_sym_file_ap.get()) - return m_sym_file_ap->ParseTypes(sc); - } - return 0; -} - -size_t -SymbolVendor::ParseVariablesForContext (const SymbolContext& sc) -{ - ModuleSP module_sp(GetModule()); - if (module_sp) - { - std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex()); - if (m_sym_file_ap.get()) - return m_sym_file_ap->ParseVariablesForContext(sc); - } - return 0; -} - -Type* -SymbolVendor::ResolveTypeUID(lldb::user_id_t type_uid) -{ - ModuleSP module_sp(GetModule()); - if (module_sp) - { - std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex()); - if (m_sym_file_ap.get()) - return m_sym_file_ap->ResolveTypeUID(type_uid); - } - return nullptr; +bool SymbolVendor::ParseCompileUnitDebugMacros(const SymbolContext &sc) { + ModuleSP module_sp(GetModule()); + if (module_sp) { + std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex()); + if (m_sym_file_ap.get()) + return m_sym_file_ap->ParseCompileUnitDebugMacros(sc); + } + return false; +} +bool SymbolVendor::ParseCompileUnitSupportFiles(const SymbolContext &sc, + FileSpecList &support_files) { + ModuleSP module_sp(GetModule()); + if (module_sp) { + std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex()); + if (m_sym_file_ap.get()) + return m_sym_file_ap->ParseCompileUnitSupportFiles(sc, support_files); + } + return false; } +bool SymbolVendor::ParseCompileUnitIsOptimized(const SymbolContext &sc) { + ModuleSP module_sp(GetModule()); + if (module_sp) { + std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex()); + if (m_sym_file_ap.get()) + return m_sym_file_ap->ParseCompileUnitIsOptimized(sc); + } + return false; +} -uint32_t -SymbolVendor::ResolveSymbolContext (const Address& so_addr, uint32_t resolve_scope, SymbolContext& sc) -{ - ModuleSP module_sp(GetModule()); - if (module_sp) - { - std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex()); - if (m_sym_file_ap.get()) - return m_sym_file_ap->ResolveSymbolContext(so_addr, resolve_scope, sc); - } - return 0; -} - -uint32_t -SymbolVendor::ResolveSymbolContext (const FileSpec& file_spec, uint32_t line, bool check_inlines, uint32_t resolve_scope, SymbolContextList& sc_list) -{ - ModuleSP module_sp(GetModule()); - if (module_sp) - { - std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex()); - if (m_sym_file_ap.get()) - return m_sym_file_ap->ResolveSymbolContext(file_spec, line, check_inlines, resolve_scope, sc_list); - } - return 0; -} - -size_t -SymbolVendor::FindGlobalVariables (const ConstString &name, const CompilerDeclContext *parent_decl_ctx, bool append, size_t max_matches, VariableList& variables) -{ - ModuleSP module_sp(GetModule()); - if (module_sp) - { - std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex()); - if (m_sym_file_ap.get()) - return m_sym_file_ap->FindGlobalVariables(name, parent_decl_ctx, append, max_matches, variables); - } - return 0; -} - -size_t -SymbolVendor::FindGlobalVariables (const RegularExpression& regex, bool append, size_t max_matches, VariableList& variables) -{ - ModuleSP module_sp(GetModule()); - if (module_sp) - { - std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex()); - if (m_sym_file_ap.get()) - return m_sym_file_ap->FindGlobalVariables(regex, append, max_matches, variables); - } - return 0; -} - -size_t -SymbolVendor::FindFunctions(const ConstString &name, const CompilerDeclContext *parent_decl_ctx, uint32_t name_type_mask, bool include_inlines, bool append, SymbolContextList& sc_list) -{ - ModuleSP module_sp(GetModule()); - if (module_sp) - { - std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex()); - if (m_sym_file_ap.get()) - return m_sym_file_ap->FindFunctions(name, parent_decl_ctx, name_type_mask, include_inlines, append, sc_list); - } - return 0; -} - -size_t -SymbolVendor::FindFunctions(const RegularExpression& regex, bool include_inlines, bool append, SymbolContextList& sc_list) -{ - ModuleSP module_sp(GetModule()); - if (module_sp) - { - std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex()); - if (m_sym_file_ap.get()) - return m_sym_file_ap->FindFunctions(regex, include_inlines, append, sc_list); - } - return 0; +bool SymbolVendor::ParseImportedModules( + const SymbolContext &sc, std::vector<ConstString> &imported_modules) { + ModuleSP module_sp(GetModule()); + if (module_sp) { + std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex()); + if (m_sym_file_ap.get()) + return m_sym_file_ap->ParseImportedModules(sc, imported_modules); + } + return false; } +size_t SymbolVendor::ParseFunctionBlocks(const SymbolContext &sc) { + ModuleSP module_sp(GetModule()); + if (module_sp) { + std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex()); + if (m_sym_file_ap.get()) + return m_sym_file_ap->ParseFunctionBlocks(sc); + } + return 0; +} -size_t -SymbolVendor::FindTypes (const SymbolContext& sc, const ConstString &name, const CompilerDeclContext *parent_decl_ctx, bool append, size_t max_matches, llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files, TypeMap& types) -{ - ModuleSP module_sp(GetModule()); - if (module_sp) - { - std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex()); - if (m_sym_file_ap.get()) - return m_sym_file_ap->FindTypes(sc, name, parent_decl_ctx, append, max_matches, searched_symbol_files, types); - } - if (!append) - types.Clear(); - return 0; -} - -size_t -SymbolVendor::FindTypes (const std::vector<CompilerContext> &context, bool append, TypeMap& types) -{ - ModuleSP module_sp(GetModule()); - if (module_sp) - { - std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex()); - if (m_sym_file_ap.get()) - return m_sym_file_ap->FindTypes(context, append, types); - } - if (!append) - types.Clear(); - return 0; -} - -size_t -SymbolVendor::GetTypes (SymbolContextScope *sc_scope, - uint32_t type_mask, - lldb_private::TypeList &type_list) -{ - ModuleSP module_sp(GetModule()); - if (module_sp) - { - std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex()); - if (m_sym_file_ap.get()) - return m_sym_file_ap->GetTypes (sc_scope, type_mask, type_list); - } - return 0; +size_t SymbolVendor::ParseTypes(const SymbolContext &sc) { + ModuleSP module_sp(GetModule()); + if (module_sp) { + std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex()); + if (m_sym_file_ap.get()) + return m_sym_file_ap->ParseTypes(sc); + } + return 0; +} + +size_t SymbolVendor::ParseVariablesForContext(const SymbolContext &sc) { + ModuleSP module_sp(GetModule()); + if (module_sp) { + std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex()); + if (m_sym_file_ap.get()) + return m_sym_file_ap->ParseVariablesForContext(sc); + } + return 0; +} + +Type *SymbolVendor::ResolveTypeUID(lldb::user_id_t type_uid) { + ModuleSP module_sp(GetModule()); + if (module_sp) { + std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex()); + if (m_sym_file_ap.get()) + return m_sym_file_ap->ResolveTypeUID(type_uid); + } + return nullptr; +} + +uint32_t SymbolVendor::ResolveSymbolContext(const Address &so_addr, + uint32_t resolve_scope, + SymbolContext &sc) { + ModuleSP module_sp(GetModule()); + if (module_sp) { + std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex()); + if (m_sym_file_ap.get()) + return m_sym_file_ap->ResolveSymbolContext(so_addr, resolve_scope, sc); + } + return 0; +} + +uint32_t SymbolVendor::ResolveSymbolContext(const FileSpec &file_spec, + uint32_t line, bool check_inlines, + uint32_t resolve_scope, + SymbolContextList &sc_list) { + ModuleSP module_sp(GetModule()); + if (module_sp) { + std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex()); + if (m_sym_file_ap.get()) + return m_sym_file_ap->ResolveSymbolContext(file_spec, line, check_inlines, + resolve_scope, sc_list); + } + return 0; +} + +size_t SymbolVendor::FindGlobalVariables( + const ConstString &name, const CompilerDeclContext *parent_decl_ctx, + bool append, size_t max_matches, VariableList &variables) { + ModuleSP module_sp(GetModule()); + if (module_sp) { + std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex()); + if (m_sym_file_ap.get()) + return m_sym_file_ap->FindGlobalVariables(name, parent_decl_ctx, append, + max_matches, variables); + } + return 0; +} + +size_t SymbolVendor::FindGlobalVariables(const RegularExpression ®ex, + bool append, size_t max_matches, + VariableList &variables) { + ModuleSP module_sp(GetModule()); + if (module_sp) { + std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex()); + if (m_sym_file_ap.get()) + return m_sym_file_ap->FindGlobalVariables(regex, append, max_matches, + variables); + } + return 0; +} + +size_t SymbolVendor::FindFunctions(const ConstString &name, + const CompilerDeclContext *parent_decl_ctx, + uint32_t name_type_mask, + bool include_inlines, bool append, + SymbolContextList &sc_list) { + ModuleSP module_sp(GetModule()); + if (module_sp) { + std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex()); + if (m_sym_file_ap.get()) + return m_sym_file_ap->FindFunctions(name, parent_decl_ctx, name_type_mask, + include_inlines, append, sc_list); + } + return 0; +} + +size_t SymbolVendor::FindFunctions(const RegularExpression ®ex, + bool include_inlines, bool append, + SymbolContextList &sc_list) { + ModuleSP module_sp(GetModule()); + if (module_sp) { + std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex()); + if (m_sym_file_ap.get()) + return m_sym_file_ap->FindFunctions(regex, include_inlines, append, + sc_list); + } + return 0; +} + +size_t SymbolVendor::FindTypes( + const SymbolContext &sc, const ConstString &name, + const CompilerDeclContext *parent_decl_ctx, bool append, size_t max_matches, + llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files, + TypeMap &types) { + ModuleSP module_sp(GetModule()); + if (module_sp) { + std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex()); + if (m_sym_file_ap.get()) + return m_sym_file_ap->FindTypes(sc, name, parent_decl_ctx, append, + max_matches, searched_symbol_files, + types); + } + if (!append) + types.Clear(); + return 0; +} + +size_t SymbolVendor::FindTypes(const std::vector<CompilerContext> &context, + bool append, TypeMap &types) { + ModuleSP module_sp(GetModule()); + if (module_sp) { + std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex()); + if (m_sym_file_ap.get()) + return m_sym_file_ap->FindTypes(context, append, types); + } + if (!append) + types.Clear(); + return 0; +} + +size_t SymbolVendor::GetTypes(SymbolContextScope *sc_scope, uint32_t type_mask, + lldb_private::TypeList &type_list) { + ModuleSP module_sp(GetModule()); + if (module_sp) { + std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex()); + if (m_sym_file_ap.get()) + return m_sym_file_ap->GetTypes(sc_scope, type_mask, type_list); + } + return 0; } CompilerDeclContext -SymbolVendor::FindNamespace(const SymbolContext& sc, const ConstString &name, const CompilerDeclContext *parent_decl_ctx) -{ - CompilerDeclContext namespace_decl_ctx; - ModuleSP module_sp(GetModule()); - if (module_sp) - { - std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex()); - if (m_sym_file_ap.get()) - namespace_decl_ctx = m_sym_file_ap->FindNamespace (sc, name, parent_decl_ctx); - } - return namespace_decl_ctx; -} - -void -SymbolVendor::Dump(Stream *s) -{ - ModuleSP module_sp(GetModule()); - if (module_sp) - { - std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex()); - - bool show_context = false; - - s->Printf("%p: ", static_cast<void*>(this)); - s->Indent(); - s->PutCString("SymbolVendor"); - if (m_sym_file_ap.get()) - { - ObjectFile *objfile = m_sym_file_ap->GetObjectFile(); - if (objfile) - { - const FileSpec &objfile_file_spec = objfile->GetFileSpec(); - if (objfile_file_spec) - { - s->PutCString(" ("); - objfile_file_spec.Dump(s); - s->PutChar(')'); - } - } - } - s->EOL(); - s->IndentMore(); - m_type_list.Dump(s, show_context); - - CompileUnitConstIter cu_pos, cu_end; - cu_end = m_compile_units.end(); - for (cu_pos = m_compile_units.begin(); cu_pos != cu_end; ++cu_pos) - { - // We currently only dump the compile units that have been parsed - if (cu_pos->get()) - (*cu_pos)->Dump(s, show_context); +SymbolVendor::FindNamespace(const SymbolContext &sc, const ConstString &name, + const CompilerDeclContext *parent_decl_ctx) { + CompilerDeclContext namespace_decl_ctx; + ModuleSP module_sp(GetModule()); + if (module_sp) { + std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex()); + if (m_sym_file_ap.get()) + namespace_decl_ctx = + m_sym_file_ap->FindNamespace(sc, name, parent_decl_ctx); + } + return namespace_decl_ctx; +} + +void SymbolVendor::Dump(Stream *s) { + ModuleSP module_sp(GetModule()); + if (module_sp) { + std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex()); + + bool show_context = false; + + s->Printf("%p: ", static_cast<void *>(this)); + s->Indent(); + s->PutCString("SymbolVendor"); + if (m_sym_file_ap.get()) { + ObjectFile *objfile = m_sym_file_ap->GetObjectFile(); + if (objfile) { + const FileSpec &objfile_file_spec = objfile->GetFileSpec(); + if (objfile_file_spec) { + s->PutCString(" ("); + objfile_file_spec.Dump(s); + s->PutChar(')'); } + } + } + s->EOL(); + s->IndentMore(); + m_type_list.Dump(s, show_context); - s->IndentLess(); + CompileUnitConstIter cu_pos, cu_end; + cu_end = m_compile_units.end(); + for (cu_pos = m_compile_units.begin(); cu_pos != cu_end; ++cu_pos) { + // We currently only dump the compile units that have been parsed + if (cu_pos->get()) + (*cu_pos)->Dump(s, show_context); } + + s->IndentLess(); + } } -CompUnitSP -SymbolVendor::GetCompileUnitAtIndex(size_t idx) -{ - CompUnitSP cu_sp; - ModuleSP module_sp(GetModule()); - if (module_sp) - { - std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex()); - const size_t num_compile_units = GetNumCompileUnits(); - if (idx < num_compile_units) - { - cu_sp = m_compile_units[idx]; - if (cu_sp.get() == nullptr) - { - m_compile_units[idx] = m_sym_file_ap->ParseCompileUnitAtIndex(idx); - cu_sp = m_compile_units[idx]; - } - } +CompUnitSP SymbolVendor::GetCompileUnitAtIndex(size_t idx) { + CompUnitSP cu_sp; + ModuleSP module_sp(GetModule()); + if (module_sp) { + std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex()); + const size_t num_compile_units = GetNumCompileUnits(); + if (idx < num_compile_units) { + cu_sp = m_compile_units[idx]; + if (cu_sp.get() == nullptr) { + m_compile_units[idx] = m_sym_file_ap->ParseCompileUnitAtIndex(idx); + cu_sp = m_compile_units[idx]; + } } - return cu_sp; + } + return cu_sp; } -FileSpec -SymbolVendor::GetMainFileSpec() const -{ - if (m_sym_file_ap.get()) - { - const ObjectFile *symfile_objfile = m_sym_file_ap->GetObjectFile(); - if (symfile_objfile) - return symfile_objfile->GetFileSpec(); - } +FileSpec SymbolVendor::GetMainFileSpec() const { + if (m_sym_file_ap.get()) { + const ObjectFile *symfile_objfile = m_sym_file_ap->GetObjectFile(); + if (symfile_objfile) + return symfile_objfile->GetFileSpec(); + } - return FileSpec(); + return FileSpec(); } -Symtab * -SymbolVendor::GetSymtab () -{ - ModuleSP module_sp(GetModule()); - if (module_sp) - { - ObjectFile *objfile = module_sp->GetObjectFile(); - if (objfile) - { - // Get symbol table from unified section list. - return objfile->GetSymtab (); - } +Symtab *SymbolVendor::GetSymtab() { + ModuleSP module_sp(GetModule()); + if (module_sp) { + ObjectFile *objfile = module_sp->GetObjectFile(); + if (objfile) { + // Get symbol table from unified section list. + return objfile->GetSymtab(); } - return nullptr; -} - -void -SymbolVendor::ClearSymtab() -{ - ModuleSP module_sp(GetModule()); - if (module_sp) - { - ObjectFile *objfile = module_sp->GetObjectFile(); - if (objfile) - { - // Clear symbol table from unified section list. - objfile->ClearSymtab (); - } + } + return nullptr; +} + +void SymbolVendor::ClearSymtab() { + ModuleSP module_sp(GetModule()); + if (module_sp) { + ObjectFile *objfile = module_sp->GetObjectFile(); + if (objfile) { + // Clear symbol table from unified section list. + objfile->ClearSymtab(); } + } } -void -SymbolVendor::SectionFileAddressesChanged () -{ - ModuleSP module_sp(GetModule()); - if (module_sp) - { - ObjectFile *module_objfile = module_sp->GetObjectFile (); - if (m_sym_file_ap.get()) - { - ObjectFile *symfile_objfile = m_sym_file_ap->GetObjectFile (); - if (symfile_objfile != module_objfile) - symfile_objfile->SectionFileAddressesChanged (); - } - Symtab *symtab = GetSymtab (); - if (symtab) - { - symtab->SectionFileAddressesChanged (); - } +void SymbolVendor::SectionFileAddressesChanged() { + ModuleSP module_sp(GetModule()); + if (module_sp) { + ObjectFile *module_objfile = module_sp->GetObjectFile(); + if (m_sym_file_ap.get()) { + ObjectFile *symfile_objfile = m_sym_file_ap->GetObjectFile(); + if (symfile_objfile != module_objfile) + symfile_objfile->SectionFileAddressesChanged(); + } + Symtab *symtab = GetSymtab(); + if (symtab) { + symtab->SectionFileAddressesChanged(); } + } } //------------------------------------------------------------------ // PluginInterface protocol //------------------------------------------------------------------ -lldb_private::ConstString -SymbolVendor::GetPluginName() -{ - static ConstString g_name("vendor-default"); - return g_name; -} - -uint32_t -SymbolVendor::GetPluginVersion() -{ - return 1; +lldb_private::ConstString SymbolVendor::GetPluginName() { + static ConstString g_name("vendor-default"); + return g_name; } +uint32_t SymbolVendor::GetPluginVersion() { return 1; } diff --git a/lldb/source/Symbol/Symtab.cpp b/lldb/source/Symbol/Symtab.cpp index ca88ebe9c26..84619744f92 100644 --- a/lldb/source/Symbol/Symtab.cpp +++ b/lldb/source/Symbol/Symtab.cpp @@ -10,6 +10,8 @@ #include <map> #include <set> +#include "Plugins/Language/CPlusPlus/CPlusPlusLanguage.h" +#include "Plugins/Language/ObjC/ObjCLanguage.h" #include "lldb/Core/Module.h" #include "lldb/Core/RegularExpression.h" #include "lldb/Core/Section.h" @@ -19,1244 +21,1147 @@ #include "lldb/Symbol/Symbol.h" #include "lldb/Symbol/SymbolContext.h" #include "lldb/Symbol/Symtab.h" -#include "Plugins/Language/ObjC/ObjCLanguage.h" -#include "Plugins/Language/CPlusPlus/CPlusPlusLanguage.h" using namespace lldb; using namespace lldb_private; Symtab::Symtab(ObjectFile *objfile) - : m_objfile(objfile), - m_symbols(), - m_file_addr_to_index(), - m_name_to_index(), - m_mutex(), - m_file_addr_to_index_computed(false), - m_name_indexes_computed(false) -{ -} + : m_objfile(objfile), m_symbols(), m_file_addr_to_index(), + m_name_to_index(), m_mutex(), m_file_addr_to_index_computed(false), + m_name_indexes_computed(false) {} -Symtab::~Symtab() -{ -} +Symtab::~Symtab() {} -void -Symtab::Reserve(size_t count) -{ - // Clients should grab the mutex from this symbol table and lock it manually - // when calling this function to avoid performance issues. - m_symbols.reserve (count); +void Symtab::Reserve(size_t count) { + // Clients should grab the mutex from this symbol table and lock it manually + // when calling this function to avoid performance issues. + m_symbols.reserve(count); } -Symbol * -Symtab::Resize(size_t count) -{ - // Clients should grab the mutex from this symbol table and lock it manually - // when calling this function to avoid performance issues. - m_symbols.resize (count); - return m_symbols.empty() ? nullptr : &m_symbols[0]; +Symbol *Symtab::Resize(size_t count) { + // Clients should grab the mutex from this symbol table and lock it manually + // when calling this function to avoid performance issues. + m_symbols.resize(count); + return m_symbols.empty() ? nullptr : &m_symbols[0]; } -uint32_t -Symtab::AddSymbol(const Symbol& symbol) -{ - // Clients should grab the mutex from this symbol table and lock it manually - // when calling this function to avoid performance issues. - uint32_t symbol_idx = m_symbols.size(); - m_name_to_index.Clear(); - m_file_addr_to_index.Clear(); - m_symbols.push_back(symbol); - m_file_addr_to_index_computed = false; - m_name_indexes_computed = false; - return symbol_idx; +uint32_t Symtab::AddSymbol(const Symbol &symbol) { + // Clients should grab the mutex from this symbol table and lock it manually + // when calling this function to avoid performance issues. + uint32_t symbol_idx = m_symbols.size(); + m_name_to_index.Clear(); + m_file_addr_to_index.Clear(); + m_symbols.push_back(symbol); + m_file_addr_to_index_computed = false; + m_name_indexes_computed = false; + return symbol_idx; } -size_t -Symtab::GetNumSymbols() const -{ - std::lock_guard<std::recursive_mutex> guard(m_mutex); - return m_symbols.size(); +size_t Symtab::GetNumSymbols() const { + std::lock_guard<std::recursive_mutex> guard(m_mutex); + return m_symbols.size(); } -void -Symtab::SectionFileAddressesChanged () -{ - m_name_to_index.Clear(); - m_file_addr_to_index_computed = false; +void Symtab::SectionFileAddressesChanged() { + m_name_to_index.Clear(); + m_file_addr_to_index_computed = false; } -void -Symtab::Dump (Stream *s, Target *target, SortOrder sort_order) -{ - std::lock_guard<std::recursive_mutex> guard(m_mutex); - - // s->Printf("%.*p: ", (int)sizeof(void*) * 2, this); - s->Indent(); - const FileSpec &file_spec = m_objfile->GetFileSpec(); - const char * object_name = nullptr; - if (m_objfile->GetModule()) - object_name = m_objfile->GetModule()->GetObjectName().GetCString(); - - if (file_spec) - s->Printf("Symtab, file = %s%s%s%s, num_symbols = %" PRIu64, - file_spec.GetPath().c_str(), - object_name ? "(" : "", - object_name ? object_name : "", - object_name ? ")" : "", - (uint64_t)m_symbols.size()); - else - s->Printf("Symtab, num_symbols = %" PRIu64 "", (uint64_t)m_symbols.size()); - - if (!m_symbols.empty()) - { - switch (sort_order) - { - case eSortOrderNone: - { - s->PutCString (":\n"); - DumpSymbolHeader (s); - const_iterator begin = m_symbols.begin(); - const_iterator end = m_symbols.end(); - for (const_iterator pos = m_symbols.begin(); pos != end; ++pos) - { - s->Indent(); - pos->Dump(s, target, std::distance(begin, pos)); - } - } - break; - - case eSortOrderByName: - { - // Although we maintain a lookup by exact name map, the table - // isn't sorted by name. So we must make the ordered symbol list - // up ourselves. - s->PutCString (" (sorted by name):\n"); - DumpSymbolHeader (s); - typedef std::multimap<const char*, const Symbol *, CStringCompareFunctionObject> CStringToSymbol; - CStringToSymbol name_map; - for (const_iterator pos = m_symbols.begin(), end = m_symbols.end(); pos != end; ++pos) - { - const char *name = pos->GetName().AsCString(); - if (name && name[0]) - name_map.insert (std::make_pair(name, &(*pos))); - } - - for (CStringToSymbol::const_iterator pos = name_map.begin(), end = name_map.end(); pos != end; ++pos) - { - s->Indent(); - pos->second->Dump (s, target, pos->second - &m_symbols[0]); - } - } - break; - - case eSortOrderByAddress: - s->PutCString (" (sorted by address):\n"); - DumpSymbolHeader (s); - if (!m_file_addr_to_index_computed) - InitAddressIndexes(); - const size_t num_entries = m_file_addr_to_index.GetSize(); - for (size_t i=0; i<num_entries; ++i) - { - s->Indent(); - const uint32_t symbol_idx = m_file_addr_to_index.GetEntryRef(i).data; - m_symbols[symbol_idx].Dump(s, target, symbol_idx); - } - break; - } +void Symtab::Dump(Stream *s, Target *target, SortOrder sort_order) { + std::lock_guard<std::recursive_mutex> guard(m_mutex); + + // s->Printf("%.*p: ", (int)sizeof(void*) * 2, this); + s->Indent(); + const FileSpec &file_spec = m_objfile->GetFileSpec(); + const char *object_name = nullptr; + if (m_objfile->GetModule()) + object_name = m_objfile->GetModule()->GetObjectName().GetCString(); + + if (file_spec) + s->Printf("Symtab, file = %s%s%s%s, num_symbols = %" PRIu64, + file_spec.GetPath().c_str(), object_name ? "(" : "", + object_name ? object_name : "", object_name ? ")" : "", + (uint64_t)m_symbols.size()); + else + s->Printf("Symtab, num_symbols = %" PRIu64 "", (uint64_t)m_symbols.size()); + + if (!m_symbols.empty()) { + switch (sort_order) { + case eSortOrderNone: { + s->PutCString(":\n"); + DumpSymbolHeader(s); + const_iterator begin = m_symbols.begin(); + const_iterator end = m_symbols.end(); + for (const_iterator pos = m_symbols.begin(); pos != end; ++pos) { + s->Indent(); + pos->Dump(s, target, std::distance(begin, pos)); + } + } break; + + case eSortOrderByName: { + // Although we maintain a lookup by exact name map, the table + // isn't sorted by name. So we must make the ordered symbol list + // up ourselves. + s->PutCString(" (sorted by name):\n"); + DumpSymbolHeader(s); + typedef std::multimap<const char *, const Symbol *, + CStringCompareFunctionObject> + CStringToSymbol; + CStringToSymbol name_map; + for (const_iterator pos = m_symbols.begin(), end = m_symbols.end(); + pos != end; ++pos) { + const char *name = pos->GetName().AsCString(); + if (name && name[0]) + name_map.insert(std::make_pair(name, &(*pos))); + } + + for (CStringToSymbol::const_iterator pos = name_map.begin(), + end = name_map.end(); + pos != end; ++pos) { + s->Indent(); + pos->second->Dump(s, target, pos->second - &m_symbols[0]); + } + } break; + + case eSortOrderByAddress: + s->PutCString(" (sorted by address):\n"); + DumpSymbolHeader(s); + if (!m_file_addr_to_index_computed) + InitAddressIndexes(); + const size_t num_entries = m_file_addr_to_index.GetSize(); + for (size_t i = 0; i < num_entries; ++i) { + s->Indent(); + const uint32_t symbol_idx = m_file_addr_to_index.GetEntryRef(i).data; + m_symbols[symbol_idx].Dump(s, target, symbol_idx); + } + break; } + } } -void -Symtab::Dump(Stream *s, Target *target, std::vector<uint32_t>& indexes) const -{ - std::lock_guard<std::recursive_mutex> guard(m_mutex); - - const size_t num_symbols = GetNumSymbols(); - //s->Printf("%.*p: ", (int)sizeof(void*) * 2, this); - s->Indent(); - s->Printf("Symtab %" PRIu64 " symbol indexes (%" PRIu64 " symbols total):\n", (uint64_t)indexes.size(), (uint64_t)m_symbols.size()); - s->IndentMore(); - - if (!indexes.empty()) - { - std::vector<uint32_t>::const_iterator pos; - std::vector<uint32_t>::const_iterator end = indexes.end(); - DumpSymbolHeader (s); - for (pos = indexes.begin(); pos != end; ++pos) - { - size_t idx = *pos; - if (idx < num_symbols) - { - s->Indent(); - m_symbols[idx].Dump(s, target, idx); - } - } +void Symtab::Dump(Stream *s, Target *target, + std::vector<uint32_t> &indexes) const { + std::lock_guard<std::recursive_mutex> guard(m_mutex); + + const size_t num_symbols = GetNumSymbols(); + // s->Printf("%.*p: ", (int)sizeof(void*) * 2, this); + s->Indent(); + s->Printf("Symtab %" PRIu64 " symbol indexes (%" PRIu64 " symbols total):\n", + (uint64_t)indexes.size(), (uint64_t)m_symbols.size()); + s->IndentMore(); + + if (!indexes.empty()) { + std::vector<uint32_t>::const_iterator pos; + std::vector<uint32_t>::const_iterator end = indexes.end(); + DumpSymbolHeader(s); + for (pos = indexes.begin(); pos != end; ++pos) { + size_t idx = *pos; + if (idx < num_symbols) { + s->Indent(); + m_symbols[idx].Dump(s, target, idx); + } } - s->IndentLess (); + } + s->IndentLess(); } -void -Symtab::DumpSymbolHeader (Stream *s) -{ - s->Indent(" Debug symbol\n"); - s->Indent(" |Synthetic symbol\n"); - s->Indent(" ||Externally Visible\n"); - s->Indent(" |||\n"); - s->Indent("Index UserID DSX Type File Address/Value Load Address Size Flags Name\n"); - s->Indent("------- ------ --- --------------- ------------------ ------------------ ------------------ ---------- ----------------------------------\n"); +void Symtab::DumpSymbolHeader(Stream *s) { + s->Indent(" Debug symbol\n"); + s->Indent(" |Synthetic symbol\n"); + s->Indent(" ||Externally Visible\n"); + s->Indent(" |||\n"); + s->Indent("Index UserID DSX Type File Address/Value Load " + "Address Size Flags Name\n"); + s->Indent("------- ------ --- --------------- ------------------ " + "------------------ ------------------ ---------- " + "----------------------------------\n"); } - -static int -CompareSymbolID (const void *key, const void *p) -{ - const user_id_t match_uid = *(const user_id_t*) key; - const user_id_t symbol_uid = ((const Symbol *)p)->GetID(); - if (match_uid < symbol_uid) - return -1; - if (match_uid > symbol_uid) - return 1; - return 0; +static int CompareSymbolID(const void *key, const void *p) { + const user_id_t match_uid = *(const user_id_t *)key; + const user_id_t symbol_uid = ((const Symbol *)p)->GetID(); + if (match_uid < symbol_uid) + return -1; + if (match_uid > symbol_uid) + return 1; + return 0; } -Symbol * -Symtab::FindSymbolByID (lldb::user_id_t symbol_uid) const -{ - std::lock_guard<std::recursive_mutex> guard(m_mutex); +Symbol *Symtab::FindSymbolByID(lldb::user_id_t symbol_uid) const { + std::lock_guard<std::recursive_mutex> guard(m_mutex); - Symbol *symbol = (Symbol*)::bsearch (&symbol_uid, - &m_symbols[0], - m_symbols.size(), - sizeof(m_symbols[0]), - CompareSymbolID); - return symbol; + Symbol *symbol = + (Symbol *)::bsearch(&symbol_uid, &m_symbols[0], m_symbols.size(), + sizeof(m_symbols[0]), CompareSymbolID); + return symbol; } - -Symbol * -Symtab::SymbolAtIndex(size_t idx) -{ - // Clients should grab the mutex from this symbol table and lock it manually - // when calling this function to avoid performance issues. - if (idx < m_symbols.size()) - return &m_symbols[idx]; - return nullptr; +Symbol *Symtab::SymbolAtIndex(size_t idx) { + // Clients should grab the mutex from this symbol table and lock it manually + // when calling this function to avoid performance issues. + if (idx < m_symbols.size()) + return &m_symbols[idx]; + return nullptr; } - -const Symbol * -Symtab::SymbolAtIndex(size_t idx) const -{ - // Clients should grab the mutex from this symbol table and lock it manually - // when calling this function to avoid performance issues. - if (idx < m_symbols.size()) - return &m_symbols[idx]; - return nullptr; +const Symbol *Symtab::SymbolAtIndex(size_t idx) const { + // Clients should grab the mutex from this symbol table and lock it manually + // when calling this function to avoid performance issues. + if (idx < m_symbols.size()) + return &m_symbols[idx]; + return nullptr; } //---------------------------------------------------------------------- // InitNameIndexes //---------------------------------------------------------------------- -void -Symtab::InitNameIndexes() -{ - // Protected function, no need to lock mutex... - if (!m_name_indexes_computed) - { - m_name_indexes_computed = true; - Timer scoped_timer (LLVM_PRETTY_FUNCTION, "%s", LLVM_PRETTY_FUNCTION); - // Create the name index vector to be able to quickly search by name - const size_t num_symbols = m_symbols.size(); +void Symtab::InitNameIndexes() { + // Protected function, no need to lock mutex... + if (!m_name_indexes_computed) { + m_name_indexes_computed = true; + Timer scoped_timer(LLVM_PRETTY_FUNCTION, "%s", LLVM_PRETTY_FUNCTION); + // Create the name index vector to be able to quickly search by name + const size_t num_symbols = m_symbols.size(); #if 1 - m_name_to_index.Reserve (num_symbols); + m_name_to_index.Reserve(num_symbols); #else - // TODO: benchmark this to see if we save any memory. Otherwise we - // will always keep the memory reserved in the vector unless we pull - // some STL swap magic and then recopy... - uint32_t actual_count = 0; - for (const_iterator pos = m_symbols.begin(), end = m_symbols.end(); - pos != end; - ++pos) - { - const Mangled &mangled = pos->GetMangled(); - if (mangled.GetMangledName()) - ++actual_count; - - if (mangled.GetDemangledName()) - ++actual_count; - } + // TODO: benchmark this to see if we save any memory. Otherwise we + // will always keep the memory reserved in the vector unless we pull + // some STL swap magic and then recopy... + uint32_t actual_count = 0; + for (const_iterator pos = m_symbols.begin(), end = m_symbols.end(); + pos != end; ++pos) { + const Mangled &mangled = pos->GetMangled(); + if (mangled.GetMangledName()) + ++actual_count; + + if (mangled.GetDemangledName()) + ++actual_count; + } - m_name_to_index.Reserve (actual_count); + m_name_to_index.Reserve(actual_count); #endif - NameToIndexMap::Entry entry; - - // The "const char *" in "class_contexts" must come from a ConstString::GetCString() - std::set<const char *> class_contexts; - UniqueCStringMap<uint32_t> mangled_name_to_index; - std::vector<const char *> symbol_contexts(num_symbols, nullptr); - - for (entry.value = 0; entry.value<num_symbols; ++entry.value) - { - const Symbol *symbol = &m_symbols[entry.value]; - - // Don't let trampolines get into the lookup by name map - // If we ever need the trampoline symbols to be searchable by name - // we can remove this and then possibly add a new bool to any of the - // Symtab functions that lookup symbols by name to indicate if they - // want trampolines. - if (symbol->IsTrampoline()) - continue; - - const Mangled &mangled = symbol->GetMangled(); - entry.cstring = mangled.GetMangledName().GetCString(); - if (entry.cstring && entry.cstring[0]) - { - m_name_to_index.Append (entry); - - if (symbol->ContainsLinkerAnnotations()) { - // If the symbol has linker annotations, also add the version without the - // annotations. - entry.cstring = ConstString(m_objfile->StripLinkerSymbolAnnotations(entry.cstring)).GetCString(); - m_name_to_index.Append (entry); - } - - const SymbolType symbol_type = symbol->GetType(); - if (symbol_type == eSymbolTypeCode || symbol_type == eSymbolTypeResolver) - { - if (entry.cstring[0] == '_' && entry.cstring[1] == 'Z' && - (entry.cstring[2] != 'T' && // avoid virtual table, VTT structure, typeinfo structure, and typeinfo name - entry.cstring[2] != 'G' && // avoid guard variables - entry.cstring[2] != 'Z')) // named local entities (if we eventually handle eSymbolTypeData, we will want this back) - { - CPlusPlusLanguage::MethodName cxx_method (mangled.GetDemangledName(lldb::eLanguageTypeC_plus_plus)); - entry.cstring = ConstString(cxx_method.GetBasename()).GetCString(); - if (entry.cstring && entry.cstring[0]) - { - // ConstString objects permanently store the string in the pool so calling - // GetCString() on the value gets us a const char * that will never go away - const char *const_context = ConstString(cxx_method.GetContext()).GetCString(); - - if (entry.cstring[0] == '~' || !cxx_method.GetQualifiers().empty()) - { - // The first character of the demangled basename is '~' which - // means we have a class destructor. We can use this information - // to help us know what is a class and what isn't. - if (class_contexts.find(const_context) == class_contexts.end()) - class_contexts.insert(const_context); - m_method_to_index.Append (entry); - } - else - { - if (const_context && const_context[0]) - { - if (class_contexts.find(const_context) != class_contexts.end()) - { - // The current decl context is in our "class_contexts" which means - // this is a method on a class - m_method_to_index.Append (entry); - } - else - { - // We don't know if this is a function basename or a method, - // so put it into a temporary collection so once we are done - // we can look in class_contexts to see if each entry is a class - // or just a function and will put any remaining items into - // m_method_to_index or m_basename_to_index as needed - mangled_name_to_index.Append (entry); - symbol_contexts[entry.value] = const_context; - } - } - else - { - // No context for this function so this has to be a basename - m_basename_to_index.Append(entry); - } - } - } - } - } - } - - entry.cstring = mangled.GetDemangledName(symbol->GetLanguage()).GetCString(); - if (entry.cstring && entry.cstring[0]) { - m_name_to_index.Append (entry); + NameToIndexMap::Entry entry; + + // The "const char *" in "class_contexts" must come from a + // ConstString::GetCString() + std::set<const char *> class_contexts; + UniqueCStringMap<uint32_t> mangled_name_to_index; + std::vector<const char *> symbol_contexts(num_symbols, nullptr); + + for (entry.value = 0; entry.value < num_symbols; ++entry.value) { + const Symbol *symbol = &m_symbols[entry.value]; + + // Don't let trampolines get into the lookup by name map + // If we ever need the trampoline symbols to be searchable by name + // we can remove this and then possibly add a new bool to any of the + // Symtab functions that lookup symbols by name to indicate if they + // want trampolines. + if (symbol->IsTrampoline()) + continue; + + const Mangled &mangled = symbol->GetMangled(); + entry.cstring = mangled.GetMangledName().GetCString(); + if (entry.cstring && entry.cstring[0]) { + m_name_to_index.Append(entry); + + if (symbol->ContainsLinkerAnnotations()) { + // If the symbol has linker annotations, also add the version without + // the + // annotations. + entry.cstring = ConstString(m_objfile->StripLinkerSymbolAnnotations( + entry.cstring)) + .GetCString(); + m_name_to_index.Append(entry); + } - if (symbol->ContainsLinkerAnnotations()) { - // If the symbol has linker annotations, also add the version without the - // annotations. - entry.cstring = ConstString(m_objfile->StripLinkerSymbolAnnotations(entry.cstring)).GetCString(); - m_name_to_index.Append (entry); - } - } - - // If the demangled name turns out to be an ObjC name, and - // is a category name, add the version without categories to the index too. - ObjCLanguage::MethodName objc_method (entry.cstring, true); - if (objc_method.IsValid(true)) - { - entry.cstring = objc_method.GetSelector().GetCString(); - m_selector_to_index.Append (entry); - - ConstString objc_method_no_category (objc_method.GetFullNameWithoutCategory(true)); - if (objc_method_no_category) - { - entry.cstring = objc_method_no_category.GetCString(); - m_name_to_index.Append (entry); + const SymbolType symbol_type = symbol->GetType(); + if (symbol_type == eSymbolTypeCode || + symbol_type == eSymbolTypeResolver) { + if (entry.cstring[0] == '_' && entry.cstring[1] == 'Z' && + (entry.cstring[2] != 'T' && // avoid virtual table, VTT structure, + // typeinfo structure, and typeinfo + // name + entry.cstring[2] != 'G' && // avoid guard variables + entry.cstring[2] != 'Z')) // named local entities (if we + // eventually handle eSymbolTypeData, + // we will want this back) + { + CPlusPlusLanguage::MethodName cxx_method( + mangled.GetDemangledName(lldb::eLanguageTypeC_plus_plus)); + entry.cstring = ConstString(cxx_method.GetBasename()).GetCString(); + if (entry.cstring && entry.cstring[0]) { + // ConstString objects permanently store the string in the pool so + // calling + // GetCString() on the value gets us a const char * that will + // never go away + const char *const_context = + ConstString(cxx_method.GetContext()).GetCString(); + + if (entry.cstring[0] == '~' || + !cxx_method.GetQualifiers().empty()) { + // The first character of the demangled basename is '~' which + // means we have a class destructor. We can use this information + // to help us know what is a class and what isn't. + if (class_contexts.find(const_context) == class_contexts.end()) + class_contexts.insert(const_context); + m_method_to_index.Append(entry); + } else { + if (const_context && const_context[0]) { + if (class_contexts.find(const_context) != + class_contexts.end()) { + // The current decl context is in our "class_contexts" which + // means + // this is a method on a class + m_method_to_index.Append(entry); + } else { + // We don't know if this is a function basename or a method, + // so put it into a temporary collection so once we are done + // we can look in class_contexts to see if each entry is a + // class + // or just a function and will put any remaining items into + // m_method_to_index or m_basename_to_index as needed + mangled_name_to_index.Append(entry); + symbol_contexts[entry.value] = const_context; + } + } else { + // No context for this function so this has to be a basename + m_basename_to_index.Append(entry); } + } } - + } } - - size_t count; - if (!mangled_name_to_index.IsEmpty()) - { - count = mangled_name_to_index.GetSize(); - for (size_t i=0; i<count; ++i) - { - if (mangled_name_to_index.GetValueAtIndex(i, entry.value)) - { - entry.cstring = mangled_name_to_index.GetCStringAtIndex(i); - if (symbol_contexts[entry.value] && class_contexts.find(symbol_contexts[entry.value]) != class_contexts.end()) - { - m_method_to_index.Append (entry); - } - else - { - // If we got here, we have something that had a context (was inside a namespace or class) - // yet we don't know if the entry - m_method_to_index.Append (entry); - m_basename_to_index.Append (entry); - } - } - } + } + + entry.cstring = + mangled.GetDemangledName(symbol->GetLanguage()).GetCString(); + if (entry.cstring && entry.cstring[0]) { + m_name_to_index.Append(entry); + + if (symbol->ContainsLinkerAnnotations()) { + // If the symbol has linker annotations, also add the version without + // the + // annotations. + entry.cstring = ConstString(m_objfile->StripLinkerSymbolAnnotations( + entry.cstring)) + .GetCString(); + m_name_to_index.Append(entry); } - m_name_to_index.Sort(); - m_name_to_index.SizeToFit(); - m_selector_to_index.Sort(); - m_selector_to_index.SizeToFit(); - m_basename_to_index.Sort(); - m_basename_to_index.SizeToFit(); - m_method_to_index.Sort(); - m_method_to_index.SizeToFit(); - -// static StreamFile a ("/tmp/a.txt"); -// -// count = m_basename_to_index.GetSize(); -// if (count) -// { -// for (size_t i=0; i<count; ++i) -// { -// if (m_basename_to_index.GetValueAtIndex(i, entry.value)) -// a.Printf ("%s BASENAME\n", m_symbols[entry.value].GetMangled().GetName().GetCString()); -// } -// } -// count = m_method_to_index.GetSize(); -// if (count) -// { -// for (size_t i=0; i<count; ++i) -// { -// if (m_method_to_index.GetValueAtIndex(i, entry.value)) -// a.Printf ("%s METHOD\n", m_symbols[entry.value].GetMangled().GetName().GetCString()); -// } -// } + } + + // If the demangled name turns out to be an ObjC name, and + // is a category name, add the version without categories to the index + // too. + ObjCLanguage::MethodName objc_method(entry.cstring, true); + if (objc_method.IsValid(true)) { + entry.cstring = objc_method.GetSelector().GetCString(); + m_selector_to_index.Append(entry); + + ConstString objc_method_no_category( + objc_method.GetFullNameWithoutCategory(true)); + if (objc_method_no_category) { + entry.cstring = objc_method_no_category.GetCString(); + m_name_to_index.Append(entry); + } + } } -} -void -Symtab::AppendSymbolNamesToMap (const IndexCollection &indexes, - bool add_demangled, - bool add_mangled, - NameToIndexMap &name_to_index_map) const -{ - if (add_demangled || add_mangled) - { - Timer scoped_timer (LLVM_PRETTY_FUNCTION, "%s", LLVM_PRETTY_FUNCTION); - std::lock_guard<std::recursive_mutex> guard(m_mutex); - - // Create the name index vector to be able to quickly search by name - NameToIndexMap::Entry entry; - const size_t num_indexes = indexes.size(); - for (size_t i=0; i<num_indexes; ++i) - { - entry.value = indexes[i]; - assert (i < m_symbols.size()); - const Symbol *symbol = &m_symbols[entry.value]; - - const Mangled &mangled = symbol->GetMangled(); - if (add_demangled) - { - entry.cstring = mangled.GetDemangledName(symbol->GetLanguage()).GetCString(); - if (entry.cstring && entry.cstring[0]) - name_to_index_map.Append (entry); - } - - if (add_mangled) - { - entry.cstring = mangled.GetMangledName().GetCString(); - if (entry.cstring && entry.cstring[0]) - name_to_index_map.Append (entry); - } + size_t count; + if (!mangled_name_to_index.IsEmpty()) { + count = mangled_name_to_index.GetSize(); + for (size_t i = 0; i < count; ++i) { + if (mangled_name_to_index.GetValueAtIndex(i, entry.value)) { + entry.cstring = mangled_name_to_index.GetCStringAtIndex(i); + if (symbol_contexts[entry.value] && + class_contexts.find(symbol_contexts[entry.value]) != + class_contexts.end()) { + m_method_to_index.Append(entry); + } else { + // If we got here, we have something that had a context (was inside + // a namespace or class) + // yet we don't know if the entry + m_method_to_index.Append(entry); + m_basename_to_index.Append(entry); + } } + } } + m_name_to_index.Sort(); + m_name_to_index.SizeToFit(); + m_selector_to_index.Sort(); + m_selector_to_index.SizeToFit(); + m_basename_to_index.Sort(); + m_basename_to_index.SizeToFit(); + m_method_to_index.Sort(); + m_method_to_index.SizeToFit(); + + // static StreamFile a ("/tmp/a.txt"); + // + // count = m_basename_to_index.GetSize(); + // if (count) + // { + // for (size_t i=0; i<count; ++i) + // { + // if (m_basename_to_index.GetValueAtIndex(i, entry.value)) + // a.Printf ("%s BASENAME\n", + // m_symbols[entry.value].GetMangled().GetName().GetCString()); + // } + // } + // count = m_method_to_index.GetSize(); + // if (count) + // { + // for (size_t i=0; i<count; ++i) + // { + // if (m_method_to_index.GetValueAtIndex(i, entry.value)) + // a.Printf ("%s METHOD\n", + // m_symbols[entry.value].GetMangled().GetName().GetCString()); + // } + // } + } } -uint32_t -Symtab::AppendSymbolIndexesWithType (SymbolType symbol_type, std::vector<uint32_t>& indexes, uint32_t start_idx, uint32_t end_index) const -{ +void Symtab::AppendSymbolNamesToMap(const IndexCollection &indexes, + bool add_demangled, bool add_mangled, + NameToIndexMap &name_to_index_map) const { + if (add_demangled || add_mangled) { + Timer scoped_timer(LLVM_PRETTY_FUNCTION, "%s", LLVM_PRETTY_FUNCTION); std::lock_guard<std::recursive_mutex> guard(m_mutex); - uint32_t prev_size = indexes.size(); + // Create the name index vector to be able to quickly search by name + NameToIndexMap::Entry entry; + const size_t num_indexes = indexes.size(); + for (size_t i = 0; i < num_indexes; ++i) { + entry.value = indexes[i]; + assert(i < m_symbols.size()); + const Symbol *symbol = &m_symbols[entry.value]; + + const Mangled &mangled = symbol->GetMangled(); + if (add_demangled) { + entry.cstring = + mangled.GetDemangledName(symbol->GetLanguage()).GetCString(); + if (entry.cstring && entry.cstring[0]) + name_to_index_map.Append(entry); + } + + if (add_mangled) { + entry.cstring = mangled.GetMangledName().GetCString(); + if (entry.cstring && entry.cstring[0]) + name_to_index_map.Append(entry); + } + } + } +} - const uint32_t count = std::min<uint32_t> (m_symbols.size(), end_index); +uint32_t Symtab::AppendSymbolIndexesWithType(SymbolType symbol_type, + std::vector<uint32_t> &indexes, + uint32_t start_idx, + uint32_t end_index) const { + std::lock_guard<std::recursive_mutex> guard(m_mutex); - for (uint32_t i = start_idx; i < count; ++i) - { - if (symbol_type == eSymbolTypeAny || m_symbols[i].GetType() == symbol_type) - indexes.push_back(i); - } + uint32_t prev_size = indexes.size(); - return indexes.size() - prev_size; + const uint32_t count = std::min<uint32_t>(m_symbols.size(), end_index); + + for (uint32_t i = start_idx; i < count; ++i) { + if (symbol_type == eSymbolTypeAny || m_symbols[i].GetType() == symbol_type) + indexes.push_back(i); + } + + return indexes.size() - prev_size; } -uint32_t -Symtab::AppendSymbolIndexesWithTypeAndFlagsValue (SymbolType symbol_type, uint32_t flags_value, std::vector<uint32_t>& indexes, uint32_t start_idx, uint32_t end_index) const -{ - std::lock_guard<std::recursive_mutex> guard(m_mutex); +uint32_t Symtab::AppendSymbolIndexesWithTypeAndFlagsValue( + SymbolType symbol_type, uint32_t flags_value, + std::vector<uint32_t> &indexes, uint32_t start_idx, + uint32_t end_index) const { + std::lock_guard<std::recursive_mutex> guard(m_mutex); - uint32_t prev_size = indexes.size(); + uint32_t prev_size = indexes.size(); - const uint32_t count = std::min<uint32_t> (m_symbols.size(), end_index); + const uint32_t count = std::min<uint32_t>(m_symbols.size(), end_index); - for (uint32_t i = start_idx; i < count; ++i) - { - if ((symbol_type == eSymbolTypeAny || m_symbols[i].GetType() == symbol_type) && m_symbols[i].GetFlags() == flags_value) - indexes.push_back(i); - } + for (uint32_t i = start_idx; i < count; ++i) { + if ((symbol_type == eSymbolTypeAny || + m_symbols[i].GetType() == symbol_type) && + m_symbols[i].GetFlags() == flags_value) + indexes.push_back(i); + } - return indexes.size() - prev_size; + return indexes.size() - prev_size; } -uint32_t -Symtab::AppendSymbolIndexesWithType (SymbolType symbol_type, Debug symbol_debug_type, Visibility symbol_visibility, std::vector<uint32_t>& indexes, uint32_t start_idx, uint32_t end_index) const -{ - std::lock_guard<std::recursive_mutex> guard(m_mutex); +uint32_t Symtab::AppendSymbolIndexesWithType(SymbolType symbol_type, + Debug symbol_debug_type, + Visibility symbol_visibility, + std::vector<uint32_t> &indexes, + uint32_t start_idx, + uint32_t end_index) const { + std::lock_guard<std::recursive_mutex> guard(m_mutex); - uint32_t prev_size = indexes.size(); + uint32_t prev_size = indexes.size(); - const uint32_t count = std::min<uint32_t> (m_symbols.size(), end_index); + const uint32_t count = std::min<uint32_t>(m_symbols.size(), end_index); - for (uint32_t i = start_idx; i < count; ++i) - { - if (symbol_type == eSymbolTypeAny || m_symbols[i].GetType() == symbol_type) - { - if (CheckSymbolAtIndex(i, symbol_debug_type, symbol_visibility)) - indexes.push_back(i); - } + for (uint32_t i = start_idx; i < count; ++i) { + if (symbol_type == eSymbolTypeAny || + m_symbols[i].GetType() == symbol_type) { + if (CheckSymbolAtIndex(i, symbol_debug_type, symbol_visibility)) + indexes.push_back(i); } + } - return indexes.size() - prev_size; + return indexes.size() - prev_size; } - -uint32_t -Symtab::GetIndexForSymbol (const Symbol *symbol) const -{ - if (!m_symbols.empty()) - { - const Symbol *first_symbol = &m_symbols[0]; - if (symbol >= first_symbol && symbol < first_symbol + m_symbols.size()) - return symbol - first_symbol; - } - return UINT32_MAX; +uint32_t Symtab::GetIndexForSymbol(const Symbol *symbol) const { + if (!m_symbols.empty()) { + const Symbol *first_symbol = &m_symbols[0]; + if (symbol >= first_symbol && symbol < first_symbol + m_symbols.size()) + return symbol - first_symbol; + } + return UINT32_MAX; } -struct SymbolSortInfo -{ - const bool sort_by_load_addr; - const Symbol *symbols; +struct SymbolSortInfo { + const bool sort_by_load_addr; + const Symbol *symbols; }; namespace { - struct SymbolIndexComparator { - const std::vector<Symbol>& symbols; - std::vector<lldb::addr_t> &addr_cache; - - // Getting from the symbol to the Address to the File Address involves some work. - // Since there are potentially many symbols here, and we're using this for sorting so - // we're going to be computing the address many times, cache that in addr_cache. - // The array passed in has to be the same size as the symbols array passed into the - // member variable symbols, and should be initialized with LLDB_INVALID_ADDRESS. - // NOTE: You have to make addr_cache externally and pass it in because std::stable_sort - // makes copies of the comparator it is initially passed in, and you end up spending - // huge amounts of time copying this array... - - SymbolIndexComparator(const std::vector<Symbol>& s, std::vector<lldb::addr_t> &a) : symbols(s), addr_cache(a) { - assert (symbols.size() == addr_cache.size()); - } - bool operator()(uint32_t index_a, uint32_t index_b) { - addr_t value_a = addr_cache[index_a]; - if (value_a == LLDB_INVALID_ADDRESS) - { - value_a = symbols[index_a].GetAddressRef().GetFileAddress(); - addr_cache[index_a] = value_a; - } - - addr_t value_b = addr_cache[index_b]; - if (value_b == LLDB_INVALID_ADDRESS) - { - value_b = symbols[index_b].GetAddressRef().GetFileAddress(); - addr_cache[index_b] = value_b; - } - - - if (value_a == value_b) { - // The if the values are equal, use the original symbol user ID - lldb::user_id_t uid_a = symbols[index_a].GetID(); - lldb::user_id_t uid_b = symbols[index_b].GetID(); - if (uid_a < uid_b) - return true; - if (uid_a > uid_b) - return false; - return false; - } else if (value_a < value_b) - return true; - - return false; - } - }; -} +struct SymbolIndexComparator { + const std::vector<Symbol> &symbols; + std::vector<lldb::addr_t> &addr_cache; + + // Getting from the symbol to the Address to the File Address involves some + // work. + // Since there are potentially many symbols here, and we're using this for + // sorting so + // we're going to be computing the address many times, cache that in + // addr_cache. + // The array passed in has to be the same size as the symbols array passed + // into the + // member variable symbols, and should be initialized with + // LLDB_INVALID_ADDRESS. + // NOTE: You have to make addr_cache externally and pass it in because + // std::stable_sort + // makes copies of the comparator it is initially passed in, and you end up + // spending + // huge amounts of time copying this array... + + SymbolIndexComparator(const std::vector<Symbol> &s, + std::vector<lldb::addr_t> &a) + : symbols(s), addr_cache(a) { + assert(symbols.size() == addr_cache.size()); + } + bool operator()(uint32_t index_a, uint32_t index_b) { + addr_t value_a = addr_cache[index_a]; + if (value_a == LLDB_INVALID_ADDRESS) { + value_a = symbols[index_a].GetAddressRef().GetFileAddress(); + addr_cache[index_a] = value_a; + } -void -Symtab::SortSymbolIndexesByValue (std::vector<uint32_t>& indexes, bool remove_duplicates) const -{ - std::lock_guard<std::recursive_mutex> guard(m_mutex); + addr_t value_b = addr_cache[index_b]; + if (value_b == LLDB_INVALID_ADDRESS) { + value_b = symbols[index_b].GetAddressRef().GetFileAddress(); + addr_cache[index_b] = value_b; + } - Timer scoped_timer (LLVM_PRETTY_FUNCTION,LLVM_PRETTY_FUNCTION); - // No need to sort if we have zero or one items... - if (indexes.size() <= 1) - return; - - // Sort the indexes in place using std::stable_sort. - // NOTE: The use of std::stable_sort instead of std::sort here is strictly for performance, - // not correctness. The indexes vector tends to be "close" to sorted, which the - // stable sort handles better. - - std::vector<lldb::addr_t> addr_cache(m_symbols.size(), LLDB_INVALID_ADDRESS); - - SymbolIndexComparator comparator(m_symbols, addr_cache); - std::stable_sort(indexes.begin(), indexes.end(), comparator); - - // Remove any duplicates if requested - if (remove_duplicates) - std::unique(indexes.begin(), indexes.end()); + if (value_a == value_b) { + // The if the values are equal, use the original symbol user ID + lldb::user_id_t uid_a = symbols[index_a].GetID(); + lldb::user_id_t uid_b = symbols[index_b].GetID(); + if (uid_a < uid_b) + return true; + if (uid_a > uid_b) + return false; + return false; + } else if (value_a < value_b) + return true; + + return false; + } +}; } -uint32_t -Symtab::AppendSymbolIndexesWithName (const ConstString& symbol_name, std::vector<uint32_t>& indexes) -{ - std::lock_guard<std::recursive_mutex> guard(m_mutex); +void Symtab::SortSymbolIndexesByValue(std::vector<uint32_t> &indexes, + bool remove_duplicates) const { + std::lock_guard<std::recursive_mutex> guard(m_mutex); - Timer scoped_timer (LLVM_PRETTY_FUNCTION, "%s", LLVM_PRETTY_FUNCTION); - if (symbol_name) - { - const char *symbol_cstr = symbol_name.GetCString(); - if (!m_name_indexes_computed) - InitNameIndexes(); + Timer scoped_timer(LLVM_PRETTY_FUNCTION, LLVM_PRETTY_FUNCTION); + // No need to sort if we have zero or one items... + if (indexes.size() <= 1) + return; - return m_name_to_index.GetValues (symbol_cstr, indexes); - } - return 0; -} + // Sort the indexes in place using std::stable_sort. + // NOTE: The use of std::stable_sort instead of std::sort here is strictly for + // performance, + // not correctness. The indexes vector tends to be "close" to sorted, which + // the + // stable sort handles better. -uint32_t -Symtab::AppendSymbolIndexesWithName (const ConstString& symbol_name, Debug symbol_debug_type, Visibility symbol_visibility, std::vector<uint32_t>& indexes) -{ - std::lock_guard<std::recursive_mutex> guard(m_mutex); + std::vector<lldb::addr_t> addr_cache(m_symbols.size(), LLDB_INVALID_ADDRESS); - Timer scoped_timer (LLVM_PRETTY_FUNCTION, "%s", LLVM_PRETTY_FUNCTION); - if (symbol_name) - { - const size_t old_size = indexes.size(); - if (!m_name_indexes_computed) - InitNameIndexes(); - - const char *symbol_cstr = symbol_name.GetCString(); - - std::vector<uint32_t> all_name_indexes; - const size_t name_match_count = m_name_to_index.GetValues (symbol_cstr, all_name_indexes); - for (size_t i=0; i<name_match_count; ++i) - { - if (CheckSymbolAtIndex(all_name_indexes[i], symbol_debug_type, symbol_visibility)) - indexes.push_back (all_name_indexes[i]); - } - return indexes.size() - old_size; - } - return 0; -} - -uint32_t -Symtab::AppendSymbolIndexesWithNameAndType (const ConstString& symbol_name, SymbolType symbol_type, std::vector<uint32_t>& indexes) -{ - std::lock_guard<std::recursive_mutex> guard(m_mutex); + SymbolIndexComparator comparator(m_symbols, addr_cache); + std::stable_sort(indexes.begin(), indexes.end(), comparator); - if (AppendSymbolIndexesWithName(symbol_name, indexes) > 0) - { - std::vector<uint32_t>::iterator pos = indexes.begin(); - while (pos != indexes.end()) - { - if (symbol_type == eSymbolTypeAny || m_symbols[*pos].GetType() == symbol_type) - ++pos; - else - pos = indexes.erase(pos); - } - } - return indexes.size(); + // Remove any duplicates if requested + if (remove_duplicates) + std::unique(indexes.begin(), indexes.end()); } -uint32_t -Symtab::AppendSymbolIndexesWithNameAndType (const ConstString& symbol_name, SymbolType symbol_type, Debug symbol_debug_type, Visibility symbol_visibility, std::vector<uint32_t>& indexes) -{ - std::lock_guard<std::recursive_mutex> guard(m_mutex); +uint32_t Symtab::AppendSymbolIndexesWithName(const ConstString &symbol_name, + std::vector<uint32_t> &indexes) { + std::lock_guard<std::recursive_mutex> guard(m_mutex); - if (AppendSymbolIndexesWithName(symbol_name, symbol_debug_type, symbol_visibility, indexes) > 0) - { - std::vector<uint32_t>::iterator pos = indexes.begin(); - while (pos != indexes.end()) - { - if (symbol_type == eSymbolTypeAny || m_symbols[*pos].GetType() == symbol_type) - ++pos; - else - pos = indexes.erase(pos); - } - } - return indexes.size(); + Timer scoped_timer(LLVM_PRETTY_FUNCTION, "%s", LLVM_PRETTY_FUNCTION); + if (symbol_name) { + const char *symbol_cstr = symbol_name.GetCString(); + if (!m_name_indexes_computed) + InitNameIndexes(); + + return m_name_to_index.GetValues(symbol_cstr, indexes); + } + return 0; } +uint32_t Symtab::AppendSymbolIndexesWithName(const ConstString &symbol_name, + Debug symbol_debug_type, + Visibility symbol_visibility, + std::vector<uint32_t> &indexes) { + std::lock_guard<std::recursive_mutex> guard(m_mutex); -uint32_t -Symtab::AppendSymbolIndexesMatchingRegExAndType (const RegularExpression ®exp, SymbolType symbol_type, std::vector<uint32_t>& indexes) -{ - std::lock_guard<std::recursive_mutex> guard(m_mutex); + Timer scoped_timer(LLVM_PRETTY_FUNCTION, "%s", LLVM_PRETTY_FUNCTION); + if (symbol_name) { + const size_t old_size = indexes.size(); + if (!m_name_indexes_computed) + InitNameIndexes(); - uint32_t prev_size = indexes.size(); - uint32_t sym_end = m_symbols.size(); - - for (uint32_t i = 0; i < sym_end; i++) - { - if (symbol_type == eSymbolTypeAny || m_symbols[i].GetType() == symbol_type) - { - const char *name = m_symbols[i].GetName().AsCString(); - if (name) - { - if (regexp.Execute (name)) - indexes.push_back(i); - } - } - } - return indexes.size() - prev_size; + const char *symbol_cstr = symbol_name.GetCString(); + std::vector<uint32_t> all_name_indexes; + const size_t name_match_count = + m_name_to_index.GetValues(symbol_cstr, all_name_indexes); + for (size_t i = 0; i < name_match_count; ++i) { + if (CheckSymbolAtIndex(all_name_indexes[i], symbol_debug_type, + symbol_visibility)) + indexes.push_back(all_name_indexes[i]); + } + return indexes.size() - old_size; + } + return 0; } uint32_t -Symtab::AppendSymbolIndexesMatchingRegExAndType (const RegularExpression ®exp, SymbolType symbol_type, Debug symbol_debug_type, Visibility symbol_visibility, std::vector<uint32_t>& indexes) -{ - std::lock_guard<std::recursive_mutex> guard(m_mutex); - - uint32_t prev_size = indexes.size(); - uint32_t sym_end = m_symbols.size(); - - for (uint32_t i = 0; i < sym_end; i++) - { - if (symbol_type == eSymbolTypeAny || m_symbols[i].GetType() == symbol_type) - { - if (CheckSymbolAtIndex(i, symbol_debug_type, symbol_visibility) == false) - continue; - - const char *name = m_symbols[i].GetName().AsCString(); - if (name) - { - if (regexp.Execute (name)) - indexes.push_back(i); - } - } +Symtab::AppendSymbolIndexesWithNameAndType(const ConstString &symbol_name, + SymbolType symbol_type, + std::vector<uint32_t> &indexes) { + std::lock_guard<std::recursive_mutex> guard(m_mutex); + + if (AppendSymbolIndexesWithName(symbol_name, indexes) > 0) { + std::vector<uint32_t>::iterator pos = indexes.begin(); + while (pos != indexes.end()) { + if (symbol_type == eSymbolTypeAny || + m_symbols[*pos].GetType() == symbol_type) + ++pos; + else + pos = indexes.erase(pos); } - return indexes.size() - prev_size; - + } + return indexes.size(); } -Symbol * -Symtab::FindSymbolWithType (SymbolType symbol_type, Debug symbol_debug_type, Visibility symbol_visibility, uint32_t& start_idx) -{ - std::lock_guard<std::recursive_mutex> guard(m_mutex); - - const size_t count = m_symbols.size(); - for (size_t idx = start_idx; idx < count; ++idx) - { - if (symbol_type == eSymbolTypeAny || m_symbols[idx].GetType() == symbol_type) - { - if (CheckSymbolAtIndex(idx, symbol_debug_type, symbol_visibility)) - { - start_idx = idx; - return &m_symbols[idx]; - } - } +uint32_t Symtab::AppendSymbolIndexesWithNameAndType( + const ConstString &symbol_name, SymbolType symbol_type, + Debug symbol_debug_type, Visibility symbol_visibility, + std::vector<uint32_t> &indexes) { + std::lock_guard<std::recursive_mutex> guard(m_mutex); + + if (AppendSymbolIndexesWithName(symbol_name, symbol_debug_type, + symbol_visibility, indexes) > 0) { + std::vector<uint32_t>::iterator pos = indexes.begin(); + while (pos != indexes.end()) { + if (symbol_type == eSymbolTypeAny || + m_symbols[*pos].GetType() == symbol_type) + ++pos; + else + pos = indexes.erase(pos); } - return nullptr; + } + return indexes.size(); } -size_t -Symtab::FindAllSymbolsWithNameAndType (const ConstString &name, SymbolType symbol_type, std::vector<uint32_t>& symbol_indexes) -{ - std::lock_guard<std::recursive_mutex> guard(m_mutex); - - Timer scoped_timer (LLVM_PRETTY_FUNCTION, "%s", LLVM_PRETTY_FUNCTION); - // Initialize all of the lookup by name indexes before converting NAME - // to a uniqued string NAME_STR below. - if (!m_name_indexes_computed) - InitNameIndexes(); - - if (name) - { - // The string table did have a string that matched, but we need - // to check the symbols and match the symbol_type if any was given. - AppendSymbolIndexesWithNameAndType (name, symbol_type, symbol_indexes); +uint32_t Symtab::AppendSymbolIndexesMatchingRegExAndType( + const RegularExpression ®exp, SymbolType symbol_type, + std::vector<uint32_t> &indexes) { + std::lock_guard<std::recursive_mutex> guard(m_mutex); + + uint32_t prev_size = indexes.size(); + uint32_t sym_end = m_symbols.size(); + + for (uint32_t i = 0; i < sym_end; i++) { + if (symbol_type == eSymbolTypeAny || + m_symbols[i].GetType() == symbol_type) { + const char *name = m_symbols[i].GetName().AsCString(); + if (name) { + if (regexp.Execute(name)) + indexes.push_back(i); + } } - return symbol_indexes.size(); + } + return indexes.size() - prev_size; } -size_t -Symtab::FindAllSymbolsWithNameAndType (const ConstString &name, SymbolType symbol_type, Debug symbol_debug_type, Visibility symbol_visibility, std::vector<uint32_t>& symbol_indexes) -{ - std::lock_guard<std::recursive_mutex> guard(m_mutex); - - Timer scoped_timer (LLVM_PRETTY_FUNCTION, "%s", LLVM_PRETTY_FUNCTION); - // Initialize all of the lookup by name indexes before converting NAME - // to a uniqued string NAME_STR below. - if (!m_name_indexes_computed) - InitNameIndexes(); +uint32_t Symtab::AppendSymbolIndexesMatchingRegExAndType( + const RegularExpression ®exp, SymbolType symbol_type, + Debug symbol_debug_type, Visibility symbol_visibility, + std::vector<uint32_t> &indexes) { + std::lock_guard<std::recursive_mutex> guard(m_mutex); + + uint32_t prev_size = indexes.size(); + uint32_t sym_end = m_symbols.size(); + + for (uint32_t i = 0; i < sym_end; i++) { + if (symbol_type == eSymbolTypeAny || + m_symbols[i].GetType() == symbol_type) { + if (CheckSymbolAtIndex(i, symbol_debug_type, symbol_visibility) == false) + continue; + + const char *name = m_symbols[i].GetName().AsCString(); + if (name) { + if (regexp.Execute(name)) + indexes.push_back(i); + } + } + } + return indexes.size() - prev_size; +} - if (name) - { - // The string table did have a string that matched, but we need - // to check the symbols and match the symbol_type if any was given. - AppendSymbolIndexesWithNameAndType (name, symbol_type, symbol_debug_type, symbol_visibility, symbol_indexes); +Symbol *Symtab::FindSymbolWithType(SymbolType symbol_type, + Debug symbol_debug_type, + Visibility symbol_visibility, + uint32_t &start_idx) { + std::lock_guard<std::recursive_mutex> guard(m_mutex); + + const size_t count = m_symbols.size(); + for (size_t idx = start_idx; idx < count; ++idx) { + if (symbol_type == eSymbolTypeAny || + m_symbols[idx].GetType() == symbol_type) { + if (CheckSymbolAtIndex(idx, symbol_debug_type, symbol_visibility)) { + start_idx = idx; + return &m_symbols[idx]; + } } - return symbol_indexes.size(); + } + return nullptr; } size_t -Symtab::FindAllSymbolsMatchingRexExAndType (const RegularExpression ®ex, SymbolType symbol_type, Debug symbol_debug_type, Visibility symbol_visibility, std::vector<uint32_t>& symbol_indexes) -{ - std::lock_guard<std::recursive_mutex> guard(m_mutex); +Symtab::FindAllSymbolsWithNameAndType(const ConstString &name, + SymbolType symbol_type, + std::vector<uint32_t> &symbol_indexes) { + std::lock_guard<std::recursive_mutex> guard(m_mutex); + + Timer scoped_timer(LLVM_PRETTY_FUNCTION, "%s", LLVM_PRETTY_FUNCTION); + // Initialize all of the lookup by name indexes before converting NAME + // to a uniqued string NAME_STR below. + if (!m_name_indexes_computed) + InitNameIndexes(); + + if (name) { + // The string table did have a string that matched, but we need + // to check the symbols and match the symbol_type if any was given. + AppendSymbolIndexesWithNameAndType(name, symbol_type, symbol_indexes); + } + return symbol_indexes.size(); +} - AppendSymbolIndexesMatchingRegExAndType(regex, symbol_type, symbol_debug_type, symbol_visibility, symbol_indexes); - return symbol_indexes.size(); +size_t Symtab::FindAllSymbolsWithNameAndType( + const ConstString &name, SymbolType symbol_type, Debug symbol_debug_type, + Visibility symbol_visibility, std::vector<uint32_t> &symbol_indexes) { + std::lock_guard<std::recursive_mutex> guard(m_mutex); + + Timer scoped_timer(LLVM_PRETTY_FUNCTION, "%s", LLVM_PRETTY_FUNCTION); + // Initialize all of the lookup by name indexes before converting NAME + // to a uniqued string NAME_STR below. + if (!m_name_indexes_computed) + InitNameIndexes(); + + if (name) { + // The string table did have a string that matched, but we need + // to check the symbols and match the symbol_type if any was given. + AppendSymbolIndexesWithNameAndType(name, symbol_type, symbol_debug_type, + symbol_visibility, symbol_indexes); + } + return symbol_indexes.size(); } -Symbol * -Symtab::FindFirstSymbolWithNameAndType (const ConstString &name, SymbolType symbol_type, Debug symbol_debug_type, Visibility symbol_visibility) -{ - std::lock_guard<std::recursive_mutex> guard(m_mutex); +size_t Symtab::FindAllSymbolsMatchingRexExAndType( + const RegularExpression ®ex, SymbolType symbol_type, + Debug symbol_debug_type, Visibility symbol_visibility, + std::vector<uint32_t> &symbol_indexes) { + std::lock_guard<std::recursive_mutex> guard(m_mutex); - Timer scoped_timer (LLVM_PRETTY_FUNCTION, "%s", LLVM_PRETTY_FUNCTION); - if (!m_name_indexes_computed) - InitNameIndexes(); - - if (name) - { - std::vector<uint32_t> matching_indexes; - // The string table did have a string that matched, but we need - // to check the symbols and match the symbol_type if any was given. - if (AppendSymbolIndexesWithNameAndType (name, symbol_type, symbol_debug_type, symbol_visibility, matching_indexes)) - { - std::vector<uint32_t>::const_iterator pos, end = matching_indexes.end(); - for (pos = matching_indexes.begin(); pos != end; ++pos) - { - Symbol *symbol = SymbolAtIndex(*pos); - - if (symbol->Compare(name, symbol_type)) - return symbol; - } - } + AppendSymbolIndexesMatchingRegExAndType(regex, symbol_type, symbol_debug_type, + symbol_visibility, symbol_indexes); + return symbol_indexes.size(); +} + +Symbol *Symtab::FindFirstSymbolWithNameAndType(const ConstString &name, + SymbolType symbol_type, + Debug symbol_debug_type, + Visibility symbol_visibility) { + std::lock_guard<std::recursive_mutex> guard(m_mutex); + + Timer scoped_timer(LLVM_PRETTY_FUNCTION, "%s", LLVM_PRETTY_FUNCTION); + if (!m_name_indexes_computed) + InitNameIndexes(); + + if (name) { + std::vector<uint32_t> matching_indexes; + // The string table did have a string that matched, but we need + // to check the symbols and match the symbol_type if any was given. + if (AppendSymbolIndexesWithNameAndType(name, symbol_type, symbol_debug_type, + symbol_visibility, + matching_indexes)) { + std::vector<uint32_t>::const_iterator pos, end = matching_indexes.end(); + for (pos = matching_indexes.begin(); pos != end; ++pos) { + Symbol *symbol = SymbolAtIndex(*pos); + + if (symbol->Compare(name, symbol_type)) + return symbol; + } } - return nullptr; + } + return nullptr; } -typedef struct -{ - const Symtab *symtab; - const addr_t file_addr; - Symbol *match_symbol; - const uint32_t *match_index_ptr; - addr_t match_offset; +typedef struct { + const Symtab *symtab; + const addr_t file_addr; + Symbol *match_symbol; + const uint32_t *match_index_ptr; + addr_t match_offset; } SymbolSearchInfo; // Add all the section file start address & size to the RangeVector, -// recusively adding any children sections. -static void -AddSectionsToRangeMap (SectionList *sectlist, RangeVector<addr_t, addr_t> §ion_ranges) -{ - const int num_sections = sectlist->GetNumSections (0); - for (int i = 0; i < num_sections; i++) - { - SectionSP sect_sp = sectlist->GetSectionAtIndex (i); - if (sect_sp) - { - SectionList &child_sectlist = sect_sp->GetChildren(); - - // If this section has children, add the children to the RangeVector. - // Else add this section to the RangeVector. - if (child_sectlist.GetNumSections (0) > 0) - { - AddSectionsToRangeMap (&child_sectlist, section_ranges); - } - else - { - size_t size = sect_sp->GetByteSize(); - if (size > 0) - { - addr_t base_addr = sect_sp->GetFileAddress(); - RangeVector<addr_t, addr_t>::Entry entry; - entry.SetRangeBase (base_addr); - entry.SetByteSize (size); - section_ranges.Append (entry); - } - } +// recusively adding any children sections. +static void AddSectionsToRangeMap(SectionList *sectlist, + RangeVector<addr_t, addr_t> §ion_ranges) { + const int num_sections = sectlist->GetNumSections(0); + for (int i = 0; i < num_sections; i++) { + SectionSP sect_sp = sectlist->GetSectionAtIndex(i); + if (sect_sp) { + SectionList &child_sectlist = sect_sp->GetChildren(); + + // If this section has children, add the children to the RangeVector. + // Else add this section to the RangeVector. + if (child_sectlist.GetNumSections(0) > 0) { + AddSectionsToRangeMap(&child_sectlist, section_ranges); + } else { + size_t size = sect_sp->GetByteSize(); + if (size > 0) { + addr_t base_addr = sect_sp->GetFileAddress(); + RangeVector<addr_t, addr_t>::Entry entry; + entry.SetRangeBase(base_addr); + entry.SetByteSize(size); + section_ranges.Append(entry); } + } } + } } -void -Symtab::InitAddressIndexes() -{ - // Protected function, no need to lock mutex... - if (!m_file_addr_to_index_computed && !m_symbols.empty()) - { - m_file_addr_to_index_computed = true; - - FileRangeToIndexMap::Entry entry; - const_iterator begin = m_symbols.begin(); - const_iterator end = m_symbols.end(); - for (const_iterator pos = m_symbols.begin(); pos != end; ++pos) - { - if (pos->ValueIsAddress()) - { - entry.SetRangeBase(pos->GetAddressRef().GetFileAddress()); - entry.SetByteSize(pos->GetByteSize()); - entry.data = std::distance(begin, pos); - m_file_addr_to_index.Append(entry); +void Symtab::InitAddressIndexes() { + // Protected function, no need to lock mutex... + if (!m_file_addr_to_index_computed && !m_symbols.empty()) { + m_file_addr_to_index_computed = true; + + FileRangeToIndexMap::Entry entry; + const_iterator begin = m_symbols.begin(); + const_iterator end = m_symbols.end(); + for (const_iterator pos = m_symbols.begin(); pos != end; ++pos) { + if (pos->ValueIsAddress()) { + entry.SetRangeBase(pos->GetAddressRef().GetFileAddress()); + entry.SetByteSize(pos->GetByteSize()); + entry.data = std::distance(begin, pos); + m_file_addr_to_index.Append(entry); + } + } + const size_t num_entries = m_file_addr_to_index.GetSize(); + if (num_entries > 0) { + m_file_addr_to_index.Sort(); + + // Create a RangeVector with the start & size of all the sections for + // this objfile. We'll need to check this for any FileRangeToIndexMap + // entries with an uninitialized size, which could potentially be a + // large number so reconstituting the weak pointer is busywork when it + // is invariant information. + SectionList *sectlist = m_objfile->GetSectionList(); + RangeVector<addr_t, addr_t> section_ranges; + if (sectlist) { + AddSectionsToRangeMap(sectlist, section_ranges); + section_ranges.Sort(); + } + + // Iterate through the FileRangeToIndexMap and fill in the size for any + // entries that didn't already have a size from the Symbol (e.g. if we + // have a plain linker symbol with an address only, instead of debug info + // where we get an address and a size and a type, etc.) + for (size_t i = 0; i < num_entries; i++) { + FileRangeToIndexMap::Entry *entry = + m_file_addr_to_index.GetMutableEntryAtIndex(i); + if (entry->GetByteSize() == 0) { + addr_t curr_base_addr = entry->GetRangeBase(); + const RangeVector<addr_t, addr_t>::Entry *containing_section = + section_ranges.FindEntryThatContains(curr_base_addr); + + // Use the end of the section as the default max size of the symbol + addr_t sym_size = 0; + if (containing_section) { + sym_size = + containing_section->GetByteSize() - + (entry->GetRangeBase() - containing_section->GetRangeBase()); + } + + for (size_t j = i; j < num_entries; j++) { + FileRangeToIndexMap::Entry *next_entry = + m_file_addr_to_index.GetMutableEntryAtIndex(j); + addr_t next_base_addr = next_entry->GetRangeBase(); + if (next_base_addr > curr_base_addr) { + addr_t size_to_next_symbol = next_base_addr - curr_base_addr; + + // Take the difference between this symbol and the next one as its + // size, + // if it is less than the size of the section. + if (sym_size == 0 || size_to_next_symbol < sym_size) { + sym_size = size_to_next_symbol; + } + break; } + } + + if (sym_size > 0) { + entry->SetByteSize(sym_size); + Symbol &symbol = m_symbols[entry->data]; + symbol.SetByteSize(sym_size); + symbol.SetSizeIsSynthesized(true); + } } - const size_t num_entries = m_file_addr_to_index.GetSize(); - if (num_entries > 0) - { - m_file_addr_to_index.Sort(); - - // Create a RangeVector with the start & size of all the sections for - // this objfile. We'll need to check this for any FileRangeToIndexMap - // entries with an uninitialized size, which could potentially be a - // large number so reconstituting the weak pointer is busywork when it - // is invariant information. - SectionList *sectlist = m_objfile->GetSectionList(); - RangeVector<addr_t, addr_t> section_ranges; - if (sectlist) - { - AddSectionsToRangeMap (sectlist, section_ranges); - section_ranges.Sort(); - } + } - // Iterate through the FileRangeToIndexMap and fill in the size for any - // entries that didn't already have a size from the Symbol (e.g. if we - // have a plain linker symbol with an address only, instead of debug info - // where we get an address and a size and a type, etc.) - for (size_t i = 0; i < num_entries; i++) - { - FileRangeToIndexMap::Entry *entry = m_file_addr_to_index.GetMutableEntryAtIndex (i); - if (entry->GetByteSize() == 0) - { - addr_t curr_base_addr = entry->GetRangeBase(); - const RangeVector<addr_t, addr_t>::Entry *containing_section = - section_ranges.FindEntryThatContains (curr_base_addr); - - // Use the end of the section as the default max size of the symbol - addr_t sym_size = 0; - if (containing_section) - { - sym_size = containing_section->GetByteSize() - - (entry->GetRangeBase() - containing_section->GetRangeBase()); - } - - for (size_t j = i; j < num_entries; j++) - { - FileRangeToIndexMap::Entry *next_entry = m_file_addr_to_index.GetMutableEntryAtIndex (j); - addr_t next_base_addr = next_entry->GetRangeBase(); - if (next_base_addr > curr_base_addr) - { - addr_t size_to_next_symbol = next_base_addr - curr_base_addr; - - // Take the difference between this symbol and the next one as its size, - // if it is less than the size of the section. - if (sym_size == 0 || size_to_next_symbol < sym_size) - { - sym_size = size_to_next_symbol; - } - break; - } - } - - if (sym_size > 0) - { - entry->SetByteSize (sym_size); - Symbol &symbol = m_symbols[entry->data]; - symbol.SetByteSize (sym_size); - symbol.SetSizeIsSynthesized (true); - } - } - } - - // Sort again in case the range size changes the ordering - m_file_addr_to_index.Sort(); - } + // Sort again in case the range size changes the ordering + m_file_addr_to_index.Sort(); } + } } -void -Symtab::CalculateSymbolSizes () -{ - std::lock_guard<std::recursive_mutex> guard(m_mutex); - - if (!m_symbols.empty()) - { - if (!m_file_addr_to_index_computed) - InitAddressIndexes(); - - const size_t num_entries = m_file_addr_to_index.GetSize(); - - for (size_t i = 0; i < num_entries; ++i) - { - // The entries in the m_file_addr_to_index have calculated the sizes already - // so we will use this size if we need to. - const FileRangeToIndexMap::Entry &entry = m_file_addr_to_index.GetEntryRef(i); - - Symbol &symbol = m_symbols[entry.data]; - - // If the symbol size is already valid, no need to do anything - if (symbol.GetByteSizeIsValid()) - continue; - - const addr_t range_size = entry.GetByteSize(); - if (range_size > 0) - { - symbol.SetByteSize(range_size); - symbol.SetSizeIsSynthesized(true); - } - } - } -} +void Symtab::CalculateSymbolSizes() { + std::lock_guard<std::recursive_mutex> guard(m_mutex); -Symbol * -Symtab::FindSymbolAtFileAddress (addr_t file_addr) -{ - std::lock_guard<std::recursive_mutex> guard(m_mutex); + if (!m_symbols.empty()) { if (!m_file_addr_to_index_computed) - InitAddressIndexes(); + InitAddressIndexes(); + + const size_t num_entries = m_file_addr_to_index.GetSize(); + + for (size_t i = 0; i < num_entries; ++i) { + // The entries in the m_file_addr_to_index have calculated the sizes + // already + // so we will use this size if we need to. + const FileRangeToIndexMap::Entry &entry = + m_file_addr_to_index.GetEntryRef(i); - const FileRangeToIndexMap::Entry *entry = m_file_addr_to_index.FindEntryStartsAt(file_addr); - if (entry) - { - Symbol* symbol = SymbolAtIndex(entry->data); - if (symbol->GetFileAddress() == file_addr) - return symbol; + Symbol &symbol = m_symbols[entry.data]; + + // If the symbol size is already valid, no need to do anything + if (symbol.GetByteSizeIsValid()) + continue; + + const addr_t range_size = entry.GetByteSize(); + if (range_size > 0) { + symbol.SetByteSize(range_size); + symbol.SetSizeIsSynthesized(true); + } } - return nullptr; + } } -Symbol * -Symtab::FindSymbolContainingFileAddress (addr_t file_addr) -{ - std::lock_guard<std::recursive_mutex> guard(m_mutex); +Symbol *Symtab::FindSymbolAtFileAddress(addr_t file_addr) { + std::lock_guard<std::recursive_mutex> guard(m_mutex); + if (!m_file_addr_to_index_computed) + InitAddressIndexes(); + + const FileRangeToIndexMap::Entry *entry = + m_file_addr_to_index.FindEntryStartsAt(file_addr); + if (entry) { + Symbol *symbol = SymbolAtIndex(entry->data); + if (symbol->GetFileAddress() == file_addr) + return symbol; + } + return nullptr; +} - if (!m_file_addr_to_index_computed) - InitAddressIndexes(); +Symbol *Symtab::FindSymbolContainingFileAddress(addr_t file_addr) { + std::lock_guard<std::recursive_mutex> guard(m_mutex); - const FileRangeToIndexMap::Entry *entry = m_file_addr_to_index.FindEntryThatContains(file_addr); - if (entry) - { - Symbol* symbol = SymbolAtIndex(entry->data); - if (symbol->ContainsFileAddress(file_addr)) - return symbol; - } - return nullptr; + if (!m_file_addr_to_index_computed) + InitAddressIndexes(); + + const FileRangeToIndexMap::Entry *entry = + m_file_addr_to_index.FindEntryThatContains(file_addr); + if (entry) { + Symbol *symbol = SymbolAtIndex(entry->data); + if (symbol->ContainsFileAddress(file_addr)) + return symbol; + } + return nullptr; } -void -Symtab::ForEachSymbolContainingFileAddress(addr_t file_addr, std::function<bool(Symbol *)> const &callback) -{ - std::lock_guard<std::recursive_mutex> guard(m_mutex); +void Symtab::ForEachSymbolContainingFileAddress( + addr_t file_addr, std::function<bool(Symbol *)> const &callback) { + std::lock_guard<std::recursive_mutex> guard(m_mutex); - if (!m_file_addr_to_index_computed) - InitAddressIndexes(); + if (!m_file_addr_to_index_computed) + InitAddressIndexes(); - std::vector<uint32_t> all_addr_indexes; + std::vector<uint32_t> all_addr_indexes; - // Get all symbols with file_addr - const size_t addr_match_count = m_file_addr_to_index.FindEntryIndexesThatContain(file_addr, all_addr_indexes); + // Get all symbols with file_addr + const size_t addr_match_count = + m_file_addr_to_index.FindEntryIndexesThatContain(file_addr, + all_addr_indexes); - for (size_t i = 0; i < addr_match_count; ++i) - { - Symbol* symbol = SymbolAtIndex(all_addr_indexes[i]); - if (symbol->ContainsFileAddress(file_addr)) - { - if (!callback(symbol)) - break; - } + for (size_t i = 0; i < addr_match_count; ++i) { + Symbol *symbol = SymbolAtIndex(all_addr_indexes[i]); + if (symbol->ContainsFileAddress(file_addr)) { + if (!callback(symbol)) + break; } + } } -void -Symtab::SymbolIndicesToSymbolContextList (std::vector<uint32_t> &symbol_indexes, SymbolContextList &sc_list) -{ - // No need to protect this call using m_mutex all other method calls are - // already thread safe. - - const bool merge_symbol_into_function = true; - size_t num_indices = symbol_indexes.size(); - if (num_indices > 0) - { - SymbolContext sc; - sc.module_sp = m_objfile->GetModule(); - for (size_t i = 0; i < num_indices; i++) - { - sc.symbol = SymbolAtIndex (symbol_indexes[i]); - if (sc.symbol) - sc_list.AppendIfUnique(sc, merge_symbol_into_function); - } +void Symtab::SymbolIndicesToSymbolContextList( + std::vector<uint32_t> &symbol_indexes, SymbolContextList &sc_list) { + // No need to protect this call using m_mutex all other method calls are + // already thread safe. + + const bool merge_symbol_into_function = true; + size_t num_indices = symbol_indexes.size(); + if (num_indices > 0) { + SymbolContext sc; + sc.module_sp = m_objfile->GetModule(); + for (size_t i = 0; i < num_indices; i++) { + sc.symbol = SymbolAtIndex(symbol_indexes[i]); + if (sc.symbol) + sc_list.AppendIfUnique(sc, merge_symbol_into_function); } + } } - -size_t -Symtab::FindFunctionSymbols (const ConstString &name, - uint32_t name_type_mask, - SymbolContextList& sc_list) -{ - size_t count = 0; - std::vector<uint32_t> symbol_indexes; - - const char *name_cstr = name.GetCString(); - - // eFunctionNameTypeAuto should be pre-resolved by a call to Module::PrepareForFunctionNameLookup() - assert ((name_type_mask & eFunctionNameTypeAuto) == 0); - - if (name_type_mask & (eFunctionNameTypeBase | eFunctionNameTypeFull)) - { - std::vector<uint32_t> temp_symbol_indexes; - FindAllSymbolsWithNameAndType (name, eSymbolTypeAny, temp_symbol_indexes); - - unsigned temp_symbol_indexes_size = temp_symbol_indexes.size(); - if (temp_symbol_indexes_size > 0) - { - std::lock_guard<std::recursive_mutex> guard(m_mutex); - for (unsigned i = 0; i < temp_symbol_indexes_size; i++) - { - SymbolContext sym_ctx; - sym_ctx.symbol = SymbolAtIndex (temp_symbol_indexes[i]); - if (sym_ctx.symbol) - { - switch (sym_ctx.symbol->GetType()) - { - case eSymbolTypeCode: - case eSymbolTypeResolver: - case eSymbolTypeReExported: - symbol_indexes.push_back(temp_symbol_indexes[i]); - break; - default: - break; - } - } - } - } - } - - if (name_type_mask & eFunctionNameTypeBase) - { - // From mangled names we can't tell what is a basename and what - // is a method name, so we just treat them the same - if (!m_name_indexes_computed) - InitNameIndexes(); - - if (!m_basename_to_index.IsEmpty()) - { - const UniqueCStringMap<uint32_t>::Entry *match; - for (match = m_basename_to_index.FindFirstValueForName(name_cstr); - match != nullptr; - match = m_basename_to_index.FindNextValueForName(match)) - { - symbol_indexes.push_back(match->value); - } - } - } - - if (name_type_mask & eFunctionNameTypeMethod) - { - if (!m_name_indexes_computed) - InitNameIndexes(); - - if (!m_method_to_index.IsEmpty()) - { - const UniqueCStringMap<uint32_t>::Entry *match; - for (match = m_method_to_index.FindFirstValueForName(name_cstr); - match != nullptr; - match = m_method_to_index.FindNextValueForName(match)) - { - symbol_indexes.push_back(match->value); - } +size_t Symtab::FindFunctionSymbols(const ConstString &name, + uint32_t name_type_mask, + SymbolContextList &sc_list) { + size_t count = 0; + std::vector<uint32_t> symbol_indexes; + + const char *name_cstr = name.GetCString(); + + // eFunctionNameTypeAuto should be pre-resolved by a call to + // Module::PrepareForFunctionNameLookup() + assert((name_type_mask & eFunctionNameTypeAuto) == 0); + + if (name_type_mask & (eFunctionNameTypeBase | eFunctionNameTypeFull)) { + std::vector<uint32_t> temp_symbol_indexes; + FindAllSymbolsWithNameAndType(name, eSymbolTypeAny, temp_symbol_indexes); + + unsigned temp_symbol_indexes_size = temp_symbol_indexes.size(); + if (temp_symbol_indexes_size > 0) { + std::lock_guard<std::recursive_mutex> guard(m_mutex); + for (unsigned i = 0; i < temp_symbol_indexes_size; i++) { + SymbolContext sym_ctx; + sym_ctx.symbol = SymbolAtIndex(temp_symbol_indexes[i]); + if (sym_ctx.symbol) { + switch (sym_ctx.symbol->GetType()) { + case eSymbolTypeCode: + case eSymbolTypeResolver: + case eSymbolTypeReExported: + symbol_indexes.push_back(temp_symbol_indexes[i]); + break; + default: + break; + } } + } } + } - if (name_type_mask & eFunctionNameTypeSelector) - { - if (!m_name_indexes_computed) - InitNameIndexes(); - - if (!m_selector_to_index.IsEmpty()) - { - const UniqueCStringMap<uint32_t>::Entry *match; - for (match = m_selector_to_index.FindFirstValueForName(name_cstr); - match != nullptr; - match = m_selector_to_index.FindNextValueForName(match)) - { - symbol_indexes.push_back(match->value); - } - } + if (name_type_mask & eFunctionNameTypeBase) { + // From mangled names we can't tell what is a basename and what + // is a method name, so we just treat them the same + if (!m_name_indexes_computed) + InitNameIndexes(); + + if (!m_basename_to_index.IsEmpty()) { + const UniqueCStringMap<uint32_t>::Entry *match; + for (match = m_basename_to_index.FindFirstValueForName(name_cstr); + match != nullptr; + match = m_basename_to_index.FindNextValueForName(match)) { + symbol_indexes.push_back(match->value); + } } + } - if (!symbol_indexes.empty()) - { - std::sort(symbol_indexes.begin(), symbol_indexes.end()); - symbol_indexes.erase(std::unique(symbol_indexes.begin(), symbol_indexes.end()), symbol_indexes.end()); - count = symbol_indexes.size(); - SymbolIndicesToSymbolContextList (symbol_indexes, sc_list); + if (name_type_mask & eFunctionNameTypeMethod) { + if (!m_name_indexes_computed) + InitNameIndexes(); + + if (!m_method_to_index.IsEmpty()) { + const UniqueCStringMap<uint32_t>::Entry *match; + for (match = m_method_to_index.FindFirstValueForName(name_cstr); + match != nullptr; + match = m_method_to_index.FindNextValueForName(match)) { + symbol_indexes.push_back(match->value); + } } + } - return count; + if (name_type_mask & eFunctionNameTypeSelector) { + if (!m_name_indexes_computed) + InitNameIndexes(); + + if (!m_selector_to_index.IsEmpty()) { + const UniqueCStringMap<uint32_t>::Entry *match; + for (match = m_selector_to_index.FindFirstValueForName(name_cstr); + match != nullptr; + match = m_selector_to_index.FindNextValueForName(match)) { + symbol_indexes.push_back(match->value); + } + } + } + + if (!symbol_indexes.empty()) { + std::sort(symbol_indexes.begin(), symbol_indexes.end()); + symbol_indexes.erase( + std::unique(symbol_indexes.begin(), symbol_indexes.end()), + symbol_indexes.end()); + count = symbol_indexes.size(); + SymbolIndicesToSymbolContextList(symbol_indexes, sc_list); + } + + return count; } - -const Symbol * -Symtab::GetParent (Symbol *child_symbol) const -{ - uint32_t child_idx = GetIndexForSymbol(child_symbol); - if (child_idx != UINT32_MAX && child_idx > 0) - { - for (uint32_t idx = child_idx - 1; idx != UINT32_MAX; --idx) - { - const Symbol *symbol = SymbolAtIndex (idx); - const uint32_t sibling_idx = symbol->GetSiblingIndex(); - if (sibling_idx != UINT32_MAX && sibling_idx > child_idx) - return symbol; - } +const Symbol *Symtab::GetParent(Symbol *child_symbol) const { + uint32_t child_idx = GetIndexForSymbol(child_symbol); + if (child_idx != UINT32_MAX && child_idx > 0) { + for (uint32_t idx = child_idx - 1; idx != UINT32_MAX; --idx) { + const Symbol *symbol = SymbolAtIndex(idx); + const uint32_t sibling_idx = symbol->GetSiblingIndex(); + if (sibling_idx != UINT32_MAX && sibling_idx > child_idx) + return symbol; } - return NULL; + } + return NULL; } diff --git a/lldb/source/Symbol/Type.cpp b/lldb/source/Symbol/Type.cpp index 8b51d99ece3..2374a6d2b20 100644 --- a/lldb/source/Symbol/Type.cpp +++ b/lldb/source/Symbol/Type.cpp @@ -13,8 +13,8 @@ // C++ Includes // Other libraries and framework includes // Project includes -#include "lldb/Core/DataExtractor.h" #include "lldb/Core/DataBufferHeap.h" +#include "lldb/Core/DataExtractor.h" #include "lldb/Core/Module.h" #include "lldb/Core/Scalar.h" #include "lldb/Core/StreamString.h" @@ -40,1339 +40,1076 @@ using namespace lldb; using namespace lldb_private; -void -CompilerContext::Dump() const -{ - switch (type) - { - case CompilerContextKind::Invalid: printf("Invalid"); break; - case CompilerContextKind::TranslationUnit: printf("TranslationUnit"); break; - case CompilerContextKind::Module: printf("Module"); break; - case CompilerContextKind::Namespace: printf("Namespace"); break; - case CompilerContextKind::Class: printf("Class"); break; - case CompilerContextKind::Structure: printf("Structure"); break; - case CompilerContextKind::Union: printf("Union"); break; - case CompilerContextKind::Function: printf("Function"); break; - case CompilerContextKind::Variable: printf("Variable"); break; - case CompilerContextKind::Enumeration: printf("Enumeration"); break; - case CompilerContextKind::Typedef: printf("Typedef"); break; - } - printf("(\"%s\")\n", name.GetCString()); -} - -class TypeAppendVisitor -{ +void CompilerContext::Dump() const { + switch (type) { + case CompilerContextKind::Invalid: + printf("Invalid"); + break; + case CompilerContextKind::TranslationUnit: + printf("TranslationUnit"); + break; + case CompilerContextKind::Module: + printf("Module"); + break; + case CompilerContextKind::Namespace: + printf("Namespace"); + break; + case CompilerContextKind::Class: + printf("Class"); + break; + case CompilerContextKind::Structure: + printf("Structure"); + break; + case CompilerContextKind::Union: + printf("Union"); + break; + case CompilerContextKind::Function: + printf("Function"); + break; + case CompilerContextKind::Variable: + printf("Variable"); + break; + case CompilerContextKind::Enumeration: + printf("Enumeration"); + break; + case CompilerContextKind::Typedef: + printf("Typedef"); + break; + } + printf("(\"%s\")\n", name.GetCString()); +} + +class TypeAppendVisitor { public: - TypeAppendVisitor(TypeListImpl &type_list) : - m_type_list(type_list) - { - } - - bool - operator() (const lldb::TypeSP& type) - { - m_type_list.Append(TypeImplSP(new TypeImpl(type))); - return true; - } - -private: - TypeListImpl &m_type_list; -}; - -void -TypeListImpl::Append (const lldb_private::TypeList &type_list) -{ - TypeAppendVisitor cb(*this); - type_list.ForEach(cb); -} + TypeAppendVisitor(TypeListImpl &type_list) : m_type_list(type_list) {} -SymbolFileType::SymbolFileType (SymbolFile &symbol_file, const lldb::TypeSP &type_sp) : - UserID (type_sp ? type_sp->GetID() : LLDB_INVALID_UID), - m_symbol_file (symbol_file), - m_type_sp (type_sp) -{ -} + bool operator()(const lldb::TypeSP &type) { + m_type_list.Append(TypeImplSP(new TypeImpl(type))); + return true; + } +private: + TypeListImpl &m_type_list; +}; -Type * -SymbolFileType::GetType () -{ - if (!m_type_sp) - { - Type *resolved_type = m_symbol_file.ResolveTypeUID (GetID()); - if (resolved_type) - m_type_sp = resolved_type->shared_from_this(); +void TypeListImpl::Append(const lldb_private::TypeList &type_list) { + TypeAppendVisitor cb(*this); + type_list.ForEach(cb); +} + +SymbolFileType::SymbolFileType(SymbolFile &symbol_file, + const lldb::TypeSP &type_sp) + : UserID(type_sp ? type_sp->GetID() : LLDB_INVALID_UID), + m_symbol_file(symbol_file), m_type_sp(type_sp) {} + +Type *SymbolFileType::GetType() { + if (!m_type_sp) { + Type *resolved_type = m_symbol_file.ResolveTypeUID(GetID()); + if (resolved_type) + m_type_sp = resolved_type->shared_from_this(); + } + return m_type_sp.get(); +} + +Type::Type(lldb::user_id_t uid, SymbolFile *symbol_file, + const ConstString &name, uint64_t byte_size, + SymbolContextScope *context, user_id_t encoding_uid, + EncodingDataType encoding_uid_type, const Declaration &decl, + const CompilerType &compiler_type, + ResolveState compiler_type_resolve_state) + : std::enable_shared_from_this<Type>(), UserID(uid), m_name(name), + m_symbol_file(symbol_file), m_context(context), m_encoding_type(nullptr), + m_encoding_uid(encoding_uid), m_encoding_uid_type(encoding_uid_type), + m_byte_size(byte_size), m_decl(decl), m_compiler_type(compiler_type) { + m_flags.compiler_type_resolve_state = + (compiler_type ? compiler_type_resolve_state : eResolveStateUnresolved); + m_flags.is_complete_objc_class = false; +} + +Type::Type() + : std::enable_shared_from_this<Type>(), UserID(0), m_name("<INVALID TYPE>"), + m_symbol_file(nullptr), m_context(nullptr), m_encoding_type(nullptr), + m_encoding_uid(LLDB_INVALID_UID), m_encoding_uid_type(eEncodingInvalid), + m_byte_size(0), m_decl(), m_compiler_type() { + m_flags.compiler_type_resolve_state = eResolveStateUnresolved; + m_flags.is_complete_objc_class = false; +} + +Type::Type(const Type &rhs) + : std::enable_shared_from_this<Type>(rhs), UserID(rhs), m_name(rhs.m_name), + m_symbol_file(rhs.m_symbol_file), m_context(rhs.m_context), + m_encoding_type(rhs.m_encoding_type), m_encoding_uid(rhs.m_encoding_uid), + m_encoding_uid_type(rhs.m_encoding_uid_type), + m_byte_size(rhs.m_byte_size), m_decl(rhs.m_decl), + m_compiler_type(rhs.m_compiler_type), m_flags(rhs.m_flags) {} + +const Type &Type::operator=(const Type &rhs) { + if (this != &rhs) { + } + return *this; +} + +void Type::GetDescription(Stream *s, lldb::DescriptionLevel level, + bool show_name) { + *s << "id = " << (const UserID &)*this; + + // Call the name accessor to make sure we resolve the type name + if (show_name) { + const ConstString &type_name = GetName(); + if (type_name) { + *s << ", name = \"" << type_name << '"'; + ConstString qualified_type_name(GetQualifiedName()); + if (qualified_type_name != type_name) { + *s << ", qualified = \"" << qualified_type_name << '"'; + } } - return m_type_sp.get(); -} - - -Type::Type -( - lldb::user_id_t uid, - SymbolFile* symbol_file, - const ConstString &name, - uint64_t byte_size, - SymbolContextScope *context, - user_id_t encoding_uid, - EncodingDataType encoding_uid_type, - const Declaration& decl, - const CompilerType &compiler_type, - ResolveState compiler_type_resolve_state -) : - std::enable_shared_from_this<Type> (), - UserID (uid), - m_name (name), - m_symbol_file (symbol_file), - m_context (context), - m_encoding_type (nullptr), - m_encoding_uid (encoding_uid), - m_encoding_uid_type (encoding_uid_type), - m_byte_size (byte_size), - m_decl (decl), - m_compiler_type (compiler_type) -{ - m_flags.compiler_type_resolve_state = (compiler_type ? compiler_type_resolve_state : eResolveStateUnresolved); - m_flags.is_complete_objc_class = false; -} - -Type::Type () : - std::enable_shared_from_this<Type> (), - UserID (0), - m_name ("<INVALID TYPE>"), - m_symbol_file (nullptr), - m_context (nullptr), - m_encoding_type (nullptr), - m_encoding_uid (LLDB_INVALID_UID), - m_encoding_uid_type (eEncodingInvalid), - m_byte_size (0), - m_decl (), - m_compiler_type () -{ - m_flags.compiler_type_resolve_state = eResolveStateUnresolved; - m_flags.is_complete_objc_class = false; -} - - -Type::Type (const Type &rhs) : - std::enable_shared_from_this<Type> (rhs), - UserID (rhs), - m_name (rhs.m_name), - m_symbol_file (rhs.m_symbol_file), - m_context (rhs.m_context), - m_encoding_type (rhs.m_encoding_type), - m_encoding_uid (rhs.m_encoding_uid), - m_encoding_uid_type (rhs.m_encoding_uid_type), - m_byte_size (rhs.m_byte_size), - m_decl (rhs.m_decl), - m_compiler_type (rhs.m_compiler_type), - m_flags (rhs.m_flags) -{ -} - -const Type& -Type::operator= (const Type& rhs) -{ - if (this != &rhs) - { + } + + // Call the get byte size accesor so we resolve our byte size + if (GetByteSize()) + s->Printf(", byte-size = %" PRIu64, m_byte_size); + bool show_fullpaths = (level == lldb::eDescriptionLevelVerbose); + m_decl.Dump(s, show_fullpaths); + + if (m_compiler_type.IsValid()) { + *s << ", compiler_type = \""; + GetForwardCompilerType().DumpTypeDescription(s); + *s << '"'; + } else if (m_encoding_uid != LLDB_INVALID_UID) { + s->Printf(", type_uid = 0x%8.8" PRIx64, m_encoding_uid); + switch (m_encoding_uid_type) { + case eEncodingInvalid: + break; + case eEncodingIsUID: + s->PutCString(" (unresolved type)"); + break; + case eEncodingIsConstUID: + s->PutCString(" (unresolved const type)"); + break; + case eEncodingIsRestrictUID: + s->PutCString(" (unresolved restrict type)"); + break; + case eEncodingIsVolatileUID: + s->PutCString(" (unresolved volatile type)"); + break; + case eEncodingIsTypedefUID: + s->PutCString(" (unresolved typedef)"); + break; + case eEncodingIsPointerUID: + s->PutCString(" (unresolved pointer)"); + break; + case eEncodingIsLValueReferenceUID: + s->PutCString(" (unresolved L value reference)"); + break; + case eEncodingIsRValueReferenceUID: + s->PutCString(" (unresolved R value reference)"); + break; + case eEncodingIsSyntheticUID: + s->PutCString(" (synthetic type)"); + break; } - return *this; -} - - -void -Type::GetDescription (Stream *s, lldb::DescriptionLevel level, bool show_name) -{ - *s << "id = " << (const UserID&)*this; - - // Call the name accessor to make sure we resolve the type name - if (show_name) - { - const ConstString &type_name = GetName(); - if (type_name) - { - *s << ", name = \"" << type_name << '"'; - ConstString qualified_type_name (GetQualifiedName()); - if (qualified_type_name != type_name) - { - *s << ", qualified = \"" << qualified_type_name << '"'; - } - } + } +} + +void Type::Dump(Stream *s, bool show_context) { + s->Printf("%p: ", static_cast<void *>(this)); + s->Indent(); + *s << "Type" << static_cast<const UserID &>(*this) << ' '; + if (m_name) + *s << ", name = \"" << m_name << "\""; + + if (m_byte_size != 0) + s->Printf(", size = %" PRIu64, m_byte_size); + + if (show_context && m_context != nullptr) { + s->PutCString(", context = ( "); + m_context->DumpSymbolContext(s); + s->PutCString(" )"); + } + + bool show_fullpaths = false; + m_decl.Dump(s, show_fullpaths); + + if (m_compiler_type.IsValid()) { + *s << ", compiler_type = " << m_compiler_type.GetOpaqueQualType() << ' '; + GetForwardCompilerType().DumpTypeDescription(s); + } else if (m_encoding_uid != LLDB_INVALID_UID) { + *s << ", type_data = " << (uint64_t)m_encoding_uid; + switch (m_encoding_uid_type) { + case eEncodingInvalid: + break; + case eEncodingIsUID: + s->PutCString(" (unresolved type)"); + break; + case eEncodingIsConstUID: + s->PutCString(" (unresolved const type)"); + break; + case eEncodingIsRestrictUID: + s->PutCString(" (unresolved restrict type)"); + break; + case eEncodingIsVolatileUID: + s->PutCString(" (unresolved volatile type)"); + break; + case eEncodingIsTypedefUID: + s->PutCString(" (unresolved typedef)"); + break; + case eEncodingIsPointerUID: + s->PutCString(" (unresolved pointer)"); + break; + case eEncodingIsLValueReferenceUID: + s->PutCString(" (unresolved L value reference)"); + break; + case eEncodingIsRValueReferenceUID: + s->PutCString(" (unresolved R value reference)"); + break; + case eEncodingIsSyntheticUID: + s->PutCString(" (synthetic type)"); + break; } + } - // Call the get byte size accesor so we resolve our byte size - if (GetByteSize()) - s->Printf(", byte-size = %" PRIu64, m_byte_size); - bool show_fullpaths = (level == lldb::eDescriptionLevelVerbose); - m_decl.Dump(s, show_fullpaths); - - if (m_compiler_type.IsValid()) - { - *s << ", compiler_type = \""; - GetForwardCompilerType ().DumpTypeDescription(s); - *s << '"'; - } - else if (m_encoding_uid != LLDB_INVALID_UID) - { - s->Printf(", type_uid = 0x%8.8" PRIx64, m_encoding_uid); - switch (m_encoding_uid_type) - { - case eEncodingInvalid: break; - case eEncodingIsUID: s->PutCString(" (unresolved type)"); break; - case eEncodingIsConstUID: s->PutCString(" (unresolved const type)"); break; - case eEncodingIsRestrictUID: s->PutCString(" (unresolved restrict type)"); break; - case eEncodingIsVolatileUID: s->PutCString(" (unresolved volatile type)"); break; - case eEncodingIsTypedefUID: s->PutCString(" (unresolved typedef)"); break; - case eEncodingIsPointerUID: s->PutCString(" (unresolved pointer)"); break; - case eEncodingIsLValueReferenceUID: s->PutCString(" (unresolved L value reference)"); break; - case eEncodingIsRValueReferenceUID: s->PutCString(" (unresolved R value reference)"); break; - case eEncodingIsSyntheticUID: s->PutCString(" (synthetic type)"); break; - } - } + // + // if (m_access) + // s->Printf(", access = %u", m_access); + s->EOL(); } +const ConstString &Type::GetName() { + if (!m_name) + m_name = GetForwardCompilerType().GetConstTypeName(); + return m_name; +} -void -Type::Dump (Stream *s, bool show_context) -{ - s->Printf("%p: ", static_cast<void*>(this)); - s->Indent(); - *s << "Type" << static_cast<const UserID&>(*this) << ' '; - if (m_name) - *s << ", name = \"" << m_name << "\""; - - if (m_byte_size != 0) - s->Printf(", size = %" PRIu64, m_byte_size); +void Type::DumpTypeName(Stream *s) { GetName().Dump(s, "<invalid-type-name>"); } - if (show_context && m_context != nullptr) - { - s->PutCString(", context = ( "); - m_context->DumpSymbolContext(s); - s->PutCString(" )"); +void Type::DumpValue(ExecutionContext *exe_ctx, Stream *s, + const DataExtractor &data, uint32_t data_byte_offset, + bool show_types, bool show_summary, bool verbose, + lldb::Format format) { + if (ResolveClangType(eResolveStateForward)) { + if (show_types) { + s->PutChar('('); + if (verbose) + s->Printf("Type{0x%8.8" PRIx64 "} ", GetID()); + DumpTypeName(s); + s->PutCString(") "); } - bool show_fullpaths = false; - m_decl.Dump (s,show_fullpaths); - - if (m_compiler_type.IsValid()) - { - *s << ", compiler_type = " << m_compiler_type.GetOpaqueQualType() << ' '; - GetForwardCompilerType ().DumpTypeDescription (s); - } - else if (m_encoding_uid != LLDB_INVALID_UID) - { - *s << ", type_data = " << (uint64_t)m_encoding_uid; - switch (m_encoding_uid_type) - { - case eEncodingInvalid: break; - case eEncodingIsUID: s->PutCString(" (unresolved type)"); break; - case eEncodingIsConstUID: s->PutCString(" (unresolved const type)"); break; - case eEncodingIsRestrictUID: s->PutCString(" (unresolved restrict type)"); break; - case eEncodingIsVolatileUID: s->PutCString(" (unresolved volatile type)"); break; - case eEncodingIsTypedefUID: s->PutCString(" (unresolved typedef)"); break; - case eEncodingIsPointerUID: s->PutCString(" (unresolved pointer)"); break; - case eEncodingIsLValueReferenceUID: s->PutCString(" (unresolved L value reference)"); break; - case eEncodingIsRValueReferenceUID: s->PutCString(" (unresolved R value reference)"); break; - case eEncodingIsSyntheticUID: s->PutCString(" (synthetic type)"); break; - } - } - -// -// if (m_access) -// s->Printf(", access = %u", m_access); - s->EOL(); -} - -const ConstString & -Type::GetName() -{ - if (!m_name) - m_name = GetForwardCompilerType ().GetConstTypeName(); - return m_name; -} - -void -Type::DumpTypeName(Stream *s) -{ - GetName().Dump(s, "<invalid-type-name>"); -} - - -void -Type::DumpValue -( - ExecutionContext *exe_ctx, - Stream *s, - const DataExtractor &data, - uint32_t data_byte_offset, - bool show_types, - bool show_summary, - bool verbose, - lldb::Format format -) -{ - if (ResolveClangType(eResolveStateForward)) - { - if (show_types) - { - s->PutChar('('); - if (verbose) - s->Printf("Type{0x%8.8" PRIx64 "} ", GetID()); - DumpTypeName (s); - s->PutCString(") "); - } - - GetForwardCompilerType ().DumpValue (exe_ctx, - s, - format == lldb::eFormatDefault ? GetFormat() : format, - data, - data_byte_offset, - GetByteSize(), - 0, // Bitfield bit size - 0, // Bitfield bit offset - show_types, - show_summary, - verbose, - 0); + GetForwardCompilerType().DumpValue( + exe_ctx, s, format == lldb::eFormatDefault ? GetFormat() : format, data, + data_byte_offset, GetByteSize(), + 0, // Bitfield bit size + 0, // Bitfield bit offset + show_types, show_summary, verbose, 0); + } +} + +Type *Type::GetEncodingType() { + if (m_encoding_type == nullptr && m_encoding_uid != LLDB_INVALID_UID) + m_encoding_type = m_symbol_file->ResolveTypeUID(m_encoding_uid); + return m_encoding_type; +} + +uint64_t Type::GetByteSize() { + if (m_byte_size == 0) { + switch (m_encoding_uid_type) { + case eEncodingInvalid: + case eEncodingIsSyntheticUID: + break; + case eEncodingIsUID: + case eEncodingIsConstUID: + case eEncodingIsRestrictUID: + case eEncodingIsVolatileUID: + case eEncodingIsTypedefUID: { + Type *encoding_type = GetEncodingType(); + if (encoding_type) + m_byte_size = encoding_type->GetByteSize(); + if (m_byte_size == 0) + m_byte_size = GetLayoutCompilerType().GetByteSize(nullptr); + } break; + + // If we are a pointer or reference, then this is just a pointer size; + case eEncodingIsPointerUID: + case eEncodingIsLValueReferenceUID: + case eEncodingIsRValueReferenceUID: { + ArchSpec arch; + if (m_symbol_file->GetObjectFile()->GetArchitecture(arch)) + m_byte_size = arch.GetAddressByteSize(); + } break; } + } + return m_byte_size; } -Type * -Type::GetEncodingType () -{ - if (m_encoding_type == nullptr && m_encoding_uid != LLDB_INVALID_UID) - m_encoding_type = m_symbol_file->ResolveTypeUID(m_encoding_uid); - return m_encoding_type; -} - - - -uint64_t -Type::GetByteSize() -{ - if (m_byte_size == 0) - { - switch (m_encoding_uid_type) - { - case eEncodingInvalid: - case eEncodingIsSyntheticUID: - break; - case eEncodingIsUID: - case eEncodingIsConstUID: - case eEncodingIsRestrictUID: - case eEncodingIsVolatileUID: - case eEncodingIsTypedefUID: - { - Type *encoding_type = GetEncodingType (); - if (encoding_type) - m_byte_size = encoding_type->GetByteSize(); - if (m_byte_size == 0) - m_byte_size = GetLayoutCompilerType ().GetByteSize(nullptr); - } - break; - - // If we are a pointer or reference, then this is just a pointer size; - case eEncodingIsPointerUID: - case eEncodingIsLValueReferenceUID: - case eEncodingIsRValueReferenceUID: - { - ArchSpec arch; - if (m_symbol_file->GetObjectFile()->GetArchitecture(arch)) - m_byte_size = arch.GetAddressByteSize(); - } - break; - } - } - return m_byte_size; +uint32_t Type::GetNumChildren(bool omit_empty_base_classes) { + return GetForwardCompilerType().GetNumChildren(omit_empty_base_classes); } +bool Type::IsAggregateType() { + return GetForwardCompilerType().IsAggregateType(); +} -uint32_t -Type::GetNumChildren (bool omit_empty_base_classes) -{ - return GetForwardCompilerType ().GetNumChildren(omit_empty_base_classes); +lldb::TypeSP Type::GetTypedefType() { + lldb::TypeSP type_sp; + if (IsTypedef()) { + Type *typedef_type = m_symbol_file->ResolveTypeUID(m_encoding_uid); + if (typedef_type) + type_sp = typedef_type->shared_from_this(); + } + return type_sp; } -bool -Type::IsAggregateType () -{ - return GetForwardCompilerType ().IsAggregateType(); +lldb::Format Type::GetFormat() { return GetForwardCompilerType().GetFormat(); } + +lldb::Encoding Type::GetEncoding(uint64_t &count) { + // Make sure we resolve our type if it already hasn't been. + return GetForwardCompilerType().GetEncoding(count); } -lldb::TypeSP -Type::GetTypedefType() -{ - lldb::TypeSP type_sp; - if (IsTypedef()) - { - Type *typedef_type = m_symbol_file->ResolveTypeUID(m_encoding_uid); - if (typedef_type) - type_sp = typedef_type->shared_from_this(); +bool Type::DumpValueInMemory(ExecutionContext *exe_ctx, Stream *s, + lldb::addr_t address, AddressType address_type, + bool show_types, bool show_summary, bool verbose) { + if (address != LLDB_INVALID_ADDRESS) { + DataExtractor data; + Target *target = nullptr; + if (exe_ctx) + target = exe_ctx->GetTargetPtr(); + if (target) + data.SetByteOrder(target->GetArchitecture().GetByteOrder()); + if (ReadFromMemory(exe_ctx, address, address_type, data)) { + DumpValue(exe_ctx, s, data, 0, show_types, show_summary, verbose); + return true; } - return type_sp; -} - - - -lldb::Format -Type::GetFormat () -{ - return GetForwardCompilerType ().GetFormat(); -} - - - -lldb::Encoding -Type::GetEncoding (uint64_t &count) -{ - // Make sure we resolve our type if it already hasn't been. - return GetForwardCompilerType ().GetEncoding(count); -} - -bool -Type::DumpValueInMemory -( - ExecutionContext *exe_ctx, - Stream *s, - lldb::addr_t address, - AddressType address_type, - bool show_types, - bool show_summary, - bool verbose -) -{ - if (address != LLDB_INVALID_ADDRESS) - { - DataExtractor data; - Target *target = nullptr; - if (exe_ctx) - target = exe_ctx->GetTargetPtr(); - if (target) - data.SetByteOrder (target->GetArchitecture().GetByteOrder()); - if (ReadFromMemory (exe_ctx, address, address_type, data)) - { - DumpValue(exe_ctx, s, data, 0, show_types, show_summary, verbose); - return true; - } - } - return false; + } + return false; } - -bool -Type::ReadFromMemory (ExecutionContext *exe_ctx, lldb::addr_t addr, AddressType address_type, DataExtractor &data) -{ - if (address_type == eAddressTypeFile) - { - // Can't convert a file address to anything valid without more - // context (which Module it came from) +bool Type::ReadFromMemory(ExecutionContext *exe_ctx, lldb::addr_t addr, + AddressType address_type, DataExtractor &data) { + if (address_type == eAddressTypeFile) { + // Can't convert a file address to anything valid without more + // context (which Module it came from) + return false; + } + + const uint64_t byte_size = GetByteSize(); + if (data.GetByteSize() < byte_size) { + lldb::DataBufferSP data_sp(new DataBufferHeap(byte_size, '\0')); + data.SetData(data_sp); + } + + uint8_t *dst = const_cast<uint8_t *>(data.PeekData(0, byte_size)); + if (dst != nullptr) { + if (address_type == eAddressTypeHost) { + // The address is an address in this process, so just copy it + if (addr == 0) return false; - } - - const uint64_t byte_size = GetByteSize(); - if (data.GetByteSize() < byte_size) - { - lldb::DataBufferSP data_sp(new DataBufferHeap (byte_size, '\0')); - data.SetData(data_sp); - } - - uint8_t* dst = const_cast<uint8_t*>(data.PeekData(0, byte_size)); - if (dst != nullptr) - { - if (address_type == eAddressTypeHost) - { - // The address is an address in this process, so just copy it - if (addr == 0) - return false; - memcpy (dst, (uint8_t*)nullptr + addr, byte_size); - return true; - } - else - { - if (exe_ctx) - { - Process *process = exe_ctx->GetProcessPtr(); - if (process) - { - Error error; - return exe_ctx->GetProcessPtr()->ReadMemory(addr, dst, byte_size, error) == byte_size; - } - } + memcpy(dst, (uint8_t *)nullptr + addr, byte_size); + return true; + } else { + if (exe_ctx) { + Process *process = exe_ctx->GetProcessPtr(); + if (process) { + Error error; + return exe_ctx->GetProcessPtr()->ReadMemory(addr, dst, byte_size, + error) == byte_size; } + } } - return false; + } + return false; } - -bool -Type::WriteToMemory (ExecutionContext *exe_ctx, lldb::addr_t addr, AddressType address_type, DataExtractor &data) -{ - return false; +bool Type::WriteToMemory(ExecutionContext *exe_ctx, lldb::addr_t addr, + AddressType address_type, DataExtractor &data) { + return false; } +TypeList *Type::GetTypeList() { return GetSymbolFile()->GetTypeList(); } -TypeList* -Type::GetTypeList() -{ - return GetSymbolFile()->GetTypeList(); -} - -const Declaration & -Type::GetDeclaration () const -{ - return m_decl; -} - -bool -Type::ResolveClangType (ResolveState compiler_type_resolve_state) -{ - // TODO: This needs to consider the correct type system to use. - Type *encoding_type = nullptr; - if (!m_compiler_type.IsValid()) - { - encoding_type = GetEncodingType(); - if (encoding_type) - { - switch (m_encoding_uid_type) - { - case eEncodingIsUID: - { - CompilerType encoding_compiler_type = encoding_type->GetForwardCompilerType (); - if (encoding_compiler_type.IsValid()) - { - m_compiler_type = encoding_compiler_type; - m_flags.compiler_type_resolve_state = encoding_type->m_flags.compiler_type_resolve_state; - } - } - break; - - case eEncodingIsConstUID: - m_compiler_type = encoding_type->GetForwardCompilerType ().AddConstModifier(); - break; - - case eEncodingIsRestrictUID: - m_compiler_type = encoding_type->GetForwardCompilerType ().AddRestrictModifier(); - break; - - case eEncodingIsVolatileUID: - m_compiler_type = encoding_type->GetForwardCompilerType ().AddVolatileModifier(); - break; - - case eEncodingIsTypedefUID: - m_compiler_type = encoding_type->GetForwardCompilerType ().CreateTypedef(m_name.AsCString("__lldb_invalid_typedef_name"), - GetSymbolFile()->GetDeclContextContainingUID(GetID())); - m_name.Clear(); - break; - - case eEncodingIsPointerUID: - m_compiler_type = encoding_type->GetForwardCompilerType ().GetPointerType(); - break; - - case eEncodingIsLValueReferenceUID: - m_compiler_type = encoding_type->GetForwardCompilerType ().GetLValueReferenceType(); - break; - - case eEncodingIsRValueReferenceUID: - m_compiler_type = encoding_type->GetForwardCompilerType ().GetRValueReferenceType(); - break; - - default: - assert(!"Unhandled encoding_data_type."); - break; - } - } - else - { - // We have no encoding type, return void? - TypeSystem *type_system = m_symbol_file->GetTypeSystemForLanguage(eLanguageTypeC); - CompilerType void_compiler_type = type_system->GetBasicTypeFromAST(eBasicTypeVoid); - switch (m_encoding_uid_type) - { - case eEncodingIsUID: - m_compiler_type = void_compiler_type; - break; - - case eEncodingIsConstUID: - m_compiler_type = void_compiler_type.AddConstModifier(); - break; - - case eEncodingIsRestrictUID: - m_compiler_type = void_compiler_type.AddRestrictModifier(); - break; - - case eEncodingIsVolatileUID: - m_compiler_type = void_compiler_type.AddVolatileModifier(); - break; - - case eEncodingIsTypedefUID: - m_compiler_type = void_compiler_type.CreateTypedef(m_name.AsCString("__lldb_invalid_typedef_name"), - GetSymbolFile()->GetDeclContextContainingUID(GetID())); - break; - - case eEncodingIsPointerUID: - m_compiler_type = void_compiler_type.GetPointerType (); - break; - - case eEncodingIsLValueReferenceUID: - m_compiler_type = void_compiler_type.GetLValueReferenceType(); - break; - - case eEncodingIsRValueReferenceUID: - m_compiler_type = void_compiler_type.GetRValueReferenceType(); - break; - - default: - assert(!"Unhandled encoding_data_type."); - break; - } - } - - // When we have a EncodingUID, our "m_flags.compiler_type_resolve_state" is set to eResolveStateUnresolved - // so we need to update it to say that we now have a forward declaration since that is what we created - // above. - if (m_compiler_type.IsValid()) - m_flags.compiler_type_resolve_state = eResolveStateForward; +const Declaration &Type::GetDeclaration() const { return m_decl; } +bool Type::ResolveClangType(ResolveState compiler_type_resolve_state) { + // TODO: This needs to consider the correct type system to use. + Type *encoding_type = nullptr; + if (!m_compiler_type.IsValid()) { + encoding_type = GetEncodingType(); + if (encoding_type) { + switch (m_encoding_uid_type) { + case eEncodingIsUID: { + CompilerType encoding_compiler_type = + encoding_type->GetForwardCompilerType(); + if (encoding_compiler_type.IsValid()) { + m_compiler_type = encoding_compiler_type; + m_flags.compiler_type_resolve_state = + encoding_type->m_flags.compiler_type_resolve_state; + } + } break; + + case eEncodingIsConstUID: + m_compiler_type = + encoding_type->GetForwardCompilerType().AddConstModifier(); + break; + + case eEncodingIsRestrictUID: + m_compiler_type = + encoding_type->GetForwardCompilerType().AddRestrictModifier(); + break; + + case eEncodingIsVolatileUID: + m_compiler_type = + encoding_type->GetForwardCompilerType().AddVolatileModifier(); + break; + + case eEncodingIsTypedefUID: + m_compiler_type = encoding_type->GetForwardCompilerType().CreateTypedef( + m_name.AsCString("__lldb_invalid_typedef_name"), + GetSymbolFile()->GetDeclContextContainingUID(GetID())); + m_name.Clear(); + break; + + case eEncodingIsPointerUID: + m_compiler_type = + encoding_type->GetForwardCompilerType().GetPointerType(); + break; + + case eEncodingIsLValueReferenceUID: + m_compiler_type = + encoding_type->GetForwardCompilerType().GetLValueReferenceType(); + break; + + case eEncodingIsRValueReferenceUID: + m_compiler_type = + encoding_type->GetForwardCompilerType().GetRValueReferenceType(); + break; + + default: + assert(!"Unhandled encoding_data_type."); + break; + } + } else { + // We have no encoding type, return void? + TypeSystem *type_system = + m_symbol_file->GetTypeSystemForLanguage(eLanguageTypeC); + CompilerType void_compiler_type = + type_system->GetBasicTypeFromAST(eBasicTypeVoid); + switch (m_encoding_uid_type) { + case eEncodingIsUID: + m_compiler_type = void_compiler_type; + break; + + case eEncodingIsConstUID: + m_compiler_type = void_compiler_type.AddConstModifier(); + break; + + case eEncodingIsRestrictUID: + m_compiler_type = void_compiler_type.AddRestrictModifier(); + break; + + case eEncodingIsVolatileUID: + m_compiler_type = void_compiler_type.AddVolatileModifier(); + break; + + case eEncodingIsTypedefUID: + m_compiler_type = void_compiler_type.CreateTypedef( + m_name.AsCString("__lldb_invalid_typedef_name"), + GetSymbolFile()->GetDeclContextContainingUID(GetID())); + break; + + case eEncodingIsPointerUID: + m_compiler_type = void_compiler_type.GetPointerType(); + break; + + case eEncodingIsLValueReferenceUID: + m_compiler_type = void_compiler_type.GetLValueReferenceType(); + break; + + case eEncodingIsRValueReferenceUID: + m_compiler_type = void_compiler_type.GetRValueReferenceType(); + break; + + default: + assert(!"Unhandled encoding_data_type."); + break; + } } + // When we have a EncodingUID, our "m_flags.compiler_type_resolve_state" is + // set to eResolveStateUnresolved + // so we need to update it to say that we now have a forward declaration + // since that is what we created + // above. + if (m_compiler_type.IsValid()) + m_flags.compiler_type_resolve_state = eResolveStateForward; + } + + // Check if we have a forward reference to a class/struct/union/enum? + if (compiler_type_resolve_state == eResolveStateLayout || + compiler_type_resolve_state == eResolveStateFull) { // Check if we have a forward reference to a class/struct/union/enum? - if (compiler_type_resolve_state == eResolveStateLayout || compiler_type_resolve_state == eResolveStateFull) - { - // Check if we have a forward reference to a class/struct/union/enum? - if (m_compiler_type.IsValid() && m_flags.compiler_type_resolve_state < compiler_type_resolve_state) - { - m_flags.compiler_type_resolve_state = eResolveStateFull; - if (!m_compiler_type.IsDefined ()) - { - // We have a forward declaration, we need to resolve it to a complete definition. - m_symbol_file->CompleteType (m_compiler_type); - } - } + if (m_compiler_type.IsValid() && + m_flags.compiler_type_resolve_state < compiler_type_resolve_state) { + m_flags.compiler_type_resolve_state = eResolveStateFull; + if (!m_compiler_type.IsDefined()) { + // We have a forward declaration, we need to resolve it to a complete + // definition. + m_symbol_file->CompleteType(m_compiler_type); + } } - - // If we have an encoding type, then we need to make sure it is - // resolved appropriately. - if (m_encoding_uid != LLDB_INVALID_UID) - { - if (encoding_type == nullptr) - encoding_type = GetEncodingType(); - if (encoding_type) - { - ResolveState encoding_compiler_type_resolve_state = compiler_type_resolve_state; - - if (compiler_type_resolve_state == eResolveStateLayout) - { - switch (m_encoding_uid_type) - { - case eEncodingIsPointerUID: - case eEncodingIsLValueReferenceUID: - case eEncodingIsRValueReferenceUID: - encoding_compiler_type_resolve_state = eResolveStateForward; - break; - default: - break; - } - } - encoding_type->ResolveClangType (encoding_compiler_type_resolve_state); + } + + // If we have an encoding type, then we need to make sure it is + // resolved appropriately. + if (m_encoding_uid != LLDB_INVALID_UID) { + if (encoding_type == nullptr) + encoding_type = GetEncodingType(); + if (encoding_type) { + ResolveState encoding_compiler_type_resolve_state = + compiler_type_resolve_state; + + if (compiler_type_resolve_state == eResolveStateLayout) { + switch (m_encoding_uid_type) { + case eEncodingIsPointerUID: + case eEncodingIsLValueReferenceUID: + case eEncodingIsRValueReferenceUID: + encoding_compiler_type_resolve_state = eResolveStateForward; + break; + default: + break; } + } + encoding_type->ResolveClangType(encoding_compiler_type_resolve_state); } - return m_compiler_type.IsValid(); -} -uint32_t -Type::GetEncodingMask () -{ - uint32_t encoding_mask = 1u << m_encoding_uid_type; - Type *encoding_type = GetEncodingType(); - assert (encoding_type != this); - if (encoding_type) - encoding_mask |= encoding_type->GetEncodingMask (); - return encoding_mask; -} - -CompilerType -Type::GetFullCompilerType () -{ - ResolveClangType(eResolveStateFull); - return m_compiler_type; -} - -CompilerType -Type::GetLayoutCompilerType () -{ - ResolveClangType(eResolveStateLayout); - return m_compiler_type; -} - -CompilerType -Type::GetForwardCompilerType () -{ - ResolveClangType (eResolveStateForward); - return m_compiler_type; -} - -int -Type::Compare(const Type &a, const Type &b) -{ - // Just compare the UID values for now... - lldb::user_id_t a_uid = a.GetID(); - lldb::user_id_t b_uid = b.GetID(); - if (a_uid < b_uid) - return -1; - if (a_uid > b_uid) - return 1; - return 0; -} - -ConstString -Type::GetQualifiedName () -{ - return GetForwardCompilerType ().GetConstTypeName(); -} - -bool -Type::GetTypeScopeAndBasename (const char* &name_cstr, - std::string &scope, - std::string &basename, - TypeClass &type_class) -{ - // Protect against null c string. - - type_class = eTypeClassAny; - - if (name_cstr && name_cstr[0]) - { - llvm::StringRef name_strref(name_cstr); - if (name_strref.startswith("struct ")) - { - name_cstr += 7; - type_class = eTypeClassStruct; - } - else if (name_strref.startswith("class ")) - { - name_cstr += 6; - type_class = eTypeClassClass; - } - else if (name_strref.startswith("union ")) - { - name_cstr += 6; - type_class = eTypeClassUnion; - } - else if (name_strref.startswith("enum ")) - { - name_cstr += 5; - type_class = eTypeClassEnumeration; - } - else if (name_strref.startswith("typedef ")) - { - name_cstr += 8; - type_class = eTypeClassTypedef; - } - const char *basename_cstr = name_cstr; - const char* namespace_separator = ::strstr (basename_cstr, "::"); - if (namespace_separator) - { - const char* template_arg_char = ::strchr (basename_cstr, '<'); - while (namespace_separator != nullptr) - { - if (template_arg_char && namespace_separator > template_arg_char) // but namespace'd template arguments are still good to go - break; - basename_cstr = namespace_separator + 2; - namespace_separator = strstr(basename_cstr, "::"); - } - if (basename_cstr > name_cstr) - { - scope.assign (name_cstr, basename_cstr - name_cstr); - basename.assign (basename_cstr); - return true; - } - } + } + return m_compiler_type.IsValid(); +} +uint32_t Type::GetEncodingMask() { + uint32_t encoding_mask = 1u << m_encoding_uid_type; + Type *encoding_type = GetEncodingType(); + assert(encoding_type != this); + if (encoding_type) + encoding_mask |= encoding_type->GetEncodingMask(); + return encoding_mask; +} + +CompilerType Type::GetFullCompilerType() { + ResolveClangType(eResolveStateFull); + return m_compiler_type; +} + +CompilerType Type::GetLayoutCompilerType() { + ResolveClangType(eResolveStateLayout); + return m_compiler_type; +} + +CompilerType Type::GetForwardCompilerType() { + ResolveClangType(eResolveStateForward); + return m_compiler_type; +} + +int Type::Compare(const Type &a, const Type &b) { + // Just compare the UID values for now... + lldb::user_id_t a_uid = a.GetID(); + lldb::user_id_t b_uid = b.GetID(); + if (a_uid < b_uid) + return -1; + if (a_uid > b_uid) + return 1; + return 0; +} + +ConstString Type::GetQualifiedName() { + return GetForwardCompilerType().GetConstTypeName(); +} + +bool Type::GetTypeScopeAndBasename(const char *&name_cstr, std::string &scope, + std::string &basename, + TypeClass &type_class) { + // Protect against null c string. + + type_class = eTypeClassAny; + + if (name_cstr && name_cstr[0]) { + llvm::StringRef name_strref(name_cstr); + if (name_strref.startswith("struct ")) { + name_cstr += 7; + type_class = eTypeClassStruct; + } else if (name_strref.startswith("class ")) { + name_cstr += 6; + type_class = eTypeClassClass; + } else if (name_strref.startswith("union ")) { + name_cstr += 6; + type_class = eTypeClassUnion; + } else if (name_strref.startswith("enum ")) { + name_cstr += 5; + type_class = eTypeClassEnumeration; + } else if (name_strref.startswith("typedef ")) { + name_cstr += 8; + type_class = eTypeClassTypedef; } - return false; + const char *basename_cstr = name_cstr; + const char *namespace_separator = ::strstr(basename_cstr, "::"); + if (namespace_separator) { + const char *template_arg_char = ::strchr(basename_cstr, '<'); + while (namespace_separator != nullptr) { + if (template_arg_char && + namespace_separator > template_arg_char) // but namespace'd template + // arguments are still good + // to go + break; + basename_cstr = namespace_separator + 2; + namespace_separator = strstr(basename_cstr, "::"); + } + if (basename_cstr > name_cstr) { + scope.assign(name_cstr, basename_cstr - name_cstr); + basename.assign(basename_cstr); + return true; + } + } + } + return false; +} + +ModuleSP Type::GetModule() { + if (m_symbol_file) + return m_symbol_file->GetObjectFile()->GetModule(); + return ModuleSP(); } +TypeAndOrName::TypeAndOrName() : m_type_pair(), m_type_name() {} -ModuleSP -Type::GetModule() -{ - if (m_symbol_file) - return m_symbol_file->GetObjectFile()->GetModule(); - return ModuleSP(); +TypeAndOrName::TypeAndOrName(TypeSP &in_type_sp) : m_type_pair(in_type_sp) { + if (in_type_sp) + m_type_name = in_type_sp->GetName(); } +TypeAndOrName::TypeAndOrName(const char *in_type_str) + : m_type_name(in_type_str) {} -TypeAndOrName::TypeAndOrName () : m_type_pair(), m_type_name() -{ +TypeAndOrName::TypeAndOrName(const TypeAndOrName &rhs) + : m_type_pair(rhs.m_type_pair), m_type_name(rhs.m_type_name) {} +TypeAndOrName::TypeAndOrName(ConstString &in_type_const_string) + : m_type_name(in_type_const_string) {} + +TypeAndOrName &TypeAndOrName::operator=(const TypeAndOrName &rhs) { + if (this != &rhs) { + m_type_name = rhs.m_type_name; + m_type_pair = rhs.m_type_pair; + } + return *this; } -TypeAndOrName::TypeAndOrName (TypeSP &in_type_sp) : m_type_pair(in_type_sp) -{ - if (in_type_sp) - m_type_name = in_type_sp->GetName(); +bool TypeAndOrName::operator==(const TypeAndOrName &other) const { + if (m_type_pair != other.m_type_pair) + return false; + if (m_type_name != other.m_type_name) + return false; + return true; } -TypeAndOrName::TypeAndOrName (const char *in_type_str) : m_type_name(in_type_str) -{ +bool TypeAndOrName::operator!=(const TypeAndOrName &other) const { + if (m_type_pair != other.m_type_pair) + return true; + if (m_type_name != other.m_type_name) + return true; + return false; } -TypeAndOrName::TypeAndOrName (const TypeAndOrName &rhs) : m_type_pair (rhs.m_type_pair), m_type_name (rhs.m_type_name) -{ +ConstString TypeAndOrName::GetName() const { + if (m_type_name) + return m_type_name; + if (m_type_pair) + return m_type_pair.GetName(); + return ConstString("<invalid>"); +} +void TypeAndOrName::SetName(const ConstString &type_name) { + m_type_name = type_name; } -TypeAndOrName::TypeAndOrName (ConstString &in_type_const_string) : m_type_name (in_type_const_string) -{ +void TypeAndOrName::SetName(const char *type_name_cstr) { + m_type_name.SetCString(type_name_cstr); } -TypeAndOrName & -TypeAndOrName::operator= (const TypeAndOrName &rhs) -{ - if (this != &rhs) - { - m_type_name = rhs.m_type_name; - m_type_pair = rhs.m_type_pair; - } - return *this; +void TypeAndOrName::SetTypeSP(lldb::TypeSP type_sp) { + m_type_pair.SetType(type_sp); + if (m_type_pair) + m_type_name = m_type_pair.GetName(); } -bool -TypeAndOrName::operator==(const TypeAndOrName &other) const -{ - if (m_type_pair != other.m_type_pair) - return false; - if (m_type_name != other.m_type_name) - return false; - return true; +void TypeAndOrName::SetCompilerType(CompilerType compiler_type) { + m_type_pair.SetType(compiler_type); + if (m_type_pair) + m_type_name = m_type_pair.GetName(); } -bool -TypeAndOrName::operator!=(const TypeAndOrName &other) const -{ - if (m_type_pair != other.m_type_pair) - return true; - if (m_type_name != other.m_type_name) - return true; +bool TypeAndOrName::IsEmpty() const { + if ((bool)m_type_name || (bool)m_type_pair) return false; + else + return true; } -ConstString -TypeAndOrName::GetName () const -{ - if (m_type_name) - return m_type_name; - if (m_type_pair) - return m_type_pair.GetName(); - return ConstString("<invalid>"); +void TypeAndOrName::Clear() { + m_type_name.Clear(); + m_type_pair.Clear(); } -void -TypeAndOrName::SetName (const ConstString &type_name) -{ - m_type_name = type_name; -} +bool TypeAndOrName::HasName() const { return (bool)m_type_name; } -void -TypeAndOrName::SetName (const char *type_name_cstr) -{ - m_type_name.SetCString (type_name_cstr); +bool TypeAndOrName::HasTypeSP() const { + return m_type_pair.GetTypeSP().get() != nullptr; } -void -TypeAndOrName::SetTypeSP (lldb::TypeSP type_sp) -{ - m_type_pair.SetType(type_sp); - if (m_type_pair) - m_type_name = m_type_pair.GetName(); +bool TypeAndOrName::HasCompilerType() const { + return m_type_pair.GetCompilerType().IsValid(); } -void -TypeAndOrName::SetCompilerType (CompilerType compiler_type) -{ - m_type_pair.SetType(compiler_type); - if (m_type_pair) - m_type_name = m_type_pair.GetName(); -} +TypeImpl::TypeImpl() : m_module_wp(), m_static_type(), m_dynamic_type() {} -bool -TypeAndOrName::IsEmpty() const -{ - if ((bool)m_type_name || (bool)m_type_pair) - return false; - else - return true; -} +TypeImpl::TypeImpl(const TypeImpl &rhs) + : m_module_wp(rhs.m_module_wp), m_static_type(rhs.m_static_type), + m_dynamic_type(rhs.m_dynamic_type) {} -void -TypeAndOrName::Clear () -{ - m_type_name.Clear(); - m_type_pair.Clear(); +TypeImpl::TypeImpl(const lldb::TypeSP &type_sp) + : m_module_wp(), m_static_type(), m_dynamic_type() { + SetType(type_sp); } -bool -TypeAndOrName::HasName () const -{ - return (bool)m_type_name; +TypeImpl::TypeImpl(const CompilerType &compiler_type) + : m_module_wp(), m_static_type(), m_dynamic_type() { + SetType(compiler_type); } -bool -TypeAndOrName::HasTypeSP () const -{ - return m_type_pair.GetTypeSP().get() != nullptr; +TypeImpl::TypeImpl(const lldb::TypeSP &type_sp, const CompilerType &dynamic) + : m_module_wp(), m_static_type(type_sp), m_dynamic_type(dynamic) { + SetType(type_sp, dynamic); } -bool -TypeAndOrName::HasCompilerType () const -{ - return m_type_pair.GetCompilerType().IsValid(); +TypeImpl::TypeImpl(const CompilerType &static_type, + const CompilerType &dynamic_type) + : m_module_wp(), m_static_type(), m_dynamic_type() { + SetType(static_type, dynamic_type); } - -TypeImpl::TypeImpl() : - m_module_wp(), - m_static_type(), - m_dynamic_type() -{ +TypeImpl::TypeImpl(const TypePair &pair, const CompilerType &dynamic) + : m_module_wp(), m_static_type(), m_dynamic_type() { + SetType(pair, dynamic); } -TypeImpl::TypeImpl(const TypeImpl& rhs) : - m_module_wp (rhs.m_module_wp), - m_static_type(rhs.m_static_type), - m_dynamic_type(rhs.m_dynamic_type) -{ +void TypeImpl::SetType(const lldb::TypeSP &type_sp) { + m_static_type.SetType(type_sp); + if (type_sp) + m_module_wp = type_sp->GetModule(); + else + m_module_wp = lldb::ModuleWP(); } -TypeImpl::TypeImpl (const lldb::TypeSP &type_sp) : - m_module_wp (), - m_static_type(), - m_dynamic_type() -{ - SetType (type_sp); +void TypeImpl::SetType(const CompilerType &compiler_type) { + m_module_wp = lldb::ModuleWP(); + m_static_type.SetType(compiler_type); +} + +void TypeImpl::SetType(const lldb::TypeSP &type_sp, + const CompilerType &dynamic) { + SetType(type_sp); + m_dynamic_type = dynamic; +} + +void TypeImpl::SetType(const CompilerType &compiler_type, + const CompilerType &dynamic) { + m_module_wp = lldb::ModuleWP(); + m_static_type.SetType(compiler_type); + m_dynamic_type = dynamic; +} + +void TypeImpl::SetType(const TypePair &pair, const CompilerType &dynamic) { + m_module_wp = pair.GetModule(); + m_static_type = pair; + m_dynamic_type = dynamic; +} + +TypeImpl &TypeImpl::operator=(const TypeImpl &rhs) { + if (rhs != *this) { + m_module_wp = rhs.m_module_wp; + m_static_type = rhs.m_static_type; + m_dynamic_type = rhs.m_dynamic_type; + } + return *this; +} + +bool TypeImpl::CheckModule(lldb::ModuleSP &module_sp) const { + // Check if we have a module for this type. If we do and the shared pointer is + // can be successfully initialized with m_module_wp, return true. Else return + // false + // if we didn't have a module, or if we had a module and it has been deleted. + // Any + // functions doing anything with a TypeSP in this TypeImpl class should call + // this + // function and only do anything with the ivars if this function returns true. + // If + // we have a module, the "module_sp" will be filled in with a strong reference + // to the + // module so that the module will at least stay around long enough for the + // type + // query to succeed. + module_sp = m_module_wp.lock(); + if (!module_sp) { + lldb::ModuleWP empty_module_wp; + // If either call to "std::weak_ptr::owner_before(...) value returns true, + // this + // indicates that m_module_wp once contained (possibly still does) a + // reference + // to a valid shared pointer. This helps us know if we had a valid reference + // to + // a section which is now invalid because the module it was in was deleted + if (empty_module_wp.owner_before(m_module_wp) || + m_module_wp.owner_before(empty_module_wp)) { + // m_module_wp had a valid reference to a module, but all strong + // references + // have been released and the module has been deleted + return false; + } + } + // We either successfully locked the module, or didn't have one to begin with + return true; } -TypeImpl::TypeImpl (const CompilerType &compiler_type) : - m_module_wp (), - m_static_type(), - m_dynamic_type() -{ - SetType (compiler_type); +bool TypeImpl::operator==(const TypeImpl &rhs) const { + return m_static_type == rhs.m_static_type && + m_dynamic_type == rhs.m_dynamic_type; } -TypeImpl::TypeImpl (const lldb::TypeSP &type_sp, const CompilerType &dynamic) : - m_module_wp (), - m_static_type (type_sp), - m_dynamic_type(dynamic) -{ - SetType (type_sp, dynamic); +bool TypeImpl::operator!=(const TypeImpl &rhs) const { + return m_static_type != rhs.m_static_type || + m_dynamic_type != rhs.m_dynamic_type; } -TypeImpl::TypeImpl (const CompilerType &static_type, const CompilerType &dynamic_type) : - m_module_wp (), - m_static_type (), - m_dynamic_type() -{ - SetType (static_type, dynamic_type); +bool TypeImpl::IsValid() const { + // just a name is not valid + ModuleSP module_sp; + if (CheckModule(module_sp)) + return m_static_type.IsValid() || m_dynamic_type.IsValid(); + return false; } -TypeImpl::TypeImpl (const TypePair &pair, const CompilerType &dynamic) : - m_module_wp (), - m_static_type (), - m_dynamic_type() -{ - SetType (pair, dynamic); -} +TypeImpl::operator bool() const { return IsValid(); } -void -TypeImpl::SetType (const lldb::TypeSP &type_sp) -{ - m_static_type.SetType(type_sp); - if (type_sp) - m_module_wp = type_sp->GetModule(); - else - m_module_wp = lldb::ModuleWP(); +void TypeImpl::Clear() { + m_module_wp = lldb::ModuleWP(); + m_static_type.Clear(); + m_dynamic_type.Clear(); } -void -TypeImpl::SetType (const CompilerType &compiler_type) -{ - m_module_wp = lldb::ModuleWP(); - m_static_type.SetType (compiler_type); +ConstString TypeImpl::GetName() const { + ModuleSP module_sp; + if (CheckModule(module_sp)) { + if (m_dynamic_type) + return m_dynamic_type.GetTypeName(); + return m_static_type.GetName(); + } + return ConstString(); } -void -TypeImpl::SetType (const lldb::TypeSP &type_sp, const CompilerType &dynamic) -{ - SetType (type_sp); - m_dynamic_type = dynamic; +ConstString TypeImpl::GetDisplayTypeName() const { + ModuleSP module_sp; + if (CheckModule(module_sp)) { + if (m_dynamic_type) + return m_dynamic_type.GetDisplayTypeName(); + return m_static_type.GetDisplayTypeName(); + } + return ConstString(); } -void -TypeImpl::SetType (const CompilerType &compiler_type, const CompilerType &dynamic) -{ - m_module_wp = lldb::ModuleWP(); - m_static_type.SetType (compiler_type); - m_dynamic_type = dynamic; -} - -void -TypeImpl::SetType (const TypePair &pair, const CompilerType &dynamic) -{ - m_module_wp = pair.GetModule(); - m_static_type = pair; - m_dynamic_type = dynamic; -} - -TypeImpl& -TypeImpl::operator = (const TypeImpl& rhs) -{ - if (rhs != *this) - { - m_module_wp = rhs.m_module_wp; - m_static_type = rhs.m_static_type; - m_dynamic_type = rhs.m_dynamic_type; - } - return *this; -} - -bool -TypeImpl::CheckModule (lldb::ModuleSP &module_sp) const -{ - // Check if we have a module for this type. If we do and the shared pointer is - // can be successfully initialized with m_module_wp, return true. Else return false - // if we didn't have a module, or if we had a module and it has been deleted. Any - // functions doing anything with a TypeSP in this TypeImpl class should call this - // function and only do anything with the ivars if this function returns true. If - // we have a module, the "module_sp" will be filled in with a strong reference to the - // module so that the module will at least stay around long enough for the type - // query to succeed. - module_sp = m_module_wp.lock(); - if (!module_sp) - { - lldb::ModuleWP empty_module_wp; - // If either call to "std::weak_ptr::owner_before(...) value returns true, this - // indicates that m_module_wp once contained (possibly still does) a reference - // to a valid shared pointer. This helps us know if we had a valid reference to - // a section which is now invalid because the module it was in was deleted - if (empty_module_wp.owner_before(m_module_wp) || m_module_wp.owner_before(empty_module_wp)) - { - // m_module_wp had a valid reference to a module, but all strong references - // have been released and the module has been deleted - return false; - } +TypeImpl TypeImpl::GetPointerType() const { + ModuleSP module_sp; + if (CheckModule(module_sp)) { + if (m_dynamic_type.IsValid()) { + return TypeImpl(m_static_type.GetPointerType(), + m_dynamic_type.GetPointerType()); } - // We either successfully locked the module, or didn't have one to begin with - return true; + return TypeImpl(m_static_type.GetPointerType()); + } + return TypeImpl(); } -bool -TypeImpl::operator == (const TypeImpl& rhs) const -{ - return m_static_type == rhs.m_static_type && m_dynamic_type == rhs.m_dynamic_type; +TypeImpl TypeImpl::GetPointeeType() const { + ModuleSP module_sp; + if (CheckModule(module_sp)) { + if (m_dynamic_type.IsValid()) { + return TypeImpl(m_static_type.GetPointeeType(), + m_dynamic_type.GetPointeeType()); + } + return TypeImpl(m_static_type.GetPointeeType()); + } + return TypeImpl(); } -bool -TypeImpl::operator != (const TypeImpl& rhs) const -{ - return m_static_type != rhs.m_static_type || m_dynamic_type != rhs.m_dynamic_type; +TypeImpl TypeImpl::GetReferenceType() const { + ModuleSP module_sp; + if (CheckModule(module_sp)) { + if (m_dynamic_type.IsValid()) { + return TypeImpl(m_static_type.GetReferenceType(), + m_dynamic_type.GetLValueReferenceType()); + } + return TypeImpl(m_static_type.GetReferenceType()); + } + return TypeImpl(); } -bool -TypeImpl::IsValid() const -{ - // just a name is not valid - ModuleSP module_sp; - if (CheckModule (module_sp)) - return m_static_type.IsValid() || m_dynamic_type.IsValid(); - return false; +TypeImpl TypeImpl::GetTypedefedType() const { + ModuleSP module_sp; + if (CheckModule(module_sp)) { + if (m_dynamic_type.IsValid()) { + return TypeImpl(m_static_type.GetTypedefedType(), + m_dynamic_type.GetTypedefedType()); + } + return TypeImpl(m_static_type.GetTypedefedType()); + } + return TypeImpl(); } -TypeImpl::operator bool () const -{ - return IsValid(); +TypeImpl TypeImpl::GetDereferencedType() const { + ModuleSP module_sp; + if (CheckModule(module_sp)) { + if (m_dynamic_type.IsValid()) { + return TypeImpl(m_static_type.GetDereferencedType(), + m_dynamic_type.GetNonReferenceType()); + } + return TypeImpl(m_static_type.GetDereferencedType()); + } + return TypeImpl(); } -void -TypeImpl::Clear() -{ - m_module_wp = lldb::ModuleWP(); - m_static_type.Clear(); - m_dynamic_type.Clear(); -} - -ConstString -TypeImpl::GetName () const -{ - ModuleSP module_sp; - if (CheckModule (module_sp)) - { - if (m_dynamic_type) - return m_dynamic_type.GetTypeName(); - return m_static_type.GetName (); - } - return ConstString(); -} - -ConstString -TypeImpl::GetDisplayTypeName () const -{ - ModuleSP module_sp; - if (CheckModule (module_sp)) - { - if (m_dynamic_type) - return m_dynamic_type.GetDisplayTypeName(); - return m_static_type.GetDisplayTypeName(); - } - return ConstString(); -} - -TypeImpl -TypeImpl::GetPointerType () const -{ - ModuleSP module_sp; - if (CheckModule (module_sp)) - { - if (m_dynamic_type.IsValid()) - { - return TypeImpl(m_static_type.GetPointerType(), m_dynamic_type.GetPointerType()); - } - return TypeImpl(m_static_type.GetPointerType()); - } - return TypeImpl(); -} - -TypeImpl -TypeImpl::GetPointeeType () const -{ - ModuleSP module_sp; - if (CheckModule (module_sp)) - { - if (m_dynamic_type.IsValid()) - { - return TypeImpl(m_static_type.GetPointeeType(), m_dynamic_type.GetPointeeType()); - } - return TypeImpl(m_static_type.GetPointeeType()); - } - return TypeImpl(); -} - -TypeImpl -TypeImpl::GetReferenceType () const -{ - ModuleSP module_sp; - if (CheckModule (module_sp)) - { - if (m_dynamic_type.IsValid()) - { - return TypeImpl(m_static_type.GetReferenceType(), m_dynamic_type.GetLValueReferenceType()); - } - return TypeImpl(m_static_type.GetReferenceType()); - } - return TypeImpl(); -} - -TypeImpl -TypeImpl::GetTypedefedType () const -{ - ModuleSP module_sp; - if (CheckModule (module_sp)) - { - if (m_dynamic_type.IsValid()) - { - return TypeImpl(m_static_type.GetTypedefedType(), m_dynamic_type.GetTypedefedType()); - } - return TypeImpl(m_static_type.GetTypedefedType()); - } - return TypeImpl(); -} - -TypeImpl -TypeImpl::GetDereferencedType () const -{ - ModuleSP module_sp; - if (CheckModule (module_sp)) - { - if (m_dynamic_type.IsValid()) - { - return TypeImpl(m_static_type.GetDereferencedType(), m_dynamic_type.GetNonReferenceType()); - } - return TypeImpl(m_static_type.GetDereferencedType()); - } - return TypeImpl(); -} - -TypeImpl -TypeImpl::GetUnqualifiedType() const -{ - ModuleSP module_sp; - if (CheckModule (module_sp)) - { - if (m_dynamic_type.IsValid()) - { - return TypeImpl(m_static_type.GetUnqualifiedType(), m_dynamic_type.GetFullyUnqualifiedType()); - } - return TypeImpl(m_static_type.GetUnqualifiedType()); +TypeImpl TypeImpl::GetUnqualifiedType() const { + ModuleSP module_sp; + if (CheckModule(module_sp)) { + if (m_dynamic_type.IsValid()) { + return TypeImpl(m_static_type.GetUnqualifiedType(), + m_dynamic_type.GetFullyUnqualifiedType()); } - return TypeImpl(); -} - -TypeImpl -TypeImpl::GetCanonicalType() const -{ - ModuleSP module_sp; - if (CheckModule (module_sp)) - { - if (m_dynamic_type.IsValid()) - { - return TypeImpl(m_static_type.GetCanonicalType(), m_dynamic_type.GetCanonicalType()); - } - return TypeImpl(m_static_type.GetCanonicalType()); - } - return TypeImpl(); -} - -CompilerType -TypeImpl::GetCompilerType (bool prefer_dynamic) -{ - ModuleSP module_sp; - if (CheckModule (module_sp)) - { - if (prefer_dynamic) - { - if (m_dynamic_type.IsValid()) - return m_dynamic_type; - } - return m_static_type.GetCompilerType(); - } - return CompilerType(); -} - -TypeSystem * -TypeImpl::GetTypeSystem (bool prefer_dynamic) -{ - ModuleSP module_sp; - if (CheckModule (module_sp)) - { - if (prefer_dynamic) - { - if (m_dynamic_type.IsValid()) - return m_dynamic_type.GetTypeSystem(); - } - return m_static_type.GetCompilerType().GetTypeSystem(); - } - return NULL; -} - -bool -TypeImpl::GetDescription (lldb_private::Stream &strm, - lldb::DescriptionLevel description_level) -{ - ModuleSP module_sp; - if (CheckModule (module_sp)) - { - if (m_dynamic_type.IsValid()) - { - strm.Printf("Dynamic:\n"); - m_dynamic_type.DumpTypeDescription(&strm); - strm.Printf("\nStatic:\n"); - } - m_static_type.GetCompilerType().DumpTypeDescription(&strm); - } - else - { - strm.PutCString("Invalid TypeImpl module for type has been deleted\n"); + return TypeImpl(m_static_type.GetUnqualifiedType()); + } + return TypeImpl(); +} + +TypeImpl TypeImpl::GetCanonicalType() const { + ModuleSP module_sp; + if (CheckModule(module_sp)) { + if (m_dynamic_type.IsValid()) { + return TypeImpl(m_static_type.GetCanonicalType(), + m_dynamic_type.GetCanonicalType()); } - return true; + return TypeImpl(m_static_type.GetCanonicalType()); + } + return TypeImpl(); } -bool -TypeMemberFunctionImpl::IsValid () -{ - return m_type.IsValid() && m_kind != lldb::eMemberFunctionKindUnknown; -} - -ConstString -TypeMemberFunctionImpl::GetName () const -{ - return m_name; -} - -ConstString -TypeMemberFunctionImpl::GetMangledName () const -{ - return m_decl.GetMangledName(); -} - -CompilerType -TypeMemberFunctionImpl::GetType () const -{ - return m_type; -} - -lldb::MemberFunctionKind -TypeMemberFunctionImpl::GetKind () const -{ - return m_kind; -} - -bool -TypeMemberFunctionImpl::GetDescription (Stream& stream) -{ - switch (m_kind) { - case lldb::eMemberFunctionKindUnknown: - return false; - case lldb::eMemberFunctionKindConstructor: - stream.Printf("constructor for %s", m_type.GetTypeName().AsCString("<unknown>")); - break; - case lldb::eMemberFunctionKindDestructor: - stream.Printf("destructor for %s", m_type.GetTypeName().AsCString("<unknown>")); - break; - case lldb::eMemberFunctionKindInstanceMethod: - stream.Printf("instance method %s of type %s", - m_name.AsCString(), - m_decl.GetDeclContext().GetName().AsCString()); - break; - case lldb::eMemberFunctionKindStaticMethod: - stream.Printf("static method %s of type %s", - m_name.AsCString(), - m_decl.GetDeclContext().GetName().AsCString()); - break; +CompilerType TypeImpl::GetCompilerType(bool prefer_dynamic) { + ModuleSP module_sp; + if (CheckModule(module_sp)) { + if (prefer_dynamic) { + if (m_dynamic_type.IsValid()) + return m_dynamic_type; } - return true; + return m_static_type.GetCompilerType(); + } + return CompilerType(); } -CompilerType -TypeMemberFunctionImpl::GetReturnType () const -{ - if (m_type) - return m_type.GetFunctionReturnType(); - return m_decl.GetFunctionReturnType(); +TypeSystem *TypeImpl::GetTypeSystem(bool prefer_dynamic) { + ModuleSP module_sp; + if (CheckModule(module_sp)) { + if (prefer_dynamic) { + if (m_dynamic_type.IsValid()) + return m_dynamic_type.GetTypeSystem(); + } + return m_static_type.GetCompilerType().GetTypeSystem(); + } + return NULL; +} + +bool TypeImpl::GetDescription(lldb_private::Stream &strm, + lldb::DescriptionLevel description_level) { + ModuleSP module_sp; + if (CheckModule(module_sp)) { + if (m_dynamic_type.IsValid()) { + strm.Printf("Dynamic:\n"); + m_dynamic_type.DumpTypeDescription(&strm); + strm.Printf("\nStatic:\n"); + } + m_static_type.GetCompilerType().DumpTypeDescription(&strm); + } else { + strm.PutCString("Invalid TypeImpl module for type has been deleted\n"); + } + return true; } -size_t -TypeMemberFunctionImpl::GetNumArguments () const -{ - if (m_type) - return m_type.GetNumberOfFunctionArguments(); - else - return m_decl.GetNumFunctionArguments(); +bool TypeMemberFunctionImpl::IsValid() { + return m_type.IsValid() && m_kind != lldb::eMemberFunctionKindUnknown; } -CompilerType -TypeMemberFunctionImpl::GetArgumentAtIndex (size_t idx) const -{ - if (m_type) - return m_type.GetFunctionArgumentAtIndex (idx); - else - return m_decl.GetFunctionArgumentType(idx); +ConstString TypeMemberFunctionImpl::GetName() const { return m_name; } + +ConstString TypeMemberFunctionImpl::GetMangledName() const { + return m_decl.GetMangledName(); } -TypeEnumMemberImpl::TypeEnumMemberImpl (const lldb::TypeImplSP &integer_type_sp, - const ConstString &name, - const llvm::APSInt &value) : - m_integer_type_sp(integer_type_sp), - m_name(name), - m_value(value), - m_valid((bool)name && (bool)integer_type_sp) +CompilerType TypeMemberFunctionImpl::GetType() const { return m_type; } -{ +lldb::MemberFunctionKind TypeMemberFunctionImpl::GetKind() const { + return m_kind; } + +bool TypeMemberFunctionImpl::GetDescription(Stream &stream) { + switch (m_kind) { + case lldb::eMemberFunctionKindUnknown: + return false; + case lldb::eMemberFunctionKindConstructor: + stream.Printf("constructor for %s", + m_type.GetTypeName().AsCString("<unknown>")); + break; + case lldb::eMemberFunctionKindDestructor: + stream.Printf("destructor for %s", + m_type.GetTypeName().AsCString("<unknown>")); + break; + case lldb::eMemberFunctionKindInstanceMethod: + stream.Printf("instance method %s of type %s", m_name.AsCString(), + m_decl.GetDeclContext().GetName().AsCString()); + break; + case lldb::eMemberFunctionKindStaticMethod: + stream.Printf("static method %s of type %s", m_name.AsCString(), + m_decl.GetDeclContext().GetName().AsCString()); + break; + } + return true; +} + +CompilerType TypeMemberFunctionImpl::GetReturnType() const { + if (m_type) + return m_type.GetFunctionReturnType(); + return m_decl.GetFunctionReturnType(); +} + +size_t TypeMemberFunctionImpl::GetNumArguments() const { + if (m_type) + return m_type.GetNumberOfFunctionArguments(); + else + return m_decl.GetNumFunctionArguments(); +} + +CompilerType TypeMemberFunctionImpl::GetArgumentAtIndex(size_t idx) const { + if (m_type) + return m_type.GetFunctionArgumentAtIndex(idx); + else + return m_decl.GetFunctionArgumentType(idx); +} + +TypeEnumMemberImpl::TypeEnumMemberImpl(const lldb::TypeImplSP &integer_type_sp, + const ConstString &name, + const llvm::APSInt &value) + : m_integer_type_sp(integer_type_sp), m_name(name), m_value(value), + m_valid((bool)name && (bool)integer_type_sp) + +{} diff --git a/lldb/source/Symbol/TypeList.cpp b/lldb/source/Symbol/TypeList.cpp index f181dd66463..4d32afcb051 100644 --- a/lldb/source/Symbol/TypeList.cpp +++ b/lldb/source/Symbol/TypeList.cpp @@ -7,7 +7,6 @@ // //===----------------------------------------------------------------------===// - // C Includes // C++ Includes #include <vector> @@ -25,31 +24,24 @@ using namespace lldb; using namespace lldb_private; -TypeList::TypeList() : - m_types () -{ -} +TypeList::TypeList() : m_types() {} //---------------------------------------------------------------------- // Destructor //---------------------------------------------------------------------- -TypeList::~TypeList() -{ -} +TypeList::~TypeList() {} -void -TypeList::Insert (const TypeSP& type_sp) -{ - // Just push each type on the back for now. We will worry about uniquing later - if (type_sp) - m_types.push_back(type_sp); +void TypeList::Insert(const TypeSP &type_sp) { + // Just push each type on the back for now. We will worry about uniquing later + if (type_sp) + m_types.push_back(type_sp); } //---------------------------------------------------------------------- // Find a base type by its unique ID. //---------------------------------------------------------------------- -//TypeSP -//TypeList::FindType(lldb::user_id_t uid) +// TypeSP +// TypeList::FindType(lldb::user_id_t uid) //{ // iterator pos = m_types.find(uid); // if (pos != m_types.end()) @@ -60,8 +52,8 @@ TypeList::Insert (const TypeSP& type_sp) //---------------------------------------------------------------------- // Find a type by name. //---------------------------------------------------------------------- -//TypeList -//TypeList::FindTypes (const ConstString &name) +// TypeList +// TypeList::FindTypes (const ConstString &name) //{ // // Do we ever need to make a lookup by name map? Here we are doing // // a linear search which isn't going to be fast. @@ -73,194 +65,158 @@ TypeList::Insert (const TypeSP& type_sp) // return types; //} -void -TypeList::Clear() -{ - m_types.clear(); -} +void TypeList::Clear() { m_types.clear(); } -uint32_t -TypeList::GetSize() const -{ - return m_types.size(); -} +uint32_t TypeList::GetSize() const { return m_types.size(); } // GetTypeAtIndex isn't used a lot for large type lists, currently only for // type lists that are returned for "image dump -t TYPENAME" commands and other // simple symbol queries that grab the first result... -TypeSP -TypeList::GetTypeAtIndex(uint32_t idx) -{ - iterator pos, end; - uint32_t i = idx; - for (pos = m_types.begin(), end = m_types.end(); pos != end; ++pos) - { - if (i == 0) - return *pos; - --i; - } - return TypeSP(); +TypeSP TypeList::GetTypeAtIndex(uint32_t idx) { + iterator pos, end; + uint32_t i = idx; + for (pos = m_types.begin(), end = m_types.end(); pos != end; ++pos) { + if (i == 0) + return *pos; + --i; + } + return TypeSP(); } -void -TypeList::ForEach (std::function <bool(const lldb::TypeSP &type_sp)> const &callback) const -{ - for (auto pos = m_types.begin(), end = m_types.end(); pos != end; ++pos) - { - if (!callback(*pos)) - break; - } +void TypeList::ForEach( + std::function<bool(const lldb::TypeSP &type_sp)> const &callback) const { + for (auto pos = m_types.begin(), end = m_types.end(); pos != end; ++pos) { + if (!callback(*pos)) + break; + } } -void -TypeList::ForEach (std::function <bool(lldb::TypeSP &type_sp)> const &callback) -{ - for (auto pos = m_types.begin(), end = m_types.end(); pos != end; ++pos) - { - if (!callback(*pos)) - break; - } +void TypeList::ForEach( + std::function<bool(lldb::TypeSP &type_sp)> const &callback) { + for (auto pos = m_types.begin(), end = m_types.end(); pos != end; ++pos) { + if (!callback(*pos)) + break; + } } -void -TypeList::Dump(Stream *s, bool show_context) -{ - for (iterator pos = m_types.begin(), end = m_types.end(); pos != end; ++pos) - { - pos->get()->Dump(s, show_context); - } +void TypeList::Dump(Stream *s, bool show_context) { + for (iterator pos = m_types.begin(), end = m_types.end(); pos != end; ++pos) { + pos->get()->Dump(s, show_context); + } } -void -TypeList::RemoveMismatchedTypes (const char *qualified_typename, - bool exact_match) -{ - std::string type_scope; - std::string type_basename; - TypeClass type_class = eTypeClassAny; - if (!Type::GetTypeScopeAndBasename (qualified_typename, type_scope, type_basename, type_class)) - { - type_basename = qualified_typename; - type_scope.clear(); - } - return RemoveMismatchedTypes (type_scope, type_basename, type_class, exact_match); +void TypeList::RemoveMismatchedTypes(const char *qualified_typename, + bool exact_match) { + std::string type_scope; + std::string type_basename; + TypeClass type_class = eTypeClassAny; + if (!Type::GetTypeScopeAndBasename(qualified_typename, type_scope, + type_basename, type_class)) { + type_basename = qualified_typename; + type_scope.clear(); + } + return RemoveMismatchedTypes(type_scope, type_basename, type_class, + exact_match); } -void -TypeList::RemoveMismatchedTypes (const std::string &type_scope, - const std::string &type_basename, - TypeClass type_class, - bool exact_match) -{ - // Our "collection" type currently is a std::map which doesn't - // have any good way to iterate and remove items from the map - // so we currently just make a new list and add all of the matching - // types to it, and then swap it into m_types at the end - collection matching_types; - - iterator pos, end = m_types.end(); - - for (pos = m_types.begin(); pos != end; ++pos) - { - Type* the_type = pos->get(); - bool keep_match = false; - TypeClass match_type_class = eTypeClassAny; - - if (type_class != eTypeClassAny) - { - match_type_class = the_type->GetForwardCompilerType ().GetTypeClass (); - if ((match_type_class & type_class) == 0) - continue; - } +void TypeList::RemoveMismatchedTypes(const std::string &type_scope, + const std::string &type_basename, + TypeClass type_class, bool exact_match) { + // Our "collection" type currently is a std::map which doesn't + // have any good way to iterate and remove items from the map + // so we currently just make a new list and add all of the matching + // types to it, and then swap it into m_types at the end + collection matching_types; + + iterator pos, end = m_types.end(); + + for (pos = m_types.begin(); pos != end; ++pos) { + Type *the_type = pos->get(); + bool keep_match = false; + TypeClass match_type_class = eTypeClassAny; + + if (type_class != eTypeClassAny) { + match_type_class = the_type->GetForwardCompilerType().GetTypeClass(); + if ((match_type_class & type_class) == 0) + continue; + } - ConstString match_type_name_const_str (the_type->GetQualifiedName()); - if (match_type_name_const_str) - { - const char *match_type_name = match_type_name_const_str.GetCString(); - std::string match_type_scope; - std::string match_type_basename; - if (Type::GetTypeScopeAndBasename (match_type_name, - match_type_scope, - match_type_basename, - match_type_class)) - { - if (match_type_basename == type_basename) - { - const size_t type_scope_size = type_scope.size(); - const size_t match_type_scope_size = match_type_scope.size(); - if (exact_match || (type_scope_size == match_type_scope_size)) - { - keep_match = match_type_scope == type_scope; - } - else - { - if (match_type_scope_size > type_scope_size) - { - const size_t type_scope_pos = match_type_scope.rfind(type_scope); - if (type_scope_pos == match_type_scope_size - type_scope_size) - { - if (type_scope_pos >= 2) - { - // Our match scope ends with the type scope we were looking for, - // but we need to make sure what comes before the matching - // type scope is a namespace boundary in case we are trying to match: - // type_basename = "d" - // type_scope = "b::c::" - // We want to match: - // match_type_scope "a::b::c::" - // But not: - // match_type_scope "a::bb::c::" - // So below we make sure what comes before "b::c::" in match_type_scope - // is "::", or the namespace boundary - if (match_type_scope[type_scope_pos - 1] == ':' && - match_type_scope[type_scope_pos - 2] == ':') - { - keep_match = true; - } - } - } - } - } + ConstString match_type_name_const_str(the_type->GetQualifiedName()); + if (match_type_name_const_str) { + const char *match_type_name = match_type_name_const_str.GetCString(); + std::string match_type_scope; + std::string match_type_basename; + if (Type::GetTypeScopeAndBasename(match_type_name, match_type_scope, + match_type_basename, + match_type_class)) { + if (match_type_basename == type_basename) { + const size_t type_scope_size = type_scope.size(); + const size_t match_type_scope_size = match_type_scope.size(); + if (exact_match || (type_scope_size == match_type_scope_size)) { + keep_match = match_type_scope == type_scope; + } else { + if (match_type_scope_size > type_scope_size) { + const size_t type_scope_pos = match_type_scope.rfind(type_scope); + if (type_scope_pos == match_type_scope_size - type_scope_size) { + if (type_scope_pos >= 2) { + // Our match scope ends with the type scope we were looking + // for, + // but we need to make sure what comes before the matching + // type scope is a namespace boundary in case we are trying to + // match: + // type_basename = "d" + // type_scope = "b::c::" + // We want to match: + // match_type_scope "a::b::c::" + // But not: + // match_type_scope "a::bb::c::" + // So below we make sure what comes before "b::c::" in + // match_type_scope + // is "::", or the namespace boundary + if (match_type_scope[type_scope_pos - 1] == ':' && + match_type_scope[type_scope_pos - 2] == ':') { + keep_match = true; + } } + } } - else - { - // The type we are currently looking at doesn't exists - // in a namespace or class, so it only matches if there - // is no type scope... - keep_match = type_scope.empty() && type_basename.compare(match_type_name) == 0; - } - } - - if (keep_match) - { - matching_types.push_back(*pos); + } } + } else { + // The type we are currently looking at doesn't exists + // in a namespace or class, so it only matches if there + // is no type scope... + keep_match = + type_scope.empty() && type_basename.compare(match_type_name) == 0; + } } - m_types.swap(matching_types); -} - -void -TypeList::RemoveMismatchedTypes (TypeClass type_class) -{ - if (type_class == eTypeClassAny) - return; - // Our "collection" type currently is a std::map which doesn't - // have any good way to iterate and remove items from the map - // so we currently just make a new list and add all of the matching - // types to it, and then swap it into m_types at the end - collection matching_types; - - iterator pos, end = m_types.end(); - - for (pos = m_types.begin(); pos != end; ++pos) - { - Type* the_type = pos->get(); - TypeClass match_type_class = the_type->GetForwardCompilerType ().GetTypeClass (); - if (match_type_class & type_class) - matching_types.push_back (*pos); + if (keep_match) { + matching_types.push_back(*pos); } - m_types.swap(matching_types); + } + m_types.swap(matching_types); +} + +void TypeList::RemoveMismatchedTypes(TypeClass type_class) { + if (type_class == eTypeClassAny) + return; + + // Our "collection" type currently is a std::map which doesn't + // have any good way to iterate and remove items from the map + // so we currently just make a new list and add all of the matching + // types to it, and then swap it into m_types at the end + collection matching_types; + + iterator pos, end = m_types.end(); + + for (pos = m_types.begin(); pos != end; ++pos) { + Type *the_type = pos->get(); + TypeClass match_type_class = + the_type->GetForwardCompilerType().GetTypeClass(); + if (match_type_class & type_class) + matching_types.push_back(*pos); + } + m_types.swap(matching_types); } diff --git a/lldb/source/Symbol/TypeMap.cpp b/lldb/source/Symbol/TypeMap.cpp index 6dc22ccbda9..21eb611e7b8 100644 --- a/lldb/source/Symbol/TypeMap.cpp +++ b/lldb/source/Symbol/TypeMap.cpp @@ -7,7 +7,6 @@ // //===----------------------------------------------------------------------===// - // C Includes // C++ Includes #include <vector> @@ -38,50 +37,39 @@ using namespace lldb; using namespace lldb_private; using namespace clang; -TypeMap::TypeMap() : - m_types () -{ -} +TypeMap::TypeMap() : m_types() {} //---------------------------------------------------------------------- // Destructor //---------------------------------------------------------------------- -TypeMap::~TypeMap() -{ -} +TypeMap::~TypeMap() {} -void -TypeMap::Insert (const TypeSP& type_sp) -{ - // Just push each type on the back for now. We will worry about uniquing later - if (type_sp) - m_types.insert(std::make_pair(type_sp->GetID(), type_sp)); +void TypeMap::Insert(const TypeSP &type_sp) { + // Just push each type on the back for now. We will worry about uniquing later + if (type_sp) + m_types.insert(std::make_pair(type_sp->GetID(), type_sp)); } +bool TypeMap::InsertUnique(const TypeSP &type_sp) { + if (type_sp) { + user_id_t type_uid = type_sp->GetID(); + iterator pos, end = m_types.end(); -bool -TypeMap::InsertUnique (const TypeSP& type_sp) -{ - if (type_sp) - { - user_id_t type_uid = type_sp->GetID(); - iterator pos, end = m_types.end(); - - for (pos = m_types.find(type_uid); pos != end && pos->second->GetID() == type_uid; ++pos) - { - if (pos->second.get() == type_sp.get()) - return false; - } - Insert (type_sp); + for (pos = m_types.find(type_uid); + pos != end && pos->second->GetID() == type_uid; ++pos) { + if (pos->second.get() == type_sp.get()) + return false; } - return true; + Insert(type_sp); + } + return true; } //---------------------------------------------------------------------- // Find a base type by its unique ID. //---------------------------------------------------------------------- -//TypeSP -//TypeMap::FindType(lldb::user_id_t uid) +// TypeSP +// TypeMap::FindType(lldb::user_id_t uid) //{ // iterator pos = m_types.find(uid); // if (pos != m_types.end()) @@ -92,8 +80,8 @@ TypeMap::InsertUnique (const TypeSP& type_sp) //---------------------------------------------------------------------- // Find a type by name. //---------------------------------------------------------------------- -//TypeMap -//TypeMap::FindTypes (const ConstString &name) +// TypeMap +// TypeMap::FindTypes (const ConstString &name) //{ // // Do we ever need to make a lookup by name map? Here we are doing // // a linear search which isn't going to be fast. @@ -105,218 +93,174 @@ TypeMap::InsertUnique (const TypeSP& type_sp) // return types; //} -void -TypeMap::Clear() -{ - m_types.clear(); -} +void TypeMap::Clear() { m_types.clear(); } -uint32_t -TypeMap::GetSize() const -{ - return m_types.size(); -} +uint32_t TypeMap::GetSize() const { return m_types.size(); } -bool -TypeMap::Empty() const -{ - return m_types.empty(); -} +bool TypeMap::Empty() const { return m_types.empty(); } // GetTypeAtIndex isn't used a lot for large type lists, currently only for // type lists that are returned for "image dump -t TYPENAME" commands and other // simple symbol queries that grab the first result... -TypeSP -TypeMap::GetTypeAtIndex(uint32_t idx) -{ - iterator pos, end; - uint32_t i = idx; - for (pos = m_types.begin(), end = m_types.end(); pos != end; ++pos) - { - if (i == 0) - return pos->second; - --i; - } - return TypeSP(); +TypeSP TypeMap::GetTypeAtIndex(uint32_t idx) { + iterator pos, end; + uint32_t i = idx; + for (pos = m_types.begin(), end = m_types.end(); pos != end; ++pos) { + if (i == 0) + return pos->second; + --i; + } + return TypeSP(); } -void -TypeMap::ForEach (std::function <bool(const lldb::TypeSP &type_sp)> const &callback) const -{ - for (auto pos = m_types.begin(), end = m_types.end(); pos != end; ++pos) - { - if (!callback(pos->second)) - break; - } +void TypeMap::ForEach( + std::function<bool(const lldb::TypeSP &type_sp)> const &callback) const { + for (auto pos = m_types.begin(), end = m_types.end(); pos != end; ++pos) { + if (!callback(pos->second)) + break; + } } -void -TypeMap::ForEach (std::function <bool(lldb::TypeSP &type_sp)> const &callback) -{ - for (auto pos = m_types.begin(), end = m_types.end(); pos != end; ++pos) - { - if (!callback(pos->second)) - break; - } +void TypeMap::ForEach( + std::function<bool(lldb::TypeSP &type_sp)> const &callback) { + for (auto pos = m_types.begin(), end = m_types.end(); pos != end; ++pos) { + if (!callback(pos->second)) + break; + } } -bool -TypeMap::Remove (const lldb::TypeSP &type_sp) -{ - if (type_sp) - { - lldb::user_id_t uid = type_sp->GetID(); - for (iterator pos = m_types.find(uid), end = m_types.end(); pos != end && pos->first == uid; ++pos) - { - if (pos->second == type_sp) - { - m_types.erase(pos); - return true; - } - } +bool TypeMap::Remove(const lldb::TypeSP &type_sp) { + if (type_sp) { + lldb::user_id_t uid = type_sp->GetID(); + for (iterator pos = m_types.find(uid), end = m_types.end(); + pos != end && pos->first == uid; ++pos) { + if (pos->second == type_sp) { + m_types.erase(pos); + return true; + } } - return false; + } + return false; } -void -TypeMap::Dump(Stream *s, bool show_context) -{ - for (iterator pos = m_types.begin(), end = m_types.end(); pos != end; ++pos) - { - pos->second->Dump(s, show_context); - } +void TypeMap::Dump(Stream *s, bool show_context) { + for (iterator pos = m_types.begin(), end = m_types.end(); pos != end; ++pos) { + pos->second->Dump(s, show_context); + } } -void -TypeMap::RemoveMismatchedTypes (const char *qualified_typename, - bool exact_match) -{ - std::string type_scope; - std::string type_basename; - TypeClass type_class = eTypeClassAny; - if (!Type::GetTypeScopeAndBasename (qualified_typename, type_scope, type_basename, type_class)) - { - type_basename = qualified_typename; - type_scope.clear(); - } - return RemoveMismatchedTypes (type_scope, type_basename, type_class, exact_match); +void TypeMap::RemoveMismatchedTypes(const char *qualified_typename, + bool exact_match) { + std::string type_scope; + std::string type_basename; + TypeClass type_class = eTypeClassAny; + if (!Type::GetTypeScopeAndBasename(qualified_typename, type_scope, + type_basename, type_class)) { + type_basename = qualified_typename; + type_scope.clear(); + } + return RemoveMismatchedTypes(type_scope, type_basename, type_class, + exact_match); } -void -TypeMap::RemoveMismatchedTypes (const std::string &type_scope, - const std::string &type_basename, - TypeClass type_class, - bool exact_match) -{ - // Our "collection" type currently is a std::map which doesn't - // have any good way to iterate and remove items from the map - // so we currently just make a new list and add all of the matching - // types to it, and then swap it into m_types at the end - collection matching_types; +void TypeMap::RemoveMismatchedTypes(const std::string &type_scope, + const std::string &type_basename, + TypeClass type_class, bool exact_match) { + // Our "collection" type currently is a std::map which doesn't + // have any good way to iterate and remove items from the map + // so we currently just make a new list and add all of the matching + // types to it, and then swap it into m_types at the end + collection matching_types; - iterator pos, end = m_types.end(); - - for (pos = m_types.begin(); pos != end; ++pos) - { - Type* the_type = pos->second.get(); - bool keep_match = false; - TypeClass match_type_class = eTypeClassAny; - - if (type_class != eTypeClassAny) - { - match_type_class = the_type->GetForwardCompilerType ().GetTypeClass (); - if ((match_type_class & type_class) == 0) - continue; - } + iterator pos, end = m_types.end(); - ConstString match_type_name_const_str (the_type->GetQualifiedName()); - if (match_type_name_const_str) - { - const char *match_type_name = match_type_name_const_str.GetCString(); - std::string match_type_scope; - std::string match_type_basename; - if (Type::GetTypeScopeAndBasename (match_type_name, - match_type_scope, - match_type_basename, - match_type_class)) - { - if (match_type_basename == type_basename) - { - const size_t type_scope_size = type_scope.size(); - const size_t match_type_scope_size = match_type_scope.size(); - if (exact_match || (type_scope_size == match_type_scope_size)) - { - keep_match = match_type_scope == type_scope; - } - else - { - if (match_type_scope_size > type_scope_size) - { - const size_t type_scope_pos = match_type_scope.rfind(type_scope); - if (type_scope_pos == match_type_scope_size - type_scope_size) - { - if (type_scope_pos >= 2) - { - // Our match scope ends with the type scope we were looking for, - // but we need to make sure what comes before the matching - // type scope is a namespace boundary in case we are trying to match: - // type_basename = "d" - // type_scope = "b::c::" - // We want to match: - // match_type_scope "a::b::c::" - // But not: - // match_type_scope "a::bb::c::" - // So below we make sure what comes before "b::c::" in match_type_scope - // is "::", or the namespace boundary - if (match_type_scope[type_scope_pos - 1] == ':' && - match_type_scope[type_scope_pos - 2] == ':') - { - keep_match = true; - } - } - } - } - } + for (pos = m_types.begin(); pos != end; ++pos) { + Type *the_type = pos->second.get(); + bool keep_match = false; + TypeClass match_type_class = eTypeClassAny; + + if (type_class != eTypeClassAny) { + match_type_class = the_type->GetForwardCompilerType().GetTypeClass(); + if ((match_type_class & type_class) == 0) + continue; + } + + ConstString match_type_name_const_str(the_type->GetQualifiedName()); + if (match_type_name_const_str) { + const char *match_type_name = match_type_name_const_str.GetCString(); + std::string match_type_scope; + std::string match_type_basename; + if (Type::GetTypeScopeAndBasename(match_type_name, match_type_scope, + match_type_basename, + match_type_class)) { + if (match_type_basename == type_basename) { + const size_t type_scope_size = type_scope.size(); + const size_t match_type_scope_size = match_type_scope.size(); + if (exact_match || (type_scope_size == match_type_scope_size)) { + keep_match = match_type_scope == type_scope; + } else { + if (match_type_scope_size > type_scope_size) { + const size_t type_scope_pos = match_type_scope.rfind(type_scope); + if (type_scope_pos == match_type_scope_size - type_scope_size) { + if (type_scope_pos >= 2) { + // Our match scope ends with the type scope we were looking + // for, + // but we need to make sure what comes before the matching + // type scope is a namespace boundary in case we are trying to + // match: + // type_basename = "d" + // type_scope = "b::c::" + // We want to match: + // match_type_scope "a::b::c::" + // But not: + // match_type_scope "a::bb::c::" + // So below we make sure what comes before "b::c::" in + // match_type_scope + // is "::", or the namespace boundary + if (match_type_scope[type_scope_pos - 1] == ':' && + match_type_scope[type_scope_pos - 2] == ':') { + keep_match = true; + } } + } } - else - { - // The type we are currently looking at doesn't exists - // in a namespace or class, so it only matches if there - // is no type scope... - keep_match = type_scope.empty() && type_basename.compare(match_type_name) == 0; - } - } - - if (keep_match) - { - matching_types.insert (*pos); + } } + } else { + // The type we are currently looking at doesn't exists + // in a namespace or class, so it only matches if there + // is no type scope... + keep_match = + type_scope.empty() && type_basename.compare(match_type_name) == 0; + } } - m_types.swap(matching_types); -} -void -TypeMap::RemoveMismatchedTypes (TypeClass type_class) -{ - if (type_class == eTypeClassAny) - return; - - // Our "collection" type currently is a std::map which doesn't - // have any good way to iterate and remove items from the map - // so we currently just make a new list and add all of the matching - // types to it, and then swap it into m_types at the end - collection matching_types; - - iterator pos, end = m_types.end(); - - for (pos = m_types.begin(); pos != end; ++pos) - { - Type* the_type = pos->second.get(); - TypeClass match_type_class = the_type->GetForwardCompilerType ().GetTypeClass (); - if (match_type_class & type_class) - matching_types.insert (*pos); + if (keep_match) { + matching_types.insert(*pos); } - m_types.swap(matching_types); + } + m_types.swap(matching_types); +} + +void TypeMap::RemoveMismatchedTypes(TypeClass type_class) { + if (type_class == eTypeClassAny) + return; + + // Our "collection" type currently is a std::map which doesn't + // have any good way to iterate and remove items from the map + // so we currently just make a new list and add all of the matching + // types to it, and then swap it into m_types at the end + collection matching_types; + + iterator pos, end = m_types.end(); + + for (pos = m_types.begin(); pos != end; ++pos) { + Type *the_type = pos->second.get(); + TypeClass match_type_class = + the_type->GetForwardCompilerType().GetTypeClass(); + if (match_type_class & type_class) + matching_types.insert(*pos); + } + m_types.swap(matching_types); } diff --git a/lldb/source/Symbol/TypeSystem.cpp b/lldb/source/Symbol/TypeSystem.cpp index 3aadcaa0c64..3f68f6234c3 100644 --- a/lldb/source/Symbol/TypeSystem.cpp +++ b/lldb/source/Symbol/TypeSystem.cpp @@ -15,278 +15,224 @@ using namespace lldb_private; -TypeSystem::TypeSystem(LLVMCastKind kind) : - m_kind (kind), - m_sym_file (nullptr) -{ -} +TypeSystem::TypeSystem(LLVMCastKind kind) : m_kind(kind), m_sym_file(nullptr) {} -TypeSystem::~TypeSystem() -{ -} +TypeSystem::~TypeSystem() {} -lldb::TypeSystemSP -TypeSystem::CreateInstance (lldb::LanguageType language, Module *module) -{ - uint32_t i = 0; - TypeSystemCreateInstance create_callback; - while ((create_callback = PluginManager::GetTypeSystemCreateCallbackAtIndex (i++)) != nullptr) - { - lldb::TypeSystemSP type_system_sp = create_callback(language, module, nullptr); - if (type_system_sp) - return type_system_sp; - } +lldb::TypeSystemSP TypeSystem::CreateInstance(lldb::LanguageType language, + Module *module) { + uint32_t i = 0; + TypeSystemCreateInstance create_callback; + while ((create_callback = PluginManager::GetTypeSystemCreateCallbackAtIndex( + i++)) != nullptr) { + lldb::TypeSystemSP type_system_sp = + create_callback(language, module, nullptr); + if (type_system_sp) + return type_system_sp; + } - return lldb::TypeSystemSP(); + return lldb::TypeSystemSP(); } -lldb::TypeSystemSP -TypeSystem::CreateInstance (lldb::LanguageType language, Target *target) -{ - uint32_t i = 0; - TypeSystemCreateInstance create_callback; - while ((create_callback = PluginManager::GetTypeSystemCreateCallbackAtIndex (i++)) != nullptr) - { - lldb::TypeSystemSP type_system_sp = create_callback(language, nullptr, target); - if (type_system_sp) - return type_system_sp; - } +lldb::TypeSystemSP TypeSystem::CreateInstance(lldb::LanguageType language, + Target *target) { + uint32_t i = 0; + TypeSystemCreateInstance create_callback; + while ((create_callback = PluginManager::GetTypeSystemCreateCallbackAtIndex( + i++)) != nullptr) { + lldb::TypeSystemSP type_system_sp = + create_callback(language, nullptr, target); + if (type_system_sp) + return type_system_sp; + } - return lldb::TypeSystemSP(); + return lldb::TypeSystemSP(); } -bool -TypeSystem::IsAnonymousType (lldb::opaque_compiler_type_t type) -{ - return false; +bool TypeSystem::IsAnonymousType(lldb::opaque_compiler_type_t type) { + return false; } -CompilerType -TypeSystem::GetArrayType (lldb::opaque_compiler_type_t type, uint64_t size) -{ - return CompilerType(); +CompilerType TypeSystem::GetArrayType(lldb::opaque_compiler_type_t type, + uint64_t size) { + return CompilerType(); } CompilerType -TypeSystem::GetLValueReferenceType (lldb::opaque_compiler_type_t type) -{ - return CompilerType(); +TypeSystem::GetLValueReferenceType(lldb::opaque_compiler_type_t type) { + return CompilerType(); } CompilerType -TypeSystem::GetRValueReferenceType (lldb::opaque_compiler_type_t type) -{ - return CompilerType(); +TypeSystem::GetRValueReferenceType(lldb::opaque_compiler_type_t type) { + return CompilerType(); } -CompilerType -TypeSystem::AddConstModifier (lldb::opaque_compiler_type_t type) -{ - return CompilerType(); +CompilerType TypeSystem::AddConstModifier(lldb::opaque_compiler_type_t type) { + return CompilerType(); } CompilerType -TypeSystem::AddVolatileModifier (lldb::opaque_compiler_type_t type) -{ - return CompilerType(); +TypeSystem::AddVolatileModifier(lldb::opaque_compiler_type_t type) { + return CompilerType(); } CompilerType -TypeSystem::AddRestrictModifier (lldb::opaque_compiler_type_t type) -{ - return CompilerType(); +TypeSystem::AddRestrictModifier(lldb::opaque_compiler_type_t type) { + return CompilerType(); } -CompilerType -TypeSystem::CreateTypedef (lldb::opaque_compiler_type_t type, const char *name, const CompilerDeclContext &decl_ctx) -{ - return CompilerType(); +CompilerType TypeSystem::CreateTypedef(lldb::opaque_compiler_type_t type, + const char *name, + const CompilerDeclContext &decl_ctx) { + return CompilerType(); } -CompilerType -TypeSystem::GetBuiltinTypeByName (const ConstString &name) -{ - return CompilerType(); +CompilerType TypeSystem::GetBuiltinTypeByName(const ConstString &name) { + return CompilerType(); } -CompilerType -TypeSystem::GetTypeForFormatters (void* type) -{ - return CompilerType(this, type); +CompilerType TypeSystem::GetTypeForFormatters(void *type) { + return CompilerType(this, type); } -LazyBool -TypeSystem::ShouldPrintAsOneLiner (void* type, ValueObject* valobj) -{ - return eLazyBoolCalculate; +LazyBool TypeSystem::ShouldPrintAsOneLiner(void *type, ValueObject *valobj) { + return eLazyBoolCalculate; } -bool -TypeSystem::IsMeaninglessWithoutDynamicResolution (void* type) -{ - return false; +bool TypeSystem::IsMeaninglessWithoutDynamicResolution(void *type) { + return false; } -ConstString -TypeSystem::DeclGetMangledName (void *opaque_decl) -{ - return ConstString(); +ConstString TypeSystem::DeclGetMangledName(void *opaque_decl) { + return ConstString(); } -CompilerDeclContext -TypeSystem::DeclGetDeclContext (void *opaque_decl) -{ - return CompilerDeclContext(); +CompilerDeclContext TypeSystem::DeclGetDeclContext(void *opaque_decl) { + return CompilerDeclContext(); } -CompilerType -TypeSystem::DeclGetFunctionReturnType(void *opaque_decl) -{ - return CompilerType(); +CompilerType TypeSystem::DeclGetFunctionReturnType(void *opaque_decl) { + return CompilerType(); } -size_t -TypeSystem::DeclGetFunctionNumArguments(void *opaque_decl) -{ - return 0; -} +size_t TypeSystem::DeclGetFunctionNumArguments(void *opaque_decl) { return 0; } -CompilerType -TypeSystem::DeclGetFunctionArgumentType (void *opaque_decl, size_t arg_idx) -{ - return CompilerType(); +CompilerType TypeSystem::DeclGetFunctionArgumentType(void *opaque_decl, + size_t arg_idx) { + return CompilerType(); } - std::vector<CompilerDecl> -TypeSystem::DeclContextFindDeclByName (void *opaque_decl_ctx, - ConstString name, - bool ignore_imported_decls) -{ - return std::vector<CompilerDecl>(); +TypeSystem::DeclContextFindDeclByName(void *opaque_decl_ctx, ConstString name, + bool ignore_imported_decls) { + return std::vector<CompilerDecl>(); } - #pragma mark TypeSystemMap -TypeSystemMap::TypeSystemMap() : m_mutex(), m_map(), m_clear_in_progress(false) -{ -} +TypeSystemMap::TypeSystemMap() + : m_mutex(), m_map(), m_clear_in_progress(false) {} -TypeSystemMap::~TypeSystemMap() -{ -} +TypeSystemMap::~TypeSystemMap() {} -void -TypeSystemMap::Clear () -{ - collection map; - { - std::lock_guard<std::mutex> guard(m_mutex); - map = m_map; - m_clear_in_progress = true; +void TypeSystemMap::Clear() { + collection map; + { + std::lock_guard<std::mutex> guard(m_mutex); + map = m_map; + m_clear_in_progress = true; + } + std::set<TypeSystem *> visited; + for (auto pair : map) { + TypeSystem *type_system = pair.second.get(); + if (type_system && !visited.count(type_system)) { + visited.insert(type_system); + type_system->Finalize(); } - std::set<TypeSystem *> visited; - for (auto pair : map) - { - TypeSystem *type_system = pair.second.get(); - if (type_system && !visited.count(type_system)) - { - visited.insert(type_system); - type_system->Finalize(); - } + } + map.clear(); + { + std::lock_guard<std::mutex> guard(m_mutex); + m_map.clear(); + m_clear_in_progress = false; + } +} + +void TypeSystemMap::ForEach(std::function<bool(TypeSystem *)> const &callback) { + std::lock_guard<std::mutex> guard(m_mutex); + // Use a std::set so we only call the callback once for each unique + // TypeSystem instance + std::set<TypeSystem *> visited; + for (auto pair : m_map) { + TypeSystem *type_system = pair.second.get(); + if (type_system && !visited.count(type_system)) { + visited.insert(type_system); + if (callback(type_system) == false) + break; } - map.clear(); - { - std::lock_guard<std::mutex> guard(m_mutex); - m_map.clear(); - m_clear_in_progress = false; + } +} + +TypeSystem *TypeSystemMap::GetTypeSystemForLanguage(lldb::LanguageType language, + Module *module, + bool can_create) { + std::lock_guard<std::mutex> guard(m_mutex); + collection::iterator pos = m_map.find(language); + if (pos != m_map.end()) + return pos->second.get(); + + for (const auto &pair : m_map) { + if (pair.second && pair.second->SupportsLanguage(language)) { + // Add a new mapping for "language" to point to an already existing + // TypeSystem that supports this language + AddToMap(language, pair.second); + return pair.second.get(); } -} + } + if (!can_create) + return nullptr; -void -TypeSystemMap::ForEach (std::function <bool(TypeSystem *)> const &callback) -{ - std::lock_guard<std::mutex> guard(m_mutex); - // Use a std::set so we only call the callback once for each unique - // TypeSystem instance - std::set<TypeSystem *> visited; - for (auto pair : m_map) - { - TypeSystem *type_system = pair.second.get(); - if (type_system && !visited.count(type_system)) - { - visited.insert(type_system); - if (callback (type_system) == false) - break; - } - } + // Cache even if we get a shared pointer that contains null type system back + lldb::TypeSystemSP type_system_sp = + TypeSystem::CreateInstance(language, module); + AddToMap(language, type_system_sp); + return type_system_sp.get(); } -TypeSystem * -TypeSystemMap::GetTypeSystemForLanguage (lldb::LanguageType language, Module *module, bool can_create) -{ - std::lock_guard<std::mutex> guard(m_mutex); - collection::iterator pos = m_map.find(language); - if (pos != m_map.end()) - return pos->second.get(); - - for (const auto &pair : m_map) - { - if (pair.second && pair.second->SupportsLanguage(language)) - { - // Add a new mapping for "language" to point to an already existing - // TypeSystem that supports this language - AddToMap(language, pair.second); - return pair.second.get(); - } - } - - if (!can_create) - return nullptr; +TypeSystem *TypeSystemMap::GetTypeSystemForLanguage(lldb::LanguageType language, + Target *target, + bool can_create) { + std::lock_guard<std::mutex> guard(m_mutex); + collection::iterator pos = m_map.find(language); + if (pos != m_map.end()) + return pos->second.get(); - // Cache even if we get a shared pointer that contains null type system back - lldb::TypeSystemSP type_system_sp = TypeSystem::CreateInstance (language, module); - AddToMap (language, type_system_sp); - return type_system_sp.get(); -} + for (const auto &pair : m_map) { + if (pair.second && pair.second->SupportsLanguage(language)) { + // Add a new mapping for "language" to point to an already existing + // TypeSystem that supports this language -TypeSystem * -TypeSystemMap::GetTypeSystemForLanguage (lldb::LanguageType language, Target *target, bool can_create) -{ - std::lock_guard<std::mutex> guard(m_mutex); - collection::iterator pos = m_map.find(language); - if (pos != m_map.end()) - return pos->second.get(); - - for (const auto &pair : m_map) - { - if (pair.second && pair.second->SupportsLanguage(language)) - { - // Add a new mapping for "language" to point to an already existing - // TypeSystem that supports this language - - AddToMap(language, pair.second); - return pair.second.get(); - } + AddToMap(language, pair.second); + return pair.second.get(); } + } - if (!can_create) - return nullptr; + if (!can_create) + return nullptr; - // Cache even if we get a shared pointer that contains null type system back - lldb::TypeSystemSP type_system_sp; - if (!m_clear_in_progress) - type_system_sp = TypeSystem::CreateInstance (language, target); + // Cache even if we get a shared pointer that contains null type system back + lldb::TypeSystemSP type_system_sp; + if (!m_clear_in_progress) + type_system_sp = TypeSystem::CreateInstance(language, target); - AddToMap(language, type_system_sp); - return type_system_sp.get(); + AddToMap(language, type_system_sp); + return type_system_sp.get(); } -void -TypeSystemMap::AddToMap (lldb::LanguageType language, lldb::TypeSystemSP const &type_system_sp) -{ - if (!m_clear_in_progress) - m_map[language] = type_system_sp; +void TypeSystemMap::AddToMap(lldb::LanguageType language, + lldb::TypeSystemSP const &type_system_sp) { + if (!m_clear_in_progress) + m_map[language] = type_system_sp; } diff --git a/lldb/source/Symbol/UnwindPlan.cpp b/lldb/source/Symbol/UnwindPlan.cpp index 18f0cb7b9db..8a20ef8cce2 100644 --- a/lldb/source/Symbol/UnwindPlan.cpp +++ b/lldb/source/Symbol/UnwindPlan.cpp @@ -18,558 +18,497 @@ using namespace lldb; using namespace lldb_private; -bool -UnwindPlan::Row::RegisterLocation::operator == (const UnwindPlan::Row::RegisterLocation& rhs) const -{ - if (m_type == rhs.m_type) - { - switch (m_type) - { - case unspecified: - case undefined: - case same: - return true; - - case atCFAPlusOffset: - case isCFAPlusOffset: - return m_location.offset == rhs.m_location.offset; - - case inOtherRegister: - return m_location.reg_num == rhs.m_location.reg_num; - - case atDWARFExpression: - case isDWARFExpression: - if (m_location.expr.length == rhs.m_location.expr.length) - return !memcmp (m_location.expr.opcodes, rhs.m_location.expr.opcodes, m_location.expr.length); - break; - } +bool UnwindPlan::Row::RegisterLocation:: +operator==(const UnwindPlan::Row::RegisterLocation &rhs) const { + if (m_type == rhs.m_type) { + switch (m_type) { + case unspecified: + case undefined: + case same: + return true; + + case atCFAPlusOffset: + case isCFAPlusOffset: + return m_location.offset == rhs.m_location.offset; + + case inOtherRegister: + return m_location.reg_num == rhs.m_location.reg_num; + + case atDWARFExpression: + case isDWARFExpression: + if (m_location.expr.length == rhs.m_location.expr.length) + return !memcmp(m_location.expr.opcodes, rhs.m_location.expr.opcodes, + m_location.expr.length); + break; } - return false; + } + return false; } -// This function doesn't copy the dwarf expression bytes; they must remain in allocated +// This function doesn't copy the dwarf expression bytes; they must remain in +// allocated // memory for the lifespan of this UnwindPlan object. -void -UnwindPlan::Row::RegisterLocation::SetAtDWARFExpression (const uint8_t *opcodes, uint32_t len) -{ - m_type = atDWARFExpression; - m_location.expr.opcodes = opcodes; - m_location.expr.length = len; +void UnwindPlan::Row::RegisterLocation::SetAtDWARFExpression( + const uint8_t *opcodes, uint32_t len) { + m_type = atDWARFExpression; + m_location.expr.opcodes = opcodes; + m_location.expr.length = len; } -// This function doesn't copy the dwarf expression bytes; they must remain in allocated +// This function doesn't copy the dwarf expression bytes; they must remain in +// allocated // memory for the lifespan of this UnwindPlan object. -void -UnwindPlan::Row::RegisterLocation::SetIsDWARFExpression (const uint8_t *opcodes, uint32_t len) -{ - m_type = isDWARFExpression; - m_location.expr.opcodes = opcodes; - m_location.expr.length = len; -} - -void -UnwindPlan::Row::RegisterLocation::Dump (Stream &s, const UnwindPlan* unwind_plan, const UnwindPlan::Row* row, Thread* thread, bool verbose) const -{ - switch (m_type) - { - case unspecified: - if (verbose) - s.PutCString ("=<unspec>"); - else - s.PutCString ("=!"); - break; - case undefined: - if (verbose) - s.PutCString ("=<undef>"); - else - s.PutCString ("=?"); - break; - case same: - s.PutCString ("= <same>"); - break; - - case atCFAPlusOffset: - case isCFAPlusOffset: - { - s.PutChar('='); - if (m_type == atCFAPlusOffset) - s.PutChar('['); - s.Printf ("CFA%+d", m_location.offset); - if (m_type == atCFAPlusOffset) - s.PutChar(']'); - } - break; - - case inOtherRegister: - { - const RegisterInfo *other_reg_info = nullptr; - if (unwind_plan) - other_reg_info = unwind_plan->GetRegisterInfo (thread, m_location.reg_num); - if (other_reg_info) - s.Printf ("=%s", other_reg_info->name); - else - s.Printf ("=reg(%u)", m_location.reg_num); - } - break; - - case atDWARFExpression: - case isDWARFExpression: - { - s.PutChar('='); - if (m_type == atDWARFExpression) - s.PutCString("[dwarf-expr]"); - else - s.PutCString("dwarf-expr"); - } - break; - - } -} - -static void -DumpRegisterName (Stream &s, const UnwindPlan* unwind_plan, Thread *thread, uint32_t reg_num) { - const RegisterInfo *reg_info = unwind_plan->GetRegisterInfo (thread, reg_num); - if (reg_info) - s.PutCString (reg_info->name); +void UnwindPlan::Row::RegisterLocation::SetIsDWARFExpression( + const uint8_t *opcodes, uint32_t len) { + m_type = isDWARFExpression; + m_location.expr.opcodes = opcodes; + m_location.expr.length = len; +} + +void UnwindPlan::Row::RegisterLocation::Dump(Stream &s, + const UnwindPlan *unwind_plan, + const UnwindPlan::Row *row, + Thread *thread, + bool verbose) const { + switch (m_type) { + case unspecified: + if (verbose) + s.PutCString("=<unspec>"); else - s.Printf ("reg(%u)", reg_num); -} - -bool -UnwindPlan::Row::CFAValue::operator == (const UnwindPlan::Row::CFAValue& rhs) const -{ - if (m_type == rhs.m_type) - { - switch (m_type) - { - case unspecified: - return true; - - case isRegisterPlusOffset: - return m_value.reg.offset == rhs.m_value.reg.offset; - - case isRegisterDereferenced: - return m_value.reg.reg_num == rhs.m_value.reg.reg_num; - - case isDWARFExpression: - if (m_value.expr.length == rhs.m_value.expr.length) - return !memcmp (m_value.expr.opcodes, rhs.m_value.expr.opcodes, m_value.expr.length); - break; - } - } - return false; -} - -void -UnwindPlan::Row::CFAValue::Dump(Stream &s, const UnwindPlan* unwind_plan, Thread* thread) const -{ - switch(m_type) { - case isRegisterPlusOffset: - DumpRegisterName(s, unwind_plan, thread, m_value.reg.reg_num); - s.Printf ("%+3d", m_value.reg.offset); - break; - case isRegisterDereferenced: - s.PutChar ('['); - DumpRegisterName(s, unwind_plan, thread, m_value.reg.reg_num); - s.PutChar (']'); - break; - case isDWARFExpression: - s.PutCString ("dwarf-expr"); - break; - default: - s.PutCString ("unspecified"); - break; - } -} - -void -UnwindPlan::Row::Clear () -{ - m_cfa_value.SetUnspecified(); - m_offset = 0; - m_register_locations.clear(); -} - -void -UnwindPlan::Row::Dump (Stream& s, const UnwindPlan* unwind_plan, Thread* thread, addr_t base_addr) const -{ - if (base_addr != LLDB_INVALID_ADDRESS) - s.Printf ("0x%16.16" PRIx64 ": CFA=", base_addr + GetOffset()); + s.PutCString("=!"); + break; + case undefined: + if (verbose) + s.PutCString("=<undef>"); else - s.Printf ("%4" PRId64 ": CFA=", GetOffset()); - - m_cfa_value.Dump(s, unwind_plan, thread); - s.Printf(" => "); - for (collection::const_iterator idx = m_register_locations.begin (); idx != m_register_locations.end (); ++idx) - { - DumpRegisterName(s, unwind_plan, thread, idx->first); - const bool verbose = false; - idx->second.Dump(s, unwind_plan, this, thread, verbose); - s.PutChar (' '); - } - s.EOL(); -} - -UnwindPlan::Row::Row() : - m_offset (0), - m_cfa_value (), - m_register_locations () -{ -} - -bool -UnwindPlan::Row::GetRegisterInfo (uint32_t reg_num, UnwindPlan::Row::RegisterLocation& register_location) const -{ - collection::const_iterator pos = m_register_locations.find(reg_num); - if (pos != m_register_locations.end()) - { - register_location = pos->second; - return true; - } - return false; + s.PutCString("=?"); + break; + case same: + s.PutCString("= <same>"); + break; + + case atCFAPlusOffset: + case isCFAPlusOffset: { + s.PutChar('='); + if (m_type == atCFAPlusOffset) + s.PutChar('['); + s.Printf("CFA%+d", m_location.offset); + if (m_type == atCFAPlusOffset) + s.PutChar(']'); + } break; + + case inOtherRegister: { + const RegisterInfo *other_reg_info = nullptr; + if (unwind_plan) + other_reg_info = unwind_plan->GetRegisterInfo(thread, m_location.reg_num); + if (other_reg_info) + s.Printf("=%s", other_reg_info->name); + else + s.Printf("=reg(%u)", m_location.reg_num); + } break; + + case atDWARFExpression: + case isDWARFExpression: { + s.PutChar('='); + if (m_type == atDWARFExpression) + s.PutCString("[dwarf-expr]"); + else + s.PutCString("dwarf-expr"); + } break; + } } -void -UnwindPlan::Row::RemoveRegisterInfo (uint32_t reg_num) -{ - collection::const_iterator pos = m_register_locations.find(reg_num); - if (pos != m_register_locations.end()) - { - m_register_locations.erase(pos); - } +static void DumpRegisterName(Stream &s, const UnwindPlan *unwind_plan, + Thread *thread, uint32_t reg_num) { + const RegisterInfo *reg_info = unwind_plan->GetRegisterInfo(thread, reg_num); + if (reg_info) + s.PutCString(reg_info->name); + else + s.Printf("reg(%u)", reg_num); } -void -UnwindPlan::Row::SetRegisterInfo (uint32_t reg_num, const UnwindPlan::Row::RegisterLocation register_location) -{ - m_register_locations[reg_num] = register_location; -} +bool UnwindPlan::Row::CFAValue:: +operator==(const UnwindPlan::Row::CFAValue &rhs) const { + if (m_type == rhs.m_type) { + switch (m_type) { + case unspecified: + return true; -bool -UnwindPlan::Row::SetRegisterLocationToAtCFAPlusOffset (uint32_t reg_num, int32_t offset, bool can_replace) -{ - if (!can_replace && m_register_locations.find(reg_num) != m_register_locations.end()) - return false; - RegisterLocation reg_loc; - reg_loc.SetAtCFAPlusOffset(offset); - m_register_locations[reg_num] = reg_loc; - return true; -} + case isRegisterPlusOffset: + return m_value.reg.offset == rhs.m_value.reg.offset; -bool -UnwindPlan::Row::SetRegisterLocationToIsCFAPlusOffset (uint32_t reg_num, int32_t offset, bool can_replace) -{ - if (!can_replace && m_register_locations.find(reg_num) != m_register_locations.end()) - return false; - RegisterLocation reg_loc; - reg_loc.SetIsCFAPlusOffset(offset); - m_register_locations[reg_num] = reg_loc; - return true; -} + case isRegisterDereferenced: + return m_value.reg.reg_num == rhs.m_value.reg.reg_num; -bool -UnwindPlan::Row::SetRegisterLocationToUndefined (uint32_t reg_num, bool can_replace, bool can_replace_only_if_unspecified) -{ - collection::iterator pos = m_register_locations.find(reg_num); - collection::iterator end = m_register_locations.end(); - - if (pos != end) - { - if (!can_replace) - return false; - if (can_replace_only_if_unspecified && !pos->second.IsUnspecified()) - return false; + case isDWARFExpression: + if (m_value.expr.length == rhs.m_value.expr.length) + return !memcmp(m_value.expr.opcodes, rhs.m_value.expr.opcodes, + m_value.expr.length); + break; } - RegisterLocation reg_loc; - reg_loc.SetUndefined(); - m_register_locations[reg_num] = reg_loc; + } + return false; +} + +void UnwindPlan::Row::CFAValue::Dump(Stream &s, const UnwindPlan *unwind_plan, + Thread *thread) const { + switch (m_type) { + case isRegisterPlusOffset: + DumpRegisterName(s, unwind_plan, thread, m_value.reg.reg_num); + s.Printf("%+3d", m_value.reg.offset); + break; + case isRegisterDereferenced: + s.PutChar('['); + DumpRegisterName(s, unwind_plan, thread, m_value.reg.reg_num); + s.PutChar(']'); + break; + case isDWARFExpression: + s.PutCString("dwarf-expr"); + break; + default: + s.PutCString("unspecified"); + break; + } +} + +void UnwindPlan::Row::Clear() { + m_cfa_value.SetUnspecified(); + m_offset = 0; + m_register_locations.clear(); +} + +void UnwindPlan::Row::Dump(Stream &s, const UnwindPlan *unwind_plan, + Thread *thread, addr_t base_addr) const { + if (base_addr != LLDB_INVALID_ADDRESS) + s.Printf("0x%16.16" PRIx64 ": CFA=", base_addr + GetOffset()); + else + s.Printf("%4" PRId64 ": CFA=", GetOffset()); + + m_cfa_value.Dump(s, unwind_plan, thread); + s.Printf(" => "); + for (collection::const_iterator idx = m_register_locations.begin(); + idx != m_register_locations.end(); ++idx) { + DumpRegisterName(s, unwind_plan, thread, idx->first); + const bool verbose = false; + idx->second.Dump(s, unwind_plan, this, thread, verbose); + s.PutChar(' '); + } + s.EOL(); +} + +UnwindPlan::Row::Row() : m_offset(0), m_cfa_value(), m_register_locations() {} + +bool UnwindPlan::Row::GetRegisterInfo( + uint32_t reg_num, + UnwindPlan::Row::RegisterLocation ®ister_location) const { + collection::const_iterator pos = m_register_locations.find(reg_num); + if (pos != m_register_locations.end()) { + register_location = pos->second; return true; + } + return false; } -bool -UnwindPlan::Row::SetRegisterLocationToUnspecified (uint32_t reg_num, bool can_replace) -{ - if (!can_replace && m_register_locations.find(reg_num) != m_register_locations.end()) - return false; - RegisterLocation reg_loc; - reg_loc.SetUnspecified(); - m_register_locations[reg_num] = reg_loc; - return true; -} - -bool -UnwindPlan::Row::SetRegisterLocationToRegister (uint32_t reg_num, - uint32_t other_reg_num, - bool can_replace) -{ - if (!can_replace && m_register_locations.find(reg_num) != m_register_locations.end()) - return false; - RegisterLocation reg_loc; - reg_loc.SetInRegister(other_reg_num); - m_register_locations[reg_num] = reg_loc; - return true; +void UnwindPlan::Row::RemoveRegisterInfo(uint32_t reg_num) { + collection::const_iterator pos = m_register_locations.find(reg_num); + if (pos != m_register_locations.end()) { + m_register_locations.erase(pos); + } } -bool -UnwindPlan::Row::SetRegisterLocationToSame (uint32_t reg_num, bool must_replace) -{ - if (must_replace && m_register_locations.find(reg_num) == m_register_locations.end()) - return false; - RegisterLocation reg_loc; - reg_loc.SetSame(); - m_register_locations[reg_num] = reg_loc; - return true; +void UnwindPlan::Row::SetRegisterInfo( + uint32_t reg_num, + const UnwindPlan::Row::RegisterLocation register_location) { + m_register_locations[reg_num] = register_location; } -bool -UnwindPlan::Row::operator == (const UnwindPlan::Row& rhs) const -{ - return m_offset == rhs.m_offset && m_cfa_value == rhs.m_cfa_value && - m_register_locations == rhs.m_register_locations; +bool UnwindPlan::Row::SetRegisterLocationToAtCFAPlusOffset(uint32_t reg_num, + int32_t offset, + bool can_replace) { + if (!can_replace && + m_register_locations.find(reg_num) != m_register_locations.end()) + return false; + RegisterLocation reg_loc; + reg_loc.SetAtCFAPlusOffset(offset); + m_register_locations[reg_num] = reg_loc; + return true; } -void -UnwindPlan::AppendRow (const UnwindPlan::RowSP &row_sp) -{ - if (m_row_list.empty() || m_row_list.back()->GetOffset() != row_sp->GetOffset()) - m_row_list.push_back(row_sp); - else - m_row_list.back() = row_sp; +bool UnwindPlan::Row::SetRegisterLocationToIsCFAPlusOffset(uint32_t reg_num, + int32_t offset, + bool can_replace) { + if (!can_replace && + m_register_locations.find(reg_num) != m_register_locations.end()) + return false; + RegisterLocation reg_loc; + reg_loc.SetIsCFAPlusOffset(offset); + m_register_locations[reg_num] = reg_loc; + return true; +} + +bool UnwindPlan::Row::SetRegisterLocationToUndefined( + uint32_t reg_num, bool can_replace, bool can_replace_only_if_unspecified) { + collection::iterator pos = m_register_locations.find(reg_num); + collection::iterator end = m_register_locations.end(); + + if (pos != end) { + if (!can_replace) + return false; + if (can_replace_only_if_unspecified && !pos->second.IsUnspecified()) + return false; + } + RegisterLocation reg_loc; + reg_loc.SetUndefined(); + m_register_locations[reg_num] = reg_loc; + return true; +} + +bool UnwindPlan::Row::SetRegisterLocationToUnspecified(uint32_t reg_num, + bool can_replace) { + if (!can_replace && + m_register_locations.find(reg_num) != m_register_locations.end()) + return false; + RegisterLocation reg_loc; + reg_loc.SetUnspecified(); + m_register_locations[reg_num] = reg_loc; + return true; } -void -UnwindPlan::InsertRow (const UnwindPlan::RowSP &row_sp, bool replace_existing) -{ - collection::iterator it = m_row_list.begin(); - while (it != m_row_list.end()) { - RowSP row = *it; - if (row->GetOffset() >= row_sp->GetOffset()) - break; - it++; - } - if (it == m_row_list.end() || (*it)->GetOffset() != row_sp->GetOffset()) - m_row_list.insert(it, row_sp); - else if (replace_existing) - *it = row_sp; +bool UnwindPlan::Row::SetRegisterLocationToRegister(uint32_t reg_num, + uint32_t other_reg_num, + bool can_replace) { + if (!can_replace && + m_register_locations.find(reg_num) != m_register_locations.end()) + return false; + RegisterLocation reg_loc; + reg_loc.SetInRegister(other_reg_num); + m_register_locations[reg_num] = reg_loc; + return true; } -UnwindPlan::RowSP -UnwindPlan::GetRowForFunctionOffset (int offset) const -{ - RowSP row; - if (!m_row_list.empty()) - { - if (offset == -1) - row = m_row_list.back(); +bool UnwindPlan::Row::SetRegisterLocationToSame(uint32_t reg_num, + bool must_replace) { + if (must_replace && + m_register_locations.find(reg_num) == m_register_locations.end()) + return false; + RegisterLocation reg_loc; + reg_loc.SetSame(); + m_register_locations[reg_num] = reg_loc; + return true; +} + +bool UnwindPlan::Row::operator==(const UnwindPlan::Row &rhs) const { + return m_offset == rhs.m_offset && m_cfa_value == rhs.m_cfa_value && + m_register_locations == rhs.m_register_locations; +} + +void UnwindPlan::AppendRow(const UnwindPlan::RowSP &row_sp) { + if (m_row_list.empty() || + m_row_list.back()->GetOffset() != row_sp->GetOffset()) + m_row_list.push_back(row_sp); + else + m_row_list.back() = row_sp; +} + +void UnwindPlan::InsertRow(const UnwindPlan::RowSP &row_sp, + bool replace_existing) { + collection::iterator it = m_row_list.begin(); + while (it != m_row_list.end()) { + RowSP row = *it; + if (row->GetOffset() >= row_sp->GetOffset()) + break; + it++; + } + if (it == m_row_list.end() || (*it)->GetOffset() != row_sp->GetOffset()) + m_row_list.insert(it, row_sp); + else if (replace_existing) + *it = row_sp; +} + +UnwindPlan::RowSP UnwindPlan::GetRowForFunctionOffset(int offset) const { + RowSP row; + if (!m_row_list.empty()) { + if (offset == -1) + row = m_row_list.back(); + else { + collection::const_iterator pos, end = m_row_list.end(); + for (pos = m_row_list.begin(); pos != end; ++pos) { + if ((*pos)->GetOffset() <= static_cast<lldb::offset_t>(offset)) + row = *pos; else - { - collection::const_iterator pos, end = m_row_list.end(); - for (pos = m_row_list.begin(); pos != end; ++pos) - { - if ((*pos)->GetOffset() <= static_cast<lldb::offset_t>(offset)) - row = *pos; - else - break; - } - } - } - return row; -} - -bool -UnwindPlan::IsValidRowIndex (uint32_t idx) const -{ - return idx < m_row_list.size(); -} - -const UnwindPlan::RowSP -UnwindPlan::GetRowAtIndex (uint32_t idx) const -{ - if (idx < m_row_list.size()) - return m_row_list[idx]; - else - { - Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND)); - if (log) - log->Printf ("error: UnwindPlan::GetRowAtIndex(idx = %u) invalid index (number rows is %u)", idx, (uint32_t)m_row_list.size()); - return UnwindPlan::RowSP(); - } -} - -const UnwindPlan::RowSP -UnwindPlan::GetLastRow () const -{ - if (m_row_list.empty()) - { - Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND)); - if (log) - log->Printf ("UnwindPlan::GetLastRow() when rows are empty"); - return UnwindPlan::RowSP(); + break; + } } - return m_row_list.back(); -} - -int -UnwindPlan::GetRowCount () const -{ - return m_row_list.size (); -} - -void -UnwindPlan::SetPlanValidAddressRange (const AddressRange& range) -{ - if (range.GetBaseAddress().IsValid() && range.GetByteSize() != 0) - m_plan_valid_address_range = range; -} - -bool -UnwindPlan::PlanValidAtAddress (Address addr) -{ - // If this UnwindPlan has no rows, it is an invalid UnwindPlan. - if (GetRowCount() == 0) - { - Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND)); - if (log) - { - StreamString s; - if (addr.Dump (&s, nullptr, Address::DumpStyleSectionNameOffset)) - { - log->Printf ("UnwindPlan is invalid -- no unwind rows for UnwindPlan '%s' at address %s", - m_source_name.GetCString(), s.GetData()); - } - else - { - log->Printf ("UnwindPlan is invalid -- no unwind rows for UnwindPlan '%s'", - m_source_name.GetCString()); - } - } - return false; + } + return row; +} + +bool UnwindPlan::IsValidRowIndex(uint32_t idx) const { + return idx < m_row_list.size(); +} + +const UnwindPlan::RowSP UnwindPlan::GetRowAtIndex(uint32_t idx) const { + if (idx < m_row_list.size()) + return m_row_list[idx]; + else { + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_UNWIND)); + if (log) + log->Printf("error: UnwindPlan::GetRowAtIndex(idx = %u) invalid index " + "(number rows is %u)", + idx, (uint32_t)m_row_list.size()); + return UnwindPlan::RowSP(); + } +} + +const UnwindPlan::RowSP UnwindPlan::GetLastRow() const { + if (m_row_list.empty()) { + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_UNWIND)); + if (log) + log->Printf("UnwindPlan::GetLastRow() when rows are empty"); + return UnwindPlan::RowSP(); + } + return m_row_list.back(); +} + +int UnwindPlan::GetRowCount() const { return m_row_list.size(); } + +void UnwindPlan::SetPlanValidAddressRange(const AddressRange &range) { + if (range.GetBaseAddress().IsValid() && range.GetByteSize() != 0) + m_plan_valid_address_range = range; +} + +bool UnwindPlan::PlanValidAtAddress(Address addr) { + // If this UnwindPlan has no rows, it is an invalid UnwindPlan. + if (GetRowCount() == 0) { + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_UNWIND)); + if (log) { + StreamString s; + if (addr.Dump(&s, nullptr, Address::DumpStyleSectionNameOffset)) { + log->Printf("UnwindPlan is invalid -- no unwind rows for UnwindPlan " + "'%s' at address %s", + m_source_name.GetCString(), s.GetData()); + } else { + log->Printf( + "UnwindPlan is invalid -- no unwind rows for UnwindPlan '%s'", + m_source_name.GetCString()); + } } - - // If the 0th Row of unwind instructions is missing, or if it doesn't provide - // a register to use to find the Canonical Frame Address, this is not a valid UnwindPlan. - if (GetRowAtIndex(0).get() == nullptr || - GetRowAtIndex(0)->GetCFAValue().GetValueType() == Row::CFAValue::unspecified) - { - Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND)); - if (log) - { - StreamString s; - if (addr.Dump (&s, nullptr, Address::DumpStyleSectionNameOffset)) - { - log->Printf ("UnwindPlan is invalid -- no CFA register defined in row 0 for UnwindPlan '%s' at address %s", - m_source_name.GetCString(), s.GetData()); - } - else - { - log->Printf ("UnwindPlan is invalid -- no CFA register defined in row 0 for UnwindPlan '%s'", - m_source_name.GetCString()); - } - } - return false; + return false; + } + + // If the 0th Row of unwind instructions is missing, or if it doesn't provide + // a register to use to find the Canonical Frame Address, this is not a valid + // UnwindPlan. + if (GetRowAtIndex(0).get() == nullptr || + GetRowAtIndex(0)->GetCFAValue().GetValueType() == + Row::CFAValue::unspecified) { + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_UNWIND)); + if (log) { + StreamString s; + if (addr.Dump(&s, nullptr, Address::DumpStyleSectionNameOffset)) { + log->Printf("UnwindPlan is invalid -- no CFA register defined in row 0 " + "for UnwindPlan '%s' at address %s", + m_source_name.GetCString(), s.GetData()); + } else { + log->Printf("UnwindPlan is invalid -- no CFA register defined in row 0 " + "for UnwindPlan '%s'", + m_source_name.GetCString()); + } } - - if (!m_plan_valid_address_range.GetBaseAddress().IsValid() || m_plan_valid_address_range.GetByteSize() == 0) - return true; - - if (!addr.IsValid()) - return true; - - if (m_plan_valid_address_range.ContainsFileAddress (addr)) - return true; - return false; -} + } -void -UnwindPlan::Dump (Stream& s, Thread *thread, lldb::addr_t base_addr) const -{ - if (!m_source_name.IsEmpty()) - { - s.Printf ("This UnwindPlan originally sourced from %s\n", m_source_name.GetCString()); - } - if (m_lsda_address.IsValid() && m_personality_func_addr.IsValid()) - { - TargetSP target_sp(thread->CalculateTarget()); - addr_t lsda_load_addr = m_lsda_address.GetLoadAddress (target_sp.get()); - addr_t personality_func_load_addr = m_personality_func_addr.GetLoadAddress (target_sp.get()); - - if (lsda_load_addr != LLDB_INVALID_ADDRESS && personality_func_load_addr != LLDB_INVALID_ADDRESS) - { - s.Printf("LSDA address 0x%" PRIx64 ", personality routine is at address 0x%" PRIx64 "\n", - lsda_load_addr, personality_func_load_addr); - } - } - s.Printf ("This UnwindPlan is sourced from the compiler: "); - switch (m_plan_is_sourced_from_compiler) - { - case eLazyBoolYes: - s.Printf ("yes.\n"); - break; - case eLazyBoolNo: - s.Printf ("no.\n"); - break; - case eLazyBoolCalculate: - s.Printf ("not specified.\n"); - break; - } - s.Printf ("This UnwindPlan is valid at all instruction locations: "); - switch (m_plan_is_valid_at_all_instruction_locations) - { - case eLazyBoolYes: - s.Printf ("yes.\n"); - break; - case eLazyBoolNo: - s.Printf ("no.\n"); - break; - case eLazyBoolCalculate: - s.Printf ("not specified.\n"); - break; - } - if (m_plan_valid_address_range.GetBaseAddress().IsValid() && m_plan_valid_address_range.GetByteSize() > 0) - { - s.PutCString ("Address range of this UnwindPlan: "); - TargetSP target_sp(thread->CalculateTarget()); - m_plan_valid_address_range.Dump (&s, target_sp.get(), Address::DumpStyleSectionNameOffset); - s.EOL(); - } - collection::const_iterator pos, begin = m_row_list.begin(), end = m_row_list.end(); - for (pos = begin; pos != end; ++pos) - { - s.Printf ("row[%u]: ", (uint32_t)std::distance (begin, pos)); - (*pos)->Dump(s, this, thread, base_addr); - } -} + if (!m_plan_valid_address_range.GetBaseAddress().IsValid() || + m_plan_valid_address_range.GetByteSize() == 0) + return true; -void -UnwindPlan::SetSourceName (const char *source) -{ - m_source_name = ConstString (source); -} + if (!addr.IsValid()) + return true; -ConstString -UnwindPlan::GetSourceName () const -{ - return m_source_name; -} + if (m_plan_valid_address_range.ContainsFileAddress(addr)) + return true; -const RegisterInfo * -UnwindPlan::GetRegisterInfo (Thread* thread, uint32_t unwind_reg) const -{ - if (thread) - { - RegisterContext *reg_ctx = thread->GetRegisterContext().get(); - if (reg_ctx) - { - uint32_t reg; - if (m_register_kind == eRegisterKindLLDB) - reg = unwind_reg; - else - reg = reg_ctx->ConvertRegisterKindToRegisterNumber (m_register_kind, unwind_reg); - if (reg != LLDB_INVALID_REGNUM) - return reg_ctx->GetRegisterInfoAtIndex (reg); - } + return false; +} + +void UnwindPlan::Dump(Stream &s, Thread *thread, lldb::addr_t base_addr) const { + if (!m_source_name.IsEmpty()) { + s.Printf("This UnwindPlan originally sourced from %s\n", + m_source_name.GetCString()); + } + if (m_lsda_address.IsValid() && m_personality_func_addr.IsValid()) { + TargetSP target_sp(thread->CalculateTarget()); + addr_t lsda_load_addr = m_lsda_address.GetLoadAddress(target_sp.get()); + addr_t personality_func_load_addr = + m_personality_func_addr.GetLoadAddress(target_sp.get()); + + if (lsda_load_addr != LLDB_INVALID_ADDRESS && + personality_func_load_addr != LLDB_INVALID_ADDRESS) { + s.Printf("LSDA address 0x%" PRIx64 + ", personality routine is at address 0x%" PRIx64 "\n", + lsda_load_addr, personality_func_load_addr); + } + } + s.Printf("This UnwindPlan is sourced from the compiler: "); + switch (m_plan_is_sourced_from_compiler) { + case eLazyBoolYes: + s.Printf("yes.\n"); + break; + case eLazyBoolNo: + s.Printf("no.\n"); + break; + case eLazyBoolCalculate: + s.Printf("not specified.\n"); + break; + } + s.Printf("This UnwindPlan is valid at all instruction locations: "); + switch (m_plan_is_valid_at_all_instruction_locations) { + case eLazyBoolYes: + s.Printf("yes.\n"); + break; + case eLazyBoolNo: + s.Printf("no.\n"); + break; + case eLazyBoolCalculate: + s.Printf("not specified.\n"); + break; + } + if (m_plan_valid_address_range.GetBaseAddress().IsValid() && + m_plan_valid_address_range.GetByteSize() > 0) { + s.PutCString("Address range of this UnwindPlan: "); + TargetSP target_sp(thread->CalculateTarget()); + m_plan_valid_address_range.Dump(&s, target_sp.get(), + Address::DumpStyleSectionNameOffset); + s.EOL(); + } + collection::const_iterator pos, begin = m_row_list.begin(), + end = m_row_list.end(); + for (pos = begin; pos != end; ++pos) { + s.Printf("row[%u]: ", (uint32_t)std::distance(begin, pos)); + (*pos)->Dump(s, this, thread, base_addr); + } +} + +void UnwindPlan::SetSourceName(const char *source) { + m_source_name = ConstString(source); +} + +ConstString UnwindPlan::GetSourceName() const { return m_source_name; } + +const RegisterInfo *UnwindPlan::GetRegisterInfo(Thread *thread, + uint32_t unwind_reg) const { + if (thread) { + RegisterContext *reg_ctx = thread->GetRegisterContext().get(); + if (reg_ctx) { + uint32_t reg; + if (m_register_kind == eRegisterKindLLDB) + reg = unwind_reg; + else + reg = reg_ctx->ConvertRegisterKindToRegisterNumber(m_register_kind, + unwind_reg); + if (reg != LLDB_INVALID_REGNUM) + return reg_ctx->GetRegisterInfoAtIndex(reg); } - return nullptr; + } + return nullptr; } - diff --git a/lldb/source/Symbol/UnwindTable.cpp b/lldb/source/Symbol/UnwindTable.cpp index 87c18d94b07..336f0c3e04a 100644 --- a/lldb/source/Symbol/UnwindTable.cpp +++ b/lldb/source/Symbol/UnwindTable.cpp @@ -13,185 +13,168 @@ #include "lldb/Core/Module.h" #include "lldb/Core/Section.h" -#include "lldb/Symbol/ObjectFile.h" -#include "lldb/Symbol/FuncUnwinders.h" -#include "lldb/Symbol/SymbolContext.h" -#include "lldb/Symbol/DWARFCallFrameInfo.h" #include "lldb/Symbol/ArmUnwindInfo.h" #include "lldb/Symbol/CompactUnwindInfo.h" +#include "lldb/Symbol/DWARFCallFrameInfo.h" +#include "lldb/Symbol/FuncUnwinders.h" +#include "lldb/Symbol/ObjectFile.h" +#include "lldb/Symbol/SymbolContext.h" // There is one UnwindTable object per ObjectFile. -// It contains a list of Unwind objects -- one per function, populated lazily -- for the ObjectFile. +// It contains a list of Unwind objects -- one per function, populated lazily -- +// for the ObjectFile. // Each Unwind object has multiple UnwindPlans for different scenarios. using namespace lldb; using namespace lldb_private; UnwindTable::UnwindTable(ObjectFile &objfile) - : m_object_file(objfile), - m_unwinds(), - m_initialized(false), - m_mutex(), - m_eh_frame_up(), - m_compact_unwind_up(), - m_arm_unwind_up() -{ -} + : m_object_file(objfile), m_unwinds(), m_initialized(false), m_mutex(), + m_eh_frame_up(), m_compact_unwind_up(), m_arm_unwind_up() {} -// We can't do some of this initialization when the ObjectFile is running its ctor; delay doing it +// We can't do some of this initialization when the ObjectFile is running its +// ctor; delay doing it // until needed for something. -void -UnwindTable::Initialize () -{ - if (m_initialized) - return; - - std::lock_guard<std::mutex> guard(m_mutex); - - if (m_initialized) // check again once we've acquired the lock - return; - - SectionList* sl = m_object_file.GetSectionList (); - if (sl) - { - SectionSP sect = sl->FindSectionByType (eSectionTypeEHFrame, true); - if (sect.get()) - { - m_eh_frame_up.reset(new DWARFCallFrameInfo(m_object_file, sect, eRegisterKindEHFrame, true)); - } - sect = sl->FindSectionByType (eSectionTypeCompactUnwind, true); - if (sect.get()) - { - m_compact_unwind_up.reset(new CompactUnwindInfo(m_object_file, sect)); - } - sect = sl->FindSectionByType (eSectionTypeARMexidx, true); - if (sect.get()) - { - SectionSP sect_extab = sl->FindSectionByType (eSectionTypeARMextab, true); - if (sect_extab.get()) - { - m_arm_unwind_up.reset(new ArmUnwindInfo(m_object_file, sect, sect_extab)); - } - } +void UnwindTable::Initialize() { + if (m_initialized) + return; + + std::lock_guard<std::mutex> guard(m_mutex); + + if (m_initialized) // check again once we've acquired the lock + return; + + SectionList *sl = m_object_file.GetSectionList(); + if (sl) { + SectionSP sect = sl->FindSectionByType(eSectionTypeEHFrame, true); + if (sect.get()) { + m_eh_frame_up.reset(new DWARFCallFrameInfo(m_object_file, sect, + eRegisterKindEHFrame, true)); } - - m_initialized = true; -} + sect = sl->FindSectionByType(eSectionTypeCompactUnwind, true); + if (sect.get()) { + m_compact_unwind_up.reset(new CompactUnwindInfo(m_object_file, sect)); + } + sect = sl->FindSectionByType(eSectionTypeARMexidx, true); + if (sect.get()) { + SectionSP sect_extab = sl->FindSectionByType(eSectionTypeARMextab, true); + if (sect_extab.get()) { + m_arm_unwind_up.reset( + new ArmUnwindInfo(m_object_file, sect, sect_extab)); + } + } + } -UnwindTable::~UnwindTable () -{ + m_initialized = true; } -FuncUnwindersSP -UnwindTable::GetFuncUnwindersContainingAddress (const Address& addr, SymbolContext &sc) -{ - FuncUnwindersSP no_unwind_found; - - Initialize(); - - std::lock_guard<std::mutex> guard(m_mutex); - - // There is an UnwindTable per object file, so we can safely use file handles - addr_t file_addr = addr.GetFileAddress(); - iterator end = m_unwinds.end (); - iterator insert_pos = end; - if (!m_unwinds.empty()) - { - insert_pos = m_unwinds.lower_bound (file_addr); - iterator pos = insert_pos; - if ((pos == m_unwinds.end ()) || (pos != m_unwinds.begin() && pos->second->GetFunctionStartAddress() != addr)) - --pos; - - if (pos->second->ContainsAddress (addr)) - return pos->second; - } +UnwindTable::~UnwindTable() {} - AddressRange range; - if (!sc.GetAddressRange(eSymbolContextFunction | eSymbolContextSymbol, 0, false, range) || !range.GetBaseAddress().IsValid()) - { - // Does the eh_frame unwind info has a function bounds for this addr? - if (m_eh_frame_up == nullptr || !m_eh_frame_up->GetAddressRange (addr, range)) - { - return no_unwind_found; - } +FuncUnwindersSP +UnwindTable::GetFuncUnwindersContainingAddress(const Address &addr, + SymbolContext &sc) { + FuncUnwindersSP no_unwind_found; + + Initialize(); + + std::lock_guard<std::mutex> guard(m_mutex); + + // There is an UnwindTable per object file, so we can safely use file handles + addr_t file_addr = addr.GetFileAddress(); + iterator end = m_unwinds.end(); + iterator insert_pos = end; + if (!m_unwinds.empty()) { + insert_pos = m_unwinds.lower_bound(file_addr); + iterator pos = insert_pos; + if ((pos == m_unwinds.end()) || + (pos != m_unwinds.begin() && + pos->second->GetFunctionStartAddress() != addr)) + --pos; + + if (pos->second->ContainsAddress(addr)) + return pos->second; + } + + AddressRange range; + if (!sc.GetAddressRange(eSymbolContextFunction | eSymbolContextSymbol, 0, + false, range) || + !range.GetBaseAddress().IsValid()) { + // Does the eh_frame unwind info has a function bounds for this addr? + if (m_eh_frame_up == nullptr || + !m_eh_frame_up->GetAddressRange(addr, range)) { + return no_unwind_found; } - - FuncUnwindersSP func_unwinder_sp(new FuncUnwinders(*this, range)); - m_unwinds.insert (insert_pos, std::make_pair(range.GetBaseAddress().GetFileAddress(), func_unwinder_sp)); -// StreamFile s(stdout, false); -// Dump (s); - return func_unwinder_sp; + } + + FuncUnwindersSP func_unwinder_sp(new FuncUnwinders(*this, range)); + m_unwinds.insert(insert_pos, + std::make_pair(range.GetBaseAddress().GetFileAddress(), + func_unwinder_sp)); + // StreamFile s(stdout, false); + // Dump (s); + return func_unwinder_sp; } -// Ignore any existing FuncUnwinders for this function, create a new one and don't add it to the -// UnwindTable. This is intended for use by target modules show-unwind where we want to create +// Ignore any existing FuncUnwinders for this function, create a new one and +// don't add it to the +// UnwindTable. This is intended for use by target modules show-unwind where we +// want to create // new UnwindPlans, not re-use existing ones. FuncUnwindersSP -UnwindTable::GetUncachedFuncUnwindersContainingAddress (const Address& addr, SymbolContext &sc) -{ - FuncUnwindersSP no_unwind_found; - Initialize(); - - AddressRange range; - if (!sc.GetAddressRange(eSymbolContextFunction | eSymbolContextSymbol, 0, false, range) || !range.GetBaseAddress().IsValid()) - { - // Does the eh_frame unwind info has a function bounds for this addr? - if (m_eh_frame_up == nullptr || !m_eh_frame_up->GetAddressRange (addr, range)) - { - return no_unwind_found; - } +UnwindTable::GetUncachedFuncUnwindersContainingAddress(const Address &addr, + SymbolContext &sc) { + FuncUnwindersSP no_unwind_found; + Initialize(); + + AddressRange range; + if (!sc.GetAddressRange(eSymbolContextFunction | eSymbolContextSymbol, 0, + false, range) || + !range.GetBaseAddress().IsValid()) { + // Does the eh_frame unwind info has a function bounds for this addr? + if (m_eh_frame_up == nullptr || + !m_eh_frame_up->GetAddressRange(addr, range)) { + return no_unwind_found; } + } - FuncUnwindersSP func_unwinder_sp(new FuncUnwinders(*this, range)); - return func_unwinder_sp; + FuncUnwindersSP func_unwinder_sp(new FuncUnwinders(*this, range)); + return func_unwinder_sp; } - -void -UnwindTable::Dump (Stream &s) -{ - std::lock_guard<std::mutex> guard(m_mutex); - s.Printf("UnwindTable for '%s':\n", m_object_file.GetFileSpec().GetPath().c_str()); - const_iterator begin = m_unwinds.begin(); - const_iterator end = m_unwinds.end(); - for (const_iterator pos = begin; pos != end; ++pos) - { - s.Printf ("[%u] 0x%16.16" PRIx64 "\n", (unsigned)std::distance (begin, pos), pos->first); - } - s.EOL(); +void UnwindTable::Dump(Stream &s) { + std::lock_guard<std::mutex> guard(m_mutex); + s.Printf("UnwindTable for '%s':\n", + m_object_file.GetFileSpec().GetPath().c_str()); + const_iterator begin = m_unwinds.begin(); + const_iterator end = m_unwinds.end(); + for (const_iterator pos = begin; pos != end; ++pos) { + s.Printf("[%u] 0x%16.16" PRIx64 "\n", (unsigned)std::distance(begin, pos), + pos->first); + } + s.EOL(); } -DWARFCallFrameInfo * -UnwindTable::GetEHFrameInfo () -{ - Initialize(); - return m_eh_frame_up.get(); +DWARFCallFrameInfo *UnwindTable::GetEHFrameInfo() { + Initialize(); + return m_eh_frame_up.get(); } -CompactUnwindInfo * -UnwindTable::GetCompactUnwindInfo () -{ - Initialize(); - return m_compact_unwind_up.get(); +CompactUnwindInfo *UnwindTable::GetCompactUnwindInfo() { + Initialize(); + return m_compact_unwind_up.get(); } -ArmUnwindInfo * -UnwindTable::GetArmUnwindInfo () -{ - Initialize(); - return m_arm_unwind_up.get(); +ArmUnwindInfo *UnwindTable::GetArmUnwindInfo() { + Initialize(); + return m_arm_unwind_up.get(); } -bool -UnwindTable::GetArchitecture (lldb_private::ArchSpec &arch) -{ - return m_object_file.GetArchitecture (arch); +bool UnwindTable::GetArchitecture(lldb_private::ArchSpec &arch) { + return m_object_file.GetArchitecture(arch); } -bool -UnwindTable::GetAllowAssemblyEmulationUnwindPlans () -{ - return m_object_file.AllowAssemblyEmulationUnwindPlans (); +bool UnwindTable::GetAllowAssemblyEmulationUnwindPlans() { + return m_object_file.AllowAssemblyEmulationUnwindPlans(); } diff --git a/lldb/source/Symbol/Variable.cpp b/lldb/source/Symbol/Variable.cpp index dd27b1b5d80..6ba6cf94106 100644 --- a/lldb/source/Symbol/Variable.cpp +++ b/lldb/source/Symbol/Variable.cpp @@ -10,14 +10,14 @@ #include "lldb/Symbol/Variable.h" #include "lldb/Core/Module.h" -#include "lldb/Core/Stream.h" #include "lldb/Core/RegularExpression.h" +#include "lldb/Core/Stream.h" #include "lldb/Core/ValueObject.h" #include "lldb/Core/ValueObjectVariable.h" #include "lldb/Symbol/Block.h" +#include "lldb/Symbol/CompileUnit.h" #include "lldb/Symbol/CompilerDecl.h" #include "lldb/Symbol/CompilerDeclContext.h" -#include "lldb/Symbol/CompileUnit.h" #include "lldb/Symbol/Function.h" #include "lldb/Symbol/SymbolContext.h" #include "lldb/Symbol/SymbolFile.h" @@ -28,8 +28,8 @@ #include "lldb/Target/Process.h" #include "lldb/Target/RegisterContext.h" #include "lldb/Target/StackFrame.h" -#include "lldb/Target/Thread.h" #include "lldb/Target/Target.h" +#include "lldb/Target/Thread.h" using namespace lldb; using namespace lldb_private; @@ -37,948 +37,732 @@ using namespace lldb_private; //---------------------------------------------------------------------- // Variable constructor //---------------------------------------------------------------------- -Variable::Variable (lldb::user_id_t uid, - const char *name, - const char *mangled, // The mangled or fully qualified name of the variable. - const lldb::SymbolFileTypeSP &symfile_type_sp, - ValueType scope, - SymbolContextScope *context, - const RangeList& scope_range, - Declaration* decl_ptr, - const DWARFExpression& location, - bool external, - bool artificial, - bool static_member) : - UserID(uid), - m_name(name), - m_mangled (ConstString(mangled)), - m_symfile_type_sp(symfile_type_sp), - m_scope(scope), - m_owner_scope(context), - m_scope_range(scope_range), - m_declaration(decl_ptr), - m_location(location), - m_external(external), - m_artificial(artificial), - m_static_member(static_member) -{ -} +Variable::Variable( + lldb::user_id_t uid, const char *name, + const char *mangled, // The mangled or fully qualified name of the variable. + const lldb::SymbolFileTypeSP &symfile_type_sp, ValueType scope, + SymbolContextScope *context, const RangeList &scope_range, + Declaration *decl_ptr, const DWARFExpression &location, bool external, + bool artificial, bool static_member) + : UserID(uid), m_name(name), m_mangled(ConstString(mangled)), + m_symfile_type_sp(symfile_type_sp), m_scope(scope), + m_owner_scope(context), m_scope_range(scope_range), + m_declaration(decl_ptr), m_location(location), m_external(external), + m_artificial(artificial), m_static_member(static_member) {} //---------------------------------------------------------------------- // Destructor //---------------------------------------------------------------------- -Variable::~Variable() -{ +Variable::~Variable() {} + +lldb::LanguageType Variable::GetLanguage() const { + SymbolContext variable_sc; + m_owner_scope->CalculateSymbolContext(&variable_sc); + if (variable_sc.comp_unit) + return variable_sc.comp_unit->GetLanguage(); + return lldb::eLanguageTypeUnknown; } -lldb::LanguageType -Variable::GetLanguage () const -{ - SymbolContext variable_sc; - m_owner_scope->CalculateSymbolContext(&variable_sc); - if (variable_sc.comp_unit) - return variable_sc.comp_unit->GetLanguage(); - return lldb::eLanguageTypeUnknown; +ConstString Variable::GetName() const { + ConstString name = m_mangled.GetName(GetLanguage()); + if (name) + return name; + return m_name; } +ConstString Variable::GetUnqualifiedName() const { return m_name; } +bool Variable::NameMatches(const ConstString &name) const { + if (m_name == name) + return true; + SymbolContext variable_sc; + m_owner_scope->CalculateSymbolContext(&variable_sc); -ConstString -Variable::GetName() const -{ - ConstString name = m_mangled.GetName(GetLanguage()); - if (name) - return name; - return m_name; + LanguageType language = eLanguageTypeUnknown; + if (variable_sc.comp_unit) + language = variable_sc.comp_unit->GetLanguage(); + return m_mangled.NameMatches(name, language); } - -ConstString -Variable::GetUnqualifiedName() const -{ - return m_name; +bool Variable::NameMatches(const RegularExpression ®ex) const { + if (regex.Execute(m_name.AsCString())) + return true; + if (m_mangled) + return m_mangled.NameMatches(regex, GetLanguage()); + return false; } - -bool -Variable::NameMatches (const ConstString &name) const -{ - if (m_name == name) - return true; - SymbolContext variable_sc; - m_owner_scope->CalculateSymbolContext(&variable_sc); - - LanguageType language = eLanguageTypeUnknown; - if (variable_sc.comp_unit) - language = variable_sc.comp_unit->GetLanguage(); - return m_mangled.NameMatches (name, language); -} -bool -Variable::NameMatches (const RegularExpression& regex) const -{ - if (regex.Execute (m_name.AsCString())) - return true; - if (m_mangled) - return m_mangled.NameMatches (regex, GetLanguage()); - return false; +Type *Variable::GetType() { + if (m_symfile_type_sp) + return m_symfile_type_sp->GetType(); + return nullptr; } -Type * -Variable::GetType() -{ - if (m_symfile_type_sp) - return m_symfile_type_sp->GetType(); - return nullptr; -} +void Variable::Dump(Stream *s, bool show_context) const { + s->Printf("%p: ", static_cast<const void *>(this)); + s->Indent(); + *s << "Variable" << (const UserID &)*this; -void -Variable::Dump(Stream *s, bool show_context) const -{ - s->Printf("%p: ", static_cast<const void*>(this)); - s->Indent(); - *s << "Variable" << (const UserID&)*this; - - if (m_name) - *s << ", name = \"" << m_name << "\""; - - if (m_symfile_type_sp) - { - Type *type = m_symfile_type_sp->GetType(); - if (type) - { - *s << ", type = {" << type->GetID() << "} " << (void*)type << " ("; - type->DumpTypeName(s); - s->PutChar(')'); - } - } + if (m_name) + *s << ", name = \"" << m_name << "\""; - if (m_scope != eValueTypeInvalid) - { - s->PutCString(", scope = "); - switch (m_scope) - { - case eValueTypeVariableGlobal: s->PutCString(m_external ? "global" : "static"); break; - case eValueTypeVariableArgument: - s->PutCString("parameter"); - break; - case eValueTypeVariableLocal: s->PutCString("local"); break; - case eValueTypeVariableThreadLocal: - s->PutCString("thread local"); - break; - default: *s << "??? (" << m_scope << ')'; - } + if (m_symfile_type_sp) { + Type *type = m_symfile_type_sp->GetType(); + if (type) { + *s << ", type = {" << type->GetID() << "} " << (void *)type << " ("; + type->DumpTypeName(s); + s->PutChar(')'); } + } - if (show_context && m_owner_scope != nullptr) - { - s->PutCString(", context = ( "); - m_owner_scope->DumpSymbolContext(s); - s->PutCString(" )"); + if (m_scope != eValueTypeInvalid) { + s->PutCString(", scope = "); + switch (m_scope) { + case eValueTypeVariableGlobal: + s->PutCString(m_external ? "global" : "static"); + break; + case eValueTypeVariableArgument: + s->PutCString("parameter"); + break; + case eValueTypeVariableLocal: + s->PutCString("local"); + break; + case eValueTypeVariableThreadLocal: + s->PutCString("thread local"); + break; + default: + *s << "??? (" << m_scope << ')'; } - - bool show_fullpaths = false; - m_declaration.Dump(s, show_fullpaths); - - if (m_location.IsValid()) - { - s->PutCString(", location = "); - lldb::addr_t loclist_base_addr = LLDB_INVALID_ADDRESS; - if (m_location.IsLocationList()) - { - SymbolContext variable_sc; - m_owner_scope->CalculateSymbolContext(&variable_sc); - if (variable_sc.function) - loclist_base_addr = variable_sc.function->GetAddressRange().GetBaseAddress().GetFileAddress(); - } - ABI *abi = nullptr; - if (m_owner_scope) - { - ModuleSP module_sp (m_owner_scope->CalculateSymbolContextModule()); - if (module_sp) - abi = ABI::FindPlugin (module_sp->GetArchitecture()).get(); - } - m_location.GetDescription(s, lldb::eDescriptionLevelBrief, loclist_base_addr, abi); + } + + if (show_context && m_owner_scope != nullptr) { + s->PutCString(", context = ( "); + m_owner_scope->DumpSymbolContext(s); + s->PutCString(" )"); + } + + bool show_fullpaths = false; + m_declaration.Dump(s, show_fullpaths); + + if (m_location.IsValid()) { + s->PutCString(", location = "); + lldb::addr_t loclist_base_addr = LLDB_INVALID_ADDRESS; + if (m_location.IsLocationList()) { + SymbolContext variable_sc; + m_owner_scope->CalculateSymbolContext(&variable_sc); + if (variable_sc.function) + loclist_base_addr = variable_sc.function->GetAddressRange() + .GetBaseAddress() + .GetFileAddress(); + } + ABI *abi = nullptr; + if (m_owner_scope) { + ModuleSP module_sp(m_owner_scope->CalculateSymbolContextModule()); + if (module_sp) + abi = ABI::FindPlugin(module_sp->GetArchitecture()).get(); } + m_location.GetDescription(s, lldb::eDescriptionLevelBrief, + loclist_base_addr, abi); + } - if (m_external) - s->PutCString(", external"); + if (m_external) + s->PutCString(", external"); - if (m_artificial) - s->PutCString(", artificial"); + if (m_artificial) + s->PutCString(", artificial"); - s->EOL(); + s->EOL(); } -bool -Variable::DumpDeclaration (Stream *s, bool show_fullpaths, bool show_module) -{ - bool dumped_declaration_info = false; - if (m_owner_scope) - { - SymbolContext sc; - m_owner_scope->CalculateSymbolContext(&sc); - sc.block = nullptr; - sc.line_entry.Clear(); - bool show_inlined_frames = false; - const bool show_function_arguments = true; - const bool show_function_name = true; - - dumped_declaration_info = sc.DumpStopContext (s, - nullptr, - Address(), - show_fullpaths, - show_module, - show_inlined_frames, - show_function_arguments, - show_function_name); - - if (sc.function) - s->PutChar(':'); - } - if (m_declaration.DumpStopContext (s, false)) - dumped_declaration_info = true; - return dumped_declaration_info; +bool Variable::DumpDeclaration(Stream *s, bool show_fullpaths, + bool show_module) { + bool dumped_declaration_info = false; + if (m_owner_scope) { + SymbolContext sc; + m_owner_scope->CalculateSymbolContext(&sc); + sc.block = nullptr; + sc.line_entry.Clear(); + bool show_inlined_frames = false; + const bool show_function_arguments = true; + const bool show_function_name = true; + + dumped_declaration_info = sc.DumpStopContext( + s, nullptr, Address(), show_fullpaths, show_module, show_inlined_frames, + show_function_arguments, show_function_name); + + if (sc.function) + s->PutChar(':'); + } + if (m_declaration.DumpStopContext(s, false)) + dumped_declaration_info = true; + return dumped_declaration_info; } -size_t -Variable::MemorySize() const -{ - return sizeof(Variable); +size_t Variable::MemorySize() const { return sizeof(Variable); } + +CompilerDeclContext Variable::GetDeclContext() { + Type *type = GetType(); + if (type) + return type->GetSymbolFile()->GetDeclContextContainingUID(GetID()); + return CompilerDeclContext(); } -CompilerDeclContext -Variable::GetDeclContext () -{ - Type *type = GetType(); - if (type) - return type->GetSymbolFile()->GetDeclContextContainingUID(GetID()); - return CompilerDeclContext(); +CompilerDecl Variable::GetDecl() { + Type *type = GetType(); + return type ? type->GetSymbolFile()->GetDeclForUID(GetID()) : CompilerDecl(); } -CompilerDecl -Variable::GetDecl () -{ - Type *type = GetType(); - return type ? type->GetSymbolFile()->GetDeclForUID(GetID()) : CompilerDecl(); +void Variable::CalculateSymbolContext(SymbolContext *sc) { + if (m_owner_scope) { + m_owner_scope->CalculateSymbolContext(sc); + sc->variable = this; + } else + sc->Clear(false); } -void -Variable::CalculateSymbolContext (SymbolContext *sc) -{ - if (m_owner_scope) - { - m_owner_scope->CalculateSymbolContext(sc); - sc->variable = this; +bool Variable::LocationIsValidForFrame(StackFrame *frame) { + // Is the variable is described by a single location? + if (!m_location.IsLocationList()) { + // Yes it is, the location is valid. + return true; + } + + if (frame) { + Function *function = + frame->GetSymbolContext(eSymbolContextFunction).function; + if (function) { + TargetSP target_sp(frame->CalculateTarget()); + + addr_t loclist_base_load_addr = + function->GetAddressRange().GetBaseAddress().GetLoadAddress( + target_sp.get()); + if (loclist_base_load_addr == LLDB_INVALID_ADDRESS) + return false; + // It is a location list. We just need to tell if the location + // list contains the current address when converted to a load + // address + return m_location.LocationListContainsAddress( + loclist_base_load_addr, + frame->GetFrameCodeAddress().GetLoadAddress(target_sp.get())); } - else - sc->Clear(false); + } + return false; } -bool -Variable::LocationIsValidForFrame (StackFrame *frame) -{ - // Is the variable is described by a single location? - if (!m_location.IsLocationList()) - { - // Yes it is, the location is valid. +bool Variable::LocationIsValidForAddress(const Address &address) { + // Be sure to resolve the address to section offset prior to + // calling this function. + if (address.IsSectionOffset()) { + SymbolContext sc; + CalculateSymbolContext(&sc); + if (sc.module_sp == address.GetModule()) { + // Is the variable is described by a single location? + if (!m_location.IsLocationList()) { + // Yes it is, the location is valid. return true; + } + + if (sc.function) { + addr_t loclist_base_file_addr = + sc.function->GetAddressRange().GetBaseAddress().GetFileAddress(); + if (loclist_base_file_addr == LLDB_INVALID_ADDRESS) + return false; + // It is a location list. We just need to tell if the location + // list contains the current address when converted to a load + // address + return m_location.LocationListContainsAddress(loclist_base_file_addr, + address.GetFileAddress()); + } } - - if (frame) - { - Function *function = frame->GetSymbolContext(eSymbolContextFunction).function; - if (function) - { - TargetSP target_sp (frame->CalculateTarget()); - - addr_t loclist_base_load_addr = function->GetAddressRange().GetBaseAddress().GetLoadAddress (target_sp.get()); - if (loclist_base_load_addr == LLDB_INVALID_ADDRESS) - return false; - // It is a location list. We just need to tell if the location - // list contains the current address when converted to a load - // address - return m_location.LocationListContainsAddress (loclist_base_load_addr, - frame->GetFrameCodeAddress().GetLoadAddress (target_sp.get())); - } - } - return false; + } + return false; } -bool -Variable::LocationIsValidForAddress (const Address &address) -{ - // Be sure to resolve the address to section offset prior to - // calling this function. - if (address.IsSectionOffset()) - { - SymbolContext sc; - CalculateSymbolContext(&sc); - if (sc.module_sp == address.GetModule()) - { - // Is the variable is described by a single location? - if (!m_location.IsLocationList()) - { - // Yes it is, the location is valid. - return true; - } - - if (sc.function) - { - addr_t loclist_base_file_addr = sc.function->GetAddressRange().GetBaseAddress().GetFileAddress(); - if (loclist_base_file_addr == LLDB_INVALID_ADDRESS) - return false; - // It is a location list. We just need to tell if the location - // list contains the current address when converted to a load - // address - return m_location.LocationListContainsAddress (loclist_base_file_addr, - address.GetFileAddress()); - } - } +bool Variable::IsInScope(StackFrame *frame) { + switch (m_scope) { + case eValueTypeRegister: + case eValueTypeRegisterSet: + return frame != nullptr; + + case eValueTypeConstResult: + case eValueTypeVariableGlobal: + case eValueTypeVariableStatic: + case eValueTypeVariableThreadLocal: + return true; + + case eValueTypeVariableArgument: + case eValueTypeVariableLocal: + if (frame) { + // We don't have a location list, we just need to see if the block + // that this variable was defined in is currently + Block *deepest_frame_block = + frame->GetSymbolContext(eSymbolContextBlock).block; + if (deepest_frame_block) { + SymbolContext variable_sc; + CalculateSymbolContext(&variable_sc); + + // Check for static or global variable defined at the compile unit + // level that wasn't defined in a block + if (variable_sc.block == nullptr) + return true; + + // Check if the variable is valid in the current block + if (variable_sc.block != deepest_frame_block && + !variable_sc.block->Contains(deepest_frame_block)) + return false; + + // If no scope range is specified then it means that the scope is the + // same as the + // scope of the enclosing lexical block. + if (m_scope_range.IsEmpty()) + return true; + + addr_t file_address = frame->GetFrameCodeAddress().GetFileAddress(); + return m_scope_range.FindEntryThatContains(file_address) != nullptr; + } } - return false; -} - -bool -Variable::IsInScope (StackFrame *frame) -{ - switch (m_scope) - { - case eValueTypeRegister: - case eValueTypeRegisterSet: - return frame != nullptr; - - case eValueTypeConstResult: - case eValueTypeVariableGlobal: - case eValueTypeVariableStatic: - case eValueTypeVariableThreadLocal: - return true; + break; - case eValueTypeVariableArgument: - case eValueTypeVariableLocal: - if (frame) - { - // We don't have a location list, we just need to see if the block - // that this variable was defined in is currently - Block *deepest_frame_block = frame->GetSymbolContext(eSymbolContextBlock).block; - if (deepest_frame_block) - { - SymbolContext variable_sc; - CalculateSymbolContext (&variable_sc); - - // Check for static or global variable defined at the compile unit - // level that wasn't defined in a block - if (variable_sc.block == nullptr) - return true; - - // Check if the variable is valid in the current block - if (variable_sc.block != deepest_frame_block && - !variable_sc.block->Contains(deepest_frame_block)) - return false; - - // If no scope range is specified then it means that the scope is the same as the - // scope of the enclosing lexical block. - if (m_scope_range.IsEmpty()) - return true; - - addr_t file_address = frame->GetFrameCodeAddress().GetFileAddress(); - return m_scope_range.FindEntryThatContains(file_address) != nullptr; - } - } - break; - - default: - break; - } - return false; + default: + break; + } + return false; } -Error -Variable::GetValuesForVariableExpressionPath (const char *variable_expr_path, - ExecutionContextScope *scope, - GetVariableCallback callback, - void *baton, - VariableList &variable_list, - ValueObjectList &valobj_list) -{ - Error error; - if (variable_expr_path && callback) - { - switch (variable_expr_path[0]) - { - case '*': - { - error = Variable::GetValuesForVariableExpressionPath (variable_expr_path + 1, - scope, - callback, - baton, - variable_list, - valobj_list); - if (error.Success()) - { - for (uint32_t i=0; i<valobj_list.GetSize(); ) - { - Error tmp_error; - ValueObjectSP valobj_sp (valobj_list.GetValueObjectAtIndex(i)->Dereference(tmp_error)); - if (tmp_error.Fail()) - { - variable_list.RemoveVariableAtIndex (i); - valobj_list.RemoveValueObjectAtIndex (i); - } - else - { - valobj_list.SetValueObjectAtIndex (i, valobj_sp); - ++i; - } - } - } - else - { - error.SetErrorString ("unknown error"); - } - return error; - } - break; - - case '&': - { - error = Variable::GetValuesForVariableExpressionPath (variable_expr_path + 1, - scope, - callback, - baton, - variable_list, - valobj_list); - if (error.Success()) - { - for (uint32_t i=0; i<valobj_list.GetSize(); ) - { - Error tmp_error; - ValueObjectSP valobj_sp (valobj_list.GetValueObjectAtIndex(i)->AddressOf(tmp_error)); - if (tmp_error.Fail()) - { - variable_list.RemoveVariableAtIndex (i); - valobj_list.RemoveValueObjectAtIndex (i); - } - else - { - valobj_list.SetValueObjectAtIndex (i, valobj_sp); - ++i; - } +Error Variable::GetValuesForVariableExpressionPath( + const char *variable_expr_path, ExecutionContextScope *scope, + GetVariableCallback callback, void *baton, VariableList &variable_list, + ValueObjectList &valobj_list) { + Error error; + if (variable_expr_path && callback) { + switch (variable_expr_path[0]) { + case '*': { + error = Variable::GetValuesForVariableExpressionPath( + variable_expr_path + 1, scope, callback, baton, variable_list, + valobj_list); + if (error.Success()) { + for (uint32_t i = 0; i < valobj_list.GetSize();) { + Error tmp_error; + ValueObjectSP valobj_sp( + valobj_list.GetValueObjectAtIndex(i)->Dereference(tmp_error)); + if (tmp_error.Fail()) { + variable_list.RemoveVariableAtIndex(i); + valobj_list.RemoveValueObjectAtIndex(i); + } else { + valobj_list.SetValueObjectAtIndex(i, valobj_sp); + ++i; + } + } + } else { + error.SetErrorString("unknown error"); + } + return error; + } break; + + case '&': { + error = Variable::GetValuesForVariableExpressionPath( + variable_expr_path + 1, scope, callback, baton, variable_list, + valobj_list); + if (error.Success()) { + for (uint32_t i = 0; i < valobj_list.GetSize();) { + Error tmp_error; + ValueObjectSP valobj_sp( + valobj_list.GetValueObjectAtIndex(i)->AddressOf(tmp_error)); + if (tmp_error.Fail()) { + variable_list.RemoveVariableAtIndex(i); + valobj_list.RemoveValueObjectAtIndex(i); + } else { + valobj_list.SetValueObjectAtIndex(i, valobj_sp); + ++i; + } + } + } else { + error.SetErrorString("unknown error"); + } + return error; + } break; + + default: { + static RegularExpression g_regex("^([A-Za-z_:][A-Za-z_0-9:]*)(.*)"); + RegularExpression::Match regex_match(1); + if (g_regex.Execute(variable_expr_path, ®ex_match)) { + std::string variable_name; + if (regex_match.GetMatchAtIndex(variable_expr_path, 1, variable_name)) { + variable_list.Clear(); + if (callback(baton, variable_name.c_str(), variable_list)) { + uint32_t i = 0; + while (i < variable_list.GetSize()) { + VariableSP var_sp(variable_list.GetVariableAtIndex(i)); + ValueObjectSP valobj_sp; + if (var_sp) { + ValueObjectSP variable_valobj_sp( + ValueObjectVariable::Create(scope, var_sp)); + if (variable_valobj_sp) { + const char *variable_sub_expr_path = + variable_expr_path + variable_name.size(); + if (*variable_sub_expr_path) { + const char *first_unparsed = nullptr; + ValueObject::ExpressionPathScanEndReason reason_to_stop; + ValueObject::ExpressionPathEndResultType final_value_type; + ValueObject::GetValueForExpressionPathOptions options; + ValueObject::ExpressionPathAftermath final_task_on_target; + + valobj_sp = variable_valobj_sp->GetValueForExpressionPath( + variable_sub_expr_path, &first_unparsed, + &reason_to_stop, &final_value_type, options, + &final_task_on_target); + if (!valobj_sp) { + error.SetErrorStringWithFormat( + "invalid expression path '%s' for variable '%s'", + variable_sub_expr_path, + var_sp->GetName().GetCString()); } + } else { + // Just the name of a variable with no extras + valobj_sp = variable_valobj_sp; + } } - else - { - error.SetErrorString ("unknown error"); - } - return error; + } + + if (!var_sp || !valobj_sp) { + variable_list.RemoveVariableAtIndex(i); + } else { + valobj_list.Append(valobj_sp); + ++i; + } } - break; - - default: - { - static RegularExpression g_regex ("^([A-Za-z_:][A-Za-z_0-9:]*)(.*)"); - RegularExpression::Match regex_match(1); - if (g_regex.Execute(variable_expr_path, ®ex_match)) - { - std::string variable_name; - if (regex_match.GetMatchAtIndex(variable_expr_path, 1, variable_name)) - { - variable_list.Clear(); - if (callback (baton, variable_name.c_str(), variable_list)) - { - uint32_t i=0; - while (i < variable_list.GetSize()) - { - VariableSP var_sp (variable_list.GetVariableAtIndex (i)); - ValueObjectSP valobj_sp; - if (var_sp) - { - ValueObjectSP variable_valobj_sp(ValueObjectVariable::Create (scope, var_sp)); - if (variable_valobj_sp) - { - const char *variable_sub_expr_path = variable_expr_path + variable_name.size(); - if (*variable_sub_expr_path) - { - const char* first_unparsed = nullptr; - ValueObject::ExpressionPathScanEndReason reason_to_stop; - ValueObject::ExpressionPathEndResultType final_value_type; - ValueObject::GetValueForExpressionPathOptions options; - ValueObject::ExpressionPathAftermath final_task_on_target; - - valobj_sp = variable_valobj_sp->GetValueForExpressionPath (variable_sub_expr_path, - &first_unparsed, - &reason_to_stop, - &final_value_type, - options, - &final_task_on_target); - if (!valobj_sp) - { - error.SetErrorStringWithFormat ("invalid expression path '%s' for variable '%s'", - variable_sub_expr_path, - var_sp->GetName().GetCString()); - } - } - else - { - // Just the name of a variable with no extras - valobj_sp = variable_valobj_sp; - } - } - } - - if (!var_sp || !valobj_sp) - { - variable_list.RemoveVariableAtIndex (i); - } - else - { - valobj_list.Append(valobj_sp); - ++i; - } - } - - if (variable_list.GetSize() > 0) - { - error.Clear(); - return error; - } - } - } - } - error.SetErrorStringWithFormat ("unable to extract a variable name from '%s'", variable_expr_path); + + if (variable_list.GetSize() > 0) { + error.Clear(); + return error; } - break; + } } + } + error.SetErrorStringWithFormat( + "unable to extract a variable name from '%s'", variable_expr_path); + } break; } - error.SetErrorString ("unknown error"); - return error; + } + error.SetErrorString("unknown error"); + return error; } -bool -Variable::DumpLocationForAddress (Stream *s, const Address &address) -{ - // Be sure to resolve the address to section offset prior to - // calling this function. - if (address.IsSectionOffset()) - { - SymbolContext sc; - CalculateSymbolContext(&sc); - if (sc.module_sp == address.GetModule()) - { - ABI *abi = nullptr; - if (m_owner_scope) - { - ModuleSP module_sp (m_owner_scope->CalculateSymbolContextModule()); - if (module_sp) - abi = ABI::FindPlugin (module_sp->GetArchitecture()).get(); - } - - const addr_t file_addr = address.GetFileAddress(); - if (sc.function) - { - if (sc.function->GetAddressRange().ContainsFileAddress(address)) - { - addr_t loclist_base_file_addr = sc.function->GetAddressRange().GetBaseAddress().GetFileAddress(); - if (loclist_base_file_addr == LLDB_INVALID_ADDRESS) - return false; - return m_location.DumpLocationForAddress (s, - eDescriptionLevelBrief, - loclist_base_file_addr, - file_addr, - abi); - } - } - return m_location.DumpLocationForAddress (s, - eDescriptionLevelBrief, - LLDB_INVALID_ADDRESS, - file_addr, - abi); +bool Variable::DumpLocationForAddress(Stream *s, const Address &address) { + // Be sure to resolve the address to section offset prior to + // calling this function. + if (address.IsSectionOffset()) { + SymbolContext sc; + CalculateSymbolContext(&sc); + if (sc.module_sp == address.GetModule()) { + ABI *abi = nullptr; + if (m_owner_scope) { + ModuleSP module_sp(m_owner_scope->CalculateSymbolContextModule()); + if (module_sp) + abi = ABI::FindPlugin(module_sp->GetArchitecture()).get(); + } + + const addr_t file_addr = address.GetFileAddress(); + if (sc.function) { + if (sc.function->GetAddressRange().ContainsFileAddress(address)) { + addr_t loclist_base_file_addr = + sc.function->GetAddressRange().GetBaseAddress().GetFileAddress(); + if (loclist_base_file_addr == LLDB_INVALID_ADDRESS) + return false; + return m_location.DumpLocationForAddress(s, eDescriptionLevelBrief, + loclist_base_file_addr, + file_addr, abi); } + } + return m_location.DumpLocationForAddress( + s, eDescriptionLevelBrief, LLDB_INVALID_ADDRESS, file_addr, abi); } - return false; + } + return false; } - -static void -PrivateAutoComplete (StackFrame *frame, - const std::string &partial_path, - const std::string &prefix_path, // Anything that has been resolved already will be in here - const CompilerType& compiler_type, - StringList &matches, - bool &word_complete); - -static void -PrivateAutoCompleteMembers (StackFrame *frame, - const std::string &partial_member_name, - const std::string &partial_path, - const std::string &prefix_path, // Anything that has been resolved already will be in here - const CompilerType& compiler_type, - StringList &matches, - bool &word_complete); - -static void -PrivateAutoCompleteMembers (StackFrame *frame, - const std::string &partial_member_name, - const std::string &partial_path, - const std::string &prefix_path, // Anything that has been resolved already will be in here - const CompilerType& compiler_type, - StringList &matches, - bool &word_complete) -{ - - // We are in a type parsing child members - const uint32_t num_bases = compiler_type.GetNumDirectBaseClasses(); - - if (num_bases > 0) - { - for (uint32_t i = 0; i < num_bases; ++i) - { - CompilerType base_class_type = compiler_type.GetDirectBaseClassAtIndex(i, nullptr); - - PrivateAutoCompleteMembers (frame, - partial_member_name, - partial_path, - prefix_path, - base_class_type.GetCanonicalType(), - matches, - word_complete); - } +static void PrivateAutoComplete( + StackFrame *frame, const std::string &partial_path, + const std::string + &prefix_path, // Anything that has been resolved already will be in here + const CompilerType &compiler_type, + StringList &matches, bool &word_complete); + +static void PrivateAutoCompleteMembers( + StackFrame *frame, const std::string &partial_member_name, + const std::string &partial_path, + const std::string + &prefix_path, // Anything that has been resolved already will be in here + const CompilerType &compiler_type, + StringList &matches, bool &word_complete); + +static void PrivateAutoCompleteMembers( + StackFrame *frame, const std::string &partial_member_name, + const std::string &partial_path, + const std::string + &prefix_path, // Anything that has been resolved already will be in here + const CompilerType &compiler_type, + StringList &matches, bool &word_complete) { + + // We are in a type parsing child members + const uint32_t num_bases = compiler_type.GetNumDirectBaseClasses(); + + if (num_bases > 0) { + for (uint32_t i = 0; i < num_bases; ++i) { + CompilerType base_class_type = + compiler_type.GetDirectBaseClassAtIndex(i, nullptr); + + PrivateAutoCompleteMembers( + frame, partial_member_name, partial_path, prefix_path, + base_class_type.GetCanonicalType(), matches, word_complete); } + } - const uint32_t num_vbases = compiler_type.GetNumVirtualBaseClasses(); - - if (num_vbases > 0) - { - for (uint32_t i = 0; i < num_vbases; ++i) - { - CompilerType vbase_class_type = compiler_type.GetVirtualBaseClassAtIndex(i,nullptr); - - PrivateAutoCompleteMembers (frame, - partial_member_name, - partial_path, - prefix_path, - vbase_class_type.GetCanonicalType(), - matches, - word_complete); - } - } + const uint32_t num_vbases = compiler_type.GetNumVirtualBaseClasses(); - // We are in a type parsing child members - const uint32_t num_fields = compiler_type.GetNumFields(); - - if (num_fields > 0) - { - for (uint32_t i = 0; i < num_fields; ++i) - { - std::string member_name; - - CompilerType member_compiler_type = compiler_type.GetFieldAtIndex (i, member_name, nullptr, nullptr, nullptr); - - if (partial_member_name.empty() || - member_name.find(partial_member_name) == 0) - { - if (member_name == partial_member_name) - { - PrivateAutoComplete (frame, - partial_path, - prefix_path + member_name, // Anything that has been resolved already will be in here - member_compiler_type.GetCanonicalType(), - matches, - word_complete); - } - else - { - matches.AppendString (prefix_path + member_name); - } - } + if (num_vbases > 0) { + for (uint32_t i = 0; i < num_vbases; ++i) { + CompilerType vbase_class_type = + compiler_type.GetVirtualBaseClassAtIndex(i, nullptr); + + PrivateAutoCompleteMembers( + frame, partial_member_name, partial_path, prefix_path, + vbase_class_type.GetCanonicalType(), matches, word_complete); + } + } + + // We are in a type parsing child members + const uint32_t num_fields = compiler_type.GetNumFields(); + + if (num_fields > 0) { + for (uint32_t i = 0; i < num_fields; ++i) { + std::string member_name; + + CompilerType member_compiler_type = compiler_type.GetFieldAtIndex( + i, member_name, nullptr, nullptr, nullptr); + + if (partial_member_name.empty() || + member_name.find(partial_member_name) == 0) { + if (member_name == partial_member_name) { + PrivateAutoComplete( + frame, partial_path, + prefix_path + member_name, // Anything that has been resolved + // already will be in here + member_compiler_type.GetCanonicalType(), matches, word_complete); + } else { + matches.AppendString(prefix_path + member_name); } + } } + } } -static void -PrivateAutoComplete (StackFrame *frame, - const std::string &partial_path, - const std::string &prefix_path, // Anything that has been resolved already will be in here - const CompilerType& compiler_type, - StringList &matches, - bool &word_complete) -{ -// printf ("\nPrivateAutoComplete()\n\tprefix_path = '%s'\n\tpartial_path = '%s'\n", prefix_path.c_str(), partial_path.c_str()); - std::string remaining_partial_path; - - const lldb::TypeClass type_class = compiler_type.GetTypeClass(); - if (partial_path.empty()) - { - if (compiler_type.IsValid()) - { - switch (type_class) - { - default: - case eTypeClassArray: - case eTypeClassBlockPointer: - case eTypeClassBuiltin: - case eTypeClassComplexFloat: - case eTypeClassComplexInteger: - case eTypeClassEnumeration: - case eTypeClassFunction: - case eTypeClassMemberPointer: - case eTypeClassReference: - case eTypeClassTypedef: - case eTypeClassVector: - { - matches.AppendString (prefix_path); - word_complete = matches.GetSize() == 1; - } - break; - - case eTypeClassClass: - case eTypeClassStruct: - case eTypeClassUnion: - if (prefix_path.back() != '.') - matches.AppendString (prefix_path + '.'); - break; - - case eTypeClassObjCObject: - case eTypeClassObjCInterface: - break; - case eTypeClassObjCObjectPointer: - case eTypeClassPointer: - { - bool omit_empty_base_classes = true; - if (compiler_type.GetNumChildren (omit_empty_base_classes) > 0) - matches.AppendString (prefix_path + "->"); - else - { - matches.AppendString (prefix_path); - word_complete = true; - } - } - break; - } +static void PrivateAutoComplete( + StackFrame *frame, const std::string &partial_path, + const std::string + &prefix_path, // Anything that has been resolved already will be in here + const CompilerType &compiler_type, + StringList &matches, bool &word_complete) { + // printf ("\nPrivateAutoComplete()\n\tprefix_path = '%s'\n\tpartial_path = + // '%s'\n", prefix_path.c_str(), partial_path.c_str()); + std::string remaining_partial_path; + + const lldb::TypeClass type_class = compiler_type.GetTypeClass(); + if (partial_path.empty()) { + if (compiler_type.IsValid()) { + switch (type_class) { + default: + case eTypeClassArray: + case eTypeClassBlockPointer: + case eTypeClassBuiltin: + case eTypeClassComplexFloat: + case eTypeClassComplexInteger: + case eTypeClassEnumeration: + case eTypeClassFunction: + case eTypeClassMemberPointer: + case eTypeClassReference: + case eTypeClassTypedef: + case eTypeClassVector: { + matches.AppendString(prefix_path); + word_complete = matches.GetSize() == 1; + } break; + + case eTypeClassClass: + case eTypeClassStruct: + case eTypeClassUnion: + if (prefix_path.back() != '.') + matches.AppendString(prefix_path + '.'); + break; + + case eTypeClassObjCObject: + case eTypeClassObjCInterface: + break; + case eTypeClassObjCObjectPointer: + case eTypeClassPointer: { + bool omit_empty_base_classes = true; + if (compiler_type.GetNumChildren(omit_empty_base_classes) > 0) + matches.AppendString(prefix_path + "->"); + else { + matches.AppendString(prefix_path); + word_complete = true; } - else - { - if (frame) - { - const bool get_file_globals = true; - - VariableList *variable_list = frame->GetVariableList(get_file_globals); - - if (variable_list) - { - const size_t num_variables = variable_list->GetSize(); - for (size_t i=0; i<num_variables; ++i) - { - Variable *variable = variable_list->GetVariableAtIndex(i).get(); - matches.AppendString (variable->GetName().AsCString()); - } - } - } + } break; + } + } else { + if (frame) { + const bool get_file_globals = true; + + VariableList *variable_list = frame->GetVariableList(get_file_globals); + + if (variable_list) { + const size_t num_variables = variable_list->GetSize(); + for (size_t i = 0; i < num_variables; ++i) { + Variable *variable = variable_list->GetVariableAtIndex(i).get(); + matches.AppendString(variable->GetName().AsCString()); + } } + } } - else - { - const char ch = partial_path[0]; - switch (ch) - { - case '*': - if (prefix_path.empty()) - { - PrivateAutoComplete (frame, - partial_path.substr(1), - std::string("*"), - compiler_type, - matches, - word_complete); - } - break; + } else { + const char ch = partial_path[0]; + switch (ch) { + case '*': + if (prefix_path.empty()) { + PrivateAutoComplete(frame, partial_path.substr(1), std::string("*"), + compiler_type, matches, word_complete); + } + break; + + case '&': + if (prefix_path.empty()) { + PrivateAutoComplete(frame, partial_path.substr(1), std::string("&"), + compiler_type, matches, word_complete); + } + break; + + case '-': + if (partial_path[1] == '>' && !prefix_path.empty()) { + switch (type_class) { + case lldb::eTypeClassPointer: { + CompilerType pointee_type(compiler_type.GetPointeeType()); + if (partial_path[2]) { + // If there is more after the "->", then search deeper + PrivateAutoComplete( + frame, partial_path.substr(2), prefix_path + "->", + pointee_type.GetCanonicalType(), matches, word_complete); + } else { + // Nothing after the "->", so list all members + PrivateAutoCompleteMembers( + frame, std::string(), std::string(), prefix_path + "->", + pointee_type.GetCanonicalType(), matches, word_complete); + } + } break; + default: + break; + } + } + break; + + case '.': + if (compiler_type.IsValid()) { + switch (type_class) { + case lldb::eTypeClassUnion: + case lldb::eTypeClassStruct: + case lldb::eTypeClassClass: + if (partial_path[1]) { + // If there is more after the ".", then search deeper + PrivateAutoComplete(frame, partial_path.substr(1), + prefix_path + ".", compiler_type, matches, + word_complete); + + } else { + // Nothing after the ".", so list all members + PrivateAutoCompleteMembers(frame, std::string(), partial_path, + prefix_path + ".", compiler_type, + matches, word_complete); + } + break; + default: + break; + } + } + break; + default: + if (isalpha(ch) || ch == '_' || ch == '$') { + const size_t partial_path_len = partial_path.size(); + size_t pos = 1; + while (pos < partial_path_len) { + const char curr_ch = partial_path[pos]; + if (isalnum(curr_ch) || curr_ch == '_' || curr_ch == '$') { + ++pos; + continue; + } + break; + } + + std::string token(partial_path, 0, pos); + remaining_partial_path = partial_path.substr(pos); - case '&': - if (prefix_path.empty()) - { - PrivateAutoComplete (frame, - partial_path.substr(1), - std::string("&"), - compiler_type, - matches, + if (compiler_type.IsValid()) { + PrivateAutoCompleteMembers(frame, token, remaining_partial_path, + prefix_path, compiler_type, matches, word_complete); - } - break; + } else if (frame) { + // We haven't found our variable yet + const bool get_file_globals = true; - case '-': - if (partial_path[1] == '>' && !prefix_path.empty()) - { - switch (type_class) - { - case lldb::eTypeClassPointer: - { - CompilerType pointee_type(compiler_type.GetPointeeType()); - if (partial_path[2]) - { - // If there is more after the "->", then search deeper - PrivateAutoComplete (frame, - partial_path.substr(2), - prefix_path + "->", - pointee_type.GetCanonicalType(), - matches, - word_complete); - } - else - { - // Nothing after the "->", so list all members - PrivateAutoCompleteMembers (frame, - std::string(), - std::string(), - prefix_path + "->", - pointee_type.GetCanonicalType(), - matches, - word_complete); - } - } - break; - default: - break; - } - } - break; - - case '.': - if (compiler_type.IsValid()) - { - switch (type_class) - { - case lldb::eTypeClassUnion: - case lldb::eTypeClassStruct: - case lldb::eTypeClassClass: - if (partial_path[1]) - { - // If there is more after the ".", then search deeper - PrivateAutoComplete (frame, - partial_path.substr(1), - prefix_path + ".", - compiler_type, - matches, - word_complete); - - } - else - { - // Nothing after the ".", so list all members - PrivateAutoCompleteMembers (frame, - std::string(), - partial_path, - prefix_path + ".", - compiler_type, - matches, - word_complete); - } - break; - default: - break; - } - } + VariableList *variable_list = + frame->GetVariableList(get_file_globals); + + if (!variable_list) break; - default: - if (isalpha(ch) || ch == '_' || ch == '$') - { - const size_t partial_path_len = partial_path.size(); - size_t pos = 1; - while (pos < partial_path_len) - { - const char curr_ch = partial_path[pos]; - if (isalnum(curr_ch) || curr_ch == '_' || curr_ch == '$') - { - ++pos; - continue; - } - break; - } - std::string token(partial_path, 0, pos); - remaining_partial_path = partial_path.substr(pos); - - if (compiler_type.IsValid()) - { - PrivateAutoCompleteMembers (frame, - token, - remaining_partial_path, - prefix_path, - compiler_type, - matches, - word_complete); - } - else if (frame) - { - // We haven't found our variable yet - const bool get_file_globals = true; - - VariableList *variable_list = frame->GetVariableList(get_file_globals); - - if (!variable_list) - break; - - const size_t num_variables = variable_list->GetSize(); - for (size_t i=0; i<num_variables; ++i) - { - Variable *variable = variable_list->GetVariableAtIndex(i).get(); - - if (!variable) - continue; - - const char *variable_name = variable->GetName().AsCString(); - if (strstr(variable_name, token.c_str()) == variable_name) - { - if (strcmp (variable_name, token.c_str()) == 0) - { - Type *variable_type = variable->GetType(); - if (variable_type) - { - CompilerType variable_compiler_type (variable_type->GetForwardCompilerType ()); - PrivateAutoComplete (frame, - remaining_partial_path, - prefix_path + token, // Anything that has been resolved already will be in here - variable_compiler_type.GetCanonicalType(), - matches, - word_complete); - } - else - { - matches.AppendString (prefix_path + variable_name); - } - } - else if (remaining_partial_path.empty()) - { - matches.AppendString (prefix_path + variable_name); - } - } - } + const size_t num_variables = variable_list->GetSize(); + for (size_t i = 0; i < num_variables; ++i) { + Variable *variable = variable_list->GetVariableAtIndex(i).get(); + + if (!variable) + continue; + + const char *variable_name = variable->GetName().AsCString(); + if (strstr(variable_name, token.c_str()) == variable_name) { + if (strcmp(variable_name, token.c_str()) == 0) { + Type *variable_type = variable->GetType(); + if (variable_type) { + CompilerType variable_compiler_type( + variable_type->GetForwardCompilerType()); + PrivateAutoComplete( + frame, remaining_partial_path, + prefix_path + token, // Anything that has been resolved + // already will be in here + variable_compiler_type.GetCanonicalType(), matches, + word_complete); + } else { + matches.AppendString(prefix_path + variable_name); } + } else if (remaining_partial_path.empty()) { + matches.AppendString(prefix_path + variable_name); + } } - break; + } } + } + break; } + } } +size_t Variable::AutoComplete(const ExecutionContext &exe_ctx, + const char *partial_path_cstr, + StringList &matches, bool &word_complete) { + word_complete = false; + std::string partial_path; + std::string prefix_path; + CompilerType compiler_type; + if (partial_path_cstr && partial_path_cstr[0]) + partial_path = partial_path_cstr; + PrivateAutoComplete(exe_ctx.GetFramePtr(), partial_path, prefix_path, + compiler_type, matches, word_complete); -size_t -Variable::AutoComplete (const ExecutionContext &exe_ctx, - const char *partial_path_cstr, - StringList &matches, - bool &word_complete) -{ - word_complete = false; - std::string partial_path; - std::string prefix_path; - CompilerType compiler_type; - if (partial_path_cstr && partial_path_cstr[0]) - partial_path = partial_path_cstr; - - PrivateAutoComplete (exe_ctx.GetFramePtr(), - partial_path, - prefix_path, - compiler_type, - matches, - word_complete); - - return matches.GetSize(); + return matches.GetSize(); } - diff --git a/lldb/source/Symbol/VariableList.cpp b/lldb/source/Symbol/VariableList.cpp index 487c5719434..a81b95b7937 100644 --- a/lldb/source/Symbol/VariableList.cpp +++ b/lldb/source/Symbol/VariableList.cpp @@ -11,8 +11,8 @@ #include "lldb/Core/RegularExpression.h" #include "lldb/Symbol/Block.h" -#include "lldb/Symbol/Function.h" #include "lldb/Symbol/CompileUnit.h" +#include "lldb/Symbol/Function.h" using namespace lldb; using namespace lldb_private; @@ -20,214 +20,162 @@ using namespace lldb_private; //---------------------------------------------------------------------- // VariableList constructor //---------------------------------------------------------------------- -VariableList::VariableList() : - m_variables() -{ -} +VariableList::VariableList() : m_variables() {} //---------------------------------------------------------------------- // Destructor //---------------------------------------------------------------------- -VariableList::~VariableList() -{ -} - -void -VariableList::AddVariable(const VariableSP &var_sp) -{ - m_variables.push_back(var_sp); -} - -bool -VariableList::AddVariableIfUnique (const lldb::VariableSP &var_sp) -{ - if (FindVariableIndex (var_sp) == UINT32_MAX) - { - m_variables.push_back(var_sp); - return true; - } - return false; -} +VariableList::~VariableList() {} -void -VariableList::AddVariables(VariableList *variable_list) -{ - if (variable_list) - { - std::copy(variable_list->m_variables.begin(), // source begin - variable_list->m_variables.end(), // source end - back_inserter(m_variables)); // destination - } -} - -void -VariableList::Clear() -{ - m_variables.clear(); -} - -VariableSP -VariableList::GetVariableAtIndex(size_t idx) const -{ - VariableSP var_sp; - if (idx < m_variables.size()) - var_sp = m_variables[idx]; - return var_sp; +void VariableList::AddVariable(const VariableSP &var_sp) { + m_variables.push_back(var_sp); } -VariableSP -VariableList::RemoveVariableAtIndex(size_t idx) -{ - VariableSP var_sp; - if (idx < m_variables.size()) - { - var_sp = m_variables[idx]; - m_variables.erase (m_variables.begin() + idx); - } - return var_sp; -} - -uint32_t -VariableList::FindVariableIndex (const VariableSP &var_sp) -{ - iterator pos, end = m_variables.end(); - for (pos = m_variables.begin(); pos != end; ++pos) - { - if (pos->get() == var_sp.get()) - return std::distance (m_variables.begin(), pos); +bool VariableList::AddVariableIfUnique(const lldb::VariableSP &var_sp) { + if (FindVariableIndex(var_sp) == UINT32_MAX) { + m_variables.push_back(var_sp); + return true; + } + return false; +} + +void VariableList::AddVariables(VariableList *variable_list) { + if (variable_list) { + std::copy(variable_list->m_variables.begin(), // source begin + variable_list->m_variables.end(), // source end + back_inserter(m_variables)); // destination + } +} + +void VariableList::Clear() { m_variables.clear(); } + +VariableSP VariableList::GetVariableAtIndex(size_t idx) const { + VariableSP var_sp; + if (idx < m_variables.size()) + var_sp = m_variables[idx]; + return var_sp; +} + +VariableSP VariableList::RemoveVariableAtIndex(size_t idx) { + VariableSP var_sp; + if (idx < m_variables.size()) { + var_sp = m_variables[idx]; + m_variables.erase(m_variables.begin() + idx); + } + return var_sp; +} + +uint32_t VariableList::FindVariableIndex(const VariableSP &var_sp) { + iterator pos, end = m_variables.end(); + for (pos = m_variables.begin(); pos != end; ++pos) { + if (pos->get() == var_sp.get()) + return std::distance(m_variables.begin(), pos); + } + return UINT32_MAX; +} + +VariableSP VariableList::FindVariable(const ConstString &name, + bool include_static_members) { + VariableSP var_sp; + iterator pos, end = m_variables.end(); + for (pos = m_variables.begin(); pos != end; ++pos) { + if ((*pos)->NameMatches(name)) { + if (include_static_members || !(*pos)->IsStaticMember()) { + var_sp = (*pos); + break; + } } - return UINT32_MAX; -} - -VariableSP -VariableList::FindVariable(const ConstString& name, bool include_static_members) -{ - VariableSP var_sp; - iterator pos, end = m_variables.end(); - for (pos = m_variables.begin(); pos != end; ++pos) - { - if ((*pos)->NameMatches(name)) - { - if (include_static_members || !(*pos)->IsStaticMember()) - { - var_sp = (*pos); - break; - } - } + } + return var_sp; +} + +VariableSP VariableList::FindVariable(const ConstString &name, + lldb::ValueType value_type, + bool include_static_members) { + VariableSP var_sp; + iterator pos, end = m_variables.end(); + for (pos = m_variables.begin(); pos != end; ++pos) { + if ((*pos)->NameMatches(name) && (*pos)->GetScope() == value_type) { + if (include_static_members || !(*pos)->IsStaticMember()) { + var_sp = (*pos); + break; + } } - return var_sp; -} - -VariableSP -VariableList::FindVariable (const ConstString& name, lldb::ValueType value_type, bool include_static_members) -{ - VariableSP var_sp; - iterator pos, end = m_variables.end(); - for (pos = m_variables.begin(); pos != end; ++pos) - { - if ((*pos)->NameMatches(name) && (*pos)->GetScope() == value_type) - { - if (include_static_members || !(*pos)->IsStaticMember()) - { - var_sp = (*pos); - break; - } - } + } + return var_sp; +} + +size_t VariableList::AppendVariablesIfUnique(VariableList &var_list) { + const size_t initial_size = var_list.GetSize(); + iterator pos, end = m_variables.end(); + for (pos = m_variables.begin(); pos != end; ++pos) + var_list.AddVariableIfUnique(*pos); + return var_list.GetSize() - initial_size; +} + +size_t VariableList::AppendVariablesIfUnique(const RegularExpression ®ex, + VariableList &var_list, + size_t &total_matches) { + const size_t initial_size = var_list.GetSize(); + iterator pos, end = m_variables.end(); + for (pos = m_variables.begin(); pos != end; ++pos) { + if ((*pos)->NameMatches(regex)) { + // Note the total matches found + total_matches++; + // Only add this variable if it isn't already in the "var_list" + var_list.AddVariableIfUnique(*pos); } - return var_sp; -} - -size_t -VariableList::AppendVariablesIfUnique(VariableList &var_list) -{ - const size_t initial_size = var_list.GetSize(); - iterator pos, end = m_variables.end(); - for (pos = m_variables.begin(); pos != end; ++pos) + } + // Return the number of new unique variables added to "var_list" + return var_list.GetSize() - initial_size; +} + +size_t VariableList::AppendVariablesWithScope(lldb::ValueType type, + VariableList &var_list, + bool if_unique) { + const size_t initial_size = var_list.GetSize(); + iterator pos, end = m_variables.end(); + for (pos = m_variables.begin(); pos != end; ++pos) { + if ((*pos)->GetScope() == type) { + if (if_unique) var_list.AddVariableIfUnique(*pos); - return var_list.GetSize() - initial_size; -} - -size_t -VariableList::AppendVariablesIfUnique (const RegularExpression& regex, VariableList &var_list, size_t& total_matches) -{ - const size_t initial_size = var_list.GetSize(); - iterator pos, end = m_variables.end(); - for (pos = m_variables.begin(); pos != end; ++pos) - { - if ((*pos)->NameMatches (regex)) - { - // Note the total matches found - total_matches++; - // Only add this variable if it isn't already in the "var_list" - var_list.AddVariableIfUnique (*pos); - } - } - // Return the number of new unique variables added to "var_list" - return var_list.GetSize() - initial_size; -} - -size_t -VariableList::AppendVariablesWithScope (lldb::ValueType type, - VariableList &var_list, - bool if_unique) -{ - const size_t initial_size = var_list.GetSize(); - iterator pos, end = m_variables.end(); - for (pos = m_variables.begin(); pos != end; ++pos) - { - if ((*pos)->GetScope() == type) - { - if (if_unique) - var_list.AddVariableIfUnique (*pos); - else - var_list.AddVariable(*pos); - } - } - // Return the number of new unique variables added to "var_list" - return var_list.GetSize() - initial_size; -} - -uint32_t -VariableList::FindIndexForVariable (Variable* variable) -{ - VariableSP var_sp; - iterator pos; - const iterator begin = m_variables.begin(); - const iterator end = m_variables.end(); - for (pos = m_variables.begin(); pos != end; ++pos) - { - if ((*pos).get() == variable) - return std::distance (begin, pos); - } - return UINT32_MAX; -} - -size_t -VariableList::MemorySize() const -{ - size_t mem_size = sizeof(VariableList); - const_iterator pos, end = m_variables.end(); - for (pos = m_variables.begin(); pos != end; ++pos) - mem_size += (*pos)->MemorySize(); - return mem_size; -} - -size_t -VariableList::GetSize() const -{ - return m_variables.size(); -} - -void -VariableList::Dump(Stream *s, bool show_context) const -{ -// s.Printf("%.*p: ", (int)sizeof(void*) * 2, this); -// s.Indent(); -// s << "VariableList\n"; - - const_iterator pos, end = m_variables.end(); - for (pos = m_variables.begin(); pos != end; ++pos) - { - (*pos)->Dump(s, show_context); + else + var_list.AddVariable(*pos); } + } + // Return the number of new unique variables added to "var_list" + return var_list.GetSize() - initial_size; +} + +uint32_t VariableList::FindIndexForVariable(Variable *variable) { + VariableSP var_sp; + iterator pos; + const iterator begin = m_variables.begin(); + const iterator end = m_variables.end(); + for (pos = m_variables.begin(); pos != end; ++pos) { + if ((*pos).get() == variable) + return std::distance(begin, pos); + } + return UINT32_MAX; +} + +size_t VariableList::MemorySize() const { + size_t mem_size = sizeof(VariableList); + const_iterator pos, end = m_variables.end(); + for (pos = m_variables.begin(); pos != end; ++pos) + mem_size += (*pos)->MemorySize(); + return mem_size; +} + +size_t VariableList::GetSize() const { return m_variables.size(); } + +void VariableList::Dump(Stream *s, bool show_context) const { + // s.Printf("%.*p: ", (int)sizeof(void*) * 2, this); + // s.Indent(); + // s << "VariableList\n"; + + const_iterator pos, end = m_variables.end(); + for (pos = m_variables.begin(); pos != end; ++pos) { + (*pos)->Dump(s, show_context); + } } diff --git a/lldb/source/Symbol/VerifyDecl.cpp b/lldb/source/Symbol/VerifyDecl.cpp index 765568040ec..96ed47a527a 100644 --- a/lldb/source/Symbol/VerifyDecl.cpp +++ b/lldb/source/Symbol/VerifyDecl.cpp @@ -10,7 +10,4 @@ #include "lldb/Symbol/VerifyDecl.h" #include "clang/AST/DeclBase.h" -void lldb_private::VerifyDecl (clang::Decl *decl) -{ - decl->getAccess(); -} +void lldb_private::VerifyDecl(clang::Decl *decl) { decl->getAccess(); } |