Add support for -fno-optimize-sibling-calls. Currently only implemented in the
X86 backend in LLVM.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@148689 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/clang/Driver/CC1Options.td b/include/clang/Driver/CC1Options.td
index 3b87dd2..3d59906 100644
--- a/include/clang/Driver/CC1Options.td
+++ b/include/clang/Driver/CC1Options.td
@@ -166,6 +166,8 @@
   HelpText<"Enable additional debug output">;
 def mdisable_fp_elim : Flag<"-mdisable-fp-elim">,
   HelpText<"Disable frame pointer elimination optimization">;
+def mdisable_tail_calls : Flag<"-mdisable-tail-calls">,
+  HelpText<"Disable tail call optimization, keeping the call stack accurate">;
 def menable_no_infinities : Flag<"-menable-no-infs">,
   HelpText<"Allow optimization to assume there are no infinities.">;
 def menable_no_nans : Flag<"-menable-no-nans">,
diff --git a/include/clang/Driver/Options.td b/include/clang/Driver/Options.td
index 66d7f55..18e7777 100644
--- a/include/clang/Driver/Options.td
+++ b/include/clang/Driver/Options.td
@@ -473,6 +473,8 @@
 def fobjc : Flag<"-fobjc">, Group<f_Group>;
 def fomit_frame_pointer : Flag<"-fomit-frame-pointer">, Group<f_Group>;
 def fopenmp : Flag<"-fopenmp">, Group<f_Group>;
+def fno_optimize_sibling_calls : Flag<"-fno-optimize-sibling-calls">, Group<f_Group>;
+def foptimize_sibling_calls : Flag<"-foptimize-sibling-calls">, Group<f_Group>;
 def force__cpusubtype__ALL : Flag<"-force_cpusubtype_ALL">;
 def force__flat__namespace : Flag<"-force_flat_namespace">;
 def force__load : Separate<"-force_load">;
diff --git a/include/clang/Frontend/CodeGenOptions.h b/include/clang/Frontend/CodeGenOptions.h
index e6462c0..a0d260f 100644
--- a/include/clang/Frontend/CodeGenOptions.h
+++ b/include/clang/Frontend/CodeGenOptions.h
@@ -50,6 +50,7 @@
                                   /// internal state before optimizations are
                                   /// done.
   unsigned DisableRedZone    : 1; /// Set when -mno-red-zone is enabled.
+  unsigned DisableTailCalls  : 1; /// Do not emit tail calls.
   unsigned EmitDeclMetadata  : 1; /// Emit special metadata indicating what
                                   /// Decl* various IR entities came from.  Only
                                   /// useful when running CodeGen as a
@@ -166,6 +167,7 @@
     DisableFPElim = 0;
     DisableLLVMOpts = 0;
     DisableRedZone = 0;
+    DisableTailCalls = 0;
     EmitDeclMetadata = 0;
     EmitGcovArcs = 0;
     EmitGcovNotes = 0;
diff --git a/lib/CodeGen/BackendUtil.cpp b/lib/CodeGen/BackendUtil.cpp
index d5350f5..c163695 100644
--- a/lib/CodeGen/BackendUtil.cpp
+++ b/lib/CodeGen/BackendUtil.cpp
@@ -326,6 +326,7 @@
   Options.UseSoftFloat = CodeGenOpts.SoftFloat;
   Options.StackAlignmentOverride = CodeGenOpts.StackAlignment;
   Options.RealignStack = CodeGenOpts.StackRealignment;
+  Options.DisableTailCalls = CodeGenOpts.DisableTailCalls;
 
   TargetMachine *TM = TheTarget->createTargetMachine(Triple, TargetOpts.CPU,
                                                      FeaturesStr, Options,
diff --git a/lib/Driver/Tools.cpp b/lib/Driver/Tools.cpp
index a3ce05f..7254a36 100644
--- a/lib/Driver/Tools.cpp
+++ b/lib/Driver/Tools.cpp
@@ -1435,6 +1435,9 @@
                     options::OPT_fno_strict_aliasing,
                     getToolChain().IsStrictAliasingDefault()))
     CmdArgs.push_back("-relaxed-aliasing");
+  if (!Args.hasFlag(options::OPT_foptimize_sibling_calls,
+                    options::OPT_fno_optimize_sibling_calls))
+    CmdArgs.push_back("-mdisable-tail-calls");
 
   // Handle various floating point optimization flags, mapping them to the
   // appropriate LLVM code generation flags. The pattern for all of these is to
diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp
index 671cfc5..f457609 100644
--- a/lib/Frontend/CompilerInvocation.cpp
+++ b/lib/Frontend/CompilerInvocation.cpp
@@ -146,6 +146,8 @@
     Res.push_back("-disable-llvm-optzns");
   if (Opts.DisableRedZone)
     Res.push_back("-disable-red-zone");
+  if (Opts.DisableTailCalls)
+    Res.push_back("-mdisable-tail-calls");
   if (!Opts.DebugCompilationDir.empty()) {
     Res.push_back("-fdebug-compilation-dir");
     Res.push_back(Opts.DebugCompilationDir);
@@ -1098,6 +1100,7 @@
   Opts.CodeModel = Args.getLastArgValue(OPT_mcode_model);
   Opts.DebugPass = Args.getLastArgValue(OPT_mdebug_pass);
   Opts.DisableFPElim = Args.hasArg(OPT_mdisable_fp_elim);
+  Opts.DisableTailCalls = Args.hasArg(OPT_mdisable_tail_calls);
   Opts.FloatABI = Args.getLastArgValue(OPT_mfloat_abi);
   Opts.HiddenWeakVTables = Args.hasArg(OPT_fhidden_weak_vtables);
   Opts.LessPreciseFPMAD = Args.hasArg(OPT_cl_mad_enable);
diff --git a/test/Driver/no-sibling-calls.c b/test/Driver/no-sibling-calls.c
new file mode 100644
index 0000000..c248990
--- /dev/null
+++ b/test/Driver/no-sibling-calls.c
@@ -0,0 +1,8 @@
+// RUN: %clang -### %s -fno-optimize-sibling-calls 2> %t
+// RUN: FileCheck --check-prefix=CHECK-NOSC < %t %s
+// CHECK-NOSC: "-mdisable-tail-calls"
+
+// RUN: %clang -### -foptimize-sibling-calls %s 2> %t
+// RUN: FileCheck --check-prefix=CHECK-OSC < %t %s
+// CHECK-OSC-NOT: "-mdisable-tail-calls"
+