2016-12-13 03:34:26 +08:00
|
|
|
//===- MetadataLoader.cpp - Internal BitcodeReader implementation ---------===//
|
|
|
|
//
|
2019-01-19 16:50:56 +08:00
|
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
2016-12-13 03:34:26 +08:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#include "MetadataLoader.h"
|
|
|
|
#include "ValueList.h"
|
|
|
|
|
|
|
|
#include "llvm/ADT/APFloat.h"
|
|
|
|
#include "llvm/ADT/APInt.h"
|
|
|
|
#include "llvm/ADT/ArrayRef.h"
|
|
|
|
#include "llvm/ADT/DenseMap.h"
|
2017-01-05 06:54:33 +08:00
|
|
|
#include "llvm/ADT/DenseSet.h"
|
2016-12-13 03:34:26 +08:00
|
|
|
#include "llvm/ADT/None.h"
|
|
|
|
#include "llvm/ADT/STLExtras.h"
|
|
|
|
#include "llvm/ADT/SmallString.h"
|
|
|
|
#include "llvm/ADT/SmallVector.h"
|
2017-01-05 06:54:33 +08:00
|
|
|
#include "llvm/ADT/Statistic.h"
|
2016-12-13 03:34:26 +08:00
|
|
|
#include "llvm/ADT/StringRef.h"
|
|
|
|
#include "llvm/ADT/Twine.h"
|
|
|
|
#include "llvm/Bitcode/BitcodeReader.h"
|
2019-07-04 06:40:07 +08:00
|
|
|
#include "llvm/Bitstream/BitstreamReader.h"
|
2016-12-13 03:34:26 +08:00
|
|
|
#include "llvm/Bitcode/LLVMBitCodes.h"
|
|
|
|
#include "llvm/IR/Argument.h"
|
|
|
|
#include "llvm/IR/Attributes.h"
|
|
|
|
#include "llvm/IR/AutoUpgrade.h"
|
|
|
|
#include "llvm/IR/BasicBlock.h"
|
|
|
|
#include "llvm/IR/CallingConv.h"
|
|
|
|
#include "llvm/IR/Comdat.h"
|
|
|
|
#include "llvm/IR/Constant.h"
|
|
|
|
#include "llvm/IR/Constants.h"
|
|
|
|
#include "llvm/IR/DebugInfo.h"
|
|
|
|
#include "llvm/IR/DebugInfoMetadata.h"
|
|
|
|
#include "llvm/IR/DebugLoc.h"
|
|
|
|
#include "llvm/IR/DerivedTypes.h"
|
|
|
|
#include "llvm/IR/DiagnosticPrinter.h"
|
|
|
|
#include "llvm/IR/Function.h"
|
|
|
|
#include "llvm/IR/GVMaterializer.h"
|
|
|
|
#include "llvm/IR/GlobalAlias.h"
|
|
|
|
#include "llvm/IR/GlobalIFunc.h"
|
|
|
|
#include "llvm/IR/GlobalIndirectSymbol.h"
|
|
|
|
#include "llvm/IR/GlobalObject.h"
|
|
|
|
#include "llvm/IR/GlobalValue.h"
|
|
|
|
#include "llvm/IR/GlobalVariable.h"
|
|
|
|
#include "llvm/IR/InlineAsm.h"
|
|
|
|
#include "llvm/IR/InstrTypes.h"
|
|
|
|
#include "llvm/IR/Instruction.h"
|
|
|
|
#include "llvm/IR/Instructions.h"
|
2017-04-18 09:21:53 +08:00
|
|
|
#include "llvm/IR/IntrinsicInst.h"
|
2017-06-06 19:49:48 +08:00
|
|
|
#include "llvm/IR/Intrinsics.h"
|
2016-12-13 03:34:26 +08:00
|
|
|
#include "llvm/IR/LLVMContext.h"
|
|
|
|
#include "llvm/IR/Module.h"
|
|
|
|
#include "llvm/IR/ModuleSummaryIndex.h"
|
|
|
|
#include "llvm/IR/OperandTraits.h"
|
|
|
|
#include "llvm/IR/TrackingMDRef.h"
|
|
|
|
#include "llvm/IR/Type.h"
|
|
|
|
#include "llvm/IR/ValueHandle.h"
|
|
|
|
#include "llvm/Support/AtomicOrdering.h"
|
|
|
|
#include "llvm/Support/Casting.h"
|
|
|
|
#include "llvm/Support/CommandLine.h"
|
|
|
|
#include "llvm/Support/Compiler.h"
|
|
|
|
#include "llvm/Support/Debug.h"
|
|
|
|
#include "llvm/Support/Error.h"
|
|
|
|
#include "llvm/Support/ErrorHandling.h"
|
|
|
|
#include "llvm/Support/ManagedStatic.h"
|
|
|
|
#include "llvm/Support/MemoryBuffer.h"
|
|
|
|
#include "llvm/Support/raw_ostream.h"
|
|
|
|
#include <algorithm>
|
|
|
|
#include <cassert>
|
|
|
|
#include <cstddef>
|
|
|
|
#include <cstdint>
|
|
|
|
#include <deque>
|
|
|
|
#include <limits>
|
|
|
|
#include <map>
|
|
|
|
#include <memory>
|
|
|
|
#include <string>
|
|
|
|
#include <system_error>
|
|
|
|
#include <tuple>
|
|
|
|
#include <utility>
|
|
|
|
#include <vector>
|
|
|
|
|
|
|
|
using namespace llvm;
|
|
|
|
|
2017-01-05 06:54:33 +08:00
|
|
|
#define DEBUG_TYPE "bitcode-reader"
|
|
|
|
|
|
|
|
STATISTIC(NumMDStringLoaded, "Number of MDStrings loaded");
|
|
|
|
STATISTIC(NumMDNodeTemporary, "Number of MDNode::Temporary created");
|
|
|
|
STATISTIC(NumMDRecordLoaded, "Number of Metadata records loaded");
|
|
|
|
|
2016-12-17 05:25:01 +08:00
|
|
|
/// Flag whether we need to import full type definitions for ThinLTO.
|
|
|
|
/// Currently needed for Darwin and LLDB.
|
|
|
|
static cl::opt<bool> ImportFullTypeDefinitions(
|
|
|
|
"import-full-type-definitions", cl::init(false), cl::Hidden,
|
|
|
|
cl::desc("Import full type definitions for ThinLTO."));
|
|
|
|
|
2017-01-05 06:54:33 +08:00
|
|
|
static cl::opt<bool> DisableLazyLoading(
|
|
|
|
"disable-ondemand-mds-loading", cl::init(false), cl::Hidden,
|
|
|
|
cl::desc("Force disable the lazy-loading on-demand of metadata when "
|
|
|
|
"loading bitcode for importing."));
|
|
|
|
|
2016-12-13 03:34:26 +08:00
|
|
|
namespace {
|
|
|
|
|
2019-05-03 21:50:38 +08:00
|
|
|
static int64_t unrotateSign(uint64_t U) { return (U & 1) ? ~(U >> 1) : U >> 1; }
|
2016-12-13 03:34:26 +08:00
|
|
|
|
|
|
|
class BitcodeReaderMetadataList {
|
|
|
|
/// Array of metadata references.
|
|
|
|
///
|
|
|
|
/// Don't use std::vector here. Some versions of libc++ copy (instead of
|
|
|
|
/// move) on resize, and TrackingMDRef is very expensive to copy.
|
|
|
|
SmallVector<TrackingMDRef, 1> MetadataPtrs;
|
|
|
|
|
2016-12-25 12:22:54 +08:00
|
|
|
/// The set of indices in MetadataPtrs above of forward references that were
|
|
|
|
/// generated.
|
|
|
|
SmallDenseSet<unsigned, 1> ForwardReference;
|
|
|
|
|
|
|
|
/// The set of indices in MetadataPtrs above of Metadata that need to be
|
|
|
|
/// resolved.
|
|
|
|
SmallDenseSet<unsigned, 1> UnresolvedNodes;
|
|
|
|
|
2016-12-13 03:34:26 +08:00
|
|
|
/// Structures for resolving old type refs.
|
|
|
|
struct {
|
|
|
|
SmallDenseMap<MDString *, TempMDTuple, 1> Unknown;
|
|
|
|
SmallDenseMap<MDString *, DICompositeType *, 1> Final;
|
|
|
|
SmallDenseMap<MDString *, DICompositeType *, 1> FwdDecls;
|
|
|
|
SmallVector<std::pair<TrackingMDRef, TempMDTuple>, 1> Arrays;
|
|
|
|
} OldTypeRefs;
|
|
|
|
|
|
|
|
LLVMContext &Context;
|
|
|
|
|
2019-07-14 20:35:50 +08:00
|
|
|
/// Maximum number of valid references. Forward references exceeding the
|
|
|
|
/// maximum must be invalid.
|
|
|
|
unsigned RefsUpperBound;
|
|
|
|
|
2016-12-13 03:34:26 +08:00
|
|
|
public:
|
2019-07-14 20:35:50 +08:00
|
|
|
BitcodeReaderMetadataList(LLVMContext &C, size_t RefsUpperBound)
|
|
|
|
: Context(C),
|
|
|
|
RefsUpperBound(std::min((size_t)std::numeric_limits<unsigned>::max(),
|
|
|
|
RefsUpperBound)) {}
|
2016-12-13 03:34:26 +08:00
|
|
|
|
|
|
|
// vector compatibility methods
|
|
|
|
unsigned size() const { return MetadataPtrs.size(); }
|
|
|
|
void resize(unsigned N) { MetadataPtrs.resize(N); }
|
|
|
|
void push_back(Metadata *MD) { MetadataPtrs.emplace_back(MD); }
|
|
|
|
void clear() { MetadataPtrs.clear(); }
|
|
|
|
Metadata *back() const { return MetadataPtrs.back(); }
|
|
|
|
void pop_back() { MetadataPtrs.pop_back(); }
|
|
|
|
bool empty() const { return MetadataPtrs.empty(); }
|
|
|
|
|
|
|
|
Metadata *operator[](unsigned i) const {
|
|
|
|
assert(i < MetadataPtrs.size());
|
|
|
|
return MetadataPtrs[i];
|
|
|
|
}
|
|
|
|
|
|
|
|
Metadata *lookup(unsigned I) const {
|
|
|
|
if (I < MetadataPtrs.size())
|
|
|
|
return MetadataPtrs[I];
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
void shrinkTo(unsigned N) {
|
|
|
|
assert(N <= size() && "Invalid shrinkTo request!");
|
2016-12-25 12:22:54 +08:00
|
|
|
assert(ForwardReference.empty() && "Unexpected forward refs");
|
|
|
|
assert(UnresolvedNodes.empty() && "Unexpected unresolved node");
|
2016-12-13 03:34:26 +08:00
|
|
|
MetadataPtrs.resize(N);
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Return the given metadata, creating a replaceable forward reference if
|
|
|
|
/// necessary.
|
|
|
|
Metadata *getMetadataFwdRef(unsigned Idx);
|
|
|
|
|
2018-01-17 20:29:38 +08:00
|
|
|
/// Return the given metadata only if it is fully resolved.
|
2016-12-13 03:34:26 +08:00
|
|
|
///
|
|
|
|
/// Gives the same result as \a lookup(), unless \a MDNode::isResolved()
|
|
|
|
/// would give \c false.
|
|
|
|
Metadata *getMetadataIfResolved(unsigned Idx);
|
|
|
|
|
|
|
|
MDNode *getMDNodeFwdRefOrNull(unsigned Idx);
|
|
|
|
void assignValue(Metadata *MD, unsigned Idx);
|
|
|
|
void tryToResolveCycles();
|
2016-12-25 12:22:54 +08:00
|
|
|
bool hasFwdRefs() const { return !ForwardReference.empty(); }
|
2017-01-05 06:54:33 +08:00
|
|
|
int getNextFwdRef() {
|
|
|
|
assert(hasFwdRefs());
|
|
|
|
return *ForwardReference.begin();
|
|
|
|
}
|
2016-12-13 03:34:26 +08:00
|
|
|
|
|
|
|
/// Upgrade a type that had an MDString reference.
|
|
|
|
void addTypeRef(MDString &UUID, DICompositeType &CT);
|
|
|
|
|
|
|
|
/// Upgrade a type that had an MDString reference.
|
|
|
|
Metadata *upgradeTypeRef(Metadata *MaybeUUID);
|
|
|
|
|
|
|
|
/// Upgrade a type ref array that may have MDString references.
|
|
|
|
Metadata *upgradeTypeRefArray(Metadata *MaybeTuple);
|
|
|
|
|
|
|
|
private:
|
|
|
|
Metadata *resolveTypeRefArray(Metadata *MaybeTuple);
|
|
|
|
};
|
|
|
|
|
|
|
|
void BitcodeReaderMetadataList::assignValue(Metadata *MD, unsigned Idx) {
|
2016-12-25 12:22:54 +08:00
|
|
|
if (auto *MDN = dyn_cast<MDNode>(MD))
|
|
|
|
if (!MDN->isResolved())
|
|
|
|
UnresolvedNodes.insert(Idx);
|
|
|
|
|
2016-12-13 03:34:26 +08:00
|
|
|
if (Idx == size()) {
|
|
|
|
push_back(MD);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (Idx >= size())
|
|
|
|
resize(Idx + 1);
|
|
|
|
|
|
|
|
TrackingMDRef &OldMD = MetadataPtrs[Idx];
|
|
|
|
if (!OldMD) {
|
|
|
|
OldMD.reset(MD);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// If there was a forward reference to this value, replace it.
|
|
|
|
TempMDTuple PrevMD(cast<MDTuple>(OldMD.get()));
|
|
|
|
PrevMD->replaceAllUsesWith(MD);
|
2016-12-25 12:22:54 +08:00
|
|
|
ForwardReference.erase(Idx);
|
2016-12-13 03:34:26 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
Metadata *BitcodeReaderMetadataList::getMetadataFwdRef(unsigned Idx) {
|
2019-07-14 20:35:50 +08:00
|
|
|
// Bail out for a clearly invalid value.
|
|
|
|
if (Idx >= RefsUpperBound)
|
|
|
|
return nullptr;
|
|
|
|
|
2016-12-13 03:34:26 +08:00
|
|
|
if (Idx >= size())
|
|
|
|
resize(Idx + 1);
|
|
|
|
|
|
|
|
if (Metadata *MD = MetadataPtrs[Idx])
|
|
|
|
return MD;
|
|
|
|
|
|
|
|
// Track forward refs to be resolved later.
|
2016-12-25 12:22:54 +08:00
|
|
|
ForwardReference.insert(Idx);
|
2016-12-13 03:34:26 +08:00
|
|
|
|
|
|
|
// Create and return a placeholder, which will later be RAUW'd.
|
2017-01-05 06:54:33 +08:00
|
|
|
++NumMDNodeTemporary;
|
2016-12-13 03:34:26 +08:00
|
|
|
Metadata *MD = MDNode::getTemporary(Context, None).release();
|
|
|
|
MetadataPtrs[Idx].reset(MD);
|
|
|
|
return MD;
|
|
|
|
}
|
|
|
|
|
|
|
|
Metadata *BitcodeReaderMetadataList::getMetadataIfResolved(unsigned Idx) {
|
|
|
|
Metadata *MD = lookup(Idx);
|
|
|
|
if (auto *N = dyn_cast_or_null<MDNode>(MD))
|
|
|
|
if (!N->isResolved())
|
|
|
|
return nullptr;
|
|
|
|
return MD;
|
|
|
|
}
|
|
|
|
|
|
|
|
MDNode *BitcodeReaderMetadataList::getMDNodeFwdRefOrNull(unsigned Idx) {
|
|
|
|
return dyn_cast_or_null<MDNode>(getMetadataFwdRef(Idx));
|
|
|
|
}
|
|
|
|
|
|
|
|
void BitcodeReaderMetadataList::tryToResolveCycles() {
|
2016-12-25 12:22:54 +08:00
|
|
|
if (!ForwardReference.empty())
|
2016-12-13 03:34:26 +08:00
|
|
|
// Still forward references... can't resolve cycles.
|
|
|
|
return;
|
|
|
|
|
|
|
|
// Give up on finding a full definition for any forward decls that remain.
|
|
|
|
for (const auto &Ref : OldTypeRefs.FwdDecls)
|
|
|
|
OldTypeRefs.Final.insert(Ref);
|
|
|
|
OldTypeRefs.FwdDecls.clear();
|
|
|
|
|
|
|
|
// Upgrade from old type ref arrays. In strange cases, this could add to
|
|
|
|
// OldTypeRefs.Unknown.
|
2016-12-25 12:22:54 +08:00
|
|
|
for (const auto &Array : OldTypeRefs.Arrays)
|
2016-12-13 03:34:26 +08:00
|
|
|
Array.second->replaceAllUsesWith(resolveTypeRefArray(Array.first.get()));
|
|
|
|
OldTypeRefs.Arrays.clear();
|
|
|
|
|
|
|
|
// Replace old string-based type refs with the resolved node, if possible.
|
|
|
|
// If we haven't seen the node, leave it to the verifier to complain about
|
|
|
|
// the invalid string reference.
|
|
|
|
for (const auto &Ref : OldTypeRefs.Unknown) {
|
|
|
|
if (DICompositeType *CT = OldTypeRefs.Final.lookup(Ref.first))
|
|
|
|
Ref.second->replaceAllUsesWith(CT);
|
|
|
|
else
|
|
|
|
Ref.second->replaceAllUsesWith(Ref.first);
|
|
|
|
}
|
|
|
|
OldTypeRefs.Unknown.clear();
|
|
|
|
|
2016-12-25 12:22:54 +08:00
|
|
|
if (UnresolvedNodes.empty())
|
2016-12-13 03:34:26 +08:00
|
|
|
// Nothing to do.
|
|
|
|
return;
|
|
|
|
|
|
|
|
// Resolve any cycles.
|
2016-12-25 12:22:54 +08:00
|
|
|
for (unsigned I : UnresolvedNodes) {
|
2016-12-13 03:34:26 +08:00
|
|
|
auto &MD = MetadataPtrs[I];
|
|
|
|
auto *N = dyn_cast_or_null<MDNode>(MD);
|
|
|
|
if (!N)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
assert(!N->isTemporary() && "Unexpected forward reference");
|
|
|
|
N->resolveCycles();
|
|
|
|
}
|
|
|
|
|
2016-12-25 12:22:54 +08:00
|
|
|
// Make sure we return early again until there's another unresolved ref.
|
|
|
|
UnresolvedNodes.clear();
|
2016-12-13 03:34:26 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void BitcodeReaderMetadataList::addTypeRef(MDString &UUID,
|
|
|
|
DICompositeType &CT) {
|
|
|
|
assert(CT.getRawIdentifier() == &UUID && "Mismatched UUID");
|
|
|
|
if (CT.isForwardDecl())
|
|
|
|
OldTypeRefs.FwdDecls.insert(std::make_pair(&UUID, &CT));
|
|
|
|
else
|
|
|
|
OldTypeRefs.Final.insert(std::make_pair(&UUID, &CT));
|
|
|
|
}
|
|
|
|
|
|
|
|
Metadata *BitcodeReaderMetadataList::upgradeTypeRef(Metadata *MaybeUUID) {
|
|
|
|
auto *UUID = dyn_cast_or_null<MDString>(MaybeUUID);
|
|
|
|
if (LLVM_LIKELY(!UUID))
|
|
|
|
return MaybeUUID;
|
|
|
|
|
|
|
|
if (auto *CT = OldTypeRefs.Final.lookup(UUID))
|
|
|
|
return CT;
|
|
|
|
|
|
|
|
auto &Ref = OldTypeRefs.Unknown[UUID];
|
|
|
|
if (!Ref)
|
|
|
|
Ref = MDNode::getTemporary(Context, None);
|
|
|
|
return Ref.get();
|
|
|
|
}
|
|
|
|
|
|
|
|
Metadata *BitcodeReaderMetadataList::upgradeTypeRefArray(Metadata *MaybeTuple) {
|
|
|
|
auto *Tuple = dyn_cast_or_null<MDTuple>(MaybeTuple);
|
|
|
|
if (!Tuple || Tuple->isDistinct())
|
|
|
|
return MaybeTuple;
|
|
|
|
|
|
|
|
// Look through the array immediately if possible.
|
|
|
|
if (!Tuple->isTemporary())
|
|
|
|
return resolveTypeRefArray(Tuple);
|
|
|
|
|
|
|
|
// Create and return a placeholder to use for now. Eventually
|
|
|
|
// resolveTypeRefArrays() will be resolve this forward reference.
|
|
|
|
OldTypeRefs.Arrays.emplace_back(
|
|
|
|
std::piecewise_construct, std::forward_as_tuple(Tuple),
|
|
|
|
std::forward_as_tuple(MDTuple::getTemporary(Context, None)));
|
|
|
|
return OldTypeRefs.Arrays.back().second.get();
|
|
|
|
}
|
|
|
|
|
|
|
|
Metadata *BitcodeReaderMetadataList::resolveTypeRefArray(Metadata *MaybeTuple) {
|
|
|
|
auto *Tuple = dyn_cast_or_null<MDTuple>(MaybeTuple);
|
|
|
|
if (!Tuple || Tuple->isDistinct())
|
|
|
|
return MaybeTuple;
|
|
|
|
|
2019-05-07 10:06:37 +08:00
|
|
|
// Look through the DITypeRefArray, upgrading each DIType *.
|
2016-12-13 03:34:26 +08:00
|
|
|
SmallVector<Metadata *, 32> Ops;
|
|
|
|
Ops.reserve(Tuple->getNumOperands());
|
|
|
|
for (Metadata *MD : Tuple->operands())
|
|
|
|
Ops.push_back(upgradeTypeRef(MD));
|
|
|
|
|
|
|
|
return MDTuple::get(Context, Ops);
|
|
|
|
}
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
|
|
|
|
class PlaceholderQueue {
|
|
|
|
// Placeholders would thrash around when moved, so store in a std::deque
|
|
|
|
// instead of some sort of vector.
|
|
|
|
std::deque<DistinctMDOperandPlaceholder> PHs;
|
|
|
|
|
|
|
|
public:
|
2017-01-20 18:18:32 +08:00
|
|
|
~PlaceholderQueue() {
|
|
|
|
assert(empty() && "PlaceholderQueue hasn't been flushed before being destroyed");
|
|
|
|
}
|
2017-01-05 06:54:33 +08:00
|
|
|
bool empty() { return PHs.empty(); }
|
2016-12-13 03:34:26 +08:00
|
|
|
DistinctMDOperandPlaceholder &getPlaceholderOp(unsigned ID);
|
|
|
|
void flush(BitcodeReaderMetadataList &MetadataList);
|
2017-01-05 06:54:33 +08:00
|
|
|
|
|
|
|
/// Return the list of temporaries nodes in the queue, these need to be
|
|
|
|
/// loaded before we can flush the queue.
|
|
|
|
void getTemporaries(BitcodeReaderMetadataList &MetadataList,
|
|
|
|
DenseSet<unsigned> &Temporaries) {
|
|
|
|
for (auto &PH : PHs) {
|
|
|
|
auto ID = PH.getID();
|
|
|
|
auto *MD = MetadataList.lookup(ID);
|
|
|
|
if (!MD) {
|
|
|
|
Temporaries.insert(ID);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
auto *N = dyn_cast_or_null<MDNode>(MD);
|
|
|
|
if (N && N->isTemporary())
|
|
|
|
Temporaries.insert(ID);
|
|
|
|
}
|
|
|
|
}
|
2016-12-13 03:34:26 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
} // end anonymous namespace
|
|
|
|
|
|
|
|
DistinctMDOperandPlaceholder &PlaceholderQueue::getPlaceholderOp(unsigned ID) {
|
|
|
|
PHs.emplace_back(ID);
|
|
|
|
return PHs.back();
|
|
|
|
}
|
|
|
|
|
|
|
|
void PlaceholderQueue::flush(BitcodeReaderMetadataList &MetadataList) {
|
|
|
|
while (!PHs.empty()) {
|
2016-12-25 11:55:53 +08:00
|
|
|
auto *MD = MetadataList.lookup(PHs.front().getID());
|
|
|
|
assert(MD && "Flushing placeholder on unassigned MD");
|
2016-12-23 10:20:09 +08:00
|
|
|
#ifndef NDEBUG
|
2016-12-25 11:55:53 +08:00
|
|
|
if (auto *MDN = dyn_cast<MDNode>(MD))
|
2016-12-23 10:20:09 +08:00
|
|
|
assert(MDN->isResolved() &&
|
|
|
|
"Flushing Placeholder while cycles aren't resolved");
|
|
|
|
#endif
|
|
|
|
PHs.front().replaceUseWith(MD);
|
2016-12-13 03:34:26 +08:00
|
|
|
PHs.pop_front();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
} // anonynous namespace
|
|
|
|
|
2017-06-14 21:14:38 +08:00
|
|
|
static Error error(const Twine &Message) {
|
|
|
|
return make_error<StringError>(
|
|
|
|
Message, make_error_code(BitcodeError::CorruptedBitcode));
|
|
|
|
}
|
|
|
|
|
2016-12-13 03:34:26 +08:00
|
|
|
class MetadataLoader::MetadataLoaderImpl {
|
|
|
|
BitcodeReaderMetadataList MetadataList;
|
|
|
|
BitcodeReaderValueList &ValueList;
|
|
|
|
BitstreamCursor &Stream;
|
|
|
|
LLVMContext &Context;
|
|
|
|
Module &TheModule;
|
|
|
|
std::function<Type *(unsigned)> getTypeByID;
|
|
|
|
|
2017-01-05 06:54:33 +08:00
|
|
|
/// Cursor associated with the lazy-loading of Metadata. This is the easy way
|
|
|
|
/// to keep around the right "context" (Abbrev list) to be able to jump in
|
|
|
|
/// the middle of the metadata block and load any record.
|
|
|
|
BitstreamCursor IndexCursor;
|
|
|
|
|
|
|
|
/// Index that keeps track of MDString values.
|
|
|
|
std::vector<StringRef> MDStringRef;
|
|
|
|
|
|
|
|
/// On-demand loading of a single MDString. Requires the index above to be
|
|
|
|
/// populated.
|
|
|
|
MDString *lazyLoadOneMDString(unsigned Idx);
|
|
|
|
|
|
|
|
/// Index that keeps track of where to find a metadata record in the stream.
|
|
|
|
std::vector<uint64_t> GlobalMetadataBitPosIndex;
|
|
|
|
|
|
|
|
/// Populate the index above to enable lazily loading of metadata, and load
|
|
|
|
/// the named metadata as well as the transitively referenced global
|
|
|
|
/// Metadata.
|
2017-01-08 02:31:38 +08:00
|
|
|
Expected<bool> lazyLoadModuleMetadataBlock();
|
2017-01-05 06:54:33 +08:00
|
|
|
|
|
|
|
/// On-demand loading of a single metadata. Requires the index above to be
|
|
|
|
/// populated.
|
|
|
|
void lazyLoadOneMetadata(unsigned Idx, PlaceholderQueue &Placeholders);
|
|
|
|
|
2016-12-23 11:59:18 +08:00
|
|
|
// Keep mapping of seens pair of old-style CU <-> SP, and update pointers to
|
|
|
|
// point from SP to CU after a block is completly parsed.
|
|
|
|
std::vector<std::pair<DICompileUnit *, Metadata *>> CUSubprograms;
|
|
|
|
|
2016-12-13 03:34:26 +08:00
|
|
|
/// Functions that need to be matched with subprograms when upgrading old
|
|
|
|
/// metadata.
|
|
|
|
SmallDenseMap<Function *, DISubprogram *, 16> FunctionsWithSPs;
|
|
|
|
|
|
|
|
// Map the bitcode's custom MDKind ID to the Module's MDKind ID.
|
|
|
|
DenseMap<unsigned, unsigned> MDKindMap;
|
|
|
|
|
2016-12-17 03:16:29 +08:00
|
|
|
bool StripTBAA = false;
|
2016-12-13 03:34:26 +08:00
|
|
|
bool HasSeenOldLoopTags = false;
|
2017-02-08 01:35:41 +08:00
|
|
|
bool NeedUpgradeToDIGlobalVariableExpression = false;
|
2017-04-18 09:21:53 +08:00
|
|
|
bool NeedDeclareExpressionUpgrade = false;
|
2016-12-13 03:34:26 +08:00
|
|
|
|
2016-12-23 10:20:02 +08:00
|
|
|
/// True if metadata is being parsed for a module being ThinLTO imported.
|
|
|
|
bool IsImporting = false;
|
|
|
|
|
2016-12-23 11:59:18 +08:00
|
|
|
Error parseOneMetadata(SmallVectorImpl<uint64_t> &Record, unsigned Code,
|
|
|
|
PlaceholderQueue &Placeholders, StringRef Blob,
|
2017-01-05 06:54:33 +08:00
|
|
|
unsigned &NextMetadataNo);
|
2016-12-13 03:34:26 +08:00
|
|
|
Error parseMetadataStrings(ArrayRef<uint64_t> Record, StringRef Blob,
|
2017-01-13 22:39:03 +08:00
|
|
|
function_ref<void(StringRef)> CallBack);
|
2016-12-13 03:34:26 +08:00
|
|
|
Error parseGlobalObjectAttachment(GlobalObject &GO,
|
|
|
|
ArrayRef<uint64_t> Record);
|
|
|
|
Error parseMetadataKindRecord(SmallVectorImpl<uint64_t> &Record);
|
|
|
|
|
2017-01-05 06:54:33 +08:00
|
|
|
void resolveForwardRefsAndPlaceholders(PlaceholderQueue &Placeholders);
|
|
|
|
|
|
|
|
/// Upgrade old-style CU <-> SP pointers to point from SP to CU.
|
|
|
|
void upgradeCUSubprograms() {
|
|
|
|
for (auto CU_SP : CUSubprograms)
|
|
|
|
if (auto *SPs = dyn_cast_or_null<MDTuple>(CU_SP.second))
|
|
|
|
for (auto &Op : SPs->operands())
|
2017-04-27 07:59:52 +08:00
|
|
|
if (auto *SP = dyn_cast_or_null<DISubprogram>(Op))
|
|
|
|
SP->replaceUnit(CU_SP.first);
|
2017-01-05 06:54:33 +08:00
|
|
|
CUSubprograms.clear();
|
|
|
|
}
|
|
|
|
|
2017-02-08 01:35:41 +08:00
|
|
|
/// Upgrade old-style bare DIGlobalVariables to DIGlobalVariableExpressions.
|
|
|
|
void upgradeCUVariables() {
|
|
|
|
if (!NeedUpgradeToDIGlobalVariableExpression)
|
|
|
|
return;
|
|
|
|
|
|
|
|
// Upgrade list of variables attached to the CUs.
|
|
|
|
if (NamedMDNode *CUNodes = TheModule.getNamedMetadata("llvm.dbg.cu"))
|
|
|
|
for (unsigned I = 0, E = CUNodes->getNumOperands(); I != E; ++I) {
|
|
|
|
auto *CU = cast<DICompileUnit>(CUNodes->getOperand(I));
|
|
|
|
if (auto *GVs = dyn_cast_or_null<MDTuple>(CU->getRawGlobalVariables()))
|
|
|
|
for (unsigned I = 0; I < GVs->getNumOperands(); I++)
|
|
|
|
if (auto *GV =
|
|
|
|
dyn_cast_or_null<DIGlobalVariable>(GVs->getOperand(I))) {
|
2017-08-31 02:06:51 +08:00
|
|
|
auto *DGVE = DIGlobalVariableExpression::getDistinct(
|
|
|
|
Context, GV, DIExpression::get(Context, {}));
|
2017-02-08 01:35:41 +08:00
|
|
|
GVs->replaceOperandWith(I, DGVE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Upgrade variables attached to globals.
|
|
|
|
for (auto &GV : TheModule.globals()) {
|
2017-05-17 02:41:46 +08:00
|
|
|
SmallVector<MDNode *, 1> MDs;
|
2017-02-08 01:35:41 +08:00
|
|
|
GV.getMetadata(LLVMContext::MD_dbg, MDs);
|
|
|
|
GV.eraseMetadata(LLVMContext::MD_dbg);
|
|
|
|
for (auto *MD : MDs)
|
2019-10-02 19:48:17 +08:00
|
|
|
if (auto *DGV = dyn_cast<DIGlobalVariable>(MD)) {
|
2017-08-31 02:06:51 +08:00
|
|
|
auto *DGVE = DIGlobalVariableExpression::getDistinct(
|
|
|
|
Context, DGV, DIExpression::get(Context, {}));
|
2017-02-08 01:35:41 +08:00
|
|
|
GV.addMetadata(LLVMContext::MD_dbg, *DGVE);
|
|
|
|
} else
|
|
|
|
GV.addMetadata(LLVMContext::MD_dbg, *MD);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-04-18 09:21:53 +08:00
|
|
|
/// Remove a leading DW_OP_deref from DIExpressions in a dbg.declare that
|
|
|
|
/// describes a function argument.
|
|
|
|
void upgradeDeclareExpressions(Function &F) {
|
|
|
|
if (!NeedDeclareExpressionUpgrade)
|
|
|
|
return;
|
|
|
|
|
|
|
|
for (auto &BB : F)
|
|
|
|
for (auto &I : BB)
|
|
|
|
if (auto *DDI = dyn_cast<DbgDeclareInst>(&I))
|
|
|
|
if (auto *DIExpr = DDI->getExpression())
|
|
|
|
if (DIExpr->startsWithDeref() &&
|
|
|
|
dyn_cast_or_null<Argument>(DDI->getAddress())) {
|
|
|
|
SmallVector<uint64_t, 8> Ops;
|
|
|
|
Ops.append(std::next(DIExpr->elements_begin()),
|
|
|
|
DIExpr->elements_end());
|
|
|
|
auto *E = DIExpression::get(Context, Ops);
|
|
|
|
DDI->setOperand(2, MetadataAsValue::get(Context, E));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-06-14 21:14:38 +08:00
|
|
|
/// Upgrade the expression from previous versions.
|
|
|
|
Error upgradeDIExpression(uint64_t FromVersion,
|
|
|
|
MutableArrayRef<uint64_t> &Expr,
|
|
|
|
SmallVectorImpl<uint64_t> &Buffer) {
|
|
|
|
auto N = Expr.size();
|
|
|
|
switch (FromVersion) {
|
|
|
|
default:
|
|
|
|
return error("Invalid record");
|
|
|
|
case 0:
|
|
|
|
if (N >= 3 && Expr[N - 3] == dwarf::DW_OP_bit_piece)
|
|
|
|
Expr[N - 3] = dwarf::DW_OP_LLVM_fragment;
|
|
|
|
LLVM_FALLTHROUGH;
|
|
|
|
case 1:
|
|
|
|
// Move DW_OP_deref to the end.
|
|
|
|
if (N && Expr[0] == dwarf::DW_OP_deref) {
|
|
|
|
auto End = Expr.end();
|
|
|
|
if (Expr.size() >= 3 &&
|
|
|
|
*std::prev(End, 3) == dwarf::DW_OP_LLVM_fragment)
|
|
|
|
End = std::prev(End, 3);
|
|
|
|
std::move(std::next(Expr.begin()), End, Expr.begin());
|
|
|
|
*std::prev(End) = dwarf::DW_OP_deref;
|
|
|
|
}
|
|
|
|
NeedDeclareExpressionUpgrade = true;
|
|
|
|
LLVM_FALLTHROUGH;
|
|
|
|
case 2: {
|
|
|
|
// Change DW_OP_plus to DW_OP_plus_uconst.
|
|
|
|
// Change DW_OP_minus to DW_OP_uconst, DW_OP_minus
|
|
|
|
auto SubExpr = ArrayRef<uint64_t>(Expr);
|
|
|
|
while (!SubExpr.empty()) {
|
|
|
|
// Skip past other operators with their operands
|
|
|
|
// for this version of the IR, obtained from
|
|
|
|
// from historic DIExpression::ExprOperand::getSize().
|
|
|
|
size_t HistoricSize;
|
|
|
|
switch (SubExpr.front()) {
|
|
|
|
default:
|
|
|
|
HistoricSize = 1;
|
|
|
|
break;
|
|
|
|
case dwarf::DW_OP_constu:
|
|
|
|
case dwarf::DW_OP_minus:
|
|
|
|
case dwarf::DW_OP_plus:
|
|
|
|
HistoricSize = 2;
|
|
|
|
break;
|
|
|
|
case dwarf::DW_OP_LLVM_fragment:
|
|
|
|
HistoricSize = 3;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
// If the expression is malformed, make sure we don't
|
|
|
|
// copy more elements than we should.
|
|
|
|
HistoricSize = std::min(SubExpr.size(), HistoricSize);
|
|
|
|
ArrayRef<uint64_t> Args = SubExpr.slice(1, HistoricSize-1);
|
|
|
|
|
|
|
|
switch (SubExpr.front()) {
|
|
|
|
case dwarf::DW_OP_plus:
|
|
|
|
Buffer.push_back(dwarf::DW_OP_plus_uconst);
|
|
|
|
Buffer.append(Args.begin(), Args.end());
|
|
|
|
break;
|
|
|
|
case dwarf::DW_OP_minus:
|
|
|
|
Buffer.push_back(dwarf::DW_OP_constu);
|
|
|
|
Buffer.append(Args.begin(), Args.end());
|
|
|
|
Buffer.push_back(dwarf::DW_OP_minus);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
Buffer.push_back(*SubExpr.begin());
|
|
|
|
Buffer.append(Args.begin(), Args.end());
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Continue with remaining elements.
|
|
|
|
SubExpr = SubExpr.slice(HistoricSize);
|
|
|
|
}
|
|
|
|
Expr = MutableArrayRef<uint64_t>(Buffer);
|
|
|
|
LLVM_FALLTHROUGH;
|
|
|
|
}
|
|
|
|
case 3:
|
|
|
|
// Up-to-date!
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return Error::success();
|
|
|
|
}
|
|
|
|
|
2017-02-08 01:35:41 +08:00
|
|
|
void upgradeDebugInfo() {
|
|
|
|
upgradeCUSubprograms();
|
|
|
|
upgradeCUVariables();
|
|
|
|
}
|
|
|
|
|
2016-12-13 03:34:26 +08:00
|
|
|
public:
|
|
|
|
MetadataLoaderImpl(BitstreamCursor &Stream, Module &TheModule,
|
|
|
|
BitcodeReaderValueList &ValueList,
|
2016-12-23 10:20:02 +08:00
|
|
|
std::function<Type *(unsigned)> getTypeByID,
|
|
|
|
bool IsImporting)
|
2019-07-14 20:35:50 +08:00
|
|
|
: MetadataList(TheModule.getContext(), Stream.SizeInBytes()),
|
|
|
|
ValueList(ValueList), Stream(Stream), Context(TheModule.getContext()),
|
|
|
|
TheModule(TheModule), getTypeByID(std::move(getTypeByID)),
|
|
|
|
IsImporting(IsImporting) {}
|
2016-12-13 03:34:26 +08:00
|
|
|
|
2016-12-23 10:20:02 +08:00
|
|
|
Error parseMetadata(bool ModuleLevel);
|
2016-12-13 03:34:26 +08:00
|
|
|
|
|
|
|
bool hasFwdRefs() const { return MetadataList.hasFwdRefs(); }
|
2017-01-21 04:29:16 +08:00
|
|
|
|
|
|
|
Metadata *getMetadataFwdRefOrLoad(unsigned ID) {
|
|
|
|
if (ID < MDStringRef.size())
|
|
|
|
return lazyLoadOneMDString(ID);
|
|
|
|
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())) {
|
|
|
|
PlaceholderQueue Placeholders;
|
|
|
|
lazyLoadOneMetadata(ID, Placeholders);
|
|
|
|
resolveForwardRefsAndPlaceholders(Placeholders);
|
|
|
|
return MetadataList.lookup(ID);
|
|
|
|
}
|
|
|
|
return MetadataList.getMetadataFwdRef(ID);
|
2016-12-13 03:34:26 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
DISubprogram *lookupSubprogramForFunction(Function *F) {
|
|
|
|
return FunctionsWithSPs.lookup(F);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool hasSeenOldLoopTags() { return HasSeenOldLoopTags; }
|
|
|
|
|
|
|
|
Error parseMetadataAttachment(
|
|
|
|
Function &F, const SmallVectorImpl<Instruction *> &InstructionList);
|
|
|
|
|
|
|
|
Error parseMetadataKinds();
|
|
|
|
|
2016-12-17 03:16:29 +08:00
|
|
|
void setStripTBAA(bool Value) { StripTBAA = Value; }
|
|
|
|
bool isStrippingTBAA() { return StripTBAA; }
|
|
|
|
|
2016-12-13 03:34:26 +08:00
|
|
|
unsigned size() const { return MetadataList.size(); }
|
|
|
|
void shrinkTo(unsigned N) { MetadataList.shrinkTo(N); }
|
2017-04-18 09:21:53 +08:00
|
|
|
void upgradeDebugIntrinsics(Function &F) { upgradeDeclareExpressions(F); }
|
2016-12-13 03:34:26 +08:00
|
|
|
};
|
|
|
|
|
2017-01-08 02:31:38 +08:00
|
|
|
Expected<bool>
|
|
|
|
MetadataLoader::MetadataLoaderImpl::lazyLoadModuleMetadataBlock() {
|
2017-01-05 06:54:33 +08:00
|
|
|
IndexCursor = Stream;
|
|
|
|
SmallVector<uint64_t, 64> Record;
|
|
|
|
// Get the abbrevs, and preload record positions to make them lazy-loadable.
|
|
|
|
while (true) {
|
2019-06-27 03:50:12 +08:00
|
|
|
Expected<BitstreamEntry> MaybeEntry = IndexCursor.advanceSkippingSubblocks(
|
2017-01-05 06:54:33 +08:00
|
|
|
BitstreamCursor::AF_DontPopBlockAtEnd);
|
2019-06-27 03:50:12 +08:00
|
|
|
if (!MaybeEntry)
|
|
|
|
return MaybeEntry.takeError();
|
|
|
|
BitstreamEntry Entry = MaybeEntry.get();
|
|
|
|
|
2017-01-05 06:54:33 +08:00
|
|
|
switch (Entry.Kind) {
|
|
|
|
case BitstreamEntry::SubBlock: // Handled for us already.
|
|
|
|
case BitstreamEntry::Error:
|
|
|
|
return error("Malformed block");
|
|
|
|
case BitstreamEntry::EndBlock: {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
case BitstreamEntry::Record: {
|
|
|
|
// The interesting case.
|
|
|
|
++NumMDRecordLoaded;
|
|
|
|
uint64_t CurrentPos = IndexCursor.GetCurrentBitNo();
|
2019-06-27 03:50:12 +08:00
|
|
|
Expected<unsigned> MaybeCode = IndexCursor.skipRecord(Entry.ID);
|
|
|
|
if (!MaybeCode)
|
|
|
|
return MaybeCode.takeError();
|
|
|
|
unsigned Code = MaybeCode.get();
|
2017-01-05 06:54:33 +08:00
|
|
|
switch (Code) {
|
|
|
|
case bitc::METADATA_STRINGS: {
|
|
|
|
// Rewind and parse the strings.
|
2019-06-27 03:50:12 +08:00
|
|
|
if (Error Err = IndexCursor.JumpToBit(CurrentPos))
|
|
|
|
return std::move(Err);
|
2017-01-05 06:54:33 +08:00
|
|
|
StringRef Blob;
|
|
|
|
Record.clear();
|
2019-06-27 03:50:12 +08:00
|
|
|
if (Expected<unsigned> MaybeRecord =
|
|
|
|
IndexCursor.readRecord(Entry.ID, Record, &Blob))
|
|
|
|
;
|
|
|
|
else
|
|
|
|
return MaybeRecord.takeError();
|
2017-01-05 06:54:33 +08:00
|
|
|
unsigned NumStrings = Record[0];
|
|
|
|
MDStringRef.reserve(NumStrings);
|
|
|
|
auto IndexNextMDString = [&](StringRef Str) {
|
|
|
|
MDStringRef.push_back(Str);
|
|
|
|
};
|
|
|
|
if (auto Err = parseMetadataStrings(Record, Blob, IndexNextMDString))
|
|
|
|
return std::move(Err);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case bitc::METADATA_INDEX_OFFSET: {
|
|
|
|
// This is the offset to the index, when we see this we skip all the
|
|
|
|
// records and load only an index to these.
|
2019-06-27 03:50:12 +08:00
|
|
|
if (Error Err = IndexCursor.JumpToBit(CurrentPos))
|
|
|
|
return std::move(Err);
|
2017-01-05 06:54:33 +08:00
|
|
|
Record.clear();
|
2019-06-27 03:50:12 +08:00
|
|
|
if (Expected<unsigned> MaybeRecord =
|
|
|
|
IndexCursor.readRecord(Entry.ID, Record))
|
|
|
|
;
|
|
|
|
else
|
|
|
|
return MaybeRecord.takeError();
|
2017-01-05 06:54:33 +08:00
|
|
|
if (Record.size() != 2)
|
|
|
|
return error("Invalid record");
|
|
|
|
auto Offset = Record[0] + (Record[1] << 32);
|
|
|
|
auto BeginPos = IndexCursor.GetCurrentBitNo();
|
2019-06-27 03:50:12 +08:00
|
|
|
if (Error Err = IndexCursor.JumpToBit(BeginPos + Offset))
|
|
|
|
return std::move(Err);
|
|
|
|
Expected<BitstreamEntry> MaybeEntry =
|
|
|
|
IndexCursor.advanceSkippingSubblocks(
|
|
|
|
BitstreamCursor::AF_DontPopBlockAtEnd);
|
|
|
|
if (!MaybeEntry)
|
|
|
|
return MaybeEntry.takeError();
|
|
|
|
Entry = MaybeEntry.get();
|
2017-01-05 06:54:33 +08:00
|
|
|
assert(Entry.Kind == BitstreamEntry::Record &&
|
|
|
|
"Corrupted bitcode: Expected `Record` when trying to find the "
|
|
|
|
"Metadata index");
|
|
|
|
Record.clear();
|
2019-06-27 03:50:12 +08:00
|
|
|
if (Expected<unsigned> MaybeCode =
|
|
|
|
IndexCursor.readRecord(Entry.ID, Record))
|
|
|
|
assert(MaybeCode.get() == bitc::METADATA_INDEX &&
|
|
|
|
"Corrupted bitcode: Expected `METADATA_INDEX` when trying to "
|
|
|
|
"find the Metadata index");
|
|
|
|
else
|
|
|
|
return MaybeCode.takeError();
|
2017-01-05 06:54:33 +08:00
|
|
|
// Delta unpack
|
|
|
|
auto CurrentValue = BeginPos;
|
|
|
|
GlobalMetadataBitPosIndex.reserve(Record.size());
|
|
|
|
for (auto &Elt : Record) {
|
|
|
|
CurrentValue += Elt;
|
|
|
|
GlobalMetadataBitPosIndex.push_back(CurrentValue);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case bitc::METADATA_INDEX:
|
|
|
|
// We don't expect to get there, the Index is loaded when we encounter
|
|
|
|
// the offset.
|
|
|
|
return error("Corrupted Metadata block");
|
|
|
|
case bitc::METADATA_NAME: {
|
|
|
|
// Named metadata need to be materialized now and aren't deferred.
|
2019-06-27 03:50:12 +08:00
|
|
|
if (Error Err = IndexCursor.JumpToBit(CurrentPos))
|
|
|
|
return std::move(Err);
|
2017-01-05 06:54:33 +08:00
|
|
|
Record.clear();
|
2019-06-27 03:50:12 +08:00
|
|
|
|
|
|
|
unsigned Code;
|
|
|
|
if (Expected<unsigned> MaybeCode =
|
|
|
|
IndexCursor.readRecord(Entry.ID, Record)) {
|
|
|
|
Code = MaybeCode.get();
|
|
|
|
assert(Code == bitc::METADATA_NAME);
|
|
|
|
} else
|
|
|
|
return MaybeCode.takeError();
|
2017-01-05 06:54:33 +08:00
|
|
|
|
|
|
|
// Read name of the named metadata.
|
|
|
|
SmallString<8> Name(Record.begin(), Record.end());
|
2019-06-27 03:50:12 +08:00
|
|
|
if (Expected<unsigned> MaybeCode = IndexCursor.ReadCode())
|
|
|
|
Code = MaybeCode.get();
|
|
|
|
else
|
|
|
|
return MaybeCode.takeError();
|
2017-01-05 06:54:33 +08:00
|
|
|
|
|
|
|
// Named Metadata comes in two parts, we expect the name to be followed
|
|
|
|
// by the node
|
|
|
|
Record.clear();
|
2019-06-27 03:50:12 +08:00
|
|
|
if (Expected<unsigned> MaybeNextBitCode =
|
|
|
|
IndexCursor.readRecord(Code, Record))
|
|
|
|
assert(MaybeNextBitCode.get() == bitc::METADATA_NAMED_NODE);
|
|
|
|
else
|
|
|
|
return MaybeNextBitCode.takeError();
|
2017-01-05 06:54:33 +08:00
|
|
|
|
|
|
|
// Read named metadata elements.
|
|
|
|
unsigned Size = Record.size();
|
|
|
|
NamedMDNode *NMD = TheModule.getOrInsertNamedMetadata(Name);
|
|
|
|
for (unsigned i = 0; i != Size; ++i) {
|
|
|
|
// FIXME: We could use a placeholder here, however NamedMDNode are
|
|
|
|
// taking MDNode as operand and not using the Metadata infrastructure.
|
|
|
|
// It is acknowledged by 'TODO: Inherit from Metadata' in the
|
|
|
|
// NamedMDNode class definition.
|
|
|
|
MDNode *MD = MetadataList.getMDNodeFwdRefOrNull(Record[i]);
|
2018-11-15 05:57:51 +08:00
|
|
|
assert(MD && "Invalid metadata: expect fwd ref to MDNode");
|
2017-01-05 06:54:33 +08:00
|
|
|
NMD->addOperand(MD);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case bitc::METADATA_GLOBAL_DECL_ATTACHMENT: {
|
|
|
|
// FIXME: we need to do this early because we don't materialize global
|
|
|
|
// value explicitly.
|
2019-06-27 03:50:12 +08:00
|
|
|
if (Error Err = IndexCursor.JumpToBit(CurrentPos))
|
|
|
|
return std::move(Err);
|
2017-01-05 06:54:33 +08:00
|
|
|
Record.clear();
|
2019-06-27 03:50:12 +08:00
|
|
|
if (Expected<unsigned> MaybeRecord =
|
|
|
|
IndexCursor.readRecord(Entry.ID, Record))
|
|
|
|
;
|
|
|
|
else
|
|
|
|
return MaybeRecord.takeError();
|
2017-01-05 06:54:33 +08:00
|
|
|
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 std::move(Err);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case bitc::METADATA_KIND:
|
|
|
|
case bitc::METADATA_STRING_OLD:
|
|
|
|
case bitc::METADATA_OLD_FN_NODE:
|
|
|
|
case bitc::METADATA_OLD_NODE:
|
|
|
|
case bitc::METADATA_VALUE:
|
|
|
|
case bitc::METADATA_DISTINCT_NODE:
|
|
|
|
case bitc::METADATA_NODE:
|
|
|
|
case bitc::METADATA_LOCATION:
|
|
|
|
case bitc::METADATA_GENERIC_DEBUG:
|
|
|
|
case bitc::METADATA_SUBRANGE:
|
|
|
|
case bitc::METADATA_ENUMERATOR:
|
|
|
|
case bitc::METADATA_BASIC_TYPE:
|
|
|
|
case bitc::METADATA_DERIVED_TYPE:
|
|
|
|
case bitc::METADATA_COMPOSITE_TYPE:
|
|
|
|
case bitc::METADATA_SUBROUTINE_TYPE:
|
|
|
|
case bitc::METADATA_MODULE:
|
|
|
|
case bitc::METADATA_FILE:
|
|
|
|
case bitc::METADATA_COMPILE_UNIT:
|
|
|
|
case bitc::METADATA_SUBPROGRAM:
|
|
|
|
case bitc::METADATA_LEXICAL_BLOCK:
|
|
|
|
case bitc::METADATA_LEXICAL_BLOCK_FILE:
|
|
|
|
case bitc::METADATA_NAMESPACE:
|
Add LLVM IR debug info support for Fortran COMMON blocks
COMMON blocks are a feature of Fortran that has no direct analog in C languages, but they are similar to data sections in assembly language programming. A COMMON block is a named area of memory that holds a collection of variables. Fortran subprograms may map the COMMON block memory area to their own, possibly distinct, non-empty list of variables. A Fortran COMMON block might look like the following example.
COMMON /ALPHA/ I, J
For this construct, the compiler generates a new scope-like DI construct (!DICommonBlock) into which variables (see I, J above) can be placed. As the common block implies a range of storage with global lifetime, the !DICommonBlock refers to a !DIGlobalVariable. The Fortran variable that comprise the COMMON block are also linked via metadata to offsets within the global variable that stands for the entire common block.
@alpha_ = common global %alphabytes_ zeroinitializer, align 64, !dbg !27, !dbg !30, !dbg !33
!14 = distinct !DISubprogram(…)
!20 = distinct !DICommonBlock(scope: !14, declaration: !25, name: "alpha")
!25 = distinct !DIGlobalVariable(scope: !20, name: "common alpha", type: !24)
!27 = !DIGlobalVariableExpression(var: !25, expr: !DIExpression())
!29 = distinct !DIGlobalVariable(scope: !20, name: "i", file: !3, type: !28)
!30 = !DIGlobalVariableExpression(var: !29, expr: !DIExpression())
!31 = distinct !DIGlobalVariable(scope: !20, name: "j", file: !3, type: !28)
!32 = !DIExpression(DW_OP_plus_uconst, 4)
!33 = !DIGlobalVariableExpression(var: !31, expr: !32)
The DWARF generated for this is as follows.
DW_TAG_common_block:
DW_AT_name: alpha
DW_AT_location: @alpha_+0
DW_TAG_variable:
DW_AT_name: common alpha
DW_AT_type: array of 8 bytes
DW_AT_location: @alpha_+0
DW_TAG_variable:
DW_AT_name: i
DW_AT_type: integer*4
DW_AT_location: @Alpha+0
DW_TAG_variable:
DW_AT_name: j
DW_AT_type: integer*4
DW_AT_location: @Alpha+4
Patch by Eric Schweitz!
Differential Revision: https://reviews.llvm.org/D54327
llvm-svn: 357934
2019-04-09 03:13:55 +08:00
|
|
|
case bitc::METADATA_COMMON_BLOCK:
|
2017-01-05 06:54:33 +08:00
|
|
|
case bitc::METADATA_MACRO:
|
|
|
|
case bitc::METADATA_MACRO_FILE:
|
|
|
|
case bitc::METADATA_TEMPLATE_TYPE:
|
|
|
|
case bitc::METADATA_TEMPLATE_VALUE:
|
|
|
|
case bitc::METADATA_GLOBAL_VAR:
|
|
|
|
case bitc::METADATA_LOCAL_VAR:
|
[DebugInfo] Add DILabel metadata and intrinsic llvm.dbg.label.
In order to set breakpoints on labels and list source code around
labels, we need collect debug information for labels, i.e., label
name, the function label belong, line number in the file, and the
address label located. In order to keep these information in LLVM
IR and to allow backend to generate debug information correctly.
We create a new kind of metadata for labels, DILabel. The format
of DILabel is
!DILabel(scope: !1, name: "foo", file: !2, line: 3)
We hope to keep debug information as much as possible even the
code is optimized. So, we create a new kind of intrinsic for label
metadata to avoid the metadata is eliminated with basic block.
The intrinsic will keep existing if we keep it from optimized out.
The format of the intrinsic is
llvm.dbg.label(metadata !1)
It has only one argument, that is the DILabel metadata. The
intrinsic will follow the label immediately. Backend could get the
label metadata through the intrinsic's parameter.
We also create DIBuilder API for labels to be used by Frontend.
Frontend could use createLabel() to allocate DILabel objects, and use
insertLabel() to insert llvm.dbg.label intrinsic in LLVM IR.
Differential Revision: https://reviews.llvm.org/D45024
Patch by Hsiangkai Wang.
llvm-svn: 331841
2018-05-09 10:40:45 +08:00
|
|
|
case bitc::METADATA_LABEL:
|
2017-01-05 06:54:33 +08:00
|
|
|
case bitc::METADATA_EXPRESSION:
|
|
|
|
case bitc::METADATA_OBJC_PROPERTY:
|
|
|
|
case bitc::METADATA_IMPORTED_ENTITY:
|
|
|
|
case bitc::METADATA_GLOBAL_VAR_EXPR:
|
|
|
|
// We don't expect to see any of these, if we see one, give up on
|
|
|
|
// lazy-loading and fallback.
|
|
|
|
MDStringRef.clear();
|
|
|
|
GlobalMetadataBitPosIndex.clear();
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-12-13 03:34:26 +08:00
|
|
|
/// Parse a METADATA_BLOCK. If ModuleLevel is true then we are parsing
|
|
|
|
/// module level metadata.
|
2016-12-23 10:20:02 +08:00
|
|
|
Error MetadataLoader::MetadataLoaderImpl::parseMetadata(bool ModuleLevel) {
|
2016-12-13 03:34:26 +08:00
|
|
|
if (!ModuleLevel && MetadataList.hasFwdRefs())
|
|
|
|
return error("Invalid metadata: fwd refs into function blocks");
|
|
|
|
|
2017-01-05 06:54:33 +08:00
|
|
|
// Record the entry position so that we can jump back here and efficiently
|
|
|
|
// skip the whole block in case we lazy-load.
|
|
|
|
auto EntryPos = Stream.GetCurrentBitNo();
|
|
|
|
|
2019-06-27 03:50:12 +08:00
|
|
|
if (Error Err = Stream.EnterSubBlock(bitc::METADATA_BLOCK_ID))
|
|
|
|
return Err;
|
2016-12-13 03:34:26 +08:00
|
|
|
|
|
|
|
SmallVector<uint64_t, 64> Record;
|
|
|
|
PlaceholderQueue Placeholders;
|
|
|
|
|
2017-01-05 06:54:33 +08:00
|
|
|
// We lazy-load module-level metadata: we build an index for each record, and
|
|
|
|
// then load individual record as needed, starting with the named metadata.
|
|
|
|
if (ModuleLevel && IsImporting && MetadataList.empty() &&
|
|
|
|
!DisableLazyLoading) {
|
2017-01-08 02:31:38 +08:00
|
|
|
auto SuccessOrErr = lazyLoadModuleMetadataBlock();
|
2017-01-05 06:54:33 +08:00
|
|
|
if (!SuccessOrErr)
|
|
|
|
return SuccessOrErr.takeError();
|
|
|
|
if (SuccessOrErr.get()) {
|
|
|
|
// An index was successfully created and we will be able to load metadata
|
|
|
|
// on-demand.
|
|
|
|
MetadataList.resize(MDStringRef.size() +
|
|
|
|
GlobalMetadataBitPosIndex.size());
|
|
|
|
|
|
|
|
// Reading the named metadata created forward references and/or
|
|
|
|
// placeholders, that we flush here.
|
|
|
|
resolveForwardRefsAndPlaceholders(Placeholders);
|
2017-02-08 01:35:41 +08:00
|
|
|
upgradeDebugInfo();
|
2017-01-05 06:54:33 +08:00
|
|
|
// Return at the beginning of the block, since it is easy to skip it
|
|
|
|
// entirely from there.
|
|
|
|
Stream.ReadBlockEnd(); // Pop the abbrev block context.
|
2019-06-27 03:50:12 +08:00
|
|
|
if (Error Err = IndexCursor.JumpToBit(EntryPos))
|
|
|
|
return Err;
|
|
|
|
if (Error Err = Stream.SkipBlock()) {
|
|
|
|
// FIXME this drops the error on the floor, which
|
|
|
|
// ThinLTO/X86/debuginfo-cu-import.ll relies on.
|
|
|
|
consumeError(std::move(Err));
|
|
|
|
return Error::success();
|
|
|
|
}
|
2017-01-05 06:54:33 +08:00
|
|
|
return Error::success();
|
|
|
|
}
|
|
|
|
// Couldn't load an index, fallback to loading all the block "old-style".
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned NextMetadataNo = MetadataList.size();
|
|
|
|
|
2016-12-13 03:34:26 +08:00
|
|
|
// Read all the records.
|
|
|
|
while (true) {
|
2019-06-27 03:50:12 +08:00
|
|
|
Expected<BitstreamEntry> MaybeEntry = Stream.advanceSkippingSubblocks();
|
|
|
|
if (!MaybeEntry)
|
|
|
|
return MaybeEntry.takeError();
|
|
|
|
BitstreamEntry Entry = MaybeEntry.get();
|
2016-12-13 03:34:26 +08:00
|
|
|
|
|
|
|
switch (Entry.Kind) {
|
|
|
|
case BitstreamEntry::SubBlock: // Handled for us already.
|
|
|
|
case BitstreamEntry::Error:
|
|
|
|
return error("Malformed block");
|
|
|
|
case BitstreamEntry::EndBlock:
|
2017-01-05 06:54:33 +08:00
|
|
|
resolveForwardRefsAndPlaceholders(Placeholders);
|
2017-02-08 01:35:41 +08:00
|
|
|
upgradeDebugInfo();
|
2016-12-13 03:34:26 +08:00
|
|
|
return Error::success();
|
|
|
|
case BitstreamEntry::Record:
|
|
|
|
// The interesting case.
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Read a record.
|
|
|
|
Record.clear();
|
|
|
|
StringRef Blob;
|
2017-01-05 06:54:33 +08:00
|
|
|
++NumMDRecordLoaded;
|
2019-06-27 03:50:12 +08:00
|
|
|
if (Expected<unsigned> MaybeCode =
|
|
|
|
Stream.readRecord(Entry.ID, Record, &Blob)) {
|
|
|
|
if (Error Err = parseOneMetadata(Record, MaybeCode.get(), Placeholders,
|
|
|
|
Blob, NextMetadataNo))
|
|
|
|
return Err;
|
|
|
|
} else
|
|
|
|
return MaybeCode.takeError();
|
2016-12-23 11:59:18 +08:00
|
|
|
}
|
|
|
|
}
|
2016-12-13 03:34:26 +08:00
|
|
|
|
2017-01-05 06:54:33 +08:00
|
|
|
MDString *MetadataLoader::MetadataLoaderImpl::lazyLoadOneMDString(unsigned ID) {
|
|
|
|
++NumMDStringLoaded;
|
|
|
|
if (Metadata *MD = MetadataList.lookup(ID))
|
|
|
|
return cast<MDString>(MD);
|
|
|
|
auto MDS = MDString::get(Context, MDStringRef[ID]);
|
|
|
|
MetadataList.assignValue(MDS, ID);
|
|
|
|
return MDS;
|
|
|
|
}
|
|
|
|
|
|
|
|
void MetadataLoader::MetadataLoaderImpl::lazyLoadOneMetadata(
|
|
|
|
unsigned ID, PlaceholderQueue &Placeholders) {
|
|
|
|
assert(ID < (MDStringRef.size()) + GlobalMetadataBitPosIndex.size());
|
|
|
|
assert(ID >= MDStringRef.size() && "Unexpected lazy-loading of MDString");
|
|
|
|
// Lookup first if the metadata hasn't already been loaded.
|
|
|
|
if (auto *MD = MetadataList.lookup(ID)) {
|
2019-09-26 19:30:47 +08:00
|
|
|
auto *N = cast<MDNode>(MD);
|
2017-01-19 02:36:21 +08:00
|
|
|
if (!N->isTemporary())
|
|
|
|
return;
|
2017-01-05 06:54:33 +08:00
|
|
|
}
|
|
|
|
SmallVector<uint64_t, 64> Record;
|
|
|
|
StringRef Blob;
|
2019-06-27 03:50:12 +08:00
|
|
|
if (Error Err = IndexCursor.JumpToBit(
|
|
|
|
GlobalMetadataBitPosIndex[ID - MDStringRef.size()]))
|
|
|
|
report_fatal_error("lazyLoadOneMetadata failed jumping: " +
|
|
|
|
toString(std::move(Err)));
|
|
|
|
Expected<BitstreamEntry> MaybeEntry = IndexCursor.advanceSkippingSubblocks();
|
|
|
|
if (!MaybeEntry)
|
|
|
|
// FIXME this drops the error on the floor.
|
|
|
|
report_fatal_error("lazyLoadOneMetadata failed advanceSkippingSubblocks: " +
|
|
|
|
toString(MaybeEntry.takeError()));
|
|
|
|
BitstreamEntry Entry = MaybeEntry.get();
|
2017-01-05 06:54:33 +08:00
|
|
|
++NumMDRecordLoaded;
|
2019-06-27 03:50:12 +08:00
|
|
|
if (Expected<unsigned> MaybeCode =
|
|
|
|
IndexCursor.readRecord(Entry.ID, Record, &Blob)) {
|
|
|
|
if (Error Err =
|
|
|
|
parseOneMetadata(Record, MaybeCode.get(), Placeholders, Blob, ID))
|
|
|
|
report_fatal_error("Can't lazyload MD, parseOneMetadata: " +
|
|
|
|
toString(std::move(Err)));
|
|
|
|
} else
|
|
|
|
report_fatal_error("Can't lazyload MD: " + toString(MaybeCode.takeError()));
|
2017-01-05 06:54:33 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Ensure that all forward-references and placeholders are resolved.
|
|
|
|
/// Iteratively lazy-loading metadata on-demand if needed.
|
|
|
|
void MetadataLoader::MetadataLoaderImpl::resolveForwardRefsAndPlaceholders(
|
|
|
|
PlaceholderQueue &Placeholders) {
|
|
|
|
DenseSet<unsigned> Temporaries;
|
|
|
|
while (1) {
|
|
|
|
// Populate Temporaries with the placeholders that haven't been loaded yet.
|
|
|
|
Placeholders.getTemporaries(MetadataList, Temporaries);
|
|
|
|
|
|
|
|
// If we don't have any temporary, or FwdReference, we're done!
|
|
|
|
if (Temporaries.empty() && !MetadataList.hasFwdRefs())
|
|
|
|
break;
|
|
|
|
|
|
|
|
// First, load all the temporaries. This can add new placeholders or
|
|
|
|
// forward references.
|
|
|
|
for (auto ID : Temporaries)
|
|
|
|
lazyLoadOneMetadata(ID, Placeholders);
|
|
|
|
Temporaries.clear();
|
|
|
|
|
|
|
|
// Second, load the forward-references. This can also add new placeholders
|
|
|
|
// or forward references.
|
|
|
|
while (MetadataList.hasFwdRefs())
|
|
|
|
lazyLoadOneMetadata(MetadataList.getNextFwdRef(), Placeholders);
|
|
|
|
}
|
|
|
|
// At this point we don't have any forward reference remaining, or temporary
|
|
|
|
// that haven't been loaded. We can safely drop RAUW support and mark cycles
|
|
|
|
// as resolved.
|
|
|
|
MetadataList.tryToResolveCycles();
|
|
|
|
|
|
|
|
// Finally, everything is in place, we can replace the placeholders operands
|
|
|
|
// with the final node they refer to.
|
|
|
|
Placeholders.flush(MetadataList);
|
|
|
|
}
|
|
|
|
|
2016-12-23 11:59:18 +08:00
|
|
|
Error MetadataLoader::MetadataLoaderImpl::parseOneMetadata(
|
|
|
|
SmallVectorImpl<uint64_t> &Record, unsigned Code,
|
2017-01-05 06:54:33 +08:00
|
|
|
PlaceholderQueue &Placeholders, StringRef Blob, unsigned &NextMetadataNo) {
|
2016-12-13 03:34:26 +08:00
|
|
|
|
2016-12-23 11:59:18 +08:00
|
|
|
bool IsDistinct = false;
|
|
|
|
auto getMD = [&](unsigned ID) -> Metadata * {
|
2017-01-05 06:54:33 +08:00
|
|
|
if (ID < MDStringRef.size())
|
|
|
|
return lazyLoadOneMDString(ID);
|
2017-01-19 02:36:21 +08:00
|
|
|
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.
|
2016-12-23 11:59:18 +08:00
|
|
|
return MetadataList.getMetadataFwdRef(ID);
|
2017-01-19 02:36:21 +08:00
|
|
|
}
|
2016-12-23 11:59:18 +08:00
|
|
|
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.
|
2017-01-05 06:54:33 +08:00
|
|
|
auto MDS = getMDOrNull(ID);
|
|
|
|
return cast_or_null<MDString>(MDS);
|
2016-12-23 11:59:18 +08:00
|
|
|
};
|
2016-12-13 03:34:26 +08:00
|
|
|
|
2016-12-23 11:59:18 +08:00
|
|
|
// Support for old type refs.
|
|
|
|
auto getDITypeRefOrNull = [&](unsigned ID) {
|
|
|
|
return MetadataList.upgradeTypeRef(getMDOrNull(ID));
|
|
|
|
};
|
2016-12-13 03:34:26 +08:00
|
|
|
|
2016-12-23 11:59:18 +08:00
|
|
|
#define GET_OR_DISTINCT(CLASS, ARGS) \
|
|
|
|
(IsDistinct ? CLASS::getDistinct ARGS : CLASS::get ARGS)
|
2016-12-13 03:34:26 +08:00
|
|
|
|
2016-12-23 11:59:18 +08:00
|
|
|
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();
|
2019-06-27 03:50:12 +08:00
|
|
|
Expected<unsigned> MaybeCode = Stream.ReadCode();
|
|
|
|
if (!MaybeCode)
|
|
|
|
return MaybeCode.takeError();
|
|
|
|
Code = MaybeCode.get();
|
2016-12-23 11:59:18 +08:00
|
|
|
|
2017-01-05 06:54:33 +08:00
|
|
|
++NumMDRecordLoaded;
|
2019-06-27 03:50:12 +08:00
|
|
|
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();
|
2016-12-23 11:59:18 +08:00
|
|
|
|
|
|
|
// 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)
|
2018-11-15 05:57:51 +08:00
|
|
|
return error("Invalid named metadata: expect fwd ref to MDNode");
|
2016-12-23 11:59:18 +08:00
|
|
|
NMD->addOperand(MD);
|
2016-12-13 03:34:26 +08:00
|
|
|
}
|
2016-12-23 11:59:18 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case bitc::METADATA_OLD_FN_NODE: {
|
|
|
|
// FIXME: Remove in 4.0.
|
|
|
|
// 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 = [&] {
|
Avoid using unspecified ordering in MetadataLoader::MetadataLoaderImpl::parseOneMetadata.
Summary:
MetadataLoader::MetadataLoaderImpl::parseOneMetadata uses
the following construct in a number of places:
```
MetadataList.assignValue(<...>, NextMetadataNo++);
```
There, NextMetadataNo gets incremented, and since the order
of arguments evaluation is not specified, that can happen
before or after other arguments are evaluated.
In a few cases the other arguments indirectly use NextMetadataNo.
For instance, it's
```
MetadataList.assignValue(
GET_OR_DISTINCT(DIModule,
(Context, getMDOrNull(Record[1]),
getMDString(Record[2]), getMDString(Record[3]),
getMDString(Record[4]), getMDString(Record[5]))),
NextMetadataNo++);
```
getMDOrNull calls getMD that uses NextMetadataNo:
```
MetadataList.getMetadataFwdRef(NextMetadataNo);
```
Therefore, the order of evaluation becomes important. That caused
a very subtle LLD crash that only happens if compiled with GCC or
if LLD is built with LTO. In the case if LLD is compiled with Clang
and regular linking mode, everything worked as intended.
This change extracts incrementing of NextMetadataNo outside of
the arguments list to guarantee the correct order of evaluation.
For the record, this has taken 3 days to track to the origin. It all
started with a ThinLTO bot in Chrome not being able to link a target
if debug info is enabled.
Reviewers: pcc, mehdi_amini
Reviewed By: mehdi_amini
Subscribers: aprantl, llvm-commits
Differential Revision: https://reviews.llvm.org/D29204
llvm-svn: 293291
2017-01-27 23:54:49 +08:00
|
|
|
MetadataList.assignValue(MDNode::get(Context, None), NextMetadataNo);
|
|
|
|
NextMetadataNo++;
|
2016-12-23 11:59:18 +08:00
|
|
|
};
|
|
|
|
if (Record.size() != 2) {
|
|
|
|
dropRecord();
|
2016-12-13 03:34:26 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2016-12-23 11:59:18 +08:00
|
|
|
Type *Ty = getTypeByID(Record[0]);
|
|
|
|
if (Ty->isMetadataTy() || Ty->isVoidTy()) {
|
|
|
|
dropRecord();
|
2016-12-13 03:34:26 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2016-12-23 11:59:18 +08:00
|
|
|
MetadataList.assignValue(
|
|
|
|
LocalAsMetadata::get(ValueList.getValueFwdRef(Record[1], Ty)),
|
Avoid using unspecified ordering in MetadataLoader::MetadataLoaderImpl::parseOneMetadata.
Summary:
MetadataLoader::MetadataLoaderImpl::parseOneMetadata uses
the following construct in a number of places:
```
MetadataList.assignValue(<...>, NextMetadataNo++);
```
There, NextMetadataNo gets incremented, and since the order
of arguments evaluation is not specified, that can happen
before or after other arguments are evaluated.
In a few cases the other arguments indirectly use NextMetadataNo.
For instance, it's
```
MetadataList.assignValue(
GET_OR_DISTINCT(DIModule,
(Context, getMDOrNull(Record[1]),
getMDString(Record[2]), getMDString(Record[3]),
getMDString(Record[4]), getMDString(Record[5]))),
NextMetadataNo++);
```
getMDOrNull calls getMD that uses NextMetadataNo:
```
MetadataList.getMetadataFwdRef(NextMetadataNo);
```
Therefore, the order of evaluation becomes important. That caused
a very subtle LLD crash that only happens if compiled with GCC or
if LLD is built with LTO. In the case if LLD is compiled with Clang
and regular linking mode, everything worked as intended.
This change extracts incrementing of NextMetadataNo outside of
the arguments list to guarantee the correct order of evaluation.
For the record, this has taken 3 days to track to the origin. It all
started with a ThinLTO bot in Chrome not being able to link a target
if debug info is enabled.
Reviewers: pcc, mehdi_amini
Reviewed By: mehdi_amini
Subscribers: aprantl, llvm-commits
Differential Revision: https://reviews.llvm.org/D29204
llvm-svn: 293291
2017-01-27 23:54:49 +08:00
|
|
|
NextMetadataNo);
|
|
|
|
NextMetadataNo++;
|
2016-12-23 11:59:18 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case bitc::METADATA_OLD_NODE: {
|
|
|
|
// FIXME: Remove in 4.0.
|
|
|
|
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)
|
2016-12-13 03:34:26 +08:00
|
|
|
return error("Invalid record");
|
2016-12-23 11:59:18 +08:00
|
|
|
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);
|
2016-12-13 03:34:26 +08:00
|
|
|
}
|
Avoid using unspecified ordering in MetadataLoader::MetadataLoaderImpl::parseOneMetadata.
Summary:
MetadataLoader::MetadataLoaderImpl::parseOneMetadata uses
the following construct in a number of places:
```
MetadataList.assignValue(<...>, NextMetadataNo++);
```
There, NextMetadataNo gets incremented, and since the order
of arguments evaluation is not specified, that can happen
before or after other arguments are evaluated.
In a few cases the other arguments indirectly use NextMetadataNo.
For instance, it's
```
MetadataList.assignValue(
GET_OR_DISTINCT(DIModule,
(Context, getMDOrNull(Record[1]),
getMDString(Record[2]), getMDString(Record[3]),
getMDString(Record[4]), getMDString(Record[5]))),
NextMetadataNo++);
```
getMDOrNull calls getMD that uses NextMetadataNo:
```
MetadataList.getMetadataFwdRef(NextMetadataNo);
```
Therefore, the order of evaluation becomes important. That caused
a very subtle LLD crash that only happens if compiled with GCC or
if LLD is built with LTO. In the case if LLD is compiled with Clang
and regular linking mode, everything worked as intended.
This change extracts incrementing of NextMetadataNo outside of
the arguments list to guarantee the correct order of evaluation.
For the record, this has taken 3 days to track to the origin. It all
started with a ThinLTO bot in Chrome not being able to link a target
if debug info is enabled.
Reviewers: pcc, mehdi_amini
Reviewed By: mehdi_amini
Subscribers: aprantl, llvm-commits
Differential Revision: https://reviews.llvm.org/D29204
llvm-svn: 293291
2017-01-27 23:54:49 +08:00
|
|
|
MetadataList.assignValue(MDNode::get(Context, Elts), NextMetadataNo);
|
|
|
|
NextMetadataNo++;
|
2016-12-23 11:59:18 +08:00
|
|
|
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)),
|
Avoid using unspecified ordering in MetadataLoader::MetadataLoaderImpl::parseOneMetadata.
Summary:
MetadataLoader::MetadataLoaderImpl::parseOneMetadata uses
the following construct in a number of places:
```
MetadataList.assignValue(<...>, NextMetadataNo++);
```
There, NextMetadataNo gets incremented, and since the order
of arguments evaluation is not specified, that can happen
before or after other arguments are evaluated.
In a few cases the other arguments indirectly use NextMetadataNo.
For instance, it's
```
MetadataList.assignValue(
GET_OR_DISTINCT(DIModule,
(Context, getMDOrNull(Record[1]),
getMDString(Record[2]), getMDString(Record[3]),
getMDString(Record[4]), getMDString(Record[5]))),
NextMetadataNo++);
```
getMDOrNull calls getMD that uses NextMetadataNo:
```
MetadataList.getMetadataFwdRef(NextMetadataNo);
```
Therefore, the order of evaluation becomes important. That caused
a very subtle LLD crash that only happens if compiled with GCC or
if LLD is built with LTO. In the case if LLD is compiled with Clang
and regular linking mode, everything worked as intended.
This change extracts incrementing of NextMetadataNo outside of
the arguments list to guarantee the correct order of evaluation.
For the record, this has taken 3 days to track to the origin. It all
started with a ThinLTO bot in Chrome not being able to link a target
if debug info is enabled.
Reviewers: pcc, mehdi_amini
Reviewed By: mehdi_amini
Subscribers: aprantl, llvm-commits
Differential Revision: https://reviews.llvm.org/D29204
llvm-svn: 293291
2017-01-27 23:54:49 +08:00
|
|
|
NextMetadataNo);
|
|
|
|
NextMetadataNo++;
|
2016-12-23 11:59:18 +08:00
|
|
|
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),
|
Avoid using unspecified ordering in MetadataLoader::MetadataLoaderImpl::parseOneMetadata.
Summary:
MetadataLoader::MetadataLoaderImpl::parseOneMetadata uses
the following construct in a number of places:
```
MetadataList.assignValue(<...>, NextMetadataNo++);
```
There, NextMetadataNo gets incremented, and since the order
of arguments evaluation is not specified, that can happen
before or after other arguments are evaluated.
In a few cases the other arguments indirectly use NextMetadataNo.
For instance, it's
```
MetadataList.assignValue(
GET_OR_DISTINCT(DIModule,
(Context, getMDOrNull(Record[1]),
getMDString(Record[2]), getMDString(Record[3]),
getMDString(Record[4]), getMDString(Record[5]))),
NextMetadataNo++);
```
getMDOrNull calls getMD that uses NextMetadataNo:
```
MetadataList.getMetadataFwdRef(NextMetadataNo);
```
Therefore, the order of evaluation becomes important. That caused
a very subtle LLD crash that only happens if compiled with GCC or
if LLD is built with LTO. In the case if LLD is compiled with Clang
and regular linking mode, everything worked as intended.
This change extracts incrementing of NextMetadataNo outside of
the arguments list to guarantee the correct order of evaluation.
For the record, this has taken 3 days to track to the origin. It all
started with a ThinLTO bot in Chrome not being able to link a target
if debug info is enabled.
Reviewers: pcc, mehdi_amini
Reviewed By: mehdi_amini
Subscribers: aprantl, llvm-commits
Differential Revision: https://reviews.llvm.org/D29204
llvm-svn: 293291
2017-01-27 23:54:49 +08:00
|
|
|
NextMetadataNo);
|
|
|
|
NextMetadataNo++;
|
2016-12-23 11:59:18 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case bitc::METADATA_LOCATION: {
|
2018-09-21 02:59:33 +08:00
|
|
|
if (Record.size() != 5 && Record.size() != 6)
|
2016-12-23 11:59:18 +08:00
|
|
|
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]);
|
2018-09-21 02:59:33 +08:00
|
|
|
bool ImplicitCode = Record.size() == 6 && Record[5];
|
2016-12-23 11:59:18 +08:00
|
|
|
MetadataList.assignValue(
|
[IR] Add a boolean field in DILocation to know if a line must covered or not
Summary:
Some lines have a hit counter where they should not have one.
For example, in C++, some cleanup is adding at the end of a scope represented by a '}'.
So such a line has a hit counter where a user expects to not have one.
The goal of the patch is to add this information in DILocation which is used to get the covered lines in GCOVProfiling.cpp.
A following patch in clang will add this information when generating IR (https://reviews.llvm.org/D49916).
Reviewers: marco-c, davidxl, vsk, javed.absar, rnk
Reviewed By: rnk
Subscribers: eraman, xur, danielcdh, aprantl, rnk, dblaikie, #debug-info, vsk, llvm-commits, sylvestre.ledru
Tags: #debug-info
Differential Revision: https://reviews.llvm.org/D49915
llvm-svn: 342631
2018-09-20 16:53:06 +08:00
|
|
|
GET_OR_DISTINCT(DILocation, (Context, Line, Column, Scope, InlinedAt,
|
|
|
|
ImplicitCode)),
|
Avoid using unspecified ordering in MetadataLoader::MetadataLoaderImpl::parseOneMetadata.
Summary:
MetadataLoader::MetadataLoaderImpl::parseOneMetadata uses
the following construct in a number of places:
```
MetadataList.assignValue(<...>, NextMetadataNo++);
```
There, NextMetadataNo gets incremented, and since the order
of arguments evaluation is not specified, that can happen
before or after other arguments are evaluated.
In a few cases the other arguments indirectly use NextMetadataNo.
For instance, it's
```
MetadataList.assignValue(
GET_OR_DISTINCT(DIModule,
(Context, getMDOrNull(Record[1]),
getMDString(Record[2]), getMDString(Record[3]),
getMDString(Record[4]), getMDString(Record[5]))),
NextMetadataNo++);
```
getMDOrNull calls getMD that uses NextMetadataNo:
```
MetadataList.getMetadataFwdRef(NextMetadataNo);
```
Therefore, the order of evaluation becomes important. That caused
a very subtle LLD crash that only happens if compiled with GCC or
if LLD is built with LTO. In the case if LLD is compiled with Clang
and regular linking mode, everything worked as intended.
This change extracts incrementing of NextMetadataNo outside of
the arguments list to guarantee the correct order of evaluation.
For the record, this has taken 3 days to track to the origin. It all
started with a ThinLTO bot in Chrome not being able to link a target
if debug info is enabled.
Reviewers: pcc, mehdi_amini
Reviewed By: mehdi_amini
Subscribers: aprantl, llvm-commits
Differential Revision: https://reviews.llvm.org/D29204
llvm-svn: 293291
2017-01-27 23:54:49 +08:00
|
|
|
NextMetadataNo);
|
|
|
|
NextMetadataNo++;
|
2016-12-23 11:59:18 +08:00
|
|
|
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)),
|
Avoid using unspecified ordering in MetadataLoader::MetadataLoaderImpl::parseOneMetadata.
Summary:
MetadataLoader::MetadataLoaderImpl::parseOneMetadata uses
the following construct in a number of places:
```
MetadataList.assignValue(<...>, NextMetadataNo++);
```
There, NextMetadataNo gets incremented, and since the order
of arguments evaluation is not specified, that can happen
before or after other arguments are evaluated.
In a few cases the other arguments indirectly use NextMetadataNo.
For instance, it's
```
MetadataList.assignValue(
GET_OR_DISTINCT(DIModule,
(Context, getMDOrNull(Record[1]),
getMDString(Record[2]), getMDString(Record[3]),
getMDString(Record[4]), getMDString(Record[5]))),
NextMetadataNo++);
```
getMDOrNull calls getMD that uses NextMetadataNo:
```
MetadataList.getMetadataFwdRef(NextMetadataNo);
```
Therefore, the order of evaluation becomes important. That caused
a very subtle LLD crash that only happens if compiled with GCC or
if LLD is built with LTO. In the case if LLD is compiled with Clang
and regular linking mode, everything worked as intended.
This change extracts incrementing of NextMetadataNo outside of
the arguments list to guarantee the correct order of evaluation.
For the record, this has taken 3 days to track to the origin. It all
started with a ThinLTO bot in Chrome not being able to link a target
if debug info is enabled.
Reviewers: pcc, mehdi_amini
Reviewed By: mehdi_amini
Subscribers: aprantl, llvm-commits
Differential Revision: https://reviews.llvm.org/D29204
llvm-svn: 293291
2017-01-27 23:54:49 +08:00
|
|
|
NextMetadataNo);
|
|
|
|
NextMetadataNo++;
|
2016-12-23 11:59:18 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case bitc::METADATA_SUBRANGE: {
|
[Metadata] Extend 'count' field of DISubrange to take a metadata node
Summary:
This patch extends the DISubrange 'count' field to take either a
(signed) constant integer value or a reference to a DILocalVariable
or DIGlobalVariable.
This is patch [1/3] in a series to extend LLVM's DISubrange Metadata
node to support debugging of C99 variable length arrays and vectors with
runtime length like the Scalable Vector Extension for AArch64. It is
also a first step towards representing more complex cases like arrays
in Fortran.
Reviewers: echristo, pcc, aprantl, dexonsmith, clayborg, kristof.beyls, dblaikie
Reviewed By: aprantl
Subscribers: rnk, probinson, fhahn, aemerson, rengolin, JDevlieghere, llvm-commits
Differential Revision: https://reviews.llvm.org/D41695
llvm-svn: 323313
2018-01-24 17:56:07 +08:00
|
|
|
Metadata *Val = nullptr;
|
|
|
|
// Operand 'count' is interpreted as:
|
|
|
|
// - Signed integer (version 0)
|
|
|
|
// - Metadata node (version 1)
|
|
|
|
switch (Record[0] >> 1) {
|
|
|
|
case 0:
|
|
|
|
Val = GET_OR_DISTINCT(DISubrange,
|
|
|
|
(Context, Record[1], unrotateSign(Record.back())));
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
Val = GET_OR_DISTINCT(DISubrange, (Context, getMDOrNull(Record[1]),
|
|
|
|
unrotateSign(Record.back())));
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return error("Invalid record: Unsupported version of DISubrange");
|
|
|
|
}
|
2016-12-23 11:59:18 +08:00
|
|
|
|
[Metadata] Extend 'count' field of DISubrange to take a metadata node
Summary:
This patch extends the DISubrange 'count' field to take either a
(signed) constant integer value or a reference to a DILocalVariable
or DIGlobalVariable.
This is patch [1/3] in a series to extend LLVM's DISubrange Metadata
node to support debugging of C99 variable length arrays and vectors with
runtime length like the Scalable Vector Extension for AArch64. It is
also a first step towards representing more complex cases like arrays
in Fortran.
Reviewers: echristo, pcc, aprantl, dexonsmith, clayborg, kristof.beyls, dblaikie
Reviewed By: aprantl
Subscribers: rnk, probinson, fhahn, aemerson, rengolin, JDevlieghere, llvm-commits
Differential Revision: https://reviews.llvm.org/D41695
llvm-svn: 323313
2018-01-24 17:56:07 +08:00
|
|
|
MetadataList.assignValue(Val, NextMetadataNo);
|
|
|
|
IsDistinct = Record[0] & 1;
|
Avoid using unspecified ordering in MetadataLoader::MetadataLoaderImpl::parseOneMetadata.
Summary:
MetadataLoader::MetadataLoaderImpl::parseOneMetadata uses
the following construct in a number of places:
```
MetadataList.assignValue(<...>, NextMetadataNo++);
```
There, NextMetadataNo gets incremented, and since the order
of arguments evaluation is not specified, that can happen
before or after other arguments are evaluated.
In a few cases the other arguments indirectly use NextMetadataNo.
For instance, it's
```
MetadataList.assignValue(
GET_OR_DISTINCT(DIModule,
(Context, getMDOrNull(Record[1]),
getMDString(Record[2]), getMDString(Record[3]),
getMDString(Record[4]), getMDString(Record[5]))),
NextMetadataNo++);
```
getMDOrNull calls getMD that uses NextMetadataNo:
```
MetadataList.getMetadataFwdRef(NextMetadataNo);
```
Therefore, the order of evaluation becomes important. That caused
a very subtle LLD crash that only happens if compiled with GCC or
if LLD is built with LTO. In the case if LLD is compiled with Clang
and regular linking mode, everything worked as intended.
This change extracts incrementing of NextMetadataNo outside of
the arguments list to guarantee the correct order of evaluation.
For the record, this has taken 3 days to track to the origin. It all
started with a ThinLTO bot in Chrome not being able to link a target
if debug info is enabled.
Reviewers: pcc, mehdi_amini
Reviewed By: mehdi_amini
Subscribers: aprantl, llvm-commits
Differential Revision: https://reviews.llvm.org/D29204
llvm-svn: 293291
2017-01-27 23:54:49 +08:00
|
|
|
NextMetadataNo++;
|
2016-12-23 11:59:18 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case bitc::METADATA_ENUMERATOR: {
|
|
|
|
if (Record.size() != 3)
|
|
|
|
return error("Invalid record");
|
|
|
|
|
2018-02-13 00:10:09 +08:00
|
|
|
IsDistinct = Record[0] & 1;
|
|
|
|
bool IsUnsigned = Record[0] & 2;
|
2016-12-23 11:59:18 +08:00
|
|
|
MetadataList.assignValue(
|
|
|
|
GET_OR_DISTINCT(DIEnumerator, (Context, unrotateSign(Record[1]),
|
2018-02-13 00:10:09 +08:00
|
|
|
IsUnsigned, getMDString(Record[2]))),
|
Avoid using unspecified ordering in MetadataLoader::MetadataLoaderImpl::parseOneMetadata.
Summary:
MetadataLoader::MetadataLoaderImpl::parseOneMetadata uses
the following construct in a number of places:
```
MetadataList.assignValue(<...>, NextMetadataNo++);
```
There, NextMetadataNo gets incremented, and since the order
of arguments evaluation is not specified, that can happen
before or after other arguments are evaluated.
In a few cases the other arguments indirectly use NextMetadataNo.
For instance, it's
```
MetadataList.assignValue(
GET_OR_DISTINCT(DIModule,
(Context, getMDOrNull(Record[1]),
getMDString(Record[2]), getMDString(Record[3]),
getMDString(Record[4]), getMDString(Record[5]))),
NextMetadataNo++);
```
getMDOrNull calls getMD that uses NextMetadataNo:
```
MetadataList.getMetadataFwdRef(NextMetadataNo);
```
Therefore, the order of evaluation becomes important. That caused
a very subtle LLD crash that only happens if compiled with GCC or
if LLD is built with LTO. In the case if LLD is compiled with Clang
and regular linking mode, everything worked as intended.
This change extracts incrementing of NextMetadataNo outside of
the arguments list to guarantee the correct order of evaluation.
For the record, this has taken 3 days to track to the origin. It all
started with a ThinLTO bot in Chrome not being able to link a target
if debug info is enabled.
Reviewers: pcc, mehdi_amini
Reviewed By: mehdi_amini
Subscribers: aprantl, llvm-commits
Differential Revision: https://reviews.llvm.org/D29204
llvm-svn: 293291
2017-01-27 23:54:49 +08:00
|
|
|
NextMetadataNo);
|
|
|
|
NextMetadataNo++;
|
2016-12-23 11:59:18 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case bitc::METADATA_BASIC_TYPE: {
|
2018-08-15 03:35:34 +08:00
|
|
|
if (Record.size() < 6 || Record.size() > 7)
|
2016-12-23 11:59:18 +08:00
|
|
|
return error("Invalid record");
|
|
|
|
|
|
|
|
IsDistinct = Record[0];
|
2018-08-15 03:35:34 +08:00
|
|
|
DINode::DIFlags Flags = (Record.size() > 6) ?
|
|
|
|
static_cast<DINode::DIFlags>(Record[6]) : DINode::FlagZero;
|
|
|
|
|
2016-12-23 11:59:18 +08:00
|
|
|
MetadataList.assignValue(
|
|
|
|
GET_OR_DISTINCT(DIBasicType,
|
|
|
|
(Context, Record[1], getMDString(Record[2]), Record[3],
|
2018-08-15 03:35:34 +08:00
|
|
|
Record[4], Record[5], Flags)),
|
Avoid using unspecified ordering in MetadataLoader::MetadataLoaderImpl::parseOneMetadata.
Summary:
MetadataLoader::MetadataLoaderImpl::parseOneMetadata uses
the following construct in a number of places:
```
MetadataList.assignValue(<...>, NextMetadataNo++);
```
There, NextMetadataNo gets incremented, and since the order
of arguments evaluation is not specified, that can happen
before or after other arguments are evaluated.
In a few cases the other arguments indirectly use NextMetadataNo.
For instance, it's
```
MetadataList.assignValue(
GET_OR_DISTINCT(DIModule,
(Context, getMDOrNull(Record[1]),
getMDString(Record[2]), getMDString(Record[3]),
getMDString(Record[4]), getMDString(Record[5]))),
NextMetadataNo++);
```
getMDOrNull calls getMD that uses NextMetadataNo:
```
MetadataList.getMetadataFwdRef(NextMetadataNo);
```
Therefore, the order of evaluation becomes important. That caused
a very subtle LLD crash that only happens if compiled with GCC or
if LLD is built with LTO. In the case if LLD is compiled with Clang
and regular linking mode, everything worked as intended.
This change extracts incrementing of NextMetadataNo outside of
the arguments list to guarantee the correct order of evaluation.
For the record, this has taken 3 days to track to the origin. It all
started with a ThinLTO bot in Chrome not being able to link a target
if debug info is enabled.
Reviewers: pcc, mehdi_amini
Reviewed By: mehdi_amini
Subscribers: aprantl, llvm-commits
Differential Revision: https://reviews.llvm.org/D29204
llvm-svn: 293291
2017-01-27 23:54:49 +08:00
|
|
|
NextMetadataNo);
|
|
|
|
NextMetadataNo++;
|
2016-12-23 11:59:18 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case bitc::METADATA_DERIVED_TYPE: {
|
2017-03-09 07:55:44 +08:00
|
|
|
if (Record.size() < 12 || Record.size() > 13)
|
2016-12-23 11:59:18 +08:00
|
|
|
return error("Invalid record");
|
|
|
|
|
2017-03-09 07:55:44 +08:00
|
|
|
// 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;
|
|
|
|
|
2016-12-23 11:59:18 +08:00
|
|
|
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],
|
2017-03-09 07:55:44 +08:00
|
|
|
Record[9], DWARFAddressSpace, Flags,
|
|
|
|
getDITypeRefOrNull(Record[11]))),
|
Avoid using unspecified ordering in MetadataLoader::MetadataLoaderImpl::parseOneMetadata.
Summary:
MetadataLoader::MetadataLoaderImpl::parseOneMetadata uses
the following construct in a number of places:
```
MetadataList.assignValue(<...>, NextMetadataNo++);
```
There, NextMetadataNo gets incremented, and since the order
of arguments evaluation is not specified, that can happen
before or after other arguments are evaluated.
In a few cases the other arguments indirectly use NextMetadataNo.
For instance, it's
```
MetadataList.assignValue(
GET_OR_DISTINCT(DIModule,
(Context, getMDOrNull(Record[1]),
getMDString(Record[2]), getMDString(Record[3]),
getMDString(Record[4]), getMDString(Record[5]))),
NextMetadataNo++);
```
getMDOrNull calls getMD that uses NextMetadataNo:
```
MetadataList.getMetadataFwdRef(NextMetadataNo);
```
Therefore, the order of evaluation becomes important. That caused
a very subtle LLD crash that only happens if compiled with GCC or
if LLD is built with LTO. In the case if LLD is compiled with Clang
and regular linking mode, everything worked as intended.
This change extracts incrementing of NextMetadataNo outside of
the arguments list to guarantee the correct order of evaluation.
For the record, this has taken 3 days to track to the origin. It all
started with a ThinLTO bot in Chrome not being able to link a target
if debug info is enabled.
Reviewers: pcc, mehdi_amini
Reviewed By: mehdi_amini
Subscribers: aprantl, llvm-commits
Differential Revision: https://reviews.llvm.org/D29204
llvm-svn: 293291
2017-01-27 23:54:49 +08:00
|
|
|
NextMetadataNo);
|
|
|
|
NextMetadataNo++;
|
2016-12-23 11:59:18 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case bitc::METADATA_COMPOSITE_TYPE: {
|
2018-02-07 07:45:59 +08:00
|
|
|
if (Record.size() < 16 || Record.size() > 17)
|
2016-12-23 11:59:18 +08:00
|
|
|
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;
|
2018-02-07 07:45:59 +08:00
|
|
|
Metadata *Discriminator = nullptr;
|
2016-12-23 11:59:18 +08:00
|
|
|
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.
|
2017-01-04 07:19:29 +08:00
|
|
|
if (IsImporting && !ImportFullTypeDefinitions && Identifier &&
|
2016-12-23 11:59:18 +08:00
|
|
|
(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]);
|
2018-02-07 07:45:59 +08:00
|
|
|
if (Record.size() > 16)
|
|
|
|
Discriminator = getMDOrNull(Record[16]);
|
2016-12-13 03:34:26 +08:00
|
|
|
}
|
2016-12-23 11:59:18 +08:00
|
|
|
DICompositeType *CT = nullptr;
|
|
|
|
if (Identifier)
|
|
|
|
CT = DICompositeType::buildODRType(
|
|
|
|
Context, *Identifier, Tag, Name, File, Line, Scope, BaseType,
|
|
|
|
SizeInBits, AlignInBits, OffsetInBits, Flags, Elements, RuntimeLang,
|
2018-02-07 07:45:59 +08:00
|
|
|
VTableHolder, TemplateParams, Discriminator);
|
2016-12-23 11:59:18 +08:00
|
|
|
|
|
|
|
// 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,
|
2018-09-21 20:03:14 +08:00
|
|
|
Identifier, Discriminator));
|
2016-12-23 11:59:18 +08:00
|
|
|
if (!IsNotUsedInTypeRef && Identifier)
|
|
|
|
MetadataList.addTypeRef(*Identifier, *cast<DICompositeType>(CT));
|
|
|
|
|
Avoid using unspecified ordering in MetadataLoader::MetadataLoaderImpl::parseOneMetadata.
Summary:
MetadataLoader::MetadataLoaderImpl::parseOneMetadata uses
the following construct in a number of places:
```
MetadataList.assignValue(<...>, NextMetadataNo++);
```
There, NextMetadataNo gets incremented, and since the order
of arguments evaluation is not specified, that can happen
before or after other arguments are evaluated.
In a few cases the other arguments indirectly use NextMetadataNo.
For instance, it's
```
MetadataList.assignValue(
GET_OR_DISTINCT(DIModule,
(Context, getMDOrNull(Record[1]),
getMDString(Record[2]), getMDString(Record[3]),
getMDString(Record[4]), getMDString(Record[5]))),
NextMetadataNo++);
```
getMDOrNull calls getMD that uses NextMetadataNo:
```
MetadataList.getMetadataFwdRef(NextMetadataNo);
```
Therefore, the order of evaluation becomes important. That caused
a very subtle LLD crash that only happens if compiled with GCC or
if LLD is built with LTO. In the case if LLD is compiled with Clang
and regular linking mode, everything worked as intended.
This change extracts incrementing of NextMetadataNo outside of
the arguments list to guarantee the correct order of evaluation.
For the record, this has taken 3 days to track to the origin. It all
started with a ThinLTO bot in Chrome not being able to link a target
if debug info is enabled.
Reviewers: pcc, mehdi_amini
Reviewed By: mehdi_amini
Subscribers: aprantl, llvm-commits
Differential Revision: https://reviews.llvm.org/D29204
llvm-svn: 293291
2017-01-27 23:54:49 +08:00
|
|
|
MetadataList.assignValue(CT, NextMetadataNo);
|
|
|
|
NextMetadataNo++;
|
2016-12-23 11:59:18 +08:00
|
|
|
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)),
|
Avoid using unspecified ordering in MetadataLoader::MetadataLoaderImpl::parseOneMetadata.
Summary:
MetadataLoader::MetadataLoaderImpl::parseOneMetadata uses
the following construct in a number of places:
```
MetadataList.assignValue(<...>, NextMetadataNo++);
```
There, NextMetadataNo gets incremented, and since the order
of arguments evaluation is not specified, that can happen
before or after other arguments are evaluated.
In a few cases the other arguments indirectly use NextMetadataNo.
For instance, it's
```
MetadataList.assignValue(
GET_OR_DISTINCT(DIModule,
(Context, getMDOrNull(Record[1]),
getMDString(Record[2]), getMDString(Record[3]),
getMDString(Record[4]), getMDString(Record[5]))),
NextMetadataNo++);
```
getMDOrNull calls getMD that uses NextMetadataNo:
```
MetadataList.getMetadataFwdRef(NextMetadataNo);
```
Therefore, the order of evaluation becomes important. That caused
a very subtle LLD crash that only happens if compiled with GCC or
if LLD is built with LTO. In the case if LLD is compiled with Clang
and regular linking mode, everything worked as intended.
This change extracts incrementing of NextMetadataNo outside of
the arguments list to guarantee the correct order of evaluation.
For the record, this has taken 3 days to track to the origin. It all
started with a ThinLTO bot in Chrome not being able to link a target
if debug info is enabled.
Reviewers: pcc, mehdi_amini
Reviewed By: mehdi_amini
Subscribers: aprantl, llvm-commits
Differential Revision: https://reviews.llvm.org/D29204
llvm-svn: 293291
2017-01-27 23:54:49 +08:00
|
|
|
NextMetadataNo);
|
|
|
|
NextMetadataNo++;
|
2016-12-23 11:59:18 +08:00
|
|
|
break;
|
|
|
|
}
|
2016-12-13 03:34:26 +08:00
|
|
|
|
2016-12-23 11:59:18 +08:00
|
|
|
case bitc::METADATA_MODULE: {
|
|
|
|
if (Record.size() != 6)
|
|
|
|
return error("Invalid record");
|
|
|
|
|
|
|
|
IsDistinct = Record[0];
|
|
|
|
MetadataList.assignValue(
|
|
|
|
GET_OR_DISTINCT(DIModule,
|
|
|
|
(Context, getMDOrNull(Record[1]),
|
|
|
|
getMDString(Record[2]), getMDString(Record[3]),
|
|
|
|
getMDString(Record[4]), getMDString(Record[5]))),
|
Avoid using unspecified ordering in MetadataLoader::MetadataLoaderImpl::parseOneMetadata.
Summary:
MetadataLoader::MetadataLoaderImpl::parseOneMetadata uses
the following construct in a number of places:
```
MetadataList.assignValue(<...>, NextMetadataNo++);
```
There, NextMetadataNo gets incremented, and since the order
of arguments evaluation is not specified, that can happen
before or after other arguments are evaluated.
In a few cases the other arguments indirectly use NextMetadataNo.
For instance, it's
```
MetadataList.assignValue(
GET_OR_DISTINCT(DIModule,
(Context, getMDOrNull(Record[1]),
getMDString(Record[2]), getMDString(Record[3]),
getMDString(Record[4]), getMDString(Record[5]))),
NextMetadataNo++);
```
getMDOrNull calls getMD that uses NextMetadataNo:
```
MetadataList.getMetadataFwdRef(NextMetadataNo);
```
Therefore, the order of evaluation becomes important. That caused
a very subtle LLD crash that only happens if compiled with GCC or
if LLD is built with LTO. In the case if LLD is compiled with Clang
and regular linking mode, everything worked as intended.
This change extracts incrementing of NextMetadataNo outside of
the arguments list to guarantee the correct order of evaluation.
For the record, this has taken 3 days to track to the origin. It all
started with a ThinLTO bot in Chrome not being able to link a target
if debug info is enabled.
Reviewers: pcc, mehdi_amini
Reviewed By: mehdi_amini
Subscribers: aprantl, llvm-commits
Differential Revision: https://reviews.llvm.org/D29204
llvm-svn: 293291
2017-01-27 23:54:49 +08:00
|
|
|
NextMetadataNo);
|
|
|
|
NextMetadataNo++;
|
2016-12-23 11:59:18 +08:00
|
|
|
break;
|
|
|
|
}
|
2016-12-13 03:34:26 +08:00
|
|
|
|
2016-12-23 11:59:18 +08:00
|
|
|
case bitc::METADATA_FILE: {
|
2018-02-24 07:01:06 +08:00
|
|
|
if (Record.size() != 3 && Record.size() != 5 && Record.size() != 6)
|
2016-12-23 11:59:18 +08:00
|
|
|
return error("Invalid record");
|
2016-12-13 03:34:26 +08:00
|
|
|
|
2016-12-23 11:59:18 +08:00
|
|
|
IsDistinct = Record[0];
|
2018-02-13 03:45:54 +08:00
|
|
|
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.
|
2018-02-24 07:01:06 +08:00
|
|
|
if (Record.size() > 4 && Record[3] && Record[4])
|
2018-02-13 03:45:54 +08:00
|
|
|
Checksum.emplace(static_cast<DIFile::ChecksumKind>(Record[3]),
|
|
|
|
getMDString(Record[4]));
|
2016-12-23 11:59:18 +08:00
|
|
|
MetadataList.assignValue(
|
|
|
|
GET_OR_DISTINCT(
|
2016-12-25 18:12:09 +08:00
|
|
|
DIFile,
|
2018-02-24 07:01:06 +08:00
|
|
|
(Context, getMDString(Record[1]), getMDString(Record[2]), Checksum,
|
|
|
|
Record.size() > 5 ? Optional<MDString *>(getMDString(Record[5]))
|
|
|
|
: None)),
|
Avoid using unspecified ordering in MetadataLoader::MetadataLoaderImpl::parseOneMetadata.
Summary:
MetadataLoader::MetadataLoaderImpl::parseOneMetadata uses
the following construct in a number of places:
```
MetadataList.assignValue(<...>, NextMetadataNo++);
```
There, NextMetadataNo gets incremented, and since the order
of arguments evaluation is not specified, that can happen
before or after other arguments are evaluated.
In a few cases the other arguments indirectly use NextMetadataNo.
For instance, it's
```
MetadataList.assignValue(
GET_OR_DISTINCT(DIModule,
(Context, getMDOrNull(Record[1]),
getMDString(Record[2]), getMDString(Record[3]),
getMDString(Record[4]), getMDString(Record[5]))),
NextMetadataNo++);
```
getMDOrNull calls getMD that uses NextMetadataNo:
```
MetadataList.getMetadataFwdRef(NextMetadataNo);
```
Therefore, the order of evaluation becomes important. That caused
a very subtle LLD crash that only happens if compiled with GCC or
if LLD is built with LTO. In the case if LLD is compiled with Clang
and regular linking mode, everything worked as intended.
This change extracts incrementing of NextMetadataNo outside of
the arguments list to guarantee the correct order of evaluation.
For the record, this has taken 3 days to track to the origin. It all
started with a ThinLTO bot in Chrome not being able to link a target
if debug info is enabled.
Reviewers: pcc, mehdi_amini
Reviewed By: mehdi_amini
Subscribers: aprantl, llvm-commits
Differential Revision: https://reviews.llvm.org/D29204
llvm-svn: 293291
2017-01-27 23:54:49 +08:00
|
|
|
NextMetadataNo);
|
|
|
|
NextMetadataNo++;
|
2016-12-23 11:59:18 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case bitc::METADATA_COMPILE_UNIT: {
|
2017-09-13 05:50:41 +08:00
|
|
|
if (Record.size() < 14 || Record.size() > 19)
|
2016-12-23 11:59:18 +08:00
|
|
|
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],
|
Change debug-info-for-profiling from a TargetOption to a function attribute.
Summary: LTO requires the debug-info-for-profiling to be a function attribute.
Reviewers: echristo, mehdi_amini, dblaikie, probinson, aprantl
Reviewed By: mehdi_amini, dblaikie, aprantl
Subscribers: aprantl, probinson, ahatanak, llvm-commits, mehdi_amini
Differential Revision: https://reviews.llvm.org/D29203
llvm-svn: 293833
2017-02-02 06:45:09 +08:00
|
|
|
Record.size() <= 16 ? true : Record[16],
|
2017-09-13 05:50:41 +08:00
|
|
|
Record.size() <= 17 ? false : Record[17],
|
2018-11-14 04:08:10 +08:00
|
|
|
Record.size() <= 18 ? 0 : Record[18],
|
|
|
|
Record.size() <= 19 ? 0 : Record[19]);
|
2016-12-23 11:59:18 +08:00
|
|
|
|
Avoid using unspecified ordering in MetadataLoader::MetadataLoaderImpl::parseOneMetadata.
Summary:
MetadataLoader::MetadataLoaderImpl::parseOneMetadata uses
the following construct in a number of places:
```
MetadataList.assignValue(<...>, NextMetadataNo++);
```
There, NextMetadataNo gets incremented, and since the order
of arguments evaluation is not specified, that can happen
before or after other arguments are evaluated.
In a few cases the other arguments indirectly use NextMetadataNo.
For instance, it's
```
MetadataList.assignValue(
GET_OR_DISTINCT(DIModule,
(Context, getMDOrNull(Record[1]),
getMDString(Record[2]), getMDString(Record[3]),
getMDString(Record[4]), getMDString(Record[5]))),
NextMetadataNo++);
```
getMDOrNull calls getMD that uses NextMetadataNo:
```
MetadataList.getMetadataFwdRef(NextMetadataNo);
```
Therefore, the order of evaluation becomes important. That caused
a very subtle LLD crash that only happens if compiled with GCC or
if LLD is built with LTO. In the case if LLD is compiled with Clang
and regular linking mode, everything worked as intended.
This change extracts incrementing of NextMetadataNo outside of
the arguments list to guarantee the correct order of evaluation.
For the record, this has taken 3 days to track to the origin. It all
started with a ThinLTO bot in Chrome not being able to link a target
if debug info is enabled.
Reviewers: pcc, mehdi_amini
Reviewed By: mehdi_amini
Subscribers: aprantl, llvm-commits
Differential Revision: https://reviews.llvm.org/D29204
llvm-svn: 293291
2017-01-27 23:54:49 +08:00
|
|
|
MetadataList.assignValue(CU, NextMetadataNo);
|
|
|
|
NextMetadataNo++;
|
2016-12-23 11:59:18 +08:00
|
|
|
|
|
|
|
// Move the Upgrade the list of subprograms.
|
|
|
|
if (Metadata *SPs = getMDOrNullWithoutPlaceholders(Record[11]))
|
|
|
|
CUSubprograms.push_back({CU, SPs});
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case bitc::METADATA_SUBPROGRAM: {
|
2017-04-27 06:56:44 +08:00
|
|
|
if (Record.size() < 18 || Record.size() > 21)
|
2016-12-23 11:59:18 +08:00
|
|
|
return error("Invalid record");
|
|
|
|
|
2018-11-29 05:14:32 +08:00
|
|
|
bool HasSPFlags = Record[0] & 4;
|
2019-03-19 21:49:03 +08:00
|
|
|
|
|
|
|
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],
|
|
|
|
/*DIFlagMainSubprogram*/HasOldMainSubprogramFlag);
|
2018-11-29 05:14:32 +08:00
|
|
|
|
|
|
|
// All definitions should be distinct.
|
|
|
|
IsDistinct = (Record[0] & 1) || (SPFlags & DISubprogram::SPFlagDefinition);
|
2016-12-23 11:59:18 +08:00
|
|
|
// 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.
|
2018-11-29 05:14:32 +08:00
|
|
|
// Version 5 repacked flags into DISPFlags, changing many element numbers.
|
|
|
|
bool HasUnit = Record[0] & 2;
|
|
|
|
if (!HasSPFlags && HasUnit && Record.size() < 19)
|
2016-12-23 11:59:18 +08:00
|
|
|
return error("Invalid record");
|
2018-11-29 05:14:32 +08:00
|
|
|
if (HasSPFlags && !HasUnit)
|
|
|
|
return error("Invalid record");
|
|
|
|
// Accommodate older formats.
|
|
|
|
bool HasFn = false;
|
|
|
|
bool HasThisAdj = true;
|
|
|
|
bool HasThrownTypes = true;
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
Metadata *CUorFn = getMDOrNull(Record[12 + OffsetB]);
|
2016-12-23 11:59:18 +08:00
|
|
|
DISubprogram *SP = GET_OR_DISTINCT(
|
2017-04-27 06:56:44 +08:00
|
|
|
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
|
2018-11-29 05:14:32 +08:00
|
|
|
Record[7 + OffsetA], // scopeLine
|
|
|
|
getDITypeRefOrNull(Record[8 + OffsetA]), // containingType
|
|
|
|
Record[10 + OffsetA], // virtualIndex
|
|
|
|
HasThisAdj ? Record[16 + OffsetB] : 0, // thisAdjustment
|
2019-03-19 21:49:03 +08:00
|
|
|
Flags, // flags
|
2018-11-20 02:29:28 +08:00
|
|
|
SPFlags, // SPFlags
|
2017-04-27 06:56:44 +08:00
|
|
|
HasUnit ? CUorFn : nullptr, // unit
|
2018-11-29 05:14:32 +08:00
|
|
|
getMDOrNull(Record[13 + OffsetB]), // templateParams
|
|
|
|
getMDOrNull(Record[14 + OffsetB]), // declaration
|
|
|
|
getMDOrNull(Record[15 + OffsetB]), // retainedNodes
|
|
|
|
HasThrownTypes ? getMDOrNull(Record[17 + OffsetB])
|
|
|
|
: nullptr // thrownTypes
|
2017-04-27 06:56:44 +08:00
|
|
|
));
|
Avoid using unspecified ordering in MetadataLoader::MetadataLoaderImpl::parseOneMetadata.
Summary:
MetadataLoader::MetadataLoaderImpl::parseOneMetadata uses
the following construct in a number of places:
```
MetadataList.assignValue(<...>, NextMetadataNo++);
```
There, NextMetadataNo gets incremented, and since the order
of arguments evaluation is not specified, that can happen
before or after other arguments are evaluated.
In a few cases the other arguments indirectly use NextMetadataNo.
For instance, it's
```
MetadataList.assignValue(
GET_OR_DISTINCT(DIModule,
(Context, getMDOrNull(Record[1]),
getMDString(Record[2]), getMDString(Record[3]),
getMDString(Record[4]), getMDString(Record[5]))),
NextMetadataNo++);
```
getMDOrNull calls getMD that uses NextMetadataNo:
```
MetadataList.getMetadataFwdRef(NextMetadataNo);
```
Therefore, the order of evaluation becomes important. That caused
a very subtle LLD crash that only happens if compiled with GCC or
if LLD is built with LTO. In the case if LLD is compiled with Clang
and regular linking mode, everything worked as intended.
This change extracts incrementing of NextMetadataNo outside of
the arguments list to guarantee the correct order of evaluation.
For the record, this has taken 3 days to track to the origin. It all
started with a ThinLTO bot in Chrome not being able to link a target
if debug info is enabled.
Reviewers: pcc, mehdi_amini
Reviewed By: mehdi_amini
Subscribers: aprantl, llvm-commits
Differential Revision: https://reviews.llvm.org/D29204
llvm-svn: 293291
2017-01-27 23:54:49 +08:00
|
|
|
MetadataList.assignValue(SP, NextMetadataNo);
|
|
|
|
NextMetadataNo++;
|
2016-12-23 11:59:18 +08:00
|
|
|
|
|
|
|
// 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);
|
|
|
|
}
|
2016-12-13 03:34:26 +08:00
|
|
|
}
|
2016-12-23 11:59:18 +08:00
|
|
|
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])),
|
Avoid using unspecified ordering in MetadataLoader::MetadataLoaderImpl::parseOneMetadata.
Summary:
MetadataLoader::MetadataLoaderImpl::parseOneMetadata uses
the following construct in a number of places:
```
MetadataList.assignValue(<...>, NextMetadataNo++);
```
There, NextMetadataNo gets incremented, and since the order
of arguments evaluation is not specified, that can happen
before or after other arguments are evaluated.
In a few cases the other arguments indirectly use NextMetadataNo.
For instance, it's
```
MetadataList.assignValue(
GET_OR_DISTINCT(DIModule,
(Context, getMDOrNull(Record[1]),
getMDString(Record[2]), getMDString(Record[3]),
getMDString(Record[4]), getMDString(Record[5]))),
NextMetadataNo++);
```
getMDOrNull calls getMD that uses NextMetadataNo:
```
MetadataList.getMetadataFwdRef(NextMetadataNo);
```
Therefore, the order of evaluation becomes important. That caused
a very subtle LLD crash that only happens if compiled with GCC or
if LLD is built with LTO. In the case if LLD is compiled with Clang
and regular linking mode, everything worked as intended.
This change extracts incrementing of NextMetadataNo outside of
the arguments list to guarantee the correct order of evaluation.
For the record, this has taken 3 days to track to the origin. It all
started with a ThinLTO bot in Chrome not being able to link a target
if debug info is enabled.
Reviewers: pcc, mehdi_amini
Reviewed By: mehdi_amini
Subscribers: aprantl, llvm-commits
Differential Revision: https://reviews.llvm.org/D29204
llvm-svn: 293291
2017-01-27 23:54:49 +08:00
|
|
|
NextMetadataNo);
|
|
|
|
NextMetadataNo++;
|
2016-12-23 11:59:18 +08:00
|
|
|
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])),
|
Avoid using unspecified ordering in MetadataLoader::MetadataLoaderImpl::parseOneMetadata.
Summary:
MetadataLoader::MetadataLoaderImpl::parseOneMetadata uses
the following construct in a number of places:
```
MetadataList.assignValue(<...>, NextMetadataNo++);
```
There, NextMetadataNo gets incremented, and since the order
of arguments evaluation is not specified, that can happen
before or after other arguments are evaluated.
In a few cases the other arguments indirectly use NextMetadataNo.
For instance, it's
```
MetadataList.assignValue(
GET_OR_DISTINCT(DIModule,
(Context, getMDOrNull(Record[1]),
getMDString(Record[2]), getMDString(Record[3]),
getMDString(Record[4]), getMDString(Record[5]))),
NextMetadataNo++);
```
getMDOrNull calls getMD that uses NextMetadataNo:
```
MetadataList.getMetadataFwdRef(NextMetadataNo);
```
Therefore, the order of evaluation becomes important. That caused
a very subtle LLD crash that only happens if compiled with GCC or
if LLD is built with LTO. In the case if LLD is compiled with Clang
and regular linking mode, everything worked as intended.
This change extracts incrementing of NextMetadataNo outside of
the arguments list to guarantee the correct order of evaluation.
For the record, this has taken 3 days to track to the origin. It all
started with a ThinLTO bot in Chrome not being able to link a target
if debug info is enabled.
Reviewers: pcc, mehdi_amini
Reviewed By: mehdi_amini
Subscribers: aprantl, llvm-commits
Differential Revision: https://reviews.llvm.org/D29204
llvm-svn: 293291
2017-01-27 23:54:49 +08:00
|
|
|
NextMetadataNo);
|
|
|
|
NextMetadataNo++;
|
2016-12-23 11:59:18 +08:00
|
|
|
break;
|
|
|
|
}
|
Add LLVM IR debug info support for Fortran COMMON blocks
COMMON blocks are a feature of Fortran that has no direct analog in C languages, but they are similar to data sections in assembly language programming. A COMMON block is a named area of memory that holds a collection of variables. Fortran subprograms may map the COMMON block memory area to their own, possibly distinct, non-empty list of variables. A Fortran COMMON block might look like the following example.
COMMON /ALPHA/ I, J
For this construct, the compiler generates a new scope-like DI construct (!DICommonBlock) into which variables (see I, J above) can be placed. As the common block implies a range of storage with global lifetime, the !DICommonBlock refers to a !DIGlobalVariable. The Fortran variable that comprise the COMMON block are also linked via metadata to offsets within the global variable that stands for the entire common block.
@alpha_ = common global %alphabytes_ zeroinitializer, align 64, !dbg !27, !dbg !30, !dbg !33
!14 = distinct !DISubprogram(…)
!20 = distinct !DICommonBlock(scope: !14, declaration: !25, name: "alpha")
!25 = distinct !DIGlobalVariable(scope: !20, name: "common alpha", type: !24)
!27 = !DIGlobalVariableExpression(var: !25, expr: !DIExpression())
!29 = distinct !DIGlobalVariable(scope: !20, name: "i", file: !3, type: !28)
!30 = !DIGlobalVariableExpression(var: !29, expr: !DIExpression())
!31 = distinct !DIGlobalVariable(scope: !20, name: "j", file: !3, type: !28)
!32 = !DIExpression(DW_OP_plus_uconst, 4)
!33 = !DIGlobalVariableExpression(var: !31, expr: !32)
The DWARF generated for this is as follows.
DW_TAG_common_block:
DW_AT_name: alpha
DW_AT_location: @alpha_+0
DW_TAG_variable:
DW_AT_name: common alpha
DW_AT_type: array of 8 bytes
DW_AT_location: @alpha_+0
DW_TAG_variable:
DW_AT_name: i
DW_AT_type: integer*4
DW_AT_location: @Alpha+0
DW_TAG_variable:
DW_AT_name: j
DW_AT_type: integer*4
DW_AT_location: @Alpha+4
Patch by Eric Schweitz!
Differential Revision: https://reviews.llvm.org/D54327
llvm-svn: 357934
2019-04-09 03:13:55 +08:00
|
|
|
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;
|
|
|
|
}
|
2016-12-23 11:59:18 +08:00
|
|
|
case bitc::METADATA_NAMESPACE: {
|
2017-04-29 06:25:46 +08:00
|
|
|
// 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
|
2016-12-23 11:59:18 +08:00
|
|
|
return error("Invalid record");
|
|
|
|
|
|
|
|
IsDistinct = Record[0] & 1;
|
|
|
|
bool ExportSymbols = Record[0] & 2;
|
|
|
|
MetadataList.assignValue(
|
|
|
|
GET_OR_DISTINCT(DINamespace,
|
2017-04-29 06:25:46 +08:00
|
|
|
(Context, getMDOrNull(Record[1]), Name, ExportSymbols)),
|
Avoid using unspecified ordering in MetadataLoader::MetadataLoaderImpl::parseOneMetadata.
Summary:
MetadataLoader::MetadataLoaderImpl::parseOneMetadata uses
the following construct in a number of places:
```
MetadataList.assignValue(<...>, NextMetadataNo++);
```
There, NextMetadataNo gets incremented, and since the order
of arguments evaluation is not specified, that can happen
before or after other arguments are evaluated.
In a few cases the other arguments indirectly use NextMetadataNo.
For instance, it's
```
MetadataList.assignValue(
GET_OR_DISTINCT(DIModule,
(Context, getMDOrNull(Record[1]),
getMDString(Record[2]), getMDString(Record[3]),
getMDString(Record[4]), getMDString(Record[5]))),
NextMetadataNo++);
```
getMDOrNull calls getMD that uses NextMetadataNo:
```
MetadataList.getMetadataFwdRef(NextMetadataNo);
```
Therefore, the order of evaluation becomes important. That caused
a very subtle LLD crash that only happens if compiled with GCC or
if LLD is built with LTO. In the case if LLD is compiled with Clang
and regular linking mode, everything worked as intended.
This change extracts incrementing of NextMetadataNo outside of
the arguments list to guarantee the correct order of evaluation.
For the record, this has taken 3 days to track to the origin. It all
started with a ThinLTO bot in Chrome not being able to link a target
if debug info is enabled.
Reviewers: pcc, mehdi_amini
Reviewed By: mehdi_amini
Subscribers: aprantl, llvm-commits
Differential Revision: https://reviews.llvm.org/D29204
llvm-svn: 293291
2017-01-27 23:54:49 +08:00
|
|
|
NextMetadataNo);
|
|
|
|
NextMetadataNo++;
|
2016-12-23 11:59:18 +08:00
|
|
|
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]))),
|
Avoid using unspecified ordering in MetadataLoader::MetadataLoaderImpl::parseOneMetadata.
Summary:
MetadataLoader::MetadataLoaderImpl::parseOneMetadata uses
the following construct in a number of places:
```
MetadataList.assignValue(<...>, NextMetadataNo++);
```
There, NextMetadataNo gets incremented, and since the order
of arguments evaluation is not specified, that can happen
before or after other arguments are evaluated.
In a few cases the other arguments indirectly use NextMetadataNo.
For instance, it's
```
MetadataList.assignValue(
GET_OR_DISTINCT(DIModule,
(Context, getMDOrNull(Record[1]),
getMDString(Record[2]), getMDString(Record[3]),
getMDString(Record[4]), getMDString(Record[5]))),
NextMetadataNo++);
```
getMDOrNull calls getMD that uses NextMetadataNo:
```
MetadataList.getMetadataFwdRef(NextMetadataNo);
```
Therefore, the order of evaluation becomes important. That caused
a very subtle LLD crash that only happens if compiled with GCC or
if LLD is built with LTO. In the case if LLD is compiled with Clang
and regular linking mode, everything worked as intended.
This change extracts incrementing of NextMetadataNo outside of
the arguments list to guarantee the correct order of evaluation.
For the record, this has taken 3 days to track to the origin. It all
started with a ThinLTO bot in Chrome not being able to link a target
if debug info is enabled.
Reviewers: pcc, mehdi_amini
Reviewed By: mehdi_amini
Subscribers: aprantl, llvm-commits
Differential Revision: https://reviews.llvm.org/D29204
llvm-svn: 293291
2017-01-27 23:54:49 +08:00
|
|
|
NextMetadataNo);
|
|
|
|
NextMetadataNo++;
|
2016-12-23 11:59:18 +08:00
|
|
|
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]))),
|
Avoid using unspecified ordering in MetadataLoader::MetadataLoaderImpl::parseOneMetadata.
Summary:
MetadataLoader::MetadataLoaderImpl::parseOneMetadata uses
the following construct in a number of places:
```
MetadataList.assignValue(<...>, NextMetadataNo++);
```
There, NextMetadataNo gets incremented, and since the order
of arguments evaluation is not specified, that can happen
before or after other arguments are evaluated.
In a few cases the other arguments indirectly use NextMetadataNo.
For instance, it's
```
MetadataList.assignValue(
GET_OR_DISTINCT(DIModule,
(Context, getMDOrNull(Record[1]),
getMDString(Record[2]), getMDString(Record[3]),
getMDString(Record[4]), getMDString(Record[5]))),
NextMetadataNo++);
```
getMDOrNull calls getMD that uses NextMetadataNo:
```
MetadataList.getMetadataFwdRef(NextMetadataNo);
```
Therefore, the order of evaluation becomes important. That caused
a very subtle LLD crash that only happens if compiled with GCC or
if LLD is built with LTO. In the case if LLD is compiled with Clang
and regular linking mode, everything worked as intended.
This change extracts incrementing of NextMetadataNo outside of
the arguments list to guarantee the correct order of evaluation.
For the record, this has taken 3 days to track to the origin. It all
started with a ThinLTO bot in Chrome not being able to link a target
if debug info is enabled.
Reviewers: pcc, mehdi_amini
Reviewed By: mehdi_amini
Subscribers: aprantl, llvm-commits
Differential Revision: https://reviews.llvm.org/D29204
llvm-svn: 293291
2017-01-27 23:54:49 +08:00
|
|
|
NextMetadataNo);
|
|
|
|
NextMetadataNo++;
|
2016-12-23 11:59:18 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case bitc::METADATA_TEMPLATE_TYPE: {
|
|
|
|
if (Record.size() != 3)
|
|
|
|
return error("Invalid record");
|
|
|
|
|
|
|
|
IsDistinct = Record[0];
|
|
|
|
MetadataList.assignValue(GET_OR_DISTINCT(DITemplateTypeParameter,
|
|
|
|
(Context, getMDString(Record[1]),
|
|
|
|
getDITypeRefOrNull(Record[2]))),
|
Avoid using unspecified ordering in MetadataLoader::MetadataLoaderImpl::parseOneMetadata.
Summary:
MetadataLoader::MetadataLoaderImpl::parseOneMetadata uses
the following construct in a number of places:
```
MetadataList.assignValue(<...>, NextMetadataNo++);
```
There, NextMetadataNo gets incremented, and since the order
of arguments evaluation is not specified, that can happen
before or after other arguments are evaluated.
In a few cases the other arguments indirectly use NextMetadataNo.
For instance, it's
```
MetadataList.assignValue(
GET_OR_DISTINCT(DIModule,
(Context, getMDOrNull(Record[1]),
getMDString(Record[2]), getMDString(Record[3]),
getMDString(Record[4]), getMDString(Record[5]))),
NextMetadataNo++);
```
getMDOrNull calls getMD that uses NextMetadataNo:
```
MetadataList.getMetadataFwdRef(NextMetadataNo);
```
Therefore, the order of evaluation becomes important. That caused
a very subtle LLD crash that only happens if compiled with GCC or
if LLD is built with LTO. In the case if LLD is compiled with Clang
and regular linking mode, everything worked as intended.
This change extracts incrementing of NextMetadataNo outside of
the arguments list to guarantee the correct order of evaluation.
For the record, this has taken 3 days to track to the origin. It all
started with a ThinLTO bot in Chrome not being able to link a target
if debug info is enabled.
Reviewers: pcc, mehdi_amini
Reviewed By: mehdi_amini
Subscribers: aprantl, llvm-commits
Differential Revision: https://reviews.llvm.org/D29204
llvm-svn: 293291
2017-01-27 23:54:49 +08:00
|
|
|
NextMetadataNo);
|
|
|
|
NextMetadataNo++;
|
2016-12-23 11:59:18 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case bitc::METADATA_TEMPLATE_VALUE: {
|
|
|
|
if (Record.size() != 5)
|
|
|
|
return error("Invalid record");
|
|
|
|
|
|
|
|
IsDistinct = Record[0];
|
|
|
|
MetadataList.assignValue(
|
|
|
|
GET_OR_DISTINCT(DITemplateValueParameter,
|
|
|
|
(Context, Record[1], getMDString(Record[2]),
|
|
|
|
getDITypeRefOrNull(Record[3]),
|
|
|
|
getMDOrNull(Record[4]))),
|
Avoid using unspecified ordering in MetadataLoader::MetadataLoaderImpl::parseOneMetadata.
Summary:
MetadataLoader::MetadataLoaderImpl::parseOneMetadata uses
the following construct in a number of places:
```
MetadataList.assignValue(<...>, NextMetadataNo++);
```
There, NextMetadataNo gets incremented, and since the order
of arguments evaluation is not specified, that can happen
before or after other arguments are evaluated.
In a few cases the other arguments indirectly use NextMetadataNo.
For instance, it's
```
MetadataList.assignValue(
GET_OR_DISTINCT(DIModule,
(Context, getMDOrNull(Record[1]),
getMDString(Record[2]), getMDString(Record[3]),
getMDString(Record[4]), getMDString(Record[5]))),
NextMetadataNo++);
```
getMDOrNull calls getMD that uses NextMetadataNo:
```
MetadataList.getMetadataFwdRef(NextMetadataNo);
```
Therefore, the order of evaluation becomes important. That caused
a very subtle LLD crash that only happens if compiled with GCC or
if LLD is built with LTO. In the case if LLD is compiled with Clang
and regular linking mode, everything worked as intended.
This change extracts incrementing of NextMetadataNo outside of
the arguments list to guarantee the correct order of evaluation.
For the record, this has taken 3 days to track to the origin. It all
started with a ThinLTO bot in Chrome not being able to link a target
if debug info is enabled.
Reviewers: pcc, mehdi_amini
Reviewed By: mehdi_amini
Subscribers: aprantl, llvm-commits
Differential Revision: https://reviews.llvm.org/D29204
llvm-svn: 293291
2017-01-27 23:54:49 +08:00
|
|
|
NextMetadataNo);
|
|
|
|
NextMetadataNo++;
|
2016-12-23 11:59:18 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case bitc::METADATA_GLOBAL_VAR: {
|
2018-10-04 02:44:53 +08:00
|
|
|
if (Record.size() < 11 || Record.size() > 13)
|
2016-12-23 11:59:18 +08:00
|
|
|
return error("Invalid record");
|
2016-12-13 03:34:26 +08:00
|
|
|
|
2016-12-23 11:59:18 +08:00
|
|
|
IsDistinct = Record[0] & 1;
|
|
|
|
unsigned Version = Record[0] >> 1;
|
2016-12-13 03:34:26 +08:00
|
|
|
|
2018-10-04 02:44:53 +08:00
|
|
|
if (Version == 2) {
|
|
|
|
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])),
|
|
|
|
NextMetadataNo);
|
|
|
|
|
|
|
|
NextMetadataNo++;
|
|
|
|
} else if (Version == 1) {
|
|
|
|
// No upgrade necessary. A null field will be introduced to indicate
|
|
|
|
// that no parameter information is available.
|
2016-12-13 03:34:26 +08:00
|
|
|
MetadataList.assignValue(
|
2016-12-23 11:59:18 +08:00
|
|
|
GET_OR_DISTINCT(DIGlobalVariable,
|
2016-12-13 03:34:26 +08:00
|
|
|
(Context, getMDOrNull(Record[1]),
|
|
|
|
getMDString(Record[2]), getMDString(Record[3]),
|
2016-12-23 11:59:18 +08:00
|
|
|
getMDOrNull(Record[4]), Record[5],
|
|
|
|
getDITypeRefOrNull(Record[6]), Record[7], Record[8],
|
2018-10-04 02:44:53 +08:00
|
|
|
getMDOrNull(Record[10]), nullptr, Record[11])),
|
Avoid using unspecified ordering in MetadataLoader::MetadataLoaderImpl::parseOneMetadata.
Summary:
MetadataLoader::MetadataLoaderImpl::parseOneMetadata uses
the following construct in a number of places:
```
MetadataList.assignValue(<...>, NextMetadataNo++);
```
There, NextMetadataNo gets incremented, and since the order
of arguments evaluation is not specified, that can happen
before or after other arguments are evaluated.
In a few cases the other arguments indirectly use NextMetadataNo.
For instance, it's
```
MetadataList.assignValue(
GET_OR_DISTINCT(DIModule,
(Context, getMDOrNull(Record[1]),
getMDString(Record[2]), getMDString(Record[3]),
getMDString(Record[4]), getMDString(Record[5]))),
NextMetadataNo++);
```
getMDOrNull calls getMD that uses NextMetadataNo:
```
MetadataList.getMetadataFwdRef(NextMetadataNo);
```
Therefore, the order of evaluation becomes important. That caused
a very subtle LLD crash that only happens if compiled with GCC or
if LLD is built with LTO. In the case if LLD is compiled with Clang
and regular linking mode, everything worked as intended.
This change extracts incrementing of NextMetadataNo outside of
the arguments list to guarantee the correct order of evaluation.
For the record, this has taken 3 days to track to the origin. It all
started with a ThinLTO bot in Chrome not being able to link a target
if debug info is enabled.
Reviewers: pcc, mehdi_amini
Reviewed By: mehdi_amini
Subscribers: aprantl, llvm-commits
Differential Revision: https://reviews.llvm.org/D29204
llvm-svn: 293291
2017-01-27 23:54:49 +08:00
|
|
|
NextMetadataNo);
|
2018-10-04 02:44:53 +08:00
|
|
|
|
Avoid using unspecified ordering in MetadataLoader::MetadataLoaderImpl::parseOneMetadata.
Summary:
MetadataLoader::MetadataLoaderImpl::parseOneMetadata uses
the following construct in a number of places:
```
MetadataList.assignValue(<...>, NextMetadataNo++);
```
There, NextMetadataNo gets incremented, and since the order
of arguments evaluation is not specified, that can happen
before or after other arguments are evaluated.
In a few cases the other arguments indirectly use NextMetadataNo.
For instance, it's
```
MetadataList.assignValue(
GET_OR_DISTINCT(DIModule,
(Context, getMDOrNull(Record[1]),
getMDString(Record[2]), getMDString(Record[3]),
getMDString(Record[4]), getMDString(Record[5]))),
NextMetadataNo++);
```
getMDOrNull calls getMD that uses NextMetadataNo:
```
MetadataList.getMetadataFwdRef(NextMetadataNo);
```
Therefore, the order of evaluation becomes important. That caused
a very subtle LLD crash that only happens if compiled with GCC or
if LLD is built with LTO. In the case if LLD is compiled with Clang
and regular linking mode, everything worked as intended.
This change extracts incrementing of NextMetadataNo outside of
the arguments list to guarantee the correct order of evaluation.
For the record, this has taken 3 days to track to the origin. It all
started with a ThinLTO bot in Chrome not being able to link a target
if debug info is enabled.
Reviewers: pcc, mehdi_amini
Reviewed By: mehdi_amini
Subscribers: aprantl, llvm-commits
Differential Revision: https://reviews.llvm.org/D29204
llvm-svn: 293291
2017-01-27 23:54:49 +08:00
|
|
|
NextMetadataNo++;
|
2016-12-23 11:59:18 +08:00
|
|
|
} else if (Version == 0) {
|
|
|
|
// Upgrade old metadata, which stored a global variable reference or a
|
|
|
|
// ConstantInt here.
|
2017-02-09 01:44:43 +08:00
|
|
|
NeedUpgradeToDIGlobalVariableExpression = true;
|
2016-12-23 11:59:18 +08:00
|
|
|
Metadata *Expr = getMDOrNull(Record[9]);
|
2016-12-13 03:34:26 +08:00
|
|
|
uint32_t AlignInBits = 0;
|
2016-12-23 11:59:18 +08:00
|
|
|
if (Record.size() > 11) {
|
|
|
|
if (Record[11] > (uint64_t)std::numeric_limits<uint32_t>::max())
|
2016-12-13 03:34:26 +08:00
|
|
|
return error("Alignment value is too large");
|
2016-12-23 11:59:18 +08:00
|
|
|
AlignInBits = Record[11];
|
2016-12-13 03:34:26 +08:00
|
|
|
}
|
2016-12-23 11:59:18 +08:00
|
|
|
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],
|
2018-10-04 02:44:53 +08:00
|
|
|
getMDOrNull(Record[10]), nullptr, AlignInBits));
|
2016-12-23 11:59:18 +08:00
|
|
|
|
2017-02-08 01:35:41 +08:00
|
|
|
DIGlobalVariableExpression *DGVE = nullptr;
|
|
|
|
if (Attach || Expr)
|
2017-08-31 02:06:51 +08:00
|
|
|
DGVE = DIGlobalVariableExpression::getDistinct(
|
|
|
|
Context, DGV, Expr ? Expr : DIExpression::get(Context, {}));
|
2016-12-23 11:59:18 +08:00
|
|
|
if (Attach)
|
|
|
|
Attach->addDebugInfo(DGVE);
|
2017-02-08 01:35:41 +08:00
|
|
|
|
|
|
|
auto *MDNode = Expr ? cast<Metadata>(DGVE) : cast<Metadata>(DGV);
|
|
|
|
MetadataList.assignValue(MDNode, NextMetadataNo);
|
|
|
|
NextMetadataNo++;
|
2016-12-23 11:59:18 +08:00
|
|
|
} 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
|
2017-03-30 20:59:53 +08:00
|
|
|
// this is newer version of record which doesn't have artificial tag.
|
2016-12-23 11:59:18 +08:00
|
|
|
bool HasTag = !HasAlignment && Record.size() > 8;
|
|
|
|
DINode::DIFlags Flags = static_cast<DINode::DIFlags>(Record[7 + HasTag]);
|
|
|
|
uint32_t AlignInBits = 0;
|
|
|
|
if (HasAlignment) {
|
|
|
|
if (Record[8 + HasTag] > (uint64_t)std::numeric_limits<uint32_t>::max())
|
|
|
|
return error("Alignment value is too large");
|
|
|
|
AlignInBits = Record[8 + HasTag];
|
2016-12-13 03:34:26 +08:00
|
|
|
}
|
2016-12-23 11:59:18 +08:00
|
|
|
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)),
|
Avoid using unspecified ordering in MetadataLoader::MetadataLoaderImpl::parseOneMetadata.
Summary:
MetadataLoader::MetadataLoaderImpl::parseOneMetadata uses
the following construct in a number of places:
```
MetadataList.assignValue(<...>, NextMetadataNo++);
```
There, NextMetadataNo gets incremented, and since the order
of arguments evaluation is not specified, that can happen
before or after other arguments are evaluated.
In a few cases the other arguments indirectly use NextMetadataNo.
For instance, it's
```
MetadataList.assignValue(
GET_OR_DISTINCT(DIModule,
(Context, getMDOrNull(Record[1]),
getMDString(Record[2]), getMDString(Record[3]),
getMDString(Record[4]), getMDString(Record[5]))),
NextMetadataNo++);
```
getMDOrNull calls getMD that uses NextMetadataNo:
```
MetadataList.getMetadataFwdRef(NextMetadataNo);
```
Therefore, the order of evaluation becomes important. That caused
a very subtle LLD crash that only happens if compiled with GCC or
if LLD is built with LTO. In the case if LLD is compiled with Clang
and regular linking mode, everything worked as intended.
This change extracts incrementing of NextMetadataNo outside of
the arguments list to guarantee the correct order of evaluation.
For the record, this has taken 3 days to track to the origin. It all
started with a ThinLTO bot in Chrome not being able to link a target
if debug info is enabled.
Reviewers: pcc, mehdi_amini
Reviewed By: mehdi_amini
Subscribers: aprantl, llvm-commits
Differential Revision: https://reviews.llvm.org/D29204
llvm-svn: 293291
2017-01-27 23:54:49 +08:00
|
|
|
NextMetadataNo);
|
|
|
|
NextMetadataNo++;
|
2016-12-23 11:59:18 +08:00
|
|
|
break;
|
|
|
|
}
|
[DebugInfo] Add DILabel metadata and intrinsic llvm.dbg.label.
In order to set breakpoints on labels and list source code around
labels, we need collect debug information for labels, i.e., label
name, the function label belong, line number in the file, and the
address label located. In order to keep these information in LLVM
IR and to allow backend to generate debug information correctly.
We create a new kind of metadata for labels, DILabel. The format
of DILabel is
!DILabel(scope: !1, name: "foo", file: !2, line: 3)
We hope to keep debug information as much as possible even the
code is optimized. So, we create a new kind of intrinsic for label
metadata to avoid the metadata is eliminated with basic block.
The intrinsic will keep existing if we keep it from optimized out.
The format of the intrinsic is
llvm.dbg.label(metadata !1)
It has only one argument, that is the DILabel metadata. The
intrinsic will follow the label immediately. Backend could get the
label metadata through the intrinsic's parameter.
We also create DIBuilder API for labels to be used by Frontend.
Frontend could use createLabel() to allocate DILabel objects, and use
insertLabel() to insert llvm.dbg.label intrinsic in LLVM IR.
Differential Revision: https://reviews.llvm.org/D45024
Patch by Hsiangkai Wang.
llvm-svn: 331841
2018-05-09 10:40:45 +08:00
|
|
|
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;
|
|
|
|
}
|
2016-12-23 11:59:18 +08:00
|
|
|
case bitc::METADATA_EXPRESSION: {
|
|
|
|
if (Record.size() < 1)
|
|
|
|
return error("Invalid record");
|
|
|
|
|
|
|
|
IsDistinct = Record[0] & 1;
|
2017-04-18 09:21:53 +08:00
|
|
|
uint64_t Version = Record[0] >> 1;
|
2016-12-23 11:59:18 +08:00
|
|
|
auto Elts = MutableArrayRef<uint64_t>(Record).slice(1);
|
2017-06-14 21:14:38 +08:00
|
|
|
|
|
|
|
SmallVector<uint64_t, 6> Buffer;
|
|
|
|
if (Error Err = upgradeDIExpression(Version, Elts, Buffer))
|
|
|
|
return Err;
|
2016-12-23 11:59:18 +08:00
|
|
|
|
|
|
|
MetadataList.assignValue(
|
2017-06-14 21:14:38 +08:00
|
|
|
GET_OR_DISTINCT(DIExpression, (Context, Elts)), NextMetadataNo);
|
Avoid using unspecified ordering in MetadataLoader::MetadataLoaderImpl::parseOneMetadata.
Summary:
MetadataLoader::MetadataLoaderImpl::parseOneMetadata uses
the following construct in a number of places:
```
MetadataList.assignValue(<...>, NextMetadataNo++);
```
There, NextMetadataNo gets incremented, and since the order
of arguments evaluation is not specified, that can happen
before or after other arguments are evaluated.
In a few cases the other arguments indirectly use NextMetadataNo.
For instance, it's
```
MetadataList.assignValue(
GET_OR_DISTINCT(DIModule,
(Context, getMDOrNull(Record[1]),
getMDString(Record[2]), getMDString(Record[3]),
getMDString(Record[4]), getMDString(Record[5]))),
NextMetadataNo++);
```
getMDOrNull calls getMD that uses NextMetadataNo:
```
MetadataList.getMetadataFwdRef(NextMetadataNo);
```
Therefore, the order of evaluation becomes important. That caused
a very subtle LLD crash that only happens if compiled with GCC or
if LLD is built with LTO. In the case if LLD is compiled with Clang
and regular linking mode, everything worked as intended.
This change extracts incrementing of NextMetadataNo outside of
the arguments list to guarantee the correct order of evaluation.
For the record, this has taken 3 days to track to the origin. It all
started with a ThinLTO bot in Chrome not being able to link a target
if debug info is enabled.
Reviewers: pcc, mehdi_amini
Reviewed By: mehdi_amini
Subscribers: aprantl, llvm-commits
Differential Revision: https://reviews.llvm.org/D29204
llvm-svn: 293291
2017-01-27 23:54:49 +08:00
|
|
|
NextMetadataNo++;
|
2016-12-23 11:59:18 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case bitc::METADATA_GLOBAL_VAR_EXPR: {
|
|
|
|
if (Record.size() != 3)
|
|
|
|
return error("Invalid record");
|
|
|
|
|
|
|
|
IsDistinct = Record[0];
|
2017-08-31 02:06:51 +08:00
|
|
|
Metadata *Expr = getMDOrNull(Record[2]);
|
|
|
|
if (!Expr)
|
|
|
|
Expr = DIExpression::get(Context, {});
|
|
|
|
MetadataList.assignValue(
|
|
|
|
GET_OR_DISTINCT(DIGlobalVariableExpression,
|
|
|
|
(Context, getMDOrNull(Record[1]), Expr)),
|
|
|
|
NextMetadataNo);
|
Avoid using unspecified ordering in MetadataLoader::MetadataLoaderImpl::parseOneMetadata.
Summary:
MetadataLoader::MetadataLoaderImpl::parseOneMetadata uses
the following construct in a number of places:
```
MetadataList.assignValue(<...>, NextMetadataNo++);
```
There, NextMetadataNo gets incremented, and since the order
of arguments evaluation is not specified, that can happen
before or after other arguments are evaluated.
In a few cases the other arguments indirectly use NextMetadataNo.
For instance, it's
```
MetadataList.assignValue(
GET_OR_DISTINCT(DIModule,
(Context, getMDOrNull(Record[1]),
getMDString(Record[2]), getMDString(Record[3]),
getMDString(Record[4]), getMDString(Record[5]))),
NextMetadataNo++);
```
getMDOrNull calls getMD that uses NextMetadataNo:
```
MetadataList.getMetadataFwdRef(NextMetadataNo);
```
Therefore, the order of evaluation becomes important. That caused
a very subtle LLD crash that only happens if compiled with GCC or
if LLD is built with LTO. In the case if LLD is compiled with Clang
and regular linking mode, everything worked as intended.
This change extracts incrementing of NextMetadataNo outside of
the arguments list to guarantee the correct order of evaluation.
For the record, this has taken 3 days to track to the origin. It all
started with a ThinLTO bot in Chrome not being able to link a target
if debug info is enabled.
Reviewers: pcc, mehdi_amini
Reviewed By: mehdi_amini
Subscribers: aprantl, llvm-commits
Differential Revision: https://reviews.llvm.org/D29204
llvm-svn: 293291
2017-01-27 23:54:49 +08:00
|
|
|
NextMetadataNo++;
|
2016-12-23 11:59:18 +08:00
|
|
|
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]))),
|
Avoid using unspecified ordering in MetadataLoader::MetadataLoaderImpl::parseOneMetadata.
Summary:
MetadataLoader::MetadataLoaderImpl::parseOneMetadata uses
the following construct in a number of places:
```
MetadataList.assignValue(<...>, NextMetadataNo++);
```
There, NextMetadataNo gets incremented, and since the order
of arguments evaluation is not specified, that can happen
before or after other arguments are evaluated.
In a few cases the other arguments indirectly use NextMetadataNo.
For instance, it's
```
MetadataList.assignValue(
GET_OR_DISTINCT(DIModule,
(Context, getMDOrNull(Record[1]),
getMDString(Record[2]), getMDString(Record[3]),
getMDString(Record[4]), getMDString(Record[5]))),
NextMetadataNo++);
```
getMDOrNull calls getMD that uses NextMetadataNo:
```
MetadataList.getMetadataFwdRef(NextMetadataNo);
```
Therefore, the order of evaluation becomes important. That caused
a very subtle LLD crash that only happens if compiled with GCC or
if LLD is built with LTO. In the case if LLD is compiled with Clang
and regular linking mode, everything worked as intended.
This change extracts incrementing of NextMetadataNo outside of
the arguments list to guarantee the correct order of evaluation.
For the record, this has taken 3 days to track to the origin. It all
started with a ThinLTO bot in Chrome not being able to link a target
if debug info is enabled.
Reviewers: pcc, mehdi_amini
Reviewed By: mehdi_amini
Subscribers: aprantl, llvm-commits
Differential Revision: https://reviews.llvm.org/D29204
llvm-svn: 293291
2017-01-27 23:54:49 +08:00
|
|
|
NextMetadataNo);
|
|
|
|
NextMetadataNo++;
|
2016-12-23 11:59:18 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case bitc::METADATA_IMPORTED_ENTITY: {
|
2017-07-19 08:09:54 +08:00
|
|
|
if (Record.size() != 6 && Record.size() != 7)
|
2016-12-23 11:59:18 +08:00
|
|
|
return error("Invalid record");
|
|
|
|
|
|
|
|
IsDistinct = Record[0];
|
2017-07-19 08:09:54 +08:00
|
|
|
bool HasFile = (Record.size() == 7);
|
2016-12-23 11:59:18 +08:00
|
|
|
MetadataList.assignValue(
|
|
|
|
GET_OR_DISTINCT(DIImportedEntity,
|
|
|
|
(Context, Record[1], getMDOrNull(Record[2]),
|
2017-07-19 08:09:54 +08:00
|
|
|
getDITypeRefOrNull(Record[3]),
|
|
|
|
HasFile ? getMDOrNull(Record[6]) : nullptr,
|
|
|
|
HasFile ? Record[4] : 0, getMDString(Record[5]))),
|
Avoid using unspecified ordering in MetadataLoader::MetadataLoaderImpl::parseOneMetadata.
Summary:
MetadataLoader::MetadataLoaderImpl::parseOneMetadata uses
the following construct in a number of places:
```
MetadataList.assignValue(<...>, NextMetadataNo++);
```
There, NextMetadataNo gets incremented, and since the order
of arguments evaluation is not specified, that can happen
before or after other arguments are evaluated.
In a few cases the other arguments indirectly use NextMetadataNo.
For instance, it's
```
MetadataList.assignValue(
GET_OR_DISTINCT(DIModule,
(Context, getMDOrNull(Record[1]),
getMDString(Record[2]), getMDString(Record[3]),
getMDString(Record[4]), getMDString(Record[5]))),
NextMetadataNo++);
```
getMDOrNull calls getMD that uses NextMetadataNo:
```
MetadataList.getMetadataFwdRef(NextMetadataNo);
```
Therefore, the order of evaluation becomes important. That caused
a very subtle LLD crash that only happens if compiled with GCC or
if LLD is built with LTO. In the case if LLD is compiled with Clang
and regular linking mode, everything worked as intended.
This change extracts incrementing of NextMetadataNo outside of
the arguments list to guarantee the correct order of evaluation.
For the record, this has taken 3 days to track to the origin. It all
started with a ThinLTO bot in Chrome not being able to link a target
if debug info is enabled.
Reviewers: pcc, mehdi_amini
Reviewed By: mehdi_amini
Subscribers: aprantl, llvm-commits
Differential Revision: https://reviews.llvm.org/D29204
llvm-svn: 293291
2017-01-27 23:54:49 +08:00
|
|
|
NextMetadataNo);
|
|
|
|
NextMetadataNo++;
|
2016-12-23 11:59:18 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case bitc::METADATA_STRING_OLD: {
|
|
|
|
std::string String(Record.begin(), Record.end());
|
2016-12-13 03:34:26 +08:00
|
|
|
|
2016-12-23 11:59:18 +08:00
|
|
|
// Test for upgrading !llvm.loop.
|
|
|
|
HasSeenOldLoopTags |= mayBeOldLoopAttachmentTag(String);
|
2017-01-05 06:54:33 +08:00
|
|
|
++NumMDStringLoaded;
|
2016-12-23 11:59:18 +08:00
|
|
|
Metadata *MD = MDString::get(Context, String);
|
Avoid using unspecified ordering in MetadataLoader::MetadataLoaderImpl::parseOneMetadata.
Summary:
MetadataLoader::MetadataLoaderImpl::parseOneMetadata uses
the following construct in a number of places:
```
MetadataList.assignValue(<...>, NextMetadataNo++);
```
There, NextMetadataNo gets incremented, and since the order
of arguments evaluation is not specified, that can happen
before or after other arguments are evaluated.
In a few cases the other arguments indirectly use NextMetadataNo.
For instance, it's
```
MetadataList.assignValue(
GET_OR_DISTINCT(DIModule,
(Context, getMDOrNull(Record[1]),
getMDString(Record[2]), getMDString(Record[3]),
getMDString(Record[4]), getMDString(Record[5]))),
NextMetadataNo++);
```
getMDOrNull calls getMD that uses NextMetadataNo:
```
MetadataList.getMetadataFwdRef(NextMetadataNo);
```
Therefore, the order of evaluation becomes important. That caused
a very subtle LLD crash that only happens if compiled with GCC or
if LLD is built with LTO. In the case if LLD is compiled with Clang
and regular linking mode, everything worked as intended.
This change extracts incrementing of NextMetadataNo outside of
the arguments list to guarantee the correct order of evaluation.
For the record, this has taken 3 days to track to the origin. It all
started with a ThinLTO bot in Chrome not being able to link a target
if debug info is enabled.
Reviewers: pcc, mehdi_amini
Reviewed By: mehdi_amini
Subscribers: aprantl, llvm-commits
Differential Revision: https://reviews.llvm.org/D29204
llvm-svn: 293291
2017-01-27 23:54:49 +08:00
|
|
|
MetadataList.assignValue(MD, NextMetadataNo);
|
|
|
|
NextMetadataNo++;
|
2016-12-23 11:59:18 +08:00
|
|
|
break;
|
|
|
|
}
|
2017-01-05 06:54:33 +08:00
|
|
|
case bitc::METADATA_STRINGS: {
|
|
|
|
auto CreateNextMDString = [&](StringRef Str) {
|
|
|
|
++NumMDStringLoaded;
|
Avoid using unspecified ordering in MetadataLoader::MetadataLoaderImpl::parseOneMetadata.
Summary:
MetadataLoader::MetadataLoaderImpl::parseOneMetadata uses
the following construct in a number of places:
```
MetadataList.assignValue(<...>, NextMetadataNo++);
```
There, NextMetadataNo gets incremented, and since the order
of arguments evaluation is not specified, that can happen
before or after other arguments are evaluated.
In a few cases the other arguments indirectly use NextMetadataNo.
For instance, it's
```
MetadataList.assignValue(
GET_OR_DISTINCT(DIModule,
(Context, getMDOrNull(Record[1]),
getMDString(Record[2]), getMDString(Record[3]),
getMDString(Record[4]), getMDString(Record[5]))),
NextMetadataNo++);
```
getMDOrNull calls getMD that uses NextMetadataNo:
```
MetadataList.getMetadataFwdRef(NextMetadataNo);
```
Therefore, the order of evaluation becomes important. That caused
a very subtle LLD crash that only happens if compiled with GCC or
if LLD is built with LTO. In the case if LLD is compiled with Clang
and regular linking mode, everything worked as intended.
This change extracts incrementing of NextMetadataNo outside of
the arguments list to guarantee the correct order of evaluation.
For the record, this has taken 3 days to track to the origin. It all
started with a ThinLTO bot in Chrome not being able to link a target
if debug info is enabled.
Reviewers: pcc, mehdi_amini
Reviewed By: mehdi_amini
Subscribers: aprantl, llvm-commits
Differential Revision: https://reviews.llvm.org/D29204
llvm-svn: 293291
2017-01-27 23:54:49 +08:00
|
|
|
MetadataList.assignValue(MDString::get(Context, Str), NextMetadataNo);
|
|
|
|
NextMetadataNo++;
|
2017-01-05 06:54:33 +08:00
|
|
|
};
|
|
|
|
if (Error Err = parseMetadataStrings(Record, Blob, CreateNextMDString))
|
2016-12-23 11:59:18 +08:00
|
|
|
return Err;
|
|
|
|
break;
|
2017-01-05 06:54:33 +08:00
|
|
|
}
|
2016-12-23 11:59:18 +08:00
|
|
|
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)))
|
2016-12-13 03:34:26 +08:00
|
|
|
return Err;
|
2016-12-23 11:59:18 +08:00
|
|
|
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;
|
|
|
|
}
|
2016-12-13 03:34:26 +08:00
|
|
|
}
|
2016-12-23 11:59:18 +08:00
|
|
|
return Error::success();
|
2017-01-05 06:54:33 +08:00
|
|
|
#undef GET_OR_DISTINCT
|
2016-12-13 03:34:26 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
Error MetadataLoader::MetadataLoaderImpl::parseMetadataStrings(
|
2017-01-05 06:54:33 +08:00
|
|
|
ArrayRef<uint64_t> Record, StringRef Blob,
|
2017-01-13 22:39:03 +08:00
|
|
|
function_ref<void(StringRef)> CallBack) {
|
2016-12-13 03:34:26 +08:00
|
|
|
// All the MDStrings in the block are emitted together in a single
|
|
|
|
// record. The strings are concatenated and stored in a blob along with
|
|
|
|
// their sizes.
|
|
|
|
if (Record.size() != 2)
|
|
|
|
return error("Invalid record: metadata strings layout");
|
|
|
|
|
|
|
|
unsigned NumStrings = Record[0];
|
|
|
|
unsigned StringsOffset = Record[1];
|
|
|
|
if (!NumStrings)
|
|
|
|
return error("Invalid record: metadata strings with no strings");
|
|
|
|
if (StringsOffset > Blob.size())
|
|
|
|
return error("Invalid record: metadata strings corrupt offset");
|
|
|
|
|
|
|
|
StringRef Lengths = Blob.slice(0, StringsOffset);
|
|
|
|
SimpleBitstreamCursor R(Lengths);
|
|
|
|
|
|
|
|
StringRef Strings = Blob.drop_front(StringsOffset);
|
|
|
|
do {
|
|
|
|
if (R.AtEndOfStream())
|
|
|
|
return error("Invalid record: metadata strings bad length");
|
|
|
|
|
2019-06-27 03:50:12 +08:00
|
|
|
Expected<uint32_t> MaybeSize = R.ReadVBR(6);
|
|
|
|
if (!MaybeSize)
|
|
|
|
return MaybeSize.takeError();
|
|
|
|
uint32_t Size = MaybeSize.get();
|
2016-12-13 03:34:26 +08:00
|
|
|
if (Strings.size() < Size)
|
|
|
|
return error("Invalid record: metadata strings truncated chars");
|
|
|
|
|
2017-01-05 06:54:33 +08:00
|
|
|
CallBack(Strings.slice(0, Size));
|
2016-12-13 03:34:26 +08:00
|
|
|
Strings = Strings.drop_front(Size);
|
|
|
|
} while (--NumStrings);
|
|
|
|
|
|
|
|
return Error::success();
|
|
|
|
}
|
|
|
|
|
|
|
|
Error MetadataLoader::MetadataLoaderImpl::parseGlobalObjectAttachment(
|
|
|
|
GlobalObject &GO, ArrayRef<uint64_t> Record) {
|
|
|
|
assert(Record.size() % 2 == 0);
|
|
|
|
for (unsigned I = 0, E = Record.size(); I != E; I += 2) {
|
|
|
|
auto K = MDKindMap.find(Record[I]);
|
|
|
|
if (K == MDKindMap.end())
|
|
|
|
return error("Invalid ID");
|
|
|
|
MDNode *MD = MetadataList.getMDNodeFwdRefOrNull(Record[I + 1]);
|
|
|
|
if (!MD)
|
2018-11-15 05:57:51 +08:00
|
|
|
return error("Invalid metadata attachment: expect fwd ref to MDNode");
|
2016-12-13 03:34:26 +08:00
|
|
|
GO.addMetadata(K->second, *MD);
|
|
|
|
}
|
|
|
|
return Error::success();
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Parse metadata attachments.
|
|
|
|
Error MetadataLoader::MetadataLoaderImpl::parseMetadataAttachment(
|
|
|
|
Function &F, const SmallVectorImpl<Instruction *> &InstructionList) {
|
2019-06-27 03:50:12 +08:00
|
|
|
if (Error Err = Stream.EnterSubBlock(bitc::METADATA_ATTACHMENT_ID))
|
|
|
|
return Err;
|
2016-12-13 03:34:26 +08:00
|
|
|
|
|
|
|
SmallVector<uint64_t, 64> Record;
|
2017-01-08 08:44:45 +08:00
|
|
|
PlaceholderQueue Placeholders;
|
2016-12-13 03:34:26 +08:00
|
|
|
|
|
|
|
while (true) {
|
2019-06-27 03:50:12 +08:00
|
|
|
Expected<BitstreamEntry> MaybeEntry = Stream.advanceSkippingSubblocks();
|
|
|
|
if (!MaybeEntry)
|
|
|
|
return MaybeEntry.takeError();
|
|
|
|
BitstreamEntry Entry = MaybeEntry.get();
|
2016-12-13 03:34:26 +08:00
|
|
|
|
|
|
|
switch (Entry.Kind) {
|
|
|
|
case BitstreamEntry::SubBlock: // Handled for us already.
|
|
|
|
case BitstreamEntry::Error:
|
|
|
|
return error("Malformed block");
|
|
|
|
case BitstreamEntry::EndBlock:
|
2017-01-08 08:44:45 +08:00
|
|
|
resolveForwardRefsAndPlaceholders(Placeholders);
|
2016-12-13 03:34:26 +08:00
|
|
|
return Error::success();
|
|
|
|
case BitstreamEntry::Record:
|
|
|
|
// The interesting case.
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Read a metadata attachment record.
|
|
|
|
Record.clear();
|
2017-01-05 06:54:33 +08:00
|
|
|
++NumMDRecordLoaded;
|
2019-06-27 03:50:12 +08:00
|
|
|
Expected<unsigned> MaybeRecord = Stream.readRecord(Entry.ID, Record);
|
|
|
|
if (!MaybeRecord)
|
|
|
|
return MaybeRecord.takeError();
|
|
|
|
switch (MaybeRecord.get()) {
|
2016-12-13 03:34:26 +08:00
|
|
|
default: // Default behavior: ignore.
|
|
|
|
break;
|
|
|
|
case bitc::METADATA_ATTACHMENT: {
|
|
|
|
unsigned RecordLength = Record.size();
|
|
|
|
if (Record.empty())
|
|
|
|
return error("Invalid record");
|
|
|
|
if (RecordLength % 2 == 0) {
|
|
|
|
// A function attachment.
|
|
|
|
if (Error Err = parseGlobalObjectAttachment(F, Record))
|
|
|
|
return Err;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
// An instruction attachment.
|
|
|
|
Instruction *Inst = InstructionList[Record[0]];
|
|
|
|
for (unsigned i = 1; i != RecordLength; i = i + 2) {
|
|
|
|
unsigned Kind = Record[i];
|
|
|
|
DenseMap<unsigned, unsigned>::iterator I = MDKindMap.find(Kind);
|
|
|
|
if (I == MDKindMap.end())
|
|
|
|
return error("Invalid ID");
|
2016-12-17 03:16:29 +08:00
|
|
|
if (I->second == LLVMContext::MD_tbaa && StripTBAA)
|
|
|
|
continue;
|
|
|
|
|
2017-01-05 06:54:33 +08:00
|
|
|
auto Idx = Record[i + 1];
|
|
|
|
if (Idx < (MDStringRef.size() + GlobalMetadataBitPosIndex.size()) &&
|
2017-01-08 04:24:23 +08:00
|
|
|
!MetadataList.lookup(Idx)) {
|
2017-01-05 06:54:33 +08:00
|
|
|
// Load the attachment if it is in the lazy-loadable range and hasn't
|
|
|
|
// been loaded yet.
|
|
|
|
lazyLoadOneMetadata(Idx, Placeholders);
|
2017-01-08 04:24:23 +08:00
|
|
|
resolveForwardRefsAndPlaceholders(Placeholders);
|
|
|
|
}
|
2017-01-05 06:54:33 +08:00
|
|
|
|
|
|
|
Metadata *Node = MetadataList.getMetadataFwdRef(Idx);
|
2016-12-13 03:34:26 +08:00
|
|
|
if (isa<LocalAsMetadata>(Node))
|
|
|
|
// Drop the attachment. This used to be legal, but there's no
|
|
|
|
// upgrade path.
|
|
|
|
break;
|
|
|
|
MDNode *MD = dyn_cast_or_null<MDNode>(Node);
|
|
|
|
if (!MD)
|
|
|
|
return error("Invalid metadata attachment");
|
|
|
|
|
|
|
|
if (HasSeenOldLoopTags && I->second == LLVMContext::MD_loop)
|
|
|
|
MD = upgradeInstructionLoopAttachment(*MD);
|
|
|
|
|
|
|
|
if (I->second == LLVMContext::MD_tbaa) {
|
|
|
|
assert(!MD->isTemporary() && "should load MDs before attachments");
|
|
|
|
MD = UpgradeTBAANode(*MD);
|
|
|
|
}
|
|
|
|
Inst->setMetadata(I->second, MD);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Parse a single METADATA_KIND record, inserting result in MDKindMap.
|
|
|
|
Error MetadataLoader::MetadataLoaderImpl::parseMetadataKindRecord(
|
|
|
|
SmallVectorImpl<uint64_t> &Record) {
|
|
|
|
if (Record.size() < 2)
|
|
|
|
return error("Invalid record");
|
|
|
|
|
|
|
|
unsigned Kind = Record[0];
|
|
|
|
SmallString<8> Name(Record.begin() + 1, Record.end());
|
|
|
|
|
|
|
|
unsigned NewKind = TheModule.getMDKindID(Name.str());
|
|
|
|
if (!MDKindMap.insert(std::make_pair(Kind, NewKind)).second)
|
|
|
|
return error("Conflicting METADATA_KIND records");
|
|
|
|
return Error::success();
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Parse the metadata kinds out of the METADATA_KIND_BLOCK.
|
|
|
|
Error MetadataLoader::MetadataLoaderImpl::parseMetadataKinds() {
|
2019-06-27 03:50:12 +08:00
|
|
|
if (Error Err = Stream.EnterSubBlock(bitc::METADATA_KIND_BLOCK_ID))
|
|
|
|
return Err;
|
2016-12-13 03:34:26 +08:00
|
|
|
|
|
|
|
SmallVector<uint64_t, 64> Record;
|
|
|
|
|
|
|
|
// Read all the records.
|
|
|
|
while (true) {
|
2019-06-27 03:50:12 +08:00
|
|
|
Expected<BitstreamEntry> MaybeEntry = Stream.advanceSkippingSubblocks();
|
|
|
|
if (!MaybeEntry)
|
|
|
|
return MaybeEntry.takeError();
|
|
|
|
BitstreamEntry Entry = MaybeEntry.get();
|
2016-12-13 03:34:26 +08:00
|
|
|
|
|
|
|
switch (Entry.Kind) {
|
|
|
|
case BitstreamEntry::SubBlock: // Handled for us already.
|
|
|
|
case BitstreamEntry::Error:
|
|
|
|
return error("Malformed block");
|
|
|
|
case BitstreamEntry::EndBlock:
|
|
|
|
return Error::success();
|
|
|
|
case BitstreamEntry::Record:
|
|
|
|
// The interesting case.
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Read a record.
|
|
|
|
Record.clear();
|
2017-01-05 06:54:33 +08:00
|
|
|
++NumMDRecordLoaded;
|
2019-06-27 03:50:12 +08:00
|
|
|
Expected<unsigned> MaybeCode = Stream.readRecord(Entry.ID, Record);
|
|
|
|
if (!MaybeCode)
|
|
|
|
return MaybeCode.takeError();
|
|
|
|
switch (MaybeCode.get()) {
|
2016-12-13 03:34:26 +08:00
|
|
|
default: // Default behavior: ignore.
|
|
|
|
break;
|
|
|
|
case bitc::METADATA_KIND: {
|
|
|
|
if (Error Err = parseMetadataKindRecord(Record))
|
|
|
|
return Err;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
MetadataLoader &MetadataLoader::operator=(MetadataLoader &&RHS) {
|
|
|
|
Pimpl = std::move(RHS.Pimpl);
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
MetadataLoader::MetadataLoader(MetadataLoader &&RHS)
|
2016-12-23 10:20:02 +08:00
|
|
|
: Pimpl(std::move(RHS.Pimpl)) {}
|
2016-12-13 03:34:26 +08:00
|
|
|
|
|
|
|
MetadataLoader::~MetadataLoader() = default;
|
|
|
|
MetadataLoader::MetadataLoader(BitstreamCursor &Stream, Module &TheModule,
|
|
|
|
BitcodeReaderValueList &ValueList,
|
2016-12-17 05:25:01 +08:00
|
|
|
bool IsImporting,
|
2016-12-13 03:34:26 +08:00
|
|
|
std::function<Type *(unsigned)> getTypeByID)
|
2019-08-15 23:54:37 +08:00
|
|
|
: Pimpl(std::make_unique<MetadataLoaderImpl>(
|
2017-01-13 22:39:03 +08:00
|
|
|
Stream, TheModule, ValueList, std::move(getTypeByID), IsImporting)) {}
|
2016-12-13 03:34:26 +08:00
|
|
|
|
|
|
|
Error MetadataLoader::parseMetadata(bool ModuleLevel) {
|
2016-12-23 10:20:02 +08:00
|
|
|
return Pimpl->parseMetadata(ModuleLevel);
|
2016-12-13 03:34:26 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
bool MetadataLoader::hasFwdRefs() const { return Pimpl->hasFwdRefs(); }
|
|
|
|
|
|
|
|
/// Return the given metadata, creating a replaceable forward reference if
|
|
|
|
/// necessary.
|
2017-01-21 04:29:16 +08:00
|
|
|
Metadata *MetadataLoader::getMetadataFwdRefOrLoad(unsigned Idx) {
|
|
|
|
return Pimpl->getMetadataFwdRefOrLoad(Idx);
|
2016-12-13 03:34:26 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
DISubprogram *MetadataLoader::lookupSubprogramForFunction(Function *F) {
|
|
|
|
return Pimpl->lookupSubprogramForFunction(F);
|
|
|
|
}
|
|
|
|
|
|
|
|
Error MetadataLoader::parseMetadataAttachment(
|
|
|
|
Function &F, const SmallVectorImpl<Instruction *> &InstructionList) {
|
|
|
|
return Pimpl->parseMetadataAttachment(F, InstructionList);
|
|
|
|
}
|
|
|
|
|
|
|
|
Error MetadataLoader::parseMetadataKinds() {
|
|
|
|
return Pimpl->parseMetadataKinds();
|
|
|
|
}
|
|
|
|
|
2016-12-17 03:16:29 +08:00
|
|
|
void MetadataLoader::setStripTBAA(bool StripTBAA) {
|
|
|
|
return Pimpl->setStripTBAA(StripTBAA);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool MetadataLoader::isStrippingTBAA() { return Pimpl->isStrippingTBAA(); }
|
|
|
|
|
2016-12-13 03:34:26 +08:00
|
|
|
unsigned MetadataLoader::size() const { return Pimpl->size(); }
|
|
|
|
void MetadataLoader::shrinkTo(unsigned N) { return Pimpl->shrinkTo(N); }
|
2017-04-18 09:21:53 +08:00
|
|
|
|
|
|
|
void MetadataLoader::upgradeDebugIntrinsics(Function &F) {
|
|
|
|
return Pimpl->upgradeDebugIntrinsics(F);
|
|
|
|
}
|