Skip to content

Commit 2ed29d8

Browse files
committed
[CodeView] Fortran debug info emission in Code View.
Differential Revision: https://reviews.llvm.org/D112826
1 parent 5c8d305 commit 2ed29d8

File tree

3 files changed

+263
-53
lines changed

3 files changed

+263
-53
lines changed

llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp

Lines changed: 107 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -561,6 +561,44 @@ void CodeViewDebug::emitCodeViewMagicVersion() {
561561
OS.emitInt32(COFF::DEBUG_SECTION_MAGIC);
562562
}
563563

564+
static SourceLanguage MapDWLangToCVLang(unsigned DWLang) {
565+
switch (DWLang) {
566+
case dwarf::DW_LANG_C:
567+
case dwarf::DW_LANG_C89:
568+
case dwarf::DW_LANG_C99:
569+
case dwarf::DW_LANG_C11:
570+
case dwarf::DW_LANG_ObjC:
571+
return SourceLanguage::C;
572+
case dwarf::DW_LANG_C_plus_plus:
573+
case dwarf::DW_LANG_C_plus_plus_03:
574+
case dwarf::DW_LANG_C_plus_plus_11:
575+
case dwarf::DW_LANG_C_plus_plus_14:
576+
return SourceLanguage::Cpp;
577+
case dwarf::DW_LANG_Fortran77:
578+
case dwarf::DW_LANG_Fortran90:
579+
case dwarf::DW_LANG_Fortran95:
580+
case dwarf::DW_LANG_Fortran03:
581+
case dwarf::DW_LANG_Fortran08:
582+
return SourceLanguage::Fortran;
583+
case dwarf::DW_LANG_Pascal83:
584+
return SourceLanguage::Pascal;
585+
case dwarf::DW_LANG_Cobol74:
586+
case dwarf::DW_LANG_Cobol85:
587+
return SourceLanguage::Cobol;
588+
case dwarf::DW_LANG_Java:
589+
return SourceLanguage::Java;
590+
case dwarf::DW_LANG_D:
591+
return SourceLanguage::D;
592+
case dwarf::DW_LANG_Swift:
593+
return SourceLanguage::Swift;
594+
default:
595+
// There's no CodeView representation for this language, and CV doesn't
596+
// have an "unknown" option for the language field, so we'll use MASM,
597+
// as it's very low level.
598+
return SourceLanguage::Masm;
599+
}
600+
}
601+
564602
void CodeViewDebug::beginModule(Module *M) {
565603
// If module doesn't have named metadata anchors or COFF debug section
566604
// is not available, skip any debug info related stuff.
@@ -574,6 +612,13 @@ void CodeViewDebug::beginModule(Module *M) {
574612

575613
TheCPU = mapArchToCVCPUType(Triple(M->getTargetTriple()).getArch());
576614

615+
// Get the current source language.
616+
NamedMDNode *CUs = MMI->getModule()->getNamedMetadata("llvm.dbg.cu");
617+
const MDNode *Node = *CUs->operands().begin();
618+
const auto *CU = cast<DICompileUnit>(Node);
619+
620+
CurrentSourceLanguage = MapDWLangToCVLang(CU->getSourceLanguage());
621+
577622
collectGlobalVariableInfo();
578623

579624
// Check if we should emit type record hashes.
@@ -731,44 +776,6 @@ void CodeViewDebug::emitTypeGlobalHashes() {
731776
}
732777
}
733778

734-
static SourceLanguage MapDWLangToCVLang(unsigned DWLang) {
735-
switch (DWLang) {
736-
case dwarf::DW_LANG_C:
737-
case dwarf::DW_LANG_C89:
738-
case dwarf::DW_LANG_C99:
739-
case dwarf::DW_LANG_C11:
740-
case dwarf::DW_LANG_ObjC:
741-
return SourceLanguage::C;
742-
case dwarf::DW_LANG_C_plus_plus:
743-
case dwarf::DW_LANG_C_plus_plus_03:
744-
case dwarf::DW_LANG_C_plus_plus_11:
745-
case dwarf::DW_LANG_C_plus_plus_14:
746-
return SourceLanguage::Cpp;
747-
case dwarf::DW_LANG_Fortran77:
748-
case dwarf::DW_LANG_Fortran90:
749-
case dwarf::DW_LANG_Fortran95:
750-
case dwarf::DW_LANG_Fortran03:
751-
case dwarf::DW_LANG_Fortran08:
752-
return SourceLanguage::Fortran;
753-
case dwarf::DW_LANG_Pascal83:
754-
return SourceLanguage::Pascal;
755-
case dwarf::DW_LANG_Cobol74:
756-
case dwarf::DW_LANG_Cobol85:
757-
return SourceLanguage::Cobol;
758-
case dwarf::DW_LANG_Java:
759-
return SourceLanguage::Java;
760-
case dwarf::DW_LANG_D:
761-
return SourceLanguage::D;
762-
case dwarf::DW_LANG_Swift:
763-
return SourceLanguage::Swift;
764-
default:
765-
// There's no CodeView representation for this language, and CV doesn't
766-
// have an "unknown" option for the language field, so we'll use MASM,
767-
// as it's very low level.
768-
return SourceLanguage::Masm;
769-
}
770-
}
771-
772779
namespace {
773780
struct Version {
774781
int Part[4];
@@ -798,12 +805,8 @@ void CodeViewDebug::emitCompilerInformation() {
798805
MCSymbol *CompilerEnd = beginSymbolRecord(SymbolKind::S_COMPILE3);
799806
uint32_t Flags = 0;
800807

801-
NamedMDNode *CUs = MMI->getModule()->getNamedMetadata("llvm.dbg.cu");
802-
const MDNode *Node = *CUs->operands().begin();
803-
const auto *CU = cast<DICompileUnit>(Node);
804-
805808
// The low byte of the flags indicates the source language.
806-
Flags = MapDWLangToCVLang(CU->getSourceLanguage());
809+
Flags = CurrentSourceLanguage;
807810
// TODO: Figure out which other flags need to be set.
808811
if (MMI->getModule()->getProfileSummary(/*IsCS*/ false) != nullptr) {
809812
Flags |= static_cast<uint32_t>(CompileSym3Flags::PGO);
@@ -815,6 +818,10 @@ void CodeViewDebug::emitCompilerInformation() {
815818
OS.AddComment("CPUType");
816819
OS.emitInt16(static_cast<uint64_t>(TheCPU));
817820

821+
NamedMDNode *CUs = MMI->getModule()->getNamedMetadata("llvm.dbg.cu");
822+
const MDNode *Node = *CUs->operands().begin();
823+
const auto *CU = cast<DICompileUnit>(Node);
824+
818825
StringRef CompilerVersion = CU->getProducer();
819826
Version FrontVer = parseVersion(CompilerVersion);
820827
OS.AddComment("Frontend version");
@@ -1574,6 +1581,8 @@ TypeIndex CodeViewDebug::lowerType(const DIType *Ty, const DIType *ClassTy) {
15741581
return lowerTypeClass(cast<DICompositeType>(Ty));
15751582
case dwarf::DW_TAG_union_type:
15761583
return lowerTypeUnion(cast<DICompositeType>(Ty));
1584+
case dwarf::DW_TAG_string_type:
1585+
return lowerTypeString(cast<DIStringType>(Ty));
15771586
case dwarf::DW_TAG_unspecified_type:
15781587
if (Ty->getName() == "decltype(nullptr)")
15791588
return TypeIndex::NullptrT();
@@ -1618,14 +1627,19 @@ TypeIndex CodeViewDebug::lowerTypeArray(const DICompositeType *Ty) {
16181627

16191628
const DISubrange *Subrange = cast<DISubrange>(Element);
16201629
int64_t Count = -1;
1621-
// Calculate the count if either LowerBound is absent or is zero and
1622-
// either of Count or UpperBound are constant.
1623-
auto *LI = Subrange->getLowerBound().dyn_cast<ConstantInt *>();
1624-
if (!Subrange->getRawLowerBound() || (LI && (LI->getSExtValue() == 0))) {
1625-
if (auto *CI = Subrange->getCount().dyn_cast<ConstantInt*>())
1626-
Count = CI->getSExtValue();
1627-
else if (auto *UI = Subrange->getUpperBound().dyn_cast<ConstantInt*>())
1628-
Count = UI->getSExtValue() + 1; // LowerBound is zero
1630+
1631+
// If Subrange has a Count field, use it.
1632+
// Otherwise, if it has an upperboud, use (upperbound - lowerbound + 1),
1633+
// where lowerbound is from the LowerBound field of the Subrange,
1634+
// or the language default lowerbound if that field is unspecified.
1635+
if (auto *CI = Subrange->getCount().dyn_cast<ConstantInt *>())
1636+
Count = CI->getSExtValue();
1637+
else if (auto *UI = Subrange->getUpperBound().dyn_cast<ConstantInt *>()) {
1638+
// Fortran uses 1 as the default lowerbound; other languages use 0.
1639+
int64_t Lowerbound = (moduleIsInFortran()) ? 1 : 0;
1640+
auto *LI = Subrange->getLowerBound().dyn_cast<ConstantInt *>();
1641+
Lowerbound = (LI) ? LI->getSExtValue() : Lowerbound;
1642+
Count = UI->getSExtValue() - Lowerbound + 1;
16291643
}
16301644

16311645
// Forward declarations of arrays without a size and VLAs use a count of -1.
@@ -1651,6 +1665,26 @@ TypeIndex CodeViewDebug::lowerTypeArray(const DICompositeType *Ty) {
16511665
return ElementTypeIndex;
16521666
}
16531667

1668+
// This function lowers a Fortran character type (DIStringType).
1669+
// Note that it handles only the character*n variant (using SizeInBits
1670+
// field in DIString to describe the type size) at the moment.
1671+
// Other variants (leveraging the StringLength and StringLengthExp
1672+
// fields in DIStringType) remain TBD.
1673+
TypeIndex CodeViewDebug::lowerTypeString(const DIStringType *Ty) {
1674+
TypeIndex CharType = TypeIndex(SimpleTypeKind::NarrowCharacter);
1675+
uint64_t ArraySize = Ty->getSizeInBits() >> 3;
1676+
StringRef Name = Ty->getName();
1677+
// IndexType is size_t, which depends on the bitness of the target.
1678+
TypeIndex IndexType = getPointerSizeInBytes() == 8
1679+
? TypeIndex(SimpleTypeKind::UInt64Quad)
1680+
: TypeIndex(SimpleTypeKind::UInt32Long);
1681+
1682+
// Create a type of character array of ArraySize.
1683+
ArrayRecord AR(CharType, IndexType, ArraySize, Name);
1684+
1685+
return TypeTable.writeLeafType(AR);
1686+
}
1687+
16541688
TypeIndex CodeViewDebug::lowerTypeBasic(const DIBasicType *Ty) {
16551689
TypeIndex Index;
16561690
dwarf::TypeKind Kind;
@@ -2183,6 +2217,7 @@ void CodeViewDebug::clear() {
21832217
TypeIndices.clear();
21842218
CompleteTypeIndices.clear();
21852219
ScopeGlobals.clear();
2220+
CVGlobalVariableOffsets.clear();
21862221
}
21872222

21882223
void CodeViewDebug::collectMemberInfo(ClassInfo &Info,
@@ -3068,6 +3103,15 @@ void CodeViewDebug::collectGlobalVariableInfo() {
30683103
const DIGlobalVariable *DIGV = GVE->getVariable();
30693104
const DIExpression *DIE = GVE->getExpression();
30703105

3106+
if ((DIE->getNumElements() == 2) &&
3107+
(DIE->getElement(0) == dwarf::DW_OP_plus_uconst))
3108+
// Record the constant offset for the variable.
3109+
//
3110+
// A Fortran common block uses this idiom to encode the offset
3111+
// of a variable from the common block's starting address.
3112+
CVGlobalVariableOffsets.insert(
3113+
std::make_pair(DIGV, DIE->getElement(1)));
3114+
30713115
// Emit constant global variables in a global symbol section.
30723116
if (GlobalMap.count(GVE) == 0 && DIE->isConstant()) {
30733117
CVGlobalVariable CVGV = {DIGV, DIE};
@@ -3232,7 +3276,11 @@ void CodeViewDebug::emitDebugInfoForGlobal(const CVGlobalVariable &CVGV) {
32323276
if (const auto *MemberDecl = dyn_cast_or_null<DIDerivedType>(
32333277
DIGV->getRawStaticDataMemberDeclaration()))
32343278
Scope = MemberDecl->getScope();
3235-
std::string QualifiedName = getFullyQualifiedName(Scope, DIGV->getName());
3279+
// For Fortran, the scoping portion is elided in its name so that we can
3280+
// reference the variable in the command line of the VS debugger.
3281+
std::string QualifiedName =
3282+
(moduleIsInFortran()) ? std::string(DIGV->getName())
3283+
: getFullyQualifiedName(Scope, DIGV->getName());
32363284

32373285
if (const GlobalVariable *GV =
32383286
CVGV.GVInfo.dyn_cast<const GlobalVariable *>()) {
@@ -3248,7 +3296,13 @@ void CodeViewDebug::emitDebugInfoForGlobal(const CVGlobalVariable &CVGV) {
32483296
OS.AddComment("Type");
32493297
OS.emitInt32(getCompleteTypeIndex(DIGV->getType()).getIndex());
32503298
OS.AddComment("DataOffset");
3251-
OS.EmitCOFFSecRel32(GVSym, /*Offset=*/0);
3299+
3300+
uint64_t Offset = 0;
3301+
if (CVGlobalVariableOffsets.find(DIGV) != CVGlobalVariableOffsets.end())
3302+
// Use the offset seen while collecting info on globals.
3303+
Offset = CVGlobalVariableOffsets[DIGV];
3304+
OS.EmitCOFFSecRel32(GVSym, Offset);
3305+
32523306
OS.AddComment("Segment");
32533307
OS.EmitCOFFSectionIndex(GVSym);
32543308
OS.AddComment("Name");

llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,13 @@ class LLVM_LIBRARY_VISIBILITY CodeViewDebug : public DebugHandlerBase {
186186
};
187187
FunctionInfo *CurFn = nullptr;
188188

189+
codeview::SourceLanguage CurrentSourceLanguage =
190+
codeview::SourceLanguage::Masm;
191+
192+
// This map records the constant offset in DIExpression of the
193+
// DIGlobalVariableExpression referencing the DIGlobalVariable.
194+
DenseMap<const DIGlobalVariable *, uint64_t> CVGlobalVariableOffsets;
195+
189196
// Map used to seperate variables according to the lexical scope they belong
190197
// in. This is populated by recordLocalVariable() before
191198
// collectLexicalBlocks() separates the variables between the FunctionInfo
@@ -400,6 +407,7 @@ class LLVM_LIBRARY_VISIBILITY CodeViewDebug : public DebugHandlerBase {
400407
codeview::TypeIndex lowerType(const DIType *Ty, const DIType *ClassTy);
401408
codeview::TypeIndex lowerTypeAlias(const DIDerivedType *Ty);
402409
codeview::TypeIndex lowerTypeArray(const DICompositeType *Ty);
410+
codeview::TypeIndex lowerTypeString(const DIStringType *Ty);
403411
codeview::TypeIndex lowerTypeBasic(const DIBasicType *Ty);
404412
codeview::TypeIndex lowerTypePointer(
405413
const DIDerivedType *Ty,
@@ -464,6 +472,11 @@ class LLVM_LIBRARY_VISIBILITY CodeViewDebug : public DebugHandlerBase {
464472
/// Gather post-function debug information.
465473
void endFunctionImpl(const MachineFunction *) override;
466474

475+
/// Check if the current module is in Fortran.
476+
bool moduleIsInFortran() {
477+
return CurrentSourceLanguage == codeview::SourceLanguage::Fortran;
478+
}
479+
467480
public:
468481
CodeViewDebug(AsmPrinter *AP);
469482

0 commit comments

Comments
 (0)