in llvm/lib/Bitcode/Reader/BitcodeReader.cpp [2338:2999]
Error BitcodeReader::parseConstants() {
if (Error Err = Stream.EnterSubBlock(bitc::CONSTANTS_BLOCK_ID))
return Err;
SmallVector<uint64_t, 64> Record;
// Read all the records for this value table.
Type *CurTy = Type::getInt32Ty(Context);
unsigned NextCstNo = ValueList.size();
struct DelayedShufTy {
VectorType *OpTy;
VectorType *RTy;
uint64_t Op0Idx;
uint64_t Op1Idx;
uint64_t Op2Idx;
unsigned CstNo;
};
std::vector<DelayedShufTy> DelayedShuffles;
struct DelayedSelTy {
Type *OpTy;
uint64_t Op0Idx;
uint64_t Op1Idx;
uint64_t Op2Idx;
unsigned CstNo;
};
std::vector<DelayedSelTy> DelayedSelectors;
while (true) {
Expected<BitstreamEntry> MaybeEntry = Stream.advanceSkippingSubblocks();
if (!MaybeEntry)
return MaybeEntry.takeError();
BitstreamEntry Entry = MaybeEntry.get();
switch (Entry.Kind) {
case BitstreamEntry::SubBlock: // Handled for us already.
case BitstreamEntry::Error:
return error("Malformed block");
case BitstreamEntry::EndBlock:
// Once all the constants have been read, go through and resolve forward
// references.
//
// We have to treat shuffles specially because they don't have three
// operands anymore. We need to convert the shuffle mask into an array,
// and we can't convert a forward reference.
for (auto &DelayedShuffle : DelayedShuffles) {
VectorType *OpTy = DelayedShuffle.OpTy;
VectorType *RTy = DelayedShuffle.RTy;
uint64_t Op0Idx = DelayedShuffle.Op0Idx;
uint64_t Op1Idx = DelayedShuffle.Op1Idx;
uint64_t Op2Idx = DelayedShuffle.Op2Idx;
uint64_t CstNo = DelayedShuffle.CstNo;
Constant *Op0 = ValueList.getConstantFwdRef(Op0Idx, OpTy);
Constant *Op1 = ValueList.getConstantFwdRef(Op1Idx, OpTy);
Type *ShufTy =
VectorType::get(Type::getInt32Ty(Context), RTy->getElementCount());
Constant *Op2 = ValueList.getConstantFwdRef(Op2Idx, ShufTy);
if (!ShuffleVectorInst::isValidOperands(Op0, Op1, Op2))
return error("Invalid shufflevector operands");
SmallVector<int, 16> Mask;
ShuffleVectorInst::getShuffleMask(Op2, Mask);
Value *V = ConstantExpr::getShuffleVector(Op0, Op1, Mask);
ValueList.assignValue(V, CstNo);
}
for (auto &DelayedSelector : DelayedSelectors) {
Type *OpTy = DelayedSelector.OpTy;
Type *SelectorTy = Type::getInt1Ty(Context);
uint64_t Op0Idx = DelayedSelector.Op0Idx;
uint64_t Op1Idx = DelayedSelector.Op1Idx;
uint64_t Op2Idx = DelayedSelector.Op2Idx;
uint64_t CstNo = DelayedSelector.CstNo;
Constant *Op1 = ValueList.getConstantFwdRef(Op1Idx, OpTy);
Constant *Op2 = ValueList.getConstantFwdRef(Op2Idx, OpTy);
// The selector might be an i1 or an <n x i1>
// Get the type from the ValueList before getting a forward ref.
if (VectorType *VTy = dyn_cast<VectorType>(OpTy)) {
Value *V = ValueList[Op0Idx];
assert(V);
if (SelectorTy != V->getType())
SelectorTy = VectorType::get(SelectorTy, VTy->getElementCount());
}
Constant *Op0 = ValueList.getConstantFwdRef(Op0Idx, SelectorTy);
Value *V = ConstantExpr::getSelect(Op0, Op1, Op2);
ValueList.assignValue(V, CstNo);
}
if (NextCstNo != ValueList.size())
return error("Invalid constant reference");
ValueList.resolveConstantForwardRefs();
return Error::success();
case BitstreamEntry::Record:
// The interesting case.
break;
}
// Read a record.
Record.clear();
Type *VoidType = Type::getVoidTy(Context);
Value *V = nullptr;
Expected<unsigned> MaybeBitCode = Stream.readRecord(Entry.ID, Record);
if (!MaybeBitCode)
return MaybeBitCode.takeError();
switch (unsigned BitCode = MaybeBitCode.get()) {
default: // Default behavior: unknown constant
case bitc::CST_CODE_UNDEF: // UNDEF
V = UndefValue::get(CurTy);
break;
case bitc::CST_CODE_POISON: // POISON
V = PoisonValue::get(CurTy);
break;
case bitc::CST_CODE_SETTYPE: // SETTYPE: [typeid]
if (Record.empty())
return error("Invalid record");
if (Record[0] >= TypeList.size() || !TypeList[Record[0]])
return error("Invalid record");
if (TypeList[Record[0]] == VoidType)
return error("Invalid constant type");
CurTy = TypeList[Record[0]];
continue; // Skip the ValueList manipulation.
case bitc::CST_CODE_NULL: // NULL
if (CurTy->isVoidTy() || CurTy->isFunctionTy() || CurTy->isLabelTy())
return error("Invalid type for a constant null value");
V = Constant::getNullValue(CurTy);
break;
case bitc::CST_CODE_INTEGER: // INTEGER: [intval]
if (!CurTy->isIntegerTy() || Record.empty())
return error("Invalid record");
V = ConstantInt::get(CurTy, decodeSignRotatedValue(Record[0]));
break;
case bitc::CST_CODE_WIDE_INTEGER: {// WIDE_INTEGER: [n x intval]
if (!CurTy->isIntegerTy() || Record.empty())
return error("Invalid record");
APInt VInt =
readWideAPInt(Record, cast<IntegerType>(CurTy)->getBitWidth());
V = ConstantInt::get(Context, VInt);
break;
}
case bitc::CST_CODE_FLOAT: { // FLOAT: [fpval]
if (Record.empty())
return error("Invalid record");
if (CurTy->isHalfTy())
V = ConstantFP::get(Context, APFloat(APFloat::IEEEhalf(),
APInt(16, (uint16_t)Record[0])));
else if (CurTy->isBFloatTy())
V = ConstantFP::get(Context, APFloat(APFloat::BFloat(),
APInt(16, (uint32_t)Record[0])));
else if (CurTy->isFloatTy())
V = ConstantFP::get(Context, APFloat(APFloat::IEEEsingle(),
APInt(32, (uint32_t)Record[0])));
else if (CurTy->isDoubleTy())
V = ConstantFP::get(Context, APFloat(APFloat::IEEEdouble(),
APInt(64, Record[0])));
else if (CurTy->isX86_FP80Ty()) {
// Bits are not stored the same way as a normal i80 APInt, compensate.
uint64_t Rearrange[2];
Rearrange[0] = (Record[1] & 0xffffLL) | (Record[0] << 16);
Rearrange[1] = Record[0] >> 48;
V = ConstantFP::get(Context, APFloat(APFloat::x87DoubleExtended(),
APInt(80, Rearrange)));
} else if (CurTy->isFP128Ty())
V = ConstantFP::get(Context, APFloat(APFloat::IEEEquad(),
APInt(128, Record)));
else if (CurTy->isPPC_FP128Ty())
V = ConstantFP::get(Context, APFloat(APFloat::PPCDoubleDouble(),
APInt(128, Record)));
else
V = UndefValue::get(CurTy);
break;
}
case bitc::CST_CODE_AGGREGATE: {// AGGREGATE: [n x value number]
if (Record.empty())
return error("Invalid record");
unsigned Size = Record.size();
SmallVector<Constant*, 16> Elts;
if (StructType *STy = dyn_cast<StructType>(CurTy)) {
for (unsigned i = 0; i != Size; ++i)
Elts.push_back(ValueList.getConstantFwdRef(Record[i],
STy->getElementType(i)));
V = ConstantStruct::get(STy, Elts);
} else if (ArrayType *ATy = dyn_cast<ArrayType>(CurTy)) {
Type *EltTy = ATy->getElementType();
for (unsigned i = 0; i != Size; ++i)
Elts.push_back(ValueList.getConstantFwdRef(Record[i], EltTy));
V = ConstantArray::get(ATy, Elts);
} else if (VectorType *VTy = dyn_cast<VectorType>(CurTy)) {
Type *EltTy = VTy->getElementType();
for (unsigned i = 0; i != Size; ++i)
Elts.push_back(ValueList.getConstantFwdRef(Record[i], EltTy));
V = ConstantVector::get(Elts);
} else {
V = UndefValue::get(CurTy);
}
break;
}
case bitc::CST_CODE_STRING: // STRING: [values]
case bitc::CST_CODE_CSTRING: { // CSTRING: [values]
if (Record.empty())
return error("Invalid record");
SmallString<16> Elts(Record.begin(), Record.end());
V = ConstantDataArray::getString(Context, Elts,
BitCode == bitc::CST_CODE_CSTRING);
break;
}
case bitc::CST_CODE_DATA: {// DATA: [n x value]
if (Record.empty())
return error("Invalid record");
Type *EltTy;
if (auto *Array = dyn_cast<ArrayType>(CurTy))
EltTy = Array->getElementType();
else
EltTy = cast<VectorType>(CurTy)->getElementType();
if (EltTy->isIntegerTy(8)) {
SmallVector<uint8_t, 16> Elts(Record.begin(), Record.end());
if (isa<VectorType>(CurTy))
V = ConstantDataVector::get(Context, Elts);
else
V = ConstantDataArray::get(Context, Elts);
} else if (EltTy->isIntegerTy(16)) {
SmallVector<uint16_t, 16> Elts(Record.begin(), Record.end());
if (isa<VectorType>(CurTy))
V = ConstantDataVector::get(Context, Elts);
else
V = ConstantDataArray::get(Context, Elts);
} else if (EltTy->isIntegerTy(32)) {
SmallVector<uint32_t, 16> Elts(Record.begin(), Record.end());
if (isa<VectorType>(CurTy))
V = ConstantDataVector::get(Context, Elts);
else
V = ConstantDataArray::get(Context, Elts);
} else if (EltTy->isIntegerTy(64)) {
SmallVector<uint64_t, 16> Elts(Record.begin(), Record.end());
if (isa<VectorType>(CurTy))
V = ConstantDataVector::get(Context, Elts);
else
V = ConstantDataArray::get(Context, Elts);
} else if (EltTy->isHalfTy()) {
SmallVector<uint16_t, 16> Elts(Record.begin(), Record.end());
if (isa<VectorType>(CurTy))
V = ConstantDataVector::getFP(EltTy, Elts);
else
V = ConstantDataArray::getFP(EltTy, Elts);
} else if (EltTy->isBFloatTy()) {
SmallVector<uint16_t, 16> Elts(Record.begin(), Record.end());
if (isa<VectorType>(CurTy))
V = ConstantDataVector::getFP(EltTy, Elts);
else
V = ConstantDataArray::getFP(EltTy, Elts);
} else if (EltTy->isFloatTy()) {
SmallVector<uint32_t, 16> Elts(Record.begin(), Record.end());
if (isa<VectorType>(CurTy))
V = ConstantDataVector::getFP(EltTy, Elts);
else
V = ConstantDataArray::getFP(EltTy, Elts);
} else if (EltTy->isDoubleTy()) {
SmallVector<uint64_t, 16> Elts(Record.begin(), Record.end());
if (isa<VectorType>(CurTy))
V = ConstantDataVector::getFP(EltTy, Elts);
else
V = ConstantDataArray::getFP(EltTy, Elts);
} else {
return error("Invalid type for value");
}
break;
}
case bitc::CST_CODE_CE_UNOP: { // CE_UNOP: [opcode, opval]
if (Record.size() < 2)
return error("Invalid record");
int Opc = getDecodedUnaryOpcode(Record[0], CurTy);
if (Opc < 0) {
V = UndefValue::get(CurTy); // Unknown unop.
} else {
Constant *LHS = ValueList.getConstantFwdRef(Record[1], CurTy);
unsigned Flags = 0;
V = ConstantExpr::get(Opc, LHS, Flags);
}
break;
}
case bitc::CST_CODE_CE_BINOP: { // CE_BINOP: [opcode, opval, opval]
if (Record.size() < 3)
return error("Invalid record");
int Opc = getDecodedBinaryOpcode(Record[0], CurTy);
if (Opc < 0) {
V = UndefValue::get(CurTy); // Unknown binop.
} else {
Constant *LHS = ValueList.getConstantFwdRef(Record[1], CurTy);
Constant *RHS = ValueList.getConstantFwdRef(Record[2], CurTy);
unsigned Flags = 0;
if (Record.size() >= 4) {
if (Opc == Instruction::Add ||
Opc == Instruction::Sub ||
Opc == Instruction::Mul ||
Opc == Instruction::Shl) {
if (Record[3] & (1 << bitc::OBO_NO_SIGNED_WRAP))
Flags |= OverflowingBinaryOperator::NoSignedWrap;
if (Record[3] & (1 << bitc::OBO_NO_UNSIGNED_WRAP))
Flags |= OverflowingBinaryOperator::NoUnsignedWrap;
} else if (Opc == Instruction::SDiv ||
Opc == Instruction::UDiv ||
Opc == Instruction::LShr ||
Opc == Instruction::AShr) {
if (Record[3] & (1 << bitc::PEO_EXACT))
Flags |= SDivOperator::IsExact;
}
}
V = ConstantExpr::get(Opc, LHS, RHS, Flags);
}
break;
}
case bitc::CST_CODE_CE_CAST: { // CE_CAST: [opcode, opty, opval]
if (Record.size() < 3)
return error("Invalid record");
int Opc = getDecodedCastOpcode(Record[0]);
if (Opc < 0) {
V = UndefValue::get(CurTy); // Unknown cast.
} else {
Type *OpTy = getTypeByID(Record[1]);
if (!OpTy)
return error("Invalid record");
Constant *Op = ValueList.getConstantFwdRef(Record[2], OpTy);
V = UpgradeBitCastExpr(Opc, Op, CurTy);
if (!V) V = ConstantExpr::getCast(Opc, Op, CurTy);
}
break;
}
case bitc::CST_CODE_CE_INBOUNDS_GEP: // [ty, n x operands]
case bitc::CST_CODE_CE_GEP: // [ty, n x operands]
case bitc::CST_CODE_CE_GEP_WITH_INRANGE_INDEX: { // [ty, flags, n x
// operands]
unsigned OpNum = 0;
Type *PointeeType = nullptr;
if (BitCode == bitc::CST_CODE_CE_GEP_WITH_INRANGE_INDEX ||
Record.size() % 2)
PointeeType = getTypeByID(Record[OpNum++]);
bool InBounds = false;
Optional<unsigned> InRangeIndex;
if (BitCode == bitc::CST_CODE_CE_GEP_WITH_INRANGE_INDEX) {
uint64_t Op = Record[OpNum++];
InBounds = Op & 1;
InRangeIndex = Op >> 1;
} else if (BitCode == bitc::CST_CODE_CE_INBOUNDS_GEP)
InBounds = true;
SmallVector<Constant*, 16> Elts;
Type *Elt0FullTy = nullptr;
while (OpNum != Record.size()) {
if (!Elt0FullTy)
Elt0FullTy = getTypeByID(Record[OpNum]);
Type *ElTy = getTypeByID(Record[OpNum++]);
if (!ElTy)
return error("Invalid record");
Elts.push_back(ValueList.getConstantFwdRef(Record[OpNum++], ElTy));
}
if (Elts.size() < 1)
return error("Invalid gep with no operands");
PointerType *OrigPtrTy = cast<PointerType>(Elt0FullTy->getScalarType());
if (!PointeeType)
PointeeType = OrigPtrTy->getElementType();
else if (!OrigPtrTy->isOpaqueOrPointeeTypeMatches(PointeeType))
return error("Explicit gep operator type does not match pointee type "
"of pointer operand");
ArrayRef<Constant *> Indices(Elts.begin() + 1, Elts.end());
V = ConstantExpr::getGetElementPtr(PointeeType, Elts[0], Indices,
InBounds, InRangeIndex);
break;
}
case bitc::CST_CODE_CE_SELECT: { // CE_SELECT: [opval#, opval#, opval#]
if (Record.size() < 3)
return error("Invalid record");
DelayedSelectors.push_back(
{CurTy, Record[0], Record[1], Record[2], NextCstNo});
(void)ValueList.getConstantFwdRef(NextCstNo, CurTy);
++NextCstNo;
continue;
}
case bitc::CST_CODE_CE_EXTRACTELT
: { // CE_EXTRACTELT: [opty, opval, opty, opval]
if (Record.size() < 3)
return error("Invalid record");
VectorType *OpTy =
dyn_cast_or_null<VectorType>(getTypeByID(Record[0]));
if (!OpTy)
return error("Invalid record");
Constant *Op0 = ValueList.getConstantFwdRef(Record[1], OpTy);
Constant *Op1 = nullptr;
if (Record.size() == 4) {
Type *IdxTy = getTypeByID(Record[2]);
if (!IdxTy)
return error("Invalid record");
Op1 = ValueList.getConstantFwdRef(Record[3], IdxTy);
} else {
// Deprecated, but still needed to read old bitcode files.
Op1 = ValueList.getConstantFwdRef(Record[2], Type::getInt32Ty(Context));
}
if (!Op1)
return error("Invalid record");
V = ConstantExpr::getExtractElement(Op0, Op1);
break;
}
case bitc::CST_CODE_CE_INSERTELT
: { // CE_INSERTELT: [opval, opval, opty, opval]
VectorType *OpTy = dyn_cast<VectorType>(CurTy);
if (Record.size() < 3 || !OpTy)
return error("Invalid record");
Constant *Op0 = ValueList.getConstantFwdRef(Record[0], OpTy);
Constant *Op1 = ValueList.getConstantFwdRef(Record[1],
OpTy->getElementType());
Constant *Op2 = nullptr;
if (Record.size() == 4) {
Type *IdxTy = getTypeByID(Record[2]);
if (!IdxTy)
return error("Invalid record");
Op2 = ValueList.getConstantFwdRef(Record[3], IdxTy);
} else {
// Deprecated, but still needed to read old bitcode files.
Op2 = ValueList.getConstantFwdRef(Record[2], Type::getInt32Ty(Context));
}
if (!Op2)
return error("Invalid record");
V = ConstantExpr::getInsertElement(Op0, Op1, Op2);
break;
}
case bitc::CST_CODE_CE_SHUFFLEVEC: { // CE_SHUFFLEVEC: [opval, opval, opval]
VectorType *OpTy = dyn_cast<VectorType>(CurTy);
if (Record.size() < 3 || !OpTy)
return error("Invalid record");
DelayedShuffles.push_back(
{OpTy, OpTy, Record[0], Record[1], Record[2], NextCstNo});
++NextCstNo;
continue;
}
case bitc::CST_CODE_CE_SHUFVEC_EX: { // [opty, opval, opval, opval]
VectorType *RTy = dyn_cast<VectorType>(CurTy);
VectorType *OpTy =
dyn_cast_or_null<VectorType>(getTypeByID(Record[0]));
if (Record.size() < 4 || !RTy || !OpTy)
return error("Invalid record");
DelayedShuffles.push_back(
{OpTy, RTy, Record[1], Record[2], Record[3], NextCstNo});
++NextCstNo;
continue;
}
case bitc::CST_CODE_CE_CMP: { // CE_CMP: [opty, opval, opval, pred]
if (Record.size() < 4)
return error("Invalid record");
Type *OpTy = getTypeByID(Record[0]);
if (!OpTy)
return error("Invalid record");
Constant *Op0 = ValueList.getConstantFwdRef(Record[1], OpTy);
Constant *Op1 = ValueList.getConstantFwdRef(Record[2], OpTy);
if (OpTy->isFPOrFPVectorTy())
V = ConstantExpr::getFCmp(Record[3], Op0, Op1);
else
V = ConstantExpr::getICmp(Record[3], Op0, Op1);
break;
}
// This maintains backward compatibility, pre-asm dialect keywords.
// Deprecated, but still needed to read old bitcode files.
case bitc::CST_CODE_INLINEASM_OLD: {
if (Record.size() < 2)
return error("Invalid record");
std::string AsmStr, ConstrStr;
bool HasSideEffects = Record[0] & 1;
bool IsAlignStack = Record[0] >> 1;
unsigned AsmStrSize = Record[1];
if (2+AsmStrSize >= Record.size())
return error("Invalid record");
unsigned ConstStrSize = Record[2+AsmStrSize];
if (3+AsmStrSize+ConstStrSize > Record.size())
return error("Invalid record");
for (unsigned i = 0; i != AsmStrSize; ++i)
AsmStr += (char)Record[2+i];
for (unsigned i = 0; i != ConstStrSize; ++i)
ConstrStr += (char)Record[3+AsmStrSize+i];
UpgradeInlineAsmString(&AsmStr);
// FIXME: support upgrading in opaque pointers mode.
V = InlineAsm::get(
cast<FunctionType>(cast<PointerType>(CurTy)->getElementType()),
AsmStr, ConstrStr, HasSideEffects, IsAlignStack);
break;
}
// This version adds support for the asm dialect keywords (e.g.,
// inteldialect).
case bitc::CST_CODE_INLINEASM_OLD2: {
if (Record.size() < 2)
return error("Invalid record");
std::string AsmStr, ConstrStr;
bool HasSideEffects = Record[0] & 1;
bool IsAlignStack = (Record[0] >> 1) & 1;
unsigned AsmDialect = Record[0] >> 2;
unsigned AsmStrSize = Record[1];
if (2+AsmStrSize >= Record.size())
return error("Invalid record");
unsigned ConstStrSize = Record[2+AsmStrSize];
if (3+AsmStrSize+ConstStrSize > Record.size())
return error("Invalid record");
for (unsigned i = 0; i != AsmStrSize; ++i)
AsmStr += (char)Record[2+i];
for (unsigned i = 0; i != ConstStrSize; ++i)
ConstrStr += (char)Record[3+AsmStrSize+i];
UpgradeInlineAsmString(&AsmStr);
// FIXME: support upgrading in opaque pointers mode.
V = InlineAsm::get(
cast<FunctionType>(cast<PointerType>(CurTy)->getElementType()),
AsmStr, ConstrStr, HasSideEffects, IsAlignStack,
InlineAsm::AsmDialect(AsmDialect));
break;
}
// This version adds support for the unwind keyword.
case bitc::CST_CODE_INLINEASM_OLD3: {
if (Record.size() < 2)
return error("Invalid record");
unsigned OpNum = 0;
std::string AsmStr, ConstrStr;
bool HasSideEffects = Record[OpNum] & 1;
bool IsAlignStack = (Record[OpNum] >> 1) & 1;
unsigned AsmDialect = (Record[OpNum] >> 2) & 1;
bool CanThrow = (Record[OpNum] >> 3) & 1;
++OpNum;
unsigned AsmStrSize = Record[OpNum];
++OpNum;
if (OpNum + AsmStrSize >= Record.size())
return error("Invalid record");
unsigned ConstStrSize = Record[OpNum + AsmStrSize];
if (OpNum + 1 + AsmStrSize + ConstStrSize > Record.size())
return error("Invalid record");
for (unsigned i = 0; i != AsmStrSize; ++i)
AsmStr += (char)Record[OpNum + i];
++OpNum;
for (unsigned i = 0; i != ConstStrSize; ++i)
ConstrStr += (char)Record[OpNum + AsmStrSize + i];
UpgradeInlineAsmString(&AsmStr);
// FIXME: support upgrading in opaque pointers mode.
V = InlineAsm::get(
cast<FunctionType>(cast<PointerType>(CurTy)->getElementType()),
AsmStr, ConstrStr, HasSideEffects, IsAlignStack,
InlineAsm::AsmDialect(AsmDialect), CanThrow);
break;
}
// This version adds explicit function type.
case bitc::CST_CODE_INLINEASM: {
if (Record.size() < 3)
return error("Invalid record");
unsigned OpNum = 0;
auto *FnTy = dyn_cast_or_null<FunctionType>(getTypeByID(Record[OpNum]));
++OpNum;
if (!FnTy)
return error("Invalid record");
std::string AsmStr, ConstrStr;
bool HasSideEffects = Record[OpNum] & 1;
bool IsAlignStack = (Record[OpNum] >> 1) & 1;
unsigned AsmDialect = (Record[OpNum] >> 2) & 1;
bool CanThrow = (Record[OpNum] >> 3) & 1;
++OpNum;
unsigned AsmStrSize = Record[OpNum];
++OpNum;
if (OpNum + AsmStrSize >= Record.size())
return error("Invalid record");
unsigned ConstStrSize = Record[OpNum + AsmStrSize];
if (OpNum + 1 + AsmStrSize + ConstStrSize > Record.size())
return error("Invalid record");
for (unsigned i = 0; i != AsmStrSize; ++i)
AsmStr += (char)Record[OpNum + i];
++OpNum;
for (unsigned i = 0; i != ConstStrSize; ++i)
ConstrStr += (char)Record[OpNum + AsmStrSize + i];
UpgradeInlineAsmString(&AsmStr);
V = InlineAsm::get(FnTy, AsmStr, ConstrStr, HasSideEffects, IsAlignStack,
InlineAsm::AsmDialect(AsmDialect), CanThrow);
break;
}
case bitc::CST_CODE_BLOCKADDRESS:{
if (Record.size() < 3)
return error("Invalid record");
Type *FnTy = getTypeByID(Record[0]);
if (!FnTy)
return error("Invalid record");
Function *Fn =
dyn_cast_or_null<Function>(ValueList.getConstantFwdRef(Record[1],FnTy));
if (!Fn)
return error("Invalid record");
// If the function is already parsed we can insert the block address right
// away.
BasicBlock *BB;
unsigned BBID = Record[2];
if (!BBID)
// Invalid reference to entry block.
return error("Invalid ID");
if (!Fn->empty()) {
Function::iterator BBI = Fn->begin(), BBE = Fn->end();
for (size_t I = 0, E = BBID; I != E; ++I) {
if (BBI == BBE)
return error("Invalid ID");
++BBI;
}
BB = &*BBI;
} else {
// Otherwise insert a placeholder and remember it so it can be inserted
// when the function is parsed.
auto &FwdBBs = BasicBlockFwdRefs[Fn];
if (FwdBBs.empty())
BasicBlockFwdRefQueue.push_back(Fn);
if (FwdBBs.size() < BBID + 1)
FwdBBs.resize(BBID + 1);
if (!FwdBBs[BBID])
FwdBBs[BBID] = BasicBlock::Create(Context);
BB = FwdBBs[BBID];
}
V = BlockAddress::get(Fn, BB);
break;
}
case bitc::CST_CODE_DSO_LOCAL_EQUIVALENT: {
if (Record.size() < 2)
return error("Invalid record");
Type *GVTy = getTypeByID(Record[0]);
if (!GVTy)
return error("Invalid record");
GlobalValue *GV = dyn_cast_or_null<GlobalValue>(
ValueList.getConstantFwdRef(Record[1], GVTy));
if (!GV)
return error("Invalid record");
V = DSOLocalEquivalent::get(GV);
break;
}
case bitc::CST_CODE_NO_CFI_VALUE: {
if (Record.size() < 2)
return error("Invalid record");
Type *GVTy = getTypeByID(Record[0]);
if (!GVTy)
return error("Invalid record");
GlobalValue *GV = dyn_cast_or_null<GlobalValue>(
ValueList.getConstantFwdRef(Record[1], GVTy));
if (!GV)
return error("Invalid record");
V = NoCFIValue::get(GV);
break;
}
}
ValueList.assignValue(V, NextCstNo);
++NextCstNo;
}
}