summaryrefslogtreecommitdiffstats
path: root/include/llvm/Support
diff options
context:
space:
mode:
Diffstat (limited to 'include/llvm/Support')
-rw-r--r--include/llvm/Support/Casting.h2
-rw-r--r--include/llvm/Support/Compiler.h6
-rw-r--r--include/llvm/Support/ConstantFolder.h6
-rw-r--r--include/llvm/Support/Debug.h21
-rw-r--r--include/llvm/Support/Format.h7
-rw-r--r--include/llvm/Support/FormattedStream.h2
-rw-r--r--include/llvm/Support/IRBuilder.h236
-rw-r--r--include/llvm/Support/NoFolder.h6
-rw-r--r--include/llvm/Support/StandardPasses.h3
-rw-r--r--include/llvm/Support/TargetFolder.h6
-rw-r--r--include/llvm/Support/circular_raw_ostream.h171
-rw-r--r--include/llvm/Support/raw_os_ostream.h2
-rw-r--r--include/llvm/Support/raw_ostream.h18
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() {}
OpenPOWER on IntegriCloud