зеркало из https://github.com/dotnet/llilc.git
Enable calls to methods that require type arg (instantiation information).
The type arg is passed after vararg cookie and before regular args. Modify ReaderBse::rdrCall to handle type args. Add placeholders for future handling of vararg cookie. Change the type of type arg to be nativeint. Change the SomeBool ? 1 : 0 pattern to (int)SomeBool. We compile 3 more methods in HelloWorld and 315 more methods in all tests. Closes #280.
This commit is contained in:
Родитель
fbfca74df0
Коммит
8d2b714511
|
@ -2760,8 +2760,8 @@ void ReaderBase::getMSILInstrStackDelta(ReaderBaseNS::OPCODE Opcode,
|
||||||
getCallSiteSignature(Handle, Token, &Sig, &HasThis);
|
getCallSiteSignature(Handle, Token, &Sig, &HasThis);
|
||||||
ReturnsVoid = (Sig.retType == CORINFO_TYPE_VOID);
|
ReturnsVoid = (Sig.retType == CORINFO_TYPE_VOID);
|
||||||
|
|
||||||
NumPop += (Sig.numArgs + (HasThis ? 1 : 0));
|
NumPop += (Sig.numArgs + (int)HasThis);
|
||||||
NumPush = (ReturnsVoid ? 0 : 1);
|
NumPush = (int)!ReturnsVoid;
|
||||||
} else {
|
} else {
|
||||||
// "bad token" error will show up later, global verify
|
// "bad token" error will show up later, global verify
|
||||||
// should not complain.
|
// should not complain.
|
||||||
|
@ -2773,7 +2773,7 @@ void ReaderBase::getMSILInstrStackDelta(ReaderBaseNS::OPCODE Opcode,
|
||||||
CORINFO_SIG_INFO Sig;
|
CORINFO_SIG_INFO Sig;
|
||||||
|
|
||||||
JitInfo->getMethodSig(getCurrentMethodHandle(), &Sig);
|
JitInfo->getMethodSig(getCurrentMethodHandle(), &Sig);
|
||||||
NumPop = ((Sig.retType == CORINFO_TYPE_VOID) ? 0 : 1);
|
NumPop = (int)(Sig.retType != CORINFO_TYPE_VOID);
|
||||||
NumPush = 0;
|
NumPush = 0;
|
||||||
} break;
|
} break;
|
||||||
default:
|
default:
|
||||||
|
@ -3402,7 +3402,7 @@ void ReaderBase::fgAttachGlobalVerifyData(FlowGraphNode *HeadBlock) {
|
||||||
//
|
//
|
||||||
// Note that EH funclet has the exception object
|
// Note that EH funclet has the exception object
|
||||||
// already placed on the stack.
|
// already placed on the stack.
|
||||||
Current = isRegionStartBlock(Block) ? 1 : 0;
|
Current = (int)isRegionStartBlock(Block);
|
||||||
Min = Current;
|
Min = Current;
|
||||||
Max = Current;
|
Max = Current;
|
||||||
Start = fgNodeGetStartMSILOffset(Block);
|
Start = fgNodeGetStartMSILOffset(Block);
|
||||||
|
@ -4819,9 +4819,15 @@ ReaderBase::rdrCall(ReaderCallTargetData *Data, ReaderBaseNS::CallOpcode Opcode,
|
||||||
IRNode *ReturnNode;
|
IRNode *ReturnNode;
|
||||||
CallArgTriple *ArgArray;
|
CallArgTriple *ArgArray;
|
||||||
uint32_t NumArgs;
|
uint32_t NumArgs;
|
||||||
uint32_t FirstArgNum;
|
int FirstArgNum;
|
||||||
|
int TypeArgNum;
|
||||||
|
int VarArgNum;
|
||||||
bool HasThis;
|
bool HasThis;
|
||||||
|
bool IsVarArg;
|
||||||
|
bool HasTypeArg;
|
||||||
|
uint32_t TotalArgs;
|
||||||
int Index;
|
int Index;
|
||||||
|
CORINFO_CALL_INFO *CallInfo = Data->getCallInfo();
|
||||||
|
|
||||||
// Tail call is only permitted for call, calli and callvirt.
|
// Tail call is only permitted for call, calli and callvirt.
|
||||||
ASSERTNR(!Data->isTailCall() || (Opcode == ReaderBaseNS::Call) ||
|
ASSERTNR(!Data->isTailCall() || (Opcode == ReaderBaseNS::Call) ||
|
||||||
|
@ -4853,8 +4859,8 @@ ReaderBase::rdrCall(ReaderCallTargetData *Data, ReaderBaseNS::CallOpcode Opcode,
|
||||||
if (ReaderBaseNS::Calli == Opcode) {
|
if (ReaderBaseNS::Calli == Opcode) {
|
||||||
Data->CallTargetNode = ReaderOperandStack->pop();
|
Data->CallTargetNode = ReaderOperandStack->pop();
|
||||||
} else {
|
} else {
|
||||||
handleMemberAccess(Data->getCallInfo()->accessAllowed,
|
handleMemberAccess(CallInfo->accessAllowed,
|
||||||
Data->getCallInfo()->callsiteCalloutHelper);
|
CallInfo->callsiteCalloutHelper);
|
||||||
|
|
||||||
// If the current method calls a method which needs a security
|
// If the current method calls a method which needs a security
|
||||||
// check, we need to reserve a slot for the security object in
|
// check, we need to reserve a slot for the security object in
|
||||||
|
@ -4869,7 +4875,7 @@ ReaderBase::rdrCall(ReaderCallTargetData *Data, ReaderBaseNS::CallOpcode Opcode,
|
||||||
// if we're going to have to mess around with Args don't bother
|
// if we're going to have to mess around with Args don't bother
|
||||||
&&
|
&&
|
||||||
(!Data->hasThis() ||
|
(!Data->hasThis() ||
|
||||||
Data->getCallInfo()->thisTransform == CORINFO_NO_THIS_TRANSFORM)) {
|
CallInfo->thisTransform == CORINFO_NO_THIS_TRANSFORM)) {
|
||||||
// assert(!(mflags & CORINFO_FLG_VIRTUAL) ||
|
// assert(!(mflags & CORINFO_FLG_VIRTUAL) ||
|
||||||
// (mflags & CORINFO_FLG_FINAL) ||
|
// (mflags & CORINFO_FLG_FINAL) ||
|
||||||
// (clsFlags & CORINFO_FLG_FINAL));
|
// (clsFlags & CORINFO_FLG_FINAL));
|
||||||
|
@ -4887,8 +4893,8 @@ ReaderBase::rdrCall(ReaderCallTargetData *Data, ReaderBaseNS::CallOpcode Opcode,
|
||||||
IntrinsicArg1 = (IRNode *)ReaderOperandStack->pop();
|
IntrinsicArg1 = (IRNode *)ReaderOperandStack->pop();
|
||||||
IntrinsicArg2 = (IRNode *)ReaderOperandStack->pop();
|
IntrinsicArg2 = (IRNode *)ReaderOperandStack->pop();
|
||||||
|
|
||||||
IntrinsicRet = arrayGetDimLength(IntrinsicArg1, IntrinsicArg2,
|
IntrinsicRet =
|
||||||
Data->getCallInfo());
|
arrayGetDimLength(IntrinsicArg1, IntrinsicArg2, CallInfo);
|
||||||
if (IntrinsicRet) {
|
if (IntrinsicRet) {
|
||||||
return IntrinsicRet;
|
return IntrinsicRet;
|
||||||
}
|
}
|
||||||
|
@ -5079,7 +5085,6 @@ ReaderBase::rdrCall(ReaderCallTargetData *Data, ReaderBaseNS::CallOpcode Opcode,
|
||||||
|
|
||||||
CORINFO_CLASS_HANDLE Class = Data->getClassHandle();
|
CORINFO_CLASS_HANDLE Class = Data->getClassHandle();
|
||||||
CORINFO_METHOD_HANDLE Method = Data->getMethodHandle();
|
CORINFO_METHOD_HANDLE Method = Data->getMethodHandle();
|
||||||
CORINFO_CALL_INFO *CallInfo = Data->getCallInfo();
|
|
||||||
ASSERTNR(CallInfo);
|
ASSERTNR(CallInfo);
|
||||||
|
|
||||||
#ifdef FEATURE_CORECLR
|
#ifdef FEATURE_CORECLR
|
||||||
|
@ -5145,6 +5150,28 @@ ReaderBase::rdrCall(ReaderCallTargetData *Data, ReaderBaseNS::CallOpcode Opcode,
|
||||||
// Get the number of arguments to this method.
|
// Get the number of arguments to this method.
|
||||||
NumArgs = (uint32_t)SigInfo->numArgs;
|
NumArgs = (uint32_t)SigInfo->numArgs;
|
||||||
HasThis = Data->hasThis();
|
HasThis = Data->hasThis();
|
||||||
|
IsVarArg = SigInfo->isVarArg();
|
||||||
|
|
||||||
|
// Extra argument containing instantiation information is passed in the
|
||||||
|
// following circumstances:
|
||||||
|
// (a) To the AddressAt method on array classes; the extra parameter is the
|
||||||
|
// array's type handle (a TypeDesc)
|
||||||
|
// (b) To shared-code instance methods in generic structs; the extra parameter
|
||||||
|
// is the struct's type handle (a vtable ptr)
|
||||||
|
// (c) To shared-code per-instantiation non-generic static methods in generic
|
||||||
|
// classes and structs; the extra parameter is the type handle
|
||||||
|
// (d) To shared-code generic methods; the extra parameter is an
|
||||||
|
// exact-instantiation MethodDesc
|
||||||
|
//
|
||||||
|
// For shared instance target, we must add the instantiation parameter
|
||||||
|
// as an argument. It is ordered after the vararg cookie and before the
|
||||||
|
// regular arguments.
|
||||||
|
// However, if a helper call provides the function address, it always gives us
|
||||||
|
// an instantiating stub, so don't add an instantiation parameter.
|
||||||
|
HasTypeArg = SigInfo->hasTypeArg() &&
|
||||||
|
(CallInfo->kind != CORINFO_VIRTUALCALL_LDVIRTFTN);
|
||||||
|
TotalArgs = (uint32_t)HasThis + (uint32_t)IsVarArg + (uint32_t)HasTypeArg +
|
||||||
|
(uint32_t)NumArgs;
|
||||||
|
|
||||||
// Special case for newobj, currently the first
|
// Special case for newobj, currently the first
|
||||||
// argument is handled/appended in CanonNewObj.
|
// argument is handled/appended in CanonNewObj.
|
||||||
|
@ -5156,6 +5183,9 @@ ReaderBase::rdrCall(ReaderCallTargetData *Data, ReaderBaseNS::CallOpcode Opcode,
|
||||||
FirstArgNum = 1;
|
FirstArgNum = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VarArgNum = IsVarArg ? (int)HasThis : -1;
|
||||||
|
TypeArgNum = HasTypeArg ? (int)HasThis + (int)IsVarArg : -1;
|
||||||
|
|
||||||
// Create arg array and populate with stack arguments.
|
// Create arg array and populate with stack arguments.
|
||||||
// - struct return pointer does not live on arg array,
|
// - struct return pointer does not live on arg array,
|
||||||
// it is passed to GenIR as destination.
|
// it is passed to GenIR as destination.
|
||||||
|
@ -5169,15 +5199,14 @@ ReaderBase::rdrCall(ReaderCallTargetData *Data, ReaderBaseNS::CallOpcode Opcode,
|
||||||
// First populate ArgType, argClass fields.
|
// First populate ArgType, argClass fields.
|
||||||
ArgArray = nullptr;
|
ArgArray = nullptr;
|
||||||
|
|
||||||
if ((HasThis + NumArgs) > 0) {
|
if (TotalArgs > 0) {
|
||||||
CORINFO_ARG_LIST_HANDLE Args;
|
CORINFO_ARG_LIST_HANDLE Args;
|
||||||
CorInfoType CorType;
|
CorInfoType CorType;
|
||||||
CORINFO_CLASS_HANDLE ArgType, Class;
|
CORINFO_CLASS_HANDLE ArgType, Class;
|
||||||
|
|
||||||
ArgArray =
|
ArgArray = (CallArgTriple *)_alloca(sizeof(CallArgTriple) * TotalArgs);
|
||||||
(CallArgTriple *)_alloca(sizeof(CallArgTriple) * (NumArgs + HasThis));
|
|
||||||
#if !defined(NODEBUG)
|
#if !defined(NODEBUG)
|
||||||
memset(ArgArray, 0, sizeof(CallArgTriple) * (NumArgs + HasThis));
|
memset(ArgArray, 0, sizeof(CallArgTriple) * TotalArgs);
|
||||||
#endif
|
#endif
|
||||||
Args = SigInfo->args;
|
Args = SigInfo->args;
|
||||||
Index = 0;
|
Index = 0;
|
||||||
|
@ -5194,8 +5223,20 @@ ReaderBase::rdrCall(ReaderCallTargetData *Data, ReaderBaseNS::CallOpcode Opcode,
|
||||||
Index++;
|
Index++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (IsVarArg) {
|
||||||
|
// TODO: we'll need to handle varargs here.
|
||||||
|
Index++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If this call has a type arg, then it's right before fixed params.
|
||||||
|
if (HasTypeArg) {
|
||||||
|
ArgArray[Index].ArgType = CORINFO_TYPE_NATIVEINT;
|
||||||
|
ArgArray[Index].ArgClass = 0;
|
||||||
|
Index++;
|
||||||
|
}
|
||||||
|
|
||||||
// Populate remaining argument list
|
// Populate remaining argument list
|
||||||
for (; Index < (int)(NumArgs + HasThis); Index++) {
|
for (; Index < (int)TotalArgs; Index++) {
|
||||||
CorType = strip(JitInfo->getArgType(SigInfo, Args, &ArgType));
|
CorType = strip(JitInfo->getArgType(SigInfo, Args, &ArgType));
|
||||||
ASSERTNR(CorType != CORINFO_TYPE_VAR); // common generics trouble
|
ASSERTNR(CorType != CORINFO_TYPE_VAR); // common generics trouble
|
||||||
|
|
||||||
|
@ -5230,8 +5271,18 @@ ReaderBase::rdrCall(ReaderCallTargetData *Data, ReaderBaseNS::CallOpcode Opcode,
|
||||||
// Now pop args from argument stack (including this)
|
// Now pop args from argument stack (including this)
|
||||||
// - populating argument list in reverse order.
|
// - populating argument list in reverse order.
|
||||||
// For newobj the this pointer is not yet on the stack
|
// For newobj the this pointer is not yet on the stack
|
||||||
// so don't pop it!
|
// so don't pop it! Type arg and vararg cookie are not on the stack either.
|
||||||
for (Index = NumArgs + HasThis - 1; Index >= (int)FirstArgNum; Index--) {
|
for (Index = TotalArgs - 1; Index >= FirstArgNum; Index--) {
|
||||||
|
if (Index == VarArgNum) {
|
||||||
|
// TODO: we'll need to handle varargs here.
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (Index == TypeArgNum) {
|
||||||
|
ArgArray[Index].ArgNode = Data->getTypeContextNode();
|
||||||
|
ASSERTNR(ArgArray[Index].ArgNode != NULL);
|
||||||
|
ASSERTMNR(!Data->isCallI(), "CALLI on parameterized type");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
ArgArray[Index].ArgNode = (IRNode *)ReaderOperandStack->pop();
|
ArgArray[Index].ArgNode = (IRNode *)ReaderOperandStack->pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5267,7 +5318,7 @@ ReaderBase::rdrCall(ReaderCallTargetData *Data, ReaderBaseNS::CallOpcode Opcode,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ask GenIR to emit call, returns a ReturnNode.
|
// Ask GenIR to emit call, returns a ReturnNode.
|
||||||
ReturnNode = genCall(Data, ArgArray, NumArgs + HasThis, CallNode);
|
ReturnNode = genCall(Data, ArgArray, TotalArgs, CallNode);
|
||||||
return ReturnNode;
|
return ReturnNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5755,10 +5806,8 @@ void ReaderBase::buildUpParams(uint32_t NumParams) {
|
||||||
// comes instParam (typeArg cookie)
|
// comes instParam (typeArg cookie)
|
||||||
if (HasTypeArg) {
|
if (HasTypeArg) {
|
||||||
// this is not a real arg. we do not record it for verification
|
// this is not a real arg. we do not record it for verification
|
||||||
// maybe not the right type... it may not matter.
|
CORINFO_CLASS_HANDLE Class = 0;
|
||||||
CORINFO_CLASS_HANDLE Class =
|
createSym(ParamIndex, false, CORINFO_TYPE_NATIVEINT, Class, false,
|
||||||
getBuiltinClass(CorInfoClassId::CLASSID_TYPE_HANDLE);
|
|
||||||
createSym(ParamIndex, false, CORINFO_TYPE_PTR, Class, false,
|
|
||||||
ReaderSpecialSymbolType::Reader_InstParam);
|
ReaderSpecialSymbolType::Reader_InstParam);
|
||||||
ParamIndex++;
|
ParamIndex++;
|
||||||
}
|
}
|
||||||
|
@ -5767,8 +5816,8 @@ void ReaderBase::buildUpParams(uint32_t NumParams) {
|
||||||
for (; ParamIndex < NumParams; ParamIndex++) {
|
for (; ParamIndex < NumParams; ParamIndex++) {
|
||||||
|
|
||||||
if (VerificationNeeded) {
|
if (VerificationNeeded) {
|
||||||
verifyRecordParamType(ParamIndex - (IsVarArg ? 1 : 0) -
|
verifyRecordParamType(ParamIndex - (uint32_t)IsVarArg -
|
||||||
(HasTypeArg ? 1 : 0),
|
(uint32_t)HasTypeArg,
|
||||||
&(MethodInfo->args), Locs);
|
&(MethodInfo->args), Locs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1331,11 +1331,9 @@ FunctionType *GenIR::getFunctionType(CORINFO_SIG_INFO &Sig,
|
||||||
bool HasTypeArg = Sig.hasTypeArg();
|
bool HasTypeArg = Sig.hasTypeArg();
|
||||||
|
|
||||||
if (HasTypeArg) {
|
if (HasTypeArg) {
|
||||||
// maybe not the right type... for now just match what we pick in
|
CORINFO_CLASS_HANDLE Class = 0;
|
||||||
// ReaderBase::buildUpParams
|
Type *TypeArgType = getType(CORINFO_TYPE_NATIVEINT, Class);
|
||||||
CORINFO_CLASS_HANDLE Class =
|
|
||||||
getBuiltinClass(CorInfoClassId::CLASSID_TYPE_HANDLE);
|
|
||||||
Type *TypeArgType = getType(CORINFO_TYPE_PTR, Class);
|
|
||||||
Arguments.push_back(TypeArgType);
|
Arguments.push_back(TypeArgType);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3194,10 +3192,6 @@ IRNode *GenIR::genCall(ReaderCallTargetData *CallTargetInfo,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (SigInfo->hasTypeArg()) {
|
|
||||||
throw NotYetImplementedException("Call HasTypeArg");
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((CallInfo != nullptr) && (CallInfo->kind == CORINFO_VIRTUALCALL_STUB)) {
|
if ((CallInfo != nullptr) && (CallInfo->kind == CORINFO_VIRTUALCALL_STUB)) {
|
||||||
// VSD calls have a special calling convention that requires the pointer
|
// VSD calls have a special calling convention that requires the pointer
|
||||||
// to the stub in a target-specific register.
|
// to the stub in a target-specific register.
|
||||||
|
|
Загрузка…
Ссылка в новой задаче