Skip to content
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

[AVR] Fix parsing & emitting relative jumps #102936

Closed
wants to merge 2 commits into from
Closed
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
2 changes: 1 addition & 1 deletion llvm/test/MC/AVR/hex-immediates.s
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
; RUN: llvm-mc -filetype=obj -triple=avr %s -o %t
; RUN: llvm-objdump --no-print-imm-hex -d %t | FileCheck %s --check-prefix=DEC
; RUN: llvm-objdump -d --print-imm-hex %t | FileCheck %s --check-prefix=HEX
; RUN: llvm-objdump -dr --print-imm-hex %t | FileCheck %s --check-prefix=HEX

; DEC: ldi r24, 66
; HEX: ldi r24, 0x42
Expand Down
4 changes: 1 addition & 3 deletions llvm/test/MC/AVR/inst-adc.s
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
; RUN: llvm-mc -triple avr -show-encoding < %s | FileCheck %s
; RUN: llvm-mc -filetype=obj -triple avr < %s | llvm-objdump -d - | FileCheck --check-prefix=CHECK-INST %s

; RUN: llvm-mc -filetype=obj -triple avr < %s | llvm-objdump -dr - | FileCheck --check-prefix=CHECK-INST %s

foo:

adc r0, r15
adc r15, r0
adc r16, r31
Expand Down
4 changes: 1 addition & 3 deletions llvm/test/MC/AVR/inst-add.s
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
; RUN: llvm-mc -triple avr -show-encoding < %s | FileCheck %s
; RUN: llvm-mc -filetype=obj -triple avr < %s | llvm-objdump -d - | FileCheck --check-prefix=CHECK-INST %s

; RUN: llvm-mc -filetype=obj -triple avr < %s | llvm-objdump -dr - | FileCheck --check-prefix=CHECK-INST %s

foo:

add r0, r15
add r15, r0
add r16, r31
Expand Down
2 changes: 0 additions & 2 deletions llvm/test/MC/AVR/inst-adiw.s
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
; RUN: llvm-mc -triple avr -mattr=addsubiw -show-encoding < %s | FileCheck %s
; RUN: llvm-mc -filetype=obj -triple avr -mattr=addsubiw < %s | llvm-objdump --no-print-imm-hex -dr --mattr=addsubiw - | FileCheck --check-prefix=CHECK-INST %s


foo:

adiw r26, 12
adiw r26, 63

Expand Down
4 changes: 1 addition & 3 deletions llvm/test/MC/AVR/inst-and.s
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
; RUN: llvm-mc -triple avr -show-encoding < %s | FileCheck %s
; RUN: llvm-mc -filetype=obj -triple avr < %s | llvm-objdump -d - | FileCheck --check-prefix=CHECK-INST %s

; RUN: llvm-mc -filetype=obj -triple avr < %s | llvm-objdump -dr - | FileCheck --check-prefix=CHECK-INST %s

foo:

and r0, r15
and r15, r0
and r16, r31
Expand Down
4 changes: 1 addition & 3 deletions llvm/test/MC/AVR/inst-andi.s
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
; RUN: llvm-mc -triple avr -show-encoding < %s | FileCheck %s
; RUN: llvm-mc -filetype=obj -triple avr < %s | llvm-objdump --no-print-imm-hex -d - | FileCheck --check-prefix=CHECK-INST %s

; RUN: llvm-mc -filetype=obj -triple avr < %s | llvm-objdump --no-print-imm-hex -dr - | FileCheck --check-prefix=CHECK-INST %s

foo:

andi r16, 255
andi r29, 190
andi r22, 172
Expand Down
4 changes: 1 addition & 3 deletions llvm/test/MC/AVR/inst-asr.s
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
; RUN: llvm-mc -triple avr -show-encoding < %s | FileCheck %s
; RUN: llvm-mc -filetype=obj -triple avr < %s | llvm-objdump -d - | FileCheck -check-prefix=CHECK-INST %s

; RUN: llvm-mc -filetype=obj -triple avr < %s | llvm-objdump -dr - | FileCheck -check-prefix=CHECK-INST %s

foo:

asr r31
asr r25
asr r5
Expand Down
4 changes: 1 addition & 3 deletions llvm/test/MC/AVR/inst-bld.s
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
; RUN: llvm-mc -triple avr -show-encoding < %s | FileCheck %s
; RUN: llvm-mc -filetype=obj -triple avr < %s | llvm-objdump --no-print-imm-hex -d - | FileCheck --check-prefix=CHECK-INST %s

; RUN: llvm-mc -filetype=obj -triple avr < %s | llvm-objdump --no-print-imm-hex -dr - | FileCheck --check-prefix=CHECK-INST %s

foo:

bld r3, 5
bld r1, 1
bld r0, 0
Expand Down
25 changes: 13 additions & 12 deletions llvm/test/MC/AVR/inst-brbc.s
Original file line number Diff line number Diff line change
@@ -1,24 +1,25 @@
; RUN: llvm-mc -triple avr -show-encoding < %s | FileCheck %s
; RUN: llvm-mc -filetype=obj -triple avr < %s \
; RUN: | llvm-objdump -d - | FileCheck --check-prefix=INST %s
; RUN: | llvm-objdump -dr - | 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]
Copy link
Member

Choose a reason for hiding this comment

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

Though the generated binary is correct, which makes TinyGo fully work. The disassembly of llvm-objdump is not in accordance with avr-objdump. avr-objdump will output 1a: 23 f4 brvc .+8, without an extra +2.

So can we also fix llvm-objdump ? BTW, is it possible to fix this issue by modification in adjustRelativeBranch. (Sorry I have not enough time to investigate my suggestion)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I see, yes - we probably have to approach the problem differently, since treating . as +2 leaks into the objdump's output.

We've already got this commit merged, but I'll prepare a better fix in the coming days.

; 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
24 changes: 12 additions & 12 deletions llvm/test/MC/AVR/inst-brbs.s
Original file line number Diff line number Diff line change
@@ -1,24 +1,24 @@
; RUN: llvm-mc -triple avr -show-encoding < %s | FileCheck %s
; RUN: llvm-mc -filetype=obj -triple avr < %s \
; RUN: | llvm-objdump -d - | FileCheck --check-prefix=INST %s
; RUN: | llvm-objdump -dr - | 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 -dr - \
; 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 -dr - \
; 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
4 changes: 1 addition & 3 deletions llvm/test/MC/AVR/inst-break.s
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
; RUN: llvm-mc -triple avr -mattr=break -show-encoding < %s | FileCheck %s
; RUN: llvm-mc -filetype=obj -triple avr -mattr=break < %s | llvm-objdump -d --mattr=break - | FileCheck --check-prefix=CHECK-INST %s

; RUN: llvm-mc -filetype=obj -triple avr -mattr=break < %s | llvm-objdump -dr --mattr=break - | FileCheck --check-prefix=CHECK-INST %s

foo:

break

; CHECK: break ; encoding: [0x98,0x95]
Expand Down
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 -dr - \
; 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 -dr - \
; 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
Loading
Loading