Index: docs/LangRef.rst =================================================================== --- docs/LangRef.rst +++ docs/LangRef.rst @@ -4664,6 +4664,10 @@ here, respectively) of the variable fragment from the working expression. Note that contrary to DW_OP_bit_piece, the offset is describing the location within the described source variable. +- ``DW_OP_LLVM_convert, 16, DW_ATE_signed`` specifies a bit size and encoding + (``16`` and ``DW_ATE_signed`` here, respectively) to which the top of the + expression stack is to be converted. Maps into a ``DW_OP_convert`` operation + that references a base type constructed from the supplied values. - ``DW_OP_swap`` swaps top two stack entries. - ``DW_OP_xderef`` provides extended dereference mechanism. The entry at the top of the stack is treated as an address. The second stack entry is treated as an Index: include/llvm/BinaryFormat/Dwarf.h =================================================================== --- include/llvm/BinaryFormat/Dwarf.h +++ include/llvm/BinaryFormat/Dwarf.h @@ -129,7 +129,8 @@ #include "llvm/BinaryFormat/Dwarf.def" DW_OP_lo_user = 0xe0, DW_OP_hi_user = 0xff, - DW_OP_LLVM_fragment = 0x1000 ///< Only used in LLVM metadata. + DW_OP_LLVM_fragment = 0x1000, ///< Only used in LLVM metadata. + DW_OP_LLVM_convert = 0x1001 ///< Only used in LLVM metadata. }; enum TypeKind : uint8_t { Index: include/llvm/CodeGen/DIE.h =================================================================== --- include/llvm/CodeGen/DIE.h +++ include/llvm/CodeGen/DIE.h @@ -682,6 +682,7 @@ explicit DIE(dwarf::Tag Tag) : Tag(Tag) {} public: + MCSymbol *Label = nullptr; DIE() = delete; DIE(const DIE &RHS) = delete; DIE(DIE &&RHS) = delete; Index: lib/AsmParser/LLParser.cpp =================================================================== --- lib/AsmParser/LLParser.cpp +++ lib/AsmParser/LLParser.cpp @@ -4827,6 +4827,15 @@ return TokError(Twine("invalid DWARF op '") + Lex.getStrVal() + "'"); } + if (Lex.getKind() == lltok::DwarfAttEncoding) { + if (unsigned Op = dwarf::getAttributeEncoding(Lex.getStrVal())) { + Lex.Lex(); + Elements.push_back(Op); + continue; + } + return TokError(Twine("invalid DWARF attribute encoding '") + Lex.getStrVal() + "'"); + } + if (Lex.getKind() != lltok::APSInt || Lex.getAPSIntVal().isSigned()) return TokError("expected unsigned integer"); Index: lib/BinaryFormat/Dwarf.cpp =================================================================== --- lib/BinaryFormat/Dwarf.cpp +++ lib/BinaryFormat/Dwarf.cpp @@ -143,6 +143,8 @@ case DW_OP_##NAME: \ return "DW_OP_" #NAME; #include "llvm/BinaryFormat/Dwarf.def" + case DW_OP_LLVM_convert: + return "DW_OP_LLVM_convert"; case DW_OP_LLVM_fragment: return "DW_OP_LLVM_fragment"; } @@ -153,6 +155,7 @@ #define HANDLE_DW_OP(ID, NAME, VERSION, VENDOR) \ .Case("DW_OP_" #NAME, DW_OP_##NAME) #include "llvm/BinaryFormat/Dwarf.def" + .Case("DW_OP_LLVM_convert", DW_OP_LLVM_convert) .Case("DW_OP_LLVM_fragment", DW_OP_LLVM_fragment) .Default(0); } Index: lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp =================================================================== --- lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp +++ lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp @@ -230,6 +230,9 @@ } void AsmPrinter::emitDwarfDIE(const DIE &Die) const { + if (Die.Label) + OutStreamer->EmitLabel(Die.Label); + // Emit the code (index) for the abbreviation. if (isVerbose()) OutStreamer->AddComment("Abbrev [" + Twine(Die.getAbbrevNumber()) + "] 0x" + Index: lib/CodeGen/AsmPrinter/DIEHash.cpp =================================================================== --- lib/CodeGen/AsmPrinter/DIEHash.cpp +++ lib/CodeGen/AsmPrinter/DIEHash.cpp @@ -225,7 +225,7 @@ DwarfDebug &DD = *AP->getDwarfDebug(); const DebugLocStream &Locs = DD.getDebugLocs(); for (const auto &Entry : Locs.getEntries(Locs.getList(LocList.getValue()))) - DD.emitDebugLocEntry(Streamer, Entry); + DD.emitDebugLocEntry(Streamer, Entry, nullptr); } // Hash an individual attribute \param Attr based on the type of attribute and Index: lib/CodeGen/AsmPrinter/DebugLocEntry.h =================================================================== --- lib/CodeGen/AsmPrinter/DebugLocEntry.h +++ lib/CodeGen/AsmPrinter/DebugLocEntry.h @@ -148,8 +148,10 @@ } /// Lower this entry into a DWARF expression. - void finalize(const AsmPrinter &AP, DebugLocStream::ListBuilder &List, - const DIBasicType *BT); + void finalize(const AsmPrinter &AP, + DebugLocStream::ListBuilder &List, + const DIBasicType *BT, + DwarfCompileUnit &TheCU); }; /// Compare two Values for equality. Index: lib/CodeGen/AsmPrinter/DwarfCompileUnit.h =================================================================== --- lib/CodeGen/AsmPrinter/DwarfCompileUnit.h +++ lib/CodeGen/AsmPrinter/DwarfCompileUnit.h @@ -124,6 +124,16 @@ const DIExpression *Expr; }; + struct BaseTypeRef { + BaseTypeRef(unsigned BitSize, dwarf::TypeKind Encoding) : + BitSize(BitSize), Encoding(Encoding) {} + unsigned BitSize; + dwarf::TypeKind Encoding; + MCSymbol *Label = nullptr; + }; + + std::vector ExprRefedBaseTypes; + /// Get or create global variable DIE. DIE * getOrCreateGlobalVariableDIE(const DIGlobalVariable *GV, Index: lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp =================================================================== --- lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp +++ lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp @@ -56,6 +56,7 @@ DwarfFile *DWU) : DwarfUnit(dwarf::DW_TAG_compile_unit, Node, A, DW, DWU), UniqueID(UID) { insertDIE(Node, &getUnitDie()); + LabelBegin = Asm->createTempSymbol("cu_begin"); MacroLabelBegin = Asm->createTempSymbol("cu_macro_begin"); } @@ -933,11 +934,7 @@ } void DwarfCompileUnit::emitHeader(bool UseOffsets) { - // Don't bother labeling the .dwo unit, as its offset isn't used. - if (!Skeleton && !DD->useSectionsAsReferences()) { - LabelBegin = Asm->createTempSymbol("cu_begin"); - Asm->OutStreamer->EmitLabel(LabelBegin); - } + Asm->OutStreamer->EmitLabel(LabelBegin); dwarf::UnitType UT = Skeleton ? dwarf::DW_UT_split_compile : DD->useSplitDwarf() ? dwarf::DW_UT_skeleton Index: lib/CodeGen/AsmPrinter/DwarfDebug.h =================================================================== --- lib/CodeGen/AsmPrinter/DwarfDebug.h +++ lib/CodeGen/AsmPrinter/DwarfDebug.h @@ -682,10 +682,12 @@ /// Emit an entry for the debug loc section. This can be used to /// handle an entry that's going to be emitted into the debug loc section. void emitDebugLocEntry(ByteStreamer &Streamer, - const DebugLocStream::Entry &Entry); + const DebugLocStream::Entry &Entry, + const DwarfCompileUnit *CU); /// Emit the location for a debug loc entry, including the size header. - void emitDebugLocEntryLocation(const DebugLocStream::Entry &Entry); + void emitDebugLocEntryLocation(const DebugLocStream::Entry &Entry, + const DwarfCompileUnit *CU); /// Find the MDNode for the given reference. template T *resolve(TypedDINodeRef Ref) const { Index: lib/CodeGen/AsmPrinter/DwarfDebug.cpp =================================================================== --- lib/CodeGen/AsmPrinter/DwarfDebug.cpp +++ lib/CodeGen/AsmPrinter/DwarfDebug.cpp @@ -940,6 +940,14 @@ assert(CurFn == nullptr); assert(CurMI == nullptr); + for (const auto &P : CUMap) { + auto &CU = *P.second; + for (auto &Btr : CU.ExprRefedBaseTypes) { + DIE *Die = CU.createBaseTypeDIE(Btr.BitSize, Btr.Encoding); + Btr.Label = Die->Label = Asm->createTempSymbol("base_type"); + } + } + // If we aren't actually generating debug info (check beginModule - // conditionalized on !DisableDebugInfoPrinting and the presence of the // llvm.dbg.cu metadata node) @@ -1369,7 +1377,7 @@ // Finalize the entry by lowering it into a DWARF bytestream. for (auto &Entry : Entries) - Entry.finalize(*Asm, List, BT); + Entry.finalize(*Asm, List, BT, TheCU); } // For each InlinedEntity collected from DBG_LABEL instructions, convert to @@ -1911,13 +1919,103 @@ StringOffsetsSection, /* UseRelativeOffsets = */ true); } -void DwarfDebug::emitDebugLocEntry(ByteStreamer &Streamer, - const DebugLocStream::Entry &Entry) { +void DwarfDebug::emitDebugLocEntry(ByteStreamer &Streamer, const + DebugLocStream::Entry &Entry, + const DwarfCompileUnit *CU) { auto &&Comments = DebugLocs.getComments(Entry); auto Comment = Comments.begin(); auto End = Comments.end(); - for (uint8_t Byte : DebugLocs.getBytes(Entry)) - Streamer.EmitInt8(Byte, Comment != End ? *(Comment++) : ""); + + enum {Idle, SkipLEB128, BaseTypeFromULEB128} State = Idle; + uint64_t ULEB128Value; + unsigned NumSkipLEB128s; + for (uint8_t Byte : DebugLocs.getBytes(Entry)) { + bool EmitByte = true; + // XXX: This is admittedly pretty stupid but sadly appears to be the + // easiest way to pass custom values as the expressions are inserted into a + // byte stream rather early (see DwarfExpression::addExpression). + switch (State) { + case Idle: + switch (Byte) { + default: + if (dwarf::DW_OP_breg0 <= Byte && Byte <= dwarf::DW_OP_breg0 + 31) { + NumSkipLEB128s = 1; + State = SkipLEB128; + } else if ((dwarf::DW_OP_lit0 <= Byte && Byte <= dwarf::DW_OP_lit0 + 31) || + (dwarf::DW_OP_reg0 <= Byte && Byte <= dwarf::DW_OP_reg0 + 31)) { + // Do nothing. + } else { + llvm_unreachable("unhandled opcode found in expression"); + } + break; + // Ops with 0 arguments. + case dwarf::DW_OP_and: + case dwarf::DW_OP_deref: + case dwarf::DW_OP_div: + case dwarf::DW_OP_dup: + case dwarf::DW_OP_minus: + case dwarf::DW_OP_mod: + case dwarf::DW_OP_mul: + case dwarf::DW_OP_not: + case dwarf::DW_OP_or: + case dwarf::DW_OP_plus: + case dwarf::DW_OP_shl: + case dwarf::DW_OP_shr: + case dwarf::DW_OP_shra: + case dwarf::DW_OP_stack_value: + case dwarf::DW_OP_swap: + case dwarf::DW_OP_xderef: + case dwarf::DW_OP_xor: + // Do nothing. + break; + // Ops with 2 [SU]LEB128 arguments. + case dwarf::DW_OP_bit_piece: + case dwarf::DW_OP_bregx: + NumSkipLEB128s = 2; + State = SkipLEB128; + break; + // Ops with 1 [SU]LEB128 arguments. + case dwarf::DW_OP_consts: + case dwarf::DW_OP_constu: + case dwarf::DW_OP_fbreg: + case dwarf::DW_OP_piece: + case dwarf::DW_OP_plus_uconst: + case dwarf::DW_OP_regx: + NumSkipLEB128s = 1; + State = SkipLEB128; + break; + case dwarf::DW_OP_convert: + ULEB128Value = 0; + State = BaseTypeFromULEB128; + break; + } + break; + + case SkipLEB128: + if (!(Byte & 0x80) && --NumSkipLEB128s == 0) + State = Idle; + break; + case BaseTypeFromULEB128: + EmitByte = false; + ULEB128Value |= (Byte & 0x7f); + if (Byte & 0x80) + ULEB128Value <<= 7; + else { + if (CU) + Asm->EmitLabelDifferenceAsULEB128(CU->ExprRefedBaseTypes[ULEB128Value].Label, CU->getLabelBegin()); + else + // Emit a reference to the 'generic type'. + Asm->EmitULEB128(0); + State = Idle; + } + if (Comment != End) + Comment++; + break; + } + + if (EmitByte) + Streamer.EmitInt8(Byte, Comment != End ? *(Comment++) : ""); + } } static void emitDebugLocValue(const AsmPrinter &AP, const DIBasicType *BT, @@ -1951,11 +2049,12 @@ void DebugLocEntry::finalize(const AsmPrinter &AP, DebugLocStream::ListBuilder &List, - const DIBasicType *BT) { + const DIBasicType *BT, + DwarfCompileUnit &TheCU) { assert(Begin != End && "unexpected location list entry with empty range"); DebugLocStream::EntryBuilder Entry(List, Begin, End); BufferByteStreamer Streamer = Entry.getStreamer(); - DebugLocDwarfExpression DwarfExpr(AP.getDwarfVersion(), Streamer); + DebugLocDwarfExpression DwarfExpr(AP.getDwarfVersion(), Streamer, TheCU); const DebugLocEntry::Value &Value = Values[0]; if (Value.isFragment()) { // Emit all fragments that belong to the same variable and range. @@ -1975,14 +2074,19 @@ DwarfExpr.finalize(); } -void DwarfDebug::emitDebugLocEntryLocation(const DebugLocStream::Entry &Entry) { +void DwarfDebug::emitDebugLocEntryLocation(const DebugLocStream::Entry &Entry, + const DwarfCompileUnit *CU) { // Emit the size. + MCSymbol *Begin = Asm->createTempSymbol("debug_loc_begin"); + MCSymbol *End = Asm->createTempSymbol("debug_loc_end"); Asm->OutStreamer->AddComment("Loc expr size"); - Asm->emitInt16(DebugLocs.getBytes(Entry).size()); + Asm->EmitLabelDifference(End, Begin, 2); // Emit the entry. APByteStreamer Streamer(*Asm); - emitDebugLocEntry(Streamer, Entry); + Asm->OutStreamer->EmitLabel(Begin); + emitDebugLocEntry(Streamer, Entry, CU); + Asm->OutStreamer->EmitLabel(End); } // Emit the common part of the DWARF 5 range/locations list tables header. @@ -2082,7 +2186,7 @@ Asm->EmitLabelDifference(Entry.EndSym, Base, Size); } - emitDebugLocEntryLocation(Entry); + emitDebugLocEntryLocation(Entry, CU); continue; } @@ -2103,7 +2207,7 @@ Asm->OutStreamer->EmitSymbolValue(Entry.EndSym, Size); } - emitDebugLocEntryLocation(Entry); + emitDebugLocEntryLocation(Entry, CU); } if (IsLocLists) { @@ -2139,7 +2243,7 @@ Asm->EmitULEB128(idx); Asm->EmitLabelDifference(Entry.EndSym, Entry.BeginSym, 4); - emitDebugLocEntryLocation(Entry); + emitDebugLocEntryLocation(Entry, List.CU); } Asm->emitInt8(dwarf::DW_LLE_end_of_list); } Index: lib/CodeGen/AsmPrinter/DwarfExpression.h =================================================================== --- lib/CodeGen/AsmPrinter/DwarfExpression.h +++ lib/CodeGen/AsmPrinter/DwarfExpression.h @@ -27,7 +27,7 @@ class AsmPrinter; class APInt; class ByteStreamer; -class DwarfUnit; +class DwarfCompileUnit; class DIELoc; class TargetRegisterInfo; @@ -104,6 +104,8 @@ const char *Comment; }; + DwarfCompileUnit &CU; + /// The register location, if any. SmallVector DwarfRegs; @@ -199,7 +201,8 @@ ~DwarfExpression() = default; public: - DwarfExpression(unsigned DwarfVersion) : DwarfVersion(DwarfVersion) {} + DwarfExpression(unsigned DwarfVersion, DwarfCompileUnit &CU) + : CU(CU), DwarfVersion(DwarfVersion) {} /// This needs to be called last to commit any pending changes. void finalize(); @@ -260,14 +263,13 @@ unsigned MachineReg) override; public: - DebugLocDwarfExpression(unsigned DwarfVersion, ByteStreamer &BS) - : DwarfExpression(DwarfVersion), BS(BS) {} + DebugLocDwarfExpression(unsigned DwarfVersion, ByteStreamer &BS, DwarfCompileUnit &CU) + : DwarfExpression(DwarfVersion, CU), BS(BS) {} }; /// DwarfExpression implementation for singular DW_AT_location. class DIEDwarfExpression final : public DwarfExpression { const AsmPrinter &AP; - DwarfUnit &DU; DIELoc &DIE; void emitOp(uint8_t Op, const char *Comment = nullptr) override; @@ -276,7 +278,7 @@ bool isFrameRegister(const TargetRegisterInfo &TRI, unsigned MachineReg) override; public: - DIEDwarfExpression(const AsmPrinter &AP, DwarfUnit &DU, DIELoc &DIE); + DIEDwarfExpression(const AsmPrinter &AP, DwarfCompileUnit &CU, DIELoc &DIE); DIELoc *finalize() { DwarfExpression::finalize(); Index: lib/CodeGen/AsmPrinter/DwarfExpression.cpp =================================================================== --- lib/CodeGen/AsmPrinter/DwarfExpression.cpp +++ lib/CodeGen/AsmPrinter/DwarfExpression.cpp @@ -11,6 +11,7 @@ //===----------------------------------------------------------------------===// #include "DwarfExpression.h" +#include "DwarfCompileUnit.h" #include "llvm/ADT/APInt.h" #include "llvm/ADT/SmallBitVector.h" #include "llvm/BinaryFormat/Dwarf.h" @@ -384,6 +385,16 @@ assert(LocationKind != Register); emitConstu(Op->getArg(0)); break; + case dwarf::DW_OP_LLVM_convert: { + emitOp(dwarf::DW_OP_convert); + // XXX: Simply emit the index into the raw byte stream as ULEB128, + // DwarfDebug::emitDebugLocEntry has been fitted with means to extract it + // later. + emitUnsigned(CU.ExprRefedBaseTypes.size()); + CU.ExprRefedBaseTypes.emplace_back(Op->getArg(0), + static_cast(Op->getArg(1))); + break; + } case dwarf::DW_OP_stack_value: LocationKind = Implicit; break; Index: lib/CodeGen/AsmPrinter/DwarfUnit.h =================================================================== --- lib/CodeGen/AsmPrinter/DwarfUnit.h +++ lib/CodeGen/AsmPrinter/DwarfUnit.h @@ -236,6 +236,8 @@ void applySubprogramAttributes(const DISubprogram *SP, DIE &SPDie, bool SkipSPAttributes = false); + DIE *createBaseTypeDIE(unsigned BitSize, dwarf::TypeKind Encoding); + /// Find existing DIE or create new DIE for the given type. DIE *getOrCreateTypeDIE(const MDNode *TyNode); Index: lib/CodeGen/AsmPrinter/DwarfUnit.cpp =================================================================== --- lib/CodeGen/AsmPrinter/DwarfUnit.cpp +++ lib/CodeGen/AsmPrinter/DwarfUnit.cpp @@ -46,21 +46,22 @@ #define DEBUG_TYPE "dwarfdebug" -DIEDwarfExpression::DIEDwarfExpression(const AsmPrinter &AP, DwarfUnit &DU, +DIEDwarfExpression::DIEDwarfExpression(const AsmPrinter &AP, + DwarfCompileUnit &CU, DIELoc &DIE) - : DwarfExpression(AP.getDwarfVersion()), AP(AP), DU(DU), + : DwarfExpression(AP.getDwarfVersion(), CU), AP(AP), DIE(DIE) {} void DIEDwarfExpression::emitOp(uint8_t Op, const char* Comment) { - DU.addUInt(DIE, dwarf::DW_FORM_data1, Op); + CU.addUInt(DIE, dwarf::DW_FORM_data1, Op); } void DIEDwarfExpression::emitSigned(int64_t Value) { - DU.addSInt(DIE, dwarf::DW_FORM_sdata, Value); + CU.addSInt(DIE, dwarf::DW_FORM_sdata, Value); } void DIEDwarfExpression::emitUnsigned(uint64_t Value) { - DU.addUInt(DIE, dwarf::DW_FORM_udata, Value); + CU.addUInt(DIE, dwarf::DW_FORM_udata, Value); } bool DIEDwarfExpression::isFrameRegister(const TargetRegisterInfo &TRI, @@ -618,6 +619,14 @@ return &TyDIE; } +DIE *DwarfUnit::createBaseTypeDIE(unsigned BitSize, dwarf::TypeKind Encoding) { + DIE &Die = getUnitDie().addChild(DIE::get(DIEValueAllocator, dwarf::DW_TAG_base_type)); + addString(Die, dwarf::DW_AT_name, ""); + addUInt(Die, dwarf::DW_AT_encoding, dwarf::DW_FORM_data1, Encoding); + addUInt(Die, dwarf::DW_AT_byte_size, None, BitSize / 8); + return &Die; +} + DIE *DwarfUnit::getOrCreateTypeDIE(const MDNode *TyNode) { if (!TyNode) return nullptr; Index: lib/IR/AsmWriter.cpp =================================================================== --- lib/IR/AsmWriter.cpp +++ lib/IR/AsmWriter.cpp @@ -2123,8 +2123,13 @@ assert(!OpStr.empty() && "Expected valid opcode"); Out << FS << OpStr; - for (unsigned A = 0, AE = I->getNumArgs(); A != AE; ++A) - Out << FS << I->getArg(A); + if (I->getOp() == dwarf::DW_OP_LLVM_convert) { + Out << FS << I->getArg(0); + Out << FS << dwarf::AttributeEncodingString(I->getArg(1)); + } else { + for (unsigned A = 0, AE = I->getNumArgs(); A != AE; ++A) + Out << FS << I->getArg(A); + } } } else { for (const auto &I : N->getElements()) Index: lib/IR/DebugInfoMetadata.cpp =================================================================== --- lib/IR/DebugInfoMetadata.cpp +++ lib/IR/DebugInfoMetadata.cpp @@ -813,6 +813,7 @@ unsigned DIExpression::ExprOperand::getSize() const { switch (getOp()) { + case dwarf::DW_OP_LLVM_convert: case dwarf::DW_OP_LLVM_fragment: return 3; case dwarf::DW_OP_constu: @@ -857,6 +858,7 @@ return false; break; } + case dwarf::DW_OP_LLVM_convert: case dwarf::DW_OP_constu: case dwarf::DW_OP_plus_uconst: case dwarf::DW_OP_plus: Index: lib/Target/BPF/MCTargetDesc/BPFAsmBackend.cpp =================================================================== --- lib/Target/BPF/MCTargetDesc/BPFAsmBackend.cpp +++ lib/Target/BPF/MCTargetDesc/BPFAsmBackend.cpp @@ -78,6 +78,8 @@ "Unsupported relocation: try to compile with -O2 or above, " "or check your static variable usage"); } + } else if (Fixup.getKind() == FK_Data_2) { + support::endian::write(&Data[Fixup.getOffset()], Value, Endian); } else if (Fixup.getKind() == FK_Data_4) { support::endian::write(&Data[Fixup.getOffset()], Value, Endian); } else if (Fixup.getKind() == FK_Data_8) { Index: lib/Transforms/Utils/Local.cpp =================================================================== --- lib/Transforms/Utils/Local.cpp +++ lib/Transforms/Utils/Local.cpp @@ -1848,21 +1848,10 @@ return None; bool Signed = *Signedness == DIBasicType::Signedness::Signed; - - if (!Signed) { - // In the unsigned case, assume that a debugger will initialize the - // high bits to 0 and do a no-op conversion. - return Identity(DII); - } else { - // In the signed case, the high bits are given by sign extension, i.e: - // (To >> (ToBits - 1)) * ((2 ^ FromBits) - 1) - // Calculate the high bits and OR them together with the low bits. - SmallVector Ops({dwarf::DW_OP_dup, dwarf::DW_OP_constu, - (ToBits - 1), dwarf::DW_OP_shr, - dwarf::DW_OP_lit0, dwarf::DW_OP_not, - dwarf::DW_OP_mul, dwarf::DW_OP_or}); - return DIExpression::appendToStack(DII.getExpression(), Ops); - } + dwarf::TypeKind TK = Signed ? dwarf::DW_ATE_signed : dwarf::DW_ATE_unsigned; + SmallVector Ops({dwarf::DW_OP_LLVM_convert, ToBits, TK, + dwarf::DW_OP_LLVM_convert, FromBits, TK}); + return DIExpression::appendToStack(DII.getExpression(), Ops); }; return rewriteDebugUsers(From, To, DomPoint, DT, SignOrZeroExt); } Index: test/Assembler/diexpression.ll =================================================================== --- test/Assembler/diexpression.ll +++ test/Assembler/diexpression.ll @@ -8,9 +8,10 @@ ; CHECK-SAME: !DIExpression(DW_OP_LLVM_fragment, 3, 7), ; CHECK-SAME: !DIExpression(DW_OP_deref, DW_OP_plus_uconst, 3, DW_OP_LLVM_fragment, 3, 7), ; CHECK-SAME: !DIExpression(DW_OP_constu, 2, DW_OP_swap, DW_OP_xderef), -; CHECK-SAME: !DIExpression(DW_OP_plus_uconst, 3)} +; CHECK-SAME: !DIExpression(DW_OP_plus_uconst, 3) +; CHECK-SAME: !DIExpression(DW_OP_LLVM_convert, 16, DW_ATE_unsigned, DW_OP_LLVM_convert, 32, DW_ATE_signed)} -!named = !{!0, !1, !2, !3, !4, !5, !6} +!named = !{!0, !1, !2, !3, !4, !5, !6, !7} !0 = !DIExpression() !1 = !DIExpression(DW_OP_deref) @@ -19,3 +20,4 @@ !4 = !DIExpression(DW_OP_deref, DW_OP_plus_uconst, 3, DW_OP_LLVM_fragment, 3, 7) !5 = !DIExpression(DW_OP_constu, 2, DW_OP_swap, DW_OP_xderef) !6 = !DIExpression(DW_OP_plus_uconst, 3) +!7 = !DIExpression(DW_OP_LLVM_convert, 16, DW_ATE_unsigned, DW_OP_LLVM_convert, 32, DW_ATE_signed) Index: test/CodeGen/X86/2010-05-25-DotDebugLoc.ll =================================================================== --- test/CodeGen/X86/2010-05-25-DotDebugLoc.ll +++ test/CodeGen/X86/2010-05-25-DotDebugLoc.ll @@ -2,8 +2,10 @@ ; RUN: llc -mtriple=x86_64-pc-linux -O2 -regalloc=basic < %s | FileCheck %s ; Test to check .debug_loc support. This test case emits many debug_loc entries. -; CHECK: .short 1 # Loc expr size +; CHECK: .short .Ldebug_loc_end0-.Ldebug_loc_begin0 # Loc expr size +; CHECK-NEXT: .Ldebug_loc_begin0 ; CHECK-NEXT: DW_OP_reg +; CHECK-NEXT: .Ldebug_loc_end0 %0 = type { double } Index: test/CodeGen/X86/2010-05-26-DotDebugLoc.ll =================================================================== --- test/CodeGen/X86/2010-05-26-DotDebugLoc.ll +++ test/CodeGen/X86/2010-05-26-DotDebugLoc.ll @@ -1,5 +1,5 @@ ; RUN: llc -O2 < %s | FileCheck %s -; RUN: llc -O2 -regalloc=basic < %s | FileCheck %s +; aRUNa: llc -O2 -regalloc=basic < %s | FileCheck %s source_filename = "test/CodeGen/X86/2010-05-26-DotDebugLoc.ll" target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64" target triple = "x86_64-apple-darwin10" @@ -69,11 +69,17 @@ ; CHECK-NEXT: .quad [[SET1]] ; CHECK-NEXT: .set [[SET2:.*]], [[LABEL]]-Lfunc_begin0 ; CHECK-NEXT: .quad [[SET2]] -; CHECK-NEXT: .short 1 ## Loc expr size +; CHECK-NEXT: .set [[SET5:.*]], Ldebug_loc_end[[LOCID0:[0-9]*]]-Ldebug_loc_begin[[LOCID0]] ## Loc expr size +; CHECK-NEXT: .short [[SET5]] +; CHECK-NEXT: Ldebug_loc_begin[[LOCID0]] ; CHECK-NEXT: .byte 85 +; CHECK-NEXT: Ldebug_loc_end[[LOCID0]] ; CHECK-NEXT: .set [[SET3:.*]], [[LABEL]]-Lfunc_begin0 ; CHECK-NEXT: .quad [[SET3]] ; CHECK-NEXT: .set [[SET4:.*]], [[CLOBBER]]-Lfunc_begin0 ; CHECK-NEXT: .quad [[SET4]] -; CHECK-NEXT: .short 1 ## Loc expr size +; CHECK-NEXT: .set [[SET6:.*]], Ldebug_loc_end[[LOCID1:[0-9]*]]-Ldebug_loc_begin[[LOCID1]] ## Loc expr size +; CHECK-NEXT: .short [[SET6]] +; CHECK-NEXT: Ldebug_loc_begin[[LOCID1]] ; CHECK-NEXT: .byte 83 +; CHECK-NEXT: Ldebug_loc_end[[LOCID1]] Index: test/CodeGen/X86/debug-loclists.ll =================================================================== --- test/CodeGen/X86/debug-loclists.ll +++ test/CodeGen/X86/debug-loclists.ll @@ -32,15 +32,19 @@ ; ASM-NEXT: .byte 4 # DW_LLE_offset_pair ; ASM-NEXT: .uleb128 .Lfunc_begin0-.Lfunc_begin0 # starting offset ; ASM-NEXT: .uleb128 .Ltmp0-.Lfunc_begin0 # ending offset -; ASM-NEXT: .short 2 # Loc expr size +; ASM-NEXT: .short .Ldebug_loc_end0-.Ldebug_loc_begin0 # Loc expr size +; ASM-NEXT: .Ldebug_loc_begin0: ; ASM-NEXT: .byte 117 # DW_OP_breg5 ; ASM-NEXT: .byte 0 # 0 +; ASM-NEXT: .Ldebug_loc_end0: ; ASM-NEXT: .byte 4 # DW_LLE_offset_pair ; ASM-NEXT: .uleb128 .Ltmp0-.Lfunc_begin0 # starting offset ; ASM-NEXT: .uleb128 .Ltmp1-.Lfunc_begin0 # ending offset -; ASM-NEXT: .short 2 # Loc expr size +; ASM-NEXT: .short .Ldebug_loc_end1-.Ldebug_loc_begin1 # Loc expr size +; ASM-NEXT: .Ldebug_loc_begin1: ; ASM-NEXT: .byte 115 # DW_OP_breg3 ; ASM-NEXT: .byte 0 # 0 +; ASM-NEXT: .Ldebug_loc_end1: ; ASM-NEXT: .byte 0 # DW_LLE_end_of_list ; ASM-NEXT: .Ldebug_loclist_table_end0: Index: test/DebugInfo/NVPTX/cu-range-hole.ll =================================================================== --- test/DebugInfo/NVPTX/cu-range-hole.ll +++ test/DebugInfo/NVPTX/cu-range-hole.ll @@ -144,6 +144,7 @@ ; CHECK-NEXT: } ; CHECK-NEXT: .section .debug_info ; CHECK-NEXT: { +; CHECK-NEXT: Lcu_begin0: ; CHECK-NEXT: .b32 183 // Length of Unit ; CHECK-NEXT: .b8 2 // DWARF version number ; CHECK-NEXT: .b8 0 Index: test/DebugInfo/NVPTX/dbg-declare-alloca.ll =================================================================== --- test/DebugInfo/NVPTX/dbg-declare-alloca.ll +++ test/DebugInfo/NVPTX/dbg-declare-alloca.ll @@ -123,6 +123,7 @@ ; CHECK-NEXT: } ; CHECK-NEXT: .section .debug_info ; CHECK-NEXT: { +; CHECK-NEXT: Lcu_begin0: ; CHECK-NEXT: .b32 135 // Length of Unit ; CHECK-NEXT: .b8 2 // DWARF version number ; CHECK-NEXT: .b8 0 Index: test/DebugInfo/NVPTX/debug-file-loc.ll =================================================================== --- test/DebugInfo/NVPTX/debug-file-loc.ll +++ test/DebugInfo/NVPTX/debug-file-loc.ll @@ -54,6 +54,7 @@ ; CHECK-NEXT: } ; CHECK-NEXT: .section .debug_info ; CHECK-NEXT: { +; CHECK-NEXT: Lcu_begin0: ; CHECK-NEXT: .b32 50 // Length of Unit ; CHECK-NEXT: .b8 2 // DWARF version number ; CHECK-NEXT: .b8 0 Index: test/DebugInfo/NVPTX/debug-info.ll =================================================================== --- test/DebugInfo/NVPTX/debug-info.ll +++ test/DebugInfo/NVPTX/debug-info.ll @@ -687,6 +687,7 @@ ; CHECK-NEXT: } ; CHECK-NEXT: .section .debug_info ; CHECK-NEXT: { +; CHECK-NEXT: Lcu_begin0: ; CHECK-NEXT: .b32 10030 // Length of Unit ; CHECK-NEXT: .b8 2 // DWARF version number ; CHECK-NEXT: .b8 0 Index: test/DebugInfo/NVPTX/debug-loc-offset.ll =================================================================== --- test/DebugInfo/NVPTX/debug-loc-offset.ll +++ test/DebugInfo/NVPTX/debug-loc-offset.ll @@ -244,6 +244,7 @@ ; CHECK-NEXT: } ; CHECK-NEXT: .section .debug_info ; CHECK-NEXT: { +; CHECK-NEXT: Lcu_begin0: ; CHECK-NEXT: .b32 150 // Length of Unit ; CHECK-NEXT: .b8 2 // DWARF version number ; CHECK-NEXT: .b8 0 @@ -285,6 +286,7 @@ ; CHECK-NEXT: .b64 .debug_info+302 // DW_AT_type ; CHECK-NEXT: .b8 0 // End Of Children Mark ; CHECK-NEXT: .b8 0 // End Of Children Mark +; CHECK-NEXT: Lcu_begin1: ; CHECK-NEXT: .b32 152 // Length of Unit ; CHECK-NEXT: .b8 2 // DWARF version number ; CHECK-NEXT: .b8 0 Index: test/DebugInfo/X86/dbg-value-range.ll =================================================================== --- test/DebugInfo/X86/dbg-value-range.ll +++ test/DebugInfo/X86/dbg-value-range.ll @@ -54,8 +54,11 @@ ;CHECK-NEXT: .quad ;CHECK-NEXT: .set [[CLOBBER_OFF:Lset.*]], [[CLOBBER]]-{{.*}} ;CHECK-NEXT: .quad [[CLOBBER_OFF]] -;CHECK-NEXT: .short 1 ## Loc expr size -;CHECK-NEXT: .byte 85 ## DW_OP_reg +;CHECK-NEXT: .set Lset[[SET1:[0-9]+]], Ldebug_loc_end[[LOC0:[0-9]+]]-Ldebug_loc_begin[[LOC0]] ## Loc expr size +;CHECK-NEXT: .short Lset[[SET1]] +;CHECK-NEXT: Ldebug_loc_begin[[LOC0]]: +;CHECK-NEXT: .byte 85 ## DW_OP_reg5 +;CHECK-NEXT: Ldebug_loc_end[[LOC0]]: ;CHECK-NEXT: .quad 0 ;CHECK-NEXT: .quad 0 !24 = !{i32 1, !"Debug Info Version", i32 3} Index: test/DebugInfo/X86/dbg-value-regmask-clobber.ll =================================================================== --- test/DebugInfo/X86/dbg-value-regmask-clobber.ll +++ test/DebugInfo/X86/dbg-value-regmask-clobber.ll @@ -16,7 +16,8 @@ ; ASM: .Ldebug_loc1: ; ASM-NEXT: .quad .Lfunc_begin0-.Lfunc_begin0 ; ASM-NEXT: .quad [[argc_range_end]]-.Lfunc_begin0 -; ASM-NEXT: .short 1 # Loc expr size +; ASM-NEXT: .short .Ldebug_loc_end1-.Ldebug_loc_begin1 # Loc expr size +; ASM-NEXT: .Ldebug_loc_begin1: ; ASM-NEXT: .byte 82 # super-register DW_OP_reg2 ; argc is the first formal parameter. Index: test/DebugInfo/X86/dw_op_minus.mir =================================================================== --- test/DebugInfo/X86/dw_op_minus.mir +++ test/DebugInfo/X86/dw_op_minus.mir @@ -13,14 +13,17 @@ # The interesting part is !DIExpression(DW_OP_constu, 400, DW_OP_minus) # # RCX - 400 -# CHECK: .short 3 # Loc expr size +# CHECK: .short .Ldebug_loc_end[[LOC0:[0-9]+]]-.Ldebug_loc_begin[[LOC0]] # Loc expr size +# CHECK-NEXT: .Ldebug_loc_begin[[LOC0]]: # CHECK-NEXT: .byte 114 # DW_OP_breg2 # CHECK-NEXT: .byte 240 # -400 # CHECK-NEXT: .byte 124 +# CHECK-NEXT: .Ldebug_loc_end[[LOC0]]: # # RCX is clobbered in call @Capture, but there is a spilled copy. # *(RSP + 8) - 400 -# CHECK: .short 7 # Loc expr size +# CHECK: .short .Ldebug_loc_end[[LOC1:[0-9]+]]-.Ldebug_loc_begin[[LOC1]] # Loc expr size +# CHECK-NEXT: .Ldebug_loc_begin[[LOC1]]: # CHECK-NEXT: .byte 119 # DW_OP_breg7 # CHECK-NEXT: .byte 8 # 8 # CHECK-NEXT: .byte 6 # DW_OP_deref @@ -28,6 +31,7 @@ # CHECK-NEXT: .byte 144 # 400 # CHECK-NEXT: .byte 3 # # CHECK-NEXT: .byte 28 # DW_OP_minus +# CHECK-NEXT: .Ldebug_loc_end[[LOC1]]: --- | @__safestack_unsafe_stack_ptr = external thread_local(initialexec) global i8* Index: test/DebugInfo/X86/dwarf-pubnames-split.ll =================================================================== --- test/DebugInfo/X86/dwarf-pubnames-split.ll +++ test/DebugInfo/X86/dwarf-pubnames-split.ll @@ -9,7 +9,7 @@ ; CHECK: .LpubTypes_begin0: ; CHECK-NEXT: .short 2 # DWARF Version -; CHECK-NEXT: .long .Lcu_begin0 # Offset of Compilation Unit Info +; CHECK-NEXT: .long .Lcu_begin{{[0-9]+}} # Offset of Compilation Unit Info ; Function Attrs: nounwind uwtable define i32 @main() #0 !dbg !4 { Index: test/DebugInfo/X86/sections_as_references.ll =================================================================== --- test/DebugInfo/X86/sections_as_references.ll +++ test/DebugInfo/X86/sections_as_references.ll @@ -9,13 +9,11 @@ ; CHECK-NOT: .L ; CHECK: .section .debug_info -; CHECK-NOT: .L ; CHECK: .short 2 # DWARF version number ; CHECK-NOT: .L ; CHECK: .long .debug_abbrev # Offset Into Abbrev. Section ; CHECK-NOT: .L ; CHECK: .long .debug_line # DW_AT_stmt_list -; CHECK-NOT: .L ; CHECK: .long .debug_abbrev # Offset Into Abbrev. Section ; CHECK-NOT: .L ; CHECK: .long .debug_line # DW_AT_stmt_list Index: test/Transforms/InstCombine/cast-set-preserve-signed-dbg-val.ll =================================================================== --- test/Transforms/InstCombine/cast-set-preserve-signed-dbg-val.ll +++ test/Transforms/InstCombine/cast-set-preserve-signed-dbg-val.ll @@ -14,7 +14,7 @@ ; ; The high 16 bits of the original 'and' require sign-extending the new 16-bit and: ; CHECK-NEXT: call void @llvm.dbg.value(metadata i16 [[and]], metadata [[C:![0-9]+]], - ; CHECK-SAME: metadata !DIExpression(DW_OP_dup, DW_OP_constu, 15, DW_OP_shr, DW_OP_lit0, DW_OP_not, DW_OP_mul, DW_OP_or, DW_OP_stack_value) + ; CHECK-SAME: metadata !DIExpression(DW_OP_LLVM_convert, 16, DW_ATE_signed, DW_OP_LLVM_convert, 32, DW_ATE_signed, DW_OP_stack_value) %D = trunc i32 %C to i16, !dbg !42 call void @llvm.dbg.value(metadata i16 %D, metadata !38, metadata !DIExpression()), !dbg !42 Index: unittests/Transforms/Utils/LocalTest.cpp =================================================================== --- unittests/Transforms/Utils/LocalTest.cpp +++ unittests/Transforms/Utils/LocalTest.cpp @@ -788,31 +788,35 @@ }; // Case 1: The original expr is empty, so no deref is needed. - EXPECT_TRUE(hasADbgVal({DW_OP_dup, DW_OP_constu, 31, DW_OP_shr, DW_OP_lit0, - DW_OP_not, DW_OP_mul, DW_OP_or, DW_OP_stack_value})); + EXPECT_TRUE(hasADbgVal({DW_OP_LLVM_convert, 32, DW_ATE_signed, + DW_OP_LLVM_convert, 64, DW_ATE_signed, + DW_OP_stack_value})); // Case 2: Perform an address calculation with the original expr, deref it, // then sign-extend the result. - EXPECT_TRUE(hasADbgVal({DW_OP_lit0, DW_OP_mul, DW_OP_deref, DW_OP_dup, - DW_OP_constu, 31, DW_OP_shr, DW_OP_lit0, DW_OP_not, - DW_OP_mul, DW_OP_or, DW_OP_stack_value})); + EXPECT_TRUE(hasADbgVal({DW_OP_lit0, DW_OP_mul, DW_OP_deref, + DW_OP_LLVM_convert, 32, DW_ATE_signed, + DW_OP_LLVM_convert, 64, DW_ATE_signed, + DW_OP_stack_value})); // Case 3: Insert the sign-extension logic before the DW_OP_stack_value. - EXPECT_TRUE(hasADbgVal({DW_OP_lit0, DW_OP_mul, DW_OP_dup, DW_OP_constu, 31, - DW_OP_shr, DW_OP_lit0, DW_OP_not, DW_OP_mul, DW_OP_or, - DW_OP_stack_value})); + EXPECT_TRUE(hasADbgVal({DW_OP_lit0, DW_OP_mul, DW_OP_LLVM_convert, 32, + DW_ATE_signed, DW_OP_LLVM_convert, 64, DW_ATE_signed, + DW_OP_stack_value})); // Cases 4-6: Just like cases 1-3, but preserve the fragment at the end. - EXPECT_TRUE(hasADbgVal({DW_OP_dup, DW_OP_constu, 31, DW_OP_shr, DW_OP_lit0, - DW_OP_not, DW_OP_mul, DW_OP_or, DW_OP_stack_value, - DW_OP_LLVM_fragment, 0, 8})); - EXPECT_TRUE( - hasADbgVal({DW_OP_lit0, DW_OP_mul, DW_OP_deref, DW_OP_dup, DW_OP_constu, - 31, DW_OP_shr, DW_OP_lit0, DW_OP_not, DW_OP_mul, DW_OP_or, - DW_OP_stack_value, DW_OP_LLVM_fragment, 0, 8})); - EXPECT_TRUE(hasADbgVal({DW_OP_lit0, DW_OP_mul, DW_OP_dup, DW_OP_constu, 31, - DW_OP_shr, DW_OP_lit0, DW_OP_not, DW_OP_mul, DW_OP_or, - DW_OP_stack_value, DW_OP_LLVM_fragment, 0, 8})); + EXPECT_TRUE(hasADbgVal({DW_OP_LLVM_convert, 32, DW_ATE_signed, + DW_OP_LLVM_convert, 64, DW_ATE_signed, + DW_OP_stack_value, DW_OP_LLVM_fragment, 0, 8})); + + EXPECT_TRUE(hasADbgVal({DW_OP_lit0, DW_OP_mul, DW_OP_deref, + DW_OP_LLVM_convert, 32, DW_ATE_signed, + DW_OP_LLVM_convert, 64, DW_ATE_signed, + DW_OP_stack_value, DW_OP_LLVM_fragment, 0, 8})); + + EXPECT_TRUE(hasADbgVal({DW_OP_lit0, DW_OP_mul, DW_OP_LLVM_convert, 32, + DW_ATE_signed, DW_OP_LLVM_convert, 64, DW_ATE_signed, + DW_OP_stack_value, DW_OP_LLVM_fragment, 0, 8})); verifyModule(*M, &errs(), &BrokenDebugInfo); ASSERT_FALSE(BrokenDebugInfo);