mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-05-18 22:38:56 +00:00
Discard code that supported old bytecode formats. This makes the Bytecode
Reader code much easier to read and maintain. Backwards compatibility from version 5 format has been retained. Older formats will produce an error. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@31723 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
df1a10ece6
commit
d798a515e9
@ -68,7 +68,7 @@ struct BytecodeAnalysis {
|
|||||||
unsigned vbrCompBytes; ///< Number of vbr bytes (compressed)
|
unsigned vbrCompBytes; ///< Number of vbr bytes (compressed)
|
||||||
unsigned vbrExpdBytes; ///< Number of vbr bytes (expanded)
|
unsigned vbrExpdBytes; ///< Number of vbr bytes (expanded)
|
||||||
|
|
||||||
typedef std::map<BytecodeFormat::CompressedBytecodeBlockIdentifiers,unsigned>
|
typedef std::map<BytecodeFormat::BytecodeBlockIdentifiers,unsigned>
|
||||||
BlockSizeMap;
|
BlockSizeMap;
|
||||||
BlockSizeMap BlockSizes;
|
BlockSizeMap BlockSizes;
|
||||||
|
|
||||||
|
@ -20,78 +20,37 @@ namespace llvm {
|
|||||||
class BytecodeFormat { // Throw the constants into a poorman's namespace...
|
class BytecodeFormat { // Throw the constants into a poorman's namespace...
|
||||||
BytecodeFormat(); // do not implement
|
BytecodeFormat(); // do not implement
|
||||||
public:
|
public:
|
||||||
|
/// The the identifier and the size of the block are encoded into a single
|
||||||
// ID Numbers that are used in bytecode files...
|
/// vbr_uint32 with 5 bits for the block identifier and 27-bits for block
|
||||||
enum FileBlockIDs {
|
/// length. This limits blocks to a maximum of
|
||||||
// File level identifiers...
|
|
||||||
Module = 0x01,
|
|
||||||
|
|
||||||
// Module subtypes:
|
|
||||||
Function = 0x11,
|
|
||||||
ConstantPool,
|
|
||||||
SymbolTable,
|
|
||||||
ModuleGlobalInfo,
|
|
||||||
GlobalTypePlane,
|
|
||||||
DependentLibs,
|
|
||||||
|
|
||||||
// Function subtypes:
|
|
||||||
// Can also have ConstantPool block
|
|
||||||
// Can also have SymbolTable block
|
|
||||||
BasicBlock = 0x31,// May contain many basic blocks (obsolete since LLVM 1.1)
|
|
||||||
|
|
||||||
// InstructionList - The instructions in the body of a function. This
|
|
||||||
// superceeds the old BasicBlock node used in LLVM 1.0.
|
|
||||||
InstructionList = 0x32,
|
|
||||||
|
|
||||||
// CompactionTable - blocks with this id are used to define local remapping
|
|
||||||
// tables for a function, allowing the indices used within the function to
|
|
||||||
// be as small as possible. This often allows the instructions to be
|
|
||||||
// encoded more efficiently.
|
|
||||||
CompactionTable = 0x33
|
|
||||||
};
|
|
||||||
|
|
||||||
/// In LLVM 1.3 format, the identifier and the size of the block are
|
|
||||||
/// encoded into a single vbr_uint32 with 5 bits for the block identifier
|
|
||||||
/// and 27-bits for block length. This limits blocks to a maximum of
|
|
||||||
/// 128MBytes of data, and block types to 31 which should be sufficient
|
/// 128MBytes of data, and block types to 31 which should be sufficient
|
||||||
/// for the foreseeable usage. Because the values of block identifiers MUST
|
/// for the foreseeable usage. Because the values of block identifiers MUST
|
||||||
/// fit within 5 bits (values 1-31), this enumeration is used to ensure
|
/// fit within 5 bits (values 1-31), this enumeration is used to ensure
|
||||||
/// smaller values are used for 1.3 and subsequent bytecode versions.
|
/// smaller values are used for 1.3 and subsequent bytecode versions.
|
||||||
/// @brief The block number identifiers used in LLVM 1.3 bytecode
|
/// @brief The block number identifiers used in LLVM 1.3 bytecode
|
||||||
/// format.
|
/// format.
|
||||||
enum CompressedBytecodeBlockIdentifiers {
|
enum BytecodeBlockIdentifiers {
|
||||||
|
|
||||||
// Zero value ist verbotten!
|
Reserved_DoNotUse = 0, ///< Zero value is forbidden, do not use.
|
||||||
Reserved_DoNotUse = 0x00, ///< Don't use this!
|
ModuleBlockID = 1, ///< Module block that contains other blocks.
|
||||||
|
FunctionBlockID = 2, ///< Function block identifier
|
||||||
|
ConstantPoolBlockID = 3, ///< Constant pool identifier
|
||||||
|
SymbolTableBlockID = 4, ///< Symbol table identifier
|
||||||
|
ModuleGlobalInfoBlockID= 5, ///< Module global info identifier
|
||||||
|
GlobalTypePlaneBlockID = 6, ///< Global type plan identifier
|
||||||
|
InstructionListBlockID = 7, ///< All instructions in a function
|
||||||
|
|
||||||
// This is the uber block that contains the rest of the blocks.
|
/// Blocks with this id are used to define a function local remapping
|
||||||
ModuleBlockID = 0x01, ///< 1.3 identifier for modules
|
/// table for the function's values. This allows the indices used within
|
||||||
|
/// the function to be as small as possible. This often allows the
|
||||||
// Module subtypes:
|
/// instructions to be encoded more efficiently because VBR takes fewer
|
||||||
|
/// bytes with smaller values.
|
||||||
// This is the identifier for a function
|
/// @brief Value Compaction Table Block
|
||||||
FunctionBlockID = 0x02, ///< 1.3 identifier for Functions
|
CompactionTableBlockID = 0x08,
|
||||||
ConstantPoolBlockID = 0x03, ///< 1.3 identifier for constant pool
|
|
||||||
SymbolTableBlockID = 0x04, ///< 1.3 identifier for symbol table
|
|
||||||
ModuleGlobalInfoBlockID = 0x05,///< 1.3 identifier for module globals
|
|
||||||
GlobalTypePlaneBlockID = 0x06, ///< 1.3 identifier for global types
|
|
||||||
|
|
||||||
// Function subtypes:
|
|
||||||
|
|
||||||
// InstructionList - The instructions in the body of a function. This
|
|
||||||
// superceeds the old BasicBlock node used in LLVM 1.0.
|
|
||||||
InstructionListBlockID = 0x07, ///< 1.3 identifier for insruction list
|
|
||||||
|
|
||||||
// CompactionTable - blocks with this id are used to define local remapping
|
|
||||||
// tables for a function, allowing the indices used within the function to
|
|
||||||
// be as small as possible. This often allows the instructions to be
|
|
||||||
// encoded more efficiently.
|
|
||||||
CompactionTableBlockID = 0x08, ///< 1.3 identifier for compaction tables
|
|
||||||
|
|
||||||
// Not a block id, just used to count them
|
// Not a block id, just used to count them
|
||||||
NumberOfBlockIDs
|
NumberOfBlockIDs
|
||||||
};
|
};
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // End llvm namespace
|
} // End llvm namespace
|
||||||
|
@ -532,7 +532,7 @@ public:
|
|||||||
assert(BType >= BytecodeFormat::ModuleBlockID);
|
assert(BType >= BytecodeFormat::ModuleBlockID);
|
||||||
assert(BType < BytecodeFormat::NumberOfBlockIDs);
|
assert(BType < BytecodeFormat::NumberOfBlockIDs);
|
||||||
bca.BlockSizes[
|
bca.BlockSizes[
|
||||||
llvm::BytecodeFormat::CompressedBytecodeBlockIdentifiers(BType)] += Size;
|
llvm::BytecodeFormat::BytecodeBlockIdentifiers(BType)] += Size;
|
||||||
|
|
||||||
if (bca.version < 3) // Check for long block headers versions
|
if (bca.version < 3) // Check for long block headers versions
|
||||||
bca.BlockSizes[llvm::BytecodeFormat::Reserved_DoNotUse] += 8;
|
bca.BlockSizes[llvm::BytecodeFormat::Reserved_DoNotUse] += 8;
|
||||||
|
@ -73,18 +73,6 @@ inline void BytecodeReader::checkPastBlockEnd(const char * block_name) {
|
|||||||
" block.");
|
" block.");
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Align the buffer position to a 32 bit boundary
|
|
||||||
inline void BytecodeReader::align32() {
|
|
||||||
if (hasAlignment) {
|
|
||||||
BufPtr Save = At;
|
|
||||||
At = (const unsigned char *)((intptr_t)(At+3) & (~3UL));
|
|
||||||
if (At > Save)
|
|
||||||
if (Handler) Handler->handleAlignment(At - Save);
|
|
||||||
if (At > BlockEnd)
|
|
||||||
error("Ran out of data while aligning!");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Read a whole unsigned integer
|
/// Read a whole unsigned integer
|
||||||
inline unsigned BytecodeReader::read_uint() {
|
inline unsigned BytecodeReader::read_uint() {
|
||||||
if (At+4 > BlockEnd)
|
if (At+4 > BlockEnd)
|
||||||
@ -179,43 +167,9 @@ inline void BytecodeReader::read_double(double& DoubleVal) {
|
|||||||
|
|
||||||
/// Read a block header and obtain its type and size
|
/// Read a block header and obtain its type and size
|
||||||
inline void BytecodeReader::read_block(unsigned &Type, unsigned &Size) {
|
inline void BytecodeReader::read_block(unsigned &Type, unsigned &Size) {
|
||||||
if ( hasLongBlockHeaders ) {
|
Size = read_uint(); // Read the header
|
||||||
Type = read_uint();
|
Type = Size & 0x1F; // mask low order five bits to get type
|
||||||
Size = read_uint();
|
Size >>= 5; // high order 27 bits is the size
|
||||||
switch (Type) {
|
|
||||||
case BytecodeFormat::Reserved_DoNotUse :
|
|
||||||
error("Reserved_DoNotUse used as Module Type?");
|
|
||||||
Type = BytecodeFormat::ModuleBlockID; break;
|
|
||||||
case BytecodeFormat::Module:
|
|
||||||
Type = BytecodeFormat::ModuleBlockID; break;
|
|
||||||
case BytecodeFormat::Function:
|
|
||||||
Type = BytecodeFormat::FunctionBlockID; break;
|
|
||||||
case BytecodeFormat::ConstantPool:
|
|
||||||
Type = BytecodeFormat::ConstantPoolBlockID; break;
|
|
||||||
case BytecodeFormat::SymbolTable:
|
|
||||||
Type = BytecodeFormat::SymbolTableBlockID; break;
|
|
||||||
case BytecodeFormat::ModuleGlobalInfo:
|
|
||||||
Type = BytecodeFormat::ModuleGlobalInfoBlockID; break;
|
|
||||||
case BytecodeFormat::GlobalTypePlane:
|
|
||||||
Type = BytecodeFormat::GlobalTypePlaneBlockID; break;
|
|
||||||
case BytecodeFormat::InstructionList:
|
|
||||||
Type = BytecodeFormat::InstructionListBlockID; break;
|
|
||||||
case BytecodeFormat::CompactionTable:
|
|
||||||
Type = BytecodeFormat::CompactionTableBlockID; break;
|
|
||||||
case BytecodeFormat::BasicBlock:
|
|
||||||
/// This block type isn't used after version 1.1. However, we have to
|
|
||||||
/// still allow the value in case this is an old bc format file.
|
|
||||||
/// We just let its value creep thru.
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
error("Invalid block id found: " + utostr(Type));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Size = read_uint();
|
|
||||||
Type = Size & 0x1F; // mask low order five bits
|
|
||||||
Size >>= 5; // get rid of five low order bits, leaving high 27
|
|
||||||
}
|
|
||||||
BlockStart = At;
|
BlockStart = At;
|
||||||
if (At + Size > BlockEnd)
|
if (At + Size > BlockEnd)
|
||||||
error("Attempt to size a block past end of memory");
|
error("Attempt to size a block past end of memory");
|
||||||
@ -223,56 +177,13 @@ inline void BytecodeReader::read_block(unsigned &Type, unsigned &Size) {
|
|||||||
if (Handler) Handler->handleBlock(Type, BlockStart, Size);
|
if (Handler) Handler->handleBlock(Type, BlockStart, Size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// In LLVM 1.2 and before, Types were derived from Value and so they were
|
|
||||||
/// written as part of the type planes along with any other Value. In LLVM
|
|
||||||
/// 1.3 this changed so that Type does not derive from Value. Consequently,
|
|
||||||
/// the BytecodeReader's containers for Values can't contain Types because
|
|
||||||
/// there's no inheritance relationship. This means that the "Type Type"
|
|
||||||
/// plane is defunct along with the Type::TypeTyID TypeID. In LLVM 1.3
|
|
||||||
/// whenever a bytecode construct must have both types and values together,
|
|
||||||
/// the types are always read/written first and then the Values. Furthermore
|
|
||||||
/// since Type::TypeTyID no longer exists, its value (12) now corresponds to
|
|
||||||
/// Type::LabelTyID. In order to overcome this we must "sanitize" all the
|
|
||||||
/// type TypeIDs we encounter. For LLVM 1.3 bytecode files, there's no change.
|
|
||||||
/// For LLVM 1.2 and before, this function will decrement the type id by
|
|
||||||
/// one to account for the missing Type::TypeTyID enumerator if the value is
|
|
||||||
/// larger than 12 (Type::LabelTyID). If the value is exactly 12, then this
|
|
||||||
/// function returns true, otherwise false. This helps detect situations
|
|
||||||
/// where the pre 1.3 bytecode is indicating that what follows is a type.
|
|
||||||
/// @returns true iff type id corresponds to pre 1.3 "type type"
|
|
||||||
inline bool BytecodeReader::sanitizeTypeId(unsigned &TypeId) {
|
|
||||||
if (hasTypeDerivedFromValue) { /// do nothing if 1.3 or later
|
|
||||||
if (TypeId == Type::LabelTyID) {
|
|
||||||
TypeId = Type::VoidTyID; // sanitize it
|
|
||||||
return true; // indicate we got TypeTyID in pre 1.3 bytecode
|
|
||||||
} else if (TypeId > Type::LabelTyID)
|
|
||||||
--TypeId; // shift all planes down because type type plane is missing
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Reads a vbr uint to read in a type id and does the necessary
|
|
||||||
/// conversion on it by calling sanitizeTypeId.
|
|
||||||
/// @returns true iff \p TypeId read corresponds to a pre 1.3 "type type"
|
|
||||||
/// @see sanitizeTypeId
|
|
||||||
inline bool BytecodeReader::read_typeid(unsigned &TypeId) {
|
|
||||||
TypeId = read_vbr_uint();
|
|
||||||
if ( !has32BitTypes )
|
|
||||||
if ( TypeId == 0x00FFFFFF )
|
|
||||||
TypeId = read_vbr_uint();
|
|
||||||
return sanitizeTypeId(TypeId);
|
|
||||||
}
|
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
// IR Lookup Methods
|
// IR Lookup Methods
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
/// Determine if a type id has an implicit null value
|
/// Determine if a type id has an implicit null value
|
||||||
inline bool BytecodeReader::hasImplicitNull(unsigned TyID) {
|
inline bool BytecodeReader::hasImplicitNull(unsigned TyID) {
|
||||||
if (!hasExplicitPrimitiveZeros)
|
|
||||||
return TyID != Type::LabelTyID && TyID != Type::VoidTyID;
|
return TyID != Type::LabelTyID && TyID != Type::VoidTyID;
|
||||||
return TyID >= Type::FirstDerivedTyID;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Obtain a type given a typeid and account for things like compaction tables,
|
/// Obtain a type given a typeid and account for things like compaction tables,
|
||||||
@ -304,23 +215,11 @@ const Type *BytecodeReader::getType(unsigned ID) {
|
|||||||
return Type::VoidTy;
|
return Type::VoidTy;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get a sanitized type id. This just makes sure that the \p ID
|
/// This method just saves some coding. It uses read_vbr_uint to read
|
||||||
/// is both sanitized and not the "type type" of pre-1.3 bytecode.
|
|
||||||
/// @see sanitizeTypeId
|
|
||||||
inline const Type* BytecodeReader::getSanitizedType(unsigned& ID) {
|
|
||||||
if (sanitizeTypeId(ID))
|
|
||||||
error("Invalid type id encountered");
|
|
||||||
return getType(ID);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// This method just saves some coding. It uses read_typeid to read
|
|
||||||
/// in a sanitized type id, errors that its not the type type, and
|
/// in a sanitized type id, errors that its not the type type, and
|
||||||
/// then calls getType to return the type value.
|
/// then calls getType to return the type value.
|
||||||
inline const Type* BytecodeReader::readSanitizedType() {
|
inline const Type* BytecodeReader::readType() {
|
||||||
unsigned ID;
|
return getType(read_vbr_uint());
|
||||||
if (read_typeid(ID))
|
|
||||||
error("Invalid type id encountered");
|
|
||||||
return getType(ID);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the slot number associated with a type accounting for primitive
|
/// Get the slot number associated with a type accounting for primitive
|
||||||
@ -590,12 +489,6 @@ BytecodeReader::upgradeInstrOpcodes(
|
|||||||
if (!hasSignlessDivRem && !hasSignlessShrCastSetcc)
|
if (!hasSignlessDivRem && !hasSignlessShrCastSetcc)
|
||||||
return 0; // The opcode is fine the way it is.
|
return 0; // The opcode is fine the way it is.
|
||||||
|
|
||||||
// If this is a bytecode format that did not include the unreachable
|
|
||||||
// instruction, bump up the opcode number to adjust it.
|
|
||||||
if (hasNoUnreachableInst)
|
|
||||||
if (Opcode >= 6 && Opcode < 62)
|
|
||||||
++Opcode;
|
|
||||||
|
|
||||||
// If this is bytecode version 6, that only had signed Rem and Div
|
// If this is bytecode version 6, that only had signed Rem and Div
|
||||||
// instructions, then we must compensate for those two instructions only.
|
// instructions, then we must compensate for those two instructions only.
|
||||||
// So that the switch statement below works, we're trying to turn this into
|
// So that the switch statement below works, we're trying to turn this into
|
||||||
@ -779,7 +672,7 @@ BytecodeReader::upgradeInstrOpcodes(
|
|||||||
CallInst* bar = new CallInst(NF, getValue(iType, Oprnds[0]));
|
CallInst* bar = new CallInst(NF, getValue(iType, Oprnds[0]));
|
||||||
BB->getInstList().push_back(bar);
|
BB->getInstList().push_back(bar);
|
||||||
BB->getInstList().push_back(new StoreInst(bar, foo));
|
BB->getInstList().push_back(new StoreInst(bar, foo));
|
||||||
Instruction* tmp = new VAArgInst(foo, getSanitizedType(Oprnds[1]));
|
Instruction* tmp = new VAArgInst(foo, getType(Oprnds[1]));
|
||||||
BB->getInstList().push_back(tmp);
|
BB->getInstList().push_back(tmp);
|
||||||
Result = new LoadInst(foo);
|
Result = new LoadInst(foo);
|
||||||
break;
|
break;
|
||||||
@ -803,7 +696,7 @@ BytecodeReader::upgradeInstrOpcodes(
|
|||||||
CallInst* bar = new CallInst(NF, getValue(iType, Oprnds[0]));
|
CallInst* bar = new CallInst(NF, getValue(iType, Oprnds[0]));
|
||||||
BB->getInstList().push_back(bar);
|
BB->getInstList().push_back(bar);
|
||||||
BB->getInstList().push_back(new StoreInst(bar, foo));
|
BB->getInstList().push_back(new StoreInst(bar, foo));
|
||||||
Result = new VAArgInst(foo, getSanitizedType(Oprnds[1]));
|
Result = new VAArgInst(foo, getType(Oprnds[1]));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 34: // Select
|
case 34: // Select
|
||||||
@ -919,11 +812,10 @@ void BytecodeReader::ParseInstruction(std::vector<unsigned> &Oprnds,
|
|||||||
|
|
||||||
for (unsigned i = 0; i != NumOprnds; ++i)
|
for (unsigned i = 0; i != NumOprnds; ++i)
|
||||||
Oprnds[i] = read_vbr_uint();
|
Oprnds[i] = read_vbr_uint();
|
||||||
align32();
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Type *InstTy = getSanitizedType(iType);
|
const Type *InstTy = getType(iType);
|
||||||
|
|
||||||
// Make the necessary adjustments for dealing with backwards compatibility
|
// Make the necessary adjustments for dealing with backwards compatibility
|
||||||
// of opcodes.
|
// of opcodes.
|
||||||
@ -955,7 +847,7 @@ void BytecodeReader::ParseInstruction(std::vector<unsigned> &Oprnds,
|
|||||||
if (Oprnds.size() != 2)
|
if (Oprnds.size() != 2)
|
||||||
error("Invalid VAArg instruction!");
|
error("Invalid VAArg instruction!");
|
||||||
Result = new VAArgInst(getValue(iType, Oprnds[0]),
|
Result = new VAArgInst(getValue(iType, Oprnds[0]),
|
||||||
getSanitizedType(Oprnds[1]));
|
getType(Oprnds[1]));
|
||||||
break;
|
break;
|
||||||
case Instruction::ExtractElement: {
|
case Instruction::ExtractElement: {
|
||||||
if (Oprnds.size() != 2)
|
if (Oprnds.size() != 2)
|
||||||
@ -1001,7 +893,7 @@ void BytecodeReader::ParseInstruction(std::vector<unsigned> &Oprnds,
|
|||||||
if (Oprnds.size() != 2)
|
if (Oprnds.size() != 2)
|
||||||
error("Invalid Cast instruction!");
|
error("Invalid Cast instruction!");
|
||||||
Result = new CastInst(getValue(iType, Oprnds[0]),
|
Result = new CastInst(getValue(iType, Oprnds[0]),
|
||||||
getSanitizedType(Oprnds[1]));
|
getType(Oprnds[1]));
|
||||||
break;
|
break;
|
||||||
case Instruction::Select:
|
case Instruction::Select:
|
||||||
if (Oprnds.size() != 3)
|
if (Oprnds.size() != 3)
|
||||||
@ -1235,7 +1127,6 @@ void BytecodeReader::ParseInstruction(std::vector<unsigned> &Oprnds,
|
|||||||
|
|
||||||
unsigned ValIdx = Oprnds[i];
|
unsigned ValIdx = Oprnds[i];
|
||||||
unsigned IdxTy = 0;
|
unsigned IdxTy = 0;
|
||||||
if (!hasRestrictedGEPTypes) {
|
|
||||||
// Struct indices are always uints, sequential type indices can be
|
// Struct indices are always uints, sequential type indices can be
|
||||||
// any of the 32 or 64-bit integer types. The actual choice of
|
// any of the 32 or 64-bit integer types. The actual choice of
|
||||||
// type is encoded in the low two bits of the slot number.
|
// type is encoded in the low two bits of the slot number.
|
||||||
@ -1251,18 +1142,7 @@ void BytecodeReader::ParseInstruction(std::vector<unsigned> &Oprnds,
|
|||||||
}
|
}
|
||||||
ValIdx >>= 2;
|
ValIdx >>= 2;
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
IdxTy = isa<StructType>(TopTy) ? Type::UByteTyID : Type::LongTyID;
|
|
||||||
}
|
|
||||||
|
|
||||||
Idx.push_back(getValue(IdxTy, ValIdx));
|
Idx.push_back(getValue(IdxTy, ValIdx));
|
||||||
|
|
||||||
// Convert ubyte struct indices into uint struct indices.
|
|
||||||
if (isa<StructType>(TopTy) && hasRestrictedGEPTypes)
|
|
||||||
if (ConstantInt *C = dyn_cast<ConstantInt>(Idx.back()))
|
|
||||||
if (C->getType() == Type::UByteTy)
|
|
||||||
Idx[Idx.size()-1] = ConstantExpr::getCast(C, Type::UIntTy);
|
|
||||||
|
|
||||||
NextTy = GetElementPtrInst::getIndexedType(InstTy, Idx, true);
|
NextTy = GetElementPtrInst::getIndexedType(InstTy, Idx, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1309,16 +1189,16 @@ void BytecodeReader::ParseInstruction(std::vector<unsigned> &Oprnds,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Get a particular numbered basic block, which might be a forward reference.
|
/// Get a particular numbered basic block, which might be a forward reference.
|
||||||
/// This works together with ParseBasicBlock to handle these forward references
|
/// This works together with ParseInstructionList to handle these forward
|
||||||
/// in a clean manner. This function is used when constructing phi, br, switch,
|
/// references in a clean manner. This function is used when constructing
|
||||||
/// and other instructions that reference basic blocks. Blocks are numbered
|
/// phi, br, switch, and other instructions that reference basic blocks.
|
||||||
/// sequentially as they appear in the function.
|
/// Blocks are numbered sequentially as they appear in the function.
|
||||||
BasicBlock *BytecodeReader::getBasicBlock(unsigned ID) {
|
BasicBlock *BytecodeReader::getBasicBlock(unsigned ID) {
|
||||||
// Make sure there is room in the table...
|
// Make sure there is room in the table...
|
||||||
if (ParsedBasicBlocks.size() <= ID) ParsedBasicBlocks.resize(ID+1);
|
if (ParsedBasicBlocks.size() <= ID) ParsedBasicBlocks.resize(ID+1);
|
||||||
|
|
||||||
// First check to see if this is a backwards reference, i.e., ParseBasicBlock
|
// First check to see if this is a backwards reference, i.e. this block
|
||||||
// has already created this block, or if the forward reference has already
|
// has already been created, or if the forward reference has already
|
||||||
// been created.
|
// been created.
|
||||||
if (ParsedBasicBlocks[ID])
|
if (ParsedBasicBlocks[ID])
|
||||||
return ParsedBasicBlocks[ID];
|
return ParsedBasicBlocks[ID];
|
||||||
@ -1328,34 +1208,10 @@ BasicBlock *BytecodeReader::getBasicBlock(unsigned ID) {
|
|||||||
return ParsedBasicBlocks[ID] = new BasicBlock();
|
return ParsedBasicBlocks[ID] = new BasicBlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// In LLVM 1.0 bytecode files, we used to output one basicblock at a time.
|
|
||||||
/// This method reads in one of the basicblock packets. This method is not used
|
|
||||||
/// for bytecode files after LLVM 1.0
|
|
||||||
/// @returns The basic block constructed.
|
|
||||||
BasicBlock *BytecodeReader::ParseBasicBlock(unsigned BlockNo) {
|
|
||||||
if (Handler) Handler->handleBasicBlockBegin(BlockNo);
|
|
||||||
|
|
||||||
BasicBlock *BB = 0;
|
|
||||||
|
|
||||||
if (ParsedBasicBlocks.size() == BlockNo)
|
|
||||||
ParsedBasicBlocks.push_back(BB = new BasicBlock());
|
|
||||||
else if (ParsedBasicBlocks[BlockNo] == 0)
|
|
||||||
BB = ParsedBasicBlocks[BlockNo] = new BasicBlock();
|
|
||||||
else
|
|
||||||
BB = ParsedBasicBlocks[BlockNo];
|
|
||||||
|
|
||||||
std::vector<unsigned> Operands;
|
|
||||||
while (moreInBlock())
|
|
||||||
ParseInstruction(Operands, BB);
|
|
||||||
|
|
||||||
if (Handler) Handler->handleBasicBlockEnd(BlockNo);
|
|
||||||
return BB;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Parse all of the BasicBlock's & Instruction's in the body of a function.
|
/// 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 post 1.0 bytecode files, we no longer emit basic block individually,
|
||||||
/// in order to avoid per-basic-block overhead.
|
/// in order to avoid per-basic-block overhead.
|
||||||
/// @returns Rhe number of basic blocks encountered.
|
/// @returns the number of basic blocks encountered.
|
||||||
unsigned BytecodeReader::ParseInstructionList(Function* F) {
|
unsigned BytecodeReader::ParseInstructionList(Function* F) {
|
||||||
unsigned BlockNo = 0;
|
unsigned BlockNo = 0;
|
||||||
std::vector<unsigned> Args;
|
std::vector<unsigned> Args;
|
||||||
@ -1401,10 +1257,6 @@ void BytecodeReader::ParseSymbolTable(Function *CurrentFunction,
|
|||||||
E = CurrentFunction->end(); I != E; ++I)
|
E = CurrentFunction->end(); I != E; ++I)
|
||||||
BBMap.push_back(I);
|
BBMap.push_back(I);
|
||||||
|
|
||||||
/// In LLVM 1.3 we write types separately from values so
|
|
||||||
/// The types are always first in the symbol table. This is
|
|
||||||
/// because Type no longer derives from Value.
|
|
||||||
if (!hasTypeDerivedFromValue) {
|
|
||||||
// Symtab block header: [num entries]
|
// Symtab block header: [num entries]
|
||||||
unsigned NumEntries = read_vbr_uint();
|
unsigned NumEntries = read_vbr_uint();
|
||||||
for (unsigned i = 0; i < NumEntries; ++i) {
|
for (unsigned i = 0; i < NumEntries; ++i) {
|
||||||
@ -1414,28 +1266,16 @@ void BytecodeReader::ParseSymbolTable(Function *CurrentFunction,
|
|||||||
const Type* T = getType(slot);
|
const Type* T = getType(slot);
|
||||||
ST->insert(Name, T);
|
ST->insert(Name, T);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
while (moreInBlock()) {
|
while (moreInBlock()) {
|
||||||
// Symtab block header: [num entries][type id number]
|
// Symtab block header: [num entries][type id number]
|
||||||
unsigned NumEntries = read_vbr_uint();
|
unsigned NumEntries = read_vbr_uint();
|
||||||
unsigned Typ = 0;
|
unsigned Typ = read_vbr_uint();
|
||||||
bool isTypeType = read_typeid(Typ);
|
|
||||||
|
|
||||||
for (unsigned i = 0; i != NumEntries; ++i) {
|
for (unsigned i = 0; i != NumEntries; ++i) {
|
||||||
// Symtab entry: [def slot #][name]
|
// Symtab entry: [def slot #][name]
|
||||||
unsigned slot = read_vbr_uint();
|
unsigned slot = read_vbr_uint();
|
||||||
std::string Name = read_str();
|
std::string Name = read_str();
|
||||||
|
|
||||||
// if we're reading a pre 1.3 bytecode file and the type plane
|
|
||||||
// is the "type type", handle it here
|
|
||||||
if (isTypeType) {
|
|
||||||
const Type* T = getType(slot);
|
|
||||||
if (T == 0)
|
|
||||||
error("Failed type look-up for name '" + Name + "'");
|
|
||||||
ST->insert(Name, T);
|
|
||||||
continue; // code below must be short circuited
|
|
||||||
} else {
|
|
||||||
Value *V = 0;
|
Value *V = 0;
|
||||||
if (Typ == Type::LabelTyID) {
|
if (Typ == Type::LabelTyID) {
|
||||||
if (slot < BBMap.size())
|
if (slot < BBMap.size())
|
||||||
@ -1448,7 +1288,6 @@ void BytecodeReader::ParseSymbolTable(Function *CurrentFunction,
|
|||||||
V->setName(Name);
|
V->setName(Name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
checkPastBlockEnd("Symbol Table");
|
checkPastBlockEnd("Symbol Table");
|
||||||
if (Handler) Handler->handleSymbolTableEnd();
|
if (Handler) Handler->handleSymbolTableEnd();
|
||||||
}
|
}
|
||||||
@ -1456,9 +1295,7 @@ void BytecodeReader::ParseSymbolTable(Function *CurrentFunction,
|
|||||||
/// Read in the types portion of a compaction table.
|
/// Read in the types portion of a compaction table.
|
||||||
void BytecodeReader::ParseCompactionTypes(unsigned NumEntries) {
|
void BytecodeReader::ParseCompactionTypes(unsigned NumEntries) {
|
||||||
for (unsigned i = 0; i != NumEntries; ++i) {
|
for (unsigned i = 0; i != NumEntries; ++i) {
|
||||||
unsigned TypeSlot = 0;
|
unsigned TypeSlot = read_vbr_uint();
|
||||||
if (read_typeid(TypeSlot))
|
|
||||||
error("Invalid type in compaction table: type type");
|
|
||||||
const Type *Typ = getGlobalTableType(TypeSlot);
|
const Type *Typ = getGlobalTableType(TypeSlot);
|
||||||
CompactionTypes.push_back(std::make_pair(Typ, TypeSlot));
|
CompactionTypes.push_back(std::make_pair(Typ, TypeSlot));
|
||||||
if (Handler) Handler->handleCompactionTableType(i, TypeSlot, Typ);
|
if (Handler) Handler->handleCompactionTableType(i, TypeSlot, Typ);
|
||||||
@ -1471,14 +1308,9 @@ void BytecodeReader::ParseCompactionTable() {
|
|||||||
// Notify handler that we're beginning a compaction table.
|
// Notify handler that we're beginning a compaction table.
|
||||||
if (Handler) Handler->handleCompactionTableBegin();
|
if (Handler) Handler->handleCompactionTableBegin();
|
||||||
|
|
||||||
// In LLVM 1.3 Type no longer derives from Value. So,
|
// Get the types for the compaction table.
|
||||||
// we always write them first in the compaction table
|
|
||||||
// because they can't occupy a "type plane" where the
|
|
||||||
// Values reside.
|
|
||||||
if (! hasTypeDerivedFromValue) {
|
|
||||||
unsigned NumEntries = read_vbr_uint();
|
unsigned NumEntries = read_vbr_uint();
|
||||||
ParseCompactionTypes(NumEntries);
|
ParseCompactionTypes(NumEntries);
|
||||||
}
|
|
||||||
|
|
||||||
// Compaction tables live in separate blocks so we have to loop
|
// Compaction tables live in separate blocks so we have to loop
|
||||||
// until we've read the whole thing.
|
// until we've read the whole thing.
|
||||||
@ -1486,7 +1318,6 @@ void BytecodeReader::ParseCompactionTable() {
|
|||||||
// Read the number of Value* entries in the compaction table
|
// Read the number of Value* entries in the compaction table
|
||||||
unsigned NumEntries = read_vbr_uint();
|
unsigned NumEntries = read_vbr_uint();
|
||||||
unsigned Ty = 0;
|
unsigned Ty = 0;
|
||||||
unsigned isTypeType = false;
|
|
||||||
|
|
||||||
// Decode the type from value read in. Most compaction table
|
// Decode the type from value read in. Most compaction table
|
||||||
// planes will have one or two entries in them. If that's the
|
// planes will have one or two entries in them. If that's the
|
||||||
@ -1496,20 +1327,14 @@ void BytecodeReader::ParseCompactionTable() {
|
|||||||
// In this case, both low-order bits are set (value 3). This
|
// In this case, both low-order bits are set (value 3). This
|
||||||
// is a signal that the typeid follows.
|
// is a signal that the typeid follows.
|
||||||
NumEntries >>= 2;
|
NumEntries >>= 2;
|
||||||
isTypeType = read_typeid(Ty);
|
Ty = read_vbr_uint();
|
||||||
} else {
|
} else {
|
||||||
// In this case, the low-order bits specify the number of entries
|
// In this case, the low-order bits specify the number of entries
|
||||||
// and the high order bits specify the type.
|
// and the high order bits specify the type.
|
||||||
Ty = NumEntries >> 2;
|
Ty = NumEntries >> 2;
|
||||||
isTypeType = sanitizeTypeId(Ty);
|
|
||||||
NumEntries &= 3;
|
NumEntries &= 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
// if we're reading a pre 1.3 bytecode file and the type plane
|
|
||||||
// is the "type type", handle it here
|
|
||||||
if (isTypeType) {
|
|
||||||
ParseCompactionTypes(NumEntries);
|
|
||||||
} else {
|
|
||||||
// Make sure we have enough room for the plane.
|
// Make sure we have enough room for the plane.
|
||||||
if (Ty >= CompactionValues.size())
|
if (Ty >= CompactionValues.size())
|
||||||
CompactionValues.resize(Ty+1);
|
CompactionValues.resize(Ty+1);
|
||||||
@ -1533,7 +1358,6 @@ void BytecodeReader::ParseCompactionTable() {
|
|||||||
if (Handler) Handler->handleCompactionTableValue(i, Ty, ValSlot);
|
if (Handler) Handler->handleCompactionTableValue(i, Ty, ValSlot);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
// Notify handler that the compaction table is done.
|
// Notify handler that the compaction table is done.
|
||||||
if (Handler) Handler->handleCompactionTableEnd();
|
if (Handler) Handler->handleCompactionTableEnd();
|
||||||
}
|
}
|
||||||
@ -1543,23 +1367,20 @@ void BytecodeReader::ParseCompactionTable() {
|
|||||||
// a derived type, then additional data is read to fill out the type
|
// a derived type, then additional data is read to fill out the type
|
||||||
// definition.
|
// definition.
|
||||||
const Type *BytecodeReader::ParseType() {
|
const Type *BytecodeReader::ParseType() {
|
||||||
unsigned PrimType = 0;
|
unsigned PrimType = read_vbr_uint();
|
||||||
if (read_typeid(PrimType))
|
|
||||||
error("Invalid type (type type) in type constants!");
|
|
||||||
|
|
||||||
const Type *Result = 0;
|
const Type *Result = 0;
|
||||||
if ((Result = Type::getPrimitiveType((Type::TypeID)PrimType)))
|
if ((Result = Type::getPrimitiveType((Type::TypeID)PrimType)))
|
||||||
return Result;
|
return Result;
|
||||||
|
|
||||||
switch (PrimType) {
|
switch (PrimType) {
|
||||||
case Type::FunctionTyID: {
|
case Type::FunctionTyID: {
|
||||||
const Type *RetType = readSanitizedType();
|
const Type *RetType = readType();
|
||||||
|
|
||||||
unsigned NumParams = read_vbr_uint();
|
unsigned NumParams = read_vbr_uint();
|
||||||
|
|
||||||
std::vector<const Type*> Params;
|
std::vector<const Type*> Params;
|
||||||
while (NumParams--)
|
while (NumParams--)
|
||||||
Params.push_back(readSanitizedType());
|
Params.push_back(readType());
|
||||||
|
|
||||||
bool isVarArg = Params.size() && Params.back() == Type::VoidTy;
|
bool isVarArg = Params.size() && Params.back() == Type::VoidTy;
|
||||||
if (isVarArg) Params.pop_back();
|
if (isVarArg) Params.pop_back();
|
||||||
@ -1568,34 +1389,30 @@ const Type *BytecodeReader::ParseType() {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Type::ArrayTyID: {
|
case Type::ArrayTyID: {
|
||||||
const Type *ElementType = readSanitizedType();
|
const Type *ElementType = readType();
|
||||||
unsigned NumElements = read_vbr_uint();
|
unsigned NumElements = read_vbr_uint();
|
||||||
Result = ArrayType::get(ElementType, NumElements);
|
Result = ArrayType::get(ElementType, NumElements);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Type::PackedTyID: {
|
case Type::PackedTyID: {
|
||||||
const Type *ElementType = readSanitizedType();
|
const Type *ElementType = readType();
|
||||||
unsigned NumElements = read_vbr_uint();
|
unsigned NumElements = read_vbr_uint();
|
||||||
Result = PackedType::get(ElementType, NumElements);
|
Result = PackedType::get(ElementType, NumElements);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Type::StructTyID: {
|
case Type::StructTyID: {
|
||||||
std::vector<const Type*> Elements;
|
std::vector<const Type*> Elements;
|
||||||
unsigned Typ = 0;
|
unsigned Typ = read_vbr_uint();
|
||||||
if (read_typeid(Typ))
|
|
||||||
error("Invalid element type (type type) for structure!");
|
|
||||||
|
|
||||||
while (Typ) { // List is terminated by void/0 typeid
|
while (Typ) { // List is terminated by void/0 typeid
|
||||||
Elements.push_back(getType(Typ));
|
Elements.push_back(getType(Typ));
|
||||||
if (read_typeid(Typ))
|
Typ = read_vbr_uint();
|
||||||
error("Invalid element type (type type) for structure!");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Result = StructType::get(Elements);
|
Result = StructType::get(Elements);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Type::PointerTyID: {
|
case Type::PointerTyID: {
|
||||||
Result = PointerType::get(readSanitizedType());
|
Result = PointerType::get(readType());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1676,14 +1493,6 @@ inline unsigned BytecodeReader::upgradeCEOpcodes(
|
|||||||
if (!hasSignlessDivRem && !hasSignlessShrCastSetcc)
|
if (!hasSignlessDivRem && !hasSignlessShrCastSetcc)
|
||||||
return Opcode;
|
return Opcode;
|
||||||
|
|
||||||
#if 0
|
|
||||||
// If this is a bytecode format that did not include the unreachable
|
|
||||||
// instruction, bump up the opcode number to adjust it.
|
|
||||||
if (hasNoUnreachableInst)
|
|
||||||
if (Opcode >= 6 && Opcode < 62)
|
|
||||||
++Opcode;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// If this is bytecode version 6, that only had signed Rem and Div
|
// If this is bytecode version 6, that only had signed Rem and Div
|
||||||
// instructions, then we must compensate for those two instructions only.
|
// instructions, then we must compensate for those two instructions only.
|
||||||
// So that the switch statement below works, we're trying to turn this into
|
// So that the switch statement below works, we're trying to turn this into
|
||||||
@ -1805,7 +1614,6 @@ Value *BytecodeReader::ParseConstantPoolValue(unsigned TypeID) {
|
|||||||
unsigned isExprNumArgs = read_vbr_uint();
|
unsigned isExprNumArgs = read_vbr_uint();
|
||||||
|
|
||||||
if (isExprNumArgs) {
|
if (isExprNumArgs) {
|
||||||
if (!hasNoUndefValue) {
|
|
||||||
// 'undef' is encoded with 'exprnumargs' == 1.
|
// 'undef' is encoded with 'exprnumargs' == 1.
|
||||||
if (isExprNumArgs == 1)
|
if (isExprNumArgs == 1)
|
||||||
return UndefValue::get(getType(TypeID));
|
return UndefValue::get(getType(TypeID));
|
||||||
@ -1829,22 +1637,16 @@ Value *BytecodeReader::ParseConstantPoolValue(unsigned TypeID) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
--isExprNumArgs;
|
--isExprNumArgs;
|
||||||
}
|
|
||||||
|
|
||||||
// FIXME: Encoding of constant exprs could be much more compact!
|
// FIXME: Encoding of constant exprs could be much more compact!
|
||||||
std::vector<Constant*> ArgVec;
|
std::vector<Constant*> ArgVec;
|
||||||
ArgVec.reserve(isExprNumArgs);
|
ArgVec.reserve(isExprNumArgs);
|
||||||
unsigned Opcode = read_vbr_uint();
|
unsigned Opcode = read_vbr_uint();
|
||||||
|
|
||||||
// Bytecode files before LLVM 1.4 need have a missing terminator inst.
|
|
||||||
if (hasNoUnreachableInst) Opcode++;
|
|
||||||
|
|
||||||
// Read the slot number and types of each of the arguments
|
// Read the slot number and types of each of the arguments
|
||||||
for (unsigned i = 0; i != isExprNumArgs; ++i) {
|
for (unsigned i = 0; i != isExprNumArgs; ++i) {
|
||||||
unsigned ArgValSlot = read_vbr_uint();
|
unsigned ArgValSlot = read_vbr_uint();
|
||||||
unsigned ArgTypeSlot = 0;
|
unsigned ArgTypeSlot = read_vbr_uint();
|
||||||
if (read_typeid(ArgTypeSlot))
|
|
||||||
error("Invalid argument type (type type) for constant value");
|
|
||||||
|
|
||||||
// Get the arg value from its slot if it exists, otherwise a placeholder
|
// Get the arg value from its slot if it exists, otherwise a placeholder
|
||||||
ArgVec.push_back(getConstantValue(ArgTypeSlot, ArgValSlot));
|
ArgVec.push_back(getConstantValue(ArgTypeSlot, ArgValSlot));
|
||||||
@ -1863,20 +1665,6 @@ Value *BytecodeReader::ParseConstantPoolValue(unsigned TypeID) {
|
|||||||
return Result;
|
return Result;
|
||||||
} else if (Opcode == Instruction::GetElementPtr) { // GetElementPtr
|
} else if (Opcode == Instruction::GetElementPtr) { // GetElementPtr
|
||||||
std::vector<Constant*> IdxList(ArgVec.begin()+1, ArgVec.end());
|
std::vector<Constant*> IdxList(ArgVec.begin()+1, ArgVec.end());
|
||||||
|
|
||||||
if (hasRestrictedGEPTypes) {
|
|
||||||
const Type *BaseTy = ArgVec[0]->getType();
|
|
||||||
generic_gep_type_iterator<std::vector<Constant*>::iterator>
|
|
||||||
GTI = gep_type_begin(BaseTy, IdxList.begin(), IdxList.end()),
|
|
||||||
E = gep_type_end(BaseTy, IdxList.begin(), IdxList.end());
|
|
||||||
for (unsigned i = 0; GTI != E; ++GTI, ++i)
|
|
||||||
if (isa<StructType>(*GTI)) {
|
|
||||||
if (IdxList[i]->getType() != Type::UByteTy)
|
|
||||||
error("Invalid index for getelementptr!");
|
|
||||||
IdxList[i] = ConstantExpr::getCast(IdxList[i], Type::UIntTy);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Constant* Result = ConstantExpr::getGetElementPtr(ArgVec[0], IdxList);
|
Constant* Result = ConstantExpr::getGetElementPtr(ArgVec[0], IdxList);
|
||||||
if (Handler) Handler->handleConstantExpression(Opcode, ArgVec, Result);
|
if (Handler) Handler->handleConstantExpression(Opcode, ArgVec, Result);
|
||||||
return Result;
|
return Result;
|
||||||
@ -2068,9 +1856,7 @@ void BytecodeReader::ResolveReferencesToConstant(Constant *NewV, unsigned Typ,
|
|||||||
/// Parse the constant strings section.
|
/// Parse the constant strings section.
|
||||||
void BytecodeReader::ParseStringConstants(unsigned NumEntries, ValueTable &Tab){
|
void BytecodeReader::ParseStringConstants(unsigned NumEntries, ValueTable &Tab){
|
||||||
for (; NumEntries; --NumEntries) {
|
for (; NumEntries; --NumEntries) {
|
||||||
unsigned Typ = 0;
|
unsigned Typ = read_vbr_uint();
|
||||||
if (read_typeid(Typ))
|
|
||||||
error("Invalid type (type type) for string constant");
|
|
||||||
const Type *Ty = getType(Typ);
|
const Type *Ty = getType(Typ);
|
||||||
if (!isa<ArrayType>(Ty))
|
if (!isa<ArrayType>(Ty))
|
||||||
error("String constant data invalid!");
|
error("String constant data invalid!");
|
||||||
@ -2106,22 +1892,16 @@ void BytecodeReader::ParseConstantPool(ValueTable &Tab,
|
|||||||
/// In LLVM 1.3 Type does not derive from Value so the types
|
/// In LLVM 1.3 Type does not derive from Value so the types
|
||||||
/// do not occupy a plane. Consequently, we read the types
|
/// do not occupy a plane. Consequently, we read the types
|
||||||
/// first in the constant pool.
|
/// first in the constant pool.
|
||||||
if (isFunction && !hasTypeDerivedFromValue) {
|
if (isFunction) {
|
||||||
unsigned NumEntries = read_vbr_uint();
|
unsigned NumEntries = read_vbr_uint();
|
||||||
ParseTypes(TypeTab, NumEntries);
|
ParseTypes(TypeTab, NumEntries);
|
||||||
}
|
}
|
||||||
|
|
||||||
while (moreInBlock()) {
|
while (moreInBlock()) {
|
||||||
unsigned NumEntries = read_vbr_uint();
|
unsigned NumEntries = read_vbr_uint();
|
||||||
unsigned Typ = 0;
|
unsigned Typ = read_vbr_uint();
|
||||||
bool isTypeType = read_typeid(Typ);
|
|
||||||
|
|
||||||
/// In LLVM 1.2 and before, Types were written to the
|
if (Typ == Type::VoidTyID) {
|
||||||
/// bytecode file in the "Type Type" plane (#12).
|
|
||||||
/// In 1.3 plane 12 is now the label plane. Handle this here.
|
|
||||||
if (isTypeType) {
|
|
||||||
ParseTypes(TypeTab, NumEntries);
|
|
||||||
} else if (Typ == Type::VoidTyID) {
|
|
||||||
/// Use of Type::VoidTyID is a misnomer. It actually means
|
/// Use of Type::VoidTyID is a misnomer. It actually means
|
||||||
/// that the following plane is constant strings
|
/// that the following plane is constant strings
|
||||||
assert(&Tab == &ModuleValues && "Cannot read strings in functions!");
|
assert(&Tab == &ModuleValues && "Cannot read strings in functions!");
|
||||||
@ -2213,20 +1993,6 @@ void BytecodeReader::ParseFunctionBody(Function* F) {
|
|||||||
ParseCompactionTable();
|
ParseCompactionTable();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case BytecodeFormat::BasicBlock: {
|
|
||||||
if (!InsertedArguments) {
|
|
||||||
// Insert arguments into the value table before we parse the first basic
|
|
||||||
// block in the function, but after we potentially read in the
|
|
||||||
// compaction table.
|
|
||||||
insertArguments(F);
|
|
||||||
InsertedArguments = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
BasicBlock *BB = ParseBasicBlock(BlockNum++);
|
|
||||||
F->getBasicBlockList().push_back(BB);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case BytecodeFormat::InstructionListBlockID: {
|
case BytecodeFormat::InstructionListBlockID: {
|
||||||
// Insert arguments into the value table before we parse the instruction
|
// Insert arguments into the value table before we parse the instruction
|
||||||
// list for the function, but after we potentially read in the compaction
|
// list for the function, but after we potentially read in the compaction
|
||||||
@ -2253,9 +2019,6 @@ void BytecodeReader::ParseFunctionBody(Function* F) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
BlockEnd = MyEnd;
|
BlockEnd = MyEnd;
|
||||||
|
|
||||||
// Malformed bc file if read past end of block.
|
|
||||||
align32();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make sure there were no references to non-existant basic blocks.
|
// Make sure there were no references to non-existant basic blocks.
|
||||||
@ -2382,11 +2145,6 @@ bool BytecodeReader::ParseAllFunctionBodies(std::string* ErrMsg) {
|
|||||||
void BytecodeReader::ParseGlobalTypes() {
|
void BytecodeReader::ParseGlobalTypes() {
|
||||||
// Read the number of types
|
// Read the number of types
|
||||||
unsigned NumEntries = read_vbr_uint();
|
unsigned NumEntries = read_vbr_uint();
|
||||||
|
|
||||||
// Ignore the type plane identifier for types if the bc file is pre 1.3
|
|
||||||
if (hasTypeDerivedFromValue)
|
|
||||||
read_vbr_uint();
|
|
||||||
|
|
||||||
ParseTypes(ModuleTypes, NumEntries);
|
ParseTypes(ModuleTypes, NumEntries);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2405,8 +2163,6 @@ void BytecodeReader::ParseModuleGlobalInfo() {
|
|||||||
// VarType Fields: bit0 = isConstant, bit1 = hasInitializer, bit2,3,4 =
|
// VarType Fields: bit0 = isConstant, bit1 = hasInitializer, bit2,3,4 =
|
||||||
// Linkage, bit4+ = slot#
|
// Linkage, bit4+ = slot#
|
||||||
unsigned SlotNo = VarType >> 5;
|
unsigned SlotNo = VarType >> 5;
|
||||||
if (sanitizeTypeId(SlotNo))
|
|
||||||
error("Invalid type (type type) for global var!");
|
|
||||||
unsigned LinkageID = (VarType >> 2) & 7;
|
unsigned LinkageID = (VarType >> 2) & 7;
|
||||||
bool isConstant = VarType & 1;
|
bool isConstant = VarType & 1;
|
||||||
bool hasInitializer = (VarType & 2) != 0;
|
bool hasInitializer = (VarType & 2) != 0;
|
||||||
@ -2477,9 +2233,6 @@ void BytecodeReader::ParseModuleGlobalInfo() {
|
|||||||
// Read the function objects for all of the functions that are coming
|
// Read the function objects for all of the functions that are coming
|
||||||
unsigned FnSignature = read_vbr_uint();
|
unsigned FnSignature = read_vbr_uint();
|
||||||
|
|
||||||
if (hasNoFlagsForFunctions)
|
|
||||||
FnSignature = (FnSignature << 5) + 1;
|
|
||||||
|
|
||||||
// List is terminated by VoidTy.
|
// List is terminated by VoidTy.
|
||||||
while (((FnSignature & (~0U >> 1)) >> 5) != Type::VoidTyID) {
|
while (((FnSignature & (~0U >> 1)) >> 5) != Type::VoidTyID) {
|
||||||
const Type *Ty = getType((FnSignature & (~0U >> 1)) >> 5);
|
const Type *Ty = getType((FnSignature & (~0U >> 1)) >> 5);
|
||||||
@ -2535,8 +2288,6 @@ void BytecodeReader::ParseModuleGlobalInfo() {
|
|||||||
|
|
||||||
// Get the next function signature.
|
// Get the next function signature.
|
||||||
FnSignature = read_vbr_uint();
|
FnSignature = read_vbr_uint();
|
||||||
if (hasNoFlagsForFunctions)
|
|
||||||
FnSignature = (FnSignature << 5) + 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now that the function signature list is set up, reverse it so that we can
|
// Now that the function signature list is set up, reverse it so that we can
|
||||||
@ -2548,11 +2299,7 @@ void BytecodeReader::ParseModuleGlobalInfo() {
|
|||||||
/// into this to get their section name.
|
/// into this to get their section name.
|
||||||
std::vector<std::string> SectionNames;
|
std::vector<std::string> SectionNames;
|
||||||
|
|
||||||
if (hasInconsistentModuleGlobalInfo) {
|
// Read in the dependent library information.
|
||||||
align32();
|
|
||||||
} else if (!hasNoDependentLibraries) {
|
|
||||||
// If this bytecode format has dependent library information in it, read in
|
|
||||||
// the number of dependent library items that follow.
|
|
||||||
unsigned num_dep_libs = read_vbr_uint();
|
unsigned num_dep_libs = read_vbr_uint();
|
||||||
std::string dep_lib;
|
std::string dep_lib;
|
||||||
while (num_dep_libs--) {
|
while (num_dep_libs--) {
|
||||||
@ -2568,7 +2315,7 @@ void BytecodeReader::ParseModuleGlobalInfo() {
|
|||||||
if (Handler)
|
if (Handler)
|
||||||
Handler->handleTargetTriple(triple);
|
Handler->handleTargetTriple(triple);
|
||||||
|
|
||||||
if (!hasAlignment && At != BlockEnd) {
|
if (At != BlockEnd) {
|
||||||
// If the file has section info in it, read the section names now.
|
// If the file has section info in it, read the section names now.
|
||||||
unsigned NumSections = read_vbr_uint();
|
unsigned NumSections = read_vbr_uint();
|
||||||
while (NumSections--)
|
while (NumSections--)
|
||||||
@ -2576,9 +2323,8 @@ void BytecodeReader::ParseModuleGlobalInfo() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// If the file has module-level inline asm, read it now.
|
// If the file has module-level inline asm, read it now.
|
||||||
if (!hasAlignment && At != BlockEnd)
|
if (At != BlockEnd)
|
||||||
TheModule->setModuleInlineAsm(read_str());
|
TheModule->setModuleInlineAsm(read_str());
|
||||||
}
|
|
||||||
|
|
||||||
// If any globals are in specified sections, assign them now.
|
// If any globals are in specified sections, assign them now.
|
||||||
for (std::map<GlobalValue*, unsigned>::iterator I = SectionID.begin(), E =
|
for (std::map<GlobalValue*, unsigned>::iterator I = SectionID.begin(), E =
|
||||||
@ -2613,18 +2359,7 @@ void BytecodeReader::ParseVersionInfo() {
|
|||||||
|
|
||||||
RevisionNum = Version >> 4;
|
RevisionNum = Version >> 4;
|
||||||
|
|
||||||
// Default values for the current bytecode version
|
// Default the backwards compatibility flag values for the current BC version
|
||||||
hasInconsistentModuleGlobalInfo = false;
|
|
||||||
hasExplicitPrimitiveZeros = false;
|
|
||||||
hasRestrictedGEPTypes = false;
|
|
||||||
hasTypeDerivedFromValue = false;
|
|
||||||
hasLongBlockHeaders = false;
|
|
||||||
has32BitTypes = false;
|
|
||||||
hasNoDependentLibraries = false;
|
|
||||||
hasAlignment = false;
|
|
||||||
hasNoUndefValue = false;
|
|
||||||
hasNoFlagsForFunctions = false;
|
|
||||||
hasNoUnreachableInst = false;
|
|
||||||
hasSignlessDivRem = false;
|
hasSignlessDivRem = false;
|
||||||
hasSignlessShrCastSetcc = false;
|
hasSignlessShrCastSetcc = false;
|
||||||
|
|
||||||
@ -2632,76 +2367,12 @@ void BytecodeReader::ParseVersionInfo() {
|
|||||||
// bytecode file's version number
|
// bytecode file's version number
|
||||||
switch (RevisionNum) {
|
switch (RevisionNum) {
|
||||||
case 0: // LLVM 1.0, 1.1 (Released)
|
case 0: // LLVM 1.0, 1.1 (Released)
|
||||||
// Base LLVM 1.0 bytecode format.
|
|
||||||
hasInconsistentModuleGlobalInfo = true;
|
|
||||||
hasExplicitPrimitiveZeros = true;
|
|
||||||
|
|
||||||
// FALL THROUGH
|
|
||||||
|
|
||||||
case 1: // LLVM 1.2 (Released)
|
case 1: // LLVM 1.2 (Released)
|
||||||
// LLVM 1.2 added explicit support for emitting strings efficiently.
|
|
||||||
|
|
||||||
// Also, it fixed the problem where the size of the ModuleGlobalInfo block
|
|
||||||
// included the size for the alignment at the end, where the rest of the
|
|
||||||
// blocks did not.
|
|
||||||
|
|
||||||
// LLVM 1.2 and before required that GEP indices be ubyte constants for
|
|
||||||
// structures and longs for sequential types.
|
|
||||||
hasRestrictedGEPTypes = true;
|
|
||||||
|
|
||||||
// LLVM 1.2 and before had the Type class derive from Value class. This
|
|
||||||
// changed in release 1.3 and consequently LLVM 1.3 bytecode files are
|
|
||||||
// written differently because Types can no longer be part of the
|
|
||||||
// type planes for Values.
|
|
||||||
hasTypeDerivedFromValue = true;
|
|
||||||
|
|
||||||
// FALL THROUGH
|
|
||||||
|
|
||||||
case 2: // 1.2.5 (Not Released)
|
case 2: // 1.2.5 (Not Released)
|
||||||
|
|
||||||
// LLVM 1.2 and earlier had two-word block headers. This is a bit wasteful,
|
|
||||||
// especially for small files where the 8 bytes per block is a large
|
|
||||||
// fraction of the total block size. In LLVM 1.3, the block type and length
|
|
||||||
// are compressed into a single 32-bit unsigned integer. 27 bits for length,
|
|
||||||
// 5 bits for block type.
|
|
||||||
hasLongBlockHeaders = true;
|
|
||||||
|
|
||||||
// LLVM 1.2 and earlier wrote type slot numbers as vbr_uint32. In LLVM 1.3
|
|
||||||
// this has been reduced to vbr_uint24. It shouldn't make much difference
|
|
||||||
// since we haven't run into a module with > 24 million types, but for
|
|
||||||
// safety the 24-bit restriction has been enforced in 1.3 to free some bits
|
|
||||||
// in various places and to ensure consistency.
|
|
||||||
has32BitTypes = true;
|
|
||||||
|
|
||||||
// LLVM 1.2 and earlier did not provide a target triple nor a list of
|
|
||||||
// libraries on which the bytecode is dependent. LLVM 1.3 provides these
|
|
||||||
// features, for use in future versions of LLVM.
|
|
||||||
hasNoDependentLibraries = true;
|
|
||||||
|
|
||||||
// FALL THROUGH
|
|
||||||
|
|
||||||
case 3: // LLVM 1.3 (Released)
|
case 3: // LLVM 1.3 (Released)
|
||||||
// LLVM 1.3 and earlier caused alignment bytes to be written on some block
|
|
||||||
// boundaries and at the end of some strings. In extreme cases (e.g. lots
|
|
||||||
// of GEP references to a constant array), this can increase the file size
|
|
||||||
// by 30% or more. In version 1.4 alignment is done away with completely.
|
|
||||||
hasAlignment = true;
|
|
||||||
|
|
||||||
// FALL THROUGH
|
|
||||||
|
|
||||||
case 4: // 1.3.1 (Not Released)
|
case 4: // 1.3.1 (Not Released)
|
||||||
// In version 4, we did not support the 'undef' constant.
|
error("Old bytecode formats no longer supported");
|
||||||
hasNoUndefValue = true;
|
break;
|
||||||
|
|
||||||
// In version 4 and above, we did not include space for flags for functions
|
|
||||||
// in the module info block.
|
|
||||||
hasNoFlagsForFunctions = true;
|
|
||||||
|
|
||||||
// In version 4 and above, we did not include the 'unreachable' instruction
|
|
||||||
// in the opcode numbering in the bytecode file.
|
|
||||||
hasNoUnreachableInst = true;
|
|
||||||
|
|
||||||
// FALL THROUGH
|
|
||||||
|
|
||||||
case 5: // 1.4 (Released)
|
case 5: // 1.4 (Released)
|
||||||
// In version 6, the Div and Rem instructions were converted to their
|
// In version 6, the Div and Rem instructions were converted to their
|
||||||
@ -2712,7 +2383,7 @@ void BytecodeReader::ParseVersionInfo() {
|
|||||||
|
|
||||||
// FALL THROUGH
|
// FALL THROUGH
|
||||||
|
|
||||||
case 6: // Signless Rem & Div Implementation (1.9 release)
|
case 6: // 1.9 (Released)
|
||||||
// In version 5 and prior, instructions were signless while integer types
|
// In version 5 and prior, instructions were signless while integer types
|
||||||
// were signed. In version 6, instructions became signed and types became
|
// were signed. In version 6, instructions became signed and types became
|
||||||
// signless. For example in version 5 we have the DIV instruction but in
|
// signless. For example in version 5 we have the DIV instruction but in
|
||||||
@ -2747,7 +2418,6 @@ void BytecodeReader::ParseModule() {
|
|||||||
|
|
||||||
// Read into instance variables...
|
// Read into instance variables...
|
||||||
ParseVersionInfo();
|
ParseVersionInfo();
|
||||||
align32();
|
|
||||||
|
|
||||||
bool SeenModuleGlobalInfo = false;
|
bool SeenModuleGlobalInfo = false;
|
||||||
bool SeenGlobalTypePlane = false;
|
bool SeenGlobalTypePlane = false;
|
||||||
@ -2794,7 +2464,6 @@ void BytecodeReader::ParseModule() {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
BlockEnd = MyEnd;
|
BlockEnd = MyEnd;
|
||||||
align32();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// After the module constant pool has been read, we can safely initialize
|
// After the module constant pool has been read, we can safely initialize
|
||||||
|
@ -292,69 +292,6 @@ private:
|
|||||||
|
|
||||||
/// Flags to distinguish LLVM 1.0 & 1.1 bytecode formats (revision #0)
|
/// Flags to distinguish LLVM 1.0 & 1.1 bytecode formats (revision #0)
|
||||||
|
|
||||||
/// Revision #0 had an explicit alignment of data only for the
|
|
||||||
/// ModuleGlobalInfo block. This was fixed to be like all other blocks in 1.2
|
|
||||||
bool hasInconsistentModuleGlobalInfo;
|
|
||||||
|
|
||||||
/// Revision #0 also explicitly encoded zero values for primitive types like
|
|
||||||
/// int/sbyte/etc.
|
|
||||||
bool hasExplicitPrimitiveZeros;
|
|
||||||
|
|
||||||
// Flags to control features specific the LLVM 1.2 and before (revision #1)
|
|
||||||
|
|
||||||
/// LLVM 1.2 and earlier required that getelementptr structure indices were
|
|
||||||
/// ubyte constants and that sequential type indices were longs.
|
|
||||||
bool hasRestrictedGEPTypes;
|
|
||||||
|
|
||||||
/// LLVM 1.2 and earlier had class Type deriving from Value and the Type
|
|
||||||
/// objects were located in the "Type Type" plane of various lists in read
|
|
||||||
/// by the bytecode reader. In LLVM 1.3 this is no longer the case. Types are
|
|
||||||
/// completely distinct from Values. Consequently, Types are written in fixed
|
|
||||||
/// locations in LLVM 1.3. This flag indicates that the older Type derived
|
|
||||||
/// from Value style of bytecode file is being read.
|
|
||||||
bool hasTypeDerivedFromValue;
|
|
||||||
|
|
||||||
/// LLVM 1.2 and earlier encoded block headers as two uint (8 bytes), one for
|
|
||||||
/// the size and one for the type. This is a bit wasteful, especially for
|
|
||||||
/// small files where the 8 bytes per block is a large fraction of the total
|
|
||||||
/// block size. In LLVM 1.3, the block type and length are encoded into a
|
|
||||||
/// single uint32 by restricting the number of block types (limit 31) and the
|
|
||||||
/// maximum size of a block (limit 2^27-1=134,217,727). Note that the module
|
|
||||||
/// block still uses the 8-byte format so the maximum size of a file can be
|
|
||||||
/// 2^32-1 bytes long.
|
|
||||||
bool hasLongBlockHeaders;
|
|
||||||
|
|
||||||
/// LLVM 1.2 and earlier wrote type slot numbers as vbr_uint32. In LLVM 1.3
|
|
||||||
/// this has been reduced to vbr_uint24. It shouldn't make much difference
|
|
||||||
/// since we haven't run into a module with > 24 million types, but for safety
|
|
||||||
/// the 24-bit restriction has been enforced in 1.3 to free some bits in
|
|
||||||
/// various places and to ensure consistency. In particular, global vars are
|
|
||||||
/// restricted to 24-bits.
|
|
||||||
bool has32BitTypes;
|
|
||||||
|
|
||||||
/// LLVM 1.2 and earlier did not provide a target triple nor a list of
|
|
||||||
/// libraries on which the bytecode is dependent. LLVM 1.3 provides these
|
|
||||||
/// features, for use in future versions of LLVM.
|
|
||||||
bool hasNoDependentLibraries;
|
|
||||||
|
|
||||||
/// LLVM 1.3 and earlier caused blocks and other fields to start on 32-bit
|
|
||||||
/// aligned boundaries. This can lead to as much as 30% bytecode size overhead
|
|
||||||
/// in various corner cases (lots of long instructions). In LLVM 1.4,
|
|
||||||
/// alignment of bytecode fields was done away with completely.
|
|
||||||
bool hasAlignment;
|
|
||||||
|
|
||||||
// In version 4 and earlier, the bytecode format did not support the 'undef'
|
|
||||||
// constant.
|
|
||||||
bool hasNoUndefValue;
|
|
||||||
|
|
||||||
// In version 4 and earlier, the bytecode format did not save space for flags
|
|
||||||
// in the global info block for functions.
|
|
||||||
bool hasNoFlagsForFunctions;
|
|
||||||
|
|
||||||
// In version 4 and earlier, there was no opcode space reserved for the
|
|
||||||
// unreachable instruction.
|
|
||||||
bool hasNoUnreachableInst;
|
|
||||||
|
|
||||||
// In version 6, the Div and Rem instructions were converted to be the
|
// In version 6, the Div and Rem instructions were converted to be the
|
||||||
// signed instructions UDiv, SDiv, URem and SRem. This flag will be true if
|
// signed instructions UDiv, SDiv, URem and SRem. This flag will be true if
|
||||||
// the Div and Rem instructions are signless (ver 5 and prior).
|
// the Div and Rem instructions are signless (ver 5 and prior).
|
||||||
@ -453,12 +390,8 @@ private:
|
|||||||
/// @brief Converts a type slot number to its Type*
|
/// @brief Converts a type slot number to its Type*
|
||||||
const Type *getType(unsigned ID);
|
const Type *getType(unsigned ID);
|
||||||
|
|
||||||
/// @brief Converts a pre-sanitized type slot number to its Type* and
|
/// @brief Read in a type id and turn it into a Type*
|
||||||
/// sanitizes the type id.
|
inline const Type* readType();
|
||||||
inline const Type* getSanitizedType(unsigned& ID );
|
|
||||||
|
|
||||||
/// @brief Read in and get a sanitized type id
|
|
||||||
inline const Type* readSanitizedType();
|
|
||||||
|
|
||||||
/// @brief Converts a Type* to its type slot number
|
/// @brief Converts a Type* to its type slot number
|
||||||
unsigned getTypeSlot(const Type *Ty);
|
unsigned getTypeSlot(const Type *Ty);
|
||||||
@ -559,12 +492,6 @@ private:
|
|||||||
|
|
||||||
/// @brief Read a bytecode block header
|
/// @brief Read a bytecode block header
|
||||||
inline void read_block(unsigned &Type, unsigned &Size);
|
inline void read_block(unsigned &Type, unsigned &Size);
|
||||||
|
|
||||||
/// @brief Read a type identifier and sanitize it.
|
|
||||||
inline bool read_typeid(unsigned &TypeId);
|
|
||||||
|
|
||||||
/// @brief Recalculate type ID for pre 1.3 bytecode files.
|
|
||||||
inline bool sanitizeTypeId(unsigned &TypeId );
|
|
||||||
/// @}
|
/// @}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,97 +0,0 @@
|
|||||||
; This bytecode test pounds on constant expressions
|
|
||||||
|
|
||||||
; RUN: llvm-as < %s | llvm-dis > %t1
|
|
||||||
; RUN: llvm-dis < %s.bc-13 > %t2
|
|
||||||
; RUN: diff %t1 %t2
|
|
||||||
|
|
||||||
; This testcase is for testing expressions constructed from
|
|
||||||
; constant values, including constant pointers to globals.
|
|
||||||
;
|
|
||||||
|
|
||||||
;;-------------------------------
|
|
||||||
;; Test constant cast expressions
|
|
||||||
;;-------------------------------
|
|
||||||
|
|
||||||
global ulong u0x00001 ; hexadecimal unsigned integer constants
|
|
||||||
global long s0x0012312 ; hexadecimal signed integer constants
|
|
||||||
|
|
||||||
%t2 = global int* %t1 ;; Forward reference without cast
|
|
||||||
%t3 = global uint* cast (int* %t1 to uint*) ;; Forward reference with cast
|
|
||||||
%t1 = global int 4 ;; int* %0
|
|
||||||
%t4 = global int** cast (uint** %t3 to int**) ;; Cast of a previous cast
|
|
||||||
%t5 = global uint** %t3 ;; Reference to a previous cast
|
|
||||||
%t6 = global int*** %t4 ;; Different ref. to a previous cast
|
|
||||||
%t7 = global float* cast (int 12345678 to float*) ;; Cast ordinary value to ptr
|
|
||||||
%t9 = global int cast (float cast (int 8 to float) to int) ;; Nested cast expression
|
|
||||||
|
|
||||||
global int* cast (float* %0 to int*) ;; Forward numeric reference
|
|
||||||
global float* %0 ;; Duplicate forward numeric reference
|
|
||||||
global float 0.0
|
|
||||||
|
|
||||||
|
|
||||||
;;---------------------------------------------------
|
|
||||||
;; Test constant getelementpr expressions for arrays
|
|
||||||
;;---------------------------------------------------
|
|
||||||
|
|
||||||
%array = constant [2 x int] [ int 12, int 52 ]
|
|
||||||
%arrayPtr = global int* getelementptr ([2 x int]* %array, long 0, long 0) ;; int* &%array[0][0]
|
|
||||||
%arrayPtr5 = global int** getelementptr (int** %arrayPtr, long 5) ;; int* &%arrayPtr[5]
|
|
||||||
|
|
||||||
%somestr = constant [11x sbyte] c"hello world"
|
|
||||||
%char5 = global sbyte* getelementptr([11x sbyte]* %somestr, long 0, long 5)
|
|
||||||
|
|
||||||
;; cast of getelementptr
|
|
||||||
%char8a = global int* cast (sbyte* getelementptr([11x sbyte]* %somestr, long 0, long 8) to int*)
|
|
||||||
|
|
||||||
;; getelementptr containing casts
|
|
||||||
%char8b = global sbyte* getelementptr([11x sbyte]* %somestr, long cast (ubyte 0 to long), long cast (sbyte 8 to long))
|
|
||||||
|
|
||||||
;;-------------------------------------------------------
|
|
||||||
;; TODO: Test constant getelementpr expressions for structures
|
|
||||||
;;-------------------------------------------------------
|
|
||||||
|
|
||||||
%SType = type { int , {float, {ubyte} }, ulong } ;; struct containing struct
|
|
||||||
%SAType = type { int , {[2x float], ulong} } ;; struct containing array
|
|
||||||
|
|
||||||
%S1 = global %SType* null ;; Global initialized to NULL
|
|
||||||
%S2c = constant %SType { int 1, {float,{ubyte}} {float 2.0, {ubyte} {ubyte 3}}, ulong 4}
|
|
||||||
|
|
||||||
%S3c = constant %SAType { int 1, {[2x float], ulong} {[2x float] [float 2.0, float 3.0], ulong 4} }
|
|
||||||
|
|
||||||
%S1ptr = global %SType** %S1 ;; Ref. to global S1
|
|
||||||
%S2 = global %SType* %S2c ;; Ref. to constant S2
|
|
||||||
%S3 = global %SAType* %S3c ;; Ref. to constant S3
|
|
||||||
|
|
||||||
;; Pointer to float (**%S1).1.0
|
|
||||||
%S1fld1a = global float* getelementptr (%SType* %S2c, long 0, ubyte 1, ubyte 0)
|
|
||||||
;; Another ptr to the same!
|
|
||||||
%S1fld1b = global float* getelementptr (%SType* %S2c, long 0, ubyte 1, ubyte 0)
|
|
||||||
|
|
||||||
%S1fld1bptr = global float** %S1fld1b ;; Ref. to previous pointer
|
|
||||||
|
|
||||||
;; Pointer to ubyte (**%S2).1.1.0
|
|
||||||
%S2fld3 = global ubyte* getelementptr (%SType* %S2c, long 0, ubyte 1, ubyte 1, ubyte 0)
|
|
||||||
|
|
||||||
;; Pointer to float (**%S2).1.0[0]
|
|
||||||
;%S3fld3 = global float* getelementptr (%SAType** %S3, long 0, long 0, ubyte 1, ubyte 0, long 0)
|
|
||||||
|
|
||||||
;;---------------------------------------------------------
|
|
||||||
;; TODO: Test constant expressions for unary and binary operators
|
|
||||||
;;---------------------------------------------------------
|
|
||||||
|
|
||||||
|
|
||||||
;;---------------------------------------------------
|
|
||||||
;; Test duplicate constant expressions
|
|
||||||
;;---------------------------------------------------
|
|
||||||
|
|
||||||
%t4 = global int** cast (uint** %t3 to int**)
|
|
||||||
|
|
||||||
%char8a = global int* cast (sbyte* getelementptr([11x sbyte]* %somestr, long 0, long 8) to int*)
|
|
||||||
|
|
||||||
;%S3fld3 = global float* getelementptr (%SAType** %S3, long 0, long 0, ubyte 1, ubyte 0, long 0)
|
|
||||||
|
|
||||||
|
|
||||||
;;---------------------------------------------------
|
|
||||||
|
|
||||||
implementation
|
|
||||||
|
|
Binary file not shown.
21089
test/Bytecode/slow.ll
21089
test/Bytecode/slow.ll
File diff suppressed because it is too large
Load Diff
Binary file not shown.
@ -1,2 +1,3 @@
|
|||||||
; Just see if we can disassemble the ver6.ll.bc bc file for upgrade purposes.
|
; Just see if we can disassemble the ver6.ll.bc bc file for upgrade purposes.
|
||||||
; RUN: llvm-dis < %s.bc | llvm-as | llc -o /dev/null -f -march=c
|
; RUN: llvm-dis < %s.bc | llvm-as | llc -o /dev/null -f -march=c
|
||||||
|
; RUN: llvm-dis < %s.bc | llvm-as | opt -verify | llvm-dis | llvm-as -o /dev/null -f
|
||||||
|
Loading…
x
Reference in New Issue
Block a user