diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -3665,6 +3665,13 @@ Group, HelpText<"Do not produce relaxation hints for linkers to try optimizing PIC " "call sequences into direct calls (MIPS only)">, Flags<[HelpHidden]>; +def mmips_pc64_rel : Flag<["-"], "mmips-pc64-rel">, + Group, + HelpText<"Use MIPS 64-bit PC-relative relocations">, Flags<[HelpHidden]>; +def mno_mips_pc64_rel : Flag<["-"], "mno-mips-pc64-rel">, + Group, + HelpText<"Do not use MIPS 64-bit PC-relative relocations">, + Flags<[HelpHidden]>; def mglibc : Flag<["-"], "mglibc">, Group, Flags<[HelpHidden]>; def muclibc : Flag<["-"], "muclibc">, Group, Flags<[HelpHidden]>; def module_file_info : Flag<["-"], "module-file-info">, Flags<[NoXarchOption,CC1Option]>, Group, diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -1980,6 +1980,16 @@ CmdArgs.push_back("-mips-jalr-reloc=0"); } } + + if (Arg *A = Args.getLastArg(options::OPT_mmips_pc64_rel, + options::OPT_mno_mips_pc64_rel)) { + CmdArgs.push_back("-mllvm"); + if (A->getOption().matches(options::OPT_mmips_pc64_rel)) + CmdArgs.push_back("-mmips-pc64-rel=true"); + else + CmdArgs.push_back("-mmips-pc64-rel=false"); + A->claim(); + } } void Clang::AddPPCTargetArgs(const ArgList &Args, diff --git a/clang/test/Driver/mips-features.c b/clang/test/Driver/mips-features.c --- a/clang/test/Driver/mips-features.c +++ b/clang/test/Driver/mips-features.c @@ -456,3 +456,15 @@ // RUN: -mrelax-pic-calls -mno-relax-pic-calls 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-NO-RELAX-PIC-CALLS %s // CHECK-NO-RELAX-PIC-CALLS: "-mllvm" "-mips-jalr-reloc=0" +// +// -mmips-pc64-rel +// RUN: %clang -target mips-unknown-linux-gnu -### -c %s \ +// RUN: -mno-mips-pc64-rel -mmips-pc64-rel 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-PC64-REL %s +// CHECK-PC64-REL-NOT: "-mllvm" "-mmips-pc64-rel=false" +// +// -mno-mips-pc64-rel +// RUN: %clang -target mips-unknown-linux-gnu -### -c %s \ +// RUN: -mmips-pc64-rel -mno-mips-pc64-rel 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-NO-PC64-REL %s +// CHECK-NO-PC64-REL: "-mllvm" "-mmips-pc64-rel=false" diff --git a/lld/test/ELF/mips-eh_frame-pic.s b/lld/test/ELF/mips-eh_frame-pic.s --- a/lld/test/ELF/mips-eh_frame-pic.s +++ b/lld/test/ELF/mips-eh_frame-pic.s @@ -12,11 +12,11 @@ ## relative addressing. # NOPIC-ERR: ld.lld: error: can't create dynamic relocation R_MIPS_64 against local symbol in readonly segment -## For -fPIC, .eh_frame should contain DW_EH_PE_pcrel | DW_EH_PE_sdata4 values: +## For -fPIC, .eh_frame should contain DW_EH_PE_pcrel | DW_EH_PE_sdata8 values: # RUN: llvm-mc -filetype=obj -triple=mips64-unknown-linux --position-independent %s -o %t-pic.o # RUN: llvm-readobj -r %t-pic.o | FileCheck %s --check-prefixes=RELOCS,PIC64-RELOCS # RUN: ld.lld -shared %t-pic.o -o %t-pic.so -# RUN: llvm-dwarfdump --eh-frame %t-pic.so | FileCheck %s --check-prefix=PIC-EH-FRAME +# RUN: llvm-dwarfdump --eh-frame %t-pic.so | FileCheck %s --check-prefix=PIC64-EH-FRAME ## Also check MIPS32: # RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux %s -o %t-nopic32.o @@ -31,12 +31,12 @@ # RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux --position-independent %s -o %t-pic32.o # RUN: llvm-readobj -r %t-pic32.o | FileCheck %s --check-prefixes=RELOCS,PIC32-RELOCS # RUN: ld.lld -shared %t-pic32.o -o %t-pic32.so -# RUN: llvm-dwarfdump --eh-frame %t-pic32.so | FileCheck %s --check-prefix=PIC-EH-FRAME +# RUN: llvm-dwarfdump --eh-frame %t-pic32.so | FileCheck %s --check-prefix=PIC32-EH-FRAME # RELOCS: .rel{{a?}}.eh_frame { # ABS32-RELOCS-NEXT: 0x1C R_MIPS_32 .text # ABS64-RELOCS-NEXT: 0x1C R_MIPS_64/R_MIPS_NONE/R_MIPS_NONE .text -# PIC64-RELOCS-NEXT: 0x1C R_MIPS_PC32/R_MIPS_NONE/R_MIPS_NONE - +# PIC64-RELOCS-NEXT: 0x1C R_MIPS_PC32/R_MIPS_64/R_MIPS_NONE - # PIC32-RELOCS-NEXT: 0x1C R_MIPS_PC32 - # RELOCS-NEXT: } @@ -44,10 +44,10 @@ ## ^^ fde pointer encoding: DW_EH_PE_sdata8 # ABS32-EH-FRAME: Augmentation data: 0B ## ^^ fde pointer encoding: DW_EH_PE_sdata4 -# PIC-EH-FRAME: Augmentation data: 1B -## ^^ fde pointer encoding: DW_EH_PE_pcrel | DW_EH_PE_sdata4 -## Note: ld.bfd converts the R_MIPS_64 relocs to DW_EH_PE_pcrel | DW_EH_PE_sdata8 -## for N64 ABI (and DW_EH_PE_pcrel | DW_EH_PE_sdata4 for MIPS32) +# PIC32-EH-FRAME: Augmentation data: 1B +## ^^ fde pointer encoding: DW_EH_PE_pcrel | DW_EH_PE_sdata4 +# PIC64-EH-FRAME: Augmentation data: 1C +## ^^ fde pointer encoding: DW_EH_PE_pcrel | DW_EH_PE_sdata8 .ent func .global func diff --git a/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp b/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp --- a/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp +++ b/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp @@ -70,6 +70,10 @@ using namespace llvm; using namespace dwarf; +namespace llvm { +extern cl::opt MipsPC64Relocation; +} + static void GetObjCImageInfo(Module &M, unsigned &Version, unsigned &Flags, StringRef &Section) { SmallVector ModuleFlags; @@ -220,13 +224,9 @@ // identify N64 from just a triple. TTypeEncoding = dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4; - // We don't support PC-relative LSDA references in GAS so we use the default - // DW_EH_PE_absptr for those. - // FreeBSD must be explicit about the data size and using pcrel since it's - // assembler/linker won't do the automatic conversion that the Linux tools - // do. - if (TgtM.getTargetTriple().isOSFreeBSD()) { + if (isPositionIndependent() && + (MipsPC64Relocation || TgtM.getTargetTriple().isMIPS32())) { PersonalityEncoding |= dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4; LSDAEncoding = dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4; } diff --git a/llvm/lib/MC/MCObjectFileInfo.cpp b/llvm/lib/MC/MCObjectFileInfo.cpp --- a/llvm/lib/MC/MCObjectFileInfo.cpp +++ b/llvm/lib/MC/MCObjectFileInfo.cpp @@ -21,9 +21,16 @@ #include "llvm/MC/MCSectionMachO.h" #include "llvm/MC/MCSectionWasm.h" #include "llvm/MC/MCSectionXCOFF.h" +#include "llvm/Support/CommandLine.h" using namespace llvm; +namespace llvm { +cl::opt + MipsPC64Relocation("mmips-pc64-rel", cl::init(true), + cl::desc("Use MIPS 64-bit PC-relative relocations")); +} + static bool useCompactUnwind(const Triple &T) { // Only on darwin. if (!T.isOSDarwin()) @@ -308,14 +315,11 @@ case Triple::mipsel: case Triple::mips64: case Triple::mips64el: - // We cannot use DW_EH_PE_sdata8 for the large PositionIndependent case - // since there is no R_MIPS_PC64 relocation (only a 32-bit version). - if (PositionIndependent && !Large) - FDECFIEncoding = dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4; - else - FDECFIEncoding = Ctx->getAsmInfo()->getCodePointerSize() == 4 - ? dwarf::DW_EH_PE_sdata4 - : dwarf::DW_EH_PE_sdata8; + FDECFIEncoding = Ctx->getAsmInfo()->getCodePointerSize() == 4 + ? dwarf::DW_EH_PE_sdata4 + : dwarf::DW_EH_PE_sdata8; + if (PositionIndependent && (MipsPC64Relocation || T.isMIPS32())) + FDECFIEncoding |= dwarf::DW_EH_PE_pcrel; break; case Triple::ppc64: case Triple::ppc64le: diff --git a/llvm/test/CodeGen/Mips/ehframe-indirect.ll b/llvm/test/CodeGen/Mips/ehframe-indirect.ll --- a/llvm/test/CodeGen/Mips/ehframe-indirect.ll +++ b/llvm/test/CodeGen/Mips/ehframe-indirect.ll @@ -1,34 +1,40 @@ ; RUN: llc -mtriple=mipsel-linux-gnu < %s -asm-verbose -relocation-model=pic | \ -; RUN: FileCheck -check-prefixes=ALL,LINUX,LINUX-O32,O32 %s +; RUN: FileCheck -check-prefixes=ALL,O32 %s ; RUN: llc -mtriple=mipsel-linux-android < %s -asm-verbose -relocation-model=pic | \ -; RUN: FileCheck -check-prefixes=ALL,LINUX,LINUX-O32,O32 %s +; RUN: FileCheck -check-prefixes=ALL,O32 %s ; RUN: llc -mtriple=mips64el-linux-gnu -target-abi=n32 < %s -asm-verbose -relocation-model=pic | \ -; RUN: FileCheck -check-prefixes=ALL,LINUX,LINUX-NEW,N32 %s +; RUN: FileCheck -check-prefixes=ALL,N32,N32REL %s ; RUN: llc -mtriple=mips64el-linux-gnu < %s -asm-verbose -relocation-model=pic | \ -; RUN: FileCheck -check-prefixes=ALL,LINUX,LINUX-NEW,N64 %s +; RUN: FileCheck -check-prefixes=ALL,N64,N64REL %s ; RUN: llc -mtriple=mips64el-linux-android < %s -asm-verbose -relocation-model=pic | \ -; RUN: FileCheck -check-prefixes=ALL,LINUX,LINUX-NEW,N64 %s +; RUN: FileCheck -check-prefixes=ALL,N64,N64REL %s ; RUN: llc -mtriple=mips64el-linux-gnu < %s -asm-verbose -relocation-model=pic | \ -; RUN: FileCheck -check-prefixes=ALL,LINUX,LINUX-NEW,N64 %s -; RUN: llc -mtriple=mips-unknown-freebsd11.0 < %s -asm-verbose -relocation-model=pic | \ -; RUN: FileCheck -check-prefixes=ALL,FREEBSD,FREEBSD-O32,O32 %s +; RUN: FileCheck -check-prefixes=ALL,N64,N64REL %s ; RUN: llc -mtriple=mips64-unknown-freebsd11.0 < %s -asm-verbose -relocation-model=pic | \ -; RUN: FileCheck -check-prefixes=ALL,FREEBSD,FREEBSD-NEW,N64 %s +; RUN: FileCheck -check-prefixes=ALL,N64,N64REL %s + +; RUN: llc -mtriple=mips64-linux-gnu -target-abi=n32 -mmips-pc64-rel=false \ +; RUN: -asm-verbose -relocation-model=pic < %s | \ +; RUN: FileCheck -check-prefixes=ALL,N32,N32ABS %s +; RUN: llc -mtriple=mips64-linux-gnu -mmips-pc64-rel=false \ +; RUN: -asm-verbose -relocation-model=pic < %s | \ +; RUN: FileCheck -check-prefixes=ALL,N64,N64ABS %s @_ZTISt9exception = external constant i8* define i32 @main() personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) { ; ALL: .cfi_startproc -; Linux must rely on the assembler/linker converting the encodings. -; LINUX: .cfi_personality 128, DW.ref.__gxx_personality_v0 -; LINUX-O32: .cfi_lsda 0, $exception0 -; LINUX-NEW: .cfi_lsda 0, .Lexception0 - -; FreeBSD can (and must) be more direct about the encodings it wants. -; FREEBSD: .cfi_personality 155, DW.ref.__gxx_personality_v0 -; FREEBSD-O32: .cfi_lsda 27, $exception0 -; FREEBSD-NEW: .cfi_lsda 27, .Lexception0 +; O32: .cfi_personality 155, DW.ref.__gxx_personality_v0 +; O32: .cfi_lsda 27, $exception0 +; N32REL: .cfi_personality 155, DW.ref.__gxx_personality_v0 +; N32REL: .cfi_lsda 27, .Lexception0 +; N32ABS: .cfi_personality 128, DW.ref.__gxx_personality_v0 +; N32ABS: .cfi_lsda 0, .Lexception0 +; N64REL: .cfi_personality 155, DW.ref.__gxx_personality_v0 +; N64REL: .cfi_lsda 27, .Lexception0 +; N64ABS: .cfi_personality 128, DW.ref.__gxx_personality_v0 +; N64ABS: .cfi_lsda 0, .Lexception0 entry: invoke void @foo() to label %cont unwind label %lpad diff --git a/llvm/test/DebugInfo/Mips/eh_frame.ll b/llvm/test/DebugInfo/Mips/eh_frame.ll --- a/llvm/test/DebugInfo/Mips/eh_frame.ll +++ b/llvm/test/DebugInfo/Mips/eh_frame.ll @@ -17,9 +17,9 @@ ; STATIC-DAG: R_MIPS_32 00000000 .gcc_except_table ; PIC-LABEL: Relocation section '.rel.eh_frame' -; PIC-DAG: R_MIPS_32 00000000 DW.ref.__gxx_personality_v0 +; PIC-DAG: R_MIPS_PC32 00000000 DW.ref.__gxx_personality_v0 +; PIC-DAG: R_MIPS_PC32 ; PIC-DAG: R_MIPS_PC32 -; PIC-DAG: R_MIPS_32 00000000 .gcc_except_table ; CHECK-READELF: DW.ref.__gxx_personality_v0 ; CHECK-READELF-STATIC-NEXT: R_MIPS_32 00000000 .text diff --git a/llvm/test/MC/Mips/eh-frame.s b/llvm/test/MC/Mips/eh-frame.s --- a/llvm/test/MC/Mips/eh-frame.s +++ b/llvm/test/MC/Mips/eh-frame.s @@ -33,14 +33,18 @@ // RUN: llvm-readobj -r %t.o | FileCheck --check-prefixes=RELOCS,PIC64 %s // RUN: llvm-dwarfdump -eh-frame %t.o | FileCheck --check-prefixes=DWARF64,DWARF64_PIC %s -/// However using the large code model forces R_MIPS_64 since there is no R_MIPS_PC64 relocation: // RUN: llvm-mc -filetype=obj %s -o %t.o -triple mips64-unknown-linux-gnu --position-independent --large-code-model -// RUN: llvm-readobj -r %t.o | FileCheck --check-prefixes=RELOCS,ABS64 %s -// RUN: llvm-dwarfdump -eh-frame %t.o | FileCheck --check-prefixes=DWARF64,DWARF64_ABS %s +// RUN: llvm-readobj -r %t.o | FileCheck --check-prefixes=RELOCS,PIC64 %s +// RUN: llvm-dwarfdump -eh-frame %t.o | FileCheck --check-prefixes=DWARF64,DWARF64_PIC %s // RUN: llvm-mc -filetype=obj %s -o %t.o -triple mips64el-unknown-linux-gnu --position-independent --large-code-model -// RUN: llvm-readobj -r %t.o | FileCheck --check-prefixes=RELOCS,ABS64 %s -// RUN: llvm-dwarfdump -eh-frame %t.o | FileCheck --check-prefixes=DWARF64,DWARF64_ABS %s +// RUN: llvm-readobj -r %t.o | FileCheck --check-prefixes=RELOCS,PIC64 %s +// RUN: llvm-dwarfdump -eh-frame %t.o | FileCheck --check-prefixes=DWARF64,DWARF64_PIC %s + +// RUN: llvm-mc -filetype=obj %s -o %t.o -triple mips64-unknown-linux-gnu \ +// RUN: --position-independent --large-code-model -mmips-pc64-rel=false +// RUN: llvm-readobj -r %t.o | FileCheck --check-prefixes=RELOCS,OLD64 %s +// RUN: llvm-dwarfdump -eh-frame %t.o | FileCheck --check-prefixes=DWARF64,DWARF64_OLD %s func: .cfi_startproc @@ -51,7 +55,8 @@ // ABS32-NEXT: R_MIPS_32 // ABS64-NEXT: R_MIPS_64/R_MIPS_NONE/R_MIPS_NONE // PIC32-NEXT: R_MIPS_PC32 -// PIC64-NEXT: R_MIPS_PC32/R_MIPS_NONE/R_MIPS_NONE +// PIC64-NEXT: R_MIPS_PC32/R_MIPS_64/R_MIPS_NONE +// OLD64-NEXT: R_MIPS_64/R_MIPS_NONE/R_MIPS_NONE // RELOCS-NEXT: } // DWARF32: 00000000 00000010 00000000 CIE @@ -87,14 +92,17 @@ // DWARF64-NEXT: Return address column: 31 // DWARF64_ABS-NEXT: Augmentation data: 0C // ^^ fde pointer encoding: DW_EH_PE_sdata8 -// DWARF64_PIC: Augmentation data: 1B -// ^^ fde pointer encoding: DW_EH_PE_pcrel | DW_EH_PE_sdata4 +// DWARF64_PIC: Augmentation data: 1C +// ^^ fde pointer encoding: DW_EH_PE_pcrel | DW_EH_PE_sdata8 +// DWARF64_OLD: Augmentation data: 0C +// ^^ fde pointer encoding: DW_EH_PE_sdata8 // DWARF64-EMPTY: // DWARF64-NEXT: DW_CFA_def_cfa_register: SP_64 // DWARF64_PIC-NEXT: DW_CFA_nop: // // DWARF64_ABS: 00000014 00000018 00000018 FDE cie=00000000 pc=00000000...00000000 -// DWARF64_PIC: 00000014 00000010 00000018 FDE cie=00000000 pc=00000000...00000000 +// DWARF64_PIC: 00000014 00000018 00000018 FDE cie=00000000 pc=0000001c...0000001c +// DWARF64_OLD: 00000014 00000018 00000018 FDE cie=00000000 pc=00000000...00000000 // DWARF64-NEXT: Format: DWARF32 // DWARF64-NEXT: DW_CFA_nop: // DWARF64-NEXT: DW_CFA_nop: