IntrinsicEmitter.cpp revision bd0fa4c00d7870b1da36eac7b2181700381f2f96
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"
711f4096054367cab3acab3a74c719ef6d3090606aMichael J. Spencer        "#if defined(_MSC_VER) && defined(setjmp) && \\\n"
721f4096054367cab3acab3a74c719ef6d3090606aMichael J. Spencer        "                         !defined(setjmp_undefined_for_msvc)\n"
7308047f616977f204df6054c481601f2237cc308dMichael J. Spencer        "#  pragma push_macro(\"setjmp\")\n"
7408047f616977f204df6054c481601f2237cc308dMichael J. Spencer        "#  undef setjmp\n"
751f4096054367cab3acab3a74c719ef6d3090606aMichael J. Spencer        "#  define setjmp_undefined_for_msvc\n"
767d9663c70b3300070298d716dba6e6f6ce2d1e3eDouglas Gregor        "#endif\n\n";
777d9663c70b3300070298d716dba6e6f6ce2d1e3eDouglas Gregor}
787d9663c70b3300070298d716dba6e6f6ce2d1e3eDouglas Gregor
797d9663c70b3300070298d716dba6e6f6ce2d1e3eDouglas Gregorvoid IntrinsicEmitter::EmitSuffix(raw_ostream &OS) {
801f4096054367cab3acab3a74c719ef6d3090606aMichael J. Spencer  OS << "#if defined(_MSC_VER) && defined(setjmp_undefined_for_msvc)\n"
817d9663c70b3300070298d716dba6e6f6ce2d1e3eDouglas Gregor        "// let's return it to _setjmp state\n"
8208047f616977f204df6054c481601f2237cc308dMichael J. Spencer        "#  pragma pop_macro(\"setjmp\")\n"
831f4096054367cab3acab3a74c719ef6d3090606aMichael J. Spencer        "#  undef setjmp_undefined_for_msvc\n"
847d9663c70b3300070298d716dba6e6f6ce2d1e3eDouglas Gregor        "#endif\n\n";
859e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner}
869e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner
879e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattnervoid IntrinsicEmitter::EmitEnumInfo(const std::vector<CodeGenIntrinsic> &Ints,
881a55180238dbcf11113f610aea010447e51f595bDaniel Dunbar                                    raw_ostream &OS) {
899b843b249462980ae4630dc37d1bcccde884a5a7Chris Lattner  OS << "// Enum values for Intrinsics.h\n";
909e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner  OS << "#ifdef GET_INTRINSIC_ENUM_VALUES\n";
919e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner  for (unsigned i = 0, e = Ints.size(); i != e; ++i) {
929e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner    OS << "    " << Ints[i].EnumName;
939e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner    OS << ((i != e-1) ? ", " : "  ");
949e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner    OS << std::string(40-Ints[i].EnumName.size(), ' ')
959e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner      << "// " << Ints[i].Name << "\n";
969e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner  }
979e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner  OS << "#endif\n\n";
989e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner}
999b843b249462980ae4630dc37d1bcccde884a5a7Chris Lattner
1009b843b249462980ae4630dc37d1bcccde884a5a7Chris Lattnervoid IntrinsicEmitter::
1019b843b249462980ae4630dc37d1bcccde884a5a7Chris LattnerEmitFnNameRecognizer(const std::vector<CodeGenIntrinsic> &Ints,
1021a55180238dbcf11113f610aea010447e51f595bDaniel Dunbar                     raw_ostream &OS) {
103cc67c75b67d22653ea9380020e9a40381233901dChris Lattner  // Build a 'first character of function name' -> intrinsic # mapping.
104cc67c75b67d22653ea9380020e9a40381233901dChris Lattner  std::map<char, std::vector<unsigned> > IntMapping;
1059b843b249462980ae4630dc37d1bcccde884a5a7Chris Lattner  for (unsigned i = 0, e = Ints.size(); i != e; ++i)
106cc67c75b67d22653ea9380020e9a40381233901dChris Lattner    IntMapping[Ints[i].Name[5]].push_back(i);
107cc67c75b67d22653ea9380020e9a40381233901dChris Lattner
1089b843b249462980ae4630dc37d1bcccde884a5a7Chris Lattner  OS << "// Function name -> enum value recognizer code.\n";
1099b843b249462980ae4630dc37d1bcccde884a5a7Chris Lattner  OS << "#ifdef GET_FUNCTION_RECOGNIZER\n";
110cc67c75b67d22653ea9380020e9a40381233901dChris Lattner  OS << "  StringRef NameR(Name+6, Len-6);   // Skip over 'llvm.'\n";
111cc67c75b67d22653ea9380020e9a40381233901dChris Lattner  OS << "  switch (Name[5]) {                  // Dispatch on first letter.\n";
112cc67c75b67d22653ea9380020e9a40381233901dChris Lattner  OS << "  default: break;\n";
113cc67c75b67d22653ea9380020e9a40381233901dChris Lattner  // Emit the intrinsic matching stuff by first letter.
114cc67c75b67d22653ea9380020e9a40381233901dChris Lattner  for (std::map<char, std::vector<unsigned> >::iterator I = IntMapping.begin(),
1159b843b249462980ae4630dc37d1bcccde884a5a7Chris Lattner       E = IntMapping.end(); I != E; ++I) {
116cc67c75b67d22653ea9380020e9a40381233901dChris Lattner    OS << "  case '" << I->first << "':\n";
117cc67c75b67d22653ea9380020e9a40381233901dChris Lattner    std::vector<unsigned> &IntList = I->second;
118cc67c75b67d22653ea9380020e9a40381233901dChris Lattner
119cc67c75b67d22653ea9380020e9a40381233901dChris Lattner    // Emit all the overloaded intrinsics first, build a table of the
120cc67c75b67d22653ea9380020e9a40381233901dChris Lattner    // non-overloaded ones.
121cc67c75b67d22653ea9380020e9a40381233901dChris Lattner    std::vector<StringMatcher::StringPair> MatchTable;
1229b843b249462980ae4630dc37d1bcccde884a5a7Chris Lattner
123cc67c75b67d22653ea9380020e9a40381233901dChris Lattner    for (unsigned i = 0, e = IntList.size(); i != e; ++i) {
124cc67c75b67d22653ea9380020e9a40381233901dChris Lattner      unsigned IntNo = IntList[i];
125cc67c75b67d22653ea9380020e9a40381233901dChris Lattner      std::string Result = "return " + TargetPrefix + "Intrinsic::" +
126cc67c75b67d22653ea9380020e9a40381233901dChris Lattner        Ints[IntNo].EnumName + ";";
127cc67c75b67d22653ea9380020e9a40381233901dChris Lattner
128cc67c75b67d22653ea9380020e9a40381233901dChris Lattner      if (!Ints[IntNo].isOverloaded) {
129cc67c75b67d22653ea9380020e9a40381233901dChris Lattner        MatchTable.push_back(std::make_pair(Ints[IntNo].Name.substr(6),Result));
130cc67c75b67d22653ea9380020e9a40381233901dChris Lattner        continue;
131cc67c75b67d22653ea9380020e9a40381233901dChris Lattner      }
132cc67c75b67d22653ea9380020e9a40381233901dChris Lattner
133cc67c75b67d22653ea9380020e9a40381233901dChris Lattner      // For overloaded intrinsics, only the prefix needs to match
134cc67c75b67d22653ea9380020e9a40381233901dChris Lattner      std::string TheStr = Ints[IntNo].Name.substr(6);
1352738ff9c22d27ce3e4aee6f250eb68f594db1ce9Chris Lattner      TheStr += '.';  // Require "bswap." instead of bswap.
136cc67c75b67d22653ea9380020e9a40381233901dChris Lattner      OS << "    if (NameR.startswith(\"" << TheStr << "\")) "
137cc67c75b67d22653ea9380020e9a40381233901dChris Lattner         << Result << '\n';
1382738ff9c22d27ce3e4aee6f250eb68f594db1ce9Chris Lattner    }
139cc67c75b67d22653ea9380020e9a40381233901dChris Lattner
140cc67c75b67d22653ea9380020e9a40381233901dChris Lattner    // Emit the matcher logic for the fixed length strings.
141cc67c75b67d22653ea9380020e9a40381233901dChris Lattner    StringMatcher("NameR", MatchTable, OS).Emit(1);
142cc67c75b67d22653ea9380020e9a40381233901dChris Lattner    OS << "    break;  // end of '" << I->first << "' case.\n";
1439b843b249462980ae4630dc37d1bcccde884a5a7Chris Lattner  }
144cc67c75b67d22653ea9380020e9a40381233901dChris Lattner
1459b843b249462980ae4630dc37d1bcccde884a5a7Chris Lattner  OS << "  }\n";
146f97a00e681c7a526d49759d0d1b9d327cbf6c04aChris Lattner  OS << "#endif\n\n";
147f97a00e681c7a526d49759d0d1b9d327cbf6c04aChris Lattner}
148f97a00e681c7a526d49759d0d1b9d327cbf6c04aChris Lattner
149fda6affb95e9f68278cb5cf75dc3fd3406978255Chris Lattnervoid IntrinsicEmitter::
150fda6affb95e9f68278cb5cf75dc3fd3406978255Chris LattnerEmitIntrinsicToNameTable(const std::vector<CodeGenIntrinsic> &Ints,
1511a55180238dbcf11113f610aea010447e51f595bDaniel Dunbar                         raw_ostream &OS) {
152fda6affb95e9f68278cb5cf75dc3fd3406978255Chris Lattner  OS << "// Intrinsic ID to name table\n";
153fda6affb95e9f68278cb5cf75dc3fd3406978255Chris Lattner  OS << "#ifdef GET_INTRINSIC_NAME_TABLE\n";
154fda6affb95e9f68278cb5cf75dc3fd3406978255Chris Lattner  OS << "  // Note that entry #0 is the invalid intrinsic!\n";
155f065a6f711dca09ba36ec8fd3556c4936cdbe621Evan Cheng  for (unsigned i = 0, e = Ints.size(); i != e; ++i)
156f065a6f711dca09ba36ec8fd3556c4936cdbe621Evan Cheng    OS << "  \"" << Ints[i].Name << "\",\n";
157fda6affb95e9f68278cb5cf75dc3fd3406978255Chris Lattner  OS << "#endif\n\n";
158fda6affb95e9f68278cb5cf75dc3fd3406978255Chris Lattner}
159fda6affb95e9f68278cb5cf75dc3fd3406978255Chris Lattner
1600d52ff1f7b993750a74a5d4432273092de9af069Mon P Wangvoid IntrinsicEmitter::
1610d52ff1f7b993750a74a5d4432273092de9af069Mon P WangEmitIntrinsicToOverloadTable(const std::vector<CodeGenIntrinsic> &Ints,
1621a55180238dbcf11113f610aea010447e51f595bDaniel Dunbar                         raw_ostream &OS) {
1630d52ff1f7b993750a74a5d4432273092de9af069Mon P Wang  OS << "// Intrinsic ID to overload table\n";
1640d52ff1f7b993750a74a5d4432273092de9af069Mon P Wang  OS << "#ifdef GET_INTRINSIC_OVERLOAD_TABLE\n";
1650d52ff1f7b993750a74a5d4432273092de9af069Mon P Wang  OS << "  // Note that entry #0 is the invalid intrinsic!\n";
1660d52ff1f7b993750a74a5d4432273092de9af069Mon P Wang  for (unsigned i = 0, e = Ints.size(); i != e; ++i) {
1670d52ff1f7b993750a74a5d4432273092de9af069Mon P Wang    OS << "  ";
1680d52ff1f7b993750a74a5d4432273092de9af069Mon P Wang    if (Ints[i].isOverloaded)
1690d52ff1f7b993750a74a5d4432273092de9af069Mon P Wang      OS << "true";
1700d52ff1f7b993750a74a5d4432273092de9af069Mon P Wang    else
1710d52ff1f7b993750a74a5d4432273092de9af069Mon P Wang      OS << "false";
1720d52ff1f7b993750a74a5d4432273092de9af069Mon P Wang    OS << ",\n";
1730d52ff1f7b993750a74a5d4432273092de9af069Mon P Wang  }
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)";
184825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson  } else if (VT == MVT::f32) {
1851d0be15f89cb5056e20e2d24faa8d6afb1573bcaOwen Anderson    OS << "Type::getFloatTy(Context)";
186825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson  } else if (VT == MVT::f64) {
1871d0be15f89cb5056e20e2d24faa8d6afb1573bcaOwen Anderson    OS << "Type::getDoubleTy(Context)";
188825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson  } else if (VT == MVT::f80) {
1891d0be15f89cb5056e20e2d24faa8d6afb1573bcaOwen Anderson    OS << "Type::getX86_FP80Ty(Context)";
190825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson  } else if (VT == MVT::f128) {
1911d0be15f89cb5056e20e2d24faa8d6afb1573bcaOwen Anderson    OS << "Type::getFP128Ty(Context)";
192825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson  } else if (VT == MVT::ppcf128) {
1931d0be15f89cb5056e20e2d24faa8d6afb1573bcaOwen Anderson    OS << "Type::getPPC_FP128Ty(Context)";
194825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson  } else if (VT == MVT::isVoid) {
1951d0be15f89cb5056e20e2d24faa8d6afb1573bcaOwen Anderson    OS << "Type::getVoidTy(Context)";
196825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson  } else if (VT == MVT::Metadata) {
1971d0be15f89cb5056e20e2d24faa8d6afb1573bcaOwen Anderson    OS << "Type::getMetadataTy(Context)";
1988be452545a1d3921f006c4d5673f14165ceead82Dale Johannesen  } else if (VT == MVT::x86mmx) {
1998be452545a1d3921f006c4d5673f14165ceead82Dale Johannesen    OS << "Type::getX86_MMXTy(Context)";
2006994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth  } else {
2016994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth    assert(false && "Unsupported ValueType!");
20218faf5d9f7f89130b9e3304965b81e1c70ebb75cChris Lattner  }
20318faf5d9f7f89130b9e3304965b81e1c70ebb75cChris Lattner}
20418faf5d9f7f89130b9e3304965b81e1c70ebb75cChris Lattner
2051a55180238dbcf11113f610aea010447e51f595bDaniel Dunbarstatic void EmitTypeGenerate(raw_ostream &OS, const Record *ArgType,
206cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling                             unsigned &ArgNo);
207cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling
2081a55180238dbcf11113f610aea010447e51f595bDaniel Dunbarstatic void EmitTypeGenerate(raw_ostream &OS,
209cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling                             const std::vector<Record*> &ArgTypes,
210cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling                             unsigned &ArgNo) {
21193dc92e412fd06250e46951bffb6040eca9baebdChris Lattner  if (ArgTypes.empty())
21293dc92e412fd06250e46951bffb6040eca9baebdChris Lattner    return EmitTypeForValueType(OS, MVT::isVoid);
21393dc92e412fd06250e46951bffb6040eca9baebdChris Lattner
21493dc92e412fd06250e46951bffb6040eca9baebdChris Lattner  if (ArgTypes.size() == 1)
21593dc92e412fd06250e46951bffb6040eca9baebdChris Lattner    return EmitTypeGenerate(OS, ArgTypes.front(), ArgNo);
216cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling
217d7f2a6cb3fbc012763adb42fd967f6fefbb22a37Owen Anderson  OS << "StructType::get(Context, ";
218cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling
219cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling  for (std::vector<Record*>::const_iterator
22020072af3b0b22d90afbce769409f4ed822520366Bill Wendling         I = ArgTypes.begin(), E = ArgTypes.end(); I != E; ++I) {
221cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling    EmitTypeGenerate(OS, *I, ArgNo);
22220072af3b0b22d90afbce769409f4ed822520366Bill Wendling    OS << ", ";
22320072af3b0b22d90afbce769409f4ed822520366Bill Wendling  }
224cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling
22520072af3b0b22d90afbce769409f4ed822520366Bill Wendling  OS << " NULL)";
226cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling}
227cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling
2281a55180238dbcf11113f610aea010447e51f595bDaniel Dunbarstatic void EmitTypeGenerate(raw_ostream &OS, const Record *ArgType,
22984c614d1ac671b1a5524169f20028f51c30be728Reid Spencer                             unsigned &ArgNo) {
230825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson  MVT::SimpleValueType VT = getValueType(ArgType->getValueAsDef("VT"));
2316994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth
2326994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth  if (ArgType->isSubClassOf("LLVMMatchType")) {
2336994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth    unsigned Number = ArgType->getValueAsInt("Number");
2346994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth    assert(Number < ArgNo && "Invalid matching number!");
235bc03979536a1ecb220f1330719f3e3973a81ab0bBob Wilson    if (ArgType->isSubClassOf("LLVMExtendedElementVectorType"))
236bc03979536a1ecb220f1330719f3e3973a81ab0bBob Wilson      OS << "VectorType::getExtendedElementVectorType"
237bc03979536a1ecb220f1330719f3e3973a81ab0bBob Wilson         << "(dyn_cast<VectorType>(Tys[" << Number << "]))";
238bc03979536a1ecb220f1330719f3e3973a81ab0bBob Wilson    else if (ArgType->isSubClassOf("LLVMTruncatedElementVectorType"))
239bc03979536a1ecb220f1330719f3e3973a81ab0bBob Wilson      OS << "VectorType::getTruncatedElementVectorType"
240bc03979536a1ecb220f1330719f3e3973a81ab0bBob Wilson         << "(dyn_cast<VectorType>(Tys[" << Number << "]))";
241bc03979536a1ecb220f1330719f3e3973a81ab0bBob Wilson    else
242bc03979536a1ecb220f1330719f3e3973a81ab0bBob Wilson      OS << "Tys[" << Number << "]";
243825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson  } else if (VT == MVT::iAny || VT == MVT::fAny || VT == MVT::vAny) {
24484c614d1ac671b1a5524169f20028f51c30be728Reid Spencer    // NOTE: The ArgNo variable here is not the absolute argument number, it is
24584c614d1ac671b1a5524169f20028f51c30be728Reid Spencer    // the index of the "arbitrary" type in the Tys array passed to the
24684c614d1ac671b1a5524169f20028f51c30be728Reid Spencer    // Intrinsic::getDeclaration function. Consequently, we only want to
2476994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth    // increment it when we actually hit an overloaded type. Getting this wrong
2486994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth    // leads to very subtle bugs!
2496994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth    OS << "Tys[" << ArgNo++ << "]";
250e50ed30282bb5b4a9ed952580523f2dda16215acOwen Anderson  } else if (EVT(VT).isVector()) {
251e50ed30282bb5b4a9ed952580523f2dda16215acOwen Anderson    EVT VVT = VT;
2529d6565a5b1fbc4286d6ee638d8f47a3171a9ed7eReid Spencer    OS << "VectorType::get(";
253825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson    EmitTypeForValueType(OS, VVT.getVectorElementType().getSimpleVT().SimpleTy);
25483ec4b6711980242ef3c55a4fa36b2d7a39c1bfbDuncan Sands    OS << ", " << VVT.getVectorNumElements() << ")";
255825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson  } else if (VT == MVT::iPTR) {
25643ad6b3e0d6ada51e9b23aab3e061187f1f5710cChristopher Lamb    OS << "PointerType::getUnqual(";
257c4de3dec62c3f60ae7297f93c19c799c403c2e9fReid Spencer    EmitTypeGenerate(OS, ArgType->getValueAsDef("ElTy"), ArgNo);
25895af592a631f403e1458ec1155f89fc31011572cJim Laskey    OS << ")";
259825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson  } else if (VT == MVT::iPTRAny) {
260e3b3a7241c01f26613694e53b26b01abf764ddfcMon P Wang    // Make sure the user has passed us an argument type to overload. If not,
261e3b3a7241c01f26613694e53b26b01abf764ddfcMon P Wang    // treat it as an ordinary (not overloaded) intrinsic.
262e3b3a7241c01f26613694e53b26b01abf764ddfcMon P Wang    OS << "(" << ArgNo << " < numTys) ? Tys[" << ArgNo
263e3b3a7241c01f26613694e53b26b01abf764ddfcMon P Wang    << "] : PointerType::getUnqual(";
264e3b3a7241c01f26613694e53b26b01abf764ddfcMon P Wang    EmitTypeGenerate(OS, ArgType->getValueAsDef("ElTy"), ArgNo);
265e3b3a7241c01f26613694e53b26b01abf764ddfcMon P Wang    OS << ")";
266e3b3a7241c01f26613694e53b26b01abf764ddfcMon P Wang    ++ArgNo;
267825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson  } else if (VT == MVT::isVoid) {
2686994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth    if (ArgNo == 0)
2691d0be15f89cb5056e20e2d24faa8d6afb1573bcaOwen Anderson      OS << "Type::getVoidTy(Context)";
2706994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth    else
271825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson      // MVT::isVoid is used to mean varargs here.
2726994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth      OS << "...";
27395af592a631f403e1458ec1155f89fc31011572cJim Laskey  } else {
2746994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth    EmitTypeForValueType(OS, VT);
27595af592a631f403e1458ec1155f89fc31011572cJim Laskey  }
27695af592a631f403e1458ec1155f89fc31011572cJim Laskey}
27795af592a631f403e1458ec1155f89fc31011572cJim Laskey
278da4231f134989af7dc6bd3408821ba573def27b2Jim Grosbach/// RecordListComparator - Provide a deterministic comparator for lists of
279c4d9b240b157efa9301d451ac44c12f6b004db8fChris Lattner/// records.
280c4d9b240b157efa9301d451ac44c12f6b004db8fChris Lattnernamespace {
281cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling  typedef std::pair<std::vector<Record*>, std::vector<Record*> > RecPair;
282c4d9b240b157efa9301d451ac44c12f6b004db8fChris Lattner  struct RecordListComparator {
283cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling    bool operator()(const RecPair &LHS,
284cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling                    const RecPair &RHS) const {
285c4d9b240b157efa9301d451ac44c12f6b004db8fChris Lattner      unsigned i = 0;
286cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling      const std::vector<Record*> *LHSVec = &LHS.first;
287cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling      const std::vector<Record*> *RHSVec = &RHS.first;
288cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling      unsigned RHSSize = RHSVec->size();
289cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling      unsigned LHSSize = LHSVec->size();
290cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling
29193dc92e412fd06250e46951bffb6040eca9baebdChris Lattner      for (; 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();
29593dc92e412fd06250e46951bffb6040eca9baebdChris Lattner      }
296cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling
297023422a6eb9ea692a5a837dc1daf256ac75ac6b0Bill Wendling      if (i != RHSSize) return true;
298cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling
299cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling      i = 0;
300cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling      LHSVec = &LHS.second;
301cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling      RHSVec = &RHS.second;
302cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling      RHSSize = RHSVec->size();
303cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling      LHSSize = LHSVec->size();
304cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling
305cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling      for (i = 0; i != LHSSize; ++i) {
306cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling        if (i == RHSSize) return false;  // RHS is shorter than LHS.
307cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling        if ((*LHSVec)[i] != (*RHSVec)[i])
308cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling          return (*LHSVec)[i]->getName() < (*RHSVec)[i]->getName();
309cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling      }
310cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling
311cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling      return i != RHSSize;
312c4d9b240b157efa9301d451ac44c12f6b004db8fChris Lattner    }
313c4d9b240b157efa9301d451ac44c12f6b004db8fChris Lattner  };
314c4d9b240b157efa9301d451ac44c12f6b004db8fChris Lattner}
315c4d9b240b157efa9301d451ac44c12f6b004db8fChris Lattner
316f97a00e681c7a526d49759d0d1b9d327cbf6c04aChris Lattnervoid IntrinsicEmitter::EmitVerifier(const std::vector<CodeGenIntrinsic> &Ints,
3171a55180238dbcf11113f610aea010447e51f595bDaniel Dunbar                                    raw_ostream &OS) {
318f97a00e681c7a526d49759d0d1b9d327cbf6c04aChris Lattner  OS << "// Verifier::visitIntrinsicFunctionCall code.\n";
319f97a00e681c7a526d49759d0d1b9d327cbf6c04aChris Lattner  OS << "#ifdef GET_INTRINSIC_VERIFIER\n";
320f97a00e681c7a526d49759d0d1b9d327cbf6c04aChris Lattner  OS << "  switch (ID) {\n";
321f97a00e681c7a526d49759d0d1b9d327cbf6c04aChris Lattner  OS << "  default: assert(0 && \"Invalid intrinsic!\");\n";
322c4d9b240b157efa9301d451ac44c12f6b004db8fChris Lattner
323c4d9b240b157efa9301d451ac44c12f6b004db8fChris Lattner  // This checking can emit a lot of very common code.  To reduce the amount of
324c4d9b240b157efa9301d451ac44c12f6b004db8fChris Lattner  // code that we emit, batch up cases that have identical types.  This avoids
325c4d9b240b157efa9301d451ac44c12f6b004db8fChris Lattner  // problems where GCC can run out of memory compiling Verifier.cpp.
326cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling  typedef std::map<RecPair, std::vector<unsigned>, RecordListComparator> MapTy;
327c4d9b240b157efa9301d451ac44c12f6b004db8fChris Lattner  MapTy UniqueArgInfos;
328c4d9b240b157efa9301d451ac44c12f6b004db8fChris Lattner
329c4d9b240b157efa9301d451ac44c12f6b004db8fChris Lattner  // Compute the unique argument type info.
330c4d9b240b157efa9301d451ac44c12f6b004db8fChris Lattner  for (unsigned i = 0, e = Ints.size(); i != e; ++i)
331cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling    UniqueArgInfos[make_pair(Ints[i].IS.RetTypeDefs,
332cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling                             Ints[i].IS.ParamTypeDefs)].push_back(i);
333c4d9b240b157efa9301d451ac44c12f6b004db8fChris Lattner
334c4d9b240b157efa9301d451ac44c12f6b004db8fChris Lattner  // Loop through the array, emitting one comparison for each batch.
335c4d9b240b157efa9301d451ac44c12f6b004db8fChris Lattner  for (MapTy::iterator I = UniqueArgInfos.begin(),
336c4d9b240b157efa9301d451ac44c12f6b004db8fChris Lattner       E = UniqueArgInfos.end(); I != E; ++I) {
337cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling    for (unsigned i = 0, e = I->second.size(); i != e; ++i)
338c4d9b240b157efa9301d451ac44c12f6b004db8fChris Lattner      OS << "  case Intrinsic::" << Ints[I->second[i]].EnumName << ":\t\t// "
339c4d9b240b157efa9301d451ac44c12f6b004db8fChris Lattner         << Ints[I->second[i]].Name << "\n";
340f124b46b4f18b1a8f054a1222324ae15079f6ed8Chris Lattner
341cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling    const RecPair &ArgTypes = I->first;
342cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling    const std::vector<Record*> &RetTys = ArgTypes.first;
343cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling    const std::vector<Record*> &ParamTys = ArgTypes.second;
34409b1366f3f310b5648aa8cd72ed16b9f19b4c68dBob Wilson    std::vector<unsigned> OverloadedTypeIndices;
345cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling
346cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling    OS << "    VerifyIntrinsicPrototype(ID, IF, " << RetTys.size() << ", "
347cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling       << ParamTys.size();
348cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling
349cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling    // Emit return types.
350cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling    for (unsigned j = 0, je = RetTys.size(); j != je; ++j) {
351cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling      Record *ArgType = RetTys[j];
352cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling      OS << ", ";
353cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling
3546994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth      if (ArgType->isSubClassOf("LLVMMatchType")) {
3556994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth        unsigned Number = ArgType->getValueAsInt("Number");
35609b1366f3f310b5648aa8cd72ed16b9f19b4c68dBob Wilson        assert(Number < OverloadedTypeIndices.size() &&
35709b1366f3f310b5648aa8cd72ed16b9f19b4c68dBob Wilson               "Invalid matching number!");
35809b1366f3f310b5648aa8cd72ed16b9f19b4c68dBob Wilson        Number = OverloadedTypeIndices[Number];
359bc03979536a1ecb220f1330719f3e3973a81ab0bBob Wilson        if (ArgType->isSubClassOf("LLVMExtendedElementVectorType"))
360bc03979536a1ecb220f1330719f3e3973a81ab0bBob Wilson          OS << "~(ExtendedElementVectorType | " << Number << ")";
361bc03979536a1ecb220f1330719f3e3973a81ab0bBob Wilson        else if (ArgType->isSubClassOf("LLVMTruncatedElementVectorType"))
362bc03979536a1ecb220f1330719f3e3973a81ab0bBob Wilson          OS << "~(TruncatedElementVectorType | " << Number << ")";
363bc03979536a1ecb220f1330719f3e3973a81ab0bBob Wilson        else
364bc03979536a1ecb220f1330719f3e3973a81ab0bBob Wilson          OS << "~" << Number;
3656994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth      } else {
366825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson        MVT::SimpleValueType VT = getValueType(ArgType->getValueAsDef("VT"));
3676994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth        OS << getEnumName(VT);
368cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling
36961fc4cf7aa0b87ceab62082cee8ef5ce3f574ffcBob Wilson        if (EVT(VT).isOverloaded())
37009b1366f3f310b5648aa8cd72ed16b9f19b4c68dBob Wilson          OverloadedTypeIndices.push_back(j);
37109b1366f3f310b5648aa8cd72ed16b9f19b4c68dBob Wilson
372825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson        if (VT == MVT::isVoid && j != 0 && j != je - 1)
373cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling          throw "Var arg type not last argument";
374cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling      }
375cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling    }
376cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling
377cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling    // Emit the parameter types.
378cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling    for (unsigned j = 0, je = ParamTys.size(); j != je; ++j) {
379cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling      Record *ArgType = ParamTys[j];
380cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling      OS << ", ";
381cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling
382cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling      if (ArgType->isSubClassOf("LLVMMatchType")) {
383cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling        unsigned Number = ArgType->getValueAsInt("Number");
38409b1366f3f310b5648aa8cd72ed16b9f19b4c68dBob Wilson        assert(Number < OverloadedTypeIndices.size() &&
38509b1366f3f310b5648aa8cd72ed16b9f19b4c68dBob Wilson               "Invalid matching number!");
38609b1366f3f310b5648aa8cd72ed16b9f19b4c68dBob Wilson        Number = OverloadedTypeIndices[Number];
387bc03979536a1ecb220f1330719f3e3973a81ab0bBob Wilson        if (ArgType->isSubClassOf("LLVMExtendedElementVectorType"))
388bc03979536a1ecb220f1330719f3e3973a81ab0bBob Wilson          OS << "~(ExtendedElementVectorType | " << Number << ")";
389bc03979536a1ecb220f1330719f3e3973a81ab0bBob Wilson        else if (ArgType->isSubClassOf("LLVMTruncatedElementVectorType"))
390bc03979536a1ecb220f1330719f3e3973a81ab0bBob Wilson          OS << "~(TruncatedElementVectorType | " << Number << ")";
391bc03979536a1ecb220f1330719f3e3973a81ab0bBob Wilson        else
392bc03979536a1ecb220f1330719f3e3973a81ab0bBob Wilson          OS << "~" << Number;
393cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling      } else {
394825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson        MVT::SimpleValueType VT = getValueType(ArgType->getValueAsDef("VT"));
395cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling        OS << getEnumName(VT);
396cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling
39761fc4cf7aa0b87ceab62082cee8ef5ce3f574ffcBob Wilson        if (EVT(VT).isOverloaded())
39809b1366f3f310b5648aa8cd72ed16b9f19b4c68dBob Wilson          OverloadedTypeIndices.push_back(j + RetTys.size());
39909b1366f3f310b5648aa8cd72ed16b9f19b4c68dBob Wilson
400825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson        if (VT == MVT::isVoid && j != 0 && j != je - 1)
40195d97b90e8427255c8298f5d3a1ab605af62aab4Jim Laskey          throw "Var arg type not last argument";
40295d97b90e8427255c8298f5d3a1ab605af62aab4Jim Laskey      }
40395d97b90e8427255c8298f5d3a1ab605af62aab4Jim Laskey    }
40495d97b90e8427255c8298f5d3a1ab605af62aab4Jim Laskey
4056994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth    OS << ");\n";
406f97a00e681c7a526d49759d0d1b9d327cbf6c04aChris Lattner    OS << "    break;\n";
407f97a00e681c7a526d49759d0d1b9d327cbf6c04aChris Lattner  }
408f97a00e681c7a526d49759d0d1b9d327cbf6c04aChris Lattner  OS << "  }\n";
409f97a00e681c7a526d49759d0d1b9d327cbf6c04aChris Lattner  OS << "#endif\n\n";
4109b843b249462980ae4630dc37d1bcccde884a5a7Chris Lattner}
4119b843b249462980ae4630dc37d1bcccde884a5a7Chris Lattner
41295af592a631f403e1458ec1155f89fc31011572cJim Laskeyvoid IntrinsicEmitter::EmitGenerator(const std::vector<CodeGenIntrinsic> &Ints,
4131a55180238dbcf11113f610aea010447e51f595bDaniel Dunbar                                     raw_ostream &OS) {
41495af592a631f403e1458ec1155f89fc31011572cJim Laskey  OS << "// Code for generating Intrinsic function declarations.\n";
41595af592a631f403e1458ec1155f89fc31011572cJim Laskey  OS << "#ifdef GET_INTRINSIC_GENERATOR\n";
41695af592a631f403e1458ec1155f89fc31011572cJim Laskey  OS << "  switch (id) {\n";
41795af592a631f403e1458ec1155f89fc31011572cJim Laskey  OS << "  default: assert(0 && \"Invalid intrinsic!\");\n";
41895af592a631f403e1458ec1155f89fc31011572cJim Laskey
41995af592a631f403e1458ec1155f89fc31011572cJim Laskey  // Similar to GET_INTRINSIC_VERIFIER, batch up cases that have identical
42095af592a631f403e1458ec1155f89fc31011572cJim Laskey  // types.
421cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling  typedef std::map<RecPair, std::vector<unsigned>, RecordListComparator> MapTy;
42295af592a631f403e1458ec1155f89fc31011572cJim Laskey  MapTy UniqueArgInfos;
42395af592a631f403e1458ec1155f89fc31011572cJim Laskey
42495af592a631f403e1458ec1155f89fc31011572cJim Laskey  // Compute the unique argument type info.
42595af592a631f403e1458ec1155f89fc31011572cJim Laskey  for (unsigned i = 0, e = Ints.size(); i != e; ++i)
426cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling    UniqueArgInfos[make_pair(Ints[i].IS.RetTypeDefs,
427cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling                             Ints[i].IS.ParamTypeDefs)].push_back(i);
42895af592a631f403e1458ec1155f89fc31011572cJim Laskey
42995af592a631f403e1458ec1155f89fc31011572cJim Laskey  // Loop through the array, emitting one generator for each batch.
43049de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen  std::string IntrinsicStr = TargetPrefix + "Intrinsic::";
43149de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen
43295af592a631f403e1458ec1155f89fc31011572cJim Laskey  for (MapTy::iterator I = UniqueArgInfos.begin(),
43395af592a631f403e1458ec1155f89fc31011572cJim Laskey       E = UniqueArgInfos.end(); I != E; ++I) {
434cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling    for (unsigned i = 0, e = I->second.size(); i != e; ++i)
43549de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen      OS << "  case " << IntrinsicStr << Ints[I->second[i]].EnumName
43649de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen         << ":\t\t// " << Ints[I->second[i]].Name << "\n";
43795af592a631f403e1458ec1155f89fc31011572cJim Laskey
438cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling    const RecPair &ArgTypes = I->first;
439cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling    const std::vector<Record*> &RetTys = ArgTypes.first;
440cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling    const std::vector<Record*> &ParamTys = ArgTypes.second;
441cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling
442cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling    unsigned N = ParamTys.size();
44395af592a631f403e1458ec1155f89fc31011572cJim Laskey
4446994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth    if (N > 1 &&
445825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson        getValueType(ParamTys[N - 1]->getValueAsDef("VT")) == MVT::isVoid) {
44695af592a631f403e1458ec1155f89fc31011572cJim Laskey      OS << "    IsVarArg = true;\n";
44795af592a631f403e1458ec1155f89fc31011572cJim Laskey      --N;
44895af592a631f403e1458ec1155f89fc31011572cJim Laskey    }
449cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling
45084c614d1ac671b1a5524169f20028f51c30be728Reid Spencer    unsigned ArgNo = 0;
45195af592a631f403e1458ec1155f89fc31011572cJim Laskey    OS << "    ResultTy = ";
452cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling    EmitTypeGenerate(OS, RetTys, ArgNo);
45395af592a631f403e1458ec1155f89fc31011572cJim Laskey    OS << ";\n";
45495af592a631f403e1458ec1155f89fc31011572cJim Laskey
455cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling    for (unsigned j = 0; j != N; ++j) {
45695af592a631f403e1458ec1155f89fc31011572cJim Laskey      OS << "    ArgTys.push_back(";
457cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling      EmitTypeGenerate(OS, ParamTys[j], ArgNo);
45895af592a631f403e1458ec1155f89fc31011572cJim Laskey      OS << ");\n";
45995af592a631f403e1458ec1155f89fc31011572cJim Laskey    }
460cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling
46195af592a631f403e1458ec1155f89fc31011572cJim Laskey    OS << "    break;\n";
46295af592a631f403e1458ec1155f89fc31011572cJim Laskey  }
463cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling
46495af592a631f403e1458ec1155f89fc31011572cJim Laskey  OS << "  }\n";
46595af592a631f403e1458ec1155f89fc31011572cJim Laskey  OS << "#endif\n\n";
46695af592a631f403e1458ec1155f89fc31011572cJim Laskey}
46795af592a631f403e1458ec1155f89fc31011572cJim Laskey
468bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCallnamespace {
469bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall  enum ModRefKind {
470bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall    MRK_none,
471bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall    MRK_readonly,
472bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall    MRK_readnone
473bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall  };
474bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall
475bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall  ModRefKind getModRefKind(const CodeGenIntrinsic &intrinsic) {
476bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall    switch (intrinsic.ModRef) {
477bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall    case CodeGenIntrinsic::NoMem:
478bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall      return MRK_readnone;
479bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall    case CodeGenIntrinsic::ReadArgMem:
480bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall    case CodeGenIntrinsic::ReadMem:
481bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall      return MRK_readonly;
482bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall    case CodeGenIntrinsic::ReadWriteArgMem:
483bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall    case CodeGenIntrinsic::ReadWriteMem:
484bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall      return MRK_none;
485bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall    }
486bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall    assert(0 && "bad mod-ref kind");
487bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall    return MRK_none;
488bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall  }
489bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall
490bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall  struct AttributeComparator {
491bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall    bool operator()(const CodeGenIntrinsic *L, const CodeGenIntrinsic *R) const {
492bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall      // Sort throwing intrinsics after non-throwing intrinsics.
493bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall      if (L->canThrow != R->canThrow)
494bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall        return R->canThrow;
495bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall
496bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall      // Try to order by readonly/readnone attribute.
497bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall      ModRefKind LK = getModRefKind(*L);
498bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall      ModRefKind RK = getModRefKind(*R);
499bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall      if (LK != RK) return (LK > RK);
500bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall
501bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall      // Order by argument attributes.
502bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall      // This is reliable because each side is already sorted internally.
503bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall      return (L->ArgumentAttributes < R->ArgumentAttributes);
504bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall    }
505bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall  };
506bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall}
507bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall
508048ffb239c282277959463c61200b86e2380cb84Chris Lattner/// EmitAttributes - This emits the Intrinsic::getAttributes method.
5094e5f35973c1bc56cce14d44c6f8f4ad1e9f1a438Chris Lattnervoid IntrinsicEmitter::
5101a55180238dbcf11113f610aea010447e51f595bDaniel DunbarEmitAttributes(const std::vector<CodeGenIntrinsic> &Ints, raw_ostream &OS) {
511a3355ffb3d30d19d226bbb75707991c60f236e37Duncan Sands  OS << "// Add parameter attributes that are not common to all intrinsics.\n";
512a3355ffb3d30d19d226bbb75707991c60f236e37Duncan Sands  OS << "#ifdef GET_INTRINSIC_ATTRIBUTES\n";
51349de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen  if (TargetOnly)
51449de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen    OS << "static AttrListPtr getAttributes(" << TargetPrefix
515bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall       << "Intrinsic::ID id) {\n";
51649de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen  else
517bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall    OS << "AttrListPtr Intrinsic::getAttributes(ID id) {\n";
518bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall
519bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall  // Compute the maximum number of attribute arguments.
520bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall  std::vector<const CodeGenIntrinsic*> sortedIntrinsics(Ints.size());
521bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall  unsigned maxArgAttrs = 0;
5224e5f35973c1bc56cce14d44c6f8f4ad1e9f1a438Chris Lattner  for (unsigned i = 0, e = Ints.size(); i != e; ++i) {
523bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall    const CodeGenIntrinsic &intrinsic = Ints[i];
524bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall    sortedIntrinsics[i] = &intrinsic;
525bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall    maxArgAttrs =
526bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall      std::max(maxArgAttrs, unsigned(intrinsic.ArgumentAttributes.size()));
5274e5f35973c1bc56cce14d44c6f8f4ad1e9f1a438Chris Lattner  }
528bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall
529bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall  // Emit an array of AttributeWithIndex.  Most intrinsics will have
530bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall  // at least one entry, for the function itself (index ~1), which is
531bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall  // usually nounwind.
532bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall  OS << "  AttributeWithIndex AWI[" << maxArgAttrs+1 << "];\n";
533d4a2700fdc5bc8ac50084fcb39155e01e86168d5Chris Lattner  OS << "  unsigned NumAttrs = 0;\n";
53410dae94be2ccb187bd4e3da53771be54057acd6cChris Lattner  OS << "  switch (id) {\n";
535bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall  OS << "    default: break;\n";
536bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall
537bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall  AttributeComparator precedes;
538bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall
539bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall  std::stable_sort(sortedIntrinsics.begin(), sortedIntrinsics.end(), precedes);
54010dae94be2ccb187bd4e3da53771be54057acd6cChris Lattner
541bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall  for (unsigned i = 0, e = sortedIntrinsics.size(); i != e; ++i) {
542bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall    const CodeGenIntrinsic &intrinsic = *sortedIntrinsics[i];
543bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall    OS << "  case " << TargetPrefix << "Intrinsic::"
544bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall       << intrinsic.EnumName << ":\n";
54510dae94be2ccb187bd4e3da53771be54057acd6cChris Lattner
546bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall    // Fill out the case if this is the last case for this range of
547bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall    // intrinsics.
548bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall    if (i + 1 != e && !precedes(&intrinsic, sortedIntrinsics[i + 1]))
549bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall      continue;
550bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall
551bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall    // Keep track of the number of attributes we're writing out.
552bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall    unsigned numAttrs = 0;
55310dae94be2ccb187bd4e3da53771be54057acd6cChris Lattner
554bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall    // The argument attributes are alreadys sorted by argument index.
555bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall    for (unsigned ai = 0, ae = intrinsic.ArgumentAttributes.size(); ai != ae;) {
556bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall      unsigned argNo = intrinsic.ArgumentAttributes[ai].first;
557d4a2700fdc5bc8ac50084fcb39155e01e86168d5Chris Lattner
558bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall      OS << "    AWI[" << numAttrs++ << "] = AttributeWithIndex::get("
559bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall         << argNo+1 << ", ";
560bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall
561bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall      bool moreThanOne = false;
562d4a2700fdc5bc8ac50084fcb39155e01e86168d5Chris Lattner
563bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall      do {
564bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall        if (moreThanOne) OS << '|';
565bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall
566bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall        switch (intrinsic.ArgumentAttributes[ai].second) {
567d4a2700fdc5bc8ac50084fcb39155e01e86168d5Chris Lattner        case CodeGenIntrinsic::NoCapture:
568bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall          OS << "Attribute::NoCapture";
569d4a2700fdc5bc8ac50084fcb39155e01e86168d5Chris Lattner          break;
570d4a2700fdc5bc8ac50084fcb39155e01e86168d5Chris Lattner        }
571bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall
572bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall        ++ai;
573bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall        moreThanOne = true;
574bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall      } while (ai != ae && intrinsic.ArgumentAttributes[ai].first == argNo);
575bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall
576bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall      OS << ");\n";
577bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall    }
578bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall
579bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall    ModRefKind modRef = getModRefKind(intrinsic);
580bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall
581bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall    if (!intrinsic.canThrow || modRef) {
582bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall      OS << "    AWI[" << numAttrs++ << "] = AttributeWithIndex::get(~0, ";
583bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall      if (!intrinsic.canThrow) {
584bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall        OS << "Attribute::NoUnwind";
585bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall        if (modRef) OS << '|';
586bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall      }
587bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall      switch (modRef) {
588bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall      case MRK_none: break;
589bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall      case MRK_readonly: OS << "Attribute::ReadOnly"; break;
590bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall      case MRK_readnone: OS << "Attribute::ReadNone"; break;
591d4a2700fdc5bc8ac50084fcb39155e01e86168d5Chris Lattner      }
592d4a2700fdc5bc8ac50084fcb39155e01e86168d5Chris Lattner      OS << ");\n";
593d4a2700fdc5bc8ac50084fcb39155e01e86168d5Chris Lattner    }
594bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall
595bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall    if (numAttrs) {
596bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall      OS << "    NumAttrs = " << numAttrs << ";\n";
597bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall      OS << "    break;\n";
598bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall    } else {
599bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall      OS << "    return AttrListPtr();\n";
600bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall    }
60110dae94be2ccb187bd4e3da53771be54057acd6cChris Lattner  }
60210dae94be2ccb187bd4e3da53771be54057acd6cChris Lattner
60310dae94be2ccb187bd4e3da53771be54057acd6cChris Lattner  OS << "  }\n";
604bd0fa4c00d7870b1da36eac7b2181700381f2f96John McCall  OS << "  return AttrListPtr::get(AWI, NumAttrs);\n";
605048ffb239c282277959463c61200b86e2380cb84Chris Lattner  OS << "}\n";
606d4a2700fdc5bc8ac50084fcb39155e01e86168d5Chris Lattner  OS << "#endif // GET_INTRINSIC_ATTRIBUTES\n\n";
6074e5f35973c1bc56cce14d44c6f8f4ad1e9f1a438Chris Lattner}
608022f64fbbc4669623e79b805379266fed519017dChris Lattner
609d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands/// EmitModRefBehavior - Determine intrinsic alias analysis mod/ref behavior.
610d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sandsvoid IntrinsicEmitter::
6111a55180238dbcf11113f610aea010447e51f595bDaniel DunbarEmitModRefBehavior(const std::vector<CodeGenIntrinsic> &Ints, raw_ostream &OS){
612d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands  OS << "// Determine intrinsic alias analysis mod/ref behavior.\n";
613d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands  OS << "#ifdef GET_INTRINSIC_MODREF_BEHAVIOR\n";
6147c422ac216fe39fc9c402a704cf296cca9dc5b22Duncan Sands  OS << "switch (iid) {\n";
615d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands  OS << "default:\n    return UnknownModRefBehavior;\n";
616d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands  for (unsigned i = 0, e = Ints.size(); i != e; ++i) {
6177365c091f92db5e68c98d7faedc6c34e1bbbc898Dan Gohman    if (Ints[i].ModRef == CodeGenIntrinsic::ReadWriteMem)
618d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands      continue;
619d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands    OS << "case " << TargetPrefix << "Intrinsic::" << Ints[i].EnumName
620d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands      << ":\n";
621d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands    switch (Ints[i].ModRef) {
622d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands    default:
623d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands      assert(false && "Unknown Mod/Ref type!");
624d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands    case CodeGenIntrinsic::NoMem:
625d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands      OS << "  return DoesNotAccessMemory;\n";
626d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands      break;
627d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands    case CodeGenIntrinsic::ReadArgMem:
628e88ccb545d0e03fd4445d361100fc95f350c6663Dan Gohman      OS << "  return OnlyReadsArgumentPointees;\n";
6299423f633654af6045b1efa7795edfe8ea0533d7eDan Gohman      break;
630d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands    case CodeGenIntrinsic::ReadMem:
631d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands      OS << "  return OnlyReadsMemory;\n";
632d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands      break;
6337365c091f92db5e68c98d7faedc6c34e1bbbc898Dan Gohman    case CodeGenIntrinsic::ReadWriteArgMem:
634e88ccb545d0e03fd4445d361100fc95f350c6663Dan Gohman      OS << "  return OnlyAccessesArgumentPointees;\n";
635d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands      break;
636d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands    }
637d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands  }
638d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands  OS << "}\n";
639d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands  OS << "#endif // GET_INTRINSIC_MODREF_BEHAVIOR\n\n";
640d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands}
641d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands
642022f64fbbc4669623e79b805379266fed519017dChris Lattnervoid IntrinsicEmitter::
6431a55180238dbcf11113f610aea010447e51f595bDaniel DunbarEmitGCCBuiltinList(const std::vector<CodeGenIntrinsic> &Ints, raw_ostream &OS){
644022f64fbbc4669623e79b805379266fed519017dChris Lattner  OS << "// Get the GCC builtin that corresponds to an LLVM intrinsic.\n";
645022f64fbbc4669623e79b805379266fed519017dChris Lattner  OS << "#ifdef GET_GCC_BUILTIN_NAME\n";
646022f64fbbc4669623e79b805379266fed519017dChris Lattner  OS << "  switch (F->getIntrinsicID()) {\n";
647022f64fbbc4669623e79b805379266fed519017dChris Lattner  OS << "  default: BuiltinName = \"\"; break;\n";
648022f64fbbc4669623e79b805379266fed519017dChris Lattner  for (unsigned i = 0, e = Ints.size(); i != e; ++i) {
649022f64fbbc4669623e79b805379266fed519017dChris Lattner    if (!Ints[i].GCCBuiltinName.empty()) {
650022f64fbbc4669623e79b805379266fed519017dChris Lattner      OS << "  case Intrinsic::" << Ints[i].EnumName << ": BuiltinName = \""
651022f64fbbc4669623e79b805379266fed519017dChris Lattner         << Ints[i].GCCBuiltinName << "\"; break;\n";
652022f64fbbc4669623e79b805379266fed519017dChris Lattner    }
653022f64fbbc4669623e79b805379266fed519017dChris Lattner  }
654022f64fbbc4669623e79b805379266fed519017dChris Lattner  OS << "  }\n";
655022f64fbbc4669623e79b805379266fed519017dChris Lattner  OS << "#endif\n\n";
656767a25b8788b5e313c99c16b4d359478432901f5Reid Spencer}
6573f8b8913bc9cb232871445eefa8654caf7f9986fChris Lattner
658331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner/// EmitTargetBuiltins - All of the builtins in the specified map are for the
659331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner/// same target, and we already checked it.
660331bf92fb51f058672144681b3d0e67d30f5699fChris Lattnerstatic void EmitTargetBuiltins(const std::map<std::string, std::string> &BIM,
66149de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen                               const std::string &TargetPrefix,
6621a55180238dbcf11113f610aea010447e51f595bDaniel Dunbar                               raw_ostream &OS) {
663331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner
664298b176559d5c76d7d9f7fdd06429a75892de043Chris Lattner  std::vector<StringMatcher::StringPair> Results;
665331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner
666298b176559d5c76d7d9f7fdd06429a75892de043Chris Lattner  for (std::map<std::string, std::string>::const_iterator I = BIM.begin(),
667298b176559d5c76d7d9f7fdd06429a75892de043Chris Lattner       E = BIM.end(); I != E; ++I) {
668298b176559d5c76d7d9f7fdd06429a75892de043Chris Lattner    std::string ResultCode =
669298b176559d5c76d7d9f7fdd06429a75892de043Chris Lattner    "return " + TargetPrefix + "Intrinsic::" + I->second + ";";
670298b176559d5c76d7d9f7fdd06429a75892de043Chris Lattner    Results.push_back(StringMatcher::StringPair(I->first, ResultCode));
671331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner  }
672298b176559d5c76d7d9f7fdd06429a75892de043Chris Lattner
673298b176559d5c76d7d9f7fdd06429a75892de043Chris Lattner  StringMatcher("BuiltinName", Results, OS).Emit();
674331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner}
675331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner
676331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner
6773f8b8913bc9cb232871445eefa8654caf7f9986fChris Lattnervoid IntrinsicEmitter::
6783f8b8913bc9cb232871445eefa8654caf7f9986fChris LattnerEmitIntrinsicToGCCBuiltinMap(const std::vector<CodeGenIntrinsic> &Ints,
6791a55180238dbcf11113f610aea010447e51f595bDaniel Dunbar                             raw_ostream &OS) {
680fa0fba1c546091c485e5513eadeef181dda370abChris Lattner  typedef std::map<std::string, std::map<std::string, std::string> > BIMTy;
6813f8b8913bc9cb232871445eefa8654caf7f9986fChris Lattner  BIMTy BuiltinMap;
6823f8b8913bc9cb232871445eefa8654caf7f9986fChris Lattner  for (unsigned i = 0, e = Ints.size(); i != e; ++i) {
6833f8b8913bc9cb232871445eefa8654caf7f9986fChris Lattner    if (!Ints[i].GCCBuiltinName.empty()) {
684fa0fba1c546091c485e5513eadeef181dda370abChris Lattner      // Get the map for this target prefix.
685fa0fba1c546091c485e5513eadeef181dda370abChris Lattner      std::map<std::string, std::string> &BIM =BuiltinMap[Ints[i].TargetPrefix];
686fa0fba1c546091c485e5513eadeef181dda370abChris Lattner
687fa0fba1c546091c485e5513eadeef181dda370abChris Lattner      if (!BIM.insert(std::make_pair(Ints[i].GCCBuiltinName,
688fa0fba1c546091c485e5513eadeef181dda370abChris Lattner                                     Ints[i].EnumName)).second)
6893f8b8913bc9cb232871445eefa8654caf7f9986fChris Lattner        throw "Intrinsic '" + Ints[i].TheDef->getName() +
6903f8b8913bc9cb232871445eefa8654caf7f9986fChris Lattner              "': duplicate GCC builtin name!";
6913f8b8913bc9cb232871445eefa8654caf7f9986fChris Lattner    }
6923f8b8913bc9cb232871445eefa8654caf7f9986fChris Lattner  }
6933f8b8913bc9cb232871445eefa8654caf7f9986fChris Lattner
6943f8b8913bc9cb232871445eefa8654caf7f9986fChris Lattner  OS << "// Get the LLVM intrinsic that corresponds to a GCC builtin.\n";
6953f8b8913bc9cb232871445eefa8654caf7f9986fChris Lattner  OS << "// This is used by the C front-end.  The GCC builtin name is passed\n";
6963f8b8913bc9cb232871445eefa8654caf7f9986fChris Lattner  OS << "// in as BuiltinName, and a target prefix (e.g. 'ppc') is passed\n";
6973f8b8913bc9cb232871445eefa8654caf7f9986fChris Lattner  OS << "// in as TargetPrefix.  The result is assigned to 'IntrinsicID'.\n";
6983f8b8913bc9cb232871445eefa8654caf7f9986fChris Lattner  OS << "#ifdef GET_LLVM_INTRINSIC_FOR_GCC_BUILTIN\n";
69949de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen
70049de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen  if (TargetOnly) {
70149de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen    OS << "static " << TargetPrefix << "Intrinsic::ID "
70249de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen       << "getIntrinsicForGCCBuiltin(const char "
703298b176559d5c76d7d9f7fdd06429a75892de043Chris Lattner       << "*TargetPrefixStr, const char *BuiltinNameStr) {\n";
70449de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen  } else {
70549de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen    OS << "Intrinsic::ID Intrinsic::getIntrinsicForGCCBuiltin(const char "
706298b176559d5c76d7d9f7fdd06429a75892de043Chris Lattner       << "*TargetPrefixStr, const char *BuiltinNameStr) {\n";
70749de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen  }
70849de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen
709298b176559d5c76d7d9f7fdd06429a75892de043Chris Lattner  OS << "  StringRef BuiltinName(BuiltinNameStr);\n";
710298b176559d5c76d7d9f7fdd06429a75892de043Chris Lattner  OS << "  StringRef TargetPrefix(TargetPrefixStr);\n\n";
711331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner
7123f8b8913bc9cb232871445eefa8654caf7f9986fChris Lattner  // Note: this could emit significantly better code if we cared.
7133f8b8913bc9cb232871445eefa8654caf7f9986fChris Lattner  for (BIMTy::iterator I = BuiltinMap.begin(), E = BuiltinMap.end();I != E;++I){
714fa0fba1c546091c485e5513eadeef181dda370abChris Lattner    OS << "  ";
715fa0fba1c546091c485e5513eadeef181dda370abChris Lattner    if (!I->first.empty())
716298b176559d5c76d7d9f7fdd06429a75892de043Chris Lattner      OS << "if (TargetPrefix == \"" << I->first << "\") ";
717fa0fba1c546091c485e5513eadeef181dda370abChris Lattner    else
718fa0fba1c546091c485e5513eadeef181dda370abChris Lattner      OS << "/* Target Independent Builtins */ ";
719fa0fba1c546091c485e5513eadeef181dda370abChris Lattner    OS << "{\n";
720fa0fba1c546091c485e5513eadeef181dda370abChris Lattner
721fa0fba1c546091c485e5513eadeef181dda370abChris Lattner    // Emit the comparisons for this target prefix.
72249de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen    EmitTargetBuiltins(I->second, TargetPrefix, OS);
723fa0fba1c546091c485e5513eadeef181dda370abChris Lattner    OS << "  }\n";
7243f8b8913bc9cb232871445eefa8654caf7f9986fChris Lattner  }
725298b176559d5c76d7d9f7fdd06429a75892de043Chris Lattner  OS << "  return ";
726298b176559d5c76d7d9f7fdd06429a75892de043Chris Lattner  if (!TargetPrefix.empty())
727298b176559d5c76d7d9f7fdd06429a75892de043Chris Lattner    OS << "(" << TargetPrefix << "Intrinsic::ID)";
728298b176559d5c76d7d9f7fdd06429a75892de043Chris Lattner  OS << "Intrinsic::not_intrinsic;\n";
72949de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen  OS << "}\n";
7303f8b8913bc9cb232871445eefa8654caf7f9986fChris Lattner  OS << "#endif\n\n";
7313f8b8913bc9cb232871445eefa8654caf7f9986fChris Lattner}
732