blob: 05c75cd4fc2e76eeb3f0c58dd69cb691212bd56d [file] [log] [blame]
//===- 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"
#include "llvm/Support/raw_ostream.h"
using namespace llvm;
cl::opt<bool>
llvm::PNaClAllowLocalSymbolTables(
"allow-local-symbol-tables",
cl::desc("Allow (function) local symbol tables in PNaCl bitcode files"),
cl::init(false));
void NaClBitcodeReader::FreeState() {
if (BufferOwned)
delete Buffer;
Buffer = 0;
std::vector<Type*>().swap(TypeList);
ValueList.clear();
std::vector<Function*>().swap(FunctionsWithBodies);
DeferredFunctionInfo.clear();
}
//===----------------------------------------------------------------------===//
// 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) {
case 0: return GlobalValue::ExternalLinkage;
case 3: return GlobalValue::InternalLinkage;
default:
report_fatal_error("PNaCl bitcode contains invalid linkage type");
}
}
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_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 CallingConv::ID GetDecodedCallingConv(unsigned Val) {
switch (Val) {
default:
report_fatal_error("PNaCl bitcode contains invalid calling conventions.");
case naclbitc::C_CallingConv: return CallingConv::C;
}
}
static FCmpInst::Predicate GetDecodedFCmpPredicate(unsigned Val) {
switch (Val) {
default:
report_fatal_error(
"PNaCl bitcode contains invalid floating comparison predicate");
case naclbitc::FCMP_FALSE: return FCmpInst::FCMP_FALSE;
case naclbitc::FCMP_OEQ: return FCmpInst::FCMP_OEQ;
case naclbitc::FCMP_OGT: return FCmpInst::FCMP_OGT;
case naclbitc::FCMP_OGE: return FCmpInst::FCMP_OGE;
case naclbitc::FCMP_OLT: return FCmpInst::FCMP_OLT;
case naclbitc::FCMP_OLE: return FCmpInst::FCMP_OLE;
case naclbitc::FCMP_ONE: return FCmpInst::FCMP_ONE;
case naclbitc::FCMP_ORD: return FCmpInst::FCMP_ORD;
case naclbitc::FCMP_UNO: return FCmpInst::FCMP_UNO;
case naclbitc::FCMP_UEQ: return FCmpInst::FCMP_UEQ;
case naclbitc::FCMP_UGT: return FCmpInst::FCMP_UGT;
case naclbitc::FCMP_UGE: return FCmpInst::FCMP_UGE;
case naclbitc::FCMP_ULT: return FCmpInst::FCMP_ULT;
case naclbitc::FCMP_ULE: return FCmpInst::FCMP_ULE;
case naclbitc::FCMP_UNE: return FCmpInst::FCMP_UNE;
case naclbitc::FCMP_TRUE: return FCmpInst::FCMP_TRUE;
}
}
static ICmpInst::Predicate GetDecodedICmpPredicate(unsigned Val) {
switch (Val) {
default:
report_fatal_error(
"PNaCl bitcode contains invalid integer comparison predicate");
case naclbitc::ICMP_EQ: return ICmpInst::ICMP_EQ;
case naclbitc::ICMP_NE: return ICmpInst::ICMP_NE;
case naclbitc::ICMP_UGT: return ICmpInst::ICMP_UGT;
case naclbitc::ICMP_UGE: return ICmpInst::ICMP_UGE;
case naclbitc::ICMP_ULT: return ICmpInst::ICMP_ULT;
case naclbitc::ICMP_ULE: return ICmpInst::ICMP_ULE;
case naclbitc::ICMP_SGT: return ICmpInst::ICMP_SGT;
case naclbitc::ICMP_SGE: return ICmpInst::ICMP_SGE;
case naclbitc::ICMP_SLT: return ICmpInst::ICMP_SLT;
case naclbitc::ICMP_SLE: return ICmpInst::ICMP_SLE;
}
}
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;
}
// 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;
}
void NaClBitcodeReaderValueList::OverwriteValue(Value *V, unsigned Idx) {
ValuePtrs[Idx] = V;
}
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;
}
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!");
SmallVector<uint64_t, 64> Record;
unsigned NumRecords = 0;
// Read all the records for this type table.
while (1) {
NaClBitstreamEntry Entry = Stream.advanceSkippingSubblocks();
switch (Entry.Kind) {
case NaClBitstreamEntry::SubBlock: // Handled for us already.
case NaClBitstreamEntry::Error:
Error("Error in the type table block");
return true;
case NaClBitstreamEntry::EndBlock:
if (NumRecords != TypeList.size())
return Error("Invalid type forward reference in TYPE_BLOCK");
return false;
case NaClBitstreamEntry::Record:
// The interesting case.
break;
}
// Read a record.
Record.clear();
Type *ResultTy = 0;
unsigned TypeCode = Stream.readRecord(Entry.ID, Record);
switch (TypeCode) {
default: {
std::string Message;
raw_string_ostream StrM(Message);
StrM << "Unknown type code in type table: " << TypeCode;
StrM.flush();
return Error(Message);
}
case naclbitc::TYPE_CODE_NUMENTRY: // TYPE_CODE_NUMENTRY: [numentries]
// TYPE_CODE_NUMENTRY contains a count of the number of types in the
// type list. This allows us to reserve space.
if (Record.size() < 1)
return Error("Invalid TYPE_CODE_NUMENTRY record");
TypeList.resize(Record[0]);
continue;
case naclbitc::TYPE_CODE_VOID: // VOID
ResultTy = Type::getVoidTy(Context);
break;
case naclbitc::TYPE_CODE_FLOAT: // FLOAT
ResultTy = Type::getFloatTy(Context);
break;
case naclbitc::TYPE_CODE_DOUBLE: // DOUBLE
ResultTy = Type::getDoubleTy(Context);
break;
case naclbitc::TYPE_CODE_INTEGER: // INTEGER: [width]
if (Record.size() < 1)
return Error("Invalid Integer type record");
ResultTy = IntegerType::get(Context, Record[0]);
break;
case naclbitc::TYPE_CODE_FUNCTION: {
// FUNCTION: [vararg, retty, paramty x N]
if (Record.size() < 2)
return Error("Invalid FUNCTION type record");
SmallVector<Type*, 8> ArgTys;
for (unsigned i = 2, e = Record.size(); i != e; ++i) {
if (Type *T = getTypeByID(Record[i]))
ArgTys.push_back(T);
else
break;
}
ResultTy = getTypeByID(Record[1]);
if (ResultTy == 0 || ArgTys.size() < Record.size()-2)
return Error("invalid type in function type");
ResultTy = FunctionType::get(ResultTy, ArgTys, Record[0]);
break;
}
}
if (NumRecords >= TypeList.size())
return Error("invalid TYPE table");
assert(ResultTy && "Didn't read a type?");
assert(TypeList[NumRecords] == 0 && "Already read type?");
TypeList[NumRecords++] = ResultTy;
}
}
bool NaClBitcodeReader::ParseGlobalVars() {
if (Stream.EnterSubBlock(naclbitc::GLOBALVAR_BLOCK_ID))
return Error("Malformed block record");
SmallVector<uint64_t, 64> Record;
// True when processing a global variable. Stays true until all records
// are processed, and the global variable is created.
bool ProcessingGlobal = false;
// The alignment value defined for the global variable.
unsigned VarAlignment = 0;
// True if the variable is read-only.
bool VarIsConstant = false;
// The initializer for the global variable.
SmallVector<Constant *, 10> VarInit;
// The number of initializers needed for the global variable.
unsigned VarInitializersNeeded = 0;
unsigned FirstValueNo = ValueList.size();
// The index of the next global variable.
unsigned NextValueNo = FirstValueNo;
// The number of expected global variable definitions.
unsigned NumGlobals = 0;
// Read all global variable records.
while (1) {
NaClBitstreamEntry Entry = Stream.advanceSkippingSubblocks();
switch (Entry.Kind) {
case NaClBitstreamEntry::SubBlock:
case NaClBitstreamEntry::Error:
return Error("Error in the global vars block");
case NaClBitstreamEntry::EndBlock:
if (ProcessingGlobal || NumGlobals != (NextValueNo - FirstValueNo))
return Error("Error in the global vars block");
return false;
case NaClBitstreamEntry::Record:
// The interesting case.
break;
}
// Read a record.
Record.clear();
unsigned Bitcode = Stream.readRecord(Entry.ID, Record);
switch (Bitcode) {
default: return Error("Unknown global variable entry");
case naclbitc::GLOBALVAR_VAR:
// Start the definition of a global variable.
if (ProcessingGlobal || Record.size() != 2)
return Error("Bad GLOBALVAR_VAR record");
ProcessingGlobal = true;
VarAlignment = (1 << Record[0]) >> 1;
VarIsConstant = Record[1] != 0;
// Assume (by default) there is a single initializer.
VarInitializersNeeded = 1;
break;
case naclbitc::GLOBALVAR_COMPOUND:
// Global variable has multiple initializers. Changes the
// default number of initializers to the given value in
// Record[0].
if (!ProcessingGlobal || !VarInit.empty() ||
VarInitializersNeeded != 1 || Record.size() != 1)
return Error("Bad GLOBALVAR_COMPOUND record");
VarInitializersNeeded = Record[0];
break;
case naclbitc::GLOBALVAR_ZEROFILL: {
// Define an initializer that defines a sequence of zero-filled bytes.
if (!ProcessingGlobal || Record.size() != 1)
return Error("Bad GLOBALVAR_ZEROFILL record");
Type *Ty = ArrayType::get(Type::getInt8Ty(Context), Record[0]);
Constant *Zero = ConstantAggregateZero::get(Ty);
VarInit.push_back(Zero);
break;
}
case naclbitc::GLOBALVAR_DATA: {
// Defines an initializer defined by a sequence of byte values.
if (!ProcessingGlobal || Record.size() < 1)
return Error("Bad GLOBALVAR_DATA record");
unsigned Size = Record.size();
uint8_t *Buf = new uint8_t[Size];
assert(Buf);
for (unsigned i = 0; i < Size; ++i)
Buf[i] = Record[i];
Constant *Init = ConstantDataArray::get(
Context, ArrayRef<uint8_t>(Buf, Buf + Size));
VarInit.push_back(Init);
delete[] Buf;
break;
}
case naclbitc::GLOBALVAR_RELOC: {
// Define a relocation initializer.
if (!ProcessingGlobal || Record.size() < 1 || Record.size() > 2)
return Error("Bad GLOBALVAR_RELOC record");
Constant *BaseVal =
ValueList.getOrCreateGlobalVarRef(Record[0], TheModule);
if (BaseVal == 0)
return Error("Bad base value in GLOBALVAR_RELOC record");
Type *IntPtrType = IntegerType::get(Context, 32);
Constant *Val = ConstantExpr::getPtrToInt(BaseVal, IntPtrType);
if (Record.size() == 2) {
uint32_t Addend = Record[1];
Val = ConstantExpr::getAdd(Val, ConstantInt::get(IntPtrType,
Addend));
}
VarInit.push_back(Val);
break;
}
case naclbitc::GLOBALVAR_COUNT:
if (Record.size() != 1 || NumGlobals != 0)
return Error("Invalid global count record");
NumGlobals = Record[0];
break;
}
// If more initializers needed for global variable, continue processing.
if (!ProcessingGlobal || VarInit.size() < VarInitializersNeeded)
continue;
Constant *Init = 0;
switch (VarInit.size()) {
case 0:
return Error("No initializer for global variable in global vars block");
case 1:
Init = VarInit[0];
break;
default:
Init = ConstantStruct::getAnon(Context, VarInit, true);
break;
}
GlobalVariable *GV = new GlobalVariable(
*TheModule, Init->getType(), VarIsConstant,
GlobalValue::InternalLinkage, Init, "");
GV->setAlignment(VarAlignment);
ValueList.AssignGlobalVar(GV, NextValueNo);
++NextValueNo;
ProcessingGlobal = false;
VarAlignment = 0;
VarIsConstant = false;
VarInitializersNeeded = 0;
VarInit.clear();
}
}
bool NaClBitcodeReader::ParseValueSymbolTable() {
DEBUG(dbgs() << "-> ParseValueSymbolTable\n");
if (Stream.EnterSubBlock(naclbitc::VALUE_SYMTAB_BLOCK_ID))
return Error("Malformed block record");
SmallVector<uint64_t, 64> Record;
// Read all the records for this value table.
SmallString<128> ValueName;
while (1) {
NaClBitstreamEntry Entry = Stream.advanceSkippingSubblocks();
switch (Entry.Kind) {
case NaClBitstreamEntry::SubBlock: // Handled for us already.
case NaClBitstreamEntry::Error:
return Error("malformed value symbol table block");
case NaClBitstreamEntry::EndBlock:
DEBUG(dbgs() << "<- ParseValueSymbolTable\n");
return false;
case NaClBitstreamEntry::Record:
// The interesting case.
break;
}
// Read a record.
Record.clear();
switch (Stream.readRecord(Entry.ID, Record)) {
default: // Default behavior: unknown type.
break;
case naclbitc::VST_CODE_ENTRY: { // VST_ENTRY: [valueid, namechar x N]
if (ConvertToString(Record, 1, ValueName))
return Error("Invalid VST_ENTRY record");
unsigned ValueID = Record[0];
if (ValueID >= ValueList.size())
return Error("Invalid Value ID in VST_ENTRY record");
Value *V = ValueList[ValueID];
V->setName(StringRef(ValueName.data(), ValueName.size()));
ValueName.clear();
break;
}
case naclbitc::VST_CODE_BBENTRY: {
if (ConvertToString(Record, 1, ValueName))
return Error("Invalid VST_BBENTRY record");
BasicBlock *BB = getBasicBlock(Record[0]);
if (BB == 0)
return Error("Invalid BB ID in VST_BBENTRY record");
BB->setName(StringRef(ValueName.data(), ValueName.size()));
ValueName.clear();
break;
}
}
}
}
bool NaClBitcodeReader::ParseConstants() {
DEBUG(dbgs() << "-> ParseConstants\n");
if (Stream.EnterSubBlock(naclbitc::CONSTANTS_BLOCK_ID))
return Error("Malformed block record");
SmallVector<uint64_t, 64> Record;
// Read all the records for this value table.
Type *CurTy = Type::getInt32Ty(Context);
unsigned NextCstNo = ValueList.size();
while (1) {
NaClBitstreamEntry Entry = Stream.advanceSkippingSubblocks();
switch (Entry.Kind) {
case NaClBitstreamEntry::SubBlock: // Handled for us already.
case NaClBitstreamEntry::Error:
return Error("malformed block record in AST file");
case NaClBitstreamEntry::EndBlock:
if (NextCstNo != ValueList.size())
return Error("Invalid constant reference!");
DEBUG(dbgs() << "<- ParseConstants\n");
return false;
case NaClBitstreamEntry::Record:
// The interesting case.
break;
}
// Read a record.
Record.clear();
Value *V = 0;
unsigned BitCode = Stream.readRecord(Entry.ID, Record);
switch (BitCode) {
default: {
std::string Message;
raw_string_ostream StrM(Message);
StrM << "Invalid Constant code: " << BitCode;
StrM.flush();
return Error(Message);
}
case naclbitc::CST_CODE_UNDEF: // UNDEF
V = UndefValue::get(CurTy);
break;
case naclbitc::CST_CODE_SETTYPE: // SETTYPE: [typeid]
if (Record.empty())
return Error("Malformed CST_SETTYPE record");
if (Record[0] >= TypeList.size())
return Error("Invalid Type ID in CST_SETTYPE record");
CurTy = TypeList[Record[0]];
continue; // Skip the ValueList manipulation.
case naclbitc::CST_CODE_INTEGER: // INTEGER: [intval]
if (!CurTy->isIntegerTy() || Record.empty())
return Error("Invalid CST_INTEGER record");
V = ConstantInt::get(CurTy, NaClDecodeSignRotatedValue(Record[0]));
break;
case naclbitc::CST_CODE_FLOAT: { // FLOAT: [fpval]
if (Record.empty())
return Error("Invalid FLOAT record");
if (CurTy->isFloatTy())
V = ConstantFP::get(Context, APFloat(APFloat::IEEEsingle,
APInt(32, (uint32_t)Record[0])));
else if (CurTy->isDoubleTy())
V = ConstantFP::get(Context, APFloat(APFloat::IEEEdouble,
APInt(64, Record[0])));
else
return Error("Unknown type for FLOAT record");
break;
}
}
ValueList.AssignValue(V, NextCstNo);
++NextCstNo;
}
}
/// RememberAndSkipFunctionBody - When we see the block for a function body,
/// remember where it is and then skip it. This lets us lazily deserialize the
/// functions.
bool NaClBitcodeReader::RememberAndSkipFunctionBody() {
DEBUG(dbgs() << "-> RememberAndSkipFunctionBody\n");
// Get the function we are talking about.
if (FunctionsWithBodies.empty())
return Error("Insufficient function protos");
Function *Fn = FunctionsWithBodies.back();
FunctionsWithBodies.pop_back();
// Save the current stream state.
uint64_t CurBit = Stream.GetCurrentBitNo();
DeferredFunctionInfo[Fn] = CurBit;
// Skip over the function block for now.
if (Stream.SkipBlock())
return Error("Malformed block record");
DEBUG(dbgs() << "<- RememberAndSkipFunctionBody\n");
return false;
}
bool NaClBitcodeReader::GlobalCleanup() {
// Look for intrinsic functions which need to be upgraded at some point
for (Module::iterator FI = TheModule->begin(), FE = TheModule->end();
FI != FE; ++FI) {
Function *NewFn;
if (UpgradeIntrinsicFunction(FI, NewFn))
UpgradedIntrinsics.push_back(std::make_pair(FI, NewFn));
}
// Look for global variables which need to be renamed.
for (Module::global_iterator
GI = TheModule->global_begin(), GE = TheModule->global_end();
GI != GE; ++GI)
UpgradeGlobalVariable(GI);
return false;
}
FunctionType *NaClBitcodeReader::AddPointerTypesToIntrinsicType(
StringRef Name, FunctionType *FTy) {
Type *ReturnTy = FTy->getReturnType();
SmallVector<Type *, 8> ArgTypes(FTy->param_begin(), FTy->param_end());
// Ideally we wouldn't need a list of supported intrinsics here, but
// Intrinsic::* doesn't provide a function for recovering the
// expected type of an intrinsic given its full name.
// TODO(mseaborn): We could reuse the intrinsic list from
// PNaClABIVerifyModule.cpp here.
if (Name == "llvm.nacl.read.tp" ||
Name == "llvm.stacksave") {
ReturnTy = Type::getInt8PtrTy(Context);
} else if (Name == "llvm.nacl.setjmp" ||
Name == "llvm.nacl.longjmp" ||
Name == "llvm.stackrestore" ||
Name.startswith("llvm.memset.")) {
assert(ArgTypes.size() >= 1);
ArgTypes[0] = Type::getInt8PtrTy(Context);
} else if (Name.startswith("llvm.memcpy.") ||
Name.startswith("llvm.memmove.")) {
assert(ArgTypes.size() >= 2);
ArgTypes[0] = Type::getInt8PtrTy(Context);
ArgTypes[1] = Type::getInt8PtrTy(Context);
} else if (Name.startswith("llvm.nacl.atomic.load.") ||
Name.startswith("llvm.nacl.atomic.cmpxchg.")) {
assert(ArgTypes.size() >= 1);
ArgTypes[0] = ReturnTy->getPointerTo();
} else if (Name.startswith("llvm.nacl.atomic.store.")) {
assert(ArgTypes.size() >= 2);
ArgTypes[1] = ArgTypes[0]->getPointerTo();
} else if (Name.startswith("llvm.nacl.atomic.rmw.")) {
assert(ArgTypes.size() >= 3);
ArgTypes[1] = ArgTypes[2]->getPointerTo();
} else if (Name == "llvm.nacl.atomic.is.lock.free") {
assert(ArgTypes.size() >= 2);
ArgTypes[1] = Type::getInt8PtrTy(Context);
}
return FunctionType::get(ReturnTy, ArgTypes, false);
}
void NaClBitcodeReader::AddPointerTypesToIntrinsicParams() {
for (unsigned Index = 0, E = ValueList.size(); Index < E; ++Index) {
if (Function *Func = dyn_cast<Function>(ValueList[Index])) {
if (Func->isIntrinsic()) {
FunctionType *FTy = AddPointerTypesToIntrinsicType(
Func->getName(), Func->getFunctionType());
Function *NewIntrinsic = Function::Create(
FTy, GlobalValue::ExternalLinkage, "", TheModule);
NewIntrinsic->takeName(Func);
ValueList.OverwriteValue(NewIntrinsic, Index);
Func->eraseFromParent();
}
}
}
}
bool NaClBitcodeReader::ParseModule(bool Resume) {
DEBUG(dbgs() << "-> ParseModule\n");
if (Resume)
Stream.JumpToBit(NextUnreadBit);
else if (Stream.EnterSubBlock(naclbitc::MODULE_BLOCK_ID))
return Error("Malformed block record");
SmallVector<uint64_t, 64> Record;
// Read all the records for this module.
while (1) {
NaClBitstreamEntry Entry = Stream.advance();
switch (Entry.Kind) {
case NaClBitstreamEntry::Error:
Error("malformed module block");
return true;
case NaClBitstreamEntry::EndBlock:
DEBUG(dbgs() << "<- ParseModule\n");
return GlobalCleanup();
case NaClBitstreamEntry::SubBlock:
switch (Entry.ID) {
default: {
std::string Message;
raw_string_ostream StrM(Message);
StrM << "Unknown block ID: " << Entry.ID;
return Error(StrM.str());
}
case naclbitc::BLOCKINFO_BLOCK_ID:
if (Stream.ReadBlockInfoBlock())
return Error("Malformed BlockInfoBlock");
break;
case naclbitc::TYPE_BLOCK_ID_NEW:
if (ParseTypeTable())
return true;
break;
case naclbitc::GLOBALVAR_BLOCK_ID:
if (ParseGlobalVars())
return true;
break;
case naclbitc::VALUE_SYMTAB_BLOCK_ID:
if (ParseValueSymbolTable())
return true;
SeenValueSymbolTable = true;
// Now that we know the names of the intrinsics, we can add
// pointer types to the intrinsic declarations' types.
AddPointerTypesToIntrinsicParams();
break;
case naclbitc::FUNCTION_BLOCK_ID:
// If this is the first function body we've seen, reverse the
// FunctionsWithBodies list.
if (!SeenFirstFunctionBody) {
std::reverse(FunctionsWithBodies.begin(), FunctionsWithBodies.end());
if (GlobalCleanup())
return true;
SeenFirstFunctionBody = true;
}
if (RememberAndSkipFunctionBody())
return true;
// For streaming bitcode, suspend parsing when we reach the function
// bodies. Subsequent materialization calls will resume it when
// necessary. For streaming, the function bodies must be at the end of
// the bitcode. If the bitcode file is old, the symbol table will be
// at the end instead and will not have been seen yet. In this case,
// just finish the parse now.
if (LazyStreamer && SeenValueSymbolTable) {
NextUnreadBit = Stream.GetCurrentBitNo();
DEBUG(dbgs() << "<- ParseModule\n");
return false;
}
break;
}
continue;
case NaClBitstreamEntry::Record:
// The interesting case.
break;
}
// Read a record.
unsigned Selector = Stream.readRecord(Entry.ID, Record);
switch (Selector) {
default: {
std::string Message;
raw_string_ostream StrM(Message);
StrM << "Invalid MODULE_CODE: " << Selector;
StrM.flush();
return Error(Message);
}
case naclbitc::MODULE_CODE_VERSION: { // VERSION: [version#]
if (Record.size() < 1)
return Error("Malformed MODULE_CODE_VERSION");
// Only version #1 is supported for PNaCl. Version #0 is not supported.
unsigned module_version = Record[0];
if (module_version != 1)
return Error("Unknown bitstream version!");
break;
}
// FUNCTION: [type, callingconv, isproto, linkage]
case naclbitc::MODULE_CODE_FUNCTION: {
if (Record.size() < 4)
return Error("Invalid MODULE_CODE_FUNCTION record");
Type *Ty = getTypeByID(Record[0]);
if (!Ty) return Error("Invalid MODULE_CODE_FUNCTION record");
FunctionType *FTy = dyn_cast<FunctionType>(Ty);
if (!FTy)
return Error("Function not declared with a function type!");
Function *Func = Function::Create(FTy, GlobalValue::ExternalLinkage,
"", TheModule);
Func->setCallingConv(GetDecodedCallingConv(Record[1]));
bool isProto = Record[2];
Func->setLinkage(GetDecodedLinkage(Record[3]));
ValueList.push_back(Func);
// If this is a function with a body, remember the prototype we are
// creating now, so that we can match up the body with them later.
if (!isProto) {
FunctionsWithBodies.push_back(Func);
if (LazyStreamer) DeferredFunctionInfo[Func] = 0;
}
break;
}
}
Record.clear();
}
}
bool NaClBitcodeReader::ParseBitcodeInto(Module *M) {
TheModule = 0;
// PNaCl does not support different DataLayouts in pexes, so we
// implicitly set the DataLayout to the following default.
//
// This is not usually needed by the backend, but it might be used
// by IR passes that the PNaCl translator runs. We set this in the
// reader rather than in pnacl-llc so that 'opt' will also use the
// correct DataLayout if it is run on a pexe.
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; // InitSream will set the error string.
// We expect a number of well-defined blocks, though we don't necessarily
// need to understand them all.
while (1) {
if (Stream.AtEndOfStream())
return false;
NaClBitstreamEntry Entry =
Stream.advance(NaClBitstreamCursor::AF_DontAutoprocessAbbrevs);
switch (Entry.Kind) {
case NaClBitstreamEntry::Error:
Error("malformed module file");
return true;
case NaClBitstreamEntry::EndBlock:
return false;
case NaClBitstreamEntry::SubBlock:
switch (Entry.ID) {
case naclbitc::BLOCKINFO_BLOCK_ID:
if (Stream.ReadBlockInfoBlock())
return Error("Malformed BlockInfoBlock");
break;
case naclbitc::MODULE_BLOCK_ID:
// Reject multiple MODULE_BLOCK's in a single bitstream.
if (TheModule)
return Error("Multiple MODULE_BLOCKs in same stream");
TheModule = M;
if (ParseModule(false))
return true;
if (LazyStreamer) return false;
break;
default:
if (Stream.SkipBlock())
return Error("Malformed block record");
break;
}
continue;
case NaClBitstreamEntry::Record:
// There should be no records in the top-level of blocks.
return Error("Invalid record at top-level");
}
}
}
// Returns true if error occured installing I into BB.
bool NaClBitcodeReader::InstallInstruction(
BasicBlock *BB, Instruction *I) {
// Add instruction to end of current BB. If there is no current BB, reject
// this file.
if (BB == 0) {
delete I;
return Error("Invalid instruction with no BB");
}
BB->getInstList().push_back(I);
return false;
}
CastInst *
NaClBitcodeReader::CreateCast(unsigned BBIndex, Instruction::CastOps Op,
Type *CT, Value *V, bool DeferInsertion) {
if (BBIndex >= FunctionBBs.size())
report_fatal_error("CreateCast on unknown basic block");
BasicBlockInfo &BBInfo = FunctionBBs[BBIndex];
NaClBitcodeReaderCast ModeledCast(Op, CT, V);
CastInst *Cast = BBInfo.CastMap[ModeledCast];
if (Cast == NULL) {
Cast = CastInst::Create(Op, V, CT);
BBInfo.CastMap[ModeledCast] = Cast;
if (DeferInsertion) {
BBInfo.PhiCasts.push_back(Cast);
}
}
if (!DeferInsertion && Cast->getParent() == 0) {
InstallInstruction(BBInfo.BB, Cast);
}
return Cast;
}
Value *NaClBitcodeReader::ConvertOpToScalar(Value *Op, unsigned BBIndex,
bool DeferInsertion) {
if (Op->getType()->isPointerTy()) {
return CreateCast(BBIndex, Instruction::PtrToInt, IntPtrType, Op,
DeferInsertion);
}
return Op;
}
Value *NaClBitcodeReader::ConvertOpToType(Value *Op, Type *T,
unsigned BBIndex) {
Type *OpTy = Op->getType();
if (OpTy == T) return Op;
if (OpTy->isPointerTy()) {
if (T == IntPtrType) {
return ConvertOpToScalar(Op, BBIndex);
} else {
return CreateCast(BBIndex, Instruction::BitCast, T, Op);
}
} else if (OpTy == IntPtrType) {
return CreateCast(BBIndex, Instruction::IntToPtr, T, Op);
}
std::string Message;
raw_string_ostream StrM(Message);
StrM << "Can't convert " << *Op << " to type " << *T << "\n";
report_fatal_error(StrM.str());
}
/// ParseFunctionBody - Lazily parse the specified function body block.
bool NaClBitcodeReader::ParseFunctionBody(Function *F) {
DEBUG(dbgs() << "-> ParseFunctionBody\n");
if (Stream.EnterSubBlock(naclbitc::FUNCTION_BLOCK_ID))
return Error("Malformed block record");
unsigned ModuleValueListSize = ValueList.size();
// Add all the function arguments to the value table.
for(Function::arg_iterator I = F->arg_begin(), E = F->arg_end(); I != E; ++I)
ValueList.push_back(I);
unsigned NextValueNo = ValueList.size();
BasicBlock *CurBB = 0;
unsigned CurBBNo = 0;
// Read all the records.
SmallVector<uint64_t, 64> Record;
while (1) {
NaClBitstreamEntry Entry = Stream.advance();
switch (Entry.Kind) {
case NaClBitstreamEntry::Error:
return Error("Bitcode error in function block");
case NaClBitstreamEntry::EndBlock:
goto OutOfRecordLoop;
case NaClBitstreamEntry::SubBlock:
switch (Entry.ID) {
default: // Skip unknown content.
dbgs() << "default skip block\n";
if (Stream.SkipBlock())
return Error("Malformed block record");
break;
case naclbitc::CONSTANTS_BLOCK_ID:
if (ParseConstants())
return true;
NextValueNo = ValueList.size();
break;
case naclbitc::VALUE_SYMTAB_BLOCK_ID:
if (PNaClAllowLocalSymbolTables) {
if (ParseValueSymbolTable())
return true;
} else {
return Error("Local value symbol tables not allowed");
}
break;
}
continue;
case NaClBitstreamEntry::Record:
// The interesting case.
break;
}
// Read a record.
Record.clear();
Instruction *I = 0;
unsigned BitCode = Stream.readRecord(Entry.ID, Record);
switch (BitCode) {
default: {// Default behavior: reject
std::string Message;
raw_string_ostream StrM(Message);
StrM << "Unknown instruction record: <" << BitCode;
for (unsigned I = 0, E = Record.size(); I != E; ++I) {
StrM << " " << Record[I];
}
StrM << ">";
return Error(StrM.str());
}
case naclbitc::FUNC_CODE_DECLAREBLOCKS: // DECLAREBLOCKS: [nblocks]
if (Record.size() < 1 || Record[0] == 0)
return Error("Invalid DECLAREBLOCKS record");
// Create all the basic blocks for the function.
FunctionBBs.resize(Record[0]);
for (unsigned i = 0, e = FunctionBBs.size(); i != e; ++i) {
BasicBlockInfo &BBInfo = FunctionBBs[i];
BBInfo.BB = BasicBlock::Create(Context, "", F);
}
CurBB = FunctionBBs.at(0).BB;
continue;
case naclbitc::FUNC_CODE_INST_BINOP: {
// BINOP: [opval, opval, opcode[, flags]]
// Note: Only old PNaCl bitcode files may contain flags. If
// they are found, we ignore them.
unsigned OpNum = 0;
Value *LHS, *RHS;
if (popValue(Record, &OpNum, NextValueNo, &LHS) ||
popValue(Record, &OpNum, NextValueNo, &RHS) ||
OpNum+1 > Record.size())
return Error("Invalid BINOP record");
LHS = ConvertOpToScalar(LHS, CurBBNo);
RHS = ConvertOpToScalar(RHS, CurBBNo);
int Opc = GetDecodedBinaryOpcode(Record[OpNum++], LHS->getType());
if (Opc == -1) return Error("Invalid BINOP record");
I = BinaryOperator::Create((Instruction::BinaryOps)Opc, LHS, RHS);
break;
}
case naclbitc::FUNC_CODE_INST_CAST: { // CAST: [opval, destty, castopc]
unsigned OpNum = 0;
Value *Op;
if (popValue(Record, &OpNum, NextValueNo, &Op) ||
OpNum+2 != Record.size())
return Error("Invalid CAST record: bad record size");
Type *ResTy = getTypeByID(Record[OpNum]);
if (ResTy == 0)
return Error("Invalid CAST record: bad type ID");
int Opc = GetDecodedCastOpcode(Record[OpNum+1]);
if (Opc == -1)
return Error("Invalid CAST record: bad opcode");
// If a ptrtoint cast was elided on the argument of the cast,
// add it back. Note: The casts allowed here should match the
// casts in NaClValueEnumerator::ExpectsScalarValue.
switch (Opc) {
case Instruction::Trunc:
case Instruction::ZExt:
case Instruction::SExt:
case Instruction::UIToFP:
case Instruction::SIToFP:
Op = ConvertOpToScalar(Op, CurBBNo);
break;
default:
break;
}
I = CastInst::Create((Instruction::CastOps)Opc, Op, ResTy);
break;
}
case naclbitc::FUNC_CODE_INST_VSELECT: {// VSELECT: [opval, opval, pred]
// new form of select
// handles select i1 or select [N x i1]
unsigned OpNum = 0;
Value *TrueVal, *FalseVal, *Cond;
if (popValue(Record, &OpNum, NextValueNo, &TrueVal) ||
popValue(Record, &OpNum, NextValueNo, &FalseVal) ||
popValue(Record, &OpNum, NextValueNo, &Cond))
return Error("Invalid SELECT record");
TrueVal = ConvertOpToScalar(TrueVal, CurBBNo);
FalseVal = ConvertOpToScalar(FalseVal, CurBBNo);
// expect i1
if (Cond->getType() != Type::getInt1Ty(Context))
return Error("Invalid SELECT condition type");
I = SelectInst::Create(Cond, TrueVal, FalseVal);
break;
}
case naclbitc::FUNC_CODE_INST_CMP2: { // CMP2: [opval, opval, pred]
// FCmp/ICmp returning bool or vector of bool
unsigned OpNum = 0;
Value *LHS, *RHS;
if (popValue(Record, &OpNum, NextValueNo, &LHS) ||
popValue(Record, &OpNum, NextValueNo, &RHS) ||
OpNum+1 != Record.size())
return Error("Invalid CMP record");
LHS = ConvertOpToScalar(LHS, CurBBNo);
RHS = ConvertOpToScalar(RHS, CurBBNo);
if (LHS->getType()->isFPOrFPVectorTy())
I = new FCmpInst(GetDecodedFCmpPredicate(Record[OpNum]), LHS, RHS);
else
I = new ICmpInst(GetDecodedICmpPredicate(Record[OpNum]), LHS, RHS);
break;
}
case naclbitc::FUNC_CODE_INST_RET: // RET: [opval<optional>]
{
unsigned Size = Record.size();
if (Size == 0) {
I = ReturnInst::Create(Context);
break;
}
unsigned OpNum = 0;
Value *Op = NULL;
if (popValue(Record, &OpNum, NextValueNo, &Op))
return Error("Invalid RET record");
if (OpNum != Record.size())
return Error("Invalid RET record");
I = ReturnInst::Create(Context, ConvertOpToScalar(Op, CurBBNo));
break;
}
case naclbitc::FUNC_CODE_INST_BR: { // BR: [bb#, bb#, opval] or [bb#]
if (Record.size() != 1 && Record.size() != 3)
return Error("Invalid BR record");
BasicBlock *TrueDest = getBasicBlock(Record[0]);
if (TrueDest == 0)
return Error("Invalid BR record");
if (Record.size() == 1) {
I = BranchInst::Create(TrueDest);
}
else {
BasicBlock *FalseDest = getBasicBlock(Record[1]);
Value *Cond = getValue(Record, 2, NextValueNo);
if (FalseDest == 0 || Cond == 0)
return Error("Invalid BR record");
I = BranchInst::Create(TrueDest, FalseDest, Cond);
}
break;
}
case naclbitc::FUNC_CODE_INST_SWITCH: { // SWITCH: [opty, op0, op1, ...]
if (Record.size() < 4)
return Error("Invalid SWITCH record");
Type *OpTy = getTypeByID(Record[0]);
unsigned ValueBitWidth = cast<IntegerType>(OpTy)->getBitWidth();
if (ValueBitWidth > 64)
return Error("Wide integers are not supported in PNaCl bitcode");
Value *Cond = getValue(Record, 1, NextValueNo);
BasicBlock *Default = getBasicBlock(Record[2]);
if (OpTy == 0 || Cond == 0 || Default == 0)
return Error("Invalid SWITCH record");
unsigned NumCases = Record[3];
SwitchInst *SI = SwitchInst::Create(Cond, Default, NumCases);
unsigned CurIdx = 4;
for (unsigned i = 0; i != NumCases; ++i) {
// The PNaCl bitcode format has vestigial support for case
// ranges, but we no longer support reading them because
// no-one produced them.
// See https://code.google.com/p/nativeclient/issues/detail?id=3758
unsigned NumItems = Record[CurIdx++];
bool isSingleNumber = Record[CurIdx++];
if (NumItems != 1 || !isSingleNumber)
return Error("Case ranges are not supported in PNaCl bitcode");
APInt CaseValue(ValueBitWidth,
NaClDecodeSignRotatedValue(Record[CurIdx++]));
BasicBlock *DestBB = getBasicBlock(Record[CurIdx++]);
SI->addCase(ConstantInt::get(Context, CaseValue), DestBB);
}
I = SI;
break;
}
case naclbitc::FUNC_CODE_INST_UNREACHABLE: // UNREACHABLE
I = new UnreachableInst(Context);
break;
case naclbitc::FUNC_CODE_INST_PHI: { // PHI: [ty, val0,bb0, ...]
if (Record.size() < 1 || ((Record.size()-1)&1))
return Error("Invalid PHI record");
Type *Ty = getTypeByID(Record[0]);
if (!Ty) return Error("Invalid PHI record");
PHINode *PN = PHINode::Create(Ty, (Record.size()-1)/2);
for (unsigned i = 0, e = Record.size()-1; i != e; i += 2) {
Value *V;
// With relative value IDs, it is possible that operands have
// negative IDs (for forward references). Use a signed VBR
// representation to keep the encoding small.
V = getValueSigned(Record, 1+i, NextValueNo);
unsigned BBIndex = Record[2+i];
BasicBlock *BB = getBasicBlock(BBIndex);
if (!V || !BB) return Error("Invalid PHI record");
if (Ty == IntPtrType) {
// Delay installing scalar casts until all instructions of
// the function are rendered. This guarantees that we insert
// the conversion just before the incoming edge (or use an
// existing conversion if already installed).
V = ConvertOpToScalar(V, BBIndex, /* DeferInsertion = */ true);
}
PN->addIncoming(V, BB);
}
I = PN;
break;
}
case naclbitc::FUNC_CODE_INST_ALLOCA: { // ALLOCA: [op, align]
if (Record.size() != 2)
return Error("Invalid ALLOCA record");
Value *Size;
unsigned OpNum = 0;
if (popValue(Record, &OpNum, NextValueNo, &Size))
return Error("Invalid ALLOCA record");
unsigned Align = Record[1];
I = new AllocaInst(Type::getInt8Ty(Context), Size, (1 << Align) >> 1);
break;
}
case naclbitc::FUNC_CODE_INST_LOAD: {
// LOAD: [op, align, ty]
unsigned OpNum = 0;
Value *Op;
if (popValue(Record, &OpNum, NextValueNo, &Op) ||
Record.size() != 3)
return Error("Invalid LOAD record");
// Add pointer cast to op.
Type *T = getTypeByID(Record[2]);
if (T == 0)
return Error("Invalid type for load instruction");
Op = ConvertOpToType(Op, T->getPointerTo(), CurBBNo);
if (Op == 0) return true;
I = new LoadInst(Op, "", false, (1 << Record[OpNum]) >> 1);
break;
}
case naclbitc::FUNC_CODE_INST_STORE: {
// STORE: [ptr, val, align]
unsigned OpNum = 0;
Value *Val, *Ptr;
if (popValue(Record, &OpNum, NextValueNo, &Ptr) ||
popValue(Record, &OpNum, NextValueNo, &Val))
return Error("Invalid STORE record");
if (OpNum+1 != Record.size())
return Error("Invalid STORE record");
Val = ConvertOpToScalar(Val, CurBBNo);
Ptr = ConvertOpToType(Ptr, Val->getType()->getPointerTo(), CurBBNo);
I = new StoreInst(Val, Ptr, false, (1 << Record[OpNum]) >> 1);
break;
}
case naclbitc::FUNC_CODE_INST_CALL:
case naclbitc::FUNC_CODE_INST_CALL_INDIRECT: {
// CALL: [cc, fnid, arg0, arg1...]
// CALL_INDIRECT: [cc, fnid, fnty, args...]
if ((Record.size() < 2) ||
(BitCode == naclbitc::FUNC_CODE_INST_CALL_INDIRECT &&
Record.size() < 3))
return Error("Invalid CALL record");
unsigned CCInfo = Record[0];
unsigned OpNum = 1;
Value *Callee;
if (popValue(Record, &OpNum, NextValueNo, &Callee))
return Error("Invalid CALL record");
// Build function type for call.
FunctionType *FTy = 0;
Type *ReturnType = 0;
if (BitCode == naclbitc::FUNC_CODE_INST_CALL_INDIRECT) {
// Callee type has been elided, add back in.
ReturnType = getTypeByID(Record[2]);
++OpNum;
} else {
// Get type signature from callee.
if (PointerType *OpTy = dyn_cast<PointerType>(Callee->getType())) {
FTy = dyn_cast<FunctionType>(OpTy->getElementType());
}
if (FTy == 0)
return Error("Invalid type for CALL record");
}
unsigned NumParams = Record.size() - OpNum;
if (FTy && NumParams != FTy->getNumParams())
return Error("Invalid CALL record");
// Process call arguments.
SmallVector<Value*, 6> Args;
for (unsigned Index = 0; Index < NumParams; ++Index) {
Value *Arg;
if (popValue(Record, &OpNum, NextValueNo, &Arg))
Error("Invalid argument in CALL record");
if (FTy) {
// Add a cast, to a pointer type if necessary, in case this
// is an intrinsic call that takes a pointer argument.
Arg = ConvertOpToType(Arg, FTy->getParamType(Index), CurBBNo);
} else {
Arg = ConvertOpToScalar(Arg, CurBBNo);
}
Args.push_back(Arg);
}
if (FTy == 0) {
// Reconstruct the function type and cast the function pointer
// to it.
SmallVector<Type*, 6> ArgTypes;
for (unsigned Index = 0; Index < NumParams; ++Index)
ArgTypes.push_back(Args[Index]->getType());
FTy = FunctionType::get(ReturnType, ArgTypes, false);
Callee = ConvertOpToType(Callee, FTy->getPointerTo(), CurBBNo);
}
// Construct call.
I = CallInst::Create(Callee, Args);
cast<CallInst>(I)->setCallingConv(GetDecodedCallingConv(CCInfo>>1));
cast<CallInst>(I)->setTailCall(CCInfo & 1);
break;
}
case naclbitc::FUNC_CODE_INST_FORWARDTYPEREF:
// Build corresponding forward reference.
if (Record.size() != 2 ||
ValueList.createValueFwdRef(Record[0], getTypeByID(Record[1])))
return Error("Invalid FORWARDTYPEREF record");
continue;
}
if (InstallInstruction(CurBB, I))
return true;
// If this was a terminator instruction, move to the next block.
if (isa<TerminatorInst>(I)) {
++CurBBNo;
CurBB = getBasicBlock(CurBBNo);
}
// Non-void values get registered in the value table for future use.
if (I && !I->getType()->isVoidTy()) {
Value *NewVal = I;
if (NewVal->getType()->isPointerTy() &&
ValueList.getValueFwdRef(NextValueNo)) {
// Forward-referenced values cannot have pointer type.
NewVal = ConvertOpToScalar(NewVal, CurBBNo);
}
ValueList.AssignValue(NewVal, NextValueNo++);
}
}
OutOfRecordLoop:
// Add PHI conversions to corresponding incoming block, if not
// already in the block. Also clear all conversions after fixing
// PHI conversions.
for (unsigned I = 0, NumBBs = FunctionBBs.size(); I < NumBBs; ++I) {
BasicBlockInfo &BBInfo = FunctionBBs[I];
std::vector<CastInst*> &PhiCasts = BBInfo.PhiCasts;
for (std::vector<CastInst*>::iterator Iter = PhiCasts.begin(),
IterEnd = PhiCasts.end(); Iter != IterEnd; ++Iter) {
CastInst *Cast = *Iter;
if (Cast->getParent() == 0) {
BasicBlock *BB = BBInfo.BB;
BB->getInstList().insert(BB->getTerminator(), Cast);
}
}
PhiCasts.clear();
BBInfo.CastMap.clear();
}
// Check the function list for unresolved values.
if (Argument *A = dyn_cast<Argument>(ValueList.back())) {
if (A->getParent() == 0) {
// We found at least one unresolved value. Nuke them all to avoid leaks.
for (unsigned i = ModuleValueListSize, e = ValueList.size(); i != e; ++i){
if ((A = dyn_cast<Argument>(ValueList[i])) && A->getParent() == 0) {
A->replaceAllUsesWith(UndefValue::get(A->getType()));
delete A;
}
}
return Error("Never resolved value found in function!");
}
}
// Trim the value list down to the size it was before we parsed this function.
ValueList.shrinkTo(ModuleValueListSize);
FunctionBBs.clear();
DEBUG(dbgs() << "-> ParseFunctionBody\n");
return false;
}
/// FindFunctionInStream - Find the function body in the bitcode stream
bool NaClBitcodeReader::FindFunctionInStream(Function *F,
DenseMap<Function*, uint64_t>::iterator DeferredFunctionInfoIterator) {
while (DeferredFunctionInfoIterator->second == 0) {
if (Stream.AtEndOfStream())
return Error("Could not find Function in stream");
// ParseModule will parse the next body in the stream and set its
// position in the DeferredFunctionInfo map.
if (ParseModule(true)) return true;
}
return false;
}
//===----------------------------------------------------------------------===//
// GVMaterializer implementation
//===----------------------------------------------------------------------===//
bool NaClBitcodeReader::isMaterializable(const GlobalValue *GV) const {
if (const Function *F = dyn_cast<Function>(GV)) {
return F->isDeclaration() &&
DeferredFunctionInfo.count(const_cast<Function*>(F));
}
return false;
}
error_code NaClBitcodeReader::Materialize(GlobalValue *GV) {
Function *F = dyn_cast<Function>(GV);
// If it's not a function or is already material, ignore the request.
if (!F || !F->isMaterializable())
return error_code::success();
DenseMap<Function*, uint64_t>::iterator DFII = DeferredFunctionInfo.find(F);
assert(DFII != DeferredFunctionInfo.end() && "Deferred function not found!");
// If its position is recorded as 0, its body is somewhere in the stream
// but we haven't seen it yet.
if (DFII->second == 0) {
if (FindFunctionInStream(F, DFII)) {
// Refactoring upstream in LLVM 3.4 means we can no longer
// return an error string here, so return a catch-all error
// code.
// TODO(mseaborn): Clean up the reader to return a more
// meaningful error_code here.
return make_error_code(errc::invalid_argument);
}
}
// Move the bit stream to the saved position of the deferred function body.
Stream.JumpToBit(DFII->second);
if (ParseFunctionBody(F)) {
// TODO(mseaborn): Clean up the reader to return a more meaningful
// error_code instead of a catch-all.
return make_error_code(errc::invalid_argument);
}
// Upgrade any old intrinsic calls in the function.
for (UpgradedIntrinsicMap::iterator I = UpgradedIntrinsics.begin(),
E = UpgradedIntrinsics.end(); I != E; ++I) {
if (I->first != I->second) {
for (Value::use_iterator UI = I->first->use_begin(),
UE = I->first->use_end(); UI != UE; ) {
if (CallInst* CI = dyn_cast<CallInst>(*UI++))
UpgradeIntrinsicCall(CI, I->second);
}
}
}
return error_code::success();
}
bool NaClBitcodeReader::isDematerializable(const GlobalValue *GV) const {
const Function *F = dyn_cast<Function>(GV);
if (!F || F->isDeclaration())
return false;
return DeferredFunctionInfo.count(const_cast<Function*>(F));
}
void NaClBitcodeReader::Dematerialize(GlobalValue *GV) {
Function *F = dyn_cast<Function>(GV);
// If this function isn't dematerializable, this is a noop.
if (!F || !isDematerializable(F))
return;
assert(DeferredFunctionInfo.count(F) && "No info to read function later?");
// Just forget the function body, we can remat it later.
F->deleteBody();
}
error_code NaClBitcodeReader::MaterializeModule(Module *M) {
assert(M == TheModule &&
"Can only Materialize the Module this NaClBitcodeReader is attached to.");
// Iterate over the module, deserializing any functions that are still on
// disk.
for (Module::iterator F = TheModule->begin(), E = TheModule->end();
F != E; ++F) {
if (F->isMaterializable()) {
if (error_code EC = Materialize(F))
return EC;
}
}
// At this point, if there are any function bodies, the current bit is
// pointing to the END_BLOCK record after them. Now make sure the rest
// of the bits in the module have been read.
if (NextUnreadBit)
ParseModule(true);
// Upgrade any intrinsic calls that slipped through (should not happen!) and
// delete the old functions to clean up. We can't do this unless the entire
// module is materialized because there could always be another function body
// with calls to the old function.
for (std::vector<std::pair<Function*, Function*> >::iterator I =
UpgradedIntrinsics.begin(), E = UpgradedIntrinsics.end(); I != E; ++I) {
if (I->first != I->second) {
for (Value::use_iterator UI = I->first->use_begin(),
UE = I->first->use_end(); UI != UE; ) {
if (CallInst* CI = dyn_cast<CallInst>(*UI++))
UpgradeIntrinsicCall(CI, I->second);
}
if (!I->first->use_empty())
I->first->replaceAllUsesWith(I->second);
I->first->eraseFromParent();
}
}
std::vector<std::pair<Function*, Function*> >().swap(UpgradedIntrinsics);
return error_code::success();
}
bool NaClBitcodeReader::InitStream() {
if (LazyStreamer) return InitLazyStream();
return InitStreamFromBuffer();
}
bool NaClBitcodeReader::InitStreamFromBuffer() {
const unsigned char *BufPtr = (const unsigned char*)Buffer->getBufferStart();
const unsigned char *BufEnd = BufPtr+Buffer->getBufferSize();
if (Buffer->getBufferSize() & 3)
return Error("Bitcode stream should be a multiple of 4 bytes in length");
if (Header.Read(BufPtr, BufEnd))
return Error(Header.Unsupported());
StreamFile.reset(new NaClBitstreamReader(BufPtr, BufEnd));
Stream.init(*StreamFile);
if (AcceptHeader())
return Error(Header.Unsupported());
return false;
}
bool NaClBitcodeReader::InitLazyStream() {
if (Header.Read(LazyStreamer))
return Error(Header.Unsupported());
StreamFile.reset(new NaClBitstreamReader(LazyStreamer, Header.getHeaderSize()));
Stream.init(*StreamFile);
if (AcceptHeader())
return Error(Header.Unsupported());
return false;
}
//===----------------------------------------------------------------------===//
// External interface
//===----------------------------------------------------------------------===//
/// getNaClLazyBitcodeModule - lazy function-at-a-time loading from a file.
///
Module *llvm::getNaClLazyBitcodeModule(MemoryBuffer *Buffer,
LLVMContext& Context,
std::string *ErrMsg,
bool AcceptSupportedOnly) {
Module *M = new Module(Buffer->getBufferIdentifier(), Context);
NaClBitcodeReader *R =
new NaClBitcodeReader(Buffer, Context, AcceptSupportedOnly);
M->setMaterializer(R);
if (R->ParseBitcodeInto(M)) {
if (ErrMsg)
*ErrMsg = R->getErrorString();
delete M; // Also deletes R.
return 0;
}
// Have the NaClBitcodeReader dtor delete 'Buffer'.
R->setBufferOwned(true);
return M;
}
Module *llvm::getNaClStreamedBitcodeModule(const std::string &name,
StreamableMemoryObject *Streamer,
LLVMContext &Context,
std::string *ErrMsg,
bool AcceptSupportedOnly) {
Module *M = new Module(name, Context);
NaClBitcodeReader *R =
new NaClBitcodeReader(Streamer, Context, AcceptSupportedOnly);
M->setMaterializer(R);
if (R->ParseBitcodeInto(M)) {
if (ErrMsg)
*ErrMsg = R->getErrorString();
delete M; // Also deletes R.
return 0;
}
R->setBufferOwned(false); // no buffer to delete
return M;
}
/// NaClParseBitcodeFile - Read the specified bitcode file, returning the module.
/// If an error occurs, return null and fill in *ErrMsg if non-null.
Module *llvm::NaClParseBitcodeFile(MemoryBuffer *Buffer, LLVMContext& Context,
std::string *ErrMsg,
bool AcceptSupportedOnly){
Module *M = getNaClLazyBitcodeModule(Buffer, Context, ErrMsg,
AcceptSupportedOnly);
if (!M) return 0;
// Don't let the NaClBitcodeReader dtor delete 'Buffer', regardless of whether
// there was an error.
static_cast<NaClBitcodeReader*>(M->getMaterializer())->setBufferOwned(false);
// Read in the entire module, and destroy the NaClBitcodeReader.
if (M->MaterializeAllPermanently(ErrMsg)) {
delete M;
return 0;
}
// TODO: Restore the use-lists to the in-memory state when the bitcode was
// written. We must defer until the Module has been fully materialized.
return M;
}