diff options
Diffstat (limited to 'include/llvm/Support')
-rw-r--r-- | include/llvm/Support/Casting.h | 2 | ||||
-rw-r--r-- | include/llvm/Support/Compiler.h | 6 | ||||
-rw-r--r-- | include/llvm/Support/ConstantFolder.h | 6 | ||||
-rw-r--r-- | include/llvm/Support/Debug.h | 21 | ||||
-rw-r--r-- | include/llvm/Support/Format.h | 7 | ||||
-rw-r--r-- | include/llvm/Support/FormattedStream.h | 2 | ||||
-rw-r--r-- | include/llvm/Support/IRBuilder.h | 236 | ||||
-rw-r--r-- | include/llvm/Support/NoFolder.h | 6 | ||||
-rw-r--r-- | include/llvm/Support/StandardPasses.h | 3 | ||||
-rw-r--r-- | include/llvm/Support/TargetFolder.h | 6 | ||||
-rw-r--r-- | include/llvm/Support/circular_raw_ostream.h | 171 | ||||
-rw-r--r-- | include/llvm/Support/raw_os_ostream.h | 2 | ||||
-rw-r--r-- | include/llvm/Support/raw_ostream.h | 18 |
13 files changed, 349 insertions, 137 deletions
diff --git a/include/llvm/Support/Casting.h b/include/llvm/Support/Casting.h index 35fb29e..37a7c3b 100644 --- a/include/llvm/Support/Casting.h +++ b/include/llvm/Support/Casting.h @@ -251,7 +251,7 @@ struct foo { }; template <> inline bool isa_impl<foo,bar>(const bar &Val) { - errs() << "Classof: " << &Val << "\n"; + dbgs() << "Classof: " << &Val << "\n"; return true; } diff --git a/include/llvm/Support/Compiler.h b/include/llvm/Support/Compiler.h index 8861a20..1376e46 100644 --- a/include/llvm/Support/Compiler.h +++ b/include/llvm/Support/Compiler.h @@ -29,6 +29,12 @@ #define ATTRIBUTE_USED #endif +#if (__GNUC__ >= 4 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1)) +#define ATTRIBUTE_UNUSED __attribute__((__unused__)) +#else +#define ATTRIBUTE_UNUSED +#endif + #ifdef __GNUC__ // aka 'ATTRIBUTE_CONST' but following LLVM Conventions. #define ATTRIBUTE_READNONE __attribute__((__const__)) #else diff --git a/include/llvm/Support/ConstantFolder.h b/include/llvm/Support/ConstantFolder.h index b73cea0..1339e9f 100644 --- a/include/llvm/Support/ConstantFolder.h +++ b/include/llvm/Support/ConstantFolder.h @@ -54,6 +54,9 @@ public: Constant *CreateMul(Constant *LHS, Constant *RHS) const { return ConstantExpr::getMul(LHS, RHS); } + Constant *CreateNSWMul(Constant *LHS, Constant *RHS) const { + return ConstantExpr::getNSWMul(LHS, RHS); + } Constant *CreateFMul(Constant *LHS, Constant *RHS) const { return ConstantExpr::getFMul(LHS, RHS); } @@ -109,6 +112,9 @@ public: Constant *CreateNeg(Constant *C) const { return ConstantExpr::getNeg(C); } + Constant *CreateNSWNeg(Constant *C) const { + return ConstantExpr::getNSWNeg(C); + } Constant *CreateFNeg(Constant *C) const { return ConstantExpr::getFNeg(C); } diff --git a/include/llvm/Support/Debug.h b/include/llvm/Support/Debug.h index e8bc0ce..8651fc1 100644 --- a/include/llvm/Support/Debug.h +++ b/include/llvm/Support/Debug.h @@ -28,6 +28,8 @@ namespace llvm { +class raw_ostream; + /// DEBUG_TYPE macro - Files can specify a DEBUG_TYPE as a string, which causes /// all of their DEBUG statements to be activatable with -debug-only=thatstring. #ifndef DEBUG_TYPE @@ -58,7 +60,7 @@ void SetCurrentDebugType(const char *Type); /// this is a debug build, then the code specified as the option to the macro /// will be executed. Otherwise it will not be. Example: /// -/// DEBUG_WITH_TYPE("bitset", errs() << "Bitset contains: " << Bitset << "\n"); +/// DEBUG_WITH_TYPE("bitset", dbgs() << "Bitset contains: " << Bitset << "\n"); /// /// This will emit the debug information if -debug is present, and -debug-only /// is not specified, or is specified as "bitset". @@ -72,15 +74,28 @@ void SetCurrentDebugType(const char *Type); #define DEBUG_WITH_TYPE(TYPE, X) do { } while (0) #endif +/// EnableDebugBuffering - This defaults to false. If true, the debug +/// stream will install signal handlers to dump any buffered debug +/// output. It allows clients to selectively allow the debug stream +/// to install signal handlers if they are certain there will be no +/// conflict. +/// +extern bool EnableDebugBuffering; + +/// dbgs() - This returns a reference to a raw_ostream for debugging +/// messages. If debugging is disabled it returns errs(). Use it +/// like: dbgs() << "foo" << "bar"; +raw_ostream &dbgs(); + // DEBUG macro - This macro should be used by passes to emit debug information. // In the '-debug' option is specified on the commandline, and if this is a // debug build, then the code specified as the option to the macro will be // executed. Otherwise it will not be. Example: // -// DEBUG(errs() << "Bitset contains: " << Bitset << "\n"); +// DEBUG(dbgs() << "Bitset contains: " << Bitset << "\n"); // #define DEBUG(X) DEBUG_WITH_TYPE(DEBUG_TYPE, X) - + } // End llvm namespace #endif diff --git a/include/llvm/Support/Format.h b/include/llvm/Support/Format.h index 340f517..f64e3db 100644 --- a/include/llvm/Support/Format.h +++ b/include/llvm/Support/Format.h @@ -25,7 +25,12 @@ #include <cassert> #include <cstdio> -#ifdef WIN32 +#ifdef _MSC_VER +// FIXME: This define is wrong: +// - _snprintf does not guarantee that trailing null is always added - if +// there is no space for null, it does not report any error. +// - According to C++ standard, snprintf should be visible in the 'std' +// namespace - this define makes this impossible. #define snprintf _snprintf #endif diff --git a/include/llvm/Support/FormattedStream.h b/include/llvm/Support/FormattedStream.h index 24a3546..09ab17c 100644 --- a/include/llvm/Support/FormattedStream.h +++ b/include/llvm/Support/FormattedStream.h @@ -59,7 +59,7 @@ namespace llvm /// current_pos - Return the current position within the stream, /// not counting the bytes currently in the buffer. - virtual uint64_t current_pos() { + virtual uint64_t current_pos() const { // This has the same effect as calling TheStream.current_pos(), // but that interface is private. return TheStream->tell() - TheStream->GetNumBytesInBuffer(); diff --git a/include/llvm/Support/IRBuilder.h b/include/llvm/Support/IRBuilder.h index 1310d70..eabf6ad 100644 --- a/include/llvm/Support/IRBuilder.h +++ b/include/llvm/Support/IRBuilder.h @@ -15,17 +15,13 @@ #ifndef LLVM_SUPPORT_IRBUILDER_H #define LLVM_SUPPORT_IRBUILDER_H -#include "llvm/Constants.h" #include "llvm/Instructions.h" -#include "llvm/GlobalAlias.h" -#include "llvm/GlobalVariable.h" -#include "llvm/Function.h" -#include "llvm/Metadata.h" -#include "llvm/LLVMContext.h" +#include "llvm/BasicBlock.h" #include "llvm/ADT/Twine.h" #include "llvm/Support/ConstantFolder.h" namespace llvm { + class MDNode; /// IRBuilderDefaultInserter - This provides the default implementation of the /// IRBuilder 'InsertHelper' method that is called whenever an instruction is @@ -41,138 +37,72 @@ protected: I->setName(Name); } }; - - -/// IRBuilder - This provides a uniform API for creating instructions and -/// inserting them into a basic block: either at the end of a BasicBlock, or -/// at a specific iterator location in a block. -/// -/// Note that the builder does not expose the full generality of LLVM -/// instructions. For access to extra instruction properties, use the mutators -/// (e.g. setVolatile) on the instructions after they have been created. -/// The first template argument handles whether or not to preserve names in the -/// final instruction output. This defaults to on. The second template argument -/// specifies a class to use for creating constants. This defaults to creating -/// minimally folded constants. The fourth template argument allows clients to -/// specify custom insertion hooks that are called on every newly created -/// insertion. -template<bool preserveNames = true, typename T = ConstantFolder, - typename Inserter = IRBuilderDefaultInserter<preserveNames> > -class IRBuilder : public Inserter { + +/// IRBuilderBase - Common base class shared among various IRBuilders. +class IRBuilderBase { + unsigned DbgMDKind; + MDNode *CurDbgLocation; +protected: BasicBlock *BB; BasicBlock::iterator InsertPt; - unsigned MDKind; - MDNode *CurDbgLocation; LLVMContext &Context; - T Folder; public: - IRBuilder(LLVMContext &C, const T &F, const Inserter &I = Inserter()) - : Inserter(I), MDKind(0), CurDbgLocation(0), Context(C), Folder(F) { - ClearInsertionPoint(); - } - explicit IRBuilder(LLVMContext &C) - : MDKind(0), CurDbgLocation(0), Context(C), Folder(C) { + IRBuilderBase(LLVMContext &context) + : DbgMDKind(0), CurDbgLocation(0), Context(context) { ClearInsertionPoint(); } - explicit IRBuilder(BasicBlock *TheBB, const T &F) - : MDKind(0), CurDbgLocation(0), Context(TheBB->getContext()), Folder(F) { - SetInsertPoint(TheBB); - } - - explicit IRBuilder(BasicBlock *TheBB) - : MDKind(0), CurDbgLocation(0), Context(TheBB->getContext()), - Folder(Context) { - SetInsertPoint(TheBB); - } - - IRBuilder(BasicBlock *TheBB, BasicBlock::iterator IP, const T& F) - : MDKind(0), CurDbgLocation(0), Context(TheBB->getContext()), Folder(F) { - SetInsertPoint(TheBB, IP); - } - - IRBuilder(BasicBlock *TheBB, BasicBlock::iterator IP) - : MDKind(0), CurDbgLocation(0), Context(TheBB->getContext()), - Folder(Context) { - SetInsertPoint(TheBB, IP); - } - - /// getFolder - Get the constant folder being used. - const T &getFolder() { return Folder; } - - /// isNamePreserving - Return true if this builder is configured to actually - /// add the requested names to IR created through it. - bool isNamePreserving() const { return preserveNames; } - //===--------------------------------------------------------------------===// // Builder configuration methods //===--------------------------------------------------------------------===// - + /// ClearInsertionPoint - Clear the insertion point: created instructions will /// not be inserted into a block. void ClearInsertionPoint() { BB = 0; } - + BasicBlock *GetInsertBlock() const { return BB; } - BasicBlock::iterator GetInsertPoint() const { return InsertPt; } - + /// SetInsertPoint - This specifies that created instructions should be /// appended to the end of the specified block. void SetInsertPoint(BasicBlock *TheBB) { BB = TheBB; InsertPt = BB->end(); } - + /// SetInsertPoint - This specifies that created instructions should be /// inserted at the specified point. void SetInsertPoint(BasicBlock *TheBB, BasicBlock::iterator IP) { BB = TheBB; InsertPt = IP; } - + /// SetCurrentDebugLocation - Set location information used by debugging /// information. - void SetCurrentDebugLocation(MDNode *L) { - if (MDKind == 0) - MDKind = Context.getMetadata().getMDKind("dbg"); - if (MDKind == 0) - MDKind = Context.getMetadata().registerMDKind("dbg"); - CurDbgLocation = L; - } - + void SetCurrentDebugLocation(MDNode *L); MDNode *getCurrentDebugLocation() const { return CurDbgLocation; } - - /// SetDebugLocation - Set location information for the given instruction. - void SetDebugLocation(Instruction *I) { - if (CurDbgLocation) - Context.getMetadata().addMD(MDKind, CurDbgLocation, I); - } - - /// SetDebugLocation - Set location information for the given instruction. - void SetDebugLocation(Instruction *I, MDNode *Loc) { - if (MDKind == 0) - MDKind = Context.getMetadata().getMDKind("dbg"); - if (MDKind == 0) - MDKind = Context.getMetadata().registerMDKind("dbg"); - Context.getMetadata().addMD(MDKind, Loc, I); - } - - /// Insert - Insert and return the specified instruction. - template<typename InstTy> - InstTy *Insert(InstTy *I, const Twine &Name = "") const { - this->InsertHelper(I, Name, BB, InsertPt); - if (CurDbgLocation) - Context.getMetadata().addMD(MDKind, CurDbgLocation, I); - return I; - } + + /// SetInstDebugLocation - If this builder has a current debug location, set + /// it on the specified instruction. + void SetInstDebugLocation(Instruction *I) const; //===--------------------------------------------------------------------===// + // Miscellaneous creation methods. + //===--------------------------------------------------------------------===// + + /// CreateGlobalString - Make a new global variable with an initializer that + /// has array of i8 type filled in the the nul terminated string value + /// specified. If Name is specified, it is the name of the global variable + /// created. + Value *CreateGlobalString(const char *Str = "", const Twine &Name = ""); + + //===--------------------------------------------------------------------===// // Type creation methods //===--------------------------------------------------------------------===// - + /// getInt1Ty - Fetch the type representing a single bit const Type *getInt1Ty() { return Type::getInt1Ty(Context); @@ -197,7 +127,7 @@ public: const Type *getInt64Ty() { return Type::getInt64Ty(Context); } - + /// getFloatTy - Fetch the type representing a 32-bit floating point value. const Type *getFloatTy() { return Type::getFloatTy(Context); @@ -212,6 +142,72 @@ public: const Type *getVoidTy() { return Type::getVoidTy(Context); } + + /// getCurrentFunctionReturnType - Get the return type of the current function + /// that we're emitting into. + const Type *getCurrentFunctionReturnType() const; +}; + +/// IRBuilder - This provides a uniform API for creating instructions and +/// inserting them into a basic block: either at the end of a BasicBlock, or +/// at a specific iterator location in a block. +/// +/// Note that the builder does not expose the full generality of LLVM +/// instructions. For access to extra instruction properties, use the mutators +/// (e.g. setVolatile) on the instructions after they have been created. +/// The first template argument handles whether or not to preserve names in the +/// final instruction output. This defaults to on. The second template argument +/// specifies a class to use for creating constants. This defaults to creating +/// minimally folded constants. The fourth template argument allows clients to +/// specify custom insertion hooks that are called on every newly created +/// insertion. +template<bool preserveNames = true, typename T = ConstantFolder, + typename Inserter = IRBuilderDefaultInserter<preserveNames> > +class IRBuilder : public IRBuilderBase, public Inserter { + T Folder; +public: + IRBuilder(LLVMContext &C, const T &F, const Inserter &I = Inserter()) + : IRBuilderBase(C), Inserter(I), Folder(F) { + } + + explicit IRBuilder(LLVMContext &C) : IRBuilderBase(C), Folder(C) { + } + + explicit IRBuilder(BasicBlock *TheBB, const T &F) + : IRBuilderBase(TheBB->getContext()), Folder(F) { + SetInsertPoint(TheBB); + } + + explicit IRBuilder(BasicBlock *TheBB) + : IRBuilderBase(TheBB->getContext()), Folder(Context) { + SetInsertPoint(TheBB); + } + + IRBuilder(BasicBlock *TheBB, BasicBlock::iterator IP, const T& F) + : IRBuilderBase(TheBB->getContext()), Folder(F) { + SetInsertPoint(TheBB, IP); + } + + IRBuilder(BasicBlock *TheBB, BasicBlock::iterator IP) + : IRBuilderBase(TheBB->getContext()), Folder(Context) { + SetInsertPoint(TheBB, IP); + } + + /// getFolder - Get the constant folder being used. + const T &getFolder() { return Folder; } + + /// isNamePreserving - Return true if this builder is configured to actually + /// add the requested names to IR created through it. + bool isNamePreserving() const { return preserveNames; } + + /// Insert - Insert and return the specified instruction. + template<typename InstTy> + InstTy *Insert(InstTy *I, const Twine &Name = "") const { + this->InsertHelper(I, Name, BB, InsertPt); + if (getCurrentDebugLocation() != 0) + this->SetInstDebugLocation(I); + return I; + } //===--------------------------------------------------------------------===// // Instruction creation methods: Terminators @@ -228,7 +224,7 @@ public: ReturnInst *CreateRet(Value *V) { return Insert(ReturnInst::Create(Context, V)); } - + /// CreateAggregateRet - Create a sequence of N insertvalue instructions, /// with one Value from the retVals array each, that build a aggregate /// return value one value at a time, and a ret instruction to return @@ -236,9 +232,8 @@ public: /// code that uses aggregate return values as a vehicle for having /// multiple return values. /// - ReturnInst *CreateAggregateRet(Value * const* retVals, unsigned N) { - const Type *RetType = BB->getParent()->getReturnType(); - Value *V = UndefValue::get(RetType); + ReturnInst *CreateAggregateRet(Value *const *retVals, unsigned N) { + Value *V = UndefValue::get(getCurrentFunctionReturnType()); for (unsigned i = 0; i != N; ++i) V = CreateInsertValue(V, retVals[i], i, "mrv"); return Insert(ReturnInst::Create(Context, V)); @@ -353,6 +348,12 @@ public: return Folder.CreateMul(LC, RC); return Insert(BinaryOperator::CreateMul(LHS, RHS), Name); } + Value *CreateNSWMul(Value *LHS, Value *RHS, const Twine &Name = "") { + if (Constant *LC = dyn_cast<Constant>(LHS)) + if (Constant *RC = dyn_cast<Constant>(RHS)) + return Folder.CreateNSWMul(LC, RC); + return Insert(BinaryOperator::CreateNSWMul(LHS, RHS), Name); + } Value *CreateFMul(Value *LHS, Value *RHS, const Twine &Name = "") { if (Constant *LC = dyn_cast<Constant>(LHS)) if (Constant *RC = dyn_cast<Constant>(RHS)) @@ -478,6 +479,11 @@ public: return Folder.CreateNeg(VC); return Insert(BinaryOperator::CreateNeg(V), Name); } + Value *CreateNSWNeg(Value *V, const Twine &Name = "") { + if (Constant *VC = dyn_cast<Constant>(V)) + return Folder.CreateNSWNeg(VC); + return Insert(BinaryOperator::CreateNSWNeg(V), Name); + } Value *CreateFNeg(Value *V, const Twine &Name = "") { if (Constant *VC = dyn_cast<Constant>(V)) return Folder.CreateFNeg(VC); @@ -639,26 +645,16 @@ public: Value *CreateStructGEP(Value *Ptr, unsigned Idx, const Twine &Name = "") { return CreateConstInBoundsGEP2_32(Ptr, 0, Idx, Name); } - Value *CreateGlobalString(const char *Str = "", const Twine &Name = "") { - Constant *StrConstant = ConstantArray::get(Context, Str, true); - Module &M = *BB->getParent()->getParent(); - GlobalVariable *gv = new GlobalVariable(M, - StrConstant->getType(), - true, - GlobalValue::InternalLinkage, - StrConstant, - "", - 0, - false); - gv->setName(Name); - return gv; - } + + /// CreateGlobalStringPtr - Same as CreateGlobalString, but return a pointer + /// with "i8*" type instead of a pointer to array of i8. Value *CreateGlobalStringPtr(const char *Str = "", const Twine &Name = "") { Value *gv = CreateGlobalString(Str, Name); Value *zero = ConstantInt::get(Type::getInt32Ty(Context), 0); Value *Args[] = { zero, zero }; return CreateInBoundsGEP(gv, Args, Args+2, Name); } + //===--------------------------------------------------------------------===// // Instruction creation methods: Cast/Conversion Operators //===--------------------------------------------------------------------===// diff --git a/include/llvm/Support/NoFolder.h b/include/llvm/Support/NoFolder.h index 7f2f149..78a9035 100644 --- a/include/llvm/Support/NoFolder.h +++ b/include/llvm/Support/NoFolder.h @@ -60,6 +60,9 @@ public: Value *CreateMul(Constant *LHS, Constant *RHS) const { return BinaryOperator::CreateMul(LHS, RHS); } + Value *CreateNSWMul(Constant *LHS, Constant *RHS) const { + return BinaryOperator::CreateNSWMul(LHS, RHS); + } Value *CreateFMul(Constant *LHS, Constant *RHS) const { return BinaryOperator::CreateFMul(LHS, RHS); } @@ -115,6 +118,9 @@ public: Value *CreateNeg(Constant *C) const { return BinaryOperator::CreateNeg(C); } + Value *CreateNSWNeg(Constant *C) const { + return BinaryOperator::CreateNSWNeg(C); + } Value *CreateNot(Constant *C) const { return BinaryOperator::CreateNot(C); } diff --git a/include/llvm/Support/StandardPasses.h b/include/llvm/Support/StandardPasses.h index 18be1ad..f233c18 100644 --- a/include/llvm/Support/StandardPasses.h +++ b/include/llvm/Support/StandardPasses.h @@ -137,7 +137,8 @@ namespace llvm { if (UnrollLoops) PM->add(createLoopUnrollPass()); // Unroll small loops PM->add(createInstructionCombiningPass()); // Clean up after the unroller - PM->add(createGVNPass()); // Remove redundancies + if (OptimizationLevel > 1) + PM->add(createGVNPass()); // Remove redundancies PM->add(createMemCpyOptPass()); // Remove memcpy / form memset PM->add(createSCCPPass()); // Constant prop with SCCP diff --git a/include/llvm/Support/TargetFolder.h b/include/llvm/Support/TargetFolder.h index afed853..59dd29b 100644 --- a/include/llvm/Support/TargetFolder.h +++ b/include/llvm/Support/TargetFolder.h @@ -67,6 +67,9 @@ public: Constant *CreateMul(Constant *LHS, Constant *RHS) const { return Fold(ConstantExpr::getMul(LHS, RHS)); } + Constant *CreateNSWMul(Constant *LHS, Constant *RHS) const { + return Fold(ConstantExpr::getNSWMul(LHS, RHS)); + } Constant *CreateFMul(Constant *LHS, Constant *RHS) const { return Fold(ConstantExpr::getFMul(LHS, RHS)); } @@ -122,6 +125,9 @@ public: Constant *CreateNeg(Constant *C) const { return Fold(ConstantExpr::getNeg(C)); } + Constant *CreateNSWNeg(Constant *C) const { + return Fold(ConstantExpr::getNSWNeg(C)); + } Constant *CreateFNeg(Constant *C) const { return Fold(ConstantExpr::getFNeg(C)); } diff --git a/include/llvm/Support/circular_raw_ostream.h b/include/llvm/Support/circular_raw_ostream.h new file mode 100644 index 0000000..2b3c329 --- /dev/null +++ b/include/llvm/Support/circular_raw_ostream.h @@ -0,0 +1,171 @@ +//===-- llvm/Support/circular_raw_ostream.h - Buffered streams --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains raw_ostream implementations for streams to do circular +// buffering of their output. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_CIRCULAR_RAW_OSTREAM_H +#define LLVM_SUPPORT_CIRCULAR_RAW_OSTREAM_H + +#include "llvm/Support/raw_ostream.h" + +namespace llvm +{ + /// circular_raw_ostream - A raw_ostream which *can* save its data + /// to a circular buffer, or can pass it through directly to an + /// underlying stream if specified with a buffer of zero. + /// + class circular_raw_ostream : public raw_ostream { + public: + /// TAKE_OWNERSHIP - Tell this stream that it owns the underlying + /// stream and is responsible for cleanup, memory management + /// issues, etc. + /// + static const bool TAKE_OWNERSHIP = true; + + /// REFERENCE_ONLY - Tell this stream it should not manage the + /// held stream. + /// + static const bool REFERENCE_ONLY = false; + + private: + /// TheStream - The real stream we output to. We set it to be + /// unbuffered, since we're already doing our own buffering. + /// + raw_ostream *TheStream; + + /// OwnsStream - Are we responsible for managing the underlying + /// stream? + /// + bool OwnsStream; + + /// BufferSize - The size of the buffer in bytes. + /// + size_t BufferSize; + + /// BufferArray - The actual buffer storage. + /// + char *BufferArray; + + /// Cur - Pointer to the current output point in BufferArray. + /// + char *Cur; + + /// Filled - Indicate whether the buffer has been completely + /// filled. This helps avoid garbage output. + /// + bool Filled; + + /// Banner - A pointer to a banner to print before dumping the + /// log. + /// + const char *Banner; + + /// flushBuffer - Dump the contents of the buffer to Stream. + /// + void flushBuffer(void) { + if (Filled) + // Write the older portion of the buffer. + TheStream->write(Cur, BufferArray + BufferSize - Cur); + // Write the newer portion of the buffer. + TheStream->write(BufferArray, Cur - BufferArray); + Cur = BufferArray; + Filled = false; + } + + virtual void write_impl(const char *Ptr, size_t Size); + + /// current_pos - Return the current position within the stream, + /// not counting the bytes currently in the buffer. + /// + virtual uint64_t current_pos() const { + // This has the same effect as calling TheStream.current_pos(), + // but that interface is private. + return TheStream->tell() - TheStream->GetNumBytesInBuffer(); + } + + public: + /// circular_raw_ostream - Construct an optionally + /// circular-buffered stream, handing it an underlying stream to + /// do the "real" output. + /// + /// As a side effect, if BuffSize is nonzero, the given Stream is + /// set to be Unbuffered. This is because circular_raw_ostream + /// does its own buffering, so it doesn't want another layer of + /// buffering to be happening underneath it. + /// + /// "Owns" tells the circular_raw_ostream whether it is + /// responsible for managing the held stream, doing memory + /// management of it, etc. + /// + circular_raw_ostream(raw_ostream &Stream, const char *Header, + size_t BuffSize = 0, bool Owns = REFERENCE_ONLY) + : raw_ostream(/*unbuffered*/true), + TheStream(0), + OwnsStream(Owns), + BufferSize(BuffSize), + BufferArray(0), + Filled(false), + Banner(Header) { + if (BufferSize != 0) + BufferArray = new char[BufferSize]; + Cur = BufferArray; + setStream(Stream, Owns); + } + explicit circular_raw_ostream() + : raw_ostream(/*unbuffered*/true), + TheStream(0), + OwnsStream(REFERENCE_ONLY), + BufferArray(0), + Filled(false), + Banner("") { + Cur = BufferArray; + } + + ~circular_raw_ostream() { + flush(); + flushBufferWithBanner(); + releaseStream(); + delete[] BufferArray; + } + + /// setStream - Tell the circular_raw_ostream to output a + /// different stream. "Owns" tells circular_raw_ostream whether + /// it should take responsibility for managing the underlying + /// stream. + /// + void setStream(raw_ostream &Stream, bool Owns = REFERENCE_ONLY) { + releaseStream(); + TheStream = &Stream; + OwnsStream = Owns; + } + + /// flushBufferWithBanner - Force output of the buffer along with + /// a small header. + /// + void flushBufferWithBanner(void); + + private: + /// releaseStream - Delete the held stream if needed. Otherwise, + /// transfer the buffer settings from this circular_raw_ostream + /// back to the underlying stream. + /// + void releaseStream() { + if (!TheStream) + return; + if (OwnsStream) + delete TheStream; + } + }; +} // end llvm namespace + + +#endif diff --git a/include/llvm/Support/raw_os_ostream.h b/include/llvm/Support/raw_os_ostream.h index e0978b2..4f5d361 100644 --- a/include/llvm/Support/raw_os_ostream.h +++ b/include/llvm/Support/raw_os_ostream.h @@ -30,7 +30,7 @@ class raw_os_ostream : public raw_ostream { /// current_pos - Return the current position within the stream, not /// counting the bytes currently in the buffer. - virtual uint64_t current_pos(); + virtual uint64_t current_pos() const; public: raw_os_ostream(std::ostream &O) : OS(O) {} diff --git a/include/llvm/Support/raw_ostream.h b/include/llvm/Support/raw_ostream.h index 2b3341d..d3c45c2 100644 --- a/include/llvm/Support/raw_ostream.h +++ b/include/llvm/Support/raw_ostream.h @@ -85,7 +85,7 @@ public: virtual ~raw_ostream(); /// tell - Return the current offset with the file. - uint64_t tell() { return current_pos() + GetNumBytesInBuffer(); } + uint64_t tell() const { return current_pos() + GetNumBytesInBuffer(); } /// has_error - Return the value of the flag in this raw_ostream indicating /// whether an output error has been encountered. @@ -116,7 +116,7 @@ public: SetBufferAndMode(new char[Size], Size, InternalBuffer); } - size_t GetBufferSize() { + size_t GetBufferSize() const { // If we're supposed to be buffered but haven't actually gotten around // to allocating the buffer yet, return the value that would be used. if (BufferMode != Unbuffered && OutBufStart == 0) @@ -269,7 +269,7 @@ private: /// current_pos - Return the current position within the stream, not /// counting the bytes currently in the buffer. - virtual uint64_t current_pos() = 0; + virtual uint64_t current_pos() const = 0; protected: /// SetBuffer - Use the provided buffer as the raw_ostream buffer. This is @@ -282,7 +282,7 @@ protected: /// preferred_buffer_size - Return an efficient buffer size for the /// underlying output mechanism. - virtual size_t preferred_buffer_size(); + virtual size_t preferred_buffer_size() const; /// error_detected - Set the flag indicating that an output error has /// been encountered. @@ -325,10 +325,10 @@ class raw_fd_ostream : public raw_ostream { /// current_pos - Return the current position within the stream, not /// counting the bytes currently in the buffer. - virtual uint64_t current_pos() { return pos; } + virtual uint64_t current_pos() const { return pos; } /// preferred_buffer_size - Determine an efficient buffer size. - virtual size_t preferred_buffer_size(); + virtual size_t preferred_buffer_size() const; public: @@ -423,7 +423,7 @@ class raw_string_ostream : public raw_ostream { /// current_pos - Return the current position within the stream, not /// counting the bytes currently in the buffer. - virtual uint64_t current_pos() { return OS.size(); } + virtual uint64_t current_pos() const { return OS.size(); } public: explicit raw_string_ostream(std::string &O) : OS(O) {} ~raw_string_ostream(); @@ -447,7 +447,7 @@ class raw_svector_ostream : public raw_ostream { /// current_pos - Return the current position within the stream, not /// counting the bytes currently in the buffer. - virtual uint64_t current_pos(); + virtual uint64_t current_pos() const; public: /// Construct a new raw_svector_ostream. /// @@ -468,7 +468,7 @@ class raw_null_ostream : public raw_ostream { /// current_pos - Return the current position within the stream, not /// counting the bytes currently in the buffer. - virtual uint64_t current_pos(); + virtual uint64_t current_pos() const; public: explicit raw_null_ostream() {} |