Index: include/llvm/DebugInfo/CodeView/TypeIndex.h =================================================================== --- include/llvm/DebugInfo/CodeView/TypeIndex.h +++ include/llvm/DebugInfo/CodeView/TypeIndex.h @@ -135,6 +135,8 @@ static TypeIndex UInt16Short() { return TypeIndex(SimpleTypeKind::UInt16Short); } + static TypeIndex Int16() { return TypeIndex(SimpleTypeKind::Int16); } + static TypeIndex UInt16() { return TypeIndex(SimpleTypeKind::UInt16); } static TypeIndex Int32() { return TypeIndex(SimpleTypeKind::Int32); } static TypeIndex UInt32() { return TypeIndex(SimpleTypeKind::UInt32); } static TypeIndex Int32Long() { return TypeIndex(SimpleTypeKind::Int32Long); } @@ -149,7 +151,20 @@ } static TypeIndex Float32() { return TypeIndex(SimpleTypeKind::Float32); } + static TypeIndex Float48() { return TypeIndex(SimpleTypeKind::Float48); } static TypeIndex Float64() { return TypeIndex(SimpleTypeKind::Float64); } + static TypeIndex Float80() { return TypeIndex(SimpleTypeKind::Float80); } + static TypeIndex Float128() { return TypeIndex(SimpleTypeKind::Float128); } + + static TypeIndex Complex32() { return TypeIndex(SimpleTypeKind::Complex32); } + static TypeIndex Complex64() { return TypeIndex(SimpleTypeKind::Complex64); } + static TypeIndex Complex80() { return TypeIndex(SimpleTypeKind::Complex80); } + static TypeIndex Complex128() { return TypeIndex(SimpleTypeKind::Complex128); } + + static TypeIndex Boolean8() { return TypeIndex(SimpleTypeKind::Boolean8); } + static TypeIndex Boolean16() { return TypeIndex(SimpleTypeKind::Boolean16); } + static TypeIndex Boolean32() { return TypeIndex(SimpleTypeKind::Boolean32); } + static TypeIndex Boolean64() { return TypeIndex(SimpleTypeKind::Boolean64); } private: support::ulittle32_t Index; Index: include/llvm/DebugInfo/CodeView/TypeRecord.h =================================================================== --- include/llvm/DebugInfo/CodeView/TypeRecord.h +++ include/llvm/DebugInfo/CodeView/TypeRecord.h @@ -877,6 +877,8 @@ StringRef getName() const { return Name; } + static uint32_t getLayoutSize() { return 2 + sizeof(Layout); } + private: struct Layout { TypeIndex ParentScope; Index: lib/CodeGen/AsmPrinter/CMakeLists.txt =================================================================== --- lib/CodeGen/AsmPrinter/CMakeLists.txt +++ lib/CodeGen/AsmPrinter/CMakeLists.txt @@ -22,6 +22,7 @@ OcamlGCPrinter.cpp WinException.cpp CodeViewDebug.cpp + CodeViewType.cpp ) add_dependencies(LLVMAsmPrinter intrinsics_gen) Index: lib/CodeGen/AsmPrinter/CodeViewDebug.h =================================================================== --- lib/CodeGen/AsmPrinter/CodeViewDebug.h +++ lib/CodeGen/AsmPrinter/CodeViewDebug.h @@ -14,6 +14,7 @@ #ifndef LLVM_LIB_CODEGEN_ASMPRINTER_CODEVIEWDEBUG_H #define LLVM_LIB_CODEGEN_ASMPRINTER_CODEVIEWDEBUG_H +#include "CodeViewType.h" #include "DebugHandlerBase.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/StringMap.h" @@ -69,6 +70,7 @@ struct LocalVariable { const DILocalVariable *DIVar = nullptr; SmallVector DefRanges; + const CodeViewType *CVType = nullptr; }; struct InlineSite { @@ -90,6 +92,9 @@ SmallVector Locals; + // Function type. + CodeViewType *FnType = nullptr; + DebugLoc LastLoc; const MCSymbol *Begin = nullptr; const MCSymbol *End = nullptr; @@ -99,21 +104,18 @@ }; FunctionInfo *CurFn; + // All types in the order they should be emitted. + typedef std::vector CodeViewTypeTable; + CodeViewTypeTable TypeTable; + DenseMap TypeMap; + + // CodeView void type created lazily, once per module. + CodeViewType *VoidType = nullptr; + /// The next available function index for use with our .cv_* directives. Not /// to be confused with type indices for LF_FUNC_ID records. unsigned NextFuncId = 0; - /// The next available type index. - unsigned NextTypeIndex = llvm::codeview::TypeIndex::FirstNonSimpleIndex; - - /// Get the next type index and reserve it. Can be used to reserve more than - /// one type index. - unsigned getNextTypeIndex(unsigned NumRecords = 1) { - unsigned Result = NextTypeIndex; - NextTypeIndex += NumRecords; - return Result; - } - InlineSite &getInlineSite(const DILocation *InlinedAt, const DISubprogram *Inlinee); @@ -132,14 +134,7 @@ DenseMap SubprogramIndices; /// All inlined subprograms in the order they should be emitted. - SmallVector InlinedSubprograms; - - /// The first type index that refers to an LF_FUNC_ID record. We have one - /// record per inlined subprogram. - /// FIXME: Keep in sync with emitTypeInformation until we buffer type records - /// on the side as we go. Once we buffer type records, we can allocate type - /// indices on demand without interleaving our assembly output. - unsigned FuncIdTypeIndexStart = NextTypeIndex + 2; + MapVector InlinedSubprograms; typedef std::map FileToFilepathMapTy; FileToFilepathMapTy FileToFilepathMap; @@ -154,10 +149,76 @@ FileIdMap.clear(); FnDebugInfo.clear(); FileToFilepathMap.clear(); + for (auto T : TypeTable) { + delete T; + } + TypeTable.clear(); + TypeMap.clear(); + VoidType = nullptr; + } + + // Helper lowering functions. + void appendType(CodeViewType* CVType); + void mapLLVMTypeToCodeViewType(const DIType *Type, CodeViewType *CVType); + CodeViewType *getMappedCodeViewType(const DIType *Type); + CodeViewType *getVoidType(); + // Lower LLVM type to CodeViewType functions. + CodeViewType *lowerType(const DIType *Type); + CodeViewTypeArgumentList *lowerTypeSubroutineArgumentList( + DITypeRefArray Elements, uint16_t FirstArgIndex); + CodeViewType *lowerTypeBasic(const DIBasicType *Type); + CodeViewType *lowerTypeSubroutine(const DISubroutineType *Type); + CodeViewType *lowerSubprogramType(const DISubprogram *SP); + CodeViewType *lowerSubprogramId(const DISubprogram *SP, + const Function *GV = nullptr); + + void layout(); + + // Helper emit functions. + void emitInt8(int Value) { + OS.EmitIntValue(Value, 1); + } + + void emitInt16(int Value) { + OS.EmitIntValue(Value, 2); + } + + void emitInt32(int Value) { + OS.EmitIntValue(Value, 4); } + void emitString(StringRef S); + + void emitBytes(const char *data, size_t size) { + OS.EmitBytes(StringRef(data, size)); + } + + void emitFill(size_t size, const uint8_t byte) { + OS.EmitFill(size, byte); + } + + void addComment(StringRef comment) { + OS.AddComment(comment); + } + + void emitLabel(MCSymbol *symbol) { + OS.EmitLabel(symbol); + } + + void emitValue(const MCExpr *value, unsigned int sizeInBytes) { + OS.EmitValue(value, sizeInBytes); + } + + void emitPadding(unsigned int Count); + + // Routines for emiting the .debug$T section. void emitTypeInformation(); + void emitType(const CodeViewType *CVType); + void emitTypeFunctionID(const CodeViewTypeFunctionID *CVType); + void emitTypeProcedure(const CodeViewTypeProcedure *CVType); + void emitTypeArgumentList(const CodeViewTypeArgumentList *CVType); + // Routines for emiting the .debug$S section. void emitInlineeFuncIdsAndLines(); void emitDebugInfoForFunction(const Function *GV, FunctionInfo &FI); @@ -177,6 +238,10 @@ void emitLocalVariable(const LocalVariable &Var); + /// Find the MDNode for the given reference. + template static T *resolve(TypedDINodeRef Ref) { + return Ref.resolve(); + } public: CodeViewDebug(AsmPrinter *Asm); Index: lib/CodeGen/AsmPrinter/CodeViewDebug.cpp =================================================================== --- lib/CodeGen/AsmPrinter/CodeViewDebug.cpp +++ lib/CodeGen/AsmPrinter/CodeViewDebug.cpp @@ -116,13 +116,15 @@ auto InlineeInsertion = SubprogramIndices.insert({Inlinee, InlinedSubprograms.size()}); if (InlineeInsertion.second) - InlinedSubprograms.push_back(Inlinee); + InlinedSubprograms.insert( + std::make_pair(Inlinee, lowerSubprogramId(Inlinee))); } return *Site; } void CodeViewDebug::recordLocalVariable(LocalVariable &&Var, const DILocation *InlinedAt) { + Var.CVType = lowerType(resolve(Var.DIVar->getType())); if (InlinedAt) { // This variable was inlined. Associate it with the InlineSite. const DISubprogram *Inlinee = Var.DIVar->getScope()->getSubprogram(); @@ -201,6 +203,7 @@ if (FnDebugInfo.empty()) return; + layout(); emitTypeInformation(); // FIXME: For functions that are comdat, we should emit separate .debug$S @@ -234,15 +237,6 @@ clear(); } -static void emitNullTerminatedSymbolName(MCStreamer &OS, StringRef S) { - // Microsoft's linker seems to have trouble with symbol names longer than - // 0xffd8 bytes. - S = S.substr(0, 0xffd8); - SmallString<32> NullTerminatedString(S); - NullTerminatedString.push_back('\0'); - OS.EmitBytes(NullTerminatedString); -} - void CodeViewDebug::emitTypeInformation() { // Do nothing if we have no debug info or no inlined subprograms. The types // we currently emit exist only to support inlined call site info. @@ -250,7 +244,8 @@ MMI->getModule()->getNamedMetadata("llvm.dbg.cu"); if (!CU_Nodes) return; - if (InlinedSubprograms.empty()) + + if (TypeTable.empty()) return; // Start the .debug$T section with 0x4. @@ -258,57 +253,9 @@ OS.AddComment("Debug section magic"); OS.EmitIntValue(COFF::DEBUG_SECTION_MAGIC, 4); - // This type info currently only holds function ids for use with inline call - // frame info. All functions are assigned a simple 'void ()' type. Emit that - // type here. - unsigned ArgListIndex = getNextTypeIndex(); - OS.AddComment("Type record length"); - OS.EmitIntValue(ArgListRecord::getLayoutSize(), 2); - OS.AddComment("Leaf type: LF_ARGLIST"); - OS.EmitIntValue(LF_ARGLIST, 2); - OS.AddComment("Number of arguments"); - OS.EmitIntValue(0, 4); - - unsigned VoidFnTyIdx = getNextTypeIndex(); - OS.AddComment("Type record length"); - OS.EmitIntValue(ProcedureRecord::getLayoutSize(), 2); - OS.AddComment("Leaf type: LF_PROCEDURE"); - OS.EmitIntValue(LF_PROCEDURE, 2); - OS.AddComment("Return type index"); - OS.EmitIntValue(TypeIndex::Void().getIndex(), 4); - OS.AddComment("Calling convention"); - OS.EmitIntValue(char(CallingConvention::NearC), 1); - OS.AddComment("Function options"); - OS.EmitIntValue(char(FunctionOptions::None), 1); - OS.AddComment("# of parameters"); - OS.EmitIntValue(0, 2); - OS.AddComment("Argument list type index"); - OS.EmitIntValue(ArgListIndex, 4); - - // Emit LF_FUNC_ID records for all inlined subprograms to the type stream. - // Allocate one type index for each func id. - unsigned NextIdx = getNextTypeIndex(InlinedSubprograms.size()); - (void)NextIdx; - assert(NextIdx == FuncIdTypeIndexStart && "func id type indices broken"); - for (auto *SP : InlinedSubprograms) { - StringRef DisplayName = SP->getDisplayName(); - OS.AddComment("Type record length"); - MCSymbol *FuncBegin = MMI->getContext().createTempSymbol(), - *FuncEnd = MMI->getContext().createTempSymbol(); - OS.emitAbsoluteSymbolDiff(FuncEnd, FuncBegin, 2); - OS.EmitLabel(FuncBegin); - OS.AddComment("Leaf type: LF_FUNC_ID"); - OS.EmitIntValue(LF_FUNC_ID, 2); - OS.AddComment("Scope type index"); - OS.EmitIntValue(0, 4); - OS.AddComment("Function type"); - OS.EmitIntValue(VoidFnTyIdx, 4); - { - OS.AddComment("Function name"); - emitNullTerminatedSymbolName(OS, DisplayName); - } - OS.EmitLabel(FuncEnd); + for (const auto *CVType : TypeTable) { + emitType(CVType); } } @@ -330,8 +277,9 @@ OS.AddComment("Inlinee lines signature"); OS.EmitIntValue(unsigned(InlineeLinesSignature::Normal), 4); - unsigned InlineeIndex = FuncIdTypeIndexStart; - for (const DISubprogram *SP : InlinedSubprograms) { + for (const auto Itr : InlinedSubprograms) { + const DISubprogram *SP = Itr.first; + unsigned InlineeIndex = CodeViewType::getIndexOrNone(Itr.second); OS.AddBlankLine(); unsigned FileId = maybeRecordFile(SP->getFile()); OS.AddComment("Inlined function " + SP->getDisplayName() + " starts at " + @@ -346,9 +294,6 @@ OS.EmitIntValue(FileOffset, 4); OS.AddComment("Starting line number"); OS.EmitIntValue(SP->getLine(), 4); - - // The next inlined subprogram has the next function id. - InlineeIndex++; } OS.EmitLabel(InlineEnd); @@ -371,8 +316,8 @@ MCSymbol *InlineBegin = MMI->getContext().createTempSymbol(), *InlineEnd = MMI->getContext().createTempSymbol(); - assert(SubprogramIndices.count(Site.Inlinee)); - unsigned InlineeIdx = FuncIdTypeIndexStart + SubprogramIndices[Site.Inlinee]; + unsigned InlineeIndex = + CodeViewType::getIndexOrNone(InlinedSubprograms[Site.Inlinee]); // SymbolRecord OS.AddComment("Record length"); @@ -386,7 +331,7 @@ OS.AddComment("PtrEnd"); OS.EmitIntValue(0, 4); OS.AddComment("Inlinee type index"); - OS.EmitIntValue(InlineeIdx, 4); + OS.EmitIntValue(InlineeIndex, 4); unsigned FileId = maybeRecordFile(Site.Inlinee->getFile()); unsigned StartLineNum = Site.Inlinee->getLine(); @@ -465,7 +410,7 @@ OS.AddComment("Offset before epilogue"); OS.EmitIntValue(0, 4); OS.AddComment("Function type index"); - OS.EmitIntValue(0, 4); + OS.EmitIntValue(CodeViewType::getIndexOrNone(FI.FnType), 4); OS.AddComment("Function section relative address"); OS.EmitCOFFSecRel32(Fn); OS.AddComment("Function section index"); @@ -475,7 +420,7 @@ // Emit the function display name as a null-terminated string. OS.AddComment("Function name"); // Truncate the name so we won't overflow the record length field. - emitNullTerminatedSymbolName(OS, FuncName); + emitString(FuncName); OS.EmitLabel(ProcRecordEnd); for (const LocalVariable &Var : FI.Locals) @@ -716,11 +661,11 @@ Flags |= LocalSymFlags::IsOptimizedOut; OS.AddComment("TypeIndex"); - OS.EmitIntValue(TypeIndex::Int32().getIndex(), 4); + OS.EmitIntValue(CodeViewType::getIndexOrNone(Var.CVType), 4); OS.AddComment("Flags"); OS.EmitIntValue(static_cast(Flags), 2); // Truncate the name so we won't overflow the record length field. - emitNullTerminatedSymbolName(OS, Var.DIVar->getName()); + emitString(Var.DIVar->getName()); OS.EmitLabel(LocalEnd); // Calculate the on disk prefix of the appropriate def range record. The @@ -777,6 +722,8 @@ return; } + CurFn->FnType = lowerSubprogramId(GV->getSubprogram(), GV); + CurFn->End = Asm->getFunctionEnd(); CurFn = nullptr; @@ -793,3 +740,516 @@ return; maybeRecordLocation(DL, Asm->MF); } + + +//===----------------------------------------------------------------------===// +// CodeViewDebug type function implementation +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// INDEX_BASIC_TYPE_MAPPINGS +// +// Maps LLVM basic types to TypeIndex encodings. +// +//===----------------------------------------------------------------------===// + +#define INDEX_BASIC_TYPE_MAPPINGS \ + X(dwarf::DW_ATE_address, 4, Void) \ + X(dwarf::DW_ATE_boolean, 1, Boolean8) \ + X(dwarf::DW_ATE_boolean, 2, Boolean16) \ + X(dwarf::DW_ATE_boolean, 4, Boolean32) \ + X(dwarf::DW_ATE_boolean, 8, Boolean64) \ + X(dwarf::DW_ATE_complex_float, 4, Complex32) \ + X(dwarf::DW_ATE_complex_float, 8, Complex64) \ + X(dwarf::DW_ATE_complex_float, 10, Complex80) \ + X(dwarf::DW_ATE_complex_float, 16, Complex128) \ + X(dwarf::DW_ATE_float, 4, Float32) \ + X(dwarf::DW_ATE_float, 6, Float48) \ + X(dwarf::DW_ATE_float, 8, Float64) \ + X(dwarf::DW_ATE_float, 10, Float80) \ + X(dwarf::DW_ATE_float, 16, Float128) \ + X(dwarf::DW_ATE_decimal_float, 4, Float32) \ + X(dwarf::DW_ATE_decimal_float, 6, Float48) \ + X(dwarf::DW_ATE_decimal_float, 8, Float64) \ + X(dwarf::DW_ATE_decimal_float, 10, Float80) \ + X(dwarf::DW_ATE_decimal_float, 16, Float128) \ + X(dwarf::DW_ATE_signed, 1, SignedCharacter) \ + X(dwarf::DW_ATE_signed, 2, Int16Short) \ + X(dwarf::DW_ATE_signed, 4, Int32) \ + X(dwarf::DW_ATE_signed, 8, Int64) \ + X(dwarf::DW_ATE_signed_char, 1, SignedCharacter) \ + X(dwarf::DW_ATE_unsigned, 1, UnsignedCharacter) \ + X(dwarf::DW_ATE_unsigned, 2, UInt16) \ + X(dwarf::DW_ATE_unsigned, 4, UInt32) \ + X(dwarf::DW_ATE_unsigned, 8, UInt64) \ + X(dwarf::DW_ATE_unsigned_char, 1, UnsignedCharacter) + +//===----------------------------------------------------------------------===// +// toBasicTypeIndex(Type) +// +// Returns an CodeView TypeIndex encoding for the specified LLVM basic type. +// +//===----------------------------------------------------------------------===// + +static TypeIndex toBasicTypeIndex(const DIBasicType *Type) { + TypeIndex Index; + dwarf::TypeKind Kind; + uint32_t ByteSize; + + Kind = static_cast(Type->getEncoding()); + ByteSize = Type->getSizeInBits() >> 3; + +#define X(KIND, BYTESIZE, INDEX_FN) \ + if (Kind == KIND && ByteSize == BYTESIZE) { \ + Index = TypeIndex::INDEX_FN(); \ + } else + INDEX_BASIC_TYPE_MAPPINGS +#undef X + { Index = TypeIndex(); } + + // Map "long INT" types to "LONG" types. + // + if (Type->getName().count("long")) { + switch (Index.getSimpleKind()) { + case (SimpleTypeKind::Int32) : Index = TypeIndex::Int32Long(); break; + case (SimpleTypeKind::UInt32) : Index = TypeIndex::UInt32Long(); break; + default: + // For everything else leave the index unchanged. + break; + } + } + + return Index; +} + +//===----------------------------------------------------------------------===// +// getMappedCodeViewType(Type) +// +// If the specified LLVM type has already been mapped to an existing CodeView +// type then the CodeView type is returned. Otherwise nullptr is returned. +// +//===----------------------------------------------------------------------===// +CodeViewType *CodeViewDebug::getMappedCodeViewType(const DIType *Type) { + auto itr = TypeMap.find(Type); + if (itr == TypeMap.end()) { + return nullptr; + } + + return itr->second; /* second is the CodeView type */ +} + +//===----------------------------------------------------------------------===// +// appendType(type) +// +// Appends the specified type to the end of the type table which will be +// emitted to the .debug$T section. +// +//===----------------------------------------------------------------------===// + +void CodeViewDebug::appendType(CodeViewType* CVType) { + TypeTable.push_back(CVType); +} + +//===----------------------------------------------------------------------===// +// mapLLVMTypeToCodeViewType(Type, CVType) +// +// Map an LLVM type to an CodeView type. Future references to the LLVM type +// will reuse the existing CodeView type from the map. +// +//===----------------------------------------------------------------------===// + +void CodeViewDebug::mapLLVMTypeToCodeViewType(const DIType *Type, + CodeViewType *CVType) { + TypeMap.insert(std::make_pair(Type, CVType)); +} + +//===----------------------------------------------------------------------===// +// getVoidType() +// +// Return CodeView void type, create one if it was not created yet. +// +//===----------------------------------------------------------------------===// +CodeViewType *CodeViewDebug::getVoidType() { + if (VoidType == nullptr) { + CodeViewTypeBasic *CVType; + + CVType = CodeViewTypeBasic::create(); + CVType->setTypeIndex(TypeIndex::Void()); + CVType->setSizeInBits(0); + + appendType(CVType); + VoidType = CVType; + } + + return VoidType; +} + +//===----------------------------------------------------------------------===// +// lowerType(Type) +// +// Lowers the specified LLVM type into one or more CodeView type entries. +// +//===----------------------------------------------------------------------===// + +CodeViewType *CodeViewDebug::lowerType(const DIType *Type) { + CodeViewType *CVType; + unsigned int Tag; + + if (Type == nullptr) { + return getVoidType(); + } + + if (CVType = getMappedCodeViewType(Type)) { + return CVType; + } + + Tag = Type->getTag(); + switch (Tag) { + case dwarf::DW_TAG_base_type: + CVType = lowerTypeBasic(cast(Type)); break; + case dwarf::DW_TAG_subroutine_type: + CVType = lowerTypeSubroutine(cast(Type)); break; + default: + // TODO: Enable this assert once all types are implemented + //assert(Tag != Tag && "Unhandled type Tag!"); + CVType = nullptr; + break; + } + + return CVType; +} + +//===----------------------------------------------------------------------===// +// lowerTypeBasic(Type) +// +// Lowers the specified LLVM type, which must be a basic type, to a CodeView +// intermediate representation. +// +//===----------------------------------------------------------------------===// + +CodeViewType *CodeViewDebug::lowerTypeBasic(const DIBasicType *Type) { + const uint32_t SizeInBits = Type->getSizeInBits(); + const TypeIndex Index = toBasicTypeIndex(Type); + CodeViewTypeBasic *CVType; + + CVType = CodeViewTypeBasic::create(); + CVType->setTypeIndex(Index); + CVType->setSizeInBits(SizeInBits); + + appendType(CVType); + mapLLVMTypeToCodeViewType(Type, CVType); + + return CVType; +} + +//===----------------------------------------------------------------------===// +// lowerTypeSubroutineArgumentList(Elements, FirstArgIndex) +// +// Lowers all of the argument types in the specified elements array and +// creates a new argument list type entry containing each of the lowered +// argument types. +// +//===----------------------------------------------------------------------===// + +CodeViewTypeArgumentList *CodeViewDebug::lowerTypeSubroutineArgumentList( + DITypeRefArray Elements, uint16_t FirstArgIndex) { + CodeViewTypeArgumentList *ArgList; + DIType *ArgType; + + // Create the argument list type entry. + // + ArgList = CodeViewTypeArgumentList::create(); + + // Walk each of the elements, starting with the first argument index, lower + // the argument type and append it's index to the argument list. + // + for (unsigned i = FirstArgIndex, size = Elements.size(); i < size; ++i) { + ArgType = resolve(Elements[i]); + if (ArgType) { + ArgList->append(lowerType(ArgType)); + } + else { + assert(i == size - 1); // A variadic argument must be the last argument. + ArgList->append(nullptr); // FIXME: handle variadic argument + } + } + + appendType(ArgList); + + return ArgList; +} + +//===----------------------------------------------------------------------===// +// lowerTypeSubroutine(Type) +// +// Lower the specified LLVM subroutine type to CodeView type entries. +// +//===----------------------------------------------------------------------===// + +CodeViewType *CodeViewDebug::lowerTypeSubroutine(const DISubroutineType *Type) { + CodeViewTypeProcedure *CVType; + CodeViewTypeArgumentList *ArgListType; + CodeViewType *ReturnType; + int CallingConvention; + uint16_t ParamCount; + DITypeRefArray Arguments; + + // Lower the return type. + // + // The return type is recorded in the argument list at index "0". If the + // argument list is empty then the return type is void and there are no + // parameters. + // + Arguments = Type->getTypeArray(); + ReturnType = lowerType(Arguments.size() ? resolve(Arguments[0]) : nullptr); + + // Lower the argument list. + // + // The return type will be index "0", so the first argument is index "1". + // + ArgListType = lowerTypeSubroutineArgumentList(Arguments, 1); + ParamCount = ArgListType->getArgumentCount(); + + // Determine the calling convention this routine uses. + // + // FIXME: Current implementation uses only NearC calling convention. + CallingConvention = (int)CallingConvention::NearC; + + // Create an TypeRecordKind::Procedure type entry. + // + CVType = CodeViewTypeProcedure::create(); + CVType->setReturnType(ReturnType); + CVType->setArgumentList(ArgListType); + CVType->setParamCount(ParamCount); + CVType->setCallingConvention(CallingConvention); + + appendType(CVType); + mapLLVMTypeToCodeViewType(Type, CVType); + + return CVType; +} + +//===----------------------------------------------------------------------===// +// lowerSubprogramType(SP) +// +// Lowers the subroutine type of the specified subprogram. +// +//===----------------------------------------------------------------------===// + +CodeViewType *CodeViewDebug::lowerSubprogramType(const DISubprogram *SP) { + CodeViewType *CVType; + const DISubroutineType *Type; + const DIType *ClassType; + + if (!SP) + return nullptr; + + Type = SP->getType(); + ClassType = dyn_cast(resolve(SP->getScope())); + + if (ClassType) { + // TODO: implement this case. + CVType = nullptr; + } + else { + CVType = lowerType(Type); // Indirectly calls lowerTypeSubroutine(). + } + + return CVType; +} + +//===----------------------------------------------------------------------===// +// lowerSubprogramId(SP, GV) +// +// Lowers the LLVM subprogram to CodeView ID entry. +// +//===----------------------------------------------------------------------===// + +CodeViewType *CodeViewDebug::lowerSubprogramId(const DISubprogram *SP, + const Function *GV) { + + if (!SP) + return nullptr; + + CodeViewType *CVType = lowerSubprogramType(SP); + + StringRef FuncName = SP->getDisplayName(); + // If our DISubprogram name is empty, use the mangled name. + if (FuncName.empty()) + if (GV) + FuncName = GlobalValue::getRealLinkageName(GV->getName()); + else + FuncName = SP->getName(); + + CodeViewTypeFunctionID *FuncIDType = CodeViewTypeFunctionID::create(); + FuncIDType->setType(CVType); + FuncIDType->setParentScope(nullptr); // FIXME + FuncIDType->setParentClassType(nullptr); // FIXME + FuncIDType->setName(FuncName); + appendType(FuncIDType); + + return FuncIDType; +} + +void CodeViewDebug::layout() { + // Assign unique indexes to each type in the type table. + // + // When emitting the type table to an object file, we need to assign the type + // index to every type here. + // + uint16_t NextTypeIndex = llvm::codeview::TypeIndex::FirstNonSimpleIndex; + for (CodeViewType *CVType : TypeTable) { + switch (CVType->getTypeKind()) { + case CodeViewTypeKind::TypeBasic: + // Basic types are indexed when created and will not be emitted. + break; + default: + CVType->setTypeIndex(TypeIndex(NextTypeIndex++)); + break; + } + } +} + +//===----------------------------------------------------------------------===// +// emitString(Count) +//===----------------------------------------------------------------------===// +void CodeViewDebug::emitString(StringRef S) { + // Microsoft's linker seems to have trouble with symbol names longer than + // 0xffd8 bytes. + S = S.substr(0, 0xffd8); + SmallString<32> NullTerminatedString(S); + NullTerminatedString.push_back('\0'); + OS.EmitBytes(NullTerminatedString); +} + +static size_t paddingBytes(const size_t Size) { + const uint32_t Alignment = 4; + return (Alignment - (Size % Alignment)) % Alignment; +} + +//===----------------------------------------------------------------------===// +// emitPadding(Count) +//===----------------------------------------------------------------------===// + +void CodeViewDebug::emitPadding(unsigned int Count) { + static const int PaddingArray[16] = { + LF_PAD0, LF_PAD1, LF_PAD2, LF_PAD3, + LF_PAD4, LF_PAD5, LF_PAD6, LF_PAD7, + LF_PAD8, LF_PAD9, LF_PAD10, LF_PAD11, + LF_PAD12, LF_PAD13, LF_PAD14, LF_PAD15 }; + + assert(Count < 16); + + for (unsigned int I = Count; I > 0; --I) { + addComment("Padding"); + emitInt8(PaddingArray[I]); + } +} + +//===----------------------------------------------------------------------===// +// emitType(CVType) +//===----------------------------------------------------------------------===// + +void CodeViewDebug::emitType(const CodeViewType *CVType) { + CodeViewTypeKind Kind; + + Kind = CVType->getTypeKind(); + switch (Kind) { + case CodeViewTypeKind::TypeBasic: + // Primitive Types Are Predefined And Not Emitted. + break; + case CodeViewTypeKind::TypeFunctionId: + emitTypeFunctionID(static_cast(CVType)); + break; + case CodeViewTypeKind::TypeProcedure: + emitTypeProcedure(static_cast(CVType)); + break; + case CodeViewTypeKind::TypeArgumentList: + emitTypeArgumentList(static_cast(CVType)); + break; + default: + // TODO: Enable this assert once all types are implemented + //assert(Kind != Kind && invalid type kind); + break; + } +} + +//===----------------------------------------------------------------------===// +// emitTypeFunctionID(CVType) +//===----------------------------------------------------------------------===// + +void CodeViewDebug::emitTypeFunctionID(const CodeViewTypeFunctionID *CVType) { + StringRef Name = CVType->getName(); + const CodeViewType *FuncType = CVType->getType(); + const CodeViewType *ClassType = CVType->getParentClassType(); + const CodeViewType *ScopeType = + ClassType ? ClassType : CVType->getParentScope(); + unsigned SymbolID = LF_FUNC_ID; + const size_t Length = 2 + FuncIdRecord::getLayoutSize() + Name.size() + 1; + const size_t Padding = paddingBytes(Length); + + addComment("Type record length"); + emitInt16(Length + Padding - 2); + addComment("Leaf type: LF_FUNC_ID"); + emitInt16(SymbolID); + addComment("Parent scope type"); + emitInt32(CodeViewType::getIndexOrNone(ScopeType)); + addComment("Function type"); + emitInt32(CodeViewType::getIndexOrNone(FuncType)); + addComment("Function name"); + emitString(Name); + emitPadding(Padding); +} + +//===----------------------------------------------------------------------===// +// emitTypeProcedure(CVType) +//===----------------------------------------------------------------------===// + +void CodeViewDebug::emitTypeProcedure(const CodeViewTypeProcedure *CVType) { + const CodeViewType *ReturnType = CVType->getReturnType(); + int CallingConvention = CVType->getCallingConvention(); + uint16_t ParamCount = CVType->getParamCount(); + const CodeViewType *ArgList = CVType->getArgumentList(); + const size_t Length = 2 + ProcedureRecord::getLayoutSize(); + const size_t Padding = paddingBytes(Length); + + addComment("Type record length"); + emitInt16(Length + Padding - 2); + addComment("Leaf type: LF_PROCEDURE"); + emitInt16(LF_PROCEDURE); + addComment("Return Type"); + emitInt32(CodeViewType::getIndexOrNone(ReturnType)); + addComment("Calling Convention"); + emitInt8(CallingConvention); + addComment("Reserved"); + emitInt8(0); + addComment("Number of arguments"); + emitInt16(ParamCount); + addComment("Argument List Type"); + emitInt32(CodeViewType::getIndexOrNone(ArgList)); + emitPadding(Padding); +} + +//===----------------------------------------------------------------------===// +// emitTypeArgumentList(CVType) +//===----------------------------------------------------------------------===// + +void CodeViewDebug::emitTypeArgumentList( + const CodeViewTypeArgumentList *CVType) { + uint32_t ArgCount = CVType->getArgumentCount(); + const auto *ArgList = CVType->getArgumentList(); + const size_t Length = 2 + ArgListRecord::getLayoutSize() + (4 * ArgCount); + const size_t Padding = paddingBytes(Length); + + addComment("Type record length"); + emitInt16(Length + Padding - 2); + addComment("Leaf type: LF_ARGLIST"); + emitInt16(LF_ARGLIST); + addComment("Number of arguments"); + emitInt32(ArgCount); + for (const CodeViewType *ArgType : *ArgList) { + addComment("Argument Type"); + emitInt32(CodeViewType::getIndexOrNone(ArgType)); + } + emitPadding(Padding); +} Index: lib/CodeGen/AsmPrinter/CodeViewType.h =================================================================== --- lib/CodeGen/AsmPrinter/CodeViewType.h +++ lib/CodeGen/AsmPrinter/CodeViewType.h @@ -0,0 +1,166 @@ +//===-- llvm/lib/CodeGen/AsmPrinter/CodeViewType.h ----*- C++ -*--===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains support for writing Microsoft CodeView debug type info. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_CODEGEN_ASMPRINTER_CODEVIEWTYPE_H +#define LLVM_LIB_CODEGEN_ASMPRINTER_CODEVIEWTYPE_H + +#include "llvm/ADT/SmallVector.h" +#include "llvm/DebugInfo/CodeView/TypeIndex.h" + +namespace llvm { + +//===----------------------------------------------------------------------===// +// CodeViewTypeKind +//===----------------------------------------------------------------------===// +enum class CodeViewTypeKind : uint32_t { + TypeNone = 0, + TypeBasic = 1, + TypeFunctionId = 2, + TypeProcedure = 3, + TypeArgumentList = 4 +}; + +//===----------------------------------------------------------------------===// +// CodeViewType +//===----------------------------------------------------------------------===// + +class CodeViewType { +private: + CodeViewTypeKind Kind; + codeview::TypeIndex Index; + uint32_t SizeInBits; + +protected: + CodeViewType(CodeViewTypeKind Kind); + +public: + virtual ~CodeViewType(); + + CodeViewTypeKind getTypeKind() const; + + codeview::TypeIndex getTypeIndex() const; + void setTypeIndex(const codeview::TypeIndex Index); + + uint32_t getSizeInBits() const; + void setSizeInBits(uint32_t SizeInBits); + + static unsigned getIndexOrNone(const CodeViewType * CVType); +}; + +//===----------------------------------------------------------------------===// +// CodeViewTypeBasic +//===----------------------------------------------------------------------===// + +class CodeViewTypeBasic : public CodeViewType { +protected: + CodeViewTypeBasic(); + +public: + ~CodeViewTypeBasic(); + + static CodeViewTypeBasic *create(); +}; + +//===----------------------------------------------------------------------===// +// CodeViewTypeFunctionID +//===----------------------------------------------------------------------===// + +class CodeViewTypeFunctionID : public CodeViewType { +private: + CodeViewType *CVType; + CodeViewType *ParentScope; + CodeViewType *ParentClassType; + std::string Name; + +protected: + CodeViewTypeFunctionID(); + +public: + ~CodeViewTypeFunctionID(); + + static CodeViewTypeFunctionID *create(); + + CodeViewType *getType() const; + void setType(CodeViewType *Type); + + CodeViewType *getParentScope() const; + void setParentScope(CodeViewType *Scope); + + CodeViewType *getParentClassType() const; + void setParentClassType(CodeViewType *ClassType); + + StringRef getName() const; + void setName(StringRef Name); +}; + +//===----------------------------------------------------------------------===// +// CodeViewTypeProcedure +//===----------------------------------------------------------------------===// + +class CodeViewTypeProcedure : public CodeViewType { +private: + CodeViewType *ReturnType; + CodeViewType *ArgumentList; + int CallingConvention; + uint16_t ParamCount; + +protected: + CodeViewTypeProcedure(); + +public: + ~CodeViewTypeProcedure(); + + static CodeViewTypeProcedure *create(); + + CodeViewType *getReturnType() const; + void setReturnType(CodeViewType *CVType); + + int getCallingConvention() const; + void setCallingConvention(int CC); + + uint16_t getParamCount() const; + void setParamCount(uint16_t Count); + + CodeViewType *getArgumentList() const; + void setArgumentList(CodeViewType *ArgList); +}; + +//===----------------------------------------------------------------------===// +// CodeViewTypeArgumentList +//===----------------------------------------------------------------------===// + +class CodeViewTypeArgumentList : public CodeViewType { +public: + typedef SmallVector ArgTypeList; + +private: + ArgTypeList ArgumentList; + +protected: + CodeViewTypeArgumentList(); + +public: + ~CodeViewTypeArgumentList(); + + static CodeViewTypeArgumentList *create(); + + const ArgTypeList *getArgumentList() const; + ArgTypeList *getArgumentList(); + + uint32_t getArgumentCount() const; + void append(CodeViewType *Argument); +}; + +} // End of namespace llvm + +#endif Index: lib/CodeGen/AsmPrinter/CodeViewType.cpp =================================================================== --- lib/CodeGen/AsmPrinter/CodeViewType.cpp +++ lib/CodeGen/AsmPrinter/CodeViewType.cpp @@ -0,0 +1,164 @@ +//===-- llvm/lib/CodeGen/AsmPrinter/CodeViewType.cpp --*- C++ -*--===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains support for writing Microsoft CodeView debug type info. +// +//===----------------------------------------------------------------------===// + +#include "CodeViewType.h" + +using namespace llvm; +using namespace llvm::codeview; + +//===----------------------------------------------------------------------===// +// CodeViewType +//===----------------------------------------------------------------------===// + +CodeViewType::CodeViewType(CodeViewTypeKind K) : Kind(K) {} + +CodeViewType::~CodeViewType() {} + +CodeViewTypeKind CodeViewType::getTypeKind() const { return Kind; } + +TypeIndex CodeViewType::getTypeIndex() const { return Index; } + +void CodeViewType::setTypeIndex(const TypeIndex I) { Index = I; } + +uint32_t CodeViewType::getSizeInBits() const { return SizeInBits; } + +void CodeViewType::setSizeInBits(uint32_t Size) { SizeInBits = Size; } + +unsigned CodeViewType::getIndexOrNone(const CodeViewType * CVType) { + if (!CVType) + return (unsigned)SimpleTypeKind::None; + return CVType->getTypeIndex().getIndex(); +} + +//===----------------------------------------------------------------------===// +// CodeViewTypeBasic +//===----------------------------------------------------------------------===// + +CodeViewTypeBasic::CodeViewTypeBasic() + : CodeViewType(CodeViewTypeKind::TypeBasic) {} + +CodeViewTypeBasic::~CodeViewTypeBasic() {} + +CodeViewTypeBasic *CodeViewTypeBasic::create() { + return new CodeViewTypeBasic(); +} + +//===----------------------------------------------------------------------===// +// CodeViewTypeFunctionID +//===----------------------------------------------------------------------===// + +CodeViewTypeFunctionID::CodeViewTypeFunctionID() + : CodeViewType(CodeViewTypeKind::TypeFunctionId), CVType(nullptr), + ParentScope(nullptr) {} + +CodeViewTypeFunctionID::~CodeViewTypeFunctionID() {} + +CodeViewTypeFunctionID *CodeViewTypeFunctionID::create() { + return new CodeViewTypeFunctionID(); +} + +CodeViewType *CodeViewTypeFunctionID::getType() const { return CVType; } + +void CodeViewTypeFunctionID::setType(CodeViewType *Type) { CVType = Type; } + +CodeViewType *CodeViewTypeFunctionID::getParentScope() const { return ParentScope; } + +void CodeViewTypeFunctionID::setParentScope(CodeViewType *ScopeType) { + ParentScope = ScopeType; +} + +CodeViewType *CodeViewTypeFunctionID::getParentClassType() const { + return ParentClassType; +} + +void CodeViewTypeFunctionID::setParentClassType(CodeViewType *ClassType) { + ParentClassType = ClassType; +} + +StringRef CodeViewTypeFunctionID::getName() const { return Name; } + +void CodeViewTypeFunctionID::setName(StringRef N) { Name = N; } + +//===----------------------------------------------------------------------===// +// CodeViewTypeProcedure +//===----------------------------------------------------------------------===// + +CodeViewTypeProcedure::CodeViewTypeProcedure() + : CodeViewType(CodeViewTypeKind::TypeProcedure), + ReturnType(nullptr), + ArgumentList(nullptr), + CallingConvention(0), + ParamCount(0) {} + +CodeViewTypeProcedure::~CodeViewTypeProcedure() {} + +CodeViewTypeProcedure *CodeViewTypeProcedure::create() { + return new CodeViewTypeProcedure(); +} + +CodeViewType *CodeViewTypeProcedure::getReturnType() const { + return ReturnType; +} + +void CodeViewTypeProcedure::setReturnType(CodeViewType *CVType) { + ReturnType = CVType; +} + +int CodeViewTypeProcedure::getCallingConvention() const { + return CallingConvention; +} + +void CodeViewTypeProcedure::setCallingConvention(int CC) { + CallingConvention = CC; +} + +uint16_t CodeViewTypeProcedure::getParamCount() const { return ParamCount; } + +void CodeViewTypeProcedure::setParamCount(uint16_t Count) { + ParamCount = Count; +} + +CodeViewType *CodeViewTypeProcedure::getArgumentList() const { return ArgumentList; } + +void CodeViewTypeProcedure::setArgumentList(CodeViewType *ArgList) { + ArgumentList = ArgList; +} + +//===----------------------------------------------------------------------===// +// CodeViewTypeArgumentList +//===----------------------------------------------------------------------===// + +CodeViewTypeArgumentList::CodeViewTypeArgumentList() + : CodeViewType(CodeViewTypeKind::TypeArgumentList), + ArgumentList() {} + +CodeViewTypeArgumentList::~CodeViewTypeArgumentList() {} + +CodeViewTypeArgumentList *CodeViewTypeArgumentList::create() { + return new CodeViewTypeArgumentList(); +} + +const CodeViewTypeArgumentList::ArgTypeList * +CodeViewTypeArgumentList::getArgumentList() const { return &ArgumentList; } + +CodeViewTypeArgumentList::ArgTypeList * +CodeViewTypeArgumentList::getArgumentList() { return &ArgumentList; } + +uint32_t CodeViewTypeArgumentList::getArgumentCount() const { + return ArgumentList.size(); +} + +void CodeViewTypeArgumentList::append(CodeViewType *Argument) { + ArgumentList.push_back(Argument); +} + Index: test/DebugInfo/COFF/asm.ll =================================================================== --- test/DebugInfo/COFF/asm.ll +++ test/DebugInfo/COFF/asm.ll @@ -21,6 +21,26 @@ ; X86: ret ; X86: [[END_OF_F:.?Lfunc_end.*]]: ; +; X86-LABEL: .section .debug$T,"dr" +; X86-NEXT: .long 4 +; X86-NEXT: .short 6 +; X86-NEXT: .short 4609 +; X86-NEXT: .long 0 +; X86-NEXT: .short 14 +; X86-NEXT: .short 4104 +; X86-NEXT: .long 3 +; X86-NEXT: .byte 0 +; X86-NEXT: .byte 0 +; X86-NEXT: .short 0 +; X86-NEXT: .long 4096 +; X86-NEXT: .short 14 +; X86-NEXT: .short 5633 +; X86-NEXT: .long 0 +; X86-NEXT: .long 4097 +; X86-NEXT: .asciz "f" +; X86-NEXT:.byte 242 +; X86-NEXT:.byte 241 +; ; X86-LABEL: .section .debug$S,"dr" ; X86-NEXT: .long 4 ; Symbol subsection @@ -36,7 +56,7 @@ ; X86-NEXT: .long [[END_OF_F]]-_f ; X86-NEXT: .long 0 ; X86-NEXT: .long 0 -; X86-NEXT: .long 0 +; X86-NEXT: .long 4098 ; X86-NEXT: .secrel32 _f ; X86-NEXT: .secidx _f ; X86-NEXT: .byte 0 @@ -112,6 +132,26 @@ ; X64-NEXT: ret ; X64: [[END_OF_F:.?Lfunc_end.*]]: ; +; X64-LABEL: .section .debug$T,"dr" +; X64-NEXT: .long 4 +; X64-NEXT: .short 6 +; X64-NEXT: .short 4609 +; X64-NEXT: .long 0 +; X64-NEXT: .short 14 +; X64-NEXT: .short 4104 +; X64-NEXT: .long 3 +; X64-NEXT: .byte 0 +; X64-NEXT: .byte 0 +; X64-NEXT: .short 0 +; X64-NEXT: .long 4096 +; X64-NEXT: .short 14 +; X64-NEXT: .short 5633 +; X64-NEXT: .long 0 +; X64-NEXT: .long 4097 +; X64-NEXT: .asciz "f" +; X64-NEXT:.byte 242 +; X64-NEXT:.byte 241 +; ; X64-LABEL: .section .debug$S,"dr" ; X64-NEXT: .long 4 ; Symbol subsection @@ -127,7 +167,7 @@ ; X64-NEXT: .long [[END_OF_F]]-f ; X64-NEXT: .long 0 ; X64-NEXT: .long 0 -; X64-NEXT: .long 0 +; X64-NEXT: .long 4098 ; X64-NEXT: .secrel32 f ; X64-NEXT: .secidx f ; X64-NEXT: .byte 0 Index: test/DebugInfo/COFF/basic-types.ll =================================================================== --- test/DebugInfo/COFF/basic-types.ll +++ test/DebugInfo/COFF/basic-types.ll @@ -0,0 +1,272 @@ +; RUN: llc -mcpu=core2 -mtriple=i686-pc-win32 < %s | FileCheck %s --check-prefix=ASM +; RUN: llc -mcpu=core2 -mtriple=i686-pc-win32 < %s -filetype=obj | llvm-readobj -codeview | FileCheck %s --check-prefix=OBJ + +; This LL file was generated by running +; 'clang -O0 -c -g -gcodeview -S -emit-llvm' on the following code: +; 1: extern volatile int x; +; 2: void foo() { +; 3: bool b; +; 4: char c; +; 5: short s; +; 6: int i; +; 7: long l; +; 8: float f; +; 9: double d; +; 10: long double ld; +; 11: unsigned char uc; +; 12: insigned short us; +; 13: unsigned int ui; +; 14: unsigned long ul; +; 15: x += (int)&b + (int)&c + (int)&s + (int)&i + (int)&l + (int)&f + (int)&d +; 16: + (int)&ld + (int)&uc + (int)&us + (int)&ui + (int)&ul; +; 17: } + +; ASM: .section .debug$T,"dr" +; ASM: .long 4 +; ASM: .short 6 +; ASM: .short 4609 +; ASM: .long 0 +; ASM: .short 14 +; ASM: .short 4104 +; ASM: .long 3 +; ASM: .byte 0 +; ASM: .byte 0 +; ASM: .short 0 +; ASM: .long 4096 +; ASM: .short 14 +; ASM: .short 5633 +; ASM: .long 0 +; ASM: .long 4097 +; ASM: .asciz "foo" +; +; ASM: .section .debug$S,"dr" +; ASM: .short 4414 # Record kind: S_LOCAL +; ASM: .long 48 # TypeIndex +; ASM: .asciz "b" +; ASM: .short 4414 # Record kind: S_LOCAL +; ASM: .long 16 # TypeIndex +; ASM: .asciz "c" +; ASM: .short 4414 # Record kind: S_LOCAL +; ASM: .long 17 # TypeIndex +; ASM: .asciz "s" +; ASM: .short 4414 # Record kind: S_LOCAL +; ASM: .long 116 # TypeIndex +; ASM: .asciz "i" +; ASM: .short 4414 # Record kind: S_LOCAL +; ASM: .long 18 # TypeIndex +; ASM: .asciz "l" +; ASM: .short 4414 # Record kind: S_LOCAL +; ASM: .long 64 # TypeIndex +; ASM: .asciz "f" +; ASM: .short 4414 # Record kind: S_LOCAL +; ASM: .long 65 # TypeIndex +; ASM: .asciz "d" +; ASM: .short 4414 # Record kind: S_LOCAL +; ASM: .long 65 # TypeIndex +; ASM: .asciz "ld" +; ASM: .short 4414 # Record kind: S_LOCAL +; ASM: .long 32 # TypeIndex +; ASM: .asciz "uc" +; ASM: .short 4414 # Record kind: S_LOCAL +; ASM: .long 115 # TypeIndex +; ASM: .asciz "us" +; ASM: .short 4414 # Record kind: S_LOCAL +; ASM: .long 117 # TypeIndex +; ASM: .asciz "ui" +; ASM: .short 4414 # Record kind: S_LOCAL +; ASM: .long 34 # TypeIndex +; ASM: .asciz "ul" + +; OBJ: Local { +; OBJ: Type: bool (0x30) +; OBJ: VarName: b +; OBJ: } +; OBJ: Local { +; OBJ: Type: signed char (0x10) +; OBJ: VarName: c +; OBJ: } +; OBJ: Local { +; OBJ: Type: short (0x11) +; OBJ: VarName: s +; OBJ: } +; OBJ: Local { +; OBJ: Type: int (0x74) +; OBJ: VarName: i +; OBJ: } +; OBJ: Local { +; OBJ: Type: long (0x12) +; OBJ: VarName: l +; OBJ: } +; OBJ: Local { +; OBJ: Type: float (0x40) +; OBJ: VarName: f +; OBJ: } +; OBJ: Local { +; OBJ: Type: double (0x41) +; OBJ: VarName: d +; OBJ: } +; OBJ: Local { +; OBJ: Type: double (0x41) +; OBJ: VarName: ld +; OBJ: } +; OBJ: Local { +; OBJ: Type: unsigned char (0x20) +; OBJ: VarName: uc +; OBJ: } +; OBJ: Local { +; OBJ: Type: unsigned __int16 (0x73) +; OBJ: VarName: us +; OBJ: } +; OBJ: Local { +; OBJ: Type: unsigned (0x75) +; OBJ: VarName: ui +; OBJ: } +; OBJ: Local { +; OBJ: Type: unsigned long (0x22) +; OBJ: VarName: ul +; OBJ: } + +; ModuleID = 'basic-types.cpp' +target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-pc-windows-msvc18.0.0" + +@"\01?x@@3HC" = external global i32, align 4 + +; Function Attrs: nounwind +define void @"\01?foo@@YAXXZ"() #0 !dbg !8 { +entry: + %b = alloca i8, align 1 + %c = alloca i8, align 1 + %s = alloca i16, align 2 + %i = alloca i32, align 4 + %l = alloca i32, align 4 + %f = alloca float, align 4 + %d = alloca double, align 8 + %ld = alloca double, align 8 + %uc = alloca i8, align 1 + %us = alloca i16, align 2 + %ui = alloca i32, align 4 + %ul = alloca i32, align 4 + call void @llvm.dbg.declare(metadata i8* %b, metadata !11, metadata !13), !dbg !14 + call void @llvm.dbg.declare(metadata i8* %c, metadata !15, metadata !13), !dbg !17 + call void @llvm.dbg.declare(metadata i16* %s, metadata !18, metadata !13), !dbg !20 + call void @llvm.dbg.declare(metadata i32* %i, metadata !21, metadata !13), !dbg !22 + call void @llvm.dbg.declare(metadata i32* %l, metadata !23, metadata !13), !dbg !25 + call void @llvm.dbg.declare(metadata float* %f, metadata !26, metadata !13), !dbg !28 + call void @llvm.dbg.declare(metadata double* %d, metadata !29, metadata !13), !dbg !31 + call void @llvm.dbg.declare(metadata double* %ld, metadata !32, metadata !13), !dbg !34 + call void @llvm.dbg.declare(metadata i8* %uc, metadata !35, metadata !13), !dbg !37 + call void @llvm.dbg.declare(metadata i16* %us, metadata !38, metadata !13), !dbg !40 + call void @llvm.dbg.declare(metadata i32* %ui, metadata !41, metadata !13), !dbg !43 + call void @llvm.dbg.declare(metadata i32* %ul, metadata !44, metadata !13), !dbg !46 + %0 = ptrtoint i8* %b to i32, !dbg !47 + %1 = ptrtoint i8* %c to i32, !dbg !48 + %add = add nsw i32 %0, %1, !dbg !49 + %2 = ptrtoint i16* %s to i32, !dbg !50 + %add1 = add nsw i32 %add, %2, !dbg !51 + %3 = ptrtoint i32* %i to i32, !dbg !52 + %add2 = add nsw i32 %add1, %3, !dbg !53 + %4 = ptrtoint i32* %l to i32, !dbg !54 + %add3 = add nsw i32 %add2, %4, !dbg !55 + %5 = ptrtoint float* %f to i32, !dbg !56 + %add4 = add nsw i32 %add3, %5, !dbg !57 + %6 = ptrtoint double* %d to i32, !dbg !58 + %add5 = add nsw i32 %add4, %6, !dbg !59 + %7 = ptrtoint double* %ld to i32, !dbg !60 + %add6 = add nsw i32 %add5, %7, !dbg !61 + %8 = ptrtoint i8* %uc to i32, !dbg !62 + %add7 = add nsw i32 %add6, %8, !dbg !63 + %9 = ptrtoint i16* %us to i32, !dbg !64 + %add8 = add nsw i32 %add7, %9, !dbg !65 + %10 = ptrtoint i32* %ui to i32, !dbg !66 + %add9 = add nsw i32 %add8, %10, !dbg !67 + %11 = ptrtoint i32* %ul to i32, !dbg !68 + %add10 = add nsw i32 %add9, %11, !dbg !69 + %12 = load volatile i32, i32* @"\01?x@@3HC", align 4, !dbg !70 + %add11 = add nsw i32 %12, %add10, !dbg !70 + store volatile i32 %add11, i32* @"\01?x@@3HC", align 4, !dbg !70 + ret void, !dbg !71 +} + +; Function Attrs: nounwind readnone +declare void @llvm.dbg.declare(metadata, metadata, metadata) #1 + +attributes #0 = { nounwind } +attributes #1 = { nounwind readnone } + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!5, !6} +!llvm.ident = !{!7} + +!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !1, producer: "clang version 3.9.0 (trunk 269756)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, retainedTypes: !3) +!1 = !DIFile(filename: "basic-types.cpp", directory: "/") +!2 = !{} +!3 = !{!4} +!4 = !DIBasicType(name: "int", size: 32, align: 32, encoding: DW_ATE_signed) +!5 = !{i32 2, !"CodeView", i32 1} +!6 = !{i32 2, !"Debug Info Version", i32 3} +!7 = !{!"clang version 3.9.0 (trunk 269756)"} +!8 = distinct !DISubprogram(name: "foo", linkageName: "\01?foo@@YAXXZ", scope: !1, file: !1, line: 2, type: !9, isLocal: false, isDefinition: true, scopeLine: 2, flags: DIFlagPrototyped, isOptimized: false, unit: !0, variables: !2) +!9 = !DISubroutineType(types: !10) +!10 = !{null} +!11 = !DILocalVariable(name: "b", scope: !8, file: !1, line: 3, type: !12) +!12 = !DIBasicType(name: "bool", size: 8, align: 8, encoding: DW_ATE_boolean) +!13 = !DIExpression() +!14 = !DILocation(line: 3, column: 8, scope: !8) +!15 = !DILocalVariable(name: "c", scope: !8, file: !1, line: 4, type: !16) +!16 = !DIBasicType(name: "char", size: 8, align: 8, encoding: DW_ATE_signed_char) +!17 = !DILocation(line: 4, column: 8, scope: !8) +!18 = !DILocalVariable(name: "s", scope: !8, file: !1, line: 5, type: !19) +!19 = !DIBasicType(name: "short", size: 16, align: 16, encoding: DW_ATE_signed) +!20 = !DILocation(line: 5, column: 9, scope: !8) +!21 = !DILocalVariable(name: "i", scope: !8, file: !1, line: 6, type: !4) +!22 = !DILocation(line: 6, column: 7, scope: !8) +!23 = !DILocalVariable(name: "l", scope: !8, file: !1, line: 7, type: !24) +!24 = !DIBasicType(name: "long int", size: 32, align: 32, encoding: DW_ATE_signed) +!25 = !DILocation(line: 7, column: 8, scope: !8) +!26 = !DILocalVariable(name: "f", scope: !8, file: !1, line: 8, type: !27) +!27 = !DIBasicType(name: "float", size: 32, align: 32, encoding: DW_ATE_float) +!28 = !DILocation(line: 8, column: 9, scope: !8) +!29 = !DILocalVariable(name: "d", scope: !8, file: !1, line: 9, type: !30) +!30 = !DIBasicType(name: "double", size: 64, align: 64, encoding: DW_ATE_float) +!31 = !DILocation(line: 9, column: 10, scope: !8) +!32 = !DILocalVariable(name: "ld", scope: !8, file: !1, line: 10, type: !33) +!33 = !DIBasicType(name: "long double", size: 64, align: 64, encoding: DW_ATE_float) +!34 = !DILocation(line: 10, column: 15, scope: !8) +!35 = !DILocalVariable(name: "uc", scope: !8, file: !1, line: 11, type: !36) +!36 = !DIBasicType(name: "unsigned char", size: 8, align: 8, encoding: DW_ATE_unsigned_char) +!37 = !DILocation(line: 11, column: 17, scope: !8) +!38 = !DILocalVariable(name: "us", scope: !8, file: !1, line: 12, type: !39) +!39 = !DIBasicType(name: "unsigned short", size: 16, align: 16, encoding: DW_ATE_unsigned) +!40 = !DILocation(line: 12, column: 18, scope: !8) +!41 = !DILocalVariable(name: "ui", scope: !8, file: !1, line: 13, type: !42) +!42 = !DIBasicType(name: "unsigned int", size: 32, align: 32, encoding: DW_ATE_unsigned) +!43 = !DILocation(line: 13, column: 16, scope: !8) +!44 = !DILocalVariable(name: "ul", scope: !8, file: !1, line: 14, type: !45) +!45 = !DIBasicType(name: "long unsigned int", size: 32, align: 32, encoding: DW_ATE_unsigned) +!46 = !DILocation(line: 14, column: 17, scope: !8) +!47 = !DILocation(line: 15, column: 8, scope: !8) +!48 = !DILocation(line: 15, column: 18, scope: !8) +!49 = !DILocation(line: 15, column: 16, scope: !8) +!50 = !DILocation(line: 15, column: 28, scope: !8) +!51 = !DILocation(line: 15, column: 26, scope: !8) +!52 = !DILocation(line: 15, column: 38, scope: !8) +!53 = !DILocation(line: 15, column: 36, scope: !8) +!54 = !DILocation(line: 15, column: 48, scope: !8) +!55 = !DILocation(line: 15, column: 46, scope: !8) +!56 = !DILocation(line: 15, column: 58, scope: !8) +!57 = !DILocation(line: 15, column: 56, scope: !8) +!58 = !DILocation(line: 15, column: 68, scope: !8) +!59 = !DILocation(line: 15, column: 66, scope: !8) +!60 = !DILocation(line: 16, column: 6, scope: !8) +!61 = !DILocation(line: 16, column: 5, scope: !8) +!62 = !DILocation(line: 16, column: 17, scope: !8) +!63 = !DILocation(line: 16, column: 15, scope: !8) +!64 = !DILocation(line: 16, column: 28, scope: !8) +!65 = !DILocation(line: 16, column: 26, scope: !8) +!66 = !DILocation(line: 16, column: 39, scope: !8) +!67 = !DILocation(line: 16, column: 37, scope: !8) +!68 = !DILocation(line: 16, column: 50, scope: !8) +!69 = !DILocation(line: 16, column: 48, scope: !8) +!70 = !DILocation(line: 15, column: 5, scope: !8) +!71 = !DILocation(line: 17, column: 1, scope: !8) Index: test/DebugInfo/COFF/function-type.ll =================================================================== --- test/DebugInfo/COFF/function-type.ll +++ test/DebugInfo/COFF/function-type.ll @@ -0,0 +1,117 @@ +; RUN: llc -mcpu=core2 -mtriple=i686-pc-win32 < %s | FileCheck %s --check-prefix=ASM +; RUN: llc -mcpu=core2 -mtriple=i686-pc-win32 < %s -filetype=obj | llvm-readobj -codeview | FileCheck %s --check-prefix=OBJ + +; This LL file was generated by running +; 'clang -O0 -c -g -gcodeview -S -emit-llvm' on the following code: +; 1: int foo(char c, short s, long l, float f) { +; 2: return 0; +; 3: } + +; ASM: .section .debug$T,"dr" +; ASM: long 4 # Debug section magic +; ASM: short 22 # Type record length +; ASM: short 4609 # Leaf type: LF_ARGLIST +; ASM: long 4 # Number of arguments +; ASM: long 16 # Argument Type +; ASM: long 17 # Argument Type +; ASM: long 18 # Argument Type +; ASM: long 64 # Argument Type +; ASM: short 14 # Type record length +; ASM: short 4104 # Leaf type: LF_PROCEDURE +; ASM: long 116 # Return Type +; ASM: byte 0 # Calling Convention +; ASM: byte 0 # Reserved +; ASM: short 4 # Number of arguments +; ASM: long 4096 # Argument List Type +; ASM: short 14 # Type record length +; ASM: short 5633 # Leaf type: LF_FUNC_ID +; ASM: long 0 # Parent scope type +; ASM: long 4097 # Function type +; ASM: asciz "foo" # Function name + +; OBJ: CodeViewTypes [ +; OBJ: Section: .debug$T (4) +; OBJ: Magic: 0x4 +; OBJ: ArgList (0x1000) { +; OBJ: TypeLeafKind: LF_ARGLIST (0x1201) +; OBJ: NumArgs: 4 +; OBJ: Arguments [ +; OBJ: ArgType: signed char (0x10) +; OBJ: ArgType: short (0x11) +; OBJ: ArgType: long (0x12) +; OBJ: ArgType: float (0x40) +; OBJ: ] +; OBJ: } +; OBJ: Procedure (0x1001) { +; OBJ: TypeLeafKind: LF_PROCEDURE (0x1008) +; OBJ: ReturnType: int (0x74) +; OBJ: CallingConvention: NearC (0x0) +; OBJ: FunctionOptions [ (0x0) +; OBJ: ] +; OBJ: NumParameters: 4 +; OBJ: ArgListType: (signed char, short, long, float) (0x1000) +; OBJ: } +; OBJ: FuncId (0x1002) { +; OBJ: TypeLeafKind: LF_FUNC_ID (0x1601) +; OBJ: ParentScope: 0x0 +; OBJ: FunctionType: int (signed char, short, long, float) (0x1001) +; OBJ: Name: foo +; OBJ: } +; OBJ: ] + +; ModuleID = 'function-type.c' +target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-pc-windows-msvc18.0.0" + +; Function Attrs: nounwind +define i32 @foo(i8 signext %c, i16 signext %s, i32 %l, float %f) #0 !dbg !6 { +entry: + %f.addr = alloca float, align 4 + %l.addr = alloca i32, align 4 + %s.addr = alloca i16, align 2 + %c.addr = alloca i8, align 1 + store float %f, float* %f.addr, align 4 + call void @llvm.dbg.declare(metadata float* %f.addr, metadata !14, metadata !15), !dbg !16 + store i32 %l, i32* %l.addr, align 4 + call void @llvm.dbg.declare(metadata i32* %l.addr, metadata !17, metadata !15), !dbg !18 + store i16 %s, i16* %s.addr, align 2 + call void @llvm.dbg.declare(metadata i16* %s.addr, metadata !19, metadata !15), !dbg !20 + store i8 %c, i8* %c.addr, align 1 + call void @llvm.dbg.declare(metadata i8* %c.addr, metadata !21, metadata !15), !dbg !22 + ret i32 0, !dbg !23 +} + +; Function Attrs: nounwind readnone +declare void @llvm.dbg.declare(metadata, metadata, metadata) #1 + +attributes #0 = { nounwind } +attributes #1 = { nounwind readnone } + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!3, !4} +!llvm.ident = !{!5} + +!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 3.9.0 (trunk 269756)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2) +!1 = !DIFile(filename: "function-type.c", directory: "/") +!2 = !{} +!3 = !{i32 2, !"CodeView", i32 1} +!4 = !{i32 2, !"Debug Info Version", i32 3} +!5 = !{!"clang version 3.9.0 (trunk 269756)"} +!6 = distinct !DISubprogram(name: "foo", scope: !1, file: !1, line: 1, type: !7, isLocal: false, isDefinition: true, scopeLine: 1, flags: DIFlagPrototyped, isOptimized: false, unit: !0, variables: !2) +!7 = !DISubroutineType(types: !8) +!8 = !{!9, !10, !11, !12, !13} +!9 = !DIBasicType(name: "int", size: 32, align: 32, encoding: DW_ATE_signed) +!10 = !DIBasicType(name: "char", size: 8, align: 8, encoding: DW_ATE_signed_char) +!11 = !DIBasicType(name: "short", size: 16, align: 16, encoding: DW_ATE_signed) +!12 = !DIBasicType(name: "long int", size: 32, align: 32, encoding: DW_ATE_signed) +!13 = !DIBasicType(name: "float", size: 32, align: 32, encoding: DW_ATE_float) +!14 = !DILocalVariable(name: "f", arg: 4, scope: !6, file: !1, line: 1, type: !13) +!15 = !DIExpression() +!16 = !DILocation(line: 1, column: 40, scope: !6) +!17 = !DILocalVariable(name: "l", arg: 3, scope: !6, file: !1, line: 1, type: !12) +!18 = !DILocation(line: 1, column: 31, scope: !6) +!19 = !DILocalVariable(name: "s", arg: 2, scope: !6, file: !1, line: 1, type: !11) +!20 = !DILocation(line: 1, column: 23, scope: !6) +!21 = !DILocalVariable(name: "c", arg: 1, scope: !6, file: !1, line: 1, type: !10) +!22 = !DILocation(line: 1, column: 14, scope: !6) +!23 = !DILocation(line: 2, column: 3, scope: !6) Index: test/DebugInfo/COFF/inlining.ll =================================================================== --- test/DebugInfo/COFF/inlining.ll +++ test/DebugInfo/COFF/inlining.ll @@ -94,6 +94,12 @@ ; OBJ: FunctionType: void () (0x1001) ; OBJ: Name: foo ; OBJ: } +; OBJ: FuncId (0x1004) { +; OBJ: TypeLeafKind: LF_FUNC_ID (0x1601) +; OBJ: ParentScope: 0x0 +; OBJ: FunctionType: void () (0x1001) +; OBJ: Name: baz +; OBJ: } ; OBJ-NOT: TypeLeafKind: LF_FUNC_ID ; OBJ: ] @@ -120,7 +126,7 @@ ; OBJ: CodeSize: 0x3D ; OBJ: DbgStart: 0x0 ; OBJ: DbgEnd: 0x0 -; OBJ: FunctionType: 0x0 +; OBJ: FunctionType: baz (0x1004) ; OBJ: CodeOffset: ?baz@@YAXXZ+0x0 ; OBJ: Segment: 0x0 ; OBJ: Flags [ (0x0) Index: test/DebugInfo/COFF/multifile.ll =================================================================== --- test/DebugInfo/COFF/multifile.ll +++ test/DebugInfo/COFF/multifile.ll @@ -30,6 +30,26 @@ ; X86: ret ; X86: [[END_OF_F:.?Lfunc_end.*]]: ; +; X86-LABEL: .section .debug$T,"dr" +; X86-NEXT: .long 4 +; X86-NEXT: .short 6 +; X86-NEXT: .short 4609 +; X86-NEXT: .long 0 +; X86-NEXT: .short 14 +; X86-NEXT: .short 4104 +; X86-NEXT: .long 3 +; X86-NEXT: .byte 0 +; X86-NEXT: .byte 0 +; X86-NEXT: .short 0 +; X86-NEXT: .long 4096 +; X86-NEXT: .short 14 +; X86-NEXT: .short 5633 +; X86-NEXT: .long 0 +; X86-NEXT: .long 4097 +; X86-NEXT: .asciz "f" +; X86-NEXT: .byte 242 +; X86-NEXT: .byte 241 +; ; X86-LABEL: .section .debug$S,"dr" ; X86-NEXT: .long 4 ; Symbol subsection @@ -45,7 +65,7 @@ ; X86-NEXT: .long [[END_OF_F]]-_f ; X86-NEXT: .long 0 ; X86-NEXT: .long 0 -; X86-NEXT: .long 0 +; X86-NEXT: .long 4098 ; X86-NEXT: .secrel32 _f ; X86-NEXT: .secidx _f ; X86-NEXT: .byte 0 @@ -136,6 +156,26 @@ ; X64-NEXT: ret ; X64: [[END_OF_F:.?Lfunc_end.*]]: ; +; X64-LABEL: .section .debug$T,"dr" +; X64-NEXT: .long 4 +; X64-NEXT: .short 6 +; X64-NEXT: .short 4609 +; X64-NEXT: .long 0 +; X64-NEXT: .short 14 +; X64-NEXT: .short 4104 +; X64-NEXT: .long 3 +; X64-NEXT: .byte 0 +; X64-NEXT: .byte 0 +; X64-NEXT: .short 0 +; X64-NEXT: .long 4096 +; X64-NEXT: .short 14 +; X64-NEXT: .short 5633 +; X64-NEXT: .long 0 +; X64-NEXT: .long 4097 +; X64-NEXT: .asciz "f" +; X64-NEXT: .byte 242 +; X64-NEXT: .byte 241 +; ; X64-LABEL: .section .debug$S,"dr" ; X64-NEXT: .long 4 ; Symbol subsection @@ -151,7 +191,7 @@ ; X64-NEXT: .long [[END_OF_F]]-f ; X64-NEXT: .long 0 ; X64-NEXT: .long 0 -; X64-NEXT: .long 0 +; X64-NEXT: .long 4098 ; X64-NEXT: .secrel32 f ; X64-NEXT: .secidx f ; X64-NEXT: .byte 0 Index: test/DebugInfo/COFF/multifunction.ll =================================================================== --- test/DebugInfo/COFF/multifunction.ll +++ test/DebugInfo/COFF/multifunction.ll @@ -51,6 +51,40 @@ ; X86: ret ; X86: [[END_OF_F:.?Lfunc_end.*]]: ; +; X86-LABEL: .section .debug$T,"dr" +; X86-NEXT: .long 4 +; X86-NEXT: .short 6 +; X86-NEXT: .short 4609 +; X86-NEXT: .long 0 +; X86-NEXT: .short 14 +; X86-NEXT: .short 4104 +; X86-NEXT: .long 3 +; X86-NEXT: .byte 0 +; X86-NEXT: .byte 0 +; X86-NEXT: .short 0 +; X86-NEXT: .long 4096 +; X86-NEXT: .short 14 +; X86-NEXT: .short 5633 +; X86-NEXT: .long 0 +; X86-NEXT: .long 4097 +; X86-NEXT: .asciz "x" +; X86-NEXT: .byte 242 +; X86-NEXT: .byte 241 +; X86-NEXT: .short 14 +; X86-NEXT: .short 5633 +; X86-NEXT: .long 0 +; X86-NEXT: .long 4097 +; X86-NEXT: .asciz "y" +; X86-NEXT: .byte 242 +; X86-NEXT: .byte 241 +; X86-NEXT: .short 14 +; X86-NEXT: .short 5633 +; X86-NEXT: .long 0 +; X86-NEXT: .long 4097 +; X86-NEXT: .asciz "f" +; X86-NEXT: .byte 242 +; X86-NEXT: .byte 241 +; ; X86-LABEL: .section .debug$S,"dr" ; X86-NEXT: .long 4 ; Symbol subsection for x @@ -66,7 +100,7 @@ ; X86-NEXT: .long [[END_OF_X]]-_x ; X86-NEXT: .long 0 ; X86-NEXT: .long 0 -; X86-NEXT: .long 0 +; X86-NEXT: .long 4098 ; X86-NEXT: .secrel32 _x ; X86-NEXT: .secidx _x ; X86-NEXT: .byte 0 @@ -91,7 +125,7 @@ ; X86-NEXT: .long [[END_OF_Y]]-_y ; X86-NEXT: .long 0 ; X86-NEXT: .long 0 -; X86-NEXT: .long 0 +; X86-NEXT: .long 4099 ; X86-NEXT: .secrel32 _y ; X86-NEXT: .secidx _y ; X86-NEXT: .byte 0 @@ -116,7 +150,7 @@ ; X86-NEXT: .long [[END_OF_F]]-_f ; X86-NEXT: .long 0 ; X86-NEXT: .long 0 -; X86-NEXT: .long 0 +; X86-NEXT: .long 4100 ; X86-NEXT: .secrel32 _f ; X86-NEXT: .secidx _f ; X86-NEXT: .byte 0 @@ -311,6 +345,40 @@ ; X64-NEXT: ret ; X64: [[END_OF_F:.?Lfunc_end.*]]: ; +; X64-LABEL: .section .debug$T,"dr" +; X64-NEXT: .long 4 +; X64-NEXT: .short 6 +; X64-NEXT: .short 4609 +; X64-NEXT: .long 0 +; X64-NEXT: .short 14 +; X64-NEXT: .short 4104 +; X64-NEXT: .long 3 +; X64-NEXT: .byte 0 +; X64-NEXT: .byte 0 +; X64-NEXT: .short 0 +; X64-NEXT: .long 4096 +; X64-NEXT: .short 14 +; X64-NEXT: .short 5633 +; X64-NEXT: .long 0 +; X64-NEXT: .long 4097 +; X64-NEXT: .asciz "x" +; X64-NEXT: .byte 242 +; X64-NEXT: .byte 241 +; X64-NEXT: .short 14 +; X64-NEXT: .short 5633 +; X64-NEXT: .long 0 +; X64-NEXT: .long 4097 +; X64-NEXT: .asciz "y" +; X64-NEXT: .byte 242 +; X64-NEXT: .byte 241 +; X64-NEXT: .short 14 +; X64-NEXT: .short 5633 +; X64-NEXT: .long 0 +; X64-NEXT: .long 4097 +; X64-NEXT: .asciz "f" +; X64-NEXT: .byte 242 +; X64-NEXT: .byte 241 +; ; X64-LABEL: .section .debug$S,"dr" ; X64-NEXT: .long 4 ; Symbol subsection for x @@ -326,7 +394,7 @@ ; X64-NEXT: .long [[END_OF_X]]-x ; X64-NEXT: .long 0 ; X64-NEXT: .long 0 -; X64-NEXT: .long 0 +; X64-NEXT: .long 4098 ; X64-NEXT: .secrel32 x ; X64-NEXT: .secidx x ; X64-NEXT: .byte 0 @@ -351,7 +419,7 @@ ; X64-NEXT: .long [[END_OF_Y]]-y ; X64-NEXT: .long 0 ; X64-NEXT: .long 0 -; X64-NEXT: .long 0 +; X64-NEXT: .long 4099 ; X64-NEXT: .secrel32 y ; X64-NEXT: .secidx y ; X64-NEXT: .byte 0 @@ -376,7 +444,7 @@ ; X64-NEXT: .long [[END_OF_F]]-f ; X64-NEXT: .long 0 ; X64-NEXT: .long 0 -; X64-NEXT: .long 0 +; X64-NEXT: .long 4100 ; X64-NEXT: .secrel32 f ; X64-NEXT: .secidx f ; X64-NEXT: .byte 0 Index: test/DebugInfo/COFF/simple.ll =================================================================== --- test/DebugInfo/COFF/simple.ll +++ test/DebugInfo/COFF/simple.ll @@ -20,6 +20,26 @@ ; X86: ret ; X86: [[END_OF_F:Lfunc_end.*]]: ; +; X86-LABEL: .section .debug$T,"dr" +; X86-NEXT:.long 4 +; X86-NEXT:.short 6 +; X86-NEXT:.short 4609 +; X86-NEXT:.long 0 +; X86-NEXT:.short 14 +; X86-NEXT:.short 4104 +; X86-NEXT:.long 3 +; X86-NEXT:.byte 0 +; X86-NEXT:.byte 0 +; X86-NEXT:.short 0 +; X86-NEXT:.long 4096 +; X86-NEXT:.short 14 +; X86-NEXT:.short 5633 +; X86-NEXT:.long 0 +; X86-NEXT:.long 4097 +; X86-NEXT:.asciz "f" +; X86-NEXT:.byte 242 +; X86-NEXT:.byte 241 +; ; X86-LABEL: .section .debug$S,"dr" ; X86-NEXT: .long 4 ; Symbol subsection @@ -35,7 +55,7 @@ ; X86-NEXT: .long [[END_OF_F]]-_f ; X86-NEXT: .long 0 ; X86-NEXT: .long 0 -; X86-NEXT: .long 0 +; X86-NEXT: .long 4098 ; X86-NEXT: .secrel32 _f ; X86-NEXT: .secidx _f ; X86-NEXT: .byte 0 @@ -108,6 +128,26 @@ ; X64-NEXT: ret ; X64: [[END_OF_F:.?Lfunc_end.*]]: ; +; X64-LABEL: .section .debug$T,"dr" +; X64-NEXT:.long 4 +; X64-NEXT:.short 6 +; X64-NEXT:.short 4609 +; X64-NEXT:.long 0 +; X64-NEXT:.short 14 +; X64-NEXT:.short 4104 +; X64-NEXT:.long 3 +; X64-NEXT:.byte 0 +; X64-NEXT:.byte 0 +; X64-NEXT:.short 0 +; X64-NEXT:.long 4096 +; X64-NEXT:.short 14 +; X64-NEXT:.short 5633 +; X64-NEXT:.long 0 +; X64-NEXT:.long 4097 +; X64-NEXT:.asciz "f" +; X64-NEXT:.byte 242 +; X64-NEXT:.byte 241 +; ; X64-LABEL: .section .debug$S,"dr" ; X64-NEXT: .long 4 ; Symbol subsection @@ -123,7 +163,7 @@ ; X64-NEXT: .long [[END_OF_F]]-f ; X64-NEXT: .long 0 ; X64-NEXT: .long 0 -; X64-NEXT: .long 0 +; X64-NEXT: .long 4098 ; X64-NEXT: .secrel32 f ; X64-NEXT: .secidx f ; X64-NEXT: .byte 0