1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
|
//===-- Support/Annotation.h - Annotation classes ---------------*- C++ -*-===//
//
// This file contains the declarations for two classes: Annotation & Annotable.
// Using these two simple classes, anything that derives from Annotable can have
// Annotation subclasses attached to them, ready for easy retrieval.
//
// Annotations are designed to be easily attachable to various classes.
//
// The AnnotationManager class is essential for using these classes. It is
// responsible for turning Annotation name strings into tokens [unique id #'s]
// that may be used to search for and create annotations.
//
//===----------------------------------------------------------------------===//
#ifndef SUPPORT_ANNOTATION_H
#define SUPPORT_ANNOTATION_H
#include <string>
class AnnotationID;
class Annotation;
class Annotable;
class AnnotationManager;
//===----------------------------------------------------------------------===//
//
// AnnotationID - This class is a thin wrapper around an unsigned integer that
// is used to hopefully prevent errors using AnnotationID's. They may be copied
// freely around and passed byvalue with little or no overhead.
//
class AnnotationID {
friend class AnnotationManager;
unsigned ID;
AnnotationID(); // Default ctor is disabled
inline AnnotationID(unsigned i) : ID(i) {} // Only creatable from AnnMgr
public:
inline AnnotationID(const AnnotationID &A) : ID(A.ID) {}
inline bool operator==(const AnnotationID &A) const {
return A.ID == ID;
}
inline bool operator<(const AnnotationID &A) const {
return ID < A.ID;
}
};
//===----------------------------------------------------------------------===//
//
// Annotation Class - This class serves as a base class for any specific
// annotations that you might need. Simply subclass this to add extra
// information to the annotations.
//
class Annotation {
friend class Annotable; // Annotable manipulates Next list
AnnotationID ID; // ID number, as obtained from AnnotationManager
Annotation *Next; // The next annotation in the linked list
public:
inline Annotation(AnnotationID id) : ID(id), Next(0) {}
virtual ~Annotation() {} // Designed to be subclassed
// getID - Return the unique ID# of this annotation
inline AnnotationID getID() const { return ID; }
// getNext - Return the next annotation in the list...
inline Annotation *getNext() const { return Next; }
};
//===----------------------------------------------------------------------===//
//
// Annotable - This class is used as a base class for all objects that would
// like to have annotation capability. One notable subclass is Value, which
// means annotations can be attached to almost everything in LLVM.
//
// Annotable objects keep their annotation list sorted as annotations are
// inserted and deleted. This is used to ensure that annotations with identical
// ID#'s are stored sequentially.
//
class Annotable {
mutable Annotation *AnnotationList;
Annotable(const Annotable &); // Do not implement
void operator=(const Annotable &); // Do not implement
public:
Annotable() : AnnotationList(0) {}
virtual ~Annotable() { // Virtual because it's designed to be subclassed...
Annotation *A = AnnotationList;
while (A) {
Annotation *Next = A->getNext();
delete A;
A = Next;
}
}
// getAnnotation - Search the list for annotations of the specified ID. The
// pointer returned is either null (if no annotations of the specified ID
// exist), or it points to the first element of a potentially list of elements
// with identical ID #'s.
//
Annotation *getAnnotation(AnnotationID ID) const {
for (Annotation *A = AnnotationList; A; A = A->getNext())
if (A->getID() == ID) return A;
return 0;
}
// getOrCreateAnnotation - Search through the annotation list, if there is
// no annotation with the specified ID, then use the AnnotationManager to
// create one.
//
inline Annotation *getOrCreateAnnotation(AnnotationID ID) const;
// addAnnotation - Insert the annotation into the list in a sorted location.
//
void addAnnotation(Annotation *A) const {
assert(A->Next == 0 && "Annotation already in list?!?");
Annotation **AL = &AnnotationList;
while (*AL && (*AL)->ID < A->getID()) // Find where to insert annotation
AL = &((*AL)->Next);
A->Next = *AL; // Link the annotation in
*AL = A;
}
// unlinkAnnotation - Remove the first annotation of the specified ID... and
// then return the unlinked annotation. The annotation object is not deleted.
//
inline Annotation *unlinkAnnotation(AnnotationID ID) const {
for (Annotation **A = &AnnotationList; *A; A = &((*A)->Next))
if ((*A)->getID() == ID) {
Annotation *Ret = *A;
*A = Ret->Next;
Ret->Next = 0;
return Ret;
}
return 0;
}
// deleteAnnotation - Delete the first annotation of the specified ID in the
// list. Unlink unlinkAnnotation, this actually deletes the annotation object
//
bool deleteAnnotation(AnnotationID ID) const {
Annotation *A = unlinkAnnotation(ID);
delete A;
return A != 0;
}
};
//===----------------------------------------------------------------------===//
//
// AnnotationManager - This class is primarily responsible for maintaining a
// one-to-one mapping between string Annotation names and Annotation ID numbers.
//
// Compared to the rest of the Annotation system, these mapping methods are
// relatively slow, so they should be avoided by locally caching Annotation
// ID #'s. These methods are safe to call at any time, even by static ctors, so
// they should be used by static ctors most of the time.
//
// This class also provides support for annotations that are created on demand
// by the Annotable::getOrCreateAnnotation method. To get this to work, simply
// register an annotation handler
//
struct AnnotationManager {
typedef Annotation *(*Factory)(AnnotationID, const Annotable *, void*);
//===--------------------------------------------------------------------===//
// Basic ID <-> Name map functionality
static AnnotationID getID(const std::string &Name); // Name -> ID
static const std::string &getName(AnnotationID ID); // ID -> Name
// getID - Name -> ID + registration of a factory function for demand driven
// annotation support.
static AnnotationID getID(const std::string &Name, Factory Fact,
void *Data = 0);
//===--------------------------------------------------------------------===//
// Annotation creation on demand support...
// registerAnnotationFactory - This method is used to register a callback
// function used to create an annotation on demand if it is needed by the
// Annotable::getOrCreateAnnotation method.
//
static void registerAnnotationFactory(AnnotationID ID, Factory Func,
void *ExtraData = 0);
// createAnnotation - Create an annotation of the specified ID for the
// specified object, using a register annotation creation function.
//
static Annotation *createAnnotation(AnnotationID ID, const Annotable *Obj);
};
// getOrCreateAnnotation - Search through the annotation list, if there is
// no annotation with the specified ID, then use the AnnotationManager to
// create one.
//
inline Annotation *Annotable::getOrCreateAnnotation(AnnotationID ID) const {
Annotation *A = getAnnotation(ID); // Fast path, check for preexisting ann
if (A) return A;
// No annotation found, ask the annotation manager to create an annotation...
A = AnnotationManager::createAnnotation(ID, this);
assert(A && "AnnotationManager could not create annotation!");
addAnnotation(A);
return A;
}
#endif
|