Skip to content

Commit 9b39c1e

Browse files
committed
Add external import path switch
1 parent 0e5c41f commit 9b39c1e

File tree

8 files changed

+111
-30
lines changed

8 files changed

+111
-30
lines changed

compiler/src/dmd/cli.d

+3
Original file line numberDiff line numberDiff line change
@@ -460,6 +460,9 @@ dmd -cov -unittest myprog.d
460460
Option("I=<directory>",
461461
"look for imports also in directory"
462462
),
463+
Option("extI=<directory>",
464+
"look for imports that are out of the currently compiling binary, used to set the module as DllImport"
465+
),
463466
Option("i[=<pattern>]",
464467
"include imported modules in the compilation",
465468
q"{$(P Enables "include imports" mode, where the compiler will include imported

compiler/src/dmd/dmodule.d

+3
Original file line numberDiff line numberDiff line change
@@ -417,6 +417,8 @@ extern (C++) final class Module : Package
417417
SearchOptFlags searchCacheFlags; // cached flags
418418
bool insearch;
419419

420+
bool isExplicitlyOutOfBinary; // Is this module known to be out of binary, and must be DllImport'd?
421+
420422
/**
421423
* A root module is one that will be compiled all the way to
422424
* object code. This field holds the root module that caused
@@ -536,6 +538,7 @@ extern (C++) final class Module : Package
536538
auto m = new Module(loc, filename, ident, 0, 0);
537539

538540
// TODO: apply import path information (pathInfo) on to module
541+
m.isExplicitlyOutOfBinary = importPathThatFoundUs.isOutOfBinary;
539542

540543
if (!m.read(loc))
541544
return null;

compiler/src/dmd/e2ir.d

+78-25
Original file line numberDiff line numberDiff line change
@@ -498,52 +498,105 @@ private __gshared StringTable!(Symbol*) *stringTab;
498498
/*********************************************
499499
* Figure out whether a data symbol should be dllimported
500500
* Params:
501-
* var = declaration of the symbol
501+
* symbl = declaration of the symbol
502502
* Returns:
503503
* true if symbol should be imported from a DLL
504504
*/
505-
bool isDllImported(Dsymbol var)
505+
bool isDllImported(Dsymbol symbl)
506506
{
507+
// Windows is the only platform which dmd supports, that uses the DllImport/DllExport scheme.
507508
if (!(target.os & Target.OS.Windows))
508509
return false;
509-
if (var.isImportedSymbol())
510+
511+
// If function does not have a body, check to see if its marked as DllImport or is set to be exported.
512+
// If a global variable has both export + extern, it is DllImport
513+
if (symbl.isImportedSymbol())
510514
return true;
511-
if (driverParams.symImport == SymImport.none)
512-
return false;
513-
if (auto vd = var.isDeclaration())
515+
516+
// Functions can go through the generated trampoline function.
517+
// Not efficient, but it works.
518+
if (symbl.isFuncDeclaration())
519+
return false; // can always jump through import table
520+
521+
// Global variables are allowed, but not TLS or read only memory.
522+
if (auto vd = symbl.isDeclaration())
523+
{
514524
if (!vd.isDataseg() || vd.isThreadlocal())
515525
return false;
516-
if (var.isFuncDeclaration())
517-
return false; // can always jump through import table
518-
if (auto tid = var.isTypeInfoDeclaration())
526+
}
527+
528+
final switch(driverParams.symImport)
519529
{
530+
case SymImport.none:
531+
// If DllImport overriding is disabled, do not change dllimport status.
532+
return false;
533+
534+
case SymImport.defaultLibsOnly:
535+
case SymImport.all:
536+
// If to access anything in druntime/phobos you need DllImport, verify against this.
537+
break;
538+
}
539+
const systemLibraryNeedDllImport = true;
540+
541+
// For TypeInfo's check to see if its in druntime and DllImport it
542+
if (auto tid = symbl.isTypeInfoDeclaration())
543+
{
544+
// Built in TypeInfo's are defined in druntime
520545
if (builtinTypeInfo(tid.tinfo))
521-
return true;
546+
return systemLibraryNeedDllImport;
547+
548+
// Convert TypeInfo to its symbol
522549
if (auto ad = isAggregate(tid.type))
523-
var = ad;
550+
symbl = ad;
524551
}
525-
if (driverParams.symImport == SymImport.defaultLibsOnly)
552+
526553
{
527-
auto m = var.getModule();
554+
// Filter the symbol based upon the module it is in.
555+
556+
auto m = symbl.getModule();
528557
if (!m || !m.md)
529558
return false;
530-
const id = m.md.packages.length ? m.md.packages[0] : null;
531-
if (id && id != Id.core && id != Id.std)
532-
return false;
533-
if (!id && m.md.id != Id.std && m.md.id != Id.object)
534-
return false;
559+
560+
if (driverParams.symImport == SymImport.all || m.isExplicitlyOutOfBinary)
561+
{
562+
// If a module is specified as being out of binary (-extI), then it is allowed to be DllImport.
563+
}
564+
else if (systemLibraryNeedDllImport)
565+
{
566+
// Filter out all modules that are not in druntime/phobos if we are only doing default libs only
567+
568+
const id = m.md.packages.length ? m.md.packages[0] : null;
569+
if (id && id != Id.core && id != Id.std)
570+
return false;
571+
if (!id && m.md.id != Id.std && m.md.id != Id.object)
572+
return false;
573+
}
535574
}
536-
else if (driverParams.symImport != SymImport.all)
537-
return false;
538-
if (auto mod = var.isModule())
539-
return !mod.isRoot(); // non-root ModuleInfo symbol
540-
if (var.inNonRoot())
575+
576+
// If symbol is a ModuleInfo, check to see if module is being compiled.
577+
if (auto mod = symbl.isModule())
578+
{
579+
const isBeingCompiled = mod.isRoot();
580+
return !isBeingCompiled; // non-root ModuleInfo symbol
581+
}
582+
583+
// Check to see if a template has been instatiated in current compilation,
584+
// if it is defined in a external module, its DllImport.
585+
if (symbl.inNonRoot())
541586
return true; // not instantiated, and defined in non-root
542-
if (auto ti = var.isInstantiated()) // && !defineOnDeclare(sym, false))
587+
588+
// If a template has been instatiated, only DllImport if it is codegen'ing
589+
if (auto ti = symbl.isInstantiated()) // && !defineOnDeclare(sym, false))
543590
return !ti.needsCodegen(); // instantiated but potentially culled (needsCodegen())
544-
if (auto vd = var.isVarDeclaration())
591+
592+
// If a variable declaration and is extern
593+
if (auto vd = symbl.isVarDeclaration())
594+
{
595+
// Shouldn't this be including an export check too???
545596
if (vd.storage_class & STC.extern_)
546597
return true; // externally defined global variable
598+
}
599+
547600
return false;
548601
}
549602

compiler/src/dmd/frontend.h

+7-3
Original file line numberDiff line numberDiff line change
@@ -7111,6 +7111,7 @@ class Module final : public Package
71117111
Dsymbol* searchCacheSymbol;
71127112
uint32_t searchCacheFlags;
71137113
bool insearch;
7114+
bool isExplicitlyOutOfBinary;
71147115
Module* importedFrom;
71157116
Array<Dsymbol* >* decldefs;
71167117
Array<Module* > aimports;
@@ -8349,12 +8350,15 @@ struct Verbose final
83498350
struct ImportPathInfo final
83508351
{
83518352
const char* path;
8353+
bool isOutOfBinary;
83528354
ImportPathInfo() :
8353-
path()
8355+
path(),
8356+
isOutOfBinary()
83548357
{
83558358
}
8356-
ImportPathInfo(const char* path) :
8357-
path(path)
8359+
ImportPathInfo(const char* path, bool isOutOfBinary = false) :
8360+
path(path),
8361+
isOutOfBinary(isOutOfBinary)
83588362
{}
83598363
};
83608364

compiler/src/dmd/globals.d

+1
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,7 @@ extern(C++) struct Verbose
153153

154154
extern (C++) struct ImportPathInfo {
155155
const(char)* path; // char*'s of where to look for import modules
156+
bool isOutOfBinary; // Will any module found from this path be out of binary?
156157
}
157158

158159
/// Put command line switches in here

compiler/src/dmd/globals.h

+10-2
Original file line numberDiff line numberDiff line change
@@ -158,9 +158,17 @@ struct Verbose
158158
struct ImportPathInfo
159159
{
160160
const char* path;
161+
d_bool isOutOfBinary;
161162

162-
ImportPathInfo() : path(NULL) { }
163-
ImportPathInfo(const char* p) : path(p) { }
163+
ImportPathInfo() :
164+
path(),
165+
isOutOfBinary()
166+
{
167+
}
168+
ImportPathInfo(const char* path, d_bool isOutOfBinary = false) :
169+
path(path),
170+
isOutOfBinary(isOutOfBinary)
171+
{}
164172
};
165173

166174
// Put command line switches in here

compiler/src/dmd/mars.d

+7
Original file line numberDiff line numberDiff line change
@@ -1573,6 +1573,13 @@ bool parseCommandLine(const ref Strings arguments, const size_t argc, ref Param
15731573
{
15741574
params.imppath.push(ImportPathInfo(p + 2 + (p[2] == '=')));
15751575
}
1576+
else if (startsWith(p + 1, "extI"))
1577+
{
1578+
// External import path switch -extI
1579+
auto importPathInfo = ImportPathInfo(p + 5 + (p[5] == '='));
1580+
importPathInfo.isOutOfBinary = true;
1581+
params.imppath.push(importPathInfo);
1582+
}
15761583
else if (p[1] == 'm' && p[2] == 'v' && p[3] == '=') // https://dlang.org/dmd.html#switch-mv
15771584
{
15781585
if (p[4] && strchr(p + 5, '='))

compiler/src/dmd/module.h

+2
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,8 @@ class Module final : public Package
100100
SearchOptFlags searchCacheFlags; // cached flags
101101
d_bool insearch;
102102

103+
d_bool isExplicitlyOutOfBinary; // Is this module known to be out of binary, and must be DllImport'd?
104+
103105
// module from command line we're imported from,
104106
// i.e. a module that will be taken all the
105107
// way to an object file

0 commit comments

Comments
 (0)