summaryrefslogtreecommitdiff
path: root/lib/Bytecode/Reader/ConstantReader.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Bytecode/Reader/ConstantReader.cpp')
-rw-r--r--lib/Bytecode/Reader/ConstantReader.cpp218
1 files changed, 218 insertions, 0 deletions
diff --git a/lib/Bytecode/Reader/ConstantReader.cpp b/lib/Bytecode/Reader/ConstantReader.cpp
new file mode 100644
index 0000000000..b85bd887ef
--- /dev/null
+++ b/lib/Bytecode/Reader/ConstantReader.cpp
@@ -0,0 +1,218 @@
+//===- ReadConst.cpp - Code to constants and constant pools -----------------===
+//
+// This file implements functionality to deserialize constants and entire
+// constant pools.
+//
+// Note that this library should be as fast as possible, reentrant, and
+// threadsafe!!
+//
+//===------------------------------------------------------------------------===
+
+#include "llvm/Module.h"
+#include "llvm/BasicBlock.h"
+#include "llvm/ConstPoolVals.h"
+#include "llvm/DerivedTypes.h"
+#include "ReaderInternals.h"
+
+bool BytecodeParser::parseTypeConstant(const uchar *&Buf, const uchar *EndBuf,
+ ConstPoolVal *&V) {
+ const Type *Val = 0;
+
+ unsigned PrimType;
+ if (read_vbr(Buf, EndBuf, PrimType)) return true;
+
+ if ((Val = Type::getPrimitiveType((Type::PrimitiveID)PrimType))) {
+ V = new ConstPoolType(Val); // It's just a primitive ID.
+ return false;
+ }
+
+ switch (PrimType) {
+ case Type::MethodTyID: {
+ unsigned Typ;
+ if (read_vbr(Buf, EndBuf, Typ)) return true;
+ const Type *RetType = getType(Typ);
+ if (RetType == 0) return true;
+
+ MethodType::ParamTypes Params;
+
+ if (read_vbr(Buf, EndBuf, Typ)) return true;
+ while (Typ) {
+ const Type *Ty = getType(Typ);
+ if (Ty == 0) return true;
+ Params.push_back(Ty);
+
+ if (read_vbr(Buf, EndBuf, Typ)) return true;
+ }
+
+ Val = MethodType::getMethodType(RetType, Params);
+ break;
+ }
+ case Type::ArrayTyID: {
+ unsigned ElTyp;
+ if (read_vbr(Buf, EndBuf, ElTyp)) return true;
+ const Type *ElementType = getType(ElTyp);
+ if (ElementType == 0) return true;
+
+ int NumElements;
+ if (read_vbr(Buf, EndBuf, NumElements)) return true;
+ Val = ArrayType::getArrayType(ElementType, NumElements);
+ break;
+ }
+ case Type::StructTyID: {
+ unsigned Typ;
+ StructType::ElementTypes Elements;
+
+ if (read_vbr(Buf, EndBuf, Typ)) return true;
+ while (Typ) { // List is terminated by void/0 typeid
+ const Type *Ty = getType(Typ);
+ if (Ty == 0) return true;
+ Elements.push_back(Ty);
+
+ if (read_vbr(Buf, EndBuf, Typ)) return true;
+ }
+
+ Val = StructType::getStructType(Elements);
+ break;
+ }
+ case Type::PointerTyID: {
+ unsigned ElTyp;
+ if (read_vbr(Buf, EndBuf, ElTyp)) return true;
+ const Type *ElementType = getType(ElTyp);
+ if (ElementType == 0) return true;
+ Val = PointerType::getPointerType(ElementType);
+ break;
+ }
+
+ default:
+ cerr << __FILE__ << ":" << __LINE__ << ": Don't know how to deserialize"
+ << " primitive Type " << PrimType << "\n";
+ return true;
+ }
+
+ V = new ConstPoolType(Val);
+ return false;
+}
+
+bool BytecodeParser::parseConstPoolValue(const uchar *&Buf,
+ const uchar *EndBuf,
+ const Type *Ty, ConstPoolVal *&V) {
+ switch (Ty->getPrimitiveID()) {
+ case Type::BoolTyID: {
+ unsigned Val;
+ if (read_vbr(Buf, EndBuf, Val)) return true;
+ if (Val != 0 && Val != 1) return true;
+ V = new ConstPoolBool(Val == 1);
+ break;
+ }
+
+ case Type::UByteTyID: // Unsigned integer types...
+ case Type::UShortTyID:
+ case Type::UIntTyID: {
+ unsigned Val;
+ if (read_vbr(Buf, EndBuf, Val)) return true;
+ if (!ConstPoolUInt::isValueValidForType(Ty, Val)) return true;
+ V = new ConstPoolUInt(Ty, Val);
+ break;
+ }
+
+ case Type::ULongTyID: {
+ uint64_t Val;
+ if (read_vbr(Buf, EndBuf, Val)) return true;
+ V = new ConstPoolUInt(Ty, Val);
+ break;
+ }
+
+ case Type::SByteTyID: // Unsigned integer types...
+ case Type::ShortTyID:
+ case Type::IntTyID: {
+ int Val;
+ if (read_vbr(Buf, EndBuf, Val)) return true;
+ if (!ConstPoolSInt::isValueValidForType(Ty, Val)) return 0;
+ V = new ConstPoolSInt(Ty, Val);
+ break;
+ }
+
+ case Type::LongTyID: {
+ int64_t Val;
+ if (read_vbr(Buf, EndBuf, Val)) return true;
+ V = new ConstPoolSInt(Ty, Val);
+ break;
+ }
+
+ case Type::TypeTyID:
+ if (parseTypeConstant(Buf, EndBuf, V)) return true;
+ break;
+
+ case Type::ArrayTyID: {
+ const ArrayType *AT = (const ArrayType*)Ty;
+ unsigned NumElements;
+ if (AT->isSized()) // Sized array, # elements stored in type!
+ NumElements = (unsigned)AT->getNumElements();
+ else // Unsized array, # elements stored in stream!
+ if (read_vbr(Buf, EndBuf, NumElements)) return true;
+
+ vector<ConstPoolVal *> Elements;
+ while (NumElements--) { // Read all of the elements of the constant.
+ unsigned Slot;
+ if (read_vbr(Buf, EndBuf, Slot)) return true;
+ Value *V = getValue(AT->getElementType(), Slot, false);
+ if (!V || V->getValueType() != Value::ConstantVal)
+ return true;
+ Elements.push_back((ConstPoolVal*)V);
+ }
+ V = new ConstPoolArray(AT, Elements);
+ break;
+ }
+
+ case Type::StructTyID: {
+ const StructType *ST = (const StructType*)Ty;
+ const StructType::ElementTypes &ET = ST->getElementTypes();
+
+ vector<ConstPoolVal *> Elements;
+ for (unsigned i = 0; i < ET.size(); ++i) {
+ unsigned Slot;
+ if (read_vbr(Buf, EndBuf, Slot)) return true;
+ Value *V = getValue(ET[i], Slot, false);
+ if (!V || V->getValueType() != Value::ConstantVal)
+ return true;
+ Elements.push_back((ConstPoolVal*)V);
+ }
+
+ V = new ConstPoolStruct(ST, Elements);
+ break;
+ }
+
+ default:
+ cerr << __FILE__ << ":" << __LINE__
+ << ": Don't know how to deserialize constant value of type '"
+ << Ty->getName() << "'\n";
+ return true;
+ }
+ return false;
+}
+
+bool BytecodeParser::ParseConstantPool(const uchar *&Buf, const uchar *EndBuf,
+ SymTabValue::ConstantPoolType &CP,
+ ValueTable &Tab) {
+ while (Buf < EndBuf) {
+ unsigned NumEntries, Typ;
+
+ if (read_vbr(Buf, EndBuf, NumEntries) ||
+ read_vbr(Buf, EndBuf, Typ)) return true;
+ const Type *Ty = getType(Typ);
+ if (Ty == 0) return true;
+
+ for (unsigned i = 0; i < NumEntries; i++) {
+ ConstPoolVal *I;
+ if (parseConstPoolValue(Buf, EndBuf, Ty, I)) return true;
+#if 0
+ cerr << " Read const value: <" << I->getType()->getName()
+ << ">: " << I->getStrValue() << endl;
+#endif
+ insertValue(I, Tab);
+ CP.insert(I);
+ }
+ }
+
+ return Buf > EndBuf;
+}