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