Skip to content

Commit

Permalink
[ELF] Automatically fall back to ld.bfd or ld.lld if LTO is in use
Browse files Browse the repository at this point in the history
This is very hacky but highly practical, so I couldn't resist to not
implement this. We should support LTO natively in the future. In the
meantime, this feature should work as a poor-man's replacement.

Fixes rui314#242
  • Loading branch information
rui314 committed Jan 4, 2022
1 parent 0565a6a commit a5029d1
Show file tree
Hide file tree
Showing 5 changed files with 43 additions and 11 deletions.
23 changes: 21 additions & 2 deletions elf/main.cc
Original file line number Diff line number Diff line change
Expand Up @@ -89,8 +89,10 @@ void read_file(Context<E> &ctx, MappedFile<Context<E>> *mf) {
parse_linker_script(ctx, mf);
return;
case FileType::LLVM_BITCODE:
Fatal(ctx) << mf->name << ": looks like this is an LLVM bitcode, "
<< "but mold does not support LTO";
Warn(ctx) << mf->name << ": looks like this is an LLVM bitcode, "
<< "but mold does not support LTO";
ctx.llvm_lto = true;
return;
default:
Fatal(ctx) << mf->name << ": unknown file type: " << type;
}
Expand Down Expand Up @@ -436,6 +438,23 @@ static int elf_main(int argc, char **argv) {
// included to the final output.
resolve_symbols(ctx);

// We currently do not natively support LTO.
// If LLVM LTO is in use, fallback to the lld linker by invoking
// it with the exact same command line arguments as we got.
if (ctx.llvm_lto) {
Warn(ctx) << "LLVM LTO is detected, so falling back to ld.lld";
argv[0] = (char *)"ld.lld";
execvp("ld.lld", argv);
Fatal(ctx) << "execvp failed: ld.lld: " << errno_string();
}

// Do the same for GCC LTO.
if (ctx.gcc_lto) {
Warn(ctx) << "GCC LTO is detected, so falling back to ld.bfd";
execvp("ld.bfd", argv);
Fatal(ctx) << "execvp failed: ld.bfd: " << errno_string();
}

// Remove redundant comdat sections (e.g. duplicate inline functions).
eliminate_comdats(ctx);

Expand Down
3 changes: 3 additions & 0 deletions elf/mold.h
Original file line number Diff line number Diff line change
Expand Up @@ -1305,6 +1305,9 @@ struct Context {
tbb::task_group tg;

bool has_error = false;
bool gcc_lto = false;
bool llvm_lto = false;

i64 page_size = -1;

// Symbol table
Expand Down
8 changes: 5 additions & 3 deletions elf/passes.cc
Original file line number Diff line number Diff line change
Expand Up @@ -167,9 +167,11 @@ void resolve_symbols(Context<E> &ctx) {
file->resolve_common_symbols(ctx);
});

if (Symbol<E> *sym = get_symbol(ctx, "__gnu_lto_slim"); sym->file)
Fatal(ctx) << *sym->file << ": looks like this file contains a GCC "
<< "intermediate code, but mold does not support LTO";
if (Symbol<E> *sym = get_symbol(ctx, "__gnu_lto_slim"); sym->file) {
Warn(ctx) << *sym->file << ": looks like this file contains a GCC "
<< "intermediate code, but mold does not support LTO";
ctx.gcc_lto = true;
}
}

template <typename E>
Expand Down
10 changes: 7 additions & 3 deletions test/elf/lto-gcc-error.sh → test/elf/lto-gcc-fallback.sh
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,14 @@ t="$(pwd)/out/test/elf/$testname"
mkdir -p "$t"

cat <<EOF | gcc -flto -c -o "$t"/a.o -xc -
int main() {}
#include <stdio.h>
int main() {
printf("Hello world\n");
}
EOF

! clang -fuse-ld="$mold" -o "$t"/exe "$t"/a.o &> "$t"/log
grep -q '.*/a.o: .*mold does not support LTO' "$t"/log
gcc -B"$(pwd)" -o "$t"/exe "$t"/a.o >& "$t"/log
grep -q 'falling back' "$t"/log
"$t"/exe | grep -q 'Hello world'

echo OK
10 changes: 7 additions & 3 deletions test/elf/lto-llvm-error.sh → test/elf/lto-llvm-fallback.sh
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,14 @@ t="$(pwd)/out/test/elf/$testname"
mkdir -p "$t"

cat <<EOF | clang -flto -c -o "$t"/a.o -xc -
int main() {}
#include <stdio.h>
int main() {
printf("Hello world\n");
}
EOF

! clang -fuse-ld="$mold" -o "$t"/exe "$t"/a.o &> "$t"/log
grep -q '.*/a.o: .*mold does not support LTO' "$t"/log
clang -fuse-ld="$mold" -o "$t"/exe "$t"/a.o &> "$t"/log
grep -q 'falling back' "$t"/log
"$t"/exe | grep -q 'Hello world'

echo OK

0 comments on commit a5029d1

Please sign in to comment.