[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