aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2008-07-09 05:14:23 +0000
committerChris Lattner <sabre@nondot.org>2008-07-09 05:14:23 +0000
commita660f4bb07e5a8cf446b00c498c8c4c1ec28a447 (patch)
tree2594b58ba6928d273d01ca864bbacf322aacc040 /llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
parent304deea9e6dc94ba6c4b8ea93322c0f71cf8a385 (diff)
downloadllvm-a660f4bb07e5a8cf446b00c498c8c4c1ec28a447.zip
llvm-a660f4bb07e5a8cf446b00c498c8c4c1ec28a447.tar.gz
llvm-a660f4bb07e5a8cf446b00c498c8c4c1ec28a447.tar.bz2
Add a little wrapper header that is put around bc files when emitting
bc files for modules with a target triple that indicates they are for darwin. The reader unconditionally handles this, and the writer could turn this on for more targets if we care. This change has two benefits for darwin: 1) it allows us to encode the cpu type of the file in an easy to read place that doesn't require decoding the bc file. 2) it works around a bug (IMO) in darwin's AR where it is incapable of handling files that are not a multiple of 8 bytes long. BC files are only guaranteed to be multiples of 4 bytes long. llvm-svn: 53275
Diffstat (limited to 'llvm/lib/Bitcode/Writer/BitcodeWriter.cpp')
-rw-r--r--llvm/lib/Bitcode/Writer/BitcodeWriter.cpp75
1 files changed, 74 insertions, 1 deletions
diff --git a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
index 0030aca..9794fac 100644
--- a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
+++ b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
@@ -1273,6 +1273,70 @@ static void WriteModule(const Module *M, BitstreamWriter &Stream) {
Stream.ExitBlock();
}
+/// EmitDarwinBCHeader - If generating a bc file on darwin, we have to emit a
+/// header and trailer to make it compatible with the system archiver. To do
+/// this we emit the following header, and then emit a trailer that pads the
+/// file out to be a multiple of 16 bytes.
+///
+/// struct bc_header {
+/// uint32_t Magic; // 0x0B17C0DE
+/// uint32_t Version; // Version, currently always 0.
+/// uint32_t BitcodeOffset; // Offset to traditional bitcode file.
+/// uint32_t BitcodeSize; // Size of traditional bitcode file.
+/// uint32_t CPUType; // CPU specifier.
+/// ... potentially more later ...
+/// };
+enum {
+ DarwinBCSizeFieldOffset = 3*4, // Offset to bitcode_size.
+ DarwinBCHeaderSize = 5*4
+};
+
+static void EmitDarwinBCHeader(BitstreamWriter &Stream,
+ const std::string &TT) {
+ unsigned CPUType = ~0U;
+
+ // Match x86_64-*, i[3-9]86-*, powerpc-*, powerpc64-*. The CPUType is a
+ // magic number from /usr/include/mach/machine.h. It is ok to reproduce the
+ // specific constants here because they are implicitly part of the Darwin ABI.
+ enum {
+ DARWIN_CPU_ARCH_ABI64 = 0x01000000,
+ DARWIN_CPU_TYPE_X86 = 7,
+ DARWIN_CPU_TYPE_POWERPC = 18
+ };
+
+ if (TT.find("x86_64-") == 0)
+ CPUType = DARWIN_CPU_TYPE_X86 | DARWIN_CPU_ARCH_ABI64;
+ else if (TT.size() >= 5 && TT[0] == 'i' && TT[2] == '8' && TT[3] == '6' &&
+ TT[4] == '-' && TT[1] - '3' < 6)
+ CPUType = DARWIN_CPU_TYPE_X86;
+ else if (TT.find("powerpc-") == 0)
+ CPUType = DARWIN_CPU_TYPE_POWERPC;
+ else if (TT.find("powerpc64-") == 0)
+ CPUType = DARWIN_CPU_TYPE_POWERPC | DARWIN_CPU_ARCH_ABI64;
+
+ // Traditional Bitcode starts after header.
+ unsigned BCOffset = DarwinBCHeaderSize;
+
+ Stream.Emit(0x0B17C0DE, 32);
+ Stream.Emit(0 , 32); // Version.
+ Stream.Emit(BCOffset , 32);
+ Stream.Emit(0 , 32); // Filled in later.
+ Stream.Emit(CPUType , 32);
+}
+
+/// EmitDarwinBCTrailer - Emit the darwin epilog after the bitcode file and
+/// finalize the header.
+static void EmitDarwinBCTrailer(BitstreamWriter &Stream, unsigned BufferSize) {
+ // Update the size field in the header.
+ Stream.BackpatchWord(DarwinBCSizeFieldOffset, BufferSize-DarwinBCHeaderSize);
+
+ // If the file is not a multiple of 16 bytes, insert dummy padding.
+ while (BufferSize & 15) {
+ Stream.Emit(0, 8);
+ ++BufferSize;
+ }
+}
+
/// WriteBitcodeToFile - Write the specified module to the specified output
/// stream.
@@ -1282,6 +1346,11 @@ void llvm::WriteBitcodeToFile(const Module *M, std::ostream &Out) {
Buffer.reserve(256*1024);
+ // If this is darwin, emit a file header and trailer if needed.
+ bool isDarwin = M->getTargetTriple().find("-darwin") != std::string::npos;
+ if (isDarwin)
+ EmitDarwinBCHeader(Stream, M->getTargetTriple());
+
// Emit the file header.
Stream.Emit((unsigned)'B', 8);
Stream.Emit((unsigned)'C', 8);
@@ -1292,10 +1361,14 @@ void llvm::WriteBitcodeToFile(const Module *M, std::ostream &Out) {
// Emit the module.
WriteModule(M, Stream);
+
+ if (isDarwin)
+ EmitDarwinBCTrailer(Stream, Buffer.size());
+
// If writing to stdout, set binary mode.
if (llvm::cout == Out)
- sys::Program::ChangeStdoutToBinary();
+ sys::Program::ChangeStdoutToBinary();
// Write the generated bitstream to "Out".
Out.write((char*)&Buffer.front(), Buffer.size());