1 //===- IntrinsicEmitter.cpp - Generate intrinsic information --------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This tablegen backend emits information about intrinsic functions. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #include "CodeGenTarget.h" 15 #include "IntrinsicEmitter.h" 16 #include "Record.h" 17 #include "llvm/ADT/StringExtras.h" 18 #include <algorithm> 19 using namespace llvm; 20 21 //===----------------------------------------------------------------------===// 22 // IntrinsicEmitter Implementation 23 //===----------------------------------------------------------------------===// 24 25 void IntrinsicEmitter::run(std::ostream &OS) { 26 EmitSourceFileHeader("Intrinsic Function Source Fragment", OS); 27 28 std::vector<CodeGenIntrinsic> Ints = LoadIntrinsics(Records, TargetOnly); 29 30 if (TargetOnly && !Ints.empty()) 31 TargetPrefix = Ints[0].TargetPrefix; 32 33 // Emit the enum information. 34 EmitEnumInfo(Ints, OS); 35 36 // Emit the intrinsic ID -> name table. 37 EmitIntrinsicToNameTable(Ints, OS); 38 39 // Emit the intrinsic ID -> overload table. 40 EmitIntrinsicToOverloadTable(Ints, OS); 41 42 // Emit the function name recognizer. 43 EmitFnNameRecognizer(Ints, OS); 44 45 // Emit the intrinsic verifier. 46 EmitVerifier(Ints, OS); 47 48 // Emit the intrinsic declaration generator. 49 EmitGenerator(Ints, OS); 50 51 // Emit the intrinsic parameter attributes. 52 EmitAttributes(Ints, OS); 53 54 // Emit intrinsic alias analysis mod/ref behavior. 55 EmitModRefBehavior(Ints, OS); 56 57 // Emit a list of intrinsics with corresponding GCC builtins. 58 EmitGCCBuiltinList(Ints, OS); 59 60 // Emit code to translate GCC builtins into LLVM intrinsics. 61 EmitIntrinsicToGCCBuiltinMap(Ints, OS); 62 } 63 64 void IntrinsicEmitter::EmitEnumInfo(const std::vector<CodeGenIntrinsic> &Ints, 65 std::ostream &OS) { 66 OS << "// Enum values for Intrinsics.h\n"; 67 OS << "#ifdef GET_INTRINSIC_ENUM_VALUES\n"; 68 for (unsigned i = 0, e = Ints.size(); i != e; ++i) { 69 OS << " " << Ints[i].EnumName; 70 OS << ((i != e-1) ? ", " : " "); 71 OS << std::string(40-Ints[i].EnumName.size(), ' ') 72 << "// " << Ints[i].Name << "\n"; 73 } 74 OS << "#endif\n\n"; 75 } 76 77 void IntrinsicEmitter:: 78 EmitFnNameRecognizer(const std::vector<CodeGenIntrinsic> &Ints, 79 std::ostream &OS) { 80 // Build a function name -> intrinsic name mapping. 81 std::map<std::string, unsigned> IntMapping; 82 for (unsigned i = 0, e = Ints.size(); i != e; ++i) 83 IntMapping[Ints[i].Name] = i; 84 85 OS << "// Function name -> enum value recognizer code.\n"; 86 OS << "#ifdef GET_FUNCTION_RECOGNIZER\n"; 87 OS << " switch (Name[5]) {\n"; 88 OS << " default:\n"; 89 // Emit the intrinsics in sorted order. 90 char LastChar = 0; 91 for (std::map<std::string, unsigned>::iterator I = IntMapping.begin(), 92 E = IntMapping.end(); I != E; ++I) { 93 if (I->first[5] != LastChar) { 94 LastChar = I->first[5]; 95 OS << " break;\n"; 96 OS << " case '" << LastChar << "':\n"; 97 } 98 99 // For overloaded intrinsics, only the prefix needs to match 100 if (Ints[I->second].isOverloaded) 101 OS << " if (Len > " << I->first.size() 102 << " && !memcmp(Name, \"" << I->first << ".\", " 103 << (I->first.size() + 1) << ")) return " << TargetPrefix << "Intrinsic::" 104 << Ints[I->second].EnumName << ";\n"; 105 else 106 OS << " if (Len == " << I->first.size() 107 << " && !memcmp(Name, \"" << I->first << "\", " 108 << I->first.size() << ")) return " << TargetPrefix << "Intrinsic::" 109 << Ints[I->second].EnumName << ";\n"; 110 } 111 OS << " }\n"; 112 OS << "#endif\n\n"; 113 } 114 115 void IntrinsicEmitter:: 116 EmitIntrinsicToNameTable(const std::vector<CodeGenIntrinsic> &Ints, 117 std::ostream &OS) { 118 OS << "// Intrinsic ID to name table\n"; 119 OS << "#ifdef GET_INTRINSIC_NAME_TABLE\n"; 120 OS << " // Note that entry #0 is the invalid intrinsic!\n"; 121 for (unsigned i = 0, e = Ints.size(); i != e; ++i) 122 OS << " \"" << Ints[i].Name << "\",\n"; 123 OS << "#endif\n\n"; 124 } 125 126 void IntrinsicEmitter:: 127 EmitIntrinsicToOverloadTable(const std::vector<CodeGenIntrinsic> &Ints, 128 std::ostream &OS) { 129 OS << "// Intrinsic ID to overload table\n"; 130 OS << "#ifdef GET_INTRINSIC_OVERLOAD_TABLE\n"; 131 OS << " // Note that entry #0 is the invalid intrinsic!\n"; 132 for (unsigned i = 0, e = Ints.size(); i != e; ++i) { 133 OS << " "; 134 if (Ints[i].isOverloaded) 135 OS << "true"; 136 else 137 OS << "false"; 138 OS << ",\n"; 139 } 140 OS << "#endif\n\n"; 141 } 142 143 static void EmitTypeForValueType(std::ostream &OS, MVT::SimpleValueType VT) { 144 if (MVT(VT).isInteger()) { 145 unsigned BitWidth = MVT(VT).getSizeInBits(); 146 OS << "IntegerType::get(" << BitWidth << ")"; 147 } else if (VT == MVT::Other) { 148 // MVT::OtherVT is used to mean the empty struct type here. 149 OS << "StructType::get()"; 150 } else if (VT == MVT::f32) { 151 OS << "Type::FloatTy"; 152 } else if (VT == MVT::f64) { 153 OS << "Type::DoubleTy"; 154 } else if (VT == MVT::f80) { 155 OS << "Type::X86_FP80Ty"; 156 } else if (VT == MVT::f128) { 157 OS << "Type::FP128Ty"; 158 } else if (VT == MVT::ppcf128) { 159 OS << "Type::PPC_FP128Ty"; 160 } else if (VT == MVT::isVoid) { 161 OS << "Type::VoidTy"; 162 } else { 163 assert(false && "Unsupported ValueType!"); 164 } 165 } 166 167 static void EmitTypeGenerate(std::ostream &OS, const Record *ArgType, 168 unsigned &ArgNo); 169 170 static void EmitTypeGenerate(std::ostream &OS, 171 const std::vector<Record*> &ArgTypes, 172 unsigned &ArgNo) { 173 if (ArgTypes.size() == 1) { 174 EmitTypeGenerate(OS, ArgTypes.front(), ArgNo); 175 return; 176 } 177 178 OS << "StructType::get("; 179 180 for (std::vector<Record*>::const_iterator 181 I = ArgTypes.begin(), E = ArgTypes.end(); I != E; ++I) { 182 EmitTypeGenerate(OS, *I, ArgNo); 183 OS << ", "; 184 } 185 186 OS << " NULL)"; 187 } 188 189 static void EmitTypeGenerate(std::ostream &OS, const Record *ArgType, 190 unsigned &ArgNo) { 191 MVT::SimpleValueType VT = getValueType(ArgType->getValueAsDef("VT")); 192 193 if (ArgType->isSubClassOf("LLVMMatchType")) { 194 unsigned Number = ArgType->getValueAsInt("Number"); 195 assert(Number < ArgNo && "Invalid matching number!"); 196 if (ArgType->isSubClassOf("LLVMExtendedElementVectorType")) 197 OS << "VectorType::getExtendedElementVectorType" 198 << "(dyn_cast<VectorType>(Tys[" << Number << "]))"; 199 else if (ArgType->isSubClassOf("LLVMTruncatedElementVectorType")) 200 OS << "VectorType::getTruncatedElementVectorType" 201 << "(dyn_cast<VectorType>(Tys[" << Number << "]))"; 202 else 203 OS << "Tys[" << Number << "]"; 204 } else if (VT == MVT::iAny || VT == MVT::fAny) { 205 // NOTE: The ArgNo variable here is not the absolute argument number, it is 206 // the index of the "arbitrary" type in the Tys array passed to the 207 // Intrinsic::getDeclaration function. Consequently, we only want to 208 // increment it when we actually hit an overloaded type. Getting this wrong 209 // leads to very subtle bugs! 210 OS << "Tys[" << ArgNo++ << "]"; 211 } else if (MVT(VT).isVector()) { 212 MVT VVT = VT; 213 OS << "VectorType::get("; 214 EmitTypeForValueType(OS, VVT.getVectorElementType().getSimpleVT()); 215 OS << ", " << VVT.getVectorNumElements() << ")"; 216 } else if (VT == MVT::iPTR) { 217 OS << "PointerType::getUnqual("; 218 EmitTypeGenerate(OS, ArgType->getValueAsDef("ElTy"), ArgNo); 219 OS << ")"; 220 } else if (VT == MVT::iPTRAny) { 221 // Make sure the user has passed us an argument type to overload. If not, 222 // treat it as an ordinary (not overloaded) intrinsic. 223 OS << "(" << ArgNo << " < numTys) ? Tys[" << ArgNo 224 << "] : PointerType::getUnqual("; 225 EmitTypeGenerate(OS, ArgType->getValueAsDef("ElTy"), ArgNo); 226 OS << ")"; 227 ++ArgNo; 228 } else if (VT == MVT::isVoid) { 229 if (ArgNo == 0) 230 OS << "Type::VoidTy"; 231 else 232 // MVT::isVoid is used to mean varargs here. 233 OS << "..."; 234 } else { 235 EmitTypeForValueType(OS, VT); 236 } 237 } 238 239 /// RecordListComparator - Provide a deterministic comparator for lists of 240 /// records. 241 namespace { 242 typedef std::pair<std::vector<Record*>, std::vector<Record*> > RecPair; 243 struct RecordListComparator { 244 bool operator()(const RecPair &LHS, 245 const RecPair &RHS) const { 246 unsigned i = 0; 247 const std::vector<Record*> *LHSVec = &LHS.first; 248 const std::vector<Record*> *RHSVec = &RHS.first; 249 unsigned RHSSize = RHSVec->size(); 250 unsigned LHSSize = LHSVec->size(); 251 252 do { 253 if (i == RHSSize) return false; // RHS is shorter than LHS. 254 if ((*LHSVec)[i] != (*RHSVec)[i]) 255 return (*LHSVec)[i]->getName() < (*RHSVec)[i]->getName(); 256 } while (++i != LHSSize); 257 258 if (i != RHSSize) return true; 259 260 i = 0; 261 LHSVec = &LHS.second; 262 RHSVec = &RHS.second; 263 RHSSize = RHSVec->size(); 264 LHSSize = LHSVec->size(); 265 266 for (i = 0; i != LHSSize; ++i) { 267 if (i == RHSSize) return false; // RHS is shorter than LHS. 268 if ((*LHSVec)[i] != (*RHSVec)[i]) 269 return (*LHSVec)[i]->getName() < (*RHSVec)[i]->getName(); 270 } 271 272 return i != RHSSize; 273 } 274 }; 275 } 276 277 void IntrinsicEmitter::EmitVerifier(const std::vector<CodeGenIntrinsic> &Ints, 278 std::ostream &OS) { 279 OS << "// Verifier::visitIntrinsicFunctionCall code.\n"; 280 OS << "#ifdef GET_INTRINSIC_VERIFIER\n"; 281 OS << " switch (ID) {\n"; 282 OS << " default: assert(0 && \"Invalid intrinsic!\");\n"; 283 284 // This checking can emit a lot of very common code. To reduce the amount of 285 // code that we emit, batch up cases that have identical types. This avoids 286 // problems where GCC can run out of memory compiling Verifier.cpp. 287 typedef std::map<RecPair, std::vector<unsigned>, RecordListComparator> MapTy; 288 MapTy UniqueArgInfos; 289 290 // Compute the unique argument type info. 291 for (unsigned i = 0, e = Ints.size(); i != e; ++i) 292 UniqueArgInfos[make_pair(Ints[i].IS.RetTypeDefs, 293 Ints[i].IS.ParamTypeDefs)].push_back(i); 294 295 // Loop through the array, emitting one comparison for each batch. 296 for (MapTy::iterator I = UniqueArgInfos.begin(), 297 E = UniqueArgInfos.end(); I != E; ++I) { 298 for (unsigned i = 0, e = I->second.size(); i != e; ++i) 299 OS << " case Intrinsic::" << Ints[I->second[i]].EnumName << ":\t\t// " 300 << Ints[I->second[i]].Name << "\n"; 301 302 const RecPair &ArgTypes = I->first; 303 const std::vector<Record*> &RetTys = ArgTypes.first; 304 const std::vector<Record*> &ParamTys = ArgTypes.second; 305 306 OS << " VerifyIntrinsicPrototype(ID, IF, " << RetTys.size() << ", " 307 << ParamTys.size(); 308 309 // Emit return types. 310 for (unsigned j = 0, je = RetTys.size(); j != je; ++j) { 311 Record *ArgType = RetTys[j]; 312 OS << ", "; 313 314 if (ArgType->isSubClassOf("LLVMMatchType")) { 315 unsigned Number = ArgType->getValueAsInt("Number"); 316 if (ArgType->isSubClassOf("LLVMExtendedElementVectorType")) 317 OS << "~(ExtendedElementVectorType | " << Number << ")"; 318 else if (ArgType->isSubClassOf("LLVMTruncatedElementVectorType")) 319 OS << "~(TruncatedElementVectorType | " << Number << ")"; 320 else 321 OS << "~" << Number; 322 } else { 323 MVT::SimpleValueType VT = getValueType(ArgType->getValueAsDef("VT")); 324 OS << getEnumName(VT); 325 326 if (VT == MVT::isVoid && j != 0 && j != je - 1) 327 throw "Var arg type not last argument"; 328 } 329 } 330 331 // Emit the parameter types. 332 for (unsigned j = 0, je = ParamTys.size(); j != je; ++j) { 333 Record *ArgType = ParamTys[j]; 334 OS << ", "; 335 336 if (ArgType->isSubClassOf("LLVMMatchType")) { 337 unsigned Number = ArgType->getValueAsInt("Number"); 338 if (ArgType->isSubClassOf("LLVMExtendedElementVectorType")) 339 OS << "~(ExtendedElementVectorType | " << Number << ")"; 340 else if (ArgType->isSubClassOf("LLVMTruncatedElementVectorType")) 341 OS << "~(TruncatedElementVectorType | " << Number << ")"; 342 else 343 OS << "~" << Number; 344 } else { 345 MVT::SimpleValueType VT = getValueType(ArgType->getValueAsDef("VT")); 346 OS << getEnumName(VT); 347 348 if (VT == MVT::isVoid && j != 0 && j != je - 1) 349 throw "Var arg type not last argument"; 350 } 351 } 352 353 OS << ");\n"; 354 OS << " break;\n"; 355 } 356 OS << " }\n"; 357 OS << "#endif\n\n"; 358 } 359 360 void IntrinsicEmitter::EmitGenerator(const std::vector<CodeGenIntrinsic> &Ints, 361 std::ostream &OS) { 362 OS << "// Code for generating Intrinsic function declarations.\n"; 363 OS << "#ifdef GET_INTRINSIC_GENERATOR\n"; 364 OS << " switch (id) {\n"; 365 OS << " default: assert(0 && \"Invalid intrinsic!\");\n"; 366 367 // Similar to GET_INTRINSIC_VERIFIER, batch up cases that have identical 368 // types. 369 typedef std::map<RecPair, std::vector<unsigned>, RecordListComparator> MapTy; 370 MapTy UniqueArgInfos; 371 372 // Compute the unique argument type info. 373 for (unsigned i = 0, e = Ints.size(); i != e; ++i) 374 UniqueArgInfos[make_pair(Ints[i].IS.RetTypeDefs, 375 Ints[i].IS.ParamTypeDefs)].push_back(i); 376 377 // Loop through the array, emitting one generator for each batch. 378 std::string IntrinsicStr = TargetPrefix + "Intrinsic::"; 379 380 for (MapTy::iterator I = UniqueArgInfos.begin(), 381 E = UniqueArgInfos.end(); I != E; ++I) { 382 for (unsigned i = 0, e = I->second.size(); i != e; ++i) 383 OS << " case " << IntrinsicStr << Ints[I->second[i]].EnumName 384 << ":\t\t// " << Ints[I->second[i]].Name << "\n"; 385 386 const RecPair &ArgTypes = I->first; 387 const std::vector<Record*> &RetTys = ArgTypes.first; 388 const std::vector<Record*> &ParamTys = ArgTypes.second; 389 390 unsigned N = ParamTys.size(); 391 392 if (N > 1 && 393 getValueType(ParamTys[N - 1]->getValueAsDef("VT")) == MVT::isVoid) { 394 OS << " IsVarArg = true;\n"; 395 --N; 396 } 397 398 unsigned ArgNo = 0; 399 OS << " ResultTy = "; 400 EmitTypeGenerate(OS, RetTys, ArgNo); 401 OS << ";\n"; 402 403 for (unsigned j = 0; j != N; ++j) { 404 OS << " ArgTys.push_back("; 405 EmitTypeGenerate(OS, ParamTys[j], ArgNo); 406 OS << ");\n"; 407 } 408 409 OS << " break;\n"; 410 } 411 412 OS << " }\n"; 413 OS << "#endif\n\n"; 414 } 415 416 /// EmitAttributes - This emits the Intrinsic::getAttributes method. 417 void IntrinsicEmitter:: 418 EmitAttributes(const std::vector<CodeGenIntrinsic> &Ints, std::ostream &OS) { 419 OS << "// Add parameter attributes that are not common to all intrinsics.\n"; 420 OS << "#ifdef GET_INTRINSIC_ATTRIBUTES\n"; 421 if (TargetOnly) 422 OS << "static AttrListPtr getAttributes(" << TargetPrefix 423 << "Intrinsic::ID id) {"; 424 else 425 OS << "AttrListPtr Intrinsic::getAttributes(ID id) {"; 426 OS << " // No intrinsic can throw exceptions.\n"; 427 OS << " Attributes Attr = Attribute::NoUnwind;\n"; 428 OS << " switch (id) {\n"; 429 OS << " default: break;\n"; 430 unsigned MaxArgAttrs = 0; 431 for (unsigned i = 0, e = Ints.size(); i != e; ++i) { 432 MaxArgAttrs = 433 std::max(MaxArgAttrs, unsigned(Ints[i].ArgumentAttributes.size())); 434 switch (Ints[i].ModRef) { 435 default: break; 436 case CodeGenIntrinsic::NoMem: 437 OS << " case " << TargetPrefix << "Intrinsic::" << Ints[i].EnumName 438 << ":\n"; 439 break; 440 } 441 } 442 OS << " Attr |= Attribute::ReadNone; // These do not access memory.\n"; 443 OS << " break;\n"; 444 for (unsigned i = 0, e = Ints.size(); i != e; ++i) { 445 switch (Ints[i].ModRef) { 446 default: break; 447 case CodeGenIntrinsic::ReadArgMem: 448 case CodeGenIntrinsic::ReadMem: 449 OS << " case " << TargetPrefix << "Intrinsic::" << Ints[i].EnumName 450 << ":\n"; 451 break; 452 } 453 } 454 OS << " Attr |= Attribute::ReadOnly; // These do not write memory.\n"; 455 OS << " break;\n"; 456 OS << " }\n"; 457 OS << " AttributeWithIndex AWI[" << MaxArgAttrs+1 << "];\n"; 458 OS << " unsigned NumAttrs = 0;\n"; 459 OS << " switch (id) {\n"; 460 OS << " default: break;\n"; 461 462 // Add argument attributes for any intrinsics that have them. 463 for (unsigned i = 0, e = Ints.size(); i != e; ++i) { 464 if (Ints[i].ArgumentAttributes.empty()) continue; 465 466 OS << " case " << TargetPrefix << "Intrinsic::" << Ints[i].EnumName 467 << ":\n"; 468 469 std::vector<std::pair<unsigned, CodeGenIntrinsic::ArgAttribute> > ArgAttrs = 470 Ints[i].ArgumentAttributes; 471 // Sort by argument index. 472 std::sort(ArgAttrs.begin(), ArgAttrs.end()); 473 474 unsigned NumArgsWithAttrs = 0; 475 476 while (!ArgAttrs.empty()) { 477 unsigned ArgNo = ArgAttrs[0].first; 478 479 OS << " AWI[" << NumArgsWithAttrs++ << "] = AttributeWithIndex::get(" 480 << ArgNo+1 << ", 0"; 481 482 while (!ArgAttrs.empty() && ArgAttrs[0].first == ArgNo) { 483 switch (ArgAttrs[0].second) { 484 default: assert(0 && "Unknown arg attribute"); 485 case CodeGenIntrinsic::NoCapture: 486 OS << "|Attribute::NoCapture"; 487 break; 488 } 489 ArgAttrs.erase(ArgAttrs.begin()); 490 } 491 OS << ");\n"; 492 } 493 494 OS << " NumAttrs = " << NumArgsWithAttrs << ";\n"; 495 OS << " break;\n"; 496 } 497 498 OS << " }\n"; 499 OS << " AWI[NumAttrs] = AttributeWithIndex::get(~0, Attr);\n"; 500 OS << " return AttrListPtr::get(AWI, NumAttrs+1);\n"; 501 OS << "}\n"; 502 OS << "#endif // GET_INTRINSIC_ATTRIBUTES\n\n"; 503 } 504 505 /// EmitModRefBehavior - Determine intrinsic alias analysis mod/ref behavior. 506 void IntrinsicEmitter:: 507 EmitModRefBehavior(const std::vector<CodeGenIntrinsic> &Ints, std::ostream &OS){ 508 OS << "// Determine intrinsic alias analysis mod/ref behavior.\n"; 509 OS << "#ifdef GET_INTRINSIC_MODREF_BEHAVIOR\n"; 510 OS << "switch (id) {\n"; 511 OS << "default:\n return UnknownModRefBehavior;\n"; 512 for (unsigned i = 0, e = Ints.size(); i != e; ++i) { 513 if (Ints[i].ModRef == CodeGenIntrinsic::WriteMem) 514 continue; 515 OS << "case " << TargetPrefix << "Intrinsic::" << Ints[i].EnumName 516 << ":\n"; 517 switch (Ints[i].ModRef) { 518 default: 519 assert(false && "Unknown Mod/Ref type!"); 520 case CodeGenIntrinsic::NoMem: 521 OS << " return DoesNotAccessMemory;\n"; 522 break; 523 case CodeGenIntrinsic::ReadArgMem: 524 case CodeGenIntrinsic::ReadMem: 525 OS << " return OnlyReadsMemory;\n"; 526 break; 527 case CodeGenIntrinsic::WriteArgMem: 528 OS << " return AccessesArguments;\n"; 529 break; 530 } 531 } 532 OS << "}\n"; 533 OS << "#endif // GET_INTRINSIC_MODREF_BEHAVIOR\n\n"; 534 } 535 536 void IntrinsicEmitter:: 537 EmitGCCBuiltinList(const std::vector<CodeGenIntrinsic> &Ints, std::ostream &OS){ 538 OS << "// Get the GCC builtin that corresponds to an LLVM intrinsic.\n"; 539 OS << "#ifdef GET_GCC_BUILTIN_NAME\n"; 540 OS << " switch (F->getIntrinsicID()) {\n"; 541 OS << " default: BuiltinName = \"\"; break;\n"; 542 for (unsigned i = 0, e = Ints.size(); i != e; ++i) { 543 if (!Ints[i].GCCBuiltinName.empty()) { 544 OS << " case Intrinsic::" << Ints[i].EnumName << ": BuiltinName = \"" 545 << Ints[i].GCCBuiltinName << "\"; break;\n"; 546 } 547 } 548 OS << " }\n"; 549 OS << "#endif\n\n"; 550 } 551 552 /// EmitBuiltinComparisons - Emit comparisons to determine whether the specified 553 /// sorted range of builtin names is equal to the current builtin. This breaks 554 /// it down into a simple tree. 555 /// 556 /// At this point, we know that all the builtins in the range have the same name 557 /// for the first 'CharStart' characters. Only the end of the name needs to be 558 /// discriminated. 559 typedef std::map<std::string, std::string>::const_iterator StrMapIterator; 560 static void EmitBuiltinComparisons(StrMapIterator Start, StrMapIterator End, 561 unsigned CharStart, unsigned Indent, 562 std::string TargetPrefix, std::ostream &OS) { 563 if (Start == End) return; // empty range. 564 565 // Determine what, if anything, is the same about all these strings. 566 std::string CommonString = Start->first; 567 unsigned NumInRange = 0; 568 for (StrMapIterator I = Start; I != End; ++I, ++NumInRange) { 569 // Find the first character that doesn't match. 570 const std::string &ThisStr = I->first; 571 unsigned NonMatchChar = CharStart; 572 while (NonMatchChar < CommonString.size() && 573 NonMatchChar < ThisStr.size() && 574 CommonString[NonMatchChar] == ThisStr[NonMatchChar]) 575 ++NonMatchChar; 576 // Truncate off pieces that don't match. 577 CommonString.resize(NonMatchChar); 578 } 579 580 // Just compare the rest of the string. 581 if (NumInRange == 1) { 582 if (CharStart != CommonString.size()) { 583 OS << std::string(Indent*2, ' ') << "if (!memcmp(BuiltinName"; 584 if (CharStart) OS << "+" << CharStart; 585 OS << ", \"" << (CommonString.c_str()+CharStart) << "\", "; 586 OS << CommonString.size() - CharStart << "))\n"; 587 ++Indent; 588 } 589 OS << std::string(Indent*2, ' ') << "IntrinsicID = " << TargetPrefix 590 << "Intrinsic::"; 591 OS << Start->second << ";\n"; 592 return; 593 } 594 595 // At this point, we potentially have a common prefix for these builtins, emit 596 // a check for this common prefix. 597 if (CommonString.size() != CharStart) { 598 OS << std::string(Indent*2, ' ') << "if (!memcmp(BuiltinName"; 599 if (CharStart) OS << "+" << CharStart; 600 OS << ", \"" << (CommonString.c_str()+CharStart) << "\", "; 601 OS << CommonString.size()-CharStart << ")) {\n"; 602 603 EmitBuiltinComparisons(Start, End, CommonString.size(), Indent+1, 604 TargetPrefix, OS); 605 OS << std::string(Indent*2, ' ') << "}\n"; 606 return; 607 } 608 609 // Output a switch on the character that differs across the set. 610 OS << std::string(Indent*2, ' ') << "switch (BuiltinName[" << CharStart 611 << "]) {"; 612 if (CharStart) 613 OS << " // \"" << std::string(Start->first.begin(), 614 Start->first.begin()+CharStart) << "\""; 615 OS << "\n"; 616 617 for (StrMapIterator I = Start; I != End; ) { 618 char ThisChar = I->first[CharStart]; 619 OS << std::string(Indent*2, ' ') << "case '" << ThisChar << "':\n"; 620 // Figure out the range that has this common character. 621 StrMapIterator NextChar = I; 622 for (++NextChar; NextChar != End && NextChar->first[CharStart] == ThisChar; 623 ++NextChar) 624 /*empty*/; 625 EmitBuiltinComparisons(I, NextChar, CharStart+1, Indent+1, TargetPrefix,OS); 626 OS << std::string(Indent*2, ' ') << " break;\n"; 627 I = NextChar; 628 } 629 OS << std::string(Indent*2, ' ') << "}\n"; 630 } 631 632 /// EmitTargetBuiltins - All of the builtins in the specified map are for the 633 /// same target, and we already checked it. 634 static void EmitTargetBuiltins(const std::map<std::string, std::string> &BIM, 635 const std::string &TargetPrefix, 636 std::ostream &OS) { 637 // Rearrange the builtins by length. 638 std::vector<std::map<std::string, std::string> > BuiltinsByLen; 639 BuiltinsByLen.reserve(100); 640 641 for (StrMapIterator I = BIM.begin(), E = BIM.end(); I != E; ++I) { 642 if (I->first.size() >= BuiltinsByLen.size()) 643 BuiltinsByLen.resize(I->first.size()+1); 644 BuiltinsByLen[I->first.size()].insert(*I); 645 } 646 647 // Now that we have all the builtins by their length, emit a switch stmt. 648 OS << " switch (strlen(BuiltinName)) {\n"; 649 OS << " default: break;\n"; 650 for (unsigned i = 0, e = BuiltinsByLen.size(); i != e; ++i) { 651 if (BuiltinsByLen[i].empty()) continue; 652 OS << " case " << i << ":\n"; 653 EmitBuiltinComparisons(BuiltinsByLen[i].begin(), BuiltinsByLen[i].end(), 654 0, 3, TargetPrefix, OS); 655 OS << " break;\n"; 656 } 657 OS << " }\n"; 658 } 659 660 661 void IntrinsicEmitter:: 662 EmitIntrinsicToGCCBuiltinMap(const std::vector<CodeGenIntrinsic> &Ints, 663 std::ostream &OS) { 664 typedef std::map<std::string, std::map<std::string, std::string> > BIMTy; 665 BIMTy BuiltinMap; 666 for (unsigned i = 0, e = Ints.size(); i != e; ++i) { 667 if (!Ints[i].GCCBuiltinName.empty()) { 668 // Get the map for this target prefix. 669 std::map<std::string, std::string> &BIM =BuiltinMap[Ints[i].TargetPrefix]; 670 671 if (!BIM.insert(std::make_pair(Ints[i].GCCBuiltinName, 672 Ints[i].EnumName)).second) 673 throw "Intrinsic '" + Ints[i].TheDef->getName() + 674 "': duplicate GCC builtin name!"; 675 } 676 } 677 678 OS << "// Get the LLVM intrinsic that corresponds to a GCC builtin.\n"; 679 OS << "// This is used by the C front-end. The GCC builtin name is passed\n"; 680 OS << "// in as BuiltinName, and a target prefix (e.g. 'ppc') is passed\n"; 681 OS << "// in as TargetPrefix. The result is assigned to 'IntrinsicID'.\n"; 682 OS << "#ifdef GET_LLVM_INTRINSIC_FOR_GCC_BUILTIN\n"; 683 684 if (TargetOnly) { 685 OS << "static " << TargetPrefix << "Intrinsic::ID " 686 << "getIntrinsicForGCCBuiltin(const char " 687 << "*TargetPrefix, const char *BuiltinName) {\n"; 688 OS << " " << TargetPrefix << "Intrinsic::ID IntrinsicID = "; 689 } else { 690 OS << "Intrinsic::ID Intrinsic::getIntrinsicForGCCBuiltin(const char " 691 << "*TargetPrefix, const char *BuiltinName) {\n"; 692 OS << " Intrinsic::ID IntrinsicID = "; 693 } 694 695 if (TargetOnly) 696 OS << "(" << TargetPrefix<< "Intrinsic::ID)"; 697 698 OS << "Intrinsic::not_intrinsic;\n"; 699 700 // Note: this could emit significantly better code if we cared. 701 for (BIMTy::iterator I = BuiltinMap.begin(), E = BuiltinMap.end();I != E;++I){ 702 OS << " "; 703 if (!I->first.empty()) 704 OS << "if (!strcmp(TargetPrefix, \"" << I->first << "\")) "; 705 else 706 OS << "/* Target Independent Builtins */ "; 707 OS << "{\n"; 708 709 // Emit the comparisons for this target prefix. 710 EmitTargetBuiltins(I->second, TargetPrefix, OS); 711 OS << " }\n"; 712 } 713 OS << " return IntrinsicID;\n"; 714 OS << "}\n"; 715 OS << "#endif\n\n"; 716 } 717