in llvm/lib/Bitcode/Reader/MetadataLoader.cpp [1137:2121]
Error MetadataLoader::MetadataLoaderImpl::parseOneMetadata(
SmallVectorImpl<uint64_t> &Record, unsigned Code,
PlaceholderQueue &Placeholders, StringRef Blob, unsigned &NextMetadataNo) {
bool IsDistinct = false;
auto getMD = [&](unsigned ID) -> Metadata * {
if (ID < MDStringRef.size())
return lazyLoadOneMDString(ID);
if (!IsDistinct) {
if (auto *MD = MetadataList.lookup(ID))
return MD;
// If lazy-loading is enabled, we try recursively to load the operand
// instead of creating a temporary.
if (ID < (MDStringRef.size() + GlobalMetadataBitPosIndex.size())) {
// Create a temporary for the node that is referencing the operand we
// will lazy-load. It is needed before recursing in case there are
// uniquing cycles.
MetadataList.getMetadataFwdRef(NextMetadataNo);
lazyLoadOneMetadata(ID, Placeholders);
return MetadataList.lookup(ID);
}
// Return a temporary.
return MetadataList.getMetadataFwdRef(ID);
}
if (auto *MD = MetadataList.getMetadataIfResolved(ID))
return MD;
return &Placeholders.getPlaceholderOp(ID);
};
auto getMDOrNull = [&](unsigned ID) -> Metadata * {
if (ID)
return getMD(ID - 1);
return nullptr;
};
auto getMDOrNullWithoutPlaceholders = [&](unsigned ID) -> Metadata * {
if (ID)
return MetadataList.getMetadataFwdRef(ID - 1);
return nullptr;
};
auto getMDString = [&](unsigned ID) -> MDString * {
// This requires that the ID is not really a forward reference. In
// particular, the MDString must already have been resolved.
auto MDS = getMDOrNull(ID);
return cast_or_null<MDString>(MDS);
};
// Support for old type refs.
auto getDITypeRefOrNull = [&](unsigned ID) {
return MetadataList.upgradeTypeRef(getMDOrNull(ID));
};
#define GET_OR_DISTINCT(CLASS, ARGS) \
(IsDistinct ? CLASS::getDistinct ARGS : CLASS::get ARGS)
switch (Code) {
default: // Default behavior: ignore.
break;
case bitc::METADATA_NAME: {
// Read name of the named metadata.
SmallString<8> Name(Record.begin(), Record.end());
Record.clear();
if (Error E = Stream.ReadCode().moveInto(Code))
return E;
++NumMDRecordLoaded;
if (Expected<unsigned> MaybeNextBitCode = Stream.readRecord(Code, Record)) {
if (MaybeNextBitCode.get() != bitc::METADATA_NAMED_NODE)
return error("METADATA_NAME not followed by METADATA_NAMED_NODE");
} else
return MaybeNextBitCode.takeError();
// Read named metadata elements.
unsigned Size = Record.size();
NamedMDNode *NMD = TheModule.getOrInsertNamedMetadata(Name);
for (unsigned i = 0; i != Size; ++i) {
MDNode *MD = MetadataList.getMDNodeFwdRefOrNull(Record[i]);
if (!MD)
return error("Invalid named metadata: expect fwd ref to MDNode");
NMD->addOperand(MD);
}
break;
}
case bitc::METADATA_OLD_FN_NODE: {
// Deprecated, but still needed to read old bitcode files.
// This is a LocalAsMetadata record, the only type of function-local
// metadata.
if (Record.size() % 2 == 1)
return error("Invalid record");
// If this isn't a LocalAsMetadata record, we're dropping it. This used
// to be legal, but there's no upgrade path.
auto dropRecord = [&] {
MetadataList.assignValue(MDNode::get(Context, None), NextMetadataNo);
NextMetadataNo++;
};
if (Record.size() != 2) {
dropRecord();
break;
}
Type *Ty = getTypeByID(Record[0]);
if (Ty->isMetadataTy() || Ty->isVoidTy()) {
dropRecord();
break;
}
MetadataList.assignValue(
LocalAsMetadata::get(ValueList.getValueFwdRef(Record[1], Ty)),
NextMetadataNo);
NextMetadataNo++;
break;
}
case bitc::METADATA_OLD_NODE: {
// Deprecated, but still needed to read old bitcode files.
if (Record.size() % 2 == 1)
return error("Invalid record");
unsigned Size = Record.size();
SmallVector<Metadata *, 8> Elts;
for (unsigned i = 0; i != Size; i += 2) {
Type *Ty = getTypeByID(Record[i]);
if (!Ty)
return error("Invalid record");
if (Ty->isMetadataTy())
Elts.push_back(getMD(Record[i + 1]));
else if (!Ty->isVoidTy()) {
auto *MD =
ValueAsMetadata::get(ValueList.getValueFwdRef(Record[i + 1], Ty));
assert(isa<ConstantAsMetadata>(MD) &&
"Expected non-function-local metadata");
Elts.push_back(MD);
} else
Elts.push_back(nullptr);
}
MetadataList.assignValue(MDNode::get(Context, Elts), NextMetadataNo);
NextMetadataNo++;
break;
}
case bitc::METADATA_VALUE: {
if (Record.size() != 2)
return error("Invalid record");
Type *Ty = getTypeByID(Record[0]);
if (Ty->isMetadataTy() || Ty->isVoidTy())
return error("Invalid record");
MetadataList.assignValue(
ValueAsMetadata::get(ValueList.getValueFwdRef(Record[1], Ty)),
NextMetadataNo);
NextMetadataNo++;
break;
}
case bitc::METADATA_DISTINCT_NODE:
IsDistinct = true;
LLVM_FALLTHROUGH;
case bitc::METADATA_NODE: {
SmallVector<Metadata *, 8> Elts;
Elts.reserve(Record.size());
for (unsigned ID : Record)
Elts.push_back(getMDOrNull(ID));
MetadataList.assignValue(IsDistinct ? MDNode::getDistinct(Context, Elts)
: MDNode::get(Context, Elts),
NextMetadataNo);
NextMetadataNo++;
break;
}
case bitc::METADATA_LOCATION: {
if (Record.size() != 5 && Record.size() != 6)
return error("Invalid record");
IsDistinct = Record[0];
unsigned Line = Record[1];
unsigned Column = Record[2];
Metadata *Scope = getMD(Record[3]);
Metadata *InlinedAt = getMDOrNull(Record[4]);
bool ImplicitCode = Record.size() == 6 && Record[5];
MetadataList.assignValue(
GET_OR_DISTINCT(DILocation, (Context, Line, Column, Scope, InlinedAt,
ImplicitCode)),
NextMetadataNo);
NextMetadataNo++;
break;
}
case bitc::METADATA_GENERIC_DEBUG: {
if (Record.size() < 4)
return error("Invalid record");
IsDistinct = Record[0];
unsigned Tag = Record[1];
unsigned Version = Record[2];
if (Tag >= 1u << 16 || Version != 0)
return error("Invalid record");
auto *Header = getMDString(Record[3]);
SmallVector<Metadata *, 8> DwarfOps;
for (unsigned I = 4, E = Record.size(); I != E; ++I)
DwarfOps.push_back(getMDOrNull(Record[I]));
MetadataList.assignValue(
GET_OR_DISTINCT(GenericDINode, (Context, Tag, Header, DwarfOps)),
NextMetadataNo);
NextMetadataNo++;
break;
}
case bitc::METADATA_SUBRANGE: {
Metadata *Val = nullptr;
// Operand 'count' is interpreted as:
// - Signed integer (version 0)
// - Metadata node (version 1)
// Operand 'lowerBound' is interpreted as:
// - Signed integer (version 0 and 1)
// - Metadata node (version 2)
// Operands 'upperBound' and 'stride' are interpreted as:
// - Metadata node (version 2)
switch (Record[0] >> 1) {
case 0:
Val = GET_OR_DISTINCT(DISubrange,
(Context, Record[1], unrotateSign(Record[2])));
break;
case 1:
Val = GET_OR_DISTINCT(DISubrange, (Context, getMDOrNull(Record[1]),
unrotateSign(Record[2])));
break;
case 2:
Val = GET_OR_DISTINCT(
DISubrange, (Context, getMDOrNull(Record[1]), getMDOrNull(Record[2]),
getMDOrNull(Record[3]), getMDOrNull(Record[4])));
break;
default:
return error("Invalid record: Unsupported version of DISubrange");
}
MetadataList.assignValue(Val, NextMetadataNo);
IsDistinct = Record[0] & 1;
NextMetadataNo++;
break;
}
case bitc::METADATA_GENERIC_SUBRANGE: {
Metadata *Val = nullptr;
Val = GET_OR_DISTINCT(DIGenericSubrange,
(Context, getMDOrNull(Record[1]),
getMDOrNull(Record[2]), getMDOrNull(Record[3]),
getMDOrNull(Record[4])));
MetadataList.assignValue(Val, NextMetadataNo);
IsDistinct = Record[0] & 1;
NextMetadataNo++;
break;
}
case bitc::METADATA_ENUMERATOR: {
if (Record.size() < 3)
return error("Invalid record");
IsDistinct = Record[0] & 1;
bool IsUnsigned = Record[0] & 2;
bool IsBigInt = Record[0] & 4;
APInt Value;
if (IsBigInt) {
const uint64_t BitWidth = Record[1];
const size_t NumWords = Record.size() - 3;
Value = readWideAPInt(makeArrayRef(&Record[3], NumWords), BitWidth);
} else
Value = APInt(64, unrotateSign(Record[1]), !IsUnsigned);
MetadataList.assignValue(
GET_OR_DISTINCT(DIEnumerator,
(Context, Value, IsUnsigned, getMDString(Record[2]))),
NextMetadataNo);
NextMetadataNo++;
break;
}
case bitc::METADATA_BASIC_TYPE: {
if (Record.size() < 6 || Record.size() > 7)
return error("Invalid record");
IsDistinct = Record[0];
DINode::DIFlags Flags = (Record.size() > 6)
? static_cast<DINode::DIFlags>(Record[6])
: DINode::FlagZero;
MetadataList.assignValue(
GET_OR_DISTINCT(DIBasicType,
(Context, Record[1], getMDString(Record[2]), Record[3],
Record[4], Record[5], Flags)),
NextMetadataNo);
NextMetadataNo++;
break;
}
case bitc::METADATA_STRING_TYPE: {
if (Record.size() != 8)
return error("Invalid record");
IsDistinct = Record[0];
MetadataList.assignValue(
GET_OR_DISTINCT(DIStringType,
(Context, Record[1], getMDString(Record[2]),
getMDOrNull(Record[3]), getMDOrNull(Record[4]),
Record[5], Record[6], Record[7])),
NextMetadataNo);
NextMetadataNo++;
break;
}
case bitc::METADATA_DERIVED_TYPE: {
if (Record.size() < 12 || Record.size() > 14)
return error("Invalid record");
// DWARF address space is encoded as N->getDWARFAddressSpace() + 1. 0 means
// that there is no DWARF address space associated with DIDerivedType.
Optional<unsigned> DWARFAddressSpace;
if (Record.size() > 12 && Record[12])
DWARFAddressSpace = Record[12] - 1;
Metadata *Annotations = nullptr;
if (Record.size() > 13 && Record[13])
Annotations = getMDOrNull(Record[13]);
IsDistinct = Record[0];
DINode::DIFlags Flags = static_cast<DINode::DIFlags>(Record[10]);
MetadataList.assignValue(
GET_OR_DISTINCT(DIDerivedType,
(Context, Record[1], getMDString(Record[2]),
getMDOrNull(Record[3]), Record[4],
getDITypeRefOrNull(Record[5]),
getDITypeRefOrNull(Record[6]), Record[7], Record[8],
Record[9], DWARFAddressSpace, Flags,
getDITypeRefOrNull(Record[11]), Annotations)),
NextMetadataNo);
NextMetadataNo++;
break;
}
case bitc::METADATA_COMPOSITE_TYPE: {
if (Record.size() < 16 || Record.size() > 22)
return error("Invalid record");
// If we have a UUID and this is not a forward declaration, lookup the
// mapping.
IsDistinct = Record[0] & 0x1;
bool IsNotUsedInTypeRef = Record[0] >= 2;
unsigned Tag = Record[1];
MDString *Name = getMDString(Record[2]);
Metadata *File = getMDOrNull(Record[3]);
unsigned Line = Record[4];
Metadata *Scope = getDITypeRefOrNull(Record[5]);
Metadata *BaseType = nullptr;
uint64_t SizeInBits = Record[7];
if (Record[8] > (uint64_t)std::numeric_limits<uint32_t>::max())
return error("Alignment value is too large");
uint32_t AlignInBits = Record[8];
uint64_t OffsetInBits = 0;
DINode::DIFlags Flags = static_cast<DINode::DIFlags>(Record[10]);
Metadata *Elements = nullptr;
unsigned RuntimeLang = Record[12];
Metadata *VTableHolder = nullptr;
Metadata *TemplateParams = nullptr;
Metadata *Discriminator = nullptr;
Metadata *DataLocation = nullptr;
Metadata *Associated = nullptr;
Metadata *Allocated = nullptr;
Metadata *Rank = nullptr;
Metadata *Annotations = nullptr;
auto *Identifier = getMDString(Record[15]);
// If this module is being parsed so that it can be ThinLTO imported
// into another module, composite types only need to be imported
// as type declarations (unless full type definitions requested).
// Create type declarations up front to save memory. Also, buildODRType
// handles the case where this is type ODRed with a definition needed
// by the importing module, in which case the existing definition is
// used.
if (IsImporting && !ImportFullTypeDefinitions && Identifier &&
(Tag == dwarf::DW_TAG_enumeration_type ||
Tag == dwarf::DW_TAG_class_type ||
Tag == dwarf::DW_TAG_structure_type ||
Tag == dwarf::DW_TAG_union_type)) {
Flags = Flags | DINode::FlagFwdDecl;
} else {
BaseType = getDITypeRefOrNull(Record[6]);
OffsetInBits = Record[9];
Elements = getMDOrNull(Record[11]);
VTableHolder = getDITypeRefOrNull(Record[13]);
TemplateParams = getMDOrNull(Record[14]);
if (Record.size() > 16)
Discriminator = getMDOrNull(Record[16]);
if (Record.size() > 17)
DataLocation = getMDOrNull(Record[17]);
if (Record.size() > 19) {
Associated = getMDOrNull(Record[18]);
Allocated = getMDOrNull(Record[19]);
}
if (Record.size() > 20) {
Rank = getMDOrNull(Record[20]);
}
if (Record.size() > 21) {
Annotations = getMDOrNull(Record[21]);
}
}
DICompositeType *CT = nullptr;
if (Identifier)
CT = DICompositeType::buildODRType(
Context, *Identifier, Tag, Name, File, Line, Scope, BaseType,
SizeInBits, AlignInBits, OffsetInBits, Flags, Elements, RuntimeLang,
VTableHolder, TemplateParams, Discriminator, DataLocation, Associated,
Allocated, Rank, Annotations);
// Create a node if we didn't get a lazy ODR type.
if (!CT)
CT = GET_OR_DISTINCT(DICompositeType,
(Context, Tag, Name, File, Line, Scope, BaseType,
SizeInBits, AlignInBits, OffsetInBits, Flags,
Elements, RuntimeLang, VTableHolder, TemplateParams,
Identifier, Discriminator, DataLocation, Associated,
Allocated, Rank, Annotations));
if (!IsNotUsedInTypeRef && Identifier)
MetadataList.addTypeRef(*Identifier, *cast<DICompositeType>(CT));
MetadataList.assignValue(CT, NextMetadataNo);
NextMetadataNo++;
break;
}
case bitc::METADATA_SUBROUTINE_TYPE: {
if (Record.size() < 3 || Record.size() > 4)
return error("Invalid record");
bool IsOldTypeRefArray = Record[0] < 2;
unsigned CC = (Record.size() > 3) ? Record[3] : 0;
IsDistinct = Record[0] & 0x1;
DINode::DIFlags Flags = static_cast<DINode::DIFlags>(Record[1]);
Metadata *Types = getMDOrNull(Record[2]);
if (LLVM_UNLIKELY(IsOldTypeRefArray))
Types = MetadataList.upgradeTypeRefArray(Types);
MetadataList.assignValue(
GET_OR_DISTINCT(DISubroutineType, (Context, Flags, CC, Types)),
NextMetadataNo);
NextMetadataNo++;
break;
}
case bitc::METADATA_MODULE: {
if (Record.size() < 5 || Record.size() > 9)
return error("Invalid record");
unsigned Offset = Record.size() >= 8 ? 2 : 1;
IsDistinct = Record[0];
MetadataList.assignValue(
GET_OR_DISTINCT(
DIModule,
(Context, Record.size() >= 8 ? getMDOrNull(Record[1]) : nullptr,
getMDOrNull(Record[0 + Offset]), getMDString(Record[1 + Offset]),
getMDString(Record[2 + Offset]), getMDString(Record[3 + Offset]),
getMDString(Record[4 + Offset]),
Record.size() <= 7 ? 0 : Record[7],
Record.size() <= 8 ? false : Record[8])),
NextMetadataNo);
NextMetadataNo++;
break;
}
case bitc::METADATA_FILE: {
if (Record.size() != 3 && Record.size() != 5 && Record.size() != 6)
return error("Invalid record");
IsDistinct = Record[0];
Optional<DIFile::ChecksumInfo<MDString *>> Checksum;
// The BitcodeWriter writes null bytes into Record[3:4] when the Checksum
// is not present. This matches up with the old internal representation,
// and the old encoding for CSK_None in the ChecksumKind. The new
// representation reserves the value 0 in the ChecksumKind to continue to
// encode None in a backwards-compatible way.
if (Record.size() > 4 && Record[3] && Record[4])
Checksum.emplace(static_cast<DIFile::ChecksumKind>(Record[3]),
getMDString(Record[4]));
MetadataList.assignValue(
GET_OR_DISTINCT(
DIFile,
(Context, getMDString(Record[1]), getMDString(Record[2]), Checksum,
Record.size() > 5 ? Optional<MDString *>(getMDString(Record[5]))
: None)),
NextMetadataNo);
NextMetadataNo++;
break;
}
case bitc::METADATA_COMPILE_UNIT: {
if (Record.size() < 14 || Record.size() > 22)
return error("Invalid record");
// Ignore Record[0], which indicates whether this compile unit is
// distinct. It's always distinct.
IsDistinct = true;
auto *CU = DICompileUnit::getDistinct(
Context, Record[1], getMDOrNull(Record[2]), getMDString(Record[3]),
Record[4], getMDString(Record[5]), Record[6], getMDString(Record[7]),
Record[8], getMDOrNull(Record[9]), getMDOrNull(Record[10]),
getMDOrNull(Record[12]), getMDOrNull(Record[13]),
Record.size() <= 15 ? nullptr : getMDOrNull(Record[15]),
Record.size() <= 14 ? 0 : Record[14],
Record.size() <= 16 ? true : Record[16],
Record.size() <= 17 ? false : Record[17],
Record.size() <= 18 ? 0 : Record[18],
Record.size() <= 19 ? false : Record[19],
Record.size() <= 20 ? nullptr : getMDString(Record[20]),
Record.size() <= 21 ? nullptr : getMDString(Record[21]));
MetadataList.assignValue(CU, NextMetadataNo);
NextMetadataNo++;
// Move the Upgrade the list of subprograms.
if (Metadata *SPs = getMDOrNullWithoutPlaceholders(Record[11]))
CUSubprograms.push_back({CU, SPs});
break;
}
case bitc::METADATA_SUBPROGRAM: {
if (Record.size() < 18 || Record.size() > 21)
return error("Invalid record");
bool HasSPFlags = Record[0] & 4;
DINode::DIFlags Flags;
DISubprogram::DISPFlags SPFlags;
if (!HasSPFlags)
Flags = static_cast<DINode::DIFlags>(Record[11 + 2]);
else {
Flags = static_cast<DINode::DIFlags>(Record[11]);
SPFlags = static_cast<DISubprogram::DISPFlags>(Record[9]);
}
// Support for old metadata when
// subprogram specific flags are placed in DIFlags.
const unsigned DIFlagMainSubprogram = 1 << 21;
bool HasOldMainSubprogramFlag = Flags & DIFlagMainSubprogram;
if (HasOldMainSubprogramFlag)
// Remove old DIFlagMainSubprogram from DIFlags.
// Note: This assumes that any future use of bit 21 defaults to it
// being 0.
Flags &= ~static_cast<DINode::DIFlags>(DIFlagMainSubprogram);
if (HasOldMainSubprogramFlag && HasSPFlags)
SPFlags |= DISubprogram::SPFlagMainSubprogram;
else if (!HasSPFlags)
SPFlags = DISubprogram::toSPFlags(
/*IsLocalToUnit=*/Record[7], /*IsDefinition=*/Record[8],
/*IsOptimized=*/Record[14], /*Virtuality=*/Record[11],
/*IsMainSubprogram=*/HasOldMainSubprogramFlag);
// All definitions should be distinct.
IsDistinct = (Record[0] & 1) || (SPFlags & DISubprogram::SPFlagDefinition);
// Version 1 has a Function as Record[15].
// Version 2 has removed Record[15].
// Version 3 has the Unit as Record[15].
// Version 4 added thisAdjustment.
// Version 5 repacked flags into DISPFlags, changing many element numbers.
bool HasUnit = Record[0] & 2;
if (!HasSPFlags && HasUnit && Record.size() < 19)
return error("Invalid record");
if (HasSPFlags && !HasUnit)
return error("Invalid record");
// Accommodate older formats.
bool HasFn = false;
bool HasThisAdj = true;
bool HasThrownTypes = true;
bool HasAnnotations = false;
unsigned OffsetA = 0;
unsigned OffsetB = 0;
if (!HasSPFlags) {
OffsetA = 2;
OffsetB = 2;
if (Record.size() >= 19) {
HasFn = !HasUnit;
OffsetB++;
}
HasThisAdj = Record.size() >= 20;
HasThrownTypes = Record.size() >= 21;
} else {
HasAnnotations = Record.size() >= 19;
}
Metadata *CUorFn = getMDOrNull(Record[12 + OffsetB]);
DISubprogram *SP = GET_OR_DISTINCT(
DISubprogram,
(Context,
getDITypeRefOrNull(Record[1]), // scope
getMDString(Record[2]), // name
getMDString(Record[3]), // linkageName
getMDOrNull(Record[4]), // file
Record[5], // line
getMDOrNull(Record[6]), // type
Record[7 + OffsetA], // scopeLine
getDITypeRefOrNull(Record[8 + OffsetA]), // containingType
Record[10 + OffsetA], // virtualIndex
HasThisAdj ? Record[16 + OffsetB] : 0, // thisAdjustment
Flags, // flags
SPFlags, // SPFlags
HasUnit ? CUorFn : nullptr, // unit
getMDOrNull(Record[13 + OffsetB]), // templateParams
getMDOrNull(Record[14 + OffsetB]), // declaration
getMDOrNull(Record[15 + OffsetB]), // retainedNodes
HasThrownTypes ? getMDOrNull(Record[17 + OffsetB])
: nullptr, // thrownTypes
HasAnnotations ? getMDOrNull(Record[18 + OffsetB])
: nullptr // annotations
));
MetadataList.assignValue(SP, NextMetadataNo);
NextMetadataNo++;
// Upgrade sp->function mapping to function->sp mapping.
if (HasFn) {
if (auto *CMD = dyn_cast_or_null<ConstantAsMetadata>(CUorFn))
if (auto *F = dyn_cast<Function>(CMD->getValue())) {
if (F->isMaterializable())
// Defer until materialized; unmaterialized functions may not have
// metadata.
FunctionsWithSPs[F] = SP;
else if (!F->empty())
F->setSubprogram(SP);
}
}
break;
}
case bitc::METADATA_LEXICAL_BLOCK: {
if (Record.size() != 5)
return error("Invalid record");
IsDistinct = Record[0];
MetadataList.assignValue(
GET_OR_DISTINCT(DILexicalBlock,
(Context, getMDOrNull(Record[1]),
getMDOrNull(Record[2]), Record[3], Record[4])),
NextMetadataNo);
NextMetadataNo++;
break;
}
case bitc::METADATA_LEXICAL_BLOCK_FILE: {
if (Record.size() != 4)
return error("Invalid record");
IsDistinct = Record[0];
MetadataList.assignValue(
GET_OR_DISTINCT(DILexicalBlockFile,
(Context, getMDOrNull(Record[1]),
getMDOrNull(Record[2]), Record[3])),
NextMetadataNo);
NextMetadataNo++;
break;
}
case bitc::METADATA_COMMON_BLOCK: {
IsDistinct = Record[0] & 1;
MetadataList.assignValue(
GET_OR_DISTINCT(DICommonBlock,
(Context, getMDOrNull(Record[1]),
getMDOrNull(Record[2]), getMDString(Record[3]),
getMDOrNull(Record[4]), Record[5])),
NextMetadataNo);
NextMetadataNo++;
break;
}
case bitc::METADATA_NAMESPACE: {
// Newer versions of DINamespace dropped file and line.
MDString *Name;
if (Record.size() == 3)
Name = getMDString(Record[2]);
else if (Record.size() == 5)
Name = getMDString(Record[3]);
else
return error("Invalid record");
IsDistinct = Record[0] & 1;
bool ExportSymbols = Record[0] & 2;
MetadataList.assignValue(
GET_OR_DISTINCT(DINamespace,
(Context, getMDOrNull(Record[1]), Name, ExportSymbols)),
NextMetadataNo);
NextMetadataNo++;
break;
}
case bitc::METADATA_MACRO: {
if (Record.size() != 5)
return error("Invalid record");
IsDistinct = Record[0];
MetadataList.assignValue(
GET_OR_DISTINCT(DIMacro,
(Context, Record[1], Record[2], getMDString(Record[3]),
getMDString(Record[4]))),
NextMetadataNo);
NextMetadataNo++;
break;
}
case bitc::METADATA_MACRO_FILE: {
if (Record.size() != 5)
return error("Invalid record");
IsDistinct = Record[0];
MetadataList.assignValue(
GET_OR_DISTINCT(DIMacroFile,
(Context, Record[1], Record[2], getMDOrNull(Record[3]),
getMDOrNull(Record[4]))),
NextMetadataNo);
NextMetadataNo++;
break;
}
case bitc::METADATA_TEMPLATE_TYPE: {
if (Record.size() < 3 || Record.size() > 4)
return error("Invalid record");
IsDistinct = Record[0];
MetadataList.assignValue(
GET_OR_DISTINCT(DITemplateTypeParameter,
(Context, getMDString(Record[1]),
getDITypeRefOrNull(Record[2]),
(Record.size() == 4) ? getMDOrNull(Record[3])
: getMDOrNull(false))),
NextMetadataNo);
NextMetadataNo++;
break;
}
case bitc::METADATA_TEMPLATE_VALUE: {
if (Record.size() < 5 || Record.size() > 6)
return error("Invalid record");
IsDistinct = Record[0];
MetadataList.assignValue(
GET_OR_DISTINCT(
DITemplateValueParameter,
(Context, Record[1], getMDString(Record[2]),
getDITypeRefOrNull(Record[3]),
(Record.size() == 6) ? getMDOrNull(Record[4]) : getMDOrNull(false),
(Record.size() == 6) ? getMDOrNull(Record[5])
: getMDOrNull(Record[4]))),
NextMetadataNo);
NextMetadataNo++;
break;
}
case bitc::METADATA_GLOBAL_VAR: {
if (Record.size() < 11 || Record.size() > 13)
return error("Invalid record");
IsDistinct = Record[0] & 1;
unsigned Version = Record[0] >> 1;
if (Version == 2) {
Metadata *Annotations = nullptr;
if (Record.size() > 12)
Annotations = getMDOrNull(Record[12]);
MetadataList.assignValue(
GET_OR_DISTINCT(DIGlobalVariable,
(Context, getMDOrNull(Record[1]),
getMDString(Record[2]), getMDString(Record[3]),
getMDOrNull(Record[4]), Record[5],
getDITypeRefOrNull(Record[6]), Record[7], Record[8],
getMDOrNull(Record[9]), getMDOrNull(Record[10]),
Record[11], Annotations)),
NextMetadataNo);
NextMetadataNo++;
} else if (Version == 1) {
// No upgrade necessary. A null field will be introduced to indicate
// that no parameter information is available.
MetadataList.assignValue(
GET_OR_DISTINCT(
DIGlobalVariable,
(Context, getMDOrNull(Record[1]), getMDString(Record[2]),
getMDString(Record[3]), getMDOrNull(Record[4]), Record[5],
getDITypeRefOrNull(Record[6]), Record[7], Record[8],
getMDOrNull(Record[10]), nullptr, Record[11], nullptr)),
NextMetadataNo);
NextMetadataNo++;
} else if (Version == 0) {
// Upgrade old metadata, which stored a global variable reference or a
// ConstantInt here.
NeedUpgradeToDIGlobalVariableExpression = true;
Metadata *Expr = getMDOrNull(Record[9]);
uint32_t AlignInBits = 0;
if (Record.size() > 11) {
if (Record[11] > (uint64_t)std::numeric_limits<uint32_t>::max())
return error("Alignment value is too large");
AlignInBits = Record[11];
}
GlobalVariable *Attach = nullptr;
if (auto *CMD = dyn_cast_or_null<ConstantAsMetadata>(Expr)) {
if (auto *GV = dyn_cast<GlobalVariable>(CMD->getValue())) {
Attach = GV;
Expr = nullptr;
} else if (auto *CI = dyn_cast<ConstantInt>(CMD->getValue())) {
Expr = DIExpression::get(Context,
{dwarf::DW_OP_constu, CI->getZExtValue(),
dwarf::DW_OP_stack_value});
} else {
Expr = nullptr;
}
}
DIGlobalVariable *DGV = GET_OR_DISTINCT(
DIGlobalVariable,
(Context, getMDOrNull(Record[1]), getMDString(Record[2]),
getMDString(Record[3]), getMDOrNull(Record[4]), Record[5],
getDITypeRefOrNull(Record[6]), Record[7], Record[8],
getMDOrNull(Record[10]), nullptr, AlignInBits, nullptr));
DIGlobalVariableExpression *DGVE = nullptr;
if (Attach || Expr)
DGVE = DIGlobalVariableExpression::getDistinct(
Context, DGV, Expr ? Expr : DIExpression::get(Context, {}));
if (Attach)
Attach->addDebugInfo(DGVE);
auto *MDNode = Expr ? cast<Metadata>(DGVE) : cast<Metadata>(DGV);
MetadataList.assignValue(MDNode, NextMetadataNo);
NextMetadataNo++;
} else
return error("Invalid record");
break;
}
case bitc::METADATA_LOCAL_VAR: {
// 10th field is for the obseleted 'inlinedAt:' field.
if (Record.size() < 8 || Record.size() > 10)
return error("Invalid record");
IsDistinct = Record[0] & 1;
bool HasAlignment = Record[0] & 2;
// 2nd field used to be an artificial tag, either DW_TAG_auto_variable or
// DW_TAG_arg_variable, if we have alignment flag encoded it means, that
// this is newer version of record which doesn't have artificial tag.
bool HasTag = !HasAlignment && Record.size() > 8;
DINode::DIFlags Flags = static_cast<DINode::DIFlags>(Record[7 + HasTag]);
uint32_t AlignInBits = 0;
Metadata *Annotations = nullptr;
if (HasAlignment) {
if (Record[8] > (uint64_t)std::numeric_limits<uint32_t>::max())
return error("Alignment value is too large");
AlignInBits = Record[8];
if (Record.size() > 9)
Annotations = getMDOrNull(Record[9]);
}
MetadataList.assignValue(
GET_OR_DISTINCT(DILocalVariable,
(Context, getMDOrNull(Record[1 + HasTag]),
getMDString(Record[2 + HasTag]),
getMDOrNull(Record[3 + HasTag]), Record[4 + HasTag],
getDITypeRefOrNull(Record[5 + HasTag]),
Record[6 + HasTag], Flags, AlignInBits, Annotations)),
NextMetadataNo);
NextMetadataNo++;
break;
}
case bitc::METADATA_LABEL: {
if (Record.size() != 5)
return error("Invalid record");
IsDistinct = Record[0] & 1;
MetadataList.assignValue(
GET_OR_DISTINCT(DILabel, (Context, getMDOrNull(Record[1]),
getMDString(Record[2]),
getMDOrNull(Record[3]), Record[4])),
NextMetadataNo);
NextMetadataNo++;
break;
}
case bitc::METADATA_EXPRESSION: {
if (Record.size() < 1)
return error("Invalid record");
IsDistinct = Record[0] & 1;
uint64_t Version = Record[0] >> 1;
auto Elts = MutableArrayRef<uint64_t>(Record).slice(1);
SmallVector<uint64_t, 6> Buffer;
if (Error Err = upgradeDIExpression(Version, Elts, Buffer))
return Err;
MetadataList.assignValue(GET_OR_DISTINCT(DIExpression, (Context, Elts)),
NextMetadataNo);
NextMetadataNo++;
break;
}
case bitc::METADATA_GLOBAL_VAR_EXPR: {
if (Record.size() != 3)
return error("Invalid record");
IsDistinct = Record[0];
Metadata *Expr = getMDOrNull(Record[2]);
if (!Expr)
Expr = DIExpression::get(Context, {});
MetadataList.assignValue(
GET_OR_DISTINCT(DIGlobalVariableExpression,
(Context, getMDOrNull(Record[1]), Expr)),
NextMetadataNo);
NextMetadataNo++;
break;
}
case bitc::METADATA_OBJC_PROPERTY: {
if (Record.size() != 8)
return error("Invalid record");
IsDistinct = Record[0];
MetadataList.assignValue(
GET_OR_DISTINCT(DIObjCProperty,
(Context, getMDString(Record[1]),
getMDOrNull(Record[2]), Record[3],
getMDString(Record[4]), getMDString(Record[5]),
Record[6], getDITypeRefOrNull(Record[7]))),
NextMetadataNo);
NextMetadataNo++;
break;
}
case bitc::METADATA_IMPORTED_ENTITY: {
if (Record.size() < 6 && Record.size() > 8)
return error("Invalid record");
IsDistinct = Record[0];
bool HasFile = (Record.size() >= 7);
bool HasElements = (Record.size() >= 8);
MetadataList.assignValue(
GET_OR_DISTINCT(DIImportedEntity,
(Context, Record[1], getMDOrNull(Record[2]),
getDITypeRefOrNull(Record[3]),
HasFile ? getMDOrNull(Record[6]) : nullptr,
HasFile ? Record[4] : 0, getMDString(Record[5]),
HasElements ? getMDOrNull(Record[7]) : nullptr)),
NextMetadataNo);
NextMetadataNo++;
break;
}
case bitc::METADATA_STRING_OLD: {
std::string String(Record.begin(), Record.end());
// Test for upgrading !llvm.loop.
HasSeenOldLoopTags |= mayBeOldLoopAttachmentTag(String);
++NumMDStringLoaded;
Metadata *MD = MDString::get(Context, String);
MetadataList.assignValue(MD, NextMetadataNo);
NextMetadataNo++;
break;
}
case bitc::METADATA_STRINGS: {
auto CreateNextMDString = [&](StringRef Str) {
++NumMDStringLoaded;
MetadataList.assignValue(MDString::get(Context, Str), NextMetadataNo);
NextMetadataNo++;
};
if (Error Err = parseMetadataStrings(Record, Blob, CreateNextMDString))
return Err;
break;
}
case bitc::METADATA_GLOBAL_DECL_ATTACHMENT: {
if (Record.size() % 2 == 0)
return error("Invalid record");
unsigned ValueID = Record[0];
if (ValueID >= ValueList.size())
return error("Invalid record");
if (auto *GO = dyn_cast<GlobalObject>(ValueList[ValueID]))
if (Error Err = parseGlobalObjectAttachment(
*GO, ArrayRef<uint64_t>(Record).slice(1)))
return Err;
break;
}
case bitc::METADATA_KIND: {
// Support older bitcode files that had METADATA_KIND records in a
// block with METADATA_BLOCK_ID.
if (Error Err = parseMetadataKindRecord(Record))
return Err;
break;
}
case bitc::METADATA_ARG_LIST: {
SmallVector<ValueAsMetadata *, 4> Elts;
Elts.reserve(Record.size());
for (uint64_t Elt : Record) {
Metadata *MD = getMD(Elt);
if (isa<MDNode>(MD) && cast<MDNode>(MD)->isTemporary())
return error(
"Invalid record: DIArgList should not contain forward refs");
if (!isa<ValueAsMetadata>(MD))
return error("Invalid record");
Elts.push_back(cast<ValueAsMetadata>(MD));
}
MetadataList.assignValue(DIArgList::get(Context, Elts), NextMetadataNo);
NextMetadataNo++;
break;
}
}
return Error::success();
#undef GET_OR_DISTINCT
}