Skip to content
This repository was archived by the owner on Feb 5, 2019. It is now read-only.

Commit f46b724

Browse files
committed
Add (unsupported experimental) feature allowing byte aligned bitcode.
This is the first step of allowing PNaCl bitcode files to generate and accept byte aligned bitcode records. To write bitcode files with byte alignment, one uses the command-line argument '--align-bitcode-records'. When such bitcode files are written, a corresponding flag is added to the bitcode header so that the reader knows whether it should align bitcode records. This allows old PNaCl bitcode files to continue to work. BUG=https://code.google.com/p/nativeclient/issues/detail?id=4164 [email protected] Review URL: https://codereview.chromium.org/1122423005
1 parent 4c20e87 commit f46b724

File tree

13 files changed

+372
-84
lines changed

13 files changed

+372
-84
lines changed

include/llvm/Bitcode/NaCl/NaClBitcodeHeader.h

Lines changed: 34 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -38,13 +38,18 @@ class NaClBitcodeHeaderField {
3838
// Defines the ID associated with the value. Valid values are in
3939
// {0x0, ..., 0xFFF}
4040
typedef enum {
41-
kInvalid = 0, // KUnknownType.
42-
kPNaClVersion = 1 // kUint32.
41+
kInvalid = 0, // KUnknownType.
42+
kPNaClVersion = 1, // kUint32Type.
43+
kAlignBitcodeRecords = 2, // kFlagType.
44+
kTag_MAX = kAlignBitcodeRecords
4345
} Tag;
4446
// Defines the type of value.
4547
typedef enum {
4648
kBufferType, // Buffer of form uint8_t[len].
47-
kUInt32Type
49+
kUInt32Type,
50+
kFlagType,
51+
kUnknownType,
52+
kFieldType_MAX = kUnknownType
4853
} FieldType;
4954
// Defines the number of bytes in a (32-bit) word.
5055
static const int WordSize = 4;
@@ -55,6 +60,9 @@ class NaClBitcodeHeaderField {
5560
// Create an invalid header field.
5661
NaClBitcodeHeaderField();
5762

63+
// Creates a header field where MyID is a flag.
64+
NaClBitcodeHeaderField(Tag MyID);
65+
5866
// Create a header field with an uint32_t value.
5967
NaClBitcodeHeaderField(Tag MyID, uint32_t value);
6068

@@ -78,6 +86,18 @@ class NaClBitcodeHeaderField {
7886
/// \brief Read field from Buf[BufLen].
7987
bool Read(const uint8_t *Buf, size_t BufLen);
8088

89+
/// \brief Returns string describing ID of field.
90+
static const char *IDName(Tag ID);
91+
const char *IDName() const {
92+
return IDName(ID);
93+
}
94+
95+
/// \brief Returns string describing type of field.
96+
static const char *TypeName(FieldType FType);
97+
const char *TypeName() const {
98+
return TypeName(FType);
99+
}
100+
81101
/// \brief Returns string describing field.
82102
std::string Contents() const;
83103

@@ -108,8 +128,11 @@ class NaClBitcodeHeaderField {
108128
FixedSubfield EncodeTypedID() const { return (ID << 4) | FType; }
109129
// Extract out ID and Type from a fixed subfield.
110130
void DecodeTypedID(FixedSubfield Subfield, Tag &ID, FieldType &FType) {
111-
ID = static_cast<Tag>(Subfield >> 4);
112-
FType = static_cast<FieldType>(Subfield & 0xF);
131+
FixedSubfield PossibleID = Subfield >> 4;
132+
ID = (PossibleID > kTag_MAX ? kInvalid : static_cast<Tag>(PossibleID));
133+
FixedSubfield PossibleFType = Subfield & 0xF;
134+
FType = (PossibleFType > kFieldType_MAX
135+
? kUnknownType : static_cast<FieldType>(PossibleFType));
113136
}
114137
// Combined size of the fixed subfields
115138
const static size_t kTagLenSize = 2 * sizeof(FixedSubfield);
@@ -144,6 +167,8 @@ class NaClBitcodeHeader {
144167
bool IsReadableFlag;
145168
// Defines the PNaCl version defined by the header file.
146169
uint32_t PNaClVersion;
170+
// Byte align bitcode records when nonzero.
171+
bool AlignBitcodeRecords = false;
147172

148173
public:
149174
static const int WordSize = NaClBitcodeHeaderField::WordSize;
@@ -173,7 +198,7 @@ class NaClBitcodeHeader {
173198
/// field.
174199
///
175200
/// Returns false if able to read (all of) the bitcode header.
176-
bool Read(const unsigned char *&BufPtr, const unsigned char *&BufEnd);
201+
bool Read(const unsigned char *BufPtr, const unsigned char *BufEnd);
177202

178203
// \brief Read the PNaCl bitcode header, recording the fields found
179204
// in the header. Returns false if able to read (all of) the bitcode header.
@@ -209,6 +234,9 @@ class NaClBitcodeHeader {
209234
/// \brief Returns the PNaClVersion, as defined by the header.
210235
uint32_t GetPNaClVersion() const { return PNaClVersion; }
211236

237+
/// \brief Returns if one should byte align bitcode records.
238+
bool getAlignBitcodeRecords() const { return AlignBitcodeRecords; }
239+
212240
private:
213241
// Reads and verifies the first 8 bytes of the header, consisting
214242
// of the magic number 'PEXE', and the value defining the number

include/llvm/Bitcode/NaCl/NaClBitstreamReader.h

Lines changed: 39 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#define LLVM_BITCODE_NACL_NACLBITSTREAMREADER_H
1818

1919
#include "llvm/ADT/SmallVector.h"
20+
#include "llvm/Bitcode/NaCl/NaClBitcodeHeader.h"
2021
#include "llvm/Bitcode/NaCl/NaClLLVMBitCodes.h"
2122
#include "llvm/Support/Endian.h"
2223
#include "llvm/Support/StreamingMemoryObject.h"
@@ -61,34 +62,48 @@ class NaClBitstreamReader {
6162
std::vector<NaClBitCodeAbbrev*> Abbrevs;
6263
};
6364
private:
65+
friend class NaClBitstreamCursor;
66+
6467
std::unique_ptr<MemoryObject> BitcodeBytes;
6568

6669
std::vector<BlockInfo> BlockInfoRecords;
6770

6871
/// \brief Holds the offset of the first byte after the header.
6972
size_t InitialAddress;
7073

74+
// True if filler should be added to byte align records.
75+
bool AlignBitcodeRecords = false;
76+
7177
NaClBitstreamReader(const NaClBitstreamReader&) LLVM_DELETED_FUNCTION;
7278
void operator=(const NaClBitstreamReader&) LLVM_DELETED_FUNCTION;
73-
public:
74-
NaClBitstreamReader() : InitialAddress(0) {}
7579

80+
void initFromHeader(NaClBitcodeHeader &Header) {
81+
InitialAddress = Header.getHeaderSize();
82+
AlignBitcodeRecords = Header.getAlignBitcodeRecords();
83+
}
84+
85+
public:
86+
/// Read stream from sequence of bytes [Start .. End) after parsing
87+
/// the given bitcode header.
7688
NaClBitstreamReader(const unsigned char *Start, const unsigned char *End,
77-
size_t MyInitialAddress=0) {
78-
InitialAddress = MyInitialAddress;
79-
init(Start, End);
89+
NaClBitcodeHeader &Header)
90+
: BitcodeBytes(getNonStreamedMemoryObject(Start, End)) {
91+
initFromHeader(Header);
8092
}
8193

82-
NaClBitstreamReader(MemoryObject *Bytes, size_t MyInitialAddress=0)
83-
: InitialAddress(MyInitialAddress) {
84-
BitcodeBytes.reset(Bytes);
94+
/// Read stream from Bytes, after parsing the given bitcode header.
95+
NaClBitstreamReader(MemoryObject *Bytes, NaClBitcodeHeader &Header)
96+
: BitcodeBytes(Bytes) {
97+
initFromHeader(Header);
8598
}
8699

87-
void init(const unsigned char *Start, const unsigned char *End) {
88-
assert(((End-Start) & 3) == 0 &&"Bitcode stream not a multiple of 4 bytes");
89-
BitcodeBytes.reset(getNonStreamedMemoryObject(Start, End));
100+
/// Read stream from bytes, starting at the given initial address.
101+
/// Provides simple API for unit testing.
102+
NaClBitstreamReader(MemoryObject *Bytes, size_t InitialAddress)
103+
: BitcodeBytes(Bytes), InitialAddress(InitialAddress) {
90104
}
91105

106+
// Returns the memory object that is being read.
92107
MemoryObject &getBitcodeBytes() { return *BitcodeBytes; }
93108

94109
~NaClBitstreamReader() {
@@ -516,6 +531,19 @@ class NaClBitstreamCursor {
516531
}
517532

518533
private:
534+
void SkipToByteBoundary() {
535+
unsigned BitsToSkip = BitsInCurWord % CHAR_BIT;
536+
if (BitsToSkip) {
537+
CurWord >>= BitsToSkip;
538+
BitsInCurWord -= BitsToSkip;
539+
}
540+
}
541+
542+
void SkipToByteBoundaryIfAligned() {
543+
if (BitStream->AlignBitcodeRecords)
544+
SkipToByteBoundary();
545+
}
546+
519547
void SkipToFourByteBoundary() {
520548
// If word_t is 64-bits and if we've read less than 32 bits, just dump
521549
// the bits we have up to the next 32-bit boundary.

include/llvm/Bitcode/NaCl/NaClBitstreamWriter.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include "llvm/ADT/SmallVector.h"
1919
#include "llvm/ADT/StringRef.h"
2020
#include "llvm/Bitcode/NaCl/NaClBitCodes.h"
21+
#include "llvm/Bitcode/NaCl/NaClBitcodeHeader.h"
2122
#include <vector>
2223

2324
namespace llvm {
@@ -61,6 +62,9 @@ class NaClBitstreamWriter {
6162
};
6263
std::vector<BlockInfo> BlockInfoRecords;
6364

65+
// True if filler should be added to byte align records.
66+
bool AlignBitcodeRecords = false;
67+
6468
/// AbbrevValues - Wrapper class that allows the bitstream writer to
6569
/// prefix a code to the set of values, associated with a record to
6670
/// emit, without having to destructively change the contents of
@@ -137,6 +141,10 @@ class NaClBitstreamWriter {
137141
}
138142
}
139143

144+
void initFromHeader(const NaClBitcodeHeader &Header) {
145+
AlignBitcodeRecords = Header.getAlignBitcodeRecords();
146+
}
147+
140148
/// \brief Retrieve the current position in the stream, in bits.
141149
uint64_t GetCurrentBitNo() const { return GetBufferOffset() * 8 + CurBit; }
142150

@@ -172,6 +180,17 @@ class NaClBitstreamWriter {
172180
}
173181
}
174182

183+
void flushToByte() {
184+
unsigned BitsToFlush = (32 - CurBit) % CHAR_BIT;
185+
if (BitsToFlush)
186+
Emit(0, BitsToFlush);
187+
}
188+
189+
void flushToByteIfAligned() {
190+
if (AlignBitcodeRecords)
191+
flushToByte();
192+
}
193+
175194
void FlushToWord() {
176195
if (CurBit) {
177196
WriteWord(CurValue);
@@ -416,12 +435,14 @@ class NaClBitstreamWriter {
416435
EmitVBR(static_cast<uint32_t>(Vals.size()), 6);
417436
for (unsigned i = 0, e = static_cast<unsigned>(Vals.size()); i != e; ++i)
418437
EmitVBR64(Vals[i], 6);
438+
flushToByteIfAligned();
419439
return;
420440
}
421441

422442
// combine code and values, and then emit.
423443
AbbrevValues<uintty> AbbrevVals(Code, Vals);
424444
EmitRecordWithAbbrevImpl(Abbrev, AbbrevVals);
445+
flushToByteIfAligned();
425446
}
426447

427448
//===--------------------------------------------------------------------===//
@@ -446,6 +467,7 @@ class NaClBitstreamWriter {
446467
EmitVBR64(Op.getValue(), 5);
447468
}
448469
}
470+
flushToByteIfAligned();
449471
}
450472
public:
451473

lib/Bitcode/NaCl/Analysis/NaClBitcodeAnalyzer.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -419,7 +419,7 @@ int AnalyzeBitcodeInBuffer(const std::unique_ptr<MemoryBuffer> &Buf,
419419
if (!Header.IsReadable())
420420
Error("Bitcode file is not readable");
421421

422-
NaClBitstreamReader StreamFile(BufPtr, EndBufPtr);
422+
NaClBitstreamReader StreamFile(BufPtr, EndBufPtr, Header);
423423
NaClBitstreamCursor Stream(StreamFile);
424424

425425
unsigned NumTopBlocks = 0;

lib/Bitcode/NaCl/Analysis/NaClCompress.cpp

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1161,11 +1161,16 @@ static bool analyzeBitcode(
11611161

11621162
// First read header and verify it is good.
11631163
NaClBitcodeHeader Header;
1164-
if (Header.Read(BufPtr, EndBufPtr) || !Header.IsSupported())
1164+
if (Header.Read(BufPtr, EndBufPtr))
11651165
return Error("Invalid PNaCl bitcode header");
1166+
if (!Header.IsSupported()) {
1167+
errs() << Header.Unsupported();
1168+
if (!Header.IsReadable())
1169+
return Error("Invalid PNaCl bitcode header");
1170+
}
11661171

11671172
// Create a bitstream reader to read the bitcode file.
1168-
NaClBitstreamReader StreamFile(BufPtr, EndBufPtr);
1173+
NaClBitstreamReader StreamFile(BufPtr, EndBufPtr, Header);
11691174
NaClBitstreamCursor Stream(StreamFile);
11701175

11711176
// Parse the the bitcode file.
@@ -1389,7 +1394,7 @@ static bool chooseAbbrevs(MemoryBuffer *MemBuf, BlockAbbrevsMapType &AbbrevsMap,
13891394
return Error("Invalid PNaCl bitcode header");
13901395

13911396
// Create the bitcode reader.
1392-
NaClBitstreamReader StreamFile(BufPtr, EndBufPtr);
1397+
NaClBitstreamReader StreamFile(BufPtr, EndBufPtr, Header);
13931398
NaClBitstreamCursor Stream(StreamFile);
13941399

13951400
// Set up the parser.
@@ -1587,7 +1592,7 @@ static bool copyBitcode(const NaClBitcodeCompressor::CompressFlags &Flags,
15871592
return Error("Invalid PNaCl bitcode header");
15881593

15891594
// Create the bitcode reader.
1590-
NaClBitstreamReader StreamFile(BufPtr, EndBufPtr);
1595+
NaClBitstreamReader StreamFile(BufPtr, EndBufPtr, Header);
15911596
NaClBitstreamCursor Stream(StreamFile);
15921597

15931598
// Create the bitcode writer.

lib/Bitcode/NaCl/Analysis/NaClObjDump.cpp

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3531,18 +3531,23 @@ bool NaClObjDump(MemoryBufferRef MemBuf, raw_ostream &Output,
35313531

35323532
const unsigned char *BufPtr = (const unsigned char *)MemBuf.getBufferStart();
35333533
const unsigned char *EndBufPtr = BufPtr+MemBuf.getBufferSize();
3534-
const unsigned char *HeaderPtr = BufPtr;
35353534

35363535
// Read header and verify it is good.
35373536
NaClBitcodeHeader Header;
3538-
if (Header.Read(HeaderPtr, EndBufPtr) || !Header.IsSupported()) {
3537+
if (Header.Read(BufPtr, EndBufPtr)) {
35393538
ObjDump.Error() << "Invalid PNaCl bitcode header.\n";
35403539
return true;
35413540
}
3541+
if (!Header.IsSupported()) {
3542+
ObjDump.Warning() << Header.Unsupported();
3543+
if (!Header.IsReadable()) {
3544+
ObjDump.Error() << "Invalid PNaCl bitcode header.\n";
3545+
return true;
3546+
}
3547+
}
35423548

35433549
// Create a bitstream reader to read the bitcode file.
3544-
NaClBitstreamReader InputStreamFile(BufPtr, EndBufPtr,
3545-
Header.getHeaderSize());
3550+
NaClBitstreamReader InputStreamFile(BufPtr, EndBufPtr, Header);
35463551
NaClBitstreamCursor InputStream(InputStreamFile);
35473552

35483553
// Parse the the bitcode file.

0 commit comments

Comments
 (0)