diff options
Diffstat (limited to 'lib/CodeGen/AsmPrinter/AsmPrinter.cpp')
-rw-r--r-- | lib/CodeGen/AsmPrinter/AsmPrinter.cpp | 300 |
1 files changed, 174 insertions, 126 deletions
diff --git a/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/lib/CodeGen/AsmPrinter/AsmPrinter.cpp index ff427c9a0d75..31037095aa2b 100644 --- a/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ b/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -1,4 +1,4 @@ -//===-- AsmPrinter.cpp - Common AsmPrinter code ---------------------------===// +//===- AsmPrinter.cpp - Common AsmPrinter code ----------------------------===// // // The LLVM Compiler Infrastructure // @@ -29,10 +29,11 @@ #include "llvm/ADT/Triple.h" #include "llvm/ADT/Twine.h" #include "llvm/Analysis/ConstantFolding.h" +#include "llvm/Analysis/EHPersonalities.h" #include "llvm/Analysis/ObjectUtils.h" +#include "llvm/Analysis/OptimizationRemarkEmitter.h" #include "llvm/BinaryFormat/Dwarf.h" #include "llvm/BinaryFormat/ELF.h" -#include "llvm/CodeGen/Analysis.h" #include "llvm/CodeGen/GCMetadata.h" #include "llvm/CodeGen/GCMetadataPrinter.h" #include "llvm/CodeGen/GCStrategy.h" @@ -46,10 +47,19 @@ #include "llvm/CodeGen/MachineJumpTableInfo.h" #include "llvm/CodeGen/MachineLoopInfo.h" #include "llvm/CodeGen/MachineMemOperand.h" +#include "llvm/CodeGen/MachineModuleInfo.h" #include "llvm/CodeGen/MachineModuleInfoImpls.h" #include "llvm/CodeGen/MachineOperand.h" #include "llvm/CodeGen/MachineOptimizationRemarkEmitter.h" +#include "llvm/CodeGen/TargetFrameLowering.h" +#include "llvm/CodeGen/TargetInstrInfo.h" +#include "llvm/CodeGen/TargetLowering.h" +#include "llvm/CodeGen/TargetLoweringObjectFile.h" +#include "llvm/CodeGen/TargetOpcodes.h" +#include "llvm/CodeGen/TargetRegisterInfo.h" +#include "llvm/CodeGen/TargetSubtargetInfo.h" #include "llvm/IR/BasicBlock.h" +#include "llvm/IR/Comdat.h" #include "llvm/IR/Constant.h" #include "llvm/IR/Constants.h" #include "llvm/IR/DataLayout.h" @@ -62,14 +72,18 @@ #include "llvm/IR/GlobalObject.h" #include "llvm/IR/GlobalValue.h" #include "llvm/IR/GlobalVariable.h" +#include "llvm/IR/Instruction.h" #include "llvm/IR/Mangler.h" #include "llvm/IR/Metadata.h" #include "llvm/IR/Module.h" #include "llvm/IR/Operator.h" +#include "llvm/IR/Type.h" #include "llvm/IR/Value.h" #include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCCodePadder.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCDirectives.h" +#include "llvm/MC/MCDwarf.h" #include "llvm/MC/MCExpr.h" #include "llvm/MC/MCInst.h" #include "llvm/MC/MCSection.h" @@ -78,29 +92,28 @@ #include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCSubtargetInfo.h" #include "llvm/MC/MCSymbol.h" +#include "llvm/MC/MCSymbolELF.h" #include "llvm/MC/MCTargetOptions.h" #include "llvm/MC/MCValue.h" #include "llvm/MC/SectionKind.h" #include "llvm/Pass.h" #include "llvm/Support/Casting.h" +#include "llvm/Support/CommandLine.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/Format.h" #include "llvm/Support/MathExtras.h" +#include "llvm/Support/Path.h" #include "llvm/Support/TargetRegistry.h" #include "llvm/Support/Timer.h" #include "llvm/Support/raw_ostream.h" -#include "llvm/Target/TargetFrameLowering.h" -#include "llvm/Target/TargetInstrInfo.h" -#include "llvm/Target/TargetLowering.h" -#include "llvm/Target/TargetLoweringObjectFile.h" #include "llvm/Target/TargetMachine.h" -#include "llvm/Target/TargetRegisterInfo.h" -#include "llvm/Target/TargetSubtargetInfo.h" +#include "llvm/Target/TargetOptions.h" #include <algorithm> #include <cassert> #include <cinttypes> #include <cstdint> +#include <iterator> #include <limits> #include <memory> #include <string> @@ -129,7 +142,8 @@ static cl::opt<bool> char AsmPrinter::ID = 0; -typedef DenseMap<GCStrategy*, std::unique_ptr<GCMetadataPrinter>> gcp_map_type; +using gcp_map_type = DenseMap<GCStrategy *, std::unique_ptr<GCMetadataPrinter>>; + static gcp_map_type &getGCMap(void *&P) { if (!P) P = new gcp_map_type(); @@ -184,7 +198,6 @@ bool AsmPrinter::isPositionIndependent() const { } /// getFunctionNumber - Return a unique ID for the current function. -/// unsigned AsmPrinter::getFunctionNumber() const { return MF->getFunctionNumber(); } @@ -221,8 +234,7 @@ void AsmPrinter::getAnalysisUsage(AnalysisUsage &AU) const { AU.addRequired<MachineModuleInfo>(); AU.addRequired<MachineOptimizationRemarkEmitterPass>(); AU.addRequired<GCModuleInfo>(); - if (isVerbose()) - AU.addRequired<MachineLoopInfo>(); + AU.addRequired<MachineLoopInfo>(); } bool AsmPrinter::doInitialization(Module &M) { @@ -242,28 +254,8 @@ bool AsmPrinter::doInitialization(Module &M) { // alternative is duplicated code in each of the target asm printers that // use the directive, where it would need the same conditionalization // anyway. - const Triple &TT = TM.getTargetTriple(); - // If there is a version specified, Major will be non-zero. - if (TT.isOSDarwin() && TT.getOSMajorVersion() != 0) { - unsigned Major, Minor, Update; - MCVersionMinType VersionType; - if (TT.isWatchOS()) { - VersionType = MCVM_WatchOSVersionMin; - TT.getWatchOSVersion(Major, Minor, Update); - } else if (TT.isTvOS()) { - VersionType = MCVM_TvOSVersionMin; - TT.getiOSVersion(Major, Minor, Update); - } else if (TT.isMacOSX()) { - VersionType = MCVM_OSXVersionMin; - if (!TT.getMacOSXVersion(Major, Minor, Update)) - Major = 0; - } else { - VersionType = MCVM_IOSVersionMin; - TT.getiOSVersion(Major, Minor, Update); - } - if (Major != 0) - OutStreamer->EmitVersionMin(VersionType, Major, Minor, Update); - } + const Triple &Target = TM.getTargetTriple(); + OutStreamer->EmitVersionForTarget(Target); // Allow the target to emit any magic that it wants at the start of the file. EmitStartOfAsmFile(M); @@ -272,7 +264,8 @@ bool AsmPrinter::doInitialization(Module &M) { // don't, this at least helps the user find where a global came from. if (MAI->hasSingleParameterDotFile()) { // .file "foo.c" - OutStreamer->EmitFileDirective(M.getSourceFileName()); + OutStreamer->EmitFileDirective( + llvm::sys::path::filename(M.getSourceFileName())); } GCModuleInfo *MI = getAnalysisIfAvailable<GCModuleInfo>(); @@ -628,35 +621,35 @@ void AsmPrinter::EmitDebugThreadLocal(const MCExpr *Value, /// EmitFunctionHeader - This method emits the header for the current /// function. void AsmPrinter::EmitFunctionHeader() { - const Function *F = MF->getFunction(); + const Function &F = MF->getFunction(); if (isVerbose()) OutStreamer->GetCommentOS() << "-- Begin function " - << GlobalValue::dropLLVMManglingEscape(F->getName()) << '\n'; + << GlobalValue::dropLLVMManglingEscape(F.getName()) << '\n'; // Print out constants referenced by the function EmitConstantPool(); // Print the 'header' of function. - OutStreamer->SwitchSection(getObjFileLowering().SectionForGlobal(F, TM)); - EmitVisibility(CurrentFnSym, F->getVisibility()); + OutStreamer->SwitchSection(getObjFileLowering().SectionForGlobal(&F, TM)); + EmitVisibility(CurrentFnSym, F.getVisibility()); - EmitLinkage(F, CurrentFnSym); + EmitLinkage(&F, CurrentFnSym); if (MAI->hasFunctionAlignment()) - EmitAlignment(MF->getAlignment(), F); + EmitAlignment(MF->getAlignment(), &F); if (MAI->hasDotTypeDotSizeDirective()) OutStreamer->EmitSymbolAttribute(CurrentFnSym, MCSA_ELF_TypeFunction); if (isVerbose()) { - F->printAsOperand(OutStreamer->GetCommentOS(), - /*PrintType=*/false, F->getParent()); + F.printAsOperand(OutStreamer->GetCommentOS(), + /*PrintType=*/false, F.getParent()); OutStreamer->GetCommentOS() << '\n'; } // Emit the prefix data. - if (F->hasPrefixData()) { + if (F.hasPrefixData()) { if (MAI->hasSubsectionsViaSymbols()) { // Preserving prefix data on platforms which use subsections-via-symbols // is a bit tricky. Here we introduce a symbol for the prefix data @@ -665,12 +658,12 @@ void AsmPrinter::EmitFunctionHeader() { MCSymbol *PrefixSym = OutContext.createLinkerPrivateTempSymbol(); OutStreamer->EmitLabel(PrefixSym); - EmitGlobalConstant(F->getParent()->getDataLayout(), F->getPrefixData()); + EmitGlobalConstant(F.getParent()->getDataLayout(), F.getPrefixData()); // Emit an .alt_entry directive for the actual function symbol. OutStreamer->EmitSymbolAttribute(CurrentFnSym, MCSA_AltEntry); } else { - EmitGlobalConstant(F->getParent()->getDataLayout(), F->getPrefixData()); + EmitGlobalConstant(F.getParent()->getDataLayout(), F.getPrefixData()); } } @@ -682,7 +675,7 @@ void AsmPrinter::EmitFunctionHeader() { // references to the dangling symbols. Emit them at the start of the function // so that we don't get references to undefined symbols. std::vector<MCSymbol*> DeadBlockSyms; - MMI->takeDeletedSymbolsForFunction(F, DeadBlockSyms); + MMI->takeDeletedSymbolsForFunction(&F, DeadBlockSyms); for (unsigned i = 0, e = DeadBlockSyms.size(); i != e; ++i) { OutStreamer->AddComment("Address taken block that was later removed"); OutStreamer->EmitLabel(DeadBlockSyms[i]); @@ -707,8 +700,8 @@ void AsmPrinter::EmitFunctionHeader() { } // Emit the prologue data. - if (F->hasPrologueData()) - EmitGlobalConstant(F->getParent()->getDataLayout(), F->getPrologueData()); + if (F.hasPrologueData()) + EmitGlobalConstant(F.getParent()->getDataLayout(), F.getPrologueData()); } /// EmitFunctionEntryLabel - Emit the label that is the entrypoint for the @@ -729,9 +722,11 @@ void AsmPrinter::EmitFunctionEntryLabel() { } /// emitComments - Pretty-print comments for instructions. -static void emitComments(const MachineInstr &MI, raw_ostream &CommentOS, +/// It returns true iff the sched comment was emitted. +/// Otherwise it returns false. +static bool emitComments(const MachineInstr &MI, raw_ostream &CommentOS, AsmPrinter *AP) { - const MachineFunction *MF = MI.getParent()->getParent(); + const MachineFunction *MF = MI.getMF(); const TargetInstrInfo *TII = MF->getSubtarget().getInstrInfo(); // Check for spills and reloads @@ -773,12 +768,16 @@ static void emitComments(const MachineInstr &MI, raw_ostream &CommentOS, CommentOS << " Reload Reuse"; } - if (Commented && AP->EnablePrintSchedInfo) - // If any comment was added above and we need sched info comment then - // add this new comment just after the above comment w/o "\n" between them. - CommentOS << " " << MF->getSubtarget().getSchedInfoStr(MI) << "\n"; - else if (Commented) + if (Commented) { + if (AP->EnablePrintSchedInfo) { + // If any comment was added above and we need sched info comment then add + // this new comment just after the above comment w/o "\n" between them. + CommentOS << " " << MF->getSubtarget().getSchedInfoStr(MI) << "\n"; + return true; + } CommentOS << "\n"; + } + return false; } /// emitImplicitDef - This method emits the specified machine instruction @@ -789,7 +788,7 @@ void AsmPrinter::emitImplicitDef(const MachineInstr *MI) const { SmallString<128> Str; raw_svector_ostream OS(Str); OS << "implicit-def: " - << PrintReg(RegNo, MF->getSubtarget().getRegisterInfo()); + << printReg(RegNo, MF->getSubtarget().getRegisterInfo()); OutStreamer->AddComment(OS.str()); OutStreamer->AddBlankLine(); @@ -802,10 +801,8 @@ static void emitKill(const MachineInstr *MI, AsmPrinter &AP) { for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { const MachineOperand &Op = MI->getOperand(i); assert(Op.isReg() && "KILL instruction must have only register operands"); - OS << ' ' - << PrintReg(Op.getReg(), - AP.MF->getSubtarget().getRegisterInfo()) - << (Op.isDef() ? "<def>" : "<kill>"); + OS << ' ' << (Op.isDef() ? "def " : "killed ") + << printReg(Op.getReg(), AP.MF->getSubtarget().getRegisterInfo()); } AP.OutStreamer->AddComment(OS.str()); AP.OutStreamer->AddBlankLine(); @@ -890,7 +887,7 @@ static bool emitDebugValueComment(const MachineInstr *MI, AsmPrinter &AP) { } if (MemLoc) OS << '['; - OS << PrintReg(Reg, AP.MF->getSubtarget().getRegisterInfo()); + OS << printReg(Reg, AP.MF->getSubtarget().getRegisterInfo()); } if (MemLoc) @@ -901,9 +898,9 @@ static bool emitDebugValueComment(const MachineInstr *MI, AsmPrinter &AP) { return true; } -AsmPrinter::CFIMoveType AsmPrinter::needsCFIMoves() { +AsmPrinter::CFIMoveType AsmPrinter::needsCFIMoves() const { if (MAI->getExceptionHandlingType() == ExceptionHandling::DwarfCFI && - MF->getFunction()->needsUnwindTableEntry()) + MF->getFunction().needsUnwindTableEntry()) return CFI_M_EH; if (MMI->hasDebugInfo()) @@ -913,7 +910,7 @@ AsmPrinter::CFIMoveType AsmPrinter::needsCFIMoves() { } bool AsmPrinter::needsSEHMoves() { - return MAI->usesWindowsCFI() && MF->getFunction()->needsUnwindTableEntry(); + return MAI->usesWindowsCFI() && MF->getFunction().needsUnwindTableEntry(); } void AsmPrinter::emitCFIInstruction(const MachineInstr &MI) { @@ -951,6 +948,31 @@ void AsmPrinter::emitFrameAlloc(const MachineInstr &MI) { MCConstantExpr::create(FrameOffset, OutContext)); } +void AsmPrinter::emitStackSizeSection(const MachineFunction &MF) { + if (!MF.getTarget().Options.EmitStackSizeSection) + return; + + MCSection *StackSizeSection = getObjFileLowering().getStackSizesSection(); + if (!StackSizeSection) + return; + + const MachineFrameInfo &FrameInfo = MF.getFrameInfo(); + // Don't emit functions with dynamic stack allocations. + if (FrameInfo.hasVarSizedObjects()) + return; + + OutStreamer->PushSection(); + OutStreamer->SwitchSection(StackSizeSection); + + const MCSymbol *FunctionSymbol = getSymbol(&MF.getFunction()); + uint64_t StackSize = FrameInfo.getStackSize(); + OutStreamer->EmitValue(MCSymbolRefExpr::create(FunctionSymbol, OutContext), + /* size = */ 8); + OutStreamer->EmitULEB128IntValue(StackSize); + + OutStreamer->PopSection(); +} + static bool needFuncLabelsForEHOrDebugInfo(const MachineFunction &MF, MachineModuleInfo *MMI) { if (!MF.getLandingPads().empty() || MF.hasEHFunclets() || MMI->hasDebugInfo()) @@ -958,10 +980,10 @@ static bool needFuncLabelsForEHOrDebugInfo(const MachineFunction &MF, // We might emit an EH table that uses function begin and end labels even if // we don't have any landingpads. - if (!MF.getFunction()->hasPersonalityFn()) + if (!MF.getFunction().hasPersonalityFn()) return false; return !isNoOpWithoutInvoke( - classifyEHPersonality(MF.getFunction()->getPersonalityFn())); + classifyEHPersonality(MF.getFunction().getPersonalityFn())); } /// EmitFunctionBody - This method emits the body and trailer for a @@ -981,7 +1003,6 @@ void AsmPrinter::EmitFunctionBody() { // Print a label for the basic block. EmitBasicBlockStart(MBB); for (auto &MI : MBB) { - // Print the assembly for the instruction. if (!MI.isPosition() && !MI.isImplicitDef() && !MI.isKill() && !MI.isDebugValue()) { @@ -998,18 +1019,18 @@ void AsmPrinter::EmitFunctionBody() { } } - if (isVerbose()) - emitComments(MI, OutStreamer->GetCommentOS(), this); + if (isVerbose() && emitComments(MI, OutStreamer->GetCommentOS(), this)) { + MachineInstr *MIP = const_cast<MachineInstr *>(&MI); + MIP->setAsmPrinterFlag(MachineInstr::NoSchedComment); + } switch (MI.getOpcode()) { case TargetOpcode::CFI_INSTRUCTION: emitCFIInstruction(MI); break; - case TargetOpcode::LOCAL_ESCAPE: emitFrameAlloc(MI); break; - case TargetOpcode::EH_LABEL: case TargetOpcode::GC_LABEL: OutStreamer->EmitLabel(MI.getOperand(0).getMCSymbol()); @@ -1049,7 +1070,7 @@ void AsmPrinter::EmitFunctionBody() { EmittedInsts += NumInstsInFunction; MachineOptimizationRemarkAnalysis R(DEBUG_TYPE, "InstructionCount", - MF->getFunction()->getSubprogram(), + MF->getFunction().getSubprogram(), &MF->front()); R << ore::NV("NumInstructions", NumInstsInFunction) << " instructions in function"; @@ -1077,8 +1098,8 @@ void AsmPrinter::EmitFunctionBody() { } } - const Function *F = MF->getFunction(); - for (const auto &BB : *F) { + const Function &F = MF->getFunction(); + for (const auto &BB : F) { if (!BB.hasAddressTaken()) continue; MCSymbol *Sym = GetBlockAddressSymbol(&BB); @@ -1125,6 +1146,9 @@ void AsmPrinter::EmitFunctionBody() { HI.Handler->endFunction(MF); } + // Emit section containing stack size metadata. + emitStackSizeSection(*MF); + if (isVerbose()) OutStreamer->GetCommentOS() << "-- End function\n"; @@ -1380,6 +1404,16 @@ bool AsmPrinter::doFinalization(Module &M) { PtrSize); } + // Emit .note.GNU-split-stack and .note.GNU-no-split-stack sections if + // split-stack is used. + if (TM.getTargetTriple().isOSBinFormatELF() && MMI->hasSplitStack()) { + OutStreamer->SwitchSection( + OutContext.getELFSection(".note.GNU-split-stack", ELF::SHT_PROGBITS, 0)); + if (MMI->hasNosplitStack()) + OutStreamer->SwitchSection( + OutContext.getELFSection(".note.GNU-no-split-stack", ELF::SHT_PROGBITS, 0)); + } + // If we don't have any trampolines, then we don't require stack memory // to be executable. Some targets have a directive to declare this. Function *InitTrampolineIntrinsic = M.getFunction("llvm.init.trampoline"); @@ -1408,7 +1442,7 @@ MCSymbol *AsmPrinter::getCurExceptionSym() { void AsmPrinter::SetupMachineFunction(MachineFunction &MF) { this->MF = &MF; // Get the function symbol. - CurrentFnSym = getSymbol(MF.getFunction()); + CurrentFnSym = getSymbol(&MF.getFunction()); CurrentFnSymForSize = CurrentFnSym; CurrentFnBegin = nullptr; CurExceptionSym = nullptr; @@ -1420,8 +1454,7 @@ void AsmPrinter::SetupMachineFunction(MachineFunction &MF) { } ORE = &getAnalysis<MachineOptimizationRemarkEmitterPass>().getORE(); - if (isVerbose()) - LI = &getAnalysis<MachineLoopInfo>(); + LI = &getAnalysis<MachineLoopInfo>(); const TargetSubtargetInfo &STI = MF.getSubtarget(); EnablePrintSchedInfo = PrintSchedule.getNumOccurrences() @@ -1446,7 +1479,6 @@ namespace { /// representations of the constants in the constant pool MCP. This is /// used to print out constants which have been "spilled to memory" by /// the code generator. -/// void AsmPrinter::EmitConstantPool() { const MachineConstantPool *MCP = MF->getConstantPool(); const std::vector<MachineConstantPoolEntry> &CP = MCP->getConstants(); @@ -1526,7 +1558,6 @@ void AsmPrinter::EmitConstantPool() { /// EmitJumpTableInfo - Print assembly representations of the jump tables used /// by the current function to the current output stream. -/// void AsmPrinter::EmitJumpTableInfo() { const DataLayout &DL = MF->getDataLayout(); const MachineJumpTableInfo *MJTI = MF->getJumpTableInfo(); @@ -1537,14 +1568,14 @@ void AsmPrinter::EmitJumpTableInfo() { // Pick the directive to use to print the jump table entries, and switch to // the appropriate section. - const Function *F = MF->getFunction(); + const Function &F = MF->getFunction(); const TargetLoweringObjectFile &TLOF = getObjFileLowering(); bool JTInDiffSection = !TLOF.shouldPutJumpTableInFunctionSection( MJTI->getEntryKind() == MachineJumpTableInfo::EK_LabelDifference32, - *F); + F); if (JTInDiffSection) { // Drop it in the readonly section. - MCSection *ReadOnlySection = TLOF.getSectionForJumpTable(*F, TM); + MCSection *ReadOnlySection = TLOF.getSectionForJumpTable(F, TM); OutStreamer->SwitchSection(ReadOnlySection); } @@ -1723,7 +1754,7 @@ struct Structor { Structor() = default; }; -} // end anonymous namespace +} // end anonymous namespace /// EmitXXStructorList - Emit the ctor or dtor list taking into account the init /// priority. @@ -1818,13 +1849,11 @@ void AsmPrinter::EmitInt8(int Value) const { } /// EmitInt16 - Emit a short directive and value. -/// void AsmPrinter::EmitInt16(int Value) const { OutStreamer->EmitIntValue(Value, 2); } /// EmitInt32 - Emit a long directive and value. -/// void AsmPrinter::EmitInt32(int Value) const { OutStreamer->EmitIntValue(Value, 4); } @@ -1866,7 +1895,6 @@ void AsmPrinter::EmitLabelPlusOffset(const MCSymbol *Label, uint64_t Offset, // byte alignment. If a global value is specified, and if that global has // an explicit alignment requested, it will override the alignment request // if required for correctness. -// void AsmPrinter::EmitAlignment(unsigned NumBits, const GlobalObject *GV) const { if (GV) NumBits = getGVAlignmentLog2(GV, GV->getParent()->getDataLayout(), NumBits); @@ -1921,7 +1949,7 @@ const MCExpr *AsmPrinter::lowerConstant(const Constant *CV) { raw_string_ostream OS(S); OS << "Unsupported expression in static initializer: "; CE->printAsOperand(OS, /*PrintType=*/false, - !MF ? nullptr : MF->getFunction()->getParent()); + !MF ? nullptr : MF->getFunction().getParent()); report_fatal_error(OS.str()); } case Instruction::GetElementPtr: { @@ -2317,7 +2345,6 @@ static void handleIndirectSymViaGOTPCRel(AsmPrinter &AP, const MCExpr **ME, // // cstexpr := <gotequiv> - <foo> + gotpcrelcst, where // gotpcrelcst := <offset from @foo base> + <cst> - // MCValue MV; if (!(*ME)->evaluateAsRelocatable(MV, nullptr, nullptr) || MV.isAbsolute()) return; @@ -2348,7 +2375,6 @@ static void handleIndirectSymViaGOTPCRel(AsmPrinter &AP, const MCExpr **ME, // If gotpcrelcst is positive it means that we can safely fold the pc rel // displacement into the GOTPCREL. We can also can have an extra offset <cst> // if the target knows how to encode it. - // int64_t GOTPCRelCst = Offset + MV.getConstant(); if (GOTPCRelCst < 0) return; @@ -2370,7 +2396,6 @@ static void handleIndirectSymViaGOTPCRel(AsmPrinter &AP, const MCExpr **ME, // .long 42 // foo: // .long bar@GOTPCREL+<gotpcrelcst> - // AsmPrinter::GOTEquivUsePair Result = AP.GlobalGOTEquivs[GOTEquivSym]; const GlobalVariable *GV = Result.first; int NumUses = (int)Result.second; @@ -2550,7 +2575,6 @@ static void PrintParentLoopComment(raw_ostream &OS, const MachineLoop *Loop, << " Depth=" << Loop->getLoopDepth() << '\n'; } - /// PrintChildLoopComment - Print comments about child loops within /// the loop for this basic block, with nesting. static void PrintChildLoopComment(raw_ostream &OS, const MachineLoop *Loop, @@ -2603,6 +2627,23 @@ static void emitBasicBlockLoopComments(const MachineBasicBlock &MBB, PrintChildLoopComment(OS, Loop, AP.getFunctionNumber()); } +void AsmPrinter::setupCodePaddingContext(const MachineBasicBlock &MBB, + MCCodePaddingContext &Context) const { + assert(MF != nullptr && "Machine function must be valid"); + assert(LI != nullptr && "Loop info must be valid"); + Context.IsPaddingActive = !MF->hasInlineAsm() && + !MF->getFunction().optForSize() && + TM.getOptLevel() != CodeGenOpt::None; + const MachineLoop *CurrentLoop = LI->getLoopFor(&MBB); + Context.IsBasicBlockInsideInnermostLoop = + CurrentLoop != nullptr && CurrentLoop->getSubLoops().empty(); + Context.IsBasicBlockReachableViaFallthrough = + std::find(MBB.pred_begin(), MBB.pred_end(), MBB.getPrevNode()) != + MBB.pred_end(); + Context.IsBasicBlockReachableViaBranch = + MBB.pred_size() > 0 && !isBlockOnlyReachableByFallthrough(&MBB); +} + /// EmitBasicBlockStart - This method prints the label for the specified /// MachineBasicBlock, an alignment (if present) and a comment describing /// it if appropriate. @@ -2618,6 +2659,9 @@ void AsmPrinter::EmitBasicBlockStart(const MachineBasicBlock &MBB) const { // Emit an alignment directive for this block, if needed. if (unsigned Align = MBB.getAlignment()) EmitAlignment(Align); + MCCodePaddingContext Context; + setupCodePaddingContext(MBB, Context); + OutStreamer->EmitCodePaddingBasicBlockStart(Context); // 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 @@ -2652,13 +2696,20 @@ void AsmPrinter::EmitBasicBlockStart(const MachineBasicBlock &MBB) const { (isBlockOnlyReachableByFallthrough(&MBB) && !MBB.isEHFuncletEntry())) { if (isVerbose()) { // NOTE: Want this comment at start of line, don't emit with AddComment. - OutStreamer->emitRawComment(" BB#" + Twine(MBB.getNumber()) + ":", false); + OutStreamer->emitRawComment(" %bb." + Twine(MBB.getNumber()) + ":", + false); } } else { OutStreamer->EmitLabel(MBB.getSymbol()); } } +void AsmPrinter::EmitBasicBlockEnd(const MachineBasicBlock &MBB) { + MCCodePaddingContext Context; + setupCodePaddingContext(MBB, Context); + OutStreamer->EmitCodePaddingBasicBlockEnd(Context); +} + void AsmPrinter::EmitVisibility(MCSymbol *Sym, unsigned Visibility, bool IsDefinition) const { MCSymbolAttr Attr = MCSA_Invalid; @@ -2765,10 +2816,13 @@ void AsmPrinter::XRayFunctionEntry::emit(int Bytes, MCStreamer *Out, Out->EmitSymbolValue(Sled, Bytes); Out->EmitSymbolValue(CurrentFnSym, Bytes); auto Kind8 = static_cast<uint8_t>(Kind); - Out->EmitBytes(StringRef(reinterpret_cast<const char *>(&Kind8), 1)); - Out->EmitBytes( + Out->EmitBinaryData(StringRef(reinterpret_cast<const char *>(&Kind8), 1)); + Out->EmitBinaryData( StringRef(reinterpret_cast<const char *>(&AlwaysInstrument), 1)); - Out->EmitZeros(2 * Bytes - 2); // Pad the previous two entries + Out->EmitBinaryData(StringRef(reinterpret_cast<const char *>(&Version), 1)); + auto Padding = (4 * Bytes) - ((2 * Bytes) + 3); + assert(Padding >= 0 && "Instrumentation map entry > 4 * Word Size"); + Out->EmitZeros(Padding); } void AsmPrinter::emitXRayTable() { @@ -2776,23 +2830,26 @@ void AsmPrinter::emitXRayTable() { return; auto PrevSection = OutStreamer->getCurrentSectionOnly(); - auto Fn = MF->getFunction(); + const Function &F = MF->getFunction(); MCSection *InstMap = nullptr; MCSection *FnSledIndex = nullptr; if (MF->getSubtarget().getTargetTriple().isOSBinFormatELF()) { - if (Fn->hasComdat()) { - InstMap = OutContext.getELFSection("xray_instr_map", ELF::SHT_PROGBITS, - ELF::SHF_ALLOC | ELF::SHF_GROUP, 0, - Fn->getComdat()->getName()); - FnSledIndex = OutContext.getELFSection("xray_fn_idx", ELF::SHT_PROGBITS, - ELF::SHF_ALLOC | ELF::SHF_GROUP, 0, - Fn->getComdat()->getName()); - } else { - InstMap = OutContext.getELFSection("xray_instr_map", ELF::SHT_PROGBITS, - ELF::SHF_ALLOC); - FnSledIndex = OutContext.getELFSection("xray_fn_idx", ELF::SHT_PROGBITS, - ELF::SHF_ALLOC); + auto Associated = dyn_cast<MCSymbolELF>(CurrentFnSym); + assert(Associated != nullptr); + auto Flags = ELF::SHF_WRITE | ELF::SHF_ALLOC | ELF::SHF_LINK_ORDER; + std::string GroupName; + if (F.hasComdat()) { + Flags |= ELF::SHF_GROUP; + GroupName = F.getComdat()->getName(); } + + auto UniqueID = ++XRayFnUniqueID; + InstMap = + OutContext.getELFSection("xray_instr_map", ELF::SHT_PROGBITS, Flags, 0, + GroupName, UniqueID, Associated); + FnSledIndex = + OutContext.getELFSection("xray_fn_idx", ELF::SHT_PROGBITS, Flags, 0, + GroupName, UniqueID, Associated); } else if (MF->getSubtarget().getTargetTriple().isOSBinFormatMachO()) { InstMap = OutContext.getMachOSection("__DATA", "xray_instr_map", 0, SectionKind::getReadOnlyWithRel()); @@ -2802,15 +2859,7 @@ void AsmPrinter::emitXRayTable() { llvm_unreachable("Unsupported target"); } - // Before we switch over, we force a reference to a label inside the - // xray_fn_idx sections. This makes sure that the xray_fn_idx section is kept - // live by the linker if the function is not garbage-collected. Since this - // function is always called just before the function's end, we assume that - // this is happening after the last return instruction. auto WordSizeBytes = MAI->getCodePointerSize(); - MCSymbol *IdxRef = OutContext.createTempSymbol("xray_fn_idx_synth_", true); - OutStreamer->EmitCodeAlignment(16); - OutStreamer->EmitSymbolValue(IdxRef, WordSizeBytes, false); // Now we switch to the instrumentation map section. Because this is done // per-function, we are able to create an index entry that will represent the @@ -2829,24 +2878,23 @@ void AsmPrinter::emitXRayTable() { // pointers. This should work for both 32-bit and 64-bit platforms. OutStreamer->SwitchSection(FnSledIndex); OutStreamer->EmitCodeAlignment(2 * WordSizeBytes); - OutStreamer->EmitLabel(IdxRef); - OutStreamer->EmitSymbolValue(SledsStart, WordSizeBytes); - OutStreamer->EmitSymbolValue(SledsEnd, WordSizeBytes); + OutStreamer->EmitSymbolValue(SledsStart, WordSizeBytes, false); + OutStreamer->EmitSymbolValue(SledsEnd, WordSizeBytes, false); OutStreamer->SwitchSection(PrevSection); Sleds.clear(); } void AsmPrinter::recordSled(MCSymbol *Sled, const MachineInstr &MI, - SledKind Kind) { - auto Fn = MI.getParent()->getParent()->getFunction(); - auto Attr = Fn->getFnAttribute("function-instrument"); - bool LogArgs = Fn->hasFnAttribute("xray-log-args"); + SledKind Kind, uint8_t Version) { + const Function &F = MI.getMF()->getFunction(); + auto Attr = F.getFnAttribute("function-instrument"); + bool LogArgs = F.hasFnAttribute("xray-log-args"); bool AlwaysInstrument = Attr.isStringAttribute() && Attr.getValueAsString() == "xray-always"; if (Kind == SledKind::FUNCTION_ENTER && LogArgs) Kind = SledKind::LOG_ARGS_ENTER; - Sleds.emplace_back( - XRayFunctionEntry{ Sled, CurrentFnSym, Kind, AlwaysInstrument, Fn }); + Sleds.emplace_back(XRayFunctionEntry{Sled, CurrentFnSym, Kind, + AlwaysInstrument, &F, Version}); } uint16_t AsmPrinter::getDwarfVersion() const { |