mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-08-09 11:25:55 +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:
@@ -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 {
|
namespace {
|
||||||
/// @brief A class for maintaining the slot number definition
|
/// @brief A class for maintaining the slot number definition
|
||||||
/// as a placeholder for the actual definition for forward constants defs.
|
/// as a placeholder for the actual definition for forward constants defs.
|
||||||
class ConstantPlaceHolder : public ConstantExpr {
|
class ConstantPlaceHolder : public ConstantExpr {
|
||||||
ConstantPlaceHolder(); // DO NOT IMPLEMENT
|
ConstantPlaceHolder(); // DO NOT IMPLEMENT
|
||||||
void operator=(const ConstantPlaceHolder &); // DO NOT IMPLEMENT
|
void operator=(const ConstantPlaceHolder &); // DO NOT IMPLEMENT
|
||||||
public:
|
public:
|
||||||
Use Op;
|
Use Op;
|
||||||
ConstantPlaceHolder(const Type *Ty)
|
ConstantPlaceHolder(const Type *Ty)
|
||||||
: ConstantExpr(Ty, Instruction::UserOp1, &Op, 1),
|
: ConstantExpr(Ty, Instruction::UserOp1, &Op, 1),
|
||||||
Op(UndefValue::get(Type::Int32Ty), this) {
|
Op(UndefValue::get(Type::Int32Ty), this) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -79,8 +118,11 @@ Constant *BitcodeReaderValueList::getConstantFwdRef(unsigned Idx,
|
|||||||
NumOperands = Idx+1;
|
NumOperands = Idx+1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Uses[Idx])
|
if (Uses[Idx]) {
|
||||||
|
assert(Ty == getOperand(Idx)->getType() &&
|
||||||
|
"Type mismatch in constant table!");
|
||||||
return cast<Constant>(getOperand(Idx));
|
return cast<Constant>(getOperand(Idx));
|
||||||
|
}
|
||||||
|
|
||||||
// Create and return a placeholder, which will later be RAUW'd.
|
// Create and return a placeholder, which will later be RAUW'd.
|
||||||
Constant *C = new ConstantPlaceHolder(Ty);
|
Constant *C = new ConstantPlaceHolder(Ty);
|
||||||
@@ -466,6 +508,91 @@ bool BitcodeReader::ParseConstants(BitstreamReader &Stream) {
|
|||||||
} else {
|
} else {
|
||||||
V = UndefValue::get(CurTy);
|
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 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,
|
static void WriteStringRecord(unsigned Code, const std::string &Str,
|
||||||
unsigned AbbrevToUse, BitstreamWriter &Stream) {
|
unsigned AbbrevToUse, BitstreamWriter &Stream) {
|
||||||
SmallVector<unsigned, 64> Vals;
|
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)
|
for (unsigned i = 0, e = C->getNumOperands(); i != e; ++i)
|
||||||
Record.push_back(VE.getValueID(C->getOperand(i)));
|
Record.push_back(VE.getValueID(C->getOperand(i)));
|
||||||
} else if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(C)) {
|
} else if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(C)) {
|
||||||
Code = bitc::CST_CODE_CONSTEXPR;
|
switch (CE->getOpcode()) {
|
||||||
// FIXME: optimize for binops, compares, etc.
|
default:
|
||||||
Record.push_back(CE->getOpcode());
|
if (Instruction::isCast(CE->getOpcode())) {
|
||||||
Record.push_back(CE->getNumOperands());
|
Code = bitc::CST_CODE_CE_CAST;
|
||||||
for (unsigned i = 0, e = CE->getNumOperands(); i != e; ++i)
|
Record.push_back(GetEncodedCastOpcode(CE->getOpcode()));
|
||||||
Record.push_back(VE.getValueID(C->getOperand(i)));
|
Record.push_back(VE.getTypeID(C->getOperand(0)->getType()));
|
||||||
// Compares also pass their predicate.
|
Record.push_back(VE.getValueID(C->getOperand(0)));
|
||||||
if (CE->isCompare())
|
} else {
|
||||||
Record.push_back((unsigned)CE->getPredicate());
|
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 {
|
} else {
|
||||||
assert(0 && "Unknown constant!");
|
assert(0 && "Unknown constant!");
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user