IntrinsicEmitter.cpp revision 93dc92e412fd06250e46951bffb6040eca9baebd
19e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner//===- IntrinsicEmitter.cpp - Generate intrinsic information --------------===//
29e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner//
39e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner//                     The LLVM Compiler Infrastructure
49e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner//
53060910e290949a9ac5eda8726d030790c4d60ffChris Lattner// This file is distributed under the University of Illinois Open Source
63060910e290949a9ac5eda8726d030790c4d60ffChris Lattner// License. See LICENSE.TXT for details.
79e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner//
89e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner//===----------------------------------------------------------------------===//
99e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner//
109e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner// This tablegen backend emits information about intrinsic functions.
119e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner//
129e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner//===----------------------------------------------------------------------===//
139e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner
146994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth#include "CodeGenTarget.h"
159e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner#include "IntrinsicEmitter.h"
169e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner#include "Record.h"
1718faf5d9f7f89130b9e3304965b81e1c70ebb75cChris Lattner#include "llvm/ADT/StringExtras.h"
1871c3bc3d966bd874f760abf055c559673f925029Jeff Cohen#include <algorithm>
199e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattnerusing namespace llvm;
209e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner
219e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner//===----------------------------------------------------------------------===//
229e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner// IntrinsicEmitter Implementation
239e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner//===----------------------------------------------------------------------===//
249e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner
251a55180238dbcf11113f610aea010447e51f595bDaniel Dunbarvoid IntrinsicEmitter::run(raw_ostream &OS) {
269e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner  EmitSourceFileHeader("Intrinsic Function Source Fragment", OS);
279e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner
2849de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen  std::vector<CodeGenIntrinsic> Ints = LoadIntrinsics(Records, TargetOnly);
2949de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen
3049de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen  if (TargetOnly && !Ints.empty())
3149de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen    TargetPrefix = Ints[0].TargetPrefix;
329e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner
339e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner  // Emit the enum information.
349e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner  EmitEnumInfo(Ints, OS);
35fda6affb95e9f68278cb5cf75dc3fd3406978255Chris Lattner
36fda6affb95e9f68278cb5cf75dc3fd3406978255Chris Lattner  // Emit the intrinsic ID -> name table.
37fda6affb95e9f68278cb5cf75dc3fd3406978255Chris Lattner  EmitIntrinsicToNameTable(Ints, OS);
380d52ff1f7b993750a74a5d4432273092de9af069Mon P Wang
390d52ff1f7b993750a74a5d4432273092de9af069Mon P Wang  // Emit the intrinsic ID -> overload table.
400d52ff1f7b993750a74a5d4432273092de9af069Mon P Wang  EmitIntrinsicToOverloadTable(Ints, OS);
410d52ff1f7b993750a74a5d4432273092de9af069Mon P Wang
429b843b249462980ae4630dc37d1bcccde884a5a7Chris Lattner  // Emit the function name recognizer.
439b843b249462980ae4630dc37d1bcccde884a5a7Chris Lattner  EmitFnNameRecognizer(Ints, OS);
44fda6affb95e9f68278cb5cf75dc3fd3406978255Chris Lattner
45f97a00e681c7a526d49759d0d1b9d327cbf6c04aChris Lattner  // Emit the intrinsic verifier.
46f97a00e681c7a526d49759d0d1b9d327cbf6c04aChris Lattner  EmitVerifier(Ints, OS);
476448ee44c6f232f215d5d9f145a0d71a983c4a3fChris Lattner
4895af592a631f403e1458ec1155f89fc31011572cJim Laskey  // Emit the intrinsic declaration generator.
4995af592a631f403e1458ec1155f89fc31011572cJim Laskey  EmitGenerator(Ints, OS);
5095af592a631f403e1458ec1155f89fc31011572cJim Laskey
51a3355ffb3d30d19d226bbb75707991c60f236e37Duncan Sands  // Emit the intrinsic parameter attributes.
52a3355ffb3d30d19d226bbb75707991c60f236e37Duncan Sands  EmitAttributes(Ints, OS);
53022f64fbbc4669623e79b805379266fed519017dChris Lattner
54d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands  // Emit intrinsic alias analysis mod/ref behavior.
55d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands  EmitModRefBehavior(Ints, OS);
56d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands
57022f64fbbc4669623e79b805379266fed519017dChris Lattner  // Emit a list of intrinsics with corresponding GCC builtins.
58022f64fbbc4669623e79b805379266fed519017dChris Lattner  EmitGCCBuiltinList(Ints, OS);
593f8b8913bc9cb232871445eefa8654caf7f9986fChris Lattner
603f8b8913bc9cb232871445eefa8654caf7f9986fChris Lattner  // Emit code to translate GCC builtins into LLVM intrinsics.
613f8b8913bc9cb232871445eefa8654caf7f9986fChris Lattner  EmitIntrinsicToGCCBuiltinMap(Ints, OS);
629e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner}
639e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner
649e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattnervoid IntrinsicEmitter::EmitEnumInfo(const std::vector<CodeGenIntrinsic> &Ints,
651a55180238dbcf11113f610aea010447e51f595bDaniel Dunbar                                    raw_ostream &OS) {
669b843b249462980ae4630dc37d1bcccde884a5a7Chris Lattner  OS << "// Enum values for Intrinsics.h\n";
679e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner  OS << "#ifdef GET_INTRINSIC_ENUM_VALUES\n";
689e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner  for (unsigned i = 0, e = Ints.size(); i != e; ++i) {
699e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner    OS << "    " << Ints[i].EnumName;
709e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner    OS << ((i != e-1) ? ", " : "  ");
719e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner    OS << std::string(40-Ints[i].EnumName.size(), ' ')
729e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner      << "// " << Ints[i].Name << "\n";
739e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner  }
749e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner  OS << "#endif\n\n";
759e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner}
769b843b249462980ae4630dc37d1bcccde884a5a7Chris Lattner
779b843b249462980ae4630dc37d1bcccde884a5a7Chris Lattnervoid IntrinsicEmitter::
789b843b249462980ae4630dc37d1bcccde884a5a7Chris LattnerEmitFnNameRecognizer(const std::vector<CodeGenIntrinsic> &Ints,
791a55180238dbcf11113f610aea010447e51f595bDaniel Dunbar                     raw_ostream &OS) {
809b843b249462980ae4630dc37d1bcccde884a5a7Chris Lattner  // Build a function name -> intrinsic name mapping.
81c4de3dec62c3f60ae7297f93c19c799c403c2e9fReid Spencer  std::map<std::string, unsigned> IntMapping;
829b843b249462980ae4630dc37d1bcccde884a5a7Chris Lattner  for (unsigned i = 0, e = Ints.size(); i != e; ++i)
83c4de3dec62c3f60ae7297f93c19c799c403c2e9fReid Spencer    IntMapping[Ints[i].Name] = i;
849b843b249462980ae4630dc37d1bcccde884a5a7Chris Lattner
859b843b249462980ae4630dc37d1bcccde884a5a7Chris Lattner  OS << "// Function name -> enum value recognizer code.\n";
869b843b249462980ae4630dc37d1bcccde884a5a7Chris Lattner  OS << "#ifdef GET_FUNCTION_RECOGNIZER\n";
879b843b249462980ae4630dc37d1bcccde884a5a7Chris Lattner  OS << "  switch (Name[5]) {\n";
883b515802f652b16b05c9a8f344d219a0739b36a3Chris Lattner  OS << "  default:\n";
899b843b249462980ae4630dc37d1bcccde884a5a7Chris Lattner  // Emit the intrinsics in sorted order.
909b843b249462980ae4630dc37d1bcccde884a5a7Chris Lattner  char LastChar = 0;
91c4de3dec62c3f60ae7297f93c19c799c403c2e9fReid Spencer  for (std::map<std::string, unsigned>::iterator I = IntMapping.begin(),
929b843b249462980ae4630dc37d1bcccde884a5a7Chris Lattner       E = IntMapping.end(); I != E; ++I) {
939b843b249462980ae4630dc37d1bcccde884a5a7Chris Lattner    if (I->first[5] != LastChar) {
949b843b249462980ae4630dc37d1bcccde884a5a7Chris Lattner      LastChar = I->first[5];
953b515802f652b16b05c9a8f344d219a0739b36a3Chris Lattner      OS << "    break;\n";
969b843b249462980ae4630dc37d1bcccde884a5a7Chris Lattner      OS << "  case '" << LastChar << "':\n";
979b843b249462980ae4630dc37d1bcccde884a5a7Chris Lattner    }
989b843b249462980ae4630dc37d1bcccde884a5a7Chris Lattner
99c4de3dec62c3f60ae7297f93c19c799c403c2e9fReid Spencer    // For overloaded intrinsics, only the prefix needs to match
100c4de3dec62c3f60ae7297f93c19c799c403c2e9fReid Spencer    if (Ints[I->second].isOverloaded)
1016994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth      OS << "    if (Len > " << I->first.size()
1026994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth       << " && !memcmp(Name, \"" << I->first << ".\", "
10349de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen       << (I->first.size() + 1) << ")) return " << TargetPrefix << "Intrinsic::"
1046994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth       << Ints[I->second].EnumName << ";\n";
105c4de3dec62c3f60ae7297f93c19c799c403c2e9fReid Spencer    else
106c4de3dec62c3f60ae7297f93c19c799c403c2e9fReid Spencer      OS << "    if (Len == " << I->first.size()
1076994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth         << " && !memcmp(Name, \"" << I->first << "\", "
10849de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen         << I->first.size() << ")) return " << TargetPrefix << "Intrinsic::"
109c4de3dec62c3f60ae7297f93c19c799c403c2e9fReid Spencer         << Ints[I->second].EnumName << ";\n";
1109b843b249462980ae4630dc37d1bcccde884a5a7Chris Lattner  }
1119b843b249462980ae4630dc37d1bcccde884a5a7Chris Lattner  OS << "  }\n";
112f97a00e681c7a526d49759d0d1b9d327cbf6c04aChris Lattner  OS << "#endif\n\n";
113f97a00e681c7a526d49759d0d1b9d327cbf6c04aChris Lattner}
114f97a00e681c7a526d49759d0d1b9d327cbf6c04aChris Lattner
115fda6affb95e9f68278cb5cf75dc3fd3406978255Chris Lattnervoid IntrinsicEmitter::
116fda6affb95e9f68278cb5cf75dc3fd3406978255Chris LattnerEmitIntrinsicToNameTable(const std::vector<CodeGenIntrinsic> &Ints,
1171a55180238dbcf11113f610aea010447e51f595bDaniel Dunbar                         raw_ostream &OS) {
118fda6affb95e9f68278cb5cf75dc3fd3406978255Chris Lattner  OS << "// Intrinsic ID to name table\n";
119fda6affb95e9f68278cb5cf75dc3fd3406978255Chris Lattner  OS << "#ifdef GET_INTRINSIC_NAME_TABLE\n";
120fda6affb95e9f68278cb5cf75dc3fd3406978255Chris Lattner  OS << "  // Note that entry #0 is the invalid intrinsic!\n";
121f065a6f711dca09ba36ec8fd3556c4936cdbe621Evan Cheng  for (unsigned i = 0, e = Ints.size(); i != e; ++i)
122f065a6f711dca09ba36ec8fd3556c4936cdbe621Evan Cheng    OS << "  \"" << Ints[i].Name << "\",\n";
123fda6affb95e9f68278cb5cf75dc3fd3406978255Chris Lattner  OS << "#endif\n\n";
124fda6affb95e9f68278cb5cf75dc3fd3406978255Chris Lattner}
125fda6affb95e9f68278cb5cf75dc3fd3406978255Chris Lattner
1260d52ff1f7b993750a74a5d4432273092de9af069Mon P Wangvoid IntrinsicEmitter::
1270d52ff1f7b993750a74a5d4432273092de9af069Mon P WangEmitIntrinsicToOverloadTable(const std::vector<CodeGenIntrinsic> &Ints,
1281a55180238dbcf11113f610aea010447e51f595bDaniel Dunbar                         raw_ostream &OS) {
1290d52ff1f7b993750a74a5d4432273092de9af069Mon P Wang  OS << "// Intrinsic ID to overload table\n";
1300d52ff1f7b993750a74a5d4432273092de9af069Mon P Wang  OS << "#ifdef GET_INTRINSIC_OVERLOAD_TABLE\n";
1310d52ff1f7b993750a74a5d4432273092de9af069Mon P Wang  OS << "  // Note that entry #0 is the invalid intrinsic!\n";
1320d52ff1f7b993750a74a5d4432273092de9af069Mon P Wang  for (unsigned i = 0, e = Ints.size(); i != e; ++i) {
1330d52ff1f7b993750a74a5d4432273092de9af069Mon P Wang    OS << "  ";
1340d52ff1f7b993750a74a5d4432273092de9af069Mon P Wang    if (Ints[i].isOverloaded)
1350d52ff1f7b993750a74a5d4432273092de9af069Mon P Wang      OS << "true";
1360d52ff1f7b993750a74a5d4432273092de9af069Mon P Wang    else
1370d52ff1f7b993750a74a5d4432273092de9af069Mon P Wang      OS << "false";
1380d52ff1f7b993750a74a5d4432273092de9af069Mon P Wang    OS << ",\n";
1390d52ff1f7b993750a74a5d4432273092de9af069Mon P Wang  }
1400d52ff1f7b993750a74a5d4432273092de9af069Mon P Wang  OS << "#endif\n\n";
1410d52ff1f7b993750a74a5d4432273092de9af069Mon P Wang}
1420d52ff1f7b993750a74a5d4432273092de9af069Mon P Wang
143825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Andersonstatic void EmitTypeForValueType(raw_ostream &OS, MVT::SimpleValueType VT) {
144e50ed30282bb5b4a9ed952580523f2dda16215acOwen Anderson  if (EVT(VT).isInteger()) {
145e50ed30282bb5b4a9ed952580523f2dda16215acOwen Anderson    unsigned BitWidth = EVT(VT).getSizeInBits();
1461d0be15f89cb5056e20e2d24faa8d6afb1573bcaOwen Anderson    OS << "IntegerType::get(Context, " << BitWidth << ")";
147825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson  } else if (VT == MVT::Other) {
148825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson    // MVT::OtherVT is used to mean the empty struct type here.
149d7f2a6cb3fbc012763adb42fd967f6fefbb22a37Owen Anderson    OS << "StructType::get(Context)";
150825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson  } else if (VT == MVT::f32) {
1511d0be15f89cb5056e20e2d24faa8d6afb1573bcaOwen Anderson    OS << "Type::getFloatTy(Context)";
152825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson  } else if (VT == MVT::f64) {
1531d0be15f89cb5056e20e2d24faa8d6afb1573bcaOwen Anderson    OS << "Type::getDoubleTy(Context)";
154825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson  } else if (VT == MVT::f80) {
1551d0be15f89cb5056e20e2d24faa8d6afb1573bcaOwen Anderson    OS << "Type::getX86_FP80Ty(Context)";
156825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson  } else if (VT == MVT::f128) {
1571d0be15f89cb5056e20e2d24faa8d6afb1573bcaOwen Anderson    OS << "Type::getFP128Ty(Context)";
158825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson  } else if (VT == MVT::ppcf128) {
1591d0be15f89cb5056e20e2d24faa8d6afb1573bcaOwen Anderson    OS << "Type::getPPC_FP128Ty(Context)";
160825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson  } else if (VT == MVT::isVoid) {
1611d0be15f89cb5056e20e2d24faa8d6afb1573bcaOwen Anderson    OS << "Type::getVoidTy(Context)";
162825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson  } else if (VT == MVT::Metadata) {
1631d0be15f89cb5056e20e2d24faa8d6afb1573bcaOwen Anderson    OS << "Type::getMetadataTy(Context)";
1646994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth  } else {
1656994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth    assert(false && "Unsupported ValueType!");
16618faf5d9f7f89130b9e3304965b81e1c70ebb75cChris Lattner  }
16718faf5d9f7f89130b9e3304965b81e1c70ebb75cChris Lattner}
16818faf5d9f7f89130b9e3304965b81e1c70ebb75cChris Lattner
1691a55180238dbcf11113f610aea010447e51f595bDaniel Dunbarstatic void EmitTypeGenerate(raw_ostream &OS, const Record *ArgType,
170cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling                             unsigned &ArgNo);
171cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling
1721a55180238dbcf11113f610aea010447e51f595bDaniel Dunbarstatic void EmitTypeGenerate(raw_ostream &OS,
173cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling                             const std::vector<Record*> &ArgTypes,
174cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling                             unsigned &ArgNo) {
17593dc92e412fd06250e46951bffb6040eca9baebdChris Lattner  if (ArgTypes.empty())
17693dc92e412fd06250e46951bffb6040eca9baebdChris Lattner    return EmitTypeForValueType(OS, MVT::isVoid);
17793dc92e412fd06250e46951bffb6040eca9baebdChris Lattner
17893dc92e412fd06250e46951bffb6040eca9baebdChris Lattner  if (ArgTypes.size() == 1)
17993dc92e412fd06250e46951bffb6040eca9baebdChris Lattner    return EmitTypeGenerate(OS, ArgTypes.front(), ArgNo);
180cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling
181d7f2a6cb3fbc012763adb42fd967f6fefbb22a37Owen Anderson  OS << "StructType::get(Context, ";
182cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling
183cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling  for (std::vector<Record*>::const_iterator
18420072af3b0b22d90afbce769409f4ed822520366Bill Wendling         I = ArgTypes.begin(), E = ArgTypes.end(); I != E; ++I) {
185cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling    EmitTypeGenerate(OS, *I, ArgNo);
18620072af3b0b22d90afbce769409f4ed822520366Bill Wendling    OS << ", ";
18720072af3b0b22d90afbce769409f4ed822520366Bill Wendling  }
188cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling
18920072af3b0b22d90afbce769409f4ed822520366Bill Wendling  OS << " NULL)";
190cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling}
191cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling
1921a55180238dbcf11113f610aea010447e51f595bDaniel Dunbarstatic void EmitTypeGenerate(raw_ostream &OS, const Record *ArgType,
19384c614d1ac671b1a5524169f20028f51c30be728Reid Spencer                             unsigned &ArgNo) {
194825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson  MVT::SimpleValueType VT = getValueType(ArgType->getValueAsDef("VT"));
1956994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth
1966994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth  if (ArgType->isSubClassOf("LLVMMatchType")) {
1976994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth    unsigned Number = ArgType->getValueAsInt("Number");
1986994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth    assert(Number < ArgNo && "Invalid matching number!");
199bc03979536a1ecb220f1330719f3e3973a81ab0bBob Wilson    if (ArgType->isSubClassOf("LLVMExtendedElementVectorType"))
200bc03979536a1ecb220f1330719f3e3973a81ab0bBob Wilson      OS << "VectorType::getExtendedElementVectorType"
201bc03979536a1ecb220f1330719f3e3973a81ab0bBob Wilson         << "(dyn_cast<VectorType>(Tys[" << Number << "]))";
202bc03979536a1ecb220f1330719f3e3973a81ab0bBob Wilson    else if (ArgType->isSubClassOf("LLVMTruncatedElementVectorType"))
203bc03979536a1ecb220f1330719f3e3973a81ab0bBob Wilson      OS << "VectorType::getTruncatedElementVectorType"
204bc03979536a1ecb220f1330719f3e3973a81ab0bBob Wilson         << "(dyn_cast<VectorType>(Tys[" << Number << "]))";
205bc03979536a1ecb220f1330719f3e3973a81ab0bBob Wilson    else
206bc03979536a1ecb220f1330719f3e3973a81ab0bBob Wilson      OS << "Tys[" << Number << "]";
207825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson  } else if (VT == MVT::iAny || VT == MVT::fAny || VT == MVT::vAny) {
20884c614d1ac671b1a5524169f20028f51c30be728Reid Spencer    // NOTE: The ArgNo variable here is not the absolute argument number, it is
20984c614d1ac671b1a5524169f20028f51c30be728Reid Spencer    // the index of the "arbitrary" type in the Tys array passed to the
21084c614d1ac671b1a5524169f20028f51c30be728Reid Spencer    // Intrinsic::getDeclaration function. Consequently, we only want to
2116994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth    // increment it when we actually hit an overloaded type. Getting this wrong
2126994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth    // leads to very subtle bugs!
2136994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth    OS << "Tys[" << ArgNo++ << "]";
214e50ed30282bb5b4a9ed952580523f2dda16215acOwen Anderson  } else if (EVT(VT).isVector()) {
215e50ed30282bb5b4a9ed952580523f2dda16215acOwen Anderson    EVT VVT = VT;
2169d6565a5b1fbc4286d6ee638d8f47a3171a9ed7eReid Spencer    OS << "VectorType::get(";
217825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson    EmitTypeForValueType(OS, VVT.getVectorElementType().getSimpleVT().SimpleTy);
21883ec4b6711980242ef3c55a4fa36b2d7a39c1bfbDuncan Sands    OS << ", " << VVT.getVectorNumElements() << ")";
219825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson  } else if (VT == MVT::iPTR) {
22043ad6b3e0d6ada51e9b23aab3e061187f1f5710cChristopher Lamb    OS << "PointerType::getUnqual(";
221c4de3dec62c3f60ae7297f93c19c799c403c2e9fReid Spencer    EmitTypeGenerate(OS, ArgType->getValueAsDef("ElTy"), ArgNo);
22295af592a631f403e1458ec1155f89fc31011572cJim Laskey    OS << ")";
223825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson  } else if (VT == MVT::iPTRAny) {
224e3b3a7241c01f26613694e53b26b01abf764ddfcMon P Wang    // Make sure the user has passed us an argument type to overload. If not,
225e3b3a7241c01f26613694e53b26b01abf764ddfcMon P Wang    // treat it as an ordinary (not overloaded) intrinsic.
226e3b3a7241c01f26613694e53b26b01abf764ddfcMon P Wang    OS << "(" << ArgNo << " < numTys) ? Tys[" << ArgNo
227e3b3a7241c01f26613694e53b26b01abf764ddfcMon P Wang    << "] : PointerType::getUnqual(";
228e3b3a7241c01f26613694e53b26b01abf764ddfcMon P Wang    EmitTypeGenerate(OS, ArgType->getValueAsDef("ElTy"), ArgNo);
229e3b3a7241c01f26613694e53b26b01abf764ddfcMon P Wang    OS << ")";
230e3b3a7241c01f26613694e53b26b01abf764ddfcMon P Wang    ++ArgNo;
231825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson  } else if (VT == MVT::isVoid) {
2326994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth    if (ArgNo == 0)
2331d0be15f89cb5056e20e2d24faa8d6afb1573bcaOwen Anderson      OS << "Type::getVoidTy(Context)";
2346994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth    else
235825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson      // MVT::isVoid is used to mean varargs here.
2366994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth      OS << "...";
23795af592a631f403e1458ec1155f89fc31011572cJim Laskey  } else {
2386994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth    EmitTypeForValueType(OS, VT);
23995af592a631f403e1458ec1155f89fc31011572cJim Laskey  }
24095af592a631f403e1458ec1155f89fc31011572cJim Laskey}
24195af592a631f403e1458ec1155f89fc31011572cJim Laskey
242da4231f134989af7dc6bd3408821ba573def27b2Jim Grosbach/// RecordListComparator - Provide a deterministic comparator for lists of
243c4d9b240b157efa9301d451ac44c12f6b004db8fChris Lattner/// records.
244c4d9b240b157efa9301d451ac44c12f6b004db8fChris Lattnernamespace {
245cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling  typedef std::pair<std::vector<Record*>, std::vector<Record*> > RecPair;
246c4d9b240b157efa9301d451ac44c12f6b004db8fChris Lattner  struct RecordListComparator {
247cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling    bool operator()(const RecPair &LHS,
248cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling                    const RecPair &RHS) const {
249c4d9b240b157efa9301d451ac44c12f6b004db8fChris Lattner      unsigned i = 0;
250cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling      const std::vector<Record*> *LHSVec = &LHS.first;
251cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling      const std::vector<Record*> *RHSVec = &RHS.first;
252cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling      unsigned RHSSize = RHSVec->size();
253cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling      unsigned LHSSize = LHSVec->size();
254cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling
25593dc92e412fd06250e46951bffb6040eca9baebdChris Lattner      for (; i != LHSSize; ++i) {
256cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling        if (i == RHSSize) return false;  // RHS is shorter than LHS.
257cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling        if ((*LHSVec)[i] != (*RHSVec)[i])
258cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling          return (*LHSVec)[i]->getName() < (*RHSVec)[i]->getName();
25993dc92e412fd06250e46951bffb6040eca9baebdChris Lattner      }
260cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling
261023422a6eb9ea692a5a837dc1daf256ac75ac6b0Bill Wendling      if (i != RHSSize) return true;
262cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling
263cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling      i = 0;
264cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling      LHSVec = &LHS.second;
265cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling      RHSVec = &RHS.second;
266cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling      RHSSize = RHSVec->size();
267cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling      LHSSize = LHSVec->size();
268cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling
269cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling      for (i = 0; i != LHSSize; ++i) {
270cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling        if (i == RHSSize) return false;  // RHS is shorter than LHS.
271cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling        if ((*LHSVec)[i] != (*RHSVec)[i])
272cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling          return (*LHSVec)[i]->getName() < (*RHSVec)[i]->getName();
273cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling      }
274cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling
275cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling      return i != RHSSize;
276c4d9b240b157efa9301d451ac44c12f6b004db8fChris Lattner    }
277c4d9b240b157efa9301d451ac44c12f6b004db8fChris Lattner  };
278c4d9b240b157efa9301d451ac44c12f6b004db8fChris Lattner}
279c4d9b240b157efa9301d451ac44c12f6b004db8fChris Lattner
280f97a00e681c7a526d49759d0d1b9d327cbf6c04aChris Lattnervoid IntrinsicEmitter::EmitVerifier(const std::vector<CodeGenIntrinsic> &Ints,
2811a55180238dbcf11113f610aea010447e51f595bDaniel Dunbar                                    raw_ostream &OS) {
282f97a00e681c7a526d49759d0d1b9d327cbf6c04aChris Lattner  OS << "// Verifier::visitIntrinsicFunctionCall code.\n";
283f97a00e681c7a526d49759d0d1b9d327cbf6c04aChris Lattner  OS << "#ifdef GET_INTRINSIC_VERIFIER\n";
284f97a00e681c7a526d49759d0d1b9d327cbf6c04aChris Lattner  OS << "  switch (ID) {\n";
285f97a00e681c7a526d49759d0d1b9d327cbf6c04aChris Lattner  OS << "  default: assert(0 && \"Invalid intrinsic!\");\n";
286c4d9b240b157efa9301d451ac44c12f6b004db8fChris Lattner
287c4d9b240b157efa9301d451ac44c12f6b004db8fChris Lattner  // This checking can emit a lot of very common code.  To reduce the amount of
288c4d9b240b157efa9301d451ac44c12f6b004db8fChris Lattner  // code that we emit, batch up cases that have identical types.  This avoids
289c4d9b240b157efa9301d451ac44c12f6b004db8fChris Lattner  // problems where GCC can run out of memory compiling Verifier.cpp.
290cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling  typedef std::map<RecPair, std::vector<unsigned>, RecordListComparator> MapTy;
291c4d9b240b157efa9301d451ac44c12f6b004db8fChris Lattner  MapTy UniqueArgInfos;
292c4d9b240b157efa9301d451ac44c12f6b004db8fChris Lattner
293c4d9b240b157efa9301d451ac44c12f6b004db8fChris Lattner  // Compute the unique argument type info.
294c4d9b240b157efa9301d451ac44c12f6b004db8fChris Lattner  for (unsigned i = 0, e = Ints.size(); i != e; ++i)
295cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling    UniqueArgInfos[make_pair(Ints[i].IS.RetTypeDefs,
296cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling                             Ints[i].IS.ParamTypeDefs)].push_back(i);
297c4d9b240b157efa9301d451ac44c12f6b004db8fChris Lattner
298c4d9b240b157efa9301d451ac44c12f6b004db8fChris Lattner  // Loop through the array, emitting one comparison for each batch.
299c4d9b240b157efa9301d451ac44c12f6b004db8fChris Lattner  for (MapTy::iterator I = UniqueArgInfos.begin(),
300c4d9b240b157efa9301d451ac44c12f6b004db8fChris Lattner       E = UniqueArgInfos.end(); I != E; ++I) {
301cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling    for (unsigned i = 0, e = I->second.size(); i != e; ++i)
302c4d9b240b157efa9301d451ac44c12f6b004db8fChris Lattner      OS << "  case Intrinsic::" << Ints[I->second[i]].EnumName << ":\t\t// "
303c4d9b240b157efa9301d451ac44c12f6b004db8fChris Lattner         << Ints[I->second[i]].Name << "\n";
304f124b46b4f18b1a8f054a1222324ae15079f6ed8Chris Lattner
305cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling    const RecPair &ArgTypes = I->first;
306cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling    const std::vector<Record*> &RetTys = ArgTypes.first;
307cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling    const std::vector<Record*> &ParamTys = ArgTypes.second;
30809b1366f3f310b5648aa8cd72ed16b9f19b4c68dBob Wilson    std::vector<unsigned> OverloadedTypeIndices;
309cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling
310cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling    OS << "    VerifyIntrinsicPrototype(ID, IF, " << RetTys.size() << ", "
311cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling       << ParamTys.size();
312cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling
313cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling    // Emit return types.
314cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling    for (unsigned j = 0, je = RetTys.size(); j != je; ++j) {
315cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling      Record *ArgType = RetTys[j];
316cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling      OS << ", ";
317cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling
3186994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth      if (ArgType->isSubClassOf("LLVMMatchType")) {
3196994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth        unsigned Number = ArgType->getValueAsInt("Number");
32009b1366f3f310b5648aa8cd72ed16b9f19b4c68dBob Wilson        assert(Number < OverloadedTypeIndices.size() &&
32109b1366f3f310b5648aa8cd72ed16b9f19b4c68dBob Wilson               "Invalid matching number!");
32209b1366f3f310b5648aa8cd72ed16b9f19b4c68dBob Wilson        Number = OverloadedTypeIndices[Number];
323bc03979536a1ecb220f1330719f3e3973a81ab0bBob Wilson        if (ArgType->isSubClassOf("LLVMExtendedElementVectorType"))
324bc03979536a1ecb220f1330719f3e3973a81ab0bBob Wilson          OS << "~(ExtendedElementVectorType | " << Number << ")";
325bc03979536a1ecb220f1330719f3e3973a81ab0bBob Wilson        else if (ArgType->isSubClassOf("LLVMTruncatedElementVectorType"))
326bc03979536a1ecb220f1330719f3e3973a81ab0bBob Wilson          OS << "~(TruncatedElementVectorType | " << Number << ")";
327bc03979536a1ecb220f1330719f3e3973a81ab0bBob Wilson        else
328bc03979536a1ecb220f1330719f3e3973a81ab0bBob Wilson          OS << "~" << Number;
3296994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth      } else {
330825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson        MVT::SimpleValueType VT = getValueType(ArgType->getValueAsDef("VT"));
3316994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth        OS << getEnumName(VT);
332cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling
33361fc4cf7aa0b87ceab62082cee8ef5ce3f574ffcBob Wilson        if (EVT(VT).isOverloaded())
33409b1366f3f310b5648aa8cd72ed16b9f19b4c68dBob Wilson          OverloadedTypeIndices.push_back(j);
33509b1366f3f310b5648aa8cd72ed16b9f19b4c68dBob Wilson
336825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson        if (VT == MVT::isVoid && j != 0 && j != je - 1)
337cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling          throw "Var arg type not last argument";
338cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling      }
339cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling    }
340cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling
341cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling    // Emit the parameter types.
342cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling    for (unsigned j = 0, je = ParamTys.size(); j != je; ++j) {
343cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling      Record *ArgType = ParamTys[j];
344cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling      OS << ", ";
345cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling
346cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling      if (ArgType->isSubClassOf("LLVMMatchType")) {
347cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling        unsigned Number = ArgType->getValueAsInt("Number");
34809b1366f3f310b5648aa8cd72ed16b9f19b4c68dBob Wilson        assert(Number < OverloadedTypeIndices.size() &&
34909b1366f3f310b5648aa8cd72ed16b9f19b4c68dBob Wilson               "Invalid matching number!");
35009b1366f3f310b5648aa8cd72ed16b9f19b4c68dBob Wilson        Number = OverloadedTypeIndices[Number];
351bc03979536a1ecb220f1330719f3e3973a81ab0bBob Wilson        if (ArgType->isSubClassOf("LLVMExtendedElementVectorType"))
352bc03979536a1ecb220f1330719f3e3973a81ab0bBob Wilson          OS << "~(ExtendedElementVectorType | " << Number << ")";
353bc03979536a1ecb220f1330719f3e3973a81ab0bBob Wilson        else if (ArgType->isSubClassOf("LLVMTruncatedElementVectorType"))
354bc03979536a1ecb220f1330719f3e3973a81ab0bBob Wilson          OS << "~(TruncatedElementVectorType | " << Number << ")";
355bc03979536a1ecb220f1330719f3e3973a81ab0bBob Wilson        else
356bc03979536a1ecb220f1330719f3e3973a81ab0bBob Wilson          OS << "~" << Number;
357cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling      } else {
358825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson        MVT::SimpleValueType VT = getValueType(ArgType->getValueAsDef("VT"));
359cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling        OS << getEnumName(VT);
360cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling
36161fc4cf7aa0b87ceab62082cee8ef5ce3f574ffcBob Wilson        if (EVT(VT).isOverloaded())
36209b1366f3f310b5648aa8cd72ed16b9f19b4c68dBob Wilson          OverloadedTypeIndices.push_back(j + RetTys.size());
36309b1366f3f310b5648aa8cd72ed16b9f19b4c68dBob Wilson
364825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson        if (VT == MVT::isVoid && j != 0 && j != je - 1)
36595d97b90e8427255c8298f5d3a1ab605af62aab4Jim Laskey          throw "Var arg type not last argument";
36695d97b90e8427255c8298f5d3a1ab605af62aab4Jim Laskey      }
36795d97b90e8427255c8298f5d3a1ab605af62aab4Jim Laskey    }
36895d97b90e8427255c8298f5d3a1ab605af62aab4Jim Laskey
3696994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth    OS << ");\n";
370f97a00e681c7a526d49759d0d1b9d327cbf6c04aChris Lattner    OS << "    break;\n";
371f97a00e681c7a526d49759d0d1b9d327cbf6c04aChris Lattner  }
372f97a00e681c7a526d49759d0d1b9d327cbf6c04aChris Lattner  OS << "  }\n";
373f97a00e681c7a526d49759d0d1b9d327cbf6c04aChris Lattner  OS << "#endif\n\n";
3749b843b249462980ae4630dc37d1bcccde884a5a7Chris Lattner}
3759b843b249462980ae4630dc37d1bcccde884a5a7Chris Lattner
37695af592a631f403e1458ec1155f89fc31011572cJim Laskeyvoid IntrinsicEmitter::EmitGenerator(const std::vector<CodeGenIntrinsic> &Ints,
3771a55180238dbcf11113f610aea010447e51f595bDaniel Dunbar                                     raw_ostream &OS) {
37895af592a631f403e1458ec1155f89fc31011572cJim Laskey  OS << "// Code for generating Intrinsic function declarations.\n";
37995af592a631f403e1458ec1155f89fc31011572cJim Laskey  OS << "#ifdef GET_INTRINSIC_GENERATOR\n";
38095af592a631f403e1458ec1155f89fc31011572cJim Laskey  OS << "  switch (id) {\n";
38195af592a631f403e1458ec1155f89fc31011572cJim Laskey  OS << "  default: assert(0 && \"Invalid intrinsic!\");\n";
38295af592a631f403e1458ec1155f89fc31011572cJim Laskey
38395af592a631f403e1458ec1155f89fc31011572cJim Laskey  // Similar to GET_INTRINSIC_VERIFIER, batch up cases that have identical
38495af592a631f403e1458ec1155f89fc31011572cJim Laskey  // types.
385cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling  typedef std::map<RecPair, std::vector<unsigned>, RecordListComparator> MapTy;
38695af592a631f403e1458ec1155f89fc31011572cJim Laskey  MapTy UniqueArgInfos;
38795af592a631f403e1458ec1155f89fc31011572cJim Laskey
38895af592a631f403e1458ec1155f89fc31011572cJim Laskey  // Compute the unique argument type info.
38995af592a631f403e1458ec1155f89fc31011572cJim Laskey  for (unsigned i = 0, e = Ints.size(); i != e; ++i)
390cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling    UniqueArgInfos[make_pair(Ints[i].IS.RetTypeDefs,
391cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling                             Ints[i].IS.ParamTypeDefs)].push_back(i);
39295af592a631f403e1458ec1155f89fc31011572cJim Laskey
39395af592a631f403e1458ec1155f89fc31011572cJim Laskey  // Loop through the array, emitting one generator for each batch.
39449de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen  std::string IntrinsicStr = TargetPrefix + "Intrinsic::";
39549de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen
39695af592a631f403e1458ec1155f89fc31011572cJim Laskey  for (MapTy::iterator I = UniqueArgInfos.begin(),
39795af592a631f403e1458ec1155f89fc31011572cJim Laskey       E = UniqueArgInfos.end(); I != E; ++I) {
398cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling    for (unsigned i = 0, e = I->second.size(); i != e; ++i)
39949de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen      OS << "  case " << IntrinsicStr << Ints[I->second[i]].EnumName
40049de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen         << ":\t\t// " << Ints[I->second[i]].Name << "\n";
40195af592a631f403e1458ec1155f89fc31011572cJim Laskey
402cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling    const RecPair &ArgTypes = I->first;
403cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling    const std::vector<Record*> &RetTys = ArgTypes.first;
404cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling    const std::vector<Record*> &ParamTys = ArgTypes.second;
405cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling
406cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling    unsigned N = ParamTys.size();
40795af592a631f403e1458ec1155f89fc31011572cJim Laskey
4086994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth    if (N > 1 &&
409825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson        getValueType(ParamTys[N - 1]->getValueAsDef("VT")) == MVT::isVoid) {
41095af592a631f403e1458ec1155f89fc31011572cJim Laskey      OS << "    IsVarArg = true;\n";
41195af592a631f403e1458ec1155f89fc31011572cJim Laskey      --N;
41295af592a631f403e1458ec1155f89fc31011572cJim Laskey    }
413cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling
41484c614d1ac671b1a5524169f20028f51c30be728Reid Spencer    unsigned ArgNo = 0;
41595af592a631f403e1458ec1155f89fc31011572cJim Laskey    OS << "    ResultTy = ";
416cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling    EmitTypeGenerate(OS, RetTys, ArgNo);
41795af592a631f403e1458ec1155f89fc31011572cJim Laskey    OS << ";\n";
41895af592a631f403e1458ec1155f89fc31011572cJim Laskey
419cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling    for (unsigned j = 0; j != N; ++j) {
42095af592a631f403e1458ec1155f89fc31011572cJim Laskey      OS << "    ArgTys.push_back(";
421cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling      EmitTypeGenerate(OS, ParamTys[j], ArgNo);
42295af592a631f403e1458ec1155f89fc31011572cJim Laskey      OS << ");\n";
42395af592a631f403e1458ec1155f89fc31011572cJim Laskey    }
424cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling
42595af592a631f403e1458ec1155f89fc31011572cJim Laskey    OS << "    break;\n";
42695af592a631f403e1458ec1155f89fc31011572cJim Laskey  }
427cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling
42895af592a631f403e1458ec1155f89fc31011572cJim Laskey  OS << "  }\n";
42995af592a631f403e1458ec1155f89fc31011572cJim Laskey  OS << "#endif\n\n";
43095af592a631f403e1458ec1155f89fc31011572cJim Laskey}
43195af592a631f403e1458ec1155f89fc31011572cJim Laskey
432048ffb239c282277959463c61200b86e2380cb84Chris Lattner/// EmitAttributes - This emits the Intrinsic::getAttributes method.
4334e5f35973c1bc56cce14d44c6f8f4ad1e9f1a438Chris Lattnervoid IntrinsicEmitter::
4341a55180238dbcf11113f610aea010447e51f595bDaniel DunbarEmitAttributes(const std::vector<CodeGenIntrinsic> &Ints, raw_ostream &OS) {
435a3355ffb3d30d19d226bbb75707991c60f236e37Duncan Sands  OS << "// Add parameter attributes that are not common to all intrinsics.\n";
436a3355ffb3d30d19d226bbb75707991c60f236e37Duncan Sands  OS << "#ifdef GET_INTRINSIC_ATTRIBUTES\n";
43749de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen  if (TargetOnly)
43849de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen    OS << "static AttrListPtr getAttributes(" << TargetPrefix
43949de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen       << "Intrinsic::ID id) {";
44049de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen  else
44149de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen    OS << "AttrListPtr Intrinsic::getAttributes(ID id) {";
442048ffb239c282277959463c61200b86e2380cb84Chris Lattner  OS << "  // No intrinsic can throw exceptions.\n";
443048ffb239c282277959463c61200b86e2380cb84Chris Lattner  OS << "  Attributes Attr = Attribute::NoUnwind;\n";
444a3355ffb3d30d19d226bbb75707991c60f236e37Duncan Sands  OS << "  switch (id) {\n";
4457056de375d898d9d9ecc17e170632d91d18be4a8Chris Lattner  OS << "  default: break;\n";
44610dae94be2ccb187bd4e3da53771be54057acd6cChris Lattner  unsigned MaxArgAttrs = 0;
4477056de375d898d9d9ecc17e170632d91d18be4a8Chris Lattner  for (unsigned i = 0, e = Ints.size(); i != e; ++i) {
44810dae94be2ccb187bd4e3da53771be54057acd6cChris Lattner    MaxArgAttrs =
44910dae94be2ccb187bd4e3da53771be54057acd6cChris Lattner      std::max(MaxArgAttrs, unsigned(Ints[i].ArgumentAttributes.size()));
4507056de375d898d9d9ecc17e170632d91d18be4a8Chris Lattner    switch (Ints[i].ModRef) {
4517056de375d898d9d9ecc17e170632d91d18be4a8Chris Lattner    default: break;
4527056de375d898d9d9ecc17e170632d91d18be4a8Chris Lattner    case CodeGenIntrinsic::NoMem:
45349de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen      OS << "  case " << TargetPrefix << "Intrinsic::" << Ints[i].EnumName
45449de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen         << ":\n";
4557056de375d898d9d9ecc17e170632d91d18be4a8Chris Lattner      break;
4567056de375d898d9d9ecc17e170632d91d18be4a8Chris Lattner    }
4577056de375d898d9d9ecc17e170632d91d18be4a8Chris Lattner  }
4580598866c052147c31b808391f58434ce3dbfb838Devang Patel  OS << "    Attr |= Attribute::ReadNone; // These do not access memory.\n";
459a3355ffb3d30d19d226bbb75707991c60f236e37Duncan Sands  OS << "    break;\n";
4604e5f35973c1bc56cce14d44c6f8f4ad1e9f1a438Chris Lattner  for (unsigned i = 0, e = Ints.size(); i != e; ++i) {
4614e5f35973c1bc56cce14d44c6f8f4ad1e9f1a438Chris Lattner    switch (Ints[i].ModRef) {
462022f64fbbc4669623e79b805379266fed519017dChris Lattner    default: break;
463022f64fbbc4669623e79b805379266fed519017dChris Lattner    case CodeGenIntrinsic::ReadArgMem:
464022f64fbbc4669623e79b805379266fed519017dChris Lattner    case CodeGenIntrinsic::ReadMem:
46549de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen      OS << "  case " << TargetPrefix << "Intrinsic::" << Ints[i].EnumName
46649de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen         << ":\n";
467022f64fbbc4669623e79b805379266fed519017dChris Lattner      break;
4684e5f35973c1bc56cce14d44c6f8f4ad1e9f1a438Chris Lattner    }
4694e5f35973c1bc56cce14d44c6f8f4ad1e9f1a438Chris Lattner  }
4700598866c052147c31b808391f58434ce3dbfb838Devang Patel  OS << "    Attr |= Attribute::ReadOnly; // These do not write memory.\n";
471a3355ffb3d30d19d226bbb75707991c60f236e37Duncan Sands  OS << "    break;\n";
4724e5f35973c1bc56cce14d44c6f8f4ad1e9f1a438Chris Lattner  OS << "  }\n";
47310dae94be2ccb187bd4e3da53771be54057acd6cChris Lattner  OS << "  AttributeWithIndex AWI[" << MaxArgAttrs+1 << "];\n";
474d4a2700fdc5bc8ac50084fcb39155e01e86168d5Chris Lattner  OS << "  unsigned NumAttrs = 0;\n";
47510dae94be2ccb187bd4e3da53771be54057acd6cChris Lattner  OS << "  switch (id) {\n";
47610dae94be2ccb187bd4e3da53771be54057acd6cChris Lattner  OS << "  default: break;\n";
47710dae94be2ccb187bd4e3da53771be54057acd6cChris Lattner
47810dae94be2ccb187bd4e3da53771be54057acd6cChris Lattner  // Add argument attributes for any intrinsics that have them.
47910dae94be2ccb187bd4e3da53771be54057acd6cChris Lattner  for (unsigned i = 0, e = Ints.size(); i != e; ++i) {
48010dae94be2ccb187bd4e3da53771be54057acd6cChris Lattner    if (Ints[i].ArgumentAttributes.empty()) continue;
48110dae94be2ccb187bd4e3da53771be54057acd6cChris Lattner
48249de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen    OS << "  case " << TargetPrefix << "Intrinsic::" << Ints[i].EnumName
48349de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen       << ":\n";
48410dae94be2ccb187bd4e3da53771be54057acd6cChris Lattner
48510dae94be2ccb187bd4e3da53771be54057acd6cChris Lattner    std::vector<std::pair<unsigned, CodeGenIntrinsic::ArgAttribute> > ArgAttrs =
48610dae94be2ccb187bd4e3da53771be54057acd6cChris Lattner      Ints[i].ArgumentAttributes;
48710dae94be2ccb187bd4e3da53771be54057acd6cChris Lattner    // Sort by argument index.
48810dae94be2ccb187bd4e3da53771be54057acd6cChris Lattner    std::sort(ArgAttrs.begin(), ArgAttrs.end());
48910dae94be2ccb187bd4e3da53771be54057acd6cChris Lattner
49010dae94be2ccb187bd4e3da53771be54057acd6cChris Lattner    unsigned NumArgsWithAttrs = 0;
49110dae94be2ccb187bd4e3da53771be54057acd6cChris Lattner
492d4a2700fdc5bc8ac50084fcb39155e01e86168d5Chris Lattner    while (!ArgAttrs.empty()) {
493d4a2700fdc5bc8ac50084fcb39155e01e86168d5Chris Lattner      unsigned ArgNo = ArgAttrs[0].first;
494d4a2700fdc5bc8ac50084fcb39155e01e86168d5Chris Lattner
495d4a2700fdc5bc8ac50084fcb39155e01e86168d5Chris Lattner      OS << "    AWI[" << NumArgsWithAttrs++ << "] = AttributeWithIndex::get("
496d4a2700fdc5bc8ac50084fcb39155e01e86168d5Chris Lattner         << ArgNo+1 << ", 0";
497d4a2700fdc5bc8ac50084fcb39155e01e86168d5Chris Lattner
498d4a2700fdc5bc8ac50084fcb39155e01e86168d5Chris Lattner      while (!ArgAttrs.empty() && ArgAttrs[0].first == ArgNo) {
499d4a2700fdc5bc8ac50084fcb39155e01e86168d5Chris Lattner        switch (ArgAttrs[0].second) {
500d4a2700fdc5bc8ac50084fcb39155e01e86168d5Chris Lattner        default: assert(0 && "Unknown arg attribute");
501d4a2700fdc5bc8ac50084fcb39155e01e86168d5Chris Lattner        case CodeGenIntrinsic::NoCapture:
502d4a2700fdc5bc8ac50084fcb39155e01e86168d5Chris Lattner          OS << "|Attribute::NoCapture";
503d4a2700fdc5bc8ac50084fcb39155e01e86168d5Chris Lattner          break;
504d4a2700fdc5bc8ac50084fcb39155e01e86168d5Chris Lattner        }
505d4a2700fdc5bc8ac50084fcb39155e01e86168d5Chris Lattner        ArgAttrs.erase(ArgAttrs.begin());
506d4a2700fdc5bc8ac50084fcb39155e01e86168d5Chris Lattner      }
507d4a2700fdc5bc8ac50084fcb39155e01e86168d5Chris Lattner      OS << ");\n";
508d4a2700fdc5bc8ac50084fcb39155e01e86168d5Chris Lattner    }
50910dae94be2ccb187bd4e3da53771be54057acd6cChris Lattner
510d4a2700fdc5bc8ac50084fcb39155e01e86168d5Chris Lattner    OS << "    NumAttrs = " << NumArgsWithAttrs << ";\n";
51110dae94be2ccb187bd4e3da53771be54057acd6cChris Lattner    OS << "    break;\n";
51210dae94be2ccb187bd4e3da53771be54057acd6cChris Lattner  }
51310dae94be2ccb187bd4e3da53771be54057acd6cChris Lattner
51410dae94be2ccb187bd4e3da53771be54057acd6cChris Lattner  OS << "  }\n";
515d4a2700fdc5bc8ac50084fcb39155e01e86168d5Chris Lattner  OS << "  AWI[NumAttrs] = AttributeWithIndex::get(~0, Attr);\n";
516d4a2700fdc5bc8ac50084fcb39155e01e86168d5Chris Lattner  OS << "  return AttrListPtr::get(AWI, NumAttrs+1);\n";
517048ffb239c282277959463c61200b86e2380cb84Chris Lattner  OS << "}\n";
518d4a2700fdc5bc8ac50084fcb39155e01e86168d5Chris Lattner  OS << "#endif // GET_INTRINSIC_ATTRIBUTES\n\n";
5194e5f35973c1bc56cce14d44c6f8f4ad1e9f1a438Chris Lattner}
520022f64fbbc4669623e79b805379266fed519017dChris Lattner
521d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands/// EmitModRefBehavior - Determine intrinsic alias analysis mod/ref behavior.
522d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sandsvoid IntrinsicEmitter::
5231a55180238dbcf11113f610aea010447e51f595bDaniel DunbarEmitModRefBehavior(const std::vector<CodeGenIntrinsic> &Ints, raw_ostream &OS){
524d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands  OS << "// Determine intrinsic alias analysis mod/ref behavior.\n";
525d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands  OS << "#ifdef GET_INTRINSIC_MODREF_BEHAVIOR\n";
5267c422ac216fe39fc9c402a704cf296cca9dc5b22Duncan Sands  OS << "switch (iid) {\n";
527d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands  OS << "default:\n    return UnknownModRefBehavior;\n";
528d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands  for (unsigned i = 0, e = Ints.size(); i != e; ++i) {
529d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands    if (Ints[i].ModRef == CodeGenIntrinsic::WriteMem)
530d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands      continue;
531d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands    OS << "case " << TargetPrefix << "Intrinsic::" << Ints[i].EnumName
532d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands      << ":\n";
533d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands    switch (Ints[i].ModRef) {
534d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands    default:
535d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands      assert(false && "Unknown Mod/Ref type!");
536d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands    case CodeGenIntrinsic::NoMem:
537d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands      OS << "  return DoesNotAccessMemory;\n";
538d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands      break;
539d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands    case CodeGenIntrinsic::ReadArgMem:
540d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands    case CodeGenIntrinsic::ReadMem:
541d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands      OS << "  return OnlyReadsMemory;\n";
542d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands      break;
543d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands    case CodeGenIntrinsic::WriteArgMem:
544d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands      OS << "  return AccessesArguments;\n";
545d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands      break;
546d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands    }
547d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands  }
548d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands  OS << "}\n";
549d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands  OS << "#endif // GET_INTRINSIC_MODREF_BEHAVIOR\n\n";
550d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands}
551d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands
552022f64fbbc4669623e79b805379266fed519017dChris Lattnervoid IntrinsicEmitter::
5531a55180238dbcf11113f610aea010447e51f595bDaniel DunbarEmitGCCBuiltinList(const std::vector<CodeGenIntrinsic> &Ints, raw_ostream &OS){
554022f64fbbc4669623e79b805379266fed519017dChris Lattner  OS << "// Get the GCC builtin that corresponds to an LLVM intrinsic.\n";
555022f64fbbc4669623e79b805379266fed519017dChris Lattner  OS << "#ifdef GET_GCC_BUILTIN_NAME\n";
556022f64fbbc4669623e79b805379266fed519017dChris Lattner  OS << "  switch (F->getIntrinsicID()) {\n";
557022f64fbbc4669623e79b805379266fed519017dChris Lattner  OS << "  default: BuiltinName = \"\"; break;\n";
558022f64fbbc4669623e79b805379266fed519017dChris Lattner  for (unsigned i = 0, e = Ints.size(); i != e; ++i) {
559022f64fbbc4669623e79b805379266fed519017dChris Lattner    if (!Ints[i].GCCBuiltinName.empty()) {
560022f64fbbc4669623e79b805379266fed519017dChris Lattner      OS << "  case Intrinsic::" << Ints[i].EnumName << ": BuiltinName = \""
561022f64fbbc4669623e79b805379266fed519017dChris Lattner         << Ints[i].GCCBuiltinName << "\"; break;\n";
562022f64fbbc4669623e79b805379266fed519017dChris Lattner    }
563022f64fbbc4669623e79b805379266fed519017dChris Lattner  }
564022f64fbbc4669623e79b805379266fed519017dChris Lattner  OS << "  }\n";
565022f64fbbc4669623e79b805379266fed519017dChris Lattner  OS << "#endif\n\n";
566767a25b8788b5e313c99c16b4d359478432901f5Reid Spencer}
5673f8b8913bc9cb232871445eefa8654caf7f9986fChris Lattner
568331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner/// EmitBuiltinComparisons - Emit comparisons to determine whether the specified
569331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner/// sorted range of builtin names is equal to the current builtin.  This breaks
570331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner/// it down into a simple tree.
571331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner///
572331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner/// At this point, we know that all the builtins in the range have the same name
573331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner/// for the first 'CharStart' characters.  Only the end of the name needs to be
574331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner/// discriminated.
575331bf92fb51f058672144681b3d0e67d30f5699fChris Lattnertypedef std::map<std::string, std::string>::const_iterator StrMapIterator;
576331bf92fb51f058672144681b3d0e67d30f5699fChris Lattnerstatic void EmitBuiltinComparisons(StrMapIterator Start, StrMapIterator End,
577331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner                                   unsigned CharStart, unsigned Indent,
5781a55180238dbcf11113f610aea010447e51f595bDaniel Dunbar                                   std::string TargetPrefix, raw_ostream &OS) {
579331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner  if (Start == End) return; // empty range.
580331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner
581331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner  // Determine what, if anything, is the same about all these strings.
582331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner  std::string CommonString = Start->first;
583331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner  unsigned NumInRange = 0;
584331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner  for (StrMapIterator I = Start; I != End; ++I, ++NumInRange) {
585331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner    // Find the first character that doesn't match.
586331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner    const std::string &ThisStr = I->first;
587331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner    unsigned NonMatchChar = CharStart;
588331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner    while (NonMatchChar < CommonString.size() &&
589331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner           NonMatchChar < ThisStr.size() &&
590331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner           CommonString[NonMatchChar] == ThisStr[NonMatchChar])
591331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner      ++NonMatchChar;
592331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner    // Truncate off pieces that don't match.
593331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner    CommonString.resize(NonMatchChar);
594331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner  }
595331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner
596331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner  // Just compare the rest of the string.
597331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner  if (NumInRange == 1) {
598331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner    if (CharStart != CommonString.size()) {
599331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner      OS << std::string(Indent*2, ' ') << "if (!memcmp(BuiltinName";
600331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner      if (CharStart) OS << "+" << CharStart;
601331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner      OS << ", \"" << (CommonString.c_str()+CharStart) << "\", ";
602331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner      OS << CommonString.size() - CharStart << "))\n";
603331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner      ++Indent;
604331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner    }
60549de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen    OS << std::string(Indent*2, ' ') << "IntrinsicID = " << TargetPrefix
60649de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen       << "Intrinsic::";
607331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner    OS << Start->second << ";\n";
608331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner    return;
609331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner  }
610331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner
611331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner  // At this point, we potentially have a common prefix for these builtins, emit
612331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner  // a check for this common prefix.
613331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner  if (CommonString.size() != CharStart) {
614331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner    OS << std::string(Indent*2, ' ') << "if (!memcmp(BuiltinName";
615331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner    if (CharStart) OS << "+" << CharStart;
616331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner    OS << ", \"" << (CommonString.c_str()+CharStart) << "\", ";
617331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner    OS << CommonString.size()-CharStart << ")) {\n";
618331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner
61949de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen    EmitBuiltinComparisons(Start, End, CommonString.size(), Indent+1,
62049de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen                           TargetPrefix, OS);
621331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner    OS << std::string(Indent*2, ' ') << "}\n";
622331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner    return;
623331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner  }
624331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner
625331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner  // Output a switch on the character that differs across the set.
626331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner  OS << std::string(Indent*2, ' ') << "switch (BuiltinName[" << CharStart
627331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner      << "]) {";
628331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner  if (CharStart)
629331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner    OS << "  // \"" << std::string(Start->first.begin(),
630331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner                                   Start->first.begin()+CharStart) << "\"";
631331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner  OS << "\n";
632331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner
633331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner  for (StrMapIterator I = Start; I != End; ) {
634331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner    char ThisChar = I->first[CharStart];
635331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner    OS << std::string(Indent*2, ' ') << "case '" << ThisChar << "':\n";
636331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner    // Figure out the range that has this common character.
637331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner    StrMapIterator NextChar = I;
638331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner    for (++NextChar; NextChar != End && NextChar->first[CharStart] == ThisChar;
639331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner         ++NextChar)
640331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner      /*empty*/;
64149de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen    EmitBuiltinComparisons(I, NextChar, CharStart+1, Indent+1, TargetPrefix,OS);
642331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner    OS << std::string(Indent*2, ' ') << "  break;\n";
643331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner    I = NextChar;
644331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner  }
645331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner  OS << std::string(Indent*2, ' ') << "}\n";
646331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner}
647331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner
648331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner/// EmitTargetBuiltins - All of the builtins in the specified map are for the
649331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner/// same target, and we already checked it.
650331bf92fb51f058672144681b3d0e67d30f5699fChris Lattnerstatic void EmitTargetBuiltins(const std::map<std::string, std::string> &BIM,
65149de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen                               const std::string &TargetPrefix,
6521a55180238dbcf11113f610aea010447e51f595bDaniel Dunbar                               raw_ostream &OS) {
653331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner  // Rearrange the builtins by length.
654331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner  std::vector<std::map<std::string, std::string> > BuiltinsByLen;
655331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner  BuiltinsByLen.reserve(100);
656331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner
657331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner  for (StrMapIterator I = BIM.begin(), E = BIM.end(); I != E; ++I) {
658331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner    if (I->first.size() >= BuiltinsByLen.size())
659331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner      BuiltinsByLen.resize(I->first.size()+1);
660331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner    BuiltinsByLen[I->first.size()].insert(*I);
661331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner  }
662331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner
663331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner  // Now that we have all the builtins by their length, emit a switch stmt.
664331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner  OS << "    switch (strlen(BuiltinName)) {\n";
665331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner  OS << "    default: break;\n";
666331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner  for (unsigned i = 0, e = BuiltinsByLen.size(); i != e; ++i) {
667331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner    if (BuiltinsByLen[i].empty()) continue;
668331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner    OS << "    case " << i << ":\n";
669331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner    EmitBuiltinComparisons(BuiltinsByLen[i].begin(), BuiltinsByLen[i].end(),
67049de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen                           0, 3, TargetPrefix, OS);
671331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner    OS << "      break;\n";
672331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner  }
673331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner  OS << "    }\n";
674331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner}
675331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner
676331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner
6773f8b8913bc9cb232871445eefa8654caf7f9986fChris Lattnervoid IntrinsicEmitter::
6783f8b8913bc9cb232871445eefa8654caf7f9986fChris LattnerEmitIntrinsicToGCCBuiltinMap(const std::vector<CodeGenIntrinsic> &Ints,
6791a55180238dbcf11113f610aea010447e51f595bDaniel Dunbar                             raw_ostream &OS) {
680fa0fba1c546091c485e5513eadeef181dda370abChris Lattner  typedef std::map<std::string, std::map<std::string, std::string> > BIMTy;
6813f8b8913bc9cb232871445eefa8654caf7f9986fChris Lattner  BIMTy BuiltinMap;
6823f8b8913bc9cb232871445eefa8654caf7f9986fChris Lattner  for (unsigned i = 0, e = Ints.size(); i != e; ++i) {
6833f8b8913bc9cb232871445eefa8654caf7f9986fChris Lattner    if (!Ints[i].GCCBuiltinName.empty()) {
684fa0fba1c546091c485e5513eadeef181dda370abChris Lattner      // Get the map for this target prefix.
685fa0fba1c546091c485e5513eadeef181dda370abChris Lattner      std::map<std::string, std::string> &BIM =BuiltinMap[Ints[i].TargetPrefix];
686fa0fba1c546091c485e5513eadeef181dda370abChris Lattner
687fa0fba1c546091c485e5513eadeef181dda370abChris Lattner      if (!BIM.insert(std::make_pair(Ints[i].GCCBuiltinName,
688fa0fba1c546091c485e5513eadeef181dda370abChris Lattner                                     Ints[i].EnumName)).second)
6893f8b8913bc9cb232871445eefa8654caf7f9986fChris Lattner        throw "Intrinsic '" + Ints[i].TheDef->getName() +
6903f8b8913bc9cb232871445eefa8654caf7f9986fChris Lattner              "': duplicate GCC builtin name!";
6913f8b8913bc9cb232871445eefa8654caf7f9986fChris Lattner    }
6923f8b8913bc9cb232871445eefa8654caf7f9986fChris Lattner  }
6933f8b8913bc9cb232871445eefa8654caf7f9986fChris Lattner
6943f8b8913bc9cb232871445eefa8654caf7f9986fChris Lattner  OS << "// Get the LLVM intrinsic that corresponds to a GCC builtin.\n";
6953f8b8913bc9cb232871445eefa8654caf7f9986fChris Lattner  OS << "// This is used by the C front-end.  The GCC builtin name is passed\n";
6963f8b8913bc9cb232871445eefa8654caf7f9986fChris Lattner  OS << "// in as BuiltinName, and a target prefix (e.g. 'ppc') is passed\n";
6973f8b8913bc9cb232871445eefa8654caf7f9986fChris Lattner  OS << "// in as TargetPrefix.  The result is assigned to 'IntrinsicID'.\n";
6983f8b8913bc9cb232871445eefa8654caf7f9986fChris Lattner  OS << "#ifdef GET_LLVM_INTRINSIC_FOR_GCC_BUILTIN\n";
69949de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen
70049de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen  if (TargetOnly) {
70149de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen    OS << "static " << TargetPrefix << "Intrinsic::ID "
70249de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen       << "getIntrinsicForGCCBuiltin(const char "
70349de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen       << "*TargetPrefix, const char *BuiltinName) {\n";
70449de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen    OS << "  " << TargetPrefix << "Intrinsic::ID IntrinsicID = ";
70549de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen  } else {
70649de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen    OS << "Intrinsic::ID Intrinsic::getIntrinsicForGCCBuiltin(const char "
70749de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen       << "*TargetPrefix, const char *BuiltinName) {\n";
70849de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen    OS << "  Intrinsic::ID IntrinsicID = ";
70949de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen  }
71049de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen
71149de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen  if (TargetOnly)
71249de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen    OS << "(" << TargetPrefix<< "Intrinsic::ID)";
71349de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen
71449de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen  OS << "Intrinsic::not_intrinsic;\n";
715331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner
7163f8b8913bc9cb232871445eefa8654caf7f9986fChris Lattner  // Note: this could emit significantly better code if we cared.
7173f8b8913bc9cb232871445eefa8654caf7f9986fChris Lattner  for (BIMTy::iterator I = BuiltinMap.begin(), E = BuiltinMap.end();I != E;++I){
718fa0fba1c546091c485e5513eadeef181dda370abChris Lattner    OS << "  ";
719fa0fba1c546091c485e5513eadeef181dda370abChris Lattner    if (!I->first.empty())
720fa0fba1c546091c485e5513eadeef181dda370abChris Lattner      OS << "if (!strcmp(TargetPrefix, \"" << I->first << "\")) ";
721fa0fba1c546091c485e5513eadeef181dda370abChris Lattner    else
722fa0fba1c546091c485e5513eadeef181dda370abChris Lattner      OS << "/* Target Independent Builtins */ ";
723fa0fba1c546091c485e5513eadeef181dda370abChris Lattner    OS << "{\n";
724fa0fba1c546091c485e5513eadeef181dda370abChris Lattner
725fa0fba1c546091c485e5513eadeef181dda370abChris Lattner    // Emit the comparisons for this target prefix.
72649de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen    EmitTargetBuiltins(I->second, TargetPrefix, OS);
727fa0fba1c546091c485e5513eadeef181dda370abChris Lattner    OS << "  }\n";
7283f8b8913bc9cb232871445eefa8654caf7f9986fChris Lattner  }
72949de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen  OS << "  return IntrinsicID;\n";
73049de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen  OS << "}\n";
7313f8b8913bc9cb232871445eefa8654caf7f9986fChris Lattner  OS << "#endif\n\n";
7323f8b8913bc9cb232871445eefa8654caf7f9986fChris Lattner}
733