@@ -286,21 +286,46 @@ StackMaps::parseOperand(MachineInstr::const_mop_iterator MOI,
286286
287287
288288 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 ;
294305 if (MOI->isReg ()) {
295306 Register R = MOI->getReg ();
296307 if (SpillOffsets.count (R) > 0 ) {
297- Offset = SpillOffsets[R];
308+ RHS = SpillOffsets[R];
298309 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+ }
304329 }
305330 }
306331 }
@@ -312,7 +337,7 @@ StackMaps::parseOperand(MachineInstr::const_mop_iterator MOI,
312337 Offset = TRI->getSubRegIdxOffset (SubRegIdx);
313338
314339 Locs.emplace_back (Location::Register, TRI->getSpillSize (*RC), DwarfRegNum,
315- Offset);
340+ Offset, ExtraReg );
316341 return ++MOI;
317342 }
318343
@@ -813,7 +838,7 @@ void StackMaps::emitCallsiteEntries(MCStreamer &OS) {
813838 OS.emitIntValue (0 , 1 ); // Reserved
814839 OS.emitInt16 (Loc.Size );
815840 OS.emitInt16 (Loc.Reg );
816- OS.emitInt16 (0 ); // Reserved
841+ OS.emitInt16 (Loc. ExtraReg ); // Reserved
817842 OS.emitInt32 (Loc.Offset );
818843 }
819844 LiveIdx++;
0 commit comments