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

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

@ -279,9 +279,7 @@ public:
IRNode *argList() override; IRNode *argList() override;
IRNode *instParam() override; IRNode *instParam() override;
IRNode *secretParam() override { IRNode *secretParam() override;
throw NotYetImplementedException("secretParam");
};
IRNode *thisObj() override; IRNode *thisObj() override;
void boolBranch(ReaderBaseNS::BoolBranchOpcode Opcode, IRNode *Arg1) override; void boolBranch(ReaderBaseNS::BoolBranchOpcode Opcode, IRNode *Arg1) override;
@ -805,8 +803,11 @@ public:
// newobj // newobj
bool canonNewObjCall(IRNode *CallNode, ReaderCallTargetData *CallTargetData, bool canonNewObjCall(IRNode *CallNode, ReaderCallTargetData *CallTargetData,
IRNode **OutResult); IRNode **OutResult);
void canonNewArrayCall(IRNode *CallNode, ReaderCallTargetData *CallTargetData, IRNode *canonNewArrayCall(IRNode *CallNode,
IRNode **OutResult); ReaderCallTargetData *CallTargetData);
// stubs
IRNode *canonStubCall(IRNode *CallNode, ReaderCallTargetData *CallTargetData);
#endif #endif
// Used to expand multidimensional array access intrinsics // Used to expand multidimensional array access intrinsics
@ -837,11 +838,14 @@ private:
llvm::Type *getType(CorInfoType Type, CORINFO_CLASS_HANDLE ClassHandle, llvm::Type *getType(CorInfoType Type, CORINFO_CLASS_HANDLE ClassHandle,
bool GetRefClassFields = true); 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, 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, llvm::Type *getClassType(CORINFO_CLASS_HANDLE ClassHandle, bool IsRefClass,
bool GetRefClassFields); bool GetRefClassFields);
@ -1101,6 +1105,7 @@ private:
bool HasThis; bool HasThis;
bool HasTypeParameter; bool HasTypeParameter;
bool HasVarargsToken; bool HasVarargsToken;
bool HasSecretParameter;
bool KeepGenericContextAlive; bool KeepGenericContextAlive;
llvm::BasicBlock *EntryBlock; llvm::BasicBlock *EntryBlock;
llvm::Instruction *TempInsertionPoint; 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 // Init verification maps
if (VerificationNeeded) { if (VerificationNeeded) {
NumVerifyParams = NumParam; NumVerifyParams = NumParam;
@ -5626,7 +5627,7 @@ void ReaderBase::initParamsAndAutos(uint32_t NumParam, uint32_t NumAuto) {
NumVerifyAutos = 0; NumVerifyAutos = 0;
} }
buildUpParams(NumParam); buildUpParams(NumParam, HasSecretParameter);
buildUpAutos(NumAuto); buildUpAutos(NumAuto);
} }
@ -5690,7 +5691,7 @@ void ReaderBase::buildUpAutos(uint32_t NumAutos) {
// Note there is parallel logic in GenIR::GetFunctionType. // Note there is parallel logic in GenIR::GetFunctionType.
// It must be kept in sync with the logic in this method. // It must be kept in sync with the logic in this method.
// We possibly should merge these two. // We possibly should merge these two.
void ReaderBase::buildUpParams(uint32_t NumParams) { void ReaderBase::buildUpParams(uint32_t NumParams, bool HasSecretParameter) {
if (NumParams > 0) { if (NumParams > 0) {
CORINFO_ARG_LIST_HANDLE NextLoc, Locs; CORINFO_ARG_LIST_HANDLE NextLoc, Locs;
CORINFO_CLASS_HANDLE Class; CORINFO_CLASS_HANDLE Class;
@ -5752,8 +5753,10 @@ void ReaderBase::buildUpParams(uint32_t NumParams) {
ParamIndex++; ParamIndex++;
} }
uint32_t NumRealParams = HasSecretParameter ? NumParams - 1 : NumParams;
// Get the types of all of the parameters. // Get the types of all of the parameters.
for (; ParamIndex < NumParams; ParamIndex++) { for (; ParamIndex < NumRealParams; ParamIndex++) {
if (VerificationNeeded) { if (VerificationNeeded) {
verifyRecordParamType(ParamIndex - (IsVarArg ? 1 : 0) - verifyRecordParamType(ParamIndex - (IsVarArg ? 1 : 0) -
@ -5765,6 +5768,14 @@ void ReaderBase::buildUpParams(uint32_t NumParams) {
createSym(ParamIndex, false, CorType, Class, false); createSym(ParamIndex, false, CorType, Class, false);
Locs = NextLoc; 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); ASSERTNR(UNREACHED);
} }
const uint32_t JitFlags = JitContext->Flags;
HasSecretParameter = (JitFlags & CORJIT_FLG_PUBLISH_SECRET_PARAM) != 0;
CORINFO_METHOD_HANDLE MethodHandle = JitContext->MethodInfo->ftn; 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. // Capture low-level info about the return type for use in Return.
CORINFO_SIG_INFO Sig; CORINFO_SIG_INFO Sig;
@ -300,7 +304,7 @@ void GenIR::readerPrePass(uint8_t *Buffer, uint32_t NumBytes) {
KeepGenericContextAlive = false; KeepGenericContextAlive = false;
UnreachableContinuationBlock = nullptr; UnreachableContinuationBlock = nullptr;
initParamsAndAutos(NumArgs, NumLocals); initParamsAndAutos(NumArgs, NumLocals, HasSecretParameter);
// Take note of the current insertion point in case we need // Take note of the current insertion point in case we need
// to add more allocas later. // 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. // Check for special cases where the Jit needs to do extra work.
const uint32_t MethodFlags = getCurrentMethodAttribs(); const uint32_t MethodFlags = getCurrentMethodAttribs();
const uint32_t JitFlags = JitContext->Flags;
// TODO: support for synchronized methods // TODO: support for synchronized methods
if (MethodFlags & CORINFO_FLG_SYNCH) { 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 // TODO: Insert class initialization check if necessary
CorInfoInitClassResult InitResult = CorInfoInitClassResult InitResult =
initClass(nullptr, getCurrentMethodHandle(), getCurrentContext()); 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; Module *M = JitContext->CurrentModule;
FunctionType *Ty = getFunctionType(MethodHandle); FunctionType *Ty = getFunctionType(MethodHandle, HasSecretParameter);
llvm::Function *F = Function::Create(Ty, Function::ExternalLinkage, llvm::Function *F = Function::Create(Ty, Function::ExternalLinkage,
M->getModuleIdentifier(), M); M->getModuleIdentifier(), M);
@ -511,6 +509,17 @@ Function *GenIR::getFunction(CORINFO_METHOD_HANDLE MethodHandle) {
Args->setName(Twine("param") + Twine(N++)); 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; return F;
} }
@ -552,6 +561,14 @@ IRNode *GenIR::thisObj() {
return (IRNode *)UnmodifiedThis; 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). // Get the value of the varargs token (aka argList).
IRNode *GenIR::argList() { IRNode *GenIR::argList() {
ASSERT(HasVarargsToken); ASSERT(HasVarargsToken);
@ -1305,11 +1322,12 @@ Type *GenIR::getClassType(CORINFO_CLASS_HANDLE ClassHandle, bool IsRefClass,
} }
// Obtain an LLVM function type from a method handle. // 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; CORINFO_SIG_INFO Sig;
getMethodSig(Method, &Sig); getMethodSig(Method, &Sig);
CORINFO_CLASS_HANDLE Class = getMethodClass(Method); CORINFO_CLASS_HANDLE Class = getMethodClass(Method);
FunctionType *Result = getFunctionType(Sig, Class); FunctionType *Result = getFunctionType(Sig, Class, HasSecretParameter);
return Result; return Result;
} }
@ -1318,7 +1336,8 @@ FunctionType *GenIR::getFunctionType(CORINFO_METHOD_HANDLE Method) {
// If the signature has an implicit 'this' parameter, // If the signature has an implicit 'this' parameter,
// ThisClass must be passed in as the appropriate class handle. // ThisClass must be passed in as the appropriate class handle.
FunctionType *GenIR::getFunctionType(CORINFO_SIG_INFO &Sig, FunctionType *GenIR::getFunctionType(CORINFO_SIG_INFO &Sig,
CORINFO_CLASS_HANDLE ThisClass) { CORINFO_CLASS_HANDLE ThisClass,
bool HasSecretParameter) {
CorInfoType ReturnType = Sig.retType; CorInfoType ReturnType = Sig.retType;
CORINFO_CLASS_HANDLE ReturnClass = Sig.retTypeClass; CORINFO_CLASS_HANDLE ReturnClass = Sig.retTypeClass;
Type *LLVMReturnType = this->getType(ReturnType, ReturnClass); Type *LLVMReturnType = this->getType(ReturnType, ReturnClass);
@ -1355,9 +1374,8 @@ FunctionType *GenIR::getFunctionType(CORINFO_SIG_INFO &Sig,
bool HasTypeArg = Sig.hasTypeArg(); bool HasTypeArg = Sig.hasTypeArg();
if (HasTypeArg) { if (HasTypeArg) {
CORINFO_CLASS_HANDLE Class = 0; CORINFO_CLASS_HANDLE Class = nullptr;
Type *TypeArgType = getType(CORINFO_TYPE_NATIVEINT, Class); Type *TypeArgType = getType(CORINFO_TYPE_NATIVEINT, Class);
Arguments.push_back(TypeArgType); Arguments.push_back(TypeArgType);
} }
@ -1371,6 +1389,12 @@ FunctionType *GenIR::getFunctionType(CORINFO_SIG_INFO &Sig,
Arguments.push_back(LLVMArgType); 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 *FunctionType =
FunctionType::get(LLVMReturnType, Arguments, IsVarArg); FunctionType::get(LLVMReturnType, Arguments, IsVarArg);
@ -3259,6 +3283,8 @@ IRNode *GenIR::genCall(ReaderCallTargetData *CallTargetInfo,
IRNode *TargetNode = CallTargetInfo->getCallTargetNode(); IRNode *TargetNode = CallTargetInfo->getCallTargetNode();
CORINFO_SIG_INFO *SigInfo = CallTargetInfo->getSigInfo(); CORINFO_SIG_INFO *SigInfo = CallTargetInfo->getSigInfo();
CORINFO_CALL_INFO *CallInfo = CallTargetInfo->getCallInfo(); CORINFO_CALL_INFO *CallInfo = CallTargetInfo->getCallInfo();
bool IsStubCall =
(CallInfo != nullptr) && (CallInfo->kind == CORINFO_VIRTUALCALL_STUB);
unsigned HiddenMBParamSize = 0; unsigned HiddenMBParamSize = 0;
GCLayout *GCInfo = nullptr; 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. // Ask GenIR to create return value.
if (!CallTargetInfo->isNewObj()) { if (!CallTargetInfo->isNewObj()) {
ReturnNode = makeCallReturnNode(SigInfo, &HiddenMBParamSize, &GCInfo); ReturnNode = makeCallReturnNode(SigInfo, &HiddenMBParamSize, &GCInfo);
@ -3338,8 +3358,8 @@ IRNode *GenIR::genCall(ReaderCallTargetData *CallTargetInfo,
} }
CallInst *CallInst = LLVMBuilder->CreateCall(TargetNode, Arguments); CallInst *CallInst = LLVMBuilder->CreateCall(TargetNode, Arguments);
CorInfoIntrinsics IntrinsicID = CallTargetInfo->getCorInstrinsic();
CorInfoIntrinsics IntrinsicID = CallTargetInfo->getCorInstrinsic();
if ((0 <= IntrinsicID) && (IntrinsicID < CORINFO_INTRINSIC_Count)) { if ((0 <= IntrinsicID) && (IntrinsicID < CORINFO_INTRINSIC_Count)) {
throw NotYetImplementedException("Call intrinsic"); throw NotYetImplementedException("Call intrinsic");
} }
@ -3363,6 +3383,10 @@ IRNode *GenIR::genCall(ReaderCallTargetData *CallTargetInfo,
} }
} }
if (IsStubCall) {
Call = canonStubCall(Call, CallTargetInfo);
}
if (ReturnNode != nullptr) { if (ReturnNode != nullptr) {
return ReturnNode; return ReturnNode;
} }
@ -3401,7 +3425,7 @@ bool GenIR::canonNewObjCall(IRNode *CallNode,
if (IsArray) { if (IsArray) {
// Zero-based, one-dimensional arrays are allocated via newarr; // Zero-based, one-dimensional arrays are allocated via newarr;
// all other arrays are allocated via newobj // all other arrays are allocated via newobj
canonNewArrayCall(CallNode, CallTargetData, OutResult); *OutResult = canonNewArrayCall(CallNode, CallTargetData);
LLVMBuilder->SetInsertPoint(CurrentBlock, SavedInsertPoint); LLVMBuilder->SetInsertPoint(CurrentBlock, SavedInsertPoint);
DoneBeingProcessed = true; DoneBeingProcessed = true;
} else if (IsVarObjSize) { } else if (IsVarObjSize) {
@ -3415,12 +3439,11 @@ bool GenIR::canonNewObjCall(IRNode *CallNode,
// Change the type of the called function and // Change the type of the called function and
// the type of the CallInstruction. // the type of the CallInstruction.
CallInst *CallInstruction = dyn_cast<CallInst>(CallNode); CallInst *CallInstruction = cast<CallInst>(CallNode);
Value *CalledValue = CallInstruction->getCalledValue(); Value *CalledValue = CallInstruction->getCalledValue();
PointerType *CalledValueType = PointerType *CalledValueType = cast<PointerType>(CalledValue->getType());
dyn_cast<PointerType>(CalledValue->getType());
FunctionType *FuncType = FunctionType *FuncType =
dyn_cast<FunctionType>(CalledValueType->getElementType()); cast<FunctionType>(CalledValueType->getElementType());
// Construct the new function type. // Construct the new function type.
std::vector<Type *> Arguments; std::vector<Type *> Arguments;
@ -3488,9 +3511,8 @@ bool GenIR::canonNewObjCall(IRNode *CallNode,
return DoneBeingProcessed; return DoneBeingProcessed;
} }
void GenIR::canonNewArrayCall(IRNode *Call, IRNode *GenIR::canonNewArrayCall(IRNode *Call,
ReaderCallTargetData *CallTargetData, ReaderCallTargetData *CallTargetData) {
IRNode **OutResult) {
CallInst *CallInstruction = dyn_cast<CallInst>(Call); CallInst *CallInstruction = dyn_cast<CallInst>(Call);
Value *CalledValue = CallInstruction->getCalledValue(); Value *CalledValue = CallInstruction->getCalledValue();
PointerType *CalledValueType = dyn_cast<PointerType>(CalledValue->getType()); PointerType *CalledValueType = dyn_cast<PointerType>(CalledValue->getType());
@ -3543,18 +3565,63 @@ void GenIR::canonNewArrayCall(IRNode *Call,
LLVMBuilder->CreateCall(NewCalledValue, NewArguments); LLVMBuilder->CreateCall(NewCalledValue, NewArguments);
CallInstruction->eraseFromParent(); CallInstruction->eraseFromParent();
*OutResult = (IRNode *)NewCallInstruction; return (IRNode *)NewCallInstruction;
return;
} }
bool GenIR::callIsCorVarArgs(IRNode *CallNode) { bool GenIR::callIsCorVarArgs(IRNode *CallNode) {
CallInst *CallInstruction = dyn_cast<CallInst>(CallNode); CallInst *CallInstruction = cast<CallInst>(CallNode);
Value *CalledValue = CallInstruction->getCalledValue(); Value *CalledValue = CallInstruction->getCalledValue();
PointerType *CalledValueType = dyn_cast<PointerType>(CalledValue->getType()); PointerType *CalledValueType = dyn_cast<PointerType>(CalledValue->getType());
return dyn_cast<FunctionType>(CalledValueType->getElementType())->isVarArg(); 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) { IRNode *GenIR::conv(ReaderBaseNS::ConvOpcode Opcode, IRNode *Arg1) {
struct ConvertInfo { struct ConvertInfo {