1193323Sed//===- IntrinsicEmitter.cpp - Generate intrinsic information --------------===// 2193323Sed// 3193323Sed// The LLVM Compiler Infrastructure 4193323Sed// 5193323Sed// This file is distributed under the University of Illinois Open Source 6193323Sed// License. See LICENSE.TXT for details. 7193323Sed// 8193323Sed//===----------------------------------------------------------------------===// 9193323Sed// 10193323Sed// This tablegen backend emits information about intrinsic functions. 11193323Sed// 12193323Sed//===----------------------------------------------------------------------===// 13193323Sed 14245431Sdim#include "CodeGenIntrinsics.h" 15193323Sed#include "CodeGenTarget.h" 16245431Sdim#include "SequenceToOffsetTable.h" 17245431Sdim#include "llvm/ADT/StringExtras.h" 18245431Sdim#include "llvm/TableGen/Error.h" 19226890Sdim#include "llvm/TableGen/Record.h" 20245431Sdim#include "llvm/TableGen/StringMatcher.h" 21245431Sdim#include "llvm/TableGen/TableGenBackend.h" 22193323Sed#include <algorithm> 23193323Sedusing namespace llvm; 24193323Sed 25245431Sdimnamespace { 26245431Sdimclass IntrinsicEmitter { 27245431Sdim RecordKeeper &Records; 28245431Sdim bool TargetOnly; 29245431Sdim std::string TargetPrefix; 30245431Sdim 31245431Sdimpublic: 32245431Sdim IntrinsicEmitter(RecordKeeper &R, bool T) 33245431Sdim : Records(R), TargetOnly(T) {} 34245431Sdim 35245431Sdim void run(raw_ostream &OS); 36245431Sdim 37245431Sdim void EmitPrefix(raw_ostream &OS); 38245431Sdim 39245431Sdim void EmitEnumInfo(const std::vector<CodeGenIntrinsic> &Ints, 40245431Sdim raw_ostream &OS); 41245431Sdim 42245431Sdim void EmitFnNameRecognizer(const std::vector<CodeGenIntrinsic> &Ints, 43245431Sdim raw_ostream &OS); 44245431Sdim void EmitIntrinsicToNameTable(const std::vector<CodeGenIntrinsic> &Ints, 45245431Sdim raw_ostream &OS); 46245431Sdim void EmitIntrinsicToOverloadTable(const std::vector<CodeGenIntrinsic> &Ints, 47245431Sdim raw_ostream &OS); 48245431Sdim void EmitVerifier(const std::vector<CodeGenIntrinsic> &Ints, 49245431Sdim raw_ostream &OS); 50245431Sdim void EmitGenerator(const std::vector<CodeGenIntrinsic> &Ints, 51245431Sdim raw_ostream &OS); 52245431Sdim void EmitAttributes(const std::vector<CodeGenIntrinsic> &Ints, 53245431Sdim raw_ostream &OS); 54245431Sdim void EmitModRefBehavior(const std::vector<CodeGenIntrinsic> &Ints, 55245431Sdim raw_ostream &OS); 56245431Sdim void EmitIntrinsicToGCCBuiltinMap(const std::vector<CodeGenIntrinsic> &Ints, 57245431Sdim raw_ostream &OS); 58245431Sdim void EmitSuffix(raw_ostream &OS); 59245431Sdim}; 60245431Sdim} // End anonymous namespace 61245431Sdim 62193323Sed//===----------------------------------------------------------------------===// 63193323Sed// IntrinsicEmitter Implementation 64193323Sed//===----------------------------------------------------------------------===// 65193323Sed 66195340Sedvoid IntrinsicEmitter::run(raw_ostream &OS) { 67245431Sdim emitSourceFileHeader("Intrinsic Function Source Fragment", OS); 68245431Sdim 69193323Sed std::vector<CodeGenIntrinsic> Ints = LoadIntrinsics(Records, TargetOnly); 70245431Sdim 71193323Sed if (TargetOnly && !Ints.empty()) 72193323Sed TargetPrefix = Ints[0].TargetPrefix; 73193323Sed 74208599Srdivacky EmitPrefix(OS); 75208599Srdivacky 76193323Sed // Emit the enum information. 77193323Sed EmitEnumInfo(Ints, OS); 78193323Sed 79193323Sed // Emit the intrinsic ID -> name table. 80193323Sed EmitIntrinsicToNameTable(Ints, OS); 81193323Sed 82193323Sed // Emit the intrinsic ID -> overload table. 83193323Sed EmitIntrinsicToOverloadTable(Ints, OS); 84193323Sed 85193323Sed // Emit the function name recognizer. 86193323Sed EmitFnNameRecognizer(Ints, OS); 87263509Sdim 88193323Sed // Emit the intrinsic declaration generator. 89193323Sed EmitGenerator(Ints, OS); 90263509Sdim 91193323Sed // Emit the intrinsic parameter attributes. 92193323Sed EmitAttributes(Ints, OS); 93193323Sed 94193323Sed // Emit intrinsic alias analysis mod/ref behavior. 95193323Sed EmitModRefBehavior(Ints, OS); 96193323Sed 97193323Sed // Emit code to translate GCC builtins into LLVM intrinsics. 98193323Sed EmitIntrinsicToGCCBuiltinMap(Ints, OS); 99208599Srdivacky 100208599Srdivacky EmitSuffix(OS); 101193323Sed} 102193323Sed 103208599Srdivackyvoid IntrinsicEmitter::EmitPrefix(raw_ostream &OS) { 104208599Srdivacky OS << "// VisualStudio defines setjmp as _setjmp\n" 105218893Sdim "#if defined(_MSC_VER) && defined(setjmp) && \\\n" 106218893Sdim " !defined(setjmp_undefined_for_msvc)\n" 107218893Sdim "# pragma push_macro(\"setjmp\")\n" 108218893Sdim "# undef setjmp\n" 109218893Sdim "# define setjmp_undefined_for_msvc\n" 110208599Srdivacky "#endif\n\n"; 111208599Srdivacky} 112208599Srdivacky 113208599Srdivackyvoid IntrinsicEmitter::EmitSuffix(raw_ostream &OS) { 114218893Sdim OS << "#if defined(_MSC_VER) && defined(setjmp_undefined_for_msvc)\n" 115208599Srdivacky "// let's return it to _setjmp state\n" 116218893Sdim "# pragma pop_macro(\"setjmp\")\n" 117218893Sdim "# undef setjmp_undefined_for_msvc\n" 118208599Srdivacky "#endif\n\n"; 119208599Srdivacky} 120208599Srdivacky 121193323Sedvoid IntrinsicEmitter::EmitEnumInfo(const std::vector<CodeGenIntrinsic> &Ints, 122195340Sed raw_ostream &OS) { 123193323Sed OS << "// Enum values for Intrinsics.h\n"; 124193323Sed OS << "#ifdef GET_INTRINSIC_ENUM_VALUES\n"; 125193323Sed for (unsigned i = 0, e = Ints.size(); i != e; ++i) { 126193323Sed OS << " " << Ints[i].EnumName; 127193323Sed OS << ((i != e-1) ? ", " : " "); 128263509Sdim OS << std::string(40-Ints[i].EnumName.size(), ' ') 129193323Sed << "// " << Ints[i].Name << "\n"; 130193323Sed } 131193323Sed OS << "#endif\n\n"; 132193323Sed} 133193323Sed 134263509Sdimstruct IntrinsicNameSorter { 135263509Sdim IntrinsicNameSorter(const std::vector<CodeGenIntrinsic> &I) 136263509Sdim : Ints(I) {} 137263509Sdim 138263509Sdim // Sort in reverse order of intrinsic name so "abc.def" appears after 139263509Sdim // "abd.def.ghi" in the overridden name matcher 140263509Sdim bool operator()(unsigned i, unsigned j) { 141263509Sdim return Ints[i].Name > Ints[j].Name; 142263509Sdim } 143263509Sdim 144263509Sdimprivate: 145263509Sdim const std::vector<CodeGenIntrinsic> &Ints; 146263509Sdim}; 147263509Sdim 148193323Sedvoid IntrinsicEmitter:: 149263509SdimEmitFnNameRecognizer(const std::vector<CodeGenIntrinsic> &Ints, 150195340Sed raw_ostream &OS) { 151218893Sdim // Build a 'first character of function name' -> intrinsic # mapping. 152218893Sdim std::map<char, std::vector<unsigned> > IntMapping; 153193323Sed for (unsigned i = 0, e = Ints.size(); i != e; ++i) 154218893Sdim IntMapping[Ints[i].Name[5]].push_back(i); 155263509Sdim 156193323Sed OS << "// Function name -> enum value recognizer code.\n"; 157193323Sed OS << "#ifdef GET_FUNCTION_RECOGNIZER\n"; 158218893Sdim OS << " StringRef NameR(Name+6, Len-6); // Skip over 'llvm.'\n"; 159218893Sdim OS << " switch (Name[5]) { // Dispatch on first letter.\n"; 160218893Sdim OS << " default: break;\n"; 161263509Sdim IntrinsicNameSorter Sorter(Ints); 162218893Sdim // Emit the intrinsic matching stuff by first letter. 163218893Sdim for (std::map<char, std::vector<unsigned> >::iterator I = IntMapping.begin(), 164193323Sed E = IntMapping.end(); I != E; ++I) { 165218893Sdim OS << " case '" << I->first << "':\n"; 166218893Sdim std::vector<unsigned> &IntList = I->second; 167218893Sdim 168263509Sdim // Sort intrinsics in reverse order of their names 169263509Sdim std::sort(IntList.begin(), IntList.end(), Sorter); 170263509Sdim 171218893Sdim // Emit all the overloaded intrinsics first, build a table of the 172218893Sdim // non-overloaded ones. 173218893Sdim std::vector<StringMatcher::StringPair> MatchTable; 174263509Sdim 175218893Sdim for (unsigned i = 0, e = IntList.size(); i != e; ++i) { 176218893Sdim unsigned IntNo = IntList[i]; 177218893Sdim std::string Result = "return " + TargetPrefix + "Intrinsic::" + 178218893Sdim Ints[IntNo].EnumName + ";"; 179218893Sdim 180218893Sdim if (!Ints[IntNo].isOverloaded) { 181218893Sdim MatchTable.push_back(std::make_pair(Ints[IntNo].Name.substr(6),Result)); 182218893Sdim continue; 183218893Sdim } 184218893Sdim 185218893Sdim // For overloaded intrinsics, only the prefix needs to match 186218893Sdim std::string TheStr = Ints[IntNo].Name.substr(6); 187218893Sdim TheStr += '.'; // Require "bswap." instead of bswap. 188218893Sdim OS << " if (NameR.startswith(\"" << TheStr << "\")) " 189218893Sdim << Result << '\n'; 190193323Sed } 191263509Sdim 192218893Sdim // Emit the matcher logic for the fixed length strings. 193218893Sdim StringMatcher("NameR", MatchTable, OS).Emit(1); 194218893Sdim OS << " break; // end of '" << I->first << "' case.\n"; 195193323Sed } 196263509Sdim 197193323Sed OS << " }\n"; 198193323Sed OS << "#endif\n\n"; 199193323Sed} 200193323Sed 201193323Sedvoid IntrinsicEmitter:: 202263509SdimEmitIntrinsicToNameTable(const std::vector<CodeGenIntrinsic> &Ints, 203195340Sed raw_ostream &OS) { 204193323Sed OS << "// Intrinsic ID to name table\n"; 205193323Sed OS << "#ifdef GET_INTRINSIC_NAME_TABLE\n"; 206193323Sed OS << " // Note that entry #0 is the invalid intrinsic!\n"; 207193323Sed for (unsigned i = 0, e = Ints.size(); i != e; ++i) 208193323Sed OS << " \"" << Ints[i].Name << "\",\n"; 209193323Sed OS << "#endif\n\n"; 210193323Sed} 211193323Sed 212193323Sedvoid IntrinsicEmitter:: 213263509SdimEmitIntrinsicToOverloadTable(const std::vector<CodeGenIntrinsic> &Ints, 214195340Sed raw_ostream &OS) { 215235633Sdim OS << "// Intrinsic ID to overload bitset\n"; 216193323Sed OS << "#ifdef GET_INTRINSIC_OVERLOAD_TABLE\n"; 217235633Sdim OS << "static const uint8_t OTable[] = {\n"; 218235633Sdim OS << " 0"; 219193323Sed for (unsigned i = 0, e = Ints.size(); i != e; ++i) { 220235633Sdim // Add one to the index so we emit a null bit for the invalid #0 intrinsic. 221235633Sdim if ((i+1)%8 == 0) 222235633Sdim OS << ",\n 0"; 223193323Sed if (Ints[i].isOverloaded) 224235633Sdim OS << " | (1<<" << (i+1)%8 << ')'; 225193323Sed } 226235633Sdim OS << "\n};\n\n"; 227235633Sdim // OTable contains a true bit at the position if the intrinsic is overloaded. 228235633Sdim OS << "return (OTable[id/8] & (1 << (id%8))) != 0;\n"; 229193323Sed OS << "#endif\n\n"; 230193323Sed} 231193323Sed 232245431Sdim 233245431Sdim// NOTE: This must be kept in synch with the copy in lib/VMCore/Function.cpp! 234245431Sdimenum IIT_Info { 235245431Sdim // Common values should be encoded with 0-15. 236245431Sdim IIT_Done = 0, 237245431Sdim IIT_I1 = 1, 238245431Sdim IIT_I8 = 2, 239245431Sdim IIT_I16 = 3, 240245431Sdim IIT_I32 = 4, 241245431Sdim IIT_I64 = 5, 242252723Sdim IIT_F16 = 6, 243252723Sdim IIT_F32 = 7, 244252723Sdim IIT_F64 = 8, 245252723Sdim IIT_V2 = 9, 246252723Sdim IIT_V4 = 10, 247252723Sdim IIT_V8 = 11, 248252723Sdim IIT_V16 = 12, 249252723Sdim IIT_V32 = 13, 250245431Sdim IIT_PTR = 14, 251245431Sdim IIT_ARG = 15, 252252723Sdim 253245431Sdim // Values from 16+ are only encodable with the inefficient encoding. 254252723Sdim IIT_MMX = 16, 255252723Sdim IIT_METADATA = 17, 256252723Sdim IIT_EMPTYSTRUCT = 18, 257252723Sdim IIT_STRUCT2 = 19, 258252723Sdim IIT_STRUCT3 = 20, 259252723Sdim IIT_STRUCT4 = 21, 260252723Sdim IIT_STRUCT5 = 22, 261252723Sdim IIT_EXTEND_VEC_ARG = 23, 262252723Sdim IIT_TRUNC_VEC_ARG = 24, 263263509Sdim IIT_ANYPTR = 25, 264263509Sdim IIT_V1 = 26, 265263509Sdim IIT_VARARG = 27 266245431Sdim}; 267245431Sdim 268245431Sdim 269245431Sdimstatic void EncodeFixedValueType(MVT::SimpleValueType VT, 270245431Sdim std::vector<unsigned char> &Sig) { 271198090Srdivacky if (EVT(VT).isInteger()) { 272198090Srdivacky unsigned BitWidth = EVT(VT).getSizeInBits(); 273245431Sdim switch (BitWidth) { 274245431Sdim default: PrintFatalError("unhandled integer type width in intrinsic!"); 275245431Sdim case 1: return Sig.push_back(IIT_I1); 276245431Sdim case 8: return Sig.push_back(IIT_I8); 277245431Sdim case 16: return Sig.push_back(IIT_I16); 278245431Sdim case 32: return Sig.push_back(IIT_I32); 279245431Sdim case 64: return Sig.push_back(IIT_I64); 280245431Sdim } 281193323Sed } 282263509Sdim 283245431Sdim switch (VT) { 284245431Sdim default: PrintFatalError("unhandled MVT in intrinsic!"); 285252723Sdim case MVT::f16: return Sig.push_back(IIT_F16); 286245431Sdim case MVT::f32: return Sig.push_back(IIT_F32); 287245431Sdim case MVT::f64: return Sig.push_back(IIT_F64); 288245431Sdim case MVT::Metadata: return Sig.push_back(IIT_METADATA); 289245431Sdim case MVT::x86mmx: return Sig.push_back(IIT_MMX); 290245431Sdim // MVT::OtherVT is used to mean the empty struct type here. 291245431Sdim case MVT::Other: return Sig.push_back(IIT_EMPTYSTRUCT); 292263509Sdim // MVT::isVoid is used to represent varargs here. 293263509Sdim case MVT::isVoid: return Sig.push_back(IIT_VARARG); 294245431Sdim } 295193323Sed} 296193323Sed 297245431Sdim#ifdef _MSC_VER 298245431Sdim#pragma optimize("",off) // MSVC 2010 optimizer can't deal with this function. 299263509Sdim#endif 300193323Sed 301245431Sdimstatic void EncodeFixedType(Record *R, std::vector<unsigned char> &ArgCodes, 302245431Sdim std::vector<unsigned char> &Sig) { 303263509Sdim 304245431Sdim if (R->isSubClassOf("LLVMMatchType")) { 305245431Sdim unsigned Number = R->getValueAsInt("Number"); 306245431Sdim assert(Number < ArgCodes.size() && "Invalid matching number!"); 307245431Sdim if (R->isSubClassOf("LLVMExtendedElementVectorType")) 308245431Sdim Sig.push_back(IIT_EXTEND_VEC_ARG); 309245431Sdim else if (R->isSubClassOf("LLVMTruncatedElementVectorType")) 310245431Sdim Sig.push_back(IIT_TRUNC_VEC_ARG); 311245431Sdim else 312245431Sdim Sig.push_back(IIT_ARG); 313245431Sdim return Sig.push_back((Number << 2) | ArgCodes[Number]); 314245431Sdim } 315263509Sdim 316245431Sdim MVT::SimpleValueType VT = getValueType(R->getValueAsDef("VT")); 317193323Sed 318245431Sdim unsigned Tmp = 0; 319245431Sdim switch (VT) { 320245431Sdim default: break; 321245431Sdim case MVT::iPTRAny: ++Tmp; // FALL THROUGH. 322245431Sdim case MVT::vAny: ++Tmp; // FALL THROUGH. 323245431Sdim case MVT::fAny: ++Tmp; // FALL THROUGH. 324245431Sdim case MVT::iAny: { 325245431Sdim // If this is an "any" valuetype, then the type is the type of the next 326263509Sdim // type in the list specified to getIntrinsic(). 327245431Sdim Sig.push_back(IIT_ARG); 328263509Sdim 329245431Sdim // Figure out what arg # this is consuming, and remember what kind it was. 330245431Sdim unsigned ArgNo = ArgCodes.size(); 331245431Sdim ArgCodes.push_back(Tmp); 332263509Sdim 333245431Sdim // Encode what sort of argument it must be in the low 2 bits of the ArgNo. 334245431Sdim return Sig.push_back((ArgNo << 2) | Tmp); 335193323Sed } 336263509Sdim 337245431Sdim case MVT::iPTR: { 338245431Sdim unsigned AddrSpace = 0; 339245431Sdim if (R->isSubClassOf("LLVMQualPointerType")) { 340245431Sdim AddrSpace = R->getValueAsInt("AddrSpace"); 341245431Sdim assert(AddrSpace < 256 && "Address space exceeds 255"); 342245431Sdim } 343245431Sdim if (AddrSpace) { 344245431Sdim Sig.push_back(IIT_ANYPTR); 345245431Sdim Sig.push_back(AddrSpace); 346245431Sdim } else { 347245431Sdim Sig.push_back(IIT_PTR); 348245431Sdim } 349245431Sdim return EncodeFixedType(R->getValueAsDef("ElTy"), ArgCodes, Sig); 350245431Sdim } 351245431Sdim } 352263509Sdim 353245431Sdim if (EVT(VT).isVector()) { 354245431Sdim EVT VVT = VT; 355245431Sdim switch (VVT.getVectorNumElements()) { 356245431Sdim default: PrintFatalError("unhandled vector type width in intrinsic!"); 357263509Sdim case 1: Sig.push_back(IIT_V1); break; 358245431Sdim case 2: Sig.push_back(IIT_V2); break; 359245431Sdim case 4: Sig.push_back(IIT_V4); break; 360245431Sdim case 8: Sig.push_back(IIT_V8); break; 361245431Sdim case 16: Sig.push_back(IIT_V16); break; 362245431Sdim case 32: Sig.push_back(IIT_V32); break; 363245431Sdim } 364263509Sdim 365245431Sdim return EncodeFixedValueType(VVT.getVectorElementType(). 366245431Sdim getSimpleVT().SimpleTy, Sig); 367245431Sdim } 368193323Sed 369245431Sdim EncodeFixedValueType(VT, Sig); 370193323Sed} 371193323Sed 372245431Sdim#ifdef _MSC_VER 373245431Sdim#pragma optimize("",on) 374245431Sdim#endif 375193323Sed 376245431Sdim/// ComputeFixedEncoding - If we can encode the type signature for this 377245431Sdim/// intrinsic into 32 bits, return it. If not, return ~0U. 378245431Sdimstatic void ComputeFixedEncoding(const CodeGenIntrinsic &Int, 379245431Sdim std::vector<unsigned char> &TypeSig) { 380245431Sdim std::vector<unsigned char> ArgCodes; 381263509Sdim 382245431Sdim if (Int.IS.RetVTs.empty()) 383245431Sdim TypeSig.push_back(IIT_Done); 384245431Sdim else if (Int.IS.RetVTs.size() == 1 && 385245431Sdim Int.IS.RetVTs[0] == MVT::isVoid) 386245431Sdim TypeSig.push_back(IIT_Done); 387245431Sdim else { 388245431Sdim switch (Int.IS.RetVTs.size()) { 389245431Sdim case 1: break; 390245431Sdim case 2: TypeSig.push_back(IIT_STRUCT2); break; 391245431Sdim case 3: TypeSig.push_back(IIT_STRUCT3); break; 392245431Sdim case 4: TypeSig.push_back(IIT_STRUCT4); break; 393245431Sdim case 5: TypeSig.push_back(IIT_STRUCT5); break; 394245431Sdim default: assert(0 && "Unhandled case in struct"); 395245431Sdim } 396263509Sdim 397245431Sdim for (unsigned i = 0, e = Int.IS.RetVTs.size(); i != e; ++i) 398245431Sdim EncodeFixedType(Int.IS.RetTypeDefs[i], ArgCodes, TypeSig); 399193323Sed } 400263509Sdim 401245431Sdim for (unsigned i = 0, e = Int.IS.ParamTypeDefs.size(); i != e; ++i) 402245431Sdim EncodeFixedType(Int.IS.ParamTypeDefs[i], ArgCodes, TypeSig); 403193323Sed} 404193323Sed 405245431Sdimstatic void printIITEntry(raw_ostream &OS, unsigned char X) { 406245431Sdim OS << (unsigned)X; 407193323Sed} 408193323Sed 409263509Sdimvoid IntrinsicEmitter::EmitGenerator(const std::vector<CodeGenIntrinsic> &Ints, 410245431Sdim raw_ostream &OS) { 411245431Sdim // If we can compute a 32-bit fixed encoding for this intrinsic, do so and 412245431Sdim // capture it in this vector, otherwise store a ~0U. 413245431Sdim std::vector<unsigned> FixedEncodings; 414263509Sdim 415245431Sdim SequenceToOffsetTable<std::vector<unsigned char> > LongEncodingTable; 416263509Sdim 417245431Sdim std::vector<unsigned char> TypeSig; 418263509Sdim 419193323Sed // Compute the unique argument type info. 420245431Sdim for (unsigned i = 0, e = Ints.size(); i != e; ++i) { 421245431Sdim // Get the signature for the intrinsic. 422245431Sdim TypeSig.clear(); 423245431Sdim ComputeFixedEncoding(Ints[i], TypeSig); 424193323Sed 425245431Sdim // Check to see if we can encode it into a 32-bit word. We can only encode 426245431Sdim // 8 nibbles into a 32-bit word. 427245431Sdim if (TypeSig.size() <= 8) { 428245431Sdim bool Failed = false; 429245431Sdim unsigned Result = 0; 430245431Sdim for (unsigned i = 0, e = TypeSig.size(); i != e; ++i) { 431245431Sdim // If we had an unencodable argument, bail out. 432245431Sdim if (TypeSig[i] > 15) { 433245431Sdim Failed = true; 434245431Sdim break; 435245431Sdim } 436245431Sdim Result = (Result << 4) | TypeSig[e-i-1]; 437193323Sed } 438263509Sdim 439245431Sdim // If this could be encoded into a 31-bit word, return it. 440245431Sdim if (!Failed && (Result >> 31) == 0) { 441245431Sdim FixedEncodings.push_back(Result); 442245431Sdim continue; 443245431Sdim } 444193323Sed } 445193323Sed 446245431Sdim // Otherwise, we're going to unique the sequence into the 447245431Sdim // LongEncodingTable, and use its offset in the 32-bit table instead. 448245431Sdim LongEncodingTable.add(TypeSig); 449263509Sdim 450245431Sdim // This is a placehold that we'll replace after the table is laid out. 451245431Sdim FixedEncodings.push_back(~0U); 452193323Sed } 453263509Sdim 454245431Sdim LongEncodingTable.layout(); 455263509Sdim 456245431Sdim OS << "// Global intrinsic function declaration type table.\n"; 457245431Sdim OS << "#ifdef GET_INTRINSIC_GENERATOR_GLOBAL\n"; 458193323Sed 459245431Sdim OS << "static const unsigned IIT_Table[] = {\n "; 460263509Sdim 461245431Sdim for (unsigned i = 0, e = FixedEncodings.size(); i != e; ++i) { 462245431Sdim if ((i & 7) == 7) 463245431Sdim OS << "\n "; 464263509Sdim 465245431Sdim // If the entry fit in the table, just emit it. 466245431Sdim if (FixedEncodings[i] != ~0U) { 467245431Sdim OS << "0x" << utohexstr(FixedEncodings[i]) << ", "; 468245431Sdim continue; 469193323Sed } 470263509Sdim 471245431Sdim TypeSig.clear(); 472245431Sdim ComputeFixedEncoding(Ints[i], TypeSig); 473193323Sed 474263509Sdim 475245431Sdim // Otherwise, emit the offset into the long encoding table. We emit it this 476245431Sdim // way so that it is easier to read the offset in the .def file. 477245431Sdim OS << "(1U<<31) | " << LongEncodingTable.get(TypeSig) << ", "; 478245431Sdim } 479263509Sdim 480245431Sdim OS << "0\n};\n\n"; 481263509Sdim 482245431Sdim // Emit the shared table of register lists. 483245431Sdim OS << "static const unsigned char IIT_LongEncodingTable[] = {\n"; 484245431Sdim if (!LongEncodingTable.empty()) 485245431Sdim LongEncodingTable.emit(OS, printIITEntry); 486245431Sdim OS << " 255\n};\n\n"; 487263509Sdim 488245431Sdim OS << "#endif\n\n"; // End of GET_INTRINSIC_GENERATOR_GLOBAL 489245431Sdim} 490193323Sed 491245431Sdimenum ModRefKind { 492245431Sdim MRK_none, 493245431Sdim MRK_readonly, 494245431Sdim MRK_readnone 495245431Sdim}; 496245431Sdim 497245431Sdimstatic ModRefKind getModRefKind(const CodeGenIntrinsic &intrinsic) { 498245431Sdim switch (intrinsic.ModRef) { 499245431Sdim case CodeGenIntrinsic::NoMem: 500245431Sdim return MRK_readnone; 501245431Sdim case CodeGenIntrinsic::ReadArgMem: 502245431Sdim case CodeGenIntrinsic::ReadMem: 503245431Sdim return MRK_readonly; 504245431Sdim case CodeGenIntrinsic::ReadWriteArgMem: 505245431Sdim case CodeGenIntrinsic::ReadWriteMem: 506245431Sdim return MRK_none; 507193323Sed } 508245431Sdim llvm_unreachable("bad mod-ref kind"); 509193323Sed} 510193323Sed 511223017Sdimnamespace { 512245431Sdimstruct AttributeComparator { 513245431Sdim bool operator()(const CodeGenIntrinsic *L, const CodeGenIntrinsic *R) const { 514245431Sdim // Sort throwing intrinsics after non-throwing intrinsics. 515245431Sdim if (L->canThrow != R->canThrow) 516245431Sdim return R->canThrow; 517223017Sdim 518245431Sdim if (L->isNoReturn != R->isNoReturn) 519245431Sdim return R->isNoReturn; 520223017Sdim 521245431Sdim // Try to order by readonly/readnone attribute. 522245431Sdim ModRefKind LK = getModRefKind(*L); 523245431Sdim ModRefKind RK = getModRefKind(*R); 524245431Sdim if (LK != RK) return (LK > RK); 525223017Sdim 526245431Sdim // Order by argument attributes. 527245431Sdim // This is reliable because each side is already sorted internally. 528245431Sdim return (L->ArgumentAttributes < R->ArgumentAttributes); 529245431Sdim } 530245431Sdim}; 531245431Sdim} // End anonymous namespace 532223017Sdim 533193323Sed/// EmitAttributes - This emits the Intrinsic::getAttributes method. 534193323Sedvoid IntrinsicEmitter:: 535195340SedEmitAttributes(const std::vector<CodeGenIntrinsic> &Ints, raw_ostream &OS) { 536193323Sed OS << "// Add parameter attributes that are not common to all intrinsics.\n"; 537193323Sed OS << "#ifdef GET_INTRINSIC_ATTRIBUTES\n"; 538193323Sed if (TargetOnly) 539252723Sdim OS << "static AttributeSet getAttributes(LLVMContext &C, " << TargetPrefix 540223017Sdim << "Intrinsic::ID id) {\n"; 541193323Sed else 542252723Sdim OS << "AttributeSet Intrinsic::getAttributes(LLVMContext &C, ID id) {\n"; 543223017Sdim 544235633Sdim // Compute the maximum number of attribute arguments and the map 545235633Sdim typedef std::map<const CodeGenIntrinsic*, unsigned, 546235633Sdim AttributeComparator> UniqAttrMapTy; 547235633Sdim UniqAttrMapTy UniqAttributes; 548223017Sdim unsigned maxArgAttrs = 0; 549235633Sdim unsigned AttrNum = 0; 550193323Sed for (unsigned i = 0, e = Ints.size(); i != e; ++i) { 551223017Sdim const CodeGenIntrinsic &intrinsic = Ints[i]; 552223017Sdim maxArgAttrs = 553223017Sdim std::max(maxArgAttrs, unsigned(intrinsic.ArgumentAttributes.size())); 554235633Sdim unsigned &N = UniqAttributes[&intrinsic]; 555235633Sdim if (N) continue; 556235633Sdim assert(AttrNum < 256 && "Too many unique attributes for table!"); 557235633Sdim N = ++AttrNum; 558193323Sed } 559223017Sdim 560252723Sdim // Emit an array of AttributeSet. Most intrinsics will have at least one 561252723Sdim // entry, for the function itself (index ~1), which is usually nounwind. 562235633Sdim OS << " static const uint8_t IntrinsicsToAttributesMap[] = {\n"; 563193323Sed 564235633Sdim for (unsigned i = 0, e = Ints.size(); i != e; ++i) { 565235633Sdim const CodeGenIntrinsic &intrinsic = Ints[i]; 566193323Sed 567235633Sdim OS << " " << UniqAttributes[&intrinsic] << ", // " 568235633Sdim << intrinsic.Name << "\n"; 569235633Sdim } 570235633Sdim OS << " };\n\n"; 571193323Sed 572252723Sdim OS << " AttributeSet AS[" << maxArgAttrs+1 << "];\n"; 573235633Sdim OS << " unsigned NumAttrs = 0;\n"; 574235633Sdim OS << " if (id != 0) {\n"; 575235633Sdim OS << " switch(IntrinsicsToAttributesMap[id - "; 576235633Sdim if (TargetOnly) 577235633Sdim OS << "Intrinsic::num_intrinsics"; 578235633Sdim else 579235633Sdim OS << "1"; 580235633Sdim OS << "]) {\n"; 581235633Sdim OS << " default: llvm_unreachable(\"Invalid attribute number\");\n"; 582235633Sdim for (UniqAttrMapTy::const_iterator I = UniqAttributes.begin(), 583235633Sdim E = UniqAttributes.end(); I != E; ++I) { 584263509Sdim OS << " case " << I->second << ": {\n"; 585223017Sdim 586235633Sdim const CodeGenIntrinsic &intrinsic = *(I->first); 587223017Sdim 588223017Sdim // Keep track of the number of attributes we're writing out. 589223017Sdim unsigned numAttrs = 0; 590223017Sdim 591223017Sdim // The argument attributes are alreadys sorted by argument index. 592245431Sdim unsigned ai = 0, ae = intrinsic.ArgumentAttributes.size(); 593245431Sdim if (ae) { 594245431Sdim while (ai != ae) { 595245431Sdim unsigned argNo = intrinsic.ArgumentAttributes[ai].first; 596235633Sdim 597263509Sdim OS << " const Attribute::AttrKind AttrParam" << argNo + 1 <<"[]= {"; 598263509Sdim bool addComma = false; 599193323Sed 600245431Sdim do { 601245431Sdim switch (intrinsic.ArgumentAttributes[ai].second) { 602245431Sdim case CodeGenIntrinsic::NoCapture: 603263509Sdim if (addComma) 604263509Sdim OS << ","; 605263509Sdim OS << "Attribute::NoCapture"; 606263509Sdim addComma = true; 607245431Sdim break; 608263509Sdim case CodeGenIntrinsic::ReadOnly: 609263509Sdim if (addComma) 610263509Sdim OS << ","; 611263509Sdim OS << "Attribute::ReadOnly"; 612263509Sdim addComma = true; 613263509Sdim break; 614263509Sdim case CodeGenIntrinsic::ReadNone: 615263509Sdim if (addComma) 616263509Sdim OS << ","; 617263509Sdim OS << "Attributes::ReadNone"; 618263509Sdim addComma = true; 619263509Sdim break; 620245431Sdim } 621223017Sdim 622245431Sdim ++ai; 623245431Sdim } while (ai != ae && intrinsic.ArgumentAttributes[ai].first == argNo); 624263509Sdim OS << "};\n"; 625252723Sdim OS << " AS[" << numAttrs++ << "] = AttributeSet::get(C, " 626263509Sdim << argNo+1 << ", AttrParam" << argNo +1 << ");\n"; 627245431Sdim } 628223017Sdim } 629223017Sdim 630223017Sdim ModRefKind modRef = getModRefKind(intrinsic); 631223017Sdim 632245431Sdim if (!intrinsic.canThrow || modRef || intrinsic.isNoReturn) { 633263509Sdim OS << " const Attribute::AttrKind Atts[] = {"; 634263509Sdim bool addComma = false; 635263509Sdim if (!intrinsic.canThrow) { 636263509Sdim OS << "Attribute::NoUnwind"; 637263509Sdim addComma = true; 638263509Sdim } 639263509Sdim if (intrinsic.isNoReturn) { 640263509Sdim if (addComma) 641263509Sdim OS << ","; 642263509Sdim OS << "Attribute::NoReturn"; 643263509Sdim addComma = true; 644263509Sdim } 645245431Sdim 646223017Sdim switch (modRef) { 647223017Sdim case MRK_none: break; 648245431Sdim case MRK_readonly: 649263509Sdim if (addComma) 650263509Sdim OS << ","; 651263509Sdim OS << "Attribute::ReadOnly"; 652245431Sdim break; 653245431Sdim case MRK_readnone: 654263509Sdim if (addComma) 655263509Sdim OS << ","; 656263509Sdim OS << "Attribute::ReadNone"; 657245431Sdim break; 658223017Sdim } 659263509Sdim OS << "};\n"; 660252723Sdim OS << " AS[" << numAttrs++ << "] = AttributeSet::get(C, " 661263509Sdim << "AttributeSet::FunctionIndex, Atts);\n"; 662193323Sed } 663223017Sdim 664223017Sdim if (numAttrs) { 665235633Sdim OS << " NumAttrs = " << numAttrs << ";\n"; 666235633Sdim OS << " break;\n"; 667263509Sdim OS << " }\n"; 668223017Sdim } else { 669252723Sdim OS << " return AttributeSet();\n"; 670223017Sdim } 671193323Sed } 672263509Sdim 673235633Sdim OS << " }\n"; 674193323Sed OS << " }\n"; 675252723Sdim OS << " return AttributeSet::get(C, ArrayRef<AttributeSet>(AS, " 676245431Sdim "NumAttrs));\n"; 677193323Sed OS << "}\n"; 678193323Sed OS << "#endif // GET_INTRINSIC_ATTRIBUTES\n\n"; 679193323Sed} 680193323Sed 681193323Sed/// EmitModRefBehavior - Determine intrinsic alias analysis mod/ref behavior. 682193323Sedvoid IntrinsicEmitter:: 683195340SedEmitModRefBehavior(const std::vector<CodeGenIntrinsic> &Ints, raw_ostream &OS){ 684235633Sdim OS << "// Determine intrinsic alias analysis mod/ref behavior.\n" 685235633Sdim << "#ifdef GET_INTRINSIC_MODREF_BEHAVIOR\n" 686235633Sdim << "assert(iid <= Intrinsic::" << Ints.back().EnumName << " && " 687235633Sdim << "\"Unknown intrinsic.\");\n\n"; 688235633Sdim 689235633Sdim OS << "static const uint8_t IntrinsicModRefBehavior[] = {\n" 690235633Sdim << " /* invalid */ UnknownModRefBehavior,\n"; 691193323Sed for (unsigned i = 0, e = Ints.size(); i != e; ++i) { 692235633Sdim OS << " /* " << TargetPrefix << Ints[i].EnumName << " */ "; 693193323Sed switch (Ints[i].ModRef) { 694193323Sed case CodeGenIntrinsic::NoMem: 695235633Sdim OS << "DoesNotAccessMemory,\n"; 696193323Sed break; 697193323Sed case CodeGenIntrinsic::ReadArgMem: 698235633Sdim OS << "OnlyReadsArgumentPointees,\n"; 699218893Sdim break; 700193323Sed case CodeGenIntrinsic::ReadMem: 701235633Sdim OS << "OnlyReadsMemory,\n"; 702193323Sed break; 703212904Sdim case CodeGenIntrinsic::ReadWriteArgMem: 704235633Sdim OS << "OnlyAccessesArgumentPointees,\n"; 705193323Sed break; 706235633Sdim case CodeGenIntrinsic::ReadWriteMem: 707235633Sdim OS << "UnknownModRefBehavior,\n"; 708235633Sdim break; 709193323Sed } 710193323Sed } 711235633Sdim OS << "};\n\n" 712235633Sdim << "return static_cast<ModRefBehavior>(IntrinsicModRefBehavior[iid]);\n" 713235633Sdim << "#endif // GET_INTRINSIC_MODREF_BEHAVIOR\n\n"; 714193323Sed} 715193323Sed 716193323Sed/// EmitTargetBuiltins - All of the builtins in the specified map are for the 717193323Sed/// same target, and we already checked it. 718193323Sedstatic void EmitTargetBuiltins(const std::map<std::string, std::string> &BIM, 719193323Sed const std::string &TargetPrefix, 720195340Sed raw_ostream &OS) { 721263509Sdim 722218893Sdim std::vector<StringMatcher::StringPair> Results; 723263509Sdim 724218893Sdim for (std::map<std::string, std::string>::const_iterator I = BIM.begin(), 725218893Sdim E = BIM.end(); I != E; ++I) { 726218893Sdim std::string ResultCode = 727218893Sdim "return " + TargetPrefix + "Intrinsic::" + I->second + ";"; 728218893Sdim Results.push_back(StringMatcher::StringPair(I->first, ResultCode)); 729193323Sed } 730218893Sdim 731218893Sdim StringMatcher("BuiltinName", Results, OS).Emit(); 732193323Sed} 733193323Sed 734263509Sdim 735193323Sedvoid IntrinsicEmitter:: 736263509SdimEmitIntrinsicToGCCBuiltinMap(const std::vector<CodeGenIntrinsic> &Ints, 737195340Sed raw_ostream &OS) { 738193323Sed typedef std::map<std::string, std::map<std::string, std::string> > BIMTy; 739193323Sed BIMTy BuiltinMap; 740193323Sed for (unsigned i = 0, e = Ints.size(); i != e; ++i) { 741193323Sed if (!Ints[i].GCCBuiltinName.empty()) { 742193323Sed // Get the map for this target prefix. 743193323Sed std::map<std::string, std::string> &BIM =BuiltinMap[Ints[i].TargetPrefix]; 744263509Sdim 745193323Sed if (!BIM.insert(std::make_pair(Ints[i].GCCBuiltinName, 746193323Sed Ints[i].EnumName)).second) 747245431Sdim PrintFatalError("Intrinsic '" + Ints[i].TheDef->getName() + 748245431Sdim "': duplicate GCC builtin name!"); 749193323Sed } 750193323Sed } 751263509Sdim 752193323Sed OS << "// Get the LLVM intrinsic that corresponds to a GCC builtin.\n"; 753193323Sed OS << "// This is used by the C front-end. The GCC builtin name is passed\n"; 754193323Sed OS << "// in as BuiltinName, and a target prefix (e.g. 'ppc') is passed\n"; 755193323Sed OS << "// in as TargetPrefix. The result is assigned to 'IntrinsicID'.\n"; 756193323Sed OS << "#ifdef GET_LLVM_INTRINSIC_FOR_GCC_BUILTIN\n"; 757263509Sdim 758193323Sed if (TargetOnly) { 759193323Sed OS << "static " << TargetPrefix << "Intrinsic::ID " 760193323Sed << "getIntrinsicForGCCBuiltin(const char " 761218893Sdim << "*TargetPrefixStr, const char *BuiltinNameStr) {\n"; 762193323Sed } else { 763193323Sed OS << "Intrinsic::ID Intrinsic::getIntrinsicForGCCBuiltin(const char " 764218893Sdim << "*TargetPrefixStr, const char *BuiltinNameStr) {\n"; 765193323Sed } 766263509Sdim 767218893Sdim OS << " StringRef BuiltinName(BuiltinNameStr);\n"; 768218893Sdim OS << " StringRef TargetPrefix(TargetPrefixStr);\n\n"; 769263509Sdim 770193323Sed // Note: this could emit significantly better code if we cared. 771193323Sed for (BIMTy::iterator I = BuiltinMap.begin(), E = BuiltinMap.end();I != E;++I){ 772193323Sed OS << " "; 773193323Sed if (!I->first.empty()) 774218893Sdim OS << "if (TargetPrefix == \"" << I->first << "\") "; 775193323Sed else 776193323Sed OS << "/* Target Independent Builtins */ "; 777193323Sed OS << "{\n"; 778193323Sed 779193323Sed // Emit the comparisons for this target prefix. 780193323Sed EmitTargetBuiltins(I->second, TargetPrefix, OS); 781193323Sed OS << " }\n"; 782193323Sed } 783218893Sdim OS << " return "; 784218893Sdim if (!TargetPrefix.empty()) 785218893Sdim OS << "(" << TargetPrefix << "Intrinsic::ID)"; 786218893Sdim OS << "Intrinsic::not_intrinsic;\n"; 787193323Sed OS << "}\n"; 788193323Sed OS << "#endif\n\n"; 789193323Sed} 790245431Sdim 791245431Sdimnamespace llvm { 792245431Sdim 793245431Sdimvoid EmitIntrinsics(RecordKeeper &RK, raw_ostream &OS, bool TargetOnly = false) { 794245431Sdim IntrinsicEmitter(RK, TargetOnly).run(OS); 795245431Sdim} 796245431Sdim 797245431Sdim} // End llvm namespace 798