in llvm/lib/Bitcode/Reader/BitcodeReader.cpp [3958:5550]
Error BitcodeReader::parseFunctionBody(Function *F) {
if (Error Err = Stream.EnterSubBlock(bitc::FUNCTION_BLOCK_ID))
return Err;
// Unexpected unresolved metadata when parsing function.
if (MDLoader->hasFwdRefs())
return error("Invalid function metadata: incoming forward references");
InstructionList.clear();
unsigned ModuleValueListSize = ValueList.size();
unsigned ModuleMDLoaderSize = MDLoader->size();
// Add all the function arguments to the value table.
#ifndef NDEBUG
unsigned ArgNo = 0;
FunctionType *FTy = FunctionTypes[F];
#endif
for (Argument &I : F->args()) {
assert(I.getType() == FTy->getParamType(ArgNo++) &&
"Incorrect fully specified type for Function Argument");
ValueList.push_back(&I);
}
unsigned NextValueNo = ValueList.size();
BasicBlock *CurBB = nullptr;
unsigned CurBBNo = 0;
DebugLoc LastLoc;
auto getLastInstruction = [&]() -> Instruction * {
if (CurBB && !CurBB->empty())
return &CurBB->back();
else if (CurBBNo && FunctionBBs[CurBBNo - 1] &&
!FunctionBBs[CurBBNo - 1]->empty())
return &FunctionBBs[CurBBNo - 1]->back();
return nullptr;
};
std::vector<OperandBundleDef> OperandBundles;
// Read all the records.
SmallVector<uint64_t, 64> Record;
while (true) {
Expected<llvm::BitstreamEntry> MaybeEntry = Stream.advance();
if (!MaybeEntry)
return MaybeEntry.takeError();
llvm::BitstreamEntry Entry = MaybeEntry.get();
switch (Entry.Kind) {
case BitstreamEntry::Error:
return error("Malformed block");
case BitstreamEntry::EndBlock:
goto OutOfRecordLoop;
case BitstreamEntry::SubBlock:
switch (Entry.ID) {
default: // Skip unknown content.
if (Error Err = Stream.SkipBlock())
return Err;
break;
case bitc::CONSTANTS_BLOCK_ID:
if (Error Err = parseConstants())
return Err;
NextValueNo = ValueList.size();
break;
case bitc::VALUE_SYMTAB_BLOCK_ID:
if (Error Err = parseValueSymbolTable())
return Err;
break;
case bitc::METADATA_ATTACHMENT_ID:
if (Error Err = MDLoader->parseMetadataAttachment(*F, InstructionList))
return Err;
break;
case bitc::METADATA_BLOCK_ID:
assert(DeferredMetadataInfo.empty() &&
"Must read all module-level metadata before function-level");
if (Error Err = MDLoader->parseFunctionMetadata())
return Err;
break;
case bitc::USELIST_BLOCK_ID:
if (Error Err = parseUseLists())
return Err;
break;
}
continue;
case BitstreamEntry::Record:
// The interesting case.
break;
}
// Read a record.
Record.clear();
Instruction *I = nullptr;
Expected<unsigned> MaybeBitCode = Stream.readRecord(Entry.ID, Record);
if (!MaybeBitCode)
return MaybeBitCode.takeError();
switch (unsigned BitCode = MaybeBitCode.get()) {
default: // Default behavior: reject
return error("Invalid value");
case bitc::FUNC_CODE_DECLAREBLOCKS: { // DECLAREBLOCKS: [nblocks]
if (Record.empty() || Record[0] == 0)
return error("Invalid record");
// Create all the basic blocks for the function.
FunctionBBs.resize(Record[0]);
// See if anything took the address of blocks in this function.
auto BBFRI = BasicBlockFwdRefs.find(F);
if (BBFRI == BasicBlockFwdRefs.end()) {
for (BasicBlock *&BB : FunctionBBs)
BB = BasicBlock::Create(Context, "", F);
} else {
auto &BBRefs = BBFRI->second;
// Check for invalid basic block references.
if (BBRefs.size() > FunctionBBs.size())
return error("Invalid ID");
assert(!BBRefs.empty() && "Unexpected empty array");
assert(!BBRefs.front() && "Invalid reference to entry block");
for (unsigned I = 0, E = FunctionBBs.size(), RE = BBRefs.size(); I != E;
++I)
if (I < RE && BBRefs[I]) {
BBRefs[I]->insertInto(F);
FunctionBBs[I] = BBRefs[I];
} else {
FunctionBBs[I] = BasicBlock::Create(Context, "", F);
}
// Erase from the table.
BasicBlockFwdRefs.erase(BBFRI);
}
CurBB = FunctionBBs[0];
continue;
}
case bitc::FUNC_CODE_DEBUG_LOC_AGAIN: // DEBUG_LOC_AGAIN
// This record indicates that the last instruction is at the same
// location as the previous instruction with a location.
I = getLastInstruction();
if (!I)
return error("Invalid record");
I->setDebugLoc(LastLoc);
I = nullptr;
continue;
case bitc::FUNC_CODE_DEBUG_LOC: { // DEBUG_LOC: [line, col, scope, ia]
I = getLastInstruction();
if (!I || Record.size() < 4)
return error("Invalid record");
unsigned Line = Record[0], Col = Record[1];
unsigned ScopeID = Record[2], IAID = Record[3];
bool isImplicitCode = Record.size() == 5 && Record[4];
MDNode *Scope = nullptr, *IA = nullptr;
if (ScopeID) {
Scope = dyn_cast_or_null<MDNode>(
MDLoader->getMetadataFwdRefOrLoad(ScopeID - 1));
if (!Scope)
return error("Invalid record");
}
if (IAID) {
IA = dyn_cast_or_null<MDNode>(
MDLoader->getMetadataFwdRefOrLoad(IAID - 1));
if (!IA)
return error("Invalid record");
}
LastLoc = DILocation::get(Scope->getContext(), Line, Col, Scope, IA,
isImplicitCode);
I->setDebugLoc(LastLoc);
I = nullptr;
continue;
}
case bitc::FUNC_CODE_INST_UNOP: { // UNOP: [opval, ty, opcode]
unsigned OpNum = 0;
Value *LHS;
if (getValueTypePair(Record, OpNum, NextValueNo, LHS) ||
OpNum+1 > Record.size())
return error("Invalid record");
int Opc = getDecodedUnaryOpcode(Record[OpNum++], LHS->getType());
if (Opc == -1)
return error("Invalid record");
I = UnaryOperator::Create((Instruction::UnaryOps)Opc, LHS);
InstructionList.push_back(I);
if (OpNum < Record.size()) {
if (isa<FPMathOperator>(I)) {
FastMathFlags FMF = getDecodedFastMathFlags(Record[OpNum]);
if (FMF.any())
I->setFastMathFlags(FMF);
}
}
break;
}
case bitc::FUNC_CODE_INST_BINOP: { // BINOP: [opval, ty, opval, opcode]
unsigned OpNum = 0;
Value *LHS, *RHS;
if (getValueTypePair(Record, OpNum, NextValueNo, LHS) ||
popValue(Record, OpNum, NextValueNo, LHS->getType(), RHS) ||
OpNum+1 > Record.size())
return error("Invalid record");
int Opc = getDecodedBinaryOpcode(Record[OpNum++], LHS->getType());
if (Opc == -1)
return error("Invalid record");
I = BinaryOperator::Create((Instruction::BinaryOps)Opc, LHS, RHS);
InstructionList.push_back(I);
if (OpNum < Record.size()) {
if (Opc == Instruction::Add ||
Opc == Instruction::Sub ||
Opc == Instruction::Mul ||
Opc == Instruction::Shl) {
if (Record[OpNum] & (1 << bitc::OBO_NO_SIGNED_WRAP))
cast<BinaryOperator>(I)->setHasNoSignedWrap(true);
if (Record[OpNum] & (1 << bitc::OBO_NO_UNSIGNED_WRAP))
cast<BinaryOperator>(I)->setHasNoUnsignedWrap(true);
} else if (Opc == Instruction::SDiv ||
Opc == Instruction::UDiv ||
Opc == Instruction::LShr ||
Opc == Instruction::AShr) {
if (Record[OpNum] & (1 << bitc::PEO_EXACT))
cast<BinaryOperator>(I)->setIsExact(true);
} else if (isa<FPMathOperator>(I)) {
FastMathFlags FMF = getDecodedFastMathFlags(Record[OpNum]);
if (FMF.any())
I->setFastMathFlags(FMF);
}
}
break;
}
case bitc::FUNC_CODE_INST_CAST: { // CAST: [opval, opty, destty, castopc]
unsigned OpNum = 0;
Value *Op;
if (getValueTypePair(Record, OpNum, NextValueNo, Op) ||
OpNum+2 != Record.size())
return error("Invalid record");
Type *ResTy = getTypeByID(Record[OpNum]);
int Opc = getDecodedCastOpcode(Record[OpNum + 1]);
if (Opc == -1 || !ResTy)
return error("Invalid record");
Instruction *Temp = nullptr;
if ((I = UpgradeBitCastInst(Opc, Op, ResTy, Temp))) {
if (Temp) {
InstructionList.push_back(Temp);
assert(CurBB && "No current BB?");
CurBB->getInstList().push_back(Temp);
}
} else {
auto CastOp = (Instruction::CastOps)Opc;
if (!CastInst::castIsValid(CastOp, Op, ResTy))
return error("Invalid cast");
I = CastInst::Create(CastOp, Op, ResTy);
}
InstructionList.push_back(I);
break;
}
case bitc::FUNC_CODE_INST_INBOUNDS_GEP_OLD:
case bitc::FUNC_CODE_INST_GEP_OLD:
case bitc::FUNC_CODE_INST_GEP: { // GEP: type, [n x operands]
unsigned OpNum = 0;
Type *Ty;
bool InBounds;
if (BitCode == bitc::FUNC_CODE_INST_GEP) {
InBounds = Record[OpNum++];
Ty = getTypeByID(Record[OpNum++]);
} else {
InBounds = BitCode == bitc::FUNC_CODE_INST_INBOUNDS_GEP_OLD;
Ty = nullptr;
}
Value *BasePtr;
if (getValueTypePair(Record, OpNum, NextValueNo, BasePtr))
return error("Invalid record");
if (!Ty) {
Ty = cast<PointerType>(BasePtr->getType()->getScalarType())
->getElementType();
} else if (!cast<PointerType>(BasePtr->getType()->getScalarType())
->isOpaqueOrPointeeTypeMatches(Ty)) {
return error(
"Explicit gep type does not match pointee type of pointer operand");
}
SmallVector<Value*, 16> GEPIdx;
while (OpNum != Record.size()) {
Value *Op;
if (getValueTypePair(Record, OpNum, NextValueNo, Op))
return error("Invalid record");
GEPIdx.push_back(Op);
}
I = GetElementPtrInst::Create(Ty, BasePtr, GEPIdx);
InstructionList.push_back(I);
if (InBounds)
cast<GetElementPtrInst>(I)->setIsInBounds(true);
break;
}
case bitc::FUNC_CODE_INST_EXTRACTVAL: {
// EXTRACTVAL: [opty, opval, n x indices]
unsigned OpNum = 0;
Value *Agg;
if (getValueTypePair(Record, OpNum, NextValueNo, Agg))
return error("Invalid record");
Type *Ty = Agg->getType();
unsigned RecSize = Record.size();
if (OpNum == RecSize)
return error("EXTRACTVAL: Invalid instruction with 0 indices");
SmallVector<unsigned, 4> EXTRACTVALIdx;
for (; OpNum != RecSize; ++OpNum) {
bool IsArray = Ty->isArrayTy();
bool IsStruct = Ty->isStructTy();
uint64_t Index = Record[OpNum];
if (!IsStruct && !IsArray)
return error("EXTRACTVAL: Invalid type");
if ((unsigned)Index != Index)
return error("Invalid value");
if (IsStruct && Index >= Ty->getStructNumElements())
return error("EXTRACTVAL: Invalid struct index");
if (IsArray && Index >= Ty->getArrayNumElements())
return error("EXTRACTVAL: Invalid array index");
EXTRACTVALIdx.push_back((unsigned)Index);
if (IsStruct)
Ty = Ty->getStructElementType(Index);
else
Ty = Ty->getArrayElementType();
}
I = ExtractValueInst::Create(Agg, EXTRACTVALIdx);
InstructionList.push_back(I);
break;
}
case bitc::FUNC_CODE_INST_INSERTVAL: {
// INSERTVAL: [opty, opval, opty, opval, n x indices]
unsigned OpNum = 0;
Value *Agg;
if (getValueTypePair(Record, OpNum, NextValueNo, Agg))
return error("Invalid record");
Value *Val;
if (getValueTypePair(Record, OpNum, NextValueNo, Val))
return error("Invalid record");
unsigned RecSize = Record.size();
if (OpNum == RecSize)
return error("INSERTVAL: Invalid instruction with 0 indices");
SmallVector<unsigned, 4> INSERTVALIdx;
Type *CurTy = Agg->getType();
for (; OpNum != RecSize; ++OpNum) {
bool IsArray = CurTy->isArrayTy();
bool IsStruct = CurTy->isStructTy();
uint64_t Index = Record[OpNum];
if (!IsStruct && !IsArray)
return error("INSERTVAL: Invalid type");
if ((unsigned)Index != Index)
return error("Invalid value");
if (IsStruct && Index >= CurTy->getStructNumElements())
return error("INSERTVAL: Invalid struct index");
if (IsArray && Index >= CurTy->getArrayNumElements())
return error("INSERTVAL: Invalid array index");
INSERTVALIdx.push_back((unsigned)Index);
if (IsStruct)
CurTy = CurTy->getStructElementType(Index);
else
CurTy = CurTy->getArrayElementType();
}
if (CurTy != Val->getType())
return error("Inserted value type doesn't match aggregate type");
I = InsertValueInst::Create(Agg, Val, INSERTVALIdx);
InstructionList.push_back(I);
break;
}
case bitc::FUNC_CODE_INST_SELECT: { // SELECT: [opval, ty, opval, opval]
// obsolete form of select
// handles select i1 ... in old bitcode
unsigned OpNum = 0;
Value *TrueVal, *FalseVal, *Cond;
if (getValueTypePair(Record, OpNum, NextValueNo, TrueVal) ||
popValue(Record, OpNum, NextValueNo, TrueVal->getType(), FalseVal) ||
popValue(Record, OpNum, NextValueNo, Type::getInt1Ty(Context), Cond))
return error("Invalid record");
I = SelectInst::Create(Cond, TrueVal, FalseVal);
InstructionList.push_back(I);
break;
}
case bitc::FUNC_CODE_INST_VSELECT: {// VSELECT: [ty,opval,opval,predty,pred]
// new form of select
// handles select i1 or select [N x i1]
unsigned OpNum = 0;
Value *TrueVal, *FalseVal, *Cond;
if (getValueTypePair(Record, OpNum, NextValueNo, TrueVal) ||
popValue(Record, OpNum, NextValueNo, TrueVal->getType(), FalseVal) ||
getValueTypePair(Record, OpNum, NextValueNo, Cond))
return error("Invalid record");
// select condition can be either i1 or [N x i1]
if (VectorType* vector_type =
dyn_cast<VectorType>(Cond->getType())) {
// expect <n x i1>
if (vector_type->getElementType() != Type::getInt1Ty(Context))
return error("Invalid type for value");
} else {
// expect i1
if (Cond->getType() != Type::getInt1Ty(Context))
return error("Invalid type for value");
}
I = SelectInst::Create(Cond, TrueVal, FalseVal);
InstructionList.push_back(I);
if (OpNum < Record.size() && isa<FPMathOperator>(I)) {
FastMathFlags FMF = getDecodedFastMathFlags(Record[OpNum]);
if (FMF.any())
I->setFastMathFlags(FMF);
}
break;
}
case bitc::FUNC_CODE_INST_EXTRACTELT: { // EXTRACTELT: [opty, opval, opval]
unsigned OpNum = 0;
Value *Vec, *Idx;
if (getValueTypePair(Record, OpNum, NextValueNo, Vec) ||
getValueTypePair(Record, OpNum, NextValueNo, Idx))
return error("Invalid record");
if (!Vec->getType()->isVectorTy())
return error("Invalid type for value");
I = ExtractElementInst::Create(Vec, Idx);
InstructionList.push_back(I);
break;
}
case bitc::FUNC_CODE_INST_INSERTELT: { // INSERTELT: [ty, opval,opval,opval]
unsigned OpNum = 0;
Value *Vec, *Elt, *Idx;
if (getValueTypePair(Record, OpNum, NextValueNo, Vec))
return error("Invalid record");
if (!Vec->getType()->isVectorTy())
return error("Invalid type for value");
if (popValue(Record, OpNum, NextValueNo,
cast<VectorType>(Vec->getType())->getElementType(), Elt) ||
getValueTypePair(Record, OpNum, NextValueNo, Idx))
return error("Invalid record");
I = InsertElementInst::Create(Vec, Elt, Idx);
InstructionList.push_back(I);
break;
}
case bitc::FUNC_CODE_INST_SHUFFLEVEC: {// SHUFFLEVEC: [opval,ty,opval,opval]
unsigned OpNum = 0;
Value *Vec1, *Vec2, *Mask;
if (getValueTypePair(Record, OpNum, NextValueNo, Vec1) ||
popValue(Record, OpNum, NextValueNo, Vec1->getType(), Vec2))
return error("Invalid record");
if (getValueTypePair(Record, OpNum, NextValueNo, Mask))
return error("Invalid record");
if (!Vec1->getType()->isVectorTy() || !Vec2->getType()->isVectorTy())
return error("Invalid type for value");
I = new ShuffleVectorInst(Vec1, Vec2, Mask);
InstructionList.push_back(I);
break;
}
case bitc::FUNC_CODE_INST_CMP: // CMP: [opty, opval, opval, pred]
// Old form of ICmp/FCmp returning bool
// Existed to differentiate between icmp/fcmp and vicmp/vfcmp which were
// both legal on vectors but had different behaviour.
case bitc::FUNC_CODE_INST_CMP2: { // CMP2: [opty, opval, opval, pred]
// FCmp/ICmp returning bool or vector of bool
unsigned OpNum = 0;
Value *LHS, *RHS;
if (getValueTypePair(Record, OpNum, NextValueNo, LHS) ||
popValue(Record, OpNum, NextValueNo, LHS->getType(), RHS))
return error("Invalid record");
if (OpNum >= Record.size())
return error(
"Invalid record: operand number exceeded available operands");
unsigned PredVal = Record[OpNum];
bool IsFP = LHS->getType()->isFPOrFPVectorTy();
FastMathFlags FMF;
if (IsFP && Record.size() > OpNum+1)
FMF = getDecodedFastMathFlags(Record[++OpNum]);
if (OpNum+1 != Record.size())
return error("Invalid record");
if (LHS->getType()->isFPOrFPVectorTy())
I = new FCmpInst((FCmpInst::Predicate)PredVal, LHS, RHS);
else
I = new ICmpInst((ICmpInst::Predicate)PredVal, LHS, RHS);
if (FMF.any())
I->setFastMathFlags(FMF);
InstructionList.push_back(I);
break;
}
case bitc::FUNC_CODE_INST_RET: // RET: [opty,opval<optional>]
{
unsigned Size = Record.size();
if (Size == 0) {
I = ReturnInst::Create(Context);
InstructionList.push_back(I);
break;
}
unsigned OpNum = 0;
Value *Op = nullptr;
if (getValueTypePair(Record, OpNum, NextValueNo, Op))
return error("Invalid record");
if (OpNum != Record.size())
return error("Invalid record");
I = ReturnInst::Create(Context, Op);
InstructionList.push_back(I);
break;
}
case bitc::FUNC_CODE_INST_BR: { // BR: [bb#, bb#, opval] or [bb#]
if (Record.size() != 1 && Record.size() != 3)
return error("Invalid record");
BasicBlock *TrueDest = getBasicBlock(Record[0]);
if (!TrueDest)
return error("Invalid record");
if (Record.size() == 1) {
I = BranchInst::Create(TrueDest);
InstructionList.push_back(I);
}
else {
BasicBlock *FalseDest = getBasicBlock(Record[1]);
Value *Cond = getValue(Record, 2, NextValueNo,
Type::getInt1Ty(Context));
if (!FalseDest || !Cond)
return error("Invalid record");
I = BranchInst::Create(TrueDest, FalseDest, Cond);
InstructionList.push_back(I);
}
break;
}
case bitc::FUNC_CODE_INST_CLEANUPRET: { // CLEANUPRET: [val] or [val,bb#]
if (Record.size() != 1 && Record.size() != 2)
return error("Invalid record");
unsigned Idx = 0;
Value *CleanupPad =
getValue(Record, Idx++, NextValueNo, Type::getTokenTy(Context));
if (!CleanupPad)
return error("Invalid record");
BasicBlock *UnwindDest = nullptr;
if (Record.size() == 2) {
UnwindDest = getBasicBlock(Record[Idx++]);
if (!UnwindDest)
return error("Invalid record");
}
I = CleanupReturnInst::Create(CleanupPad, UnwindDest);
InstructionList.push_back(I);
break;
}
case bitc::FUNC_CODE_INST_CATCHRET: { // CATCHRET: [val,bb#]
if (Record.size() != 2)
return error("Invalid record");
unsigned Idx = 0;
Value *CatchPad =
getValue(Record, Idx++, NextValueNo, Type::getTokenTy(Context));
if (!CatchPad)
return error("Invalid record");
BasicBlock *BB = getBasicBlock(Record[Idx++]);
if (!BB)
return error("Invalid record");
I = CatchReturnInst::Create(CatchPad, BB);
InstructionList.push_back(I);
break;
}
case bitc::FUNC_CODE_INST_CATCHSWITCH: { // CATCHSWITCH: [tok,num,(bb)*,bb?]
// We must have, at minimum, the outer scope and the number of arguments.
if (Record.size() < 2)
return error("Invalid record");
unsigned Idx = 0;
Value *ParentPad =
getValue(Record, Idx++, NextValueNo, Type::getTokenTy(Context));
unsigned NumHandlers = Record[Idx++];
SmallVector<BasicBlock *, 2> Handlers;
for (unsigned Op = 0; Op != NumHandlers; ++Op) {
BasicBlock *BB = getBasicBlock(Record[Idx++]);
if (!BB)
return error("Invalid record");
Handlers.push_back(BB);
}
BasicBlock *UnwindDest = nullptr;
if (Idx + 1 == Record.size()) {
UnwindDest = getBasicBlock(Record[Idx++]);
if (!UnwindDest)
return error("Invalid record");
}
if (Record.size() != Idx)
return error("Invalid record");
auto *CatchSwitch =
CatchSwitchInst::Create(ParentPad, UnwindDest, NumHandlers);
for (BasicBlock *Handler : Handlers)
CatchSwitch->addHandler(Handler);
I = CatchSwitch;
InstructionList.push_back(I);
break;
}
case bitc::FUNC_CODE_INST_CATCHPAD:
case bitc::FUNC_CODE_INST_CLEANUPPAD: { // [tok,num,(ty,val)*]
// We must have, at minimum, the outer scope and the number of arguments.
if (Record.size() < 2)
return error("Invalid record");
unsigned Idx = 0;
Value *ParentPad =
getValue(Record, Idx++, NextValueNo, Type::getTokenTy(Context));
unsigned NumArgOperands = Record[Idx++];
SmallVector<Value *, 2> Args;
for (unsigned Op = 0; Op != NumArgOperands; ++Op) {
Value *Val;
if (getValueTypePair(Record, Idx, NextValueNo, Val))
return error("Invalid record");
Args.push_back(Val);
}
if (Record.size() != Idx)
return error("Invalid record");
if (BitCode == bitc::FUNC_CODE_INST_CLEANUPPAD)
I = CleanupPadInst::Create(ParentPad, Args);
else
I = CatchPadInst::Create(ParentPad, Args);
InstructionList.push_back(I);
break;
}
case bitc::FUNC_CODE_INST_SWITCH: { // SWITCH: [opty, op0, op1, ...]
// Check magic
if ((Record[0] >> 16) == SWITCH_INST_MAGIC) {
// "New" SwitchInst format with case ranges. The changes to write this
// format were reverted but we still recognize bitcode that uses it.
// Hopefully someday we will have support for case ranges and can use
// this format again.
Type *OpTy = getTypeByID(Record[1]);
unsigned ValueBitWidth = cast<IntegerType>(OpTy)->getBitWidth();
Value *Cond = getValue(Record, 2, NextValueNo, OpTy);
BasicBlock *Default = getBasicBlock(Record[3]);
if (!OpTy || !Cond || !Default)
return error("Invalid record");
unsigned NumCases = Record[4];
SwitchInst *SI = SwitchInst::Create(Cond, Default, NumCases);
InstructionList.push_back(SI);
unsigned CurIdx = 5;
for (unsigned i = 0; i != NumCases; ++i) {
SmallVector<ConstantInt*, 1> CaseVals;
unsigned NumItems = Record[CurIdx++];
for (unsigned ci = 0; ci != NumItems; ++ci) {
bool isSingleNumber = Record[CurIdx++];
APInt Low;
unsigned ActiveWords = 1;
if (ValueBitWidth > 64)
ActiveWords = Record[CurIdx++];
Low = readWideAPInt(makeArrayRef(&Record[CurIdx], ActiveWords),
ValueBitWidth);
CurIdx += ActiveWords;
if (!isSingleNumber) {
ActiveWords = 1;
if (ValueBitWidth > 64)
ActiveWords = Record[CurIdx++];
APInt High = readWideAPInt(
makeArrayRef(&Record[CurIdx], ActiveWords), ValueBitWidth);
CurIdx += ActiveWords;
// FIXME: It is not clear whether values in the range should be
// compared as signed or unsigned values. The partially
// implemented changes that used this format in the past used
// unsigned comparisons.
for ( ; Low.ule(High); ++Low)
CaseVals.push_back(ConstantInt::get(Context, Low));
} else
CaseVals.push_back(ConstantInt::get(Context, Low));
}
BasicBlock *DestBB = getBasicBlock(Record[CurIdx++]);
for (ConstantInt *Cst : CaseVals)
SI->addCase(Cst, DestBB);
}
I = SI;
break;
}
// Old SwitchInst format without case ranges.
if (Record.size() < 3 || (Record.size() & 1) == 0)
return error("Invalid record");
Type *OpTy = getTypeByID(Record[0]);
Value *Cond = getValue(Record, 1, NextValueNo, OpTy);
BasicBlock *Default = getBasicBlock(Record[2]);
if (!OpTy || !Cond || !Default)
return error("Invalid record");
unsigned NumCases = (Record.size()-3)/2;
SwitchInst *SI = SwitchInst::Create(Cond, Default, NumCases);
InstructionList.push_back(SI);
for (unsigned i = 0, e = NumCases; i != e; ++i) {
ConstantInt *CaseVal =
dyn_cast_or_null<ConstantInt>(getFnValueByID(Record[3+i*2], OpTy));
BasicBlock *DestBB = getBasicBlock(Record[1+3+i*2]);
if (!CaseVal || !DestBB) {
delete SI;
return error("Invalid record");
}
SI->addCase(CaseVal, DestBB);
}
I = SI;
break;
}
case bitc::FUNC_CODE_INST_INDIRECTBR: { // INDIRECTBR: [opty, op0, op1, ...]
if (Record.size() < 2)
return error("Invalid record");
Type *OpTy = getTypeByID(Record[0]);
Value *Address = getValue(Record, 1, NextValueNo, OpTy);
if (!OpTy || !Address)
return error("Invalid record");
unsigned NumDests = Record.size()-2;
IndirectBrInst *IBI = IndirectBrInst::Create(Address, NumDests);
InstructionList.push_back(IBI);
for (unsigned i = 0, e = NumDests; i != e; ++i) {
if (BasicBlock *DestBB = getBasicBlock(Record[2+i])) {
IBI->addDestination(DestBB);
} else {
delete IBI;
return error("Invalid record");
}
}
I = IBI;
break;
}
case bitc::FUNC_CODE_INST_INVOKE: {
// INVOKE: [attrs, cc, normBB, unwindBB, fnty, op0,op1,op2, ...]
if (Record.size() < 4)
return error("Invalid record");
unsigned OpNum = 0;
AttributeList PAL = getAttributes(Record[OpNum++]);
unsigned CCInfo = Record[OpNum++];
BasicBlock *NormalBB = getBasicBlock(Record[OpNum++]);
BasicBlock *UnwindBB = getBasicBlock(Record[OpNum++]);
FunctionType *FTy = nullptr;
if ((CCInfo >> 13) & 1) {
FTy = dyn_cast<FunctionType>(getTypeByID(Record[OpNum++]));
if (!FTy)
return error("Explicit invoke type is not a function type");
}
Value *Callee;
if (getValueTypePair(Record, OpNum, NextValueNo, Callee))
return error("Invalid record");
PointerType *CalleeTy = dyn_cast<PointerType>(Callee->getType());
if (!CalleeTy)
return error("Callee is not a pointer");
if (!FTy) {
FTy = dyn_cast<FunctionType>(
cast<PointerType>(Callee->getType())->getElementType());
if (!FTy)
return error("Callee is not of pointer to function type");
} else if (!CalleeTy->isOpaqueOrPointeeTypeMatches(FTy))
return error("Explicit invoke type does not match pointee type of "
"callee operand");
if (Record.size() < FTy->getNumParams() + OpNum)
return error("Insufficient operands to call");
SmallVector<Value*, 16> Ops;
SmallVector<Type *, 16> ArgsTys;
for (unsigned i = 0, e = FTy->getNumParams(); i != e; ++i, ++OpNum) {
Ops.push_back(getValue(Record, OpNum, NextValueNo,
FTy->getParamType(i)));
ArgsTys.push_back(FTy->getParamType(i));
if (!Ops.back())
return error("Invalid record");
}
if (!FTy->isVarArg()) {
if (Record.size() != OpNum)
return error("Invalid record");
} else {
// Read type/value pairs for varargs params.
while (OpNum != Record.size()) {
Value *Op;
if (getValueTypePair(Record, OpNum, NextValueNo, Op))
return error("Invalid record");
Ops.push_back(Op);
ArgsTys.push_back(Op->getType());
}
}
I = InvokeInst::Create(FTy, Callee, NormalBB, UnwindBB, Ops,
OperandBundles);
OperandBundles.clear();
InstructionList.push_back(I);
cast<InvokeInst>(I)->setCallingConv(
static_cast<CallingConv::ID>(CallingConv::MaxID & CCInfo));
cast<InvokeInst>(I)->setAttributes(PAL);
propagateAttributeTypes(cast<CallBase>(I), ArgsTys);
break;
}
case bitc::FUNC_CODE_INST_RESUME: { // RESUME: [opval]
unsigned Idx = 0;
Value *Val = nullptr;
if (getValueTypePair(Record, Idx, NextValueNo, Val))
return error("Invalid record");
I = ResumeInst::Create(Val);
InstructionList.push_back(I);
break;
}
case bitc::FUNC_CODE_INST_CALLBR: {
// CALLBR: [attr, cc, norm, transfs, fty, fnid, args]
unsigned OpNum = 0;
AttributeList PAL = getAttributes(Record[OpNum++]);
unsigned CCInfo = Record[OpNum++];
BasicBlock *DefaultDest = getBasicBlock(Record[OpNum++]);
unsigned NumIndirectDests = Record[OpNum++];
SmallVector<BasicBlock *, 16> IndirectDests;
for (unsigned i = 0, e = NumIndirectDests; i != e; ++i)
IndirectDests.push_back(getBasicBlock(Record[OpNum++]));
FunctionType *FTy = nullptr;
if ((CCInfo >> bitc::CALL_EXPLICIT_TYPE) & 1) {
FTy = dyn_cast<FunctionType>(getTypeByID(Record[OpNum++]));
if (!FTy)
return error("Explicit call type is not a function type");
}
Value *Callee;
if (getValueTypePair(Record, OpNum, NextValueNo, Callee))
return error("Invalid record");
PointerType *OpTy = dyn_cast<PointerType>(Callee->getType());
if (!OpTy)
return error("Callee is not a pointer type");
if (!FTy) {
FTy = dyn_cast<FunctionType>(
cast<PointerType>(Callee->getType())->getElementType());
if (!FTy)
return error("Callee is not of pointer to function type");
} else if (!OpTy->isOpaqueOrPointeeTypeMatches(FTy))
return error("Explicit call type does not match pointee type of "
"callee operand");
if (Record.size() < FTy->getNumParams() + OpNum)
return error("Insufficient operands to call");
SmallVector<Value*, 16> Args;
SmallVector<Type *, 16> ArgsTys;
// Read the fixed params.
for (unsigned i = 0, e = FTy->getNumParams(); i != e; ++i, ++OpNum) {
Value *Arg;
if (FTy->getParamType(i)->isLabelTy())
Arg = getBasicBlock(Record[OpNum]);
else
Arg = getValue(Record, OpNum, NextValueNo, FTy->getParamType(i));
if (!Arg)
return error("Invalid record");
Args.push_back(Arg);
ArgsTys.push_back(Arg->getType());
}
// Read type/value pairs for varargs params.
if (!FTy->isVarArg()) {
if (OpNum != Record.size())
return error("Invalid record");
} else {
while (OpNum != Record.size()) {
Value *Op;
if (getValueTypePair(Record, OpNum, NextValueNo, Op))
return error("Invalid record");
Args.push_back(Op);
ArgsTys.push_back(Op->getType());
}
}
I = CallBrInst::Create(FTy, Callee, DefaultDest, IndirectDests, Args,
OperandBundles);
OperandBundles.clear();
InstructionList.push_back(I);
cast<CallBrInst>(I)->setCallingConv(
static_cast<CallingConv::ID>((0x7ff & CCInfo) >> bitc::CALL_CCONV));
cast<CallBrInst>(I)->setAttributes(PAL);
propagateAttributeTypes(cast<CallBase>(I), ArgsTys);
break;
}
case bitc::FUNC_CODE_INST_UNREACHABLE: // UNREACHABLE
I = new UnreachableInst(Context);
InstructionList.push_back(I);
break;
case bitc::FUNC_CODE_INST_PHI: { // PHI: [ty, val0,bb0, ...]
if (Record.empty())
return error("Invalid record");
// The first record specifies the type.
Type *Ty = getTypeByID(Record[0]);
if (!Ty)
return error("Invalid record");
// Phi arguments are pairs of records of [value, basic block].
// There is an optional final record for fast-math-flags if this phi has a
// floating-point type.
size_t NumArgs = (Record.size() - 1) / 2;
PHINode *PN = PHINode::Create(Ty, NumArgs);
if ((Record.size() - 1) % 2 == 1 && !isa<FPMathOperator>(PN))
return error("Invalid record");
InstructionList.push_back(PN);
for (unsigned i = 0; i != NumArgs; i++) {
Value *V;
// With the new function encoding, it is possible that operands have
// negative IDs (for forward references). Use a signed VBR
// representation to keep the encoding small.
if (UseRelativeIDs)
V = getValueSigned(Record, i * 2 + 1, NextValueNo, Ty);
else
V = getValue(Record, i * 2 + 1, NextValueNo, Ty);
BasicBlock *BB = getBasicBlock(Record[i * 2 + 2]);
if (!V || !BB)
return error("Invalid record");
PN->addIncoming(V, BB);
}
I = PN;
// If there are an even number of records, the final record must be FMF.
if (Record.size() % 2 == 0) {
assert(isa<FPMathOperator>(I) && "Unexpected phi type");
FastMathFlags FMF = getDecodedFastMathFlags(Record[Record.size() - 1]);
if (FMF.any())
I->setFastMathFlags(FMF);
}
break;
}
case bitc::FUNC_CODE_INST_LANDINGPAD:
case bitc::FUNC_CODE_INST_LANDINGPAD_OLD: {
// LANDINGPAD: [ty, val, val, num, (id0,val0 ...)?]
unsigned Idx = 0;
if (BitCode == bitc::FUNC_CODE_INST_LANDINGPAD) {
if (Record.size() < 3)
return error("Invalid record");
} else {
assert(BitCode == bitc::FUNC_CODE_INST_LANDINGPAD_OLD);
if (Record.size() < 4)
return error("Invalid record");
}
Type *Ty = getTypeByID(Record[Idx++]);
if (!Ty)
return error("Invalid record");
if (BitCode == bitc::FUNC_CODE_INST_LANDINGPAD_OLD) {
Value *PersFn = nullptr;
if (getValueTypePair(Record, Idx, NextValueNo, PersFn))
return error("Invalid record");
if (!F->hasPersonalityFn())
F->setPersonalityFn(cast<Constant>(PersFn));
else if (F->getPersonalityFn() != cast<Constant>(PersFn))
return error("Personality function mismatch");
}
bool IsCleanup = !!Record[Idx++];
unsigned NumClauses = Record[Idx++];
LandingPadInst *LP = LandingPadInst::Create(Ty, NumClauses);
LP->setCleanup(IsCleanup);
for (unsigned J = 0; J != NumClauses; ++J) {
LandingPadInst::ClauseType CT =
LandingPadInst::ClauseType(Record[Idx++]); (void)CT;
Value *Val;
if (getValueTypePair(Record, Idx, NextValueNo, Val)) {
delete LP;
return error("Invalid record");
}
assert((CT != LandingPadInst::Catch ||
!isa<ArrayType>(Val->getType())) &&
"Catch clause has a invalid type!");
assert((CT != LandingPadInst::Filter ||
isa<ArrayType>(Val->getType())) &&
"Filter clause has invalid type!");
LP->addClause(cast<Constant>(Val));
}
I = LP;
InstructionList.push_back(I);
break;
}
case bitc::FUNC_CODE_INST_ALLOCA: { // ALLOCA: [instty, opty, op, align]
if (Record.size() != 4)
return error("Invalid record");
using APV = AllocaPackedValues;
const uint64_t Rec = Record[3];
const bool InAlloca = Bitfield::get<APV::UsedWithInAlloca>(Rec);
const bool SwiftError = Bitfield::get<APV::SwiftError>(Rec);
Type *Ty = getTypeByID(Record[0]);
if (!Bitfield::get<APV::ExplicitType>(Rec)) {
auto *PTy = dyn_cast_or_null<PointerType>(Ty);
if (!PTy)
return error("Old-style alloca with a non-pointer type");
Ty = PTy->getElementType();
}
Type *OpTy = getTypeByID(Record[1]);
Value *Size = getFnValueByID(Record[2], OpTy);
MaybeAlign Align;
uint64_t AlignExp =
Bitfield::get<APV::AlignLower>(Rec) |
(Bitfield::get<APV::AlignUpper>(Rec) << APV::AlignLower::Bits);
if (Error Err = parseAlignmentValue(AlignExp, Align)) {
return Err;
}
if (!Ty || !Size)
return error("Invalid record");
// FIXME: Make this an optional field.
const DataLayout &DL = TheModule->getDataLayout();
unsigned AS = DL.getAllocaAddrSpace();
SmallPtrSet<Type *, 4> Visited;
if (!Align && !Ty->isSized(&Visited))
return error("alloca of unsized type");
if (!Align)
Align = DL.getPrefTypeAlign(Ty);
AllocaInst *AI = new AllocaInst(Ty, AS, Size, *Align);
AI->setUsedWithInAlloca(InAlloca);
AI->setSwiftError(SwiftError);
I = AI;
InstructionList.push_back(I);
break;
}
case bitc::FUNC_CODE_INST_LOAD: { // LOAD: [opty, op, align, vol]
unsigned OpNum = 0;
Value *Op;
if (getValueTypePair(Record, OpNum, NextValueNo, Op) ||
(OpNum + 2 != Record.size() && OpNum + 3 != Record.size()))
return error("Invalid record");
if (!isa<PointerType>(Op->getType()))
return error("Load operand is not a pointer type");
Type *Ty = nullptr;
if (OpNum + 3 == Record.size()) {
Ty = getTypeByID(Record[OpNum++]);
} else {
Ty = cast<PointerType>(Op->getType())->getElementType();
}
if (Error Err = typeCheckLoadStoreInst(Ty, Op->getType()))
return Err;
MaybeAlign Align;
if (Error Err = parseAlignmentValue(Record[OpNum], Align))
return Err;
SmallPtrSet<Type *, 4> Visited;
if (!Align && !Ty->isSized(&Visited))
return error("load of unsized type");
if (!Align)
Align = TheModule->getDataLayout().getABITypeAlign(Ty);
I = new LoadInst(Ty, Op, "", Record[OpNum + 1], *Align);
InstructionList.push_back(I);
break;
}
case bitc::FUNC_CODE_INST_LOADATOMIC: {
// LOADATOMIC: [opty, op, align, vol, ordering, ssid]
unsigned OpNum = 0;
Value *Op;
if (getValueTypePair(Record, OpNum, NextValueNo, Op) ||
(OpNum + 4 != Record.size() && OpNum + 5 != Record.size()))
return error("Invalid record");
if (!isa<PointerType>(Op->getType()))
return error("Load operand is not a pointer type");
Type *Ty = nullptr;
if (OpNum + 5 == Record.size()) {
Ty = getTypeByID(Record[OpNum++]);
} else {
Ty = cast<PointerType>(Op->getType())->getElementType();
}
if (Error Err = typeCheckLoadStoreInst(Ty, Op->getType()))
return Err;
AtomicOrdering Ordering = getDecodedOrdering(Record[OpNum + 2]);
if (Ordering == AtomicOrdering::NotAtomic ||
Ordering == AtomicOrdering::Release ||
Ordering == AtomicOrdering::AcquireRelease)
return error("Invalid record");
if (Ordering != AtomicOrdering::NotAtomic && Record[OpNum] == 0)
return error("Invalid record");
SyncScope::ID SSID = getDecodedSyncScopeID(Record[OpNum + 3]);
MaybeAlign Align;
if (Error Err = parseAlignmentValue(Record[OpNum], Align))
return Err;
if (!Align)
return error("Alignment missing from atomic load");
I = new LoadInst(Ty, Op, "", Record[OpNum + 1], *Align, Ordering, SSID);
InstructionList.push_back(I);
break;
}
case bitc::FUNC_CODE_INST_STORE:
case bitc::FUNC_CODE_INST_STORE_OLD: { // STORE2:[ptrty, ptr, val, align, vol]
unsigned OpNum = 0;
Value *Val, *Ptr;
if (getValueTypePair(Record, OpNum, NextValueNo, Ptr) ||
(BitCode == bitc::FUNC_CODE_INST_STORE
? getValueTypePair(Record, OpNum, NextValueNo, Val)
: popValue(Record, OpNum, NextValueNo,
cast<PointerType>(Ptr->getType())->getElementType(),
Val)) ||
OpNum + 2 != Record.size())
return error("Invalid record");
if (Error Err = typeCheckLoadStoreInst(Val->getType(), Ptr->getType()))
return Err;
MaybeAlign Align;
if (Error Err = parseAlignmentValue(Record[OpNum], Align))
return Err;
SmallPtrSet<Type *, 4> Visited;
if (!Align && !Val->getType()->isSized(&Visited))
return error("store of unsized type");
if (!Align)
Align = TheModule->getDataLayout().getABITypeAlign(Val->getType());
I = new StoreInst(Val, Ptr, Record[OpNum + 1], *Align);
InstructionList.push_back(I);
break;
}
case bitc::FUNC_CODE_INST_STOREATOMIC:
case bitc::FUNC_CODE_INST_STOREATOMIC_OLD: {
// STOREATOMIC: [ptrty, ptr, val, align, vol, ordering, ssid]
unsigned OpNum = 0;
Value *Val, *Ptr;
if (getValueTypePair(Record, OpNum, NextValueNo, Ptr) ||
!isa<PointerType>(Ptr->getType()) ||
(BitCode == bitc::FUNC_CODE_INST_STOREATOMIC
? getValueTypePair(Record, OpNum, NextValueNo, Val)
: popValue(Record, OpNum, NextValueNo,
cast<PointerType>(Ptr->getType())->getElementType(),
Val)) ||
OpNum + 4 != Record.size())
return error("Invalid record");
if (Error Err = typeCheckLoadStoreInst(Val->getType(), Ptr->getType()))
return Err;
AtomicOrdering Ordering = getDecodedOrdering(Record[OpNum + 2]);
if (Ordering == AtomicOrdering::NotAtomic ||
Ordering == AtomicOrdering::Acquire ||
Ordering == AtomicOrdering::AcquireRelease)
return error("Invalid record");
SyncScope::ID SSID = getDecodedSyncScopeID(Record[OpNum + 3]);
if (Ordering != AtomicOrdering::NotAtomic && Record[OpNum] == 0)
return error("Invalid record");
MaybeAlign Align;
if (Error Err = parseAlignmentValue(Record[OpNum], Align))
return Err;
if (!Align)
return error("Alignment missing from atomic store");
I = new StoreInst(Val, Ptr, Record[OpNum + 1], *Align, Ordering, SSID);
InstructionList.push_back(I);
break;
}
case bitc::FUNC_CODE_INST_CMPXCHG_OLD: {
// CMPXCHG_OLD: [ptrty, ptr, cmp, val, vol, ordering, synchscope,
// failure_ordering?, weak?]
const size_t NumRecords = Record.size();
unsigned OpNum = 0;
Value *Ptr = nullptr;
if (getValueTypePair(Record, OpNum, NextValueNo, Ptr))
return error("Invalid record");
if (!isa<PointerType>(Ptr->getType()))
return error("Cmpxchg operand is not a pointer type");
Value *Cmp = nullptr;
if (popValue(Record, OpNum, NextValueNo,
cast<PointerType>(Ptr->getType())->getPointerElementType(),
Cmp))
return error("Invalid record");
Value *New = nullptr;
if (popValue(Record, OpNum, NextValueNo, Cmp->getType(), New) ||
NumRecords < OpNum + 3 || NumRecords > OpNum + 5)
return error("Invalid record");
const AtomicOrdering SuccessOrdering =
getDecodedOrdering(Record[OpNum + 1]);
if (SuccessOrdering == AtomicOrdering::NotAtomic ||
SuccessOrdering == AtomicOrdering::Unordered)
return error("Invalid record");
const SyncScope::ID SSID = getDecodedSyncScopeID(Record[OpNum + 2]);
if (Error Err = typeCheckLoadStoreInst(Cmp->getType(), Ptr->getType()))
return Err;
const AtomicOrdering FailureOrdering =
NumRecords < 7
? AtomicCmpXchgInst::getStrongestFailureOrdering(SuccessOrdering)
: getDecodedOrdering(Record[OpNum + 3]);
if (FailureOrdering == AtomicOrdering::NotAtomic ||
FailureOrdering == AtomicOrdering::Unordered)
return error("Invalid record");
const Align Alignment(
TheModule->getDataLayout().getTypeStoreSize(Cmp->getType()));
I = new AtomicCmpXchgInst(Ptr, Cmp, New, Alignment, SuccessOrdering,
FailureOrdering, SSID);
cast<AtomicCmpXchgInst>(I)->setVolatile(Record[OpNum]);
if (NumRecords < 8) {
// Before weak cmpxchgs existed, the instruction simply returned the
// value loaded from memory, so bitcode files from that era will be
// expecting the first component of a modern cmpxchg.
CurBB->getInstList().push_back(I);
I = ExtractValueInst::Create(I, 0);
} else {
cast<AtomicCmpXchgInst>(I)->setWeak(Record[OpNum + 4]);
}
InstructionList.push_back(I);
break;
}
case bitc::FUNC_CODE_INST_CMPXCHG: {
// CMPXCHG: [ptrty, ptr, cmp, val, vol, success_ordering, synchscope,
// failure_ordering, weak, align?]
const size_t NumRecords = Record.size();
unsigned OpNum = 0;
Value *Ptr = nullptr;
if (getValueTypePair(Record, OpNum, NextValueNo, Ptr))
return error("Invalid record");
if (!isa<PointerType>(Ptr->getType()))
return error("Cmpxchg operand is not a pointer type");
Value *Cmp = nullptr;
if (getValueTypePair(Record, OpNum, NextValueNo, Cmp))
return error("Invalid record");
Value *Val = nullptr;
if (popValue(Record, OpNum, NextValueNo, Cmp->getType(), Val))
return error("Invalid record");
if (NumRecords < OpNum + 3 || NumRecords > OpNum + 6)
return error("Invalid record");
const bool IsVol = Record[OpNum];
const AtomicOrdering SuccessOrdering =
getDecodedOrdering(Record[OpNum + 1]);
if (!AtomicCmpXchgInst::isValidSuccessOrdering(SuccessOrdering))
return error("Invalid cmpxchg success ordering");
const SyncScope::ID SSID = getDecodedSyncScopeID(Record[OpNum + 2]);
if (Error Err = typeCheckLoadStoreInst(Cmp->getType(), Ptr->getType()))
return Err;
const AtomicOrdering FailureOrdering =
getDecodedOrdering(Record[OpNum + 3]);
if (!AtomicCmpXchgInst::isValidFailureOrdering(FailureOrdering))
return error("Invalid cmpxchg failure ordering");
const bool IsWeak = Record[OpNum + 4];
MaybeAlign Alignment;
if (NumRecords == (OpNum + 6)) {
if (Error Err = parseAlignmentValue(Record[OpNum + 5], Alignment))
return Err;
}
if (!Alignment)
Alignment =
Align(TheModule->getDataLayout().getTypeStoreSize(Cmp->getType()));
I = new AtomicCmpXchgInst(Ptr, Cmp, Val, *Alignment, SuccessOrdering,
FailureOrdering, SSID);
cast<AtomicCmpXchgInst>(I)->setVolatile(IsVol);
cast<AtomicCmpXchgInst>(I)->setWeak(IsWeak);
InstructionList.push_back(I);
break;
}
case bitc::FUNC_CODE_INST_ATOMICRMW_OLD:
case bitc::FUNC_CODE_INST_ATOMICRMW: {
// ATOMICRMW_OLD: [ptrty, ptr, val, op, vol, ordering, ssid, align?]
// ATOMICRMW: [ptrty, ptr, valty, val, op, vol, ordering, ssid, align?]
const size_t NumRecords = Record.size();
unsigned OpNum = 0;
Value *Ptr = nullptr;
if (getValueTypePair(Record, OpNum, NextValueNo, Ptr))
return error("Invalid record");
if (!isa<PointerType>(Ptr->getType()))
return error("Invalid record");
Value *Val = nullptr;
if (BitCode == bitc::FUNC_CODE_INST_ATOMICRMW_OLD) {
if (popValue(Record, OpNum, NextValueNo,
cast<PointerType>(Ptr->getType())->getPointerElementType(),
Val))
return error("Invalid record");
} else {
if (getValueTypePair(Record, OpNum, NextValueNo, Val))
return error("Invalid record");
}
if (!(NumRecords == (OpNum + 4) || NumRecords == (OpNum + 5)))
return error("Invalid record");
const AtomicRMWInst::BinOp Operation =
getDecodedRMWOperation(Record[OpNum]);
if (Operation < AtomicRMWInst::FIRST_BINOP ||
Operation > AtomicRMWInst::LAST_BINOP)
return error("Invalid record");
const bool IsVol = Record[OpNum + 1];
const AtomicOrdering Ordering = getDecodedOrdering(Record[OpNum + 2]);
if (Ordering == AtomicOrdering::NotAtomic ||
Ordering == AtomicOrdering::Unordered)
return error("Invalid record");
const SyncScope::ID SSID = getDecodedSyncScopeID(Record[OpNum + 3]);
MaybeAlign Alignment;
if (NumRecords == (OpNum + 5)) {
if (Error Err = parseAlignmentValue(Record[OpNum + 4], Alignment))
return Err;
}
if (!Alignment)
Alignment =
Align(TheModule->getDataLayout().getTypeStoreSize(Val->getType()));
I = new AtomicRMWInst(Operation, Ptr, Val, *Alignment, Ordering, SSID);
cast<AtomicRMWInst>(I)->setVolatile(IsVol);
InstructionList.push_back(I);
break;
}
case bitc::FUNC_CODE_INST_FENCE: { // FENCE:[ordering, ssid]
if (2 != Record.size())
return error("Invalid record");
AtomicOrdering Ordering = getDecodedOrdering(Record[0]);
if (Ordering == AtomicOrdering::NotAtomic ||
Ordering == AtomicOrdering::Unordered ||
Ordering == AtomicOrdering::Monotonic)
return error("Invalid record");
SyncScope::ID SSID = getDecodedSyncScopeID(Record[1]);
I = new FenceInst(Context, Ordering, SSID);
InstructionList.push_back(I);
break;
}
case bitc::FUNC_CODE_INST_CALL: {
// CALL: [paramattrs, cc, fmf, fnty, fnid, arg0, arg1...]
if (Record.size() < 3)
return error("Invalid record");
unsigned OpNum = 0;
AttributeList PAL = getAttributes(Record[OpNum++]);
unsigned CCInfo = Record[OpNum++];
FastMathFlags FMF;
if ((CCInfo >> bitc::CALL_FMF) & 1) {
FMF = getDecodedFastMathFlags(Record[OpNum++]);
if (!FMF.any())
return error("Fast math flags indicator set for call with no FMF");
}
FunctionType *FTy = nullptr;
if ((CCInfo >> bitc::CALL_EXPLICIT_TYPE) & 1) {
FTy = dyn_cast<FunctionType>(getTypeByID(Record[OpNum++]));
if (!FTy)
return error("Explicit call type is not a function type");
}
Value *Callee;
if (getValueTypePair(Record, OpNum, NextValueNo, Callee))
return error("Invalid record");
PointerType *OpTy = dyn_cast<PointerType>(Callee->getType());
if (!OpTy)
return error("Callee is not a pointer type");
if (!FTy) {
FTy = dyn_cast<FunctionType>(
cast<PointerType>(Callee->getType())->getElementType());
if (!FTy)
return error("Callee is not of pointer to function type");
} else if (!OpTy->isOpaqueOrPointeeTypeMatches(FTy))
return error("Explicit call type does not match pointee type of "
"callee operand");
if (Record.size() < FTy->getNumParams() + OpNum)
return error("Insufficient operands to call");
SmallVector<Value*, 16> Args;
SmallVector<Type *, 16> ArgsTys;
// Read the fixed params.
for (unsigned i = 0, e = FTy->getNumParams(); i != e; ++i, ++OpNum) {
if (FTy->getParamType(i)->isLabelTy())
Args.push_back(getBasicBlock(Record[OpNum]));
else
Args.push_back(getValue(Record, OpNum, NextValueNo,
FTy->getParamType(i)));
ArgsTys.push_back(FTy->getParamType(i));
if (!Args.back())
return error("Invalid record");
}
// Read type/value pairs for varargs params.
if (!FTy->isVarArg()) {
if (OpNum != Record.size())
return error("Invalid record");
} else {
while (OpNum != Record.size()) {
Value *Op;
if (getValueTypePair(Record, OpNum, NextValueNo, Op))
return error("Invalid record");
Args.push_back(Op);
ArgsTys.push_back(Op->getType());
}
}
I = CallInst::Create(FTy, Callee, Args, OperandBundles);
OperandBundles.clear();
InstructionList.push_back(I);
cast<CallInst>(I)->setCallingConv(
static_cast<CallingConv::ID>((0x7ff & CCInfo) >> bitc::CALL_CCONV));
CallInst::TailCallKind TCK = CallInst::TCK_None;
if (CCInfo & 1 << bitc::CALL_TAIL)
TCK = CallInst::TCK_Tail;
if (CCInfo & (1 << bitc::CALL_MUSTTAIL))
TCK = CallInst::TCK_MustTail;
if (CCInfo & (1 << bitc::CALL_NOTAIL))
TCK = CallInst::TCK_NoTail;
cast<CallInst>(I)->setTailCallKind(TCK);
cast<CallInst>(I)->setAttributes(PAL);
propagateAttributeTypes(cast<CallBase>(I), ArgsTys);
if (FMF.any()) {
if (!isa<FPMathOperator>(I))
return error("Fast-math-flags specified for call without "
"floating-point scalar or vector return type");
I->setFastMathFlags(FMF);
}
break;
}
case bitc::FUNC_CODE_INST_VAARG: { // VAARG: [valistty, valist, instty]
if (Record.size() < 3)
return error("Invalid record");
Type *OpTy = getTypeByID(Record[0]);
Value *Op = getValue(Record, 1, NextValueNo, OpTy);
Type *ResTy = getTypeByID(Record[2]);
if (!OpTy || !Op || !ResTy)
return error("Invalid record");
I = new VAArgInst(Op, ResTy);
InstructionList.push_back(I);
break;
}
case bitc::FUNC_CODE_OPERAND_BUNDLE: {
// A call or an invoke can be optionally prefixed with some variable
// number of operand bundle blocks. These blocks are read into
// OperandBundles and consumed at the next call or invoke instruction.
if (Record.empty() || Record[0] >= BundleTags.size())
return error("Invalid record");
std::vector<Value *> Inputs;
unsigned OpNum = 1;
while (OpNum != Record.size()) {
Value *Op;
if (getValueTypePair(Record, OpNum, NextValueNo, Op))
return error("Invalid record");
Inputs.push_back(Op);
}
OperandBundles.emplace_back(BundleTags[Record[0]], std::move(Inputs));
continue;
}
case bitc::FUNC_CODE_INST_FREEZE: { // FREEZE: [opty,opval]
unsigned OpNum = 0;
Value *Op = nullptr;
if (getValueTypePair(Record, OpNum, NextValueNo, Op))
return error("Invalid record");
if (OpNum != Record.size())
return error("Invalid record");
I = new FreezeInst(Op);
InstructionList.push_back(I);
break;
}
}
// Add instruction to end of current BB. If there is no current BB, reject
// this file.
if (!CurBB) {
I->deleteValue();
return error("Invalid instruction with no BB");
}
if (!OperandBundles.empty()) {
I->deleteValue();
return error("Operand bundles found with no consumer");
}
CurBB->getInstList().push_back(I);
// If this was a terminator instruction, move to the next block.
if (I->isTerminator()) {
++CurBBNo;
CurBB = CurBBNo < FunctionBBs.size() ? FunctionBBs[CurBBNo] : nullptr;
}
// Non-void values get registered in the value table for future use.
if (!I->getType()->isVoidTy())
ValueList.assignValue(I, NextValueNo++);
}
OutOfRecordLoop:
if (!OperandBundles.empty())
return error("Operand bundles found with no consumer");
// Check the function list for unresolved values.
if (Argument *A = dyn_cast<Argument>(ValueList.back())) {
if (!A->getParent()) {
// We found at least one unresolved value. Nuke them all to avoid leaks.
for (unsigned i = ModuleValueListSize, e = ValueList.size(); i != e; ++i){
if ((A = dyn_cast_or_null<Argument>(ValueList[i])) && !A->getParent()) {
A->replaceAllUsesWith(UndefValue::get(A->getType()));
delete A;
}
}
return error("Never resolved value found in function");
}
}
// Unexpected unresolved metadata about to be dropped.
if (MDLoader->hasFwdRefs())
return error("Invalid function metadata: outgoing forward refs");
// Trim the value list down to the size it was before we parsed this function.
ValueList.shrinkTo(ModuleValueListSize);
MDLoader->shrinkTo(ModuleMDLoaderSize);
std::vector<BasicBlock*>().swap(FunctionBBs);
return Error::success();
}