driver, bridge: support -f[no-]split-stack flags

We were always generating split-stack code. Add support of
-f[no-]split-stack flags to the driver to control whether to
use split stacks.

Change-Id: Ib97ad613296883cf64c79ac370a43c426c55bf51
Reviewed-on: https://go-review.googlesource.com/c/141677
Reviewed-by: Than McIntosh <thanm@google.com>
diff --git a/bridge/go-llvm.cpp b/bridge/go-llvm.cpp
index 5d1dcaf..631c01f 100644
--- a/bridge/go-llvm.cpp
+++ b/bridge/go-llvm.cpp
@@ -53,6 +53,7 @@
     , traceLevel_(0)
     , noInline_(false)
     , noFpElim_(false)
+    , useSplitStack_(true)
     , checkIntegrity_(true)
     , createDebugMetaData_(true)
     , exportDataStarted_(false)
@@ -468,7 +469,7 @@
   bool is_visible = true;
   bool is_declaration = false;
   bool is_inl = true;
-  bool is_splitstack = true;
+  bool is_splitstack = useSplitStack_;
   bool in_unique_section = false;
   bool is_noret = false;
 
@@ -2570,7 +2571,7 @@
       fcn->addFnAttr(llvm::Attribute::NoInline);
 
     // split-stack or nosplit
-    if (! disable_split_stack)
+    if (useSplitStack_ && !disable_split_stack)
       fcn->addFnAttr("split-stack");
 
     // allow elim frame pointer or not
@@ -2614,7 +2615,7 @@
                                    typeManager());
 
   // split-stack or nosplit
-  if (disable_split_stack)
+  if (!useSplitStack_ || disable_split_stack)
     bfunc->setSplitStack(Bfunction::NoSplit);
 
   // TODO: unique section support. llvm::GlobalObject has support for
diff --git a/bridge/go-llvm.h b/bridge/go-llvm.h
index 6b3b008..7250ed2 100644
--- a/bridge/go-llvm.h
+++ b/bridge/go-llvm.h
@@ -393,6 +393,9 @@
   // Disable frame pointer elimination if set to true.
   void setNoFpElim(bool b) { noFpElim_ = b; };
 
+  // Enable/disable the use of split stacks.
+  void setUseSplitStack(bool b) { useSplitStack_ = b; };
+
   // Target CPU and features
   void setTargetCpuAttr(const std::string &cpu);
   void setTargetFeaturesAttr(const std::string &attrs);
@@ -740,6 +743,9 @@
   // Whether to disable frame pointer elimination.
   bool noFpElim_;
 
+  // Whether to use split stacks.
+  bool useSplitStack_;
+
   // Whether to check for unexpected node sharing (e.g. same Bexpression
   // or statement pointed to by multiple parents).
   bool checkIntegrity_;
diff --git a/driver/CompileGo.cpp b/driver/CompileGo.cpp
index 976e40b..b727162 100644
--- a/driver/CompileGo.cpp
+++ b/driver/CompileGo.cpp
@@ -484,6 +484,13 @@
                                   true);
   bridge_->setNoFpElim(!omitFp);
 
+  // -f[no-]split-stack
+  bool useSplitStack =
+      driver_.reconcileOptionPair(gollvm::options::OPT_fsplit_stack,
+                                  gollvm::options::OPT_fno_split_stack,
+                                  true);
+  bridge_->setUseSplitStack(useSplitStack);
+
   // Honor -fdebug-prefix=... option.
   for (const auto &arg : driver_.args().getAllArgValues(gollvm::options::OPT_fdebug_prefix_map_EQ))
     bridge_->addDebugPrefix(llvm::StringRef(arg).split('='));
diff --git a/driver/GollvmOptions.td b/driver/GollvmOptions.td
index 61a9fae..1fe3d13 100644
--- a/driver/GollvmOptions.td
+++ b/driver/GollvmOptions.td
@@ -231,7 +231,10 @@
 
 // Target-independent "-f" options.
 
-def fsplit_stack : Flag<["-"], "fsplit-stack">, Group<f_Group>;
+def fsplit_stack : Flag<["-"], "fsplit-stack">, Group<f_Group>,
+  HelpText<"Use split stacks">;
+def fno_split_stack : Flag<["-"], "fno-split-stack">, Group<f_Group>,
+  HelpText<"Don't use split stacks">;
 
 def fPIC : Flag<["-"], "fPIC">, Group<f_Group>;
 def fno_PIC : Flag<["-"], "fno-PIC">, Group<f_Group>;