Index: llvm/trunk/include/llvm/CodeGen/AsmPrinter.h =================================================================== --- llvm/trunk/include/llvm/CodeGen/AsmPrinter.h +++ llvm/trunk/include/llvm/CodeGen/AsmPrinter.h @@ -468,10 +468,6 @@ /// Get the value for DW_AT_APPLE_isa. Zero if no isa encoding specified. virtual unsigned getISAEncoding() { return 0; } - /// EmitDwarfRegOp - Emit a dwarf register operation. - virtual void EmitDwarfRegOp(ByteStreamer &BS, - const MachineLocation &MLoc) const; - //===------------------------------------------------------------------===// // Dwarf Lowering Routines //===------------------------------------------------------------------===// Index: llvm/trunk/lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp =================================================================== --- llvm/trunk/lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp +++ llvm/trunk/lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp @@ -174,36 +174,6 @@ EmitInt32(S.getOffset()); } -/// EmitDwarfRegOp - Emit dwarf register operation. -void AsmPrinter::EmitDwarfRegOp(ByteStreamer &Streamer, - const MachineLocation &MLoc) const { - DebugLocDwarfExpression Expr(getDwarfVersion(), Streamer); - const MCRegisterInfo *MRI = MMI->getContext().getRegisterInfo(); - int Reg = MRI->getDwarfRegNum(MLoc.getReg(), false); - if (Reg < 0) { - // We assume that pointers are always in an addressable register. - if (MLoc.isIndirect()) - // FIXME: We have no reasonable way of handling errors in here. The - // caller might be in the middle of a dwarf expression. We should - // probably assert that Reg >= 0 once debug info generation is more - // mature. - return Expr.EmitOp(dwarf::DW_OP_nop, - "nop (could not find a dwarf register number)"); - - // Attempt to find a valid super- or sub-register. - if (!Expr.AddMachineRegFragment(*MF->getSubtarget().getRegisterInfo(), - MLoc.getReg())) - Expr.EmitOp(dwarf::DW_OP_nop, - "nop (could not find a dwarf register number)"); - return; - } - - if (MLoc.isIndirect()) - Expr.AddRegIndirect(Reg, MLoc.getOffset()); - else - Expr.AddReg(Reg); -} - //===----------------------------------------------------------------------===// // Dwarf Lowering Routines //===----------------------------------------------------------------------===// Index: llvm/trunk/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp =================================================================== --- llvm/trunk/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp +++ llvm/trunk/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp @@ -180,7 +180,9 @@ if (Expr) { DIEDwarfExpression DwarfExpr(*Asm, *this, *Loc); + DwarfExpr.addFragmentOffset(Expr); DwarfExpr.AddExpression(Expr); + DwarfExpr.finalize(); } } @@ -498,8 +500,10 @@ DIELoc *Loc = new (DIEValueAllocator) DIELoc; DIEDwarfExpression DwarfExpr(*Asm, *this, *Loc); // If there is an expression, emit raw unsigned bytes. + DwarfExpr.addFragmentOffset(Expr); DwarfExpr.AddUnsignedConstant(DVInsn->getOperand(0).getImm()); DwarfExpr.AddExpression(Expr); + DwarfExpr.finalize(); addBlock(*VariableDie, dwarf::DW_AT_location, Loc); } else addConstantValue(*VariableDie, DVInsn->getOperand(0), DV.getType()); @@ -524,11 +528,13 @@ const TargetFrameLowering *TFI = Asm->MF->getSubtarget().getFrameLowering(); int Offset = TFI->getFrameIndexReference(*Asm->MF, FI, FrameReg); assert(Expr != DV.getExpression().end() && "Wrong number of expressions"); + DwarfExpr.addFragmentOffset(*Expr); DwarfExpr.AddMachineRegIndirect(*Asm->MF->getSubtarget().getRegisterInfo(), FrameReg, Offset); DwarfExpr.AddExpression(*Expr); ++Expr; } + DwarfExpr.finalize(); addBlock(*VariableDie, dwarf::DW_AT_location, Loc); return VariableDie; @@ -727,16 +733,22 @@ void DwarfCompileUnit::addAddress(DIE &Die, dwarf::Attribute Attribute, const MachineLocation &Location) { DIELoc *Loc = new (DIEValueAllocator) DIELoc; + DIEDwarfExpression Expr(*Asm, *this, *Loc); bool validReg; if (Location.isReg()) - validReg = addRegisterFragment(*Loc, Location.getReg()); + validReg = Expr.AddMachineReg(*Asm->MF->getSubtarget().getRegisterInfo(), + Location.getReg()); else - validReg = addRegisterOffset(*Loc, Location.getReg(), Location.getOffset()); + validReg = + Expr.AddMachineRegIndirect(*Asm->MF->getSubtarget().getRegisterInfo(), + Location.getReg(), Location.getOffset()); if (!validReg) return; + Expr.finalize(); + // Now attach the location information to the DIE. addBlock(Die, Attribute, Loc); } @@ -750,9 +762,11 @@ const MachineLocation &Location) { DIELoc *Loc = new (DIEValueAllocator) DIELoc; DIEDwarfExpression DwarfExpr(*Asm, *this, *Loc); - DIExpressionCursor ExprCursor(DV.getSingleExpression()); + const DIExpression *Expr = DV.getSingleExpression(); + DIExpressionCursor ExprCursor(Expr); const TargetRegisterInfo &TRI = *Asm->MF->getSubtarget().getRegisterInfo(); auto Reg = Location.getReg(); + DwarfExpr.addFragmentOffset(Expr); bool ValidReg = Location.getOffset() ? DwarfExpr.AddMachineRegIndirect(TRI, Reg, Location.getOffset()) Index: llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp =================================================================== --- llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp +++ llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp @@ -1413,9 +1413,9 @@ static void emitDebugLocValue(const AsmPrinter &AP, const DIBasicType *BT, ByteStreamer &Streamer, const DebugLocEntry::Value &Value, - unsigned FragmentOffsetInBits) { + DwarfExpression &DwarfExpr) { DIExpressionCursor ExprCursor(Value.getExpression()); - DebugLocDwarfExpression DwarfExpr(AP.getDwarfVersion(), Streamer); + DwarfExpr.addFragmentOffset(Value.getExpression()); // Regular entry. if (Value.isInt()) { if (BT && (BT->getEncoding() == dwarf::DW_ATE_signed || @@ -1425,23 +1425,16 @@ DwarfExpr.AddUnsignedConstant(Value.getInt()); } else if (Value.isLocation()) { MachineLocation Loc = Value.getLoc(); - if (!ExprCursor) - // Regular entry. - AP.EmitDwarfRegOp(Streamer, Loc); - else { - // Complex address entry. - const TargetRegisterInfo &TRI = *AP.MF->getSubtarget().getRegisterInfo(); - if (Loc.getOffset()) - DwarfExpr.AddMachineRegIndirect(TRI, Loc.getReg(), Loc.getOffset()); - else - DwarfExpr.AddMachineRegExpression(TRI, ExprCursor, Loc.getReg(), - FragmentOffsetInBits); - } + const TargetRegisterInfo &TRI = *AP.MF->getSubtarget().getRegisterInfo(); + if (Loc.getOffset()) + DwarfExpr.AddMachineRegIndirect(TRI, Loc.getReg(), Loc.getOffset()); + else + DwarfExpr.AddMachineRegExpression(TRI, ExprCursor, Loc.getReg()); } else if (Value.isConstantFP()) { APInt RawBytes = Value.getConstantFP()->getValueAPF().bitcastToAPInt(); DwarfExpr.AddUnsignedConstant(RawBytes); } - DwarfExpr.AddExpression(std::move(ExprCursor), FragmentOffsetInBits); + DwarfExpr.AddExpression(std::move(ExprCursor)); } void DebugLocEntry::finalize(const AsmPrinter &AP, @@ -1449,6 +1442,7 @@ const DIBasicType *BT) { DebugLocStream::EntryBuilder Entry(List, Begin, End); BufferByteStreamer Streamer = Entry.getStreamer(); + DebugLocDwarfExpression DwarfExpr(AP.getDwarfVersion(), Streamer); const DebugLocEntry::Value &Value = Values[0]; if (Value.isFragment()) { // Emit all fragments that belong to the same variable and range. @@ -1457,27 +1451,15 @@ }) && "all values are expected to be fragments"); assert(std::is_sorted(Values.begin(), Values.end()) && "fragments are expected to be sorted"); - - unsigned Offset = 0; - for (auto Fragment : Values) { - const DIExpression *Expr = Fragment.getExpression(); - unsigned FragmentOffset = Expr->getFragmentOffsetInBits(); - unsigned FragmentSize = Expr->getFragmentSizeInBits(); - assert(Offset <= FragmentOffset && "overlapping or duplicate fragments"); - if (Offset < FragmentOffset) { - // DWARF represents gaps as pieces with no locations. - DebugLocDwarfExpression Expr(AP.getDwarfVersion(), Streamer); - Expr.AddOpPiece(FragmentOffset-Offset, 0); - Offset += FragmentOffset-Offset; - } - Offset += FragmentSize; - emitDebugLocValue(AP, BT, Streamer, Fragment, FragmentOffset); - } + for (auto Fragment : Values) + emitDebugLocValue(AP, BT, Streamer, Fragment, DwarfExpr); + } else { assert(Values.size() == 1 && "only fragments may have >1 value"); - emitDebugLocValue(AP, BT, Streamer, Value, 0); + emitDebugLocValue(AP, BT, Streamer, Value, DwarfExpr); } + DwarfExpr.finalize(); } void DwarfDebug::emitDebugLocEntryLocation(const DebugLocStream::Entry &Entry) { Index: llvm/trunk/lib/CodeGen/AsmPrinter/DwarfExpression.h =================================================================== --- llvm/trunk/lib/CodeGen/AsmPrinter/DwarfExpression.h +++ llvm/trunk/lib/CodeGen/AsmPrinter/DwarfExpression.h @@ -39,6 +39,9 @@ End = Expr->expr_op_end(); } + DIExpressionCursor(ArrayRef Expr) + : Start(Expr.begin()), End(Expr.end()) {} + /// Consume one operation. Optional take() { if (Start == End) @@ -77,10 +80,26 @@ class DwarfExpression { protected: unsigned DwarfVersion; + /// Current Fragment Offset in Bits. + uint64_t OffsetInBits = 0; + + /// Sometimes we need to add a DW_OP_bit_piece to describe a subregister. + unsigned SubRegisterSizeInBits = 0; + unsigned SubRegisterOffsetInBits = 0; + + /// Push a DW_OP_piece / DW_OP_bit_piece for emitting later, if one is needed + /// to represent a subregister. + void setSubRegisterPiece(unsigned SizeInBits, unsigned OffsetInBits) { + SubRegisterSizeInBits = SizeInBits; + SubRegisterOffsetInBits = OffsetInBits; + } public: DwarfExpression(unsigned DwarfVersion) : DwarfVersion(DwarfVersion) {} - virtual ~DwarfExpression() {} + virtual ~DwarfExpression() {}; + + /// This needs to be called last to commit any pending changes. + void finalize(); /// Output a dwarf operand and an optional assembler comment. virtual void EmitOp(uint8_t Op, const char *Comment = nullptr) = 0; @@ -97,9 +116,9 @@ /// Emit an (double-)indirect dwarf register operation. void AddRegIndirect(int DwarfReg, int Offset, bool Deref = false); - /// Emit a DW_OP_piece operation for a variable fragment. - /// \param OffsetInBits This is the offset where the fragment appears - /// inside the *source variable*. + /// Emit a DW_OP_piece or DW_OP_bit_piece operation for a variable fragment. + /// \param OffsetInBits This is an optional offset into the location that + /// is at the top of the DWARF stack. void AddOpPiece(unsigned SizeInBits, unsigned OffsetInBits = 0); /// Emit a shift-right dwarf expression. @@ -125,10 +144,7 @@ /// Emit a partial DWARF register operation. /// - /// \param MachineReg the register, - /// \param FragmentSizeInBits size and - /// \param FragmentOffsetInBits offset of the fragment in bits, if this is - /// a fragment of an aggregate value. + /// \param MachineReg The register number. /// /// If size and offset is zero an operation for the entire register is /// emitted: Some targets do not provide a DWARF register number for every @@ -137,9 +153,7 @@ /// multiple subregisters that alias the register. /// /// \return false if no DWARF register exists for MachineReg. - bool AddMachineRegFragment(const TargetRegisterInfo &TRI, unsigned MachineReg, - unsigned FragmentSizeInBits = 0, - unsigned FragmentOffsetInBits = 0); + bool AddMachineReg(const TargetRegisterInfo &TRI, unsigned MachineReg); /// Emit a signed constant. void AddSignedConstant(int64_t Value); @@ -167,6 +181,10 @@ /// fragment inside the entire variable. void AddExpression(DIExpressionCursor &&Expr, unsigned FragmentOffsetInBits = 0); + + /// If applicable, emit an empty DW_OP_piece / DW_OP_bit_piece to advance to + /// the fragment described by \c Expr. + void addFragmentOffset(const DIExpression *Expr); }; /// DwarfExpression implementation for .debug_loc entries. Index: llvm/trunk/lib/CodeGen/AsmPrinter/DwarfExpression.cpp =================================================================== --- llvm/trunk/lib/CodeGen/AsmPrinter/DwarfExpression.cpp +++ llvm/trunk/lib/CodeGen/AsmPrinter/DwarfExpression.cpp @@ -46,7 +46,9 @@ } void DwarfExpression::AddOpPiece(unsigned SizeInBits, unsigned OffsetInBits) { - assert(SizeInBits > 0 && "piece has size zero"); + if (!SizeInBits) + return; + const unsigned SizeOfByte = 8; if (OffsetInBits > 0 || SizeInBits % SizeOfByte) { EmitOp(dwarf::DW_OP_bit_piece); @@ -57,6 +59,7 @@ unsigned ByteSize = SizeInBits / SizeOfByte; EmitUnsigned(ByteSize); } + this->OffsetInBits += SizeInBits; } void DwarfExpression::AddShr(unsigned ShiftBy) { @@ -82,10 +85,8 @@ return true; } -bool DwarfExpression::AddMachineRegFragment(const TargetRegisterInfo &TRI, - unsigned MachineReg, - unsigned FragmentSizeInBits, - unsigned FragmentOffsetInBits) { +bool DwarfExpression::AddMachineReg(const TargetRegisterInfo &TRI, + unsigned MachineReg) { if (!TRI.isPhysicalRegister(MachineReg)) return false; @@ -94,8 +95,6 @@ // If this is a valid register number, emit it. if (Reg >= 0) { AddReg(Reg); - if (FragmentSizeInBits) - AddOpPiece(FragmentSizeInBits, FragmentOffsetInBits); return true; } @@ -108,24 +107,15 @@ unsigned Size = TRI.getSubRegIdxSize(Idx); unsigned RegOffset = TRI.getSubRegIdxOffset(Idx); AddReg(Reg, "super-register"); - if (FragmentOffsetInBits == RegOffset) { - AddOpPiece(Size, RegOffset); - } else { - // If this is part of a variable in a sub-register at a non-zero offset, - // we need to manually shift the value into place, since the - // DW_OP_LLVM_fragment describes the part of the variable, not the - // position of the subregister. - if (RegOffset) - AddShr(RegOffset); - AddOpPiece(Size, FragmentOffsetInBits); - } + // Use a DW_OP_bit_piece to describe the sub-register. + setSubRegisterPiece(Size, RegOffset); return true; } } // Otherwise, attempt to find a covering set of sub-register numbers. // For example, Q0 on ARM is a composition of D0+D1. - unsigned CurPos = FragmentOffsetInBits; + unsigned CurPos = 0; // The size of the register in bits, assuming 8 bits per byte. unsigned RegSize = TRI.getMinimalPhysRegClass(MachineReg)->getSize() * 8; // Keep track of the bits in the register we already emitted, so we @@ -147,7 +137,10 @@ // its range, emit a DWARF piece for it. if (Reg >= 0 && Intersection.any()) { AddReg(Reg, "sub-register"); - AddOpPiece(Size, Offset == CurPos ? 0 : Offset); + // Emit a piece for the any gap in the coverage. + if (Offset > CurPos) + AddOpPiece(Offset - CurPos); + AddOpPiece(Size); CurPos = Offset + Size; // Mark it as emitted. @@ -155,7 +148,7 @@ } } - return CurPos > FragmentOffsetInBits; + return CurPos; } void DwarfExpression::AddStackValue() { @@ -191,35 +184,21 @@ } } -static unsigned getOffsetOrZero(unsigned OffsetInBits, - unsigned FragmentOffsetInBits) { - if (OffsetInBits == FragmentOffsetInBits) - return 0; - assert(OffsetInBits >= FragmentOffsetInBits && "overlapping fragments"); - return OffsetInBits; -} - bool DwarfExpression::AddMachineRegExpression(const TargetRegisterInfo &TRI, DIExpressionCursor &ExprCursor, unsigned MachineReg, unsigned FragmentOffsetInBits) { if (!ExprCursor) - return AddMachineRegFragment(TRI, MachineReg); + return AddMachineReg(TRI, MachineReg); // Pattern-match combinations for which more efficient representations exist // first. bool ValidReg = false; auto Op = ExprCursor.peek(); switch (Op->getOp()) { - case dwarf::DW_OP_LLVM_fragment: { - unsigned OffsetInBits = Op->getArg(0); - unsigned SizeInBits = Op->getArg(1); - // Piece always comes at the end of the expression. - AddMachineRegFragment(TRI, MachineReg, SizeInBits, - getOffsetOrZero(OffsetInBits, FragmentOffsetInBits)); - ExprCursor.take(); + default: + ValidReg = AddMachineReg(TRI, MachineReg); break; - } case dwarf::DW_OP_plus: case dwarf::DW_OP_minus: { // [DW_OP_reg,Offset,DW_OP_plus, DW_OP_deref] --> [DW_OP_breg, Offset]. @@ -231,7 +210,7 @@ TRI, MachineReg, Op->getOp() == dwarf::DW_OP_plus ? Offset : -Offset); ExprCursor.consume(2); } else - ValidReg = AddMachineRegFragment(TRI, MachineReg); + ValidReg = AddMachineReg(TRI, MachineReg); break; } case dwarf::DW_OP_deref: @@ -250,10 +229,25 @@ auto Op = ExprCursor.take(); switch (Op->getOp()) { case dwarf::DW_OP_LLVM_fragment: { - unsigned OffsetInBits = Op->getArg(0); - unsigned SizeInBits = Op->getArg(1); - AddOpPiece(SizeInBits, - getOffsetOrZero(OffsetInBits, FragmentOffsetInBits)); + unsigned SizeInBits = Op->getArg(1); + unsigned FragmentOffset = Op->getArg(0); + // The fragment offset must have already been adjusted by emitting an + // empty DW_OP_piece / DW_OP_bit_piece before we emitted the base + // location. + assert(OffsetInBits >= FragmentOffset && "fragment offset not added?"); + + // If \a AddMachineReg already emitted DW_OP_piece operations to represent + // a super-register by splicing together sub-registers, subtract the size + // of the pieces that was already emitted. + SizeInBits -= OffsetInBits - FragmentOffset; + + // If \a AddMachineReg requested a DW_OP_bit_piece to stencil out a + // sub-register that is smaller than the current fragment's size, use it. + if (SubRegisterSizeInBits) + SizeInBits = std::min(SizeInBits, SubRegisterSizeInBits); + + AddOpPiece(SizeInBits, SubRegisterOffsetInBits); + setSubRegisterPiece(0, 0); break; } case dwarf::DW_OP_plus: @@ -281,3 +275,20 @@ } } } + +void DwarfExpression::finalize() { + if (SubRegisterSizeInBits) + AddOpPiece(SubRegisterSizeInBits, SubRegisterOffsetInBits); +} + +void DwarfExpression::addFragmentOffset(const DIExpression *Expr) { + if (!Expr || !Expr->isFragment()) + return; + + uint64_t FragmentOffset = Expr->getFragmentOffsetInBits(); + assert(FragmentOffset >= OffsetInBits && + "overlapping or duplicate fragments"); + if (FragmentOffset > OffsetInBits) + AddOpPiece(FragmentOffset - OffsetInBits); + OffsetInBits = FragmentOffset; +} Index: llvm/trunk/lib/CodeGen/AsmPrinter/DwarfUnit.h =================================================================== --- llvm/trunk/lib/CodeGen/AsmPrinter/DwarfUnit.h +++ llvm/trunk/lib/CodeGen/AsmPrinter/DwarfUnit.h @@ -235,19 +235,6 @@ /// Add template parameters in buffer. void addTemplateParams(DIE &Buffer, DINodeArray TParams); - /// Add register operand for a source variable fragment of the specified size - /// and offset. - /// - /// \returns false if the register does not exist, e.g., because it was never - /// materialized. - bool addRegisterFragment(DIELoc &TheDie, unsigned Reg, - unsigned SizeInBits = 0, unsigned OffsetInBits = 0); - - /// Add register offset. - /// \returns false if the register does not exist, e.g., because it was never - /// materialized. - bool addRegisterOffset(DIELoc &TheDie, unsigned Reg, int64_t Offset); - // FIXME: Should be reformulated in terms of addComplexAddress. /// Start with the address based on the location provided, and generate the /// DWARF information necessary to find the actual Block variable (navigating Index: llvm/trunk/lib/CodeGen/AsmPrinter/DwarfUnit.cpp =================================================================== --- llvm/trunk/lib/CodeGen/AsmPrinter/DwarfUnit.cpp +++ llvm/trunk/lib/CodeGen/AsmPrinter/DwarfUnit.cpp @@ -371,22 +371,6 @@ addSourceLine(Die, NS->getLine(), NS->getFilename(), NS->getDirectory()); } -bool DwarfUnit::addRegisterFragment(DIELoc &TheDie, unsigned Reg, - unsigned SizeInBits, - unsigned OffsetInBits) { - DIEDwarfExpression Expr(*Asm, *this, TheDie); - Expr.AddMachineRegFragment(*Asm->MF->getSubtarget().getRegisterInfo(), Reg, - SizeInBits, OffsetInBits); - return true; -} - -bool DwarfUnit::addRegisterOffset(DIELoc &TheDie, unsigned Reg, - int64_t Offset) { - DIEDwarfExpression Expr(*Asm, *this, TheDie); - return Expr.AddMachineRegIndirect(*Asm->MF->getSubtarget().getRegisterInfo(), - Reg, Offset); -} - /* Byref variables, in Blocks, are declared by the programmer as "SomeType VarName;", but the compiler creates a __Block_byref_x_VarName struct, and gives the variable VarName either the struct, or a pointer to the struct, as @@ -479,12 +463,17 @@ // Decode the original location, and use that as the start of the byref // variable's location. DIELoc *Loc = new (DIEValueAllocator) DIELoc; + SmallVector DIExpr; + DIEDwarfExpression Expr(*Asm, *this, *Loc); bool validReg; if (Location.isReg()) - validReg = addRegisterFragment(*Loc, Location.getReg()); + validReg = Expr.AddMachineReg(*Asm->MF->getSubtarget().getRegisterInfo(), + Location.getReg()); else - validReg = addRegisterOffset(*Loc, Location.getReg(), Location.getOffset()); + validReg = + Expr.AddMachineRegIndirect(*Asm->MF->getSubtarget().getRegisterInfo(), + Location.getReg(), Location.getOffset()); if (!validReg) return; @@ -492,27 +481,29 @@ // If we started with a pointer to the __Block_byref... struct, then // the first thing we need to do is dereference the pointer (DW_OP_deref). if (isPointer) - addUInt(*Loc, dwarf::DW_FORM_data1, dwarf::DW_OP_deref); + DIExpr.push_back(dwarf::DW_OP_deref); // Next add the offset for the '__forwarding' field: // DW_OP_plus_uconst ForwardingFieldOffset. Note there's no point in // adding the offset if it's 0. if (forwardingFieldOffset > 0) { - addUInt(*Loc, dwarf::DW_FORM_data1, dwarf::DW_OP_plus_uconst); - addUInt(*Loc, dwarf::DW_FORM_udata, forwardingFieldOffset); + DIExpr.push_back(dwarf::DW_OP_plus); + DIExpr.push_back(forwardingFieldOffset); } // Now dereference the __forwarding field to get to the real __Block_byref // struct: DW_OP_deref. - addUInt(*Loc, dwarf::DW_FORM_data1, dwarf::DW_OP_deref); + DIExpr.push_back(dwarf::DW_OP_deref); // Now that we've got the real __Block_byref... struct, add the offset // for the variable's field to get to the location of the actual variable: // DW_OP_plus_uconst varFieldOffset. Again, don't add if it's 0. if (varFieldOffset > 0) { - addUInt(*Loc, dwarf::DW_FORM_data1, dwarf::DW_OP_plus_uconst); - addUInt(*Loc, dwarf::DW_FORM_udata, varFieldOffset); + DIExpr.push_back(dwarf::DW_OP_plus); + DIExpr.push_back(varFieldOffset); } + Expr.AddExpression(makeArrayRef(DIExpr)); + Expr.finalize(); // Now attach the location information to the DIE. addBlock(Die, Attribute, Loc); Index: llvm/trunk/test/DebugInfo/AArch64/frameindices.ll =================================================================== --- llvm/trunk/test/DebugInfo/AArch64/frameindices.ll +++ llvm/trunk/test/DebugInfo/AArch64/frameindices.ll @@ -5,8 +5,8 @@ ; CHECK: DW_TAG_inlined_subroutine ; CHECK: "_Z3f111A" ; CHECK: DW_TAG_formal_parameter -; CHECK: DW_AT_location [DW_FORM_block1] (<0x0b> 91 51 9d 78 08 91 4a 9d 38 88 01 ) -; -- fbreg -47, bit-piece 120 8 , fbreg -54, bit-piece 56 136 ------^ +; CHECK: DW_AT_location [DW_FORM_block1] (<0x0c> 93 01 91 51 93 0f 93 01 91 4a 93 07 ) +; -- piece 0x00000001, fbreg -47, piece 0x0000000f, piece 0x00000001, fbreg -54, piece 0x00000007 ------^ ; CHECK: DW_AT_abstract_origin {{.*}} "p1" ; ; long a; Index: llvm/trunk/test/DebugInfo/MIR/ARM/lit.local.cfg =================================================================== --- llvm/trunk/test/DebugInfo/MIR/ARM/lit.local.cfg +++ llvm/trunk/test/DebugInfo/MIR/ARM/lit.local.cfg @@ -0,0 +1,3 @@ +if not 'ARM' in config.root.targets: + config.unsupported = True + Index: llvm/trunk/test/DebugInfo/MIR/ARM/split-superreg-piece.mir =================================================================== --- llvm/trunk/test/DebugInfo/MIR/ARM/split-superreg-piece.mir +++ llvm/trunk/test/DebugInfo/MIR/ARM/split-superreg-piece.mir @@ -0,0 +1,125 @@ +# RUN: llc -filetype=obj -o - %s | llvm-dwarfdump - | FileCheck %s +# CHECK: .debug_info contents: +# CHECK: DW_TAG_variable +# CHECK-NEXT: DW_AT_location [DW_FORM_data4] ([[OFS:.*]]) +# CHECK-NEXT: DW_AT_name {{.*}}"vec" +# CHECK: .debug_loc contents: +# CHECK: [[OFS]]: Beginning address offset: 0x0000000000000016 +# CHECK: Ending address offset: 0x000000000000001e +# CHECK: Location description: 93 10 90 80 02 93 08 90 81 02 93 08 +# piece 0x00000010, d0, piece 0x00000008, d1, piece 0x00000008 +--- | + ; Generate from (and then manually modified to incorporate a DW_OP_LLVM_fragment): + ; typedef float vec2 __attribute__((vector_size(16))); + ; vec2 v(); + ; float f() { + ; vec2 vec = v(); + ; return vec[0] + vec[1]; + ; } + + target datalayout = "e-m:o-p:32:32-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32" + target triple = "thumbv7s-apple-ios5.0.0" + + define float @f() local_unnamed_addr #0 !dbg !9 { + entry: + %call = tail call <4 x float> bitcast (<4 x float> (...)* @v to <4 x float> ()*)() #0, !dbg !19 + tail call void @llvm.dbg.value(metadata <4 x float> %call, i64 0, metadata !14, metadata !20), !dbg !21 + %vecext = extractelement <4 x float> %call, i32 0, !dbg !22 + %vecext1 = extractelement <4 x float> %call, i32 1, !dbg !23 + %add = fadd float %vecext, %vecext1, !dbg !24 + ret float %add, !dbg !25 + } + + declare arm_aapcs_vfpcc <4 x float> @v(...) local_unnamed_addr #0 + + declare void @llvm.dbg.value(metadata, i64, metadata, metadata) #0 + + attributes #0 = { nounwind readnone } + + !llvm.dbg.cu = !{!0} + !llvm.module.flags = !{!3, !4, !5, !6, !7} + !llvm.ident = !{!8} + + !0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 4.0.0 (trunk 286322) (llvm/trunk 286305)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2) + !1 = !DIFile(filename: "v.c", directory: "/") + !2 = !{} + !3 = !{i32 2, !"Dwarf Version", i32 2} + !4 = !{i32 2, !"Debug Info Version", i32 3} + !5 = !{i32 1, !"wchar_size", i32 4} + !6 = !{i32 1, !"min_enum_size", i32 4} + !7 = !{i32 1, !"PIC Level", i32 2} + !8 = !{!"clang version 4.0.0 (trunk 286322) (llvm/trunk 286305)"} + !9 = distinct !DISubprogram(name: "f", scope: !1, file: !1, line: 3, type: !10, isLocal: false, isDefinition: true, scopeLine: 3, isOptimized: true, unit: !0, variables: !13) + !10 = !DISubroutineType(types: !11) + !11 = !{!12} + !12 = !DIBasicType(name: "float", size: 32, encoding: DW_ATE_float) + !13 = !{!14} + !14 = !DILocalVariable(name: "vec", scope: !9, file: !1, line: 4, type: !15) + !15 = !DIDerivedType(tag: DW_TAG_typedef, name: "vec2", file: !1, line: 1, baseType: !16) + !16 = !DICompositeType(tag: DW_TAG_array_type, baseType: !12, size: 256, flags: DIFlagVector, elements: !17) + !17 = !{!18} + !18 = !DISubrange(count: 8) + !19 = !DILocation(line: 4, column: 13, scope: !9) + !20 = !DIExpression(DW_OP_LLVM_fragment, 128, 128) + !21 = !DILocation(line: 4, column: 7, scope: !9) + !22 = !DILocation(line: 5, column: 9, scope: !9) + !23 = !DILocation(line: 5, column: 18, scope: !9) + !24 = !DILocation(line: 5, column: 16, scope: !9) + !25 = !DILocation(line: 5, column: 2, scope: !9) + +... +--- +name: f +alignment: 1 +exposesReturnsTwice: false +legalized: false +regBankSelected: false +selected: false +tracksRegLiveness: true +calleeSavedRegisters: [ '%lr', '%d8', '%d9', '%d10', '%d11', '%d12', '%d13', + '%d14', '%d15', '%q4', '%q5', '%q6', '%q7', '%r4', + '%r5', '%r6', '%r7', '%r8', '%r10', '%r11', '%s16', + '%s17', '%s18', '%s19', '%s20', '%s21', '%s22', + '%s23', '%s24', '%s25', '%s26', '%s27', '%s28', + '%s29', '%s30', '%s31', '%d8_d10', '%d9_d11', '%d10_d12', + '%d11_d13', '%d12_d14', '%d13_d15', '%q4_q5', '%q5_q6', + '%q6_q7', '%q4_q5_q6_q7', '%r4_r5', '%r6_r7', '%r10_r11', + '%d8_d9_d10', '%d9_d10_d11', '%d10_d11_d12', '%d11_d12_d13', + '%d12_d13_d14', '%d13_d14_d15', '%d8_d10_d12', + '%d9_d11_d13', '%d10_d12_d14', '%d11_d13_d15', + '%d8_d10_d12_d14', '%d9_d11_d13_d15', '%d9_d10', + '%d11_d12', '%d13_d14', '%d9_d10_d11_d12', '%d11_d12_d13_d14' ] +frameInfo: + isFrameAddressTaken: false + isReturnAddressTaken: false + hasStackMap: false + hasPatchPoint: false + stackSize: 4 + offsetAdjustment: 0 + maxAlignment: 4 + adjustsStack: true + hasCalls: true + maxCallFrameSize: 0 + hasOpaqueSPAdjustment: false + hasVAStart: false + hasMustTailInVarArgFunc: false +stack: + - { id: 0, type: spill-slot, offset: -4, size: 4, alignment: 4, callee-saved-register: '%lr' } +body: | + bb.0.entry: + liveins: %lr + + early-clobber %sp = frame-setup t2STR_PRE killed undef %lr, %sp, -4, 14, _ + frame-setup CFI_INSTRUCTION def_cfa_offset 4 + frame-setup CFI_INSTRUCTION offset %lr, -4 + tBL 14, _, @v, csr_ios, implicit-def dead %lr, implicit %sp, implicit-def %sp, implicit-def %r0, implicit-def %r1, implicit-def %r2, implicit-def %r3, debug-location !19 + %d1 = VMOVDRR killed %r2, killed %r3, 14, _, implicit-def %q0, debug-location !19 + %d0 = VMOVDRR killed %r0, killed %r1, 14, _, implicit killed %q0, implicit-def %q0, debug-location !19 + DBG_VALUE debug-use %q0, debug-use _, !14, !20, debug-location !21 + %s4 = VMOVS %s1, 14, _, implicit-def %d2, debug-location !24 + %d0 = VADDfd %d0, killed %d2, 14, _, implicit killed %q0, debug-location !24 + %r0 = VMOVRS %s0, 14, _, implicit killed %d0, debug-location !25 + %lr, %sp = t2LDR_POST %sp, 4, 14, _, debug-location !25 + tBX_RET 14, _, implicit %r0, debug-location !25 + +... Index: llvm/trunk/test/DebugInfo/MIR/ARM/split-superreg.mir =================================================================== --- llvm/trunk/test/DebugInfo/MIR/ARM/split-superreg.mir +++ llvm/trunk/test/DebugInfo/MIR/ARM/split-superreg.mir @@ -0,0 +1,125 @@ +# RUN: llc -filetype=obj -o - %s | llvm-dwarfdump - | FileCheck %s +# CHECK: .debug_info contents: +# CHECK: DW_TAG_variable +# CHECK-NEXT: DW_AT_location [DW_FORM_data4] ([[OFS:.*]]) +# CHECK-NEXT: DW_AT_name {{.*}}"vec" +# CHECK: .debug_loc contents: +# CHECK: [[OFS]]: Beginning address offset: 0x0000000000000016 +# CHECK: Ending address offset: 0x000000000000001e +# CHECK: Location description: 90 80 02 93 08 90 81 02 93 08 +# d0, piece 0x00000008, d1, piece 0x00000008 +--- | + ; Generated from: + ; typedef float vec2 __attribute__((vector_size(16))); + ; vec2 v(); + ; float f() { + ; vec2 vec = v(); + ; return vec[0] + vec[1]; + ; } + + target datalayout = "e-m:o-p:32:32-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32" + target triple = "thumbv7s-apple-ios5.0.0" + + define float @f() local_unnamed_addr #0 !dbg !9 { + entry: + %call = tail call <4 x float> bitcast (<4 x float> (...)* @v to <4 x float> ()*)() #0, !dbg !19 + tail call void @llvm.dbg.value(metadata <4 x float> %call, i64 0, metadata !14, metadata !20), !dbg !21 + %vecext = extractelement <4 x float> %call, i32 0, !dbg !22 + %vecext1 = extractelement <4 x float> %call, i32 1, !dbg !23 + %add = fadd float %vecext, %vecext1, !dbg !24 + ret float %add, !dbg !25 + } + + declare arm_aapcs_vfpcc <4 x float> @v(...) local_unnamed_addr #0 + + declare void @llvm.dbg.value(metadata, i64, metadata, metadata) #0 + + attributes #0 = { nounwind readnone } + + !llvm.dbg.cu = !{!0} + !llvm.module.flags = !{!3, !4, !5, !6, !7} + !llvm.ident = !{!8} + + !0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 4.0.0 (trunk 286322) (llvm/trunk 286305)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2) + !1 = !DIFile(filename: "v.c", directory: "/") + !2 = !{} + !3 = !{i32 2, !"Dwarf Version", i32 2} + !4 = !{i32 2, !"Debug Info Version", i32 3} + !5 = !{i32 1, !"wchar_size", i32 4} + !6 = !{i32 1, !"min_enum_size", i32 4} + !7 = !{i32 1, !"PIC Level", i32 2} + !8 = !{!"clang version 4.0.0 (trunk 286322) (llvm/trunk 286305)"} + !9 = distinct !DISubprogram(name: "f", scope: !1, file: !1, line: 3, type: !10, isLocal: false, isDefinition: true, scopeLine: 3, isOptimized: true, unit: !0, variables: !13) + !10 = !DISubroutineType(types: !11) + !11 = !{!12} + !12 = !DIBasicType(name: "float", size: 32, encoding: DW_ATE_float) + !13 = !{!14} + !14 = !DILocalVariable(name: "vec", scope: !9, file: !1, line: 4, type: !15) + !15 = !DIDerivedType(tag: DW_TAG_typedef, name: "vec2", file: !1, line: 1, baseType: !16) + !16 = !DICompositeType(tag: DW_TAG_array_type, baseType: !12, size: 128, flags: DIFlagVector, elements: !17) + !17 = !{!18} + !18 = !DISubrange(count: 4) + !19 = !DILocation(line: 4, column: 13, scope: !9) + !20 = !DIExpression() + !21 = !DILocation(line: 4, column: 7, scope: !9) + !22 = !DILocation(line: 5, column: 9, scope: !9) + !23 = !DILocation(line: 5, column: 18, scope: !9) + !24 = !DILocation(line: 5, column: 16, scope: !9) + !25 = !DILocation(line: 5, column: 2, scope: !9) + +... +--- +name: f +alignment: 1 +exposesReturnsTwice: false +legalized: false +regBankSelected: false +selected: false +tracksRegLiveness: true +calleeSavedRegisters: [ '%lr', '%d8', '%d9', '%d10', '%d11', '%d12', '%d13', + '%d14', '%d15', '%q4', '%q5', '%q6', '%q7', '%r4', + '%r5', '%r6', '%r7', '%r8', '%r10', '%r11', '%s16', + '%s17', '%s18', '%s19', '%s20', '%s21', '%s22', + '%s23', '%s24', '%s25', '%s26', '%s27', '%s28', + '%s29', '%s30', '%s31', '%d8_d10', '%d9_d11', '%d10_d12', + '%d11_d13', '%d12_d14', '%d13_d15', '%q4_q5', '%q5_q6', + '%q6_q7', '%q4_q5_q6_q7', '%r4_r5', '%r6_r7', '%r10_r11', + '%d8_d9_d10', '%d9_d10_d11', '%d10_d11_d12', '%d11_d12_d13', + '%d12_d13_d14', '%d13_d14_d15', '%d8_d10_d12', + '%d9_d11_d13', '%d10_d12_d14', '%d11_d13_d15', + '%d8_d10_d12_d14', '%d9_d11_d13_d15', '%d9_d10', + '%d11_d12', '%d13_d14', '%d9_d10_d11_d12', '%d11_d12_d13_d14' ] +frameInfo: + isFrameAddressTaken: false + isReturnAddressTaken: false + hasStackMap: false + hasPatchPoint: false + stackSize: 4 + offsetAdjustment: 0 + maxAlignment: 4 + adjustsStack: true + hasCalls: true + maxCallFrameSize: 0 + hasOpaqueSPAdjustment: false + hasVAStart: false + hasMustTailInVarArgFunc: false +stack: + - { id: 0, type: spill-slot, offset: -4, size: 4, alignment: 4, callee-saved-register: '%lr' } +body: | + bb.0.entry: + liveins: %lr + + early-clobber %sp = frame-setup t2STR_PRE killed undef %lr, %sp, -4, 14, _ + frame-setup CFI_INSTRUCTION def_cfa_offset 4 + frame-setup CFI_INSTRUCTION offset %lr, -4 + tBL 14, _, @v, csr_ios, implicit-def dead %lr, implicit %sp, implicit-def %sp, implicit-def %r0, implicit-def %r1, implicit-def %r2, implicit-def %r3, debug-location !19 + %d1 = VMOVDRR killed %r2, killed %r3, 14, _, implicit-def %q0, debug-location !19 + %d0 = VMOVDRR killed %r0, killed %r1, 14, _, implicit killed %q0, implicit-def %q0, debug-location !19 + DBG_VALUE debug-use %q0, debug-use _, !14, !20, debug-location !21 + %s4 = VMOVS %s1, 14, _, implicit-def %d2, debug-location !24 + %d0 = VADDfd %d0, killed %d2, 14, _, implicit killed %q0, debug-location !24 + %r0 = VMOVRS %s0, 14, _, implicit killed %d0, debug-location !25 + %lr, %sp = t2LDR_POST %sp, 4, 14, _, debug-location !25 + tBX_RET 14, _, implicit %r0, debug-location !25 + +... Index: llvm/trunk/test/DebugInfo/MIR/X86/bit-piece-dh.mir =================================================================== --- llvm/trunk/test/DebugInfo/MIR/X86/bit-piece-dh.mir +++ llvm/trunk/test/DebugInfo/MIR/X86/bit-piece-dh.mir @@ -0,0 +1,102 @@ +# RUN: llc -filetype=obj -o - %s | llvm-dwarfdump - | FileCheck %s +# CHECK: .debug_info contents: +# CHECK: DW_TAG_variable +# CHECK-NEXT: DW_AT_location [DW_FORM_sec_offset] ([[OFS:.*]]) +# CHECK-NEXT: DW_AT_name {{.*}}"dh" +# CHECK: .debug_loc contents: +# CHECK: [[OFS]]: Beginning address offset: 0x0000000000000002 +# CHECK: Ending address offset: 0x000000000000000c +# CHECK: Location description: 51 9d 08 08 +# rdx, bit-piece 8 8 +--- | + ; Manually created after: + ; char f(int i) { + ; char dh = i>>8; + ; return dh; + ; } + + target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" + target triple = "x86_64-apple-macosx10.12.0" + + define signext i8 @f(i32 %i) local_unnamed_addr #0 !dbg !7 { + entry: + tail call void @llvm.dbg.value(metadata i32 %i, i64 0, metadata !13, metadata !15), !dbg !16 + %shr1 = lshr i32 %i, 8, !dbg !17 + %conv = trunc i32 %shr1 to i8, !dbg !18 + tail call void @llvm.dbg.value(metadata i8 %conv, i64 0, metadata !14, metadata !15), !dbg !19 + ret i8 %conv, !dbg !20 + } + + declare void @llvm.dbg.value(metadata, i64, metadata, metadata) #0 + + attributes #0 = { nounwind readnone } + + !llvm.dbg.cu = !{!0} + !llvm.module.flags = !{!3, !4, !5} + !llvm.ident = !{!6} + + !0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 4.0.0 (trunk 288677) (llvm/trunk 288679)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2) + !1 = !DIFile(filename: "t.c", directory: "/") + !2 = !{} + !3 = !{i32 2, !"Dwarf Version", i32 4} + !4 = !{i32 2, !"Debug Info Version", i32 3} + !5 = !{i32 1, !"PIC Level", i32 2} + !6 = !{!"clang version 4.0.0 (trunk 288677) (llvm/trunk 288679)"} + !7 = distinct !DISubprogram(name: "f", scope: !1, file: !1, line: 1, type: !8, isLocal: false, isDefinition: true, scopeLine: 1, flags: DIFlagPrototyped, isOptimized: true, unit: !0, variables: !12) + !8 = !DISubroutineType(types: !9) + !9 = !{!10, !11} + !10 = !DIBasicType(name: "char", size: 8, encoding: DW_ATE_signed_char) + !11 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) + !12 = !{!13, !14} + !13 = !DILocalVariable(name: "i", arg: 1, scope: !7, file: !1, line: 1, type: !11) + !14 = !DILocalVariable(name: "dh", scope: !7, file: !1, line: 2, type: !10) + !15 = !DIExpression() + !16 = !DILocation(line: 1, column: 12, scope: !7) + !17 = !DILocation(line: 2, column: 14, scope: !7) + !18 = !DILocation(line: 2, column: 13, scope: !7) + !19 = !DILocation(line: 2, column: 8, scope: !7) + !20 = !DILocation(line: 3, column: 3, scope: !7) + +... +--- +name: f +alignment: 4 +exposesReturnsTwice: false +legalized: false +regBankSelected: false +selected: false +tracksRegLiveness: true +liveins: + - { reg: '%edi' } +frameInfo: + isFrameAddressTaken: false + isReturnAddressTaken: false + hasStackMap: false + hasPatchPoint: false + stackSize: 8 + offsetAdjustment: 0 + maxAlignment: 0 + adjustsStack: false + hasCalls: false + maxCallFrameSize: 0 + hasOpaqueSPAdjustment: false + hasVAStart: false + hasMustTailInVarArgFunc: false +fixedStack: + - { id: 0, type: spill-slot, offset: -16, size: 8, alignment: 16 } +body: | + bb.0.entry: + liveins: %edi, %rbp + + frame-setup PUSH64r killed %rbp, implicit-def %rsp, implicit %rsp + CFI_INSTRUCTION def_cfa_offset 16 + CFI_INSTRUCTION offset %rbp, -16 + %rbp = frame-setup MOV64rr %rsp + CFI_INSTRUCTION def_cfa_register %rbp + DBG_VALUE debug-use %dh, debug-use _, !14, !15, debug-location !16 + %edi = SHR32ri killed %edi, 8, implicit-def dead %eflags, debug-location !17 + %eax = MOVSX32rr8 %dil, implicit killed %edi, debug-location !20 + %rbp = POP64r implicit-def %rsp, implicit %rsp, debug-location !20 + RETQ %eax, debug-location !20 + +... Index: llvm/trunk/test/DebugInfo/X86/PR26148.ll =================================================================== --- llvm/trunk/test/DebugInfo/X86/PR26148.ll +++ llvm/trunk/test/DebugInfo/X86/PR26148.ll @@ -21,8 +21,8 @@ ; ; CHECK: 0x00000025: Beginning address offset: 0x0000000000000004 ; CHECK: Ending address offset: 0x0000000000000004 -; CHECK: Location description: 10 03 93 04 55 93 04 -; constu 0x00000003, piece 0x00000004, rdi, piece 0x00000004 +; CHECK: Location description: 10 03 93 04 55 93 02 +; constu 0x00000003, piece 0x00000004, rdi, piece 0x00000002 ; CHECK: Beginning address offset: 0x0000000000000004 ; CHECK: Ending address offset: 0x0000000000000014 ; CHECK: Location description: 10 03 93 04 10 00 Index: llvm/trunk/test/DebugInfo/X86/dw_op_minus_direct.ll =================================================================== --- llvm/trunk/test/DebugInfo/X86/dw_op_minus_direct.ll +++ llvm/trunk/test/DebugInfo/X86/dw_op_minus_direct.ll @@ -0,0 +1,48 @@ +; Test dwarf codegen of DW_OP_minus. +; RUN: llc -filetype=obj < %s | llvm-dwarfdump - | FileCheck %s + +; This was derived manually from: +; int inc(int i) { +; return i+1; +; } + +; CHECK: Beginning address offset: 0x0000000000000000 +; CHECK: Ending address offset: 0x0000000000000004 +; CHECK: Location description: 50 10 01 1c 93 04 +; rax, constu 0x00000001, minus, piece 0x00000004 +source_filename = "minus.c" +target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-apple-macosx10.12.0" + +define i32 @inc(i32 %i) local_unnamed_addr #1 !dbg !7 { +entry: + %add = add nsw i32 %i, 1, !dbg !15 + tail call void @llvm.dbg.value(metadata i32 %add, i64 0, metadata !12, metadata !13), !dbg !14 + ret i32 %add, !dbg !16 +} + +declare void @llvm.dbg.value(metadata, i64, metadata, metadata) #1 + +attributes #1 = { nounwind readnone } + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!3, !4, !5} +!llvm.ident = !{!6} + +!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 4.0.0 (trunk 286322) (llvm/trunk 286305)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2) +!1 = !DIFile(filename: "minus.c", directory: "/tmp") +!2 = !{} +!3 = !{i32 2, !"Dwarf Version", i32 4} +!4 = !{i32 2, !"Debug Info Version", i32 3} +!5 = !{i32 1, !"PIC Level", i32 2} +!6 = !{!"clang version 4.0.0 (trunk 286322) (llvm/trunk 286305)"} +!7 = distinct !DISubprogram(name: "inc", scope: !1, file: !1, line: 1, type: !8, isLocal: false, isDefinition: true, scopeLine: 1, flags: DIFlagPrototyped, isOptimized: true, unit: !0, variables: !11) +!8 = !DISubroutineType(types: !9) +!9 = !{!10, !10} +!10 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!11 = !{!12} +!12 = !DILocalVariable(name: "i", arg: 1, scope: !7, file: !1, line: 1, type: !10) +!13 = !DIExpression(DW_OP_minus, 1) +!14 = !DILocation(line: 1, column: 13, scope: !7) +!15 = !DILocation(line: 2, column: 11, scope: !7) +!16 = !DILocation(line: 2, column: 3, scope: !7)