2017-06-20 06:05:08 +08:00
|
|
|
//===- LLVMContextImpl.h - The LLVMContextImpl opaque class -----*- C++ -*-===//
|
2009-06-30 08:48:55 +08:00
|
|
|
//
|
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
|
2009-06-30 08:48:55 +08:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
2009-07-01 01:06:46 +08:00
|
|
|
//
|
2018-07-31 03:41:25 +08:00
|
|
|
// This file declares LLVMContextImpl, the opaque implementation
|
2009-07-01 01:06:46 +08:00
|
|
|
// of LLVMContext.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
2009-06-30 08:48:55 +08:00
|
|
|
|
2014-08-14 00:26:38 +08:00
|
|
|
#ifndef LLVM_LIB_IR_LLVMCONTEXTIMPL_H
|
|
|
|
#define LLVM_LIB_IR_LLVMCONTEXTIMPL_H
|
2009-06-30 08:48:55 +08:00
|
|
|
|
2012-12-20 09:36:59 +08:00
|
|
|
#include "AttributeImpl.h"
|
2009-08-05 06:41:48 +08:00
|
|
|
#include "ConstantsContext.h"
|
2009-07-17 03:05:41 +08:00
|
|
|
#include "llvm/ADT/APFloat.h"
|
2009-07-17 02:04:31 +08:00
|
|
|
#include "llvm/ADT/APInt.h"
|
2011-06-22 16:50:06 +08:00
|
|
|
#include "llvm/ADT/ArrayRef.h"
|
2009-07-17 02:04:31 +08:00
|
|
|
#include "llvm/ADT/DenseMap.h"
|
2017-06-20 06:05:08 +08:00
|
|
|
#include "llvm/ADT/DenseMapInfo.h"
|
2014-11-18 07:28:21 +08:00
|
|
|
#include "llvm/ADT/DenseSet.h"
|
2009-07-17 07:44:30 +08:00
|
|
|
#include "llvm/ADT/FoldingSet.h"
|
2012-12-04 15:12:27 +08:00
|
|
|
#include "llvm/ADT/Hashing.h"
|
2017-06-20 06:05:08 +08:00
|
|
|
#include "llvm/ADT/Optional.h"
|
|
|
|
#include "llvm/ADT/STLExtras.h"
|
2009-12-18 03:55:06 +08:00
|
|
|
#include "llvm/ADT/SmallPtrSet.h"
|
2017-06-20 06:05:08 +08:00
|
|
|
#include "llvm/ADT/SmallVector.h"
|
2009-07-17 06:11:26 +08:00
|
|
|
#include "llvm/ADT/StringMap.h"
|
2017-06-07 11:48:56 +08:00
|
|
|
#include "llvm/BinaryFormat/Dwarf.h"
|
2013-01-02 19:36:10 +08:00
|
|
|
#include "llvm/IR/Constants.h"
|
2015-02-03 02:53:21 +08:00
|
|
|
#include "llvm/IR/DebugInfoMetadata.h"
|
2013-01-02 19:36:10 +08:00
|
|
|
#include "llvm/IR/DerivedTypes.h"
|
|
|
|
#include "llvm/IR/LLVMContext.h"
|
2019-10-29 05:53:31 +08:00
|
|
|
#include "llvm/IR/LLVMRemarkStreamer.h"
|
2013-01-02 19:36:10 +08:00
|
|
|
#include "llvm/IR/Metadata.h"
|
2017-06-20 06:05:08 +08:00
|
|
|
#include "llvm/IR/TrackingMDRef.h"
|
|
|
|
#include "llvm/Support/Allocator.h"
|
|
|
|
#include "llvm/Support/Casting.h"
|
2019-05-29 11:28:51 +08:00
|
|
|
#include "llvm/Support/StringSaver.h"
|
Output optimization remarks in YAML
(Re-committed after moving the template specialization under the yaml
namespace. GCC was complaining about this.)
This allows various presentation of this data using an external tool.
This was first recommended here[1].
As an example, consider this module:
1 int foo();
2 int bar();
3
4 int baz() {
5 return foo() + bar();
6 }
The inliner generates these missed-optimization remarks today (the
hotness information is pulled from PGO):
remark: /tmp/s.c:5:10: foo will not be inlined into baz (hotness: 30)
remark: /tmp/s.c:5:18: bar will not be inlined into baz (hotness: 30)
Now with -pass-remarks-output=<yaml-file>, we generate this YAML file:
--- !Missed
Pass: inline
Name: NotInlined
DebugLoc: { File: /tmp/s.c, Line: 5, Column: 10 }
Function: baz
Hotness: 30
Args:
- Callee: foo
- String: will not be inlined into
- Caller: baz
...
--- !Missed
Pass: inline
Name: NotInlined
DebugLoc: { File: /tmp/s.c, Line: 5, Column: 18 }
Function: baz
Hotness: 30
Args:
- Callee: bar
- String: will not be inlined into
- Caller: baz
...
This is a summary of the high-level decisions:
* There is a new streaming interface to emit optimization remarks.
E.g. for the inliner remark above:
ORE.emit(DiagnosticInfoOptimizationRemarkMissed(
DEBUG_TYPE, "NotInlined", &I)
<< NV("Callee", Callee) << " will not be inlined into "
<< NV("Caller", CS.getCaller()) << setIsVerbose());
NV stands for named value and allows the YAML client to process a remark
using its name (NotInlined) and the named arguments (Callee and Caller)
without parsing the text of the message.
Subsequent patches will update ORE users to use the new streaming API.
* I am using YAML I/O for writing the YAML file. YAML I/O requires you
to specify reading and writing at once but reading is highly non-trivial
for some of the more complex LLVM types. Since it's not clear that we
(ever) want to use LLVM to parse this YAML file, the code supports and
asserts that we're writing only.
On the other hand, I did experiment that the class hierarchy starting at
DiagnosticInfoOptimizationBase can be mapped back from YAML generated
here (see D24479).
* The YAML stream is stored in the LLVM context.
* In the example, we can probably further specify the IR value used,
i.e. print "Function" rather than "Value".
* As before hotness is computed in the analysis pass instead of
DiganosticInfo. This avoids the layering problem since BFI is in
Analysis while DiagnosticInfo is in IR.
[1] https://reviews.llvm.org/D19678#419445
Differential Revision: https://reviews.llvm.org/D24587
llvm-svn: 282539
2016-09-28 04:55:07 +08:00
|
|
|
#include "llvm/Support/YAMLTraits.h"
|
2017-06-20 06:05:08 +08:00
|
|
|
#include <algorithm>
|
|
|
|
#include <cassert>
|
|
|
|
#include <cstddef>
|
|
|
|
#include <cstdint>
|
|
|
|
#include <memory>
|
|
|
|
#include <string>
|
|
|
|
#include <utility>
|
2016-04-20 07:59:13 +08:00
|
|
|
#include <vector>
|
2009-07-22 04:13:12 +08:00
|
|
|
|
2009-06-30 08:48:55 +08:00
|
|
|
namespace llvm {
|
2009-07-25 07:12:02 +08:00
|
|
|
|
2020-04-24 20:07:02 +08:00
|
|
|
class StringRef;
|
2009-07-17 02:04:31 +08:00
|
|
|
class Type;
|
2009-07-17 07:44:30 +08:00
|
|
|
class Value;
|
2017-06-20 06:05:08 +08:00
|
|
|
class ValueHandleBase;
|
2009-07-17 02:04:31 +08:00
|
|
|
|
2020-08-03 22:31:13 +08:00
|
|
|
using DenseMapAPIntKeyInfo = DenseMapInfo<APInt>;
|
2009-07-17 02:04:31 +08:00
|
|
|
|
2013-09-12 02:05:11 +08:00
|
|
|
struct DenseMapAPFloatKeyInfo {
|
2016-12-14 19:57:17 +08:00
|
|
|
static inline APFloat getEmptyKey() { return APFloat(APFloat::Bogus(), 1); }
|
|
|
|
static inline APFloat getTombstoneKey() { return APFloat(APFloat::Bogus(), 2); }
|
2017-06-20 06:05:08 +08:00
|
|
|
|
2014-12-06 21:12:56 +08:00
|
|
|
static unsigned getHashValue(const APFloat &Key) {
|
2012-03-04 20:02:57 +08:00
|
|
|
return static_cast<unsigned>(hash_value(Key));
|
2009-07-17 03:05:41 +08:00
|
|
|
}
|
2017-06-20 06:05:08 +08:00
|
|
|
|
2014-12-06 21:12:56 +08:00
|
|
|
static bool isEqual(const APFloat &LHS, const APFloat &RHS) {
|
|
|
|
return LHS.bitwiseIsEqual(RHS);
|
|
|
|
}
|
2009-07-17 03:05:41 +08:00
|
|
|
};
|
|
|
|
|
2013-09-12 02:05:11 +08:00
|
|
|
struct AnonStructTypeKeyInfo {
|
2012-02-23 17:17:40 +08:00
|
|
|
struct KeyTy {
|
|
|
|
ArrayRef<Type*> ETypes;
|
|
|
|
bool isPacked;
|
2017-06-20 06:05:08 +08:00
|
|
|
|
2012-02-23 17:17:40 +08:00
|
|
|
KeyTy(const ArrayRef<Type*>& E, bool P) :
|
|
|
|
ETypes(E), isPacked(P) {}
|
2017-06-20 06:05:08 +08:00
|
|
|
|
2014-11-22 02:53:05 +08:00
|
|
|
KeyTy(const StructType *ST)
|
|
|
|
: ETypes(ST->elements()), isPacked(ST->isPacked()) {}
|
2017-06-20 06:05:08 +08:00
|
|
|
|
2012-02-23 17:17:40 +08: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);
|
|
|
|
}
|
|
|
|
};
|
2017-06-20 06:05:08 +08:00
|
|
|
|
2012-02-23 17:17:40 +08:00
|
|
|
static inline StructType* getEmptyKey() {
|
|
|
|
return DenseMapInfo<StructType*>::getEmptyKey();
|
|
|
|
}
|
2017-06-20 06:05:08 +08:00
|
|
|
|
2012-02-23 17:17:40 +08:00
|
|
|
static inline StructType* getTombstoneKey() {
|
|
|
|
return DenseMapInfo<StructType*>::getTombstoneKey();
|
|
|
|
}
|
2017-06-20 06:05:08 +08:00
|
|
|
|
2012-02-23 17:17:40 +08:00
|
|
|
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.
llvm-svn: 151822
2012-03-02 02:55:25 +08:00
|
|
|
return hash_combine(hash_combine_range(Key.ETypes.begin(),
|
|
|
|
Key.ETypes.end()),
|
|
|
|
Key.isPacked);
|
2012-02-23 17:17:40 +08:00
|
|
|
}
|
2017-06-20 06:05:08 +08:00
|
|
|
|
2012-02-23 17:17:40 +08:00
|
|
|
static unsigned getHashValue(const StructType *ST) {
|
|
|
|
return getHashValue(KeyTy(ST));
|
|
|
|
}
|
2017-06-20 06:05:08 +08:00
|
|
|
|
2012-02-23 17:17:40 +08:00
|
|
|
static bool isEqual(const KeyTy& LHS, const StructType *RHS) {
|
|
|
|
if (RHS == getEmptyKey() || RHS == getTombstoneKey())
|
|
|
|
return false;
|
|
|
|
return LHS == KeyTy(RHS);
|
|
|
|
}
|
2017-06-20 06:05:08 +08:00
|
|
|
|
2012-02-23 17:17:40 +08:00
|
|
|
static bool isEqual(const StructType *LHS, const StructType *RHS) {
|
|
|
|
return LHS == RHS;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2013-09-12 02:05:11 +08:00
|
|
|
struct FunctionTypeKeyInfo {
|
2012-02-23 17:17:40 +08:00
|
|
|
struct KeyTy {
|
|
|
|
const Type *ReturnType;
|
|
|
|
ArrayRef<Type*> Params;
|
|
|
|
bool isVarArg;
|
2017-06-20 06:05:08 +08:00
|
|
|
|
2012-02-23 17:17:40 +08:00
|
|
|
KeyTy(const Type* R, const ArrayRef<Type*>& P, bool V) :
|
|
|
|
ReturnType(R), Params(P), isVarArg(V) {}
|
2014-11-22 03:03:35 +08:00
|
|
|
KeyTy(const FunctionType *FT)
|
|
|
|
: ReturnType(FT->getReturnType()), Params(FT->params()),
|
|
|
|
isVarArg(FT->isVarArg()) {}
|
2017-06-20 06:05:08 +08:00
|
|
|
|
2012-02-23 17:17:40 +08: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);
|
|
|
|
}
|
|
|
|
};
|
2017-06-20 06:05:08 +08:00
|
|
|
|
2012-02-23 17:17:40 +08:00
|
|
|
static inline FunctionType* getEmptyKey() {
|
|
|
|
return DenseMapInfo<FunctionType*>::getEmptyKey();
|
|
|
|
}
|
2017-06-20 06:05:08 +08:00
|
|
|
|
2012-02-23 17:17:40 +08:00
|
|
|
static inline FunctionType* getTombstoneKey() {
|
|
|
|
return DenseMapInfo<FunctionType*>::getTombstoneKey();
|
|
|
|
}
|
2017-06-20 06:05:08 +08:00
|
|
|
|
2012-02-23 17:17:40 +08:00
|
|
|
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.
llvm-svn: 151822
2012-03-02 02:55:25 +08:00
|
|
|
return hash_combine(Key.ReturnType,
|
|
|
|
hash_combine_range(Key.Params.begin(),
|
|
|
|
Key.Params.end()),
|
|
|
|
Key.isVarArg);
|
2012-02-23 17:17:40 +08:00
|
|
|
}
|
2017-06-20 06:05:08 +08:00
|
|
|
|
2012-02-23 17:17:40 +08:00
|
|
|
static unsigned getHashValue(const FunctionType *FT) {
|
|
|
|
return getHashValue(KeyTy(FT));
|
|
|
|
}
|
2017-06-20 06:05:08 +08:00
|
|
|
|
2012-02-23 17:17:40 +08:00
|
|
|
static bool isEqual(const KeyTy& LHS, const FunctionType *RHS) {
|
|
|
|
if (RHS == getEmptyKey() || RHS == getTombstoneKey())
|
|
|
|
return false;
|
|
|
|
return LHS == KeyTy(RHS);
|
|
|
|
}
|
2017-06-20 06:05:08 +08:00
|
|
|
|
2012-02-23 17:17:40 +08:00
|
|
|
static bool isEqual(const FunctionType *LHS, const FunctionType *RHS) {
|
|
|
|
return LHS == RHS;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2018-05-01 23:54:18 +08:00
|
|
|
/// Structure for hashing arbitrary MDNode operands.
|
2015-01-20 06:53:18 +08:00
|
|
|
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-05 06:08:30 +08:00
|
|
|
MDNodeOpsKey(const NodeTy *N, unsigned Offset = 0)
|
2015-01-20 08:01:43 +08:00
|
|
|
: Ops(N->op_begin() + Offset, N->op_end()), Hash(N->getHash()) {}
|
2015-01-20 06:53:18 +08:00
|
|
|
|
2015-01-20 08:01:43 +08:00
|
|
|
template <class NodeTy>
|
|
|
|
bool compareOps(const NodeTy *RHS, unsigned Offset = 0) const {
|
2015-01-20 06:53:18 +08:00
|
|
|
if (getHash() != RHS->getHash())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
assert((RawOps.empty() || Ops.empty()) && "Two sets of operands?");
|
2015-01-20 08:01:43 +08:00
|
|
|
return RawOps.empty() ? compareOps(Ops, RHS, Offset)
|
|
|
|
: compareOps(RawOps, RHS, Offset);
|
2015-01-20 06:53:18 +08:00
|
|
|
}
|
|
|
|
|
2015-01-20 08:01:43 +08:00
|
|
|
static unsigned calculateHash(MDNode *N, unsigned Offset = 0);
|
2015-01-20 06:53:18 +08:00
|
|
|
|
|
|
|
private:
|
|
|
|
template <class T>
|
2015-01-20 08:01:43 +08:00
|
|
|
static bool compareOps(ArrayRef<T> Ops, const MDNode *RHS, unsigned Offset) {
|
|
|
|
if (Ops.size() != RHS->getNumOperands() - Offset)
|
2015-01-20 06:53:18 +08:00
|
|
|
return false;
|
2015-01-20 08:01:43 +08:00
|
|
|
return std::equal(Ops.begin(), Ops.end(), RHS->op_begin() + Offset);
|
2015-01-20 06:53:18 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static unsigned calculateHash(ArrayRef<Metadata *> Ops);
|
|
|
|
|
|
|
|
public:
|
|
|
|
unsigned getHash() const { return Hash; }
|
|
|
|
};
|
|
|
|
|
2015-02-05 06:08:30 +08:00
|
|
|
template <class NodeTy> struct MDNodeKeyImpl;
|
|
|
|
|
2016-04-17 07:42:04 +08:00
|
|
|
/// Configuration point for MDNodeInfo::isEqual().
|
|
|
|
template <class NodeTy> struct MDNodeSubsetEqualImpl {
|
2017-06-20 06:05:08 +08:00
|
|
|
using KeyTy = MDNodeKeyImpl<NodeTy>;
|
|
|
|
|
2016-04-17 07:42:04 +08:00
|
|
|
static bool isSubsetEqual(const KeyTy &LHS, const NodeTy *RHS) {
|
|
|
|
return false;
|
|
|
|
}
|
2017-06-20 06:05:08 +08:00
|
|
|
|
2016-04-17 07:42:04 +08:00
|
|
|
static bool isSubsetEqual(const NodeTy *LHS, const NodeTy *RHS) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2018-05-01 23:54:18 +08:00
|
|
|
/// DenseMapInfo for MDTuple.
|
2014-11-18 07:28:21 +08:00
|
|
|
///
|
|
|
|
/// Note that we don't need the is-function-local bit, since that's implicit in
|
|
|
|
/// the operands.
|
2015-02-05 06:08:30 +08:00
|
|
|
template <> struct MDNodeKeyImpl<MDTuple> : MDNodeOpsKey {
|
|
|
|
MDNodeKeyImpl(ArrayRef<Metadata *> Ops) : MDNodeOpsKey(Ops) {}
|
|
|
|
MDNodeKeyImpl(const MDTuple *N) : MDNodeOpsKey(N) {}
|
2012-04-11 22:06:54 +08:00
|
|
|
|
2015-02-05 08:51:35 +08:00
|
|
|
bool isKeyOf(const MDTuple *RHS) const { return compareOps(RHS); }
|
2015-01-20 06:53:18 +08:00
|
|
|
|
2015-02-05 06:08:30 +08:00
|
|
|
unsigned getHashValue() const { return getHash(); }
|
|
|
|
|
|
|
|
static unsigned calculateHash(MDTuple *N) {
|
|
|
|
return MDNodeOpsKey::calculateHash(N);
|
2012-04-11 22:06:54 +08:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2018-05-01 23:54:18 +08:00
|
|
|
/// DenseMapInfo for DILocation.
|
2015-04-30 00:38:44 +08:00
|
|
|
template <> struct MDNodeKeyImpl<DILocation> {
|
2015-02-05 06:08:30 +08:00
|
|
|
unsigned Line;
|
|
|
|
unsigned Column;
|
|
|
|
Metadata *Scope;
|
|
|
|
Metadata *InlinedAt;
|
[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
|
|
|
bool ImplicitCode;
|
2015-01-14 04:44:56 +08:00
|
|
|
|
2015-02-05 06:08:30 +08:00
|
|
|
MDNodeKeyImpl(unsigned Line, unsigned Column, Metadata *Scope,
|
[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
|
|
|
Metadata *InlinedAt, bool ImplicitCode)
|
|
|
|
: Line(Line), Column(Column), Scope(Scope), InlinedAt(InlinedAt),
|
|
|
|
ImplicitCode(ImplicitCode) {}
|
2015-04-30 00:38:44 +08:00
|
|
|
MDNodeKeyImpl(const DILocation *L)
|
2015-03-27 06:05:04 +08:00
|
|
|
: Line(L->getLine()), Column(L->getColumn()), Scope(L->getRawScope()),
|
[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
|
|
|
InlinedAt(L->getRawInlinedAt()), ImplicitCode(L->isImplicitCode()) {}
|
2015-01-14 04:44:56 +08:00
|
|
|
|
2015-04-30 00:38:44 +08:00
|
|
|
bool isKeyOf(const DILocation *RHS) const {
|
2015-02-05 06:08:30 +08:00
|
|
|
return Line == RHS->getLine() && Column == RHS->getColumn() &&
|
[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
|
|
|
Scope == RHS->getRawScope() && InlinedAt == RHS->getRawInlinedAt() &&
|
|
|
|
ImplicitCode == RHS->isImplicitCode();
|
2015-01-14 04:44:56 +08:00
|
|
|
}
|
2017-06-20 06:05:08 +08:00
|
|
|
|
2015-02-05 06:08:30 +08:00
|
|
|
unsigned getHashValue() const {
|
[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
|
|
|
return hash_combine(Line, Column, Scope, InlinedAt, ImplicitCode);
|
2015-01-14 04:44:56 +08:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2018-05-01 23:54:18 +08:00
|
|
|
/// DenseMapInfo for GenericDINode.
|
2015-04-30 00:38:44 +08:00
|
|
|
template <> struct MDNodeKeyImpl<GenericDINode> : MDNodeOpsKey {
|
2015-02-05 06:08:30 +08:00
|
|
|
unsigned Tag;
|
2016-03-19 09:02:34 +08:00
|
|
|
MDString *Header;
|
2017-06-20 06:05:08 +08:00
|
|
|
|
2016-03-19 09:02:34 +08:00
|
|
|
MDNodeKeyImpl(unsigned Tag, MDString *Header, ArrayRef<Metadata *> DwarfOps)
|
2015-02-05 06:08:30 +08:00
|
|
|
: MDNodeOpsKey(DwarfOps), Tag(Tag), Header(Header) {}
|
2015-04-30 00:38:44 +08:00
|
|
|
MDNodeKeyImpl(const GenericDINode *N)
|
2016-03-19 09:02:34 +08:00
|
|
|
: MDNodeOpsKey(N, 1), Tag(N->getTag()), Header(N->getRawHeader()) {}
|
2015-01-20 08:01:43 +08:00
|
|
|
|
2015-04-30 00:38:44 +08:00
|
|
|
bool isKeyOf(const GenericDINode *RHS) const {
|
2016-03-19 09:02:34 +08:00
|
|
|
return Tag == RHS->getTag() && Header == RHS->getRawHeader() &&
|
2015-02-05 06:08:30 +08:00
|
|
|
compareOps(RHS, 1);
|
2015-01-20 08:01:43 +08:00
|
|
|
}
|
2015-02-05 06:08:30 +08:00
|
|
|
|
|
|
|
unsigned getHashValue() const { return hash_combine(getHash(), Tag, Header); }
|
|
|
|
|
2015-04-30 00:38:44 +08:00
|
|
|
static unsigned calculateHash(GenericDINode *N) {
|
2015-02-05 06:08:30 +08:00
|
|
|
return MDNodeOpsKey::calculateHash(N, 1);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2015-04-30 00:38:44 +08:00
|
|
|
template <> struct MDNodeKeyImpl<DISubrange> {
|
[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 *CountNode;
|
2020-05-28 16:01:22 +08:00
|
|
|
Metadata *LowerBound;
|
|
|
|
Metadata *UpperBound;
|
|
|
|
Metadata *Stride;
|
|
|
|
|
|
|
|
MDNodeKeyImpl(Metadata *CountNode, Metadata *LowerBound, Metadata *UpperBound,
|
|
|
|
Metadata *Stride)
|
|
|
|
: CountNode(CountNode), LowerBound(LowerBound), UpperBound(UpperBound),
|
|
|
|
Stride(Stride) {}
|
2015-04-30 00:38:44 +08:00
|
|
|
MDNodeKeyImpl(const DISubrange *N)
|
2020-05-28 16:01:22 +08:00
|
|
|
: CountNode(N->getRawCountNode()), LowerBound(N->getRawLowerBound()),
|
|
|
|
UpperBound(N->getRawUpperBound()), Stride(N->getRawStride()) {}
|
2015-02-10 08:52:32 +08:00
|
|
|
|
2015-04-30 00:38:44 +08:00
|
|
|
bool isKeyOf(const DISubrange *RHS) const {
|
2020-05-28 16:01:22 +08:00
|
|
|
auto BoundsEqual = [=](Metadata *Node1, Metadata *Node2) -> bool {
|
|
|
|
if (Node1 == Node2)
|
|
|
|
return true;
|
|
|
|
|
|
|
|
ConstantAsMetadata *MD1 = dyn_cast_or_null<ConstantAsMetadata>(Node1);
|
|
|
|
ConstantAsMetadata *MD2 = dyn_cast_or_null<ConstantAsMetadata>(Node2);
|
|
|
|
if (MD1 && MD2) {
|
|
|
|
ConstantInt *CV1 = cast<ConstantInt>(MD1->getValue());
|
|
|
|
ConstantInt *CV2 = cast<ConstantInt>(MD2->getValue());
|
|
|
|
if (CV1->getSExtValue() == CV2->getSExtValue())
|
[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
|
|
|
return true;
|
2020-05-28 16:01:22 +08:00
|
|
|
}
|
|
|
|
return false;
|
|
|
|
};
|
[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
|
|
|
|
2020-05-28 16:01:22 +08:00
|
|
|
return BoundsEqual(CountNode, RHS->getRawCountNode()) &&
|
|
|
|
BoundsEqual(LowerBound, RHS->getRawLowerBound()) &&
|
|
|
|
BoundsEqual(UpperBound, RHS->getRawUpperBound()) &&
|
|
|
|
BoundsEqual(Stride, RHS->getRawStride());
|
2015-02-10 08:52:32 +08:00
|
|
|
}
|
2017-06-20 06:05:08 +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
|
|
|
unsigned getHashValue() const {
|
2020-05-28 16:01:22 +08:00
|
|
|
if (CountNode)
|
|
|
|
if (auto *MD = dyn_cast<ConstantAsMetadata>(CountNode))
|
|
|
|
return hash_combine(cast<ConstantInt>(MD->getValue())->getSExtValue(),
|
|
|
|
LowerBound, UpperBound, Stride);
|
|
|
|
return hash_combine(CountNode, LowerBound, UpperBound, Stride);
|
[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
|
|
|
}
|
2015-02-10 08:52:32 +08:00
|
|
|
};
|
|
|
|
|
2015-04-30 00:38:44 +08:00
|
|
|
template <> struct MDNodeKeyImpl<DIEnumerator> {
|
2020-04-19 02:31:38 +08:00
|
|
|
APInt Value;
|
2016-03-19 09:02:34 +08:00
|
|
|
MDString *Name;
|
2018-02-13 00:10:09 +08:00
|
|
|
bool IsUnsigned;
|
2015-02-10 08:52:32 +08:00
|
|
|
|
2020-04-19 02:31:38 +08:00
|
|
|
MDNodeKeyImpl(APInt Value, bool IsUnsigned, MDString *Name)
|
2018-02-13 00:10:09 +08:00
|
|
|
: Value(Value), Name(Name), IsUnsigned(IsUnsigned) {}
|
2020-04-19 02:31:38 +08:00
|
|
|
MDNodeKeyImpl(int64_t Value, bool IsUnsigned, MDString *Name)
|
|
|
|
: Value(APInt(64, Value, !IsUnsigned)), Name(Name),
|
|
|
|
IsUnsigned(IsUnsigned) {}
|
2015-04-30 00:38:44 +08:00
|
|
|
MDNodeKeyImpl(const DIEnumerator *N)
|
2018-02-13 00:10:09 +08:00
|
|
|
: Value(N->getValue()), Name(N->getRawName()),
|
|
|
|
IsUnsigned(N->isUnsigned()) {}
|
2015-02-10 08:52:32 +08:00
|
|
|
|
2015-04-30 00:38:44 +08:00
|
|
|
bool isKeyOf(const DIEnumerator *RHS) const {
|
2020-04-19 02:31:38 +08:00
|
|
|
return APInt::isSameValue(Value, RHS->getValue()) &&
|
|
|
|
IsUnsigned == RHS->isUnsigned() && Name == RHS->getRawName();
|
2015-02-10 08:52:32 +08:00
|
|
|
}
|
2017-06-20 06:05:08 +08:00
|
|
|
|
2015-02-10 08:52:32 +08:00
|
|
|
unsigned getHashValue() const { return hash_combine(Value, Name); }
|
|
|
|
};
|
|
|
|
|
2015-04-30 00:38:44 +08:00
|
|
|
template <> struct MDNodeKeyImpl<DIBasicType> {
|
2015-02-10 08:52:32 +08:00
|
|
|
unsigned Tag;
|
2016-03-19 09:02:34 +08:00
|
|
|
MDString *Name;
|
2015-02-20 07:56:07 +08:00
|
|
|
uint64_t SizeInBits;
|
2016-10-18 22:31:22 +08:00
|
|
|
uint32_t AlignInBits;
|
2015-02-10 08:52:32 +08:00
|
|
|
unsigned Encoding;
|
2018-08-15 03:35:34 +08:00
|
|
|
unsigned Flags;
|
2015-02-10 08:52:32 +08:00
|
|
|
|
2016-03-19 09:02:34 +08:00
|
|
|
MDNodeKeyImpl(unsigned Tag, MDString *Name, uint64_t SizeInBits,
|
2018-08-15 03:35:34 +08:00
|
|
|
uint32_t AlignInBits, unsigned Encoding, unsigned Flags)
|
2015-02-10 08:52:32 +08:00
|
|
|
: Tag(Tag), Name(Name), SizeInBits(SizeInBits), AlignInBits(AlignInBits),
|
2018-08-15 03:35:34 +08:00
|
|
|
Encoding(Encoding), Flags(Flags) {}
|
2015-04-30 00:38:44 +08:00
|
|
|
MDNodeKeyImpl(const DIBasicType *N)
|
2016-03-19 09:02:34 +08:00
|
|
|
: Tag(N->getTag()), Name(N->getRawName()), SizeInBits(N->getSizeInBits()),
|
2018-08-15 03:35:34 +08:00
|
|
|
AlignInBits(N->getAlignInBits()), Encoding(N->getEncoding()), Flags(N->getFlags()) {}
|
2015-02-10 08:52:32 +08:00
|
|
|
|
2015-04-30 00:38:44 +08:00
|
|
|
bool isKeyOf(const DIBasicType *RHS) const {
|
2016-03-19 09:02:34 +08:00
|
|
|
return Tag == RHS->getTag() && Name == RHS->getRawName() &&
|
2015-02-10 08:52:32 +08:00
|
|
|
SizeInBits == RHS->getSizeInBits() &&
|
|
|
|
AlignInBits == RHS->getAlignInBits() &&
|
2018-08-15 03:35:34 +08:00
|
|
|
Encoding == RHS->getEncoding() &&
|
|
|
|
Flags == RHS->getFlags();
|
2015-02-10 08:52:32 +08:00
|
|
|
}
|
2017-06-20 06:05:08 +08:00
|
|
|
|
2015-02-10 08:52:32 +08:00
|
|
|
unsigned getHashValue() const {
|
|
|
|
return hash_combine(Tag, Name, SizeInBits, AlignInBits, Encoding);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2020-08-20 18:41:22 +08:00
|
|
|
template <> struct MDNodeKeyImpl<DIStringType> {
|
|
|
|
unsigned Tag;
|
|
|
|
MDString *Name;
|
|
|
|
Metadata *StringLength;
|
|
|
|
Metadata *StringLengthExp;
|
|
|
|
uint64_t SizeInBits;
|
|
|
|
uint32_t AlignInBits;
|
|
|
|
unsigned Encoding;
|
|
|
|
|
|
|
|
MDNodeKeyImpl(unsigned Tag, MDString *Name, Metadata *StringLength,
|
|
|
|
Metadata *StringLengthExp, uint64_t SizeInBits,
|
|
|
|
uint32_t AlignInBits, unsigned Encoding)
|
|
|
|
: Tag(Tag), Name(Name), StringLength(StringLength),
|
|
|
|
StringLengthExp(StringLengthExp), SizeInBits(SizeInBits),
|
|
|
|
AlignInBits(AlignInBits), Encoding(Encoding) {}
|
|
|
|
MDNodeKeyImpl(const DIStringType *N)
|
|
|
|
: Tag(N->getTag()), Name(N->getRawName()),
|
|
|
|
StringLength(N->getRawStringLength()),
|
|
|
|
StringLengthExp(N->getRawStringLengthExp()),
|
|
|
|
SizeInBits(N->getSizeInBits()), AlignInBits(N->getAlignInBits()),
|
|
|
|
Encoding(N->getEncoding()) {}
|
|
|
|
|
|
|
|
bool isKeyOf(const DIStringType *RHS) const {
|
|
|
|
return Tag == RHS->getTag() && Name == RHS->getRawName() &&
|
|
|
|
SizeInBits == RHS->getSizeInBits() &&
|
|
|
|
AlignInBits == RHS->getAlignInBits() &&
|
|
|
|
Encoding == RHS->getEncoding();
|
|
|
|
}
|
|
|
|
unsigned getHashValue() const { return hash_combine(Tag, Name, Encoding); }
|
|
|
|
};
|
|
|
|
|
2015-04-30 00:38:44 +08:00
|
|
|
template <> struct MDNodeKeyImpl<DIDerivedType> {
|
2015-02-10 08:52:32 +08:00
|
|
|
unsigned Tag;
|
2016-03-19 09:02:34 +08:00
|
|
|
MDString *Name;
|
2015-02-10 08:52:32 +08:00
|
|
|
Metadata *File;
|
|
|
|
unsigned Line;
|
|
|
|
Metadata *Scope;
|
|
|
|
Metadata *BaseType;
|
2015-02-20 07:56:07 +08:00
|
|
|
uint64_t SizeInBits;
|
|
|
|
uint64_t OffsetInBits;
|
2016-10-18 22:31:22 +08:00
|
|
|
uint32_t AlignInBits;
|
2017-03-09 07:55:44 +08:00
|
|
|
Optional<unsigned> DWARFAddressSpace;
|
2015-02-10 08:52:32 +08:00
|
|
|
unsigned Flags;
|
|
|
|
Metadata *ExtraData;
|
|
|
|
|
2016-03-19 09:02:34 +08:00
|
|
|
MDNodeKeyImpl(unsigned Tag, MDString *Name, Metadata *File, unsigned Line,
|
2015-02-20 07:56:07 +08:00
|
|
|
Metadata *Scope, Metadata *BaseType, uint64_t SizeInBits,
|
2017-03-09 07:55:44 +08:00
|
|
|
uint32_t AlignInBits, uint64_t OffsetInBits,
|
|
|
|
Optional<unsigned> DWARFAddressSpace, unsigned Flags,
|
2015-02-10 08:52:32 +08:00
|
|
|
Metadata *ExtraData)
|
|
|
|
: Tag(Tag), Name(Name), File(File), Line(Line), Scope(Scope),
|
2016-10-18 22:31:22 +08:00
|
|
|
BaseType(BaseType), SizeInBits(SizeInBits), OffsetInBits(OffsetInBits),
|
2017-03-09 07:55:44 +08:00
|
|
|
AlignInBits(AlignInBits), DWARFAddressSpace(DWARFAddressSpace),
|
|
|
|
Flags(Flags), ExtraData(ExtraData) {}
|
2015-04-30 00:38:44 +08:00
|
|
|
MDNodeKeyImpl(const DIDerivedType *N)
|
2016-03-19 09:02:34 +08:00
|
|
|
: Tag(N->getTag()), Name(N->getRawName()), File(N->getRawFile()),
|
2015-03-28 07:05:04 +08:00
|
|
|
Line(N->getLine()), Scope(N->getRawScope()),
|
|
|
|
BaseType(N->getRawBaseType()), SizeInBits(N->getSizeInBits()),
|
2016-10-18 22:31:22 +08:00
|
|
|
OffsetInBits(N->getOffsetInBits()), AlignInBits(N->getAlignInBits()),
|
2017-03-09 07:55:44 +08:00
|
|
|
DWARFAddressSpace(N->getDWARFAddressSpace()), Flags(N->getFlags()),
|
|
|
|
ExtraData(N->getRawExtraData()) {}
|
2015-02-10 08:52:32 +08:00
|
|
|
|
2015-04-30 00:38:44 +08:00
|
|
|
bool isKeyOf(const DIDerivedType *RHS) const {
|
2016-03-19 09:02:34 +08:00
|
|
|
return Tag == RHS->getTag() && Name == RHS->getRawName() &&
|
2015-03-28 07:05:04 +08:00
|
|
|
File == RHS->getRawFile() && Line == RHS->getLine() &&
|
|
|
|
Scope == RHS->getRawScope() && BaseType == RHS->getRawBaseType() &&
|
2015-02-10 08:52:32 +08:00
|
|
|
SizeInBits == RHS->getSizeInBits() &&
|
|
|
|
AlignInBits == RHS->getAlignInBits() &&
|
2017-03-09 07:55:44 +08:00
|
|
|
OffsetInBits == RHS->getOffsetInBits() &&
|
|
|
|
DWARFAddressSpace == RHS->getDWARFAddressSpace() &&
|
|
|
|
Flags == RHS->getFlags() &&
|
2015-03-28 07:05:04 +08:00
|
|
|
ExtraData == RHS->getRawExtraData();
|
2015-02-10 08:52:32 +08:00
|
|
|
}
|
2017-06-20 06:05:08 +08:00
|
|
|
|
2015-02-10 08:52:32 +08:00
|
|
|
unsigned getHashValue() const {
|
2016-04-17 10:30:20 +08:00
|
|
|
// If this is a member inside an ODR type, only hash the type and the name.
|
|
|
|
// Otherwise the hash will be stronger than
|
|
|
|
// MDNodeSubsetEqualImpl::isODRMember().
|
2016-04-24 05:08:00 +08:00
|
|
|
if (Tag == dwarf::DW_TAG_member && Name)
|
|
|
|
if (auto *CT = dyn_cast_or_null<DICompositeType>(Scope))
|
|
|
|
if (CT->getRawIdentifier())
|
|
|
|
return hash_combine(Name, Scope);
|
2016-04-17 10:30:20 +08:00
|
|
|
|
2016-03-19 09:06:24 +08:00
|
|
|
// Intentionally computes the hash on a subset of the operands for
|
|
|
|
// performance reason. The subset has to be significant enough to avoid
|
|
|
|
// collision "most of the time". There is no correctness issue in case of
|
|
|
|
// collision because of the full check above.
|
2016-03-19 08:59:26 +08:00
|
|
|
return hash_combine(Tag, Name, File, Line, Scope, BaseType, Flags);
|
2015-02-10 08:52:32 +08:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2016-04-17 10:30:20 +08:00
|
|
|
template <> struct MDNodeSubsetEqualImpl<DIDerivedType> {
|
2017-06-20 06:05:08 +08:00
|
|
|
using KeyTy = MDNodeKeyImpl<DIDerivedType>;
|
|
|
|
|
2016-04-17 10:30:20 +08:00
|
|
|
static bool isSubsetEqual(const KeyTy &LHS, const DIDerivedType *RHS) {
|
|
|
|
return isODRMember(LHS.Tag, LHS.Scope, LHS.Name, RHS);
|
|
|
|
}
|
2017-06-20 06:05:08 +08:00
|
|
|
|
2016-04-17 10:30:20 +08:00
|
|
|
static bool isSubsetEqual(const DIDerivedType *LHS, const DIDerivedType *RHS) {
|
|
|
|
return isODRMember(LHS->getTag(), LHS->getRawScope(), LHS->getRawName(),
|
|
|
|
RHS);
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Subprograms compare equal if they declare the same function in an ODR
|
|
|
|
/// type.
|
|
|
|
static bool isODRMember(unsigned Tag, const Metadata *Scope,
|
|
|
|
const MDString *Name, const DIDerivedType *RHS) {
|
|
|
|
// Check whether the LHS is eligible.
|
2016-04-24 05:08:00 +08:00
|
|
|
if (Tag != dwarf::DW_TAG_member || !Name)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
auto *CT = dyn_cast_or_null<DICompositeType>(Scope);
|
|
|
|
if (!CT || !CT->getRawIdentifier())
|
2016-04-17 10:30:20 +08:00
|
|
|
return false;
|
|
|
|
|
|
|
|
// Compare to the RHS.
|
|
|
|
return Tag == RHS->getTag() && Name == RHS->getRawName() &&
|
|
|
|
Scope == RHS->getRawScope();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2015-04-30 00:38:44 +08:00
|
|
|
template <> struct MDNodeKeyImpl<DICompositeType> {
|
2015-02-10 08:52:32 +08:00
|
|
|
unsigned Tag;
|
2016-03-19 09:02:34 +08:00
|
|
|
MDString *Name;
|
2015-02-10 08:52:32 +08:00
|
|
|
Metadata *File;
|
|
|
|
unsigned Line;
|
|
|
|
Metadata *Scope;
|
|
|
|
Metadata *BaseType;
|
2015-02-20 07:56:07 +08:00
|
|
|
uint64_t SizeInBits;
|
|
|
|
uint64_t OffsetInBits;
|
2016-10-18 22:31:22 +08:00
|
|
|
uint32_t AlignInBits;
|
2015-02-10 08:52:32 +08:00
|
|
|
unsigned Flags;
|
|
|
|
Metadata *Elements;
|
|
|
|
unsigned RuntimeLang;
|
|
|
|
Metadata *VTableHolder;
|
|
|
|
Metadata *TemplateParams;
|
2016-03-19 09:02:34 +08:00
|
|
|
MDString *Identifier;
|
2018-02-07 07:45:59 +08:00
|
|
|
Metadata *Discriminator;
|
2020-05-15 13:54:27 +08:00
|
|
|
Metadata *DataLocation;
|
2020-07-20 22:20:37 +08:00
|
|
|
Metadata *Associated;
|
|
|
|
Metadata *Allocated;
|
2015-02-10 08:52:32 +08:00
|
|
|
|
2016-03-19 09:02:34 +08:00
|
|
|
MDNodeKeyImpl(unsigned Tag, MDString *Name, Metadata *File, unsigned Line,
|
2015-02-20 07:56:07 +08:00
|
|
|
Metadata *Scope, Metadata *BaseType, uint64_t SizeInBits,
|
2016-10-18 22:31:22 +08:00
|
|
|
uint32_t AlignInBits, uint64_t OffsetInBits, unsigned Flags,
|
2015-02-10 08:52:32 +08:00
|
|
|
Metadata *Elements, unsigned RuntimeLang,
|
|
|
|
Metadata *VTableHolder, Metadata *TemplateParams,
|
2020-05-15 13:54:27 +08:00
|
|
|
MDString *Identifier, Metadata *Discriminator,
|
2020-07-20 22:20:37 +08:00
|
|
|
Metadata *DataLocation, Metadata *Associated,
|
|
|
|
Metadata *Allocated)
|
2015-02-10 08:52:32 +08:00
|
|
|
: Tag(Tag), Name(Name), File(File), Line(Line), Scope(Scope),
|
2016-10-18 22:31:22 +08:00
|
|
|
BaseType(BaseType), SizeInBits(SizeInBits), OffsetInBits(OffsetInBits),
|
|
|
|
AlignInBits(AlignInBits), Flags(Flags), Elements(Elements),
|
2015-02-10 08:52:32 +08:00
|
|
|
RuntimeLang(RuntimeLang), VTableHolder(VTableHolder),
|
2018-02-07 07:45:59 +08:00
|
|
|
TemplateParams(TemplateParams), Identifier(Identifier),
|
2020-07-20 22:20:37 +08:00
|
|
|
Discriminator(Discriminator), DataLocation(DataLocation),
|
|
|
|
Associated(Associated), Allocated(Allocated) {}
|
2015-04-30 00:38:44 +08:00
|
|
|
MDNodeKeyImpl(const DICompositeType *N)
|
2016-03-19 09:02:34 +08:00
|
|
|
: Tag(N->getTag()), Name(N->getRawName()), File(N->getRawFile()),
|
2015-03-28 07:05:04 +08:00
|
|
|
Line(N->getLine()), Scope(N->getRawScope()),
|
|
|
|
BaseType(N->getRawBaseType()), SizeInBits(N->getSizeInBits()),
|
2016-10-18 22:31:22 +08:00
|
|
|
OffsetInBits(N->getOffsetInBits()), AlignInBits(N->getAlignInBits()),
|
2015-03-28 07:05:04 +08:00
|
|
|
Flags(N->getFlags()), Elements(N->getRawElements()),
|
|
|
|
RuntimeLang(N->getRuntimeLang()), VTableHolder(N->getRawVTableHolder()),
|
|
|
|
TemplateParams(N->getRawTemplateParams()),
|
2018-02-07 07:45:59 +08:00
|
|
|
Identifier(N->getRawIdentifier()),
|
2020-05-15 13:54:27 +08:00
|
|
|
Discriminator(N->getRawDiscriminator()),
|
2020-07-20 22:20:37 +08:00
|
|
|
DataLocation(N->getRawDataLocation()),
|
|
|
|
Associated(N->getRawAssociated()), Allocated(N->getRawAllocated()) {}
|
2015-02-10 08:52:32 +08:00
|
|
|
|
2015-04-30 00:38:44 +08:00
|
|
|
bool isKeyOf(const DICompositeType *RHS) const {
|
2016-03-19 09:02:34 +08:00
|
|
|
return Tag == RHS->getTag() && Name == RHS->getRawName() &&
|
2015-03-28 07:05:04 +08:00
|
|
|
File == RHS->getRawFile() && Line == RHS->getLine() &&
|
|
|
|
Scope == RHS->getRawScope() && BaseType == RHS->getRawBaseType() &&
|
2015-02-10 08:52:32 +08:00
|
|
|
SizeInBits == RHS->getSizeInBits() &&
|
|
|
|
AlignInBits == RHS->getAlignInBits() &&
|
|
|
|
OffsetInBits == RHS->getOffsetInBits() && Flags == RHS->getFlags() &&
|
2015-03-28 07:05:04 +08:00
|
|
|
Elements == RHS->getRawElements() &&
|
2015-02-10 08:52:32 +08:00
|
|
|
RuntimeLang == RHS->getRuntimeLang() &&
|
2015-03-28 07:05:04 +08:00
|
|
|
VTableHolder == RHS->getRawVTableHolder() &&
|
|
|
|
TemplateParams == RHS->getRawTemplateParams() &&
|
2018-02-07 07:45:59 +08:00
|
|
|
Identifier == RHS->getRawIdentifier() &&
|
2020-05-15 13:54:27 +08:00
|
|
|
Discriminator == RHS->getRawDiscriminator() &&
|
2020-07-20 22:20:37 +08:00
|
|
|
DataLocation == RHS->getRawDataLocation() &&
|
|
|
|
Associated == RHS->getRawAssociated() &&
|
|
|
|
Allocated == RHS->getRawAllocated();
|
2015-02-10 08:52:32 +08:00
|
|
|
}
|
2017-06-20 06:05:08 +08:00
|
|
|
|
2015-02-10 08:52:32 +08:00
|
|
|
unsigned getHashValue() const {
|
2016-03-19 09:06:24 +08:00
|
|
|
// Intentionally computes the hash on a subset of the operands for
|
|
|
|
// performance reason. The subset has to be significant enough to avoid
|
|
|
|
// collision "most of the time". There is no correctness issue in case of
|
|
|
|
// collision because of the full check above.
|
2016-03-19 08:59:26 +08:00
|
|
|
return hash_combine(Name, File, Line, BaseType, Scope, Elements,
|
|
|
|
TemplateParams);
|
2015-02-10 08:52:32 +08:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2015-04-30 00:38:44 +08:00
|
|
|
template <> struct MDNodeKeyImpl<DISubroutineType> {
|
2015-02-10 08:52:32 +08:00
|
|
|
unsigned Flags;
|
2016-06-09 04:34:29 +08:00
|
|
|
uint8_t CC;
|
2015-02-10 08:52:32 +08:00
|
|
|
Metadata *TypeArray;
|
|
|
|
|
2016-06-09 04:34:29 +08:00
|
|
|
MDNodeKeyImpl(unsigned Flags, uint8_t CC, Metadata *TypeArray)
|
|
|
|
: Flags(Flags), CC(CC), TypeArray(TypeArray) {}
|
2015-04-30 00:38:44 +08:00
|
|
|
MDNodeKeyImpl(const DISubroutineType *N)
|
2016-06-09 04:34:29 +08:00
|
|
|
: Flags(N->getFlags()), CC(N->getCC()), TypeArray(N->getRawTypeArray()) {}
|
2015-02-10 08:52:32 +08:00
|
|
|
|
2015-04-30 00:38:44 +08:00
|
|
|
bool isKeyOf(const DISubroutineType *RHS) const {
|
2016-06-09 04:34:29 +08:00
|
|
|
return Flags == RHS->getFlags() && CC == RHS->getCC() &&
|
|
|
|
TypeArray == RHS->getRawTypeArray();
|
2015-02-10 08:52:32 +08:00
|
|
|
}
|
2017-06-20 06:05:08 +08:00
|
|
|
|
2016-06-09 04:34:29 +08:00
|
|
|
unsigned getHashValue() const { return hash_combine(Flags, CC, TypeArray); }
|
2015-02-10 08:52:32 +08:00
|
|
|
};
|
|
|
|
|
2015-04-30 00:38:44 +08:00
|
|
|
template <> struct MDNodeKeyImpl<DIFile> {
|
2016-03-19 09:02:34 +08:00
|
|
|
MDString *Filename;
|
|
|
|
MDString *Directory;
|
2018-02-13 03:45:54 +08:00
|
|
|
Optional<DIFile::ChecksumInfo<MDString *>> Checksum;
|
2018-02-24 07:01:06 +08:00
|
|
|
Optional<MDString *> Source;
|
2015-02-10 08:52:32 +08:00
|
|
|
|
2016-12-25 18:12:09 +08:00
|
|
|
MDNodeKeyImpl(MDString *Filename, MDString *Directory,
|
2018-02-24 07:01:06 +08:00
|
|
|
Optional<DIFile::ChecksumInfo<MDString *>> Checksum,
|
|
|
|
Optional<MDString *> Source)
|
|
|
|
: Filename(Filename), Directory(Directory), Checksum(Checksum),
|
|
|
|
Source(Source) {}
|
2015-04-30 00:38:44 +08:00
|
|
|
MDNodeKeyImpl(const DIFile *N)
|
2016-12-25 18:12:09 +08:00
|
|
|
: Filename(N->getRawFilename()), Directory(N->getRawDirectory()),
|
2018-02-24 07:01:06 +08:00
|
|
|
Checksum(N->getRawChecksum()), Source(N->getRawSource()) {}
|
2015-02-10 08:52:32 +08:00
|
|
|
|
2015-04-30 00:38:44 +08:00
|
|
|
bool isKeyOf(const DIFile *RHS) const {
|
2016-03-19 09:02:34 +08:00
|
|
|
return Filename == RHS->getRawFilename() &&
|
2016-12-25 18:12:09 +08:00
|
|
|
Directory == RHS->getRawDirectory() &&
|
2018-02-24 07:01:06 +08:00
|
|
|
Checksum == RHS->getRawChecksum() &&
|
|
|
|
Source == RHS->getRawSource();
|
2016-12-25 18:12:09 +08:00
|
|
|
}
|
2017-06-20 06:05:08 +08:00
|
|
|
|
2016-12-25 18:12:09 +08:00
|
|
|
unsigned getHashValue() const {
|
2018-02-24 07:01:06 +08:00
|
|
|
return hash_combine(
|
|
|
|
Filename, Directory, Checksum ? Checksum->Kind : 0,
|
|
|
|
Checksum ? Checksum->Value : nullptr, Source.getValueOr(nullptr));
|
2015-02-10 08:52:32 +08:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2015-04-30 00:38:44 +08:00
|
|
|
template <> struct MDNodeKeyImpl<DISubprogram> {
|
2015-02-10 08:52:32 +08:00
|
|
|
Metadata *Scope;
|
2016-03-19 09:02:34 +08:00
|
|
|
MDString *Name;
|
|
|
|
MDString *LinkageName;
|
2015-02-10 08:52:32 +08:00
|
|
|
Metadata *File;
|
|
|
|
unsigned Line;
|
|
|
|
Metadata *Type;
|
|
|
|
unsigned ScopeLine;
|
|
|
|
Metadata *ContainingType;
|
|
|
|
unsigned VirtualIndex;
|
2016-07-01 10:41:21 +08:00
|
|
|
int ThisAdjustment;
|
2015-02-10 08:52:32 +08:00
|
|
|
unsigned Flags;
|
2018-11-20 02:29:28 +08:00
|
|
|
unsigned SPFlags;
|
2016-04-15 23:57:41 +08:00
|
|
|
Metadata *Unit;
|
2015-02-10 08:52:32 +08:00
|
|
|
Metadata *TemplateParams;
|
|
|
|
Metadata *Declaration;
|
[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
|
|
|
Metadata *RetainedNodes;
|
2017-04-27 06:56:44 +08:00
|
|
|
Metadata *ThrownTypes;
|
2015-02-10 08:52:32 +08:00
|
|
|
|
2016-03-19 09:02:34 +08:00
|
|
|
MDNodeKeyImpl(Metadata *Scope, MDString *Name, MDString *LinkageName,
|
2015-02-10 08:52:32 +08:00
|
|
|
Metadata *File, unsigned Line, Metadata *Type,
|
2018-11-20 02:29:28 +08:00
|
|
|
unsigned ScopeLine, Metadata *ContainingType,
|
2016-07-01 10:41:21 +08:00
|
|
|
unsigned VirtualIndex, int ThisAdjustment, unsigned Flags,
|
2018-11-20 02:29:28 +08:00
|
|
|
unsigned SPFlags, Metadata *Unit, Metadata *TemplateParams,
|
[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
|
|
|
Metadata *Declaration, Metadata *RetainedNodes,
|
2017-04-27 06:56:44 +08:00
|
|
|
Metadata *ThrownTypes)
|
2015-02-10 08:52:32 +08:00
|
|
|
: Scope(Scope), Name(Name), LinkageName(LinkageName), File(File),
|
2018-11-20 02:29:28 +08:00
|
|
|
Line(Line), Type(Type), ScopeLine(ScopeLine),
|
|
|
|
ContainingType(ContainingType), VirtualIndex(VirtualIndex),
|
|
|
|
ThisAdjustment(ThisAdjustment), Flags(Flags), SPFlags(SPFlags),
|
|
|
|
Unit(Unit), TemplateParams(TemplateParams), Declaration(Declaration),
|
[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
|
|
|
RetainedNodes(RetainedNodes), ThrownTypes(ThrownTypes) {}
|
2015-04-30 00:38:44 +08:00
|
|
|
MDNodeKeyImpl(const DISubprogram *N)
|
2016-03-19 09:02:34 +08:00
|
|
|
: Scope(N->getRawScope()), Name(N->getRawName()),
|
|
|
|
LinkageName(N->getRawLinkageName()), File(N->getRawFile()),
|
2018-11-20 02:29:28 +08:00
|
|
|
Line(N->getLine()), Type(N->getRawType()), ScopeLine(N->getScopeLine()),
|
|
|
|
ContainingType(N->getRawContainingType()),
|
|
|
|
VirtualIndex(N->getVirtualIndex()),
|
2016-07-01 10:41:21 +08:00
|
|
|
ThisAdjustment(N->getThisAdjustment()), Flags(N->getFlags()),
|
2018-11-20 02:29:28 +08:00
|
|
|
SPFlags(N->getSPFlags()), Unit(N->getRawUnit()),
|
2016-07-01 10:41:21 +08:00
|
|
|
TemplateParams(N->getRawTemplateParams()),
|
2018-11-20 02:29:28 +08:00
|
|
|
Declaration(N->getRawDeclaration()),
|
|
|
|
RetainedNodes(N->getRawRetainedNodes()),
|
2017-04-27 06:56:44 +08:00
|
|
|
ThrownTypes(N->getRawThrownTypes()) {}
|
2015-02-10 08:52:32 +08:00
|
|
|
|
2015-04-30 00:38:44 +08:00
|
|
|
bool isKeyOf(const DISubprogram *RHS) const {
|
2016-03-19 09:02:34 +08:00
|
|
|
return Scope == RHS->getRawScope() && Name == RHS->getRawName() &&
|
|
|
|
LinkageName == RHS->getRawLinkageName() &&
|
|
|
|
File == RHS->getRawFile() && Line == RHS->getLine() &&
|
2018-11-20 02:29:28 +08:00
|
|
|
Type == RHS->getRawType() && ScopeLine == RHS->getScopeLine() &&
|
2015-03-31 00:19:15 +08:00
|
|
|
ContainingType == RHS->getRawContainingType() &&
|
2016-07-01 10:41:21 +08:00
|
|
|
VirtualIndex == RHS->getVirtualIndex() &&
|
|
|
|
ThisAdjustment == RHS->getThisAdjustment() &&
|
2018-11-20 02:29:28 +08:00
|
|
|
Flags == RHS->getFlags() && SPFlags == RHS->getSPFlags() &&
|
2016-07-01 10:41:21 +08:00
|
|
|
Unit == RHS->getUnit() &&
|
2015-03-31 00:19:15 +08:00
|
|
|
TemplateParams == RHS->getRawTemplateParams() &&
|
|
|
|
Declaration == RHS->getRawDeclaration() &&
|
[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
|
|
|
RetainedNodes == RHS->getRawRetainedNodes() &&
|
2017-04-27 06:56:44 +08:00
|
|
|
ThrownTypes == RHS->getRawThrownTypes();
|
2015-02-10 08:52:32 +08:00
|
|
|
}
|
2017-06-20 06:05:08 +08:00
|
|
|
|
2018-11-20 02:29:28 +08:00
|
|
|
bool isDefinition() const { return SPFlags & DISubprogram::SPFlagDefinition; }
|
|
|
|
|
2015-02-10 08:52:32 +08:00
|
|
|
unsigned getHashValue() const {
|
2016-04-17 10:30:20 +08:00
|
|
|
// If this is a declaration inside an ODR type, only hash the type and the
|
|
|
|
// name. Otherwise the hash will be stronger than
|
|
|
|
// MDNodeSubsetEqualImpl::isDeclarationOfODRMember().
|
2018-11-20 02:29:28 +08:00
|
|
|
if (!isDefinition() && LinkageName)
|
2016-04-24 05:08:00 +08:00
|
|
|
if (auto *CT = dyn_cast_or_null<DICompositeType>(Scope))
|
|
|
|
if (CT->getRawIdentifier())
|
|
|
|
return hash_combine(LinkageName, Scope);
|
2016-04-17 10:30:20 +08:00
|
|
|
|
2016-03-19 09:06:24 +08:00
|
|
|
// Intentionally computes the hash on a subset of the operands for
|
|
|
|
// performance reason. The subset has to be significant enough to avoid
|
|
|
|
// collision "most of the time". There is no correctness issue in case of
|
|
|
|
// collision because of the full check above.
|
2016-03-19 08:59:26 +08:00
|
|
|
return hash_combine(Name, Scope, File, Type, Line);
|
2015-02-10 08:52:32 +08:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2016-04-17 10:30:20 +08:00
|
|
|
template <> struct MDNodeSubsetEqualImpl<DISubprogram> {
|
2017-06-20 06:05:08 +08:00
|
|
|
using KeyTy = MDNodeKeyImpl<DISubprogram>;
|
|
|
|
|
2016-04-17 10:30:20 +08:00
|
|
|
static bool isSubsetEqual(const KeyTy &LHS, const DISubprogram *RHS) {
|
2018-11-20 02:29:28 +08:00
|
|
|
return isDeclarationOfODRMember(LHS.isDefinition(), LHS.Scope,
|
2017-02-07 05:23:03 +08:00
|
|
|
LHS.LinkageName, LHS.TemplateParams, RHS);
|
2016-04-17 10:30:20 +08:00
|
|
|
}
|
2017-06-20 06:05:08 +08:00
|
|
|
|
2016-04-17 10:30:20 +08:00
|
|
|
static bool isSubsetEqual(const DISubprogram *LHS, const DISubprogram *RHS) {
|
|
|
|
return isDeclarationOfODRMember(LHS->isDefinition(), LHS->getRawScope(),
|
2017-02-07 05:23:03 +08:00
|
|
|
LHS->getRawLinkageName(),
|
|
|
|
LHS->getRawTemplateParams(), RHS);
|
2016-04-17 10:30:20 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Subprograms compare equal if they declare the same function in an ODR
|
|
|
|
/// type.
|
|
|
|
static bool isDeclarationOfODRMember(bool IsDefinition, const Metadata *Scope,
|
|
|
|
const MDString *LinkageName,
|
2017-02-07 05:23:03 +08:00
|
|
|
const Metadata *TemplateParams,
|
2016-04-17 10:30:20 +08:00
|
|
|
const DISubprogram *RHS) {
|
|
|
|
// Check whether the LHS is eligible.
|
2016-04-24 05:08:00 +08:00
|
|
|
if (IsDefinition || !Scope || !LinkageName)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
auto *CT = dyn_cast_or_null<DICompositeType>(Scope);
|
|
|
|
if (!CT || !CT->getRawIdentifier())
|
2016-04-17 10:30:20 +08:00
|
|
|
return false;
|
|
|
|
|
|
|
|
// Compare to the RHS.
|
2017-02-07 05:23:03 +08:00
|
|
|
// FIXME: We need to compare template parameters here to avoid incorrect
|
|
|
|
// collisions in mapMetadata when RF_MoveDistinctMDs and a ODR-DISubprogram
|
|
|
|
// has a non-ODR template parameter (i.e., a DICompositeType that does not
|
|
|
|
// have an identifier). Eventually we should decouple ODR logic from
|
|
|
|
// uniquing logic.
|
2016-04-17 10:30:20 +08:00
|
|
|
return IsDefinition == RHS->isDefinition() && Scope == RHS->getRawScope() &&
|
2017-02-07 05:23:03 +08:00
|
|
|
LinkageName == RHS->getRawLinkageName() &&
|
|
|
|
TemplateParams == RHS->getRawTemplateParams();
|
2016-04-17 10:30:20 +08:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2015-04-30 00:38:44 +08:00
|
|
|
template <> struct MDNodeKeyImpl<DILexicalBlock> {
|
2015-02-10 08:52:32 +08:00
|
|
|
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) {}
|
2015-04-30 00:38:44 +08:00
|
|
|
MDNodeKeyImpl(const DILexicalBlock *N)
|
2015-03-31 00:37:48 +08:00
|
|
|
: Scope(N->getRawScope()), File(N->getRawFile()), Line(N->getLine()),
|
2015-02-10 08:52:32 +08:00
|
|
|
Column(N->getColumn()) {}
|
|
|
|
|
2015-04-30 00:38:44 +08:00
|
|
|
bool isKeyOf(const DILexicalBlock *RHS) const {
|
2015-03-31 00:37:48 +08:00
|
|
|
return Scope == RHS->getRawScope() && File == RHS->getRawFile() &&
|
2015-02-10 08:52:32 +08:00
|
|
|
Line == RHS->getLine() && Column == RHS->getColumn();
|
|
|
|
}
|
2017-06-20 06:05:08 +08:00
|
|
|
|
2015-02-10 08:52:32 +08:00
|
|
|
unsigned getHashValue() const {
|
|
|
|
return hash_combine(Scope, File, Line, Column);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2015-04-30 00:38:44 +08:00
|
|
|
template <> struct MDNodeKeyImpl<DILexicalBlockFile> {
|
2015-02-10 08:52:32 +08:00
|
|
|
Metadata *Scope;
|
|
|
|
Metadata *File;
|
|
|
|
unsigned Discriminator;
|
|
|
|
|
|
|
|
MDNodeKeyImpl(Metadata *Scope, Metadata *File, unsigned Discriminator)
|
|
|
|
: Scope(Scope), File(File), Discriminator(Discriminator) {}
|
2015-04-30 00:38:44 +08:00
|
|
|
MDNodeKeyImpl(const DILexicalBlockFile *N)
|
2015-03-31 00:37:48 +08:00
|
|
|
: Scope(N->getRawScope()), File(N->getRawFile()),
|
2015-02-10 08:52:32 +08:00
|
|
|
Discriminator(N->getDiscriminator()) {}
|
|
|
|
|
2015-04-30 00:38:44 +08:00
|
|
|
bool isKeyOf(const DILexicalBlockFile *RHS) const {
|
2015-03-31 00:37:48 +08:00
|
|
|
return Scope == RHS->getRawScope() && File == RHS->getRawFile() &&
|
2015-02-10 08:52:32 +08:00
|
|
|
Discriminator == RHS->getDiscriminator();
|
|
|
|
}
|
2017-06-20 06:05:08 +08:00
|
|
|
|
2015-02-10 08:52:32 +08:00
|
|
|
unsigned getHashValue() const {
|
|
|
|
return hash_combine(Scope, File, Discriminator);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2015-04-30 00:38:44 +08:00
|
|
|
template <> struct MDNodeKeyImpl<DINamespace> {
|
2015-02-10 08:52:32 +08:00
|
|
|
Metadata *Scope;
|
2016-03-19 09:02:34 +08:00
|
|
|
MDString *Name;
|
2016-11-04 03:42:02 +08:00
|
|
|
bool ExportSymbols;
|
2015-02-10 08:52:32 +08:00
|
|
|
|
2017-04-29 06:25:46 +08:00
|
|
|
MDNodeKeyImpl(Metadata *Scope, MDString *Name, bool ExportSymbols)
|
|
|
|
: Scope(Scope), Name(Name), ExportSymbols(ExportSymbols) {}
|
2015-04-30 00:38:44 +08:00
|
|
|
MDNodeKeyImpl(const DINamespace *N)
|
2017-04-29 06:25:46 +08:00
|
|
|
: Scope(N->getRawScope()), Name(N->getRawName()),
|
|
|
|
ExportSymbols(N->getExportSymbols()) {}
|
2015-02-10 08:52:32 +08:00
|
|
|
|
2015-04-30 00:38:44 +08:00
|
|
|
bool isKeyOf(const DINamespace *RHS) const {
|
2017-04-29 06:25:46 +08:00
|
|
|
return Scope == RHS->getRawScope() && Name == RHS->getRawName() &&
|
2016-11-04 03:42:02 +08:00
|
|
|
ExportSymbols == RHS->getExportSymbols();
|
2015-02-10 08:52:32 +08:00
|
|
|
}
|
2017-06-20 06:05:08 +08:00
|
|
|
|
2015-02-10 08:52:32 +08:00
|
|
|
unsigned getHashValue() const {
|
2017-04-29 06:25:46 +08:00
|
|
|
return hash_combine(Scope, Name);
|
2015-02-10 08:52:32 +08:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
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
|
|
|
template <> struct MDNodeKeyImpl<DICommonBlock> {
|
|
|
|
Metadata *Scope;
|
|
|
|
Metadata *Decl;
|
|
|
|
MDString *Name;
|
|
|
|
Metadata *File;
|
|
|
|
unsigned LineNo;
|
|
|
|
|
|
|
|
MDNodeKeyImpl(Metadata *Scope, Metadata *Decl, MDString *Name,
|
|
|
|
Metadata *File, unsigned LineNo)
|
|
|
|
: Scope(Scope), Decl(Decl), Name(Name), File(File), LineNo(LineNo) {}
|
|
|
|
MDNodeKeyImpl(const DICommonBlock *N)
|
|
|
|
: Scope(N->getRawScope()), Decl(N->getRawDecl()), Name(N->getRawName()),
|
|
|
|
File(N->getRawFile()), LineNo(N->getLineNo()) {}
|
|
|
|
|
|
|
|
bool isKeyOf(const DICommonBlock *RHS) const {
|
|
|
|
return Scope == RHS->getRawScope() && Decl == RHS->getRawDecl() &&
|
|
|
|
Name == RHS->getRawName() && File == RHS->getRawFile() &&
|
|
|
|
LineNo == RHS->getLineNo();
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned getHashValue() const {
|
|
|
|
return hash_combine(Scope, Decl, Name, File, LineNo);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2015-06-30 07:03:47 +08:00
|
|
|
template <> struct MDNodeKeyImpl<DIModule> {
|
2020-05-08 14:01:41 +08:00
|
|
|
Metadata *File;
|
2015-06-30 07:03:47 +08:00
|
|
|
Metadata *Scope;
|
2016-03-19 09:02:34 +08:00
|
|
|
MDString *Name;
|
|
|
|
MDString *ConfigurationMacros;
|
|
|
|
MDString *IncludePath;
|
2020-03-04 08:05:23 +08:00
|
|
|
MDString *APINotesFile;
|
2020-05-08 14:01:41 +08:00
|
|
|
unsigned LineNo;
|
2017-06-20 06:05:08 +08:00
|
|
|
|
2020-05-08 14:01:41 +08:00
|
|
|
MDNodeKeyImpl(Metadata *File, Metadata *Scope, MDString *Name,
|
|
|
|
MDString *ConfigurationMacros, MDString *IncludePath,
|
|
|
|
MDString *APINotesFile, unsigned LineNo)
|
|
|
|
: File(File), Scope(Scope), Name(Name),
|
|
|
|
ConfigurationMacros(ConfigurationMacros), IncludePath(IncludePath),
|
|
|
|
APINotesFile(APINotesFile), LineNo(LineNo) {}
|
2015-06-30 07:03:47 +08:00
|
|
|
MDNodeKeyImpl(const DIModule *N)
|
2020-05-08 14:01:41 +08:00
|
|
|
: File(N->getRawFile()), Scope(N->getRawScope()), Name(N->getRawName()),
|
2016-03-19 09:02:34 +08:00
|
|
|
ConfigurationMacros(N->getRawConfigurationMacros()),
|
2020-03-04 08:05:23 +08:00
|
|
|
IncludePath(N->getRawIncludePath()),
|
2020-05-08 14:01:41 +08:00
|
|
|
APINotesFile(N->getRawAPINotesFile()), LineNo(N->getLineNo()) {}
|
2015-06-30 07:03:47 +08:00
|
|
|
|
|
|
|
bool isKeyOf(const DIModule *RHS) const {
|
2016-03-19 09:02:34 +08:00
|
|
|
return Scope == RHS->getRawScope() && Name == RHS->getRawName() &&
|
|
|
|
ConfigurationMacros == RHS->getRawConfigurationMacros() &&
|
2020-03-04 08:05:23 +08:00
|
|
|
IncludePath == RHS->getRawIncludePath() &&
|
2020-05-08 14:01:41 +08:00
|
|
|
APINotesFile == RHS->getRawAPINotesFile() &&
|
|
|
|
File == RHS->getRawFile() && LineNo == RHS->getLineNo();
|
2015-06-30 07:03:47 +08:00
|
|
|
}
|
2017-06-20 06:05:08 +08:00
|
|
|
|
2015-06-30 07:03:47 +08:00
|
|
|
unsigned getHashValue() const {
|
2020-01-15 05:37:04 +08:00
|
|
|
return hash_combine(Scope, Name, ConfigurationMacros, IncludePath);
|
2015-06-30 07:03:47 +08:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2015-04-30 00:38:44 +08:00
|
|
|
template <> struct MDNodeKeyImpl<DITemplateTypeParameter> {
|
2016-03-19 09:02:34 +08:00
|
|
|
MDString *Name;
|
2015-02-10 08:52:32 +08:00
|
|
|
Metadata *Type;
|
2020-03-02 13:22:12 +08:00
|
|
|
bool IsDefault;
|
2015-02-10 08:52:32 +08:00
|
|
|
|
2020-03-02 13:22:12 +08:00
|
|
|
MDNodeKeyImpl(MDString *Name, Metadata *Type, bool IsDefault)
|
|
|
|
: Name(Name), Type(Type), IsDefault(IsDefault) {}
|
2015-04-30 00:38:44 +08:00
|
|
|
MDNodeKeyImpl(const DITemplateTypeParameter *N)
|
2020-03-02 13:22:12 +08:00
|
|
|
: Name(N->getRawName()), Type(N->getRawType()),
|
|
|
|
IsDefault(N->isDefault()) {}
|
2015-02-10 08:52:32 +08:00
|
|
|
|
2015-04-30 00:38:44 +08:00
|
|
|
bool isKeyOf(const DITemplateTypeParameter *RHS) const {
|
2020-03-02 13:22:12 +08:00
|
|
|
return Name == RHS->getRawName() && Type == RHS->getRawType() &&
|
|
|
|
IsDefault == RHS->isDefault();
|
2015-02-10 08:52:32 +08:00
|
|
|
}
|
2017-06-20 06:05:08 +08:00
|
|
|
|
2020-03-02 13:22:12 +08:00
|
|
|
unsigned getHashValue() const { return hash_combine(Name, Type, IsDefault); }
|
2015-02-10 08:52:32 +08:00
|
|
|
};
|
|
|
|
|
2015-04-30 00:38:44 +08:00
|
|
|
template <> struct MDNodeKeyImpl<DITemplateValueParameter> {
|
2015-02-10 08:52:32 +08:00
|
|
|
unsigned Tag;
|
2016-03-19 09:02:34 +08:00
|
|
|
MDString *Name;
|
2015-02-10 08:52:32 +08:00
|
|
|
Metadata *Type;
|
2020-03-02 13:22:12 +08:00
|
|
|
bool IsDefault;
|
2015-02-10 08:52:32 +08:00
|
|
|
Metadata *Value;
|
|
|
|
|
2020-03-02 13:22:12 +08:00
|
|
|
MDNodeKeyImpl(unsigned Tag, MDString *Name, Metadata *Type, bool IsDefault,
|
|
|
|
Metadata *Value)
|
|
|
|
: Tag(Tag), Name(Name), Type(Type), IsDefault(IsDefault), Value(Value) {}
|
2015-04-30 00:38:44 +08:00
|
|
|
MDNodeKeyImpl(const DITemplateValueParameter *N)
|
2016-03-19 09:02:34 +08:00
|
|
|
: Tag(N->getTag()), Name(N->getRawName()), Type(N->getRawType()),
|
2020-03-02 13:22:12 +08:00
|
|
|
IsDefault(N->isDefault()), Value(N->getValue()) {}
|
2015-02-10 08:52:32 +08:00
|
|
|
|
2015-04-30 00:38:44 +08:00
|
|
|
bool isKeyOf(const DITemplateValueParameter *RHS) const {
|
2016-03-19 09:02:34 +08:00
|
|
|
return Tag == RHS->getTag() && Name == RHS->getRawName() &&
|
2020-03-02 13:22:12 +08:00
|
|
|
Type == RHS->getRawType() && IsDefault == RHS->isDefault() &&
|
|
|
|
Value == RHS->getValue();
|
2015-02-10 08:52:32 +08:00
|
|
|
}
|
2017-06-20 06:05:08 +08:00
|
|
|
|
2020-03-02 13:22:12 +08:00
|
|
|
unsigned getHashValue() const {
|
|
|
|
return hash_combine(Tag, Name, Type, IsDefault, Value);
|
|
|
|
}
|
2015-02-10 08:52:32 +08:00
|
|
|
};
|
|
|
|
|
2015-04-30 00:38:44 +08:00
|
|
|
template <> struct MDNodeKeyImpl<DIGlobalVariable> {
|
2015-02-10 08:52:32 +08:00
|
|
|
Metadata *Scope;
|
2016-03-19 09:02:34 +08:00
|
|
|
MDString *Name;
|
|
|
|
MDString *LinkageName;
|
2015-02-10 08:52:32 +08:00
|
|
|
Metadata *File;
|
|
|
|
unsigned Line;
|
|
|
|
Metadata *Type;
|
|
|
|
bool IsLocalToUnit;
|
|
|
|
bool IsDefinition;
|
|
|
|
Metadata *StaticDataMemberDeclaration;
|
2018-10-04 02:44:53 +08:00
|
|
|
Metadata *TemplateParams;
|
2016-10-27 05:32:29 +08:00
|
|
|
uint32_t AlignInBits;
|
2015-02-10 08:52:32 +08:00
|
|
|
|
2016-03-19 09:02:34 +08:00
|
|
|
MDNodeKeyImpl(Metadata *Scope, MDString *Name, MDString *LinkageName,
|
2015-02-10 08:52:32 +08:00
|
|
|
Metadata *File, unsigned Line, Metadata *Type,
|
2016-10-20 08:13:12 +08:00
|
|
|
bool IsLocalToUnit, bool IsDefinition,
|
2018-10-04 02:44:53 +08:00
|
|
|
Metadata *StaticDataMemberDeclaration, Metadata *TemplateParams,
|
|
|
|
uint32_t AlignInBits)
|
2015-02-10 08:52:32 +08:00
|
|
|
: Scope(Scope), Name(Name), LinkageName(LinkageName), File(File),
|
|
|
|
Line(Line), Type(Type), IsLocalToUnit(IsLocalToUnit),
|
2016-12-20 10:09:43 +08:00
|
|
|
IsDefinition(IsDefinition),
|
2016-10-20 08:13:12 +08:00
|
|
|
StaticDataMemberDeclaration(StaticDataMemberDeclaration),
|
2018-10-04 02:44:53 +08:00
|
|
|
TemplateParams(TemplateParams), AlignInBits(AlignInBits) {}
|
2015-04-30 00:38:44 +08:00
|
|
|
MDNodeKeyImpl(const DIGlobalVariable *N)
|
2016-03-19 09:02:34 +08:00
|
|
|
: Scope(N->getRawScope()), Name(N->getRawName()),
|
|
|
|
LinkageName(N->getRawLinkageName()), File(N->getRawFile()),
|
2015-03-28 01:29:58 +08:00
|
|
|
Line(N->getLine()), Type(N->getRawType()),
|
2015-02-10 08:52:32 +08:00
|
|
|
IsLocalToUnit(N->isLocalToUnit()), IsDefinition(N->isDefinition()),
|
2016-10-20 08:13:12 +08:00
|
|
|
StaticDataMemberDeclaration(N->getRawStaticDataMemberDeclaration()),
|
2018-10-04 02:44:53 +08:00
|
|
|
TemplateParams(N->getRawTemplateParams()),
|
2016-10-20 08:13:12 +08:00
|
|
|
AlignInBits(N->getAlignInBits()) {}
|
2015-02-10 08:52:32 +08:00
|
|
|
|
2015-04-30 00:38:44 +08:00
|
|
|
bool isKeyOf(const DIGlobalVariable *RHS) const {
|
2016-03-19 09:02:34 +08:00
|
|
|
return Scope == RHS->getRawScope() && Name == RHS->getRawName() &&
|
|
|
|
LinkageName == RHS->getRawLinkageName() &&
|
|
|
|
File == RHS->getRawFile() && Line == RHS->getLine() &&
|
|
|
|
Type == RHS->getRawType() && IsLocalToUnit == RHS->isLocalToUnit() &&
|
2015-02-10 08:52:32 +08:00
|
|
|
IsDefinition == RHS->isDefinition() &&
|
2015-03-28 01:29:58 +08:00
|
|
|
StaticDataMemberDeclaration ==
|
2016-10-20 08:13:12 +08:00
|
|
|
RHS->getRawStaticDataMemberDeclaration() &&
|
2018-10-04 02:44:53 +08:00
|
|
|
TemplateParams == RHS->getRawTemplateParams() &&
|
2016-10-20 08:13:12 +08:00
|
|
|
AlignInBits == RHS->getAlignInBits();
|
2015-02-10 08:52:32 +08:00
|
|
|
}
|
2017-06-20 06:05:08 +08:00
|
|
|
|
2015-02-10 08:52:32 +08:00
|
|
|
unsigned getHashValue() const {
|
2016-10-20 08:13:12 +08:00
|
|
|
// We do not use AlignInBits in hashing function here on purpose:
|
|
|
|
// in most cases this param for local variable is zero (for function param
|
|
|
|
// it is always zero). This leads to lots of hash collisions and errors on
|
|
|
|
// cases with lots of similar variables.
|
|
|
|
// clang/test/CodeGen/debug-info-257-args.c is an example of this problem,
|
|
|
|
// generated IR is random for each run and test fails with Align included.
|
|
|
|
// TODO: make hashing work fine with such situations
|
2015-02-10 08:52:32 +08:00
|
|
|
return hash_combine(Scope, Name, LinkageName, File, Line, Type,
|
2016-12-20 10:09:43 +08:00
|
|
|
IsLocalToUnit, IsDefinition, /* AlignInBits, */
|
2015-02-10 08:52:32 +08:00
|
|
|
StaticDataMemberDeclaration);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2015-04-30 00:38:44 +08:00
|
|
|
template <> struct MDNodeKeyImpl<DILocalVariable> {
|
2015-02-10 08:52:32 +08:00
|
|
|
Metadata *Scope;
|
2016-03-19 09:02:34 +08:00
|
|
|
MDString *Name;
|
2015-02-10 08:52:32 +08:00
|
|
|
Metadata *File;
|
|
|
|
unsigned Line;
|
|
|
|
Metadata *Type;
|
|
|
|
unsigned Arg;
|
|
|
|
unsigned Flags;
|
2016-10-27 05:32:29 +08:00
|
|
|
uint32_t AlignInBits;
|
2015-02-10 08:52:32 +08:00
|
|
|
|
2016-03-19 09:02:34 +08:00
|
|
|
MDNodeKeyImpl(Metadata *Scope, MDString *Name, Metadata *File, unsigned Line,
|
2016-10-20 08:13:12 +08:00
|
|
|
Metadata *Type, unsigned Arg, unsigned Flags,
|
2016-10-27 05:32:29 +08:00
|
|
|
uint32_t AlignInBits)
|
2015-08-01 02:58:39 +08:00
|
|
|
: Scope(Scope), Name(Name), File(File), Line(Line), Type(Type), Arg(Arg),
|
2016-10-20 08:13:12 +08:00
|
|
|
Flags(Flags), AlignInBits(AlignInBits) {}
|
2015-04-30 00:38:44 +08:00
|
|
|
MDNodeKeyImpl(const DILocalVariable *N)
|
2016-03-19 09:02:34 +08:00
|
|
|
: Scope(N->getRawScope()), Name(N->getRawName()), File(N->getRawFile()),
|
2015-08-01 02:58:39 +08:00
|
|
|
Line(N->getLine()), Type(N->getRawType()), Arg(N->getArg()),
|
2016-10-20 08:13:12 +08:00
|
|
|
Flags(N->getFlags()), AlignInBits(N->getAlignInBits()) {}
|
2015-02-10 08:52:32 +08:00
|
|
|
|
2015-04-30 00:38:44 +08:00
|
|
|
bool isKeyOf(const DILocalVariable *RHS) const {
|
2016-03-19 09:02:34 +08:00
|
|
|
return Scope == RHS->getRawScope() && Name == RHS->getRawName() &&
|
2015-08-01 02:58:39 +08:00
|
|
|
File == RHS->getRawFile() && Line == RHS->getLine() &&
|
|
|
|
Type == RHS->getRawType() && Arg == RHS->getArg() &&
|
2016-10-20 08:13:12 +08:00
|
|
|
Flags == RHS->getFlags() && AlignInBits == RHS->getAlignInBits();
|
2015-02-10 08:52:32 +08:00
|
|
|
}
|
2017-06-20 06:05:08 +08:00
|
|
|
|
2015-02-10 08:52:32 +08:00
|
|
|
unsigned getHashValue() const {
|
2016-10-20 08:13:12 +08:00
|
|
|
// We do not use AlignInBits in hashing function here on purpose:
|
|
|
|
// in most cases this param for local variable is zero (for function param
|
|
|
|
// it is always zero). This leads to lots of hash collisions and errors on
|
|
|
|
// cases with lots of similar variables.
|
|
|
|
// clang/test/CodeGen/debug-info-257-args.c is an example of this problem,
|
|
|
|
// generated IR is random for each run and test fails with Align included.
|
|
|
|
// TODO: make hashing work fine with such situations
|
2015-08-01 02:58:39 +08:00
|
|
|
return hash_combine(Scope, Name, File, Line, Type, Arg, Flags);
|
2015-02-10 08:52:32 +08:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
[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
|
|
|
template <> struct MDNodeKeyImpl<DILabel> {
|
|
|
|
Metadata *Scope;
|
|
|
|
MDString *Name;
|
|
|
|
Metadata *File;
|
|
|
|
unsigned Line;
|
|
|
|
|
|
|
|
MDNodeKeyImpl(Metadata *Scope, MDString *Name, Metadata *File, unsigned Line)
|
|
|
|
: Scope(Scope), Name(Name), File(File), Line(Line) {}
|
|
|
|
MDNodeKeyImpl(const DILabel *N)
|
|
|
|
: Scope(N->getRawScope()), Name(N->getRawName()), File(N->getRawFile()),
|
|
|
|
Line(N->getLine()) {}
|
|
|
|
|
|
|
|
bool isKeyOf(const DILabel *RHS) const {
|
|
|
|
return Scope == RHS->getRawScope() && Name == RHS->getRawName() &&
|
|
|
|
File == RHS->getRawFile() && Line == RHS->getLine();
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Using name and line to get hash value. It should already be mostly unique.
|
|
|
|
unsigned getHashValue() const {
|
|
|
|
return hash_combine(Scope, Name, Line);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2015-04-30 00:38:44 +08:00
|
|
|
template <> struct MDNodeKeyImpl<DIExpression> {
|
2015-02-10 08:52:32 +08:00
|
|
|
ArrayRef<uint64_t> Elements;
|
|
|
|
|
|
|
|
MDNodeKeyImpl(ArrayRef<uint64_t> Elements) : Elements(Elements) {}
|
2015-04-30 00:38:44 +08:00
|
|
|
MDNodeKeyImpl(const DIExpression *N) : Elements(N->getElements()) {}
|
2015-02-10 08:52:32 +08:00
|
|
|
|
2015-04-30 00:38:44 +08:00
|
|
|
bool isKeyOf(const DIExpression *RHS) const {
|
2015-02-10 08:52:32 +08:00
|
|
|
return Elements == RHS->getElements();
|
|
|
|
}
|
2017-06-20 06:05:08 +08:00
|
|
|
|
2015-02-10 08:52:32 +08:00
|
|
|
unsigned getHashValue() const {
|
|
|
|
return hash_combine_range(Elements.begin(), Elements.end());
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2016-12-20 10:09:43 +08:00
|
|
|
template <> struct MDNodeKeyImpl<DIGlobalVariableExpression> {
|
|
|
|
Metadata *Variable;
|
|
|
|
Metadata *Expression;
|
|
|
|
|
|
|
|
MDNodeKeyImpl(Metadata *Variable, Metadata *Expression)
|
|
|
|
: Variable(Variable), Expression(Expression) {}
|
|
|
|
MDNodeKeyImpl(const DIGlobalVariableExpression *N)
|
|
|
|
: Variable(N->getRawVariable()), Expression(N->getRawExpression()) {}
|
|
|
|
|
|
|
|
bool isKeyOf(const DIGlobalVariableExpression *RHS) const {
|
|
|
|
return Variable == RHS->getRawVariable() &&
|
|
|
|
Expression == RHS->getRawExpression();
|
|
|
|
}
|
2017-06-20 06:05:08 +08:00
|
|
|
|
2016-12-20 10:09:43 +08:00
|
|
|
unsigned getHashValue() const { return hash_combine(Variable, Expression); }
|
|
|
|
};
|
|
|
|
|
2015-04-30 00:38:44 +08:00
|
|
|
template <> struct MDNodeKeyImpl<DIObjCProperty> {
|
2016-03-19 09:02:34 +08:00
|
|
|
MDString *Name;
|
2015-02-10 08:52:32 +08:00
|
|
|
Metadata *File;
|
|
|
|
unsigned Line;
|
2016-03-19 09:02:34 +08:00
|
|
|
MDString *GetterName;
|
|
|
|
MDString *SetterName;
|
2015-02-10 08:52:32 +08:00
|
|
|
unsigned Attributes;
|
|
|
|
Metadata *Type;
|
|
|
|
|
2016-03-19 09:02:34 +08:00
|
|
|
MDNodeKeyImpl(MDString *Name, Metadata *File, unsigned Line,
|
|
|
|
MDString *GetterName, MDString *SetterName, unsigned Attributes,
|
2015-02-10 08:52:32 +08:00
|
|
|
Metadata *Type)
|
|
|
|
: Name(Name), File(File), Line(Line), GetterName(GetterName),
|
|
|
|
SetterName(SetterName), Attributes(Attributes), Type(Type) {}
|
2015-04-30 00:38:44 +08:00
|
|
|
MDNodeKeyImpl(const DIObjCProperty *N)
|
2016-03-19 09:02:34 +08:00
|
|
|
: Name(N->getRawName()), File(N->getRawFile()), Line(N->getLine()),
|
|
|
|
GetterName(N->getRawGetterName()), SetterName(N->getRawSetterName()),
|
2015-03-31 01:21:38 +08:00
|
|
|
Attributes(N->getAttributes()), Type(N->getRawType()) {}
|
2015-02-10 08:52:32 +08:00
|
|
|
|
2015-04-30 00:38:44 +08:00
|
|
|
bool isKeyOf(const DIObjCProperty *RHS) const {
|
2016-03-19 09:02:34 +08:00
|
|
|
return Name == RHS->getRawName() && File == RHS->getRawFile() &&
|
|
|
|
Line == RHS->getLine() && GetterName == RHS->getRawGetterName() &&
|
|
|
|
SetterName == RHS->getRawSetterName() &&
|
2015-03-31 01:21:38 +08:00
|
|
|
Attributes == RHS->getAttributes() && Type == RHS->getRawType();
|
2015-02-10 08:52:32 +08:00
|
|
|
}
|
2017-06-20 06:05:08 +08:00
|
|
|
|
2015-02-10 08:52:32 +08:00
|
|
|
unsigned getHashValue() const {
|
|
|
|
return hash_combine(Name, File, Line, GetterName, SetterName, Attributes,
|
|
|
|
Type);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2015-04-30 00:38:44 +08:00
|
|
|
template <> struct MDNodeKeyImpl<DIImportedEntity> {
|
2015-02-10 08:52:32 +08:00
|
|
|
unsigned Tag;
|
|
|
|
Metadata *Scope;
|
|
|
|
Metadata *Entity;
|
2017-07-19 08:09:54 +08:00
|
|
|
Metadata *File;
|
2015-02-10 08:52:32 +08:00
|
|
|
unsigned Line;
|
2016-03-19 09:02:34 +08:00
|
|
|
MDString *Name;
|
2015-02-10 08:52:32 +08:00
|
|
|
|
2017-07-19 08:09:54 +08:00
|
|
|
MDNodeKeyImpl(unsigned Tag, Metadata *Scope, Metadata *Entity, Metadata *File,
|
|
|
|
unsigned Line, MDString *Name)
|
|
|
|
: Tag(Tag), Scope(Scope), Entity(Entity), File(File), Line(Line),
|
|
|
|
Name(Name) {}
|
2015-04-30 00:38:44 +08:00
|
|
|
MDNodeKeyImpl(const DIImportedEntity *N)
|
2015-03-31 01:21:38 +08:00
|
|
|
: Tag(N->getTag()), Scope(N->getRawScope()), Entity(N->getRawEntity()),
|
2017-07-19 08:09:54 +08:00
|
|
|
File(N->getRawFile()), Line(N->getLine()), Name(N->getRawName()) {}
|
2015-02-10 08:52:32 +08:00
|
|
|
|
2015-04-30 00:38:44 +08:00
|
|
|
bool isKeyOf(const DIImportedEntity *RHS) const {
|
2015-03-31 01:21:38 +08:00
|
|
|
return Tag == RHS->getTag() && Scope == RHS->getRawScope() &&
|
2017-07-19 08:09:54 +08:00
|
|
|
Entity == RHS->getRawEntity() && File == RHS->getFile() &&
|
|
|
|
Line == RHS->getLine() && Name == RHS->getRawName();
|
2015-02-10 08:52:32 +08:00
|
|
|
}
|
2017-06-20 06:05:08 +08:00
|
|
|
|
2015-02-10 08:52:32 +08:00
|
|
|
unsigned getHashValue() const {
|
2017-07-19 08:09:54 +08:00
|
|
|
return hash_combine(Tag, Scope, Entity, File, Line, Name);
|
2015-02-10 08:52:32 +08:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2015-12-10 20:56:35 +08:00
|
|
|
template <> struct MDNodeKeyImpl<DIMacro> {
|
|
|
|
unsigned MIType;
|
|
|
|
unsigned Line;
|
2016-03-19 09:02:34 +08:00
|
|
|
MDString *Name;
|
|
|
|
MDString *Value;
|
2015-12-10 20:56:35 +08:00
|
|
|
|
2016-03-19 09:02:34 +08:00
|
|
|
MDNodeKeyImpl(unsigned MIType, unsigned Line, MDString *Name, MDString *Value)
|
2015-12-10 20:56:35 +08:00
|
|
|
: MIType(MIType), Line(Line), Name(Name), Value(Value) {}
|
|
|
|
MDNodeKeyImpl(const DIMacro *N)
|
2016-03-19 09:02:34 +08:00
|
|
|
: MIType(N->getMacinfoType()), Line(N->getLine()), Name(N->getRawName()),
|
|
|
|
Value(N->getRawValue()) {}
|
2015-12-10 20:56:35 +08:00
|
|
|
|
|
|
|
bool isKeyOf(const DIMacro *RHS) const {
|
|
|
|
return MIType == RHS->getMacinfoType() && Line == RHS->getLine() &&
|
2016-03-19 09:02:34 +08:00
|
|
|
Name == RHS->getRawName() && Value == RHS->getRawValue();
|
2015-12-10 20:56:35 +08:00
|
|
|
}
|
2017-06-20 06:05:08 +08:00
|
|
|
|
2015-12-10 20:56:35 +08:00
|
|
|
unsigned getHashValue() const {
|
|
|
|
return hash_combine(MIType, Line, Name, Value);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
template <> struct MDNodeKeyImpl<DIMacroFile> {
|
|
|
|
unsigned MIType;
|
|
|
|
unsigned Line;
|
|
|
|
Metadata *File;
|
|
|
|
Metadata *Elements;
|
|
|
|
|
|
|
|
MDNodeKeyImpl(unsigned MIType, unsigned Line, Metadata *File,
|
|
|
|
Metadata *Elements)
|
|
|
|
: MIType(MIType), Line(Line), File(File), Elements(Elements) {}
|
|
|
|
MDNodeKeyImpl(const DIMacroFile *N)
|
|
|
|
: MIType(N->getMacinfoType()), Line(N->getLine()), File(N->getRawFile()),
|
|
|
|
Elements(N->getRawElements()) {}
|
|
|
|
|
|
|
|
bool isKeyOf(const DIMacroFile *RHS) const {
|
|
|
|
return MIType == RHS->getMacinfoType() && Line == RHS->getLine() &&
|
2016-07-31 22:41:50 +08:00
|
|
|
File == RHS->getRawFile() && Elements == RHS->getRawElements();
|
2015-12-10 20:56:35 +08:00
|
|
|
}
|
2017-06-20 06:05:08 +08:00
|
|
|
|
2015-12-10 20:56:35 +08:00
|
|
|
unsigned getHashValue() const {
|
|
|
|
return hash_combine(MIType, Line, File, Elements);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2018-05-01 23:54:18 +08:00
|
|
|
/// DenseMapInfo for MDNode subclasses.
|
2015-02-05 06:08:30 +08:00
|
|
|
template <class NodeTy> struct MDNodeInfo {
|
2017-06-20 06:05:08 +08:00
|
|
|
using KeyTy = MDNodeKeyImpl<NodeTy>;
|
|
|
|
using SubsetEqualTy = MDNodeSubsetEqualImpl<NodeTy>;
|
|
|
|
|
2015-02-05 06:08:30 +08:00
|
|
|
static inline NodeTy *getEmptyKey() {
|
|
|
|
return DenseMapInfo<NodeTy *>::getEmptyKey();
|
2015-01-20 08:01:43 +08:00
|
|
|
}
|
2017-06-20 06:05:08 +08:00
|
|
|
|
2015-02-05 06:08:30 +08:00
|
|
|
static inline NodeTy *getTombstoneKey() {
|
|
|
|
return DenseMapInfo<NodeTy *>::getTombstoneKey();
|
2015-01-20 08:01:43 +08:00
|
|
|
}
|
2017-06-20 06:05:08 +08:00
|
|
|
|
2015-02-05 06:08:30 +08:00
|
|
|
static unsigned getHashValue(const KeyTy &Key) { return Key.getHashValue(); }
|
2017-06-20 06:05:08 +08:00
|
|
|
|
2015-02-05 06:08:30 +08:00
|
|
|
static unsigned getHashValue(const NodeTy *N) {
|
|
|
|
return KeyTy(N).getHashValue();
|
2015-01-20 08:01:43 +08:00
|
|
|
}
|
2017-06-20 06:05:08 +08:00
|
|
|
|
2015-02-05 06:08:30 +08:00
|
|
|
static bool isEqual(const KeyTy &LHS, const NodeTy *RHS) {
|
|
|
|
if (RHS == getEmptyKey() || RHS == getTombstoneKey())
|
|
|
|
return false;
|
2016-04-17 07:42:04 +08:00
|
|
|
return SubsetEqualTy::isSubsetEqual(LHS, RHS) || LHS.isKeyOf(RHS);
|
2015-01-20 08:01:43 +08:00
|
|
|
}
|
2017-06-20 06:05:08 +08:00
|
|
|
|
2015-02-05 06:08:30 +08:00
|
|
|
static bool isEqual(const NodeTy *LHS, const NodeTy *RHS) {
|
2016-04-17 07:42:04 +08:00
|
|
|
if (LHS == RHS)
|
|
|
|
return true;
|
|
|
|
if (RHS == getEmptyKey() || RHS == getTombstoneKey())
|
|
|
|
return false;
|
|
|
|
return SubsetEqualTy::isSubsetEqual(LHS, RHS);
|
2015-01-20 08:01:43 +08:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2017-06-20 06:05:08 +08:00
|
|
|
#define HANDLE_MDNODE_LEAF(CLASS) using CLASS##Info = MDNodeInfo<CLASS>;
|
2015-02-05 06:08:30 +08:00
|
|
|
#include "llvm/IR/Metadata.def"
|
|
|
|
|
2018-05-01 23:54:18 +08:00
|
|
|
/// Map-like storage for metadata attachments.
|
2015-04-25 04:36:25 +08:00
|
|
|
class MDAttachmentMap {
|
|
|
|
SmallVector<std::pair<unsigned, TrackingMDNodeRef>, 2> Attachments;
|
|
|
|
|
|
|
|
public:
|
|
|
|
bool empty() const { return Attachments.empty(); }
|
|
|
|
size_t size() const { return Attachments.size(); }
|
|
|
|
|
2018-05-01 23:54:18 +08:00
|
|
|
/// Get a particular attachment (if any).
|
2015-04-25 04:36:25 +08:00
|
|
|
MDNode *lookup(unsigned ID) const;
|
|
|
|
|
2018-05-01 23:54:18 +08:00
|
|
|
/// Set an attachment to a particular node.
|
2015-04-25 04:36:25 +08:00
|
|
|
///
|
|
|
|
/// Set the \c ID attachment to \c MD, replacing the current attachment at \c
|
|
|
|
/// ID (if anyway).
|
|
|
|
void set(unsigned ID, MDNode &MD);
|
|
|
|
|
2018-05-01 23:54:18 +08:00
|
|
|
/// Remove an attachment.
|
2015-04-25 04:36:25 +08:00
|
|
|
///
|
|
|
|
/// Remove the attachment at \c ID, if any.
|
2018-05-31 21:29:58 +08:00
|
|
|
bool erase(unsigned ID);
|
2015-04-25 04:36:25 +08:00
|
|
|
|
2018-05-01 23:54:18 +08:00
|
|
|
/// Copy out all the attachments.
|
2015-04-25 04:36:25 +08:00
|
|
|
///
|
|
|
|
/// Copies all the current attachments into \c Result, sorting by attachment
|
|
|
|
/// ID. This function does \em not clear \c Result.
|
|
|
|
void getAll(SmallVectorImpl<std::pair<unsigned, MDNode *>> &Result) const;
|
|
|
|
|
2018-05-01 23:54:18 +08:00
|
|
|
/// Erase matching attachments.
|
2015-04-25 04:36:25 +08:00
|
|
|
///
|
|
|
|
/// Erases all attachments matching the \c shouldRemove predicate.
|
|
|
|
template <class PredTy> void remove_if(PredTy shouldRemove) {
|
2016-08-12 12:32:42 +08:00
|
|
|
Attachments.erase(llvm::remove_if(Attachments, shouldRemove),
|
|
|
|
Attachments.end());
|
2015-04-25 04:36:25 +08:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2016-06-01 09:17:57 +08:00
|
|
|
/// Multimap-like storage for metadata attachments for globals. This differs
|
|
|
|
/// from MDAttachmentMap in that it allows multiple attachments per metadata
|
|
|
|
/// kind.
|
|
|
|
class MDGlobalAttachmentMap {
|
|
|
|
struct Attachment {
|
|
|
|
unsigned MDKind;
|
|
|
|
TrackingMDNodeRef Node;
|
|
|
|
};
|
|
|
|
SmallVector<Attachment, 1> Attachments;
|
|
|
|
|
|
|
|
public:
|
|
|
|
bool empty() const { return Attachments.empty(); }
|
|
|
|
|
|
|
|
/// Appends all attachments with the given ID to \c Result in insertion order.
|
|
|
|
/// If the global has no attachments with the given ID, or if ID is invalid,
|
|
|
|
/// leaves Result unchanged.
|
2018-05-31 21:29:58 +08:00
|
|
|
void get(unsigned ID, SmallVectorImpl<MDNode *> &Result) const;
|
|
|
|
|
|
|
|
/// Returns the first attachment with the given ID or nullptr if no such
|
|
|
|
/// attachment exists.
|
|
|
|
MDNode *lookup(unsigned ID) const;
|
2016-06-01 09:17:57 +08:00
|
|
|
|
|
|
|
void insert(unsigned ID, MDNode &MD);
|
2018-05-31 21:29:58 +08:00
|
|
|
bool erase(unsigned ID);
|
2016-06-01 09:17:57 +08:00
|
|
|
|
|
|
|
/// Appends all attachments for the global to \c Result, sorting by attachment
|
|
|
|
/// ID. Attachments with the same ID appear in insertion order. This function
|
|
|
|
/// does \em not clear \c Result.
|
|
|
|
void getAll(SmallVectorImpl<std::pair<unsigned, MDNode *>> &Result) const;
|
|
|
|
};
|
|
|
|
|
2013-09-12 02:05:11 +08:00
|
|
|
class LLVMContextImpl {
|
2009-08-12 01:45:13 +08:00
|
|
|
public:
|
2010-09-09 02:03:32 +08: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;
|
2018-07-31 03:41:25 +08:00
|
|
|
|
2017-06-20 06:05:08 +08:00
|
|
|
LLVMContext::InlineAsmDiagHandlerTy InlineAsmDiagHandler = nullptr;
|
|
|
|
void *InlineAsmDiagContext = nullptr;
|
2013-12-18 01:47:22 +08:00
|
|
|
|
2019-10-29 05:53:31 +08:00
|
|
|
/// The main remark streamer used by all the other streamers (e.g. IR, MIR,
|
|
|
|
/// frontends, etc.). This should only be used by the specific streamers, and
|
|
|
|
/// never directly.
|
|
|
|
std::unique_ptr<remarks::RemarkStreamer> MainRemarkStreamer;
|
|
|
|
|
2017-09-16 04:10:09 +08:00
|
|
|
std::unique_ptr<DiagnosticHandler> DiagHandler;
|
2017-06-20 06:05:08 +08:00
|
|
|
bool RespectDiagnosticFilters = false;
|
[ORE] Unify spelling as "diagnostics hotness"
Summary:
To enable profile hotness information in diagnostics output, Clang takes
the option `-fdiagnostics-show-hotness` -- that's "diagnostics", with an
"s" at the end. Clang also defines `CodeGenOptions::DiagnosticsWithHotness`.
LLVM, on the other hand, defines
`LLVMContext::getDiagnosticHotnessRequested` -- that's "diagnostic", not
"diagnostics". It's a small difference, but it's confusing, typo-inducing, and
frustrating.
Add a new method with the spelling "diagnostics", and "deprecate" the
old spelling.
Reviewers: anemet, davidxl
Reviewed By: anemet
Subscribers: llvm-commits, mehdi_amini
Differential Revision: https://reviews.llvm.org/D34864
llvm-svn: 306848
2017-07-01 02:13:59 +08:00
|
|
|
bool DiagnosticsHotnessRequested = false;
|
2017-07-01 07:14:53 +08:00
|
|
|
uint64_t DiagnosticsHotnessThreshold = 0;
|
2019-10-29 05:53:31 +08:00
|
|
|
/// The specialized remark streamer used by LLVM's OptimizationRemarkEmitter.
|
2020-02-05 09:42:47 +08:00
|
|
|
std::unique_ptr<LLVMRemarkStreamer> LLVMRS;
|
2013-12-18 01:47:22 +08:00
|
|
|
|
2017-06-20 06:05:08 +08:00
|
|
|
LLVMContext::YieldCallbackTy YieldCallback = nullptr;
|
|
|
|
void *YieldOpaqueHandle = nullptr;
|
2014-05-16 10:33:15 +08:00
|
|
|
|
2017-06-20 06:05:08 +08:00
|
|
|
using IntMapTy =
|
|
|
|
DenseMap<APInt, std::unique_ptr<ConstantInt>, DenseMapAPIntKeyInfo>;
|
2009-07-17 02:04:31 +08:00
|
|
|
IntMapTy IntConstants;
|
2014-12-06 13:57:06 +08:00
|
|
|
|
2017-06-20 06:05:08 +08:00
|
|
|
using FPMapTy =
|
|
|
|
DenseMap<APFloat, std::unique_ptr<ConstantFP>, DenseMapAPFloatKeyInfo>;
|
2009-07-17 03:05:41 +08:00
|
|
|
FPMapTy FPConstants;
|
2012-09-27 05:07:29 +08:00
|
|
|
|
2012-12-20 09:36:59 +08:00
|
|
|
FoldingSet<AttributeImpl> AttrsSet;
|
Rename AttributeSet to AttributeList
Summary:
This class is a list of AttributeSetNodes corresponding the function
prototype of a call or function declaration. This class used to be
called ParamAttrListPtr, then AttrListPtr, then AttributeSet. It is
typically accessed by parameter and return value index, so
"AttributeList" seems like a more intuitive name.
Rename AttributeSetImpl to AttributeListImpl to follow suit.
It's useful to rename this class so that we can rename AttributeSetNode
to AttributeSet later. AttributeSet is the set of attributes that apply
to a single function, argument, or return value.
Reviewers: sanjoy, javed.absar, chandlerc, pete
Reviewed By: pete
Subscribers: pete, jholewinski, arsenm, dschuff, mehdi_amini, jfb, nhaehnle, sbc100, void, llvm-commits
Differential Revision: https://reviews.llvm.org/D31102
llvm-svn: 298393
2017-03-22 00:57:19 +08:00
|
|
|
FoldingSet<AttributeListImpl> AttrsLists;
|
2013-01-24 08:06:56 +08:00
|
|
|
FoldingSet<AttributeSetNode> AttrsSetNodes;
|
2012-11-20 13:09:20 +08:00
|
|
|
|
2016-04-06 14:41:54 +08:00
|
|
|
StringMap<MDString, BumpPtrAllocator> 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.)
llvm-svn: 223802
2014-12-10 02:38:53 +08:00
|
|
|
DenseMap<Value *, ValueAsMetadata *> ValuesAsMetadata;
|
|
|
|
DenseMap<Metadata *, MetadataAsValue *> MetadataAsValues;
|
2012-09-27 05:07:29 +08:00
|
|
|
|
2015-06-02 06:24:01 +08:00
|
|
|
DenseMap<const Value*, ValueName*> ValueNames;
|
|
|
|
|
2015-08-04 01:26:41 +08:00
|
|
|
#define HANDLE_MDNODE_LEAF_UNIQUABLE(CLASS) \
|
|
|
|
DenseSet<CLASS *, CLASS##Info> CLASS##s;
|
2015-02-05 05:46:12 +08:00
|
|
|
#include "llvm/IR/Metadata.def"
|
2012-09-27 05:07:29 +08:00
|
|
|
|
2016-04-17 11:58:21 +08:00
|
|
|
// Optional map for looking up composite types by identifier.
|
2016-04-20 00:06:50 +08:00
|
|
|
Optional<DenseMap<const MDString *, DICompositeType *>> DITypeMap;
|
2016-04-17 11:58:21 +08:00
|
|
|
|
2010-03-13 09:26:15 +08: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
|
2016-04-20 07:59:13 +08:00
|
|
|
// one object can destroy them. Keep track of them here so we can delete
|
|
|
|
// them on context teardown.
|
|
|
|
std::vector<MDNode *> DistinctMDNodes;
|
2014-11-18 08:37:17 +08:00
|
|
|
|
2016-10-11 00:26:13 +08:00
|
|
|
DenseMap<Type *, std::unique_ptr<ConstantAggregateZero>> CAZConstants;
|
2009-08-11 02:16:08 +08:00
|
|
|
|
2017-06-20 06:05:08 +08:00
|
|
|
using ArrayConstantsTy = ConstantUniqueMap<ConstantArray>;
|
2009-07-25 07:12:02 +08:00
|
|
|
ArrayConstantsTy ArrayConstants;
|
2018-07-31 03:41:25 +08:00
|
|
|
|
2017-06-20 06:05:08 +08:00
|
|
|
using StructConstantsTy = ConstantUniqueMap<ConstantStruct>;
|
2009-07-25 07:12:02 +08:00
|
|
|
StructConstantsTy StructConstants;
|
2018-07-31 03:41:25 +08:00
|
|
|
|
2017-06-20 06:05:08 +08:00
|
|
|
using VectorConstantsTy = ConstantUniqueMap<ConstantVector>;
|
2009-07-25 07:12:02 +08:00
|
|
|
VectorConstantsTy VectorConstants;
|
2012-01-23 23:20:12 +08:00
|
|
|
|
2016-10-11 00:26:13 +08:00
|
|
|
DenseMap<PointerType *, std::unique_ptr<ConstantPointerNull>> CPNConstants;
|
|
|
|
|
|
|
|
DenseMap<Type *, std::unique_ptr<UndefValue>> UVConstants;
|
|
|
|
|
2012-01-24 06:57:10 +08:00
|
|
|
StringMap<ConstantDataSequential*> CDSConstants;
|
|
|
|
|
2014-01-19 10:13:50 +08:00
|
|
|
DenseMap<std::pair<const Function *, const BasicBlock *>, BlockAddress *>
|
|
|
|
BlockAddresses;
|
2014-08-20 00:39:58 +08:00
|
|
|
ConstantUniqueMap<ConstantExpr> ExprConstants;
|
|
|
|
|
|
|
|
ConstantUniqueMap<InlineAsm> InlineAsms;
|
2014-08-19 09:02:18 +08:00
|
|
|
|
2017-06-20 06:05:08 +08:00
|
|
|
ConstantInt *TheTrueVal = nullptr;
|
|
|
|
ConstantInt *TheFalseVal = nullptr;
|
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.)
llvm-svn: 223802
2014-12-10 02:38:53 +08:00
|
|
|
|
2015-11-17 04:55:57 +08:00
|
|
|
std::unique_ptr<ConstantTokenNone> TheNoneToken;
|
2015-11-12 05:57:16 +08:00
|
|
|
|
2009-08-26 00:00:35 +08:00
|
|
|
// Basic type instances.
|
[IR][BFloat] Add BFloat IR type
Summary:
The BFloat IR type is introduced to provide support for, initially, the BFloat16
datatype introduced with the Armv8.6 architecture (optional from Armv8.2
onwards). It has an 8-bit exponent and a 7-bit mantissa and behaves like an IEEE
754 floating point IR type.
This is part of a patch series upstreaming Armv8.6 features. Subsequent patches
will upstream intrinsics support and C-lang support for BFloat.
Reviewers: SjoerdMeijer, rjmccall, rsmith, liutianle, RKSimon, craig.topper, jfb, LukeGeeson, sdesmalen, deadalnix, ctetreau
Subscribers: hiraditya, llvm-commits, danielkiss, arphaman, kristof.beyls, dexonsmith
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D78190
2020-04-01 06:49:38 +08:00
|
|
|
Type VoidTy, LabelTy, HalfTy, BFloatTy, FloatTy, DoubleTy, MetadataTy,
|
|
|
|
TokenTy;
|
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.
llvm-svn: 134829
2011-07-10 01:41:24 +08:00
|
|
|
Type X86_FP80Ty, FP128Ty, PPC_FP128Ty, X86_MMXTy;
|
2015-04-17 23:32:15 +08:00
|
|
|
IntegerType Int1Ty, Int8Ty, Int16Ty, Int32Ty, Int64Ty, Int128Ty;
|
2018-07-31 03:41:25 +08:00
|
|
|
|
2019-05-29 11:28:51 +08:00
|
|
|
BumpPtrAllocator Alloc;
|
|
|
|
UniqueStringSaver Saver{Alloc};
|
2018-07-31 03:41:25 +08:00
|
|
|
|
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.
llvm-svn: 134829
2011-07-10 01:41:24 +08:00
|
|
|
DenseMap<unsigned, IntegerType*> IntegerTypes;
|
2014-12-07 03:22:54 +08:00
|
|
|
|
2017-06-20 06:05:08 +08:00
|
|
|
using FunctionTypeSet = DenseSet<FunctionType *, FunctionTypeKeyInfo>;
|
2014-12-07 03:22:54 +08:00
|
|
|
FunctionTypeSet FunctionTypes;
|
2017-06-20 06:05:08 +08:00
|
|
|
using StructTypeSet = DenseSet<StructType *, AnonStructTypeKeyInfo>;
|
2014-12-07 03:22:54 +08:00
|
|
|
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.
llvm-svn: 134829
2011-07-10 01:41:24 +08:00
|
|
|
StringMap<StructType*> NamedStructTypes;
|
2017-06-20 06:05:08 +08:00
|
|
|
unsigned NamedStructTypesUniqueID = 0;
|
2018-07-31 03:41:25 +08:00
|
|
|
|
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.
llvm-svn: 134829
2011-07-10 01:41:24 +08:00
|
|
|
DenseMap<std::pair<Type *, uint64_t>, ArrayType*> ArrayTypes;
|
2019-07-05 20:48:16 +08:00
|
|
|
DenseMap<std::pair<Type *, ElementCount>, VectorType*> VectorTypes;
|
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.
llvm-svn: 134829
2011-07-10 01:41:24 +08:00
|
|
|
DenseMap<Type*, PointerType*> PointerTypes; // Pointers in AddrSpace = 0
|
|
|
|
DenseMap<std::pair<Type*, unsigned>, PointerType*> ASPointerTypes;
|
2010-02-11 14:41:30 +08:00
|
|
|
|
2009-08-19 02:28:58 +08: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-02 02:48:54 +08:00
|
|
|
/// whether or not a value has an entry in this map.
|
2017-06-20 06:05:08 +08:00
|
|
|
using ValueHandlesTy = DenseMap<Value *, ValueHandleBase *>;
|
2009-08-19 02:28:58 +08:00
|
|
|
ValueHandlesTy ValueHandles;
|
2018-07-31 03:41:25 +08:00
|
|
|
|
2009-12-29 17:01:33 +08: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.)
llvm-svn: 223802
2014-12-10 02:38:53 +08:00
|
|
|
|
2015-04-25 04:16:42 +08:00
|
|
|
/// Collection of per-instruction metadata used in this context.
|
2015-04-25 04:36:25 +08:00
|
|
|
DenseMap<const Instruction *, MDAttachmentMap> InstructionMetadata;
|
2015-04-25 04:16:42 +08:00
|
|
|
|
2016-06-01 07:01:54 +08:00
|
|
|
/// Collection of per-GlobalObject metadata used in this context.
|
2016-06-01 09:17:57 +08:00
|
|
|
DenseMap<const GlobalObject *, MDGlobalAttachmentMap> GlobalObjectMetadata;
|
2015-04-25 05:51:02 +08:00
|
|
|
|
Move the section name from GlobalObject to the LLVMContext
Summary:
Convention wisdom says that bytes in Function are precious, and the
vast, vast majority of globals do not live in special sections. Even
when they do, they tend to live in the same section. Store the section
name on the LLVMContext in a StringSet, and maintain a map from
GlobalObject* to section name like we do for metadata, prefix data, etc.
The fact that we've survived this long wasting at least three pointers
of space in Function suggests that Function bytes are perhaps not as
precious as we once thought. Given that most functions have metadata
attachments when debug info is enabled, we might consider adding a
pointer here to make that access more efficient.
Reviewers: jlebar, dexonsmith, mehdi_amini
Subscribers: mehdi_amini, aprantl, llvm-commits
Differential Revision: https://reviews.llvm.org/D28150
llvm-svn: 291613
2017-01-11 07:23:58 +08:00
|
|
|
/// Collection of per-GlobalObject sections used in this context.
|
|
|
|
DenseMap<const GlobalObject *, StringRef> GlobalObjectSections;
|
|
|
|
|
2019-05-29 11:29:01 +08:00
|
|
|
/// Collection of per-GlobalValue partitions used in this context.
|
|
|
|
DenseMap<const GlobalValue *, StringRef> GlobalValuePartitions;
|
|
|
|
|
2014-03-04 04:06:11 +08: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;
|
|
|
|
|
2018-05-01 23:54:18 +08:00
|
|
|
/// A set of interned tags for operand bundles. The StringMap maps
|
2015-09-25 03:14:18 +08:00
|
|
|
/// bundle tags to their IDs.
|
|
|
|
///
|
|
|
|
/// \see LLVMContext::getOperandBundleTagID
|
|
|
|
StringMap<uint32_t> BundleTagCache;
|
|
|
|
|
|
|
|
StringMapEntry<uint32_t> *getOrInsertBundleTag(StringRef Tag);
|
|
|
|
void getOperandBundleTags(SmallVectorImpl<StringRef> &Tags) const;
|
|
|
|
uint32_t getOperandBundleTagID(StringRef Tag) const;
|
|
|
|
|
2017-07-12 06:23:00 +08:00
|
|
|
/// A set of interned synchronization scopes. The StringMap maps
|
|
|
|
/// synchronization scope names to their respective synchronization scope IDs.
|
|
|
|
StringMap<SyncScope::ID> SSC;
|
|
|
|
|
|
|
|
/// getOrInsertSyncScopeID - Maps synchronization scope name to
|
|
|
|
/// synchronization scope ID. Every synchronization scope registered with
|
|
|
|
/// LLVMContext has unique ID except pre-defined ones.
|
|
|
|
SyncScope::ID getOrInsertSyncScopeID(StringRef SSN);
|
|
|
|
|
|
|
|
/// getSyncScopeNames - Populates client supplied SmallVector with
|
|
|
|
/// synchronization scope names registered with LLVMContext. Synchronization
|
|
|
|
/// scope names are ordered by increasing synchronization scope IDs.
|
|
|
|
void getSyncScopeNames(SmallVectorImpl<StringRef> &SSNs) const;
|
|
|
|
|
2016-01-08 10:28:20 +08:00
|
|
|
/// Maintain the GC name for each function.
|
|
|
|
///
|
|
|
|
/// This saves allocating an additional word in Function for programs which
|
|
|
|
/// do not use GC (i.e., most programs) at the cost of increased overhead for
|
|
|
|
/// clients which do use GC.
|
|
|
|
DenseMap<const Function*, std::string> GCNames;
|
|
|
|
|
Add a flag to the LLVMContext to disable name for Value other than GlobalValue
Summary:
This is intended to be a performance flag, on the same level as clang
cc1 option "--disable-free". LLVM will never initialize it by default,
it will be up to the client creating the LLVMContext to request this
behavior. Clang will do it by default in Release build (just like
--disable-free).
"opt" and "llc" can opt-in using -disable-named-value command line
option.
When performing LTO on llvm-tblgen, the initial merging of IR peaks
at 92MB without this patch, and 86MB after this patch,setNameImpl()
drops from 6.5MB to 0.5MB.
The total link time goes from ~29.5s to ~27.8s.
Compared to a compile-time flag (like the IRBuilder one), it performs
very close. I profiled on SROA and obtain these results:
420ms with IRBuilder that preserve name
372ms with IRBuilder that strip name
375ms with IRBuilder that preserve name, and a runtime flag to strip
Reviewers: chandlerc, dexonsmith, bogner
Subscribers: joker.eph, llvm-commits
Differential Revision: http://reviews.llvm.org/D17946
From: Mehdi Amini <mehdi.amini@apple.com>
llvm-svn: 263086
2016-03-10 09:28:54 +08:00
|
|
|
/// Flag to indicate if Value (other than GlobalValue) retains their name or
|
|
|
|
/// not.
|
|
|
|
bool DiscardValueNames = false;
|
|
|
|
|
2010-03-22 05:17:34 +08:00
|
|
|
LLVMContextImpl(LLVMContext &C);
|
|
|
|
~LLVMContextImpl();
|
2015-01-21 03:24:59 +08:00
|
|
|
|
|
|
|
/// Destroy the ConstantArrays if they are not used.
|
|
|
|
void dropTriviallyDeadConstantArrays();
|
2016-04-23 06:06:11 +08:00
|
|
|
|
2018-04-05 18:29:37 +08:00
|
|
|
mutable OptPassGate *OPG = nullptr;
|
|
|
|
|
2018-05-01 23:54:18 +08:00
|
|
|
/// Access the object which can disable optional passes and individual
|
2018-04-05 18:29:37 +08:00
|
|
|
/// optimizations at compile time.
|
|
|
|
OptPassGate &getOptPassGate() const;
|
|
|
|
|
2018-05-01 23:54:18 +08:00
|
|
|
/// Set the object which can disable optional passes and individual
|
2018-04-05 18:29:37 +08:00
|
|
|
/// optimizations at compile time.
|
|
|
|
///
|
|
|
|
/// The lifetime of the object must be guaranteed to extend as long as the
|
|
|
|
/// LLVMContext is used by compilation.
|
|
|
|
void setOptPassGate(OptPassGate&);
|
2009-06-30 08:48:55 +08:00
|
|
|
};
|
|
|
|
|
2017-06-20 06:05:08 +08:00
|
|
|
} // end namespace llvm
|
2009-06-30 08:48:55 +08:00
|
|
|
|
2017-06-20 06:05:08 +08:00
|
|
|
#endif // LLVM_LIB_IR_LLVMCONTEXTIMPL_H
|