PandA-2024.02
PragmaParser.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  */
46 #include "PragmaParser.hpp"
47 
48 #include "Parameter.hpp"
49 #include "exceptions.hpp"
50 #include "fileIO.hpp"
51 #include "pragma_constants.hpp"
52 #include "pragma_manager.hpp"
53 #include "string_manipulation.hpp"
54 
55 #include <filesystem>
56 #include <fstream>
57 
58 unsigned int PragmaParser::number = 0;
59 
60 // constructor
62  : PM(_PM),
63  debug_level(_Param->get_class_debug_level(GET_CLASS(*this))),
64  Param(_Param),
65  level(0),
66  search_function(false)
67 {
68  THROW_ASSERT(PM, "Pragma manager not initialized");
69 }
70 
71 // destructor
72 PragmaParser::~PragmaParser() = default;
73 
74 std::string PragmaParser::substitutePragmas(const std::string& input_filename)
75 {
76  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "-->Substituting pragma in " + input_filename);
77  THROW_ASSERT(std::filesystem::exists(std::filesystem::path(input_filename)),
78  "Input file \"" + input_filename + "\" does not exist");
79 
80  const auto temp_path = Param->getOption<std::string>(OPT_output_temporary_directory) + "pragma";
81  std::filesystem::create_directories(temp_path);
82  const auto output_filename = temp_path + "/" + std::filesystem::path(input_filename).filename().string();
83  std::ofstream fileOutput(output_filename, std::ios::out);
84 
85  level = 0;
86  // unsigned line_number = 0;
87 
88  // Get a stream from the input file
89  std::ifstream instream(input_filename);
90  // Test if the file has been correctly opened
91  THROW_ASSERT(instream.is_open(), "INPUT FILE ERROR: Could not open input file: " + input_filename);
92  while(!instream.eof())
93  {
94  std::string input_line;
95  getline(instream, input_line);
96  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "Read line <" + input_line + ">");
97  std::string output_line = input_line;
98 
100  if(search_function)
101  {
102  std::string::size_type notwhite = output_line.find_first_of('(');
103  if(notwhite != std::string::npos)
104  {
105  std::string Token = input_line;
106  Token.erase(notwhite);
107  name_function += Token;
108 
109  notwhite = name_function.find_last_not_of(" \t\r\n");
110  name_function.erase(notwhite + 1);
111  notwhite = name_function.find_last_of(" \t\n*>");
112  name_function.erase(0, notwhite + 1);
114 
116  if(level == 0)
117  {
118  PM->AddFunctionDefinitionPragmas(name_function, FunctionPragmas);
119  }
120 
121  name_function.clear();
122  search_function = false;
123  FunctionPragmas.clear();
124  }
125  else
126  {
127  name_function += input_line + " ";
128  }
129  }
130  if(input_line.find("#pragma") != std::string::npos)
131  {
133  output_line = input_line;
134  char const* delims = " \t\r\n";
135  // trim leading whitespace
136  std::string::size_type notwhite = output_line.find_first_not_of(delims);
137  output_line.erase(0, notwhite);
138  // trim trailing whitespace
139  notwhite = output_line.find_last_not_of(delims);
140  output_line.erase(notwhite + 1);
141 
142  analyze_pragma(output_line);
143  }
144 
146  fileOutput << output_line << std::endl;
147 
149  bool found = false;
150  for(char i : input_line)
151  {
152  if(i == '{')
153  {
154  level++;
156  "---Found {: Current level " + std::to_string(level));
157  if(!found)
158  {
159  for(auto& FloatingPragma : FloatingPragmas)
160  {
161  OpenPragmas[level].push_back(FloatingPragma);
162  }
163  FloatingPragmas.clear();
164  }
165  found = true;
166  }
167  if(i == '}')
168  {
169  if(OpenPragmas.count(level))
170  {
171  for(auto& open_pragma : OpenPragmas[level])
172  {
173  fileOutput << std::string(STR_CST_pragma_function_end) + "(\"" << open_pragma << "\");" << std::endl;
174  }
175  OpenPragmas[level].clear();
176  }
177  level--;
179  "---Found }: Current level " + std::to_string(level));
180  }
181  }
182 
184  // line_number++;
185  }
186 
187  fileOutput.close();
188  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Substituted pragma in " + input_filename);
189  return output_filename;
190 }
191 
192 bool PragmaParser::analyze_pragma(std::string& Line)
193 {
195  if(Line.find(STR_CST_pragma_keyword_omp) != std::string::npos)
196  {
197  if(!Param->getOption<bool>(OPT_ignore_parallelism))
198  {
199  return recognize_omp_pragma(Line);
200  }
201  else
202  {
203  return false;
204  }
205  }
206 
207  if(Line.find("call_hw") != std::string::npos)
208  {
210  if(!Param->getOption<bool>(OPT_ignore_mapping) and !Param->getOption<bool>(OPT_mapping))
211  {
212  return recognize_mapping_pragma(Line);
213  }
214  else
215  {
216  return false;
217  }
218  }
219 
221  if(Line.find("call_point_hw") != std::string::npos)
222  {
223  return recognize_call_point_hw_pragma(Line);
224  }
225 
227  if(Line.find("issue") != std::string::npos)
228  {
229  return recognize_issue_pragma(Line);
230  }
231 
233  if(Line.find("profiling") != std::string::npos)
234  {
235  return recognize_profiling_pragma(Line);
236  }
237 
239  if(Line.find("generate_hw") != std::string::npos)
240  {
241  Line.clear();
242  return true;
243  }
244 
246  return recognize_generic_pragma(Line);
247 }
248 
250 {
251  INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---Looking for openmp pragma in " + line);
252  std::string original_line = line;
254  if(omp_pragma_type == pragma_manager::OMP_UNKNOWN)
255  {
256  THROW_ERROR("Unsupported openmp directive in line " + line);
257  }
258  bool single_line_pragma = false;
260  "---Found directive " + pragma_manager::omp_directive_keywords[omp_pragma_type]);
261  switch(omp_pragma_type)
262  {
268  {
269  search_function = true;
270  single_line_pragma = true;
272  break;
273  }
275  {
276  FunctionPragmas.insert(line);
277  search_function = true;
278  return true;
279  }
287  {
288  line = std::string(STR_CST_pragma_function_start) + "(\"" STR_CST_pragma_keyword_omp "\", ";
289  break;
290  }
292  {
293  THROW_UNREACHABLE("Unsupported openmp directive in line " + line);
294  break;
295  }
296  default:
297  {
298  THROW_UNREACHABLE("");
299  }
300  }
301  const std::string omp_pragma_directive = pragma_manager::omp_directive_keywords[omp_pragma_type];
302  line += "\"" + omp_pragma_directive + "\"";
303  original_line.erase(0, original_line.find(omp_pragma_directive) + omp_pragma_directive.size());
304  if(not single_line_pragma)
305  {
306  FloatingPragmas.push_back(
307  STR_CST_pragma_keyword_omp "\", \"" + omp_pragma_directive +
308  (original_line.size() ? "\", \"" + original_line.substr(1, original_line.size() - 1) : ""));
309  }
310 
311  if(original_line.size())
312  {
313  line += ", \"" + original_line.substr(1, original_line.size() - 1) + "\"";
314  }
315  line += ");";
316  return true;
317 }
318 
320 {
321  const std::string old_line = line;
322  line = std::string(STR_CST_pragma_function_single_line_two_arguments) + "(";
323  line += "\"" + std::string(STR_CST_pragma_keyword_map) + "\"";
324  line += ", ";
325  std::vector<std::string> splitted = SplitString(old_line, " ");
326  THROW_ASSERT(splitted.size() == 4 or splitted.size() == 5, "Error in syntax of mapping pragma: " + old_line);
327  THROW_ASSERT(splitted[2] == std::string(STR_CST_pragma_keyword_call_point_hw),
328  "Expecting " + std::string(STR_CST_pragma_keyword_call_point_hw) + " - Found : " + splitted[2]);
329  line += "\"" + std::string(STR_CST_pragma_keyword_call_point_hw) + "\"";
330  line += ", \"" + splitted[3] + "\"";
331  if(splitted.size() == 5)
332  {
333  line += ", \"" + splitted[4] + "\"";
334  }
335  line += ");";
336  return true;
337 }
338 
340 {
341  if(level == 0)
342  {
343  FunctionPragmas.insert(Line);
344  search_function = true;
345  return true;
346  }
347  else
348  {
349  PM->setGenericPragma(number, Line);
350  Line = "__pragma__" + std::to_string(number) + "_();";
351  number++;
352  return false;
353  }
354 }
355 
357 {
358  FunctionPragmas.insert(Line);
359  search_function = true;
360  return false;
361 }
362 
364 {
365  FunctionPragmas.insert(Line);
366  search_function = true;
367  return false;
368 }
369 
371 {
372  // Line = "__pragma__(\"generic\", \"" + Line + "\");";
373  if(level == 0)
374  {
375  FunctionPragmas.insert(Line);
376  search_function = true;
377  }
378  else
379  {
380  PM->setGenericPragma(number, Line);
381  Line = "__pragma__" + std::to_string(number) + "_();";
382  number++;
383  }
384  return false;
385 }
const ParameterConstRef Param
reference to the parameter data-structure
#define DEBUG_LEVEL_VERY_PEDANTIC
extremely verbose debugging print is performed.
#define INDENT_DBG_MEX(dbgLevel, curDbgLevel, mex)
We are producing a debug version of the program, so the message is printed;.
static const std::string omp_directive_keywords[OMP_UNKNOWN]
The list of omp directive keywords.
#define GET_CLASS(obj)
Macro returning the actual type of an object.
const int debug_level
current debugging level
const std::vector< std::string > SplitString(const std::string &input, const std::string &separators)
Function which splits a string into tokens.
#define STR_CST_pragma_function_end
The function replacing an ending pragma.
exceptions managed by PandA
unsigned int level
counter for nesting level
constant strings used in pragma identification
void line(int x1, int y1, int x2, int y2, unsigned int color)
Definition: main.c:110
Auxiliary methods for manipulating string.
bool recognize_generic_pragma(std::string &Line)
Retrieve information about a generic pragma directive (i.e., none of the known ones has been detected...
const pragma_managerRef PM
pointer to the pragma manager data-structure
#define THROW_UNREACHABLE(str_expr)
helper function used to specify that some points should never be reached
Definition: exceptions.hpp:292
#define STR_CST_pragma_function_single_line_two_arguments
The function replacing a single line pragma with two argument.
std::map< unsigned int, std::list< std::string > > OpenPragmas
#define STR_CST_pragma_function_single_line_one_argument
The function replacing a single line pragma with single argument.
bool recognize_mapping_pragma(std::string &Line)
Retrieve information about a pragma directive when a mapping pragma has been found.
#define STR_CST_pragma_keyword_call_point_hw
The call_point_hw pragma keyword.
Manager for pragma annotations.
utility function used to read files.
CustomUnorderedSet< std::string > FunctionPragmas
OmpPragmaType
The possible openmp pragmas Note that sections has to go before section but after parallel sections o...
std::string name_function
#define THROW_ERROR(str_expr)
helper function used to throw an error in a standard way
Definition: exceptions.hpp:263
#define STR_CST_pragma_keyword_map
The keyword &#39;map&#39; which identifies mapping pragmas.
static unsigned int number
counter of generic pragma
Parsing pragma from C sources.
#define STR_CST_pragma_keyword_omp
The keyword &#39;omp&#39; which identifies openmp pragmas.
bool recognize_issue_pragma(std::string &Line)
Retrieve information about a pragma directive when an issue pragma has been found.
~PragmaParser()
Destructor.
Template borrowed from the ANTLR library by Terence Parr (http://www.jGuru.com - Software rights: htt...
Definition: refcount.hpp:94
bool analyze_pragma(std::string &Line)
Retrieve information about a pragma directive when the token "#pragma" has been found.
int level
Definition: main.c:98
std::list< std::string > FloatingPragmas
this class is used to manage the command-line or XML options.
bool recognize_omp_pragma(std::string &Line)
Retrieve information about a pragma directive when a OpenMP (parallelism) pragma has been found...
PragmaParser(const pragma_managerRef PM, const ParameterConstRef Param)
Constructor.
std::string substitutePragmas(const std::string &OldFile)
Substitute the pragmas with proper functions.
bool recognize_call_point_hw_pragma(std::string &line) const
Retrieve information about a pragma directive of type pragma map call_point_hw.
static OmpPragmaType GetOmpPragmaType(const std::string &directive)
Returns the identifier corresponding to an openmp directive.
#define STR_CST_pragma_function_start
The function replacing an opening pragma.
bool recognize_profiling_pragma(std::string &Line)
Retrieve information about a pragma directive when a profiling pragma has been found.
#define THROW_ASSERT(cond, str_expr)
helper function used to check an assert and if needed to throw an error in a standard way ...
Definition: exceptions.hpp:289

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