2010-03-21 21:17:34 +00:00
|
|
|
//===-- LLVMContextImpl.h - The LLVMContextImpl opaque class ----*- C++ -*-===//
|
2009-06-30 00:48:55 +00:00
|
|
|
//
|
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
2009-06-30 17:06:46 +00:00
|
|
|
//
|
|
|
|
// This file declares LLVMContextImpl, the opaque implementation
|
|
|
|
// of LLVMContext.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
2009-06-30 00:48:55 +00:00
|
|
|
|
2014-08-13 16:26:38 +00:00
|
|
|
#ifndef LLVM_LIB_IR_LLVMCONTEXTIMPL_H
|
|
|
|
#define LLVM_LIB_IR_LLVMCONTEXTIMPL_H
|
2009-06-30 00:48:55 +00:00
|
|
|
|
2012-12-20 01:36:59 +00:00
|
|
|
#include "AttributeImpl.h"
|
2009-08-04 22:41:48 +00:00
|
|
|
#include "ConstantsContext.h"
|
2009-07-16 19:05:41 +00:00
|
|
|
#include "llvm/ADT/APFloat.h"
|
2009-07-16 18:04:31 +00:00
|
|
|
#include "llvm/ADT/APInt.h"
|
2011-06-22 08:50:06 +00:00
|
|
|
#include "llvm/ADT/ArrayRef.h"
|
2009-07-16 18:04:31 +00:00
|
|
|
#include "llvm/ADT/DenseMap.h"
|
2014-11-17 23:28:21 +00:00
|
|
|
#include "llvm/ADT/DenseSet.h"
|
2009-07-16 23:44:30 +00:00
|
|
|
#include "llvm/ADT/FoldingSet.h"
|
2012-12-04 07:12:27 +00:00
|
|
|
#include "llvm/ADT/Hashing.h"
|
2009-12-17 19:55:06 +00:00
|
|
|
#include "llvm/ADT/SmallPtrSet.h"
|
2009-07-16 22:11:26 +00:00
|
|
|
#include "llvm/ADT/StringMap.h"
|
2013-01-02 11:36:10 +00:00
|
|
|
#include "llvm/IR/Constants.h"
|
2015-02-02 18:53:21 +00:00
|
|
|
#include "llvm/IR/DebugInfoMetadata.h"
|
2013-01-02 11:36:10 +00:00
|
|
|
#include "llvm/IR/DerivedTypes.h"
|
|
|
|
#include "llvm/IR/LLVMContext.h"
|
|
|
|
#include "llvm/IR/Metadata.h"
|
2014-03-04 11:17:44 +00:00
|
|
|
#include "llvm/IR/ValueHandle.h"
|
2009-07-23 23:25:33 +00:00
|
|
|
#include <vector>
|
2009-07-21 20:13:12 +00:00
|
|
|
|
2009-06-30 00:48:55 +00:00
|
|
|
namespace llvm {
|
2009-07-24 23:12:02 +00:00
|
|
|
|
2009-07-16 18:04:31 +00:00
|
|
|
class ConstantInt;
|
2009-07-16 19:05:41 +00:00
|
|
|
class ConstantFP;
|
2014-05-22 14:19:46 +00:00
|
|
|
class DiagnosticInfoOptimizationRemark;
|
|
|
|
class DiagnosticInfoOptimizationRemarkMissed;
|
|
|
|
class DiagnosticInfoOptimizationRemarkAnalysis;
|
2015-01-16 20:07:33 +00:00
|
|
|
class GCStrategy;
|
2009-08-11 17:45:13 +00:00
|
|
|
class LLVMContext;
|
2009-07-16 18:04:31 +00:00
|
|
|
class Type;
|
2009-07-16 23:44:30 +00:00
|
|
|
class Value;
|
2009-07-16 18:04:31 +00:00
|
|
|
|
2013-09-11 18:05:11 +00:00
|
|
|
struct DenseMapAPIntKeyInfo {
|
2014-12-06 13:12:56 +00:00
|
|
|
static inline APInt getEmptyKey() {
|
|
|
|
APInt V(nullptr, 0);
|
|
|
|
V.VAL = 0;
|
|
|
|
return V;
|
|
|
|
}
|
|
|
|
static inline APInt getTombstoneKey() {
|
|
|
|
APInt V(nullptr, 0);
|
|
|
|
V.VAL = 1;
|
|
|
|
return V;
|
|
|
|
}
|
|
|
|
static unsigned getHashValue(const APInt &Key) {
|
2012-03-04 12:02:57 +00:00
|
|
|
return static_cast<unsigned>(hash_value(Key));
|
2009-07-16 18:04:31 +00:00
|
|
|
}
|
2014-12-06 13:12:56 +00:00
|
|
|
static bool isEqual(const APInt &LHS, const APInt &RHS) {
|
|
|
|
return LHS.getBitWidth() == RHS.getBitWidth() && LHS == RHS;
|
|
|
|
}
|
2009-07-16 18:04:31 +00:00
|
|
|
};
|
|
|
|
|
2013-09-11 18:05:11 +00:00
|
|
|
struct DenseMapAPFloatKeyInfo {
|
2014-12-06 13:12:56 +00:00
|
|
|
static inline APFloat getEmptyKey() { return APFloat(APFloat::Bogus, 1); }
|
|
|
|
static inline APFloat getTombstoneKey() { return APFloat(APFloat::Bogus, 2); }
|
|
|
|
static unsigned getHashValue(const APFloat &Key) {
|
2012-03-04 12:02:57 +00:00
|
|
|
return static_cast<unsigned>(hash_value(Key));
|
2009-07-16 19:05:41 +00:00
|
|
|
}
|
2014-12-06 13:12:56 +00:00
|
|
|
static bool isEqual(const APFloat &LHS, const APFloat &RHS) {
|
|
|
|
return LHS.bitwiseIsEqual(RHS);
|
|
|
|
}
|
2009-07-16 19:05:41 +00:00
|
|
|
};
|
|
|
|
|
2013-09-11 18:05:11 +00:00
|
|
|
struct AnonStructTypeKeyInfo {
|
2012-02-23 09:17:40 +00:00
|
|
|
struct KeyTy {
|
|
|
|
ArrayRef<Type*> ETypes;
|
|
|
|
bool isPacked;
|
|
|
|
KeyTy(const ArrayRef<Type*>& E, bool P) :
|
|
|
|
ETypes(E), isPacked(P) {}
|
2014-11-21 18:53:05 +00:00
|
|
|
KeyTy(const StructType *ST)
|
|
|
|
: ETypes(ST->elements()), isPacked(ST->isPacked()) {}
|
2012-02-23 09:17:40 +00:00
|
|
|
bool operator==(const KeyTy& that) const {
|
|
|
|
if (isPacked != that.isPacked)
|
|
|
|
return false;
|
|
|
|
if (ETypes != that.ETypes)
|
|
|
|
return false;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
bool operator!=(const KeyTy& that) const {
|
|
|
|
return !this->operator==(that);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
static inline StructType* getEmptyKey() {
|
|
|
|
return DenseMapInfo<StructType*>::getEmptyKey();
|
|
|
|
}
|
|
|
|
static inline StructType* getTombstoneKey() {
|
|
|
|
return DenseMapInfo<StructType*>::getTombstoneKey();
|
|
|
|
}
|
|
|
|
static unsigned getHashValue(const KeyTy& Key) {
|
Rewrite LLVM's generalized support library for hashing to follow the API
of the proposed standard hashing interfaces (N3333), and to use
a modified and tuned version of the CityHash algorithm.
Some of the highlights of this change:
-- Significantly higher quality hashing algorithm with very well
distributed results, and extremely few collisions. Should be close to
a checksum for up to 64-bit keys. Very little clustering or clumping of
hash codes, to better distribute load on probed hash tables.
-- Built-in support for reserved values.
-- Simplified API that composes cleanly with other C++ idioms and APIs.
-- Better scaling performance as keys grow. This is the fastest
algorithm I've found and measured for moderately sized keys (such as
show up in some of the uniquing and folding use cases)
-- Support for enabling per-execution seeds to prevent table ordering
or other artifacts of hashing algorithms to impact the output of
LLVM. The seeding would make each run different and highlight these
problems during bootstrap.
This implementation was tested extensively using the SMHasher test
suite, and pased with flying colors, doing better than the original
CityHash algorithm even.
I've included a unittest, although it is somewhat minimal at the moment.
I've also added (or refactored into the proper location) type traits
necessary to implement this, and converted users of GeneralHash over.
My only immediate concerns with this implementation is the performance
of hashing small keys. I've already started working to improve this, and
will continue to do so. Currently, the only algorithms faster produce
lower quality results, but it is likely there is a better compromise
than the current one.
Many thanks to Jeffrey Yasskin who did most of the work on the N3333
paper, pair-programmed some of this code, and reviewed much of it. Many
thanks also go to Geoff Pike Pike and Jyrki Alakuijala, the original
authors of CityHash on which this is heavily based, and Austin Appleby
who created MurmurHash and the SMHasher test suite.
Also thanks to Nadav, Tobias, Howard, Jay, Nick, Ahmed, and Duncan for
all of the review comments! If there are further comments or concerns,
please let me know and I'll jump on 'em.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@151822 91177308-0d34-0410-b5e6-96231b3b80d8
2012-03-01 18:55:25 +00:00
|
|
|
return hash_combine(hash_combine_range(Key.ETypes.begin(),
|
|
|
|
Key.ETypes.end()),
|
|
|
|
Key.isPacked);
|
2012-02-23 09:17:40 +00:00
|
|
|
}
|
|
|
|
static unsigned getHashValue(const StructType *ST) {
|
|
|
|
return getHashValue(KeyTy(ST));
|
|
|
|
}
|
|
|
|
static bool isEqual(const KeyTy& LHS, const StructType *RHS) {
|
|
|
|
if (RHS == getEmptyKey() || RHS == getTombstoneKey())
|
|
|
|
return false;
|
|
|
|
return LHS == KeyTy(RHS);
|
|
|
|
}
|
|
|
|
static bool isEqual(const StructType *LHS, const StructType *RHS) {
|
|
|
|
return LHS == RHS;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2013-09-11 18:05:11 +00:00
|
|
|
struct FunctionTypeKeyInfo {
|
2012-02-23 09:17:40 +00:00
|
|
|
struct KeyTy {
|
|
|
|
const Type *ReturnType;
|
|
|
|
ArrayRef<Type*> Params;
|
|
|
|
bool isVarArg;
|
|
|
|
KeyTy(const Type* R, const ArrayRef<Type*>& P, bool V) :
|
|
|
|
ReturnType(R), Params(P), isVarArg(V) {}
|
2014-11-21 19:03:35 +00:00
|
|
|
KeyTy(const FunctionType *FT)
|
|
|
|
: ReturnType(FT->getReturnType()), Params(FT->params()),
|
|
|
|
isVarArg(FT->isVarArg()) {}
|
2012-02-23 09:17:40 +00:00
|
|
|
bool operator==(const KeyTy& that) const {
|
|
|
|
if (ReturnType != that.ReturnType)
|
|
|
|
return false;
|
|
|
|
if (isVarArg != that.isVarArg)
|
|
|
|
return false;
|
|
|
|
if (Params != that.Params)
|
|
|
|
return false;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
bool operator!=(const KeyTy& that) const {
|
|
|
|
return !this->operator==(that);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
static inline FunctionType* getEmptyKey() {
|
|
|
|
return DenseMapInfo<FunctionType*>::getEmptyKey();
|
|
|
|
}
|
|
|
|
static inline FunctionType* getTombstoneKey() {
|
|
|
|
return DenseMapInfo<FunctionType*>::getTombstoneKey();
|
|
|
|
}
|
|
|
|
static unsigned getHashValue(const KeyTy& Key) {
|
Rewrite LLVM's generalized support library for hashing to follow the API
of the proposed standard hashing interfaces (N3333), and to use
a modified and tuned version of the CityHash algorithm.
Some of the highlights of this change:
-- Significantly higher quality hashing algorithm with very well
distributed results, and extremely few collisions. Should be close to
a checksum for up to 64-bit keys. Very little clustering or clumping of
hash codes, to better distribute load on probed hash tables.
-- Built-in support for reserved values.
-- Simplified API that composes cleanly with other C++ idioms and APIs.
-- Better scaling performance as keys grow. This is the fastest
algorithm I've found and measured for moderately sized keys (such as
show up in some of the uniquing and folding use cases)
-- Support for enabling per-execution seeds to prevent table ordering
or other artifacts of hashing algorithms to impact the output of
LLVM. The seeding would make each run different and highlight these
problems during bootstrap.
This implementation was tested extensively using the SMHasher test
suite, and pased with flying colors, doing better than the original
CityHash algorithm even.
I've included a unittest, although it is somewhat minimal at the moment.
I've also added (or refactored into the proper location) type traits
necessary to implement this, and converted users of GeneralHash over.
My only immediate concerns with this implementation is the performance
of hashing small keys. I've already started working to improve this, and
will continue to do so. Currently, the only algorithms faster produce
lower quality results, but it is likely there is a better compromise
than the current one.
Many thanks to Jeffrey Yasskin who did most of the work on the N3333
paper, pair-programmed some of this code, and reviewed much of it. Many
thanks also go to Geoff Pike Pike and Jyrki Alakuijala, the original
authors of CityHash on which this is heavily based, and Austin Appleby
who created MurmurHash and the SMHasher test suite.
Also thanks to Nadav, Tobias, Howard, Jay, Nick, Ahmed, and Duncan for
all of the review comments! If there are further comments or concerns,
please let me know and I'll jump on 'em.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@151822 91177308-0d34-0410-b5e6-96231b3b80d8
2012-03-01 18:55:25 +00:00
|
|
|
return hash_combine(Key.ReturnType,
|
|
|
|
hash_combine_range(Key.Params.begin(),
|
|
|
|
Key.Params.end()),
|
|
|
|
Key.isVarArg);
|
2012-02-23 09:17:40 +00:00
|
|
|
}
|
|
|
|
static unsigned getHashValue(const FunctionType *FT) {
|
|
|
|
return getHashValue(KeyTy(FT));
|
|
|
|
}
|
|
|
|
static bool isEqual(const KeyTy& LHS, const FunctionType *RHS) {
|
|
|
|
if (RHS == getEmptyKey() || RHS == getTombstoneKey())
|
|
|
|
return false;
|
|
|
|
return LHS == KeyTy(RHS);
|
|
|
|
}
|
|
|
|
static bool isEqual(const FunctionType *LHS, const FunctionType *RHS) {
|
|
|
|
return LHS == RHS;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2015-01-19 22:53:18 +00:00
|
|
|
/// \brief Structure for hashing arbitrary MDNode operands.
|
|
|
|
class MDNodeOpsKey {
|
|
|
|
ArrayRef<Metadata *> RawOps;
|
|
|
|
ArrayRef<MDOperand> Ops;
|
|
|
|
|
|
|
|
unsigned Hash;
|
|
|
|
|
|
|
|
protected:
|
|
|
|
MDNodeOpsKey(ArrayRef<Metadata *> Ops)
|
|
|
|
: RawOps(Ops), Hash(calculateHash(Ops)) {}
|
|
|
|
|
|
|
|
template <class NodeTy>
|
2015-02-04 22:08:30 +00:00
|
|
|
MDNodeOpsKey(const NodeTy *N, unsigned Offset = 0)
|
2015-01-20 00:01:43 +00:00
|
|
|
: Ops(N->op_begin() + Offset, N->op_end()), Hash(N->getHash()) {}
|
2015-01-19 22:53:18 +00:00
|
|
|
|
2015-01-20 00:01:43 +00:00
|
|
|
template <class NodeTy>
|
|
|
|
bool compareOps(const NodeTy *RHS, unsigned Offset = 0) const {
|
2015-01-19 22:53:18 +00:00
|
|
|
if (getHash() != RHS->getHash())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
assert((RawOps.empty() || Ops.empty()) && "Two sets of operands?");
|
2015-01-20 00:01:43 +00:00
|
|
|
return RawOps.empty() ? compareOps(Ops, RHS, Offset)
|
|
|
|
: compareOps(RawOps, RHS, Offset);
|
2015-01-19 22:53:18 +00:00
|
|
|
}
|
|
|
|
|
2015-01-20 00:01:43 +00:00
|
|
|
static unsigned calculateHash(MDNode *N, unsigned Offset = 0);
|
2015-01-19 22:53:18 +00:00
|
|
|
|
|
|
|
private:
|
|
|
|
template <class T>
|
2015-01-20 00:01:43 +00:00
|
|
|
static bool compareOps(ArrayRef<T> Ops, const MDNode *RHS, unsigned Offset) {
|
|
|
|
if (Ops.size() != RHS->getNumOperands() - Offset)
|
2015-01-19 22:53:18 +00:00
|
|
|
return false;
|
2015-01-20 00:01:43 +00:00
|
|
|
return std::equal(Ops.begin(), Ops.end(), RHS->op_begin() + Offset);
|
2015-01-19 22:53:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static unsigned calculateHash(ArrayRef<Metadata *> Ops);
|
|
|
|
|
|
|
|
public:
|
|
|
|
unsigned getHash() const { return Hash; }
|
|
|
|
};
|
|
|
|
|
2015-02-04 22:08:30 +00:00
|
|
|
template <class NodeTy> struct MDNodeKeyImpl;
|
|
|
|
template <class NodeTy> struct MDNodeInfo;
|
|
|
|
|
2015-01-12 20:09:34 +00:00
|
|
|
/// \brief DenseMapInfo for MDTuple.
|
2014-11-17 23:28:21 +00:00
|
|
|
///
|
|
|
|
/// Note that we don't need the is-function-local bit, since that's implicit in
|
|
|
|
/// the operands.
|
2015-02-04 22:08:30 +00:00
|
|
|
template <> struct MDNodeKeyImpl<MDTuple> : MDNodeOpsKey {
|
|
|
|
MDNodeKeyImpl(ArrayRef<Metadata *> Ops) : MDNodeOpsKey(Ops) {}
|
|
|
|
MDNodeKeyImpl(const MDTuple *N) : MDNodeOpsKey(N) {}
|
2012-04-11 14:06:54 +00:00
|
|
|
|
2015-02-05 00:51:35 +00:00
|
|
|
bool isKeyOf(const MDTuple *RHS) const { return compareOps(RHS); }
|
2015-01-19 22:53:18 +00:00
|
|
|
|
2015-02-04 22:08:30 +00:00
|
|
|
unsigned getHashValue() const { return getHash(); }
|
|
|
|
|
|
|
|
static unsigned calculateHash(MDTuple *N) {
|
|
|
|
return MDNodeOpsKey::calculateHash(N);
|
2012-04-11 14:06:54 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2015-01-13 20:44:56 +00:00
|
|
|
/// \brief DenseMapInfo for MDLocation.
|
2015-02-04 22:08:30 +00:00
|
|
|
template <> struct MDNodeKeyImpl<MDLocation> {
|
|
|
|
unsigned Line;
|
|
|
|
unsigned Column;
|
|
|
|
Metadata *Scope;
|
|
|
|
Metadata *InlinedAt;
|
2015-01-13 20:44:56 +00:00
|
|
|
|
2015-02-04 22:08:30 +00:00
|
|
|
MDNodeKeyImpl(unsigned Line, unsigned Column, Metadata *Scope,
|
|
|
|
Metadata *InlinedAt)
|
|
|
|
: Line(Line), Column(Column), Scope(Scope), InlinedAt(InlinedAt) {}
|
2015-01-13 20:44:56 +00:00
|
|
|
|
2015-02-04 22:08:30 +00:00
|
|
|
MDNodeKeyImpl(const MDLocation *L)
|
|
|
|
: Line(L->getLine()), Column(L->getColumn()), Scope(L->getScope()),
|
|
|
|
InlinedAt(L->getInlinedAt()) {}
|
2015-01-13 20:44:56 +00:00
|
|
|
|
2015-02-05 00:51:35 +00:00
|
|
|
bool isKeyOf(const MDLocation *RHS) const {
|
2015-02-04 22:08:30 +00:00
|
|
|
return Line == RHS->getLine() && Column == RHS->getColumn() &&
|
|
|
|
Scope == RHS->getScope() && InlinedAt == RHS->getInlinedAt();
|
2015-01-13 20:44:56 +00:00
|
|
|
}
|
2015-02-04 22:08:30 +00:00
|
|
|
unsigned getHashValue() const {
|
|
|
|
return hash_combine(Line, Column, Scope, InlinedAt);
|
2015-01-13 20:44:56 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2015-01-22 22:47:44 +00:00
|
|
|
/// \brief DenseMapInfo for GenericDebugNode.
|
2015-02-04 22:08:30 +00:00
|
|
|
template <> struct MDNodeKeyImpl<GenericDebugNode> : MDNodeOpsKey {
|
|
|
|
unsigned Tag;
|
|
|
|
StringRef Header;
|
|
|
|
MDNodeKeyImpl(unsigned Tag, StringRef Header, ArrayRef<Metadata *> DwarfOps)
|
|
|
|
: MDNodeOpsKey(DwarfOps), Tag(Tag), Header(Header) {}
|
|
|
|
MDNodeKeyImpl(const GenericDebugNode *N)
|
|
|
|
: MDNodeOpsKey(N, 1), Tag(N->getTag()), Header(N->getHeader()) {}
|
2015-01-20 00:01:43 +00:00
|
|
|
|
2015-02-05 00:51:35 +00:00
|
|
|
bool isKeyOf(const GenericDebugNode *RHS) const {
|
2015-02-04 22:08:30 +00:00
|
|
|
return Tag == RHS->getTag() && Header == RHS->getHeader() &&
|
|
|
|
compareOps(RHS, 1);
|
2015-01-20 00:01:43 +00:00
|
|
|
}
|
2015-02-04 22:08:30 +00:00
|
|
|
|
|
|
|
unsigned getHashValue() const { return hash_combine(getHash(), Tag, Header); }
|
|
|
|
|
|
|
|
static unsigned calculateHash(GenericDebugNode *N) {
|
|
|
|
return MDNodeOpsKey::calculateHash(N, 1);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2015-02-10 00:52:32 +00:00
|
|
|
template <> struct MDNodeKeyImpl<MDSubrange> {
|
|
|
|
int64_t Count;
|
|
|
|
int64_t Lo;
|
|
|
|
|
|
|
|
MDNodeKeyImpl(int64_t Count, int64_t Lo) : Count(Count), Lo(Lo) {}
|
|
|
|
MDNodeKeyImpl(const MDSubrange *N) : Count(N->getCount()), Lo(N->getLo()) {}
|
|
|
|
|
|
|
|
bool isKeyOf(const MDSubrange *RHS) const {
|
|
|
|
return Count == RHS->getCount() && Lo == RHS->getLo();
|
|
|
|
}
|
|
|
|
unsigned getHashValue() const { return hash_combine(Count, Lo); }
|
|
|
|
};
|
|
|
|
|
|
|
|
template <> struct MDNodeKeyImpl<MDEnumerator> {
|
|
|
|
int64_t Value;
|
|
|
|
StringRef Name;
|
|
|
|
|
|
|
|
MDNodeKeyImpl(int64_t Value, StringRef Name) : Value(Value), Name(Name) {}
|
|
|
|
MDNodeKeyImpl(const MDEnumerator *N)
|
|
|
|
: Value(N->getValue()), Name(N->getName()) {}
|
|
|
|
|
|
|
|
bool isKeyOf(const MDEnumerator *RHS) const {
|
|
|
|
return Value == RHS->getValue() && Name == RHS->getName();
|
|
|
|
}
|
|
|
|
unsigned getHashValue() const { return hash_combine(Value, Name); }
|
|
|
|
};
|
|
|
|
|
|
|
|
template <> struct MDNodeKeyImpl<MDBasicType> {
|
|
|
|
unsigned Tag;
|
|
|
|
StringRef Name;
|
|
|
|
unsigned SizeInBits;
|
|
|
|
unsigned AlignInBits;
|
|
|
|
unsigned Encoding;
|
|
|
|
|
|
|
|
MDNodeKeyImpl(unsigned Tag, StringRef Name, unsigned SizeInBits,
|
|
|
|
unsigned AlignInBits, unsigned Encoding)
|
|
|
|
: Tag(Tag), Name(Name), SizeInBits(SizeInBits), AlignInBits(AlignInBits),
|
|
|
|
Encoding(Encoding) {}
|
|
|
|
MDNodeKeyImpl(const MDBasicType *N)
|
|
|
|
: Tag(N->getTag()), Name(N->getName()), SizeInBits(N->getSizeInBits()),
|
|
|
|
AlignInBits(N->getAlignInBits()), Encoding(N->getEncoding()) {}
|
|
|
|
|
|
|
|
bool isKeyOf(const MDBasicType *RHS) const {
|
|
|
|
return Tag == RHS->getTag() && Name == RHS->getName() &&
|
|
|
|
SizeInBits == RHS->getSizeInBits() &&
|
|
|
|
AlignInBits == RHS->getAlignInBits() &&
|
|
|
|
Encoding == RHS->getEncoding();
|
|
|
|
}
|
|
|
|
unsigned getHashValue() const {
|
|
|
|
return hash_combine(Tag, Name, SizeInBits, AlignInBits, Encoding);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
template <> struct MDNodeKeyImpl<MDDerivedType> {
|
|
|
|
unsigned Tag;
|
|
|
|
StringRef Name;
|
|
|
|
Metadata *File;
|
|
|
|
unsigned Line;
|
|
|
|
Metadata *Scope;
|
|
|
|
Metadata *BaseType;
|
|
|
|
unsigned SizeInBits;
|
|
|
|
unsigned AlignInBits;
|
|
|
|
unsigned OffsetInBits;
|
|
|
|
unsigned Flags;
|
|
|
|
Metadata *ExtraData;
|
|
|
|
|
|
|
|
MDNodeKeyImpl(unsigned Tag, StringRef Name, Metadata *File, unsigned Line,
|
|
|
|
Metadata *Scope, Metadata *BaseType, unsigned SizeInBits,
|
|
|
|
unsigned AlignInBits, unsigned OffsetInBits, unsigned Flags,
|
|
|
|
Metadata *ExtraData)
|
|
|
|
: Tag(Tag), Name(Name), File(File), Line(Line), Scope(Scope),
|
|
|
|
BaseType(BaseType), SizeInBits(SizeInBits), AlignInBits(AlignInBits),
|
|
|
|
OffsetInBits(OffsetInBits), Flags(Flags), ExtraData(ExtraData) {}
|
|
|
|
MDNodeKeyImpl(const MDDerivedType *N)
|
|
|
|
: Tag(N->getTag()), Name(N->getName()), File(N->getFile()),
|
|
|
|
Line(N->getLine()), Scope(N->getScope()), BaseType(N->getBaseType()),
|
|
|
|
SizeInBits(N->getSizeInBits()), AlignInBits(N->getAlignInBits()),
|
|
|
|
OffsetInBits(N->getOffsetInBits()), Flags(N->getFlags()),
|
|
|
|
ExtraData(N->getExtraData()) {}
|
|
|
|
|
|
|
|
bool isKeyOf(const MDDerivedType *RHS) const {
|
|
|
|
return Tag == RHS->getTag() && Name == RHS->getName() &&
|
|
|
|
File == RHS->getFile() && Line == RHS->getLine() &&
|
|
|
|
Scope == RHS->getScope() && BaseType == RHS->getBaseType() &&
|
|
|
|
SizeInBits == RHS->getSizeInBits() &&
|
|
|
|
AlignInBits == RHS->getAlignInBits() &&
|
|
|
|
OffsetInBits == RHS->getOffsetInBits() && Flags == RHS->getFlags() &&
|
|
|
|
ExtraData == RHS->getExtraData();
|
|
|
|
}
|
|
|
|
unsigned getHashValue() const {
|
|
|
|
return hash_combine(Tag, Name, File, Line, Scope, BaseType, SizeInBits,
|
|
|
|
AlignInBits, OffsetInBits, Flags, ExtraData);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
template <> struct MDNodeKeyImpl<MDCompositeType> {
|
|
|
|
unsigned Tag;
|
|
|
|
StringRef Name;
|
|
|
|
Metadata *File;
|
|
|
|
unsigned Line;
|
|
|
|
Metadata *Scope;
|
|
|
|
Metadata *BaseType;
|
|
|
|
unsigned SizeInBits;
|
|
|
|
unsigned AlignInBits;
|
|
|
|
unsigned OffsetInBits;
|
|
|
|
unsigned Flags;
|
|
|
|
Metadata *Elements;
|
|
|
|
unsigned RuntimeLang;
|
|
|
|
Metadata *VTableHolder;
|
|
|
|
Metadata *TemplateParams;
|
|
|
|
StringRef Identifier;
|
|
|
|
|
|
|
|
MDNodeKeyImpl(unsigned Tag, StringRef Name, Metadata *File, unsigned Line,
|
|
|
|
Metadata *Scope, Metadata *BaseType, unsigned SizeInBits,
|
|
|
|
unsigned AlignInBits, unsigned OffsetInBits, unsigned Flags,
|
|
|
|
Metadata *Elements, unsigned RuntimeLang,
|
|
|
|
Metadata *VTableHolder, Metadata *TemplateParams,
|
|
|
|
StringRef Identifier)
|
|
|
|
: Tag(Tag), Name(Name), File(File), Line(Line), Scope(Scope),
|
|
|
|
BaseType(BaseType), SizeInBits(SizeInBits), AlignInBits(AlignInBits),
|
|
|
|
OffsetInBits(OffsetInBits), Flags(Flags), Elements(Elements),
|
|
|
|
RuntimeLang(RuntimeLang), VTableHolder(VTableHolder),
|
|
|
|
TemplateParams(TemplateParams), Identifier(Identifier) {}
|
|
|
|
MDNodeKeyImpl(const MDCompositeType *N)
|
|
|
|
: Tag(N->getTag()), Name(N->getName()), File(N->getFile()),
|
|
|
|
Line(N->getLine()), Scope(N->getScope()), BaseType(N->getBaseType()),
|
|
|
|
SizeInBits(N->getSizeInBits()), AlignInBits(N->getAlignInBits()),
|
|
|
|
OffsetInBits(N->getOffsetInBits()), Flags(N->getFlags()),
|
|
|
|
Elements(N->getElements()), RuntimeLang(N->getRuntimeLang()),
|
|
|
|
VTableHolder(N->getVTableHolder()),
|
|
|
|
TemplateParams(N->getTemplateParams()), Identifier(N->getIdentifier()) {
|
|
|
|
}
|
|
|
|
|
|
|
|
bool isKeyOf(const MDCompositeType *RHS) const {
|
|
|
|
return Tag == RHS->getTag() && Name == RHS->getName() &&
|
|
|
|
File == RHS->getFile() && Line == RHS->getLine() &&
|
|
|
|
Scope == RHS->getScope() && BaseType == RHS->getBaseType() &&
|
|
|
|
SizeInBits == RHS->getSizeInBits() &&
|
|
|
|
AlignInBits == RHS->getAlignInBits() &&
|
|
|
|
OffsetInBits == RHS->getOffsetInBits() && Flags == RHS->getFlags() &&
|
|
|
|
Elements == RHS->getElements() &&
|
|
|
|
RuntimeLang == RHS->getRuntimeLang() &&
|
|
|
|
VTableHolder == RHS->getVTableHolder() &&
|
|
|
|
TemplateParams == RHS->getTemplateParams() &&
|
|
|
|
Identifier == RHS->getIdentifier();
|
|
|
|
}
|
|
|
|
unsigned getHashValue() const {
|
|
|
|
return hash_combine(Tag, Name, File, Line, Scope, BaseType, SizeInBits,
|
|
|
|
AlignInBits, OffsetInBits, Flags, Elements, RuntimeLang,
|
|
|
|
VTableHolder, TemplateParams, Identifier);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
template <> struct MDNodeKeyImpl<MDSubroutineType> {
|
|
|
|
unsigned Flags;
|
|
|
|
Metadata *TypeArray;
|
|
|
|
|
|
|
|
MDNodeKeyImpl(int64_t Flags, Metadata *TypeArray)
|
|
|
|
: Flags(Flags), TypeArray(TypeArray) {}
|
|
|
|
MDNodeKeyImpl(const MDSubroutineType *N)
|
|
|
|
: Flags(N->getFlags()), TypeArray(N->getTypeArray()) {}
|
|
|
|
|
|
|
|
bool isKeyOf(const MDSubroutineType *RHS) const {
|
|
|
|
return Flags == RHS->getFlags() && TypeArray == RHS->getTypeArray();
|
|
|
|
}
|
|
|
|
unsigned getHashValue() const { return hash_combine(Flags, TypeArray); }
|
|
|
|
};
|
|
|
|
|
|
|
|
template <> struct MDNodeKeyImpl<MDFile> {
|
|
|
|
StringRef Filename;
|
|
|
|
StringRef Directory;
|
|
|
|
|
|
|
|
MDNodeKeyImpl(StringRef Filename, StringRef Directory)
|
|
|
|
: Filename(Filename), Directory(Directory) {}
|
|
|
|
MDNodeKeyImpl(const MDFile *N)
|
|
|
|
: Filename(N->getFilename()), Directory(N->getDirectory()) {}
|
|
|
|
|
|
|
|
bool isKeyOf(const MDFile *RHS) const {
|
|
|
|
return Filename == RHS->getFilename() && Directory == RHS->getDirectory();
|
|
|
|
}
|
|
|
|
unsigned getHashValue() const { return hash_combine(Filename, Directory); }
|
|
|
|
};
|
|
|
|
|
|
|
|
template <> struct MDNodeKeyImpl<MDCompileUnit> {
|
|
|
|
unsigned SourceLanguage;
|
|
|
|
Metadata *File;
|
|
|
|
StringRef Producer;
|
|
|
|
bool IsOptimized;
|
|
|
|
StringRef Flags;
|
|
|
|
unsigned RuntimeVersion;
|
|
|
|
StringRef SplitDebugFilename;
|
|
|
|
unsigned EmissionKind;
|
|
|
|
Metadata *EnumTypes;
|
|
|
|
Metadata *RetainedTypes;
|
|
|
|
Metadata *Subprograms;
|
|
|
|
Metadata *GlobalVariables;
|
|
|
|
Metadata *ImportedEntities;
|
|
|
|
|
|
|
|
MDNodeKeyImpl(unsigned SourceLanguage, Metadata *File, StringRef Producer,
|
|
|
|
bool IsOptimized, StringRef Flags, unsigned RuntimeVersion,
|
|
|
|
StringRef SplitDebugFilename, unsigned EmissionKind,
|
|
|
|
Metadata *EnumTypes, Metadata *RetainedTypes,
|
|
|
|
Metadata *Subprograms, Metadata *GlobalVariables,
|
|
|
|
Metadata *ImportedEntities)
|
|
|
|
: SourceLanguage(SourceLanguage), File(File), Producer(Producer),
|
|
|
|
IsOptimized(IsOptimized), Flags(Flags), RuntimeVersion(RuntimeVersion),
|
|
|
|
SplitDebugFilename(SplitDebugFilename), EmissionKind(EmissionKind),
|
|
|
|
EnumTypes(EnumTypes), RetainedTypes(RetainedTypes),
|
|
|
|
Subprograms(Subprograms), GlobalVariables(GlobalVariables),
|
|
|
|
ImportedEntities(ImportedEntities) {}
|
|
|
|
MDNodeKeyImpl(const MDCompileUnit *N)
|
|
|
|
: SourceLanguage(N->getSourceLanguage()), File(N->getFile()),
|
|
|
|
Producer(N->getProducer()), IsOptimized(N->isOptimized()),
|
|
|
|
Flags(N->getFlags()), RuntimeVersion(N->getRuntimeVersion()),
|
|
|
|
SplitDebugFilename(N->getSplitDebugFilename()),
|
|
|
|
EmissionKind(N->getEmissionKind()), EnumTypes(N->getEnumTypes()),
|
|
|
|
RetainedTypes(N->getRetainedTypes()), Subprograms(N->getSubprograms()),
|
|
|
|
GlobalVariables(N->getGlobalVariables()),
|
|
|
|
ImportedEntities(N->getImportedEntities()) {}
|
|
|
|
|
|
|
|
bool isKeyOf(const MDCompileUnit *RHS) const {
|
|
|
|
return SourceLanguage == RHS->getSourceLanguage() &&
|
|
|
|
File == RHS->getFile() && Producer == RHS->getProducer() &&
|
|
|
|
IsOptimized == RHS->isOptimized() && Flags == RHS->getFlags() &&
|
|
|
|
RuntimeVersion == RHS->getRuntimeVersion() &&
|
|
|
|
SplitDebugFilename == RHS->getSplitDebugFilename() &&
|
|
|
|
EmissionKind == RHS->getEmissionKind() &&
|
|
|
|
EnumTypes == RHS->getEnumTypes() &&
|
|
|
|
RetainedTypes == RHS->getRetainedTypes() &&
|
|
|
|
Subprograms == RHS->getSubprograms() &&
|
|
|
|
GlobalVariables == RHS->getGlobalVariables() &&
|
|
|
|
ImportedEntities == RHS->getImportedEntities();
|
|
|
|
}
|
|
|
|
unsigned getHashValue() const {
|
|
|
|
return hash_combine(SourceLanguage, File, Producer, IsOptimized, Flags,
|
|
|
|
RuntimeVersion, SplitDebugFilename, EmissionKind,
|
|
|
|
EnumTypes, RetainedTypes, Subprograms, GlobalVariables,
|
|
|
|
ImportedEntities);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
template <> struct MDNodeKeyImpl<MDSubprogram> {
|
|
|
|
Metadata *Scope;
|
|
|
|
StringRef Name;
|
|
|
|
StringRef LinkageName;
|
|
|
|
Metadata *File;
|
|
|
|
unsigned Line;
|
|
|
|
Metadata *Type;
|
|
|
|
bool IsLocalToUnit;
|
|
|
|
bool IsDefinition;
|
|
|
|
unsigned ScopeLine;
|
|
|
|
Metadata *ContainingType;
|
|
|
|
unsigned Virtuality;
|
|
|
|
unsigned VirtualIndex;
|
|
|
|
unsigned Flags;
|
|
|
|
bool IsOptimized;
|
|
|
|
Metadata *Function;
|
|
|
|
Metadata *TemplateParams;
|
|
|
|
Metadata *Declaration;
|
|
|
|
Metadata *Variables;
|
|
|
|
|
|
|
|
MDNodeKeyImpl(Metadata *Scope, StringRef Name, StringRef LinkageName,
|
|
|
|
Metadata *File, unsigned Line, Metadata *Type,
|
|
|
|
bool IsLocalToUnit, bool IsDefinition, unsigned ScopeLine,
|
|
|
|
Metadata *ContainingType, unsigned Virtuality,
|
|
|
|
unsigned VirtualIndex, unsigned Flags, bool IsOptimized,
|
|
|
|
Metadata *Function, Metadata *TemplateParams,
|
|
|
|
Metadata *Declaration, Metadata *Variables)
|
|
|
|
: Scope(Scope), Name(Name), LinkageName(LinkageName), File(File),
|
|
|
|
Line(Line), Type(Type), IsLocalToUnit(IsLocalToUnit),
|
|
|
|
IsDefinition(IsDefinition), ScopeLine(ScopeLine),
|
|
|
|
ContainingType(ContainingType), Virtuality(Virtuality),
|
|
|
|
VirtualIndex(VirtualIndex), Flags(Flags), IsOptimized(IsOptimized),
|
|
|
|
Function(Function), TemplateParams(TemplateParams),
|
|
|
|
Declaration(Declaration), Variables(Variables) {}
|
|
|
|
MDNodeKeyImpl(const MDSubprogram *N)
|
|
|
|
: Scope(N->getScope()), Name(N->getName()),
|
|
|
|
LinkageName(N->getLinkageName()), File(N->getFile()),
|
|
|
|
Line(N->getLine()), Type(N->getType()),
|
|
|
|
IsLocalToUnit(N->isLocalToUnit()), IsDefinition(N->isDefinition()),
|
|
|
|
ScopeLine(N->getScopeLine()), ContainingType(N->getContainingType()),
|
|
|
|
Virtuality(N->getVirtuality()), VirtualIndex(N->getVirtualIndex()),
|
|
|
|
Flags(N->getFlags()), IsOptimized(N->isOptimized()),
|
|
|
|
Function(N->getFunction()), TemplateParams(N->getTemplateParams()),
|
|
|
|
Declaration(N->getDeclaration()), Variables(N->getVariables()) {}
|
|
|
|
|
|
|
|
bool isKeyOf(const MDSubprogram *RHS) const {
|
|
|
|
return Scope == RHS->getScope() && Name == RHS->getName() &&
|
|
|
|
LinkageName == RHS->getLinkageName() && File == RHS->getFile() &&
|
|
|
|
Line == RHS->getLine() && Type == RHS->getType() &&
|
|
|
|
IsLocalToUnit == RHS->isLocalToUnit() &&
|
|
|
|
IsDefinition == RHS->isDefinition() &&
|
|
|
|
ScopeLine == RHS->getScopeLine() &&
|
|
|
|
ContainingType == RHS->getContainingType() &&
|
|
|
|
Virtuality == RHS->getVirtuality() &&
|
|
|
|
VirtualIndex == RHS->getVirtualIndex() && Flags == RHS->getFlags() &&
|
|
|
|
IsOptimized == RHS->isOptimized() &&
|
|
|
|
Function == RHS->getFunction() &&
|
|
|
|
TemplateParams == RHS->getTemplateParams() &&
|
|
|
|
Declaration == RHS->getDeclaration() &&
|
|
|
|
Variables == RHS->getVariables();
|
|
|
|
}
|
|
|
|
unsigned getHashValue() const {
|
|
|
|
return hash_combine(Scope, Name, LinkageName, File, Line, Type,
|
|
|
|
IsLocalToUnit, IsDefinition, ScopeLine, ContainingType,
|
|
|
|
Virtuality, VirtualIndex, Flags, IsOptimized, Function,
|
|
|
|
TemplateParams, Declaration, Variables);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
template <> struct MDNodeKeyImpl<MDLexicalBlock> {
|
|
|
|
Metadata *Scope;
|
|
|
|
Metadata *File;
|
|
|
|
unsigned Line;
|
|
|
|
unsigned Column;
|
|
|
|
|
|
|
|
MDNodeKeyImpl(Metadata *Scope, Metadata *File, unsigned Line, unsigned Column)
|
|
|
|
: Scope(Scope), File(File), Line(Line), Column(Column) {}
|
|
|
|
MDNodeKeyImpl(const MDLexicalBlock *N)
|
|
|
|
: Scope(N->getScope()), File(N->getFile()), Line(N->getLine()),
|
|
|
|
Column(N->getColumn()) {}
|
|
|
|
|
|
|
|
bool isKeyOf(const MDLexicalBlock *RHS) const {
|
|
|
|
return Scope == RHS->getScope() && File == RHS->getFile() &&
|
|
|
|
Line == RHS->getLine() && Column == RHS->getColumn();
|
|
|
|
}
|
|
|
|
unsigned getHashValue() const {
|
|
|
|
return hash_combine(Scope, File, Line, Column);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
template <> struct MDNodeKeyImpl<MDLexicalBlockFile> {
|
|
|
|
Metadata *Scope;
|
|
|
|
Metadata *File;
|
|
|
|
unsigned Discriminator;
|
|
|
|
|
|
|
|
MDNodeKeyImpl(Metadata *Scope, Metadata *File, unsigned Discriminator)
|
|
|
|
: Scope(Scope), File(File), Discriminator(Discriminator) {}
|
|
|
|
MDNodeKeyImpl(const MDLexicalBlockFile *N)
|
|
|
|
: Scope(N->getScope()), File(N->getFile()),
|
|
|
|
Discriminator(N->getDiscriminator()) {}
|
|
|
|
|
|
|
|
bool isKeyOf(const MDLexicalBlockFile *RHS) const {
|
|
|
|
return Scope == RHS->getScope() && File == RHS->getFile() &&
|
|
|
|
Discriminator == RHS->getDiscriminator();
|
|
|
|
}
|
|
|
|
unsigned getHashValue() const {
|
|
|
|
return hash_combine(Scope, File, Discriminator);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
template <> struct MDNodeKeyImpl<MDNamespace> {
|
|
|
|
Metadata *Scope;
|
|
|
|
Metadata *File;
|
|
|
|
StringRef Name;
|
|
|
|
unsigned Line;
|
|
|
|
|
|
|
|
MDNodeKeyImpl(Metadata *Scope, Metadata *File, StringRef Name, unsigned Line)
|
|
|
|
: Scope(Scope), File(File), Name(Name), Line(Line) {}
|
|
|
|
MDNodeKeyImpl(const MDNamespace *N)
|
|
|
|
: Scope(N->getScope()), File(N->getFile()), Name(N->getName()),
|
|
|
|
Line(N->getLine()) {}
|
|
|
|
|
|
|
|
bool isKeyOf(const MDNamespace *RHS) const {
|
|
|
|
return Scope == RHS->getScope() && File == RHS->getFile() &&
|
|
|
|
Name == RHS->getName() && Line == RHS->getLine();
|
|
|
|
}
|
|
|
|
unsigned getHashValue() const {
|
|
|
|
return hash_combine(Scope, File, Name, Line);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
template <> struct MDNodeKeyImpl<MDTemplateTypeParameter> {
|
|
|
|
StringRef Name;
|
|
|
|
Metadata *Type;
|
|
|
|
|
2015-02-19 00:37:21 +00:00
|
|
|
MDNodeKeyImpl(StringRef Name, Metadata *Type) : Name(Name), Type(Type) {}
|
2015-02-10 00:52:32 +00:00
|
|
|
MDNodeKeyImpl(const MDTemplateTypeParameter *N)
|
2015-02-19 00:37:21 +00:00
|
|
|
: Name(N->getName()), Type(N->getType()) {}
|
2015-02-10 00:52:32 +00:00
|
|
|
|
|
|
|
bool isKeyOf(const MDTemplateTypeParameter *RHS) const {
|
2015-02-19 00:37:21 +00:00
|
|
|
return Name == RHS->getName() && Type == RHS->getType();
|
2015-02-10 00:52:32 +00:00
|
|
|
}
|
2015-02-19 00:37:21 +00:00
|
|
|
unsigned getHashValue() const { return hash_combine(Name, Type); }
|
2015-02-10 00:52:32 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
template <> struct MDNodeKeyImpl<MDTemplateValueParameter> {
|
|
|
|
unsigned Tag;
|
|
|
|
StringRef Name;
|
|
|
|
Metadata *Type;
|
|
|
|
Metadata *Value;
|
|
|
|
|
2015-02-19 00:37:21 +00:00
|
|
|
MDNodeKeyImpl(unsigned Tag, StringRef Name, Metadata *Type, Metadata *Value)
|
|
|
|
: Tag(Tag), Name(Name), Type(Type), Value(Value) {}
|
2015-02-10 00:52:32 +00:00
|
|
|
MDNodeKeyImpl(const MDTemplateValueParameter *N)
|
2015-02-19 00:37:21 +00:00
|
|
|
: Tag(N->getTag()), Name(N->getName()), Type(N->getType()),
|
|
|
|
Value(N->getValue()) {}
|
2015-02-10 00:52:32 +00:00
|
|
|
|
|
|
|
bool isKeyOf(const MDTemplateValueParameter *RHS) const {
|
2015-02-19 00:37:21 +00:00
|
|
|
return Tag == RHS->getTag() && Name == RHS->getName() &&
|
|
|
|
Type == RHS->getType() && Value == RHS->getValue();
|
2015-02-10 00:52:32 +00:00
|
|
|
}
|
2015-02-19 00:37:21 +00:00
|
|
|
unsigned getHashValue() const { return hash_combine(Tag, Name, Type, Value); }
|
2015-02-10 00:52:32 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
template <> struct MDNodeKeyImpl<MDGlobalVariable> {
|
|
|
|
Metadata *Scope;
|
|
|
|
StringRef Name;
|
|
|
|
StringRef LinkageName;
|
|
|
|
Metadata *File;
|
|
|
|
unsigned Line;
|
|
|
|
Metadata *Type;
|
|
|
|
bool IsLocalToUnit;
|
|
|
|
bool IsDefinition;
|
|
|
|
Metadata *Variable;
|
|
|
|
Metadata *StaticDataMemberDeclaration;
|
|
|
|
|
|
|
|
MDNodeKeyImpl(Metadata *Scope, StringRef Name, StringRef LinkageName,
|
|
|
|
Metadata *File, unsigned Line, Metadata *Type,
|
|
|
|
bool IsLocalToUnit, bool IsDefinition, Metadata *Variable,
|
|
|
|
Metadata *StaticDataMemberDeclaration)
|
|
|
|
: Scope(Scope), Name(Name), LinkageName(LinkageName), File(File),
|
|
|
|
Line(Line), Type(Type), IsLocalToUnit(IsLocalToUnit),
|
|
|
|
IsDefinition(IsDefinition), Variable(Variable),
|
|
|
|
StaticDataMemberDeclaration(StaticDataMemberDeclaration) {}
|
|
|
|
MDNodeKeyImpl(const MDGlobalVariable *N)
|
|
|
|
: Scope(N->getScope()), Name(N->getName()),
|
|
|
|
LinkageName(N->getLinkageName()), File(N->getFile()),
|
|
|
|
Line(N->getLine()), Type(N->getType()),
|
|
|
|
IsLocalToUnit(N->isLocalToUnit()), IsDefinition(N->isDefinition()),
|
|
|
|
Variable(N->getVariable()),
|
|
|
|
StaticDataMemberDeclaration(N->getStaticDataMemberDeclaration()) {}
|
|
|
|
|
|
|
|
bool isKeyOf(const MDGlobalVariable *RHS) const {
|
|
|
|
return Scope == RHS->getScope() && Name == RHS->getName() &&
|
|
|
|
LinkageName == RHS->getLinkageName() && File == RHS->getFile() &&
|
|
|
|
Line == RHS->getLine() && Type == RHS->getType() &&
|
|
|
|
IsLocalToUnit == RHS->isLocalToUnit() &&
|
|
|
|
IsDefinition == RHS->isDefinition() &&
|
|
|
|
Variable == RHS->getVariable() &&
|
|
|
|
StaticDataMemberDeclaration == RHS->getStaticDataMemberDeclaration();
|
|
|
|
}
|
|
|
|
unsigned getHashValue() const {
|
|
|
|
return hash_combine(Scope, Name, LinkageName, File, Line, Type,
|
|
|
|
IsLocalToUnit, IsDefinition, Variable,
|
|
|
|
StaticDataMemberDeclaration);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
template <> struct MDNodeKeyImpl<MDLocalVariable> {
|
|
|
|
unsigned Tag;
|
|
|
|
Metadata *Scope;
|
|
|
|
StringRef Name;
|
|
|
|
Metadata *File;
|
|
|
|
unsigned Line;
|
|
|
|
Metadata *Type;
|
|
|
|
unsigned Arg;
|
|
|
|
unsigned Flags;
|
|
|
|
Metadata *InlinedAt;
|
|
|
|
|
|
|
|
MDNodeKeyImpl(unsigned Tag, Metadata *Scope, StringRef Name, Metadata *File,
|
|
|
|
unsigned Line, Metadata *Type, unsigned Arg, unsigned Flags,
|
|
|
|
Metadata *InlinedAt)
|
|
|
|
: Tag(Tag), Scope(Scope), Name(Name), File(File), Line(Line), Type(Type),
|
|
|
|
Arg(Arg), Flags(Flags), InlinedAt(InlinedAt) {}
|
|
|
|
MDNodeKeyImpl(const MDLocalVariable *N)
|
|
|
|
: Tag(N->getTag()), Scope(N->getScope()), Name(N->getName()),
|
|
|
|
File(N->getFile()), Line(N->getLine()), Type(N->getType()),
|
|
|
|
Arg(N->getArg()), Flags(N->getFlags()), InlinedAt(N->getInlinedAt()) {}
|
|
|
|
|
|
|
|
bool isKeyOf(const MDLocalVariable *RHS) const {
|
|
|
|
return Tag == RHS->getTag() && Scope == RHS->getScope() &&
|
|
|
|
Name == RHS->getName() && File == RHS->getFile() &&
|
|
|
|
Line == RHS->getLine() && Type == RHS->getType() &&
|
|
|
|
Arg == RHS->getArg() && Flags == RHS->getFlags() &&
|
|
|
|
InlinedAt == RHS->getInlinedAt();
|
|
|
|
}
|
|
|
|
unsigned getHashValue() const {
|
|
|
|
return hash_combine(Tag, Scope, Name, File, Line, Type, Arg, Flags,
|
|
|
|
InlinedAt);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
template <> struct MDNodeKeyImpl<MDExpression> {
|
|
|
|
ArrayRef<uint64_t> Elements;
|
|
|
|
|
|
|
|
MDNodeKeyImpl(ArrayRef<uint64_t> Elements) : Elements(Elements) {}
|
|
|
|
MDNodeKeyImpl(const MDExpression *N) : Elements(N->getElements()) {}
|
|
|
|
|
|
|
|
bool isKeyOf(const MDExpression *RHS) const {
|
|
|
|
return Elements == RHS->getElements();
|
|
|
|
}
|
|
|
|
unsigned getHashValue() const {
|
|
|
|
return hash_combine_range(Elements.begin(), Elements.end());
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
template <> struct MDNodeKeyImpl<MDObjCProperty> {
|
|
|
|
StringRef Name;
|
|
|
|
Metadata *File;
|
|
|
|
unsigned Line;
|
|
|
|
StringRef GetterName;
|
|
|
|
StringRef SetterName;
|
|
|
|
unsigned Attributes;
|
|
|
|
Metadata *Type;
|
|
|
|
|
|
|
|
MDNodeKeyImpl(StringRef Name, Metadata *File, unsigned Line,
|
|
|
|
StringRef GetterName, StringRef SetterName, unsigned Attributes,
|
|
|
|
Metadata *Type)
|
|
|
|
: Name(Name), File(File), Line(Line), GetterName(GetterName),
|
|
|
|
SetterName(SetterName), Attributes(Attributes), Type(Type) {}
|
|
|
|
MDNodeKeyImpl(const MDObjCProperty *N)
|
|
|
|
: Name(N->getName()), File(N->getFile()), Line(N->getLine()),
|
|
|
|
GetterName(N->getGetterName()), SetterName(N->getSetterName()),
|
|
|
|
Attributes(N->getAttributes()), Type(N->getType()) {}
|
|
|
|
|
|
|
|
bool isKeyOf(const MDObjCProperty *RHS) const {
|
|
|
|
return Name == RHS->getName() && File == RHS->getFile() &&
|
|
|
|
Line == RHS->getLine() && GetterName == RHS->getGetterName() &&
|
|
|
|
SetterName == RHS->getSetterName() &&
|
|
|
|
Attributes == RHS->getAttributes() && Type == RHS->getType();
|
|
|
|
}
|
|
|
|
unsigned getHashValue() const {
|
|
|
|
return hash_combine(Name, File, Line, GetterName, SetterName, Attributes,
|
|
|
|
Type);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
template <> struct MDNodeKeyImpl<MDImportedEntity> {
|
|
|
|
unsigned Tag;
|
|
|
|
Metadata *Scope;
|
|
|
|
Metadata *Entity;
|
|
|
|
unsigned Line;
|
|
|
|
StringRef Name;
|
|
|
|
|
|
|
|
MDNodeKeyImpl(unsigned Tag, Metadata *Scope, Metadata *Entity, unsigned Line,
|
|
|
|
StringRef Name)
|
|
|
|
: Tag(Tag), Scope(Scope), Entity(Entity), Line(Line), Name(Name) {}
|
|
|
|
MDNodeKeyImpl(const MDImportedEntity *N)
|
|
|
|
: Tag(N->getTag()), Scope(N->getScope()), Entity(N->getEntity()),
|
|
|
|
Line(N->getLine()), Name(N->getName()) {}
|
|
|
|
|
|
|
|
bool isKeyOf(const MDImportedEntity *RHS) const {
|
|
|
|
return Tag == RHS->getTag() && Scope == RHS->getScope() &&
|
|
|
|
Entity == RHS->getEntity() && Line == RHS->getLine() &&
|
|
|
|
Name == RHS->getName();
|
|
|
|
}
|
|
|
|
unsigned getHashValue() const {
|
|
|
|
return hash_combine(Tag, Scope, Entity, Line, Name);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2015-02-04 22:08:30 +00:00
|
|
|
/// \brief DenseMapInfo for MDNode subclasses.
|
|
|
|
template <class NodeTy> struct MDNodeInfo {
|
|
|
|
typedef MDNodeKeyImpl<NodeTy> KeyTy;
|
|
|
|
static inline NodeTy *getEmptyKey() {
|
|
|
|
return DenseMapInfo<NodeTy *>::getEmptyKey();
|
2015-01-20 00:01:43 +00:00
|
|
|
}
|
2015-02-04 22:08:30 +00:00
|
|
|
static inline NodeTy *getTombstoneKey() {
|
|
|
|
return DenseMapInfo<NodeTy *>::getTombstoneKey();
|
2015-01-20 00:01:43 +00:00
|
|
|
}
|
2015-02-04 22:08:30 +00:00
|
|
|
static unsigned getHashValue(const KeyTy &Key) { return Key.getHashValue(); }
|
|
|
|
static unsigned getHashValue(const NodeTy *N) {
|
|
|
|
return KeyTy(N).getHashValue();
|
2015-01-20 00:01:43 +00:00
|
|
|
}
|
2015-02-04 22:08:30 +00:00
|
|
|
static bool isEqual(const KeyTy &LHS, const NodeTy *RHS) {
|
|
|
|
if (RHS == getEmptyKey() || RHS == getTombstoneKey())
|
|
|
|
return false;
|
2015-02-05 00:51:35 +00:00
|
|
|
return LHS.isKeyOf(RHS);
|
2015-01-20 00:01:43 +00:00
|
|
|
}
|
2015-02-04 22:08:30 +00:00
|
|
|
static bool isEqual(const NodeTy *LHS, const NodeTy *RHS) {
|
2015-01-20 00:01:43 +00:00
|
|
|
return LHS == RHS;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2015-02-04 22:08:30 +00:00
|
|
|
#define HANDLE_MDNODE_LEAF(CLASS) typedef MDNodeInfo<CLASS> CLASS##Info;
|
|
|
|
#include "llvm/IR/Metadata.def"
|
|
|
|
|
2013-09-11 18:05:11 +00:00
|
|
|
class LLVMContextImpl {
|
2009-08-11 17:45:13 +00:00
|
|
|
public:
|
2010-09-08 18:03:32 +00:00
|
|
|
/// OwnedModules - The set of modules instantiated in this context, and which
|
|
|
|
/// will be automatically deleted if this context is deleted.
|
|
|
|
SmallPtrSet<Module*, 4> OwnedModules;
|
|
|
|
|
2013-02-11 05:37:07 +00:00
|
|
|
LLVMContext::InlineAsmDiagHandlerTy InlineAsmDiagHandler;
|
|
|
|
void *InlineAsmDiagContext;
|
2013-12-17 17:47:22 +00:00
|
|
|
|
|
|
|
LLVMContext::DiagnosticHandlerTy DiagnosticHandler;
|
|
|
|
void *DiagnosticContext;
|
2014-10-01 18:36:03 +00:00
|
|
|
bool RespectDiagnosticFilters;
|
2013-12-17 17:47:22 +00:00
|
|
|
|
2014-05-16 02:33:15 +00:00
|
|
|
LLVMContext::YieldCallbackTy YieldCallback;
|
|
|
|
void *YieldOpaqueHandle;
|
|
|
|
|
2014-12-06 13:12:56 +00:00
|
|
|
typedef DenseMap<APInt, ConstantInt *, DenseMapAPIntKeyInfo> IntMapTy;
|
2009-07-16 18:04:31 +00:00
|
|
|
IntMapTy IntConstants;
|
2014-12-06 05:57:06 +00:00
|
|
|
|
2014-12-06 13:12:56 +00:00
|
|
|
typedef DenseMap<APFloat, ConstantFP *, DenseMapAPFloatKeyInfo> FPMapTy;
|
2009-07-16 19:05:41 +00:00
|
|
|
FPMapTy FPConstants;
|
2012-09-26 21:07:29 +00:00
|
|
|
|
2012-12-20 01:36:59 +00:00
|
|
|
FoldingSet<AttributeImpl> AttrsSet;
|
2012-12-19 22:42:22 +00:00
|
|
|
FoldingSet<AttributeSetImpl> AttrsLists;
|
2013-01-24 00:06:56 +00:00
|
|
|
FoldingSet<AttributeSetNode> AttrsSetNodes;
|
2012-11-20 05:09:20 +00:00
|
|
|
|
2014-11-14 01:17:09 +00:00
|
|
|
StringMap<MDString> MDStringCache;
|
IR: Split Metadata from Value
Split `Metadata` away from the `Value` class hierarchy, as part of
PR21532. Assembly and bitcode changes are in the wings, but this is the
bulk of the change for the IR C++ API.
I have a follow-up patch prepared for `clang`. If this breaks other
sub-projects, I apologize in advance :(. Help me compile it on Darwin
I'll try to fix it. FWIW, the errors should be easy to fix, so it may
be simpler to just fix it yourself.
This breaks the build for all metadata-related code that's out-of-tree.
Rest assured the transition is mechanical and the compiler should catch
almost all of the problems.
Here's a quick guide for updating your code:
- `Metadata` is the root of a class hierarchy with three main classes:
`MDNode`, `MDString`, and `ValueAsMetadata`. It is distinct from
the `Value` class hierarchy. It is typeless -- i.e., instances do
*not* have a `Type`.
- `MDNode`'s operands are all `Metadata *` (instead of `Value *`).
- `TrackingVH<MDNode>` and `WeakVH` referring to metadata can be
replaced with `TrackingMDNodeRef` and `TrackingMDRef`, respectively.
If you're referring solely to resolved `MDNode`s -- post graph
construction -- just use `MDNode*`.
- `MDNode` (and the rest of `Metadata`) have only limited support for
`replaceAllUsesWith()`.
As long as an `MDNode` is pointing at a forward declaration -- the
result of `MDNode::getTemporary()` -- it maintains a side map of its
uses and can RAUW itself. Once the forward declarations are fully
resolved RAUW support is dropped on the ground. This means that
uniquing collisions on changing operands cause nodes to become
"distinct". (This already happened fairly commonly, whenever an
operand went to null.)
If you're constructing complex (non self-reference) `MDNode` cycles,
you need to call `MDNode::resolveCycles()` on each node (or on a
top-level node that somehow references all of the nodes). Also,
don't do that. Metadata cycles (and the RAUW machinery needed to
construct them) are expensive.
- An `MDNode` can only refer to a `Constant` through a bridge called
`ConstantAsMetadata` (one of the subclasses of `ValueAsMetadata`).
As a side effect, accessing an operand of an `MDNode` that is known
to be, e.g., `ConstantInt`, takes three steps: first, cast from
`Metadata` to `ConstantAsMetadata`; second, extract the `Constant`;
third, cast down to `ConstantInt`.
The eventual goal is to introduce `MDInt`/`MDFloat`/etc. and have
metadata schema owners transition away from using `Constant`s when
the type isn't important (and they don't care about referring to
`GlobalValue`s).
In the meantime, I've added transitional API to the `mdconst`
namespace that matches semantics with the old code, in order to
avoid adding the error-prone three-step equivalent to every call
site. If your old code was:
MDNode *N = foo();
bar(isa <ConstantInt>(N->getOperand(0)));
baz(cast <ConstantInt>(N->getOperand(1)));
bak(cast_or_null <ConstantInt>(N->getOperand(2)));
bat(dyn_cast <ConstantInt>(N->getOperand(3)));
bay(dyn_cast_or_null<ConstantInt>(N->getOperand(4)));
you can trivially match its semantics with:
MDNode *N = foo();
bar(mdconst::hasa <ConstantInt>(N->getOperand(0)));
baz(mdconst::extract <ConstantInt>(N->getOperand(1)));
bak(mdconst::extract_or_null <ConstantInt>(N->getOperand(2)));
bat(mdconst::dyn_extract <ConstantInt>(N->getOperand(3)));
bay(mdconst::dyn_extract_or_null<ConstantInt>(N->getOperand(4)));
and when you transition your metadata schema to `MDInt`:
MDNode *N = foo();
bar(isa <MDInt>(N->getOperand(0)));
baz(cast <MDInt>(N->getOperand(1)));
bak(cast_or_null <MDInt>(N->getOperand(2)));
bat(dyn_cast <MDInt>(N->getOperand(3)));
bay(dyn_cast_or_null<MDInt>(N->getOperand(4)));
- A `CallInst` -- specifically, intrinsic instructions -- can refer to
metadata through a bridge called `MetadataAsValue`. This is a
subclass of `Value` where `getType()->isMetadataTy()`.
`MetadataAsValue` is the *only* class that can legally refer to a
`LocalAsMetadata`, which is a bridged form of non-`Constant` values
like `Argument` and `Instruction`. It can also refer to any other
`Metadata` subclass.
(I'll break all your testcases in a follow-up commit, when I propagate
this change to assembly.)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@223802 91177308-0d34-0410-b5e6-96231b3b80d8
2014-12-09 18:38:53 +00:00
|
|
|
DenseMap<Value *, ValueAsMetadata *> ValuesAsMetadata;
|
|
|
|
DenseMap<Metadata *, MetadataAsValue *> MetadataAsValues;
|
2012-09-26 21:07:29 +00:00
|
|
|
|
2015-02-04 21:46:12 +00:00
|
|
|
#define HANDLE_MDNODE_LEAF(CLASS) DenseSet<CLASS *, CLASS##Info> CLASS##s;
|
|
|
|
#include "llvm/IR/Metadata.def"
|
2012-09-26 21:07:29 +00:00
|
|
|
|
2010-03-13 01:26:15 +00:00
|
|
|
// MDNodes may be uniqued or not uniqued. When they're not uniqued, they
|
|
|
|
// aren't in the MDNodeSet, but they're still shared between objects, so no
|
|
|
|
// one object can destroy them. This set allows us to at least destroy them
|
|
|
|
// on Context destruction.
|
2015-01-19 23:13:14 +00:00
|
|
|
SmallPtrSet<MDNode *, 1> DistinctMDNodes;
|
2014-11-18 00:37:17 +00:00
|
|
|
|
2014-11-25 02:26:22 +00:00
|
|
|
DenseMap<Type*, ConstantAggregateZero*> CAZConstants;
|
2009-08-10 18:16:08 +00:00
|
|
|
|
2014-08-19 16:39:58 +00:00
|
|
|
typedef ConstantUniqueMap<ConstantArray> ArrayConstantsTy;
|
2009-07-24 23:12:02 +00:00
|
|
|
ArrayConstantsTy ArrayConstants;
|
2009-07-21 20:13:12 +00:00
|
|
|
|
2014-08-19 16:39:58 +00:00
|
|
|
typedef ConstantUniqueMap<ConstantStruct> StructConstantsTy;
|
2009-07-24 23:12:02 +00:00
|
|
|
StructConstantsTy StructConstants;
|
2009-07-23 23:25:33 +00:00
|
|
|
|
2014-08-19 16:39:58 +00:00
|
|
|
typedef ConstantUniqueMap<ConstantVector> VectorConstantsTy;
|
2009-07-24 23:12:02 +00:00
|
|
|
VectorConstantsTy VectorConstants;
|
2009-07-24 00:36:24 +00:00
|
|
|
|
2012-01-23 15:20:12 +00:00
|
|
|
DenseMap<PointerType*, ConstantPointerNull*> CPNConstants;
|
|
|
|
|
|
|
|
DenseMap<Type*, UndefValue*> UVConstants;
|
2009-07-31 22:45:43 +00:00
|
|
|
|
2012-01-23 22:57:10 +00:00
|
|
|
StringMap<ConstantDataSequential*> CDSConstants;
|
|
|
|
|
2014-01-19 02:13:50 +00:00
|
|
|
DenseMap<std::pair<const Function *, const BasicBlock *>, BlockAddress *>
|
|
|
|
BlockAddresses;
|
2014-08-19 16:39:58 +00:00
|
|
|
ConstantUniqueMap<ConstantExpr> ExprConstants;
|
|
|
|
|
|
|
|
ConstantUniqueMap<InlineAsm> InlineAsms;
|
2014-08-19 01:02:18 +00:00
|
|
|
|
2009-07-21 02:47:59 +00:00
|
|
|
ConstantInt *TheTrueVal;
|
|
|
|
ConstantInt *TheFalseVal;
|
IR: Split Metadata from Value
Split `Metadata` away from the `Value` class hierarchy, as part of
PR21532. Assembly and bitcode changes are in the wings, but this is the
bulk of the change for the IR C++ API.
I have a follow-up patch prepared for `clang`. If this breaks other
sub-projects, I apologize in advance :(. Help me compile it on Darwin
I'll try to fix it. FWIW, the errors should be easy to fix, so it may
be simpler to just fix it yourself.
This breaks the build for all metadata-related code that's out-of-tree.
Rest assured the transition is mechanical and the compiler should catch
almost all of the problems.
Here's a quick guide for updating your code:
- `Metadata` is the root of a class hierarchy with three main classes:
`MDNode`, `MDString`, and `ValueAsMetadata`. It is distinct from
the `Value` class hierarchy. It is typeless -- i.e., instances do
*not* have a `Type`.
- `MDNode`'s operands are all `Metadata *` (instead of `Value *`).
- `TrackingVH<MDNode>` and `WeakVH` referring to metadata can be
replaced with `TrackingMDNodeRef` and `TrackingMDRef`, respectively.
If you're referring solely to resolved `MDNode`s -- post graph
construction -- just use `MDNode*`.
- `MDNode` (and the rest of `Metadata`) have only limited support for
`replaceAllUsesWith()`.
As long as an `MDNode` is pointing at a forward declaration -- the
result of `MDNode::getTemporary()` -- it maintains a side map of its
uses and can RAUW itself. Once the forward declarations are fully
resolved RAUW support is dropped on the ground. This means that
uniquing collisions on changing operands cause nodes to become
"distinct". (This already happened fairly commonly, whenever an
operand went to null.)
If you're constructing complex (non self-reference) `MDNode` cycles,
you need to call `MDNode::resolveCycles()` on each node (or on a
top-level node that somehow references all of the nodes). Also,
don't do that. Metadata cycles (and the RAUW machinery needed to
construct them) are expensive.
- An `MDNode` can only refer to a `Constant` through a bridge called
`ConstantAsMetadata` (one of the subclasses of `ValueAsMetadata`).
As a side effect, accessing an operand of an `MDNode` that is known
to be, e.g., `ConstantInt`, takes three steps: first, cast from
`Metadata` to `ConstantAsMetadata`; second, extract the `Constant`;
third, cast down to `ConstantInt`.
The eventual goal is to introduce `MDInt`/`MDFloat`/etc. and have
metadata schema owners transition away from using `Constant`s when
the type isn't important (and they don't care about referring to
`GlobalValue`s).
In the meantime, I've added transitional API to the `mdconst`
namespace that matches semantics with the old code, in order to
avoid adding the error-prone three-step equivalent to every call
site. If your old code was:
MDNode *N = foo();
bar(isa <ConstantInt>(N->getOperand(0)));
baz(cast <ConstantInt>(N->getOperand(1)));
bak(cast_or_null <ConstantInt>(N->getOperand(2)));
bat(dyn_cast <ConstantInt>(N->getOperand(3)));
bay(dyn_cast_or_null<ConstantInt>(N->getOperand(4)));
you can trivially match its semantics with:
MDNode *N = foo();
bar(mdconst::hasa <ConstantInt>(N->getOperand(0)));
baz(mdconst::extract <ConstantInt>(N->getOperand(1)));
bak(mdconst::extract_or_null <ConstantInt>(N->getOperand(2)));
bat(mdconst::dyn_extract <ConstantInt>(N->getOperand(3)));
bay(mdconst::dyn_extract_or_null<ConstantInt>(N->getOperand(4)));
and when you transition your metadata schema to `MDInt`:
MDNode *N = foo();
bar(isa <MDInt>(N->getOperand(0)));
baz(cast <MDInt>(N->getOperand(1)));
bak(cast_or_null <MDInt>(N->getOperand(2)));
bat(dyn_cast <MDInt>(N->getOperand(3)));
bay(dyn_cast_or_null<MDInt>(N->getOperand(4)));
- A `CallInst` -- specifically, intrinsic instructions -- can refer to
metadata through a bridge called `MetadataAsValue`. This is a
subclass of `Value` where `getType()->isMetadataTy()`.
`MetadataAsValue` is the *only* class that can legally refer to a
`LocalAsMetadata`, which is a bridged form of non-`Constant` values
like `Argument` and `Instruction`. It can also refer to any other
`Metadata` subclass.
(I'll break all your testcases in a follow-up commit, when I propagate
this change to assembly.)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@223802 91177308-0d34-0410-b5e6-96231b3b80d8
2014-12-09 18:38:53 +00:00
|
|
|
|
2009-08-25 16:00:35 +00:00
|
|
|
// Basic type instances.
|
2011-12-17 00:04:22 +00:00
|
|
|
Type VoidTy, LabelTy, HalfTy, FloatTy, DoubleTy, MetadataTy;
|
Land the long talked about "type system rewrite" patch. This
patch brings numerous advantages to LLVM. One way to look at it
is through diffstat:
109 files changed, 3005 insertions(+), 5906 deletions(-)
Removing almost 3K lines of code is a good thing. Other advantages
include:
1. Value::getType() is a simple load that can be CSE'd, not a mutating
union-find operation.
2. Types a uniqued and never move once created, defining away PATypeHolder.
3. Structs can be "named" now, and their name is part of the identity that
uniques them. This means that the compiler doesn't merge them structurally
which makes the IR much less confusing.
4. Now that there is no way to get a cycle in a type graph without a named
struct type, "upreferences" go away.
5. Type refinement is completely gone, which should make LTO much MUCH faster
in some common cases with C++ code.
6. Types are now generally immutable, so we can use "Type *" instead
"const Type *" everywhere.
Downsides of this patch are that it removes some functions from the C API,
so people using those will have to upgrade to (not yet added) new API.
"LLVM 3.0" is the right time to do this.
There are still some cleanups pending after this, this patch is large enough
as-is.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@134829 91177308-0d34-0410-b5e6-96231b3b80d8
2011-07-09 17:41:24 +00:00
|
|
|
Type X86_FP80Ty, FP128Ty, PPC_FP128Ty, X86_MMXTy;
|
|
|
|
IntegerType Int1Ty, Int8Ty, Int16Ty, Int32Ty, Int64Ty;
|
2010-02-11 06:41:30 +00:00
|
|
|
|
2011-07-15 05:49:15 +00:00
|
|
|
|
|
|
|
/// TypeAllocator - All dynamically allocated types are allocated from this.
|
|
|
|
/// They live forever until the context is torn down.
|
|
|
|
BumpPtrAllocator TypeAllocator;
|
|
|
|
|
Land the long talked about "type system rewrite" patch. This
patch brings numerous advantages to LLVM. One way to look at it
is through diffstat:
109 files changed, 3005 insertions(+), 5906 deletions(-)
Removing almost 3K lines of code is a good thing. Other advantages
include:
1. Value::getType() is a simple load that can be CSE'd, not a mutating
union-find operation.
2. Types a uniqued and never move once created, defining away PATypeHolder.
3. Structs can be "named" now, and their name is part of the identity that
uniques them. This means that the compiler doesn't merge them structurally
which makes the IR much less confusing.
4. Now that there is no way to get a cycle in a type graph without a named
struct type, "upreferences" go away.
5. Type refinement is completely gone, which should make LTO much MUCH faster
in some common cases with C++ code.
6. Types are now generally immutable, so we can use "Type *" instead
"const Type *" everywhere.
Downsides of this patch are that it removes some functions from the C API,
so people using those will have to upgrade to (not yet added) new API.
"LLVM 3.0" is the right time to do this.
There are still some cleanups pending after this, this patch is large enough
as-is.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@134829 91177308-0d34-0410-b5e6-96231b3b80d8
2011-07-09 17:41:24 +00:00
|
|
|
DenseMap<unsigned, IntegerType*> IntegerTypes;
|
2014-12-06 19:22:54 +00:00
|
|
|
|
|
|
|
typedef DenseSet<FunctionType *, FunctionTypeKeyInfo> FunctionTypeSet;
|
|
|
|
FunctionTypeSet FunctionTypes;
|
|
|
|
typedef DenseSet<StructType *, AnonStructTypeKeyInfo> StructTypeSet;
|
|
|
|
StructTypeSet AnonStructTypes;
|
Land the long talked about "type system rewrite" patch. This
patch brings numerous advantages to LLVM. One way to look at it
is through diffstat:
109 files changed, 3005 insertions(+), 5906 deletions(-)
Removing almost 3K lines of code is a good thing. Other advantages
include:
1. Value::getType() is a simple load that can be CSE'd, not a mutating
union-find operation.
2. Types a uniqued and never move once created, defining away PATypeHolder.
3. Structs can be "named" now, and their name is part of the identity that
uniques them. This means that the compiler doesn't merge them structurally
which makes the IR much less confusing.
4. Now that there is no way to get a cycle in a type graph without a named
struct type, "upreferences" go away.
5. Type refinement is completely gone, which should make LTO much MUCH faster
in some common cases with C++ code.
6. Types are now generally immutable, so we can use "Type *" instead
"const Type *" everywhere.
Downsides of this patch are that it removes some functions from the C API,
so people using those will have to upgrade to (not yet added) new API.
"LLVM 3.0" is the right time to do this.
There are still some cleanups pending after this, this patch is large enough
as-is.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@134829 91177308-0d34-0410-b5e6-96231b3b80d8
2011-07-09 17:41:24 +00:00
|
|
|
StringMap<StructType*> NamedStructTypes;
|
|
|
|
unsigned NamedStructTypesUniqueID;
|
|
|
|
|
|
|
|
DenseMap<std::pair<Type *, uint64_t>, ArrayType*> ArrayTypes;
|
|
|
|
DenseMap<std::pair<Type *, unsigned>, VectorType*> VectorTypes;
|
|
|
|
DenseMap<Type*, PointerType*> PointerTypes; // Pointers in AddrSpace = 0
|
|
|
|
DenseMap<std::pair<Type*, unsigned>, PointerType*> ASPointerTypes;
|
2010-02-11 06:41:30 +00:00
|
|
|
|
2009-12-17 19:55:06 +00:00
|
|
|
|
2009-08-18 18:28:58 +00:00
|
|
|
/// ValueHandles - This map keeps track of all of the value handles that are
|
|
|
|
/// watching a Value*. The Value::HasValueHandle bit is used to know
|
2013-03-01 18:48:54 +00:00
|
|
|
/// whether or not a value has an entry in this map.
|
2009-08-18 18:28:58 +00:00
|
|
|
typedef DenseMap<Value*, ValueHandleBase*> ValueHandlesTy;
|
|
|
|
ValueHandlesTy ValueHandles;
|
|
|
|
|
2009-12-29 09:01:33 +00:00
|
|
|
/// CustomMDKindNames - Map to hold the metadata string to ID mapping.
|
|
|
|
StringMap<unsigned> CustomMDKindNames;
|
IR: Split Metadata from Value
Split `Metadata` away from the `Value` class hierarchy, as part of
PR21532. Assembly and bitcode changes are in the wings, but this is the
bulk of the change for the IR C++ API.
I have a follow-up patch prepared for `clang`. If this breaks other
sub-projects, I apologize in advance :(. Help me compile it on Darwin
I'll try to fix it. FWIW, the errors should be easy to fix, so it may
be simpler to just fix it yourself.
This breaks the build for all metadata-related code that's out-of-tree.
Rest assured the transition is mechanical and the compiler should catch
almost all of the problems.
Here's a quick guide for updating your code:
- `Metadata` is the root of a class hierarchy with three main classes:
`MDNode`, `MDString`, and `ValueAsMetadata`. It is distinct from
the `Value` class hierarchy. It is typeless -- i.e., instances do
*not* have a `Type`.
- `MDNode`'s operands are all `Metadata *` (instead of `Value *`).
- `TrackingVH<MDNode>` and `WeakVH` referring to metadata can be
replaced with `TrackingMDNodeRef` and `TrackingMDRef`, respectively.
If you're referring solely to resolved `MDNode`s -- post graph
construction -- just use `MDNode*`.
- `MDNode` (and the rest of `Metadata`) have only limited support for
`replaceAllUsesWith()`.
As long as an `MDNode` is pointing at a forward declaration -- the
result of `MDNode::getTemporary()` -- it maintains a side map of its
uses and can RAUW itself. Once the forward declarations are fully
resolved RAUW support is dropped on the ground. This means that
uniquing collisions on changing operands cause nodes to become
"distinct". (This already happened fairly commonly, whenever an
operand went to null.)
If you're constructing complex (non self-reference) `MDNode` cycles,
you need to call `MDNode::resolveCycles()` on each node (or on a
top-level node that somehow references all of the nodes). Also,
don't do that. Metadata cycles (and the RAUW machinery needed to
construct them) are expensive.
- An `MDNode` can only refer to a `Constant` through a bridge called
`ConstantAsMetadata` (one of the subclasses of `ValueAsMetadata`).
As a side effect, accessing an operand of an `MDNode` that is known
to be, e.g., `ConstantInt`, takes three steps: first, cast from
`Metadata` to `ConstantAsMetadata`; second, extract the `Constant`;
third, cast down to `ConstantInt`.
The eventual goal is to introduce `MDInt`/`MDFloat`/etc. and have
metadata schema owners transition away from using `Constant`s when
the type isn't important (and they don't care about referring to
`GlobalValue`s).
In the meantime, I've added transitional API to the `mdconst`
namespace that matches semantics with the old code, in order to
avoid adding the error-prone three-step equivalent to every call
site. If your old code was:
MDNode *N = foo();
bar(isa <ConstantInt>(N->getOperand(0)));
baz(cast <ConstantInt>(N->getOperand(1)));
bak(cast_or_null <ConstantInt>(N->getOperand(2)));
bat(dyn_cast <ConstantInt>(N->getOperand(3)));
bay(dyn_cast_or_null<ConstantInt>(N->getOperand(4)));
you can trivially match its semantics with:
MDNode *N = foo();
bar(mdconst::hasa <ConstantInt>(N->getOperand(0)));
baz(mdconst::extract <ConstantInt>(N->getOperand(1)));
bak(mdconst::extract_or_null <ConstantInt>(N->getOperand(2)));
bat(mdconst::dyn_extract <ConstantInt>(N->getOperand(3)));
bay(mdconst::dyn_extract_or_null<ConstantInt>(N->getOperand(4)));
and when you transition your metadata schema to `MDInt`:
MDNode *N = foo();
bar(isa <MDInt>(N->getOperand(0)));
baz(cast <MDInt>(N->getOperand(1)));
bak(cast_or_null <MDInt>(N->getOperand(2)));
bat(dyn_cast <MDInt>(N->getOperand(3)));
bay(dyn_cast_or_null<MDInt>(N->getOperand(4)));
- A `CallInst` -- specifically, intrinsic instructions -- can refer to
metadata through a bridge called `MetadataAsValue`. This is a
subclass of `Value` where `getType()->isMetadataTy()`.
`MetadataAsValue` is the *only* class that can legally refer to a
`LocalAsMetadata`, which is a bridged form of non-`Constant` values
like `Argument` and `Instruction`. It can also refer to any other
`Metadata` subclass.
(I'll break all your testcases in a follow-up commit, when I propagate
this change to assembly.)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@223802 91177308-0d34-0410-b5e6-96231b3b80d8
2014-12-09 18:38:53 +00:00
|
|
|
|
|
|
|
typedef std::pair<unsigned, TrackingMDNodeRef> MDPairTy;
|
2009-12-29 09:01:33 +00:00
|
|
|
typedef SmallVector<MDPairTy, 2> MDMapTy;
|
|
|
|
|
|
|
|
/// MetadataStore - Collection of per-instruction metadata used in this
|
|
|
|
/// context.
|
|
|
|
DenseMap<const Instruction *, MDMapTy> MetadataStore;
|
|
|
|
|
2014-03-03 20:06:11 +00:00
|
|
|
/// DiscriminatorTable - This table maps file:line locations to an
|
|
|
|
/// integer representing the next DWARF path discriminator to assign to
|
|
|
|
/// instructions in different blocks at the same location.
|
|
|
|
DenseMap<std::pair<const char *, unsigned>, unsigned> DiscriminatorTable;
|
|
|
|
|
2013-03-01 18:48:54 +00:00
|
|
|
/// IntrinsicIDCache - Cache of intrinsic name (string) to numeric ID mappings
|
|
|
|
/// requested in this context
|
|
|
|
typedef DenseMap<const Function*, unsigned> IntrinsicIDCacheTy;
|
|
|
|
IntrinsicIDCacheTy IntrinsicIDCache;
|
|
|
|
|
2013-09-16 01:08:15 +00:00
|
|
|
/// \brief Mapping from a function to its prefix data, which is stored as the
|
|
|
|
/// operand of an unparented ReturnInst so that the prefix data has a Use.
|
|
|
|
typedef DenseMap<const Function *, ReturnInst *> PrefixDataMapTy;
|
|
|
|
PrefixDataMapTy PrefixDataMap;
|
|
|
|
|
2014-12-03 02:08:38 +00:00
|
|
|
/// \brief Mapping from a function to its prologue data, which is stored as
|
|
|
|
/// the operand of an unparented ReturnInst so that the prologue data has a
|
|
|
|
/// Use.
|
|
|
|
typedef DenseMap<const Function *, ReturnInst *> PrologueDataMapTy;
|
|
|
|
PrologueDataMapTy PrologueDataMap;
|
|
|
|
|
2010-04-01 00:37:44 +00:00
|
|
|
int getOrAddScopeRecordIdxEntry(MDNode *N, int ExistingIdx);
|
|
|
|
int getOrAddScopeInlinedAtIdxEntry(MDNode *Scope, MDNode *IA,int ExistingIdx);
|
2015-01-16 20:07:33 +00:00
|
|
|
|
2010-03-21 21:17:34 +00:00
|
|
|
LLVMContextImpl(LLVMContext &C);
|
|
|
|
~LLVMContextImpl();
|
2015-01-20 19:24:59 +00:00
|
|
|
|
|
|
|
/// Destroy the ConstantArrays if they are not used.
|
|
|
|
void dropTriviallyDeadConstantArrays();
|
2009-06-30 00:48:55 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2009-06-30 17:06:46 +00:00
|
|
|
#endif
|