[llvm-commits] [llvm] r75156 - in /llvm/trunk: include/llvm/CodeGen/AsmStream.h lib/CodeGen/AsmStream.cpp

Chris Lattner clattner at apple.com
Thu Jul 9 11:33:02 PDT 2009


On Jul 9, 2009, at 11:27 AM, David Greene wrote:
> Author: greened
> Date: Thu Jul  9 13:27:23 2009
> New Revision: 75156
>
> URL: http://llvm.org/viewvc/llvm-project?rev=75156&view=rev
> Log:
>
> Add some classes to produce pretty-printed asm.  We'll use these
> shortly to provide nicely printed comments and other goodies in
> asm files.

Hi David,

This looks interesting, but we're actively moving away from  
std::ostream and related gunk.  This is a step backward in that respect.

-Chris

>
> Added:
>    llvm/trunk/include/llvm/CodeGen/AsmStream.h
>    llvm/trunk/lib/CodeGen/AsmStream.cpp
>
> Added: llvm/trunk/include/llvm/CodeGen/AsmStream.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/AsmStream.h?rev=75156&view=auto
>
> = 
> = 
> = 
> = 
> = 
> = 
> = 
> = 
> ======================================================================
> --- llvm/trunk/include/llvm/CodeGen/AsmStream.h (added)
> +++ llvm/trunk/include/llvm/CodeGen/AsmStream.h Thu Jul  9 13:27:23  
> 2009
> @@ -0,0 +1,442 @@
> +//===-- llvm/CodeGen/AsmStream.h - AsmStream Framework --------*- C+ 
> + -*-===//
> +//
> +//                     The LLVM Compiler Infrastructure
> +//
> +// This file was developed by the LLVM research group and is  
> distributed under
> +// the University of Illinois Open Source License. See LICENSE.TXT  
> for details.
> +//
> +// 
> = 
> = 
> = 
> ----------------------------------------------------------------------= 
> ==//
> +//
> +// This file contains streambuf and ostream implementations for ASM  
> printers
> +// to do things like pretty-print comments.
> +//
> +// 
> = 
> = 
> = 
> ----------------------------------------------------------------------= 
> ==//
> +
> +#ifndef LLVM_CODEGEN_ASMSTREAM_H
> +#define LLVM_CODEGEN_ASMSTREAM_H
> +
> +#include "llvm/Target/TargetAsmInfo.h"
> +
> +#include <streambuf>
> +#include <iomanip>
> +#include <iterator>
> +#include <llvm/Support/Streams.h>
> +
> +#include <sys/types.h>
> +#include <sys/stat.h>
> +#include <fcntl.h>
> +#include <unistd.h>
> +
> +namespace llvm
> +{
> +  /// BasicAsmStreambuf - A stream buffer to count columns and allow
> +  /// placement of output at specific columns.
> +  ///
> +  /// TODO: This only works on POSIX systems for now
> +  template<typename charT, typename Traits =  
> std::char_traits<charT> >
> +  class BasicAsmStreambuf
> +      : public std::basic_streambuf<charT, Traits> {
> +  private:
> +    static const int bufferSize = 10;
> +    charT buffer_array[bufferSize];
> +    int column;
> +    int fd;
> +
> +    bool formatted;
> +
> +    typedef typename std::basic_streambuf<charT, Traits>::int_type  
> int_type;
> +
> +  protected:
> +    void setFD(int f) {
> +      fd = f;
> +    }
> +
> +    int getFD(void) const {
> +      return(fd);
> +    }
> +
> +    bool FDSet(void) const {
> +      return(getFD() != -1);
> +    }
> +
> +  public:
> +    BasicAsmStreambuf(void)
> +        : std::basic_streambuf<charT, Traits>(), column(0), fd(-1),
> +            formatted(true) {
> +      // Assure we have room for one character when overflow is  
> called
> +      setp(buffer_array, buffer_array+(bufferSize-1));
> +    }
> +
> +    explicit BasicAsmStreambuf(int f)
> +        : std::basic_streambuf<charT, Traits>(), column(0), fd(f),
> +            formatted(true) {
> +      // Assure we have room for one character when overflow is  
> called
> +      setp(buffer_array, buffer_array+(bufferSize-1));
> +    }
> +
> +    virtual ~BasicAsmStreambuf(void) {
> +      sync();
> +    }
> +
> +    void setColumn(int newcol, int minpad = 0) {
> +      if (formatted) {
> +        // Flush the current buffer to get the most recent column
> +        if (Traits::eq_int_type(flushBuffer(), Traits::eof())) {
> +          // Error
> +          assert(0 && "Corrupted output buffer");
> +        }
> +
> +        // Output spaces until we reach the desired column
> +        int num = newcol - column;
> +        if (num <= 0) {
> +          num = minpad;
> +        }
> +
> +        // TODO: Use sputn
> +        while (num-- > 0) {
> +          if (Traits::eq_int_type(this->sputc(' '), Traits::eof())) {
> +            assert(0 && "Corrupted output buffer");
> +          }
> +        }
> +      }
> +    };
> +
> +  protected:
> +    void setFormatting(bool v) {
> +      formatted = v;
> +    }
> +
> +    int flushBuffer(void) {
> +      if (FDSet()) {
> +        if (formatted) {
> +          // Keep track of the current column by scanning the  
> string for
> +          // special characters
> +
> +          // Find the last newline.  This is our column start.  If  
> there
> +          // is no newline, start with the current column.
> +          charT *nlpos = NULL;
> +          for (charT *pos = this->pptr(), *epos = this->pbase();  
> pos > epos; --pos) {
> +            if (Traits::eq(*(pos-1), '\n')) {
> +              nlpos = pos-1;
> +              // The newline will be counted, setting this to zero.
> +              // We need to do it this way in case nlpos is pptr(),
> +              // which is one after epptr() after overflow is called.
> +              column = -1;
> +              break;
> +            }
> +          }
> +
> +          if (nlpos == NULL) {
> +            nlpos = this->pbase();
> +          }
> +
> +          // Walk through looking for tabs and advance column as  
> appropriate
> +          for (charT *pos = nlpos, *epos = this->pptr(); pos !=  
> epos; ++pos) {
> +            ++column;
> +            if (Traits::eq(*pos, '\t')) {
> +              // Advance to next tab stop (every eight characters)
> +              column += ((8 - (column & 0x7)) & 0x7);
> +              assert(!(column & 0x3) && "Column out of alignment");
> +            }
> +          }
> +        }
> +
> +        // Write out the buffer
> +        int num = this->pptr() - this->pbase();
> +
> +        if (write(fd, buffer_array, num) != num) {
> +          return(Traits::eof());
> +        }
> +        this->pbump(-num);
> +        return(num);
> +      }
> +      return(0);
> +    }
> +
> +    // Buffer full, so write c and all buffered characters
> +    virtual int_type overflow(int_type c) {
> +      if (!Traits::eq_int_type(c, Traits::eof())) {
> +        *this->pptr() = c;
> +        this->pbump(1);
> +        //++column;
> +        if (Traits::eq_int_type(flushBuffer(), Traits::eof())) {
> +          // Error
> +          return Traits::eof();
> +        }
> +
> +        return Traits::not_eof(c);
> +      }
> +      return Traits::eof();
> +    }
> +
> +    // Write multiple characters (TODO)
> +    //    virtual std::streamsize xsputn(const char *s,
> +    //                             std::streamsize num) {
> +    //}
> +
> +    // Flush data in the buffer
> +    virtual int sync(void) {
> +      if (Traits::eq_int_type(flushBuffer(),Traits::eof())) {
> +        // Error
> +        return -1;
> +      }
> +      return 0;
> +    }
> +  };
> +
> +  typedef BasicAsmStreambuf<char> AsmStreambuf;
> +  typedef BasicAsmStreambuf<wchar_t> AsmWStreambuf;
> +
> +  /// BasicAsmFilebuf - An AsmStreambuf to write to files
> +  ///
> +  template<typename charT, typename Traits =  
> std::char_traits<charT> >
> +  class BasicAsmFilebuf
> +      : public BasicAsmStreambuf<charT, Traits> {
> +  public:
> +    BasicAsmFilebuf(void)
> +        : BasicAsmStreambuf<charT, Traits>() {}
> +    BasicAsmFilebuf(const std::basic_string<charT, Traits> &name,
> +                    std::ios_base::openmode mode)
> +        : BasicAsmStreambuf<charT, Traits>() {
> +      open(name.c_str(), mode);
> +    }
> +
> +    ~BasicAsmFilebuf(void) {
> +      close();
> +    }
> +
> +    BasicAsmFilebuf *open(const charT *name,  
> std::ios_base::openmode mode) {
> +      int flags = 0;
> +      if (mode & std::ios_base::in) {
> +        flags |= O_RDONLY;
> +      }
> +      if (mode & std::ios_base::out) {
> +        if (mode & std::ios_base::in) {
> +          flags |= O_RDWR;
> +        }
> +        else {
> +          flags |= O_WRONLY;
> +        }
> +        flags |= O_CREAT;
> +      }
> +      if (mode & std::ios_base::trunc) {
> +        flags |= O_TRUNC;
> +      }
> +      if (mode & std::ios_base::app) {
> +        flags |= O_APPEND;
> +      }
> +
> +      if (mode & std::ios_base::binary) {
> +        this->setFormatting(false);
> +      }
> +      else {
> +        this->setFormatting(true);
> +      }
> +
> +      int fd = ::open(name, flags, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP| 
> S_IROTH|S_IWOTH);
> +      assert(fd != -1 && "Cannot open output file");
> +
> +      this->setFD(fd);
> +
> +      return(this);
> +    }
> +
> +    BasicAsmFilebuf *close(void) {
> +      if (is_open()) {
> +        int result = ::close(this->getFD());
> +        assert(result != -1 && "Could not close output file");
> +        this->setFD(-1);
> +      }
> +
> +      return(this);
> +    }
> +
> +    bool is_open(void) const {
> +      return(this->getFD() != -1);
> +    }
> +  };
> +
> +  typedef BasicAsmFilebuf<char> AsmFilebuf;
> +  typedef BasicAsmFilebuf<wchar_t> AsmWFilebuf;
> +
> +  /// BasicAsmOStream - std::ostream equivalent for BasicAsmStreambuf
> +  ///
> +  template<typename charT, typename Traits =  
> std::char_traits<charT> >
> +  class BasicAsmOStream
> +      : public std::basic_ostream<charT, Traits> {
> +  protected:
> +    typedef BasicAsmStreambuf<charT, Traits> streambuf;
> +    streambuf *bufptr;
> +
> +  public:
> +    explicit BasicAsmOStream(streambuf *b)
> +        : std::basic_ostream<charT, Traits>(b), bufptr(b) {
> +      assert(b && "Invalid streambuf in OStream constructor");
> +      assert(this->rdbuf()
> +             && "Invalid basic_ostream buf in OStream constructor");
> +    }
> +
> +    streambuf *buffer(void) {
> +      assert(bufptr && "Invalid streambuf in buffer");
> +      assert(this->rdbuf()
> +             && "Invalid basic_ostream buf in rdbuf");
> +      return(bufptr);
> +    }
> +  };
> +
> +  typedef BasicAsmOStream<char> AsmOStream;
> +  typedef BasicAsmOStream<wchar_t> AsmWOStream;
> +
> +  /// BasicAsmOFStream - std::ofstream equivalent for BasicAsmFilebuf
> +  ///
> +  template<typename charT, typename Traits =  
> std::char_traits<charT> >
> +  class BasicAsmOFStream
> +      : public BasicAsmOStream<charT, Traits> {
> +  protected:
> +    BasicAsmFilebuf<charT, Traits> buf;
> +
> +  public:
> +    BasicAsmOFStream(void) : BasicAsmOStream<charT, Traits>(&buf) {}
> +    explicit BasicAsmOFStream(const std::basic_string<charT,  
> Traits> &name)
> +        : BasicAsmOStream<charT, Traits>(&buf),
> +            buf(name, std::ios_base::out | std::ios_base::trunc) {
> +      assert(this->buffer() && "Invalid streambuf in OFStream  
> constructor");
> +      assert(this->rdbuf()
> +             && "Invalid basic_ostream buf in OFStream constructor");
> +    }
> +
> +    explicit BasicAsmOFStream(const std::basic_string<charT,  
> Traits> &name,
> +                              std::ios_base::openmode mode)
> +        : BasicAsmOStream<charT, Traits>(&buf),
> +            buf(name, mode) {
> +      assert(this->buffer() && "Invalid streambuf in OFStream  
> constructor");
> +      assert(this->rdbuf()
> +             && "Invalid basic_ostream buf in OFStream constructor");
> +    }
> +
> +    ~BasicAsmOFStream(void) {
> +      close();
> +    }
> +
> +    bool open(const std::basic_string<charT, Traits> &name) {
> +      assert(this->buffer() && "Invalid streambuf in open1");
> +      assert(this->rdbuf()
> +             && "Invalid basic_ostream buf in open1");
> +
> +      buf.open(name.c_str(), std::ios_base::out |  
> std::ios_base::trunc);
> +
> +      assert(this->buffer() && "Invalid streambuf in open2");
> +      assert(this->rdbuf()
> +             && "Invalid basic_ostream buf in open2");
> +
> +      assert(this->good() && "Not good");
> +      assert((bool)(*this) && "Not true");
> +
> +      return(true);
> +    }
> +
> +    bool close(void) {
> +      buf.close();
> +      return(true);
> +    }
> +
> +    bool is_open(void) const {
> +      return(buf.is_open());
> +    }
> +  };
> +
> +  typedef BasicAsmOFStream<char> AsmOFStream;
> +  typedef BasicAsmOFStream<wchar_t> AsmWOFStream;
> +
> +  /// Column - An I/O manipulator to advance the output to a  
> certain column
> +  ///
> +  class Column {
> +  private:
> +    int column;
> +
> +  public:
> +    explicit Column(int c)
> +        : column(c) {}
> +
> +    template<typename OStream>
> +    OStream &operator()(OStream &out) const {
> +      // Make at least one space before the comment
> +      out.buffer()->setColumn(column, 1);
> +      return(out);
> +    }
> +  };
> +
> +  template<typename OStream>
> +  OStream &operator<<(OStream &out, const Column &column)
> +  {
> +    return(column(out));
> +  }
> +
> +  /// Comment - An I/O manipulator to output an end-of-line comment
> +  ///
> +  class Comment
> +      : public Column {
> +  private:
> +    static const int CommentColumn = 60;
> +    std::string text;
> +    const TargetAsmInfo &TAI;
> +
> +  public:
> +    Comment(const std::string &comment,
> +            const TargetAsmInfo &tai)
> +        : Column(CommentColumn), text(comment), TAI(tai) {}
> +
> +    template<typename OStream>
> +    OStream &operator()(OStream &out) const {
> +      Column::operator()(out);
> +      out << TAI.getCommentString() << " " << text;
> +      return(out);
> +    }
> +  };
> +
> +  template<typename OStream>
> +  OStream &operator<<(OStream &out, const Comment &comment)
> +  {
> +    return(comment(out));
> +  }
> +
> +  /// raw_asm_ostream - A raw_ostream that writes to an AsmOStream
> +  /// This exposes additional AsmOStream capability.
> +  class raw_asm_ostream : public raw_ostream {
> +    AsmOStream &OS;
> +  public:
> +    raw_asm_ostream(AsmOStream &O) : OS(O) {}
> +    ~raw_asm_ostream();
> +
> +    AsmOStream &getStream(void) {
> +      flush();
> +      return OS;
> +    }
> +
> +    raw_asm_ostream &operator<<(const Column &column) {
> +      flush();
> +      OS << column;
> +      return *this;
> +    }
> +
> +    raw_asm_ostream &operator<<(const Comment &comment) {
> +      flush();
> +      OS << comment;
> +      return *this;
> +    }
> +
> +    /// flush_impl - The is the piece of the class that is  
> implemented by
> +    /// subclasses.  This outputs the currently buffered data and  
> resets the
> +    /// buffer to empty.
> +    virtual void flush_impl();
> +  };
> +
> +  /// WARNING: Do NOT use these streams in the constructors of global
> +  /// objects.  There is no mechanism to ensure they are initialized
> +  /// before other global objects.
> +  ///
> +  extern raw_asm_ostream asmout;
> +  extern raw_asm_ostream asmerr;
> +}
> +
> +#endif
>
> Added: llvm/trunk/lib/CodeGen/AsmStream.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmStream.cpp?rev=75156&view=auto
>
> = 
> = 
> = 
> = 
> = 
> = 
> = 
> = 
> ======================================================================
> --- llvm/trunk/lib/CodeGen/AsmStream.cpp (added)
> +++ llvm/trunk/lib/CodeGen/AsmStream.cpp Thu Jul  9 13:27:23 2009
> @@ -0,0 +1,47 @@
> +//===-- llvm/CodeGen/AsmStream.cpp - AsmStream Framework --------*-  
> C++ -*-===//
> +//
> +//                     The LLVM Compiler Infrastructure
> +//
> +// This file was developed by the LLVM research group and is  
> distributed under
> +// the University of Illinois Open Source License. See LICENSE.TXT  
> for details.
> +//
> +// 
> = 
> = 
> = 
> ----------------------------------------------------------------------= 
> ==//
> +//
> +// This file contains instantiations of "standard" AsmOStreams.
> +//
> +// 
> = 
> = 
> = 
> ----------------------------------------------------------------------= 
> ==//
> +
> +#include "llvm/CodeGen/AsmStream.h"
> +
> +#include <unistd.h>
> +
> +namespace llvm {
> +  AsmStreambuf asmoutbuf(STDOUT_FILENO);
> +  AsmStreambuf asmerrbuf(STDERR_FILENO);
> +
> +  // 
> = 
> = 
> = 
> ----------------------------------------------------------------------= 
> ==//
> +  //  raw_asm_ostream
> +  // 
> = 
> = 
> = 
> ----------------------------------------------------------------------= 
> ==//
> +
> +  raw_asm_ostream::~raw_asm_ostream() {
> +    flush();
> +  }
> +
> +  /// flush_impl - The is the piece of the class that is  
> implemented by
> +  /// subclasses.  This outputs the currently buffered data and  
> resets the
> +  /// buffer to empty.
> +  void raw_asm_ostream::flush_impl() {
> +    if (OutBufCur-OutBufStart)
> +      OS.write(OutBufStart, OutBufCur-OutBufStart);
> +
> +    HandleFlush();
> +  }
> +
> +  namespace {
> +    AsmOStream AsmOut(&asmoutbuf);
> +    AsmOStream AsmErr(&asmerrbuf);
> +  }
> +
> +  raw_asm_ostream asmout(AsmOut);
> +  raw_asm_ostream asmerr(AsmErr);
> +}
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits




More information about the llvm-commits mailing list