Slipstream LDC-specific main() mods directly into ddmd/mars.d

This commit is contained in:
Martin 2016-08-27 23:10:48 +02:00
parent 36edf4f200
commit 94d8cad554
4 changed files with 145 additions and 376 deletions

View file

@ -60,9 +60,7 @@
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#if LDC_POSIX
#include <errno.h>
#elif _WIN32
#if _WIN32
#include <windows.h>
#endif
@ -77,9 +75,6 @@ int rt_init();
// In ddmd/doc.d
void gendocfile(Module *m);
// In driver/main.d
void writeModuleDependencyFile();
using namespace opts;
extern void getenv_setargv(const char *envvar, int *pargc, char ***pargv);
@ -1010,45 +1005,6 @@ static void dumpPredefinedVersions() {
}
}
/// Emits the .json AST description file.
///
/// This (ugly) piece of code has been taken from DMD's mars.c and should be
/// kept in sync with the former.
static void emitJson(Modules &modules) {
OutBuffer buf;
json_generate(&buf, &modules);
// Write buf to file
const char *name = global.params.jsonfilename;
if (name && name[0] == '-' && name[1] == 0) {
// Write to stdout; assume it succeeds
size_t n = fwrite(buf.data, 1, buf.offset, stdout);
assert(n == buf.offset); // keep gcc happy about return values
} else {
/* The filename generation code here should be harmonized with
* Module::setOutfile()
*/
const char *jsonfilename;
if (name && *name) {
jsonfilename = FileName::defaultExt(name, global.json_ext);
} else {
// Generate json file name from first obj name
const char *n = (*global.params.objfiles)[0];
n = FileName::name(n);
// if (!FileName::absolute(name))
// name = FileName::combine(dir, name);
jsonfilename = FileName::forceExt(n, global.json_ext);
}
ensurePathToNameExists(Loc(), jsonfilename);
auto jsonfile = File::create(jsonfilename);
jsonfile->setbuffer(buf.data, buf.offset);
jsonfile->ref = 1;
writeFile(Loc(), jsonfile);
}
}
int cppmain(int argc, char **argv) {
#if LDC_LLVM_VER >= 309
llvm::sys::PrintStackTraceOnErrorSignal(argv[0]);
@ -1150,282 +1106,11 @@ int cppmain(int argc, char **argv) {
global.lib_ext = "a";
}
// Initialization
Type::_init();
Id::initialize();
Module::_init();
Target::_init();
Expression::_init();
builtin_init();
objc_init();
// Build import search path
if (global.params.imppath) {
for (unsigned i = 0; i < global.params.imppath->dim; i++) {
const char *path = (*global.params.imppath)[i];
Strings *a = FileName::splitPath(path);
if (a) {
if (!global.path)
global.path = new Strings();
global.path->append(a);
}
}
}
// Build string import search path
if (global.params.fileImppath) {
for (unsigned i = 0; i < global.params.fileImppath->dim; i++) {
const char *path = (*global.params.fileImppath)[i];
Strings *a = FileName::splitPath(path);
if (a) {
if (!global.filePath)
global.filePath = new Strings();
global.filePath->append(a);
}
}
}
if (global.params.addMain) {
// a dummy name, we never actually look up this file
files.push(global.main_d);
}
// Create Modules
Modules modules;
modules.reserve(files.dim);
for (unsigned i = 0; i < files.dim; i++) {
const char *name;
const char *p = files[i];
p = FileName::name(p); // strip path
const char *ext = FileName::ext(p);
char *newname;
if (ext) {
/* Deduce what to do with a file based on its extension
*/
#if LDC_POSIX
if (FileName::equals(ext, global.obj_ext))
#else
if (FileName::equals(ext, global.obj_ext) ||
FileName::equals(ext, global.obj_ext_alt))
#endif
{
global.params.objfiles->push(files[i]);
continue;
}
// Detect LLVM bitcode files on commandline
if (FileName::equals(ext, global.bc_ext)) {
global.params.bitcodeFiles->push(files[i]);
continue;
}
if (FileName::equals(ext, global.lib_ext)) {
global.params.libfiles->push(files[i]);
continue;
}
if (strcmp(ext, global.ddoc_ext) == 0) {
global.params.ddocfiles->push(files[i]);
continue;
}
if (FileName::equals(ext, global.json_ext)) {
global.params.doJsonGeneration = true;
global.params.jsonfilename = files[i];
continue;
}
#if !LDC_POSIX
if (FileName::equals(ext, "res")) {
global.params.resfile = files[i];
continue;
}
if (FileName::equals(ext, "def")) {
global.params.deffile = files[i];
continue;
}
if (FileName::equals(ext, "exe")) {
global.params.exefile = files[i];
continue;
}
#endif
/* Examine extension to see if it is a valid
* D source file extension
*/
if (FileName::equals(ext, global.mars_ext) ||
FileName::equals(ext, global.hdr_ext) ||
FileName::equals(ext, "dd")) {
ext--; // skip onto '.'
assert(*ext == '.');
newname = static_cast<char *>(mem.xmalloc((ext - p) + 1));
memcpy(newname, p, ext - p);
newname[ext - p] = 0; // strip extension
name = newname;
if (name[0] == 0 || strcmp(name, "..") == 0 || strcmp(name, ".") == 0)
goto Linvalid;
} else {
error(Loc(), "unrecognized file extension %s", ext);
fatal();
}
} else {
name = p;
if (!*name) {
Linvalid:
error(Loc(), "invalid file name '%s'", files[i]);
fatal();
}
}
/* At this point, name is the D source file name stripped of
* its path and extension.
*/
auto id = Identifier::idPool(name, strlen(name));
auto m = Module::create(files[i], id, global.params.doDocComments,
global.params.doHdrGeneration);
modules.push(m);
}
// Read files
/* Start by "reading" the dummy main.d file
*/
if (global.params.addMain) {
for (unsigned i = 0; 1; i++) {
assert(i != modules.dim);
Module *m = modules[i];
if (strcmp(m->srcfile->name->str, global.main_d) == 0) {
static const char buf[] = "int main(){return 0;}";
m->srcfile->setbuffer(const_cast<char *>(buf), sizeof(buf));
m->srcfile->ref = 1;
break;
}
}
}
// Single threaded
for (unsigned i = 0; i < modules.dim; i++) {
Module *m = modules[i];
m->read(Loc());
}
// Parse files
bool anydocfiles = false;
auto filecount = modules.dim;
for (unsigned filei = 0, modi = 0; filei < filecount; filei++, modi++) {
Module *m = modules[modi];
if (global.params.verbose)
fprintf(global.stdmsg, "parse %s\n", m->toChars());
if (!Module::rootModule)
Module::rootModule = m;
m->importedFrom = m; // m->isRoot() == true
m->parse(global.params.doDocComments);
buildTargetFiles(m, singleObj, createSharedLib || createStaticLib);
m->deleteObjFile();
if (m->isDocFile) {
anydocfiles = true;
gendocfile(m);
// Remove m from list of modules
modules.remove(modi);
modi--;
// Remove m's object file from list of object files
for (unsigned j = 0; j < global.params.objfiles->dim; j++) {
if (m->objfile->name->str == (*global.params.objfiles)[j]) {
global.params.objfiles->remove(j);
break;
}
}
if (global.params.objfiles->dim == 0)
global.params.link = false;
}
}
if (anydocfiles && modules.dim &&
(global.params.oneobj || global.params.objname)) {
error(Loc(), "conflicting Ddoc and obj generation options");
fatal();
}
if (global.errors)
fatal();
if (global.params.doHdrGeneration) {
/* Generate 'header' import files.
* Since 'header' import files must be independent of command
* line switches and what else is imported, they are generated
* before any semantic analysis.
*/
for (unsigned i = 0; i < modules.dim; i++) {
Module *m = modules[i];
if (global.params.verbose)
fprintf(global.stdmsg, "import %s\n", m->toChars());
genhdrfile(m);
}
}
if (global.errors)
fatal();
// load all unconditional imports for better symbol resolving
for (unsigned i = 0; i < modules.dim; i++) {
Module *m = modules[i];
if (global.params.verbose)
fprintf(global.stdmsg, "importall %s\n", m->toChars());
m->importAll(nullptr);
}
if (global.errors)
fatal();
// Do semantic analysis
for (unsigned i = 0; i < modules.dim; i++) {
Module *m = modules[i];
if (global.params.verbose)
fprintf(global.stdmsg, "semantic %s\n", m->toChars());
m->semantic(nullptr);
}
if (global.errors)
fatal();
Module::dprogress = 1;
Module::runDeferredSemantic();
if (Module::deferred.dim) {
for (unsigned i = 0; i < Module::deferred.dim; i++) {
Dsymbol *sd = Module::deferred[i];
sd->error("unable to resolve forward reference in definition");
}
fatal();
}
// Do pass 2 semantic analysis
for (unsigned i = 0; i < modules.dim; i++) {
Module *m = modules[i];
if (global.params.verbose)
fprintf(global.stdmsg, "semantic2 %s\n", m->toChars());
m->semantic2(nullptr);
}
if (global.errors)
fatal();
// Do pass 3 semantic analysis
for (unsigned i = 0; i < modules.dim; i++) {
Module *m = modules[i];
if (global.params.verbose)
fprintf(global.stdmsg, "semantic3 %s\n", m->toChars());
m->semantic3(nullptr);
}
Module::runDeferredSemantic3();
if (global.errors)
fatal();
// Do not attempt to generate output files if errors or warnings occurred
if (global.errors || global.warnings)
fatal();
// Now that we analyzed all modules, write the module dependency file if
// the user requested it.
writeModuleDependencyFile();
// Generate the AST-describing JSON file.
if (global.params.doJsonGeneration)
emitJson(modules);
// Generate DDoc output files.
if (!global.errors && global.params.doDocComments) {
for (unsigned i = 0; i < modules.dim; i++) {
Module *m = modules[i];
gendocfile(m);
}
}
Strings libmodules;
return mars_mainBody(files, libmodules, createStaticLib, createSharedLib, staticFlag);
}
void codegenModules(Modules &modules) {
// Generate one or more object/IR/bitcode files.
if (global.params.obj && !modules.empty()) {
ldc::CodeGenerator cg(getGlobalContext(), singleObj);
@ -1452,37 +1137,4 @@ int cppmain(int argc, char **argv) {
freeRuntime();
llvm::llvm_shutdown();
if (global.errors)
fatal();
// Finally, produce the final executable/archive and run it, if we are
// supposed to.
int status = EXIT_SUCCESS;
if (!global.params.objfiles->dim) {
if (global.params.link) {
error(Loc(), "no object files to link");
} else if (createStaticLib) {
error(Loc(), "no object files");
}
} else {
if (global.params.link) {
status = linkObjToBinary(createSharedLib, staticFlag);
} else if (createStaticLib) {
status = createStaticLibrary();
}
if (global.params.run) {
if (!status) {
status = runProgram();
/* Delete .obj files and .exe file
*/
for (unsigned i = 0; i < modules.dim; i++) {
modules[i]->deleteObjFile();
}
deleteExeFile();
}
}
}
return status;
}