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