diff options
Diffstat (limited to 'lib/Bytecode')
-rw-r--r-- | lib/Bytecode/Reader/Reader.cpp | 80 | ||||
-rw-r--r-- | lib/Bytecode/Reader/Reader.h | 14 | ||||
-rw-r--r-- | lib/Bytecode/Writer/SlotCalculator.cpp | 75 | ||||
-rw-r--r-- | lib/Bytecode/Writer/SlotCalculator.h | 3 | ||||
-rw-r--r-- | lib/Bytecode/Writer/Writer.cpp | 62 |
5 files changed, 139 insertions, 95 deletions
diff --git a/lib/Bytecode/Reader/Reader.cpp b/lib/Bytecode/Reader/Reader.cpp index 787d000c23..ce3826cb24 100644 --- a/lib/Bytecode/Reader/Reader.cpp +++ b/lib/Bytecode/Reader/Reader.cpp @@ -189,7 +189,7 @@ inline bool BytecodeReader::hasImplicitNull(unsigned TyID) { /// Obtain a type given a typeid and account for things like compaction tables, /// function level vs module level, and the offsetting for the primitive types. const Type *BytecodeReader::getType(unsigned ID) { - if (ID < Type::FirstDerivedTyID) + if (ID <= Type::LastPrimitiveTyID) if (const Type *T = Type::getPrimitiveType((Type::TypeID)ID)) return T; // Asked for a primitive type... @@ -573,7 +573,7 @@ void BytecodeReader::ParseInstruction(std::vector<unsigned> &Oprnds, if (Oprnds.size() != 2) error("Invalid extractelement instruction!"); Value *V1 = getValue(iType, Oprnds[0]); - Value *V2 = getValue(Type::Int32TyID, Oprnds[1]); + Value *V2 = getValue(Int32TySlot, Oprnds[1]); if (!ExtractElementInst::isValidOperands(V1, V2)) error("Invalid extractelement instruction!"); @@ -588,7 +588,7 @@ void BytecodeReader::ParseInstruction(std::vector<unsigned> &Oprnds, Value *V1 = getValue(iType, Oprnds[0]); Value *V2 = getValue(getTypeSlot(PackedTy->getElementType()),Oprnds[1]); - Value *V3 = getValue(Type::Int32TyID, Oprnds[2]); + Value *V3 = getValue(Int32TySlot, Oprnds[2]); if (!InsertElementInst::isValidOperands(V1, V2, V3)) error("Invalid insertelement instruction!"); @@ -684,7 +684,7 @@ void BytecodeReader::ParseInstruction(std::vector<unsigned> &Oprnds, case Instruction::Select: if (Oprnds.size() != 3) error("Invalid Select instruction!"); - Result = new SelectInst(getValue(Type::Int1TyID, Oprnds[0]), + Result = new SelectInst(getValue(BoolTySlot, Oprnds[0]), getValue(iType, Oprnds[1]), getValue(iType, Oprnds[2])); break; @@ -714,7 +714,7 @@ void BytecodeReader::ParseInstruction(std::vector<unsigned> &Oprnds, case Instruction::AShr: Result = new ShiftInst(Instruction::OtherOps(Opcode), getValue(iType, Oprnds[0]), - getValue(Type::Int8TyID, Oprnds[1])); + getValue(Int8TySlot, Oprnds[1])); break; case Instruction::Ret: if (Oprnds.size() == 0) @@ -730,7 +730,7 @@ void BytecodeReader::ParseInstruction(std::vector<unsigned> &Oprnds, Result = new BranchInst(getBasicBlock(Oprnds[0])); else if (Oprnds.size() == 3) Result = new BranchInst(getBasicBlock(Oprnds[0]), - getBasicBlock(Oprnds[1]), getValue(Type::Int1TyID , Oprnds[2])); + getBasicBlock(Oprnds[1]), getValue(BoolTySlot, Oprnds[2])); else error("Invalid number of operands for a 'br' instruction!"); break; @@ -877,7 +877,7 @@ void BytecodeReader::ParseInstruction(std::vector<unsigned> &Oprnds, error("Invalid malloc instruction!"); Result = new MallocInst(cast<PointerType>(InstTy)->getElementType(), - getValue(Type::Int32TyID, Oprnds[0]), Align); + getValue(Int32TySlot, Oprnds[0]), Align); break; } case Instruction::Alloca: { @@ -890,7 +890,7 @@ void BytecodeReader::ParseInstruction(std::vector<unsigned> &Oprnds, error("Invalid alloca instruction!"); Result = new AllocaInst(cast<PointerType>(InstTy)->getElementType(), - getValue(Type::Int32TyID, Oprnds[0]), Align); + getValue(Int32TySlot, Oprnds[0]), Align); break; } case Instruction::Free: @@ -916,12 +916,12 @@ void BytecodeReader::ParseInstruction(std::vector<unsigned> &Oprnds, // 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 = Type::Int32TyID; + IdxTy = Int32TySlot; else { switch (ValIdx & 1) { default: - case 0: IdxTy = Type::Int32TyID; break; - case 1: IdxTy = Type::Int64TyID; break; + case 0: IdxTy = Int32TySlot; break; + case 1: IdxTy = Int64TySlot; break; } ValIdx >>= 1; } @@ -1064,7 +1064,7 @@ void BytecodeReader::ParseValueSymbolTable(Function *CurrentFunction, unsigned slot = read_vbr_uint(); std::string Name = read_str(); Value *V = 0; - if (Typ == Type::LabelTyID) { + if (Typ == LabelTySlot) { if (slot < BBMap.size()) V = BBMap[slot]; } else { @@ -1160,6 +1160,11 @@ const Type *BytecodeReader::ParseType() { return Result; switch (PrimType) { + case Type::IntegerTyID: { + unsigned NumBits = read_vbr_uint(); + Result = IntegerType::get(NumBits); + break; + } case Type::FunctionTyID: { const Type *RetType = readType(); unsigned RetAttr = read_vbr_uint(); @@ -1204,7 +1209,7 @@ const Type *BytecodeReader::ParseType() { Result = StructType::get(Elements, false); break; } - case Type::BC_ONLY_PackedStructTyID: { + case Type::PackedStructTyID: { std::vector<const Type*> Elements; unsigned Typ = read_vbr_uint(); while (Typ) { // List is terminated by void/0 typeid @@ -1399,32 +1404,29 @@ Value *BytecodeReader::ParseConstantPoolValue(unsigned TypeID) { const Type *Ty = getType(TypeID); Constant *Result = 0; switch (Ty->getTypeID()) { - case Type::Int1TyID: { - unsigned Val = read_vbr_uint(); - if (Val != 0 && Val != 1) - error("Invalid boolean value read."); - Result = ConstantInt::get(Type::Int1Ty, Val == 1); - if (Handler) Handler->handleConstantValue(Result); - break; - } - - case Type::Int8TyID: // Unsigned integer types... - case Type::Int16TyID: - case Type::Int32TyID: { - unsigned Val = read_vbr_uint(); - if (!ConstantInt::isValueValidForType(Ty, uint64_t(Val))) - error("Invalid unsigned byte/short/int read."); - Result = ConstantInt::get(Ty, Val); - if (Handler) Handler->handleConstantValue(Result); - break; - } - - case Type::Int64TyID: { - uint64_t Val = read_vbr_uint64(); - if (!ConstantInt::isValueValidForType(Ty, Val)) - error("Invalid constant integer read."); - Result = ConstantInt::get(Ty, Val); - if (Handler) Handler->handleConstantValue(Result); + case Type::IntegerTyID: { + const IntegerType *IT = cast<IntegerType>(Ty); + if (IT->getBitWidth() <= 32) { + uint32_t Val = read_vbr_uint(); + if (IT->getBitWidth() == 1) { + if (Val != 0 && Val != 1) + error("Invalid boolean value read."); + Result = ConstantInt::get(Type::Int1Ty, Val == 1); + if (Handler) Handler->handleConstantValue(Result); + } else { + if (!ConstantInt::isValueValidForType(Ty, uint64_t(Val))) + error("Integer value read is invalid for type."); + Result = ConstantInt::get(IT, Val); + if (Handler) Handler->handleConstantValue(Result); + } + } else if (IT->getBitWidth() <= 64) { + uint64_t Val = read_vbr_uint64(); + if (!ConstantInt::isValueValidForType(Ty, Val)) + error("Invalid constant integer read."); + Result = ConstantInt::get(IT, Val); + if (Handler) Handler->handleConstantValue(Result); + } else + assert("Integer types > 64 bits not supported"); break; } case Type::FloatTyID: { diff --git a/lib/Bytecode/Reader/Reader.h b/lib/Bytecode/Reader/Reader.h index 677c39f99f..3e64f2d027 100644 --- a/lib/Bytecode/Reader/Reader.h +++ b/lib/Bytecode/Reader/Reader.h @@ -415,6 +415,20 @@ private: BytecodeReader(const BytecodeReader &); // DO NOT IMPLEMENT void operator=(const BytecodeReader &); // DO NOT IMPLEMENT + // This enum provides the values of the well-known type slots that are always + // emitted as the first few types in the table by the BytecodeWriter class. + enum WellKnownTypeSlots { + VoidTypeSlot = 0, ///< TypeID == VoidTyID + FloatTySlot = 1, ///< TypeID == FloatTyID + DoubleTySlot = 2, ///< TypeID == DoubleTyID + LabelTySlot = 3, ///< TypeID == LabelTyID + BoolTySlot = 4, ///< TypeID == IntegerTyID, width = 1 + Int8TySlot = 5, ///< TypeID == IntegerTyID, width = 8 + Int16TySlot = 6, ///< TypeID == IntegerTyID, width = 16 + Int32TySlot = 7, ///< TypeID == IntegerTyID, width = 32 + Int64TySlot = 8 ///< TypeID == IntegerTyID, width = 64 + }; + /// @} /// @name Reader Primitives /// @{ diff --git a/lib/Bytecode/Writer/SlotCalculator.cpp b/lib/Bytecode/Writer/SlotCalculator.cpp index fdf7174b85..2d4cd0c4cb 100644 --- a/lib/Bytecode/Writer/SlotCalculator.cpp +++ b/lib/Bytecode/Writer/SlotCalculator.cpp @@ -31,26 +31,45 @@ #include <functional> using namespace llvm; -#if 0 +#ifndef NDEBUG #include "llvm/Support/Streams.h" -#define SC_DEBUG(X) cerr << X +#include "llvm/Support/CommandLine.h" +static cl::opt<bool> SlotCalculatorDebugOption("scdebug",cl::init(false), + cl::desc("Enable SlotCalculator debug output"), cl::Hidden); +#define SC_DEBUG(X) if (SlotCalculatorDebugOption) cerr << X #else #define SC_DEBUG(X) #endif +void SlotCalculator::insertPrimitives() { + // Preload the table with the built-in types. These built-in types are + // inserted first to ensure that they have low integer indices which helps to + // keep bytecode sizes small. Note that the first group of indices must match + // the Type::TypeIDs for the primitive types. After that the integer types are + // added, but the order and value is not critical. What is critical is that + // the indices of these "well known" slot numbers be properly maintained in + // Reader.h which uses them directly to extract values of these types. + SC_DEBUG("Inserting primitive types:\n"); + // See WellKnownTypeSlots in Reader.h + insertType(Type::VoidTy, true); // 0: VoidTySlot + insertType(Type::FloatTy, true); // 1: FloatTySlot + insertType(Type::DoubleTy, true); // 2: DoubleTySlot + insertType(Type::LabelTy, true); // 3: LabelTySlot + assert(TypeMap.size() == Type::FirstDerivedTyID && "Invalid primitive insert"); + // Above here *must* correspond 1:1 with the primitive types. + insertType(Type::Int1Ty, true); // 4: BoolTySlot + insertType(Type::Int8Ty, true); // 5: Int8TySlot + insertType(Type::Int16Ty, true); // 6: Int16TySlot + insertType(Type::Int32Ty, true); // 7: Int32TySlot + insertType(Type::Int64Ty, true); // 8: Int64TySlot +} + SlotCalculator::SlotCalculator(const Module *M ) { ModuleContainsAllFunctionConstants = false; ModuleTypeLevel = 0; TheModule = M; - // Preload table... Make sure that all of the primitive types are in the table - // and that their Primitive ID is equal to their slot # - // - SC_DEBUG("Inserting primitive types:\n"); - for (unsigned i = 0; i < Type::FirstDerivedTyID; ++i) { - assert(Type::getPrimitiveType((Type::TypeID)i)); - insertType(Type::getPrimitiveType((Type::TypeID)i), true); - } + insertPrimitives(); if (M == 0) return; // Empty table... processModule(); @@ -60,14 +79,7 @@ SlotCalculator::SlotCalculator(const Function *M ) { ModuleContainsAllFunctionConstants = false; TheModule = M ? M->getParent() : 0; - // Preload table... Make sure that all of the primitive types are in the table - // and that their Primitive ID is equal to their slot # - // - SC_DEBUG("Inserting primitive types:\n"); - for (unsigned i = 0; i < Type::FirstDerivedTyID; ++i) { - assert(Type::getPrimitiveType((Type::TypeID)i)); - insertType(Type::getPrimitiveType((Type::TypeID)i), true); - } + insertPrimitives(); if (TheModule == 0) return; // Empty table... @@ -423,15 +435,14 @@ unsigned SlotCalculator::getOrCreateCompactionTableSlot(const Value *V) { /// getOrCreateCompactionTableSlot - This method is used to build up the initial /// approximation of the compaction table. unsigned SlotCalculator::getOrCreateCompactionTableSlot(const Type *T) { - std::map<const Type*, unsigned>::iterator I = - CompactionTypeMap.lower_bound(T); + CompactionTypeMapType::iterator I = CompactionTypeMap.lower_bound(T); if (I != CompactionTypeMap.end() && I->first == T) return I->second; // Already exists? unsigned SlotNo = CompactionTypes.size(); - SC_DEBUG("Inserting Compaction Type #" << SlotNo << ": " << T << "\n"); + SC_DEBUG("Inserting Compaction Type #" << SlotNo << ": " << *T << "\n"); CompactionTypes.push_back(T); - CompactionTypeMap.insert(std::make_pair(T, SlotNo)); + CompactionTypeMap[T] = SlotNo; return SlotNo; } @@ -452,6 +463,16 @@ void SlotCalculator::buildCompactionTable(const Function *F) { CompactionTypes.push_back(PrimTy); CompactionTypeMap[PrimTy] = i; } + CompactionTypeMap[Type::Int1Ty] = CompactionTypes.size(); + CompactionTypes.push_back(Type::Int1Ty); + CompactionTypeMap[Type::Int8Ty] = CompactionTypes.size(); + CompactionTypes.push_back(Type::Int8Ty); + CompactionTypeMap[Type::Int16Ty] = CompactionTypes.size(); + CompactionTypes.push_back(Type::Int16Ty); + CompactionTypeMap[Type::Int32Ty] = CompactionTypes.size(); + CompactionTypes.push_back(Type::Int32Ty); + CompactionTypeMap[Type::Int64Ty] = CompactionTypes.size(); + CompactionTypes.push_back(Type::Int64Ty); // Next, include any types used by function arguments. for (Function::const_arg_iterator I = F->arg_begin(), E = F->arg_end(); @@ -485,7 +506,7 @@ void SlotCalculator::buildCompactionTable(const Function *F) { if (CompactionTable[i].empty() && (i != Type::VoidTyID) && i != Type::LabelTyID) { const Type *Ty = CompactionTypes[i]; - SC_DEBUG("Getting Null Value #" << i << " for Type " << Ty << "\n"); + SC_DEBUG("Getting Null Value #" << i << " for Type " << *Ty << "\n"); assert(Ty->getTypeID() != Type::VoidTyID); assert(Ty->getTypeID() != Type::LabelTyID); getOrCreateCompactionTableSlot(Constant::getNullValue(Ty)); @@ -618,7 +639,8 @@ void SlotCalculator::pruneCompactionTable() { /// to determine if its actually empty. bool SlotCalculator::CompactionTableIsEmpty() const { // Check a degenerate case, just in case. - if (CompactionTable.size() == 0) return true; + if (CompactionTable.size() == 0) + return true; // Check each plane for (unsigned i = 0, e = CompactionTable.size(); i < e; ++i) { @@ -830,7 +852,7 @@ int SlotCalculator::doInsertValue(const Value *D) { unsigned DestSlot = NodeMap[D] = Table[Ty].size(); Table[Ty].push_back(D); - SC_DEBUG(" Inserting value [" << Ty << "] = " << D << " slot=" << + SC_DEBUG(" Inserting value [" << Ty << "] = " << *D << " slot=" << DestSlot << " ["); // G = Global, C = Constant, T = Type, F = Function, o = other SC_DEBUG((isa<GlobalVariable>(D) ? "G" : (isa<Constant>(D) ? "C" : @@ -848,7 +870,6 @@ int SlotCalculator::doInsertType(const Type *Ty) { unsigned DestSlot = TypeMap[Ty] = Types.size(); Types.push_back(Ty); - SC_DEBUG(" Inserting type [" << DestSlot << "] = " << Ty << "\n" ); + SC_DEBUG(" Inserting type [" << DestSlot << "] = " << *Ty << "\n" ); return (int)DestSlot; } - diff --git a/lib/Bytecode/Writer/SlotCalculator.h b/lib/Bytecode/Writer/SlotCalculator.h index 405c0edbd3..de91d2e8f5 100644 --- a/lib/Bytecode/Writer/SlotCalculator.h +++ b/lib/Bytecode/Writer/SlotCalculator.h @@ -177,6 +177,9 @@ private: unsigned getOrCreateCompactionTableSlot(const Value *V); unsigned getOrCreateCompactionTableSlot(const Type *V); void pruneCompactionTable(); + + // insertPrimitives - helper for constructors to insert primitive types. + void insertPrimitives(); }; } // End llvm namespace diff --git a/lib/Bytecode/Writer/Writer.cpp b/lib/Bytecode/Writer/Writer.cpp index 9a04428007..c7003cdd7f 100644 --- a/lib/Bytecode/Writer/Writer.cpp +++ b/lib/Bytecode/Writer/Writer.cpp @@ -200,16 +200,18 @@ inline BytecodeBlock::~BytecodeBlock() { // Do backpatch when block goes out void BytecodeWriter::outputType(const Type *T) { const StructType* STy = dyn_cast<StructType>(T); if(STy && STy->isPacked()) - output_vbr((unsigned)Type::BC_ONLY_PackedStructTyID); + output_vbr((unsigned)Type::PackedStructTyID); else output_vbr((unsigned)T->getTypeID()); // That's all there is to handling primitive types... - if (T->isPrimitiveType()) { + if (T->isPrimitiveType()) return; // We might do this if we alias a prim type: %x = type int - } switch (T->getTypeID()) { // Handle derived types now. + case Type::IntegerTyID: + output_vbr(cast<IntegerType>(T)->getBitWidth()); + break; case Type::FunctionTyID: { const FunctionType *MT = cast<FunctionType>(T); int Slot = Table.getSlot(MT->getReturnType()); @@ -290,8 +292,8 @@ void BytecodeWriter::outputType(const Type *T) { } void BytecodeWriter::outputConstant(const Constant *CPV) { - assert((CPV->getType()->isPrimitiveType() || !CPV->isNullValue()) && - "Shouldn't output null constants!"); + assert(((CPV->getType()->isPrimitiveType() || CPV->getType()->isIntegral()) || + !CPV->isNullValue()) && "Shouldn't output null constants!"); // We must check for a ConstantExpr before switching by type because // a ConstantExpr can be of any type, and has no explicit value. @@ -321,19 +323,21 @@ void BytecodeWriter::outputConstant(const Constant *CPV) { } switch (CPV->getType()->getTypeID()) { - case Type::Int1TyID: // Boolean Types - if (cast<ConstantInt>(CPV)->getZExtValue()) - output_vbr(1U); - else - output_vbr(0U); - break; - - case Type::Int8TyID: // Unsigned integer types... - case Type::Int16TyID: - case Type::Int32TyID: - case Type::Int64TyID: - output_vbr(cast<ConstantInt>(CPV)->getZExtValue()); + case Type::IntegerTyID: { // Integer types... + unsigned NumBits = cast<IntegerType>(CPV->getType())->getBitWidth(); + if (NumBits == 1) + if (cast<ConstantInt>(CPV)->getZExtValue()) + output_vbr(1U); + else + output_vbr(0U); + else if (NumBits <= 32) + output_vbr(uint32_t(cast<ConstantInt>(CPV)->getZExtValue())); + else if (NumBits <= 64) + output_vbr(uint64_t(cast<ConstantInt>(CPV)->getZExtValue())); + else + assert("Integer types > 64 bits not supported."); break; + } case Type::ArrayTyID: { const ConstantArray *CPA = cast<ConstantArray>(CPV); @@ -484,12 +488,12 @@ void BytecodeWriter::outputInstructionFormat0(const Instruction *I, assert(Slot >= 0 && "No slot number for value!?!?"); if (isa<SequentialType>(*TI)) { - unsigned IdxId; - switch (I->getOperand(Idx)->getType()->getTypeID()) { - default: assert(0 && "Unknown index type!"); - case Type::Int32TyID: IdxId = 0; break; - case Type::Int64TyID: IdxId = 1; break; - } + // These should be either 32-bits or 64-bits, however, with bit + // accurate types we just distinguish between less than or equal to + // 32-bits or greater than 32-bits. + const IntegerType *IdxTy = + cast<IntegerType>(I->getOperand(Idx)->getType()); + unsigned IdxId = IdxTy->getBitWidth() <= 32 ? 0 : 1; Slot = (Slot << 1) | IdxId; } output_vbr(unsigned(Slot)); @@ -735,12 +739,12 @@ void BytecodeWriter::outputInstruction(const Instruction &I) { for (gep_type_iterator I = gep_type_begin(GEP), E = gep_type_end(GEP); I != E; ++I, ++Idx) if (isa<SequentialType>(*I)) { - unsigned IdxId; - switch (GEP->getOperand(Idx)->getType()->getTypeID()) { - default: assert(0 && "Unknown index type!"); - case Type::Int32TyID: IdxId = 0; break; - case Type::Int64TyID: IdxId = 1; break; - } + // These should be either 32-bits or 64-bits, however, with bit + // accurate types we just distinguish between less than or equal to + // 32-bits or greater than 32-bits. + const IntegerType *IdxTy = + cast<IntegerType>(GEP->getOperand(Idx)->getType()); + unsigned IdxId = IdxTy->getBitWidth() <= 32 ? 0 : 1; Slots[Idx] = (Slots[Idx] << 1) | IdxId; if (Slots[Idx] > MaxOpSlot) MaxOpSlot = Slots[Idx]; } |