TableGen.cpp revision 7b9ffe4a6db2e59c18510aac4ba30902653e13eb
1//===- TableGen.cpp - Top-Level TableGen implementation -------------------===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9// 10// TableGen is a tool which can be used to build up a description of something, 11// then invoke one or more "tablegen backends" to emit information about the 12// description in some predefined format. In practice, this is used by the LLVM 13// code generators to automate generation of a code generator through a 14// high-level description of the target. 15// 16//===----------------------------------------------------------------------===// 17 18#include "Record.h" 19#include "TGParser.h" 20#include "llvm/Support/CommandLine.h" 21#include "llvm/Support/Streams.h" 22#include "llvm/System/Signals.h" 23#include "llvm/Support/FileUtilities.h" 24#include "llvm/Support/MemoryBuffer.h" 25#include "llvm/Support/PrettyStackTrace.h" 26#include "CallingConvEmitter.h" 27#include "CodeEmitterGen.h" 28#include "RegisterInfoEmitter.h" 29#include "InstrInfoEmitter.h" 30#include "InstrEnumEmitter.h" 31#include "AsmWriterEmitter.h" 32#include "DAGISelEmitter.h" 33#include "FastISelEmitter.h" 34#include "SubtargetEmitter.h" 35#include "IntrinsicEmitter.h" 36#include "LLVMCConfigurationEmitter.h" 37#include <algorithm> 38#include <cstdio> 39#include <fstream> 40#include <ios> 41using namespace llvm; 42 43enum ActionType { 44 PrintRecords, 45 GenEmitter, 46 GenRegisterEnums, GenRegister, GenRegisterHeader, 47 GenInstrEnums, GenInstrs, GenAsmWriter, 48 GenCallingConv, 49 GenDAGISel, 50 GenFastISel, 51 GenSubtarget, 52 GenIntrinsic, 53 GenTgtIntrinsic, 54 GenLLVMCConf, 55 PrintEnums 56}; 57 58namespace { 59 cl::opt<ActionType> 60 Action(cl::desc("Action to perform:"), 61 cl::values(clEnumValN(PrintRecords, "print-records", 62 "Print all records to stdout (default)"), 63 clEnumValN(GenEmitter, "gen-emitter", 64 "Generate machine code emitter"), 65 clEnumValN(GenRegisterEnums, "gen-register-enums", 66 "Generate enum values for registers"), 67 clEnumValN(GenRegister, "gen-register-desc", 68 "Generate a register info description"), 69 clEnumValN(GenRegisterHeader, "gen-register-desc-header", 70 "Generate a register info description header"), 71 clEnumValN(GenInstrEnums, "gen-instr-enums", 72 "Generate enum values for instructions"), 73 clEnumValN(GenInstrs, "gen-instr-desc", 74 "Generate instruction descriptions"), 75 clEnumValN(GenCallingConv, "gen-callingconv", 76 "Generate calling convention descriptions"), 77 clEnumValN(GenAsmWriter, "gen-asm-writer", 78 "Generate assembly writer"), 79 clEnumValN(GenDAGISel, "gen-dag-isel", 80 "Generate a DAG instruction selector"), 81 clEnumValN(GenFastISel, "gen-fast-isel", 82 "Generate a \"fast\" instruction selector"), 83 clEnumValN(GenSubtarget, "gen-subtarget", 84 "Generate subtarget enumerations"), 85 clEnumValN(GenIntrinsic, "gen-intrinsic", 86 "Generate intrinsic information"), 87 clEnumValN(GenTgtIntrinsic, "gen-tgt-intrinsic", 88 "Generate target intrinsic information"), 89 clEnumValN(GenLLVMCConf, "gen-llvmc", 90 "Generate LLVMC configuration library"), 91 clEnumValN(PrintEnums, "print-enums", 92 "Print enum values for a class"), 93 clEnumValEnd)); 94 95 cl::opt<std::string> 96 Class("class", cl::desc("Print Enum list for this class"), 97 cl::value_desc("class name")); 98 99 cl::opt<std::string> 100 OutputFilename("o", cl::desc("Output filename"), cl::value_desc("filename"), 101 cl::init("-")); 102 103 cl::opt<std::string> 104 InputFilename(cl::Positional, cl::desc("<input file>"), cl::init("-")); 105 106 cl::list<std::string> 107 IncludeDirs("I", cl::desc("Directory of include files"), 108 cl::value_desc("directory"), cl::Prefix); 109} 110 111 112// FIXME: Eliminate globals from tblgen. 113RecordKeeper llvm::Records; 114 115static TGSourceMgr SrcMgr; 116 117void PrintError(TGLoc ErrorLoc, const std::string &Msg) { 118 SrcMgr.PrintError(ErrorLoc, Msg); 119} 120 121 122 123/// ParseFile - this function begins the parsing of the specified tablegen 124/// file. 125static bool ParseFile(const std::string &Filename, 126 const std::vector<std::string> &IncludeDirs, 127 TGSourceMgr &SrcMgr) { 128 std::string ErrorStr; 129 MemoryBuffer *F = MemoryBuffer::getFileOrSTDIN(Filename.c_str(), &ErrorStr); 130 if (F == 0) { 131 cerr << "Could not open input file '" + Filename + "': " << ErrorStr <<"\n"; 132 return true; 133 } 134 135 // Tell SrcMgr about this buffer, which is what TGParser will pick up. 136 SrcMgr.AddNewSourceBuffer(F, TGLoc()); 137 138 TGParser Parser(SrcMgr); 139 140 // Record the location of the include directory so that the lexer can find 141 // it later. 142 Parser.setIncludeDirs(IncludeDirs); 143 144 return Parser.ParseFile(); 145} 146 147int main(int argc, char **argv) { 148 sys::PrintStackTraceOnErrorSignal(); 149 PrettyStackTraceProgram X(argc, argv); 150 cl::ParseCommandLineOptions(argc, argv); 151 152 153 // Parse the input file. 154 if (ParseFile(InputFilename, IncludeDirs, SrcMgr)) 155 return 1; 156 157 std::ostream *Out = cout.stream(); 158 if (OutputFilename != "-") { 159 Out = new std::ofstream(OutputFilename.c_str()); 160 161 if (!Out->good()) { 162 cerr << argv[0] << ": error opening " << OutputFilename << "!\n"; 163 return 1; 164 } 165 166 // Make sure the file gets removed if *gasp* tablegen crashes... 167 sys::RemoveFileOnSignal(sys::Path(OutputFilename)); 168 } 169 170 try { 171 switch (Action) { 172 case PrintRecords: 173 *Out << Records; // No argument, dump all contents 174 break; 175 case GenEmitter: 176 CodeEmitterGen(Records).run(*Out); 177 break; 178 179 case GenRegisterEnums: 180 RegisterInfoEmitter(Records).runEnums(*Out); 181 break; 182 case GenRegister: 183 RegisterInfoEmitter(Records).run(*Out); 184 break; 185 case GenRegisterHeader: 186 RegisterInfoEmitter(Records).runHeader(*Out); 187 break; 188 189 case GenInstrEnums: 190 InstrEnumEmitter(Records).run(*Out); 191 break; 192 case GenInstrs: 193 InstrInfoEmitter(Records).run(*Out); 194 break; 195 case GenCallingConv: 196 CallingConvEmitter(Records).run(*Out); 197 break; 198 case GenAsmWriter: 199 AsmWriterEmitter(Records).run(*Out); 200 break; 201 202 case GenDAGISel: 203 DAGISelEmitter(Records).run(*Out); 204 break; 205 case GenFastISel: 206 FastISelEmitter(Records).run(*Out); 207 break; 208 case GenSubtarget: 209 SubtargetEmitter(Records).run(*Out); 210 break; 211 case GenIntrinsic: 212 IntrinsicEmitter(Records).run(*Out); 213 break; 214 case GenTgtIntrinsic: 215 IntrinsicEmitter(Records, true).run(*Out); 216 break; 217 case GenLLVMCConf: 218 LLVMCConfigurationEmitter(Records).run(*Out); 219 break; 220 case PrintEnums: 221 { 222 std::vector<Record*> Recs = Records.getAllDerivedDefinitions(Class); 223 for (unsigned i = 0, e = Recs.size(); i != e; ++i) 224 *Out << Recs[i]->getName() << ", "; 225 *Out << "\n"; 226 break; 227 } 228 default: 229 assert(1 && "Invalid Action"); 230 return 1; 231 } 232 } catch (const std::string &Error) { 233 cerr << argv[0] << ": " << Error << "\n"; 234 if (Out != cout.stream()) { 235 delete Out; // Close the file 236 std::remove(OutputFilename.c_str()); // Remove the file, it's broken 237 } 238 return 1; 239 } catch (const char *Error) { 240 cerr << argv[0] << ": " << Error << "\n"; 241 if (Out != cout.stream()) { 242 delete Out; // Close the file 243 std::remove(OutputFilename.c_str()); // Remove the file, it's broken 244 } 245 return 1; 246 } catch (...) { 247 cerr << argv[0] << ": Unknown unexpected exception occurred.\n"; 248 if (Out != cout.stream()) { 249 delete Out; // Close the file 250 std::remove(OutputFilename.c_str()); // Remove the file, it's broken 251 } 252 return 2; 253 } 254 255 if (Out != cout.stream()) { 256 delete Out; // Close the file 257 } 258 return 0; 259} 260