Rip out FileCache and replace with FileManager (#13193)

This commit is contained in:
Harrison 2021-10-27 02:51:19 -04:00 committed by GitHub
parent c0dab2b877
commit 469890bac1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 448 additions and 294 deletions

View file

@ -22,7 +22,7 @@ subPackage {
"src/dmd/console.d" \
"src/dmd/entity.d" \
"src/dmd/errors.d" \
"src/dmd/filecache.d" \
"src/dmd/file_manager.d" \
"src/dmd/globals.d" \
"src/dmd/id.d" \
"src/dmd/identifier.d" \
@ -92,7 +92,7 @@ subPackage {
console,\
entity,\
errors,\
filecache,\
file_manager,\
globals,\
id,\
identifier,\

View file

@ -1406,7 +1406,7 @@ auto sourceFiles()
statement.h staticassert.h target.h template.h tokens.h version.h visitor.h
"),
lexer: fileArray(env["D"], "
console.d entity.d errors.d filecache.d globals.d id.d identifier.d lexer.d tokens.d utf.d
console.d entity.d errors.d file_manager.d globals.d id.d identifier.d lexer.d tokens.d utf.d
") ~ fileArray(env["ROOT"], "
array.d bitarray.d ctfloat.d file.d filename.d hash.d port.d region.d rmem.d
rootobject.d stringtable.d

View file

@ -245,14 +245,14 @@ Note that these groups have no strict meaning, the category assignments are a bi
Note: many other utilities are in [dmd/root](https://github.com/dlang/dmd/tree/master/src/dmd/root).
| File | Purpose |
|-----------------------------------------------------------------------------|---------------------------------------------------|
| [env.d](https://github.com/dlang/dmd/blob/master/src/dmd/env.d) | Modify environment variables |
| [console.d](https://github.com/dlang/dmd/blob/master/src/dmd/console.d) | Print error messages in color |
| [utf.d](https://github.com/dlang/dmd/blob/master/src/dmd/utf.d) | Encoding/decoding Unicode text |
| [filecache.d](https://github.com/dlang/dmd/blob/master/src/dmd/filecache.d) | Keep file contents in memory |
| [utils.d](https://github.com/dlang/dmd/blob/master/src/dmd/utils.d) | Utility functions related to files and file paths |
| [complex.d](https://github.com/dlang/dmd/blob/master/src/dmd/complex.d) | A complex number type |
| File | Purpose |
|-----------------------------------------------------------------------------------|---------------------------------------------------|
| [env.d](https://github.com/dlang/dmd/blob/master/src/dmd/env.d) | Modify environment variables |
| [console.d](https://github.com/dlang/dmd/blob/master/src/dmd/console.d) | Print error messages in color |
| [utf.d](https://github.com/dlang/dmd/blob/master/src/dmd/utf.d) | Encoding/decoding Unicode text |
| [file_manager.d](https://github.com/dlang/dmd/blob/master/src/dmd/file_manager.d) | Keep file contents in memory |
| [utils.d](https://github.com/dlang/dmd/blob/master/src/dmd/utils.d) | Utility functions related to files and file paths |
| [complex.d](https://github.com/dlang/dmd/blob/master/src/dmd/complex.d) | A complex number type |
| File | Purpose |
|---------------------------------------------------------------------------------|---------------------------------------------------------------|

View file

@ -31,6 +31,7 @@ import dmd.dsymbolsem;
import dmd.errors;
import dmd.expression;
import dmd.expressionsem;
import dmd.file_manager;
import dmd.globals;
import dmd.id;
import dmd.identifier;
@ -50,113 +51,6 @@ import dmd.target;
import dmd.utils;
import dmd.visitor;
enum package_d = "package." ~ mars_ext;
enum package_di = "package." ~ hdr_ext;
/********************************************
* Look for the source file if it's different from filename.
* Look for .di, .d, directory, and along global.path.
* Does not open the file.
* Params:
* filename = as supplied by the user
* path = path to look for filename
* Returns:
* the found file name or
* `null` if it is not different from filename.
*/
private const(char)[] lookForSourceFile(const char[] filename, const char*[] path)
{
//printf("lookForSourceFile(`%.*s`)\n", cast(int)filename.length, filename.ptr);
/* Search along path[] for .di file, then .d file, then .i file, then .c file.
*/
const sdi = FileName.forceExt(filename, hdr_ext);
if (FileName.exists(sdi) == 1)
return sdi;
scope(exit) FileName.free(sdi.ptr);
const sd = FileName.forceExt(filename, mars_ext);
if (FileName.exists(sd) == 1)
return sd;
scope(exit) FileName.free(sd.ptr);
const si = FileName.forceExt(filename, i_ext);
if (FileName.exists(si) == 1)
return si;
scope(exit) FileName.free(si.ptr);
const sc = FileName.forceExt(filename, c_ext);
if (FileName.exists(sc) == 1)
return sc;
scope(exit) FileName.free(sc.ptr);
if (FileName.exists(filename) == 2)
{
/* The filename exists and it's a directory.
* Therefore, the result should be: filename/package.d
* iff filename/package.d is a file
*/
const ni = FileName.combine(filename, package_di);
if (FileName.exists(ni) == 1)
return ni;
FileName.free(ni.ptr);
const n = FileName.combine(filename, package_d);
if (FileName.exists(n) == 1)
return n;
FileName.free(n.ptr);
}
if (FileName.absolute(filename))
return null;
if (!path.length)
return null;
foreach (entry; path)
{
const p = entry.toDString();
const(char)[] n = FileName.combine(p, sdi);
if (FileName.exists(n) == 1) {
return n;
}
FileName.free(n.ptr);
n = FileName.combine(p, sd);
if (FileName.exists(n) == 1) {
return n;
}
FileName.free(n.ptr);
n = FileName.combine(p, si);
if (FileName.exists(n) == 1) {
return n;
}
FileName.free(n.ptr);
n = FileName.combine(p, sc);
if (FileName.exists(n) == 1) {
return n;
}
FileName.free(n.ptr);
const b = FileName.removeExt(filename);
n = FileName.combine(p, b);
FileName.free(b.ptr);
if (FileName.exists(n) == 2)
{
const n2i = FileName.combine(n, package_di);
if (FileName.exists(n2i) == 1)
return n2i;
FileName.free(n2i.ptr);
const n2 = FileName.combine(n, package_d);
if (FileName.exists(n2) == 1) {
return n2;
}
FileName.free(n2.ptr);
}
FileName.free(n.ptr);
}
return null;
}
// function used to call semantic3 on a module's dependencies
void semantic3OnDependencies(Module m)
{
@ -414,7 +308,7 @@ extern (C++) class Package : ScopeDsymbol
packages ~= s.ident;
reverse(packages);
if (lookForSourceFile(getFilename(packages, ident), global.path ? (*global.path)[] : null))
if (FileManager.lookForSourceFile(getFilename(packages, ident), global.path ? (*global.path)[] : null))
Module.load(Loc.initial, packages, this.ident);
else
isPkgMod = PKG.package_;
@ -612,7 +506,7 @@ extern (C++) final class Module : Package
// foo\bar\baz
const(char)[] filename = getFilename(packages, ident);
// Look for the source file
if (const result = lookForSourceFile(filename, global.path ? (*global.path)[] : null))
if (const result = FileManager.lookForSourceFile(filename, global.path ? (*global.path)[] : null))
filename = result; // leaks
auto m = new Module(loc, filename, ident, 0, 0);
@ -781,14 +675,25 @@ extern (C++) final class Module : Package
return true; // already read
//printf("Module::read('%s') file '%s'\n", toChars(), srcfile.toChars());
auto readResult = File.read(srcfile.toChars());
if (global.params.emitMakeDeps)
{
global.params.makeDeps.push(srcfile.toChars());
}
return loadSourceBuffer(loc, readResult);
if (auto readResult = FileManager.fileManager.lookup(srcfile))
{
srcBuffer = readResult;
return true;
}
auto readResult = File.read(srcfile.toChars());
if (loadSourceBuffer(loc, readResult))
{
FileManager.fileManager.add(srcfile, srcBuffer);
return true;
}
return false;
}
/// syntactic parse

View file

@ -387,29 +387,33 @@ private void verrorPrint(const ref Loc loc, Color headerColor, const(char)* head
!loc.filename.strstr(".d-mixin-") &&
!global.params.mixinOut)
{
import dmd.filecache : FileCache;
auto fllines = FileCache.fileCache.addOrGetFile(loc.filename.toDString());
if (loc.linnum - 1 < fllines.lines.length)
import dmd.file_manager : FileManager;
import dmd.root.filename : FileName;
const fileName = FileName(loc.filename.toDString);
if (auto file = FileManager.fileManager.lookup(fileName))
{
auto line = fllines.lines[loc.linnum - 1];
if (loc.charnum < line.length)
const(char)[][] lines = FileManager.fileManager.getLines(fileName);
if (loc.linnum - 1 < lines.length)
{
fprintf(stderr, "%.*s\n", cast(int)line.length, line.ptr);
// The number of column bytes and the number of display columns
// occupied by a character are not the same for non-ASCII charaters.
// https://issues.dlang.org/show_bug.cgi?id=21849
size_t c = 0;
while (c < loc.charnum - 1)
auto line = lines[loc.linnum - 1];
if (loc.charnum < line.length)
{
import dmd.utf : utf_decodeChar;
dchar u;
const msg = utf_decodeChar(line, c, u);
assert(msg is null, msg);
fputc(' ', stderr);
fprintf(stderr, "%.*s\n", cast(int)line.length, line.ptr);
// The number of column bytes and the number of display columns
// occupied by a character are not the same for non-ASCII charaters.
// https://issues.dlang.org/show_bug.cgi?id=21849
size_t c = 0;
while (c < loc.charnum - 1)
{
import dmd.utf : utf_decodeChar;
dchar u;
const msg = utf_decodeChar(line, c, u);
assert(msg is null, msg);
fputc(' ', stderr);
}
fputc('^', stderr);
fputc('\n', stderr);
}
fputc('^', stderr);
fputc('\n', stderr);
}
}
}

View file

@ -43,6 +43,7 @@ import dmd.dtemplate;
import dmd.errors;
import dmd.escape;
import dmd.expression;
import dmd.file_manager;
import dmd.func;
import dmd.globals;
import dmd.hdrgen;
@ -6051,17 +6052,29 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
}
{
auto readResult = File.read(name);
if (!readResult.success)
auto fileName = FileName(name.toDString);
if (auto fmResult = FileManager.fileManager.lookup(fileName))
{
e.error("cannot read file `%s`", name);
return setError();
se = new StringExp(e.loc, fmResult.data);
}
else
{
// take ownership of buffer (probably leaking)
auto data = readResult.extractSlice();
se = new StringExp(e.loc, data);
auto readResult = File.read(name);
if (!readResult.success)
{
e.error("cannot read file `%s`", name);
return setError();
}
else
{
// take ownership of buffer (probably leaking)
auto data = readResult.extractSlice();
se = new StringExp(e.loc, data);
FileBuffer* fileBuffer = FileBuffer.create();
fileBuffer.data = data;
FileManager.fileManager.add(fileName, fileBuffer);
}
}
}
result = se.expressionSemantic(sc);

301
src/dmd/file_manager.d Normal file
View file

@ -0,0 +1,301 @@
/**
* Read a file from disk and store it in memory.
*
* Copyright: Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved
* 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/file_manager.d, _file_manager.d)
* Documentation: https://dlang.org/phobos/dmd_file_manager.html
* Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/file_manager.d
*/
module dmd.file_manager;
import dmd.root.stringtable : StringTable;
import dmd.root.file : File, FileBuffer;
import dmd.root.filename : FileName;
import dmd.root.string : toDString;
import dmd.globals;
import dmd.identifier;
enum package_d = "package." ~ mars_ext;
enum package_di = "package." ~ hdr_ext;
extern(C++) struct FileManager
{
private StringTable!(FileBuffer*) files;
private __gshared bool initialized = false;
nothrow:
extern(D) private FileBuffer* readToFileBuffer(const(char)[] filename)
{
if (!initialized)
FileManager._init();
auto readResult = File.read(filename);
if (readResult.success)
{
FileBuffer* fb;
if (auto val = files.lookup(filename))
fb = val.value;
if (!fb)
fb = FileBuffer.create();
fb.data = readResult.extractSlice();
return files.insert(filename, fb) == null ? null : fb;
}
else
{
return null;
}
}
/********************************************
* Look for the source file if it's different from filename.
* Look for .di, .d, directory, and along global.path.
* Does not open the file.
* Params:
* filename = as supplied by the user
* path = path to look for filename
* Returns:
* the found file name or
* `null` if it is not different from filename.
*/
extern(D) static const(char)[] lookForSourceFile(const char[] filename, const char*[] path)
{
//printf("lookForSourceFile(`%.*s`)\n", cast(int)filename.length, filename.ptr);
/* Search along path[] for .di file, then .d file, then .i file, then .c file.
*/
const sdi = FileName.forceExt(filename, hdr_ext);
if (FileName.exists(sdi) == 1)
return sdi;
scope(exit) FileName.free(sdi.ptr);
const sd = FileName.forceExt(filename, mars_ext);
if (FileName.exists(sd) == 1)
return sd;
scope(exit) FileName.free(sd.ptr);
const si = FileName.forceExt(filename, i_ext);
if (FileName.exists(si) == 1)
return si;
scope(exit) FileName.free(si.ptr);
const sc = FileName.forceExt(filename, c_ext);
if (FileName.exists(sc) == 1)
return sc;
scope(exit) FileName.free(sc.ptr);
if (FileName.exists(filename) == 2)
{
/* The filename exists and it's a directory.
* Therefore, the result should be: filename/package.d
* iff filename/package.d is a file
*/
const ni = FileName.combine(filename, package_di);
if (FileName.exists(ni) == 1)
return ni;
FileName.free(ni.ptr);
const n = FileName.combine(filename, package_d);
if (FileName.exists(n) == 1)
return n;
FileName.free(n.ptr);
}
if (FileName.absolute(filename))
return null;
if (!path.length)
return null;
foreach (entry; path)
{
const p = entry.toDString();
const(char)[] n = FileName.combine(p, sdi);
if (FileName.exists(n) == 1) {
return n;
}
FileName.free(n.ptr);
n = FileName.combine(p, sd);
if (FileName.exists(n) == 1) {
return n;
}
FileName.free(n.ptr);
n = FileName.combine(p, si);
if (FileName.exists(n) == 1) {
return n;
}
FileName.free(n.ptr);
n = FileName.combine(p, sc);
if (FileName.exists(n) == 1) {
return n;
}
FileName.free(n.ptr);
const b = FileName.removeExt(filename);
n = FileName.combine(p, b);
FileName.free(b.ptr);
if (FileName.exists(n) == 2)
{
const n2i = FileName.combine(n, package_di);
if (FileName.exists(n2i) == 1)
return n2i;
FileName.free(n2i.ptr);
const n2 = FileName.combine(n, package_d);
if (FileName.exists(n2) == 1) {
return n2;
}
FileName.free(n2.ptr);
}
FileName.free(n.ptr);
}
return null;
}
/**
* Looks up the given filename from the internal file buffer table.
* If the file does not already exist within the table, it will be read from the filesystem.
* If it has been read before,
*
* Returns: the loaded source file if it was found in memory,
* otherwise `null`
*/
extern(D) FileBuffer* lookup(FileName filename)
{
if (!initialized)
FileManager._init();
if (auto val = files.lookup(filename.toString))
{
// There is a chance that the buffer could've been
// stolen by a reader with extractSlice, so we should
// try and do our reading logic if that happens.
if (val !is null && val.value.data !is null)
{
return val.value;
}
}
const name = filename.toString;
auto res = FileName.exists(name);
if (res == 1)
return readToFileBuffer(name);
const fullName = lookForSourceFile(name, global.path ? (*global.path)[] : null);
if (!fullName)
return null;
return readToFileBuffer(fullName);
}
extern(C++) FileBuffer* lookup(const(char)* filename)
{
return lookup(FileName(filename.toDString));
}
/**
* Looks up the given filename from the internal file buffer table, and returns the lines within the file.
* If the file does not already exist within the table, it will be read from the filesystem.
* If it has been read before,
*
* Returns: the loaded source file if it was found in memory,
* otherwise `null`
*/
extern(D) const(char)[][] getLines(FileName file)
{
if (!initialized)
FileManager._init();
const(char)[][] lines;
if (FileBuffer* buffer = lookup(file))
{
ubyte[] slice = buffer.data[0 .. buffer.data.length];
size_t start, end;
ubyte c;
for (auto i = 0; i < slice.length; i++)
{
c = slice[i];
if (c == '\n' || c == '\r')
{
if (i != 0)
{
end = i;
lines ~= cast(const(char)[])slice[start .. end];
}
// Check for Windows-style CRLF newlines
if (c == '\r')
{
if (slice.length > i + 1 && slice[i + 1] == '\n')
{
// This is a CRLF sequence, skip over two characters
start = i + 2;
i++;
}
else
{
// Just a CR sequence
start = i + 1;
}
}
else
{
// The next line should start after the LF sequence
start = i + 1;
}
}
}
if (slice[$ - 1] != '\r' && slice[$ - 1] != '\n')
{
end = slice.length;
lines ~= cast(const(char)[])slice[start .. end];
}
}
return lines;
}
/**
* Adds a FileBuffer to the table.
*
* Returns: The FileBuffer added, or null
*/
extern(D) FileBuffer* add(FileName filename, FileBuffer* filebuffer)
{
if (!initialized)
FileManager._init();
auto val = files.insert(filename.toString, filebuffer);
return val == null ? null : val.value;
}
extern(C++) FileBuffer* add(const(char)* filename, FileBuffer* filebuffer)
{
if (!initialized)
FileManager._init();
auto val = files.insert(filename.toDString, filebuffer);
return val == null ? null : val.value;
}
__gshared fileManager = FileManager();
// Initialize the global FileManager singleton
extern(C++) static __gshared void _init()
{
if (!initialized)
{
fileManager.initialize();
initialized = true;
}
}
void initialize()
{
files._init();
}
}

19
src/dmd/file_manager.h Normal file
View file

@ -0,0 +1,19 @@
/* Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
* written by Walter Bright
* http://www.digitalmars.com
* Distributed under the Boost Software License, Version 1.0.
* http://www.boost.org/LICENSE_1_0.txt
* https://github.com/dlang/dmd/blob/master/src/dmd/file_manager.h
*/
#pragma once
#include "root/file.h"
struct FileManager
{
static void _init();
FileBuffer* lookup(const char* filename);
FileBuffer* add(const char* filename, FileBuffer* filebuffer);
};

View file

@ -1,137 +0,0 @@
/**
* Cache the contents from files read from disk into memory.
*
* Copyright: Copyright (C) 1999-2021 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/filecache.d, filecache.d)
* Documentation: https://dlang.org/phobos/dmd_filecache.html
* Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/filecache.d
*/
module dmd.filecache;
import dmd.root.stringtable;
import dmd.root.array;
import dmd.root.file;
import dmd.root.filename;
import core.stdc.stdio;
/**
A line-by-line representation of a $(REF File, dmd,root,file).
*/
class FileAndLines
{
FileName* file;
FileBuffer* buffer;
const(char[])[] lines;
nothrow:
/**
File to read and split into its lines.
*/
this(const(char)[] filename)
{
file = new FileName(filename);
readAndSplit();
}
// Read a file and split the file buffer linewise
private void readAndSplit()
{
auto readResult = File.read(file.toChars());
// FIXME: check success
// take ownership of buffer
buffer = new FileBuffer(readResult.extractSlice());
ubyte* buf = buffer.data.ptr;
// slice into lines
while (*buf)
{
auto prevBuf = buf;
for (; *buf != '\n' && *buf != '\r'; buf++)
{
if (!*buf)
break;
}
// handle Windows line endings
if (*buf == '\r' && *(buf + 1) == '\n')
buf++;
lines ~= cast(const(char)[]) prevBuf[0 .. buf - prevBuf];
buf++;
}
}
void destroy()
{
if (file)
{
file.destroy();
file = null;
buffer.destroy();
buffer = null;
lines.destroy();
lines = null;
}
}
~this()
{
destroy();
}
}
/**
A simple file cache that can be used to avoid reading the same file multiple times.
It stores its cached files as $(LREF FileAndLines)
*/
struct FileCache
{
private StringTable!(FileAndLines) files;
nothrow:
/**
Add or get a file from the file cache.
If the file isn't part of the cache, it will be read from the filesystem.
If the file has been read before, the cached file object will be returned
Params:
file = file to load in (or get from) the cache
Returns: a $(LREF FileAndLines) object containing a line-by-line representation of the requested file
*/
FileAndLines addOrGetFile(const(char)[] file)
{
if (auto payload = files.lookup(file))
{
if (payload !is null)
return payload.value;
}
auto lines = new FileAndLines(file);
files.insert(file, lines);
return lines;
}
__gshared fileCache = FileCache();
// Initializes the global FileCache singleton
static __gshared void _init()
{
fileCache.initialize();
}
void initialize()
{
files._init();
}
void deinitialize()
{
foreach (sv; files)
sv.destroy();
files.reset();
}
}

View file

@ -116,7 +116,6 @@ void initDMD(
import dmd.cond : VersionCondition;
import dmd.dmodule : Module;
import dmd.expression : Expression;
import dmd.filecache : FileCache;
import dmd.globals : CHECKENABLE, global;
import dmd.id : Id;
import dmd.identifier : Identifier;
@ -148,7 +147,6 @@ void initDMD(
Module._init();
Expression._init();
Objc._init();
FileCache._init();
addDefaultVersionIdentifiers(global.params, target);
@ -401,7 +399,12 @@ Tuple!(Module, "module_", Diagnostics, "diagnostics") parseModule(AST = ASTCodeg
buffer: FileBuffer(cast(ubyte[]) code.dup ~ '\0')
};
m.loadSourceBuffer(Loc.initial, readResult);
if (m.loadSourceBuffer(Loc.initial, readResult))
{
import dmd.file_manager : FileManager;
import dmd.root.filename : FileName;
FileManager.fileManager.add(FileName(fileName), m.srcBuffer);
}
}
m.parseModule!AST();

View file

@ -2488,10 +2488,6 @@ struct MatchAccumulator final
{}
};
static const char* const package_d = "package.d";
static const char* const package_di = "package.di";
enum class StructFlags
{
none = 0,
@ -4987,6 +4983,40 @@ enum class CPU
native = 12,
};
struct StringEntry final
{
uint32_t hash;
uint32_t vptr;
StringEntry() :
hash(),
vptr()
{
}
StringEntry(uint32_t hash, uint32_t vptr = 0u) :
hash(hash),
vptr(vptr)
{}
};
template <typename T>
struct StringTable final
{
// Ignoring var table alignment 0
_d_dynamicArray< StringEntry > table;
// Ignoring var pools alignment 0
_d_dynamicArray< uint8_t* > pools;
// Ignoring var nfill alignment 0
size_t nfill;
// Ignoring var count alignment 0
size_t count;
// Ignoring var countTrigger alignment 0
size_t countTrigger;
~StringTable();
StringTable()
{
}
};
typedef _d_real longdouble;
class AggregateDeclaration : public ScopeDsymbol
@ -7883,6 +7913,22 @@ extern void fatal();
extern void halt();
struct FileManager final
{
private:
StringTable<FileBuffer* > files;
static bool initialized;
public:
FileBuffer* lookup(const char* filename);
FileBuffer* add(const char* filename, FileBuffer* filebuffer);
static FileManager fileManager;
static void _init();
void initialize();
FileManager()
{
}
};
struct Id final
{
static Identifier* IUnknown;

View file

@ -38,6 +38,7 @@ import dmd.dtemplate;
import dmd.dtoh;
import dmd.errors;
import dmd.expression;
import dmd.file_manager;
import dmd.globals;
import dmd.hdrgen;
import dmd.id;
@ -300,8 +301,6 @@ private int tryMain(size_t argc, const(char)** argv, ref Param params)
Module._init();
Expression._init();
Objc._init();
import dmd.filecache : FileCache;
FileCache._init();
reconcileLinkRunLib(params, files.dim);
version(CRuntime_Microsoft)
@ -362,6 +361,7 @@ private int tryMain(size_t argc, const(char)** argv, ref Param params)
{
auto buffer = readFromStdin();
m.srcBuffer = new FileBuffer(buffer.extractSlice());
FileManager.fileManager.add(m.srcfile, m.srcBuffer);
}
}