Skip to content

[AVR] Fix parsing & emitting relative jumps #106722

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Aug 30, 2024
Merged
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
15 changes: 11 additions & 4 deletions llvm/lib/Target/AVR/AsmParser/AVRAsmParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ class AVRAsmParser : public MCTargetAsmParser {
int parseRegisterName();
int parseRegister(bool RestoreOnFailure = false);
bool tryParseRegisterOperand(OperandVector &Operands);
bool tryParseExpression(OperandVector &Operands);
bool tryParseExpression(OperandVector &Operands, int64_t offset);
bool tryParseRelocExpression(OperandVector &Operands);
void eatComma();

Expand Down Expand Up @@ -418,7 +418,7 @@ bool AVRAsmParser::tryParseRegisterOperand(OperandVector &Operands) {
return false;
}

bool AVRAsmParser::tryParseExpression(OperandVector &Operands) {
bool AVRAsmParser::tryParseExpression(OperandVector &Operands, int64_t offset) {
SMLoc S = Parser.getTok().getLoc();

if (!tryParseRelocExpression(Operands))
Expand All @@ -437,6 +437,11 @@ bool AVRAsmParser::tryParseExpression(OperandVector &Operands) {
if (getParser().parseExpression(Expression))
return true;

if (offset) {
Expression = MCBinaryExpr::createAdd(
Expression, MCConstantExpr::create(offset, getContext()), getContext());
}

SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Operands.push_back(AVROperand::CreateImm(Expression, S, E));
return false;
Expand Down Expand Up @@ -529,8 +534,9 @@ bool AVRAsmParser::parseOperand(OperandVector &Operands, bool maybeReg) {
[[fallthrough]];
case AsmToken::LParen:
case AsmToken::Integer:
return tryParseExpression(Operands, 0);
case AsmToken::Dot:
return tryParseExpression(Operands);
return tryParseExpression(Operands, 2);
case AsmToken::Plus:
case AsmToken::Minus: {
// If the sign preceeds a number, parse the number,
Expand All @@ -540,7 +546,7 @@ bool AVRAsmParser::parseOperand(OperandVector &Operands, bool maybeReg) {
case AsmToken::BigNum:
case AsmToken::Identifier:
case AsmToken::Real:
if (!tryParseExpression(Operands))
if (!tryParseExpression(Operands, 0))
return false;
break;
default:
Expand Down Expand Up @@ -643,6 +649,7 @@ bool AVRAsmParser::ParseInstruction(ParseInstructionInfo &Info,
// These specific operands should be treated as addresses/symbols/labels,
// other than registers.
bool maybeReg = true;

if (OperandNum == 1) {
std::array<StringRef, 8> Insts = {"lds", "adiw", "sbiw", "ldi"};
for (auto Inst : Insts) {
Expand Down
12 changes: 5 additions & 7 deletions llvm/lib/Target/AVR/MCTargetDesc/AVRAsmBackend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,9 @@ static void adjustRelativeBranch(unsigned Size, const MCFixup &Fixup,

// Rightshifts the value by one.
AVR::fixups::adjustBranchTarget(Value);

// Jumps are relative to the current instruction.
Value -= 1;
}

/// 22-bit absolute fixup.
Expand Down Expand Up @@ -513,15 +516,10 @@ bool AVRAsmBackend::shouldForceRelocation(const MCAssembler &Asm,
switch ((unsigned)Fixup.getKind()) {
default:
return Fixup.getKind() >= FirstLiteralRelocationKind;
// Fixups which should always be recorded as relocations.
case AVR::fixup_7_pcrel:
case AVR::fixup_13_pcrel:
// Do not force relocation for PC relative branch like 'rjmp .',
// 'rcall . - off' and 'breq . + off'.
if (const auto *SymA = Target.getSymA())
if (SymA->getSymbol().getName().size() == 0)
return false;
[[fallthrough]];
// Always resolve relocations for PC-relative branches
return false;
case AVR::fixup_call:
return true;
}
Expand Down
25 changes: 25 additions & 0 deletions llvm/test/CodeGen/AVR/jmp.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
; RUN: llc -filetype=obj -mtriple=avr < %s | llvm-objdump -dr --no-show-raw-insn - | FileCheck %s

define i8 @foo(i8 %a) {
bb0:
%0 = tail call i8 @bar(i8 %a)
%1 = icmp eq i8 %0, 123
br i1 %1, label %bb1, label %bb2

bb1:
ret i8 100

bb2:
ret i8 200
}

declare i8 @bar(i8);

; CHECK: rcall .-2
; CHECK-NEXT: 00000000: R_AVR_13_PCREL bar
; CHECK-NEXT: cpi r24, 0x7b
; CHECK-NEXT: brne .+4
; CHECK-NEXT: ldi r24, 0x64
; CHECK-NEXT: ret
; CHECK-NEXT: ldi r24, 0xc8
; CHECK-NEXT: ret
23 changes: 12 additions & 11 deletions llvm/test/MC/AVR/inst-brbc.s
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,23 @@
; RUN: | llvm-objdump -d - | FileCheck --check-prefix=INST %s

foo:

brbc 3, .+8
brbc 0, .-16
.short 0xf759
.short 0xf752
.short 0xf74c
.short 0xf4c7

; CHECK: brvc .Ltmp0+8 ; encoding: [0bAAAAA011,0b111101AA]
; CHECK: ; fixup A - offset: 0, value: .Ltmp0+8, kind: fixup_7_pcrel
; CHECK: brcc .Ltmp1-16 ; encoding: [0bAAAAA000,0b111101AA]
; CHECK: ; fixup A - offset: 0, value: .Ltmp1-16, kind: fixup_7_pcrel
; CHECK: brvc (.Ltmp0+8)+2 ; encoding: [0bAAAAA011,0b111101AA]
; CHECK-NEXT: ; fixup A - offset: 0, value: (.Ltmp0+8)+2, kind: fixup_7_pcrel
;
; CHECK: brcc (.Ltmp1-16)+2 ; encoding: [0bAAAAA000,0b111101AA]
; CHECK-NEXT: ; fixup A - offset: 0, value: (.Ltmp1-16)+2, kind: fixup_7_pcrel

; INST: 23 f4 brvc .+8
; INST: c0 f7 brsh .-16
; INST: 59 f7 brne .-42
; INST: 52 f7 brpl .-44
; INST: 4c f7 brge .-46
; INST: c7 f4 brid .+48
; INST-LABEL: <foo>:
; INST-NEXT: 23 f4 brvc .+8
; INST-NEXT: c0 f7 brsh .-16
; INST-NEXT: 59 f7 brne .-42
; INST-NEXT: 52 f7 brpl .-44
; INST-NEXT: 4c f7 brge .-46
; INST-NEXT: c7 f4 brid .+48
22 changes: 11 additions & 11 deletions llvm/test/MC/AVR/inst-brbs.s
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,22 @@
; RUN: | llvm-objdump -d - | FileCheck --check-prefix=INST %s

foo:

brbs 3, .+8
brbs 0, .-12
.short 0xf359
.short 0xf352
.short 0xf34c
.short 0xf077

; CHECK: brvs .Ltmp0+8 ; encoding: [0bAAAAA011,0b111100AA]
; CHECK: ; fixup A - offset: 0, value: .Ltmp0+8, kind: fixup_7_pcrel
; CHECK: brcs .Ltmp1-12 ; encoding: [0bAAAAA000,0b111100AA]
; CHECK: ; fixup A - offset: 0, value: .Ltmp1-12, kind: fixup_7_pcrel
; CHECK: brvs (.Ltmp0+8)+2 ; encoding: [0bAAAAA011,0b111100AA]
; CHECK-NEXT: ; fixup A - offset: 0, value: (.Ltmp0+8)+2, kind: fixup_7_pcrel
; CHECK: brcs (.Ltmp1-12)+2 ; encoding: [0bAAAAA000,0b111100AA]
; CHECK-NEXT: ; fixup A - offset: 0, value: (.Ltmp1-12)+2, kind: fixup_7_pcrel

; INST: 23 f0 brvs .+8
; INST: d0 f3 brlo .-12
; INST: 59 f3 breq .-42
; INST: 52 f3 brmi .-44
; INST: 4c f3 brlt .-46
; INST: 77 f0 brie .+28
; INST-LABEL: <foo>:
; INST-NEXT: 23 f0 brvs .+8
; INST-NEXT: d0 f3 brlo .-12
; INST-NEXT: 59 f3 breq .-42
; INST-NEXT: 52 f3 brmi .-44
; INST-NEXT: 4c f3 brlt .-46
; INST-NEXT: 77 f0 brie .+28
28 changes: 28 additions & 0 deletions llvm/test/MC/AVR/inst-brcc.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
; RUN: llvm-mc -triple avr -show-encoding < %s | FileCheck %s
;
; RUN: llvm-mc -filetype=obj -triple avr < %s \
; RUN: | llvm-objdump -d - \
; RUN: | FileCheck --check-prefix=INST %s

foo:
brcc .+66
brcc .-22
brbc 0, .+66
brbc 0, bar

bar:

; CHECK: brcc (.Ltmp0+66)+2 ; encoding: [0bAAAAA000,0b111101AA]
; CHECK-NEXT: ; fixup A - offset: 0, value: (.Ltmp0+66)+2, kind: fixup_7_pcrel
; CHECK: brcc (.Ltmp1-22)+2 ; encoding: [0bAAAAA000,0b111101AA]
; CHECK-NEXT: ; fixup A - offset: 0, value: (.Ltmp1-22)+2, kind: fixup_7_pcrel
; CHECK: brcc (.Ltmp2+66)+2 ; encoding: [0bAAAAA000,0b111101AA]
; CHECK-NEXT: ; fixup A - offset: 0, value: (.Ltmp2+66)+2, kind: fixup_7_pcrel
; CHECK: brcc bar ; encoding: [0bAAAAA000,0b111101AA]
; CHECK-NEXT: ; fixup A - offset: 0, value: bar, kind: fixup_7_pcrel

; INST-LABEL: <foo>:
; INST-NEXT: 08 f5 brsh .+66
; INST-NEXT: a8 f7 brsh .-22
; INST-NEXT: 08 f5 brsh .+66
; INST-NEXT: 00 f4 brsh .+0
28 changes: 28 additions & 0 deletions llvm/test/MC/AVR/inst-brcs.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
; RUN: llvm-mc -triple avr -show-encoding < %s | FileCheck %s
;
; RUN: llvm-mc -filetype=obj -triple avr < %s \
; RUN: | llvm-objdump -d - \
; RUN: | FileCheck --check-prefix=INST %s

foo:
brcs .+8
brcs .+4
brbs 0, .+8
brbs 0, bar

bar:

; CHECK: brcs (.Ltmp0+8)+2 ; encoding: [0bAAAAA000,0b111100AA]
; CHECK-NEXT: ; fixup A - offset: 0, value: (.Ltmp0+8)+2, kind: fixup_7_pcrel
; CHECK: brcs (.Ltmp1+4)+2 ; encoding: [0bAAAAA000,0b111100AA]
; CHECK-NEXT: ; fixup A - offset: 0, value: (.Ltmp1+4)+2, kind: fixup_7_pcrel
; CHECK: brcs (.Ltmp2+8)+2 ; encoding: [0bAAAAA000,0b111100AA]
; CHECK-NEXT: ; fixup A - offset: 0, value: (.Ltmp2+8)+2, kind: fixup_7_pcrel
; CHECK: brcs bar ; encoding: [0bAAAAA000,0b111100AA]
; CHECK-NEXT: ; fixup A - offset: 0, value: bar, kind: fixup_7_pcrel

; INST-LABEL: <foo>:
; INST-NEXT: 20 f0 brlo .+8
; INST-NEXT: 10 f0 brlo .+4
; INST-NEXT: 20 f0 brlo .+8
; INST-NEXT: 00 f0 brlo .+0
28 changes: 28 additions & 0 deletions llvm/test/MC/AVR/inst-breq.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
; RUN: llvm-mc -triple avr -show-encoding < %s | FileCheck %s
;
; RUN: llvm-mc -filetype=obj -triple avr < %s \
; RUN: | llvm-objdump -d - \
; RUN: | FileCheck --check-prefix=INST %s

foo:
breq .-18
breq .-12
brbs 1, .-18
brbs 1, bar

bar:

; CHECK: breq (.Ltmp0-18)+2 ; encoding: [0bAAAAA001,0b111100AA]
; CHECK-NEXT: ; fixup A - offset: 0, value: (.Ltmp0-18)+2, kind: fixup_7_pcrel
; CHECK: breq (.Ltmp1-12)+2 ; encoding: [0bAAAAA001,0b111100AA]
; CHECK-NEXT: ; fixup A - offset: 0, value: (.Ltmp1-12)+2, kind: fixup_7_pcrel
; CHECK: brbs 1, (.Ltmp2-18)+2 ; encoding: [0bAAAAA001,0b111100AA]
; CHECK-NEXT: ; fixup A - offset: 0, value: (.Ltmp2-18)+2, kind: fixup_7_pcrel
; CHECK: brbs 1, bar ; encoding: [0bAAAAA001,0b111100AA]
; CHECK-NEXT: ; fixup A - offset: 0, value: bar, kind: fixup_7_pcrel

; INST-LABEL: <foo>:
; INST-NEXT: b9 f3 breq .-18
; INST-NEXT: d1 f3 breq .-12
; INST-NEXT: b9 f3 breq .-18
; INST-NEXT: 01 f0 breq .+0
24 changes: 24 additions & 0 deletions llvm/test/MC/AVR/inst-brge.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
; RUN: llvm-mc -triple avr -show-encoding < %s | FileCheck %s
;
; RUN: llvm-mc -filetype=obj -triple avr < %s \
; RUN: | llvm-objdump -d - \
; RUN: | FileCheck --check-prefix=INST %s

foo:
brge .+50
brge .+42
brge bar

bar:

; CHECK: brge (.Ltmp0+50)+2 ; encoding: [0bAAAAA100,0b111101AA]
; CHECK-NEXT: ; fixup A - offset: 0, value: (.Ltmp0+50)+2, kind: fixup_7_pcrel
; CHECK: brge (.Ltmp1+42)+2 ; encoding: [0bAAAAA100,0b111101AA]
; CHECK-NEXT: ; fixup A - offset: 0, value: (.Ltmp1+42)+2, kind: fixup_7_pcrel
; CHECK: brge bar ; encoding: [0bAAAAA100,0b111101AA]
; CHECK-NEXT: ; fixup A - offset: 0, value: bar, kind: fixup_7_pcrel

; INST-LABEL: <foo>:
; INST-NEXT: cc f4 brge .+50
; INST-NEXT: ac f4 brge .+42
; INST-NEXT: 04 f4 brge .+0
24 changes: 24 additions & 0 deletions llvm/test/MC/AVR/inst-brhc.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
; RUN: llvm-mc -triple avr -show-encoding < %s | FileCheck %s
;
; RUN: llvm-mc -filetype=obj -triple avr < %s \
; RUN: | llvm-objdump -d - \
; RUN: | FileCheck --check-prefix=INST %s

foo:
brhc .+12
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Having so many instructions could be a maintenance problem.

For other targets we typically pack tests of the same instruction format.

llvm/test/MC/M68k/ and llvm/test/MC/LoongArch/ are good examples.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, thanks - I'll take a look!

brhc .+14
brhc bar

bar:

; CHECK: brhc (.Ltmp0+12)+2 ; encoding: [0bAAAAA101,0b111101AA]
; CHECK-NEXT: ; fixup A - offset: 0, value: (.Ltmp0+12)+2, kind: fixup_7_pcrel
; CHECK: brhc (.Ltmp1+14)+2 ; encoding: [0bAAAAA101,0b111101AA]
; CHECK-NEXT: ; fixup A - offset: 0, value: (.Ltmp1+14)+2, kind: fixup_7_pcrel
; CHECK: brhc bar ; encoding: [0bAAAAA101,0b111101AA]
; CHECK-NEXT: ; fixup A - offset: 0, value: bar, kind: fixup_7_pcrel

; INST-LABEL: <foo>:
; INST-NEXT: 35 f4 brhc .+12
; INST-NEXT: 3d f4 brhc .+14
; INST-NEXT: 05 f4 brhc .+0
24 changes: 24 additions & 0 deletions llvm/test/MC/AVR/inst-brhs.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
; RUN: llvm-mc -triple avr -show-encoding < %s | FileCheck %s
;
; RUN: llvm-mc -filetype=obj -triple avr < %s \
; RUN: | llvm-objdump -d - \
; RUN: | FileCheck --check-prefix=INST %s

foo:
brhs .-66
brhs .+14
brhs bar

bar:

; CHECK: brhs (.Ltmp0-66)+2 ; encoding: [0bAAAAA101,0b111100AA]
; CHECK-NEXT: ; fixup A - offset: 0, value: (.Ltmp0-66)+2, kind: fixup_7_pcrel
; CHECK: brhs (.Ltmp1+14)+2 ; encoding: [0bAAAAA101,0b111100AA]
; CHECK-NEXT: ; fixup A - offset: 0, value: (.Ltmp1+14)+2, kind: fixup_7_pcrel
; CHECK: brhs bar ; encoding: [0bAAAAA101,0b111100AA]
; CHECK-NEXT: ; fixup A - offset: 0, value: bar, kind: fixup_7_pcrel

; INST-LABEL: <foo>:
; INST-NEXT: fd f2 brhs .-66
; INST-NEXT: 3d f0 brhs .+14
; INST-NEXT: 05 f0 brhs .+0
24 changes: 24 additions & 0 deletions llvm/test/MC/AVR/inst-brid.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
; RUN: llvm-mc -triple avr -show-encoding < %s | FileCheck %s
;
; RUN: llvm-mc -filetype=obj -triple avr < %s \
; RUN: | llvm-objdump -d - \
; RUN: | FileCheck --check-prefix=INST %s

foo:
brid .+42
brid .+62
brid bar

bar:

; CHECK: brid (.Ltmp0+42)+2 ; encoding: [0bAAAAA111,0b111101AA]
; CHECK-NEXT: ; fixup A - offset: 0, value: (.Ltmp0+42)+2, kind: fixup_7_pcrel
; CHECK: brid (.Ltmp1+62)+2 ; encoding: [0bAAAAA111,0b111101AA]
; CHECK-NEXT: ; fixup A - offset: 0, value: (.Ltmp1+62)+2, kind: fixup_7_pcrel
; CHECK: brid bar ; encoding: [0bAAAAA111,0b111101AA]
; CHECK-NEXT: ; fixup A - offset: 0, value: bar, kind: fixup_7_pcrel

; INST-LABEL: <foo>:
; INST-NEXT: af f4 brid .+42
; INST-NEXT: ff f4 brid .+62
; INST-NEXT: 07 f4 brid .+0
24 changes: 24 additions & 0 deletions llvm/test/MC/AVR/inst-brie.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
; RUN: llvm-mc -triple avr -show-encoding < %s | FileCheck %s
;
; RUN: llvm-mc -filetype=obj -triple avr < %s \
; RUN: | llvm-objdump -d - \
; RUN: | FileCheck --check-prefix=INST %s

foo:
brie .+20
brie .+40
brie bar

bar:

; CHECK: brie (.Ltmp0+20)+2 ; encoding: [0bAAAAA111,0b111100AA]
; CHECK-NEXT: ; fixup A - offset: 0, value: (.Ltmp0+20)+2, kind: fixup_7_pcrel
; CHECK: brie (.Ltmp1+40)+2 ; encoding: [0bAAAAA111,0b111100AA]
; CHECK-NEXT: ; fixup A - offset: 0, value: (.Ltmp1+40)+2, kind: fixup_7_pcrel
; CHECK: brie bar ; encoding: [0bAAAAA111,0b111100AA]
; CHECK-NEXT: ; fixup A - offset: 0, value: bar, kind: fixup_7_pcrel

; INST-LABEL: <foo>:
; INST-NEXT: 57 f0 brie .+20
; INST-NEXT: a7 f0 brie .+40
; INST-NEXT: 07 f0 brie .+0
Loading
Loading