<html><head></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; "><br><div><div>On May 8, 2012, at 3:52 AM, Gordon Keiser wrote:</div><br class="Apple-interchange-newline"><blockquote type="cite"><span class="Apple-style-span" style="border-collapse: separate; font-family: Helvetica; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: 2; text-align: -webkit-auto; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-border-horizontal-spacing: 0px; -webkit-border-vertical-spacing: 0px; -webkit-text-decorations-in-effect: none; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; font-size: medium; "><div lang="EN-US" link="blue" vlink="purple"><div class="WordSection1" style="page: WordSection1; "><div style="margin-top: 0in; margin-right: 0in; margin-left: 0in; margin-bottom: 0.0001pt; font-size: 12pt; font-family: 'Times New Roman', serif; "><span style="font-size: 11pt; font-family: Calibri, sans-serif; color: rgb(31, 73, 125); ">FWIW, I'd be interested in working on the Windows implementation.   I've been knee-deep in *nixes lately and wouldn't mind the refresher.  <span class="Apple-converted-space"> </span></span><span style="font-size: 11pt; font-family: Wingdings; color: rgb(31, 73, 125); ">J</span></div></div></div></span></blockquote><div>Cool!   </div><div><br></div><div>Does my proposed interface make sense to implement on top of Windows APIs?  </div><div><br></div><div>-Nick</div><div><br></div><div><br></div><blockquote type="cite"><span class="Apple-style-span" style="border-collapse: separate; font-family: Helvetica; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: 2; text-align: -webkit-auto; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-border-horizontal-spacing: 0px; -webkit-border-vertical-spacing: 0px; -webkit-text-decorations-in-effect: none; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; font-size: medium; "><div lang="EN-US" link="blue" vlink="purple"><div class="WordSection1" style="page: WordSection1; "><div style="margin-top: 0in; margin-right: 0in; margin-left: 0in; margin-bottom: 0.0001pt; font-size: 12pt; font-family: 'Times New Roman', serif; "><a name="_MailEndCompose"><span style="font-size: 11pt; font-family: Calibri, sans-serif; color: rgb(31, 73, 125); "><o:p> </o:p></span></a></div><div style="border-top-style: none; border-right-style: none; border-bottom-style: none; border-width: initial; border-color: initial; border-left-style: solid; border-left-color: blue; border-left-width: 1.5pt; padding-top: 0in; padding-right: 0in; padding-bottom: 0in; padding-left: 4pt; "><div><div style="border-right-style: none; border-bottom-style: none; border-left-style: none; border-width: initial; border-color: initial; border-top-style: solid; border-top-color: rgb(181, 196, 223); border-top-width: 1pt; padding-top: 3pt; padding-right: 0in; padding-bottom: 0in; padding-left: 0in; "><div style="margin-top: 0in; margin-right: 0in; margin-left: 0in; margin-bottom: 0.0001pt; font-size: 12pt; font-family: 'Times New Roman', serif; "><b><span style="font-size: 10pt; font-family: Tahoma, sans-serif; ">From:</span></b><span style="font-size: 10pt; font-family: Tahoma, sans-serif; "><span class="Apple-converted-space"> </span><a href="mailto:llvmdev-bounces@cs.uiuc.edu" style="color: blue; text-decoration: underline; ">llvmdev-bounces@cs.uiuc.edu</a><span class="Apple-converted-space"> </span>[mailto:llvmdev-bounces@cs.uiuc.edu]<span class="Apple-converted-space"> </span><b>On Behalf Of<span class="Apple-converted-space"> </span></b>Nick Kledzik<br><b>Sent:</b><span class="Apple-converted-space"> </span>Monday, May 07, 2012 3:57 PM<br><b>To:</b><span class="Apple-converted-space"> </span>LLVM Developers Mailing List<br><b>Subject:</b><span class="Apple-converted-space"> </span>[LLVMdev] [RFC] llvm/include/Support/OutputBuffer.h<o:p></o:p></span></div></div></div><div style="margin-top: 0in; margin-right: 0in; margin-left: 0in; margin-bottom: 0.0001pt; font-size: 12pt; font-family: 'Times New Roman', serif; "><o:p> </o:p></div><div><div style="margin-top: 0in; margin-right: 0in; margin-left: 0in; margin-bottom: 0.0001pt; font-size: 12pt; font-family: 'Times New Roman', serif; ">For the reasons listed in my 03-May-2012 email, I am proposing a new llvm/Support class for using in writing binary files:<o:p></o:p></div></div><div><div style="margin-top: 0in; margin-right: 0in; margin-left: 0in; margin-bottom: 0.0001pt; font-size: 12pt; font-family: 'Times New Roman', serif; "><o:p> </o:p></div></div><div style="margin-top: 0in; margin-right: 0in; margin-left: 0in; margin-bottom: 0.0001pt; font-size: 12pt; font-family: 'Times New Roman', serif; "><span style="font-size: 7.5pt; font-family: Monaco, serif; ">/// OutputBuffer - This interface provides simple way to create an in-memory<br>/// buffer which when done will be written to a file. During the lifetime of <br>/// </span><span class="apple-style-span"><span style="font-size: 10pt; font-family: Monaco, serif; ">these</span></span>  <span style="font-size: 7.5pt; font-family: Monaco, serif; ">objects, the content or existence of the specified file is undefined. <br>/// That is, creating an OutputBuffer for a file may immediately remove the <br>/// file.<br>/// If the OutputBuffer is committed, the target file's content will become <br>/// the buffer content at the time of the commit.  If the OutputBuffer is not <br>/// committed, the file will be deleted in the OutputBuffer buffer destructor.<br>class OutputBuffer {<br>public:<br>  enum Flags {<br>    F_executable = 1, /// set the 'x' bit on the resulting file<br>  }; <br><br>  /// Factory method to create an OutputBuffer object which manages a read/write<br>  /// buffer of the specified size. When committed, the buffer will be written<br>  /// to the file at the specified path.  <br>  static error_code createFile(StringRef filePath, Flags flags, size_t size, <br>                               OwningPtr<OutputBuffer> &result);<br>  <br><br>  /// Returns a pointer to the start of the buffer.<br>  uint8_t *bufferStart();<br>  <br>  /// Returns a pointer to the end of the buffer.<br>  uint8_t *bufferEnd();<br>  <br>  /// Returns size of the buffer.<br>  size_t size();<br>    <br>  /// Flushes the content of the buffer to its file and deallocates the <br>  /// buffer.  If commit() is not called before this object's destructor<br>  /// is called, the file is deleted in the destructor. The optional parameter<br>  /// is used if it turns out you want the file size to be smaller than<br>  /// initially requested.<br>  void commit(int64_t newSmallerSize = -1);<br>};</span><o:p></o:p></div><div><div style="margin-top: 0in; margin-right: 0in; margin-left: 0in; margin-bottom: 0.0001pt; font-size: 12pt; font-family: 'Times New Roman', serif; "><o:p> </o:p></div></div><div><div style="margin-top: 0in; margin-right: 0in; margin-left: 0in; margin-bottom: 0.0001pt; font-size: 12pt; font-family: 'Times New Roman', serif; "><o:p> </o:p></div></div><div><div style="margin-top: 0in; margin-right: 0in; margin-left: 0in; margin-bottom: 0.0001pt; font-size: 12pt; font-family: 'Times New Roman', serif; ">The Flags will probable need to be extended over time to handle other clients needs.<o:p></o:p></div></div><div><div style="margin-top: 0in; margin-right: 0in; margin-left: 0in; margin-bottom: 0.0001pt; font-size: 12pt; font-family: 'Times New Roman', serif; "><o:p> </o:p></div></div><div><div style="margin-top: 0in; margin-right: 0in; margin-left: 0in; margin-bottom: 0.0001pt; font-size: 12pt; font-family: 'Times New Roman', serif; ">For Unix/Darwin, my plan is to implement this by:<o:p></o:p></div></div><div><div style="margin-top: 0in; margin-right: 0in; margin-left: 0in; margin-bottom: 0.0001pt; font-size: 12pt; font-family: 'Times New Roman', serif; ">1) delete the file<o:p></o:p></div></div><div><div style="margin-top: 0in; margin-right: 0in; margin-left: 0in; margin-bottom: 0.0001pt; font-size: 12pt; font-family: 'Times New Roman', serif; ">2) create a new file with a random name in same directory<o:p></o:p></div></div><div><div style="margin-top: 0in; margin-right: 0in; margin-left: 0in; margin-bottom: 0.0001pt; font-size: 12pt; font-family: 'Times New Roman', serif; ">3) truncate the file to the new size<o:p></o:p></div></div><div><div style="margin-top: 0in; margin-right: 0in; margin-left: 0in; margin-bottom: 0.0001pt; font-size: 12pt; font-family: 'Times New Roman', serif; ">4) mmap() in the file r/w<o:p></o:p></div></div><div><div style="margin-top: 0in; margin-right: 0in; margin-left: 0in; margin-bottom: 0.0001pt; font-size: 12pt; font-family: 'Times New Roman', serif; ">5) On commit, unmap the file, rename() to final name<o:p></o:p></div></div><div><div style="margin-top: 0in; margin-right: 0in; margin-left: 0in; margin-bottom: 0.0001pt; font-size: 12pt; font-family: 'Times New Roman', serif; ">6) In destructor, if not committed, unmap, delete the randomly named file<o:p></o:p></div></div><div><div style="margin-top: 0in; margin-right: 0in; margin-left: 0in; margin-bottom: 0.0001pt; font-size: 12pt; font-family: 'Times New Roman', serif; "> <o:p></o:p></div></div><div><div style="margin-top: 0in; margin-right: 0in; margin-left: 0in; margin-bottom: 0.0001pt; font-size: 12pt; font-family: 'Times New Roman', serif; ">I'll leave the windows implementation empty and let someone with windows experience do the implementation.<o:p></o:p></div></div><div><div style="margin-top: 0in; margin-right: 0in; margin-left: 0in; margin-bottom: 0.0001pt; font-size: 12pt; font-family: 'Times New Roman', serif; "><o:p> </o:p></div></div><div><div style="margin-top: 0in; margin-right: 0in; margin-left: 0in; margin-bottom: 0.0001pt; font-size: 12pt; font-family: 'Times New Roman', serif; ">Comments? Suggestions?<o:p></o:p></div></div><div><div style="margin-top: 0in; margin-right: 0in; margin-left: 0in; margin-bottom: 0.0001pt; font-size: 12pt; font-family: 'Times New Roman', serif; "><o:p> </o:p></div></div><div><div style="margin-top: 0in; margin-right: 0in; margin-left: 0in; margin-bottom: 0.0001pt; font-size: 12pt; font-family: 'Times New Roman', serif; ">-Nick<o:p></o:p></div></div><div><div style="margin-top: 0in; margin-right: 0in; margin-left: 0in; margin-bottom: 0.0001pt; font-size: 12pt; font-family: 'Times New Roman', serif; "><o:p> </o:p></div></div><div><div style="margin-top: 0in; margin-right: 0in; margin-left: 0in; margin-bottom: 0.0001pt; font-size: 12pt; font-family: 'Times New Roman', serif; "><o:p> </o:p></div><div><blockquote style="margin-top: 5pt; margin-bottom: 5pt; "><div><div style="margin-top: 0in; margin-right: 0in; margin-left: 0in; margin-bottom: 0.0001pt; font-size: 12pt; font-family: 'Times New Roman', serif; ">On May 3, 2012, at 6:10 PM, Nick Kledzik wrote:<o:p></o:p></div></div></blockquote></div><blockquote style="margin-top: 5pt; margin-bottom: 5pt; "><div><div style="margin-top: 0in; margin-right: 0in; margin-left: 0in; margin-bottom: 0.0001pt; font-size: 12pt; font-family: 'Times New Roman', serif; ">Existing llvm code tends to use raw_ostream for writing files.  But raw_ostream is not a good match for a linker for a couple of reasons:<br><br>1) When the linker creates an executable, the file needs the 'x' bit set.  Currently raw_fd_ostream has no way to set that.<br><br>2) The Unix conformance suite actually has some test cases where the linker is run and the output file does exists but is not writable, or is not writable but is in a writable directory, or with funky umask values.   raw_fd_ostream interface has no way to match those semantics.<br><br>3) On darwin we have found the linker performs better if it opens the output file, truncates it to the output size, then mmaps in the file, then writes directly into that memory buffer.  This avoids the memory copy from the private buffer to the OS file system buffer in the write() syscall.<br><br>4) In the model we are using for lld, a streaming output interface is not optimal.   Currently, lld copies chunks of code from the (read-only) input files, to a temporary buffer, then applies any fixups (relocations), then streams out that temporary buffer.  If instead we had a big output buffer, the linker could copy the code chunks directly to the output buffer and apply the fixups there, avoiding an extra copy. <o:p></o:p></div></div><div style="margin-top: 0in; margin-right: 0in; margin-left: 0in; margin-bottom: 0.0001pt; font-size: 12pt; font-family: 'Times New Roman', serif; "><o:p> </o:p></div></blockquote></div></div></div></div></span></blockquote></div><br></body></html>