IntrinsicEmitter.cpp revision cc67c75b67d22653ea9380020e9a40381233901d
19e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner//===- IntrinsicEmitter.cpp - Generate intrinsic information --------------===//
29e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner//
39e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner//                     The LLVM Compiler Infrastructure
49e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner//
53060910e290949a9ac5eda8726d030790c4d60ffChris Lattner// This file is distributed under the University of Illinois Open Source
63060910e290949a9ac5eda8726d030790c4d60ffChris Lattner// License. See LICENSE.TXT for details.
79e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner//
89e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner//===----------------------------------------------------------------------===//
99e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner//
109e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner// This tablegen backend emits information about intrinsic functions.
119e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner//
129e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner//===----------------------------------------------------------------------===//
139e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner
146994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth#include "CodeGenTarget.h"
159e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner#include "IntrinsicEmitter.h"
169e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner#include "Record.h"
17298b176559d5c76d7d9f7fdd06429a75892de043Chris Lattner#include "StringMatcher.h"
1818faf5d9f7f89130b9e3304965b81e1c70ebb75cChris Lattner#include "llvm/ADT/StringExtras.h"
1971c3bc3d966bd874f760abf055c559673f925029Jeff Cohen#include <algorithm>
209e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattnerusing namespace llvm;
219e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner
229e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner//===----------------------------------------------------------------------===//
239e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner// IntrinsicEmitter Implementation
249e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner//===----------------------------------------------------------------------===//
259e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner
261a55180238dbcf11113f610aea010447e51f595bDaniel Dunbarvoid IntrinsicEmitter::run(raw_ostream &OS) {
279e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner  EmitSourceFileHeader("Intrinsic Function Source Fragment", OS);
289e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner
2949de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen  std::vector<CodeGenIntrinsic> Ints = LoadIntrinsics(Records, TargetOnly);
3049de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen
3149de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen  if (TargetOnly && !Ints.empty())
3249de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen    TargetPrefix = Ints[0].TargetPrefix;
339e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner
347d9663c70b3300070298d716dba6e6f6ce2d1e3eDouglas Gregor  EmitPrefix(OS);
357d9663c70b3300070298d716dba6e6f6ce2d1e3eDouglas Gregor
369e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner  // Emit the enum information.
379e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner  EmitEnumInfo(Ints, OS);
38fda6affb95e9f68278cb5cf75dc3fd3406978255Chris Lattner
39fda6affb95e9f68278cb5cf75dc3fd3406978255Chris Lattner  // Emit the intrinsic ID -> name table.
40fda6affb95e9f68278cb5cf75dc3fd3406978255Chris Lattner  EmitIntrinsicToNameTable(Ints, OS);
410d52ff1f7b993750a74a5d4432273092de9af069Mon P Wang
420d52ff1f7b993750a74a5d4432273092de9af069Mon P Wang  // Emit the intrinsic ID -> overload table.
430d52ff1f7b993750a74a5d4432273092de9af069Mon P Wang  EmitIntrinsicToOverloadTable(Ints, OS);
440d52ff1f7b993750a74a5d4432273092de9af069Mon P Wang
459b843b249462980ae4630dc37d1bcccde884a5a7Chris Lattner  // Emit the function name recognizer.
469b843b249462980ae4630dc37d1bcccde884a5a7Chris Lattner  EmitFnNameRecognizer(Ints, OS);
47fda6affb95e9f68278cb5cf75dc3fd3406978255Chris Lattner
48f97a00e681c7a526d49759d0d1b9d327cbf6c04aChris Lattner  // Emit the intrinsic verifier.
49f97a00e681c7a526d49759d0d1b9d327cbf6c04aChris Lattner  EmitVerifier(Ints, OS);
506448ee44c6f232f215d5d9f145a0d71a983c4a3fChris Lattner
5195af592a631f403e1458ec1155f89fc31011572cJim Laskey  // Emit the intrinsic declaration generator.
5295af592a631f403e1458ec1155f89fc31011572cJim Laskey  EmitGenerator(Ints, OS);
5395af592a631f403e1458ec1155f89fc31011572cJim Laskey
54a3355ffb3d30d19d226bbb75707991c60f236e37Duncan Sands  // Emit the intrinsic parameter attributes.
55a3355ffb3d30d19d226bbb75707991c60f236e37Duncan Sands  EmitAttributes(Ints, OS);
56022f64fbbc4669623e79b805379266fed519017dChris Lattner
57d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands  // Emit intrinsic alias analysis mod/ref behavior.
58d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands  EmitModRefBehavior(Ints, OS);
59d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands
60022f64fbbc4669623e79b805379266fed519017dChris Lattner  // Emit a list of intrinsics with corresponding GCC builtins.
61022f64fbbc4669623e79b805379266fed519017dChris Lattner  EmitGCCBuiltinList(Ints, OS);
623f8b8913bc9cb232871445eefa8654caf7f9986fChris Lattner
633f8b8913bc9cb232871445eefa8654caf7f9986fChris Lattner  // Emit code to translate GCC builtins into LLVM intrinsics.
643f8b8913bc9cb232871445eefa8654caf7f9986fChris Lattner  EmitIntrinsicToGCCBuiltinMap(Ints, OS);
657d9663c70b3300070298d716dba6e6f6ce2d1e3eDouglas Gregor
667d9663c70b3300070298d716dba6e6f6ce2d1e3eDouglas Gregor  EmitSuffix(OS);
677d9663c70b3300070298d716dba6e6f6ce2d1e3eDouglas Gregor}
687d9663c70b3300070298d716dba6e6f6ce2d1e3eDouglas Gregor
697d9663c70b3300070298d716dba6e6f6ce2d1e3eDouglas Gregorvoid IntrinsicEmitter::EmitPrefix(raw_ostream &OS) {
707d9663c70b3300070298d716dba6e6f6ce2d1e3eDouglas Gregor  OS << "// VisualStudio defines setjmp as _setjmp\n"
717d9663c70b3300070298d716dba6e6f6ce2d1e3eDouglas Gregor        "#if defined(_MSC_VER) && defined(setjmp)\n"
727d9663c70b3300070298d716dba6e6f6ce2d1e3eDouglas Gregor        "#define setjmp_undefined_for_visual_studio\n"
737d9663c70b3300070298d716dba6e6f6ce2d1e3eDouglas Gregor        "#undef setjmp\n"
747d9663c70b3300070298d716dba6e6f6ce2d1e3eDouglas Gregor        "#endif\n\n";
757d9663c70b3300070298d716dba6e6f6ce2d1e3eDouglas Gregor}
767d9663c70b3300070298d716dba6e6f6ce2d1e3eDouglas Gregor
777d9663c70b3300070298d716dba6e6f6ce2d1e3eDouglas Gregorvoid IntrinsicEmitter::EmitSuffix(raw_ostream &OS) {
787d9663c70b3300070298d716dba6e6f6ce2d1e3eDouglas Gregor  OS << "#if defined(_MSC_VER) && defined(setjmp_undefined_for_visual_studio)\n"
797d9663c70b3300070298d716dba6e6f6ce2d1e3eDouglas Gregor        "// let's return it to _setjmp state\n"
807d9663c70b3300070298d716dba6e6f6ce2d1e3eDouglas Gregor        "#define setjmp _setjmp\n"
817d9663c70b3300070298d716dba6e6f6ce2d1e3eDouglas Gregor        "#endif\n\n";
829e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner}
839e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner
849e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattnervoid IntrinsicEmitter::EmitEnumInfo(const std::vector<CodeGenIntrinsic> &Ints,
851a55180238dbcf11113f610aea010447e51f595bDaniel Dunbar                                    raw_ostream &OS) {
869b843b249462980ae4630dc37d1bcccde884a5a7Chris Lattner  OS << "// Enum values for Intrinsics.h\n";
879e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner  OS << "#ifdef GET_INTRINSIC_ENUM_VALUES\n";
889e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner  for (unsigned i = 0, e = Ints.size(); i != e; ++i) {
899e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner    OS << "    " << Ints[i].EnumName;
909e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner    OS << ((i != e-1) ? ", " : "  ");
919e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner    OS << std::string(40-Ints[i].EnumName.size(), ' ')
929e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner      << "// " << Ints[i].Name << "\n";
939e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner  }
949e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner  OS << "#endif\n\n";
959e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner}
969b843b249462980ae4630dc37d1bcccde884a5a7Chris Lattner
979b843b249462980ae4630dc37d1bcccde884a5a7Chris Lattnervoid IntrinsicEmitter::
989b843b249462980ae4630dc37d1bcccde884a5a7Chris LattnerEmitFnNameRecognizer(const std::vector<CodeGenIntrinsic> &Ints,
991a55180238dbcf11113f610aea010447e51f595bDaniel Dunbar                     raw_ostream &OS) {
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) {
1600d52ff1f7b993750a74a5d4432273092de9af069Mon P Wang  OS << "// Intrinsic ID to overload table\n";
1610d52ff1f7b993750a74a5d4432273092de9af069Mon P Wang  OS << "#ifdef GET_INTRINSIC_OVERLOAD_TABLE\n";
1620d52ff1f7b993750a74a5d4432273092de9af069Mon P Wang  OS << "  // Note that entry #0 is the invalid intrinsic!\n";
1630d52ff1f7b993750a74a5d4432273092de9af069Mon P Wang  for (unsigned i = 0, e = Ints.size(); i != e; ++i) {
1640d52ff1f7b993750a74a5d4432273092de9af069Mon P Wang    OS << "  ";
1650d52ff1f7b993750a74a5d4432273092de9af069Mon P Wang    if (Ints[i].isOverloaded)
1660d52ff1f7b993750a74a5d4432273092de9af069Mon P Wang      OS << "true";
1670d52ff1f7b993750a74a5d4432273092de9af069Mon P Wang    else
1680d52ff1f7b993750a74a5d4432273092de9af069Mon P Wang      OS << "false";
1690d52ff1f7b993750a74a5d4432273092de9af069Mon P Wang    OS << ",\n";
1700d52ff1f7b993750a74a5d4432273092de9af069Mon P Wang  }
1710d52ff1f7b993750a74a5d4432273092de9af069Mon P Wang  OS << "#endif\n\n";
1720d52ff1f7b993750a74a5d4432273092de9af069Mon P Wang}
1730d52ff1f7b993750a74a5d4432273092de9af069Mon P Wang
174825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Andersonstatic void EmitTypeForValueType(raw_ostream &OS, MVT::SimpleValueType VT) {
175e50ed30282bb5b4a9ed952580523f2dda16215acOwen Anderson  if (EVT(VT).isInteger()) {
176e50ed30282bb5b4a9ed952580523f2dda16215acOwen Anderson    unsigned BitWidth = EVT(VT).getSizeInBits();
1771d0be15f89cb5056e20e2d24faa8d6afb1573bcaOwen Anderson    OS << "IntegerType::get(Context, " << BitWidth << ")";
178825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson  } else if (VT == MVT::Other) {
179825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson    // MVT::OtherVT is used to mean the empty struct type here.
180d7f2a6cb3fbc012763adb42fd967f6fefbb22a37Owen Anderson    OS << "StructType::get(Context)";
181825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson  } else if (VT == MVT::f32) {
1821d0be15f89cb5056e20e2d24faa8d6afb1573bcaOwen Anderson    OS << "Type::getFloatTy(Context)";
183825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson  } else if (VT == MVT::f64) {
1841d0be15f89cb5056e20e2d24faa8d6afb1573bcaOwen Anderson    OS << "Type::getDoubleTy(Context)";
185825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson  } else if (VT == MVT::f80) {
1861d0be15f89cb5056e20e2d24faa8d6afb1573bcaOwen Anderson    OS << "Type::getX86_FP80Ty(Context)";
187825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson  } else if (VT == MVT::f128) {
1881d0be15f89cb5056e20e2d24faa8d6afb1573bcaOwen Anderson    OS << "Type::getFP128Ty(Context)";
189825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson  } else if (VT == MVT::ppcf128) {
1901d0be15f89cb5056e20e2d24faa8d6afb1573bcaOwen Anderson    OS << "Type::getPPC_FP128Ty(Context)";
191825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson  } else if (VT == MVT::isVoid) {
1921d0be15f89cb5056e20e2d24faa8d6afb1573bcaOwen Anderson    OS << "Type::getVoidTy(Context)";
193825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson  } else if (VT == MVT::Metadata) {
1941d0be15f89cb5056e20e2d24faa8d6afb1573bcaOwen Anderson    OS << "Type::getMetadataTy(Context)";
1956994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth  } else {
1966994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth    assert(false && "Unsupported ValueType!");
19718faf5d9f7f89130b9e3304965b81e1c70ebb75cChris Lattner  }
19818faf5d9f7f89130b9e3304965b81e1c70ebb75cChris Lattner}
19918faf5d9f7f89130b9e3304965b81e1c70ebb75cChris Lattner
2001a55180238dbcf11113f610aea010447e51f595bDaniel Dunbarstatic void EmitTypeGenerate(raw_ostream &OS, const Record *ArgType,
201cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling                             unsigned &ArgNo);
202cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling
2031a55180238dbcf11113f610aea010447e51f595bDaniel Dunbarstatic void EmitTypeGenerate(raw_ostream &OS,
204cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling                             const std::vector<Record*> &ArgTypes,
205cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling                             unsigned &ArgNo) {
20693dc92e412fd06250e46951bffb6040eca9baebdChris Lattner  if (ArgTypes.empty())
20793dc92e412fd06250e46951bffb6040eca9baebdChris Lattner    return EmitTypeForValueType(OS, MVT::isVoid);
20893dc92e412fd06250e46951bffb6040eca9baebdChris Lattner
20993dc92e412fd06250e46951bffb6040eca9baebdChris Lattner  if (ArgTypes.size() == 1)
21093dc92e412fd06250e46951bffb6040eca9baebdChris Lattner    return EmitTypeGenerate(OS, ArgTypes.front(), ArgNo);
211cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling
212d7f2a6cb3fbc012763adb42fd967f6fefbb22a37Owen Anderson  OS << "StructType::get(Context, ";
213cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling
214cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling  for (std::vector<Record*>::const_iterator
21520072af3b0b22d90afbce769409f4ed822520366Bill Wendling         I = ArgTypes.begin(), E = ArgTypes.end(); I != E; ++I) {
216cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling    EmitTypeGenerate(OS, *I, ArgNo);
21720072af3b0b22d90afbce769409f4ed822520366Bill Wendling    OS << ", ";
21820072af3b0b22d90afbce769409f4ed822520366Bill Wendling  }
219cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling
22020072af3b0b22d90afbce769409f4ed822520366Bill Wendling  OS << " NULL)";
221cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling}
222cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling
2231a55180238dbcf11113f610aea010447e51f595bDaniel Dunbarstatic void EmitTypeGenerate(raw_ostream &OS, const Record *ArgType,
22484c614d1ac671b1a5524169f20028f51c30be728Reid Spencer                             unsigned &ArgNo) {
225825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson  MVT::SimpleValueType VT = getValueType(ArgType->getValueAsDef("VT"));
2266994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth
2276994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth  if (ArgType->isSubClassOf("LLVMMatchType")) {
2286994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth    unsigned Number = ArgType->getValueAsInt("Number");
2296994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth    assert(Number < ArgNo && "Invalid matching number!");
230bc03979536a1ecb220f1330719f3e3973a81ab0bBob Wilson    if (ArgType->isSubClassOf("LLVMExtendedElementVectorType"))
231bc03979536a1ecb220f1330719f3e3973a81ab0bBob Wilson      OS << "VectorType::getExtendedElementVectorType"
232bc03979536a1ecb220f1330719f3e3973a81ab0bBob Wilson         << "(dyn_cast<VectorType>(Tys[" << Number << "]))";
233bc03979536a1ecb220f1330719f3e3973a81ab0bBob Wilson    else if (ArgType->isSubClassOf("LLVMTruncatedElementVectorType"))
234bc03979536a1ecb220f1330719f3e3973a81ab0bBob Wilson      OS << "VectorType::getTruncatedElementVectorType"
235bc03979536a1ecb220f1330719f3e3973a81ab0bBob Wilson         << "(dyn_cast<VectorType>(Tys[" << Number << "]))";
236bc03979536a1ecb220f1330719f3e3973a81ab0bBob Wilson    else
237bc03979536a1ecb220f1330719f3e3973a81ab0bBob Wilson      OS << "Tys[" << Number << "]";
238825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson  } else if (VT == MVT::iAny || VT == MVT::fAny || VT == MVT::vAny) {
23984c614d1ac671b1a5524169f20028f51c30be728Reid Spencer    // NOTE: The ArgNo variable here is not the absolute argument number, it is
24084c614d1ac671b1a5524169f20028f51c30be728Reid Spencer    // the index of the "arbitrary" type in the Tys array passed to the
24184c614d1ac671b1a5524169f20028f51c30be728Reid Spencer    // Intrinsic::getDeclaration function. Consequently, we only want to
2426994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth    // increment it when we actually hit an overloaded type. Getting this wrong
2436994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth    // leads to very subtle bugs!
2446994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth    OS << "Tys[" << ArgNo++ << "]";
245e50ed30282bb5b4a9ed952580523f2dda16215acOwen Anderson  } else if (EVT(VT).isVector()) {
246e50ed30282bb5b4a9ed952580523f2dda16215acOwen Anderson    EVT VVT = VT;
2479d6565a5b1fbc4286d6ee638d8f47a3171a9ed7eReid Spencer    OS << "VectorType::get(";
248825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson    EmitTypeForValueType(OS, VVT.getVectorElementType().getSimpleVT().SimpleTy);
24983ec4b6711980242ef3c55a4fa36b2d7a39c1bfbDuncan Sands    OS << ", " << VVT.getVectorNumElements() << ")";
250825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson  } else if (VT == MVT::iPTR) {
25143ad6b3e0d6ada51e9b23aab3e061187f1f5710cChristopher Lamb    OS << "PointerType::getUnqual(";
252c4de3dec62c3f60ae7297f93c19c799c403c2e9fReid Spencer    EmitTypeGenerate(OS, ArgType->getValueAsDef("ElTy"), ArgNo);
25395af592a631f403e1458ec1155f89fc31011572cJim Laskey    OS << ")";
254825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson  } else if (VT == MVT::iPTRAny) {
255e3b3a7241c01f26613694e53b26b01abf764ddfcMon P Wang    // Make sure the user has passed us an argument type to overload. If not,
256e3b3a7241c01f26613694e53b26b01abf764ddfcMon P Wang    // treat it as an ordinary (not overloaded) intrinsic.
257e3b3a7241c01f26613694e53b26b01abf764ddfcMon P Wang    OS << "(" << ArgNo << " < numTys) ? Tys[" << ArgNo
258e3b3a7241c01f26613694e53b26b01abf764ddfcMon P Wang    << "] : PointerType::getUnqual(";
259e3b3a7241c01f26613694e53b26b01abf764ddfcMon P Wang    EmitTypeGenerate(OS, ArgType->getValueAsDef("ElTy"), ArgNo);
260e3b3a7241c01f26613694e53b26b01abf764ddfcMon P Wang    OS << ")";
261e3b3a7241c01f26613694e53b26b01abf764ddfcMon P Wang    ++ArgNo;
262825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson  } else if (VT == MVT::isVoid) {
2636994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth    if (ArgNo == 0)
2641d0be15f89cb5056e20e2d24faa8d6afb1573bcaOwen Anderson      OS << "Type::getVoidTy(Context)";
2656994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth    else
266825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson      // MVT::isVoid is used to mean varargs here.
2676994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth      OS << "...";
26895af592a631f403e1458ec1155f89fc31011572cJim Laskey  } else {
2696994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth    EmitTypeForValueType(OS, VT);
27095af592a631f403e1458ec1155f89fc31011572cJim Laskey  }
27195af592a631f403e1458ec1155f89fc31011572cJim Laskey}
27295af592a631f403e1458ec1155f89fc31011572cJim Laskey
273da4231f134989af7dc6bd3408821ba573def27b2Jim Grosbach/// RecordListComparator - Provide a deterministic comparator for lists of
274c4d9b240b157efa9301d451ac44c12f6b004db8fChris Lattner/// records.
275c4d9b240b157efa9301d451ac44c12f6b004db8fChris Lattnernamespace {
276cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling  typedef std::pair<std::vector<Record*>, std::vector<Record*> > RecPair;
277c4d9b240b157efa9301d451ac44c12f6b004db8fChris Lattner  struct RecordListComparator {
278cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling    bool operator()(const RecPair &LHS,
279cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling                    const RecPair &RHS) const {
280c4d9b240b157efa9301d451ac44c12f6b004db8fChris Lattner      unsigned i = 0;
281cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling      const std::vector<Record*> *LHSVec = &LHS.first;
282cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling      const std::vector<Record*> *RHSVec = &RHS.first;
283cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling      unsigned RHSSize = RHSVec->size();
284cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling      unsigned LHSSize = LHSVec->size();
285cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling
28693dc92e412fd06250e46951bffb6040eca9baebdChris Lattner      for (; i != LHSSize; ++i) {
287cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling        if (i == RHSSize) return false;  // RHS is shorter than LHS.
288cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling        if ((*LHSVec)[i] != (*RHSVec)[i])
289cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling          return (*LHSVec)[i]->getName() < (*RHSVec)[i]->getName();
29093dc92e412fd06250e46951bffb6040eca9baebdChris Lattner      }
291cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling
292023422a6eb9ea692a5a837dc1daf256ac75ac6b0Bill Wendling      if (i != RHSSize) return true;
293cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling
294cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling      i = 0;
295cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling      LHSVec = &LHS.second;
296cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling      RHSVec = &RHS.second;
297cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling      RHSSize = RHSVec->size();
298cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling      LHSSize = LHSVec->size();
299cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling
300cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling      for (i = 0; i != LHSSize; ++i) {
301cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling        if (i == RHSSize) return false;  // RHS is shorter than LHS.
302cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling        if ((*LHSVec)[i] != (*RHSVec)[i])
303cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling          return (*LHSVec)[i]->getName() < (*RHSVec)[i]->getName();
304cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling      }
305cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling
306cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling      return i != RHSSize;
307c4d9b240b157efa9301d451ac44c12f6b004db8fChris Lattner    }
308c4d9b240b157efa9301d451ac44c12f6b004db8fChris Lattner  };
309c4d9b240b157efa9301d451ac44c12f6b004db8fChris Lattner}
310c4d9b240b157efa9301d451ac44c12f6b004db8fChris Lattner
311f97a00e681c7a526d49759d0d1b9d327cbf6c04aChris Lattnervoid IntrinsicEmitter::EmitVerifier(const std::vector<CodeGenIntrinsic> &Ints,
3121a55180238dbcf11113f610aea010447e51f595bDaniel Dunbar                                    raw_ostream &OS) {
313f97a00e681c7a526d49759d0d1b9d327cbf6c04aChris Lattner  OS << "// Verifier::visitIntrinsicFunctionCall code.\n";
314f97a00e681c7a526d49759d0d1b9d327cbf6c04aChris Lattner  OS << "#ifdef GET_INTRINSIC_VERIFIER\n";
315f97a00e681c7a526d49759d0d1b9d327cbf6c04aChris Lattner  OS << "  switch (ID) {\n";
316f97a00e681c7a526d49759d0d1b9d327cbf6c04aChris Lattner  OS << "  default: assert(0 && \"Invalid intrinsic!\");\n";
317c4d9b240b157efa9301d451ac44c12f6b004db8fChris Lattner
318c4d9b240b157efa9301d451ac44c12f6b004db8fChris Lattner  // This checking can emit a lot of very common code.  To reduce the amount of
319c4d9b240b157efa9301d451ac44c12f6b004db8fChris Lattner  // code that we emit, batch up cases that have identical types.  This avoids
320c4d9b240b157efa9301d451ac44c12f6b004db8fChris Lattner  // problems where GCC can run out of memory compiling Verifier.cpp.
321cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling  typedef std::map<RecPair, std::vector<unsigned>, RecordListComparator> MapTy;
322c4d9b240b157efa9301d451ac44c12f6b004db8fChris Lattner  MapTy UniqueArgInfos;
323c4d9b240b157efa9301d451ac44c12f6b004db8fChris Lattner
324c4d9b240b157efa9301d451ac44c12f6b004db8fChris Lattner  // Compute the unique argument type info.
325c4d9b240b157efa9301d451ac44c12f6b004db8fChris Lattner  for (unsigned i = 0, e = Ints.size(); i != e; ++i)
326cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling    UniqueArgInfos[make_pair(Ints[i].IS.RetTypeDefs,
327cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling                             Ints[i].IS.ParamTypeDefs)].push_back(i);
328c4d9b240b157efa9301d451ac44c12f6b004db8fChris Lattner
329c4d9b240b157efa9301d451ac44c12f6b004db8fChris Lattner  // Loop through the array, emitting one comparison for each batch.
330c4d9b240b157efa9301d451ac44c12f6b004db8fChris Lattner  for (MapTy::iterator I = UniqueArgInfos.begin(),
331c4d9b240b157efa9301d451ac44c12f6b004db8fChris Lattner       E = UniqueArgInfos.end(); I != E; ++I) {
332cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling    for (unsigned i = 0, e = I->second.size(); i != e; ++i)
333c4d9b240b157efa9301d451ac44c12f6b004db8fChris Lattner      OS << "  case Intrinsic::" << Ints[I->second[i]].EnumName << ":\t\t// "
334c4d9b240b157efa9301d451ac44c12f6b004db8fChris Lattner         << Ints[I->second[i]].Name << "\n";
335f124b46b4f18b1a8f054a1222324ae15079f6ed8Chris Lattner
336cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling    const RecPair &ArgTypes = I->first;
337cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling    const std::vector<Record*> &RetTys = ArgTypes.first;
338cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling    const std::vector<Record*> &ParamTys = ArgTypes.second;
33909b1366f3f310b5648aa8cd72ed16b9f19b4c68dBob Wilson    std::vector<unsigned> OverloadedTypeIndices;
340cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling
341cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling    OS << "    VerifyIntrinsicPrototype(ID, IF, " << RetTys.size() << ", "
342cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling       << ParamTys.size();
343cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling
344cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling    // Emit return types.
345cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling    for (unsigned j = 0, je = RetTys.size(); j != je; ++j) {
346cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling      Record *ArgType = RetTys[j];
347cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling      OS << ", ";
348cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling
3496994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth      if (ArgType->isSubClassOf("LLVMMatchType")) {
3506994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth        unsigned Number = ArgType->getValueAsInt("Number");
35109b1366f3f310b5648aa8cd72ed16b9f19b4c68dBob Wilson        assert(Number < OverloadedTypeIndices.size() &&
35209b1366f3f310b5648aa8cd72ed16b9f19b4c68dBob Wilson               "Invalid matching number!");
35309b1366f3f310b5648aa8cd72ed16b9f19b4c68dBob Wilson        Number = OverloadedTypeIndices[Number];
354bc03979536a1ecb220f1330719f3e3973a81ab0bBob Wilson        if (ArgType->isSubClassOf("LLVMExtendedElementVectorType"))
355bc03979536a1ecb220f1330719f3e3973a81ab0bBob Wilson          OS << "~(ExtendedElementVectorType | " << Number << ")";
356bc03979536a1ecb220f1330719f3e3973a81ab0bBob Wilson        else if (ArgType->isSubClassOf("LLVMTruncatedElementVectorType"))
357bc03979536a1ecb220f1330719f3e3973a81ab0bBob Wilson          OS << "~(TruncatedElementVectorType | " << Number << ")";
358bc03979536a1ecb220f1330719f3e3973a81ab0bBob Wilson        else
359bc03979536a1ecb220f1330719f3e3973a81ab0bBob Wilson          OS << "~" << Number;
3606994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth      } else {
361825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson        MVT::SimpleValueType VT = getValueType(ArgType->getValueAsDef("VT"));
3626994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth        OS << getEnumName(VT);
363cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling
36461fc4cf7aa0b87ceab62082cee8ef5ce3f574ffcBob Wilson        if (EVT(VT).isOverloaded())
36509b1366f3f310b5648aa8cd72ed16b9f19b4c68dBob Wilson          OverloadedTypeIndices.push_back(j);
36609b1366f3f310b5648aa8cd72ed16b9f19b4c68dBob Wilson
367825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson        if (VT == MVT::isVoid && j != 0 && j != je - 1)
368cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling          throw "Var arg type not last argument";
369cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling      }
370cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling    }
371cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling
372cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling    // Emit the parameter types.
373cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling    for (unsigned j = 0, je = ParamTys.size(); j != je; ++j) {
374cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling      Record *ArgType = ParamTys[j];
375cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling      OS << ", ";
376cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling
377cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling      if (ArgType->isSubClassOf("LLVMMatchType")) {
378cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling        unsigned Number = ArgType->getValueAsInt("Number");
37909b1366f3f310b5648aa8cd72ed16b9f19b4c68dBob Wilson        assert(Number < OverloadedTypeIndices.size() &&
38009b1366f3f310b5648aa8cd72ed16b9f19b4c68dBob Wilson               "Invalid matching number!");
38109b1366f3f310b5648aa8cd72ed16b9f19b4c68dBob Wilson        Number = OverloadedTypeIndices[Number];
382bc03979536a1ecb220f1330719f3e3973a81ab0bBob Wilson        if (ArgType->isSubClassOf("LLVMExtendedElementVectorType"))
383bc03979536a1ecb220f1330719f3e3973a81ab0bBob Wilson          OS << "~(ExtendedElementVectorType | " << Number << ")";
384bc03979536a1ecb220f1330719f3e3973a81ab0bBob Wilson        else if (ArgType->isSubClassOf("LLVMTruncatedElementVectorType"))
385bc03979536a1ecb220f1330719f3e3973a81ab0bBob Wilson          OS << "~(TruncatedElementVectorType | " << Number << ")";
386bc03979536a1ecb220f1330719f3e3973a81ab0bBob Wilson        else
387bc03979536a1ecb220f1330719f3e3973a81ab0bBob Wilson          OS << "~" << Number;
388cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling      } else {
389825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson        MVT::SimpleValueType VT = getValueType(ArgType->getValueAsDef("VT"));
390cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling        OS << getEnumName(VT);
391cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling
39261fc4cf7aa0b87ceab62082cee8ef5ce3f574ffcBob Wilson        if (EVT(VT).isOverloaded())
39309b1366f3f310b5648aa8cd72ed16b9f19b4c68dBob Wilson          OverloadedTypeIndices.push_back(j + RetTys.size());
39409b1366f3f310b5648aa8cd72ed16b9f19b4c68dBob Wilson
395825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson        if (VT == MVT::isVoid && j != 0 && j != je - 1)
39695d97b90e8427255c8298f5d3a1ab605af62aab4Jim Laskey          throw "Var arg type not last argument";
39795d97b90e8427255c8298f5d3a1ab605af62aab4Jim Laskey      }
39895d97b90e8427255c8298f5d3a1ab605af62aab4Jim Laskey    }
39995d97b90e8427255c8298f5d3a1ab605af62aab4Jim Laskey
4006994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth    OS << ");\n";
401f97a00e681c7a526d49759d0d1b9d327cbf6c04aChris Lattner    OS << "    break;\n";
402f97a00e681c7a526d49759d0d1b9d327cbf6c04aChris Lattner  }
403f97a00e681c7a526d49759d0d1b9d327cbf6c04aChris Lattner  OS << "  }\n";
404f97a00e681c7a526d49759d0d1b9d327cbf6c04aChris Lattner  OS << "#endif\n\n";
4059b843b249462980ae4630dc37d1bcccde884a5a7Chris Lattner}
4069b843b249462980ae4630dc37d1bcccde884a5a7Chris Lattner
40795af592a631f403e1458ec1155f89fc31011572cJim Laskeyvoid IntrinsicEmitter::EmitGenerator(const std::vector<CodeGenIntrinsic> &Ints,
4081a55180238dbcf11113f610aea010447e51f595bDaniel Dunbar                                     raw_ostream &OS) {
40995af592a631f403e1458ec1155f89fc31011572cJim Laskey  OS << "// Code for generating Intrinsic function declarations.\n";
41095af592a631f403e1458ec1155f89fc31011572cJim Laskey  OS << "#ifdef GET_INTRINSIC_GENERATOR\n";
41195af592a631f403e1458ec1155f89fc31011572cJim Laskey  OS << "  switch (id) {\n";
41295af592a631f403e1458ec1155f89fc31011572cJim Laskey  OS << "  default: assert(0 && \"Invalid intrinsic!\");\n";
41395af592a631f403e1458ec1155f89fc31011572cJim Laskey
41495af592a631f403e1458ec1155f89fc31011572cJim Laskey  // Similar to GET_INTRINSIC_VERIFIER, batch up cases that have identical
41595af592a631f403e1458ec1155f89fc31011572cJim Laskey  // types.
416cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling  typedef std::map<RecPair, std::vector<unsigned>, RecordListComparator> MapTy;
41795af592a631f403e1458ec1155f89fc31011572cJim Laskey  MapTy UniqueArgInfos;
41895af592a631f403e1458ec1155f89fc31011572cJim Laskey
41995af592a631f403e1458ec1155f89fc31011572cJim Laskey  // Compute the unique argument type info.
42095af592a631f403e1458ec1155f89fc31011572cJim Laskey  for (unsigned i = 0, e = Ints.size(); i != e; ++i)
421cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling    UniqueArgInfos[make_pair(Ints[i].IS.RetTypeDefs,
422cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling                             Ints[i].IS.ParamTypeDefs)].push_back(i);
42395af592a631f403e1458ec1155f89fc31011572cJim Laskey
42495af592a631f403e1458ec1155f89fc31011572cJim Laskey  // Loop through the array, emitting one generator for each batch.
42549de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen  std::string IntrinsicStr = TargetPrefix + "Intrinsic::";
42649de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen
42795af592a631f403e1458ec1155f89fc31011572cJim Laskey  for (MapTy::iterator I = UniqueArgInfos.begin(),
42895af592a631f403e1458ec1155f89fc31011572cJim Laskey       E = UniqueArgInfos.end(); I != E; ++I) {
429cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling    for (unsigned i = 0, e = I->second.size(); i != e; ++i)
43049de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen      OS << "  case " << IntrinsicStr << Ints[I->second[i]].EnumName
43149de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen         << ":\t\t// " << Ints[I->second[i]].Name << "\n";
43295af592a631f403e1458ec1155f89fc31011572cJim Laskey
433cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling    const RecPair &ArgTypes = I->first;
434cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling    const std::vector<Record*> &RetTys = ArgTypes.first;
435cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling    const std::vector<Record*> &ParamTys = ArgTypes.second;
436cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling
437cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling    unsigned N = ParamTys.size();
43895af592a631f403e1458ec1155f89fc31011572cJim Laskey
4396994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth    if (N > 1 &&
440825b72b0571821bf2d378749f69d6c4cfb52d2f9Owen Anderson        getValueType(ParamTys[N - 1]->getValueAsDef("VT")) == MVT::isVoid) {
44195af592a631f403e1458ec1155f89fc31011572cJim Laskey      OS << "    IsVarArg = true;\n";
44295af592a631f403e1458ec1155f89fc31011572cJim Laskey      --N;
44395af592a631f403e1458ec1155f89fc31011572cJim Laskey    }
444cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling
44584c614d1ac671b1a5524169f20028f51c30be728Reid Spencer    unsigned ArgNo = 0;
44695af592a631f403e1458ec1155f89fc31011572cJim Laskey    OS << "    ResultTy = ";
447cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling    EmitTypeGenerate(OS, RetTys, ArgNo);
44895af592a631f403e1458ec1155f89fc31011572cJim Laskey    OS << ";\n";
44995af592a631f403e1458ec1155f89fc31011572cJim Laskey
450cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling    for (unsigned j = 0; j != N; ++j) {
45195af592a631f403e1458ec1155f89fc31011572cJim Laskey      OS << "    ArgTys.push_back(";
452cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling      EmitTypeGenerate(OS, ParamTys[j], ArgNo);
45395af592a631f403e1458ec1155f89fc31011572cJim Laskey      OS << ");\n";
45495af592a631f403e1458ec1155f89fc31011572cJim Laskey    }
455cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling
45695af592a631f403e1458ec1155f89fc31011572cJim Laskey    OS << "    break;\n";
45795af592a631f403e1458ec1155f89fc31011572cJim Laskey  }
458cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling
45995af592a631f403e1458ec1155f89fc31011572cJim Laskey  OS << "  }\n";
46095af592a631f403e1458ec1155f89fc31011572cJim Laskey  OS << "#endif\n\n";
46195af592a631f403e1458ec1155f89fc31011572cJim Laskey}
46295af592a631f403e1458ec1155f89fc31011572cJim Laskey
463048ffb239c282277959463c61200b86e2380cb84Chris Lattner/// EmitAttributes - This emits the Intrinsic::getAttributes method.
4644e5f35973c1bc56cce14d44c6f8f4ad1e9f1a438Chris Lattnervoid IntrinsicEmitter::
4651a55180238dbcf11113f610aea010447e51f595bDaniel DunbarEmitAttributes(const std::vector<CodeGenIntrinsic> &Ints, raw_ostream &OS) {
466a3355ffb3d30d19d226bbb75707991c60f236e37Duncan Sands  OS << "// Add parameter attributes that are not common to all intrinsics.\n";
467a3355ffb3d30d19d226bbb75707991c60f236e37Duncan Sands  OS << "#ifdef GET_INTRINSIC_ATTRIBUTES\n";
46849de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen  if (TargetOnly)
46949de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen    OS << "static AttrListPtr getAttributes(" << TargetPrefix
47049de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen       << "Intrinsic::ID id) {";
47149de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen  else
47249de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen    OS << "AttrListPtr Intrinsic::getAttributes(ID id) {";
473048ffb239c282277959463c61200b86e2380cb84Chris Lattner  OS << "  // No intrinsic can throw exceptions.\n";
474048ffb239c282277959463c61200b86e2380cb84Chris Lattner  OS << "  Attributes Attr = Attribute::NoUnwind;\n";
475a3355ffb3d30d19d226bbb75707991c60f236e37Duncan Sands  OS << "  switch (id) {\n";
4767056de375d898d9d9ecc17e170632d91d18be4a8Chris Lattner  OS << "  default: break;\n";
47710dae94be2ccb187bd4e3da53771be54057acd6cChris Lattner  unsigned MaxArgAttrs = 0;
4787056de375d898d9d9ecc17e170632d91d18be4a8Chris Lattner  for (unsigned i = 0, e = Ints.size(); i != e; ++i) {
47910dae94be2ccb187bd4e3da53771be54057acd6cChris Lattner    MaxArgAttrs =
48010dae94be2ccb187bd4e3da53771be54057acd6cChris Lattner      std::max(MaxArgAttrs, unsigned(Ints[i].ArgumentAttributes.size()));
4817056de375d898d9d9ecc17e170632d91d18be4a8Chris Lattner    switch (Ints[i].ModRef) {
4827056de375d898d9d9ecc17e170632d91d18be4a8Chris Lattner    default: break;
4837056de375d898d9d9ecc17e170632d91d18be4a8Chris Lattner    case CodeGenIntrinsic::NoMem:
48449de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen      OS << "  case " << TargetPrefix << "Intrinsic::" << Ints[i].EnumName
48549de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen         << ":\n";
4867056de375d898d9d9ecc17e170632d91d18be4a8Chris Lattner      break;
4877056de375d898d9d9ecc17e170632d91d18be4a8Chris Lattner    }
4887056de375d898d9d9ecc17e170632d91d18be4a8Chris Lattner  }
4890598866c052147c31b808391f58434ce3dbfb838Devang Patel  OS << "    Attr |= Attribute::ReadNone; // These do not access memory.\n";
490a3355ffb3d30d19d226bbb75707991c60f236e37Duncan Sands  OS << "    break;\n";
4914e5f35973c1bc56cce14d44c6f8f4ad1e9f1a438Chris Lattner  for (unsigned i = 0, e = Ints.size(); i != e; ++i) {
4924e5f35973c1bc56cce14d44c6f8f4ad1e9f1a438Chris Lattner    switch (Ints[i].ModRef) {
493022f64fbbc4669623e79b805379266fed519017dChris Lattner    default: break;
494022f64fbbc4669623e79b805379266fed519017dChris Lattner    case CodeGenIntrinsic::ReadArgMem:
495022f64fbbc4669623e79b805379266fed519017dChris Lattner    case CodeGenIntrinsic::ReadMem:
49649de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen      OS << "  case " << TargetPrefix << "Intrinsic::" << Ints[i].EnumName
49749de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen         << ":\n";
498022f64fbbc4669623e79b805379266fed519017dChris Lattner      break;
4994e5f35973c1bc56cce14d44c6f8f4ad1e9f1a438Chris Lattner    }
5004e5f35973c1bc56cce14d44c6f8f4ad1e9f1a438Chris Lattner  }
5010598866c052147c31b808391f58434ce3dbfb838Devang Patel  OS << "    Attr |= Attribute::ReadOnly; // These do not write memory.\n";
502a3355ffb3d30d19d226bbb75707991c60f236e37Duncan Sands  OS << "    break;\n";
5034e5f35973c1bc56cce14d44c6f8f4ad1e9f1a438Chris Lattner  OS << "  }\n";
50410dae94be2ccb187bd4e3da53771be54057acd6cChris Lattner  OS << "  AttributeWithIndex AWI[" << MaxArgAttrs+1 << "];\n";
505d4a2700fdc5bc8ac50084fcb39155e01e86168d5Chris Lattner  OS << "  unsigned NumAttrs = 0;\n";
50610dae94be2ccb187bd4e3da53771be54057acd6cChris Lattner  OS << "  switch (id) {\n";
50710dae94be2ccb187bd4e3da53771be54057acd6cChris Lattner  OS << "  default: break;\n";
50810dae94be2ccb187bd4e3da53771be54057acd6cChris Lattner
50910dae94be2ccb187bd4e3da53771be54057acd6cChris Lattner  // Add argument attributes for any intrinsics that have them.
51010dae94be2ccb187bd4e3da53771be54057acd6cChris Lattner  for (unsigned i = 0, e = Ints.size(); i != e; ++i) {
51110dae94be2ccb187bd4e3da53771be54057acd6cChris Lattner    if (Ints[i].ArgumentAttributes.empty()) continue;
51210dae94be2ccb187bd4e3da53771be54057acd6cChris Lattner
51349de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen    OS << "  case " << TargetPrefix << "Intrinsic::" << Ints[i].EnumName
51449de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen       << ":\n";
51510dae94be2ccb187bd4e3da53771be54057acd6cChris Lattner
51610dae94be2ccb187bd4e3da53771be54057acd6cChris Lattner    std::vector<std::pair<unsigned, CodeGenIntrinsic::ArgAttribute> > ArgAttrs =
51710dae94be2ccb187bd4e3da53771be54057acd6cChris Lattner      Ints[i].ArgumentAttributes;
51810dae94be2ccb187bd4e3da53771be54057acd6cChris Lattner    // Sort by argument index.
51910dae94be2ccb187bd4e3da53771be54057acd6cChris Lattner    std::sort(ArgAttrs.begin(), ArgAttrs.end());
52010dae94be2ccb187bd4e3da53771be54057acd6cChris Lattner
52110dae94be2ccb187bd4e3da53771be54057acd6cChris Lattner    unsigned NumArgsWithAttrs = 0;
52210dae94be2ccb187bd4e3da53771be54057acd6cChris Lattner
523d4a2700fdc5bc8ac50084fcb39155e01e86168d5Chris Lattner    while (!ArgAttrs.empty()) {
524d4a2700fdc5bc8ac50084fcb39155e01e86168d5Chris Lattner      unsigned ArgNo = ArgAttrs[0].first;
525d4a2700fdc5bc8ac50084fcb39155e01e86168d5Chris Lattner
526d4a2700fdc5bc8ac50084fcb39155e01e86168d5Chris Lattner      OS << "    AWI[" << NumArgsWithAttrs++ << "] = AttributeWithIndex::get("
527d4a2700fdc5bc8ac50084fcb39155e01e86168d5Chris Lattner         << ArgNo+1 << ", 0";
528d4a2700fdc5bc8ac50084fcb39155e01e86168d5Chris Lattner
529d4a2700fdc5bc8ac50084fcb39155e01e86168d5Chris Lattner      while (!ArgAttrs.empty() && ArgAttrs[0].first == ArgNo) {
530d4a2700fdc5bc8ac50084fcb39155e01e86168d5Chris Lattner        switch (ArgAttrs[0].second) {
531d4a2700fdc5bc8ac50084fcb39155e01e86168d5Chris Lattner        default: assert(0 && "Unknown arg attribute");
532d4a2700fdc5bc8ac50084fcb39155e01e86168d5Chris Lattner        case CodeGenIntrinsic::NoCapture:
533d4a2700fdc5bc8ac50084fcb39155e01e86168d5Chris Lattner          OS << "|Attribute::NoCapture";
534d4a2700fdc5bc8ac50084fcb39155e01e86168d5Chris Lattner          break;
535d4a2700fdc5bc8ac50084fcb39155e01e86168d5Chris Lattner        }
536d4a2700fdc5bc8ac50084fcb39155e01e86168d5Chris Lattner        ArgAttrs.erase(ArgAttrs.begin());
537d4a2700fdc5bc8ac50084fcb39155e01e86168d5Chris Lattner      }
538d4a2700fdc5bc8ac50084fcb39155e01e86168d5Chris Lattner      OS << ");\n";
539d4a2700fdc5bc8ac50084fcb39155e01e86168d5Chris Lattner    }
54010dae94be2ccb187bd4e3da53771be54057acd6cChris Lattner
541d4a2700fdc5bc8ac50084fcb39155e01e86168d5Chris Lattner    OS << "    NumAttrs = " << NumArgsWithAttrs << ";\n";
54210dae94be2ccb187bd4e3da53771be54057acd6cChris Lattner    OS << "    break;\n";
54310dae94be2ccb187bd4e3da53771be54057acd6cChris Lattner  }
54410dae94be2ccb187bd4e3da53771be54057acd6cChris Lattner
54510dae94be2ccb187bd4e3da53771be54057acd6cChris Lattner  OS << "  }\n";
546d4a2700fdc5bc8ac50084fcb39155e01e86168d5Chris Lattner  OS << "  AWI[NumAttrs] = AttributeWithIndex::get(~0, Attr);\n";
547d4a2700fdc5bc8ac50084fcb39155e01e86168d5Chris Lattner  OS << "  return AttrListPtr::get(AWI, NumAttrs+1);\n";
548048ffb239c282277959463c61200b86e2380cb84Chris Lattner  OS << "}\n";
549d4a2700fdc5bc8ac50084fcb39155e01e86168d5Chris Lattner  OS << "#endif // GET_INTRINSIC_ATTRIBUTES\n\n";
5504e5f35973c1bc56cce14d44c6f8f4ad1e9f1a438Chris Lattner}
551022f64fbbc4669623e79b805379266fed519017dChris Lattner
552d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands/// EmitModRefBehavior - Determine intrinsic alias analysis mod/ref behavior.
553d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sandsvoid IntrinsicEmitter::
5541a55180238dbcf11113f610aea010447e51f595bDaniel DunbarEmitModRefBehavior(const std::vector<CodeGenIntrinsic> &Ints, raw_ostream &OS){
555d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands  OS << "// Determine intrinsic alias analysis mod/ref behavior.\n";
556d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands  OS << "#ifdef GET_INTRINSIC_MODREF_BEHAVIOR\n";
5577c422ac216fe39fc9c402a704cf296cca9dc5b22Duncan Sands  OS << "switch (iid) {\n";
558d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands  OS << "default:\n    return UnknownModRefBehavior;\n";
559d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands  for (unsigned i = 0, e = Ints.size(); i != e; ++i) {
5607365c091f92db5e68c98d7faedc6c34e1bbbc898Dan Gohman    if (Ints[i].ModRef == CodeGenIntrinsic::ReadWriteMem)
561d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands      continue;
562d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands    OS << "case " << TargetPrefix << "Intrinsic::" << Ints[i].EnumName
563d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands      << ":\n";
564d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands    switch (Ints[i].ModRef) {
565d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands    default:
566d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands      assert(false && "Unknown Mod/Ref type!");
567d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands    case CodeGenIntrinsic::NoMem:
568d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands      OS << "  return DoesNotAccessMemory;\n";
569d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands      break;
570d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands    case CodeGenIntrinsic::ReadArgMem:
571d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands    case CodeGenIntrinsic::ReadMem:
572d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands      OS << "  return OnlyReadsMemory;\n";
573d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands      break;
5747365c091f92db5e68c98d7faedc6c34e1bbbc898Dan Gohman    case CodeGenIntrinsic::ReadWriteArgMem:
575d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands      OS << "  return AccessesArguments;\n";
576d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands      break;
577d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands    }
578d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands  }
579d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands  OS << "}\n";
580d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands  OS << "#endif // GET_INTRINSIC_MODREF_BEHAVIOR\n\n";
581d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands}
582d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands
583022f64fbbc4669623e79b805379266fed519017dChris Lattnervoid IntrinsicEmitter::
5841a55180238dbcf11113f610aea010447e51f595bDaniel DunbarEmitGCCBuiltinList(const std::vector<CodeGenIntrinsic> &Ints, raw_ostream &OS){
585022f64fbbc4669623e79b805379266fed519017dChris Lattner  OS << "// Get the GCC builtin that corresponds to an LLVM intrinsic.\n";
586022f64fbbc4669623e79b805379266fed519017dChris Lattner  OS << "#ifdef GET_GCC_BUILTIN_NAME\n";
587022f64fbbc4669623e79b805379266fed519017dChris Lattner  OS << "  switch (F->getIntrinsicID()) {\n";
588022f64fbbc4669623e79b805379266fed519017dChris Lattner  OS << "  default: BuiltinName = \"\"; break;\n";
589022f64fbbc4669623e79b805379266fed519017dChris Lattner  for (unsigned i = 0, e = Ints.size(); i != e; ++i) {
590022f64fbbc4669623e79b805379266fed519017dChris Lattner    if (!Ints[i].GCCBuiltinName.empty()) {
591022f64fbbc4669623e79b805379266fed519017dChris Lattner      OS << "  case Intrinsic::" << Ints[i].EnumName << ": BuiltinName = \""
592022f64fbbc4669623e79b805379266fed519017dChris Lattner         << Ints[i].GCCBuiltinName << "\"; break;\n";
593022f64fbbc4669623e79b805379266fed519017dChris Lattner    }
594022f64fbbc4669623e79b805379266fed519017dChris Lattner  }
595022f64fbbc4669623e79b805379266fed519017dChris Lattner  OS << "  }\n";
596022f64fbbc4669623e79b805379266fed519017dChris Lattner  OS << "#endif\n\n";
597767a25b8788b5e313c99c16b4d359478432901f5Reid Spencer}
5983f8b8913bc9cb232871445eefa8654caf7f9986fChris Lattner
599331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner/// EmitTargetBuiltins - All of the builtins in the specified map are for the
600331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner/// same target, and we already checked it.
601331bf92fb51f058672144681b3d0e67d30f5699fChris Lattnerstatic void EmitTargetBuiltins(const std::map<std::string, std::string> &BIM,
60249de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen                               const std::string &TargetPrefix,
6031a55180238dbcf11113f610aea010447e51f595bDaniel Dunbar                               raw_ostream &OS) {
604331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner
605298b176559d5c76d7d9f7fdd06429a75892de043Chris Lattner  std::vector<StringMatcher::StringPair> Results;
606331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner
607298b176559d5c76d7d9f7fdd06429a75892de043Chris Lattner  for (std::map<std::string, std::string>::const_iterator I = BIM.begin(),
608298b176559d5c76d7d9f7fdd06429a75892de043Chris Lattner       E = BIM.end(); I != E; ++I) {
609298b176559d5c76d7d9f7fdd06429a75892de043Chris Lattner    std::string ResultCode =
610298b176559d5c76d7d9f7fdd06429a75892de043Chris Lattner    "return " + TargetPrefix + "Intrinsic::" + I->second + ";";
611298b176559d5c76d7d9f7fdd06429a75892de043Chris Lattner    Results.push_back(StringMatcher::StringPair(I->first, ResultCode));
612331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner  }
613298b176559d5c76d7d9f7fdd06429a75892de043Chris Lattner
614298b176559d5c76d7d9f7fdd06429a75892de043Chris Lattner  StringMatcher("BuiltinName", Results, OS).Emit();
615331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner}
616331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner
617331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner
6183f8b8913bc9cb232871445eefa8654caf7f9986fChris Lattnervoid IntrinsicEmitter::
6193f8b8913bc9cb232871445eefa8654caf7f9986fChris LattnerEmitIntrinsicToGCCBuiltinMap(const std::vector<CodeGenIntrinsic> &Ints,
6201a55180238dbcf11113f610aea010447e51f595bDaniel Dunbar                             raw_ostream &OS) {
621fa0fba1c546091c485e5513eadeef181dda370abChris Lattner  typedef std::map<std::string, std::map<std::string, std::string> > BIMTy;
6223f8b8913bc9cb232871445eefa8654caf7f9986fChris Lattner  BIMTy BuiltinMap;
6233f8b8913bc9cb232871445eefa8654caf7f9986fChris Lattner  for (unsigned i = 0, e = Ints.size(); i != e; ++i) {
6243f8b8913bc9cb232871445eefa8654caf7f9986fChris Lattner    if (!Ints[i].GCCBuiltinName.empty()) {
625fa0fba1c546091c485e5513eadeef181dda370abChris Lattner      // Get the map for this target prefix.
626fa0fba1c546091c485e5513eadeef181dda370abChris Lattner      std::map<std::string, std::string> &BIM =BuiltinMap[Ints[i].TargetPrefix];
627fa0fba1c546091c485e5513eadeef181dda370abChris Lattner
628fa0fba1c546091c485e5513eadeef181dda370abChris Lattner      if (!BIM.insert(std::make_pair(Ints[i].GCCBuiltinName,
629fa0fba1c546091c485e5513eadeef181dda370abChris Lattner                                     Ints[i].EnumName)).second)
6303f8b8913bc9cb232871445eefa8654caf7f9986fChris Lattner        throw "Intrinsic '" + Ints[i].TheDef->getName() +
6313f8b8913bc9cb232871445eefa8654caf7f9986fChris Lattner              "': duplicate GCC builtin name!";
6323f8b8913bc9cb232871445eefa8654caf7f9986fChris Lattner    }
6333f8b8913bc9cb232871445eefa8654caf7f9986fChris Lattner  }
6343f8b8913bc9cb232871445eefa8654caf7f9986fChris Lattner
6353f8b8913bc9cb232871445eefa8654caf7f9986fChris Lattner  OS << "// Get the LLVM intrinsic that corresponds to a GCC builtin.\n";
6363f8b8913bc9cb232871445eefa8654caf7f9986fChris Lattner  OS << "// This is used by the C front-end.  The GCC builtin name is passed\n";
6373f8b8913bc9cb232871445eefa8654caf7f9986fChris Lattner  OS << "// in as BuiltinName, and a target prefix (e.g. 'ppc') is passed\n";
6383f8b8913bc9cb232871445eefa8654caf7f9986fChris Lattner  OS << "// in as TargetPrefix.  The result is assigned to 'IntrinsicID'.\n";
6393f8b8913bc9cb232871445eefa8654caf7f9986fChris Lattner  OS << "#ifdef GET_LLVM_INTRINSIC_FOR_GCC_BUILTIN\n";
64049de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen
64149de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen  if (TargetOnly) {
64249de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen    OS << "static " << TargetPrefix << "Intrinsic::ID "
64349de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen       << "getIntrinsicForGCCBuiltin(const char "
644298b176559d5c76d7d9f7fdd06429a75892de043Chris Lattner       << "*TargetPrefixStr, const char *BuiltinNameStr) {\n";
64549de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen  } else {
64649de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen    OS << "Intrinsic::ID Intrinsic::getIntrinsicForGCCBuiltin(const char "
647298b176559d5c76d7d9f7fdd06429a75892de043Chris Lattner       << "*TargetPrefixStr, const char *BuiltinNameStr) {\n";
64849de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen  }
64949de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen
650298b176559d5c76d7d9f7fdd06429a75892de043Chris Lattner  OS << "  StringRef BuiltinName(BuiltinNameStr);\n";
651298b176559d5c76d7d9f7fdd06429a75892de043Chris Lattner  OS << "  StringRef TargetPrefix(TargetPrefixStr);\n\n";
652331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner
6533f8b8913bc9cb232871445eefa8654caf7f9986fChris Lattner  // Note: this could emit significantly better code if we cared.
6543f8b8913bc9cb232871445eefa8654caf7f9986fChris Lattner  for (BIMTy::iterator I = BuiltinMap.begin(), E = BuiltinMap.end();I != E;++I){
655fa0fba1c546091c485e5513eadeef181dda370abChris Lattner    OS << "  ";
656fa0fba1c546091c485e5513eadeef181dda370abChris Lattner    if (!I->first.empty())
657298b176559d5c76d7d9f7fdd06429a75892de043Chris Lattner      OS << "if (TargetPrefix == \"" << I->first << "\") ";
658fa0fba1c546091c485e5513eadeef181dda370abChris Lattner    else
659fa0fba1c546091c485e5513eadeef181dda370abChris Lattner      OS << "/* Target Independent Builtins */ ";
660fa0fba1c546091c485e5513eadeef181dda370abChris Lattner    OS << "{\n";
661fa0fba1c546091c485e5513eadeef181dda370abChris Lattner
662fa0fba1c546091c485e5513eadeef181dda370abChris Lattner    // Emit the comparisons for this target prefix.
66349de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen    EmitTargetBuiltins(I->second, TargetPrefix, OS);
664fa0fba1c546091c485e5513eadeef181dda370abChris Lattner    OS << "  }\n";
6653f8b8913bc9cb232871445eefa8654caf7f9986fChris Lattner  }
666298b176559d5c76d7d9f7fdd06429a75892de043Chris Lattner  OS << "  return ";
667298b176559d5c76d7d9f7fdd06429a75892de043Chris Lattner  if (!TargetPrefix.empty())
668298b176559d5c76d7d9f7fdd06429a75892de043Chris Lattner    OS << "(" << TargetPrefix << "Intrinsic::ID)";
669298b176559d5c76d7d9f7fdd06429a75892de043Chris Lattner  OS << "Intrinsic::not_intrinsic;\n";
67049de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen  OS << "}\n";
6713f8b8913bc9cb232871445eefa8654caf7f9986fChris Lattner  OS << "#endif\n\n";
6723f8b8913bc9cb232871445eefa8654caf7f9986fChris Lattner}
673