TableGen.cpp revision 208954
155682Smarkm//===- TableGen.cpp - Top-Level TableGen implementation -------------------===// 255682Smarkm// 355682Smarkm// The LLVM Compiler Infrastructure 455682Smarkm// 555682Smarkm// This file is distributed under the University of Illinois Open Source 655682Smarkm// License. See LICENSE.TXT for details. 755682Smarkm// 8233294Sstas//===----------------------------------------------------------------------===// 9102644Snectar// 10102644Snectar// TableGen is a tool which can be used to build up a description of something, 11178825Sdfr// then invoke one or more "tablegen backends" to emit information about the 12102644Snectar// description in some predefined format. In practice, this is used by the LLVM 13233294Sstas// code generators to automate generation of a code generator through a 14178825Sdfr// high-level description of the target. 1555682Smarkm// 16178825Sdfr//===----------------------------------------------------------------------===// 17178825Sdfr 18178825Sdfr#include "AsmMatcherEmitter.h" 19178825Sdfr#include "AsmWriterEmitter.h" 20178825Sdfr#include "CallingConvEmitter.h" 21233294Sstas#include "ClangASTNodesEmitter.h" 22233294Sstas#include "ClangDiagnosticsEmitter.h" 23233294Sstas#include "CodeEmitterGen.h" 24233294Sstas#include "DAGISelEmitter.h" 25233294Sstas#include "DisassemblerEmitter.h" 26233294Sstas#include "EDEmitter.h" 27178825Sdfr#include "FastISelEmitter.h" 28178825Sdfr#include "InstrEnumEmitter.h" 29178825Sdfr#include "InstrInfoEmitter.h" 30178825Sdfr#include "IntrinsicEmitter.h" 31178825Sdfr#include "LLVMCConfigurationEmitter.h" 32178825Sdfr#include "OptParserEmitter.h" 33178825Sdfr#include "Record.h" 34178825Sdfr#include "RegisterInfoEmitter.h" 35178825Sdfr#include "ARMDecoderEmitter.h" 36178825Sdfr#include "SubtargetEmitter.h" 37178825Sdfr#include "TGParser.h" 38178825Sdfr#include "llvm/Support/CommandLine.h" 39178825Sdfr#include "llvm/Support/MemoryBuffer.h" 40178825Sdfr#include "llvm/Support/PrettyStackTrace.h" 41178825Sdfr#include "llvm/Support/raw_ostream.h" 42178825Sdfr#include "llvm/System/Signals.h" 43178825Sdfr#include <algorithm> 44178825Sdfr#include <cstdio> 45178825Sdfrusing namespace llvm; 46178825Sdfr 47178825Sdfrenum ActionType { 4855682Smarkm PrintRecords, 49102644Snectar GenEmitter, 50102644Snectar GenRegisterEnums, GenRegister, GenRegisterHeader, 51102644Snectar GenInstrEnums, GenInstrs, GenAsmWriter, GenAsmMatcher, 52178825Sdfr GenARMDecoder, 5355682Smarkm GenDisassembler, 5455682Smarkm GenCallingConv, 55102644Snectar GenClangDiagsDefs, 56102644Snectar GenClangDiagGroups, 57102644Snectar GenClangStmtNodes, 58102644Snectar GenDAGISel, 59178825Sdfr GenFastISel, 6055682Smarkm GenOptParserDefs, GenOptParserImpl, 6155682Smarkm 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