|
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,97 @@ 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 | + addInstToSpecificSourceAtom(KeyInstruction, Backup, |
| 158 | + KeyInstructionsInfo.CurrentAtom); |
| 159 | +} |
| 160 | + |
| 161 | +void CGDebugInfo::addInstToSpecificSourceAtom(llvm::Instruction *KeyInstruction, |
| 162 | + llvm::Value *Backup, |
| 163 | + uint64_t Group) { |
| 164 | + if (!Group || !CGM.getCodeGenOpts().DebugKeyInstructions) |
| 165 | + return; |
| 166 | + |
| 167 | + addInstSourceAtomMetadata(KeyInstruction, Group, /*Rank=*/1); |
| 168 | + |
| 169 | + llvm::Instruction *BackupI = |
| 170 | + llvm::dyn_cast_or_null<llvm::Instruction>(Backup); |
| 171 | + if (!BackupI) |
| 172 | + return; |
| 173 | + |
| 174 | + // Add the backup instruction to the group. |
| 175 | + addInstSourceAtomMetadata(BackupI, Group, /*Rank=*/2); |
| 176 | + |
| 177 | + // Look through chains of casts too, as they're probably going to evaporate. |
| 178 | + // FIXME: And other nops like zero length geps? |
| 179 | + // FIXME: Should use Cast->isNoopCast()? |
| 180 | + uint8_t Rank = 3; |
| 181 | + while (auto *Cast = dyn_cast<llvm::CastInst>(BackupI)) { |
| 182 | + BackupI = dyn_cast<llvm::Instruction>(Cast->getOperand(0)); |
| 183 | + if (!BackupI) |
| 184 | + break; |
| 185 | + addInstSourceAtomMetadata(BackupI, Group, Rank++); |
| 186 | + } |
| 187 | +} |
| 188 | + |
| 189 | +void CGDebugInfo::completeFunction() { |
| 190 | + // Reset the atom group number tracker as the numbers are function-local. |
| 191 | + KeyInstructionsInfo.NextAtom = 1; |
| 192 | + KeyInstructionsInfo.HighestEmittedAtom = 0; |
| 193 | + KeyInstructionsInfo.CurrentAtom = 0; |
| 194 | +} |
| 195 | + |
| 196 | +ApplyAtomGroup::ApplyAtomGroup(CGDebugInfo *DI) : DI(DI) { |
| 197 | + if (!DI) |
| 198 | + return; |
| 199 | + OriginalAtom = DI->KeyInstructionsInfo.CurrentAtom; |
| 200 | + DI->KeyInstructionsInfo.CurrentAtom = DI->KeyInstructionsInfo.NextAtom++; |
| 201 | +} |
| 202 | + |
| 203 | +ApplyAtomGroup::~ApplyAtomGroup() { |
| 204 | + if (!DI) |
| 205 | + return; |
| 206 | + |
| 207 | + // We may not have used the group number at all. |
| 208 | + DI->KeyInstructionsInfo.NextAtom = |
| 209 | + std::min(DI->KeyInstructionsInfo.HighestEmittedAtom + 1, |
| 210 | + DI->KeyInstructionsInfo.NextAtom); |
| 211 | + |
| 212 | + DI->KeyInstructionsInfo.CurrentAtom = OriginalAtom; |
| 213 | +} |
| 214 | + |
122 | 215 | ApplyDebugLocation::ApplyDebugLocation(CodeGenFunction &CGF,
|
123 | 216 | SourceLocation TemporaryLocation)
|
124 | 217 | : CGF(&CGF) {
|
@@ -174,8 +267,15 @@ ApplyDebugLocation::ApplyDebugLocation(CodeGenFunction &CGF, llvm::DebugLoc Loc)
|
174 | 267 | return;
|
175 | 268 | }
|
176 | 269 | OriginalLocation = CGF.Builder.getCurrentDebugLocation();
|
177 |
| - if (Loc) |
| 270 | + if (Loc) { |
| 271 | + // Key Instructions: drop the atom group and rank to avoid accidentally |
| 272 | + // propagating it around. |
| 273 | + if (Loc->getAtomGroup()) |
| 274 | + Loc = llvm::DILocation::get(Loc->getContext(), Loc.getLine(), |
| 275 | + Loc->getColumn(), Loc->getScope(), |
| 276 | + Loc->getInlinedAt(), Loc.isImplicitCode()); |
178 | 277 | CGF.Builder.SetCurrentDebugLocation(std::move(Loc));
|
| 278 | + } |
179 | 279 | }
|
180 | 280 |
|
181 | 281 | ApplyDebugLocation::~ApplyDebugLocation() {
|
|
0 commit comments