1 //===- CodeGenIntrinsics.cpp - Intrinsic Class Wrapper --------------------===// 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 defines a wrapper class for the 'Intrinsic' TableGen class. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #include "CodeGenIntrinsics.h" 14 #include "llvm/ADT/ArrayRef.h" 15 #include "llvm/ADT/STLExtras.h" 16 #include "llvm/ADT/Twine.h" 17 #include "llvm/Support/ErrorHandling.h" 18 #include "llvm/TableGen/Error.h" 19 #include "llvm/TableGen/Record.h" 20 #include <algorithm> 21 #include <cassert> 22 using namespace llvm; 23 24 //===----------------------------------------------------------------------===// 25 // CodeGenIntrinsic Implementation 26 //===----------------------------------------------------------------------===// 27 28 CodeGenIntrinsicContext::CodeGenIntrinsicContext(const RecordKeeper &RC) { 29 for (const Record *Rec : RC.getAllDerivedDefinitions("IntrinsicProperty")) 30 if (Rec->getValueAsBit("IsDefault")) 31 DefaultProperties.push_back(Rec); 32 33 // The maximum number of values that an intrinsic can return is the size of 34 // of `IIT_RetNumbers` list - 1 (since we index into this list using the 35 // number of return values as the index). 36 const auto *IIT_RetNumbers = 37 dyn_cast_or_null<ListInit>(RC.getGlobal("IIT_RetNumbers")); 38 if (!IIT_RetNumbers) 39 PrintFatalError("unable to find 'IIT_RetNumbers' list"); 40 MaxNumReturn = IIT_RetNumbers->size() - 1; 41 } 42 43 CodeGenIntrinsicTable::CodeGenIntrinsicTable(const RecordKeeper &RC) { 44 CodeGenIntrinsicContext Ctx(RC); 45 46 ArrayRef<const Record *> Defs = RC.getAllDerivedDefinitions("Intrinsic"); 47 Intrinsics.reserve(Defs.size()); 48 49 for (const Record *Def : Defs) 50 Intrinsics.emplace_back(CodeGenIntrinsic(Def, Ctx)); 51 52 llvm::sort(Intrinsics, 53 [](const CodeGenIntrinsic &LHS, const CodeGenIntrinsic &RHS) { 54 // Order target independent intrinsics before target dependent 55 // ones. 56 bool LHSHasTarget = !LHS.TargetPrefix.empty(); 57 bool RHSHasTarget = !RHS.TargetPrefix.empty(); 58 59 // To ensure deterministic sorted order when duplicates are 60 // present, use record ID as a tie-breaker similar to 61 // sortAndReportDuplicates in Utils.cpp. 62 unsigned LhsID = LHS.TheDef->getID(); 63 unsigned RhsID = RHS.TheDef->getID(); 64 65 return std::tie(LHSHasTarget, LHS.Name, LhsID) < 66 std::tie(RHSHasTarget, RHS.Name, RhsID); 67 }); 68 69 Targets.push_back({"", 0, 0}); 70 for (size_t I = 0, E = Intrinsics.size(); I < E; ++I) 71 if (Intrinsics[I].TargetPrefix != Targets.back().Name) { 72 Targets.back().Count = I - Targets.back().Offset; 73 Targets.push_back({Intrinsics[I].TargetPrefix, I, 0}); 74 } 75 Targets.back().Count = Intrinsics.size() - Targets.back().Offset; 76 77 CheckDuplicateIntrinsics(); 78 CheckTargetIndependentIntrinsics(); 79 } 80 81 // Check for duplicate intrinsic names. 82 void CodeGenIntrinsicTable::CheckDuplicateIntrinsics() const { 83 // Since the Intrinsics vector is already sorted by name, if there are 2 or 84 // more intrinsics with duplicate names, they will appear adjacent in sorted 85 // order. Note that if the intrinsic name was derived from the record name 86 // there cannot be be duplicate as TableGen parser would have flagged that. 87 // However, if the name was specified in the intrinsic definition, then its 88 // possible to have duplicate names. 89 auto I = std::adjacent_find( 90 Intrinsics.begin(), Intrinsics.end(), 91 [](const CodeGenIntrinsic &Int1, const CodeGenIntrinsic &Int2) { 92 return Int1.Name == Int2.Name; 93 }); 94 if (I == Intrinsics.end()) 95 return; 96 97 // Found a duplicate intrinsics. 98 const CodeGenIntrinsic &First = *I; 99 const CodeGenIntrinsic &Second = *(I + 1); 100 PrintError(Second.TheDef, 101 Twine("Intrinsic `") + First.Name + "` is already defined"); 102 PrintFatalNote(First.TheDef, "Previous definition here"); 103 } 104 105 // For target independent intrinsics, check that their second dotted component 106 // does not match any target name. 107 void CodeGenIntrinsicTable::CheckTargetIndependentIntrinsics() const { 108 SmallDenseSet<StringRef> TargetNames; 109 for (const auto &Target : ArrayRef(Targets).drop_front()) 110 TargetNames.insert(Target.Name); 111 112 // Set of target independent intrinsics. 113 const auto &Set = Targets[0]; 114 for (const auto &Int : ArrayRef(&Intrinsics[Set.Offset], Set.Count)) { 115 StringRef Name = Int.Name; 116 StringRef Prefix = Name.drop_front(5).split('.').first; 117 if (!TargetNames.contains(Prefix)) 118 continue; 119 PrintFatalError(Int.TheDef, 120 "target independent intrinsic `" + Name + 121 "' has prefix `llvm." + Prefix + 122 "` that conflicts with intrinsics for target `" + 123 Prefix + "`"); 124 } 125 } 126 127 CodeGenIntrinsic &CodeGenIntrinsicMap::operator[](const Record *Record) { 128 if (!Record->isSubClassOf("Intrinsic")) 129 PrintFatalError("Intrinsic defs should be subclass of 'Intrinsic' class"); 130 131 auto [Iter, Inserted] = Map.try_emplace(Record); 132 if (Inserted) 133 Iter->second = std::make_unique<CodeGenIntrinsic>(Record, Ctx); 134 return *Iter->second; 135 } 136 137 CodeGenIntrinsic::CodeGenIntrinsic(const Record *R, 138 const CodeGenIntrinsicContext &Ctx) 139 : TheDef(R) { 140 StringRef DefName = TheDef->getName(); 141 ArrayRef<SMLoc> DefLoc = R->getLoc(); 142 143 if (!DefName.starts_with("int_")) 144 PrintFatalError(DefLoc, 145 "Intrinsic '" + DefName + "' does not start with 'int_'!"); 146 147 EnumName = DefName.substr(4); 148 149 // Ignore a missing ClangBuiltinName field. 150 ClangBuiltinName = 151 R->getValueAsOptionalString("ClangBuiltinName").value_or(""); 152 // Ignore a missing MSBuiltinName field. 153 MSBuiltinName = R->getValueAsOptionalString("MSBuiltinName").value_or(""); 154 155 TargetPrefix = R->getValueAsString("TargetPrefix"); 156 Name = R->getValueAsString("LLVMName").str(); 157 158 if (Name == "") { 159 // If an explicit name isn't specified, derive one from the DefName. 160 Name = "llvm." + EnumName.str(); 161 llvm::replace(Name, '_', '.'); 162 } else { 163 // Verify it starts with "llvm.". 164 if (!StringRef(Name).starts_with("llvm.")) 165 PrintFatalError(DefLoc, "Intrinsic '" + DefName + 166 "'s name does not start with 'llvm.'!"); 167 } 168 169 // If TargetPrefix is specified, make sure that Name starts with 170 // "llvm.<targetprefix>.". 171 if (!TargetPrefix.empty()) { 172 StringRef Prefix = StringRef(Name).drop_front(5); // Drop llvm. 173 if (!Prefix.consume_front(TargetPrefix) || !Prefix.starts_with('.')) 174 PrintFatalError(DefLoc, "Intrinsic '" + DefName + 175 "' does not start with 'llvm." + 176 TargetPrefix + ".'!"); 177 } 178 179 unsigned NumRet = R->getValueAsListInit("RetTypes")->size(); 180 if (NumRet > Ctx.MaxNumReturn) 181 PrintFatalError(DefLoc, "intrinsics can only return upto " + 182 Twine(Ctx.MaxNumReturn) + " values, '" + 183 DefName + "' returns " + Twine(NumRet) + 184 " values"); 185 186 const Record *TypeInfo = R->getValueAsDef("TypeInfo"); 187 if (!TypeInfo->isSubClassOf("TypeInfoGen")) 188 PrintFatalError(DefLoc, "TypeInfo field in " + DefName + 189 " should be of subclass of TypeInfoGen!"); 190 191 isOverloaded = TypeInfo->getValueAsBit("isOverloaded"); 192 const ListInit *TypeList = TypeInfo->getValueAsListInit("Types"); 193 194 // Types field is a concatenation of Return types followed by Param types. 195 unsigned Idx = 0; 196 for (; Idx < NumRet; ++Idx) 197 IS.RetTys.push_back(TypeList->getElementAsRecord(Idx)); 198 199 for (unsigned E = TypeList->size(); Idx < E; ++Idx) 200 IS.ParamTys.push_back(TypeList->getElementAsRecord(Idx)); 201 202 // Parse the intrinsic properties. 203 ListInit *PropList = R->getValueAsListInit("IntrProperties"); 204 for (unsigned i = 0, e = PropList->size(); i != e; ++i) { 205 const Record *Property = PropList->getElementAsRecord(i); 206 assert(Property->isSubClassOf("IntrinsicProperty") && 207 "Expected a property!"); 208 209 setProperty(Property); 210 } 211 212 // Set default properties to true. 213 setDefaultProperties(Ctx.DefaultProperties); 214 215 // Also record the SDPatternOperator Properties. 216 Properties = parseSDPatternOperatorProperties(R); 217 218 // Sort the argument attributes for later benefit. 219 for (auto &Attrs : ArgumentAttributes) 220 llvm::sort(Attrs); 221 } 222 223 void CodeGenIntrinsic::setDefaultProperties( 224 ArrayRef<const Record *> DefaultProperties) { 225 // opt-out of using default attributes. 226 if (TheDef->getValueAsBit("DisableDefaultAttributes")) 227 return; 228 229 for (const Record *Rec : DefaultProperties) 230 setProperty(Rec); 231 } 232 233 void CodeGenIntrinsic::setProperty(const Record *R) { 234 if (R->getName() == "IntrNoMem") 235 ME = MemoryEffects::none(); 236 else if (R->getName() == "IntrReadMem") { 237 if (ME.onlyWritesMemory()) 238 PrintFatalError(TheDef->getLoc(), 239 Twine("IntrReadMem cannot be used after IntrNoMem or " 240 "IntrWriteMem. Default is ReadWrite")); 241 ME &= MemoryEffects::readOnly(); 242 } else if (R->getName() == "IntrWriteMem") { 243 if (ME.onlyReadsMemory()) 244 PrintFatalError(TheDef->getLoc(), 245 Twine("IntrWriteMem cannot be used after IntrNoMem or " 246 "IntrReadMem. Default is ReadWrite")); 247 ME &= MemoryEffects::writeOnly(); 248 } else if (R->getName() == "IntrArgMemOnly") 249 ME &= MemoryEffects::argMemOnly(); 250 else if (R->getName() == "IntrInaccessibleMemOnly") 251 ME &= MemoryEffects::inaccessibleMemOnly(); 252 else if (R->getName() == "IntrInaccessibleMemOrArgMemOnly") 253 ME &= MemoryEffects::inaccessibleOrArgMemOnly(); 254 else if (R->getName() == "Commutative") 255 isCommutative = true; 256 else if (R->getName() == "Throws") 257 canThrow = true; 258 else if (R->getName() == "IntrNoDuplicate") 259 isNoDuplicate = true; 260 else if (R->getName() == "IntrNoMerge") 261 isNoMerge = true; 262 else if (R->getName() == "IntrConvergent") 263 isConvergent = true; 264 else if (R->getName() == "IntrNoReturn") 265 isNoReturn = true; 266 else if (R->getName() == "IntrNoCallback") 267 isNoCallback = true; 268 else if (R->getName() == "IntrNoSync") 269 isNoSync = true; 270 else if (R->getName() == "IntrNoFree") 271 isNoFree = true; 272 else if (R->getName() == "IntrWillReturn") 273 isWillReturn = !isNoReturn; 274 else if (R->getName() == "IntrCold") 275 isCold = true; 276 else if (R->getName() == "IntrSpeculatable") 277 isSpeculatable = true; 278 else if (R->getName() == "IntrHasSideEffects") 279 hasSideEffects = true; 280 else if (R->getName() == "IntrStrictFP") 281 isStrictFP = true; 282 else if (R->isSubClassOf("NoCapture")) { 283 unsigned ArgNo = R->getValueAsInt("ArgNo"); 284 addArgAttribute(ArgNo, NoCapture); 285 } else if (R->isSubClassOf("NoAlias")) { 286 unsigned ArgNo = R->getValueAsInt("ArgNo"); 287 addArgAttribute(ArgNo, NoAlias); 288 } else if (R->isSubClassOf("NoUndef")) { 289 unsigned ArgNo = R->getValueAsInt("ArgNo"); 290 addArgAttribute(ArgNo, NoUndef); 291 } else if (R->isSubClassOf("NonNull")) { 292 unsigned ArgNo = R->getValueAsInt("ArgNo"); 293 addArgAttribute(ArgNo, NonNull); 294 } else if (R->isSubClassOf("Returned")) { 295 unsigned ArgNo = R->getValueAsInt("ArgNo"); 296 addArgAttribute(ArgNo, Returned); 297 } else if (R->isSubClassOf("ReadOnly")) { 298 unsigned ArgNo = R->getValueAsInt("ArgNo"); 299 addArgAttribute(ArgNo, ReadOnly); 300 } else if (R->isSubClassOf("WriteOnly")) { 301 unsigned ArgNo = R->getValueAsInt("ArgNo"); 302 addArgAttribute(ArgNo, WriteOnly); 303 } else if (R->isSubClassOf("ReadNone")) { 304 unsigned ArgNo = R->getValueAsInt("ArgNo"); 305 addArgAttribute(ArgNo, ReadNone); 306 } else if (R->isSubClassOf("ImmArg")) { 307 unsigned ArgNo = R->getValueAsInt("ArgNo"); 308 addArgAttribute(ArgNo, ImmArg); 309 } else if (R->isSubClassOf("Align")) { 310 unsigned ArgNo = R->getValueAsInt("ArgNo"); 311 uint64_t Align = R->getValueAsInt("Align"); 312 addArgAttribute(ArgNo, Alignment, Align); 313 } else if (R->isSubClassOf("Dereferenceable")) { 314 unsigned ArgNo = R->getValueAsInt("ArgNo"); 315 uint64_t Bytes = R->getValueAsInt("Bytes"); 316 addArgAttribute(ArgNo, Dereferenceable, Bytes); 317 } else 318 llvm_unreachable("Unknown property!"); 319 } 320 321 bool CodeGenIntrinsic::isParamAPointer(unsigned ParamIdx) const { 322 if (ParamIdx >= IS.ParamTys.size()) 323 return false; 324 return (IS.ParamTys[ParamIdx]->isSubClassOf("LLVMQualPointerType") || 325 IS.ParamTys[ParamIdx]->isSubClassOf("LLVMAnyPointerType")); 326 } 327 328 bool CodeGenIntrinsic::isParamImmArg(unsigned ParamIdx) const { 329 // Convert argument index to attribute index starting from `FirstArgIndex`. 330 ++ParamIdx; 331 if (ParamIdx >= ArgumentAttributes.size()) 332 return false; 333 ArgAttribute Val{ImmArg, 0}; 334 return std::binary_search(ArgumentAttributes[ParamIdx].begin(), 335 ArgumentAttributes[ParamIdx].end(), Val); 336 } 337 338 void CodeGenIntrinsic::addArgAttribute(unsigned Idx, ArgAttrKind AK, 339 uint64_t V) { 340 if (Idx >= ArgumentAttributes.size()) 341 ArgumentAttributes.resize(Idx + 1); 342 ArgumentAttributes[Idx].emplace_back(AK, V); 343 } 344