std::vector<std::string> GCTable;
std::vector<Type*> TypeList;
+ DenseMap<Function *, FunctionType *> FunctionTypes;
BitcodeReaderValueList ValueList;
Optional<MetadataLoader> MDLoader;
std::vector<Comdat *> ComdatList;
StructType *createIdentifiedStructType(LLVMContext &Context, StringRef Name);
StructType *createIdentifiedStructType(LLVMContext &Context);
- Type *getTypeByID(unsigned ID);
+ /// Map all pointer types within \param Ty to the opaque pointer
+ /// type in the same address space if opaque pointers are being
+ /// used, otherwise nop. This converts a bitcode-reader internal
+ /// type into one suitable for use in a Value.
+ Type *flattenPointerTypes(Type *Ty) {
+ return Ty;
+ }
+
+ /// Given a fully structured pointer type (i.e. not opaque), return
+ /// the flattened form of its element, suitable for use in a Value.
+ Type *getPointerElementFlatType(Type *Ty) {
+ return flattenPointerTypes(cast<PointerType>(Ty)->getElementType());
+ }
+
+ /// Given a fully structured pointer type, get its element type in
+ /// both fully structured form, and flattened form suitable for use
+ /// in a Value.
+ std::pair<Type *, Type *> getPointerElementTypes(Type *FullTy) {
+ Type *ElTy = cast<PointerType>(FullTy)->getElementType();
+ return std::make_pair(ElTy, flattenPointerTypes(ElTy));
+ }
+
+ /// Return the flattened type (suitable for use in a Value)
+ /// specified by the given \param ID.
+ Type *getTypeByID(unsigned ID) {
+ return flattenPointerTypes(getFullyStructuredTypeByID(ID));
+ }
- Value *getFnValueByID(unsigned ID, Type *Ty) {
+ /// Return the fully structured (bitcode-reader internal) type
+ /// corresponding to the given \param ID.
+ Type *getFullyStructuredTypeByID(unsigned ID);
+
+ Value *getFnValueByID(unsigned ID, Type *Ty, Type **FullTy = nullptr) {
if (Ty && Ty->isMetadataTy())
return MetadataAsValue::get(Ty->getContext(), getFnMetadataByID(ID));
- return ValueList.getValueFwdRef(ID, Ty);
+ return ValueList.getValueFwdRef(ID, Ty, FullTy);
}
Metadata *getFnMetadataByID(unsigned ID) {
/// Increment Slot past the number of slots used in the record. Return true on
/// failure.
bool getValueTypePair(SmallVectorImpl<uint64_t> &Record, unsigned &Slot,
- unsigned InstNum, Value *&ResVal) {
+ unsigned InstNum, Value *&ResVal,
+ Type **FullTy = nullptr) {
if (Slot == Record.size()) return true;
unsigned ValNo = (unsigned)Record[Slot++];
// Adjust the ValNo, if it was encoded relative to the InstNum.
if (ValNo < InstNum) {
// If this is not a forward reference, just return the value we already
// have.
- ResVal = getFnValueByID(ValNo, nullptr);
+ ResVal = getFnValueByID(ValNo, nullptr, FullTy);
return ResVal == nullptr;
}
if (Slot == Record.size())
unsigned TypeNo = (unsigned)Record[Slot++];
ResVal = getFnValueByID(ValNo, getTypeByID(TypeNo));
+ if (FullTy)
+ *FullTy = getFullyStructuredTypeByID(TypeNo);
return ResVal == nullptr;
}
/// Upgrades old-style typeless byval attributes by adding the corresponding
/// argument's pointee type.
- void propagateByValTypes(CallBase *CB);
+ void propagateByValTypes(CallBase *CB, ArrayRef<Type *> ArgsFullTys);
/// Converts alignment exponent (i.e. power of two (or zero)) to the
/// corresponding alignment to use. If alignment is too large, returns
}
}
-Type *BitcodeReader::getTypeByID(unsigned ID) {
+Type *BitcodeReader::getFullyStructuredTypeByID(unsigned ID) {
// The type table size is always specified correctly.
if (ID >= TypeList.size())
return nullptr;
// Read all the records for this value table.
Type *CurTy = Type::getInt32Ty(Context);
+ Type *CurFullTy = Type::getInt32Ty(Context);
unsigned NextCstNo = ValueList.size();
while (true) {
return error("Invalid record");
if (TypeList[Record[0]] == VoidType)
return error("Invalid constant type");
- CurTy = TypeList[Record[0]];
+ CurFullTy = TypeList[Record[0]];
+ CurTy = flattenPointerTypes(CurFullTy);
continue; // Skip the ValueList manipulation.
case bitc::CST_CODE_NULL: // NULL
V = Constant::getNullValue(CurTy);
InBounds = true;
SmallVector<Constant*, 16> Elts;
+ Type *Elt0FullTy = nullptr;
while (OpNum != Record.size()) {
+ if (!Elt0FullTy)
+ Elt0FullTy = getFullyStructuredTypeByID(Record[OpNum]);
Type *ElTy = getTypeByID(Record[OpNum++]);
if (!ElTy)
return error("Invalid record");
return error("Invalid gep with no operands");
Type *ImplicitPointeeType =
- cast<PointerType>(Elts[0]->getType()->getScalarType())
- ->getElementType();
+ getPointerElementFlatType(Elt0FullTy->getScalarType());
if (!PointeeType)
PointeeType = ImplicitPointeeType;
else if (PointeeType != ImplicitPointeeType)
AsmStr += (char)Record[2+i];
for (unsigned i = 0; i != ConstStrSize; ++i)
ConstrStr += (char)Record[3+AsmStrSize+i];
- PointerType *PTy = cast<PointerType>(CurTy);
UpgradeInlineAsmString(&AsmStr);
- V = InlineAsm::get(cast<FunctionType>(PTy->getElementType()),
- AsmStr, ConstrStr, HasSideEffects, IsAlignStack);
+ V = InlineAsm::get(
+ cast<FunctionType>(getPointerElementFlatType(CurFullTy)), AsmStr,
+ ConstrStr, HasSideEffects, IsAlignStack);
break;
}
// This version adds support for the asm dialect keywords (e.g.,
AsmStr += (char)Record[2+i];
for (unsigned i = 0; i != ConstStrSize; ++i)
ConstrStr += (char)Record[3+AsmStrSize+i];
- PointerType *PTy = cast<PointerType>(CurTy);
UpgradeInlineAsmString(&AsmStr);
- V = InlineAsm::get(cast<FunctionType>(PTy->getElementType()),
- AsmStr, ConstrStr, HasSideEffects, IsAlignStack,
- InlineAsm::AsmDialect(AsmDialect));
+ V = InlineAsm::get(
+ cast<FunctionType>(getPointerElementFlatType(CurFullTy)), AsmStr,
+ ConstrStr, HasSideEffects, IsAlignStack,
+ InlineAsm::AsmDialect(AsmDialect));
break;
}
case bitc::CST_CODE_BLOCKADDRESS:{
}
}
- ValueList.assignValue(V, NextCstNo);
+ assert(V->getType() == flattenPointerTypes(CurFullTy) &&
+ "Incorrect fully structured type provided for Constant");
+ ValueList.assignValue(V, NextCstNo, CurFullTy);
++NextCstNo;
}
}
if (Record.size() < 6)
return error("Invalid record");
- Type *Ty = getTypeByID(Record[0]);
+ Type *FullTy = getFullyStructuredTypeByID(Record[0]);
+ Type *Ty = flattenPointerTypes(FullTy);
if (!Ty)
return error("Invalid record");
bool isConstant = Record[1] & 1;
if (!Ty->isPointerTy())
return error("Invalid type for value");
AddressSpace = cast<PointerType>(Ty)->getAddressSpace();
- Ty = cast<PointerType>(Ty)->getElementType();
+ std::tie(FullTy, Ty) = getPointerElementTypes(FullTy);
}
uint64_t RawLinkage = Record[3];
else
upgradeDLLImportExportLinkage(NewGV, RawLinkage);
- ValueList.push_back(NewGV);
+ FullTy = PointerType::get(FullTy, AddressSpace);
+ assert(NewGV->getType() == flattenPointerTypes(FullTy) &&
+ "Incorrect fully specified type for GlobalVariable");
+ ValueList.push_back(NewGV, FullTy);
// Remember which value to use for the global initializer.
if (unsigned InitID = Record[2])
if (Record.size() < 8)
return error("Invalid record");
- Type *Ty = getTypeByID(Record[0]);
- if (!Ty)
- return error("Invalid record");
- if (auto *PTy = dyn_cast<PointerType>(Ty))
- Ty = PTy->getElementType();
- auto *FTy = dyn_cast<FunctionType>(Ty);
+ Type *FullFTy = getFullyStructuredTypeByID(Record[0]);
+ Type *FTy = flattenPointerTypes(FullFTy);
if (!FTy)
+ return error("Invalid record");
+ if (isa<PointerType>(FTy))
+ std::tie(FullFTy, FTy) = getPointerElementTypes(FullFTy);
+
+ if (!isa<FunctionType>(FTy))
return error("Invalid type for value");
auto CC = static_cast<CallingConv::ID>(Record[1]);
if (CC & ~CallingConv::MaxID)
if (Record.size() > 16)
AddrSpace = Record[16];
- Function *Func = Function::Create(FTy, GlobalValue::ExternalLinkage,
- AddrSpace, Name, TheModule);
+ Function *Func =
+ Function::Create(cast<FunctionType>(FTy), GlobalValue::ExternalLinkage,
+ AddrSpace, Name, TheModule);
+
+ assert(Func->getFunctionType() == flattenPointerTypes(FullFTy) &&
+ "Incorrect fully specified type provided for function");
+ FunctionTypes[Func] = cast<FunctionType>(FullFTy);
Func->setCallingConv(CC);
bool isProto = Record[2];
// Upgrade any old-style byval without a type by propagating the argument's
// pointee type. There should be no opaque pointers where the byval type is
// implicit.
- for (auto &Arg : Func->args()) {
- if (Arg.hasByValAttr() &&
- !Arg.getAttribute(Attribute::ByVal).getValueAsType()) {
- Arg.removeAttr(Attribute::ByVal);
- Arg.addAttr(Attribute::getWithByValType(
- Context, Arg.getType()->getPointerElementType()));
- }
+ for (unsigned i = 0; i != Func->arg_size(); ++i) {
+ if (!Func->hasParamAttribute(i, Attribute::ByVal))
+ continue;
+
+ Type *PTy = cast<FunctionType>(FullFTy)->getParamType(i);
+ Func->removeParamAttr(i, Attribute::ByVal);
+ Func->addParamAttr(i, Attribute::getWithByValType(
+ Context, getPointerElementFlatType(PTy)));
}
unsigned Alignment;
if (Record.size() > 18)
Func->setPartition(StringRef(Strtab.data() + Record[17], Record[18]));
- ValueList.push_back(Func);
+ Type *FullTy = PointerType::get(FullFTy, AddrSpace);
+ assert(Func->getType() == flattenPointerTypes(FullTy) &&
+ "Incorrect fully specified type provided for Function");
+ ValueList.push_back(Func, FullTy);
// If this is a function with a body, remember the prototype we are
// creating now, so that we can match up the body with them later.
if (Record.size() < (3 + (unsigned)NewRecord))
return error("Invalid record");
unsigned OpNum = 0;
- Type *Ty = getTypeByID(Record[OpNum++]);
+ Type *FullTy = getFullyStructuredTypeByID(Record[OpNum++]);
+ Type *Ty = flattenPointerTypes(FullTy);
if (!Ty)
return error("Invalid record");
auto *PTy = dyn_cast<PointerType>(Ty);
if (!PTy)
return error("Invalid type for value");
- Ty = PTy->getElementType();
+ std::tie(FullTy, Ty) = getPointerElementTypes(FullTy);
AddrSpace = PTy->getAddressSpace();
} else {
AddrSpace = Record[OpNum++];
else
NewGA = GlobalIFunc::create(Ty, AddrSpace, getDecodedLinkage(Linkage), Name,
nullptr, TheModule);
+
+ assert(NewGA->getValueType() == flattenPointerTypes(FullTy) &&
+ "Incorrect fully structured type provided for GlobalIndirectSymbol");
// Old bitcode files didn't have visibility field.
// Local linkage must have default visibility.
if (OpNum != Record.size()) {
OpNum += 2;
}
- ValueList.push_back(NewGA);
+ FullTy = PointerType::get(FullTy, AddrSpace);
+ assert(NewGA->getType() == flattenPointerTypes(FullTy) &&
+ "Incorrect fully structured type provided for GlobalIndirectSymbol");
+ ValueList.push_back(NewGA, FullTy);
IndirectSymbolInits.push_back(std::make_pair(NewGA, Val));
return Error::success();
}
return Error::success();
}
-void BitcodeReader::propagateByValTypes(CallBase *CB) {
- for (unsigned i = 0; i < CB->getNumArgOperands(); ++i) {
- if (CB->paramHasAttr(i, Attribute::ByVal) &&
- !CB->getAttribute(i, Attribute::ByVal).getValueAsType()) {
- CB->removeParamAttr(i, Attribute::ByVal);
- CB->addParamAttr(
- i, Attribute::getWithByValType(
- Context,
- CB->getArgOperand(i)->getType()->getPointerElementType()));
- }
+void BitcodeReader::propagateByValTypes(CallBase *CB,
+ ArrayRef<Type *> ArgsFullTys) {
+ for (unsigned i = 0; i != CB->arg_size(); ++i) {
+ if (!CB->paramHasAttr(i, Attribute::ByVal))
+ continue;
+
+ CB->removeParamAttr(i, Attribute::ByVal);
+ CB->addParamAttr(
+ i, Attribute::getWithByValType(
+ Context, getPointerElementFlatType(ArgsFullTys[i])));
}
}
unsigned ModuleMDLoaderSize = MDLoader->size();
// Add all the function arguments to the value table.
- for (Argument &I : F->args())
- ValueList.push_back(&I);
-
+ unsigned ArgNo = 0;
+ FunctionType *FullFTy = FunctionTypes[F];
+ for (Argument &I : F->args()) {
+ assert(I.getType() == flattenPointerTypes(FullFTy->getParamType(ArgNo)) &&
+ "Incorrect fully specified type for Function Argument");
+ ValueList.push_back(&I, FullFTy->getParamType(ArgNo++));
+ }
unsigned NextValueNo = ValueList.size();
BasicBlock *CurBB = nullptr;
unsigned CurBBNo = 0;
// Read a record.
Record.clear();
Instruction *I = nullptr;
+ Type *FullTy = nullptr;
Expected<unsigned> MaybeBitCode = Stream.readRecord(Entry.ID, Record);
if (!MaybeBitCode)
return MaybeBitCode.takeError();
OpNum+2 != Record.size())
return error("Invalid record");
- Type *ResTy = getTypeByID(Record[OpNum]);
+ FullTy = getFullyStructuredTypeByID(Record[OpNum]);
+ Type *ResTy = flattenPointerTypes(FullTy);
int Opc = getDecodedCastOpcode(Record[OpNum + 1]);
if (Opc == -1 || !ResTy)
return error("Invalid record");
if (BitCode == bitc::FUNC_CODE_INST_GEP) {
InBounds = Record[OpNum++];
- Ty = getTypeByID(Record[OpNum++]);
+ FullTy = getFullyStructuredTypeByID(Record[OpNum++]);
+ Ty = flattenPointerTypes(FullTy);
} else {
InBounds = BitCode == bitc::FUNC_CODE_INST_INBOUNDS_GEP_OLD;
Ty = nullptr;
}
Value *BasePtr;
- if (getValueTypePair(Record, OpNum, NextValueNo, BasePtr))
+ Type *FullBaseTy = nullptr;
+ if (getValueTypePair(Record, OpNum, NextValueNo, BasePtr, &FullBaseTy))
return error("Invalid record");
- if (!Ty)
- Ty = cast<PointerType>(BasePtr->getType()->getScalarType())
- ->getElementType();
- else if (Ty !=
- cast<PointerType>(BasePtr->getType()->getScalarType())
- ->getElementType())
+ if (!Ty) {
+ std::tie(FullTy, Ty) =
+ getPointerElementTypes(FullBaseTy->getScalarType());
+ } else if (Ty != getPointerElementFlatType(FullBaseTy->getScalarType()))
return error(
"Explicit gep type does not match pointee type of pointer operand");
}
I = GetElementPtrInst::Create(Ty, BasePtr, GEPIdx);
+ FullTy = GetElementPtrInst::getGEPReturnType(FullTy, I, GEPIdx);
InstructionList.push_back(I);
if (InBounds)
// EXTRACTVAL: [opty, opval, n x indices]
unsigned OpNum = 0;
Value *Agg;
- if (getValueTypePair(Record, OpNum, NextValueNo, Agg))
+ if (getValueTypePair(Record, OpNum, NextValueNo, Agg, &FullTy))
return error("Invalid record");
unsigned RecSize = Record.size();
return error("EXTRACTVAL: Invalid instruction with 0 indices");
SmallVector<unsigned, 4> EXTRACTVALIdx;
- Type *CurTy = Agg->getType();
for (; OpNum != RecSize; ++OpNum) {
- bool IsArray = CurTy->isArrayTy();
- bool IsStruct = CurTy->isStructTy();
+ bool IsArray = FullTy->isArrayTy();
+ bool IsStruct = FullTy->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 >= CurTy->getStructNumElements())
+ if (IsStruct && Index >= FullTy->getStructNumElements())
return error("EXTRACTVAL: Invalid struct index");
- if (IsArray && Index >= CurTy->getArrayNumElements())
+ if (IsArray && Index >= FullTy->getArrayNumElements())
return error("EXTRACTVAL: Invalid array index");
EXTRACTVALIdx.push_back((unsigned)Index);
if (IsStruct)
- CurTy = CurTy->getStructElementType(Index);
+ FullTy = FullTy->getStructElementType(Index);
else
- CurTy = CurTy->getArrayElementType();
+ FullTy = FullTy->getArrayElementType();
}
I = ExtractValueInst::Create(Agg, EXTRACTVALIdx);
// INSERTVAL: [opty, opval, opty, opval, n x indices]
unsigned OpNum = 0;
Value *Agg;
- if (getValueTypePair(Record, OpNum, NextValueNo, Agg))
+ if (getValueTypePair(Record, OpNum, NextValueNo, Agg, &FullTy))
return error("Invalid record");
Value *Val;
if (getValueTypePair(Record, OpNum, NextValueNo, Val))
// handles select i1 ... in old bitcode
unsigned OpNum = 0;
Value *TrueVal, *FalseVal, *Cond;
- if (getValueTypePair(Record, OpNum, NextValueNo, TrueVal) ||
+ if (getValueTypePair(Record, OpNum, NextValueNo, TrueVal, &FullTy) ||
popValue(Record, OpNum, NextValueNo, TrueVal->getType(), FalseVal) ||
popValue(Record, OpNum, NextValueNo, Type::getInt1Ty(Context), Cond))
return error("Invalid record");
// handles select i1 or select [N x i1]
unsigned OpNum = 0;
Value *TrueVal, *FalseVal, *Cond;
- if (getValueTypePair(Record, OpNum, NextValueNo, TrueVal) ||
+ if (getValueTypePair(Record, OpNum, NextValueNo, TrueVal, &FullTy) ||
popValue(Record, OpNum, NextValueNo, TrueVal->getType(), FalseVal) ||
getValueTypePair(Record, OpNum, NextValueNo, Cond))
return error("Invalid record");
case bitc::FUNC_CODE_INST_EXTRACTELT: { // EXTRACTELT: [opty, opval, opval]
unsigned OpNum = 0;
Value *Vec, *Idx;
- if (getValueTypePair(Record, OpNum, NextValueNo, Vec) ||
+ if (getValueTypePair(Record, OpNum, NextValueNo, Vec, &FullTy) ||
getValueTypePair(Record, OpNum, NextValueNo, Idx))
return error("Invalid record");
if (!Vec->getType()->isVectorTy())
return error("Invalid type for value");
I = ExtractElementInst::Create(Vec, Idx);
+ FullTy = FullTy->getVectorElementType();
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))
+ if (getValueTypePair(Record, OpNum, NextValueNo, Vec, &FullTy))
return error("Invalid record");
if (!Vec->getType()->isVectorTy())
return error("Invalid type for value");
case bitc::FUNC_CODE_INST_SHUFFLEVEC: {// SHUFFLEVEC: [opval,ty,opval,opval]
unsigned OpNum = 0;
Value *Vec1, *Vec2, *Mask;
- if (getValueTypePair(Record, OpNum, NextValueNo, Vec1) ||
+ if (getValueTypePair(Record, OpNum, NextValueNo, Vec1, &FullTy) ||
popValue(Record, OpNum, NextValueNo, Vec1->getType(), Vec2))
return error("Invalid record");
if (!Vec1->getType()->isVectorTy() || !Vec2->getType()->isVectorTy())
return error("Invalid type for value");
I = new ShuffleVectorInst(Vec1, Vec2, Mask);
+ FullTy = VectorType::get(FullTy->getVectorElementType(),
+ Mask->getType()->getVectorNumElements());
InstructionList.push_back(I);
break;
}
BasicBlock *UnwindBB = getBasicBlock(Record[OpNum++]);
FunctionType *FTy = nullptr;
- if (CCInfo >> 13 & 1 &&
- !(FTy = dyn_cast<FunctionType>(getTypeByID(Record[OpNum++]))))
- return error("Explicit invoke type is not a function type");
+ FunctionType *FullFTy = nullptr;
+ if ((CCInfo >> 13) & 1) {
+ FullFTy =
+ dyn_cast<FunctionType>(getFullyStructuredTypeByID(Record[OpNum++]));
+ if (!FullFTy)
+ return error("Explicit invoke type is not a function type");
+ FTy = cast<FunctionType>(flattenPointerTypes(FullFTy));
+ }
Value *Callee;
- if (getValueTypePair(Record, OpNum, NextValueNo, Callee))
+ if (getValueTypePair(Record, OpNum, NextValueNo, Callee, &FullTy))
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>(CalleeTy->getElementType());
- if (!FTy)
+ FullFTy =
+ dyn_cast<FunctionType>(cast<PointerType>(FullTy)->getElementType());
+ if (!FullFTy)
return error("Callee is not of pointer to function type");
- } else if (CalleeTy->getElementType() != FTy)
+ FTy = cast<FunctionType>(flattenPointerTypes(FullFTy));
+ } else if (getPointerElementFlatType(FullTy) != 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> ArgsFullTys;
for (unsigned i = 0, e = FTy->getNumParams(); i != e; ++i, ++OpNum) {
Ops.push_back(getValue(Record, OpNum, NextValueNo,
FTy->getParamType(i)));
+ ArgsFullTys.push_back(FullFTy->getParamType(i));
if (!Ops.back())
return error("Invalid record");
}
// Read type/value pairs for varargs params.
while (OpNum != Record.size()) {
Value *Op;
- if (getValueTypePair(Record, OpNum, NextValueNo, Op))
+ Type *FullTy;
+ if (getValueTypePair(Record, OpNum, NextValueNo, Op, &FullTy))
return error("Invalid record");
Ops.push_back(Op);
+ ArgsFullTys.push_back(FullTy);
}
}
I = InvokeInst::Create(FTy, Callee, NormalBB, UnwindBB, Ops,
OperandBundles);
+ FullTy = FullFTy->getReturnType();
OperandBundles.clear();
InstructionList.push_back(I);
cast<InvokeInst>(I)->setCallingConv(
static_cast<CallingConv::ID>(CallingConv::MaxID & CCInfo));
cast<InvokeInst>(I)->setAttributes(PAL);
- propagateByValTypes(cast<CallBase>(I));
+ propagateByValTypes(cast<CallBase>(I), ArgsFullTys);
break;
}
IndirectDests.push_back(getBasicBlock(Record[OpNum++]));
FunctionType *FTy = nullptr;
- if (CCInfo >> bitc::CALL_EXPLICIT_TYPE & 1 &&
- !(FTy = dyn_cast<FunctionType>(getTypeByID(Record[OpNum++]))))
- return error("Explicit call type is not a function type");
+ FunctionType *FullFTy = nullptr;
+ if ((CCInfo >> bitc::CALL_EXPLICIT_TYPE) & 1) {
+ FullFTy =
+ dyn_cast<FunctionType>(getFullyStructuredTypeByID(Record[OpNum++]));
+ if (!FullFTy)
+ return error("Explicit call type is not a function type");
+ FTy = cast<FunctionType>(flattenPointerTypes(FullFTy));
+ }
Value *Callee;
- if (getValueTypePair(Record, OpNum, NextValueNo, Callee))
+ if (getValueTypePair(Record, OpNum, NextValueNo, Callee, &FullTy))
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>(OpTy->getElementType());
- if (!FTy)
+ FullFTy =
+ dyn_cast<FunctionType>(cast<PointerType>(FullTy)->getElementType());
+ if (!FullFTy)
return error("Callee is not of pointer to function type");
- } else if (OpTy->getElementType() != FTy)
+ FTy = cast<FunctionType>(flattenPointerTypes(FullFTy));
+ } else if (getPointerElementFlatType(FullTy) != FTy)
return error("Explicit call type does not match pointee type of "
"callee operand");
if (Record.size() < FTy->getNumParams() + OpNum)
I = CallBrInst::Create(FTy, Callee, DefaultDest, IndirectDests, Args,
OperandBundles);
+ FullTy = FullFTy->getReturnType();
OperandBundles.clear();
InstructionList.push_back(I);
cast<CallBrInst>(I)->setCallingConv(
case bitc::FUNC_CODE_INST_PHI: { // PHI: [ty, val0,bb0, ...]
if (Record.size() < 1 || ((Record.size()-1)&1))
return error("Invalid record");
- Type *Ty = getTypeByID(Record[0]);
+ FullTy = getFullyStructuredTypeByID(Record[0]);
+ Type *Ty = flattenPointerTypes(FullTy);
if (!Ty)
return error("Invalid record");
if (Record.size() < 4)
return error("Invalid record");
}
- Type *Ty = getTypeByID(Record[Idx++]);
+ FullTy = getFullyStructuredTypeByID(Record[Idx++]);
+ Type *Ty = flattenPointerTypes(FullTy);
if (!Ty)
return error("Invalid record");
if (BitCode == bitc::FUNC_CODE_INST_LANDINGPAD_OLD) {
SwiftErrorMask;
bool InAlloca = AlignRecord & InAllocaMask;
bool SwiftError = AlignRecord & SwiftErrorMask;
- Type *Ty = getTypeByID(Record[0]);
+ FullTy = getFullyStructuredTypeByID(Record[0]);
+ Type *Ty = flattenPointerTypes(FullTy);
if ((AlignRecord & ExplicitTypeMask) == 0) {
auto *PTy = dyn_cast_or_null<PointerType>(Ty);
if (!PTy)
return error("Old-style alloca with a non-pointer type");
- Ty = PTy->getElementType();
+ std::tie(FullTy, Ty) = getPointerElementTypes(FullTy);
}
Type *OpTy = getTypeByID(Record[1]);
Value *Size = getFnValueByID(Record[2], OpTy);
AI->setUsedWithInAlloca(InAlloca);
AI->setSwiftError(SwiftError);
I = AI;
+ FullTy = PointerType::get(FullTy, AS);
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) ||
+ if (getValueTypePair(Record, OpNum, NextValueNo, Op, &FullTy) ||
(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++]);
+ if (OpNum + 3 == Record.size()) {
+ FullTy = getFullyStructuredTypeByID(Record[OpNum++]);
+ Ty = flattenPointerTypes(FullTy);
+ } else
+ std::tie(FullTy, Ty) = getPointerElementTypes(FullTy);
+
if (Error Err = typeCheckLoadStoreInst(Ty, Op->getType()))
return Err;
- if (!Ty)
- Ty = cast<PointerType>(Op->getType())->getElementType();
unsigned Align;
if (Error Err = parseAlignmentValue(Record[OpNum], Align))
return Err;
I = new LoadInst(Ty, Op, "", Record[OpNum + 1], Align);
-
InstructionList.push_back(I);
break;
}
// LOADATOMIC: [opty, op, align, vol, ordering, ssid]
unsigned OpNum = 0;
Value *Op;
- if (getValueTypePair(Record, OpNum, NextValueNo, Op) ||
+ if (getValueTypePair(Record, OpNum, NextValueNo, Op, &FullTy) ||
(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++]);
+ if (OpNum + 5 == Record.size()) {
+ FullTy = getFullyStructuredTypeByID(Record[OpNum++]);
+ Ty = flattenPointerTypes(FullTy);
+ } else
+ std::tie(FullTy, Ty) = getPointerElementTypes(FullTy);
+
if (Error Err = typeCheckLoadStoreInst(Ty, Op->getType()))
return Err;
- if (!Ty)
- Ty = cast<PointerType>(Op->getType())->getElementType();
AtomicOrdering Ordering = getDecodedOrdering(Record[OpNum + 2]);
if (Ordering == AtomicOrdering::NotAtomic ||
if (Error Err = parseAlignmentValue(Record[OpNum], Align))
return Err;
I = new LoadInst(Ty, Op, "", Record[OpNum + 1], Align, Ordering, SSID);
-
InstructionList.push_back(I);
break;
}
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) ||
+ Type *FullTy;
+ if (getValueTypePair(Record, OpNum, NextValueNo, Ptr, &FullTy) ||
(BitCode == bitc::FUNC_CODE_INST_STORE
? getValueTypePair(Record, OpNum, NextValueNo, Val)
: popValue(Record, OpNum, NextValueNo,
- cast<PointerType>(Ptr->getType())->getElementType(),
- Val)) ||
+ getPointerElementFlatType(FullTy), Val)) ||
OpNum + 2 != Record.size())
return error("Invalid record");
// STOREATOMIC: [ptrty, ptr, val, align, vol, ordering, ssid]
unsigned OpNum = 0;
Value *Val, *Ptr;
- if (getValueTypePair(Record, OpNum, NextValueNo, Ptr) ||
+ Type *FullTy;
+ if (getValueTypePair(Record, OpNum, NextValueNo, Ptr, &FullTy) ||
!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)) ||
+ getPointerElementFlatType(FullTy), Val)) ||
OpNum + 4 != Record.size())
return error("Invalid record");
// failureordering?, isweak?]
unsigned OpNum = 0;
Value *Ptr, *Cmp, *New;
- if (getValueTypePair(Record, OpNum, NextValueNo, Ptr) ||
- (BitCode == bitc::FUNC_CODE_INST_CMPXCHG
- ? getValueTypePair(Record, OpNum, NextValueNo, Cmp)
- : popValue(Record, OpNum, NextValueNo,
- cast<PointerType>(Ptr->getType())->getElementType(),
- Cmp)) ||
- popValue(Record, OpNum, NextValueNo, Cmp->getType(), New) ||
+ if (getValueTypePair(Record, OpNum, NextValueNo, Ptr, &FullTy))
+ return error("Invalid record");
+
+ if (!isa<PointerType>(Ptr->getType()))
+ return error("Cmpxchg operand is not a pointer type");
+
+ if (BitCode == bitc::FUNC_CODE_INST_CMPXCHG) {
+ if (getValueTypePair(Record, OpNum, NextValueNo, Cmp, &FullTy))
+ return error("Invalid record");
+ } else if (popValue(Record, OpNum, NextValueNo,
+ getPointerElementFlatType(FullTy), Cmp))
+ return error("Invalid record");
+ else
+ FullTy = cast<PointerType>(FullTy)->getElementType();
+
+ if (popValue(Record, OpNum, NextValueNo, Cmp->getType(), New) ||
Record.size() < OpNum + 3 || Record.size() > OpNum + 5)
return error("Invalid record");
+
AtomicOrdering SuccessOrdering = getDecodedOrdering(Record[OpNum + 1]);
if (SuccessOrdering == AtomicOrdering::NotAtomic ||
SuccessOrdering == AtomicOrdering::Unordered)
I = new AtomicCmpXchgInst(Ptr, Cmp, New, SuccessOrdering, FailureOrdering,
SSID);
+ FullTy = StructType::get(Context, {FullTy, Type::getInt1Ty(Context)});
cast<AtomicCmpXchgInst>(I)->setVolatile(Record[OpNum]);
if (Record.size() < 8) {
// expecting the first component of a modern cmpxchg.
CurBB->getInstList().push_back(I);
I = ExtractValueInst::Create(I, 0);
+ FullTy = cast<StructType>(FullTy)->getElementType(0);
} else {
cast<AtomicCmpXchgInst>(I)->setWeak(Record[OpNum+4]);
}
// ATOMICRMW:[ptrty, ptr, val, op, vol, ordering, ssid]
unsigned OpNum = 0;
Value *Ptr, *Val;
- if (getValueTypePair(Record, OpNum, NextValueNo, Ptr) ||
+ if (getValueTypePair(Record, OpNum, NextValueNo, Ptr, &FullTy) ||
!isa<PointerType>(Ptr->getType()) ||
popValue(Record, OpNum, NextValueNo,
- cast<PointerType>(Ptr->getType())->getElementType(), Val) ||
- OpNum+4 != Record.size())
+ getPointerElementFlatType(FullTy), Val) ||
+ OpNum + 4 != Record.size())
return error("Invalid record");
AtomicRMWInst::BinOp Operation = getDecodedRMWOperation(Record[OpNum]);
if (Operation < AtomicRMWInst::FIRST_BINOP ||
return error("Invalid record");
SyncScope::ID SSID = getDecodedSyncScopeID(Record[OpNum + 3]);
I = new AtomicRMWInst(Operation, Ptr, Val, Ordering, SSID);
+ FullTy = getPointerElementFlatType(FullTy);
cast<AtomicRMWInst>(I)->setVolatile(Record[OpNum+1]);
InstructionList.push_back(I);
break;
}
FunctionType *FTy = nullptr;
- if (CCInfo >> bitc::CALL_EXPLICIT_TYPE & 1 &&
- !(FTy = dyn_cast<FunctionType>(getTypeByID(Record[OpNum++]))))
- return error("Explicit call type is not a function type");
+ FunctionType *FullFTy = nullptr;
+ if ((CCInfo >> bitc::CALL_EXPLICIT_TYPE) & 1) {
+ FullFTy =
+ dyn_cast<FunctionType>(getFullyStructuredTypeByID(Record[OpNum++]));
+ if (!FullFTy)
+ return error("Explicit call type is not a function type");
+ FTy = cast<FunctionType>(flattenPointerTypes(FullFTy));
+ }
Value *Callee;
- if (getValueTypePair(Record, OpNum, NextValueNo, Callee))
+ if (getValueTypePair(Record, OpNum, NextValueNo, Callee, &FullTy))
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>(OpTy->getElementType());
- if (!FTy)
+ FullFTy =
+ dyn_cast<FunctionType>(cast<PointerType>(FullTy)->getElementType());
+ if (!FullFTy)
return error("Callee is not of pointer to function type");
- } else if (OpTy->getElementType() != FTy)
+ FTy = cast<FunctionType>(flattenPointerTypes(FullFTy));
+ } else if (getPointerElementFlatType(FullTy) != 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> ArgsFullTys;
// Read the fixed params.
for (unsigned i = 0, e = FTy->getNumParams(); i != e; ++i, ++OpNum) {
if (FTy->getParamType(i)->isLabelTy())
else
Args.push_back(getValue(Record, OpNum, NextValueNo,
FTy->getParamType(i)));
+ ArgsFullTys.push_back(FullFTy->getParamType(i));
if (!Args.back())
return error("Invalid record");
}
} else {
while (OpNum != Record.size()) {
Value *Op;
- if (getValueTypePair(Record, OpNum, NextValueNo, Op))
+ Type *FullTy;
+ if (getValueTypePair(Record, OpNum, NextValueNo, Op, &FullTy))
return error("Invalid record");
Args.push_back(Op);
+ ArgsFullTys.push_back(FullTy);
}
}
I = CallInst::Create(FTy, Callee, Args, OperandBundles);
+ FullTy = FullFTy->getReturnType();
OperandBundles.clear();
InstructionList.push_back(I);
cast<CallInst>(I)->setCallingConv(
TCK = CallInst::TCK_NoTail;
cast<CallInst>(I)->setTailCallKind(TCK);
cast<CallInst>(I)->setAttributes(PAL);
- propagateByValTypes(cast<CallBase>(I));
+ propagateByValTypes(cast<CallBase>(I), ArgsFullTys);
if (FMF.any()) {
if (!isa<FPMathOperator>(I))
return error("Fast-math-flags specified for call without "
return error("Invalid record");
Type *OpTy = getTypeByID(Record[0]);
Value *Op = getValue(Record, 1, NextValueNo, OpTy);
- Type *ResTy = getTypeByID(Record[2]);
+ FullTy = getFullyStructuredTypeByID(Record[2]);
+ Type *ResTy = flattenPointerTypes(FullTy);
if (!OpTy || !Op || !ResTy)
return error("Invalid record");
I = new VAArgInst(Op, ResTy);
}
// Non-void values get registered in the value table for future use.
- if (I && !I->getType()->isVoidTy())
- ValueList.assignValue(I, NextValueNo++);
+ if (I && !I->getType()->isVoidTy()) {
+ if (!FullTy) {
+ FullTy = I->getType();
+ assert(
+ !FullTy->isPointerTy() && !isa<StructType>(FullTy) &&
+ !isa<ArrayType>(FullTy) &&
+ (!isa<VectorType>(FullTy) ||
+ FullTy->getVectorElementType()->isFloatingPointTy() ||
+ FullTy->getVectorElementType()->isIntegerTy()) &&
+ "Structured types must be assigned with corresponding non-opaque "
+ "pointer type");
+ }
+
+ assert(I->getType() == flattenPointerTypes(FullTy) &&
+ "Incorrect fully structured type provided for Instruction");
+ ValueList.assignValue(I, NextValueNo++, FullTy);
+ }
}
OutOfRecordLoop: