Newer
Older
//===- InstrInfoEmitter.cpp - Generate a Instruction Set Desc. ------------===//
// 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.
//
//===----------------------------------------------------------------------===//
#include "InstrInfoEmitter.h"
#include "CodeGenTarget.h"
#include "llvm/ADT/StringExtras.h"
static void PrintDefList(const std::vector<Record*> &Uses,
unsigned Num, raw_ostream &OS) {
Chris Lattner
committed
OS << "static const unsigned ImplicitList" << Num << "[] = { ";
for (unsigned i = 0, e = Uses.size(); i != e; ++i)
OS << getQualifiedName(Uses[i]) << ", ";
Evan Cheng
committed
static void PrintBarriers(std::vector<Record*> &Barriers,
unsigned Num, raw_ostream &OS) {
Evan Cheng
committed
OS << "static const TargetRegisterClass* Barriers" << Num << "[] = { ";
for (unsigned i = 0, e = Barriers.size(); i != e; ++i)
OS << "&" << getQualifiedName(Barriers[i]) << "RegClass, ";
OS << "NULL };\n";
}
//===----------------------------------------------------------------------===//
// Instruction Itinerary Information.
//===----------------------------------------------------------------------===//
void InstrInfoEmitter::GatherItinClasses() {
std::vector<Record*> DefList =
Records.getAllDerivedDefinitions("InstrItinClass");
std::sort(DefList.begin(), DefList.end(), LessRecord());
for (unsigned i = 0, N = DefList.size(); i < N; i++)
ItinClassMap[DefList[i]->getName()] = i;
}
unsigned InstrInfoEmitter::getItinClassNumber(const Record *InstRec) {
return ItinClassMap[InstRec->getValueAsDef("Itinerary")->getName()];
}
//===----------------------------------------------------------------------===//
// Operand Info Emission.
//===----------------------------------------------------------------------===//
Chris Lattner
committed
std::vector<std::string>
InstrInfoEmitter::GetOperandInfo(const CodeGenInstruction &Inst) {
std::vector<std::string> Result;
Chris Lattner
committed
for (unsigned i = 0, e = Inst.OperandList.size(); i != e; ++i) {
Chris Lattner
committed
// Handle aggregate operands and normal operands the same way by expanding
// either case into a list of operands for this op.
std::vector<CodeGenInstruction::OperandInfo> OperandList;
// This might be a multiple operand thing. Targets like X86 have
// registers in their multi-operand operands. It may also be an anonymous
// operand, which has a single operand, but no declared class for the
// operand.
DagInit *MIOI = Inst.OperandList[i].MIOperandInfo;
if (!MIOI || MIOI->getNumArgs() == 0) {
// Single, anonymous, operand.
OperandList.push_back(Inst.OperandList[i]);
} else {
for (unsigned j = 0, e = Inst.OperandList[i].MINumOperands; j != e; ++j) {
Chris Lattner
committed
OperandList.push_back(Inst.OperandList[i]);
Chris Lattner
committed
Chris Lattner
committed
Record *OpR = dynamic_cast<DefInit*>(MIOI->getArg(j))->getDef();
OperandList.back().Rec = OpR;
}
}
Chris Lattner
committed
for (unsigned j = 0, e = OperandList.size(); j != e; ++j) {
Record *OpR = OperandList[j].Rec;
std::string Res;
if (OpR->isSubClassOf("RegisterClass"))
Res += getQualifiedName(OpR) + "RegClassID, ";
else if (OpR->isSubClassOf("PointerLikeRegClass"))
Res += utostr(OpR->getValueAsInt("RegClassKind")) + ", ";
Chris Lattner
committed
else
Res += "0, ";
Chris Lattner
committed
// Fill in applicable flags.
Res += "0";
Chris Lattner
committed
Chris Lattner
committed
// Ptr value whose register class is resolved via callback.
if (OpR->isSubClassOf("PointerLikeRegClass"))
Res += "|(1<<TOI::LookupPtrRegClass)";
Chris Lattner
committed
// Predicate operands. Check to see if the original unexpanded operand
// was of type PredicateOperand.
if (Inst.OperandList[i].Rec->isSubClassOf("PredicateOperand"))
Res += "|(1<<TOI::Predicate)";
Chris Lattner
committed
// Optional def operands. Check to see if the original unexpanded operand
// was of type OptionalDefOperand.
if (Inst.OperandList[i].Rec->isSubClassOf("OptionalDefOperand"))
Res += "|(1<<TOI::OptionalDef)";
Chris Lattner
committed
// Fill in constraint info.
Res += ", ";
const CodeGenInstruction::ConstraintInfo &Constraint =
Inst.OperandList[i].Constraints[j];
if (Constraint.isNone())
Res += "0";
else if (Constraint.isEarlyClobber())
Res += "(1 << TOI::EARLY_CLOBBER)";
else {
assert(Constraint.isTied());
Res += "((" + utostr(Constraint.getTiedOperand()) +
" << 16) | (1 << TOI::TIED_TO))";
}
Chris Lattner
committed
Result.push_back(Res);
}
}
return Result;
}
void InstrInfoEmitter::EmitOperandInfo(raw_ostream &OS,
OperandInfoMapTy &OperandInfoIDs) {
// ID #0 is for no operand info.
unsigned OperandListNum = 0;
OperandInfoIDs[std::vector<std::string>()] = ++OperandListNum;
OS << "\n";
const CodeGenTarget &Target = CDP.getTargetInfo();
for (CodeGenTarget::inst_iterator II = Target.inst_begin(),
E = Target.inst_end(); II != E; ++II) {
std::vector<std::string> OperandInfo = GetOperandInfo(**II);
unsigned &N = OperandInfoIDs[OperandInfo];
if (N != 0) continue;
N = ++OperandListNum;
OS << "static const TargetOperandInfo OperandInfo" << N << "[] = { ";
for (unsigned i = 0, e = OperandInfo.size(); i != e; ++i)
OS << "{ " << OperandInfo[i] << " }, ";
OS << "};\n";
}
}
Evan Cheng
committed
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
void InstrInfoEmitter::DetectRegisterClassBarriers(std::vector<Record*> &Defs,
const std::vector<CodeGenRegisterClass> &RCs,
std::vector<Record*> &Barriers) {
std::set<Record*> DefSet;
unsigned NumDefs = Defs.size();
for (unsigned i = 0; i < NumDefs; ++i)
DefSet.insert(Defs[i]);
for (unsigned i = 0, e = RCs.size(); i != e; ++i) {
const CodeGenRegisterClass &RC = RCs[i];
unsigned NumRegs = RC.Elements.size();
if (NumRegs > NumDefs)
continue; // Can't possibly clobber this RC.
bool Clobber = true;
for (unsigned j = 0; j < NumRegs; ++j) {
Record *Reg = RC.Elements[j];
if (!DefSet.count(Reg)) {
Clobber = false;
break;
}
}
if (Clobber)
Barriers.push_back(RC.TheDef);
}
}
//===----------------------------------------------------------------------===//
// Main Output.
//===----------------------------------------------------------------------===//
// run - Emit the main instruction description records for the target...
void InstrInfoEmitter::run(raw_ostream &OS) {
EmitSourceFileHeader("Target Instruction Descriptors", OS);
OS << "namespace llvm {\n\n";
CodeGenTarget &Target = CDP.getTargetInfo();
const std::string &TargetName = Target.getName();
Record *InstrInfo = Target.getInstructionSet();
Evan Cheng
committed
const std::vector<CodeGenRegisterClass> &RCs = Target.getRegisterClasses();
Chris Lattner
committed
// Keep track of all of the def lists we have emitted already.
std::map<std::vector<Record*>, unsigned> EmittedLists;
unsigned ListNumber = 0;
Evan Cheng
committed
std::map<std::vector<Record*>, unsigned> EmittedBarriers;
unsigned BarrierNumber = 0;
std::map<Record*, unsigned> BarriersMap;
Chris Lattner
committed
// Emit all of the instruction's implicit uses and defs.
for (CodeGenTarget::inst_iterator II = Target.inst_begin(),
E = Target.inst_end(); II != E; ++II) {
Record *Inst = (*II)->TheDef;
Chris Lattner
committed
std::vector<Record*> Uses = Inst->getValueAsListOfDefs("Uses");
if (!Uses.empty()) {
Chris Lattner
committed
unsigned &IL = EmittedLists[Uses];
Chris Lattner
committed
}
Chris Lattner
committed
std::vector<Record*> Defs = Inst->getValueAsListOfDefs("Defs");
if (!Defs.empty()) {
Evan Cheng
committed
std::vector<Record*> RCBarriers;
DetectRegisterClassBarriers(Defs, RCs, RCBarriers);
if (!RCBarriers.empty()) {
unsigned &IB = EmittedBarriers[RCBarriers];
if (!IB) PrintBarriers(RCBarriers, IB = ++BarrierNumber, OS);
BarriersMap.insert(std::make_pair(Inst, IB));
}
Chris Lattner
committed
unsigned &IL = EmittedLists[Defs];
Chris Lattner
committed
}
// Emit all of the operand info records.
EmitOperandInfo(OS, OperandInfoIDs);
// Emit all of the TargetInstrDesc records in their ENUM ordering.
OS << "\nstatic const TargetInstrDesc " << TargetName
const std::vector<const CodeGenInstruction*> &NumberedInstructions =
Target.getInstructionsByEnumValue();
for (unsigned i = 0, e = NumberedInstructions.size(); i != e; ++i)
emitRecord(*NumberedInstructions[i], i, InstrInfo, EmittedLists,
Evan Cheng
committed
BarriersMap, OperandInfoIDs, OS);
OS << "} // End llvm namespace \n";
void InstrInfoEmitter::emitRecord(const CodeGenInstruction &Inst, unsigned Num,
Chris Lattner
committed
Record *InstrInfo,
Chris Lattner
committed
std::map<std::vector<Record*>, unsigned> &EmittedLists,
Evan Cheng
committed
std::map<Record*, unsigned> &BarriersMap,
Chris Lattner
committed
int MinOperands = 0;
if (!Inst.OperandList.empty())
Chris Lattner
committed
// Each logical operand can be multiple MI operands.
MinOperands = Inst.OperandList.back().MIOperandNo +
Chris Lattner
committed
Inst.OperandList.back().MINumOperands;
OS << Num << ",\t" << MinOperands << ",\t"
<< Inst.NumDefs << ",\t" << getItinClassNumber(Inst.TheDef)
<< ",\t\"" << Inst.TheDef->getName() << "\", 0";
// Emit all of the target indepedent flags...
Bill Wendling
committed
if (Inst.isReturn) OS << "|(1<<TID::Return)";
if (Inst.isBranch) OS << "|(1<<TID::Branch)";
if (Inst.isIndirectBranch) OS << "|(1<<TID::IndirectBranch)";
if (Inst.isBarrier) OS << "|(1<<TID::Barrier)";
if (Inst.hasDelaySlot) OS << "|(1<<TID::DelaySlot)";
if (Inst.isCall) OS << "|(1<<TID::Call)";
if (Inst.canFoldAsLoad) OS << "|(1<<TID::FoldableAsLoad)";
Bill Wendling
committed
if (Inst.mayLoad) OS << "|(1<<TID::MayLoad)";
if (Inst.mayStore) OS << "|(1<<TID::MayStore)";
if (Inst.isPredicable) OS << "|(1<<TID::Predicable)";
if (Inst.isConvertibleToThreeAddress) OS << "|(1<<TID::ConvertibleTo3Addr)";
Bill Wendling
committed
if (Inst.isCommutable) OS << "|(1<<TID::Commutable)";
if (Inst.isTerminator) OS << "|(1<<TID::Terminator)";
if (Inst.isReMaterializable) OS << "|(1<<TID::Rematerializable)";
if (Inst.isNotDuplicable) OS << "|(1<<TID::NotDuplicable)";
if (Inst.hasOptionalDef) OS << "|(1<<TID::HasOptionalDef)";
if (Inst.usesCustomInserter) OS << "|(1<<TID::UsesCustomInserter)";
if (Inst.isVariadic) OS << "|(1<<TID::Variadic)";
Bill Wendling
committed
if (Inst.hasSideEffects) OS << "|(1<<TID::UnmodeledSideEffects)";
if (Inst.isAsCheapAsAMove) OS << "|(1<<TID::CheapAsAMove)";
if (Inst.hasExtraSrcRegAllocReq) OS << "|(1<<TID::ExtraSrcRegAllocReq)";
if (Inst.hasExtraDefRegAllocReq) OS << "|(1<<TID::ExtraDefRegAllocReq)";
// Emit all of the target-specific flags...
Jakob Stoklund Olesen
committed
BitsInit *TSF = Inst.TheDef->getValueAsBitsInit("TSFlags");
if (!TSF) throw "no TSFlags?";
uint64_t Value = 0;
for (unsigned i = 0, e = TSF->getNumBits(); i != e; ++i) {
if (BitInit *Bit = dynamic_cast<BitInit*>(TSF->getBit(i)))
Value |= uint64_t(Bit->getValue()) << i;
else
throw "Invalid TSFlags bit in " + Inst.TheDef->getName();
}
OS << ", 0x";
OS.write_hex(Value);
// Emit the implicit uses and defs lists...
Chris Lattner
committed
std::vector<Record*> UseList = Inst.TheDef->getValueAsListOfDefs("Uses");
if (UseList.empty())
OS << "NULL, ";
Chris Lattner
committed
OS << "ImplicitList" << EmittedLists[UseList] << ", ";
Chris Lattner
committed
std::vector<Record*> DefList = Inst.TheDef->getValueAsListOfDefs("Defs");
if (DefList.empty())
OS << "NULL, ";
Chris Lattner
committed
OS << "ImplicitList" << EmittedLists[DefList] << ", ";
Evan Cheng
committed
std::map<Record*, unsigned>::iterator BI = BarriersMap.find(Inst.TheDef);
if (BI == BarriersMap.end())
OS << "NULL, ";
else
OS << "Barriers" << BI->second << ", ";
// Emit the operand info.
Chris Lattner
committed
std::vector<std::string> OperandInfo = GetOperandInfo(Inst);
if (OperandInfo.empty())
OS << "0";
OS << "OperandInfo" << OpInfo.find(OperandInfo)->second;
Jakob Stoklund Olesen
committed
OS << " }, // Inst #" << Num << " = " << Inst.TheDef->getName() << "\n";