Fixes for Visual Studio users. Patch by OvermindDL1 on llvm-dev!
[oota-llvm.git] / lib / Support / Annotation.cpp
1 //===-- Annotation.cpp - Implement the Annotation Classes -----------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file implements the AnnotationManager class.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #include "llvm/Support/Annotation.h"
15 #include "llvm/Support/ManagedStatic.h"
16 #include <map>
17 #include <cstring>
18 using namespace llvm;
19
20 Annotation::~Annotation() {}  // Designed to be subclassed
21
22 Annotable::~Annotable() {   // Virtual because it's designed to be subclassed...
23   Annotation *A = AnnotationList;
24   while (A) {
25     Annotation *Next = A->getNext();
26     delete A;
27     A = Next;
28   }
29 }
30
31 namespace {
32   class StrCmp {
33   public:
34     bool operator()(const char *a, const char *b) const {
35       return strcmp(a, b) < 0;
36     }
37   };
38 }
39
40 typedef std::map<const char*, unsigned, StrCmp> IDMapType;
41 static unsigned IDCounter = 0;  // Unique ID counter
42
43 // Static member to ensure initialiation on demand.
44 static ManagedStatic<IDMapType> IDMap;
45
46 // On demand annotation creation support...
47 typedef Annotation *(*AnnFactory)(AnnotationID, const Annotable *, void *);
48 typedef std::map<unsigned, std::pair<AnnFactory,void*> > FactMapType;
49
50 static FactMapType *TheFactMap = 0;
51 static FactMapType &getFactMap() {
52   if (TheFactMap == 0)
53     TheFactMap = new FactMapType();
54   return *TheFactMap;
55 }
56
57 static void eraseFromFactMap(unsigned ID) {
58   assert(TheFactMap && "No entries found!");
59   TheFactMap->erase(ID);
60   if (TheFactMap->empty()) {   // Delete when empty
61     delete TheFactMap;
62     TheFactMap = 0;
63   }
64 }
65
66 AnnotationID AnnotationManager::getID(const char *Name) {  // Name -> ID
67   IDMapType::iterator I = IDMap->find(Name);
68   if (I == IDMap->end()) {
69     (*IDMap)[Name] = IDCounter++;   // Add a new element
70     return AnnotationID(IDCounter-1);
71   }
72   return AnnotationID(I->second);
73 }
74
75 // getID - Name -> ID + registration of a factory function for demand driven
76 // annotation support.
77 AnnotationID AnnotationManager::getID(const char *Name, Factory Fact,
78                                       void *Data) {
79   AnnotationID Result(getID(Name));
80   registerAnnotationFactory(Result, Fact, Data);
81   return Result;
82 }
83
84 // getName - This function is especially slow, but that's okay because it should
85 // only be used for debugging.
86 //
87 const char *AnnotationManager::getName(AnnotationID ID) {  // ID -> Name
88   IDMapType &TheMap = *IDMap;
89   for (IDMapType::iterator I = TheMap.begin(); ; ++I) {
90     assert(I != TheMap.end() && "Annotation ID is unknown!");
91     if (I->second == ID.ID) return I->first;
92   }
93 }
94
95 // registerAnnotationFactory - This method is used to register a callback
96 // function used to create an annotation on demand if it is needed by the
97 // Annotable::findOrCreateAnnotation method.
98 //
99 void AnnotationManager::registerAnnotationFactory(AnnotationID ID, AnnFactory F,
100                                                   void *ExtraData) {
101   if (F)
102     getFactMap()[ID.ID] = std::make_pair(F, ExtraData);
103   else
104     eraseFromFactMap(ID.ID);
105 }
106
107 // createAnnotation - Create an annotation of the specified ID for the
108 // specified object, using a register annotation creation function.
109 //
110 Annotation *AnnotationManager::createAnnotation(AnnotationID ID,
111                                                 const Annotable *Obj) {
112   FactMapType::iterator I = getFactMap().find(ID.ID);
113   if (I == getFactMap().end()) return 0;
114   return I->second.first(ID, Obj, I->second.second);
115 }