TableGen.cpp revision 210299
1214501Srpaulo//===- TableGen.cpp - Top-Level TableGen implementation -------------------===// 2214501Srpaulo// 3214501Srpaulo// The LLVM Compiler Infrastructure 4214501Srpaulo// 5214501Srpaulo// This file is distributed under the University of Illinois Open Source 6214501Srpaulo// License. See LICENSE.TXT for details. 7214501Srpaulo// 8214501Srpaulo//===----------------------------------------------------------------------===// 9214501Srpaulo// 10214501Srpaulo// TableGen is a tool which can be used to build up a description of something, 11214501Srpaulo// then invoke one or more "tablegen backends" to emit information about the 12214501Srpaulo// description in some predefined format. In practice, this is used by the LLVM 13214501Srpaulo// code generators to automate generation of a code generator through a 14214501Srpaulo// high-level description of the target. 15214501Srpaulo// 16214501Srpaulo//===----------------------------------------------------------------------===// 17214501Srpaulo 18214501Srpaulo#include "AsmMatcherEmitter.h" 19214501Srpaulo#include "AsmWriterEmitter.h" 20214501Srpaulo#include "CallingConvEmitter.h" 21214501Srpaulo#include "ClangASTNodesEmitter.h" 22214501Srpaulo#include "ClangAttrEmitter.h" 23214501Srpaulo#include "ClangDiagnosticsEmitter.h" 24214501Srpaulo#include "CodeEmitterGen.h" 25214501Srpaulo#include "DAGISelEmitter.h" 26214501Srpaulo#include "DisassemblerEmitter.h" 27214501Srpaulo#include "EDEmitter.h" 28214501Srpaulo#include "FastISelEmitter.h" 29214501Srpaulo#include "InstrEnumEmitter.h" 30214501Srpaulo#include "InstrInfoEmitter.h" 31214501Srpaulo#include "IntrinsicEmitter.h" 32214501Srpaulo#include "LLVMCConfigurationEmitter.h" 33214501Srpaulo#include "NeonEmitter.h" 34214501Srpaulo#include "OptParserEmitter.h" 35214501Srpaulo#include "Record.h" 36214501Srpaulo#include "RegisterInfoEmitter.h" 37214501Srpaulo#include "ARMDecoderEmitter.h" 38214501Srpaulo#include "SubtargetEmitter.h" 39214501Srpaulo#include "TGParser.h" 40214501Srpaulo#include "llvm/Support/CommandLine.h" 41214501Srpaulo#include "llvm/Support/MemoryBuffer.h" 42214501Srpaulo#include "llvm/Support/PrettyStackTrace.h" 43214501Srpaulo#include "llvm/Support/raw_ostream.h" 44214501Srpaulo#include "llvm/System/Signals.h" 45214501Srpaulo#include <algorithm> 46214501Srpaulo#include <cstdio> 47214501Srpaulousing namespace llvm; 48214501Srpaulo 49214501Srpauloenum ActionType { 50214501Srpaulo PrintRecords, 51214501Srpaulo GenEmitter, 52214501Srpaulo GenRegisterEnums, GenRegister, GenRegisterHeader, 53214501Srpaulo GenInstrEnums, GenInstrs, GenAsmWriter, GenAsmMatcher, 54214501Srpaulo GenARMDecoder, 55214501Srpaulo GenDisassembler, 56214501Srpaulo GenCallingConv, 57214501Srpaulo GenClangAttrClasses, 58214501Srpaulo GenClangAttrList, 59 GenClangDiagsDefs, 60 GenClangDiagGroups, 61 GenClangDeclNodes, 62 GenClangStmtNodes, 63 GenDAGISel, 64 GenFastISel, 65 GenOptParserDefs, GenOptParserImpl, 66 GenSubtarget, 67 GenIntrinsic, 68 GenTgtIntrinsic, 69 GenLLVMCConf, 70 GenEDHeader, GenEDInfo, 71 GenArmNeon, 72 GenArmNeonSema, 73 PrintEnums 74}; 75 76namespace { 77 cl::opt<ActionType> 78 Action(cl::desc("Action to perform:"), 79 cl::values(clEnumValN(PrintRecords, "print-records", 80 "Print all records to stdout (default)"), 81 clEnumValN(GenEmitter, "gen-emitter", 82 "Generate machine code emitter"), 83 clEnumValN(GenRegisterEnums, "gen-register-enums", 84 "Generate enum values for registers"), 85 clEnumValN(GenRegister, "gen-register-desc", 86 "Generate a register info description"), 87 clEnumValN(GenRegisterHeader, "gen-register-desc-header", 88 "Generate a register info description header"), 89 clEnumValN(GenInstrEnums, "gen-instr-enums", 90 "Generate enum values for instructions"), 91 clEnumValN(GenInstrs, "gen-instr-desc", 92 "Generate instruction descriptions"), 93 clEnumValN(GenCallingConv, "gen-callingconv", 94 "Generate calling convention descriptions"), 95 clEnumValN(GenAsmWriter, "gen-asm-writer", 96 "Generate assembly writer"), 97 clEnumValN(GenARMDecoder, "gen-arm-decoder", 98 "Generate decoders for ARM/Thumb"), 99 clEnumValN(GenDisassembler, "gen-disassembler", 100 "Generate disassembler"), 101 clEnumValN(GenAsmMatcher, "gen-asm-matcher", 102 "Generate assembly instruction matcher"), 103 clEnumValN(GenDAGISel, "gen-dag-isel", 104 "Generate a DAG instruction selector"), 105 clEnumValN(GenFastISel, "gen-fast-isel", 106 "Generate a \"fast\" instruction selector"), 107 clEnumValN(GenOptParserDefs, "gen-opt-parser-defs", 108 "Generate option definitions"), 109 clEnumValN(GenOptParserImpl, "gen-opt-parser-impl", 110 "Generate option parser implementation"), 111 clEnumValN(GenSubtarget, "gen-subtarget", 112 "Generate subtarget enumerations"), 113 clEnumValN(GenIntrinsic, "gen-intrinsic", 114 "Generate intrinsic information"), 115 clEnumValN(GenTgtIntrinsic, "gen-tgt-intrinsic", 116 "Generate target intrinsic information"), 117 clEnumValN(GenClangAttrClasses, "gen-clang-attr-classes", 118 "Generate clang attribute clases"), 119 clEnumValN(GenClangAttrList, "gen-clang-attr-list", 120 "Generate a clang attribute list"), 121 clEnumValN(GenClangDiagsDefs, "gen-clang-diags-defs", 122 "Generate Clang diagnostics definitions"), 123 clEnumValN(GenClangDiagGroups, "gen-clang-diag-groups", 124 "Generate Clang diagnostic groups"), 125 clEnumValN(GenClangDeclNodes, "gen-clang-decl-nodes", 126 "Generate Clang AST statement nodes"), 127 clEnumValN(GenClangStmtNodes, "gen-clang-stmt-nodes", 128 "Generate Clang AST statement nodes"), 129 clEnumValN(GenLLVMCConf, "gen-llvmc", 130 "Generate LLVMC configuration library"), 131 clEnumValN(GenEDHeader, "gen-enhanced-disassembly-header", 132 "Generate enhanced disassembly info header"), 133 clEnumValN(GenEDInfo, "gen-enhanced-disassembly-info", 134 "Generate enhanced disassembly info"), 135 clEnumValN(GenArmNeon, "gen-arm-neon", 136 "Generate arm_neon.h for clang"), 137 clEnumValN(GenArmNeonSema, "gen-arm-neon-sema", 138 "Generate ARM NEON sema support for clang"), 139 clEnumValN(PrintEnums, "print-enums", 140 "Print enum values for a class"), 141 clEnumValEnd)); 142 143 cl::opt<std::string> 144 Class("class", cl::desc("Print Enum list for this class"), 145 cl::value_desc("class name")); 146 147 cl::opt<std::string> 148 OutputFilename("o", cl::desc("Output filename"), cl::value_desc("filename"), 149 cl::init("-")); 150 151 cl::opt<std::string> 152 InputFilename(cl::Positional, cl::desc("<input file>"), cl::init("-")); 153 154 cl::list<std::string> 155 IncludeDirs("I", cl::desc("Directory of include files"), 156 cl::value_desc("directory"), cl::Prefix); 157 158 cl::opt<std::string> 159 ClangComponent("clang-component", 160 cl::desc("Only use warnings from specified component"), 161 cl::value_desc("component"), cl::Hidden); 162} 163 164 165// FIXME: Eliminate globals from tblgen. 166RecordKeeper llvm::Records; 167 168static SourceMgr SrcMgr; 169 170void llvm::PrintError(SMLoc ErrorLoc, const std::string &Msg) { 171 SrcMgr.PrintMessage(ErrorLoc, Msg, "error"); 172} 173 174 175 176/// ParseFile - this function begins the parsing of the specified tablegen 177/// file. 178static bool ParseFile(const std::string &Filename, 179 const std::vector<std::string> &IncludeDirs, 180 SourceMgr &SrcMgr) { 181 std::string ErrorStr; 182 MemoryBuffer *F = MemoryBuffer::getFileOrSTDIN(Filename.c_str(), &ErrorStr); 183 if (F == 0) { 184 errs() << "Could not open input file '" << Filename << "': " 185 << ErrorStr <<"\n"; 186 return true; 187 } 188 189 // Tell SrcMgr about this buffer, which is what TGParser will pick up. 190 SrcMgr.AddNewSourceBuffer(F, SMLoc()); 191 192 // Record the location of the include directory so that the lexer can find 193 // it later. 194 SrcMgr.setIncludeDirs(IncludeDirs); 195 196 TGParser Parser(SrcMgr); 197 198 return Parser.ParseFile(); 199} 200 201int main(int argc, char **argv) { 202 sys::PrintStackTraceOnErrorSignal(); 203 PrettyStackTraceProgram X(argc, argv); 204 cl::ParseCommandLineOptions(argc, argv); 205 206 207 // Parse the input file. 208 if (ParseFile(InputFilename, IncludeDirs, SrcMgr)) 209 return 1; 210 211 std::string Error; 212 raw_fd_ostream Out(OutputFilename.c_str(), Error); 213 if (!Error.empty()) { 214 errs() << argv[0] << ": error opening " << OutputFilename 215 << ":" << Error << "\n"; 216 return 1; 217 } 218 219 // Make sure the file gets removed if *gasp* tablegen crashes... 220 sys::RemoveFileOnSignal(sys::Path(OutputFilename)); 221 222 try { 223 switch (Action) { 224 case PrintRecords: 225 Out << Records; // No argument, dump all contents 226 break; 227 case GenEmitter: 228 CodeEmitterGen(Records).run(Out); 229 break; 230 231 case GenRegisterEnums: 232 RegisterInfoEmitter(Records).runEnums(Out); 233 break; 234 case GenRegister: 235 RegisterInfoEmitter(Records).run(Out); 236 break; 237 case GenRegisterHeader: 238 RegisterInfoEmitter(Records).runHeader(Out); 239 break; 240 case GenInstrEnums: 241 InstrEnumEmitter(Records).run(Out); 242 break; 243 case GenInstrs: 244 InstrInfoEmitter(Records).run(Out); 245 break; 246 case GenCallingConv: 247 CallingConvEmitter(Records).run(Out); 248 break; 249 case GenAsmWriter: 250 AsmWriterEmitter(Records).run(Out); 251 break; 252 case GenARMDecoder: 253 ARMDecoderEmitter(Records).run(Out); 254 break; 255 case GenAsmMatcher: 256 AsmMatcherEmitter(Records).run(Out); 257 break; 258 case GenClangAttrClasses: 259 ClangAttrClassEmitter(Records).run(Out); 260 break; 261 case GenClangAttrList: 262 ClangAttrListEmitter(Records).run(Out); 263 break; 264 case GenClangDiagsDefs: 265 ClangDiagsDefsEmitter(Records, ClangComponent).run(Out); 266 break; 267 case GenClangDiagGroups: 268 ClangDiagGroupsEmitter(Records).run(Out); 269 break; 270 case GenClangDeclNodes: 271 ClangASTNodesEmitter(Records, "Decl", "Decl").run(Out); 272 ClangDeclContextEmitter(Records).run(Out); 273 break; 274 case GenClangStmtNodes: 275 ClangASTNodesEmitter(Records, "Stmt", "").run(Out); 276 break; 277 case GenDisassembler: 278 DisassemblerEmitter(Records).run(Out); 279 break; 280 case GenOptParserDefs: 281 OptParserEmitter(Records, true).run(Out); 282 break; 283 case GenOptParserImpl: 284 OptParserEmitter(Records, false).run(Out); 285 break; 286 case GenDAGISel: 287 DAGISelEmitter(Records).run(Out); 288 break; 289 case GenFastISel: 290 FastISelEmitter(Records).run(Out); 291 break; 292 case GenSubtarget: 293 SubtargetEmitter(Records).run(Out); 294 break; 295 case GenIntrinsic: 296 IntrinsicEmitter(Records).run(Out); 297 break; 298 case GenTgtIntrinsic: 299 IntrinsicEmitter(Records, true).run(Out); 300 break; 301 case GenLLVMCConf: 302 LLVMCConfigurationEmitter(Records).run(Out); 303 break; 304 case GenEDHeader: 305 EDEmitter(Records).runHeader(Out); 306 break; 307 case GenEDInfo: 308 EDEmitter(Records).run(Out); 309 break; 310 case GenArmNeon: 311 NeonEmitter(Records).run(Out); 312 break; 313 case GenArmNeonSema: 314 NeonEmitter(Records).runHeader(Out); 315 break; 316 case PrintEnums: 317 { 318 std::vector<Record*> Recs = Records.getAllDerivedDefinitions(Class); 319 for (unsigned i = 0, e = Recs.size(); i != e; ++i) 320 Out << Recs[i]->getName() << ", "; 321 Out << "\n"; 322 break; 323 } 324 default: 325 assert(1 && "Invalid Action"); 326 return 1; 327 } 328 329 return 0; 330 331 } catch (const TGError &Error) { 332 errs() << argv[0] << ": error:\n"; 333 PrintError(Error.getLoc(), Error.getMessage()); 334 335 } catch (const std::string &Error) { 336 errs() << argv[0] << ": " << Error << "\n"; 337 } catch (const char *Error) { 338 errs() << argv[0] << ": " << Error << "\n"; 339 } catch (...) { 340 errs() << argv[0] << ": Unknown unexpected exception occurred.\n"; 341 } 342 343 if (OutputFilename != "-") 344 std::remove(OutputFilename.c_str()); // Remove the file, it's broken 345 return 1; 346} 347