diff options
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 95207cb..1995149 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 9d50c5c..6c4c28d 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 21cfeff..e7fda6d 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 6be1060..c0e8fea 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 6c804f4..e39baea 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 77aea1e..69263fa 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 76d621e..7a67df48 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 105c3c2..e3da6f1 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 259a450..8ba83d4 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 98eef06..2b632c5 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 10a70d9..43a83bb 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 ef788d0..2684db9 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 5318327..9504ea1 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 88a28ba..22576ee 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 c72ca04..5d1dbde 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 2fa41b8..0abd8a2 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 598af27..06f8ad5 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 faca778..0c69007 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 45cda8d..79073a6 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 9b3a043..691afdf 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 6b4dea7..02ab0c1 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 1f2f57a2..8176fa1 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 18da7ef..fd233cc 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 1fa792c..623930c 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 1e55ce6..2fa30b7 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 808dfd3..8d8b606 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 c569943..f47bfd0 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 ca88ebe..8461974 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 8b51d99..2374a6d 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 f181dd6..4d32afc 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 6dc22cc..21eb611 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 3aadcaa..3f68f623 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 18f0cb7..8a20ef8 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 87c18d9..336f0c3 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 dd27b1b..6ba6cf9 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 487c571..a81b95b 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 7655680..96ed47a 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(); } |