Streamline main() with DMD's (ddmd/mars.d)

This commit is contained in:
Martin 2016-08-27 15:54:47 +02:00
parent 37559774a7
commit 24cecc268c
4 changed files with 170 additions and 168 deletions

View file

@ -762,7 +762,7 @@ int createStaticLibrary() {
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
void deleteExecutable() { void deleteExeFile() {
if (!gExePath.empty() && !llvm::sys::fs::is_directory(gExePath)) { if (!gExePath.empty() && !llvm::sys::fs::is_directory(gExePath)) {
llvm::sys::fs::remove(gExePath); llvm::sys::fs::remove(gExePath);
} }
@ -770,7 +770,7 @@ void deleteExecutable() {
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
int runExecutable() { int runProgram() {
assert(!gExePath.empty()); assert(!gExePath.empty());
// assert(gExePath.isValid()); // assert(gExePath.isValid());

View file

@ -43,12 +43,12 @@ int createStaticLibrary();
/** /**
* Delete the executable that was previously linked with linkObjToBinary. * Delete the executable that was previously linked with linkObjToBinary.
*/ */
void deleteExecutable(); void deleteExeFile();
/** /**
* Runs the executable that was previously linked with linkObjToBinary. * Runs the executable that was previously linked with linkObjToBinary.
* @return the return status of the executable. * @return the return status of the executable.
*/ */
int runExecutable(); int runProgram();
#endif // LDC_DRIVER_LINKER_H #endif // LDC_DRIVER_LINKER_H

View file

@ -1020,10 +1020,10 @@ static void emitJson(Modules &modules) {
// Write buf to file // Write buf to file
const char *name = global.params.jsonfilename; const char *name = global.params.jsonfilename;
if (name && name[0] == '-' && name[1] == 0) {
if (name && name[0] == '-' && // Write to stdout; assume it succeeds
name[1] == 0) { // Write to stdout; assume it succeeds size_t n = fwrite(buf.data, 1, buf.offset, stdout);
(void)fwrite(buf.data, 1, buf.offset, stdout); assert(n == buf.offset); // keep gcc happy about return values
} else { } else {
/* The filename generation code here should be harmonized with /* The filename generation code here should be harmonized with
* Module::setOutfile() * Module::setOutfile()
@ -1036,17 +1036,13 @@ static void emitJson(Modules &modules) {
// Generate json file name from first obj name // Generate json file name from first obj name
const char *n = (*global.params.objfiles)[0]; const char *n = (*global.params.objfiles)[0];
n = FileName::name(n); n = FileName::name(n);
// if (!FileName::absolute(name)) // if (!FileName::absolute(name))
// name = FileName::combine(dir, name); // name = FileName::combine(dir, name);
jsonfilename = FileName::forceExt(n, global.json_ext); jsonfilename = FileName::forceExt(n, global.json_ext);
} }
ensurePathToNameExists(Loc(), jsonfilename); ensurePathToNameExists(Loc(), jsonfilename);
auto jsonfile = File::create(jsonfilename); auto jsonfile = File::create(jsonfilename);
jsonfile->setbuffer(buf.data, buf.offset); jsonfile->setbuffer(buf.data, buf.offset);
jsonfile->ref = 1; jsonfile->ref = 1;
writeFile(Loc(), jsonfile); writeFile(Loc(), jsonfile);
@ -1147,7 +1143,8 @@ int cppmain(int argc, char **argv) {
if (global.params.targetTriple->isOSWindows()) { if (global.params.targetTriple->isOSWindows()) {
global.dll_ext = "dll"; global.dll_ext = "dll";
global.lib_ext = "lib"; global.lib_ext =
(global.params.targetTriple->isWindowsMSVCEnvironment() ? "lib" : "a");
} else { } else {
global.dll_ext = "so"; global.dll_ext = "so";
global.lib_ext = "a"; global.lib_ext = "a";
@ -1165,14 +1162,11 @@ int cppmain(int argc, char **argv) {
// Build import search path // Build import search path
if (global.params.imppath) { if (global.params.imppath) {
for (unsigned i = 0; i < global.params.imppath->dim; i++) { for (unsigned i = 0; i < global.params.imppath->dim; i++) {
const char *path = const char *path = (*global.params.imppath)[i];
static_cast<const char *>(global.params.imppath->data[i]);
Strings *a = FileName::splitPath(path); Strings *a = FileName::splitPath(path);
if (a) { if (a) {
if (!global.path) { if (!global.path)
global.path = new Strings(); global.path = new Strings();
}
global.path->append(a); global.path->append(a);
} }
} }
@ -1181,14 +1175,11 @@ int cppmain(int argc, char **argv) {
// Build string import search path // Build string import search path
if (global.params.fileImppath) { if (global.params.fileImppath) {
for (unsigned i = 0; i < global.params.fileImppath->dim; i++) { for (unsigned i = 0; i < global.params.fileImppath->dim; i++) {
const char *path = const char *path = (*global.params.fileImppath)[i];
static_cast<const char *>(global.params.fileImppath->data[i]);
Strings *a = FileName::splitPath(path); Strings *a = FileName::splitPath(path);
if (a) { if (a) {
if (!global.filePath) { if (!global.filePath)
global.filePath = new Strings(); global.filePath = new Strings();
}
global.filePath->append(a); global.filePath->append(a);
} }
} }
@ -1196,151 +1187,156 @@ int cppmain(int argc, char **argv) {
if (global.params.addMain) { if (global.params.addMain) {
// a dummy name, we never actually look up this file // a dummy name, we never actually look up this file
files.push(const_cast<char *>(global.main_d)); files.push(global.main_d);
} }
// Create Modules // Create Modules
Modules modules; Modules modules;
modules.reserve(files.dim); modules.reserve(files.dim);
for (unsigned i = 0; i < files.dim; i++) { for (unsigned i = 0; i < files.dim; i++) {
Identifier *id;
const char *ext;
const char *name; const char *name;
const char *p = files[i];
const char *p = files.data[i];
p = FileName::name(p); // strip path p = FileName::name(p); // strip path
ext = FileName::ext(p); const char *ext = FileName::ext(p);
char *newname;
if (ext) { if (ext) {
/* Deduce what to do with a file based on its extension
*/
#if LDC_POSIX #if LDC_POSIX
if (strcmp(ext, global.obj_ext) == 0) if (FileName::equals(ext, global.obj_ext))
#else #else
if (Port::stricmp(ext, global.obj_ext) == 0 || if (FileName::equals(ext, global.obj_ext) ||
Port::stricmp(ext, global.obj_ext_alt) == 0) FileName::equals(ext, global.obj_ext_alt))
#endif #endif
{ {
global.params.objfiles->push(static_cast<const char *>(files.data[i])); global.params.objfiles->push(files[i]);
continue; continue;
} }
// Detect LLVM bitcode files on commandline // Detect LLVM bitcode files on commandline
#if LDC_POSIX if (FileName::equals(ext, global.bc_ext)) {
if (strcmp(ext, global.bc_ext) == 0) global.params.bitcodeFiles->push(files[i]);
#else
if (Port::stricmp(ext, global.bc_ext) == 0)
#endif
{
global.params.bitcodeFiles->push(static_cast<const char *>(files.data[i]));
continue; continue;
} }
if (FileName::equals(ext, global.lib_ext)) {
#if LDC_POSIX global.params.libfiles->push(files[i]);
if (strcmp(ext, "a") == 0)
#elif __MINGW32__
if (Port::stricmp(ext, "a") == 0)
#else
if (Port::stricmp(ext, "lib") == 0)
#endif
{
global.params.libfiles->push(static_cast<const char *>(files.data[i]));
continue; continue;
} }
if (strcmp(ext, global.ddoc_ext) == 0) { if (strcmp(ext, global.ddoc_ext) == 0) {
global.params.ddocfiles->push(static_cast<const char *>(files.data[i])); global.params.ddocfiles->push(files[i]);
continue; continue;
} }
if (FileName::equals(ext, global.json_ext)) { if (FileName::equals(ext, global.json_ext)) {
global.params.doJsonGeneration = 1; global.params.doJsonGeneration = true;
global.params.jsonfilename = static_cast<const char *>(files.data[i]); global.params.jsonfilename = files[i];
continue; continue;
} }
#if !LDC_POSIX #if !LDC_POSIX
if (Port::stricmp(ext, "res") == 0) { if (FileName::equals(ext, "res")) {
global.params.resfile = static_cast<const char *>(files.data[i]); global.params.resfile = files[i];
continue; continue;
} }
if (FileName::equals(ext, "def")) {
if (Port::stricmp(ext, "def") == 0) { global.params.deffile = files[i];
global.params.deffile = static_cast<const char *>(files.data[i]);
continue; continue;
} }
if (FileName::equals(ext, "exe")) {
if (Port::stricmp(ext, "exe") == 0) { global.params.exefile = files[i];
global.params.exefile = static_cast<const char *>(files.data[i]);
continue; continue;
} }
#endif #endif
/* Examine extension to see if it is a valid
if (Port::stricmp(ext, global.mars_ext) == 0 || * D source file extension
Port::stricmp(ext, global.hdr_ext) == 0 || */
if (FileName::equals(ext, global.mars_ext) ||
FileName::equals(ext, global.hdr_ext) ||
FileName::equals(ext, "dd")) { FileName::equals(ext, "dd")) {
ext--; // skip onto '.' ext--; // skip onto '.'
assert(*ext == '.'); assert(*ext == '.');
char *tmp = static_cast<char *>(mem.xmalloc((ext - p) + 1)); newname = static_cast<char *>(mem.xmalloc((ext - p) + 1));
memcpy(tmp, p, ext - p); memcpy(newname, p, ext - p);
tmp[ext - p] = 0; // strip extension newname[ext - p] = 0; // strip extension
name = tmp; name = newname;
if (name[0] == 0 || strcmp(name, "..") == 0 || strcmp(name, ".") == 0)
if (name[0] == 0 || strcmp(name, "..") == 0 || strcmp(name, ".") == 0) {
goto Linvalid; goto Linvalid;
}
} else { } else {
error(Loc(), "unrecognized file extension %s\n", ext); error(Loc(), "unrecognized file extension %s", ext);
fatal(); fatal();
} }
} else { } else {
name = p; name = p;
if (!*p) { if (!*name) {
Linvalid: Linvalid:
error(Loc(), "invalid file name '%s'", error(Loc(), "invalid file name '%s'", files[i]);
static_cast<const char *>(files.data[i]));
fatal(); fatal();
} }
name = p;
} }
/* At this point, name is the D source file name stripped of
id = Identifier::idPool(name, strlen(name)); * its path and extension.
auto m = Module::create(files.data[i], id, global.params.doDocComments, */
auto id = Identifier::idPool(name, strlen(name));
auto m = Module::create(files[i], id, global.params.doDocComments,
global.params.doHdrGeneration); global.params.doHdrGeneration);
modules.push(m); modules.push(m);
} }
// Read files, parse them // 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++) { for (unsigned i = 0; i < modules.dim; i++) {
Module *m = modules[i]; Module *m = modules[i];
if (global.params.verbose) { 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()); fprintf(global.stdmsg, "parse %s\n", m->toChars());
} if (!Module::rootModule)
if (!Module::rootModule) {
Module::rootModule = m; Module::rootModule = m;
} m->importedFrom = m; // m->isRoot() == true
m->importedFrom = m;
if (strcmp(m->srcfile->name->str, global.main_d) == 0) {
static const char buf[] = "void main(){}";
m->srcfile->setbuffer(const_cast<char *>(buf), sizeof(buf));
m->srcfile->ref = 1;
} else {
m->read(Loc());
}
m->parse(global.params.doDocComments); m->parse(global.params.doDocComments);
buildTargetFiles(m, singleObj, createSharedLib || createStaticLib); buildTargetFiles(m, singleObj, createSharedLib || createStaticLib);
m->deleteObjFile(); m->deleteObjFile();
if (m->isDocFile) { if (m->isDocFile) {
anydocfiles = true;
gendocfile(m); gendocfile(m);
// Remove m from list of modules // Remove m from list of modules
modules.remove(i); modules.remove(modi);
i--; 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 (global.errors) { if (anydocfiles && modules.dim &&
(global.params.oneobj || global.params.objname)) {
error(Loc(), "conflicting Ddoc and obj generation options");
fatal(); fatal();
} }
if (global.errors)
fatal();
if (global.params.doHdrGeneration) { if (global.params.doHdrGeneration) {
/* Generate 'header' import files. /* Generate 'header' import files.
@ -1349,73 +1345,87 @@ int cppmain(int argc, char **argv) {
* before any semantic analysis. * before any semantic analysis.
*/ */
for (unsigned i = 0; i < modules.dim; i++) { for (unsigned i = 0; i < modules.dim; i++) {
if (global.params.verbose) { Module *m = modules[i];
fprintf(global.stdmsg, "import %s\n", modules[i]->toChars()); if (global.params.verbose)
} fprintf(global.stdmsg, "import %s\n", m->toChars());
genhdrfile(modules[i]); genhdrfile(m);
} }
} }
if (global.errors) { if (global.errors)
fatal(); fatal();
}
// load all unconditional imports for better symbol resolving // load all unconditional imports for better symbol resolving
for (unsigned i = 0; i < modules.dim; i++) { for (unsigned i = 0; i < modules.dim; i++) {
if (global.params.verbose) { Module *m = modules[i];
fprintf(global.stdmsg, "importall %s\n", modules[i]->toChars()); if (global.params.verbose)
} fprintf(global.stdmsg, "importall %s\n", m->toChars());
modules[i]->importAll(nullptr); m->importAll(nullptr);
} }
if (global.errors) { if (global.errors)
fatal(); fatal();
}
// Do semantic analysis // Do semantic analysis
for (unsigned i = 0; i < modules.dim; i++) { for (unsigned i = 0; i < modules.dim; i++) {
if (global.params.verbose) { Module *m = modules[i];
fprintf(global.stdmsg, "semantic %s\n", modules[i]->toChars()); if (global.params.verbose)
} fprintf(global.stdmsg, "semantic %s\n", m->toChars());
modules[i]->semantic(nullptr); m->semantic(nullptr);
} }
if (global.errors) { if (global.errors)
fatal(); fatal();
}
Module::dprogress = 1; Module::dprogress = 1;
Module::runDeferredSemantic(); 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 // Do pass 2 semantic analysis
for (unsigned i = 0; i < modules.dim; i++) { for (unsigned i = 0; i < modules.dim; i++) {
if (global.params.verbose) { Module *m = modules[i];
fprintf(global.stdmsg, "semantic2 %s\n", modules[i]->toChars()); if (global.params.verbose)
} fprintf(global.stdmsg, "semantic2 %s\n", m->toChars());
modules[i]->semantic2(nullptr); m->semantic2(nullptr);
} }
if (global.errors) { if (global.errors)
fatal(); fatal();
}
// Do pass 3 semantic analysis // Do pass 3 semantic analysis
for (unsigned i = 0; i < modules.dim; i++) { for (unsigned i = 0; i < modules.dim; i++) {
if (global.params.verbose) { Module *m = modules[i];
fprintf(global.stdmsg, "semantic3 %s\n", modules[i]->toChars()); if (global.params.verbose)
} fprintf(global.stdmsg, "semantic3 %s\n", m->toChars());
modules[i]->semantic3(nullptr); m->semantic3(nullptr);
}
if (global.errors) {
fatal();
} }
Module::runDeferredSemantic3(); Module::runDeferredSemantic3();
if (global.errors)
if (global.errors || global.warnings) { fatal();
// Do not attempt to generate output files if errors or warnings occurred
if (global.errors || global.warnings)
fatal(); fatal();
}
// Now that we analyzed all modules, write the module dependency file if // Now that we analyzed all modules, write the module dependency file if
// the user requested it. // the user requested it.
writeModuleDependencyFile(); 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);
}
}
// Generate one or more object/IR/bitcode files. // Generate one or more object/IR/bitcode files.
if (global.params.obj && !modules.empty()) { if (global.params.obj && !modules.empty()) {
ldc::CodeGenerator cg(getGlobalContext(), singleObj); ldc::CodeGenerator cg(getGlobalContext(), singleObj);
@ -1430,36 +1440,20 @@ int cppmain(int argc, char **argv) {
// codegenned. // codegenned.
for (d_size_t i = modules.dim; i-- > 0;) { for (d_size_t i = modules.dim; i-- > 0;) {
Module *const m = modules[i]; Module *const m = modules[i];
if (global.params.verbose) { if (global.params.verbose)
fprintf(global.stdmsg, "code %s\n", m->toChars()); fprintf(global.stdmsg, "code %s\n", m->toChars());
}
cg.emit(m); cg.emit(m);
if (global.errors) { if (global.errors)
fatal(); fatal();
}
} }
} }
// Generate DDoc output files.
if (global.params.doDocComments) {
for (unsigned i = 0; i < modules.dim; i++) {
gendocfile(modules[i]);
}
}
// Generate the AST-describing JSON file.
if (global.params.doJsonGeneration) {
emitJson(modules);
}
freeRuntime(); freeRuntime();
llvm::llvm_shutdown(); llvm::llvm_shutdown();
if (global.errors)
if (global.errors) {
fatal(); fatal();
}
// Finally, produce the final executable/archive and run it, if we are // Finally, produce the final executable/archive and run it, if we are
// supposed to. // supposed to.
@ -1477,14 +1471,16 @@ int cppmain(int argc, char **argv) {
status = createStaticLibrary(); status = createStaticLibrary();
} }
if (global.params.run && status == EXIT_SUCCESS) { if (global.params.run) {
status = runExecutable(); if (!status) {
status = runProgram();
/// Delete .obj files and .exe file. /* Delete .obj files and .exe file
for (unsigned i = 0; i < modules.dim; i++) { */
modules[i]->deleteObjFile(); for (unsigned i = 0; i < modules.dim; i++) {
modules[i]->deleteObjFile();
}
deleteExeFile();
} }
deleteExecutable();
} }
} }

View file

@ -13,18 +13,24 @@
module driver.main; module driver.main;
import core.stdc.stdio;
import ddmd.globals; import ddmd.globals;
import ddmd.root.file; import ddmd.root.file;
import ddmd.root.outbuffer; import ddmd.root.outbuffer;
extern (C++) void writeModuleDependencyFile() extern (C++) void writeModuleDependencyFile()
{ {
if (global.params.moduleDepsFile !is null) if (global.params.moduleDeps)
{ {
auto deps = File(global.params.moduleDepsFile); OutBuffer* ob = global.params.moduleDeps;
OutBuffer *ob = global.params.moduleDeps; if (global.params.moduleDepsFile)
deps.setbuffer(cast(void*)ob.data, ob.offset); {
deps.write(); auto deps = File(global.params.moduleDepsFile);
deps.setbuffer(cast(void*)ob.data, ob.offset);
deps.write();
}
else
printf("%.*s", cast(int)ob.offset, ob.data);
} }
} }