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

Commit

Permalink
GcInfo: Report Struct containing one GcPointer correctly
Browse files Browse the repository at this point in the history
This change fixes a bug in the the GcInfo header,
where the ReturnKind is reported incorrectly for certain structs.

Structs that contain only one GCPointer or ByRef, can be returned
in a single register (Windows/Unix/OSX). The ReturnKind for these
struct-returns should be RT_Object/RT_ByRef, but they are currently
incorrectly reported as RT_Scalar. This change fixes the problem.

Fixes: dotnet/corefx#11260
  • Loading branch information
Swaroop Sridhar committed Aug 31, 2016
1 parent ebab1e7 commit 2c8b716
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 11 deletions.
2 changes: 1 addition & 1 deletion src/jit/compiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -906,7 +906,7 @@ var_types Compiler::getArgTypeForStruct(CORINFO_CLASS_HANDLE clsHnd,
// that multiple registers are used to return this struct.
//
var_types Compiler::getReturnTypeForStruct(CORINFO_CLASS_HANDLE clsHnd,
structPassingKind* wbReturnStruct,
structPassingKind* wbReturnStruct /* = nullptr */,
unsigned structSize /* = 0 */)
{
var_types useType = TYP_UNKNOWN;
Expand Down
2 changes: 1 addition & 1 deletion src/jit/compiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -3839,7 +3839,7 @@ class Compiler
// If you have already retrieved the struct size then pass it as the optional third argument
//
var_types getReturnTypeForStruct(CORINFO_CLASS_HANDLE clsHnd,
structPassingKind* wbPassStruct,
structPassingKind* wbPassStruct = nullptr,
unsigned structSize = 0);

#ifdef DEBUG
Expand Down
40 changes: 31 additions & 9 deletions src/jit/gcencode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3541,6 +3541,7 @@ void GCInfo::gcInfoBlockHdrSave(GcInfoEncoder* gcInfoEncoder, unsigned methodSiz
switch (compiler->info.compRetType)
{
case TYP_REF:
case TYP_ARRAY:
returnKind = RT_Object;
break;
case TYP_BYREF:
Expand All @@ -3549,19 +3550,40 @@ void GCInfo::gcInfoBlockHdrSave(GcInfoEncoder* gcInfoEncoder, unsigned methodSiz
case TYP_STRUCT:
{
CORINFO_CLASS_HANDLE structType = compiler->info.compMethodInfo->args.retTypeClass;
if (compiler->IsMultiRegReturnedType(structType) && !compiler->IsHfa(structType))
var_types retType = compiler->getReturnTypeForStruct(structType);

switch (retType)
{
BYTE gcPtrs[2] = {TYPE_GC_NONE, TYPE_GC_NONE};
compiler->info.compCompHnd->getClassGClayout(structType, gcPtrs);
case TYP_REF:
case TYP_ARRAY:
returnKind = RT_Object;
break;

ReturnKind first = GCTypeToReturnKind((CorInfoGCType)gcPtrs[0]);
ReturnKind second = GCTypeToReturnKind((CorInfoGCType)gcPtrs[1]);
case TYP_BYREF:
returnKind = RT_ByRef;
break;

returnKind = GetStructReturnKind(first, second);
}
else
{
case TYP_STRUCT:
if (compiler->IsHfa(structType))
{
returnKind = RT_Scalar;
}
else
{
// Multi-reg return
BYTE gcPtrs[2] = { TYPE_GC_NONE, TYPE_GC_NONE };
compiler->info.compCompHnd->getClassGClayout(structType, gcPtrs);

ReturnKind first = GCTypeToReturnKind((CorInfoGCType)gcPtrs[0]);
ReturnKind second = GCTypeToReturnKind((CorInfoGCType)gcPtrs[1]);

returnKind = GetStructReturnKind(first, second);
}
break;

default:
returnKind = RT_Scalar;
break;
}
break;
}
Expand Down

0 comments on commit 2c8b716

Please sign in to comment.