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:
Eugene Rozenfeld 2015-03-20 17:14:56 -07:00
Родитель fbfca74df0
Коммит 8d2b714511
2 изменённых файлов: 77 добавлений и 34 удалений

Просмотреть файл

@ -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.