зеркало из https://github.com/dotnet/llilc.git
Merge pull request #345 from pgavlin/callconv
Support VSD calls and methods with a secret parameter.
This commit is contained in:
Коммит
87ee4e6dce
|
@ -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 {
|
||||
|
|
Загрузка…
Ссылка в новой задаче