Add a new "NewDebugLoc" class which will eventually replace DebugLoc,
[oota-llvm.git] / lib / VMCore / DebugLoc.cpp
1 //===-- DebugLoc.cpp - Implement DebugLoc class ---------------------------===//
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 #include "llvm/Support/DebugLoc.h"
11 #include "LLVMContextImpl.h"
12 using namespace llvm;
13
14 //===----------------------------------------------------------------------===//
15 // DebugLoc Implementation
16 //===----------------------------------------------------------------------===//
17
18 MDNode *NewDebugLoc::getScope(const LLVMContext &Ctx) const {
19   if (ScopeIdx == 0) return 0;
20   
21   if (ScopeIdx > 0) {
22     // Positive ScopeIdx is an index into ScopeRecords, which has no inlined-at
23     // position specified.
24     assert(unsigned(ScopeIdx) <= Ctx.pImpl->ScopeRecords.size() &&
25            "Invalid ScopeIdx!");
26     return Ctx.pImpl->ScopeRecords[ScopeIdx-1].get();
27   }
28   
29   // Otherwise, the index is in the ScopeInlinedAtRecords array.
30   assert(unsigned(-ScopeIdx) <= Ctx.pImpl->ScopeInlinedAtRecords.size() &&
31          "Invalid ScopeIdx");
32   return Ctx.pImpl->ScopeInlinedAtRecords[-ScopeIdx-1].first.get();
33 }
34
35 MDNode *NewDebugLoc::getInlinedAt(const LLVMContext &Ctx) const {
36   // Positive ScopeIdx is an index into ScopeRecords, which has no inlined-at
37   // position specified.  Zero is invalid.
38   if (ScopeIdx >= 0) return 0;
39   
40   // Otherwise, the index is in the ScopeInlinedAtRecords array.
41   assert(unsigned(-ScopeIdx) <= Ctx.pImpl->ScopeInlinedAtRecords.size() &&
42          "Invalid ScopeIdx");
43   return Ctx.pImpl->ScopeInlinedAtRecords[-ScopeIdx-1].second.get();
44 }
45
46 /// Return both the Scope and the InlinedAt values.
47 void NewDebugLoc::getScopeAndInlinedAt(MDNode *&Scope, MDNode *&IA,
48                                        const LLVMContext &Ctx) const {
49   if (ScopeIdx == 0) {
50     Scope = IA = 0;
51     return;
52   }
53   
54   if (ScopeIdx > 0) {
55     // Positive ScopeIdx is an index into ScopeRecords, which has no inlined-at
56     // position specified.
57     assert(unsigned(ScopeIdx) <= Ctx.pImpl->ScopeRecords.size() &&
58            "Invalid ScopeIdx!");
59     Scope = Ctx.pImpl->ScopeRecords[ScopeIdx-1].get();
60     IA = 0;
61     return;
62   }
63   
64   // Otherwise, the index is in the ScopeInlinedAtRecords array.
65   assert(unsigned(-ScopeIdx) <= Ctx.pImpl->ScopeInlinedAtRecords.size() &&
66          "Invalid ScopeIdx");
67   Scope = Ctx.pImpl->ScopeInlinedAtRecords[-ScopeIdx-1].first.get();
68   IA    = Ctx.pImpl->ScopeInlinedAtRecords[-ScopeIdx-1].second.get();
69 }
70
71
72 NewDebugLoc NewDebugLoc::get(unsigned Line, unsigned Col,
73                              MDNode *Scope, MDNode *InlinedAt) {
74   NewDebugLoc Result;
75   
76   // If no scope is available, this is an unknown location.
77   if (Scope == 0) return Result;
78   
79   // Saturate line and col to "unknown".
80   if (Col > 255) Col = 0;
81   if (Line >= (1 << 24)) Line = 0;
82   Result.LineCol = Line | (Col << 24);
83   
84   LLVMContext &Ctx = Scope->getContext();
85   
86   // If there is no inlined-at location, use the ScopeRecords array.
87   if (InlinedAt == 0)
88     Result.ScopeIdx = Ctx.pImpl->getOrAddScopeRecordIdxEntry(Scope, 0);
89   else
90     Result.ScopeIdx = Ctx.pImpl->getOrAddScopeInlinedAtIdxEntry(Scope,
91                                                                 InlinedAt, 0);
92
93   return Result;
94 }
95
96 /// getAsMDNode - This method converts the compressed DebugLoc node into a
97 /// DILocation compatible MDNode.
98 MDNode *NewDebugLoc::getAsMDNode(const LLVMContext &Ctx) const {
99   if (isUnknown()) return 0;
100   
101   MDNode *Scope, *IA;
102   getScopeAndInlinedAt(Scope, IA, Ctx);
103   assert(Scope && "If scope is null, this should be isUnknown()");
104   
105   LLVMContext &Ctx2 = Scope->getContext();
106   const Type *Int32 = Type::getInt32Ty(Ctx2);
107   Value *Elts[] = {
108     ConstantInt::get(Int32, getLine()), ConstantInt::get(Int32, getCol()),
109     Scope, IA
110   };
111   return MDNode::get(Ctx2, &Elts[0], 4);
112 }
113
114
115 //===----------------------------------------------------------------------===//
116 // LLVMContextImpl Implementation
117 //===----------------------------------------------------------------------===//
118
119 int LLVMContextImpl::getOrAddScopeRecordIdxEntry(MDNode *Scope,
120                                                  int ExistingIdx) {
121   // If we already have an entry for this scope, return it.
122   int &Idx = ScopeRecordIdx[Scope];
123   if (Idx) return Idx;
124   
125   // If we don't have an entry, but ExistingIdx is specified, use it.
126   if (ExistingIdx)
127     return Idx = ExistingIdx;
128   
129   // Otherwise add a new entry.
130   
131   // Start out ScopeRecords with a minimal reasonable size to avoid
132   // excessive reallocation starting out.
133   if (ScopeRecords.empty())
134     ScopeRecords.reserve(128);
135   
136   // Index is biased by 1 for index.
137   Idx = ScopeRecords.size()+1;
138   ScopeRecords.push_back(DebugRecVH(Scope, this, Idx));
139   return Idx;
140 }
141
142 int LLVMContextImpl::getOrAddScopeInlinedAtIdxEntry(MDNode *Scope, MDNode *IA,
143                                                     int ExistingIdx) {
144   // If we already have an entry, return it.
145   int &Idx = ScopeInlinedAtIdx[std::make_pair(Scope, IA)];
146   if (Idx) return Idx;
147   
148   // If we don't have an entry, but ExistingIdx is specified, use it.
149   if (ExistingIdx)
150     return Idx = ExistingIdx;
151   
152   // Start out ScopeInlinedAtRecords with a minimal reasonable size to avoid
153   // excessive reallocation starting out.
154   if (ScopeInlinedAtRecords.empty())
155     ScopeInlinedAtRecords.reserve(128);
156     
157   // Index is biased by 1 and negated.
158   Idx = -ScopeInlinedAtRecords.size()-1;
159   ScopeInlinedAtRecords.push_back(std::make_pair(DebugRecVH(Scope, this, Idx),
160                                                  DebugRecVH(IA, this, Idx)));
161   return Idx;
162 }
163
164
165 //===----------------------------------------------------------------------===//
166 // DebugRecVH Implementation
167 //===----------------------------------------------------------------------===//
168
169 /// deleted - The MDNode this is pointing to got deleted, so this pointer needs
170 /// to drop to null and we need remove our entry from the DenseMap.
171 void DebugRecVH::deleted() {
172   // If this is a  non-canonical reference, just drop the value to null, we know
173   // it doesn't have a map entry.
174   if (Idx == 0) {
175     setValPtr(0);
176     return;
177   }
178     
179   MDNode *Cur = get();
180   
181   // If the index is positive, it is an entry in ScopeRecords.
182   if (Idx > 0) {
183     assert(Ctx->ScopeRecordIdx[Cur] == Idx && "Mapping out of date!");
184     Ctx->ScopeRecordIdx.erase(Cur);
185     // Reset this VH to null and we're done.
186     setValPtr(0);
187     Idx = 0;
188     return;
189   }
190   
191   // Otherwise, it is an entry in ScopeInlinedAtRecords, we don't know if it
192   // is the scope or the inlined-at record entry.
193   assert(unsigned(-Idx-1) < Ctx->ScopeInlinedAtRecords.size());
194   std::pair<DebugRecVH, DebugRecVH> &Entry = Ctx->ScopeInlinedAtRecords[-Idx-1];
195   assert((this == &Entry.first || this == &Entry.second) &&
196          "Mapping out of date!");
197   
198   MDNode *OldScope = Entry.first.get();
199   MDNode *OldInlinedAt = Entry.second.get();
200   assert(OldScope != 0 && OldInlinedAt != 0 &&
201          "Entry should be non-canonical if either val dropped to null");
202
203   // Otherwise, we do have an entry in it, nuke it and we're done.
204   assert(Ctx->ScopeInlinedAtIdx[std::make_pair(OldScope, OldInlinedAt)] == Idx&&
205          "Mapping out of date");
206   Ctx->ScopeInlinedAtIdx.erase(std::make_pair(OldScope, OldInlinedAt));
207   
208   // Reset this VH to null.
209   setValPtr(0);
210   Idx = 0;
211 }
212
213 void DebugRecVH::allUsesReplacedWith(Value *NewVa) {
214   // If being replaced with a non-mdnode value (e.g. undef) handle this as if
215   // the mdnode got deleted.
216   MDNode *NewVal = dyn_cast<MDNode>(NewVa);
217   if (NewVal == 0) return deleted();
218   
219   // If this is a non-canonical reference, just change it, we know it already
220   // doesn't have a map entry.
221   if (Idx == 0) {
222     setValPtr(NewVa);
223     return;
224   }
225   
226   MDNode *OldVal = get();
227   assert(OldVal != NewVa && "Node replaced with self?");
228   
229   // If the index is positive, it is an entry in ScopeRecords.
230   if (Idx > 0) {
231     assert(Ctx->ScopeRecordIdx[OldVal] == Idx && "Mapping out of date!");
232     Ctx->ScopeRecordIdx.erase(OldVal);
233     setValPtr(NewVal);
234
235     int NewEntry = Ctx->getOrAddScopeRecordIdxEntry(NewVal, Idx);
236     
237     // If NewVal already has an entry, this becomes a non-canonical reference,
238     // just drop Idx to 0 to signify this.
239     if (NewEntry != Idx)
240       Idx = 0;
241     return;
242   }
243   
244   // Otherwise, it is an entry in ScopeInlinedAtRecords, we don't know if it
245   // is the scope or the inlined-at record entry.
246   assert(unsigned(-Idx-1) < Ctx->ScopeInlinedAtRecords.size());
247   std::pair<DebugRecVH, DebugRecVH> &Entry = Ctx->ScopeInlinedAtRecords[-Idx-1];
248   assert((this == &Entry.first || this == &Entry.second) &&
249          "Mapping out of date!");
250   
251   MDNode *OldScope = Entry.first.get();
252   MDNode *OldInlinedAt = Entry.second.get();
253   assert(OldScope != 0 && OldInlinedAt != 0 &&
254          "Entry should be non-canonical if either val dropped to null");
255   
256   // Otherwise, we do have an entry in it, nuke it and we're done.
257   assert(Ctx->ScopeInlinedAtIdx[std::make_pair(OldScope, OldInlinedAt)] == Idx&&
258          "Mapping out of date");
259   Ctx->ScopeInlinedAtIdx.erase(std::make_pair(OldScope, OldInlinedAt));
260   
261   // Reset this VH to the new value.
262   setValPtr(NewVal);
263
264   int NewIdx = Ctx->getOrAddScopeInlinedAtIdxEntry(Entry.first.get(),
265                                                    Entry.second.get(), Idx);
266   // If NewVal already has an entry, this becomes a non-canonical reference,
267   // just drop Idx to 0 to signify this.
268   if (NewIdx != Idx)
269     Idx = 0;
270 }