mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-12-27 14:07:32 +00: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) {
|
const Type *BitcodeReader::getTypeByID(unsigned ID, bool isTypeTable) {
|
||||||
// If the TypeID is in range, return it.
|
// 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.
|
// Read all the records for this value table.
|
||||||
const Type *CurTy = Type::Int32Ty;
|
const Type *CurTy = Type::Int32Ty;
|
||||||
|
unsigned NextCstNo = ValueList.size();
|
||||||
while (1) {
|
while (1) {
|
||||||
unsigned Code = Stream.ReadCode();
|
unsigned Code = Stream.ReadCode();
|
||||||
if (Code == bitc::END_BLOCK) {
|
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();
|
return Stream.ReadBlockEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -403,9 +440,48 @@ bool BitcodeReader::ParseConstants(BitstreamReader &Stream) {
|
|||||||
else
|
else
|
||||||
V = UndefValue::get(CurTy);
|
V = UndefValue::get(CurTy);
|
||||||
break;
|
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
|
#ifndef BITCODE_READER_H
|
||||||
#define BITCODE_READER_H
|
#define BITCODE_READER_H
|
||||||
|
|
||||||
#include "llvm/Type.h"
|
|
||||||
#include "llvm/ModuleProvider.h"
|
#include "llvm/ModuleProvider.h"
|
||||||
|
#include "llvm/Type.h"
|
||||||
|
#include "llvm/User.h"
|
||||||
#include "llvm/Bitcode/LLVMBitCodes.h"
|
#include "llvm/Bitcode/LLVMBitCodes.h"
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
namespace llvm {
|
namespace llvm {
|
||||||
class BitstreamReader;
|
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 {
|
class BitcodeReader : public ModuleProvider {
|
||||||
const char *ErrorString;
|
const char *ErrorString;
|
||||||
|
|
||||||
std::vector<PATypeHolder> TypeList;
|
std::vector<PATypeHolder> TypeList;
|
||||||
std::vector<Value*> ValueList;
|
BitcodeReaderValueList ValueList;
|
||||||
std::vector<std::pair<GlobalVariable*, unsigned> > GlobalInits;
|
std::vector<std::pair<GlobalVariable*, unsigned> > GlobalInits;
|
||||||
public:
|
public:
|
||||||
virtual ~BitcodeReader() {}
|
virtual ~BitcodeReader() {}
|
||||||
|
Loading…
Reference in New Issue
Block a user