@@ -31,60 +31,72 @@ 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;
34
+ static bool checkSignedWidth (unsigned Width, uint64_t Value,
35
+ std::string Description, const MCFixup &Fixup,
36
+ MCContext *Ctx) {
37
+ if (isIntN (Width, Value)) {
38
+ return true ;
39
+ }
39
40
41
+ if (Ctx) {
40
42
int64_t Min = minIntN (Width);
41
43
int64_t Max = maxIntN (Width);
42
44
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 );
45
+ Ctx-> reportError (Fixup. getLoc (), Twine ( " out of range " ) + Description +
46
+ " (expected an integer in the range " +
47
+ Twine (Min) + " to " + Twine (Max) +
48
+ " ) " );
47
49
}
50
+
51
+ return false ;
48
52
}
49
53
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;
54
+ static bool checkUnsignedWidth (unsigned Width, uint64_t Value,
55
+ std::string Description, const MCFixup &Fixup,
56
+ MCContext *Ctx) {
57
+ if (isUIntN (Width, Value)) {
58
+ return true ;
59
+ }
55
60
61
+ if (Ctx) {
56
62
int64_t Max = maxUIntN (Width);
57
63
58
- Diagnostic +=
59
- " (expected an integer in the range 0 to " + std::to_string (Max) + " ) " ;
60
-
61
- Ctx-> reportError (Fixup. getLoc (), Diagnostic );
64
+ Ctx-> reportError (Fixup. getLoc (),
65
+ Twine ( " out of range " ) + Description +
66
+ " (expected an integer in the range 0 to " +
67
+ Twine (Max) + " ) " );
62
68
}
69
+
70
+ return false ;
63
71
}
64
72
65
73
// / Adjusts the value of a branch target before fixup application.
66
74
static void adjustBranch (unsigned Size , const MCFixup &Fixup, uint64_t &Value,
67
75
MCContext *Ctx) {
68
76
// We have one extra bit of precision because the value is rightshifted by
69
77
// one.
70
- unsigned_width (Size + 1 , Value, std::string (" branch target" ), Fixup, Ctx);
78
+ checkUnsignedWidth (Size + 1 , Value, std::string (" branch target" ), Fixup, Ctx);
71
79
72
80
// Rightshifts the value by one.
73
81
AVR::fixups::adjustBranchTarget (Value);
74
82
}
75
83
76
84
// / 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) {
85
+ static bool adjustRelativeBranch (unsigned Size , const MCFixup &Fixup,
86
+ uint64_t &Value, MCContext *Ctx,
87
+ const MCSubtargetInfo *STI = nullptr ) {
79
88
// Jumps are relative to the current instruction.
80
89
Value -= 2 ;
81
90
82
91
// We have one extra bit of precision because the value is rightshifted by
83
92
// one.
84
93
Size += 1 ;
85
94
86
- if (!isIntN (Size , Value) &&
87
- Ctx->getSubtargetInfo ()->hasFeature (AVR::FeatureWrappingRjmp)) {
95
+ if (!STI) {
96
+ STI = Ctx->getSubtargetInfo ();
97
+ }
98
+
99
+ if (!isIntN (Size , Value) && STI->hasFeature (AVR::FeatureWrappingRjmp)) {
88
100
const int32_t FlashSize = 0x2000 ;
89
101
int32_t SignedValue = Value;
90
102
@@ -96,10 +108,15 @@ static void adjustRelativeBranch(unsigned Size, const MCFixup &Fixup,
96
108
}
97
109
}
98
110
99
- signed_width (Size , Value, std::string (" branch target" ), Fixup, Ctx);
111
+ if (!checkSignedWidth (Size , Value, std::string (" branch target" ), Fixup,
112
+ Ctx)) {
113
+ return false ;
114
+ }
100
115
101
116
// Rightshifts the value by one.
102
117
AVR::fixups::adjustBranchTarget (Value);
118
+
119
+ return true ;
103
120
}
104
121
105
122
// / 22-bit absolute fixup.
@@ -152,7 +169,7 @@ static void fixup_13_pcrel(unsigned Size, const MCFixup &Fixup, uint64_t &Value,
152
169
// / Resolves to:
153
170
// / 10q0 qq10 0000 1qqq
154
171
static void fixup_6 (const MCFixup &Fixup, uint64_t &Value, MCContext *Ctx) {
155
- unsigned_width (6 , Value, std::string (" immediate" ), Fixup, Ctx);
172
+ checkUnsignedWidth (6 , Value, std::string (" immediate" ), Fixup, Ctx);
156
173
157
174
Value = ((Value & 0x20 ) << 8 ) | ((Value & 0x18 ) << 7 ) | (Value & 0x07 );
158
175
}
@@ -164,7 +181,7 @@ static void fixup_6(const MCFixup &Fixup, uint64_t &Value, MCContext *Ctx) {
164
181
// / 0000 0000 kk00 kkkk
165
182
static void fixup_6_adiw (const MCFixup &Fixup, uint64_t &Value,
166
183
MCContext *Ctx) {
167
- unsigned_width (6 , Value, std::string (" immediate" ), Fixup, Ctx);
184
+ checkUnsignedWidth (6 , Value, std::string (" immediate" ), Fixup, Ctx);
168
185
169
186
Value = ((Value & 0x30 ) << 2 ) | (Value & 0x0f );
170
187
}
@@ -174,7 +191,7 @@ static void fixup_6_adiw(const MCFixup &Fixup, uint64_t &Value,
174
191
// / Resolves to:
175
192
// / 0000 0000 AAAA A000
176
193
static void fixup_port5 (const MCFixup &Fixup, uint64_t &Value, MCContext *Ctx) {
177
- unsigned_width (5 , Value, std::string (" port number" ), Fixup, Ctx);
194
+ checkUnsignedWidth (5 , Value, std::string (" port number" ), Fixup, Ctx);
178
195
179
196
Value &= 0x1f ;
180
197
@@ -186,7 +203,7 @@ static void fixup_port5(const MCFixup &Fixup, uint64_t &Value, MCContext *Ctx) {
186
203
// / Resolves to:
187
204
// / 1011 0AAd dddd AAAA
188
205
static void fixup_port6 (const MCFixup &Fixup, uint64_t &Value, MCContext *Ctx) {
189
- unsigned_width (6 , Value, std::string (" port number" ), Fixup, Ctx);
206
+ checkUnsignedWidth (6 , Value, std::string (" port number" ), Fixup, Ctx);
190
207
191
208
Value = ((Value & 0x30 ) << 5 ) | (Value & 0x0f );
192
209
}
@@ -197,7 +214,7 @@ static void fixup_port6(const MCFixup &Fixup, uint64_t &Value, MCContext *Ctx) {
197
214
// / 1010 ikkk dddd kkkk
198
215
static void fixup_lds_sts_16 (const MCFixup &Fixup, uint64_t &Value,
199
216
MCContext *Ctx) {
200
- unsigned_width (7 , Value, std::string (" immediate" ), Fixup, Ctx);
217
+ checkUnsignedWidth (7 , Value, std::string (" immediate" ), Fixup, Ctx);
201
218
Value = ((Value & 0x70 ) << 8 ) | (Value & 0x0f );
202
219
}
203
220
@@ -331,13 +348,15 @@ void AVRAsmBackend::adjustFixupValue(const MCFixup &Fixup,
331
348
adjust::ldi::ms8 (Size , Fixup, Value, Ctx);
332
349
break ;
333
350
case AVR::fixup_16:
334
- adjust::unsigned_width (16 , Value, std::string (" port number" ), Fixup, Ctx);
351
+ adjust::checkUnsignedWidth (16 , Value, std::string (" port number" ), Fixup,
352
+ Ctx);
335
353
336
354
Value &= 0xffff ;
337
355
break ;
338
356
case AVR::fixup_16_pm:
339
357
Value >>= 1 ; // Flash addresses are always shifted.
340
- adjust::unsigned_width (16 , Value, std::string (" port number" ), Fixup, Ctx);
358
+ adjust::checkUnsignedWidth (16 , Value, std::string (" port number" ), Fixup,
359
+ Ctx);
341
360
342
361
Value &= 0xffff ;
343
362
break ;
@@ -512,14 +531,25 @@ bool AVRAsmBackend::writeNopData(raw_ostream &OS, uint64_t Count,
512
531
bool AVRAsmBackend::shouldForceRelocation (const MCAssembler &Asm,
513
532
const MCFixup &Fixup,
514
533
const MCValue &Target,
534
+ const uint64_t Value,
515
535
const MCSubtargetInfo *STI) {
516
536
switch ((unsigned )Fixup.getKind ()) {
517
537
default :
518
538
return Fixup.getKind () >= FirstLiteralRelocationKind;
539
+
519
540
case AVR::fixup_7_pcrel:
520
- case AVR::fixup_13_pcrel:
521
- // Always resolve relocations for PC-relative branches
522
- return false ;
541
+ case AVR::fixup_13_pcrel: {
542
+ uint64_t ValueEx = Value;
543
+ uint64_t Size = AVRAsmBackend::getFixupKindInfo (Fixup.getKind ()).TargetSize ;
544
+
545
+ // If the jump is too large to encode it, fall back to a relocation.
546
+ //
547
+ // Note that trying to actually link that relocation *would* fail, but the
548
+ // hopes are that the module we're currently compiling won't be actually
549
+ // linked to the final binary.
550
+ return !adjust::adjustRelativeBranch (Size , Fixup, ValueEx, nullptr , STI);
551
+ }
552
+
523
553
case AVR::fixup_call:
524
554
return true ;
525
555
}
0 commit comments