diff options
Diffstat (limited to 'llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp')
-rw-r--r-- | llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp | 919 |
1 files changed, 523 insertions, 396 deletions
diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp index 6f9aa4dd79fd5..f8f7b74baf916 100644 --- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -31,16 +31,13 @@ #include "llvm/Analysis/ConstantFolding.h" #include "llvm/Analysis/EHPersonalities.h" #include "llvm/Analysis/OptimizationRemarkEmitter.h" -#include "llvm/Analysis/ProfileSummaryInfo.h" #include "llvm/BinaryFormat/COFF.h" #include "llvm/BinaryFormat/Dwarf.h" #include "llvm/BinaryFormat/ELF.h" #include "llvm/CodeGen/GCMetadata.h" #include "llvm/CodeGen/GCMetadataPrinter.h" #include "llvm/CodeGen/GCStrategy.h" -#include "llvm/CodeGen/LazyMachineBlockFrequencyInfo.h" #include "llvm/CodeGen/MachineBasicBlock.h" -#include "llvm/CodeGen/MachineBlockFrequencyInfo.h" #include "llvm/CodeGen/MachineConstantPool.h" #include "llvm/CodeGen/MachineDominators.h" #include "llvm/CodeGen/MachineFrameInfo.h" @@ -55,7 +52,6 @@ #include "llvm/CodeGen/MachineModuleInfoImpls.h" #include "llvm/CodeGen/MachineOperand.h" #include "llvm/CodeGen/MachineOptimizationRemarkEmitter.h" -#include "llvm/CodeGen/MachineSizeOpts.h" #include "llvm/CodeGen/StackMaps.h" #include "llvm/CodeGen/TargetFrameLowering.h" #include "llvm/CodeGen/TargetInstrInfo.h" @@ -81,7 +77,6 @@ #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" @@ -106,6 +101,7 @@ #include "llvm/Pass.h" #include "llvm/Remarks/Remark.h" #include "llvm/Remarks/RemarkFormat.h" +#include "llvm/Remarks/RemarkStreamer.h" #include "llvm/Remarks/RemarkStringTable.h" #include "llvm/Support/Casting.h" #include "llvm/Support/CommandLine.h" @@ -161,11 +157,11 @@ static gcp_map_type &getGCMap(void *&P) { /// getGVAlignment - Return the alignment to use for the specified global /// value. This rounds up to the preferred alignment if possible and legal. -Align AsmPrinter::getGVAlignment(const GlobalValue *GV, const DataLayout &DL, +Align AsmPrinter::getGVAlignment(const GlobalObject *GV, const DataLayout &DL, Align InAlign) { Align Alignment; if (const GlobalVariable *GVar = dyn_cast<GlobalVariable>(GV)) - Alignment = Align(DL.getPreferredAlignment(GVar)); + Alignment = DL.getPreferredAlign(GVar); // If InAlign is specified, round it to it. if (InAlign > Alignment) @@ -231,7 +227,7 @@ const MCSubtargetInfo &AsmPrinter::getSubtargetInfo() const { } void AsmPrinter::EmitToStreamer(MCStreamer &S, const MCInst &Inst) { - S.EmitInstruction(Inst, getSubtargetInfo()); + S.emitInstruction(Inst, getSubtargetInfo()); } void AsmPrinter::emitInitialRawDwarfLocDirective(const MachineFunction &MF) { @@ -248,11 +244,8 @@ const MCSection *AsmPrinter::getCurrentSection() const { void AsmPrinter::getAnalysisUsage(AnalysisUsage &AU) const { AU.setPreservesAll(); MachineFunctionPass::getAnalysisUsage(AU); - AU.addRequired<MachineModuleInfoWrapperPass>(); AU.addRequired<MachineOptimizationRemarkEmitterPass>(); AU.addRequired<GCModuleInfo>(); - AU.addRequired<LazyMachineBlockFrequencyInfoPass>(); - AU.addRequired<ProfileSummaryInfoWrapperPass>(); } bool AsmPrinter::doInitialization(Module &M) { @@ -277,16 +270,16 @@ bool AsmPrinter::doInitialization(Module &M) { // use the directive, where it would need the same conditionalization // anyway. const Triple &Target = TM.getTargetTriple(); - OutStreamer->EmitVersionForTarget(Target, M.getSDKVersion()); + OutStreamer->emitVersionForTarget(Target, M.getSDKVersion()); // Allow the target to emit any magic that it wants at the start of the file. - EmitStartOfAsmFile(M); + emitStartOfAsmFile(M); // Very minimal debug info. It is ignored if we emit actual debug info. If we // don't, this at least helps the user find where a global came from. if (MAI->hasSingleParameterDotFile()) { // .file "foo.c" - OutStreamer->EmitFileDirective( + OutStreamer->emitFileDirective( llvm::sys::path::filename(M.getSourceFileName())); } @@ -305,21 +298,21 @@ bool AsmPrinter::doInitialization(Module &M) { TM.getTargetFeatureString())); OutStreamer->AddComment("Start of file scope inline assembly"); OutStreamer->AddBlankLine(); - EmitInlineAsm(M.getModuleInlineAsm()+"\n", + emitInlineAsm(M.getModuleInlineAsm() + "\n", OutContext.getSubtargetCopy(*STI), TM.Options.MCOptions); OutStreamer->AddComment("End of file scope inline assembly"); OutStreamer->AddBlankLine(); } if (MAI->doesSupportDebugInformation()) { - bool EmitCodeView = MMI->getModule()->getCodeViewFlag(); + bool EmitCodeView = M.getCodeViewFlag(); if (EmitCodeView && TM.getTargetTriple().isOSWindows()) { Handlers.emplace_back(std::make_unique<CodeViewDebug>(this), DbgTimerName, DbgTimerDescription, CodeViewLineTablesGroupName, CodeViewLineTablesGroupDescription); } - if (!EmitCodeView || MMI->getModule()->getDwarfVersion()) { + if (!EmitCodeView || M.getDwarfVersion()) { DD = new DwarfDebug(this, &M); DD->beginModule(); Handlers.emplace_back(std::unique_ptr<DwarfDebug>(DD), DbgTimerName, @@ -382,8 +375,7 @@ bool AsmPrinter::doInitialization(Module &M) { DWARFGroupDescription); // Emit tables for any value of cfguard flag (i.e. cfguard=1 or cfguard=2). - if (mdconst::extract_or_null<ConstantInt>( - MMI->getModule()->getModuleFlag("cfguard"))) + if (mdconst::extract_or_null<ConstantInt>(M.getModuleFlag("cfguard"))) Handlers.emplace_back(std::make_unique<WinCFGuard>(this), CFGuardName, CFGuardDescription, DWARFGroupName, DWARFGroupDescription); @@ -397,7 +389,7 @@ static bool canBeHidden(const GlobalValue *GV, const MCAsmInfo &MAI) { return GV->canBeOmittedFromSymbolTable(); } -void AsmPrinter::EmitLinkage(const GlobalValue *GV, MCSymbol *GVSym) const { +void AsmPrinter::emitLinkage(const GlobalValue *GV, MCSymbol *GVSym) const { GlobalValue::LinkageTypes Linkage = GV->getLinkage(); switch (Linkage) { case GlobalValue::CommonLinkage: @@ -407,35 +399,31 @@ void AsmPrinter::EmitLinkage(const GlobalValue *GV, MCSymbol *GVSym) const { case GlobalValue::WeakODRLinkage: if (MAI->hasWeakDefDirective()) { // .globl _foo - OutStreamer->EmitSymbolAttribute(GVSym, MCSA_Global); + OutStreamer->emitSymbolAttribute(GVSym, MCSA_Global); if (!canBeHidden(GV, *MAI)) // .weak_definition _foo - OutStreamer->EmitSymbolAttribute(GVSym, MCSA_WeakDefinition); + OutStreamer->emitSymbolAttribute(GVSym, MCSA_WeakDefinition); else - OutStreamer->EmitSymbolAttribute(GVSym, MCSA_WeakDefAutoPrivate); - } else if (MAI->hasLinkOnceDirective()) { + OutStreamer->emitSymbolAttribute(GVSym, MCSA_WeakDefAutoPrivate); + } else if (MAI->avoidWeakIfComdat() && GV->hasComdat()) { // .globl _foo - OutStreamer->EmitSymbolAttribute(GVSym, MCSA_Global); + OutStreamer->emitSymbolAttribute(GVSym, MCSA_Global); //NOTE: linkonce is handled by the section the symbol was assigned to. } else { // .weak _foo - OutStreamer->EmitSymbolAttribute(GVSym, MCSA_Weak); + OutStreamer->emitSymbolAttribute(GVSym, MCSA_Weak); } return; case GlobalValue::ExternalLinkage: - // If external, declare as a global symbol: .globl _foo - OutStreamer->EmitSymbolAttribute(GVSym, MCSA_Global); + OutStreamer->emitSymbolAttribute(GVSym, MCSA_Global); return; case GlobalValue::PrivateLinkage: - return; case GlobalValue::InternalLinkage: - if (MAI->hasDotLGloblDirective()) - OutStreamer->EmitSymbolAttribute(GVSym, MCSA_LGlobal); return; - case GlobalValue::AppendingLinkage: - case GlobalValue::AvailableExternallyLinkage: case GlobalValue::ExternalWeakLinkage: + case GlobalValue::AvailableExternallyLinkage: + case GlobalValue::AppendingLinkage: llvm_unreachable("Should never emit this"); } llvm_unreachable("Unknown linkage type!"); @@ -450,8 +438,27 @@ MCSymbol *AsmPrinter::getSymbol(const GlobalValue *GV) const { return TM.getSymbol(GV); } +MCSymbol *AsmPrinter::getSymbolPreferLocal(const GlobalValue &GV) const { + // On ELF, use .Lfoo$local if GV is a non-interposable GlobalObject with an + // exact definion (intersection of GlobalValue::hasExactDefinition() and + // !isInterposable()). These linkages include: external, appending, internal, + // private. It may be profitable to use a local alias for external. The + // assembler would otherwise be conservative and assume a global default + // visibility symbol can be interposable, even if the code generator already + // assumed it. + 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"); + } + return TM.getSymbol(&GV); +} + /// EmitGlobalVariable - Emit the specified global variable to the .s file. -void AsmPrinter::EmitGlobalVariable(const GlobalVariable *GV) { +void AsmPrinter::emitGlobalVariable(const GlobalVariable *GV) { bool IsEmuTLSVar = TM.useEmulatedTLS() && GV->isThreadLocal(); assert(!(IsEmuTLSVar && GV->hasCommonLinkage()) && "No emulated TLS variables in the common section"); @@ -463,7 +470,7 @@ void AsmPrinter::EmitGlobalVariable(const GlobalVariable *GV) { if (GV->hasInitializer()) { // Check to see if this is a special global used by LLVM, if so, emit it. - if (EmitSpecialLLVMGlobal(GV)) + if (emitSpecialLLVMGlobal(GV)) return; // Skip the emission of global equivalents. The symbol can be emitted later @@ -486,7 +493,7 @@ void AsmPrinter::EmitGlobalVariable(const GlobalVariable *GV) { // getOrCreateEmuTLSControlSym only creates the symbol with name and default // attributes. // GV's or GVSym's attributes will be used for the EmittedSym. - EmitVisibility(EmittedSym, GV->getVisibility(), !GV->isDeclaration()); + emitVisibility(EmittedSym, GV->getVisibility(), !GV->isDeclaration()); if (!GV->hasInitializer()) // External globals require no extra code. return; @@ -497,7 +504,7 @@ void AsmPrinter::EmitGlobalVariable(const GlobalVariable *GV) { "' is already defined"); if (MAI->hasDotTypeDotSizeDirective()) - OutStreamer->EmitSymbolAttribute(EmittedSym, MCSA_ELF_TypeObject); + OutStreamer->emitSymbolAttribute(EmittedSym, MCSA_ELF_TypeObject); SectionKind GVKind = TargetLoweringObjectFile::getKindForGlobal(GV, TM); @@ -522,7 +529,7 @@ void AsmPrinter::EmitGlobalVariable(const GlobalVariable *GV) { // .comm _foo, 42, 4 const bool SupportsAlignment = getObjFileLowering().getCommDirectiveSupportsAlignment(); - OutStreamer->EmitCommonSymbol(GVSym, Size, + OutStreamer->emitCommonSymbol(GVSym, Size, SupportsAlignment ? Alignment.value() : 0); return; } @@ -536,9 +543,9 @@ void AsmPrinter::EmitGlobalVariable(const GlobalVariable *GV) { TheSection->isVirtualSection()) { if (Size == 0) Size = 1; // zerofill of 0 bytes is undefined. - EmitLinkage(GV, GVSym); + emitLinkage(GV, GVSym); // .zerofill __DATA, __bss, _foo, 400, 5 - OutStreamer->EmitZerofill(TheSection, GVSym, Size, Alignment.value()); + OutStreamer->emitZerofill(TheSection, GVSym, Size, Alignment.value()); return; } @@ -557,16 +564,16 @@ void AsmPrinter::EmitGlobalVariable(const GlobalVariable *GV) { // Prefer to simply fall back to .local / .comm in this case. if (MAI->getLCOMMDirectiveAlignmentType() != LCOMM::NoAlignment) { // .lcomm _foo, 42 - OutStreamer->EmitLocalCommonSymbol(GVSym, Size, Alignment.value()); + OutStreamer->emitLocalCommonSymbol(GVSym, Size, Alignment.value()); return; } // .local _foo - OutStreamer->EmitSymbolAttribute(GVSym, MCSA_Local); + OutStreamer->emitSymbolAttribute(GVSym, MCSA_Local); // .comm _foo, 42, 4 const bool SupportsAlignment = getObjFileLowering().getCommDirectiveSupportsAlignment(); - OutStreamer->EmitCommonSymbol(GVSym, Size, + OutStreamer->emitCommonSymbol(GVSym, Size, SupportsAlignment ? Alignment.value() : 0); return; } @@ -588,14 +595,14 @@ void AsmPrinter::EmitGlobalVariable(const GlobalVariable *GV) { if (GVKind.isThreadBSS()) { TheSection = getObjFileLowering().getTLSBSSSection(); - OutStreamer->EmitTBSSSymbol(TheSection, MangSym, Size, Alignment.value()); + OutStreamer->emitTBSSSymbol(TheSection, MangSym, Size, Alignment.value()); } else if (GVKind.isThreadData()) { OutStreamer->SwitchSection(TheSection); - EmitAlignment(Alignment, GV); - OutStreamer->EmitLabel(MangSym); + emitAlignment(Alignment, GV); + OutStreamer->emitLabel(MangSym); - EmitGlobalConstant(GV->getParent()->getDataLayout(), + emitGlobalConstant(GV->getParent()->getDataLayout(), GV->getInitializer()); } @@ -606,18 +613,18 @@ void AsmPrinter::EmitGlobalVariable(const GlobalVariable *GV) { OutStreamer->SwitchSection(TLVSect); // Emit the linkage here. - EmitLinkage(GV, GVSym); - OutStreamer->EmitLabel(GVSym); + emitLinkage(GV, GVSym); + OutStreamer->emitLabel(GVSym); // Three pointers in size: // - __tlv_bootstrap - used to make sure support exists // - spare pointer, used when mapped by the runtime // - pointer to mangled symbol above with initializer unsigned PtrSize = DL.getPointerTypeSize(GV->getType()); - OutStreamer->EmitSymbolValue(GetExternalSymbolSymbol("_tlv_bootstrap"), + OutStreamer->emitSymbolValue(GetExternalSymbolSymbol("_tlv_bootstrap"), PtrSize); - OutStreamer->EmitIntValue(0, PtrSize); - OutStreamer->EmitSymbolValue(MangSym, PtrSize); + OutStreamer->emitIntValue(0, PtrSize); + OutStreamer->emitSymbolValue(MangSym, PtrSize); OutStreamer->AddBlankLine(); return; @@ -627,12 +634,15 @@ void AsmPrinter::EmitGlobalVariable(const GlobalVariable *GV) { OutStreamer->SwitchSection(TheSection); - EmitLinkage(GV, EmittedInitSym); - EmitAlignment(Alignment, GV); + emitLinkage(GV, EmittedInitSym); + emitAlignment(Alignment, GV); - OutStreamer->EmitLabel(EmittedInitSym); + OutStreamer->emitLabel(EmittedInitSym); + MCSymbol *LocalAlias = getSymbolPreferLocal(*GV); + if (LocalAlias != EmittedInitSym) + OutStreamer->emitLabel(LocalAlias); - EmitGlobalConstant(GV->getParent()->getDataLayout(), GV->getInitializer()); + emitGlobalConstant(GV->getParent()->getDataLayout(), GV->getInitializer()); if (MAI->hasDotTypeDotSizeDirective()) // .size foo, 42 @@ -646,13 +656,15 @@ void AsmPrinter::EmitGlobalVariable(const GlobalVariable *GV) { /// /// \p Value - The value to emit. /// \p Size - The size of the integer (in bytes) to emit. -void AsmPrinter::EmitDebugValue(const MCExpr *Value, unsigned Size) const { - OutStreamer->EmitValue(Value, Size); +void AsmPrinter::emitDebugValue(const MCExpr *Value, unsigned Size) const { + OutStreamer->emitValue(Value, Size); } +void AsmPrinter::emitFunctionHeaderComment() {} + /// EmitFunctionHeader - This method emits the header for the current /// function. -void AsmPrinter::EmitFunctionHeader() { +void AsmPrinter::emitFunctionHeader() { const Function &F = MF->getFunction(); if (isVerbose()) @@ -661,29 +673,32 @@ void AsmPrinter::EmitFunctionHeader() { << GlobalValue::dropLLVMManglingEscape(F.getName()) << '\n'; // Print out constants referenced by the function - EmitConstantPool(); + emitConstantPool(); // Print the 'header' of function. - OutStreamer->SwitchSection(getObjFileLowering().SectionForGlobal(&F, TM)); - EmitVisibility(CurrentFnSym, F.getVisibility()); + MF->setSection(getObjFileLowering().SectionForGlobal(&F, TM)); + OutStreamer->SwitchSection(MF->getSection()); + + if (!MAI->hasVisibilityOnlyWithLinkage()) + emitVisibility(CurrentFnSym, F.getVisibility()); - if (MAI->needsFunctionDescriptors() && - F.getLinkage() != GlobalValue::InternalLinkage) - EmitLinkage(&F, CurrentFnDescSym); + if (MAI->needsFunctionDescriptors()) + emitLinkage(&F, CurrentFnDescSym); - 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); + OutStreamer->emitSymbolAttribute(CurrentFnSym, MCSA_ELF_TypeFunction); if (F.hasFnAttribute(Attribute::Cold)) - OutStreamer->EmitSymbolAttribute(CurrentFnSym, MCSA_Cold); + OutStreamer->emitSymbolAttribute(CurrentFnSym, MCSA_Cold); if (isVerbose()) { F.printAsOperand(OutStreamer->GetCommentOS(), /*PrintType=*/false, F.getParent()); + emitFunctionHeaderComment(); OutStreamer->GetCommentOS() << '\n'; } @@ -695,44 +710,57 @@ void AsmPrinter::EmitFunctionHeader() { // and use the .alt_entry attribute to mark the function's real entry point // as an alternative entry point to the prefix-data symbol. MCSymbol *PrefixSym = OutContext.createLinkerPrivateTempSymbol(); - OutStreamer->EmitLabel(PrefixSym); + 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); + OutStreamer->emitSymbolAttribute(CurrentFnSym, MCSA_AltEntry); } else { - EmitGlobalConstant(F.getParent()->getDataLayout(), F.getPrefixData()); + emitGlobalConstant(F.getParent()->getDataLayout(), F.getPrefixData()); } } + // Emit M NOPs for -fpatchable-function-entry=N,M where M>0. We arbitrarily + // place prefix data before NOPs. + unsigned PatchableFunctionPrefix = 0; + unsigned PatchableFunctionEntry = 0; + (void)F.getFnAttribute("patchable-function-prefix") + .getValueAsString() + .getAsInteger(10, PatchableFunctionPrefix); + (void)F.getFnAttribute("patchable-function-entry") + .getValueAsString() + .getAsInteger(10, PatchableFunctionEntry); + if (PatchableFunctionPrefix) { + CurrentPatchableFunctionEntrySym = + OutContext.createLinkerPrivateTempSymbol(); + OutStreamer->emitLabel(CurrentPatchableFunctionEntrySym); + emitNops(PatchableFunctionPrefix); + } else if (PatchableFunctionEntry) { + // May be reassigned when emitting the body, to reference the label after + // the initial BTI (AArch64) or endbr32/endbr64 (x86). + CurrentPatchableFunctionEntrySym = CurrentFnBegin; + } + // Emit the function descriptor. This is a virtual function to allow targets - // to emit their specific function descriptor. + // to emit their specific function descriptor. Right now it is only used by + // the AIX target. The PowerPC 64-bit V1 ELF target also uses function + // descriptors and should be converted to use this hook as well. if (MAI->needsFunctionDescriptors()) - EmitFunctionDescriptor(); + emitFunctionDescriptor(); // Emit the CurrentFnSym. This is a virtual function to allow targets to do // their wild and crazy things as required. - EmitFunctionEntryLabel(); - - // If the function had address-taken blocks that got deleted, then we have - // 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); - for (unsigned i = 0, e = DeadBlockSyms.size(); i != e; ++i) { - OutStreamer->AddComment("Address taken block that was later removed"); - OutStreamer->EmitLabel(DeadBlockSyms[i]); - } + emitFunctionEntryLabel(); if (CurrentFnBegin) { if (MAI->useAssignmentForEHBegin()) { MCSymbol *CurPos = OutContext.createTempSymbol(); - OutStreamer->EmitLabel(CurPos); - OutStreamer->EmitAssignment(CurrentFnBegin, + OutStreamer->emitLabel(CurPos); + OutStreamer->emitAssignment(CurrentFnBegin, MCSymbolRefExpr::create(CurPos, OutContext)); } else { - OutStreamer->EmitLabel(CurrentFnBegin); + OutStreamer->emitLabel(CurrentFnBegin); } } @@ -745,12 +773,12 @@ void AsmPrinter::EmitFunctionHeader() { // Emit the prologue data. if (F.hasPrologueData()) - EmitGlobalConstant(F.getParent()->getDataLayout(), F.getPrologueData()); + emitGlobalConstant(F.getParent()->getDataLayout(), F.getPrologueData()); } /// EmitFunctionEntryLabel - Emit the label that is the entrypoint for the /// function. This can be overridden by targets as required to do custom stuff. -void AsmPrinter::EmitFunctionEntryLabel() { +void AsmPrinter::emitFunctionEntryLabel() { CurrentFnSym->redefineIfPossible(); // The function label could have already been emitted if two symbols end up @@ -762,7 +790,13 @@ void AsmPrinter::EmitFunctionEntryLabel() { report_fatal_error("'" + Twine(CurrentFnSym->getName()) + "' label emitted multiple times to assembly file"); - return OutStreamer->EmitLabel(CurrentFnSym); + OutStreamer->emitLabel(CurrentFnSym); + + if (TM.getTargetTriple().isOSBinFormatELF()) { + MCSymbol *Sym = getSymbolPreferLocal(MF->getFunction()); + if (Sym != CurrentFnSym) + OutStreamer->emitLabel(Sym); + } } /// emitComments - Pretty-print comments for instructions. @@ -842,7 +876,7 @@ static bool emitDebugValueComment(const MachineInstr *MI, AsmPrinter &AP) { OS << " <- "; // The second operand is only an offset if it's an immediate. - bool MemLoc = MI->getOperand(0).isReg() && MI->getOperand(1).isImm(); + bool MemLoc = MI->isIndirectDebugValue(); int64_t Offset = MemLoc ? MI->getOperand(1).getImm() : 0; const DIExpression *Expr = MI->getDebugExpression(); if (Expr->getNumElements()) { @@ -861,11 +895,11 @@ static bool emitDebugValueComment(const MachineInstr *MI, AsmPrinter &AP) { } // Register or immediate value. Register 0 means undef. - if (MI->getOperand(0).isFPImm()) { - APFloat APF = APFloat(MI->getOperand(0).getFPImm()->getValueAPF()); - if (MI->getOperand(0).getFPImm()->getType()->isFloatTy()) { + if (MI->getDebugOperand(0).isFPImm()) { + APFloat APF = APFloat(MI->getDebugOperand(0).getFPImm()->getValueAPF()); + if (MI->getDebugOperand(0).getFPImm()->getType()->isFloatTy()) { OS << (double)APF.convertToFloat(); - } else if (MI->getOperand(0).getFPImm()->getType()->isDoubleTy()) { + } else if (MI->getDebugOperand(0).getFPImm()->getType()->isDoubleTy()) { OS << APF.convertToDouble(); } else { // There is no good way to print long double. Convert a copy to @@ -875,23 +909,23 @@ static bool emitDebugValueComment(const MachineInstr *MI, AsmPrinter &AP) { &ignored); OS << "(long double) " << APF.convertToDouble(); } - } else if (MI->getOperand(0).isImm()) { - OS << MI->getOperand(0).getImm(); - } else if (MI->getOperand(0).isCImm()) { - MI->getOperand(0).getCImm()->getValue().print(OS, false /*isSigned*/); - } else if (MI->getOperand(0).isTargetIndex()) { - auto Op = MI->getOperand(0); + } else if (MI->getDebugOperand(0).isImm()) { + OS << MI->getDebugOperand(0).getImm(); + } else if (MI->getDebugOperand(0).isCImm()) { + MI->getDebugOperand(0).getCImm()->getValue().print(OS, false /*isSigned*/); + } else if (MI->getDebugOperand(0).isTargetIndex()) { + auto Op = MI->getDebugOperand(0); OS << "!target-index(" << Op.getIndex() << "," << Op.getOffset() << ")"; return true; } else { - unsigned Reg; - if (MI->getOperand(0).isReg()) { - Reg = MI->getOperand(0).getReg(); + Register Reg; + if (MI->getDebugOperand(0).isReg()) { + Reg = MI->getDebugOperand(0).getReg(); } else { - assert(MI->getOperand(0).isFI() && "Unknown operand type"); + assert(MI->getDebugOperand(0).isFI() && "Unknown operand type"); const TargetFrameLowering *TFI = AP.MF->getSubtarget().getFrameLowering(); - Offset += TFI->getFrameIndexReference(*AP.MF, - MI->getOperand(0).getIndex(), Reg); + Offset += TFI->getFrameIndexReference( + *AP.MF, MI->getDebugOperand(0).getIndex(), Reg); MemLoc = true; } if (Reg == 0) { @@ -985,7 +1019,7 @@ void AsmPrinter::emitFrameAlloc(const MachineInstr &MI) { int FrameOffset = MI.getOperand(1).getImm(); // Emit a symbol assignment. - OutStreamer->EmitAssignment(FrameAllocSym, + OutStreamer->emitAssignment(FrameAllocSym, MCConstantExpr::create(FrameOffset, OutContext)); } @@ -1008,15 +1042,15 @@ void AsmPrinter::emitStackSizeSection(const MachineFunction &MF) { const MCSymbol *FunctionSymbol = getFunctionBegin(); uint64_t StackSize = FrameInfo.getStackSize(); - OutStreamer->EmitSymbolValue(FunctionSymbol, TM.getProgramPointerSize()); - OutStreamer->EmitULEB128IntValue(StackSize); + OutStreamer->emitSymbolValue(FunctionSymbol, TM.getProgramPointerSize()); + OutStreamer->emitULEB128IntValue(StackSize); OutStreamer->PopSection(); } -static bool needFuncLabelsForEHOrDebugInfo(const MachineFunction &MF, - MachineModuleInfo *MMI) { - if (!MF.getLandingPads().empty() || MF.hasEHFunclets() || MMI->hasDebugInfo()) +static bool needFuncLabelsForEHOrDebugInfo(const MachineFunction &MF) { + MachineModuleInfo &MMI = MF.getMMI(); + if (!MF.getLandingPads().empty() || MF.hasEHFunclets() || MMI.hasDebugInfo()) return true; // We might emit an EH table that uses function begin and end labels even if @@ -1029,11 +1063,11 @@ static bool needFuncLabelsForEHOrDebugInfo(const MachineFunction &MF, /// EmitFunctionBody - This method emits the body and trailer for a /// function. -void AsmPrinter::EmitFunctionBody() { - EmitFunctionHeader(); +void AsmPrinter::emitFunctionBody() { + emitFunctionHeader(); // Emit target-specific gunk before the function body. - EmitFunctionBodyStart(); + emitFunctionBodyStart(); bool ShouldPrintDebugScopes = MMI->hasDebugInfo(); @@ -1058,9 +1092,10 @@ void AsmPrinter::EmitFunctionBody() { // Print out code for the function. bool HasAnyRealCode = false; int NumInstsInFunction = 0; + for (auto &MBB : *MF) { // Print a label for the basic block. - EmitBasicBlockStart(MBB); + emitBasicBlockStart(MBB); for (auto &MI : MBB) { // Print the assembly for the instruction. if (!MI.isPosition() && !MI.isImplicitDef() && !MI.isKill() && @@ -1071,7 +1106,7 @@ void AsmPrinter::EmitFunctionBody() { // If there is a pre-instruction symbol, emit a label for it here. if (MCSymbol *S = MI.getPreInstrSymbol()) - OutStreamer->EmitLabel(S); + OutStreamer->emitLabel(S); if (ShouldPrintDebugScopes) { for (const HandlerInfo &HI : Handlers) { @@ -1095,22 +1130,22 @@ void AsmPrinter::EmitFunctionBody() { case TargetOpcode::ANNOTATION_LABEL: case TargetOpcode::EH_LABEL: case TargetOpcode::GC_LABEL: - OutStreamer->EmitLabel(MI.getOperand(0).getMCSymbol()); + OutStreamer->emitLabel(MI.getOperand(0).getMCSymbol()); break; case TargetOpcode::INLINEASM: case TargetOpcode::INLINEASM_BR: - EmitInlineAsm(&MI); + emitInlineAsm(&MI); break; case TargetOpcode::DBG_VALUE: if (isVerbose()) { if (!emitDebugValueComment(&MI, *this)) - EmitInstruction(&MI); + emitInstruction(&MI); } break; case TargetOpcode::DBG_LABEL: if (isVerbose()) { if (!emitDebugLabelComment(&MI, *this)) - EmitInstruction(&MI); + emitInstruction(&MI); } break; case TargetOpcode::IMPLICIT_DEF: @@ -1120,13 +1155,13 @@ void AsmPrinter::EmitFunctionBody() { if (isVerbose()) emitKill(&MI, *this); break; default: - EmitInstruction(&MI); + emitInstruction(&MI); break; } // If there is a post-instruction symbol, emit a label for it here. if (MCSymbol *S = MI.getPostInstrSymbol()) - OutStreamer->EmitLabel(S); + OutStreamer->emitLabel(S); if (ShouldPrintDebugScopes) { for (const HandlerInfo &HI : Handlers) { @@ -1138,7 +1173,44 @@ void AsmPrinter::EmitFunctionBody() { } } - EmitBasicBlockEnd(MBB); + // 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); + } + + // 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()) { + if (!MBB.sameSection(&MF->front())) { + if (MAI->hasDotTypeDotSizeDirective()) + emitELFSizeDirective(CurrentSectionBeginSym); + MBBSectionRanges[MBB.getSectionIDNum()] = + MBBSectionRange{CurrentSectionBeginSym, CurrentBBEnd}; + } + } + emitBasicBlockEnd(MBB); } EmittedInsts += NumInstsInFunction; @@ -1167,10 +1239,13 @@ void AsmPrinter::EmitFunctionBody() { // unspecified. if (Noop.getOpcode()) { OutStreamer->AddComment("avoids zero-length function"); - OutStreamer->EmitInstruction(Noop, getSubtargetInfo()); + emitNops(1); } } + // Switch to the original section in case basic block sections was used. + OutStreamer->SwitchSection(MF->getSection()); + const Function &F = MF->getFunction(); for (const auto &BB : F) { if (!BB.hasAddressTaken()) @@ -1179,17 +1254,17 @@ void AsmPrinter::EmitFunctionBody() { if (Sym->isDefined()) continue; OutStreamer->AddComment("Address of block that was removed by CodeGen"); - OutStreamer->EmitLabel(Sym); + OutStreamer->emitLabel(Sym); } // Emit target-specific gunk after the function body. - EmitFunctionBodyEnd(); + emitFunctionBodyEnd(); - if (needFuncLabelsForEHOrDebugInfo(*MF, MMI) || + if (needFuncLabelsForEHOrDebugInfo(*MF) || MAI->hasDotTypeDotSizeDirective()) { // Create a symbol for the end of function. CurrentFnEnd = createTempSymbol("func_end"); - OutStreamer->EmitLabel(CurrentFnEnd); + OutStreamer->emitLabel(CurrentFnEnd); } // If the target wants a .size directive for the size of the function, emit @@ -1209,8 +1284,11 @@ void AsmPrinter::EmitFunctionBody() { HI.Handler->markFunctionEnd(); } + MBBSectionRanges[MF->front().getSectionIDNum()] = + MBBSectionRange{CurrentFnBegin, CurrentFnEnd}; + // Print out jump tables referenced by the function. - EmitJumpTableInfo(); + emitJumpTableInfo(); // Emit post-function debug and/or EH information. for (const HandlerInfo &HI : Handlers) { @@ -1306,7 +1384,7 @@ void AsmPrinter::emitGlobalGOTEquivs() { GlobalGOTEquivs.clear(); for (auto *GV : FailedCandidates) - EmitGlobalVariable(GV); + emitGlobalVariable(GV); } void AsmPrinter::emitGlobalIndirectSymbol(Module &M, @@ -1314,9 +1392,9 @@ void AsmPrinter::emitGlobalIndirectSymbol(Module &M, MCSymbol *Name = getSymbol(&GIS); if (GIS.hasExternalLinkage() || !MAI->getWeakRefDirective()) - OutStreamer->EmitSymbolAttribute(Name, MCSA_Global); + OutStreamer->emitSymbolAttribute(Name, MCSA_Global); else if (GIS.hasWeakLinkage() || GIS.hasLinkOnceLinkage()) - OutStreamer->EmitSymbolAttribute(Name, MCSA_WeakReference); + OutStreamer->emitSymbolAttribute(Name, MCSA_WeakReference); else assert(GIS.hasLocalLinkage() && "Invalid alias or ifunc linkage"); @@ -1333,19 +1411,22 @@ void AsmPrinter::emitGlobalIndirectSymbol(Module &M, // 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) - OutStreamer->EmitSymbolAttribute(Name, isa<GlobalIFunc>(GIS) + OutStreamer->emitSymbolAttribute(Name, isa<GlobalIFunc>(GIS) ? MCSA_ELF_TypeIndFunction : MCSA_ELF_TypeFunction); - EmitVisibility(Name, GIS.getVisibility()); + emitVisibility(Name, GIS.getVisibility()); const MCExpr *Expr = lowerConstant(GIS.getIndirectSymbol()); if (isa<GlobalAlias>(&GIS) && MAI->hasAltEntry() && isa<MCBinaryExpr>(Expr)) - OutStreamer->EmitSymbolAttribute(Name, MCSA_AltEntry); + OutStreamer->emitSymbolAttribute(Name, MCSA_AltEntry); // Emit the directives as assignments aka .set: - OutStreamer->EmitAssignment(Name, Expr); + OutStreamer->emitAssignment(Name, Expr); + MCSymbol *LocalAlias = getSymbolPreferLocal(GIS); + if (LocalAlias != Name) + OutStreamer->emitAssignment(LocalAlias, Expr); if (auto *GA = dyn_cast<GlobalAlias>(&GIS)) { // If the aliasee does not correspond to a symbol in the output, i.e. the @@ -1363,7 +1444,7 @@ void AsmPrinter::emitGlobalIndirectSymbol(Module &M, } } -void AsmPrinter::emitRemarksSection(RemarkStreamer &RS) { +void AsmPrinter::emitRemarksSection(remarks::RemarkStreamer &RS) { if (!RS.needsSection()) return; @@ -1388,7 +1469,7 @@ void AsmPrinter::emitRemarksSection(RemarkStreamer &RS) { OutContext.getObjectFileInfo()->getRemarksSection(); OutStreamer->SwitchSection(RemarksSection); - OutStreamer->EmitBinaryData(OS.str()); + OutStreamer->emitBinaryData(OS.str()); } bool AsmPrinter::doFinalization(Module &M) { @@ -1405,31 +1486,51 @@ bool AsmPrinter::doFinalization(Module &M) { // Emit global variables. for (const auto &G : M.globals()) - EmitGlobalVariable(&G); + emitGlobalVariable(&G); // Emit remaining GOT equivalent globals. emitGlobalGOTEquivs(); - // Emit visibility info for declarations + const TargetLoweringObjectFile &TLOF = getObjFileLowering(); + + // Emit linkage(XCOFF) and visibility info for declarations for (const Function &F : M) { if (!F.isDeclarationForLinker()) continue; - GlobalValue::VisibilityTypes V = F.getVisibility(); - if (V == GlobalValue::DefaultVisibility) - continue; MCSymbol *Name = getSymbol(&F); - EmitVisibility(Name, V, false); + // Function getSymbol gives us the function descriptor symbol for XCOFF. + + if (!TM.getTargetTriple().isOSBinFormatXCOFF()) { + GlobalValue::VisibilityTypes V = F.getVisibility(); + if (V == GlobalValue::DefaultVisibility) + continue; + + emitVisibility(Name, V, false); + continue; + } + + if (F.isIntrinsic()) + continue; + + // Handle the XCOFF case. + // 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 descriptor. + emitLinkage(&F, Name); } // 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 (RemarkStreamer *RS = M.getContext().getRemarkStreamer()) + if (remarks::RemarkStreamer *RS = M.getContext().getMainRemarkStreamer()) emitRemarksSection(*RS); - const TargetLoweringObjectFile &TLOF = getObjFileLowering(); - TLOF.emitModuleMetadata(*OutStreamer, M); if (TM.getTargetTriple().isOSBinFormatELF()) { @@ -1441,10 +1542,10 @@ bool AsmPrinter::doFinalization(Module &M) { OutStreamer->SwitchSection(TLOF.getDataSection()); const DataLayout &DL = M.getDataLayout(); - EmitAlignment(Align(DL.getPointerSize())); + emitAlignment(Align(DL.getPointerSize())); for (const auto &Stub : Stubs) { - OutStreamer->EmitLabel(Stub.first); - OutStreamer->EmitSymbolValue(Stub.second.getPointer(), + OutStreamer->emitLabel(Stub.first); + OutStreamer->emitSymbolValue(Stub.second.getPointer(), DL.getPointerSize()); } } @@ -1468,10 +1569,10 @@ bool AsmPrinter::doFinalization(Module &M) { COFF::IMAGE_SCN_LNK_COMDAT, SectionKind::getReadOnly(), Stub.first->getName(), COFF::IMAGE_COMDAT_SELECT_ANY)); - EmitAlignment(Align(DL.getPointerSize())); - OutStreamer->EmitSymbolAttribute(Stub.first, MCSA_Global); - OutStreamer->EmitLabel(Stub.first); - OutStreamer->EmitSymbolValue(Stub.second.getPointer(), + emitAlignment(Align(DL.getPointerSize())); + OutStreamer->emitSymbolAttribute(Stub.first, MCSA_Global); + OutStreamer->emitLabel(Stub.first); + OutStreamer->emitSymbolValue(Stub.second.getPointer(), DL.getPointerSize()); } } @@ -1497,7 +1598,7 @@ bool AsmPrinter::doFinalization(Module &M) { for (const auto &GO : M.global_objects()) { if (!GO.hasExternalWeakLinkage()) continue; - OutStreamer->EmitSymbolAttribute(getSymbol(&GO), MCSA_WeakReference); + OutStreamer->emitSymbolAttribute(getSymbol(&GO), MCSA_WeakReference); } } @@ -1528,25 +1629,25 @@ bool AsmPrinter::doFinalization(Module &M) { MP->finishAssembly(M, *MI, *this); // Emit llvm.ident metadata in an '.ident' directive. - EmitModuleIdents(M); + emitModuleIdents(M); // Emit bytes for llvm.commandline metadata. - EmitModuleCommandLines(M); + emitModuleCommandLines(M); // Emit __morestack address if needed for indirect calls. if (MMI->usesMorestackAddr()) { - unsigned Align = 1; + Align Alignment(1); MCSection *ReadOnlySection = getObjFileLowering().getSectionForConstant( getDataLayout(), SectionKind::getReadOnly(), - /*C=*/nullptr, Align); + /*C=*/nullptr, Alignment); OutStreamer->SwitchSection(ReadOnlySection); MCSymbol *AddrSymbol = OutContext.getOrCreateSymbol(StringRef("__morestack_addr")); - OutStreamer->EmitLabel(AddrSymbol); + OutStreamer->emitLabel(AddrSymbol); unsigned PtrSize = MAI->getCodePointerSize(); - OutStreamer->EmitSymbolValue(GetExternalSymbolSymbol("__morestack"), + OutStreamer->emitSymbolValue(GetExternalSymbolSymbol("__morestack"), PtrSize); } @@ -1578,7 +1679,7 @@ bool AsmPrinter::doFinalization(Module &M) { OS.flush(); if (!Flags.empty()) { OutStreamer->SwitchSection(TLOF.getDrectveSection()); - OutStreamer->EmitBytes(Flags); + OutStreamer->emitBytes(Flags); } Flags.clear(); } @@ -1604,7 +1705,7 @@ bool AsmPrinter::doFinalization(Module &M) { if (!Flags.empty()) { OutStreamer->SwitchSection(TLOF.getDrectveSection()); - OutStreamer->EmitBytes(Flags); + OutStreamer->emitBytes(Flags); } Flags.clear(); } @@ -1614,12 +1715,12 @@ bool AsmPrinter::doFinalization(Module &M) { if (TM.Options.EmitAddrsig) { // Emit address-significance attributes for all globals. - OutStreamer->EmitAddrsig(); + OutStreamer->emitAddrsig(); for (const GlobalValue &GV : M.global_values()) if (!GV.use_empty() && !GV.isThreadLocal() && !GV.hasDLLImportStorageClass() && !GV.getName().startswith("llvm.") && !GV.hasAtLeastLocalUnnamedAddr()) - OutStreamer->EmitAddrsigSym(getSymbol(&GV)); + OutStreamer->emitAddrsigSym(getSymbol(&GV)); } // Emit symbol partition specifications (ELF only). @@ -1630,11 +1731,12 @@ bool AsmPrinter::doFinalization(Module &M) { 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( + OutStreamer->SwitchSection( + OutContext.getELFSection(".llvm_sympart", ELF::SHT_LLVM_SYMPART, 0, 0, + "", ++UniqueID, nullptr)); + OutStreamer->emitBytes(GV.getPartition()); + OutStreamer->emitZeros(1); + OutStreamer->emitValue( MCSymbolRefExpr::create(getSymbol(&GV), OutContext), MAI->getCodePointerSize()); } @@ -1642,7 +1744,7 @@ bool AsmPrinter::doFinalization(Module &M) { // Allow the target to emit any magic that it wants at the end of the file, // after everything else has gone out. - EmitEndOfAsmFile(M); + emitEndOfAsmFile(M); MMI = nullptr; @@ -1665,30 +1767,31 @@ void AsmPrinter::SetupMachineFunction(MachineFunction &MF) { const Function &F = MF.getFunction(); // Get the function symbol. - if (MAI->needsFunctionDescriptors()) { - assert(TM.getTargetTriple().isOSAIX() && "Function descriptor is only" - " supported on AIX."); + if (!MAI->needsFunctionDescriptors()) { + CurrentFnSym = getSymbol(&MF.getFunction()); + } else { + assert(TM.getTargetTriple().isOSAIX() && + "Only AIX uses the function descriptor hooks."); + // AIX is unique here in that the name of the symbol emitted for the + // function body does not have the same name as the source function's + // C-linkage name. assert(CurrentFnDescSym && "The function descriptor symbol needs to be" - " initalized first."); + " initalized first."); // Get the function entry point symbol. - CurrentFnSym = - OutContext.getOrCreateSymbol("." + CurrentFnDescSym->getName()); - - MCSectionXCOFF *FnEntryPointSec = - cast<MCSectionXCOFF>(getObjFileLowering().SectionForGlobal(&F, TM)); - // Set the containing csect. - cast<MCSymbolXCOFF>(CurrentFnSym)->setContainingCsect(FnEntryPointSec); - } else { - CurrentFnSym = getSymbol(&MF.getFunction()); + CurrentFnSym = getObjFileLowering().getFunctionEntryPointSymbol(&F, TM); } CurrentFnSymForSize = CurrentFnSym; CurrentFnBegin = nullptr; + CurrentSectionBeginSym = nullptr; + MBBSectionRanges.clear(); CurExceptionSym = nullptr; bool NeedsLocalForSize = MAI->needsLocalForSize(); if (F.hasFnAttribute("patchable-function-entry") || - needFuncLabelsForEHOrDebugInfo(MF, MMI) || NeedsLocalForSize || + F.hasFnAttribute("function-instrument") || + F.hasFnAttribute("xray-instruction-threshold") || + needFuncLabelsForEHOrDebugInfo(MF) || NeedsLocalForSize || MF.getTarget().Options.EmitStackSizeSection) { CurrentFnBegin = createTempSymbol("func_begin"); if (NeedsLocalForSize) @@ -1696,13 +1799,6 @@ void AsmPrinter::SetupMachineFunction(MachineFunction &MF) { } ORE = &getAnalysis<MachineOptimizationRemarkEmitterPass>().getORE(); - PSI = &getAnalysis<ProfileSummaryInfoWrapperPass>().getPSI(); - MBFI = (PSI && PSI->hasProfileSummary()) ? - // ORE conditionally computes MBFI. If available, use it, otherwise - // request it. - (ORE->getBFI() ? ORE->getBFI() : - &getAnalysis<LazyMachineBlockFrequencyInfoPass>().getBFI()) : - nullptr; } namespace { @@ -1710,10 +1806,10 @@ namespace { // Keep track the alignment, constpool entries per Section. struct SectionCPs { MCSection *S; - unsigned Alignment; + Align Alignment; SmallVector<unsigned, 4> CPEs; - SectionCPs(MCSection *s, unsigned a) : S(s), Alignment(a) {} + SectionCPs(MCSection *s, Align a) : S(s), Alignment(a) {} }; } // end anonymous namespace @@ -1722,7 +1818,7 @@ 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() { +void AsmPrinter::emitConstantPool() { const MachineConstantPool *MCP = MF->getConstantPool(); const std::vector<MachineConstantPoolEntry> &CP = MCP->getConstants(); if (CP.empty()) return; @@ -1732,7 +1828,7 @@ void AsmPrinter::EmitConstantPool() { SmallVector<SectionCPs, 4> CPSections; for (unsigned i = 0, e = CP.size(); i != e; ++i) { const MachineConstantPoolEntry &CPE = CP[i]; - unsigned Align = CPE.getAlignment(); + Align Alignment = CPE.getAlign(); SectionKind Kind = CPE.getSectionKind(&getDataLayout()); @@ -1740,8 +1836,8 @@ void AsmPrinter::EmitConstantPool() { if (!CPE.isMachineConstantPoolEntry()) C = CPE.Val.ConstVal; - MCSection *S = getObjFileLowering().getSectionForConstant(getDataLayout(), - Kind, C, Align); + MCSection *S = getObjFileLowering().getSectionForConstant( + getDataLayout(), Kind, C, Alignment); // The number of sections are small, just do a linear search from the // last section to the first. @@ -1755,11 +1851,11 @@ void AsmPrinter::EmitConstantPool() { } if (!Found) { SecIdx = CPSections.size(); - CPSections.push_back(SectionCPs(S, Align)); + CPSections.push_back(SectionCPs(S, Alignment)); } - if (Align > CPSections[SecIdx].Alignment) - CPSections[SecIdx].Alignment = Align; + if (Alignment > CPSections[SecIdx].Alignment) + CPSections[SecIdx].Alignment = Alignment; CPSections[SecIdx].CPEs.push_back(i); } @@ -1773,14 +1869,9 @@ void AsmPrinter::EmitConstantPool() { if (!Sym->isUndefined()) continue; - if (TM.getTargetTriple().isOSBinFormatXCOFF()) { - cast<MCSymbolXCOFF>(Sym)->setContainingCsect( - cast<MCSectionXCOFF>(CPSections[i].S)); - } - if (CurSection != CPSections[i].S) { OutStreamer->SwitchSection(CPSections[i].S); - EmitAlignment(Align(CPSections[i].Alignment)); + emitAlignment(Align(CPSections[i].Alignment)); CurSection = CPSections[i].S; Offset = 0; } @@ -1788,25 +1879,24 @@ void AsmPrinter::EmitConstantPool() { MachineConstantPoolEntry CPE = CP[CPI]; // Emit inter-object padding for alignment. - unsigned AlignMask = CPE.getAlignment() - 1; - unsigned NewOffset = (Offset + AlignMask) & ~AlignMask; - OutStreamer->EmitZeros(NewOffset - Offset); + unsigned NewOffset = alignTo(Offset, CPE.getAlign()); + OutStreamer->emitZeros(NewOffset - Offset); Type *Ty = CPE.getType(); Offset = NewOffset + getDataLayout().getTypeAllocSize(Ty); - OutStreamer->EmitLabel(Sym); + OutStreamer->emitLabel(Sym); if (CPE.isMachineConstantPoolEntry()) - EmitMachineConstantPoolValue(CPE.Val.MachineCPVal); + emitMachineConstantPoolValue(CPE.Val.MachineCPVal); else - EmitGlobalConstant(getDataLayout(), CPE.Val.ConstVal); + emitGlobalConstant(getDataLayout(), CPE.Val.ConstVal); } } } -/// EmitJumpTableInfo - Print assembly representations of the jump tables used -/// by the current function to the current output stream. -void AsmPrinter::EmitJumpTableInfo() { +// Print assembly representations of the jump tables used by the current +// function. +void AsmPrinter::emitJumpTableInfo() { const DataLayout &DL = MF->getDataLayout(); const MachineJumpTableInfo *MJTI = MF->getJumpTableInfo(); if (!MJTI) return; @@ -1827,12 +1917,12 @@ void AsmPrinter::EmitJumpTableInfo() { OutStreamer->SwitchSection(ReadOnlySection); } - EmitAlignment(Align(MJTI->getEntryAlignment(DL))); + emitAlignment(Align(MJTI->getEntryAlignment(DL))); // Jump tables in code sections are marked with a data_region directive // where that's supported. if (!JTInDiffSection) - OutStreamer->EmitDataRegion(MCDR_DataRegionJT32); + OutStreamer->emitDataRegion(MCDR_DataRegionJT32); for (unsigned JTI = 0, e = JT.size(); JTI != e; ++JTI) { const std::vector<MachineBasicBlock*> &JTBBs = JT[JTI].MBBs; @@ -1855,7 +1945,7 @@ void AsmPrinter::EmitJumpTableInfo() { // .set LJTSet, LBB32-base const MCExpr *LHS = MCSymbolRefExpr::create(MBB->getSymbol(), OutContext); - OutStreamer->EmitAssignment(GetJTSetSymbol(JTI, MBB->getNumber()), + OutStreamer->emitAssignment(GetJTSetSymbol(JTI, MBB->getNumber()), MCBinaryExpr::createSub(LHS, Base, OutContext)); } @@ -1869,25 +1959,21 @@ void AsmPrinter::EmitJumpTableInfo() { // FIXME: This doesn't have to have any specific name, just any randomly // named and numbered local label started with 'l' would work. Simplify // GetJTISymbol. - OutStreamer->EmitLabel(GetJTISymbol(JTI, true)); + OutStreamer->emitLabel(GetJTISymbol(JTI, true)); MCSymbol* JTISymbol = GetJTISymbol(JTI); - if (TM.getTargetTriple().isOSBinFormatXCOFF()) { - cast<MCSymbolXCOFF>(JTISymbol)->setContainingCsect( - cast<MCSectionXCOFF>(TLOF.getSectionForJumpTable(F, TM))); - } - OutStreamer->EmitLabel(JTISymbol); + OutStreamer->emitLabel(JTISymbol); for (unsigned ii = 0, ee = JTBBs.size(); ii != ee; ++ii) - EmitJumpTableEntry(MJTI, JTBBs[ii], JTI); + emitJumpTableEntry(MJTI, JTBBs[ii], JTI); } if (!JTInDiffSection) - OutStreamer->EmitDataRegion(MCDR_DataRegionEnd); + OutStreamer->emitDataRegion(MCDR_DataRegionEnd); } /// EmitJumpTableEntry - Emit a jump table entry for the specified MBB to the /// current stream. -void AsmPrinter::EmitJumpTableEntry(const MachineJumpTableInfo *MJTI, +void AsmPrinter::emitJumpTableEntry(const MachineJumpTableInfo *MJTI, const MachineBasicBlock *MBB, unsigned UID) const { assert(MBB && MBB->getNumber() >= 0 && "Invalid basic block"); @@ -1909,7 +1995,7 @@ void AsmPrinter::EmitJumpTableEntry(const MachineJumpTableInfo *MJTI, // with a relocation as gp-relative, e.g.: // .gprel32 LBB123 MCSymbol *MBBSym = MBB->getSymbol(); - OutStreamer->EmitGPRel32Value(MCSymbolRefExpr::create(MBBSym, OutContext)); + OutStreamer->emitGPRel32Value(MCSymbolRefExpr::create(MBBSym, OutContext)); return; } @@ -1918,7 +2004,7 @@ void AsmPrinter::EmitJumpTableEntry(const MachineJumpTableInfo *MJTI, // with a relocation as gp-relative, e.g.: // .gpdword LBB123 MCSymbol *MBBSym = MBB->getSymbol(); - OutStreamer->EmitGPRel64Value(MCSymbolRefExpr::create(MBBSym, OutContext)); + OutStreamer->emitGPRel64Value(MCSymbolRefExpr::create(MBBSym, OutContext)); return; } @@ -1946,16 +2032,16 @@ void AsmPrinter::EmitJumpTableEntry(const MachineJumpTableInfo *MJTI, assert(Value && "Unknown entry kind!"); unsigned EntrySize = MJTI->getEntrySize(getDataLayout()); - OutStreamer->EmitValue(Value, EntrySize); + OutStreamer->emitValue(Value, EntrySize); } /// EmitSpecialLLVMGlobal - Check to see if the specified global is a /// special global used by LLVM. If so, emit it and return true, otherwise /// do nothing and return false. -bool AsmPrinter::EmitSpecialLLVMGlobal(const GlobalVariable *GV) { +bool AsmPrinter::emitSpecialLLVMGlobal(const GlobalVariable *GV) { if (GV->getName() == "llvm.used") { if (MAI->hasNoDeadStrip()) // No need to emit this at all. - EmitLLVMUsedList(cast<ConstantArray>(GV->getInitializer())); + emitLLVMUsedList(cast<ConstantArray>(GV->getInitializer())); return true; } @@ -1969,14 +2055,14 @@ bool AsmPrinter::EmitSpecialLLVMGlobal(const GlobalVariable *GV) { assert(GV->hasInitializer() && "Not a special LLVM global!"); if (GV->getName() == "llvm.global_ctors") { - EmitXXStructorList(GV->getParent()->getDataLayout(), GV->getInitializer(), + emitXXStructorList(GV->getParent()->getDataLayout(), GV->getInitializer(), /* isCtor */ true); return true; } if (GV->getName() == "llvm.global_dtors") { - EmitXXStructorList(GV->getParent()->getDataLayout(), GV->getInitializer(), + emitXXStructorList(GV->getParent()->getDataLayout(), GV->getInitializer(), /* isCtor */ false); return true; @@ -1987,13 +2073,13 @@ bool AsmPrinter::EmitSpecialLLVMGlobal(const GlobalVariable *GV) { /// EmitLLVMUsedList - For targets that define a MAI::UsedDirective, mark each /// global in the specified llvm.used list. -void AsmPrinter::EmitLLVMUsedList(const ConstantArray *InitList) { +void AsmPrinter::emitLLVMUsedList(const ConstantArray *InitList) { // Should be an array of 'i8*'. for (unsigned i = 0, e = InitList->getNumOperands(); i != e; ++i) { const GlobalValue *GV = dyn_cast<GlobalValue>(InitList->getOperand(i)->stripPointerCasts()); if (GV) - OutStreamer->EmitSymbolAttribute(getSymbol(GV), MCSA_NoDeadStrip); + OutStreamer->emitSymbolAttribute(getSymbol(GV), MCSA_NoDeadStrip); } } @@ -2011,27 +2097,16 @@ struct Structor { /// EmitXXStructorList - Emit the ctor or dtor list taking into account the init /// priority. -void AsmPrinter::EmitXXStructorList(const DataLayout &DL, const Constant *List, +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; - // Sanity check the structors list. - const ConstantArray *InitList = dyn_cast<ConstantArray>(List); - if (!InitList) return; // Not an array! - StructType *ETy = dyn_cast<StructType>(InitList->getType()->getElementType()); - 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. SmallVector<Structor, 8> Structors; - for (Value *O : InitList->operands()) { - ConstantStruct *CS = dyn_cast<ConstantStruct>(O); - if (!CS) continue; // Malformed. + 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. ConstantInt *Priority = dyn_cast<ConstantInt>(CS->getOperand(0)); @@ -2069,12 +2144,12 @@ void AsmPrinter::EmitXXStructorList(const DataLayout &DL, const Constant *List, : Obj.getStaticDtorSection(S.Priority, KeySym)); OutStreamer->SwitchSection(OutputSection); if (OutStreamer->getCurrentSection() != OutStreamer->getPreviousSection()) - EmitAlignment(Align); - EmitXXStructor(DL, S.Func); + emitAlignment(Align); + emitXXStructor(DL, S.Func); } } -void AsmPrinter::EmitModuleIdents(Module &M) { +void AsmPrinter::emitModuleIdents(Module &M) { if (!MAI->hasIdentDirective()) return; @@ -2084,12 +2159,12 @@ void AsmPrinter::EmitModuleIdents(Module &M) { assert(N->getNumOperands() == 1 && "llvm.ident metadata entry can have only one operand"); const MDString *S = cast<MDString>(N->getOperand(0)); - OutStreamer->EmitIdent(S->getString()); + OutStreamer->emitIdent(S->getString()); } } } -void AsmPrinter::EmitModuleCommandLines(Module &M) { +void AsmPrinter::emitModuleCommandLines(Module &M) { MCSection *CommandLine = getObjFileLowering().getSectionForCommandLines(); if (!CommandLine) return; @@ -2100,14 +2175,14 @@ void AsmPrinter::EmitModuleCommandLines(Module &M) { OutStreamer->PushSection(); OutStreamer->SwitchSection(CommandLine); - OutStreamer->EmitZeros(1); + OutStreamer->emitZeros(1); for (unsigned i = 0, e = NMD->getNumOperands(); i != e; ++i) { const MDNode *N = NMD->getOperand(i); assert(N->getNumOperands() == 1 && "llvm.commandline metadata entry can have only one operand"); const MDString *S = cast<MDString>(N->getOperand(0)); - OutStreamer->EmitBytes(S->getString()); - OutStreamer->EmitZeros(1); + OutStreamer->emitBytes(S->getString()); + OutStreamer->emitZeros(1); } OutStreamer->PopSection(); } @@ -2118,29 +2193,23 @@ void AsmPrinter::EmitModuleCommandLines(Module &M) { /// Emit a byte directive and value. /// -void AsmPrinter::emitInt8(int Value) const { - OutStreamer->EmitIntValue(Value, 1); -} +void AsmPrinter::emitInt8(int Value) const { OutStreamer->emitInt8(Value); } /// Emit a short directive and value. -void AsmPrinter::emitInt16(int Value) const { - OutStreamer->EmitIntValue(Value, 2); -} +void AsmPrinter::emitInt16(int Value) const { OutStreamer->emitInt16(Value); } /// Emit a long directive and value. -void AsmPrinter::emitInt32(int Value) const { - OutStreamer->EmitIntValue(Value, 4); -} +void AsmPrinter::emitInt32(int Value) const { OutStreamer->emitInt32(Value); } /// Emit a long long directive and value. void AsmPrinter::emitInt64(uint64_t Value) const { - OutStreamer->EmitIntValue(Value, 8); + OutStreamer->emitInt64(Value); } /// Emit something like ".long Hi-Lo" where the size in bytes of the directive /// is specified by Size and Hi/Lo specify the labels. This implicitly uses /// .set if it avoids relocations. -void AsmPrinter::EmitLabelDifference(const MCSymbol *Hi, const MCSymbol *Lo, +void AsmPrinter::emitLabelDifference(const MCSymbol *Hi, const MCSymbol *Lo, unsigned Size) const { OutStreamer->emitAbsoluteSymbolDiff(Hi, Lo, Size); } @@ -2148,13 +2217,13 @@ void AsmPrinter::EmitLabelDifference(const MCSymbol *Hi, const MCSymbol *Lo, /// EmitLabelPlusOffset - Emit something like ".long Label+Offset" /// where the size in bytes of the directive is specified by Size and Label /// specifies the label. This implicitly uses .set if it is available. -void AsmPrinter::EmitLabelPlusOffset(const MCSymbol *Label, uint64_t Offset, +void AsmPrinter::emitLabelPlusOffset(const MCSymbol *Label, uint64_t Offset, unsigned Size, bool IsSectionRelative) const { if (MAI->needsDwarfSectionOffsetDirective() && IsSectionRelative) { OutStreamer->EmitCOFFSecRel32(Label, Offset); if (Size > 4) - OutStreamer->EmitZeros(Size - 4); + OutStreamer->emitZeros(Size - 4); return; } @@ -2164,7 +2233,7 @@ void AsmPrinter::EmitLabelPlusOffset(const MCSymbol *Label, uint64_t Offset, Expr = MCBinaryExpr::createAdd( Expr, MCConstantExpr::create(Offset, OutContext), OutContext); - OutStreamer->EmitValue(Expr, Size); + OutStreamer->emitValue(Expr, Size); } //===----------------------------------------------------------------------===// @@ -2173,17 +2242,17 @@ void AsmPrinter::EmitLabelPlusOffset(const MCSymbol *Label, uint64_t Offset, // two boundary. 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(Align Alignment, const GlobalObject *GV) const { +void AsmPrinter::emitAlignment(Align Alignment, const GlobalObject *GV) const { if (GV) Alignment = getGVAlignment(GV, GV->getParent()->getDataLayout(), Alignment); - if (Alignment == Align::None()) + if (Alignment == Align(1)) return; // 1-byte aligned: no need to emit alignment. if (getCurrentSection()->getKind().isText()) - OutStreamer->EmitCodeAlignment(Alignment.value()); + OutStreamer->emitCodeAlignment(Alignment.value()); else - OutStreamer->EmitValueToAlignment(Alignment.value()); + OutStreamer->emitValueToAlignment(Alignment.value()); } //===----------------------------------------------------------------------===// @@ -2211,23 +2280,22 @@ const MCExpr *AsmPrinter::lowerConstant(const Constant *CV) { } switch (CE->getOpcode()) { - default: + default: { // If the code isn't optimized, there may be outstanding folding // opportunities. Attempt to fold the expression using DataLayout as a // last resort before giving up. - if (Constant *C = ConstantFoldConstant(CE, getDataLayout())) - if (C != CE) - return lowerConstant(C); + Constant *C = ConstantFoldConstant(CE, getDataLayout()); + if (C != CE) + return lowerConstant(C); // Otherwise report the problem to the user. - { - std::string S; - raw_string_ostream OS(S); - OS << "Unsupported expression in static initializer: "; - CE->printAsOperand(OS, /*PrintType=*/false, - !MF ? nullptr : MF->getFunction().getParent()); - report_fatal_error(OS.str()); - } + std::string S; + raw_string_ostream OS(S); + OS << "Unsupported expression in static initializer: "; + CE->printAsOperand(OS, /*PrintType=*/false, + !MF ? nullptr : MF->getFunction().getParent()); + report_fatal_error(OS.str()); + } case Instruction::GetElementPtr: { // Generate a symbolic expression for the byte address APInt OffsetAI(getDataLayout().getPointerTypeSizeInBits(CE->getType()), 0); @@ -2413,7 +2481,7 @@ static void emitGlobalConstantDataSequential(const DataLayout &DL, // If this can be emitted with .ascii/.asciz, emit it as such. if (CDS->isString()) - return AP.OutStreamer->EmitBytes(CDS->getAsString()); + return AP.OutStreamer->emitBytes(CDS->getAsString()); // Otherwise, emit the values in successive locations. unsigned ElementByteSize = CDS->getElementByteSize(); @@ -2422,7 +2490,7 @@ static void emitGlobalConstantDataSequential(const DataLayout &DL, if (AP.isVerbose()) AP.OutStreamer->GetCommentOS() << format("0x%" PRIx64 "\n", CDS->getElementAsInteger(i)); - AP.OutStreamer->EmitIntValue(CDS->getElementAsInteger(i), + AP.OutStreamer->emitIntValue(CDS->getElementAsInteger(i), ElementByteSize); } } else { @@ -2432,11 +2500,11 @@ static void emitGlobalConstantDataSequential(const DataLayout &DL, } unsigned Size = DL.getTypeAllocSize(CDS->getType()); - unsigned EmittedSize = DL.getTypeAllocSize(CDS->getType()->getElementType()) * - CDS->getNumElements(); + unsigned EmittedSize = + DL.getTypeAllocSize(CDS->getElementType()) * CDS->getNumElements(); assert(EmittedSize <= Size && "Size cannot be less than EmittedSize!"); if (unsigned Padding = Size - EmittedSize) - AP.OutStreamer->EmitZeros(Padding); + AP.OutStreamer->emitZeros(Padding); } static void emitGlobalConstantArray(const DataLayout &DL, @@ -2467,7 +2535,7 @@ static void emitGlobalConstantVector(const DataLayout &DL, unsigned EmittedSize = DL.getTypeAllocSize(CV->getType()->getElementType()) * CV->getType()->getNumElements(); if (unsigned Padding = Size - EmittedSize) - AP.OutStreamer->EmitZeros(Padding); + AP.OutStreamer->emitZeros(Padding); } static void emitGlobalConstantStruct(const DataLayout &DL, @@ -2492,7 +2560,7 @@ static void emitGlobalConstantStruct(const DataLayout &DL, // Insert padding - this may include padding to increase the size of the // current field up to the ABI size (if the struct is not packed) as well // as padding to ensure that the next field starts at the right offset. - AP.OutStreamer->EmitZeros(PadSize); + AP.OutStreamer->emitZeros(PadSize); } assert(SizeSoFar == Layout->getSizeInBytes() && "Layout of constant struct may be incorrect!"); @@ -2524,22 +2592,22 @@ static void emitGlobalConstantFP(APFloat APF, Type *ET, AsmPrinter &AP) { int Chunk = API.getNumWords() - 1; if (TrailingBytes) - AP.OutStreamer->EmitIntValue(p[Chunk--], TrailingBytes); + AP.OutStreamer->emitIntValueInHexWithPadding(p[Chunk--], TrailingBytes); for (; Chunk >= 0; --Chunk) - AP.OutStreamer->EmitIntValue(p[Chunk], sizeof(uint64_t)); + AP.OutStreamer->emitIntValueInHexWithPadding(p[Chunk], sizeof(uint64_t)); } else { unsigned Chunk; for (Chunk = 0; Chunk < NumBytes / sizeof(uint64_t); ++Chunk) - AP.OutStreamer->EmitIntValue(p[Chunk], sizeof(uint64_t)); + AP.OutStreamer->emitIntValueInHexWithPadding(p[Chunk], sizeof(uint64_t)); if (TrailingBytes) - AP.OutStreamer->EmitIntValue(p[Chunk], TrailingBytes); + AP.OutStreamer->emitIntValueInHexWithPadding(p[Chunk], TrailingBytes); } // Emit the tail padding for the long double. const DataLayout &DL = AP.getDataLayout(); - AP.OutStreamer->EmitZeros(DL.getTypeAllocSize(ET) - DL.getTypeStoreSize(ET)); + AP.OutStreamer->emitZeros(DL.getTypeAllocSize(ET) - DL.getTypeStoreSize(ET)); } static void emitGlobalConstantFP(const ConstantFP *CFP, AsmPrinter &AP) { @@ -2570,9 +2638,10 @@ static void emitGlobalConstantLargeInt(const ConstantInt *CI, AsmPrinter &AP) { // [chunk1][chunk2] ... [chunkN]. // The most significant chunk is chunkN and it should be emitted first. // However, due to the alignment issue chunkN contains useless bits. - // Realign the chunks so that they contain only useless information: + // Realign the chunks so that they contain only useful information: // ExtraBits 0 1 (BitWidth / 64) - 1 // chu[nk1 chu][nk2 chu] ... [nkN-1 chunkN] + ExtraBitsSize = alignTo(ExtraBitsSize, 8); ExtraBits = Realigned.getRawData()[0] & (((uint64_t)-1) >> (64 - ExtraBitsSize)); Realigned.lshrInPlace(ExtraBitsSize); @@ -2586,19 +2655,19 @@ static void emitGlobalConstantLargeInt(const ConstantInt *CI, AsmPrinter &AP) { const uint64_t *RawData = Realigned.getRawData(); for (unsigned i = 0, e = BitWidth / 64; i != e; ++i) { uint64_t Val = DL.isBigEndian() ? RawData[e - i - 1] : RawData[i]; - AP.OutStreamer->EmitIntValue(Val, 8); + AP.OutStreamer->emitIntValue(Val, 8); } if (ExtraBitsSize) { // Emit the extra bits after the 64-bits chunks. // Emit a directive that fills the expected size. - uint64_t Size = AP.getDataLayout().getTypeAllocSize(CI->getType()); + uint64_t Size = AP.getDataLayout().getTypeStoreSize(CI->getType()); Size -= (BitWidth / 64) * 8; assert(Size && Size * 8 >= ExtraBitsSize && (ExtraBits & (((uint64_t)-1) >> (64 - ExtraBitsSize))) == ExtraBits && "Directive too small for extra bits."); - AP.OutStreamer->EmitIntValue(ExtraBits, Size); + AP.OutStreamer->emitIntValue(ExtraBits, Size); } } @@ -2705,30 +2774,32 @@ static void emitGlobalConstantImpl(const DataLayout &DL, const Constant *CV, BaseCV = dyn_cast<Constant>(CV->user_back()); if (isa<ConstantAggregateZero>(CV) || isa<UndefValue>(CV)) - return AP.OutStreamer->EmitZeros(Size); + return AP.OutStreamer->emitZeros(Size); if (const ConstantInt *CI = dyn_cast<ConstantInt>(CV)) { - switch (Size) { - case 1: - case 2: - case 4: - case 8: + const uint64_t StoreSize = DL.getTypeStoreSize(CV->getType()); + + if (StoreSize < 8) { if (AP.isVerbose()) AP.OutStreamer->GetCommentOS() << format("0x%" PRIx64 "\n", CI->getZExtValue()); - AP.OutStreamer->EmitIntValue(CI->getZExtValue(), Size); - return; - default: + AP.OutStreamer->emitIntValue(CI->getZExtValue(), StoreSize); + } else { emitGlobalConstantLargeInt(CI, AP); - return; } + + // Emit tail padding if needed + if (Size != StoreSize) + AP.OutStreamer->emitZeros(Size - StoreSize); + + return; } if (const ConstantFP *CFP = dyn_cast<ConstantFP>(CV)) return emitGlobalConstantFP(CFP, AP); if (isa<ConstantPointerNull>(CV)) { - AP.OutStreamer->EmitIntValue(0, Size); + AP.OutStreamer->emitIntValue(0, Size); return; } @@ -2752,7 +2823,7 @@ static void emitGlobalConstantImpl(const DataLayout &DL, const Constant *CV, // to emit the value in chunks. Try to constant fold the value and emit it // that way. Constant *New = ConstantFoldConstant(CE, DL); - if (New && New != CE) + if (New != CE) return emitGlobalConstantImpl(DL, New, AP); } } @@ -2770,22 +2841,22 @@ static void emitGlobalConstantImpl(const DataLayout &DL, const Constant *CV, if (AP.getObjFileLowering().supportIndirectSymViaGOTPCRel()) handleIndirectSymViaGOTPCRel(AP, &ME, BaseCV, Offset); - AP.OutStreamer->EmitValue(ME, Size); + AP.OutStreamer->emitValue(ME, Size); } /// EmitGlobalConstant - Print a general LLVM constant to the .s file. -void AsmPrinter::EmitGlobalConstant(const DataLayout &DL, const Constant *CV) { +void AsmPrinter::emitGlobalConstant(const DataLayout &DL, const Constant *CV) { uint64_t Size = DL.getTypeAllocSize(CV->getType()); if (Size) emitGlobalConstantImpl(DL, CV, *this); else if (MAI->hasSubsectionsViaSymbols()) { // If the global has zero size, emit a single byte so that two labels don't // look like they are at the same location. - OutStreamer->EmitIntValue(0, 1); + OutStreamer->emitIntValue(0, 1); } } -void AsmPrinter::EmitMachineConstantPoolValue(MachineConstantPoolValue *MCPV) { +void AsmPrinter::emitMachineConstantPoolValue(MachineConstantPoolValue *MCPV) { // Target doesn't support this yet! llvm_unreachable("Target does not support EmitMachineConstantPoolValue"); } @@ -2797,6 +2868,13 @@ void AsmPrinter::printOffset(int64_t Offset, raw_ostream &OS) const { OS << Offset; } +void AsmPrinter::emitNops(unsigned N) { + MCInst Nop; + MF->getSubtarget().getInstrInfo()->getNoop(Nop); + for (; N; --N) + EmitToStreamer(*OutStreamer, Nop); +} + //===----------------------------------------------------------------------===// // Symbol Lowering Routines. //===----------------------------------------------------------------------===// @@ -2822,12 +2900,13 @@ MCSymbol *AsmPrinter::GetCPISymbol(unsigned CPID) const { const DataLayout &DL = MF->getDataLayout(); SectionKind Kind = CPE.getSectionKind(&DL); const Constant *C = CPE.Val.ConstVal; - unsigned Align = CPE.Alignment; + Align Alignment = CPE.Alignment; if (const MCSectionCOFF *S = dyn_cast<MCSectionCOFF>( - getObjFileLowering().getSectionForConstant(DL, Kind, C, Align))) { + getObjFileLowering().getSectionForConstant(DL, Kind, C, + Alignment))) { if (MCSymbol *Sym = S->getCOMDATSymbol()) { if (Sym->isUndefined()) - OutStreamer->EmitSymbolAttribute(Sym, MCSA_Global); + OutStreamer->emitSymbolAttribute(Sym, MCSA_Global); return Sym; } } @@ -2929,10 +3008,10 @@ static void emitBasicBlockLoopComments(const MachineBasicBlock &MBB, PrintChildLoopComment(OS, Loop, AP.getFunctionNumber()); } -/// EmitBasicBlockStart - This method prints the label for the specified +/// emitBasicBlockStart - This method prints the label for the specified /// MachineBasicBlock, an alignment (if present) and a comment describing /// it if appropriate. -void AsmPrinter::EmitBasicBlockStart(const MachineBasicBlock &MBB) { +void AsmPrinter::emitBasicBlockStart(const MachineBasicBlock &MBB) { // End the previous funclet and start a new one. if (MBB.isEHFuncletEntry()) { for (const HandlerInfo &HI : Handlers) { @@ -2943,8 +3022,8 @@ void AsmPrinter::EmitBasicBlockStart(const MachineBasicBlock &MBB) { // Emit an alignment directive for this block, if needed. const Align Alignment = MBB.getAlignment(); - if (Alignment != Align::None()) - EmitAlignment(Alignment); + if (Alignment != Align(1)) + emitAlignment(Alignment); // 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 @@ -2959,7 +3038,7 @@ void AsmPrinter::EmitBasicBlockStart(const MachineBasicBlock &MBB) { // their corresponding BB's address taken in IR if (BB->hasAddressTaken()) for (MCSymbol *Sym : MMI->getAddrLabelSymbolToEmit(BB)) - OutStreamer->EmitLabel(Sym); + OutStreamer->emitLabel(Sym); } // Print some verbose block comments. @@ -2976,25 +3055,44 @@ void AsmPrinter::EmitBasicBlockStart(const MachineBasicBlock &MBB) { emitBasicBlockLoopComments(MBB, MLI, *this); } - // Print the main label for the block. if (MBB.pred_empty() || - (isBlockOnlyReachableByFallthrough(&MBB) && !MBB.isEHFuncletEntry() && - !MBB.hasLabelMustBeEmitted())) { + (!MF->hasBBLabels() && 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()) + if (isVerbose() && MBB.hasLabelMustBeEmitted()) { OutStreamer->AddComment("Label of block must be emitted"); - OutStreamer->EmitLabel(MBB.getSymbol()); + } + 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); } } -void AsmPrinter::EmitBasicBlockEnd(const MachineBasicBlock &MBB) {} +void AsmPrinter::emitBasicBlockEnd(const MachineBasicBlock &MBB) { + // Check if CFI information needs to be updated for this MBB with basic block + // sections. + if (MBB.isEndSection()) + for (const HandlerInfo &HI : Handlers) + HI.Handler->endBasicBlock(MBB); +} -void AsmPrinter::EmitVisibility(MCSymbol *Sym, unsigned Visibility, +void AsmPrinter::emitVisibility(MCSymbol *Sym, unsigned Visibility, bool IsDefinition) const { MCSymbolAttr Attr = MCSA_Invalid; @@ -3012,7 +3110,7 @@ void AsmPrinter::EmitVisibility(MCSymbol *Sym, unsigned Visibility, } if (Attr != MCSA_Invalid) - OutStreamer->EmitSymbolAttribute(Sym, Attr); + OutStreamer->emitSymbolAttribute(Sym, Attr); } /// isBlockOnlyReachableByFallthough - Return true if the basic block has @@ -3020,6 +3118,10 @@ void AsmPrinter::EmitVisibility(MCSymbol *Sym, unsigned Visibility, /// 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()) @@ -3069,11 +3171,10 @@ GCMetadataPrinter *AsmPrinter::GetOrCreateGCPrinter(GCStrategy &S) { auto Name = S.getName(); - for (GCMetadataPrinterRegistry::iterator - I = GCMetadataPrinterRegistry::begin(), - E = GCMetadataPrinterRegistry::end(); I != E; ++I) - if (Name == I->getName()) { - std::unique_ptr<GCMetadataPrinter> GMP = I->instantiate(); + for (const GCMetadataPrinterRegistry::entry &GCMetaPrinter : + GCMetadataPrinterRegistry::entries()) + if (Name == GCMetaPrinter.getName()) { + std::unique_ptr<GCMetadataPrinter> GMP = GCMetaPrinter.instantiate(); GMP->S = &S; auto IterBool = GCMap.insert(std::make_pair(&S, std::move(GMP))); return IterBool.first->second.get(); @@ -3111,18 +3212,15 @@ void AsmPrinterHandler::markFunctionEnd() {} // In the binary's "xray_instr_map" section, an array of these function entries // describes each instrumentation point. When XRay patches your code, the index // into this table will be given to your handler as a patch point identifier. -void AsmPrinter::XRayFunctionEntry::emit(int Bytes, MCStreamer *Out, - const MCSymbol *CurrentFnSym) const { - Out->EmitSymbolValue(Sled, Bytes); - Out->EmitSymbolValue(CurrentFnSym, Bytes); +void AsmPrinter::XRayFunctionEntry::emit(int Bytes, MCStreamer *Out) const { auto Kind8 = static_cast<uint8_t>(Kind); - Out->EmitBinaryData(StringRef(reinterpret_cast<const char *>(&Kind8), 1)); - Out->EmitBinaryData( + Out->emitBinaryData(StringRef(reinterpret_cast<const char *>(&Kind8), 1)); + Out->emitBinaryData( StringRef(reinterpret_cast<const char *>(&AlwaysInstrument), 1)); - Out->EmitBinaryData(StringRef(reinterpret_cast<const char *>(&Version), 1)); + 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); + Out->emitZeros(Padding); } void AsmPrinter::emitXRayTable() { @@ -3133,28 +3231,34 @@ void AsmPrinter::emitXRayTable() { const Function &F = MF->getFunction(); MCSection *InstMap = nullptr; MCSection *FnSledIndex = nullptr; - if (MF->getSubtarget().getTargetTriple().isOSBinFormatELF()) { - auto Associated = dyn_cast<MCSymbolELF>(CurrentFnSym); - assert(Associated != nullptr); - auto Flags = ELF::SHF_WRITE | ELF::SHF_ALLOC | ELF::SHF_LINK_ORDER; - std::string GroupName; + 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(); + 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; 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); + InstMap = OutContext.getELFSection("xray_instr_map", ELF::SHT_PROGBITS, + Flags, 0, GroupName, + MCSection::NonUniqueID, LinkedToSym); + + if (!TM.Options.XRayOmitFunctionIndex) + FnSledIndex = OutContext.getELFSection( + "xray_fn_idx", ELF::SHT_PROGBITS, Flags | ELF::SHF_WRITE, 0, + GroupName, MCSection::NonUniqueID, LinkedToSym); } else if (MF->getSubtarget().getTargetTriple().isOSBinFormatMachO()) { InstMap = OutContext.getMachOSection("__DATA", "xray_instr_map", 0, SectionKind::getReadOnlyWithRel()); - FnSledIndex = OutContext.getMachOSection("__DATA", "xray_fn_idx", 0, - SectionKind::getReadOnlyWithRel()); + if (!TM.Options.XRayOmitFunctionIndex) + FnSledIndex = OutContext.getMachOSection( + "__DATA", "xray_fn_idx", 0, SectionKind::getReadOnlyWithRel()); } else { llvm_unreachable("Unsupported target"); } @@ -3164,23 +3268,46 @@ void AsmPrinter::emitXRayTable() { // 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 // range of sleds associated with a function. + auto &Ctx = OutContext; MCSymbol *SledsStart = OutContext.createTempSymbol("xray_sleds_start", true); OutStreamer->SwitchSection(InstMap); - OutStreamer->EmitLabel(SledsStart); - for (const auto &Sled : Sleds) - Sled.emit(WordSizeBytes, OutStreamer.get(), CurrentFnSym); + 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); + } + Sled.emit(WordSizeBytes, OutStreamer.get()); + } MCSymbol *SledsEnd = OutContext.createTempSymbol("xray_sleds_end", true); - OutStreamer->EmitLabel(SledsEnd); + OutStreamer->emitLabel(SledsEnd); // We then emit a single entry in the index per function. We use the symbols // that bound the instrumentation map as the range for a specific function. // Each entry here will be 2 * word size aligned, as we're writing down two // pointers. This should work for both 32-bit and 64-bit platforms. - OutStreamer->SwitchSection(FnSledIndex); - OutStreamer->EmitCodeAlignment(2 * WordSizeBytes); - OutStreamer->EmitSymbolValue(SledsStart, WordSizeBytes, false); - OutStreamer->EmitSymbolValue(SledsEnd, WordSizeBytes, false); - OutStreamer->SwitchSection(PrevSection); + if (FnSledIndex) { + OutStreamer->SwitchSection(FnSledIndex); + OutStreamer->emitCodeAlignment(2 * WordSizeBytes); + OutStreamer->emitSymbolValue(SledsStart, WordSizeBytes, false); + OutStreamer->emitSymbolValue(SledsEnd, WordSizeBytes, false); + OutStreamer->SwitchSection(PrevSection); + } Sleds.clear(); } @@ -3199,36 +3326,36 @@ void AsmPrinter::recordSled(MCSymbol *Sled, const MachineInstr &MI, void AsmPrinter::emitPatchableFunctionEntries() { const Function &F = MF->getFunction(); - if (!F.hasFnAttribute("patchable-function-entry")) + unsigned PatchableFunctionPrefix = 0, PatchableFunctionEntry = 0; + (void)F.getFnAttribute("patchable-function-prefix") + .getValueAsString() + .getAsInteger(10, PatchableFunctionPrefix); + (void)F.getFnAttribute("patchable-function-entry") + .getValueAsString() + .getAsInteger(10, PatchableFunctionEntry); + if (!PatchableFunctionPrefix && !PatchableFunctionEntry) return; const unsigned PointerSize = getPointerSize(); if (TM.getTargetTriple().isOSBinFormatELF()) { auto Flags = ELF::SHF_WRITE | ELF::SHF_ALLOC; + const MCSymbolELF *LinkedToSym = nullptr; + StringRef GroupName; - // As of binutils 2.33, GNU as does not support section flag "o" or linkage - // field "unique". Use SHF_LINK_ORDER if we are using the integrated - // assembler. + // GNU as < 2.35 did not support section flag 'o'. Use SHF_LINK_ORDER only + // if we are using the integrated assembler. if (MAI->useIntegratedAssembler()) { Flags |= ELF::SHF_LINK_ORDER; - std::string GroupName; if (F.hasComdat()) { Flags |= ELF::SHF_GROUP; GroupName = F.getComdat()->getName(); } - MCSection *Section = getObjFileLowering().SectionForGlobal(&F, TM); - unsigned UniqueID = - PatchableFunctionEntryID - .try_emplace(Section, PatchableFunctionEntryID.size()) - .first->second; - OutStreamer->SwitchSection(OutContext.getELFSection( - "__patchable_function_entries", ELF::SHT_PROGBITS, Flags, 0, - GroupName, UniqueID, cast<MCSymbolELF>(CurrentFnSym))); - } else { - OutStreamer->SwitchSection(OutContext.getELFSection( - "__patchable_function_entries", ELF::SHT_PROGBITS, Flags)); + LinkedToSym = cast<MCSymbolELF>(CurrentFnSym); } - EmitAlignment(Align(PointerSize)); - OutStreamer->EmitSymbolValue(CurrentFnBegin, PointerSize); + OutStreamer->SwitchSection(OutContext.getELFSection( + "__patchable_function_entries", ELF::SHT_PROGBITS, Flags, 0, GroupName, + MCSection::NonUniqueID, LinkedToSym)); + emitAlignment(Align(PointerSize)); + OutStreamer->emitSymbolValue(CurrentPatchableFunctionEntrySym, PointerSize); } } |