Index: include/llvm/CodeGen/AsmPrinter.h =================================================================== --- include/llvm/CodeGen/AsmPrinter.h +++ include/llvm/CodeGen/AsmPrinter.h @@ -656,6 +656,8 @@ void EmitLLVMUsedList(const ConstantArray *InitList); /// Emit llvm.ident metadata in an '.ident' directive. void EmitModuleIdents(Module &M); + /// Emit bytes for llvm.commandline metadata. + void EmitModuleCommandLines(Module &M); void EmitXXStructorList(const DataLayout &DL, const Constant *List, bool isCtor); Index: include/llvm/CodeGen/TargetLoweringObjectFileImpl.h =================================================================== --- include/llvm/CodeGen/TargetLoweringObjectFileImpl.h +++ include/llvm/CodeGen/TargetLoweringObjectFileImpl.h @@ -90,6 +90,8 @@ const MCExpr *lowerRelativeReference(const GlobalValue *LHS, const GlobalValue *RHS, const TargetMachine &TM) const override; + + MCSection *getSectionForCommandLines() const override; }; class TargetLoweringObjectFileMachO : public TargetLoweringObjectFile { Index: include/llvm/Target/TargetLoweringObjectFile.h =================================================================== --- include/llvm/Target/TargetLoweringObjectFile.h +++ include/llvm/Target/TargetLoweringObjectFile.h @@ -201,6 +201,12 @@ virtual void emitLinkerFlagsForUsed(raw_ostream &OS, const GlobalValue *GV) const {} + /// If supported, return the section to use for the llvm.commandline + /// metadata. Otherwise, return nullptr. + virtual MCSection *getSectionForCommandLines() const { + return nullptr; + } + protected: virtual MCSection *SelectSectionForGlobal(const GlobalObject *GO, SectionKind Kind, Index: lib/CodeGen/AsmPrinter/AsmPrinter.cpp =================================================================== --- lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -1500,6 +1500,9 @@ // Emit llvm.ident metadata in an '.ident' directive. EmitModuleIdents(M); + // Emit bytes for llvm.commandline metadata. + EmitModuleCommandLines(M); + // Emit __morestack address if needed for indirect calls. if (MMI->usesMorestackAddr()) { unsigned Align = 1; @@ -2009,6 +2012,30 @@ } } +void AsmPrinter::EmitModuleCommandLines(Module &M) { + MCSection *CommandLine = getObjFileLowering().getSectionForCommandLines(); + if (!CommandLine) + return; + + if (const NamedMDNode *NMD = M.getNamedMetadata("llvm.commandline")) { + if (!NMD->getNumOperands()) + return; + + OutStreamer->PushSection(); + OutStreamer->SwitchSection(CommandLine); + 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(N->getOperand(0)); + OutStreamer->EmitBytes(S->getString()); + OutStreamer->EmitZeros(1); + } + OutStreamer->PopSection(); + } +} + //===--------------------------------------------------------------------===// // Emission and print routines // Index: lib/CodeGen/TargetLoweringObjectFileImpl.cpp =================================================================== --- lib/CodeGen/TargetLoweringObjectFileImpl.cpp +++ lib/CodeGen/TargetLoweringObjectFileImpl.cpp @@ -795,6 +795,11 @@ MCSymbolRefExpr::create(TM.getSymbol(RHS), getContext()), getContext()); } +MCSection *TargetLoweringObjectFileELF::getSectionForCommandLines() const { + return getContext().getELFSection(".LLVM.command.line", ELF::SHT_PROGBITS, + ELF::SHF_MERGE | ELF::SHF_STRINGS, 1, ""); +} + void TargetLoweringObjectFileELF::InitializeELF(bool UseInitArray_) { UseInitArray = UseInitArray_; Index: lib/IR/Verifier.cpp =================================================================== --- lib/IR/Verifier.cpp +++ lib/IR/Verifier.cpp @@ -383,6 +383,7 @@ visitModuleFlags(M); visitModuleIdents(M); + visitModuleCommandLines(M); verifyCompileUnits(); @@ -405,6 +406,7 @@ void visitValueAsMetadata(const ValueAsMetadata &MD, Function *F); void visitComdat(const Comdat &C); void visitModuleIdents(const Module &M); + void visitModuleCommandLines(const Module &M); void visitModuleFlags(const Module &M); void visitModuleFlag(const MDNode *Op, DenseMap &SeenIDs, @@ -1303,6 +1305,24 @@ } } +void Verifier::visitModuleCommandLines(const Module &M) { + const NamedMDNode *CommandLines = M.getNamedMetadata("llvm.commandline"); + if (!CommandLines) + return; + + // llvm.commandline takes a list of metadata entry. Each entry has only one + // string. Scan each llvm.commandline entry and make sure that this + // requirement is met. + for (const MDNode *N : CommandLines->operands()) { + Assert(N->getNumOperands() == 1, + "incorrect number of operands in llvm.commandline metadata", N); + Assert(dyn_cast_or_null(N->getOperand(0)), + ("invalid value for llvm.commandline metadata entry operand" + "(the operand should be a string)"), + N->getOperand(0)); + } +} + void Verifier::visitModuleFlags(const Module &M) { const NamedMDNode *Flags = M.getModuleFlagsMetadata(); if (!Flags) return; Index: test/CodeGen/X86/commandline-metadata.ll =================================================================== --- /dev/null +++ test/CodeGen/X86/commandline-metadata.ll @@ -0,0 +1,13 @@ +; RUN: llc -mtriple=x86_64-linux < %s | FileCheck %s +; Verify that llvm.commandline metadata is emitted to a section named +; .LLVM.command.line with each line separated with null bytes. + +; CHECK: .section .LLVM.command.line,"MS",@progbits,1 +; CHECK-NEXT: .zero 1 +; CHECK-NEXT: .ascii "clang -command -line" +; CHECK-NEXT: .zero 1 +; CHECK-NEXT: .ascii "something else" +; CHECK-NEXT: .zero 1 +!llvm.commandline = !{!0, !1} +!0 = !{!"clang -command -line"} +!1 = !{!"something else"} Index: test/Linker/Inputs/commandline.a.ll =================================================================== --- /dev/null +++ test/Linker/Inputs/commandline.a.ll @@ -0,0 +1,3 @@ +!llvm.commandline = !{!0, !1} +!0 = !{!"compiler -v1"} +!1 = !{!"compiler -v2"} Index: test/Linker/Inputs/commandline.b.ll =================================================================== --- /dev/null +++ test/Linker/Inputs/commandline.b.ll @@ -0,0 +1,2 @@ +!llvm.commandline = !{!0} +!0 = !{!"compiler -v3"} Index: test/Linker/commandline.ll =================================================================== --- /dev/null +++ test/Linker/commandline.ll @@ -0,0 +1,9 @@ +; RUN: llvm-link %S/Inputs/commandline.a.ll %S/Inputs/commandline.b.ll -S | FileCheck %s + +; Verify that multiple input llvm.commandline metadata are linked together. + +; CHECK-DAG: !llvm.commandline = !{!0, !1, !2} +; CHECK-DAG: "compiler -v1" +; CHECK-DAG: "compiler -v2" +; CHECK-DAG: "compiler -v3" + Index: test/Verifier/commandline-meta1.ll =================================================================== --- /dev/null +++ test/Verifier/commandline-meta1.ll @@ -0,0 +1,12 @@ +; RUN: not llvm-as < %s -o /dev/null 2>&1 | FileCheck %s +; Verify that llvm.commandline is properly structured. +; llvm.commandline takes a list of metadata entries. +; Each metadata entry can have only one string. + +!llvm.commandline = !{!0, !1} +!0 = !{!"commandline string"} +!1 = !{!"string1", !"string2"} +; CHECK: assembly parsed, but does not verify as correct! +; CHECK-NEXT: incorrect number of operands in llvm.commandline metadata +; CHECK-NEXT: !1 + Index: test/Verifier/commandline-meta2.ll =================================================================== --- /dev/null +++ test/Verifier/commandline-meta2.ll @@ -0,0 +1,13 @@ +; RUN: not llvm-as < %s -o /dev/null 2>&1 | FileCheck %s +; Verify that llvm.commandline is properly structured. +; llvm.commandline takes a list of metadata entries. +; Each metadata entry can contain one string only. + +!llvm.commandline = !{!0, !1, !2, !3} +!0 = !{!"str1"} +!1 = !{!"str2"} +!2 = !{!"str3"} +!3 = !{i32 1} +; CHECK: assembly parsed, but does not verify as correct! +; CHECK-NEXT: invalid value for llvm.commandline metadata entry operand(the operand should be a string) +; CHECK-NEXT: i32 1 Index: test/Verifier/commandline-meta3.ll =================================================================== --- /dev/null +++ test/Verifier/commandline-meta3.ll @@ -0,0 +1,10 @@ +; RUN: not llvm-as < %s -o /dev/null 2>&1 | FileCheck %s +; Verify that llvm.commandline is properly structured. +; llvm.commandline takes a list of metadata entries. +; Each metadata entry can contain one string only. + +!llvm.commandline = !{!0} +!0 = !{!{!"nested metadata"}} +; CHECK: assembly parsed, but does not verify as correct! +; CHECK-NEXT: invalid value for llvm.commandline metadata entry operand(the operand should be a string) +; CHECK-NEXT: !1 Index: test/Verifier/commandline-meta4.ll =================================================================== --- /dev/null +++ test/Verifier/commandline-meta4.ll @@ -0,0 +1,9 @@ +; RUN: not llvm-as < %s -o /dev/null 2>&1 | FileCheck %s +; Verify that llvm.commandline is properly structured. +; llvm.commandline takes a list of metadata entries. +; Each metadata entry can contain one string only. + +!llvm.commandline = !{!0} +!0 = !{null} +; CHECK: assembly parsed, but does not verify as correct! +; CHECK-NEXT: invalid value for llvm.commandline metadata entry operand(the operand should be a string)