mirror of
https://github.com/RPCS3/llvm.git
synced 2025-02-03 17:24:24 +00:00
implement reading and writing of constant exprs.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@36394 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
c9c448ffa2
commit
f581c3b81e
@ -55,17 +55,56 @@ static GlobalValue::VisibilityTypes GetDecodedVisibility(unsigned Val) {
|
||||
}
|
||||
}
|
||||
|
||||
static int GetDecodedCastOpcode(unsigned Val) {
|
||||
switch (Val) {
|
||||
default: return -1;
|
||||
case bitc::CAST_TRUNC : return Instruction::Trunc;
|
||||
case bitc::CAST_ZEXT : return Instruction::ZExt;
|
||||
case bitc::CAST_SEXT : return Instruction::SExt;
|
||||
case bitc::CAST_FPTOUI : return Instruction::FPToUI;
|
||||
case bitc::CAST_FPTOSI : return Instruction::FPToSI;
|
||||
case bitc::CAST_UITOFP : return Instruction::UIToFP;
|
||||
case bitc::CAST_SITOFP : return Instruction::SIToFP;
|
||||
case bitc::CAST_FPTRUNC : return Instruction::FPTrunc;
|
||||
case bitc::CAST_FPEXT : return Instruction::FPExt;
|
||||
case bitc::CAST_PTRTOINT: return Instruction::PtrToInt;
|
||||
case bitc::CAST_INTTOPTR: return Instruction::IntToPtr;
|
||||
case bitc::CAST_BITCAST : return Instruction::BitCast;
|
||||
}
|
||||
}
|
||||
static int GetDecodedBinaryOpcode(unsigned Val, const Type *Ty) {
|
||||
switch (Val) {
|
||||
default: return -1;
|
||||
case bitc::BINOP_ADD: return Instruction::Add;
|
||||
case bitc::BINOP_SUB: return Instruction::Sub;
|
||||
case bitc::BINOP_MUL: return Instruction::Mul;
|
||||
case bitc::BINOP_UDIV: return Instruction::UDiv;
|
||||
case bitc::BINOP_SDIV:
|
||||
return Ty->isFPOrFPVector() ? Instruction::FDiv : Instruction::SDiv;
|
||||
case bitc::BINOP_UREM: return Instruction::URem;
|
||||
case bitc::BINOP_SREM:
|
||||
return Ty->isFPOrFPVector() ? Instruction::FRem : Instruction::SRem;
|
||||
case bitc::BINOP_SHL: return Instruction::Shl;
|
||||
case bitc::BINOP_LSHR: return Instruction::LShr;
|
||||
case bitc::BINOP_ASHR: return Instruction::AShr;
|
||||
case bitc::BINOP_AND: return Instruction::And;
|
||||
case bitc::BINOP_OR: return Instruction::Or;
|
||||
case bitc::BINOP_XOR: return Instruction::Xor;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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) {
|
||||
public:
|
||||
Use Op;
|
||||
ConstantPlaceHolder(const Type *Ty)
|
||||
: ConstantExpr(Ty, Instruction::UserOp1, &Op, 1),
|
||||
Op(UndefValue::get(Type::Int32Ty), this) {
|
||||
}
|
||||
};
|
||||
}
|
||||
@ -79,8 +118,11 @@ Constant *BitcodeReaderValueList::getConstantFwdRef(unsigned Idx,
|
||||
NumOperands = Idx+1;
|
||||
}
|
||||
|
||||
if (Uses[Idx])
|
||||
if (Uses[Idx]) {
|
||||
assert(Ty == getOperand(Idx)->getType() &&
|
||||
"Type mismatch in constant table!");
|
||||
return cast<Constant>(getOperand(Idx));
|
||||
}
|
||||
|
||||
// Create and return a placeholder, which will later be RAUW'd.
|
||||
Constant *C = new ConstantPlaceHolder(Ty);
|
||||
@ -466,6 +508,91 @@ bool BitcodeReader::ParseConstants(BitstreamReader &Stream) {
|
||||
} else {
|
||||
V = UndefValue::get(CurTy);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case bitc::CST_CODE_CE_BINOP: { // CE_BINOP: [opcode, opval, opval]
|
||||
if (Record.size() < 3) return Error("Invalid CE_BINOP record");
|
||||
int Opc = GetDecodedBinaryOpcode(Record[0], CurTy);
|
||||
if (Opc < 0) return UndefValue::get(CurTy); // Unknown binop.
|
||||
|
||||
Constant *LHS = ValueList.getConstantFwdRef(Record[1], CurTy);
|
||||
Constant *RHS = ValueList.getConstantFwdRef(Record[2], CurTy);
|
||||
V = ConstantExpr::get(Opc, LHS, RHS);
|
||||
break;
|
||||
}
|
||||
case bitc::CST_CODE_CE_CAST: { // CE_CAST: [opcode, opty, opval]
|
||||
if (Record.size() < 3) return Error("Invalid CE_CAST record");
|
||||
int Opc = GetDecodedCastOpcode(Record[0]);
|
||||
if (Opc < 0) return UndefValue::get(CurTy); // Unknown cast.
|
||||
|
||||
const Type *OpTy = getTypeByID(Record[1]);
|
||||
Constant *Op = ValueList.getConstantFwdRef(Record[2], OpTy);
|
||||
V = ConstantExpr::getCast(Opc, Op, CurTy);
|
||||
break;
|
||||
}
|
||||
case bitc::CST_CODE_CE_GEP: { // CE_GEP: [n x operands]
|
||||
if ((Record.size() & 1) == 0) return Error("Invalid CE_GEP record");
|
||||
SmallVector<Constant*, 16> Elts;
|
||||
for (unsigned i = 1, e = Record.size(); i != e; i += 2) {
|
||||
const Type *ElTy = getTypeByID(Record[i]);
|
||||
if (!ElTy) return Error("Invalid CE_GEP record");
|
||||
Elts.push_back(ValueList.getConstantFwdRef(Record[i+1], ElTy));
|
||||
}
|
||||
return ConstantExpr::getGetElementPtr(Elts[0], &Elts[1], Elts.size()-1);
|
||||
}
|
||||
case bitc::CST_CODE_CE_SELECT: // CE_SELECT: [opval#, opval#, opval#]
|
||||
if (Record.size() < 3) return Error("Invalid CE_SELECT record");
|
||||
V = ConstantExpr::getSelect(ValueList.getConstantFwdRef(Record[0],
|
||||
Type::Int1Ty),
|
||||
ValueList.getConstantFwdRef(Record[1],CurTy),
|
||||
ValueList.getConstantFwdRef(Record[2],CurTy));
|
||||
break;
|
||||
case bitc::CST_CODE_CE_EXTRACTELT: { // CE_EXTRACTELT: [opty, opval, opval]
|
||||
if (Record.size() < 3) return Error("Invalid CE_EXTRACTELT record");
|
||||
const VectorType *OpTy =
|
||||
dyn_cast_or_null<VectorType>(getTypeByID(Record[0]));
|
||||
if (OpTy == 0) return Error("Invalid CE_EXTRACTELT record");
|
||||
Constant *Op0 = ValueList.getConstantFwdRef(Record[1], OpTy);
|
||||
Constant *Op1 = ValueList.getConstantFwdRef(Record[2],
|
||||
OpTy->getElementType());
|
||||
V = ConstantExpr::getExtractElement(Op0, Op1);
|
||||
break;
|
||||
}
|
||||
case bitc::CST_CODE_CE_INSERTELT: { // CE_INSERTELT: [opval, opval, opval]
|
||||
const VectorType *OpTy = dyn_cast<VectorType>(CurTy);
|
||||
if (Record.size() < 3 || OpTy == 0)
|
||||
return Error("Invalid CE_INSERTELT record");
|
||||
Constant *Op0 = ValueList.getConstantFwdRef(Record[0], OpTy);
|
||||
Constant *Op1 = ValueList.getConstantFwdRef(Record[1],
|
||||
OpTy->getElementType());
|
||||
Constant *Op2 = ValueList.getConstantFwdRef(Record[2], Type::Int32Ty);
|
||||
V = ConstantExpr::getInsertElement(Op0, Op1, Op2);
|
||||
break;
|
||||
}
|
||||
case bitc::CST_CODE_CE_SHUFFLEVEC: { // CE_SHUFFLEVEC: [opval, opval, opval]
|
||||
const VectorType *OpTy = dyn_cast<VectorType>(CurTy);
|
||||
if (Record.size() < 3 || OpTy == 0)
|
||||
return Error("Invalid CE_INSERTELT record");
|
||||
Constant *Op0 = ValueList.getConstantFwdRef(Record[0], OpTy);
|
||||
Constant *Op1 = ValueList.getConstantFwdRef(Record[1], OpTy);
|
||||
const Type *ShufTy=VectorType::get(Type::Int32Ty, OpTy->getNumElements());
|
||||
Constant *Op2 = ValueList.getConstantFwdRef(Record[2], ShufTy);
|
||||
V = ConstantExpr::getShuffleVector(Op0, Op1, Op2);
|
||||
break;
|
||||
}
|
||||
case bitc::CST_CODE_CE_CMP: { // CE_CMP: [opty, opval, opval, pred]
|
||||
if (Record.size() < 4) return Error("Invalid CE_CMP record");
|
||||
const Type *OpTy = getTypeByID(Record[0]);
|
||||
if (OpTy == 0) return Error("Invalid CE_CMP record");
|
||||
Constant *Op0 = ValueList.getConstantFwdRef(Record[1], OpTy);
|
||||
Constant *Op1 = ValueList.getConstantFwdRef(Record[2], OpTy);
|
||||
|
||||
if (OpTy->isFloatingPoint())
|
||||
V = ConstantExpr::getFCmp(Record[3], Op0, Op1);
|
||||
else
|
||||
V = ConstantExpr::getICmp(Record[3], Op0, Op1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -25,6 +25,47 @@ using namespace llvm;
|
||||
|
||||
static const unsigned CurVersion = 0;
|
||||
|
||||
static unsigned GetEncodedCastOpcode(unsigned Opcode) {
|
||||
switch (Opcode) {
|
||||
default: assert(0 && "Unknown cast instruction!");
|
||||
case Instruction::Trunc : return bitc::CAST_TRUNC;
|
||||
case Instruction::ZExt : return bitc::CAST_ZEXT;
|
||||
case Instruction::SExt : return bitc::CAST_SEXT;
|
||||
case Instruction::FPToUI : return bitc::CAST_FPTOUI;
|
||||
case Instruction::FPToSI : return bitc::CAST_FPTOSI;
|
||||
case Instruction::UIToFP : return bitc::CAST_UITOFP;
|
||||
case Instruction::SIToFP : return bitc::CAST_SITOFP;
|
||||
case Instruction::FPTrunc : return bitc::CAST_FPTRUNC;
|
||||
case Instruction::FPExt : return bitc::CAST_FPEXT;
|
||||
case Instruction::PtrToInt: return bitc::CAST_PTRTOINT;
|
||||
case Instruction::IntToPtr: return bitc::CAST_INTTOPTR;
|
||||
case Instruction::BitCast : return bitc::CAST_BITCAST;
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned GetEncodedBinaryOpcode(unsigned Opcode) {
|
||||
switch (Opcode) {
|
||||
default: assert(0 && "Unknown binary instruction!");
|
||||
case Instruction::Add: return bitc::BINOP_ADD;
|
||||
case Instruction::Sub: return bitc::BINOP_SUB;
|
||||
case Instruction::Mul: return bitc::BINOP_MUL;
|
||||
case Instruction::UDiv: return bitc::BINOP_UDIV;
|
||||
case Instruction::FDiv:
|
||||
case Instruction::SDiv: return bitc::BINOP_SDIV;
|
||||
case Instruction::URem: return bitc::BINOP_UREM;
|
||||
case Instruction::FRem:
|
||||
case Instruction::SRem: return bitc::BINOP_SREM;
|
||||
case Instruction::Shl: return bitc::BINOP_SHL;
|
||||
case Instruction::LShr: return bitc::BINOP_LSHR;
|
||||
case Instruction::AShr: return bitc::BINOP_ASHR;
|
||||
case Instruction::And: return bitc::BINOP_AND;
|
||||
case Instruction::Or: return bitc::BINOP_OR;
|
||||
case Instruction::Xor: return bitc::BINOP_XOR;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void WriteStringRecord(unsigned Code, const std::string &Str,
|
||||
unsigned AbbrevToUse, BitstreamWriter &Stream) {
|
||||
SmallVector<unsigned, 64> Vals;
|
||||
@ -408,15 +449,62 @@ static void WriteConstants(unsigned FirstVal, unsigned LastVal,
|
||||
for (unsigned i = 0, e = C->getNumOperands(); i != e; ++i)
|
||||
Record.push_back(VE.getValueID(C->getOperand(i)));
|
||||
} else if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(C)) {
|
||||
Code = bitc::CST_CODE_CONSTEXPR;
|
||||
// FIXME: optimize for binops, compares, etc.
|
||||
Record.push_back(CE->getOpcode());
|
||||
Record.push_back(CE->getNumOperands());
|
||||
for (unsigned i = 0, e = CE->getNumOperands(); i != e; ++i)
|
||||
Record.push_back(VE.getValueID(C->getOperand(i)));
|
||||
// Compares also pass their predicate.
|
||||
if (CE->isCompare())
|
||||
Record.push_back((unsigned)CE->getPredicate());
|
||||
switch (CE->getOpcode()) {
|
||||
default:
|
||||
if (Instruction::isCast(CE->getOpcode())) {
|
||||
Code = bitc::CST_CODE_CE_CAST;
|
||||
Record.push_back(GetEncodedCastOpcode(CE->getOpcode()));
|
||||
Record.push_back(VE.getTypeID(C->getOperand(0)->getType()));
|
||||
Record.push_back(VE.getValueID(C->getOperand(0)));
|
||||
} else {
|
||||
assert(CE->getNumOperands() == 2 && "Unknown constant expr!");
|
||||
Code = bitc::CST_CODE_CE_BINOP;
|
||||
Record.push_back(GetEncodedBinaryOpcode(CE->getOpcode()));
|
||||
Record.push_back(VE.getValueID(C->getOperand(0)));
|
||||
Record.push_back(VE.getValueID(C->getOperand(1)));
|
||||
}
|
||||
break;
|
||||
case Instruction::GetElementPtr:
|
||||
Code = bitc::CST_CODE_CE_GEP;
|
||||
Record.push_back(CE->getNumOperands());
|
||||
for (unsigned i = 0, e = CE->getNumOperands(); i != e; ++i) {
|
||||
Record.push_back(VE.getTypeID(C->getOperand(i)->getType()));
|
||||
Record.push_back(VE.getValueID(C->getOperand(i)));
|
||||
}
|
||||
break;
|
||||
case Instruction::Select:
|
||||
Code = bitc::CST_CODE_CE_SELECT;
|
||||
Record.push_back(VE.getValueID(C->getOperand(0)));
|
||||
Record.push_back(VE.getValueID(C->getOperand(1)));
|
||||
Record.push_back(VE.getValueID(C->getOperand(2)));
|
||||
break;
|
||||
case Instruction::ExtractElement:
|
||||
Code = bitc::CST_CODE_CE_EXTRACTELT;
|
||||
Record.push_back(VE.getTypeID(C->getOperand(0)->getType()));
|
||||
Record.push_back(VE.getValueID(C->getOperand(0)));
|
||||
Record.push_back(VE.getValueID(C->getOperand(1)));
|
||||
break;
|
||||
case Instruction::InsertElement:
|
||||
Code = bitc::CST_CODE_CE_INSERTELT;
|
||||
Record.push_back(VE.getValueID(C->getOperand(0)));
|
||||
Record.push_back(VE.getValueID(C->getOperand(1)));
|
||||
Record.push_back(VE.getValueID(C->getOperand(2)));
|
||||
break;
|
||||
case Instruction::ShuffleVector:
|
||||
Code = bitc::CST_CODE_CE_SHUFFLEVEC;
|
||||
Record.push_back(VE.getValueID(C->getOperand(0)));
|
||||
Record.push_back(VE.getValueID(C->getOperand(1)));
|
||||
Record.push_back(VE.getValueID(C->getOperand(2)));
|
||||
break;
|
||||
case Instruction::ICmp:
|
||||
case Instruction::FCmp:
|
||||
Code = bitc::CST_CODE_CE_CMP;
|
||||
Record.push_back(VE.getTypeID(C->getOperand(0)->getType()));
|
||||
Record.push_back(VE.getValueID(C->getOperand(0)));
|
||||
Record.push_back(VE.getValueID(C->getOperand(1)));
|
||||
Record.push_back(CE->getPredicate());
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
assert(0 && "Unknown constant!");
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user