aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKarl Schimpf <kschimpf@google.com>2013-07-22 13:36:16 -0700
committerKarl Schimpf <kschimpf@google.com>2013-07-22 13:36:16 -0700
commit0b41f88a8de25db50e1a57645a6e132954a6dcd2 (patch)
tree059d73d19b2f788ce145d90015dd53b091095f28
parent208b40ed21d78767d9d1c3c855cbd2e3a3c02451 (diff)
Enable ability to have multiple PNaCl wire format versions.
Modifies PNaCl bitcode reader/writer to accept PNaClVersion=1 as supported, and all other versions are unsupported and unreadable. The PNaCl bitcode reader/writer will generate appropriate messages (including what version is unsupported if applicable). Also allows command-line option --pnacl-version for setting the PNaClVersion in the PNaCl bitcode writer. Also fixes some problems on PNaCl bitcode headers, using common support to determine when the read/written PNaCl bitcode file is valid. BUG=None R=jvoung@chromium.org Review URL: https://codereview.chromium.org/19400002
-rw-r--r--include/llvm/Bitcode/NaCl/NaClBitcodeHeader.h12
-rw-r--r--include/llvm/Bitcode/NaCl/NaClReaderWriter.h26
-rw-r--r--lib/Bitcode/NaCl/Reader/NaClBitcodeHeader.cpp6
-rw-r--r--lib/Bitcode/NaCl/Reader/NaClBitcodeReader.cpp2
-rw-r--r--lib/Bitcode/NaCl/Reader/NaClBitcodeReader.h9
-rw-r--r--lib/Bitcode/NaCl/Writer/NaClBitcodeWriter.cpp45
-rw-r--r--lib/Bitcode/NaCl/Writer/NaClValueEnumerator.cpp3
-rw-r--r--lib/Bitcode/NaCl/Writer/NaClValueEnumerator.h5
8 files changed, 76 insertions, 32 deletions
diff --git a/include/llvm/Bitcode/NaCl/NaClBitcodeHeader.h b/include/llvm/Bitcode/NaCl/NaClBitcodeHeader.h
index 8febf95564..4f5f83a17a 100644
--- a/include/llvm/Bitcode/NaCl/NaClBitcodeHeader.h
+++ b/include/llvm/Bitcode/NaCl/NaClBitcodeHeader.h
@@ -151,6 +151,12 @@ public:
/// is readable and supported.
void InstallFields();
+ /// \brief Adds a field to the list of fields in a header. Takes ownership
+ /// of fields added.
+ void push_back(NaClBitcodeHeaderField *Field) {
+ Fields.push_back(Field);
+ }
+
/// \brief Read the PNaCl bitcode header, The format of the header is:
///
/// 1) 'PEXE' - The four character sequence defining the magic number.
@@ -172,9 +178,9 @@ public:
// \brief Returns the number of bytes read to consume the header.
size_t getHeaderSize() { return HeaderSize; }
- /// \brief Returns C string describing why the header describes
- /// an unsupported PNaCl Bitcode file. Returns 0 if supported.
- const std::string Unsupported() const { return UnsupportedMessage; }
+ /// \brief Returns string describing why the header describes
+ /// an unsupported PNaCl Bitcode file.
+ const std::string &Unsupported() const { return UnsupportedMessage; }
/// \brief Returns true if supported. That is, it can be run in the
/// browser.
diff --git a/include/llvm/Bitcode/NaCl/NaClReaderWriter.h b/include/llvm/Bitcode/NaCl/NaClReaderWriter.h
index 53feb8ab86..1eb188a83e 100644
--- a/include/llvm/Bitcode/NaCl/NaClReaderWriter.h
+++ b/include/llvm/Bitcode/NaCl/NaClReaderWriter.h
@@ -30,6 +30,15 @@ namespace llvm {
/// this takes ownership of 'buffer' and returns a non-null pointer. On
/// error, this returns null, *does not* take ownership of Buffer, and fills
/// in *ErrMsg with an error description if ErrMsg is non-null.
+ ///
+ /// The AcceptSupportedOnly argument is used to decide which PNaCl versions
+ /// of the PNaCl bitcode to accept. There are three forms:
+ /// 1) Readable and supported.
+ /// 2) Readable and unsupported. Allows testing of code before becoming
+ /// supported, as well as running experiments on the bitcode format.
+ /// 3) Unreadable.
+ /// When AcceptSupportedOnly is true, only form 1 is allowed. When
+ /// AcceptSupportedOnly is false, forms 1 and 2 are allowed.
Module *getNaClLazyBitcodeModule(MemoryBuffer *Buffer,
LLVMContext &Context,
std::string *ErrMsg = 0,
@@ -39,6 +48,9 @@ namespace llvm {
/// and prepare for lazy deserialization and streaming of function bodies.
/// On error, this returns null, and fills in *ErrMsg with an error
/// description if ErrMsg is non-null.
+ ///
+ /// See getNaClLazyBitcodeModule for an explanation of argument
+ /// AcceptSupportedOnly.
Module *getNaClStreamedBitcodeModule(const std::string &name,
DataStreamer *streamer,
LLVMContext &Context,
@@ -49,6 +61,9 @@ namespace llvm {
/// returning the module. If an error occurs, this returns null and
/// fills in *ErrMsg if it is non-null. This method *never* takes
/// ownership of Buffer.
+ ///
+ /// See getNaClLazyBitcodeModule for an explanation of argument
+ /// AcceptSupportedOnly.
Module *NaClParseBitcodeFile(MemoryBuffer *Buffer, LLVMContext &Context,
std::string *ErrMsg = 0,
bool AcceptSupportedOnly = true);
@@ -57,7 +72,16 @@ namespace llvm {
/// specified raw output stream, using PNaCl wire format. For
/// streams where it matters, the given stream should be in "binary"
/// mode.
- void NaClWriteBitcodeToFile(const Module *M, raw_ostream &Out);
+ ///
+ /// The AcceptSupportedOnly argument is used to decide which PNaCl versions
+ /// of the PNaCl bitcode to generate. There are two forms:
+ /// 1) Writable and supported.
+ /// 2) Writable and unsupported. Allows testing of code before becoming
+ /// supported, as well as running experiments on the bitcode format.
+ /// When AcceptSupportedOnly is true, only form 1 is allowed. When
+ /// AcceptSupportedOnly is false, forms 1 and 2 are allowed.
+ void NaClWriteBitcodeToFile(const Module *M, raw_ostream &Out,
+ bool AcceptSupportedOnly = true);
/// isNaClBitcode - Return true if the given bytes are the magic bytes for
/// PNaCl bitcode wire format.
diff --git a/lib/Bitcode/NaCl/Reader/NaClBitcodeHeader.cpp b/lib/Bitcode/NaCl/Reader/NaClBitcodeHeader.cpp
index aa73b9cffa..2dd2af5dc3 100644
--- a/lib/Bitcode/NaCl/Reader/NaClBitcodeHeader.cpp
+++ b/lib/Bitcode/NaCl/Reader/NaClBitcodeHeader.cpp
@@ -249,8 +249,12 @@ void NaClBitcodeHeader::InstallFields() {
if (PNaClVersion != 1) {
IsSupportedFlag = false;
IsReadableFlag = false;
- UnsupportedMessage = "Unsupported Version";
UpdatedUnsupportedMessage = true;
+ UnsupportedMessage.clear();
+ raw_string_ostream UnsupportedStream(UnsupportedMessage);
+ UnsupportedStream << "Unsupported PNaCl bitcode version: "
+ << PNaClVersion << "\n";
+ UnsupportedStream.flush();
}
if (Fields.size() != 1) {
IsSupportedFlag = false;
diff --git a/lib/Bitcode/NaCl/Reader/NaClBitcodeReader.cpp b/lib/Bitcode/NaCl/Reader/NaClBitcodeReader.cpp
index 09a94c08cf..c7eb1ac683 100644
--- a/lib/Bitcode/NaCl/Reader/NaClBitcodeReader.cpp
+++ b/lib/Bitcode/NaCl/Reader/NaClBitcodeReader.cpp
@@ -1504,7 +1504,7 @@ bool NaClBitcodeReader::ParseBitcodeInto(Module *M) {
M->setDataLayout("e-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-"
"f32:32:32-f64:64:64-p:32:32:32-v128:32:32");
- if (InitStream()) return true;
+ if (InitStream()) return Error(Header.Unsupported());
// We expect a number of well-defined blocks, though we don't necessarily
// need to understand them all.
diff --git a/lib/Bitcode/NaCl/Reader/NaClBitcodeReader.h b/lib/Bitcode/NaCl/Reader/NaClBitcodeReader.h
index 3b9d8982d5..fe7b5c1e9e 100644
--- a/lib/Bitcode/NaCl/Reader/NaClBitcodeReader.h
+++ b/lib/Bitcode/NaCl/Reader/NaClBitcodeReader.h
@@ -207,15 +207,11 @@ public:
virtual bool MaterializeModule(Module *M, std::string *ErrInfo = 0);
virtual void Dematerialize(GlobalValue *GV);
- bool Error(const char *Str) {
- ErrorString = Str;
- return true;
- }
bool Error(const std::string &Str) {
ErrorString = Str;
return true;
}
- const char *getErrorString() const { return ErrorString.c_str(); }
+ const std::string &getErrorString() const { return ErrorString; }
/// @brief Main interface to parsing a bitcode buffer.
/// @returns true if an error occurred.
@@ -227,6 +223,9 @@ private:
return !(Header.IsSupported() ||
(!AcceptSupportedBitcodeOnly && Header.IsReadable()));
}
+ uint32_t GetPNaClVersion() const {
+ return Header.GetPNaClVersion();
+ }
Type *getTypeByID(unsigned ID);
// Returns the value associated with ID. The value must already exist,
// or a forward referenced value created by getOrCreateFnVaueByID.
diff --git a/lib/Bitcode/NaCl/Writer/NaClBitcodeWriter.cpp b/lib/Bitcode/NaCl/Writer/NaClBitcodeWriter.cpp
index 223d1bf416..e41ef6062c 100644
--- a/lib/Bitcode/NaCl/Writer/NaClBitcodeWriter.cpp
+++ b/lib/Bitcode/NaCl/Writer/NaClBitcodeWriter.cpp
@@ -35,6 +35,11 @@
#include <map>
using namespace llvm;
+static cl::opt<unsigned>
+PNaClVersion("pnacl-version",
+ cl::desc("Specify PNaCl bitcode version to write"),
+ cl::init(1));
+
/// These are manifest constants used by the bitcode writer. They do
/// not need to be kept in sync with the reader, but need to be
/// consistent within this file.
@@ -1635,7 +1640,7 @@ static void WriteModule(const Module *M, NaClBitstreamWriter &Stream) {
Stream.EmitRecord(naclbitc::MODULE_CODE_VERSION, Vals);
// Analyze the module, enumerating globals, functions, etc.
- NaClValueEnumerator VE(M);
+ NaClValueEnumerator VE(M, PNaClVersion);
// Emit blockinfo, which defines the standard abbreviations etc.
WriteBlockInfo(VE, Stream);
@@ -1666,9 +1671,9 @@ static void WriteModule(const Module *M, NaClBitstreamWriter &Stream) {
// 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,
+// Write out the given Header to the bitstream.
+static void WriteHeader(
+ const NaClBitcodeHeader &Header,
NaClBitstreamWriter& Stream) {
// Emit placeholder for number of bytes used to hold header fields.
// This value is necessary so that the streamable reader can preallocate
@@ -1676,17 +1681,16 @@ static void WriteHeaderFields(
Stream.Emit(0, naclbitc::BlockSizeWidth);
unsigned BytesForHeader = 0;
- unsigned NumberFields = Fields.size();
+ unsigned NumberFields = Header.NumberFields();
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))
+ for (unsigned F = 0; F < NumberFields; ++F) {
+ NaClBitcodeHeaderField *Field = Header.GetField(F);
+ if (!Field->Write(Buffer, kMaxVariableFieldSize))
report_fatal_error("Header field too big to generate");
- size_t limit = (*Iter)->GetTotalSize();
+ size_t limit = Field->GetTotalSize();
for (size_t i = 0; i < limit; i++) {
Stream.Emit(Buffer[i], 8);
}
@@ -1702,12 +1706,10 @@ static void WriteHeaderFields(
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) {
+void llvm::NaClWriteBitcodeToFile(const Module *M, raw_ostream &Out,
+ bool AcceptSupportedOnly) {
SmallVector<char, 0> Buffer;
Buffer.reserve(256*1024);
@@ -1721,13 +1723,18 @@ void llvm::NaClWriteBitcodeToFile(const Module *M, raw_ostream &Out) {
Stream.Emit((unsigned)'X', 8);
Stream.Emit((unsigned)'E', 8);
- // Collect header fields to add.
+ // Define header and install into stream.
{
- std::vector<NaClBitcodeHeaderField*> HeaderFields;
- HeaderFields.push_back(
+ NaClBitcodeHeader Header;
+ Header.push_back(
new NaClBitcodeHeaderField(NaClBitcodeHeaderField::kPNaClVersion,
- kPNaClVersion));
- WriteHeaderFields(HeaderFields, Stream);
+ PNaClVersion));
+ Header.InstallFields();
+ if (!(Header.IsSupported() ||
+ (!AcceptSupportedOnly && Header.IsReadable()))) {
+ report_fatal_error(Header.Unsupported());
+ }
+ WriteHeader(Header, Stream);
}
// Emit the module.
diff --git a/lib/Bitcode/NaCl/Writer/NaClValueEnumerator.cpp b/lib/Bitcode/NaCl/Writer/NaClValueEnumerator.cpp
index 5e2484a3f3..01b4ff8df5 100644
--- a/lib/Bitcode/NaCl/Writer/NaClValueEnumerator.cpp
+++ b/lib/Bitcode/NaCl/Writer/NaClValueEnumerator.cpp
@@ -32,7 +32,8 @@ static bool isIntOrIntVectorValue(const std::pair<const Value*, unsigned> &V) {
}
/// NaClValueEnumerator - Enumerate module-level information.
-NaClValueEnumerator::NaClValueEnumerator(const Module *M) {
+NaClValueEnumerator::NaClValueEnumerator(const Module *M, uint32_t PNaClVersion)
+ : PNaClVersion(PNaClVersion) {
// Create map for counting frequency of types, and set field
// TypeCountMap accordingly. Note: Pointer field TypeCountMap is
// used to deal with the fact that types are added through various
diff --git a/lib/Bitcode/NaCl/Writer/NaClValueEnumerator.h b/lib/Bitcode/NaCl/Writer/NaClValueEnumerator.h
index e98a091ba8..21bbb2fb76 100644
--- a/lib/Bitcode/NaCl/Writer/NaClValueEnumerator.h
+++ b/lib/Bitcode/NaCl/Writer/NaClValueEnumerator.h
@@ -84,10 +84,13 @@ private:
// The number of global variable IDs defined in the bitcode file.
unsigned NumGlobalVarIDs;
+ // The version of PNaCl bitcode to generate.
+ uint32_t PNaClVersion;
+
NaClValueEnumerator(const NaClValueEnumerator &) LLVM_DELETED_FUNCTION;
void operator=(const NaClValueEnumerator &) LLVM_DELETED_FUNCTION;
public:
- NaClValueEnumerator(const Module *M);
+ NaClValueEnumerator(const Module *M, uint32_t PNaClVersion);
void dump() const;
void print(raw_ostream &OS, const ValueMapType &Map, const char *Name) const;