TableGen.cpp revision 208599
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 "AsmMatcherEmitter.h" 19#include "AsmWriterEmitter.h" 20#include "CallingConvEmitter.h" 21#include "ClangASTNodesEmitter.h" 22#include "ClangDiagnosticsEmitter.h" 23#include "CodeEmitterGen.h" 24#include "DAGISelEmitter.h" 25#include "DisassemblerEmitter.h" 26#include "EDEmitter.h" 27#include "FastISelEmitter.h" 28#include "InstrEnumEmitter.h" 29#include "InstrInfoEmitter.h" 30#include "IntrinsicEmitter.h" 31#include "LLVMCConfigurationEmitter.h" 32#include "OptParserEmitter.h" 33#include "Record.h" 34#include "RegisterInfoEmitter.h" 35#include "ARMDecoderEmitter.h" 36#include "SubtargetEmitter.h" 37#include "TGParser.h" 38#include "llvm/Support/CommandLine.h" 39#include "llvm/Support/MemoryBuffer.h" 40#include "llvm/Support/PrettyStackTrace.h" 41#include "llvm/Support/raw_ostream.h" 42#include "llvm/System/Signals.h" 43#include <algorithm> 44#include <cstdio> 45using namespace llvm; 46 47enum ActionType { 48 PrintRecords, 49 GenEmitter, 50 GenRegisterEnums, GenRegister, GenRegisterHeader, 51 GenInstrEnums, GenInstrs, GenAsmWriter, GenAsmMatcher, 52 GenARMDecoder, 53 GenDisassembler, 54 GenCallingConv, 55 GenClangDiagsDefs, 56 GenClangDiagGroups, 57 GenClangStmtNodes, 58 GenDAGISel, 59 GenFastISel, 60 GenOptParserDefs, GenOptParserImpl, 61 GenSubtarget, 62 GenIntrinsic, 63 GenTgtIntrinsic, 64 GenLLVMCConf, 65 GenEDHeader, GenEDInfo, 66 PrintEnums 67}; 68 69namespace { 70 cl::opt<ActionType> 71 Action(cl::desc("Action to perform:"), 72 cl::values(clEnumValN(PrintRecords, "print-records", 73 "Print all records to stdout (default)"), 74 clEnumValN(GenEmitter, "gen-emitter", 75 "Generate machine code emitter"), 76 clEnumValN(GenRegisterEnums, "gen-register-enums", 77 "Generate enum values for registers"), 78 clEnumValN(GenRegister, "gen-register-desc", 79 "Generate a register info description"), 80 clEnumValN(GenRegisterHeader, "gen-register-desc-header", 81 "Generate a register info description header"), 82 clEnumValN(GenInstrEnums, "gen-instr-enums", 83 "Generate enum values for instructions"), 84 clEnumValN(GenInstrs, "gen-instr-desc", 85 "Generate instruction descriptions"), 86 clEnumValN(GenCallingConv, "gen-callingconv", 87 "Generate calling convention descriptions"), 88 clEnumValN(GenAsmWriter, "gen-asm-writer", 89 "Generate assembly writer"), 90 clEnumValN(GenARMDecoder, "gen-arm-decoder", 91 "Generate decoders for ARM/Thumb"), 92 clEnumValN(GenDisassembler, "gen-disassembler", 93 "Generate disassembler"), 94 clEnumValN(GenAsmMatcher, "gen-asm-matcher", 95 "Generate assembly instruction matcher"), 96 clEnumValN(GenDAGISel, "gen-dag-isel", 97 "Generate a DAG instruction selector"), 98 clEnumValN(GenFastISel, "gen-fast-isel", 99 "Generate a \"fast\" instruction selector"), 100 clEnumValN(GenOptParserDefs, "gen-opt-parser-defs", 101 "Generate option definitions"), 102 clEnumValN(GenOptParserImpl, "gen-opt-parser-impl", 103 "Generate option parser implementation"), 104 clEnumValN(GenSubtarget, "gen-subtarget", 105 "Generate subtarget enumerations"), 106 clEnumValN(GenIntrinsic, "gen-intrinsic", 107 "Generate intrinsic information"), 108 clEnumValN(GenTgtIntrinsic, "gen-tgt-intrinsic", 109 "Generate target intrinsic information"), 110 clEnumValN(GenClangDiagsDefs, "gen-clang-diags-defs", 111 "Generate Clang diagnostics definitions"), 112 clEnumValN(GenClangDiagGroups, "gen-clang-diag-groups", 113 "Generate Clang diagnostic groups"), 114 clEnumValN(GenClangStmtNodes, "gen-clang-stmt-nodes", 115 "Generate Clang AST statement nodes"), 116 clEnumValN(GenLLVMCConf, "gen-llvmc", 117 "Generate LLVMC configuration library"), 118 clEnumValN(GenEDHeader, "gen-enhanced-disassembly-header", 119 "Generate enhanced disassembly info header"), 120 clEnumValN(GenEDInfo, "gen-enhanced-disassembly-info", 121 "Generate enhanced disassembly info"), 122 clEnumValN(PrintEnums, "print-enums", 123 "Print enum values for a class"), 124 clEnumValEnd)); 125 126 cl::opt<std::string> 127 Class("class", cl::desc("Print Enum list for this class"), 128 cl::value_desc("class name")); 129 130 cl::opt<std::string> 131 OutputFilename("o", cl::desc("Output filename"), cl::value_desc("filename"), 132 cl::init("-")); 133 134 cl::opt<std::string> 135 InputFilename(cl::Positional, cl::desc("<input file>"), cl::init("-")); 136 137 cl::list<std::string> 138 IncludeDirs("I", cl::desc("Directory of include files"), 139 cl::value_desc("directory"), cl::Prefix); 140 141 cl::opt<std::string> 142 ClangComponent("clang-component", 143 cl::desc("Only use warnings from specified component"), 144 cl::value_desc("component"), cl::Hidden); 145} 146 147 148// FIXME: Eliminate globals from tblgen. 149RecordKeeper llvm::Records; 150 151static SourceMgr SrcMgr; 152 153void llvm::PrintError(SMLoc ErrorLoc, const std::string &Msg) { 154 SrcMgr.PrintMessage(ErrorLoc, Msg, "error"); 155} 156 157 158 159/// ParseFile - this function begins the parsing of the specified tablegen 160/// file. 161static bool ParseFile(const std::string &Filename, 162 const std::vector<std::string> &IncludeDirs, 163 SourceMgr &SrcMgr) { 164 std::string ErrorStr; 165 MemoryBuffer *F = MemoryBuffer::getFileOrSTDIN(Filename.c_str(), &ErrorStr); 166 if (F == 0) { 167 errs() << "Could not open input file '" << Filename << "': " 168 << ErrorStr <<"\n"; 169 return true; 170 } 171 172 // Tell SrcMgr about this buffer, which is what TGParser will pick up. 173 SrcMgr.AddNewSourceBuffer(F, SMLoc()); 174 175 // Record the location of the include directory so that the lexer can find 176 // it later. 177 SrcMgr.setIncludeDirs(IncludeDirs); 178 179 TGParser Parser(SrcMgr); 180 181 return Parser.ParseFile(); 182} 183 184int main(int argc, char **argv) { 185 sys::PrintStackTraceOnErrorSignal(); 186 PrettyStackTraceProgram X(argc, argv); 187 cl::ParseCommandLineOptions(argc, argv); 188 189 190 // Parse the input file. 191 if (ParseFile(InputFilename, IncludeDirs, SrcMgr)) 192 return 1; 193 194 raw_ostream *Out = &outs(); 195 if (OutputFilename != "-") { 196 std::string Error; 197 Out = new raw_fd_ostream(OutputFilename.c_str(), Error); 198 199 if (!Error.empty()) { 200 errs() << argv[0] << ": error opening " << OutputFilename 201 << ":" << Error << "\n"; 202 return 1; 203 } 204 205 // Make sure the file gets removed if *gasp* tablegen crashes... 206 sys::RemoveFileOnSignal(sys::Path(OutputFilename)); 207 } 208 209 try { 210 switch (Action) { 211 case PrintRecords: 212 *Out << Records; // No argument, dump all contents 213 break; 214 case GenEmitter: 215 CodeEmitterGen(Records).run(*Out); 216 break; 217 218 case GenRegisterEnums: 219 RegisterInfoEmitter(Records).runEnums(*Out); 220 break; 221 case GenRegister: 222 RegisterInfoEmitter(Records).run(*Out); 223 break; 224 case GenRegisterHeader: 225 RegisterInfoEmitter(Records).runHeader(*Out); 226 break; 227 case GenInstrEnums: 228 InstrEnumEmitter(Records).run(*Out); 229 break; 230 case GenInstrs: 231 InstrInfoEmitter(Records).run(*Out); 232 break; 233 case GenCallingConv: 234 CallingConvEmitter(Records).run(*Out); 235 break; 236 case GenAsmWriter: 237 AsmWriterEmitter(Records).run(*Out); 238 break; 239 case GenARMDecoder: 240 ARMDecoderEmitter(Records).run(*Out); 241 break; 242 case GenAsmMatcher: 243 AsmMatcherEmitter(Records).run(*Out); 244 break; 245 case GenClangDiagsDefs: 246 ClangDiagsDefsEmitter(Records, ClangComponent).run(*Out); 247 break; 248 case GenClangDiagGroups: 249 ClangDiagGroupsEmitter(Records).run(*Out); 250 break; 251 case GenClangStmtNodes: 252 ClangStmtNodesEmitter(Records).run(*Out); 253 break; 254 case GenDisassembler: 255 DisassemblerEmitter(Records).run(*Out); 256 break; 257 case GenOptParserDefs: 258 OptParserEmitter(Records, true).run(*Out); 259 break; 260 case GenOptParserImpl: 261 OptParserEmitter(Records, false).run(*Out); 262 break; 263 case GenDAGISel: 264 DAGISelEmitter(Records).run(*Out); 265 break; 266 case GenFastISel: 267 FastISelEmitter(Records).run(*Out); 268 break; 269 case GenSubtarget: 270 SubtargetEmitter(Records).run(*Out); 271 break; 272 case GenIntrinsic: 273 IntrinsicEmitter(Records).run(*Out); 274 break; 275 case GenTgtIntrinsic: 276 IntrinsicEmitter(Records, true).run(*Out); 277 break; 278 case GenLLVMCConf: 279 LLVMCConfigurationEmitter(Records).run(*Out); 280 break; 281 case GenEDHeader: 282 EDEmitter(Records).runHeader(*Out); 283 break; 284 case GenEDInfo: 285 EDEmitter(Records).run(*Out); 286 break; 287 case PrintEnums: 288 { 289 std::vector<Record*> Recs = Records.getAllDerivedDefinitions(Class); 290 for (unsigned i = 0, e = Recs.size(); i != e; ++i) 291 *Out << Recs[i]->getName() << ", "; 292 *Out << "\n"; 293 break; 294 } 295 default: 296 assert(1 && "Invalid Action"); 297 return 1; 298 } 299 300 if (Out != &outs()) 301 delete Out; // Close the file 302 return 0; 303 304 } catch (const TGError &Error) { 305 errs() << argv[0] << ": error:\n"; 306 PrintError(Error.getLoc(), Error.getMessage()); 307 308 } catch (const std::string &Error) { 309 errs() << argv[0] << ": " << Error << "\n"; 310 } catch (const char *Error) { 311 errs() << argv[0] << ": " << Error << "\n"; 312 } catch (...) { 313 errs() << argv[0] << ": Unknown unexpected exception occurred.\n"; 314 } 315 316 if (Out != &outs()) { 317 delete Out; // Close the file 318 std::remove(OutputFilename.c_str()); // Remove the file, it's broken 319 } 320 return 1; 321} 322