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