diff --git a/clang/include/clang/Driver/CC1Options.td b/clang/include/clang/Driver/CC1Options.td index 3189145326bc..f95e72bef6d1 100644 --- a/clang/include/clang/Driver/CC1Options.td +++ b/clang/include/clang/Driver/CC1Options.td @@ -143,6 +143,8 @@ def mno_exec_stack : Flag<["-"], "mnoexecstack">, HelpText<"Mark the file as not needing an executable stack">; def massembler_fatal_warnings : Flag<["-"], "massembler-fatal-warnings">, HelpText<"Make assembler warnings fatal">; +def mrelax_relocations : Flag<["--"], "mrelax-relocations">, + HelpText<"Use relaxabel elf relocations">; def compress_debug_sections : Flag<["-"], "compress-debug-sections">, HelpText<"Compress DWARF debug sections using zlib">; def msave_temp_labels : Flag<["-"], "msave-temp-labels">, diff --git a/clang/include/clang/Frontend/CodeGenOptions.def b/clang/include/clang/Frontend/CodeGenOptions.def index 2e2344a8e4a4..ca81964df0e4 100644 --- a/clang/include/clang/Frontend/CodeGenOptions.def +++ b/clang/include/clang/Frontend/CodeGenOptions.def @@ -30,6 +30,7 @@ CODEGENOPT(Name, Bits, Default) CODEGENOPT(DisableIntegratedAS, 1, 0) ///< -no-integrated-as CODEGENOPT(CompressDebugSections, 1, 0) ///< -Wa,-compress-debug-sections +CODEGENOPT(RelaxELFRelocations, 1, 0) ///< -Wa,--mrelax-relocations CODEGENOPT(AsmVerbose , 1, 0) ///< -dA, -fverbose-asm. CODEGENOPT(AssumeSaneOperatorNew , 1, 1) ///< implicit __attribute__((malloc)) operator new CODEGENOPT(Autolink , 1, 1) ///< -fno-autolink diff --git a/clang/lib/CodeGen/BackendUtil.cpp b/clang/lib/CodeGen/BackendUtil.cpp index 2577eecdf84b..0b0b5a764ad5 100644 --- a/clang/lib/CodeGen/BackendUtil.cpp +++ b/clang/lib/CodeGen/BackendUtil.cpp @@ -593,6 +593,7 @@ TargetMachine *EmitAssemblyHelper::CreateTargetMachine(bool MustCreateTM) { Options.UseInitArray = CodeGenOpts.UseInitArray; Options.DisableIntegratedAS = CodeGenOpts.DisableIntegratedAS; Options.CompressDebugSections = CodeGenOpts.CompressDebugSections; + Options.RelaxELFRelocations = CodeGenOpts.RelaxELFRelocations; // Set EABI version. Options.EABIVersion = llvm::StringSwitch(TargetOpts.EABIVersion) diff --git a/clang/lib/Driver/Tools.cpp b/clang/lib/Driver/Tools.cpp index 1c6082e3c588..c6edc2a14f6a 100644 --- a/clang/lib/Driver/Tools.cpp +++ b/clang/lib/Driver/Tools.cpp @@ -2797,6 +2797,8 @@ static void CollectArgsForIntegratedAssembler(Compilation &C, // When using an integrated assembler, translate -Wa, and -Xassembler // options. bool CompressDebugSections = false; + + bool UseRelaxRelocations = false; const char *MipsTargetFeature = nullptr; for (const Arg *A : Args.filtered(options::OPT_Wa_COMMA, options::OPT_Xassembler)) { @@ -2872,6 +2874,12 @@ static void CollectArgsForIntegratedAssembler(Compilation &C, } else if (Value == "-nocompress-debug-sections" || Value == "--nocompress-debug-sections") { CompressDebugSections = false; + } else if (Value == "-mrelax-relocations=yes" || + Value == "--mrelax-relocations=yes") { + UseRelaxRelocations = true; + } else if (Value == "-mrelax-relocations=no" || + Value == "--mrelax-relocations=no") { + UseRelaxRelocations = false; } else if (Value.startswith("-I")) { CmdArgs.push_back(Value.data()); // We need to consume the next argument if the current arg is a plain @@ -2903,6 +2911,8 @@ static void CollectArgsForIntegratedAssembler(Compilation &C, else D.Diag(diag::warn_debug_compression_unavailable); } + if (UseRelaxRelocations) + CmdArgs.push_back("--mrelax-relocations"); if (MipsTargetFeature != nullptr) { CmdArgs.push_back("-target-feature"); CmdArgs.push_back(MipsTargetFeature); diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index 3b4c50b83569..4bb08c8a81c1 100644 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -683,6 +683,7 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK, Opts.InstrumentForProfiling = Args.hasArg(OPT_pg); Opts.EmitOpenCLArgMetadata = Args.hasArg(OPT_cl_kernel_arg_info); Opts.CompressDebugSections = Args.hasArg(OPT_compress_debug_sections); + Opts.RelaxELFRelocations = Args.hasArg(OPT_mrelax_relocations); Opts.DebugCompilationDir = Args.getLastArgValue(OPT_fdebug_compilation_dir); for (auto A : Args.filtered(OPT_mlink_bitcode_file, OPT_mlink_cuda_bitcode)) { unsigned LinkFlags = llvm::Linker::Flags::None; diff --git a/clang/test/CodeGen/relax.c b/clang/test/CodeGen/relax.c new file mode 100644 index 000000000000..dd3ec4886bb7 --- /dev/null +++ b/clang/test/CodeGen/relax.c @@ -0,0 +1,9 @@ +// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -emit-obj --mrelax-relocations %s -mrelocation-model pic -o %t +// RUN: llvm-readobj -r %t | FileCheck %s + +// CHECK: R_X86_64_REX_GOTPCRELX foo + +extern int foo; +int *f(void) { + return &foo; +} diff --git a/clang/test/Driver/relax.c b/clang/test/Driver/relax.c new file mode 100644 index 000000000000..170d2751b291 --- /dev/null +++ b/clang/test/Driver/relax.c @@ -0,0 +1,4 @@ +// RUN: %clang -### -c -integrated-as -Wa,--mrelax-relocations=yes %s 2>&1 | FileCheck %s + +// CHECK: "-cc1" +// CHECK: "--mrelax-relocations" diff --git a/clang/test/Driver/relax.s b/clang/test/Driver/relax.s new file mode 100644 index 000000000000..d2941e2f173f --- /dev/null +++ b/clang/test/Driver/relax.s @@ -0,0 +1,12 @@ +// REQUIRES: x86-registered-target +// RUN: %clang -### -c -integrated-as -Wa,--mrelax-relocations=yes %s 2>&1 | FileCheck %s + +// CHECK: "-cc1as" +// CHECK: "--mrelax-relocations" + +// RUN: %clang -cc1as -triple x86_64-pc-linux --mrelax-relocations %s -o %t -filetype obj +// RUN: llvm-readobj -r %t | FileCheck --check-prefix=REL %s + +// REL: R_X86_64_REX_GOTPCRELX foo + + movq foo@GOTPCREL(%rip), %rax diff --git a/clang/tools/driver/cc1as_main.cpp b/clang/tools/driver/cc1as_main.cpp index 60ef7c966404..1c032c09ef63 100644 --- a/clang/tools/driver/cc1as_main.cpp +++ b/clang/tools/driver/cc1as_main.cpp @@ -88,6 +88,7 @@ struct AssemblerInvocation { unsigned SaveTemporaryLabels : 1; unsigned GenDwarfForAssembly : 1; unsigned CompressDebugSections : 1; + unsigned RelaxELFRelocations : 1; unsigned DwarfVersion; std::string DwarfDebugFlags; std::string DwarfDebugProducer; @@ -200,6 +201,7 @@ bool AssemblerInvocation::CreateFromArgs(AssemblerInvocation &Opts, // Any DebugInfoKind implies GenDwarfForAssembly. Opts.GenDwarfForAssembly = Args.hasArg(OPT_debug_info_kind_EQ); Opts.CompressDebugSections = Args.hasArg(OPT_compress_debug_sections); + Opts.RelaxELFRelocations = Args.hasArg(OPT_mrelax_relocations); Opts.DwarfVersion = getLastArgIntValue(Args, OPT_dwarf_version_EQ, 2, Diags); Opts.DwarfDebugFlags = Args.getLastArgValue(OPT_dwarf_debug_flags); Opts.DwarfDebugProducer = Args.getLastArgValue(OPT_dwarf_debug_producer); @@ -315,6 +317,8 @@ static bool ExecuteAssembler(AssemblerInvocation &Opts, if (Opts.CompressDebugSections) MAI->setCompressDebugSections(DebugCompressionType::DCT_ZlibGnu); + MAI->setRelaxELFRelocations(Opts.RelaxELFRelocations); + bool IsBinary = Opts.OutputType == AssemblerInvocation::FT_Obj; std::unique_ptr FDOS = getOutputStream(Opts, Diags, IsBinary); if (!FDOS)