X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;f=utils%2FTableGen%2FTableGen.cpp;h=7bd52b37cf06eaf602f9266d0d10d18ab87d39fb;hb=2082ebe8b3a5db302748828ab4f79a36d239c1d9;hp=17f2b2e7181600667299149ec0f71017dcd94bbc;hpb=30709543d2463948d2b6e30a4411a29940cfde69;p=oota-llvm.git diff --git a/utils/TableGen/TableGen.cpp b/utils/TableGen/TableGen.cpp index 17f2b2e7181..7bd52b37cf0 100644 --- a/utils/TableGen/TableGen.cpp +++ b/utils/TableGen/TableGen.cpp @@ -1,15 +1,40 @@ +//===- TableGen.cpp - Top-Level TableGen implementation -------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// TableGen is a tool which can be used to build up a description of something, +// then invoke one or more "tablegen backends" to emit information about the +// description in some predefined format. In practice, this is used by the LLVM +// code generators to automate generation of a code generator through a +// high-level description of the target. +// +//===----------------------------------------------------------------------===// + #include "Record.h" #include "Support/CommandLine.h" -#include "Support/Signals.h" +#include "llvm/System/Signals.h" +#include "Support/FileUtilities.h" #include "CodeEmitterGen.h" +#include "RegisterInfoEmitter.h" +#include "InstrInfoEmitter.h" +#include "InstrSelectorEmitter.h" #include +#include #include +using namespace llvm; enum ActionType { PrintRecords, GenEmitter, + GenRegisterEnums, GenRegister, GenRegisterHeader, + GenInstrEnums, GenInstrs, GenInstrSelector, PrintEnums, - Parse, + Parse }; namespace { @@ -19,25 +44,46 @@ namespace { "Print all records to stdout (default)"), clEnumValN(GenEmitter, "gen-emitter", "Generate machine code emitter"), + clEnumValN(GenRegisterEnums, "gen-register-enums", + "Generate enum values for registers"), + clEnumValN(GenRegister, "gen-register-desc", + "Generate a register info description"), + clEnumValN(GenRegisterHeader, "gen-register-desc-header", + "Generate a register info description header"), + clEnumValN(GenInstrEnums, "gen-instr-enums", + "Generate enum values for instructions"), + clEnumValN(GenInstrs, "gen-instr-desc", + "Generate instruction descriptions"), + clEnumValN(GenInstrSelector, "gen-instr-selector", + "Generate an instruction selector"), clEnumValN(PrintEnums, "print-enums", "Print enum values for a class"), clEnumValN(Parse, "parse", "Interpret machine code (testing only)"), - 0)); + clEnumValEnd)); cl::opt Class("class", cl::desc("Print Enum list for this class"), cl::value_desc("class name")); - cl::opt - OutputFilename("o", cl::desc("Output filename"), cl::value_desc("filename"), - cl::init("-")); -} + cl::opt + OutputFilename("o", cl::desc("Output filename"), cl::value_desc("filename"), + cl::init("-")); + cl::opt + InputFilename(cl::Positional, cl::desc(""), cl::init("-")); -void ParseFile(); + cl::opt + IncludeDir("I", cl::desc("Directory of include files"), + cl::value_desc("directory"), cl::init("")); +} + +namespace llvm { + void ParseFile(const std::string &Filename, + const std::string &IncludeDir); +} -RecordKeeper Records; +RecordKeeper llvm::Records; static Init *getBit(Record *R, unsigned BitNo) { const std::vector &V = R->getValues(); @@ -52,7 +98,7 @@ static Init *getBit(Record *R, unsigned BitNo) { } std::cerr << "Cannot find requested bit!\n"; - abort(); + exit(1); return 0; } @@ -157,9 +203,9 @@ static unsigned getFirstFixedBitInSequence(std::vector::iterator IB, } // ParseMachineCode - Try to split the vector of instructions (which is -// intentially taken by-copy) in half, narrowing down the possible instructions -// that we may have found. Eventually, this list will get pared down to zero or -// one instruction, in which case we have a match or failure. +// intentionally taken by-copy) in half, narrowing down the possible +// instructions that we may have found. Eventually, this list will get pared +// down to zero or one instruction, in which case we have a match or failure. // static Record *ParseMachineCode(std::vector::iterator InstsB, std::vector::iterator InstsE, @@ -171,7 +217,7 @@ static Record *ParseMachineCode(std::vector::iterator InstsB, for (unsigned i = 0, e = getNumBits(Inst); i != e; ++i) if (BitInit *BI = dynamic_cast(getBit(Inst, i))) if (getMemoryBit(M, i) != BI->getValue()) - return 0; + throw std::string("Parse failed!\n"); return Inst; } @@ -228,7 +274,7 @@ static Record *ParseMachineCode(std::vector::iterator InstsB, if (RangeBegin == InstsB && RangeEnd == InstsE) { std::cerr << "Error: Could not distinguish among the following insts!:\n"; PrintRange(InstsB, InstsE); - abort(); + exit(1); } #if 0 @@ -350,24 +396,11 @@ static void ParseMachineCode() { }; #endif - std::vector Insts; - - const std::map &Defs = Records.getDefs(); - Record *Inst = Records.getClass("Instruction"); - assert(Inst && "Couldn't find Instruction class!"); - - for (std::map::const_iterator I = Defs.begin(), - E = Defs.end(); I != E; ++I) - if (I->second->isSubClassOf(Inst)) - Insts.push_back(I->second); + std::vector Insts = Records.getAllDerivedDefinitions("Instruction"); unsigned char *BuffPtr = Buffer; while (1) { Record *R = ParseMachineCode(Insts.begin(), Insts.end(), BuffPtr); - if (R == 0) { - std::cout << "Parse failed!\n"; - return; - } PrintInstruction(R, BuffPtr); unsigned Bits = getNumBits(R); @@ -376,10 +409,9 @@ static void ParseMachineCode() { } } - int main(int argc, char **argv) { cl::ParseCommandLineOptions(argc, argv); - ParseFile(); + ParseFile(InputFilename, IncludeDir); std::ostream *Out = &std::cout; if (OutputFilename != "-") { @@ -394,34 +426,60 @@ int main(int argc, char **argv) { RemoveFileOnSignal(OutputFilename); } - int ErrorCode = 0; - - switch (Action) { - case Parse: ParseMachineCode(); break; - case GenEmitter: - ErrorCode = CodeEmitterGen(Records).createEmitter(*Out); - break; - case PrintRecords: - *Out << Records; // No argument, dump all contents - break; - case PrintEnums: - Record *R = Records.getClass(Class); - if (R == 0) { - std::cerr << "Cannot find class '" << Class << "'!\n"; - abort(); + try { + switch (Action) { + case PrintRecords: + *Out << Records; // No argument, dump all contents + break; + case Parse: + ParseMachineCode(); + break; + case GenEmitter: + CodeEmitterGen(Records).run(*Out); + break; + + case GenRegisterEnums: + RegisterInfoEmitter(Records).runEnums(*Out); + break; + case GenRegister: + RegisterInfoEmitter(Records).run(*Out); + break; + case GenRegisterHeader: + RegisterInfoEmitter(Records).runHeader(*Out); + break; + + case GenInstrEnums: + InstrInfoEmitter(Records).runEnums(*Out); + break; + case GenInstrs: + InstrInfoEmitter(Records).run(*Out); + break; + case GenInstrSelector: + InstrSelectorEmitter(Records).run(*Out); + break; + case PrintEnums: + { + std::vector Recs = Records.getAllDerivedDefinitions(Class); + for (unsigned i = 0, e = Recs.size(); i != e; ++i) + *Out << Recs[i]->getName() << ", "; + *Out << "\n"; + break; } - - const std::map &Defs = Records.getDefs(); - for (std::map::const_iterator I = Defs.begin(), - E = Defs.end(); I != E; ++I) { - if (I->second->isSubClassOf(R)) { - *Out << I->first << ", "; - } + default: + assert(1 && "Invalid Action"); + return 1; + } + } catch (const std::string &Error) { + std::cerr << Error << "\n"; + if (Out != &std::cout) { + delete Out; // Close the file + std::remove(OutputFilename.c_str()); // Remove the file, it's broken } - *Out << "\n"; - break; + return 1; } - if (Out != &std::cout) delete Out; - return ErrorCode; + if (Out != &std::cout) { + delete Out; // Close the file + } + return 0; }