Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/dmd/globals.d
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,7 @@ struct Param
bool mcpuUsage; // print help on -mcpu switch
bool transitionUsage; // print help on -transition switch
bool logo; // print compiler logo
bool showProbingInfo; // print detailed information about the compiler

CPU cpu = CPU.baseline; // CPU instruction set to target

Expand Down
59 changes: 39 additions & 20 deletions src/dmd/lexer.d
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,44 @@ unittest
}
}

long parseVersionXX(const(char)* _version)
{
struct Version
{
uint major;
uint minor;
bool point;
}
Version rVersion;

with(rVersion)
for (const(char)* p = _version + 1; 1; p++)
{
const c = *p;
if (isdigit(cast(char)c))
minor = minor * 10 + c - '0';
else if (c == '.')
{
if (point)
break; // ignore everything after second '.'
point = true;
major = minor;
minor = 0;
}
else
break;
}
return rVersion.major * 1000 + rVersion.minor;
}

unittest
{
assert(parseVersionXX("v2.078.0-265-g4a9eac019-dirty") == 2078);
assert(parseVersionXX("v2.078.0") == 2078);
assert(parseVersionXX("v2.078.1") == 2078);
assert(parseVersionXX("v2.070.2-rc.2") == 2070);
}

/***********************************************************
*/
class Lexer
Expand Down Expand Up @@ -516,27 +554,8 @@ class Lexer
}
else if (id == Id.VERSIONX)
{
uint major = 0;
uint minor = 0;
bool point = false;
for (const(char)* p = global._version + 1; 1; p++)
{
const c = *p;
if (isdigit(cast(char)c))
minor = minor * 10 + c - '0';
else if (c == '.')
{
if (point)
break; // ignore everything after second '.'
point = true;
major = minor;
minor = 0;
}
else
break;
}
t.value = TOKint64v;
t.unsvalue = major * 1000 + minor;
t.unsvalue = parseVersionXX(global._version);
}
else if (id == Id.EOFX)
{
Expand Down
12 changes: 12 additions & 0 deletions src/dmd/mars.d
Original file line number Diff line number Diff line change
Expand Up @@ -472,6 +472,13 @@ private int tryMain(size_t argc, const(char)** argv)
Objc._init();
builtin_init();

if (global.params.showProbingInfo)
{
import dmd.probing : printProbingInfo;
printProbingInfo();
return EXIT_SUCCESS;
}

if (global.params.verbose)
{
fprintf(global.stdmsg, "binary %s\n", global.params.argv0);
Expand Down Expand Up @@ -2098,6 +2105,11 @@ private bool parseCommandLine(const ref Strings arguments, const size_t argc, re
params.manual = true;
return false;
}
else if (strcmp(p + 1, "probe") == 0) // not documented for 2.079
{
params.showProbingInfo = true;
return false;
}
else if (arg == "-run") // https://dlang.org/dmd.html#switch-run
{
params.run = true;
Expand Down
161 changes: 161 additions & 0 deletions src/dmd/probing.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
/**
* Compiler implementation of the
* $(LINK2 http://www.dlang.org, D programming language).
*
* This modules helps to create a list of supported features (aka probing output).
* The probing information is returned in JSON.
*
* Copyright: Copyright (c) 1999-2018 by The D Language Foundation, All Rights Reserved
* Authors: $(LINK2 http://www.digitalmars.com, Walter Bright)
* License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
* Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/probing.d, _probing.d)
* Documentation: https://dlang.org/phobos/dmd_probing.html
* Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/probing.d
*/

module dmd.probing;

/**
Prints a list of supported features (aka probing output) to stdout.
The output is in JSON.
*/
void printProbingInfo()
{
import core.stdc.stdio : printf;
import dmd.globals : global;

printf("{\n");
bool needsComma;
void printKey(const(char*) key, void function() value)
{
if (needsComma)
printf(",");
printf("\n");
needsComma = true;
printf(" \"%s\": ", key);
value();
}

printKey("compiler", (){
printf(`"%s"`, determineCompiler());
});
printKey("frontendVersion", (){
printf("%d", versionXX());
});
printKey("compilerFrontend", (){
printf(`"%s"`, global._version);
});
printKey("config", (){
if (*global.inifilename != '\0')
printf(`"%s"`, global.inifilename);
else
printf("null");
});
printKey("binary", (){
printf(`"%s"`, global.params.argv0);
});
printKey("platform", (){
printJSONArray(&determinePlatform);
});
printKey("architecture", (){
printJSONArray(&determineArchitecture);
});
printKey("predefinedVersions", (){
printJSONArray(&predefinedVersions);
});
printf("\n}\n");
}

private long versionXX()
{
import dmd.lexer : parseVersionXX;
import dmd.globals : global;
return global._version.parseVersionXX;
}

private const(char*) determineCompiler()
{
import core.stdc.string : strcmp;
import dmd.globals : global;

if (strcmp(global.compiler.vendor, "Digital Mars D") == 0)
return "dmd";
else if (strcmp(global.compiler.vendor, "LDC") == 0)
return "ldc";
else if (strcmp(global.compiler.vendor, "GNU") == 0)
return "gdc";
else if (strcmp(global.compiler.vendor, "SDC") == 0)
return "sdc";

return null;
};

private void printJSONArray(void function(void delegate(string)) fun)
{
import core.stdc.stdio : printf;
static immutable const(char*) indent = " ";

bool isFirst = true;
printf("[\n");
void print(string s)
{
if (!isFirst)
printf(",\n");
printf(`%s%s"%s"`, indent, indent, s.ptr);
isFirst = false;
}
fun(&print);
printf("\n%s]", indent);
}

private void determinePlatform(void delegate(string) print)
{
import dmd.globals : global;

if (global.params.isWindows)
{
print("windows");
}
else
{
print("posix");
if (global.params.isLinux)
print("linux");
if (global.params.isOSX)
print("osx");
if (global.params.isFreeBSD)
{
print("freebsd");
print("bsd");
}
if (global.params.isOpenBSD)
{
print("openbsd");
print("bsd");
}
if (global.params.isSolaris)
{
print("solaris");
print("bsd");
}
}
}

private void determineArchitecture(void delegate(string) print)
{
import dmd.globals : global;

if (global.params.is64bit)
print("x86_64");
else
version(X86) print("x86");
}

private void predefinedVersions(void delegate(string) print)
{
import dmd.globals : global;
foreach (const s; *global.versionids)
{
print(cast(string) s.toString);
}
}
5 changes: 3 additions & 2 deletions src/posix.mak
Original file line number Diff line number Diff line change
Expand Up @@ -296,7 +296,8 @@ FRONT_SRCS=$(addsuffix .d, $(addprefix $D/,access aggregate aliasthis apply argt
dinifile dinterpret dmacro dmangle dmodule doc dscope dstruct dsymbol dsymbolsem \
dtemplate dversion escape expression expressionsem func \
hdrgen id impcnvtab imphint init initsem inline inlinecost intrange \
json lib libelf libmach link mars mtype nogc nspace objc opover optimize parse permissivevisitor sapply templateparamsem \
json lib libelf libmach link mars mtype nogc nspace objc opover optimize parse permissivevisitor \
probing sapply templateparamsem \
sideeffect statement staticassert target typesem traits transitivevisitor parsetimevisitor visitor \
typinf utils scanelf scanmach statement_rewrite_walker statementsem staticcond safe blockexit printast \
semantic2 semantic3))
Expand Down Expand Up @@ -457,7 +458,7 @@ $G/dmd: $(DMD_SRCS) $(ROOT_SRCS) $G/newdelete.o $G/backend.a $G/lexer.a $(STRING
CC="$(HOST_CXX)" $(HOST_DMD_RUN) -of$@ $(MODEL_FLAG) -vtls -J$G -J../res -L-lstdc++ $(DFLAGS) $(filter-out $(STRING_IMPORT_FILES) $(HOST_DMD_PATH) $(LEXER_ROOT) $G/dmd.conf,$^)
endif

$G/dmd-unittest: $(DMD_SRCS) $(ROOT_SRCS) $G/newdelete.o $G/lexer.a $(G_GLUE_OBJS) $(G_OBJS) $(STRING_IMPORT_FILES) $(HOST_DMD_PATH)
$G/dmd-unittest: $(DMD_SRCS) $(ROOT_SRCS) $G/newdelete.o $G/lexer.a $(G_GLUE_OBJS) $(G_OBJS) $(STRING_IMPORT_FILES) $(HOST_DMD_PATH) $(LEXER_SRCS)
CC=$(HOST_CXX) $(HOST_DMD_RUN) -of$@ $(MODEL_FLAG) -vtls -J$G -J../res -L-lstdc++ $(DFLAGS) -g -unittest -main -version=NoMain $(filter-out $(STRING_IMPORT_FILES) $(HOST_DMD_PATH),$^)

unittest: $G/dmd-unittest
Expand Down
2 changes: 1 addition & 1 deletion src/win32.mak
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ FRONT_SRCS=$D/access.d $D/aggregate.d $D/aliasthis.d $D/apply.d $D/argtypes.d $D
$D/expression.d $D/expressionsem.d $D/func.d $D/hdrgen.d $D/id.d $D/imphint.d \
$D/impcnvtab.d $D/init.d $D/initsem.d $D/inline.d $D/inlinecost.d $D/intrange.d $D/json.d $D/lib.d $D/link.d \
$D/mars.d $D/mtype.d $D/nogc.d $D/nspace.d $D/objc.d $D/opover.d $D/optimize.d $D/parse.d \
$D/sapply.d $D/sideeffect.d $D/statement.d $D/staticassert.d $D/target.d \
$D/probing.d $D/sapply.d $D/sideeffect.d $D/statement.d $D/staticassert.d $D/target.d \
$D/safe.d $D/blockexit.d $D/permissivevisitor.d $D/transitivevisitor.d $D/parsetimevisitor.d $D/printast.d $D/typesem.d \
$D/traits.d $D/utils.d $D/visitor.d $D/libomf.d $D/scanomf.d $D/templateparamsem.d $D/typinf.d \
$D/libmscoff.d $D/scanmscoff.d $D/statement_rewrite_walker.d $D/statementsem.d $D/staticcond.d \
Expand Down
12 changes: 12 additions & 0 deletions test/runnable/test_probing.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#!/usr/bin/env bash

set -e


if [ "${OS}" == "win32" -o "${OS}" == "win64" ]; then
expected="windows"
else
expected="posix"
fi

"${DMD}" -probe | grep "${expected}"