Refactored output buffer methods from MachO and ELF writers.
authorBill Wendling <isanbard@gmail.com>
Wed, 17 Jan 2007 22:17:24 +0000 (22:17 +0000)
committerBill Wendling <isanbard@gmail.com>
Wed, 17 Jan 2007 22:17:24 +0000 (22:17 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@33310 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/Support/OutputBuffer.h [new file with mode: 0644]

diff --git a/include/llvm/Support/OutputBuffer.h b/include/llvm/Support/OutputBuffer.h
new file mode 100644 (file)
index 0000000..24a655c
--- /dev/null
@@ -0,0 +1,146 @@
+//=== OutputBuffer.h - Output Buffer ----------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file was developed by Bill Wendling and is distributed under the
+// University of Illinois Open Source License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Methods to output values to a data buffer.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_OUTPUTBUFFER_H
+#define LLVM_SUPPORT_OUTPUTBUFFER_H
+
+#include <vector>
+
+namespace llvm {
+  
+  class OutputBuffer {
+    /// Output buffer.
+    std::vector<unsigned char> &Output;
+
+    /// is64Bit/isLittleEndian - This information is inferred from the target
+    /// machine directly, indicating what header values and flags to set.
+    bool is64Bit, isLittleEndian;
+  public:
+    OutputBuffer(const TargetMachine& TM,
+                 std::vector<unsigned char> &Out) : Output(Out) {
+      is64Bit = TM.getTargetData()->getPointerSizeInBits() == 64;
+      isLittleEndian = TM.getTargetData()->isLittleEndian();
+    }
+
+    // align - Emit padding into the file until the current output position is
+    // aligned to the specified power of two boundary.
+    void align(unsigned Boundary) {
+      assert(Boundary && (Boundary & (Boundary - 1)) == 0 &&
+             "Must alitypedef std::vector<unsigned char> DataBuffer;gn to 2^k boundary");
+      size_t Size = Output.size();
+      
+      if (Size & (Boundary - 1)) {
+        // Add padding to get alignment to the correct place.
+        size_t Pad = Boundary - (Size & (Boundary - 1));
+        Output.resize(Size + Pad);
+      }
+    }
+
+    //===------------------------------------------------------------------===//
+    // Out Functions - Output the specified value to the data buffer.
+
+    void outbyte(unsigned char X) {
+      Output.push_back(X);
+    }
+    void outhalf(unsigned short X) {
+      if (isLittleEndian) {
+        Output.push_back(X & 255);
+        Output.push_back(X >> 8);
+      } else {
+        Output.push_back(X >> 8);
+        Output.push_back(X & 255);
+      }
+    }
+    void outword(unsigned X) {
+      if (isLittleEndian) {
+        Output.push_back((X >>  0) & 255);
+        Output.push_back((X >>  8) & 255);
+        Output.push_back((X >> 16) & 255);
+        Output.push_back((X >> 24) & 255);
+      } else {
+        Output.push_back((X >> 24) & 255);
+        Output.push_back((X >> 16) & 255);
+        Output.push_back((X >>  8) & 255);
+        Output.push_back((X >>  0) & 255);
+      }
+    }
+    void outxword(uint64_t X) {
+      if (isLittleEndian) {
+        Output.push_back(unsigned(X >>  0) & 255);
+        Output.push_back(unsigned(X >>  8) & 255);
+        Output.push_back(unsigned(X >> 16) & 255);
+        Output.push_back(unsigned(X >> 24) & 255);
+        Output.push_back(unsigned(X >> 32) & 255);
+        Output.push_back(unsigned(X >> 40) & 255);
+        Output.push_back(unsigned(X >> 48) & 255);
+        Output.push_back(unsigned(X >> 56) & 255);
+      } else {
+        Output.push_back(unsigned(X >> 56) & 255);
+        Output.push_back(unsigned(X >> 48) & 255);
+        Output.push_back(unsigned(X >> 40) & 255);
+        Output.push_back(unsigned(X >> 32) & 255);
+        Output.push_back(unsigned(X >> 24) & 255);
+        Output.push_back(unsigned(X >> 16) & 255);
+        Output.push_back(unsigned(X >>  8) & 255);
+        Output.push_back(unsigned(X >>  0) & 255);
+      }
+    }
+    void outaddr32(unsigned X) {
+      outword(X);
+    }
+    void outaddr64(uint64_t X) {
+      outxword(X);
+    }
+    void outaddr(uint64_t X) {
+      if (!is64Bit)
+        outword((unsigned)X);
+      else
+        outxword(X);
+    }
+    void outstring(std::string &S, unsigned Length) {
+      unsigned len_to_copy = S.length() < Length ? S.length() : Length;
+      unsigned len_to_fill = S.length() < Length ? Length - S.length() : 0;
+      
+      for (unsigned i = 0; i < len_to_copy; ++i)
+        outbyte(S[i]);
+      
+      for (unsigned i = 0; i < len_to_fill; ++i)
+        outbyte(0);
+    }
+
+    //===------------------------------------------------------------------===//
+    // Fix Functions - Replace an existing entry at an offset.
+
+    void fixhalf(unsigned short X, unsigned Offset) {
+      unsigned char *P = &Output[Offset];
+      P[0] = (X >> (isLittleEndian ?  0 : 8)) & 255;
+      P[1] = (X >> (isLittleEndian ?  8 : 0)) & 255;
+    }
+    void fixword(unsigned X, unsigned Offset) {
+      unsigned char *P = &Output[Offset];
+      P[0] = (X >> (isLittleEndian ?  0 : 24)) & 255;
+      P[1] = (X >> (isLittleEndian ?  8 : 16)) & 255;
+      P[2] = (X >> (isLittleEndian ? 16 :  8)) & 255;
+      P[3] = (X >> (isLittleEndian ? 24 :  0)) & 255;
+    }
+    void fixaddr(uint64_t X, unsigned Offset) {
+      if (!is64Bit)
+        fixword((unsigned)X, Offset);
+      else
+        assert(0 && "Emission of 64-bit data not implemented yet!");
+    }
+  };
+  
+} // end llvm namespace
+
+#endif // LLVM_SUPPORT_OUTPUTBUFFER_H