From: Eric Christopher Date: Tue, 23 Aug 2011 17:56:55 +0000 (+0000) Subject: Add support for a verifier to the driver. Currently only verifies debug X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=f857186fd1995b34185d063a29b11ad4f948519f;p=clang Add support for a verifier to the driver. Currently only verifies debug output on darwin so is hard coded there. As a note this will need a little bit of refactoring in the class hierarchy to separate it out for different verifiers based on input type. Fixes rdar://8256258. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@138343 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Driver/Action.h b/include/clang/Driver/Action.h index f51d8d9c9a..a33c33bf73 100644 --- a/include/clang/Driver/Action.h +++ b/include/clang/Driver/Action.h @@ -44,9 +44,10 @@ public: LinkJobClass, LipoJobClass, DsymutilJobClass, + VerifyJobClass, JobClassFirst=PreprocessJobClass, - JobClassLast=DsymutilJobClass + JobClassLast=VerifyJobClass }; static const char *getClassName(ActionClass AC); @@ -214,6 +215,15 @@ public: static bool classof(const DsymutilJobAction *) { return true; } }; +class VerifyJobAction : public JobAction { +public: + VerifyJobAction(ActionList &Inputs, types::ID Type); + static bool classof(const Action *A) { + return A->getKind() == VerifyJobClass; + } + static bool classof(const VerifyJobAction *) { return true; } +}; + } // end namespace driver } // end namespace clang diff --git a/include/clang/Driver/Options.td b/include/clang/Driver/Options.td index 5294fe0464..f97afb82ce 100644 --- a/include/clang/Driver/Options.td +++ b/include/clang/Driver/Options.td @@ -693,6 +693,8 @@ def u : JoinedOrSeparate<"-u">, Group; def use_gold_plugin : Flag<"-use-gold-plugin">; def v : Flag<"-v">, HelpText<"Show commands to run and use verbose output">; +def verify : Flag<"-verify">, Flags<[DriverOption]>, + HelpText<"Verify output using a verifier.">; def weak_l : Joined<"-weak-l">, Flags<[LinkerInput]>; def weak__framework : Separate<"-weak_framework">, Flags<[LinkerInput]>; def weak__library : Separate<"-weak_library">, Flags<[LinkerInput]>; diff --git a/lib/Driver/Action.cpp b/lib/Driver/Action.cpp index 549ce0a7f4..ac95446e5b 100644 --- a/lib/Driver/Action.cpp +++ b/lib/Driver/Action.cpp @@ -31,6 +31,7 @@ const char *Action::getClassName(ActionClass AC) { case LinkJobClass: return "linker"; case LipoJobClass: return "lipo"; case DsymutilJobClass: return "dsymutil"; + case VerifyJobClass: return "verify"; } assert(0 && "invalid class"); @@ -84,3 +85,7 @@ LipoJobAction::LipoJobAction(ActionList &Inputs, types::ID Type) DsymutilJobAction::DsymutilJobAction(ActionList &Inputs, types::ID Type) : JobAction(DsymutilJobClass, Inputs, Type) { } + +VerifyJobAction::VerifyJobAction(ActionList &Inputs, types::ID Type) + : JobAction(VerifyJobClass, Inputs, Type) { +} diff --git a/lib/Driver/Driver.cpp b/lib/Driver/Driver.cpp index fee601de73..12ad1b7838 100644 --- a/lib/Driver/Driver.cpp +++ b/lib/Driver/Driver.cpp @@ -829,6 +829,19 @@ void Driver::BuildUniversalActions(const ToolChain &TC, Actions.pop_back(); Actions.push_back(new DsymutilJobAction(Inputs, types::TY_dSYM)); + + // Verify the debug output if we're in assert mode. + // TODO: The verifier is noisy by default so put this under an + // option for now. + #ifndef NDEBUG + if (Args.hasArg(options::OPT_verify)) { + ActionList VerifyInputs; + VerifyInputs.push_back(Actions.back()); + Actions.pop_back(); + Actions.push_back(new VerifyJobAction(VerifyInputs, + types::TY_Nothing)); + } + #endif } } } @@ -1297,6 +1310,11 @@ void Driver::BuildJobsForAction(Compilation &C, if (AtTopLevel && isa(A)) SubJobAtTopLevel = true; + // Also treat verify sub-jobs as being at the top-level. They don't + // produce any output and so don't need temporary output names. + if (AtTopLevel && isa(A)) + SubJobAtTopLevel = true; + InputInfo II; BuildJobsForAction(C, *it, TC, BoundArch, SubJobAtTopLevel, LinkingOutput, II); @@ -1340,7 +1358,8 @@ const char *Driver::GetNamedOutputPath(Compilation &C, bool AtTopLevel) const { llvm::PrettyStackTraceString CrashInfo("Computing output path"); // Output to a user requested destination? - if (AtTopLevel && !isa(JA)) { + if (AtTopLevel && !isa(JA) && + !isa(JA)) { if (Arg *FinalOutput = C.getArgs().getLastArg(options::OPT_o)) return C.addResultFile(FinalOutput->getValue(C.getArgs())); } @@ -1361,7 +1380,7 @@ const char *Driver::GetNamedOutputPath(Compilation &C, StringRef BaseName; // Dsymutil actions should use the full path. - if (isa(JA)) + if (isa(JA) || isa(JA)) BaseName = BasePath; else BaseName = llvm::sys::path::filename(BasePath); diff --git a/lib/Driver/ToolChains.cpp b/lib/Driver/ToolChains.cpp index 821b07bc6f..079de9a2cb 100644 --- a/lib/Driver/ToolChains.cpp +++ b/lib/Driver/ToolChains.cpp @@ -255,6 +255,8 @@ Tool &Darwin::SelectTool(const Compilation &C, const JobAction &JA, T = new tools::darwin::Lipo(*this); break; case Action::DsymutilJobClass: T = new tools::darwin::Dsymutil(*this); break; + case Action::VerifyJobClass: + T = new tools::darwin::VerifyDebug(*this); break; } } @@ -362,8 +364,8 @@ void DarwinClang::AddLinkSearchPathArgs(const ArgList &Args, void DarwinClang::AddLinkARCArgs(const ArgList &Args, ArgStringList &CmdArgs) const { - - CmdArgs.push_back("-force_load"); + + CmdArgs.push_back("-force_load"); llvm::sys::Path P(getDriver().ClangExecutable); P.eraseComponent(); // 'clang' P.eraseComponent(); // 'bin' @@ -385,13 +387,13 @@ void DarwinClang::AddLinkARCArgs(const ArgList &Args, } void DarwinClang::AddLinkRuntimeLib(const ArgList &Args, - ArgStringList &CmdArgs, + ArgStringList &CmdArgs, const char *DarwinStaticLib) const { llvm::sys::Path P(getDriver().ResourceDir); P.appendComponent("lib"); P.appendComponent("darwin"); P.appendComponent(DarwinStaticLib); - + // For now, allow missing resource libraries to support developers who may // not have compiler-rt checked out or integrated into their build. bool Exists; @@ -1008,6 +1010,8 @@ Tool &Generic_GCC::SelectTool(const Compilation &C, T = new tools::darwin::Lipo(*this); break; case Action::DsymutilJobClass: T = new tools::darwin::Dsymutil(*this); break; + case Action::VerifyJobClass: + T = new tools::darwin::VerifyDebug(*this); break; } } @@ -1371,7 +1375,7 @@ static bool HasMultilib(llvm::Triple::ArchType Arch, enum LinuxDistro Distro) { } if (Arch == llvm::Triple::ppc64) return true; - if ((Arch == llvm::Triple::x86 || Arch == llvm::Triple::ppc) && + if ((Arch == llvm::Triple::x86 || Arch == llvm::Triple::ppc) && IsDebianBased(Distro)) return true; return false; @@ -1596,14 +1600,14 @@ Linux::Linux(const HostInfo &Host, const llvm::Triple &Triple) Exists) && Exists) GccTriple = "powerpc64-unknown-linux-gnu"; else if (!llvm::sys::fs::exists("/usr/lib64/gcc/" - "powerpc64-unknown-linux-gnu", Exists) && + "powerpc64-unknown-linux-gnu", Exists) && Exists) GccTriple = "powerpc64-unknown-linux-gnu"; } std::string Base = findGCCBaseLibDir(GccTriple); path_list &Paths = getFilePaths(); - bool Is32Bits = (getArch() == llvm::Triple::x86 || + bool Is32Bits = (getArch() == llvm::Triple::x86 || getArch() == llvm::Triple::ppc); std::string Suffix; @@ -1776,6 +1780,7 @@ Tool &Windows::SelectTool(const Compilation &C, const JobAction &JA, case Action::BindArchClass: case Action::LipoJobClass: case Action::DsymutilJobClass: + case Action::VerifyJobClass: assert(0 && "Invalid tool kind."); case Action::PreprocessJobClass: case Action::PrecompileJobClass: diff --git a/lib/Driver/Tools.cpp b/lib/Driver/Tools.cpp index e147c05ffe..33e11fb849 100644 --- a/lib/Driver/Tools.cpp +++ b/lib/Driver/Tools.cpp @@ -3482,6 +3482,26 @@ void darwin::Dsymutil::ConstructJob(Compilation &C, const JobAction &JA, C.addCommand(new Command(JA, *this, Exec, CmdArgs)); } +void darwin::VerifyDebug::ConstructJob(Compilation &C, const JobAction &JA, + const InputInfo &Output, + const InputInfoList &Inputs, + const ArgList &Args, + const char *LinkingOutput) const { + ArgStringList CmdArgs; + CmdArgs.push_back("--verify"); + + assert(Inputs.size() == 1 && "Unable to handle multiple inputs."); + const InputInfo &Input = Inputs[0]; + assert(Input.isFilename() && "Unexpected verify input"); + + // Grabbing the output of the earlier dsymutil run. + CmdArgs.push_back(Input.getFilename()); + + const char *Exec = + Args.MakeArgString(getToolChain().GetProgramPath("dwarfdump")); + C.addCommand(new Command(JA, *this, Exec, CmdArgs)); +} + void auroraux::Assemble::ConstructJob(Compilation &C, const JobAction &JA, const InputInfo &Output, const InputInfoList &Inputs, diff --git a/lib/Driver/Tools.h b/lib/Driver/Tools.h index 702fc9d5c3..a4f732e1c2 100644 --- a/lib/Driver/Tools.h +++ b/lib/Driver/Tools.h @@ -277,6 +277,21 @@ namespace darwin { const ArgList &TCArgs, const char *LinkingOutput) const; }; + + class LLVM_LIBRARY_VISIBILITY VerifyDebug : public DarwinTool { + public: + VerifyDebug(const ToolChain &TC) : DarwinTool("darwin::VerifyDebug", + "dwarfdump", TC) {} + + virtual bool hasIntegratedCPP() const { return false; } + + virtual void ConstructJob(Compilation &C, const JobAction &JA, + const InputInfo &Output, + const InputInfoList &Inputs, + const ArgList &TCArgs, + const char *LinkingOutput) const; + }; + } /// openbsd -- Directly call GNU Binutils assembler and linker diff --git a/test/Driver/darwin-verify-debug.c b/test/Driver/darwin-verify-debug.c new file mode 100644 index 0000000000..85445e9403 --- /dev/null +++ b/test/Driver/darwin-verify-debug.c @@ -0,0 +1,33 @@ +// Check that we verify debug output properly with multiple -arch options. +// +// RUN: %clang -ccc-host-triple x86_64-apple-darwin10 -ccc-print-phases \ +// RUN: -verify -arch i386 -arch x86_64 %s -g 2> %t +// RUN: FileCheck -check-prefix=CHECK-MULTIARCH-ACTIONS < %t %s +// +// CHECK-MULTIARCH-ACTIONS: 0: input, "{{.*}}darwin-verify-debug.c", c +// CHECK-MULTIARCH-ACTIONS: 8: dsymutil, {7}, dSYM +// CHECK-MULTIARCH-ACTIONS: 9: verify, {8}, none +// +// RUN: %clang -ccc-host-triple x86_64-apple-darwin10 -ccc-print-bindings \ +// RUN: -verify -arch i386 -arch x86_64 %s -g 2> %t +// RUN: FileCheck -check-prefix=CHECK-MULTIARCH-BINDINGS < %t %s +// +// CHECK-MULTIARCH-BINDINGS: # "x86_64-apple-darwin10" - "darwin::Dsymutil", inputs: ["a.out"], output: "a.out.dSYM" +// CHECK-MULTIARCH-BINDINGS: # "x86_64-apple-darwin10" - "darwin::VerifyDebug", inputs: ["a.out.dSYM"], output: (nothing) + +// Check output name derivation. +// +// RUN: %clang -ccc-host-triple x86_64-apple-darwin10 -ccc-print-bindings \ +// RUN: -verify -o foo %s -g 2> %t +// RUN: FileCheck -check-prefix=CHECK-OUTPUT-NAME < %t %s +// +// CHECK-OUTPUT-NAME: "x86_64-apple-darwin10" - "darwin::Link", inputs: [{{.*}}], output: "foo" +// CHECK-OUTPUT-NAME: "x86_64-apple-darwin10" - "darwin::Dsymutil", inputs: ["foo"], output: "foo.dSYM" +// CHECK-OUTPUT-NAME: "x86_64-apple-darwin10" - "darwin::VerifyDebug", inputs: ["foo.dSYM"], output: (nothing) + +// Check that we only verify when needed. +// +// RUN: touch %t.o +// RUN: %clang -ccc-host-triple x86_64-apple-darwin10 -ccc-print-bindings \ +// RUN: -verify -o foo %t.o -g 2> %t +// RUN: grep "Verify" %t | count 0