IntrinsicEmitter.cpp revision 298b176559d5c76d7d9f7fdd06429a75892de043
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"
17298b176559d5c76d7d9f7fdd06429a75892de043Chris Lattner#include "StringMatcher.h"
1818faf5d9f7f89130b9e3304965b81e1c70ebb75cChris Lattner#include "llvm/ADT/StringExtras.h"
1971c3bc3d966bd874f760abf055c559673f925029Jeff Cohen#include <algorithm>
209e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattnerusing namespace llvm;
219e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner
229e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner//===----------------------------------------------------------------------===//
239e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner// IntrinsicEmitter Implementation
249e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner//===----------------------------------------------------------------------===//
259e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner
261a55180238dbcf11113f610aea010447e51f595bDaniel Dunbarvoid IntrinsicEmitter::run(raw_ostream &OS) {
279e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner  EmitSourceFileHeader("Intrinsic Function Source Fragment", OS);
289e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner
2949de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen  std::vector<CodeGenIntrinsic> Ints = LoadIntrinsics(Records, TargetOnly);
3049de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen
3149de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen  if (TargetOnly && !Ints.empty())
3249de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen    TargetPrefix = Ints[0].TargetPrefix;
339e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner
347d9663c70b3300070298d716dba6e6f6ce2d1e3eDouglas Gregor  EmitPrefix(OS);
357d9663c70b3300070298d716dba6e6f6ce2d1e3eDouglas Gregor
369e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner  // Emit the enum information.
379e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner  EmitEnumInfo(Ints, OS);
38fda6affb95e9f68278cb5cf75dc3fd3406978255Chris Lattner
39fda6affb95e9f68278cb5cf75dc3fd3406978255Chris Lattner  // Emit the intrinsic ID -> name table.
40fda6affb95e9f68278cb5cf75dc3fd3406978255Chris Lattner  EmitIntrinsicToNameTable(Ints, OS);
410d52ff1f7b993750a74a5d4432273092de9af069Mon P Wang
420d52ff1f7b993750a74a5d4432273092de9af069Mon P Wang  // Emit the intrinsic ID -> overload table.
430d52ff1f7b993750a74a5d4432273092de9af069Mon P Wang  EmitIntrinsicToOverloadTable(Ints, OS);
440d52ff1f7b993750a74a5d4432273092de9af069Mon P Wang
459b843b249462980ae4630dc37d1bcccde884a5a7Chris Lattner  // Emit the function name recognizer.
469b843b249462980ae4630dc37d1bcccde884a5a7Chris Lattner  EmitFnNameRecognizer(Ints, OS);
47fda6affb95e9f68278cb5cf75dc3fd3406978255Chris Lattner
48f97a00e681c7a526d49759d0d1b9d327cbf6c04aChris Lattner  // Emit the intrinsic verifier.
49f97a00e681c7a526d49759d0d1b9d327cbf6c04aChris Lattner  EmitVerifier(Ints, OS);
506448ee44c6f232f215d5d9f145a0d71a983c4a3fChris Lattner
5195af592a631f403e1458ec1155f89fc31011572cJim Laskey  // Emit the intrinsic declaration generator.
5295af592a631f403e1458ec1155f89fc31011572cJim Laskey  EmitGenerator(Ints, OS);
5395af592a631f403e1458ec1155f89fc31011572cJim Laskey
54a3355ffb3d30d19d226bbb75707991c60f236e37Duncan Sands  // Emit the intrinsic parameter attributes.
55a3355ffb3d30d19d226bbb75707991c60f236e37Duncan Sands  EmitAttributes(Ints, OS);
56022f64fbbc4669623e79b805379266fed519017dChris Lattner
57d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands  // Emit intrinsic alias analysis mod/ref behavior.
58d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands  EmitModRefBehavior(Ints, OS);
59d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands
60022f64fbbc4669623e79b805379266fed519017dChris Lattner  // Emit a list of intrinsics with corresponding GCC builtins.
61022f64fbbc4669623e79b805379266fed519017dChris Lattner  EmitGCCBuiltinList(Ints, OS);
623f8b8913bc9cb232871445eefa8654caf7f9986fChris Lattner
633f8b8913bc9cb232871445eefa8654caf7f9986fChris Lattner  // Emit code to translate GCC builtins into LLVM intrinsics.
643f8b8913bc9cb232871445eefa8654caf7f9986fChris Lattner  EmitIntrinsicToGCCBuiltinMap(Ints, OS);
657d9663c70b3300070298d716dba6e6f6ce2d1e3eDouglas Gregor
667d9663c70b3300070298d716dba6e6f6ce2d1e3eDouglas Gregor  EmitSuffix(OS);
677d9663c70b3300070298d716dba6e6f6ce2d1e3eDouglas Gregor}
687d9663c70b3300070298d716dba6e6f6ce2d1e3eDouglas Gregor
697d9663c70b3300070298d716dba6e6f6ce2d1e3eDouglas Gregorvoid IntrinsicEmitter::EmitPrefix(raw_ostream &OS) {
707d9663c70b3300070298d716dba6e6f6ce2d1e3eDouglas Gregor  OS << "// VisualStudio defines setjmp as _setjmp\n"
717d9663c70b3300070298d716dba6e6f6ce2d1e3eDouglas Gregor        "#if defined(_MSC_VER) && defined(setjmp)\n"
727d9663c70b3300070298d716dba6e6f6ce2d1e3eDouglas Gregor        "#define setjmp_undefined_for_visual_studio\n"
737d9663c70b3300070298d716dba6e6f6ce2d1e3eDouglas Gregor        "#undef setjmp\n"
747d9663c70b3300070298d716dba6e6f6ce2d1e3eDouglas Gregor        "#endif\n\n";
757d9663c70b3300070298d716dba6e6f6ce2d1e3eDouglas Gregor}
767d9663c70b3300070298d716dba6e6f6ce2d1e3eDouglas Gregor
777d9663c70b3300070298d716dba6e6f6ce2d1e3eDouglas Gregorvoid IntrinsicEmitter::EmitSuffix(raw_ostream &OS) {
787d9663c70b3300070298d716dba6e6f6ce2d1e3eDouglas Gregor  OS << "#if defined(_MSC_VER) && defined(setjmp_undefined_for_visual_studio)\n"
797d9663c70b3300070298d716dba6e6f6ce2d1e3eDouglas Gregor        "// let's return it to _setjmp state\n"
807d9663c70b3300070298d716dba6e6f6ce2d1e3eDouglas Gregor        "#define setjmp _setjmp\n"
817d9663c70b3300070298d716dba6e6f6ce2d1e3eDouglas Gregor        "#endif\n\n";
829e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner}
839e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner
849e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattnervoid IntrinsicEmitter::EmitEnumInfo(const std::vector<CodeGenIntrinsic> &Ints,
851a55180238dbcf11113f610aea010447e51f595bDaniel Dunbar                                    raw_ostream &OS) {
869b843b249462980ae4630dc37d1bcccde884a5a7Chris Lattner  OS << "// Enum values for Intrinsics.h\n";
879e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner  OS << "#ifdef GET_INTRINSIC_ENUM_VALUES\n";
889e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner  for (unsigned i = 0, e = Ints.size(); i != e; ++i) {
899e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner    OS << "    " << Ints[i].EnumName;
909e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner    OS << ((i != e-1) ? ", " : "  ");
919e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner    OS << std::string(40-Ints[i].EnumName.size(), ' ')
929e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner      << "// " << Ints[i].Name << "\n";
939e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner  }
949e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner  OS << "#endif\n\n";
959e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner}
969b843b249462980ae4630dc37d1bcccde884a5a7Chris Lattner
979b843b249462980ae4630dc37d1bcccde884a5a7Chris Lattnervoid IntrinsicEmitter::
989b843b249462980ae4630dc37d1bcccde884a5a7Chris LattnerEmitFnNameRecognizer(const std::vector<CodeGenIntrinsic> &Ints,
991a55180238dbcf11113f610aea010447e51f595bDaniel Dunbar                     raw_ostream &OS) {
1009b843b249462980ae4630dc37d1bcccde884a5a7Chris Lattner  // Build a function name -> intrinsic name mapping.
101c4de3dec62c3f60ae7297f93c19c799c403c2e9fReid Spencer  std::map<std::string, unsigned> IntMapping;
1029b843b249462980ae4630dc37d1bcccde884a5a7Chris Lattner  for (unsigned i = 0, e = Ints.size(); i != e; ++i)
1032738ff9c22d27ce3e4aee6f250eb68f594db1ce9Chris Lattner    IntMapping[Ints[i].Name.substr(5)] = i;
1049b843b249462980ae4630dc37d1bcccde884a5a7Chris Lattner
1059b843b249462980ae4630dc37d1bcccde884a5a7Chris Lattner  OS << "// Function name -> enum value recognizer code.\n";
1069b843b249462980ae4630dc37d1bcccde884a5a7Chris Lattner  OS << "#ifdef GET_FUNCTION_RECOGNIZER\n";
1072738ff9c22d27ce3e4aee6f250eb68f594db1ce9Chris Lattner  OS << "  Name += 5; Len -= 5;  // Skip over 'llvm.'\n";
1082738ff9c22d27ce3e4aee6f250eb68f594db1ce9Chris Lattner  OS << "  switch (*Name) {      // Dispatch on first letter.\n";
1093b515802f652b16b05c9a8f344d219a0739b36a3Chris Lattner  OS << "  default:\n";
1109b843b249462980ae4630dc37d1bcccde884a5a7Chris Lattner  // Emit the intrinsics in sorted order.
1119b843b249462980ae4630dc37d1bcccde884a5a7Chris Lattner  char LastChar = 0;
112c4de3dec62c3f60ae7297f93c19c799c403c2e9fReid Spencer  for (std::map<std::string, unsigned>::iterator I = IntMapping.begin(),
1139b843b249462980ae4630dc37d1bcccde884a5a7Chris Lattner       E = IntMapping.end(); I != E; ++I) {
1142738ff9c22d27ce3e4aee6f250eb68f594db1ce9Chris Lattner    if (I->first[0] != LastChar) {
1152738ff9c22d27ce3e4aee6f250eb68f594db1ce9Chris Lattner      LastChar = I->first[0];
1163b515802f652b16b05c9a8f344d219a0739b36a3Chris Lattner      OS << "    break;\n";
1179b843b249462980ae4630dc37d1bcccde884a5a7Chris Lattner      OS << "  case '" << LastChar << "':\n";
1189b843b249462980ae4630dc37d1bcccde884a5a7Chris Lattner    }
1199b843b249462980ae4630dc37d1bcccde884a5a7Chris Lattner
120c4de3dec62c3f60ae7297f93c19c799c403c2e9fReid Spencer    // For overloaded intrinsics, only the prefix needs to match
1212738ff9c22d27ce3e4aee6f250eb68f594db1ce9Chris Lattner    std::string TheStr = I->first;
1222738ff9c22d27ce3e4aee6f250eb68f594db1ce9Chris Lattner    if (Ints[I->second].isOverloaded) {
1232738ff9c22d27ce3e4aee6f250eb68f594db1ce9Chris Lattner      TheStr += '.';  // Require "bswap." instead of bswap.
1242738ff9c22d27ce3e4aee6f250eb68f594db1ce9Chris Lattner      OS << "    if (Len > " << I->first.size();
1252738ff9c22d27ce3e4aee6f250eb68f594db1ce9Chris Lattner    } else {
1262738ff9c22d27ce3e4aee6f250eb68f594db1ce9Chris Lattner      OS << "    if (Len == " << I->first.size();
1272738ff9c22d27ce3e4aee6f250eb68f594db1ce9Chris Lattner    }
1282738ff9c22d27ce3e4aee6f250eb68f594db1ce9Chris Lattner
1292738ff9c22d27ce3e4aee6f250eb68f594db1ce9Chris Lattner    OS << " && !memcmp(Name, \"" << TheStr << "\", "
1302738ff9c22d27ce3e4aee6f250eb68f594db1ce9Chris Lattner       << TheStr.size() << ")) return " << TargetPrefix << "Intrinsic::"
1316994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth       << Ints[I->second].EnumName << ";\n";
1329b843b249462980ae4630dc37d1bcccde884a5a7Chris Lattner  }
1339b843b249462980ae4630dc37d1bcccde884a5a7Chris Lattner  OS << "  }\n";
134f97a00e681c7a526d49759d0d1b9d327cbf6c04aChris Lattner  OS << "#endif\n\n";
135f97a00e681c7a526d49759d0d1b9d327cbf6c04aChris Lattner}
136f97a00e681c7a526d49759d0d1b9d327cbf6c04aChris Lattner
137fda6affb95e9f68278cb5cf75dc3fd3406978255Chris Lattnervoid IntrinsicEmitter::
138fda6affb95e9f68278cb5cf75dc3fd3406978255Chris LattnerEmitIntrinsicToNameTable(const std::vector<CodeGenIntrinsic> &Ints,
1391a55180238dbcf11113f610aea010447e51f595bDaniel Dunbar                         raw_ostream &OS) {
140fda6affb95e9f68278cb5cf75dc3fd3406978255Chris Lattner  OS << "// Intrinsic ID to name table\n";
141fda6affb95e9f68278cb5cf75dc3fd3406978255Chris Lattner  OS << "#ifdef GET_INTRINSIC_NAME_TABLE\n";
142fda6affb95e9f68278cb5cf75dc3fd3406978255Chris Lattner  OS << "  // Note that entry #0 is the invalid intrinsic!\n";
143f065a6f711dca09ba36ec8fd3556c4936cdbe621Evan Cheng  for (unsigned i = 0, e = Ints.size(); i != e; ++i)
144f065a6f711dca09ba36ec8fd3556c4936cdbe621Evan Cheng    OS << "  \"" << Ints[i].Name << "\",\n";
145fda6affb95e9f68278cb5cf75dc3fd3406978255Chris Lattner  OS << "#endif\n\n";
146fda6affb95e9f68278cb5cf75dc3fd3406978255Chris Lattner}
147fda6affb95e9f68278cb5cf75dc3fd3406978255Chris Lattner
1480d52ff1f7b993750a74a5d4432273092de9af069Mon P Wangvoid IntrinsicEmitter::
1490d52ff1f7b993750a74a5d4432273092de9af069Mon P WangEmitIntrinsicToOverloadTable(const std::vector<CodeGenIntrinsic> &Ints,
1501a55180238dbcf11113f610aea010447e51f595bDaniel Dunbar                         raw_ostream &OS) {
1510d52ff1f7b993750a74a5d4432273092de9af069Mon P Wang  OS << "// Intrinsic ID to overload table\n";
1520d52ff1f7b993750a74a5d4432273092de9af069Mon P Wang  OS << "#ifdef GET_INTRINSIC_OVERLOAD_TABLE\n";
1530d52ff1f7b993750a74a5d4432273092de9af069Mon P Wang  OS << "  // Note that entry #0 is the invalid intrinsic!\n";
1540d52ff1f7b993750a74a5d4432273092de9af069Mon P Wang  for (unsigned i = 0, e = Ints.size(); i != e; ++i) {
1550d52ff1f7b993750a74a5d4432273092de9af069Mon P Wang    OS << "  ";
1560d52ff1f7b993750a74a5d4432273092de9af069Mon P Wang    if (Ints[i].isOverloaded)
1570d52ff1f7b993750a74a5d4432273092de9af069Mon P Wang      OS << "true";
1580d52ff1f7b993750a74a5d4432273092de9af069Mon P Wang    else
1590d52ff1f7b993750a74a5d4432273092de9af069Mon P Wang      OS << "false";
1600d52ff1f7b993750a74a5d4432273092de9af069Mon P Wang    OS << ",\n";
1610d52ff1f7b993750a74a5d4432273092de9af069Mon P Wang  }
1620d52ff1f7b993750a74a5d4432273092de9af069Mon P Wang  OS << "#endif\n\n";
1630d52ff1f7b993750a74a5d4432273092de9af069Mon P Wang}
1640d52ff1f7b993750a74a5d4432273092de9af069Mon P Wang
165825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Andersonstatic void EmitTypeForValueType(raw_ostream &OS, MVT::SimpleValueType VT) {
166e50ed30282bb5b4a9ed952580523f2dda16215acOwen Anderson  if (EVT(VT).isInteger()) {
167e50ed30282bb5b4a9ed952580523f2dda16215acOwen Anderson    unsigned BitWidth = EVT(VT).getSizeInBits();
1681d0be15f89cb5056e20e2d24faa8d6afb1573bcaOwen Anderson    OS << "IntegerType::get(Context, " << BitWidth << ")";
169825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson  } else if (VT == MVT::Other) {
170825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson    // MVT::OtherVT is used to mean the empty struct type here.
171d7f2a6cb3fbc012763adb42fd967f6fefbb22a37Owen Anderson    OS << "StructType::get(Context)";
172825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson  } else if (VT == MVT::f32) {
1731d0be15f89cb5056e20e2d24faa8d6afb1573bcaOwen Anderson    OS << "Type::getFloatTy(Context)";
174825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson  } else if (VT == MVT::f64) {
1751d0be15f89cb5056e20e2d24faa8d6afb1573bcaOwen Anderson    OS << "Type::getDoubleTy(Context)";
176825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson  } else if (VT == MVT::f80) {
1771d0be15f89cb5056e20e2d24faa8d6afb1573bcaOwen Anderson    OS << "Type::getX86_FP80Ty(Context)";
178825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson  } else if (VT == MVT::f128) {
1791d0be15f89cb5056e20e2d24faa8d6afb1573bcaOwen Anderson    OS << "Type::getFP128Ty(Context)";
180825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson  } else if (VT == MVT::ppcf128) {
1811d0be15f89cb5056e20e2d24faa8d6afb1573bcaOwen Anderson    OS << "Type::getPPC_FP128Ty(Context)";
182825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson  } else if (VT == MVT::isVoid) {
1831d0be15f89cb5056e20e2d24faa8d6afb1573bcaOwen Anderson    OS << "Type::getVoidTy(Context)";
184825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson  } else if (VT == MVT::Metadata) {
1851d0be15f89cb5056e20e2d24faa8d6afb1573bcaOwen Anderson    OS << "Type::getMetadataTy(Context)";
1866994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth  } else {
1876994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth    assert(false && "Unsupported ValueType!");
18818faf5d9f7f89130b9e3304965b81e1c70ebb75cChris Lattner  }
18918faf5d9f7f89130b9e3304965b81e1c70ebb75cChris Lattner}
19018faf5d9f7f89130b9e3304965b81e1c70ebb75cChris Lattner
1911a55180238dbcf11113f610aea010447e51f595bDaniel Dunbarstatic void EmitTypeGenerate(raw_ostream &OS, const Record *ArgType,
192cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling                             unsigned &ArgNo);
193cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling
1941a55180238dbcf11113f610aea010447e51f595bDaniel Dunbarstatic void EmitTypeGenerate(raw_ostream &OS,
195cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling                             const std::vector<Record*> &ArgTypes,
196cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling                             unsigned &ArgNo) {
19793dc92e412fd06250e46951bffb6040eca9baebdChris Lattner  if (ArgTypes.empty())
19893dc92e412fd06250e46951bffb6040eca9baebdChris Lattner    return EmitTypeForValueType(OS, MVT::isVoid);
19993dc92e412fd06250e46951bffb6040eca9baebdChris Lattner
20093dc92e412fd06250e46951bffb6040eca9baebdChris Lattner  if (ArgTypes.size() == 1)
20193dc92e412fd06250e46951bffb6040eca9baebdChris Lattner    return EmitTypeGenerate(OS, ArgTypes.front(), ArgNo);
202cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling
203d7f2a6cb3fbc012763adb42fd967f6fefbb22a37Owen Anderson  OS << "StructType::get(Context, ";
204cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling
205cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling  for (std::vector<Record*>::const_iterator
20620072af3b0b22d90afbce769409f4ed822520366Bill Wendling         I = ArgTypes.begin(), E = ArgTypes.end(); I != E; ++I) {
207cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling    EmitTypeGenerate(OS, *I, ArgNo);
20820072af3b0b22d90afbce769409f4ed822520366Bill Wendling    OS << ", ";
20920072af3b0b22d90afbce769409f4ed822520366Bill Wendling  }
210cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling
21120072af3b0b22d90afbce769409f4ed822520366Bill Wendling  OS << " NULL)";
212cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling}
213cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling
2141a55180238dbcf11113f610aea010447e51f595bDaniel Dunbarstatic void EmitTypeGenerate(raw_ostream &OS, const Record *ArgType,
21584c614d1ac671b1a5524169f20028f51c30be728Reid Spencer                             unsigned &ArgNo) {
216825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson  MVT::SimpleValueType VT = getValueType(ArgType->getValueAsDef("VT"));
2176994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth
2186994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth  if (ArgType->isSubClassOf("LLVMMatchType")) {
2196994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth    unsigned Number = ArgType->getValueAsInt("Number");
2206994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth    assert(Number < ArgNo && "Invalid matching number!");
221bc03979536a1ecb220f1330719f3e3973a81ab0bBob Wilson    if (ArgType->isSubClassOf("LLVMExtendedElementVectorType"))
222bc03979536a1ecb220f1330719f3e3973a81ab0bBob Wilson      OS << "VectorType::getExtendedElementVectorType"
223bc03979536a1ecb220f1330719f3e3973a81ab0bBob Wilson         << "(dyn_cast<VectorType>(Tys[" << Number << "]))";
224bc03979536a1ecb220f1330719f3e3973a81ab0bBob Wilson    else if (ArgType->isSubClassOf("LLVMTruncatedElementVectorType"))
225bc03979536a1ecb220f1330719f3e3973a81ab0bBob Wilson      OS << "VectorType::getTruncatedElementVectorType"
226bc03979536a1ecb220f1330719f3e3973a81ab0bBob Wilson         << "(dyn_cast<VectorType>(Tys[" << Number << "]))";
227bc03979536a1ecb220f1330719f3e3973a81ab0bBob Wilson    else
228bc03979536a1ecb220f1330719f3e3973a81ab0bBob Wilson      OS << "Tys[" << Number << "]";
229825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson  } else if (VT == MVT::iAny || VT == MVT::fAny || VT == MVT::vAny) {
23084c614d1ac671b1a5524169f20028f51c30be728Reid Spencer    // NOTE: The ArgNo variable here is not the absolute argument number, it is
23184c614d1ac671b1a5524169f20028f51c30be728Reid Spencer    // the index of the "arbitrary" type in the Tys array passed to the
23284c614d1ac671b1a5524169f20028f51c30be728Reid Spencer    // Intrinsic::getDeclaration function. Consequently, we only want to
2336994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth    // increment it when we actually hit an overloaded type. Getting this wrong
2346994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth    // leads to very subtle bugs!
2356994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth    OS << "Tys[" << ArgNo++ << "]";
236e50ed30282bb5b4a9ed952580523f2dda16215acOwen Anderson  } else if (EVT(VT).isVector()) {
237e50ed30282bb5b4a9ed952580523f2dda16215acOwen Anderson    EVT VVT = VT;
2389d6565a5b1fbc4286d6ee638d8f47a3171a9ed7eReid Spencer    OS << "VectorType::get(";
239825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson    EmitTypeForValueType(OS, VVT.getVectorElementType().getSimpleVT().SimpleTy);
24083ec4b6711980242ef3c55a4fa36b2d7a39c1bfbDuncan Sands    OS << ", " << VVT.getVectorNumElements() << ")";
241825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson  } else if (VT == MVT::iPTR) {
24243ad6b3e0d6ada51e9b23aab3e061187f1f5710cChristopher Lamb    OS << "PointerType::getUnqual(";
243c4de3dec62c3f60ae7297f93c19c799c403c2e9fReid Spencer    EmitTypeGenerate(OS, ArgType->getValueAsDef("ElTy"), ArgNo);
24495af592a631f403e1458ec1155f89fc31011572cJim Laskey    OS << ")";
245825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson  } else if (VT == MVT::iPTRAny) {
246e3b3a7241c01f26613694e53b26b01abf764ddfcMon P Wang    // Make sure the user has passed us an argument type to overload. If not,
247e3b3a7241c01f26613694e53b26b01abf764ddfcMon P Wang    // treat it as an ordinary (not overloaded) intrinsic.
248e3b3a7241c01f26613694e53b26b01abf764ddfcMon P Wang    OS << "(" << ArgNo << " < numTys) ? Tys[" << ArgNo
249e3b3a7241c01f26613694e53b26b01abf764ddfcMon P Wang    << "] : PointerType::getUnqual(";
250e3b3a7241c01f26613694e53b26b01abf764ddfcMon P Wang    EmitTypeGenerate(OS, ArgType->getValueAsDef("ElTy"), ArgNo);
251e3b3a7241c01f26613694e53b26b01abf764ddfcMon P Wang    OS << ")";
252e3b3a7241c01f26613694e53b26b01abf764ddfcMon P Wang    ++ArgNo;
253825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson  } else if (VT == MVT::isVoid) {
2546994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth    if (ArgNo == 0)
2551d0be15f89cb5056e20e2d24faa8d6afb1573bcaOwen Anderson      OS << "Type::getVoidTy(Context)";
2566994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth    else
257825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson      // MVT::isVoid is used to mean varargs here.
2586994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth      OS << "...";
25995af592a631f403e1458ec1155f89fc31011572cJim Laskey  } else {
2606994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth    EmitTypeForValueType(OS, VT);
26195af592a631f403e1458ec1155f89fc31011572cJim Laskey  }
26295af592a631f403e1458ec1155f89fc31011572cJim Laskey}
26395af592a631f403e1458ec1155f89fc31011572cJim Laskey
264da4231f134989af7dc6bd3408821ba573def27b2Jim Grosbach/// RecordListComparator - Provide a deterministic comparator for lists of
265c4d9b240b157efa9301d451ac44c12f6b004db8fChris Lattner/// records.
266c4d9b240b157efa9301d451ac44c12f6b004db8fChris Lattnernamespace {
267cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling  typedef std::pair<std::vector<Record*>, std::vector<Record*> > RecPair;
268c4d9b240b157efa9301d451ac44c12f6b004db8fChris Lattner  struct RecordListComparator {
269cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling    bool operator()(const RecPair &LHS,
270cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling                    const RecPair &RHS) const {
271c4d9b240b157efa9301d451ac44c12f6b004db8fChris Lattner      unsigned i = 0;
272cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling      const std::vector<Record*> *LHSVec = &LHS.first;
273cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling      const std::vector<Record*> *RHSVec = &RHS.first;
274cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling      unsigned RHSSize = RHSVec->size();
275cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling      unsigned LHSSize = LHSVec->size();
276cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling
27793dc92e412fd06250e46951bffb6040eca9baebdChris Lattner      for (; i != LHSSize; ++i) {
278cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling        if (i == RHSSize) return false;  // RHS is shorter than LHS.
279cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling        if ((*LHSVec)[i] != (*RHSVec)[i])
280cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling          return (*LHSVec)[i]->getName() < (*RHSVec)[i]->getName();
28193dc92e412fd06250e46951bffb6040eca9baebdChris Lattner      }
282cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling
283023422a6eb9ea692a5a837dc1daf256ac75ac6b0Bill Wendling      if (i != RHSSize) return true;
284cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling
285cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling      i = 0;
286cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling      LHSVec = &LHS.second;
287cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling      RHSVec = &RHS.second;
288cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling      RHSSize = RHSVec->size();
289cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling      LHSSize = LHSVec->size();
290cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling
291cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling      for (i = 0; i != LHSSize; ++i) {
292cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling        if (i == RHSSize) return false;  // RHS is shorter than LHS.
293cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling        if ((*LHSVec)[i] != (*RHSVec)[i])
294cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling          return (*LHSVec)[i]->getName() < (*RHSVec)[i]->getName();
295cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling      }
296cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling
297cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling      return i != RHSSize;
298c4d9b240b157efa9301d451ac44c12f6b004db8fChris Lattner    }
299c4d9b240b157efa9301d451ac44c12f6b004db8fChris Lattner  };
300c4d9b240b157efa9301d451ac44c12f6b004db8fChris Lattner}
301c4d9b240b157efa9301d451ac44c12f6b004db8fChris Lattner
302f97a00e681c7a526d49759d0d1b9d327cbf6c04aChris Lattnervoid IntrinsicEmitter::EmitVerifier(const std::vector<CodeGenIntrinsic> &Ints,
3031a55180238dbcf11113f610aea010447e51f595bDaniel Dunbar                                    raw_ostream &OS) {
304f97a00e681c7a526d49759d0d1b9d327cbf6c04aChris Lattner  OS << "// Verifier::visitIntrinsicFunctionCall code.\n";
305f97a00e681c7a526d49759d0d1b9d327cbf6c04aChris Lattner  OS << "#ifdef GET_INTRINSIC_VERIFIER\n";
306f97a00e681c7a526d49759d0d1b9d327cbf6c04aChris Lattner  OS << "  switch (ID) {\n";
307f97a00e681c7a526d49759d0d1b9d327cbf6c04aChris Lattner  OS << "  default: assert(0 && \"Invalid intrinsic!\");\n";
308c4d9b240b157efa9301d451ac44c12f6b004db8fChris Lattner
309c4d9b240b157efa9301d451ac44c12f6b004db8fChris Lattner  // This checking can emit a lot of very common code.  To reduce the amount of
310c4d9b240b157efa9301d451ac44c12f6b004db8fChris Lattner  // code that we emit, batch up cases that have identical types.  This avoids
311c4d9b240b157efa9301d451ac44c12f6b004db8fChris Lattner  // problems where GCC can run out of memory compiling Verifier.cpp.
312cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling  typedef std::map<RecPair, std::vector<unsigned>, RecordListComparator> MapTy;
313c4d9b240b157efa9301d451ac44c12f6b004db8fChris Lattner  MapTy UniqueArgInfos;
314c4d9b240b157efa9301d451ac44c12f6b004db8fChris Lattner
315c4d9b240b157efa9301d451ac44c12f6b004db8fChris Lattner  // Compute the unique argument type info.
316c4d9b240b157efa9301d451ac44c12f6b004db8fChris Lattner  for (unsigned i = 0, e = Ints.size(); i != e; ++i)
317cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling    UniqueArgInfos[make_pair(Ints[i].IS.RetTypeDefs,
318cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling                             Ints[i].IS.ParamTypeDefs)].push_back(i);
319c4d9b240b157efa9301d451ac44c12f6b004db8fChris Lattner
320c4d9b240b157efa9301d451ac44c12f6b004db8fChris Lattner  // Loop through the array, emitting one comparison for each batch.
321c4d9b240b157efa9301d451ac44c12f6b004db8fChris Lattner  for (MapTy::iterator I = UniqueArgInfos.begin(),
322c4d9b240b157efa9301d451ac44c12f6b004db8fChris Lattner       E = UniqueArgInfos.end(); I != E; ++I) {
323cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling    for (unsigned i = 0, e = I->second.size(); i != e; ++i)
324c4d9b240b157efa9301d451ac44c12f6b004db8fChris Lattner      OS << "  case Intrinsic::" << Ints[I->second[i]].EnumName << ":\t\t// "
325c4d9b240b157efa9301d451ac44c12f6b004db8fChris Lattner         << Ints[I->second[i]].Name << "\n";
326f124b46b4f18b1a8f054a1222324ae15079f6ed8Chris Lattner
327cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling    const RecPair &ArgTypes = I->first;
328cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling    const std::vector<Record*> &RetTys = ArgTypes.first;
329cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling    const std::vector<Record*> &ParamTys = ArgTypes.second;
33009b1366f3f310b5648aa8cd72ed16b9f19b4c68dBob Wilson    std::vector<unsigned> OverloadedTypeIndices;
331cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling
332cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling    OS << "    VerifyIntrinsicPrototype(ID, IF, " << RetTys.size() << ", "
333cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling       << ParamTys.size();
334cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling
335cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling    // Emit return types.
336cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling    for (unsigned j = 0, je = RetTys.size(); j != je; ++j) {
337cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling      Record *ArgType = RetTys[j];
338cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling      OS << ", ";
339cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling
3406994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth      if (ArgType->isSubClassOf("LLVMMatchType")) {
3416994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth        unsigned Number = ArgType->getValueAsInt("Number");
34209b1366f3f310b5648aa8cd72ed16b9f19b4c68dBob Wilson        assert(Number < OverloadedTypeIndices.size() &&
34309b1366f3f310b5648aa8cd72ed16b9f19b4c68dBob Wilson               "Invalid matching number!");
34409b1366f3f310b5648aa8cd72ed16b9f19b4c68dBob Wilson        Number = OverloadedTypeIndices[Number];
345bc03979536a1ecb220f1330719f3e3973a81ab0bBob Wilson        if (ArgType->isSubClassOf("LLVMExtendedElementVectorType"))
346bc03979536a1ecb220f1330719f3e3973a81ab0bBob Wilson          OS << "~(ExtendedElementVectorType | " << Number << ")";
347bc03979536a1ecb220f1330719f3e3973a81ab0bBob Wilson        else if (ArgType->isSubClassOf("LLVMTruncatedElementVectorType"))
348bc03979536a1ecb220f1330719f3e3973a81ab0bBob Wilson          OS << "~(TruncatedElementVectorType | " << Number << ")";
349bc03979536a1ecb220f1330719f3e3973a81ab0bBob Wilson        else
350bc03979536a1ecb220f1330719f3e3973a81ab0bBob Wilson          OS << "~" << Number;
3516994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth      } else {
352825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson        MVT::SimpleValueType VT = getValueType(ArgType->getValueAsDef("VT"));
3536994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth        OS << getEnumName(VT);
354cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling
35561fc4cf7aa0b87ceab62082cee8ef5ce3f574ffcBob Wilson        if (EVT(VT).isOverloaded())
35609b1366f3f310b5648aa8cd72ed16b9f19b4c68dBob Wilson          OverloadedTypeIndices.push_back(j);
35709b1366f3f310b5648aa8cd72ed16b9f19b4c68dBob Wilson
358825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson        if (VT == MVT::isVoid && j != 0 && j != je - 1)
359cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling          throw "Var arg type not last argument";
360cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling      }
361cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling    }
362cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling
363cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling    // Emit the parameter types.
364cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling    for (unsigned j = 0, je = ParamTys.size(); j != je; ++j) {
365cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling      Record *ArgType = ParamTys[j];
366cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling      OS << ", ";
367cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling
368cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling      if (ArgType->isSubClassOf("LLVMMatchType")) {
369cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling        unsigned Number = ArgType->getValueAsInt("Number");
37009b1366f3f310b5648aa8cd72ed16b9f19b4c68dBob Wilson        assert(Number < OverloadedTypeIndices.size() &&
37109b1366f3f310b5648aa8cd72ed16b9f19b4c68dBob Wilson               "Invalid matching number!");
37209b1366f3f310b5648aa8cd72ed16b9f19b4c68dBob Wilson        Number = OverloadedTypeIndices[Number];
373bc03979536a1ecb220f1330719f3e3973a81ab0bBob Wilson        if (ArgType->isSubClassOf("LLVMExtendedElementVectorType"))
374bc03979536a1ecb220f1330719f3e3973a81ab0bBob Wilson          OS << "~(ExtendedElementVectorType | " << Number << ")";
375bc03979536a1ecb220f1330719f3e3973a81ab0bBob Wilson        else if (ArgType->isSubClassOf("LLVMTruncatedElementVectorType"))
376bc03979536a1ecb220f1330719f3e3973a81ab0bBob Wilson          OS << "~(TruncatedElementVectorType | " << Number << ")";
377bc03979536a1ecb220f1330719f3e3973a81ab0bBob Wilson        else
378bc03979536a1ecb220f1330719f3e3973a81ab0bBob Wilson          OS << "~" << Number;
379cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling      } else {
380825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson        MVT::SimpleValueType VT = getValueType(ArgType->getValueAsDef("VT"));
381cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling        OS << getEnumName(VT);
382cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling
38361fc4cf7aa0b87ceab62082cee8ef5ce3f574ffcBob Wilson        if (EVT(VT).isOverloaded())
38409b1366f3f310b5648aa8cd72ed16b9f19b4c68dBob Wilson          OverloadedTypeIndices.push_back(j + RetTys.size());
38509b1366f3f310b5648aa8cd72ed16b9f19b4c68dBob Wilson
386825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson        if (VT == MVT::isVoid && j != 0 && j != je - 1)
38795d97b90e8427255c8298f5d3a1ab605af62aab4Jim Laskey          throw "Var arg type not last argument";
38895d97b90e8427255c8298f5d3a1ab605af62aab4Jim Laskey      }
38995d97b90e8427255c8298f5d3a1ab605af62aab4Jim Laskey    }
39095d97b90e8427255c8298f5d3a1ab605af62aab4Jim Laskey
3916994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth    OS << ");\n";
392f97a00e681c7a526d49759d0d1b9d327cbf6c04aChris Lattner    OS << "    break;\n";
393f97a00e681c7a526d49759d0d1b9d327cbf6c04aChris Lattner  }
394f97a00e681c7a526d49759d0d1b9d327cbf6c04aChris Lattner  OS << "  }\n";
395f97a00e681c7a526d49759d0d1b9d327cbf6c04aChris Lattner  OS << "#endif\n\n";
3969b843b249462980ae4630dc37d1bcccde884a5a7Chris Lattner}
3979b843b249462980ae4630dc37d1bcccde884a5a7Chris Lattner
39895af592a631f403e1458ec1155f89fc31011572cJim Laskeyvoid IntrinsicEmitter::EmitGenerator(const std::vector<CodeGenIntrinsic> &Ints,
3991a55180238dbcf11113f610aea010447e51f595bDaniel Dunbar                                     raw_ostream &OS) {
40095af592a631f403e1458ec1155f89fc31011572cJim Laskey  OS << "// Code for generating Intrinsic function declarations.\n";
40195af592a631f403e1458ec1155f89fc31011572cJim Laskey  OS << "#ifdef GET_INTRINSIC_GENERATOR\n";
40295af592a631f403e1458ec1155f89fc31011572cJim Laskey  OS << "  switch (id) {\n";
40395af592a631f403e1458ec1155f89fc31011572cJim Laskey  OS << "  default: assert(0 && \"Invalid intrinsic!\");\n";
40495af592a631f403e1458ec1155f89fc31011572cJim Laskey
40595af592a631f403e1458ec1155f89fc31011572cJim Laskey  // Similar to GET_INTRINSIC_VERIFIER, batch up cases that have identical
40695af592a631f403e1458ec1155f89fc31011572cJim Laskey  // types.
407cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling  typedef std::map<RecPair, std::vector<unsigned>, RecordListComparator> MapTy;
40895af592a631f403e1458ec1155f89fc31011572cJim Laskey  MapTy UniqueArgInfos;
40995af592a631f403e1458ec1155f89fc31011572cJim Laskey
41095af592a631f403e1458ec1155f89fc31011572cJim Laskey  // Compute the unique argument type info.
41195af592a631f403e1458ec1155f89fc31011572cJim Laskey  for (unsigned i = 0, e = Ints.size(); i != e; ++i)
412cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling    UniqueArgInfos[make_pair(Ints[i].IS.RetTypeDefs,
413cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling                             Ints[i].IS.ParamTypeDefs)].push_back(i);
41495af592a631f403e1458ec1155f89fc31011572cJim Laskey
41595af592a631f403e1458ec1155f89fc31011572cJim Laskey  // Loop through the array, emitting one generator for each batch.
41649de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen  std::string IntrinsicStr = TargetPrefix + "Intrinsic::";
41749de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen
41895af592a631f403e1458ec1155f89fc31011572cJim Laskey  for (MapTy::iterator I = UniqueArgInfos.begin(),
41995af592a631f403e1458ec1155f89fc31011572cJim Laskey       E = UniqueArgInfos.end(); I != E; ++I) {
420cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling    for (unsigned i = 0, e = I->second.size(); i != e; ++i)
42149de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen      OS << "  case " << IntrinsicStr << Ints[I->second[i]].EnumName
42249de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen         << ":\t\t// " << Ints[I->second[i]].Name << "\n";
42395af592a631f403e1458ec1155f89fc31011572cJim Laskey
424cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling    const RecPair &ArgTypes = I->first;
425cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling    const std::vector<Record*> &RetTys = ArgTypes.first;
426cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling    const std::vector<Record*> &ParamTys = ArgTypes.second;
427cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling
428cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling    unsigned N = ParamTys.size();
42995af592a631f403e1458ec1155f89fc31011572cJim Laskey
4306994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth    if (N > 1 &&
431825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson        getValueType(ParamTys[N - 1]->getValueAsDef("VT")) == MVT::isVoid) {
43295af592a631f403e1458ec1155f89fc31011572cJim Laskey      OS << "    IsVarArg = true;\n";
43395af592a631f403e1458ec1155f89fc31011572cJim Laskey      --N;
43495af592a631f403e1458ec1155f89fc31011572cJim Laskey    }
435cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling
43684c614d1ac671b1a5524169f20028f51c30be728Reid Spencer    unsigned ArgNo = 0;
43795af592a631f403e1458ec1155f89fc31011572cJim Laskey    OS << "    ResultTy = ";
438cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling    EmitTypeGenerate(OS, RetTys, ArgNo);
43995af592a631f403e1458ec1155f89fc31011572cJim Laskey    OS << ";\n";
44095af592a631f403e1458ec1155f89fc31011572cJim Laskey
441cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling    for (unsigned j = 0; j != N; ++j) {
44295af592a631f403e1458ec1155f89fc31011572cJim Laskey      OS << "    ArgTys.push_back(";
443cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling      EmitTypeGenerate(OS, ParamTys[j], ArgNo);
44495af592a631f403e1458ec1155f89fc31011572cJim Laskey      OS << ");\n";
44595af592a631f403e1458ec1155f89fc31011572cJim Laskey    }
446cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling
44795af592a631f403e1458ec1155f89fc31011572cJim Laskey    OS << "    break;\n";
44895af592a631f403e1458ec1155f89fc31011572cJim Laskey  }
449cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling
45095af592a631f403e1458ec1155f89fc31011572cJim Laskey  OS << "  }\n";
45195af592a631f403e1458ec1155f89fc31011572cJim Laskey  OS << "#endif\n\n";
45295af592a631f403e1458ec1155f89fc31011572cJim Laskey}
45395af592a631f403e1458ec1155f89fc31011572cJim Laskey
454048ffb239c282277959463c61200b86e2380cb84Chris Lattner/// EmitAttributes - This emits the Intrinsic::getAttributes method.
4554e5f35973c1bc56cce14d44c6f8f4ad1e9f1a438Chris Lattnervoid IntrinsicEmitter::
4561a55180238dbcf11113f610aea010447e51f595bDaniel DunbarEmitAttributes(const std::vector<CodeGenIntrinsic> &Ints, raw_ostream &OS) {
457a3355ffb3d30d19d226bbb75707991c60f236e37Duncan Sands  OS << "// Add parameter attributes that are not common to all intrinsics.\n";
458a3355ffb3d30d19d226bbb75707991c60f236e37Duncan Sands  OS << "#ifdef GET_INTRINSIC_ATTRIBUTES\n";
45949de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen  if (TargetOnly)
46049de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen    OS << "static AttrListPtr getAttributes(" << TargetPrefix
46149de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen       << "Intrinsic::ID id) {";
46249de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen  else
46349de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen    OS << "AttrListPtr Intrinsic::getAttributes(ID id) {";
464048ffb239c282277959463c61200b86e2380cb84Chris Lattner  OS << "  // No intrinsic can throw exceptions.\n";
465048ffb239c282277959463c61200b86e2380cb84Chris Lattner  OS << "  Attributes Attr = Attribute::NoUnwind;\n";
466a3355ffb3d30d19d226bbb75707991c60f236e37Duncan Sands  OS << "  switch (id) {\n";
4677056de375d898d9d9ecc17e170632d91d18be4a8Chris Lattner  OS << "  default: break;\n";
46810dae94be2ccb187bd4e3da53771be54057acd6cChris Lattner  unsigned MaxArgAttrs = 0;
4697056de375d898d9d9ecc17e170632d91d18be4a8Chris Lattner  for (unsigned i = 0, e = Ints.size(); i != e; ++i) {
47010dae94be2ccb187bd4e3da53771be54057acd6cChris Lattner    MaxArgAttrs =
47110dae94be2ccb187bd4e3da53771be54057acd6cChris Lattner      std::max(MaxArgAttrs, unsigned(Ints[i].ArgumentAttributes.size()));
4727056de375d898d9d9ecc17e170632d91d18be4a8Chris Lattner    switch (Ints[i].ModRef) {
4737056de375d898d9d9ecc17e170632d91d18be4a8Chris Lattner    default: break;
4747056de375d898d9d9ecc17e170632d91d18be4a8Chris Lattner    case CodeGenIntrinsic::NoMem:
47549de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen      OS << "  case " << TargetPrefix << "Intrinsic::" << Ints[i].EnumName
47649de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen         << ":\n";
4777056de375d898d9d9ecc17e170632d91d18be4a8Chris Lattner      break;
4787056de375d898d9d9ecc17e170632d91d18be4a8Chris Lattner    }
4797056de375d898d9d9ecc17e170632d91d18be4a8Chris Lattner  }
4800598866c052147c31b808391f58434ce3dbfb838Devang Patel  OS << "    Attr |= Attribute::ReadNone; // These do not access memory.\n";
481a3355ffb3d30d19d226bbb75707991c60f236e37Duncan Sands  OS << "    break;\n";
4824e5f35973c1bc56cce14d44c6f8f4ad1e9f1a438Chris Lattner  for (unsigned i = 0, e = Ints.size(); i != e; ++i) {
4834e5f35973c1bc56cce14d44c6f8f4ad1e9f1a438Chris Lattner    switch (Ints[i].ModRef) {
484022f64fbbc4669623e79b805379266fed519017dChris Lattner    default: break;
485022f64fbbc4669623e79b805379266fed519017dChris Lattner    case CodeGenIntrinsic::ReadArgMem:
486022f64fbbc4669623e79b805379266fed519017dChris Lattner    case CodeGenIntrinsic::ReadMem:
48749de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen      OS << "  case " << TargetPrefix << "Intrinsic::" << Ints[i].EnumName
48849de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen         << ":\n";
489022f64fbbc4669623e79b805379266fed519017dChris Lattner      break;
4904e5f35973c1bc56cce14d44c6f8f4ad1e9f1a438Chris Lattner    }
4914e5f35973c1bc56cce14d44c6f8f4ad1e9f1a438Chris Lattner  }
4920598866c052147c31b808391f58434ce3dbfb838Devang Patel  OS << "    Attr |= Attribute::ReadOnly; // These do not write memory.\n";
493a3355ffb3d30d19d226bbb75707991c60f236e37Duncan Sands  OS << "    break;\n";
4944e5f35973c1bc56cce14d44c6f8f4ad1e9f1a438Chris Lattner  OS << "  }\n";
49510dae94be2ccb187bd4e3da53771be54057acd6cChris Lattner  OS << "  AttributeWithIndex AWI[" << MaxArgAttrs+1 << "];\n";
496d4a2700fdc5bc8ac50084fcb39155e01e86168d5Chris Lattner  OS << "  unsigned NumAttrs = 0;\n";
49710dae94be2ccb187bd4e3da53771be54057acd6cChris Lattner  OS << "  switch (id) {\n";
49810dae94be2ccb187bd4e3da53771be54057acd6cChris Lattner  OS << "  default: break;\n";
49910dae94be2ccb187bd4e3da53771be54057acd6cChris Lattner
50010dae94be2ccb187bd4e3da53771be54057acd6cChris Lattner  // Add argument attributes for any intrinsics that have them.
50110dae94be2ccb187bd4e3da53771be54057acd6cChris Lattner  for (unsigned i = 0, e = Ints.size(); i != e; ++i) {
50210dae94be2ccb187bd4e3da53771be54057acd6cChris Lattner    if (Ints[i].ArgumentAttributes.empty()) continue;
50310dae94be2ccb187bd4e3da53771be54057acd6cChris Lattner
50449de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen    OS << "  case " << TargetPrefix << "Intrinsic::" << Ints[i].EnumName
50549de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen       << ":\n";
50610dae94be2ccb187bd4e3da53771be54057acd6cChris Lattner
50710dae94be2ccb187bd4e3da53771be54057acd6cChris Lattner    std::vector<std::pair<unsigned, CodeGenIntrinsic::ArgAttribute> > ArgAttrs =
50810dae94be2ccb187bd4e3da53771be54057acd6cChris Lattner      Ints[i].ArgumentAttributes;
50910dae94be2ccb187bd4e3da53771be54057acd6cChris Lattner    // Sort by argument index.
51010dae94be2ccb187bd4e3da53771be54057acd6cChris Lattner    std::sort(ArgAttrs.begin(), ArgAttrs.end());
51110dae94be2ccb187bd4e3da53771be54057acd6cChris Lattner
51210dae94be2ccb187bd4e3da53771be54057acd6cChris Lattner    unsigned NumArgsWithAttrs = 0;
51310dae94be2ccb187bd4e3da53771be54057acd6cChris Lattner
514d4a2700fdc5bc8ac50084fcb39155e01e86168d5Chris Lattner    while (!ArgAttrs.empty()) {
515d4a2700fdc5bc8ac50084fcb39155e01e86168d5Chris Lattner      unsigned ArgNo = ArgAttrs[0].first;
516d4a2700fdc5bc8ac50084fcb39155e01e86168d5Chris Lattner
517d4a2700fdc5bc8ac50084fcb39155e01e86168d5Chris Lattner      OS << "    AWI[" << NumArgsWithAttrs++ << "] = AttributeWithIndex::get("
518d4a2700fdc5bc8ac50084fcb39155e01e86168d5Chris Lattner         << ArgNo+1 << ", 0";
519d4a2700fdc5bc8ac50084fcb39155e01e86168d5Chris Lattner
520d4a2700fdc5bc8ac50084fcb39155e01e86168d5Chris Lattner      while (!ArgAttrs.empty() && ArgAttrs[0].first == ArgNo) {
521d4a2700fdc5bc8ac50084fcb39155e01e86168d5Chris Lattner        switch (ArgAttrs[0].second) {
522d4a2700fdc5bc8ac50084fcb39155e01e86168d5Chris Lattner        default: assert(0 && "Unknown arg attribute");
523d4a2700fdc5bc8ac50084fcb39155e01e86168d5Chris Lattner        case CodeGenIntrinsic::NoCapture:
524d4a2700fdc5bc8ac50084fcb39155e01e86168d5Chris Lattner          OS << "|Attribute::NoCapture";
525d4a2700fdc5bc8ac50084fcb39155e01e86168d5Chris Lattner          break;
526d4a2700fdc5bc8ac50084fcb39155e01e86168d5Chris Lattner        }
527d4a2700fdc5bc8ac50084fcb39155e01e86168d5Chris Lattner        ArgAttrs.erase(ArgAttrs.begin());
528d4a2700fdc5bc8ac50084fcb39155e01e86168d5Chris Lattner      }
529d4a2700fdc5bc8ac50084fcb39155e01e86168d5Chris Lattner      OS << ");\n";
530d4a2700fdc5bc8ac50084fcb39155e01e86168d5Chris Lattner    }
53110dae94be2ccb187bd4e3da53771be54057acd6cChris Lattner
532d4a2700fdc5bc8ac50084fcb39155e01e86168d5Chris Lattner    OS << "    NumAttrs = " << NumArgsWithAttrs << ";\n";
53310dae94be2ccb187bd4e3da53771be54057acd6cChris Lattner    OS << "    break;\n";
53410dae94be2ccb187bd4e3da53771be54057acd6cChris Lattner  }
53510dae94be2ccb187bd4e3da53771be54057acd6cChris Lattner
53610dae94be2ccb187bd4e3da53771be54057acd6cChris Lattner  OS << "  }\n";
537d4a2700fdc5bc8ac50084fcb39155e01e86168d5Chris Lattner  OS << "  AWI[NumAttrs] = AttributeWithIndex::get(~0, Attr);\n";
538d4a2700fdc5bc8ac50084fcb39155e01e86168d5Chris Lattner  OS << "  return AttrListPtr::get(AWI, NumAttrs+1);\n";
539048ffb239c282277959463c61200b86e2380cb84Chris Lattner  OS << "}\n";
540d4a2700fdc5bc8ac50084fcb39155e01e86168d5Chris Lattner  OS << "#endif // GET_INTRINSIC_ATTRIBUTES\n\n";
5414e5f35973c1bc56cce14d44c6f8f4ad1e9f1a438Chris Lattner}
542022f64fbbc4669623e79b805379266fed519017dChris Lattner
543d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands/// EmitModRefBehavior - Determine intrinsic alias analysis mod/ref behavior.
544d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sandsvoid IntrinsicEmitter::
5451a55180238dbcf11113f610aea010447e51f595bDaniel DunbarEmitModRefBehavior(const std::vector<CodeGenIntrinsic> &Ints, raw_ostream &OS){
546d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands  OS << "// Determine intrinsic alias analysis mod/ref behavior.\n";
547d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands  OS << "#ifdef GET_INTRINSIC_MODREF_BEHAVIOR\n";
5487c422ac216fe39fc9c402a704cf296cca9dc5b22Duncan Sands  OS << "switch (iid) {\n";
549d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands  OS << "default:\n    return UnknownModRefBehavior;\n";
550d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands  for (unsigned i = 0, e = Ints.size(); i != e; ++i) {
5517365c091f92db5e68c98d7faedc6c34e1bbbc898Dan Gohman    if (Ints[i].ModRef == CodeGenIntrinsic::ReadWriteMem)
552d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands      continue;
553d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands    OS << "case " << TargetPrefix << "Intrinsic::" << Ints[i].EnumName
554d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands      << ":\n";
555d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands    switch (Ints[i].ModRef) {
556d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands    default:
557d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands      assert(false && "Unknown Mod/Ref type!");
558d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands    case CodeGenIntrinsic::NoMem:
559d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands      OS << "  return DoesNotAccessMemory;\n";
560d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands      break;
561d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands    case CodeGenIntrinsic::ReadArgMem:
562d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands    case CodeGenIntrinsic::ReadMem:
563d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands      OS << "  return OnlyReadsMemory;\n";
564d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands      break;
5657365c091f92db5e68c98d7faedc6c34e1bbbc898Dan Gohman    case CodeGenIntrinsic::ReadWriteArgMem:
566d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands      OS << "  return AccessesArguments;\n";
567d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands      break;
568d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands    }
569d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands  }
570d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands  OS << "}\n";
571d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands  OS << "#endif // GET_INTRINSIC_MODREF_BEHAVIOR\n\n";
572d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands}
573d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands
574022f64fbbc4669623e79b805379266fed519017dChris Lattnervoid IntrinsicEmitter::
5751a55180238dbcf11113f610aea010447e51f595bDaniel DunbarEmitGCCBuiltinList(const std::vector<CodeGenIntrinsic> &Ints, raw_ostream &OS){
576022f64fbbc4669623e79b805379266fed519017dChris Lattner  OS << "// Get the GCC builtin that corresponds to an LLVM intrinsic.\n";
577022f64fbbc4669623e79b805379266fed519017dChris Lattner  OS << "#ifdef GET_GCC_BUILTIN_NAME\n";
578022f64fbbc4669623e79b805379266fed519017dChris Lattner  OS << "  switch (F->getIntrinsicID()) {\n";
579022f64fbbc4669623e79b805379266fed519017dChris Lattner  OS << "  default: BuiltinName = \"\"; break;\n";
580022f64fbbc4669623e79b805379266fed519017dChris Lattner  for (unsigned i = 0, e = Ints.size(); i != e; ++i) {
581022f64fbbc4669623e79b805379266fed519017dChris Lattner    if (!Ints[i].GCCBuiltinName.empty()) {
582022f64fbbc4669623e79b805379266fed519017dChris Lattner      OS << "  case Intrinsic::" << Ints[i].EnumName << ": BuiltinName = \""
583022f64fbbc4669623e79b805379266fed519017dChris Lattner         << Ints[i].GCCBuiltinName << "\"; break;\n";
584022f64fbbc4669623e79b805379266fed519017dChris Lattner    }
585022f64fbbc4669623e79b805379266fed519017dChris Lattner  }
586022f64fbbc4669623e79b805379266fed519017dChris Lattner  OS << "  }\n";
587022f64fbbc4669623e79b805379266fed519017dChris Lattner  OS << "#endif\n\n";
588767a25b8788b5e313c99c16b4d359478432901f5Reid Spencer}
5893f8b8913bc9cb232871445eefa8654caf7f9986fChris Lattner
590331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner/// EmitTargetBuiltins - All of the builtins in the specified map are for the
591331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner/// same target, and we already checked it.
592331bf92fb51f058672144681b3d0e67d30f5699fChris Lattnerstatic void EmitTargetBuiltins(const std::map<std::string, std::string> &BIM,
59349de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen                               const std::string &TargetPrefix,
5941a55180238dbcf11113f610aea010447e51f595bDaniel Dunbar                               raw_ostream &OS) {
595331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner
596298b176559d5c76d7d9f7fdd06429a75892de043Chris Lattner  std::vector<StringMatcher::StringPair> Results;
597331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner
598298b176559d5c76d7d9f7fdd06429a75892de043Chris Lattner  for (std::map<std::string, std::string>::const_iterator I = BIM.begin(),
599298b176559d5c76d7d9f7fdd06429a75892de043Chris Lattner       E = BIM.end(); I != E; ++I) {
600298b176559d5c76d7d9f7fdd06429a75892de043Chris Lattner    std::string ResultCode =
601298b176559d5c76d7d9f7fdd06429a75892de043Chris Lattner    "return " + TargetPrefix + "Intrinsic::" + I->second + ";";
602298b176559d5c76d7d9f7fdd06429a75892de043Chris Lattner    Results.push_back(StringMatcher::StringPair(I->first, ResultCode));
603331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner  }
604298b176559d5c76d7d9f7fdd06429a75892de043Chris Lattner
605298b176559d5c76d7d9f7fdd06429a75892de043Chris Lattner  StringMatcher("BuiltinName", Results, OS).Emit();
606331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner}
607331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner
608331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner
6093f8b8913bc9cb232871445eefa8654caf7f9986fChris Lattnervoid IntrinsicEmitter::
6103f8b8913bc9cb232871445eefa8654caf7f9986fChris LattnerEmitIntrinsicToGCCBuiltinMap(const std::vector<CodeGenIntrinsic> &Ints,
6111a55180238dbcf11113f610aea010447e51f595bDaniel Dunbar                             raw_ostream &OS) {
612fa0fba1c546091c485e5513eadeef181dda370abChris Lattner  typedef std::map<std::string, std::map<std::string, std::string> > BIMTy;
6133f8b8913bc9cb232871445eefa8654caf7f9986fChris Lattner  BIMTy BuiltinMap;
6143f8b8913bc9cb232871445eefa8654caf7f9986fChris Lattner  for (unsigned i = 0, e = Ints.size(); i != e; ++i) {
6153f8b8913bc9cb232871445eefa8654caf7f9986fChris Lattner    if (!Ints[i].GCCBuiltinName.empty()) {
616fa0fba1c546091c485e5513eadeef181dda370abChris Lattner      // Get the map for this target prefix.
617fa0fba1c546091c485e5513eadeef181dda370abChris Lattner      std::map<std::string, std::string> &BIM =BuiltinMap[Ints[i].TargetPrefix];
618fa0fba1c546091c485e5513eadeef181dda370abChris Lattner
619fa0fba1c546091c485e5513eadeef181dda370abChris Lattner      if (!BIM.insert(std::make_pair(Ints[i].GCCBuiltinName,
620fa0fba1c546091c485e5513eadeef181dda370abChris Lattner                                     Ints[i].EnumName)).second)
6213f8b8913bc9cb232871445eefa8654caf7f9986fChris Lattner        throw "Intrinsic '" + Ints[i].TheDef->getName() +
6223f8b8913bc9cb232871445eefa8654caf7f9986fChris Lattner              "': duplicate GCC builtin name!";
6233f8b8913bc9cb232871445eefa8654caf7f9986fChris Lattner    }
6243f8b8913bc9cb232871445eefa8654caf7f9986fChris Lattner  }
6253f8b8913bc9cb232871445eefa8654caf7f9986fChris Lattner
6263f8b8913bc9cb232871445eefa8654caf7f9986fChris Lattner  OS << "// Get the LLVM intrinsic that corresponds to a GCC builtin.\n";
6273f8b8913bc9cb232871445eefa8654caf7f9986fChris Lattner  OS << "// This is used by the C front-end.  The GCC builtin name is passed\n";
6283f8b8913bc9cb232871445eefa8654caf7f9986fChris Lattner  OS << "// in as BuiltinName, and a target prefix (e.g. 'ppc') is passed\n";
6293f8b8913bc9cb232871445eefa8654caf7f9986fChris Lattner  OS << "// in as TargetPrefix.  The result is assigned to 'IntrinsicID'.\n";
6303f8b8913bc9cb232871445eefa8654caf7f9986fChris Lattner  OS << "#ifdef GET_LLVM_INTRINSIC_FOR_GCC_BUILTIN\n";
63149de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen
63249de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen  if (TargetOnly) {
63349de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen    OS << "static " << TargetPrefix << "Intrinsic::ID "
63449de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen       << "getIntrinsicForGCCBuiltin(const char "
635298b176559d5c76d7d9f7fdd06429a75892de043Chris Lattner       << "*TargetPrefixStr, const char *BuiltinNameStr) {\n";
63649de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen  } else {
63749de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen    OS << "Intrinsic::ID Intrinsic::getIntrinsicForGCCBuiltin(const char "
638298b176559d5c76d7d9f7fdd06429a75892de043Chris Lattner       << "*TargetPrefixStr, const char *BuiltinNameStr) {\n";
63949de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen  }
64049de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen
641298b176559d5c76d7d9f7fdd06429a75892de043Chris Lattner  OS << "  StringRef BuiltinName(BuiltinNameStr);\n";
642298b176559d5c76d7d9f7fdd06429a75892de043Chris Lattner  OS << "  StringRef TargetPrefix(TargetPrefixStr);\n\n";
643331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner
6443f8b8913bc9cb232871445eefa8654caf7f9986fChris Lattner  // Note: this could emit significantly better code if we cared.
6453f8b8913bc9cb232871445eefa8654caf7f9986fChris Lattner  for (BIMTy::iterator I = BuiltinMap.begin(), E = BuiltinMap.end();I != E;++I){
646fa0fba1c546091c485e5513eadeef181dda370abChris Lattner    OS << "  ";
647fa0fba1c546091c485e5513eadeef181dda370abChris Lattner    if (!I->first.empty())
648298b176559d5c76d7d9f7fdd06429a75892de043Chris Lattner      OS << "if (TargetPrefix == \"" << I->first << "\") ";
649fa0fba1c546091c485e5513eadeef181dda370abChris Lattner    else
650fa0fba1c546091c485e5513eadeef181dda370abChris Lattner      OS << "/* Target Independent Builtins */ ";
651fa0fba1c546091c485e5513eadeef181dda370abChris Lattner    OS << "{\n";
652fa0fba1c546091c485e5513eadeef181dda370abChris Lattner
653fa0fba1c546091c485e5513eadeef181dda370abChris Lattner    // Emit the comparisons for this target prefix.
65449de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen    EmitTargetBuiltins(I->second, TargetPrefix, OS);
655fa0fba1c546091c485e5513eadeef181dda370abChris Lattner    OS << "  }\n";
6563f8b8913bc9cb232871445eefa8654caf7f9986fChris Lattner  }
657298b176559d5c76d7d9f7fdd06429a75892de043Chris Lattner  OS << "  return ";
658298b176559d5c76d7d9f7fdd06429a75892de043Chris Lattner  if (!TargetPrefix.empty())
659298b176559d5c76d7d9f7fdd06429a75892de043Chris Lattner    OS << "(" << TargetPrefix << "Intrinsic::ID)";
660298b176559d5c76d7d9f7fdd06429a75892de043Chris Lattner  OS << "Intrinsic::not_intrinsic;\n";
66149de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen  OS << "}\n";
6623f8b8913bc9cb232871445eefa8654caf7f9986fChris Lattner  OS << "#endif\n\n";
6633f8b8913bc9cb232871445eefa8654caf7f9986fChris Lattner}
664