diff options
Diffstat (limited to 'lldb/include/lldb/Utility')
54 files changed, 1165 insertions, 1330 deletions
diff --git a/lldb/include/lldb/Utility/AnsiTerminal.h b/lldb/include/lldb/Utility/AnsiTerminal.h index 21375e3821ca..c391adb2cf89 100644 --- a/lldb/include/lldb/Utility/AnsiTerminal.h +++ b/lldb/include/lldb/Utility/AnsiTerminal.h @@ -1,3 +1,7 @@ +#ifndef LLDB_UTILITY_ANSITERMINAL_H + +#define LLDB_UTILITY_ANSITERMINAL_H + //===---------------------AnsiTerminal.h ------------------------*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. @@ -111,7 +115,7 @@ inline std::string FormatAnsiTerminalCodes(llvm::StringRef format, llvm::StringRef left, right; std::tie(left, right) = format.split(tok_hdr); - fmt.append(left); + fmt += left; if (left == format && right.empty()) { // The header was not found. Just exit. @@ -138,3 +142,5 @@ inline std::string FormatAnsiTerminalCodes(llvm::StringRef format, } } } // namespace lldb_private + +#endif diff --git a/lldb/include/lldb/Utility/ArchSpec.h b/lldb/include/lldb/Utility/ArchSpec.h index 15e2fdb10c32..5466e573c1a5 100644 --- a/lldb/include/lldb/Utility/ArchSpec.h +++ b/lldb/include/lldb/Utility/ArchSpec.h @@ -16,6 +16,7 @@ #include "lldb/lldb-private-enumerations.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/Triple.h" +#include "llvm/Support/YAMLTraits.h" #include <cstddef> #include <cstdint> #include <string> @@ -188,6 +189,10 @@ public: eCore_arc, // little endian ARC + eCore_avr, + + eCore_wasm32, + kNumCores, kCore_invalid, @@ -537,4 +542,16 @@ bool ParseMachCPUDashSubtypeTriple(llvm::StringRef triple_str, ArchSpec &arch); } // namespace lldb_private -#endif // #ifndef LLDB_UTILITY_ARCHSPEC_H +namespace llvm { +namespace yaml { +template <> struct ScalarTraits<lldb_private::ArchSpec> { + static void output(const lldb_private::ArchSpec &, void *, raw_ostream &); + static StringRef input(StringRef, void *, lldb_private::ArchSpec &); + static QuotingType mustQuote(StringRef S) { return QuotingType::Double; } +}; +} // namespace yaml +} // namespace llvm + +LLVM_YAML_IS_SEQUENCE_VECTOR(lldb_private::ArchSpec) + +#endif // LLDB_UTILITY_ARCHSPEC_H diff --git a/lldb/include/lldb/Utility/Args.h b/lldb/include/lldb/Utility/Args.h index 1308f4038dbd..2cce7d0c697c 100644 --- a/lldb/include/lldb/Utility/Args.h +++ b/lldb/include/lldb/Utility/Args.h @@ -14,6 +14,7 @@ #include "lldb/lldb-types.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/StringRef.h" +#include "llvm/Support/YAMLTraits.h" #include <string> #include <utility> #include <vector> @@ -34,6 +35,9 @@ public: struct ArgEntry { private: friend class Args; + friend struct llvm::yaml::MappingTraits<Args>; + friend struct llvm::yaml::MappingTraits<Args::ArgEntry>; + std::unique_ptr<char[]> ptr; char quote; @@ -283,6 +287,8 @@ public: char quote_char); private: + friend struct llvm::yaml::MappingTraits<Args>; + std::vector<ArgEntry> m_entries; std::vector<char *> m_argv; }; @@ -373,4 +379,28 @@ private: } // namespace lldb_private +namespace llvm { +namespace yaml { +template <> struct MappingTraits<lldb_private::Args::ArgEntry> { + class NormalizedArgEntry { + public: + NormalizedArgEntry(IO &) {} + NormalizedArgEntry(IO &, lldb_private::Args::ArgEntry &entry) + : value(entry.ref()), quote(entry.quote) {} + lldb_private::Args::ArgEntry denormalize(IO &) { + return lldb_private::Args::ArgEntry(value, quote); + } + StringRef value; + uint8_t quote; + }; + static void mapping(IO &io, lldb_private::Args::ArgEntry &v); +}; +template <> struct MappingTraits<lldb_private::Args> { + static void mapping(IO &io, lldb_private::Args &v); +}; +} // namespace yaml +} // namespace llvm + +LLVM_YAML_IS_SEQUENCE_VECTOR(lldb_private::Args::ArgEntry) + #endif // LLDB_UTILITY_ARGS_H diff --git a/lldb/include/lldb/Utility/Baton.h b/lldb/include/lldb/Utility/Baton.h index c42867489c65..010f8da43868 100644 --- a/lldb/include/lldb/Utility/Baton.h +++ b/lldb/include/lldb/Utility/Baton.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef lldb_Baton_h_ -#define lldb_Baton_h_ +#ifndef LLDB_UTILITY_BATON_H +#define LLDB_UTILITY_BATON_H #include "lldb/lldb-enumerations.h" #include "lldb/lldb-public.h" @@ -76,4 +76,4 @@ protected: } // namespace lldb_private -#endif // lldb_Baton_h_ +#endif // LLDB_UTILITY_BATON_H diff --git a/lldb/include/lldb/Utility/Broadcaster.h b/lldb/include/lldb/Utility/Broadcaster.h index ead597d626d7..03995454ecb0 100644 --- a/lldb/include/lldb/Utility/Broadcaster.h +++ b/lldb/include/lldb/Utility/Broadcaster.h @@ -259,19 +259,6 @@ public: void CheckInWithManager(); /// Broadcast an event which has no associated data. - /// - /// \param[in] event_type - /// The element from the enum defining this broadcaster's events - /// that is being broadcast. - /// - /// \param[in] event_data - /// User event data that will be owned by the lldb::Event that - /// is created internally. - /// - /// \param[in] unique - /// If true, then only add an event of this type if there isn't - /// one already in the queue. - /// void BroadcastEvent(lldb::EventSP &event_sp) { m_broadcaster_sp->BroadcastEvent(event_sp); } @@ -308,7 +295,7 @@ public: /// different from what is requested in \a event_mask, and to track this the /// actual event bits that are acquired get returned. /// - /// \param[in] listener + /// \param[in] listener_sp /// The Listener object that wants to monitor the events that /// get broadcast by this object. /// @@ -347,9 +334,6 @@ public: /// \param[in] event_mask /// A bit mask that indicates which events the listener is /// asking to monitor. - /// - /// \return - /// The NULL terminated C string name of this Broadcaster. void SetEventName(uint32_t event_mask, const char *name) { m_broadcaster_sp->SetEventName(event_mask, name); } @@ -367,7 +351,7 @@ public: /// (assuming \a listener was listening to this object) for other listener /// objects to use. /// - /// \param[in] listener + /// \param[in] listener_sp /// A Listener object that previously called AddListener. /// /// \param[in] event_mask @@ -389,7 +373,7 @@ public: /// now go to the hijacking listener. Only one hijack can occur at a time. /// If we need more than this we will have to implement a Listener stack. /// - /// \param[in] listener + /// \param[in] listener_sp /// A Listener object. You do not need to call StartListeningForEvents /// for this broadcaster (that would fail anyway since the event bits /// would most likely be taken by the listener(s) you are usurping. @@ -530,7 +514,8 @@ protected: std::vector<uint32_t> m_hijacking_masks; private: - DISALLOW_COPY_AND_ASSIGN(BroadcasterImpl); + BroadcasterImpl(const BroadcasterImpl &) = delete; + const BroadcasterImpl &operator=(const BroadcasterImpl &) = delete; }; typedef std::shared_ptr<BroadcasterImpl> BroadcasterImplSP; @@ -549,7 +534,8 @@ private: /// The name of this broadcaster object. const ConstString m_broadcaster_name; - DISALLOW_COPY_AND_ASSIGN(Broadcaster); + Broadcaster(const Broadcaster &) = delete; + const Broadcaster &operator=(const Broadcaster &) = delete; }; } // namespace lldb_private diff --git a/lldb/include/lldb/Utility/CompletionRequest.h b/lldb/include/lldb/Utility/CompletionRequest.h index 570f626ac54e..1fbc96944e82 100644 --- a/lldb/include/lldb/Utility/CompletionRequest.h +++ b/lldb/include/lldb/Utility/CompletionRequest.h @@ -17,16 +17,21 @@ namespace lldb_private { enum class CompletionMode { - // The current token has been completed. + /// The current token has been completed. The client should indicate this + /// to the user (usually this is done by adding a trailing space behind the + /// token). + /// Example: "command sub" -> "command subcommand " (note the trailing space). Normal, - // The current token has been partially completed. This means that we found - // a completion, but that the completed token is still incomplete. Examples - // for this are file paths, where we want to complete "/bi" to "/bin/", but - // the file path token is still incomplete after the completion. Clients - // should not indicate to the user that this is a full completion (e.g. by - // not inserting the usual trailing space after a successful completion). + /// The current token has been partially completed. This means that we found + /// a completion, but that the token is still incomplete. Examples + /// for this are file paths, where we want to complete "/bi" to "/bin/", but + /// the file path token is still incomplete after the completion. Clients + /// should not indicate to the user that this is a full completion (e.g. by + /// not inserting the usual trailing space after a successful completion). + /// Example: "file /us" -> "file /usr/" (note the missing trailing space). Partial, - // The full line has been rewritten by the completion. + /// The full line has been rewritten by the completion. + /// Example: "alias name" -> "other_command full_name". RewriteLine, }; @@ -35,7 +40,12 @@ public: /// A single completion and all associated data. class Completion { + /// The actual text that should be completed. The meaning of this text + /// is defined by the CompletionMode. + /// \see m_mode std::string m_completion; + /// The description that should be displayed to the user alongside the + /// completion text. std::string m_descripton; CompletionMode m_mode; @@ -53,9 +63,12 @@ public: }; private: + /// List of found completions. std::vector<Completion> m_results; - /// List of added completions so far. Used to filter out duplicates. + /// A set of the unique keys of all found completions so far. Used to filter + /// out duplicates. + /// \see CompletionResult::Completion::GetUniqueKey llvm::StringSet<> m_added_values; public: @@ -102,7 +115,19 @@ public: CompletionRequest(llvm::StringRef command_line, unsigned raw_cursor_pos, CompletionResult &result); - llvm::StringRef GetRawLine() const { return m_command; } + /// Returns the raw user input used to create this CompletionRequest cut off + /// at the cursor position. The cursor will be at the end of the raw line. + llvm::StringRef GetRawLine() const { + return m_command.substr(0, GetRawCursorPos()); + } + + /// Returns the full raw user input used to create this CompletionRequest. + /// This string is not cut off at the cursor position and will include + /// characters behind the cursor position. + /// + /// You should most likely *not* use this function unless the characters + /// behind the cursor position influence the completion. + llvm::StringRef GetRawLineWithUnusedSuffix() const { return m_command; } unsigned GetRawCursorPos() const { return m_raw_cursor_pos; } @@ -135,8 +160,8 @@ public: /// the suggested completion is stored, so the given string can be free'd /// afterwards. /// - /// \param match The suggested completion. - /// \param completion An optional description of the completion string. The + /// \param completion The suggested completion. + /// \param description An optional description of the completion string. The /// description will be displayed to the user alongside the completion. /// \param mode The CompletionMode for this completion. void AddCompletion(llvm::StringRef completion, @@ -148,7 +173,7 @@ public: /// Adds a possible completion string if the completion would complete the /// current argument. /// - /// \param match The suggested completion. + /// \param completion The suggested completion. /// \param description An optional description of the completion string. The /// description will be displayed to the user alongside the completion. template <CompletionMode M = CompletionMode::Normal> @@ -178,7 +203,7 @@ public: /// The number of completions and descriptions must be identical. /// /// \param completions The list of completions. - /// \param completions The list of descriptions. + /// \param descriptions The list of descriptions. /// /// \see AddCompletion void AddCompletions(const StringList &completions, diff --git a/lldb/include/lldb/Utility/Connection.h b/lldb/include/lldb/Utility/Connection.h index 9e66dee1363b..39e6e40191b0 100644 --- a/lldb/include/lldb/Utility/Connection.h +++ b/lldb/include/lldb/Utility/Connection.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef liblldb_Connection_h_ -#define liblldb_Connection_h_ +#ifndef LLDB_UTILITY_CONNECTION_H +#define LLDB_UTILITY_CONNECTION_H #include "lldb/lldb-defines.h" #include "lldb/lldb-enumerations.h" @@ -125,7 +125,7 @@ public: /// Subclasses must override this function. /// /// \param[in] dst - /// A desination buffer that must be at least \a dst_len bytes + /// A destination buffer that must be at least \a dst_len bytes /// long. /// /// \param[in] dst_len @@ -175,9 +175,10 @@ public: private: // For Connection only - DISALLOW_COPY_AND_ASSIGN(Connection); + Connection(const Connection &) = delete; + const Connection &operator=(const Connection &) = delete; }; } // namespace lldb_private -#endif // liblldb_Connection_h_ +#endif // LLDB_UTILITY_CONNECTION_H diff --git a/lldb/include/lldb/Utility/ConstString.h b/lldb/include/lldb/Utility/ConstString.h index 74750459d16f..1e55b2ebb957 100644 --- a/lldb/include/lldb/Utility/ConstString.h +++ b/lldb/include/lldb/Utility/ConstString.h @@ -6,12 +6,13 @@ // //===----------------------------------------------------------------------===// -#ifndef liblldb_ConstString_h_ -#define liblldb_ConstString_h_ +#ifndef LLDB_UTILITY_CONSTSTRING_H +#define LLDB_UTILITY_CONSTSTRING_H -#include "llvm/ADT/StringRef.h" #include "llvm/ADT/DenseMapInfo.h" +#include "llvm/ADT/StringRef.h" #include "llvm/Support/FormatVariadic.h" +#include "llvm/Support/YAMLTraits.h" #include <stddef.h> @@ -481,6 +482,21 @@ template <> struct DenseMapInfo<lldb_private::ConstString> { } }; /// \} + +namespace yaml { +template <> struct ScalarTraits<lldb_private::ConstString> { + static void output(const lldb_private::ConstString &, void *, raw_ostream &); + static StringRef input(StringRef, void *, lldb_private::ConstString &); + static QuotingType mustQuote(StringRef S) { return QuotingType::Double; } +}; +} // namespace yaml + +inline raw_ostream &operator<<(raw_ostream &os, lldb_private::ConstString s) { + os << s.GetStringRef(); + return os; } +} // namespace llvm + +LLVM_YAML_IS_SEQUENCE_VECTOR(lldb_private::ConstString) -#endif // liblldb_ConstString_h_ +#endif // LLDB_UTILITY_CONSTSTRING_H diff --git a/lldb/include/lldb/Utility/DataBuffer.h b/lldb/include/lldb/Utility/DataBuffer.h index 523569301e84..302b13307958 100644 --- a/lldb/include/lldb/Utility/DataBuffer.h +++ b/lldb/include/lldb/Utility/DataBuffer.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef liblldb_DataBuffer_h_ -#define liblldb_DataBuffer_h_ +#ifndef LLDB_UTILITY_DATABUFFER_H +#define LLDB_UTILITY_DATABUFFER_H #if defined(__cplusplus) #include <stdint.h> @@ -79,7 +79,21 @@ public: } }; +class DataBufferUnowned : public DataBuffer { +public: + DataBufferUnowned(uint8_t *bytes, lldb::offset_t size) + : m_bytes(bytes), m_size(size) {} + + uint8_t *GetBytes() override { return m_bytes; } + const uint8_t *GetBytes() const override { return m_bytes; } + lldb::offset_t GetByteSize() const override { return m_size; } + +private: + uint8_t *m_bytes; + lldb::offset_t m_size; +}; + } // namespace lldb_private #endif /// #if defined(__cplusplus) -#endif /// lldb_DataBuffer_h_ +#endif // LLDB_UTILITY_DATABUFFER_H diff --git a/lldb/include/lldb/Utility/DataBufferHeap.h b/lldb/include/lldb/Utility/DataBufferHeap.h index 2a64694d7f29..ace526bf0a47 100644 --- a/lldb/include/lldb/Utility/DataBufferHeap.h +++ b/lldb/include/lldb/Utility/DataBufferHeap.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef liblldb_DataBufferHeap_h_ -#define liblldb_DataBufferHeap_h_ +#ifndef LLDB_UTILITY_DATABUFFERHEAP_H +#define LLDB_UTILITY_DATABUFFERHEAP_H #include "lldb/Utility/DataBuffer.h" #include "lldb/lldb-types.h" @@ -109,4 +109,4 @@ private: } // namespace lldb_private -#endif // liblldb_DataBufferHeap_h_ +#endif // LLDB_UTILITY_DATABUFFERHEAP_H diff --git a/lldb/include/lldb/Utility/DataBufferLLVM.h b/lldb/include/lldb/Utility/DataBufferLLVM.h index d4c110743068..4dc800c348c5 100644 --- a/lldb/include/lldb/Utility/DataBufferLLVM.h +++ b/lldb/include/lldb/Utility/DataBufferLLVM.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLDB_CORE_DATABUFFERLLVM_H -#define LLDB_CORE_DATABUFFERLLVM_H +#ifndef LLDB_UTILITY_DATABUFFERLLVM_H +#define LLDB_UTILITY_DATABUFFERLLVM_H #include "lldb/Utility/DataBuffer.h" #include "lldb/lldb-types.h" diff --git a/lldb/include/lldb/Utility/DataEncoder.h b/lldb/include/lldb/Utility/DataEncoder.h index f4964b250b9d..8edec54c36f5 100644 --- a/lldb/include/lldb/Utility/DataEncoder.h +++ b/lldb/include/lldb/Utility/DataEncoder.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef liblldb_DataEncoder_h_ -#define liblldb_DataEncoder_h_ +#ifndef LLDB_UTILITY_DATAENCODER_H +#define LLDB_UTILITY_DATAENCODER_H #if defined(__cplusplus) @@ -225,7 +225,6 @@ private: /// The total number of bytes of data this object refers to. size_t GetByteSize() const { return m_end - m_start; } -private: /// A pointer to the first byte of data. uint8_t *m_start; @@ -243,10 +242,11 @@ private: /// be shared among multiple instances mutable lldb::DataBufferSP m_data_sp; - DISALLOW_COPY_AND_ASSIGN(DataEncoder); + DataEncoder(const DataEncoder &) = delete; + const DataEncoder &operator=(const DataEncoder &) = delete; }; } // namespace lldb_private #endif // #if defined (__cplusplus) -#endif // #ifndef liblldb_DataEncoder_h_ +#endif // LLDB_UTILITY_DATAENCODER_H diff --git a/lldb/include/lldb/Utility/DataExtractor.h b/lldb/include/lldb/Utility/DataExtractor.h index bf0d1055cf43..0210af5cf6d1 100644 --- a/lldb/include/lldb/Utility/DataExtractor.h +++ b/lldb/include/lldb/Utility/DataExtractor.h @@ -9,12 +9,14 @@ #ifndef LLDB_UTILITY_DATAEXTRACTOR_H #define LLDB_UTILITY_DATAEXTRACTOR_H +#include "lldb/Utility/Endian.h" #include "lldb/lldb-defines.h" #include "lldb/lldb-enumerations.h" #include "lldb/lldb-forward.h" #include "lldb/lldb-types.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/Support/DataExtractor.h" +#include "llvm/Support/SwapByteOrder.h" #include <cassert> #include <stdint.h> @@ -535,13 +537,13 @@ public: uint32_t bitfield_bit_size, uint32_t bitfield_bit_offset) const; - /// Extract an signed integer of size \a byte_size from \a *offset_ptr, then - /// extract and signe extend the bitfield from this value if \a + /// Extract an signed integer of size \a size from \a *offset_ptr, then + /// extract and sign-extend the bitfield from this value if \a /// bitfield_bit_size is non-zero. /// - /// Extract a single signed integer value (sign extending if required) and + /// Extract a single signed integer value (sign-extending if required) and /// update the offset pointed to by \a offset_ptr. The size of the extracted - /// integer is specified by the \a byte_size argument. \a byte_size must + /// integer is specified by the \a size argument. \a size must /// have a value greater than or equal to one and less than or equal to /// eight since the return value is 64 bits wide. /// @@ -573,24 +575,6 @@ public: uint32_t bitfield_bit_size, uint32_t bitfield_bit_offset) const; - /// Extract an pointer from \a *offset_ptr. - /// - /// Extract a single pointer from the data and update the offset pointed to - /// by \a offset_ptr. The size of the extracted pointer comes from the \a - /// m_addr_size member variable and should be set correctly prior to - /// extracting any pointer values. - /// - /// \param[in,out] offset_ptr - /// A pointer to an offset within the data that will be advanced - /// by the appropriate number of bytes if the value is extracted - /// correctly. If the offset is out of bounds or there are not - /// enough bytes to extract this value, the offset will be left - /// unmodified. - /// - /// \return - /// The extracted pointer value as a 64 integer. - uint64_t GetPointer(lldb::offset_t *offset_ptr) const; - /// Get the current byte order value. /// /// \return @@ -997,19 +981,33 @@ public: } protected: + template <typename T> T Get(lldb::offset_t *offset_ptr, T fail_value) const { + constexpr size_t src_size = sizeof(T); + T val = fail_value; + + const T *src = static_cast<const T *>(GetData(offset_ptr, src_size)); + if (!src) + return val; + + memcpy(&val, src, src_size); + if (m_byte_order != endian::InlHostByteOrder()) + llvm::sys::swapByteOrder(val); + + return val; + } + // Member variables const uint8_t *m_start; ///< A pointer to the first byte of data. const uint8_t *m_end; ///< A pointer to the byte that is past the end of the data. lldb::ByteOrder m_byte_order; ///< The byte order of the data we are extracting from. - uint32_t m_addr_size; ///< The address size to use when extracting pointers or - /// addresses - mutable lldb::DataBufferSP m_data_sp; ///< The shared pointer to data that can - /// be shared among multiple instances + uint32_t m_addr_size; ///< The address size to use when extracting addresses. + /// The shared pointer to data that can be shared among multiple instances + lldb::DataBufferSP m_data_sp; const uint32_t m_target_byte_size; }; } // namespace lldb_private -#endif // liblldb_DataExtractor_h_ +#endif // LLDB_UTILITY_DATAEXTRACTOR_H diff --git a/lldb/include/lldb/Utility/Endian.h b/lldb/include/lldb/Utility/Endian.h index cead5f8603d2..1d1f8fa333b8 100644 --- a/lldb/include/lldb/Utility/Endian.h +++ b/lldb/include/lldb/Utility/Endian.h @@ -30,4 +30,4 @@ inline lldb::ByteOrder InlHostByteOrder() { } } -#endif // liblldb_host_endian_h_ +#endif // LLDB_UTILITY_ENDIAN_H diff --git a/lldb/include/lldb/Utility/Environment.h b/lldb/include/lldb/Utility/Environment.h index 398b3bae3106..e2af2eb2463d 100644 --- a/lldb/include/lldb/Utility/Environment.h +++ b/lldb/include/lldb/Utility/Environment.h @@ -50,6 +50,7 @@ public: using Base::erase; using Base::find; using Base::insert; + using Base::insert_or_assign; using Base::lookup; using Base::size; using Base::try_emplace; @@ -68,7 +69,8 @@ public: } std::pair<iterator, bool> insert(llvm::StringRef KeyEqValue) { - return insert(KeyEqValue.split('=')); + auto Split = KeyEqValue.split('='); + return insert(std::make_pair(Split.first, std::string(Split.second))); } void insert(const_iterator first, const_iterator last); @@ -92,4 +94,4 @@ template <> struct format_provider<lldb_private::Environment> { }; } // namespace llvm -#endif // #ifndef LLDB_UTILITY_ENVIRONMENT_H +#endif // LLDB_UTILITY_ENVIRONMENT_H diff --git a/lldb/include/lldb/Utility/Event.h b/lldb/include/lldb/Utility/Event.h index dd5d08024cef..06c02629d448 100644 --- a/lldb/include/lldb/Utility/Event.h +++ b/lldb/include/lldb/Utility/Event.h @@ -48,7 +48,8 @@ public: private: virtual void DoOnRemoval(Event *event_ptr) {} - DISALLOW_COPY_AND_ASSIGN(EventData); + EventData(const EventData &) = delete; + const EventData &operator=(const EventData &) = delete; }; // lldb::EventDataBytes @@ -92,7 +93,8 @@ public: private: std::string m_bytes; - DISALLOW_COPY_AND_ASSIGN(EventDataBytes); + EventDataBytes(const EventDataBytes &) = delete; + const EventDataBytes &operator=(const EventDataBytes &) = delete; }; class EventDataReceipt : public EventData { @@ -169,7 +171,9 @@ private: StructuredData::ObjectSP m_object_sp; lldb::StructuredDataPluginSP m_plugin_sp; - DISALLOW_COPY_AND_ASSIGN(EventDataStructuredData); + EventDataStructuredData(const EventDataStructuredData &) = delete; + const EventDataStructuredData & + operator=(const EventDataStructuredData &) = delete; }; // lldb::Event @@ -242,7 +246,8 @@ private: uint32_t m_type; // The bit describing this event lldb::EventDataSP m_data_sp; // User specific data for this event - DISALLOW_COPY_AND_ASSIGN(Event); + Event(const Event &) = delete; + const Event &operator=(const Event &) = delete; Event() = delete; }; diff --git a/lldb/include/lldb/Utility/FileSpec.h b/lldb/include/lldb/Utility/FileSpec.h index 533426671cc6..f7cbeb247100 100644 --- a/lldb/include/lldb/Utility/FileSpec.h +++ b/lldb/include/lldb/Utility/FileSpec.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef liblldb_FileSpec_h_ -#define liblldb_FileSpec_h_ +#ifndef LLDB_UTILITY_FILESPEC_H +#define LLDB_UTILITY_FILESPEC_H #include <functional> #include <string> @@ -18,6 +18,7 @@ #include "llvm/Support/FileSystem.h" #include "llvm/Support/FormatVariadic.h" #include "llvm/Support/Path.h" +#include "llvm/Support/YAMLTraits.h" #include <stddef.h> #include <stdint.h> @@ -397,6 +398,8 @@ public: ConstString GetLastPathComponent() const; protected: + friend struct llvm::yaml::MappingTraits<FileSpec>; + // Convenience method for setting the file without changing the style. void SetFile(llvm::StringRef path); @@ -410,6 +413,8 @@ protected: /// Dump a FileSpec object to a stream Stream &operator<<(Stream &s, const FileSpec &f); +/// Prevent ODR violations with traits for llvm::sys::path::Style. +LLVM_YAML_STRONG_TYPEDEF(FileSpec::Style, FileSpecStyle) } // namespace lldb_private namespace llvm { @@ -436,6 +441,16 @@ template <> struct format_provider<lldb_private::FileSpec> { static void format(const lldb_private::FileSpec &F, llvm::raw_ostream &Stream, StringRef Style); }; + +namespace yaml { +template <> struct ScalarEnumerationTraits<lldb_private::FileSpecStyle> { + static void enumeration(IO &io, lldb_private::FileSpecStyle &style); +}; + +template <> struct MappingTraits<lldb_private::FileSpec> { + static void mapping(IO &io, lldb_private::FileSpec &f); +}; +} // namespace yaml } // namespace llvm -#endif // liblldb_FileSpec_h_ +#endif // LLDB_UTILITY_FILESPEC_H diff --git a/lldb/include/lldb/Utility/Flags.h b/lldb/include/lldb/Utility/Flags.h index 254a5ec443c3..19f750639e94 100644 --- a/lldb/include/lldb/Utility/Flags.h +++ b/lldb/include/lldb/Utility/Flags.h @@ -29,7 +29,7 @@ public: /// Constructs this object with \a mask as the initial value for all of the /// flags. /// - /// \param[in] mask + /// \param[in] flags /// The initial value for all flags. Flags(ValueType flags = 0) : m_flags(flags) {} @@ -116,4 +116,4 @@ protected: } // namespace lldb_private -#endif // liblldb_Flags_h_ +#endif // LLDB_UTILITY_FLAGS_H diff --git a/lldb/include/lldb/Utility/GDBRemote.h b/lldb/include/lldb/Utility/GDBRemote.h index 21b2c8cd73cd..f5749b7e6eaf 100644 --- a/lldb/include/lldb/Utility/GDBRemote.h +++ b/lldb/include/lldb/Utility/GDBRemote.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef liblldb_GDBRemote_h_ -#define liblldb_GDBRemote_h_ +#ifndef LLDB_UTILITY_GDBREMOTE_H +#define LLDB_UTILITY_GDBREMOTE_H #include "lldb/Utility/FileSpec.h" #include "lldb/Utility/Reproducer.h" @@ -155,4 +155,4 @@ template <> struct MappingTraits<lldb_private::GDBRemotePacket> { } // namespace yaml } // namespace llvm -#endif // liblldb_GDBRemote_h_ +#endif // LLDB_UTILITY_GDBREMOTE_H diff --git a/lldb/include/lldb/Utility/IOObject.h b/lldb/include/lldb/Utility/IOObject.h index 16ed580abf71..9b2b9cfcfec0 100644 --- a/lldb/include/lldb/Utility/IOObject.h +++ b/lldb/include/lldb/Utility/IOObject.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef liblldb_Host_Common_IOObject_h_ -#define liblldb_Host_Common_IOObject_h_ +#ifndef LLDB_UTILITY_IOOBJECT_H +#define LLDB_UTILITY_IOOBJECT_H #include <stdarg.h> #include <stdio.h> @@ -45,7 +45,8 @@ protected: FDType m_fd_type; private: - DISALLOW_COPY_AND_ASSIGN(IOObject); + IOObject(const IOObject &) = delete; + const IOObject &operator=(const IOObject &) = delete; }; } // namespace lldb_private diff --git a/lldb/include/lldb/Utility/Iterable.h b/lldb/include/lldb/Utility/Iterable.h index d9c61aa958cc..3f9b8b1e4c57 100644 --- a/lldb/include/lldb/Utility/Iterable.h +++ b/lldb/include/lldb/Utility/Iterable.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef liblldb_Iterable_h_ -#define liblldb_Iterable_h_ +#ifndef LLDB_UTILITY_ITERABLE_H +#define LLDB_UTILITY_ITERABLE_H #include <utility> @@ -194,4 +194,4 @@ private: } // namespace lldb_private -#endif // liblldb_Iterable_h_ +#endif // LLDB_UTILITY_ITERABLE_H diff --git a/lldb/include/lldb/Utility/LLDBAssert.h b/lldb/include/lldb/Utility/LLDBAssert.h index 7008dd82496d..845af1d4cc2a 100644 --- a/lldb/include/lldb/Utility/LLDBAssert.h +++ b/lldb/include/lldb/Utility/LLDBAssert.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef utility_LLDBAssert_h_ -#define utility_LLDBAssert_h_ +#ifndef LLDB_UTILITY_LLDBASSERT_H +#define LLDB_UTILITY_LLDBASSERT_H #ifdef LLDB_CONFIGURATION_DEBUG #define lldbassert(x) assert(x) @@ -22,4 +22,4 @@ void lldb_assert(bool expression, const char *expr_text, const char *func, const char *file, unsigned int line); } -#endif // utility_LLDBAssert_h_ +#endif // LLDB_UTILITY_LLDBASSERT_H diff --git a/lldb/include/lldb/Utility/Listener.h b/lldb/include/lldb/Utility/Listener.h index 17fc47880e8f..9d96e36c5abc 100644 --- a/lldb/include/lldb/Utility/Listener.h +++ b/lldb/include/lldb/Utility/Listener.h @@ -145,7 +145,8 @@ private: // bool exact); // For Listener only - DISALLOW_COPY_AND_ASSIGN(Listener); + Listener(const Listener &) = delete; + const Listener &operator=(const Listener &) = delete; }; } // namespace lldb_private diff --git a/lldb/include/lldb/Utility/Predicate.h b/lldb/include/lldb/Utility/Predicate.h index cbccc3e91a8b..a17ac05f6e56 100644 --- a/lldb/include/lldb/Utility/Predicate.h +++ b/lldb/include/lldb/Utility/Predicate.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef liblldb_Predicate_h_ -#define liblldb_Predicate_h_ +#ifndef LLDB_UTILITY_PREDICATE_H +#define LLDB_UTILITY_PREDICATE_H #include <stdint.h> #include <time.h> @@ -221,9 +221,10 @@ private: m_condition.notify_all(); } - DISALLOW_COPY_AND_ASSIGN(Predicate); + Predicate(const Predicate &) = delete; + const Predicate &operator=(const Predicate &) = delete; }; } // namespace lldb_private -#endif // liblldb_Predicate_h_ +#endif // LLDB_UTILITY_PREDICATE_H diff --git a/lldb/include/lldb/Utility/ProcessInfo.h b/lldb/include/lldb/Utility/ProcessInfo.h index 9188bf3b7090..ec91060cda54 100644 --- a/lldb/include/lldb/Utility/ProcessInfo.h +++ b/lldb/include/lldb/Utility/ProcessInfo.h @@ -9,13 +9,13 @@ #ifndef LLDB_UTILITY_PROCESSINFO_H #define LLDB_UTILITY_PROCESSINFO_H -// LLDB headers #include "lldb/Utility/ArchSpec.h" #include "lldb/Utility/Args.h" #include "lldb/Utility/Environment.h" #include "lldb/Utility/FileSpec.h" #include "lldb/Utility/NameMatches.h" - +#include "lldb/Utility/Reproducer.h" +#include "llvm/Support/YAMLTraits.h" #include <vector> namespace lldb_private { @@ -89,6 +89,7 @@ public: const Environment &GetEnvironment() const { return m_environment; } protected: + template <class T> friend struct llvm::yaml::MappingTraits; FileSpec m_executable; std::string m_arg0; // argv[0] if supported. If empty, then use m_executable. // Not all process plug-ins support specifying an argv[0] that differs from @@ -150,46 +151,13 @@ public: bool verbose) const; protected: + friend struct llvm::yaml::MappingTraits<ProcessInstanceInfo>; uint32_t m_euid; uint32_t m_egid; lldb::pid_t m_parent_pid; }; -class ProcessInstanceInfoList { -public: - ProcessInstanceInfoList() = default; - - void Clear() { m_infos.clear(); } - - size_t GetSize() { return m_infos.size(); } - - void Append(const ProcessInstanceInfo &info) { m_infos.push_back(info); } - - llvm::StringRef GetProcessNameAtIndex(size_t idx) { - return ((idx < m_infos.size()) ? m_infos[idx].GetNameAsStringRef() : ""); - } - - lldb::pid_t GetProcessIDAtIndex(size_t idx) { - return ((idx < m_infos.size()) ? m_infos[idx].GetProcessID() : 0); - } - - bool GetInfoAtIndex(size_t idx, ProcessInstanceInfo &info) { - if (idx < m_infos.size()) { - info = m_infos[idx]; - return true; - } - return false; - } - - // You must ensure "idx" is valid before calling this function - const ProcessInstanceInfo &GetProcessInfoAtIndex(size_t idx) const { - assert(idx < m_infos.size()); - return m_infos[idx]; - } - -protected: - std::vector<ProcessInstanceInfo> m_infos; -}; +typedef std::vector<ProcessInstanceInfo> ProcessInstanceInfoList; // ProcessInstanceInfoMatch // @@ -248,6 +216,52 @@ protected: bool m_match_all_users; }; +namespace repro { +class ProcessInfoRecorder : public AbstractRecorder { +public: + ProcessInfoRecorder(const FileSpec &filename, std::error_code &ec) + : AbstractRecorder(filename, ec) {} + + static llvm::Expected<std::unique_ptr<ProcessInfoRecorder>> + Create(const FileSpec &filename); + + void Record(const ProcessInstanceInfoList &process_infos); +}; + +class ProcessInfoProvider : public repro::Provider<ProcessInfoProvider> { +public: + struct Info { + static const char *name; + static const char *file; + }; + + ProcessInfoProvider(const FileSpec &directory) : Provider(directory) {} + + ProcessInfoRecorder *GetNewProcessInfoRecorder(); + + void Keep() override; + void Discard() override; + + static char ID; + +private: + std::unique_ptr<llvm::raw_fd_ostream> m_stream_up; + std::vector<std::unique_ptr<ProcessInfoRecorder>> m_process_info_recorders; +}; + +llvm::Optional<ProcessInstanceInfoList> GetReplayProcessInstanceInfoList(); + +} // namespace repro } // namespace lldb_private -#endif // #ifndef LLDB_UTILITY_PROCESSINFO_H +LLVM_YAML_IS_SEQUENCE_VECTOR(lldb_private::ProcessInstanceInfo) + +namespace llvm { +namespace yaml { +template <> struct MappingTraits<lldb_private::ProcessInstanceInfo> { + static void mapping(IO &io, lldb_private::ProcessInstanceInfo &PII); +}; +} // namespace yaml +} // namespace llvm + +#endif // LLDB_UTILITY_PROCESSINFO_H diff --git a/lldb/include/lldb/Utility/RangeMap.h b/lldb/include/lldb/Utility/RangeMap.h index 9e0307351836..fb24c5a43479 100644 --- a/lldb/include/lldb/Utility/RangeMap.h +++ b/lldb/include/lldb/Utility/RangeMap.h @@ -122,220 +122,13 @@ template <typename B, typename S> struct Range { } }; -// A range array class where you get to define the type of the ranges -// that the collection contains. - -template <typename B, typename S, unsigned N> class RangeArray { +template <typename B, typename S, unsigned N = 0> class RangeVector { public: typedef B BaseType; typedef S SizeType; typedef Range<B, S> Entry; typedef llvm::SmallVector<Entry, N> Collection; - RangeArray() = default; - - ~RangeArray() = default; - - void Append(const Entry &entry) { m_entries.push_back(entry); } - - void Append(B base, S size) { m_entries.emplace_back(base, size); } - - bool RemoveEntrtAtIndex(uint32_t idx) { - if (idx < m_entries.size()) { - m_entries.erase(m_entries.begin() + idx); - return true; - } - return false; - } - - void Sort() { - if (m_entries.size() > 1) - std::stable_sort(m_entries.begin(), m_entries.end()); - } - -#ifdef ASSERT_RANGEMAP_ARE_SORTED - bool IsSorted() const { - typename Collection::const_iterator pos, end, prev; - for (pos = m_entries.begin(), end = m_entries.end(), prev = end; pos != end; - prev = pos++) { - if (prev != end && *pos < *prev) - return false; - } - return true; - } -#endif - - void CombineConsecutiveRanges() { -#ifdef ASSERT_RANGEMAP_ARE_SORTED - assert(IsSorted()); -#endif - // Can't combine if ranges if we have zero or one range - if (m_entries.size() > 1) { - // The list should be sorted prior to calling this function - typename Collection::iterator pos; - typename Collection::iterator end; - typename Collection::iterator prev; - bool can_combine = false; - // First we determine if we can combine any of the Entry objects so we - // don't end up allocating and making a new collection for no reason - for (pos = m_entries.begin(), end = m_entries.end(), prev = end; - pos != end; prev = pos++) { - if (prev != end && prev->DoesAdjoinOrIntersect(*pos)) { - can_combine = true; - break; - } - } - - // We we can combine at least one entry, then we make a new collection - // and populate it accordingly, and then swap it into place. - if (can_combine) { - Collection minimal_ranges; - for (pos = m_entries.begin(), end = m_entries.end(), prev = end; - pos != end; prev = pos++) { - if (prev != end && prev->DoesAdjoinOrIntersect(*pos)) - minimal_ranges.back().SetRangeEnd( - std::max<BaseType>(prev->GetRangeEnd(), pos->GetRangeEnd())); - else - minimal_ranges.push_back(*pos); - } - // Use the swap technique in case our new vector is much smaller. We - // must swap when using the STL because std::vector objects never - // release or reduce the memory once it has been allocated/reserved. - m_entries.swap(minimal_ranges); - } - } - } - - BaseType GetMinRangeBase(BaseType fail_value) const { -#ifdef ASSERT_RANGEMAP_ARE_SORTED - assert(IsSorted()); -#endif - if (m_entries.empty()) - return fail_value; - // m_entries must be sorted, so if we aren't empty, we grab the first - // range's base - return m_entries.front().GetRangeBase(); - } - - BaseType GetMaxRangeEnd(BaseType fail_value) const { -#ifdef ASSERT_RANGEMAP_ARE_SORTED - assert(IsSorted()); -#endif - if (m_entries.empty()) - return fail_value; - // m_entries must be sorted, so if we aren't empty, we grab the last - // range's end - return m_entries.back().GetRangeEnd(); - } - - void Slide(BaseType slide) { - typename Collection::iterator pos, end; - for (pos = m_entries.begin(), end = m_entries.end(); pos != end; ++pos) - pos->Slide(slide); - } - - void Clear() { m_entries.clear(); } - - bool IsEmpty() const { return m_entries.empty(); } - - size_t GetSize() const { return m_entries.size(); } - - const Entry *GetEntryAtIndex(size_t i) const { - return ((i < m_entries.size()) ? &m_entries[i] : nullptr); - } - - // Clients must ensure that "i" is a valid index prior to calling this - // function - const Entry &GetEntryRef(size_t i) const { return m_entries[i]; } - - Entry *Back() { return (m_entries.empty() ? nullptr : &m_entries.back()); } - - const Entry *Back() const { - return (m_entries.empty() ? nullptr : &m_entries.back()); - } - - static bool BaseLessThan(const Entry &lhs, const Entry &rhs) { - return lhs.GetRangeBase() < rhs.GetRangeBase(); - } - - uint32_t FindEntryIndexThatContains(B addr) const { -#ifdef ASSERT_RANGEMAP_ARE_SORTED - assert(IsSorted()); -#endif - if (!m_entries.empty()) { - Entry entry(addr, 1); - typename Collection::const_iterator begin = m_entries.begin(); - typename Collection::const_iterator end = m_entries.end(); - typename Collection::const_iterator pos = - std::lower_bound(begin, end, entry, BaseLessThan); - - if (pos != end && pos->Contains(addr)) { - return std::distance(begin, pos); - } else if (pos != begin) { - --pos; - if (pos->Contains(addr)) - return std::distance(begin, pos); - } - } - return UINT32_MAX; - } - - const Entry *FindEntryThatContains(B addr) const { -#ifdef ASSERT_RANGEMAP_ARE_SORTED - assert(IsSorted()); -#endif - if (!m_entries.empty()) { - Entry entry(addr, 1); - typename Collection::const_iterator begin = m_entries.begin(); - typename Collection::const_iterator end = m_entries.end(); - typename Collection::const_iterator pos = - std::lower_bound(begin, end, entry, BaseLessThan); - - if (pos != end && pos->Contains(addr)) { - return &(*pos); - } else if (pos != begin) { - --pos; - if (pos->Contains(addr)) { - return &(*pos); - } - } - } - return nullptr; - } - - const Entry *FindEntryThatContains(const Entry &range) const { -#ifdef ASSERT_RANGEMAP_ARE_SORTED - assert(IsSorted()); -#endif - if (!m_entries.empty()) { - typename Collection::const_iterator begin = m_entries.begin(); - typename Collection::const_iterator end = m_entries.end(); - typename Collection::const_iterator pos = - std::lower_bound(begin, end, range, BaseLessThan); - - if (pos != end && pos->Contains(range)) { - return &(*pos); - } else if (pos != begin) { - --pos; - if (pos->Contains(range)) { - return &(*pos); - } - } - } - return nullptr; - } - -protected: - Collection m_entries; -}; - -template <typename B, typename S> class RangeVector { -public: - typedef B BaseType; - typedef S SizeType; - typedef Range<B, S> Entry; - typedef std::vector<Entry> Collection; - RangeVector() = default; ~RangeVector() = default; @@ -601,19 +394,31 @@ struct RangeData : public Range<B, S> { RangeData(B base, S size, DataType d) : Range<B, S>(base, size), data(d) {} }; +// We can treat the vector as a flattened Binary Search Tree, augmenting it +// with upper bounds (max of range endpoints) for every index allows us to +// query for range containment quicker. +template <typename B, typename S, typename T> +struct AugmentedRangeData : public RangeData<B, S, T> { + B upper_bound; + + AugmentedRangeData(const RangeData<B, S, T> &rd) + : RangeData<B, S, T>(rd), upper_bound() {} +}; + template <typename B, typename S, typename T, unsigned N = 0, class Compare = std::less<T>> class RangeDataVector { public: typedef lldb_private::Range<B, S> Range; typedef RangeData<B, S, T> Entry; - typedef llvm::SmallVector<Entry, N> Collection; + typedef AugmentedRangeData<B, S, T> AugmentedEntry; + typedef llvm::SmallVector<AugmentedEntry, N> Collection; RangeDataVector(Compare compare = Compare()) : m_compare(compare) {} ~RangeDataVector() = default; - void Append(const Entry &entry) { m_entries.push_back(entry); } + void Append(const Entry &entry) { m_entries.emplace_back(entry); } void Sort() { if (m_entries.size() > 1) @@ -625,13 +430,13 @@ public: return a.size < b.size; return compare(a.data, b.data); }); + if (!m_entries.empty()) + ComputeUpperBounds(0, m_entries.size()); } #ifdef ASSERT_RANGEMAP_ARE_SORTED bool IsSorted() const { typename Collection::const_iterator pos, end, prev; - // First we determine if we can combine any of the Entry objects so we - // don't end up allocating and making a new collection for no reason for (pos = m_entries.begin(), end = m_entries.end(), prev = end; pos != end; prev = pos++) { if (prev != end && *pos < *prev) @@ -701,26 +506,20 @@ public: } uint32_t FindEntryIndexThatContains(B addr) const { - const Entry *entry = FindEntryThatContains(addr); + const AugmentedEntry *entry = + static_cast<const AugmentedEntry *>(FindEntryThatContains(addr)); if (entry) return std::distance(m_entries.begin(), entry); return UINT32_MAX; } - uint32_t FindEntryIndexesThatContain(B addr, - std::vector<uint32_t> &indexes) const { + uint32_t FindEntryIndexesThatContain(B addr, std::vector<uint32_t> &indexes) { #ifdef ASSERT_RANGEMAP_ARE_SORTED assert(IsSorted()); #endif - // Search the entries until the first entry that has a larger base address - // than `addr`. As m_entries is sorted by their base address, all following - // entries can't contain `addr` as their base address is already larger. - for (const auto &entry : m_entries) { - if (entry.Contains(addr)) - indexes.push_back(entry.data); - else if (entry.GetRangeBase() > addr) - break; - } + if (!m_entries.empty()) + FindEntryIndexesThatContain(addr, 0, m_entries.size(), indexes); + return indexes.size(); } @@ -806,6 +605,54 @@ public: protected: Collection m_entries; Compare m_compare; + +private: + // Compute extra information needed for search + B ComputeUpperBounds(size_t lo, size_t hi) { + size_t mid = (lo + hi) / 2; + AugmentedEntry &entry = m_entries[mid]; + + entry.upper_bound = entry.base + entry.size; + + if (lo < mid) + entry.upper_bound = + std::max(entry.upper_bound, ComputeUpperBounds(lo, mid)); + + if (mid + 1 < hi) + entry.upper_bound = + std::max(entry.upper_bound, ComputeUpperBounds(mid + 1, hi)); + + return entry.upper_bound; + } + + // This is based on the augmented tree implementation found at + // https://en.wikipedia.org/wiki/Interval_tree#Augmented_tree + void FindEntryIndexesThatContain(B addr, size_t lo, size_t hi, + std::vector<uint32_t> &indexes) { + size_t mid = (lo + hi) / 2; + const AugmentedEntry &entry = m_entries[mid]; + + // addr is greater than the rightmost point of any interval below mid + // so there are cannot be any matches. + if (addr > entry.upper_bound) + return; + + // Recursively search left subtree + if (lo < mid) + FindEntryIndexesThatContain(addr, lo, mid, indexes); + + // If addr is smaller than the start of the current interval it + // cannot contain it nor can any of its right subtree. + if (addr < entry.base) + return; + + if (entry.Contains(addr)) + indexes.push_back(entry.data); + + // Recursively search right subtree + if (mid + 1 < hi) + FindEntryIndexesThatContain(addr, mid + 1, hi, indexes); + } }; // A simple range with data class where you get to define the type of diff --git a/lldb/include/lldb/Utility/RegisterValue.h b/lldb/include/lldb/Utility/RegisterValue.h index eeb3ce52a82b..c9f295a8d95a 100644 --- a/lldb/include/lldb/Utility/RegisterValue.h +++ b/lldb/include/lldb/Utility/RegisterValue.h @@ -26,7 +26,8 @@ struct RegisterInfo; class RegisterValue { public: - enum { kMaxRegisterByteSize = 64u }; + // big enough to support up to 256 byte AArch64 SVE + enum { kMaxRegisterByteSize = 256u }; enum Type { eTypeInvalid, @@ -259,9 +260,10 @@ protected: Scalar m_scalar; struct { - uint8_t bytes[kMaxRegisterByteSize]; // This must be big enough to hold any - // register for any supported target. - uint8_t length; + mutable uint8_t + bytes[kMaxRegisterByteSize]; // This must be big enough to hold any + // register for any supported target. + uint16_t length; lldb::ByteOrder byte_order; } buffer; }; diff --git a/lldb/include/lldb/Utility/RegularExpression.h b/lldb/include/lldb/Utility/RegularExpression.h index 6acc203d8e7c..415f1b58b111 100644 --- a/lldb/include/lldb/Utility/RegularExpression.h +++ b/lldb/include/lldb/Utility/RegularExpression.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef liblldb_RegularExpression_h_ -#define liblldb_RegularExpression_h_ +#ifndef LLDB_UTILITY_REGULAREXPRESSION_H +#define LLDB_UTILITY_REGULAREXPRESSION_H #include "llvm/ADT/StringRef.h" #include "llvm/Support/Error.h" @@ -91,4 +91,4 @@ private: } // namespace lldb_private -#endif // liblldb_RegularExpression_h_ +#endif // LLDB_UTILITY_REGULAREXPRESSION_H diff --git a/lldb/include/lldb/Utility/Reproducer.h b/lldb/include/lldb/Utility/Reproducer.h index 0d23fe8571ff..ab673e5e0019 100644 --- a/lldb/include/lldb/Utility/Reproducer.h +++ b/lldb/include/lldb/Utility/Reproducer.h @@ -27,6 +27,7 @@ class Reproducer; enum class ReproducerMode { Capture, Replay, + PassiveReplay, Off, }; @@ -98,6 +99,8 @@ public: return m_collector; } + void recordInterestingDirectory(const llvm::Twine &dir); + void Keep() override { auto mapping = GetRoot().CopyByAppendingPathComponent(Info::file); // Temporary files that are removed during execution can cause copy errors. @@ -132,7 +135,7 @@ public: static char ID; }; -/// Provider for the LLDB current working directroy. +/// Provider for the LLDB current working directory. /// /// When the reproducer is kept, it writes lldb's current working directory to /// a file named cwd.txt in the reproducer root. @@ -142,8 +145,11 @@ public: llvm::SmallString<128> cwd; if (std::error_code EC = llvm::sys::fs::current_path(cwd)) return; - m_cwd = cwd.str(); + m_cwd = std::string(cwd.str()); } + + void Update(llvm::StringRef path) { m_cwd = std::string(path); } + struct Info { static const char *name; static const char *file; @@ -153,6 +159,9 @@ public: static char ID; }; +/// The recorder is a small object handed out by a provider to record data. It +/// is commonly used in combination with a MultiProvider which is meant to +/// record information for multiple instances of the same source of data. class AbstractRecorder { protected: AbstractRecorder(const FileSpec &filename, std::error_code &ec) @@ -175,6 +184,7 @@ protected: bool m_record; }; +/// Recorder that records its data as text to a file. class DataRecorder : public AbstractRecorder { public: DataRecorder(const FileSpec &filename, std::error_code &ec) @@ -193,24 +203,88 @@ public: } }; -class CommandProvider : public Provider<CommandProvider> { +/// Recorder that records its data as YAML to a file. +class YamlRecorder : public AbstractRecorder { +public: + YamlRecorder(const FileSpec &filename, std::error_code &ec) + : AbstractRecorder(filename, ec) {} + + static llvm::Expected<std::unique_ptr<YamlRecorder>> + Create(const FileSpec &filename); + + template <typename T> void Record(const T &t) { + if (!m_record) + return; + llvm::yaml::Output yout(m_os); + // The YAML traits are defined as non-const because they are used for + // serialization and deserialization. The cast is safe because + // serialization doesn't modify the object. + yout << const_cast<T &>(t); + m_os.flush(); + } +}; + +/// The MultiProvider is a provider that hands out recorder which can be used +/// to capture data for different instances of the same object. The recorders +/// can be passed around or stored as an instance member. +/// +/// The Info::file for the MultiProvider contains an index of files for every +/// recorder. Use the MultiLoader to read the index and get the individual +/// files. +template <typename T, typename V> +class MultiProvider : public repro::Provider<V> { +public: + MultiProvider(const FileSpec &directory) : Provider<V>(directory) {} + + T *GetNewRecorder() { + std::size_t i = m_recorders.size() + 1; + std::string filename = (llvm::Twine(V::Info::name) + llvm::Twine("-") + + llvm::Twine(i) + llvm::Twine(".yaml")) + .str(); + auto recorder_or_error = + T::Create(this->GetRoot().CopyByAppendingPathComponent(filename)); + if (!recorder_or_error) { + llvm::consumeError(recorder_or_error.takeError()); + return nullptr; + } + + m_recorders.push_back(std::move(*recorder_or_error)); + return m_recorders.back().get(); + } + + void Keep() override { + std::vector<std::string> files; + for (auto &recorder : m_recorders) { + recorder->Stop(); + files.push_back(recorder->GetFilename().GetPath()); + } + + FileSpec file = this->GetRoot().CopyByAppendingPathComponent(V::Info::file); + std::error_code ec; + llvm::raw_fd_ostream os(file.GetPath(), ec, llvm::sys::fs::OF_Text); + if (ec) + return; + llvm::yaml::Output yout(os); + yout << files; + } + + void Discard() override { m_recorders.clear(); } + +private: + std::vector<std::unique_ptr<T>> m_recorders; +}; + +class CommandProvider : public MultiProvider<DataRecorder, CommandProvider> { public: struct Info { static const char *name; static const char *file; }; - CommandProvider(const FileSpec &directory) : Provider(directory) {} - - DataRecorder *GetNewDataRecorder(); - - void Keep() override; - void Discard() override; + CommandProvider(const FileSpec &directory) + : MultiProvider<DataRecorder, CommandProvider>(directory) {} static char ID; - -private: - std::vector<std::unique_ptr<DataRecorder>> m_data_recorders; }; /// The generator is responsible for the logic needed to generate a @@ -231,6 +305,12 @@ public: /// might need to clean up files already written to disk. void Discard(); + /// Enable or disable auto generate. + void SetAutoGenerate(bool b); + + /// Return whether auto generate is enabled. + bool IsAutoGenerate() const; + /// Create and register a new provider. template <typename T> T *Create() { std::unique_ptr<ProviderBase> provider = std::make_unique<T>(m_root); @@ -272,11 +352,14 @@ private: /// Flag to ensure that we never call both keep and discard. bool m_done = false; + + /// Flag to auto generate a reproducer when it would otherwise be discarded. + bool m_auto_generate = false; }; class Loader final { public: - Loader(FileSpec root); + Loader(FileSpec root, bool passive = false); template <typename T> FileSpec GetFile() { if (!HasFile(T::file)) @@ -298,12 +381,15 @@ public: const FileSpec &GetRoot() const { return m_root; } + bool IsPassiveReplay() const { return m_passive_replay; } + private: bool HasFile(llvm::StringRef file); FileSpec m_root; std::vector<std::string> m_files; bool m_loaded; + bool m_passive_replay; }; /// The reproducer enables clients to obtain access to the Generator and @@ -331,7 +417,7 @@ public: protected: llvm::Error SetCapture(llvm::Optional<FileSpec> root); - llvm::Error SetReplay(llvm::Optional<FileSpec> root); + llvm::Error SetReplay(llvm::Optional<FileSpec> root, bool passive = false); private: static llvm::Optional<Reproducer> &InstanceImpl(); @@ -342,6 +428,8 @@ private: mutable std::mutex m_mutex; }; +/// Loader for data captured with the MultiProvider. It will read the index and +/// return the path to the files in the index. template <typename T> class MultiLoader { public: MultiLoader(std::vector<std::string> files) : m_files(files) {} diff --git a/lldb/include/lldb/Utility/ReproducerInstrumentation.h b/lldb/include/lldb/Utility/ReproducerInstrumentation.h index 75d66045758f..5fc33ad1a17b 100644 --- a/lldb/include/lldb/Utility/ReproducerInstrumentation.h +++ b/lldb/include/lldb/Utility/ReproducerInstrumentation.h @@ -5,8 +5,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLDB_UTILITY_REPRODUCER_INSTRUMENTATION_H -#define LLDB_UTILITY_REPRODUCER_INSTRUMENTATION_H +#ifndef LLDB_UTILITY_REPRODUCERINSTRUMENTATION_H +#define LLDB_UTILITY_REPRODUCERINSTRUMENTATION_H #include "lldb/Utility/FileSpec.h" #include "lldb/Utility/Log.h" @@ -16,7 +16,6 @@ #include "llvm/ADT/StringRef.h" #include "llvm/Support/ErrorHandling.h" -#include <iostream> #include <map> #include <type_traits> @@ -33,6 +32,11 @@ inline void stringify_append(llvm::raw_string_ostream &ss, const T &t) { } template <typename T> +inline void stringify_append(llvm::raw_string_ostream &ss, T *t) { + ss << reinterpret_cast<void *>(t); +} + +template <typename T> inline void stringify_append(llvm::raw_string_ostream &ss, const T *t) { ss << reinterpret_cast<const void *>(t); } @@ -43,6 +47,12 @@ inline void stringify_append<char>(llvm::raw_string_ostream &ss, ss << '\"' << t << '\"'; } +template <> +inline void stringify_append<std::nullptr_t>(llvm::raw_string_ostream &ss, + const std::nullptr_t &t) { + ss << "\"nullptr\""; +} + template <typename Head> inline void stringify_helper(llvm::raw_string_ostream &ss, const Head &head) { stringify_append(ss, head); @@ -69,120 +79,146 @@ template <typename... Ts> inline std::string stringify_args(const Ts &... ts) { // #define LLDB_REPRO_INSTR_TRACE #define LLDB_REGISTER_CONSTRUCTOR(Class, Signature) \ - R.Register<Class * Signature>(&construct<Class Signature>::doit, "", #Class, \ - #Class, #Signature) + R.Register<Class * Signature>(&construct<Class Signature>::record, "", \ + #Class, #Class, #Signature) + #define LLDB_REGISTER_METHOD(Result, Class, Method, Signature) \ R.Register( \ - &invoke<Result(Class::*) Signature>::method<(&Class::Method)>::doit, \ + &invoke<Result(Class::*) Signature>::method<(&Class::Method)>::record, \ #Result, #Class, #Method, #Signature) + #define LLDB_REGISTER_METHOD_CONST(Result, Class, Method, Signature) \ - R.Register(&invoke<Result(Class::*) Signature const>::method_const<( \ - &Class::Method)>::doit, \ + R.Register(&invoke<Result(Class::*) \ + Signature const>::method<(&Class::Method)>::record, \ #Result, #Class, #Method, #Signature) + #define LLDB_REGISTER_STATIC_METHOD(Result, Class, Method, Signature) \ - R.Register<Result Signature>( \ - static_cast<Result(*) Signature>(&Class::Method), #Result, #Class, \ - #Method, #Signature) + R.Register(&invoke<Result(*) Signature>::method<(&Class::Method)>::record, \ + #Result, #Class, #Method, #Signature) + +#define LLDB_REGISTER_CHAR_PTR_METHOD_STATIC(Result, Class, Method) \ + R.Register( \ + &invoke<Result (*)(char *, size_t)>::method<(&Class::Method)>::record, \ + &invoke_char_ptr<Result (*)(char *, \ + size_t)>::method<(&Class::Method)>::record, \ + #Result, #Class, #Method, "(char*, size_t"); + +#define LLDB_REGISTER_CHAR_PTR_METHOD(Result, Class, Method) \ + R.Register(&invoke<Result (Class::*)(char *, size_t)>::method<( \ + &Class::Method)>::record, \ + &invoke_char_ptr<Result (Class::*)(char *, size_t)>::method<( \ + &Class::Method)>::record, \ + #Result, #Class, #Method, "(char*, size_t"); + +#define LLDB_REGISTER_CHAR_PTR_METHOD_CONST(Result, Class, Method) \ + R.Register(&invoke<Result (Class::*)(char *, size_t) \ + const>::method<(&Class::Method)>::record, \ + &invoke_char_ptr<Result (Class::*)(char *, size_t) \ + const>::method<(&Class::Method)>::record, \ + #Result, #Class, #Method, "(char*, size_t"); + +#define LLDB_CONSTRUCT_(T, Class, ...) \ + lldb_private::repro::Recorder _recorder(LLVM_PRETTY_FUNCTION); \ + lldb_private::repro::construct<T>::handle(LLDB_GET_INSTRUMENTATION_DATA(), \ + _recorder, Class, __VA_ARGS__); #define LLDB_RECORD_CONSTRUCTOR(Class, Signature, ...) \ - lldb_private::repro::Recorder sb_recorder(LLVM_PRETTY_FUNCTION, \ - stringify_args(__VA_ARGS__)); \ - if (lldb_private::repro::InstrumentationData data = \ - LLDB_GET_INSTRUMENTATION_DATA()) { \ - sb_recorder.Record(data.GetSerializer(), data.GetRegistry(), \ - &lldb_private::repro::construct<Class Signature>::doit, \ - __VA_ARGS__); \ - sb_recorder.RecordResult(this); \ - } + LLDB_CONSTRUCT_(Class Signature, this, __VA_ARGS__) #define LLDB_RECORD_CONSTRUCTOR_NO_ARGS(Class) \ - lldb_private::repro::Recorder sb_recorder(LLVM_PRETTY_FUNCTION); \ - if (lldb_private::repro::InstrumentationData data = \ + LLDB_CONSTRUCT_(Class(), this, lldb_private::repro::EmptyArg()) + +#define LLDB_RECORD_(T1, T2, ...) \ + lldb_private::repro::Recorder _recorder(LLVM_PRETTY_FUNCTION, \ + stringify_args(__VA_ARGS__)); \ + if (lldb_private::repro::InstrumentationData _data = \ LLDB_GET_INSTRUMENTATION_DATA()) { \ - sb_recorder.Record(data.GetSerializer(), data.GetRegistry(), \ - &lldb_private::repro::construct<Class()>::doit); \ - sb_recorder.RecordResult(this); \ + if (lldb_private::repro::Serializer *_serializer = \ + _data.GetSerializer()) { \ + _recorder.Record(*_serializer, _data.GetRegistry(), \ + &lldb_private::repro::invoke<T1>::method<T2>::record, \ + __VA_ARGS__); \ + } else if (lldb_private::repro::Deserializer *_deserializer = \ + _data.GetDeserializer()) { \ + if (_recorder.ShouldCapture()) { \ + return lldb_private::repro::invoke<T1>::method<T2>::replay( \ + _recorder, *_deserializer, _data.GetRegistry()); \ + } \ + } \ } #define LLDB_RECORD_METHOD(Result, Class, Method, Signature, ...) \ - lldb_private::repro::Recorder sb_recorder( \ - LLVM_PRETTY_FUNCTION, stringify_args(*this, __VA_ARGS__)); \ - if (lldb_private::repro::InstrumentationData data = \ - LLDB_GET_INSTRUMENTATION_DATA()) { \ - sb_recorder.Record( \ - data.GetSerializer(), data.GetRegistry(), \ - &lldb_private::repro::invoke<Result(Class::*) Signature>::method<( \ - &Class::Method)>::doit, \ - this, __VA_ARGS__); \ - } + LLDB_RECORD_(Result(Class::*) Signature, (&Class::Method), this, __VA_ARGS__) #define LLDB_RECORD_METHOD_CONST(Result, Class, Method, Signature, ...) \ - lldb_private::repro::Recorder sb_recorder( \ - LLVM_PRETTY_FUNCTION, stringify_args(*this, __VA_ARGS__)); \ - if (lldb_private::repro::InstrumentationData data = \ - LLDB_GET_INSTRUMENTATION_DATA()) { \ - sb_recorder.Record( \ - data.GetSerializer(), data.GetRegistry(), \ - &lldb_private::repro::invoke<Result( \ - Class::*) Signature const>::method_const<(&Class::Method)>::doit, \ - this, __VA_ARGS__); \ - } + LLDB_RECORD_(Result(Class::*) Signature const, (&Class::Method), this, \ + __VA_ARGS__) #define LLDB_RECORD_METHOD_NO_ARGS(Result, Class, Method) \ - lldb_private::repro::Recorder sb_recorder(LLVM_PRETTY_FUNCTION, \ - stringify_args(*this)); \ - if (lldb_private::repro::InstrumentationData data = \ - LLDB_GET_INSTRUMENTATION_DATA()) { \ - sb_recorder.Record(data.GetSerializer(), data.GetRegistry(), \ - &lldb_private::repro::invoke<Result ( \ - Class::*)()>::method<(&Class::Method)>::doit, \ - this); \ - } + LLDB_RECORD_(Result (Class::*)(), (&Class::Method), this) #define LLDB_RECORD_METHOD_CONST_NO_ARGS(Result, Class, Method) \ - lldb_private::repro::Recorder sb_recorder(LLVM_PRETTY_FUNCTION, \ - stringify_args(*this)); \ - if (lldb_private::repro::InstrumentationData data = \ - LLDB_GET_INSTRUMENTATION_DATA()) { \ - sb_recorder.Record( \ - data.GetSerializer(), data.GetRegistry(), \ - &lldb_private::repro::invoke<Result ( \ - Class::*)() const>::method_const<(&Class::Method)>::doit, \ - this); \ - } + LLDB_RECORD_(Result (Class::*)() const, (&Class::Method), this) #define LLDB_RECORD_STATIC_METHOD(Result, Class, Method, Signature, ...) \ - lldb_private::repro::Recorder sb_recorder(LLVM_PRETTY_FUNCTION, \ - stringify_args(__VA_ARGS__)); \ - if (lldb_private::repro::InstrumentationData data = \ - LLDB_GET_INSTRUMENTATION_DATA()) { \ - sb_recorder.Record(data.GetSerializer(), data.GetRegistry(), \ - static_cast<Result(*) Signature>(&Class::Method), \ - __VA_ARGS__); \ - } + LLDB_RECORD_(Result(*) Signature, (&Class::Method), __VA_ARGS__) #define LLDB_RECORD_STATIC_METHOD_NO_ARGS(Result, Class, Method) \ - lldb_private::repro::Recorder sb_recorder(LLVM_PRETTY_FUNCTION); \ - if (lldb_private::repro::InstrumentationData data = \ + LLDB_RECORD_(Result (*)(), (&Class::Method), lldb_private::repro::EmptyArg()) + +#define LLDB_RECORD_CHAR_PTR_(T1, T2, StrOut, ...) \ + lldb_private::repro::Recorder _recorder(LLVM_PRETTY_FUNCTION, \ + stringify_args(__VA_ARGS__)); \ + if (lldb_private::repro::InstrumentationData _data = \ LLDB_GET_INSTRUMENTATION_DATA()) { \ - sb_recorder.Record(data.GetSerializer(), data.GetRegistry(), \ - static_cast<Result (*)()>(&Class::Method)); \ + if (lldb_private::repro::Serializer *_serializer = \ + _data.GetSerializer()) { \ + _recorder.Record(*_serializer, _data.GetRegistry(), \ + &lldb_private::repro::invoke<T1>::method<(T2)>::record, \ + __VA_ARGS__); \ + } else if (lldb_private::repro::Deserializer *_deserializer = \ + _data.GetDeserializer()) { \ + if (_recorder.ShouldCapture()) { \ + return lldb_private::repro::invoke_char_ptr<T1>::method<T2>::replay( \ + _recorder, *_deserializer, _data.GetRegistry(), StrOut); \ + } \ + } \ } -#define LLDB_RECORD_RESULT(Result) sb_recorder.RecordResult(Result); +#define LLDB_RECORD_CHAR_PTR_METHOD(Result, Class, Method, Signature, StrOut, \ + ...) \ + LLDB_RECORD_CHAR_PTR_(Result(Class::*) Signature, (&Class::Method), StrOut, \ + this, __VA_ARGS__) + +#define LLDB_RECORD_CHAR_PTR_METHOD_CONST(Result, Class, Method, Signature, \ + StrOut, ...) \ + LLDB_RECORD_CHAR_PTR_(Result(Class::*) Signature const, (&Class::Method), \ + StrOut, this, __VA_ARGS__) + +#define LLDB_RECORD_CHAR_PTR_STATIC_METHOD(Result, Class, Method, Signature, \ + StrOut, ...) \ + LLDB_RECORD_CHAR_PTR_(Result(*) Signature, (&Class::Method), StrOut, \ + __VA_ARGS__) + +#define LLDB_RECORD_RESULT(Result) _recorder.RecordResult(Result, true); /// The LLDB_RECORD_DUMMY macro is special because it doesn't actually record /// anything. It's used to track API boundaries when we cannot record for /// technical reasons. #define LLDB_RECORD_DUMMY(Result, Class, Method, Signature, ...) \ - lldb_private::repro::Recorder sb_recorder(LLVM_PRETTY_FUNCTION, \ - stringify_args(__VA_ARGS__)); + lldb_private::repro::Recorder _recorder; + #define LLDB_RECORD_DUMMY_NO_ARGS(Result, Class, Method) \ - lldb_private::repro::Recorder sb_recorder(LLVM_PRETTY_FUNCTION); + lldb_private::repro::Recorder _recorder; namespace lldb_private { namespace repro { +template <class T> +struct is_trivially_serializable + : std::integral_constant<bool, std::is_fundamental<T>::value || + std::is_enum<T>::value> {}; + /// Mapping between serialized indices and their corresponding objects. /// /// This class is used during replay to map indices back to in-memory objects. @@ -205,19 +241,24 @@ public: } /// Adds a pointer to an object to the mapping for the given index. - template <typename T> void AddObjectForIndex(unsigned idx, T *object) { + template <typename T> T *AddObjectForIndex(unsigned idx, T *object) { AddObjectForIndexImpl( idx, static_cast<void *>( const_cast<typename std::remove_const<T>::type *>(object))); + return object; } /// Adds a reference to an object to the mapping for the given index. - template <typename T> void AddObjectForIndex(unsigned idx, T &object) { + template <typename T> T &AddObjectForIndex(unsigned idx, T &object) { AddObjectForIndexImpl( idx, static_cast<void *>( const_cast<typename std::remove_const<T>::type *>(&object))); + return object; } + /// Get all objects sorted by their index. + std::vector<void *> GetAllObjects() const; + private: /// Helper method that does the actual lookup. The void* result is later cast /// by the caller. @@ -238,11 +279,11 @@ struct ReferenceTag {}; struct ValueTag {}; struct FundamentalPointerTag {}; struct FundamentalReferenceTag {}; -struct NotImplementedTag {}; /// Return the deserialization tag for the given type T. template <class T> struct serializer_tag { - typedef typename std::conditional<std::is_trivially_copyable<T>::value, ValueTag, NotImplementedTag>::type type; + typedef typename std::conditional<std::is_trivially_copyable<T>::value, + ValueTag, ReferenceTag>::type type; }; template <class T> struct serializer_tag<T *> { typedef @@ -275,27 +316,37 @@ public: /// Deserialize and interpret value as T. template <typename T> T Deserialize() { + T t = Read<T>(typename serializer_tag<T>::type()); #ifdef LLDB_REPRO_INSTR_TRACE - llvm::errs() << "Deserializing with " << LLVM_PRETTY_FUNCTION << "\n"; + llvm::errs() << "Deserializing with " << LLVM_PRETTY_FUNCTION << " -> " + << stringify_args(t) << "\n"; #endif - return Read<T>(typename serializer_tag<T>::type()); + return t; + } + + template <typename T> const T &HandleReplayResult(const T &t) { + unsigned result = Deserialize<unsigned>(); + if (is_trivially_serializable<T>::value) + return t; + // We need to make a copy as the original object might go out of scope. + return *m_index_to_object.AddObjectForIndex(result, new T(t)); } /// Store the returned value in the index-to-object mapping. - template <typename T> void HandleReplayResult(const T &t) { + template <typename T> T &HandleReplayResult(T &t) { unsigned result = Deserialize<unsigned>(); - if (std::is_fundamental<T>::value) - return; + if (is_trivially_serializable<T>::value) + return t; // We need to make a copy as the original object might go out of scope. - m_index_to_object.AddObjectForIndex(result, new T(t)); + return *m_index_to_object.AddObjectForIndex(result, new T(t)); } /// Store the returned value in the index-to-object mapping. - template <typename T> void HandleReplayResult(T *t) { + template <typename T> T *HandleReplayResult(T *t) { unsigned result = Deserialize<unsigned>(); - if (std::is_fundamental<T>::value) - return; - m_index_to_object.AddObjectForIndex(result, t); + if (is_trivially_serializable<T>::value) + return t; + return m_index_to_object.AddObjectForIndex(result, t); } /// All returned types are recorded, even when the function returns a void. @@ -306,12 +357,11 @@ public: (void)result; } -private: - template <typename T> T Read(NotImplementedTag) { - m_buffer = m_buffer.drop_front(sizeof(T)); - return T(); + std::vector<void *> GetAllObjects() const { + return m_index_to_object.GetAllObjects(); } +private: template <typename T> T Read(ValueTag) { assert(HasData(sizeof(T))); T t; @@ -362,7 +412,11 @@ private: /// Partial specialization for C-style strings. We read the string value /// instead of treating it as pointer. template <> const char *Deserializer::Deserialize<const char *>(); +template <> const char **Deserializer::Deserialize<const char **>(); +template <> const uint8_t *Deserializer::Deserialize<const uint8_t *>(); +template <> const void *Deserializer::Deserialize<const void *>(); template <> char *Deserializer::Deserialize<char *>(); +template <> void *Deserializer::Deserialize<void *>(); /// Helpers to auto-synthesize function replay code. It deserializes the replay /// function's arguments one by one and finally calls the corresponding @@ -404,7 +458,11 @@ struct DefaultReplayer<Result(Args...)> : public Replayer { DefaultReplayer(Result (*f)(Args...)) : Replayer(), f(f) {} void operator()(Deserializer &deserializer) const override { - deserializer.HandleReplayResult( + Replay(deserializer); + } + + Result Replay(Deserializer &deserializer) const { + return deserializer.HandleReplayResult( DeserializationHelper<Args...>::template deserialized<Result>::doit( deserializer, f)); } @@ -419,6 +477,10 @@ struct DefaultReplayer<void(Args...)> : public Replayer { DefaultReplayer(void (*f)(Args...)) : Replayer(), f(f) {} void operator()(Deserializer &deserializer) const override { + Replay(deserializer); + } + + void Replay(Deserializer &deserializer) const { DeserializationHelper<Args...>::template deserialized<void>::doit( deserializer, f); deserializer.HandleReplayResultVoid(); @@ -474,18 +536,25 @@ public: /// Replay functions from a buffer. bool Replay(llvm::StringRef buffer); + /// Replay functions from a deserializer. + bool Replay(Deserializer &deserializer); + /// Returns the ID for a given function address. unsigned GetID(uintptr_t addr); + /// Get the replayer matching the given ID. + Replayer *GetReplayer(unsigned id); + + std::string GetSignature(unsigned id); + + void CheckID(unsigned expected, unsigned actual); + protected: /// Register the given replayer for a function (and the ID mapping). void DoRegister(uintptr_t RunID, std::unique_ptr<Replayer> replayer, SignatureStr signature); private: - std::string GetSignature(unsigned id); - Replayer *GetReplayer(unsigned id); - /// Mapping of function addresses to replayers and their ID. std::map<uintptr_t, std::pair<std::unique_ptr<Replayer>, unsigned>> m_replayers; @@ -494,37 +563,6 @@ private: std::map<unsigned, std::pair<Replayer *, SignatureStr>> m_ids; }; -/// To be used as the "Runtime ID" of a constructor. It also invokes the -/// constructor when called. -template <typename Signature> struct construct; -template <typename Class, typename... Args> struct construct<Class(Args...)> { - static Class *doit(Args... args) { return new Class(args...); } -}; - -/// To be used as the "Runtime ID" of a member function. It also invokes the -/// member function when called. -template <typename Signature> struct invoke; -template <typename Result, typename Class, typename... Args> -struct invoke<Result (Class::*)(Args...)> { - template <Result (Class::*m)(Args...)> struct method { - static Result doit(Class *c, Args... args) { return (c->*m)(args...); } - }; -}; - -template <typename Result, typename Class, typename... Args> -struct invoke<Result (Class::*)(Args...) const> { - template <Result (Class::*m)(Args...) const> struct method_const { - static Result doit(Class *c, Args... args) { return (c->*m)(args...); } - }; -}; - -template <typename Class, typename... Args> -struct invoke<void (Class::*)(Args...)> { - template <void (Class::*m)(Args...)> struct method { - static void doit(Class *c, Args... args) { (c->*m)(args...); } - }; -}; - /// Maps an object to an index for serialization. Indices are unique and /// incremented for every new object. /// @@ -561,6 +599,10 @@ private: /// fundamental types (in which case we serialize its value) and pointer to /// objects (in which case we serialize their index). template <typename T> void Serialize(T *t) { +#ifdef LLDB_REPRO_INSTR_TRACE + llvm::errs() << "Serializing with " << LLVM_PRETTY_FUNCTION << " -> " + << stringify_args(t) << "\n"; +#endif if (std::is_fundamental<T>::value) { Serialize(*t); } else { @@ -573,7 +615,11 @@ private: /// fundamental types (in which case we serialize its value) and references /// to objects (in which case we serialize their index). template <typename T> void Serialize(T &t) { - if (std::is_fundamental<T>::value) { +#ifdef LLDB_REPRO_INSTR_TRACE + llvm::errs() << "Serializing with " << LLVM_PRETTY_FUNCTION << " -> " + << stringify_args(t) << "\n"; +#endif + if (is_trivially_serializable<T>::value) { m_stream.write(reinterpret_cast<const char *>(&t), sizeof(T)); } else { unsigned idx = m_tracker.GetIndexForObject(&t); @@ -581,14 +627,43 @@ private: } } + void Serialize(const void *v) { + // FIXME: Support void* + } + void Serialize(void *v) { // FIXME: Support void* - llvm_unreachable("void* is currently unsupported."); } void Serialize(const char *t) { - m_stream << t; - m_stream.write(0x0); +#ifdef LLDB_REPRO_INSTR_TRACE + llvm::errs() << "Serializing with " << LLVM_PRETTY_FUNCTION << " -> " + << stringify_args(t) << "\n"; +#endif + const size_t size = t ? strlen(t) : std::numeric_limits<size_t>::max(); + Serialize(size); + if (t) { + m_stream << t; + m_stream.write(0x0); + } + } + + void Serialize(const char **t) { + size_t size = 0; + if (!t) { + Serialize(size); + return; + } + + // Compute the size of the array. + const char *const *temp = t; + while (*temp++) + size++; + Serialize(size); + + // Serialize the content of the array. + while (*t) + Serialize(*t++); } /// Serialization stream. @@ -596,24 +671,46 @@ private: /// Mapping of objects to indices. ObjectToIndex m_tracker; -}; +}; // namespace repro class InstrumentationData { public: - InstrumentationData() : m_serializer(nullptr), m_registry(nullptr){}; - InstrumentationData(Serializer &serializer, Registry ®istry) - : m_serializer(&serializer), m_registry(®istry){}; - - Serializer &GetSerializer() { return *m_serializer; } + Serializer *GetSerializer() { return m_serializer; } + Deserializer *GetDeserializer() { return m_deserializer; } Registry &GetRegistry() { return *m_registry; } - operator bool() { return m_serializer != nullptr && m_registry != nullptr; } + operator bool() { + return (m_serializer != nullptr || m_deserializer != nullptr) && + m_registry != nullptr; + } + + static void Initialize(Serializer &serializer, Registry ®istry); + static void Initialize(Deserializer &serializer, Registry ®istry); + static InstrumentationData &Instance(); + +protected: + friend llvm::optional_detail::OptionalStorage<InstrumentationData, true>; + friend llvm::Optional<InstrumentationData>; + + InstrumentationData() + : m_serializer(nullptr), m_deserializer(nullptr), m_registry(nullptr) {} + InstrumentationData(Serializer &serializer, Registry ®istry) + : m_serializer(&serializer), m_deserializer(nullptr), + m_registry(®istry) {} + InstrumentationData(Deserializer &deserializer, Registry ®istry) + : m_serializer(nullptr), m_deserializer(&deserializer), + m_registry(®istry) {} private: + static llvm::Optional<InstrumentationData> &InstanceImpl(); + Serializer *m_serializer; + Deserializer *m_deserializer; Registry *m_registry; }; +struct EmptyArg {}; + /// RAII object that records function invocations and their return value. /// /// API calls are only captured when the API boundary is crossed. Once we're in @@ -628,7 +725,8 @@ private: /// this class is also used for logging. class Recorder { public: - Recorder(llvm::StringRef pretty_func = {}, std::string &&pretty_args = {}); + Recorder(); + Recorder(llvm::StringRef pretty_func, std::string &&pretty_args = {}); ~Recorder(); /// Records a single function call. @@ -679,9 +777,26 @@ public: m_result_recorded = true; } + /// Specializations for the no-argument methods. These are passed an empty + /// dummy argument so the same variadic macro can be used. These methods + /// strip the arguments before forwarding them. + template <typename Result> + void Record(Serializer &serializer, Registry ®istry, Result (*f)(), + const EmptyArg &arg) { + Record(serializer, registry, f); + } + /// Record the result of a function call. - template <typename Result> Result RecordResult(Result &&r) { - UpdateBoundary(); + template <typename Result> + Result RecordResult(Result &&r, bool update_boundary) { + // When recording the result from the LLDB_RECORD_RESULT macro, we need to + // update the boundary so we capture the copy constructor. However, when + // called to record the this pointer of the (copy) constructor, the + // boundary should not be toggled, because it is called from the + // LLDB_RECORD_CONSTRUCTOR macro, which might be followed by other API + // calls. + if (update_boundary) + UpdateBoundary(); if (m_serializer && ShouldCapture()) { assert(!m_result_recorded); m_serializer->SerializeAll(r); @@ -690,14 +805,41 @@ public: return std::forward<Result>(r); } + template <typename Result, typename T> + Result Replay(Deserializer &deserializer, Registry ®istry, uintptr_t addr, + bool update_boundary) { + unsigned actual_id = registry.GetID(addr); + unsigned id = deserializer.Deserialize<unsigned>(); + registry.CheckID(id, actual_id); + return ReplayResult<Result>( + static_cast<DefaultReplayer<T> *>(registry.GetReplayer(id)) + ->Replay(deserializer), + update_boundary); + } + + void Replay(Deserializer &deserializer, Registry ®istry, uintptr_t addr) { + unsigned actual_id = registry.GetID(addr); + unsigned id = deserializer.Deserialize<unsigned>(); + registry.CheckID(id, actual_id); + registry.GetReplayer(id)->operator()(deserializer); + } + + template <typename Result> + Result ReplayResult(Result &&r, bool update_boundary) { + if (update_boundary) + UpdateBoundary(); + return std::forward<Result>(r); + } + + bool ShouldCapture() { return m_local_boundary; } + private: + template <typename T> friend struct replay; void UpdateBoundary() { if (m_local_boundary) g_global_boundary = false; } - bool ShouldCapture() { return m_local_boundary; } - #ifdef LLDB_REPRO_INSTR_TRACE void Log(unsigned id) { llvm::errs() << "Recording " << id << ": " << m_pretty_func << " (" @@ -721,7 +863,197 @@ private: static bool g_global_boundary; }; +/// To be used as the "Runtime ID" of a constructor. It also invokes the +/// constructor when called. +template <typename Signature> struct construct; +template <typename Class, typename... Args> struct construct<Class(Args...)> { + static Class *handle(lldb_private::repro::InstrumentationData data, + lldb_private::repro::Recorder &recorder, Class *c, + const EmptyArg &) { + return handle(data, recorder, c); + } + + static Class *handle(lldb_private::repro::InstrumentationData data, + lldb_private::repro::Recorder &recorder, Class *c, + Args... args) { + if (!data) + return nullptr; + + if (Serializer *serializer = data.GetSerializer()) { + recorder.Record(*serializer, data.GetRegistry(), &record, args...); + recorder.RecordResult(c, false); + } else if (Deserializer *deserializer = data.GetDeserializer()) { + if (recorder.ShouldCapture()) { + replay(recorder, *deserializer, data.GetRegistry()); + } + } + + return nullptr; + } + + static Class *record(Args... args) { return new Class(args...); } + + static Class *replay(Recorder &recorder, Deserializer &deserializer, + Registry ®istry) { + return recorder.Replay<Class *, Class *(Args...)>( + deserializer, registry, uintptr_t(&record), false); + } +}; + +/// To be used as the "Runtime ID" of a member function. It also invokes the +/// member function when called. +template <typename Signature> struct invoke; +template <typename Result, typename Class, typename... Args> +struct invoke<Result (Class::*)(Args...)> { + template <Result (Class::*m)(Args...)> struct method { + static Result record(Class *c, Args... args) { return (c->*m)(args...); } + + static Result replay(Recorder &recorder, Deserializer &deserializer, + Registry ®istry) { + return recorder.Replay<Result, Result(Class *, Args...)>( + deserializer, registry, uintptr_t(&record), true); + } + }; +}; + +template <typename Class, typename... Args> +struct invoke<void (Class::*)(Args...)> { + template <void (Class::*m)(Args...)> struct method { + static void record(Class *c, Args... args) { (c->*m)(args...); } + static void replay(Recorder &recorder, Deserializer &deserializer, + Registry ®istry) { + recorder.Replay(deserializer, registry, uintptr_t(&record)); + } + }; +}; + +template <typename Result, typename Class, typename... Args> +struct invoke<Result (Class::*)(Args...) const> { + template <Result (Class::*m)(Args...) const> struct method { + static Result record(Class *c, Args... args) { return (c->*m)(args...); } + static Result replay(Recorder &recorder, Deserializer &deserializer, + Registry ®istry) { + return recorder.Replay<Result, Result(Class *, Args...)>( + deserializer, registry, uintptr_t(&record), true); + } + }; +}; + +template <typename Class, typename... Args> +struct invoke<void (Class::*)(Args...) const> { + template <void (Class::*m)(Args...) const> struct method { + static void record(Class *c, Args... args) { return (c->*m)(args...); } + static void replay(Recorder &recorder, Deserializer &deserializer, + Registry ®istry) { + recorder.Replay(deserializer, registry, uintptr_t(&record)); + } + }; +}; + +template <typename Signature> struct replay; + +template <typename Result, typename Class, typename... Args> +struct replay<Result (Class::*)(Args...)> { + template <Result (Class::*m)(Args...)> struct method {}; +}; + +template <typename Result, typename... Args> +struct invoke<Result (*)(Args...)> { + template <Result (*m)(Args...)> struct method { + static Result record(Args... args) { return (*m)(args...); } + static Result replay(Recorder &recorder, Deserializer &deserializer, + Registry ®istry) { + return recorder.Replay<Result, Result(Args...)>(deserializer, registry, + uintptr_t(&record), true); + } + }; +}; + +template <typename... Args> struct invoke<void (*)(Args...)> { + template <void (*m)(Args...)> struct method { + static void record(Args... args) { return (*m)(args...); } + static void replay(Recorder &recorder, Deserializer &deserializer, + Registry ®istry) { + recorder.Replay(deserializer, registry, uintptr_t(&record)); + } + }; +}; + +/// Special handling for functions returning strings as (char*, size_t). +/// { + +/// For inline replay, we ignore the arguments and use the ones from the +/// serializer instead. This doesn't work for methods that use a char* and a +/// size to return a string. For one these functions have a custom replayer to +/// prevent override the input buffer. Furthermore, the template-generated +/// deserialization is not easy to hook into. +/// +/// The specializations below hand-implement the serialization logic for the +/// inline replay. Instead of using the function from the registry, it uses the +/// one passed into the macro. +template <typename Signature> struct invoke_char_ptr; +template <typename Result, typename Class, typename... Args> +struct invoke_char_ptr<Result (Class::*)(Args...) const> { + template <Result (Class::*m)(Args...) const> struct method { + static Result record(Class *c, char *s, size_t l) { + char *buffer = reinterpret_cast<char *>(calloc(l, sizeof(char))); + return (c->*m)(buffer, l); + } + + static Result replay(Recorder &recorder, Deserializer &deserializer, + Registry ®istry, char *str) { + deserializer.Deserialize<unsigned>(); + Class *c = deserializer.Deserialize<Class *>(); + deserializer.Deserialize<const char *>(); + size_t l = deserializer.Deserialize<size_t>(); + return recorder.ReplayResult( + std::move(deserializer.HandleReplayResult((c->*m)(str, l))), true); + } + }; +}; + +template <typename Signature> struct invoke_char_ptr; +template <typename Result, typename Class, typename... Args> +struct invoke_char_ptr<Result (Class::*)(Args...)> { + template <Result (Class::*m)(Args...)> struct method { + static Result record(Class *c, char *s, size_t l) { + char *buffer = reinterpret_cast<char *>(calloc(l, sizeof(char))); + return (c->*m)(buffer, l); + } + + static Result replay(Recorder &recorder, Deserializer &deserializer, + Registry ®istry, char *str) { + deserializer.Deserialize<unsigned>(); + Class *c = deserializer.Deserialize<Class *>(); + deserializer.Deserialize<const char *>(); + size_t l = deserializer.Deserialize<size_t>(); + return recorder.ReplayResult( + std::move(deserializer.HandleReplayResult((c->*m)(str, l))), true); + } + }; +}; + +template <typename Result, typename... Args> +struct invoke_char_ptr<Result (*)(Args...)> { + template <Result (*m)(Args...)> struct method { + static Result record(char *s, size_t l) { + char *buffer = reinterpret_cast<char *>(calloc(l, sizeof(char))); + return (*m)(buffer, l); + } + + static Result replay(Recorder &recorder, Deserializer &deserializer, + Registry ®istry, char *str) { + deserializer.Deserialize<unsigned>(); + deserializer.Deserialize<const char *>(); + size_t l = deserializer.Deserialize<size_t>(); + return recorder.ReplayResult( + std::move(deserializer.HandleReplayResult((*m)(str, l))), true); + } + }; +}; +/// } + } // namespace repro } // namespace lldb_private -#endif // LLDB_UTILITY_REPRODUCER_INSTRUMENTATION_H +#endif // LLDB_UTILITY_REPRODUCERINSTRUMENTATION_H diff --git a/lldb/include/lldb/Utility/Scalar.h b/lldb/include/lldb/Utility/Scalar.h index 69c948ec6222..f215fa71c84c 100644 --- a/lldb/include/lldb/Utility/Scalar.h +++ b/lldb/include/lldb/Utility/Scalar.h @@ -83,20 +83,11 @@ public: Scalar(double v) : m_type(e_double), m_float(v) { m_float = llvm::APFloat(v); } - Scalar(long double v, bool ieee_quad) - : m_type(e_long_double), m_float(static_cast<float>(0)), - m_ieee_quad(ieee_quad) { - if (ieee_quad) - m_float = - llvm::APFloat(llvm::APFloat::IEEEquad(), - llvm::APInt(BITWIDTH_INT128, NUM_OF_WORDS_INT128, - (reinterpret_cast<type128 *>(&v))->x)); - else - m_float = - llvm::APFloat(llvm::APFloat::x87DoubleExtended(), - llvm::APInt(BITWIDTH_INT128, NUM_OF_WORDS_INT128, - (reinterpret_cast<type128 *>(&v))->x)); - } + Scalar(long double v) + : m_type(e_long_double), + m_float(llvm::APFloat::x87DoubleExtended(), + llvm::APInt(BITWIDTH_INT128, NUM_OF_WORDS_INT128, + (reinterpret_cast<type128 *>(&v))->x)) {} Scalar(llvm::APInt v) : m_type(), m_float(static_cast<float>(0)) { m_integer = llvm::APInt(v); m_type = GetBestTypeForBitSize(m_integer.getBitWidth(), true); @@ -115,7 +106,10 @@ public: bool ClearBit(uint32_t bit); - const void *GetBytes() const; + /// Store the binary representation of this value into the given storage. + /// Exactly GetByteSize() bytes will be stored, and the buffer must be large + /// enough to hold this data. + void GetBytes(llvm::MutableArrayRef<uint8_t> storage) const; size_t GetByteSize() const; @@ -131,7 +125,7 @@ public: m_integer.clearAllBits(); } - const char *GetTypeAsCString() const; + const char *GetTypeAsCString() const { return GetValueTypeAsCString(m_type); } void GetValue(Stream *s, bool show_type) const; @@ -139,8 +133,8 @@ public: return (m_type >= e_sint) && (m_type <= e_long_double); } - /// Convert integer to \p type, limited to \p bits size. - void TruncOrExtendTo(Scalar::Type type, uint16_t bits); + /// Convert to an integer with \p bits and the given signedness. + void TruncOrExtendTo(uint16_t bits, bool sign); bool Promote(Scalar::Type type); @@ -162,16 +156,6 @@ public: // automagically by the compiler, so no temporary objects will need to be // created. As a result, we currently don't need a variety of overloaded set // value accessors. - Scalar &operator=(const int i); - Scalar &operator=(unsigned int v); - Scalar &operator=(long v); - Scalar &operator=(unsigned long v); - Scalar &operator=(long long v); - Scalar &operator=(unsigned long long v); - Scalar &operator=(float v); - Scalar &operator=(double v); - Scalar &operator=(long double v); - Scalar &operator=(llvm::APInt v); Scalar &operator+=(const Scalar &rhs); Scalar &operator<<=(const Scalar &rhs); // Shift left Scalar &operator>>=(const Scalar &rhs); // Shift right (arithmetic) @@ -204,7 +188,7 @@ public: unsigned char UChar(unsigned char fail_value = 0) const; - signed char SChar(char fail_value = 0) const; + signed char SChar(signed char fail_value = 0) const; unsigned short UShort(unsigned short fail_value = 0) const; @@ -220,7 +204,7 @@ public: unsigned long long ULongLong(unsigned long long fail_value = 0) const; - llvm::APInt SInt128(llvm::APInt &fail_value) const; + llvm::APInt SInt128(const llvm::APInt &fail_value) const; llvm::APInt UInt128(const llvm::APInt &fail_value) const; @@ -282,7 +266,8 @@ protected: Scalar::Type m_type; llvm::APInt m_integer; llvm::APFloat m_float; - bool m_ieee_quad = false; + + template <typename T> T GetAs(T fail_value) const; private: friend const Scalar operator+(const Scalar &lhs, const Scalar &rhs); diff --git a/lldb/include/lldb/Utility/SelectHelper.h b/lldb/include/lldb/Utility/SelectHelper.h index ec37f194d329..63f1fe6421cf 100644 --- a/lldb/include/lldb/Utility/SelectHelper.h +++ b/lldb/include/lldb/Utility/SelectHelper.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef liblldb_SelectHelper_h_ -#define liblldb_SelectHelper_h_ +#ifndef LLDB_UTILITY_SELECTHELPER_H +#define LLDB_UTILITY_SELECTHELPER_H #include "lldb/Utility/Status.h" #include "lldb/lldb-types.h" @@ -68,4 +68,4 @@ protected: llvm::Optional<std::chrono::steady_clock::time_point> m_end_time; }; -#endif // liblldb_SelectHelper_h_ +#endif // LLDB_UTILITY_SELECTHELPER_H diff --git a/lldb/include/lldb/Utility/SharedCluster.h b/lldb/include/lldb/Utility/SharedCluster.h index 71bbb334cff3..375c1c131a09 100644 --- a/lldb/include/lldb/Utility/SharedCluster.h +++ b/lldb/include/lldb/Utility/SharedCluster.h @@ -6,90 +6,54 @@ // //===----------------------------------------------------------------------===// -#ifndef utility_SharedCluster_h_ -#define utility_SharedCluster_h_ +#ifndef LLDB_UTILITY_SHAREDCLUSTER_H +#define LLDB_UTILITY_SHAREDCLUSTER_H #include "lldb/Utility/LLDBAssert.h" -#include "lldb/Utility/SharingPtr.h" - -#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallVector.h" +#include <memory> #include <mutex> namespace lldb_private { -namespace imp { -template <typename T> -class shared_ptr_refcount : public lldb_private::imp::shared_count { -public: - template <class Y> - shared_ptr_refcount(Y *in) : shared_count(0), manager(in) {} - - shared_ptr_refcount() : shared_count(0) {} - - ~shared_ptr_refcount() override {} - - void on_zero_shared() override { manager->DecrementRefCount(); } - -private: - T *manager; -}; - -} // namespace imp - -template <class T> class ClusterManager { +template <class T> +class ClusterManager : public std::enable_shared_from_this<ClusterManager<T>> { public: - ClusterManager() : m_objects(), m_external_ref(0), m_mutex() {} + static std::shared_ptr<ClusterManager> Create() { + return std::shared_ptr<ClusterManager>(new ClusterManager()); + } ~ClusterManager() { - for (typename llvm::SmallPtrSet<T *, 16>::iterator pos = m_objects.begin(), - end = m_objects.end(); - pos != end; ++pos) { - T *object = *pos; - delete object; - } - - // Decrement refcount should have been called on this ClusterManager, and - // it should have locked the mutex, now we will unlock it before we destroy - // it... - m_mutex.unlock(); + for (T *obj : m_objects) + delete obj; } void ManageObject(T *new_object) { std::lock_guard<std::mutex> guard(m_mutex); - m_objects.insert(new_object); + assert(!llvm::is_contained(m_objects, new_object) && + "ManageObject called twice for the same object?"); + m_objects.push_back(new_object); } - typename lldb_private::SharingPtr<T> GetSharedPointer(T *desired_object) { - { - std::lock_guard<std::mutex> guard(m_mutex); - m_external_ref++; - if (0 == m_objects.count(desired_object)) { - lldbassert(false && "object not found in shared cluster when expected"); - desired_object = nullptr; - } + std::shared_ptr<T> GetSharedPointer(T *desired_object) { + std::lock_guard<std::mutex> guard(m_mutex); + auto this_sp = this->shared_from_this(); + if (!llvm::is_contained(m_objects, desired_object)) { + lldbassert(false && "object not found in shared cluster when expected"); + desired_object = nullptr; } - return typename lldb_private::SharingPtr<T>( - desired_object, new imp::shared_ptr_refcount<ClusterManager>(this)); + return {std::move(this_sp), desired_object}; } private: - void DecrementRefCount() { - m_mutex.lock(); - m_external_ref--; - if (m_external_ref == 0) - delete this; - else - m_mutex.unlock(); - } - - friend class imp::shared_ptr_refcount<ClusterManager>; + ClusterManager() : m_objects(), m_mutex() {} - llvm::SmallPtrSet<T *, 16> m_objects; - int m_external_ref; + llvm::SmallVector<T *, 16> m_objects; std::mutex m_mutex; }; } // namespace lldb_private -#endif // utility_SharedCluster_h_ +#endif // LLDB_UTILITY_SHAREDCLUSTER_H diff --git a/lldb/include/lldb/Utility/SharingPtr.h b/lldb/include/lldb/Utility/SharingPtr.h deleted file mode 100644 index e4ab3d27a69b..000000000000 --- a/lldb/include/lldb/Utility/SharingPtr.h +++ /dev/null @@ -1,609 +0,0 @@ -//===---------------------SharingPtr.h --------------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef utility_SharingPtr_h_ -#define utility_SharingPtr_h_ - -#include <memory> - -// Microsoft Visual C++ currently does not enable std::atomic to work in CLR -// mode - as such we need to "hack around it" for MSVC++ builds only using -// Windows specific intrinsics instead of the C++11 atomic support -#ifdef _MSC_VER -#include <intrin.h> -#else -#include <atomic> -#endif - -#include <stddef.h> - - -//#define ENABLE_SP_LOGGING 1 // DON'T CHECK THIS LINE IN UNLESS COMMENTED OUT -#if defined(ENABLE_SP_LOGGING) - -extern "C" void track_sp(void *sp_this, void *ptr, long count); - -#endif - -namespace lldb_private { - -namespace imp { - -class shared_count { - shared_count(const shared_count &) = delete; - shared_count &operator=(const shared_count &) = delete; - -public: - explicit shared_count(long refs = 0) : shared_owners_(refs) {} - - void add_shared(); - void release_shared(); - long use_count() const { return shared_owners_ + 1; } - -protected: -#ifdef _MSC_VER - long shared_owners_; -#else - std::atomic<long> shared_owners_; -#endif - virtual ~shared_count(); - -private: - virtual void on_zero_shared() = 0; -}; - -template <class T> class shared_ptr_pointer : public shared_count { - T data_; - -public: - shared_ptr_pointer(T p) : data_(p) {} - -private: - void on_zero_shared() override; - - shared_ptr_pointer(const shared_ptr_pointer &) = delete; - shared_ptr_pointer &operator=(const shared_ptr_pointer &) = delete; -}; - -template <class T> void shared_ptr_pointer<T>::on_zero_shared() { - delete data_; -} - -template <class T> class shared_ptr_emplace : public shared_count { - T data_; - -public: - shared_ptr_emplace() : data_() {} - - template <class A0> shared_ptr_emplace(A0 &a0) : data_(a0) {} - - template <class A0, class A1> - shared_ptr_emplace(A0 &a0, A1 &a1) : data_(a0, a1) {} - - template <class A0, class A1, class A2> - shared_ptr_emplace(A0 &a0, A1 &a1, A2 &a2) : data_(a0, a1, a2) {} - - template <class A0, class A1, class A2, class A3> - shared_ptr_emplace(A0 &a0, A1 &a1, A2 &a2, A3 &a3) : data_(a0, a1, a2, a3) {} - - template <class A0, class A1, class A2, class A3, class A4> - shared_ptr_emplace(A0 &a0, A1 &a1, A2 &a2, A3 &a3, A4 &a4) - : data_(a0, a1, a2, a3, a4) {} - -private: - void on_zero_shared() override; - -public: - T *get() { return &data_; } -}; - -template <class T> void shared_ptr_emplace<T>::on_zero_shared() {} - -} // namespace imp - -template <class T> class SharingPtr { -public: - typedef T element_type; - -private: - element_type *ptr_; - imp::shared_count *cntrl_; - - struct nat { - int for_bool_; - }; - -public: - SharingPtr(); - SharingPtr(std::nullptr_t); - template <class Y> explicit SharingPtr(Y *p); - template <class Y> explicit SharingPtr(Y *p, imp::shared_count *ctrl_block); - template <class Y> SharingPtr(const SharingPtr<Y> &r, element_type *p); - SharingPtr(const SharingPtr &r); - template <class Y> SharingPtr(const SharingPtr<Y> &r); - - ~SharingPtr(); - - SharingPtr &operator=(const SharingPtr &r); - template <class Y> SharingPtr &operator=(const SharingPtr<Y> &r); - - void swap(SharingPtr &r); - void reset(); - template <class Y> void reset(Y *p); - void reset(std::nullptr_t); - - element_type *get() const { return ptr_; } - element_type &operator*() const { return *ptr_; } - element_type *operator->() const { return ptr_; } - long use_count() const { return cntrl_ ? cntrl_->use_count() : 0; } - bool unique() const { return use_count() == 1; } - bool empty() const { return cntrl_ == nullptr; } - operator nat *() const { return (nat *)get(); } - - static SharingPtr<T> make_shared(); - - template <class A0> static SharingPtr<T> make_shared(A0 &); - - template <class A0, class A1> static SharingPtr<T> make_shared(A0 &, A1 &); - - template <class A0, class A1, class A2> - static SharingPtr<T> make_shared(A0 &, A1 &, A2 &); - - template <class A0, class A1, class A2, class A3> - static SharingPtr<T> make_shared(A0 &, A1 &, A2 &, A3 &); - - template <class A0, class A1, class A2, class A3, class A4> - static SharingPtr<T> make_shared(A0 &, A1 &, A2 &, A3 &, A4 &); - -private: - template <class U> friend class SharingPtr; -}; - -template <class T> -inline SharingPtr<T>::SharingPtr() : ptr_(nullptr), cntrl_(nullptr) {} - -template <class T> -inline SharingPtr<T>::SharingPtr(std::nullptr_t) - : ptr_(nullptr), cntrl_(nullptr) {} - -template <class T> -template <class Y> -SharingPtr<T>::SharingPtr(Y *p) : ptr_(p), cntrl_(nullptr) { - std::unique_ptr<Y> hold(p); - typedef imp::shared_ptr_pointer<Y *> _CntrlBlk; - cntrl_ = new _CntrlBlk(p); - hold.release(); -} - -template <class T> -template <class Y> -SharingPtr<T>::SharingPtr(Y *p, imp::shared_count *cntrl_block) - : ptr_(p), cntrl_(cntrl_block) {} - -template <class T> -template <class Y> -inline SharingPtr<T>::SharingPtr(const SharingPtr<Y> &r, element_type *p) - : ptr_(p), cntrl_(r.cntrl_) { - if (cntrl_) - cntrl_->add_shared(); -} - -template <class T> -inline SharingPtr<T>::SharingPtr(const SharingPtr &r) - : ptr_(r.ptr_), cntrl_(r.cntrl_) { - if (cntrl_) - cntrl_->add_shared(); -} - -template <class T> -template <class Y> -inline SharingPtr<T>::SharingPtr(const SharingPtr<Y> &r) - : ptr_(r.ptr_), cntrl_(r.cntrl_) { - if (cntrl_) - cntrl_->add_shared(); -} - -template <class T> SharingPtr<T>::~SharingPtr() { - if (cntrl_) - cntrl_->release_shared(); -} - -template <class T> -inline SharingPtr<T> &SharingPtr<T>::operator=(const SharingPtr &r) { - SharingPtr(r).swap(*this); - return *this; -} - -template <class T> -template <class Y> -inline SharingPtr<T> &SharingPtr<T>::operator=(const SharingPtr<Y> &r) { - SharingPtr(r).swap(*this); - return *this; -} - -template <class T> inline void SharingPtr<T>::swap(SharingPtr &r) { - std::swap(ptr_, r.ptr_); - std::swap(cntrl_, r.cntrl_); -} - -template <class T> inline void SharingPtr<T>::reset() { - SharingPtr().swap(*this); -} - -template <class T> inline void SharingPtr<T>::reset(std::nullptr_t p) { - reset(); -} - -template <class T> template <class Y> inline void SharingPtr<T>::reset(Y *p) { - SharingPtr(p).swap(*this); -} - -template <class T> SharingPtr<T> SharingPtr<T>::make_shared() { - typedef imp::shared_ptr_emplace<T> CntrlBlk; - SharingPtr<T> r; - r.cntrl_ = new CntrlBlk(); - r.ptr_ = static_cast<CntrlBlk *>(r.cntrl_)->get(); - return r; -} - -template <class T> -template <class A0> -SharingPtr<T> SharingPtr<T>::make_shared(A0 &a0) { - typedef imp::shared_ptr_emplace<T> CntrlBlk; - SharingPtr<T> r; - r.cntrl_ = new CntrlBlk(a0); - r.ptr_ = static_cast<CntrlBlk *>(r.cntrl_)->get(); - return r; -} - -template <class T> -template <class A0, class A1> -SharingPtr<T> SharingPtr<T>::make_shared(A0 &a0, A1 &a1) { - typedef imp::shared_ptr_emplace<T> CntrlBlk; - SharingPtr<T> r; - r.cntrl_ = new CntrlBlk(a0, a1); - r.ptr_ = static_cast<CntrlBlk *>(r.cntrl_)->get(); - return r; -} - -template <class T> -template <class A0, class A1, class A2> -SharingPtr<T> SharingPtr<T>::make_shared(A0 &a0, A1 &a1, A2 &a2) { - typedef imp::shared_ptr_emplace<T> CntrlBlk; - SharingPtr<T> r; - r.cntrl_ = new CntrlBlk(a0, a1, a2); - r.ptr_ = static_cast<CntrlBlk *>(r.cntrl_)->get(); - return r; -} - -template <class T> -template <class A0, class A1, class A2, class A3> -SharingPtr<T> SharingPtr<T>::make_shared(A0 &a0, A1 &a1, A2 &a2, A3 &a3) { - typedef imp::shared_ptr_emplace<T> CntrlBlk; - SharingPtr<T> r; - r.cntrl_ = new CntrlBlk(a0, a1, a2, a3); - r.ptr_ = static_cast<CntrlBlk *>(r.cntrl_)->get(); - return r; -} - -template <class T> -template <class A0, class A1, class A2, class A3, class A4> -SharingPtr<T> SharingPtr<T>::make_shared(A0 &a0, A1 &a1, A2 &a2, A3 &a3, - A4 &a4) { - typedef imp::shared_ptr_emplace<T> CntrlBlk; - SharingPtr<T> r; - r.cntrl_ = new CntrlBlk(a0, a1, a2, a3, a4); - r.ptr_ = static_cast<CntrlBlk *>(r.cntrl_)->get(); - return r; -} - -template <class T> inline SharingPtr<T> make_shared() { - return SharingPtr<T>::make_shared(); -} - -template <class T, class A0> inline SharingPtr<T> make_shared(A0 &a0) { - return SharingPtr<T>::make_shared(a0); -} - -template <class T, class A0, class A1> -inline SharingPtr<T> make_shared(A0 &a0, A1 &a1) { - return SharingPtr<T>::make_shared(a0, a1); -} - -template <class T, class A0, class A1, class A2> -inline SharingPtr<T> make_shared(A0 &a0, A1 &a1, A2 &a2) { - return SharingPtr<T>::make_shared(a0, a1, a2); -} - -template <class T, class A0, class A1, class A2, class A3> -inline SharingPtr<T> make_shared(A0 &a0, A1 &a1, A2 &a2, A3 &a3) { - return SharingPtr<T>::make_shared(a0, a1, a2, a3); -} - -template <class T, class A0, class A1, class A2, class A3, class A4> -inline SharingPtr<T> make_shared(A0 &a0, A1 &a1, A2 &a2, A3 &a3, A4 &a4) { - return SharingPtr<T>::make_shared(a0, a1, a2, a3, a4); -} - -template <class T, class U> -inline bool operator==(const SharingPtr<T> &__x, const SharingPtr<U> &__y) { - return __x.get() == __y.get(); -} - -template <class T, class U> -inline bool operator!=(const SharingPtr<T> &__x, const SharingPtr<U> &__y) { - return !(__x == __y); -} - -template <class T, class U> -inline bool operator<(const SharingPtr<T> &__x, const SharingPtr<U> &__y) { - return __x.get() < __y.get(); -} - -template <class T> inline void swap(SharingPtr<T> &__x, SharingPtr<T> &__y) { - __x.swap(__y); -} - -template <class T, class U> -inline SharingPtr<T> static_pointer_cast(const SharingPtr<U> &r) { - return SharingPtr<T>(r, static_cast<T *>(r.get())); -} - -template <class T, class U> -SharingPtr<T> const_pointer_cast(const SharingPtr<U> &r) { - return SharingPtr<T>(r, const_cast<T *>(r.get())); -} - -template <class T> class LoggingSharingPtr : public SharingPtr<T> { - typedef SharingPtr<T> base; - -public: - typedef void (*Callback)(void *, const LoggingSharingPtr &, bool action); - // action: false means increment just happened - // true means decrement is about to happen - - LoggingSharingPtr() : cb_(0), baton_(nullptr) {} - - LoggingSharingPtr(Callback cb, void *baton) : cb_(cb), baton_(baton) { - if (cb_) - cb_(baton_, *this, false); - } - - template <class Y> - LoggingSharingPtr(Y *p) : base(p), cb_(0), baton_(nullptr) {} - - template <class Y> - LoggingSharingPtr(Y *p, Callback cb, void *baton) - : base(p), cb_(cb), baton_(baton) { - if (cb_) - cb_(baton_, *this, false); - } - - ~LoggingSharingPtr() { - if (cb_) - cb_(baton_, *this, true); - } - - LoggingSharingPtr(const LoggingSharingPtr &p) - : base(p), cb_(p.cb_), baton_(p.baton_) { - if (cb_) - cb_(baton_, *this, false); - } - - LoggingSharingPtr &operator=(const LoggingSharingPtr &p) { - if (cb_) - cb_(baton_, *this, true); - base::operator=(p); - cb_ = p.cb_; - baton_ = p.baton_; - if (cb_) - cb_(baton_, *this, false); - return *this; - } - - void reset() { - if (cb_) - cb_(baton_, *this, true); - base::reset(); - } - - template <class Y> void reset(Y *p) { - if (cb_) - cb_(baton_, *this, true); - base::reset(p); - if (cb_) - cb_(baton_, *this, false); - } - - void SetCallback(Callback cb, void *baton) { - cb_ = cb; - baton_ = baton; - } - - void ClearCallback() { - cb_ = 0; - baton_ = 0; - } - -private: - Callback cb_; - void *baton_; -}; - -template <class T> class IntrusiveSharingPtr; - -template <class T> class ReferenceCountedBase { -public: - explicit ReferenceCountedBase() : shared_owners_(-1) {} - - void add_shared(); - - void release_shared(); - - long use_count() const { return shared_owners_ + 1; } - -protected: - long shared_owners_; - - friend class IntrusiveSharingPtr<T>; - -private: - ReferenceCountedBase(const ReferenceCountedBase &) = delete; - ReferenceCountedBase &operator=(const ReferenceCountedBase &) = delete; -}; - -template <class T> void lldb_private::ReferenceCountedBase<T>::add_shared() { -#ifdef _MSC_VER - _InterlockedIncrement(&shared_owners_); -#else - ++shared_owners_; -#endif -} - -template <class T> -void lldb_private::ReferenceCountedBase<T>::release_shared() { -#ifdef _MSC_VER - if (_InterlockedDecrement(&shared_owners_) == -1) -#else - if (--shared_owners_ == -1) -#endif - delete static_cast<T *>(this); -} - -template <class T> -class ReferenceCountedBaseVirtual : public imp::shared_count { -public: - explicit ReferenceCountedBaseVirtual() : imp::shared_count(-1) {} - - ~ReferenceCountedBaseVirtual() override = default; - - void on_zero_shared() override; -}; - -template <class T> void ReferenceCountedBaseVirtual<T>::on_zero_shared() {} - -template <typename T> class IntrusiveSharingPtr { -public: - typedef T element_type; - - explicit IntrusiveSharingPtr() : ptr_(0) {} - - explicit IntrusiveSharingPtr(T *ptr) : ptr_(ptr) { add_shared(); } - - IntrusiveSharingPtr(const IntrusiveSharingPtr &rhs) : ptr_(rhs.ptr_) { - add_shared(); - } - - template <class X> - IntrusiveSharingPtr(const IntrusiveSharingPtr<X> &rhs) : ptr_(rhs.get()) { - add_shared(); - } - - IntrusiveSharingPtr &operator=(const IntrusiveSharingPtr &rhs) { - reset(rhs.get()); - return *this; - } - - template <class X> - IntrusiveSharingPtr &operator=(const IntrusiveSharingPtr<X> &rhs) { - reset(rhs.get()); - return *this; - } - - IntrusiveSharingPtr &operator=(T *ptr) { - reset(ptr); - return *this; - } - - ~IntrusiveSharingPtr() { - release_shared(); - ptr_ = nullptr; - } - - T &operator*() const { return *ptr_; } - - T *operator->() const { return ptr_; } - - T *get() const { return ptr_; } - - explicit operator bool() const { return ptr_ != 0; } - - void swap(IntrusiveSharingPtr &rhs) { - std::swap(ptr_, rhs.ptr_); -#if defined(ENABLE_SP_LOGGING) - track_sp(this, ptr_, use_count()); - track_sp(&rhs, rhs.ptr_, rhs.use_count()); -#endif - } - - void reset(T *ptr = nullptr) { IntrusiveSharingPtr(ptr).swap(*this); } - - long use_count() const { - if (ptr_) - return ptr_->use_count(); - return 0; - } - - bool unique() const { return use_count() == 1; } - -private: - element_type *ptr_; - - void add_shared() { - if (ptr_) { - ptr_->add_shared(); -#if defined(ENABLE_SP_LOGGING) - track_sp(this, ptr_, ptr_->use_count()); -#endif - } - } - void release_shared() { - if (ptr_) { -#if defined(ENABLE_SP_LOGGING) - track_sp(this, nullptr, ptr_->use_count() - 1); -#endif - ptr_->release_shared(); - } - } -}; - -template <class T, class U> -inline bool operator==(const IntrusiveSharingPtr<T> &lhs, - const IntrusiveSharingPtr<U> &rhs) { - return lhs.get() == rhs.get(); -} - -template <class T, class U> -inline bool operator!=(const IntrusiveSharingPtr<T> &lhs, - const IntrusiveSharingPtr<U> &rhs) { - return lhs.get() != rhs.get(); -} - -template <class T, class U> -inline bool operator==(const IntrusiveSharingPtr<T> &lhs, U *rhs) { - return lhs.get() == rhs; -} - -template <class T, class U> -inline bool operator!=(const IntrusiveSharingPtr<T> &lhs, U *rhs) { - return lhs.get() != rhs; -} - -template <class T, class U> -inline bool operator==(T *lhs, const IntrusiveSharingPtr<U> &rhs) { - return lhs == rhs.get(); -} - -template <class T, class U> -inline bool operator!=(T *lhs, const IntrusiveSharingPtr<U> &rhs) { - return lhs != rhs.get(); -} - -} // namespace lldb_private - -#endif // utility_SharingPtr_h_ diff --git a/lldb/include/lldb/Utility/Status.h b/lldb/include/lldb/Utility/Status.h index 36f52922c9bc..9babad18edc0 100644 --- a/lldb/include/lldb/Utility/Status.h +++ b/lldb/include/lldb/Utility/Status.h @@ -111,7 +111,7 @@ public: /// Set accessor from a kern_return_t. /// - /// Set accesssor for the error value to \a err and the error type to \c + /// Set accessor for the error value to \a err and the error type to \c /// MachKernel. /// /// \param[in] err @@ -123,9 +123,9 @@ public: int SetExpressionErrorWithFormat(lldb::ExpressionResults, const char *format, ...) __attribute__((format(printf, 3, 4))); - /// Set accesssor with an error value and type. + /// Set accessor with an error value and type. /// - /// Set accesssor for the error value to \a err and the error type to \a + /// Set accessor for the error value to \a err and the error type to \a /// type. /// /// \param[in] err @@ -217,4 +217,4 @@ template <> struct format_provider<lldb_private::Status> { } \ } while (0); -#endif // #ifndef LLDB_UTILITY_STATUS_H +#endif // LLDB_UTILITY_STATUS_H diff --git a/lldb/include/lldb/Utility/Stream.h b/lldb/include/lldb/Utility/Stream.h index 18a16a3461c1..e7f065a1fc7b 100644 --- a/lldb/include/lldb/Utility/Stream.h +++ b/lldb/include/lldb/Utility/Stream.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef liblldb_Stream_h_ -#define liblldb_Stream_h_ +#ifndef LLDB_UTILITY_STREAM_H +#define LLDB_UTILITY_STREAM_H #include "lldb/Utility/Flags.h" #include "lldb/lldb-defines.h" @@ -56,12 +56,13 @@ public: /// /// Construct with dump flags \a flags and the default address size. \a /// flags can be any of the above enumeration logical OR'ed together. - Stream(uint32_t flags, uint32_t addr_size, lldb::ByteOrder byte_order); + Stream(uint32_t flags, uint32_t addr_size, lldb::ByteOrder byte_order, + bool colors = false); /// Construct a default Stream, not binary, host byte order and host addr /// size. /// - Stream(); + Stream(bool colors = false); // FIXME: Streams should not be copyable. Stream(const Stream &other) : m_forwarder(*this) { (*this) = other; } @@ -270,10 +271,8 @@ public: /// optional string following the indentation spaces. /// /// \param[in] s - /// A C string to print following the indentation. If nullptr, just - /// output the indentation characters. - size_t Indent(const char *s = nullptr); - size_t Indent(llvm::StringRef s); + /// A string to print following the indentation. + size_t Indent(llvm::StringRef s = ""); /// Decrement the current indentation level. void IndentLess(unsigned amount = 2); @@ -405,8 +404,10 @@ protected: } public: - RawOstreamForward(Stream &target) - : llvm::raw_ostream(/*unbuffered*/ true), m_target(target) {} + RawOstreamForward(Stream &target, bool colors = false) + : llvm::raw_ostream(/*unbuffered*/ true), m_target(target) { + enable_colors(colors); + } }; RawOstreamForward m_forwarder; }; @@ -461,4 +462,4 @@ void DumpAddressRange(llvm::raw_ostream &s, uint64_t lo_addr, uint64_t hi_addr, } // namespace lldb_private -#endif // liblldb_Stream_h_ +#endif // LLDB_UTILITY_STREAM_H diff --git a/lldb/include/lldb/Utility/StreamCallback.h b/lldb/include/lldb/Utility/StreamCallback.h index 6dbee67ecca2..d6d74fb84799 100644 --- a/lldb/include/lldb/Utility/StreamCallback.h +++ b/lldb/include/lldb/Utility/StreamCallback.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef liblldb_StreamCallback_h_ -#define liblldb_StreamCallback_h_ +#ifndef LLDB_UTILITY_STREAMCALLBACK_H +#define LLDB_UTILITY_STREAMCALLBACK_H #include "lldb/lldb-types.h" #include "llvm/Support/raw_ostream.h" @@ -32,4 +32,4 @@ private: } // namespace lldb_private -#endif // liblldb_StreamCallback_h +#endif // LLDB_UTILITY_STREAMCALLBACK_H diff --git a/lldb/include/lldb/Utility/StreamString.h b/lldb/include/lldb/Utility/StreamString.h index 581e102d4e80..b0be0f7dd76a 100644 --- a/lldb/include/lldb/Utility/StreamString.h +++ b/lldb/include/lldb/Utility/StreamString.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef liblldb_StreamString_h_ -#define liblldb_StreamString_h_ +#ifndef LLDB_UTILITY_STREAMSTRING_H +#define LLDB_UTILITY_STREAMSTRING_H #include "lldb/Utility/Stream.h" #include "lldb/lldb-enumerations.h" @@ -51,4 +51,4 @@ protected: } // namespace lldb_private -#endif // liblldb_StreamString_h_ +#endif // LLDB_UTILITY_STREAMSTRING_H diff --git a/lldb/include/lldb/Utility/StreamTee.h b/lldb/include/lldb/Utility/StreamTee.h index 92e94d4494f6..2995bc07f42a 100644 --- a/lldb/include/lldb/Utility/StreamTee.h +++ b/lldb/include/lldb/Utility/StreamTee.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef liblldb_StreamTee_h_ -#define liblldb_StreamTee_h_ +#ifndef LLDB_UTILITY_STREAMTEE_H +#define LLDB_UTILITY_STREAMTEE_H #include <limits.h> @@ -19,7 +19,8 @@ namespace lldb_private { class StreamTee : public Stream { public: - StreamTee() : Stream(), m_streams_mutex(), m_streams() {} + StreamTee(bool colors = false) + : Stream(colors), m_streams_mutex(), m_streams() {} StreamTee(lldb::StreamSP &stream_sp) : Stream(), m_streams_mutex(), m_streams() { @@ -137,4 +138,4 @@ protected: } // namespace lldb_private -#endif // liblldb_StreamTee_h_ +#endif // LLDB_UTILITY_STREAMTEE_H diff --git a/lldb/include/lldb/Utility/StringExtractor.h b/lldb/include/lldb/Utility/StringExtractor.h index 293fef2fbe6b..6a5bb24779a4 100644 --- a/lldb/include/lldb/Utility/StringExtractor.h +++ b/lldb/include/lldb/Utility/StringExtractor.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef utility_StringExtractor_h_ -#define utility_StringExtractor_h_ +#ifndef LLDB_UTILITY_STRINGEXTRACTOR_H +#define LLDB_UTILITY_STRINGEXTRACTOR_H #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/StringRef.h" @@ -26,7 +26,7 @@ public: virtual ~StringExtractor(); void Reset(llvm::StringRef str) { - m_packet = str; + m_packet = std::string(str); m_index = 0; } @@ -118,4 +118,4 @@ protected: uint64_t m_index; }; -#endif // utility_StringExtractor_h_ +#endif // LLDB_UTILITY_STRINGEXTRACTOR_H diff --git a/lldb/include/lldb/Utility/StringLexer.h b/lldb/include/lldb/Utility/StringLexer.h index 533fd4fb896e..52f98e860da2 100644 --- a/lldb/include/lldb/Utility/StringLexer.h +++ b/lldb/include/lldb/Utility/StringLexer.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef utility_StringLexer_h_ -#define utility_StringLexer_h_ +#ifndef LLDB_UTILITY_STRINGLEXER_H +#define LLDB_UTILITY_STRINGLEXER_H #include <initializer_list> #include <string> @@ -53,4 +53,4 @@ private: } // namespace lldb_private -#endif // #ifndef utility_StringLexer_h_ +#endif // LLDB_UTILITY_STRINGLEXER_H diff --git a/lldb/include/lldb/Utility/StringList.h b/lldb/include/lldb/Utility/StringList.h index 0b1d955678b3..591a15861593 100644 --- a/lldb/include/lldb/Utility/StringList.h +++ b/lldb/include/lldb/Utility/StringList.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef liblldb_StringList_h_ -#define liblldb_StringList_h_ +#ifndef LLDB_UTILITY_STRINGLIST_H +#define LLDB_UTILITY_STRINGLIST_H #include "llvm/ADT/StringRef.h" @@ -132,4 +132,4 @@ private: } // namespace lldb_private -#endif // liblldb_StringList_h_ +#endif // LLDB_UTILITY_STRINGLIST_H diff --git a/lldb/include/lldb/Utility/StructuredData.h b/lldb/include/lldb/Utility/StructuredData.h index 01b14fc3d4d3..14c82e669676 100644 --- a/lldb/include/lldb/Utility/StructuredData.h +++ b/lldb/include/lldb/Utility/StructuredData.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef liblldb_StructuredData_h_ -#define liblldb_StructuredData_h_ +#ifndef LLDB_UTILITY_STRUCTUREDDATA_H +#define LLDB_UTILITY_STRUCTUREDDATA_H #include "llvm/ADT/StringRef.h" #include "llvm/Support/JSON.h" @@ -339,7 +339,7 @@ public: explicit String(llvm::StringRef S) : Object(lldb::eStructuredDataTypeString), m_value(S) {} - void SetValue(llvm::StringRef S) { m_value = S; } + void SetValue(llvm::StringRef S) { m_value = std::string(S); } llvm::StringRef GetValue() { return m_value; } @@ -553,4 +553,4 @@ public: } // namespace lldb_private -#endif // liblldb_StructuredData_h_ +#endif // LLDB_UTILITY_STRUCTUREDDATA_H diff --git a/lldb/include/lldb/Utility/TildeExpressionResolver.h b/lldb/include/lldb/Utility/TildeExpressionResolver.h index 196fdfcf9ab4..3253767ffd75 100644 --- a/lldb/include/lldb/Utility/TildeExpressionResolver.h +++ b/lldb/include/lldb/Utility/TildeExpressionResolver.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLDB_UTILITY_TILDE_EXPRESSION_RESOLVER_H -#define LLDB_UTILITY_TILDE_EXPRESSION_RESOLVER_H +#ifndef LLDB_UTILITY_TILDEEXPRESSIONRESOLVER_H +#define LLDB_UTILITY_TILDEEXPRESSIONRESOLVER_H #include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringSet.h" @@ -61,4 +61,4 @@ public: }; } -#endif // #ifndef LLDB_UTILITY_TILDE_EXPRESSION_RESOLVER_H +#endif // LLDB_UTILITY_TILDEEXPRESSIONRESOLVER_H diff --git a/lldb/include/lldb/Utility/Timeout.h b/lldb/include/lldb/Utility/Timeout.h index 202b747fd480..80e201515577 100644 --- a/lldb/include/lldb/Utility/Timeout.h +++ b/lldb/include/lldb/Utility/Timeout.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef liblldb_Timeout_h_ -#define liblldb_Timeout_h_ +#ifndef LLDB_UTILITY_TIMEOUT_H +#define LLDB_UTILITY_TIMEOUT_H #include "llvm/ADT/Optional.h" #include "llvm/Support/Chrono.h" @@ -67,4 +67,4 @@ struct format_provider<lldb_private::Timeout<Ratio>, void> { }; } -#endif // liblldb_Timeout_h_ +#endif // LLDB_UTILITY_TIMEOUT_H diff --git a/lldb/include/lldb/Utility/Timer.h b/lldb/include/lldb/Utility/Timer.h index ad9421a75b15..f97315b2db0f 100644 --- a/lldb/include/lldb/Utility/Timer.h +++ b/lldb/include/lldb/Utility/Timer.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef liblldb_Timer_h_ -#define liblldb_Timer_h_ +#ifndef LLDB_UTILITY_TIMER_H +#define LLDB_UTILITY_TIMER_H #include "lldb/lldb-defines.h" #include "llvm/Support/Chrono.h" @@ -34,7 +34,8 @@ public: std::atomic<uint64_t> m_count; std::atomic<Category *> m_next; - DISALLOW_COPY_AND_ASSIGN(Category); + Category(const Category &) = delete; + const Category &operator=(const Category &) = delete; }; /// Default constructor. @@ -66,9 +67,10 @@ protected: static std::atomic<unsigned> g_display_depth; private: - DISALLOW_COPY_AND_ASSIGN(Timer); + Timer(const Timer &) = delete; + const Timer &operator=(const Timer &) = delete; }; } // namespace lldb_private -#endif // liblldb_Timer_h_ +#endif // LLDB_UTILITY_TIMER_H diff --git a/lldb/include/lldb/Utility/TraceOptions.h b/lldb/include/lldb/Utility/TraceOptions.h index d5e21ccd8ba3..97aad33899be 100644 --- a/lldb/include/lldb/Utility/TraceOptions.h +++ b/lldb/include/lldb/Utility/TraceOptions.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef liblldb_TraceOptions_h_ -#define liblldb_TraceOptions_h_ +#ifndef LLDB_UTILITY_TRACEOPTIONS_H +#define LLDB_UTILITY_TRACEOPTIONS_H #include "lldb/lldb-defines.h" #include "lldb/lldb-enumerations.h" @@ -57,4 +57,4 @@ private: }; } -#endif // liblldb_TraceOptions_h_ +#endif // LLDB_UTILITY_TRACEOPTIONS_H diff --git a/lldb/include/lldb/Utility/UUID.h b/lldb/include/lldb/Utility/UUID.h index 0284357be44a..5327719094c0 100644 --- a/lldb/include/lldb/Utility/UUID.h +++ b/lldb/include/lldb/Utility/UUID.h @@ -63,18 +63,13 @@ public: std::string GetAsString(llvm::StringRef separator = "-") const; - size_t SetFromStringRef(llvm::StringRef str, uint32_t num_uuid_bytes = 16); + bool SetFromStringRef(llvm::StringRef str); // Same as SetFromStringRef, but if the resultant UUID is all 0 bytes, set the // UUID to invalid. - size_t SetFromOptionalStringRef(llvm::StringRef str, - uint32_t num_uuid_bytes = 16); - - // Decode as many UUID bytes (up to 16) as possible from the C string "cstr" - // This is used for auto completion where a partial UUID might have been - // typed in. It - /// Decode as many UUID bytes (up to 16) as possible from the C - /// string \a cstr. + bool SetFromOptionalStringRef(llvm::StringRef str); + + /// Decode as many UUID bytes as possible from the C string \a cstr. /// /// \param[in] str /// An llvm::StringRef that points at a UUID string value (no leading @@ -88,8 +83,7 @@ public: /// The original string, with all decoded bytes removed. static llvm::StringRef DecodeUUIDBytesFromString(llvm::StringRef str, - llvm::SmallVectorImpl<uint8_t> &uuid_bytes, - uint32_t num_uuid_bytes = 16); + llvm::SmallVectorImpl<uint8_t> &uuid_bytes); private: UUID(llvm::ArrayRef<uint8_t> bytes) : m_bytes(bytes.begin(), bytes.end()) {} diff --git a/lldb/include/lldb/Utility/UriParser.h b/lldb/include/lldb/Utility/UriParser.h index 4a3f01230e1a..6a64c3d747b5 100644 --- a/lldb/include/lldb/Utility/UriParser.h +++ b/lldb/include/lldb/Utility/UriParser.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef utility_UriParser_h_ -#define utility_UriParser_h_ +#ifndef LLDB_UTILITY_URIPARSER_H +#define LLDB_UTILITY_URIPARSER_H #include "llvm/ADT/StringRef.h" @@ -28,4 +28,4 @@ public: }; } -#endif // utility_UriParser_h_ +#endif // LLDB_UTILITY_URIPARSER_H diff --git a/lldb/include/lldb/Utility/UserID.h b/lldb/include/lldb/Utility/UserID.h index 2dc5cdb23d0e..9fc6985a5a99 100644 --- a/lldb/include/lldb/Utility/UserID.h +++ b/lldb/include/lldb/Utility/UserID.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef liblldb_UserID_h_ -#define liblldb_UserID_h_ +#ifndef LLDB_UTILITY_USERID_H +#define LLDB_UTILITY_USERID_H #include "lldb/lldb-defines.h" #include "lldb/lldb-types.h" @@ -90,4 +90,4 @@ Stream &operator<<(Stream &strm, const UserID &uid); } // namespace lldb_private -#endif // liblldb_UserID_h_ +#endif // LLDB_UTILITY_USERID_H diff --git a/lldb/include/lldb/Utility/UserIDResolver.h b/lldb/include/lldb/Utility/UserIDResolver.h index bca82a11b660..e0f7b69cc075 100644 --- a/lldb/include/lldb/Utility/UserIDResolver.h +++ b/lldb/include/lldb/Utility/UserIDResolver.h @@ -53,4 +53,4 @@ private: } // namespace lldb_private -#endif // #ifndef LLDB_HOST_USERIDRESOLVER_H +#endif // LLDB_UTILITY_USERIDRESOLVER_H diff --git a/lldb/include/lldb/Utility/VASPrintf.h b/lldb/include/lldb/Utility/VASPrintf.h index 582645fd2292..a4b5f7ddae2c 100644 --- a/lldb/include/lldb/Utility/VASPrintf.h +++ b/lldb/include/lldb/Utility/VASPrintf.h @@ -17,4 +17,4 @@ namespace lldb_private { bool VASprintf(llvm::SmallVectorImpl<char> &buf, const char *fmt, va_list args); } -#endif // #ifdef LLDB_UTILITY_VASPRINTF_H +#endif // LLDB_UTILITY_VASPRINTF_H diff --git a/lldb/include/lldb/Utility/VMRange.h b/lldb/include/lldb/Utility/VMRange.h index 72f859b67582..4b01cd86da2c 100644 --- a/lldb/include/lldb/Utility/VMRange.h +++ b/lldb/include/lldb/Utility/VMRange.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef liblldb_VMRange_h_ -#define liblldb_VMRange_h_ +#ifndef LLDB_UTILITY_VMRANGE_H +#define LLDB_UTILITY_VMRANGE_H #include "lldb/lldb-types.h" #include "llvm/Support/raw_ostream.h" @@ -101,4 +101,4 @@ bool operator>=(const VMRange &lhs, const VMRange &rhs); } // namespace lldb_private -#endif // liblldb_VMRange_h_ +#endif // LLDB_UTILITY_VMRANGE_H diff --git a/lldb/include/lldb/Utility/XcodeSDK.h b/lldb/include/lldb/Utility/XcodeSDK.h new file mode 100644 index 000000000000..307fe7f46798 --- /dev/null +++ b/lldb/include/lldb/Utility/XcodeSDK.h @@ -0,0 +1,96 @@ +//===-- XcodeSDK.h ----------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLDB_UTILITY_SDK_H +#define LLDB_UTILITY_SDK_H + +#include "lldb/lldb-forward.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/VersionTuple.h" +#include <tuple> + +namespace llvm { +class Triple; +} + +namespace lldb_private { + +/// An abstraction for Xcode-style SDKs that works like \ref ArchSpec. +class XcodeSDK { + std::string m_name; + +public: + /// Different types of Xcode SDKs. + enum Type : int { + MacOSX = 0, + iPhoneSimulator, + iPhoneOS, + AppleTVSimulator, + AppleTVOS, + WatchSimulator, + watchOS, + bridgeOS, + Linux, + unknown = -1 + }; + static constexpr int numSDKTypes = Linux + 1; + + /// A parsed SDK directory name. + struct Info { + Type type = unknown; + llvm::VersionTuple version; + bool internal = false; + + Info() = default; + bool operator<(const Info &other) const; + bool operator==(const Info &other) const; + }; + + + /// Default constructor, constructs an empty string. + XcodeSDK() = default; + /// Construct an XcodeSDK object from a specification. + XcodeSDK(Info info); + /// Initialize an XcodeSDK object with an SDK name. The SDK name is the last + /// directory component of a path one would pass to clang's -isysroot + /// parameter. For example, "MacOSX.10.14.sdk". + XcodeSDK(std::string &&name) : m_name(std::move(name)) {} + static XcodeSDK GetAnyMacOS() { return XcodeSDK("MacOSX.sdk"); } + + /// The merge function follows a strict order to maintain monotonicity: + /// 1. SDK with the higher SDKType wins. + /// 2. The newer SDK wins. + void Merge(XcodeSDK other); + + XcodeSDK &operator=(XcodeSDK other); + XcodeSDK(const XcodeSDK&) = default; + bool operator==(XcodeSDK other); + + /// Return parsed SDK type and version number. + Info Parse() const; + bool IsAppleInternalSDK() const; + llvm::VersionTuple GetVersion() const; + Type GetType() const; + llvm::StringRef GetString() const; + /// Whether this Xcode SDK supports Swift. + bool SupportsSwift() const; + + /// Whether LLDB feels confident importing Clang modules from this SDK. + static bool SDKSupportsModules(Type type, llvm::VersionTuple version); + static bool SDKSupportsModules(Type desired_type, const FileSpec &sdk_path); + /// Return the canonical SDK name, such as "macosx" for the macOS SDK. + static std::string GetCanonicalName(Info info); + /// Return the best-matching SDK type for a specific triple. + static XcodeSDK::Type GetSDKTypeForTriple(const llvm::Triple &triple); + + static std::string FindXcodeContentsDirectoryInPath(llvm::StringRef path); +}; + +} // namespace lldb_private + +#endif |