blob: f44b7034424c0a784863a1ddfe4daf6d1c91295a [file] [log] [blame]
//===--- LocalTypeDataCache.h - Dominance-scoped type data cache --*- C++ -*-=//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
// This file defines the LocalTypeDataCache type, which is used by
// IRGenFunction to cache the information available for types in a local
// context.
//
//===----------------------------------------------------------------------===//
#ifndef SWIFT_IRGEN_LOCALTYPEDATACACHE_H
#define SWIFT_IRGEN_LOCALTYPEDATACACHE_H
#include "swift/AST/Type.h"
#include <utility>
namespace swift {
class TypeBase;
namespace irgen {
enum class ValueWitness : unsigned;
/// A nonce value for storing some sort of locally-known information
/// about a type.
class LocalTypeData {
public:
using RawType = unsigned;
private:
RawType Value;
explicit LocalTypeData(unsigned Value) : Value(Value) {}
/// Magic values for special kinds of index.
enum : RawType {
Metatype = ~0U,
ValueWitnessTable = ~1U,
ValueWitnessBase = 0xFFFFFF00U,
};
public:
LocalTypeData() = default;
// The magic values are all in the "negative" range and so do
// not collide with reasonable index values.
/// A reference to the type metadata.
static LocalTypeData forMetatype() { return LocalTypeData(Metatype); }
/// A reference to the value witness table.
static LocalTypeData forValueWitnessTable() {
return LocalTypeData(ValueWitnessTable);
}
/// A reference to a specific value witness.
static LocalTypeData forValueWitness(ValueWitness witness) {
return LocalTypeData((unsigned)witness + ValueWitnessBase);
}
/// A reference to a protocol witness table for an archetype.
static LocalTypeData forArchetypeProtocolWitness(unsigned index) {
return LocalTypeData(index);
}
RawType getRawValue() const {
return Value;
}
};
class LocalTypeDataCache {
public:
using Key = std::pair<TypeBase*, LocalTypeData::RawType>;
static Key getKey(CanType type, LocalTypeData index) {
return Key(type.getPointer(), index.getRawValue());
}
/// An opaque class for storing keys for the dominance callback. The
/// key is assumed to be something like a pointer, and a null pointer is
/// assumed to mean a non-dominating point.
class DominanceKey {
void *Value;
public:
explicit DominanceKey(void *value = nullptr) : Value(value) {}
template <class T> T* as() const { return reinterpret_cast<T*>(Value); }
explicit operator bool() const { return Value != nullptr; }
};
/// A RAII object for managing a dominance scope.
class DominanceScope {
LocalTypeDataCache &Cache;
DominanceKey OldDefinitionPoint;
public:
explicit DominanceScope(LocalTypeDataCache &cache, DominanceKey newPoint)
: Cache(cache), OldDefinitionPoint(cache.ActiveDefinitionPoint) {
cache.ActiveDefinitionPoint = newPoint;
assert(!newPoint || cache.Callback);
}
DominanceScope(const DominanceScope &other) = delete;
DominanceScope &operator=(const DominanceScope &other) = delete;
~DominanceScope() {
Cache.ActiveDefinitionPoint = OldDefinitionPoint;
}
};
using DominanceCallback = bool(IRGenFunction &IGF, DominanceKey key);
private:
/// The dominance callback. This can be set at most once; when it's not
/// set, the cache must never have a non-null active definition point.
DominanceCallback *Callback = nullptr;
DominanceKey ActiveDefinitionPoint;
struct CacheEntryBase {
DominanceKey DefinitionPoint;
};
struct Source {
llvm::Value *Value;
MetadataPath::Map<llvm::Value*> Path;
};
std::vector<
public:
};
}
}
#endif