aboutsummaryrefslogtreecommitdiff
path: root/lib/Bitcode
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Bitcode')
-rw-r--r--lib/Bitcode/CMakeLists.txt1
-rw-r--r--lib/Bitcode/LLVMBuild.txt2
-rw-r--r--lib/Bitcode/Makefile2
-rw-r--r--lib/Bitcode/NaCl/CMakeLists.txt2
-rw-r--r--lib/Bitcode/NaCl/LLVMBuild.txt24
-rw-r--r--lib/Bitcode/NaCl/Makefile14
-rw-r--r--lib/Bitcode/NaCl/Reader/CMakeLists.txt7
-rw-r--r--lib/Bitcode/NaCl/Reader/LLVMBuild.txt22
-rw-r--r--lib/Bitcode/NaCl/Reader/Makefile15
-rw-r--r--lib/Bitcode/NaCl/Reader/NaClBitcodeHeader.cpp261
-rw-r--r--lib/Bitcode/NaCl/Reader/NaClBitcodeReader.cpp2644
-rw-r--r--lib/Bitcode/NaCl/Reader/NaClBitcodeReader.h297
-rw-r--r--lib/Bitcode/NaCl/Reader/NaClBitstreamReader.cpp374
-rw-r--r--lib/Bitcode/NaCl/Writer/CMakeLists.txt5
-rw-r--r--lib/Bitcode/NaCl/Writer/LLVMBuild.txt22
-rw-r--r--lib/Bitcode/NaCl/Writer/Makefile15
-rw-r--r--lib/Bitcode/NaCl/Writer/NaClBitcodeWriter.cpp1790
-rw-r--r--lib/Bitcode/NaCl/Writer/NaClValueEnumerator.cpp443
-rw-r--r--lib/Bitcode/NaCl/Writer/NaClValueEnumerator.h157
-rw-r--r--lib/Bitcode/Reader/BitcodeReader.cpp21
20 files changed, 6116 insertions, 2 deletions
diff --git a/lib/Bitcode/CMakeLists.txt b/lib/Bitcode/CMakeLists.txt
index ff7e290cad..8969ec83f5 100644
--- a/lib/Bitcode/CMakeLists.txt
+++ b/lib/Bitcode/CMakeLists.txt
@@ -1,2 +1,3 @@
add_subdirectory(Reader)
add_subdirectory(Writer)
+add_subdirectory(NaCl)
diff --git a/lib/Bitcode/LLVMBuild.txt b/lib/Bitcode/LLVMBuild.txt
index af9936bbe8..415a33dfdf 100644
--- a/lib/Bitcode/LLVMBuild.txt
+++ b/lib/Bitcode/LLVMBuild.txt
@@ -16,7 +16,7 @@
;===------------------------------------------------------------------------===;
[common]
-subdirectories = Reader Writer
+subdirectories = Reader Writer NaCl
[component_0]
type = Group
diff --git a/lib/Bitcode/Makefile b/lib/Bitcode/Makefile
index 2d6b5ad1fe..cbaab3578c 100644
--- a/lib/Bitcode/Makefile
+++ b/lib/Bitcode/Makefile
@@ -8,7 +8,7 @@
##===----------------------------------------------------------------------===##
LEVEL = ../..
-PARALLEL_DIRS = Reader Writer
+PARALLEL_DIRS = Reader Writer NaCl
include $(LEVEL)/Makefile.common
diff --git a/lib/Bitcode/NaCl/CMakeLists.txt b/lib/Bitcode/NaCl/CMakeLists.txt
new file mode 100644
index 0000000000..5a8b272bef
--- /dev/null
+++ b/lib/Bitcode/NaCl/CMakeLists.txt
@@ -0,0 +1,2 @@
+add_subdirectory(Writer)
+add_subdirectory(Reader)
diff --git a/lib/Bitcode/NaCl/LLVMBuild.txt b/lib/Bitcode/NaCl/LLVMBuild.txt
new file mode 100644
index 0000000000..a29928d2a0
--- /dev/null
+++ b/lib/Bitcode/NaCl/LLVMBuild.txt
@@ -0,0 +1,24 @@
+;===- ./lib/Bitcode/NaCl/LLVMBuild.txt ------------------------*- Conf -*--===;
+;
+; The LLVM Compiler Infrastructure
+;
+; This file is distributed under the University of Illinois Open Source
+; License. See LICENSE.TXT for details.
+;
+;===------------------------------------------------------------------------===;
+;
+; This is an LLVMBuild description file for the components in this subdirectory.
+;
+; For more information on the LLVMBuild system, please see:
+;
+; http://llvm.org/docs/LLVMBuild.html
+;
+;===------------------------------------------------------------------------===;
+
+[common]
+subdirectories = Writer Reader
+
+[component_0]
+type = Group
+name = NaClBitcode
+parent = Bitcode
diff --git a/lib/Bitcode/NaCl/Makefile b/lib/Bitcode/NaCl/Makefile
new file mode 100644
index 0000000000..5bbbc351a1
--- /dev/null
+++ b/lib/Bitcode/NaCl/Makefile
@@ -0,0 +1,14 @@
+##===- lib/Bitcode/NaCl/Makefile ---------------------------*- Makefile -*-===##
+#
+# The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+##===----------------------------------------------------------------------===##
+
+LEVEL = ../../..
+PARALLEL_DIRS = Writer Reader
+
+include $(LEVEL)/Makefile.common
+
diff --git a/lib/Bitcode/NaCl/Reader/CMakeLists.txt b/lib/Bitcode/NaCl/Reader/CMakeLists.txt
new file mode 100644
index 0000000000..9e4de723c1
--- /dev/null
+++ b/lib/Bitcode/NaCl/Reader/CMakeLists.txt
@@ -0,0 +1,7 @@
+add_llvm_library(LLVMNaClBitReader
+ NaClBitcodeHeader.cpp
+ NaClBitcodeReader.cpp
+ NaClBitstreamReader.cpp
+ )
+
+add_dependencies(LLVMNaClBitReader intrinsics_gen)
diff --git a/lib/Bitcode/NaCl/Reader/LLVMBuild.txt b/lib/Bitcode/NaCl/Reader/LLVMBuild.txt
new file mode 100644
index 0000000000..acf354f5b5
--- /dev/null
+++ b/lib/Bitcode/NaCl/Reader/LLVMBuild.txt
@@ -0,0 +1,22 @@
+;===- ./lib/Bitcode/NaClReader/LLVMBuild.txt -------------------*- Conf -*--===;
+;
+; The LLVM Compiler Infrastructure
+;
+; This file is distributed under the University of Illinois Open Source
+; License. See LICENSE.TXT for details.
+;
+;===------------------------------------------------------------------------===;
+;
+; This is an LLVMBuild description file for the components in this subdirectory.
+;
+; For more information on the LLVMBuild system, please see:
+;
+; http://llvm.org/docs/LLVMBuild.html
+;
+;===------------------------------------------------------------------------===;
+
+[component_0]
+type = Library
+name = NaClBitReader
+parent = NaClBitcode
+required_libraries = Core Support
diff --git a/lib/Bitcode/NaCl/Reader/Makefile b/lib/Bitcode/NaCl/Reader/Makefile
new file mode 100644
index 0000000000..92c75c29a4
--- /dev/null
+++ b/lib/Bitcode/NaCl/Reader/Makefile
@@ -0,0 +1,15 @@
+##===- lib/Bitcode/NaCl/Reader/Makefile --------------------*- Makefile -*-===##
+#
+# The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+##===----------------------------------------------------------------------===##
+
+LEVEL = ../../../..
+LIBRARYNAME = LLVMNaClBitReader
+BUILD_ARCHIVE = 1
+
+include $(LEVEL)/Makefile.common
+
diff --git a/lib/Bitcode/NaCl/Reader/NaClBitcodeHeader.cpp b/lib/Bitcode/NaCl/Reader/NaClBitcodeHeader.cpp
new file mode 100644
index 0000000000..aa73b9cffa
--- /dev/null
+++ b/lib/Bitcode/NaCl/Reader/NaClBitcodeHeader.cpp
@@ -0,0 +1,261 @@
+//===- NaClBitcodeHeader.cpp ----------------------------------------------===//
+// PNaCl bitcode header reader.
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Bitcode/NaCl/NaClBitcodeHeader.h"
+#include "llvm/Bitcode/NaCl/NaClReaderWriter.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/Format.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/StreamableMemoryObject.h"
+
+#include <limits>
+#include <cstring>
+#include <iomanip>
+
+using namespace llvm;
+
+NaClBitcodeHeaderField::NaClBitcodeHeaderField()
+ : ID(kInvalid), FType(kBufferType), Len(0), Data(0) {}
+
+NaClBitcodeHeaderField::NaClBitcodeHeaderField(Tag MyID, uint32_t MyValue)
+ : ID(MyID), FType(kUInt32Type), Len(4), Data(new uint8_t[4]) {
+ Data[0] = static_cast<uint8_t>(MyValue & 0xFF);
+ Data[1] = static_cast<uint8_t>((MyValue >> 8) & 0xFF);
+ Data[2] = static_cast<uint8_t>((MyValue >> 16) & 0xFF);
+ Data[3] = static_cast<uint8_t>((MyValue >> 24) & 0xFF);
+}
+
+uint32_t NaClBitcodeHeaderField::GetUInt32Value() const {
+ assert(FType == kUInt32Type && "Header field must be uint32");
+ return static_cast<uint32_t>(Data[0]) |
+ (static_cast<uint32_t>(Data[1]) << 8) |
+ (static_cast<uint32_t>(Data[2]) << 16) |
+ (static_cast<uint32_t>(Data[2]) << 24);
+}
+
+NaClBitcodeHeaderField::NaClBitcodeHeaderField(Tag MyID, size_t MyLen,
+ uint8_t *MyData)
+ : ID(MyID), FType(kBufferType), Len(MyLen), Data(new uint8_t[MyLen]) {
+ for (size_t i = 0; i < MyLen; ++i) {
+ Data[i] = MyData[i];
+ }
+}
+
+bool NaClBitcodeHeaderField::Write(uint8_t *Buf, size_t BufLen) const {
+ size_t FieldsLen = kTagLenSize + Len;
+ size_t PadLen = (WordSize - (FieldsLen & (WordSize-1))) & (WordSize-1);
+ // Ensure buffer is large enough and that length can be represented
+ // in 32 bits
+ if (BufLen < FieldsLen + PadLen ||
+ Len > std::numeric_limits<FixedSubfield>::max())
+ return false;
+
+ WriteFixedSubfield(EncodeTypedID(), Buf);
+ WriteFixedSubfield(static_cast<FixedSubfield>(Len),
+ Buf + sizeof(FixedSubfield));
+ memcpy(Buf + kTagLenSize, Data, Len);
+ // Pad out to word alignment
+ if (PadLen) {
+ memset(Buf + FieldsLen, 0, PadLen);
+ }
+ return true;
+}
+
+bool NaClBitcodeHeaderField::Read(const uint8_t *Buf, size_t BufLen) {
+ if (BufLen < kTagLenSize)
+ return false;
+ FixedSubfield IdField;
+ ReadFixedSubfield(&IdField, Buf);
+ FixedSubfield LengthField;
+ ReadFixedSubfield(&LengthField, Buf + sizeof(FixedSubfield));
+ size_t Length = static_cast<size_t>(LengthField);
+ if (BufLen < kTagLenSize + Length)
+ return false;
+ if (Len != Length) {
+ // Need to reallocate data buffer.
+ if (Data)
+ delete[] Data;
+ Data = new uint8_t[Length];
+ }
+ Len = Length;
+ DecodeTypedID(IdField, ID, FType);
+ memcpy(Data, Buf + kTagLenSize, Len);
+ return true;
+}
+
+std::string NaClBitcodeHeaderField::Contents() const {
+ std::string buffer;
+ raw_string_ostream ss(buffer);
+ switch (ID) {
+ case kPNaClVersion:
+ ss << "PNaCl Version";
+ break;
+ case kInvalid:
+ ss << "Invalid";
+ break;
+ default:
+ report_fatal_error("PNaCl bitcode file contains unknown field tag");
+ }
+ ss << ": ";
+ switch (FType) {
+ case kUInt32Type:
+ ss << GetUInt32Value();
+ break;
+ case kBufferType:
+ ss << "[";
+ for (size_t i = 0; i < Len; ++i) {
+ if (i)
+ ss << " ";
+ ss << format("%02x", Data[i]);
+ }
+ ss << "]";
+ break;
+ default:
+ report_fatal_error("PNaCL bitcode file contains unknown field type");
+ }
+ return ss.str();
+}
+
+NaClBitcodeHeader::NaClBitcodeHeader()
+ : HeaderSize(0), UnsupportedMessage(), IsSupportedFlag(false),
+ IsReadableFlag(false), PNaClVersion(0) {}
+
+NaClBitcodeHeader::~NaClBitcodeHeader() {
+ for (std::vector<NaClBitcodeHeaderField *>::const_iterator
+ Iter = Fields.begin(),
+ IterEnd = Fields.end();
+ Iter != IterEnd; ++Iter) {
+ delete *Iter;
+ }
+}
+
+bool NaClBitcodeHeader::ReadPrefix(const unsigned char *BufPtr,
+ const unsigned char *BufEnd,
+ unsigned &NumFields, unsigned &NumBytes) {
+ // Must contain PEXE.
+ if (!isNaClBitcode(BufPtr, BufEnd))
+ return true;
+ BufPtr += WordSize;
+
+ // Read #Fields and number of bytes needed for the header.
+ if (BufPtr + WordSize > BufEnd)
+ return true;
+ NumFields = static_cast<unsigned>(BufPtr[0]) |
+ (static_cast<unsigned>(BufPtr[1]) << 8);
+ NumBytes = static_cast<unsigned>(BufPtr[2]) |
+ (static_cast<unsigned>(BufPtr[3]) << 8);
+ BufPtr += WordSize;
+ return false;
+}
+
+bool NaClBitcodeHeader::ReadFields(const unsigned char *BufPtr,
+ const unsigned char *BufEnd,
+ unsigned NumFields, unsigned NumBytes) {
+ HeaderSize = NumBytes + (2 * WordSize);
+
+ // Read in each field.
+ for (size_t i = 0; i < NumFields; ++i) {
+ NaClBitcodeHeaderField *Field = new NaClBitcodeHeaderField();
+ Fields.push_back(Field);
+ if (!Field->Read(BufPtr, BufEnd - BufPtr))
+ return true;
+ size_t FieldSize = Field->GetTotalSize();
+ BufPtr += FieldSize;
+ }
+ return false;
+}
+
+bool NaClBitcodeHeader::Read(const unsigned char *&BufPtr,
+ const unsigned char *&BufEnd) {
+ unsigned NumFields;
+ unsigned NumBytes;
+ if (ReadPrefix(BufPtr, BufEnd, NumFields, NumBytes))
+ return true;
+ BufPtr += 2 * WordSize;
+
+ if (ReadFields(BufPtr, BufEnd, NumFields, NumBytes))
+ return true;
+ BufPtr += NumBytes;
+ InstallFields();
+ return false;
+}
+
+bool NaClBitcodeHeader::Read(StreamableMemoryObject *Bytes) {
+ unsigned NumFields;
+ unsigned NumBytes;
+ {
+ unsigned char Buffer[2 * WordSize];
+ if (Bytes->readBytes(0, sizeof(Buffer), Buffer, NULL) ||
+ ReadPrefix(Buffer, Buffer + sizeof(Buffer), NumFields, NumBytes))
+ return true;
+ }
+ uint8_t *Header = new uint8_t[NumBytes];
+ bool failed =
+ Bytes->readBytes(2 * WordSize, NumBytes, Header, NULL) ||
+ ReadFields(Header, Header + NumBytes, NumFields, NumBytes);
+ delete[] Header;
+ if (failed)
+ return true;
+ InstallFields();
+ return false;
+}
+
+NaClBitcodeHeaderField *
+NaClBitcodeHeader::GetTaggedField(NaClBitcodeHeaderField::Tag ID) const {
+ for (std::vector<NaClBitcodeHeaderField *>::const_iterator
+ Iter = Fields.begin(),
+ IterEnd = Fields.end();
+ Iter != IterEnd; ++Iter) {
+ if ((*Iter)->GetID() == ID) {
+ return *Iter;
+ }
+ }
+ return 0;
+}
+
+NaClBitcodeHeaderField *NaClBitcodeHeader::GetField(size_t index) const {
+ if (index >= Fields.size())
+ return 0;
+ return Fields[index];
+}
+
+NaClBitcodeHeaderField *GetPNaClVersionPtr(NaClBitcodeHeader *Header) {
+ if (NaClBitcodeHeaderField *Version =
+ Header->GetTaggedField(NaClBitcodeHeaderField::kPNaClVersion)) {
+ if (Version->GetType() == NaClBitcodeHeaderField::kUInt32Type) {
+ return Version;
+ }
+ }
+ return 0;
+}
+
+void NaClBitcodeHeader::InstallFields() {
+ // Assume supported until contradicted.
+ bool UpdatedUnsupportedMessage = false;
+ IsSupportedFlag = true;
+ IsReadableFlag = true;
+ UnsupportedMessage = "Supported";
+ PNaClVersion = 0;
+ if (NaClBitcodeHeaderField *Version = GetPNaClVersionPtr(this)) {
+ PNaClVersion = Version->GetUInt32Value();
+ }
+ if (PNaClVersion != 1) {
+ IsSupportedFlag = false;
+ IsReadableFlag = false;
+ UnsupportedMessage = "Unsupported Version";
+ UpdatedUnsupportedMessage = true;
+ }
+ if (Fields.size() != 1) {
+ IsSupportedFlag = false;
+ IsReadableFlag = false;
+ if (!UpdatedUnsupportedMessage)
+ UnsupportedMessage = "Unknown header field(s) found";
+ }
+}
diff --git a/lib/Bitcode/NaCl/Reader/NaClBitcodeReader.cpp b/lib/Bitcode/NaCl/Reader/NaClBitcodeReader.cpp
new file mode 100644
index 0000000000..5f14a639ba
--- /dev/null
+++ b/lib/Bitcode/NaCl/Reader/NaClBitcodeReader.cpp
@@ -0,0 +1,2644 @@
+//===- NaClBitcodeReader.cpp ----------------------------------------------===//
+// Internal NaClBitcodeReader implementation
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#define DEBUG_TYPE "NaClBitcodeReader"
+
+#include "llvm/Bitcode/NaCl/NaClReaderWriter.h"
+#include "NaClBitcodeReader.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/AutoUpgrade.h"
+#include "llvm/IR/Constants.h"
+#include "llvm/IR/DerivedTypes.h"
+#include "llvm/IR/InlineAsm.h"
+#include "llvm/IR/IntrinsicInst.h"
+#include "llvm/IR/Module.h"
+#include "llvm/IR/OperandTraits.h"
+#include "llvm/IR/Operator.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/DataStream.h"
+#include "llvm/Support/MathExtras.h"
+#include "llvm/Support/MemoryBuffer.h"
+using namespace llvm;
+
+enum {
+ SWITCH_INST_MAGIC = 0x4B5 // May 2012 => 1205 => Hex
+};
+
+void NaClBitcodeReader::materializeForwardReferencedFunctions() {
+ while (!BlockAddrFwdRefs.empty()) {
+ Function *F = BlockAddrFwdRefs.begin()->first;
+ F->Materialize();
+ }
+}
+
+void NaClBitcodeReader::FreeState() {
+ if (BufferOwned)
+ delete Buffer;
+ Buffer = 0;
+ std::vector<Type*>().swap(TypeList);
+ ValueList.clear();
+
+ std::vector<BasicBlock*>().swap(FunctionBBs);
+ std::vector<Function*>().swap(FunctionsWithBodies);
+ DeferredFunctionInfo.clear();
+
+ assert(BlockAddrFwdRefs.empty() && "Unresolved blockaddress fwd references");
+}
+
+//===----------------------------------------------------------------------===//
+// Helper functions to implement forward reference resolution, etc.
+//===----------------------------------------------------------------------===//
+
+/// ConvertToString - Convert a string from a record into an std::string, return
+/// true on failure.
+template<typename StrTy>
+static bool ConvertToString(ArrayRef<uint64_t> Record, unsigned Idx,
+ StrTy &Result) {
+ if (Idx > Record.size())
+ return true;
+
+ for (unsigned i = Idx, e = Record.size(); i != e; ++i)
+ Result += (char)Record[i];
+ return false;
+}
+
+static GlobalValue::LinkageTypes GetDecodedLinkage(unsigned Val) {
+ switch (Val) {
+ default: // Map unknown/new linkages to external
+ case 0: return GlobalValue::ExternalLinkage;
+ case 1: return GlobalValue::WeakAnyLinkage;
+ case 2: return GlobalValue::AppendingLinkage;
+ case 3: return GlobalValue::InternalLinkage;
+ case 4: return GlobalValue::LinkOnceAnyLinkage;
+ case 5: return GlobalValue::DLLImportLinkage;
+ case 6: return GlobalValue::DLLExportLinkage;
+ case 7: return GlobalValue::ExternalWeakLinkage;
+ case 8: return GlobalValue::CommonLinkage;
+ case 9: return GlobalValue::PrivateLinkage;
+ case 10: return GlobalValue::WeakODRLinkage;
+ case 11: return GlobalValue::LinkOnceODRLinkage;
+ case 12: return GlobalValue::AvailableExternallyLinkage;
+ case 13: return GlobalValue::LinkerPrivateLinkage;
+ case 14: return GlobalValue::LinkerPrivateWeakLinkage;
+ case 15: return GlobalValue::LinkOnceODRAutoHideLinkage;
+ }
+}
+
+static GlobalValue::VisibilityTypes GetDecodedVisibility(unsigned Val) {
+ switch (Val) {
+ default: // Map unknown visibilities to default.
+ case 0: return GlobalValue::DefaultVisibility;
+ case 1: return GlobalValue::HiddenVisibility;
+ case 2: return GlobalValue::ProtectedVisibility;
+ }
+}
+
+static int GetDecodedCastOpcode(unsigned Val) {
+ switch (Val) {
+ default: return -1;
+ case naclbitc::CAST_TRUNC : return Instruction::Trunc;
+ case naclbitc::CAST_ZEXT : return Instruction::ZExt;
+ case naclbitc::CAST_SEXT : return Instruction::SExt;
+ case naclbitc::CAST_FPTOUI : return Instruction::FPToUI;
+ case naclbitc::CAST_FPTOSI : return Instruction::FPToSI;
+ case naclbitc::CAST_UITOFP : return Instruction::UIToFP;
+ case naclbitc::CAST_SITOFP : return Instruction::SIToFP;
+ case naclbitc::CAST_FPTRUNC : return Instruction::FPTrunc;
+ case naclbitc::CAST_FPEXT : return Instruction::FPExt;
+ case naclbitc::CAST_PTRTOINT: return Instruction::PtrToInt;
+ case naclbitc::CAST_INTTOPTR: return Instruction::IntToPtr;
+ case naclbitc::CAST_BITCAST : return Instruction::BitCast;
+ }
+}
+static int GetDecodedBinaryOpcode(unsigned Val, Type *Ty) {
+ switch (Val) {
+ default: return -1;
+ case naclbitc::BINOP_ADD:
+ return Ty->isFPOrFPVectorTy() ? Instruction::FAdd : Instruction::Add;
+ case naclbitc::BINOP_SUB:
+ return Ty->isFPOrFPVectorTy() ? Instruction::FSub : Instruction::Sub;
+ case naclbitc::BINOP_MUL:
+ return Ty->isFPOrFPVectorTy() ? Instruction::FMul : Instruction::Mul;
+ case naclbitc::BINOP_UDIV: return Instruction::UDiv;
+ case naclbitc::BINOP_SDIV:
+ return Ty->isFPOrFPVectorTy() ? Instruction::FDiv : Instruction::SDiv;
+ case naclbitc::BINOP_UREM: return Instruction::URem;
+ case naclbitc::BINOP_SREM:
+ return Ty->isFPOrFPVectorTy() ? Instruction::FRem : Instruction::SRem;
+ case naclbitc::BINOP_SHL: return Instruction::Shl;
+ case naclbitc::BINOP_LSHR: return Instruction::LShr;
+ case naclbitc::BINOP_ASHR: return Instruction::AShr;
+ case naclbitc::BINOP_AND: return Instruction::And;
+ case naclbitc::BINOP_OR: return Instruction::Or;
+ case naclbitc::BINOP_XOR: return Instruction::Xor;
+ }
+}
+
+static AtomicRMWInst::BinOp GetDecodedRMWOperation(unsigned Val) {
+ switch (Val) {
+ default: return AtomicRMWInst::BAD_BINOP;
+ case naclbitc::RMW_XCHG: return AtomicRMWInst::Xchg;
+ case naclbitc::RMW_ADD: return AtomicRMWInst::Add;
+ case naclbitc::RMW_SUB: return AtomicRMWInst::Sub;
+ case naclbitc::RMW_AND: return AtomicRMWInst::And;
+ case naclbitc::RMW_NAND: return AtomicRMWInst::Nand;
+ case naclbitc::RMW_OR: return AtomicRMWInst::Or;
+ case naclbitc::RMW_XOR: return AtomicRMWInst::Xor;
+ case naclbitc::RMW_MAX: return AtomicRMWInst::Max;
+ case naclbitc::RMW_MIN: return AtomicRMWInst::Min;
+ case naclbitc::RMW_UMAX: return AtomicRMWInst::UMax;
+ case naclbitc::RMW_UMIN: return AtomicRMWInst::UMin;
+ }
+}
+
+static AtomicOrdering GetDecodedOrdering(unsigned Val) {
+ switch (Val) {
+ case naclbitc::ORDERING_NOTATOMIC: return NotAtomic;
+ case naclbitc::ORDERING_UNORDERED: return Unordered;
+ case naclbitc::ORDERING_MONOTONIC: return Monotonic;
+ case naclbitc::ORDERING_ACQUIRE: return Acquire;
+ case naclbitc::ORDERING_RELEASE: return Release;
+ case naclbitc::ORDERING_ACQREL: return AcquireRelease;
+ default: // Map unknown orderings to sequentially-consistent.
+ case naclbitc::ORDERING_SEQCST: return SequentiallyConsistent;
+ }
+}
+
+static SynchronizationScope GetDecodedSynchScope(unsigned Val) {
+ switch (Val) {
+ case naclbitc::SYNCHSCOPE_SINGLETHREAD: return SingleThread;
+ default: // Map unknown scopes to cross-thread.
+ case naclbitc::SYNCHSCOPE_CROSSTHREAD: return CrossThread;
+ }
+}
+
+static CallingConv::ID GetDecodedCallingConv(unsigned Val) {
+ switch (Val) {
+ default:
+ report_fatal_error("PNaCl bitcode contains invalid calling conventions.");
+ case naclbitc::C_CallingConv: return CallingConv::C;
+ }
+}
+
+namespace llvm {
+namespace {
+ /// @brief A class for maintaining the slot number definition
+ /// as a placeholder for the actual definition for forward constants defs.
+ class ConstantPlaceHolder : public ConstantExpr {
+ void operator=(const ConstantPlaceHolder &) LLVM_DELETED_FUNCTION;
+ public:
+ // allocate space for exactly one operand
+ void *operator new(size_t s) {
+ return User::operator new(s, 1);
+ }
+ explicit ConstantPlaceHolder(Type *Ty, LLVMContext& Context)
+ : ConstantExpr(Ty, Instruction::UserOp1, &Op<0>(), 1) {
+ Op<0>() = UndefValue::get(Type::getInt32Ty(Context));
+ }
+
+ /// @brief Methods to support type inquiry through isa, cast, and dyn_cast.
+ static bool classof(const Value *V) {
+ return isa<ConstantExpr>(V) &&
+ cast<ConstantExpr>(V)->getOpcode() == Instruction::UserOp1;
+ }
+
+
+ /// Provide fast operand accessors
+ //DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
+ };
+}
+
+// FIXME: can we inherit this from ConstantExpr?
+template <>
+struct OperandTraits<ConstantPlaceHolder> :
+ public FixedNumOperandTraits<ConstantPlaceHolder, 1> {
+};
+}
+
+
+void NaClBitcodeReaderValueList::AssignValue(Value *V, unsigned Idx) {
+ assert(V);
+ if (Idx == size()) {
+ push_back(V);
+ return;
+ }
+
+ if (Idx >= size())
+ resize(Idx+1);
+
+ WeakVH &OldV = ValuePtrs[Idx];
+ if (OldV == 0) {
+ OldV = V;
+ return;
+ }
+
+ // Handle constants and non-constants (e.g. instrs) differently for
+ // efficiency.
+ if (Constant *PHC = dyn_cast<Constant>(&*OldV)) {
+ ResolveConstants.push_back(std::make_pair(PHC, Idx));
+ OldV = V;
+ } else {
+ // If there was a forward reference to this value, replace it.
+ Value *PrevVal = OldV;
+ OldV->replaceAllUsesWith(V);
+ delete PrevVal;
+ }
+}
+
+void NaClBitcodeReaderValueList::AssignGlobalVar(GlobalVariable *GV,
+ unsigned Idx) {
+ assert(GV);
+
+ if (Idx == size()) {
+ push_back(GV);
+ return;
+ }
+
+ if (Idx >= size())
+ resize(Idx+1);
+
+ WeakVH &OldV = ValuePtrs[Idx];
+ if (OldV == 0) {
+ OldV = GV;
+ return;
+ }
+
+ // If there was a forward reference to this value, replace it.
+ Value *PrevVal = OldV;
+ GlobalVariable *Placeholder = cast<GlobalVariable>(PrevVal);
+ Placeholder->replaceAllUsesWith(
+ ConstantExpr::getBitCast(GV, Placeholder->getType()));
+ Placeholder->eraseFromParent();
+ ValuePtrs[Idx] = GV;
+}
+
+Constant *NaClBitcodeReaderValueList::getConstantFwdRef(unsigned Idx,
+ Type *Ty) {
+ if (Idx >= size())
+ resize(Idx + 1);
+
+ if (Value *V = ValuePtrs[Idx]) {
+ assert(Ty == V->getType() && "Type mismatch in constant table!");
+ return cast<Constant>(V);
+ }
+
+ // Create and return a placeholder, which will later be RAUW'd.
+ Constant *C = new ConstantPlaceHolder(Ty, Context);
+ ValuePtrs[Idx] = C;
+ return C;
+}
+
+Value *NaClBitcodeReaderValueList::getValueFwdRef(unsigned Idx) {
+ if (Idx >= size())
+ return 0;
+
+ if (Value *V = ValuePtrs[Idx])
+ return V;
+
+ return 0;
+}
+
+bool NaClBitcodeReaderValueList::createValueFwdRef(unsigned Idx, Type *Ty) {
+ if (Idx >= size())
+ resize(Idx + 1);
+
+ // Return an error if this a duplicate definition of Idx.
+ if (ValuePtrs[Idx])
+ return true;
+
+ // No type specified, must be invalid reference.
+ if (Ty == 0)
+ return true;
+
+ // Create a placeholder, which will later be RAUW'd.
+ ValuePtrs[Idx] = new Argument(Ty);
+ return false;
+}
+
+Constant *NaClBitcodeReaderValueList::getOrCreateGlobalVarRef(
+ unsigned Idx, Module *M) {
+ // First make sure the element for Idx is defined.
+ if (Idx >= size())
+ resize(Idx + 1);
+
+ // Now get its value (if applicable).
+ if (Value *V = ValuePtrs[Idx])
+ return dyn_cast<Constant>(V);
+
+ // Create a placeholder, which will later be RAUW'd.
+ Type *PlaceholderType = Type::getInt8Ty(Context);
+
+ Constant *C =
+ new GlobalVariable(*M, PlaceholderType, false,
+ GlobalValue::ExternalLinkage, 0);
+ ValuePtrs[Idx] = C;
+ return C;
+}
+
+/// ResolveConstantForwardRefs - Once all constants are read, this method bulk
+/// resolves any forward references. The idea behind this is that we sometimes
+/// get constants (such as large arrays) which reference *many* forward ref
+/// constants. Replacing each of these causes a lot of thrashing when
+/// building/reuniquing the constant. Instead of doing this, we look at all the
+/// uses and rewrite all the place holders at once for any constant that uses
+/// a placeholder.
+void NaClBitcodeReaderValueList::ResolveConstantForwardRefs() {
+ // Sort the values by-pointer so that they are efficient to look up with a
+ // binary search.
+ std::sort(ResolveConstants.begin(), ResolveConstants.end());
+
+ SmallVector<Constant*, 64> NewOps;
+
+ while (!ResolveConstants.empty()) {
+ Value *RealVal = operator[](ResolveConstants.back().second);
+ Constant *Placeholder = ResolveConstants.back().first;
+ ResolveConstants.pop_back();
+
+ // Loop over all users of the placeholder, updating them to reference the
+ // new value. If they reference more than one placeholder, update them all
+ // at once.
+ while (!Placeholder->use_empty()) {
+ Value::use_iterator UI = Placeholder->use_begin();
+ User *U = *UI;
+
+ // If the using object isn't uniqued, just update the operands. This
+ // handles instructions and initializers for global variables.
+ if (!isa<Constant>(U) || isa<GlobalValue>(U)) {
+ UI.getUse().set(RealVal);
+ continue;
+ }
+
+ // Otherwise, we have a constant that uses the placeholder. Replace that
+ // constant with a new constant that has *all* placeholder uses updated.
+ Constant *UserC = cast<Constant>(U);
+ for (User::op_iterator I = UserC->op_begin(), E = UserC->op_end();
+ I != E; ++I) {
+ Value *NewOp;
+ if (!isa<ConstantPlaceHolder>(*I)) {
+ // Not a placeholder reference.
+ NewOp = *I;
+ } else if (*I == Placeholder) {
+ // Common case is that it just references this one placeholder.
+ NewOp = RealVal;
+ } else {
+ // Otherwise, look up the placeholder in ResolveConstants.
+ ResolveConstantsTy::iterator It =
+ std::lower_bound(ResolveConstants.begin(), ResolveConstants.end(),
+ std::pair<Constant*, unsigned>(cast<Constant>(*I),
+ 0));
+ assert(It != ResolveConstants.end() && It->first == *I);
+ NewOp = operator[](It->second);
+ }
+
+ NewOps.push_back(cast<Constant>(NewOp));
+ }
+
+ // Make the new constant.
+ Constant *NewC;
+ if (ConstantArray *UserCA = dyn_cast<ConstantArray>(UserC)) {
+ NewC = ConstantArray::get(UserCA->getType(), NewOps);
+ } else if (ConstantStruct *UserCS = dyn_cast<ConstantStruct>(UserC)) {
+ NewC = ConstantStruct::get(UserCS->getType(), NewOps);
+ } else if (isa<ConstantVector>(UserC)) {
+ NewC = ConstantVector::get(NewOps);
+ } else {
+ assert(isa<ConstantExpr>(UserC) && "Must be a ConstantExpr.");
+ NewC = cast<ConstantExpr>(UserC)->getWithOperands(NewOps);
+ }
+
+ UserC->replaceAllUsesWith(NewC);
+ UserC->destroyConstant();
+ NewOps.clear();
+ }
+
+ // Update all ValueHandles, they should be the only users at this point.
+ Placeholder->replaceAllUsesWith(RealVal);
+ delete Placeholder;
+ }
+}
+
+Type *NaClBitcodeReader::getTypeByID(unsigned ID) {
+ // The type table size is always specified correctly.
+ if (ID >= TypeList.size())
+ return 0;
+
+ if (Type *Ty = TypeList[ID])
+ return Ty;
+
+ // If we have a forward reference, the only possible case is when it is to a
+ // named struct. Just create a placeholder for now.
+ return TypeList[ID] = StructType::create(Context);
+}
+
+
+//===----------------------------------------------------------------------===//
+// Functions for parsing blocks from the bitcode file
+//===----------------------------------------------------------------------===//
+
+
+bool NaClBitcodeReader::ParseTypeTable() {
+ DEBUG(dbgs() << "-> ParseTypeTable\n");
+ if (Stream.EnterSubBlock(naclbitc::TYPE_BLOCK_ID_NEW))
+ return Error("Malformed block record");
+
+ bool result = ParseTypeTableBody();
+ if (!result)
+ DEBUG(dbgs() << "<- ParseTypeTable\n");
+ return result;
+}
+
+bool NaClBitcodeReader::ParseTypeTableBody() {
+ if (!TypeList.empty())
+ return Error("Multiple TYPE_BLOCKs found!");