aboutsummaryrefslogtreecommitdiff
path: root/lib/Bitcode/NaCl/Writer/NaClBitcodeWriter.cpp
diff options
context:
space:
mode:
authorKarl Schimpf <kschimpf@google.com>2013-06-06 10:03:24 -0700
committerKarl Schimpf <kschimpf@google.com>2013-06-06 10:03:24 -0700
commit37bdd9174a1cba17b369c8c1f561e70c458e0c13 (patch)
tree1f6a984ebb94ccd819c6e38646d91bb5c7eb6977 /lib/Bitcode/NaCl/Writer/NaClBitcodeWriter.cpp
parentc0d9b337419b72e69cbd9c64f84ae39560ab344f (diff)
Make PNaCl bitcode files have a different format from LLVM bitcode files.
BUG= https://code.google.com/p/nativeclient/issues/detail?id=3405 R=dschuff@chromium.org Review URL: https://codereview.chromium.org/15907008
Diffstat (limited to 'lib/Bitcode/NaCl/Writer/NaClBitcodeWriter.cpp')
-rw-r--r--lib/Bitcode/NaCl/Writer/NaClBitcodeWriter.cpp132
1 files changed, 55 insertions, 77 deletions
diff --git a/lib/Bitcode/NaCl/Writer/NaClBitcodeWriter.cpp b/lib/Bitcode/NaCl/Writer/NaClBitcodeWriter.cpp
index d77a79a2c9..522ef1bbba 100644
--- a/lib/Bitcode/NaCl/Writer/NaClBitcodeWriter.cpp
+++ b/lib/Bitcode/NaCl/Writer/NaClBitcodeWriter.cpp
@@ -13,6 +13,7 @@
#define DEBUG_TYPE "NaClBitcodeWriter"
+#include "llvm/Bitcode/NaCl/NaClBitcodeHeader.h"
#include "llvm/Bitcode/NaCl/NaClReaderWriter.h"
#include "NaClValueEnumerator.h"
#include "llvm/ADT/Triple.h"
@@ -1903,24 +1904,6 @@ static void WriteModule(const Module *M, NaClBitstreamWriter &Stream) {
DEBUG(dbgs() << "<- WriteModule\n");
}
-/// 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 WriteInt32ToBuffer(uint32_t Value, SmallVectorImpl<char> &Buffer,
uint32_t &Position) {
Buffer[Position + 0] = (unsigned char) (Value >> 0);
@@ -1930,52 +1913,49 @@ static void WriteInt32ToBuffer(uint32_t Value, SmallVectorImpl<char> &Buffer,
Position += 4;
}
-static void EmitDarwinBCHeaderAndTrailer(SmallVectorImpl<char> &Buffer,
- const Triple &TT) {
- unsigned CPUType = ~0U;
-
- // Match x86_64-*, i[3-9]86-*, powerpc-*, powerpc64-*, arm-*, thumb-*,
- // armv[0-9]-*, thumbv[0-9]-*, armv5te-*, or armv6t2-*. 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_ARM = 12,
- DARWIN_CPU_TYPE_POWERPC = 18
- };
-
- Triple::ArchType Arch = TT.getArch();
- if (Arch == Triple::x86_64)
- CPUType = DARWIN_CPU_TYPE_X86 | DARWIN_CPU_ARCH_ABI64;
- else if (Arch == Triple::x86)
- CPUType = DARWIN_CPU_TYPE_X86;
- else if (Arch == Triple::ppc)
- CPUType = DARWIN_CPU_TYPE_POWERPC;
- else if (Arch == Triple::ppc64)
- CPUType = DARWIN_CPU_TYPE_POWERPC | DARWIN_CPU_ARCH_ABI64;
- else if (Arch == Triple::arm || Arch == Triple::thumb)
- CPUType = DARWIN_CPU_TYPE_ARM;
-
- // Traditional Bitcode starts after header.
- assert(Buffer.size() >= DarwinBCHeaderSize &&
- "Expected header size to be reserved");
- unsigned BCOffset = DarwinBCHeaderSize;
- unsigned BCSize = Buffer.size()-DarwinBCHeaderSize;
-
- // Write the magic and version.
- unsigned Position = 0;
- WriteInt32ToBuffer(0x0B17C0DE , Buffer, Position);
- WriteInt32ToBuffer(0 , Buffer, Position); // Version.
- WriteInt32ToBuffer(BCOffset , Buffer, Position);
- WriteInt32ToBuffer(BCSize , Buffer, Position);
- WriteInt32ToBuffer(CPUType , Buffer, Position);
-
- // If the file is not a multiple of 16 bytes, insert dummy padding.
- while (Buffer.size() & 15)
- Buffer.push_back(0);
+// Max size for variable fields. Currently only used for writing them
+// out to files (the parsing works for arbitrary sizes).
+static const size_t kMaxVariableFieldSize = 256;
+
+// Write out the given fields to the bitstream.
+static void WriteHeaderFields(
+ const std::vector<NaClBitcodeHeaderField*> &Fields,
+ NaClBitstreamWriter& Stream) {
+ // Emit placeholder for number of bytes used to hold header fields.
+ // This value is necessary so that the streamable reader can preallocate
+ // a buffer to read the fields.
+ Stream.Emit(0, naclbitc::BlockSizeWidth);
+ unsigned BytesForHeader = 0;
+
+ unsigned NumberFields = Fields.size();
+ if (NumberFields > 0xFFFF)
+ report_fatal_error("Too many header fields");
+
+ uint8_t Buffer[kMaxVariableFieldSize];
+ for (std::vector<NaClBitcodeHeaderField*>::const_iterator
+ Iter = Fields.begin(), IterEnd = Fields.end();
+ Iter != IterEnd; ++Iter) {
+ if (!(*Iter)->Write(Buffer, kMaxVariableFieldSize))
+ report_fatal_error("Header field too big to generate");
+ size_t limit = (*Iter)->GetTotalSize();
+ for (size_t i = 0; i < limit; i++) {
+ Stream.Emit(Buffer[i], 8);
+ }
+ BytesForHeader += limit;
+ }
+
+ if (BytesForHeader > 0xFFFF)
+ report_fatal_error("Header fields to big to save");
+
+ // Encode #fields in top two bytes, and #bytes to hold fields in
+ // bottom two bytes. Then backpatch into second word.
+ unsigned Value = NumberFields | (BytesForHeader << 16);
+ Stream.BackpatchWord(NaClBitcodeHeader::WordSize, Value);
}
+// Define the version of PNaCl bitcode we are generating.
+static const uint16_t kPNaClVersion = 1;
+
/// WriteBitcodeToFile - Write the specified module to the specified output
/// stream.
void llvm::NaClWriteBitcodeToFile(const Module *M, raw_ostream &Out) {
@@ -1985,31 +1965,29 @@ void llvm::NaClWriteBitcodeToFile(const Module *M, raw_ostream &Out) {
// Convert Deplib info to metadata
M->convertLibraryListToMetadata(); // @LOCALMOD
- // If this is darwin or another generic macho target, reserve space for the
- // header.
- Triple TT(M->getTargetTriple());
- if (TT.isOSDarwin())
- Buffer.insert(Buffer.begin(), DarwinBCHeaderSize, 0);
-
// Emit the module into the buffer.
{
NaClBitstreamWriter Stream(Buffer);
// Emit the file header.
- Stream.Emit((unsigned)'B', 8);
- Stream.Emit((unsigned)'C', 8);
- Stream.Emit(0x0, 4);
- Stream.Emit(0xC, 4);
- Stream.Emit(0xE, 4);
- Stream.Emit(0xD, 4);
+ Stream.Emit((unsigned)'P', 8);
+ Stream.Emit((unsigned)'E', 8);
+ Stream.Emit((unsigned)'X', 8);
+ Stream.Emit((unsigned)'E', 8);
+
+ // Collect header fields to add.
+ {
+ std::vector<NaClBitcodeHeaderField*> HeaderFields;
+ HeaderFields.push_back(
+ new NaClBitcodeHeaderField(NaClBitcodeHeaderField::kPNaClVersion,
+ kPNaClVersion));
+ WriteHeaderFields(HeaderFields, Stream);
+ }
// Emit the module.
WriteModule(M, Stream);
}
- if (TT.isOSDarwin())
- EmitDarwinBCHeaderAndTrailer(Buffer, TT);
-
// Write the generated bitstream to "Out".
Out.write((char*)&Buffer.front(), Buffer.size());
}