@@ -261,7 +261,11 @@ uint64_t MCAssembler::computeFragmentSize(const MCFragment &F) const {
261
261
}
262
262
int64_t Size = NumValues * FF.getValueSize ();
263
263
if (Size < 0 ) {
264
- getContext ().reportError (FF.getLoc (), " invalid number of bytes" );
264
+ // The expression might use symbol values which have not yet converged.
265
+ // Allow the first few iterations to have temporary negative values. The
266
+ // limit is somewhat arbitrary but allows contrived interdependency.
267
+ if (RelaxSteps >= 2 )
268
+ getContext ().reportError (FF.getLoc (), " invalid number of bytes" );
265
269
return 0 ;
266
270
}
267
271
return Size;
@@ -428,28 +432,6 @@ void MCAssembler::layoutBundle(MCFragment *Prev, MCFragment *F) const {
428
432
DF->Offset = EF->Offset ;
429
433
}
430
434
431
- void MCAssembler::ensureValid (MCSection &Sec) const {
432
- if (Sec.hasLayout ())
433
- return ;
434
- Sec.setHasLayout (true );
435
- MCFragment *Prev = nullptr ;
436
- uint64_t Offset = 0 ;
437
- for (MCFragment &F : Sec) {
438
- F.Offset = Offset;
439
- if (isBundlingEnabled () && F.hasInstructions ()) {
440
- layoutBundle (Prev, &F);
441
- Offset = F.Offset ;
442
- }
443
- Offset += computeFragmentSize (F);
444
- Prev = &F;
445
- }
446
- }
447
-
448
- uint64_t MCAssembler::getFragmentOffset (const MCFragment &F) const {
449
- ensureValid (*F.getParent ());
450
- return F.Offset ;
451
- }
452
-
453
435
// Simple getSymbolOffset helper for the non-variable case.
454
436
static bool getLabelOffset (const MCAssembler &Asm, const MCSymbol &S,
455
437
bool ReportError, uint64_t &Val) {
@@ -929,22 +911,38 @@ void MCAssembler::layout() {
929
911
930
912
// Layout until everything fits.
931
913
this ->HasLayout = true ;
932
- while (layoutOnce ()) {
914
+ for (MCSection &Sec : *this ) {
915
+ MCFragment *Prev = nullptr ;
916
+ uint64_t Offset = 0 ;
917
+ for (MCFragment &F : Sec) {
918
+ F.Offset = Offset;
919
+ if (LLVM_UNLIKELY (isBundlingEnabled ())) {
920
+ if (F.hasInstructions ()) {
921
+ layoutBundle (Prev, &F);
922
+ Offset = F.Offset ;
923
+ }
924
+ Prev = &F;
925
+ }
926
+ Offset += computeFragmentSize (F);
927
+ }
928
+ }
929
+ while (relaxOnce ())
933
930
if (getContext ().hadError ())
934
931
return ;
935
- // Size of fragments in one section can depend on the size of fragments in
936
- // another. If any fragment has changed size, we have to re-layout (and
937
- // as a result possibly further relax) all.
938
- for (MCSection &Sec : *this )
939
- Sec.setHasLayout (false );
940
- }
941
932
942
933
DEBUG_WITH_TYPE (" mc-dump" , {
943
934
errs () << " assembler backend - post-relaxation\n --\n " ;
944
935
dump (); });
945
936
946
- // Finalize the layout, including fragment lowering.
947
- getBackend ().finishLayout (*this );
937
+ // Some targets might want to adjust fragment offsets. If so, perform another
938
+ // relaxation loop.
939
+ if (getBackend ().finishLayout (*this ))
940
+ while (relaxOnce ())
941
+ if (getContext ().hadError ())
942
+ return ;
943
+
944
+ // Trigger computeFragmentSize errors.
945
+ RelaxSteps = UINT_MAX;
948
946
949
947
DEBUG_WITH_TYPE (" mc-dump" , {
950
948
errs () << " assembler backend - final-layout\n --\n " ;
@@ -1073,11 +1071,11 @@ bool MCAssembler::fragmentNeedsRelaxation(const MCRelaxableFragment *F) const {
1073
1071
return false ;
1074
1072
}
1075
1073
1076
- bool MCAssembler::relaxInstruction (MCRelaxableFragment &F) {
1074
+ void MCAssembler::relaxInstruction (MCRelaxableFragment &F) {
1077
1075
assert (getEmitterPtr () &&
1078
1076
" Expected CodeEmitter defined for relaxInstruction" );
1079
1077
if (!fragmentNeedsRelaxation (&F))
1080
- return false ;
1078
+ return ;
1081
1079
1082
1080
++stats::RelaxedInstructions;
1083
1081
@@ -1095,10 +1093,9 @@ bool MCAssembler::relaxInstruction(MCRelaxableFragment &F) {
1095
1093
F.getContents ().clear ();
1096
1094
getEmitter ().encodeInstruction (Relaxed, F.getContents (), F.getFixups (),
1097
1095
*F.getSubtargetInfo ());
1098
- return true ;
1099
1096
}
1100
1097
1101
- bool MCAssembler::relaxLEB (MCLEBFragment &LF) {
1098
+ void MCAssembler::relaxLEB (MCLEBFragment &LF) {
1102
1099
const unsigned OldSize = static_cast <unsigned >(LF.getContents ().size ());
1103
1100
unsigned PadTo = OldSize;
1104
1101
int64_t Value;
@@ -1134,7 +1131,6 @@ bool MCAssembler::relaxLEB(MCLEBFragment &LF) {
1134
1131
encodeSLEB128 (Value, OSE, PadTo);
1135
1132
else
1136
1133
encodeULEB128 (Value, OSE, PadTo);
1137
- return OldSize != LF.getContents ().size ();
1138
1134
}
1139
1135
1140
1136
// / Check if the branch crosses the boundary.
@@ -1174,11 +1170,11 @@ static bool needPadding(uint64_t StartAddr, uint64_t Size,
1174
1170
isAgainstBoundary (StartAddr, Size, BoundaryAlignment);
1175
1171
}
1176
1172
1177
- bool MCAssembler::relaxBoundaryAlign (MCBoundaryAlignFragment &BF) {
1173
+ void MCAssembler::relaxBoundaryAlign (MCBoundaryAlignFragment &BF) {
1178
1174
// BoundaryAlignFragment that doesn't need to align any fragment should not be
1179
1175
// relaxed.
1180
1176
if (!BF.getLastFragment ())
1181
- return false ;
1177
+ return ;
1182
1178
1183
1179
uint64_t AlignedOffset = getFragmentOffset (BF);
1184
1180
uint64_t AlignedSize = 0 ;
@@ -1192,19 +1188,15 @@ bool MCAssembler::relaxBoundaryAlign(MCBoundaryAlignFragment &BF) {
1192
1188
uint64_t NewSize = needPadding (AlignedOffset, AlignedSize, BoundaryAlignment)
1193
1189
? offsetToAlignment (AlignedOffset, BoundaryAlignment)
1194
1190
: 0U ;
1195
- if (NewSize == BF.getSize ())
1196
- return false ;
1197
1191
BF.setSize (NewSize);
1198
- return true ;
1199
1192
}
1200
1193
1201
- bool MCAssembler::relaxDwarfLineAddr (MCDwarfLineAddrFragment &DF) {
1194
+ void MCAssembler::relaxDwarfLineAddr (MCDwarfLineAddrFragment &DF) {
1202
1195
bool WasRelaxed;
1203
1196
if (getBackend ().relaxDwarfLineAddr (*this , DF, WasRelaxed))
1204
- return WasRelaxed ;
1197
+ return ;
1205
1198
1206
1199
MCContext &Context = getContext ();
1207
- uint64_t OldSize = DF.getContents ().size ();
1208
1200
int64_t AddrDelta;
1209
1201
bool Abs = DF.getAddrDelta ().evaluateKnownAbsolute (AddrDelta, *this );
1210
1202
assert (Abs && " We created a line delta with an invalid expression" );
@@ -1217,13 +1209,12 @@ bool MCAssembler::relaxDwarfLineAddr(MCDwarfLineAddrFragment &DF) {
1217
1209
1218
1210
MCDwarfLineAddr::encode (Context, getDWARFLinetableParams (), LineDelta,
1219
1211
AddrDelta, Data);
1220
- return OldSize != Data.size ();
1221
1212
}
1222
1213
1223
- bool MCAssembler::relaxDwarfCallFrameFragment (MCDwarfCallFrameFragment &DF) {
1214
+ void MCAssembler::relaxDwarfCallFrameFragment (MCDwarfCallFrameFragment &DF) {
1224
1215
bool WasRelaxed;
1225
1216
if (getBackend ().relaxDwarfCFA (*this , DF, WasRelaxed))
1226
- return WasRelaxed ;
1217
+ return ;
1227
1218
1228
1219
MCContext &Context = getContext ();
1229
1220
int64_t Value;
@@ -1232,31 +1223,25 @@ bool MCAssembler::relaxDwarfCallFrameFragment(MCDwarfCallFrameFragment &DF) {
1232
1223
getContext ().reportError (DF.getAddrDelta ().getLoc (),
1233
1224
" invalid CFI advance_loc expression" );
1234
1225
DF.setAddrDelta (MCConstantExpr::create (0 , Context));
1235
- return false ;
1226
+ return ;
1236
1227
}
1237
1228
1238
1229
SmallVectorImpl<char > &Data = DF.getContents ();
1239
- uint64_t OldSize = Data.size ();
1240
1230
Data.clear ();
1241
1231
DF.getFixups ().clear ();
1242
1232
1243
1233
MCDwarfFrameEmitter::encodeAdvanceLoc (Context, Value, Data);
1244
- return OldSize != Data.size ();
1245
1234
}
1246
1235
1247
- bool MCAssembler::relaxCVInlineLineTable (MCCVInlineLineTableFragment &F) {
1248
- unsigned OldSize = F.getContents ().size ();
1236
+ void MCAssembler::relaxCVInlineLineTable (MCCVInlineLineTableFragment &F) {
1249
1237
getContext ().getCVContext ().encodeInlineLineTable (*this , F);
1250
- return OldSize != F.getContents ().size ();
1251
1238
}
1252
1239
1253
- bool MCAssembler::relaxCVDefRange (MCCVDefRangeFragment &F) {
1254
- unsigned OldSize = F.getContents ().size ();
1240
+ void MCAssembler::relaxCVDefRange (MCCVDefRangeFragment &F) {
1255
1241
getContext ().getCVContext ().encodeDefRange (*this , F);
1256
- return OldSize != F.getContents ().size ();
1257
1242
}
1258
1243
1259
- bool MCAssembler::relaxPseudoProbeAddr (MCPseudoProbeAddrFragment &PF) {
1244
+ void MCAssembler::relaxPseudoProbeAddr (MCPseudoProbeAddrFragment &PF) {
1260
1245
uint64_t OldSize = PF.getContents ().size ();
1261
1246
int64_t AddrDelta;
1262
1247
bool Abs = PF.getAddrDelta ().evaluateKnownAbsolute (AddrDelta, *this );
@@ -1269,13 +1254,12 @@ bool MCAssembler::relaxPseudoProbeAddr(MCPseudoProbeAddrFragment &PF) {
1269
1254
1270
1255
// AddrDelta is a signed integer
1271
1256
encodeSLEB128 (AddrDelta, OSE, OldSize);
1272
- return OldSize != Data.size ();
1273
1257
}
1274
1258
1275
- bool MCAssembler::relaxFragment (MCFragment &F) {
1259
+ void MCAssembler::relaxFragment (MCFragment &F) {
1276
1260
switch (F.getKind ()) {
1277
1261
default :
1278
- return false ;
1262
+ return ;
1279
1263
case MCFragment::FT_Relaxable:
1280
1264
assert (!getRelaxAll () &&
1281
1265
" Did not expect a MCRelaxableFragment in RelaxAll mode" );
@@ -1297,15 +1281,57 @@ bool MCAssembler::relaxFragment(MCFragment &F) {
1297
1281
}
1298
1282
}
1299
1283
1300
- bool MCAssembler::layoutOnce () {
1284
+ bool MCAssembler::relaxOnce () {
1301
1285
++stats::RelaxationSteps;
1286
+ ++RelaxSteps;
1302
1287
1303
- bool Changed = false ;
1304
- for (MCSection &Sec : *this )
1305
- for (MCFragment &Frag : Sec)
1306
- if (relaxFragment (Frag))
1307
- Changed = true ;
1308
- return Changed;
1288
+ // Size of fragments in one section can depend on the size of fragments in
1289
+ // another. If any fragment has changed size, we have to re-layout (and
1290
+ // as a result possibly further relax) all sections.
1291
+ bool ChangedAny = false , Changed;
1292
+ for (MCSection &Sec : *this ) {
1293
+ // Assume each iteration finalizes at least one extra fragment. If the
1294
+ // layout does not converge after N+1 iterations, bail out.
1295
+ auto MaxIter = Sec.curFragList ()->Tail ->getLayoutOrder () + 1 ;
1296
+ uint64_t OldSize = getSectionAddressSize (Sec);
1297
+ do {
1298
+ uint64_t Offset = 0 ;
1299
+ Changed = false ;
1300
+ if (LLVM_UNLIKELY (isBundlingEnabled ())) {
1301
+ MCFragment *Prev = nullptr ;
1302
+ for (MCFragment &F : Sec) {
1303
+ F.Offset = Offset;
1304
+ relaxFragment (F);
1305
+ if (F.hasInstructions ()) {
1306
+ layoutBundle (Prev, &F);
1307
+ Offset = F.Offset ;
1308
+ }
1309
+ Prev = &F;
1310
+ if (F.Offset != Offset) {
1311
+ F.Offset = Offset;
1312
+ Changed = true ;
1313
+ }
1314
+ Offset += computeFragmentSize (F);
1315
+ }
1316
+ } else {
1317
+ for (MCFragment &F : Sec) {
1318
+ if (F.Offset != Offset) {
1319
+ F.Offset = Offset;
1320
+ Changed = true ;
1321
+ }
1322
+ relaxFragment (F);
1323
+ Offset += computeFragmentSize (F);
1324
+ }
1325
+ }
1326
+
1327
+ Changed |= OldSize != Offset;
1328
+ ChangedAny |= Changed;
1329
+ OldSize = Offset;
1330
+ } while (Changed && --MaxIter);
1331
+ if (MaxIter == 0 )
1332
+ return false ;
1333
+ }
1334
+ return ChangedAny;
1309
1335
}
1310
1336
1311
1337
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
0 commit comments