<html><head><meta http-equiv="Content-Type" content="text/html charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class="">A few remarks</div><br class=""><div><blockquote type="cite" class=""><div class="">On Sep 19, 2016, at 1:18 PM, Zachary Turner via lldb-dev <<a href="mailto:lldb-dev@lists.llvm.org" class="">lldb-dev@lists.llvm.org</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><div dir="ltr" class="">Following up with Kate's post from a few weeks ago, I think the dust has settled on the code reformat and it went over pretty smoothly for the most part.  So I thought it might be worth throwing out some ideas for where we go from here.  I have a large list of ideas (more ideas than time, sadly) that I've been collecting over the past few weeks, so I figured I would throw them out in the open for discussion.<div class=""><br class=""></div><div class=""><span id="inbox-inbox-docs-internal-guid-68353e50-4408-e1e7-100e-f9ce9abc13e0" class=""><div style="line-height: 1.38; margin-top: 0pt; margin-bottom: 0pt;" class=""><span style="font-size:14.6667px;font-family:arial;vertical-align:baseline;white-space:pre-wrap" class="">I’ve grouped the areas for improvement into 3 high level categories.</span></div><br class=""><ol style="margin-top:0pt;margin-bottom:0pt" class=""><li style="list-style-type:decimal;font-size:14.6667px;font-family:arial;vertical-align:baseline" class=""><div style="line-height: 1.38; margin-top: 0pt; margin-bottom: 0pt;" class=""><span style="font-size:14.6667px;font-weight:700;font-style:italic;vertical-align:baseline;white-space:pre-wrap" class="">De</span><span style="font-size:14.6667px;vertical-align:baseline;white-space:pre-wrap" class="">-inventing the wheel - We should use more code from LLVM, and delete code in LLDB where LLVM provides a solution.  In cases where there is an LLVM thing that is *similar* to what we need, we should extend the LLVM thing to support what we need, and then use it.  Following are some areas I've identified.  This list is by no means complete.  For each one, I've given a personal assessment of how likely it is to cause some (temporary) hiccups, how much it would help us in the long run, and how difficult it would be to do.  Without further ado:</span></div></li><ol style="margin-top:0pt;margin-bottom:0pt" class=""><li style="list-style-type:lower-alpha;font-size:14.6667px;font-family:arial;vertical-align:baseline" class=""><div style="line-height: 1.38; margin-top: 0pt; margin-bottom: 0pt;" class=""><span style="font-size:14.6667px;vertical-align:baseline;white-space:pre-wrap" class="">Use </span><span style="font-size:14.6667px;font-family:"courier new";vertical-align:baseline;white-space:pre-wrap" class="">llvm::Regex</span><span style="font-size:14.6667px;vertical-align:baseline;white-space:pre-wrap" class=""> instead of </span><span style="font-size:14.6667px;font-family:"courier new";vertical-align:baseline;white-space:pre-wrap" class="">lldb::Regex</span></div></li><ol style="margin-top:0pt;margin-bottom:0pt" class=""><li style="list-style-type:lower-roman;font-size:14.6667px;vertical-align:baseline" class=""><div style="line-height: 1.38; margin-top: 0pt; margin-bottom: 0pt;" class=""><span style="font-family:"courier new";font-size:14.6667px;vertical-align:baseline;white-space:pre-wrap" class="">llvm::Regex</span><span style="font-size:14.6667px;vertical-align:baseline;white-space:pre-wrap" class=""><font face="arial" class=""> doesn’t support enhanced mode.  Could we add support for this to </font></span><span style="font-family:"courier new";font-size:14.6667px;line-height:20.24px;white-space:pre-wrap" class="">llvm::Regex?</span></div></li><li style="list-style-type:lower-roman;font-size:14.6667px;font-family:arial;vertical-align:baseline" class=""><div style="line-height: 1.38; margin-top: 0pt; margin-bottom: 0pt;" class=""><span style="font-size:14.6667px;vertical-align:baseline;white-space:pre-wrap" class="">Risk: 6</span></div></li><li style="list-style-type:lower-roman;font-size:14.6667px;font-family:arial;vertical-align:baseline" class=""><div style="line-height: 1.38; margin-top: 0pt; margin-bottom: 0pt;" class=""><span style="font-size:14.6667px;vertical-align:baseline;white-space:pre-wrap" class="">Impact: 3</span></div></li><li style="list-style-type:lower-roman;font-size:14.6667px;font-family:arial;vertical-align:baseline" class=""><div style="line-height: 1.38; margin-top: 0pt; margin-bottom: 0pt;" class=""><span style="font-size:14.6667px;vertical-align:baseline;white-space:pre-wrap" class="">Difficulty / Effort: 3  (5 if we have to add enhanced mode support)</span></div></li></ol><li style="list-style-type:lower-alpha;font-size:14.6667px;font-family:arial;vertical-align:baseline" class=""><div style="line-height: 1.38; margin-top: 0pt; margin-bottom: 0pt;" class=""><span style="font-size:14.6667px;vertical-align:baseline;white-space:pre-wrap" class="">Use llvm streams instead of </span><span style="font-size:14.6667px;font-family:"courier new";vertical-align:baseline;white-space:pre-wrap" class="">lldb::StreamString</span></div></li><ol style="margin-top:0pt;margin-bottom:0pt" class=""><li style="list-style-type:lower-roman;font-size:14.6667px;font-family:arial;vertical-align:baseline" class=""><div style="line-height: 1.38; margin-top: 0pt; margin-bottom: 0pt;" class=""><span style="font-size:14.6667px;vertical-align:baseline;white-space:pre-wrap" class="">Supports output re-targeting (stderr, stdout, std::string, etc), printf style formatting, and type-safe streaming operators.</span></div></li><li style="list-style-type:lower-roman;font-size:14.6667px;font-family:arial;vertical-align:baseline" class=""><div style="line-height: 1.38; margin-top: 0pt; margin-bottom: 0pt;" class=""><span style="font-size:14.6667px;vertical-align:baseline;white-space:pre-wrap" class="">Interoperates nicely with many existing llvm utility classes</span></div></li><li style="list-style-type:lower-roman;font-size:14.6667px;font-family:arial;vertical-align:baseline" class=""><div style="line-height: 1.38; margin-top: 0pt; margin-bottom: 0pt;" class=""><span style="font-size:14.6667px;vertical-align:baseline;white-space:pre-wrap" class="">Risk: 4</span></div></li><li style="list-style-type:lower-roman;font-size:14.6667px;font-family:arial;vertical-align:baseline" class=""><div style="line-height: 1.38; margin-top: 0pt; margin-bottom: 0pt;" class=""><span style="font-size:14.6667px;vertical-align:baseline;white-space:pre-wrap" class="">Impact: 5</span></div></li><li style="list-style-type:lower-roman;font-size:14.6667px;font-family:arial;vertical-align:baseline" class=""><div style="line-height: 1.38; margin-top: 0pt; margin-bottom: 0pt;" class=""><span style="font-size:14.6667px;vertical-align:baseline;white-space:pre-wrap" class="">Difficulty / Effort: 7</span></div></li></ol><li style="list-style-type:lower-alpha;font-size:14.6667px;font-family:arial;vertical-align:baseline" class=""><div style="line-height: 1.38; margin-top: 0pt; margin-bottom: 0pt;" class=""><span style="font-size:14.6667px;vertical-align:baseline;white-space:pre-wrap" class="">Use </span><span style="font-size:14.6667px;font-family:"courier new";vertical-align:baseline;white-space:pre-wrap" class="">llvm::Error</span><span style="font-size:14.6667px;vertical-align:baseline;white-space:pre-wrap" class=""> instead of </span><span style="font-size:14.6667px;font-family:"courier new";vertical-align:baseline;white-space:pre-wrap" class="">lldb::Error</span></div></li><ol style="margin-top:0pt;margin-bottom:0pt" class=""><li style="list-style-type:lower-roman;font-size:14.6667px;font-family:arial;vertical-align:baseline" class=""><div style="line-height: 1.38; margin-top: 0pt; margin-bottom: 0pt;" class=""><span style="font-size:14.6667px;vertical-align:baseline;white-space:pre-wrap" class=""><span style="font-size:14.6667px;line-height:20.24px;font-family:"courier new";vertical-align:baseline" class="">llvm::Error</span><span style="font-size:14.6667px;line-height:20.24px;vertical-align:baseline" class=""> </span>is an error class that *requires* you to check whether it succeeded or it will assert.</span></div></li></ol></ol></ol></span></div></div></div></blockquote><div><br class=""></div><div>I assume that assertion would be stripped in Release builds?</div><div>We have our own lldbassert() macro currently, which assert()s in Debug mode, but in Release mode produces an error message and continues</div><div>It would be great if llvm::Error allowed us to plug that in..</div><div><br class=""></div><blockquote type="cite" class=""><div class=""><div dir="ltr" class=""><div class=""><span id="inbox-inbox-docs-internal-guid-68353e50-4408-e1e7-100e-f9ce9abc13e0" class=""><ol style="margin-top:0pt;margin-bottom:0pt" class=""><ol style="margin-top:0pt;margin-bottom:0pt" class="" start="4"><ol style="margin-top:0pt;margin-bottom:0pt" class="" start="1"><li style="list-style-type:lower-roman;font-size:14.6667px;font-family:arial;vertical-align:baseline" class=""><div style="line-height: 1.38; margin-top: 0pt; margin-bottom: 0pt;" class=""><span style="font-size:14.6667px;vertical-align:baseline;white-space:pre-wrap" class="">  In a way, it's similar to a C++ exception, except that it doesn't come with the performance hit associated with exceptions.  It's extensible, and can be easily extended to support the various ways LLDB needs to construct errors and error messages.</span></div></li><li style="list-style-type:lower-roman;font-size:14.6667px;font-family:arial;vertical-align:baseline" class=""><div style="margin-top: 0pt; margin-bottom: 0pt;" class=""><span style="line-height:1.38;font-size:14.6667px;vertical-align:baseline;white-space:pre-wrap" class="">Would need to first rename </span><span style="line-height:1.38;font-size:14.6667px;font-family:"courier new";vertical-align:baseline;white-space:pre-wrap" class="">lldb::Error</span><span style="line-height:1.38;font-size:14.6667px;vertical-align:baseline;white-space:pre-wrap" class=""> to </span><span style="font-size:14.6667px;font-family:"courier new";vertical-align:baseline;white-space:pre-wrap" class=""><span style="line-height:1.38" class="">LLDBError </span></span><span style="font-size:14.6667px;line-height:20.24px;white-space:pre-wrap" class="">so that te conversion from <span style="font-family:"courier new";font-size:14.6667px;line-height:20.24px" class="">LLDBError</span> to </span><span style="font-family:"courier new";font-size:14.6667px;line-height:20.24px;white-space:pre-wrap" class="">llvm::Error </span><span style="font-size:14.6667px;line-height:20.24px;white-space:pre-wrap" class="">could be done incrementally.</span></div></li><li style="list-style-type:lower-roman;font-size:14.6667px;font-family:arial;vertical-align:baseline" class=""><div style="line-height: 1.38; margin-top: 0pt; margin-bottom: 0pt;" class=""><span style="font-size:14.6667px;vertical-align:baseline;white-space:pre-wrap" class="">Risk: 7</span></div></li><li style="list-style-type:lower-roman;font-size:14.6667px;font-family:arial;vertical-align:baseline" class=""><div style="line-height: 1.38; margin-top: 0pt; margin-bottom: 0pt;" class=""><span style="font-size:14.6667px;vertical-align:baseline;white-space:pre-wrap" class="">Impact: 7</span></div></li><li style="list-style-type:lower-roman;font-size:14.6667px;font-family:arial;vertical-align:baseline" class=""><div style="line-height: 1.38; margin-top: 0pt; margin-bottom: 0pt;" class=""><span style="font-size:14.6667px;vertical-align:baseline;white-space:pre-wrap" class="">Difficulty / Effort: 8</span></div></li></ol><li style="list-style-type:lower-alpha;font-size:14.6667px;font-family:arial;vertical-align:baseline" class=""><div style="line-height: 1.38; margin-top: 0pt; margin-bottom: 0pt;" class=""><span style="font-size:14.6667px;font-family:"courier new";vertical-align:baseline;white-space:pre-wrap" class="">StringRef</span><span style="font-size:14.6667px;vertical-align:baseline;white-space:pre-wrap" class=""> instead of </span><span style="font-size:14.6667px;font-family:"courier new";vertical-align:baseline;white-space:pre-wrap" class="">const char *</span><span style="font-size:14.6667px;vertical-align:baseline;white-space:pre-wrap" class="">, len everywhere</span></div></li><ol style="margin-top:0pt;margin-bottom:0pt" class=""><li style="list-style-type:lower-roman;font-size:14.6667px;font-family:arial;vertical-align:baseline" class=""><div style="line-height: 1.38; margin-top: 0pt; margin-bottom: 0pt;" class=""><span style="font-size:14.6667px;vertical-align:baseline;white-space:pre-wrap" class="">Can do most common string operations in a way that is guaranteed to be safe.</span></div></li><li style="list-style-type:lower-roman;font-size:14.6667px;font-family:arial;vertical-align:baseline" class=""><div style="line-height: 1.38; margin-top: 0pt; margin-bottom: 0pt;" class=""><span style="font-size:14.6667px;vertical-align:baseline;white-space:pre-wrap" class="">Reduces string manipulation algorithm complexity by an order of magnitude.</span></div></li><li style="list-style-type:lower-roman;font-size:14.6667px;font-family:arial;vertical-align:baseline" class=""><div style="line-height: 1.38; margin-top: 0pt; margin-bottom: 0pt;" class=""><span style="font-size:14.6667px;vertical-align:baseline;white-space:pre-wrap" class="">Can potentially eliminate tens of thousands of string copies across the codebase.</span></div></li><li style="list-style-type:lower-roman;font-size:14.6667px;font-family:arial;vertical-align:baseline" class=""><div style="line-height: 1.38; margin-top: 0pt; margin-bottom: 0pt;" class=""><span style="font-size:14.6667px;vertical-align:baseline;white-space:pre-wrap" class="">Simplifies code.</span></div></li><li style="list-style-type:lower-roman;font-size:14.6667px;font-family:arial;vertical-align:baseline" class=""><div style="line-height: 1.38; margin-top: 0pt; margin-bottom: 0pt;" class=""><span style="font-size:14.6667px;vertical-align:baseline;white-space:pre-wrap" class="">Risk: 3</span></div></li><li style="list-style-type:lower-roman;font-size:14.6667px;font-family:arial;vertical-align:baseline" class=""><div style="line-height: 1.38; margin-top: 0pt; margin-bottom: 0pt;" class=""><span style="font-size:14.6667px;vertical-align:baseline;white-space:pre-wrap" class="">Impact: 8</span></div></li><li style="list-style-type:lower-roman;font-size:14.6667px;font-family:arial;vertical-align:baseline" class=""><div style="line-height: 1.38; margin-top: 0pt; margin-bottom: 0pt;" class=""><span style="font-size:14.6667px;vertical-align:baseline;white-space:pre-wrap" class="">Difficulty / Effort: 7</span></div></li></ol><li style="list-style-type:lower-alpha;font-size:14.6667px;font-family:arial;vertical-align:baseline" class=""><div style="line-height: 1.38; margin-top: 0pt; margin-bottom: 0pt;" class=""><span style="font-size:14.6667px;font-family:"courier new";vertical-align:baseline;white-space:pre-wrap" class="">ArrayRef </span><span style="font-size:14.6667px;vertical-align:baseline;white-space:pre-wrap" class="">instead of </span><span style="font-size:14.6667px;font-family:"courier new";vertical-align:baseline;white-space:pre-wrap" class="">const void *</span><span style="font-size:14.6667px;vertical-align:baseline;white-space:pre-wrap" class="">, len everywhere</span></div></li><ol style="margin-top:0pt;margin-bottom:0pt" class=""><li style="list-style-type:lower-roman;font-size:14.6667px;font-family:arial;vertical-align:baseline" class=""><div style="line-height: 1.38; margin-top: 0pt; margin-bottom: 0pt;" class=""><span style="font-size:14.6667px;vertical-align:baseline;white-space:pre-wrap" class="">Same analysis as </span><span style="font-size:14.6667px;font-family:"courier new";vertical-align:baseline;white-space:pre-wrap" class="">StringRef</span></div></li></ol><li style="list-style-type:lower-alpha;font-size:14.6667px;font-family:arial;vertical-align:baseline" class=""><div style="line-height: 1.38; margin-top: 0pt; margin-bottom: 0pt;" class=""><span style="font-size:14.6667px;font-family:"courier new";vertical-align:baseline;white-space:pre-wrap" class="">MutableArrayRef </span><span style="font-size:14.6667px;vertical-align:baseline;white-space:pre-wrap" class="">instead of </span><span style="font-size:14.6667px;font-family:"courier new";vertical-align:baseline;white-space:pre-wrap" class="">void *</span><span style="font-size:14.6667px;vertical-align:baseline;white-space:pre-wrap" class="">, len everywhere</span></div></li><ol style="margin-top:0pt;margin-bottom:0pt" class=""><li style="list-style-type:lower-roman;font-size:14.6667px;font-family:arial;vertical-align:baseline" class=""><div style="line-height: 1.38; margin-top: 0pt; margin-bottom: 0pt;" class=""><span style="font-size:14.6667px;vertical-align:baseline;white-space:pre-wrap" class="">Same analysis as </span><span style="font-size:14.6667px;font-family:"courier new";vertical-align:baseline;white-space:pre-wrap" class="">StringRef</span></div></li></ol></ol></ol></span></div></div></div></blockquote><div><br class=""></div><div>I don't think we have a lot of those - IIRC, it's mostly in the SB API where SWIG is supposed to map it back to a Python string</div><br class=""><blockquote type="cite" class=""><div class=""><div dir="ltr" class=""><div class=""><span id="inbox-inbox-docs-internal-guid-68353e50-4408-e1e7-100e-f9ce9abc13e0" class=""><ol style="margin-top:0pt;margin-bottom:0pt" class="" start="2"><ol style="margin-top:0pt;margin-bottom:0pt" class="" start="7"><li style="list-style-type:lower-alpha;font-size:14.6667px;font-family:arial;vertical-align:baseline" class=""><div style="line-height: 1.38; margin-top: 0pt; margin-bottom: 0pt;" class=""><span style="font-size:14.6667px;vertical-align:baseline;white-space:pre-wrap" class="">Delete </span><span style="font-size:14.6667px;font-family:"courier new";vertical-align:baseline;white-space:pre-wrap" class="">ConstString</span><span style="font-size:14.6667px;vertical-align:baseline;white-space:pre-wrap" class="">, use a modified </span><span style="font-size:14.6667px;font-family:"courier new";vertical-align:baseline;white-space:pre-wrap" class="">StringPool</span><span style="font-size:14.6667px;vertical-align:baseline;white-space:pre-wrap" class=""> that is thread-safe.</span></div></li><ol style="margin-top:0pt;margin-bottom:0pt" class=""><li style="list-style-type:lower-roman;font-size:14.6667px;font-family:arial;vertical-align:baseline" class=""><div style="line-height: 1.38; margin-top: 0pt; margin-bottom: 0pt;" class=""><span style="font-size:14.6667px;font-family:"courier new";vertical-align:baseline;white-space:pre-wrap" class="">StringPool</span><span style="font-size:14.6667px;vertical-align:baseline;white-space:pre-wrap" class=""> is a non thread-safe version of </span><span style="font-size:14.6667px;font-family:"courier new";vertical-align:baseline;white-space:pre-wrap" class="">ConstString</span><span style="font-size:14.6667px;vertical-align:baseline;white-space:pre-wrap" class="">.</span></div></li><li style="list-style-type:lower-roman;font-size:14.6667px;font-family:arial;vertical-align:baseline" class=""><div style="line-height: 1.38; margin-top: 0pt; margin-bottom: 0pt;" class=""><span style="font-size:14.6667px;vertical-align:baseline;white-space:pre-wrap" class="">Strings are internally refcounted so they can be cleaned up when they are no longer used.  </span><span style="font-size:14.6667px;font-family:"courier new";vertical-align:baseline;white-space:pre-wrap" class="">ConstStrings</span><span style="font-size:14.6667px;vertical-align:baseline;white-space:pre-wrap" class=""> are a large source of memory in LLDB, so ref-counting and removing stale strings has the potential to be a huge savings.</span></div></li><li style="list-style-type:lower-roman;font-size:14.6667px;font-family:arial;vertical-align:baseline" class=""><div style="line-height: 1.38; margin-top: 0pt; margin-bottom: 0pt;" class=""><span style="font-size:14.6667px;vertical-align:baseline;white-space:pre-wrap" class="">Risk: 2</span></div></li><li style="list-style-type:lower-roman;font-size:14.6667px;font-family:arial;vertical-align:baseline" class=""><div style="line-height: 1.38; margin-top: 0pt; margin-bottom: 0pt;" class=""><span style="font-size:14.6667px;vertical-align:baseline;white-space:pre-wrap" class="">Impact: 9</span></div></li><li style="list-style-type:lower-roman;font-size:14.6667px;font-family:arial;vertical-align:baseline" class=""><div style="line-height: 1.38; margin-top: 0pt; margin-bottom: 0pt;" class=""><span style="font-size:14.6667px;vertical-align:baseline;white-space:pre-wrap" class="">Difficulty / Effort: 6</span></div></li></ol><li style="list-style-type:lower-alpha;font-size:14.6667px;font-family:arial;vertical-align:baseline" class=""><div style="line-height: 1.38; margin-top: 0pt; margin-bottom: 0pt;" class=""><span style="font-size:14.6667px;font-family:"courier new";vertical-align:baseline;white-space:pre-wrap" class="">thread_local </span><span style="font-size:14.6667px;vertical-align:baseline;white-space:pre-wrap" class="">instead of </span><span style="font-size:14.6667px;font-family:"courier new";vertical-align:baseline;white-space:pre-wrap" class="">lldb::ThreadLocal</span></div></li><ol style="margin-top:0pt;margin-bottom:0pt" class=""><li style="list-style-type:lower-roman;font-size:14.6667px;font-family:arial;vertical-align:baseline" class=""><div style="line-height: 1.38; margin-top: 0pt; margin-bottom: 0pt;" class=""><span style="font-size:14.6667px;vertical-align:baseline;white-space:pre-wrap" class="">This fixes a number of bugs on Windows that cannot be fixed otherwise, as they require compiler support.</span></div></li><li style="list-style-type:lower-roman;font-size:14.6667px;font-family:arial;vertical-align:baseline" class=""><div style="line-height: 1.38; margin-top: 0pt; margin-bottom: 0pt;" class=""><span style="font-size:14.6667px;vertical-align:baseline;white-space:pre-wrap" class="">Some other compilers may not support this yet?</span></div></li><li style="list-style-type:lower-roman;font-size:14.6667px;font-family:arial;vertical-align:baseline" class=""><div style="line-height: 1.38; margin-top: 0pt; margin-bottom: 0pt;" class=""><span style="font-size:14.6667px;vertical-align:baseline;white-space:pre-wrap" class="">Risk: 2</span></div></li><li style="list-style-type:lower-roman;font-size:14.6667px;font-family:arial;vertical-align:baseline" class=""><div style="line-height: 1.38; margin-top: 0pt; margin-bottom: 0pt;" class=""><span style="font-size:14.6667px;vertical-align:baseline;white-space:pre-wrap" class="">Impact: 3</span></div></li><li style="list-style-type:lower-roman;font-size:14.6667px;font-family:arial;vertical-align:baseline" class=""><div style="line-height: 1.38; margin-top: 0pt; margin-bottom: 0pt;" class=""><span style="font-size:14.6667px;vertical-align:baseline;white-space:pre-wrap" class="">Difficulty: 3</span></div></li></ol><li style="list-style-type:lower-alpha;font-size:14.6667px;font-family:arial;vertical-align:baseline" class=""><div style="line-height: 1.38; margin-top: 0pt; margin-bottom: 0pt;" class=""><span style="font-size:14.6667px;vertical-align:baseline;white-space:pre-wrap" class="">Use </span><span style="font-size:14.6667px;font-family:"courier new";vertical-align:baseline;white-space:pre-wrap" class="">llvm::cl</span><span style="font-size:14.6667px;vertical-align:baseline;white-space:pre-wrap" class=""> for the command line arguments to the primary lldb executable.</span></div></li><ol style="margin-top:0pt;margin-bottom:0pt" class=""><li style="list-style-type:lower-roman;font-size:14.6667px;font-family:arial;vertical-align:baseline" class=""><div style="line-height: 1.38; margin-top: 0pt; margin-bottom: 0pt;" class=""><span style="font-size:14.6667px;vertical-align:baseline;white-space:pre-wrap" class="">Risk: 2</span></div></li><li style="list-style-type:lower-roman;font-size:14.6667px;font-family:arial;vertical-align:baseline" class=""><div style="line-height: 1.38; margin-top: 0pt; margin-bottom: 0pt;" class=""><span style="font-size:14.6667px;vertical-align:baseline;white-space:pre-wrap" class="">Impact: 3</span></div></li><li style="list-style-type:lower-roman;font-size:14.6667px;font-family:arial;vertical-align:baseline" class=""><div style="line-height: 1.38; margin-top: 0pt; margin-bottom: 0pt;" class=""><span style="font-size:14.6667px;vertical-align:baseline;white-space:pre-wrap" class="">Difficulty / Effort: 4</span></div></li></ol></ol><li style="list-style-type:decimal;font-size:14.6667px;font-family:arial;vertical-align:baseline" class=""><div style="line-height: 1.38; margin-top: 0pt; margin-bottom: 0pt;" class=""><span style="font-size:14.6667px;vertical-align:baseline;white-space:pre-wrap" class="">Testing - Our testing infrastructure is unstable, and our test coverage is lacking.  We should take steps to improve this.</span></div></li><ol style="margin-top:0pt;margin-bottom:0pt" class=""><li style="list-style-type:lower-alpha;font-size:14.6667px;font-family:arial;vertical-align:baseline" class=""><div style="line-height: 1.38; margin-top: 0pt; margin-bottom: 0pt;" class=""><span style="font-size:14.6667px;vertical-align:baseline;white-space:pre-wrap" class="">Port as much as possible to lit</span></div></li><ol style="margin-top:0pt;margin-bottom:0pt" class=""><li style="list-style-type:lower-roman;font-size:14.6667px;font-family:arial;vertical-align:baseline" class=""><div style="line-height: 1.38; margin-top: 0pt; margin-bottom: 0pt;" class=""><span style="font-size:14.6667px;vertical-align:baseline;white-space:pre-wrap" class="">Simple tests should be trivial to port to lit today.  If nothing else this serves as a proof of concept while increasing the speed and stability of the test suite, since lit is a more stable harness.</span></div></li></ol><li style="list-style-type:lower-alpha;font-size:14.6667px;font-family:arial;vertical-align:baseline" class=""><div style="line-height: 1.38; margin-top: 0pt; margin-bottom: 0pt;" class=""><span style="font-size:14.6667px;vertical-align:baseline;white-space:pre-wrap" class="">Separate testing tools</span></div></li><ol style="margin-top:0pt;margin-bottom:0pt" class=""><li style="list-style-type:lower-roman;font-size:14.6667px;font-family:arial;vertical-align:baseline" class=""><div style="line-height: 1.38; margin-top: 0pt; margin-bottom: 0pt;" class=""><span style="font-size:14.6667px;vertical-align:baseline;white-space:pre-wrap" class="">One question that remains open is </span><span style="font-size:14.6667px;font-weight:700;vertical-align:baseline;white-space:pre-wrap" class="">how</span><span style="font-size:14.6667px;vertical-align:baseline;white-space:pre-wrap" class=""> to represent the complicated needs of a debugger in lit tests.  Part a) above covers the trivial cases, but what about the difficult cases?  In </span><a href="https://reviews.llvm.org/D24591" style="text-decoration:none" class=""><span style="font-size:14.6667px;color:rgb(17,85,204);text-decoration:underline;vertical-align:baseline;white-space:pre-wrap" class="">https://reviews.llvm.org/D24591</span></a><span style="font-size:14.6667px;vertical-align:baseline;white-space:pre-wrap" class=""> a number of ideas were discussed.  We started getting to this idea towards the end, about a separate tool which has an interface independent of the command line interface and which can be used to test.  lldb-mi was mentioned.  While I have serious concerns about lldb-mi due to its poorly written and tested codebase, I do agree in principle with the methodology.  In fact, this is the entire philosophy behind lit as used with LLVM, clang, lld, etc.  </span></div></li></ol></ol></ol><br class=""><div style="line-height: 1.38; margin-top: 0pt; margin-bottom: 0pt; margin-left: 108pt;" class=""><span style="font-size:14.6667px;font-family:arial;vertical-align:baseline;white-space:pre-wrap" class="">I don’t take full credit for this idea.  I had been toying with a similar idea for some time, but it was further cemented in an offline discussion with a co-worker.  </span></div><br class=""><div style="line-height: 1.38; margin-top: 0pt; margin-bottom: 0pt; margin-left: 108pt;" class=""><span style="font-size:14.6667px;font-family:arial;vertical-align:baseline;white-space:pre-wrap" class="">There many small, targeted tools in LLVM (e.g. llc, lli, llvm-objdump, etc) whose purpose are to be chained together to do interesting things.  Instead of a command line api as we think of in LLDB where you type commands from an interactive prompt, they have a command line api as you would expect from any tool which is launched from a shell.</span></div><br class=""><div style="line-height: 1.38; margin-top: 0pt; margin-bottom: 0pt; margin-left: 108pt;" class=""><span style="font-size:14.6667px;font-family:arial;vertical-align:baseline;white-space:pre-wrap" class="">I can imagine many potential candidates for lldb tools of this nature.  Off the top of my head:</span></div><ol style="margin-top:0pt;margin-bottom:0pt" class=""><li dir="ltr" style="list-style-type:decimal;font-size:14.6667px;font-family:arial;vertical-align:baseline;margin-left:144px" class=""><div style="line-height: 1.38; margin-top: 0pt; margin-bottom: 0pt;" class=""><span style="font-size:14.6667px;vertical-align:baseline;white-space:pre-wrap" class="">lldb-unwind - A tool for testing the unwinder.  Accepts byte code as input and passes it through to the unwinder, outputting a compressed summary of the steps taken while unwinding, which could be pattern matched in lit.  The output format is entirely controlled by the tool, and not by the unwinder itself, so it would be stable in the face of changes to the underlying unwinder.  Could have various options to enable or disable features of the unwinder in order to force the unwinder into modes that can be tricky to encounter in the wild.</span></div></li><li dir="ltr" style="list-style-type:decimal;font-size:14.6667px;font-family:arial;vertical-align:baseline;margin-left:144px" class=""><div style="line-height: 1.38; margin-top: 0pt; margin-bottom: 0pt;" class=""><span style="font-size:14.6667px;vertical-align:baseline;white-space:pre-wrap" class="">lldb-symbol - A tool for testing symbol resolution.  Could have options for testing things like:</span></div></li><ol style="margin-top:0pt;margin-bottom:0pt" class=""><li dir="ltr" style="list-style-type:lower-alpha;font-size:14.6667px;font-family:arial;vertical-align:baseline;margin-left:144px" class=""><div style="line-height: 1.38; margin-top: 0pt; margin-bottom: 0pt;" class=""><span style="font-size:14.6667px;vertical-align:baseline;white-space:pre-wrap" class="">Determining if a symbol matches an executable</span></div></li><li dir="ltr" style="list-style-type:lower-alpha;font-size:14.6667px;font-family:arial;vertical-align:baseline;margin-left:144px" class=""><div style="line-height: 1.38; margin-top: 0pt; margin-bottom: 0pt;" class=""><span style="font-size:14.6667px;vertical-align:baseline;white-space:pre-wrap" class="">looking up a symbol by name in the debug info, and mapping it to an address in the process.  </span></div></li><li dir="ltr" style="list-style-type:lower-alpha;font-size:14.6667px;font-family:arial;vertical-align:baseline;margin-left:144px" class=""><div style="line-height: 1.38; margin-top: 0pt; margin-bottom: 0pt;" class=""><span style="font-size:14.6667px;vertical-align:baseline;white-space:pre-wrap" class="">Displaying candidate symbols when doing name lookup in a particular scope (e.g. while stopped at a breakpoint).</span></div></li></ol><li dir="ltr" style="list-style-type:decimal;font-size:14.6667px;font-family:arial;vertical-align:baseline;margin-left:144px" class=""><div style="line-height: 1.38; margin-top: 0pt; margin-bottom: 0pt;" class=""><span style="font-size:14.6667px;vertical-align:baseline;white-space:pre-wrap" class="">lldb-breakpoint - A tool for testing breakpoints and stepping.  Various options could include:</span></div></li><ol style="margin-top:0pt;margin-bottom:0pt" class=""><li dir="ltr" style="list-style-type:lower-alpha;font-size:14.6667px;font-family:arial;vertical-align:baseline;margin-left:144px" class=""><div style="line-height: 1.38; margin-top: 0pt; margin-bottom: 0pt;" class=""><span style="font-size:14.6667px;vertical-align:baseline;white-space:pre-wrap" class="">Set breakpoints and out addresses and/or symbol names where they were resolved to.</span></div></li><li dir="ltr" style="list-style-type:lower-alpha;font-size:14.6667px;font-family:arial;vertical-align:baseline;margin-left:144px" class=""><div style="line-height: 1.38; margin-top: 0pt; margin-bottom: 0pt;" class=""><span style="font-size:14.6667px;vertical-align:baseline;white-space:pre-wrap" class="">Trigger commands, so that when a breakpoint is hit the tool could automatically continue and try to run to another breakpoint, etc.</span></div></li><li dir="ltr" style="list-style-type:lower-alpha;font-size:14.6667px;font-family:arial;vertical-align:baseline;margin-left:144px" class=""><div style="line-height: 1.38; margin-top: 0pt; margin-bottom: 0pt;" class=""><span style="font-size:14.6667px;vertical-align:baseline;white-space:pre-wrap" class="">options to inspect certain useful pieces of state about an inferior, to be matched in lit. </span></div></li></ol><li dir="ltr" style="list-style-type:decimal;font-size:14.6667px;font-family:arial;vertical-align:baseline;margin-left:144px" class=""><div style="line-height: 1.38; margin-top: 0pt; margin-bottom: 0pt;" class=""><span style="font-size:14.6667px;vertical-align:baseline;white-space:pre-wrap" class="">lldb-interpreter - tests the jitter etc.  I don’t know much about this, but I don’t see why this couldn’t be tested in a manner similar to how lli is tested.</span></div></li><li dir="ltr" style="list-style-type:decimal;font-size:14.6667px;font-family:arial;vertical-align:baseline;margin-left:144px" class=""><div style="line-height: 1.38; margin-top: 0pt; margin-bottom: 0pt;" class=""><span style="font-size:14.6667px;vertical-align:baseline;white-space:pre-wrap" class="">lldb-platform - tests lldb local and remote platform interfaces.</span></div></li><li dir="ltr" style="list-style-type:decimal;font-size:14.6667px;font-family:arial;vertical-align:baseline;margin-left:144px" class=""><div style="line-height: 1.38; margin-top: 0pt; margin-bottom: 0pt;" class=""><span style="font-size:14.6667px;vertical-align:baseline;white-space:pre-wrap" class="">lldb-cli -- lldb interactive command line.</span></div></li><li dir="ltr" style="list-style-type:decimal;font-size:14.6667px;font-family:arial;vertical-align:baseline;margin-left:144px" class=""><div style="line-height: 1.38; margin-top: 0pt; margin-bottom: 0pt;" class=""><span style="font-size:14.6667px;vertical-align:baseline;white-space:pre-wrap" class="">lldb-format - lldb data formatters etc.</span></div></li></ol><ol style="margin-top:0pt;margin-bottom:0pt" start="3" class=""><li dir="ltr" style="list-style-type:lower-alpha;font-size:14.6667px;font-family:arial;vertical-align:baseline" class=""><div style="line-height: 1.38; margin-top: 0pt; margin-bottom: 0pt;" class=""><span style="font-size:14.6667px;vertical-align:baseline;white-space:pre-wrap" class="">Tests NOW, not later.</span></div></li><ol style="margin-top:0pt;margin-bottom:0pt" class=""><li dir="ltr" style="list-style-type:lower-roman;font-size:14.6667px;font-family:arial;vertical-align:baseline" class=""><div style="line-height: 1.38; margin-top: 0pt; margin-bottom: 0pt;" class=""><span style="font-size:14.6667px;vertical-align:baseline;white-space:pre-wrap" class="">I know we’ve been over this a million times and it’s not worth going over the arguments again.  And I know it’s hard to write tests, often requiring the invention of new SB APIs.  Hopefully those issues will be addressed by above a) and b) above and writing tests will be easier.  Vedant Kumar ran some analytics on the various codebases and found that LLDB has the lowest test / commit ratio of any LLVM project (He didn’t post numbers for lld, so I’m not sure what it is there).</span></div></li><ol style="margin-top:0pt;margin-bottom:0pt" class=""><li dir="ltr" style="list-style-type:decimal;font-size:14.6667px;font-family:arial;vertical-align:baseline" class=""><div style="line-height: 1.38; margin-top: 0pt; margin-bottom: 0pt;" class=""><span style="font-size:13.3333px;color:rgb(33,33,33);vertical-align:baseline;white-space:pre-wrap" class="">lldb: 287 of the past 1000 commits</span></div></li><li dir="ltr" style="list-style-type:decimal;font-size:14.6667px;font-family:arial;vertical-align:baseline" class=""><div style="line-height: 1.38; margin-top: 0pt; margin-bottom: 0pt;" class=""><span style="font-size:13.3333px;color:rgb(33,33,33);vertical-align:baseline;white-space:pre-wrap" class="">llvm: 511 of the past 1000 commits</span></div></li><li dir="ltr" style="list-style-type:decimal;font-size:14.6667px;font-family:arial;vertical-align:baseline" class=""><div style="line-height: 1.38; margin-top: 0pt; margin-bottom: 0pt;" class=""><span style="font-size:13.3333px;color:rgb(33,33,33);vertical-align:baseline;white-space:pre-wrap" class="">clang: 622 of the past 1000 commits</span></div></li><li dir="ltr" style="list-style-type:decimal;font-size:14.6667px;font-family:arial;vertical-align:baseline" class=""><div style="line-height: 1.38; margin-top: 0pt; margin-bottom: 0pt;" class=""><span style="font-size:13.3333px;color:rgb(33,33,33);vertical-align:baseline;white-space:pre-wrap" class="">compiler-rt: 543 of the past 1000 commits</span></div></li></ol></ol></ol><div style="line-height: 1.38; margin-top: 0pt; margin-bottom: 0pt; margin-left: 108pt;" class=""><span style="font-size:14.6667px;font-family:arial;color:rgb(33,33,33);vertical-align:baseline;white-space:pre-wrap" class="">This is an alarming statistic, and I would love to see this number closer to 50%.</span></div></span></div></div></div></blockquote><div><br class=""></div><div>I am definitely not innocent in this regard. However, it does happen for a reason.</div><div><br class=""></div><div>Sometimes, I am writing code in lldb that is the foundation of something I need to do over on the <a href="http://Swift.org" class="">Swift.org</a> side.</div><div><br class=""></div><div>I'll lay out foundational work/groundwork/plumbing code/... on the <a href="http://llvm.org" class="">llvm.org</a> side of the fence, but that code is a no-op there. The real grunt work happens on the Swift support. It's just architecturally sound to have non-Swift-specific bits happen on the <a href="http://llvm.org" class="">llvm.org</a> side. When that happens, I have no reasonable way (in the current model) to test the groundwork - it's just an intricate no-op that doesn't get activated.</div><div><br class=""></div><div>There are tests. They are on a different repo. It's not great, I'll admit. But right now, I would have to design an API around those bits even though I don't need one, or add commands I don't want "just" for testing. That is polluting a valuable user-facing resource with implementation details. I would gladly jump on a testing infrastructure that lets me write tests for this kind of code without extra API/commands.</div><br class=""><blockquote type="cite" class=""><div class=""><div dir="ltr" class=""><div class=""><span id="inbox-inbox-docs-internal-guid-68353e50-4408-e1e7-100e-f9ce9abc13e0" class=""><ol style="margin-top:0pt;margin-bottom:0pt" start="3" class=""><li dir="ltr" style="list-style-type:decimal;font-size:14.6667px;font-family:arial;vertical-align:baseline" class=""><div style="line-height: 1.38; margin-top: 0pt; margin-bottom: 0pt;" class=""><span style="font-size:14.6667px;line-height:20.24px;white-space:pre-wrap" class="">Code style / development conventions - Aside from just the column limitations and bracing styles, there are other areas where LLDB differs from LLVM on code style.  We should continue to adopt more of LLVM's style where it makes sense.  I've identified a couple of areas (incomplete list) which I outline below.</span>  <br class=""></div></li><ol style="margin-top:0pt;margin-bottom:0pt" class=""><li dir="ltr" style="list-style-type:lower-alpha;font-size:14.6667px;font-family:arial;vertical-align:baseline" class=""><div style="line-height: 1.38; margin-top: 0pt; margin-bottom: 0pt;" class=""><span style="font-size:14.6667px;vertical-align:baseline;white-space:pre-wrap" class="">Clean up the mess of cyclical dependencies and properly layer the libraries.  This is especially important for things like lldb-server that need to link in as little as possible, but regardless it leads to a more robust architecture, faster build and link times, better testability, and is required if we ever want to do a modules build of LLDB</span></div></li><li dir="ltr" style="list-style-type:lower-alpha;font-family:arial;vertical-align:baseline" class=""><div style="line-height: 1.38; margin-top: 0pt; margin-bottom: 0pt;" class=""><span style="font-size:14.6667px;vertical-align:baseline;white-space:pre-wrap" class="">Use CMake instead of Xcode project (CMake supports Frameworks).  CMake supports Apple Frameworks, so the main roadblock to getting this working is just someone doing it.  Segmenting the build process by platform doesn't make sense for the upstream, especially when there is a perfectly workable solution.  I have no doubt that the resulting Xcode workspace generated automatically by CMake will <b class="">not </b>be as "nice" as one that is maintained by hand.  We face this problem with Visual </span><span style="font-size:14.6667px;line-height:20.24px;white-space:pre-wrap" class="">Studio on Windows as well.  The solution that most people have adopted is to continue using the IDE for code editing and debugging, but for actually running the build, use CMake with Ninja.  A similar workflow should still be possible with an OSX CMake build, but as I do not work every day on a Mac, all I can say is that it's possible, I have no idea how impactful it would be on peoples' workflows.  </span></div></li></ol></ol></span></div></div></div></blockquote><div><br class=""></div><div>I am very much in the minority on this issue, but +100</div><div>I have no particular allegiance to CMake over Xcode, or vice versa, but I definitely don't see the value in our current multiple build system model.</div><br class=""><blockquote type="cite" class=""><div class=""><div dir="ltr" class=""><div class=""><span id="inbox-inbox-docs-internal-guid-68353e50-4408-e1e7-100e-f9ce9abc13e0" class=""><ol style="margin-top:0pt;margin-bottom:0pt" start="3" class=""><ol style="margin-top:0pt;margin-bottom:0pt" class="" start="3"><li dir="ltr" style="list-style-type:lower-alpha;font-size:14.6667px;font-family:arial;vertical-align:baseline" class=""><div style="line-height: 1.38; margin-top: 0pt; margin-bottom: 0pt;" class=""><span style="font-size:14.6667px;vertical-align:baseline;white-space:pre-wrap" class="">Variable naming conventions</span></div></li><ol style="margin-top:0pt;margin-bottom:0pt" class=""><li dir="ltr" style="list-style-type:lower-roman;font-size:14.6667px;font-family:arial;vertical-align:baseline" class=""><div style="line-height: 1.38; margin-top: 0pt; margin-bottom: 0pt;" class=""><span style="font-size:14.6667px;vertical-align:baseline;white-space:pre-wrap" class="">I don’t expect anyone is too fond of LLDB’s naming conventions, but if we’re committed to joining the LLVM ecosystem, then let’s go all the way.</span></div></li></ol><li dir="ltr" style="list-style-type:lower-alpha;font-size:14.6667px;font-family:arial;vertical-align:baseline" class=""><div style="line-height: 1.38; margin-top: 0pt; margin-bottom: 0pt;" class=""><span style="font-size:14.6667px;vertical-align:baseline;white-space:pre-wrap" class="">Use more modern C++ and less C</span></div></li><ol style="margin-top:0pt;margin-bottom:0pt" class=""><li dir="ltr" style="list-style-type:lower-roman;font-size:14.6667px;font-family:arial;vertical-align:baseline" class=""><div style="line-height: 1.38; margin-top: 0pt; margin-bottom: 0pt;" class=""><span style="font-size:14.6667px;vertical-align:baseline;white-space:pre-wrap" class="">Old habits die hard, but this isn’t just a matter of style.  It leads to safer, more robust, and less fragile code as well.</span></div></li></ol><li dir="ltr" style="list-style-type:lower-alpha;font-size:14.6667px;font-family:arial;vertical-align:baseline" class=""><div style="line-height: 1.38; margin-top: 0pt; margin-bottom: 0pt;" class=""><span style="font-size:14.6667px;vertical-align:baseline;white-space:pre-wrap" class="">Shorter functions and classes with more narrowly targeted responsibilities</span></div></li><ol style="margin-top:0pt;margin-bottom:0pt" class=""><li dir="ltr" style="list-style-type:lower-roman;font-size:14.6667px;font-family:arial;vertical-align:baseline" class=""><div style="line-height: 1.38; margin-top: 0pt; margin-bottom: 0pt;" class=""><span style="font-size:14.6667px;vertical-align:baseline;white-space:pre-wrap" class="">It’s not uncommon to find functions that are hundreds (and in a few cases even 1,000+) of lines long.  We really need to be better about breaking functions and classes down into smaller responsibilities.  This helps not just for someone coming in to read the function, but also for testing.  Smaller functions are easier to unit test.</span></div></li></ol><li dir="ltr" style="list-style-type:lower-alpha;font-size:14.6667px;font-family:arial;vertical-align:baseline" class=""><div style="line-height: 1.38; margin-top: 0pt; margin-bottom: 0pt;" class=""><span style="font-size:14.6667px;vertical-align:baseline;white-space:pre-wrap" class="">Convert </span><span style="font-size:14.6667px;font-family:"courier new";vertical-align:baseline;white-space:pre-wrap" class="">T foo(X, Y, Error &error)</span><span style="font-size:14.6667px;vertical-align:baseline;white-space:pre-wrap" class=""> functions to </span><span style="font-size:14.6667px;font-family:"courier new";vertical-align:baseline;white-space:pre-wrap" class="">Expected<T> foo(X, Y)</span><span style="font-size:14.6667px;vertical-align:baseline;white-space:pre-wrap" class=""> style (Depends on 1.c)</span></div></li><ol style="margin-top:0pt;margin-bottom:0pt" class=""><li dir="ltr" style="list-style-type:lower-roman;font-size:14.6667px;font-family:arial;vertical-align:baseline" class=""><div style="line-height: 1.38; margin-top: 0pt; margin-bottom: 0pt;" class=""><span style="font-size:14.6667px;font-family:"courier new";vertical-align:baseline;white-space:pre-wrap" class="">llvm::Expected</span><span style="font-size:14.6667px;vertical-align:baseline;white-space:pre-wrap" class=""> is based on the </span><span style="font-size:14.6667px;font-family:"courier new";vertical-align:baseline;white-space:pre-wrap" class="">llvm::Error </span><span style="font-size:14.6667px;vertical-align:baseline;white-space:pre-wrap" class="">class described earlier.  It’s used when a function is supposed to return a value, but it could fail.  By packaging the error with the return value, it’s impossible to have a situation where you use the return value even in case of an error, and because </span><span style="font-size:14.6667px;font-family:"courier new";vertical-align:baseline;white-space:pre-wrap" class="">llvm::Error </span><span style="font-size:14.6667px;vertical-align:baseline;white-space:pre-wrap" class="">has mandatory checking, it’s also impossible to have a sitaution where you don’t check the error.  So it’s very safe.  </span></div></li></ol></ol></ol><div class=""><font face="arial" class=""><span style="font-size:14.6667px;line-height:20.24px;white-space:pre-wrap" class=""><br class=""></span></font></div><div class=""><font face="arial" class=""><span style="font-size:14.6667px;line-height:20.24px;white-space:pre-wrap" class="">Whew.  That was a lot.  If you made it this far, thanks for reading!</span></font></div><div class=""><font face="arial" class=""><span style="font-size:14.6667px;line-height:20.24px;white-space:pre-wrap" class=""><br class=""></span></font></div><div class=""><span style="line-height:20.24px;white-space:pre-wrap" class="">Obviously if we were to </span><span style="line-height:20.24px;white-space:pre-wrap" class="">embark on all of the above, it would take many months to complete everything.  So I'm not proposing anyone stop what they're doing to work on this.  This is just my own personal wishlist</span></div></span></div></div>
_______________________________________________<br class="">lldb-dev mailing list<br class=""><a href="mailto:lldb-dev@lists.llvm.org" class="">lldb-dev@lists.llvm.org</a><br class="">http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-dev<br class=""></div></blockquote></div><br class=""><div class="">
<div class="" style="color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><br class="Apple-interchange-newline">Thanks,</div><div class="" style="color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><i class="">- Enrico</i><br class="">📩 egranata@<font color="#ff2600" class=""></font>.com ☎️ 27683</div>
</div>
<br class=""></body></html>