1 module driver.sdc; 2 3 import source.context; 4 5 int main(string[] args) { 6 version (DigitalMars) { 7 version (linux) { 8 import etc.linux.memoryerror; 9 // druntime not containe the necessary symbol. 10 // registerMemoryErrorHandler(); 11 } 12 } 13 14 auto context = new Context(); 15 16 import std.getopt, source.exception; 17 try { 18 return context.run(args); 19 } catch (GetOptException ex) { 20 import std.stdio; 21 writefln("%s", ex.msg); 22 writeln("Please use -h to get a list of valid options."); 23 return 1; 24 } catch (CompileException e) { 25 import util.terminal; 26 outputCaretDiagnostics(e.getFullLocation(context), e.msg); 27 28 // Rethrow in debug, so we have the stack trace. 29 debug { 30 throw e; 31 } else { 32 return 1; 33 } 34 } 35 36 // This is unreachable, but dmd can't figure this out. 37 assert(0); 38 } 39 40 int run(Context context, string[] args) { 41 import sdc.config; 42 Config conf; 43 44 import config.build; 45 conf.buildGlobalConfig("sdconfig", context); 46 47 string[] includePaths, linkerPaths; 48 bool dontLink, generateMain; 49 string outputFile; 50 bool outputLLVM, outputAsm; 51 52 import std.getopt; 53 auto help_info = getopt( 54 // sdfmt off 55 args, std.getopt.config.caseSensitive, 56 "I", "Include path", &includePaths, 57 "L", "Library path", &linkerPaths, 58 "O", "Optimization level", &conf.optLevel, 59 "c", "Stop before linking", &dontLink, 60 "o", "Output file", &outputFile, 61 "S", "Stop before assembling and output assembly file", &outputAsm, 62 "emit-llvm", "Output LLVM bitcode (-c) or LLVM assembly (-S)", &outputLLVM, 63 "main", "Generate the main function", &generateMain, 64 // sdfmt on 65 ); 66 67 if (help_info.helpWanted || args.length == 1) { 68 import std.stdio; 69 writeln("The Snazzy D Compiler"); 70 writeln("Usage: sdc [options] file.d"); 71 writeln("Options:"); 72 73 foreach (option; help_info.options) { 74 writefln(" %-16s %s", 75 // bug : optShort is empty if there is no long version 76 option.optShort.length 77 ? option.optShort 78 : (option.optLong.length == 3) 79 ? option.optLong[1 .. $] 80 : option.optLong, 81 option.help); 82 } 83 84 return 0; 85 } 86 87 conf.includePaths = includePaths ~ conf.includePaths; 88 conf.linkerPaths = linkerPaths ~ conf.linkerPaths; 89 90 auto files = args[1 .. $]; 91 92 if (outputAsm) { 93 dontLink = true; 94 } 95 96 auto executable = "a.out"; 97 auto defaultExtension = ".o"; 98 if (outputAsm) { 99 defaultExtension = outputLLVM ? ".ll" : ".s"; 100 } else if (dontLink) { 101 defaultExtension = outputLLVM ? ".bc" : ".o"; 102 } 103 104 auto objFile = files[0][0 .. $ - 2] ~ defaultExtension; 105 if (outputFile.length) { 106 if (dontLink || outputAsm) { 107 objFile = outputFile; 108 } else { 109 executable = outputFile; 110 } 111 } 112 113 // If we are generating an executable, we want a main function. 114 generateMain = generateMain || !dontLink; 115 116 // Cannot call the variable "sdc" or DMD complains about name clash 117 // with the sdc package from the import. 118 import sdc.sdc; 119 auto c = new SDC(context, files[0], conf); 120 121 foreach (file; files) { 122 c.compile(file); 123 } 124 125 if (generateMain) { 126 c.buildMain(); 127 } 128 129 if (outputAsm) { 130 if (outputLLVM) { 131 c.outputLLVMAsm(objFile); 132 } else { 133 c.outputAsm(objFile); 134 } 135 } else if (dontLink) { 136 if (outputLLVM) { 137 c.outputLLVMBitcode(objFile); 138 } else { 139 c.outputObj(objFile); 140 } 141 } else { 142 c.outputObj(objFile); 143 c.linkExecutable(objFile, executable); 144 } 145 146 return 0; 147 }