diff --git a/lld/ELF/Config.h b/lld/ELF/Config.h --- a/lld/ELF/Config.h +++ b/lld/ELF/Config.h @@ -148,6 +148,7 @@ bool emitLLVM; bool emitRelocs; bool enableNewDtags; + bool errorCallLacksNop; bool executeOnly; bool exportDynamic; bool fixCortexA53Errata843419; @@ -163,6 +164,7 @@ bool hasDynSymTab; bool ignoreDataAddressEquality; bool ignoreFunctionAddressEquality; + bool laxCallLacksNop; bool ltoCSProfileGenerate; bool ltoDebugPassManager; bool ltoNewPassManager; diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp --- a/lld/ELF/Driver.cpp +++ b/lld/ELF/Driver.cpp @@ -887,6 +887,7 @@ config->ignoreFunctionAddressEquality = args.hasArg(OPT_ignore_function_address_equality); config->init = args.getLastArgValue(OPT_init, "_init"); + config->laxCallLacksNop = args.hasArg(OPT_lax_call_lacks_nop); config->ltoAAPipeline = args.getLastArgValue(OPT_lto_aa_pipeline); config->ltoCSProfileGenerate = args.hasArg(OPT_lto_cs_profile_generate); config->ltoCSProfileFile = args.getLastArgValue(OPT_lto_cs_profile_file); diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp --- a/lld/ELF/InputSection.cpp +++ b/lld/ELF/InputSection.cpp @@ -975,13 +975,16 @@ // gcc/gfortran 5.4, 6.3 and earlier versions do not add nop for // recursive calls even if the function is preemptible. This is not // wrong in the common case where the function is not preempted at - // runtime. Just ignore. + // runtime. Just ignore if --lax-call-lacks-nop is specified. if ((bufLoc + 8 > bufEnd || read32(bufLoc + 4) != 0x60000000) && - rel.sym->file != file) { + !(config->laxCallLacksNop && rel.sym->file == file)) { + std::string hint; + if (rel.sym->file == file) + hint = "; pass -Wl,--lax-call-lacks-nop to ignore the error"; // Use substr(6) to remove the "__plt_" prefix. errorOrWarn(getErrorLocation(bufLoc) + "call to " + lld::toString(*rel.sym).substr(6) + - " lacks nop, can't restore toc"); + " lacks nop, can't restore toc" + hint); break; } write32(bufLoc + 4, 0xe8410018); // ld %r2, 24(%r1) diff --git a/lld/ELF/Options.td b/lld/ELF/Options.td --- a/lld/ELF/Options.td +++ b/lld/ELF/Options.td @@ -220,6 +220,10 @@ defm keep_unique: Eq<"keep-unique", "Do not fold this symbol during ICF">; +def lax_call_lacks_nop : F<"lax-call-lacks-nop">, + HelpText<"(PowerPC64) Don't error on b/bl not followed by nop, if the target is " + "defined in the same file. This is for compatibility with GCC<5.4 and GCC<6.4">; + defm library: Eq<"library", "Root name of library to use">, MetaVarName<"">; diff --git a/lld/test/ELF/ppc64-error-toc-tail-call.s b/lld/test/ELF/ppc64-error-toc-tail-call.s --- a/lld/test/ELF/ppc64-error-toc-tail-call.s +++ b/lld/test/ELF/ppc64-error-toc-tail-call.s @@ -11,8 +11,7 @@ // RUN: not ld.lld %t.o %t2.so -o %t 2>&1 | FileCheck %s # A tail call to an external function without a nop should issue an error. -// CHECK: call to foo lacks nop, can't restore toc -// CHECK-NOT: lacks nop +// CHECK: call to foo lacks nop, can't restore toc{{$}} .text .abiversion 2 diff --git a/lld/test/ELF/ppc64-lax-call-lacks-nop.s b/lld/test/ELF/ppc64-lax-call-lacks-nop.s new file mode 100644 --- /dev/null +++ b/lld/test/ELF/ppc64-lax-call-lacks-nop.s @@ -0,0 +1,26 @@ +# REQUIRES: ppc +## gcc/gfortran 5.4, 6.3 and earlier versions do not add nop for recursive +## calls. Test that --lax-call-lacks-nop can suppress the error. + +# RUN: llvm-mc -filetype=obj -triple=powerpc64le %s -o %t.o +# RUN: not ld.lld -shared %t.o -o /dev/null 2>&1 | FileCheck --check-prefix=ERROR %s +# RUN: ld.lld -shared --lax-call-lacks-nop %t.o -o /dev/null 2>&1 | count 0 + +# ERROR: call to bar lacks nop, can't restore toc; pass -Wl,--lax-call-lacks-nop to ignore the error + +.global _start +_start: + ## Unfortunately, MC does not emit a relocation if the target is + ## defined in the same section, so the following test case does not exercise + ## the code path. + ## b _start + ## b _start + ## + ## Define bar in another section to exercise the code path. + bl bar + bl bar + +.section .text.bar,"ax",@progbits +.global bar +bar: + blr