|
43 | 43 | #include "llvm/IR/Constants.h"
|
44 | 44 | #include "llvm/IR/DataLayout.h"
|
45 | 45 | #include "llvm/IR/DerivedTypes.h"
|
| 46 | +#include "llvm/IR/Instruction.h" |
46 | 47 | #include "llvm/IR/Instructions.h"
|
47 | 48 | #include "llvm/IR/Intrinsics.h"
|
48 | 49 | #include "llvm/IR/Metadata.h"
|
|
52 | 53 | #include "llvm/Support/SHA1.h"
|
53 | 54 | #include "llvm/Support/SHA256.h"
|
54 | 55 | #include "llvm/Support/TimeProfiler.h"
|
| 56 | +#include <cstdint> |
55 | 57 | #include <optional>
|
56 | 58 | using namespace clang;
|
57 | 59 | using namespace clang::CodeGen;
|
@@ -119,6 +121,114 @@ CGDebugInfo::~CGDebugInfo() {
|
119 | 121 | "Region stack mismatch, stack not empty!");
|
120 | 122 | }
|
121 | 123 |
|
| 124 | +void CGDebugInfo::addInstSourceAtomMetadata(llvm::Instruction *I, |
| 125 | + uint64_t Group, uint8_t Rank) { |
| 126 | + if (!I->getDebugLoc() || Group == 0 || !I->getDebugLoc()->getLine()) |
| 127 | + return; |
| 128 | + |
| 129 | + // Saturate the 3-bit rank. |
| 130 | + Rank = std::min<uint8_t>(Rank, 7); |
| 131 | + |
| 132 | + const llvm::DebugLoc &DL = I->getDebugLoc(); |
| 133 | + |
| 134 | + // Each instruction can only be attributed to one source atom (a limitation of |
| 135 | + // the implementation). If this instruction is already part of a source atom, |
| 136 | + // pick the group in which it has highest precedence (lowest rank). |
| 137 | + if (DL.get()->getAtomGroup() && DL.get()->getAtomRank() && |
| 138 | + DL.get()->getAtomRank() < Rank) { |
| 139 | + Group = DL.get()->getAtomGroup(); |
| 140 | + Rank = DL.get()->getAtomRank(); |
| 141 | + } |
| 142 | + |
| 143 | + // Update the function-local watermark so we don't reuse this number for |
| 144 | + // another atom. |
| 145 | + KeyInstructionsInfo.HighestEmittedAtom = |
| 146 | + std::max(Group, KeyInstructionsInfo.HighestEmittedAtom); |
| 147 | + |
| 148 | + // Apply the new DILocation to the instruction. |
| 149 | + llvm::DILocation *NewDL = llvm::DILocation::get( |
| 150 | + I->getContext(), DL.getLine(), DL.getCol(), DL.getScope(), |
| 151 | + DL.getInlinedAt(), DL.isImplicitCode(), Group, Rank); |
| 152 | + I->setDebugLoc(NewDL); |
| 153 | +}; |
| 154 | + |
| 155 | +void CGDebugInfo::addInstToCurrentSourceAtom(llvm::Instruction *KeyInstruction, |
| 156 | + llvm::Value *Backup) { |
| 157 | + if (!CGM.getCodeGenOpts().DebugKeyInstructions) |
| 158 | + return; |
| 159 | + |
| 160 | + uint64_t Group = KeyInstructionsInfo.CurrentAtom; |
| 161 | + if (!Group) |
| 162 | + return; |
| 163 | + |
| 164 | + addInstSourceAtomMetadata(KeyInstruction, Group, /*Rank=*/1); |
| 165 | + |
| 166 | + llvm::Instruction *BackupI = |
| 167 | + llvm::dyn_cast_or_null<llvm::Instruction>(Backup); |
| 168 | + if (!BackupI) |
| 169 | + return; |
| 170 | + |
| 171 | + // Add the backup instruction to the group. |
| 172 | + addInstSourceAtomMetadata(BackupI, Group, /*Rank=*/2); |
| 173 | + |
| 174 | + // Look through chains of casts too, as they're probably going to evaporate. |
| 175 | + // FIXME: And other nops like zero length geps? |
| 176 | + // FIXME: Should use Cast->isNoopCast()? |
| 177 | + uint8_t Rank = 3; |
| 178 | + while (auto *Cast = dyn_cast<llvm::CastInst>(BackupI)) { |
| 179 | + BackupI = dyn_cast<llvm::Instruction>(Cast->getOperand(0)); |
| 180 | + if (!BackupI) |
| 181 | + break; |
| 182 | + addInstSourceAtomMetadata(BackupI, Group, Rank++); |
| 183 | + } |
| 184 | +} |
| 185 | + |
| 186 | +void CGDebugInfo::addRetToOverrideOrNewSourceAtom(llvm::ReturnInst *Ret, |
| 187 | + llvm::Value *Backup) { |
| 188 | + if (KeyInstructionsInfo.RetAtomOverride) { |
| 189 | + uint64_t CurrentAtom = KeyInstructionsInfo.CurrentAtom; |
| 190 | + KeyInstructionsInfo.CurrentAtom = KeyInstructionsInfo.RetAtomOverride; |
| 191 | + addInstToCurrentSourceAtom(Ret, Backup); |
| 192 | + KeyInstructionsInfo.CurrentAtom = CurrentAtom; |
| 193 | + KeyInstructionsInfo.RetAtomOverride = 0; |
| 194 | + } else { |
| 195 | + auto Grp = ApplyAtomGroup(this); |
| 196 | + addInstToCurrentSourceAtom(Ret, Backup); |
| 197 | + } |
| 198 | +} |
| 199 | + |
| 200 | +void CGDebugInfo::setRetInstSourceAtomOverride(uint64_t Group) { |
| 201 | + assert(KeyInstructionsInfo.RetAtomOverride == 0); |
| 202 | + KeyInstructionsInfo.RetAtomOverride = Group; |
| 203 | +} |
| 204 | + |
| 205 | +void CGDebugInfo::completeFunction() { |
| 206 | + // Reset the atom group number tracker as the numbers are function-local. |
| 207 | + KeyInstructionsInfo.NextAtom = 1; |
| 208 | + KeyInstructionsInfo.HighestEmittedAtom = 0; |
| 209 | + KeyInstructionsInfo.CurrentAtom = 0; |
| 210 | + KeyInstructionsInfo.RetAtomOverride = 0; |
| 211 | +} |
| 212 | + |
| 213 | +ApplyAtomGroup::ApplyAtomGroup(CGDebugInfo *DI) : DI(DI) { |
| 214 | + if (!DI) |
| 215 | + return; |
| 216 | + OriginalAtom = DI->KeyInstructionsInfo.CurrentAtom; |
| 217 | + DI->KeyInstructionsInfo.CurrentAtom = DI->KeyInstructionsInfo.NextAtom++; |
| 218 | +} |
| 219 | + |
| 220 | +ApplyAtomGroup::~ApplyAtomGroup() { |
| 221 | + if (!DI) |
| 222 | + return; |
| 223 | + |
| 224 | + // We may not have used the group number at all. |
| 225 | + DI->KeyInstructionsInfo.NextAtom = |
| 226 | + std::min(DI->KeyInstructionsInfo.HighestEmittedAtom + 1, |
| 227 | + DI->KeyInstructionsInfo.NextAtom); |
| 228 | + |
| 229 | + DI->KeyInstructionsInfo.CurrentAtom = OriginalAtom; |
| 230 | +} |
| 231 | + |
122 | 232 | ApplyDebugLocation::ApplyDebugLocation(CodeGenFunction &CGF,
|
123 | 233 | SourceLocation TemporaryLocation)
|
124 | 234 | : CGF(&CGF) {
|
@@ -174,8 +284,15 @@ ApplyDebugLocation::ApplyDebugLocation(CodeGenFunction &CGF, llvm::DebugLoc Loc)
|
174 | 284 | return;
|
175 | 285 | }
|
176 | 286 | OriginalLocation = CGF.Builder.getCurrentDebugLocation();
|
177 |
| - if (Loc) |
| 287 | + if (Loc) { |
| 288 | + // Key Instructions: drop the atom group and rank to avoid accidentally |
| 289 | + // propagating it around. |
| 290 | + if (Loc->getAtomGroup()) |
| 291 | + Loc = llvm::DILocation::get(Loc->getContext(), Loc.getLine(), |
| 292 | + Loc->getColumn(), Loc->getScope(), |
| 293 | + Loc->getInlinedAt(), Loc.isImplicitCode()); |
178 | 294 | CGF.Builder.SetCurrentDebugLocation(std::move(Loc));
|
| 295 | + } |
179 | 296 | }
|
180 | 297 |
|
181 | 298 | ApplyDebugLocation::~ApplyDebugLocation() {
|
|
0 commit comments