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 "ClangAttrEmitter.h" 23 #include "ClangDiagnosticsEmitter.h" 24 #include "ClangSACheckersEmitter.h" 25 #include "CodeEmitterGen.h" 26 #include "DAGISelEmitter.h" 27 #include "DisassemblerEmitter.h" 28 #include "EDEmitter.h" 29 #include "FastISelEmitter.h" 30 #include "InstrEnumEmitter.h" 31 #include "InstrInfoEmitter.h" 32 #include "IntrinsicEmitter.h" 33 #include "LLVMCConfigurationEmitter.h" 34 #include "NeonEmitter.h" 35 #include "OptParserEmitter.h" 36 #include "Record.h" 37 #include "RegisterInfoEmitter.h" 38 #include "ARMDecoderEmitter.h" 39 #include "SubtargetEmitter.h" 40 #include "TGParser.h" 41 #include "llvm/ADT/OwningPtr.h" 42 #include "llvm/Support/CommandLine.h" 43 #include "llvm/Support/MemoryBuffer.h" 44 #include "llvm/Support/PrettyStackTrace.h" 45 #include "llvm/Support/ToolOutputFile.h" 46 #include "llvm/Support/Signals.h" 47 #include "llvm/Support/system_error.h" 48 #include <algorithm> 49 #include <cstdio> 50 using namespace llvm; 51 52 enum ActionType { 53 PrintRecords, 54 GenEmitter, 55 GenRegisterEnums, GenRegister, GenRegisterHeader, 56 GenInstrEnums, GenInstrs, GenAsmWriter, GenAsmMatcher, 57 GenARMDecoder, 58 GenDisassembler, 59 GenCallingConv, 60 GenClangAttrClasses, 61 GenClangAttrImpl, 62 GenClangAttrList, 63 GenClangAttrPCHRead, 64 GenClangAttrPCHWrite, 65 GenClangAttrSpellingList, 66 GenClangDiagsDefs, 67 GenClangDiagGroups, 68 GenClangDeclNodes, 69 GenClangStmtNodes, 70 GenClangSACheckers, 71 GenDAGISel, 72 GenFastISel, 73 GenOptParserDefs, GenOptParserImpl, 74 GenSubtarget, 75 GenIntrinsic, 76 GenTgtIntrinsic, 77 GenLLVMCConf, 78 GenEDInfo, 79 GenArmNeon, 80 GenArmNeonSema, 81 GenArmNeonTest, 82 PrintEnums 83 }; 84 85 namespace { 86 cl::opt<ActionType> 87 Action(cl::desc("Action to perform:"), 88 cl::values(clEnumValN(PrintRecords, "print-records", 89 "Print all records to stdout (default)"), 90 clEnumValN(GenEmitter, "gen-emitter", 91 "Generate machine code emitter"), 92 clEnumValN(GenRegisterEnums, "gen-register-enums", 93 "Generate enum values for registers"), 94 clEnumValN(GenRegister, "gen-register-desc", 95 "Generate a register info description"), 96 clEnumValN(GenRegisterHeader, "gen-register-desc-header", 97 "Generate a register info description header"), 98 clEnumValN(GenInstrEnums, "gen-instr-enums", 99 "Generate enum values for instructions"), 100 clEnumValN(GenInstrs, "gen-instr-desc", 101 "Generate instruction descriptions"), 102 clEnumValN(GenCallingConv, "gen-callingconv", 103 "Generate calling convention descriptions"), 104 clEnumValN(GenAsmWriter, "gen-asm-writer", 105 "Generate assembly writer"), 106 clEnumValN(GenARMDecoder, "gen-arm-decoder", 107 "Generate decoders for ARM/Thumb"), 108 clEnumValN(GenDisassembler, "gen-disassembler", 109 "Generate disassembler"), 110 clEnumValN(GenAsmMatcher, "gen-asm-matcher", 111 "Generate assembly instruction matcher"), 112 clEnumValN(GenDAGISel, "gen-dag-isel", 113 "Generate a DAG instruction selector"), 114 clEnumValN(GenFastISel, "gen-fast-isel", 115 "Generate a \"fast\" instruction selector"), 116 clEnumValN(GenOptParserDefs, "gen-opt-parser-defs", 117 "Generate option definitions"), 118 clEnumValN(GenOptParserImpl, "gen-opt-parser-impl", 119 "Generate option parser implementation"), 120 clEnumValN(GenSubtarget, "gen-subtarget", 121 "Generate subtarget enumerations"), 122 clEnumValN(GenIntrinsic, "gen-intrinsic", 123 "Generate intrinsic information"), 124 clEnumValN(GenTgtIntrinsic, "gen-tgt-intrinsic", 125 "Generate target intrinsic information"), 126 clEnumValN(GenClangAttrClasses, "gen-clang-attr-classes", 127 "Generate clang attribute clases"), 128 clEnumValN(GenClangAttrImpl, "gen-clang-attr-impl", 129 "Generate clang attribute implementations"), 130 clEnumValN(GenClangAttrList, "gen-clang-attr-list", 131 "Generate a clang attribute list"), 132 clEnumValN(GenClangAttrPCHRead, "gen-clang-attr-pch-read", 133 "Generate clang PCH attribute reader"), 134 clEnumValN(GenClangAttrPCHWrite, "gen-clang-attr-pch-write", 135 "Generate clang PCH attribute writer"), 136 clEnumValN(GenClangAttrSpellingList, "gen-clang-attr-spelling-list", 137 "Generate a clang attribute spelling list"), 138 clEnumValN(GenClangDiagsDefs, "gen-clang-diags-defs", 139 "Generate Clang diagnostics definitions"), 140 clEnumValN(GenClangDiagGroups, "gen-clang-diag-groups", 141 "Generate Clang diagnostic groups"), 142 clEnumValN(GenClangDeclNodes, "gen-clang-decl-nodes", 143 "Generate Clang AST declaration nodes"), 144 clEnumValN(GenClangStmtNodes, "gen-clang-stmt-nodes", 145 "Generate Clang AST statement nodes"), 146 clEnumValN(GenClangSACheckers, "gen-clang-sa-checkers", 147 "Generate Clang Static Analyzer checkers"), 148 clEnumValN(GenLLVMCConf, "gen-llvmc", 149 "Generate LLVMC configuration library"), 150 clEnumValN(GenEDInfo, "gen-enhanced-disassembly-info", 151 "Generate enhanced disassembly info"), 152 clEnumValN(GenArmNeon, "gen-arm-neon", 153 "Generate arm_neon.h for clang"), 154 clEnumValN(GenArmNeonSema, "gen-arm-neon-sema", 155 "Generate ARM NEON sema support for clang"), 156 clEnumValN(GenArmNeonTest, "gen-arm-neon-test", 157 "Generate ARM NEON tests for clang"), 158 clEnumValN(PrintEnums, "print-enums", 159 "Print enum values for a class"), 160 clEnumValEnd)); 161 162 cl::opt<std::string> 163 Class("class", cl::desc("Print Enum list for this class"), 164 cl::value_desc("class name")); 165 166 cl::opt<std::string> 167 OutputFilename("o", cl::desc("Output filename"), cl::value_desc("filename"), 168 cl::init("-")); 169 170 cl::opt<std::string> 171 InputFilename(cl::Positional, cl::desc("<input file>"), cl::init("-")); 172 173 cl::list<std::string> 174 IncludeDirs("I", cl::desc("Directory of include files"), 175 cl::value_desc("directory"), cl::Prefix); 176 177 cl::opt<std::string> 178 ClangComponent("clang-component", 179 cl::desc("Only use warnings from specified component"), 180 cl::value_desc("component"), cl::Hidden); 181 } 182 183 184 static SourceMgr SrcMgr; 185 186 void llvm::PrintError(SMLoc ErrorLoc, const Twine &Msg) { 187 SrcMgr.PrintMessage(ErrorLoc, Msg, "error"); 188 } 189 190 191 192 /// ParseFile - this function begins the parsing of the specified tablegen 193 /// file. 194 static bool ParseFile(const std::string &Filename, 195 const std::vector<std::string> &IncludeDirs, 196 SourceMgr &SrcMgr, 197 RecordKeeper &Records) { 198 OwningPtr<MemoryBuffer> File; 199 if (error_code ec = MemoryBuffer::getFileOrSTDIN(Filename.c_str(), File)) { 200 errs() << "Could not open input file '" << Filename << "': " 201 << ec.message() <<"\n"; 202 return true; 203 } 204 MemoryBuffer *F = File.take(); 205 206 // Tell SrcMgr about this buffer, which is what TGParser will pick up. 207 SrcMgr.AddNewSourceBuffer(F, SMLoc()); 208 209 // Record the location of the include directory so that the lexer can find 210 // it later. 211 SrcMgr.setIncludeDirs(IncludeDirs); 212 213 TGParser Parser(SrcMgr, Records); 214 215 return Parser.ParseFile(); 216 } 217 218 int main(int argc, char **argv) { 219 RecordKeeper Records; 220 221 sys::PrintStackTraceOnErrorSignal(); 222 PrettyStackTraceProgram X(argc, argv); 223 cl::ParseCommandLineOptions(argc, argv); 224 225 226 // Parse the input file. 227 if (ParseFile(InputFilename, IncludeDirs, SrcMgr, Records)) 228 return 1; 229 230 std::string Error; 231 tool_output_file Out(OutputFilename.c_str(), Error); 232 if (!Error.empty()) { 233 errs() << argv[0] << ": error opening " << OutputFilename 234 << ":" << Error << "\n"; 235 return 1; 236 } 237 238 try { 239 switch (Action) { 240 case PrintRecords: 241 Out.os() << Records; // No argument, dump all contents 242 break; 243 case GenEmitter: 244 CodeEmitterGen(Records).run(Out.os()); 245 break; 246 247 case GenRegisterEnums: 248 RegisterInfoEmitter(Records).runEnums(Out.os()); 249 break; 250 case GenRegister: 251 RegisterInfoEmitter(Records).run(Out.os()); 252 break; 253 case GenRegisterHeader: 254 RegisterInfoEmitter(Records).runHeader(Out.os()); 255 break; 256 case GenInstrEnums: 257 InstrEnumEmitter(Records).run(Out.os()); 258 break; 259 case GenInstrs: 260 InstrInfoEmitter(Records).run(Out.os()); 261 break; 262 case GenCallingConv: 263 CallingConvEmitter(Records).run(Out.os()); 264 break; 265 case GenAsmWriter: 266 AsmWriterEmitter(Records).run(Out.os()); 267 break; 268 case GenARMDecoder: 269 ARMDecoderEmitter(Records).run(Out.os()); 270 break; 271 case GenAsmMatcher: 272 AsmMatcherEmitter(Records).run(Out.os()); 273 break; 274 case GenClangAttrClasses: 275 ClangAttrClassEmitter(Records).run(Out.os()); 276 break; 277 case GenClangAttrImpl: 278 ClangAttrImplEmitter(Records).run(Out.os()); 279 break; 280 case GenClangAttrList: 281 ClangAttrListEmitter(Records).run(Out.os()); 282 break; 283 case GenClangAttrPCHRead: 284 ClangAttrPCHReadEmitter(Records).run(Out.os()); 285 break; 286 case GenClangAttrPCHWrite: 287 ClangAttrPCHWriteEmitter(Records).run(Out.os()); 288 break; 289 case GenClangAttrSpellingList: 290 ClangAttrSpellingListEmitter(Records).run(Out.os()); 291 break; 292 case GenClangDiagsDefs: 293 ClangDiagsDefsEmitter(Records, ClangComponent).run(Out.os()); 294 break; 295 case GenClangDiagGroups: 296 ClangDiagGroupsEmitter(Records).run(Out.os()); 297 break; 298 case GenClangDeclNodes: 299 ClangASTNodesEmitter(Records, "Decl", "Decl").run(Out.os()); 300 ClangDeclContextEmitter(Records).run(Out.os()); 301 break; 302 case GenClangStmtNodes: 303 ClangASTNodesEmitter(Records, "Stmt", "").run(Out.os()); 304 break; 305 case GenClangSACheckers: 306 ClangSACheckersEmitter(Records).run(Out.os()); 307 break; 308 case GenDisassembler: 309 DisassemblerEmitter(Records).run(Out.os()); 310 break; 311 case GenOptParserDefs: 312 OptParserEmitter(Records, true).run(Out.os()); 313 break; 314 case GenOptParserImpl: 315 OptParserEmitter(Records, false).run(Out.os()); 316 break; 317 case GenDAGISel: 318 DAGISelEmitter(Records).run(Out.os()); 319 break; 320 case GenFastISel: 321 FastISelEmitter(Records).run(Out.os()); 322 break; 323 case GenSubtarget: 324 SubtargetEmitter(Records).run(Out.os()); 325 break; 326 case GenIntrinsic: 327 IntrinsicEmitter(Records).run(Out.os()); 328 break; 329 case GenTgtIntrinsic: 330 IntrinsicEmitter(Records, true).run(Out.os()); 331 break; 332 case GenLLVMCConf: 333 LLVMCConfigurationEmitter(Records).run(Out.os()); 334 break; 335 case GenEDInfo: 336 EDEmitter(Records).run(Out.os()); 337 break; 338 case GenArmNeon: 339 NeonEmitter(Records).run(Out.os()); 340 break; 341 case GenArmNeonSema: 342 NeonEmitter(Records).runHeader(Out.os()); 343 break; 344 case GenArmNeonTest: 345 NeonEmitter(Records).runTests(Out.os()); 346 break; 347 case PrintEnums: 348 { 349 std::vector<Record*> Recs = Records.getAllDerivedDefinitions(Class); 350 for (unsigned i = 0, e = Recs.size(); i != e; ++i) 351 Out.os() << Recs[i]->getName() << ", "; 352 Out.os() << "\n"; 353 break; 354 } 355 default: 356 assert(1 && "Invalid Action"); 357 return 1; 358 } 359 360 // Declare success. 361 Out.keep(); 362 return 0; 363 364 } catch (const TGError &Error) { 365 errs() << argv[0] << ": error:\n"; 366 PrintError(Error.getLoc(), Error.getMessage()); 367 368 } catch (const std::string &Error) { 369 errs() << argv[0] << ": " << Error << "\n"; 370 } catch (const char *Error) { 371 errs() << argv[0] << ": " << Error << "\n"; 372 } catch (...) { 373 errs() << argv[0] << ": Unknown unexpected exception occurred.\n"; 374 } 375 376 return 1; 377 } 378