PandA-2024.02
tree-panda-gcc.cpp
Go to the documentation of this file.
1 /*
2  *
3  * _/_/_/ _/_/ _/ _/ _/_/_/ _/_/
4  * _/ _/ _/ _/ _/_/ _/ _/ _/ _/ _/
5  * _/_/_/ _/_/_/_/ _/ _/_/ _/ _/ _/_/_/_/
6  * _/ _/ _/ _/ _/ _/ _/ _/ _/
7  * _/ _/ _/ _/ _/ _/_/_/ _/ _/
8  *
9  * ***********************************************
10  * PandA Project
11  * URL: http://panda.dei.polimi.it
12  * Politecnico di Milano - DEIB
13  * System Architectures Group
14  * ***********************************************
15  * Copyright (C) 2004-2024 Politecnico di Milano
16  *
17  * This file is part of the PandA framework.
18  *
19  * The PandA framework is free software; you can redistribute it and/or modify
20  * it under the terms of the GNU General Public License as published by
21  * the Free Software Foundation; either version 3 of the License, or
22  * (at your option) any later version.
23  *
24  * This program is distributed in the hope that it will be useful,
25  * but WITHOUT ANY WARRANTY; without even the implied warranty of
26  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27  * GNU General Public License for more details.
28  *
29  * You should have received a copy of the GNU General Public License
30  * along with this program. If not, see <http://www.gnu.org/licenses/>.
31  *
32  */
44 #include "config_RELEASE.hpp"
45 
46 #include "Parameter.hpp"
47 #include "compiler_wrapper.hpp"
48 #include "cost_latency_table.hpp"
49 #include "cpu_time.hpp"
50 #include "exceptions.hpp"
51 #include "fileIO.hpp"
52 #include "parse_tree.hpp"
54 #include "tree_manager.hpp"
55 #include "utility.hpp"
56 
57 #include <csignal>
58 #include <cstdlib>
59 #include <filesystem>
60 #include <fstream>
61 #include <getopt.h>
62 #include <iosfwd>
63 #include <string>
64 
65 static char* alloc_long_option(char* argv[], int& i, int& dec)
66 {
67  size_t len1 = strlen(argv[i]);
68  size_t len2 = strlen(argv[i + 1]);
69  auto* tmp = new char[1 + len1 + 1 + len2 + 1];
70  *tmp = '-';
71  strcpy(tmp + 1, argv[i]);
72  *(tmp + 1 + len1) = '=';
73  strcpy(tmp + 1 + len1 + 1, argv[i + 1]);
74  ++i;
75  --dec;
76  return tmp;
77 }
78 
79 static char** alloc_argv(int& argc, char* argv[])
80 {
81  auto** argv_copied = new char*[static_cast<unsigned>(argc) + 1u];
82  int dec = 0;
83  for(int i = 0; i < argc; ++i)
84  {
85  char* tmp;
86  // std::cerr << argv[i] << std::endl;
87  if(strcmp(argv[i], "-include") == 0 || strcmp(argv[i], "-isystem") == 0 || strcmp(argv[i], "-iquote") == 0 ||
88  strcmp(argv[i], "-isysroot") == 0 || strcmp(argv[i], "-imultilib") == 0 || strcmp(argv[i], "-MF") == 0 ||
89  strcmp(argv[i], "-MT") == 0 || strcmp(argv[i], "-MQ") == 0)
90  {
91  tmp = alloc_long_option(argv, i, dec);
92  }
93  else if(strcmp(argv[i], "-print-libgcc-file-name") == 0)
94  {
95  const char newvalue[] = "--print-file-name=libgcc.a";
96  tmp = new char[strlen(newvalue) + 1];
97  strcpy(tmp, newvalue);
98  }
99  else
100  {
101  tmp = new char[strlen(argv[i]) + 2];
102  strcpy(tmp, argv[i]);
103  }
104  argv_copied[i + dec] = tmp;
105  }
106  argc = argc + dec;
107  argv_copied[argc] = nullptr;
108  return argv_copied;
109 }
110 
111 static void dealloc_argv(int argc, char* argv_copied[])
112 {
113  for(int i = 0; i < argc; ++i)
114  {
115  delete[] argv_copied[i];
116  }
117  delete[] argv_copied;
118 }
119 
120 static void close_everything(int argc, char* argv[], const ParameterRef& Param)
121 {
122  dealloc_argv(argc, argv);
123  if(Param && not(Param->getOption<bool>(OPT_no_clean)))
124  {
125  std::filesystem::remove_all(Param->getOption<std::string>(OPT_output_temporary_directory));
126  }
127 }
134 int main(int argc, char* argv_orig[])
135 {
136  char** argv = alloc_argv(argc, argv_orig);
137  ParameterRef Param;
138  try
139  {
140  long int total_time;
141  START_TIME(total_time);
142  // ---------- Parameter parsing ------------ //
143  Param = ParameterRef(new tree_panda_gcc_parameter(argv[0], argc, argv));
144 
145  switch(Param->Exec())
146  {
147  case PARAMETER_NOTPARSED:
148  {
150  throw "Bad Parameters format";
151  }
152  case EXIT_SUCCESS:
153  {
154  close_everything(argc, argv, Param);
155  return EXIT_SUCCESS;
156  }
157  case PARAMETER_PARSED:
158  {
159  exit_code = EXIT_FAILURE;
160  break;
161  }
162  default:
163  {
164  THROW_ERROR("Bad Parameters parsing");
165  }
166  }
167  auto output_level = Param->getOption<int>(OPT_output_level);
168  if(output_level >= OUTPUT_LEVEL_MINIMUM)
169  {
170  Param->PrintFullHeader(std::cerr);
171  }
172 
173  auto debug_level = Param->getOption<int>(OPT_debug_level);
174 
176  // it means that the Param are source code input files: GCC wrapper has to be invoked
177  const tree_managerRef TM(new tree_manager(Param));
178  if(Param->isOption(OPT_input_file))
179  {
180  long int wrapping_time;
181 
182  START_TIME(wrapping_time);
183  if(debug_level >= DEBUG_LEVEL_MINIMUM)
184  {
185  if(debug_level >= DEBUG_LEVEL_VERBOSE)
186  {
187  PRINT_DBG_MEX(DEBUG_LEVEL_VERBOSE, debug_level, "");
188  PRINT_DBG_MEX(DEBUG_LEVEL_VERBOSE, debug_level, "************************************");
189  PRINT_DBG_MEX(DEBUG_LEVEL_VERBOSE, debug_level, "* Starting GNU/GCC wrapping *");
190  PRINT_DBG_MEX(DEBUG_LEVEL_VERBOSE, debug_level, "************************************");
191  }
192  else
193  {
194  PRINT_DBG_MEX(DEBUG_LEVEL_MINIMUM, debug_level, "\n ==== Starting GNU/GCC wrapping ====");
195  }
196  }
197 
198  const CompilerWrapper_OptimizationSet optimization_set =
199  Param->getOption<CompilerWrapper_OptimizationSet>(OPT_gcc_optimization_set);
200  const CompilerWrapper_CompilerTarget compiler_target =
201  Param->getOption<CompilerWrapper_CompilerTarget>(OPT_default_compiler);
202  CompilerWrapperRef Wrap = CompilerWrapperRef(new CompilerWrapper(Param, compiler_target, optimization_set));
203 
204  auto input_files = [&]() {
205  const auto flist = Param->getOption<std::list<std::string>>(OPT_input_file);
206  return std::vector<std::string>(flist.begin(), flist.end());
207  }();
208 
209  PRINT_DBG_MEX(DEBUG_LEVEL_VERBOSE, debug_level,
210  "Created list of files: " + std::to_string(input_files.size()) +
211  " input source code files to be concatenated");
212 
214  Wrap->FillTreeManager(TM, input_files, STR_cost_latency_table_default);
215 
216  // Dump the configuration file if it has been requested by the user. Note that if the configuration
217  // has been dumped in this point (after GCC compiler has been invoked), the compilation has been completed
218  // with success and, so, the configuration is correct.
219 
220  STOP_TIME(wrapping_time);
221 #ifndef NDEBUG
222  if(debug_level >= DEBUG_LEVEL_MINIMUM)
223  {
224  dump_exec_time("Gcc wrapping time", wrapping_time);
225  }
226 #endif
227  }
228  if(!Param->isOption(OPT_gcc_E) && !Param->isOption(OPT_gcc_S))
229  {
230  long int tree_time;
231  START_TIME(tree_time);
232  if(Param->isOption(OPT_obj_files))
233  {
234  const auto object_files = Param->getOption<CustomSet<std::string>>(OPT_obj_files);
235  for(const auto& object_file : object_files)
236  {
237  if(!std::filesystem::exists(object_file))
238  {
239  THROW_ERROR("File " + object_file + " does not exist");
240  }
241  const tree_managerRef TM_new = ParseTreeFile(Param, object_file);
242  TM->merge_tree_managers(TM_new);
243  }
244  }
245  if(Param->isOption(OPT_archive_files))
246  {
247  const auto archive_files = Param->getOption<CustomSet<std::string>>(OPT_archive_files);
248  for(const auto& archive_file : archive_files)
249  {
250  if(!std::filesystem::exists(archive_file))
251  {
252  THROW_ERROR("File " + archive_file + " does not exist");
253  }
254  const auto temp_path = unique_path(Param->getOption<std::string>(OPT_output_temporary_directory) +
255  "/temp-archive-dir-%%%%-%%%%-%%%%-%%%%");
256  std::filesystem::create_directories(temp_path);
257  const auto local_archive_file = GetPath(archive_file);
258 
259  const auto command = "cd " + temp_path.string() + "; ar x " + local_archive_file;
260  if(IsError(PandaSystem(Param, command)))
261  {
262  THROW_ERROR("ar returns an error during archive extraction ");
263  }
264  for(const auto& entry : std::filesystem::directory_iterator{temp_path})
265  {
266  const tree_managerRef TM_new = ParseTreeFile(Param, entry.path().string());
267  TM->merge_tree_managers(TM_new);
268  }
269  if(!Param->getOption<bool>(OPT_no_clean))
270  {
271  std::filesystem::remove_all(temp_path);
272  }
273  }
274  }
275  STOP_TIME(tree_time);
276 
277  if(debug_level >= DEBUG_LEVEL_MINIMUM)
278  {
279  dump_exec_time("Tree analysis time", tree_time);
280  }
281  std::string raw_file_name;
282  if(Param->isOption(OPT_compress_archive))
283  {
284  auto archive_file = Param->getOption<std::string>(OPT_compress_archive);
285  std::string fname = archive_file.substr(0, archive_file.find('.'));
286  fname = fname + ".o";
287  {
288  fileIO_ostreamRef raw_file = fileIO_ostream_open(fname);
289  PRINT_DBG_MEX(DEBUG_LEVEL_VERBOSE, debug_level, "Dumping Tree-Manager");
290  (*raw_file) << TM;
291  PRINT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "Dumped Tree-Manager");
292  }
293  std::string command = "ar cru " + archive_file + " " + fname;
294  // std::cout << command << std::endl;
295  int ret = PandaSystem(Param, command);
296  if(IsError(ret))
297  {
298  THROW_ERROR("ar returns an error during archive creation ");
299  }
300  }
301  else
302  {
303  if(Param->isOption(OPT_output_file))
304  {
305  raw_file_name = Param->getOption<std::string>(OPT_output_file);
306  }
307  else
308  {
309  raw_file_name = "a.tree";
310  }
311  fileIO_ostreamRef raw_file = fileIO_ostream_open(raw_file_name);
312  PRINT_DBG_MEX(DEBUG_LEVEL_VERBOSE, debug_level, "Dumping Tree-Manager");
313  (*raw_file) << TM;
314  PRINT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "Dumped Tree-Manager");
315  }
316  }
317  STOP_TIME(total_time);
318 
319  if(debug_level > DEBUG_LEVEL_NONE)
320  {
321  dump_exec_time("\nTotal execution time", total_time);
322  }
323 
324  close_everything(argc, argv, Param);
325  return EXIT_SUCCESS;
326  }
327  catch(const char* str)
328  {
329  std::cerr << str << std::endl;
330  }
331  catch(const std::string& str)
332  {
333  std::cerr << str << std::endl;
334  }
335  catch(std::exception& e)
336  {
337  std::cerr << e.what() << std::endl;
338  }
339  catch(...)
340  {
341  std::cerr << "Unknown error type" << std::endl;
342  }
343 
344  close_everything(argc, argv, Param);
345  return exit_code;
346 }
#define DEBUG_LEVEL_VERY_PEDANTIC
extremely verbose debugging print is performed.
int exit_code
NOTE: this file must be included only by source code of the executable (i.e., the file with the main)...
#define PRINT_DBG_MEX(dbgLevel, curDbgLevel, mex)
We are producing a debug version of the program, so the message is printed;.
fileIO_ostreamRef fileIO_ostream_open(const std::string &name)
this function returns an ostream compressed or not.
Definition: fileIO.hpp:98
static void dealloc_argv(int argc, char *argv_copied[])
This class manages the tree structures extracted from the raw file.
int main(int argc, char *argv_orig[])
Main file used to perform Hardware/Software Codesign starting from C/C++/SystemC specification.
static char * alloc_long_option(char *argv[], int &i, int &dec)
exceptions managed by PandA
Specification of the tree (GCC raw) parsing interface function.
#define OUTPUT_LEVEL_MINIMUM
minimum debugging print is performed.
static void close_everything(int argc, char *argv[], const ParameterRef &Param)
Include a set of utilities used to manage CPU time measures.
static char ** alloc_argv(int &argc, char *argv[])
CompilerWrapper_OptimizationSet
Possible optimization sets.
bool IsError(const int error_value)
Utility include.
Definition: exceptions.cpp:58
std::filesystem::path unique_path(const std::filesystem::path &model)
Definition: fileIO.cpp:286
#define START_TIME(time_var)
Macro used to store the start time into time_var.
Definition: cpu_time.hpp:133
void dump_exec_time(const std::string &thing, long et)
Definition: cpu_time.hpp:126
default table used by THR LLVM optimization step.
#define PARAMETER_PARSED
An integer value to return if parameters have been right parsed.
Definition: Parameter.hpp:93
#define STOP_TIME(time_var)
Macro used to store the elapsed time into time_var.
Definition: cpu_time.hpp:136
refcount< Parameter > ParameterRef
Definition: Parameter.hpp:758
utility function used to read files.
CompilerWrapper_CompilerTarget
target of the compiler
This file collects some utility functions and macros.
#define DEBUG_LEVEL_NONE
no debugging print is performed.
#define THROW_ERROR(str_expr)
helper function used to throw an error in a standard way
Definition: exceptions.hpp:263
list command
Definition: test_panda.py:921
#define STR_cost_latency_table_default
default string for latencies
int PandaSystem(const ParameterConstRef Param, const std::string &system_command, bool host_exec, const std::string &output, const unsigned int type, const bool background, const size_t timeout)
System call forcing execution with bash.
Definition: fileIO.cpp:78
std::string GetPath(std::filesystem::path path)
Definition: fileIO.hpp:140
refcount< CompilerWrapper > CompilerWrapperRef
Refcount definition for the CompilerWrapper class.
Template borrowed from the ANTLR library by Terence Parr (http://www.jGuru.com - Software rights: htt...
Definition: refcount.hpp:94
char str[25]
Definition: fixedptc.c:8
this class is used to manage the command-line or XML options.
Main class for wrapping the frontend compiler.
#define DEBUG_LEVEL_VERBOSE
verbose debugging print is performed.
tree_managerRef ParseTreeFile(const ParameterConstRef &Param, const std::string &f)
Function that parse the dump of the patched GCC.
Definition: parse_tree.cpp:59
Class specification of the manager of the tree structures extracted from the raw file.
#define DEBUG_LEVEL_MINIMUM
minimum debugging print is performed.
#define PARAMETER_NOTPARSED
Definition: Parameter.hpp:94
Implementation of the wrapper to Gcc for C sources.

Generated on Mon Feb 12 2024 13:02:55 for PandA-2024.02 by doxygen 1.8.13