aboutsummaryrefslogtreecommitdiff
path: root/lib/Bytecode/Reader/Reader.cpp
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2007-05-06 19:42:57 +0000
committerChris Lattner <sabre@nondot.org>2007-05-06 19:42:57 +0000
commita066e378e92805ca7468a721468180587923abdf (patch)
tree767a36463e5ac0afd8fa8a161e1eb0464f9d8c32 /lib/Bytecode/Reader/Reader.cpp
parentb11f1a9ee167d278923e741cd11ccd0bfe58f816 (diff)
remove bytecode reader
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@36882 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Bytecode/Reader/Reader.cpp')
-rw-r--r--lib/Bytecode/Reader/Reader.cpp2212
1 files changed, 0 insertions, 2212 deletions
diff --git a/lib/Bytecode/Reader/Reader.cpp b/lib/Bytecode/Reader/Reader.cpp
deleted file mode 100644
index e75f0fcd61..0000000000
--- a/lib/Bytecode/Reader/Reader.cpp
+++ /dev/null
@@ -1,2212 +0,0 @@
-//===- Reader.cpp - Code to read bytecode files ---------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file was developed by the LLVM research group and is distributed under
-// the University of Illinois Open Source License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This library implements the functionality defined in llvm/Bytecode/Reader.h
-//
-// Note that this library should be as fast as possible, reentrant, and
-// threadsafe!!
-//
-// TODO: Allow passing in an option to ignore the symbol table
-//
-//===----------------------------------------------------------------------===//
-
-#include "Reader.h"
-#include "llvm/Bytecode/BytecodeHandler.h"
-#include "llvm/BasicBlock.h"
-#include "llvm/CallingConv.h"
-#include "llvm/Constants.h"
-#include "llvm/InlineAsm.h"
-#include "llvm/Instructions.h"
-#include "llvm/ParameterAttributes.h"
-#include "llvm/TypeSymbolTable.h"
-#include "llvm/Bytecode/Format.h"
-#include "llvm/Config/alloca.h"
-#include "llvm/Support/GetElementPtrTypeIterator.h"
-#include "llvm/Support/MathExtras.h"
-#include "llvm/ADT/SmallVector.h"
-#include "llvm/ADT/StringExtras.h"
-#include <sstream>
-#include <algorithm>
-using 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 {
- ConstantPlaceHolder(); // DO NOT IMPLEMENT
- void operator=(const ConstantPlaceHolder &); // DO NOT IMPLEMENT
- public:
- Use Op;
- ConstantPlaceHolder(const Type *Ty)
- : ConstantExpr(Ty, Instruction::UserOp1, &Op, 1),
- Op(UndefValue::get(Type::Int32Ty), this) {
- }
- };
-}
-
-// Provide some details on error
-inline void BytecodeReader::error(const std::string& err) {
- ErrorMsg = err + " (Vers=" + itostr(RevisionNum) + ", Pos="
- + itostr(At-MemStart) + ")";
- if (Handler) Handler->handleError(ErrorMsg);
- longjmp(context,1);
-}
-
-//===----------------------------------------------------------------------===//
-// Bytecode Reading Methods
-//===----------------------------------------------------------------------===//
-
-/// Determine if the current block being read contains any more data.
-inline bool BytecodeReader::moreInBlock() {
- return At < BlockEnd;
-}
-
-/// Throw an error if we've read past the end of the current block
-inline void BytecodeReader::checkPastBlockEnd(const char * block_name) {
- if (At > BlockEnd)
- error(std::string("Attempt to read past the end of ") + block_name +
- " block.");
-}
-
-/// Read a whole unsigned integer
-inline unsigned BytecodeReader::read_uint() {
- if (At+4 > BlockEnd)
- error("Ran out of data reading uint!");
- At += 4;
- return At[-4] | (At[-3] << 8) | (At[-2] << 16) | (At[-1] << 24);
-}
-
-/// Read a variable-bit-rate encoded unsigned integer
-inline unsigned BytecodeReader::read_vbr_uint() {
- unsigned Shift = 0;
- unsigned Result = 0;
-
- do {
- if (At == BlockEnd)
- error("Ran out of data reading vbr_uint!");
- Result |= (unsigned)((*At++) & 0x7F) << Shift;
- Shift += 7;
- } while (At[-1] & 0x80);
- return Result;
-}
-
-/// Read a variable-bit-rate encoded unsigned 64-bit integer.
-inline uint64_t BytecodeReader::read_vbr_uint64() {
- unsigned Shift = 0;
- uint64_t Result = 0;
-
- do {
- if (At == BlockEnd)
- error("Ran out of data reading vbr_uint64!");
- Result |= (uint64_t)((*At++) & 0x7F) << Shift;
- Shift += 7;
- } while (At[-1] & 0x80);
- return Result;
-}
-
-/// Read a variable-bit-rate encoded signed 64-bit integer.
-inline int64_t BytecodeReader::read_vbr_int64() {
- uint64_t R = read_vbr_uint64();
- if (R & 1) {
- if (R != 1)
- return -(int64_t)(R >> 1);
- else // There is no such thing as -0 with integers. "-0" really means
- // 0x8000000000000000.
- return 1LL << 63;
- } else
- return (int64_t)(R >> 1);
-}
-
-/// Read a pascal-style string (length followed by text)
-inline std::string BytecodeReader::read_str() {
- unsigned Size = read_vbr_uint();
- const unsigned char *OldAt = At;
- At += Size;
- if (At > BlockEnd) // Size invalid?
- error("Ran out of data reading a string!");
- return std::string((char*)OldAt, Size);
-}
-
-void BytecodeReader::read_str(SmallVectorImpl<char> &StrData) {
- StrData.clear();
- unsigned Size = read_vbr_uint();
- const unsigned char *OldAt = At;
- At += Size;
- if (At > BlockEnd) // Size invalid?
- error("Ran out of data reading a string!");
- StrData.append(OldAt, At);
-}
-
-
-/// Read an arbitrary block of data
-inline void BytecodeReader::read_data(void *Ptr, void *End) {
- unsigned char *Start = (unsigned char *)Ptr;
- unsigned Amount = (unsigned char *)End - Start;
- if (At+Amount > BlockEnd)
- error("Ran out of data!");
- std::copy(At, At+Amount, Start);
- At += Amount;
-}
-
-/// Read a float value in little-endian order
-inline void BytecodeReader::read_float(float& FloatVal) {
- /// FIXME: This isn't optimal, it has size problems on some platforms
- /// where FP is not IEEE.
- FloatVal = BitsToFloat(At[0] | (At[1] << 8) | (At[2] << 16) | (At[3] << 24));
- At+=sizeof(uint32_t);
-}
-
-/// Read a double value in little-endian order
-inline void BytecodeReader::read_double(double& DoubleVal) {
- /// FIXME: This isn't optimal, it has size problems on some platforms
- /// where FP is not IEEE.
- DoubleVal = BitsToDouble((uint64_t(At[0]) << 0) | (uint64_t(At[1]) << 8) |
- (uint64_t(At[2]) << 16) | (uint64_t(At[3]) << 24) |
- (uint64_t(At[4]) << 32) | (uint64_t(At[5]) << 40) |
- (uint64_t(At[6]) << 48) | (uint64_t(At[7]) << 56));
- At+=sizeof(uint64_t);
-}
-
-/// Read a block header and obtain its type and size
-inline void BytecodeReader::read_block(unsigned &Type, unsigned &Size) {
- Size = read_uint(); // Read the header
- Type = Size & 0x1F; // mask low order five bits to get type
- Size >>= 5; // high order 27 bits is the size
- BlockStart = At;
- if (At + Size > BlockEnd)
- error("Attempt to size a block past end of memory");
- BlockEnd = At + Size;
- if (Handler) Handler->handleBlock(Type, BlockStart, Size);
-}
-
-//===----------------------------------------------------------------------===//
-// IR Lookup Methods
-//===----------------------------------------------------------------------===//
-
-/// Determine if a type id has an implicit null value
-inline bool BytecodeReader::hasImplicitNull(unsigned TyID) {
- return TyID != Type::LabelTyID && TyID != Type::VoidTyID;
-}
-
-/// Obtain a type given a typeid and account for things like function level vs
-/// module level, and the offsetting for the primitive types.
-const Type *BytecodeReader::getType(unsigned ID) {
- if (ID <= Type::LastPrimitiveTyID)
- if (const Type *T = Type::getPrimitiveType((Type::TypeID)ID))
- return T; // Asked for a primitive type...
-
- // Otherwise, derived types need offset...
- ID -= Type::FirstDerivedTyID;
-
- // Is it a module-level type?
- if (ID < ModuleTypes.size())
- return ModuleTypes[ID].get();
-
- // Nope, is it a function-level type?
- ID -= ModuleTypes.size();
- if (ID < FunctionTypes.size())
- return FunctionTypes[ID].get();
-
- error("Illegal type reference!");
- return Type::VoidTy;
-}
-
-/// This method just saves some coding. It uses read_vbr_uint to read in a
-/// type id, errors that its not the type type, and then calls getType to
-/// return the type value.
-inline const Type* BytecodeReader::readType() {
- return getType(read_vbr_uint());
-}
-
-/// Get the slot number associated with a type accounting for primitive
-/// types and function level vs module level.
-unsigned BytecodeReader::getTypeSlot(const Type *Ty) {
- if (Ty->isPrimitiveType())
- return Ty->getTypeID();
-
- // Check the function level types first...
- TypeListTy::iterator I = std::find(FunctionTypes.begin(),
- FunctionTypes.end(), Ty);
-
- if (I != FunctionTypes.end())
- return Type::FirstDerivedTyID + ModuleTypes.size() +
- (&*I - &FunctionTypes[0]);
-
- // If we don't have our cache yet, build it now.
- if (ModuleTypeIDCache.empty()) {
- unsigned N = 0;
- ModuleTypeIDCache.reserve(ModuleTypes.size());
- for (TypeListTy::iterator I = ModuleTypes.begin(), E = ModuleTypes.end();
- I != E; ++I, ++N)
- ModuleTypeIDCache.push_back(std::make_pair(*I, N));
-
- std::sort(ModuleTypeIDCache.begin(), ModuleTypeIDCache.end());
- }
-
- // Binary search the cache for the entry.
- std::vector<std::pair<const Type*, unsigned> >::iterator IT =
- std::lower_bound(ModuleTypeIDCache.begin(), ModuleTypeIDCache.end(),
- std::make_pair(Ty, 0U));
- if (IT == ModuleTypeIDCache.end() || IT->first != Ty)
- error("Didn't find type in ModuleTypes.");
-
- return Type::FirstDerivedTyID + IT->second;
-}
-
-/// Retrieve a value of a given type and slot number, possibly creating
-/// it if it doesn't already exist.
-Value * BytecodeReader::getValue(unsigned type, unsigned oNum, bool Create) {
- assert(type != Type::LabelTyID && "getValue() cannot get blocks!");
- unsigned Num = oNum;
-
- // By default, the global type id is the type id passed in
- unsigned GlobalTyID = type;
-
- if (hasImplicitNull(GlobalTyID)) {
- const Type *Ty = getType(type);
- if (!isa<OpaqueType>(Ty)) {
- if (Num == 0)
- return Constant::getNullValue(Ty);
- --Num;
- }
- }
-
- if (GlobalTyID < ModuleValues.size())
- if (ValueList *Globals = ModuleValues[GlobalTyID]) {
- if (Num < Globals->size())
- return Globals->getOperand(Num);
- Num -= Globals->size();
- }
-
- if (type < FunctionValues.size())
- if (ValueList *Locals = FunctionValues[type])
- if (Num < Locals->size())
- return Locals->getOperand(Num);
-
- // We did not find the value.
-
- if (!Create) return 0; // Do not create a placeholder?
-
- // Did we already create a place holder?
- std::pair<unsigned,unsigned> KeyValue(type, oNum);
- ForwardReferenceMap::iterator I = ForwardReferences.lower_bound(KeyValue);
- if (I != ForwardReferences.end() && I->first == KeyValue)
- return I->second; // We have already created this placeholder
-
- // If the type exists (it should)
- if (const Type* Ty = getType(type)) {
- // Create the place holder
- Value *Val = new Argument(Ty);
- ForwardReferences.insert(I, std::make_pair(KeyValue, Val));
- return Val;
- }
- error("Can't create placeholder for value of type slot #" + utostr(type));
- return 0; // just silence warning, error calls longjmp
-}
-
-
-/// Just like getValue, except that it returns a null pointer
-/// only on error. It always returns a constant (meaning that if the value is
-/// defined, but is not a constant, that is an error). If the specified
-/// constant hasn't been parsed yet, a placeholder is defined and used.
-/// Later, after the real value is parsed, the placeholder is eliminated.
-Constant* BytecodeReader::getConstantValue(unsigned TypeSlot, unsigned Slot) {
- if (Value *V = getValue(TypeSlot, Slot, false))
- if (Constant *C = dyn_cast<Constant>(V))
- return C; // If we already have the value parsed, just return it
- else
- error("Value for slot " + utostr(Slot) +
- " is expected to be a constant!");
-
- std::pair<unsigned, unsigned> Key(TypeSlot, Slot);
- ConstantRefsType::iterator I = ConstantFwdRefs.lower_bound(Key);
-
- if (I != ConstantFwdRefs.end() && I->first == Key) {
- return I->second;
- } else {
- // Create a placeholder for the constant reference and
- // keep track of the fact that we have a forward ref to recycle it
- Constant *C = new ConstantPlaceHolder(getType(TypeSlot));
-
- // Keep track of the fact that we have a forward ref to recycle it
- ConstantFwdRefs.insert(I, std::make_pair(Key, C));
- return C;
- }
-}
-
-//===----------------------------------------------------------------------===//
-// IR Construction Methods
-//===----------------------------------------------------------------------===//
-
-/// As values are created, they are inserted into the appropriate place
-/// with this method. The ValueTable argument must be one of ModuleValues
-/// or FunctionValues data members of this class.
-unsigned BytecodeReader::insertValue(Value *Val, unsigned type,
- ValueTable &ValueTab) {
- if (ValueTab.size() <= type)
- ValueTab.resize(type+1);
-
- if (!ValueTab[type]) ValueTab[type] = new ValueList();
-
- ValueTab[type]->push_back(Val);
-
- bool HasOffset = hasImplicitNull(type) && !isa<OpaqueType>(Val->getType());
- return ValueTab[type]->size()-1 + HasOffset;
-}
-
-/// Insert the arguments of a function as new values in the reader.
-void BytecodeReader::insertArguments(Function* F) {
- const FunctionType *FT = F->getFunctionType();
- Function::arg_iterator AI = F->arg_begin();
- for (FunctionType::param_iterator It = FT->param_begin();
- It != FT->param_end(); ++It, ++AI)
- insertValue(AI, getTypeSlot(AI->getType()), FunctionValues);
-}
-
-//===----------------------------------------------------------------------===//
-// Bytecode Parsing Methods
-//===----------------------------------------------------------------------===//
-
-/// This method parses a single instruction. The instruction is
-/// inserted at the end of the \p BB provided. The arguments of
-/// the instruction are provided in the \p Oprnds vector.
-void BytecodeReader::ParseInstruction(SmallVector<unsigned, 8> &Oprnds,
- BasicBlock* BB) {
- BufPtr SaveAt = At;
-
- // Clear instruction data
- Oprnds.clear();
- unsigned iType = 0;
- unsigned Opcode = 0;
- unsigned Op = read_uint();
-
- // bits Instruction format: Common to all formats
- // --------------------------
- // 01-00: Opcode type, fixed to 1.
- // 07-02: Opcode
- Opcode = (Op >> 2) & 63;
- Oprnds.resize((Op >> 0) & 03);
-
- // Extract the operands
- switch (Oprnds.size()) {
- case 1:
- // bits Instruction format:
- // --------------------------
- // 19-08: Resulting type plane
- // 31-20: Operand #1 (if set to (2^12-1), then zero operands)
- //
- iType = (Op >> 8) & 4095;
- Oprnds[0] = (Op >> 20) & 4095;
- if (Oprnds[0] == 4095) // Handle special encoding for 0 operands...
- Oprnds.resize(0);
- break;
- case 2:
- // bits Instruction format:
- // --------------------------
- // 15-08: Resulting type plane
- // 23-16: Operand #1
- // 31-24: Operand #2
- //
- iType = (Op >> 8) & 255;
- Oprnds[0] = (Op >> 16) & 255;
- Oprnds[1] = (Op >> 24) & 255;
- break;
- case 3:
- // bits Instruction format:
- // --------------------------
- // 13-08: Resulting type plane
- // 19-14: Operand #1
- // 25-20: Operand #2
- // 31-26: Operand #3
- //
- iType = (Op >> 8) & 63;
- Oprnds[0] = (Op >> 14) & 63;
- Oprnds[1] = (Op >> 20) & 63;
- Oprnds[2] = (Op >> 26) & 63;
- break;
- case 0:
- At -= 4; // Hrm, try this again...
- Opcode = read_vbr_uint();
- Opcode >>= 2;
- iType = read_vbr_uint();
-
- unsigned NumOprnds = read_vbr_uint();
- Oprnds.resize(NumOprnds);
-
- if (NumOprnds == 0)
- error("Zero-argument instruction found; this is invalid.");
-
- for (unsigned i = 0; i != NumOprnds; ++i)
- Oprnds[i] = read_vbr_uint();
- break;
- }
-
- const Type *InstTy = getType(iType);
-
- // Make the necessary adjustments for dealing with backwards compatibility
- // of opcodes.
- Instruction* Result = 0;
-
- // First, handle the easy binary operators case
- if (Opcode >= Instruction::BinaryOpsBegin &&
- Opcode < Instruction::BinaryOpsEnd && Oprnds.size() == 2) {
- Result = BinaryOperator::create(Instruction::BinaryOps(Opcode),
- getValue(iType, Oprnds[0]),
- getValue(iType, Oprnds[1]));
- } else {
- // Indicate that we don't think this is a call instruction (yet).
- // Process based on the Opcode read
- switch (Opcode) {
- default: // There was an error, this shouldn't happen.
- if (Result == 0)
- error("Illegal instruction read!");
- break;
- case Instruction::VAArg:
- if (Oprnds.size() != 2)
- error("Invalid VAArg instruction!");
- Result = new VAArgInst(getValue(iType, Oprnds[0]),
- getType(Oprnds[1]));
- break;
- case Instruction::ExtractElement: {
- if (Oprnds.size() != 2)
- error("Invalid extractelement instruction!");
- Value *V1 = getValue(iType, Oprnds[0]);
- Value *V2 = getValue(Int32TySlot, Oprnds[1]);
-
- if (!ExtractElementInst::isValidOperands(V1, V2))
- error("Invalid extractelement instruction!");
-
- Result = new ExtractElementInst(V1, V2);
- break;
- }
- case Instruction::InsertElement: {
- const VectorType *VectorTy = dyn_cast<VectorType>(InstTy);
- if (!VectorTy || Oprnds.size() != 3)
- error("Invalid insertelement instruction!");
-
- Value *V1 = getValue(iType, Oprnds[0]);
- Value *V2 = getValue(getTypeSlot(VectorTy->getElementType()),Oprnds[1]);
- Value *V3 = getValue(Int32TySlot, Oprnds[2]);
-
- if (!InsertElementInst::isValidOperands(V1, V2, V3))
- error("Invalid insertelement instruction!");
- Result = new InsertElementInst(V1, V2, V3);
- break;
- }
- case Instruction::ShuffleVector: {
- const VectorType *VectorTy = dyn_cast<VectorType>(InstTy);
- if (!VectorTy || Oprnds.size() != 3)
- error("Invalid shufflevector instruction!");
- Value *V1 = getValue(iType, Oprnds[0]);
- Value *V2 = getValue(iType, Oprnds[1]);
- const VectorType *EltTy =
- VectorType::get(Type::Int32Ty, VectorTy->getNumElements());
- Value *V3 = getValue(getTypeSlot(EltTy), Oprnds[2]);
- if (!ShuffleVectorInst::isValidOperands(V1, V2, V3))
- error("Invalid shufflevector instruction!");
- Result = new ShuffleVectorInst(V1, V2, V3);
- break;
- }
- case Instruction::Trunc:
- if (Oprnds.size() != 2)
- error("Invalid cast instruction!");
- Result = new TruncInst(getValue(iType, Oprnds[0]),
- getType(Oprnds[1]));
- break;
- case Instruction::ZExt:
- if (Oprnds.size() != 2)
- error("Invalid cast instruction!");
- Result = new ZExtInst(getValue(iType, Oprnds[0]),
- getType(Oprnds[1]));
- break;
- case Instruction::SExt:
- if (Oprnds.size() != 2)
- error("Invalid Cast instruction!");
- Result = new SExtInst(getValue(iType, Oprnds[0]),
- getType(Oprnds[1]));
- break;
- case Instruction::FPTrunc:
- if (Oprnds.size() != 2)
- error("Invalid cast instruction!");
- Result = new FPTruncInst(getValue(iType, Oprnds[0]),
- getType(Oprnds[1]));
- break;
- case Instruction::FPExt:
- if (Oprnds.size() != 2)
- error("Invalid cast instruction!");
- Result = new FPExtInst(getValue(iType, Oprnds[0]),
- getType(Oprnds[1]));
- break;
- case Instruction::UIToFP:
- if (Oprnds.size() != 2)
- error("Invalid cast instruction!");
- Result = new UIToFPInst(getValue(iType, Oprnds[0]),
- getType(Oprnds[1]));
- break;
- case Instruction::SIToFP:
- if (Oprnds.size() != 2)
- error("Invalid cast instruction!");
- Result = new SIToFPInst(getValue(iType, Oprnds[0]),
- getType(Oprnds[1]));
- break;
- case Instruction::FPToUI:
- if (Oprnds.size() != 2)
- error("Invalid cast instruction!");
- Result = new FPToUIInst(getValue(iType, Oprnds[0]),
- getType(Oprnds[1]));
- break;
- case Instruction::FPToSI:
- if (Oprnds.size() != 2)
- error("Invalid cast instruction!");
- Result = new FPToSIInst(getValue(iType, Oprnds[0]),
- getType(Oprnds[1]));
- break;
- case Instruction::IntToPtr:
- if (Oprnds.size() != 2)
- error("Invalid cast instruction!");
- Result = new IntToPtrInst(getValue(iType, Oprnds[0]),
- getType(Oprnds[1]));
- break;
- case Instruction::PtrToInt:
- if (Oprnds.size() != 2)
- error("Invalid cast instruction!");
- Result = new PtrToIntInst(getValue(iType, Oprnds[0]),
- getType(Oprnds[1]));
- break;
- case Instruction::BitCast:
- if (Oprnds.size() != 2)
- error("Invalid cast instruction!");
- Result = new BitCastInst(getValue(iType, Oprnds[0]),
- getType(Oprnds[1]));
- break;
- case Instruction::Select:
- if (Oprnds.size() != 3)
- error("Invalid Select instruction!");
- Result = new SelectInst(getValue(BoolTySlot, Oprnds[0]),
- getValue(iType, Oprnds[1]),
- getValue(iType, Oprnds[2]));
- break;
- case Instruction::PHI: {
- if (Oprnds.size() == 0 || (Oprnds.size() & 1))
- error("Invalid phi node encountered!");
-
- PHINode *PN = new PHINode(InstTy);
- PN->reserveOperandSpace(Oprnds.size());
- for (unsigned i = 0, e = Oprnds.size(); i != e; i += 2)
- PN->addIncoming(
- getValue(iType, Oprnds[i]), getBasicBlock(Oprnds[i+1]));
- Result = PN;
- break;
- }
- case Instruction::ICmp:
- case Instruction::FCmp:
- if (Oprnds.size() != 3)
- error("Cmp instructions requires 3 operands");
- // These instructions encode the comparison predicate as the 3rd operand.
- Result = CmpInst::create(Instruction::OtherOps(Opcode),
- static_cast<unsigned short>(Oprnds[2]),
- getValue(iType, Oprnds[0]), getValue(iType, Oprnds[1]));
- break;
- case Instruction::Ret:
- if (Oprnds.size() == 0)
- Result = new ReturnInst();
- else if (Oprnds.size() == 1)
- Result = new ReturnInst(getValue(iType, Oprnds[0]));
- else
- error("Unrecognized instruction!");
- break;
-
- case Instruction::Br:
- if (Oprnds.size() == 1)
- Result = new BranchInst(getBasicBlock(Oprnds[0]));
- else if (Oprnds.size() == 3)
- Result = new BranchInst(getBasicBlock(Oprnds[0]),
- getBasicBlock(Oprnds[1]), getValue(BoolTySlot, Oprnds[2]));
- else
- error("Invalid number of operands for a 'br' instruction!");
- break;
- case Instruction::Switch: {
- if (Oprnds.size() & 1)
- error("Switch statement with odd number of arguments!");
-
- SwitchInst *I = new SwitchInst(getValue(iType, Oprnds[0]),
- getBasicBlock(Oprnds[1]),
- Oprnds.size()/2-1);
- for (unsigned i = 2, e = Oprnds.size(); i != e; i += 2)
- I->addCase(cast<ConstantInt>(getValue(iType, Oprnds[i])),
- getBasicBlock(Oprnds[i+1]));
- Result = I;
- break;
- }
- case 58: // Call with extra operand for calling conv
- case 59: // tail call, Fast CC
- case 60: // normal call, Fast CC
- case 61: // tail call, C Calling Conv
- case Instruction::Call: { // Normal Call, C Calling Convention
- if (Oprnds.size() == 0)
- error("Invalid call instruction encountered!");
- Value *F = getValue(iType, Oprnds[0]);
-
- unsigned CallingConv = CallingConv::C;
- bool isTailCall = false;
-
- if (Opcode == 61 || Opcode == 59)
- isTailCall = true;
-
- if (Opcode == 58) {
- isTailCall = Oprnds.back() & 1;
- CallingConv = Oprnds.back() >> 1;
- Oprnds.pop_back();
- } else if (Opcode == 59 || Opcode == 60) {
- CallingConv = CallingConv::Fast;
- }
-
- // Check to make sure we have a pointer to function type
- const PointerType *PTy = dyn_cast<PointerType>(F->getType());
- if (PTy == 0) error("Call to non function pointer value!");
- const FunctionType *FTy = dyn_cast<FunctionType>(PTy->getElementType());
- if (FTy == 0) error("Call to non function pointer value!");
-
- SmallVector<Value *, 8> Params;
- if (!FTy->isVarArg()) {
- FunctionType::param_iterator It = FTy->param_begin();
-
- for (unsigned i = 1, e = Oprnds.size(); i != e; ++i) {
- if (It == FTy->param_end())
- error("Invalid call instruction!");
- Params.push_back(getValue(getTypeSlot(*It++), Oprnds[i]));
- }
- if (It != FTy->param_end())
- error("Invalid call instruction!");
- } else {
- Oprnds.erase(Oprnds.begin(), Oprnds.begin()+1);
-
- unsigned FirstVariableOperand;
- if (Oprnds.size() < FTy->getNumParams())
- error("Call instruction missing operands!");
-
- // Read all of the fixed arguments
- for (unsigned i = 0, e = FTy->getNumParams(); i != e; ++i)
- Params.push_back(
- getValue(getTypeSlot(FTy->getParamType(i)),Oprnds[i]));
-
- FirstVariableOperand = FTy->getNumParams();
-
- if ((Oprnds.size()-FirstVariableOperand) & 1)
- error("Invalid call instruction!"); // Must be pairs of type/value
-
- for (unsigned i = FirstVariableOperand, e = Oprnds.size();
- i != e; i += 2)
- Params.push_back(getValue(Oprnds[i], Oprnds[i+1]));
- }
-
- Result = new CallInst(F, &Params[0], Params.size());
- if (isTailCall) cast<CallInst>(Result)->setTailCall();
- if (CallingConv) cast<CallInst>(Result)->setCallingConv(CallingConv);
- break;
- }
- case Instruction::Invoke: { // Invoke C CC
- if (Oprnds.size() < 3)
- error("Invalid invoke instruction!");
- Value *F = getValue(iType, Oprnds[0]);
-
- // Check to make sure we have a pointer to function type
- const PointerType *PTy = dyn_cast<PointerType>(F->getType());
- if (PTy == 0)
- error("Invoke to non function pointer value!");
- const FunctionType *FTy = dyn_cast<FunctionType>(PTy->getElementType());
- if (FTy == 0)
- error("Invoke to non function pointer value!");
-
- SmallVector<Value *, 8> Params;
- BasicBlock *Normal, *Except;
- unsigned CallingConv = Oprnds.back();
- Oprnds.pop_back();
-
- if (!FTy->isVarArg()) {
- Normal = getBasicBlock(Oprnds[1]);
- Except = getBasicBlock(Oprnds[2]);
-
- FunctionType::param_iterator It = FTy->param_begin();
- for (unsigned i = 3, e = Oprnds.size(); i != e; ++i) {
- if (It == FTy->param_end())
- error("Invalid invoke instruction!");
- Params.push_back(getValue(getTypeSlot(*It++), Oprnds[i]));
- }
- if (It != FTy->param_end())
- error("Invalid invoke instruction!");
- } else {
- Oprnds.erase(Oprnds.begin(), Oprnds.begin()+1);
-
- Normal = getBasicBlock(Oprnds[0]);
- Except = getBasicBlock(Oprnds[1]);
-
- unsigned FirstVariableArgument = FTy->getNumParams()+2;
- for (unsigned i = 2; i != FirstVariableArgument; ++i)
- Params.push_back(getValue(getTypeSlot(FTy->getParamType(i-2)),
- Oprnds[i]));
-
- // Must be type/value pairs. If not, error out.
- if (Oprnds.size()-FirstVariableArgument & 1)
- error("Invalid invoke instruction!");
-
- for (unsigned i = FirstVariableArgument; i < Oprnds.size(); i += 2)
- Params.push_back(getValue(Oprnds[i], Oprnds[i+1]));
- }
-
- Result = new InvokeInst(F, Normal, Except, &Params[0], Params.size());
- if (CallingConv) cast<InvokeInst>(Result)->setCallingConv(CallingConv);
- break;
- }
- case Instruction::Malloc: {
- unsigned Align = 0;
- if (Oprnds.size() == 2)
- Align = (1 << Oprnds[1]) >> 1;
- else if (Oprnds.size() > 2)
- error("Invalid malloc instruction!");
- if (!isa<PointerType>(InstTy))
- error("Invalid malloc instruction!");
-
- Result = new MallocInst(cast<PointerType>(InstTy)->getElementType(),
- getValue(Int32TySlot, Oprnds[0]), Align);
- break;
- }
- case Instruction::Alloca: {
- unsigned Align = 0;
- if (Oprnds.size() == 2)
- Align = (1 << Oprnds[1]) >> 1;
- else if (Oprnds.size() > 2)
- error("Invalid alloca instruction!");
- if (!isa<PointerType>(InstTy))
- error("Invalid alloca instruction!");
-
- Result = new AllocaInst(cast<PointerType>(InstTy)->getElementType(),
- getValue(Int32TySlot, Oprnds[0]), Align);
- break;
- }
- case Instruction::Free:
- if (!isa<PointerType>(InstTy))
- error("Invalid free instruction!");
- Result = new FreeInst(getValue(iType, Oprnds[0]));
- break;
- case Instruction::GetElementPtr: {
- if (Oprnds.size() == 0 || !isa<PointerType>(InstTy))
- error("Invalid getelementptr instruction!");
-
- SmallVector<Value*, 8> Idx;
-
- const Type *NextTy = InstTy;
- for (unsigned i = 1, e = Oprnds.size(); i != e; ++i) {
- const CompositeType *TopTy = dyn_cast_or_null<CompositeType>(NextTy);
- if (!TopTy)
- error("Invalid getelementptr instruction!");
-
- unsigned ValIdx = Oprnds[i];
- unsigned IdxTy = 0;
- // Struct indices are always uints, sequential type indices can be
- // any of the 32 or 64-bit integer types. The actual choice of
- // type is encoded in the low bit of the slot number.
- if (isa<StructType>(TopTy))
- IdxTy = Int32TySlot;
- else {
- switch (ValIdx & 1) {
- default:
- case 0: IdxTy = Int32TySlot; break;
- case 1: IdxTy = Int64TySlot; break;
- }
- ValIdx >>= 1;
- }
- Idx.push_back(getValue(IdxTy, ValIdx));
- NextTy = GetElementPtrInst::getIndexedType(InstTy, &Idx[0], Idx.size(),
- true);
- }
-
- Result = new GetElementPtrInst(getValue(iType, Oprnds[0]),
- &Idx[0], Idx.size());
- break;
- }
- case 62: { // attributed load
- if (Oprnds.size() != 2 || !isa<PointerType>(InstTy))
- error("Invalid attributed load instruction!");
- Result = new LoadInst(getValue(iType, Oprnds[0]), "", (Oprnds[1] & 1),
- (1 << (Oprnds[1]>>1)) >> 1);
- break;
- }
- case Instruction::Load:
- if (Oprnds.size() != 1 || !isa<PointerType>(InstTy))
- error("Invalid load instruction!");
- Result = new LoadInst(getValue(iType, Oprnds[0]), "");
- break;
- case 63: { // attributed store
- if (!isa<PointerType>(InstTy) || Oprnds.size() != 3)
- error("Invalid attributed store instruction!");
-
- Value *Ptr = getValue(iType, Oprnds[1]);
- const Type *ValTy = cast<PointerType>(Ptr->getType())->getElementType();
- Result = new StoreInst(getValue(getTypeSlot(ValTy), Oprnds[0]), Ptr,
- (Oprnds[2] & 1),
- (1 << (Oprnds[2]>>1)) >> 1);
- break;
- }
- case Instruction::Store: {
- if (!isa<PointerType>(InstTy) || Oprnds.size() != 2)
- error("Invalid store instruction!");
-
- Value *Ptr = getValue(iType, Oprnds[1]);
- const Type *ValTy = cast<PointerType>(Ptr->getType())->getElementType();
- Result = new StoreInst(getValue(getTypeSlot(ValTy), Oprnds[0]), Ptr,
- Opcode == 63);
- break;
- }
- case Instruction::Unwind:
- if (Oprnds.size() != 0) error("Invalid unwind instruction!");
- Result = new UnwindInst();
- break;
- case Instruction::Unreachable:
- if (Oprnds.size() != 0) error("Invalid unreachable instruction!");
- Result = new UnreachableInst();
- break;
- } // end switch(Opcode)
- } // end if !Result
-
- BB->getInstList().push_back(Result);
-
- unsigned TypeSlot;
- if (Result->getType() == InstTy)
- TypeSlot = iType;
- else
- TypeSlot = getTypeSlot(Result->getType());
-
- // We have enough info to inform the handler now.
- if (Handler)
- Handler->handleInstruction(Opcode, InstTy, &Oprnds[0], Oprnds.size(),
- Result, At-SaveAt);
-
- insertValue(Result, TypeSlot, FunctionValues);
-}
-
-/// Get a particular numbered basic block, which might be a forward reference.
-/// This works together with ParseInstructionList to handle these forward
-/// references in a clean manner. This function is used when constructing
-/// phi, br, switch, and other instructions that reference basic blocks.
-/// Blocks are numbered sequentially as they appear in the function.
-BasicBlock *BytecodeReader::getBasicBlock(unsigned ID) {
- // Make sure there is room in the table...
- if (ParsedBasicBlocks.size() <= ID) ParsedBasicBlocks.resize(ID+1);
-
- // First check to see if this is a backwards reference, i.e. this block
- // has already been created, or if the forward reference has already
- // been created.
- if (ParsedBasicBlocks[ID])
- return ParsedBasicBlocks[ID];
-
- // Otherwise, the basic block has not yet been created. Do so and add it to
- // the ParsedBasicBlocks list.
- return ParsedBasicBlocks[ID] = new BasicBlock();
-}
-
-/// Parse all of the BasicBlock's & Instruction's in the body of a function.
-/// In post 1.0 bytecode files, we no longer emit basic block individually,
-/// in order to avoid per-basic-block overhead.
-/// @returns the number of basic blocks encountered.
-unsigned BytecodeReader::ParseInstructionList(Function* F) {
- unsigned BlockNo = 0;
- SmallVector<unsigned, 8> Args;
-
- while (moreInBlock()) {
- if (Handler) Handler->handleBasicBlockBegin(BlockNo);
- BasicBlock *BB;
- if (ParsedBasicBlocks.size() == BlockNo)
- ParsedBasicBlocks.push_back(BB = new BasicBlock());
- else if (ParsedBasicBlocks[BlockNo] == 0)
- BB = ParsedBasicBlocks[BlockNo] = new BasicBlock();
- else
- BB = ParsedBasicBlocks[BlockNo];
- ++BlockNo;
- F->getBasicBlockList().push_back(BB);
-
- // Read instructions into this basic block until we get to a terminator
- while (moreInBlock() && !BB->getTerminator())
- ParseInstruction(Args, BB);
-
- if (!BB->getTerminator())
- error("Non-terminated basic block found!");
-
- if (Handler) Handler->handleBasicBlockEnd(BlockNo-1);
- }
-
- return BlockNo;
-}