diff options
Diffstat (limited to 'lib/CodeGen/AsmPrinter/AsmPrinter.cpp')
-rw-r--r-- | lib/CodeGen/AsmPrinter/AsmPrinter.cpp | 279 |
1 files changed, 171 insertions, 108 deletions
diff --git a/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/lib/CodeGen/AsmPrinter/AsmPrinter.cpp index 7070451e3330..54f6cc2d5571 100644 --- a/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ b/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -1,9 +1,8 @@ //===- AsmPrinter.cpp - Common AsmPrinter code ----------------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 // //===----------------------------------------------------------------------===// // @@ -35,7 +34,6 @@ #include "llvm/BinaryFormat/COFF.h" #include "llvm/BinaryFormat/Dwarf.h" #include "llvm/BinaryFormat/ELF.h" -#include "llvm/CodeGen/AsmPrinterHandler.h" #include "llvm/CodeGen/GCMetadata.h" #include "llvm/CodeGen/GCMetadataPrinter.h" #include "llvm/CodeGen/GCStrategy.h" @@ -60,7 +58,6 @@ #include "llvm/CodeGen/TargetLowering.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" @@ -80,6 +77,7 @@ #include "llvm/IR/Metadata.h" #include "llvm/IR/Module.h" #include "llvm/IR/Operator.h" +#include "llvm/IR/RemarkStreamer.h" #include "llvm/IR/Type.h" #include "llvm/IR/Value.h" #include "llvm/MC/MCAsmInfo.h" @@ -101,6 +99,9 @@ #include "llvm/MC/MCValue.h" #include "llvm/MC/SectionKind.h" #include "llvm/Pass.h" +#include "llvm/Remarks/Remark.h" +#include "llvm/Remarks/RemarkFormat.h" +#include "llvm/Remarks/RemarkStringTable.h" #include "llvm/Support/Casting.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Compiler.h" @@ -143,9 +144,10 @@ static const char *const CodeViewLineTablesGroupDescription = STATISTIC(EmittedInsts, "Number of machine instrs printed"); -static cl::opt<bool> - PrintSchedule("print-schedule", cl::Hidden, cl::init(false), - cl::desc("Print 'sched: [latency:throughput]' in .s output")); +static cl::opt<bool> EnableRemarksSection( + "remarks-section", + cl::desc("Emit a section containing remark diagnostics metadata"), + cl::init(false)); char AsmPrinter::ID = 0; @@ -232,6 +234,12 @@ void AsmPrinter::EmitToStreamer(MCStreamer &S, const MCInst &Inst) { S.EmitInstruction(Inst, getSubtargetInfo()); } +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); +} + /// getCurrentSection() - Return the current section we are emitting to. const MCSection *AsmPrinter::getCurrentSection() const { return OutStreamer->getCurrentSectionOnly(); @@ -252,6 +260,9 @@ bool AsmPrinter::doInitialization(Module &M) { const_cast<TargetLoweringObjectFile&>(getObjFileLowering()) .Initialize(OutContext, TM); + const_cast<TargetLoweringObjectFile &>(getObjFileLowering()) + .getModuleMetadata(M); + OutStreamer->InitSections(false); // Emit the version-min deployment target directive if needed. @@ -300,16 +311,17 @@ bool AsmPrinter::doInitialization(Module &M) { if (MAI->doesSupportDebugInformation()) { bool EmitCodeView = MMI->getModule()->getCodeViewFlag(); if (EmitCodeView && TM.getTargetTriple().isOSWindows()) { - Handlers.push_back(HandlerInfo(new CodeViewDebug(this), - DbgTimerName, DbgTimerDescription, - CodeViewLineTablesGroupName, - CodeViewLineTablesGroupDescription)); + Handlers.emplace_back(llvm::make_unique<CodeViewDebug>(this), + DbgTimerName, DbgTimerDescription, + CodeViewLineTablesGroupName, + CodeViewLineTablesGroupDescription); } if (!EmitCodeView || MMI->getModule()->getDwarfVersion()) { DD = new DwarfDebug(this, &M); DD->beginModule(); - Handlers.push_back(HandlerInfo(DD, DbgTimerName, DbgTimerDescription, - DWARFGroupName, DWARFGroupDescription)); + Handlers.emplace_back(std::unique_ptr<DwarfDebug>(DD), DbgTimerName, + DbgTimerDescription, DWARFGroupName, + DWARFGroupDescription); } } @@ -362,14 +374,15 @@ bool AsmPrinter::doInitialization(Module &M) { break; } if (ES) - Handlers.push_back(HandlerInfo(ES, EHTimerName, EHTimerDescription, - DWARFGroupName, DWARFGroupDescription)); + Handlers.emplace_back(std::unique_ptr<EHStreamer>(ES), EHTimerName, + EHTimerDescription, DWARFGroupName, + DWARFGroupDescription); if (mdconst::extract_or_null<ConstantInt>( MMI->getModule()->getModuleFlag("cfguardtable"))) - Handlers.push_back(HandlerInfo(new WinCFGuard(this), CFGuardName, - CFGuardDescription, DWARFGroupName, - DWARFGroupDescription)); + Handlers.emplace_back(llvm::make_unique<WinCFGuard>(this), CFGuardName, + CFGuardDescription, DWARFGroupName, + DWARFGroupDescription); return false; } @@ -483,7 +496,7 @@ void AsmPrinter::EmitGlobalVariable(const GlobalVariable *GV) { SectionKind GVKind = TargetLoweringObjectFile::getKindForGlobal(GV, TM); const DataLayout &DL = GV->getParent()->getDataLayout(); - uint64_t Size = DL.getTypeAllocSize(GV->getType()->getElementType()); + uint64_t Size = DL.getTypeAllocSize(GV->getValueType()); // If the alignment is specified, we *must* obey it. Overaligning a global // with a specified alignment is a prompt way to break globals emitted to @@ -658,6 +671,9 @@ void AsmPrinter::EmitFunctionHeader() { if (MAI->hasDotTypeDotSizeDirective()) OutStreamer->EmitSymbolAttribute(CurrentFnSym, MCSA_ELF_TypeFunction); + if (F.hasFnAttribute(Attribute::Cold)) + OutStreamer->EmitSymbolAttribute(CurrentFnSym, MCSA_Cold); + if (isVerbose()) { F.printAsOperand(OutStreamer->GetCommentOS(), /*PrintType=*/false, F.getParent()); @@ -738,74 +754,30 @@ void AsmPrinter::EmitFunctionEntryLabel() { } /// emitComments - Pretty-print comments for instructions. -/// It returns true iff the sched comment was emitted. -/// Otherwise it returns false. -static bool emitComments(const MachineInstr &MI, raw_ostream &CommentOS, - AsmPrinter *AP) { +static void emitComments(const MachineInstr &MI, raw_ostream &CommentOS) { const MachineFunction *MF = MI.getMF(); const TargetInstrInfo *TII = MF->getSubtarget().getInstrInfo(); // Check for spills and reloads - int FI; - - const MachineFrameInfo &MFI = MF->getFrameInfo(); - bool Commented = false; - - auto getSize = - [&MFI](const SmallVectorImpl<const MachineMemOperand *> &Accesses) { - unsigned Size = 0; - for (auto A : Accesses) - if (MFI.isSpillSlotObjectIndex( - cast<FixedStackPseudoSourceValue>(A->getPseudoValue()) - ->getFrameIndex())) - Size += A->getSize(); - return Size; - }; // We assume a single instruction only has a spill or reload, not // both. - const MachineMemOperand *MMO; - SmallVector<const MachineMemOperand *, 2> Accesses; - if (TII->isLoadFromStackSlotPostFE(MI, FI)) { - if (MFI.isSpillSlotObjectIndex(FI)) { - MMO = *MI.memoperands_begin(); - CommentOS << MMO->getSize() << "-byte Reload"; - Commented = true; - } - } else if (TII->hasLoadFromStackSlot(MI, Accesses)) { - if (auto Size = getSize(Accesses)) { - CommentOS << Size << "-byte Folded Reload"; - Commented = true; - } - } else if (TII->isStoreToStackSlotPostFE(MI, FI)) { - if (MFI.isSpillSlotObjectIndex(FI)) { - MMO = *MI.memoperands_begin(); - CommentOS << MMO->getSize() << "-byte Spill"; - Commented = true; - } - } else if (TII->hasStoreToStackSlot(MI, Accesses)) { - if (auto Size = getSize(Accesses)) { - CommentOS << Size << "-byte Folded Spill"; - Commented = true; - } + Optional<unsigned> Size; + if ((Size = MI.getRestoreSize(TII))) { + CommentOS << *Size << "-byte Reload\n"; + } else if ((Size = MI.getFoldedRestoreSize(TII))) { + if (*Size) + 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"; } // Check for spill-induced copies - if (MI.getAsmPrinterFlag(MachineInstr::ReloadReuse)) { - Commented = true; - CommentOS << " Reload Reuse"; - } - - 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; + if (MI.getAsmPrinterFlag(MachineInstr::ReloadReuse)) + CommentOS << " Reload Reuse\n"; } /// emitImplicitDef - This method emits the specified machine instruction @@ -1093,10 +1065,8 @@ void AsmPrinter::EmitFunctionBody() { } } - if (isVerbose() && emitComments(MI, OutStreamer->GetCommentOS(), this)) { - MachineInstr *MIP = const_cast<MachineInstr *>(&MI); - MIP->setAsmPrinterFlag(MachineInstr::NoSchedComment); - } + if (isVerbose()) + emitComments(MI, OutStreamer->GetCommentOS()); switch (MI.getOpcode()) { case TargetOpcode::CFI_INSTRUCTION: @@ -1105,11 +1075,13 @@ void AsmPrinter::EmitFunctionBody() { case TargetOpcode::LOCAL_ESCAPE: emitFrameAlloc(MI); break; + case TargetOpcode::ANNOTATION_LABEL: case TargetOpcode::EH_LABEL: case TargetOpcode::GC_LABEL: OutStreamer->EmitLabel(MI.getOperand(0).getMCSymbol()); break; case TargetOpcode::INLINEASM: + case TargetOpcode::INLINEASM_BR: EmitInlineAsm(&MI); break; case TargetOpcode::DBG_VALUE: @@ -1266,7 +1238,7 @@ static bool isGOTEquivalentCandidate(const GlobalVariable *GV, // GlobalVariable or Function, i.e., as GlobalValue. if (!GV->hasGlobalUnnamedAddr() || !GV->hasInitializer() || !GV->isConstant() || !GV->isDiscardableIfUnused() || - !dyn_cast<GlobalValue>(GV->getOperand(0))) + !isa<GlobalValue>(GV->getOperand(0))) return false; // To be a got equivalent, at least one of its users need to be a constant @@ -1329,9 +1301,19 @@ void AsmPrinter::emitGlobalIndirectSymbol(Module &M, 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) + if (auto *CE = dyn_cast<ConstantExpr>(GIS.getIndirectSymbol())) + if (CE->getOpcode() == Instruction::BitCast) + IsFunction = + CE->getOperand(0)->getType()->getPointerElementType()->isFunctionTy(); + // Set the symbol type to function if the alias has a function type. // This affects codegen when the aliasee is not a function. - if (GIS.getType()->getPointerElementType()->isFunctionTy()) { + if (IsFunction) { OutStreamer->EmitSymbolAttribute(Name, MCSA_ELF_TypeFunction); if (isa<GlobalIFunc>(GIS)) OutStreamer->EmitSymbolAttribute(Name, MCSA_ELF_TypeIndFunction); @@ -1363,6 +1345,66 @@ void AsmPrinter::emitGlobalIndirectSymbol(Module &M, } } +void AsmPrinter::emitRemarksSection(Module &M) { + RemarkStreamer *RS = M.getContext().getRemarkStreamer(); + if (!RS) + return; + const remarks::Serializer &Serializer = RS->getSerializer(); + + // Switch to the right section: .remarks/__remarks. + MCSection *RemarksSection = + OutContext.getObjectFileInfo()->getRemarksSection(); + OutStreamer->SwitchSection(RemarksSection); + + // Emit the magic number. + OutStreamer->EmitBytes(remarks::Magic); + // Explicitly emit a '\0'. + OutStreamer->EmitIntValue(/*Value=*/0, /*Size=*/1); + + // Emit the version number: little-endian uint64_t. + // The version number is located at the offset 0x0 in the section. + std::array<char, 8> Version; + support::endian::write64le(Version.data(), remarks::Version); + OutStreamer->EmitBinaryData(StringRef(Version.data(), Version.size())); + + // Emit the string table in the section. + // Note: we need to use the streamer here to emit it in the section. We can't + // just use the serialize function with a raw_ostream because of the way + // MCStreamers work. + uint64_t StrTabSize = + Serializer.StrTab ? Serializer.StrTab->SerializedSize : 0; + // Emit the total size of the string table (the size itself excluded): + // little-endian uint64_t. + // The total size is located after the version number. + // Note: even if no string table is used, emit 0. + std::array<char, 8> StrTabSizeBuf; + support::endian::write64le(StrTabSizeBuf.data(), StrTabSize); + OutStreamer->EmitBinaryData( + StringRef(StrTabSizeBuf.data(), StrTabSizeBuf.size())); + + if (const Optional<remarks::StringTable> &StrTab = Serializer.StrTab) { + std::vector<StringRef> StrTabStrings = StrTab->serialize(); + // Emit a list of null-terminated strings. + // Note: the order is important here: the ID used in the remarks corresponds + // to the position of the string in the section. + for (StringRef Str : StrTabStrings) { + OutStreamer->EmitBytes(Str); + // Explicitly emit a '\0'. + OutStreamer->EmitIntValue(/*Value=*/0, /*Size=*/1); + } + } + + // Emit the null-terminated absolute path to the remark file. + // The path is located at the offset 0x4 in the section. + StringRef FilenameRef = RS->getFilename(); + SmallString<128> Filename = FilenameRef; + sys::fs::make_absolute(Filename); + assert(!Filename.empty() && "The filename can't be empty."); + OutStreamer->EmitBytes(Filename); + // Explicitly emit a '\0'. + OutStreamer->EmitIntValue(/*Value=*/0, /*Size=*/1); +} + bool AsmPrinter::doFinalization(Module &M) { // Set the MachineFunction to nullptr so that we can catch attempted // accesses to MF specific features at the module level and so that @@ -1394,6 +1436,12 @@ bool AsmPrinter::doFinalization(Module &M) { EmitVisibility(Name, V, false); } + // Emit the remarks section contents. + // FIXME: Figure out when is the safest time to emit this section. It should + // not come after debug info. + if (EnableRemarksSection) + emitRemarksSection(M); + const TargetLoweringObjectFile &TLOF = getObjFileLowering(); TLOF.emitModuleMetadata(*OutStreamer, M); @@ -1448,7 +1496,6 @@ bool AsmPrinter::doFinalization(Module &M) { NamedRegionTimer T(HI.TimerName, HI.TimerDescription, HI.TimerGroupName, HI.TimerGroupDescription, TimePassesIsEnabled); HI.Handler->endModule(); - delete HI.Handler; } Handlers.clear(); DD = nullptr; @@ -1592,6 +1639,24 @@ bool AsmPrinter::doFinalization(Module &M) { OutStreamer->EmitAddrsigSym(getSymbol(&GV)); } + // Emit symbol partition specifications (ELF only). + if (TM.getTargetTriple().isOSBinFormatELF()) { + unsigned UniqueID = 0; + for (const GlobalValue &GV : M.global_values()) { + if (!GV.hasPartition() || GV.isDeclarationForLinker() || + GV.getVisibility() != GlobalValue::DefaultVisibility) + continue; + + OutStreamer->SwitchSection(OutContext.getELFSection( + ".llvm_sympart", ELF::SHT_LLVM_SYMPART, 0, 0, "", ++UniqueID)); + OutStreamer->EmitBytes(GV.getPartition()); + OutStreamer->EmitZeros(1); + OutStreamer->EmitValue( + MCSymbolRefExpr::create(getSymbol(&GV), OutContext), + MAI->getCodePointerSize()); + } + } + // Allow the target to emit any magic that it wants at the end of the file, // after everything else has gone out. EmitEndOfAsmFile(M); @@ -1628,11 +1693,6 @@ void AsmPrinter::SetupMachineFunction(MachineFunction &MF) { } ORE = &getAnalysis<MachineOptimizationRemarkEmitterPass>().getORE(); - - const TargetSubtargetInfo &STI = MF.getSubtarget(); - EnablePrintSchedInfo = PrintSchedule.getNumOccurrences() - ? PrintSchedule - : STI.supportPrintSchedInfo(); } namespace { @@ -1905,8 +1965,7 @@ bool AsmPrinter::EmitSpecialLLVMGlobal(const GlobalVariable *GV) { } /// EmitLLVMUsedList - For targets that define a MAI::UsedDirective, mark each -/// global in the specified llvm.used list for which emitUsedDirectiveFor -/// is true, as being used with this directive. +/// global in the specified llvm.used list. void AsmPrinter::EmitLLVMUsedList(const ConstantArray *InitList) { // Should be an array of 'i8*'. for (unsigned i = 0, e = InitList->getNumOperands(); i != e; ++i) { @@ -1933,7 +1992,7 @@ struct Structor { /// priority. void AsmPrinter::EmitXXStructorList(const DataLayout &DL, const Constant *List, bool isCtor) { - // Should be an array of '{ int, void ()* }' structs. The first value is the + // Should be an array of '{ i32, void ()*, i8* }' structs. The first value is the // init priority. if (!isa<ConstantArray>(List)) return; @@ -1941,12 +2000,10 @@ void AsmPrinter::EmitXXStructorList(const DataLayout &DL, const Constant *List, const ConstantArray *InitList = dyn_cast<ConstantArray>(List); if (!InitList) return; // Not an array! StructType *ETy = dyn_cast<StructType>(InitList->getType()->getElementType()); - // FIXME: Only allow the 3-field form in LLVM 4.0. - if (!ETy || ETy->getNumElements() < 2 || ETy->getNumElements() > 3) - return; // Not an array of two or three elements! - if (!isa<IntegerType>(ETy->getTypeAtIndex(0U)) || - !isa<PointerType>(ETy->getTypeAtIndex(1U))) return; // Not (int, ptr). - if (ETy->getNumElements() == 3 && !isa<PointerType>(ETy->getTypeAtIndex(2U))) + if (!ETy || ETy->getNumElements() != 3 || + !isa<IntegerType>(ETy->getTypeAtIndex(0U)) || + !isa<PointerType>(ETy->getTypeAtIndex(1U)) || + !isa<PointerType>(ETy->getTypeAtIndex(2U))) return; // Not (int, ptr, ptr). // Gather the structors in a form that's convenient for sorting by priority. @@ -1962,16 +2019,16 @@ void AsmPrinter::EmitXXStructorList(const DataLayout &DL, const Constant *List, Structor &S = Structors.back(); S.Priority = Priority->getLimitedValue(65535); S.Func = CS->getOperand(1); - if (ETy->getNumElements() == 3 && !CS->getOperand(2)->isNullValue()) + if (!CS->getOperand(2)->isNullValue()) S.ComdatKey = dyn_cast<GlobalValue>(CS->getOperand(2)->stripPointerCasts()); } // Emit the function pointers in the target-specific order unsigned Align = Log2_32(DL.getPointerPrefAlignment()); - std::stable_sort(Structors.begin(), Structors.end(), - [](const Structor &L, - const Structor &R) { return L.Priority < R.Priority; }); + llvm::stable_sort(Structors, [](const Structor &L, const Structor &R) { + return L.Priority < R.Priority; + }); for (Structor &S : Structors) { const TargetLoweringObjectFile &Obj = getObjFileLowering(); const MCSymbol *KeySym = nullptr; @@ -2199,7 +2256,10 @@ const MCExpr *AsmPrinter::lowerConstant(const Constant *CV) { // We can emit the pointer value into this slot if the slot is an // integer slot equal to the size of the pointer. - if (DL.getTypeAllocSize(Ty) == DL.getTypeAllocSize(Op->getType())) + // + // 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())) return OpExpr; // Otherwise the pointer is smaller than the resultant integer, mask off @@ -2740,7 +2800,7 @@ MCSymbol *AsmPrinter::GetBlockAddressSymbol(const BasicBlock *BB) const { /// GetCPISymbol - Return the symbol for the specified constant pool entry. MCSymbol *AsmPrinter::GetCPISymbol(unsigned CPID) const { - if (getSubtargetInfo().getTargetTriple().isKnownWindowsMSVCEnvironment()) { + if (getSubtargetInfo().getTargetTriple().isWindowsMSVCEnvironment()) { const MachineConstantPoolEntry &CPE = MF->getConstantPool()->getConstants()[CPID]; if (!CPE.isMachineConstantPoolEntry()) { @@ -2858,7 +2918,7 @@ void AsmPrinter::setupCodePaddingContext(const MachineBasicBlock &MBB, MCCodePaddingContext &Context) const { assert(MF != nullptr && "Machine function must be valid"); Context.IsPaddingActive = !MF->hasInlineAsm() && - !MF->getFunction().optForSize() && + !MF->getFunction().hasOptSize() && TM.getOptLevel() != CodeGenOpt::None; Context.IsBasicBlockReachableViaFallthrough = std::find(MBB.pred_begin(), MBB.pred_end(), MBB.getPrevNode()) != @@ -2918,13 +2978,16 @@ void AsmPrinter::EmitBasicBlockStart(const MachineBasicBlock &MBB) const { // Print the main label for the block. if (MBB.pred_empty() || - (isBlockOnlyReachableByFallthrough(&MBB) && !MBB.isEHFuncletEntry())) { + (isBlockOnlyReachableByFallthrough(&MBB) && !MBB.isEHFuncletEntry() && + !MBB.hasLabelMustBeEmitted())) { 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"); OutStreamer->EmitLabel(MBB.getSymbol()); } } |