aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2007-04-24 05:48:56 +0000
committerChris Lattner <sabre@nondot.org>2007-04-24 05:48:56 +0000
commit522b7b104c864da81c19d8b16c43b7a1f6a2fc40 (patch)
treeb3466074088bcbf9feee242542d7938cc639a235
parent0eef08046e0758f1800f32c63b817fd22264577b (diff)
downloadexternal_llvm-522b7b104c864da81c19d8b16c43b7a1f6a2fc40.zip
external_llvm-522b7b104c864da81c19d8b16c43b7a1f6a2fc40.tar.gz
external_llvm-522b7b104c864da81c19d8b16c43b7a1f6a2fc40.tar.bz2
implement support for reading aggregate constants, including handling forward
constant references, etc. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@36391 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Bitcode/Reader/BitcodeReader.cpp78
-rw-r--r--lib/Bitcode/Reader/BitcodeReader.h35
2 files changed, 108 insertions, 5 deletions
diff --git a/lib/Bitcode/Reader/BitcodeReader.cpp b/lib/Bitcode/Reader/BitcodeReader.cpp
index d974ace..fa75e00 100644
--- a/lib/Bitcode/Reader/BitcodeReader.cpp
+++ b/lib/Bitcode/Reader/BitcodeReader.cpp
@@ -55,6 +55,39 @@ static GlobalValue::VisibilityTypes GetDecodedVisibility(unsigned Val) {
}
}
+namespace {
+ /// @brief A class for maintaining the slot number definition
+ /// as a placeholder for the actual definition for forward constants defs.
+ class ConstantPlaceHolder : public ConstantExpr {
+ ConstantPlaceHolder(); // DO NOT IMPLEMENT
+ void operator=(const ConstantPlaceHolder &); // DO NOT IMPLEMENT
+public:
+ Use Op;
+ ConstantPlaceHolder(const Type *Ty)
+ : ConstantExpr(Ty, Instruction::UserOp1, &Op, 1),
+ Op(UndefValue::get(Type::Int32Ty), this) {
+ }
+ };
+}
+
+Constant *BitcodeReaderValueList::getConstantFwdRef(unsigned Idx,
+ const Type *Ty) {
+ if (Idx >= size()) {
+ // Insert a bunch of null values.
+ Uses.resize(Idx+1);
+ OperandList = &Uses[0];
+ NumOperands = Idx+1;
+ }
+
+ if (Uses[Idx])
+ return cast<Constant>(getOperand(Idx));
+
+ // Create and return a placeholder, which will later be RAUW'd.
+ Constant *C = new ConstantPlaceHolder(Ty);
+ Uses[Idx].init(C, this);
+ return C;
+}
+
const Type *BitcodeReader::getTypeByID(unsigned ID, bool isTypeTable) {
// If the TypeID is in range, return it.
@@ -324,6 +357,7 @@ bool BitcodeReader::ParseConstants(BitstreamReader &Stream) {
// Read all the records for this value table.
const Type *CurTy = Type::Int32Ty;
+ unsigned NextCstNo = ValueList.size();
while (1) {
unsigned Code = Stream.ReadCode();
if (Code == bitc::END_BLOCK) {
@@ -341,6 +375,9 @@ bool BitcodeReader::ParseConstants(BitstreamReader &Stream) {
}
}
+ if (NextCstNo != ValueList.size())
+ return Error("Invalid constant reference!");
+
return Stream.ReadBlockEnd();
}
@@ -403,9 +440,48 @@ bool BitcodeReader::ParseConstants(BitstreamReader &Stream) {
else
V = UndefValue::get(CurTy);
break;
+
+ case bitc::CST_CODE_AGGREGATE: {// AGGREGATE: [n, n x value number]
+ if (Record.empty() || Record.size() < Record[0]+1)
+ return Error("Invalid CST_AGGREGATE record");
+
+ unsigned Size = Record[0];
+ std::vector<Constant*> Elts;
+
+ if (const StructType *STy = dyn_cast<StructType>(CurTy)) {
+ for (unsigned i = 0; i != Size; ++i)
+ Elts.push_back(ValueList.getConstantFwdRef(Record[i+1],
+ STy->getElementType(i)));
+ V = ConstantStruct::get(STy, Elts);
+ } else if (const ArrayType *ATy = dyn_cast<ArrayType>(CurTy)) {
+ const Type *EltTy = ATy->getElementType();
+ for (unsigned i = 0; i != Size; ++i)
+ Elts.push_back(ValueList.getConstantFwdRef(Record[i+1], EltTy));
+ V = ConstantArray::get(ATy, Elts);
+ } else if (const VectorType *VTy = dyn_cast<VectorType>(CurTy)) {
+ const Type *EltTy = VTy->getElementType();
+ for (unsigned i = 0; i != Size; ++i)
+ Elts.push_back(ValueList.getConstantFwdRef(Record[i+1], EltTy));
+ V = ConstantVector::get(Elts);
+ } else {
+ V = UndefValue::get(CurTy);
+ }
+ }
+ }
+
+ if (NextCstNo == ValueList.size())
+ ValueList.push_back(V);
+ else if (ValueList[NextCstNo] == 0)
+ ValueList.initVal(NextCstNo, V);
+ else {
+ // If there was a forward reference to this constant,
+ Value *OldV = ValueList[NextCstNo];
+ ValueList.setOperand(NextCstNo, V);
+ OldV->replaceAllUsesWith(V);
+ delete OldV;
}
- ValueList.push_back(V);
+ ++NextCstNo;
}
}
diff --git a/lib/Bitcode/Reader/BitcodeReader.h b/lib/Bitcode/Reader/BitcodeReader.h
index bdb64c8..c7c6152 100644
--- a/lib/Bitcode/Reader/BitcodeReader.h
+++ b/lib/Bitcode/Reader/BitcodeReader.h
@@ -14,21 +14,48 @@
#ifndef BITCODE_READER_H
#define BITCODE_READER_H
-#include "llvm/Type.h"
#include "llvm/ModuleProvider.h"
+#include "llvm/Type.h"
+#include "llvm/User.h"
#include "llvm/Bitcode/LLVMBitCodes.h"
#include <vector>
namespace llvm {
class BitstreamReader;
- class Value;
- class GlobalVariable;
+
+class BitcodeReaderValueList : public User {
+ std::vector<Use> Uses;
+public:
+ BitcodeReaderValueList() : User(Type::VoidTy, Value::ArgumentVal, 0, 0) {}
+
+ // vector compatibility methods
+ unsigned size() const { return getNumOperands(); }
+ void push_back(Value *V) {
+ Uses.push_back(Use(V, this));
+ OperandList = &Uses[0];
+ ++NumOperands;
+ }
+
+ Value *operator[](unsigned i) const { return getOperand(i); }
+
+ Value *back() const { return Uses.back(); }
+ void pop_back() { Uses.pop_back(); --NumOperands; }
+ bool empty() const { return NumOperands == 0; }
+ virtual void print(std::ostream&) const {}
+
+ Constant *getConstantFwdRef(unsigned Idx, const Type *Ty);
+ void initVal(unsigned Idx, Value *V) {
+ assert(Uses[Idx] == 0 && "Cannot init an already init'd Use!");
+ Uses[Idx].init(V, this);
+ }
+};
+
class BitcodeReader : public ModuleProvider {
const char *ErrorString;
std::vector<PATypeHolder> TypeList;
- std::vector<Value*> ValueList;
+ BitcodeReaderValueList ValueList;
std::vector<std::pair<GlobalVariable*, unsigned> > GlobalInits;
public:
virtual ~BitcodeReader() {}