diff options
Diffstat (limited to 'contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp')
-rw-r--r-- | contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp | 589 |
1 files changed, 365 insertions, 224 deletions
diff --git a/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp index c7eb0257d71b..85754bf29d0c 100644 --- a/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ b/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -14,6 +14,7 @@ #include "CodeViewDebug.h" #include "DwarfDebug.h" #include "DwarfException.h" +#include "PseudoProbePrinter.h" #include "WasmException.h" #include "WinCFGuard.h" #include "WinException.h" @@ -30,6 +31,7 @@ #include "llvm/ADT/Twine.h" #include "llvm/Analysis/ConstantFolding.h" #include "llvm/Analysis/EHPersonalities.h" +#include "llvm/Analysis/MemoryLocation.h" #include "llvm/Analysis/OptimizationRemarkEmitter.h" #include "llvm/BinaryFormat/COFF.h" #include "llvm/BinaryFormat/Dwarf.h" @@ -77,6 +79,7 @@ #include "llvm/IR/Metadata.h" #include "llvm/IR/Module.h" #include "llvm/IR/Operator.h" +#include "llvm/IR/PseudoProbe.h" #include "llvm/IR/Type.h" #include "llvm/IR/Value.h" #include "llvm/MC/MCAsmInfo.h" @@ -131,17 +134,25 @@ using namespace llvm; #define DEBUG_TYPE "asm-printer" -static const char *const DWARFGroupName = "dwarf"; -static const char *const DWARFGroupDescription = "DWARF Emission"; -static const char *const DbgTimerName = "emit"; -static const char *const DbgTimerDescription = "Debug Info Emission"; -static const char *const EHTimerName = "write_exception"; -static const char *const EHTimerDescription = "DWARF Exception Writer"; -static const char *const CFGuardName = "Control Flow Guard"; -static const char *const CFGuardDescription = "Control Flow Guard"; -static const char *const CodeViewLineTablesGroupName = "linetables"; -static const char *const CodeViewLineTablesGroupDescription = - "CodeView Line Tables"; +// FIXME: this option currently only applies to DWARF, and not CodeView, tables +static cl::opt<bool> + DisableDebugInfoPrinting("disable-debug-info-print", cl::Hidden, + cl::desc("Disable debug info printing")); + +const char DWARFGroupName[] = "dwarf"; +const char DWARFGroupDescription[] = "DWARF Emission"; +const char DbgTimerName[] = "emit"; +const char DbgTimerDescription[] = "Debug Info Emission"; +const char EHTimerName[] = "write_exception"; +const char EHTimerDescription[] = "DWARF Exception Writer"; +const char CFGuardName[] = "Control Flow Guard"; +const char CFGuardDescription[] = "Control Flow Guard"; +const char CodeViewLineTablesGroupName[] = "linetables"; +const char CodeViewLineTablesGroupDescription[] = "CodeView Line Tables"; +const char PPTimerName[] = "emit"; +const char PPTimerDescription[] = "Pseudo Probe Emission"; +const char PPGroupName[] = "pseudo probe"; +const char PPGroupDescription[] = "Pseudo Probe Emission"; STATISTIC(EmittedInsts, "Number of machine instrs printed"); @@ -188,7 +199,8 @@ AsmPrinter::AsmPrinter(TargetMachine &tm, std::unique_ptr<MCStreamer> Streamer) } AsmPrinter::~AsmPrinter() { - assert(!DD && Handlers.empty() && "Debug/EH info didn't get finalized"); + assert(!DD && Handlers.size() == NumUserHandlers && + "Debug/EH info didn't get finalized"); if (GCMetadataPrinters) { gcp_map_type &GCMap = getGCMap(GCMetadataPrinters); @@ -231,9 +243,11 @@ void AsmPrinter::EmitToStreamer(MCStreamer &S, const MCInst &Inst) { } void AsmPrinter::emitInitialRawDwarfLocDirective(const MachineFunction &MF) { - assert(DD && "Dwarf debug file is not defined."); - assert(OutStreamer->hasRawTextSupport() && "Expected assembly output mode."); - (void)DD->emitInitialLocDirective(MF, /*CUID=*/0); + if (DD) { + assert(OutStreamer->hasRawTextSupport() && + "Expected assembly output mode."); + (void)DD->emitInitialLocDirective(MF, /*CUID=*/0); + } } /// getCurrentSection() - Return the current section we are emitting to. @@ -261,6 +275,9 @@ bool AsmPrinter::doInitialization(Module &M) { OutStreamer->InitSections(false); + if (DisableDebugInfoPrinting) + MMI->setDebugInfoAvailability(false); + // Emit the version-min deployment target directive if needed. // // FIXME: If we end up with a collection of these sorts of Darwin-specific @@ -296,6 +313,7 @@ bool AsmPrinter::doInitialization(Module &M) { std::unique_ptr<MCSubtargetInfo> STI(TM.getTarget().createMCSubtargetInfo( TM.getTargetTriple().str(), TM.getTargetCPU(), TM.getTargetFeatureString())); + assert(STI && "Unable to create subtarget info"); OutStreamer->AddComment("Start of file scope inline assembly"); OutStreamer->AddBlankLine(); emitInlineAsm(M.getModuleInlineAsm() + "\n", @@ -313,14 +331,21 @@ bool AsmPrinter::doInitialization(Module &M) { CodeViewLineTablesGroupDescription); } if (!EmitCodeView || M.getDwarfVersion()) { - DD = new DwarfDebug(this, &M); - DD->beginModule(); - Handlers.emplace_back(std::unique_ptr<DwarfDebug>(DD), DbgTimerName, - DbgTimerDescription, DWARFGroupName, - DWARFGroupDescription); + if (!DisableDebugInfoPrinting) { + DD = new DwarfDebug(this); + Handlers.emplace_back(std::unique_ptr<DwarfDebug>(DD), DbgTimerName, + DbgTimerDescription, DWARFGroupName, + DWARFGroupDescription); + } } } + if (M.getNamedMetadata(PseudoProbeDescMetadataName)) { + PP = new PseudoProbeHandler(this, &M); + Handlers.emplace_back(std::unique_ptr<PseudoProbeHandler>(PP), PPTimerName, + PPTimerDescription, PPGroupName, PPGroupDescription); + } + switch (MAI->getExceptionHandlingType()) { case ExceptionHandling::SjLj: case ExceptionHandling::DwarfCFI: @@ -368,6 +393,9 @@ bool AsmPrinter::doInitialization(Module &M) { case ExceptionHandling::Wasm: ES = new WasmException(this); break; + case ExceptionHandling::AIX: + ES = new AIXException(this); + break; } if (ES) Handlers.emplace_back(std::unique_ptr<EHStreamer>(ES), EHTimerName, @@ -379,6 +407,13 @@ bool AsmPrinter::doInitialization(Module &M) { Handlers.emplace_back(std::make_unique<WinCFGuard>(this), CFGuardName, CFGuardDescription, DWARFGroupName, DWARFGroupDescription); + + for (const HandlerInfo &HI : Handlers) { + NamedRegionTimer T(HI.TimerName, HI.TimerDescription, HI.TimerGroupName, + HI.TimerGroupDescription, TimePassesIsEnabled); + HI.Handler->beginModule(&M); + } + return false; } @@ -449,10 +484,8 @@ MCSymbol *AsmPrinter::getSymbolPreferLocal(const GlobalValue &GV) const { if (TM.getTargetTriple().isOSBinFormatELF() && GV.canBenefitFromLocalAlias()) { const Module &M = *GV.getParent(); if (TM.getRelocationModel() != Reloc::Static && - M.getPIELevel() == PIELevel::Default) - if (GV.isDSOLocal() || (TM.getTargetTriple().isX86() && - GV.getParent()->noSemanticInterposition())) - return getSymbolWithGlobalValueBase(&GV, "$local"); + M.getPIELevel() == PIELevel::Default && GV.isDSOLocal()) + return getSymbolWithGlobalValueBase(&GV, "$local"); } return TM.getSymbol(&GV); } @@ -500,8 +533,8 @@ void AsmPrinter::emitGlobalVariable(const GlobalVariable *GV) { GVSym->redefineIfPossible(); if (GVSym->isDefined() || GVSym->isVariable()) - report_fatal_error("symbol '" + Twine(GVSym->getName()) + - "' is already defined"); + OutContext.reportError(SMLoc(), "symbol '" + Twine(GVSym->getName()) + + "' is already defined"); if (MAI->hasDotTypeDotSizeDirective()) OutStreamer->emitSymbolAttribute(EmittedSym, MCSA_ELF_TypeObject); @@ -812,13 +845,21 @@ static void emitComments(const MachineInstr &MI, raw_ostream &CommentOS) { if ((Size = MI.getRestoreSize(TII))) { CommentOS << *Size << "-byte Reload\n"; } else if ((Size = MI.getFoldedRestoreSize(TII))) { - if (*Size) - CommentOS << *Size << "-byte Folded Reload\n"; + if (*Size) { + if (*Size == unsigned(MemoryLocation::UnknownSize)) + CommentOS << "Unknown-size Folded Reload\n"; + else + CommentOS << *Size << "-byte Folded Reload\n"; + } } else if ((Size = MI.getSpillSize(TII))) { CommentOS << *Size << "-byte Spill\n"; } else if ((Size = MI.getFoldedSpillSize(TII))) { - if (*Size) - CommentOS << *Size << "-byte Folded Spill\n"; + if (*Size) { + if (*Size == unsigned(MemoryLocation::UnknownSize)) + CommentOS << "Unknown-size Folded Spill\n"; + else + CommentOS << *Size << "-byte Folded Spill\n"; + } } // Check for spill-induced copies @@ -877,7 +918,7 @@ static bool emitDebugValueComment(const MachineInstr *MI, AsmPrinter &AP) { // The second operand is only an offset if it's an immediate. bool MemLoc = MI->isIndirectDebugValue(); - int64_t Offset = MemLoc ? MI->getOperand(1).getImm() : 0; + auto Offset = StackOffset::getFixed(MemLoc ? MI->getOperand(1).getImm() : 0); const DIExpression *Expr = MI->getDebugExpression(); if (Expr->getNumElements()) { OS << '['; @@ -916,6 +957,8 @@ static bool emitDebugValueComment(const MachineInstr *MI, AsmPrinter &AP) { } else if (MI->getDebugOperand(0).isTargetIndex()) { auto Op = MI->getDebugOperand(0); OS << "!target-index(" << Op.getIndex() << "," << Op.getOffset() << ")"; + // NOTE: Want this comment at start of line, don't emit with AddComment. + AP.OutStreamer->emitRawComment(OS.str()); return true; } else { Register Reg; @@ -941,7 +984,7 @@ static bool emitDebugValueComment(const MachineInstr *MI, AsmPrinter &AP) { } if (MemLoc) - OS << '+' << Offset << ']'; + OS << '+' << Offset.getFixed() << ']'; // NOTE: Want this comment at start of line, don't emit with AddComment. AP.OutStreamer->emitRawComment(OS.str()); @@ -1023,6 +1066,56 @@ void AsmPrinter::emitFrameAlloc(const MachineInstr &MI) { MCConstantExpr::create(FrameOffset, OutContext)); } +/// Returns the BB metadata to be emitted in the .llvm_bb_addr_map section for a +/// given basic block. This can be used to capture more precise profile +/// information. We use the last 3 bits (LSBs) to ecnode the following +/// information: +/// * (1): set if return block (ret or tail call). +/// * (2): set if ends with a tail call. +/// * (3): set if exception handling (EH) landing pad. +/// The remaining bits are zero. +static unsigned getBBAddrMapMetadata(const MachineBasicBlock &MBB) { + const TargetInstrInfo *TII = MBB.getParent()->getSubtarget().getInstrInfo(); + return ((unsigned)MBB.isReturnBlock()) | + ((!MBB.empty() && TII->isTailCall(MBB.back())) << 1) | + (MBB.isEHPad() << 2); +} + +void AsmPrinter::emitBBAddrMapSection(const MachineFunction &MF) { + MCSection *BBAddrMapSection = + getObjFileLowering().getBBAddrMapSection(*MF.getSection()); + assert(BBAddrMapSection && ".llvm_bb_addr_map section is not initialized."); + + const MCSymbol *FunctionSymbol = getFunctionBegin(); + + OutStreamer->PushSection(); + OutStreamer->SwitchSection(BBAddrMapSection); + OutStreamer->emitSymbolValue(FunctionSymbol, getPointerSize()); + // Emit the total number of basic blocks in this function. + OutStreamer->emitULEB128IntValue(MF.size()); + // Emit BB Information for each basic block in the funciton. + for (const MachineBasicBlock &MBB : MF) { + const MCSymbol *MBBSymbol = + MBB.isEntryBlock() ? FunctionSymbol : MBB.getSymbol(); + // Emit the basic block offset. + emitLabelDifferenceAsULEB128(MBBSymbol, FunctionSymbol); + // Emit the basic block size. When BBs have alignments, their size cannot + // always be computed from their offsets. + emitLabelDifferenceAsULEB128(MBB.getEndSymbol(), MBBSymbol); + OutStreamer->emitULEB128IntValue(getBBAddrMapMetadata(MBB)); + } + OutStreamer->PopSection(); +} + +void AsmPrinter::emitPseudoProbe(const MachineInstr &MI) { + auto GUID = MI.getOperand(0).getImm(); + auto Index = MI.getOperand(1).getImm(); + auto Type = MI.getOperand(2).getImm(); + auto Attr = MI.getOperand(3).getImm(); + DILocation *DebugLoc = MI.getDebugLoc(); + PP->emitPseudoProbe(GUID, Index, Type, Attr, DebugLoc); +} + void AsmPrinter::emitStackSizeSection(const MachineFunction &MF) { if (!MF.getTarget().Options.EmitStackSizeSection) return; @@ -1069,8 +1162,6 @@ void AsmPrinter::emitFunctionBody() { // Emit target-specific gunk before the function body. emitFunctionBodyStart(); - bool ShouldPrintDebugScopes = MMI->hasDebugInfo(); - if (isVerbose()) { // Get MachineDominatorTree or compute it on the fly if it's unavailable MDT = getAnalysisIfAvailable<MachineDominatorTree>(); @@ -1093,9 +1184,11 @@ void AsmPrinter::emitFunctionBody() { bool HasAnyRealCode = false; int NumInstsInFunction = 0; + bool CanDoExtraAnalysis = ORE->allowExtraAnalysis(DEBUG_TYPE); for (auto &MBB : *MF) { // Print a label for the basic block. emitBasicBlockStart(MBB); + DenseMap<StringRef, unsigned> MnemonicCounts; for (auto &MI : MBB) { // Print the assembly for the instruction. if (!MI.isPosition() && !MI.isImplicitDef() && !MI.isKill() && @@ -1108,13 +1201,10 @@ void AsmPrinter::emitFunctionBody() { if (MCSymbol *S = MI.getPreInstrSymbol()) OutStreamer->emitLabel(S); - if (ShouldPrintDebugScopes) { - for (const HandlerInfo &HI : Handlers) { - NamedRegionTimer T(HI.TimerName, HI.TimerDescription, - HI.TimerGroupName, HI.TimerGroupDescription, - TimePassesIsEnabled); - HI.Handler->beginInstruction(&MI); - } + for (const HandlerInfo &HI : Handlers) { + NamedRegionTimer T(HI.TimerName, HI.TimerDescription, HI.TimerGroupName, + HI.TimerGroupDescription, TimePassesIsEnabled); + HI.Handler->beginInstruction(&MI); } if (isVerbose()) @@ -1142,6 +1232,11 @@ void AsmPrinter::emitFunctionBody() { emitInstruction(&MI); } break; + case TargetOpcode::DBG_INSTR_REF: + // This instruction reference will have been resolved to a machine + // location, and a nearby DBG_VALUE created. We can safely ignore + // the instruction reference. + break; case TargetOpcode::DBG_LABEL: if (isVerbose()) { if (!emitDebugLabelComment(&MI, *this)) @@ -1154,8 +1249,18 @@ void AsmPrinter::emitFunctionBody() { case TargetOpcode::KILL: if (isVerbose()) emitKill(&MI, *this); break; + case TargetOpcode::PSEUDO_PROBE: + emitPseudoProbe(MI); + break; default: emitInstruction(&MI); + if (CanDoExtraAnalysis) { + MCInst MCI; + MCI.setOpcode(MI.getOpcode()); + auto Name = OutStreamer->getMnemonic(MCI); + auto I = MnemonicCounts.insert({Name, 0u}); + I.first->second++; + } break; } @@ -1163,54 +1268,69 @@ void AsmPrinter::emitFunctionBody() { if (MCSymbol *S = MI.getPostInstrSymbol()) OutStreamer->emitLabel(S); - if (ShouldPrintDebugScopes) { - for (const HandlerInfo &HI : Handlers) { - NamedRegionTimer T(HI.TimerName, HI.TimerDescription, - HI.TimerGroupName, HI.TimerGroupDescription, - TimePassesIsEnabled); - HI.Handler->endInstruction(); - } + for (const HandlerInfo &HI : Handlers) { + NamedRegionTimer T(HI.TimerName, HI.TimerDescription, HI.TimerGroupName, + HI.TimerGroupDescription, TimePassesIsEnabled); + HI.Handler->endInstruction(); } } - // We need a temporary symbol for the end of this basic block, if either we - // have BBLabels enabled and we want to emit size directive for the BBs, or - // if this basic blocks marks the end of a section (except the section - // containing the entry basic block as the end symbol for that section is - // CurrentFnEnd). - MCSymbol *CurrentBBEnd = nullptr; - if ((MAI->hasDotTypeDotSizeDirective() && MF->hasBBLabels()) || - (MBB.isEndSection() && !MBB.sameSection(&MF->front()))) { - CurrentBBEnd = OutContext.createTempSymbol(); - OutStreamer->emitLabel(CurrentBBEnd); - } + // We must emit temporary symbol for the end of this basic block, if either + // we have BBLabels enabled or if this basic blocks marks the end of a + // section (except the section containing the entry basic block as the end + // symbol for that section is CurrentFnEnd). + if (MF->hasBBLabels() || + (MAI->hasDotTypeDotSizeDirective() && MBB.isEndSection() && + !MBB.sameSection(&MF->front()))) + OutStreamer->emitLabel(MBB.getEndSymbol()); - // Helper for emitting the size directive associated with a basic block - // symbol. - auto emitELFSizeDirective = [&](MCSymbol *SymForSize) { - assert(CurrentBBEnd && "Basicblock end symbol not set!"); - const MCExpr *SizeExp = MCBinaryExpr::createSub( - MCSymbolRefExpr::create(CurrentBBEnd, OutContext), - MCSymbolRefExpr::create(SymForSize, OutContext), OutContext); - OutStreamer->emitELFSize(SymForSize, SizeExp); - }; - - // Emit size directive for the size of each basic block, if BBLabels is - // enabled. - if (MAI->hasDotTypeDotSizeDirective() && MF->hasBBLabels()) - emitELFSizeDirective(MBB.getSymbol()); - - // Emit size directive for the size of each basic block section once we - // get to the end of that section. if (MBB.isEndSection()) { + // The size directive for the section containing the entry block is + // handled separately by the function section. if (!MBB.sameSection(&MF->front())) { - if (MAI->hasDotTypeDotSizeDirective()) - emitELFSizeDirective(CurrentSectionBeginSym); + if (MAI->hasDotTypeDotSizeDirective()) { + // Emit the size directive for the basic block section. + const MCExpr *SizeExp = MCBinaryExpr::createSub( + MCSymbolRefExpr::create(MBB.getEndSymbol(), OutContext), + MCSymbolRefExpr::create(CurrentSectionBeginSym, OutContext), + OutContext); + OutStreamer->emitELFSize(CurrentSectionBeginSym, SizeExp); + } MBBSectionRanges[MBB.getSectionIDNum()] = - MBBSectionRange{CurrentSectionBeginSym, CurrentBBEnd}; + MBBSectionRange{CurrentSectionBeginSym, MBB.getEndSymbol()}; } } emitBasicBlockEnd(MBB); + + if (CanDoExtraAnalysis) { + // Skip empty blocks. + if (MBB.empty()) + continue; + + MachineOptimizationRemarkAnalysis R(DEBUG_TYPE, "InstructionMix", + MBB.begin()->getDebugLoc(), &MBB); + + // Generate instruction mix remark. First, sort counts in descending order + // by count and name. + SmallVector<std::pair<StringRef, unsigned>, 128> MnemonicVec; + for (auto &KV : MnemonicCounts) + MnemonicVec.emplace_back(KV.first, KV.second); + + sort(MnemonicVec, [](const std::pair<StringRef, unsigned> &A, + const std::pair<StringRef, unsigned> &B) { + if (A.second > B.second) + return true; + if (A.second == B.second) + return StringRef(A.first) < StringRef(B.first); + return false; + }); + R << "BasicBlock: " << ore::NV("BasicBlock", MBB.getName()) << "\n"; + for (auto &KV : MnemonicVec) { + auto Name = (Twine("INST_") + KV.first.trim()).str(); + R << KV.first << ": " << ore::NV(Name, KV.second) << "\n"; + } + ORE->emit(R); + } } EmittedInsts += NumInstsInFunction; @@ -1297,6 +1417,11 @@ void AsmPrinter::emitFunctionBody() { HI.Handler->endFunction(MF); } + // Emit section containing BB address offsets and their metadata, when + // BB labels are requested for this function. + if (MF->hasBBLabels()) + emitBBAddrMapSection(*MF); + // Emit section containing stack size metadata. emitStackSizeSection(*MF); @@ -1390,16 +1515,7 @@ void AsmPrinter::emitGlobalGOTEquivs() { void AsmPrinter::emitGlobalIndirectSymbol(Module &M, const GlobalIndirectSymbol& GIS) { MCSymbol *Name = getSymbol(&GIS); - - if (GIS.hasExternalLinkage() || !MAI->getWeakRefDirective()) - OutStreamer->emitSymbolAttribute(Name, MCSA_Global); - else if (GIS.hasWeakLinkage() || GIS.hasLinkOnceLinkage()) - OutStreamer->emitSymbolAttribute(Name, MCSA_WeakReference); - else - assert(GIS.hasLocalLinkage() && "Invalid alias or ifunc linkage"); - bool IsFunction = GIS.getValueType()->isFunctionTy(); - // Treat bitcasts of functions as functions also. This is important at least // on WebAssembly where object and function addresses can't alias each other. if (!IsFunction) @@ -1408,6 +1524,30 @@ void AsmPrinter::emitGlobalIndirectSymbol(Module &M, IsFunction = CE->getOperand(0)->getType()->getPointerElementType()->isFunctionTy(); + // AIX's assembly directive `.set` is not usable for aliasing purpose, + // so AIX has to use the extra-label-at-definition strategy. At this + // point, all the extra label is emitted, we just have to emit linkage for + // those labels. + if (TM.getTargetTriple().isOSBinFormatXCOFF()) { + assert(!isa<GlobalIFunc>(GIS) && "IFunc is not supported on AIX."); + assert(MAI->hasVisibilityOnlyWithLinkage() && + "Visibility should be handled with emitLinkage() on AIX."); + emitLinkage(&GIS, Name); + // If it's a function, also emit linkage for aliases of function entry + // point. + if (IsFunction) + emitLinkage(&GIS, + getObjFileLowering().getFunctionEntryPointSymbol(&GIS, TM)); + return; + } + + if (GIS.hasExternalLinkage() || !MAI->getWeakRefDirective()) + OutStreamer->emitSymbolAttribute(Name, MCSA_Global); + else if (GIS.hasWeakLinkage() || GIS.hasLinkOnceLinkage()) + OutStreamer->emitSymbolAttribute(Name, MCSA_WeakReference); + else + assert(GIS.hasLocalLinkage() && "Invalid alias or ifunc linkage"); + // Set the symbol type to function if the alias has a function type. // This affects codegen when the aliasee is not a function. if (IsFunction) @@ -1517,9 +1657,8 @@ bool AsmPrinter::doFinalization(Module &M) { // Variable `Name` is the function descriptor symbol (see above). Get the // function entry point symbol. MCSymbol *FnEntryPointSym = TLOF.getFunctionEntryPointSymbol(&F, TM); - if (cast<MCSymbolXCOFF>(FnEntryPointSym)->hasRepresentedCsectSet()) - // Emit linkage for the function entry point. - emitLinkage(&F, FnEntryPointSym); + // Emit linkage for the function entry point. + emitLinkage(&F, FnEntryPointSym); // Emit linkage for the function descriptor. emitLinkage(&F, Name); @@ -1584,7 +1723,11 @@ bool AsmPrinter::doFinalization(Module &M) { HI.TimerGroupDescription, TimePassesIsEnabled); HI.Handler->endModule(); } - Handlers.clear(); + + // This deletes all the ephemeral handlers that AsmPrinter added, while + // keeping all the user-added handlers alive until the AsmPrinter is + // destroyed. + Handlers.erase(Handlers.begin() + NumUserHandlers, Handlers.end()); DD = nullptr; // If the target wants to know about weak references, print them all. @@ -1668,51 +1811,6 @@ bool AsmPrinter::doFinalization(Module &M) { if (MCSection *S = MAI->getNonexecutableStackSection(OutContext)) OutStreamer->SwitchSection(S); - if (TM.getTargetTriple().isOSBinFormatCOFF()) { - // Emit /EXPORT: flags for each exported global as necessary. - const auto &TLOF = getObjFileLowering(); - std::string Flags; - - for (const GlobalValue &GV : M.global_values()) { - raw_string_ostream OS(Flags); - TLOF.emitLinkerFlagsForGlobal(OS, &GV); - OS.flush(); - if (!Flags.empty()) { - OutStreamer->SwitchSection(TLOF.getDrectveSection()); - OutStreamer->emitBytes(Flags); - } - Flags.clear(); - } - - // Emit /INCLUDE: flags for each used global as necessary. - if (const auto *LU = M.getNamedGlobal("llvm.used")) { - assert(LU->hasInitializer() && - "expected llvm.used to have an initializer"); - assert(isa<ArrayType>(LU->getValueType()) && - "expected llvm.used to be an array type"); - if (const auto *A = cast<ConstantArray>(LU->getInitializer())) { - for (const Value *Op : A->operands()) { - const auto *GV = cast<GlobalValue>(Op->stripPointerCasts()); - // Global symbols with internal or private linkage are not visible to - // the linker, and thus would cause an error when the linker tried to - // preserve the symbol due to the `/include:` directive. - if (GV->hasLocalLinkage()) - continue; - - raw_string_ostream OS(Flags); - TLOF.emitLinkerFlagsForUsed(OS, GV); - OS.flush(); - - if (!Flags.empty()) { - OutStreamer->SwitchSection(TLOF.getDrectveSection()); - OutStreamer->emitBytes(Flags); - } - Flags.clear(); - } - } - } - } - if (TM.Options.EmitAddrsig) { // Emit address-significance attributes for all globals. OutStreamer->emitAddrsig(); @@ -1756,10 +1854,11 @@ bool AsmPrinter::doFinalization(Module &M) { return false; } -MCSymbol *AsmPrinter::getCurExceptionSym() { - if (!CurExceptionSym) - CurExceptionSym = createTempSymbol("exception"); - return CurExceptionSym; +MCSymbol *AsmPrinter::getMBBExceptionSym(const MachineBasicBlock &MBB) { + auto Res = MBBSectionExceptionSyms.try_emplace(MBB.getSectionIDNum()); + if (Res.second) + Res.first->second = createTempSymbol("exception"); + return Res.first->second; } void AsmPrinter::SetupMachineFunction(MachineFunction &MF) { @@ -1786,13 +1885,13 @@ void AsmPrinter::SetupMachineFunction(MachineFunction &MF) { CurrentFnBegin = nullptr; CurrentSectionBeginSym = nullptr; MBBSectionRanges.clear(); - CurExceptionSym = nullptr; + MBBSectionExceptionSyms.clear(); bool NeedsLocalForSize = MAI->needsLocalForSize(); if (F.hasFnAttribute("patchable-function-entry") || F.hasFnAttribute("function-instrument") || F.hasFnAttribute("xray-instruction-threshold") || needFuncLabelsForEHOrDebugInfo(MF) || NeedsLocalForSize || - MF.getTarget().Options.EmitStackSizeSection) { + MF.getTarget().Options.EmitStackSizeSection || MF.hasBBLabels()) { CurrentFnBegin = createTempSymbol("func_begin"); if (NeedsLocalForSize) CurrentFnSymForSize = CurrentFnBegin; @@ -1882,8 +1981,7 @@ void AsmPrinter::emitConstantPool() { unsigned NewOffset = alignTo(Offset, CPE.getAlign()); OutStreamer->emitZeros(NewOffset - Offset); - Type *Ty = CPE.getType(); - Offset = NewOffset + getDataLayout().getTypeAllocSize(Ty); + Offset = NewOffset + CPE.getSizeInBytes(getDataLayout()); OutStreamer->emitLabel(Sym); if (CPE.isMachineConstantPoolEntry()) @@ -2083,47 +2181,50 @@ void AsmPrinter::emitLLVMUsedList(const ConstantArray *InitList) { } } -namespace { - -struct Structor { - int Priority = 0; - Constant *Func = nullptr; - GlobalValue *ComdatKey = nullptr; - - Structor() = default; -}; - -} // end anonymous namespace - -/// EmitXXStructorList - Emit the ctor or dtor list taking into account the init -/// priority. -void AsmPrinter::emitXXStructorList(const DataLayout &DL, const Constant *List, - bool isCtor) { - // Should be an array of '{ i32, void ()*, i8* }' structs. The first value is the - // init priority. - if (!isa<ConstantArray>(List)) return; +void AsmPrinter::preprocessXXStructorList(const DataLayout &DL, + const Constant *List, + SmallVector<Structor, 8> &Structors) { + // Should be an array of '{ i32, void ()*, i8* }' structs. The first value is + // the init priority. + if (!isa<ConstantArray>(List)) + return; // Gather the structors in a form that's convenient for sorting by priority. - SmallVector<Structor, 8> Structors; for (Value *O : cast<ConstantArray>(List)->operands()) { auto *CS = cast<ConstantStruct>(O); if (CS->getOperand(1)->isNullValue()) - break; // Found a null terminator, skip the rest. + break; // Found a null terminator, skip the rest. ConstantInt *Priority = dyn_cast<ConstantInt>(CS->getOperand(0)); - if (!Priority) continue; // Malformed. + if (!Priority) + continue; // Malformed. Structors.push_back(Structor()); Structor &S = Structors.back(); S.Priority = Priority->getLimitedValue(65535); S.Func = CS->getOperand(1); - if (!CS->getOperand(2)->isNullValue()) + if (!CS->getOperand(2)->isNullValue()) { + if (TM.getTargetTriple().isOSAIX()) + llvm::report_fatal_error( + "associated data of XXStructor list is not yet supported on AIX"); S.ComdatKey = dyn_cast<GlobalValue>(CS->getOperand(2)->stripPointerCasts()); + } } // Emit the function pointers in the target-specific order llvm::stable_sort(Structors, [](const Structor &L, const Structor &R) { return L.Priority < R.Priority; }); +} + +/// EmitXXStructorList - Emit the ctor or dtor list taking into account the init +/// priority. +void AsmPrinter::emitXXStructorList(const DataLayout &DL, const Constant *List, + bool IsCtor) { + SmallVector<Structor, 8> Structors; + preprocessXXStructorList(DL, List, Structors); + if (Structors.empty()) + return; + const Align Align = DL.getPointerPrefAlignment(); for (Structor &S : Structors) { const TargetLoweringObjectFile &Obj = getObjFileLowering(); @@ -2139,8 +2240,9 @@ void AsmPrinter::emitXXStructorList(const DataLayout &DL, const Constant *List, KeySym = getSymbol(GV); } + MCSection *OutputSection = - (isCtor ? Obj.getStaticCtorSection(S.Priority, KeySym) + (IsCtor ? Obj.getStaticCtorSection(S.Priority, KeySym) : Obj.getStaticDtorSection(S.Priority, KeySym)); OutStreamer->SwitchSection(OutputSection); if (OutStreamer->getCurrentSection() != OutStreamer->getPreviousSection()) @@ -2274,12 +2376,25 @@ const MCExpr *AsmPrinter::lowerConstant(const Constant *CV) { if (const BlockAddress *BA = dyn_cast<BlockAddress>(CV)) return MCSymbolRefExpr::create(GetBlockAddressSymbol(BA), Ctx); + if (const auto *Equiv = dyn_cast<DSOLocalEquivalent>(CV)) + return getObjFileLowering().lowerDSOLocalEquivalent(Equiv, TM); + const ConstantExpr *CE = dyn_cast<ConstantExpr>(CV); if (!CE) { llvm_unreachable("Unknown constant value to lower!"); } switch (CE->getOpcode()) { + case Instruction::AddrSpaceCast: { + const Constant *Op = CE->getOperand(0); + unsigned DstAS = CE->getType()->getPointerAddressSpace(); + unsigned SrcAS = Op->getType()->getPointerAddressSpace(); + if (TM.isNoopAddrSpaceCast(SrcAS, DstAS)) + return lowerConstant(Op); + + // Fallthrough to error. + LLVM_FALLTHROUGH; + } default: { // If the code isn't optimized, there may be outstanding folding // opportunities. Attempt to fold the expression using DataLayout as a @@ -2345,7 +2460,8 @@ const MCExpr *AsmPrinter::lowerConstant(const Constant *CV) { // // If the pointer is larger than the resultant integer, then // as with Trunc just depend on the assembler to truncate it. - if (DL.getTypeAllocSize(Ty) <= DL.getTypeAllocSize(Op->getType())) + if (DL.getTypeAllocSize(Ty).getFixedSize() <= + DL.getTypeAllocSize(Op->getType()).getFixedSize()) return OpExpr; // Otherwise the pointer is smaller than the resultant integer, mask off @@ -2359,18 +2475,25 @@ const MCExpr *AsmPrinter::lowerConstant(const Constant *CV) { case Instruction::Sub: { GlobalValue *LHSGV; APInt LHSOffset; + DSOLocalEquivalent *DSOEquiv; if (IsConstantOffsetFromGlobal(CE->getOperand(0), LHSGV, LHSOffset, - getDataLayout())) { + getDataLayout(), &DSOEquiv)) { GlobalValue *RHSGV; APInt RHSOffset; if (IsConstantOffsetFromGlobal(CE->getOperand(1), RHSGV, RHSOffset, getDataLayout())) { const MCExpr *RelocExpr = getObjFileLowering().lowerRelativeReference(LHSGV, RHSGV, TM); - if (!RelocExpr) + if (!RelocExpr) { + const MCExpr *LHSExpr = + MCSymbolRefExpr::create(getSymbol(LHSGV), Ctx); + if (DSOEquiv && + getObjFileLowering().supportDSOLocalEquivalentLowering()) + LHSExpr = + getObjFileLowering().lowerDSOLocalEquivalent(DSOEquiv, TM); RelocExpr = MCBinaryExpr::createSub( - MCSymbolRefExpr::create(getSymbol(LHSGV), Ctx), - MCSymbolRefExpr::create(getSymbol(RHSGV), Ctx), Ctx); + LHSExpr, MCSymbolRefExpr::create(getSymbol(RHSGV), Ctx), Ctx); + } int64_t Addend = (LHSOffset - RHSOffset).getSExtValue(); if (Addend != 0) RelocExpr = MCBinaryExpr::createAdd( @@ -3001,7 +3124,7 @@ static void emitBasicBlockLoopComments(const MachineBasicBlock &MBB, OS.indent(Loop->getLoopDepth()*2-2); OS << "This "; - if (Loop->empty()) + if (Loop->isInnermost()) OS << "Inner "; OS << "Loop Header: Depth=" + Twine(Loop->getLoopDepth()) << '\n'; @@ -3025,6 +3148,16 @@ void AsmPrinter::emitBasicBlockStart(const MachineBasicBlock &MBB) { if (Alignment != Align(1)) emitAlignment(Alignment); + // Switch to a new section if this basic block must begin a section. The + // entry block is always placed in the function section and is handled + // separately. + if (MBB.isBeginSection() && !MBB.isEntryBlock()) { + OutStreamer->SwitchSection( + getObjFileLowering().getSectionForMachineBasicBlock(MF->getFunction(), + MBB, TM)); + CurrentSectionBeginSym = MBB.getSymbol(); + } + // If the block has its address taken, emit any labels that were used to // reference the block. It is possible that there is more than one label // here, because multiple LLVM BB's may have been RAUW'd to this block after @@ -3055,33 +3188,25 @@ void AsmPrinter::emitBasicBlockStart(const MachineBasicBlock &MBB) { emitBasicBlockLoopComments(MBB, MLI, *this); } - if (MBB.pred_empty() || - (!MF->hasBBLabels() && isBlockOnlyReachableByFallthrough(&MBB) && - !MBB.isEHFuncletEntry() && !MBB.hasLabelMustBeEmitted())) { + // Print the main label for the block. + if (shouldEmitLabelForBasicBlock(MBB)) { + if (isVerbose() && MBB.hasLabelMustBeEmitted()) + OutStreamer->AddComment("Label of block must be emitted"); + OutStreamer->emitLabel(MBB.getSymbol()); + } else { if (isVerbose()) { // NOTE: Want this comment at start of line, don't emit with AddComment. OutStreamer->emitRawComment(" %bb." + Twine(MBB.getNumber()) + ":", false); } - } else { - if (isVerbose() && MBB.hasLabelMustBeEmitted()) { - OutStreamer->AddComment("Label of block must be emitted"); - } - auto *BBSymbol = MBB.getSymbol(); - // Switch to a new section if this basic block must begin a section. - if (MBB.isBeginSection()) { - OutStreamer->SwitchSection( - getObjFileLowering().getSectionForMachineBasicBlock(MF->getFunction(), - MBB, TM)); - CurrentSectionBeginSym = BBSymbol; - } - OutStreamer->emitLabel(BBSymbol); - // With BB sections, each basic block must handle CFI information on its own - // if it begins a section. - if (MBB.isBeginSection()) - for (const HandlerInfo &HI : Handlers) - HI.Handler->beginBasicBlock(MBB); } + + // With BB sections, each basic block must handle CFI information on its own + // if it begins a section (Entry block is handled separately by + // AsmPrinterHandler::beginFunction). + if (MBB.isBeginSection() && !MBB.isEntryBlock()) + for (const HandlerInfo &HI : Handlers) + HI.Handler->beginBasicBlock(MBB); } void AsmPrinter::emitBasicBlockEnd(const MachineBasicBlock &MBB) { @@ -3113,15 +3238,26 @@ void AsmPrinter::emitVisibility(MCSymbol *Sym, unsigned Visibility, OutStreamer->emitSymbolAttribute(Sym, Attr); } +bool AsmPrinter::shouldEmitLabelForBasicBlock( + const MachineBasicBlock &MBB) const { + // With `-fbasic-block-sections=`, a label is needed for every non-entry block + // in the labels mode (option `=labels`) and every section beginning in the + // sections mode (`=all` and `=list=`). + if ((MF->hasBBLabels() || MBB.isBeginSection()) && !MBB.isEntryBlock()) + return true; + // A label is needed for any block with at least one predecessor (when that + // predecessor is not the fallthrough predecessor, or if it is an EH funclet + // entry, or if a label is forced). + return !MBB.pred_empty() && + (!isBlockOnlyReachableByFallthrough(&MBB) || MBB.isEHFuncletEntry() || + MBB.hasLabelMustBeEmitted()); +} + /// isBlockOnlyReachableByFallthough - Return true if the basic block has /// exactly one predecessor and the control transfer mechanism between /// the predecessor and this block is a fall-through. bool AsmPrinter:: isBlockOnlyReachableByFallthrough(const MachineBasicBlock *MBB) const { - // With BasicBlock Sections, beginning of the section is not a fallthrough. - if (MBB->isBeginSection()) - return false; - // If this is a landing pad, it isn't a fall through. If it has no preds, // then nothing falls through to it. if (MBB->isEHPad() || MBB->pred_empty()) @@ -3232,14 +3368,10 @@ void AsmPrinter::emitXRayTable() { MCSection *InstMap = nullptr; MCSection *FnSledIndex = nullptr; const Triple &TT = TM.getTargetTriple(); - // Use PC-relative addresses on all targets except MIPS (MIPS64 cannot use - // PC-relative addresses because R_MIPS_PC64 does not exist). - bool PCRel = !TT.isMIPS(); + // Use PC-relative addresses on all targets. if (TT.isOSBinFormatELF()) { auto LinkedToSym = cast<MCSymbolELF>(CurrentFnSym); auto Flags = ELF::SHF_ALLOC | ELF::SHF_LINK_ORDER; - if (!PCRel) - Flags |= ELF::SHF_WRITE; StringRef GroupName; if (F.hasComdat()) { Flags |= ELF::SHF_GROUP; @@ -3273,25 +3405,20 @@ void AsmPrinter::emitXRayTable() { OutStreamer->SwitchSection(InstMap); OutStreamer->emitLabel(SledsStart); for (const auto &Sled : Sleds) { - if (PCRel) { - MCSymbol *Dot = Ctx.createTempSymbol(); - OutStreamer->emitLabel(Dot); - OutStreamer->emitValueImpl( - MCBinaryExpr::createSub(MCSymbolRefExpr::create(Sled.Sled, Ctx), - MCSymbolRefExpr::create(Dot, Ctx), Ctx), - WordSizeBytes); - OutStreamer->emitValueImpl( - MCBinaryExpr::createSub( - MCSymbolRefExpr::create(CurrentFnBegin, Ctx), - MCBinaryExpr::createAdd( - MCSymbolRefExpr::create(Dot, Ctx), - MCConstantExpr::create(WordSizeBytes, Ctx), Ctx), - Ctx), - WordSizeBytes); - } else { - OutStreamer->emitSymbolValue(Sled.Sled, WordSizeBytes); - OutStreamer->emitSymbolValue(CurrentFnSym, WordSizeBytes); - } + MCSymbol *Dot = Ctx.createTempSymbol(); + OutStreamer->emitLabel(Dot); + OutStreamer->emitValueImpl( + MCBinaryExpr::createSub(MCSymbolRefExpr::create(Sled.Sled, Ctx), + MCSymbolRefExpr::create(Dot, Ctx), Ctx), + WordSizeBytes); + OutStreamer->emitValueImpl( + MCBinaryExpr::createSub( + MCSymbolRefExpr::create(CurrentFnBegin, Ctx), + MCBinaryExpr::createAdd(MCSymbolRefExpr::create(Dot, Ctx), + MCConstantExpr::create(WordSizeBytes, Ctx), + Ctx), + Ctx), + WordSizeBytes); Sled.emit(WordSizeBytes, OutStreamer.get()); } MCSymbol *SledsEnd = OutContext.createTempSymbol("xray_sleds_end", true); @@ -3366,3 +3493,17 @@ uint16_t AsmPrinter::getDwarfVersion() const { void AsmPrinter::setDwarfVersion(uint16_t Version) { OutStreamer->getContext().setDwarfVersion(Version); } + +bool AsmPrinter::isDwarf64() const { + return OutStreamer->getContext().getDwarfFormat() == dwarf::DWARF64; +} + +unsigned int AsmPrinter::getDwarfOffsetByteSize() const { + return dwarf::getDwarfOffsetByteSize( + OutStreamer->getContext().getDwarfFormat()); +} + +unsigned int AsmPrinter::getUnitLengthFieldByteSize() const { + return dwarf::getUnitLengthFieldByteSize( + OutStreamer->getContext().getDwarfFormat()); +} |