ROSE  0.11.145.0
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 
143  // C/C++ only
144  e_reduction_bitand, // &
145  e_reduction_bitor, // |
146  e_reduction_bitxor, // ^
147  e_reduction_logand, // &&
148  e_reduction_logor, // ||
149 
150  // Fortran operator
151  e_reduction_and, // .and.
152  e_reduction_or, // .or.
153  e_reduction_eqv, // fortran .eqv.
154  e_reduction_neqv, // fortran .neqv.
155 
156  // reduction intrinsic procedure name for Fortran
157  // min, max also for C
158  e_reduction_max,
159  e_reduction_min,
160 
161  e_reduction_iand,
162  e_reduction_ior,
163  e_reduction_ieor,
164 
165  //5 schedule policies for
166  //---------------------
167  e_schedule_none,
168  e_schedule_static,
169  e_schedule_dynamic,
170  e_schedule_guided,
171  e_schedule_auto,
172  e_schedule_runtime,
173 
174  // 4 device map variants
175  //----------------------
176  e_map_alloc,
177  e_map_to,
178  e_map_from,
179  e_map_tofrom,
180 
181  // experimental dist_data clause dist_data(dim1_policy, dim2_policy, dim3_policy)
182  // A policy can be block(n), cyclic(n), or duplicate
183  e_dist_data,
184  e_duplicate,
185  e_block,
186  e_cyclic,
187 
188  // experimental SIMD directive, phlin 8/5/2013
189  e_simd,
190  e_declare_simd,
191  e_safelen,
192  e_simdlen,
193  e_uniform,
194  e_aligned,
195  e_linear,
196 
197  // task dependence type
198  e_depend_in,
199  e_depend_out,
200  e_depend_inout,
201 
202  // not an OpenMP construct
203  e_not_omp
204 
205  }; //end omp_construct_enum
206 
207  // A new variable to communicate the context of OpenMP parser
208  // what directive is being parsed right now.
209  // This is useful for rare case of parsing "declare simd"
210  extern omp_construct_enum cur_omp_directive;
211 
212  //-------------------------------------------------------------------
213  // some utility functions
214 
216  // Better using OmpSupport::toString() to avoid ambiguous
217  std::string toString(omp_construct_enum omp_type);
218 
220  bool isFortranEndDirective(omp_construct_enum omp_type);
221 
223  bool isFortranBeginDirective(omp_construct_enum omp_type);
224 
226  bool isDirective(omp_construct_enum omp_type);
227 
229  bool isDirectiveWithBody(omp_construct_enum omp_type);
230 
232  bool isClause(omp_construct_enum omp_type);
233 
235  bool isReductionOperator(omp_construct_enum omp_type);
236 
238  bool isDependenceType(omp_construct_enum omp_type);
239 
240  class OmpAttribute;
242  //
244  ROSE_DLL_API OmpAttribute* buildOmpAttribute(enum omp_construct_enum directive_type, SgNode* context_node, bool useDefined);
245 
247  ROSE_DLL_API void addOmpAttribute(OmpAttribute* ompattribute, SgNode* node);
248 
250  ROSE_DLL_API void removeOmpAttribute(OmpAttribute* ompattribute, SgNode* node);
251 
253  ROSE_DLL_API bool isEquivalentOmpAttribute (OmpAttribute* a1, OmpAttribute* a2);
254 
255  class OmpAttributeList;
257  ROSE_DLL_API OmpAttributeList* getOmpAttributeList(SgNode* node);
258 
260  OmpAttribute* getOmpAttribute(SgNode* node);
261 
263  omp_construct_enum getOmpConstructEnum(SgPragmaDeclaration* decl);
264 
266  omp_construct_enum getBeginOmpConstructEnum (omp_construct_enum end_enum);
267 
269  omp_construct_enum getEndOmpConstructEnum (omp_construct_enum begin_enum);
270 
272  ROSE_DLL_API void generatePragmaFromOmpAttribute(SgNode* sg_node);
273  //TODO this is duplicated from autoParallization project's generatedOpenMPPragmas()
274  // We should remove this duplicate once autopar is moved into rose/src
275 
277  ROSE_DLL_API std::string generateDiffTextFromOmpAttribute(SgNode* sg_node);
278 
279  //------------------------------------------------------------------
280  // By default, the persistent attribute attached to an OpenMP pragma node in SAGE III AST
281  // Attaching to pragma is easier since a few directives have no obvious
282  // associated code blocks, like threadprivate.
283  //
284  // The attribute can also be attached by a scope affected by OpenMP. This is used during
285  // automatic parallelization when the corresponding pragma is not yet generated.
286  //
287  // A cure-all approach is used to simplify the handling.
288  // OmpAttribute is implemented using a 'flat' data structure encompass all
289  // possible directives, clauses
290  // and their various contents, if any.
291  //
292  // different types of pragmas need different information in some cases
293  // e.g.
294  // 'omp for' needs scheduling type
295  //------------------------------------------------------------------
296 
297  class ROSE_DLL_API OmpAttributeList :public AstAttribute
298  {
299  public:
300  std::vector<OmpAttribute*> ompAttriList;
301  // Restore to legal OpenMP directive strings
302  std::string toOpenMPString();
303  // Pretty print for debugging purpose
304  void print();
305  ~OmpAttributeList();
306 
307  // This attribute attempts to manage its own memory by calling "delete" whenever the attribute is removed from an AST
308  // node. It avoids memory leaks by not allowing OmpAttributeList attributes to be copied (no virtual "copy"
309  // constructor), and it never tries to replace one OmpAttributeList object with another with AstAttributeMechanism's
310  // "set" or "replace" methods or the corresponding methods in SgNode. However, it leaks memory if an AST node is deleted.
311  virtual OwnershipPolicy getOwnershipPolicy() const override {
312  return CUSTOM_OWNERSHIP;
313  }
314  // MS2018: added to fix warning
315  virtual std::string attribute_class_name() const override;
316  virtual OmpAttributeList* copy() override;
317  };
318 
320  class ROSE_DLL_API OmpAttribute
321  {
322  public:
325  SgPragmaDeclaration* getPragmaDeclaration();
326 
329  void setPreprocessingInfo(PreprocessingInfo* info) { pinfo=info;};
330 
332  SgNode* getNode(){return mNode;};
333  void setNode(SgNode* n) { mNode= n;};
335  void setOmpDirectiveType(omp_construct_enum omptype){ assert (isDirective(omptype)); omp_type = omptype;}
336  omp_construct_enum getOmpDirectiveType() {return omp_type;}
337 
340  void addClause(omp_construct_enum clause_type);
342  bool hasClause(omp_construct_enum clause_type);
343 
345  std::vector<omp_construct_enum> getClauses();
346 
349  SgVariableSymbol* addVariable(omp_construct_enum targetConstruct, const std::string& varString, SgInitializedName* sgvar=NULL);
350 
352  SgVariableSymbol* addVariable(omp_construct_enum targetConstruct, SgExpression* varExp);
353 
355  bool hasVariableList(omp_construct_enum);
357  std::vector<std::pair<std::string,SgNode* > >
358  getVariableList(omp_construct_enum);
359 
361  // We store a list (vector) of dimension bounds for each array variable
362  std::map<SgSymbol*, std::vector < std::pair <SgExpression*, SgExpression*> > > array_dimensions;
363 
364  // dist_data (dim1_policy, dim2_policy, dim3_policy) for mapped arrays
365  // we use std::map <variable, policy_vector> to represent this.
366  // the policy vector contains up to three pair of (policy, optional size)
367  // e.g. map(x[0:n][0:m] dist_data(duplicate, block(2)))
368  // -----------------------------------
369  std::map <SgSymbol* , std::vector < std::pair<omp_construct_enum, SgExpression*> > > dist_data_policies;
370 
372  std::vector<enum omp_construct_enum> get_clauses(const std::string& variable);
373 
375  bool appendDistDataPolicy(SgVariableSymbol* array_symbol, omp_construct_enum dist_data_policy, SgExpression* size_exp = NULL);
376 
378  std::vector < std::pair < omp_construct_enum, SgExpression*> > getDistDataPolicy (SgVariableSymbol* array_symbol);
379 
382  void addExpression(omp_construct_enum targetConstruct, const std::string& expString, SgExpression* sgexp=NULL);
383 
385  std::pair<std::string, SgExpression*>
386  getExpression(omp_construct_enum targetConstruct);
387 
389  //
390  // Reduction needs special handling
391  // since multiple ones with different operator types can co-exist within one pragma
392  // We categories reduction clauses by their operator type and store variable lists for each of the reduction operator type, not with the reduction clause
393 
394  // Add a new reduction clause with the specified operator
395  void setReductionOperator(omp_construct_enum operatorx);
396 
398  std::vector<omp_construct_enum> getReductionOperators();
399 
401  bool hasReductionOperator(omp_construct_enum operatorx);
402 
403  //------------------------------------------
404  // Add a new clause with the specified operator
405  void setDependenceType(omp_construct_enum operatorx);
406 
408  std::vector<omp_construct_enum> getDependenceTypes();
409 
411  bool hasDependenceType(omp_construct_enum operatorx);
412 
413 
414  // map clause is similar to reduction clause,
415  //
416  // Add a new map clauses with the specified variant type
417  void setMapVariant(omp_construct_enum operatorx);
419  std::vector<omp_construct_enum> getMapVariants();
421  bool hasMapVariant(omp_construct_enum operatorx);
422 
424  bool isMapVariant(omp_construct_enum omp_type);
425 
426  // default () value
427  void setDefaultValue(omp_construct_enum valuex);
428  omp_construct_enum getDefaultValue();
429 
430  // proc_bind() policy
431  void setProcBindPolicy(omp_construct_enum valuex);
432  omp_construct_enum getProcBindPolicy();
433 
434  //Atomicity of Atomic Clause
435  void setAtomicAtomicity(omp_construct_enum valuex);
436  omp_construct_enum getAtomicAtomicity();
437 
438  // Schedule kind
439  omp_construct_enum getScheduleKind();
440  void setScheduleKind(omp_construct_enum kindx);
441 
443  bool isInConstruct(const std::string & variable, enum omp_construct_enum);
444 
446  void setCriticalName(const std::string & name);
447  std::string getCriticalName() {return name;};
448  bool isNamedCritical(){return hasName;};
449 
451  void print();
452 
454  bool get_isUserDefined() {return isUserDefined; }
455 
457  //not named toString() to void ambiguous with OmpAttribute::toString()
458  std::string toOpenMPString();
459  friend OmpAttribute* buildOmpAttribute(omp_construct_enum directive_type, SgNode* node, bool userDefined);
460  //------------------hide the implementation details, could be changed anytime!!
461  //----------------------------------------------------------------------------
462  private:
463  //It is recommended to use OmpSupport::buildOmpAttribute() instead of
464  //using the constructors here
466  OmpAttribute()
467  {
468  mNode = NULL;
469  omp_type = e_unknown;
470  init();
471  isUserDefined = true;
472  }
474  OmpAttribute(omp_construct_enum omptype, SgNode* mynode):
475  mNode(mynode),omp_type(omptype){
476  /*The initialization order has to match the declaration order,
477  * otherwise get a compilation warning*/
478  init();
479  isUserDefined = true;
480  if (mNode != NULL )
481  {
482 #if 0 // [Robb Matzke 2021-03-28]: causes unused variable warning every time this header is included
483  SgLocatedNode * lnode = isSgLocatedNode (mNode);
484  ROSE_ASSERT (lnode != NULL);
485  //ROSE_ASSERT (lnode->get_file_info()->get_filename()!=std::string("transformation"));
486 #else // fixed version
487  ROSE_ASSERT(isSgLocatedNode(mNode));
488 #endif
489  }
490  // Liao 2/12/2010, we allow build empty attribute as a replacement of a default constructor.
491  // This is used by autoParallization to tentatively create an instance and later fill data fields.
492  // assert(isDirective(omptype));
493  }
494 
496  SgNode* mNode;
498  PreprocessingInfo* pinfo;
499 
501  bool isUserDefined;
502 
504  enum omp_construct_enum omp_type;
505 
507  // vector is used to preserve the order of clauses in the directive
508  // map is used to fast query if a clause exists or not
509  // Some clauses are allowed to appear more than once, merge the content into the first occurrence in our implementation.
510  std::vector<omp_construct_enum> clauses;
511  std::map<omp_construct_enum,bool> clause_map;
512 
513  // Multiple reduction clauses, each has a different operator
514  //value for reduction operation: + -, * & | etc
515  std::vector<omp_construct_enum> reduction_operators;
516 
518  std::vector<omp_construct_enum> dependence_types;
519 
520  // Liao, 1/15/2013, map variant:
521  // there could be multiple map clause with the same variant type: alloc, to, from , and tofrom.
522  std::vector<omp_construct_enum> map_variants;
523  //enum omp_construct_enum map_variant;
524 
525  //variable lists-------------------
526  //appeared within some directives and clauses
527  //The clauses/directive are: flush, threadprivate, private, firstprivate,
528  // shared, copyin, reduction, lastprivate, copyprivate
529  // We use a pair of (name, SgNode) for each variable
530  // It is highly possible that a variable having more than one OpenMP properties.
531  // For example, a variable can be both firstprivate and lastprivate.
532  std::map<omp_construct_enum, std::vector<std::pair<std::string,SgNode* > > > variable_lists;
533  // A reverse map from a variable to the clauses the variable appears
534  std::map<std::string, std::vector<omp_construct_enum> > var_clauses;
535 
536 
537  // expressions ----------------------
538  // e.g.: if (exp), num_threads(exp), schedule(,exp), collapse(exp)
539  std::map<omp_construct_enum, std::pair<std::string, SgExpression*> > expressions;
540 
541  // values for some clauses -------------------------
542  // values for default() clause: data scoping information
543  // choices are: none,shared, private, firstprivate
544  omp_construct_enum default_scope;
545 
546  // values for proc_bind() clause
547  omp_construct_enum proc_bind_policy;
548 
549  // Atomic clause's atomicity
550  omp_construct_enum atomicity;
551 
552  // value for omp for's schedule policies
553  omp_construct_enum schedule_kind;
554 
555  // Only used for omp critical to indicate if it is named or not
556  // name for the directive, only used for omp critical
557  bool hasName;
558  std::string name;
559 
560  // Misc fields --------------------------------
561  // help translation and analysis
562  bool isOrphaned; //true if parent omp parallel is not in the static lexical scope
563 
564  // Additional information to help translation
565  int wrapperCount; // the shared variables from the same scope which needs wrapper
566 
567  //optional information
568  OmpAttribute * parent; //upper-level OMP pragma's attribute
569 
572  void init() ;
573 
575  // invoke OmpSupport::toString() to stringify the enumerate type internally
576  // some variables have the optional dist_data policy
577  std::string toOpenMPString(omp_construct_enum omp_type);
578 
580  std::string toOpenMPString(std::vector<std::pair<std::string,SgNode* > > varList, bool checkDistPolicy = false);
581 
583  std::string toOpenMPString (std::vector < std::pair <omp_construct_enum, SgExpression*> > dim_policies);
584  }; // end class OmpAttribute
585 
586 
587  // save encountered Fortran OpenMP directives here.
588  // We reuse the list later on to build OpenMP AST for Fortran
589  extern std::list<OmpAttribute* > omp_comment_list;
590 
591 
592 } //end namespace OmpSupport
593 
594 #endif //Omp_Attribute_h_INCLUDED
595 
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:332
OwnershipPolicy
Who owns this attribute.
virtual OwnershipPolicy getOwnershipPolicy() const override
Who owns this attribute.
Definition: OmpAttribute.h:311
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.
Base class for all IR node attribute values.
One attribute object stores all information within an OpenMP pragma (directive and clauses) ...
Definition: OmpAttribute.h:320
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:9846
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:328
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:362
void setOmpDirectiveType(omp_construct_enum omptype)
---------—directive type----—
Definition: OmpAttribute.h:335
ROSE_DLL_API std::string generateDiffTextFromOmpAttribute(SgNode *sg_node)
Generate diff text from OmpAttribute attached to a statement.