1//===--- AttrImpl.cpp - Classes for representing attributes -----*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9//  This file contains out-of-line methods for Attr classes.
10//
11//===----------------------------------------------------------------------===//
12
13#include "clang/AST/ASTContext.h"
14#include "clang/AST/Attr.h"
15#include "clang/AST/Expr.h"
16#include "clang/AST/Type.h"
17using namespace clang;
18
19void LoopHintAttr::printPrettyPragma(raw_ostream &OS,
20                                     const PrintingPolicy &Policy) const {
21  unsigned SpellingIndex = getAttributeSpellingListIndex();
22  // For "#pragma unroll" and "#pragma nounroll" the string "unroll" or
23  // "nounroll" is already emitted as the pragma name.
24  if (SpellingIndex == Pragma_nounroll ||
25      SpellingIndex == Pragma_nounroll_and_jam)
26    return;
27  else if (SpellingIndex == Pragma_unroll ||
28           SpellingIndex == Pragma_unroll_and_jam) {
29    OS << ' ' << getValueString(Policy);
30    return;
31  }
32
33  assert(SpellingIndex == Pragma_clang_loop && "Unexpected spelling");
34  OS << ' ' << getOptionName(option) << getValueString(Policy);
35}
36
37// Return a string containing the loop hint argument including the
38// enclosing parentheses.
39std::string LoopHintAttr::getValueString(const PrintingPolicy &Policy) const {
40  std::string ValueName;
41  llvm::raw_string_ostream OS(ValueName);
42  OS << "(";
43  if (state == Numeric)
44    value->printPretty(OS, nullptr, Policy);
45  else if (state == FixedWidth || state == ScalableWidth) {
46    if (value) {
47      value->printPretty(OS, nullptr, Policy);
48      if (state == ScalableWidth)
49        OS << ", scalable";
50    } else if (state == ScalableWidth)
51      OS << "scalable";
52    else
53      OS << "fixed";
54  } else if (state == Enable)
55    OS << "enable";
56  else if (state == Full)
57    OS << "full";
58  else if (state == AssumeSafety)
59    OS << "assume_safety";
60  else
61    OS << "disable";
62  OS << ")";
63  return OS.str();
64}
65
66// Return a string suitable for identifying this attribute in diagnostics.
67std::string
68LoopHintAttr::getDiagnosticName(const PrintingPolicy &Policy) const {
69  unsigned SpellingIndex = getAttributeSpellingListIndex();
70  if (SpellingIndex == Pragma_nounroll)
71    return "#pragma nounroll";
72  else if (SpellingIndex == Pragma_unroll)
73    return "#pragma unroll" +
74           (option == UnrollCount ? getValueString(Policy) : "");
75  else if (SpellingIndex == Pragma_nounroll_and_jam)
76    return "#pragma nounroll_and_jam";
77  else if (SpellingIndex == Pragma_unroll_and_jam)
78    return "#pragma unroll_and_jam" +
79           (option == UnrollAndJamCount ? getValueString(Policy) : "");
80
81  assert(SpellingIndex == Pragma_clang_loop && "Unexpected spelling");
82  return getOptionName(option) + getValueString(Policy);
83}
84
85void OMPDeclareSimdDeclAttr::printPrettyPragma(
86    raw_ostream &OS, const PrintingPolicy &Policy) const {
87  if (getBranchState() != BS_Undefined)
88    OS << ' ' << ConvertBranchStateTyToStr(getBranchState());
89  if (auto *E = getSimdlen()) {
90    OS << " simdlen(";
91    E->printPretty(OS, nullptr, Policy);
92    OS << ")";
93  }
94  if (uniforms_size() > 0) {
95    OS << " uniform";
96    StringRef Sep = "(";
97    for (auto *E : uniforms()) {
98      OS << Sep;
99      E->printPretty(OS, nullptr, Policy);
100      Sep = ", ";
101    }
102    OS << ")";
103  }
104  alignments_iterator NI = alignments_begin();
105  for (auto *E : aligneds()) {
106    OS << " aligned(";
107    E->printPretty(OS, nullptr, Policy);
108    if (*NI) {
109      OS << ": ";
110      (*NI)->printPretty(OS, nullptr, Policy);
111    }
112    OS << ")";
113    ++NI;
114  }
115  steps_iterator I = steps_begin();
116  modifiers_iterator MI = modifiers_begin();
117  for (auto *E : linears()) {
118    OS << " linear(";
119    if (*MI != OMPC_LINEAR_unknown)
120      OS << getOpenMPSimpleClauseTypeName(llvm::omp::Clause::OMPC_linear, *MI)
121         << "(";
122    E->printPretty(OS, nullptr, Policy);
123    if (*MI != OMPC_LINEAR_unknown)
124      OS << ")";
125    if (*I) {
126      OS << ": ";
127      (*I)->printPretty(OS, nullptr, Policy);
128    }
129    OS << ")";
130    ++I;
131    ++MI;
132  }
133}
134
135void OMPDeclareTargetDeclAttr::printPrettyPragma(
136    raw_ostream &OS, const PrintingPolicy &Policy) const {
137  // Use fake syntax because it is for testing and debugging purpose only.
138  if (getDevType() != DT_Any)
139    OS << " device_type(" << ConvertDevTypeTyToStr(getDevType()) << ")";
140  if (getMapType() != MT_To)
141    OS << ' ' << ConvertMapTypeTyToStr(getMapType());
142}
143
144llvm::Optional<OMPDeclareTargetDeclAttr *>
145OMPDeclareTargetDeclAttr::getActiveAttr(const ValueDecl *VD) {
146  if (!VD->hasAttrs())
147    return llvm::None;
148  unsigned Level = 0;
149  OMPDeclareTargetDeclAttr *FoundAttr = nullptr;
150  for (auto *Attr : VD->specific_attrs<OMPDeclareTargetDeclAttr>()) {
151    if (Level <= Attr->getLevel()) {
152      Level = Attr->getLevel();
153      FoundAttr = Attr;
154    }
155  }
156  if (FoundAttr)
157    return FoundAttr;
158  return llvm::None;
159}
160
161llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy>
162OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(const ValueDecl *VD) {
163  llvm::Optional<OMPDeclareTargetDeclAttr *> ActiveAttr = getActiveAttr(VD);
164  if (ActiveAttr.hasValue())
165    return ActiveAttr.getValue()->getMapType();
166  return llvm::None;
167}
168
169llvm::Optional<OMPDeclareTargetDeclAttr::DevTypeTy>
170OMPDeclareTargetDeclAttr::getDeviceType(const ValueDecl *VD) {
171  llvm::Optional<OMPDeclareTargetDeclAttr *> ActiveAttr = getActiveAttr(VD);
172  if (ActiveAttr.hasValue())
173    return ActiveAttr.getValue()->getDevType();
174  return llvm::None;
175}
176
177llvm::Optional<SourceLocation>
178OMPDeclareTargetDeclAttr::getLocation(const ValueDecl *VD) {
179  llvm::Optional<OMPDeclareTargetDeclAttr *> ActiveAttr = getActiveAttr(VD);
180  if (ActiveAttr.hasValue())
181    return ActiveAttr.getValue()->getRange().getBegin();
182  return llvm::None;
183}
184
185namespace clang {
186llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const OMPTraitInfo &TI);
187llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const OMPTraitInfo *TI);
188}
189
190void OMPDeclareVariantAttr::printPrettyPragma(
191    raw_ostream &OS, const PrintingPolicy &Policy) const {
192  if (const Expr *E = getVariantFuncRef()) {
193    OS << "(";
194    E->printPretty(OS, nullptr, Policy);
195    OS << ")";
196  }
197  OS << " match(" << traitInfos << ")";
198}
199
200#include "clang/AST/AttrImpl.inc"
201