IntrinsicEmitter.cpp revision da4231f134989af7dc6bd3408821ba573def27b2
19e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner//===- IntrinsicEmitter.cpp - Generate intrinsic information --------------===//
29e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner//
39e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner//                     The LLVM Compiler Infrastructure
49e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner//
53060910e290949a9ac5eda8726d030790c4d60ffChris Lattner// This file is distributed under the University of Illinois Open Source
63060910e290949a9ac5eda8726d030790c4d60ffChris Lattner// License. See LICENSE.TXT for details.
79e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner//
89e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner//===----------------------------------------------------------------------===//
99e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner//
109e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner// This tablegen backend emits information about intrinsic functions.
119e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner//
129e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner//===----------------------------------------------------------------------===//
139e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner
146994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth#include "CodeGenTarget.h"
159e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner#include "IntrinsicEmitter.h"
169e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner#include "Record.h"
1718faf5d9f7f89130b9e3304965b81e1c70ebb75cChris Lattner#include "llvm/ADT/StringExtras.h"
1871c3bc3d966bd874f760abf055c559673f925029Jeff Cohen#include <algorithm>
199e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattnerusing namespace llvm;
209e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner
219e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner//===----------------------------------------------------------------------===//
229e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner// IntrinsicEmitter Implementation
239e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner//===----------------------------------------------------------------------===//
249e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner
259e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattnervoid IntrinsicEmitter::run(std::ostream &OS) {
269e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner  EmitSourceFileHeader("Intrinsic Function Source Fragment", OS);
279e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner
2849de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen  std::vector<CodeGenIntrinsic> Ints = LoadIntrinsics(Records, TargetOnly);
2949de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen
3049de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen  if (TargetOnly && !Ints.empty())
3149de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen    TargetPrefix = Ints[0].TargetPrefix;
329e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner
339e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner  // Emit the enum information.
349e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner  EmitEnumInfo(Ints, OS);
35fda6affb95e9f68278cb5cf75dc3fd3406978255Chris Lattner
36fda6affb95e9f68278cb5cf75dc3fd3406978255Chris Lattner  // Emit the intrinsic ID -> name table.
37fda6affb95e9f68278cb5cf75dc3fd3406978255Chris Lattner  EmitIntrinsicToNameTable(Ints, OS);
380d52ff1f7b993750a74a5d4432273092de9af069Mon P Wang
390d52ff1f7b993750a74a5d4432273092de9af069Mon P Wang  // Emit the intrinsic ID -> overload table.
400d52ff1f7b993750a74a5d4432273092de9af069Mon P Wang  EmitIntrinsicToOverloadTable(Ints, OS);
410d52ff1f7b993750a74a5d4432273092de9af069Mon P Wang
429b843b249462980ae4630dc37d1bcccde884a5a7Chris Lattner  // Emit the function name recognizer.
439b843b249462980ae4630dc37d1bcccde884a5a7Chris Lattner  EmitFnNameRecognizer(Ints, OS);
44fda6affb95e9f68278cb5cf75dc3fd3406978255Chris Lattner
45f97a00e681c7a526d49759d0d1b9d327cbf6c04aChris Lattner  // Emit the intrinsic verifier.
46f97a00e681c7a526d49759d0d1b9d327cbf6c04aChris Lattner  EmitVerifier(Ints, OS);
476448ee44c6f232f215d5d9f145a0d71a983c4a3fChris Lattner
4895af592a631f403e1458ec1155f89fc31011572cJim Laskey  // Emit the intrinsic declaration generator.
4995af592a631f403e1458ec1155f89fc31011572cJim Laskey  EmitGenerator(Ints, OS);
5095af592a631f403e1458ec1155f89fc31011572cJim Laskey
51a3355ffb3d30d19d226bbb75707991c60f236e37Duncan Sands  // Emit the intrinsic parameter attributes.
52a3355ffb3d30d19d226bbb75707991c60f236e37Duncan Sands  EmitAttributes(Ints, OS);
53022f64fbbc4669623e79b805379266fed519017dChris Lattner
54d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands  // Emit intrinsic alias analysis mod/ref behavior.
55d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands  EmitModRefBehavior(Ints, OS);
56d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands
57022f64fbbc4669623e79b805379266fed519017dChris Lattner  // Emit a list of intrinsics with corresponding GCC builtins.
58022f64fbbc4669623e79b805379266fed519017dChris Lattner  EmitGCCBuiltinList(Ints, OS);
593f8b8913bc9cb232871445eefa8654caf7f9986fChris Lattner
603f8b8913bc9cb232871445eefa8654caf7f9986fChris Lattner  // Emit code to translate GCC builtins into LLVM intrinsics.
613f8b8913bc9cb232871445eefa8654caf7f9986fChris Lattner  EmitIntrinsicToGCCBuiltinMap(Ints, OS);
629e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner}
639e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner
649e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattnervoid IntrinsicEmitter::EmitEnumInfo(const std::vector<CodeGenIntrinsic> &Ints,
659e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner                                    std::ostream &OS) {
669b843b249462980ae4630dc37d1bcccde884a5a7Chris Lattner  OS << "// Enum values for Intrinsics.h\n";
679e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner  OS << "#ifdef GET_INTRINSIC_ENUM_VALUES\n";
689e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner  for (unsigned i = 0, e = Ints.size(); i != e; ++i) {
699e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner    OS << "    " << Ints[i].EnumName;
709e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner    OS << ((i != e-1) ? ", " : "  ");
719e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner    OS << std::string(40-Ints[i].EnumName.size(), ' ')
729e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner      << "// " << Ints[i].Name << "\n";
739e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner  }
749e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner  OS << "#endif\n\n";
759e493cfcc32aee58e6750ce1efa52d5c3bc3f893Chris Lattner}
769b843b249462980ae4630dc37d1bcccde884a5a7Chris Lattner
779b843b249462980ae4630dc37d1bcccde884a5a7Chris Lattnervoid IntrinsicEmitter::
789b843b249462980ae4630dc37d1bcccde884a5a7Chris LattnerEmitFnNameRecognizer(const std::vector<CodeGenIntrinsic> &Ints,
799b843b249462980ae4630dc37d1bcccde884a5a7Chris Lattner                     std::ostream &OS) {
809b843b249462980ae4630dc37d1bcccde884a5a7Chris Lattner  // Build a function name -> intrinsic name mapping.
81c4de3dec62c3f60ae7297f93c19c799c403c2e9fReid Spencer  std::map<std::string, unsigned> IntMapping;
829b843b249462980ae4630dc37d1bcccde884a5a7Chris Lattner  for (unsigned i = 0, e = Ints.size(); i != e; ++i)
83c4de3dec62c3f60ae7297f93c19c799c403c2e9fReid Spencer    IntMapping[Ints[i].Name] = i;
849b843b249462980ae4630dc37d1bcccde884a5a7Chris Lattner
859b843b249462980ae4630dc37d1bcccde884a5a7Chris Lattner  OS << "// Function name -> enum value recognizer code.\n";
869b843b249462980ae4630dc37d1bcccde884a5a7Chris Lattner  OS << "#ifdef GET_FUNCTION_RECOGNIZER\n";
879b843b249462980ae4630dc37d1bcccde884a5a7Chris Lattner  OS << "  switch (Name[5]) {\n";
883b515802f652b16b05c9a8f344d219a0739b36a3Chris Lattner  OS << "  default:\n";
899b843b249462980ae4630dc37d1bcccde884a5a7Chris Lattner  // Emit the intrinsics in sorted order.
909b843b249462980ae4630dc37d1bcccde884a5a7Chris Lattner  char LastChar = 0;
91c4de3dec62c3f60ae7297f93c19c799c403c2e9fReid Spencer  for (std::map<std::string, unsigned>::iterator I = IntMapping.begin(),
929b843b249462980ae4630dc37d1bcccde884a5a7Chris Lattner       E = IntMapping.end(); I != E; ++I) {
939b843b249462980ae4630dc37d1bcccde884a5a7Chris Lattner    if (I->first[5] != LastChar) {
949b843b249462980ae4630dc37d1bcccde884a5a7Chris Lattner      LastChar = I->first[5];
953b515802f652b16b05c9a8f344d219a0739b36a3Chris Lattner      OS << "    break;\n";
969b843b249462980ae4630dc37d1bcccde884a5a7Chris Lattner      OS << "  case '" << LastChar << "':\n";
979b843b249462980ae4630dc37d1bcccde884a5a7Chris Lattner    }
989b843b249462980ae4630dc37d1bcccde884a5a7Chris Lattner
99c4de3dec62c3f60ae7297f93c19c799c403c2e9fReid Spencer    // For overloaded intrinsics, only the prefix needs to match
100c4de3dec62c3f60ae7297f93c19c799c403c2e9fReid Spencer    if (Ints[I->second].isOverloaded)
1016994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth      OS << "    if (Len > " << I->first.size()
1026994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth       << " && !memcmp(Name, \"" << I->first << ".\", "
10349de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen       << (I->first.size() + 1) << ")) return " << TargetPrefix << "Intrinsic::"
1046994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth       << Ints[I->second].EnumName << ";\n";
105c4de3dec62c3f60ae7297f93c19c799c403c2e9fReid Spencer    else
106c4de3dec62c3f60ae7297f93c19c799c403c2e9fReid Spencer      OS << "    if (Len == " << I->first.size()
1076994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth         << " && !memcmp(Name, \"" << I->first << "\", "
10849de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen         << I->first.size() << ")) return " << TargetPrefix << "Intrinsic::"
109c4de3dec62c3f60ae7297f93c19c799c403c2e9fReid Spencer         << Ints[I->second].EnumName << ";\n";
1109b843b249462980ae4630dc37d1bcccde884a5a7Chris Lattner  }
1119b843b249462980ae4630dc37d1bcccde884a5a7Chris Lattner  OS << "  }\n";
112f97a00e681c7a526d49759d0d1b9d327cbf6c04aChris Lattner  OS << "#endif\n\n";
113f97a00e681c7a526d49759d0d1b9d327cbf6c04aChris Lattner}
114f97a00e681c7a526d49759d0d1b9d327cbf6c04aChris Lattner
115fda6affb95e9f68278cb5cf75dc3fd3406978255Chris Lattnervoid IntrinsicEmitter::
116fda6affb95e9f68278cb5cf75dc3fd3406978255Chris LattnerEmitIntrinsicToNameTable(const std::vector<CodeGenIntrinsic> &Ints,
117fda6affb95e9f68278cb5cf75dc3fd3406978255Chris Lattner                         std::ostream &OS) {
118fda6affb95e9f68278cb5cf75dc3fd3406978255Chris Lattner  OS << "// Intrinsic ID to name table\n";
119fda6affb95e9f68278cb5cf75dc3fd3406978255Chris Lattner  OS << "#ifdef GET_INTRINSIC_NAME_TABLE\n";
120fda6affb95e9f68278cb5cf75dc3fd3406978255Chris Lattner  OS << "  // Note that entry #0 is the invalid intrinsic!\n";
121f065a6f711dca09ba36ec8fd3556c4936cdbe621Evan Cheng  for (unsigned i = 0, e = Ints.size(); i != e; ++i)
122f065a6f711dca09ba36ec8fd3556c4936cdbe621Evan Cheng    OS << "  \"" << Ints[i].Name << "\",\n";
123fda6affb95e9f68278cb5cf75dc3fd3406978255Chris Lattner  OS << "#endif\n\n";
124fda6affb95e9f68278cb5cf75dc3fd3406978255Chris Lattner}
125fda6affb95e9f68278cb5cf75dc3fd3406978255Chris Lattner
1260d52ff1f7b993750a74a5d4432273092de9af069Mon P Wangvoid IntrinsicEmitter::
1270d52ff1f7b993750a74a5d4432273092de9af069Mon P WangEmitIntrinsicToOverloadTable(const std::vector<CodeGenIntrinsic> &Ints,
1280d52ff1f7b993750a74a5d4432273092de9af069Mon P Wang                         std::ostream &OS) {
1290d52ff1f7b993750a74a5d4432273092de9af069Mon P Wang  OS << "// Intrinsic ID to overload table\n";
1300d52ff1f7b993750a74a5d4432273092de9af069Mon P Wang  OS << "#ifdef GET_INTRINSIC_OVERLOAD_TABLE\n";
1310d52ff1f7b993750a74a5d4432273092de9af069Mon P Wang  OS << "  // Note that entry #0 is the invalid intrinsic!\n";
1320d52ff1f7b993750a74a5d4432273092de9af069Mon P Wang  for (unsigned i = 0, e = Ints.size(); i != e; ++i) {
1330d52ff1f7b993750a74a5d4432273092de9af069Mon P Wang    OS << "  ";
1340d52ff1f7b993750a74a5d4432273092de9af069Mon P Wang    if (Ints[i].isOverloaded)
1350d52ff1f7b993750a74a5d4432273092de9af069Mon P Wang      OS << "true";
1360d52ff1f7b993750a74a5d4432273092de9af069Mon P Wang    else
1370d52ff1f7b993750a74a5d4432273092de9af069Mon P Wang      OS << "false";
1380d52ff1f7b993750a74a5d4432273092de9af069Mon P Wang    OS << ",\n";
1390d52ff1f7b993750a74a5d4432273092de9af069Mon P Wang  }
1400d52ff1f7b993750a74a5d4432273092de9af069Mon P Wang  OS << "#endif\n\n";
1410d52ff1f7b993750a74a5d4432273092de9af069Mon P Wang}
1420d52ff1f7b993750a74a5d4432273092de9af069Mon P Wang
14383ec4b6711980242ef3c55a4fa36b2d7a39c1bfbDuncan Sandsstatic void EmitTypeForValueType(std::ostream &OS, MVT::SimpleValueType VT) {
14483ec4b6711980242ef3c55a4fa36b2d7a39c1bfbDuncan Sands  if (MVT(VT).isInteger()) {
14583ec4b6711980242ef3c55a4fa36b2d7a39c1bfbDuncan Sands    unsigned BitWidth = MVT(VT).getSizeInBits();
1466994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth    OS << "IntegerType::get(" << BitWidth << ")";
1476994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth  } else if (VT == MVT::Other) {
1486994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth    // MVT::OtherVT is used to mean the empty struct type here.
1496994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth    OS << "StructType::get(std::vector<const Type *>())";
1506994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth  } else if (VT == MVT::f32) {
1516994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth    OS << "Type::FloatTy";
1526994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth  } else if (VT == MVT::f64) {
1536994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth    OS << "Type::DoubleTy";
154317096ab3710fda0960be58804e9f80c800340f6Dale Johannesen  } else if (VT == MVT::f80) {
155317096ab3710fda0960be58804e9f80c800340f6Dale Johannesen    OS << "Type::X86_FP80Ty";
156317096ab3710fda0960be58804e9f80c800340f6Dale Johannesen  } else if (VT == MVT::f128) {
157317096ab3710fda0960be58804e9f80c800340f6Dale Johannesen    OS << "Type::FP128Ty";
158317096ab3710fda0960be58804e9f80c800340f6Dale Johannesen  } else if (VT == MVT::ppcf128) {
159317096ab3710fda0960be58804e9f80c800340f6Dale Johannesen    OS << "Type::PPC_FP128Ty";
1606994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth  } else if (VT == MVT::isVoid) {
1616994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth    OS << "Type::VoidTy";
1626994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth  } else {
1636994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth    assert(false && "Unsupported ValueType!");
16418faf5d9f7f89130b9e3304965b81e1c70ebb75cChris Lattner  }
16518faf5d9f7f89130b9e3304965b81e1c70ebb75cChris Lattner}
16618faf5d9f7f89130b9e3304965b81e1c70ebb75cChris Lattner
167cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendlingstatic void EmitTypeGenerate(std::ostream &OS, const Record *ArgType,
168cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling                             unsigned &ArgNo);
169cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling
170cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendlingstatic void EmitTypeGenerate(std::ostream &OS,
171cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling                             const std::vector<Record*> &ArgTypes,
172cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling                             unsigned &ArgNo) {
173cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling  if (ArgTypes.size() == 1) {
174cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling    EmitTypeGenerate(OS, ArgTypes.front(), ArgNo);
175cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling    return;
176cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling  }
177cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling
178cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling  OS << "StructType::get(";
179cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling
180cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling  for (std::vector<Record*>::const_iterator
18120072af3b0b22d90afbce769409f4ed822520366Bill Wendling         I = ArgTypes.begin(), E = ArgTypes.end(); I != E; ++I) {
182cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling    EmitTypeGenerate(OS, *I, ArgNo);
18320072af3b0b22d90afbce769409f4ed822520366Bill Wendling    OS << ", ";
18420072af3b0b22d90afbce769409f4ed822520366Bill Wendling  }
185cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling
18620072af3b0b22d90afbce769409f4ed822520366Bill Wendling  OS << " NULL)";
187cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling}
188cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling
189cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendlingstatic void EmitTypeGenerate(std::ostream &OS, const Record *ArgType,
19084c614d1ac671b1a5524169f20028f51c30be728Reid Spencer                             unsigned &ArgNo) {
19183ec4b6711980242ef3c55a4fa36b2d7a39c1bfbDuncan Sands  MVT::SimpleValueType VT = getValueType(ArgType->getValueAsDef("VT"));
1926994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth
1936994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth  if (ArgType->isSubClassOf("LLVMMatchType")) {
1946994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth    unsigned Number = ArgType->getValueAsInt("Number");
1956994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth    assert(Number < ArgNo && "Invalid matching number!");
196bc03979536a1ecb220f1330719f3e3973a81ab0bBob Wilson    if (ArgType->isSubClassOf("LLVMExtendedElementVectorType"))
197bc03979536a1ecb220f1330719f3e3973a81ab0bBob Wilson      OS << "VectorType::getExtendedElementVectorType"
198bc03979536a1ecb220f1330719f3e3973a81ab0bBob Wilson         << "(dyn_cast<VectorType>(Tys[" << Number << "]))";
199bc03979536a1ecb220f1330719f3e3973a81ab0bBob Wilson    else if (ArgType->isSubClassOf("LLVMTruncatedElementVectorType"))
200bc03979536a1ecb220f1330719f3e3973a81ab0bBob Wilson      OS << "VectorType::getTruncatedElementVectorType"
201bc03979536a1ecb220f1330719f3e3973a81ab0bBob Wilson         << "(dyn_cast<VectorType>(Tys[" << Number << "]))";
202bc03979536a1ecb220f1330719f3e3973a81ab0bBob Wilson    else
203bc03979536a1ecb220f1330719f3e3973a81ab0bBob Wilson      OS << "Tys[" << Number << "]";
2040fee3ff93ea0bf1ce6466fec1d8496514d76e289Dan Gohman  } else if (VT == MVT::iAny || VT == MVT::fAny) {
20584c614d1ac671b1a5524169f20028f51c30be728Reid Spencer    // NOTE: The ArgNo variable here is not the absolute argument number, it is
20684c614d1ac671b1a5524169f20028f51c30be728Reid Spencer    // the index of the "arbitrary" type in the Tys array passed to the
20784c614d1ac671b1a5524169f20028f51c30be728Reid Spencer    // Intrinsic::getDeclaration function. Consequently, we only want to
2086994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth    // increment it when we actually hit an overloaded type. Getting this wrong
2096994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth    // leads to very subtle bugs!
2106994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth    OS << "Tys[" << ArgNo++ << "]";
21183ec4b6711980242ef3c55a4fa36b2d7a39c1bfbDuncan Sands  } else if (MVT(VT).isVector()) {
21283ec4b6711980242ef3c55a4fa36b2d7a39c1bfbDuncan Sands    MVT VVT = VT;
2139d6565a5b1fbc4286d6ee638d8f47a3171a9ed7eReid Spencer    OS << "VectorType::get(";
21483ec4b6711980242ef3c55a4fa36b2d7a39c1bfbDuncan Sands    EmitTypeForValueType(OS, VVT.getVectorElementType().getSimpleVT());
21583ec4b6711980242ef3c55a4fa36b2d7a39c1bfbDuncan Sands    OS << ", " << VVT.getVectorNumElements() << ")";
2166994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth  } else if (VT == MVT::iPTR) {
21743ad6b3e0d6ada51e9b23aab3e061187f1f5710cChristopher Lamb    OS << "PointerType::getUnqual(";
218c4de3dec62c3f60ae7297f93c19c799c403c2e9fReid Spencer    EmitTypeGenerate(OS, ArgType->getValueAsDef("ElTy"), ArgNo);
21995af592a631f403e1458ec1155f89fc31011572cJim Laskey    OS << ")";
220e3b3a7241c01f26613694e53b26b01abf764ddfcMon P Wang  } else if (VT == MVT::iPTRAny) {
221e3b3a7241c01f26613694e53b26b01abf764ddfcMon P Wang    // Make sure the user has passed us an argument type to overload. If not,
222e3b3a7241c01f26613694e53b26b01abf764ddfcMon P Wang    // treat it as an ordinary (not overloaded) intrinsic.
223e3b3a7241c01f26613694e53b26b01abf764ddfcMon P Wang    OS << "(" << ArgNo << " < numTys) ? Tys[" << ArgNo
224e3b3a7241c01f26613694e53b26b01abf764ddfcMon P Wang    << "] : PointerType::getUnqual(";
225e3b3a7241c01f26613694e53b26b01abf764ddfcMon P Wang    EmitTypeGenerate(OS, ArgType->getValueAsDef("ElTy"), ArgNo);
226e3b3a7241c01f26613694e53b26b01abf764ddfcMon P Wang    OS << ")";
227e3b3a7241c01f26613694e53b26b01abf764ddfcMon P Wang    ++ArgNo;
2286994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth  } else if (VT == MVT::isVoid) {
2296994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth    if (ArgNo == 0)
2306994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth      OS << "Type::VoidTy";
2316994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth    else
2326994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth      // MVT::isVoid is used to mean varargs here.
2336994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth      OS << "...";
23495af592a631f403e1458ec1155f89fc31011572cJim Laskey  } else {
2356994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth    EmitTypeForValueType(OS, VT);
23695af592a631f403e1458ec1155f89fc31011572cJim Laskey  }
23795af592a631f403e1458ec1155f89fc31011572cJim Laskey}
23895af592a631f403e1458ec1155f89fc31011572cJim Laskey
239da4231f134989af7dc6bd3408821ba573def27b2Jim Grosbach/// RecordListComparator - Provide a deterministic comparator for lists of
240c4d9b240b157efa9301d451ac44c12f6b004db8fChris Lattner/// records.
241c4d9b240b157efa9301d451ac44c12f6b004db8fChris Lattnernamespace {
242cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling  typedef std::pair<std::vector<Record*>, std::vector<Record*> > RecPair;
243c4d9b240b157efa9301d451ac44c12f6b004db8fChris Lattner  struct RecordListComparator {
244cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling    bool operator()(const RecPair &LHS,
245cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling                    const RecPair &RHS) const {
246c4d9b240b157efa9301d451ac44c12f6b004db8fChris Lattner      unsigned i = 0;
247cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling      const std::vector<Record*> *LHSVec = &LHS.first;
248cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling      const std::vector<Record*> *RHSVec = &RHS.first;
249cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling      unsigned RHSSize = RHSVec->size();
250cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling      unsigned LHSSize = LHSVec->size();
251cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling
252c4d9b240b157efa9301d451ac44c12f6b004db8fChris Lattner      do {
253cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling        if (i == RHSSize) return false;  // RHS is shorter than LHS.
254cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling        if ((*LHSVec)[i] != (*RHSVec)[i])
255cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling          return (*LHSVec)[i]->getName() < (*RHSVec)[i]->getName();
256cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling      } while (++i != LHSSize);
257cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling
258023422a6eb9ea692a5a837dc1daf256ac75ac6b0Bill Wendling      if (i != RHSSize) return true;
259cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling
260cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling      i = 0;
261cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling      LHSVec = &LHS.second;
262cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling      RHSVec = &RHS.second;
263cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling      RHSSize = RHSVec->size();
264cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling      LHSSize = LHSVec->size();
265cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling
266cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling      for (i = 0; i != LHSSize; ++i) {
267cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling        if (i == RHSSize) return false;  // RHS is shorter than LHS.
268cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling        if ((*LHSVec)[i] != (*RHSVec)[i])
269cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling          return (*LHSVec)[i]->getName() < (*RHSVec)[i]->getName();
270cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling      }
271cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling
272cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling      return i != RHSSize;
273c4d9b240b157efa9301d451ac44c12f6b004db8fChris Lattner    }
274c4d9b240b157efa9301d451ac44c12f6b004db8fChris Lattner  };
275c4d9b240b157efa9301d451ac44c12f6b004db8fChris Lattner}
276c4d9b240b157efa9301d451ac44c12f6b004db8fChris Lattner
277f97a00e681c7a526d49759d0d1b9d327cbf6c04aChris Lattnervoid IntrinsicEmitter::EmitVerifier(const std::vector<CodeGenIntrinsic> &Ints,
278f97a00e681c7a526d49759d0d1b9d327cbf6c04aChris Lattner                                    std::ostream &OS) {
279f97a00e681c7a526d49759d0d1b9d327cbf6c04aChris Lattner  OS << "// Verifier::visitIntrinsicFunctionCall code.\n";
280f97a00e681c7a526d49759d0d1b9d327cbf6c04aChris Lattner  OS << "#ifdef GET_INTRINSIC_VERIFIER\n";
281f97a00e681c7a526d49759d0d1b9d327cbf6c04aChris Lattner  OS << "  switch (ID) {\n";
282f97a00e681c7a526d49759d0d1b9d327cbf6c04aChris Lattner  OS << "  default: assert(0 && \"Invalid intrinsic!\");\n";
283c4d9b240b157efa9301d451ac44c12f6b004db8fChris Lattner
284c4d9b240b157efa9301d451ac44c12f6b004db8fChris Lattner  // This checking can emit a lot of very common code.  To reduce the amount of
285c4d9b240b157efa9301d451ac44c12f6b004db8fChris Lattner  // code that we emit, batch up cases that have identical types.  This avoids
286c4d9b240b157efa9301d451ac44c12f6b004db8fChris Lattner  // problems where GCC can run out of memory compiling Verifier.cpp.
287cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling  typedef std::map<RecPair, std::vector<unsigned>, RecordListComparator> MapTy;
288c4d9b240b157efa9301d451ac44c12f6b004db8fChris Lattner  MapTy UniqueArgInfos;
289c4d9b240b157efa9301d451ac44c12f6b004db8fChris Lattner
290c4d9b240b157efa9301d451ac44c12f6b004db8fChris Lattner  // Compute the unique argument type info.
291c4d9b240b157efa9301d451ac44c12f6b004db8fChris Lattner  for (unsigned i = 0, e = Ints.size(); i != e; ++i)
292cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling    UniqueArgInfos[make_pair(Ints[i].IS.RetTypeDefs,
293cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling                             Ints[i].IS.ParamTypeDefs)].push_back(i);
294c4d9b240b157efa9301d451ac44c12f6b004db8fChris Lattner
295c4d9b240b157efa9301d451ac44c12f6b004db8fChris Lattner  // Loop through the array, emitting one comparison for each batch.
296c4d9b240b157efa9301d451ac44c12f6b004db8fChris Lattner  for (MapTy::iterator I = UniqueArgInfos.begin(),
297c4d9b240b157efa9301d451ac44c12f6b004db8fChris Lattner       E = UniqueArgInfos.end(); I != E; ++I) {
298cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling    for (unsigned i = 0, e = I->second.size(); i != e; ++i)
299c4d9b240b157efa9301d451ac44c12f6b004db8fChris Lattner      OS << "  case Intrinsic::" << Ints[I->second[i]].EnumName << ":\t\t// "
300c4d9b240b157efa9301d451ac44c12f6b004db8fChris Lattner         << Ints[I->second[i]].Name << "\n";
301f124b46b4f18b1a8f054a1222324ae15079f6ed8Chris Lattner
302cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling    const RecPair &ArgTypes = I->first;
303cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling    const std::vector<Record*> &RetTys = ArgTypes.first;
304cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling    const std::vector<Record*> &ParamTys = ArgTypes.second;
305cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling
306cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling    OS << "    VerifyIntrinsicPrototype(ID, IF, " << RetTys.size() << ", "
307cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling       << ParamTys.size();
308cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling
309cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling    // Emit return types.
310cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling    for (unsigned j = 0, je = RetTys.size(); j != je; ++j) {
311cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling      Record *ArgType = RetTys[j];
312cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling      OS << ", ";
313cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling
3146994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth      if (ArgType->isSubClassOf("LLVMMatchType")) {
3156994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth        unsigned Number = ArgType->getValueAsInt("Number");
3166994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth        assert(Number < j && "Invalid matching number!");
317bc03979536a1ecb220f1330719f3e3973a81ab0bBob Wilson        if (ArgType->isSubClassOf("LLVMExtendedElementVectorType"))
318bc03979536a1ecb220f1330719f3e3973a81ab0bBob Wilson          OS << "~(ExtendedElementVectorType | " << Number << ")";
319bc03979536a1ecb220f1330719f3e3973a81ab0bBob Wilson        else if (ArgType->isSubClassOf("LLVMTruncatedElementVectorType"))
320bc03979536a1ecb220f1330719f3e3973a81ab0bBob Wilson          OS << "~(TruncatedElementVectorType | " << Number << ")";
321bc03979536a1ecb220f1330719f3e3973a81ab0bBob Wilson        else
322bc03979536a1ecb220f1330719f3e3973a81ab0bBob Wilson          OS << "~" << Number;
3236994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth      } else {
32483ec4b6711980242ef3c55a4fa36b2d7a39c1bfbDuncan Sands        MVT::SimpleValueType VT = getValueType(ArgType->getValueAsDef("VT"));
3256994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth        OS << getEnumName(VT);
326cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling
327cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling        if (VT == MVT::isVoid && j != 0 && j != je - 1)
328cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling          throw "Var arg type not last argument";
329cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling      }
330cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling    }
331cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling
332cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling    // Emit the parameter types.
333cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling    for (unsigned j = 0, je = ParamTys.size(); j != je; ++j) {
334cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling      Record *ArgType = ParamTys[j];
335cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling      OS << ", ";
336cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling
337cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling      if (ArgType->isSubClassOf("LLVMMatchType")) {
338cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling        unsigned Number = ArgType->getValueAsInt("Number");
339cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling        assert(Number < j + RetTys.size() && "Invalid matching number!");
340bc03979536a1ecb220f1330719f3e3973a81ab0bBob Wilson        if (ArgType->isSubClassOf("LLVMExtendedElementVectorType"))
341bc03979536a1ecb220f1330719f3e3973a81ab0bBob Wilson          OS << "~(ExtendedElementVectorType | " << Number << ")";
342bc03979536a1ecb220f1330719f3e3973a81ab0bBob Wilson        else if (ArgType->isSubClassOf("LLVMTruncatedElementVectorType"))
343bc03979536a1ecb220f1330719f3e3973a81ab0bBob Wilson          OS << "~(TruncatedElementVectorType | " << Number << ")";
344bc03979536a1ecb220f1330719f3e3973a81ab0bBob Wilson        else
345bc03979536a1ecb220f1330719f3e3973a81ab0bBob Wilson          OS << "~" << Number;
346cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling      } else {
347cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling        MVT::SimpleValueType VT = getValueType(ArgType->getValueAsDef("VT"));
348cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling        OS << getEnumName(VT);
349cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling
350cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling        if (VT == MVT::isVoid && j != 0 && j != je - 1)
35195d97b90e8427255c8298f5d3a1ab605af62aab4Jim Laskey          throw "Var arg type not last argument";
35295d97b90e8427255c8298f5d3a1ab605af62aab4Jim Laskey      }
35395d97b90e8427255c8298f5d3a1ab605af62aab4Jim Laskey    }
35495d97b90e8427255c8298f5d3a1ab605af62aab4Jim Laskey
3556994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth    OS << ");\n";
356f97a00e681c7a526d49759d0d1b9d327cbf6c04aChris Lattner    OS << "    break;\n";
357f97a00e681c7a526d49759d0d1b9d327cbf6c04aChris Lattner  }
358f97a00e681c7a526d49759d0d1b9d327cbf6c04aChris Lattner  OS << "  }\n";
359f97a00e681c7a526d49759d0d1b9d327cbf6c04aChris Lattner  OS << "#endif\n\n";
3609b843b249462980ae4630dc37d1bcccde884a5a7Chris Lattner}
3619b843b249462980ae4630dc37d1bcccde884a5a7Chris Lattner
36295af592a631f403e1458ec1155f89fc31011572cJim Laskeyvoid IntrinsicEmitter::EmitGenerator(const std::vector<CodeGenIntrinsic> &Ints,
36395af592a631f403e1458ec1155f89fc31011572cJim Laskey                                     std::ostream &OS) {
36495af592a631f403e1458ec1155f89fc31011572cJim Laskey  OS << "// Code for generating Intrinsic function declarations.\n";
36595af592a631f403e1458ec1155f89fc31011572cJim Laskey  OS << "#ifdef GET_INTRINSIC_GENERATOR\n";
36695af592a631f403e1458ec1155f89fc31011572cJim Laskey  OS << "  switch (id) {\n";
36795af592a631f403e1458ec1155f89fc31011572cJim Laskey  OS << "  default: assert(0 && \"Invalid intrinsic!\");\n";
36895af592a631f403e1458ec1155f89fc31011572cJim Laskey
36995af592a631f403e1458ec1155f89fc31011572cJim Laskey  // Similar to GET_INTRINSIC_VERIFIER, batch up cases that have identical
37095af592a631f403e1458ec1155f89fc31011572cJim Laskey  // types.
371cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling  typedef std::map<RecPair, std::vector<unsigned>, RecordListComparator> MapTy;
37295af592a631f403e1458ec1155f89fc31011572cJim Laskey  MapTy UniqueArgInfos;
37395af592a631f403e1458ec1155f89fc31011572cJim Laskey
37495af592a631f403e1458ec1155f89fc31011572cJim Laskey  // Compute the unique argument type info.
37595af592a631f403e1458ec1155f89fc31011572cJim Laskey  for (unsigned i = 0, e = Ints.size(); i != e; ++i)
376cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling    UniqueArgInfos[make_pair(Ints[i].IS.RetTypeDefs,
377cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling                             Ints[i].IS.ParamTypeDefs)].push_back(i);
37895af592a631f403e1458ec1155f89fc31011572cJim Laskey
37995af592a631f403e1458ec1155f89fc31011572cJim Laskey  // Loop through the array, emitting one generator for each batch.
38049de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen  std::string IntrinsicStr = TargetPrefix + "Intrinsic::";
38149de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen
38295af592a631f403e1458ec1155f89fc31011572cJim Laskey  for (MapTy::iterator I = UniqueArgInfos.begin(),
38395af592a631f403e1458ec1155f89fc31011572cJim Laskey       E = UniqueArgInfos.end(); I != E; ++I) {
384cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling    for (unsigned i = 0, e = I->second.size(); i != e; ++i)
38549de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen      OS << "  case " << IntrinsicStr << Ints[I->second[i]].EnumName
38649de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen         << ":\t\t// " << Ints[I->second[i]].Name << "\n";
38795af592a631f403e1458ec1155f89fc31011572cJim Laskey
388cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling    const RecPair &ArgTypes = I->first;
389cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling    const std::vector<Record*> &RetTys = ArgTypes.first;
390cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling    const std::vector<Record*> &ParamTys = ArgTypes.second;
391cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling
392cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling    unsigned N = ParamTys.size();
39395af592a631f403e1458ec1155f89fc31011572cJim Laskey
3946994040a952e5fb27605eb3cf29ed86c4e59cf62Chandler Carruth    if (N > 1 &&
395cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling        getValueType(ParamTys[N - 1]->getValueAsDef("VT")) == MVT::isVoid) {
39695af592a631f403e1458ec1155f89fc31011572cJim Laskey      OS << "    IsVarArg = true;\n";
39795af592a631f403e1458ec1155f89fc31011572cJim Laskey      --N;
39895af592a631f403e1458ec1155f89fc31011572cJim Laskey    }
399cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling
40084c614d1ac671b1a5524169f20028f51c30be728Reid Spencer    unsigned ArgNo = 0;
40195af592a631f403e1458ec1155f89fc31011572cJim Laskey    OS << "    ResultTy = ";
402cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling    EmitTypeGenerate(OS, RetTys, ArgNo);
40395af592a631f403e1458ec1155f89fc31011572cJim Laskey    OS << ";\n";
40495af592a631f403e1458ec1155f89fc31011572cJim Laskey
405cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling    for (unsigned j = 0; j != N; ++j) {
40695af592a631f403e1458ec1155f89fc31011572cJim Laskey      OS << "    ArgTys.push_back(";
407cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling      EmitTypeGenerate(OS, ParamTys[j], ArgNo);
40895af592a631f403e1458ec1155f89fc31011572cJim Laskey      OS << ");\n";
40995af592a631f403e1458ec1155f89fc31011572cJim Laskey    }
410cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling
41195af592a631f403e1458ec1155f89fc31011572cJim Laskey    OS << "    break;\n";
41295af592a631f403e1458ec1155f89fc31011572cJim Laskey  }
413cdcc3e6e12b8b4e224bd62c96768c5f5e325aaceBill Wendling
41495af592a631f403e1458ec1155f89fc31011572cJim Laskey  OS << "  }\n";
41595af592a631f403e1458ec1155f89fc31011572cJim Laskey  OS << "#endif\n\n";
41695af592a631f403e1458ec1155f89fc31011572cJim Laskey}
41795af592a631f403e1458ec1155f89fc31011572cJim Laskey
418048ffb239c282277959463c61200b86e2380cb84Chris Lattner/// EmitAttributes - This emits the Intrinsic::getAttributes method.
4194e5f35973c1bc56cce14d44c6f8f4ad1e9f1a438Chris Lattnervoid IntrinsicEmitter::
420a3355ffb3d30d19d226bbb75707991c60f236e37Duncan SandsEmitAttributes(const std::vector<CodeGenIntrinsic> &Ints, std::ostream &OS) {
421a3355ffb3d30d19d226bbb75707991c60f236e37Duncan Sands  OS << "// Add parameter attributes that are not common to all intrinsics.\n";
422a3355ffb3d30d19d226bbb75707991c60f236e37Duncan Sands  OS << "#ifdef GET_INTRINSIC_ATTRIBUTES\n";
42349de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen  if (TargetOnly)
42449de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen    OS << "static AttrListPtr getAttributes(" << TargetPrefix
42549de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen       << "Intrinsic::ID id) {";
42649de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen  else
42749de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen    OS << "AttrListPtr Intrinsic::getAttributes(ID id) {";
428048ffb239c282277959463c61200b86e2380cb84Chris Lattner  OS << "  // No intrinsic can throw exceptions.\n";
429048ffb239c282277959463c61200b86e2380cb84Chris Lattner  OS << "  Attributes Attr = Attribute::NoUnwind;\n";
430a3355ffb3d30d19d226bbb75707991c60f236e37Duncan Sands  OS << "  switch (id) {\n";
4317056de375d898d9d9ecc17e170632d91d18be4a8Chris Lattner  OS << "  default: break;\n";
43210dae94be2ccb187bd4e3da53771be54057acd6cChris Lattner  unsigned MaxArgAttrs = 0;
4337056de375d898d9d9ecc17e170632d91d18be4a8Chris Lattner  for (unsigned i = 0, e = Ints.size(); i != e; ++i) {
43410dae94be2ccb187bd4e3da53771be54057acd6cChris Lattner    MaxArgAttrs =
43510dae94be2ccb187bd4e3da53771be54057acd6cChris Lattner      std::max(MaxArgAttrs, unsigned(Ints[i].ArgumentAttributes.size()));
4367056de375d898d9d9ecc17e170632d91d18be4a8Chris Lattner    switch (Ints[i].ModRef) {
4377056de375d898d9d9ecc17e170632d91d18be4a8Chris Lattner    default: break;
4387056de375d898d9d9ecc17e170632d91d18be4a8Chris Lattner    case CodeGenIntrinsic::NoMem:
43949de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen      OS << "  case " << TargetPrefix << "Intrinsic::" << Ints[i].EnumName
44049de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen         << ":\n";
4417056de375d898d9d9ecc17e170632d91d18be4a8Chris Lattner      break;
4427056de375d898d9d9ecc17e170632d91d18be4a8Chris Lattner    }
4437056de375d898d9d9ecc17e170632d91d18be4a8Chris Lattner  }
4440598866c052147c31b808391f58434ce3dbfb838Devang Patel  OS << "    Attr |= Attribute::ReadNone; // These do not access memory.\n";
445a3355ffb3d30d19d226bbb75707991c60f236e37Duncan Sands  OS << "    break;\n";
4464e5f35973c1bc56cce14d44c6f8f4ad1e9f1a438Chris Lattner  for (unsigned i = 0, e = Ints.size(); i != e; ++i) {
4474e5f35973c1bc56cce14d44c6f8f4ad1e9f1a438Chris Lattner    switch (Ints[i].ModRef) {
448022f64fbbc4669623e79b805379266fed519017dChris Lattner    default: break;
449022f64fbbc4669623e79b805379266fed519017dChris Lattner    case CodeGenIntrinsic::ReadArgMem:
450022f64fbbc4669623e79b805379266fed519017dChris Lattner    case CodeGenIntrinsic::ReadMem:
45149de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen      OS << "  case " << TargetPrefix << "Intrinsic::" << Ints[i].EnumName
45249de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen         << ":\n";
453022f64fbbc4669623e79b805379266fed519017dChris Lattner      break;
4544e5f35973c1bc56cce14d44c6f8f4ad1e9f1a438Chris Lattner    }
4554e5f35973c1bc56cce14d44c6f8f4ad1e9f1a438Chris Lattner  }
4560598866c052147c31b808391f58434ce3dbfb838Devang Patel  OS << "    Attr |= Attribute::ReadOnly; // These do not write memory.\n";
457a3355ffb3d30d19d226bbb75707991c60f236e37Duncan Sands  OS << "    break;\n";
4584e5f35973c1bc56cce14d44c6f8f4ad1e9f1a438Chris Lattner  OS << "  }\n";
45910dae94be2ccb187bd4e3da53771be54057acd6cChris Lattner  OS << "  AttributeWithIndex AWI[" << MaxArgAttrs+1 << "];\n";
460d4a2700fdc5bc8ac50084fcb39155e01e86168d5Chris Lattner  OS << "  unsigned NumAttrs = 0;\n";
46110dae94be2ccb187bd4e3da53771be54057acd6cChris Lattner  OS << "  switch (id) {\n";
46210dae94be2ccb187bd4e3da53771be54057acd6cChris Lattner  OS << "  default: break;\n";
46310dae94be2ccb187bd4e3da53771be54057acd6cChris Lattner
46410dae94be2ccb187bd4e3da53771be54057acd6cChris Lattner  // Add argument attributes for any intrinsics that have them.
46510dae94be2ccb187bd4e3da53771be54057acd6cChris Lattner  for (unsigned i = 0, e = Ints.size(); i != e; ++i) {
46610dae94be2ccb187bd4e3da53771be54057acd6cChris Lattner    if (Ints[i].ArgumentAttributes.empty()) continue;
46710dae94be2ccb187bd4e3da53771be54057acd6cChris Lattner
46849de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen    OS << "  case " << TargetPrefix << "Intrinsic::" << Ints[i].EnumName
46949de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen       << ":\n";
47010dae94be2ccb187bd4e3da53771be54057acd6cChris Lattner
47110dae94be2ccb187bd4e3da53771be54057acd6cChris Lattner    std::vector<std::pair<unsigned, CodeGenIntrinsic::ArgAttribute> > ArgAttrs =
47210dae94be2ccb187bd4e3da53771be54057acd6cChris Lattner      Ints[i].ArgumentAttributes;
47310dae94be2ccb187bd4e3da53771be54057acd6cChris Lattner    // Sort by argument index.
47410dae94be2ccb187bd4e3da53771be54057acd6cChris Lattner    std::sort(ArgAttrs.begin(), ArgAttrs.end());
47510dae94be2ccb187bd4e3da53771be54057acd6cChris Lattner
47610dae94be2ccb187bd4e3da53771be54057acd6cChris Lattner    unsigned NumArgsWithAttrs = 0;
47710dae94be2ccb187bd4e3da53771be54057acd6cChris Lattner
478d4a2700fdc5bc8ac50084fcb39155e01e86168d5Chris Lattner    while (!ArgAttrs.empty()) {
479d4a2700fdc5bc8ac50084fcb39155e01e86168d5Chris Lattner      unsigned ArgNo = ArgAttrs[0].first;
480d4a2700fdc5bc8ac50084fcb39155e01e86168d5Chris Lattner
481d4a2700fdc5bc8ac50084fcb39155e01e86168d5Chris Lattner      OS << "    AWI[" << NumArgsWithAttrs++ << "] = AttributeWithIndex::get("
482d4a2700fdc5bc8ac50084fcb39155e01e86168d5Chris Lattner         << ArgNo+1 << ", 0";
483d4a2700fdc5bc8ac50084fcb39155e01e86168d5Chris Lattner
484d4a2700fdc5bc8ac50084fcb39155e01e86168d5Chris Lattner      while (!ArgAttrs.empty() && ArgAttrs[0].first == ArgNo) {
485d4a2700fdc5bc8ac50084fcb39155e01e86168d5Chris Lattner        switch (ArgAttrs[0].second) {
486d4a2700fdc5bc8ac50084fcb39155e01e86168d5Chris Lattner        default: assert(0 && "Unknown arg attribute");
487d4a2700fdc5bc8ac50084fcb39155e01e86168d5Chris Lattner        case CodeGenIntrinsic::NoCapture:
488d4a2700fdc5bc8ac50084fcb39155e01e86168d5Chris Lattner          OS << "|Attribute::NoCapture";
489d4a2700fdc5bc8ac50084fcb39155e01e86168d5Chris Lattner          break;
490d4a2700fdc5bc8ac50084fcb39155e01e86168d5Chris Lattner        }
491d4a2700fdc5bc8ac50084fcb39155e01e86168d5Chris Lattner        ArgAttrs.erase(ArgAttrs.begin());
492d4a2700fdc5bc8ac50084fcb39155e01e86168d5Chris Lattner      }
493d4a2700fdc5bc8ac50084fcb39155e01e86168d5Chris Lattner      OS << ");\n";
494d4a2700fdc5bc8ac50084fcb39155e01e86168d5Chris Lattner    }
49510dae94be2ccb187bd4e3da53771be54057acd6cChris Lattner
496d4a2700fdc5bc8ac50084fcb39155e01e86168d5Chris Lattner    OS << "    NumAttrs = " << NumArgsWithAttrs << ";\n";
49710dae94be2ccb187bd4e3da53771be54057acd6cChris Lattner    OS << "    break;\n";
49810dae94be2ccb187bd4e3da53771be54057acd6cChris Lattner  }
49910dae94be2ccb187bd4e3da53771be54057acd6cChris Lattner
50010dae94be2ccb187bd4e3da53771be54057acd6cChris Lattner  OS << "  }\n";
501d4a2700fdc5bc8ac50084fcb39155e01e86168d5Chris Lattner  OS << "  AWI[NumAttrs] = AttributeWithIndex::get(~0, Attr);\n";
502d4a2700fdc5bc8ac50084fcb39155e01e86168d5Chris Lattner  OS << "  return AttrListPtr::get(AWI, NumAttrs+1);\n";
503048ffb239c282277959463c61200b86e2380cb84Chris Lattner  OS << "}\n";
504d4a2700fdc5bc8ac50084fcb39155e01e86168d5Chris Lattner  OS << "#endif // GET_INTRINSIC_ATTRIBUTES\n\n";
5054e5f35973c1bc56cce14d44c6f8f4ad1e9f1a438Chris Lattner}
506022f64fbbc4669623e79b805379266fed519017dChris Lattner
507d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands/// EmitModRefBehavior - Determine intrinsic alias analysis mod/ref behavior.
508d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sandsvoid IntrinsicEmitter::
509d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan SandsEmitModRefBehavior(const std::vector<CodeGenIntrinsic> &Ints, std::ostream &OS){
510d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands  OS << "// Determine intrinsic alias analysis mod/ref behavior.\n";
511d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands  OS << "#ifdef GET_INTRINSIC_MODREF_BEHAVIOR\n";
512d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands  OS << "switch (id) {\n";
513d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands  OS << "default:\n    return UnknownModRefBehavior;\n";
514d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands  for (unsigned i = 0, e = Ints.size(); i != e; ++i) {
515d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands    if (Ints[i].ModRef == CodeGenIntrinsic::WriteMem)
516d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands      continue;
517d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands    OS << "case " << TargetPrefix << "Intrinsic::" << Ints[i].EnumName
518d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands      << ":\n";
519d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands    switch (Ints[i].ModRef) {
520d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands    default:
521d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands      assert(false && "Unknown Mod/Ref type!");
522d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands    case CodeGenIntrinsic::NoMem:
523d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands      OS << "  return DoesNotAccessMemory;\n";
524d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands      break;
525d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands    case CodeGenIntrinsic::ReadArgMem:
526d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands    case CodeGenIntrinsic::ReadMem:
527d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands      OS << "  return OnlyReadsMemory;\n";
528d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands      break;
529d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands    case CodeGenIntrinsic::WriteArgMem:
530d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands      OS << "  return AccessesArguments;\n";
531d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands      break;
532d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands    }
533d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands  }
534d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands  OS << "}\n";
535d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands  OS << "#endif // GET_INTRINSIC_MODREF_BEHAVIOR\n\n";
536d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands}
537d869b3847f1dee78e1e4e1ed3cb41bd3ab0a079cDuncan Sands
538022f64fbbc4669623e79b805379266fed519017dChris Lattnervoid IntrinsicEmitter::
539022f64fbbc4669623e79b805379266fed519017dChris LattnerEmitGCCBuiltinList(const std::vector<CodeGenIntrinsic> &Ints, std::ostream &OS){
540022f64fbbc4669623e79b805379266fed519017dChris Lattner  OS << "// Get the GCC builtin that corresponds to an LLVM intrinsic.\n";
541022f64fbbc4669623e79b805379266fed519017dChris Lattner  OS << "#ifdef GET_GCC_BUILTIN_NAME\n";
542022f64fbbc4669623e79b805379266fed519017dChris Lattner  OS << "  switch (F->getIntrinsicID()) {\n";
543022f64fbbc4669623e79b805379266fed519017dChris Lattner  OS << "  default: BuiltinName = \"\"; break;\n";
544022f64fbbc4669623e79b805379266fed519017dChris Lattner  for (unsigned i = 0, e = Ints.size(); i != e; ++i) {
545022f64fbbc4669623e79b805379266fed519017dChris Lattner    if (!Ints[i].GCCBuiltinName.empty()) {
546022f64fbbc4669623e79b805379266fed519017dChris Lattner      OS << "  case Intrinsic::" << Ints[i].EnumName << ": BuiltinName = \""
547022f64fbbc4669623e79b805379266fed519017dChris Lattner         << Ints[i].GCCBuiltinName << "\"; break;\n";
548022f64fbbc4669623e79b805379266fed519017dChris Lattner    }
549022f64fbbc4669623e79b805379266fed519017dChris Lattner  }
550022f64fbbc4669623e79b805379266fed519017dChris Lattner  OS << "  }\n";
551022f64fbbc4669623e79b805379266fed519017dChris Lattner  OS << "#endif\n\n";
552767a25b8788b5e313c99c16b4d359478432901f5Reid Spencer}
5533f8b8913bc9cb232871445eefa8654caf7f9986fChris Lattner
554331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner/// EmitBuiltinComparisons - Emit comparisons to determine whether the specified
555331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner/// sorted range of builtin names is equal to the current builtin.  This breaks
556331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner/// it down into a simple tree.
557331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner///
558331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner/// At this point, we know that all the builtins in the range have the same name
559331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner/// for the first 'CharStart' characters.  Only the end of the name needs to be
560331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner/// discriminated.
561331bf92fb51f058672144681b3d0e67d30f5699fChris Lattnertypedef std::map<std::string, std::string>::const_iterator StrMapIterator;
562331bf92fb51f058672144681b3d0e67d30f5699fChris Lattnerstatic void EmitBuiltinComparisons(StrMapIterator Start, StrMapIterator End,
563331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner                                   unsigned CharStart, unsigned Indent,
56449de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen                                   std::string TargetPrefix, std::ostream &OS) {
565331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner  if (Start == End) return; // empty range.
566331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner
567331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner  // Determine what, if anything, is the same about all these strings.
568331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner  std::string CommonString = Start->first;
569331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner  unsigned NumInRange = 0;
570331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner  for (StrMapIterator I = Start; I != End; ++I, ++NumInRange) {
571331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner    // Find the first character that doesn't match.
572331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner    const std::string &ThisStr = I->first;
573331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner    unsigned NonMatchChar = CharStart;
574331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner    while (NonMatchChar < CommonString.size() &&
575331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner           NonMatchChar < ThisStr.size() &&
576331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner           CommonString[NonMatchChar] == ThisStr[NonMatchChar])
577331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner      ++NonMatchChar;
578331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner    // Truncate off pieces that don't match.
579331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner    CommonString.resize(NonMatchChar);
580331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner  }
581331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner
582331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner  // Just compare the rest of the string.
583331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner  if (NumInRange == 1) {
584331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner    if (CharStart != CommonString.size()) {
585331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner      OS << std::string(Indent*2, ' ') << "if (!memcmp(BuiltinName";
586331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner      if (CharStart) OS << "+" << CharStart;
587331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner      OS << ", \"" << (CommonString.c_str()+CharStart) << "\", ";
588331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner      OS << CommonString.size() - CharStart << "))\n";
589331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner      ++Indent;
590331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner    }
59149de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen    OS << std::string(Indent*2, ' ') << "IntrinsicID = " << TargetPrefix
59249de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen       << "Intrinsic::";
593331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner    OS << Start->second << ";\n";
594331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner    return;
595331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner  }
596331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner
597331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner  // At this point, we potentially have a common prefix for these builtins, emit
598331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner  // a check for this common prefix.
599331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner  if (CommonString.size() != CharStart) {
600331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner    OS << std::string(Indent*2, ' ') << "if (!memcmp(BuiltinName";
601331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner    if (CharStart) OS << "+" << CharStart;
602331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner    OS << ", \"" << (CommonString.c_str()+CharStart) << "\", ";
603331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner    OS << CommonString.size()-CharStart << ")) {\n";
604331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner
60549de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen    EmitBuiltinComparisons(Start, End, CommonString.size(), Indent+1,
60649de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen                           TargetPrefix, OS);
607331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner    OS << std::string(Indent*2, ' ') << "}\n";
608331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner    return;
609331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner  }
610331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner
611331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner  // Output a switch on the character that differs across the set.
612331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner  OS << std::string(Indent*2, ' ') << "switch (BuiltinName[" << CharStart
613331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner      << "]) {";
614331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner  if (CharStart)
615331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner    OS << "  // \"" << std::string(Start->first.begin(),
616331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner                                   Start->first.begin()+CharStart) << "\"";
617331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner  OS << "\n";
618331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner
619331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner  for (StrMapIterator I = Start; I != End; ) {
620331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner    char ThisChar = I->first[CharStart];
621331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner    OS << std::string(Indent*2, ' ') << "case '" << ThisChar << "':\n";
622331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner    // Figure out the range that has this common character.
623331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner    StrMapIterator NextChar = I;
624331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner    for (++NextChar; NextChar != End && NextChar->first[CharStart] == ThisChar;
625331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner         ++NextChar)
626331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner      /*empty*/;
62749de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen    EmitBuiltinComparisons(I, NextChar, CharStart+1, Indent+1, TargetPrefix,OS);
628331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner    OS << std::string(Indent*2, ' ') << "  break;\n";
629331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner    I = NextChar;
630331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner  }
631331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner  OS << std::string(Indent*2, ' ') << "}\n";
632331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner}
633331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner
634331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner/// EmitTargetBuiltins - All of the builtins in the specified map are for the
635331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner/// same target, and we already checked it.
636331bf92fb51f058672144681b3d0e67d30f5699fChris Lattnerstatic void EmitTargetBuiltins(const std::map<std::string, std::string> &BIM,
63749de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen                               const std::string &TargetPrefix,
638331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner                               std::ostream &OS) {
639331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner  // Rearrange the builtins by length.
640331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner  std::vector<std::map<std::string, std::string> > BuiltinsByLen;
641331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner  BuiltinsByLen.reserve(100);
642331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner
643331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner  for (StrMapIterator I = BIM.begin(), E = BIM.end(); I != E; ++I) {
644331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner    if (I->first.size() >= BuiltinsByLen.size())
645331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner      BuiltinsByLen.resize(I->first.size()+1);
646331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner    BuiltinsByLen[I->first.size()].insert(*I);
647331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner  }
648331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner
649331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner  // Now that we have all the builtins by their length, emit a switch stmt.
650331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner  OS << "    switch (strlen(BuiltinName)) {\n";
651331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner  OS << "    default: break;\n";
652331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner  for (unsigned i = 0, e = BuiltinsByLen.size(); i != e; ++i) {
653331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner    if (BuiltinsByLen[i].empty()) continue;
654331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner    OS << "    case " << i << ":\n";
655331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner    EmitBuiltinComparisons(BuiltinsByLen[i].begin(), BuiltinsByLen[i].end(),
65649de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen                           0, 3, TargetPrefix, OS);
657331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner    OS << "      break;\n";
658331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner  }
659331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner  OS << "    }\n";
660331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner}
661331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner
662331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner
6633f8b8913bc9cb232871445eefa8654caf7f9986fChris Lattnervoid IntrinsicEmitter::
6643f8b8913bc9cb232871445eefa8654caf7f9986fChris LattnerEmitIntrinsicToGCCBuiltinMap(const std::vector<CodeGenIntrinsic> &Ints,
6653f8b8913bc9cb232871445eefa8654caf7f9986fChris Lattner                             std::ostream &OS) {
666fa0fba1c546091c485e5513eadeef181dda370abChris Lattner  typedef std::map<std::string, std::map<std::string, std::string> > BIMTy;
6673f8b8913bc9cb232871445eefa8654caf7f9986fChris Lattner  BIMTy BuiltinMap;
6683f8b8913bc9cb232871445eefa8654caf7f9986fChris Lattner  for (unsigned i = 0, e = Ints.size(); i != e; ++i) {
6693f8b8913bc9cb232871445eefa8654caf7f9986fChris Lattner    if (!Ints[i].GCCBuiltinName.empty()) {
670fa0fba1c546091c485e5513eadeef181dda370abChris Lattner      // Get the map for this target prefix.
671fa0fba1c546091c485e5513eadeef181dda370abChris Lattner      std::map<std::string, std::string> &BIM =BuiltinMap[Ints[i].TargetPrefix];
672fa0fba1c546091c485e5513eadeef181dda370abChris Lattner
673fa0fba1c546091c485e5513eadeef181dda370abChris Lattner      if (!BIM.insert(std::make_pair(Ints[i].GCCBuiltinName,
674fa0fba1c546091c485e5513eadeef181dda370abChris Lattner                                     Ints[i].EnumName)).second)
6753f8b8913bc9cb232871445eefa8654caf7f9986fChris Lattner        throw "Intrinsic '" + Ints[i].TheDef->getName() +
6763f8b8913bc9cb232871445eefa8654caf7f9986fChris Lattner              "': duplicate GCC builtin name!";
6773f8b8913bc9cb232871445eefa8654caf7f9986fChris Lattner    }
6783f8b8913bc9cb232871445eefa8654caf7f9986fChris Lattner  }
6793f8b8913bc9cb232871445eefa8654caf7f9986fChris Lattner
6803f8b8913bc9cb232871445eefa8654caf7f9986fChris Lattner  OS << "// Get the LLVM intrinsic that corresponds to a GCC builtin.\n";
6813f8b8913bc9cb232871445eefa8654caf7f9986fChris Lattner  OS << "// This is used by the C front-end.  The GCC builtin name is passed\n";
6823f8b8913bc9cb232871445eefa8654caf7f9986fChris Lattner  OS << "// in as BuiltinName, and a target prefix (e.g. 'ppc') is passed\n";
6833f8b8913bc9cb232871445eefa8654caf7f9986fChris Lattner  OS << "// in as TargetPrefix.  The result is assigned to 'IntrinsicID'.\n";
6843f8b8913bc9cb232871445eefa8654caf7f9986fChris Lattner  OS << "#ifdef GET_LLVM_INTRINSIC_FOR_GCC_BUILTIN\n";
68549de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen
68649de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen  if (TargetOnly) {
68749de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen    OS << "static " << TargetPrefix << "Intrinsic::ID "
68849de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen       << "getIntrinsicForGCCBuiltin(const char "
68949de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen       << "*TargetPrefix, const char *BuiltinName) {\n";
69049de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen    OS << "  " << TargetPrefix << "Intrinsic::ID IntrinsicID = ";
69149de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen  } else {
69249de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen    OS << "Intrinsic::ID Intrinsic::getIntrinsicForGCCBuiltin(const char "
69349de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen       << "*TargetPrefix, const char *BuiltinName) {\n";
69449de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen    OS << "  Intrinsic::ID IntrinsicID = ";
69549de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen  }
69649de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen
69749de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen  if (TargetOnly)
69849de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen    OS << "(" << TargetPrefix<< "Intrinsic::ID)";
69949de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen
70049de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen  OS << "Intrinsic::not_intrinsic;\n";
701331bf92fb51f058672144681b3d0e67d30f5699fChris Lattner
7023f8b8913bc9cb232871445eefa8654caf7f9986fChris Lattner  // Note: this could emit significantly better code if we cared.
7033f8b8913bc9cb232871445eefa8654caf7f9986fChris Lattner  for (BIMTy::iterator I = BuiltinMap.begin(), E = BuiltinMap.end();I != E;++I){
704fa0fba1c546091c485e5513eadeef181dda370abChris Lattner    OS << "  ";
705fa0fba1c546091c485e5513eadeef181dda370abChris Lattner    if (!I->first.empty())
706fa0fba1c546091c485e5513eadeef181dda370abChris Lattner      OS << "if (!strcmp(TargetPrefix, \"" << I->first << "\")) ";
707fa0fba1c546091c485e5513eadeef181dda370abChris Lattner    else
708fa0fba1c546091c485e5513eadeef181dda370abChris Lattner      OS << "/* Target Independent Builtins */ ";
709fa0fba1c546091c485e5513eadeef181dda370abChris Lattner    OS << "{\n";
710fa0fba1c546091c485e5513eadeef181dda370abChris Lattner
711fa0fba1c546091c485e5513eadeef181dda370abChris Lattner    // Emit the comparisons for this target prefix.
71249de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen    EmitTargetBuiltins(I->second, TargetPrefix, OS);
713fa0fba1c546091c485e5513eadeef181dda370abChris Lattner    OS << "  }\n";
7143f8b8913bc9cb232871445eefa8654caf7f9986fChris Lattner  }
71549de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen  OS << "  return IntrinsicID;\n";
71649de98214b82fefeb8f16efbf8cdd8813a85469bDale Johannesen  OS << "}\n";
7173f8b8913bc9cb232871445eefa8654caf7f9986fChris Lattner  OS << "#endif\n\n";
7183f8b8913bc9cb232871445eefa8654caf7f9986fChris Lattner}
719