{
// This must be a SIMD type that's fully enregistered, but is passed as an HFA.
// Each field will be inserted into the same destination register.
- assert(varTypeIsSIMD(varDsc) &&
- !compiler->isOpaqueSIMDType(varDsc->lvVerTypeInfo.GetClassHandle()));
+ assert(varTypeIsSIMD(varDsc) && !compiler->isOpaqueSIMDType(varDsc->GetStructHnd()));
assert(regArgTab[argNum].slot <= (int)varDsc->lvHfaSlots());
assert(argNum > 0);
assert(regArgTab[argNum - 1].varNum == varNum);
unsigned lvSlotNum; // original slot # (if remapped)
- typeInfo lvVerTypeInfo; // type info needed for verification
-
// class handle for the local or null if not known or not a class,
// for a struct handle use `GetStructHnd()`.
CORINFO_CLASS_HANDLE lvClassHnd;
// If the local is a TYP_STRUCT, get/set a class handle describing it
CORINFO_CLASS_HANDLE lvaGetStruct(unsigned varNum);
- void lvaSetStruct(unsigned varNum, CORINFO_CLASS_HANDLE typeHnd, bool unsafeValueClsCheck, bool setTypeInfo = true);
+ void lvaSetStruct(unsigned varNum, CORINFO_CLASS_HANDLE typeHnd, bool unsafeValueClsCheck);
void lvaSetStructUsedAsVarArg(unsigned varNum);
// If the local is TYP_REF, set or update the associated class information.
void impPushVar(GenTree* op, typeInfo tiRetVal);
GenTreeLclVar* impCreateLocalNode(unsigned lclNum DEBUGARG(IL_OFFSET offset));
- void impLoadVar(unsigned lclNum, IL_OFFSET offset, const typeInfo& tiRetVal);
- void impLoadVar(unsigned lclNum, IL_OFFSET offset)
- {
- impLoadVar(lclNum, offset, lvaGetDesc(lclNum)->lvVerTypeInfo);
- }
+ void impLoadVar(unsigned lclNum, IL_OFFSET offset);
void impLoadArg(unsigned ilArgNum, IL_OFFSET offset);
void impLoadLoc(unsigned ilLclNum, IL_OFFSET offset);
bool impReturnInstruction(int prefixFlags, OPCODE& opcode);
void verConvertBBToThrowVerificationException(BasicBlock* block DEBUGARG(bool logMsg));
void verHandleVerificationFailure(BasicBlock* block DEBUGARG(bool logMsg));
+ typeInfo verMakeTypeInfoForLocal(unsigned lclNum);
typeInfo verMakeTypeInfo(CORINFO_CLASS_HANDLE clsHnd,
bool bashStructToRef = false); // converts from jit type representation to typeInfo
typeInfo verMakeTypeInfo(CorInfoType ciType,
const BYTE* codeBegp = codeAddr;
const BYTE* codeEndp = codeAddr + codeSize;
unsigned varNum;
- var_types varType = DUMMY_INIT(TYP_UNDEF); // TYP_ type
- typeInfo ti; // Verifier type.
+ var_types varType = DUMMY_INIT(TYP_UNDEF); // TYP_ type
bool typeIsNormed = false;
FgStack pushedStack;
const bool isForceInline = (info.compFlags & CORINFO_FLG_FORCEINLINE) != 0;
if (opcode == CEE_LDLOCA || opcode == CEE_LDLOCA_S)
{
varType = impInlineInfo->lclVarInfo[varNum + impInlineInfo->argCnt].lclTypeInfo;
- ti = impInlineInfo->lclVarInfo[varNum + impInlineInfo->argCnt].lclVerTypeInfo;
impInlineInfo->lclVarInfo[varNum + impInlineInfo->argCnt].lclHasLdlocaOp = true;
}
noway_assert(opcode == CEE_LDARGA || opcode == CEE_LDARGA_S);
varType = impInlineInfo->lclVarInfo[varNum].lclTypeInfo;
- ti = impInlineInfo->lclVarInfo[varNum].lclVerTypeInfo;
impInlineInfo->inlArgInfo[varNum].argHasLdargaOp = true;
}
varType = (var_types)lvaTable[varNum].lvType;
- ti = lvaTable[varNum].lvVerTypeInfo;
// Determine if the next instruction will consume
// the address. If so we won't mark this var as
}
} // isInlining
- typeIsNormed = ti.IsValueClass() && !varTypeIsStruct(varType);
+ typeIsNormed = !varTypeIsGC(varType) && !varTypeIsStruct(varType);
}
break;
arg0varDsc->SetDoNotEnregReason(thisVarDsc->GetDoNotEnregReason());
#endif
arg0varDsc->lvHasILStoreOp = thisVarDsc->lvHasILStoreOp;
- arg0varDsc->lvVerTypeInfo = thisVarDsc->lvVerTypeInfo;
- // Clear the TI_FLAG_THIS_PTR in the original 'this' pointer.
- noway_assert(arg0varDsc->lvVerTypeInfo.IsThisPtr());
- thisVarDsc->lvVerTypeInfo.ClearThisPtr();
- // Note that here we don't clear `m_doNotEnregReason` and it stays
- // `doNotEnreg` with `AddrExposed` reason.
+ // Note that here we don't clear `m_doNotEnregReason` and it stays `doNotEnreg` with `AddrExposed` reason.
thisVarDsc->CleanAddressExposed();
thisVarDsc->lvHasILStoreOp = false;
}
#ifdef DEBUG
shadowVarDsc->SetDoNotEnregReason(varDsc->GetDoNotEnregReason());
#endif
- shadowVarDsc->lvVerTypeInfo = varDsc->lvVerTypeInfo;
+
if (varTypeIsStruct(type))
{
// We don't need unsafe value cls check here since we are copying the params and this flag
#endif // DEBUG
}
-/******************************************************************************/
+typeInfo Compiler::verMakeTypeInfoForLocal(unsigned lclNum)
+{
+ LclVarDsc* varDsc = lvaGetDesc(lclNum);
+
+ if ((varDsc->TypeGet() == TYP_BLK) || (varDsc->TypeGet() == TYP_LCLBLK))
+ {
+ return typeInfo();
+ }
+ if (varDsc->TypeGet() == TYP_BYREF)
+ {
+ // Pretend all byrefs are pointing to bytes.
+ return typeInfo(TI_BYTE).MakeByRef();
+ }
+ if (varTypeIsStruct(varDsc))
+ {
+ return typeInfo(TI_STRUCT, varDsc->GetStructHnd());
+ }
+
+ return typeInfo(varDsc->TypeGet());
+}
+
typeInfo Compiler::verMakeTypeInfo(CorInfoType ciType, CORINFO_CLASS_HANDLE clsHnd)
{
assert(ciType < CORINFO_TYPE_COUNT);
assert(IsTargetAbi(CORINFO_NATIVEAOT_ABI));
if (call->OperGet() != GT_LCL_VAR) // can be already converted by impFixupCallStructReturn.
{
- unsigned calliSlot = lvaGrabTemp(true DEBUGARG("calli"));
- LclVarDsc* varDsc = lvaGetDesc(calliSlot);
- varDsc->lvVerTypeInfo = tiRetVal;
+ unsigned calliSlot = lvaGrabTemp(true DEBUGARG("calli"));
+ LclVarDsc* varDsc = lvaGetDesc(calliSlot);
+
impAssignTempGen(calliSlot, call, tiRetVal.GetClassHandle(), (unsigned)CHECK_SPILL_NONE);
// impAssignTempGen can change src arg list and return type for call that returns struct.
var_types type = genActualType(lvaTable[calliSlot].TypeGet());
// &aliasedVar doesnt need GTF_GLOB_REF, though alisasedVar does
assert((op1->gtFlags & GTF_GLOB_REF) == 0);
- tiRetVal = lvaTable[lclNum].lvVerTypeInfo;
-
+ tiRetVal = typeInfo(TI_BYTE).MakeByRef();
impPushOnStack(op1, tiRetVal);
break;
// Load a local/argument on the operand stack
// lclNum is an index into lvaTable *NOT* the arg/lcl index in the IL
-void Compiler::impLoadVar(unsigned lclNum, IL_OFFSET offset, const typeInfo& tiRetVal)
+void Compiler::impLoadVar(unsigned lclNum, IL_OFFSET offset)
{
- impPushVar(impCreateLocalNode(lclNum DEBUGARG(offset)), tiRetVal);
+ impPushVar(impCreateLocalNode(lclNum DEBUGARG(offset)), verMakeTypeInfoForLocal(lclNum));
}
// Load an argument on the operand stack
{
lvaSetStruct(tmpNum, inlineeLocal.lclVerTypeInfo.GetClassHandle(), true /* unsafe value cls check */);
}
- else
- {
- // This is a wrapped primitive. Make sure the verstate knows that
- lvaTable[tmpNum].lvVerTypeInfo = inlineeLocal.lclVerTypeInfo;
- }
}
#ifdef DEBUG
lvaSetStructUsedAsVarArg(tmpNum);
}
}
- else
- {
- // This is a wrapped primitive. Make sure the verstate knows that
- lvaTable[tmpNum].lvVerTypeInfo = lclInfo.lclVerTypeInfo;
- }
}
argInfo.argHasTmp = true;
lvaSetClass(varDscInfo->varNum, info.compClassHnd);
}
- varDsc->lvVerTypeInfo = typeInfo();
-
- // Mark the 'this' pointer for the method
- varDsc->lvVerTypeInfo.SetIsThisPtr();
-
varDsc->lvIsRegArg = 1;
noway_assert(varDscInfo->intRegArgNum == 0);
compFloatingPointUsed = true;
}
- if (typeHnd)
+ if (typeHnd != NO_CLASS_HANDLE)
{
- unsigned cFlags = info.compCompHnd->getClassAttribs(typeHnd);
-
- // We can get typeHnds for primitive types, these are value types which only contain
- // a primitive. We will need the typeHnd to distinguish them, so we store it here.
- if ((cFlags & CORINFO_FLG_VALUECLASS) && !varTypeIsStruct(type))
- {
- // printf("This is a struct that the JIT will treat as a primitive\n");
- varDsc->lvVerTypeInfo = verMakeTypeInfo(typeHnd);
- }
-
- varDsc->lvOverlappingFields = StructHasOverlappingFields(cFlags);
+ varDsc->lvOverlappingFields = StructHasOverlappingFields(info.compCompHnd->getClassAttribs(typeHnd));
}
#if FEATURE_IMPLICIT_BYREFS
}
if ((varTypeIsStruct(type)))
{
- lvaSetStruct(varNum, typeHnd, typeHnd != nullptr, true);
+ lvaSetStruct(varNum, typeHnd, typeHnd != NO_CLASS_HANDLE);
if (info.compIsVarArgs)
{
lvaSetStructUsedAsVarArg(varNum);
{
// Set size to zero so that lvaSetStruct will appropriately set the SIMD-relevant fields.
fieldVarDsc->lvExactSize = 0;
- compiler->lvaSetStruct(varNum, pFieldInfo->fldTypeHnd, false, true);
+ compiler->lvaSetStruct(varNum, pFieldInfo->fldTypeHnd, false);
// We will not recursively promote this, so mark it as 'lvRegStruct' (note that we wouldn't
// be promoting this if we didn't think it could be enregistered.
fieldVarDsc->lvRegStruct = true;
/*****************************************************************************
* Set the lvClass for a local variable of a struct type */
-void Compiler::lvaSetStruct(unsigned varNum, CORINFO_CLASS_HANDLE typeHnd, bool unsafeValueClsCheck, bool setTypeInfo)
+void Compiler::lvaSetStruct(unsigned varNum, CORINFO_CLASS_HANDLE typeHnd, bool unsafeValueClsCheck)
{
LclVarDsc* varDsc = lvaGetDesc(varNum);
- if (setTypeInfo)
- {
- varDsc->lvVerTypeInfo = typeInfo(TI_STRUCT, typeHnd);
- }
// Set the type and associated info if we haven't already set it.
if (varDsc->lvType == TYP_UNDEF)
{
printf(" ld-addr-op");
}
- if (varDsc->lvVerTypeInfo.IsThisPtr())
+ if (lvaIsOriginalThisArg(lclNum))
{
printf(" this");
}
FOREACH_HBV_BIT_SET(lclNum, fgOutgoingArgTemps)
{
LclVarDsc* varDsc = lvaGetDesc((unsigned)lclNum);
- if (typeInfo::AreEquivalent(varDsc->lvVerTypeInfo, typeInfo(TI_STRUCT, copyBlkClass)) &&
- !fgCurrentlyInUseArgTemps->testBit(lclNum))
+ if ((varDsc->GetStructHnd() == copyBlkClass) && !fgCurrentlyInUseArgTemps->testBit(lclNum))
{
tmp = (unsigned)lclNum;
found = true;