Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.

Commit 4f8c7d1

Browse files
author
Lubomir Litchev
committed
Fixed the bug described in GH issue 1831.
When generating unboxing function, if the return value is nullables returned in 2 registers, creating the temp var to pass to the helper function is not enough. Also need to make sure the operand type stack is properly maintained.
1 parent af48d72 commit 4f8c7d1

File tree

1 file changed

+26
-4
lines changed

1 file changed

+26
-4
lines changed

src/jit/importer.cpp

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12572,8 +12572,10 @@ MATH_MAYBE_CALL_NO_OVF: ovfl = false;
1257212572
// Unbox nullable helper returns a TYP_STRUCT.
1257312573
// We need to spill it to a temp so than we can take the address of it.
1257412574
// We need the temp so we can pass its address to the unbox_nullable jit helper function.
12575-
// This is needed for 2 register returned nullables.
12576-
// The one register ones are normalized. For the bigger than 16 bytes ones there is retbuf already passed in rdi.
12575+
// This is needed for nullables returned in 2 registers.
12576+
// The ones returned in a single register are normalized.
12577+
// For the bigger than 16 bytes nullables there is retbuf already passed in
12578+
// rdi/rsi (depending whether there is a "this").
1257712579

1257812580
unsigned tmp = lvaGrabTemp(true DEBUGARG("UNBOXing a register returnable nullable"));
1257912581
lvaTable[tmp].lvDontPromote = true;
@@ -12585,14 +12587,34 @@ MATH_MAYBE_CALL_NO_OVF: ovfl = false;
1258512587

1258612588
op2 = gtNewLclvNode(tmp, TYP_STRUCT);
1258712589
op2 = gtNewOperNode(GT_ADDR, TYP_BYREF, op2);
12588-
op1 = gtNewOperNode(GT_COMMA, TYP_STRUCT, op1, op2);
12590+
op1 = gtNewOperNode(GT_COMMA, TYP_BYREF, op1, op2);
12591+
12592+
// In this case the return value of the unbox helper is TYP_BYREF.
12593+
// Make sure the right type is placed on the operand type stack.
12594+
impPushOnStack(op1, tiRetVal);
12595+
12596+
// Load the struct.
12597+
oper = GT_LDOBJ;
12598+
12599+
assert(op1->gtType == TYP_BYREF);
12600+
assert(!tiVerificationNeeded || tiRetVal.IsByRef());
12601+
12602+
goto LDOBJ;
12603+
}
12604+
else
12605+
{
12606+
// If non register passable struct we have it materialized in the RetBuf.
12607+
assert(op1->gtType == TYP_STRUCT);
12608+
tiRetVal = verMakeTypeInfo(resolvedToken.hClass);
12609+
assert(tiRetVal.IsValueClass());
1258912610
}
1259012611
}
12591-
#endif // defined(FEATURE_UNIX_AMD64_STRUCT_PASSING)
1259212612

12613+
#else // !defined(FEATURE_UNIX_AMD64_STRUCT_PASSING)
1259312614
assert(op1->gtType == TYP_STRUCT);
1259412615
tiRetVal = verMakeTypeInfo(resolvedToken.hClass);
1259512616
assert(tiRetVal.IsValueClass());
12617+
#endif // !defined(FEATURE_UNIX_AMD64_STRUCT_PASSING)
1259612618
}
1259712619

1259812620
impPushOnStack(op1, tiRetVal);

0 commit comments

Comments
 (0)