12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023 |
- //===- llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp ----------------------===//
- //
- // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
- // See https://llvm.org/LICENSE.txt for license information.
- // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
- //
- //===----------------------------------------------------------------------===//
- //
- // This file contains support for writing Microsoft CodeView debug info.
- //
- //===----------------------------------------------------------------------===//
- #include "CodeViewDebug.h"
- #include "DwarfExpression.h"
- #include "llvm/ADT/APSInt.h"
- #include "llvm/ADT/ArrayRef.h"
- #include "llvm/ADT/DenseMap.h"
- #include "llvm/ADT/DenseSet.h"
- #include "llvm/ADT/MapVector.h"
- #include "llvm/ADT/None.h"
- #include "llvm/ADT/Optional.h"
- #include "llvm/ADT/STLExtras.h"
- #include "llvm/ADT/SmallString.h"
- #include "llvm/ADT/SmallVector.h"
- #include "llvm/ADT/StringRef.h"
- #include "llvm/ADT/TinyPtrVector.h"
- #include "llvm/ADT/Triple.h"
- #include "llvm/ADT/Twine.h"
- #include "llvm/BinaryFormat/COFF.h"
- #include "llvm/BinaryFormat/Dwarf.h"
- #include "llvm/CodeGen/AsmPrinter.h"
- #include "llvm/CodeGen/LexicalScopes.h"
- #include "llvm/CodeGen/MachineFrameInfo.h"
- #include "llvm/CodeGen/MachineFunction.h"
- #include "llvm/CodeGen/MachineInstr.h"
- #include "llvm/CodeGen/MachineModuleInfo.h"
- #include "llvm/CodeGen/MachineOperand.h"
- #include "llvm/CodeGen/TargetFrameLowering.h"
- #include "llvm/CodeGen/TargetRegisterInfo.h"
- #include "llvm/CodeGen/TargetSubtargetInfo.h"
- #include "llvm/Config/llvm-config.h"
- #include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
- #include "llvm/DebugInfo/CodeView/CodeView.h"
- #include "llvm/DebugInfo/CodeView/ContinuationRecordBuilder.h"
- #include "llvm/DebugInfo/CodeView/DebugInlineeLinesSubsection.h"
- #include "llvm/DebugInfo/CodeView/EnumTables.h"
- #include "llvm/DebugInfo/CodeView/Line.h"
- #include "llvm/DebugInfo/CodeView/SymbolRecord.h"
- #include "llvm/DebugInfo/CodeView/TypeDumpVisitor.h"
- #include "llvm/DebugInfo/CodeView/TypeIndex.h"
- #include "llvm/DebugInfo/CodeView/TypeRecord.h"
- #include "llvm/DebugInfo/CodeView/TypeTableCollection.h"
- #include "llvm/IR/Constants.h"
- #include "llvm/IR/DataLayout.h"
- #include "llvm/IR/DebugInfoMetadata.h"
- #include "llvm/IR/DebugLoc.h"
- #include "llvm/IR/Function.h"
- #include "llvm/IR/GlobalValue.h"
- #include "llvm/IR/GlobalVariable.h"
- #include "llvm/IR/Metadata.h"
- #include "llvm/IR/Module.h"
- #include "llvm/MC/MCAsmInfo.h"
- #include "llvm/MC/MCContext.h"
- #include "llvm/MC/MCSectionCOFF.h"
- #include "llvm/MC/MCStreamer.h"
- #include "llvm/MC/MCSymbol.h"
- #include "llvm/Support/BinaryByteStream.h"
- #include "llvm/Support/BinaryStreamReader.h"
- #include "llvm/Support/Casting.h"
- #include "llvm/Support/CommandLine.h"
- #include "llvm/Support/Compiler.h"
- #include "llvm/Support/Endian.h"
- #include "llvm/Support/Error.h"
- #include "llvm/Support/ErrorHandling.h"
- #include "llvm/Support/FormatVariadic.h"
- #include "llvm/Support/Path.h"
- #include "llvm/Support/SMLoc.h"
- #include "llvm/Support/ScopedPrinter.h"
- #include "llvm/Target/TargetLoweringObjectFile.h"
- #include "llvm/Target/TargetMachine.h"
- #include <algorithm>
- #include <cassert>
- #include <cctype>
- #include <cstddef>
- #include <cstdint>
- #include <iterator>
- #include <limits>
- #include <string>
- #include <utility>
- #include <vector>
- using namespace llvm;
- using namespace llvm::codeview;
- static CPUType mapArchToCVCPUType(Triple::ArchType Type) {
- switch (Type) {
- case Triple::ArchType::x86:
- return CPUType::Pentium3;
- case Triple::ArchType::x86_64:
- return CPUType::X64;
- case Triple::ArchType::thumb:
- return CPUType::Thumb;
- case Triple::ArchType::aarch64:
- return CPUType::ARM64;
- default:
- report_fatal_error("target architecture doesn't map to a CodeView CPUType");
- }
- }
- CodeViewDebug::CodeViewDebug(AsmPrinter *AP)
- : DebugHandlerBase(AP), OS(*Asm->OutStreamer), TypeTable(Allocator) {
- // If module doesn't have named metadata anchors or COFF debug section
- // is not available, skip any debug info related stuff.
- if (!MMI->getModule()->getNamedMetadata("llvm.dbg.cu") ||
- !AP->getObjFileLowering().getCOFFDebugSymbolsSection()) {
- Asm = nullptr;
- MMI->setDebugInfoAvailability(false);
- return;
- }
- // Tell MMI that we have debug info.
- MMI->setDebugInfoAvailability(true);
- TheCPU =
- mapArchToCVCPUType(Triple(MMI->getModule()->getTargetTriple()).getArch());
- collectGlobalVariableInfo();
- // Check if we should emit type record hashes.
- ConstantInt *GH = mdconst::extract_or_null<ConstantInt>(
- MMI->getModule()->getModuleFlag("CodeViewGHash"));
- EmitDebugGlobalHashes = GH && !GH->isZero();
- }
- StringRef CodeViewDebug::getFullFilepath(const DIFile *File) {
- std::string &Filepath = FileToFilepathMap[File];
- if (!Filepath.empty())
- return Filepath;
- StringRef Dir = File->getDirectory(), Filename = File->getFilename();
- // If this is a Unix-style path, just use it as is. Don't try to canonicalize
- // it textually because one of the path components could be a symlink.
- if (Dir.startswith("/") || Filename.startswith("/")) {
- if (llvm::sys::path::is_absolute(Filename, llvm::sys::path::Style::posix))
- return Filename;
- Filepath = Dir;
- if (Dir.back() != '/')
- Filepath += '/';
- Filepath += Filename;
- return Filepath;
- }
- // Clang emits directory and relative filename info into the IR, but CodeView
- // operates on full paths. We could change Clang to emit full paths too, but
- // that would increase the IR size and probably not needed for other users.
- // For now, just concatenate and canonicalize the path here.
- if (Filename.find(':') == 1)
- Filepath = Filename;
- else
- Filepath = (Dir + "\\" + Filename).str();
- // Canonicalize the path. We have to do it textually because we may no longer
- // have access the file in the filesystem.
- // First, replace all slashes with backslashes.
- std::replace(Filepath.begin(), Filepath.end(), '/', '\\');
- // Remove all "\.\" with "\".
- size_t Cursor = 0;
- while ((Cursor = Filepath.find("\\.\\", Cursor)) != std::string::npos)
- Filepath.erase(Cursor, 2);
- // Replace all "\XXX\..\" with "\". Don't try too hard though as the original
- // path should be well-formatted, e.g. start with a drive letter, etc.
- Cursor = 0;
- while ((Cursor = Filepath.find("\\..\\", Cursor)) != std::string::npos) {
- // Something's wrong if the path starts with "\..\", abort.
- if (Cursor == 0)
- break;
- size_t PrevSlash = Filepath.rfind('\\', Cursor - 1);
- if (PrevSlash == std::string::npos)
- // Something's wrong, abort.
- break;
- Filepath.erase(PrevSlash, Cursor + 3 - PrevSlash);
- // The next ".." might be following the one we've just erased.
- Cursor = PrevSlash;
- }
- // Remove all duplicate backslashes.
- Cursor = 0;
- while ((Cursor = Filepath.find("\\\\", Cursor)) != std::string::npos)
- Filepath.erase(Cursor, 1);
- return Filepath;
- }
- unsigned CodeViewDebug::maybeRecordFile(const DIFile *F) {
- StringRef FullPath = getFullFilepath(F);
- unsigned NextId = FileIdMap.size() + 1;
- auto Insertion = FileIdMap.insert(std::make_pair(FullPath, NextId));
- if (Insertion.second) {
- // We have to compute the full filepath and emit a .cv_file directive.
- ArrayRef<uint8_t> ChecksumAsBytes;
- FileChecksumKind CSKind = FileChecksumKind::None;
- if (F->getChecksum()) {
- std::string Checksum = fromHex(F->getChecksum()->Value);
- void *CKMem = OS.getContext().allocate(Checksum.size(), 1);
- memcpy(CKMem, Checksum.data(), Checksum.size());
- ChecksumAsBytes = ArrayRef<uint8_t>(
- reinterpret_cast<const uint8_t *>(CKMem), Checksum.size());
- switch (F->getChecksum()->Kind) {
- case DIFile::CSK_MD5: CSKind = FileChecksumKind::MD5; break;
- case DIFile::CSK_SHA1: CSKind = FileChecksumKind::SHA1; break;
- }
- }
- bool Success = OS.EmitCVFileDirective(NextId, FullPath, ChecksumAsBytes,
- static_cast<unsigned>(CSKind));
- (void)Success;
- assert(Success && ".cv_file directive failed");
- }
- return Insertion.first->second;
- }
- CodeViewDebug::InlineSite &
- CodeViewDebug::getInlineSite(const DILocation *InlinedAt,
- const DISubprogram *Inlinee) {
- auto SiteInsertion = CurFn->InlineSites.insert({InlinedAt, InlineSite()});
- InlineSite *Site = &SiteInsertion.first->second;
- if (SiteInsertion.second) {
- unsigned ParentFuncId = CurFn->FuncId;
- if (const DILocation *OuterIA = InlinedAt->getInlinedAt())
- ParentFuncId =
- getInlineSite(OuterIA, InlinedAt->getScope()->getSubprogram())
- .SiteFuncId;
- Site->SiteFuncId = NextFuncId++;
- OS.EmitCVInlineSiteIdDirective(
- Site->SiteFuncId, ParentFuncId, maybeRecordFile(InlinedAt->getFile()),
- InlinedAt->getLine(), InlinedAt->getColumn(), SMLoc());
- Site->Inlinee = Inlinee;
- InlinedSubprograms.insert(Inlinee);
- getFuncIdForSubprogram(Inlinee);
- }
- return *Site;
- }
- static StringRef getPrettyScopeName(const DIScope *Scope) {
- StringRef ScopeName = Scope->getName();
- if (!ScopeName.empty())
- return ScopeName;
- switch (Scope->getTag()) {
- case dwarf::DW_TAG_enumeration_type:
- case dwarf::DW_TAG_class_type:
- case dwarf::DW_TAG_structure_type:
- case dwarf::DW_TAG_union_type:
- return "<unnamed-tag>";
- case dwarf::DW_TAG_namespace:
- return "`anonymous namespace'";
- }
- return StringRef();
- }
- static const DISubprogram *getQualifiedNameComponents(
- const DIScope *Scope, SmallVectorImpl<StringRef> &QualifiedNameComponents) {
- const DISubprogram *ClosestSubprogram = nullptr;
- while (Scope != nullptr) {
- if (ClosestSubprogram == nullptr)
- ClosestSubprogram = dyn_cast<DISubprogram>(Scope);
- StringRef ScopeName = getPrettyScopeName(Scope);
- if (!ScopeName.empty())
- QualifiedNameComponents.push_back(ScopeName);
- Scope = Scope->getScope().resolve();
- }
- return ClosestSubprogram;
- }
- static std::string getQualifiedName(ArrayRef<StringRef> QualifiedNameComponents,
- StringRef TypeName) {
- std::string FullyQualifiedName;
- for (StringRef QualifiedNameComponent :
- llvm::reverse(QualifiedNameComponents)) {
- FullyQualifiedName.append(QualifiedNameComponent);
- FullyQualifiedName.append("::");
- }
- FullyQualifiedName.append(TypeName);
- return FullyQualifiedName;
- }
- static std::string getFullyQualifiedName(const DIScope *Scope, StringRef Name) {
- SmallVector<StringRef, 5> QualifiedNameComponents;
- getQualifiedNameComponents(Scope, QualifiedNameComponents);
- return getQualifiedName(QualifiedNameComponents, Name);
- }
- struct CodeViewDebug::TypeLoweringScope {
- TypeLoweringScope(CodeViewDebug &CVD) : CVD(CVD) { ++CVD.TypeEmissionLevel; }
- ~TypeLoweringScope() {
- // Don't decrement TypeEmissionLevel until after emitting deferred types, so
- // inner TypeLoweringScopes don't attempt to emit deferred types.
- if (CVD.TypeEmissionLevel == 1)
- CVD.emitDeferredCompleteTypes();
- --CVD.TypeEmissionLevel;
- }
- CodeViewDebug &CVD;
- };
- static std::string getFullyQualifiedName(const DIScope *Ty) {
- const DIScope *Scope = Ty->getScope().resolve();
- return getFullyQualifiedName(Scope, getPrettyScopeName(Ty));
- }
- TypeIndex CodeViewDebug::getScopeIndex(const DIScope *Scope) {
- // No scope means global scope and that uses the zero index.
- if (!Scope || isa<DIFile>(Scope))
- return TypeIndex();
- assert(!isa<DIType>(Scope) && "shouldn't make a namespace scope for a type");
- // Check if we've already translated this scope.
- auto I = TypeIndices.find({Scope, nullptr});
- if (I != TypeIndices.end())
- return I->second;
- // Build the fully qualified name of the scope.
- std::string ScopeName = getFullyQualifiedName(Scope);
- StringIdRecord SID(TypeIndex(), ScopeName);
- auto TI = TypeTable.writeLeafType(SID);
- return recordTypeIndexForDINode(Scope, TI);
- }
- TypeIndex CodeViewDebug::getFuncIdForSubprogram(const DISubprogram *SP) {
- assert(SP);
- // Check if we've already translated this subprogram.
- auto I = TypeIndices.find({SP, nullptr});
- if (I != TypeIndices.end())
- return I->second;
- // The display name includes function template arguments. Drop them to match
- // MSVC.
- StringRef DisplayName = SP->getName().split('<').first;
- const DIScope *Scope = SP->getScope().resolve();
- TypeIndex TI;
- if (const auto *Class = dyn_cast_or_null<DICompositeType>(Scope)) {
- // If the scope is a DICompositeType, then this must be a method. Member
- // function types take some special handling, and require access to the
- // subprogram.
- TypeIndex ClassType = getTypeIndex(Class);
- MemberFuncIdRecord MFuncId(ClassType, getMemberFunctionType(SP, Class),
- DisplayName);
- TI = TypeTable.writeLeafType(MFuncId);
- } else {
- // Otherwise, this must be a free function.
- TypeIndex ParentScope = getScopeIndex(Scope);
- FuncIdRecord FuncId(ParentScope, getTypeIndex(SP->getType()), DisplayName);
- TI = TypeTable.writeLeafType(FuncId);
- }
- return recordTypeIndexForDINode(SP, TI);
- }
- static bool isNonTrivial(const DICompositeType *DCTy) {
- return ((DCTy->getFlags() & DINode::FlagNonTrivial) == DINode::FlagNonTrivial);
- }
- static FunctionOptions
- getFunctionOptions(const DISubroutineType *Ty,
- const DICompositeType *ClassTy = nullptr,
- StringRef SPName = StringRef("")) {
- FunctionOptions FO = FunctionOptions::None;
- const DIType *ReturnTy = nullptr;
- if (auto TypeArray = Ty->getTypeArray()) {
- if (TypeArray.size())
- ReturnTy = TypeArray[0].resolve();
- }
- if (auto *ReturnDCTy = dyn_cast_or_null<DICompositeType>(ReturnTy)) {
- if (isNonTrivial(ReturnDCTy))
- FO |= FunctionOptions::CxxReturnUdt;
- }
- // DISubroutineType is unnamed. Use DISubprogram's i.e. SPName in comparison.
- if (ClassTy && isNonTrivial(ClassTy) && SPName == ClassTy->getName()) {
- FO |= FunctionOptions::Constructor;
- // TODO: put the FunctionOptions::ConstructorWithVirtualBases flag.
- }
- return FO;
- }
- TypeIndex CodeViewDebug::getMemberFunctionType(const DISubprogram *SP,
- const DICompositeType *Class) {
- // Always use the method declaration as the key for the function type. The
- // method declaration contains the this adjustment.
- if (SP->getDeclaration())
- SP = SP->getDeclaration();
- assert(!SP->getDeclaration() && "should use declaration as key");
- // Key the MemberFunctionRecord into the map as {SP, Class}. It won't collide
- // with the MemberFuncIdRecord, which is keyed in as {SP, nullptr}.
- auto I = TypeIndices.find({SP, Class});
- if (I != TypeIndices.end())
- return I->second;
- // Make sure complete type info for the class is emitted *after* the member
- // function type, as the complete class type is likely to reference this
- // member function type.
- TypeLoweringScope S(*this);
- const bool IsStaticMethod = (SP->getFlags() & DINode::FlagStaticMember) != 0;
- FunctionOptions FO = getFunctionOptions(SP->getType(), Class, SP->getName());
- TypeIndex TI = lowerTypeMemberFunction(
- SP->getType(), Class, SP->getThisAdjustment(), IsStaticMethod, FO);
- return recordTypeIndexForDINode(SP, TI, Class);
- }
- TypeIndex CodeViewDebug::recordTypeIndexForDINode(const DINode *Node,
- TypeIndex TI,
- const DIType *ClassTy) {
- auto InsertResult = TypeIndices.insert({{Node, ClassTy}, TI});
- (void)InsertResult;
- assert(InsertResult.second && "DINode was already assigned a type index");
- return TI;
- }
- unsigned CodeViewDebug::getPointerSizeInBytes() {
- return MMI->getModule()->getDataLayout().getPointerSizeInBits() / 8;
- }
- void CodeViewDebug::recordLocalVariable(LocalVariable &&Var,
- const LexicalScope *LS) {
- if (const DILocation *InlinedAt = LS->getInlinedAt()) {
- // This variable was inlined. Associate it with the InlineSite.
- const DISubprogram *Inlinee = Var.DIVar->getScope()->getSubprogram();
- InlineSite &Site = getInlineSite(InlinedAt, Inlinee);
- Site.InlinedLocals.emplace_back(Var);
- } else {
- // This variable goes into the corresponding lexical scope.
- ScopeVariables[LS].emplace_back(Var);
- }
- }
- static void addLocIfNotPresent(SmallVectorImpl<const DILocation *> &Locs,
- const DILocation *Loc) {
- auto B = Locs.begin(), E = Locs.end();
- if (std::find(B, E, Loc) == E)
- Locs.push_back(Loc);
- }
- void CodeViewDebug::maybeRecordLocation(const DebugLoc &DL,
- const MachineFunction *MF) {
- // Skip this instruction if it has the same location as the previous one.
- if (!DL || DL == PrevInstLoc)
- return;
- const DIScope *Scope = DL.get()->getScope();
- if (!Scope)
- return;
- // Skip this line if it is longer than the maximum we can record.
- LineInfo LI(DL.getLine(), DL.getLine(), /*IsStatement=*/true);
- if (LI.getStartLine() != DL.getLine() || LI.isAlwaysStepInto() ||
- LI.isNeverStepInto())
- return;
- ColumnInfo CI(DL.getCol(), /*EndColumn=*/0);
- if (CI.getStartColumn() != DL.getCol())
- return;
- if (!CurFn->HaveLineInfo)
- CurFn->HaveLineInfo = true;
- unsigned FileId = 0;
- if (PrevInstLoc.get() && PrevInstLoc->getFile() == DL->getFile())
- FileId = CurFn->LastFileId;
- else
- FileId = CurFn->LastFileId = maybeRecordFile(DL->getFile());
- PrevInstLoc = DL;
- unsigned FuncId = CurFn->FuncId;
- if (const DILocation *SiteLoc = DL->getInlinedAt()) {
- const DILocation *Loc = DL.get();
- // If this location was actually inlined from somewhere else, give it the ID
- // of the inline call site.
- FuncId =
- getInlineSite(SiteLoc, Loc->getScope()->getSubprogram()).SiteFuncId;
- // Ensure we have links in the tree of inline call sites.
- bool FirstLoc = true;
- while ((SiteLoc = Loc->getInlinedAt())) {
- InlineSite &Site =
- getInlineSite(SiteLoc, Loc->getScope()->getSubprogram());
- if (!FirstLoc)
- addLocIfNotPresent(Site.ChildSites, Loc);
- FirstLoc = false;
- Loc = SiteLoc;
- }
- addLocIfNotPresent(CurFn->ChildSites, Loc);
- }
- OS.EmitCVLocDirective(FuncId, FileId, DL.getLine(), DL.getCol(),
- /*PrologueEnd=*/false, /*IsStmt=*/false,
- DL->getFilename(), SMLoc());
- }
- void CodeViewDebug::emitCodeViewMagicVersion() {
- OS.EmitValueToAlignment(4);
- OS.AddComment("Debug section magic");
- OS.EmitIntValue(COFF::DEBUG_SECTION_MAGIC, 4);
- }
- void CodeViewDebug::endModule() {
- if (!Asm || !MMI->hasDebugInfo())
- return;
- assert(Asm != nullptr);
- // The COFF .debug$S section consists of several subsections, each starting
- // with a 4-byte control code (e.g. 0xF1, 0xF2, etc) and then a 4-byte length
- // of the payload followed by the payload itself. The subsections are 4-byte
- // aligned.
- // Use the generic .debug$S section, and make a subsection for all the inlined
- // subprograms.
- switchToDebugSectionForSymbol(nullptr);
- MCSymbol *CompilerInfo = beginCVSubsection(DebugSubsectionKind::Symbols);
- emitCompilerInformation();
- endCVSubsection(CompilerInfo);
- emitInlineeLinesSubsection();
- // Emit per-function debug information.
- for (auto &P : FnDebugInfo)
- if (!P.first->isDeclarationForLinker())
- emitDebugInfoForFunction(P.first, *P.second);
- // Emit global variable debug information.
- setCurrentSubprogram(nullptr);
- emitDebugInfoForGlobals();
- // Emit retained types.
- emitDebugInfoForRetainedTypes();
- // Switch back to the generic .debug$S section after potentially processing
- // comdat symbol sections.
- switchToDebugSectionForSymbol(nullptr);
- // Emit UDT records for any types used by global variables.
- if (!GlobalUDTs.empty()) {
- MCSymbol *SymbolsEnd = beginCVSubsection(DebugSubsectionKind::Symbols);
- emitDebugInfoForUDTs(GlobalUDTs);
- endCVSubsection(SymbolsEnd);
- }
- // This subsection holds a file index to offset in string table table.
- OS.AddComment("File index to string table offset subsection");
- OS.EmitCVFileChecksumsDirective();
- // This subsection holds the string table.
- OS.AddComment("String table");
- OS.EmitCVStringTableDirective();
- // Emit S_BUILDINFO, which points to LF_BUILDINFO. Put this in its own symbol
- // subsection in the generic .debug$S section at the end. There is no
- // particular reason for this ordering other than to match MSVC.
- emitBuildInfo();
- // Emit type information and hashes last, so that any types we translate while
- // emitting function info are included.
- emitTypeInformation();
- if (EmitDebugGlobalHashes)
- emitTypeGlobalHashes();
- clear();
- }
- static void emitNullTerminatedSymbolName(MCStreamer &OS, StringRef S,
- unsigned MaxFixedRecordLength = 0xF00) {
- // The maximum CV record length is 0xFF00. Most of the strings we emit appear
- // after a fixed length portion of the record. The fixed length portion should
- // always be less than 0xF00 (3840) bytes, so truncate the string so that the
- // overall record size is less than the maximum allowed.
- SmallString<32> NullTerminatedString(
- S.take_front(MaxRecordLength - MaxFixedRecordLength - 1));
- NullTerminatedString.push_back('\0');
- OS.EmitBytes(NullTerminatedString);
- }
- void CodeViewDebug::emitTypeInformation() {
- if (TypeTable.empty())
- return;
- // Start the .debug$T or .debug$P section with 0x4.
- OS.SwitchSection(Asm->getObjFileLowering().getCOFFDebugTypesSection());
- emitCodeViewMagicVersion();
- SmallString<8> CommentPrefix;
- if (OS.isVerboseAsm()) {
- CommentPrefix += '\t';
- CommentPrefix += Asm->MAI->getCommentString();
- CommentPrefix += ' ';
- }
- TypeTableCollection Table(TypeTable.records());
- Optional<TypeIndex> B = Table.getFirst();
- while (B) {
- // This will fail if the record data is invalid.
- CVType Record = Table.getType(*B);
- if (OS.isVerboseAsm()) {
- // Emit a block comment describing the type record for readability.
- SmallString<512> CommentBlock;
- raw_svector_ostream CommentOS(CommentBlock);
- ScopedPrinter SP(CommentOS);
- SP.setPrefix(CommentPrefix);
- TypeDumpVisitor TDV(Table, &SP, false);
- Error E = codeview::visitTypeRecord(Record, *B, TDV);
- if (E) {
- logAllUnhandledErrors(std::move(E), errs(), "error: ");
- llvm_unreachable("produced malformed type record");
- }
- // emitRawComment will insert its own tab and comment string before
- // the first line, so strip off our first one. It also prints its own
- // newline.
- OS.emitRawComment(
- CommentOS.str().drop_front(CommentPrefix.size() - 1).rtrim());
- }
- OS.EmitBinaryData(Record.str_data());
- B = Table.getNext(*B);
- }
- }
- void CodeViewDebug::emitTypeGlobalHashes() {
- if (TypeTable.empty())
- return;
- // Start the .debug$H section with the version and hash algorithm, currently
- // hardcoded to version 0, SHA1.
- OS.SwitchSection(Asm->getObjFileLowering().getCOFFGlobalTypeHashesSection());
- OS.EmitValueToAlignment(4);
- OS.AddComment("Magic");
- OS.EmitIntValue(COFF::DEBUG_HASHES_SECTION_MAGIC, 4);
- OS.AddComment("Section Version");
- OS.EmitIntValue(0, 2);
- OS.AddComment("Hash Algorithm");
- OS.EmitIntValue(uint16_t(GlobalTypeHashAlg::SHA1_8), 2);
- TypeIndex TI(TypeIndex::FirstNonSimpleIndex);
- for (const auto &GHR : TypeTable.hashes()) {
- if (OS.isVerboseAsm()) {
- // Emit an EOL-comment describing which TypeIndex this hash corresponds
- // to, as well as the stringified SHA1 hash.
- SmallString<32> Comment;
- raw_svector_ostream CommentOS(Comment);
- CommentOS << formatv("{0:X+} [{1}]", TI.getIndex(), GHR);
- OS.AddComment(Comment);
- ++TI;
- }
- assert(GHR.Hash.size() == 8);
- StringRef S(reinterpret_cast<const char *>(GHR.Hash.data()),
- GHR.Hash.size());
- OS.EmitBinaryData(S);
- }
- }
- static SourceLanguage MapDWLangToCVLang(unsigned DWLang) {
- switch (DWLang) {
- case dwarf::DW_LANG_C:
- case dwarf::DW_LANG_C89:
- case dwarf::DW_LANG_C99:
- case dwarf::DW_LANG_C11:
- case dwarf::DW_LANG_ObjC:
- return SourceLanguage::C;
- case dwarf::DW_LANG_C_plus_plus:
- case dwarf::DW_LANG_C_plus_plus_03:
- case dwarf::DW_LANG_C_plus_plus_11:
- case dwarf::DW_LANG_C_plus_plus_14:
- return SourceLanguage::Cpp;
- case dwarf::DW_LANG_Fortran77:
- case dwarf::DW_LANG_Fortran90:
- case dwarf::DW_LANG_Fortran03:
- case dwarf::DW_LANG_Fortran08:
- return SourceLanguage::Fortran;
- case dwarf::DW_LANG_Pascal83:
- return SourceLanguage::Pascal;
- case dwarf::DW_LANG_Cobol74:
- case dwarf::DW_LANG_Cobol85:
- return SourceLanguage::Cobol;
- case dwarf::DW_LANG_Java:
- return SourceLanguage::Java;
- case dwarf::DW_LANG_D:
- return SourceLanguage::D;
- case dwarf::DW_LANG_Swift:
- return SourceLanguage::Swift;
- default:
- // There's no CodeView representation for this language, and CV doesn't
- // have an "unknown" option for the language field, so we'll use MASM,
- // as it's very low level.
- return SourceLanguage::Masm;
- }
- }
- namespace {
- struct Version {
- int Part[4];
- };
- } // end anonymous namespace
- // Takes a StringRef like "clang 4.0.0.0 (other nonsense 123)" and parses out
- // the version number.
- static Version parseVersion(StringRef Name) {
- Version V = {{0}};
- int N = 0;
- for (const char C : Name) {
- if (isdigit(C)) {
- V.Part[N] *= 10;
- V.Part[N] += C - '0';
- } else if (C == '.') {
- ++N;
- if (N >= 4)
- return V;
- } else if (N > 0)
- return V;
- }
- return V;
- }
- void CodeViewDebug::emitCompilerInformation() {
- MCSymbol *CompilerEnd = beginSymbolRecord(SymbolKind::S_COMPILE3);
- uint32_t Flags = 0;
- NamedMDNode *CUs = MMI->getModule()->getNamedMetadata("llvm.dbg.cu");
- const MDNode *Node = *CUs->operands().begin();
- const auto *CU = cast<DICompileUnit>(Node);
- // The low byte of the flags indicates the source language.
- Flags = MapDWLangToCVLang(CU->getSourceLanguage());
- // TODO: Figure out which other flags need to be set.
- OS.AddComment("Flags and language");
- OS.EmitIntValue(Flags, 4);
- OS.AddComment("CPUType");
- OS.EmitIntValue(static_cast<uint64_t>(TheCPU), 2);
- StringRef CompilerVersion = CU->getProducer();
- Version FrontVer = parseVersion(CompilerVersion);
- OS.AddComment("Frontend version");
- for (int N = 0; N < 4; ++N)
- OS.EmitIntValue(FrontVer.Part[N], 2);
- // Some Microsoft tools, like Binscope, expect a backend version number of at
- // least 8.something, so we'll coerce the LLVM version into a form that
- // guarantees it'll be big enough without really lying about the version.
- int Major = 1000 * LLVM_VERSION_MAJOR +
- 10 * LLVM_VERSION_MINOR +
- LLVM_VERSION_PATCH;
- // Clamp it for builds that use unusually large version numbers.
- Major = std::min<int>(Major, std::numeric_limits<uint16_t>::max());
- Version BackVer = {{ Major, 0, 0, 0 }};
- OS.AddComment("Backend version");
- for (int N = 0; N < 4; ++N)
- OS.EmitIntValue(BackVer.Part[N], 2);
- OS.AddComment("Null-terminated compiler version string");
- emitNullTerminatedSymbolName(OS, CompilerVersion);
- endSymbolRecord(CompilerEnd);
- }
- static TypeIndex getStringIdTypeIdx(GlobalTypeTableBuilder &TypeTable,
- StringRef S) {
- StringIdRecord SIR(TypeIndex(0x0), S);
- return TypeTable.writeLeafType(SIR);
- }
- void CodeViewDebug::emitBuildInfo() {
- // First, make LF_BUILDINFO. It's a sequence of strings with various bits of
- // build info. The known prefix is:
- // - Absolute path of current directory
- // - Compiler path
- // - Main source file path, relative to CWD or absolute
- // - Type server PDB file
- // - Canonical compiler command line
- // If frontend and backend compilation are separated (think llc or LTO), it's
- // not clear if the compiler path should refer to the executable for the
- // frontend or the backend. Leave it blank for now.
- TypeIndex BuildInfoArgs[BuildInfoRecord::MaxArgs] = {};
- NamedMDNode *CUs = MMI->getModule()->getNamedMetadata("llvm.dbg.cu");
- const MDNode *Node = *CUs->operands().begin(); // FIXME: Multiple CUs.
- const auto *CU = cast<DICompileUnit>(Node);
- const DIFile *MainSourceFile = CU->getFile();
- BuildInfoArgs[BuildInfoRecord::CurrentDirectory] =
- getStringIdTypeIdx(TypeTable, MainSourceFile->getDirectory());
- BuildInfoArgs[BuildInfoRecord::SourceFile] =
- getStringIdTypeIdx(TypeTable, MainSourceFile->getFilename());
- // FIXME: Path to compiler and command line. PDB is intentionally blank unless
- // we implement /Zi type servers.
- BuildInfoRecord BIR(BuildInfoArgs);
- TypeIndex BuildInfoIndex = TypeTable.writeLeafType(BIR);
- // Make a new .debug$S subsection for the S_BUILDINFO record, which points
- // from the module symbols into the type stream.
- MCSymbol *BISubsecEnd = beginCVSubsection(DebugSubsectionKind::Symbols);
- MCSymbol *BIEnd = beginSymbolRecord(SymbolKind::S_BUILDINFO);
- OS.AddComment("LF_BUILDINFO index");
- OS.EmitIntValue(BuildInfoIndex.getIndex(), 4);
- endSymbolRecord(BIEnd);
- endCVSubsection(BISubsecEnd);
- }
- void CodeViewDebug::emitInlineeLinesSubsection() {
- if (InlinedSubprograms.empty())
- return;
- OS.AddComment("Inlinee lines subsection");
- MCSymbol *InlineEnd = beginCVSubsection(DebugSubsectionKind::InlineeLines);
- // We emit the checksum info for files. This is used by debuggers to
- // determine if a pdb matches the source before loading it. Visual Studio,
- // for instance, will display a warning that the breakpoints are not valid if
- // the pdb does not match the source.
- OS.AddComment("Inlinee lines signature");
- OS.EmitIntValue(unsigned(InlineeLinesSignature::Normal), 4);
- for (const DISubprogram *SP : InlinedSubprograms) {
- assert(TypeIndices.count({SP, nullptr}));
- TypeIndex InlineeIdx = TypeIndices[{SP, nullptr}];
- OS.AddBlankLine();
- unsigned FileId = maybeRecordFile(SP->getFile());
- OS.AddComment("Inlined function " + SP->getName() + " starts at " +
- SP->getFilename() + Twine(':') + Twine(SP->getLine()));
- OS.AddBlankLine();
- OS.AddComment("Type index of inlined function");
- OS.EmitIntValue(InlineeIdx.getIndex(), 4);
- OS.AddComment("Offset into filechecksum table");
- OS.EmitCVFileChecksumOffsetDirective(FileId);
- OS.AddComment("Starting line number");
- OS.EmitIntValue(SP->getLine(), 4);
- }
- endCVSubsection(InlineEnd);
- }
- void CodeViewDebug::emitInlinedCallSite(const FunctionInfo &FI,
- const DILocation *InlinedAt,
- const InlineSite &Site) {
- assert(TypeIndices.count({Site.Inlinee, nullptr}));
- TypeIndex InlineeIdx = TypeIndices[{Site.Inlinee, nullptr}];
- // SymbolRecord
- MCSymbol *InlineEnd = beginSymbolRecord(SymbolKind::S_INLINESITE);
- OS.AddComment("PtrParent");
- OS.EmitIntValue(0, 4);
- OS.AddComment("PtrEnd");
- OS.EmitIntValue(0, 4);
- OS.AddComment("Inlinee type index");
- OS.EmitIntValue(InlineeIdx.getIndex(), 4);
- unsigned FileId = maybeRecordFile(Site.Inlinee->getFile());
- unsigned StartLineNum = Site.Inlinee->getLine();
- OS.EmitCVInlineLinetableDirective(Site.SiteFuncId, FileId, StartLineNum,
- FI.Begin, FI.End);
- endSymbolRecord(InlineEnd);
- emitLocalVariableList(FI, Site.InlinedLocals);
- // Recurse on child inlined call sites before closing the scope.
- for (const DILocation *ChildSite : Site.ChildSites) {
- auto I = FI.InlineSites.find(ChildSite);
- assert(I != FI.InlineSites.end() &&
- "child site not in function inline site map");
- emitInlinedCallSite(FI, ChildSite, I->second);
- }
- // Close the scope.
- emitEndSymbolRecord(SymbolKind::S_INLINESITE_END);
- }
- void CodeViewDebug::switchToDebugSectionForSymbol(const MCSymbol *GVSym) {
- // If we have a symbol, it may be in a section that is COMDAT. If so, find the
- // comdat key. A section may be comdat because of -ffunction-sections or
- // because it is comdat in the IR.
- MCSectionCOFF *GVSec =
- GVSym ? dyn_cast<MCSectionCOFF>(&GVSym->getSection()) : nullptr;
- const MCSymbol *KeySym = GVSec ? GVSec->getCOMDATSymbol() : nullptr;
- MCSectionCOFF *DebugSec = cast<MCSectionCOFF>(
- Asm->getObjFileLowering().getCOFFDebugSymbolsSection());
- DebugSec = OS.getContext().getAssociativeCOFFSection(DebugSec, KeySym);
- OS.SwitchSection(DebugSec);
- // Emit the magic version number if this is the first time we've switched to
- // this section.
- if (ComdatDebugSections.insert(DebugSec).second)
- emitCodeViewMagicVersion();
- }
- // Emit an S_THUNK32/S_END symbol pair for a thunk routine.
- // The only supported thunk ordinal is currently the standard type.
- void CodeViewDebug::emitDebugInfoForThunk(const Function *GV,
- FunctionInfo &FI,
- const MCSymbol *Fn) {
- std::string FuncName = GlobalValue::dropLLVMManglingEscape(GV->getName());
- const ThunkOrdinal ordinal = ThunkOrdinal::Standard; // Only supported kind.
- OS.AddComment("Symbol subsection for " + Twine(FuncName));
- MCSymbol *SymbolsEnd = beginCVSubsection(DebugSubsectionKind::Symbols);
- // Emit S_THUNK32
- MCSymbol *ThunkRecordEnd = beginSymbolRecord(SymbolKind::S_THUNK32);
- OS.AddComment("PtrParent");
- OS.EmitIntValue(0, 4);
- OS.AddComment("PtrEnd");
- OS.EmitIntValue(0, 4);
- OS.AddComment("PtrNext");
- OS.EmitIntValue(0, 4);
- OS.AddComment("Thunk section relative address");
- OS.EmitCOFFSecRel32(Fn, /*Offset=*/0);
- OS.AddComment("Thunk section index");
- OS.EmitCOFFSectionIndex(Fn);
- OS.AddComment("Code size");
- OS.emitAbsoluteSymbolDiff(FI.End, Fn, 2);
- OS.AddComment("Ordinal");
- OS.EmitIntValue(unsigned(ordinal), 1);
- OS.AddComment("Function name");
- emitNullTerminatedSymbolName(OS, FuncName);
- // Additional fields specific to the thunk ordinal would go here.
- endSymbolRecord(ThunkRecordEnd);
- // Local variables/inlined routines are purposely omitted here. The point of
- // marking this as a thunk is so Visual Studio will NOT stop in this routine.
- // Emit S_PROC_ID_END
- emitEndSymbolRecord(SymbolKind::S_PROC_ID_END);
- endCVSubsection(SymbolsEnd);
- }
- void CodeViewDebug::emitDebugInfoForFunction(const Function *GV,
- FunctionInfo &FI) {
- // For each function there is a separate subsection which holds the PC to
- // file:line table.
- const MCSymbol *Fn = Asm->getSymbol(GV);
- assert(Fn);
- // Switch to the to a comdat section, if appropriate.
- switchToDebugSectionForSymbol(Fn);
- std::string FuncName;
- auto *SP = GV->getSubprogram();
- assert(SP);
- setCurrentSubprogram(SP);
- if (SP->isThunk()) {
- emitDebugInfoForThunk(GV, FI, Fn);
- return;
- }
- // If we have a display name, build the fully qualified name by walking the
- // chain of scopes.
- if (!SP->getName().empty())
- FuncName =
- getFullyQualifiedName(SP->getScope().resolve(), SP->getName());
- // If our DISubprogram name is empty, use the mangled name.
- if (FuncName.empty())
- FuncName = GlobalValue::dropLLVMManglingEscape(GV->getName());
- // Emit FPO data, but only on 32-bit x86. No other platforms use it.
- if (Triple(MMI->getModule()->getTargetTriple()).getArch() == Triple::x86)
- OS.EmitCVFPOData(Fn);
- // Emit a symbol subsection, required by VS2012+ to find function boundaries.
- OS.AddComment("Symbol subsection for " + Twine(FuncName));
- MCSymbol *SymbolsEnd = beginCVSubsection(DebugSubsectionKind::Symbols);
- {
- SymbolKind ProcKind = GV->hasLocalLinkage() ? SymbolKind::S_LPROC32_ID
- : SymbolKind::S_GPROC32_ID;
- MCSymbol *ProcRecordEnd = beginSymbolRecord(ProcKind);
- // These fields are filled in by tools like CVPACK which run after the fact.
- OS.AddComment("PtrParent");
- OS.EmitIntValue(0, 4);
- OS.AddComment("PtrEnd");
- OS.EmitIntValue(0, 4);
- OS.AddComment("PtrNext");
- OS.EmitIntValue(0, 4);
- // This is the important bit that tells the debugger where the function
- // code is located and what's its size:
- OS.AddComment("Code size");
- OS.emitAbsoluteSymbolDiff(FI.End, Fn, 4);
- OS.AddComment("Offset after prologue");
- OS.EmitIntValue(0, 4);
- OS.AddComment("Offset before epilogue");
- OS.EmitIntValue(0, 4);
- OS.AddComment("Function type index");
- OS.EmitIntValue(getFuncIdForSubprogram(GV->getSubprogram()).getIndex(), 4);
- OS.AddComment("Function section relative address");
- OS.EmitCOFFSecRel32(Fn, /*Offset=*/0);
- OS.AddComment("Function section index");
- OS.EmitCOFFSectionIndex(Fn);
- OS.AddComment("Flags");
- OS.EmitIntValue(0, 1);
- // Emit the function display name as a null-terminated string.
- OS.AddComment("Function name");
- // Truncate the name so we won't overflow the record length field.
- emitNullTerminatedSymbolName(OS, FuncName);
- endSymbolRecord(ProcRecordEnd);
- MCSymbol *FrameProcEnd = beginSymbolRecord(SymbolKind::S_FRAMEPROC);
- // Subtract out the CSR size since MSVC excludes that and we include it.
- OS.AddComment("FrameSize");
- OS.EmitIntValue(FI.FrameSize - FI.CSRSize, 4);
- OS.AddComment("Padding");
- OS.EmitIntValue(0, 4);
- OS.AddComment("Offset of padding");
- OS.EmitIntValue(0, 4);
- OS.AddComment("Bytes of callee saved registers");
- OS.EmitIntValue(FI.CSRSize, 4);
- OS.AddComment("Exception handler offset");
- OS.EmitIntValue(0, 4);
- OS.AddComment("Exception handler section");
- OS.EmitIntValue(0, 2);
- OS.AddComment("Flags (defines frame register)");
- OS.EmitIntValue(uint32_t(FI.FrameProcOpts), 4);
- endSymbolRecord(FrameProcEnd);
- emitLocalVariableList(FI, FI.Locals);
- emitGlobalVariableList(FI.Globals);
- emitLexicalBlockList(FI.ChildBlocks, FI);
- // Emit inlined call site information. Only emit functions inlined directly
- // into the parent function. We'll emit the other sites recursively as part
- // of their parent inline site.
- for (const DILocation *InlinedAt : FI.ChildSites) {
- auto I = FI.InlineSites.find(InlinedAt);
- assert(I != FI.InlineSites.end() &&
- "child site not in function inline site map");
- emitInlinedCallSite(FI, InlinedAt, I->second);
- }
- for (auto Annot : FI.Annotations) {
- MCSymbol *Label = Annot.first;
- MDTuple *Strs = cast<MDTuple>(Annot.second);
- MCSymbol *AnnotEnd = beginSymbolRecord(SymbolKind::S_ANNOTATION);
- OS.EmitCOFFSecRel32(Label, /*Offset=*/0);
- // FIXME: Make sure we don't overflow the max record size.
- OS.EmitCOFFSectionIndex(Label);
- OS.EmitIntValue(Strs->getNumOperands(), 2);
- for (Metadata *MD : Strs->operands()) {
- // MDStrings are null terminated, so we can do EmitBytes and get the
- // nice .asciz directive.
- StringRef Str = cast<MDString>(MD)->getString();
- assert(Str.data()[Str.size()] == '\0' && "non-nullterminated MDString");
- OS.EmitBytes(StringRef(Str.data(), Str.size() + 1));
- }
- endSymbolRecord(AnnotEnd);
- }
- if (SP != nullptr)
- emitDebugInfoForUDTs(LocalUDTs);
- // We're done with this function.
- emitEndSymbolRecord(SymbolKind::S_PROC_ID_END);
- }
- endCVSubsection(SymbolsEnd);
- // We have an assembler directive that takes care of the whole line table.
- OS.EmitCVLinetableDirective(FI.FuncId, Fn, FI.End);
- }
- CodeViewDebug::LocalVarDefRange
- CodeViewDebug::createDefRangeMem(uint16_t CVRegister, int Offset) {
- LocalVarDefRange DR;
- DR.InMemory = -1;
- DR.DataOffset = Offset;
- assert(DR.DataOffset == Offset && "truncation");
- DR.IsSubfield = 0;
- DR.StructOffset = 0;
- DR.CVRegister = CVRegister;
- return DR;
- }
- void CodeViewDebug::collectVariableInfoFromMFTable(
- DenseSet<InlinedEntity> &Processed) {
- const MachineFunction &MF = *Asm->MF;
- const TargetSubtargetInfo &TSI = MF.getSubtarget();
- const TargetFrameLowering *TFI = TSI.getFrameLowering();
- const TargetRegisterInfo *TRI = TSI.getRegisterInfo();
- for (const MachineFunction::VariableDbgInfo &VI : MF.getVariableDbgInfo()) {
- if (!VI.Var)
- continue;
- assert(VI.Var->isValidLocationForIntrinsic(VI.Loc) &&
- "Expected inlined-at fields to agree");
- Processed.insert(InlinedEntity(VI.Var, VI.Loc->getInlinedAt()));
- LexicalScope *Scope = LScopes.findLexicalScope(VI.Loc);
- // If variable scope is not found then skip this variable.
- if (!Scope)
- continue;
- // If the variable has an attached offset expression, extract it.
- // FIXME: Try to handle DW_OP_deref as well.
- int64_t ExprOffset = 0;
- if (VI.Expr)
- if (!VI.Expr->extractIfOffset(ExprOffset))
- continue;
- // Get the frame register used and the offset.
- unsigned FrameReg = 0;
- int FrameOffset = TFI->getFrameIndexReference(*Asm->MF, VI.Slot, FrameReg);
- uint16_t CVReg = TRI->getCodeViewRegNum(FrameReg);
- // Calculate the label ranges.
- LocalVarDefRange DefRange =
- createDefRangeMem(CVReg, FrameOffset + ExprOffset);
- for (const InsnRange &Range : Scope->getRanges()) {
- const MCSymbol *Begin = getLabelBeforeInsn(Range.first);
- const MCSymbol *End = getLabelAfterInsn(Range.second);
- End = End ? End : Asm->getFunctionEnd();
- DefRange.Ranges.emplace_back(Begin, End);
- }
- LocalVariable Var;
- Var.DIVar = VI.Var;
- Var.DefRanges.emplace_back(std::move(DefRange));
- recordLocalVariable(std::move(Var), Scope);
- }
- }
- static bool canUseReferenceType(const DbgVariableLocation &Loc) {
- return !Loc.LoadChain.empty() && Loc.LoadChain.back() == 0;
- }
- static bool needsReferenceType(const DbgVariableLocation &Loc) {
- return Loc.LoadChain.size() == 2 && Loc.LoadChain.back() == 0;
- }
- void CodeViewDebug::calculateRanges(
- LocalVariable &Var, const DbgValueHistoryMap::InstrRanges &Ranges) {
- const TargetRegisterInfo *TRI = Asm->MF->getSubtarget().getRegisterInfo();
- // Calculate the definition ranges.
- for (auto I = Ranges.begin(), E = Ranges.end(); I != E; ++I) {
- const InsnRange &Range = *I;
- const MachineInstr *DVInst = Range.first;
- assert(DVInst->isDebugValue() && "Invalid History entry");
- // FIXME: Find a way to represent constant variables, since they are
- // relatively common.
- Optional<DbgVariableLocation> Location =
- DbgVariableLocation::extractFromMachineInstruction(*DVInst);
- if (!Location)
- continue;
- // CodeView can only express variables in register and variables in memory
- // at a constant offset from a register. However, for variables passed
- // indirectly by pointer, it is common for that pointer to be spilled to a
- // stack location. For the special case of one offseted load followed by a
- // zero offset load (a pointer spilled to the stack), we change the type of
- // the local variable from a value type to a reference type. This tricks the
- // debugger into doing the load for us.
- if (Var.UseReferenceType) {
- // We're using a reference type. Drop the last zero offset load.
- if (canUseReferenceType(*Location))
- Location->LoadChain.pop_back();
- else
- continue;
- } else if (needsReferenceType(*Location)) {
- // This location can't be expressed without switching to a reference type.
- // Start over using that.
- Var.UseReferenceType = true;
- Var.DefRanges.clear();
- calculateRanges(Var, Ranges);
- return;
- }
- // We can only handle a register or an offseted load of a register.
- if (Location->Register == 0 || Location->LoadChain.size() > 1)
- continue;
- {
- LocalVarDefRange DR;
- DR.CVRegister = TRI->getCodeViewRegNum(Location->Register);
- DR.InMemory = !Location->LoadChain.empty();
- DR.DataOffset =
- !Location->LoadChain.empty() ? Location->LoadChain.back() : 0;
- if (Location->FragmentInfo) {
- DR.IsSubfield = true;
- DR.StructOffset = Location->FragmentInfo->OffsetInBits / 8;
- } else {
- DR.IsSubfield = false;
- DR.StructOffset = 0;
- }
- if (Var.DefRanges.empty() ||
- Var.DefRanges.back().isDifferentLocation(DR)) {
- Var.DefRanges.emplace_back(std::move(DR));
- }
- }
- // Compute the label range.
- const MCSymbol *Begin = getLabelBeforeInsn(Range.first);
- const MCSymbol *End = getLabelAfterInsn(Range.second);
- if (!End) {
- // This range is valid until the next overlapping bitpiece. In the
- // common case, ranges will not be bitpieces, so they will overlap.
- auto J = std::next(I);
- const DIExpression *DIExpr = DVInst->getDebugExpression();
- while (J != E &&
- !DIExpr->fragmentsOverlap(J->first->getDebugExpression()))
- ++J;
- if (J != E)
- End = getLabelBeforeInsn(J->first);
- else
- End = Asm->getFunctionEnd();
- }
- // If the last range end is our begin, just extend the last range.
- // Otherwise make a new range.
- SmallVectorImpl<std::pair<const MCSymbol *, const MCSymbol *>> &R =
- Var.DefRanges.back().Ranges;
- if (!R.empty() && R.back().second == Begin)
- R.back().second = End;
- else
- R.emplace_back(Begin, End);
- // FIXME: Do more range combining.
- }
- }
- void CodeViewDebug::collectVariableInfo(const DISubprogram *SP) {
- DenseSet<InlinedEntity> Processed;
- // Grab the variable info that was squirreled away in the MMI side-table.
- collectVariableInfoFromMFTable(Processed);
- for (const auto &I : DbgValues) {
- InlinedEntity IV = I.first;
- if (Processed.count(IV))
- continue;
- const DILocalVariable *DIVar = cast<DILocalVariable>(IV.first);
- const DILocation *InlinedAt = IV.second;
- // Instruction ranges, specifying where IV is accessible.
- const auto &Ranges = I.second;
- LexicalScope *Scope = nullptr;
- if (InlinedAt)
- Scope = LScopes.findInlinedScope(DIVar->getScope(), InlinedAt);
- else
- Scope = LScopes.findLexicalScope(DIVar->getScope());
- // If variable scope is not found then skip this variable.
- if (!Scope)
- continue;
- LocalVariable Var;
- Var.DIVar = DIVar;
- calculateRanges(Var, Ranges);
- recordLocalVariable(std::move(Var), Scope);
- }
- }
- void CodeViewDebug::beginFunctionImpl(const MachineFunction *MF) {
- const TargetSubtargetInfo &TSI = MF->getSubtarget();
- const TargetRegisterInfo *TRI = TSI.getRegisterInfo();
- const MachineFrameInfo &MFI = MF->getFrameInfo();
- const Function &GV = MF->getFunction();
- auto Insertion = FnDebugInfo.insert({&GV, llvm::make_unique<FunctionInfo>()});
- assert(Insertion.second && "function already has info");
- CurFn = Insertion.first->second.get();
- CurFn->FuncId = NextFuncId++;
- CurFn->Begin = Asm->getFunctionBegin();
- // The S_FRAMEPROC record reports the stack size, and how many bytes of
- // callee-saved registers were used. For targets that don't use a PUSH
- // instruction (AArch64), this will be zero.
- CurFn->CSRSize = MFI.getCVBytesOfCalleeSavedRegisters();
- CurFn->FrameSize = MFI.getStackSize();
- CurFn->OffsetAdjustment = MFI.getOffsetAdjustment();
- CurFn->HasStackRealignment = TRI->needsStackRealignment(*MF);
- // For this function S_FRAMEPROC record, figure out which codeview register
- // will be the frame pointer.
- CurFn->EncodedParamFramePtrReg = EncodedFramePtrReg::None; // None.
- CurFn->EncodedLocalFramePtrReg = EncodedFramePtrReg::None; // None.
- if (CurFn->FrameSize > 0) {
- if (!TSI.getFrameLowering()->hasFP(*MF)) {
- CurFn->EncodedLocalFramePtrReg = EncodedFramePtrReg::StackPtr;
- CurFn->EncodedParamFramePtrReg = EncodedFramePtrReg::StackPtr;
- } else {
- // If there is an FP, parameters are always relative to it.
- CurFn->EncodedParamFramePtrReg = EncodedFramePtrReg::FramePtr;
- if (CurFn->HasStackRealignment) {
- // If the stack needs realignment, locals are relative to SP or VFRAME.
- CurFn->EncodedLocalFramePtrReg = EncodedFramePtrReg::StackPtr;
- } else {
- // Otherwise, locals are relative to EBP, and we probably have VLAs or
- // other stack adjustments.
- CurFn->EncodedLocalFramePtrReg = EncodedFramePtrReg::FramePtr;
- }
- }
- }
- // Compute other frame procedure options.
- FrameProcedureOptions FPO = FrameProcedureOptions::None;
- if (MFI.hasVarSizedObjects())
- FPO |= FrameProcedureOptions::HasAlloca;
- if (MF->exposesReturnsTwice())
- FPO |= FrameProcedureOptions::HasSetJmp;
- // FIXME: Set HasLongJmp if we ever track that info.
- if (MF->hasInlineAsm())
- FPO |= FrameProcedureOptions::HasInlineAssembly;
- if (GV.hasPersonalityFn()) {
- if (isAsynchronousEHPersonality(
- classifyEHPersonality(GV.getPersonalityFn())))
- FPO |= FrameProcedureOptions::HasStructuredExceptionHandling;
- else
- FPO |= FrameProcedureOptions::HasExceptionHandling;
- }
- if (GV.hasFnAttribute(Attribute::InlineHint))
- FPO |= FrameProcedureOptions::MarkedInline;
- if (GV.hasFnAttribute(Attribute::Naked))
- FPO |= FrameProcedureOptions::Naked;
- if (MFI.hasStackProtectorIndex())
- FPO |= FrameProcedureOptions::SecurityChecks;
- FPO |= FrameProcedureOptions(uint32_t(CurFn->EncodedLocalFramePtrReg) << 14U);
- FPO |= FrameProcedureOptions(uint32_t(CurFn->EncodedParamFramePtrReg) << 16U);
- if (Asm->TM.getOptLevel() != CodeGenOpt::None &&
- !GV.hasOptSize() && !GV.hasOptNone())
- FPO |= FrameProcedureOptions::OptimizedForSpeed;
- // FIXME: Set GuardCfg when it is implemented.
- CurFn->FrameProcOpts = FPO;
- OS.EmitCVFuncIdDirective(CurFn->FuncId);
- // Find the end of the function prolog. First known non-DBG_VALUE and
- // non-frame setup location marks the beginning of the function body.
- // FIXME: is there a simpler a way to do this? Can we just search
- // for the first instruction of the function, not the last of the prolog?
- DebugLoc PrologEndLoc;
- bool EmptyPrologue = true;
- for (const auto &MBB : *MF) {
- for (const auto &MI : MBB) {
- if (!MI.isMetaInstruction() && !MI.getFlag(MachineInstr::FrameSetup) &&
- MI.getDebugLoc()) {
- PrologEndLoc = MI.getDebugLoc();
- break;
- } else if (!MI.isMetaInstruction()) {
- EmptyPrologue = false;
- }
- }
- }
- // Record beginning of function if we have a non-empty prologue.
- if (PrologEndLoc && !EmptyPrologue) {
- DebugLoc FnStartDL = PrologEndLoc.getFnDebugLoc();
- maybeRecordLocation(FnStartDL, MF);
- }
- }
- static bool shouldEmitUdt(const DIType *T) {
- if (!T)
- return false;
- // MSVC does not emit UDTs for typedefs that are scoped to classes.
- if (T->getTag() == dwarf::DW_TAG_typedef) {
- if (DIScope *Scope = T->getScope().resolve()) {
- switch (Scope->getTag()) {
- case dwarf::DW_TAG_structure_type:
- case dwarf::DW_TAG_class_type:
- case dwarf::DW_TAG_union_type:
- return false;
- }
- }
- }
- while (true) {
- if (!T || T->isForwardDecl())
- return false;
- const DIDerivedType *DT = dyn_cast<DIDerivedType>(T);
- if (!DT)
- return true;
- T = DT->getBaseType().resolve();
- }
- return true;
- }
- void CodeViewDebug::addToUDTs(const DIType *Ty) {
- // Don't record empty UDTs.
- if (Ty->getName().empty())
- return;
- if (!shouldEmitUdt(Ty))
- return;
- SmallVector<StringRef, 5> QualifiedNameComponents;
- const DISubprogram *ClosestSubprogram = getQualifiedNameComponents(
- Ty->getScope().resolve(), QualifiedNameComponents);
- std::string FullyQualifiedName =
- getQualifiedName(QualifiedNameComponents, getPrettyScopeName(Ty));
- if (ClosestSubprogram == nullptr) {
- GlobalUDTs.emplace_back(std::move(FullyQualifiedName), Ty);
- } else if (ClosestSubprogram == CurrentSubprogram) {
- LocalUDTs.emplace_back(std::move(FullyQualifiedName), Ty);
- }
- // TODO: What if the ClosestSubprogram is neither null or the current
- // subprogram? Currently, the UDT just gets dropped on the floor.
- //
- // The current behavior is not desirable. To get maximal fidelity, we would
- // need to perform all type translation before beginning emission of .debug$S
- // and then make LocalUDTs a member of FunctionInfo
- }
- TypeIndex CodeViewDebug::lowerType(const DIType *Ty, const DIType *ClassTy) {
- // Generic dispatch for lowering an unknown type.
- switch (Ty->getTag()) {
- case dwarf::DW_TAG_array_type:
- return lowerTypeArray(cast<DICompositeType>(Ty));
- case dwarf::DW_TAG_typedef:
- return lowerTypeAlias(cast<DIDerivedType>(Ty));
- case dwarf::DW_TAG_base_type:
- return lowerTypeBasic(cast<DIBasicType>(Ty));
- case dwarf::DW_TAG_pointer_type:
- if (cast<DIDerivedType>(Ty)->getName() == "__vtbl_ptr_type")
- return lowerTypeVFTableShape(cast<DIDerivedType>(Ty));
- LLVM_FALLTHROUGH;
- case dwarf::DW_TAG_reference_type:
- case dwarf::DW_TAG_rvalue_reference_type:
- return lowerTypePointer(cast<DIDerivedType>(Ty));
- case dwarf::DW_TAG_ptr_to_member_type:
- return lowerTypeMemberPointer(cast<DIDerivedType>(Ty));
- case dwarf::DW_TAG_restrict_type:
- case dwarf::DW_TAG_const_type:
- case dwarf::DW_TAG_volatile_type:
- // TODO: add support for DW_TAG_atomic_type here
- return lowerTypeModifier(cast<DIDerivedType>(Ty));
- case dwarf::DW_TAG_subroutine_type:
- if (ClassTy) {
- // The member function type of a member function pointer has no
- // ThisAdjustment.
- return lowerTypeMemberFunction(cast<DISubroutineType>(Ty), ClassTy,
- /*ThisAdjustment=*/0,
- /*IsStaticMethod=*/false);
- }
- return lowerTypeFunction(cast<DISubroutineType>(Ty));
- case dwarf::DW_TAG_enumeration_type:
- return lowerTypeEnum(cast<DICompositeType>(Ty));
- case dwarf::DW_TAG_class_type:
- case dwarf::DW_TAG_structure_type:
- return lowerTypeClass(cast<DICompositeType>(Ty));
- case dwarf::DW_TAG_union_type:
- return lowerTypeUnion(cast<DICompositeType>(Ty));
- case dwarf::DW_TAG_unspecified_type:
- if (Ty->getName() == "decltype(nullptr)")
- return TypeIndex::NullptrT();
- return TypeIndex::None();
- default:
- // Use the null type index.
- return TypeIndex();
- }
- }
- TypeIndex CodeViewDebug::lowerTypeAlias(const DIDerivedType *Ty) {
- DITypeRef UnderlyingTypeRef = Ty->getBaseType();
- TypeIndex UnderlyingTypeIndex = getTypeIndex(UnderlyingTypeRef);
- StringRef TypeName = Ty->getName();
- addToUDTs(Ty);
- if (UnderlyingTypeIndex == TypeIndex(SimpleTypeKind::Int32Long) &&
- TypeName == "HRESULT")
- return TypeIndex(SimpleTypeKind::HResult);
- if (UnderlyingTypeIndex == TypeIndex(SimpleTypeKind::UInt16Short) &&
- TypeName == "wchar_t")
- return TypeIndex(SimpleTypeKind::WideCharacter);
- return UnderlyingTypeIndex;
- }
- TypeIndex CodeViewDebug::lowerTypeArray(const DICompositeType *Ty) {
- DITypeRef ElementTypeRef = Ty->getBaseType();
- TypeIndex ElementTypeIndex = getTypeIndex(ElementTypeRef);
- // IndexType is size_t, which depends on the bitness of the target.
- TypeIndex IndexType = getPointerSizeInBytes() == 8
- ? TypeIndex(SimpleTypeKind::UInt64Quad)
- : TypeIndex(SimpleTypeKind::UInt32Long);
- uint64_t ElementSize = getBaseTypeSize(ElementTypeRef) / 8;
- // Add subranges to array type.
- DINodeArray Elements = Ty->getElements();
- for (int i = Elements.size() - 1; i >= 0; --i) {
- const DINode *Element = Elements[i];
- assert(Element->getTag() == dwarf::DW_TAG_subrange_type);
- const DISubrange *Subrange = cast<DISubrange>(Element);
- assert(Subrange->getLowerBound() == 0 &&
- "codeview doesn't support subranges with lower bounds");
- int64_t Count = -1;
- if (auto *CI = Subrange->getCount().dyn_cast<ConstantInt*>())
- Count = CI->getSExtValue();
- // Forward declarations of arrays without a size and VLAs use a count of -1.
- // Emit a count of zero in these cases to match what MSVC does for arrays
- // without a size. MSVC doesn't support VLAs, so it's not clear what we
- // should do for them even if we could distinguish them.
- if (Count == -1)
- Count = 0;
- // Update the element size and element type index for subsequent subranges.
- ElementSize *= Count;
- // If this is the outermost array, use the size from the array. It will be
- // more accurate if we had a VLA or an incomplete element type size.
- uint64_t ArraySize =
- (i == 0 && ElementSize == 0) ? Ty->getSizeInBits() / 8 : ElementSize;
- StringRef Name = (i == 0) ? Ty->getName() : "";
- ArrayRecord AR(ElementTypeIndex, IndexType, ArraySize, Name);
- ElementTypeIndex = TypeTable.writeLeafType(AR);
- }
- return ElementTypeIndex;
- }
- TypeIndex CodeViewDebug::lowerTypeBasic(const DIBasicType *Ty) {
- TypeIndex Index;
- dwarf::TypeKind Kind;
- uint32_t ByteSize;
- Kind = static_cast<dwarf::TypeKind>(Ty->getEncoding());
- ByteSize = Ty->getSizeInBits() / 8;
- SimpleTypeKind STK = SimpleTypeKind::None;
- switch (Kind) {
- case dwarf::DW_ATE_address:
- // FIXME: Translate
- break;
- case dwarf::DW_ATE_boolean:
- switch (ByteSize) {
- case 1: STK = SimpleTypeKind::Boolean8; break;
- case 2: STK = SimpleTypeKind::Boolean16; break;
- case 4: STK = SimpleTypeKind::Boolean32; break;
- case 8: STK = SimpleTypeKind::Boolean64; break;
- case 16: STK = SimpleTypeKind::Boolean128; break;
- }
- break;
- case dwarf::DW_ATE_complex_float:
- switch (ByteSize) {
- case 2: STK = SimpleTypeKind::Complex16; break;
- case 4: STK = SimpleTypeKind::Complex32; break;
- case 8: STK = SimpleTypeKind::Complex64; break;
- case 10: STK = SimpleTypeKind::Complex80; break;
- case 16: STK = SimpleTypeKind::Complex128; break;
- }
- break;
- case dwarf::DW_ATE_float:
- switch (ByteSize) {
- case 2: STK = SimpleTypeKind::Float16; break;
- case 4: STK = SimpleTypeKind::Float32; break;
- case 6: STK = SimpleTypeKind::Float48; break;
- case 8: STK = SimpleTypeKind::Float64; break;
- case 10: STK = SimpleTypeKind::Float80; break;
- case 16: STK = SimpleTypeKind::Float128; break;
- }
- break;
- case dwarf::DW_ATE_signed:
- switch (ByteSize) {
- case 1: STK = SimpleTypeKind::SignedCharacter; break;
- case 2: STK = SimpleTypeKind::Int16Short; break;
- case 4: STK = SimpleTypeKind::Int32; break;
- case 8: STK = SimpleTypeKind::Int64Quad; break;
- case 16: STK = SimpleTypeKind::Int128Oct; break;
- }
- break;
- case dwarf::DW_ATE_unsigned:
- switch (ByteSize) {
- case 1: STK = SimpleTypeKind::UnsignedCharacter; break;
- case 2: STK = SimpleTypeKind::UInt16Short; break;
- case 4: STK = SimpleTypeKind::UInt32; break;
- case 8: STK = SimpleTypeKind::UInt64Quad; break;
- case 16: STK = SimpleTypeKind::UInt128Oct; break;
- }
- break;
- case dwarf::DW_ATE_UTF:
- switch (ByteSize) {
- case 2: STK = SimpleTypeKind::Character16; break;
- case 4: STK = SimpleTypeKind::Character32; break;
- }
- break;
- case dwarf::DW_ATE_signed_char:
- if (ByteSize == 1)
- STK = SimpleTypeKind::SignedCharacter;
- break;
- case dwarf::DW_ATE_unsigned_char:
- if (ByteSize == 1)
- STK = SimpleTypeKind::UnsignedCharacter;
- break;
- default:
- break;
- }
- // Apply some fixups based on the source-level type name.
- if (STK == SimpleTypeKind::Int32 && Ty->getName() == "long int")
- STK = SimpleTypeKind::Int32Long;
- if (STK == SimpleTypeKind::UInt32 && Ty->getName() == "long unsigned int")
- STK = SimpleTypeKind::UInt32Long;
- if (STK == SimpleTypeKind::UInt16Short &&
- (Ty->getName() == "wchar_t" || Ty->getName() == "__wchar_t"))
- STK = SimpleTypeKind::WideCharacter;
- if ((STK == SimpleTypeKind::SignedCharacter ||
- STK == SimpleTypeKind::UnsignedCharacter) &&
- Ty->getName() == "char")
- STK = SimpleTypeKind::NarrowCharacter;
- return TypeIndex(STK);
- }
- TypeIndex CodeViewDebug::lowerTypePointer(const DIDerivedType *Ty,
- PointerOptions PO) {
- TypeIndex PointeeTI = getTypeIndex(Ty->getBaseType());
- // Pointers to simple types without any options can use SimpleTypeMode, rather
- // than having a dedicated pointer type record.
- if (PointeeTI.isSimple() && PO == PointerOptions::None &&
- PointeeTI.getSimpleMode() == SimpleTypeMode::Direct &&
- Ty->getTag() == dwarf::DW_TAG_pointer_type) {
- SimpleTypeMode Mode = Ty->getSizeInBits() == 64
- ? SimpleTypeMode::NearPointer64
- : SimpleTypeMode::NearPointer32;
- return TypeIndex(PointeeTI.getSimpleKind(), Mode);
- }
- PointerKind PK =
- Ty->getSizeInBits() == 64 ? PointerKind::Near64 : PointerKind::Near32;
- PointerMode PM = PointerMode::Pointer;
- switch (Ty->getTag()) {
- default: llvm_unreachable("not a pointer tag type");
- case dwarf::DW_TAG_pointer_type:
- PM = PointerMode::Pointer;
- break;
- case dwarf::DW_TAG_reference_type:
- PM = PointerMode::LValueReference;
- break;
- case dwarf::DW_TAG_rvalue_reference_type:
- PM = PointerMode::RValueReference;
- break;
- }
- if (Ty->isObjectPointer())
- PO |= PointerOptions::Const;
- PointerRecord PR(PointeeTI, PK, PM, PO, Ty->getSizeInBits() / 8);
- return TypeTable.writeLeafType(PR);
- }
- static PointerToMemberRepresentation
- translatePtrToMemberRep(unsigned SizeInBytes, bool IsPMF, unsigned Flags) {
- // SizeInBytes being zero generally implies that the member pointer type was
- // incomplete, which can happen if it is part of a function prototype. In this
- // case, use the unknown model instead of the general model.
- if (IsPMF) {
- switch (Flags & DINode::FlagPtrToMemberRep) {
- case 0:
- return SizeInBytes == 0 ? PointerToMemberRepresentation::Unknown
- : PointerToMemberRepresentation::GeneralFunction;
- case DINode::FlagSingleInheritance:
- return PointerToMemberRepresentation::SingleInheritanceFunction;
- case DINode::FlagMultipleInheritance:
- return PointerToMemberRepresentation::MultipleInheritanceFunction;
- case DINode::FlagVirtualInheritance:
- return PointerToMemberRepresentation::VirtualInheritanceFunction;
- }
- } else {
- switch (Flags & DINode::FlagPtrToMemberRep) {
- case 0:
- return SizeInBytes == 0 ? PointerToMemberRepresentation::Unknown
- : PointerToMemberRepresentation::GeneralData;
- case DINode::FlagSingleInheritance:
- return PointerToMemberRepresentation::SingleInheritanceData;
- case DINode::FlagMultipleInheritance:
- return PointerToMemberRepresentation::MultipleInheritanceData;
- case DINode::FlagVirtualInheritance:
- return PointerToMemberRepresentation::VirtualInheritanceData;
- }
- }
- llvm_unreachable("invalid ptr to member representation");
- }
- TypeIndex CodeViewDebug::lowerTypeMemberPointer(const DIDerivedType *Ty,
- PointerOptions PO) {
- assert(Ty->getTag() == dwarf::DW_TAG_ptr_to_member_type);
- TypeIndex ClassTI = getTypeIndex(Ty->getClassType());
- TypeIndex PointeeTI = getTypeIndex(Ty->getBaseType(), Ty->getClassType());
- PointerKind PK = getPointerSizeInBytes() == 8 ? PointerKind::Near64
- : PointerKind::Near32;
- bool IsPMF = isa<DISubroutineType>(Ty->getBaseType());
- PointerMode PM = IsPMF ? PointerMode::PointerToMemberFunction
- : PointerMode::PointerToDataMember;
- assert(Ty->getSizeInBits() / 8 <= 0xff && "pointer size too big");
- uint8_t SizeInBytes = Ty->getSizeInBits() / 8;
- MemberPointerInfo MPI(
- ClassTI, translatePtrToMemberRep(SizeInBytes, IsPMF, Ty->getFlags()));
- PointerRecord PR(PointeeTI, PK, PM, PO, SizeInBytes, MPI);
- return TypeTable.writeLeafType(PR);
- }
- /// Given a DWARF calling convention, get the CodeView equivalent. If we don't
- /// have a translation, use the NearC convention.
- static CallingConvention dwarfCCToCodeView(unsigned DwarfCC) {
- switch (DwarfCC) {
- case dwarf::DW_CC_normal: return CallingConvention::NearC;
- case dwarf::DW_CC_BORLAND_msfastcall: return CallingConvention::NearFast;
- case dwarf::DW_CC_BORLAND_thiscall: return CallingConvention::ThisCall;
- case dwarf::DW_CC_BORLAND_stdcall: return CallingConvention::NearStdCall;
- case dwarf::DW_CC_BORLAND_pascal: return CallingConvention::NearPascal;
- case dwarf::DW_CC_LLVM_vectorcall: return CallingConvention::NearVector;
- }
- return CallingConvention::NearC;
- }
- TypeIndex CodeViewDebug::lowerTypeModifier(const DIDerivedType *Ty) {
- ModifierOptions Mods = ModifierOptions::None;
- PointerOptions PO = PointerOptions::None;
- bool IsModifier = true;
- const DIType *BaseTy = Ty;
- while (IsModifier && BaseTy) {
- // FIXME: Need to add DWARF tags for __unaligned and _Atomic
- switch (BaseTy->getTag()) {
- case dwarf::DW_TAG_const_type:
- Mods |= ModifierOptions::Const;
- PO |= PointerOptions::Const;
- break;
- case dwarf::DW_TAG_volatile_type:
- Mods |= ModifierOptions::Volatile;
- PO |= PointerOptions::Volatile;
- break;
- case dwarf::DW_TAG_restrict_type:
- // Only pointer types be marked with __restrict. There is no known flag
- // for __restrict in LF_MODIFIER records.
- PO |= PointerOptions::Restrict;
- break;
- default:
- IsModifier = false;
- break;
- }
- if (IsModifier)
- BaseTy = cast<DIDerivedType>(BaseTy)->getBaseType().resolve();
- }
- // Check if the inner type will use an LF_POINTER record. If so, the
- // qualifiers will go in the LF_POINTER record. This comes up for types like
- // 'int *const' and 'int *__restrict', not the more common cases like 'const
- // char *'.
- if (BaseTy) {
- switch (BaseTy->getTag()) {
- case dwarf::DW_TAG_pointer_type:
- case dwarf::DW_TAG_reference_type:
- case dwarf::DW_TAG_rvalue_reference_type:
- return lowerTypePointer(cast<DIDerivedType>(BaseTy), PO);
- case dwarf::DW_TAG_ptr_to_member_type:
- return lowerTypeMemberPointer(cast<DIDerivedType>(BaseTy), PO);
- default:
- break;
- }
- }
- TypeIndex ModifiedTI = getTypeIndex(BaseTy);
- // Return the base type index if there aren't any modifiers. For example, the
- // metadata could contain restrict wrappers around non-pointer types.
- if (Mods == ModifierOptions::None)
- return ModifiedTI;
- ModifierRecord MR(ModifiedTI, Mods);
- return TypeTable.writeLeafType(MR);
- }
- TypeIndex CodeViewDebug::lowerTypeFunction(const DISubroutineType *Ty) {
- SmallVector<TypeIndex, 8> ReturnAndArgTypeIndices;
- for (DITypeRef ArgTypeRef : Ty->getTypeArray())
- ReturnAndArgTypeIndices.push_back(getTypeIndex(ArgTypeRef));
- // MSVC uses type none for variadic argument.
- if (ReturnAndArgTypeIndices.size() > 1 &&
- ReturnAndArgTypeIndices.back() == TypeIndex::Void()) {
- ReturnAndArgTypeIndices.back() = TypeIndex::None();
- }
- TypeIndex ReturnTypeIndex = TypeIndex::Void();
- ArrayRef<TypeIndex> ArgTypeIndices = None;
- if (!ReturnAndArgTypeIndices.empty()) {
- auto ReturnAndArgTypesRef = makeArrayRef(ReturnAndArgTypeIndices);
- ReturnTypeIndex = ReturnAndArgTypesRef.front();
- ArgTypeIndices = ReturnAndArgTypesRef.drop_front();
- }
- ArgListRecord ArgListRec(TypeRecordKind::ArgList, ArgTypeIndices);
- TypeIndex ArgListIndex = TypeTable.writeLeafType(ArgListRec);
- CallingConvention CC = dwarfCCToCodeView(Ty->getCC());
- FunctionOptions FO = getFunctionOptions(Ty);
- ProcedureRecord Procedure(ReturnTypeIndex, CC, FO, ArgTypeIndices.size(),
- ArgListIndex);
- return TypeTable.writeLeafType(Procedure);
- }
- TypeIndex CodeViewDebug::lowerTypeMemberFunction(const DISubroutineType *Ty,
- const DIType *ClassTy,
- int ThisAdjustment,
- bool IsStaticMethod,
- FunctionOptions FO) {
- // Lower the containing class type.
- TypeIndex ClassType = getTypeIndex(ClassTy);
- DITypeRefArray ReturnAndArgs = Ty->getTypeArray();
- unsigned Index = 0;
- SmallVector<TypeIndex, 8> ArgTypeIndices;
- TypeIndex ReturnTypeIndex = TypeIndex::Void();
- if (ReturnAndArgs.size() > Index) {
- ReturnTypeIndex = getTypeIndex(ReturnAndArgs[Index++]);
- }
- // If the first argument is a pointer type and this isn't a static method,
- // treat it as the special 'this' parameter, which is encoded separately from
- // the arguments.
- TypeIndex ThisTypeIndex;
- if (!IsStaticMethod && ReturnAndArgs.size() > Index) {
- if (const DIDerivedType *PtrTy =
- dyn_cast_or_null<DIDerivedType>(ReturnAndArgs[Index].resolve())) {
- if (PtrTy->getTag() == dwarf::DW_TAG_pointer_type) {
- ThisTypeIndex = getTypeIndexForThisPtr(PtrTy, Ty);
- Index++;
- }
- }
- }
- while (Index < ReturnAndArgs.size())
- ArgTypeIndices.push_back(getTypeIndex(ReturnAndArgs[Index++]));
- // MSVC uses type none for variadic argument.
- if (!ArgTypeIndices.empty() && ArgTypeIndices.back() == TypeIndex::Void())
- ArgTypeIndices.back() = TypeIndex::None();
- ArgListRecord ArgListRec(TypeRecordKind::ArgList, ArgTypeIndices);
- TypeIndex ArgListIndex = TypeTable.writeLeafType(ArgListRec);
- CallingConvention CC = dwarfCCToCodeView(Ty->getCC());
- MemberFunctionRecord MFR(ReturnTypeIndex, ClassType, ThisTypeIndex, CC, FO,
- ArgTypeIndices.size(), ArgListIndex, ThisAdjustment);
- return TypeTable.writeLeafType(MFR);
- }
- TypeIndex CodeViewDebug::lowerTypeVFTableShape(const DIDerivedType *Ty) {
- unsigned VSlotCount =
- Ty->getSizeInBits() / (8 * Asm->MAI->getCodePointerSize());
- SmallVector<VFTableSlotKind, 4> Slots(VSlotCount, VFTableSlotKind::Near);
- VFTableShapeRecord VFTSR(Slots);
- return TypeTable.writeLeafType(VFTSR);
- }
- static MemberAccess translateAccessFlags(unsigned RecordTag, unsigned Flags) {
- switch (Flags & DINode::FlagAccessibility) {
- case DINode::FlagPrivate: return MemberAccess::Private;
- case DINode::FlagPublic: return MemberAccess::Public;
- case DINode::FlagProtected: return MemberAccess::Protected;
- case 0:
- // If there was no explicit access control, provide the default for the tag.
- return RecordTag == dwarf::DW_TAG_class_type ? MemberAccess::Private
- : MemberAccess::Public;
- }
- llvm_unreachable("access flags are exclusive");
- }
- static MethodOptions translateMethodOptionFlags(const DISubprogram *SP) {
- if (SP->isArtificial())
- return MethodOptions::CompilerGenerated;
- // FIXME: Handle other MethodOptions.
- return MethodOptions::None;
- }
- static MethodKind translateMethodKindFlags(const DISubprogram *SP,
- bool Introduced) {
- if (SP->getFlags() & DINode::FlagStaticMember)
- return MethodKind::Static;
- switch (SP->getVirtuality()) {
- case dwarf::DW_VIRTUALITY_none:
- break;
- case dwarf::DW_VIRTUALITY_virtual:
- return Introduced ? MethodKind::IntroducingVirtual : MethodKind::Virtual;
- case dwarf::DW_VIRTUALITY_pure_virtual:
- return Introduced ? MethodKind::PureIntroducingVirtual
- : MethodKind::PureVirtual;
- default:
- llvm_unreachable("unhandled virtuality case");
- }
- return MethodKind::Vanilla;
- }
- static TypeRecordKind getRecordKind(const DICompositeType *Ty) {
- switch (Ty->getTag()) {
- case dwarf::DW_TAG_class_type: return TypeRecordKind::Class;
- case dwarf::DW_TAG_structure_type: return TypeRecordKind::Struct;
- }
- llvm_unreachable("unexpected tag");
- }
- /// Return ClassOptions that should be present on both the forward declaration
- /// and the defintion of a tag type.
- static ClassOptions getCommonClassOptions(const DICompositeType *Ty) {
- ClassOptions CO = ClassOptions::None;
- // MSVC always sets this flag, even for local types. Clang doesn't always
- // appear to give every type a linkage name, which may be problematic for us.
- // FIXME: Investigate the consequences of not following them here.
- if (!Ty->getIdentifier().empty())
- CO |= ClassOptions::HasUniqueName;
- // Put the Nested flag on a type if it appears immediately inside a tag type.
- // Do not walk the scope chain. Do not attempt to compute ContainsNestedClass
- // here. That flag is only set on definitions, and not forward declarations.
- const DIScope *ImmediateScope = Ty->getScope().resolve();
- if (ImmediateScope && isa<DICompositeType>(ImmediateScope))
- CO |= ClassOptions::Nested;
- // Put the Scoped flag on function-local types. MSVC puts this flag for enum
- // type only when it has an immediate function scope. Clang never puts enums
- // inside DILexicalBlock scopes. Enum types, as generated by clang, are
- // always in function, class, or file scopes.
- if (Ty->getTag() == dwarf::DW_TAG_enumeration_type) {
- if (ImmediateScope && isa<DISubprogram>(ImmediateScope))
- CO |= ClassOptions::Scoped;
- } else {
- for (const DIScope *Scope = ImmediateScope; Scope != nullptr;
- Scope = Scope->getScope().resolve()) {
- if (isa<DISubprogram>(Scope)) {
- CO |= ClassOptions::Scoped;
- break;
- }
- }
- }
- return CO;
- }
- void CodeViewDebug::addUDTSrcLine(const DIType *Ty, TypeIndex TI) {
- switch (Ty->getTag()) {
- case dwarf::DW_TAG_class_type:
- case dwarf::DW_TAG_structure_type:
- case dwarf::DW_TAG_union_type:
- case dwarf::DW_TAG_enumeration_type:
- break;
- default:
- return;
- }
- if (const auto *File = Ty->getFile()) {
- StringIdRecord SIDR(TypeIndex(0x0), getFullFilepath(File));
- TypeIndex SIDI = TypeTable.writeLeafType(SIDR);
- UdtSourceLineRecord USLR(TI, SIDI, Ty->getLine());
- TypeTable.writeLeafType(USLR);
- }
- }
- TypeIndex CodeViewDebug::lowerTypeEnum(const DICompositeType *Ty) {
- ClassOptions CO = getCommonClassOptions(Ty);
- TypeIndex FTI;
- unsigned EnumeratorCount = 0;
- if (Ty->isForwardDecl()) {
- CO |= ClassOptions::ForwardReference;
- } else {
- ContinuationRecordBuilder ContinuationBuilder;
- ContinuationBuilder.begin(ContinuationRecordKind::FieldList);
- for (const DINode *Element : Ty->getElements()) {
- // We assume that the frontend provides all members in source declaration
- // order, which is what MSVC does.
- if (auto *Enumerator = dyn_cast_or_null<DIEnumerator>(Element)) {
- EnumeratorRecord ER(MemberAccess::Public,
- APSInt::getUnsigned(Enumerator->getValue()),
- Enumerator->getName());
- ContinuationBuilder.writeMemberType(ER);
- EnumeratorCount++;
- }
- }
- FTI = TypeTable.insertRecord(ContinuationBuilder);
- }
- std::string FullName = getFullyQualifiedName(Ty);
- EnumRecord ER(EnumeratorCount, CO, FTI, FullName, Ty->getIdentifier(),
- getTypeIndex(Ty->getBaseType()));
- TypeIndex EnumTI = TypeTable.writeLeafType(ER);
- addUDTSrcLine(Ty, EnumTI);
- return EnumTI;
- }
- //===----------------------------------------------------------------------===//
- // ClassInfo
- //===----------------------------------------------------------------------===//
- struct llvm::ClassInfo {
- struct MemberInfo {
- const DIDerivedType *MemberTypeNode;
- uint64_t BaseOffset;
- };
- // [MemberInfo]
- using MemberList = std::vector<MemberInfo>;
- using MethodsList = TinyPtrVector<const DISubprogram *>;
- // MethodName -> MethodsList
- using MethodsMap = MapVector<MDString *, MethodsList>;
- /// Base classes.
- std::vector<const DIDerivedType *> Inheritance;
- /// Direct members.
- MemberList Members;
- // Direct overloaded methods gathered by name.
- MethodsMap Methods;
- TypeIndex VShapeTI;
- std::vector<const DIType *> NestedTypes;
- };
- void CodeViewDebug::clear() {
- assert(CurFn == nullptr);
- FileIdMap.clear();
- FnDebugInfo.clear();
- FileToFilepathMap.clear();
- LocalUDTs.clear();
- GlobalUDTs.clear();
- TypeIndices.clear();
- CompleteTypeIndices.clear();
- ScopeGlobals.clear();
- }
- void CodeViewDebug::collectMemberInfo(ClassInfo &Info,
- const DIDerivedType *DDTy) {
- if (!DDTy->getName().empty()) {
- Info.Members.push_back({DDTy, 0});
- return;
- }
- // An unnamed member may represent a nested struct or union. Attempt to
- // interpret the unnamed member as a DICompositeType possibly wrapped in
- // qualifier types. Add all the indirect fields to the current record if that
- // succeeds, and drop the member if that fails.
- assert((DDTy->getOffsetInBits() % 8) == 0 && "Unnamed bitfield member!");
- uint64_t Offset = DDTy->getOffsetInBits();
- const DIType *Ty = DDTy->getBaseType().resolve();
- bool FullyResolved = false;
- while (!FullyResolved) {
- switch (Ty->getTag()) {
- case dwarf::DW_TAG_const_type:
- case dwarf::DW_TAG_volatile_type:
- // FIXME: we should apply the qualifier types to the indirect fields
- // rather than dropping them.
- Ty = cast<DIDerivedType>(Ty)->getBaseType().resolve();
- break;
- default:
- FullyResolved = true;
- break;
- }
- }
- const DICompositeType *DCTy = dyn_cast<DICompositeType>(Ty);
- if (!DCTy)
- return;
- ClassInfo NestedInfo = collectClassInfo(DCTy);
- for (const ClassInfo::MemberInfo &IndirectField : NestedInfo.Members)
- Info.Members.push_back(
- {IndirectField.MemberTypeNode, IndirectField.BaseOffset + Offset});
- }
- ClassInfo CodeViewDebug::collectClassInfo(const DICompositeType *Ty) {
- ClassInfo Info;
- // Add elements to structure type.
- DINodeArray Elements = Ty->getElements();
- for (auto *Element : Elements) {
- // We assume that the frontend provides all members in source declaration
- // order, which is what MSVC does.
- if (!Element)
- continue;
- if (auto *SP = dyn_cast<DISubprogram>(Element)) {
- Info.Methods[SP->getRawName()].push_back(SP);
- } else if (auto *DDTy = dyn_cast<DIDerivedType>(Element)) {
- if (DDTy->getTag() == dwarf::DW_TAG_member) {
- collectMemberInfo(Info, DDTy);
- } else if (DDTy->getTag() == dwarf::DW_TAG_inheritance) {
- Info.Inheritance.push_back(DDTy);
- } else if (DDTy->getTag() == dwarf::DW_TAG_pointer_type &&
- DDTy->getName() == "__vtbl_ptr_type") {
- Info.VShapeTI = getTypeIndex(DDTy);
- } else if (DDTy->getTag() == dwarf::DW_TAG_typedef) {
- Info.NestedTypes.push_back(DDTy);
- } else if (DDTy->getTag() == dwarf::DW_TAG_friend) {
- // Ignore friend members. It appears that MSVC emitted info about
- // friends in the past, but modern versions do not.
- }
- } else if (auto *Composite = dyn_cast<DICompositeType>(Element)) {
- Info.NestedTypes.push_back(Composite);
- }
- // Skip other unrecognized kinds of elements.
- }
- return Info;
- }
- static bool shouldAlwaysEmitCompleteClassType(const DICompositeType *Ty) {
- // This routine is used by lowerTypeClass and lowerTypeUnion to determine
- // if a complete type should be emitted instead of a forward reference.
- return Ty->getName().empty() && Ty->getIdentifier().empty() &&
- !Ty->isForwardDecl();
- }
- TypeIndex CodeViewDebug::lowerTypeClass(const DICompositeType *Ty) {
- // Emit the complete type for unnamed structs. C++ classes with methods
- // which have a circular reference back to the class type are expected to
- // be named by the front-end and should not be "unnamed". C unnamed
- // structs should not have circular references.
- if (shouldAlwaysEmitCompleteClassType(Ty)) {
- // If this unnamed complete type is already in the process of being defined
- // then the description of the type is malformed and cannot be emitted
- // into CodeView correctly so report a fatal error.
- auto I = CompleteTypeIndices.find(Ty);
- if (I != CompleteTypeIndices.end() && I->second == TypeIndex())
- report_fatal_error("cannot debug circular reference to unnamed type");
- return getCompleteTypeIndex(Ty);
- }
- // First, construct the forward decl. Don't look into Ty to compute the
- // forward decl options, since it might not be available in all TUs.
- TypeRecordKind Kind = getRecordKind(Ty);
- ClassOptions CO =
- ClassOptions::ForwardReference | getCommonClassOptions(Ty);
- std::string FullName = getFullyQualifiedName(Ty);
- ClassRecord CR(Kind, 0, CO, TypeIndex(), TypeIndex(), TypeIndex(), 0,
- FullName, Ty->getIdentifier());
- TypeIndex FwdDeclTI = TypeTable.writeLeafType(CR);
- if (!Ty->isForwardDecl())
- DeferredCompleteTypes.push_back(Ty);
- return FwdDeclTI;
- }
- TypeIndex CodeViewDebug::lowerCompleteTypeClass(const DICompositeType *Ty) {
- // Construct the field list and complete type record.
- TypeRecordKind Kind = getRecordKind(Ty);
- ClassOptions CO = getCommonClassOptions(Ty);
- TypeIndex FieldTI;
- TypeIndex VShapeTI;
- unsigned FieldCount;
- bool ContainsNestedClass;
- std::tie(FieldTI, VShapeTI, FieldCount, ContainsNestedClass) =
- lowerRecordFieldList(Ty);
- if (ContainsNestedClass)
- CO |= ClassOptions::ContainsNestedClass;
- // MSVC appears to set this flag by searching any destructor or method with
- // FunctionOptions::Constructor among the emitted members. Clang AST has all
- // the members, however special member functions are not yet emitted into
- // debug information. For now checking a class's non-triviality seems enough.
- // FIXME: not true for a nested unnamed struct.
- if (isNonTrivial(Ty))
- CO |= ClassOptions::HasConstructorOrDestructor;
- std::string FullName = getFullyQualifiedName(Ty);
- uint64_t SizeInBytes = Ty->getSizeInBits() / 8;
- ClassRecord CR(Kind, FieldCount, CO, FieldTI, TypeIndex(), VShapeTI,
- SizeInBytes, FullName, Ty->getIdentifier());
- TypeIndex ClassTI = TypeTable.writeLeafType(CR);
- addUDTSrcLine(Ty, ClassTI);
- addToUDTs(Ty);
- return ClassTI;
- }
- TypeIndex CodeViewDebug::lowerTypeUnion(const DICompositeType *Ty) {
- // Emit the complete type for unnamed unions.
- if (shouldAlwaysEmitCompleteClassType(Ty))
- return getCompleteTypeIndex(Ty);
- ClassOptions CO =
- ClassOptions::ForwardReference | getCommonClassOptions(Ty);
- std::string FullName = getFullyQualifiedName(Ty);
- UnionRecord UR(0, CO, TypeIndex(), 0, FullName, Ty->getIdentifier());
- TypeIndex FwdDeclTI = TypeTable.writeLeafType(UR);
- if (!Ty->isForwardDecl())
- DeferredCompleteTypes.push_back(Ty);
- return FwdDeclTI;
- }
- TypeIndex CodeViewDebug::lowerCompleteTypeUnion(const DICompositeType *Ty) {
- ClassOptions CO = ClassOptions::Sealed | getCommonClassOptions(Ty);
- TypeIndex FieldTI;
- unsigned FieldCount;
- bool ContainsNestedClass;
- std::tie(FieldTI, std::ignore, FieldCount, ContainsNestedClass) =
- lowerRecordFieldList(Ty);
- if (ContainsNestedClass)
- CO |= ClassOptions::ContainsNestedClass;
- uint64_t SizeInBytes = Ty->getSizeInBits() / 8;
- std::string FullName = getFullyQualifiedName(Ty);
- UnionRecord UR(FieldCount, CO, FieldTI, SizeInBytes, FullName,
- Ty->getIdentifier());
- TypeIndex UnionTI = TypeTable.writeLeafType(UR);
- addUDTSrcLine(Ty, UnionTI);
- addToUDTs(Ty);
- return UnionTI;
- }
- std::tuple<TypeIndex, TypeIndex, unsigned, bool>
- CodeViewDebug::lowerRecordFieldList(const DICompositeType *Ty) {
- // Manually count members. MSVC appears to count everything that generates a
- // field list record. Each individual overload in a method overload group
- // contributes to this count, even though the overload group is a single field
- // list record.
- unsigned MemberCount = 0;
- ClassInfo Info = collectClassInfo(Ty);
- ContinuationRecordBuilder ContinuationBuilder;
- ContinuationBuilder.begin(ContinuationRecordKind::FieldList);
- // Create base classes.
- for (const DIDerivedType *I : Info.Inheritance) {
- if (I->getFlags() & DINode::FlagVirtual) {
- // Virtual base.
- unsigned VBPtrOffset = I->getVBPtrOffset();
- // FIXME: Despite the accessor name, the offset is really in bytes.
- unsigned VBTableIndex = I->getOffsetInBits() / 4;
- auto RecordKind = (I->getFlags() & DINode::FlagIndirectVirtualBase) == DINode::FlagIndirectVirtualBase
- ? TypeRecordKind::IndirectVirtualBaseClass
- : TypeRecordKind::VirtualBaseClass;
- VirtualBaseClassRecord VBCR(
- RecordKind, translateAccessFlags(Ty->getTag(), I->getFlags()),
- getTypeIndex(I->getBaseType()), getVBPTypeIndex(), VBPtrOffset,
- VBTableIndex);
- ContinuationBuilder.writeMemberType(VBCR);
- MemberCount++;
- } else {
- assert(I->getOffsetInBits() % 8 == 0 &&
- "bases must be on byte boundaries");
- BaseClassRecord BCR(translateAccessFlags(Ty->getTag(), I->getFlags()),
- getTypeIndex(I->getBaseType()),
- I->getOffsetInBits() / 8);
- ContinuationBuilder.writeMemberType(BCR);
- MemberCount++;
- }
- }
- // Create members.
- for (ClassInfo::MemberInfo &MemberInfo : Info.Members) {
- const DIDerivedType *Member = MemberInfo.MemberTypeNode;
- TypeIndex MemberBaseType = getTypeIndex(Member->getBaseType());
- StringRef MemberName = Member->getName();
- MemberAccess Access =
- translateAccessFlags(Ty->getTag(), Member->getFlags());
- if (Member->isStaticMember()) {
- StaticDataMemberRecord SDMR(Access, MemberBaseType, MemberName);
- ContinuationBuilder.writeMemberType(SDMR);
- MemberCount++;
- continue;
- }
- // Virtual function pointer member.
- if ((Member->getFlags() & DINode::FlagArtificial) &&
- Member->getName().startswith("_vptr$")) {
- VFPtrRecord VFPR(getTypeIndex(Member->getBaseType()));
- ContinuationBuilder.writeMemberType(VFPR);
- MemberCount++;
- continue;
- }
- // Data member.
- uint64_t MemberOffsetInBits =
- Member->getOffsetInBits() + MemberInfo.BaseOffset;
- if (Member->isBitField()) {
- uint64_t StartBitOffset = MemberOffsetInBits;
- if (const auto *CI =
- dyn_cast_or_null<ConstantInt>(Member->getStorageOffsetInBits())) {
- MemberOffsetInBits = CI->getZExtValue() + MemberInfo.BaseOffset;
- }
- StartBitOffset -= MemberOffsetInBits;
- BitFieldRecord BFR(MemberBaseType, Member->getSizeInBits(),
- StartBitOffset);
- MemberBaseType = TypeTable.writeLeafType(BFR);
- }
- uint64_t MemberOffsetInBytes = MemberOffsetInBits / 8;
- DataMemberRecord DMR(Access, MemberBaseType, MemberOffsetInBytes,
- MemberName);
- ContinuationBuilder.writeMemberType(DMR);
- MemberCount++;
- }
- // Create methods
- for (auto &MethodItr : Info.Methods) {
- StringRef Name = MethodItr.first->getString();
- std::vector<OneMethodRecord> Methods;
- for (const DISubprogram *SP : MethodItr.second) {
- TypeIndex MethodType = getMemberFunctionType(SP, Ty);
- bool Introduced = SP->getFlags() & DINode::FlagIntroducedVirtual;
- unsigned VFTableOffset = -1;
- if (Introduced)
- VFTableOffset = SP->getVirtualIndex() * getPointerSizeInBytes();
- Methods.push_back(OneMethodRecord(
- MethodType, translateAccessFlags(Ty->getTag(), SP->getFlags()),
- translateMethodKindFlags(SP, Introduced),
- translateMethodOptionFlags(SP), VFTableOffset, Name));
- MemberCount++;
- }
- assert(!Methods.empty() && "Empty methods map entry");
- if (Methods.size() == 1)
- ContinuationBuilder.writeMemberType(Methods[0]);
- else {
- // FIXME: Make this use its own ContinuationBuilder so that
- // MethodOverloadList can be split correctly.
- MethodOverloadListRecord MOLR(Methods);
- TypeIndex MethodList = TypeTable.writeLeafType(MOLR);
- OverloadedMethodRecord OMR(Methods.size(), MethodList, Name);
- ContinuationBuilder.writeMemberType(OMR);
- }
- }
- // Create nested classes.
- for (const DIType *Nested : Info.NestedTypes) {
- NestedTypeRecord R(getTypeIndex(DITypeRef(Nested)), Nested->getName());
- ContinuationBuilder.writeMemberType(R);
- MemberCount++;
- }
- TypeIndex FieldTI = TypeTable.insertRecord(ContinuationBuilder);
- return std::make_tuple(FieldTI, Info.VShapeTI, MemberCount,
- !Info.NestedTypes.empty());
- }
- TypeIndex CodeViewDebug::getVBPTypeIndex() {
- if (!VBPType.getIndex()) {
- // Make a 'const int *' type.
- ModifierRecord MR(TypeIndex::Int32(), ModifierOptions::Const);
- TypeIndex ModifiedTI = TypeTable.writeLeafType(MR);
- PointerKind PK = getPointerSizeInBytes() == 8 ? PointerKind::Near64
- : PointerKind::Near32;
- PointerMode PM = PointerMode::Pointer;
- PointerOptions PO = PointerOptions::None;
- PointerRecord PR(ModifiedTI, PK, PM, PO, getPointerSizeInBytes());
- VBPType = TypeTable.writeLeafType(PR);
- }
- return VBPType;
- }
- TypeIndex CodeViewDebug::getTypeIndex(DITypeRef TypeRef, DITypeRef ClassTyRef) {
- const DIType *Ty = TypeRef.resolve();
- const DIType *ClassTy = ClassTyRef.resolve();
- // The null DIType is the void type. Don't try to hash it.
- if (!Ty)
- return TypeIndex::Void();
- // Check if we've already translated this type. Don't try to do a
- // get-or-create style insertion that caches the hash lookup across the
- // lowerType call. It will update the TypeIndices map.
- auto I = TypeIndices.find({Ty, ClassTy});
- if (I != TypeIndices.end())
- return I->second;
- TypeLoweringScope S(*this);
- TypeIndex TI = lowerType(Ty, ClassTy);
- return recordTypeIndexForDINode(Ty, TI, ClassTy);
- }
- codeview::TypeIndex
- CodeViewDebug::getTypeIndexForThisPtr(const DIDerivedType *PtrTy,
- const DISubroutineType *SubroutineTy) {
- assert(PtrTy->getTag() == dwarf::DW_TAG_pointer_type &&
- "this type must be a pointer type");
- PointerOptions Options = PointerOptions::None;
- if (SubroutineTy->getFlags() & DINode::DIFlags::FlagLValueReference)
- Options = PointerOptions::LValueRefThisPointer;
- else if (SubroutineTy->getFlags() & DINode::DIFlags::FlagRValueReference)
- Options = PointerOptions::RValueRefThisPointer;
- // Check if we've already translated this type. If there is no ref qualifier
- // on the function then we look up this pointer type with no associated class
- // so that the TypeIndex for the this pointer can be shared with the type
- // index for other pointers to this class type. If there is a ref qualifier
- // then we lookup the pointer using the subroutine as the parent type.
- auto I = TypeIndices.find({PtrTy, SubroutineTy});
- if (I != TypeIndices.end())
- return I->second;
- TypeLoweringScope S(*this);
- TypeIndex TI = lowerTypePointer(PtrTy, Options);
- return recordTypeIndexForDINode(PtrTy, TI, SubroutineTy);
- }
- TypeIndex CodeViewDebug::getTypeIndexForReferenceTo(DITypeRef TypeRef) {
- DIType *Ty = TypeRef.resolve();
- PointerRecord PR(getTypeIndex(Ty),
- getPointerSizeInBytes() == 8 ? PointerKind::Near64
- : PointerKind::Near32,
- PointerMode::LValueReference, PointerOptions::None,
- Ty->getSizeInBits() / 8);
- return TypeTable.writeLeafType(PR);
- }
- TypeIndex CodeViewDebug::getCompleteTypeIndex(DITypeRef TypeRef) {
- const DIType *Ty = TypeRef.resolve();
- // The null DIType is the void type. Don't try to hash it.
- if (!Ty)
- return TypeIndex::Void();
- // Look through typedefs when getting the complete type index. Call
- // getTypeIndex on the typdef to ensure that any UDTs are accumulated and are
- // emitted only once.
- if (Ty->getTag() == dwarf::DW_TAG_typedef)
- (void)getTypeIndex(Ty);
- while (Ty->getTag() == dwarf::DW_TAG_typedef)
- Ty = cast<DIDerivedType>(Ty)->getBaseType().resolve();
- // If this is a non-record type, the complete type index is the same as the
- // normal type index. Just call getTypeIndex.
- switch (Ty->getTag()) {
- case dwarf::DW_TAG_class_type:
- case dwarf::DW_TAG_structure_type:
- case dwarf::DW_TAG_union_type:
- break;
- default:
- return getTypeIndex(Ty);
- }
- // Check if we've already translated the complete record type.
- const auto *CTy = cast<DICompositeType>(Ty);
- auto InsertResult = CompleteTypeIndices.insert({CTy, TypeIndex()});
- if (!InsertResult.second)
- return InsertResult.first->second;
- TypeLoweringScope S(*this);
- // Make sure the forward declaration is emitted first. It's unclear if this
- // is necessary, but MSVC does it, and we should follow suit until we can show
- // otherwise.
- // We only emit a forward declaration for named types.
- if (!CTy->getName().empty() || !CTy->getIdentifier().empty()) {
- TypeIndex FwdDeclTI = getTypeIndex(CTy);
- // Just use the forward decl if we don't have complete type info. This
- // might happen if the frontend is using modules and expects the complete
- // definition to be emitted elsewhere.
- if (CTy->isForwardDecl())
- return FwdDeclTI;
- }
- TypeIndex TI;
- switch (CTy->getTag()) {
- case dwarf::DW_TAG_class_type:
- case dwarf::DW_TAG_structure_type:
- TI = lowerCompleteTypeClass(CTy);
- break;
- case dwarf::DW_TAG_union_type:
- TI = lowerCompleteTypeUnion(CTy);
- break;
- default:
- llvm_unreachable("not a record");
- }
- // Update the type index associated with this CompositeType. This cannot
- // use the 'InsertResult' iterator above because it is potentially
- // invalidated by map insertions which can occur while lowering the class
- // type above.
- CompleteTypeIndices[CTy] = TI;
- return TI;
- }
- /// Emit all the deferred complete record types. Try to do this in FIFO order,
- /// and do this until fixpoint, as each complete record type typically
- /// references
- /// many other record types.
- void CodeViewDebug::emitDeferredCompleteTypes() {
- SmallVector<const DICompositeType *, 4> TypesToEmit;
- while (!DeferredCompleteTypes.empty()) {
- std::swap(DeferredCompleteTypes, TypesToEmit);
- for (const DICompositeType *RecordTy : TypesToEmit)
- getCompleteTypeIndex(RecordTy);
- TypesToEmit.clear();
- }
- }
- void CodeViewDebug::emitLocalVariableList(const FunctionInfo &FI,
- ArrayRef<LocalVariable> Locals) {
- // Get the sorted list of parameters and emit them first.
- SmallVector<const LocalVariable *, 6> Params;
- for (const LocalVariable &L : Locals)
- if (L.DIVar->isParameter())
- Params.push_back(&L);
- llvm::sort(Params, [](const LocalVariable *L, const LocalVariable *R) {
- return L->DIVar->getArg() < R->DIVar->getArg();
- });
- for (const LocalVariable *L : Params)
- emitLocalVariable(FI, *L);
- // Next emit all non-parameters in the order that we found them.
- for (const LocalVariable &L : Locals)
- if (!L.DIVar->isParameter())
- emitLocalVariable(FI, L);
- }
- /// Only call this on endian-specific types like ulittle16_t and little32_t, or
- /// structs composed of them.
- template <typename T>
- static void copyBytesForDefRange(SmallString<20> &BytePrefix,
- SymbolKind SymKind, const T &DefRangeHeader) {
- BytePrefix.resize(2 + sizeof(T));
- ulittle16_t SymKindLE = ulittle16_t(SymKind);
- memcpy(&BytePrefix[0], &SymKindLE, 2);
- memcpy(&BytePrefix[2], &DefRangeHeader, sizeof(T));
- }
- void CodeViewDebug::emitLocalVariable(const FunctionInfo &FI,
- const LocalVariable &Var) {
- // LocalSym record, see SymbolRecord.h for more info.
- MCSymbol *LocalEnd = beginSymbolRecord(SymbolKind::S_LOCAL);
- LocalSymFlags Flags = LocalSymFlags::None;
- if (Var.DIVar->isParameter())
- Flags |= LocalSymFlags::IsParameter;
- if (Var.DefRanges.empty())
- Flags |= LocalSymFlags::IsOptimizedOut;
- OS.AddComment("TypeIndex");
- TypeIndex TI = Var.UseReferenceType
- ? getTypeIndexForReferenceTo(Var.DIVar->getType())
- : getCompleteTypeIndex(Var.DIVar->getType());
- OS.EmitIntValue(TI.getIndex(), 4);
- OS.AddComment("Flags");
- OS.EmitIntValue(static_cast<uint16_t>(Flags), 2);
- // Truncate the name so we won't overflow the record length field.
- emitNullTerminatedSymbolName(OS, Var.DIVar->getName());
- endSymbolRecord(LocalEnd);
- // Calculate the on disk prefix of the appropriate def range record. The
- // records and on disk formats are described in SymbolRecords.h. BytePrefix
- // should be big enough to hold all forms without memory allocation.
- SmallString<20> BytePrefix;
- for (const LocalVarDefRange &DefRange : Var.DefRanges) {
- BytePrefix.clear();
- if (DefRange.InMemory) {
- int Offset = DefRange.DataOffset;
- unsigned Reg = DefRange.CVRegister;
- // 32-bit x86 call sequences often use PUSH instructions, which disrupt
- // ESP-relative offsets. Use the virtual frame pointer, VFRAME or $T0,
- // instead. In frames without stack realignment, $T0 will be the CFA.
- if (RegisterId(Reg) == RegisterId::ESP) {
- Reg = unsigned(RegisterId::VFRAME);
- Offset += FI.OffsetAdjustment;
- }
- // If we can use the chosen frame pointer for the frame and this isn't a
- // sliced aggregate, use the smaller S_DEFRANGE_FRAMEPOINTER_REL record.
- // Otherwise, use S_DEFRANGE_REGISTER_REL.
- EncodedFramePtrReg EncFP = encodeFramePtrReg(RegisterId(Reg), TheCPU);
- if (!DefRange.IsSubfield && EncFP != EncodedFramePtrReg::None &&
- (bool(Flags & LocalSymFlags::IsParameter)
- ? (EncFP == FI.EncodedParamFramePtrReg)
- : (EncFP == FI.EncodedLocalFramePtrReg))) {
- little32_t FPOffset = little32_t(Offset);
- copyBytesForDefRange(BytePrefix, S_DEFRANGE_FRAMEPOINTER_REL, FPOffset);
- } else {
- uint16_t RegRelFlags = 0;
- if (DefRange.IsSubfield) {
- RegRelFlags = DefRangeRegisterRelSym::IsSubfieldFlag |
- (DefRange.StructOffset
- << DefRangeRegisterRelSym::OffsetInParentShift);
- }
- DefRangeRegisterRelSym::Header DRHdr;
- DRHdr.Register = Reg;
- DRHdr.Flags = RegRelFlags;
- DRHdr.BasePointerOffset = Offset;
- copyBytesForDefRange(BytePrefix, S_DEFRANGE_REGISTER_REL, DRHdr);
- }
- } else {
- assert(DefRange.DataOffset == 0 && "unexpected offset into register");
- if (DefRange.IsSubfield) {
- DefRangeSubfieldRegisterSym::Header DRHdr;
- DRHdr.Register = DefRange.CVRegister;
- DRHdr.MayHaveNoName = 0;
- DRHdr.OffsetInParent = DefRange.StructOffset;
- copyBytesForDefRange(BytePrefix, S_DEFRANGE_SUBFIELD_REGISTER, DRHdr);
- } else {
- DefRangeRegisterSym::Header DRHdr;
- DRHdr.Register = DefRange.CVRegister;
- DRHdr.MayHaveNoName = 0;
- copyBytesForDefRange(BytePrefix, S_DEFRANGE_REGISTER, DRHdr);
- }
- }
- OS.EmitCVDefRangeDirective(DefRange.Ranges, BytePrefix);
- }
- }
- void CodeViewDebug::emitLexicalBlockList(ArrayRef<LexicalBlock *> Blocks,
- const FunctionInfo& FI) {
- for (LexicalBlock *Block : Blocks)
- emitLexicalBlock(*Block, FI);
- }
- /// Emit an S_BLOCK32 and S_END record pair delimiting the contents of a
- /// lexical block scope.
- void CodeViewDebug::emitLexicalBlock(const LexicalBlock &Block,
- const FunctionInfo& FI) {
- MCSymbol *RecordEnd = beginSymbolRecord(SymbolKind::S_BLOCK32);
- OS.AddComment("PtrParent");
- OS.EmitIntValue(0, 4); // PtrParent
- OS.AddComment("PtrEnd");
- OS.EmitIntValue(0, 4); // PtrEnd
- OS.AddComment("Code size");
- OS.emitAbsoluteSymbolDiff(Block.End, Block.Begin, 4); // Code Size
- OS.AddComment("Function section relative address");
- OS.EmitCOFFSecRel32(Block.Begin, /*Offset=*/0); // Func Offset
- OS.AddComment("Function section index");
- OS.EmitCOFFSectionIndex(FI.Begin); // Func Symbol
- OS.AddComment("Lexical block name");
- emitNullTerminatedSymbolName(OS, Block.Name); // Name
- endSymbolRecord(RecordEnd);
- // Emit variables local to this lexical block.
- emitLocalVariableList(FI, Block.Locals);
- emitGlobalVariableList(Block.Globals);
- // Emit lexical blocks contained within this block.
- emitLexicalBlockList(Block.Children, FI);
- // Close the lexical block scope.
- emitEndSymbolRecord(SymbolKind::S_END);
- }
- /// Convenience routine for collecting lexical block information for a list
- /// of lexical scopes.
- void CodeViewDebug::collectLexicalBlockInfo(
- SmallVectorImpl<LexicalScope *> &Scopes,
- SmallVectorImpl<LexicalBlock *> &Blocks,
- SmallVectorImpl<LocalVariable> &Locals,
- SmallVectorImpl<CVGlobalVariable> &Globals) {
- for (LexicalScope *Scope : Scopes)
- collectLexicalBlockInfo(*Scope, Blocks, Locals, Globals);
- }
- /// Populate the lexical blocks and local variable lists of the parent with
- /// information about the specified lexical scope.
- void CodeViewDebug::collectLexicalBlockInfo(
- LexicalScope &Scope,
- SmallVectorImpl<LexicalBlock *> &ParentBlocks,
- SmallVectorImpl<LocalVariable> &ParentLocals,
- SmallVectorImpl<CVGlobalVariable> &ParentGlobals) {
- if (Scope.isAbstractScope())
- return;
- // Gather information about the lexical scope including local variables,
- // global variables, and address ranges.
- bool IgnoreScope = false;
- auto LI = ScopeVariables.find(&Scope);
- SmallVectorImpl<LocalVariable> *Locals =
- LI != ScopeVariables.end() ? &LI->second : nullptr;
- auto GI = ScopeGlobals.find(Scope.getScopeNode());
- SmallVectorImpl<CVGlobalVariable> *Globals =
- GI != ScopeGlobals.end() ? GI->second.get() : nullptr;
- const DILexicalBlock *DILB = dyn_cast<DILexicalBlock>(Scope.getScopeNode());
- const SmallVectorImpl<InsnRange> &Ranges = Scope.getRanges();
- // Ignore lexical scopes which do not contain variables.
- if (!Locals && !Globals)
- IgnoreScope = true;
- // Ignore lexical scopes which are not lexical blocks.
- if (!DILB)
- IgnoreScope = true;
- // Ignore scopes which have too many address ranges to represent in the
- // current CodeView format or do not have a valid address range.
- //
- // For lexical scopes with multiple address ranges you may be tempted to
- // construct a single range covering every instruction where the block is
- // live and everything in between. Unfortunately, Visual Studio only
- // displays variables from the first matching lexical block scope. If the
- // first lexical block contains exception handling code or cold code which
- // is moved to the bottom of the routine creating a single range covering
- // nearly the entire routine, then it will hide all other lexical blocks
- // and the variables they contain.
- if (Ranges.size() != 1 || !getLabelAfterInsn(Ranges.front().second))
- IgnoreScope = true;
- if (IgnoreScope) {
- // This scope can be safely ignored and eliminating it will reduce the
- // size of the debug information. Be sure to collect any variable and scope
- // information from the this scope or any of its children and collapse them
- // into the parent scope.
- if (Locals)
- ParentLocals.append(Locals->begin(), Locals->end());
- if (Globals)
- ParentGlobals.append(Globals->begin(), Globals->end());
- collectLexicalBlockInfo(Scope.getChildren(),
- ParentBlocks,
- ParentLocals,
- ParentGlobals);
- return;
- }
- // Create a new CodeView lexical block for this lexical scope. If we've
- // seen this DILexicalBlock before then the scope tree is malformed and
- // we can handle this gracefully by not processing it a second time.
- auto BlockInsertion = CurFn->LexicalBlocks.insert({DILB, LexicalBlock()});
- if (!BlockInsertion.second)
- return;
- // Create a lexical block containing the variables and collect the the
- // lexical block information for the children.
- const InsnRange &Range = Ranges.front();
- assert(Range.first && Range.second);
- LexicalBlock &Block = BlockInsertion.first->second;
- Block.Begin = getLabelBeforeInsn(Range.first);
- Block.End = getLabelAfterInsn(Range.second);
- assert(Block.Begin && "missing label for scope begin");
- assert(Block.End && "missing label for scope end");
- Block.Name = DILB->getName();
- if (Locals)
- Block.Locals = std::move(*Locals);
- if (Globals)
- Block.Globals = std::move(*Globals);
- ParentBlocks.push_back(&Block);
- collectLexicalBlockInfo(Scope.getChildren(),
- Block.Children,
- Block.Locals,
- Block.Globals);
- }
- void CodeViewDebug::endFunctionImpl(const MachineFunction *MF) {
- const Function &GV = MF->getFunction();
- assert(FnDebugInfo.count(&GV));
- assert(CurFn == FnDebugInfo[&GV].get());
- collectVariableInfo(GV.getSubprogram());
- // Build the lexical block structure to emit for this routine.
- if (LexicalScope *CFS = LScopes.getCurrentFunctionScope())
- collectLexicalBlockInfo(*CFS,
- CurFn->ChildBlocks,
- CurFn->Locals,
- CurFn->Globals);
- // Clear the scope and variable information from the map which will not be
- // valid after we have finished processing this routine. This also prepares
- // the map for the subsequent routine.
- ScopeVariables.clear();
- // Don't emit anything if we don't have any line tables.
- // Thunks are compiler-generated and probably won't have source correlation.
- if (!CurFn->HaveLineInfo && !GV.getSubprogram()->isThunk()) {
- FnDebugInfo.erase(&GV);
- CurFn = nullptr;
- return;
- }
- CurFn->Annotations = MF->getCodeViewAnnotations();
- CurFn->End = Asm->getFunctionEnd();
- CurFn = nullptr;
- }
- void CodeViewDebug::beginInstruction(const MachineInstr *MI) {
- DebugHandlerBase::beginInstruction(MI);
- // Ignore DBG_VALUE and DBG_LABEL locations and function prologue.
- if (!Asm || !CurFn || MI->isDebugInstr() ||
- MI->getFlag(MachineInstr::FrameSetup))
- return;
- // If the first instruction of a new MBB has no location, find the first
- // instruction with a location and use that.
- DebugLoc DL = MI->getDebugLoc();
- if (!DL && MI->getParent() != PrevInstBB) {
- for (const auto &NextMI : *MI->getParent()) {
- if (NextMI.isDebugInstr())
- continue;
- DL = NextMI.getDebugLoc();
- if (DL)
- break;
- }
- }
- PrevInstBB = MI->getParent();
- // If we still don't have a debug location, don't record a location.
- if (!DL)
- return;
- maybeRecordLocation(DL, Asm->MF);
- }
- MCSymbol *CodeViewDebug::beginCVSubsection(DebugSubsectionKind Kind) {
- MCSymbol *BeginLabel = MMI->getContext().createTempSymbol(),
- *EndLabel = MMI->getContext().createTempSymbol();
- OS.EmitIntValue(unsigned(Kind), 4);
- OS.AddComment("Subsection size");
- OS.emitAbsoluteSymbolDiff(EndLabel, BeginLabel, 4);
- OS.EmitLabel(BeginLabel);
- return EndLabel;
- }
- void CodeViewDebug::endCVSubsection(MCSymbol *EndLabel) {
- OS.EmitLabel(EndLabel);
- // Every subsection must be aligned to a 4-byte boundary.
- OS.EmitValueToAlignment(4);
- }
- static StringRef getSymbolName(SymbolKind SymKind) {
- for (const EnumEntry<SymbolKind> &EE : getSymbolTypeNames())
- if (EE.Value == SymKind)
- return EE.Name;
- return "";
- }
- MCSymbol *CodeViewDebug::beginSymbolRecord(SymbolKind SymKind) {
- MCSymbol *BeginLabel = MMI->getContext().createTempSymbol(),
- *EndLabel = MMI->getContext().createTempSymbol();
- OS.AddComment("Record length");
- OS.emitAbsoluteSymbolDiff(EndLabel, BeginLabel, 2);
- OS.EmitLabel(BeginLabel);
- if (OS.isVerboseAsm())
- OS.AddComment("Record kind: " + getSymbolName(SymKind));
- OS.EmitIntValue(unsigned(SymKind), 2);
- return EndLabel;
- }
- void CodeViewDebug::endSymbolRecord(MCSymbol *SymEnd) {
- // MSVC does not pad out symbol records to four bytes, but LLVM does to avoid
- // an extra copy of every symbol record in LLD. This increases object file
- // size by less than 1% in the clang build, and is compatible with the Visual
- // C++ linker.
- OS.EmitValueToAlignment(4);
- OS.EmitLabel(SymEnd);
- }
- void CodeViewDebug::emitEndSymbolRecord(SymbolKind EndKind) {
- OS.AddComment("Record length");
- OS.EmitIntValue(2, 2);
- if (OS.isVerboseAsm())
- OS.AddComment("Record kind: " + getSymbolName(EndKind));
- OS.EmitIntValue(unsigned(EndKind), 2); // Record Kind
- }
- void CodeViewDebug::emitDebugInfoForUDTs(
- ArrayRef<std::pair<std::string, const DIType *>> UDTs) {
- for (const auto &UDT : UDTs) {
- const DIType *T = UDT.second;
- assert(shouldEmitUdt(T));
- MCSymbol *UDTRecordEnd = beginSymbolRecord(SymbolKind::S_UDT);
- OS.AddComment("Type");
- OS.EmitIntValue(getCompleteTypeIndex(T).getIndex(), 4);
- emitNullTerminatedSymbolName(OS, UDT.first);
- endSymbolRecord(UDTRecordEnd);
- }
- }
- void CodeViewDebug::collectGlobalVariableInfo() {
- DenseMap<const DIGlobalVariableExpression *, const GlobalVariable *>
- GlobalMap;
- for (const GlobalVariable &GV : MMI->getModule()->globals()) {
- SmallVector<DIGlobalVariableExpression *, 1> GVEs;
- GV.getDebugInfo(GVEs);
- for (const auto *GVE : GVEs)
- GlobalMap[GVE] = &GV;
- }
- NamedMDNode *CUs = MMI->getModule()->getNamedMetadata("llvm.dbg.cu");
- for (const MDNode *Node : CUs->operands()) {
- const auto *CU = cast<DICompileUnit>(Node);
- for (const auto *GVE : CU->getGlobalVariables()) {
- const auto *GV = GlobalMap.lookup(GVE);
- if (!GV || GV->isDeclarationForLinker())
- continue;
- const DIGlobalVariable *DIGV = GVE->getVariable();
- DIScope *Scope = DIGV->getScope();
- SmallVector<CVGlobalVariable, 1> *VariableList;
- if (Scope && isa<DILocalScope>(Scope)) {
- // Locate a global variable list for this scope, creating one if
- // necessary.
- auto Insertion = ScopeGlobals.insert(
- {Scope, std::unique_ptr<GlobalVariableList>()});
- if (Insertion.second)
- Insertion.first->second = llvm::make_unique<GlobalVariableList>();
- VariableList = Insertion.first->second.get();
- } else if (GV->hasComdat())
- // Emit this global variable into a COMDAT section.
- VariableList = &ComdatVariables;
- else
- // Emit this globla variable in a single global symbol section.
- VariableList = &GlobalVariables;
- CVGlobalVariable CVGV = {DIGV, GV};
- VariableList->emplace_back(std::move(CVGV));
- }
- }
- }
- void CodeViewDebug::emitDebugInfoForGlobals() {
- // First, emit all globals that are not in a comdat in a single symbol
- // substream. MSVC doesn't like it if the substream is empty, so only open
- // it if we have at least one global to emit.
- switchToDebugSectionForSymbol(nullptr);
- if (!GlobalVariables.empty()) {
- OS.AddComment("Symbol subsection for globals");
- MCSymbol *EndLabel = beginCVSubsection(DebugSubsectionKind::Symbols);
- emitGlobalVariableList(GlobalVariables);
- endCVSubsection(EndLabel);
- }
- // Second, emit each global that is in a comdat into its own .debug$S
- // section along with its own symbol substream.
- for (const CVGlobalVariable &CVGV : ComdatVariables) {
- MCSymbol *GVSym = Asm->getSymbol(CVGV.GV);
- OS.AddComment("Symbol subsection for " +
- Twine(GlobalValue::dropLLVMManglingEscape(CVGV.GV->getName())));
- switchToDebugSectionForSymbol(GVSym);
- MCSymbol *EndLabel = beginCVSubsection(DebugSubsectionKind::Symbols);
- // FIXME: emitDebugInfoForGlobal() doesn't handle DIExpressions.
- emitDebugInfoForGlobal(CVGV.DIGV, CVGV.GV, GVSym);
- endCVSubsection(EndLabel);
- }
- }
- void CodeViewDebug::emitDebugInfoForRetainedTypes() {
- NamedMDNode *CUs = MMI->getModule()->getNamedMetadata("llvm.dbg.cu");
- for (const MDNode *Node : CUs->operands()) {
- for (auto *Ty : cast<DICompileUnit>(Node)->getRetainedTypes()) {
- if (DIType *RT = dyn_cast<DIType>(Ty)) {
- getTypeIndex(RT);
- // FIXME: Add to global/local DTU list.
- }
- }
- }
- }
- // Emit each global variable in the specified array.
- void CodeViewDebug::emitGlobalVariableList(ArrayRef<CVGlobalVariable> Globals) {
- for (const CVGlobalVariable &CVGV : Globals) {
- MCSymbol *GVSym = Asm->getSymbol(CVGV.GV);
- // FIXME: emitDebugInfoForGlobal() doesn't handle DIExpressions.
- emitDebugInfoForGlobal(CVGV.DIGV, CVGV.GV, GVSym);
- }
- }
- void CodeViewDebug::emitDebugInfoForGlobal(const DIGlobalVariable *DIGV,
- const GlobalVariable *GV,
- MCSymbol *GVSym) {
- // DataSym record, see SymbolRecord.h for more info. Thread local data
- // happens to have the same format as global data.
- SymbolKind DataSym = GV->isThreadLocal()
- ? (DIGV->isLocalToUnit() ? SymbolKind::S_LTHREAD32
- : SymbolKind::S_GTHREAD32)
- : (DIGV->isLocalToUnit() ? SymbolKind::S_LDATA32
- : SymbolKind::S_GDATA32);
- MCSymbol *DataEnd = beginSymbolRecord(DataSym);
- OS.AddComment("Type");
- OS.EmitIntValue(getCompleteTypeIndex(DIGV->getType()).getIndex(), 4);
- OS.AddComment("DataOffset");
- OS.EmitCOFFSecRel32(GVSym, /*Offset=*/0);
- OS.AddComment("Segment");
- OS.EmitCOFFSectionIndex(GVSym);
- OS.AddComment("Name");
- const unsigned LengthOfDataRecord = 12;
- emitNullTerminatedSymbolName(OS, DIGV->getName(), LengthOfDataRecord);
- endSymbolRecord(DataEnd);
- }
|