Skip to content

Commit

Permalink
[M68k][WIP] Limit the usages of pc-rel reloc for GNU environment
Browse files Browse the repository at this point in the history
TBA
  • Loading branch information
mshockwave committed Mar 24, 2023
1 parent 1dfa6e9 commit 767ffe4
Show file tree
Hide file tree
Showing 6 changed files with 253 additions and 5 deletions.
5 changes: 5 additions & 0 deletions clang/lib/Driver/ToolChains/Arch/M68k.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,11 @@ void m68k::getM68kTargetFeatures(const Driver &D, const llvm::Triple &Triple,
Features.push_back("+reserve-d6");
if (Args.hasArg(options::OPT_ffixed_d7))
Features.push_back("+reserve-d7");

// Handle -mpcrel / -mno-pcrel
if (Args.hasFlag(options::OPT_mpcrel, options::OPT_mno_pcrel,
false))
Features.push_back("+use-pcrel");
}

m68k::FloatABI m68k::getM68kFloatABI(const Driver &D, const ArgList &Args) {
Expand Down
7 changes: 7 additions & 0 deletions clang/test/Driver/m68k-features.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@
// REQUIRES: m68k-registered-target

// ==== PC-Relative Relocation ====
// RUN: %clang -target m68k -mpcrel -### %s 2> %t
// RUN: FileCheck --check-prefix=CHECK-PCREL < %t %s
// CHECK-PCREL: "-target-feature" "+use-pcrel"

// ==== Register Reservation ====
// RUN: %clang -target m68k -ffixed-a0 -### %s 2> %t
// RUN: FileCheck --check-prefix=CHECK-FIXED-A0 < %t %s
// CHECK-FIXED-A0: "-target-feature" "+reserve-a0"
Expand Down
4 changes: 4 additions & 0 deletions llvm/lib/Target/M68k/M68k.td
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,10 @@ foreach i = {0-7} in
SubtargetFeature<"reserve-d"#i, "UserReservedRegister[M68k::D"#i#"]",
"true", "Reserve D"#i#" register">;

def FeaturePCRel :
SubtargetFeature<"use-pcrel", "UsePCRelativeRelocation", "true",
"Use pc-relative relocation">;

//===----------------------------------------------------------------------===//
// M68k processors supported.
//===----------------------------------------------------------------------===//
Expand Down
26 changes: 21 additions & 5 deletions llvm/lib/Target/M68k/M68kSubtarget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -148,27 +148,43 @@ unsigned char M68kSubtarget::classifyBlockAddressReference() const {
return M68kII::MO_PC_RELATIVE_ADDRESS;
}

/// Return relocation kind for potential pc-relative references.
unsigned char M68kSubtarget::usePCRelReference() const {
if (isPCRelative())
return M68kII::MO_PC_RELATIVE_ADDRESS;

// BFD LD is unable to resolve pcrel relocations against DSO symbols.
// Thus, we use absolute reloc here just to be safe and (maybe) relax it
// later if the symbol is truely DSO local.
if (TargetTriple.isGNUEnvironment()) {
return isPositionIndependent() ?
M68kII::MO_GOTPCREL : M68kII::MO_ABSOLUTE_ADDRESS;
} else {
return M68kII::MO_PC_RELATIVE_ADDRESS;
}
}

unsigned char
M68kSubtarget::classifyLocalReference(const GlobalValue *GV) const {
switch (TM.getCodeModel()) {
default:
llvm_unreachable("Unsupported code model");
case CodeModel::Small:
case CodeModel::Kernel: {
return M68kII::MO_PC_RELATIVE_ADDRESS;
return usePCRelReference();
}
case CodeModel::Medium: {
if (isPositionIndependent()) {
// On M68020 and better we can fit big any data offset into dips field.
if (atLeastM68020()) {
return M68kII::MO_PC_RELATIVE_ADDRESS;
return usePCRelReference();
}
// Otherwise we could check the data size and make sure it will fit into
// 16 bit offset. For now we will be conservative and go with @GOTOFF
return M68kII::MO_GOTOFF;
} else {
if (atLeastM68020()) {
return M68kII::MO_PC_RELATIVE_ADDRESS;
return usePCRelReference();
}
return M68kII::MO_ABSOLUTE_ADDRESS;
}
Expand Down Expand Up @@ -203,14 +219,14 @@ unsigned char M68kSubtarget::classifyGlobalReference(const GlobalValue *GV,
case CodeModel::Kernel: {
if (isPositionIndependent())
return M68kII::MO_GOTPCREL;
return M68kII::MO_PC_RELATIVE_ADDRESS;
return usePCRelReference();
}
case CodeModel::Medium: {
if (isPositionIndependent())
return M68kII::MO_GOTPCREL;

if (atLeastM68020())
return M68kII::MO_PC_RELATIVE_ADDRESS;
return usePCRelReference();

return M68kII::MO_ABSOLUTE_ADDRESS;
}
Expand Down
6 changes: 6 additions & 0 deletions llvm/lib/Target/M68k/M68kSubtarget.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ class M68kTargetMachine;
class M68kSubtarget : public M68kGenSubtargetInfo {
virtual void anchor();

unsigned char usePCRelReference() const;

protected:
// These define which ISA is supported. Since each Motorola M68k ISA is
// built on top of the previous one whenever an ISA is selected the previous
Expand All @@ -55,6 +57,8 @@ class M68kSubtarget : public M68kGenSubtargetInfo {

InstrItineraryData InstrItins;

bool UsePCRelativeRelocation = false;

/// Small section is used.
bool UseSmallSection = true;

Expand Down Expand Up @@ -106,6 +110,8 @@ class M68kSubtarget : public M68kGenSubtargetInfo {
return UserReservedRegister[R];
}

bool isPCRelative() const { return UsePCRelativeRelocation; }

/// Classify a global variable reference for the current subtarget according
/// to how we should reference it in a non-pcrel context.
unsigned char classifyLocalReference(const GlobalValue *GV) const;
Expand Down
210 changes: 210 additions & 0 deletions llvm/test/CodeGen/M68k/CodeModel/small-gnu.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,210 @@
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: llc < %s -O2 -mtriple=m68k-linux-gnu -verify-machineinstrs \
; RUN: -code-model=small -relocation-model=static \
; RUN: | FileCheck %s

; RUN: llc < %s -O2 -mtriple=m68k-linux-gnu -verify-machineinstrs \
; RUN: -code-model=small -relocation-model=static -mattr="+use-pcrel" \
; RUN: | FileCheck %s --check-prefix=CHECK-PCREL

; RUN: llc < %s -O2 -mtriple=m68k-linux-gnu -verify-machineinstrs \
; RUN: -code-model=small -relocation-model=pic \
; RUN: | FileCheck %s --check-prefix=CHECK-PIC

@ptr = external global i32*
@dst = external global i32
@src = external global i32

define void @test0() nounwind {
; CHECK-LABEL: test0:
; CHECK: ; %bb.0: ; %entry
; CHECK-NEXT: move.l #dst, ptr
; CHECK-NEXT: move.l src, dst
; CHECK-NEXT: rts
;
; CHECK-PCREL-LABEL: test0:
; CHECK-PCREL: ; %bb.0: ; %entry
; CHECK-PCREL-NEXT: lea (dst,%pc), %a0
; CHECK-PCREL-NEXT: move.l %a0, (ptr,%pc)
; CHECK-PCREL-NEXT: move.l (src,%pc), (dst,%pc)
; CHECK-PCREL-NEXT: rts
;
; CHECK-PIC-LABEL: test0:
; CHECK-PIC: ; %bb.0: ; %entry
; CHECK-PIC-NEXT: move.l (dst@GOTPCREL,%pc), %a0
; CHECK-PIC-NEXT: move.l (ptr@GOTPCREL,%pc), %a1
; CHECK-PIC-NEXT: move.l %a0, (%a1)
; CHECK-PIC-NEXT: move.l (src@GOTPCREL,%pc), %a1
; CHECK-PIC-NEXT: move.l (%a1), (%a0)
; CHECK-PIC-NEXT: rts
entry:
store i32* @dst, i32** @ptr
%tmp.s = load i32, i32* @src
store i32 %tmp.s, i32* @dst
ret void
}

@ptr2 = global i32* null
@dst2 = global i32 0
@src2 = global i32 0

define void @test1() nounwind {
; CHECK-LABEL: test1:
; CHECK: ; %bb.0: ; %entry
; CHECK-NEXT: move.l #dst2, ptr2
; CHECK-NEXT: move.l src2, dst2
; CHECK-NEXT: rts
;
; CHECK-PCREL-LABEL: test1:
; CHECK-PCREL: ; %bb.0: ; %entry
; CHECK-PCREL-NEXT: lea (dst2,%pc), %a0
; CHECK-PCREL-NEXT: move.l %a0, (ptr2,%pc)
; CHECK-PCREL-NEXT: move.l (src2,%pc), (dst2,%pc)
; CHECK-PCREL-NEXT: rts
;
; CHECK-PIC-LABEL: test1:
; CHECK-PIC: ; %bb.0: ; %entry
; CHECK-PIC-NEXT: move.l (dst2@GOTPCREL,%pc), %a0
; CHECK-PIC-NEXT: move.l (ptr2@GOTPCREL,%pc), %a1
; CHECK-PIC-NEXT: move.l %a0, (%a1)
; CHECK-PIC-NEXT: move.l (src2@GOTPCREL,%pc), %a1
; CHECK-PIC-NEXT: move.l (%a1), (%a0)
; CHECK-PIC-NEXT: rts
entry:
store i32* @dst2, i32** @ptr2
%tmp.s = load i32, i32* @src2
store i32 %tmp.s, i32* @dst2
ret void
}

declare i8* @malloc(i32)

define void @test2() nounwind {
; CHECK-LABEL: test2:
; CHECK: ; %bb.0: ; %entry
; CHECK-NEXT: suba.l #4, %sp
; CHECK-NEXT: move.l #40, (%sp)
; CHECK-NEXT: jsr malloc@PLT
; CHECK-NEXT: adda.l #4, %sp
; CHECK-NEXT: rts
;
; CHECK-PCREL-LABEL: test2:
; CHECK-PCREL: ; %bb.0: ; %entry
; CHECK-PCREL-NEXT: suba.l #4, %sp
; CHECK-PCREL-NEXT: move.l #40, (%sp)
; CHECK-PCREL-NEXT: jsr malloc@PLT
; CHECK-PCREL-NEXT: adda.l #4, %sp
; CHECK-PCREL-NEXT: rts
;
; CHECK-PIC-LABEL: test2:
; CHECK-PIC: ; %bb.0: ; %entry
; CHECK-PIC-NEXT: suba.l #4, %sp
; CHECK-PIC-NEXT: move.l #40, (%sp)
; CHECK-PIC-NEXT: jsr (malloc@PLT,%pc)
; CHECK-PIC-NEXT: adda.l #4, %sp
; CHECK-PIC-NEXT: rts
entry:
%ptr = call i8* @malloc(i32 40)
ret void
}

@pfoo = external global void(...)*
declare void(...)* @afoo(...)

define void @test3() nounwind {
; CHECK-LABEL: test3:
; CHECK: ; %bb.0: ; %entry
; CHECK-NEXT: suba.l #4, %sp
; CHECK-NEXT: jsr afoo@PLT
; CHECK-NEXT: move.l %a0, pfoo
; CHECK-NEXT: jsr (%a0)
; CHECK-NEXT: adda.l #4, %sp
; CHECK-NEXT: rts
;
; CHECK-PCREL-LABEL: test3:
; CHECK-PCREL: ; %bb.0: ; %entry
; CHECK-PCREL-NEXT: suba.l #4, %sp
; CHECK-PCREL-NEXT: jsr afoo@PLT
; CHECK-PCREL-NEXT: move.l %a0, (pfoo,%pc)
; CHECK-PCREL-NEXT: jsr (%a0)
; CHECK-PCREL-NEXT: adda.l #4, %sp
; CHECK-PCREL-NEXT: rts
;
; CHECK-PIC-LABEL: test3:
; CHECK-PIC: ; %bb.0: ; %entry
; CHECK-PIC-NEXT: suba.l #4, %sp
; CHECK-PIC-NEXT: jsr (afoo@PLT,%pc)
; CHECK-PIC-NEXT: move.l (pfoo@GOTPCREL,%pc), %a1
; CHECK-PIC-NEXT: move.l %a0, (%a1)
; CHECK-PIC-NEXT: jsr (%a0)
; CHECK-PIC-NEXT: adda.l #4, %sp
; CHECK-PIC-NEXT: rts
entry:
%tmp = call void(...)*(...) @afoo()
store void(...)* %tmp, void(...)** @pfoo
%tmp1 = load void(...)*, void(...)** @pfoo
call void(...) %tmp1()
ret void
}

declare void @foo(...)

define void @test4() nounwind {
; CHECK-LABEL: test4:
; CHECK: ; %bb.0: ; %entry
; CHECK-NEXT: suba.l #4, %sp
; CHECK-NEXT: jsr foo@PLT
; CHECK-NEXT: adda.l #4, %sp
; CHECK-NEXT: rts
;
; CHECK-PCREL-LABEL: test4:
; CHECK-PCREL: ; %bb.0: ; %entry
; CHECK-PCREL-NEXT: suba.l #4, %sp
; CHECK-PCREL-NEXT: jsr foo@PLT
; CHECK-PCREL-NEXT: adda.l #4, %sp
; CHECK-PCREL-NEXT: rts
;
; CHECK-PIC-LABEL: test4:
; CHECK-PIC: ; %bb.0: ; %entry
; CHECK-PIC-NEXT: suba.l #4, %sp
; CHECK-PIC-NEXT: jsr (foo@PLT,%pc)
; CHECK-PIC-NEXT: adda.l #4, %sp
; CHECK-PIC-NEXT: rts
entry:
call void(...) @foo()
ret void
}

@ptr6 = internal global i32* null
@dst6 = internal global i32 0
@src6 = internal global i32 0

define void @test5() nounwind {
; CHECK-LABEL: test5:
; CHECK: ; %bb.0: ; %entry
; CHECK-NEXT: move.l #dst6, ptr6
; CHECK-NEXT: move.l src6, dst6
; CHECK-NEXT: rts
;
; CHECK-PCREL-LABEL: test5:
; CHECK-PCREL: ; %bb.0: ; %entry
; CHECK-PCREL-NEXT: lea (dst6,%pc), %a0
; CHECK-PCREL-NEXT: move.l %a0, (ptr6,%pc)
; CHECK-PCREL-NEXT: move.l (src6,%pc), (dst6,%pc)
; CHECK-PCREL-NEXT: rts
;
; CHECK-PIC-LABEL: test5:
; CHECK-PIC: ; %bb.0: ; %entry
; CHECK-PIC-NEXT: move.l (dst6@GOTPCREL,%pc), %a0
; CHECK-PIC-NEXT: move.l (ptr6@GOTPCREL,%pc), %a1
; CHECK-PIC-NEXT: move.l %a0, (%a1)
; CHECK-PIC-NEXT: move.l (src6@GOTPCREL,%pc), %a1
; CHECK-PIC-NEXT: move.l (%a1), (%a0)
; CHECK-PIC-NEXT: rts
entry:
store i32* @dst6, i32** @ptr6
%tmp.s = load i32, i32* @src6
store i32 %tmp.s, i32* @dst6
ret void
}

0 comments on commit 767ffe4

Please sign in to comment.