Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 2 additions & 44 deletions clang/include/clang/Serialization/ModuleManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,50 +59,8 @@ class ModuleManager {
// to implement short-circuiting logic when running DFS over the dependencies.
SmallVector<ModuleFile *, 2> Roots;

/// An \c EntryKey is a thin wrapper around a \c FileEntry that implements
/// a richer notion of identity.
///
/// A plain \c FileEntry has its identity tied to inode numbers. When the
/// module cache regenerates a PCM, some filesystem allocators may reuse
/// inode numbers for distinct modules, which can cause the cache to return
/// mismatched entries. An \c EntryKey ensures that the size and modification
/// time are taken into account when determining the identity of a key, which
/// significantly decreases - but does not eliminate - the chance of
/// a collision.
struct EntryKey {
const FileEntry *Entry;

struct Info {
static inline EntryKey getEmptyKey() {
return EntryKey{llvm::DenseMapInfo<const FileEntry *>::getEmptyKey()};
}
static inline EntryKey getTombstoneKey() {
return EntryKey{
llvm::DenseMapInfo<const FileEntry *>::getTombstoneKey()};
}
static unsigned getHashValue(const EntryKey &Val) {
return llvm::DenseMapInfo<const FileEntry *>::getHashValue(Val.Entry);
}
static bool isEqual(const EntryKey &LHS, const EntryKey &RHS) {
if (LHS.Entry == getEmptyKey().Entry ||
LHS.Entry == getTombstoneKey().Entry ||
RHS.Entry == getEmptyKey().Entry ||
RHS.Entry == getTombstoneKey().Entry) {
return LHS.Entry == RHS.Entry;
}
if (LHS.Entry == nullptr || RHS.Entry == nullptr) {
return LHS.Entry == RHS.Entry;
}
return LHS.Entry == RHS.Entry &&
LHS.Entry->getSize() == RHS.Entry->getSize() &&
LHS.Entry->getModificationTime() ==
RHS.Entry->getModificationTime();
}
};
};

/// All loaded modules, indexed by name.
llvm::DenseMap<EntryKey, ModuleFile *, EntryKey::Info> Modules;
llvm::DenseMap<const FileEntry *, ModuleFile *> Modules;

/// FileManager that handles translating between filenames and
/// FileEntry *.
Expand All @@ -118,7 +76,7 @@ class ModuleManager {
const HeaderSearch &HeaderSearchInfo;

/// A lookup of in-memory (virtual file) buffers
llvm::DenseMap<EntryKey, std::unique_ptr<llvm::MemoryBuffer>, EntryKey::Info>
llvm::DenseMap<const FileEntry *, std::unique_ptr<llvm::MemoryBuffer>>
InMemoryBuffers;

/// The visitation order.
Expand Down
49 changes: 36 additions & 13 deletions clang/lib/Serialization/ModuleManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ ModuleFile *ModuleManager::lookupByModuleName(StringRef Name) const {
}

ModuleFile *ModuleManager::lookup(const FileEntry *File) const {
auto Known = Modules.find(EntryKey{File});
auto Known = Modules.find(File);
if (Known == Modules.end())
return nullptr;

Expand All @@ -72,7 +72,7 @@ ModuleManager::lookupBuffer(StringRef Name) {
/*CacheFailure=*/false);
if (!Entry)
return nullptr;
return std::move(InMemoryBuffers[EntryKey{*Entry}]);
return std::move(InMemoryBuffers[*Entry]);
}

static bool checkSignature(ASTFileSignature Signature,
Expand Down Expand Up @@ -132,15 +132,38 @@ ModuleManager::addModule(StringRef FileName, ModuleKind Type,
return Missing;
}

// The ModuleManager's use of FileEntry nodes as the keys for its map of
// loaded modules is less than ideal. Uniqueness for FileEntry nodes is
// maintained by FileManager, which in turn uses inode numbers on hosts
// that support that. When coupled with the module cache's proclivity for
// turning over and deleting stale PCMs, this means entries for different
// module files can wind up reusing the same underlying inode. When this
// happens, subsequent accesses to the Modules map will disagree on the
// ModuleFile associated with a given file. In general, it is not sufficient
// to resolve this conundrum with a type like FileEntryRef that stores the
// name of the FileEntry node on first access because of path canonicalization
// issues. However, the paths constructed for implicit module builds are
// fully under Clang's control. We *can*, therefore, rely on their structure
// being consistent across operating systems and across subsequent accesses
// to the Modules map.
auto implicitModuleNamesMatch = [](ModuleKind Kind, const ModuleFile *MF,
const FileEntry *Entry) -> bool {
if (Kind != MK_ImplicitModule)
return true;
return Entry->getName() == MF->FileName;
};

// Check whether we already loaded this module, before
if (ModuleFile *ModuleEntry = Modules.lookup(EntryKey{Entry})) {
// Check the stored signature.
if (checkSignature(ModuleEntry->Signature, ExpectedSignature, ErrorStr))
return OutOfDate;

Module = ModuleEntry;
updateModuleImports(*ModuleEntry, ImportedBy, ImportLoc);
return AlreadyLoaded;
if (ModuleFile *ModuleEntry = Modules.lookup(Entry)) {
if (implicitModuleNamesMatch(Type, ModuleEntry, Entry)) {
// Check the stored signature.
if (checkSignature(ModuleEntry->Signature, ExpectedSignature, ErrorStr))
return OutOfDate;

Module = ModuleEntry;
updateModuleImports(*ModuleEntry, ImportedBy, ImportLoc);
return AlreadyLoaded;
}
}

// Allocate a new module.
Expand Down Expand Up @@ -208,7 +231,7 @@ ModuleManager::addModule(StringRef FileName, ModuleKind Type,
return OutOfDate;

// We're keeping this module. Store it everywhere.
Module = Modules[EntryKey{Entry}] = NewModule.get();
Module = Modules[Entry] = NewModule.get();

updateModuleImports(*NewModule, ImportedBy, ImportLoc);

Expand Down Expand Up @@ -255,7 +278,7 @@ void ModuleManager::removeModules(ModuleIterator First, ModuleMap *modMap) {

// Delete the modules and erase them from the various structures.
for (ModuleIterator victim = First; victim != Last; ++victim) {
Modules.erase(EntryKey{victim->File});
Modules.erase(victim->File);

if (modMap) {
StringRef ModuleName = victim->ModuleName;
Expand All @@ -274,7 +297,7 @@ ModuleManager::addInMemoryBuffer(StringRef FileName,
std::unique_ptr<llvm::MemoryBuffer> Buffer) {
const FileEntry *Entry =
FileMgr.getVirtualFile(FileName, Buffer->getBufferSize(), 0);
InMemoryBuffers[EntryKey{Entry}] = std::move(Buffer);
InMemoryBuffers[Entry] = std::move(Buffer);
}

ModuleManager::VisitState *ModuleManager::allocateVisitState() {
Expand Down
20 changes: 20 additions & 0 deletions clang/test/CodeGen/constantexpr-fneg.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// RUN: %clang_cc1 -emit-llvm-bc -disable-llvm-passes -o %t.bc %s
// RUN: llvm-dis %t.bc -o - | FileCheck %s

// Test case for PR45426. Make sure we do not crash while writing bitcode
// containing a simplify-able fneg constant expression. Check that the created
// bitcode file can be disassembled and has the constant expressions simplified.
//
// CHECK-LABEL define i32 @main()
// CHECK: entry:
// CHECK-NEXT: %retval = alloca i32
// CHECK-NEXT: store i32 0, i32* %retval
// CHECK-NEXT: [[LV:%.*]] = load float*, float** @c
// CHECK-NEXT: store float 1.000000e+00, float* [[LV]], align 4
// CHECK-NEXT: ret i32 -1

int a[], b;
float *c;
int main() {
return -(*c = &b != a);
}
Original file line number Diff line number Diff line change
Expand Up @@ -1729,7 +1729,7 @@ SwiftLanguageRuntimeImpl::GetTypeInfo(CompilerType type) {
swift::Demangle::Demangler Dem;
auto demangled = Dem.demangleType(mangled_no_prefix);
auto *type_ref = swift::Demangle::decodeMangledType(
reflection_ctx->getBuilder(), demangled);
reflection_ctx->getBuilder(), demangled).getType();
if (!type_ref)
return nullptr;
return reflection_ctx->getBuilder().getTypeConverter().getTypeInfo(type_ref);
Expand Down
7 changes: 7 additions & 0 deletions llvm/include/llvm/Support/type_traits.h
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,13 @@ template <typename T>
class is_trivially_copyable<T*> : public std::true_type {
};

// Workaround the resolution to DR1734
#if _MSVC_STL_UPDATE-0l > 202002l
template <>
class is_trivially_copyable<std::pair<void *, size_t>> : public std::true_type {
};
#endif


} // end namespace llvm

Expand Down
2 changes: 2 additions & 0 deletions llvm/lib/IR/Constants.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1316,6 +1316,8 @@ Constant *ConstantExpr::getWithOperands(ArrayRef<Constant *> Ops, Type *Ty,
OnlyIfReducedTy);
case Instruction::ExtractValue:
return ConstantExpr::getExtractValue(Ops[0], getIndices(), OnlyIfReducedTy);
case Instruction::FNeg:
return ConstantExpr::getFNeg(Ops[0]);
case Instruction::ShuffleVector:
return ConstantExpr::getShuffleVector(Ops[0], Ops[1], Ops[2],
OnlyIfReducedTy);
Expand Down