Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/corert.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'src/Native/ObjWriter')
-rw-r--r--src/Native/ObjWriter/.nuget/Microsoft.DotNet.ObjectWriter.nuspec20
-rw-r--r--src/Native/ObjWriter/.nuget/runtime.json19
-rw-r--r--src/Native/ObjWriter/.nuget/toolchain.osx.10.10-x64.Microsoft.DotNet.ObjectWriter.nuspec20
-rw-r--r--src/Native/ObjWriter/.nuget/toolchain.ubuntu.14.04-x64.Microsoft.DotNet.ObjectWriter.nuspec20
-rw-r--r--src/Native/ObjWriter/.nuget/toolchain.win7-x64.Microsoft.DotNet.ObjectWriter.nuspec20
-rw-r--r--src/Native/ObjWriter/CMakeLists.txt21
-rw-r--r--src/Native/ObjWriter/cordebuginfo.h194
-rw-r--r--src/Native/ObjWriter/cvconst.h18
-rw-r--r--src/Native/ObjWriter/debugInfo/codeView/codeViewTypeBuilder.cpp (renamed from src/Native/ObjWriter/typeBuilder.cpp)105
-rw-r--r--src/Native/ObjWriter/debugInfo/codeView/codeViewTypeBuilder.h73
-rw-r--r--src/Native/ObjWriter/debugInfo/dwarf/dwarfAbbrev.cpp284
-rw-r--r--src/Native/ObjWriter/debugInfo/dwarf/dwarfAbbrev.h59
-rw-r--r--src/Native/ObjWriter/debugInfo/dwarf/dwarfGen.cpp1066
-rw-r--r--src/Native/ObjWriter/debugInfo/dwarf/dwarfGen.h106
-rw-r--r--src/Native/ObjWriter/debugInfo/dwarf/dwarfTypeBuilder.cpp780
-rw-r--r--src/Native/ObjWriter/debugInfo/dwarf/dwarfTypeBuilder.h366
-rw-r--r--src/Native/ObjWriter/debugInfo/typeBuilder.h158
-rw-r--r--src/Native/ObjWriter/jitDebugInfo.h12
-rw-r--r--src/Native/ObjWriter/llvm.patch57
-rw-r--r--src/Native/ObjWriter/llvmCap/CMakeLists.txt20
-rw-r--r--src/Native/ObjWriter/objwriter.cpp114
-rw-r--r--src/Native/ObjWriter/objwriter.h48
-rw-r--r--src/Native/ObjWriter/typeBuilder.h145
23 files changed, 3273 insertions, 452 deletions
diff --git a/src/Native/ObjWriter/.nuget/Microsoft.DotNet.ObjectWriter.nuspec b/src/Native/ObjWriter/.nuget/Microsoft.DotNet.ObjectWriter.nuspec
deleted file mode 100644
index f3421bb32..000000000
--- a/src/Native/ObjWriter/.nuget/Microsoft.DotNet.ObjectWriter.nuspec
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0"?>
-<package >
- <metadata>
- <id>Microsoft.DotNet.ObjectWriter</id>
- <version>1.0.19-prerelease-00001</version>
- <title>Microsoft .NET Object File Generator</title>
- <authors>Microsoft</authors>
- <owners>Microsoft</owners>
- <licenseUrl>http://go.microsoft.com/fwlink/?LinkId=329770</licenseUrl>
- <projectUrl>https://github.com/dotnet/corert</projectUrl>
- <iconUrl>http://go.microsoft.com/fwlink/?LinkID=288859</iconUrl>
- <requireLicenseAcceptance>true</requireLicenseAcceptance>
- <description>Provides object writer to the managed to native code-generator.</description>
- <releaseNotes>Initial release</releaseNotes>
- <copyright>Copyright &#169; Microsoft Corporation</copyright>
- </metadata>
- <files>
- <file src="runtime.json" />
- </files>
-</package>
diff --git a/src/Native/ObjWriter/.nuget/runtime.json b/src/Native/ObjWriter/.nuget/runtime.json
deleted file mode 100644
index c9c5b8e6b..000000000
--- a/src/Native/ObjWriter/.nuget/runtime.json
+++ /dev/null
@@ -1,19 +0,0 @@
-{
- "runtimes": {
- "win7-x64": {
- "Microsoft.DotNet.ObjectWriter": {
- "toolchain.win7-x64.Microsoft.DotNet.ObjectWriter": "1.0.19-prerelease-00001"
- }
- },
- "ubuntu.14.04-x64": {
- "Microsoft.DotNet.ObjectWriter": {
- "toolchain.ubuntu.14.04-x64.Microsoft.DotNet.ObjectWriter": "1.0.19-prerelease-00001"
- }
- },
- "osx.10.10-x64": {
- "Microsoft.DotNet.ObjectWriter": {
- "toolchain.osx.10.10-x64.Microsoft.DotNet.ObjectWriter": "1.0.19-prerelease-00001"
- }
- }
- }
-}
diff --git a/src/Native/ObjWriter/.nuget/toolchain.osx.10.10-x64.Microsoft.DotNet.ObjectWriter.nuspec b/src/Native/ObjWriter/.nuget/toolchain.osx.10.10-x64.Microsoft.DotNet.ObjectWriter.nuspec
deleted file mode 100644
index 7a571beaf..000000000
--- a/src/Native/ObjWriter/.nuget/toolchain.osx.10.10-x64.Microsoft.DotNet.ObjectWriter.nuspec
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0"?>
-<package >
- <metadata>
- <id>toolchain.osx.10.10-x64.Microsoft.DotNet.ObjectWriter</id>
- <version>1.0.19-prerelease-00001</version>
- <title>Microsoft .NET Object File Generator</title>
- <authors>Microsoft</authors>
- <owners>Microsoft</owners>
- <licenseUrl>http://go.microsoft.com/fwlink/?LinkId=329770</licenseUrl>
- <projectUrl>https://github.com/dotnet/corert</projectUrl>
- <iconUrl>http://go.microsoft.com/fwlink/?LinkID=288859</iconUrl>
- <requireLicenseAcceptance>true</requireLicenseAcceptance>
- <description>Provides object writer to the managed to native code-generator.</description>
- <releaseNotes>Initial release</releaseNotes>
- <copyright>Copyright &#169; Microsoft Corporation</copyright>
- </metadata>
- <files>
- <file src="../libobjwriter.dylib" target="runtimes/osx.10.10-x64/native/libobjwriter.dylib" />
- </files>
-</package>
diff --git a/src/Native/ObjWriter/.nuget/toolchain.ubuntu.14.04-x64.Microsoft.DotNet.ObjectWriter.nuspec b/src/Native/ObjWriter/.nuget/toolchain.ubuntu.14.04-x64.Microsoft.DotNet.ObjectWriter.nuspec
deleted file mode 100644
index fd9c514c6..000000000
--- a/src/Native/ObjWriter/.nuget/toolchain.ubuntu.14.04-x64.Microsoft.DotNet.ObjectWriter.nuspec
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0"?>
-<package >
- <metadata>
- <id>toolchain.ubuntu.14.04-x64.Microsoft.DotNet.ObjectWriter</id>
- <version>1.0.19-prerelease-00001</version>
- <title>Microsoft .NET Object File Generator</title>
- <authors>Microsoft</authors>
- <owners>Microsoft</owners>
- <licenseUrl>http://go.microsoft.com/fwlink/?LinkId=329770</licenseUrl>
- <projectUrl>https://github.com/dotnet/corert</projectUrl>
- <iconUrl>http://go.microsoft.com/fwlink/?LinkID=288859</iconUrl>
- <requireLicenseAcceptance>true</requireLicenseAcceptance>
- <description>Provides object writer to the managed to native code-generator.</description>
- <releaseNotes>Initial release</releaseNotes>
- <copyright>Copyright &#169; Microsoft Corporation</copyright>
- </metadata>
- <files>
- <file src="../libobjwriter.so" target="runtimes/ubuntu.14.04-x64/native/libobjwriter.so" />
- </files>
-</package>
diff --git a/src/Native/ObjWriter/.nuget/toolchain.win7-x64.Microsoft.DotNet.ObjectWriter.nuspec b/src/Native/ObjWriter/.nuget/toolchain.win7-x64.Microsoft.DotNet.ObjectWriter.nuspec
deleted file mode 100644
index a54cdc230..000000000
--- a/src/Native/ObjWriter/.nuget/toolchain.win7-x64.Microsoft.DotNet.ObjectWriter.nuspec
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0"?>
-<package >
- <metadata>
- <id>toolchain.win7-x64.Microsoft.DotNet.ObjectWriter</id>
- <version>1.0.19-prerelease-00001</version>
- <title>Microsoft .NET Object File Generator</title>
- <authors>Microsoft</authors>
- <owners>Microsoft</owners>
- <licenseUrl>http://go.microsoft.com/fwlink/?LinkId=329770</licenseUrl>
- <projectUrl>https://github.com/dotnet/corert</projectUrl>
- <iconUrl>http://go.microsoft.com/fwlink/?LinkID=288859</iconUrl>
- <requireLicenseAcceptance>true</requireLicenseAcceptance>
- <description>Provides object writer to the managed to native code-generator.</description>
- <releaseNotes>Initial release</releaseNotes>
- <copyright>Copyright &#169; Microsoft Corporation</copyright>
- </metadata>
- <files>
- <file src="..\objwriter.dll" target="runtimes\win7-x64\native\objwriter.dll" />
- </files>
-</package>
diff --git a/src/Native/ObjWriter/CMakeLists.txt b/src/Native/ObjWriter/CMakeLists.txt
index fae4ddb12..490a36701 100644
--- a/src/Native/ObjWriter/CMakeLists.txt
+++ b/src/Native/ObjWriter/CMakeLists.txt
@@ -2,7 +2,15 @@ project(objwriter)
set(CMAKE_BUILD_TYPE "${OBJWRITER_BUILD_TYPE}")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OBJWRITER_C_FLAGS}")
-set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OBJWRITER_CXX_FLAGS} -std=c++11 -fno-rtti")
+set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OBJWRITER_CXX_FLAGS}")
+
+if(WIN32)
+set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /EHsc")
+endif()
+
+if(NOT WIN32)
+set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -fno-rtti")
+endif()
message(STATUS "ObjWriter configuring with (${CMAKE_BUILD_TYPE}) build type and (${LLVM_DEFAULT_TARGET_TRIPLE}) default target triple")
@@ -29,9 +37,16 @@ endif()
add_library(objwriter
SHARED
objwriter.cpp
- typeBuilder.cpp
+ debugInfo/codeView/codeViewTypeBuilder.cpp
+ debugInfo/codeView/codeViewTypeBuilder.h
+ debugInfo/dwarf/dwarfTypeBuilder.cpp
+ debugInfo/dwarf/dwarfTypeBuilder.h
+ debugInfo/dwarf/dwarfGen.cpp
+ debugInfo/dwarf/dwarfGen.h
+ debugInfo/dwarf/dwarfAbbrev.cpp
+ debugInfo/dwarf/dwarfAbbrev.h
+ debugInfo/typeBuilder.h
objwriter.h # Visual Studio generator doesn't include necessary header files into the project automatically
- typeBuilder.h
${OBJWRITER_EXPORTS_DEF}
)
diff --git a/src/Native/ObjWriter/cordebuginfo.h b/src/Native/ObjWriter/cordebuginfo.h
index 1ed430a11..46d74c2e1 100644
--- a/src/Native/ObjWriter/cordebuginfo.h
+++ b/src/Native/ObjWriter/cordebuginfo.h
@@ -195,104 +195,114 @@ public:
VLT_INVALID,
};
+ // VLT_REG/VLT_REG_FP -- Any pointer-sized enregistered value (TYP_INT, TYP_REF, etc)
+ // eg. EAX
+ // VLT_REG_BYREF -- the specified register contains the address of the variable
+ // eg. [EAX]
+
+ struct vlReg
+ {
+ RegNum vlrReg;
+ };
+
+ // VLT_STK -- Any 32 bit value which is on the stack
+ // eg. [ESP+0x20], or [EBP-0x28]
+ // VLT_STK_BYREF -- the specified stack location contains the address of the variable
+ // eg. mov EAX, [ESP+0x20]; [EAX]
+
+ struct vlStk
+ {
+ RegNum vlsBaseReg;
+ signed vlsOffset;
+ };
+
+ // VLT_REG_REG -- TYP_LONG with both DWords enregistred
+ // eg. RBM_EAXEDX
+
+ struct vlRegReg
+ {
+ RegNum vlrrReg1;
+ RegNum vlrrReg2;
+ };
+
+ // VLT_REG_STK -- Partly enregistered TYP_LONG
+ // eg { LowerDWord=EAX UpperDWord=[ESP+0x8] }
+
+ struct vlRegStk
+ {
+ RegNum vlrsReg;
+ struct
+ {
+ RegNum vlrssBaseReg;
+ signed vlrssOffset;
+ } vlrsStk;
+ };
+
+ // VLT_STK_REG -- Partly enregistered TYP_LONG
+ // eg { LowerDWord=[ESP+0x8] UpperDWord=EAX }
+
+ struct vlStkReg
+ {
+ struct
+ {
+ RegNum vlsrsBaseReg;
+ signed vlsrsOffset;
+ } vlsrStk;
+ RegNum vlsrReg;
+ };
+
+ // VLT_STK2 -- Any 64 bit value which is on the stack,
+ // in 2 successsive DWords.
+ // eg 2 DWords at [ESP+0x10]
+
+ struct vlStk2
+ {
+ RegNum vls2BaseReg;
+ signed vls2Offset;
+ };
+
+ // VLT_FPSTK -- enregisterd TYP_DOUBLE (on the FP stack)
+ // eg. ST(3). Actually it is ST("FPstkHeigth - vpFpStk")
+
+ struct vlFPstk
+ {
+ unsigned vlfReg;
+ };
+
+ // VLT_FIXED_VA -- fixed argument of a varargs function.
+ // The argument location depends on the size of the variable
+ // arguments (...). Inspecting the VARARGS_HANDLE indicates the
+ // location of the first arg. This argument can then be accessed
+ // relative to the position of the first arg
+
+ struct vlFixedVarArg
+ {
+ unsigned vlfvOffset;
+ };
+
+ // VLT_MEMORY
+
+ struct vlMemory
+ {
+ void *rpValue; // pointer to the in-process
+ // location of the value.
+ };
+
struct VarLoc
{
VarLocType vlType;
union
{
- // VLT_REG/VLT_REG_FP -- Any pointer-sized enregistered value (TYP_INT, TYP_REF, etc)
- // eg. EAX
- // VLT_REG_BYREF -- the specified register contains the address of the variable
- // eg. [EAX]
-
- struct
- {
- RegNum vlrReg;
- } vlReg;
-
- // VLT_STK -- Any 32 bit value which is on the stack
- // eg. [ESP+0x20], or [EBP-0x28]
- // VLT_STK_BYREF -- the specified stack location contains the address of the variable
- // eg. mov EAX, [ESP+0x20]; [EAX]
-
- struct
- {
- RegNum vlsBaseReg;
- signed vlsOffset;
- } vlStk;
-
- // VLT_REG_REG -- TYP_LONG with both DWords enregistred
- // eg. RBM_EAXEDX
-
- struct
- {
- RegNum vlrrReg1;
- RegNum vlrrReg2;
- } vlRegReg;
-
- // VLT_REG_STK -- Partly enregistered TYP_LONG
- // eg { LowerDWord=EAX UpperDWord=[ESP+0x8] }
-
- struct
- {
- RegNum vlrsReg;
- struct
- {
- RegNum vlrssBaseReg;
- signed vlrssOffset;
- } vlrsStk;
- } vlRegStk;
-
- // VLT_STK_REG -- Partly enregistered TYP_LONG
- // eg { LowerDWord=[ESP+0x8] UpperDWord=EAX }
-
- struct
- {
- struct
- {
- RegNum vlsrsBaseReg;
- signed vlsrsOffset;
- } vlsrStk;
- RegNum vlsrReg;
- } vlStkReg;
-
- // VLT_STK2 -- Any 64 bit value which is on the stack,
- // in 2 successsive DWords.
- // eg 2 DWords at [ESP+0x10]
-
- struct
- {
- RegNum vls2BaseReg;
- signed vls2Offset;
- } vlStk2;
-
- // VLT_FPSTK -- enregisterd TYP_DOUBLE (on the FP stack)
- // eg. ST(3). Actually it is ST("FPstkHeigth - vpFpStk")
-
- struct
- {
- unsigned vlfReg;
- } vlFPstk;
-
- // VLT_FIXED_VA -- fixed argument of a varargs function.
- // The argument location depends on the size of the variable
- // arguments (...). Inspecting the VARARGS_HANDLE indicates the
- // location of the first arg. This argument can then be accessed
- // relative to the position of the first arg
-
- struct
- {
- unsigned vlfvOffset;
- } vlFixedVarArg;
-
- // VLT_MEMORY
-
- struct
- {
- void *rpValue; // pointer to the in-process
- // location of the value.
- } vlMemory;
+ ICorDebugInfo::vlReg vlReg;
+ ICorDebugInfo::vlStk vlStk;
+ ICorDebugInfo::vlRegReg vlRegReg;
+ ICorDebugInfo::vlRegStk vlRegStk;
+ ICorDebugInfo::vlStkReg vlStkReg;
+ ICorDebugInfo::vlStk2 vlStk2;
+ ICorDebugInfo::vlFPstk vlFPstk;
+ ICorDebugInfo::vlFixedVarArg vlFixedVarArg;
+ ICorDebugInfo::vlMemory vlMemory;
};
};
diff --git a/src/Native/ObjWriter/cvconst.h b/src/Native/ObjWriter/cvconst.h
index 5c4f2569e..92c5bb4e7 100644
--- a/src/Native/ObjWriter/cvconst.h
+++ b/src/Native/ObjWriter/cvconst.h
@@ -1,18 +1,6 @@
-///////////////////////////////////////////////////////////////////////////////
-//
-// Copyright (c) 2015 Microsoft Corporation. All rights reserved.
-//
-// This code is licensed under the MIT License (MIT).
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-//
-///////////////////////////////////////////////////////////////////////////////
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
// cvconst.h - codeview constant definitions
//-----------------------------------------------------------------
diff --git a/src/Native/ObjWriter/typeBuilder.cpp b/src/Native/ObjWriter/debugInfo/codeView/codeViewTypeBuilder.cpp
index 2b6edacc5..d3af316ca 100644
--- a/src/Native/ObjWriter/typeBuilder.cpp
+++ b/src/Native/ObjWriter/debugInfo/codeView/codeViewTypeBuilder.cpp
@@ -1,55 +1,43 @@
-//===---- typeBuilder.cpp --------------------------------*- C++ -*-===//
+//===---- codeViewTypeBuilder.cpp -------------------------------*- C++ -*-===//
//
// type builder implementation using codeview::TypeTableBuilder
//
-// Copyright (c) Microsoft. All rights reserved.
-// Licensed under the MIT license.
-// See LICENSE file in the project root for full license information.
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
//
//===----------------------------------------------------------------------===//
-#include "typeBuilder.h"
+#include "codeViewTypeBuilder.h"
#include "llvm/BinaryFormat/COFF.h"
#include <sstream>
#include <vector>
-UserDefinedTypesBuilder::UserDefinedTypesBuilder()
- : Allocator(), TypeTable(Allocator), Streamer(nullptr),
- TargetPointerSize(0)
+UserDefinedCodeViewTypesBuilder::UserDefinedCodeViewTypesBuilder()
+ : Allocator(), TypeTable(Allocator)
{
VFTableShapeRecord vfTableShape(TypeRecordKind::VFTableShape);
ClassVTableTypeIndex = TypeTable.writeKnownType(vfTableShape);
}
-void UserDefinedTypesBuilder::SetStreamer(MCObjectStreamer *Streamer) {
- assert(this->Streamer == nullptr);
- assert(Streamer != nullptr);
- this->Streamer = Streamer;
-}
-
-void UserDefinedTypesBuilder::SetTargetPointerSize(unsigned TargetPointerSize) {
- assert(this->TargetPointerSize == 0);
- assert(TargetPointerSize != 0);
- this->TargetPointerSize = TargetPointerSize;
-}
-
-void UserDefinedTypesBuilder::EmitCodeViewMagicVersion() {
+void UserDefinedCodeViewTypesBuilder::EmitCodeViewMagicVersion() {
Streamer->EmitValueToAlignment(4);
Streamer->AddComment("Debug section magic");
Streamer->EmitIntValue(COFF::DEBUG_SECTION_MAGIC, 4);
}
-ClassOptions UserDefinedTypesBuilder::GetCommonClassOptions() {
+ClassOptions UserDefinedCodeViewTypesBuilder::GetCommonClassOptions() {
return ClassOptions();
}
-void UserDefinedTypesBuilder::EmitTypeInformation(
- MCSection *COFFDebugTypesSection) {
+void UserDefinedCodeViewTypesBuilder::EmitTypeInformation(
+ MCSection *TypeSection,
+ MCSection *StrSection) {
if (TypeTable.empty())
return;
- Streamer->SwitchSection(COFFDebugTypesSection);
+ Streamer->SwitchSection(TypeSection);
EmitCodeViewMagicVersion();
TypeTable.ForEachRecord([&](TypeIndex FieldTypeIndex,
@@ -59,7 +47,7 @@ void UserDefinedTypesBuilder::EmitTypeInformation(
});
}
-unsigned UserDefinedTypesBuilder::GetEnumFieldListType(
+unsigned UserDefinedCodeViewTypesBuilder::GetEnumFieldListType(
uint64 Count, const EnumRecordTypeDescriptor *TypeRecords) {
FieldListRecordBuilder FLRB(TypeTable);
FLRB.begin();
@@ -77,7 +65,7 @@ unsigned UserDefinedTypesBuilder::GetEnumFieldListType(
return Type.getIndex();
}
-unsigned UserDefinedTypesBuilder::GetEnumTypeIndex(
+unsigned UserDefinedCodeViewTypesBuilder::GetEnumTypeIndex(
const EnumTypeDescriptor &TypeDescriptor,
const EnumRecordTypeDescriptor *TypeRecords) {
@@ -92,11 +80,11 @@ unsigned UserDefinedTypesBuilder::GetEnumTypeIndex(
ElementTypeIndex);
TypeIndex Type = TypeTable.writeKnownType(EnumRecord);
- UserDefinedTypes.push_back(std::make_pair(TypeDescriptor.Name, Type));
+ UserDefinedTypes.push_back(std::make_pair(TypeDescriptor.Name, Type.getIndex()));
return Type.getIndex();
}
-unsigned UserDefinedTypesBuilder::GetClassTypeIndex(
+unsigned UserDefinedCodeViewTypesBuilder::GetClassTypeIndex(
const ClassTypeDescriptor &ClassDescriptor) {
TypeRecordKind Kind =
ClassDescriptor.IsStruct ? TypeRecordKind::Struct : TypeRecordKind::Class;
@@ -119,10 +107,11 @@ unsigned UserDefinedTypesBuilder::GetClassTypeIndex(
return FwdDeclTI.getIndex();
}
-unsigned UserDefinedTypesBuilder::GetCompleteClassTypeIndex(
+unsigned UserDefinedCodeViewTypesBuilder::GetCompleteClassTypeIndex(
const ClassTypeDescriptor &ClassDescriptor,
const ClassFieldsTypeDescriptior &ClassFieldsDescriptor,
- const DataFieldDescriptor *FieldsDescriptors) {
+ const DataFieldDescriptor *FieldsDescriptors,
+ const StaticDataFieldDescriptor *StaticsDescriptors) {
FieldListRecordBuilder FLBR(TypeTable);
FLBR.begin();
@@ -165,12 +154,12 @@ unsigned UserDefinedTypesBuilder::GetCompleteClassTypeIndex(
ClassDescriptor.Name, StringRef());
TypeIndex ClassIndex = TypeTable.writeKnownType(CR);
- UserDefinedTypes.push_back(std::make_pair(ClassDescriptor.Name, ClassIndex));
+ UserDefinedTypes.push_back(std::make_pair(ClassDescriptor.Name, ClassIndex.getIndex()));
return ClassIndex.getIndex();
}
-unsigned UserDefinedTypesBuilder::GetArrayTypeIndex(
+unsigned UserDefinedCodeViewTypesBuilder::GetArrayTypeIndex(
const ClassTypeDescriptor &ClassDescriptor,
const ArrayTypeDescriptor &ArrayDescriptor) {
FieldListRecordBuilder FLBR(TypeTable);
@@ -229,12 +218,12 @@ unsigned UserDefinedTypesBuilder::GetArrayTypeIndex(
StringRef());
TypeIndex ClassIndex = TypeTable.writeKnownType(CR);
- UserDefinedTypes.push_back(std::make_pair(ClassDescriptor.Name, ClassIndex));
+ UserDefinedTypes.push_back(std::make_pair(ClassDescriptor.Name, ClassIndex.getIndex()));
return ClassIndex.getIndex();
}
-unsigned UserDefinedTypesBuilder::GetPointerTypeIndex(const PointerTypeDescriptor& PointerDescriptor)
+unsigned UserDefinedCodeViewTypesBuilder::GetPointerTypeIndex(const PointerTypeDescriptor& PointerDescriptor)
{
uint32_t elementType = PointerDescriptor.ElementType;
PointerKind pointerKind = PointerDescriptor.Is64Bit ? PointerKind::Near64 : PointerKind::Near32;
@@ -246,7 +235,7 @@ unsigned UserDefinedTypesBuilder::GetPointerTypeIndex(const PointerTypeDescripto
return PointerIndex.getIndex();
}
-unsigned UserDefinedTypesBuilder::GetMemberFunctionTypeIndex(const MemberFunctionTypeDescriptor& MemberDescriptor,
+unsigned UserDefinedCodeViewTypesBuilder::GetMemberFunctionTypeIndex(const MemberFunctionTypeDescriptor& MemberDescriptor,
uint32_t const *const ArgumentTypes)
{
std::vector<TypeIndex> argumentTypes;
@@ -271,14 +260,52 @@ unsigned UserDefinedTypesBuilder::GetMemberFunctionTypeIndex(const MemberFunctio
return MemberFunctionIndex.getIndex();
}
-unsigned UserDefinedTypesBuilder::GetMemberFunctionId(const MemberFunctionIdTypeDescriptor& MemberIdDescriptor)
+unsigned UserDefinedCodeViewTypesBuilder::GetMemberFunctionId(const MemberFunctionIdTypeDescriptor& MemberIdDescriptor)
{
MemberFuncIdRecord MemberFuncId(TypeIndex(MemberIdDescriptor.MemberFunction), TypeIndex(MemberIdDescriptor.ParentClass), MemberIdDescriptor.Name);
TypeIndex MemberFuncIdIndex = TypeTable.writeKnownType(MemberFuncId);
return MemberFuncIdIndex.getIndex();
}
-void UserDefinedTypesBuilder::AddBaseClass(FieldListRecordBuilder &FLBR,
+unsigned UserDefinedCodeViewTypesBuilder::GetPrimitiveTypeIndex(PrimitiveTypeFlags Type) {
+ switch (Type) {
+ case PrimitiveTypeFlags::Void:
+ return TypeIndex::Void().getIndex();
+ case PrimitiveTypeFlags::Boolean:
+ return TypeIndex(SimpleTypeKind::Boolean8).getIndex();
+ case PrimitiveTypeFlags::Char:
+ return TypeIndex::WideCharacter().getIndex();
+ case PrimitiveTypeFlags::SByte:
+ return TypeIndex(SimpleTypeKind::SByte).getIndex();
+ case PrimitiveTypeFlags::Byte:
+ return TypeIndex(SimpleTypeKind::Byte).getIndex();
+ case PrimitiveTypeFlags::Int16:
+ return TypeIndex(SimpleTypeKind::Int16).getIndex();
+ case PrimitiveTypeFlags::UInt16:
+ return TypeIndex(SimpleTypeKind::UInt16).getIndex();
+ case PrimitiveTypeFlags::Int32:
+ return TypeIndex::Int32().getIndex();
+ case PrimitiveTypeFlags::UInt32:
+ return TypeIndex::UInt32().getIndex();
+ case PrimitiveTypeFlags::Int64:
+ return TypeIndex::Int64().getIndex();
+ case PrimitiveTypeFlags::UInt64:
+ return TypeIndex::UInt64().getIndex();
+ case PrimitiveTypeFlags::Single:
+ return TypeIndex::Float32().getIndex();
+ case PrimitiveTypeFlags::Double:
+ return TypeIndex::Float64().getIndex();
+ case PrimitiveTypeFlags::IntPtr:
+ case PrimitiveTypeFlags::UIntPtr:
+ return TargetPointerSize == 4 ? TypeIndex::VoidPointer32().getIndex() :
+ TypeIndex::VoidPointer64().getIndex();
+ default:
+ assert(false && "Unexpected type");
+ return 0;
+ }
+}
+
+void UserDefinedCodeViewTypesBuilder::AddBaseClass(FieldListRecordBuilder &FLBR,
unsigned BaseClassId) {
MemberAttributes def;
TypeIndex BaseTypeIndex(BaseClassId);
@@ -286,7 +313,7 @@ void UserDefinedTypesBuilder::AddBaseClass(FieldListRecordBuilder &FLBR,
FLBR.writeMemberType(BCR);
}
-void UserDefinedTypesBuilder::AddClassVTShape(FieldListRecordBuilder &FLBR) {
+void UserDefinedCodeViewTypesBuilder::AddClassVTShape(FieldListRecordBuilder &FLBR) {
VFPtrRecord VfPtr(ClassVTableTypeIndex);
FLBR.writeMemberType(VfPtr);
}
diff --git a/src/Native/ObjWriter/debugInfo/codeView/codeViewTypeBuilder.h b/src/Native/ObjWriter/debugInfo/codeView/codeViewTypeBuilder.h
new file mode 100644
index 000000000..5534cc7d3
--- /dev/null
+++ b/src/Native/ObjWriter/debugInfo/codeView/codeViewTypeBuilder.h
@@ -0,0 +1,73 @@
+//===---- codeViewTypeBuilder.h ---------------------------------*- C++ -*-===//
+//
+// type builder is used to convert .Net types into CodeView descriptors.
+//
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+//
+//===----------------------------------------------------------------------===//
+
+#pragma once
+
+#include "debugInfo/typeBuilder.h"
+#include "llvm/DebugInfo/CodeView/TypeTableBuilder.h"
+
+#include <vector>
+
+using namespace llvm::codeview;
+
+class ArrayDimensionsDescriptor {
+public:
+ const char *GetLengthName(unsigned index);
+ const char *GetBoundsName(unsigned index);
+
+private:
+ void Resize(unsigned NewSize);
+
+ std::vector<std::string> Lengths;
+ std::vector<std::string> Bounds;
+};
+
+class UserDefinedCodeViewTypesBuilder : public UserDefinedTypesBuilder {
+public:
+ UserDefinedCodeViewTypesBuilder();
+ void EmitTypeInformation(MCSection *TypeSection, MCSection *StrSection = nullptr) override;
+
+ unsigned GetEnumTypeIndex(const EnumTypeDescriptor &TypeDescriptor,
+ const EnumRecordTypeDescriptor *TypeRecords) override;
+ unsigned GetClassTypeIndex(const ClassTypeDescriptor &ClassDescriptor) override;
+ unsigned GetCompleteClassTypeIndex(
+ const ClassTypeDescriptor &ClassDescriptor,
+ const ClassFieldsTypeDescriptior &ClassFieldsDescriptor,
+ const DataFieldDescriptor *FieldsDescriptors,
+ const StaticDataFieldDescriptor *StaticsDescriptors) override;
+
+ unsigned GetArrayTypeIndex(const ClassTypeDescriptor &ClassDescriptor,
+ const ArrayTypeDescriptor &ArrayDescriptor) override;
+
+ unsigned GetPointerTypeIndex(const PointerTypeDescriptor& PointerDescriptor) override;
+
+ unsigned GetMemberFunctionTypeIndex(const MemberFunctionTypeDescriptor& MemberDescriptor,
+ uint32_t const *const ArgumentTypes) override;
+
+ unsigned GetMemberFunctionId(const MemberFunctionIdTypeDescriptor& MemberIdDescriptor) override;
+
+ unsigned GetPrimitiveTypeIndex(PrimitiveTypeFlags Type) override;
+
+private:
+ void EmitCodeViewMagicVersion();
+ ClassOptions GetCommonClassOptions();
+
+ unsigned GetEnumFieldListType(uint64 Count,
+ const EnumRecordTypeDescriptor *TypeRecords);
+
+ void AddBaseClass(FieldListRecordBuilder &FLBR, unsigned BaseClassId);
+ void AddClassVTShape(FieldListRecordBuilder &FLBR);
+
+ BumpPtrAllocator Allocator;
+ TypeTableBuilder TypeTable;
+
+ ArrayDimensionsDescriptor ArrayDimentions;
+ TypeIndex ClassVTableTypeIndex;
+}; \ No newline at end of file
diff --git a/src/Native/ObjWriter/debugInfo/dwarf/dwarfAbbrev.cpp b/src/Native/ObjWriter/debugInfo/dwarf/dwarfAbbrev.cpp
new file mode 100644
index 000000000..23ee3fa30
--- /dev/null
+++ b/src/Native/ObjWriter/debugInfo/dwarf/dwarfAbbrev.cpp
@@ -0,0 +1,284 @@
+//===---- dwarfAbbrev.cpp ---------------------------------------*- C++ -*-===//
+//
+// dwarf abbreviations implementation
+//
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+//
+//===----------------------------------------------------------------------===//
+
+#include "dwarfAbbrev.h"
+#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCObjectFileInfo.h"
+
+namespace DwarfAbbrev {
+
+void Dump(MCObjectStreamer *Streamer, uint16_t DwarfVersion, unsigned TargetPointerSize) {
+ uint16_t DW_FORM_size;
+ switch (TargetPointerSize) {
+ case 1:
+ DW_FORM_size = dwarf::DW_FORM_data1;
+ break;
+ case 2:
+ DW_FORM_size = dwarf::DW_FORM_data2;
+ break;
+ case 4:
+ DW_FORM_size = dwarf::DW_FORM_data4;
+ break;
+ case 8:
+ DW_FORM_size = dwarf::DW_FORM_data8;
+ break;
+ default:
+ assert(false && "Unexpected TargerPointerSize");
+ return;
+ }
+
+ const uint16_t AbbrevTable[] = {
+ CompileUnit,
+ dwarf::DW_TAG_compile_unit, dwarf::DW_CHILDREN_yes,
+ dwarf::DW_AT_producer, dwarf::DW_FORM_string,
+ dwarf::DW_AT_language, dwarf::DW_FORM_data2,
+ dwarf::DW_AT_stmt_list, (DwarfVersion >= 4 ? dwarf::DW_FORM_sec_offset : dwarf::DW_FORM_data4),
+ 0, 0,
+
+ BaseType,
+ dwarf::DW_TAG_base_type, dwarf::DW_CHILDREN_no,
+ dwarf::DW_AT_name, dwarf::DW_FORM_strp,
+ dwarf::DW_AT_encoding, dwarf::DW_FORM_data1,
+ dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1,
+ 0, 0,
+
+ EnumerationType,
+ dwarf::DW_TAG_enumeration_type, dwarf::DW_CHILDREN_yes,
+ dwarf::DW_AT_name, dwarf::DW_FORM_strp,
+ dwarf::DW_AT_type, dwarf::DW_FORM_ref4,
+ dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1,
+ 0, 0,
+
+ Enumerator1,
+ dwarf::DW_TAG_enumerator, dwarf::DW_CHILDREN_no,
+ dwarf::DW_AT_name, dwarf::DW_FORM_strp,
+ dwarf::DW_AT_const_value, dwarf::DW_FORM_data1,
+ 0, 0,
+
+ Enumerator2,
+ dwarf::DW_TAG_enumerator, dwarf::DW_CHILDREN_no,
+ dwarf::DW_AT_name, dwarf::DW_FORM_strp,
+ dwarf::DW_AT_const_value, dwarf::DW_FORM_data2,
+ 0, 0,
+
+ Enumerator4,
+ dwarf::DW_TAG_enumerator, dwarf::DW_CHILDREN_no,
+ dwarf::DW_AT_name, dwarf::DW_FORM_strp,
+ dwarf::DW_AT_const_value, dwarf::DW_FORM_data4,
+ 0, 0,
+
+ Enumerator8,
+ dwarf::DW_TAG_enumerator, dwarf::DW_CHILDREN_no,
+ dwarf::DW_AT_name, dwarf::DW_FORM_strp,
+ dwarf::DW_AT_const_value, dwarf::DW_FORM_data8,
+ 0, 0,
+
+ TypeDef,
+ dwarf::DW_TAG_typedef, dwarf::DW_CHILDREN_no,
+ dwarf::DW_AT_name, dwarf::DW_FORM_strp,
+ dwarf::DW_AT_type, dwarf::DW_FORM_ref4,
+ 0, 0,
+
+ Subprogram,
+ dwarf::DW_TAG_subprogram, dwarf::DW_CHILDREN_yes,
+ dwarf::DW_AT_specification, dwarf::DW_FORM_ref4,
+ dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr,
+ dwarf::DW_AT_high_pc, DW_FORM_size,
+ dwarf::DW_AT_frame_base, dwarf::DW_FORM_exprloc,
+ dwarf::DW_AT_object_pointer, dwarf::DW_FORM_ref4,
+ 0, 0,
+
+ SubprogramStatic,
+ dwarf::DW_TAG_subprogram, dwarf::DW_CHILDREN_yes,
+ dwarf::DW_AT_specification, dwarf::DW_FORM_ref4,
+ dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr,
+ dwarf::DW_AT_high_pc, DW_FORM_size,
+ dwarf::DW_AT_frame_base, dwarf::DW_FORM_exprloc,
+ 0, 0,
+
+ SubprogramSpec,
+ dwarf::DW_TAG_subprogram, dwarf::DW_CHILDREN_yes,
+ dwarf::DW_AT_name, dwarf::DW_FORM_strp,
+ dwarf::DW_AT_linkage_name, dwarf::DW_FORM_strp,
+ dwarf::DW_AT_decl_file, dwarf::DW_FORM_data1,
+ dwarf::DW_AT_decl_line, dwarf::DW_FORM_data1,
+ dwarf::DW_AT_type, dwarf::DW_FORM_ref4,
+ dwarf::DW_AT_external, dwarf::DW_FORM_flag_present,
+ dwarf::DW_AT_declaration, dwarf::DW_FORM_flag_present,
+ dwarf::DW_AT_object_pointer, dwarf::DW_FORM_ref4,
+ 0, 0,
+
+ SubprogramStaticSpec,
+ dwarf::DW_TAG_subprogram, dwarf::DW_CHILDREN_yes,
+ dwarf::DW_AT_name, dwarf::DW_FORM_strp,
+ dwarf::DW_AT_linkage_name, dwarf::DW_FORM_strp,
+ dwarf::DW_AT_decl_file, dwarf::DW_FORM_data1,
+ dwarf::DW_AT_decl_line, dwarf::DW_FORM_data1,
+ dwarf::DW_AT_type, dwarf::DW_FORM_ref4,
+ dwarf::DW_AT_external, dwarf::DW_FORM_flag_present,
+ dwarf::DW_AT_declaration, dwarf::DW_FORM_flag_present,
+ 0, 0,
+
+ Variable,
+ dwarf::DW_TAG_variable, dwarf::DW_CHILDREN_no,
+ dwarf::DW_AT_name, dwarf::DW_FORM_strp,
+ dwarf::DW_AT_decl_file, dwarf::DW_FORM_data1,
+ dwarf::DW_AT_decl_line, dwarf::DW_FORM_data1,
+ dwarf::DW_AT_type, dwarf::DW_FORM_ref4,
+ dwarf::DW_AT_location, dwarf::DW_FORM_exprloc,
+ 0, 0,
+
+ VariableLoc,
+ dwarf::DW_TAG_variable, dwarf::DW_CHILDREN_no,
+ dwarf::DW_AT_name, dwarf::DW_FORM_strp,
+ dwarf::DW_AT_decl_file, dwarf::DW_FORM_data1,
+ dwarf::DW_AT_decl_line, dwarf::DW_FORM_data1,
+ dwarf::DW_AT_type, dwarf::DW_FORM_ref4,
+ dwarf::DW_AT_location, dwarf::DW_FORM_sec_offset,
+ 0, 0,
+
+ VariableStatic,
+ dwarf::DW_TAG_variable, dwarf::DW_CHILDREN_no,
+ dwarf::DW_AT_specification, dwarf::DW_FORM_ref4,
+ dwarf::DW_AT_location, dwarf::DW_FORM_exprloc,
+ 0, 0,
+
+ FormalParameter,
+ dwarf::DW_TAG_formal_parameter, dwarf::DW_CHILDREN_no,
+ dwarf::DW_AT_name, dwarf::DW_FORM_strp,
+ dwarf::DW_AT_decl_file, dwarf::DW_FORM_data1,
+ dwarf::DW_AT_decl_line, dwarf::DW_FORM_data1,
+ dwarf::DW_AT_type, dwarf::DW_FORM_ref4,
+ dwarf::DW_AT_location, dwarf::DW_FORM_exprloc,
+ 0, 0,
+
+ FormalParameterThis,
+ dwarf::DW_TAG_formal_parameter, dwarf::DW_CHILDREN_no,
+ dwarf::DW_AT_name, dwarf::DW_FORM_strp,
+ dwarf::DW_AT_decl_file, dwarf::DW_FORM_data1,
+ dwarf::DW_AT_decl_line, dwarf::DW_FORM_data1,
+ dwarf::DW_AT_type, dwarf::DW_FORM_ref4,
+ dwarf::DW_AT_location, dwarf::DW_FORM_exprloc,
+ dwarf::DW_AT_artificial, dwarf::DW_FORM_flag_present,
+ 0, 0,
+
+ FormalParameterLoc,
+ dwarf::DW_TAG_formal_parameter, dwarf::DW_CHILDREN_no,
+ dwarf::DW_AT_name, dwarf::DW_FORM_strp,
+ dwarf::DW_AT_decl_file, dwarf::DW_FORM_data1,
+ dwarf::DW_AT_decl_line, dwarf::DW_FORM_data1,
+ dwarf::DW_AT_type, dwarf::DW_FORM_ref4,
+ dwarf::DW_AT_location, dwarf::DW_FORM_sec_offset,
+ 0, 0,
+
+ FormalParameterThisLoc,
+ dwarf::DW_TAG_formal_parameter, dwarf::DW_CHILDREN_no,
+ dwarf::DW_AT_name, dwarf::DW_FORM_strp,
+ dwarf::DW_AT_decl_file, dwarf::DW_FORM_data1,
+ dwarf::DW_AT_decl_line, dwarf::DW_FORM_data1,
+ dwarf::DW_AT_type, dwarf::DW_FORM_ref4,
+ dwarf::DW_AT_location, dwarf::DW_FORM_sec_offset,
+ dwarf::DW_AT_artificial, dwarf::DW_FORM_flag_present,
+ 0, 0,
+
+ FormalParameterSpec,
+ dwarf::DW_TAG_formal_parameter, dwarf::DW_CHILDREN_no,
+ dwarf::DW_AT_type, dwarf::DW_FORM_ref4,
+ 0, 0,
+
+ FormalParameterThisSpec,
+ dwarf::DW_TAG_formal_parameter, dwarf::DW_CHILDREN_no,
+ dwarf::DW_AT_type, dwarf::DW_FORM_ref4,
+ dwarf::DW_AT_artificial, dwarf::DW_FORM_flag_present,
+ 0, 0,
+
+ ClassType,
+ dwarf::DW_TAG_class_type, dwarf::DW_CHILDREN_yes,
+ dwarf::DW_AT_name, dwarf::DW_FORM_strp,
+ dwarf::DW_AT_byte_size, dwarf::DW_FORM_data4,
+ 0, 0,
+
+ ClassTypeDecl,
+ dwarf::DW_TAG_class_type, dwarf::DW_CHILDREN_no,
+ dwarf::DW_AT_name, dwarf::DW_FORM_strp,
+ dwarf::DW_AT_declaration, dwarf::DW_FORM_flag_present,
+ 0, 0,
+
+ ClassMember,
+ dwarf::DW_TAG_member, dwarf::DW_CHILDREN_no,
+ dwarf::DW_AT_name, dwarf::DW_FORM_strp,
+ dwarf::DW_AT_type, dwarf::DW_FORM_ref4,
+ dwarf::DW_AT_data_member_location, dwarf::DW_FORM_data4,
+ 0, 0,
+
+ ClassMemberStatic,
+ dwarf::DW_TAG_member, dwarf::DW_CHILDREN_no,
+ dwarf::DW_AT_name, dwarf::DW_FORM_strp,
+ dwarf::DW_AT_type, dwarf::DW_FORM_ref4,
+ dwarf::DW_AT_external, dwarf::DW_FORM_flag_present,
+ dwarf::DW_AT_declaration, dwarf::DW_FORM_flag_present,
+ 0, 0,
+
+ PointerType,
+ dwarf::DW_TAG_pointer_type, dwarf::DW_CHILDREN_no,
+ dwarf::DW_AT_type, dwarf::DW_FORM_ref4,
+ dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1,
+ 0, 0,
+
+ ReferenceType,
+ dwarf::DW_TAG_reference_type, dwarf::DW_CHILDREN_no,
+ dwarf::DW_AT_type, dwarf::DW_FORM_ref4,
+ dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1,
+ 0, 0,
+
+ ArrayType,
+ dwarf::DW_TAG_array_type, dwarf::DW_CHILDREN_yes,
+ dwarf::DW_AT_type, dwarf::DW_FORM_ref4,
+ 0, 0,
+
+ SubrangeType,
+ dwarf::DW_TAG_subrange_type, dwarf::DW_CHILDREN_no,
+ dwarf::DW_AT_upper_bound, dwarf::DW_FORM_udata,
+ 0, 0,
+
+ ClassInheritance,
+ dwarf::DW_TAG_inheritance, dwarf::DW_CHILDREN_no,
+ dwarf::DW_AT_type, dwarf::DW_FORM_ref4,
+ dwarf::DW_AT_data_member_location, dwarf::DW_FORM_data1,
+ 0, 0,
+
+ LexicalBlock,
+ dwarf::DW_TAG_lexical_block, dwarf::DW_CHILDREN_yes,
+ dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr,
+ dwarf::DW_AT_high_pc, DW_FORM_size,
+ 0, 0,
+
+ TryBlock,
+ dwarf::DW_TAG_try_block, dwarf::DW_CHILDREN_no,
+ dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr,
+ dwarf::DW_AT_high_pc, DW_FORM_size,
+ 0, 0,
+
+ CatchBlock,
+ dwarf::DW_TAG_catch_block, dwarf::DW_CHILDREN_no,
+ dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr,
+ dwarf::DW_AT_high_pc, DW_FORM_size,
+ 0, 0
+ };
+
+ MCContext &context = Streamer->getContext();
+ Streamer->SwitchSection(context.getObjectFileInfo()->getDwarfAbbrevSection());
+
+ for (uint16_t e : AbbrevTable) {
+ Streamer->EmitULEB128IntValue(e);
+ }
+}
+
+} \ No newline at end of file
diff --git a/src/Native/ObjWriter/debugInfo/dwarf/dwarfAbbrev.h b/src/Native/ObjWriter/debugInfo/dwarf/dwarfAbbrev.h
new file mode 100644
index 000000000..82589c027
--- /dev/null
+++ b/src/Native/ObjWriter/debugInfo/dwarf/dwarfAbbrev.h
@@ -0,0 +1,59 @@
+//===---- dwarfAbbrev.h -----------------------------------------*- C++ -*-===//
+//
+// dwarf abbreviations
+//
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+//
+//===----------------------------------------------------------------------===//
+
+#pragma once
+
+#include "llvm/BinaryFormat/Dwarf.h"
+#include "llvm/MC/MCObjectStreamer.h"
+
+using namespace llvm;
+
+namespace DwarfAbbrev {
+
+enum DwarfAbbrev : uint16_t
+{
+ CompileUnit = 0x1,
+ BaseType,
+ EnumerationType,
+ Enumerator1,
+ Enumerator2,
+ Enumerator4,
+ Enumerator8,
+ TypeDef,
+ Subprogram,
+ SubprogramStatic,
+ SubprogramSpec,
+ SubprogramStaticSpec,
+ Variable,
+ VariableLoc,
+ VariableStatic,
+ FormalParameter,
+ FormalParameterThis,
+ FormalParameterLoc,
+ FormalParameterThisLoc,
+ FormalParameterSpec,
+ FormalParameterThisSpec,
+ ClassType,
+ ClassTypeDecl,
+ ClassMember,
+ ClassMemberStatic,
+ PointerType,
+ ReferenceType,
+ ArrayType,
+ SubrangeType,
+ ClassInheritance,
+ LexicalBlock,
+ TryBlock,
+ CatchBlock
+};
+
+void Dump(MCObjectStreamer *Streamer, uint16_t DwarfVersion, unsigned TargetPointerSize);
+
+}
diff --git a/src/Native/ObjWriter/debugInfo/dwarf/dwarfGen.cpp b/src/Native/ObjWriter/debugInfo/dwarf/dwarfGen.cpp
new file mode 100644
index 000000000..518608673
--- /dev/null
+++ b/src/Native/ObjWriter/debugInfo/dwarf/dwarfGen.cpp
@@ -0,0 +1,1066 @@
+//===---- dwarfGen.cpp ------------------------------------------*- C++ -*-===//
+//
+// dwarf generator implementation
+//
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+//
+//===----------------------------------------------------------------------===//
+
+#include "dwarfGen.h"
+#include "dwarfAbbrev.h"
+
+#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCAsmInfo.h"
+#include "llvm/MC/MCObjectFileInfo.h"
+#include "llvm/Support/LEB128.h"
+
+#ifdef FEATURE_LANGID_CS
+#define DW_LANG_MICROSOFT_CSHARP 0x9e57
+#endif
+
+// Keep sync with ICorDebugInfo::RegNum (cordebuginfo.h)
+
+enum class RegNumX86
+{
+ REGNUM_EAX,
+ REGNUM_ECX,
+ REGNUM_EDX,
+ REGNUM_EBX,
+ REGNUM_ESP,
+ REGNUM_EBP,
+ REGNUM_ESI,
+ REGNUM_EDI,
+ REGNUM_COUNT,
+ REGNUM_FP = REGNUM_EBP,
+ REGNUM_SP = REGNUM_ESP
+};
+
+enum class RegNumArm
+{
+ REGNUM_R0,
+ REGNUM_R1,
+ REGNUM_R2,
+ REGNUM_R3,
+ REGNUM_R4,
+ REGNUM_R5,
+ REGNUM_R6,
+ REGNUM_R7,
+ REGNUM_R8,
+ REGNUM_R9,
+ REGNUM_R10,
+ REGNUM_R11,
+ REGNUM_R12,
+ REGNUM_SP,
+ REGNUM_LR,
+ REGNUM_PC,
+ REGNUM_COUNT,
+ REGNUM_FP = REGNUM_R7
+};
+
+enum class RegNumArm64
+{
+ REGNUM_X0,
+ REGNUM_X1,
+ REGNUM_X2,
+ REGNUM_X3,
+ REGNUM_X4,
+ REGNUM_X5,
+ REGNUM_X6,
+ REGNUM_X7,
+ REGNUM_X8,
+ REGNUM_X9,
+ REGNUM_X10,
+ REGNUM_X11,
+ REGNUM_X12,
+ REGNUM_X13,
+ REGNUM_X14,
+ REGNUM_X15,
+ REGNUM_X16,
+ REGNUM_X17,
+ REGNUM_X18,
+ REGNUM_X19,
+ REGNUM_X20,
+ REGNUM_X21,
+ REGNUM_X22,
+ REGNUM_X23,
+ REGNUM_X24,
+ REGNUM_X25,
+ REGNUM_X26,
+ REGNUM_X27,
+ REGNUM_X28,
+ REGNUM_FP,
+ REGNUM_LR,
+ REGNUM_SP,
+ REGNUM_PC,
+ REGNUM_COUNT
+};
+
+enum class RegNumAmd64
+{
+ REGNUM_RAX,
+ REGNUM_RCX,
+ REGNUM_RDX,
+ REGNUM_RBX,
+ REGNUM_RSP,
+ REGNUM_RBP,
+ REGNUM_RSI,
+ REGNUM_RDI,
+ REGNUM_R8,
+ REGNUM_R9,
+ REGNUM_R10,
+ REGNUM_R11,
+ REGNUM_R12,
+ REGNUM_R13,
+ REGNUM_R14,
+ REGNUM_R15,
+ REGNUM_COUNT,
+ REGNUM_SP = REGNUM_RSP,
+ REGNUM_FP = REGNUM_RBP
+};
+
+// Helper routines from lib/MC/MCDwarf.cpp
+static const MCExpr *forceExpAbs(MCStreamer &OS, const MCExpr* Expr) {
+ MCContext &Context = OS.getContext();
+ assert(!isa<MCSymbolRefExpr>(Expr));
+ if (Context.getAsmInfo()->hasAggressiveSymbolFolding())
+ return Expr;
+
+ MCSymbol *ABS = Context.createTempSymbol();
+ OS.EmitAssignment(ABS, Expr);
+ return MCSymbolRefExpr::create(ABS, Context);
+}
+
+static void emitAbsValue(MCStreamer &OS, const MCExpr *Value, unsigned Size) {
+ const MCExpr *ABS = forceExpAbs(OS, Value);
+ OS.EmitValue(ABS, Size);
+}
+
+static const MCExpr *MakeStartMinusEndExpr(const MCStreamer &MCOS,
+ const MCSymbol &Start,
+ const MCSymbol &End,
+ int IntVal) {
+ MCSymbolRefExpr::VariantKind Variant = MCSymbolRefExpr::VK_None;
+ const MCExpr *Res =
+ MCSymbolRefExpr::create(&End, Variant, MCOS.getContext());
+ const MCExpr *RHS =
+ MCSymbolRefExpr::create(&Start, Variant, MCOS.getContext());
+ const MCExpr *Res1 =
+ MCBinaryExpr::create(MCBinaryExpr::Sub, Res, RHS, MCOS.getContext());
+ const MCExpr *Res2 =
+ MCConstantExpr::create(IntVal, MCOS.getContext());
+ const MCExpr *Res3 =
+ MCBinaryExpr::create(MCBinaryExpr::Sub, Res1, Res2, MCOS.getContext());
+ return Res3;
+}
+
+static int GetDwarfRegNum(Triple::ArchType ArchType, int RegNum) {
+ switch (ArchType) {
+ case Triple::x86:
+ switch (static_cast<RegNumX86>(RegNum)) {
+ case RegNumX86::REGNUM_EAX: return 0;
+ case RegNumX86::REGNUM_ECX: return 1;
+ case RegNumX86::REGNUM_EDX: return 2;
+ case RegNumX86::REGNUM_EBX: return 3;
+ case RegNumX86::REGNUM_ESP: return 4;
+ case RegNumX86::REGNUM_EBP: return 5;
+ case RegNumX86::REGNUM_ESI: return 6;
+ case RegNumX86::REGNUM_EDI: return 7;
+ // fp registers
+ default:
+ return RegNum - static_cast<int>(RegNumX86::REGNUM_COUNT) + 32;
+ }
+ case Triple::arm: // fall through
+ case Triple::armeb: // fall through
+ case Triple::thumb: // fall through
+ case Triple::thumbeb:
+ switch (static_cast<RegNumArm>(RegNum)) {
+ case RegNumArm::REGNUM_R0: return 0;
+ case RegNumArm::REGNUM_R1: return 1;
+ case RegNumArm::REGNUM_R2: return 2;
+ case RegNumArm::REGNUM_R3: return 3;
+ case RegNumArm::REGNUM_R4: return 4;
+ case RegNumArm::REGNUM_R5: return 5;
+ case RegNumArm::REGNUM_R6: return 6;
+ case RegNumArm::REGNUM_R7: return 7;
+ case RegNumArm::REGNUM_R8: return 8;
+ case RegNumArm::REGNUM_R9: return 9;
+ case RegNumArm::REGNUM_R10: return 10;
+ case RegNumArm::REGNUM_R11: return 11;
+ case RegNumArm::REGNUM_R12: return 12;
+ case RegNumArm::REGNUM_SP: return 13;
+ case RegNumArm::REGNUM_LR: return 14;
+ case RegNumArm::REGNUM_PC: return 15;
+ // fp registers
+ default:
+ return RegNum - static_cast<int>(RegNumArm::REGNUM_COUNT) + 64;
+ }
+ case Triple::aarch64: // fall through
+ case Triple::aarch64_be:
+ switch (static_cast<RegNumArm64>(RegNum)) {
+ case RegNumArm64::REGNUM_X0: return 0;
+ case RegNumArm64::REGNUM_X1: return 1;
+ case RegNumArm64::REGNUM_X2: return 2;
+ case RegNumArm64::REGNUM_X3: return 3;
+ case RegNumArm64::REGNUM_X4: return 4;
+ case RegNumArm64::REGNUM_X5: return 5;
+ case RegNumArm64::REGNUM_X6: return 6;
+ case RegNumArm64::REGNUM_X7: return 7;
+ case RegNumArm64::REGNUM_X8: return 8;
+ case RegNumArm64::REGNUM_X9: return 9;
+ case RegNumArm64::REGNUM_X10: return 10;
+ case RegNumArm64::REGNUM_X11: return 11;
+ case RegNumArm64::REGNUM_X12: return 12;
+ case RegNumArm64::REGNUM_X13: return 13;
+ case RegNumArm64::REGNUM_X14: return 14;
+ case RegNumArm64::REGNUM_X15: return 15;
+ case RegNumArm64::REGNUM_X16: return 16;
+ case RegNumArm64::REGNUM_X17: return 17;
+ case RegNumArm64::REGNUM_X18: return 18;
+ case RegNumArm64::REGNUM_X19: return 19;
+ case RegNumArm64::REGNUM_X20: return 20;
+ case RegNumArm64::REGNUM_X21: return 21;
+ case RegNumArm64::REGNUM_X22: return 22;
+ case RegNumArm64::REGNUM_X23: return 23;
+ case RegNumArm64::REGNUM_X24: return 24;
+ case RegNumArm64::REGNUM_X25: return 25;
+ case RegNumArm64::REGNUM_X26: return 26;
+ case RegNumArm64::REGNUM_X27: return 27;
+ case RegNumArm64::REGNUM_X28: return 28;
+ case RegNumArm64::REGNUM_FP: return 29;
+ case RegNumArm64::REGNUM_LR: return 30;
+ case RegNumArm64::REGNUM_SP: return 31;
+ case RegNumArm64::REGNUM_PC: return 32;
+ // fp registers
+ default:
+ return RegNum - static_cast<int>(RegNumArm64::REGNUM_COUNT) + 64;
+ }
+ case Triple::x86_64:
+ switch (static_cast<RegNumAmd64>(RegNum)) {
+ case RegNumAmd64::REGNUM_RAX: return 0;
+ case RegNumAmd64::REGNUM_RDX: return 1;
+ case RegNumAmd64::REGNUM_RCX: return 2;
+ case RegNumAmd64::REGNUM_RBX: return 3;
+ case RegNumAmd64::REGNUM_RSI: return 4;
+ case RegNumAmd64::REGNUM_RDI: return 5;
+ case RegNumAmd64::REGNUM_RBP: return 6;
+ case RegNumAmd64::REGNUM_RSP: return 7;
+ case RegNumAmd64::REGNUM_R8: return 8;
+ case RegNumAmd64::REGNUM_R9: return 9;
+ case RegNumAmd64::REGNUM_R10: return 10;
+ case RegNumAmd64::REGNUM_R11: return 11;
+ case RegNumAmd64::REGNUM_R12: return 12;
+ case RegNumAmd64::REGNUM_R13: return 13;
+ case RegNumAmd64::REGNUM_R14: return 14;
+ case RegNumAmd64::REGNUM_R15: return 15;
+ // fp registers
+ default:
+ return RegNum - static_cast<int>(RegNumAmd64::REGNUM_COUNT) + 17;
+ }
+ default:
+ assert(false && "Unexpected architecture");
+ return 0;
+ }
+}
+
+static int GetDwarfFpRegNum(Triple::ArchType ArchType)
+{
+ switch (ArchType) {
+ case Triple::x86:
+ return GetDwarfRegNum(ArchType, static_cast<int>(RegNumX86::REGNUM_FP));
+ case Triple::arm: // fall through
+ case Triple::armeb: // fall through
+ case Triple::thumb: // fall through
+ case Triple::thumbeb:
+ return GetDwarfRegNum(ArchType, static_cast<int>(RegNumArm::REGNUM_FP));
+ case Triple::aarch64: // fall through
+ case Triple::aarch64_be:
+ return GetDwarfRegNum(ArchType, static_cast<int>(RegNumArm64::REGNUM_FP));
+ case Triple::x86_64:
+ return GetDwarfRegNum(ArchType, static_cast<int>(RegNumAmd64::REGNUM_FP));
+ default:
+ assert(false && "Unexpected architecture");
+ return 0;
+ }
+}
+
+static void EmitVarLocation(MCObjectStreamer *Streamer,
+ const ICorDebugInfo::NativeVarInfo &VarInfo,
+ bool IsLocList = false) {
+ MCContext &context = Streamer->getContext();
+ unsigned TargetPointerSize = context.getAsmInfo()->getCodePointerSize();
+ Triple::ArchType ArchType = context.getObjectFileInfo()->getTargetTriple().getArch();
+
+ int DwarfRegNum;
+ int DwarfRegNum2;
+ int DwarfBaseRegNum;
+ unsigned Len;
+
+ bool IsByRef = false;
+ bool IsStk2 = false;
+ bool IsRegStk = false;
+
+ switch (VarInfo.loc.vlType) {
+ case ICorDebugInfo::VLT_REG_BYREF: // fall through
+ IsByRef = true;
+ case ICorDebugInfo::VLT_REG_FP: // fall through
+ case ICorDebugInfo::VLT_REG: {
+ DwarfRegNum = GetDwarfRegNum(ArchType, VarInfo.loc.vlReg.vlrReg);
+ if (IsByRef) {
+ Len = 2;
+ if (IsLocList) {
+ Streamer->EmitIntValue(Len, 2);
+ } else {
+ Streamer->EmitULEB128IntValue(Len);
+ }
+ Streamer->EmitIntValue(DwarfRegNum + dwarf::DW_OP_breg0, 1);
+ Streamer->EmitSLEB128IntValue(0);
+ } else {
+ Len = 1;
+ if (IsLocList) {
+ Streamer->EmitIntValue(Len, 2);
+ } else {
+ Streamer->EmitULEB128IntValue(Len);
+ }
+ Streamer->EmitIntValue(DwarfRegNum + dwarf::DW_OP_reg0, 1);
+ }
+
+ break;
+ }
+ case ICorDebugInfo::VLT_STK_BYREF: // fall through
+ IsByRef = true;
+ case ICorDebugInfo::VLT_STK2:
+ IsStk2 = true;
+ case ICorDebugInfo::VLT_STK: {
+ DwarfBaseRegNum = GetDwarfRegNum(ArchType, IsStk2 ? VarInfo.loc.vlStk2.vls2BaseReg :
+ VarInfo.loc.vlStk.vlsBaseReg);
+
+ SmallString<128> Tmp;
+ raw_svector_ostream OSE(Tmp);
+ encodeSLEB128(IsStk2 ? VarInfo.loc.vlStk2.vls2Offset :
+ VarInfo.loc.vlStk.vlsOffset, OSE);
+ StringRef OffsetRepr = OSE.str();
+
+ if (IsByRef) {
+ Len = OffsetRepr.size() + 2;
+ if (IsLocList) {
+ Streamer->EmitIntValue(Len, 2);
+ } else {
+ Streamer->EmitULEB128IntValue(Len);
+ }
+ Streamer->EmitIntValue(DwarfBaseRegNum + dwarf::DW_OP_breg0, 1);
+ Streamer->EmitBytes(OffsetRepr);
+ Streamer->EmitIntValue(dwarf::DW_OP_deref, 1);
+ } else {
+ Len = OffsetRepr.size() + 1;
+ if (IsLocList) {
+ Streamer->EmitIntValue(Len, 2);
+ } else {
+ Streamer->EmitULEB128IntValue(Len);
+ }
+ Streamer->EmitIntValue(DwarfBaseRegNum + dwarf::DW_OP_breg0, 1);
+ Streamer->EmitBytes(OffsetRepr);
+ }
+
+ break;
+ }
+ case ICorDebugInfo::VLT_REG_REG: {
+ DwarfRegNum = GetDwarfRegNum(ArchType, VarInfo.loc.vlRegReg.vlrrReg1);
+ DwarfRegNum2 = GetDwarfRegNum(ArchType, VarInfo.loc.vlRegReg.vlrrReg2);
+
+ Len = (1 /* DW_OP_reg */ + 1 /* DW_OP_piece */ + 1 /* Reg size */) * 2 + 1;
+ if (IsLocList) {
+ Streamer->EmitIntValue(Len, 2);
+ } else {
+ Streamer->EmitULEB128IntValue(Len + 1);
+ }
+
+ Streamer->EmitIntValue(DwarfRegNum2 + dwarf::DW_OP_reg0, 1);
+ Streamer->EmitIntValue(dwarf::DW_OP_piece, 1);
+ Streamer->EmitULEB128IntValue(TargetPointerSize);
+
+ Streamer->EmitIntValue(DwarfRegNum + dwarf::DW_OP_reg0, 1);
+ Streamer->EmitIntValue(dwarf::DW_OP_piece, 1);
+ Streamer->EmitULEB128IntValue(TargetPointerSize);
+
+ break;
+ }
+ case ICorDebugInfo::VLT_REG_STK: // fall through
+ IsRegStk = true;
+ case ICorDebugInfo::VLT_STK_REG: {
+ DwarfRegNum = GetDwarfRegNum(ArchType, IsRegStk ? VarInfo.loc.vlRegStk.vlrsReg :
+ VarInfo.loc.vlStkReg.vlsrReg);
+ DwarfBaseRegNum = GetDwarfRegNum(ArchType, IsRegStk ? VarInfo.loc.vlRegStk.vlrsStk.vlrssBaseReg :
+ VarInfo.loc.vlStkReg.vlsrStk.vlsrsBaseReg);
+
+ SmallString<128> Tmp;
+ raw_svector_ostream OSE(Tmp);
+ encodeSLEB128(IsRegStk ? VarInfo.loc.vlRegStk.vlrsStk.vlrssOffset :
+ VarInfo.loc.vlStkReg.vlsrStk.vlsrsOffset, OSE);
+ StringRef OffsetRepr = OSE.str();
+
+ Len = (1 /* DW_OP_reg */ + 1 /* DW_OP_piece */ + 1 /* Reg size */) +
+ (1 /*DW_OP_breg */ + OffsetRepr.size() + 1 /* DW_OP_piece */ + 1 /* Reg size */) + 1;
+
+ if (IsLocList) {
+ Streamer->EmitIntValue(Len, 2);
+ } else {
+ Streamer->EmitULEB128IntValue(Len + 1);
+ }
+
+ if (IsRegStk) {
+ Streamer->EmitIntValue(DwarfRegNum + dwarf::DW_OP_reg0, 1);
+ Streamer->EmitIntValue(dwarf::DW_OP_piece, 1);
+ Streamer->EmitULEB128IntValue(TargetPointerSize);
+
+ Streamer->EmitIntValue(DwarfBaseRegNum + dwarf::DW_OP_breg0, 1);
+ Streamer->EmitBytes(OffsetRepr);
+ Streamer->EmitIntValue(dwarf::DW_OP_piece, 1);
+ Streamer->EmitULEB128IntValue(TargetPointerSize);
+ } else {
+ Streamer->EmitIntValue(DwarfBaseRegNum + dwarf::DW_OP_breg0, 1);
+ Streamer->EmitBytes(OffsetRepr);
+ Streamer->EmitIntValue(dwarf::DW_OP_piece, 1);
+ Streamer->EmitULEB128IntValue(TargetPointerSize);
+
+ Streamer->EmitIntValue(DwarfRegNum + dwarf::DW_OP_reg0, 1);
+ Streamer->EmitIntValue(dwarf::DW_OP_piece, 1);
+ Streamer->EmitULEB128IntValue(TargetPointerSize);
+ }
+
+ break;
+ }
+ case ICorDebugInfo::VLT_FPSTK:
+ case ICorDebugInfo::VLT_FIXED_VA:
+ assert(false && "Unsupported varloc type!");
+ default:
+ assert(false && "Unknown varloc type!");
+ if (IsLocList) {
+ Streamer->EmitIntValue(0, 2);
+ } else {
+ Streamer->EmitULEB128IntValue(0);
+ }
+ }
+}
+
+// Lexical scope
+
+class LexicalScope
+{
+public:
+ LexicalScope(uint64_t Start, uint64_t End, bool IsFuncScope = false) :
+ Start(Start),
+ End(End),
+ IsFuncScope(IsFuncScope) {}
+
+ LexicalScope(VarInfo *Info) :
+ Start(Info->GetStartOffset()),
+ End(Info->GetEndOffset()),
+ IsFuncScope(false) { Vars.push_back(Info); }
+
+ bool IsContains(const VarInfo *Info) const {
+ return Start <= Info->GetStartOffset() && End >= Info->GetEndOffset();
+ }
+
+ void AddVar(VarInfo *Info);
+
+ void Dump(UserDefinedDwarfTypesBuilder *TypeBuilder, MCObjectStreamer *Streamer,
+ MCSection *TypeSection, MCSection *StrSection, const MCExpr *SymExpr);
+
+private:
+ uint64_t Start;
+ uint64_t End;
+ bool IsFuncScope;
+ std::vector<VarInfo*> Vars;
+ std::vector<LexicalScope> InnerScopes;
+};
+
+void LexicalScope::AddVar(VarInfo *Info) {
+ if (Info->IsParam() && IsFuncScope) {
+ Vars.push_back(Info);
+ return;
+ }
+
+ if (!IsContains(Info))
+ return;
+
+ uint64_t VarStart = Info->GetStartOffset();
+ uint64_t VarEnd = Info->GetEndOffset();
+
+ // Var belongs to inner scope
+ if (VarStart != Start || VarEnd != End) {
+ // Try to add variable to one the inner scopes
+ for (auto &Scope : InnerScopes) {
+ if (Scope.IsContains(Info)) {
+ Scope.AddVar(Info);
+ return;
+ }
+ }
+ // We need to create new inner scope for this var
+ InnerScopes.emplace_back(Info);
+ } else {
+ Vars.push_back(Info);
+ }
+}
+
+void LexicalScope::Dump(UserDefinedDwarfTypesBuilder *TypeBuilder, MCObjectStreamer *Streamer,
+ MCSection *TypeSection, MCSection *StrSection, const MCExpr *SymExpr) {
+ Streamer->SwitchSection(TypeSection);
+
+ if (!IsFuncScope)
+ {
+ // Dump lexical block DIE
+ MCContext &context = Streamer->getContext();
+ unsigned TargetPointerSize = context.getAsmInfo()->getCodePointerSize();
+
+ // Abbrev Number
+ Streamer->EmitULEB128IntValue(DwarfAbbrev::LexicalBlock);
+
+ // DW_AT_low_pc
+ const MCExpr *StartExpr = MCConstantExpr::create(Start, context);
+ const MCExpr *LowPcExpr = MCBinaryExpr::create(MCBinaryExpr::Add, SymExpr,
+ StartExpr, context);
+ Streamer->EmitValue(LowPcExpr, TargetPointerSize);
+
+ // DW_AT_high_pc
+ Streamer->EmitIntValue(End - Start, TargetPointerSize);
+ }
+
+ for (auto *Var : Vars) {
+ Var->Dump(TypeBuilder, Streamer, TypeSection, StrSection);
+ }
+
+ for (auto &Scope : InnerScopes) {
+ Scope.Dump(TypeBuilder, Streamer, TypeSection, StrSection, SymExpr);
+ }
+
+ if (!IsFuncScope) {
+ // Terminate block
+ Streamer->EmitIntValue(0, 1);
+ }
+}
+
+// StaticVarInfo
+
+class StaticVarInfo : public DwarfInfo
+{
+public:
+ StaticVarInfo(const DwarfStaticDataField *StaticField) : StaticField(StaticField) {}
+
+ void Dump(UserDefinedDwarfTypesBuilder *TypeBuilder, MCObjectStreamer *Streamer,
+ MCSection *TypeSection, MCSection *StrSection) override;
+
+protected:
+ void DumpStrings(MCObjectStreamer *Streamer) override {};
+ void DumpTypeInfo(MCObjectStreamer *Streamer, UserDefinedDwarfTypesBuilder *TypeBuilder) override;
+
+private:
+ const DwarfStaticDataField *StaticField;
+
+ void EmitLocation(MCObjectStreamer *Streamer);
+};
+
+void StaticVarInfo::Dump(UserDefinedDwarfTypesBuilder *TypeBuilder, MCObjectStreamer *Streamer,
+ MCSection *TypeSection, MCSection *StrSection) {
+ MCContext &context = Streamer->getContext();
+ MCSymbol *Sym = context.getOrCreateSymbol(Twine(StaticField->GetStaticDataName()));
+ if (Sym->isUndefined())
+ return;
+
+ DwarfInfo::Dump(TypeBuilder, Streamer, TypeSection, StrSection);
+}
+
+void StaticVarInfo::DumpTypeInfo(MCObjectStreamer *Streamer, UserDefinedDwarfTypesBuilder *TypeBuilder) {
+ // Abbrev Number
+ Streamer->EmitULEB128IntValue(DwarfAbbrev::VariableStatic);
+
+ // DW_AT_specification
+ EmitInfoOffset(Streamer, StaticField, 4);
+
+ // DW_AT_location
+ EmitLocation(Streamer);
+}
+
+void StaticVarInfo::EmitLocation(MCObjectStreamer *Streamer) {
+ MCContext &context = Streamer->getContext();
+ unsigned TargetPointerSize = context.getAsmInfo()->getCodePointerSize();
+
+ MCSymbol *Sym = context.getOrCreateSymbol(Twine(StaticField->GetStaticDataName()));
+
+ SmallString<128> Tmp;
+ raw_svector_ostream OSE(Tmp);
+ encodeULEB128(StaticField->GetStaticOffset(), OSE);
+ StringRef OffsetRepr = OSE.str();
+
+ unsigned Len = 1 /* DW_OP_addr */ + TargetPointerSize;
+
+ // Need double deref
+ if (StaticField->IsStaticDataInObject()) {
+ Len += (1 /* DW_OP_deref */) * 2;
+ }
+
+ if (StaticField->GetStaticOffset() != 0) {
+ Len += 1 /* DW_OP_plus_uconst */ + OffsetRepr.size();
+ }
+
+ Streamer->EmitULEB128IntValue(Len);
+ Streamer->EmitIntValue(dwarf::DW_OP_addr, 1);
+ Streamer->EmitSymbolValue(Sym, TargetPointerSize);
+
+ if (StaticField->IsStaticDataInObject()) {
+ Streamer->EmitIntValue(dwarf::DW_OP_deref, 1);
+ Streamer->EmitIntValue(dwarf::DW_OP_deref, 1);
+ }
+
+ if (StaticField->GetStaticOffset() != 0) {
+ Streamer->EmitIntValue(dwarf::DW_OP_plus_uconst, 1);
+ Streamer->EmitBytes(OffsetRepr);
+ }
+}
+
+// VarInfo
+
+VarInfo::VarInfo(const DebugVarInfo &Info, bool IsThis) :
+ DebugInfo(Info),
+ LocSymbol(nullptr),
+ IsThis(IsThis) {
+ if (!Info.IsParam) {
+ assert(!Info.Ranges.empty());
+ StartOffset = Info.Ranges.front().startOffset;
+ EndOffset = Info.Ranges.back().endOffset;
+ } else {
+ // Params belong to func scope
+ StartOffset = 0xFFFFFFFF;
+ EndOffset = 0xFFFFFFFF;
+ }
+}
+
+void VarInfo::DumpLocsIfNeeded(MCObjectStreamer *Streamer,
+ MCSection *LocSection,
+ const MCExpr *SymExpr) {
+ if (!IsDebugLocNeeded())
+ return;
+
+ Streamer->SwitchSection(LocSection);
+
+ MCContext &context = Streamer->getContext();
+ unsigned TargetPointerSize = context.getAsmInfo()->getCodePointerSize();
+
+ LocSymbol = context.createTempSymbol();
+ Streamer->EmitLabel(LocSymbol);
+
+ for (const auto &NativeInfo : DebugInfo.Ranges) {
+ const MCExpr *StartOffsetExpr = MCConstantExpr::create(NativeInfo.startOffset, context);
+ const MCExpr *EndOffsetExpr = MCConstantExpr::create(NativeInfo.endOffset, context);
+
+ // Begin address
+ const MCExpr *BeginAddrExpr = MCBinaryExpr::create(MCBinaryExpr::Add, SymExpr,
+ StartOffsetExpr, context);
+ Streamer->EmitValue(BeginAddrExpr, TargetPointerSize);
+
+ // End address
+ const MCExpr *EndAddrExpr = MCBinaryExpr::create(MCBinaryExpr::Add, SymExpr,
+ EndOffsetExpr, context);
+ Streamer->EmitValue(EndAddrExpr, TargetPointerSize);
+
+ // Expression
+ EmitVarLocation(Streamer, NativeInfo, true);
+ }
+
+ // Terminate list entry
+ Streamer->EmitIntValue(0, TargetPointerSize);
+ Streamer->EmitIntValue(0, TargetPointerSize);
+}
+
+void VarInfo::DumpStrings(MCObjectStreamer *Streamer) {
+ if (IsThis) {
+ Streamer->EmitBytes(StringRef("this"));
+ } else {
+ Streamer->EmitBytes(StringRef(DebugInfo.Name));
+ }
+ Streamer->EmitIntValue(0, 1);
+}
+
+void VarInfo::DumpTypeInfo(MCObjectStreamer *Streamer, UserDefinedDwarfTypesBuilder *TypeBuilder) {
+ bool IsDebugLocUsed = IsDebugLocNeeded();
+
+ // Abbrev Number
+ if (DebugInfo.IsParam) {
+ if (IsThis) {
+ Streamer->EmitULEB128IntValue(IsDebugLocUsed ? DwarfAbbrev::FormalParameterThisLoc :
+ DwarfAbbrev::FormalParameterThis);
+ } else {
+ Streamer->EmitULEB128IntValue(IsDebugLocUsed ? DwarfAbbrev::FormalParameterLoc :
+ DwarfAbbrev::FormalParameter);
+ }
+ } else {
+ Streamer->EmitULEB128IntValue(IsDebugLocUsed ? DwarfAbbrev::VariableLoc :
+ DwarfAbbrev::Variable);
+ }
+
+ // DW_AT_name
+ EmitSectionOffset(Streamer, StrSymbol, 4);
+
+ // DW_AT_decl_file
+ Streamer->EmitIntValue(1, 1);
+
+ // DW_AT_decl_line
+ Streamer->EmitIntValue(1, 1);
+
+ // DW_AT_type
+ DwarfInfo *Info = TypeBuilder->GetTypeInfoByIndex(DebugInfo.TypeIndex);
+ assert(Info != nullptr);
+
+ EmitInfoOffset(Streamer, Info, 4);
+
+ // DW_AT_location
+ if (IsDebugLocUsed) {
+ EmitSectionOffset(Streamer, LocSymbol, 4);
+ } else {
+ assert(DebugInfo.Ranges.size() == 1);
+ EmitVarLocation(Streamer, DebugInfo.Ranges[0]);
+ }
+}
+
+// SubprogramInfo
+
+SubprogramInfo::SubprogramInfo(const char *Name,
+ int Size,
+ DwarfMemberFunctionIdTypeInfo *MethodTypeInfo,
+ const std::vector<DebugVarInfo> &DebugVarInfos,
+ const std::vector<DebugEHClauseInfo> &DebugEHClauseInfos) :
+ Name(Name),
+ Size(Size),
+ MethodTypeInfo(MethodTypeInfo),
+ DebugEHClauseInfos(DebugEHClauseInfos) {
+ bool IsStatic = MethodTypeInfo->IsStatic();
+ for (unsigned i = 0; i < DebugVarInfos.size(); i++) {
+ VarInfos.emplace_back(DebugVarInfos[i], i == 0 && !IsStatic);
+ }
+}
+
+void SubprogramInfo::Dump(UserDefinedDwarfTypesBuilder *TypeBuilder, MCObjectStreamer *Streamer,
+ MCSection *TypeSection, MCSection *StrSection, MCSection *LocSection) {
+ DumpDebugLoc(Streamer, LocSection);
+
+ DwarfInfo::Dump(TypeBuilder, Streamer, TypeSection, StrSection);
+
+ // Dump vars
+ DumpVars(TypeBuilder, Streamer, TypeSection, StrSection);
+
+ // Dump try-catch blocks
+ Streamer->SwitchSection(TypeSection);
+ DumpEHClauses(Streamer, TypeSection);
+
+ // Terminate subprogram DIE
+ Streamer->EmitIntValue(0, 1);
+}
+
+void SubprogramInfo::DumpTypeInfo(MCObjectStreamer *Streamer, UserDefinedDwarfTypesBuilder *TypeBuilder) {
+ MCContext &context = Streamer->getContext();
+ bool IsStatic = MethodTypeInfo->IsStatic();
+ unsigned TargetPointerSize = context.getAsmInfo()->getCodePointerSize();
+ Triple::ArchType ArchType = context.getObjectFileInfo()->getTargetTriple().getArch();
+
+ // Subprogram DIE
+
+ // Abbrev Number
+ Streamer->EmitULEB128IntValue(IsStatic ? DwarfAbbrev::SubprogramStatic :
+ DwarfAbbrev::Subprogram);
+
+ // DW_AT_specification
+ EmitInfoOffset(Streamer, MethodTypeInfo, 4);
+
+ // DW_AT_low_pc
+ MCSymbol *Sym = context.getOrCreateSymbol(Twine(Name));
+ const MCExpr *SymExpr = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, context);
+ Streamer->EmitValue(SymExpr, TargetPointerSize);
+
+ // DW_AT_high_pc
+ Streamer->EmitIntValue(Size, TargetPointerSize);
+
+ // DW_AT_frame_base
+ Streamer->EmitULEB128IntValue(1);
+ Streamer->EmitIntValue(GetDwarfFpRegNum(ArchType) + dwarf::DW_OP_reg0, 1);
+
+ if (!IsStatic) {
+ // DW_AT_object_pointer
+ uint32_t Offset = Streamer->getOrCreateDataFragment()->getContents().size();
+
+ Streamer->EmitIntValue(Offset + 4, 4);
+ }
+}
+
+void SubprogramInfo::DumpDebugLoc(MCObjectStreamer *Streamer, MCSection *LocSection) {
+ MCContext &context = Streamer->getContext();
+ MCSymbol *Sym = context.getOrCreateSymbol(Twine(Name));
+ const MCExpr *SymExpr = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, context);
+
+ for (auto &VarInfo : VarInfos) {
+ VarInfo.DumpLocsIfNeeded(Streamer, LocSection, SymExpr);
+ }
+}
+
+void SubprogramInfo::DumpVars(UserDefinedDwarfTypesBuilder *TypeBuilder, MCObjectStreamer *Streamer,
+ MCSection *TypeSection, MCSection *StrSection) {
+ MCContext &context = Streamer->getContext();
+ MCSymbol *Sym = context.getOrCreateSymbol(Twine(Name));
+ const MCExpr *SymExpr = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, context);
+
+ LexicalScope FuncScope(0, Size, true);
+
+ for (unsigned i = 0; i < VarInfos.size(); i++) {
+ FuncScope.AddVar(&VarInfos[i]);
+ }
+
+ FuncScope.Dump(TypeBuilder, Streamer, TypeSection, StrSection, SymExpr);
+}
+
+static void DumpEHClause(MCObjectStreamer *Streamer, MCSection *TypeSection, int Abbrev,
+ const MCExpr *SymExpr, unsigned Offset, unsigned Length) {
+ MCContext &context = Streamer->getContext();
+ unsigned TargetPointerSize = context.getAsmInfo()->getCodePointerSize();
+
+ // Abbrev Number
+ Streamer->EmitULEB128IntValue(Abbrev);
+
+ // DW_AT_low_pc
+ const MCExpr *OffsetExpr = MCConstantExpr::create(Offset, context);
+ const MCExpr *AddrExpr = MCBinaryExpr::create(MCBinaryExpr::Add, SymExpr,
+ OffsetExpr, context);
+
+ Streamer->EmitValue(AddrExpr, TargetPointerSize);
+
+ // DW_AT_high_pc
+ Streamer->EmitIntValue(Length, TargetPointerSize);
+}
+
+void SubprogramInfo::DumpEHClauses(MCObjectStreamer *Streamer, MCSection *TypeSection) {
+ MCContext &context = Streamer->getContext();
+
+ MCSymbol *Sym = context.getOrCreateSymbol(Twine(Name));
+ const MCExpr *SymExpr = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, context);
+
+ for (const auto &EHClause: DebugEHClauseInfos) {
+ // Try block DIE
+ DumpEHClause(Streamer, TypeSection, DwarfAbbrev::TryBlock,
+ SymExpr, EHClause.TryOffset, EHClause.TryLength);
+
+ // Catch block DIE
+ DumpEHClause(Streamer, TypeSection, DwarfAbbrev::CatchBlock,
+ SymExpr, EHClause.HandlerOffset, EHClause.HandlerLength);
+ }
+}
+
+// DwarfGen
+
+void DwarfGen::SetTypeBuilder(UserDefinedDwarfTypesBuilder *TypeBuilder) {
+ assert(this->TypeBuilder == nullptr);
+ assert(TypeBuilder != nullptr);
+ this->TypeBuilder = TypeBuilder;
+ this->Streamer = TypeBuilder->GetStreamer();
+}
+
+void DwarfGen::EmitCompileUnit() {
+ MCContext &context = Streamer->getContext();
+
+ MCSymbol *LineSectionSymbol = nullptr;
+ MCSymbol *AbbrevSectionSymbol = nullptr;
+ if (context.getAsmInfo()->doesDwarfUseRelocationsAcrossSections()) {
+ LineSectionSymbol = Streamer->getDwarfLineTableSymbol(0);
+
+ Streamer->SwitchSection(context.getObjectFileInfo()->getDwarfAbbrevSection());
+ AbbrevSectionSymbol = context.createTempSymbol();
+ Streamer->EmitLabel(AbbrevSectionSymbol);
+ }
+
+ MCSection *debugSection = context.getObjectFileInfo()->getDwarfInfoSection();
+ Streamer->SwitchSection(debugSection);
+
+ InfoStart = debugSection->getBeginSymbol();
+ InfoEnd = context.createTempSymbol();
+
+ // Length
+ const MCExpr *Length = MakeStartMinusEndExpr(*Streamer, *InfoStart, *InfoEnd, 4);
+ emitAbsValue(*Streamer, Length, 4);
+
+ // Version
+ Streamer->EmitIntValue(context.getDwarfVersion(), 2);
+
+ // Unit type, Addr Size and Abbrev offset - DWARF >= 5
+ // Abbrev offset, Addr Size - DWARF <= 4
+ unsigned addrSize = context.getAsmInfo()->getCodePointerSize();
+ if (context.getDwarfVersion() >= 5) {
+ Streamer->EmitIntValue(dwarf::DW_UT_compile, 1);
+ Streamer->EmitIntValue(addrSize, 1);
+ }
+
+ // Abbrev Offset
+ if (AbbrevSectionSymbol == nullptr) {
+ Streamer->EmitIntValue(0, 4);
+ } else {
+ Streamer->EmitSymbolValue(AbbrevSectionSymbol, 4,
+ context.getAsmInfo()->needsDwarfSectionOffsetDirective());
+ }
+
+ if (context.getDwarfVersion() <= 4)
+ Streamer->EmitIntValue(addrSize, 1);
+
+ // CompileUnit DIE
+
+ // Abbrev Number
+ Streamer->EmitULEB128IntValue(DwarfAbbrev::CompileUnit);
+
+ // DW_AT_producer: CoreRT
+ Streamer->EmitBytes(StringRef("CoreRT"));
+ Streamer->EmitIntValue(0, 1);
+
+ // DW_AT_language
+#ifdef FEATURE_LANGID_CS
+ Streamer->EmitIntValue(DW_LANG_MICROSOFT_CSHARP, 2);
+#else
+ Streamer->EmitIntValue(dwarf::DW_LANG_C_plus_plus, 2);
+#endif
+
+ // DW_AT_stmt_list
+ if (LineSectionSymbol == nullptr) {
+ Streamer->EmitIntValue(0, 4);
+ } else {
+ Streamer->EmitSymbolValue(LineSectionSymbol, 4,
+ context.getAsmInfo()->needsDwarfSectionOffsetDirective());
+ }
+}
+
+void DwarfGen::EmitSubprogramInfo(const char *FunctionName,
+ int FunctionSize,
+ unsigned MethodTypeIndex,
+ const std::vector<DebugVarInfo> &VarInfos,
+ const std::vector<DebugEHClauseInfo> &DebugEHClauseInfos) {
+ // return if CU isn't emitted
+ if (InfoStart == nullptr)
+ return;
+
+ if (MethodTypeIndex == 0)
+ return;
+
+ DwarfMemberFunctionIdTypeInfo *MethodTypeInfo = static_cast<DwarfMemberFunctionIdTypeInfo*>(
+ TypeBuilder->GetTypeInfoByIndex(MethodTypeIndex));
+ assert(MethodTypeInfo != nullptr);
+
+ MethodTypeInfo->SetLinkageName(FunctionName);
+
+ Subprograms.emplace_back(FunctionName, FunctionSize, MethodTypeInfo, VarInfos, DebugEHClauseInfos);
+}
+
+void DwarfGen::EmitAbbrev() {
+ // return if CU isn't emitted
+ if (InfoStart == nullptr)
+ return;
+
+ MCContext &context = Streamer->getContext();
+
+ DwarfAbbrev::Dump(Streamer, context.getDwarfVersion(),
+ context.getAsmInfo()->getCodePointerSize());
+}
+
+void DwarfGen::EmitAranges() {
+ // return if CU isn't emitted
+ if (InfoStart == nullptr)
+ return;
+
+ MCContext &context = Streamer->getContext();
+ Streamer->SwitchSection(context.getObjectFileInfo()->getDwarfARangesSection());
+
+ auto &Sections = context.getGenDwarfSectionSyms();
+
+ int Length = 4 + 2 + 4 + 1 + 1;
+ int AddrSize = context.getAsmInfo()->getCodePointerSize();
+ int Pad = 2 * AddrSize - (Length & (2 * AddrSize - 1));
+ if (Pad == 2 * AddrSize)
+ Pad = 0;
+ Length += Pad;
+
+ Length += 2 * AddrSize * Sections.size();
+ Length += 2 * AddrSize;
+
+ // Emit the header for this section.
+ // The 4 byte length not including the 4 byte value for the length.
+ Streamer->EmitIntValue(Length - 4, 4);
+
+ // The 2 byte version, which is 2.
+ Streamer->EmitIntValue(2, 2);
+
+ // The 4 byte offset to the compile unit in the .debug_info from the start
+ // of the .debug_info.
+ Streamer->EmitSymbolValue(InfoStart, 4,
+ context.getAsmInfo()->needsDwarfSectionOffsetDirective());
+
+ Streamer->EmitIntValue(AddrSize, 1);
+
+ Streamer->EmitIntValue(0, 1);
+
+ for(int i = 0; i < Pad; i++)
+ Streamer->EmitIntValue(0, 1);
+
+ for (MCSection *Sec : Sections) {
+ const MCSymbol *StartSymbol = Sec->getBeginSymbol();
+ MCSymbol *EndSymbol = Sec->getEndSymbol(context);
+ assert(StartSymbol && "StartSymbol must not be NULL");
+ assert(EndSymbol && "EndSymbol must not be NULL");
+
+ const MCExpr *Addr = MCSymbolRefExpr::create(
+ StartSymbol, MCSymbolRefExpr::VK_None, context);
+ const MCExpr *Size = MakeStartMinusEndExpr(*Streamer,
+ *StartSymbol, *EndSymbol, 0);
+ Streamer->EmitValue(Addr, AddrSize);
+ emitAbsValue(*Streamer, Size, AddrSize);
+ }
+
+ // Terminating zeros.
+ Streamer->EmitIntValue(0, AddrSize);
+ Streamer->EmitIntValue(0, AddrSize);
+}
+
+void DwarfGen::Finish() {
+ // return if CU isn't emitted
+ if (InfoStart == nullptr)
+ return;
+
+ MCContext &context = Streamer->getContext();
+
+ // Dump type info
+
+ MCSection *InfoSection = context.getObjectFileInfo()->getDwarfInfoSection();
+ MCSection *StrSection = context.getObjectFileInfo()->getDwarfStrSection();
+ MCSection *LocSection = context.getObjectFileInfo()->getDwarfLocSection();
+
+ TypeBuilder->EmitTypeInformation(InfoSection, StrSection);
+
+ // Dump subprograms
+
+ for (auto &Subprogram : Subprograms) {
+ Subprogram.Dump(TypeBuilder, Streamer, InfoSection, StrSection, LocSection);
+ }
+
+ // Dump static vars
+
+ for (const auto *ClassTypeInfo : TypeBuilder->GetClassesWithStaticFields()) {
+ for (const auto &StaticField : ClassTypeInfo->GetStaticFields()) {
+ StaticVarInfo Info(&StaticField);
+ Info.Dump(TypeBuilder, Streamer, InfoSection, StrSection);
+ }
+ }
+
+ // Add the NULL terminating the Compile Unit DIE's.
+ Streamer->SwitchSection(context.getObjectFileInfo()->getDwarfInfoSection());
+
+ Streamer->EmitIntValue(0, 1);
+
+ Streamer->EmitLabel(InfoEnd);
+
+ Streamer->SwitchSection(context.getObjectFileInfo()->getDwarfAbbrevSection());
+
+ // Terminate the abbreviations for this compilation unit
+ Streamer->EmitIntValue(0, 1);
+} \ No newline at end of file
diff --git a/src/Native/ObjWriter/debugInfo/dwarf/dwarfGen.h b/src/Native/ObjWriter/debugInfo/dwarf/dwarfGen.h
new file mode 100644
index 000000000..2fd78a5c6
--- /dev/null
+++ b/src/Native/ObjWriter/debugInfo/dwarf/dwarfGen.h
@@ -0,0 +1,106 @@
+//===---- dwarfGen.h --------------------------------------------*- C++ -*-===//
+//
+// dwarf generator is used to generate dwarf debuginfo.
+//
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+//
+//===----------------------------------------------------------------------===//
+
+#pragma once
+
+#include "llvm/MC/MCObjectStreamer.h"
+
+#include "dwarfTypeBuilder.h"
+#include "jitDebugInfo.h"
+
+#include <vector>
+
+class VarInfo : public DwarfInfo
+{
+public:
+ VarInfo(const DebugVarInfo &Info, bool IsThis);
+
+ bool IsDebugLocNeeded() const { return DebugInfo.Ranges.size() > 1; }
+
+ void DumpLocsIfNeeded(MCObjectStreamer *Streamer, MCSection *LocSection, const MCExpr *SymExpr);
+
+ uint64_t GetStartOffset() const { return StartOffset; }
+
+ uint64_t GetEndOffset() const { return EndOffset; }
+
+ bool IsParam() const { return DebugInfo.IsParam; }
+
+protected:
+ void DumpStrings(MCObjectStreamer *Streamer) override;
+ void DumpTypeInfo(MCObjectStreamer *Streamer, UserDefinedDwarfTypesBuilder *TypeBuilder) override;
+
+private:
+ DebugVarInfo DebugInfo;
+ MCSymbol *LocSymbol;
+ bool IsThis;
+ uint64_t StartOffset;
+ uint64_t EndOffset;
+};
+
+class SubprogramInfo : public DwarfInfo
+{
+public:
+ using DwarfInfo::Dump;
+
+ SubprogramInfo(const char *Name,
+ int Size,
+ DwarfMemberFunctionIdTypeInfo *MethodTypeInfo,
+ const std::vector<DebugVarInfo> &DebugVarInfos,
+ const std::vector<DebugEHClauseInfo> &DebugEHClauseInfos);
+
+ void Dump(UserDefinedDwarfTypesBuilder *TypeBuilder, MCObjectStreamer *Streamer,
+ MCSection *TypeSection, MCSection *StrSection, MCSection *LocSection);
+
+protected:
+ void DumpStrings(MCObjectStreamer *Streamer) override {}
+ void DumpTypeInfo(MCObjectStreamer *Streamer, UserDefinedDwarfTypesBuilder *TypeBuilder) override;
+
+private:
+ void DumpDebugLoc(MCObjectStreamer *Streamer, MCSection *LocSection);
+ void DumpVars(UserDefinedDwarfTypesBuilder *TypeBuilder, MCObjectStreamer *Streamer,
+ MCSection *TypeSection, MCSection *StrSection);
+ void DumpEHClauses(MCObjectStreamer *Streamer, MCSection *TypeSection);
+
+ std::string Name;
+ int Size;
+ DwarfMemberFunctionIdTypeInfo *MethodTypeInfo;
+ std::vector<DebugEHClauseInfo> DebugEHClauseInfos;
+ std::vector<VarInfo> VarInfos;
+};
+
+class DwarfGen
+{
+public:
+ DwarfGen() : Streamer(nullptr),
+ TypeBuilder(nullptr),
+ InfoStart(nullptr),
+ InfoEnd(nullptr) {}
+
+ void SetTypeBuilder(UserDefinedDwarfTypesBuilder *TypeBuilder);
+ void EmitCompileUnit();
+ void EmitSubprogramInfo(const char *FunctionName,
+ int FunctionSize,
+ unsigned MethodTypeIndex,
+ const std::vector<DebugVarInfo> &VarsInfo,
+ const std::vector<DebugEHClauseInfo> &DebugEHClauseInfos);
+
+ void EmitAbbrev();
+ void EmitAranges();
+ void Finish();
+
+private:
+ MCObjectStreamer *Streamer;
+ UserDefinedDwarfTypesBuilder *TypeBuilder;
+
+ MCSymbol *InfoStart;
+ MCSymbol *InfoEnd;
+
+ std::vector<SubprogramInfo> Subprograms;
+}; \ No newline at end of file
diff --git a/src/Native/ObjWriter/debugInfo/dwarf/dwarfTypeBuilder.cpp b/src/Native/ObjWriter/debugInfo/dwarf/dwarfTypeBuilder.cpp
new file mode 100644
index 000000000..da5448bf1
--- /dev/null
+++ b/src/Native/ObjWriter/debugInfo/dwarf/dwarfTypeBuilder.cpp
@@ -0,0 +1,780 @@
+//===---- dwarfTypeBuilder.cpp ----------------------------------*- C++ -*-===//
+//
+// dwarf type builder implementation
+//
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+//
+//===----------------------------------------------------------------------===//
+
+#include "dwarfTypeBuilder.h"
+#include "dwarfAbbrev.h"
+#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCAsmInfo.h"
+#include "llvm/MC/MCObjectFileInfo.h"
+
+#include <sstream>
+#include <vector>
+
+// DwarfInfo
+
+void DwarfInfo::Dump(UserDefinedDwarfTypesBuilder *TypeBuilder, MCObjectStreamer *Streamer,
+ MCSection *TypeSection, MCSection *StrSection) {
+ if (IsDumped)
+ return;
+
+ IsDumped = true;
+
+ MCContext &context = Streamer->getContext();
+
+ InfoSymbol = context.createTempSymbol();
+ InfoExpr = CreateOffsetExpr(context, TypeSection->getBeginSymbol(), InfoSymbol);
+
+ DumpTypes(TypeBuilder, Streamer, TypeSection, StrSection);
+
+ Streamer->SwitchSection(StrSection);
+ StrSymbol = context.createTempSymbol();
+ Streamer->EmitLabel(StrSymbol);
+ DumpStrings(Streamer);
+
+ Streamer->SwitchSection(TypeSection);
+ Streamer->EmitLabel(InfoSymbol);
+ DumpTypeInfo(Streamer, TypeBuilder);
+}
+
+void DwarfInfo::DumpTypes(UserDefinedDwarfTypesBuilder *TypeBuilder, MCObjectStreamer *Streamer,
+ MCSection *TypeSection, MCSection *StrSection) {
+ if (IsDumpedTypes)
+ return;
+
+ IsDumpedTypes = true;
+}
+
+void DwarfInfo::EmitSectionOffset(MCObjectStreamer *Streamer,
+ MCSymbol *Symbol,
+ unsigned Size,
+ uint32_t Offset) {
+ MCContext &context = Streamer->getContext();
+
+ if (context.getAsmInfo()->doesDwarfUseRelocationsAcrossSections()) {
+ if (Offset == 0) {
+ Streamer->EmitSymbolValue(Symbol, Size);
+ } else {
+ const MCSymbolRefExpr *SymbolExpr = MCSymbolRefExpr::create(Symbol,
+ MCSymbolRefExpr::VK_None, context);
+ const MCExpr *OffsetExpr = MCConstantExpr::create(Offset, context);
+ const MCExpr *Expr = MCBinaryExpr::createAdd(SymbolExpr, OffsetExpr, context);
+ Streamer->EmitValue(Expr, Size);
+ }
+ } else {
+ Streamer->EmitIntValue(Symbol->getOffset() + Offset, Size);
+ }
+}
+
+const MCExpr *DwarfInfo::CreateOffsetExpr(MCContext &Context,
+ MCSymbol *BeginSymbol,
+ MCSymbol *Symbol) {
+ MCSymbolRefExpr::VariantKind Variant = MCSymbolRefExpr::VK_None;
+ const MCExpr *StartExpr =
+ MCSymbolRefExpr::create(BeginSymbol, Variant, Context);
+ const MCExpr *EndExpr =
+ MCSymbolRefExpr::create(Symbol, Variant, Context);
+ return MCBinaryExpr::createSub(EndExpr, StartExpr, Context);
+}
+
+void DwarfInfo::EmitOffset(MCObjectStreamer *Streamer,
+ const MCExpr *OffsetExpr,
+ unsigned Size) {
+ MCContext &context = Streamer->getContext();
+
+ if (!context.getAsmInfo()->hasAggressiveSymbolFolding()) {
+ MCSymbol *Temp = context.createTempSymbol();
+ Streamer->EmitAssignment(Temp, OffsetExpr);
+ OffsetExpr = MCSymbolRefExpr::create(Temp, context);
+ }
+
+ Streamer->EmitValue(OffsetExpr, Size);
+}
+
+void DwarfInfo::EmitInfoOffset(MCObjectStreamer *Streamer, const DwarfInfo *Info, unsigned Size) {
+ uint64_t Offset = Info->InfoSymbol->getOffset();
+ if (Offset != 0) {
+ Streamer->EmitIntValue(Offset, Size);
+ } else {
+ EmitOffset(Streamer, Info->InfoExpr, Size);
+ }
+}
+
+// DwarfPrimitiveTypeInfo
+
+struct PrimitiveTypeDesc {
+ const char *Name;
+ int Encoding;
+ unsigned ByteSize;
+};
+
+static PrimitiveTypeDesc GetPrimitiveTypeDesc(PrimitiveTypeFlags Type, unsigned TargetPointerSize) {
+ switch (Type) {
+ case PrimitiveTypeFlags::Void: return {"void", dwarf::DW_ATE_address, 0};
+ case PrimitiveTypeFlags::Boolean: return {"bool", dwarf::DW_ATE_boolean, 1};
+ case PrimitiveTypeFlags::Char: return {"char16_t", dwarf::DW_ATE_UTF, 2};
+ case PrimitiveTypeFlags::SByte: return {"sbyte", dwarf::DW_ATE_signed, 1};
+ case PrimitiveTypeFlags::Byte: return {"byte", dwarf::DW_ATE_unsigned, 1};
+ case PrimitiveTypeFlags::Int16: return {"short", dwarf::DW_ATE_signed, 2};
+ case PrimitiveTypeFlags::UInt16: return {"ushort", dwarf::DW_ATE_unsigned, 2};
+ case PrimitiveTypeFlags::Int32: return {"int", dwarf::DW_ATE_signed, 4};
+ case PrimitiveTypeFlags::UInt32: return {"uint", dwarf::DW_ATE_unsigned, 4};
+ case PrimitiveTypeFlags::Int64: return {"long", dwarf::DW_ATE_signed, 8};
+ case PrimitiveTypeFlags::UInt64: return {"ulong", dwarf::DW_ATE_unsigned, 8};
+ case PrimitiveTypeFlags::IntPtr: return {"System.IntPtr", dwarf::DW_ATE_signed, TargetPointerSize};
+ case PrimitiveTypeFlags::UIntPtr: return {"System.UIntPtr", dwarf::DW_ATE_unsigned, TargetPointerSize};
+ case PrimitiveTypeFlags::Single: return {"float", dwarf::DW_ATE_float, 4};
+ case PrimitiveTypeFlags::Double: return {"double", dwarf::DW_ATE_float, 8};
+ default:
+ assert(false && "Unexpected type");
+ return {nullptr, 0, 0};
+ }
+}
+
+void DwarfPrimitiveTypeInfo::DumpStrings(MCObjectStreamer *Streamer) {
+ MCContext &context = Streamer->getContext();
+ unsigned TargetPointerSize = context.getAsmInfo()->getCodePointerSize();
+
+ PrimitiveTypeDesc TD = GetPrimitiveTypeDesc(Type, TargetPointerSize);
+ if (TD.Name == nullptr)
+ return;
+
+ Streamer->EmitBytes(StringRef(TD.Name));
+ Streamer->EmitIntValue(0, 1);
+}
+
+void DwarfPrimitiveTypeInfo::DumpTypeInfo(MCObjectStreamer *Streamer, UserDefinedDwarfTypesBuilder *TypeBuilder) {
+ MCContext &context = Streamer->getContext();
+ unsigned TargetPointerSize = context.getAsmInfo()->getCodePointerSize();
+
+ PrimitiveTypeDesc TD = GetPrimitiveTypeDesc(Type, TargetPointerSize);
+ if (TD.Name == nullptr)
+ return;
+
+ // Abbrev Number
+ Streamer->EmitULEB128IntValue(DwarfAbbrev::BaseType);
+
+ // DW_AT_name
+ EmitSectionOffset(Streamer, StrSymbol, 4);
+
+ // DW_AT_encoding
+ Streamer->EmitIntValue(TD.Encoding, 1);
+
+ // DW_AT_byte_size
+ Streamer->EmitIntValue(TD.ByteSize, 1);
+}
+
+// DwarfEnumerator
+
+void DwarfEnumerator::DumpStrings(MCObjectStreamer *Streamer) {
+ Streamer->EmitBytes(Name);
+ Streamer->EmitIntValue(0, 1);
+}
+
+void DwarfEnumerator::DumpTypeInfo(MCObjectStreamer *Streamer, UserDefinedDwarfTypesBuilder *TypeBuilder) {
+ uint8_t Size = EnumTypeInfo->GetByteSize();
+
+ // Abbrev Number
+ switch (Size) {
+ case 1:
+ Streamer->EmitULEB128IntValue(DwarfAbbrev::Enumerator1);
+ break;
+ case 2:
+ Streamer->EmitULEB128IntValue(DwarfAbbrev::Enumerator2);
+ break;
+ case 4:
+ Streamer->EmitULEB128IntValue(DwarfAbbrev::Enumerator4);
+ break;
+ case 8:
+ Streamer->EmitULEB128IntValue(DwarfAbbrev::Enumerator8);
+ break;
+ default:
+ assert(false && "Unexpected byte size value");
+ }
+
+ // DW_AT_name
+ EmitSectionOffset(Streamer, StrSymbol, 4);
+
+ // DW_AT_const_value
+ Streamer->EmitIntValue(Value, Size);
+}
+
+// DwarfEnumTypeInfo
+
+DwarfEnumTypeInfo::DwarfEnumTypeInfo(const EnumTypeDescriptor &TypeDescriptor,
+ const EnumRecordTypeDescriptor *TypeRecords) :
+ Name(TypeDescriptor.Name),
+ ElementType(TypeDescriptor.ElementType) {
+ for (uint64 i = 0; i < TypeDescriptor.ElementCount; i++) {
+ Records.emplace_back(TypeRecords[i], this);
+ }
+}
+
+void DwarfEnumTypeInfo::DumpTypes(UserDefinedDwarfTypesBuilder *TypeBuilder, MCObjectStreamer *Streamer,
+ MCSection *TypeSection, MCSection *StrSection) {
+ if (IsDumpedTypes)
+ return;
+
+ DwarfInfo::DumpTypes(TypeBuilder, Streamer, TypeSection, StrSection);
+
+ DwarfInfo *Info = TypeBuilder->GetTypeInfoByIndex(ElementType);
+ assert(Info != nullptr);
+
+ Info->Dump(TypeBuilder, Streamer, TypeSection, StrSection);
+}
+
+void DwarfEnumTypeInfo::Dump(UserDefinedDwarfTypesBuilder *TypeBuilder, MCObjectStreamer *Streamer,
+ MCSection *TypeSection, MCSection *StrSection) {
+ if (IsDumped)
+ return;
+
+ MCContext &context = Streamer->getContext();
+ unsigned TargetPointerSize = context.getAsmInfo()->getCodePointerSize();
+
+ DwarfPrimitiveTypeInfo *ElementTypeInfo = static_cast<DwarfPrimitiveTypeInfo*>(
+ TypeBuilder->GetTypeInfoByIndex(ElementType));
+ assert(ElementTypeInfo != nullptr);
+
+ PrimitiveTypeDesc TD = GetPrimitiveTypeDesc(ElementTypeInfo->GetType(), TargetPointerSize);
+ ByteSize = TD.ByteSize;
+
+ DwarfInfo::Dump(TypeBuilder, Streamer, TypeSection, StrSection);
+
+ for (auto &Enumerator : Records) {
+ Enumerator.Dump(TypeBuilder, Streamer, TypeSection, StrSection);
+ }
+
+ // Terminate DIE
+ Streamer->SwitchSection(TypeSection);
+ Streamer->EmitIntValue(0, 1);
+}
+
+void DwarfEnumTypeInfo::DumpStrings(MCObjectStreamer *Streamer) {
+ Streamer->EmitBytes(Name);
+ Streamer->EmitIntValue(0, 1);
+}
+
+void DwarfEnumTypeInfo::DumpTypeInfo(MCObjectStreamer *Streamer, UserDefinedDwarfTypesBuilder *TypeBuilder) {
+ // Abbrev Number
+ Streamer->EmitULEB128IntValue(DwarfAbbrev::EnumerationType);
+
+ // DW_AT_name
+ EmitSectionOffset(Streamer, StrSymbol, 4);
+
+ // DW_AT_type
+ DwarfInfo *Info = TypeBuilder->GetTypeInfoByIndex(ElementType);
+ assert(Info != nullptr);
+
+ EmitInfoOffset(Streamer, Info, 4);
+
+ // DW_AT_byte_size
+ Streamer->EmitIntValue(ByteSize, 1);
+}
+
+// DwarfDataField
+
+void DwarfDataField::DumpStrings(MCObjectStreamer *Streamer) {
+ Streamer->EmitBytes(StringRef(Name));
+ Streamer->EmitIntValue(0, 1);
+}
+
+void DwarfDataField::DumpTypes(UserDefinedDwarfTypesBuilder *TypeBuilder, MCObjectStreamer *Streamer,
+ MCSection *TypeSection, MCSection *StrSection) {
+ if (IsDumpedTypes)
+ return;
+
+ DwarfInfo::DumpTypes(TypeBuilder, Streamer, TypeSection, StrSection);
+
+ DwarfInfo *MemberTypeInfo = TypeBuilder->GetTypeInfoByIndex(TypeIndex);
+ assert(MemberTypeInfo != nullptr);
+
+ MemberTypeInfo->Dump(TypeBuilder, Streamer, TypeSection, StrSection);
+}
+
+void DwarfDataField::DumpTypeInfo(MCObjectStreamer *Streamer, UserDefinedDwarfTypesBuilder *TypeBuilder) {
+ // Abbrev Number
+ Streamer->EmitULEB128IntValue(DwarfAbbrev::ClassMember);
+
+ // DW_AT_name
+ EmitSectionOffset(Streamer, StrSymbol, 4);
+
+ // DW_AT_type
+ DwarfInfo *MemberTypeInfo = TypeBuilder->GetTypeInfoByIndex(TypeIndex);
+ assert(MemberTypeInfo != nullptr);
+ EmitInfoOffset(Streamer, MemberTypeInfo, 4);
+
+ // DW_AT_data_member_location
+ Streamer->EmitIntValue(Offset, 4);
+}
+
+// DwarfStaticDataField
+
+void DwarfStaticDataField::DumpTypeInfo(MCObjectStreamer *Streamer, UserDefinedDwarfTypesBuilder *TypeBuilder) {
+ // Abbrev Number
+ Streamer->EmitULEB128IntValue(DwarfAbbrev::ClassMemberStatic);
+
+ // DW_AT_name
+ EmitSectionOffset(Streamer, StrSymbol, 4);
+
+ // DW_AT_type
+ DwarfInfo *MemberTypeInfo = TypeBuilder->GetTypeInfoByIndex(TypeIndex);
+ assert(MemberTypeInfo != nullptr);
+ EmitInfoOffset(Streamer, MemberTypeInfo, 4);
+}
+
+// DwarfClassTypeInfo
+
+DwarfClassTypeInfo::DwarfClassTypeInfo(const ClassTypeDescriptor &ClassDescriptor,
+ const ClassFieldsTypeDescriptior &ClassFieldsDescriptor,
+ const DataFieldDescriptor *FieldsDescriptors,
+ const StaticDataFieldDescriptor *StaticsDescriptors) :
+ Name(ClassDescriptor.Name),
+ IsStruct(ClassDescriptor.IsStruct),
+ BaseClassId(ClassDescriptor.BaseClassId),
+ Size(ClassDescriptor.InstanceSize),
+ IsForwardDecl(false) {
+ int32_t staticIdx = 0;
+ for (int32_t i = 0; i < ClassFieldsDescriptor.FieldsCount; i++) {
+ if (FieldsDescriptors[i].Offset == 0xFFFFFFFF) {
+ StaticFields.emplace_back(FieldsDescriptors[i], StaticsDescriptors[staticIdx++]);
+ } else {
+ Fields.emplace_back(FieldsDescriptors[i]);
+ }
+ }
+}
+
+void DwarfClassTypeInfo::DumpTypes(UserDefinedDwarfTypesBuilder *TypeBuilder, MCObjectStreamer *Streamer,
+ MCSection *TypeSection, MCSection *StrSection) {
+ if (IsDumpedTypes)
+ return;
+
+ DwarfInfo::DumpTypes(TypeBuilder, Streamer, TypeSection, StrSection);
+
+ if (BaseClassId != 0) {
+ DwarfInfo *BaseClassInfo = TypeBuilder->GetTypeInfoByIndex(BaseClassId);
+ assert(BaseClassInfo != nullptr);
+
+ BaseClassInfo->Dump(TypeBuilder, Streamer, TypeSection, StrSection);
+ }
+
+ for (auto &Field : Fields) {
+ Field.DumpTypes(TypeBuilder, Streamer, TypeSection, StrSection);
+ }
+
+ for (auto &StaticField : StaticFields) {
+ StaticField.DumpTypes(TypeBuilder, Streamer, TypeSection, StrSection);
+ }
+
+ for (auto *Function : MemberFunctions) {
+ Function->DumpTypes(TypeBuilder, Streamer, TypeSection, StrSection);
+ }
+}
+
+void DwarfClassTypeInfo::Dump(UserDefinedDwarfTypesBuilder *TypeBuilder, MCObjectStreamer *Streamer,
+ MCSection *TypeSection, MCSection *StrSection) {
+ if (IsDumped)
+ return;
+
+ DwarfInfo::Dump(TypeBuilder, Streamer, TypeSection, StrSection);
+
+ if (IsForwardDecl)
+ return;
+
+ for (auto &Field : Fields) {
+ Field.Dump(TypeBuilder, Streamer, TypeSection, StrSection);
+ }
+
+ for (auto &StaticField : StaticFields) {
+ StaticField.Dump(TypeBuilder, Streamer, TypeSection, StrSection);
+ }
+
+ for (auto *Function : MemberFunctions) {
+ Function->Dump(TypeBuilder, Streamer, TypeSection, StrSection);
+ }
+
+ // Terminate DIE
+ Streamer->SwitchSection(TypeSection);
+ Streamer->EmitIntValue(0, 1);
+}
+
+void DwarfClassTypeInfo::DumpStrings(MCObjectStreamer *Streamer) {
+ Streamer->EmitBytes(StringRef(Name));
+ Streamer->EmitIntValue(0, 1);
+}
+
+void DwarfClassTypeInfo::DumpTypeInfo(MCObjectStreamer *Streamer, UserDefinedDwarfTypesBuilder *TypeBuilder) {
+ // Abbrev Number
+ Streamer->EmitULEB128IntValue(IsForwardDecl ? DwarfAbbrev::ClassTypeDecl : DwarfAbbrev::ClassType);
+
+ // DW_AT_name
+ EmitSectionOffset(Streamer, StrSymbol, 4);
+
+ if (!IsForwardDecl) {
+ // DW_AT_byte_size
+ Streamer->EmitIntValue(Size, 4);
+ }
+
+ if (BaseClassId != 0) {
+ DwarfInfo *BaseClassInfo = TypeBuilder->GetTypeInfoByIndex(BaseClassId);
+ assert(BaseClassInfo != nullptr);
+
+ // DW_TAG_inheritance DIE
+
+ // Abbrev Number
+ Streamer->EmitULEB128IntValue(DwarfAbbrev::ClassInheritance);
+
+ // DW_AT_type
+ EmitInfoOffset(Streamer, BaseClassInfo, 4);
+
+ // DW_AT_data_member_location = 0
+ Streamer->EmitIntValue(0, 1);
+ }
+}
+
+// DwarfSimpleArrayTypeInfo
+
+void DwarfSimpleArrayTypeInfo::DumpTypes(UserDefinedDwarfTypesBuilder *TypeBuilder, MCObjectStreamer *Streamer,
+ MCSection *TypeSection, MCSection *StrSection) {
+ if (IsDumpedTypes)
+ return;
+
+ DwarfInfo::DumpTypes(TypeBuilder, Streamer, TypeSection, StrSection);
+
+ DwarfInfo *ElementInfo = TypeBuilder->GetTypeInfoByIndex(ElementType);
+ assert(ElementInfo != nullptr);
+
+ ElementInfo->Dump(TypeBuilder, Streamer, TypeSection, StrSection);
+}
+
+void DwarfSimpleArrayTypeInfo::DumpStrings(MCObjectStreamer *Streamer) {
+ // nothing to dump
+}
+
+void DwarfSimpleArrayTypeInfo::DumpTypeInfo(MCObjectStreamer *Streamer, UserDefinedDwarfTypesBuilder *TypeBuilder) {
+ // Abbrev Number
+ Streamer->EmitULEB128IntValue(DwarfAbbrev::ArrayType);
+
+ DwarfInfo *Info = TypeBuilder->GetTypeInfoByIndex(ElementType);
+ assert(Info != nullptr);
+
+ // DW_AT_type
+ EmitInfoOffset(Streamer, Info, 4);
+
+ // DW_TAG_subrange_type DIE
+
+ // Abbrev Number
+ Streamer->EmitULEB128IntValue(DwarfAbbrev::SubrangeType);
+
+ // DW_AT_upper_bound
+ Streamer->EmitULEB128IntValue(Size - 1);
+
+ // Terminate DIE
+ Streamer->EmitIntValue(0, 1);
+}
+
+// DwarfPointerTypeInfo
+
+void DwarfPointerTypeInfo::DumpTypes(UserDefinedDwarfTypesBuilder *TypeBuilder, MCObjectStreamer *Streamer,
+ MCSection *TypeSection, MCSection *StrSection) {
+ if (IsDumpedTypes)
+ return;
+
+ DwarfInfo::DumpTypes(TypeBuilder, Streamer, TypeSection, StrSection);
+
+ DwarfInfo *Info = TypeBuilder->GetTypeInfoByIndex(TypeDesc.ElementType);
+ assert(Info != nullptr);
+
+ Info->Dump(TypeBuilder, Streamer, TypeSection, StrSection);
+}
+
+void DwarfPointerTypeInfo::DumpStrings(MCObjectStreamer *Streamer) {
+ // nothing to dump
+}
+
+void DwarfPointerTypeInfo::DumpTypeInfo(MCObjectStreamer *Streamer, UserDefinedDwarfTypesBuilder *TypeBuilder) {
+ // Abbrev Number
+ Streamer->EmitULEB128IntValue(TypeDesc.IsReference ? DwarfAbbrev::ReferenceType : DwarfAbbrev::PointerType);
+
+ DwarfInfo *Info = TypeBuilder->GetTypeInfoByIndex(TypeDesc.ElementType);
+ assert(Info != nullptr);
+
+ // DW_AT_type
+ EmitInfoOffset(Streamer, Info, 4);
+
+ // DW_AT_byte_size
+ Streamer->EmitIntValue(TypeDesc.Is64Bit ? 8 : 4, 1);
+}
+
+// DwarfMemberFunctionTypeInfo
+
+DwarfMemberFunctionTypeInfo::DwarfMemberFunctionTypeInfo(
+ const MemberFunctionTypeDescriptor& MemberDescriptor,
+ uint32_t const *const ArgumentTypes,
+ bool IsStaticMethod) :
+ TypeDesc(MemberDescriptor),
+ IsStaticMethod(IsStaticMethod) {
+ for (uint16_t i = 0; i < MemberDescriptor.NumberOfArguments; i++) {
+ this->ArgumentTypes.push_back(ArgumentTypes[i]);
+ }
+}
+
+void DwarfMemberFunctionTypeInfo::DumpStrings(MCObjectStreamer *Streamer) {
+ // nothing to dump
+}
+
+void DwarfMemberFunctionTypeInfo::DumpTypeInfo(MCObjectStreamer *Streamer, UserDefinedDwarfTypesBuilder *TypeBuilder) {
+ // nothing to dump
+}
+
+// DwarfMemberFunctionIdTypeInfo
+
+void DwarfMemberFunctionIdTypeInfo::DumpTypes(UserDefinedDwarfTypesBuilder *TypeBuilder, MCObjectStreamer *Streamer,
+ MCSection *TypeSection, MCSection *StrSection) {
+ if (IsDumpedTypes)
+ return;
+
+ DwarfInfo::DumpTypes(TypeBuilder, Streamer, TypeSection, StrSection);
+
+ // Dump return type
+ DwarfInfo *ReturnTypeInfo = TypeBuilder->GetTypeInfoByIndex(MemberFunctionTypeInfo->GetReturnTypeIndex());
+ assert(ReturnTypeInfo != nullptr);
+
+ ReturnTypeInfo->Dump(TypeBuilder, Streamer, TypeSection, StrSection);
+
+ // Dump this pointer type
+ if (!MemberFunctionTypeInfo->IsStatic()) {
+ DwarfInfo *ThisPtrTypeInfo = TypeBuilder->GetTypeInfoByIndex(MemberFunctionTypeInfo->GetThisPtrTypeIndex());
+ assert(ThisPtrTypeInfo != nullptr);
+
+ ThisPtrTypeInfo->Dump(TypeBuilder, Streamer, TypeSection, StrSection);
+ }
+
+ // Dump argument types
+ for (uint32_t ArgTypeIndex : MemberFunctionTypeInfo->GetArgTypes()) {
+ DwarfInfo *ArgTypeInfo = TypeBuilder->GetTypeInfoByIndex(ArgTypeIndex);
+ assert(ArgTypeInfo != nullptr);
+ ArgTypeInfo->Dump(TypeBuilder, Streamer, TypeSection, StrSection);
+ }
+}
+
+void DwarfMemberFunctionIdTypeInfo::DumpStrings(MCObjectStreamer *Streamer) {
+ Streamer->EmitBytes(StringRef(Name));
+ Streamer->EmitIntValue(0, 1);
+
+ MCContext &context = Streamer->getContext();
+ LinkageNameSymbol = context.createTempSymbol();
+ Streamer->EmitLabel(LinkageNameSymbol);
+ Streamer->EmitBytes(StringRef(LinkageName));
+ Streamer->EmitIntValue(0, 1);
+}
+
+void DwarfMemberFunctionIdTypeInfo::DumpTypeInfo(MCObjectStreamer *Streamer, UserDefinedDwarfTypesBuilder *TypeBuilder) {
+ // Abbrev Number
+ bool IsStatic = MemberFunctionTypeInfo->IsStatic();
+
+ Streamer->EmitULEB128IntValue(IsStatic ? DwarfAbbrev::SubprogramStaticSpec : DwarfAbbrev::SubprogramSpec);
+
+ // DW_AT_name
+ EmitSectionOffset(Streamer, StrSymbol, 4);
+
+ // DW_AT_linkage_name
+ EmitSectionOffset(Streamer, LinkageNameSymbol, 4);
+
+ // DW_AT_decl_file
+ Streamer->EmitIntValue(1, 1);
+
+ // DW_AT_decl_line
+ Streamer->EmitIntValue(1, 1);
+
+ // DW_AT_type
+ DwarfInfo *ReturnTypeInfo = TypeBuilder->GetTypeInfoByIndex(MemberFunctionTypeInfo->GetReturnTypeIndex());
+ assert(ReturnTypeInfo != nullptr);
+
+ EmitInfoOffset(Streamer, ReturnTypeInfo, 4);
+
+ if (!IsStatic) {
+ // DW_AT_object_pointer
+ uint32_t Offset = Streamer->getOrCreateDataFragment()->getContents().size();
+
+ Streamer->EmitIntValue(Offset + 4, 4);
+
+ // This formal parameter DIE
+ DwarfInfo *ThisTypeInfo = TypeBuilder->GetTypeInfoByIndex(MemberFunctionTypeInfo->GetThisPtrTypeIndex());
+ assert(ThisTypeInfo != nullptr);
+
+ // Abbrev Number
+ Streamer->EmitULEB128IntValue(DwarfAbbrev::FormalParameterThisSpec);
+
+ // DW_AT_type
+ EmitInfoOffset(Streamer, ThisTypeInfo, 4);
+ }
+
+ for (uint32_t ArgTypeIndex : MemberFunctionTypeInfo->GetArgTypes()) {
+ DwarfInfo *ArgTypeInfo = TypeBuilder->GetTypeInfoByIndex(ArgTypeIndex);
+ assert(ArgTypeInfo != nullptr);
+
+ // Formal parameter DIE
+
+ // Abbrev Number
+ Streamer->EmitULEB128IntValue(DwarfAbbrev::FormalParameterSpec);
+
+ // DW_AT_type
+ EmitInfoOffset(Streamer, ArgTypeInfo, 4);
+ }
+
+ // Ternimate DIE
+ Streamer->EmitIntValue(0, 1);
+}
+
+// DwarfTypesBuilder
+
+void UserDefinedDwarfTypesBuilder::EmitTypeInformation(
+ MCSection *TypeSection,
+ MCSection *StrSection) {
+ for (auto &Info : DwarfTypes) {
+ Info->Dump(this, Streamer, TypeSection, StrSection);
+ }
+}
+
+unsigned UserDefinedDwarfTypesBuilder::GetEnumTypeIndex(
+ const EnumTypeDescriptor &TypeDescriptor,
+ const EnumRecordTypeDescriptor *TypeRecords) {
+ unsigned TypeIndex = ArrayIndexToTypeIndex(DwarfTypes.size());
+ UserDefinedTypes.push_back(std::make_pair(TypeDescriptor.Name, TypeIndex));
+ DwarfTypes.push_back(make_unique<DwarfEnumTypeInfo>(TypeDescriptor, TypeRecords));
+ return TypeIndex;
+}
+
+unsigned UserDefinedDwarfTypesBuilder::GetClassTypeIndex(
+ const ClassTypeDescriptor &ClassDescriptor) {
+ unsigned TypeIndex = ArrayIndexToTypeIndex(DwarfTypes.size());
+ DwarfTypes.push_back(make_unique<DwarfClassTypeInfo>(ClassDescriptor));
+ return TypeIndex;
+}
+
+unsigned UserDefinedDwarfTypesBuilder::GetCompleteClassTypeIndex(
+ const ClassTypeDescriptor &ClassDescriptor,
+ const ClassFieldsTypeDescriptior &ClassFieldsDescriptor,
+ const DataFieldDescriptor *FieldsDescriptors,
+ const StaticDataFieldDescriptor *StaticsDescriptors) {
+ unsigned TypeIndex = ArrayIndexToTypeIndex(DwarfTypes.size());
+ UserDefinedTypes.push_back(std::make_pair(ClassDescriptor.Name, TypeIndex));
+
+ DwarfClassTypeInfo *ClassTypeInfo = new DwarfClassTypeInfo(ClassDescriptor, ClassFieldsDescriptor,
+ FieldsDescriptors, StaticsDescriptors);
+
+ DwarfTypes.push_back(std::unique_ptr<DwarfClassTypeInfo>(ClassTypeInfo));
+
+ if (ClassTypeInfo->GetStaticFields().size() > 0) {
+ ClassesWithStaticFields.push_back(ClassTypeInfo);
+ }
+
+ return TypeIndex;
+}
+
+unsigned UserDefinedDwarfTypesBuilder::GetArrayTypeIndex(
+ const ClassTypeDescriptor &ClassDescriptor,
+ const ArrayTypeDescriptor &ArrayDescriptor) {
+ // Create corresponding class info
+ ClassTypeDescriptor ArrayClassDescriptor = ClassDescriptor;
+
+ std::vector<DataFieldDescriptor> FieldDescs;
+ unsigned FieldOffset = TargetPointerSize;
+
+ FieldDescs.push_back({GetPrimitiveTypeIndex(PrimitiveTypeFlags::Int32), FieldOffset, "m_NumComponents"});
+ FieldOffset += TargetPointerSize;
+
+ if (ArrayDescriptor.IsMultiDimensional == 1) {
+ unsigned BoundsTypeIndex = GetSimpleArrayTypeIndex(GetPrimitiveTypeIndex(PrimitiveTypeFlags::Int32), ArrayDescriptor.Rank);
+ FieldDescs.push_back({BoundsTypeIndex, FieldOffset, "m_Bounds"});
+ FieldOffset += 2 * 4 * ArrayDescriptor.Rank;
+ }
+
+ unsigned DataTypeIndex = GetSimpleArrayTypeIndex(ArrayDescriptor.ElementType, 0);
+ FieldDescs.push_back({DataTypeIndex, FieldOffset, "m_Data"});
+
+ ClassFieldsTypeDescriptior FieldsTypeDesc =
+ {TargetPointerSize, ArrayDescriptor.IsMultiDimensional ? 3 : 2};
+
+ ArrayClassDescriptor.InstanceSize = FieldOffset;
+
+ unsigned TypeIndex = ArrayIndexToTypeIndex(DwarfTypes.size());
+ UserDefinedTypes.push_back(std::make_pair(ArrayClassDescriptor.Name, TypeIndex));
+ DwarfTypes.push_back(make_unique<DwarfClassTypeInfo>(ArrayClassDescriptor, FieldsTypeDesc, FieldDescs.data(), nullptr));
+
+ return TypeIndex;
+}
+
+unsigned UserDefinedDwarfTypesBuilder::GetPointerTypeIndex(const PointerTypeDescriptor& PointerDescriptor)
+{
+ unsigned TypeIndex = ArrayIndexToTypeIndex(DwarfTypes.size());
+ DwarfTypes.push_back(make_unique<DwarfPointerTypeInfo>(PointerDescriptor));
+ return TypeIndex;
+}
+
+unsigned UserDefinedDwarfTypesBuilder::GetMemberFunctionTypeIndex(const MemberFunctionTypeDescriptor& MemberDescriptor,
+ uint32_t const *const ArgumentTypes)
+{
+ unsigned TypeIndex = ArrayIndexToTypeIndex(DwarfTypes.size());
+ bool IsStatic = MemberDescriptor.TypeIndexOfThisPointer == GetPrimitiveTypeIndex(PrimitiveTypeFlags::Void);
+ DwarfTypes.push_back(make_unique<DwarfMemberFunctionTypeInfo>(MemberDescriptor, ArgumentTypes, IsStatic));
+ return TypeIndex;
+}
+
+unsigned UserDefinedDwarfTypesBuilder::GetMemberFunctionId(const MemberFunctionIdTypeDescriptor& MemberIdDescriptor)
+{
+ unsigned TypeIndex = ArrayIndexToTypeIndex(DwarfTypes.size());
+
+ DwarfMemberFunctionTypeInfo *MemberFunctionTypeInfo = static_cast<DwarfMemberFunctionTypeInfo*>(
+ GetTypeInfoByIndex(MemberIdDescriptor.MemberFunction));
+ assert(MemberFunctionTypeInfo != nullptr);
+
+ DwarfMemberFunctionIdTypeInfo *MemberFunctionIdTypeInfo =
+ new DwarfMemberFunctionIdTypeInfo(MemberIdDescriptor, MemberFunctionTypeInfo);
+
+ DwarfTypes.push_back(std::unique_ptr<DwarfMemberFunctionIdTypeInfo>(MemberFunctionIdTypeInfo));
+
+ DwarfClassTypeInfo *ParentClassInfo = static_cast<DwarfClassTypeInfo*>(
+ GetTypeInfoByIndex(MemberIdDescriptor.ParentClass));
+ assert(ParentClassInfo != nullptr);
+
+ ParentClassInfo->AddMemberFunction(MemberFunctionIdTypeInfo);
+
+ return TypeIndex;
+}
+
+unsigned UserDefinedDwarfTypesBuilder::GetPrimitiveTypeIndex(PrimitiveTypeFlags Type) {
+ auto Iter = PrimitiveDwarfTypes.find(Type);
+ if (Iter != PrimitiveDwarfTypes.end())
+ return Iter->second;
+
+ unsigned TypeIndex = ArrayIndexToTypeIndex(DwarfTypes.size());
+ DwarfTypes.push_back(make_unique<DwarfPrimitiveTypeInfo>(Type));
+
+ PrimitiveDwarfTypes.insert(std::make_pair(Type, TypeIndex));
+
+ return TypeIndex;
+}
+
+unsigned UserDefinedDwarfTypesBuilder::GetSimpleArrayTypeIndex(unsigned ElemIndex, unsigned Size) {
+ auto Iter = SimpleArrayDwarfTypes.find(ElemIndex);
+ if (Iter != SimpleArrayDwarfTypes.end()) {
+ auto CountMap = Iter->second;
+ auto CountIter = CountMap.find(Size);
+ if (CountIter != CountMap.end())
+ return CountIter->second;
+ }
+
+ unsigned TypeIndex = ArrayIndexToTypeIndex(DwarfTypes.size());
+ DwarfTypes.push_back(make_unique<DwarfSimpleArrayTypeInfo>(ElemIndex, Size));
+
+ SimpleArrayDwarfTypes[ElemIndex][Size] = TypeIndex;
+
+ return TypeIndex;
+} \ No newline at end of file
diff --git a/src/Native/ObjWriter/debugInfo/dwarf/dwarfTypeBuilder.h b/src/Native/ObjWriter/debugInfo/dwarf/dwarfTypeBuilder.h
new file mode 100644
index 000000000..0ea43a451
--- /dev/null
+++ b/src/Native/ObjWriter/debugInfo/dwarf/dwarfTypeBuilder.h
@@ -0,0 +1,366 @@
+//===---- dwarfTypeBuilder.h ------------------------------------*- C++ -*-===//
+//
+// type builder is used to convert .Net types into Dwarf debuginfo.
+//
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+//
+//===----------------------------------------------------------------------===//
+
+#pragma once
+
+#include "debugInfo/typeBuilder.h"
+
+#include <vector>
+#include <unordered_map>
+
+class UserDefinedDwarfTypesBuilder;
+
+class DwarfInfo
+{
+public:
+ DwarfInfo() :
+ StrSymbol(nullptr),
+ InfoSymbol(nullptr),
+ IsDumped(false),
+ IsDumpedTypes(false) {}
+
+ virtual ~DwarfInfo() {}
+
+ virtual void Dump(UserDefinedDwarfTypesBuilder *TypeBuilder, MCObjectStreamer *Streamer,
+ MCSection *TypeSection, MCSection *StrSection);
+
+ virtual void DumpTypes(UserDefinedDwarfTypesBuilder *TypeBuilder, MCObjectStreamer *Streamer,
+ MCSection *TypeSection, MCSection *StrSection);
+
+ MCSymbol *GetInfoSymbol() { return InfoSymbol; }
+
+ const MCExpr *GetInfoExpr() { return InfoExpr; }
+
+protected:
+ virtual void DumpStrings(MCObjectStreamer *Streamer) = 0;
+ virtual void DumpTypeInfo(MCObjectStreamer *Streamer, UserDefinedDwarfTypesBuilder *TypeBuilder) = 0;
+
+ static void EmitSectionOffset(MCObjectStreamer *Streamer,
+ MCSymbol *Symbol,
+ unsigned Size,
+ uint32_t Offset = 0);
+
+ static const MCExpr *CreateOffsetExpr(MCContext &Context,
+ MCSymbol *BeginSymbol,
+ MCSymbol *Symbol);
+
+ static void EmitOffset(MCObjectStreamer *Streamer,
+ const MCExpr *OffsetExpr,
+ unsigned Size);
+
+ static void EmitInfoOffset(MCObjectStreamer *Streamer, const DwarfInfo *Info, unsigned Size);
+
+ MCSymbol *StrSymbol;
+ MCSymbol *InfoSymbol;
+ const MCExpr *InfoExpr;
+
+ bool IsDumped;
+ bool IsDumpedTypes;
+};
+
+class DwarfPrimitiveTypeInfo : public DwarfInfo
+{
+public:
+ DwarfPrimitiveTypeInfo(PrimitiveTypeFlags PrimitiveType) : Type(PrimitiveType) {}
+
+ PrimitiveTypeFlags GetType() { return Type; }
+
+protected:
+ void DumpStrings(MCObjectStreamer *Streamer) override;
+ void DumpTypeInfo(MCObjectStreamer *Streamer, UserDefinedDwarfTypesBuilder *TypeBuilder) override;
+
+private:
+ PrimitiveTypeFlags Type;
+};
+
+class DwarfEnumTypeInfo;
+
+class DwarfEnumerator : public DwarfInfo
+{
+public:
+ DwarfEnumerator(const EnumRecordTypeDescriptor &Descriptor, DwarfEnumTypeInfo *TypeInfo) :
+ Name(Descriptor.Name), Value(Descriptor.Value), EnumTypeInfo(TypeInfo) {}
+
+protected:
+ void DumpStrings(MCObjectStreamer *Streamer) override;
+ void DumpTypeInfo(MCObjectStreamer *Streamer, UserDefinedDwarfTypesBuilder *TypeBuilder) override;
+
+private:
+ std::string Name;
+ uint64 Value;
+ DwarfEnumTypeInfo *EnumTypeInfo;
+};
+
+class DwarfEnumTypeInfo : public DwarfInfo
+{
+public:
+ DwarfEnumTypeInfo(const EnumTypeDescriptor &TypeDescriptor,
+ const EnumRecordTypeDescriptor *TypeRecords);
+
+ void Dump(UserDefinedDwarfTypesBuilder *TypeBuilder, MCObjectStreamer *Streamer,
+ MCSection *TypeSection, MCSection *StrSection) override;
+
+ void DumpTypes(UserDefinedDwarfTypesBuilder *TypeBuilder, MCObjectStreamer *Streamer,
+ MCSection *TypeSection, MCSection *StrSection) override;
+
+ uint8_t GetByteSize() const { return ByteSize; }
+
+protected:
+ void DumpStrings(MCObjectStreamer *Streamer) override;
+ void DumpTypeInfo(MCObjectStreamer *Streamer, UserDefinedDwarfTypesBuilder *TypeBuilder) override;
+
+private:
+ std::string Name;
+ uint32_t ElementType;
+ std::vector<DwarfEnumerator> Records;
+ uint8_t ByteSize;
+};
+
+class DwarfDataField : public DwarfInfo
+{
+public:
+ DwarfDataField(const DataFieldDescriptor &Descriptor) :
+ Name(Descriptor.Name),
+ TypeIndex(Descriptor.FieldTypeIndex),
+ Offset(Descriptor.Offset) {}
+
+ void DumpTypes(UserDefinedDwarfTypesBuilder *TypeBuilder, MCObjectStreamer *Streamer,
+ MCSection *TypeSection, MCSection *StrSection) override;
+
+ uint32_t GetTypeIndex() const { return TypeIndex; }
+
+ const std::string &GetName() const { return Name; }
+
+protected:
+ void DumpStrings(MCObjectStreamer *Streamer) override;
+ void DumpTypeInfo(MCObjectStreamer *Streamer, UserDefinedDwarfTypesBuilder *TypeBuilder) override;
+
+ std::string Name;
+ uint32_t TypeIndex;
+ uint64 Offset;
+};
+
+class DwarfStaticDataField : public DwarfDataField
+{
+public:
+ DwarfStaticDataField(const DataFieldDescriptor &Descriptor,
+ const StaticDataFieldDescriptor &StaticDescriptor) :
+ DwarfDataField(Descriptor),
+ StaticDataName(StaticDescriptor.StaticDataName),
+ StaticOffset(StaticDescriptor.StaticOffset),
+ StaticDataInObject(StaticDescriptor.IsStaticDataInObject) {}
+
+ const std::string &GetStaticDataName() const { return StaticDataName; }
+ uint64 GetStaticOffset() const { return StaticOffset; }
+ bool IsStaticDataInObject() const { return StaticDataInObject; }
+
+protected:
+ void DumpTypeInfo(MCObjectStreamer *Streamer, UserDefinedDwarfTypesBuilder *TypeBuilder) override;
+
+private:
+ std::string StaticDataName;
+ uint64 StaticOffset;
+ bool StaticDataInObject;
+};
+
+class DwarfMemberFunctionIdTypeInfo;
+
+class DwarfClassTypeInfo : public DwarfInfo
+{
+public:
+ DwarfClassTypeInfo(const ClassTypeDescriptor &ClassDescriptor) :
+ Name(ClassDescriptor.Name),
+ IsStruct(ClassDescriptor.IsStruct),
+ BaseClassId(ClassDescriptor.BaseClassId),
+ Size(ClassDescriptor.InstanceSize),
+ IsForwardDecl(true) {}
+
+ DwarfClassTypeInfo(const ClassTypeDescriptor &ClassDescriptor,
+ const ClassFieldsTypeDescriptior &ClassFieldsDescriptor,
+ const DataFieldDescriptor *FieldsDescriptors,
+ const StaticDataFieldDescriptor *StaticsDescriptors);
+
+ void Dump(UserDefinedDwarfTypesBuilder *TypeBuilder, MCObjectStreamer *Streamer,
+ MCSection *TypeSection, MCSection *StrSection) override;
+
+ void DumpTypes(UserDefinedDwarfTypesBuilder *TypeBuilder, MCObjectStreamer *Streamer,
+ MCSection *TypeSection, MCSection *StrSection) override;
+
+ void AddMemberFunction(DwarfMemberFunctionIdTypeInfo* TypeInfo) {
+ MemberFunctions.push_back(TypeInfo);
+ }
+
+ const std::vector<DwarfStaticDataField> &GetStaticFields() const { return StaticFields; }
+
+ const std::string &GetName() const { return Name; }
+
+protected:
+ void DumpStrings(MCObjectStreamer *Streamer) override;
+ void DumpTypeInfo(MCObjectStreamer *Streamer, UserDefinedDwarfTypesBuilder *TypeBuilder) override;
+
+private:
+ std::string Name;
+ bool IsStruct;
+ uint32_t BaseClassId;
+ uint64 Size;
+ bool IsForwardDecl;
+ std::vector<DwarfDataField> Fields;
+ std::vector<DwarfStaticDataField> StaticFields;
+ std::vector<DwarfMemberFunctionIdTypeInfo*> MemberFunctions;
+};
+
+class DwarfSimpleArrayTypeInfo : public DwarfInfo
+{
+public:
+ DwarfSimpleArrayTypeInfo(uint32_t ArrayElementType, uint64_t Size) :
+ ElementType(ArrayElementType),
+ Size(Size) {}
+
+ void DumpTypes(UserDefinedDwarfTypesBuilder *TypeBuilder, MCObjectStreamer *Streamer,
+ MCSection *TypeSection, MCSection *StrSection) override;
+
+protected:
+ void DumpStrings(MCObjectStreamer *Streamer) override;
+ void DumpTypeInfo(MCObjectStreamer *Streamer, UserDefinedDwarfTypesBuilder *TypeBuilder) override;
+
+private:
+ uint32_t ElementType;
+ uint64_t Size;
+};
+
+class DwarfPointerTypeInfo : public DwarfInfo
+{
+public:
+ DwarfPointerTypeInfo(const PointerTypeDescriptor& PointerDescriptor) :
+ TypeDesc(PointerDescriptor) {}
+
+ void DumpTypes(UserDefinedDwarfTypesBuilder *TypeBuilder, MCObjectStreamer *Streamer,
+ MCSection *TypeSection, MCSection *StrSection) override;
+
+protected:
+ void DumpStrings(MCObjectStreamer *Streamer) override;
+ void DumpTypeInfo(MCObjectStreamer *Streamer, UserDefinedDwarfTypesBuilder *TypeBuilder) override;
+
+private:
+ PointerTypeDescriptor TypeDesc;
+};
+
+class DwarfMemberFunctionTypeInfo : public DwarfInfo
+{
+public:
+ DwarfMemberFunctionTypeInfo(const MemberFunctionTypeDescriptor& MemberDescriptor,
+ uint32_t const *const ArgumentTypes,
+ bool IsStaticMethod);
+
+ const std::vector<uint32_t> &GetArgTypes() const { return ArgumentTypes; }
+
+ bool IsStatic() const { return IsStaticMethod; }
+
+ uint32_t GetReturnTypeIndex() const { return TypeDesc.ReturnType; }
+
+ uint32_t GetThisPtrTypeIndex() const { return TypeDesc.TypeIndexOfThisPointer; }
+
+protected:
+ void DumpStrings(MCObjectStreamer *Streamer) override;
+ void DumpTypeInfo(MCObjectStreamer *Streamer, UserDefinedDwarfTypesBuilder *TypeBuilder) override;
+
+private:
+ MemberFunctionTypeDescriptor TypeDesc;
+ std::vector<uint32_t> ArgumentTypes;
+ bool IsStaticMethod;
+};
+
+class DwarfMemberFunctionIdTypeInfo : public DwarfInfo
+{
+public:
+ DwarfMemberFunctionIdTypeInfo(const MemberFunctionIdTypeDescriptor& MemberIdDescriptor,
+ DwarfMemberFunctionTypeInfo *TypeInfo) :
+ LinkageName(MemberIdDescriptor.Name),
+ Name(MemberIdDescriptor.Name),
+ ParentClass(MemberIdDescriptor.ParentClass),
+ MemberFunctionTypeInfo(TypeInfo),
+ LinkageNameSymbol(nullptr) {}
+
+ const std::vector<uint32_t> &GetArgTypes() const { return MemberFunctionTypeInfo->GetArgTypes(); }
+
+ void SetLinkageName(const char *Name) { LinkageName = Name; }
+
+ void DumpTypes(UserDefinedDwarfTypesBuilder *TypeBuilder, MCObjectStreamer *Streamer,
+ MCSection *TypeSection, MCSection *StrSection) override;
+
+ bool IsStatic() const { return MemberFunctionTypeInfo->IsStatic(); }
+
+protected:
+ void DumpStrings(MCObjectStreamer *Streamer) override;
+ void DumpTypeInfo(MCObjectStreamer *Streamer, UserDefinedDwarfTypesBuilder *TypeBuilder) override;
+
+private:
+ std::string LinkageName;
+ std::string Name;
+ uint32_t ParentClass;
+ DwarfMemberFunctionTypeInfo *MemberFunctionTypeInfo;
+ MCSymbol *LinkageNameSymbol;
+};
+
+template<class T>
+class EnumHash
+{
+ typedef typename std::underlying_type<T>::type enumType;
+public:
+ size_t operator()(const T& elem) const {
+ return std::hash<enumType>()(static_cast<enumType>(elem));
+ }
+};
+
+class UserDefinedDwarfTypesBuilder : public UserDefinedTypesBuilder
+{
+public:
+ UserDefinedDwarfTypesBuilder() {}
+ void EmitTypeInformation(MCSection *TypeSection, MCSection *StrSection = nullptr) override;
+
+ unsigned GetEnumTypeIndex(const EnumTypeDescriptor &TypeDescriptor,
+ const EnumRecordTypeDescriptor *TypeRecords) override;
+ unsigned GetClassTypeIndex(const ClassTypeDescriptor &ClassDescriptor) override;
+ unsigned GetCompleteClassTypeIndex(
+ const ClassTypeDescriptor &ClassDescriptor,
+ const ClassFieldsTypeDescriptior &ClassFieldsDescriptor,
+ const DataFieldDescriptor *FieldsDescriptors,
+ const StaticDataFieldDescriptor *StaticsDescriptors) override;
+
+ unsigned GetArrayTypeIndex(const ClassTypeDescriptor &ClassDescriptor,
+ const ArrayTypeDescriptor &ArrayDescriptor) override;
+
+ unsigned GetPointerTypeIndex(const PointerTypeDescriptor& PointerDescriptor) override;
+
+ unsigned GetMemberFunctionTypeIndex(const MemberFunctionTypeDescriptor& MemberDescriptor,
+ uint32_t const *const ArgumentTypes) override;
+
+ unsigned GetMemberFunctionId(const MemberFunctionIdTypeDescriptor& MemberIdDescriptor) override;
+
+ unsigned GetPrimitiveTypeIndex(PrimitiveTypeFlags Type) override;
+
+ DwarfInfo *GetTypeInfoByIndex(unsigned Index) const { return DwarfTypes[TypeIndexToArrayIndex(Index)].get(); }
+
+ unsigned GetSimpleArrayTypeIndex(unsigned ElemIndex, unsigned Size);
+
+ const std::vector<DwarfClassTypeInfo*> &GetClassesWithStaticFields() const { return ClassesWithStaticFields; }
+
+private:
+ static const unsigned StartTypeIndex = 1; // Make TypeIndex 0 - Invalid
+ static unsigned TypeIndexToArrayIndex(unsigned TypeIndex) { return TypeIndex - StartTypeIndex; }
+ static unsigned ArrayIndexToTypeIndex(unsigned ArrayIndex) { return ArrayIndex + StartTypeIndex; }
+
+ std::vector<std::unique_ptr<DwarfInfo>> DwarfTypes;
+ std::unordered_map<PrimitiveTypeFlags, uint32_t, EnumHash<PrimitiveTypeFlags>> PrimitiveDwarfTypes;
+ // map[ElemTypeIndex][Size] -> ArrTypeIndex
+ std::unordered_map<uint32_t, std::unordered_map<uint32_t, uint32_t>> SimpleArrayDwarfTypes;
+
+ std::vector<DwarfClassTypeInfo*> ClassesWithStaticFields;
+}; \ No newline at end of file
diff --git a/src/Native/ObjWriter/debugInfo/typeBuilder.h b/src/Native/ObjWriter/debugInfo/typeBuilder.h
new file mode 100644
index 000000000..f3e3046e5
--- /dev/null
+++ b/src/Native/ObjWriter/debugInfo/typeBuilder.h
@@ -0,0 +1,158 @@
+//===---- typeBuilder.h -----------------------------------------*- C++ -*-===//
+//
+// type builder is used to convert .Net types into debuginfo.
+//
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+//
+//===----------------------------------------------------------------------===//
+
+#pragma once
+
+#include "llvm/MC/MCObjectStreamer.h"
+
+#include <string>
+#include <vector>
+
+using namespace llvm;
+
+// Keep in sync with Internal.TypeSystem.TypeFlags (Common/src/TypeSystem/Common/TypeFlags.cs)
+enum class PrimitiveTypeFlags {
+ Unknown = 0x00,
+ Void = 0x01,
+ Boolean = 0x02,
+ Char = 0x03,
+ SByte = 0x04,
+ Byte = 0x05,
+ Int16 = 0x06,
+ UInt16 = 0x07,
+ Int32 = 0x08,
+ UInt32 = 0x09,
+ Int64 = 0x0A,
+ UInt64 = 0x0B,
+ IntPtr = 0x0C,
+ UIntPtr = 0x0D,
+ Single = 0x0E,
+ Double = 0x0F
+};
+
+typedef unsigned long long uint64;
+
+#pragma pack(push, 8)
+
+extern "C" struct EnumRecordTypeDescriptor {
+ uint64 Value;
+ const char *Name;
+};
+
+extern "C" struct EnumTypeDescriptor {
+ uint32_t ElementType;
+ uint64 ElementCount;
+ const char *Name;
+};
+
+extern "C" struct ClassTypeDescriptor {
+ int32_t IsStruct;
+ const char *Name;
+ uint32_t BaseClassId;
+ uint64 InstanceSize;
+};
+
+extern "C" struct DataFieldDescriptor {
+ uint32_t FieldTypeIndex;
+ uint64 Offset;
+ const char *Name;
+};
+
+extern "C" struct StaticDataFieldDescriptor {
+ const char *StaticDataName;
+ uint64 StaticOffset;
+ int IsStaticDataInObject;
+};
+
+extern "C" struct ClassFieldsTypeDescriptior {
+ uint64 Size;
+ int32_t FieldsCount;
+};
+
+extern "C" struct ArrayTypeDescriptor {
+ uint32_t Rank;
+ uint32_t ElementType;
+ uint32_t Size; // ElementSize
+ int32_t IsMultiDimensional;
+};
+
+extern "C" struct PointerTypeDescriptor {
+ uint32_t ElementType;
+ int32_t IsReference;
+ int32_t IsConst;
+ int32_t Is64Bit;
+};
+
+extern "C" struct MemberFunctionTypeDescriptor {
+ uint32_t ReturnType;
+ uint32_t ContainingClass;
+ uint32_t TypeIndexOfThisPointer;
+ int32_t ThisAdjust;
+ uint32_t CallingConvention;
+ uint16_t NumberOfArguments;
+};
+
+extern "C" struct MemberFunctionIdTypeDescriptor {
+ uint32_t MemberFunction;
+ uint32_t ParentClass;
+ const char *Name;
+};
+
+#pragma pack(pop)
+class UserDefinedTypesBuilder {
+public:
+ UserDefinedTypesBuilder() : Streamer(nullptr), TargetPointerSize(0) {}
+ virtual ~UserDefinedTypesBuilder() {}
+ void SetStreamer(MCObjectStreamer *Streamer) {
+ assert(this->Streamer == nullptr);
+ assert(Streamer != nullptr);
+ this->Streamer = Streamer;
+ }
+ MCObjectStreamer *GetStreamer() const {
+ return Streamer;
+ }
+ void SetTargetPointerSize(unsigned TargetPointerSize) {
+ assert(this->TargetPointerSize == 0);
+ assert(TargetPointerSize != 0);
+ this->TargetPointerSize = TargetPointerSize;
+ }
+ virtual void EmitTypeInformation(MCSection *TypeSection, MCSection *StrSection = nullptr) = 0;
+
+ virtual unsigned GetEnumTypeIndex(const EnumTypeDescriptor &TypeDescriptor,
+ const EnumRecordTypeDescriptor *TypeRecords) = 0;
+ virtual unsigned GetClassTypeIndex(const ClassTypeDescriptor &ClassDescriptor) = 0;
+ virtual unsigned GetCompleteClassTypeIndex(
+ const ClassTypeDescriptor &ClassDescriptor,
+ const ClassFieldsTypeDescriptior &ClassFieldsDescriptor,
+ const DataFieldDescriptor *FieldsDescriptors,
+ const StaticDataFieldDescriptor *StaticsDescriptors) = 0;
+
+ virtual unsigned GetArrayTypeIndex(const ClassTypeDescriptor &ClassDescriptor,
+ const ArrayTypeDescriptor &ArrayDescriptor) = 0;
+
+ virtual unsigned GetPointerTypeIndex(const PointerTypeDescriptor& PointerDescriptor) = 0;
+
+ virtual unsigned GetMemberFunctionTypeIndex(const MemberFunctionTypeDescriptor& MemberDescriptor,
+ uint32_t const *const ArgumentTypes) = 0;
+
+ virtual unsigned GetMemberFunctionId(const MemberFunctionIdTypeDescriptor& MemberIdDescriptor) = 0;
+
+ virtual unsigned GetPrimitiveTypeIndex(PrimitiveTypeFlags Type) = 0;
+
+ virtual const std::vector<std::pair<std::string, uint32_t>> &GetUDTs() {
+ return UserDefinedTypes;
+ }
+
+protected:
+ MCObjectStreamer *Streamer;
+ unsigned TargetPointerSize;
+
+ std::vector<std::pair<std::string, uint32_t>> UserDefinedTypes;
+}; \ No newline at end of file
diff --git a/src/Native/ObjWriter/jitDebugInfo.h b/src/Native/ObjWriter/jitDebugInfo.h
index 103dff8ad..ec63c3dfb 100644
--- a/src/Native/ObjWriter/jitDebugInfo.h
+++ b/src/Native/ObjWriter/jitDebugInfo.h
@@ -26,6 +26,18 @@ struct DebugVarInfo {
: Name(ArgName), TypeIndex(ArgTypeIndex), IsParam(ArgIsParam) {}
};
+struct DebugEHClauseInfo {
+ unsigned TryOffset;
+ unsigned TryLength;
+ unsigned HandlerOffset;
+ unsigned HandlerLength;
+
+ DebugEHClauseInfo(unsigned TryOffset, unsigned TryLength,
+ unsigned HandlerOffset, unsigned HandlerLength) :
+ TryOffset(TryOffset), TryLength(TryLength),
+ HandlerOffset(HandlerOffset), HandlerLength(HandlerLength) {}
+};
+
typedef unsigned short CVRegMapping;
#define CVREGDAT(p2, cv) cv
diff --git a/src/Native/ObjWriter/llvm.patch b/src/Native/ObjWriter/llvm.patch
index fd8420125..67ae23ec9 100644
--- a/src/Native/ObjWriter/llvm.patch
+++ b/src/Native/ObjWriter/llvm.patch
@@ -15,7 +15,7 @@ index 7c1189e..d1d77c9 100644
/// can change its size during relaxation.
virtual void EmitInstToFragment(const MCInst &Inst, const MCSubtargetInfo &);
diff --git a/include/llvm/MC/MCStreamer.h b/include/llvm/MC/MCStreamer.h
-index 5390e79..e28a3cc 100644
+index 5390e79..5b258e7 100644
--- a/include/llvm/MC/MCStreamer.h
+++ b/include/llvm/MC/MCStreamer.h
@@ -115,6 +115,7 @@ public:
@@ -26,6 +26,16 @@ index 5390e79..e28a3cc 100644
virtual void emitUnwindRaw(int64_t StackOffset,
const SmallVectorImpl<uint8_t> &Opcodes);
+@@ -548,6 +549,9 @@ public:
+ /// etc.
+ virtual void EmitBytes(StringRef Data);
+
++ /// \brief Emit the given \p Instruction data into the current section.
++ virtual void EmitInstructionBytes(StringRef Data);
++
+ /// Functionally identical to EmitBytes. When emitting textual assembly, this
+ /// method uses .byte directives instead of .ascii or .asciz for readability.
+ virtual void EmitBinaryData(StringRef Data);
diff --git a/lib/MC/MCObjectStreamer.cpp b/lib/MC/MCObjectStreamer.cpp
index 174397e..ef7161f 100644
--- a/lib/MC/MCObjectStreamer.cpp
@@ -57,6 +67,18 @@ index 174397e..ef7161f 100644
void MCObjectStreamer::EmitCFIStartProcImpl(MCDwarfFrameInfo &Frame) {
// We need to create a local symbol to avoid relocations.
Frame.Begin = getContext().createTempSymbol();
+diff --git a/lib/MC/MCStreamer.cpp b/lib/MC/MCStreamer.cpp
+index 2bfb9a6..a710098 100644
+--- a/lib/MC/MCStreamer.cpp
++++ b/lib/MC/MCStreamer.cpp
+@@ -830,6 +830,7 @@ void MCStreamer::EmitTBSSSymbol(MCSection *Section, MCSymbol *Symbol,
+ void MCStreamer::ChangeSection(MCSection *, const MCExpr *) {}
+ void MCStreamer::EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol) {}
+ void MCStreamer::EmitBytes(StringRef Data) {}
++void MCStreamer::EmitInstructionBytes(StringRef Data) { EmitBytes(Data); }
+ void MCStreamer::EmitBinaryData(StringRef Data) { EmitBytes(Data); }
+ void MCStreamer::EmitValueImpl(const MCExpr *Value, unsigned Size, SMLoc Loc) {
+ visitUsedExpr(*Value);
diff --git a/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp b/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp
index a77df7a..e1aa752 100644
--- a/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp
@@ -122,7 +144,7 @@ index 59f31be..9b95598 100644
case ARM::fixup_arm_uncondbl:
switch (Modifier) {
diff --git a/lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp b/lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp
-index 93f4006..67ae439 100644
+index 93f4006..81e4caa 100644
--- a/lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp
+++ b/lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp
@@ -396,6 +396,7 @@ private:
@@ -141,7 +163,26 @@ index 93f4006..67ae439 100644
void emitUnwindRaw(int64_t Offset, const SmallVectorImpl<uint8_t> &Opcodes);
void ChangeSection(MCSection *Section, const MCExpr *Subsection) override {
-@@ -698,6 +700,7 @@ private:
+@@ -533,6 +535,18 @@ public:
+ MCELFStreamer::EmitBytes(Data);
+ }
+
++ /// This function is the one used to emit instruction data into the ELF
++ /// streamer. We override it to add the appropriate mapping symbol if
++ /// necessary.
++ void EmitInstructionBytes(StringRef Data) override {
++ if (IsThumb)
++ EmitThumbMappingSymbol();
++ else
++ EmitARMMappingSymbol();
++
++ MCELFStreamer::EmitBytes(Data);
++ }
++
+ void FlushPendingMappingSymbol() {
+ if (!LastEMSInfo->hasInfo())
+ return;
+@@ -698,6 +712,7 @@ private:
bool CantUnwind;
SmallVector<uint8_t, 64> Opcodes;
UnwindOpcodeAssembler UnwindOpAsm;
@@ -149,7 +190,7 @@ index 93f4006..67ae439 100644
};
} // end anonymous namespace
-@@ -740,6 +743,10 @@ void ARMTargetELFStreamer::emitRegSave(const SmallVectorImpl<unsigned> &RegList,
+@@ -740,6 +755,10 @@ void ARMTargetELFStreamer::emitRegSave(const SmallVectorImpl<unsigned> &RegList,
getStreamer().emitRegSave(RegList, isVector);
}
@@ -160,7 +201,7 @@ index 93f4006..67ae439 100644
void ARMTargetELFStreamer::emitUnwindRaw(int64_t Offset,
const SmallVectorImpl<uint8_t> &Opcodes) {
getStreamer().emitUnwindRaw(Offset, Opcodes);
-@@ -1233,6 +1240,7 @@ void ARMELFStreamer::EHReset() {
+@@ -1233,6 +1252,7 @@ void ARMELFStreamer::EHReset() {
PendingOffset = 0;
UsedFP = false;
CantUnwind = false;
@@ -168,7 +209,7 @@ index 93f4006..67ae439 100644
Opcodes.clear();
UnwindOpAsm.Reset();
-@@ -1330,6 +1338,8 @@ void ARMELFStreamer::FlushUnwindOpcodes(bool NoHandlerData) {
+@@ -1330,6 +1350,8 @@ void ARMELFStreamer::FlushUnwindOpcodes(bool NoHandlerData) {
}
// Finalize the unwind opcode sequence
@@ -177,7 +218,7 @@ index 93f4006..67ae439 100644
UnwindOpAsm.Finalize(PersonalityIndex, Opcodes);
// For compact model 0, we have to emit the unwind opcodes in the .ARM.exidx
-@@ -1374,7 +1384,13 @@ void ARMELFStreamer::FlushUnwindOpcodes(bool NoHandlerData) {
+@@ -1374,7 +1396,13 @@ void ARMELFStreamer::FlushUnwindOpcodes(bool NoHandlerData) {
//
// In case that the .handlerdata directive is not specified by the
// programmer, we should emit zero to terminate the handler data.
@@ -192,7 +233,7 @@ index 93f4006..67ae439 100644
EmitIntValue(0, 4);
}
-@@ -1457,6 +1473,10 @@ void ARMELFStreamer::emitRegSave(const SmallVectorImpl<unsigned> &RegList,
+@@ -1457,6 +1485,10 @@ void ARMELFStreamer::emitRegSave(const SmallVectorImpl<unsigned> &RegList,
UnwindOpAsm.EmitRegSave(Mask);
}
diff --git a/src/Native/ObjWriter/llvmCap/CMakeLists.txt b/src/Native/ObjWriter/llvmCap/CMakeLists.txt
index a749ea878..07dca10e9 100644
--- a/src/Native/ObjWriter/llvmCap/CMakeLists.txt
+++ b/src/Native/ObjWriter/llvmCap/CMakeLists.txt
@@ -116,14 +116,32 @@ ExternalProject_Add(LLVM
ExternalProject_Get_Property(LLVM source_dir)
set(LLVM_SOURCE_DIR ${source_dir})
ExternalProject_Add_Step(LLVM PatchingLLVM
- COMMAND git apply --3way ${OBJWRITER_ROOT}/llvm.patch COMMENT "Applying LLVM patch with ObjWriter fixes"
+ COMMAND git checkout -- .
+ COMMAND git apply ${OBJWRITER_ROOT}/llvm.patch COMMENT "Applying LLVM patch with ObjWriter fixes"
WORKING_DIRECTORY ${LLVM_SOURCE_DIR}
DEPENDEES patch
USES_TERMINAL 1
)
+
+if(CMAKE_HOST_WIN32)
+ExternalProject_Add_Step(LLVM ObjWriterInjection
+ COMMAND ${CMAKE_COMMAND} -E copy_directory ${OBJWRITER_ROOT} ${OBJWRITER_LLVM_POINT} COMMENT "copy ${OBJWRITER_ROOT} -> ${OBJWRITER_LLVM_POINT}"
+ WORKING_DIRECTORY ${LLVM_SOURCE_DIR}
+ DEPENDEES patch
+ USES_TERMINAL 1
+ )
+else()
ExternalProject_Add_Step(LLVM ObjWriterInjection
COMMAND ${CMAKE_COMMAND} -E create_symlink ${OBJWRITER_ROOT} ${OBJWRITER_LLVM_POINT} COMMENT "mklink ${OBJWRITER_ROOT} -> ${OBJWRITER_LLVM_POINT}"
WORKING_DIRECTORY ${LLVM_SOURCE_DIR}
DEPENDEES patch
USES_TERMINAL 1
)
+endif()
+
+ExternalProject_Add_Step(LLVM forceconfigure
+ COMMAND ${CMAKE_COMMAND} -E echo "Force configure of LLVM"
+ DEPENDEES update
+ DEPENDERS configure
+ ALWAYS 1
+ )
diff --git a/src/Native/ObjWriter/objwriter.cpp b/src/Native/ObjWriter/objwriter.cpp
index 55f79aa47..bdf1016dc 100644
--- a/src/Native/ObjWriter/objwriter.cpp
+++ b/src/Native/ObjWriter/objwriter.cpp
@@ -1,10 +1,10 @@
-//===---- objwriter.cpp --------------------------------*- C++ -*-===//
+//===---- objwriter.cpp -----------------------------------------*- C++ -*-===//
//
// object writer
//
-// Copyright (c) Microsoft. All rights reserved.
-// Licensed under the MIT license.
-// See LICENSE file in the project root for full license information.
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
//
//===----------------------------------------------------------------------===//
///
@@ -14,6 +14,8 @@
//===----------------------------------------------------------------------===//
#include "objwriter.h"
+#include "debugInfo/dwarf/dwarfTypeBuilder.h"
+#include "debugInfo/codeView/codeViewTypeBuilder.h"
#include "llvm/DebugInfo/CodeView/CodeView.h"
#include "llvm/DebugInfo/CodeView/Line.h"
#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
@@ -162,9 +164,18 @@ bool ObjectWriter::Init(llvm::StringRef ObjectFilePath) {
SetCodeSectionAttribute("text", CustomSectionAttributes_Executable, nullptr);
if (ObjFileInfo->getObjectFileType() == ObjFileInfo->IsCOFF) {
- TypeBuilder.SetStreamer(Streamer);
- unsigned TargetPointerSize = AssemblerPrinter->getPointerSize();
- TypeBuilder.SetTargetPointerSize(TargetPointerSize);
+ TypeBuilder.reset(new UserDefinedCodeViewTypesBuilder());
+ } else {
+ TypeBuilder.reset(new UserDefinedDwarfTypesBuilder());
+ }
+
+ TypeBuilder->SetStreamer(Streamer);
+ unsigned TargetPointerSize = AssemblerPrinter->getPointerSize();
+ TypeBuilder->SetTargetPointerSize(TargetPointerSize);
+
+ if (ObjFileInfo->getObjectFileType() == ObjFileInfo->IsELF) {
+ DwarfGenerator.reset(new DwarfGen());
+ DwarfGenerator->SetTypeBuilder(static_cast<UserDefinedDwarfTypesBuilder*>(TypeBuilder.get()));
}
return true;
@@ -294,7 +305,11 @@ void ObjectWriter::EmitAlignment(int ByteAlignment) {
}
void ObjectWriter::EmitBlob(int BlobSize, const char *Blob) {
- Streamer->EmitBytes(StringRef(Blob, BlobSize));
+ if (Streamer->getCurrentSectionOnly()->getKind().isText()) {
+ Streamer->EmitInstructionBytes(StringRef(Blob, BlobSize));
+ } else {
+ Streamer->EmitBytes(StringRef(Blob, BlobSize));
+ }
}
void ObjectWriter::EmitIntValue(uint64_t Value, unsigned Size) {
@@ -690,6 +705,22 @@ void ObjectWriter::EmitCVDebugFunctionInfo(const char *FunctionName,
Streamer->EmitCVLinetableDirective(FuncId++, Fn, FnEnd);
}
+void ObjectWriter::EmitDwarfFunctionInfo(const char *FunctionName,
+ int FunctionSize,
+ unsigned MethodTypeIndex) {
+ if (FuncId == 1) {
+ DwarfGenerator->EmitCompileUnit();
+ }
+
+ DwarfGenerator->EmitSubprogramInfo(FunctionName, FunctionSize,
+ MethodTypeIndex, DebugVarInfos, DebugEHClauseInfos);
+
+ DebugVarInfos.clear();
+ DebugEHClauseInfos.clear();
+
+ FuncId++;
+}
+
void ObjectWriter::EmitDebugFileInfo(int FileId, const char *FileName) {
assert(FileId > 0 && "FileId should be greater than 0.");
if (ObjFileInfo->getObjectFileType() == ObjFileInfo->IsCOFF) {
@@ -700,7 +731,8 @@ void ObjectWriter::EmitDebugFileInfo(int FileId, const char *FileName) {
}
void ObjectWriter::EmitDebugFunctionInfo(const char *FunctionName,
- int FunctionSize) {
+ int FunctionSize,
+ unsigned MethodTypeIndex) {
if (ObjFileInfo->getObjectFileType() == ObjFileInfo->IsCOFF) {
Streamer->EmitCVFuncIdDirective(FuncId);
EmitCVDebugFunctionInfo(FunctionName, FunctionSize);
@@ -710,6 +742,7 @@ void ObjectWriter::EmitDebugFunctionInfo(const char *FunctionName,
Streamer->EmitSymbolAttribute(Sym, MCSA_ELF_TypeFunction);
Streamer->emitELFSize(Sym,
MCConstantExpr::create(FunctionSize, *OutContext));
+ EmitDwarfFunctionInfo(FunctionName, FunctionSize, MethodTypeIndex);
}
// TODO: Should test it for Macho.
}
@@ -729,6 +762,13 @@ void ObjectWriter::EmitDebugVar(char *Name, int TypeIndex, bool IsParm,
DebugVarInfos.push_back(NewVar);
}
+void ObjectWriter::EmitDebugEHClause(unsigned TryOffset, unsigned TryLength,
+ unsigned HandlerOffset, unsigned HandlerLength) {
+ if (ObjFileInfo->getObjectFileType() == ObjFileInfo->IsELF) {
+ DebugEHClauseInfos.emplace_back(TryOffset, TryLength, HandlerOffset, HandlerLength);
+ }
+}
+
void ObjectWriter::EmitDebugLoc(int NativeOffset, int FileId, int LineNumber,
int ColNumber) {
assert(FileId > 0 && "FileId should be greater than 0.");
@@ -742,7 +782,7 @@ void ObjectWriter::EmitDebugLoc(int NativeOffset, int FileId, int LineNumber,
}
void ObjectWriter::EmitCVUserDefinedTypesSymbols() {
- const auto &UDTs = TypeBuilder.GetUDTs();
+ const auto &UDTs = TypeBuilder->GetUDTs();
if (UDTs.empty()) {
return;
}
@@ -755,12 +795,12 @@ void ObjectWriter::EmitCVUserDefinedTypesSymbols() {
EmitLabelDiff(SymbolsBegin, SymbolsEnd);
Streamer->EmitLabel(SymbolsBegin);
- for (const std::pair<std::string, codeview::TypeIndex> &UDT : UDTs) {
+ for (const std::pair<std::string, uint32_t> &UDT : UDTs) {
unsigned NameLength = UDT.first.length() + 1;
unsigned RecordLength = 2 + 4 + NameLength;
Streamer->EmitIntValue(RecordLength, 2);
Streamer->EmitIntValue(unsigned(SymbolKind::S_UDT), 2);
- Streamer->EmitIntValue(UDT.second.getIndex(), 4);
+ Streamer->EmitIntValue(UDT.second, 4);
Streamer->EmitBytes(StringRef(UDT.first.c_str(), NameLength));
}
Streamer->EmitLabel(SymbolsEnd);
@@ -769,7 +809,7 @@ void ObjectWriter::EmitCVUserDefinedTypesSymbols() {
void ObjectWriter::EmitDebugModuleInfo() {
if (ObjFileInfo->getObjectFileType() == ObjFileInfo->IsCOFF) {
- TypeBuilder.EmitTypeInformation(ObjFileInfo->getCOFFDebugTypesSection());
+ TypeBuilder->EmitTypeInformation(ObjFileInfo->getCOFFDebugTypesSection());
EmitCVUserDefinedTypesSymbols();
}
@@ -783,6 +823,10 @@ void ObjectWriter::EmitDebugModuleInfo() {
Streamer->SwitchSection(Section);
Streamer->EmitCVFileChecksumsDirective();
Streamer->EmitCVStringTableDirective();
+ } else if (ObjFileInfo->getObjectFileType() == ObjFileInfo->IsELF) {
+ DwarfGenerator->EmitAbbrev();
+ DwarfGenerator->EmitAranges();
+ DwarfGenerator->Finish();
} else {
OutContext->setGenDwarfForAssembly(true);
}
@@ -791,56 +835,50 @@ void ObjectWriter::EmitDebugModuleInfo() {
unsigned
ObjectWriter::GetEnumTypeIndex(const EnumTypeDescriptor &TypeDescriptor,
const EnumRecordTypeDescriptor *TypeRecords) {
- assert(ObjFileInfo->getObjectFileType() == ObjFileInfo->IsCOFF &&
- "only COFF is supported now");
- return TypeBuilder.GetEnumTypeIndex(TypeDescriptor, TypeRecords);
+ return TypeBuilder->GetEnumTypeIndex(TypeDescriptor, TypeRecords);
}
unsigned
ObjectWriter::GetClassTypeIndex(const ClassTypeDescriptor &ClassDescriptor) {
- assert(ObjFileInfo->getObjectFileType() == ObjFileInfo->IsCOFF &&
- "only COFF is supported now");
- return TypeBuilder.GetClassTypeIndex(ClassDescriptor);
+ unsigned res = TypeBuilder->GetClassTypeIndex(ClassDescriptor);
+ return res;
}
unsigned ObjectWriter::GetCompleteClassTypeIndex(
const ClassTypeDescriptor &ClassDescriptor,
const ClassFieldsTypeDescriptior &ClassFieldsDescriptor,
- const DataFieldDescriptor *FieldsDescriptors) {
- assert(ObjFileInfo->getObjectFileType() == ObjFileInfo->IsCOFF &&
- "only COFF is supported now");
- return TypeBuilder.GetCompleteClassTypeIndex(
- ClassDescriptor, ClassFieldsDescriptor, FieldsDescriptors);
+ const DataFieldDescriptor *FieldsDescriptors,
+ const StaticDataFieldDescriptor *StaticsDescriptors) {
+ unsigned res = TypeBuilder->GetCompleteClassTypeIndex(ClassDescriptor,
+ ClassFieldsDescriptor, FieldsDescriptors, StaticsDescriptors);
+ return res;
}
unsigned
ObjectWriter::GetArrayTypeIndex(const ClassTypeDescriptor &ClassDescriptor,
const ArrayTypeDescriptor &ArrayDescriptor) {
- assert(ObjFileInfo->getObjectFileType() == ObjFileInfo->IsCOFF &&
- "only COFF is supported now");
- return TypeBuilder.GetArrayTypeIndex(ClassDescriptor, ArrayDescriptor);
+ return TypeBuilder->GetArrayTypeIndex(ClassDescriptor, ArrayDescriptor);
}
unsigned
ObjectWriter::GetPointerTypeIndex(const PointerTypeDescriptor& PointerDescriptor) {
- assert(ObjFileInfo->getObjectFileType() == ObjFileInfo->IsCOFF &&
- "only COFF is supported now");
- return TypeBuilder.GetPointerTypeIndex(PointerDescriptor);
+ return TypeBuilder->GetPointerTypeIndex(PointerDescriptor);
}
unsigned
ObjectWriter::GetMemberFunctionTypeIndex(const MemberFunctionTypeDescriptor& MemberDescriptor,
uint32_t const *const ArgumentTypes) {
- assert(ObjFileInfo->getObjectFileType() == ObjFileInfo->IsCOFF &&
- "only COFF is supported now");
- return TypeBuilder.GetMemberFunctionTypeIndex(MemberDescriptor, ArgumentTypes);
+ return TypeBuilder->GetMemberFunctionTypeIndex(MemberDescriptor, ArgumentTypes);
}
unsigned
ObjectWriter::GetMemberFunctionId(const MemberFunctionIdTypeDescriptor& MemberIdDescriptor) {
- assert(ObjFileInfo->getObjectFileType() == ObjFileInfo->IsCOFF &&
- "only COFF is supported now");
- return TypeBuilder.GetMemberFunctionId(MemberIdDescriptor);
+ return TypeBuilder->GetMemberFunctionId(MemberIdDescriptor);
+}
+
+unsigned
+ObjectWriter::GetPrimitiveTypeIndex(int Type) {
+ return TypeBuilder->GetPrimitiveTypeIndex(static_cast<PrimitiveTypeFlags>(Type));
}
void
@@ -883,13 +921,13 @@ void ObjectWriter::EmitARMExIdxCode(int Offset, const char *Blob)
ATS.emitPad(CfiCode->Offset);
break;
case CFI_REL_OFFSET:
- RegList.push_back(CfiCode->DwarfReg);
+ RegList.push_back(CfiCode->DwarfReg + 14); // See ARMRegEncodingTable in ARMGenRegisterInfo.inc by getEncodingValue
ATS.emitRegSave(RegList, false);
break;
case CFI_DEF_CFA_REGISTER:
assert(CfiCode->Offset == 0 &&
"Unexpected Offset Value for OpDefCfaRegister");
- ATS.emitMovSP(CfiCode->DwarfReg, 0);
+ ATS.emitMovSP(CfiCode->DwarfReg + 14, 0); // See ARMRegEncodingTable in ARMGenRegisterInfo.inc by getEncodingValue
break;
default:
assert(false && "Unrecognized CFI");
diff --git a/src/Native/ObjWriter/objwriter.h b/src/Native/ObjWriter/objwriter.h
index 21327b3be..6c1ba8645 100644
--- a/src/Native/ObjWriter/objwriter.h
+++ b/src/Native/ObjWriter/objwriter.h
@@ -1,10 +1,10 @@
-//===---- objwriter.h --------------------------------*- C++ -*-===//
+//===---- objwriter.h ------------------------------------------*- C++ -*-===//
//
// object writer
//
-// Copyright (c) Microsoft. All rights reserved.
-// Licensed under the MIT license.
-// See LICENSE file in the project root for full license information.
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
//
//===----------------------------------------------------------------------===//
@@ -19,7 +19,8 @@
#include "jitDebugInfo.h"
#include <string>
#include <set>
-#include "typeBuilder.h"
+#include "debugInfo/typeBuilder.h"
+#include "debugInfo/dwarf/dwarfGen.h"
using namespace llvm;
using namespace llvm::codeview;
@@ -68,11 +69,13 @@ public:
int EmitSymbolRef(const char *SymbolName, RelocType RelocType, int Delta);
void EmitDebugFileInfo(int FileId, const char *FileName);
- void EmitDebugFunctionInfo(const char *FunctionName, int FunctionSize);
+ void EmitDebugFunctionInfo(const char *FunctionName, int FunctionSize, unsigned MethodTypeIndex);
void EmitDebugVar(char *Name, int TypeIndex, bool IsParm, int RangeCount,
const ICorDebugInfo::NativeVarInfo *Ranges);
void EmitDebugLoc(int NativeOffset, int FileId, int LineNumber,
int ColNumber);
+ void EmitDebugEHClause(unsigned TryOffset, unsigned TryLength,
+ unsigned HandlerOffset, unsigned HandlerLength);
void EmitDebugModuleInfo();
void EmitCFIStart(int Offset);
@@ -86,7 +89,8 @@ public:
unsigned GetCompleteClassTypeIndex(
const ClassTypeDescriptor &ClassDescriptor,
const ClassFieldsTypeDescriptior &ClassFieldsDescriptor,
- const DataFieldDescriptor *FieldsDescriptors);
+ const DataFieldDescriptor *FieldsDescriptors,
+ const StaticDataFieldDescriptor *StaticsDescriptors);
unsigned GetArrayTypeIndex(const ClassTypeDescriptor &ClassDescriptor,
const ArrayTypeDescriptor &ArrayDescriptor);
@@ -98,6 +102,8 @@ public:
unsigned GetMemberFunctionId(const MemberFunctionIdTypeDescriptor& MemberIdDescriptor);
+ unsigned GetPrimitiveTypeIndex(int Type);
+
void EmitARMFnStart();
void EmitARMFnEnd();
void EmitARMExIdxCode(int Offset, const char *Blob);
@@ -114,6 +120,8 @@ private:
int NumVarInfos);
void EmitCVDebugFunctionInfo(const char *FunctionName, int FunctionSize);
+ void EmitDwarfFunctionInfo(const char *FunctionName, int FunctionSize, unsigned MethodTypeIndex);
+
const MCSymbolRefExpr *GetSymbolRefExpr(
const char *SymbolName,
MCSymbolRefExpr::VariantKind Kind = MCSymbolRefExpr::VK_None);
@@ -149,16 +157,18 @@ private:
std::unique_ptr<TargetMachine> TMachine;
std::unique_ptr<AsmPrinter> AssemblerPrinter;
MCAssembler *Assembler; // Owned by MCStreamer
+ std::unique_ptr<DwarfGen> DwarfGenerator;
std::unique_ptr<raw_fd_ostream> OS;
MCTargetOptions TargetMOptions;
bool FrameOpened;
std::vector<DebugVarInfo> DebugVarInfos;
+ std::vector<DebugEHClauseInfo> DebugEHClauseInfos;
std::set<MCSection *> Sections;
int FuncId;
- UserDefinedTypesBuilder TypeBuilder;
+ std::unique_ptr<UserDefinedTypesBuilder> TypeBuilder;
std::string TripleName;
@@ -258,9 +268,10 @@ DLL_EXPORT void EmitDebugFileInfo(ObjectWriter *OW, int FileId,
DLL_EXPORT void EmitDebugFunctionInfo(ObjectWriter *OW,
const char *FunctionName,
- int FunctionSize) {
+ int FunctionSize,
+ unsigned MethodTypeIndex) {
assert(OW && "ObjWriter is null");
- OW->EmitDebugFunctionInfo(FunctionName, FunctionSize);
+ OW->EmitDebugFunctionInfo(FunctionName, FunctionSize, MethodTypeIndex);
}
DLL_EXPORT void EmitDebugVar(ObjectWriter *OW, char *Name, int TypeIndex,
@@ -270,6 +281,13 @@ DLL_EXPORT void EmitDebugVar(ObjectWriter *OW, char *Name, int TypeIndex,
OW->EmitDebugVar(Name, TypeIndex, IsParam, RangeCount, Ranges);
}
+DLL_EXPORT void EmitDebugEHClause(ObjectWriter *OW, unsigned TryOffset,
+ unsigned TryLength, unsigned HandlerOffset,
+ unsigned HandlerLength) {
+ assert(OW && "ObjWriter is null");
+ OW->EmitDebugEHClause(TryOffset, TryLength, HandlerOffset, HandlerLength);
+}
+
DLL_EXPORT void EmitDebugLoc(ObjectWriter *OW, int NativeOffset, int FileId,
int LineNumber, int ColNumber) {
assert(OW && "ObjWriter is null");
@@ -299,10 +317,11 @@ DLL_EXPORT unsigned GetClassTypeIndex(ObjectWriter *OW,
DLL_EXPORT unsigned
GetCompleteClassTypeIndex(ObjectWriter *OW, ClassTypeDescriptor ClassDescriptor,
ClassFieldsTypeDescriptior ClassFieldsDescriptor,
- DataFieldDescriptor *FieldsDescriptors) {
+ DataFieldDescriptor *FieldsDescriptors,
+ StaticDataFieldDescriptor *StaticsDescriptors) {
assert(OW && "ObjWriter is null");
return OW->GetCompleteClassTypeIndex(ClassDescriptor, ClassFieldsDescriptor,
- FieldsDescriptors);
+ FieldsDescriptors, StaticsDescriptors);
}
DLL_EXPORT unsigned GetArrayTypeIndex(ObjectWriter *OW,
@@ -331,6 +350,11 @@ DLL_EXPORT unsigned GetMemberFunctionIdTypeIndex(ObjectWriter *OW,
return OW->GetMemberFunctionId(MemberIdDescriptor);
}
+DLL_EXPORT unsigned GetPrimitiveTypeIndex(ObjectWriter *OW, int Type) {
+ assert(OW && "ObjWriter is null");
+ return OW->GetPrimitiveTypeIndex(Type);
+}
+
DLL_EXPORT void EmitARMFnStart(ObjectWriter *OW) {
assert(OW && "ObjWriter is null");
return OW->EmitARMFnStart();
diff --git a/src/Native/ObjWriter/typeBuilder.h b/src/Native/ObjWriter/typeBuilder.h
deleted file mode 100644
index a5037b769..000000000
--- a/src/Native/ObjWriter/typeBuilder.h
+++ /dev/null
@@ -1,145 +0,0 @@
-//===---- typeBuilder.h --------------------------------*- C++ -*-===//
-//
-// type builder is used to convert .Net types into CodeView descriptors.
-//
-// Copyright (c) Microsoft. All rights reserved.
-// Licensed under the MIT license.
-// See LICENSE file in the project root for full license information.
-//
-//===----------------------------------------------------------------------===//
-
-#pragma once
-
-#include "llvm/DebugInfo/CodeView/TypeTableBuilder.h"
-#include "llvm/MC/MCObjectStreamer.h"
-
-#include <string>
-#include <vector>
-
-using namespace llvm;
-using namespace llvm::codeview;
-
-typedef unsigned long long uint64;
-
-#pragma pack(push, 8)
-
-extern "C" struct EnumRecordTypeDescriptor {
- uint64 Value;
- char *Name;
-};
-
-extern "C" struct EnumTypeDescriptor {
- uint32_t ElementType;
- uint64 ElementCount;
- char *Name;
-};
-
-extern "C" struct ClassTypeDescriptor {
- int32_t IsStruct;
- char *Name;
- uint32_t BaseClassId;
-};
-
-extern "C" struct DataFieldDescriptor {
- uint32_t FieldTypeIndex;
- uint64 Offset;
- char *Name;
-};
-
-extern "C" struct ClassFieldsTypeDescriptior {
- uint64 Size;
- int32_t FieldsCount;
-};
-
-extern "C" struct ArrayTypeDescriptor {
- uint32_t Rank;
- uint32_t ElementType;
- uint32_t Size;
- int32_t IsMultiDimensional;
-};
-
-extern "C" struct PointerTypeDescriptor {
- uint32_t ElementType;
- int32_t IsReference;
- int32_t IsConst;
- int32_t Is64Bit;
-};
-
-extern "C" struct MemberFunctionTypeDescriptor {
- uint32_t ReturnType;
- uint32_t ContainingClass;
- uint32_t TypeIndexOfThisPointer;
- int32_t ThisAdjust;
- uint32_t CallingConvention;
- uint16_t NumberOfArguments;
-};
-
-extern "C" struct MemberFunctionIdTypeDescriptor {
- uint32_t MemberFunction;
- uint32_t ParentClass;
- char *Name;
-};
-
-class ArrayDimensionsDescriptor {
-public:
- const char *GetLengthName(unsigned index);
- const char *GetBoundsName(unsigned index);
-
-private:
- void Resize(unsigned NewSize);
-
- std::vector<std::string> Lengths;
- std::vector<std::string> Bounds;
-};
-
-#pragma pack(pop)
-class UserDefinedTypesBuilder {
-public:
- UserDefinedTypesBuilder();
- void SetStreamer(MCObjectStreamer *Streamer);
- void SetTargetPointerSize(unsigned TargetPointerSize);
- void EmitTypeInformation(MCSection *COFFDebugTypesSection);
-
- unsigned GetEnumTypeIndex(const EnumTypeDescriptor &TypeDescriptor,
- const EnumRecordTypeDescriptor *TypeRecords);
- unsigned GetClassTypeIndex(const ClassTypeDescriptor &ClassDescriptor);
- unsigned GetCompleteClassTypeIndex(
- const ClassTypeDescriptor &ClassDescriptor,
- const ClassFieldsTypeDescriptior &ClassFieldsDescriptor,
- const DataFieldDescriptor *FieldsDescriptors);
-
- unsigned GetArrayTypeIndex(const ClassTypeDescriptor &ClassDescriptor,
- const ArrayTypeDescriptor &ArrayDescriptor);
-
- unsigned GetPointerTypeIndex(const PointerTypeDescriptor& PointerDescriptor);
-
- unsigned GetMemberFunctionTypeIndex(const MemberFunctionTypeDescriptor& MemberDescriptor,
- uint32_t const *const ArgumentTypes);
-
- unsigned GetMemberFunctionId(const MemberFunctionIdTypeDescriptor& MemberIdDescriptor);
-
- const std::vector<std::pair<std::string, codeview::TypeIndex>> &GetUDTs() {
- return UserDefinedTypes;
- }
-
-private:
- void EmitCodeViewMagicVersion();
- ClassOptions GetCommonClassOptions();
-
- unsigned GetEnumFieldListType(uint64 Count,
- const EnumRecordTypeDescriptor *TypeRecords);
-
- void AddBaseClass(FieldListRecordBuilder &FLBR, unsigned BaseClassId);
- void AddClassVTShape(FieldListRecordBuilder &FLBR);
-
- BumpPtrAllocator Allocator;
- TypeTableBuilder TypeTable;
-
- MCObjectStreamer *Streamer;
- unsigned TargetPointerSize;
-
- ArrayDimensionsDescriptor ArrayDimentions;
- TypeIndex ClassVTableTypeIndex;
-
- std::vector<std::pair<std::string, codeview::TypeIndex>> UserDefinedTypes;
-};