1193323Sed//===- CodeGenTarget.cpp - CodeGen Target Class Wrapper -------------------===//
2193323Sed//
3193323Sed//                     The LLVM Compiler Infrastructure
4193323Sed//
5193323Sed// This file is distributed under the University of Illinois Open Source
6193323Sed// License. See LICENSE.TXT for details.
7193323Sed//
8193323Sed//===----------------------------------------------------------------------===//
9193323Sed//
10193323Sed// This class wraps target description classes used by the various code
11193323Sed// generation TableGen backends.  This makes it easier to access the data and
12193323Sed// provides a single place that needs to check it for validity.  All of these
13245431Sdim// classes abort on error conditions.
14193323Sed//
15193323Sed//===----------------------------------------------------------------------===//
16193323Sed
17193323Sed#include "CodeGenTarget.h"
18193323Sed#include "CodeGenIntrinsics.h"
19245431Sdim#include "CodeGenSchedule.h"
20252723Sdim#include "llvm/ADT/STLExtras.h"
21252723Sdim#include "llvm/ADT/StringExtras.h"
22252723Sdim#include "llvm/Support/CommandLine.h"
23245431Sdim#include "llvm/TableGen/Error.h"
24226890Sdim#include "llvm/TableGen/Record.h"
25193323Sed#include <algorithm>
26193323Sedusing namespace llvm;
27193323Sed
28193323Sedstatic cl::opt<unsigned>
29198090SrdivackyAsmParserNum("asmparsernum", cl::init(0),
30198090Srdivacky             cl::desc("Make -gen-asm-parser emit assembly parser #N"));
31198090Srdivacky
32198090Srdivackystatic cl::opt<unsigned>
33193323SedAsmWriterNum("asmwriternum", cl::init(0),
34193323Sed             cl::desc("Make -gen-asm-writer emit assembly writer #N"));
35193323Sed
36193323Sed/// getValueType - Return the MVT::SimpleValueType that the specified TableGen
37193323Sed/// record corresponds to.
38193323SedMVT::SimpleValueType llvm::getValueType(Record *Rec) {
39193323Sed  return (MVT::SimpleValueType)Rec->getValueAsInt("Value");
40193323Sed}
41193323Sed
42193323Sedstd::string llvm::getName(MVT::SimpleValueType T) {
43193323Sed  switch (T) {
44198090Srdivacky  case MVT::Other:   return "UNKNOWN";
45198090Srdivacky  case MVT::iPTR:    return "TLI.getPointerTy()";
46198090Srdivacky  case MVT::iPTRAny: return "TLI.getPointerTy()";
47198090Srdivacky  default: return getEnumName(T);
48193323Sed  }
49193323Sed}
50193323Sed
51193323Sedstd::string llvm::getEnumName(MVT::SimpleValueType T) {
52193323Sed  switch (T) {
53218893Sdim  case MVT::Other:    return "MVT::Other";
54218893Sdim  case MVT::i1:       return "MVT::i1";
55218893Sdim  case MVT::i8:       return "MVT::i8";
56218893Sdim  case MVT::i16:      return "MVT::i16";
57218893Sdim  case MVT::i32:      return "MVT::i32";
58218893Sdim  case MVT::i64:      return "MVT::i64";
59218893Sdim  case MVT::i128:     return "MVT::i128";
60218893Sdim  case MVT::iAny:     return "MVT::iAny";
61218893Sdim  case MVT::fAny:     return "MVT::fAny";
62218893Sdim  case MVT::vAny:     return "MVT::vAny";
63235633Sdim  case MVT::f16:      return "MVT::f16";
64218893Sdim  case MVT::f32:      return "MVT::f32";
65218893Sdim  case MVT::f64:      return "MVT::f64";
66218893Sdim  case MVT::f80:      return "MVT::f80";
67218893Sdim  case MVT::f128:     return "MVT::f128";
68193323Sed  case MVT::ppcf128:  return "MVT::ppcf128";
69218893Sdim  case MVT::x86mmx:   return "MVT::x86mmx";
70218893Sdim  case MVT::Glue:     return "MVT::Glue";
71218893Sdim  case MVT::isVoid:   return "MVT::isVoid";
72245431Sdim  case MVT::v2i1:     return "MVT::v2i1";
73245431Sdim  case MVT::v4i1:     return "MVT::v4i1";
74245431Sdim  case MVT::v8i1:     return "MVT::v8i1";
75245431Sdim  case MVT::v16i1:    return "MVT::v16i1";
76252723Sdim  case MVT::v32i1:    return "MVT::v32i1";
77252723Sdim  case MVT::v64i1:    return "MVT::v64i1";
78263509Sdim  case MVT::v1i8:     return "MVT::v1i8";
79218893Sdim  case MVT::v2i8:     return "MVT::v2i8";
80218893Sdim  case MVT::v4i8:     return "MVT::v4i8";
81218893Sdim  case MVT::v8i8:     return "MVT::v8i8";
82218893Sdim  case MVT::v16i8:    return "MVT::v16i8";
83218893Sdim  case MVT::v32i8:    return "MVT::v32i8";
84252723Sdim  case MVT::v64i8:    return "MVT::v64i8";
85245431Sdim  case MVT::v1i16:    return "MVT::v1i16";
86218893Sdim  case MVT::v2i16:    return "MVT::v2i16";
87218893Sdim  case MVT::v4i16:    return "MVT::v4i16";
88218893Sdim  case MVT::v8i16:    return "MVT::v8i16";
89218893Sdim  case MVT::v16i16:   return "MVT::v16i16";
90252723Sdim  case MVT::v32i16:   return "MVT::v32i16";
91245431Sdim  case MVT::v1i32:    return "MVT::v1i32";
92218893Sdim  case MVT::v2i32:    return "MVT::v2i32";
93218893Sdim  case MVT::v4i32:    return "MVT::v4i32";
94218893Sdim  case MVT::v8i32:    return "MVT::v8i32";
95245431Sdim  case MVT::v16i32:   return "MVT::v16i32";
96218893Sdim  case MVT::v1i64:    return "MVT::v1i64";
97218893Sdim  case MVT::v2i64:    return "MVT::v2i64";
98218893Sdim  case MVT::v4i64:    return "MVT::v4i64";
99218893Sdim  case MVT::v8i64:    return "MVT::v8i64";
100245431Sdim  case MVT::v16i64:   return "MVT::v16i64";
101235633Sdim  case MVT::v2f16:    return "MVT::v2f16";
102263509Sdim  case MVT::v4f16:    return "MVT::v4f16";
103263509Sdim  case MVT::v8f16:    return "MVT::v8f16";
104263509Sdim  case MVT::v1f32:    return "MVT::v1f32";
105218893Sdim  case MVT::v2f32:    return "MVT::v2f32";
106218893Sdim  case MVT::v4f32:    return "MVT::v4f32";
107218893Sdim  case MVT::v8f32:    return "MVT::v8f32";
108252723Sdim  case MVT::v16f32:   return "MVT::v16f32";
109263509Sdim  case MVT::v1f64:    return "MVT::v1f64";
110218893Sdim  case MVT::v2f64:    return "MVT::v2f64";
111218893Sdim  case MVT::v4f64:    return "MVT::v4f64";
112252723Sdim  case MVT::v8f64:    return "MVT::v8f64";
113198090Srdivacky  case MVT::Metadata: return "MVT::Metadata";
114218893Sdim  case MVT::iPTR:     return "MVT::iPTR";
115193323Sed  case MVT::iPTRAny:  return "MVT::iPTRAny";
116235633Sdim  case MVT::Untyped:  return "MVT::Untyped";
117235633Sdim  default: llvm_unreachable("ILLEGAL VALUE TYPE!");
118193323Sed  }
119193323Sed}
120193323Sed
121193323Sed/// getQualifiedName - Return the name of the specified record, with a
122193323Sed/// namespace qualifier if the record contains one.
123193323Sed///
124193323Sedstd::string llvm::getQualifiedName(const Record *R) {
125223017Sdim  std::string Namespace;
126223017Sdim  if (R->getValue("Namespace"))
127223017Sdim     Namespace = R->getValueAsString("Namespace");
128193323Sed  if (Namespace.empty()) return R->getName();
129193323Sed  return Namespace + "::" + R->getName();
130193323Sed}
131193323Sed
132193323Sed
133193323Sed/// getTarget - Return the current instance of the Target class.
134193323Sed///
135223017SdimCodeGenTarget::CodeGenTarget(RecordKeeper &records)
136245431Sdim  : Records(records), RegBank(0), SchedModels(0) {
137193323Sed  std::vector<Record*> Targets = Records.getAllDerivedDefinitions("Target");
138193323Sed  if (Targets.size() == 0)
139245431Sdim    PrintFatalError("ERROR: No 'Target' subclasses defined!");
140193323Sed  if (Targets.size() != 1)
141245431Sdim    PrintFatalError("ERROR: Multiple subclasses of Target defined!");
142193323Sed  TargetRec = Targets[0];
143193323Sed}
144193323Sed
145245431SdimCodeGenTarget::~CodeGenTarget() {
146245431Sdim  delete RegBank;
147245431Sdim  delete SchedModels;
148245431Sdim}
149193323Sed
150193323Sedconst std::string &CodeGenTarget::getName() const {
151193323Sed  return TargetRec->getName();
152193323Sed}
153193323Sed
154193323Sedstd::string CodeGenTarget::getInstNamespace() const {
155193323Sed  for (inst_iterator i = inst_begin(), e = inst_end(); i != e; ++i) {
156205407Srdivacky    // Make sure not to pick up "TargetOpcode" by accidentally getting
157193323Sed    // the namespace off the PHI instruction or something.
158205407Srdivacky    if ((*i)->Namespace != "TargetOpcode")
159205407Srdivacky      return (*i)->Namespace;
160193323Sed  }
161193323Sed
162205407Srdivacky  return "";
163193323Sed}
164193323Sed
165193323SedRecord *CodeGenTarget::getInstructionSet() const {
166193323Sed  return TargetRec->getValueAsDef("InstructionSet");
167193323Sed}
168193323Sed
169205407Srdivacky
170198090Srdivacky/// getAsmParser - Return the AssemblyParser definition for this target.
171198090Srdivacky///
172198090SrdivackyRecord *CodeGenTarget::getAsmParser() const {
173198090Srdivacky  std::vector<Record*> LI = TargetRec->getValueAsListOfDefs("AssemblyParsers");
174198090Srdivacky  if (AsmParserNum >= LI.size())
175245431Sdim    PrintFatalError("Target does not have an AsmParser #" + utostr(AsmParserNum) + "!");
176198090Srdivacky  return LI[AsmParserNum];
177198090Srdivacky}
178198090Srdivacky
179235633Sdim/// getAsmParserVariant - Return the AssmblyParserVariant definition for
180235633Sdim/// this target.
181235633Sdim///
182235633SdimRecord *CodeGenTarget::getAsmParserVariant(unsigned i) const {
183245431Sdim  std::vector<Record*> LI =
184235633Sdim    TargetRec->getValueAsListOfDefs("AssemblyParserVariants");
185235633Sdim  if (i >= LI.size())
186245431Sdim    PrintFatalError("Target does not have an AsmParserVariant #" + utostr(i) + "!");
187235633Sdim  return LI[i];
188235633Sdim}
189235633Sdim
190245431Sdim/// getAsmParserVariantCount - Return the AssmblyParserVariant definition
191235633Sdim/// available for this target.
192235633Sdim///
193235633Sdimunsigned CodeGenTarget::getAsmParserVariantCount() const {
194245431Sdim  std::vector<Record*> LI =
195235633Sdim    TargetRec->getValueAsListOfDefs("AssemblyParserVariants");
196235633Sdim  return LI.size();
197235633Sdim}
198235633Sdim
199193323Sed/// getAsmWriter - Return the AssemblyWriter definition for this target.
200193323Sed///
201193323SedRecord *CodeGenTarget::getAsmWriter() const {
202193323Sed  std::vector<Record*> LI = TargetRec->getValueAsListOfDefs("AssemblyWriters");
203193323Sed  if (AsmWriterNum >= LI.size())
204245431Sdim    PrintFatalError("Target does not have an AsmWriter #" + utostr(AsmWriterNum) + "!");
205193323Sed  return LI[AsmWriterNum];
206193323Sed}
207193323Sed
208223017SdimCodeGenRegBank &CodeGenTarget::getRegBank() const {
209223017Sdim  if (!RegBank)
210223017Sdim    RegBank = new CodeGenRegBank(Records);
211223017Sdim  return *RegBank;
212193323Sed}
213193323Sed
214224145Sdimvoid CodeGenTarget::ReadRegAltNameIndices() const {
215224145Sdim  RegAltNameIndices = Records.getAllDerivedDefinitions("RegAltNameIndex");
216224145Sdim  std::sort(RegAltNameIndices.begin(), RegAltNameIndices.end(), LessRecord());
217193323Sed}
218193323Sed
219218893Sdim/// getRegisterByName - If there is a register with the specific AsmName,
220218893Sdim/// return it.
221218893Sdimconst CodeGenRegister *CodeGenTarget::getRegisterByName(StringRef Name) const {
222245431Sdim  const StringMap<CodeGenRegister*> &Regs = getRegBank().getRegistersByName();
223245431Sdim  StringMap<CodeGenRegister*>::const_iterator I = Regs.find(Name);
224245431Sdim  if (I == Regs.end())
225245431Sdim    return 0;
226245431Sdim  return I->second;
227218893Sdim}
228218893Sdim
229205218Srdivackystd::vector<MVT::SimpleValueType> CodeGenTarget::
230205218SrdivackygetRegisterVTs(Record *R) const {
231224145Sdim  const CodeGenRegister *Reg = getRegBank().getReg(R);
232205218Srdivacky  std::vector<MVT::SimpleValueType> Result;
233226890Sdim  ArrayRef<CodeGenRegisterClass*> RCs = getRegBank().getRegClasses();
234193323Sed  for (unsigned i = 0, e = RCs.size(); i != e; ++i) {
235226890Sdim    const CodeGenRegisterClass &RC = *RCs[i];
236224145Sdim    if (RC.contains(Reg)) {
237252723Sdim      ArrayRef<MVT::SimpleValueType> InVTs = RC.getValueTypes();
238224145Sdim      Result.insert(Result.end(), InVTs.begin(), InVTs.end());
239193323Sed    }
240193323Sed  }
241221345Sdim
242206083Srdivacky  // Remove duplicates.
243206083Srdivacky  array_pod_sort(Result.begin(), Result.end());
244206083Srdivacky  Result.erase(std::unique(Result.begin(), Result.end()), Result.end());
245193323Sed  return Result;
246193323Sed}
247193323Sed
248193323Sed
249193323Sedvoid CodeGenTarget::ReadLegalValueTypes() const {
250226890Sdim  ArrayRef<CodeGenRegisterClass*> RCs = getRegBank().getRegClasses();
251193323Sed  for (unsigned i = 0, e = RCs.size(); i != e; ++i)
252226890Sdim    for (unsigned ri = 0, re = RCs[i]->VTs.size(); ri != re; ++ri)
253226890Sdim      LegalValueTypes.push_back(RCs[i]->VTs[ri]);
254221345Sdim
255193323Sed  // Remove duplicates.
256193323Sed  std::sort(LegalValueTypes.begin(), LegalValueTypes.end());
257193323Sed  LegalValueTypes.erase(std::unique(LegalValueTypes.begin(),
258193323Sed                                    LegalValueTypes.end()),
259193323Sed                        LegalValueTypes.end());
260193323Sed}
261193323Sed
262245431SdimCodeGenSchedModels &CodeGenTarget::getSchedModels() const {
263245431Sdim  if (!SchedModels)
264245431Sdim    SchedModels = new CodeGenSchedModels(Records, *this);
265245431Sdim  return *SchedModels;
266245431Sdim}
267193323Sed
268193323Sedvoid CodeGenTarget::ReadInstructions() const {
269193323Sed  std::vector<Record*> Insts = Records.getAllDerivedDefinitions("Instruction");
270193323Sed  if (Insts.size() <= 2)
271245431Sdim    PrintFatalError("No 'Instruction' subclasses defined!");
272193323Sed
273193323Sed  // Parse the instructions defined in the .td file.
274218893Sdim  for (unsigned i = 0, e = Insts.size(); i != e; ++i)
275218893Sdim    Instructions[Insts[i]] = new CodeGenInstruction(Insts[i]);
276193323Sed}
277193323Sed
278205407Srdivackystatic const CodeGenInstruction *
279205407SrdivackyGetInstByName(const char *Name,
280221345Sdim              const DenseMap<const Record*, CodeGenInstruction*> &Insts,
281218893Sdim              RecordKeeper &Records) {
282205407Srdivacky  const Record *Rec = Records.getDef(Name);
283221345Sdim
284205407Srdivacky  DenseMap<const Record*, CodeGenInstruction*>::const_iterator
285205407Srdivacky    I = Insts.find(Rec);
286205407Srdivacky  if (Rec == 0 || I == Insts.end())
287245431Sdim    PrintFatalError(std::string("Could not find '") + Name + "' instruction!");
288205407Srdivacky  return I->second;
289205407Srdivacky}
290205407Srdivacky
291205407Srdivackynamespace {
292205407Srdivacky/// SortInstByName - Sorting predicate to sort instructions by name.
293205407Srdivacky///
294205407Srdivackystruct SortInstByName {
295205407Srdivacky  bool operator()(const CodeGenInstruction *Rec1,
296205407Srdivacky                  const CodeGenInstruction *Rec2) const {
297205407Srdivacky    return Rec1->TheDef->getName() < Rec2->TheDef->getName();
298205407Srdivacky  }
299205407Srdivacky};
300205407Srdivacky}
301205407Srdivacky
302193323Sed/// getInstructionsByEnumValue - Return all of the instructions defined by the
303193323Sed/// target, ordered by their enum value.
304205407Srdivackyvoid CodeGenTarget::ComputeInstrsByEnum() const {
305210299Sed  // The ordering here must match the ordering in TargetOpcodes.h.
306263509Sdim  static const char *const FixedInstrs[] = {
307210299Sed    "PHI",
308210299Sed    "INLINEASM",
309212904Sdim    "PROLOG_LABEL",
310210299Sed    "EH_LABEL",
311210299Sed    "GC_LABEL",
312210299Sed    "KILL",
313210299Sed    "EXTRACT_SUBREG",
314210299Sed    "INSERT_SUBREG",
315210299Sed    "IMPLICIT_DEF",
316210299Sed    "SUBREG_TO_REG",
317210299Sed    "COPY_TO_REGCLASS",
318210299Sed    "DBG_VALUE",
319210299Sed    "REG_SEQUENCE",
320210299Sed    "COPY",
321235633Sdim    "BUNDLE",
322245431Sdim    "LIFETIME_START",
323245431Sdim    "LIFETIME_END",
324263509Sdim    "STACKMAP",
325263509Sdim    "PATCHPOINT",
326210299Sed    0
327210299Sed  };
328205407Srdivacky  const DenseMap<const Record*, CodeGenInstruction*> &Insts = getInstructions();
329210299Sed  for (const char *const *p = FixedInstrs; *p; ++p) {
330218893Sdim    const CodeGenInstruction *Instr = GetInstByName(*p, Insts, Records);
331210299Sed    assert(Instr && "Missing target independent instruction");
332210299Sed    assert(Instr->Namespace == "TargetOpcode" && "Bad namespace");
333210299Sed    InstrsByEnum.push_back(Instr);
334210299Sed  }
335210299Sed  unsigned EndOfPredefines = InstrsByEnum.size();
336205407Srdivacky
337205407Srdivacky  for (DenseMap<const Record*, CodeGenInstruction*>::const_iterator
338205407Srdivacky       I = Insts.begin(), E = Insts.end(); I != E; ++I) {
339205407Srdivacky    const CodeGenInstruction *CGI = I->second;
340210299Sed    if (CGI->Namespace != "TargetOpcode")
341205407Srdivacky      InstrsByEnum.push_back(CGI);
342205407Srdivacky  }
343210299Sed
344210299Sed  assert(InstrsByEnum.size() == Insts.size() && "Missing predefined instr");
345210299Sed
346205407Srdivacky  // All of the instructions are now in random order based on the map iteration.
347205407Srdivacky  // Sort them by name.
348205407Srdivacky  std::sort(InstrsByEnum.begin()+EndOfPredefines, InstrsByEnum.end(),
349205407Srdivacky            SortInstByName());
350193323Sed}
351193323Sed
352193323Sed
353193323Sed/// isLittleEndianEncoding - Return whether this target encodes its instruction
354193323Sed/// in little-endian format, i.e. bits laid out in the order [0..n]
355193323Sed///
356193323Sedbool CodeGenTarget::isLittleEndianEncoding() const {
357193323Sed  return getInstructionSet()->getValueAsBit("isLittleEndianEncoding");
358193323Sed}
359193323Sed
360245431Sdim/// guessInstructionProperties - Return true if it's OK to guess instruction
361245431Sdim/// properties instead of raising an error.
362245431Sdim///
363245431Sdim/// This is configurable as a temporary migration aid. It will eventually be
364245431Sdim/// permanently false.
365245431Sdimbool CodeGenTarget::guessInstructionProperties() const {
366245431Sdim  return getInstructionSet()->getValueAsBit("guessInstructionProperties");
367245431Sdim}
368245431Sdim
369193323Sed//===----------------------------------------------------------------------===//
370193323Sed// ComplexPattern implementation
371193323Sed//
372193323SedComplexPattern::ComplexPattern(Record *R) {
373193323Sed  Ty          = ::getValueType(R->getValueAsDef("Ty"));
374193323Sed  NumOperands = R->getValueAsInt("NumOperands");
375193323Sed  SelectFunc  = R->getValueAsString("SelectFunc");
376193323Sed  RootNodes   = R->getValueAsListOfDefs("RootNodes");
377193323Sed
378193323Sed  // Parse the properties.
379193323Sed  Properties = 0;
380193323Sed  std::vector<Record*> PropList = R->getValueAsListOfDefs("Properties");
381193323Sed  for (unsigned i = 0, e = PropList.size(); i != e; ++i)
382193323Sed    if (PropList[i]->getName() == "SDNPHasChain") {
383193323Sed      Properties |= 1 << SDNPHasChain;
384218893Sdim    } else if (PropList[i]->getName() == "SDNPOptInGlue") {
385218893Sdim      Properties |= 1 << SDNPOptInGlue;
386193323Sed    } else if (PropList[i]->getName() == "SDNPMayStore") {
387193323Sed      Properties |= 1 << SDNPMayStore;
388193323Sed    } else if (PropList[i]->getName() == "SDNPMayLoad") {
389193323Sed      Properties |= 1 << SDNPMayLoad;
390193323Sed    } else if (PropList[i]->getName() == "SDNPSideEffect") {
391193323Sed      Properties |= 1 << SDNPSideEffect;
392193323Sed    } else if (PropList[i]->getName() == "SDNPMemOperand") {
393193323Sed      Properties |= 1 << SDNPMemOperand;
394205407Srdivacky    } else if (PropList[i]->getName() == "SDNPVariadic") {
395205407Srdivacky      Properties |= 1 << SDNPVariadic;
396218893Sdim    } else if (PropList[i]->getName() == "SDNPWantRoot") {
397218893Sdim      Properties |= 1 << SDNPWantRoot;
398218893Sdim    } else if (PropList[i]->getName() == "SDNPWantParent") {
399218893Sdim      Properties |= 1 << SDNPWantParent;
400193323Sed    } else {
401195340Sed      errs() << "Unsupported SD Node property '" << PropList[i]->getName()
402195340Sed             << "' on ComplexPattern '" << R->getName() << "'!\n";
403193323Sed      exit(1);
404193323Sed    }
405193323Sed}
406193323Sed
407193323Sed//===----------------------------------------------------------------------===//
408193323Sed// CodeGenIntrinsic Implementation
409193323Sed//===----------------------------------------------------------------------===//
410193323Sed
411193323Sedstd::vector<CodeGenIntrinsic> llvm::LoadIntrinsics(const RecordKeeper &RC,
412193323Sed                                                   bool TargetOnly) {
413193323Sed  std::vector<Record*> I = RC.getAllDerivedDefinitions("Intrinsic");
414221345Sdim
415193323Sed  std::vector<CodeGenIntrinsic> Result;
416193323Sed
417193323Sed  for (unsigned i = 0, e = I.size(); i != e; ++i) {
418193323Sed    bool isTarget = I[i]->getValueAsBit("isTarget");
419193323Sed    if (isTarget == TargetOnly)
420193323Sed      Result.push_back(CodeGenIntrinsic(I[i]));
421193323Sed  }
422193323Sed  return Result;
423193323Sed}
424193323Sed
425193323SedCodeGenIntrinsic::CodeGenIntrinsic(Record *R) {
426193323Sed  TheDef = R;
427193323Sed  std::string DefName = R->getName();
428212904Sdim  ModRef = ReadWriteMem;
429193323Sed  isOverloaded = false;
430193323Sed  isCommutative = false;
431223017Sdim  canThrow = false;
432245431Sdim  isNoReturn = false;
433221345Sdim
434221345Sdim  if (DefName.size() <= 4 ||
435193323Sed      std::string(DefName.begin(), DefName.begin() + 4) != "int_")
436245431Sdim    PrintFatalError("Intrinsic '" + DefName + "' does not start with 'int_'!");
437193323Sed
438193323Sed  EnumName = std::string(DefName.begin()+4, DefName.end());
439193323Sed
440193323Sed  if (R->getValue("GCCBuiltinName"))  // Ignore a missing GCCBuiltinName field.
441193323Sed    GCCBuiltinName = R->getValueAsString("GCCBuiltinName");
442193323Sed
443193323Sed  TargetPrefix = R->getValueAsString("TargetPrefix");
444193323Sed  Name = R->getValueAsString("LLVMName");
445193323Sed
446193323Sed  if (Name == "") {
447193323Sed    // If an explicit name isn't specified, derive one from the DefName.
448193323Sed    Name = "llvm.";
449193323Sed
450193323Sed    for (unsigned i = 0, e = EnumName.size(); i != e; ++i)
451193323Sed      Name += (EnumName[i] == '_') ? '.' : EnumName[i];
452193323Sed  } else {
453193323Sed    // Verify it starts with "llvm.".
454221345Sdim    if (Name.size() <= 5 ||
455193323Sed        std::string(Name.begin(), Name.begin() + 5) != "llvm.")
456245431Sdim      PrintFatalError("Intrinsic '" + DefName + "'s name does not start with 'llvm.'!");
457193323Sed  }
458221345Sdim
459193323Sed  // If TargetPrefix is specified, make sure that Name starts with
460193323Sed  // "llvm.<targetprefix>.".
461193323Sed  if (!TargetPrefix.empty()) {
462193323Sed    if (Name.size() < 6+TargetPrefix.size() ||
463193323Sed        std::string(Name.begin() + 5, Name.begin() + 6 + TargetPrefix.size())
464193323Sed        != (TargetPrefix + "."))
465245431Sdim      PrintFatalError("Intrinsic '" + DefName + "' does not start with 'llvm." +
466245431Sdim        TargetPrefix + ".'!");
467193323Sed  }
468221345Sdim
469193323Sed  // Parse the list of return types.
470193323Sed  std::vector<MVT::SimpleValueType> OverloadedVTs;
471193323Sed  ListInit *TypeList = R->getValueAsListInit("RetTypes");
472193323Sed  for (unsigned i = 0, e = TypeList->getSize(); i != e; ++i) {
473193323Sed    Record *TyEl = TypeList->getElementAsRecord(i);
474193323Sed    assert(TyEl->isSubClassOf("LLVMType") && "Expected a type!");
475193323Sed    MVT::SimpleValueType VT;
476193323Sed    if (TyEl->isSubClassOf("LLVMMatchType")) {
477193323Sed      unsigned MatchTy = TyEl->getValueAsInt("Number");
478193323Sed      assert(MatchTy < OverloadedVTs.size() &&
479193323Sed             "Invalid matching number!");
480193323Sed      VT = OverloadedVTs[MatchTy];
481193323Sed      // It only makes sense to use the extended and truncated vector element
482193323Sed      // variants with iAny types; otherwise, if the intrinsic is not
483193323Sed      // overloaded, all the types can be specified directly.
484193323Sed      assert(((!TyEl->isSubClassOf("LLVMExtendedElementVectorType") &&
485193323Sed               !TyEl->isSubClassOf("LLVMTruncatedElementVectorType")) ||
486198090Srdivacky              VT == MVT::iAny || VT == MVT::vAny) &&
487198090Srdivacky             "Expected iAny or vAny type");
488193323Sed    } else {
489193323Sed      VT = getValueType(TyEl->getValueAsDef("VT"));
490193323Sed    }
491198090Srdivacky    if (EVT(VT).isOverloaded()) {
492193323Sed      OverloadedVTs.push_back(VT);
493206083Srdivacky      isOverloaded = true;
494193323Sed    }
495206083Srdivacky
496206083Srdivacky    // Reject invalid types.
497206083Srdivacky    if (VT == MVT::isVoid)
498245431Sdim      PrintFatalError("Intrinsic '" + DefName + " has void in result type list!");
499221345Sdim
500193323Sed    IS.RetVTs.push_back(VT);
501193323Sed    IS.RetTypeDefs.push_back(TyEl);
502193323Sed  }
503221345Sdim
504193323Sed  // Parse the list of parameter types.
505193323Sed  TypeList = R->getValueAsListInit("ParamTypes");
506193323Sed  for (unsigned i = 0, e = TypeList->getSize(); i != e; ++i) {
507193323Sed    Record *TyEl = TypeList->getElementAsRecord(i);
508193323Sed    assert(TyEl->isSubClassOf("LLVMType") && "Expected a type!");
509193323Sed    MVT::SimpleValueType VT;
510193323Sed    if (TyEl->isSubClassOf("LLVMMatchType")) {
511193323Sed      unsigned MatchTy = TyEl->getValueAsInt("Number");
512193323Sed      assert(MatchTy < OverloadedVTs.size() &&
513193323Sed             "Invalid matching number!");
514193323Sed      VT = OverloadedVTs[MatchTy];
515193323Sed      // It only makes sense to use the extended and truncated vector element
516193323Sed      // variants with iAny types; otherwise, if the intrinsic is not
517193323Sed      // overloaded, all the types can be specified directly.
518193323Sed      assert(((!TyEl->isSubClassOf("LLVMExtendedElementVectorType") &&
519193323Sed               !TyEl->isSubClassOf("LLVMTruncatedElementVectorType")) ||
520198090Srdivacky              VT == MVT::iAny || VT == MVT::vAny) &&
521198090Srdivacky             "Expected iAny or vAny type");
522193323Sed    } else
523193323Sed      VT = getValueType(TyEl->getValueAsDef("VT"));
524221345Sdim
525198090Srdivacky    if (EVT(VT).isOverloaded()) {
526193323Sed      OverloadedVTs.push_back(VT);
527206083Srdivacky      isOverloaded = true;
528193323Sed    }
529221345Sdim
530206083Srdivacky    // Reject invalid types.
531206083Srdivacky    if (VT == MVT::isVoid && i != e-1 /*void at end means varargs*/)
532245431Sdim      PrintFatalError("Intrinsic '" + DefName + " has void in result type list!");
533221345Sdim
534193323Sed    IS.ParamVTs.push_back(VT);
535193323Sed    IS.ParamTypeDefs.push_back(TyEl);
536193323Sed  }
537193323Sed
538193323Sed  // Parse the intrinsic properties.
539193323Sed  ListInit *PropList = R->getValueAsListInit("Properties");
540193323Sed  for (unsigned i = 0, e = PropList->getSize(); i != e; ++i) {
541193323Sed    Record *Property = PropList->getElementAsRecord(i);
542193323Sed    assert(Property->isSubClassOf("IntrinsicProperty") &&
543193323Sed           "Expected a property!");
544221345Sdim
545193323Sed    if (Property->getName() == "IntrNoMem")
546193323Sed      ModRef = NoMem;
547193323Sed    else if (Property->getName() == "IntrReadArgMem")
548193323Sed      ModRef = ReadArgMem;
549193323Sed    else if (Property->getName() == "IntrReadMem")
550193323Sed      ModRef = ReadMem;
551212904Sdim    else if (Property->getName() == "IntrReadWriteArgMem")
552212904Sdim      ModRef = ReadWriteArgMem;
553193323Sed    else if (Property->getName() == "Commutative")
554193323Sed      isCommutative = true;
555223017Sdim    else if (Property->getName() == "Throws")
556223017Sdim      canThrow = true;
557245431Sdim    else if (Property->getName() == "IntrNoReturn")
558245431Sdim      isNoReturn = true;
559193323Sed    else if (Property->isSubClassOf("NoCapture")) {
560193323Sed      unsigned ArgNo = Property->getValueAsInt("ArgNo");
561193323Sed      ArgumentAttributes.push_back(std::make_pair(ArgNo, NoCapture));
562263509Sdim    } else if (Property->isSubClassOf("ReadOnly")) {
563263509Sdim      unsigned ArgNo = Property->getValueAsInt("ArgNo");
564263509Sdim      ArgumentAttributes.push_back(std::make_pair(ArgNo, ReadOnly));
565263509Sdim    } else if (Property->isSubClassOf("ReadNone")) {
566263509Sdim      unsigned ArgNo = Property->getValueAsInt("ArgNo");
567263509Sdim      ArgumentAttributes.push_back(std::make_pair(ArgNo, ReadNone));
568193323Sed    } else
569235633Sdim      llvm_unreachable("Unknown property!");
570193323Sed  }
571223017Sdim
572223017Sdim  // Sort the argument attributes for later benefit.
573223017Sdim  std::sort(ArgumentAttributes.begin(), ArgumentAttributes.end());
574193323Sed}
575