diff --git a/src/dmd/backend/util2.c b/src/dmd/backend/util2.c index 05c1c1b30963..9f6e6002b416 100644 --- a/src/dmd/backend/util2.c +++ b/src/dmd/backend/util2.c @@ -38,6 +38,8 @@ void *ph_calloc(size_t nbytes); void ph_free(void *p); void *ph_realloc(void *p , size_t nbytes); +extern "C" void internalFailureLogo(FILE* stream); // from dmd/mars.d + void util_exit(int exitcode); @@ -52,6 +54,7 @@ void file_progress() void util_assert(const char *file, int line) { fflush(stdout); + internalFailureLogo(stdout); printf("Internal error: %s %d\n",file,line); err_exit(); #if __clang__ diff --git a/src/dmd/mars.d b/src/dmd/mars.d index 1a7ad3f9eb54..015b28077cdb 100644 --- a/src/dmd/mars.d +++ b/src/dmd/mars.d @@ -70,6 +70,25 @@ private void logo() printf("DMD%llu D Compiler %s\n%s %s\n", cast(ulong)size_t.sizeof * 8, global._version, global.copyright, global.written); } +/** +Print DMD's logo with more debug information and error-reporting pointers. + +Params: + stream = output stream to print the information on +*/ +extern(C) void internalFailureLogo(FILE* stream) +{ + stream.fprintf("---\n"); + stream.fprintf("ERROR: This is a compiler bug.\n" ~ + "Please report it via https://issues.dlang.org/enter_bug.cgi\n" ~ + "with, preferably, a reduced, reproducible example and the information below.\n"); + stream.fprintf("DustMite (https://github.com/CyberShadow/DustMite/wiki) can help with the reduction.\n"); + stream.fprintf("---\n"); + stream.fprintf("DMD %s\n", global._version); + stream.printPredefinedVersions; + stream.printGlobalConfigs(); + stream.fprintf("---\n"); +} /** * Print DMD's usage message on stdout @@ -495,40 +514,10 @@ private int tryMain(size_t argc, const(char)** argv) Objc._init(); builtin_init(); - printPredefinedVersions(); - if (global.params.verbose) { - message("binary %s", global.params.argv0); - message("version %s", global._version); - message("config %s", global.inifilename ? global.inifilename : "(none)"); - // Print DFLAGS environment variable - { - Strings dflags; - getenv_setargv(readFromEnv(&environment, "DFLAGS"), &dflags); - OutBuffer buf; - foreach (flag; dflags.asDArray) - { - bool needsQuoting; - for (auto flagp = flag; flagp; flagp++) - { - auto c = flagp[0]; - if (!(isalnum(c) || c == '_')) - { - needsQuoting = true; - break; - } - } - - if (flag.strchr(' ')) - buf.printf("'%s' ", flag); - else - buf.printf("%s ", flag); - } - - auto res = buf.peekSlice() ? buf.peekSlice()[0 .. $ - 1] : "(none)"; - message("DFLAGS %.*s", res.length, res.ptr); - } + stdout.printPredefinedVersions(); + stdout.printGlobalConfigs(); } //printf("%d source files\n",files.dim); @@ -1094,6 +1083,8 @@ int main() dmd_coverSetMerge(true); } + scope(failure) stderr.internalFailureLogo; + auto args = Runtime.cArgs(); return tryMain(args.argc, cast(const(char)**)args.argv); } @@ -1406,9 +1397,9 @@ void addDefaultVersionIdentifiers() VersionCondition.addPredefinedGlobalIdent("D_HardFloat"); } -private void printPredefinedVersions() +private void printPredefinedVersions(FILE* stream) { - if (global.params.verbose && global.versionids) + if (global.versionids) { OutBuffer buf; foreach (const str; *global.versionids) @@ -1416,10 +1407,46 @@ private void printPredefinedVersions() buf.writeByte(' '); buf.writestring(str.toChars()); } - message("predefs %s", buf.peekString()); + stream.fprintf("predefs %.*s", buf.peekString()); } } +extern(C) void printGlobalConfigs(FILE* stream) +{ + stream.fprintf("binary %s\n", global.params.argv0); + stream.fprintf("version %s\n", global._version); + stream.fprintf("config %s\n", global.inifilename ? global.inifilename : "(none)"); + // Print DFLAGS environment variable + { + StringTable environment; + environment._init(0); + Strings dflags; + getenv_setargv(readFromEnv(&environment, "DFLAGS"), &dflags); + environment.reset(1); + OutBuffer buf; + foreach (flag; dflags.asDArray) + { + bool needsQuoting; + for (auto flagp = flag; flagp; flagp++) + { + auto c = flagp[0]; + if (!(isalnum(c) || c == '_')) + { + needsQuoting = true; + break; + } + } + + if (flag.strchr(' ')) + buf.printf("'%s' ", flag); + else + buf.printf("%s ", flag); + } + + auto res = buf.peekSlice() ? buf.peekSlice()[0 .. $ - 1] : "(none)"; + stream.fprintf("DFLAGS %.*s\n", res.length, res.ptr); + } +} /**************************************** * Determine the instruction set to be used.