ROSE  0.9.10.44
OmpAttribute.h
1 #ifndef Omp_Attribute_h_INCLUDED
2 #define Omp_Attribute_h_INCLUDED
3 
11 //
12 // Liao 9/17, 2008
13 //
14 
15 #include <iostream>
16 #include <string>
17 #include <map>
18 #include <cassert>
19 #include <vector>
20 class SgNode;
24 namespace OmpSupport
25 {
26  // OpenMP construct name list
27  //-------------------------------------------------------------------
28  // We put all directive and clause types into one enumerate type
29  // since some internal data structure(map) have to access
30  // both directives and clauses uniformly
31  enum omp_construct_enum
32  {
33  e_unknown = 0,
34 
35  // 16 directives as OpenMP 3.0
36  e_parallel,
37  e_for,
38  e_for_simd,
39  e_do,
40  e_workshare,
41  e_sections,
42  e_section,
43  e_single,
44 
45  e_master,
46  e_critical,
47  e_barrier,
48  e_atomic,
49  e_flush,
50 
51  // Liao, 1/15/2013, experimental implementation for the draft OpenMP Accelerator Model technical report
52  e_target,
53  e_target_declare,
54  e_target_data,
55  e_target_update,
56  e_map, // map clauses
57  e_device,
58  e_begin, // 10/29/2015, experimental begin/end directives for SPMD code blocks, without changing variable scopes
59  e_end,
60 
61  e_threadprivate,
62  e_parallel_for,
63  e_parallel_for_simd,
64  e_parallel_do,
65  e_parallel_sections,
66  e_parallel_workshare,
67  e_task,
68  e_taskwait,
69  // we have both ordered directive and ordered clause,
70  //so make the name explicit
71  e_ordered_directive,
72 
73  // Fortran only end directives
74  e_end_critical,
75  e_end_do,
76  e_end_master,
77  e_end_ordered,
78  e_end_parallel_do,
79  e_end_parallel_sections,
80  e_end_parallel_workshare,
81  e_end_parallel,
82  e_end_sections,
83  e_end_single,
84  e_end_task,
85  e_end_workshare,
86 
87  // 15 clauses for OpenMP 3.0
88  // 7 data-sharing attributes clauses
89  e_default, // the clause
90  e_shared,
91  e_private,
92  e_firstprivate,
93  e_lastprivate,
94  e_copyin,
95  e_copyprivate,
96  e_proc_bind,
97 
98  //8 misc clauses
99  e_if, // used with omp parallel or omp task
100  e_num_threads, // for omp parallel only
101  e_nowait,
102  e_ordered_clause,
103  e_reduction,
104  e_schedule,
105  e_collapse,
106  e_untied,
107  e_mergeable,
108  e_final,
109  e_priority,
110  e_atomic_clause,
111  e_inbranch,
112  e_notinbranch,
113 
114  e_depend, // OpenMP 4.0 task clauses
115 
116  // Simple values for some clauses
117 
118  //4 values for default clause
119  //C/C++ default values
120  e_default_none,
121  e_default_shared,
122  //Fortran default values
123  e_default_private,
124  e_default_firstprivate,
125 
126  // proc_bind(master|close|spread)
127  e_proc_bind_master,
128  e_proc_bind_close,
129  e_proc_bind_spread,
130 
131  e_atomic_read,
132  e_atomic_write,
133  e_atomic_update,
134  e_atomic_capture,
135 
136  // reduction operations
137  //8 operand for C/C++
138  // shared 3 common operators for both C and Fortran
139  e_reduction_plus, //+
140  e_reduction_mul, //*
141  e_reduction_minus, // -
142  // C/C++ only
143  e_reduction_bitand, // &
144  e_reduction_bitor, // |
145  e_reduction_bitxor, // ^
146  e_reduction_logand, // &&
147  e_reduction_logor, // ||
148 
149  // Fortran operator
150  e_reduction_and, // .and.
151  e_reduction_or, // .or.
152  e_reduction_eqv, // fortran .eqv.
153  e_reduction_neqv, // fortran .neqv.
154  // reduction intrinsic procedure name for Fortran
155  e_reduction_max,
156  e_reduction_min,
157  e_reduction_iand,
158  e_reduction_ior,
159  e_reduction_ieor,
160 
161  //5 schedule policies for
162  //---------------------
163  e_schedule_none,
164  e_schedule_static,
165  e_schedule_dynamic,
166  e_schedule_guided,
167  e_schedule_auto,
168  e_schedule_runtime,
169 
170  // 4 device map variants
171  //----------------------
172  e_map_alloc,
173  e_map_to,
174  e_map_from,
175  e_map_tofrom,
176 
177  // experimental dist_data clause dist_data(dim1_policy, dim2_policy, dim3_policy)
178  // A policy can be block(n), cyclic(n), or duplicate
179  e_dist_data,
180  e_duplicate,
181  e_block,
182  e_cyclic,
183 
184  // experimental SIMD directive, phlin 8/5/2013
185  e_simd,
186  e_declare_simd,
187  e_safelen,
188  e_simdlen,
189  e_uniform,
190  e_aligned,
191  e_linear,
192 
193  // task dependence type
194  e_depend_in,
195  e_depend_out,
196  e_depend_inout,
197 
198  // not an OpenMP construct
199  e_not_omp
200 
201  }; //end omp_construct_enum
202 
203  // A new variable to communicate the context of OpenMP parser
204  // what directive is being parsed right now.
205  // This is useful for rare case of parsing "declare simd"
206  extern omp_construct_enum cur_omp_directive;
207 
208  //-------------------------------------------------------------------
209  // some utility functions
210 
212  // Better using OmpSupport::toString() to avoid ambiguous
213  std::string toString(omp_construct_enum omp_type);
214 
216  bool isFortranEndDirective(omp_construct_enum omp_type);
217 
219  bool isFortranBeginDirective(omp_construct_enum omp_type);
220 
222  bool isDirective(omp_construct_enum omp_type);
223 
225  bool isDirectiveWithBody(omp_construct_enum omp_type);
226 
228  bool isClause(omp_construct_enum omp_type);
229 
231  bool isReductionOperator(omp_construct_enum omp_type);
232 
234  bool isDependenceType(omp_construct_enum omp_type);
235 
236  class OmpAttribute;
238  //
240  ROSE_DLL_API OmpAttribute* buildOmpAttribute(enum omp_construct_enum directive_type, SgNode* context_node, bool useDefined);
241 
243  ROSE_DLL_API void addOmpAttribute(OmpAttribute* ompattribute, SgNode* node);
244 
246  ROSE_DLL_API void removeOmpAttribute(OmpAttribute* ompattribute, SgNode* node);
247 
249  ROSE_DLL_API bool isEquivalentOmpAttribute (OmpAttribute* a1, OmpAttribute* a2);
250 
251  class OmpAttributeList;
253  ROSE_DLL_API OmpAttributeList* getOmpAttributeList(SgNode* node);
254 
256  OmpAttribute* getOmpAttribute(SgNode* node);
257 
259  omp_construct_enum getOmpConstructEnum(SgPragmaDeclaration* decl);
260 
262  omp_construct_enum getBeginOmpConstructEnum (omp_construct_enum end_enum);
263 
265  omp_construct_enum getEndOmpConstructEnum (omp_construct_enum begin_enum);
266 
268  ROSE_DLL_API void generatePragmaFromOmpAttribute(SgNode* sg_node);
269  //TODO this is duplicated from autoParallization project's generatedOpenMPPragmas()
270  // We should remove this duplicate once autopar is moved into rose/src
271 
273  ROSE_DLL_API std::string generateDiffTextFromOmpAttribute(SgNode* sg_node);
274 
275  //------------------------------------------------------------------
276  // By default, the persistent attribute attached to an OpenMP pragma node in SAGE III AST
277  // Attaching to pragma is easier since a few directives have no obvious
278  // associated code blocks, like threadprivate.
279  //
280  // The attribute can also be attached by a scope affected by OpenMP. This is used during
281  // automatic parallelization when the corresponding pragma is not yet generated.
282  //
283  // A cure-all approach is used to simplify the handling.
284  // OmpAttribute is implemented using a 'flat' data structure encompass all
285  // possible directives, clauses
286  // and their various contents, if any.
287  //
288  // different types of pragmas need different information in some cases
289  // e.g.
290  // 'omp for' needs scheduling type
291  //------------------------------------------------------------------
292 
293  class ROSE_DLL_API OmpAttributeList :public AstAttribute
294  {
295  public:
296  std::vector<OmpAttribute*> ompAttriList;
297  // Restore to legal OpenMP directive strings
298  std::string toOpenMPString();
299  // Pretty print for debugging purpose
300  void print();
301  ~OmpAttributeList();
302 
303  // This attribute attempts to manage its own memory by calling "delete" whenever the attribute is removed from an AST
304  // node. It avoids memory leaks by not allowing OmpAttributeList attributes to be copied (no virtual "copy"
305  // constructor), and it never tries to replace one OmpAttributeList object with another with AstAttributeMechanism's
306  // "set" or "replace" methods or the corresponding methods in SgNode. However, it leaks memory if an AST node is deleted.
307  virtual OwnershipPolicy getOwnershipPolicy() const ROSE_OVERRIDE {
308  return CUSTOM_OWNERSHIP;
309  }
310  // MS2018: added to fix warning
311  virtual std::string attribute_class_name() const;
312  virtual OmpAttributeList* copy();
313  };
314 
316  class ROSE_DLL_API OmpAttribute
317  {
318  public:
321  SgPragmaDeclaration* getPragmaDeclaration();
322 
325  void setPreprocessingInfo(PreprocessingInfo* info) { pinfo=info;};
326 
328  SgNode* getNode(){return mNode;};
329  void setNode(SgNode* n) { mNode= n;};
331  void setOmpDirectiveType(omp_construct_enum omptype){ assert (isDirective(omptype)); omp_type = omptype;}
332  omp_construct_enum getOmpDirectiveType() {return omp_type;}
333 
336  void addClause(omp_construct_enum clause_type);
338  bool hasClause(omp_construct_enum clause_type);
339 
341  std::vector<omp_construct_enum> getClauses();
342 
345  SgVariableSymbol* addVariable(omp_construct_enum targetConstruct, const std::string& varString, SgInitializedName* sgvar=NULL);
346 
348  SgVariableSymbol* addVariable(omp_construct_enum targetConstruct, SgExpression* varExp);
349 
351  bool hasVariableList(omp_construct_enum);
353  std::vector<std::pair<std::string,SgNode* > >
354  getVariableList(omp_construct_enum);
355 
357  // We store a list (vector) of dimension bounds for each array variable
358  std::map<SgSymbol*, std::vector < std::pair <SgExpression*, SgExpression*> > > array_dimensions;
359 
360  // dist_data (dim1_policy, dim2_policy, dim3_policy) for mapped arrays
361  // we use std::map <variable, policy_vector> to represent this.
362  // the policy vector contains up to three pair of (policy, optional size)
363  // e.g. map(x[0:n][0:m] dist_data(duplicate, block(2)))
364  // -----------------------------------
365  std::map <SgSymbol* , std::vector < std::pair<omp_construct_enum, SgExpression*> > > dist_data_policies;
366 
368  std::vector<enum omp_construct_enum> get_clauses(const std::string& variable);
369 
371  bool appendDistDataPolicy(SgVariableSymbol* array_symbol, omp_construct_enum dist_data_policy, SgExpression* size_exp = NULL);
372 
374  std::vector < std::pair < omp_construct_enum, SgExpression*> > getDistDataPolicy (SgVariableSymbol* array_symbol);
375 
378  void addExpression(omp_construct_enum targetConstruct, const std::string& expString, SgExpression* sgexp=NULL);
379 
381  std::pair<std::string, SgExpression*>
382  getExpression(omp_construct_enum targetConstruct);
383 
385  //
386  // Reduction needs special handling
387  // since multiple ones with different operator types can co-exist within one pragma
388  // We categories reduction clauses by their operator type and store variable lists for each of the reduction operator type, not with the reduction clause
389 
390  // Add a new reduction clause with the specified operator
391  void setReductionOperator(omp_construct_enum operatorx);
392 
394  std::vector<omp_construct_enum> getReductionOperators();
395 
397  bool hasReductionOperator(omp_construct_enum operatorx);
398 
399  //------------------------------------------
400  // Add a new clause with the specified operator
401  void setDependenceType(omp_construct_enum operatorx);
402 
404  std::vector<omp_construct_enum> getDependenceTypes();
405 
407  bool hasDependenceType(omp_construct_enum operatorx);
408 
409 
410  // map clause is similar to reduction clause,
411  //
412  // Add a new map clauses with the specified variant type
413  void setMapVariant(omp_construct_enum operatorx);
415  std::vector<omp_construct_enum> getMapVariants();
417  bool hasMapVariant(omp_construct_enum operatorx);
418 
420  bool isMapVariant(omp_construct_enum omp_type);
421 
422  // default () value
423  void setDefaultValue(omp_construct_enum valuex);
424  omp_construct_enum getDefaultValue();
425 
426  // proc_bind() policy
427  void setProcBindPolicy(omp_construct_enum valuex);
428  omp_construct_enum getProcBindPolicy();
429 
430  //Atomicity of Atomic Clause
431  void setAtomicAtomicity(omp_construct_enum valuex);
432  omp_construct_enum getAtomicAtomicity();
433 
434  // Schedule kind
435  omp_construct_enum getScheduleKind();
436  void setScheduleKind(omp_construct_enum kindx);
437 
439  bool isInConstruct(const std::string & variable, enum omp_construct_enum);
440 
442  void setCriticalName(const std::string & name);
443  std::string getCriticalName() {return name;};
444  bool isNamedCritical(){return hasName;};
445 
447  void print();
448 
450  bool get_isUserDefined() {return isUserDefined; }
451 
453  //not named toString() to void ambiguous with OmpAttribute::toString()
454  std::string toOpenMPString();
455  friend OmpAttribute* buildOmpAttribute(omp_construct_enum directive_type, SgNode* node, bool userDefined);
456  //------------------hide the implementation details, could be changed anytime!!
457  //----------------------------------------------------------------------------
458  private:
459  //It is recommended to use OmpSupport::buildOmpAttribute() instead of
460  //using the constructors here
462  OmpAttribute()
463  {
464  mNode = NULL;
465  omp_type = e_unknown;
466  init();
467  isUserDefined = true;
468  }
470  OmpAttribute(omp_construct_enum omptype, SgNode* mynode):
471  mNode(mynode),omp_type(omptype){
472  /*The initialization order has to match the declaration order,
473  * otherwise get a compilation warning*/
474  init();
475  isUserDefined = true;
476  if (mNode != NULL )
477  {
478  SgLocatedNode * lnode = isSgLocatedNode (mNode);
479  ROSE_ASSERT (lnode != NULL);
480  //ROSE_ASSERT (lnode->get_file_info()->get_filename()!=std::string("transformation"));
481  }
482  // Liao 2/12/2010, we allow build empty attribute as a replacement of a default constructor.
483  // This is used by autoParallization to tentatively create an instance and later fill data fields.
484  // assert(isDirective(omptype));
485  }
486 
488  SgNode* mNode;
490  PreprocessingInfo* pinfo;
491 
493  bool isUserDefined;
494 
496  enum omp_construct_enum omp_type;
497 
499  // vector is used to preserve the order of clauses in the directive
500  // map is used to fast query if a clause exists or not
501  // Some clauses are allowed to appear more than once, merge the content into the first occurrence in our implementation.
502  std::vector<omp_construct_enum> clauses;
503  std::map<omp_construct_enum,bool> clause_map;
504 
505  // Multiple reduction clauses, each has a different operator
506  //value for reduction operation: + -, * & | etc
507  std::vector<omp_construct_enum> reduction_operators;
508 
510  std::vector<omp_construct_enum> dependence_types;
511 
512  // Liao, 1/15/2013, map variant:
513  // there could be multiple map clause with the same variant type: alloc, to, from , and tofrom.
514  std::vector<omp_construct_enum> map_variants;
515  //enum omp_construct_enum map_variant;
516 
517  //variable lists-------------------
518  //appeared within some directives and clauses
519  //The clauses/directive are: flush, threadprivate, private, firstprivate,
520  // shared, copyin, reduction, lastprivate, copyprivate
521  // We use a pair of (name, SgNode) for each variable
522  // It is highly possible that a variable having more than one OpenMP properties.
523  // For example, a variable can be both firstprivate and lastprivate.
524  std::map<omp_construct_enum, std::vector<std::pair<std::string,SgNode* > > > variable_lists;
525  // A reverse map from a variable to the clauses the variable appears
526  std::map<std::string, std::vector<omp_construct_enum> > var_clauses;
527 
528 
529  // expressions ----------------------
530  // e.g.: if (exp), num_threads(exp), schedule(,exp), collapse(exp)
531  std::map<omp_construct_enum, std::pair<std::string, SgExpression*> > expressions;
532 
533  // values for some clauses -------------------------
534  // values for default() clause: data scoping information
535  // choices are: none,shared, private, firstprivate
536  omp_construct_enum default_scope;
537 
538  // values for proc_bind() clause
539  omp_construct_enum proc_bind_policy;
540 
541  // Atomic clause's atomicity
542  omp_construct_enum atomicity;
543 
544  // value for omp for's schedule policies
545  omp_construct_enum schedule_kind;
546 
547  // Only used for omp critical to indicate if it is named or not
548  // name for the directive, only used for omp critical
549  bool hasName;
550  std::string name;
551 
552  // Misc fields --------------------------------
553  // help translation and analysis
554  bool isOrphaned; //true if parent omp parallel is not in the static lexical scope
555 
556  // Additional information to help translation
557  int wrapperCount; // the shared variables from the same scope which needs wrapper
558 
559  //optional information
560  OmpAttribute * parent; //upper-level OMP pragma's attribute
561 
564  void init() ;
565 
567  // invoke OmpSupport::toString() to stringify the enumerate type internally
568  // some variables have the optional dist_data policy
569  std::string toOpenMPString(omp_construct_enum omp_type);
570 
572  std::string toOpenMPString(std::vector<std::pair<std::string,SgNode* > > varList, bool checkDistPolicy = false);
573 
575  std::string toOpenMPString (std::vector < std::pair <omp_construct_enum, SgExpression*> > dim_policies);
576  }; // end class OmpAttribute
577 
578 
579  // save encountered Fortran OpenMP directives here.
580  // We reuse the list later on to build OpenMP AST for Fortran
581  extern std::list<OmpAttribute* > omp_comment_list;
582 
583 
584 } //end namespace OmpSupport
585 
586 #endif //Omp_Attribute_h_INCLUDED
587 
bool isDirectiveWithBody(omp_construct_enum omp_type)
Check if an OpenMP directive has a structured body.
SgNode * getNode()
Get the associated SgNode, can be SgPragmaDeclaration or others( for fortran nodes or during parallel...
Definition: OmpAttribute.h:328
This class represents the notion of a declared variable.
omp_construct_enum getEndOmpConstructEnum(omp_construct_enum begin_enum)
Get the corresponding end construct enum from a begin construct enum.
ROSE_DLL_API bool isEquivalentOmpAttribute(OmpAttribute *a1, OmpAttribute *a2)
Check if two OmpAttributes are semantically equivalent to each other.
ROSE_DLL_API OmpAttributeList * getOmpAttributeList(SgNode *node)
Get OmpAttribute from a SgNode, return NULL if not found.
OmpAttribute * getOmpAttribute(SgNode *node)
Get the first OmpAttribute from a SgNode, return NULL if not found.
omp_construct_enum getBeginOmpConstructEnum(omp_construct_enum end_enum)
Get the corresponding begin construct enum from an end construct enum.
This class represents the notion of an expression. Expressions are derived from SgLocatedNodes, since similar to statement, expressions have a concrete location within the user's source code.
bool isFortranBeginDirective(omp_construct_enum omp_type)
Check if the construct is a Fortran directive which can (optionally) have a corresponding END directi...
bool isReductionOperator(omp_construct_enum omp_type)
Check if an OpenMP construct is a reduction operator.
bool isClause(omp_construct_enum omp_type)
Check if an OpenMP construct is a clause.
bool isDependenceType(omp_construct_enum omp_type)
Check if an OpenMP construct is a dependence type for omp task depend.
ROSE_DLL_API void generatePragmaFromOmpAttribute(SgNode *sg_node)
Generate a pragma declaration from OmpAttribute attached to a statement.
One attribute object stores all information within an OpenMP pragma (directive and clauses) ...
Definition: OmpAttribute.h:316
ROSE_DLL_API OmpAttribute * buildOmpAttribute(enum omp_construct_enum directive_type, SgNode *context_node, bool useDefined)
Some utility functions to manipulate OmpAttribute.
This class represents the base class for all IR nodes within Sage III.
Definition: Cxx_Grammar.h:8672
This class represents the concept of a variable name within the compiler (a shared container for the ...
bool isDirective(omp_construct_enum omp_type)
Check if an OpenMP construct is a directive.
For preprocessing information including source comments, #include , #if, #define, etc...
ROSE_DLL_API bool hasClause(SgOmpClauseBodyStatement *clause_stmt, const VariantT &vt)
Check if an OpenMP statement has a clause of type vt.
This class represents the concept of a C Assembler statement (untested).
bool isFortranEndDirective(omp_construct_enum omp_type)
Check if the construct is a Fortran END ... directive.
ROSE_DLL_API void removeOmpAttribute(OmpAttribute *ompattribute, SgNode *node)
Remove OmpAttribute from a SgNode.
This class represents the notion of an expression or statement which has a position within the source...
PreprocessingInfo * getPreprocessingInfo()
Get the associated PreprocessingInfo for Fortran, if any.
Definition: OmpAttribute.h:324
Types and functions to support OpenMP.
std::string toString(omp_construct_enum omp_type)
Output omp_construct_enum to a string:
ROSE_DLL_API void addOmpAttribute(OmpAttribute *ompattribute, SgNode *node)
Add OmpAttribute to a SgNode.
omp_construct_enum getOmpConstructEnum(SgPragmaDeclaration *decl)
Get omp enum from an OpenMP pragma attached with OmpAttribute.
std::map< SgSymbol *, std::vector< std::pair< SgExpression *, SgExpression * > > > array_dimensions
Dimension information for array variables, used by map clause, such as map (tofrom:array[0:n][0:m]) ...
Definition: OmpAttribute.h:358
void setOmpDirectiveType(omp_construct_enum omptype)
---------—directive type----—
Definition: OmpAttribute.h:331
ROSE_DLL_API std::string generateDiffTextFromOmpAttribute(SgNode *sg_node)
Generate diff text from OmpAttribute attached to a statement.