@@ -286,21 +286,46 @@ StackMaps::parseOperand(MachineInstr::const_mop_iterator MOI,
286
286
287
287
288
288
signed Offset = 0 ;
289
- // Check if there are any mappings for this register in the spillmap. If so,
290
- // encode the additional location in the offset field of the stackmap record
291
- // (which is unused for register locations). Note that this assumes that
292
- // there can only be one additional location for each value, which may turn
293
- // out to be false.
289
+ int RHS = 0 ;
290
+ // Check for any additional mappings in the spillmap and add them to his
291
+ // location to be later encoded into stackmaps. A typical case where we need
292
+ // to record multiple sources is the following (annotated with SpillMap
293
+ // info):
294
+ //
295
+ // %rcx = load %rbp, -8 // SpillMap[rcx] = -8
296
+ // %rbx = %rcx // SpillMap[rbx] = rcx
297
+ // STACKMAP(%rbx) or STACKMAP(%rcx)
298
+ //
299
+ // First a value is loaded from the stack into %rcx and then immediately
300
+ // moved into %rbx. This means there are three sources for the same value,
301
+ // and during deoptimisation we need to make sure we write the value back to
302
+ // each one of them. Note, that the stackmap may track either of %rbx or
303
+ // %rcx, resulting in different ways below to retrieve the mappings.
304
+ int ExtraReg = 0 ;
294
305
if (MOI->isReg ()) {
295
306
Register R = MOI->getReg ();
296
307
if (SpillOffsets.count (R) > 0 ) {
297
- Offset = SpillOffsets[R];
308
+ RHS = SpillOffsets[R];
298
309
assert (SpillOffsets[R] != 0 );
299
- if (Offset > 0 ) {
300
- // If the additional location is another register encode its DWARF id.
301
- // Also temporarily add 1 since 0 is used to mean there is no
302
- // additional location.
303
- Offset = getDwarfRegNum (Offset, TRI) + 1 ;
310
+ if (RHS > 0 ) {
311
+ // The additional location is another register: encode its DWARF id.
312
+ // Also temporarily add 1 since 0 means there is no additional
313
+ // location.
314
+ ExtraReg = getDwarfRegNum (RHS, TRI) + 1 ;
315
+ // Check if the other register also has a mapping and add it.
316
+ if (SpillOffsets.count (RHS) > 0 ) {
317
+ Offset = SpillOffsets[RHS];
318
+ }
319
+ } else {
320
+ // The other location is an offset.
321
+ Offset = RHS;
322
+ // Find any additional mappings where the current register appears on
323
+ // the right hand side.
324
+ for (auto I = SpillOffsets.begin (); I != SpillOffsets.end (); I++) {
325
+ if (I->second == R) {
326
+ ExtraReg = getDwarfRegNum (I->first , TRI) + 1 ;
327
+ }
328
+ }
304
329
}
305
330
}
306
331
}
@@ -312,7 +337,7 @@ StackMaps::parseOperand(MachineInstr::const_mop_iterator MOI,
312
337
Offset = TRI->getSubRegIdxOffset (SubRegIdx);
313
338
314
339
Locs.emplace_back (Location::Register, TRI->getSpillSize (*RC), DwarfRegNum,
315
- Offset);
340
+ Offset, ExtraReg );
316
341
return ++MOI;
317
342
}
318
343
@@ -813,7 +838,7 @@ void StackMaps::emitCallsiteEntries(MCStreamer &OS) {
813
838
OS.emitIntValue (0 , 1 ); // Reserved
814
839
OS.emitInt16 (Loc.Size );
815
840
OS.emitInt16 (Loc.Reg );
816
- OS.emitInt16 (0 ); // Reserved
841
+ OS.emitInt16 (Loc. ExtraReg ); // Reserved
817
842
OS.emitInt32 (Loc.Offset );
818
843
}
819
844
LiveIdx++;
0 commit comments