mirror of
https://github.com/ldc-developers/ldc.git
synced 2025-05-07 19:36:06 +03:00
Don't reverse order of object file names
Make sure the overall order corresponds to the user's command-line order of object and source files. The only exception being singleObj builds, for which the single object file for all source files is always the first entry in the object files list (which is forwarded to the linker in that order). This is done so that we can easily get hold of the name when emitting the single object file later in the `ldc::CodeGenerator` dtor. It should also clearly define the linking order (affecting comdat selections etc.) for special singleObj builds. Also reuse some more code (wrt. output filenames) from DMD's main().
This commit is contained in:
parent
1c82c405d6
commit
b1a6315ee4
7 changed files with 96 additions and 97 deletions
79
ddmd/mars.d
79
ddmd/mars.d
|
@ -154,6 +154,7 @@ version(IN_LLVM)
|
|||
|
||||
void genCmain(Scope* sc);
|
||||
// in driver/main.cpp
|
||||
void addDefaultVersionIdentifiers();
|
||||
void codegenModules(ref Modules modules);
|
||||
// in driver/linker.cpp
|
||||
int linkObjToBinary();
|
||||
|
@ -1102,6 +1103,14 @@ Language changes listed by -transition=id:
|
|||
global.params.useAssert = true;
|
||||
if (!global.params.obj || global.params.lib)
|
||||
global.params.link = false;
|
||||
|
||||
return mars_mainBody(files, libmodules);
|
||||
}
|
||||
|
||||
} // !IN_LLVM
|
||||
|
||||
extern (C++) int mars_mainBody(ref Strings files, ref Strings libmodules)
|
||||
{
|
||||
if (global.params.link)
|
||||
{
|
||||
global.params.exefile = global.params.objname;
|
||||
|
@ -1131,10 +1140,13 @@ Language changes listed by -transition=id:
|
|||
{
|
||||
global.params.libname = global.params.objname;
|
||||
global.params.objname = null;
|
||||
version (IN_LLVM) {} else
|
||||
{
|
||||
// Haven't investigated handling these options with multiobj
|
||||
if (!global.params.cov && !global.params.trace)
|
||||
global.params.multiobj = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (global.params.objname && files.dim > 1)
|
||||
|
@ -1147,17 +1159,13 @@ Language changes listed by -transition=id:
|
|||
|
||||
// Predefined version identifiers
|
||||
addDefaultVersionIdentifiers();
|
||||
version (IN_LLVM) {} else
|
||||
{
|
||||
objc_tryMain_dObjc();
|
||||
|
||||
setDefaultLibrary();
|
||||
|
||||
return mars_mainBody(files, libmodules);
|
||||
}
|
||||
|
||||
} // !IN_LLVM
|
||||
|
||||
extern (C++) int mars_mainBody(ref Strings files, ref Strings libmodules)
|
||||
{
|
||||
// Initialization
|
||||
Type._init();
|
||||
Id.initialize();
|
||||
|
@ -1214,7 +1222,14 @@ extern (C++) int mars_mainBody(ref Strings files, ref Strings libmodules)
|
|||
// Create Modules
|
||||
Modules modules;
|
||||
modules.reserve(files.dim);
|
||||
version (IN_LLVM)
|
||||
{
|
||||
size_t firstModuleObjectFileIndex = size_t.max;
|
||||
}
|
||||
else
|
||||
{
|
||||
bool firstmodule = true;
|
||||
}
|
||||
for (size_t i = 0; i < files.dim; i++)
|
||||
{
|
||||
const(char)* name;
|
||||
|
@ -1337,7 +1352,23 @@ extern (C++) int mars_mainBody(ref Strings files, ref Strings libmodules)
|
|||
auto id = Identifier.idPool(name, strlen(name));
|
||||
auto m = new Module(files[i], id, global.params.doDocComments, global.params.doHdrGeneration);
|
||||
modules.push(m);
|
||||
version (IN_LLVM) {} else
|
||||
version (IN_LLVM)
|
||||
{
|
||||
// If `-run` is passed, the obj file is temporary and is removed after execution.
|
||||
// Make sure the name does not collide with other files from other processes by
|
||||
// creating a unique filename.
|
||||
if (global.params.run)
|
||||
m.makeObjectFilenameUnique();
|
||||
|
||||
if (!global.params.oneobj || firstModuleObjectFileIndex == size_t.max)
|
||||
{
|
||||
global.params.objfiles.push(m.objfile.name.str);
|
||||
m.checkAndAddOutputFile(m.objfile);
|
||||
if (firstModuleObjectFileIndex == size_t.max)
|
||||
firstModuleObjectFileIndex = global.params.objfiles.dim - 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (firstmodule)
|
||||
{
|
||||
|
@ -1346,6 +1377,19 @@ extern (C++) int mars_mainBody(ref Strings files, ref Strings libmodules)
|
|||
}
|
||||
}
|
||||
}
|
||||
version (IN_LLVM)
|
||||
{
|
||||
if (global.params.oneobj && modules.dim < 2)
|
||||
global.params.oneobj = false;
|
||||
// global.params.oneobj => move object file for first source file to
|
||||
// beginning of object files list
|
||||
if (global.params.oneobj && firstModuleObjectFileIndex != 0)
|
||||
{
|
||||
auto fn = (*global.params.objfiles)[firstModuleObjectFileIndex];
|
||||
global.params.objfiles.remove(firstModuleObjectFileIndex);
|
||||
global.params.objfiles.insert(0, fn);
|
||||
}
|
||||
}
|
||||
// Read files
|
||||
/* Start by "reading" the dummy main.d file
|
||||
*/
|
||||
|
@ -1612,22 +1656,6 @@ extern (C++) int mars_mainBody(ref Strings files, ref Strings libmodules)
|
|||
}
|
||||
version (IN_LLVM)
|
||||
{
|
||||
for (size_t i = 0; i < modules.dim; i++)
|
||||
{
|
||||
Module m = modules[i];
|
||||
if (!m.objfile)
|
||||
continue;
|
||||
|
||||
// If `-run` is passed, the obj file is temporary and is removed after execution.
|
||||
// Make sure the name does not collide with other files from other processes by
|
||||
// creating a unique filename.
|
||||
if (global.params.run)
|
||||
m.makeObjectFilenameUnique();
|
||||
|
||||
if (!global.params.oneobj || i == 0)
|
||||
m.checkAndAddOutputFile(m.objfile);
|
||||
}
|
||||
|
||||
codegenModules(modules);
|
||||
}
|
||||
else
|
||||
|
@ -1959,6 +1987,9 @@ extern (C++) Expressions* Expressions_create()
|
|||
return new Expressions();
|
||||
}
|
||||
|
||||
version (IN_LLVM) {} else
|
||||
{
|
||||
|
||||
/**
|
||||
* Set the default and debug libraries to link against, if not already set
|
||||
*
|
||||
|
@ -2110,3 +2141,5 @@ private void addDefaultVersionIdentifiers()
|
|||
VersionCondition.addPredefinedGlobalIdent("D_NoBoundsChecks");
|
||||
VersionCondition.addPredefinedGlobalIdent("D_HardFloat");
|
||||
}
|
||||
|
||||
} // !IN_LLVM
|
||||
|
|
|
@ -77,8 +77,7 @@ void emitLinkerOptions(IRState &irs, llvm::Module &M, llvm::LLVMContext &ctx) {
|
|||
|
||||
namespace ldc {
|
||||
CodeGenerator::CodeGenerator(llvm::LLVMContext &context, bool singleObj)
|
||||
: context_(context), moduleCount_(0), singleObj_(singleObj), ir_(nullptr),
|
||||
firstModuleObjfileName_(nullptr) {
|
||||
: context_(context), moduleCount_(0), singleObj_(singleObj), ir_(nullptr) {
|
||||
if (!ClassDeclaration::object) {
|
||||
error(Loc(), "declaration for class Object not found; druntime not "
|
||||
"configured properly");
|
||||
|
@ -95,17 +94,9 @@ CodeGenerator::CodeGenerator(llvm::LLVMContext &context, bool singleObj)
|
|||
|
||||
CodeGenerator::~CodeGenerator() {
|
||||
if (singleObj_) {
|
||||
const char *oname;
|
||||
const char *filename;
|
||||
if ((oname = global.params.exefile) || (oname = global.params.objname)) {
|
||||
filename = FileName::forceExt(oname, global.obj_ext);
|
||||
if (global.params.objdir) {
|
||||
filename =
|
||||
FileName::combine(global.params.objdir, FileName::name(filename));
|
||||
}
|
||||
} else {
|
||||
filename = firstModuleObjfileName_;
|
||||
}
|
||||
// For singleObj builds, the first object file name is the one for the first
|
||||
// source file (e.g., `b.o` for `ldc2 a.o b.d c.d`).
|
||||
const char *filename = (*global.params.objfiles)[0];
|
||||
|
||||
// If there are bitcode files passed on the cmdline, add them after all
|
||||
// other source files have been added to the (singleobj) module.
|
||||
|
@ -117,9 +108,6 @@ CodeGenerator::~CodeGenerator() {
|
|||
}
|
||||
|
||||
void CodeGenerator::prepareLLModule(Module *m) {
|
||||
if (!firstModuleObjfileName_) {
|
||||
firstModuleObjfileName_ = m->objfile->name->str;
|
||||
}
|
||||
++moduleCount_;
|
||||
|
||||
if (singleObj_ && ir_) {
|
||||
|
@ -181,7 +169,6 @@ void CodeGenerator::writeAndFreeLLModule(const char *filename) {
|
|||
IdentMetadata->addOperand(llvm::MDNode::get(ir_->context(), IdentNode));
|
||||
|
||||
writeModule(&ir_->module, filename);
|
||||
global.params.objfiles->push(const_cast<char *>(filename));
|
||||
delete ir_;
|
||||
ir_ = nullptr;
|
||||
}
|
||||
|
|
|
@ -39,7 +39,6 @@ private:
|
|||
int moduleCount_;
|
||||
bool const singleObj_;
|
||||
IRState *ir_;
|
||||
const char *firstModuleObjfileName_;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -149,10 +149,8 @@ static int linkObjToBinaryGcc(bool sharedLib, bool fullyStatic) {
|
|||
std::vector<std::string> args;
|
||||
|
||||
// object files
|
||||
for (unsigned i = 0; i < global.params.objfiles->dim; i++) {
|
||||
const char *p = static_cast<const char *>(global.params.objfiles->data[i]);
|
||||
args.push_back(p);
|
||||
}
|
||||
for (unsigned i = 0; i < global.params.objfiles->dim; i++)
|
||||
args.push_back((*global.params.objfiles)[i]);
|
||||
|
||||
// Link with profile-rt library when generating an instrumented binary.
|
||||
// profile-rt uses Phobos (MD5 hashing) and therefore must be passed on the
|
||||
|
@ -170,10 +168,8 @@ static int linkObjToBinaryGcc(bool sharedLib, bool fullyStatic) {
|
|||
}
|
||||
|
||||
// user libs
|
||||
for (unsigned i = 0; i < global.params.libfiles->dim; i++) {
|
||||
const char *p = static_cast<const char *>(global.params.libfiles->data[i]);
|
||||
args.push_back(p);
|
||||
}
|
||||
for (unsigned i = 0; i < global.params.libfiles->dim; i++)
|
||||
args.push_back((*global.params.libfiles)[i]);
|
||||
|
||||
// output filename
|
||||
std::string output = getOutputName(sharedLib);
|
||||
|
@ -211,8 +207,7 @@ static int linkObjToBinaryGcc(bool sharedLib, bool fullyStatic) {
|
|||
|
||||
// additional linker switches
|
||||
for (unsigned i = 0; i < global.params.linkswitches->dim; i++) {
|
||||
const char *p =
|
||||
static_cast<const char *>(global.params.linkswitches->data[i]);
|
||||
const char *p = (*global.params.linkswitches)[i];
|
||||
// Don't push -l and -L switches using -Xlinker, but pass them indirectly
|
||||
// via GCC. This makes sure user-defined paths take precedence over
|
||||
// GCC's builtin LIBRARY_PATHs.
|
||||
|
@ -598,10 +593,8 @@ static int linkObjToBinaryWin(bool sharedLib) {
|
|||
args.push_back("/OUT:" + output);
|
||||
|
||||
// object files
|
||||
for (unsigned i = 0; i < global.params.objfiles->dim; i++) {
|
||||
const char *p = static_cast<const char *>(global.params.objfiles->data[i]);
|
||||
args.push_back(p);
|
||||
}
|
||||
for (unsigned i = 0; i < global.params.objfiles->dim; i++)
|
||||
args.push_back((*global.params.objfiles)[i]);
|
||||
|
||||
// Link with profile-rt library when generating an instrumented binary
|
||||
// profile-rt depends on Phobos (MD5 hashing).
|
||||
|
@ -612,10 +605,8 @@ static int linkObjToBinaryWin(bool sharedLib) {
|
|||
}
|
||||
|
||||
// user libs
|
||||
for (unsigned i = 0; i < global.params.libfiles->dim; i++) {
|
||||
const char *p = static_cast<const char *>(global.params.libfiles->data[i]);
|
||||
args.push_back(p);
|
||||
}
|
||||
for (unsigned i = 0; i < global.params.libfiles->dim; i++)
|
||||
args.push_back((*global.params.libfiles)[i]);
|
||||
|
||||
// set the global gExePath
|
||||
gExePath = output;
|
||||
|
|
|
@ -658,37 +658,6 @@ void parseCommandLine(int argc, char **argv, Strings &sourceFiles,
|
|||
mRelocModel = llvm::Reloc::PIC_;
|
||||
}
|
||||
|
||||
if (global.params.link) {
|
||||
global.params.exefile = global.params.objname;
|
||||
global.params.oneobj = true;
|
||||
if (global.params.objname) {
|
||||
/* Use this to name the one object file with the same
|
||||
* name as the exe file.
|
||||
*/
|
||||
global.params.objname =
|
||||
FileName::forceExt(global.params.objname, global.obj_ext);
|
||||
/* If output directory is given, use that path rather than
|
||||
* the exe file path.
|
||||
*/
|
||||
if (global.params.objdir) {
|
||||
const char *name = FileName::name(global.params.objname);
|
||||
global.params.objname = FileName::combine(global.params.objdir, name);
|
||||
}
|
||||
}
|
||||
} else if (global.params.run) {
|
||||
error(Loc(), "flags conflict with -run");
|
||||
fatal();
|
||||
} else if (global.params.lib) {
|
||||
global.params.libname = global.params.objname;
|
||||
global.params.objname = nullptr;
|
||||
} else {
|
||||
if (global.params.objname && sourceFiles.dim > 1) {
|
||||
global.params.oneobj = true;
|
||||
// error("multiple source files, but only one .obj name");
|
||||
// fatal();
|
||||
}
|
||||
}
|
||||
|
||||
if (soname.getNumOccurrences() > 0 && !global.params.dll) {
|
||||
error(Loc(), "-soname can be used only when building a shared library");
|
||||
}
|
||||
|
@ -1130,14 +1099,9 @@ int cppmain(int argc, char **argv) {
|
|||
// allocate the target abi
|
||||
gABI = TargetABI::getTarget();
|
||||
|
||||
// Set predefined version identifiers.
|
||||
registerPredefinedVersions();
|
||||
dumpPredefinedVersions();
|
||||
|
||||
if (global.params.targetTriple->isOSWindows()) {
|
||||
global.dll_ext = "dll";
|
||||
global.lib_ext =
|
||||
(global.params.targetTriple->isWindowsMSVCEnvironment() ? "lib" : "a");
|
||||
global.lib_ext = (global.params.mscoff ? "lib" : "a");
|
||||
} else {
|
||||
global.dll_ext = "so";
|
||||
global.lib_ext = "a";
|
||||
|
@ -1147,6 +1111,11 @@ int cppmain(int argc, char **argv) {
|
|||
return mars_mainBody(files, libmodules);
|
||||
}
|
||||
|
||||
void addDefaultVersionIdentifiers() {
|
||||
registerPredefinedVersions();
|
||||
dumpPredefinedVersions();
|
||||
}
|
||||
|
||||
void codegenModules(Modules &modules) {
|
||||
// Generate one or more object/IR/bitcode files.
|
||||
if (global.params.obj && !modules.empty()) {
|
||||
|
|
19
tests/codegen/inferred_outputname.d
Normal file
19
tests/codegen/inferred_outputname.d
Normal file
|
@ -0,0 +1,19 @@
|
|||
// Make sure the inferred output filename is based on the first (source or
|
||||
// object) file, and independent from its module declaration.
|
||||
|
||||
// If it works on Windows, it will work on other platforms too, and it
|
||||
// simplifies things a bit.
|
||||
// REQUIRES: Windows
|
||||
|
||||
// 1) 2 object files compiled separately:
|
||||
// RUN: %ldc -c %S/inputs/foo.d -of=%T/foo%obj
|
||||
// RUN: %ldc %s %T/foo%obj -vv | FileCheck %s
|
||||
// 2) singleObj build with external object file and 2 source files:
|
||||
// RUN: %ldc %T/foo%obj %s %S/inputs/attr_weak_input.d -vv | FileCheck %s
|
||||
|
||||
// CHECK: Linking with:
|
||||
// CHECK-NEXT: '/OUT:inferred_outputname.exe'
|
||||
|
||||
module modulename;
|
||||
|
||||
void main() {}
|
1
tests/codegen/inputs/foo.d
Normal file
1
tests/codegen/inputs/foo.d
Normal file
|
@ -0,0 +1 @@
|
|||
void bar() {}
|
Loading…
Add table
Add a link
Reference in a new issue