Index: llvm/trunk/docs/CodeGenerator.rst =================================================================== --- llvm/trunk/docs/CodeGenerator.rst +++ llvm/trunk/docs/CodeGenerator.rst @@ -1589,6 +1589,17 @@ allocated in the function prologue. Functions with dynamic stack allocations are not included. +Emitting remark diagnostics in the object file +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +A section containing metadata on remark diagnostics will be emitted when +-remarks-section is passed. The section contains: + +* a magic number: "REMARKS\0" +* the version number: a little-endian uint64_t +* the absolute file path to the serialized remark diagnostics: a + null-terminated string. + VLIW Packetizer --------------- Index: llvm/trunk/docs/CommandGuide/llc.rst =================================================================== --- llvm/trunk/docs/CommandGuide/llc.rst +++ llvm/trunk/docs/CommandGuide/llc.rst @@ -140,6 +140,10 @@ in the function prologue. Functions with dynamic stack allocations are not included. +.. option:: -remarks-section + + Emit the .remarks (ELF) / __remarks (MachO) section which contains metadata + about remark diagnostics. Tuning/Configuration Options ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Index: llvm/trunk/include/llvm/CodeGen/AsmPrinter.h =================================================================== --- llvm/trunk/include/llvm/CodeGen/AsmPrinter.h +++ llvm/trunk/include/llvm/CodeGen/AsmPrinter.h @@ -315,6 +315,8 @@ void emitStackSizeSection(const MachineFunction &MF); + void emitRemarksSection(Module &M); + enum CFIMoveType { CFI_M_None, CFI_M_EH, CFI_M_Debug }; CFIMoveType needsCFIMoves() const; Index: llvm/trunk/include/llvm/MC/MCObjectFileInfo.h =================================================================== --- llvm/trunk/include/llvm/MC/MCObjectFileInfo.h +++ llvm/trunk/include/llvm/MC/MCObjectFileInfo.h @@ -159,6 +159,9 @@ /// FaultMap section. MCSection *FaultMapSection; + /// Remarks section. + MCSection *RemarksSection; + /// EH frame section. /// /// It is initialized on demand so it can be overwritten (with uniquing). @@ -314,6 +317,7 @@ MCSection *getStackMapSection() const { return StackMapSection; } MCSection *getFaultMapSection() const { return FaultMapSection; } + MCSection *getRemarksSection() const { return RemarksSection; } MCSection *getStackSizesSection(const MCSection &TextSec) const; Index: llvm/trunk/include/llvm/Remarks/Remark.h =================================================================== --- llvm/trunk/include/llvm/Remarks/Remark.h +++ llvm/trunk/include/llvm/Remarks/Remark.h @@ -23,6 +23,9 @@ namespace llvm { namespace remarks { +constexpr uint64_t Version = 0; +constexpr StringRef Magic("REMARKS", 7); + /// The debug location used to track a remark back to the source file. struct RemarkLocation { /// Absolute path of the source file corresponding to this remark. Index: llvm/trunk/lib/CodeGen/AsmPrinter/AsmPrinter.cpp =================================================================== --- llvm/trunk/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ llvm/trunk/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -78,6 +78,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" @@ -99,6 +100,7 @@ #include "llvm/MC/MCValue.h" #include "llvm/MC/SectionKind.h" #include "llvm/Pass.h" +#include "llvm/Remarks/Remark.h" #include "llvm/Support/Casting.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Compiler.h" @@ -141,6 +143,11 @@ STATISTIC(EmittedInsts, "Number of machine instrs printed"); +static cl::opt EnableRemarksSection( + "remarks-section", + cl::desc("Emit a section containing remark diagnostics metadata"), + cl::init(false)); + char AsmPrinter::ID = 0; using gcp_map_type = DenseMap>; @@ -1331,6 +1338,38 @@ } } +void AsmPrinter::emitRemarksSection(Module &M) { + RemarkStreamer *RS = M.getContext().getRemarkStreamer(); + if (!RS) + return; + + // 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 Version; + support::endian::write64le(Version.data(), remarks::Version); + OutStreamer->EmitBinaryData(StringRef(Version.data(), Version.size())); + + // 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 @@ -1362,6 +1401,12 @@ 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); Index: llvm/trunk/lib/MC/MCObjectFileInfo.cpp =================================================================== --- llvm/trunk/lib/MC/MCObjectFileInfo.cpp +++ llvm/trunk/lib/MC/MCObjectFileInfo.cpp @@ -290,6 +290,9 @@ FaultMapSection = Ctx->getMachOSection("__LLVM_FAULTMAPS", "__llvm_faultmaps", 0, SectionKind::getMetadata()); + RemarksSection = Ctx->getMachOSection( + "__LLVM", "__remarks", MachO::S_ATTR_DEBUG, SectionKind::getMetadata()); + TLSExtraDataSection = TLSTLVSection; } @@ -475,6 +478,9 @@ Ctx->getELFSection(".eh_frame", EHSectionType, EHSectionFlags); StackSizesSection = Ctx->getELFSection(".stack_sizes", ELF::SHT_PROGBITS, 0); + + RemarksSection = + Ctx->getELFSection(".remarks", ELF::SHT_PROGBITS, ELF::SHF_EXCLUDE); } void MCObjectFileInfo::initCOFFMCObjectFileInfo(const Triple &T) { Index: llvm/trunk/test/CodeGen/X86/remarks-section.ll =================================================================== --- llvm/trunk/test/CodeGen/X86/remarks-section.ll +++ llvm/trunk/test/CodeGen/X86/remarks-section.ll @@ -0,0 +1,33 @@ +; RUN: llc < %s -mtriple=x86_64-linux -remarks-section -pass-remarks-output=%/t.yaml | FileCheck -DPATH=%/t.yaml %s +; RUN: llc < %s -mtriple=x86_64-darwin -remarks-section -pass-remarks-output=%/t.yaml | FileCheck --check-prefix=CHECK-DARWIN -DPATH=%/t.yaml %s + +; CHECK-LABEL: func1: + +; CHECK: .section .remarks,"e",@progbits +; The magic number: +; CHECK-NEXT: .ascii "REMARKS" +; Null-terminator: +; CHECK-NEXT: .byte 0 +; The version: +; CHECK-NEXT: .byte 0x00, 0x00, 0x00, 0x00 +; CHECK-NEXT: .byte 0x00, 0x00, 0x00, 0x00 +; The remark file path: +; CHECK-NEXT: .ascii "[[PATH]]" +; Null-terminator: +; CHECK-NEXT: .byte 0 + +; CHECK-DARWIN: .section __LLVM,__remarks,regular,debug +; The magic number: +; CHECK-DARWIN-NEXT: .ascii "REMARKS" +; Null-terminator: +; CHECK-DARWIN-NEXT: .byte 0 +; The version: +; CHECK-DARWIN-NEXT: .byte 0x00, 0x00, 0x00, 0x00 +; CHECK-DARWIN-NEXT: .byte 0x00, 0x00, 0x00, 0x00 +; The remark file path: +; CHECK-DARWIN-NEXT: .ascii "[[PATH]]" +; Null-terminator: +; CHECK-DARWIN-NEXT: .byte 0 +define void @func1() { + ret void +}