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 CodeGenIntrinsicTable::CodeGenIntrinsicTable(const RecordKeeper &RC) { 29 std::vector<Record *> IntrProperties = 30 RC.getAllDerivedDefinitions("IntrinsicProperty"); 31 32 std::vector<Record *> DefaultProperties; 33 for (Record *Rec : IntrProperties) 34 if (Rec->getValueAsBit("IsDefault")) 35 DefaultProperties.push_back(Rec); 36 37 std::vector<Record *> Defs = RC.getAllDerivedDefinitions("Intrinsic"); 38 Intrinsics.reserve(Defs.size()); 39 40 for (unsigned I = 0, e = Defs.size(); I != e; ++I) 41 Intrinsics.push_back(CodeGenIntrinsic(Defs[I], DefaultProperties)); 42 43 llvm::sort(Intrinsics, 44 [](const CodeGenIntrinsic &LHS, const CodeGenIntrinsic &RHS) { 45 return std::tie(LHS.TargetPrefix, LHS.Name) < 46 std::tie(RHS.TargetPrefix, RHS.Name); 47 }); 48 Targets.push_back({"", 0, 0}); 49 for (size_t I = 0, E = Intrinsics.size(); I < E; ++I) 50 if (Intrinsics[I].TargetPrefix != Targets.back().Name) { 51 Targets.back().Count = I - Targets.back().Offset; 52 Targets.push_back({Intrinsics[I].TargetPrefix, I, 0}); 53 } 54 Targets.back().Count = Intrinsics.size() - Targets.back().Offset; 55 } 56 57 CodeGenIntrinsic::CodeGenIntrinsic(Record *R, 58 ArrayRef<Record *> DefaultProperties) { 59 TheDef = R; 60 std::string DefName = std::string(R->getName()); 61 ArrayRef<SMLoc> DefLoc = R->getLoc(); 62 Properties = 0; 63 isOverloaded = false; 64 isCommutative = false; 65 canThrow = false; 66 isNoReturn = false; 67 isNoCallback = false; 68 isNoSync = false; 69 isNoFree = false; 70 isWillReturn = false; 71 isCold = false; 72 isNoDuplicate = false; 73 isNoMerge = false; 74 isConvergent = false; 75 isSpeculatable = false; 76 hasSideEffects = false; 77 isStrictFP = false; 78 79 if (DefName.size() <= 4 || DefName.substr(0, 4) != "int_") 80 PrintFatalError(DefLoc, 81 "Intrinsic '" + DefName + "' does not start with 'int_'!"); 82 83 EnumName = DefName.substr(4); 84 85 if (R->getValue( 86 "ClangBuiltinName")) // Ignore a missing ClangBuiltinName field. 87 ClangBuiltinName = std::string(R->getValueAsString("ClangBuiltinName")); 88 if (R->getValue("MSBuiltinName")) // Ignore a missing MSBuiltinName field. 89 MSBuiltinName = std::string(R->getValueAsString("MSBuiltinName")); 90 91 TargetPrefix = std::string(R->getValueAsString("TargetPrefix")); 92 Name = std::string(R->getValueAsString("LLVMName")); 93 94 if (Name == "") { 95 // If an explicit name isn't specified, derive one from the DefName. 96 Name = "llvm."; 97 98 for (unsigned i = 0, e = EnumName.size(); i != e; ++i) 99 Name += (EnumName[i] == '_') ? '.' : EnumName[i]; 100 } else { 101 // Verify it starts with "llvm.". 102 if (Name.size() <= 5 || Name.substr(0, 5) != "llvm.") 103 PrintFatalError(DefLoc, "Intrinsic '" + DefName + 104 "'s name does not start with 'llvm.'!"); 105 } 106 107 // If TargetPrefix is specified, make sure that Name starts with 108 // "llvm.<targetprefix>.". 109 if (!TargetPrefix.empty()) { 110 if (Name.size() < 6 + TargetPrefix.size() || 111 Name.substr(5, 1 + TargetPrefix.size()) != (TargetPrefix + ".")) 112 PrintFatalError(DefLoc, "Intrinsic '" + DefName + 113 "' does not start with 'llvm." + 114 TargetPrefix + ".'!"); 115 } 116 117 if (auto *Types = R->getValue("Types")) { 118 auto *TypeList = cast<ListInit>(Types->getValue()); 119 isOverloaded = R->getValueAsBit("isOverloaded"); 120 121 unsigned I = 0; 122 for (unsigned E = R->getValueAsListInit("RetTypes")->size(); I < E; ++I) 123 IS.RetTys.push_back(TypeList->getElementAsRecord(I)); 124 125 for (unsigned E = TypeList->size(); I < E; ++I) 126 IS.ParamTys.push_back(TypeList->getElementAsRecord(I)); 127 } 128 129 // Parse the intrinsic properties. 130 ListInit *PropList = R->getValueAsListInit("IntrProperties"); 131 for (unsigned i = 0, e = PropList->size(); i != e; ++i) { 132 Record *Property = PropList->getElementAsRecord(i); 133 assert(Property->isSubClassOf("IntrinsicProperty") && 134 "Expected a property!"); 135 136 setProperty(Property); 137 } 138 139 // Set default properties to true. 140 setDefaultProperties(R, DefaultProperties); 141 142 // Also record the SDPatternOperator Properties. 143 Properties = parseSDPatternOperatorProperties(R); 144 145 // Sort the argument attributes for later benefit. 146 for (auto &Attrs : ArgumentAttributes) 147 llvm::sort(Attrs); 148 } 149 150 void CodeGenIntrinsic::setDefaultProperties( 151 Record *R, ArrayRef<Record *> DefaultProperties) { 152 // opt-out of using default attributes. 153 if (R->getValueAsBit("DisableDefaultAttributes")) 154 return; 155 156 for (Record *Rec : DefaultProperties) 157 setProperty(Rec); 158 } 159 160 void CodeGenIntrinsic::setProperty(Record *R) { 161 if (R->getName() == "IntrNoMem") 162 ME = MemoryEffects::none(); 163 else if (R->getName() == "IntrReadMem") { 164 if (ME.onlyWritesMemory()) 165 PrintFatalError(TheDef->getLoc(), 166 Twine("IntrReadMem cannot be used after IntrNoMem or " 167 "IntrWriteMem. Default is ReadWrite")); 168 ME &= MemoryEffects::readOnly(); 169 } else if (R->getName() == "IntrWriteMem") { 170 if (ME.onlyReadsMemory()) 171 PrintFatalError(TheDef->getLoc(), 172 Twine("IntrWriteMem cannot be used after IntrNoMem or " 173 "IntrReadMem. Default is ReadWrite")); 174 ME &= MemoryEffects::writeOnly(); 175 } else if (R->getName() == "IntrArgMemOnly") 176 ME &= MemoryEffects::argMemOnly(); 177 else if (R->getName() == "IntrInaccessibleMemOnly") 178 ME &= MemoryEffects::inaccessibleMemOnly(); 179 else if (R->getName() == "IntrInaccessibleMemOrArgMemOnly") 180 ME &= MemoryEffects::inaccessibleOrArgMemOnly(); 181 else if (R->getName() == "Commutative") 182 isCommutative = true; 183 else if (R->getName() == "Throws") 184 canThrow = true; 185 else if (R->getName() == "IntrNoDuplicate") 186 isNoDuplicate = true; 187 else if (R->getName() == "IntrNoMerge") 188 isNoMerge = true; 189 else if (R->getName() == "IntrConvergent") 190 isConvergent = true; 191 else if (R->getName() == "IntrNoReturn") 192 isNoReturn = true; 193 else if (R->getName() == "IntrNoCallback") 194 isNoCallback = true; 195 else if (R->getName() == "IntrNoSync") 196 isNoSync = true; 197 else if (R->getName() == "IntrNoFree") 198 isNoFree = true; 199 else if (R->getName() == "IntrWillReturn") 200 isWillReturn = !isNoReturn; 201 else if (R->getName() == "IntrCold") 202 isCold = true; 203 else if (R->getName() == "IntrSpeculatable") 204 isSpeculatable = true; 205 else if (R->getName() == "IntrHasSideEffects") 206 hasSideEffects = true; 207 else if (R->getName() == "IntrStrictFP") 208 isStrictFP = true; 209 else if (R->isSubClassOf("NoCapture")) { 210 unsigned ArgNo = R->getValueAsInt("ArgNo"); 211 addArgAttribute(ArgNo, NoCapture); 212 } else if (R->isSubClassOf("NoAlias")) { 213 unsigned ArgNo = R->getValueAsInt("ArgNo"); 214 addArgAttribute(ArgNo, NoAlias); 215 } else if (R->isSubClassOf("NoUndef")) { 216 unsigned ArgNo = R->getValueAsInt("ArgNo"); 217 addArgAttribute(ArgNo, NoUndef); 218 } else if (R->isSubClassOf("NonNull")) { 219 unsigned ArgNo = R->getValueAsInt("ArgNo"); 220 addArgAttribute(ArgNo, NonNull); 221 } else if (R->isSubClassOf("Returned")) { 222 unsigned ArgNo = R->getValueAsInt("ArgNo"); 223 addArgAttribute(ArgNo, Returned); 224 } else if (R->isSubClassOf("ReadOnly")) { 225 unsigned ArgNo = R->getValueAsInt("ArgNo"); 226 addArgAttribute(ArgNo, ReadOnly); 227 } else if (R->isSubClassOf("WriteOnly")) { 228 unsigned ArgNo = R->getValueAsInt("ArgNo"); 229 addArgAttribute(ArgNo, WriteOnly); 230 } else if (R->isSubClassOf("ReadNone")) { 231 unsigned ArgNo = R->getValueAsInt("ArgNo"); 232 addArgAttribute(ArgNo, ReadNone); 233 } else if (R->isSubClassOf("ImmArg")) { 234 unsigned ArgNo = R->getValueAsInt("ArgNo"); 235 addArgAttribute(ArgNo, ImmArg); 236 } else if (R->isSubClassOf("Align")) { 237 unsigned ArgNo = R->getValueAsInt("ArgNo"); 238 uint64_t Align = R->getValueAsInt("Align"); 239 addArgAttribute(ArgNo, Alignment, Align); 240 } else if (R->isSubClassOf("Dereferenceable")) { 241 unsigned ArgNo = R->getValueAsInt("ArgNo"); 242 uint64_t Bytes = R->getValueAsInt("Bytes"); 243 addArgAttribute(ArgNo, Dereferenceable, Bytes); 244 } else 245 llvm_unreachable("Unknown property!"); 246 } 247 248 bool CodeGenIntrinsic::isParamAPointer(unsigned ParamIdx) const { 249 if (ParamIdx >= IS.ParamTys.size()) 250 return false; 251 return (IS.ParamTys[ParamIdx]->isSubClassOf("LLVMQualPointerType") || 252 IS.ParamTys[ParamIdx]->isSubClassOf("LLVMAnyPointerType")); 253 } 254 255 bool CodeGenIntrinsic::isParamImmArg(unsigned ParamIdx) const { 256 // Convert argument index to attribute index starting from `FirstArgIndex`. 257 ++ParamIdx; 258 if (ParamIdx >= ArgumentAttributes.size()) 259 return false; 260 ArgAttribute Val{ImmArg, 0}; 261 return std::binary_search(ArgumentAttributes[ParamIdx].begin(), 262 ArgumentAttributes[ParamIdx].end(), Val); 263 } 264 265 void CodeGenIntrinsic::addArgAttribute(unsigned Idx, ArgAttrKind AK, 266 uint64_t V) { 267 if (Idx >= ArgumentAttributes.size()) 268 ArgumentAttributes.resize(Idx + 1); 269 ArgumentAttributes[Idx].emplace_back(AK, V); 270 } 271