1249259Sdim//===-- DebugLoc.cpp - Implement DebugLoc class ---------------------------===// 2249259Sdim// 3249259Sdim// The LLVM Compiler Infrastructure 4249259Sdim// 5249259Sdim// This file is distributed under the University of Illinois Open Source 6249259Sdim// License. See LICENSE.TXT for details. 7249259Sdim// 8249259Sdim//===----------------------------------------------------------------------===// 9249259Sdim 10249259Sdim#include "llvm/Support/DebugLoc.h" 11249259Sdim#include "LLVMContextImpl.h" 12249259Sdim#include "llvm/ADT/DenseMapInfo.h" 13249259Sdim#include "llvm/DebugInfo.h" 14249259Sdimusing namespace llvm; 15249259Sdim 16249259Sdim//===----------------------------------------------------------------------===// 17249259Sdim// DebugLoc Implementation 18249259Sdim//===----------------------------------------------------------------------===// 19249259Sdim 20249259SdimMDNode *DebugLoc::getScope(const LLVMContext &Ctx) const { 21249259Sdim if (ScopeIdx == 0) return 0; 22249259Sdim 23249259Sdim if (ScopeIdx > 0) { 24249259Sdim // Positive ScopeIdx is an index into ScopeRecords, which has no inlined-at 25249259Sdim // position specified. 26249259Sdim assert(unsigned(ScopeIdx) <= Ctx.pImpl->ScopeRecords.size() && 27249259Sdim "Invalid ScopeIdx!"); 28249259Sdim return Ctx.pImpl->ScopeRecords[ScopeIdx-1].get(); 29249259Sdim } 30249259Sdim 31249259Sdim // Otherwise, the index is in the ScopeInlinedAtRecords array. 32249259Sdim assert(unsigned(-ScopeIdx) <= Ctx.pImpl->ScopeInlinedAtRecords.size() && 33249259Sdim "Invalid ScopeIdx"); 34249259Sdim return Ctx.pImpl->ScopeInlinedAtRecords[-ScopeIdx-1].first.get(); 35249259Sdim} 36249259Sdim 37249259SdimMDNode *DebugLoc::getInlinedAt(const LLVMContext &Ctx) const { 38249259Sdim // Positive ScopeIdx is an index into ScopeRecords, which has no inlined-at 39249259Sdim // position specified. Zero is invalid. 40249259Sdim if (ScopeIdx >= 0) return 0; 41249259Sdim 42249259Sdim // Otherwise, the index is in the ScopeInlinedAtRecords array. 43249259Sdim assert(unsigned(-ScopeIdx) <= Ctx.pImpl->ScopeInlinedAtRecords.size() && 44249259Sdim "Invalid ScopeIdx"); 45249259Sdim return Ctx.pImpl->ScopeInlinedAtRecords[-ScopeIdx-1].second.get(); 46249259Sdim} 47249259Sdim 48249259Sdim/// Return both the Scope and the InlinedAt values. 49249259Sdimvoid DebugLoc::getScopeAndInlinedAt(MDNode *&Scope, MDNode *&IA, 50249259Sdim const LLVMContext &Ctx) const { 51249259Sdim if (ScopeIdx == 0) { 52249259Sdim Scope = IA = 0; 53249259Sdim return; 54249259Sdim } 55249259Sdim 56249259Sdim if (ScopeIdx > 0) { 57249259Sdim // Positive ScopeIdx is an index into ScopeRecords, which has no inlined-at 58249259Sdim // position specified. 59249259Sdim assert(unsigned(ScopeIdx) <= Ctx.pImpl->ScopeRecords.size() && 60249259Sdim "Invalid ScopeIdx!"); 61249259Sdim Scope = Ctx.pImpl->ScopeRecords[ScopeIdx-1].get(); 62249259Sdim IA = 0; 63249259Sdim return; 64249259Sdim } 65249259Sdim 66249259Sdim // Otherwise, the index is in the ScopeInlinedAtRecords array. 67249259Sdim assert(unsigned(-ScopeIdx) <= Ctx.pImpl->ScopeInlinedAtRecords.size() && 68249259Sdim "Invalid ScopeIdx"); 69249259Sdim Scope = Ctx.pImpl->ScopeInlinedAtRecords[-ScopeIdx-1].first.get(); 70249259Sdim IA = Ctx.pImpl->ScopeInlinedAtRecords[-ScopeIdx-1].second.get(); 71249259Sdim} 72249259Sdim 73249259Sdim 74249259SdimDebugLoc DebugLoc::get(unsigned Line, unsigned Col, 75249259Sdim MDNode *Scope, MDNode *InlinedAt) { 76249259Sdim DebugLoc Result; 77249259Sdim 78249259Sdim // If no scope is available, this is an unknown location. 79249259Sdim if (Scope == 0) return Result; 80249259Sdim 81249259Sdim // Saturate line and col to "unknown". 82249259Sdim if (Col > 255) Col = 0; 83249259Sdim if (Line >= (1 << 24)) Line = 0; 84249259Sdim Result.LineCol = Line | (Col << 24); 85249259Sdim 86249259Sdim LLVMContext &Ctx = Scope->getContext(); 87249259Sdim 88249259Sdim // If there is no inlined-at location, use the ScopeRecords array. 89249259Sdim if (InlinedAt == 0) 90249259Sdim Result.ScopeIdx = Ctx.pImpl->getOrAddScopeRecordIdxEntry(Scope, 0); 91249259Sdim else 92249259Sdim Result.ScopeIdx = Ctx.pImpl->getOrAddScopeInlinedAtIdxEntry(Scope, 93249259Sdim InlinedAt, 0); 94249259Sdim 95249259Sdim return Result; 96249259Sdim} 97249259Sdim 98249259Sdim/// getAsMDNode - This method converts the compressed DebugLoc node into a 99249259Sdim/// DILocation compatible MDNode. 100249259SdimMDNode *DebugLoc::getAsMDNode(const LLVMContext &Ctx) const { 101249259Sdim if (isUnknown()) return 0; 102249259Sdim 103249259Sdim MDNode *Scope, *IA; 104249259Sdim getScopeAndInlinedAt(Scope, IA, Ctx); 105249259Sdim assert(Scope && "If scope is null, this should be isUnknown()"); 106249259Sdim 107249259Sdim LLVMContext &Ctx2 = Scope->getContext(); 108249259Sdim Type *Int32 = Type::getInt32Ty(Ctx2); 109249259Sdim Value *Elts[] = { 110249259Sdim ConstantInt::get(Int32, getLine()), ConstantInt::get(Int32, getCol()), 111249259Sdim Scope, IA 112249259Sdim }; 113249259Sdim return MDNode::get(Ctx2, Elts); 114249259Sdim} 115249259Sdim 116249259Sdim/// getFromDILocation - Translate the DILocation quad into a DebugLoc. 117249259SdimDebugLoc DebugLoc::getFromDILocation(MDNode *N) { 118249259Sdim DILocation Loc(N); 119249259Sdim MDNode *Scope = Loc.getScope(); 120249259Sdim if (Scope == 0) return DebugLoc(); 121249259Sdim return get(Loc.getLineNumber(), Loc.getColumnNumber(), Scope, 122249259Sdim Loc.getOrigLocation()); 123249259Sdim} 124249259Sdim 125249259Sdim/// getFromDILexicalBlock - Translate the DILexicalBlock into a DebugLoc. 126249259SdimDebugLoc DebugLoc::getFromDILexicalBlock(MDNode *N) { 127249259Sdim DILexicalBlock LexBlock(N); 128249259Sdim MDNode *Scope = LexBlock.getContext(); 129249259Sdim if (Scope == 0) return DebugLoc(); 130249259Sdim return get(LexBlock.getLineNumber(), LexBlock.getColumnNumber(), Scope, NULL); 131249259Sdim} 132249259Sdim 133249259Sdimvoid DebugLoc::dump(const LLVMContext &Ctx) const { 134249259Sdim#ifndef NDEBUG 135249259Sdim if (!isUnknown()) { 136249259Sdim dbgs() << getLine(); 137249259Sdim if (getCol() != 0) 138249259Sdim dbgs() << ',' << getCol(); 139249259Sdim DebugLoc InlinedAtDL = DebugLoc::getFromDILocation(getInlinedAt(Ctx)); 140249259Sdim if (!InlinedAtDL.isUnknown()) { 141249259Sdim dbgs() << " @ "; 142249259Sdim InlinedAtDL.dump(Ctx); 143249259Sdim } else 144249259Sdim dbgs() << "\n"; 145249259Sdim } 146249259Sdim#endif 147249259Sdim} 148249259Sdim 149249259Sdim//===----------------------------------------------------------------------===// 150249259Sdim// DenseMap specialization 151249259Sdim//===----------------------------------------------------------------------===// 152249259Sdim 153249259Sdimunsigned DenseMapInfo<DebugLoc>::getHashValue(const DebugLoc &Key) { 154249259Sdim return static_cast<unsigned>(hash_combine(Key.LineCol, Key.ScopeIdx)); 155249259Sdim} 156249259Sdim 157249259Sdim//===----------------------------------------------------------------------===// 158249259Sdim// LLVMContextImpl Implementation 159249259Sdim//===----------------------------------------------------------------------===// 160249259Sdim 161249259Sdimint LLVMContextImpl::getOrAddScopeRecordIdxEntry(MDNode *Scope, 162249259Sdim int ExistingIdx) { 163249259Sdim // If we already have an entry for this scope, return it. 164249259Sdim int &Idx = ScopeRecordIdx[Scope]; 165249259Sdim if (Idx) return Idx; 166249259Sdim 167249259Sdim // If we don't have an entry, but ExistingIdx is specified, use it. 168249259Sdim if (ExistingIdx) 169249259Sdim return Idx = ExistingIdx; 170249259Sdim 171249259Sdim // Otherwise add a new entry. 172249259Sdim 173249259Sdim // Start out ScopeRecords with a minimal reasonable size to avoid 174249259Sdim // excessive reallocation starting out. 175249259Sdim if (ScopeRecords.empty()) 176249259Sdim ScopeRecords.reserve(128); 177249259Sdim 178249259Sdim // Index is biased by 1 for index. 179249259Sdim Idx = ScopeRecords.size()+1; 180249259Sdim ScopeRecords.push_back(DebugRecVH(Scope, this, Idx)); 181249259Sdim return Idx; 182249259Sdim} 183249259Sdim 184249259Sdimint LLVMContextImpl::getOrAddScopeInlinedAtIdxEntry(MDNode *Scope, MDNode *IA, 185249259Sdim int ExistingIdx) { 186249259Sdim // If we already have an entry, return it. 187249259Sdim int &Idx = ScopeInlinedAtIdx[std::make_pair(Scope, IA)]; 188249259Sdim if (Idx) return Idx; 189249259Sdim 190249259Sdim // If we don't have an entry, but ExistingIdx is specified, use it. 191249259Sdim if (ExistingIdx) 192249259Sdim return Idx = ExistingIdx; 193249259Sdim 194249259Sdim // Start out ScopeInlinedAtRecords with a minimal reasonable size to avoid 195249259Sdim // excessive reallocation starting out. 196249259Sdim if (ScopeInlinedAtRecords.empty()) 197249259Sdim ScopeInlinedAtRecords.reserve(128); 198249259Sdim 199249259Sdim // Index is biased by 1 and negated. 200249259Sdim Idx = -ScopeInlinedAtRecords.size()-1; 201249259Sdim ScopeInlinedAtRecords.push_back(std::make_pair(DebugRecVH(Scope, this, Idx), 202249259Sdim DebugRecVH(IA, this, Idx))); 203249259Sdim return Idx; 204249259Sdim} 205249259Sdim 206249259Sdim 207249259Sdim//===----------------------------------------------------------------------===// 208249259Sdim// DebugRecVH Implementation 209249259Sdim//===----------------------------------------------------------------------===// 210249259Sdim 211249259Sdim/// deleted - The MDNode this is pointing to got deleted, so this pointer needs 212249259Sdim/// to drop to null and we need remove our entry from the DenseMap. 213249259Sdimvoid DebugRecVH::deleted() { 214249259Sdim // If this is a non-canonical reference, just drop the value to null, we know 215249259Sdim // it doesn't have a map entry. 216249259Sdim if (Idx == 0) { 217249259Sdim setValPtr(0); 218249259Sdim return; 219249259Sdim } 220249259Sdim 221249259Sdim MDNode *Cur = get(); 222249259Sdim 223249259Sdim // If the index is positive, it is an entry in ScopeRecords. 224249259Sdim if (Idx > 0) { 225249259Sdim assert(Ctx->ScopeRecordIdx[Cur] == Idx && "Mapping out of date!"); 226249259Sdim Ctx->ScopeRecordIdx.erase(Cur); 227249259Sdim // Reset this VH to null and we're done. 228249259Sdim setValPtr(0); 229249259Sdim Idx = 0; 230249259Sdim return; 231249259Sdim } 232249259Sdim 233249259Sdim // Otherwise, it is an entry in ScopeInlinedAtRecords, we don't know if it 234249259Sdim // is the scope or the inlined-at record entry. 235249259Sdim assert(unsigned(-Idx-1) < Ctx->ScopeInlinedAtRecords.size()); 236249259Sdim std::pair<DebugRecVH, DebugRecVH> &Entry = Ctx->ScopeInlinedAtRecords[-Idx-1]; 237249259Sdim assert((this == &Entry.first || this == &Entry.second) && 238249259Sdim "Mapping out of date!"); 239249259Sdim 240249259Sdim MDNode *OldScope = Entry.first.get(); 241249259Sdim MDNode *OldInlinedAt = Entry.second.get(); 242249259Sdim assert(OldScope != 0 && OldInlinedAt != 0 && 243249259Sdim "Entry should be non-canonical if either val dropped to null"); 244249259Sdim 245249259Sdim // Otherwise, we do have an entry in it, nuke it and we're done. 246249259Sdim assert(Ctx->ScopeInlinedAtIdx[std::make_pair(OldScope, OldInlinedAt)] == Idx&& 247249259Sdim "Mapping out of date"); 248249259Sdim Ctx->ScopeInlinedAtIdx.erase(std::make_pair(OldScope, OldInlinedAt)); 249249259Sdim 250249259Sdim // Reset this VH to null. Drop both 'Idx' values to null to indicate that 251249259Sdim // we're in non-canonical form now. 252249259Sdim setValPtr(0); 253249259Sdim Entry.first.Idx = Entry.second.Idx = 0; 254249259Sdim} 255249259Sdim 256249259Sdimvoid DebugRecVH::allUsesReplacedWith(Value *NewVa) { 257249259Sdim // If being replaced with a non-mdnode value (e.g. undef) handle this as if 258249259Sdim // the mdnode got deleted. 259249259Sdim MDNode *NewVal = dyn_cast<MDNode>(NewVa); 260249259Sdim if (NewVal == 0) return deleted(); 261249259Sdim 262249259Sdim // If this is a non-canonical reference, just change it, we know it already 263249259Sdim // doesn't have a map entry. 264249259Sdim if (Idx == 0) { 265249259Sdim setValPtr(NewVa); 266249259Sdim return; 267249259Sdim } 268249259Sdim 269249259Sdim MDNode *OldVal = get(); 270249259Sdim assert(OldVal != NewVa && "Node replaced with self?"); 271249259Sdim 272249259Sdim // If the index is positive, it is an entry in ScopeRecords. 273249259Sdim if (Idx > 0) { 274249259Sdim assert(Ctx->ScopeRecordIdx[OldVal] == Idx && "Mapping out of date!"); 275249259Sdim Ctx->ScopeRecordIdx.erase(OldVal); 276249259Sdim setValPtr(NewVal); 277249259Sdim 278249259Sdim int NewEntry = Ctx->getOrAddScopeRecordIdxEntry(NewVal, Idx); 279249259Sdim 280249259Sdim // If NewVal already has an entry, this becomes a non-canonical reference, 281249259Sdim // just drop Idx to 0 to signify this. 282249259Sdim if (NewEntry != Idx) 283249259Sdim Idx = 0; 284249259Sdim return; 285249259Sdim } 286249259Sdim 287249259Sdim // Otherwise, it is an entry in ScopeInlinedAtRecords, we don't know if it 288249259Sdim // is the scope or the inlined-at record entry. 289249259Sdim assert(unsigned(-Idx-1) < Ctx->ScopeInlinedAtRecords.size()); 290249259Sdim std::pair<DebugRecVH, DebugRecVH> &Entry = Ctx->ScopeInlinedAtRecords[-Idx-1]; 291249259Sdim assert((this == &Entry.first || this == &Entry.second) && 292249259Sdim "Mapping out of date!"); 293249259Sdim 294249259Sdim MDNode *OldScope = Entry.first.get(); 295249259Sdim MDNode *OldInlinedAt = Entry.second.get(); 296249259Sdim assert(OldScope != 0 && OldInlinedAt != 0 && 297249259Sdim "Entry should be non-canonical if either val dropped to null"); 298249259Sdim 299249259Sdim // Otherwise, we do have an entry in it, nuke it and we're done. 300249259Sdim assert(Ctx->ScopeInlinedAtIdx[std::make_pair(OldScope, OldInlinedAt)] == Idx&& 301249259Sdim "Mapping out of date"); 302249259Sdim Ctx->ScopeInlinedAtIdx.erase(std::make_pair(OldScope, OldInlinedAt)); 303249259Sdim 304249259Sdim // Reset this VH to the new value. 305249259Sdim setValPtr(NewVal); 306249259Sdim 307249259Sdim int NewIdx = Ctx->getOrAddScopeInlinedAtIdxEntry(Entry.first.get(), 308249259Sdim Entry.second.get(), Idx); 309249259Sdim // If NewVal already has an entry, this becomes a non-canonical reference, 310249259Sdim // just drop Idx to 0 to signify this. 311249259Sdim if (NewIdx != Idx) { 312249259Sdim std::pair<DebugRecVH, DebugRecVH> &Entry=Ctx->ScopeInlinedAtRecords[-Idx-1]; 313249259Sdim Entry.first.Idx = Entry.second.Idx = 0; 314249259Sdim } 315249259Sdim} 316