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