Merge pull request #345 from pgavlin/callconv

Support VSD calls and methods with a secret parameter.
This commit is contained in:
Pat Gavlin 2015-03-24 10:58:15 -07:00
Родитель 77c7192d80 3d5454b868
Коммит 87ee4e6dce
4 изменённых файлов: 149 добавлений и 57 удалений

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

@ -281,6 +281,7 @@ enum ReaderSpecialSymbolType {
Reader_UnmodifiedThisPtr, ///< This pointer param passed to method
Reader_VarArgsToken, ///< Special param for varargs support
Reader_InstParam, ///< Special param for shared generics
Reader_SecretParam, ///< Special param for IL stubs
Reader_SecurityObject, ///< Local used for security checking
Reader_GenericsContext ///< Local holding shared generics context
};
@ -1212,26 +1213,34 @@ public:
/// direct client processing for the method parameters and the local
/// variables of the method.
///
/// \params NumParams Number of parameters to the method. Note this may
/// include implicit parameters like the this pointer.
/// \params NumAutos Number of locals described in the local signature.
void initParamsAndAutos(uint32_t NumParam, uint32_t NumAuto);
/// \param NumParams Number of parameters to the method. Note this
/// includes implicit parameters like the this
/// pointer.
/// \param NumAutos Number of locals described in the local
/// signature.
/// \param HasSecretParameter Indicates whether or not the terminal parameter
/// is the secret parameter of an IL stub.
void initParamsAndAutos(uint32_t NumParam, uint32_t NumAuto,
bool HasSecretParameter);
/// \brief Set up parameters
///
/// Uses the method signature and information from the EE to direct the
/// client to set up processing for method parameters.
///
/// \params NumParams Number of parameters to the method. Note this may
/// include implicit parameters like the this pointer.
void buildUpParams(uint32_t NumParams);
/// \param NumParams Number of parameters to the method. Note this
/// includes implicit parameters like the this
/// pointer.
/// \param HasSecretParameter Indicates whether or not the terminal parameter
/// is the secret parameter of an IL stub.
void buildUpParams(uint32_t NumParams, bool HasSecretParameter);
/// \brief Set up locals (autos)
///
/// Uses the local signature to direct the client to set up processing
/// for local variables in the method.
///
/// \params NumAutos Number of locals described in the signature.
/// \param NumAutos Number of locals described in the signature.
void buildUpAutos(uint32_t NumAutos);
/// \brief Process the next element (argument or local) in a signature
@ -1240,7 +1249,7 @@ public:
/// through a signature and obtain more detailed information about each
/// element.
///
/// \params ArgListHandle Handle for the current element of the signature
/// \param ArgListHandle Handle for the current element of the signature
/// \param Sig The signature being iterated over.
/// \param CorType [out] Optional; the CorInfoType of the current element.
/// \param Class [out] Optional; the class handle of the current element.
@ -2763,8 +2772,8 @@ public:
ReaderSpecialSymbolType Type = Reader_NotSpecialSymbol) = 0;
virtual IRNode *derefAddress(IRNode *Address, bool DestIsGCPtr, bool IsConst,
bool AddressMayBeNull = true) = 0;
IRNode *derefAddressNonNull(IRNode *Address, bool DestIsGCPtr, bool IsConst) {
return derefAddress(Address, DestIsGCPtr, IsConst, false);
}

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

@ -279,9 +279,7 @@ public:
IRNode *argList() override;
IRNode *instParam() override;
IRNode *secretParam() override {
throw NotYetImplementedException("secretParam");
};
IRNode *secretParam() override;
IRNode *thisObj() override;
void boolBranch(ReaderBaseNS::BoolBranchOpcode Opcode, IRNode *Arg1) override;
@ -805,8 +803,11 @@ public:
// newobj
bool canonNewObjCall(IRNode *CallNode, ReaderCallTargetData *CallTargetData,
IRNode **OutResult);
void canonNewArrayCall(IRNode *CallNode, ReaderCallTargetData *CallTargetData,
IRNode **OutResult);
IRNode *canonNewArrayCall(IRNode *CallNode,
ReaderCallTargetData *CallTargetData);
// stubs
IRNode *canonStubCall(IRNode *CallNode, ReaderCallTargetData *CallTargetData);
#endif
// Used to expand multidimensional array access intrinsics
@ -837,11 +838,14 @@ private:
llvm::Type *getType(CorInfoType Type, CORINFO_CLASS_HANDLE ClassHandle,
bool GetRefClassFields = true);
llvm::Function *getFunction(CORINFO_METHOD_HANDLE Method);
llvm::Function *getFunction(CORINFO_METHOD_HANDLE Method,
bool HasSecretParameter);
llvm::FunctionType *getFunctionType(CORINFO_METHOD_HANDLE Method);
llvm::FunctionType *getFunctionType(CORINFO_METHOD_HANDLE Method,
bool HasSecretParameter = false);
llvm::FunctionType *getFunctionType(CORINFO_SIG_INFO &Sig,
CORINFO_CLASS_HANDLE ThisClass);
CORINFO_CLASS_HANDLE ThisClass,
bool HasSecretParameter = false);
llvm::Type *getClassType(CORINFO_CLASS_HANDLE ClassHandle, bool IsRefClass,
bool GetRefClassFields);
@ -1101,6 +1105,7 @@ private:
bool HasThis;
bool HasTypeParameter;
bool HasVarargsToken;
bool HasSecretParameter;
bool KeepGenericContextAlive;
llvm::BasicBlock *EntryBlock;
llvm::Instruction *TempInsertionPoint;

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

@ -5609,7 +5609,8 @@ void ReaderBase::clearStack() {
}
}
void ReaderBase::initParamsAndAutos(uint32_t NumParam, uint32_t NumAuto) {
void ReaderBase::initParamsAndAutos(uint32_t NumParam, uint32_t NumAuto,
bool HasSecretParameter) {
// Init verification maps
if (VerificationNeeded) {
NumVerifyParams = NumParam;
@ -5626,7 +5627,7 @@ void ReaderBase::initParamsAndAutos(uint32_t NumParam, uint32_t NumAuto) {
NumVerifyAutos = 0;
}
buildUpParams(NumParam);
buildUpParams(NumParam, HasSecretParameter);
buildUpAutos(NumAuto);
}
@ -5690,7 +5691,7 @@ void ReaderBase::buildUpAutos(uint32_t NumAutos) {
// Note there is parallel logic in GenIR::GetFunctionType.
// It must be kept in sync with the logic in this method.
// We possibly should merge these two.
void ReaderBase::buildUpParams(uint32_t NumParams) {
void ReaderBase::buildUpParams(uint32_t NumParams, bool HasSecretParameter) {
if (NumParams > 0) {
CORINFO_ARG_LIST_HANDLE NextLoc, Locs;
CORINFO_CLASS_HANDLE Class;
@ -5752,8 +5753,10 @@ void ReaderBase::buildUpParams(uint32_t NumParams) {
ParamIndex++;
}
uint32_t NumRealParams = HasSecretParameter ? NumParams - 1 : NumParams;
// Get the types of all of the parameters.
for (; ParamIndex < NumParams; ParamIndex++) {
for (; ParamIndex < NumRealParams; ParamIndex++) {
if (VerificationNeeded) {
verifyRecordParamType(ParamIndex - (IsVarArg ? 1 : 0) -
@ -5765,6 +5768,14 @@ void ReaderBase::buildUpParams(uint32_t NumParams) {
createSym(ParamIndex, false, CorType, Class, false);
Locs = NextLoc;
}
if (HasSecretParameter) {
ASSERT(ParamIndex == NumParams - 1);
CORINFO_CLASS_HANDLE Class = 0;
createSym(ParamIndex, false, CORINFO_TYPE_NATIVEINT, Class, false,
ReaderSpecialSymbolType::Reader_SecretParam);
}
}
}

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

@ -269,8 +269,12 @@ void GenIR::readerPrePass(uint8_t *Buffer, uint32_t NumBytes) {
ASSERTNR(UNREACHED);
}
const uint32_t JitFlags = JitContext->Flags;
HasSecretParameter = (JitFlags & CORJIT_FLG_PUBLISH_SECRET_PARAM) != 0;
CORINFO_METHOD_HANDLE MethodHandle = JitContext->MethodInfo->ftn;
Function = getFunction(MethodHandle);
Function = getFunction(MethodHandle, HasSecretParameter);
// Capture low-level info about the return type for use in Return.
CORINFO_SIG_INFO Sig;
@ -300,7 +304,7 @@ void GenIR::readerPrePass(uint8_t *Buffer, uint32_t NumBytes) {
KeepGenericContextAlive = false;
UnreachableContinuationBlock = nullptr;
initParamsAndAutos(NumArgs, NumLocals);
initParamsAndAutos(NumArgs, NumLocals, HasSecretParameter);
// Take note of the current insertion point in case we need
// to add more allocas later.
@ -326,7 +330,6 @@ void GenIR::readerPrePass(uint8_t *Buffer, uint32_t NumBytes) {
// Check for special cases where the Jit needs to do extra work.
const uint32_t MethodFlags = getCurrentMethodAttribs();
const uint32_t JitFlags = JitContext->Flags;
// TODO: support for synchronized methods
if (MethodFlags & CORINFO_FLG_SYNCH) {
@ -345,12 +348,6 @@ void GenIR::readerPrePass(uint8_t *Buffer, uint32_t NumBytes) {
}
}
// TODO: support for secret parameter for shared IL stubs
if ((JitFlags & CORJIT_FLG_IL_STUB) &&
(JitFlags & CORJIT_FLG_PUBLISH_SECRET_PARAM)) {
throw NotYetImplementedException("publish secret param");
}
// TODO: Insert class initialization check if necessary
CorInfoInitClassResult InitResult =
initClass(nullptr, getCurrentMethodHandle(), getCurrentContext());
@ -495,9 +492,10 @@ void GenIR::createSym(uint32_t Num, bool IsAuto, CorInfoType CorType,
}
}
Function *GenIR::getFunction(CORINFO_METHOD_HANDLE MethodHandle) {
Function *GenIR::getFunction(CORINFO_METHOD_HANDLE MethodHandle,
bool HasSecretParameter) {
Module *M = JitContext->CurrentModule;
FunctionType *Ty = getFunctionType(MethodHandle);
FunctionType *Ty = getFunctionType(MethodHandle, HasSecretParameter);
llvm::Function *F = Function::Create(Ty, Function::ExternalLinkage,
M->getModuleIdentifier(), M);
@ -511,6 +509,17 @@ Function *GenIR::getFunction(CORINFO_METHOD_HANDLE MethodHandle) {
Args->setName(Twine("param") + Twine(N++));
}
if (HasSecretParameter) {
ASSERT((--F->arg_end())->getType() ==
getType(CORINFO_TYPE_NATIVEINT, nullptr));
LLVMContext &Context = *JitContext->LLVMContext;
AttributeSet Attrs = F->getAttributes();
F->setAttributes(
Attrs.addAttribute(Context, F->arg_size(), "CLR_SecretParameter"));
F->setCallingConv(CallingConv::CLR_SecretParameter);
}
return F;
}
@ -552,6 +561,14 @@ IRNode *GenIR::thisObj() {
return (IRNode *)UnmodifiedThis;
}
// Get the value of the secret parameter to an IL stub.
IRNode *GenIR::secretParam() {
ASSERT(HasSecretParameter);
Function::arg_iterator Args = Function->arg_end();
Value *SecretParameter = --Args;
return (IRNode *)SecretParameter;
}
// Get the value of the varargs token (aka argList).
IRNode *GenIR::argList() {
ASSERT(HasVarargsToken);
@ -1305,11 +1322,12 @@ Type *GenIR::getClassType(CORINFO_CLASS_HANDLE ClassHandle, bool IsRefClass,
}
// Obtain an LLVM function type from a method handle.
FunctionType *GenIR::getFunctionType(CORINFO_METHOD_HANDLE Method) {
FunctionType *GenIR::getFunctionType(CORINFO_METHOD_HANDLE Method,
bool HasSecretParameter) {
CORINFO_SIG_INFO Sig;
getMethodSig(Method, &Sig);
CORINFO_CLASS_HANDLE Class = getMethodClass(Method);
FunctionType *Result = getFunctionType(Sig, Class);
FunctionType *Result = getFunctionType(Sig, Class, HasSecretParameter);
return Result;
}
@ -1318,7 +1336,8 @@ FunctionType *GenIR::getFunctionType(CORINFO_METHOD_HANDLE Method) {
// If the signature has an implicit 'this' parameter,
// ThisClass must be passed in as the appropriate class handle.
FunctionType *GenIR::getFunctionType(CORINFO_SIG_INFO &Sig,
CORINFO_CLASS_HANDLE ThisClass) {
CORINFO_CLASS_HANDLE ThisClass,
bool HasSecretParameter) {
CorInfoType ReturnType = Sig.retType;
CORINFO_CLASS_HANDLE ReturnClass = Sig.retTypeClass;
Type *LLVMReturnType = this->getType(ReturnType, ReturnClass);
@ -1355,9 +1374,8 @@ FunctionType *GenIR::getFunctionType(CORINFO_SIG_INFO &Sig,
bool HasTypeArg = Sig.hasTypeArg();
if (HasTypeArg) {
CORINFO_CLASS_HANDLE Class = 0;
CORINFO_CLASS_HANDLE Class = nullptr;
Type *TypeArgType = getType(CORINFO_TYPE_NATIVEINT, Class);
Arguments.push_back(TypeArgType);
}
@ -1371,6 +1389,12 @@ FunctionType *GenIR::getFunctionType(CORINFO_SIG_INFO &Sig,
Arguments.push_back(LLVMArgType);
}
if (HasSecretParameter) {
CORINFO_CLASS_HANDLE Class = nullptr;
Type *SecretParameterType = getType(CORINFO_TYPE_NATIVEINT, Class);
Arguments.push_back(SecretParameterType);
}
FunctionType *FunctionType =
FunctionType::get(LLVMReturnType, Arguments, IsVarArg);
@ -3259,6 +3283,8 @@ IRNode *GenIR::genCall(ReaderCallTargetData *CallTargetInfo,
IRNode *TargetNode = CallTargetInfo->getCallTargetNode();
CORINFO_SIG_INFO *SigInfo = CallTargetInfo->getSigInfo();
CORINFO_CALL_INFO *CallInfo = CallTargetInfo->getCallInfo();
bool IsStubCall =
(CallInfo != nullptr) && (CallInfo->kind == CORINFO_VIRTUALCALL_STUB);
unsigned HiddenMBParamSize = 0;
GCLayout *GCInfo = nullptr;
@ -3271,12 +3297,6 @@ IRNode *GenIR::genCall(ReaderCallTargetData *CallTargetInfo,
}
}
if ((CallInfo != nullptr) && (CallInfo->kind == CORINFO_VIRTUALCALL_STUB)) {
// VSD calls have a special calling convention that requires the pointer
// to the stub in a target-specific register.
throw NotYetImplementedException("virtual stub dispatch");
}
// Ask GenIR to create return value.
if (!CallTargetInfo->isNewObj()) {
ReturnNode = makeCallReturnNode(SigInfo, &HiddenMBParamSize, &GCInfo);
@ -3338,8 +3358,8 @@ IRNode *GenIR::genCall(ReaderCallTargetData *CallTargetInfo,
}
CallInst *CallInst = LLVMBuilder->CreateCall(TargetNode, Arguments);
CorInfoIntrinsics IntrinsicID = CallTargetInfo->getCorInstrinsic();
CorInfoIntrinsics IntrinsicID = CallTargetInfo->getCorInstrinsic();
if ((0 <= IntrinsicID) && (IntrinsicID < CORINFO_INTRINSIC_Count)) {
throw NotYetImplementedException("Call intrinsic");
}
@ -3363,6 +3383,10 @@ IRNode *GenIR::genCall(ReaderCallTargetData *CallTargetInfo,
}
}
if (IsStubCall) {
Call = canonStubCall(Call, CallTargetInfo);
}
if (ReturnNode != nullptr) {
return ReturnNode;
}
@ -3401,7 +3425,7 @@ bool GenIR::canonNewObjCall(IRNode *CallNode,
if (IsArray) {
// Zero-based, one-dimensional arrays are allocated via newarr;
// all other arrays are allocated via newobj
canonNewArrayCall(CallNode, CallTargetData, OutResult);
*OutResult = canonNewArrayCall(CallNode, CallTargetData);
LLVMBuilder->SetInsertPoint(CurrentBlock, SavedInsertPoint);
DoneBeingProcessed = true;
} else if (IsVarObjSize) {
@ -3415,12 +3439,11 @@ bool GenIR::canonNewObjCall(IRNode *CallNode,
// Change the type of the called function and
// the type of the CallInstruction.
CallInst *CallInstruction = dyn_cast<CallInst>(CallNode);
CallInst *CallInstruction = cast<CallInst>(CallNode);
Value *CalledValue = CallInstruction->getCalledValue();
PointerType *CalledValueType =
dyn_cast<PointerType>(CalledValue->getType());
PointerType *CalledValueType = cast<PointerType>(CalledValue->getType());
FunctionType *FuncType =
dyn_cast<FunctionType>(CalledValueType->getElementType());
cast<FunctionType>(CalledValueType->getElementType());
// Construct the new function type.
std::vector<Type *> Arguments;
@ -3488,9 +3511,8 @@ bool GenIR::canonNewObjCall(IRNode *CallNode,
return DoneBeingProcessed;
}
void GenIR::canonNewArrayCall(IRNode *Call,
ReaderCallTargetData *CallTargetData,
IRNode **OutResult) {
IRNode *GenIR::canonNewArrayCall(IRNode *Call,
ReaderCallTargetData *CallTargetData) {
CallInst *CallInstruction = dyn_cast<CallInst>(Call);
Value *CalledValue = CallInstruction->getCalledValue();
PointerType *CalledValueType = dyn_cast<PointerType>(CalledValue->getType());
@ -3543,18 +3565,63 @@ void GenIR::canonNewArrayCall(IRNode *Call,
LLVMBuilder->CreateCall(NewCalledValue, NewArguments);
CallInstruction->eraseFromParent();
*OutResult = (IRNode *)NewCallInstruction;
return;
return (IRNode *)NewCallInstruction;
}
bool GenIR::callIsCorVarArgs(IRNode *CallNode) {
CallInst *CallInstruction = dyn_cast<CallInst>(CallNode);
CallInst *CallInstruction = cast<CallInst>(CallNode);
Value *CalledValue = CallInstruction->getCalledValue();
PointerType *CalledValueType = dyn_cast<PointerType>(CalledValue->getType());
return dyn_cast<FunctionType>(CalledValueType->getElementType())->isVarArg();
}
IRNode *GenIR::canonStubCall(IRNode *CallNode,
ReaderCallTargetData *CallTargetData) {
assert(CallTargetData != nullptr);
assert(CallTargetData->getCallInfo() != nullptr &&
CallTargetData->getCallInfo()->kind == CORINFO_VIRTUALCALL_STUB);
CallInst *Call = cast<CallInst>(CallNode);
BasicBlock *CurrentBlock = Call->getParent();
BasicBlock::iterator SavedInsertPoint = LLVMBuilder->GetInsertPoint();
LLVMBuilder->SetInsertPoint(Call);
Value *Target = Call->getCalledValue();
PointerType *TargetType = cast<PointerType>(Target->getType());
FunctionType *TargetFuncType =
cast<FunctionType>(TargetType->getElementType());
// Construct the new function type.
std::vector<Type *> ArgumentTypes;
std::vector<Value *> Arguments;
Value *IndirectionCell = (Value *)CallTargetData->getIndirectionCellNode();
assert(IndirectionCell != nullptr);
ArgumentTypes.push_back(IndirectionCell->getType());
Arguments.push_back(IndirectionCell);
for (unsigned I = 0; I < TargetFuncType->getNumParams(); ++I) {
ArgumentTypes.push_back(TargetFuncType->getParamType(I));
Arguments.push_back(Call->getArgOperand(I));
}
FunctionType *FuncType =
FunctionType::get(TargetFuncType->getReturnType(), ArgumentTypes,
TargetFuncType->isVarArg());
Value *NewTarget =
LLVMBuilder->CreatePointerCast(Target, getUnmanagedPointerType(FuncType));
CallInst *NewCall = LLVMBuilder->CreateCall(NewTarget, Arguments);
NewCall->setCallingConv(CallingConv::CLR_VirtualDispatchStub);
Call->eraseFromParent();
LLVMBuilder->SetInsertPoint(CurrentBlock, SavedInsertPoint);
return (IRNode *)NewCall;
}
IRNode *GenIR::conv(ReaderBaseNS::ConvOpcode Opcode, IRNode *Arg1) {
struct ConvertInfo {