Skip to content

Commit 6ed47d9

Browse files
committed
[AVR] Fix parsing & emitting relative jumps
1 parent a4900f0 commit 6ed47d9

26 files changed

+566
-400
lines changed

llvm/lib/Target/AVR/AsmParser/AVRAsmParser.cpp

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ class AVRAsmParser : public MCTargetAsmParser {
7272
int parseRegisterName();
7373
int parseRegister(bool RestoreOnFailure = false);
7474
bool tryParseRegisterOperand(OperandVector &Operands);
75-
bool tryParseExpression(OperandVector &Operands);
75+
bool tryParseExpression(OperandVector &Operands, int64_t offset);
7676
bool tryParseRelocExpression(OperandVector &Operands);
7777
void eatComma();
7878

@@ -418,7 +418,7 @@ bool AVRAsmParser::tryParseRegisterOperand(OperandVector &Operands) {
418418
return false;
419419
}
420420

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

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

440+
if (offset) {
441+
Expression = MCBinaryExpr::createAdd(
442+
Expression, MCConstantExpr::create(offset, getContext()), getContext());
443+
}
444+
440445
SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
441446
Operands.push_back(AVROperand::CreateImm(Expression, S, E));
442447
return false;
@@ -529,8 +534,9 @@ bool AVRAsmParser::parseOperand(OperandVector &Operands, bool maybeReg) {
529534
[[fallthrough]];
530535
case AsmToken::LParen:
531536
case AsmToken::Integer:
537+
return tryParseExpression(Operands, 0);
532538
case AsmToken::Dot:
533-
return tryParseExpression(Operands);
539+
return tryParseExpression(Operands, 2);
534540
case AsmToken::Plus:
535541
case AsmToken::Minus: {
536542
// If the sign preceeds a number, parse the number,
@@ -540,7 +546,7 @@ bool AVRAsmParser::parseOperand(OperandVector &Operands, bool maybeReg) {
540546
case AsmToken::BigNum:
541547
case AsmToken::Identifier:
542548
case AsmToken::Real:
543-
if (!tryParseExpression(Operands))
549+
if (!tryParseExpression(Operands, 0))
544550
return false;
545551
break;
546552
default:
@@ -643,6 +649,7 @@ bool AVRAsmParser::ParseInstruction(ParseInstructionInfo &Info,
643649
// These specific operands should be treated as addresses/symbols/labels,
644650
// other than registers.
645651
bool maybeReg = true;
652+
646653
if (OperandNum == 1) {
647654
std::array<StringRef, 8> Insts = {"lds", "adiw", "sbiw", "ldi"};
648655
for (auto Inst : Insts) {

llvm/lib/Target/AVR/MCTargetDesc/AVRAsmBackend.cpp

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,9 @@ static void adjustRelativeBranch(unsigned Size, const MCFixup &Fixup,
9494

9595
// Rightshifts the value by one.
9696
AVR::fixups::adjustBranchTarget(Value);
97+
98+
// Jumps are relative to the current instruction.
99+
Value -= 1;
97100
}
98101

99102
/// 22-bit absolute fixup.
@@ -513,14 +516,10 @@ bool AVRAsmBackend::shouldForceRelocation(const MCAssembler &Asm,
513516
switch ((unsigned)Fixup.getKind()) {
514517
default:
515518
return Fixup.getKind() >= FirstLiteralRelocationKind;
516-
// Fixups which should always be recorded as relocations.
517519
case AVR::fixup_7_pcrel:
518520
case AVR::fixup_13_pcrel:
519-
// Do not force relocation for PC relative branch like 'rjmp .',
520-
// 'rcall . - off' and 'breq . + off'.
521-
if (const auto *SymA = Target.getSymA())
522-
if (SymA->getSymbol().getName().size() == 0)
523-
return false;
521+
// Always resolve relocations for PC-relative branches
522+
return false;
524523
[[fallthrough]];
525524
case AVR::fixup_call:
526525
return true;

llvm/test/CodeGen/AVR/jmp.ll

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
; RUN: llc -filetype=obj -mtriple=avr < %s | llvm-objdump -d --no-show-raw-insn - | FileCheck %s
2+
3+
define i8 @foo(i8 %a) {
4+
bb0:
5+
%0 = tail call i8 @bar(i8 %a)
6+
%1 = icmp eq i8 %0, 123
7+
br i1 %1, label %bb1, label %bb2
8+
9+
bb1:
10+
ret i8 100
11+
12+
bb2:
13+
ret i8 200
14+
}
15+
16+
declare i8 @bar(i8);
17+
18+
; CHECK: rcall .-2
19+
; CHECK-NEXT: cpi r24, 0x7b
20+
; CHECK-NEXT: brne .+4
21+
; CHECK-NEXT: ldi r24, 0x64
22+
; CHECK-NEXT: ret
23+
; CHECK-NEXT: ldi r24, 0xc8
24+
; CHECK-NEXT: ret

llvm/test/MC/AVR/inst-brbc.s

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,22 +3,23 @@
33
; RUN: | llvm-objdump -d - | FileCheck --check-prefix=INST %s
44

55
foo:
6-
76
brbc 3, .+8
87
brbc 0, .-16
98
.short 0xf759
109
.short 0xf752
1110
.short 0xf74c
1211
.short 0xf4c7
1312

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

19-
; INST: 23 f4 brvc .+8
20-
; INST: c0 f7 brsh .-16
21-
; INST: 59 f7 brne .-42
22-
; INST: 52 f7 brpl .-44
23-
; INST: 4c f7 brge .-46
24-
; INST: c7 f4 brid .+48
19+
; INST-LABEL: <foo>:
20+
; INST-NEXT: 23 f4 brvc .+8
21+
; INST-NEXT: c0 f7 brsh .-16
22+
; INST-NEXT: 59 f7 brne .-42
23+
; INST-NEXT: 52 f7 brpl .-44
24+
; INST-NEXT: 4c f7 brge .-46
25+
; INST-NEXT: c7 f4 brid .+48

llvm/test/MC/AVR/inst-brbs.s

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,22 +3,22 @@
33
; RUN: | llvm-objdump -d - | FileCheck --check-prefix=INST %s
44

55
foo:
6-
76
brbs 3, .+8
87
brbs 0, .-12
98
.short 0xf359
109
.short 0xf352
1110
.short 0xf34c
1211
.short 0xf077
1312

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

19-
; INST: 23 f0 brvs .+8
20-
; INST: d0 f3 brlo .-12
21-
; INST: 59 f3 breq .-42
22-
; INST: 52 f3 brmi .-44
23-
; INST: 4c f3 brlt .-46
24-
; INST: 77 f0 brie .+28
18+
; INST-LABEL: <foo>:
19+
; INST-NEXT: 23 f0 brvs .+8
20+
; INST-NEXT: d0 f3 brlo .-12
21+
; INST-NEXT: 59 f3 breq .-42
22+
; INST-NEXT: 52 f3 brmi .-44
23+
; INST-NEXT: 4c f3 brlt .-46
24+
; INST-NEXT: 77 f0 brie .+28

llvm/test/MC/AVR/inst-brcc.s

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
; RUN: llvm-mc -triple avr -show-encoding < %s | FileCheck %s
2+
;
3+
; RUN: llvm-mc -filetype=obj -triple avr < %s \
4+
; RUN: | llvm-objdump -d - \
5+
; RUN: | FileCheck --check-prefix=INST %s
6+
7+
foo:
8+
brcc .+66
9+
brcc .-22
10+
brbc 0, .+66
11+
brbc 0, bar
12+
13+
bar:
14+
15+
; CHECK: brcc (.Ltmp0+66)+2 ; encoding: [0bAAAAA000,0b111101AA]
16+
; CHECK-NEXT: ; fixup A - offset: 0, value: (.Ltmp0+66)+2, kind: fixup_7_pcrel
17+
; CHECK: brcc (.Ltmp1-22)+2 ; encoding: [0bAAAAA000,0b111101AA]
18+
; CHECK-NEXT: ; fixup A - offset: 0, value: (.Ltmp1-22)+2, kind: fixup_7_pcrel
19+
; CHECK: brcc (.Ltmp2+66)+2 ; encoding: [0bAAAAA000,0b111101AA]
20+
; CHECK-NEXT: ; fixup A - offset: 0, value: (.Ltmp2+66)+2, kind: fixup_7_pcrel
21+
; CHECK: brcc bar ; encoding: [0bAAAAA000,0b111101AA]
22+
; CHECK-NEXT: ; fixup A - offset: 0, value: bar, kind: fixup_7_pcrel
23+
24+
; INST-LABEL: <foo>:
25+
; INST-NEXT: 08 f5 brsh .+66
26+
; INST-NEXT: a8 f7 brsh .-22
27+
; INST-NEXT: 08 f5 brsh .+66
28+
; INST-NEXT: 00 f4 brsh .+0

llvm/test/MC/AVR/inst-brcs.s

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
; RUN: llvm-mc -triple avr -show-encoding < %s | FileCheck %s
2+
;
3+
; RUN: llvm-mc -filetype=obj -triple avr < %s \
4+
; RUN: | llvm-objdump -d - \
5+
; RUN: | FileCheck --check-prefix=INST %s
6+
7+
foo:
8+
brcs .+8
9+
brcs .+4
10+
brbs 0, .+8
11+
brbs 0, bar
12+
13+
bar:
14+
15+
; CHECK: brcs (.Ltmp0+8)+2 ; encoding: [0bAAAAA000,0b111100AA]
16+
; CHECK-NEXT: ; fixup A - offset: 0, value: (.Ltmp0+8)+2, kind: fixup_7_pcrel
17+
; CHECK: brcs (.Ltmp1+4)+2 ; encoding: [0bAAAAA000,0b111100AA]
18+
; CHECK-NEXT: ; fixup A - offset: 0, value: (.Ltmp1+4)+2, kind: fixup_7_pcrel
19+
; CHECK: brcs (.Ltmp2+8)+2 ; encoding: [0bAAAAA000,0b111100AA]
20+
; CHECK-NEXT: ; fixup A - offset: 0, value: (.Ltmp2+8)+2, kind: fixup_7_pcrel
21+
; CHECK: brcs bar ; encoding: [0bAAAAA000,0b111100AA]
22+
; CHECK-NEXT: ; fixup A - offset: 0, value: bar, kind: fixup_7_pcrel
23+
24+
; INST-LABEL: <foo>:
25+
; INST-NEXT: 20 f0 brlo .+8
26+
; INST-NEXT: 10 f0 brlo .+4
27+
; INST-NEXT: 20 f0 brlo .+8
28+
; INST-NEXT: 00 f0 brlo .+0

llvm/test/MC/AVR/inst-breq.s

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
; RUN: llvm-mc -triple avr -show-encoding < %s | FileCheck %s
2+
;
3+
; RUN: llvm-mc -filetype=obj -triple avr < %s \
4+
; RUN: | llvm-objdump -d - \
5+
; RUN: | FileCheck --check-prefix=INST %s
6+
7+
foo:
8+
breq .-18
9+
breq .-12
10+
brbs 1, .-18
11+
brbs 1, bar
12+
13+
bar:
14+
15+
; CHECK: breq (.Ltmp0-18)+2 ; encoding: [0bAAAAA001,0b111100AA]
16+
; CHECK-NEXT: ; fixup A - offset: 0, value: (.Ltmp0-18)+2, kind: fixup_7_pcrel
17+
; CHECK: breq (.Ltmp1-12)+2 ; encoding: [0bAAAAA001,0b111100AA]
18+
; CHECK-NEXT: ; fixup A - offset: 0, value: (.Ltmp1-12)+2, kind: fixup_7_pcrel
19+
; CHECK: brbs 1, (.Ltmp2-18)+2 ; encoding: [0bAAAAA001,0b111100AA]
20+
; CHECK-NEXT: ; fixup A - offset: 0, value: (.Ltmp2-18)+2, kind: fixup_7_pcrel
21+
; CHECK: brbs 1, bar ; encoding: [0bAAAAA001,0b111100AA]
22+
; CHECK-NEXT: ; fixup A - offset: 0, value: bar, kind: fixup_7_pcrel
23+
24+
; INST-LABEL: <foo>:
25+
; INST-NEXT: b9 f3 breq .-18
26+
; INST-NEXT: d1 f3 breq .-12
27+
; INST-NEXT: b9 f3 breq .-18
28+
; INST-NEXT: 01 f0 breq .+0

llvm/test/MC/AVR/inst-brge.s

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
; RUN: llvm-mc -triple avr -show-encoding < %s | FileCheck %s
2+
;
3+
; RUN: llvm-mc -filetype=obj -triple avr < %s \
4+
; RUN: | llvm-objdump -d - \
5+
; RUN: | FileCheck --check-prefix=INST %s
6+
7+
foo:
8+
brge .+50
9+
brge .+42
10+
brge bar
11+
12+
bar:
13+
14+
; CHECK: brge (.Ltmp0+50)+2 ; encoding: [0bAAAAA100,0b111101AA]
15+
; CHECK-NEXT: ; fixup A - offset: 0, value: (.Ltmp0+50)+2, kind: fixup_7_pcrel
16+
; CHECK: brge (.Ltmp1+42)+2 ; encoding: [0bAAAAA100,0b111101AA]
17+
; CHECK-NEXT: ; fixup A - offset: 0, value: (.Ltmp1+42)+2, kind: fixup_7_pcrel
18+
; CHECK: brge bar ; encoding: [0bAAAAA100,0b111101AA]
19+
; CHECK-NEXT: ; fixup A - offset: 0, value: bar, kind: fixup_7_pcrel
20+
21+
; INST-LABEL: <foo>:
22+
; INST-NEXT: cc f4 brge .+50
23+
; INST-NEXT: ac f4 brge .+42
24+
; INST-NEXT: 04 f4 brge .+0

llvm/test/MC/AVR/inst-brhc.s

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
; RUN: llvm-mc -triple avr -show-encoding < %s | FileCheck %s
2+
;
3+
; RUN: llvm-mc -filetype=obj -triple avr < %s \
4+
; RUN: | llvm-objdump -d - \
5+
; RUN: | FileCheck --check-prefix=INST %s
6+
7+
foo:
8+
brhc .+12
9+
brhc .+14
10+
brhc bar
11+
12+
bar:
13+
14+
; CHECK: brhc (.Ltmp0+12)+2 ; encoding: [0bAAAAA101,0b111101AA]
15+
; CHECK-NEXT: ; fixup A - offset: 0, value: (.Ltmp0+12)+2, kind: fixup_7_pcrel
16+
; CHECK: brhc (.Ltmp1+14)+2 ; encoding: [0bAAAAA101,0b111101AA]
17+
; CHECK-NEXT: ; fixup A - offset: 0, value: (.Ltmp1+14)+2, kind: fixup_7_pcrel
18+
; CHECK: brhc bar ; encoding: [0bAAAAA101,0b111101AA]
19+
; CHECK-NEXT: ; fixup A - offset: 0, value: bar, kind: fixup_7_pcrel
20+
21+
; INST-LABEL: <foo>:
22+
; INST-NEXT: 35 f4 brhc .+12
23+
; INST-NEXT: 3d f4 brhc .+14
24+
; INST-NEXT: 05 f4 brhc .+0

llvm/test/MC/AVR/inst-brhs.s

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
; RUN: llvm-mc -triple avr -show-encoding < %s | FileCheck %s
2+
;
3+
; RUN: llvm-mc -filetype=obj -triple avr < %s \
4+
; RUN: | llvm-objdump -d - \
5+
; RUN: | FileCheck --check-prefix=INST %s
6+
7+
foo:
8+
brhs .-66
9+
brhs .+14
10+
brhs bar
11+
12+
bar:
13+
14+
; CHECK: brhs (.Ltmp0-66)+2 ; encoding: [0bAAAAA101,0b111100AA]
15+
; CHECK-NEXT: ; fixup A - offset: 0, value: (.Ltmp0-66)+2, kind: fixup_7_pcrel
16+
; CHECK: brhs (.Ltmp1+14)+2 ; encoding: [0bAAAAA101,0b111100AA]
17+
; CHECK-NEXT: ; fixup A - offset: 0, value: (.Ltmp1+14)+2, kind: fixup_7_pcrel
18+
; CHECK: brhs bar ; encoding: [0bAAAAA101,0b111100AA]
19+
; CHECK-NEXT: ; fixup A - offset: 0, value: bar, kind: fixup_7_pcrel
20+
21+
; INST-LABEL: <foo>:
22+
; INST-NEXT: fd f2 brhs .-66
23+
; INST-NEXT: 3d f0 brhs .+14
24+
; INST-NEXT: 05 f0 brhs .+0

llvm/test/MC/AVR/inst-brid.s

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
; RUN: llvm-mc -triple avr -show-encoding < %s | FileCheck %s
2+
;
3+
; RUN: llvm-mc -filetype=obj -triple avr < %s \
4+
; RUN: | llvm-objdump -d - \
5+
; RUN: | FileCheck --check-prefix=INST %s
6+
7+
foo:
8+
brid .+42
9+
brid .+62
10+
brid bar
11+
12+
bar:
13+
14+
; CHECK: brid (.Ltmp0+42)+2 ; encoding: [0bAAAAA111,0b111101AA]
15+
; CHECK-NEXT: ; fixup A - offset: 0, value: (.Ltmp0+42)+2, kind: fixup_7_pcrel
16+
; CHECK: brid (.Ltmp1+62)+2 ; encoding: [0bAAAAA111,0b111101AA]
17+
; CHECK-NEXT: ; fixup A - offset: 0, value: (.Ltmp1+62)+2, kind: fixup_7_pcrel
18+
; CHECK: brid bar ; encoding: [0bAAAAA111,0b111101AA]
19+
; CHECK-NEXT: ; fixup A - offset: 0, value: bar, kind: fixup_7_pcrel
20+
21+
; INST-LABEL: <foo>:
22+
; INST-NEXT: af f4 brid .+42
23+
; INST-NEXT: ff f4 brid .+62
24+
; INST-NEXT: 07 f4 brid .+0

llvm/test/MC/AVR/inst-brie.s

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
; RUN: llvm-mc -triple avr -show-encoding < %s | FileCheck %s
2+
;
3+
; RUN: llvm-mc -filetype=obj -triple avr < %s \
4+
; RUN: | llvm-objdump -d - \
5+
; RUN: | FileCheck --check-prefix=INST %s
6+
7+
foo:
8+
brie .+20
9+
brie .+40
10+
brie bar
11+
12+
bar:
13+
14+
; CHECK: brie (.Ltmp0+20)+2 ; encoding: [0bAAAAA111,0b111100AA]
15+
; CHECK-NEXT: ; fixup A - offset: 0, value: (.Ltmp0+20)+2, kind: fixup_7_pcrel
16+
; CHECK: brie (.Ltmp1+40)+2 ; encoding: [0bAAAAA111,0b111100AA]
17+
; CHECK-NEXT: ; fixup A - offset: 0, value: (.Ltmp1+40)+2, kind: fixup_7_pcrel
18+
; CHECK: brie bar ; encoding: [0bAAAAA111,0b111100AA]
19+
; CHECK-NEXT: ; fixup A - offset: 0, value: bar, kind: fixup_7_pcrel
20+
21+
; INST-LABEL: <foo>:
22+
; INST-NEXT: 57 f0 brie .+20
23+
; INST-NEXT: a7 f0 brie .+40
24+
; INST-NEXT: 07 f0 brie .+0

0 commit comments

Comments
 (0)