@@ -31,60 +31,48 @@ namespace adjust {
31
31
32
32
using namespace llvm ;
33
33
34
- static void signed_width (unsigned Width, uint64_t Value,
35
- std::string Description, const MCFixup &Fixup,
36
- MCContext *Ctx) {
37
- if (!isIntN (Width, Value)) {
38
- std::string Diagnostic = " out of range " + Description;
39
-
40
- int64_t Min = minIntN (Width);
41
- int64_t Max = maxIntN (Width);
42
-
43
- Diagnostic += " (expected an integer in the range " + std::to_string (Min) +
44
- " to " + std::to_string (Max) + " )" ;
45
-
46
- Ctx->reportError (Fixup.getLoc (), Diagnostic);
34
+ static bool checkUnsignedWidth (unsigned Width, uint64_t Value,
35
+ Twine Description, const MCFixup &Fixup,
36
+ MCContext *Ctx) {
37
+ if (isUIntN (Width, Value)) {
38
+ return true ;
47
39
}
48
- }
49
-
50
- static void unsigned_width (unsigned Width, uint64_t Value,
51
- std::string Description, const MCFixup &Fixup,
52
- MCContext *Ctx) {
53
- if (!isUIntN (Width, Value)) {
54
- std::string Diagnostic = " out of range " + Description;
55
40
41
+ if (Ctx) {
56
42
int64_t Max = maxUIntN (Width);
57
43
58
- Diagnostic +=
59
- " (expected an integer in the range 0 to " + std::to_string (Max) + " ) " ;
60
-
61
- Ctx-> reportError (Fixup. getLoc (), Diagnostic );
44
+ Ctx-> reportError (Fixup. getLoc (),
45
+ Twine ( " out of range " ) + Description +
46
+ " (expected an integer in the range 0 to " +
47
+ Twine (Max) + " ) " );
62
48
}
49
+
50
+ return false ;
63
51
}
64
52
65
53
// / Adjusts the value of a branch target before fixup application.
66
54
static void adjustBranch (unsigned Size , const MCFixup &Fixup, uint64_t &Value,
67
55
MCContext *Ctx) {
68
56
// We have one extra bit of precision because the value is rightshifted by
69
57
// one.
70
- unsigned_width (Size + 1 , Value, std::string (" branch target" ), Fixup, Ctx);
58
+ checkUnsignedWidth (Size + 1 , Value, std::string (" branch target" ), Fixup, Ctx);
71
59
72
60
// Rightshifts the value by one.
73
61
AVR::fixups::adjustBranchTarget (Value);
74
62
}
75
63
76
64
// / Adjusts the value of a relative branch target before fixup application.
77
- static void adjustRelativeBranch (unsigned Size , const MCFixup &Fixup,
78
- uint64_t &Value, MCContext *Ctx) {
65
+ static bool adjustRelativeBranch (unsigned Size , const MCFixup &Fixup,
66
+ uint64_t &Value,
67
+ const MCSubtargetInfo *STI = nullptr ) {
79
68
// Jumps are relative to the current instruction.
80
69
Value -= 2 ;
81
70
82
71
// We have one extra bit of precision because the value is rightshifted by
83
72
// one.
84
73
Size += 1 ;
85
74
86
- if (!isIntN (Size , Value) &&
87
- Ctx->getSubtargetInfo ()->hasFeature (AVR::FeatureWrappingRjmp)) {
75
+ if (!isIntN (Size , Value) && STI->hasFeature (AVR::FeatureWrappingRjmp)) {
88
76
const int32_t FlashSize = 0x2000 ;
89
77
int32_t SignedValue = Value;
90
78
@@ -96,10 +84,14 @@ static void adjustRelativeBranch(unsigned Size, const MCFixup &Fixup,
96
84
}
97
85
}
98
86
99
- signed_width (Size , Value, std::string (" branch target" ), Fixup, Ctx);
87
+ if (!isIntN (Size , Value)) {
88
+ return false ;
89
+ }
100
90
101
91
// Rightshifts the value by one.
102
92
AVR::fixups::adjustBranchTarget (Value);
93
+
94
+ return true ;
103
95
}
104
96
105
97
// / 22-bit absolute fixup.
@@ -126,7 +118,9 @@ static void fixup_call(unsigned Size, const MCFixup &Fixup, uint64_t &Value,
126
118
// / Offset of 0 (so the result is left shifted by 3 bits before application).
127
119
static void fixup_7_pcrel (unsigned Size , const MCFixup &Fixup, uint64_t &Value,
128
120
MCContext *Ctx) {
129
- adjustRelativeBranch (Size , Fixup, Value, Ctx);
121
+ if (!adjustRelativeBranch (Size , Fixup, Value, Ctx->getSubtargetInfo ())) {
122
+ llvm_unreachable (" should've been emitted as a relocation" );
123
+ }
130
124
131
125
// Because the value may be negative, we must mask out the sign bits
132
126
Value &= 0x7f ;
@@ -140,7 +134,9 @@ static void fixup_7_pcrel(unsigned Size, const MCFixup &Fixup, uint64_t &Value,
140
134
// / Offset of 0 (so the result isn't left-shifted before application).
141
135
static void fixup_13_pcrel (unsigned Size , const MCFixup &Fixup, uint64_t &Value,
142
136
MCContext *Ctx) {
143
- adjustRelativeBranch (Size , Fixup, Value, Ctx);
137
+ if (!adjustRelativeBranch (Size , Fixup, Value, Ctx->getSubtargetInfo ())) {
138
+ llvm_unreachable (" should've been emitted as a relocation" );
139
+ }
144
140
145
141
// Because the value may be negative, we must mask out the sign bits
146
142
Value &= 0xfff ;
@@ -152,7 +148,7 @@ static void fixup_13_pcrel(unsigned Size, const MCFixup &Fixup, uint64_t &Value,
152
148
// / Resolves to:
153
149
// / 10q0 qq10 0000 1qqq
154
150
static void fixup_6 (const MCFixup &Fixup, uint64_t &Value, MCContext *Ctx) {
155
- unsigned_width (6 , Value, std::string (" immediate" ), Fixup, Ctx);
151
+ checkUnsignedWidth (6 , Value, std::string (" immediate" ), Fixup, Ctx);
156
152
157
153
Value = ((Value & 0x20 ) << 8 ) | ((Value & 0x18 ) << 7 ) | (Value & 0x07 );
158
154
}
@@ -164,7 +160,7 @@ static void fixup_6(const MCFixup &Fixup, uint64_t &Value, MCContext *Ctx) {
164
160
// / 0000 0000 kk00 kkkk
165
161
static void fixup_6_adiw (const MCFixup &Fixup, uint64_t &Value,
166
162
MCContext *Ctx) {
167
- unsigned_width (6 , Value, std::string (" immediate" ), Fixup, Ctx);
163
+ checkUnsignedWidth (6 , Value, std::string (" immediate" ), Fixup, Ctx);
168
164
169
165
Value = ((Value & 0x30 ) << 2 ) | (Value & 0x0f );
170
166
}
@@ -174,19 +170,19 @@ static void fixup_6_adiw(const MCFixup &Fixup, uint64_t &Value,
174
170
// / Resolves to:
175
171
// / 0000 0000 AAAA A000
176
172
static void fixup_port5 (const MCFixup &Fixup, uint64_t &Value, MCContext *Ctx) {
177
- unsigned_width (5 , Value, std::string (" port number" ), Fixup, Ctx);
173
+ checkUnsignedWidth (5 , Value, std::string (" port number" ), Fixup, Ctx);
178
174
179
175
Value &= 0x1f ;
180
176
181
177
Value <<= 3 ;
182
178
}
183
179
184
- // / 6-bit port number fixup on the `IN` family of instructions.
180
+ // / 6-bit port number fixup on the IN family of instructions.
185
181
// /
186
182
// / Resolves to:
187
183
// / 1011 0AAd dddd AAAA
188
184
static void fixup_port6 (const MCFixup &Fixup, uint64_t &Value, MCContext *Ctx) {
189
- unsigned_width (6 , Value, std::string (" port number" ), Fixup, Ctx);
185
+ checkUnsignedWidth (6 , Value, std::string (" port number" ), Fixup, Ctx);
190
186
191
187
Value = ((Value & 0x30 ) << 5 ) | (Value & 0x0f );
192
188
}
@@ -197,7 +193,7 @@ static void fixup_port6(const MCFixup &Fixup, uint64_t &Value, MCContext *Ctx) {
197
193
// / 1010 ikkk dddd kkkk
198
194
static void fixup_lds_sts_16 (const MCFixup &Fixup, uint64_t &Value,
199
195
MCContext *Ctx) {
200
- unsigned_width (7 , Value, std::string (" immediate" ), Fixup, Ctx);
196
+ checkUnsignedWidth (7 , Value, std::string (" immediate" ), Fixup, Ctx);
201
197
Value = ((Value & 0x70 ) << 8 ) | (Value & 0x0f );
202
198
}
203
199
@@ -331,13 +327,15 @@ void AVRAsmBackend::adjustFixupValue(const MCFixup &Fixup,
331
327
adjust::ldi::ms8 (Size , Fixup, Value, Ctx);
332
328
break ;
333
329
case AVR::fixup_16:
334
- adjust::unsigned_width (16 , Value, std::string (" port number" ), Fixup, Ctx);
330
+ adjust::checkUnsignedWidth (16 , Value, std::string (" port number" ), Fixup,
331
+ Ctx);
335
332
336
333
Value &= 0xffff ;
337
334
break ;
338
335
case AVR::fixup_16_pm:
339
336
Value >>= 1 ; // Flash addresses are always shifted.
340
- adjust::unsigned_width (16 , Value, std::string (" port number" ), Fixup, Ctx);
337
+ adjust::checkUnsignedWidth (16 , Value, std::string (" port number" ), Fixup,
338
+ Ctx);
341
339
342
340
Value &= 0xffff ;
343
341
break ;
@@ -512,14 +510,25 @@ bool AVRAsmBackend::writeNopData(raw_ostream &OS, uint64_t Count,
512
510
bool AVRAsmBackend::shouldForceRelocation (const MCAssembler &Asm,
513
511
const MCFixup &Fixup,
514
512
const MCValue &Target,
513
+ const uint64_t Value,
515
514
const MCSubtargetInfo *STI) {
516
515
switch ((unsigned )Fixup.getKind ()) {
517
516
default :
518
517
return Fixup.getKind () >= FirstLiteralRelocationKind;
518
+
519
519
case AVR::fixup_7_pcrel:
520
- case AVR::fixup_13_pcrel:
521
- // Always resolve relocations for PC-relative branches
522
- return false ;
520
+ case AVR::fixup_13_pcrel: {
521
+ uint64_t ValueEx = Value;
522
+ uint64_t Size = AVRAsmBackend::getFixupKindInfo (Fixup.getKind ()).TargetSize ;
523
+
524
+ // If the jump is too large to encode it, fall back to a relocation.
525
+ //
526
+ // Note that trying to actually link that relocation *would* fail, but the
527
+ // hopes are that the module we're currently compiling won't be actually
528
+ // linked to the final binary.
529
+ return !adjust::adjustRelativeBranch (Size , Fixup, ValueEx, STI);
530
+ }
531
+
523
532
case AVR::fixup_call:
524
533
return true ;
525
534
}
0 commit comments