[llvm] r349155 - Implement -frecord-command-line (-frecord-gcc-switches)

Scott Linder via llvm-commits llvm-commits at lists.llvm.org
Fri Dec 14 07:38:15 PST 2018


Author: scott.linder
Date: Fri Dec 14 07:38:15 2018
New Revision: 349155

URL: http://llvm.org/viewvc/llvm-project?rev=349155&view=rev
Log:
Implement -frecord-command-line (-frecord-gcc-switches)

Implement options in clang to enable recording the driver command-line
in an ELF section.

Implement a new special named metadata, llvm.commandline, to support
frontends embedding their command-line options in IR/ASM/ELF.

This differs from the GCC implementation in some key ways:

* In GCC there is only one command-line possible per compilation-unit,
  in LLVM it mirrors llvm.ident and multiple are allowed.
* In GCC individual options are separated by NULL bytes, in LLVM entire
  command-lines are separated by NULL bytes. The advantage of the GCC
  approach is to clearly delineate options in the face of embedded
  spaces. The advantage of the LLVM approach is to support merging
  multiple command-lines unambiguously, while handling embedded spaces
  with escaping.

Differential Revision: https://reviews.llvm.org/D54487
Clang Differential Revision: https://reviews.llvm.org/D54489

Added:
    llvm/trunk/test/CodeGen/X86/commandline-metadata.ll
    llvm/trunk/test/Linker/Inputs/commandline.a.ll
    llvm/trunk/test/Linker/Inputs/commandline.b.ll
    llvm/trunk/test/Linker/commandline.ll
    llvm/trunk/test/Verifier/commandline-meta1.ll
    llvm/trunk/test/Verifier/commandline-meta2.ll
    llvm/trunk/test/Verifier/commandline-meta3.ll
    llvm/trunk/test/Verifier/commandline-meta4.ll
Modified:
    llvm/trunk/include/llvm/CodeGen/AsmPrinter.h
    llvm/trunk/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h
    llvm/trunk/include/llvm/Target/TargetLoweringObjectFile.h
    llvm/trunk/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
    llvm/trunk/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
    llvm/trunk/lib/IR/Verifier.cpp

Modified: llvm/trunk/include/llvm/CodeGen/AsmPrinter.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/AsmPrinter.h?rev=349155&r1=349154&r2=349155&view=diff
==============================================================================
--- llvm/trunk/include/llvm/CodeGen/AsmPrinter.h (original)
+++ llvm/trunk/include/llvm/CodeGen/AsmPrinter.h Fri Dec 14 07:38:15 2018
@@ -656,6 +656,8 @@ private:
   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);
 

Modified: llvm/trunk/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h?rev=349155&r1=349154&r2=349155&view=diff
==============================================================================
--- llvm/trunk/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h (original)
+++ llvm/trunk/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h Fri Dec 14 07:38:15 2018
@@ -90,6 +90,8 @@ public:
   const MCExpr *lowerRelativeReference(const GlobalValue *LHS,
                                        const GlobalValue *RHS,
                                        const TargetMachine &TM) const override;
+
+  MCSection *getSectionForCommandLines() const override;
 };
 
 class TargetLoweringObjectFileMachO : public TargetLoweringObjectFile {

Modified: llvm/trunk/include/llvm/Target/TargetLoweringObjectFile.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Target/TargetLoweringObjectFile.h?rev=349155&r1=349154&r2=349155&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Target/TargetLoweringObjectFile.h (original)
+++ llvm/trunk/include/llvm/Target/TargetLoweringObjectFile.h Fri Dec 14 07:38:15 2018
@@ -201,6 +201,12 @@ public:
   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,

Modified: llvm/trunk/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/AsmPrinter.cpp?rev=349155&r1=349154&r2=349155&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/AsmPrinter/AsmPrinter.cpp (original)
+++ llvm/trunk/lib/CodeGen/AsmPrinter/AsmPrinter.cpp Fri Dec 14 07:38:15 2018
@@ -1499,6 +1499,9 @@ bool AsmPrinter::doFinalization(Module &
   // 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;
@@ -2008,6 +2011,29 @@ void AsmPrinter::EmitModuleIdents(Module
   }
 }
 
+void AsmPrinter::EmitModuleCommandLines(Module &M) {
+  MCSection *CommandLine = getObjFileLowering().getSectionForCommandLines();
+  if (!CommandLine)
+    return;
+
+  const NamedMDNode *NMD = M.getNamedMetadata("llvm.commandline");
+  if (!NMD || !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<MDString>(N->getOperand(0));
+    OutStreamer->EmitBytes(S->getString());
+    OutStreamer->EmitZeros(1);
+  }
+  OutStreamer->PopSection();
+}
+
 //===--------------------------------------------------------------------===//
 // Emission and print routines
 //

Modified: llvm/trunk/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/TargetLoweringObjectFileImpl.cpp?rev=349155&r1=349154&r2=349155&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/TargetLoweringObjectFileImpl.cpp (original)
+++ llvm/trunk/lib/CodeGen/TargetLoweringObjectFileImpl.cpp Fri Dec 14 07:38:15 2018
@@ -795,6 +795,14 @@ const MCExpr *TargetLoweringObjectFileEL
       MCSymbolRefExpr::create(TM.getSymbol(RHS), getContext()), getContext());
 }
 
+MCSection *TargetLoweringObjectFileELF::getSectionForCommandLines() const {
+  // Use ".GCC.command.line" since this feature is to support clang's
+  // -frecord-gcc-switches which in turn attempts to mimic GCC's switch of the
+  // same name.
+  return getContext().getELFSection(".GCC.command.line", ELF::SHT_PROGBITS,
+                                    ELF::SHF_MERGE | ELF::SHF_STRINGS, 1, "");
+}
+
 void
 TargetLoweringObjectFileELF::InitializeELF(bool UseInitArray_) {
   UseInitArray = UseInitArray_;

Modified: llvm/trunk/lib/IR/Verifier.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/Verifier.cpp?rev=349155&r1=349154&r2=349155&view=diff
==============================================================================
--- llvm/trunk/lib/IR/Verifier.cpp (original)
+++ llvm/trunk/lib/IR/Verifier.cpp Fri Dec 14 07:38:15 2018
@@ -386,6 +386,7 @@ public:
 
     visitModuleFlags(M);
     visitModuleIdents(M);
+    visitModuleCommandLines(M);
 
     verifyCompileUnits();
 
@@ -408,6 +409,7 @@ private:
   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<const MDString *, const MDNode *> &SeenIDs,
@@ -1311,6 +1313,24 @@ void Verifier::visitModuleIdents(const M
             "(the operand should be a string)"),
            N->getOperand(0));
   }
+}
+
+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<MDString>(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) {

Added: llvm/trunk/test/CodeGen/X86/commandline-metadata.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/commandline-metadata.ll?rev=349155&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/X86/commandline-metadata.ll (added)
+++ llvm/trunk/test/CodeGen/X86/commandline-metadata.ll Fri Dec 14 07:38:15 2018
@@ -0,0 +1,13 @@
+; RUN: llc -mtriple=x86_64-linux < %s | FileCheck %s
+; Verify that llvm.commandline metadata is emitted to a section named
+; .GCC.command.line with each line separated with null bytes.
+
+; CHECK: .section .GCC.command.line,"MS", at 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"}

Added: llvm/trunk/test/Linker/Inputs/commandline.a.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Linker/Inputs/commandline.a.ll?rev=349155&view=auto
==============================================================================
--- llvm/trunk/test/Linker/Inputs/commandline.a.ll (added)
+++ llvm/trunk/test/Linker/Inputs/commandline.a.ll Fri Dec 14 07:38:15 2018
@@ -0,0 +1,3 @@
+!llvm.commandline = !{!0, !1}
+!0 = !{!"compiler -v1"}
+!1 = !{!"compiler -v2"}

Added: llvm/trunk/test/Linker/Inputs/commandline.b.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Linker/Inputs/commandline.b.ll?rev=349155&view=auto
==============================================================================
--- llvm/trunk/test/Linker/Inputs/commandline.b.ll (added)
+++ llvm/trunk/test/Linker/Inputs/commandline.b.ll Fri Dec 14 07:38:15 2018
@@ -0,0 +1,2 @@
+!llvm.commandline = !{!0}
+!0 = !{!"compiler -v3"}

Added: llvm/trunk/test/Linker/commandline.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Linker/commandline.ll?rev=349155&view=auto
==============================================================================
--- llvm/trunk/test/Linker/commandline.ll (added)
+++ llvm/trunk/test/Linker/commandline.ll Fri Dec 14 07:38:15 2018
@@ -0,0 +1,8 @@
+; 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: !{{[0-2]}} = !{!"compiler -v1"}
+; CHECK-DAG: !{{[0-2]}} = !{!"compiler -v2"}
+; CHECK-DAG: !{{[0-2]}} = !{!"compiler -v3"}

Added: llvm/trunk/test/Verifier/commandline-meta1.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Verifier/commandline-meta1.ll?rev=349155&view=auto
==============================================================================
--- llvm/trunk/test/Verifier/commandline-meta1.ll (added)
+++ llvm/trunk/test/Verifier/commandline-meta1.ll Fri Dec 14 07:38:15 2018
@@ -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 have only one string.
+
+!llvm.commandline = !{!0}
+!0 = !{!"string1", !"string2"}
+; CHECK: assembly parsed, but does not verify as correct!
+; CHECK-NEXT: incorrect number of operands in llvm.commandline metadata
+; CHECK-NEXT: !0

Added: llvm/trunk/test/Verifier/commandline-meta2.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Verifier/commandline-meta2.ll?rev=349155&view=auto
==============================================================================
--- llvm/trunk/test/Verifier/commandline-meta2.ll (added)
+++ llvm/trunk/test/Verifier/commandline-meta2.ll Fri Dec 14 07:38:15 2018
@@ -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 = !{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

Added: llvm/trunk/test/Verifier/commandline-meta3.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Verifier/commandline-meta3.ll?rev=349155&view=auto
==============================================================================
--- llvm/trunk/test/Verifier/commandline-meta3.ll (added)
+++ llvm/trunk/test/Verifier/commandline-meta3.ll Fri Dec 14 07:38:15 2018
@@ -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

Added: llvm/trunk/test/Verifier/commandline-meta4.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Verifier/commandline-meta4.ll?rev=349155&view=auto
==============================================================================
--- llvm/trunk/test/Verifier/commandline-meta4.ll (added)
+++ llvm/trunk/test/Verifier/commandline-meta4.ll Fri Dec 14 07:38:15 2018
@@ -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)




More information about the llvm-commits mailing list