llvm.org GIT mirror llvm / 2a39c99
Debug info: Infrastructure to support debug locations for fragmented variables (for example, by-value struct arguments passed in registers, or large integer values split across several smaller registers). On the IR level, this adds a new type of complex address operation OpPiece to DIVariable that describes size and offset of a variable fragment. On the DWARF emitter level, all pieces describing the same variable are collected, sorted and emitted as DWARF expressions using the DW_OP_piece and DW_OP_bit_piece operators. http://reviews.llvm.org/D3373 rdar://problem/15928306 What this patch doesn't do / Future work: - This patch only adds the backend machinery to make this work, patches that change SROA and SelectionDAG's type legalizer to actually create such debug info will follow. (http://reviews.llvm.org/D2680) - Making the DIVariable complex expressions into an argument of dbg.value will reduce the memory footprint of the debug metadata. - The sorting/uniquing of pieces should be moved into DebugLocEntry, to facilitate the merging of multi-piece entries. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@214576 91177308-0d34-0410-b5e6-96231b3b80d8 Adrian Prantl 5 years ago
18 changed file(s) with 683 addition(s) and 75 deletion(s). Raw diff Collapse all Expand all
587587 The context is either the subprogram or block where the variable is defined.
588588 Name the source variable name. Context and line indicate where the variable
589589 was defined. Type descriptor defines the declared type of the variable.
590
591 The ``OpPiece`` operator is used for (typically larger aggregate)
592 variables that are fragmented across several locations. It takes two
593 i32 arguments, an offset and a size in bytes to describe which piece
594 of the variable is at this location.
595
590596
591597 .. _format_common_intrinsics:
592598
404404 /// Get the value for DW_AT_APPLE_isa. Zero if no isa encoding specified.
405405 virtual unsigned getISAEncoding() { return 0; }
406406
407 /// Emit a dwarf register operation for describing
408 /// - a small value occupying only part of a register or
409 /// - a register representing only part of a value.
410 void EmitDwarfOpPiece(ByteStreamer &Streamer, unsigned SizeInBits,
411 unsigned OffsetInBits = 0) const;
412
413
407414 /// \brief Emit a partial DWARF register operation.
408415 /// \param MLoc the register
409416 /// \param PieceSize size and
420427 unsigned PieceSize = 0,
421428 unsigned PieceOffset = 0) const;
422429
423 /// Emit dwarf register operation.
430 /// EmitDwarfRegOp - Emit a dwarf register operation.
424431 /// \param Indirect whether this is a register-indirect address
425432 virtual void EmitDwarfRegOp(ByteStreamer &BS, const MachineLocation &MLoc,
426433 bool Indirect) const;
8484
8585 public:
8686 explicit DIBuilder(Module &M);
87 enum ComplexAddrKind { OpPlus=1, OpDeref };
87 enum ComplexAddrKind { OpPlus=1, OpDeref, OpPiece };
8888 enum DebugEmissionKind { FullDebug=1, LineTablesOnly };
8989
9090 /// finalize - Construct any deferred debug info descriptors.
560560 DITypeRef Ty, ArrayRef Addr,
561561 unsigned ArgNo = 0);
562562
563 /// createVariablePiece - Create a descriptor to describe one part
564 /// of aggregate variable that is fragmented across multiple Values.
565 ///
566 /// @param Variable Variable that is partially represented by this.
567 /// @param OffsetInBytes Offset of the piece in bytes.
568 /// @param SizeInBytes Size of the piece in bytes.
569 DIVariable createVariablePiece(DIVariable Variable,
570 unsigned OffsetInBytes,
571 unsigned SizeInBytes);
572
563573 /// createFunction - Create a new descriptor for the specified subprogram.
564574 /// See comments in DISubprogram for descriptions of these fields.
565575 /// @param Scope Function scope.
724724 /// information for an inlined function arguments.
725725 bool isInlinedFnArgument(const Function *CurFn);
726726
727 /// isVariablePiece - Return whether this is a piece of an aggregate
728 /// variable.
729 bool isVariablePiece() const;
730 /// getPieceOffset - Return the offset of this piece in bytes.
731 uint64_t getPieceOffset() const;
732 /// getPieceSize - Return the size of this piece in bytes.
733 uint64_t getPieceSize() const;
734
735 /// Return the size reported by the variable's type.
736 unsigned getSizeInBits(const DITypeIdentifierMap &Map);
737
727738 void printExtendedName(raw_ostream &OS) const;
728739 };
729740
841852 /// cleanseInlinedVariable - Remove inlined scope from the variable.
842853 DIVariable cleanseInlinedVariable(MDNode *DV, LLVMContext &VMContext);
843854
855 /// getEntireVariable - Remove OpPiece exprs from the variable.
856 DIVariable getEntireVariable(DIVariable DV);
857
844858 /// Construct DITypeIdentifierMap by going through retained types of each CU.
845859 DITypeIdentifierMap generateDITypeIdentifierMap(const NamedMDNode *CU_Nodes);
846860
617617 if (!Name.empty())
618618 OS << Name << ":";
619619 }
620 OS << V.getName() << " <- ";
620 OS << V.getName();
621 if (V.isVariablePiece())
622 OS << " [piece offset=" << V.getPieceOffset()
623 << " size="<
624 OS << " <- ";
621625
622626 // The second operand is only an offset if it's an immediate.
623627 bool Deref = MI->getOperand(0).isReg() && MI->getOperand(1).isImm();
213213 Streamer.EmitInt8(dwarf::DW_OP_deref, "DW_OP_deref");
214214 }
215215
216 /// Emit a dwarf register operation for describing
217 /// - a small value occupying only part of a register or
218 /// - a small register representing only part of a value.
219 static void emitDwarfOpPiece(ByteStreamer &Streamer, unsigned SizeInBits,
220 unsigned OffsetInBits) {
221 assert(SizeInBits > 0 && "zero-sized piece");
222 unsigned SizeOfByte = 8;
216 void AsmPrinter::EmitDwarfOpPiece(ByteStreamer &Streamer, unsigned SizeInBits,
217 unsigned OffsetInBits) const {
218 assert(SizeInBits > 0 && "piece has size zero");
219 const unsigned SizeOfByte = 8;
223220 if (OffsetInBits > 0 || SizeInBits % SizeOfByte) {
224221 Streamer.EmitInt8(dwarf::DW_OP_bit_piece, "DW_OP_bit_piece");
225222 Streamer.EmitULEB128(SizeInBits, Twine(SizeInBits));
254251 // If this is a valid register number, emit it.
255252 if (Reg >= 0) {
256253 emitDwarfRegOp(Streamer, Reg);
257 emitDwarfOpPiece(Streamer, PieceSizeInBits, PieceOffsetInBits);
254 EmitDwarfOpPiece(Streamer, PieceSizeInBits, PieceOffsetInBits);
258255 return;
259256 }
260257
265262 if (Reg >= 0) {
266263 unsigned Idx = TRI->getSubRegIndex(*SR, MLoc.getReg());
267264 unsigned Size = TRI->getSubRegIdxSize(Idx);
268 unsigned Offset = TRI->getSubRegIdxOffset(Idx);
265 unsigned RegOffset = TRI->getSubRegIdxOffset(Idx);
269266 OutStreamer.AddComment("super-register");
270267 emitDwarfRegOp(Streamer, Reg);
271 if (PieceOffsetInBits == Offset) {
272 emitDwarfOpPiece(Streamer, Size, Offset);
268 if (PieceOffsetInBits == RegOffset) {
269 EmitDwarfOpPiece(Streamer, Size, RegOffset);
273270 } else {
274271 // If this is part of a variable in a sub-register at a
275272 // non-zero offset, we need to manually shift the value into
276273 // place, since the DW_OP_piece describes the part of the
277274 // variable, not the position of the subregister.
278 emitDwarfOpPiece(Streamer, Size, PieceOffsetInBits);
279 if (Offset)
280 emitDwarfOpShr(Streamer, Offset);
275 if (RegOffset)
276 emitDwarfOpShr(Streamer, RegOffset);
277 EmitDwarfOpPiece(Streamer, Size, PieceOffsetInBits);
281278 }
282279 return;
283280 }
311308 if (Reg >= 0 && Intersection.any()) {
312309 OutStreamer.AddComment("sub-register");
313310 emitDwarfRegOp(Streamer, Reg);
314 emitDwarfOpPiece(Streamer, Size, Offset == CurPos ? 0 : Offset);
311 EmitDwarfOpPiece(Streamer, Size, Offset == CurPos ? 0 : Offset);
315312 CurPos = Offset + Size;
316313
317314 // Mark it as emitted.
1010 #include "llvm/ADT/SmallVector.h"
1111 #include "llvm/CodeGen/MachineBasicBlock.h"
1212 #include "llvm/CodeGen/MachineFunction.h"
13 #include "llvm/IR/DebugInfo.h"
1314 #include "llvm/Support/Debug.h"
1415 #include "llvm/Target/TargetRegisterInfo.h"
1516 #include
3536 const MachineInstr &MI) {
3637 // Instruction range should start with a DBG_VALUE instruction for the
3738 // variable.
38 assert(MI.isDebugValue() && MI.getDebugVariable() == Var);
39 assert(MI.isDebugValue() && getEntireVariable(MI.getDebugVariable()) == Var);
3940 auto &Ranges = VarInstrRanges[Var];
4041 if (!Ranges.empty() && Ranges.back().second == nullptr &&
4142 Ranges.back().first->isIdenticalTo(&MI)) {
181182 }
182183
183184 assert(MI.getNumOperands() > 1 && "Invalid DBG_VALUE instruction!");
184 const MDNode *Var = MI.getDebugVariable();
185 // Use the base variable (without any DW_OP_piece expressions)
186 // as index into History. The full variables including the
187 // piece expressions are attached to the MI.
188 DIVariable Var = getEntireVariable(MI.getDebugVariable());
185189
186190 if (unsigned PrevReg = Result.getRegisterForVar(Var))
187191 dropRegDescribedVar(RegVars, PrevReg, Var);
2727 // range. If end is not specified, location is valid until the start
2828 // instruction of the next instruction range, or until the end of the
2929 // function.
30 public:
3031 typedef std::pair InstrRange;
3132 typedef SmallVector InstrRanges;
3233 typedef MapVector InstrRangesMap;
34 private:
3335 InstrRangesMap VarInstrRanges;
3436
3537 public:
99 #ifndef CODEGEN_ASMPRINTER_DEBUGLOCENTRY_H__
1010 #define CODEGEN_ASMPRINTER_DEBUGLOCENTRY_H__
1111 #include "llvm/IR/Constants.h"
12 #include "llvm/IR/DebugInfo.h"
1213 #include "llvm/MC/MachineLocation.h"
1314 #include "llvm/MC/MCSymbol.h"
1415
105106 /// share the same Loc/Constant and if Next immediately follows this
106107 /// Entry.
107108 bool Merge(const DebugLocEntry &Next) {
109 // If this and Next are describing different pieces of the same
110 // variable, merge them by appending next's values to the current
111 // list of values.
112 if (Begin == Next.Begin && Values.size() > 0 && Next.Values.size() > 0) {
113 DIVariable Var(Values[0].Variable);
114 DIVariable NextVar(Next.Values[0].Variable);
115 if (Var.getName() == NextVar.getName() &&
116 Var.isVariablePiece() && NextVar.isVariablePiece()) {
117 Values.append(Next.Values.begin(), Next.Values.end());
118 End = Next.End;
119 return true;
120 }
121 }
122 // If this and Next are describing the same variable, merge them.
108123 if ((End == Next.Begin && Values == Next.Values)) {
109124 End = Next.End;
110125 return true;
111126 }
112127 return false;
113128 }
129
114130 const MCSymbol *getBeginSym() const { return Begin; }
115131 const MCSymbol *getEndSym() const { return End; }
116132 const DwarfCompileUnit *getCU() const { return Unit; }
117133 const ArrayRef getValues() const { return Values; }
118 void addValue(Value Val) { Values.push_back(Val); }
134 void addValue(Value Val) {
135 assert(DIVariable(Val.Variable).isVariablePiece() &&
136 "multi-value DebugLocEntries must be pieces");
137 Values.push_back(Val);
138 }
119139 };
120140
121141 }
11931193 llvm_unreachable("Unexpected 3 operand DBG_VALUE instruction!");
11941194 }
11951195
1196 /// Determine whether two variable pieces overlap.
1197 static bool piecesOverlap(DIVariable P1, DIVariable P2) {
1198 if (!P1.isVariablePiece() || !P2.isVariablePiece())
1199 return true;
1200 unsigned l1 = P1.getPieceOffset();
1201 unsigned l2 = P2.getPieceOffset();
1202 unsigned r1 = l1 + P1.getPieceSize();
1203 unsigned r2 = l2 + P2.getPieceSize();
1204 // True where [l1,r1[ and [r1,r2[ overlap.
1205 return (l1 < r2) && (l2 < r1);
1206 }
1207
1208 /// Build the location list for all DBG_VALUEs in the function that
1209 /// describe the same variable. If the ranges of several independent
1210 /// pieces of the same variable overlap partially, split them up and
1211 /// combine the ranges. The resulting DebugLocEntries are will have
1212 /// strict monotonically increasing begin addresses and will never
1213 /// overlap.
1214 //
1215 // Input:
1216 //
1217 // Ranges History [var, loc, piece ofs size]
1218 // 0 | [x, (reg0, piece 0, 32)]
1219 // 1 | | [x, (reg1, piece 32, 32)] <- IsPieceOfPrevEntry
1220 // 2 | | ...
1221 // 3 | [clobber reg0]
1222 // 4 [x, (mem, piece 0, 64)] <- overlapping with both previous pieces of x.
1223 //
1224 // Output:
1225 //
1226 // [0-1] [x, (reg0, piece 0, 32)]
1227 // [1-3] [x, (reg0, piece 0, 32), (reg1, piece 32, 32)]
1228 // [3-4] [x, (reg1, piece 32, 32)]
1229 // [4- ] [x, (mem, piece 0, 64)]
1230 void DwarfDebug::
1231 buildLocationList(SmallVectorImpl &DebugLoc,
1232 const DbgValueHistoryMap::InstrRanges &Ranges,
1233 DwarfCompileUnit *TheCU) {
1234 typedef std::pair Range;
1235 SmallVector OpenRanges;
1236
1237 for (auto I = Ranges.begin(), E = Ranges.end(); I != E; ++I) {
1238 const MachineInstr *Begin = I->first;
1239 const MachineInstr *End = I->second;
1240 assert(Begin->isDebugValue() && "Invalid History entry");
1241
1242 // Check if a variable is inaccessible in this range.
1243 if (!Begin->isDebugValue() ||
1244 (Begin->getNumOperands() > 1 && Begin->getOperand(0).isReg() &&
1245 !Begin->getOperand(0).getReg())) {
1246 OpenRanges.clear();
1247 continue;
1248 }
1249
1250 // If this piece overlaps with any open ranges, truncate them.
1251 DIVariable DIVar = Begin->getDebugVariable();
1252 auto Last = std::remove_if(OpenRanges.begin(), OpenRanges.end(), [&](Range R){
1253 return piecesOverlap(DIVar, R.first);
1254 });
1255 OpenRanges.erase(Last, OpenRanges.end());
1256
1257 const MCSymbol *StartLabel = getLabelBeforeInsn(Begin);
1258 assert(StartLabel && "Forgot label before DBG_VALUE starting a range!");
1259
1260 const MCSymbol *EndLabel;
1261 if (End != nullptr)
1262 EndLabel = getLabelAfterInsn(End);
1263 else if (std::next(I) == Ranges.end())
1264 EndLabel = FunctionEndSym;
1265 else
1266 EndLabel = getLabelBeforeInsn(std::next(I)->first);
1267 assert(EndLabel && "Forgot label after instruction ending a range!");
1268
1269 DEBUG(dbgs() << "DotDebugLoc: " << *Begin << "\n");
1270
1271 auto Value = getDebugLocValue(Begin);
1272 DebugLocEntry Loc(StartLabel, EndLabel, Value, TheCU);
1273 if (DebugLoc.empty() || !DebugLoc.back().Merge(Loc)) {
1274 // Add all values from still valid non-overlapping pieces.
1275 for (auto Range : OpenRanges)
1276 Loc.addValue(Range.second);
1277 DebugLoc.push_back(std::move(Loc));
1278 }
1279 // Add this value to the list of open ranges.
1280 if (DIVar.isVariablePiece())
1281 OpenRanges.push_back({DIVar, Value});
1282
1283 DEBUG(dbgs() << "Values:\n";
1284 for (auto Value : DebugLoc.back().getValues())
1285 Value.getVariable()->dump();
1286 dbgs() << "-----\n");
1287 }
1288 }
1289
1290
11961291 // Find variables for each lexical scope.
11971292 void
11981293 DwarfDebug::collectVariableInfo(SmallPtrSet &Processed) {
12261321 if (!Scope)
12271322 continue;
12281323
1229 Processed.insert(DV);
1324 Processed.insert(getEntireVariable(DV));
12301325 const MachineInstr *MInsn = Ranges.front().first;
12311326 assert(MInsn->isDebugValue() && "History must begin with debug value");
12321327 ensureAbstractVariableIsCreatedIfScoped(DV, Scope->getScopeNode());
12451340 DebugLocList &LocList = DotDebugLocEntries.back();
12461341 LocList.Label =
12471342 Asm->GetTempSymbol("debug_loc", DotDebugLocEntries.size() - 1);
1248 SmallVector &DebugLoc = LocList.List;
1249 for (auto I = Ranges.begin(), E = Ranges.end(); I != E; ++I) {
1250 const MachineInstr *Begin = I->first;
1251 const MachineInstr *End = I->second;
1252 assert(Begin->isDebugValue() && "Invalid History entry");
1253
1254 // Check if a variable is unaccessible in this range.
1255 if (Begin->getNumOperands() > 1 && Begin->getOperand(0).isReg() &&
1256 !Begin->getOperand(0).getReg())
1257 continue;
1258 DEBUG(dbgs() << "DotDebugLoc Pair:\n" << "\t" << *Begin);
1259 if (End != nullptr)
1260 DEBUG(dbgs() << "\t" << *End);
1261 else
1262 DEBUG(dbgs() << "\tNULL\n");
1263
1264 const MCSymbol *StartLabel = getLabelBeforeInsn(Begin);
1265 assert(StartLabel && "Forgot label before DBG_VALUE starting a range!");
1266
1267 const MCSymbol *EndLabel;
1268 if (End != nullptr)
1269 EndLabel = getLabelAfterInsn(End);
1270 else if (std::next(I) == Ranges.end())
1271 EndLabel = FunctionEndSym;
1272 else
1273 EndLabel = getLabelBeforeInsn(std::next(I)->first);
1274 assert(EndLabel && "Forgot label after instruction ending a range!");
1275
1276 DebugLocEntry Loc(StartLabel, EndLabel, getDebugLocValue(Begin), TheCU);
1277 if (DebugLoc.empty() || !DebugLoc.back().Merge(Loc))
1278 DebugLoc.push_back(std::move(Loc));
1279 }
1343
1344 // Build the location list for this variable.
1345 buildLocationList(LocList.List, Ranges, TheCU);
12801346 }
12811347
12821348 // Collect info for variables that were optimized out.
14751541
14761542 // The first mention of a function argument gets the FunctionBeginSym
14771543 // label, so arguments are visible when breaking at function entry.
1478 DIVariable DV(I.first);
1544 DIVariable DV(Ranges.front().first->getDebugVariable());
14791545 if (DV.isVariable() && DV.getTag() == dwarf::DW_TAG_arg_variable &&
1480 getDISubprogram(DV.getContext()).describes(MF->getFunction()))
1481 LabelsBeforeInsn[Ranges.front().first] = FunctionBeginSym;
1546 getDISubprogram(DV.getContext()).describes(MF->getFunction())) {
1547 if (!DV.isVariablePiece())
1548 LabelsBeforeInsn[Ranges.front().first] = FunctionBeginSym;
1549 else {
1550 // Mark all non-overlapping initial pieces.
1551 for (auto I = Ranges.begin(); I != Ranges.end(); ++I) {
1552 DIVariable Piece = I->first->getDebugVariable();
1553 if (std::all_of(Ranges.begin(), I,
1554 [&](DbgValueHistoryMap::InstrRange Pred){
1555 return !piecesOverlap(Piece, Pred.first->getDebugVariable());
1556 }))
1557 LabelsBeforeInsn[I->first] = FunctionBeginSym;
1558 else
1559 break;
1560 }
1561 }
1562 }
14821563
14831564 for (const auto &Range : Ranges) {
14841565 requestLabelBeforeInsn(Range.first);
19612042 Holder.emitStrings(Asm->getObjFileLowering().getDwarfStrSection());
19622043 }
19632044
2045 /// Emits an optimal (=sorted) sequence of DW_OP_pieces.
2046 void DwarfDebug::emitLocPieces(ByteStreamer &Streamer,
2047 const DITypeIdentifierMap &Map,
2048 ArrayRef Values) {
2049 typedef DebugLocEntry::Value Piece;
2050 SmallVector Pieces(Values.begin(), Values.end());
2051 assert(std::all_of(Pieces.begin(), Pieces.end(), [](Piece &P) {
2052 return DIVariable(P.getVariable()).isVariablePiece();
2053 }) && "all values are expected to be pieces");
2054
2055 // Sort the pieces so they can be emitted using DW_OP_piece.
2056 std::sort(Pieces.begin(), Pieces.end(), [](const Piece &A, const Piece &B) {
2057 DIVariable VarA(A.getVariable());
2058 DIVariable VarB(B.getVariable());
2059 return VarA.getPieceOffset() < VarB.getPieceOffset();
2060 });
2061 // Remove any duplicate entries by dropping all but the first.
2062 Pieces.erase(std::unique(Pieces.begin(), Pieces.end(),
2063 [] (const Piece &A,const Piece &B){
2064 return A.getVariable() == B.getVariable();
2065 }), Pieces.end());
2066
2067 unsigned Offset = 0;
2068 for (auto Piece : Pieces) {
2069 DIVariable Var(Piece.getVariable());
2070 unsigned PieceOffset = Var.getPieceOffset();
2071 unsigned PieceSize = Var.getPieceSize();
2072 assert(Offset <= PieceOffset && "overlapping pieces in DebugLocEntry");
2073 if (Offset < PieceOffset) {
2074 // The DWARF spec seriously mandates pieces with no locations for gaps.
2075 Asm->EmitDwarfOpPiece(Streamer, (PieceOffset-Offset)*8);
2076 Offset += PieceOffset-Offset;
2077 }
2078
2079 Offset += PieceSize;
2080
2081 const unsigned SizeOfByte = 8;
2082 assert(!Var.isIndirect() && "indirect address for piece");
2083 #ifndef NDEBUG
2084 unsigned VarSize = Var.getSizeInBits(Map);
2085 assert(PieceSize+PieceOffset <= VarSize/SizeOfByte
2086 && "piece is larger than or outside of variable");
2087 assert(PieceSize*SizeOfByte != VarSize
2088 && "piece covers entire variable");
2089 #endif
2090 if (Piece.isLocation() && Piece.getLoc().isReg())
2091 Asm->EmitDwarfRegOpPiece(Streamer,
2092 Piece.getLoc(),
2093 PieceSize*SizeOfByte);
2094 else {
2095 emitDebugLocValue(Streamer, Piece);
2096 Asm->EmitDwarfOpPiece(Streamer, PieceSize*SizeOfByte);
2097 }
2098 }
2099 }
2100
2101
19642102 void DwarfDebug::emitDebugLocEntry(ByteStreamer &Streamer,
19652103 const DebugLocEntry &Entry) {
1966 assert(Entry.getValues().size() == 1 &&
1967 "multi-value entries are not supported yet.");
19682104 const DebugLocEntry::Value Value = Entry.getValues()[0];
19692105 DIVariable DV(Value.getVariable());
2106 if (DV.isVariablePiece())
2107 // Emit all pieces that belong to the same variable and range.
2108 return emitLocPieces(Streamer, TypeIdentifierMap, Entry.getValues());
2109
2110 assert(Entry.getValues().size() == 1 && "only pieces may have >1 value");
2111 emitDebugLocValue(Streamer, Value);
2112 }
2113
2114 void DwarfDebug::emitDebugLocValue(ByteStreamer &Streamer,
2115 const DebugLocEntry::Value &Value) {
2116 DIVariable DV(Value.getVariable());
2117 // Regular entry.
19702118 if (Value.isInt()) {
19712119 DIBasicType BTy(resolve(DV.getType()));
19722120 if (BTy.Verify() && (BTy.getEncoding() == dwarf::DW_ATE_signed ||
20132161 } else if (Element == DIBuilder::OpDeref) {
20142162 if (!Loc.isReg())
20152163 Streamer.EmitInt8(dwarf::DW_OP_deref, "DW_OP_deref");
2164 } else if (Element == DIBuilder::OpPiece) {
2165 i += 3;
2166 // handled in emitDebugLocEntry.
20162167 } else
20172168 llvm_unreachable("unknown Opcode found in complex address");
20182169 }
534534 /// \brief Populate LexicalScope entries with variables' info.
535535 void collectVariableInfo(SmallPtrSet &ProcessedVars);
536536
537 /// \brief Build the location list for all DBG_VALUEs in the
538 /// function that describe the same variable.
539 void buildLocationList(SmallVectorImpl &DebugLoc,
540 const DbgValueHistoryMap::InstrRanges &Ranges,
541 DwarfCompileUnit *TheCU);
542
537543 /// \brief Collect variable information from the side table maintained
538544 /// by MMI.
539545 void collectVariableInfoFromMMITable(SmallPtrSet &P);
641647 /// \brief Emit an entry for the debug loc section. This can be used to
642648 /// handle an entry that's going to be emitted into the debug loc section.
643649 void emitDebugLocEntry(ByteStreamer &Streamer, const DebugLocEntry &Entry);
650 /// \brief emit a single value for the debug loc section.
651 void emitDebugLocValue(ByteStreamer &Streamer,
652 const DebugLocEntry::Value &Value);
653 /// Emits an optimal (=sorted) sequence of DW_OP_pieces.
654 void emitLocPieces(ByteStreamer &Streamer,
655 const DITypeIdentifierMap &Map,
656 ArrayRef Values);
644657
645658 /// Emit the location for a debug loc entry, including the size header.
646659 void emitDebugLocEntryLocation(const DebugLocEntry &Entry);
490490 }
491491
492492 /// addRegisterOp - Add register operand.
493 void DwarfUnit::addRegisterOp(DIELoc &TheDie, unsigned Reg) {
493 // FIXME: Ideally, this would share the implementation with
494 // AsmPrinter::EmitDwarfRegOpPiece.
495 void DwarfUnit::addRegisterOpPiece(DIELoc &TheDie, unsigned Reg,
496 unsigned SizeInBits, unsigned OffsetInBits) {
494497 const TargetRegisterInfo *RI = Asm->TM.getRegisterInfo();
495498 int DWReg = RI->getDwarfRegNum(Reg, false);
496499 bool isSubRegister = DWReg < 0;
510513 return;
511514 }
512515
513 // Emit register
516 // Emit register.
514517 if (DWReg < 32)
515518 addUInt(TheDie, dwarf::DW_FORM_data1, dwarf::DW_OP_reg0 + DWReg);
516519 else {
518521 addUInt(TheDie, dwarf::DW_FORM_udata, DWReg);
519522 }
520523
521 // Emit Mask
522 if (isSubRegister) {
523 unsigned Size = RI->getSubRegIdxSize(Idx);
524 unsigned Offset = RI->getSubRegIdxOffset(Idx);
525 if (Offset > 0) {
524 // Emit mask.
525 bool isPiece = SizeInBits > 0;
526 if (isSubRegister || isPiece) {
527 const unsigned SizeOfByte = 8;
528 unsigned RegSizeInBits = RI->getSubRegIdxSize(Idx);
529 unsigned RegOffsetInBits = RI->getSubRegIdxOffset(Idx);
530 unsigned PieceSizeInBits = std::max(SizeInBits, RegSizeInBits);
531 unsigned PieceOffsetInBits = OffsetInBits ? OffsetInBits : RegOffsetInBits;
532 assert(RegSizeInBits >= SizeInBits && "register smaller than value");
533
534 if (RegOffsetInBits != PieceOffsetInBits) {
535 // Manually shift the value into place, since the DW_OP_piece
536 // describes the part of the variable, not the position of the
537 // subregister.
538 addUInt(TheDie, dwarf::DW_FORM_data1, dwarf::DW_OP_constu);
539 addUInt(TheDie, dwarf::DW_FORM_data1, RegOffsetInBits);
540 addUInt(TheDie, dwarf::DW_FORM_data1, dwarf::DW_OP_shr);
541 }
542
543 if (PieceOffsetInBits > 0 || PieceSizeInBits % SizeOfByte) {
544 assert(PieceSizeInBits > 0 && "piece has zero size");
526545 addUInt(TheDie, dwarf::DW_FORM_data1, dwarf::DW_OP_bit_piece);
527 addUInt(TheDie, dwarf::DW_FORM_data1, Size);
528 addUInt(TheDie, dwarf::DW_FORM_data1, Offset);
529 } else {
530 unsigned ByteSize = Size / 8; // Assuming 8 bits per byte.
546 addUInt(TheDie, dwarf::DW_FORM_data1, PieceSizeInBits);
547 addUInt(TheDie, dwarf::DW_FORM_data1, PieceOffsetInBits);
548 } else {
549 assert(PieceSizeInBits > 0 && "piece has zero size");
531550 addUInt(TheDie, dwarf::DW_FORM_data1, dwarf::DW_OP_piece);
532 addUInt(TheDie, dwarf::DW_FORM_data1, ByteSize);
551 addUInt(TheDie, dwarf::DW_FORM_data1, PieceSizeInBits/SizeOfByte);
533552 }
534553 }
535554 }
559578 DIELoc *Loc = new (DIEValueAllocator) DIELoc();
560579
561580 if (Location.isReg() && !Indirect)
562 addRegisterOp(*Loc, Location.getReg());
581 addRegisterOpPiece(*Loc, Location.getReg());
563582 else {
564583 addRegisterOffset(*Loc, Location.getReg(), Location.getOffset());
565584 if (Indirect && !Location.isReg()) {
588607 // DW_OP_breg + Offset instead of DW_OP_reg + Offset.
589608 addRegisterOffset(*Loc, Location.getReg(), DV.getAddrElement(1));
590609 i = 2;
610 } else if (N >= 2 && DV.getAddrElement(0) == DIBuilder::OpDeref) {
611 addRegisterOpPiece(*Loc, Location.getReg(),
612 DV.getVariable().getPieceSize(),
613 DV.getVariable().getPieceOffset());
614 i = 3;
591615 } else
592 addRegisterOp(*Loc, Location.getReg());
616 addRegisterOpPiece(*Loc, Location.getReg());
593617 } else
594618 addRegisterOffset(*Loc, Location.getReg(), Location.getOffset());
595619
598622 if (Element == DIBuilder::OpPlus) {
599623 addUInt(*Loc, dwarf::DW_FORM_data1, dwarf::DW_OP_plus_uconst);
600624 addUInt(*Loc, dwarf::DW_FORM_udata, DV.getAddrElement(++i));
625
601626 } else if (Element == DIBuilder::OpDeref) {
602627 if (!Location.isReg())
603628 addUInt(*Loc, dwarf::DW_FORM_data1, dwarf::DW_OP_deref);
629
630 } else if (Element == DIBuilder::OpPiece) {
631 const unsigned SizeOfByte = 8;
632 unsigned PieceOffsetInBits = DV.getAddrElement(++i)*SizeOfByte;
633 unsigned PieceSizeInBits = DV.getAddrElement(++i)*SizeOfByte;
634 // Emit DW_OP_bit_piece Size Offset.
635 assert(PieceSizeInBits > 0 && "piece has zero size");
636 addUInt(*Loc, dwarf::DW_FORM_data1, dwarf::DW_OP_bit_piece);
637 addUInt(*Loc, dwarf::DW_FORM_udata, PieceSizeInBits);
638 addUInt(*Loc, dwarf::DW_FORM_udata, PieceOffsetInBits);
639
604640 } else
605641 llvm_unreachable("unknown DIBuilder Opcode");
606642 }
711747 DIELoc *Loc = new (DIEValueAllocator) DIELoc();
712748
713749 if (Location.isReg())
714 addRegisterOp(*Loc, Location.getReg());
750 addRegisterOpPiece(*Loc, Location.getReg());
715751 else
716752 addRegisterOffset(*Loc, Location.getReg(), Location.getOffset());
717753
358358 void addTemplateParams(DIE &Buffer, DIArray TParams);
359359
360360 /// addRegisterOp - Add register operand.
361 void addRegisterOp(DIELoc &TheDie, unsigned Reg);
361 void addRegisterOpPiece(DIELoc &TheDie, unsigned Reg,
362 unsigned SizeInBits = 0, unsigned OffsetInBits = 0);
362363
363364 /// addRegisterOffset - Add register offset.
364365 void addRegisterOffset(DIELoc &TheDie, unsigned Reg, int64_t Offset);
10991099 return DIVariable(MDNode::get(VMContext, Elts));
11001100 }
11011101
1102 /// createVariablePiece - Create a descriptor to describe one part
1103 /// of aggregate variable that is fragmented across multiple Values.
1104 DIVariable DIBuilder::createVariablePiece(DIVariable Variable,
1105 unsigned OffsetInBytes,
1106 unsigned SizeInBytes) {
1107 assert(SizeInBytes > 0 && "zero-size piece");
1108 Value *Addr[] = {
1109 ConstantInt::get(Type::getInt32Ty(VMContext), OpPiece),
1110 ConstantInt::get(Type::getInt32Ty(VMContext), OffsetInBytes),
1111 ConstantInt::get(Type::getInt32Ty(VMContext), SizeInBytes)
1112 };
1113
1114 assert((Variable->getNumOperands() == 8 || Variable.isVariablePiece()) &&
1115 "variable already has a complex address");
1116 SmallVector Elts;
1117 for (unsigned i = 0; i < 8; ++i)
1118 Elts.push_back(Variable->getOperand(i));
1119
1120 Elts.push_back(MDNode::get(VMContext, Addr));
1121 return DIVariable(MDNode::get(VMContext, Elts));
1122 }
1123
11021124 /// createFunction - Create a new descriptor for the specified function.
11031125 /// FIXME: this is added for dragonegg. Once we update dragonegg
11041126 /// to call resolve function, this will be removed.
1818 #include "llvm/ADT/SmallString.h"
1919 #include "llvm/Analysis/ValueTracking.h"
2020 #include "llvm/IR/Constants.h"
21 #include "llvm/IR/DIBuilder.h"
2122 #include "llvm/IR/DerivedTypes.h"
2223 #include "llvm/IR/Instructions.h"
2324 #include "llvm/IR/IntrinsicInst.h"
148149
149150 /// getInlinedAt - If this variable is inlined then return inline location.
150151 MDNode *DIVariable::getInlinedAt() const { return getNodeField(DbgNode, 7); }
152
153 bool DIVariable::isVariablePiece() const {
154 return hasComplexAddress() && getAddrElement(0) == DIBuilder::OpPiece;
155 }
156
157 uint64_t DIVariable::getPieceOffset() const {
158 assert(isVariablePiece());
159 return getAddrElement(1);
160 }
161
162 uint64_t DIVariable::getPieceSize() const {
163 assert(isVariablePiece());
164 return getAddrElement(2);
165 }
166
167 /// Return the size reported by the variable's type.
168 unsigned DIVariable::getSizeInBits(const DITypeIdentifierMap &Map) {
169 DIType Ty = getType().resolve(Map);
170 // Follow derived types until we reach a type that
171 // reports back a size.
172 while (Ty.isDerivedType() && !Ty.getSizeInBits()) {
173 DIDerivedType DT(&*Ty);
174 Ty = DT.getTypeDerivedFrom().resolve(Map);
175 }
176 assert(Ty.getSizeInBits() && "type with size 0");
177 return Ty.getSizeInBits();
178 }
179
180
181
151182
152183 //===----------------------------------------------------------------------===//
153184 // Predicates
901932 i == 7 ? Elts.push_back(Constant::getNullValue(Type::getInt32Ty(VMContext)))
902933 : Elts.push_back(DV->getOperand(i));
903934 return DIVariable(MDNode::get(VMContext, Elts));
935 }
936
937
938 /// getEntireVariable - Remove OpPiece exprs from the variable.
939 DIVariable llvm::getEntireVariable(DIVariable DV) {
940 if (!DV.isVariablePiece())
941 return DV;
942
943 SmallVector Elts;
944 for (unsigned i = 0; i < 8; ++i)
945 Elts.push_back(DV->getOperand(i));
946
947 return DIVariable(MDNode::get(DV->getContext(), Elts));
904948 }
905949
906950 /// getDISubprogram - Find subprogram that is enclosing this scope.
13921436 OS << " [" << Res << ']';
13931437
13941438 OS << " [line " << getLineNumber() << ']';
1439
1440 if (isVariablePiece())
1441 OS << " [piece, size " << getPieceSize()
1442 << ", offset " << getPieceOffset() << ']';
13951443 }
13961444
13971445 void DIObjCProperty::printInternal(raw_ostream &OS) const {
0 ; RUN: llc -O0 %s -filetype=obj -o %t.o
1 ; RUN: llvm-dwarfdump -debug-dump=loc %t.o | FileCheck --check-prefix=CHECK-DWARF %s
2 ;
3 ; rdar://problem/15928306
4 ;
5 ; Test that we can emit debug info for aggregate values that are split
6 ; up across multiple registers by SROA.
7 ;
8 ; // Compile with -O1.
9 ; typedef struct { long int a; int b;} S;
10 ;
11 ; int foo(S s) {
12 ; return s.b;
13 ; }
14 ;
15 ;
16 ; CHECK-DWARF: .debug_loc contents:
17 ;
18
19 ; 0x0000000000000000 - 0x0000000000000006: rdi, piece 0x00000008, rsi, piece 0x00000004
20 ; CHECK-DWARF: Beginning address offset: 0x0000000000000000
21 ; CHECK-DWARF: Ending address offset: [[LTMP3:.*]]
22 ; CHECK-DWARF: Location description: 55 93 08 54 93 04
23 ; 0x0000000000000006 - 0x0000000000000008: rbp-8, piece 0x00000008, rax, piece 0x00000004 )
24 ; CHECK-DWARF: Beginning address offset: [[LTMP3]]
25 ; CHECK-DWARF: Ending address offset: [[END:.*]]
26 ; CHECK-DWARF: Location description: 76 78 93 08 54 93 04
27
28 ; Function Attrs: nounwind ssp uwtable
29 define i32 @foo(i64 %s.coerce0, i32 %s.coerce1) #0 {
30 entry:
31 call void @llvm.dbg.value(metadata !{i64 %s.coerce0}, i64 0, metadata !20), !dbg !21
32 call void @llvm.dbg.value(metadata !{i32 %s.coerce1}, i64 0, metadata !22), !dbg !21
33 ret i32 %s.coerce1, !dbg !23
34 }
35
36 ; Function Attrs: nounwind readnone
37 declare void @llvm.dbg.declare(metadata, metadata) #1
38
39 ; Function Attrs: nounwind readnone
40 declare void @llvm.dbg.value(metadata, i64, metadata) #1
41
42 attributes #0 = { nounwind ssp uwtable "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" }
43 attributes #1 = { nounwind readnone }
44
45 !llvm.dbg.cu = !{!0}
46 !llvm.module.flags = !{!17, !18}
47 !llvm.ident = !{!19}
48
49 !0 = metadata !{i32 786449, metadata !1, i32 12, metadata !"clang version 3.5 ", i1 true, metadata !"", i32 0, metadata !2, metadata !2, metadata !3, metadata !2, metadata !2, metadata !""}
50 !1 = metadata !{metadata !"pieces.c", metadata !""}
51 !2 = metadata !{}
52 !3 = metadata !{metadata !4}
53 !4 = metadata !{i32 786478, metadata !1, metadata !5, metadata !"foo", metadata !"foo", metadata !"", i32 3, metadata !6, i1 false, i1 true, i32 0, i32 0, null, i32 256, i1 true, i32 (i64, i32)* @foo, null, null, metadata !15, i32 3} ; [ DW_TAG_subprogram ] [line 3] [def] [foo]
54 !5 = metadata !{i32 786473, metadata !1} ; [ DW_TAG_file_type ] [/pieces.c]
55 !6 = metadata !{i32 786453, i32 0, null, metadata !"", i32 0, i64 0, i64 0, i64 0, i32 0, null, metadata !7, i32 0, null, null, null} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ]
56 !7 = metadata !{metadata !8, metadata !9}
57 !8 = metadata !{i32 786468, null, null, metadata !"int", i32 0, i64 32, i64 32, i64 0, i32 0, i32 5} ; [ DW_TAG_base_type ] [int] [line 0, size 32, align 32, offset 0, enc DW_ATE_signed]
58 !9 = metadata !{i32 786454, metadata !1, null, metadata !"S", i32 1, i64 0, i64 0, i64 0, i32 0, metadata !10} ; [ DW_TAG_typedef ] [S] [line 1, size 0, align 0, offset 0] [from ]
59 !10 = metadata !{i32 786451, metadata !1, null, metadata !"", i32 1, i64 128, i64 64, i32 0, i32 0, null, metadata !11, i32 0, null, null, null} ; [ DW_TAG_structure_type ] [line 1, size 128, align 64, offset 0] [def] [from ]
60 !11 = metadata !{metadata !12, metadata !14}
61 !12 = metadata !{i32 786445, metadata !1, metadata !10, metadata !"a", i32 1, i64 64, i64 64, i64 0, i32 0, metadata !13} ; [ DW_TAG_member ] [a] [line 1, size 64, align 64, offset 0] [from long int]
62 !13 = metadata !{i32 786468, null, null, metadata !"long int", i32 0, i64 64, i64 64, i64 0, i32 0, i32 5} ; [ DW_TAG_base_type ] [long int] [line 0, size 64, align 64, offset 0, enc DW_ATE_signed]
63 !14 = metadata !{i32 786445, metadata !1, metadata !10, metadata !"b", i32 1, i64 32, i64 32, i64 64, i32 0, metadata !8} ; [ DW_TAG_member ] [b] [line 1, size 32, align 32, offset 64] [from int]
64 !15 = metadata !{metadata !16}
65 !16 = metadata !{i32 786689, metadata !4, metadata !"s", metadata !5, i32 16777219, metadata !9, i32 0, i32 0} ; [ DW_TAG_arg_variable ] [s] [line 3]
66 !17 = metadata !{i32 2, metadata !"Dwarf Version", i32 4}
67 !18 = metadata !{i32 1, metadata !"Debug Info Version", i32 1}
68 !19 = metadata !{metadata !"clang version 3.5 "}
69 !20 = metadata !{i32 786689, metadata !4, metadata !"s", metadata !5, i32 16777219, metadata !9, i32 0, i32 0, metadata !24} ; [ DW_TAG_arg_variable ] [s] [line 3] [piece, size 8, offset 0]
70 !21 = metadata !{i32 3, i32 0, metadata !4, null}
71 !22 = metadata !{i32 786689, metadata !4, metadata !"s", metadata !5, i32 16777219, metadata !9, i32 0, i32 0, metadata !27} ; [ DW_TAG_arg_variable ] [s] [line 3] [piece, size 4, offset 8]
72 !23 = metadata !{i32 4, i32 0, metadata !4, null}
73 !24 = metadata !{i64 3, i64 0, i64 8}
74 !25 = metadata !{}
75 !27 = metadata !{i64 3, i64 8, i64 4}
0 ; RUN: llc %s -filetype=obj -o - | llvm-dwarfdump - | FileCheck %s
1 ;
2 ; // Compile with -O1
3 ; typedef struct {
4 ; int a;
5 ; long int b;
6 ; } Inner;
7 ;
8 ; typedef struct {
9 ; Inner inner[2];
10 ; } Outer;
11 ;
12 ; int foo(Outer outer) {
13 ; Inner i1 = outer.inner[1];
14 ; return i1.a;
15 ; }
16 ;
17 ;
18 ; CHECK: DW_TAG_variable [4]
19 ; rax, piece 0x00000004
20 ; CHECK-NEXT: DW_AT_location [DW_FORM_block1]{{.*}}50 93 04
21 ; CHECK-NEXT: DW_AT_name {{.*}}"i1"
22 ;
23 ; ModuleID = '/Volumes/Data/llvm/test/DebugInfo/X86/sroasplit-1.ll'
24 target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
25 target triple = "x86_64-apple-macosx10.9.0"
26
27 %struct.Outer = type { [2 x %struct.Inner] }
28 %struct.Inner = type { i32, i64 }
29
30 ; Function Attrs: nounwind ssp uwtable
31 define i32 @foo(%struct.Outer* byval align 8 %outer) #0 {
32 entry:
33 call void @llvm.dbg.declare(metadata !{%struct.Outer* %outer}, metadata !25), !dbg !26
34 %i1.sroa.0.0..sroa_idx = getelementptr inbounds %struct.Outer* %outer, i64 0, i32 0, i64 1, i32 0, !dbg !27
35 %i1.sroa.0.0.copyload = load i32* %i1.sroa.0.0..sroa_idx, align 8, !dbg !27
36 call void @llvm.dbg.value(metadata !{i32 %i1.sroa.0.0.copyload}, i64 0, metadata !28), !dbg !27
37 %i1.sroa.2.0..sroa_raw_cast = bitcast %struct.Outer* %outer to i8*, !dbg !27
38 %i1.sroa.2.0..sroa_raw_idx = getelementptr inbounds i8* %i1.sroa.2.0..sroa_raw_cast, i64 20, !dbg !27
39 ret i32 %i1.sroa.0.0.copyload, !dbg !32
40 }
41
42 ; Function Attrs: nounwind readnone
43 declare void @llvm.dbg.declare(metadata, metadata) #1
44
45 ; Function Attrs: nounwind
46 declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture, i8* nocapture readonly, i64, i32, i1) #2
47
48 ; Function Attrs: nounwind readnone
49 declare void @llvm.dbg.value(metadata, i64, metadata) #1
50
51 attributes #0 = { nounwind ssp uwtable }
52 attributes #1 = { nounwind readnone }
53 attributes #2 = { nounwind }
54
55 !llvm.dbg.cu = !{!0}
56 !llvm.module.flags = !{!22, !23}
57 !llvm.ident = !{!24}
58
59 !0 = metadata !{i32 786449, metadata !1, i32 12, metadata !"clang version 3.5.0 ", i1 false, metadata !"", i32 0, metadata !2, metadata !2, metadata !3, metadata !2, metadata !2, metadata !"", i32 1} ; [ DW_TAG_compile_unit ] [/sroasplit-1.c] [DW_LANG_C99]
60 !1 = metadata !{metadata !"sroasplit-1.c", metadata !""}
61 !2 = metadata !{}
62 !3 = metadata !{metadata !4}
63 !4 = metadata !{i32 786478, metadata !1, metadata !5, metadata !"foo", metadata !"foo", metadata !"", i32 10, metadata !6, i1 false, i1 true, i32 0, i32 0, null, i32 256, i1 false, i32 (%struct.Outer*)* @foo, null, null, metadata !2, i32 10} ; [ DW_TAG_subprogram ] [line 10] [def] [foo]
64 !5 = metadata !{i32 786473, metadata !1} ; [ DW_TAG_file_type ] [/sroasplit-1.c]
65 !6 = metadata !{i32 786453, i32 0, null, metadata !"", i32 0, i64 0, i64 0, i64 0, i32 0, null, metadata !7, i32 0, null, null, null} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ]
66 !7 = metadata !{metadata !8, metadata !9}
67 !8 = metadata !{i32 786468, null, null, metadata !"int", i32 0, i64 32, i64 32, i64 0, i32 0, i32 5} ; [ DW_TAG_base_type ] [int] [line 0, size 32, align 32, offset 0, enc DW_ATE_signed]
68 !9 = metadata !{i32 786454, metadata !1, null, metadata !"Outer", i32 8, i64 0, i64 0, i64 0, i32 0, metadata !10} ; [ DW_TAG_typedef ] [Outer] [line 8, size 0, align 0, offset 0] [from ]
69 !10 = metadata !{i32 786451, metadata !1, null, metadata !"", i32 6, i64 256, i64 64, i32 0, i32 0, null, metadata !11, i32 0, null, null, null} ; [ DW_TAG_structure_type ] [line 6, size 256, align 64, offset 0] [def] [from ]
70 !11 = metadata !{metadata !12}
71 !12 = metadata !{i32 786445, metadata !1, metadata !10, metadata !"inner", i32 7, i64 256, i64 64, i64 0, i32 0, metadata !13} ; [ DW_TAG_member ] [inner] [line 7, size 256, align 64, offset 0] [from ]
72 !13 = metadata !{i32 786433, null, null, metadata !"", i32 0, i64 256, i64 64, i32 0, i32 0, metadata !14, metadata !20, i32 0, null, null, null} ; [ DW_TAG_array_type ] [line 0, size 256, align 64, offset 0] [from Inner]
73 !14 = metadata !{i32 786454, metadata !1, null, metadata !"Inner", i32 4, i64 0, i64 0, i64 0, i32 0, metadata !15} ; [ DW_TAG_typedef ] [Inner] [line 4, size 0, align 0, offset 0] [from ]
74 !15 = metadata !{i32 786451, metadata !1, null, metadata !"", i32 1, i64 128, i64 64, i32 0, i32 0, null, metadata !16, i32 0, null, null, null} ; [ DW_TAG_structure_type ] [line 1, size 128, align 64, offset 0] [def] [from ]
75 !16 = metadata !{metadata !17, metadata !18}
76 !17 = metadata !{i32 786445, metadata !1, metadata !15, metadata !"a", i32 2, i64 32, i64 32, i64 0, i32 0, metadata !8} ; [ DW_TAG_member ] [a] [line 2, size 32, align 32, offset 0] [from int]
77 !18 = metadata !{i32 786445, metadata !1, metadata !15, metadata !"b", i32 3, i64 64, i64 64, i64 64, i32 0, metadata !19} ; [ DW_TAG_member ] [b] [line 3, size 64, align 64, offset 64] [from long int]
78 !19 = metadata !{i32 786468, null, null, metadata !"long int", i32 0, i64 64, i64 64, i64 0, i32 0, i32 5} ; [ DW_TAG_base_type ] [long int] [line 0, size 64, align 64, offset 0, enc DW_ATE_signed]
79 !20 = metadata !{metadata !21}
80 !21 = metadata !{i32 786465, i64 0, i64 2} ; [ DW_TAG_subrange_type ] [0, 1]
81 !22 = metadata !{i32 2, metadata !"Dwarf Version", i32 2}
82 !23 = metadata !{i32 1, metadata !"Debug Info Version", i32 1}
83 !24 = metadata !{metadata !"clang version 3.5.0 "}
84 !25 = metadata !{i32 786689, metadata !4, metadata !"outer", metadata !5, i32 16777226, metadata !9, i32 0, i32 0} ; [ DW_TAG_arg_variable ] [outer] [line 10]
85 !26 = metadata !{i32 10, i32 0, metadata !4, null}
86 !27 = metadata !{i32 11, i32 0, metadata !4, null}
87 !28 = metadata !{i32 786688, metadata !4, metadata !"i1", metadata !5, i32 11, metadata !14, i32 0, i32 0, metadata !29} ; [ DW_TAG_auto_variable ] [i1] [line 11] [piece, size 4, offset 0]
88 !29 = metadata !{i32 3, i32 0, i32 4}
89 !30 = metadata !{i32 786688, metadata !4, metadata !"i1", metadata !5, i32 11, metadata !14, i32 0, i32 0, metadata !31} ; [ DW_TAG_auto_variable ] [i1] [line 11] [piece, size 12, offset 0]
90 !31 = metadata !{i32 3, i32 0, i32 12}
91 !32 = metadata !{i32 12, i32 0, metadata !4, null}
0 ; RUN: llc %s -filetype=obj -o - | llvm-dwarfdump - | FileCheck %s
1 ;
2 ; // Compile with -O1
3 ; typedef struct {
4 ; int a;
5 ; int b;
6 ; } Inner;
7 ;
8 ; typedef struct {
9 ; Inner inner[2];
10 ; } Outer;
11 ;
12 ; int foo(Outer outer) {
13 ; Inner i1 = outer.inner[1];
14 ; return i1.a;
15 ; }
16 ;
17 ; CHECK: DW_TAG_formal_parameter [3]
18 ; CHECK-NEXT: DW_AT_location [DW_FORM_data4] ([[LOC:.*]])
19 ; CHECK-NEXT: DW_AT_name {{.*}}"outer"
20 ; CHECK: DW_TAG_variable
21 ; rsi, piece 0x00000004, bit-piece 32 0
22 ; CHECK-NEXT: DW_AT_location [DW_FORM_block1] (<0x06> 54 93 04 9d 20 00 )
23 ; CHECK-NEXT: "i1"
24
25 ; CHECK: .debug_loc
26 ; CHECK: [[LOC]]:
27 ; CHECK: Beginning address offset: 0x0000000000000000
28 ; CHECK: Ending address offset: 0x0000000000000004
29 ; rdi, piece 0x00000008, piece 0x00000004, rsi, piece 0x00000004
30 ; CHECK: Location description: 55 93 08 93 04 54 93 04
31 ;
32 ; ModuleID = '/Volumes/Data/llvm/test/DebugInfo/X86/sroasplit-2.ll'
33 target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
34 target triple = "x86_64-apple-macosx10.9.0"
35
36 ; Function Attrs: nounwind ssp uwtable
37 define i32 @foo(i64 %outer.coerce0, i64 %outer.coerce1) #0 {
38 call void @llvm.dbg.value(metadata !{i64 %outer.coerce0}, i64 0, metadata !24), !dbg !26
39 call void @llvm.dbg.declare(metadata !{null}, metadata !27), !dbg !26
40 call void @llvm.dbg.value(metadata !{i64 %outer.coerce1}, i64 0, metadata !29), !dbg !26
41 call void @llvm.dbg.declare(metadata !{null}, metadata !31), !dbg !26
42 %outer.sroa.1.8.extract.trunc = trunc i64 %outer.coerce1 to i32, !dbg !33
43 call void @llvm.dbg.value(metadata !{i32 %outer.sroa.1.8.extract.trunc}, i64 0, metadata !34), !dbg !33
44 %outer.sroa.1.12.extract.shift = lshr i64 %outer.coerce1, 32, !dbg !33
45 %outer.sroa.1.12.extract.trunc = trunc i64 %outer.sroa.1.12.extract.shift to i32, !dbg !33
46 call void @llvm.dbg.value(metadata !{i32 %outer.sroa.1.12.extract.trunc}, i64 0, metadata !34), !dbg !33
47 call void @llvm.dbg.declare(metadata !{null}, metadata !34), !dbg !33
48 ret i32 %outer.sroa.1.8.extract.trunc, !dbg !36
49 }
50
51 ; Function Attrs: nounwind readnone
52 declare void @llvm.dbg.declare(metadata, metadata) #1
53
54 ; Function Attrs: nounwind
55 declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture, i8* nocapture readonly, i64, i32, i1) #2
56
57 ; Function Attrs: nounwind readnone
58 declare void @llvm.dbg.value(metadata, i64, metadata) #1
59
60 attributes #0 = { nounwind ssp uwtable "no-frame-pointer-elim"="true" }
61 attributes #1 = { nounwind readnone }
62 attributes #2 = { nounwind }
63
64 !llvm.dbg.cu = !{!0}
65 !llvm.module.flags = !{!21, !22}
66 !llvm.ident = !{!23}
67
68 !0 = metadata !{i32 786449, metadata !1, i32 12, metadata !"clang version 3.5.0 ", i1 false, metadata !"", i32 0, metadata !2, metadata !2, metadata !3, metadata !2, metadata !2, metadata !"", i32 1} ; [ DW_TAG_compile_unit ] [/sroasplit-2.c] [DW_LANG_C99]
69 !1 = metadata !{metadata !"sroasplit-2.c", metadata !""}
70 !2 = metadata !{}
71 !3 = metadata !{metadata !4}
72 !4 = metadata !{i32 786478, metadata !1, metadata !5, metadata !"foo", metadata !"foo", metadata !"", i32 10, metadata !6, i1 false, i1 true, i32 0, i32 0, null, i32 256, i1 false, i32 (i64, i64)* @foo, null, null, metadata !2, i32 10} ; [ DW_TAG_subprogram ] [line 10] [def] [foo]
73 !5 = metadata !{i32 786473, metadata !1} ; [ DW_TAG_file_type ] [/sroasplit-2.c]
74 !6 = metadata !{i32 786453, i32 0, null, metadata !"", i32 0, i64 0, i64 0, i64 0, i32 0, null, metadata !7, i32 0, null, null, null} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ]
75 !7 = metadata !{metadata !8, metadata !9}
76 !8 = metadata !{i32 786468, null, null, metadata !"int", i32 0, i64 32, i64 32, i64 0, i32 0, i32 5} ; [ DW_TAG_base_type ] [int] [line 0, size 32, align 32, offset 0, enc DW_ATE_signed]
77 !9 = metadata !{i32 786454, metadata !1, null, metadata !"Outer", i32 8, i64 0, i64 0, i64 0, i32 0, metadata !10} ; [ DW_TAG_typedef ] [Outer] [line 8, size 0, align 0, offset 0] [from ]
78 !10 = metadata !{i32 786451, metadata !1, null, metadata !"", i32 6, i64 128, i64 32, i32 0, i32 0, null, metadata !11, i32 0, null, null, null} ; [ DW_TAG_structure_type ] [line 6, size 128, align 32, offset 0] [def] [from ]
79 !11 = metadata !{metadata !12}
80 !12 = metadata !{i32 786445, metadata !1, metadata !10, metadata !"inner", i32 7, i64 128, i64 32, i64 0, i32 0, metadata !13} ; [ DW_TAG_member ] [inner] [line 7, size 128, align 32, offset 0] [from ]
81 !13 = metadata !{i32 786433, null, null, metadata !"", i32 0, i64 128, i64 32, i32 0, i32 0, metadata !14, metadata !19, i32 0, null, null, null} ; [ DW_TAG_array_type ] [line 0, size 128, align 32, offset 0] [from Inner]
82 !14 = metadata !{i32 786454, metadata !1, null, metadata !"Inner", i32 4, i64 0, i64 0, i64 0, i32 0, metadata !15} ; [ DW_TAG_typedef ] [Inner] [line 4, size 0, align 0, offset 0] [from ]
83 !15 = metadata !{i32 786451, metadata !1, null, metadata !"", i32 1, i64 64, i64 32, i32 0, i32 0, null, metadata !16, i32 0, null, null, null} ; [ DW_TAG_structure_type ] [line 1, size 64, align 32, offset 0] [def] [from ]
84 !16 = metadata !{metadata !17, metadata !18}
85 !17 = metadata !{i32 786445, metadata !1, metadata !15, metadata !"a", i32 2, i64 32, i64 32, i64 0, i32 0, metadata !8} ; [ DW_TAG_member ] [a] [line 2, size 32, align 32, offset 0] [from int]
86 !18 = metadata !{i32 786445, metadata !1, metadata !15, metadata !"b", i32 3, i64 32, i64 32, i64 32, i32 0, metadata !8} ; [ DW_TAG_member ] [b] [line 3, size 32, align 32, offset 32] [from int]
87 !19 = metadata !{metadata !20}
88 !20 = metadata !{i32 786465, i64 0, i64 2} ; [ DW_TAG_subrange_type ] [0, 1]
89 !21 = metadata !{i32 2, metadata !"Dwarf Version", i32 2}
90 !22 = metadata !{i32 1, metadata !"Debug Info Version", i32 1}
91 !23 = metadata !{metadata !"clang version 3.5.0 "}
92 !24 = metadata !{i32 786689, metadata !4, metadata !"outer", metadata !5, i32 16777226, metadata !9, i32 0, i32 0, metadata !25} ; [ DW_TAG_arg_variable ] [outer] [line 10] [piece, size 8, offset 0]
93 !25 = metadata !{i32 3, i32 0, i32 8}
94 !26 = metadata !{i32 10, i32 0, metadata !4, null}
95 !27 = metadata !{i32 786689, metadata !4, metadata !"outer", metadata !5, i32 16777226, metadata !9, i32 0, i32 0, metadata !28} ; [ DW_TAG_arg_variable ] [outer] [line 10] [piece, size 8, offset 8]
96 !28 = metadata !{i32 3, i32 8, i32 8}
97 !29 = metadata !{i32 786689, metadata !4, metadata !"outer", metadata !5, i32 16777226, metadata !9, i32 0, i32 0, metadata !30} ; [ DW_TAG_arg_variable ] [outer] [line 10] [piece, size 4, offset 12]
98 !30 = metadata !{i32 3, i32 12, i32 4}
99 !31 = metadata !{i32 786689, metadata !4, metadata !"outer", metadata !5, i32 16777226, metadata !9, i32 0, i32 0, metadata !32} ; [ DW_TAG_arg_variable ] [outer] [line 10] [piece, size 4, offset 8]
100 !32 = metadata !{i32 3, i32 8, i32 4}
101 !33 = metadata !{i32 11, i32 0, metadata !4, null}
102 !34 = metadata !{i32 786688, metadata !4, metadata !"i1", metadata !5, i32 11, metadata !14, i32 0, i32 0, metadata !35} ; [ DW_TAG_auto_variable ] [i1] [line 11] [piece, size 4, offset 0]
103 !35 = metadata !{i32 3, i32 0, i32 4}
104 !36 = metadata !{i32 12, i32 0, metadata !4, null}