mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-27 13:30:05 +00:00
Write llvm-tblgen backends as functions instead of sub-classes.
The TableGenBackend base class doesn't do much, and will be removed completely soon. Patch by Sean Silva! git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@158311 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
20aedcdfa3
commit
6f36fa981a
@ -38,6 +38,10 @@ public: // Useful helper routines...
|
||||
|
||||
};
|
||||
|
||||
/// emitSourceFileHeader - Output a LLVM style file header to the specified
|
||||
/// ostream.
|
||||
void emitSourceFileHeader(StringRef Desc, raw_ostream &OS);
|
||||
|
||||
} // End llvm namespace
|
||||
|
||||
#endif
|
||||
|
@ -19,9 +19,12 @@ void TableGenBackend::anchor() { }
|
||||
|
||||
void TableGenBackend::EmitSourceFileHeader(StringRef Desc,
|
||||
raw_ostream &OS) const {
|
||||
emitSourceFileHeader(Desc, OS);
|
||||
}
|
||||
|
||||
void llvm::emitSourceFileHeader(StringRef Desc, raw_ostream &OS) {
|
||||
OS << "//===- TableGen'erated file -------------------------------------*-"
|
||||
" C++ -*-===//\n//\n// " << Desc << "\n//\n// Automatically generate"
|
||||
"d file, do not edit!\n//\n//===------------------------------------"
|
||||
"----------------------------------===//\n\n";
|
||||
}
|
||||
|
||||
|
@ -96,7 +96,6 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "AsmMatcherEmitter.h"
|
||||
#include "CodeGenTarget.h"
|
||||
#include "StringToOffsetTable.h"
|
||||
#include "llvm/ADT/OwningPtr.h"
|
||||
@ -111,6 +110,8 @@
|
||||
#include "llvm/TableGen/Error.h"
|
||||
#include "llvm/TableGen/Record.h"
|
||||
#include "llvm/TableGen/StringMatcher.h"
|
||||
#include "llvm/TableGen/TableGenBackend.h"
|
||||
#include <cassert>
|
||||
#include <map>
|
||||
#include <set>
|
||||
using namespace llvm;
|
||||
@ -123,6 +124,14 @@ namespace {
|
||||
class AsmMatcherInfo;
|
||||
struct SubtargetFeatureInfo;
|
||||
|
||||
class AsmMatcherEmitter {
|
||||
RecordKeeper &Records;
|
||||
public:
|
||||
AsmMatcherEmitter(RecordKeeper &R) : Records(R) {}
|
||||
|
||||
void run(raw_ostream &o);
|
||||
};
|
||||
|
||||
/// ClassInfo - Helper class for storing the information about a particular
|
||||
/// class of operands which can be matched.
|
||||
struct ClassInfo {
|
||||
@ -642,7 +651,7 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
} // End anonymous namespace
|
||||
|
||||
void MatchableInfo::dump() {
|
||||
errs() << TheDef->getName() << " -- " << "flattened:\"" << AsmString <<"\"\n";
|
||||
@ -2353,8 +2362,6 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
|
||||
|
||||
// Write the output.
|
||||
|
||||
EmitSourceFileHeader("Assembly Matcher Source Fragment", OS);
|
||||
|
||||
// Information for the class declaration.
|
||||
OS << "\n#ifdef GET_ASSEMBLER_HEADER\n";
|
||||
OS << "#undef GET_ASSEMBLER_HEADER\n";
|
||||
@ -2659,3 +2666,12 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
|
||||
|
||||
OS << "#endif // GET_MATCHER_IMPLEMENTATION\n\n";
|
||||
}
|
||||
|
||||
namespace llvm {
|
||||
|
||||
void EmitAsmMatcher(RecordKeeper &RK, raw_ostream &OS) {
|
||||
emitSourceFileHeader("Assembly Matcher Source Fragment", OS);
|
||||
AsmMatcherEmitter(RK).run(OS);
|
||||
}
|
||||
|
||||
} // End llvm namespace
|
||||
|
@ -1,31 +0,0 @@
|
||||
//===- AsmMatcherEmitter.h - Generate an assembly matcher -------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This tablegen backend emits a target specifier matcher for converting parsed
|
||||
// assembly operands in the MCInst structures.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef ASMMATCHER_EMITTER_H
|
||||
#define ASMMATCHER_EMITTER_H
|
||||
|
||||
#include "llvm/TableGen/TableGenBackend.h"
|
||||
#include <cassert>
|
||||
|
||||
namespace llvm {
|
||||
class AsmMatcherEmitter : public TableGenBackend {
|
||||
RecordKeeper &Records;
|
||||
public:
|
||||
AsmMatcherEmitter(RecordKeeper &R) : Records(R) {}
|
||||
|
||||
// run - Output the matcher, returning true on failure.
|
||||
void run(raw_ostream &o);
|
||||
};
|
||||
}
|
||||
#endif
|
@ -12,7 +12,6 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "AsmWriterEmitter.h"
|
||||
#include "AsmWriterInst.h"
|
||||
#include "CodeGenTarget.h"
|
||||
#include "StringToOffsetTable.h"
|
||||
@ -22,9 +21,41 @@
|
||||
#include "llvm/Support/MathExtras.h"
|
||||
#include "llvm/TableGen/Error.h"
|
||||
#include "llvm/TableGen/Record.h"
|
||||
#include "llvm/TableGen/TableGenBackend.h"
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
using namespace llvm;
|
||||
|
||||
namespace {
|
||||
class AsmWriterEmitter {
|
||||
RecordKeeper &Records;
|
||||
std::map<const CodeGenInstruction*, AsmWriterInst*> CGIAWIMap;
|
||||
std::vector<const CodeGenInstruction*> NumberedInstructions;
|
||||
public:
|
||||
AsmWriterEmitter(RecordKeeper &R) : Records(R) {}
|
||||
|
||||
void run(raw_ostream &o);
|
||||
|
||||
private:
|
||||
void EmitPrintInstruction(raw_ostream &o);
|
||||
void EmitGetRegisterName(raw_ostream &o);
|
||||
void EmitPrintAliasInstruction(raw_ostream &O);
|
||||
|
||||
AsmWriterInst *getAsmWriterInstByID(unsigned ID) const {
|
||||
assert(ID < NumberedInstructions.size());
|
||||
std::map<const CodeGenInstruction*, AsmWriterInst*>::const_iterator I =
|
||||
CGIAWIMap.find(NumberedInstructions[ID]);
|
||||
assert(I != CGIAWIMap.end() && "Didn't find inst!");
|
||||
return I->second;
|
||||
}
|
||||
void FindUniqueOperandCommands(std::vector<std::string> &UOC,
|
||||
std::vector<unsigned> &InstIdxs,
|
||||
std::vector<unsigned> &InstOpsUsed) const;
|
||||
};
|
||||
} // end anonymous namespace
|
||||
|
||||
static void PrintCases(std::vector<std::pair<std::string,
|
||||
AsmWriterOperand> > &OpsToPrint, raw_ostream &O) {
|
||||
O << " case " << OpsToPrint.back().first << ": ";
|
||||
@ -928,10 +959,17 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) {
|
||||
}
|
||||
|
||||
void AsmWriterEmitter::run(raw_ostream &O) {
|
||||
EmitSourceFileHeader("Assembly Writer Source Fragment", O);
|
||||
|
||||
EmitPrintInstruction(O);
|
||||
EmitGetRegisterName(O);
|
||||
EmitPrintAliasInstruction(O);
|
||||
}
|
||||
|
||||
|
||||
namespace llvm {
|
||||
|
||||
void EmitAsmWriter(RecordKeeper &RK, raw_ostream &OS) {
|
||||
emitSourceFileHeader("Assembly Writer Source Fragment", OS);
|
||||
AsmWriterEmitter(RK).run(OS);
|
||||
}
|
||||
|
||||
} // End llvm namespace
|
||||
|
@ -1,54 +0,0 @@
|
||||
//===- AsmWriterEmitter.h - Generate an assembly writer ---------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This tablegen backend is responsible for emitting an assembly printer for the
|
||||
// code generator.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef ASMWRITER_EMITTER_H
|
||||
#define ASMWRITER_EMITTER_H
|
||||
|
||||
#include "llvm/TableGen/TableGenBackend.h"
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <cassert>
|
||||
|
||||
namespace llvm {
|
||||
class AsmWriterInst;
|
||||
class CodeGenInstruction;
|
||||
|
||||
class AsmWriterEmitter : public TableGenBackend {
|
||||
RecordKeeper &Records;
|
||||
std::map<const CodeGenInstruction*, AsmWriterInst*> CGIAWIMap;
|
||||
std::vector<const CodeGenInstruction*> NumberedInstructions;
|
||||
public:
|
||||
AsmWriterEmitter(RecordKeeper &R) : Records(R) {}
|
||||
|
||||
// run - Output the asmwriter, returning true on failure.
|
||||
void run(raw_ostream &o);
|
||||
|
||||
private:
|
||||
void EmitPrintInstruction(raw_ostream &o);
|
||||
void EmitGetRegisterName(raw_ostream &o);
|
||||
void EmitPrintAliasInstruction(raw_ostream &O);
|
||||
|
||||
AsmWriterInst *getAsmWriterInstByID(unsigned ID) const {
|
||||
assert(ID < NumberedInstructions.size());
|
||||
std::map<const CodeGenInstruction*, AsmWriterInst*>::const_iterator I =
|
||||
CGIAWIMap.find(NumberedInstructions[ID]);
|
||||
assert(I != CGIAWIMap.end() && "Didn't find inst!");
|
||||
return I->second;
|
||||
}
|
||||
void FindUniqueOperandCommands(std::vector<std::string> &UOC,
|
||||
std::vector<unsigned> &InstIdxs,
|
||||
std::vector<unsigned> &InstOpsUsed) const;
|
||||
};
|
||||
}
|
||||
#endif
|
@ -12,13 +12,28 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "CallingConvEmitter.h"
|
||||
#include "CodeGenTarget.h"
|
||||
#include "llvm/TableGen/Record.h"
|
||||
#include "llvm/TableGen/TableGenBackend.h"
|
||||
#include <cassert>
|
||||
using namespace llvm;
|
||||
|
||||
namespace {
|
||||
class CallingConvEmitter {
|
||||
RecordKeeper &Records;
|
||||
public:
|
||||
explicit CallingConvEmitter(RecordKeeper &R) : Records(R) {}
|
||||
|
||||
void run(raw_ostream &o);
|
||||
|
||||
private:
|
||||
void EmitCallingConv(Record *CC, raw_ostream &O);
|
||||
void EmitAction(Record *Action, unsigned Indent, raw_ostream &O);
|
||||
unsigned Counter;
|
||||
};
|
||||
} // End anonymous namespace
|
||||
|
||||
void CallingConvEmitter::run(raw_ostream &O) {
|
||||
EmitSourceFileHeader("Calling Convention Implementation Fragment", O);
|
||||
|
||||
std::vector<Record*> CCs = Records.getAllDerivedDefinitions("CallingConv");
|
||||
|
||||
@ -210,3 +225,12 @@ void CallingConvEmitter::EmitAction(Record *Action,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
namespace llvm {
|
||||
|
||||
void EmitCallingConv(RecordKeeper &RK, raw_ostream &OS) {
|
||||
emitSourceFileHeader("Calling Convention Implementation Fragment", OS);
|
||||
CallingConvEmitter(RK).run(OS);
|
||||
}
|
||||
|
||||
} // End llvm namespace
|
||||
|
@ -1,36 +0,0 @@
|
||||
//===- CallingConvEmitter.h - Generate calling conventions ------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This tablegen backend is responsible for emitting descriptions of the calling
|
||||
// conventions supported by this target.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef CALLINGCONV_EMITTER_H
|
||||
#define CALLINGCONV_EMITTER_H
|
||||
|
||||
#include "llvm/TableGen/TableGenBackend.h"
|
||||
#include <cassert>
|
||||
|
||||
namespace llvm {
|
||||
class CallingConvEmitter : public TableGenBackend {
|
||||
RecordKeeper &Records;
|
||||
public:
|
||||
explicit CallingConvEmitter(RecordKeeper &R) : Records(R) {}
|
||||
|
||||
// run - Output the asmwriter, returning true on failure.
|
||||
void run(raw_ostream &o);
|
||||
|
||||
private:
|
||||
void EmitCallingConv(Record *CC, raw_ostream &O);
|
||||
void EmitAction(Record *Action, unsigned Indent, raw_ostream &O);
|
||||
unsigned Counter;
|
||||
};
|
||||
}
|
||||
#endif
|
@ -13,13 +13,15 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "CodeEmitterGen.h"
|
||||
#include "CodeGenTarget.h"
|
||||
#include "llvm/TableGen/Record.h"
|
||||
#include "llvm/ADT/StringExtras.h"
|
||||
#include "llvm/Support/CommandLine.h"
|
||||
#include "llvm/Support/Debug.h"
|
||||
#include "llvm/TableGen/TableGenBackend.h"
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
using namespace llvm;
|
||||
|
||||
// FIXME: Somewhat hackish to use a command line option for this. There should
|
||||
@ -30,6 +32,27 @@ MCEmitter("mc-emitter",
|
||||
cl::desc("Generate CodeEmitter for use with the MC library."),
|
||||
cl::init(false));
|
||||
|
||||
namespace {
|
||||
|
||||
class CodeEmitterGen {
|
||||
RecordKeeper &Records;
|
||||
public:
|
||||
CodeEmitterGen(RecordKeeper &R) : Records(R) {}
|
||||
|
||||
void run(raw_ostream &o);
|
||||
private:
|
||||
void emitMachineOpEmitter(raw_ostream &o, const std::string &Namespace);
|
||||
void emitGetValueBit(raw_ostream &o, const std::string &Namespace);
|
||||
void reverseBits(std::vector<Record*> &Insts);
|
||||
int getVariableBit(const std::string &VarName, BitsInit *BI, int bit);
|
||||
std::string getInstructionCase(Record *R, CodeGenTarget &Target);
|
||||
void AddCodeToMergeInOperand(Record *R, BitsInit *BI,
|
||||
const std::string &VarName,
|
||||
unsigned &NumberedOp,
|
||||
std::string &Case, CodeGenTarget &Target);
|
||||
|
||||
};
|
||||
|
||||
void CodeEmitterGen::reverseBits(std::vector<Record*> &Insts) {
|
||||
for (std::vector<Record*>::iterator I = Insts.begin(), E = Insts.end();
|
||||
I != E; ++I) {
|
||||
@ -214,7 +237,6 @@ void CodeEmitterGen::run(raw_ostream &o) {
|
||||
// For little-endian instruction bit encodings, reverse the bit order
|
||||
if (Target.isLittleEndianEncoding()) reverseBits(Insts);
|
||||
|
||||
EmitSourceFileHeader("Machine Code Emitter", o);
|
||||
|
||||
const std::vector<const CodeGenInstruction*> &NumberedInstructions =
|
||||
Target.getInstructionsByEnumValue();
|
||||
@ -304,3 +326,14 @@ void CodeEmitterGen::run(raw_ostream &o) {
|
||||
<< " return Value;\n"
|
||||
<< "}\n\n";
|
||||
}
|
||||
|
||||
} // End anonymous namespace
|
||||
|
||||
namespace llvm {
|
||||
|
||||
void EmitCodeEmitter(RecordKeeper &RK, raw_ostream &OS) {
|
||||
emitSourceFileHeader("Machine Code Emitter", OS);
|
||||
CodeEmitterGen(RK).run(OS);
|
||||
}
|
||||
|
||||
} // End llvm namespace
|
||||
|
@ -1,49 +0,0 @@
|
||||
//===- CodeEmitterGen.h - Code Emitter Generator ----------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// FIXME: document
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef CODEMITTERGEN_H
|
||||
#define CODEMITTERGEN_H
|
||||
|
||||
#include "llvm/TableGen/TableGenBackend.h"
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class RecordVal;
|
||||
class BitsInit;
|
||||
class CodeGenTarget;
|
||||
|
||||
class CodeEmitterGen : public TableGenBackend {
|
||||
RecordKeeper &Records;
|
||||
public:
|
||||
CodeEmitterGen(RecordKeeper &R) : Records(R) {}
|
||||
|
||||
// run - Output the code emitter
|
||||
void run(raw_ostream &o);
|
||||
private:
|
||||
void emitMachineOpEmitter(raw_ostream &o, const std::string &Namespace);
|
||||
void emitGetValueBit(raw_ostream &o, const std::string &Namespace);
|
||||
void reverseBits(std::vector<Record*> &Insts);
|
||||
int getVariableBit(const std::string &VarName, BitsInit *BI, int bit);
|
||||
std::string getInstructionCase(Record *R, CodeGenTarget &Target);
|
||||
void
|
||||
AddCodeToMergeInOperand(Record *R, BitsInit *BI, const std::string &VarName,
|
||||
unsigned &NumberedOp,
|
||||
std::string &Case, CodeGenTarget &Target);
|
||||
|
||||
};
|
||||
|
||||
} // End llvm namespace
|
||||
|
||||
#endif
|
@ -11,12 +11,24 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "DAGISelEmitter.h"
|
||||
#include "CodeGenDAGPatterns.h"
|
||||
#include "DAGISelMatcher.h"
|
||||
#include "llvm/TableGen/Record.h"
|
||||
#include "llvm/Support/Debug.h"
|
||||
#include "llvm/TableGen/Record.h"
|
||||
#include "llvm/TableGen/TableGenBackend.h"
|
||||
using namespace llvm;
|
||||
|
||||
namespace {
|
||||
/// DAGISelEmitter - The top-level class which coordinates construction
|
||||
/// and emission of the instruction selector.
|
||||
class DAGISelEmitter {
|
||||
CodeGenDAGPatterns CGP;
|
||||
public:
|
||||
explicit DAGISelEmitter(RecordKeeper &R) : CGP(R) {}
|
||||
void run(raw_ostream &OS);
|
||||
};
|
||||
} // End anonymous namespace
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// DAGISelEmitter Helper methods
|
||||
//
|
||||
@ -104,11 +116,11 @@ struct PatternSortingPredicate {
|
||||
return LHS->ID < RHS->ID;
|
||||
}
|
||||
};
|
||||
}
|
||||
} // End anonymous namespace
|
||||
|
||||
|
||||
void DAGISelEmitter::run(raw_ostream &OS) {
|
||||
EmitSourceFileHeader("DAG Instruction Selector for the " +
|
||||
emitSourceFileHeader("DAG Instruction Selector for the " +
|
||||
CGP.getTargetInfo().getName() + " target", OS);
|
||||
|
||||
OS << "// *** NOTE: This file is #included into the middle of the target\n"
|
||||
@ -153,3 +165,11 @@ void DAGISelEmitter::run(raw_ostream &OS) {
|
||||
EmitMatcherTable(TheMatcher, CGP, OS);
|
||||
delete TheMatcher;
|
||||
}
|
||||
|
||||
namespace llvm {
|
||||
|
||||
void EmitDAGISel(RecordKeeper &RK, raw_ostream &OS) {
|
||||
DAGISelEmitter(RK).run(OS);
|
||||
}
|
||||
|
||||
} // End llvm namespace
|
||||
|
@ -1,36 +0,0 @@
|
||||
//===- DAGISelEmitter.h - Generate an instruction selector ------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This tablegen backend emits a DAG instruction selector.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef DAGISEL_EMITTER_H
|
||||
#define DAGISEL_EMITTER_H
|
||||
|
||||
#include "llvm/TableGen/TableGenBackend.h"
|
||||
#include "CodeGenDAGPatterns.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
/// DAGISelEmitter - The top-level class which coordinates construction
|
||||
/// and emission of the instruction selector.
|
||||
///
|
||||
class DAGISelEmitter : public TableGenBackend {
|
||||
CodeGenDAGPatterns CGP;
|
||||
public:
|
||||
explicit DAGISelEmitter(RecordKeeper &R) : CGP(R) {}
|
||||
|
||||
// run - Output the isel, returning true on failure.
|
||||
void run(raw_ostream &OS);
|
||||
};
|
||||
|
||||
} // End llvm namespace
|
||||
|
||||
#endif
|
@ -15,13 +15,46 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "llvm/TableGen/Record.h"
|
||||
#include "CodeGenTarget.h"
|
||||
#include "DFAPacketizerEmitter.h"
|
||||
#include "llvm/ADT/DenseSet.h"
|
||||
#include "llvm/TableGen/Record.h"
|
||||
#include "llvm/TableGen/TableGenBackend.h"
|
||||
#include <list>
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
using namespace llvm;
|
||||
|
||||
//
|
||||
// class DFAPacketizerEmitter: class that generates and prints out the DFA
|
||||
// for resource tracking.
|
||||
//
|
||||
namespace {
|
||||
class DFAPacketizerEmitter {
|
||||
private:
|
||||
std::string TargetName;
|
||||
//
|
||||
// allInsnClasses is the set of all possible resources consumed by an
|
||||
// InstrStage.
|
||||
//
|
||||
DenseSet<unsigned> allInsnClasses;
|
||||
RecordKeeper &Records;
|
||||
|
||||
public:
|
||||
DFAPacketizerEmitter(RecordKeeper &R);
|
||||
|
||||
//
|
||||
// collectAllInsnClasses: Populate allInsnClasses which is a set of units
|
||||
// used in each stage.
|
||||
//
|
||||
void collectAllInsnClasses(const std::string &Name,
|
||||
Record *ItinData,
|
||||
unsigned &NStages,
|
||||
raw_ostream &OS);
|
||||
|
||||
void run(raw_ostream &OS);
|
||||
};
|
||||
} // End anonymous namespace.
|
||||
|
||||
//
|
||||
//
|
||||
// State represents the usage of machine resources if the packet contains
|
||||
@ -266,7 +299,7 @@ bool DFA::isValidTransition(State *From, unsigned InsnClass) {
|
||||
int State::currentStateNum = 0;
|
||||
int Transition::currentTransitionNum = 0;
|
||||
|
||||
DFAGen::DFAGen(RecordKeeper &R):
|
||||
DFAPacketizerEmitter::DFAPacketizerEmitter(RecordKeeper &R):
|
||||
TargetName(CodeGenTarget(R).getName()),
|
||||
allInsnClasses(), Records(R) {}
|
||||
|
||||
@ -346,7 +379,7 @@ void DFA::writeTableAndAPI(raw_ostream &OS, const std::string &TargetName) {
|
||||
// collectAllInsnClasses - Populate allInsnClasses which is a set of units
|
||||
// used in each stage.
|
||||
//
|
||||
void DFAGen::collectAllInsnClasses(const std::string &Name,
|
||||
void DFAPacketizerEmitter::collectAllInsnClasses(const std::string &Name,
|
||||
Record *ItinData,
|
||||
unsigned &NStages,
|
||||
raw_ostream &OS) {
|
||||
@ -402,8 +435,7 @@ void DFAGen::collectAllInsnClasses(const std::string &Name,
|
||||
//
|
||||
// Run the worklist algorithm to generate the DFA.
|
||||
//
|
||||
void DFAGen::run(raw_ostream &OS) {
|
||||
EmitSourceFileHeader("Target DFA Packetizer Tables", OS);
|
||||
void DFAPacketizerEmitter::run(raw_ostream &OS) {
|
||||
|
||||
// Collect processor iteraries.
|
||||
std::vector<Record*> ProcItinList =
|
||||
@ -510,3 +542,12 @@ void DFAGen::run(raw_ostream &OS) {
|
||||
// Print out the table.
|
||||
D.writeTableAndAPI(OS, TargetName);
|
||||
}
|
||||
|
||||
namespace llvm {
|
||||
|
||||
void EmitDFAPacketizer(RecordKeeper &RK, raw_ostream &OS) {
|
||||
emitSourceFileHeader("Target DFA Packetizer Tables", OS);
|
||||
DFAPacketizerEmitter(RK).run(OS);
|
||||
}
|
||||
|
||||
} // End llvm namespace
|
||||
|
@ -1,52 +0,0 @@
|
||||
//===- DFAPacketizerEmitter.h - Packetization DFA for a VLIW machine-------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This class parses the Schedule.td file and produces an API that can be used
|
||||
// to reason about whether an instruction can be added to a packet on a VLIW
|
||||
// architecture. The class internally generates a deterministic finite
|
||||
// automaton (DFA) that models all possible mappings of machine instructions
|
||||
// to functional units as instructions are added to a packet.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "llvm/ADT/DenseSet.h"
|
||||
#include "llvm/TableGen/TableGenBackend.h"
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
namespace llvm {
|
||||
//
|
||||
// class DFAGen: class that generates and prints out the DFA for resource
|
||||
// tracking.
|
||||
//
|
||||
class DFAGen : public TableGenBackend {
|
||||
private:
|
||||
std::string TargetName;
|
||||
//
|
||||
// allInsnClasses is the set of all possible resources consumed by an
|
||||
// InstrStage.
|
||||
//
|
||||
DenseSet<unsigned> allInsnClasses;
|
||||
RecordKeeper &Records;
|
||||
|
||||
public:
|
||||
DFAGen(RecordKeeper &R);
|
||||
|
||||
//
|
||||
// collectAllInsnClasses: Populate allInsnClasses which is a set of units
|
||||
// used in each stage.
|
||||
//
|
||||
void collectAllInsnClasses(const std::string &Name,
|
||||
Record *ItinData,
|
||||
unsigned &NStages,
|
||||
raw_ostream &OS);
|
||||
|
||||
void run(raw_ostream &OS);
|
||||
};
|
||||
}
|
@ -7,13 +7,12 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "DisassemblerEmitter.h"
|
||||
#include "CodeGenTarget.h"
|
||||
#include "X86DisassemblerTables.h"
|
||||
#include "X86RecognizableInstr.h"
|
||||
#include "FixedLenDecoderEmitter.h"
|
||||
#include "llvm/TableGen/Error.h"
|
||||
#include "llvm/TableGen/Record.h"
|
||||
#include "llvm/TableGen/TableGenBackend.h"
|
||||
|
||||
using namespace llvm;
|
||||
using namespace llvm::X86Disassembler;
|
||||
@ -94,26 +93,27 @@ using namespace llvm::X86Disassembler;
|
||||
/// X86RecognizableInstr.cpp contains the implementation for a single
|
||||
/// instruction.
|
||||
|
||||
void DisassemblerEmitter::run(raw_ostream &OS) {
|
||||
CodeGenTarget Target(Records);
|
||||
namespace llvm {
|
||||
|
||||
OS << "/*===- TableGen'erated file "
|
||||
<< "---------------------------------------*- C -*-===*\n"
|
||||
<< " *\n"
|
||||
<< " * " << Target.getName() << " Disassembler\n"
|
||||
<< " *\n"
|
||||
<< " * Automatically generated file, do not edit!\n"
|
||||
<< " *\n"
|
||||
<< " *===---------------------------------------------------------------"
|
||||
<< "-------===*/\n";
|
||||
extern void EmitFixedLenDecoder(RecordKeeper &RK, raw_ostream &OS,
|
||||
std::string PredicateNamespace,
|
||||
std::string GPrefix,
|
||||
std::string GPostfix,
|
||||
std::string ROK,
|
||||
std::string RFail,
|
||||
std::string L);
|
||||
|
||||
void EmitDisassembler(RecordKeeper &Records, raw_ostream &OS) {
|
||||
CodeGenTarget Target(Records);
|
||||
emitSourceFileHeader(" * " + Target.getName() + " Disassembler", OS);
|
||||
|
||||
// X86 uses a custom disassembler.
|
||||
if (Target.getName() == "X86") {
|
||||
DisassemblerTables Tables;
|
||||
|
||||
|
||||
const std::vector<const CodeGenInstruction*> &numberedInstructions =
|
||||
Target.getInstructionsByEnumValue();
|
||||
|
||||
|
||||
for (unsigned i = 0, e = numberedInstructions.size(); i != e; ++i)
|
||||
RecognizableInstr::processInstr(Tables, *numberedInstructions[i], i);
|
||||
|
||||
@ -130,13 +130,18 @@ void DisassemblerEmitter::run(raw_ostream &OS) {
|
||||
// ARM and Thumb have a CHECK() macro to deal with DecodeStatuses.
|
||||
if (Target.getName() == "ARM" ||
|
||||
Target.getName() == "Thumb") {
|
||||
FixedLenDecoderEmitter(Records,
|
||||
"ARM",
|
||||
"if (!Check(S, ", ")) return MCDisassembler::Fail;",
|
||||
"S", "MCDisassembler::Fail",
|
||||
" MCDisassembler::DecodeStatus S = MCDisassembler::Success;\n(void)S;").run(OS);
|
||||
EmitFixedLenDecoder(Records, OS, "ARM",
|
||||
"if (!Check(S, ", ")) return MCDisassembler::Fail;",
|
||||
"S", "MCDisassembler::Fail",
|
||||
" MCDisassembler::DecodeStatus S = "
|
||||
"MCDisassembler::Success;\n(void)S;");
|
||||
return;
|
||||
}
|
||||
|
||||
FixedLenDecoderEmitter(Records, Target.getName()).run(OS);
|
||||
EmitFixedLenDecoder(Records, OS, Target.getName(),
|
||||
"if (", " == MCDisassembler::Fail)"
|
||||
" return MCDisassembler::Fail;",
|
||||
"MCDisassembler::Success", "MCDisassembler::Fail", "");
|
||||
}
|
||||
|
||||
} // End llvm namespace
|
||||
|
@ -1,28 +0,0 @@
|
||||
//===- DisassemblerEmitter.h - Disassembler Generator -----------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef DISASSEMBLEREMITTER_H
|
||||
#define DISASSEMBLEREMITTER_H
|
||||
|
||||
#include "llvm/TableGen/TableGenBackend.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class DisassemblerEmitter : public TableGenBackend {
|
||||
RecordKeeper &Records;
|
||||
public:
|
||||
DisassemblerEmitter(RecordKeeper &R) : Records(R) {}
|
||||
|
||||
/// run - Output the disassembler.
|
||||
void run(raw_ostream &o);
|
||||
};
|
||||
|
||||
} // end llvm namespace
|
||||
|
||||
#endif
|
@ -13,192 +13,199 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "EDEmitter.h"
|
||||
|
||||
#include "AsmWriterInst.h"
|
||||
#include "CodeGenTarget.h"
|
||||
|
||||
#include "llvm/TableGen/Record.h"
|
||||
#include "llvm/MC/EDInstInfo.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
#include "llvm/Support/Format.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
|
||||
#include "llvm/TableGen/Record.h"
|
||||
#include "llvm/TableGen/TableGenBackend.h"
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
// TODO: There's a suspiciously large amount of "table" data in this
|
||||
// backend which should probably be in the TableGen file itself.
|
||||
|
||||
///////////////////////////////////////////////////////////
|
||||
// Support classes for emitting nested C data structures //
|
||||
///////////////////////////////////////////////////////////
|
||||
|
||||
// TODO: These classes are probably generally useful to other backends;
|
||||
// add them to TableGen's "helper" API's.
|
||||
|
||||
namespace {
|
||||
class EnumEmitter {
|
||||
private:
|
||||
std::string Name;
|
||||
std::vector<std::string> Entries;
|
||||
public:
|
||||
EnumEmitter(const char *N) : Name(N) {
|
||||
}
|
||||
int addEntry(const char *e) {
|
||||
Entries.push_back(std::string(e));
|
||||
return Entries.size() - 1;
|
||||
}
|
||||
void emit(raw_ostream &o, unsigned int &i) {
|
||||
o.indent(i) << "enum " << Name.c_str() << " {" << "\n";
|
||||
i += 2;
|
||||
|
||||
class EnumEmitter {
|
||||
private:
|
||||
std::string Name;
|
||||
std::vector<std::string> Entries;
|
||||
public:
|
||||
EnumEmitter(const char *N) : Name(N) {
|
||||
}
|
||||
int addEntry(const char *e) {
|
||||
Entries.push_back(std::string(e));
|
||||
return Entries.size() - 1;
|
||||
}
|
||||
void emit(raw_ostream &o, unsigned int &i) {
|
||||
o.indent(i) << "enum " << Name.c_str() << " {" << "\n";
|
||||
i += 2;
|
||||
|
||||
unsigned int index = 0;
|
||||
unsigned int numEntries = Entries.size();
|
||||
for (index = 0; index < numEntries; ++index) {
|
||||
o.indent(i) << Entries[index];
|
||||
if (index < (numEntries - 1))
|
||||
o << ",";
|
||||
o << "\n";
|
||||
}
|
||||
|
||||
i -= 2;
|
||||
o.indent(i) << "};" << "\n";
|
||||
unsigned int index = 0;
|
||||
unsigned int numEntries = Entries.size();
|
||||
for (index = 0; index < numEntries; ++index) {
|
||||
o.indent(i) << Entries[index];
|
||||
if (index < (numEntries - 1))
|
||||
o << ",";
|
||||
o << "\n";
|
||||
}
|
||||
|
||||
void emitAsFlags(raw_ostream &o, unsigned int &i) {
|
||||
o.indent(i) << "enum " << Name.c_str() << " {" << "\n";
|
||||
i += 2;
|
||||
i -= 2;
|
||||
o.indent(i) << "};" << "\n";
|
||||
}
|
||||
|
||||
unsigned int index = 0;
|
||||
unsigned int numEntries = Entries.size();
|
||||
unsigned int flag = 1;
|
||||
for (index = 0; index < numEntries; ++index) {
|
||||
o.indent(i) << Entries[index] << " = " << format("0x%x", flag);
|
||||
if (index < (numEntries - 1))
|
||||
o << ",";
|
||||
o << "\n";
|
||||
flag <<= 1;
|
||||
}
|
||||
void emitAsFlags(raw_ostream &o, unsigned int &i) {
|
||||
o.indent(i) << "enum " << Name.c_str() << " {" << "\n";
|
||||
i += 2;
|
||||
|
||||
i -= 2;
|
||||
o.indent(i) << "};" << "\n";
|
||||
unsigned int index = 0;
|
||||
unsigned int numEntries = Entries.size();
|
||||
unsigned int flag = 1;
|
||||
for (index = 0; index < numEntries; ++index) {
|
||||
o.indent(i) << Entries[index] << " = " << format("0x%x", flag);
|
||||
if (index < (numEntries - 1))
|
||||
o << ",";
|
||||
o << "\n";
|
||||
flag <<= 1;
|
||||
}
|
||||
|
||||
i -= 2;
|
||||
o.indent(i) << "};" << "\n";
|
||||
}
|
||||
};
|
||||
} // End anonymous namespace
|
||||
|
||||
namespace {
|
||||
class ConstantEmitter {
|
||||
public:
|
||||
virtual ~ConstantEmitter() { }
|
||||
virtual void emit(raw_ostream &o, unsigned int &i) = 0;
|
||||
};
|
||||
} // End anonymous namespace
|
||||
|
||||
namespace {
|
||||
class LiteralConstantEmitter : public ConstantEmitter {
|
||||
private:
|
||||
bool IsNumber;
|
||||
union {
|
||||
int Number;
|
||||
const char* String;
|
||||
};
|
||||
public:
|
||||
LiteralConstantEmitter(int number = 0) :
|
||||
IsNumber(true),
|
||||
Number(number) {
|
||||
}
|
||||
void set(const char *string) {
|
||||
IsNumber = false;
|
||||
Number = 0;
|
||||
String = string;
|
||||
}
|
||||
bool is(const char *string) {
|
||||
return !strcmp(String, string);
|
||||
}
|
||||
void emit(raw_ostream &o, unsigned int &i) {
|
||||
if (IsNumber)
|
||||
o << Number;
|
||||
else
|
||||
o << String;
|
||||
}
|
||||
};
|
||||
} // End anonymous namespace
|
||||
|
||||
class ConstantEmitter {
|
||||
public:
|
||||
virtual ~ConstantEmitter() { }
|
||||
virtual void emit(raw_ostream &o, unsigned int &i) = 0;
|
||||
};
|
||||
namespace {
|
||||
class CompoundConstantEmitter : public ConstantEmitter {
|
||||
private:
|
||||
unsigned int Padding;
|
||||
std::vector<ConstantEmitter *> Entries;
|
||||
public:
|
||||
CompoundConstantEmitter(unsigned int padding = 0) : Padding(padding) {
|
||||
}
|
||||
CompoundConstantEmitter &addEntry(ConstantEmitter *e) {
|
||||
Entries.push_back(e);
|
||||
|
||||
class LiteralConstantEmitter : public ConstantEmitter {
|
||||
private:
|
||||
bool IsNumber;
|
||||
union {
|
||||
int Number;
|
||||
const char* String;
|
||||
};
|
||||
public:
|
||||
LiteralConstantEmitter(int number = 0) :
|
||||
IsNumber(true),
|
||||
Number(number) {
|
||||
return *this;
|
||||
}
|
||||
~CompoundConstantEmitter() {
|
||||
while (Entries.size()) {
|
||||
ConstantEmitter *entry = Entries.back();
|
||||
Entries.pop_back();
|
||||
delete entry;
|
||||
}
|
||||
void set(const char *string) {
|
||||
IsNumber = false;
|
||||
Number = 0;
|
||||
String = string;
|
||||
}
|
||||
void emit(raw_ostream &o, unsigned int &i) {
|
||||
o << "{" << "\n";
|
||||
i += 2;
|
||||
|
||||
unsigned int index;
|
||||
unsigned int numEntries = Entries.size();
|
||||
|
||||
unsigned int numToPrint;
|
||||
|
||||
if (Padding) {
|
||||
if (numEntries > Padding) {
|
||||
fprintf(stderr, "%u entries but %u padding\n", numEntries, Padding);
|
||||
llvm_unreachable("More entries than padding");
|
||||
}
|
||||
numToPrint = Padding;
|
||||
} else {
|
||||
numToPrint = numEntries;
|
||||
}
|
||||
bool is(const char *string) {
|
||||
return !strcmp(String, string);
|
||||
}
|
||||
void emit(raw_ostream &o, unsigned int &i) {
|
||||
if (IsNumber)
|
||||
o << Number;
|
||||
|
||||
for (index = 0; index < numToPrint; ++index) {
|
||||
o.indent(i);
|
||||
if (index < numEntries)
|
||||
Entries[index]->emit(o, i);
|
||||
else
|
||||
o << String;
|
||||
o << "-1";
|
||||
|
||||
if (index < (numToPrint - 1))
|
||||
o << ",";
|
||||
o << "\n";
|
||||
}
|
||||
};
|
||||
|
||||
class CompoundConstantEmitter : public ConstantEmitter {
|
||||
private:
|
||||
unsigned int Padding;
|
||||
std::vector<ConstantEmitter *> Entries;
|
||||
public:
|
||||
CompoundConstantEmitter(unsigned int padding = 0) : Padding(padding) {
|
||||
i -= 2;
|
||||
o.indent(i) << "}";
|
||||
}
|
||||
};
|
||||
} // End anonymous namespace
|
||||
|
||||
namespace {
|
||||
class FlagsConstantEmitter : public ConstantEmitter {
|
||||
private:
|
||||
std::vector<std::string> Flags;
|
||||
public:
|
||||
FlagsConstantEmitter() {
|
||||
}
|
||||
FlagsConstantEmitter &addEntry(const char *f) {
|
||||
Flags.push_back(std::string(f));
|
||||
return *this;
|
||||
}
|
||||
void emit(raw_ostream &o, unsigned int &i) {
|
||||
unsigned int index;
|
||||
unsigned int numFlags = Flags.size();
|
||||
if (numFlags == 0)
|
||||
o << "0";
|
||||
|
||||
for (index = 0; index < numFlags; ++index) {
|
||||
o << Flags[index].c_str();
|
||||
if (index < (numFlags - 1))
|
||||
o << " | ";
|
||||
}
|
||||
CompoundConstantEmitter &addEntry(ConstantEmitter *e) {
|
||||
Entries.push_back(e);
|
||||
|
||||
return *this;
|
||||
}
|
||||
~CompoundConstantEmitter() {
|
||||
while (Entries.size()) {
|
||||
ConstantEmitter *entry = Entries.back();
|
||||
Entries.pop_back();
|
||||
delete entry;
|
||||
}
|
||||
}
|
||||
void emit(raw_ostream &o, unsigned int &i) {
|
||||
o << "{" << "\n";
|
||||
i += 2;
|
||||
|
||||
unsigned int index;
|
||||
unsigned int numEntries = Entries.size();
|
||||
|
||||
unsigned int numToPrint;
|
||||
|
||||
if (Padding) {
|
||||
if (numEntries > Padding) {
|
||||
fprintf(stderr, "%u entries but %u padding\n", numEntries, Padding);
|
||||
llvm_unreachable("More entries than padding");
|
||||
}
|
||||
numToPrint = Padding;
|
||||
} else {
|
||||
numToPrint = numEntries;
|
||||
}
|
||||
|
||||
for (index = 0; index < numToPrint; ++index) {
|
||||
o.indent(i);
|
||||
if (index < numEntries)
|
||||
Entries[index]->emit(o, i);
|
||||
else
|
||||
o << "-1";
|
||||
|
||||
if (index < (numToPrint - 1))
|
||||
o << ",";
|
||||
o << "\n";
|
||||
}
|
||||
|
||||
i -= 2;
|
||||
o.indent(i) << "}";
|
||||
}
|
||||
};
|
||||
|
||||
class FlagsConstantEmitter : public ConstantEmitter {
|
||||
private:
|
||||
std::vector<std::string> Flags;
|
||||
public:
|
||||
FlagsConstantEmitter() {
|
||||
}
|
||||
FlagsConstantEmitter &addEntry(const char *f) {
|
||||
Flags.push_back(std::string(f));
|
||||
return *this;
|
||||
}
|
||||
void emit(raw_ostream &o, unsigned int &i) {
|
||||
unsigned int index;
|
||||
unsigned int numFlags = Flags.size();
|
||||
if (numFlags == 0)
|
||||
o << "0";
|
||||
|
||||
for (index = 0; index < numFlags; ++index) {
|
||||
o << Flags[index].c_str();
|
||||
if (index < (numFlags - 1))
|
||||
o << " | ";
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
EDEmitter::EDEmitter(RecordKeeper &R) : Records(R) {
|
||||
}
|
||||
}
|
||||
};
|
||||
} // End anonymous namespace
|
||||
|
||||
/// populateOperandOrder - Accepts a CodeGenInstruction and generates its
|
||||
/// AsmWriterInst for the desired assembly syntax, giving an ordered list of
|
||||
@ -213,9 +220,9 @@ EDEmitter::EDEmitter(RecordKeeper &R) : Records(R) {
|
||||
/// representing an index in the operand descriptor array.
|
||||
/// @arg inst - The instruction to use when looking up the operands
|
||||
/// @arg syntax - The syntax to use, according to LLVM's enumeration
|
||||
void populateOperandOrder(CompoundConstantEmitter *operandOrder,
|
||||
const CodeGenInstruction &inst,
|
||||
unsigned syntax) {
|
||||
static void populateOperandOrder(CompoundConstantEmitter *operandOrder,
|
||||
const CodeGenInstruction &inst,
|
||||
unsigned syntax) {
|
||||
unsigned int numArgs = 0;
|
||||
|
||||
AsmWriterInst awInst(inst, syntax, -1, -1);
|
||||
@ -975,17 +982,23 @@ static void emitCommonEnums(raw_ostream &o, unsigned int &i) {
|
||||
o << "\n";
|
||||
}
|
||||
|
||||
void EDEmitter::run(raw_ostream &o) {
|
||||
namespace llvm {
|
||||
|
||||
void EmitEnhancedDisassemblerInfo(RecordKeeper &RK, raw_ostream &OS) {
|
||||
emitSourceFileHeader("Enhanced Disassembler Info", OS);
|
||||
unsigned int i = 0;
|
||||
|
||||
CompoundConstantEmitter infoArray;
|
||||
CodeGenTarget target(Records);
|
||||
CodeGenTarget target(RK);
|
||||
|
||||
populateInstInfo(infoArray, target);
|
||||
|
||||
emitCommonEnums(o, i);
|
||||
emitCommonEnums(OS, i);
|
||||
|
||||
o << "static const llvm::EDInstInfo instInfo" << target.getName() << "[] = ";
|
||||
infoArray.emit(o, i);
|
||||
o << ";" << "\n";
|
||||
OS << "static const llvm::EDInstInfo instInfo"
|
||||
<< target.getName() << "[] = ";
|
||||
infoArray.emit(OS, i);
|
||||
OS << ";" << "\n";
|
||||
}
|
||||
|
||||
} // End llvm namespace
|
||||
|
@ -1,34 +0,0 @@
|
||||
//===- EDEmitter.h - Generate instruction descriptions for ED ---*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This tablegen backend is responsible for emitting a description of each
|
||||
// instruction in a format that the semantic disassembler can use to tokenize
|
||||
// and parse instructions.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef SEMANTIC_INFO_EMITTER_H
|
||||
#define SEMANTIC_INFO_EMITTER_H
|
||||
|
||||
#include "llvm/TableGen/TableGenBackend.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class EDEmitter : public TableGenBackend {
|
||||
RecordKeeper &Records;
|
||||
public:
|
||||
EDEmitter(RecordKeeper &R);
|
||||
|
||||
// run - Output the instruction table.
|
||||
void run(raw_ostream &o);
|
||||
};
|
||||
|
||||
} // End llvm namespace
|
||||
|
||||
#endif
|
@ -17,28 +17,31 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "FastISelEmitter.h"
|
||||
#include "llvm/TableGen/Error.h"
|
||||
#include "llvm/TableGen/Record.h"
|
||||
#include "CodeGenDAGPatterns.h"
|
||||
#include "llvm/ADT/SmallString.h"
|
||||
#include "llvm/Support/Debug.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
#include "llvm/TableGen/Error.h"
|
||||
#include "llvm/TableGen/Record.h"
|
||||
#include "llvm/TableGen/TableGenBackend.h"
|
||||
using namespace llvm;
|
||||
|
||||
namespace {
|
||||
|
||||
/// InstructionMemo - This class holds additional information about an
|
||||
/// instruction needed to emit code for it.
|
||||
///
|
||||
namespace {
|
||||
struct InstructionMemo {
|
||||
std::string Name;
|
||||
const CodeGenRegisterClass *RC;
|
||||
std::string SubRegNo;
|
||||
std::vector<std::string>* PhysRegs;
|
||||
};
|
||||
|
||||
} // End anonymous namespace
|
||||
|
||||
/// ImmPredicateSet - This uniques predicates (represented as a string) and
|
||||
/// gives them unique (small) integer ID's that start at 0.
|
||||
namespace {
|
||||
class ImmPredicateSet {
|
||||
DenseMap<TreePattern *, unsigned> ImmIDs;
|
||||
std::vector<TreePredicateFn> PredsByName;
|
||||
@ -63,10 +66,12 @@ public:
|
||||
iterator end() const { return PredsByName.end(); }
|
||||
|
||||
};
|
||||
} // End anonymous namespace
|
||||
|
||||
/// OperandsSignature - This class holds a description of a list of operand
|
||||
/// types. It has utility methods for emitting text based on the operands.
|
||||
///
|
||||
namespace {
|
||||
struct OperandsSignature {
|
||||
class OpKind {
|
||||
enum { OK_Reg, OK_FP, OK_Imm, OK_Invalid = -1 };
|
||||
@ -352,7 +357,9 @@ struct OperandsSignature {
|
||||
Operands[i].printManglingSuffix(OS, ImmPredicates, StripImmCodes);
|
||||
}
|
||||
};
|
||||
} // End anonymous namespace
|
||||
|
||||
namespace {
|
||||
class FastISelMap {
|
||||
typedef std::map<std::string, InstructionMemo> PredMap;
|
||||
typedef std::map<MVT::SimpleValueType, PredMap> RetPredMap;
|
||||
@ -375,8 +382,7 @@ public:
|
||||
void printImmediatePredicates(raw_ostream &OS);
|
||||
void printFunctionDefinitions(raw_ostream &OS);
|
||||
};
|
||||
|
||||
}
|
||||
} // End anonymous namespace
|
||||
|
||||
static std::string getOpcodeName(Record *Op, CodeGenDAGPatterns &CGP) {
|
||||
return CGP.getSDNodeInfo(Op).getEnumName();
|
||||
@ -850,23 +856,22 @@ void FastISelMap::printFunctionDefinitions(raw_ostream &OS) {
|
||||
// TODO: SignaturesWithConstantForms should be empty here.
|
||||
}
|
||||
|
||||
void FastISelEmitter::run(raw_ostream &OS) {
|
||||
namespace llvm {
|
||||
|
||||
void EmitFastISel(RecordKeeper &RK, raw_ostream &OS) {
|
||||
CodeGenDAGPatterns CGP(RK);
|
||||
const CodeGenTarget &Target = CGP.getTargetInfo();
|
||||
emitSourceFileHeader("\"Fast\" Instruction Selector for the " +
|
||||
Target.getName() + " target", OS);
|
||||
|
||||
// Determine the target's namespace name.
|
||||
std::string InstNS = Target.getInstNamespace() + "::";
|
||||
assert(InstNS.size() > 2 && "Can't determine target-specific namespace!");
|
||||
|
||||
EmitSourceFileHeader("\"Fast\" Instruction Selector for the " +
|
||||
Target.getName() + " target", OS);
|
||||
|
||||
FastISelMap F(InstNS);
|
||||
F.collectPatterns(CGP);
|
||||
F.printImmediatePredicates(OS);
|
||||
F.printFunctionDefinitions(OS);
|
||||
}
|
||||
|
||||
FastISelEmitter::FastISelEmitter(RecordKeeper &R)
|
||||
: CGP(R) {
|
||||
}
|
||||
|
||||
} // End llvm namespace
|
||||
|
@ -1,38 +0,0 @@
|
||||
//===- FastISelEmitter.h - Generate an instruction selector -----*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This tablegen backend emits a "fast" instruction selector.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef FASTISEL_EMITTER_H
|
||||
#define FASTISEL_EMITTER_H
|
||||
|
||||
#include "CodeGenDAGPatterns.h"
|
||||
#include "llvm/TableGen/TableGenBackend.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class CodeGenTarget;
|
||||
|
||||
/// FastISelEmitter - The top-level class which coordinates construction
|
||||
/// and emission of the instruction selector.
|
||||
///
|
||||
class FastISelEmitter : public TableGenBackend {
|
||||
CodeGenDAGPatterns CGP;
|
||||
public:
|
||||
explicit FastISelEmitter(RecordKeeper &R);
|
||||
|
||||
// run - Output the isel, returning true on failure.
|
||||
void run(raw_ostream &OS);
|
||||
};
|
||||
|
||||
} // End llvm namespace
|
||||
|
||||
#endif
|
@ -14,13 +14,14 @@
|
||||
|
||||
#define DEBUG_TYPE "decoder-emitter"
|
||||
|
||||
#include "FixedLenDecoderEmitter.h"
|
||||
#include "CodeGenTarget.h"
|
||||
#include "llvm/TableGen/Record.h"
|
||||
#include "llvm/ADT/APInt.h"
|
||||
#include "llvm/ADT/StringExtras.h"
|
||||
#include "llvm/Support/DataTypes.h"
|
||||
#include "llvm/Support/Debug.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include "llvm/TableGen/TableGenBackend.h"
|
||||
|
||||
#include <vector>
|
||||
#include <map>
|
||||
@ -28,6 +29,67 @@
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
namespace {
|
||||
struct EncodingField {
|
||||
unsigned Base, Width, Offset;
|
||||
EncodingField(unsigned B, unsigned W, unsigned O)
|
||||
: Base(B), Width(W), Offset(O) { }
|
||||
};
|
||||
} // End anonymous namespace
|
||||
|
||||
namespace {
|
||||
struct OperandInfo {
|
||||
std::vector<EncodingField> Fields;
|
||||
std::string Decoder;
|
||||
|
||||
OperandInfo(std::string D)
|
||||
: Decoder(D) { }
|
||||
|
||||
void addField(unsigned Base, unsigned Width, unsigned Offset) {
|
||||
Fields.push_back(EncodingField(Base, Width, Offset));
|
||||
}
|
||||
|
||||
unsigned numFields() const { return Fields.size(); }
|
||||
|
||||
typedef std::vector<EncodingField>::const_iterator const_iterator;
|
||||
|
||||
const_iterator begin() const { return Fields.begin(); }
|
||||
const_iterator end() const { return Fields.end(); }
|
||||
};
|
||||
} // End anonymous namespace
|
||||
|
||||
namespace {
|
||||
class FixedLenDecoderEmitter {
|
||||
public:
|
||||
|
||||
// Defaults preserved here for documentation, even though they aren't
|
||||
// strictly necessary given the way that this is currently being called.
|
||||
FixedLenDecoderEmitter(RecordKeeper &R,
|
||||
std::string PredicateNamespace,
|
||||
std::string GPrefix = "if (",
|
||||
std::string GPostfix = " == MCDisassembler::Fail)"
|
||||
" return MCDisassembler::Fail;",
|
||||
std::string ROK = "MCDisassembler::Success",
|
||||
std::string RFail = "MCDisassembler::Fail",
|
||||
std::string L = "") :
|
||||
Target(R),
|
||||
PredicateNamespace(PredicateNamespace),
|
||||
GuardPrefix(GPrefix), GuardPostfix(GPostfix),
|
||||
ReturnOK(ROK), ReturnFail(RFail), Locals(L) {}
|
||||
|
||||
// run - Output the code emitter
|
||||
void run(raw_ostream &o);
|
||||
|
||||
private:
|
||||
CodeGenTarget Target;
|
||||
public:
|
||||
std::string PredicateNamespace;
|
||||
std::string GuardPrefix, GuardPostfix;
|
||||
std::string ReturnOK, ReturnFail;
|
||||
std::string Locals;
|
||||
};
|
||||
} // End anonymous namespace
|
||||
|
||||
// The set (BIT_TRUE, BIT_FALSE, BIT_UNSET) represents a ternary logic system
|
||||
// for a bit value.
|
||||
//
|
||||
@ -83,7 +145,9 @@ static BitsInit &getBitsField(const Record &def, const char *str) {
|
||||
}
|
||||
|
||||
// Forward declaration.
|
||||
namespace {
|
||||
class FilterChooser;
|
||||
} // End anonymous namespace
|
||||
|
||||
// Representation of the instruction to work on.
|
||||
typedef std::vector<bit_value_t> insn_t;
|
||||
@ -124,6 +188,7 @@ typedef std::vector<bit_value_t> insn_t;
|
||||
/// decoder could try to decode the even/odd register numbering and assign to
|
||||
/// VST4q8a or VST4q8b, but for the time being, the decoder chooses the "a"
|
||||
/// version and return the Opcode since the two have the same Asm format string.
|
||||
namespace {
|
||||
class Filter {
|
||||
protected:
|
||||
const FilterChooser *Owner;// points to the FilterChooser who owns this filter
|
||||
@ -180,6 +245,7 @@ public:
|
||||
// the filter distinguishes more categories of instructions.
|
||||
unsigned usefulness() const;
|
||||
}; // End of class Filter
|
||||
} // End anonymous namespace
|
||||
|
||||
// These are states of our finite state machines used in FilterChooser's
|
||||
// filterProcessor() which produces the filter candidates to use.
|
||||
@ -206,6 +272,7 @@ typedef enum {
|
||||
/// It is useful to think of a Filter as governing the switch stmts of the
|
||||
/// decoding tree. And each case is delegated to an inferior FilterChooser to
|
||||
/// decide what further remaining bits to look at.
|
||||
namespace {
|
||||
class FilterChooser {
|
||||
protected:
|
||||
friend class Filter;
|
||||
@ -385,6 +452,7 @@ protected:
|
||||
// the instruction at this level or the instruction is not decodeable.
|
||||
bool emit(raw_ostream &o, unsigned &Indentation) const;
|
||||
};
|
||||
} // End anonymous namespace
|
||||
|
||||
///////////////////////////
|
||||
// //
|
||||
@ -1573,3 +1641,18 @@ void FixedLenDecoderEmitter::run(raw_ostream &o) {
|
||||
|
||||
o << "\n} // End llvm namespace \n";
|
||||
}
|
||||
|
||||
namespace llvm {
|
||||
|
||||
void EmitFixedLenDecoder(RecordKeeper &RK, raw_ostream &OS,
|
||||
std::string PredicateNamespace,
|
||||
std::string GPrefix,
|
||||
std::string GPostfix,
|
||||
std::string ROK,
|
||||
std::string RFail,
|
||||
std::string L) {
|
||||
FixedLenDecoderEmitter(RK, PredicateNamespace, GPrefix, GPostfix,
|
||||
ROK, RFail, L).run(OS);
|
||||
}
|
||||
|
||||
} // End llvm namespace
|
||||
|
@ -1,79 +0,0 @@
|
||||
//===------------ FixedLenDecoderEmitter.h - Decoder Generator --*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// It contains the tablegen backend that emits the decoder functions for
|
||||
// targets with fixed length instruction set.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef FixedLenDECODEREMITTER_H
|
||||
#define FixedLenDECODEREMITTER_H
|
||||
|
||||
#include "CodeGenTarget.h"
|
||||
|
||||
#include "llvm/TableGen/TableGenBackend.h"
|
||||
#include "llvm/Support/DataTypes.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
struct EncodingField {
|
||||
unsigned Base, Width, Offset;
|
||||
EncodingField(unsigned B, unsigned W, unsigned O)
|
||||
: Base(B), Width(W), Offset(O) { }
|
||||
};
|
||||
|
||||
struct OperandInfo {
|
||||
std::vector<EncodingField> Fields;
|
||||
std::string Decoder;
|
||||
|
||||
OperandInfo(std::string D)
|
||||
: Decoder(D) { }
|
||||
|
||||
void addField(unsigned Base, unsigned Width, unsigned Offset) {
|
||||
Fields.push_back(EncodingField(Base, Width, Offset));
|
||||
}
|
||||
|
||||
unsigned numFields() const { return Fields.size(); }
|
||||
|
||||
typedef std::vector<EncodingField>::const_iterator const_iterator;
|
||||
|
||||
const_iterator begin() const { return Fields.begin(); }
|
||||
const_iterator end() const { return Fields.end(); }
|
||||
};
|
||||
|
||||
class FixedLenDecoderEmitter : public TableGenBackend {
|
||||
public:
|
||||
FixedLenDecoderEmitter(RecordKeeper &R,
|
||||
std::string PredicateNamespace,
|
||||
std::string GPrefix = "if (",
|
||||
std::string GPostfix = " == MCDisassembler::Fail)"
|
||||
" return MCDisassembler::Fail;",
|
||||
std::string ROK = "MCDisassembler::Success",
|
||||
std::string RFail = "MCDisassembler::Fail",
|
||||
std::string L = "") :
|
||||
Target(R),
|
||||
PredicateNamespace(PredicateNamespace),
|
||||
GuardPrefix(GPrefix), GuardPostfix(GPostfix),
|
||||
ReturnOK(ROK), ReturnFail(RFail), Locals(L) {}
|
||||
|
||||
// run - Output the code emitter
|
||||
void run(raw_ostream &o);
|
||||
|
||||
private:
|
||||
CodeGenTarget Target;
|
||||
public:
|
||||
std::string PredicateNamespace;
|
||||
std::string GuardPrefix, GuardPostfix;
|
||||
std::string ReturnOK, ReturnFail;
|
||||
std::string Locals;
|
||||
};
|
||||
|
||||
} // end llvm namespace
|
||||
|
||||
#endif
|
@ -12,15 +12,51 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "InstrInfoEmitter.h"
|
||||
|
||||
#include "CodeGenDAGPatterns.h"
|
||||
#include "CodeGenTarget.h"
|
||||
#include "SequenceToOffsetTable.h"
|
||||
#include "llvm/TableGen/Record.h"
|
||||
#include "llvm/ADT/StringExtras.h"
|
||||
#include "llvm/TableGen/Record.h"
|
||||
#include "llvm/TableGen/TableGenBackend.h"
|
||||
#include <algorithm>
|
||||
#include <cstdio>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
using namespace llvm;
|
||||
|
||||
namespace {
|
||||
class InstrInfoEmitter {
|
||||
RecordKeeper &Records;
|
||||
CodeGenDAGPatterns CDP;
|
||||
std::map<std::string, unsigned> ItinClassMap;
|
||||
|
||||
public:
|
||||
InstrInfoEmitter(RecordKeeper &R) : Records(R), CDP(R) { }
|
||||
|
||||
// run - Output the instruction set description.
|
||||
void run(raw_ostream &OS);
|
||||
|
||||
private:
|
||||
void emitEnums(raw_ostream &OS);
|
||||
|
||||
typedef std::map<std::vector<std::string>, unsigned> OperandInfoMapTy;
|
||||
void emitRecord(const CodeGenInstruction &Inst, unsigned Num,
|
||||
Record *InstrInfo,
|
||||
std::map<std::vector<Record*>, unsigned> &EL,
|
||||
const OperandInfoMapTy &OpInfo,
|
||||
raw_ostream &OS);
|
||||
|
||||
// Itinerary information.
|
||||
void GatherItinClasses();
|
||||
unsigned getItinClassNumber(const Record *InstRec);
|
||||
|
||||
// Operand information.
|
||||
void EmitOperandInfo(raw_ostream &OS, OperandInfoMapTy &OperandInfoIDs);
|
||||
std::vector<std::string> GetOperandInfo(const CodeGenInstruction &Inst);
|
||||
};
|
||||
} // End anonymous namespace
|
||||
|
||||
static void PrintDefList(const std::vector<Record*> &Uses,
|
||||
unsigned Num, raw_ostream &OS) {
|
||||
OS << "static const uint16_t ImplicitList" << Num << "[] = { ";
|
||||
@ -163,11 +199,12 @@ void InstrInfoEmitter::EmitOperandInfo(raw_ostream &OS,
|
||||
|
||||
// run - Emit the main instruction description records for the target...
|
||||
void InstrInfoEmitter::run(raw_ostream &OS) {
|
||||
emitSourceFileHeader("Target Instruction Enum Values", OS);
|
||||
emitEnums(OS);
|
||||
|
||||
GatherItinClasses();
|
||||
|
||||
EmitSourceFileHeader("Target Instruction Descriptors", OS);
|
||||
emitSourceFileHeader("Target Instruction Descriptors", OS);
|
||||
|
||||
OS << "\n#ifdef GET_INSTRINFO_MC_DESC\n";
|
||||
OS << "#undef GET_INSTRINFO_MC_DESC\n";
|
||||
@ -362,7 +399,6 @@ void InstrInfoEmitter::emitRecord(const CodeGenInstruction &Inst, unsigned Num,
|
||||
|
||||
// emitEnums - Print out enum values for all of the instructions.
|
||||
void InstrInfoEmitter::emitEnums(raw_ostream &OS) {
|
||||
EmitSourceFileHeader("Target Instruction Enum Values", OS);
|
||||
|
||||
OS << "\n#ifdef GET_INSTRINFO_ENUM\n";
|
||||
OS << "#undef GET_INSTRINFO_ENUM\n";
|
||||
@ -394,3 +430,11 @@ void InstrInfoEmitter::emitEnums(raw_ostream &OS) {
|
||||
|
||||
OS << "#endif // GET_INSTRINFO_ENUM\n\n";
|
||||
}
|
||||
|
||||
namespace llvm {
|
||||
|
||||
void EmitInstrInfo(RecordKeeper &RK, raw_ostream &OS) {
|
||||
InstrInfoEmitter(RK).run(OS);
|
||||
}
|
||||
|
||||
} // End llvm namespace
|
||||
|
@ -1,62 +0,0 @@
|
||||
//===- InstrInfoEmitter.h - Generate a Instruction Set Desc. ----*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This tablegen backend is responsible for emitting a description of the target
|
||||
// instruction set for the code generator.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef INSTRINFO_EMITTER_H
|
||||
#define INSTRINFO_EMITTER_H
|
||||
|
||||
#include "CodeGenDAGPatterns.h"
|
||||
#include "llvm/TableGen/TableGenBackend.h"
|
||||
#include <vector>
|
||||
#include <map>
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class StringInit;
|
||||
class IntInit;
|
||||
class ListInit;
|
||||
class CodeGenInstruction;
|
||||
|
||||
class InstrInfoEmitter : public TableGenBackend {
|
||||
RecordKeeper &Records;
|
||||
CodeGenDAGPatterns CDP;
|
||||
std::map<std::string, unsigned> ItinClassMap;
|
||||
|
||||
public:
|
||||
InstrInfoEmitter(RecordKeeper &R) : Records(R), CDP(R) { }
|
||||
|
||||
// run - Output the instruction set description.
|
||||
void run(raw_ostream &OS);
|
||||
|
||||
private:
|
||||
void emitEnums(raw_ostream &OS);
|
||||
|
||||
typedef std::map<std::vector<std::string>, unsigned> OperandInfoMapTy;
|
||||
void emitRecord(const CodeGenInstruction &Inst, unsigned Num,
|
||||
Record *InstrInfo,
|
||||
std::map<std::vector<Record*>, unsigned> &EL,
|
||||
const OperandInfoMapTy &OpInfo,
|
||||
raw_ostream &OS);
|
||||
|
||||
// Itinerary information.
|
||||
void GatherItinClasses();
|
||||
unsigned getItinClassNumber(const Record *InstRec);
|
||||
|
||||
// Operand information.
|
||||
void EmitOperandInfo(raw_ostream &OS, OperandInfoMapTy &OperandInfoIDs);
|
||||
std::vector<std::string> GetOperandInfo(const CodeGenInstruction &Inst);
|
||||
};
|
||||
|
||||
} // End llvm namespace
|
||||
|
||||
#endif
|
@ -11,24 +11,62 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "CodeGenIntrinsics.h"
|
||||
#include "CodeGenTarget.h"
|
||||
#include "IntrinsicEmitter.h"
|
||||
#include "SequenceToOffsetTable.h"
|
||||
#include "llvm/ADT/StringExtras.h"
|
||||
#include "llvm/TableGen/Record.h"
|
||||
#include "llvm/TableGen/StringMatcher.h"
|
||||
#include "llvm/ADT/StringExtras.h"
|
||||
#include "llvm/TableGen/TableGenBackend.h"
|
||||
#include <algorithm>
|
||||
using namespace llvm;
|
||||
|
||||
namespace {
|
||||
class IntrinsicEmitter {
|
||||
RecordKeeper &Records;
|
||||
bool TargetOnly;
|
||||
std::string TargetPrefix;
|
||||
|
||||
public:
|
||||
IntrinsicEmitter(RecordKeeper &R, bool T)
|
||||
: Records(R), TargetOnly(T) {}
|
||||
|
||||
void run(raw_ostream &OS);
|
||||
|
||||
void EmitPrefix(raw_ostream &OS);
|
||||
|
||||
void EmitEnumInfo(const std::vector<CodeGenIntrinsic> &Ints,
|
||||
raw_ostream &OS);
|
||||
|
||||
void EmitFnNameRecognizer(const std::vector<CodeGenIntrinsic> &Ints,
|
||||
raw_ostream &OS);
|
||||
void EmitIntrinsicToNameTable(const std::vector<CodeGenIntrinsic> &Ints,
|
||||
raw_ostream &OS);
|
||||
void EmitIntrinsicToOverloadTable(const std::vector<CodeGenIntrinsic> &Ints,
|
||||
raw_ostream &OS);
|
||||
void EmitVerifier(const std::vector<CodeGenIntrinsic> &Ints,
|
||||
raw_ostream &OS);
|
||||
void EmitGenerator(const std::vector<CodeGenIntrinsic> &Ints,
|
||||
raw_ostream &OS);
|
||||
void EmitAttributes(const std::vector<CodeGenIntrinsic> &Ints,
|
||||
raw_ostream &OS);
|
||||
void EmitModRefBehavior(const std::vector<CodeGenIntrinsic> &Ints,
|
||||
raw_ostream &OS);
|
||||
void EmitIntrinsicToGCCBuiltinMap(const std::vector<CodeGenIntrinsic> &Ints,
|
||||
raw_ostream &OS);
|
||||
void EmitSuffix(raw_ostream &OS);
|
||||
};
|
||||
} // End anonymous namespace
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// IntrinsicEmitter Implementation
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
void IntrinsicEmitter::run(raw_ostream &OS) {
|
||||
EmitSourceFileHeader("Intrinsic Function Source Fragment", OS);
|
||||
|
||||
emitSourceFileHeader("Intrinsic Function Source Fragment", OS);
|
||||
|
||||
std::vector<CodeGenIntrinsic> Ints = LoadIntrinsics(Records, TargetOnly);
|
||||
|
||||
|
||||
if (TargetOnly && !Ints.empty())
|
||||
TargetPrefix = Ints[0].TargetPrefix;
|
||||
|
||||
@ -338,7 +376,7 @@ static void ComputeFixedEncoding(const CodeGenIntrinsic &Int,
|
||||
EncodeFixedType(Int.IS.ParamTypeDefs[i], ArgCodes, TypeSig);
|
||||
}
|
||||
|
||||
void printIITEntry(raw_ostream &OS, unsigned char X) {
|
||||
static void printIITEntry(raw_ostream &OS, unsigned char X) {
|
||||
OS << (unsigned)X;
|
||||
}
|
||||
|
||||
@ -424,48 +462,48 @@ void IntrinsicEmitter::EmitGenerator(const std::vector<CodeGenIntrinsic> &Ints,
|
||||
OS << "#endif\n\n"; // End of GET_INTRINSIC_GENERATOR_GLOBAL
|
||||
}
|
||||
|
||||
namespace {
|
||||
enum ModRefKind {
|
||||
MRK_none,
|
||||
MRK_readonly,
|
||||
MRK_readnone
|
||||
};
|
||||
enum ModRefKind {
|
||||
MRK_none,
|
||||
MRK_readonly,
|
||||
MRK_readnone
|
||||
};
|
||||
|
||||
ModRefKind getModRefKind(const CodeGenIntrinsic &intrinsic) {
|
||||
switch (intrinsic.ModRef) {
|
||||
case CodeGenIntrinsic::NoMem:
|
||||
return MRK_readnone;
|
||||
case CodeGenIntrinsic::ReadArgMem:
|
||||
case CodeGenIntrinsic::ReadMem:
|
||||
return MRK_readonly;
|
||||
case CodeGenIntrinsic::ReadWriteArgMem:
|
||||
case CodeGenIntrinsic::ReadWriteMem:
|
||||
return MRK_none;
|
||||
}
|
||||
llvm_unreachable("bad mod-ref kind");
|
||||
static ModRefKind getModRefKind(const CodeGenIntrinsic &intrinsic) {
|
||||
switch (intrinsic.ModRef) {
|
||||
case CodeGenIntrinsic::NoMem:
|
||||
return MRK_readnone;
|
||||
case CodeGenIntrinsic::ReadArgMem:
|
||||
case CodeGenIntrinsic::ReadMem:
|
||||
return MRK_readonly;
|
||||
case CodeGenIntrinsic::ReadWriteArgMem:
|
||||
case CodeGenIntrinsic::ReadWriteMem:
|
||||
return MRK_none;
|
||||
}
|
||||
|
||||
struct AttributeComparator {
|
||||
bool operator()(const CodeGenIntrinsic *L, const CodeGenIntrinsic *R) const {
|
||||
// Sort throwing intrinsics after non-throwing intrinsics.
|
||||
if (L->canThrow != R->canThrow)
|
||||
return R->canThrow;
|
||||
|
||||
if (L->isNoReturn != R->isNoReturn)
|
||||
return R->isNoReturn;
|
||||
|
||||
// Try to order by readonly/readnone attribute.
|
||||
ModRefKind LK = getModRefKind(*L);
|
||||
ModRefKind RK = getModRefKind(*R);
|
||||
if (LK != RK) return (LK > RK);
|
||||
|
||||
// Order by argument attributes.
|
||||
// This is reliable because each side is already sorted internally.
|
||||
return (L->ArgumentAttributes < R->ArgumentAttributes);
|
||||
}
|
||||
};
|
||||
llvm_unreachable("bad mod-ref kind");
|
||||
}
|
||||
|
||||
namespace {
|
||||
struct AttributeComparator {
|
||||
bool operator()(const CodeGenIntrinsic *L, const CodeGenIntrinsic *R) const {
|
||||
// Sort throwing intrinsics after non-throwing intrinsics.
|
||||
if (L->canThrow != R->canThrow)
|
||||
return R->canThrow;
|
||||
|
||||
if (L->isNoReturn != R->isNoReturn)
|
||||
return R->isNoReturn;
|
||||
|
||||
// Try to order by readonly/readnone attribute.
|
||||
ModRefKind LK = getModRefKind(*L);
|
||||
ModRefKind RK = getModRefKind(*R);
|
||||
if (LK != RK) return (LK > RK);
|
||||
|
||||
// Order by argument attributes.
|
||||
// This is reliable because each side is already sorted internally.
|
||||
return (L->ArgumentAttributes < R->ArgumentAttributes);
|
||||
}
|
||||
};
|
||||
} // End anonymous namespace
|
||||
|
||||
/// EmitAttributes - This emits the Intrinsic::getAttributes method.
|
||||
void IntrinsicEmitter::
|
||||
EmitAttributes(const std::vector<CodeGenIntrinsic> &Ints, raw_ostream &OS) {
|
||||
@ -705,3 +743,11 @@ EmitIntrinsicToGCCBuiltinMap(const std::vector<CodeGenIntrinsic> &Ints,
|
||||
OS << "}\n";
|
||||
OS << "#endif\n\n";
|
||||
}
|
||||
|
||||
namespace llvm {
|
||||
|
||||
void EmitIntrinsics(RecordKeeper &RK, raw_ostream &OS, bool TargetOnly = false) {
|
||||
IntrinsicEmitter(RK, TargetOnly).run(OS);
|
||||
}
|
||||
|
||||
} // End llvm namespace
|
||||
|
@ -1,61 +0,0 @@
|
||||
//===- IntrinsicEmitter.h - Generate intrinsic information ------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This tablegen backend emits information about intrinsic functions.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef INTRINSIC_EMITTER_H
|
||||
#define INTRINSIC_EMITTER_H
|
||||
|
||||
#include "CodeGenIntrinsics.h"
|
||||
#include "llvm/TableGen/TableGenBackend.h"
|
||||
|
||||
namespace llvm {
|
||||
class IntrinsicEmitter : public TableGenBackend {
|
||||
RecordKeeper &Records;
|
||||
bool TargetOnly;
|
||||
std::string TargetPrefix;
|
||||
|
||||
public:
|
||||
IntrinsicEmitter(RecordKeeper &R, bool T = false)
|
||||
: Records(R), TargetOnly(T) {}
|
||||
|
||||
void run(raw_ostream &OS);
|
||||
|
||||
void EmitPrefix(raw_ostream &OS);
|
||||
|
||||
void EmitEnumInfo(const std::vector<CodeGenIntrinsic> &Ints,
|
||||
raw_ostream &OS);
|
||||
|
||||
void EmitFnNameRecognizer(const std::vector<CodeGenIntrinsic> &Ints,
|
||||
raw_ostream &OS);
|
||||
void EmitIntrinsicToNameTable(const std::vector<CodeGenIntrinsic> &Ints,
|
||||
raw_ostream &OS);
|
||||
void EmitIntrinsicToOverloadTable(const std::vector<CodeGenIntrinsic> &Ints,
|
||||
raw_ostream &OS);
|
||||
void EmitVerifier(const std::vector<CodeGenIntrinsic> &Ints,
|
||||
raw_ostream &OS);
|
||||
void EmitGenerator(const std::vector<CodeGenIntrinsic> &Ints,
|
||||
raw_ostream &OS);
|
||||
void EmitAttributes(const std::vector<CodeGenIntrinsic> &Ints,
|
||||
raw_ostream &OS);
|
||||
void EmitModRefBehavior(const std::vector<CodeGenIntrinsic> &Ints,
|
||||
raw_ostream &OS);
|
||||
void EmitIntrinsicToGCCBuiltinMap(const std::vector<CodeGenIntrinsic> &Ints,
|
||||
raw_ostream &OS);
|
||||
void EmitSuffix(raw_ostream &OS);
|
||||
};
|
||||
|
||||
} // End llvm namespace
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
@ -9,16 +9,62 @@
|
||||
|
||||
#define DEBUG_TYPE "pseudo-lowering"
|
||||
#include "CodeGenInstruction.h"
|
||||
#include "PseudoLoweringEmitter.h"
|
||||
#include "CodeGenTarget.h"
|
||||
#include "llvm/ADT/IndexedMap.h"
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
#include "llvm/ADT/StringMap.h"
|
||||
#include "llvm/Support/Debug.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
#include "llvm/TableGen/Error.h"
|
||||
#include "llvm/TableGen/Record.h"
|
||||
#include "llvm/ADT/IndexedMap.h"
|
||||
#include "llvm/ADT/StringMap.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
#include "llvm/Support/Debug.h"
|
||||
#include "llvm/TableGen/TableGenBackend.h"
|
||||
#include <vector>
|
||||
using namespace llvm;
|
||||
|
||||
namespace {
|
||||
class PseudoLoweringEmitter {
|
||||
struct OpData {
|
||||
enum MapKind { Operand, Imm, Reg };
|
||||
MapKind Kind;
|
||||
union {
|
||||
unsigned Operand; // Operand number mapped to.
|
||||
uint64_t Imm; // Integer immedate value.
|
||||
Record *Reg; // Physical register.
|
||||
} Data;
|
||||
};
|
||||
struct PseudoExpansion {
|
||||
CodeGenInstruction Source; // The source pseudo instruction definition.
|
||||
CodeGenInstruction Dest; // The destination instruction to lower to.
|
||||
IndexedMap<OpData> OperandMap;
|
||||
|
||||
PseudoExpansion(CodeGenInstruction &s, CodeGenInstruction &d,
|
||||
IndexedMap<OpData> &m) :
|
||||
Source(s), Dest(d), OperandMap(m) {}
|
||||
};
|
||||
|
||||
RecordKeeper &Records;
|
||||
|
||||
// It's overkill to have an instance of the full CodeGenTarget object,
|
||||
// but it loads everything on demand, not in the constructor, so it's
|
||||
// lightweight in performance, so it works out OK.
|
||||
CodeGenTarget Target;
|
||||
|
||||
SmallVector<PseudoExpansion, 64> Expansions;
|
||||
|
||||
unsigned addDagOperandMapping(Record *Rec, DagInit *Dag,
|
||||
CodeGenInstruction &Insn,
|
||||
IndexedMap<OpData> &OperandMap,
|
||||
unsigned BaseIdx);
|
||||
void evaluateExpansion(Record *Pseudo);
|
||||
void emitLoweringEmitter(raw_ostream &o);
|
||||
public:
|
||||
PseudoLoweringEmitter(RecordKeeper &R) : Records(R), Target(R) {}
|
||||
|
||||
/// run - Output the pseudo-lowerings.
|
||||
void run(raw_ostream &o);
|
||||
};
|
||||
} // End anonymous namespace
|
||||
|
||||
// FIXME: This pass currently can only expand a pseudo to a single instruction.
|
||||
// The pseudo expansion really should take a list of dags, not just
|
||||
// a single dag, so we can do fancier things.
|
||||
@ -150,7 +196,7 @@ void PseudoLoweringEmitter::evaluateExpansion(Record *Rec) {
|
||||
|
||||
void PseudoLoweringEmitter::emitLoweringEmitter(raw_ostream &o) {
|
||||
// Emit file header.
|
||||
EmitSourceFileHeader("Pseudo-instruction MC lowering Source Fragment", o);
|
||||
emitSourceFileHeader("Pseudo-instruction MC lowering Source Fragment", o);
|
||||
|
||||
o << "bool " << Target.getName() + "AsmPrinter" << "::\n"
|
||||
<< "emitPseudoExpansionLowering(MCStreamer &OutStreamer,\n"
|
||||
@ -242,3 +288,10 @@ void PseudoLoweringEmitter::run(raw_ostream &o) {
|
||||
emitLoweringEmitter(o);
|
||||
}
|
||||
|
||||
namespace llvm {
|
||||
|
||||
void EmitPseudoLowering(RecordKeeper &RK, raw_ostream &OS) {
|
||||
PseudoLoweringEmitter(RK).run(OS);
|
||||
}
|
||||
|
||||
} // End llvm namespace
|
||||
|
@ -1,65 +0,0 @@
|
||||
//===- PseudoLoweringEmitter.h - PseudoLowering Generator -------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef PSEUDOLOWERINGEMITTER_H
|
||||
#define PSEUDOLOWERINGEMITTER_H
|
||||
|
||||
#include "CodeGenInstruction.h"
|
||||
#include "CodeGenTarget.h"
|
||||
#include "llvm/TableGen/TableGenBackend.h"
|
||||
#include "llvm/ADT/IndexedMap.h"
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class PseudoLoweringEmitter : public TableGenBackend {
|
||||
struct OpData {
|
||||
enum MapKind { Operand, Imm, Reg };
|
||||
MapKind Kind;
|
||||
union {
|
||||
unsigned Operand; // Operand number mapped to.
|
||||
uint64_t Imm; // Integer immedate value.
|
||||
Record *Reg; // Physical register.
|
||||
} Data;
|
||||
};
|
||||
struct PseudoExpansion {
|
||||
CodeGenInstruction Source; // The source pseudo instruction definition.
|
||||
CodeGenInstruction Dest; // The destination instruction to lower to.
|
||||
IndexedMap<OpData> OperandMap;
|
||||
|
||||
PseudoExpansion(CodeGenInstruction &s, CodeGenInstruction &d,
|
||||
IndexedMap<OpData> &m) :
|
||||
Source(s), Dest(d), OperandMap(m) {}
|
||||
};
|
||||
|
||||
RecordKeeper &Records;
|
||||
|
||||
// It's overkill to have an instance of the full CodeGenTarget object,
|
||||
// but it loads everything on demand, not in the constructor, so it's
|
||||
// lightweight in performance, so it works out OK.
|
||||
CodeGenTarget Target;
|
||||
|
||||
SmallVector<PseudoExpansion, 64> Expansions;
|
||||
|
||||
unsigned addDagOperandMapping(Record *Rec, DagInit *Dag,
|
||||
CodeGenInstruction &Insn,
|
||||
IndexedMap<OpData> &OperandMap,
|
||||
unsigned BaseIdx);
|
||||
void evaluateExpansion(Record *Pseudo);
|
||||
void emitLoweringEmitter(raw_ostream &o);
|
||||
public:
|
||||
PseudoLoweringEmitter(RecordKeeper &R) : Records(R), Target(R) {}
|
||||
|
||||
/// run - Output the pseudo-lowerings.
|
||||
void run(raw_ostream &o);
|
||||
};
|
||||
|
||||
} // end llvm namespace
|
||||
|
||||
#endif
|
@ -13,21 +13,58 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "RegisterInfoEmitter.h"
|
||||
#include "CodeGenTarget.h"
|
||||
#include "CodeGenRegisters.h"
|
||||
#include "CodeGenTarget.h"
|
||||
#include "SequenceToOffsetTable.h"
|
||||
#include "llvm/TableGen/Error.h"
|
||||
#include "llvm/TableGen/Record.h"
|
||||
#include "llvm/ADT/BitVector.h"
|
||||
#include "llvm/ADT/StringExtras.h"
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
#include "llvm/ADT/StringExtras.h"
|
||||
#include "llvm/ADT/Twine.h"
|
||||
#include "llvm/Support/Format.h"
|
||||
#include "llvm/TableGen/Error.h"
|
||||
#include "llvm/TableGen/Record.h"
|
||||
#include "llvm/TableGen/TableGenBackend.h"
|
||||
#include <algorithm>
|
||||
#include <set>
|
||||
#include <vector>
|
||||
using namespace llvm;
|
||||
|
||||
namespace {
|
||||
class RegisterInfoEmitter {
|
||||
RecordKeeper &Records;
|
||||
public:
|
||||
RegisterInfoEmitter(RecordKeeper &R) : Records(R) {}
|
||||
|
||||
// runEnums - Print out enum values for all of the registers.
|
||||
void runEnums(raw_ostream &o, CodeGenTarget &Target, CodeGenRegBank &Bank);
|
||||
|
||||
// runMCDesc - Print out MC register descriptions.
|
||||
void runMCDesc(raw_ostream &o, CodeGenTarget &Target, CodeGenRegBank &Bank);
|
||||
|
||||
// runTargetHeader - Emit a header fragment for the register info emitter.
|
||||
void runTargetHeader(raw_ostream &o, CodeGenTarget &Target,
|
||||
CodeGenRegBank &Bank);
|
||||
|
||||
// runTargetDesc - Output the target register and register file descriptions.
|
||||
void runTargetDesc(raw_ostream &o, CodeGenTarget &Target,
|
||||
CodeGenRegBank &Bank);
|
||||
|
||||
// run - Output the register file description.
|
||||
void run(raw_ostream &o);
|
||||
|
||||
private:
|
||||
void EmitRegMapping(raw_ostream &o,
|
||||
const std::vector<CodeGenRegister*> &Regs, bool isCtor);
|
||||
void EmitRegMappingTables(raw_ostream &o,
|
||||
const std::vector<CodeGenRegister*> &Regs,
|
||||
bool isCtor);
|
||||
void EmitRegClasses(raw_ostream &OS, CodeGenTarget &Target);
|
||||
|
||||
void EmitRegUnitPressure(raw_ostream &OS, const CodeGenRegBank &RegBank,
|
||||
const std::string &ClassName);
|
||||
};
|
||||
} // End anonymous namespace
|
||||
|
||||
// runEnums - Print out enum values for all of the registers.
|
||||
void RegisterInfoEmitter::runEnums(raw_ostream &OS,
|
||||
CodeGenTarget &Target, CodeGenRegBank &Bank) {
|
||||
@ -38,7 +75,7 @@ void RegisterInfoEmitter::runEnums(raw_ostream &OS,
|
||||
|
||||
std::string Namespace = Registers[0]->TheDef->getValueAsString("Namespace");
|
||||
|
||||
EmitSourceFileHeader("Target Register Enum Values", OS);
|
||||
emitSourceFileHeader("Target Register Enum Values", OS);
|
||||
|
||||
OS << "\n#ifdef GET_REGINFO_ENUM\n";
|
||||
OS << "#undef GET_REGINFO_ENUM\n";
|
||||
@ -490,7 +527,7 @@ static void printDiff16(raw_ostream &OS, uint16_t Val) {
|
||||
void
|
||||
RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target,
|
||||
CodeGenRegBank &RegBank) {
|
||||
EmitSourceFileHeader("MC Register Information", OS);
|
||||
emitSourceFileHeader("MC Register Information", OS);
|
||||
|
||||
OS << "\n#ifdef GET_REGINFO_MC_DESC\n";
|
||||
OS << "#undef GET_REGINFO_MC_DESC\n";
|
||||
@ -774,7 +811,7 @@ RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target,
|
||||
void
|
||||
RegisterInfoEmitter::runTargetHeader(raw_ostream &OS, CodeGenTarget &Target,
|
||||
CodeGenRegBank &RegBank) {
|
||||
EmitSourceFileHeader("Register Information Header Fragment", OS);
|
||||
emitSourceFileHeader("Register Information Header Fragment", OS);
|
||||
|
||||
OS << "\n#ifdef GET_REGINFO_HEADER\n";
|
||||
OS << "#undef GET_REGINFO_HEADER\n";
|
||||
@ -830,7 +867,7 @@ RegisterInfoEmitter::runTargetHeader(raw_ostream &OS, CodeGenTarget &Target,
|
||||
void
|
||||
RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target,
|
||||
CodeGenRegBank &RegBank){
|
||||
EmitSourceFileHeader("Target Register and Register Classes Information", OS);
|
||||
emitSourceFileHeader("Target Register and Register Classes Information", OS);
|
||||
|
||||
OS << "\n#ifdef GET_REGINFO_TARGET_DESC\n";
|
||||
OS << "#undef GET_REGINFO_TARGET_DESC\n";
|
||||
@ -1186,3 +1223,11 @@ void RegisterInfoEmitter::run(raw_ostream &OS) {
|
||||
runTargetHeader(OS, Target, RegBank);
|
||||
runTargetDesc(OS, Target, RegBank);
|
||||
}
|
||||
|
||||
namespace llvm {
|
||||
|
||||
void EmitRegisterInfo(RecordKeeper &RK, raw_ostream &OS) {
|
||||
RegisterInfoEmitter(RK).run(OS);
|
||||
}
|
||||
|
||||
} // End llvm namespace
|
||||
|
@ -1,64 +0,0 @@
|
||||
//===- RegisterInfoEmitter.h - Generate a Register File Desc. ---*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This tablegen backend is responsible for emitting a description of a target
|
||||
// register file for a code generator. It uses instances of the Register,
|
||||
// RegisterAliases, and RegisterClass classes to gather this information.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef REGISTER_INFO_EMITTER_H
|
||||
#define REGISTER_INFO_EMITTER_H
|
||||
|
||||
#include "llvm/TableGen/TableGenBackend.h"
|
||||
#include <vector>
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class CodeGenRegBank;
|
||||
struct CodeGenRegister;
|
||||
class CodeGenTarget;
|
||||
|
||||
class RegisterInfoEmitter : public TableGenBackend {
|
||||
RecordKeeper &Records;
|
||||
public:
|
||||
RegisterInfoEmitter(RecordKeeper &R) : Records(R) {}
|
||||
|
||||
// runEnums - Print out enum values for all of the registers.
|
||||
void runEnums(raw_ostream &o, CodeGenTarget &Target, CodeGenRegBank &Bank);
|
||||
|
||||
// runMCDesc - Print out MC register descriptions.
|
||||
void runMCDesc(raw_ostream &o, CodeGenTarget &Target, CodeGenRegBank &Bank);
|
||||
|
||||
// runTargetHeader - Emit a header fragment for the register info emitter.
|
||||
void runTargetHeader(raw_ostream &o, CodeGenTarget &Target,
|
||||
CodeGenRegBank &Bank);
|
||||
|
||||
// runTargetDesc - Output the target register and register file descriptions.
|
||||
void runTargetDesc(raw_ostream &o, CodeGenTarget &Target,
|
||||
CodeGenRegBank &Bank);
|
||||
|
||||
// run - Output the register file description.
|
||||
void run(raw_ostream &o);
|
||||
|
||||
private:
|
||||
void EmitRegMapping(raw_ostream &o,
|
||||
const std::vector<CodeGenRegister*> &Regs, bool isCtor);
|
||||
void EmitRegMappingTables(raw_ostream &o,
|
||||
const std::vector<CodeGenRegister*> &Regs,
|
||||
bool isCtor);
|
||||
void EmitRegClasses(raw_ostream &OS, CodeGenTarget &Target);
|
||||
|
||||
void EmitRegUnitPressure(raw_ostream &OS, const CodeGenRegBank &RegBank,
|
||||
const std::string &ClassName);
|
||||
};
|
||||
|
||||
} // End llvm namespace
|
||||
|
||||
#endif
|
@ -11,14 +11,61 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "SubtargetEmitter.h"
|
||||
#include "CodeGenTarget.h"
|
||||
#include "llvm/TableGen/Record.h"
|
||||
#include "llvm/ADT/StringExtras.h"
|
||||
#include "llvm/MC/MCInstrItineraries.h"
|
||||
#include "llvm/Support/Debug.h"
|
||||
#include "llvm/TableGen/Record.h"
|
||||
#include "llvm/TableGen/TableGenBackend.h"
|
||||
#include <algorithm>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
using namespace llvm;
|
||||
|
||||
namespace {
|
||||
class SubtargetEmitter {
|
||||
|
||||
RecordKeeper &Records;
|
||||
std::string Target;
|
||||
bool HasItineraries;
|
||||
|
||||
void Enumeration(raw_ostream &OS, const char *ClassName, bool isBits);
|
||||
unsigned FeatureKeyValues(raw_ostream &OS);
|
||||
unsigned CPUKeyValues(raw_ostream &OS);
|
||||
unsigned CollectAllItinClasses(raw_ostream &OS,
|
||||
std::map<std::string,unsigned> &ItinClassesMap,
|
||||
std::vector<Record*> &ItinClassList);
|
||||
void FormItineraryStageString(const std::string &Names,
|
||||
Record *ItinData, std::string &ItinString,
|
||||
unsigned &NStages);
|
||||
void FormItineraryOperandCycleString(Record *ItinData, std::string &ItinString,
|
||||
unsigned &NOperandCycles);
|
||||
void FormItineraryBypassString(const std::string &Names,
|
||||
Record *ItinData,
|
||||
std::string &ItinString, unsigned NOperandCycles);
|
||||
void EmitStageAndOperandCycleData(raw_ostream &OS, unsigned NItinClasses,
|
||||
std::map<std::string, unsigned> &ItinClassesMap,
|
||||
std::vector<Record*> &ItinClassList,
|
||||
std::vector<std::vector<InstrItinerary> > &ProcList);
|
||||
void EmitItineraryProp(raw_ostream &OS, const Record *R, const char *Name,
|
||||
char Separator);
|
||||
void EmitProcessorData(raw_ostream &OS,
|
||||
std::vector<Record*> &ItinClassList,
|
||||
std::vector<std::vector<InstrItinerary> > &ProcList);
|
||||
void EmitProcessorLookup(raw_ostream &OS);
|
||||
void EmitData(raw_ostream &OS);
|
||||
void ParseFeaturesFunction(raw_ostream &OS, unsigned NumFeatures,
|
||||
unsigned NumProcs);
|
||||
|
||||
public:
|
||||
SubtargetEmitter(RecordKeeper &R) : Records(R), HasItineraries(false) {}
|
||||
|
||||
void run(raw_ostream &o);
|
||||
|
||||
};
|
||||
} // End anonymous namespace
|
||||
|
||||
//
|
||||
// Enumeration - Emit the specified class as an enumeration.
|
||||
//
|
||||
@ -685,7 +732,7 @@ void SubtargetEmitter::ParseFeaturesFunction(raw_ostream &OS,
|
||||
void SubtargetEmitter::run(raw_ostream &OS) {
|
||||
Target = CodeGenTarget(Records).getName();
|
||||
|
||||
EmitSourceFileHeader("Subtarget Enumeration Source Fragment", OS);
|
||||
emitSourceFileHeader("Subtarget Enumeration Source Fragment", OS);
|
||||
|
||||
OS << "\n#ifdef GET_SUBTARGETINFO_ENUM\n";
|
||||
OS << "#undef GET_SUBTARGETINFO_ENUM\n";
|
||||
@ -802,3 +849,11 @@ void SubtargetEmitter::run(raw_ostream &OS) {
|
||||
|
||||
OS << "#endif // GET_SUBTARGETINFO_CTOR\n\n";
|
||||
}
|
||||
|
||||
namespace llvm {
|
||||
|
||||
void EmitSubtarget(RecordKeeper &RK, raw_ostream &OS) {
|
||||
SubtargetEmitter(RK).run(OS);
|
||||
}
|
||||
|
||||
} // End llvm namespace
|
||||
|
@ -1,74 +0,0 @@
|
||||
//===- SubtargetEmitter.h - Generate subtarget enumerations -----*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This tablegen backend emits subtarget enumerations.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef SUBTARGET_EMITTER_H
|
||||
#define SUBTARGET_EMITTER_H
|
||||
|
||||
#include "llvm/TableGen/TableGenBackend.h"
|
||||
#include "llvm/MC/MCInstrItineraries.h"
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class SubtargetEmitter : public TableGenBackend {
|
||||
|
||||
RecordKeeper &Records;
|
||||
std::string Target;
|
||||
bool HasItineraries;
|
||||
|
||||
void Enumeration(raw_ostream &OS, const char *ClassName, bool isBits);
|
||||
unsigned FeatureKeyValues(raw_ostream &OS);
|
||||
unsigned CPUKeyValues(raw_ostream &OS);
|
||||
unsigned CollectAllItinClasses(raw_ostream &OS,
|
||||
std::map<std::string,unsigned> &ItinClassesMap,
|
||||
std::vector<Record*> &ItinClassList);
|
||||
void FormItineraryStageString(const std::string &Names,
|
||||
Record *ItinData, std::string &ItinString,
|
||||
unsigned &NStages);
|
||||
void FormItineraryOperandCycleString(Record *ItinData, std::string &ItinString,
|
||||
unsigned &NOperandCycles);
|
||||
void FormItineraryBypassString(const std::string &Names,
|
||||
Record *ItinData,
|
||||
std::string &ItinString, unsigned NOperandCycles);
|
||||
void EmitStageAndOperandCycleData(raw_ostream &OS, unsigned NItinClasses,
|
||||
std::map<std::string, unsigned> &ItinClassesMap,
|
||||
std::vector<Record*> &ItinClassList,
|
||||
std::vector<std::vector<InstrItinerary> > &ProcList);
|
||||
void EmitItineraryProp(raw_ostream &OS, const Record *R, const char *Name,
|
||||
char Separator);
|
||||
void EmitProcessorData(raw_ostream &OS,
|
||||
std::vector<Record*> &ItinClassList,
|
||||
std::vector<std::vector<InstrItinerary> > &ProcList);
|
||||
void EmitProcessorLookup(raw_ostream &OS);
|
||||
void EmitData(raw_ostream &OS);
|
||||
void ParseFeaturesFunction(raw_ostream &OS, unsigned NumFeatures,
|
||||
unsigned NumProcs);
|
||||
|
||||
public:
|
||||
SubtargetEmitter(RecordKeeper &R) : Records(R), HasItineraries(false) {}
|
||||
|
||||
// run - Output the subtarget enumerations, returning true on failure.
|
||||
void run(raw_ostream &o);
|
||||
|
||||
};
|
||||
|
||||
|
||||
} // End llvm namespace
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
@ -11,22 +11,9 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "AsmMatcherEmitter.h"
|
||||
#include "AsmWriterEmitter.h"
|
||||
#include "CallingConvEmitter.h"
|
||||
#include "CodeEmitterGen.h"
|
||||
#include "DAGISelEmitter.h"
|
||||
#include "DFAPacketizerEmitter.h"
|
||||
#include "DisassemblerEmitter.h"
|
||||
#include "EDEmitter.h"
|
||||
#include "FastISelEmitter.h"
|
||||
#include "InstrInfoEmitter.h"
|
||||
#include "IntrinsicEmitter.h"
|
||||
#include "PseudoLoweringEmitter.h"
|
||||
#include "RegisterInfoEmitter.h"
|
||||
#include "SubtargetEmitter.h"
|
||||
#include "SetTheory.h"
|
||||
#include "TableGenBackends.h" // Declares all backends.
|
||||
|
||||
#include "SetTheory.h"
|
||||
#include "llvm/Support/CommandLine.h"
|
||||
#include "llvm/Support/PrettyStackTrace.h"
|
||||
#include "llvm/Support/Signals.h"
|
||||
@ -102,7 +89,7 @@ namespace {
|
||||
cl::opt<std::string>
|
||||
Class("class", cl::desc("Print Enum list for this class"),
|
||||
cl::value_desc("class name"));
|
||||
|
||||
|
||||
class LLVMTableGenAction : public TableGenAction {
|
||||
public:
|
||||
bool operator()(raw_ostream &OS, RecordKeeper &Records) {
|
||||
@ -111,49 +98,49 @@ namespace {
|
||||
OS << Records; // No argument, dump all contents
|
||||
break;
|
||||
case GenEmitter:
|
||||
CodeEmitterGen(Records).run(OS);
|
||||
EmitCodeEmitter(Records, OS);
|
||||
break;
|
||||
case GenRegisterInfo:
|
||||
RegisterInfoEmitter(Records).run(OS);
|
||||
EmitRegisterInfo(Records, OS);
|
||||
break;
|
||||
case GenInstrInfo:
|
||||
InstrInfoEmitter(Records).run(OS);
|
||||
EmitInstrInfo(Records, OS);
|
||||
break;
|
||||
case GenCallingConv:
|
||||
CallingConvEmitter(Records).run(OS);
|
||||
EmitCallingConv(Records, OS);
|
||||
break;
|
||||
case GenAsmWriter:
|
||||
AsmWriterEmitter(Records).run(OS);
|
||||
EmitAsmWriter(Records, OS);
|
||||
break;
|
||||
case GenAsmMatcher:
|
||||
AsmMatcherEmitter(Records).run(OS);
|
||||
EmitAsmMatcher(Records, OS);
|
||||
break;
|
||||
case GenDisassembler:
|
||||
DisassemblerEmitter(Records).run(OS);
|
||||
EmitDisassembler(Records, OS);
|
||||
break;
|
||||
case GenPseudoLowering:
|
||||
PseudoLoweringEmitter(Records).run(OS);
|
||||
EmitPseudoLowering(Records, OS);
|
||||
break;
|
||||
case GenDAGISel:
|
||||
DAGISelEmitter(Records).run(OS);
|
||||
EmitDAGISel(Records, OS);
|
||||
break;
|
||||
case GenDFAPacketizer:
|
||||
DFAGen(Records).run(OS);
|
||||
EmitDFAPacketizer(Records, OS);
|
||||
break;
|
||||
case GenFastISel:
|
||||
FastISelEmitter(Records).run(OS);
|
||||
EmitFastISel(Records, OS);
|
||||
break;
|
||||
case GenSubtarget:
|
||||
SubtargetEmitter(Records).run(OS);
|
||||
EmitSubtarget(Records, OS);
|
||||
break;
|
||||
case GenIntrinsic:
|
||||
IntrinsicEmitter(Records).run(OS);
|
||||
EmitIntrinsics(Records, OS);
|
||||
break;
|
||||
case GenTgtIntrinsic:
|
||||
IntrinsicEmitter(Records, true).run(OS);
|
||||
EmitIntrinsics(Records, OS, true);
|
||||
break;
|
||||
case GenEDInfo:
|
||||
EDEmitter(Records).run(OS);
|
||||
EmitEnhancedDisassemblerInfo(Records, OS);
|
||||
break;
|
||||
case PrintEnums:
|
||||
{
|
||||
@ -179,7 +166,7 @@ namespace {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
78
utils/TableGen/TableGenBackends.h
Normal file
78
utils/TableGen/TableGenBackends.h
Normal file
@ -0,0 +1,78 @@
|
||||
//===- TableGenBackends.h - Declarations for LLVM TableGen Backends -------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file contains the declarations for all of the LLVM TableGen
|
||||
// backends. A "TableGen backend" is just a function. See below for a
|
||||
// precise description.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
|
||||
// A TableGen backend is a function that looks like
|
||||
//
|
||||
// EmitFoo(RecordKeeper &RK, raw_ostream &OS /*, anything else you need */ )
|
||||
//
|
||||
// What you do inside of that function is up to you, but it will usually
|
||||
// involve generating C++ code to the provided raw_ostream.
|
||||
//
|
||||
// The RecordKeeper is just a top-level container for an in-memory
|
||||
// representation of the data encoded in the TableGen file. What a TableGen
|
||||
// backend does is walk around that in-memory representation and generate
|
||||
// stuff based on the information it contains.
|
||||
//
|
||||
// The in-memory representation is a node-graph (think of it like JSON but
|
||||
// with a richer ontology of types), where the nodes are subclasses of
|
||||
// Record. The methods `getClass`, `getDef` are the basic interface to
|
||||
// access the node-graph. RecordKeeper also provides a handy method
|
||||
// `getAllDerivedDefinitions`. Consult "include/llvm/TableGen/Record.h" for
|
||||
// the exact interfaces provided by Record's and RecordKeeper.
|
||||
//
|
||||
// A common pattern for TableGen backends is for the EmitFoo function to
|
||||
// instantiate a class which holds some context for the generation process,
|
||||
// and then have most of the work happen in that class's methods. This
|
||||
// pattern partly has historical roots in the previous TableGen backend API
|
||||
// that involved a class and an invocation like `FooEmitter(RK).run(OS)`.
|
||||
//
|
||||
// Remember to wrap private things in an anonymous namespace. For most
|
||||
// backends, this means that the EmitFoo function is the only thing not in
|
||||
// the anonymous namespace.
|
||||
|
||||
|
||||
// FIXME: Reorganize TableGen so that build dependencies can be more
|
||||
// accurately expressed. Currently, touching any of the emitters (or
|
||||
// anything that they transitively depend on) causes everything dependent
|
||||
// on TableGen to be rebuilt (this includes all the targets!). Perhaps have
|
||||
// a standalone TableGen binary and have the backends be loadable modules
|
||||
// of some sort; then the dependency could be expressed as being on the
|
||||
// module, and all the modules would have a common dependency on the
|
||||
// TableGen binary with as few dependencies as possible on the rest of
|
||||
// LLVM.
|
||||
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class raw_ostream;
|
||||
class RecordKeeper;
|
||||
|
||||
void EmitIntrinsics(RecordKeeper &RK, raw_ostream &OS, bool TargetOnly = false);
|
||||
void EmitAsmMatcher(RecordKeeper &RK, raw_ostream &OS);
|
||||
void EmitAsmWriter(RecordKeeper &RK, raw_ostream &OS);
|
||||
void EmitCallingConv(RecordKeeper &RK, raw_ostream &OS);
|
||||
void EmitCodeEmitter(RecordKeeper &RK, raw_ostream &OS);
|
||||
void EmitDAGISel(RecordKeeper &RK, raw_ostream &OS);
|
||||
void EmitDFAPacketizer(RecordKeeper &RK, raw_ostream &OS);
|
||||
void EmitDisassembler(RecordKeeper &RK, raw_ostream &OS);
|
||||
void EmitEnhancedDisassemblerInfo(RecordKeeper &RK, raw_ostream &OS);
|
||||
void EmitFastISel(RecordKeeper &RK, raw_ostream &OS);
|
||||
void EmitInstrInfo(RecordKeeper &RK, raw_ostream &OS);
|
||||
void EmitPseudoLowering(RecordKeeper &RK, raw_ostream &OS);
|
||||
void EmitRegisterInfo(RecordKeeper &RK, raw_ostream &OS);
|
||||
void EmitSubtarget(RecordKeeper &RK, raw_ostream &OS);
|
||||
|
||||
} // End llvm namespace
|
Loading…
Reference in New Issue
Block a user