aboutsummaryrefslogtreecommitdiff
path: root/lib/Bytecode/Reader
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Bytecode/Reader')
-rw-r--r--lib/Bytecode/Reader/ConstantReader.cpp15
-rw-r--r--lib/Bytecode/Reader/InstructionReader.cpp33
-rw-r--r--lib/Bytecode/Reader/Reader.cpp11
-rw-r--r--lib/Bytecode/Reader/ReaderInternals.h7
4 files changed, 59 insertions, 7 deletions
diff --git a/lib/Bytecode/Reader/ConstantReader.cpp b/lib/Bytecode/Reader/ConstantReader.cpp
index b4a219df6b..8691b26544 100644
--- a/lib/Bytecode/Reader/ConstantReader.cpp
+++ b/lib/Bytecode/Reader/ConstantReader.cpp
@@ -15,6 +15,7 @@
#include "ReaderInternals.h"
#include "llvm/Module.h"
#include "llvm/Constants.h"
+#include "llvm/Support/GetElementPtrTypeIterator.h"
#include <algorithm>
using namespace llvm;
@@ -164,6 +165,20 @@ Constant *BytecodeParser::parseConstantValue(const unsigned char *&Buf,
return ConstantExpr::getCast(ArgVec[0], getType(TypeID));
} else if (Opcode == Instruction::GetElementPtr) { // GetElementPtr
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)
+ throw std::string("Invalid index for getelementptr!");
+ IdxList[i] = ConstantExpr::getCast(IdxList[i], Type::UIntTy);
+ }
+ }
+
return ConstantExpr::getGetElementPtr(ArgVec[0], IdxList);
} else if (Opcode == Instruction::Select) {
assert(ArgVec.size() == 3);
diff --git a/lib/Bytecode/Reader/InstructionReader.cpp b/lib/Bytecode/Reader/InstructionReader.cpp
index 90be8cd6f5..d66b12cf0d 100644
--- a/lib/Bytecode/Reader/InstructionReader.cpp
+++ b/lib/Bytecode/Reader/InstructionReader.cpp
@@ -308,10 +308,35 @@ void BytecodeParser::ParseInstruction(const unsigned char *&Buf,
for (unsigned i = 1, e = Args.size(); i != e; ++i) {
const CompositeType *TopTy = dyn_cast_or_null<CompositeType>(NextTy);
if (!TopTy) throw std::string("Invalid getelementptr instruction!");
- // FIXME: when PR82 is resolved.
- unsigned IdxTy = isa<StructType>(TopTy) ? Type::UByteTyID :Type::LongTyID;
-
- Idx.push_back(getValue(IdxTy, Args[i]));
+
+ unsigned ValIdx = Args[i];
+ unsigned IdxTy;
+ if (!hasRestrictedGEPTypes) {
+ // 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 two bits of the slot number.
+ if (isa<StructType>(TopTy))
+ IdxTy = Type::UIntTyID;
+ else {
+ switch (ValIdx & 3) {
+ case 0: IdxTy = Type::UIntTyID; break;
+ case 1: IdxTy = Type::IntTyID; break;
+ case 2: IdxTy = Type::ULongTyID; break;
+ case 3: IdxTy = Type::LongTyID; break;
+ }
+ ValIdx >>= 2;
+ }
+ } else {
+ IdxTy = isa<StructType>(TopTy) ? Type::UByteTyID : Type::LongTyID;
+ }
+
+ Idx.push_back(getValue(IdxTy, ValIdx));
+
+ // Convert ubyte struct indices into uint struct indices.
+ if (isa<StructType>(TopTy) && hasRestrictedGEPTypes)
+ if (ConstantUInt *C = dyn_cast<ConstantUInt>(Idx.back()))
+ Idx[Idx.size()-1] = ConstantExpr::getCast(C, Type::UIntTy);
+
NextTy = GetElementPtrInst::getIndexedType(InstTy, Idx, true);
}
diff --git a/lib/Bytecode/Reader/Reader.cpp b/lib/Bytecode/Reader/Reader.cpp
index 54c91811a9..2f0879ba39 100644
--- a/lib/Bytecode/Reader/Reader.cpp
+++ b/lib/Bytecode/Reader/Reader.cpp
@@ -647,12 +647,10 @@ void BytecodeParser::ParseVersionInfo(const unsigned char *&Buf,
// Default values for the current bytecode version
hasInconsistentModuleGlobalInfo = false;
hasExplicitPrimitiveZeros = false;
+ hasRestrictedGEPTypes = false;
switch (RevisionNum) {
case 0: // LLVM 1.0, 1.1 release version
- // Compared to rev #2, we added support for weak linkage, a more dense
- // encoding, and better varargs support.
-
// Base LLVM 1.0 bytecode format.
hasInconsistentModuleGlobalInfo = true;
hasExplicitPrimitiveZeros = true;
@@ -663,6 +661,13 @@ void BytecodeParser::ParseVersionInfo(const unsigned char *&Buf,
// 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;
+
+ // FALL THROUGH
+ case 2: // LLVM 1.3 release version
break;
default:
diff --git a/lib/Bytecode/Reader/ReaderInternals.h b/lib/Bytecode/Reader/ReaderInternals.h
index 86bf800ca6..9e0ffc2c36 100644
--- a/lib/Bytecode/Reader/ReaderInternals.h
+++ b/lib/Bytecode/Reader/ReaderInternals.h
@@ -108,6 +108,13 @@ private:
// 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;
+
+
typedef std::vector<ValueList*> ValueTable;
ValueTable Values;
ValueTable ModuleValues;