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