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"
16298b176559d5c76d7d9f7fdd06429a75892de043Chris Lattner#include "StringMatcher.h"
177c788888872233748da10a8177a9a1eb176c1bc8Peter Collingbourne#include "llvm/TableGen/Record.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
603f8b8913bc9cb232871445eefa8654caf7f9986fChris Lattner  // Emit code to translate GCC builtins into LLVM intrinsics.
613f8b8913bc9cb232871445eefa8654caf7f9986fChris Lattner  EmitIntrinsicToGCCBuiltinMap(Ints, OS);
627d9663c70b3300070298d716dba6e6f6ce2d1e3eDouglas Gregor
637d9663c70b3300070298d716dba6e6f6ce2d1e3eDouglas Gregor  EmitSuffix(OS);
647d9663c70b3300070298d716dba6e6f6ce2d1e3eDouglas Gregor}
657d9663c70b3300070298d716dba6e6f6ce2d1e3eDouglas Gregor
667d9663c70b3300070298d716dba6e6f6ce2d1e3eDouglas Gregorvoid IntrinsicEmitter::EmitPrefix(raw_ostream &OS) {
677d9663c70b3300070298d716dba6e6f6ce2d1e3eDouglas Gregor  OS << "// VisualStudio defines setjmp as _setjmp\n"
681f4096054367cab3acab3a74c719ef6d3090606aMichael J. Spencer        "#if defined(_MSC_VER) && defined(setjmp) && \\\n"
691f4096054367cab3acab3a74c719ef6d3090606aMichael J. Spencer        "                         !defined(setjmp_undefined_for_msvc)\n"
7008047f616977f204df6054c481601f2237cc308dMichael J. Spencer        "#  pragma push_macro(\"setjmp\")\n"
7108047f616977f204df6054c481601f2237cc308dMichael J. Spencer        "#  undef setjmp\n"
721f4096054367cab3acab3a74c719ef6d3090606aMichael J. Spencer        "#  define setjmp_undefined_for_msvc\n"
737d9663c70b3300070298d716dba6e6f6ce2d1e3eDouglas Gregor        "#endif\n\n";
747d9663c70b3300070298d716dba6e6f6ce2d1e3eDouglas Gregor}
757d9663c70b3300070298d716dba6e6f6ce2d1e3eDouglas Gregor
767d9663c70b3300070298d716dba6e6f6ce2d1e3eDouglas Gregorvoid IntrinsicEmitter::EmitSuffix(raw_ostream &OS) {
771f4096054367cab3acab3a74c719ef6d3090606aMichael J. Spencer  OS << "#if defined(_MSC_VER) && defined(setjmp_undefined_for_msvc)\n"
787d9663c70b3300070298d716dba6e6f6ce2d1e3eDouglas Gregor        "// let's return it to _setjmp state\n"
7908047f616977f204df6054c481601f2237cc308dMichael J. Spencer        "#  pragma pop_macro(\"setjmp\")\n"
801f4096054367cab3acab3a74c719ef6d3090606aMichael J. Spencer        "#  undef setjmp_undefined_for_msvc\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) {
100cc67c75b67d22653ea9380020e9a40381233901dChris Lattner  // Build a 'first character of function name' -> intrinsic # mapping.
101cc67c75b67d22653ea9380020e9a40381233901dChris Lattner  std::map<char, std::vector<unsigned> > IntMapping;
1029b843b249462980ae4630dc37d1bcccde884a5a7Chris Lattner  for (unsigned i = 0, e = Ints.size(); i != e; ++i)
103cc67c75b67d22653ea9380020e9a40381233901dChris Lattner    IntMapping[Ints[i].Name[5]].push_back(i);
104cc67c75b67d22653ea9380020e9a40381233901dChris Lattner
1059b843b249462980ae4630dc37d1bcccde884a5a7Chris Lattner  OS << "// Function name -> enum value recognizer code.\n";
1069b843b249462980ae4630dc37d1bcccde884a5a7Chris Lattner  OS << "#ifdef GET_FUNCTION_RECOGNIZER\n";
107cc67c75b67d22653ea9380020e9a40381233901dChris Lattner  OS << "  StringRef NameR(Name+6, Len-6);   // Skip over 'llvm.'\n";
108cc67c75b67d22653ea9380020e9a40381233901dChris Lattner  OS << "  switch (Name[5]) {                  // Dispatch on first letter.\n";
109cc67c75b67d22653ea9380020e9a40381233901dChris Lattner  OS << "  default: break;\n";
110cc67c75b67d22653ea9380020e9a40381233901dChris Lattner  // Emit the intrinsic matching stuff by first letter.
111cc67c75b67d22653ea9380020e9a40381233901dChris Lattner  for (std::map<char, std::vector<unsigned> >::iterator I = IntMapping.begin(),
1129b843b249462980ae4630dc37d1bcccde884a5a7Chris Lattner       E = IntMapping.end(); I != E; ++I) {
113cc67c75b67d22653ea9380020e9a40381233901dChris Lattner    OS << "  case '" << I->first << "':\n";
114cc67c75b67d22653ea9380020e9a40381233901dChris Lattner    std::vector<unsigned> &IntList = I->second;
115cc67c75b67d22653ea9380020e9a40381233901dChris Lattner
116cc67c75b67d22653ea9380020e9a40381233901dChris Lattner    // Emit all the overloaded intrinsics first, build a table of the
117cc67c75b67d22653ea9380020e9a40381233901dChris Lattner    // non-overloaded ones.
118cc67c75b67d22653ea9380020e9a40381233901dChris Lattner    std::vector<StringMatcher::StringPair> MatchTable;
1199b843b249462980ae4630dc37d1bcccde884a5a7Chris Lattner
120cc67c75b67d22653ea9380020e9a40381233901dChris Lattner    for (unsigned i = 0, e = IntList.size(); i != e; ++i) {
121cc67c75b67d22653ea9380020e9a40381233901dChris Lattner      unsigned IntNo = IntList[i];
122cc67c75b67d22653ea9380020e9a40381233901dChris Lattner      std::string Result = "return " + TargetPrefix + "Intrinsic::" +
123cc67c75b67d22653ea9380020e9a40381233901dChris Lattner        Ints[IntNo].EnumName + ";";
124cc67c75b67d22653ea9380020e9a40381233901dChris Lattner
125cc67c75b67d22653ea9380020e9a40381233901dChris Lattner      if (!Ints[IntNo].isOverloaded) {
126cc67c75b67d22653ea9380020e9a40381233901dChris Lattner        MatchTable.push_back(std::make_pair(Ints[IntNo].Name.substr(6),Result));
127cc67c75b67d22653ea9380020e9a40381233901dChris Lattner        continue;
128cc67c75b67d22653ea9380020e9a40381233901dChris Lattner      }
129cc67c75b67d22653ea9380020e9a40381233901dChris Lattner
130cc67c75b67d22653ea9380020e9a40381233901dChris Lattner      // For overloaded intrinsics, only the prefix needs to match
131cc67c75b67d22653ea9380020e9a40381233901dChris Lattner      std::string TheStr = Ints[IntNo].Name.substr(6);
1322738ff9c22d27ce3e4aee6f250eb68f594db1ce9Chris Lattner      TheStr += '.';  // Require "bswap." instead of bswap.
133cc67c75b67d22653ea9380020e9a40381233901dChris Lattner      OS << "    if (NameR.startswith(\"" << TheStr << "\")) "
134cc67c75b67d22653ea9380020e9a40381233901dChris Lattner         << Result << '\n';
1352738ff9c22d27ce3e4aee6f250eb68f594db1ce9Chris Lattner    }
136cc67c75b67d22653ea9380020e9a40381233901dChris Lattner
137cc67c75b67d22653ea9380020e9a40381233901dChris Lattner    // Emit the matcher logic for the fixed length strings.
138cc67c75b67d22653ea9380020e9a40381233901dChris Lattner    StringMatcher("NameR", MatchTable, OS).Emit(1);
139cc67c75b67d22653ea9380020e9a40381233901dChris Lattner    OS << "    break;  // end of '" << I->first << "' case.\n";
1409b843b249462980ae4630dc37d1bcccde884a5a7Chris Lattner  }
141cc67c75b67d22653ea9380020e9a40381233901dChris Lattner
1429b843b249462980ae4630dc37d1bcccde884a5a7Chris Lattner  OS << "  }\n";
143f97a00e681c7a526d49759d0d1b9d327cbf6c04aChris Lattner  OS << "#endif\n\n";
144f97a00e681c7a526d49759d0d1b9d327cbf6c04aChris Lattner}
145f97a00e681c7a526d49759d0d1b9d327cbf6c04aChris Lattner
146fda6affb95e9f68278cb5cf75dc3fd3406978255Chris Lattnervoid IntrinsicEmitter::
147fda6affb95e9f68278cb5cf75dc3fd3406978255Chris LattnerEmitIntrinsicToNameTable(const std::vector<CodeGenIntrinsic> &Ints,
1481a55180238dbcf11113f610aea010447e51f595bDaniel Dunbar                         raw_ostream &OS) {
149fda6affb95e9f68278cb5cf75dc3fd3406978255Chris Lattner  OS << "// Intrinsic ID to name table\n";
150fda6affb95e9f68278cb5cf75dc3fd3406978255Chris Lattner  OS << "#ifdef GET_INTRINSIC_NAME_TABLE\n";
151fda6affb95e9f68278cb5cf75dc3fd3406978255Chris Lattner  OS << "  // Note that entry #0 is the invalid intrinsic!\n";
152f065a6f711dca09ba36ec8fd3556c4936cdbe621Evan Cheng  for (unsigned i = 0, e = Ints.size(); i != e; ++i)
153f065a6f711dca09ba36ec8fd3556c4936cdbe621Evan Cheng    OS << "  \"" << Ints[i].Name << "\",\n";
154fda6affb95e9f68278cb5cf75dc3fd3406978255Chris Lattner  OS << "#endif\n\n";
155fda6affb95e9f68278cb5cf75dc3fd3406978255Chris Lattner}
156fda6affb95e9f68278cb5cf75dc3fd3406978255Chris Lattner
1570d52ff1f7b993750a74a5d4432273092de9af069Mon P Wangvoid IntrinsicEmitter::
1580d52ff1f7b993750a74a5d4432273092de9af069Mon P WangEmitIntrinsicToOverloadTable(const std::vector<CodeGenIntrinsic> &Ints,
1591a55180238dbcf11113f610aea010447e51f595bDaniel Dunbar                         raw_ostream &OS) {
16036a2138cce66a164f08a36c4c5820b133c4590fdBenjamin Kramer  OS << "// Intrinsic ID to overload bitset\n";
1610d52ff1f7b993750a74a5d4432273092de9af069Mon P Wang  OS << "#ifdef GET_INTRINSIC_OVERLOAD_TABLE\n";
16236a2138cce66a164f08a36c4c5820b133c4590fdBenjamin Kramer  OS << "static const uint8_t OTable[] = {\n";
16336a2138cce66a164f08a36c4c5820b133c4590fdBenjamin Kramer  OS << "  0";
1640d52ff1f7b993750a74a5d4432273092de9af069Mon P Wang  for (unsigned i = 0, e = Ints.size(); i != e; ++i) {
16536a2138cce66a164f08a36c4c5820b133c4590fdBenjamin Kramer    // Add one to the index so we emit a null bit for the invalid #0 intrinsic.
16636a2138cce66a164f08a36c4c5820b133c4590fdBenjamin Kramer    if ((i+1)%8 == 0)
16736a2138cce66a164f08a36c4c5820b133c4590fdBenjamin Kramer      OS << ",\n  0";
1680d52ff1f7b993750a74a5d4432273092de9af069Mon P Wang    if (Ints[i].isOverloaded)
16936a2138cce66a164f08a36c4c5820b133c4590fdBenjamin Kramer      OS << " | (1<<" << (i+1)%8 << ')';
1700d52ff1f7b993750a74a5d4432273092de9af069Mon P Wang  }
17136a2138cce66a164f08a36c4c5820b133c4590fdBenjamin Kramer  OS << "\n};\n\n";
17236a2138cce66a164f08a36c4c5820b133c4590fdBenjamin Kramer  // OTable contains a true bit at the position if the intrinsic is overloaded.
17336a2138cce66a164f08a36c4c5820b133c4590fdBenjamin Kramer  OS << "return (OTable[id/8] & (1 << (id%8))) != 0;\n";
1740d52ff1f7b993750a74a5d4432273092de9af069Mon P Wang  OS << "#endif\n\n";
1750d52ff1f7b993750a74a5d4432273092de9af069Mon P Wang}
1760d52ff1f7b993750a74a5d4432273092de9af069Mon P Wang
177825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Andersonstatic void EmitTypeForValueType(raw_ostream &OS, MVT::SimpleValueType VT) {
178e50ed30282bb5b4a9ed952580523f2dda16215acOwen Anderson  if (EVT(VT).isInteger()) {
179e50ed30282bb5b4a9ed952580523f2dda16215acOwen Anderson    unsigned BitWidth = EVT(VT).getSizeInBits();
1801d0be15f89cb5056e20e2d24faa8d6afb1573bcaOwen Anderson    OS << "IntegerType::get(Context, " << BitWidth << ")";
181825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson  } else if (VT == MVT::Other) {
182825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson    // MVT::OtherVT is used to mean the empty struct type here.
183d7f2a6cb3fbc012763adb42fd967f6fefbb22a37Owen Anderson    OS << "StructType::get(Context)";
184e3376ecd504300ae529c902135f51baffbdc2824Dan Gohman  } else if (VT == MVT::f16) {
185e3376ecd504300ae529c902135f51baffbdc2824Dan Gohman    OS << "Type::getHalfTy(Context)";
186825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson  } else if (VT == MVT::f32) {
1871d0be15f89cb5056e20e2d24faa8d6afb1573bcaOwen Anderson    OS << "Type::getFloatTy(Context)";
188825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson  } else if (VT == MVT::f64) {
1891d0be15f89cb5056e20e2d24faa8d6afb1573bcaOwen Anderson    OS << "Type::getDoubleTy(Context)";
190825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson  } else if (VT == MVT::f80) {
1911d0be15f89cb5056e20e2d24faa8d6afb1573bcaOwen Anderson    OS << "Type::getX86_FP80Ty(Context)";
192825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson  } else if (VT == MVT::f128) {
1931d0be15f89cb5056e20e2d24faa8d6afb1573bcaOwen Anderson    OS << "Type::getFP128Ty(Context)";
194825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson  } else if (VT == MVT::ppcf128) {
1951d0be15f89cb5056e20e2d24faa8d6afb1573bcaOwen Anderson    OS << "Type::getPPC_FP128Ty(Context)";
196825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson  } else if (VT == MVT::isVoid) {
1971d0be15f89cb5056e20e2d24faa8d6afb1573bcaOwen Anderson    OS << "Type::getVoidTy(Context)";
198825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson  } else if (VT == MVT::Metadata) {
1991d0be15f89cb5056e20e2d24faa8d6afb1573bcaOwen Anderson    OS << "Type::getMetadataTy(Context)";
2008be452545a1d3921f006c4d5673f14165ceead82Dale Johannesen  } else if (VT == MVT::x86mmx) {
2018be452545a1d3921f006c4d5673f14165ceead82Dale Johannesen    OS << "Type::getX86_MMXTy(Context)";
2026994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth  } else {
2036994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth    assert(false && "Unsupported ValueType!");
20418faf5d9f7f89130b9e3304965b81e1c70ebb75cChris Lattner  }
20518faf5d9f7f89130b9e3304965b81e1c70ebb75cChris Lattner}
20618faf5d9f7f89130b9e3304965b81e1c70ebb75cChris Lattner
2071a55180238dbcf11113f610aea010447e51f595bDaniel Dunbarstatic void EmitTypeGenerate(raw_ostream &OS, const Record *ArgType,
208cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling                             unsigned &ArgNo);
209cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling
2101a55180238dbcf11113f610aea010447e51f595bDaniel Dunbarstatic void EmitTypeGenerate(raw_ostream &OS,
211cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling                             const std::vector<Record*> &ArgTypes,
212cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling                             unsigned &ArgNo) {
21393dc92e412fd06250e46951bffb6040eca9baebdChris Lattner  if (ArgTypes.empty())
21493dc92e412fd06250e46951bffb6040eca9baebdChris Lattner    return EmitTypeForValueType(OS, MVT::isVoid);
21593dc92e412fd06250e46951bffb6040eca9baebdChris Lattner
21693dc92e412fd06250e46951bffb6040eca9baebdChris Lattner  if (ArgTypes.size() == 1)
21793dc92e412fd06250e46951bffb6040eca9baebdChris Lattner    return EmitTypeGenerate(OS, ArgTypes.front(), ArgNo);
218cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling
219b2318662b6d2e6d9ea9917fd280dde0ba9a938adChris Lattner  OS << "StructType::get(";
220cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling
221cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling  for (std::vector<Record*>::const_iterator
22220072af3b0b22d90afbce769409f4ed822520366Bill Wendling         I = ArgTypes.begin(), E = ArgTypes.end(); I != E; ++I) {
223cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling    EmitTypeGenerate(OS, *I, ArgNo);
22420072af3b0b22d90afbce769409f4ed822520366Bill Wendling    OS << ", ";
22520072af3b0b22d90afbce769409f4ed822520366Bill Wendling  }
226cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling
22720072af3b0b22d90afbce769409f4ed822520366Bill Wendling  OS << " NULL)";
228cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling}
229cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling
2301a55180238dbcf11113f610aea010447e51f595bDaniel Dunbarstatic void EmitTypeGenerate(raw_ostream &OS, const Record *ArgType,
23184c614d1ac671b1a5524169f20028f51c30be728Reid Spencer                             unsigned &ArgNo) {
232825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson  MVT::SimpleValueType VT = getValueType(ArgType->getValueAsDef("VT"));
2336994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth
2346994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth  if (ArgType->isSubClassOf("LLVMMatchType")) {
2356994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth    unsigned Number = ArgType->getValueAsInt("Number");
2366994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth    assert(Number < ArgNo && "Invalid matching number!");
237bc03979536a1ecb220f1330719f3e3973a81ab0bBob Wilson    if (ArgType->isSubClassOf("LLVMExtendedElementVectorType"))
238bc03979536a1ecb220f1330719f3e3973a81ab0bBob Wilson      OS << "VectorType::getExtendedElementVectorType"
239bc03979536a1ecb220f1330719f3e3973a81ab0bBob Wilson         << "(dyn_cast<VectorType>(Tys[" << Number << "]))";
240bc03979536a1ecb220f1330719f3e3973a81ab0bBob Wilson    else if (ArgType->isSubClassOf("LLVMTruncatedElementVectorType"))
241bc03979536a1ecb220f1330719f3e3973a81ab0bBob Wilson      OS << "VectorType::getTruncatedElementVectorType"
242bc03979536a1ecb220f1330719f3e3973a81ab0bBob Wilson         << "(dyn_cast<VectorType>(Tys[" << Number << "]))";
243bc03979536a1ecb220f1330719f3e3973a81ab0bBob Wilson    else
244bc03979536a1ecb220f1330719f3e3973a81ab0bBob Wilson      OS << "Tys[" << Number << "]";
245825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson  } else if (VT == MVT::iAny || VT == MVT::fAny || VT == MVT::vAny) {
24684c614d1ac671b1a5524169f20028f51c30be728Reid Spencer    // NOTE: The ArgNo variable here is not the absolute argument number, it is
24784c614d1ac671b1a5524169f20028f51c30be728Reid Spencer    // the index of the "arbitrary" type in the Tys array passed to the
24884c614d1ac671b1a5524169f20028f51c30be728Reid Spencer    // Intrinsic::getDeclaration function. Consequently, we only want to
2496994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth    // increment it when we actually hit an overloaded type. Getting this wrong
2506994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth    // leads to very subtle bugs!
2516994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth    OS << "Tys[" << ArgNo++ << "]";
252e50ed30282bb5b4a9ed952580523f2dda16215acOwen Anderson  } else if (EVT(VT).isVector()) {
253e50ed30282bb5b4a9ed952580523f2dda16215acOwen Anderson    EVT VVT = VT;
2549d6565a5b1fbc4286d6ee638d8f47a3171a9ed7eReid Spencer    OS << "VectorType::get(";
255825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson    EmitTypeForValueType(OS, VVT.getVectorElementType().getSimpleVT().SimpleTy);
25683ec4b6711980242ef3c55a4fa36b2d7a39c1bfbDuncan Sands    OS << ", " << VVT.getVectorNumElements() << ")";
257825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson  } else if (VT == MVT::iPTR) {
25843ad6b3e0d6ada51e9b23aab3e061187f1f5710cChristopher Lamb    OS << "PointerType::getUnqual(";
259c4de3dec62c3f60ae7297f93c19c799c403c2e9fReid Spencer    EmitTypeGenerate(OS, ArgType->getValueAsDef("ElTy"), ArgNo);
26095af592a631f403e1458ec1155f89fc31011572cJim Laskey    OS << ")";
261825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson  } else if (VT == MVT::iPTRAny) {
262e3b3a7241c01f26613694e53b26b01abf764ddfcMon P Wang    // Make sure the user has passed us an argument type to overload. If not,
263e3b3a7241c01f26613694e53b26b01abf764ddfcMon P Wang    // treat it as an ordinary (not overloaded) intrinsic.
264eb9a85f09e18b3fe88499710404b38d3a9128f62Benjamin Kramer    OS << "(" << ArgNo << " < Tys.size()) ? Tys[" << ArgNo
265e3b3a7241c01f26613694e53b26b01abf764ddfcMon P Wang    << "] : PointerType::getUnqual(";
266e3b3a7241c01f26613694e53b26b01abf764ddfcMon P Wang    EmitTypeGenerate(OS, ArgType->getValueAsDef("ElTy"), ArgNo);
267e3b3a7241c01f26613694e53b26b01abf764ddfcMon P Wang    OS << ")";
268e3b3a7241c01f26613694e53b26b01abf764ddfcMon P Wang    ++ArgNo;
269825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson  } else if (VT == MVT::isVoid) {
2706994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth    if (ArgNo == 0)
2711d0be15f89cb5056e20e2d24faa8d6afb1573bcaOwen Anderson      OS << "Type::getVoidTy(Context)";
2726994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth    else
273825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson      // MVT::isVoid is used to mean varargs here.
2746994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth      OS << "...";
27595af592a631f403e1458ec1155f89fc31011572cJim Laskey  } else {
2766994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth    EmitTypeForValueType(OS, VT);
27795af592a631f403e1458ec1155f89fc31011572cJim Laskey  }
27895af592a631f403e1458ec1155f89fc31011572cJim Laskey}
27995af592a631f403e1458ec1155f89fc31011572cJim Laskey
280da4231f134989af7dc6bd3408821ba573def27b2Jim Grosbach/// RecordListComparator - Provide a deterministic comparator for lists of
281c4d9b240b157efa9301d451ac44c12f6b004db8fChris Lattner/// records.
282c4d9b240b157efa9301d451ac44c12f6b004db8fChris Lattnernamespace {
283cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling  typedef std::pair<std::vector<Record*>, std::vector<Record*> > RecPair;
284c4d9b240b157efa9301d451ac44c12f6b004db8fChris Lattner  struct RecordListComparator {
285cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling    bool operator()(const RecPair &LHS,
286cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling                    const RecPair &RHS) const {
287c4d9b240b157efa9301d451ac44c12f6b004db8fChris Lattner      unsigned i = 0;
288cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling      const std::vector<Record*> *LHSVec = &LHS.first;
289cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling      const std::vector<Record*> *RHSVec = &RHS.first;
290cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling      unsigned RHSSize = RHSVec->size();
291cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling      unsigned LHSSize = LHSVec->size();
292cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling
29393dc92e412fd06250e46951bffb6040eca9baebdChris Lattner      for (; i != LHSSize; ++i) {
294cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling        if (i == RHSSize) return false;  // RHS is shorter than LHS.
295cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling        if ((*LHSVec)[i] != (*RHSVec)[i])
296cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling          return (*LHSVec)[i]->getName() < (*RHSVec)[i]->getName();
29793dc92e412fd06250e46951bffb6040eca9baebdChris Lattner      }
298cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling
299023422a6eb9ea692a5a837dc1daf256ac75ac6b0Bill Wendling      if (i != RHSSize) return true;
300cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling
301cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling      i = 0;
302cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling      LHSVec = &LHS.second;
303cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling      RHSVec = &RHS.second;
304cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling      RHSSize = RHSVec->size();
305cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling      LHSSize = LHSVec->size();
306cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling
307cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling      for (i = 0; i != LHSSize; ++i) {
308cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling        if (i == RHSSize) return false;  // RHS is shorter than LHS.
309cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling        if ((*LHSVec)[i] != (*RHSVec)[i])
310cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling          return (*LHSVec)[i]->getName() < (*RHSVec)[i]->getName();
311cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling      }
312cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling
313cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling      return i != RHSSize;
314c4d9b240b157efa9301d451ac44c12f6b004db8fChris Lattner    }
315c4d9b240b157efa9301d451ac44c12f6b004db8fChris Lattner  };
316c4d9b240b157efa9301d451ac44c12f6b004db8fChris Lattner}
317c4d9b240b157efa9301d451ac44c12f6b004db8fChris Lattner
318f97a00e681c7a526d49759d0d1b9d327cbf6c04aChris Lattnervoid IntrinsicEmitter::EmitVerifier(const std::vector<CodeGenIntrinsic> &Ints,
3191a55180238dbcf11113f610aea010447e51f595bDaniel Dunbar                                    raw_ostream &OS) {
320f97a00e681c7a526d49759d0d1b9d327cbf6c04aChris Lattner  OS << "// Verifier::visitIntrinsicFunctionCall code.\n";
321f97a00e681c7a526d49759d0d1b9d327cbf6c04aChris Lattner  OS << "#ifdef GET_INTRINSIC_VERIFIER\n";
322f97a00e681c7a526d49759d0d1b9d327cbf6c04aChris Lattner  OS << "  switch (ID) {\n";
323655b8de7b2ab773a977e0c524307e71354d8af29Craig Topper  OS << "  default: llvm_unreachable(\"Invalid intrinsic!\");\n";
324c4d9b240b157efa9301d451ac44c12f6b004db8fChris Lattner
325c4d9b240b157efa9301d451ac44c12f6b004db8fChris Lattner  // This checking can emit a lot of very common code.  To reduce the amount of
326c4d9b240b157efa9301d451ac44c12f6b004db8fChris Lattner  // code that we emit, batch up cases that have identical types.  This avoids
327c4d9b240b157efa9301d451ac44c12f6b004db8fChris Lattner  // problems where GCC can run out of memory compiling Verifier.cpp.
328cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling  typedef std::map<RecPair, std::vector<unsigned>, RecordListComparator> MapTy;
329c4d9b240b157efa9301d451ac44c12f6b004db8fChris Lattner  MapTy UniqueArgInfos;
330c4d9b240b157efa9301d451ac44c12f6b004db8fChris Lattner
331c4d9b240b157efa9301d451ac44c12f6b004db8fChris Lattner  // Compute the unique argument type info.
332c4d9b240b157efa9301d451ac44c12f6b004db8fChris Lattner  for (unsigned i = 0, e = Ints.size(); i != e; ++i)
333cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling    UniqueArgInfos[make_pair(Ints[i].IS.RetTypeDefs,
334cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling                             Ints[i].IS.ParamTypeDefs)].push_back(i);
335c4d9b240b157efa9301d451ac44c12f6b004db8fChris Lattner
336c4d9b240b157efa9301d451ac44c12f6b004db8fChris Lattner  // Loop through the array, emitting one comparison for each batch.
337c4d9b240b157efa9301d451ac44c12f6b004db8fChris Lattner  for (MapTy::iterator I = UniqueArgInfos.begin(),
338c4d9b240b157efa9301d451ac44c12f6b004db8fChris Lattner       E = UniqueArgInfos.end(); I != E; ++I) {
339cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling    for (unsigned i = 0, e = I->second.size(); i != e; ++i)
340c4d9b240b157efa9301d451ac44c12f6b004db8fChris Lattner      OS << "  case Intrinsic::" << Ints[I->second[i]].EnumName << ":\t\t// "
341c4d9b240b157efa9301d451ac44c12f6b004db8fChris Lattner         << Ints[I->second[i]].Name << "\n";
342f124b46b4f18b1a8f054a1222324ae15079f6ed8Chris Lattner
343cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling    const RecPair &ArgTypes = I->first;
344cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling    const std::vector<Record*> &RetTys = ArgTypes.first;
345cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling    const std::vector<Record*> &ParamTys = ArgTypes.second;
34609b1366f3f310b5648aa8cd72ed16b9f19b4c68dBob Wilson    std::vector<unsigned> OverloadedTypeIndices;
347cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling
348cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling    OS << "    VerifyIntrinsicPrototype(ID, IF, " << RetTys.size() << ", "
349cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling       << ParamTys.size();
350cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling
351cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling    // Emit return types.
352cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling    for (unsigned j = 0, je = RetTys.size(); j != je; ++j) {
353cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling      Record *ArgType = RetTys[j];
354cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling      OS << ", ";
355cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling
3566994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth      if (ArgType->isSubClassOf("LLVMMatchType")) {
3576994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth        unsigned Number = ArgType->getValueAsInt("Number");
35809b1366f3f310b5648aa8cd72ed16b9f19b4c68dBob Wilson        assert(Number < OverloadedTypeIndices.size() &&
35909b1366f3f310b5648aa8cd72ed16b9f19b4c68dBob Wilson               "Invalid matching number!");
36009b1366f3f310b5648aa8cd72ed16b9f19b4c68dBob Wilson        Number = OverloadedTypeIndices[Number];
361bc03979536a1ecb220f1330719f3e3973a81ab0bBob Wilson        if (ArgType->isSubClassOf("LLVMExtendedElementVectorType"))
362bc03979536a1ecb220f1330719f3e3973a81ab0bBob Wilson          OS << "~(ExtendedElementVectorType | " << Number << ")";
363bc03979536a1ecb220f1330719f3e3973a81ab0bBob Wilson        else if (ArgType->isSubClassOf("LLVMTruncatedElementVectorType"))
364bc03979536a1ecb220f1330719f3e3973a81ab0bBob Wilson          OS << "~(TruncatedElementVectorType | " << Number << ")";
365bc03979536a1ecb220f1330719f3e3973a81ab0bBob Wilson        else
366bc03979536a1ecb220f1330719f3e3973a81ab0bBob Wilson          OS << "~" << Number;
3676994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth      } else {
368825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson        MVT::SimpleValueType VT = getValueType(ArgType->getValueAsDef("VT"));
3696994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth        OS << getEnumName(VT);
370cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling
37161fc4cf7aa0b87ceab62082cee8ef5ce3f574ffcBob Wilson        if (EVT(VT).isOverloaded())
37209b1366f3f310b5648aa8cd72ed16b9f19b4c68dBob Wilson          OverloadedTypeIndices.push_back(j);
37309b1366f3f310b5648aa8cd72ed16b9f19b4c68dBob Wilson
374825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson        if (VT == MVT::isVoid && j != 0 && j != je - 1)
375cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling          throw "Var arg type not last argument";
376cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling      }
377cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling    }
378cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling
379cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling    // Emit the parameter types.
380cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling    for (unsigned j = 0, je = ParamTys.size(); j != je; ++j) {
381cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling      Record *ArgType = ParamTys[j];
382cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling      OS << ", ";
383cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling
384cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling      if (ArgType->isSubClassOf("LLVMMatchType")) {
385cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling        unsigned Number = ArgType->getValueAsInt("Number");
38609b1366f3f310b5648aa8cd72ed16b9f19b4c68dBob Wilson        assert(Number < OverloadedTypeIndices.size() &&
38709b1366f3f310b5648aa8cd72ed16b9f19b4c68dBob Wilson               "Invalid matching number!");
38809b1366f3f310b5648aa8cd72ed16b9f19b4c68dBob Wilson        Number = OverloadedTypeIndices[Number];
389bc03979536a1ecb220f1330719f3e3973a81ab0bBob Wilson        if (ArgType->isSubClassOf("LLVMExtendedElementVectorType"))
390bc03979536a1ecb220f1330719f3e3973a81ab0bBob Wilson          OS << "~(ExtendedElementVectorType | " << Number << ")";
391bc03979536a1ecb220f1330719f3e3973a81ab0bBob Wilson        else if (ArgType->isSubClassOf("LLVMTruncatedElementVectorType"))
392bc03979536a1ecb220f1330719f3e3973a81ab0bBob Wilson          OS << "~(TruncatedElementVectorType | " << Number << ")";
393bc03979536a1ecb220f1330719f3e3973a81ab0bBob Wilson        else
394bc03979536a1ecb220f1330719f3e3973a81ab0bBob Wilson          OS << "~" << Number;
395cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling      } else {
396825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson        MVT::SimpleValueType VT = getValueType(ArgType->getValueAsDef("VT"));
397cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling        OS << getEnumName(VT);
398cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling
39961fc4cf7aa0b87ceab62082cee8ef5ce3f574ffcBob Wilson        if (EVT(VT).isOverloaded())
40009b1366f3f310b5648aa8cd72ed16b9f19b4c68dBob Wilson          OverloadedTypeIndices.push_back(j + RetTys.size());
40109b1366f3f310b5648aa8cd72ed16b9f19b4c68dBob Wilson
402825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson        if (VT == MVT::isVoid && j != 0 && j != je - 1)
40395d97b90e8427255c8298f5d3a1ab605af62aab4Jim Laskey          throw "Var arg type not last argument";
40495d97b90e8427255c8298f5d3a1ab605af62aab4Jim Laskey      }
40595d97b90e8427255c8298f5d3a1ab605af62aab4Jim Laskey    }
40695d97b90e8427255c8298f5d3a1ab605af62aab4Jim Laskey
4076994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth    OS << ");\n";
408f97a00e681c7a526d49759d0d1b9d327cbf6c04aChris Lattner    OS << "    break;\n";
409f97a00e681c7a526d49759d0d1b9d327cbf6c04aChris Lattner  }
410f97a00e681c7a526d49759d0d1b9d327cbf6c04aChris Lattner  OS << "  }\n";
411f97a00e681c7a526d49759d0d1b9d327cbf6c04aChris Lattner  OS << "#endif\n\n";
4129b843b249462980ae4630dc37d1bcccde884a5a7Chris Lattner}
4139b843b249462980ae4630dc37d1bcccde884a5a7Chris Lattner
41495af592a631f403e1458ec1155f89fc31011572cJim Laskeyvoid IntrinsicEmitter::EmitGenerator(const std::vector<CodeGenIntrinsic> &Ints,
4151a55180238dbcf11113f610aea010447e51f595bDaniel Dunbar                                     raw_ostream &OS) {
41695af592a631f403e1458ec1155f89fc31011572cJim Laskey  OS << "// Code for generating Intrinsic function declarations.\n";
41795af592a631f403e1458ec1155f89fc31011572cJim Laskey  OS << "#ifdef GET_INTRINSIC_GENERATOR\n";
41895af592a631f403e1458ec1155f89fc31011572cJim Laskey  OS << "  switch (id) {\n";
419655b8de7b2ab773a977e0c524307e71354d8af29Craig Topper  OS << "  default: llvm_unreachable(\"Invalid intrinsic!\");\n";
42095af592a631f403e1458ec1155f89fc31011572cJim Laskey
42195af592a631f403e1458ec1155f89fc31011572cJim Laskey  // Similar to GET_INTRINSIC_VERIFIER, batch up cases that have identical
42295af592a631f403e1458ec1155f89fc31011572cJim Laskey  // types.
423cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling  typedef std::map<RecPair, std::vector<unsigned>, RecordListComparator> MapTy;
42495af592a631f403e1458ec1155f89fc31011572cJim Laskey  MapTy UniqueArgInfos;
42595af592a631f403e1458ec1155f89fc31011572cJim Laskey
42695af592a631f403e1458ec1155f89fc31011572cJim Laskey  // Compute the unique argument type info.
42795af592a631f403e1458ec1155f89fc31011572cJim Laskey  for (unsigned i = 0, e = Ints.size(); i != e; ++i)
428cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling    UniqueArgInfos[make_pair(Ints[i].IS.RetTypeDefs,
429cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling                             Ints[i].IS.ParamTypeDefs)].push_back(i);
43095af592a631f403e1458ec1155f89fc31011572cJim Laskey
43195af592a631f403e1458ec1155f89fc31011572cJim Laskey  // Loop through the array, emitting one generator for each batch.
43249de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen  std::string IntrinsicStr = TargetPrefix + "Intrinsic::";
43349de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen
43495af592a631f403e1458ec1155f89fc31011572cJim Laskey  for (MapTy::iterator I = UniqueArgInfos.begin(),
43595af592a631f403e1458ec1155f89fc31011572cJim Laskey       E = UniqueArgInfos.end(); I != E; ++I) {
436cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling    for (unsigned i = 0, e = I->second.size(); i != e; ++i)
43749de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen      OS << "  case " << IntrinsicStr << Ints[I->second[i]].EnumName
43849de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen         << ":\t\t// " << Ints[I->second[i]].Name << "\n";
43995af592a631f403e1458ec1155f89fc31011572cJim Laskey
440cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling    const RecPair &ArgTypes = I->first;
441cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling    const std::vector<Record*> &RetTys = ArgTypes.first;
442cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling    const std::vector<Record*> &ParamTys = ArgTypes.second;
443cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling
444cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling    unsigned N = ParamTys.size();
44595af592a631f403e1458ec1155f89fc31011572cJim Laskey
4466994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth    if (N > 1 &&
447825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson        getValueType(ParamTys[N - 1]->getValueAsDef("VT")) == MVT::isVoid) {
44895af592a631f403e1458ec1155f89fc31011572cJim Laskey      OS << "    IsVarArg = true;\n";
44995af592a631f403e1458ec1155f89fc31011572cJim Laskey      --N;
45095af592a631f403e1458ec1155f89fc31011572cJim Laskey    }
451cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling
45284c614d1ac671b1a5524169f20028f51c30be728Reid Spencer    unsigned ArgNo = 0;
45395af592a631f403e1458ec1155f89fc31011572cJim Laskey    OS << "    ResultTy = ";
454cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling    EmitTypeGenerate(OS, RetTys, ArgNo);
45595af592a631f403e1458ec1155f89fc31011572cJim Laskey    OS << ";\n";
45695af592a631f403e1458ec1155f89fc31011572cJim Laskey
457cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling    for (unsigned j = 0; j != N; ++j) {
45895af592a631f403e1458ec1155f89fc31011572cJim Laskey      OS << "    ArgTys.push_back(";
459cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling      EmitTypeGenerate(OS, ParamTys[j], ArgNo);
46095af592a631f403e1458ec1155f89fc31011572cJim Laskey      OS << ");\n";
46195af592a631f403e1458ec1155f89fc31011572cJim Laskey    }
462cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling
46395af592a631f403e1458ec1155f89fc31011572cJim Laskey    OS << "    break;\n";
46495af592a631f403e1458ec1155f89fc31011572cJim Laskey  }
465cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling
46695af592a631f403e1458ec1155f89fc31011572cJim Laskey  OS << "  }\n";
46795af592a631f403e1458ec1155f89fc31011572cJim Laskey  OS << "#endif\n\n";
46895af592a631f403e1458ec1155f89fc31011572cJim Laskey}
46995af592a631f403e1458ec1155f89fc31011572cJim Laskey
470bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCallnamespace {
471bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall  enum ModRefKind {
472bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall    MRK_none,
473bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall    MRK_readonly,
474bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall    MRK_readnone
475bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall  };
476bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall
477bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall  ModRefKind getModRefKind(const CodeGenIntrinsic &intrinsic) {
478bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall    switch (intrinsic.ModRef) {
479bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall    case CodeGenIntrinsic::NoMem:
480bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall      return MRK_readnone;
481bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall    case CodeGenIntrinsic::ReadArgMem:
482bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall    case CodeGenIntrinsic::ReadMem:
483bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall      return MRK_readonly;
484bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall    case CodeGenIntrinsic::ReadWriteArgMem:
485bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall    case CodeGenIntrinsic::ReadWriteMem:
486bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall      return MRK_none;
487bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall    }
488655b8de7b2ab773a977e0c524307e71354d8af29Craig Topper    llvm_unreachable("bad mod-ref kind");
489bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall  }
490bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall
491bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall  struct AttributeComparator {
492bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall    bool operator()(const CodeGenIntrinsic *L, const CodeGenIntrinsic *R) const {
493bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall      // Sort throwing intrinsics after non-throwing intrinsics.
494bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall      if (L->canThrow != R->canThrow)
495bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall        return R->canThrow;
496bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall
497bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall      // Try to order by readonly/readnone attribute.
498bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall      ModRefKind LK = getModRefKind(*L);
499bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall      ModRefKind RK = getModRefKind(*R);
500bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall      if (LK != RK) return (LK > RK);
501bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall
502bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall      // Order by argument attributes.
503bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall      // This is reliable because each side is already sorted internally.
504bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall      return (L->ArgumentAttributes < R->ArgumentAttributes);
505bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall    }
506bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall  };
507bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall}
508bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall
509048ffb239c282277959463c61200b86e2380cb84Chris Lattner/// EmitAttributes - This emits the Intrinsic::getAttributes method.
5104e5f35973c1bc56cce14d44c6f8f4ad1e9f1a438Chris Lattnervoid IntrinsicEmitter::
5111a55180238dbcf11113f610aea010447e51f595bDaniel DunbarEmitAttributes(const std::vector<CodeGenIntrinsic> &Ints, raw_ostream &OS) {
512a3355ffb3d30d19d226bbb75707991c60f236e37Duncan Sands  OS << "// Add parameter attributes that are not common to all intrinsics.\n";
513a3355ffb3d30d19d226bbb75707991c60f236e37Duncan Sands  OS << "#ifdef GET_INTRINSIC_ATTRIBUTES\n";
51449de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen  if (TargetOnly)
51549de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen    OS << "static AttrListPtr getAttributes(" << TargetPrefix
516bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall       << "Intrinsic::ID id) {\n";
51749de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen  else
518bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall    OS << "AttrListPtr Intrinsic::getAttributes(ID id) {\n";
519bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall
5201f5952352146f229cbc249405fbe9898d168089bCraig Topper  // Compute the maximum number of attribute arguments and the map
5211f5952352146f229cbc249405fbe9898d168089bCraig Topper  typedef std::map<const CodeGenIntrinsic*, unsigned,
5221f5952352146f229cbc249405fbe9898d168089bCraig Topper                   AttributeComparator> UniqAttrMapTy;
5231f5952352146f229cbc249405fbe9898d168089bCraig Topper  UniqAttrMapTy UniqAttributes;
524bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall  unsigned maxArgAttrs = 0;
5251f5952352146f229cbc249405fbe9898d168089bCraig Topper  unsigned AttrNum = 0;
5264e5f35973c1bc56cce14d44c6f8f4ad1e9f1a438Chris Lattner  for (unsigned i = 0, e = Ints.size(); i != e; ++i) {
527bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall    const CodeGenIntrinsic &intrinsic = Ints[i];
528bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall    maxArgAttrs =
529bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall      std::max(maxArgAttrs, unsigned(intrinsic.ArgumentAttributes.size()));
5301f5952352146f229cbc249405fbe9898d168089bCraig Topper    unsigned &N = UniqAttributes[&intrinsic];
5311f5952352146f229cbc249405fbe9898d168089bCraig Topper    if (N) continue;
5321f5952352146f229cbc249405fbe9898d168089bCraig Topper    assert(AttrNum < 256 && "Too many unique attributes for table!");
5331f5952352146f229cbc249405fbe9898d168089bCraig Topper    N = ++AttrNum;
5344e5f35973c1bc56cce14d44c6f8f4ad1e9f1a438Chris Lattner  }
535bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall
536bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall  // Emit an array of AttributeWithIndex.  Most intrinsics will have
537bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall  // at least one entry, for the function itself (index ~1), which is
538bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall  // usually nounwind.
5391f5952352146f229cbc249405fbe9898d168089bCraig Topper  OS << "  static const uint8_t IntrinsicsToAttributesMap[] = {\n";
540bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall
5411f5952352146f229cbc249405fbe9898d168089bCraig Topper  for (unsigned i = 0, e = Ints.size(); i != e; ++i) {
5421f5952352146f229cbc249405fbe9898d168089bCraig Topper    const CodeGenIntrinsic &intrinsic = Ints[i];
543bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall
5441f5952352146f229cbc249405fbe9898d168089bCraig Topper    OS << "    " << UniqAttributes[&intrinsic] << ", // "
5451f5952352146f229cbc249405fbe9898d168089bCraig Topper       << intrinsic.Name << "\n";
5461f5952352146f229cbc249405fbe9898d168089bCraig Topper  }
5471f5952352146f229cbc249405fbe9898d168089bCraig Topper  OS << "  };\n\n";
54810dae94be2ccb187bd4e3da53771be54057acd6cChris Lattner
5491f5952352146f229cbc249405fbe9898d168089bCraig Topper  OS << "  AttributeWithIndex AWI[" << maxArgAttrs+1 << "];\n";
5501f5952352146f229cbc249405fbe9898d168089bCraig Topper  OS << "  unsigned NumAttrs = 0;\n";
551b57b170317f12370183111fc458de3352c5f71dcCraig Topper  OS << "  if (id != 0) {\n";
552b57b170317f12370183111fc458de3352c5f71dcCraig Topper  OS << "    switch(IntrinsicsToAttributesMap[id - ";
553b57b170317f12370183111fc458de3352c5f71dcCraig Topper  if (TargetOnly)
554b57b170317f12370183111fc458de3352c5f71dcCraig Topper    OS << "Intrinsic::num_intrinsics";
555b57b170317f12370183111fc458de3352c5f71dcCraig Topper  else
556b57b170317f12370183111fc458de3352c5f71dcCraig Topper    OS << "1";
557b57b170317f12370183111fc458de3352c5f71dcCraig Topper  OS << "]) {\n";
558b57b170317f12370183111fc458de3352c5f71dcCraig Topper  OS << "    default: llvm_unreachable(\"Invalid attribute number\");\n";
5591f5952352146f229cbc249405fbe9898d168089bCraig Topper  for (UniqAttrMapTy::const_iterator I = UniqAttributes.begin(),
5601f5952352146f229cbc249405fbe9898d168089bCraig Topper       E = UniqAttributes.end(); I != E; ++I) {
561b57b170317f12370183111fc458de3352c5f71dcCraig Topper    OS << "    case " << I->second << ":\n";
56210dae94be2ccb187bd4e3da53771be54057acd6cChris Lattner
5631f5952352146f229cbc249405fbe9898d168089bCraig Topper    const CodeGenIntrinsic &intrinsic = *(I->first);
564bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall
565bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall    // Keep track of the number of attributes we're writing out.
566bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall    unsigned numAttrs = 0;
56710dae94be2ccb187bd4e3da53771be54057acd6cChris Lattner
568bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall    // The argument attributes are alreadys sorted by argument index.
569bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall    for (unsigned ai = 0, ae = intrinsic.ArgumentAttributes.size(); ai != ae;) {
570bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall      unsigned argNo = intrinsic.ArgumentAttributes[ai].first;
5711f5952352146f229cbc249405fbe9898d168089bCraig Topper
572b57b170317f12370183111fc458de3352c5f71dcCraig Topper      OS << "      AWI[" << numAttrs++ << "] = AttributeWithIndex::get("
573bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall         << argNo+1 << ", ";
574bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall
575bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall      bool moreThanOne = false;
576d4a2700fdc5bc8ac50084fcb39155e01e86168d5Chris Lattner
577bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall      do {
578bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall        if (moreThanOne) OS << '|';
579bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall
580bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall        switch (intrinsic.ArgumentAttributes[ai].second) {
581d4a2700fdc5bc8ac50084fcb39155e01e86168d5Chris Lattner        case CodeGenIntrinsic::NoCapture:
582bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall          OS << "Attribute::NoCapture";
583d4a2700fdc5bc8ac50084fcb39155e01e86168d5Chris Lattner          break;
584d4a2700fdc5bc8ac50084fcb39155e01e86168d5Chris Lattner        }
585bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall
586bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall        ++ai;
587bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall        moreThanOne = true;
588bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall      } while (ai != ae && intrinsic.ArgumentAttributes[ai].first == argNo);
589bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall
590bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall      OS << ");\n";
591bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall    }
592bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall
593bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall    ModRefKind modRef = getModRefKind(intrinsic);
594bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall
595bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall    if (!intrinsic.canThrow || modRef) {
596b57b170317f12370183111fc458de3352c5f71dcCraig Topper      OS << "      AWI[" << numAttrs++ << "] = AttributeWithIndex::get(~0, ";
597bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall      if (!intrinsic.canThrow) {
598bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall        OS << "Attribute::NoUnwind";
599bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall        if (modRef) OS << '|';
600bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall      }
601bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall      switch (modRef) {
602bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall      case MRK_none: break;
603bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall      case MRK_readonly: OS << "Attribute::ReadOnly"; break;
604bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall      case MRK_readnone: OS << "Attribute::ReadNone"; break;
605d4a2700fdc5bc8ac50084fcb39155e01e86168d5Chris Lattner      }
606d4a2700fdc5bc8ac50084fcb39155e01e86168d5Chris Lattner      OS << ");\n";
607d4a2700fdc5bc8ac50084fcb39155e01e86168d5Chris Lattner    }
608bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall
609bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall    if (numAttrs) {
610b57b170317f12370183111fc458de3352c5f71dcCraig Topper      OS << "      NumAttrs = " << numAttrs << ";\n";
611b57b170317f12370183111fc458de3352c5f71dcCraig Topper      OS << "      break;\n";
612bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall    } else {
613b57b170317f12370183111fc458de3352c5f71dcCraig Topper      OS << "      return AttrListPtr();\n";
614bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall    }
61510dae94be2ccb187bd4e3da53771be54057acd6cChris Lattner  }
61610dae94be2ccb187bd4e3da53771be54057acd6cChris Lattner
617b57b170317f12370183111fc458de3352c5f71dcCraig Topper  OS << "    }\n";
61810dae94be2ccb187bd4e3da53771be54057acd6cChris Lattner  OS << "  }\n";
619bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall  OS << "  return AttrListPtr::get(AWI, NumAttrs);\n";
620048ffb239c282277959463c61200b86e2380cb84Chris Lattner  OS << "}\n";
621d4a2700fdc5bc8ac50084fcb39155e01e86168d5Chris Lattner  OS << "#endif // GET_INTRINSIC_ATTRIBUTES\n\n";
6224e5f35973c1bc56cce14d44c6f8f4ad1e9f1a438Chris Lattner}
623022f64fbbc4669623e79b805379266fed519017dChris Lattner
624d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands/// EmitModRefBehavior - Determine intrinsic alias analysis mod/ref behavior.
625d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sandsvoid IntrinsicEmitter::
6261a55180238dbcf11113f610aea010447e51f595bDaniel DunbarEmitModRefBehavior(const std::vector<CodeGenIntrinsic> &Ints, raw_ostream &OS){
627b519a0fe0ee02804cc77cb9c40ded6604341b71cBenjamin Kramer  OS << "// Determine intrinsic alias analysis mod/ref behavior.\n"
628b519a0fe0ee02804cc77cb9c40ded6604341b71cBenjamin Kramer     << "#ifdef GET_INTRINSIC_MODREF_BEHAVIOR\n"
629b519a0fe0ee02804cc77cb9c40ded6604341b71cBenjamin Kramer     << "assert(iid <= Intrinsic::" << Ints.back().EnumName << " && "
630b519a0fe0ee02804cc77cb9c40ded6604341b71cBenjamin Kramer     << "\"Unknown intrinsic.\");\n\n";
631b519a0fe0ee02804cc77cb9c40ded6604341b71cBenjamin Kramer
632b519a0fe0ee02804cc77cb9c40ded6604341b71cBenjamin Kramer  OS << "static const uint8_t IntrinsicModRefBehavior[] = {\n"
633b519a0fe0ee02804cc77cb9c40ded6604341b71cBenjamin Kramer     << "  /* invalid */ UnknownModRefBehavior,\n";
634d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands  for (unsigned i = 0, e = Ints.size(); i != e; ++i) {
635b519a0fe0ee02804cc77cb9c40ded6604341b71cBenjamin Kramer    OS << "  /* " << TargetPrefix << Ints[i].EnumName << " */ ";
636d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands    switch (Ints[i].ModRef) {
637d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands    case CodeGenIntrinsic::NoMem:
638b519a0fe0ee02804cc77cb9c40ded6604341b71cBenjamin Kramer      OS << "DoesNotAccessMemory,\n";
639d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands      break;
640d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands    case CodeGenIntrinsic::ReadArgMem:
641b519a0fe0ee02804cc77cb9c40ded6604341b71cBenjamin Kramer      OS << "OnlyReadsArgumentPointees,\n";
6429423f633654af6045b1efa7795edfe8ea0533d7eDan Gohman      break;
643d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands    case CodeGenIntrinsic::ReadMem:
644b519a0fe0ee02804cc77cb9c40ded6604341b71cBenjamin Kramer      OS << "OnlyReadsMemory,\n";
645d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands      break;
6467365c091f92db5e68c98d7faedc6c34e1bbbc898Dan Gohman    case CodeGenIntrinsic::ReadWriteArgMem:
647b519a0fe0ee02804cc77cb9c40ded6604341b71cBenjamin Kramer      OS << "OnlyAccessesArgumentPointees,\n";
648b519a0fe0ee02804cc77cb9c40ded6604341b71cBenjamin Kramer      break;
649b519a0fe0ee02804cc77cb9c40ded6604341b71cBenjamin Kramer    case CodeGenIntrinsic::ReadWriteMem:
650b519a0fe0ee02804cc77cb9c40ded6604341b71cBenjamin Kramer      OS << "UnknownModRefBehavior,\n";
651d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands      break;
652d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands    }
653d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands  }
654b519a0fe0ee02804cc77cb9c40ded6604341b71cBenjamin Kramer  OS << "};\n\n"
655b519a0fe0ee02804cc77cb9c40ded6604341b71cBenjamin Kramer     << "return static_cast<ModRefBehavior>(IntrinsicModRefBehavior[iid]);\n"
656b519a0fe0ee02804cc77cb9c40ded6604341b71cBenjamin Kramer     << "#endif // GET_INTRINSIC_MODREF_BEHAVIOR\n\n";
657d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands}
658d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands
659331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner/// EmitTargetBuiltins - All of the builtins in the specified map are for the
660331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner/// same target, and we already checked it.
661331bf92fb51f058672144681b3d0e67d30f5699fChris Lattnerstatic void EmitTargetBuiltins(const std::map<std::string, std::string> &BIM,
66249de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen                               const std::string &TargetPrefix,
6631a55180238dbcf11113f610aea010447e51f595bDaniel Dunbar                               raw_ostream &OS) {
664331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner
665298b176559d5c76d7d9f7fdd06429a75892de043Chris Lattner  std::vector<StringMatcher::StringPair> Results;
666331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner
667298b176559d5c76d7d9f7fdd06429a75892de043Chris Lattner  for (std::map<std::string, std::string>::const_iterator I = BIM.begin(),
668298b176559d5c76d7d9f7fdd06429a75892de043Chris Lattner       E = BIM.end(); I != E; ++I) {
669298b176559d5c76d7d9f7fdd06429a75892de043Chris Lattner    std::string ResultCode =
670298b176559d5c76d7d9f7fdd06429a75892de043Chris Lattner    "return " + TargetPrefix + "Intrinsic::" + I->second + ";";
671298b176559d5c76d7d9f7fdd06429a75892de043Chris Lattner    Results.push_back(StringMatcher::StringPair(I->first, ResultCode));
672331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner  }
673298b176559d5c76d7d9f7fdd06429a75892de043Chris Lattner
674298b176559d5c76d7d9f7fdd06429a75892de043Chris Lattner  StringMatcher("BuiltinName", Results, OS).Emit();
675331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner}
676331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner
677331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner
6783f8b8913bc9cb232871445eefa8654caf7f9986fChris Lattnervoid IntrinsicEmitter::
6793f8b8913bc9cb232871445eefa8654caf7f9986fChris LattnerEmitIntrinsicToGCCBuiltinMap(const std::vector<CodeGenIntrinsic> &Ints,
6801a55180238dbcf11113f610aea010447e51f595bDaniel Dunbar                             raw_ostream &OS) {
681fa0fba1c546091c485e5513eadeef181dda370abChris Lattner  typedef std::map<std::string, std::map<std::string, std::string> > BIMTy;
6823f8b8913bc9cb232871445eefa8654caf7f9986fChris Lattner  BIMTy BuiltinMap;
6833f8b8913bc9cb232871445eefa8654caf7f9986fChris Lattner  for (unsigned i = 0, e = Ints.size(); i != e; ++i) {
6843f8b8913bc9cb232871445eefa8654caf7f9986fChris Lattner    if (!Ints[i].GCCBuiltinName.empty()) {
685fa0fba1c546091c485e5513eadeef181dda370abChris Lattner      // Get the map for this target prefix.
686fa0fba1c546091c485e5513eadeef181dda370abChris Lattner      std::map<std::string, std::string> &BIM =BuiltinMap[Ints[i].TargetPrefix];
687fa0fba1c546091c485e5513eadeef181dda370abChris Lattner
688fa0fba1c546091c485e5513eadeef181dda370abChris Lattner      if (!BIM.insert(std::make_pair(Ints[i].GCCBuiltinName,
689fa0fba1c546091c485e5513eadeef181dda370abChris Lattner                                     Ints[i].EnumName)).second)
6903f8b8913bc9cb232871445eefa8654caf7f9986fChris Lattner        throw "Intrinsic '" + Ints[i].TheDef->getName() +
6913f8b8913bc9cb232871445eefa8654caf7f9986fChris Lattner              "': duplicate GCC builtin name!";
6923f8b8913bc9cb232871445eefa8654caf7f9986fChris Lattner    }
6933f8b8913bc9cb232871445eefa8654caf7f9986fChris Lattner  }
6943f8b8913bc9cb232871445eefa8654caf7f9986fChris Lattner
6953f8b8913bc9cb232871445eefa8654caf7f9986fChris Lattner  OS << "// Get the LLVM intrinsic that corresponds to a GCC builtin.\n";
6963f8b8913bc9cb232871445eefa8654caf7f9986fChris Lattner  OS << "// This is used by the C front-end.  The GCC builtin name is passed\n";
6973f8b8913bc9cb232871445eefa8654caf7f9986fChris Lattner  OS << "// in as BuiltinName, and a target prefix (e.g. 'ppc') is passed\n";
6983f8b8913bc9cb232871445eefa8654caf7f9986fChris Lattner  OS << "// in as TargetPrefix.  The result is assigned to 'IntrinsicID'.\n";
6993f8b8913bc9cb232871445eefa8654caf7f9986fChris Lattner  OS << "#ifdef GET_LLVM_INTRINSIC_FOR_GCC_BUILTIN\n";
70049de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen
70149de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen  if (TargetOnly) {
70249de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen    OS << "static " << TargetPrefix << "Intrinsic::ID "
70349de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen       << "getIntrinsicForGCCBuiltin(const char "
704298b176559d5c76d7d9f7fdd06429a75892de043Chris Lattner       << "*TargetPrefixStr, const char *BuiltinNameStr) {\n";
70549de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen  } else {
70649de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen    OS << "Intrinsic::ID Intrinsic::getIntrinsicForGCCBuiltin(const char "
707298b176559d5c76d7d9f7fdd06429a75892de043Chris Lattner       << "*TargetPrefixStr, const char *BuiltinNameStr) {\n";
70849de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen  }
70949de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen
710298b176559d5c76d7d9f7fdd06429a75892de043Chris Lattner  OS << "  StringRef BuiltinName(BuiltinNameStr);\n";
711298b176559d5c76d7d9f7fdd06429a75892de043Chris Lattner  OS << "  StringRef TargetPrefix(TargetPrefixStr);\n\n";
712331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner
7133f8b8913bc9cb232871445eefa8654caf7f9986fChris Lattner  // Note: this could emit significantly better code if we cared.
7143f8b8913bc9cb232871445eefa8654caf7f9986fChris Lattner  for (BIMTy::iterator I = BuiltinMap.begin(), E = BuiltinMap.end();I != E;++I){
715fa0fba1c546091c485e5513eadeef181dda370abChris Lattner    OS << "  ";
716fa0fba1c546091c485e5513eadeef181dda370abChris Lattner    if (!I->first.empty())
717298b176559d5c76d7d9f7fdd06429a75892de043Chris Lattner      OS << "if (TargetPrefix == \"" << I->first << "\") ";
718fa0fba1c546091c485e5513eadeef181dda370abChris Lattner    else
719fa0fba1c546091c485e5513eadeef181dda370abChris Lattner      OS << "/* Target Independent Builtins */ ";
720fa0fba1c546091c485e5513eadeef181dda370abChris Lattner    OS << "{\n";
721fa0fba1c546091c485e5513eadeef181dda370abChris Lattner
722fa0fba1c546091c485e5513eadeef181dda370abChris Lattner    // Emit the comparisons for this target prefix.
72349de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen    EmitTargetBuiltins(I->second, TargetPrefix, OS);
724fa0fba1c546091c485e5513eadeef181dda370abChris Lattner    OS << "  }\n";
7253f8b8913bc9cb232871445eefa8654caf7f9986fChris Lattner  }
726298b176559d5c76d7d9f7fdd06429a75892de043Chris Lattner  OS << "  return ";
727298b176559d5c76d7d9f7fdd06429a75892de043Chris Lattner  if (!TargetPrefix.empty())
728298b176559d5c76d7d9f7fdd06429a75892de043Chris Lattner    OS << "(" << TargetPrefix << "Intrinsic::ID)";
729298b176559d5c76d7d9f7fdd06429a75892de043Chris Lattner  OS << "Intrinsic::not_intrinsic;\n";
73049de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen  OS << "}\n";
7313f8b8913bc9cb232871445eefa8654caf7f9986fChris Lattner  OS << "#endif\n\n";
7323f8b8913bc9cb232871445eefa8654caf7f9986fChris Lattner}
733