blob: 0fcbf2653aa723181c9802ba548b3b8f1d63e53a [file] [log] [blame]
Chris Lattner8cb2aeb2010-04-01 00:37:44 +00001//===-- 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"
12using namespace llvm;
13
14//===----------------------------------------------------------------------===//
15// DebugLoc Implementation
16//===----------------------------------------------------------------------===//
17
18MDNode *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
35MDNode *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.
47void 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
72NewDebugLoc 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.
98MDNode *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
119int 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
142int 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.
171void 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
213void 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}