mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-23 03:02:36 +01:00
implement support for reading aggregate constants, including handling forward
constant references, etc. llvm-svn: 36391
This commit is contained in:
parent
77c83b943d
commit
ce97f22311
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ValueList.push_back(V);
|
||||
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;
|
||||
}
|
||||
|
||||
++NextCstNo;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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() {}
|
||||
|
Loading…
Reference in New Issue
Block a user