ROSE  0.9.9.139
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  };
311 
313  class ROSE_DLL_API OmpAttribute
314  {
315  public:
318  SgPragmaDeclaration* getPragmaDeclaration();
319 
322  void setPreprocessingInfo(PreprocessingInfo* info) { pinfo=info;};
323 
325  SgNode* getNode(){return mNode;};
326  void setNode(SgNode* n) { mNode= n;};
328  void setOmpDirectiveType(omp_construct_enum omptype){ assert (isDirective(omptype)); omp_type = omptype;}
329  omp_construct_enum getOmpDirectiveType() {return omp_type;}
330 
333  void addClause(omp_construct_enum clause_type);
335  bool hasClause(omp_construct_enum clause_type);
336 
338  std::vector<omp_construct_enum> getClauses();
339 
342  SgVariableSymbol* addVariable(omp_construct_enum targetConstruct, const std::string& varString, SgInitializedName* sgvar=NULL);
343 
345  SgVariableSymbol* addVariable(omp_construct_enum targetConstruct, SgExpression* varExp);
346 
348  bool hasVariableList(omp_construct_enum);
350  std::vector<std::pair<std::string,SgNode* > >
351  getVariableList(omp_construct_enum);
352 
354  // We store a list (vector) of dimension bounds for each array variable
355  std::map<SgSymbol*, std::vector < std::pair <SgExpression*, SgExpression*> > > array_dimensions;
356 
357  // dist_data (dim1_policy, dim2_policy, dim3_policy) for mapped arrays
358  // we use std::map <variable, policy_vector> to represent this.
359  // the policy vector contains up to three pair of (policy, optional size)
360  // e.g. map(x[0:n][0:m] dist_data(duplicate, block(2)))
361  // -----------------------------------
362  std::map <SgSymbol* , std::vector < std::pair<omp_construct_enum, SgExpression*> > > dist_data_policies;
363 
365  std::vector<enum omp_construct_enum> get_clauses(const std::string& variable);
366 
368  bool appendDistDataPolicy(SgVariableSymbol* array_symbol, omp_construct_enum dist_data_policy, SgExpression* size_exp = NULL);
369 
371  std::vector < std::pair < omp_construct_enum, SgExpression*> > getDistDataPolicy (SgVariableSymbol* array_symbol);
372 
375  void addExpression(omp_construct_enum targetConstruct, const std::string& expString, SgExpression* sgexp=NULL);
376 
378  std::pair<std::string, SgExpression*>
379  getExpression(omp_construct_enum targetConstruct);
380 
382  //
383  // Reduction needs special handling
384  // since multiple ones with different operator types can co-exist within one pragma
385  // We categories reduction clauses by their operator type and store variable lists for each of the reduction operator type, not with the reduction clause
386 
387  // Add a new reduction clause with the specified operator
388  void setReductionOperator(omp_construct_enum operatorx);
389 
391  std::vector<omp_construct_enum> getReductionOperators();
392 
394  bool hasReductionOperator(omp_construct_enum operatorx);
395 
396  //------------------------------------------
397  // Add a new clause with the specified operator
398  void setDependenceType(omp_construct_enum operatorx);
399 
401  std::vector<omp_construct_enum> getDependenceTypes();
402 
404  bool hasDependenceType(omp_construct_enum operatorx);
405 
406 
407  // map clause is similar to reduction clause,
408  //
409  // Add a new map clauses with the specified variant type
410  void setMapVariant(omp_construct_enum operatorx);
412  std::vector<omp_construct_enum> getMapVariants();
414  bool hasMapVariant(omp_construct_enum operatorx);
415 
417  bool isMapVariant(omp_construct_enum omp_type);
418 
419  // default () value
420  void setDefaultValue(omp_construct_enum valuex);
421  omp_construct_enum getDefaultValue();
422 
423  // proc_bind() policy
424  void setProcBindPolicy(omp_construct_enum valuex);
425  omp_construct_enum getProcBindPolicy();
426 
427  //Atomicity of Atomic Clause
428  void setAtomicAtomicity(omp_construct_enum valuex);
429  omp_construct_enum getAtomicAtomicity();
430 
431  // Schedule kind
432  omp_construct_enum getScheduleKind();
433  void setScheduleKind(omp_construct_enum kindx);
434 
436  bool isInConstruct(const std::string & variable, enum omp_construct_enum);
437 
439  void setCriticalName(const std::string & name);
440  std::string getCriticalName() {return name;};
441  bool isNamedCritical(){return hasName;};
442 
444  void print();
445 
447  bool get_isUserDefined() {return isUserDefined; }
448 
450  //not named toString() to void ambiguous with OmpAttribute::toString()
451  std::string toOpenMPString();
452  friend OmpAttribute* buildOmpAttribute(omp_construct_enum directive_type, SgNode* node, bool userDefined);
453  //------------------hide the implementation details, could be changed anytime!!
454  //----------------------------------------------------------------------------
455  private:
456  //It is recommended to use OmpSupport::buildOmpAttribute() instead of
457  //using the constructors here
459  OmpAttribute()
460  {
461  mNode = NULL;
462  omp_type = e_unknown;
463  init();
464  isUserDefined = true;
465  }
467  OmpAttribute(omp_construct_enum omptype, SgNode* mynode):
468  mNode(mynode),omp_type(omptype){
469  /*The initialization order has to match the declaration order,
470  * otherwise get a compilation warning*/
471  init();
472  isUserDefined = true;
473  if (mNode != NULL )
474  {
475  SgLocatedNode * lnode = isSgLocatedNode (mNode);
476  ROSE_ASSERT (lnode != NULL);
477  //ROSE_ASSERT (lnode->get_file_info()->get_filename()!=std::string("transformation"));
478  }
479  // Liao 2/12/2010, we allow build empty attribute as a replacement of a default constructor.
480  // This is used by autoParallization to tentatively create an instance and later fill data fields.
481  // assert(isDirective(omptype));
482  }
483 
485  SgNode* mNode;
487  PreprocessingInfo* pinfo;
488 
490  bool isUserDefined;
491 
493  enum omp_construct_enum omp_type;
494 
496  // vector is used to preserve the order of clauses in the directive
497  // map is used to fast query if a clause exists or not
498  // Some clauses are allowed to appear more than once, merge the content into the first occurrence in our implementation.
499  std::vector<omp_construct_enum> clauses;
500  std::map<omp_construct_enum,bool> clause_map;
501 
502  // Multiple reduction clauses, each has a different operator
503  //value for reduction operation: + -, * & | etc
504  std::vector<omp_construct_enum> reduction_operators;
505 
507  std::vector<omp_construct_enum> dependence_types;
508 
509  // Liao, 1/15/2013, map variant:
510  // there could be multiple map clause with the same variant type: alloc, to, from , and tofrom.
511  std::vector<omp_construct_enum> map_variants;
512  //enum omp_construct_enum map_variant;
513 
514  //variable lists-------------------
515  //appeared within some directives and clauses
516  //The clauses/directive are: flush, threadprivate, private, firstprivate,
517  // shared, copyin, reduction, lastprivate, copyprivate
518  // We use a pair of (name, SgNode) for each variable
519  // It is highly possible that a variable having more than one OpenMP properties.
520  // For example, a variable can be both firstprivate and lastprivate.
521  std::map<omp_construct_enum, std::vector<std::pair<std::string,SgNode* > > > variable_lists;
522  // A reverse map from a variable to the clauses the variable appears
523  std::map<std::string, std::vector<omp_construct_enum> > var_clauses;
524 
525 
526  // expressions ----------------------
527  // e.g.: if (exp), num_threads(exp), schedule(,exp), collapse(exp)
528  std::map<omp_construct_enum, std::pair<std::string, SgExpression*> > expressions;
529 
530  // values for some clauses -------------------------
531  // values for default() clause: data scoping information
532  // choices are: none,shared, private, firstprivate
533  omp_construct_enum default_scope;
534 
535  // values for proc_bind() clause
536  omp_construct_enum proc_bind_policy;
537 
538  // Atomic clause's atomicity
539  omp_construct_enum atomicity;
540 
541  // value for omp for's schedule policies
542  omp_construct_enum schedule_kind;
543 
544  // Only used for omp critical to indicate if it is named or not
545  // name for the directive, only used for omp critical
546  bool hasName;
547  std::string name;
548 
549  // Misc fields --------------------------------
550  // help translation and analysis
551  bool isOrphaned; //true if parent omp parallel is not in the static lexical scope
552 
553  // Additional information to help translation
554  int wrapperCount; // the shared variables from the same scope which needs wrapper
555 
556  //optional information
557  OmpAttribute * parent; //upper-level OMP pragma's attribute
558 
561  void init() ;
562 
564  // invoke OmpSupport::toString() to stringify the enumerate type internally
565  // some variables have the optional dist_data policy
566  std::string toOpenMPString(omp_construct_enum omp_type);
567 
569  std::string toOpenMPString(std::vector<std::pair<std::string,SgNode* > > varList, bool checkDistPolicy = false);
570 
572  std::string toOpenMPString (std::vector < std::pair <omp_construct_enum, SgExpression*> > dim_policies);
573  }; // end class OmpAttribute
574 
575 
576  // save encountered Fortran OpenMP directives here.
577  // We reuse the list later on to build OpenMP AST for Fortran
578  extern std::list<OmpAttribute* > omp_comment_list;
579 
580 
581 } //end namespace OmpSupport
582 
583 #endif //Omp_Attribute_h_INCLUDED
584 
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:325
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:313
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:8322
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:321
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:355
void setOmpDirectiveType(omp_construct_enum omptype)
---------—directive type----—
Definition: OmpAttribute.h:328
ROSE_DLL_API std::string generateDiffTextFromOmpAttribute(SgNode *sg_node)
Generate diff text from OmpAttribute attached to a statement.