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