Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 22 additions & 2 deletions llvm/lib/Target/PowerPC/MCTargetDesc/PPCAsmBackend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,25 @@
#include "llvm/Support/ErrorHandling.h"
using namespace llvm;

static uint64_t adjustFixupValue(unsigned Kind, uint64_t Value) {
static uint64_t adjustFixupValue(MCContext &Ctx, const MCFixup &Fixup,
unsigned Kind, uint64_t Value) {
auto checkBrFixup = [&](unsigned Bits) {
int64_t SVal = int64_t(Value);
if ((Value & 3) != 0) {
Ctx.reportError(Fixup.getLoc(), "branch target not a multiple of four (" +
Twine(SVal) + ")");
return;
}

// Low two bits are not encoded.
if (!isIntN(Bits + 2, Value)) {
Ctx.reportError(Fixup.getLoc(), "branch target out of range (" +
Twine(SVal) + " not between " +
Twine(minIntN(Bits) * 4) + " and " +
Twine(maxIntN(Bits) * 4) + ")");
}
};

switch (Kind) {
default:
llvm_unreachable("Unknown fixup kind!");
Expand All @@ -37,10 +55,12 @@ static uint64_t adjustFixupValue(unsigned Kind, uint64_t Value) {
return Value;
case PPC::fixup_ppc_brcond14:
case PPC::fixup_ppc_brcond14abs:
checkBrFixup(14);
return Value & 0xfffc;
case PPC::fixup_ppc_br24:
case PPC::fixup_ppc_br24abs:
case PPC::fixup_ppc_br24_notoc:
checkBrFixup(24);
return Value & 0x3fffffc;
case PPC::fixup_ppc_half16:
return Value & 0xffff;
Expand Down Expand Up @@ -202,7 +222,7 @@ void PPCAsmBackend::applyFixup(const MCFragment &F, const MCFixup &Fixup,
MCFixupKind Kind = Fixup.getKind();
if (mc::isRelocation(Kind))
return;
Value = adjustFixupValue(Kind, Value);
Value = adjustFixupValue(getContext(), Fixup, Kind, Value);
if (!Value)
return; // Doesn't change encoding.

Expand Down
43 changes: 43 additions & 0 deletions llvm/test/MC/PowerPC/fixup-out-of-range.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# RUN: not llvm-mc -triple powerpc64le-unknown-unknown -filetype=obj %s 2>&1 >/dev/null | FileCheck %s

# CHECK: error: branch target out of range (32772 not between -32768 and 32764)
brcond14_out_of_range_hi:
beq 0, brcond14_target
.space 0x8000

brcond14_target:
blr

# CHECK: error: branch target out of range (-32772 not between -32768 and 32764)
brcond14_out_of_range_lo:
.space 0x8004
beq 0, brcond14_out_of_range_lo

# CHECK: error: branch target not a multiple of four (5)
brcond14_misaligned:
beq 0, brcond14_misaligned_target
.byte 0

brcond14_misaligned_target:
blr

# CHECK: error: branch target out of range (33554436 not between -33554432 and 33554428)
br24_out_of_range_hi:
b br24_target
.space 0x2000000

br24_target:
blr

# CHECK: error: branch target out of range (-33554436 not between -33554432 and 33554428)
br24_out_of_range_lo:
.space 0x2000004
b br24_out_of_range_lo

# CHECK: error: branch target not a multiple of four (5)
br24_misaligned:
b br24_misaligned_target
.byte 0

br24_misaligned_target:
blr
Loading