From 02cb4cc9735e15b4d3f5f69c63708e9f905f8295 Mon Sep 17 00:00:00 2001
From: Houtan Bastani <houtan@dynare.org>
Date: Mon, 2 Dec 2019 19:21:14 +0100
Subject: [PATCH] add compiler statement

Allows the user to set the compiler, flags, and libs to be used with `use_dll`

Issue #35
---
 src/DynareBison.yy   | 21 ++++++++++++++++++++-
 src/DynareFlex.ll    |  6 ++++++
 src/ModelTree.cc     | 43 +++++++++++++++++++++++++++++++++++++++++--
 src/ModelTree.hh     |  9 ++++++++-
 src/ParsingDriver.cc | 30 ++++++++++++++++++++++++++++++
 src/ParsingDriver.hh | 10 ++++++++++
 src/StaticModel.cc   |  6 ++++++
 7 files changed, 121 insertions(+), 4 deletions(-)

diff --git a/src/DynareBison.yy b/src/DynareBison.yy
index 5734fa13..063d2a98 100644
--- a/src/DynareBison.yy
+++ b/src/DynareBison.yy
@@ -84,7 +84,7 @@ class ParsingDriver;
 %token END ENDVAL EQUAL ESTIMATION ESTIMATED_PARAMS ESTIMATED_PARAMS_BOUNDS ESTIMATED_PARAMS_INIT EXTENDED_PATH ENDOGENOUS_PRIOR EXPRESSION
 %token FILENAME DIRNAME FILTER_STEP_AHEAD FILTERED_VARS FIRST_OBS LAST_OBS SET_TIME OSR_PARAMS_BOUNDS KEEP_KALMAN_ALGO_IF_SINGULARITY_IS_DETECTED
 %token <string> FLOAT_NUMBER DATES
-%token DEFAULT FIXED_POINT FLIP OPT_ALGO
+%token DEFAULT FIXED_POINT FLIP OPT_ALGO COMPILATION_SETUP COMPILER ADD_FLAGS SUBSTITUTE_FLAGS ADD_LIBS SUBSTITUTE_LIBS
 %token FORECAST K_ORDER_SOLVER INSTRUMENTS SHIFT MEAN STDEV VARIANCE MODE INTERVAL SHAPE DOMAINN
 %token GAMMA_PDF GRAPH GRAPH_FORMAT CONDITIONAL_VARIANCE_DECOMPOSITION NOCHECK STD
 %token HISTVAL HISTVAL_FILE HOMOTOPY_SETUP HOMOTOPY_MODE HOMOTOPY_STEPS HOMOTOPY_FORCE_CONTINUE HP_FILTER HP_NGRID HYBRID ONE_SIDED_HP_FILTER
@@ -308,6 +308,7 @@ statement : parameters
           | init2shocks
           | det_cond_forecast
           | var_expectation_model
+          | compilation_setup
           ;
 
 dsample : DSAMPLE INT_NUMBER ';'
@@ -890,6 +891,24 @@ epilogue_equation : NAME { driver.add_epilogue_variable($1); } EQUAL expression
                     { driver.add_epilogue_equal($1, $4); }
                   ;
 
+compilation_setup : COMPILATION_SETUP '(' compilation_setup_options_list ')' ';' { };
+
+compilation_setup_options_list : compilation_setup_options_list COMMA compilation_setup_option
+                               | compilation_setup_option
+                               ;
+
+compilation_setup_option : SUBSTITUTE_FLAGS EQUAL QUOTED_STRING
+                           { driver.compilation_setup_substitute_flags($3); }
+                         | ADD_FLAGS EQUAL QUOTED_STRING
+                           { driver.compilation_setup_add_flags($3); }
+                         | SUBSTITUTE_LIBS EQUAL QUOTED_STRING
+                           { driver.compilation_setup_substitute_libs($3); }
+                         | ADD_LIBS EQUAL QUOTED_STRING
+                           { driver.compilation_setup_add_libs($3); }
+                         | COMPILER EQUAL QUOTED_STRING
+                           { driver.compilation_setup_compiler($3); }
+                         ;
+
 model_options : BLOCK { driver.block(); }
               | o_cutoff
 							| o_mfs
diff --git a/src/DynareFlex.ll b/src/DynareFlex.ll
index 747dbd34..989bc71b 100644
--- a/src/DynareFlex.ll
+++ b/src/DynareFlex.ll
@@ -186,6 +186,7 @@ DATE -?[0-9]+([ya]|m([1-9]|1[0-2])|q[1-4]|w([1-9]{1}|[1-4][0-9]|5[0-2]))
 <INITIAL>perfect_foresight_setup {BEGIN DYNARE_STATEMENT; return token::PERFECT_FORESIGHT_SETUP;}
 <INITIAL>perfect_foresight_solver {BEGIN DYNARE_STATEMENT; return token::PERFECT_FORESIGHT_SOLVER;}
 <INITIAL>det_cond_forecast {BEGIN DYNARE_STATEMENT; return token::DET_COND_FORECAST;}
+<INITIAL>compilation_setup {BEGIN DYNARE_STATEMENT; return token::COMPILATION_SETUP;}
 
 <DYNARE_STATEMENT>; {
   if (!sigma_e)
@@ -563,6 +564,11 @@ DATE -?[0-9]+([ya]|m([1-9]|1[0-2])|q[1-4]|w([1-9]{1}|[1-4][0-9]|5[0-2]))
 <DYNARE_STATEMENT>tolf {return token::TOLF;}
 <DYNARE_STATEMENT>tolx {return token::TOLX;}
 <DYNARE_STATEMENT>opt_algo {return token::OPT_ALGO;}
+<DYNARE_STATEMENT>add_flags {return token::ADD_FLAGS;}
+<DYNARE_STATEMENT>substitute_flags {return token::SUBSTITUTE_FLAGS;}
+<DYNARE_STATEMENT>add_libs {return token::ADD_LIBS;}
+<DYNARE_STATEMENT>substitute_libs {return token::SUBSTITUTE_LIBS;}
+<DYNARE_STATEMENT>compiler {return token::COMPILER;}
 <DYNARE_STATEMENT>instruments {return token::INSTRUMENTS;}
 <DYNARE_STATEMENT>hessian  {
   yylval->build<string>(yytext);
diff --git a/src/ModelTree.cc b/src/ModelTree.cc
index 611310a0..113a11f0 100644
--- a/src/ModelTree.cc
+++ b/src/ModelTree.cc
@@ -102,6 +102,11 @@ ModelTree::ModelTree(SymbolTable &symbol_table_arg,
 
 ModelTree::ModelTree(const ModelTree &m) :
   DataTree {m},
+  user_set_add_flags {m.user_set_add_flags},
+  user_set_subst_flags {m.user_set_subst_flags},
+  user_set_add_libs {m.user_set_add_libs},
+  user_set_subst_libs {m.user_set_subst_libs},
+  user_set_compiler {m.user_set_compiler},
   equations_lineno {m.equations_lineno},
   equation_tags {m.equation_tags},
   equation_tags_xref {m.equation_tags_xref},
@@ -157,6 +162,12 @@ ModelTree::operator=(const ModelTree &m)
   cutoff = m.cutoff;
   mfs = m.mfs;
 
+  user_set_add_flags = m.user_set_add_flags;
+  user_set_subst_flags = m.user_set_subst_flags;
+  user_set_add_libs = m.user_set_add_libs;
+  user_set_subst_libs = m.user_set_subst_libs;
+  user_set_compiler = m.user_set_compiler;
+
   copyHelper(m);
 
   return *this;
@@ -2317,7 +2328,7 @@ ModelTree::matlab_arch(const string &mexext)
 }
 
 void
-ModelTree::compileDll(const string &basename, const string &static_or_dynamic, const string &mexext, const filesystem::path &matlabroot, const filesystem::path &dynareroot)
+ModelTree::compileDll(const string &basename, const string &static_or_dynamic, const string &mexext, const filesystem::path &matlabroot, const filesystem::path &dynareroot) const
 {
   const string opt_flags = "-O3 -g0 --param ira-max-conflict-table-size=1 -fno-forward-propagate -fno-gcse -fno-dce -fno-dse -fno-tree-fre -fno-tree-pre -fno-tree-cselim -fno-tree-dse -fno-tree-dce -fno-tree-pta -fno-gcse-after-reload";
 
@@ -2411,7 +2422,35 @@ ModelTree::compileDll(const string &basename, const string &static_or_dynamic, c
      quotes to be correctly handled. See "cmd /?" for more details. */
   cmd << '"';
 #endif
-  cmd << compiler << " " << opt_flags << " " << flags.str() << " " << main_src << " " << mex_src << " -o " << binary << " " << libs;
+
+  if (user_set_compiler.empty())
+    cmd << compiler << " ";
+  else
+    if (!filesystem::exists(user_set_compiler))
+      {
+        cerr << "Error: The specified compiler '" << user_set_compiler << "' cannot be found on your system" << endl;
+        exit(EXIT_FAILURE);
+      }
+    else
+      cmd << user_set_compiler << " ";
+
+  if (user_set_subst_flags.empty())
+    cmd << opt_flags << " " << flags.str() << " ";
+  else
+    cmd << user_set_subst_flags << " ";
+
+  if (!user_set_add_flags.empty())
+    cmd << user_set_add_flags << " ";
+
+  cmd << main_src << " " << mex_src << " -o " << binary << " ";
+
+  if (user_set_subst_libs.empty())
+    cmd << libs;
+  else
+    cmd << user_set_subst_libs;
+
+  if (!user_set_add_libs.empty())
+    cmd << " " << user_set_add_libs;
 
 #ifdef _WIN32
   cmd << '"';
diff --git a/src/ModelTree.hh b/src/ModelTree.hh
index 2b5c606d..a0914aff 100644
--- a/src/ModelTree.hh
+++ b/src/ModelTree.hh
@@ -64,6 +64,13 @@ class ModelTree : public DataTree
 {
   friend class DynamicModel;
   friend class StaticModel;
+public:
+  // The following 5 variables are set via the `compiler` command
+  string user_set_add_flags;
+  string user_set_subst_flags;
+  string user_set_add_libs;
+  string user_set_subst_libs;
+  string user_set_compiler;
 protected:
   /*
    * ************** BEGIN **************
@@ -324,7 +331,7 @@ private:
   //! Returns the name of the MATLAB architecture given the extension used for MEX files
   static string matlab_arch(const string &mexext);
   //! Compiles the MEX file
-  static void compileDll(const string &basename, const string &static_or_dynamic, const string &mexext, const filesystem::path &matlabroot, const filesystem::path &dynareroot);
+  void compileDll(const string &basename, const string &static_or_dynamic, const string &mexext, const filesystem::path &matlabroot, const filesystem::path &dynareroot) const;
 
 public:
   ModelTree(SymbolTable &symbol_table_arg,
diff --git a/src/ParsingDriver.cc b/src/ParsingDriver.cc
index de9b2abb..535790be 100644
--- a/src/ParsingDriver.cc
+++ b/src/ParsingDriver.cc
@@ -793,6 +793,36 @@ ParsingDriver::mfs(const string &value)
   mod_file->static_model.mfs = val;
 }
 
+void
+ParsingDriver::compilation_setup_substitute_flags(const string & flags)
+{
+  mod_file->dynamic_model.user_set_subst_flags = flags;
+}
+
+void
+ParsingDriver::compilation_setup_add_flags(const string & flags)
+{
+  mod_file->dynamic_model.user_set_add_flags = flags;
+}
+
+void
+ParsingDriver::compilation_setup_substitute_libs(const string & libs)
+{
+  mod_file->dynamic_model.user_set_subst_libs = libs;
+}
+
+void
+ParsingDriver::compilation_setup_add_libs(const string & libs)
+{
+  mod_file->dynamic_model.user_set_add_libs = libs;
+}
+
+void
+ParsingDriver::compilation_setup_compiler(const string & compiler)
+{
+  mod_file->dynamic_model.user_set_compiler = compiler;
+}
+
 void
 ParsingDriver::balanced_growth_test_tol(const string &value)
 {
diff --git a/src/ParsingDriver.hh b/src/ParsingDriver.hh
index 06622d16..4291952b 100644
--- a/src/ParsingDriver.hh
+++ b/src/ParsingDriver.hh
@@ -358,6 +358,16 @@ public:
   void cutoff(const string &value);
   //! mfs option of model block
   void mfs(const string &value);
+  //! the flags to substitute for the default compiler flags used by `use_dll`
+  void compilation_setup_substitute_flags(const string & flags);
+  //! the flags to add to the default compiler flags used by `use_dll`
+  void compilation_setup_add_flags(const string & flags);
+  //! the libs to substitute for the default compiler libs used by `use_dll`
+  void compilation_setup_substitute_libs(const string & libs);
+  //! the libs to add to the default compiler libs used by `use_dll`
+  void compilation_setup_add_libs(const string & libs);
+  //! the compiler to replace the default compiler used by `use_dll`
+  void compilation_setup_compiler(const string & path);
   //! balanced_growth_test_tol option of model block
   void balanced_growth_test_tol(const string &value);
   //! Sets the FILENAME for the initial value in initval
diff --git a/src/StaticModel.cc b/src/StaticModel.cc
index 2c82876f..9b7a0263 100644
--- a/src/StaticModel.cc
+++ b/src/StaticModel.cc
@@ -195,6 +195,12 @@ StaticModel::StaticModel(const DynamicModel &m) :
   // Convert auxiliary equations
   for (auto aux_eq : m.aux_equations)
     addAuxEquation(aux_eq->toStatic(*this));
+
+  user_set_add_flags = m.user_set_add_flags;
+  user_set_subst_flags = m.user_set_subst_flags;
+  user_set_add_libs = m.user_set_add_libs;
+  user_set_subst_libs = m.user_set_subst_libs;
+  user_set_compiler = m.user_set_compiler;
 }
 
 void
-- 
GitLab