Skip to content

Commit de6beb0

Browse files
committedDec 14, 2018
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 llvm-svn: 349155
1 parent eed7b2e commit de6beb0

24 files changed

+222
-10
lines changed
 

Diff for: ‎clang/docs/ClangCommandLineReference.rst

+11-1
Original file line numberDiff line numberDiff line change
@@ -792,6 +792,16 @@ Don't use blacklist file for sanitizers
792792

793793
.. option:: -fparse-all-comments
794794

795+
.. option:: -frecord-command-line, -frecord-gcc-switches, -fno-record-command-line, -fno-record-gcc-switches
796+
797+
Generate a section named ".GCC.command.line" containing the clang driver
798+
command-line. After linking, the section may contain multiple command lines,
799+
which will be individually terminated by null bytes. Separate arguments within
800+
a command line are combined with spaces; spaces and backslashes within an
801+
argument are escaped with backslashes. This format differs from the format of
802+
the equivalent section produced by GCC with the -frecord-gcc-switches flag.
803+
This option is currently only supported on ELF targets.
804+
795805
.. option:: -fsanitize-address-field-padding=<arg>
796806

797807
Level of field padding for AddressSanitizer
@@ -2831,7 +2841,7 @@ Embed source text in DWARF debug sections
28312841

28322842
.. option:: -gpubnames, -gno-pubnames
28332843

2834-
.. option:: -grecord-gcc-switches, -gno-record-gcc-switches
2844+
.. option:: -grecord-command-line, -grecord-gcc-switches, -gno-record-command-line, -gno-record-gcc-switches
28352845

28362846
.. option:: -gsplit-dwarf
28372847

Diff for: ‎clang/include/clang/Basic/CodeGenOptions.h

+4
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,10 @@ class CodeGenOptions : public CodeGenOptionsBase {
148148
/// non-empty.
149149
std::string DwarfDebugFlags;
150150

151+
/// The string containing the commandline for the llvm.commandline metadata,
152+
/// if non-empty.
153+
std::string RecordCommandLine;
154+
151155
std::map<std::string, std::string> DebugPrefixMap;
152156

153157
/// The ABI to use for passing floating point arguments.

Diff for: ‎clang/include/clang/Driver/CC1Options.td

+2
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,8 @@ def fdebug_compilation_dir : Separate<["-"], "fdebug-compilation-dir">,
167167
HelpText<"The compilation directory to embed in the debug info.">;
168168
def dwarf_debug_flags : Separate<["-"], "dwarf-debug-flags">,
169169
HelpText<"The string to embed in the Dwarf debug flags record.">;
170+
def record_command_line : Separate<["-"], "record-command-line">,
171+
HelpText<"The string to embed in the .LLVM.command.line section.">;
170172
def compress_debug_sections : Flag<["-", "--"], "compress-debug-sections">,
171173
HelpText<"DWARF debug sections compression">;
172174
def compress_debug_sections_EQ : Joined<["-"], "compress-debug-sections=">,

Diff for: ‎clang/include/clang/Driver/Options.td

+11-2
Original file line numberDiff line numberDiff line change
@@ -799,6 +799,12 @@ def fcomment_block_commands : CommaJoined<["-"], "fcomment-block-commands=">, Gr
799799
HelpText<"Treat each comma separated argument in <arg> as a documentation comment block command">,
800800
MetaVarName<"<arg>">;
801801
def fparse_all_comments : Flag<["-"], "fparse-all-comments">, Group<f_clang_Group>, Flags<[CC1Option]>;
802+
def frecord_command_line : Flag<["-"], "frecord-command-line">,
803+
Group<f_clang_Group>;
804+
def fno_record_command_line : Flag<["-"], "fno-record-command-line">,
805+
Group<f_clang_Group>;
806+
def : Flag<["-"], "frecord-gcc-switches">, Alias<frecord_command_line>;
807+
def : Flag<["-"], "fno-record-gcc-switches">, Alias<fno_record_command_line>;
802808
def fcommon : Flag<["-"], "fcommon">, Group<f_Group>;
803809
def fcompile_resource_EQ : Joined<["-"], "fcompile-resource=">, Group<f_Group>;
804810
def fcomplete_member_pointers : Flag<["-"], "fcomplete-member-pointers">, Group<f_clang_Group>,
@@ -1854,9 +1860,12 @@ def gcoff : Joined<["-"], "gcoff">, Group<g_Group>, Flags<[Unsupported]>;
18541860
def gxcoff : Joined<["-"], "gxcoff">, Group<g_Group>, Flags<[Unsupported]>;
18551861
def gvms : Joined<["-"], "gvms">, Group<g_Group>, Flags<[Unsupported]>;
18561862
def gtoggle : Flag<["-"], "gtoggle">, Group<g_flags_Group>, Flags<[Unsupported]>;
1857-
def grecord_gcc_switches : Flag<["-"], "grecord-gcc-switches">, Group<g_flags_Group>;
1858-
def gno_record_gcc_switches : Flag<["-"], "gno-record-gcc-switches">,
1863+
def grecord_command_line : Flag<["-"], "grecord-command-line">,
18591864
Group<g_flags_Group>;
1865+
def gno_record_command_line : Flag<["-"], "gno-record-command-line">,
1866+
Group<g_flags_Group>;
1867+
def : Flag<["-"], "grecord-gcc-switches">, Alias<grecord_command_line>;
1868+
def : Flag<["-"], "gno-record-gcc-switches">, Alias<gno_record_command_line>;
18601869
def gstrict_dwarf : Flag<["-"], "gstrict-dwarf">, Group<g_flags_Group>;
18611870
def gno_strict_dwarf : Flag<["-"], "gno-strict-dwarf">, Group<g_flags_Group>;
18621871
def gcolumn_info : Flag<["-"], "gcolumn-info">, Group<g_flags_Group>, Flags<[CoreOption]>;

Diff for: ‎clang/lib/CodeGen/CodeGenModule.cpp

+13
Original file line numberDiff line numberDiff line change
@@ -590,6 +590,9 @@ void CodeGenModule::Release() {
590590
if (getCodeGenOpts().EmitVersionIdentMetadata)
591591
EmitVersionIdentMetadata();
592592

593+
if (!getCodeGenOpts().RecordCommandLine.empty())
594+
EmitCommandLineMetadata();
595+
593596
EmitTargetMetadata();
594597
}
595598

@@ -5217,6 +5220,16 @@ void CodeGenModule::EmitVersionIdentMetadata() {
52175220
IdentMetadata->addOperand(llvm::MDNode::get(Ctx, IdentNode));
52185221
}
52195222

5223+
void CodeGenModule::EmitCommandLineMetadata() {
5224+
llvm::NamedMDNode *CommandLineMetadata =
5225+
TheModule.getOrInsertNamedMetadata("llvm.commandline");
5226+
std::string CommandLine = getCodeGenOpts().RecordCommandLine;
5227+
llvm::LLVMContext &Ctx = TheModule.getContext();
5228+
5229+
llvm::Metadata *CommandLineNode[] = {llvm::MDString::get(Ctx, CommandLine)};
5230+
CommandLineMetadata->addOperand(llvm::MDNode::get(Ctx, CommandLineNode));
5231+
}
5232+
52205233
void CodeGenModule::EmitTargetMetadata() {
52215234
// Warning, new MangledDeclNames may be appended within this loop.
52225235
// We rely on MapVector insertions adding new elements to the end

Diff for: ‎clang/lib/CodeGen/CodeGenModule.h

+3
Original file line numberDiff line numberDiff line change
@@ -1408,6 +1408,9 @@ class CodeGenModule : public CodeGenTypeCache {
14081408
/// Emit the Clang version as llvm.ident metadata.
14091409
void EmitVersionIdentMetadata();
14101410

1411+
/// Emit the Clang commandline as llvm.commandline metadata.
1412+
void EmitCommandLineMetadata();
1413+
14111414
/// Emits target specific Metadata for global declarations.
14121415
void EmitTargetMetadata();
14131416

Diff for: ‎clang/lib/Driver/ToolChains/Clang.cpp

+22-7
Original file line numberDiff line numberDiff line change
@@ -5063,14 +5063,22 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
50635063

50645064
const char *Exec = D.getClangProgramPath();
50655065

5066-
// Optionally embed the -cc1 level arguments into the debug info, for build
5067-
// analysis.
5066+
// Optionally embed the -cc1 level arguments into the debug info or a
5067+
// section, for build analysis.
50685068
// Also record command line arguments into the debug info if
50695069
// -grecord-gcc-switches options is set on.
50705070
// By default, -gno-record-gcc-switches is set on and no recording.
5071-
if (TC.UseDwarfDebugFlags() ||
5072-
Args.hasFlag(options::OPT_grecord_gcc_switches,
5073-
options::OPT_gno_record_gcc_switches, false)) {
5071+
auto GRecordSwitches =
5072+
Args.hasFlag(options::OPT_grecord_command_line,
5073+
options::OPT_gno_record_command_line, false);
5074+
auto FRecordSwitches =
5075+
Args.hasFlag(options::OPT_frecord_command_line,
5076+
options::OPT_fno_record_command_line, false);
5077+
if (FRecordSwitches && !Triple.isOSBinFormatELF())
5078+
D.Diag(diag::err_drv_unsupported_opt_for_target)
5079+
<< Args.getLastArg(options::OPT_frecord_command_line)->getAsString(Args)
5080+
<< TripleStr;
5081+
if (TC.UseDwarfDebugFlags() || GRecordSwitches || FRecordSwitches) {
50745082
ArgStringList OriginalArgs;
50755083
for (const auto &Arg : Args)
50765084
Arg->render(Args, OriginalArgs);
@@ -5083,8 +5091,15 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
50835091
Flags += " ";
50845092
Flags += EscapedArg;
50855093
}
5086-
CmdArgs.push_back("-dwarf-debug-flags");
5087-
CmdArgs.push_back(Args.MakeArgString(Flags));
5094+
auto FlagsArgString = Args.MakeArgString(Flags);
5095+
if (TC.UseDwarfDebugFlags() || GRecordSwitches) {
5096+
CmdArgs.push_back("-dwarf-debug-flags");
5097+
CmdArgs.push_back(FlagsArgString);
5098+
}
5099+
if (FRecordSwitches) {
5100+
CmdArgs.push_back("-record-command-line");
5101+
CmdArgs.push_back(FlagsArgString);
5102+
}
50885103
}
50895104

50905105
// Host-side cuda compilation receives all device-side outputs in a single

Diff for: ‎clang/lib/Frontend/CompilerInvocation.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -755,6 +755,7 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
755755
Args.hasFlag(OPT_ffine_grained_bitfield_accesses,
756756
OPT_fno_fine_grained_bitfield_accesses, false);
757757
Opts.DwarfDebugFlags = Args.getLastArgValue(OPT_dwarf_debug_flags);
758+
Opts.RecordCommandLine = Args.getLastArgValue(OPT_record_command_line);
758759
Opts.MergeAllConstants = Args.hasArg(OPT_fmerge_all_constants);
759760
Opts.NoCommon = Args.hasArg(OPT_fno_common);
760761
Opts.NoImplicitFloat = Args.hasArg(OPT_no_implicit_float);

Diff for: ‎clang/test/Driver/clang_f_opts.c

+15
Original file line numberDiff line numberDiff line change
@@ -542,3 +542,18 @@
542542
// RUN: %clang -### -S -fomit-frame-pointer -fno-omit-frame-pointer -pg %s 2>&1 | FileCheck -check-prefix=CHECK-MIX-NO-OMIT-FP-PG %s
543543
// CHECK-NO-MIX-OMIT-FP-PG: '-fomit-frame-pointer' not allowed with '-pg'
544544
// CHECK-MIX-NO-OMIT-FP-PG-NOT: '-fomit-frame-pointer' not allowed with '-pg'
545+
546+
// RUN: %clang -### -S -target x86_64-unknown-linux -frecord-gcc-switches %s 2>&1 | FileCheck -check-prefix=CHECK-RECORD-GCC-SWITCHES %s
547+
// RUN: %clang -### -S -target x86_64-unknown-linux -fno-record-gcc-switches %s 2>&1 | FileCheck -check-prefix=CHECK-NO-RECORD-GCC-SWITCHES %s
548+
// RUN: %clang -### -S -target x86_64-unknown-linux -fno-record-gcc-switches -frecord-gcc-switches %s 2>&1 | FileCheck -check-prefix=CHECK-RECORD-GCC-SWITCHES %s
549+
// RUN: %clang -### -S -target x86_64-unknown-linux -frecord-gcc-switches -fno-record-gcc-switches %s 2>&1 | FileCheck -check-prefix=CHECK-NO-RECORD-GCC-SWITCHES %s
550+
// RUN: %clang -### -S -target x86_64-unknown-linux -frecord-command-line %s 2>&1 | FileCheck -check-prefix=CHECK-RECORD-GCC-SWITCHES %s
551+
// RUN: %clang -### -S -target x86_64-unknown-linux -fno-record-command-line %s 2>&1 | FileCheck -check-prefix=CHECK-NO-RECORD-GCC-SWITCHES %s
552+
// RUN: %clang -### -S -target x86_64-unknown-linux -fno-record-command-line -frecord-command-line %s 2>&1 | FileCheck -check-prefix=CHECK-RECORD-GCC-SWITCHES %s
553+
// RUN: %clang -### -S -target x86_64-unknown-linux -frecord-command-line -fno-record-command-line %s 2>&1 | FileCheck -check-prefix=CHECK-NO-RECORD-GCC-SWITCHES %s
554+
// Test with a couple examples of non-ELF object file formats
555+
// RUN: %clang -### -S -target x86_64-unknown-macosx -frecord-command-line %s 2>&1 | FileCheck -check-prefix=CHECK-RECORD-GCC-SWITCHES-ERROR %s
556+
// RUN: %clang -### -S -target x86_64-unknown-windows -frecord-command-line %s 2>&1 | FileCheck -check-prefix=CHECK-RECORD-GCC-SWITCHES-ERROR %s
557+
// CHECK-RECORD-GCC-SWITCHES: "-record-command-line"
558+
// CHECK-NO-RECORD-GCC-SWITCHES-NOT: "-record-command-line"
559+
// CHECK-RECORD-GCC-SWITCHES-ERROR: error: unsupported option '-frecord-command-line' for target

Diff for: ‎clang/test/Driver/debug-options.c

+11
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,17 @@
157157
// RUN: %clang -### -c -O3 -ffunction-sections -grecord-gcc-switches %s 2>&1 \
158158
// | FileCheck -check-prefix=GRECORD_OPT %s
159159
//
160+
// RUN: %clang -### -c -grecord-command-line %s 2>&1 \
161+
// | FileCheck -check-prefix=GRECORD %s
162+
// RUN: %clang -### -c -gno-record-command-line %s 2>&1 \
163+
// | FileCheck -check-prefix=GNO_RECORD %s
164+
// RUN: %clang -### -c -grecord-command-line -gno-record-command-line %s 2>&1 \
165+
// | FileCheck -check-prefix=GNO_RECORD %s/
166+
// RUN: %clang -### -c -grecord-command-line -o - %s 2>&1 \
167+
// | FileCheck -check-prefix=GRECORD_O %s
168+
// RUN: %clang -### -c -O3 -ffunction-sections -grecord-command-line %s 2>&1 \
169+
// | FileCheck -check-prefix=GRECORD_OPT %s
170+
//
160171
// RUN: %clang -### -c -gstrict-dwarf -gno-strict-dwarf %s 2>&1 \
161172
// RUN: | FileCheck -check-prefix=GIGNORE %s
162173
//

Diff for: ‎llvm/include/llvm/CodeGen/AsmPrinter.h

+2
Original file line numberDiff line numberDiff line change
@@ -656,6 +656,8 @@ class AsmPrinter : public MachineFunctionPass {
656656
void EmitLLVMUsedList(const ConstantArray *InitList);
657657
/// Emit llvm.ident metadata in an '.ident' directive.
658658
void EmitModuleIdents(Module &M);
659+
/// Emit bytes for llvm.commandline metadata.
660+
void EmitModuleCommandLines(Module &M);
659661
void EmitXXStructorList(const DataLayout &DL, const Constant *List,
660662
bool isCtor);
661663

Diff for: ‎llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h

+2
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,8 @@ class TargetLoweringObjectFileELF : public TargetLoweringObjectFile {
9090
const MCExpr *lowerRelativeReference(const GlobalValue *LHS,
9191
const GlobalValue *RHS,
9292
const TargetMachine &TM) const override;
93+
94+
MCSection *getSectionForCommandLines() const override;
9395
};
9496

9597
class TargetLoweringObjectFileMachO : public TargetLoweringObjectFile {

Diff for: ‎llvm/include/llvm/Target/TargetLoweringObjectFile.h

+6
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,12 @@ class TargetLoweringObjectFile : public MCObjectFileInfo {
201201
virtual void emitLinkerFlagsForUsed(raw_ostream &OS,
202202
const GlobalValue *GV) const {}
203203

204+
/// If supported, return the section to use for the llvm.commandline
205+
/// metadata. Otherwise, return nullptr.
206+
virtual MCSection *getSectionForCommandLines() const {
207+
return nullptr;
208+
}
209+
204210
protected:
205211
virtual MCSection *SelectSectionForGlobal(const GlobalObject *GO,
206212
SectionKind Kind,

Diff for: ‎llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp

+26
Original file line numberDiff line numberDiff line change
@@ -1499,6 +1499,9 @@ bool AsmPrinter::doFinalization(Module &M) {
14991499
// Emit llvm.ident metadata in an '.ident' directive.
15001500
EmitModuleIdents(M);
15011501

1502+
// Emit bytes for llvm.commandline metadata.
1503+
EmitModuleCommandLines(M);
1504+
15021505
// Emit __morestack address if needed for indirect calls.
15031506
if (MMI->usesMorestackAddr()) {
15041507
unsigned Align = 1;
@@ -2008,6 +2011,29 @@ void AsmPrinter::EmitModuleIdents(Module &M) {
20082011
}
20092012
}
20102013

2014+
void AsmPrinter::EmitModuleCommandLines(Module &M) {
2015+
MCSection *CommandLine = getObjFileLowering().getSectionForCommandLines();
2016+
if (!CommandLine)
2017+
return;
2018+
2019+
const NamedMDNode *NMD = M.getNamedMetadata("llvm.commandline");
2020+
if (!NMD || !NMD->getNumOperands())
2021+
return;
2022+
2023+
OutStreamer->PushSection();
2024+
OutStreamer->SwitchSection(CommandLine);
2025+
OutStreamer->EmitZeros(1);
2026+
for (unsigned i = 0, e = NMD->getNumOperands(); i != e; ++i) {
2027+
const MDNode *N = NMD->getOperand(i);
2028+
assert(N->getNumOperands() == 1 &&
2029+
"llvm.commandline metadata entry can have only one operand");
2030+
const MDString *S = cast<MDString>(N->getOperand(0));
2031+
OutStreamer->EmitBytes(S->getString());
2032+
OutStreamer->EmitZeros(1);
2033+
}
2034+
OutStreamer->PopSection();
2035+
}
2036+
20112037
//===--------------------------------------------------------------------===//
20122038
// Emission and print routines
20132039
//

Diff for: ‎llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp

+8
Original file line numberDiff line numberDiff line change
@@ -795,6 +795,14 @@ const MCExpr *TargetLoweringObjectFileELF::lowerRelativeReference(
795795
MCSymbolRefExpr::create(TM.getSymbol(RHS), getContext()), getContext());
796796
}
797797

798+
MCSection *TargetLoweringObjectFileELF::getSectionForCommandLines() const {
799+
// Use ".GCC.command.line" since this feature is to support clang's
800+
// -frecord-gcc-switches which in turn attempts to mimic GCC's switch of the
801+
// same name.
802+
return getContext().getELFSection(".GCC.command.line", ELF::SHT_PROGBITS,
803+
ELF::SHF_MERGE | ELF::SHF_STRINGS, 1, "");
804+
}
805+
798806
void
799807
TargetLoweringObjectFileELF::InitializeELF(bool UseInitArray_) {
800808
UseInitArray = UseInitArray_;

Diff for: ‎llvm/lib/IR/Verifier.cpp

+20
Original file line numberDiff line numberDiff line change
@@ -386,6 +386,7 @@ class Verifier : public InstVisitor<Verifier>, VerifierSupport {
386386

387387
visitModuleFlags(M);
388388
visitModuleIdents(M);
389+
visitModuleCommandLines(M);
389390

390391
verifyCompileUnits();
391392

@@ -408,6 +409,7 @@ class Verifier : public InstVisitor<Verifier>, VerifierSupport {
408409
void visitValueAsMetadata(const ValueAsMetadata &MD, Function *F);
409410
void visitComdat(const Comdat &C);
410411
void visitModuleIdents(const Module &M);
412+
void visitModuleCommandLines(const Module &M);
411413
void visitModuleFlags(const Module &M);
412414
void visitModuleFlag(const MDNode *Op,
413415
DenseMap<const MDString *, const MDNode *> &SeenIDs,
@@ -1313,6 +1315,24 @@ void Verifier::visitModuleIdents(const Module &M) {
13131315
}
13141316
}
13151317

1318+
void Verifier::visitModuleCommandLines(const Module &M) {
1319+
const NamedMDNode *CommandLines = M.getNamedMetadata("llvm.commandline");
1320+
if (!CommandLines)
1321+
return;
1322+
1323+
// llvm.commandline takes a list of metadata entry. Each entry has only one
1324+
// string. Scan each llvm.commandline entry and make sure that this
1325+
// requirement is met.
1326+
for (const MDNode *N : CommandLines->operands()) {
1327+
Assert(N->getNumOperands() == 1,
1328+
"incorrect number of operands in llvm.commandline metadata", N);
1329+
Assert(dyn_cast_or_null<MDString>(N->getOperand(0)),
1330+
("invalid value for llvm.commandline metadata entry operand"
1331+
"(the operand should be a string)"),
1332+
N->getOperand(0));
1333+
}
1334+
}
1335+
13161336
void Verifier::visitModuleFlags(const Module &M) {
13171337
const NamedMDNode *Flags = M.getModuleFlagsMetadata();
13181338
if (!Flags) return;

Diff for: ‎llvm/test/CodeGen/X86/commandline-metadata.ll

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
; RUN: llc -mtriple=x86_64-linux < %s | FileCheck %s
2+
; Verify that llvm.commandline metadata is emitted to a section named
3+
; .GCC.command.line with each line separated with null bytes.
4+
5+
; CHECK: .section .GCC.command.line,"MS",@progbits,1
6+
; CHECK-NEXT: .zero 1
7+
; CHECK-NEXT: .ascii "clang -command -line"
8+
; CHECK-NEXT: .zero 1
9+
; CHECK-NEXT: .ascii "something else"
10+
; CHECK-NEXT: .zero 1
11+
!llvm.commandline = !{!0, !1}
12+
!0 = !{!"clang -command -line"}
13+
!1 = !{!"something else"}

Diff for: ‎llvm/test/Linker/Inputs/commandline.a.ll

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
!llvm.commandline = !{!0, !1}
2+
!0 = !{!"compiler -v1"}
3+
!1 = !{!"compiler -v2"}

Diff for: ‎llvm/test/Linker/Inputs/commandline.b.ll

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
!llvm.commandline = !{!0}
2+
!0 = !{!"compiler -v3"}

Diff for: ‎llvm/test/Linker/commandline.ll

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
; RUN: llvm-link %S/Inputs/commandline.a.ll %S/Inputs/commandline.b.ll -S | FileCheck %s
2+
3+
; Verify that multiple input llvm.commandline metadata are linked together.
4+
5+
; CHECK-DAG: !llvm.commandline = !{!0, !1, !2}
6+
; CHECK-DAG: !{{[0-2]}} = !{!"compiler -v1"}
7+
; CHECK-DAG: !{{[0-2]}} = !{!"compiler -v2"}
8+
; CHECK-DAG: !{{[0-2]}} = !{!"compiler -v3"}

Diff for: ‎llvm/test/Verifier/commandline-meta1.ll

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
; RUN: not llvm-as < %s -o /dev/null 2>&1 | FileCheck %s
2+
; Verify that llvm.commandline is properly structured.
3+
; llvm.commandline takes a list of metadata entries.
4+
; Each metadata entry can have only one string.
5+
6+
!llvm.commandline = !{!0}
7+
!0 = !{!"string1", !"string2"}
8+
; CHECK: assembly parsed, but does not verify as correct!
9+
; CHECK-NEXT: incorrect number of operands in llvm.commandline metadata
10+
; CHECK-NEXT: !0

Diff for: ‎llvm/test/Verifier/commandline-meta2.ll

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
; RUN: not llvm-as < %s -o /dev/null 2>&1 | FileCheck %s
2+
; Verify that llvm.commandline is properly structured.
3+
; llvm.commandline takes a list of metadata entries.
4+
; Each metadata entry can contain one string only.
5+
6+
!llvm.commandline = !{!0}
7+
!0 = !{i32 1}
8+
; CHECK: assembly parsed, but does not verify as correct!
9+
; CHECK-NEXT: invalid value for llvm.commandline metadata entry operand(the operand should be a string)
10+
; CHECK-NEXT: i32 1

Diff for: ‎llvm/test/Verifier/commandline-meta3.ll

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
; RUN: not llvm-as < %s -o /dev/null 2>&1 | FileCheck %s
2+
; Verify that llvm.commandline is properly structured.
3+
; llvm.commandline takes a list of metadata entries.
4+
; Each metadata entry can contain one string only.
5+
6+
!llvm.commandline = !{!0}
7+
!0 = !{!{!"nested metadata"}}
8+
; CHECK: assembly parsed, but does not verify as correct!
9+
; CHECK-NEXT: invalid value for llvm.commandline metadata entry operand(the operand should be a string)
10+
; CHECK-NEXT: !1

Diff for: ‎llvm/test/Verifier/commandline-meta4.ll

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
; RUN: not llvm-as < %s -o /dev/null 2>&1 | FileCheck %s
2+
; Verify that llvm.commandline is properly structured.
3+
; llvm.commandline takes a list of metadata entries.
4+
; Each metadata entry can contain one string only.
5+
6+
!llvm.commandline = !{!0}
7+
!0 = !{null}
8+
; CHECK: assembly parsed, but does not verify as correct!
9+
; CHECK-NEXT: invalid value for llvm.commandline metadata entry operand(the operand should be a string)

0 commit comments

Comments
 (0)
Please sign in to comment.