]> granicus.if.org Git - clang/commitdiff
Introduce -fembed-bitcode driver option
authorSteven Wu <stevenwu@apple.com>
Tue, 1 Mar 2016 01:07:58 +0000 (01:07 +0000)
committerSteven Wu <stevenwu@apple.com>
Tue, 1 Mar 2016 01:07:58 +0000 (01:07 +0000)
Summary:
This is the clang driver part of the change to embedded bitcode. This
includes:
1. -fembed-bitcode option which breaks down the compilation into two
stages. The first stage emits optimized bitcode and the second stage
compiles bitcode into object file.
2. -fembed-bitcode-marker option which doesn't really break down to
two stages to speedup the compilation flow.
3. pass the correct linker flag to darwin linker if tool chains supports
embedded bitcode.

Reviewers: rsmith, thakis

Subscribers: thakis, cfe-commits

Differential Revision: http://reviews.llvm.org/D17390

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@262282 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Basic/DiagnosticDriverKinds.td
include/clang/Driver/Driver.h
include/clang/Driver/Options.td
include/clang/Driver/ToolChain.h
lib/Driver/Driver.cpp
lib/Driver/ToolChains.cpp
lib/Driver/ToolChains.h
lib/Driver/Tools.cpp
test/Driver/embed-bitcode.c [new file with mode: 0644]

index 4b232006660f71b90d543cd9a54a1522a96921ca..c6e6eaf47cc9ae728d78a36ab8474498d0811b4e 100644 (file)
@@ -134,7 +134,9 @@ def err_drv_omp_host_ir_file_not_found : Error<
   "The provided host compiler IR file '%0' is required to generate code for OpenMP target regions but cannot be found.">;
 def err_drv_omp_host_target_not_supported : Error<
   "The target '%0' is not a supported OpenMP host target.">;
-  
+def err_drv_bitcode_unsupported_on_toolchain : Error<
+  "-fembed-bitcode is not supported on versions of iOS prior to 6.0">;
+
 def warn_O4_is_O3 : Warning<"-O4 is equivalent to -O3">, InGroup<Deprecated>;
 def warn_drv_lto_libpath : Warning<"libLTO.dylib relative to clang installed dir not found; using 'ld' default search path instead">,
   InGroup<LibLTO>;
index b6580456f4165f1a21d0b9392ba214e831d85dff..ccf23e046962daa4efc539821b99b248a34aef5a 100644 (file)
@@ -83,6 +83,12 @@ class Driver {
     SaveTempsObj
   } SaveTemps;
 
+  enum BitcodeEmbedMode {
+    EmbedNone,
+    EmbedMarker,
+    EmbedBitcode
+  } BitcodeEmbed;
+
   /// LTO mode selected via -f(no-)?lto(=.*)? options.
   LTOKind LTOMode;
 
@@ -262,6 +268,9 @@ public:
   bool isSaveTempsEnabled() const { return SaveTemps != SaveTempsNone; }
   bool isSaveTempsObj() const { return SaveTemps == SaveTempsObj; }
 
+  bool embedBitcodeEnabled() const { return BitcodeEmbed == EmbedBitcode; }
+  bool embedBitcodeMarkerOnly() const { return BitcodeEmbed == EmbedMarker; }
+
   /// @}
   /// @name Primary Functionality
   /// @{
index 8a22abcfdca5890878a40142b391b82911cb8c46..e05808eb513782154f10c77fd572a565ae449f2f 100644 (file)
@@ -437,6 +437,12 @@ def fno_autolink : Flag <["-"], "fno-autolink">, Group<f_Group>,
   Flags<[DriverOption, CC1Option]>,
   HelpText<"Disable generation of linker directives for automatic library linking">;
 
+def fembed_bitcode : Flag<["-"], "fembed-bitcode">, Group<f_Group>,
+  Flags<[CC1Option, CC1AsOption]>,
+  HelpText<"Embed LLVM IR bitcode as data">;
+def fembed_bitcode_marker : Flag<["-"], "fembed-bitcode-marker">,
+  Group<f_Group>, Flags<[CC1Option]>,
+  HelpText<"Embed placeholder LLVM IR data as a marker">;
 def fgnu_inline_asm : Flag<["-"], "fgnu-inline-asm">, Group<f_Group>, Flags<[DriverOption]>;
 def fno_gnu_inline_asm : Flag<["-"], "fno-gnu-inline-asm">, Group<f_Group>,
   Flags<[DriverOption, CC1Option]>,
index da0c40e8ad6f32b9146fe9ce6a21ada27978fe33..e093f6331672a7cdb1a4fd6cfe6f3e1b8f558806 100644 (file)
@@ -319,6 +319,11 @@ public:
     return false;
   }
 
+  /// SupportsEmbeddedBitcode - Does this tool chain support embedded bitcode.
+  virtual bool SupportsEmbeddedBitcode() const {
+    return false;
+  }
+
   /// getThreadModel() - Which thread model does this target use?
   virtual std::string getThreadModel() const { return "posix"; }
 
index 6a85dabdeb6383ce20a0ba050479cc56818ee798..eaf29de2aaf179f9140ab933643b20f2d9a73851 100644 (file)
@@ -50,7 +50,7 @@ Driver::Driver(StringRef ClangExecutable, StringRef DefaultTargetTriple,
                DiagnosticsEngine &Diags,
                IntrusiveRefCntPtr<vfs::FileSystem> VFS)
     : Opts(createDriverOptTable()), Diags(Diags), VFS(VFS), Mode(GCCMode),
-      SaveTemps(SaveTempsNone), LTOMode(LTOK_None),
+      SaveTemps(SaveTempsNone), BitcodeEmbed(EmbedNone), LTOMode(LTOK_None),
       ClangExecutable(ClangExecutable),
       SysRoot(DEFAULT_SYSROOT), UseStdLib(true),
       DefaultTargetTriple(DefaultTargetTriple),
@@ -479,6 +479,19 @@ Compilation *Driver::BuildCompilation(ArrayRef<const char *> ArgList) {
                     .Default(SaveTempsCwd);
   }
 
+  // Ignore -fembed-bitcode options with LTO
+  // since the output will be bitcode anyway.
+  if (!Args.hasFlag(options::OPT_flto, options::OPT_fno_lto, false)) {
+    if (Args.hasArg(options::OPT_fembed_bitcode))
+      BitcodeEmbed = EmbedBitcode;
+    else if (Args.hasArg(options::OPT_fembed_bitcode_marker))
+      BitcodeEmbed = EmbedMarker;
+  } else {
+    // claim the bitcode option under LTO so no warning is issued.
+    Args.ClaimAllArgs(options::OPT_fembed_bitcode);
+    Args.ClaimAllArgs(options::OPT_fembed_bitcode_marker);
+  }
+
   setLTOMode(Args);
 
   std::unique_ptr<llvm::opt::InputArgList> UArgs =
@@ -1723,7 +1736,8 @@ void Driver::BuildJobs(Compilation &C) const {
 // CudaHostAction, updates CollapsedCHA with the pointer to it so the
 // caller can deal with extra handling such action requires.
 static const Tool *selectToolForJob(Compilation &C, bool SaveTemps,
-                                    const ToolChain *TC, const JobAction *JA,
+                                    bool EmbedBitcode, const ToolChain *TC,
+                                    const JobAction *JA,
                                     const ActionList *&Inputs,
                                     const CudaHostAction *&CollapsedCHA) {
   const Tool *ToolForJob = nullptr;
@@ -1739,10 +1753,12 @@ static const Tool *selectToolForJob(Compilation &C, bool SaveTemps,
       !C.getArgs().hasArg(options::OPT__SLASH_Fa) &&
       isa<AssembleJobAction>(JA) && Inputs->size() == 1 &&
       isa<BackendJobAction>(*Inputs->begin())) {
-    // A BackendJob is always preceded by a CompileJob, and without
-    // -save-temps they will always get combined together, so instead of
-    // checking the backend tool, check if the tool for the CompileJob
-    // has an integrated assembler.
+    // A BackendJob is always preceded by a CompileJob, and without -save-temps
+    // or -fembed-bitcode, they will always get combined together, so instead of
+    // checking the backend tool, check if the tool for the CompileJob has an
+    // integrated assembler. For -fembed-bitcode, CompileJob is still used to
+    // look up tools for BackendJob, but they need to match before we can split
+    // them.
     const ActionList *BackendInputs = &(*Inputs)[0]->getInputs();
     // Compile job may be wrapped in CudaHostAction, extract it if
     // that's the case and update CollapsedCHA if we combine phases.
@@ -1753,6 +1769,14 @@ static const Tool *selectToolForJob(Compilation &C, bool SaveTemps,
     const Tool *Compiler = TC->SelectTool(*CompileJA);
     if (!Compiler)
       return nullptr;
+    // When using -fembed-bitcode, it is required to have the same tool (clang)
+    // for both CompilerJA and BackendJA. Otherwise, combine two stages.
+    if (EmbedBitcode) {
+      JobAction *InputJA = cast<JobAction>(*Inputs->begin());
+      const Tool *BackendTool = TC->SelectTool(*InputJA);
+      if (BackendTool == Compiler)
+        CompileJA = InputJA;
+    }
     if (Compiler->hasIntegratedAssembler()) {
       Inputs = &CompileJA->getInputs();
       ToolForJob = Compiler;
@@ -1761,8 +1785,8 @@ static const Tool *selectToolForJob(Compilation &C, bool SaveTemps,
   }
 
   // A backend job should always be combined with the preceding compile job
-  // unless OPT_save_temps is enabled and the compiler is capable of emitting
-  // LLVM IR as an intermediate output.
+  // unless OPT_save_temps or OPT_fembed_bitcode is enabled and the compiler is
+  // capable of emitting LLVM IR as an intermediate output.
   if (isa<BackendJobAction>(JA)) {
     // Check if the compiler supports emitting LLVM IR.
     assert(Inputs->size() == 1);
@@ -1775,7 +1799,8 @@ static const Tool *selectToolForJob(Compilation &C, bool SaveTemps,
     const Tool *Compiler = TC->SelectTool(*CompileJA);
     if (!Compiler)
       return nullptr;
-    if (!Compiler->canEmitIR() || !SaveTemps) {
+    if (!Compiler->canEmitIR() ||
+        (!SaveTemps && !EmbedBitcode)) {
       Inputs = &CompileJA->getInputs();
       ToolForJob = Compiler;
       CollapsedCHA = CHA;
@@ -1889,7 +1914,8 @@ InputInfo Driver::BuildJobsForActionNoCache(
   const JobAction *JA = cast<JobAction>(A);
   const CudaHostAction *CollapsedCHA = nullptr;
   const Tool *T =
-      selectToolForJob(C, isSaveTempsEnabled(), TC, JA, Inputs, CollapsedCHA);
+      selectToolForJob(C, isSaveTempsEnabled(), embedBitcodeEnabled(), TC, JA,
+                       Inputs, CollapsedCHA);
   if (!T)
     return InputInfo();
 
index a0fad02b6c617a9fb889f941046a67fcfa9c56ef..6cc512b6a16a5a0d99e4bcb4e13fa161d206b067 100644 (file)
@@ -1103,6 +1103,13 @@ bool Darwin::UseSjLjExceptions(const ArgList &Args) const {
   return !Triple.isWatchABI();
 }
 
+bool Darwin::SupportsEmbeddedBitcode() const {
+  assert(TargetInitialized && "Target not initialized!");
+  if (isTargetIPhoneOS() && isIPhoneOSVersionLT(6, 0))
+    return false;
+  return true;
+}
+
 bool MachO::isPICDefault() const { return true; }
 
 bool MachO::isPIEDefault() const { return false; }
index b956ac9405252e17f4cd8ec835da9b81bbaacf82..aab4d337683f79cb48555b41e2a1d21a6676efec 100644 (file)
@@ -542,6 +542,8 @@ public:
 
   bool UseSjLjExceptions(const llvm::opt::ArgList &Args) const override;
 
+  bool SupportsEmbeddedBitcode() const override;
+
   SanitizerMask getSupportedSanitizers() const override;
 };
 
index e5dbe9bae0cd8a15a9060e75d871c3e07db9c3d5..a0fceb9672af472827bb3d5826875d38f1a6eead 100644 (file)
@@ -3625,6 +3625,17 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
     Args.AddLastArg(CmdArgs, options::OPT_fthinlto_index_EQ);
   }
 
+  // Embed-bitcode option.
+  if (C.getDriver().embedBitcodeEnabled() &&
+      (isa<BackendJobAction>(JA) || isa<AssembleJobAction>(JA))) {
+    // Add flags implied by -fembed-bitcode.
+    CmdArgs.push_back("-fembed-bitcode");
+    // Disable all llvm IR level optimizations.
+    CmdArgs.push_back("-disable-llvm-optzns");
+  }
+  if (C.getDriver().embedBitcodeMarkerOnly())
+    CmdArgs.push_back("-fembed-bitcode-marker");
+
   // We normally speed up the clang process a bit by skipping destructors at
   // exit, but when we're generating diagnostics we can rely on some of the
   // cleanup.
@@ -7262,6 +7273,15 @@ void darwin::Linker::AddLinkArgs(Compilation &C, const ArgList &Args,
     else
       CmdArgs.push_back("-no_pie");
   }
+  // for embed-bitcode, use -bitcode_bundle in linker command
+  if (C.getDriver().embedBitcodeEnabled() ||
+      C.getDriver().embedBitcodeMarkerOnly()) {
+    // Check if the toolchain supports bitcode build flow.
+    if (MachOTC.SupportsEmbeddedBitcode())
+      CmdArgs.push_back("-bitcode_bundle");
+    else
+      D.Diag(diag::err_drv_bitcode_unsupported_on_toolchain);
+  }
 
   Args.AddLastArg(CmdArgs, options::OPT_prebind);
   Args.AddLastArg(CmdArgs, options::OPT_noprebind);
diff --git a/test/Driver/embed-bitcode.c b/test/Driver/embed-bitcode.c
new file mode 100644 (file)
index 0000000..6ac0d54
--- /dev/null
@@ -0,0 +1,38 @@
+// RUN: %clang -ccc-print-bindings -c %s -fembed-bitcode 2>&1 | FileCheck %s
+// CHECK: clang
+// CHECK: clang
+
+// RUN: %clang %s -fembed-bitcode 2>&1 -### | FileCheck %s -check-prefix=CHECK-CC
+// CHECK-CC: -cc1
+// CHECK-CC: -emit-llvm-bc
+// CHECK-CC: -cc1
+// CHECK-CC: -emit-obj
+// CHECK-CC: -fembed-bitcode
+// CHECK-CC: ld
+// CHECK-CC: -bitcode_bundle
+
+// RUN: %clang %s -save-temps -fembed-bitcode 2>&1 -### | FileCheck %s -check-prefix=CHECK-SAVE-TEMP
+// CHECK-SAVE-TEMP: -cc1
+// CHECK-SAVE-TEMP: -E
+// CHECK-SAVE-TEMP: -cc1
+// CHECK-SAVE-TEMP: -emit-llvm-bc
+// CHECK-SAVE-TEMP: -cc1
+// CHECK-SAVE-TEMP: -S
+// CHECK-SAVE-TEMP: -fembed-bitcode
+// CHECK-SAVE-TEMP: -cc1as
+// CHECK-SAVE-TEMP: ld
+// CHECK-SAVE-TEMP: -bitcode_bundle
+
+// RUN: %clang -c %s -flto -fembed-bitcode 2>&1 -### | FileCheck %s -check-prefix=CHECK-LTO
+// CHECK-LTO: -cc1
+// CHECK-LTO: -emit-llvm-bc
+// CHECK-LTO-NOT: warning: argument unused during compilation: '-fembed-bitcode'
+// CHECK-LTO-NOT: -cc1
+// CHECK-LTO-NOT: -fembed-bitcode
+
+// RUN: %clang -c %s -fembed-bitcode-marker 2>&1 -### | FileCheck %s -check-prefix=CHECK-MARKER
+// CHECK-MARKER: -cc1
+// CHECK-MARKER: -emit-obj
+// CHECK-MARKER: -fembed-bitcode-marker
+// CHECK-MARKER-NOT: -cc1
+