This wraps LLVMBuilder->CreateCall, and will be where the logic goes that
instead creates an invoke with an appropriate exception edge if we're in a
protected region.
This commit is contained in:
Joseph Tremoulet 2015-04-08 13:06:04 -04:00
Родитель b60b5bf718
Коммит 9369fba917
6 изменённых файлов: 220 добавлений и 128 удалений

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

@ -68,13 +68,14 @@ public:
/// \param Reader The \p GenIR instance that will be used to emit
/// IR.
/// \param Target The call target.
/// \param MayThrow True iff the callee may raise an exception
/// \param Args The arguments to the call.
/// \param IndirectionCell The indirection cell argument for the call, if
/// any.
/// \param CallNode [out] The call instruction.
///
/// \returns The result of the call to the target.
llvm::Value *emitCall(GenIR &Reader, llvm::Value *Target,
llvm::Value *emitCall(GenIR &Reader, llvm::Value *Target, bool mayThrow,
llvm::ArrayRef<llvm::Value *> Args,
llvm::Value *IndirectionCell,
llvm::Value **CallNode) const;

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

@ -3134,15 +3134,16 @@ public:
IRNode *ThisArg) = 0;
// Helper callback used by rdrCall to emit call code.
virtual IRNode *genCall(ReaderCallTargetData *CallTargetData,
virtual IRNode *genCall(ReaderCallTargetData *CallTargetData, bool MayThrow,
std::vector<IRNode *> Args, IRNode **CallNode) = 0;
virtual bool canMakeDirectCall(ReaderCallTargetData *CallTargetData) = 0;
// Generate call to helper
virtual IRNode *callHelper(CorInfoHelpFunc HelperID, IRNode *Dst,
IRNode *Arg1 = nullptr, IRNode *Arg2 = nullptr,
IRNode *Arg3 = nullptr, IRNode *Arg4 = nullptr,
virtual IRNode *callHelper(CorInfoHelpFunc HelperID, bool MayThrow,
IRNode *Dst, IRNode *Arg1 = nullptr,
IRNode *Arg2 = nullptr, IRNode *Arg3 = nullptr,
IRNode *Arg4 = nullptr,
ReaderAlignType Alignment = Reader_AlignUnknown,
bool IsVolatile = false, bool NoCtor = false,
bool CanMoveUp = false) = 0;

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

@ -24,6 +24,7 @@
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/Verifier.h"
#include "llvm/IR/CFG.h"
#include "llvm/IR/CallSite.h"
#include "reader.h"
#include "abi.h"
#include "abisignature.h"
@ -719,13 +720,13 @@ public:
IRNode *ThisArg) override;
// Helper callback used by rdrCall to emit call code.
IRNode *genCall(ReaderCallTargetData *CallTargetInfo,
IRNode *genCall(ReaderCallTargetData *CallTargetInfo, bool MayThrow,
std::vector<IRNode *> Args, IRNode **CallNode) override;
bool canMakeDirectCall(ReaderCallTargetData *CallTargetData) override;
// Generate call to helper
IRNode *callHelper(CorInfoHelpFunc HelperID, IRNode *Dst,
IRNode *callHelper(CorInfoHelpFunc HelperID, bool MayThrow, IRNode *Dst,
IRNode *Arg1 = nullptr, IRNode *Arg2 = nullptr,
IRNode *Arg3 = nullptr, IRNode *Arg4 = nullptr,
ReaderAlignType Alignment = Reader_AlignUnknown,
@ -733,12 +734,13 @@ public:
bool CanMoveUp = false) override;
// Generate call to helper
IRNode *callHelperImpl(CorInfoHelpFunc HelperID, llvm::Type *ReturnType,
IRNode *Arg1 = nullptr, IRNode *Arg2 = nullptr,
IRNode *Arg3 = nullptr, IRNode *Arg4 = nullptr,
ReaderAlignType Alignment = Reader_AlignUnknown,
bool IsVolatile = false, bool NoCtor = false,
bool CanMoveUp = false);
llvm::CallSite callHelperImpl(CorInfoHelpFunc HelperID, bool MayThrow,
llvm::Type *ReturnType, IRNode *Arg1 = nullptr,
IRNode *Arg2 = nullptr, IRNode *Arg3 = nullptr,
IRNode *Arg4 = nullptr,
ReaderAlignType Alignment = Reader_AlignUnknown,
bool IsVolatile = false, bool NoCtor = false,
bool CanMoveUp = false);
/// Generate special generics helper that might need to insert flow. The
/// helper is called if NullCheckArg is null at compile-time or if it
@ -1031,17 +1033,19 @@ private:
///
/// \param Condition Condition that will trigger the call.
/// \param HelperId Id of the call helper.
/// \param MayThrow true if the helper call may raise an exception.
/// \param ReturnType Return type of the call helper.
/// \param Arg1 First helper argument.
/// \param Arg2 Second helper argument.
/// \param CallReturns true iff the helper call returns.
/// \param CallBlockName Name of the basic block that will contain the call.
/// \returns Generated call instruction.
llvm::CallInst *genConditionalHelperCall(llvm::Value *Condition,
CorInfoHelpFunc HelperId,
llvm::Type *ReturnType, IRNode *Arg1,
IRNode *Arg2, bool CallReturns,
const llvm::Twine &CallBlockName);
/// \returns Generated call/invoke instruction.
llvm::CallSite genConditionalHelperCall(llvm::Value *Condition,
CorInfoHelpFunc HelperId,
bool MayThrow, llvm::Type *ReturnType,
IRNode *Arg1, IRNode *Arg2,
bool CallReturns,
const llvm::Twine &CallBlockName);
/// Generate a call to the throw helper if the condition is met.
///
@ -1144,6 +1148,17 @@ private:
return makeLoad(Address, IsVolatile, false);
}
/// \brief Create a call or invoke instruction
///
/// The call is inserted at the LLVMBuilder's current insertion point.
///
/// \param Callee Target of the call
/// \param MayThrow True if the callee may raise an exception
/// \param Args Arguments to pass to the callee
/// \returns A \p CallSite wrapping the CallInst or InvokeInst
llvm::CallSite makeCall(llvm::Value *Callee, bool MayThrow,
llvm::ArrayRef<llvm::Value *> Args);
/// Store a value to an argument passed indirectly.
///
/// The storage backing such arguments may be loacted on the heap; any stores

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

@ -87,7 +87,7 @@ ABICallSignature::ABICallSignature(const ReaderCallSignature &TheSignature,
: ABISignature(TheSignature, Reader, TheABIInfo), Signature(TheSignature) {}
Value *ABICallSignature::emitCall(GenIR &Reader, llvm::Value *Target,
llvm::ArrayRef<Value *> Args,
bool MayThrow, llvm::ArrayRef<Value *> Args,
llvm::Value *IndirectionCell,
llvm::Value **CallNode) const {
assert(Target->getType()->isIntegerTy(Reader.TargetPointerSizeInBits));
@ -150,7 +150,7 @@ Value *ABICallSignature::emitCall(GenIR &Reader, llvm::Value *Target,
Type *FunctionPtrTy = Reader.getUnmanagedPointerType(FunctionTy);
Target = Builder.CreateIntToPtr(Target, FunctionPtrTy);
CallInst *Call = Builder.CreateCall(Target, Arguments);
CallSite Call = Reader.makeCall(Target, MayThrow, Arguments);
CallingConv::ID CC;
if (HasIndirectionCell) {
@ -159,18 +159,18 @@ Value *ABICallSignature::emitCall(GenIR &Reader, llvm::Value *Target,
} else {
CC = getLLVMCallingConv(Signature.getCallingConvention());
}
Call->setCallingConv(CC);
Call.setCallingConv(CC);
if (ResultNode == nullptr) {
assert(!HasIndirectResult);
const CallArgType &SigResultType = Signature.getResultType();
Type *Ty = Reader.getType(SigResultType.CorType, SigResultType.Class);
ResultNode = coerce(Reader, Ty, Call);
ResultNode = coerce(Reader, Ty, Call.getInstruction());
} else {
ResultNode = Builder.CreateLoad(ResultNode);
}
*CallNode = Call;
*CallNode = Call.getInstruction();
return ResultNode;
}

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

@ -1309,7 +1309,8 @@ void ReaderBase::insertHelperCall(
HelperArgNodes[Index] = CurrentArg;
}
callHelper(AccessAllowedInfo.helperNum, nullptr, HelperArgNodes[0],
const bool MayThrow = true;
callHelper(AccessAllowedInfo.helperNum, MayThrow, nullptr, HelperArgNodes[0],
HelperArgNodes[1], HelperArgNodes[2], HelperArgNodes[3]);
}
@ -3685,8 +3686,9 @@ void ReaderBase::cpBlk(IRNode *Count, // byte count
IRNode *SrcAddr, // source address
IRNode *DestAddr, // dest address
ReaderAlignType Alignment, bool IsVolatile) {
callHelper(CORINFO_HELP_MEMCPY, nullptr, DestAddr, SrcAddr, Count, nullptr,
Alignment, IsVolatile);
const bool MayThrow = true;
callHelper(CORINFO_HELP_MEMCPY, MayThrow, nullptr, DestAddr, SrcAddr, Count,
nullptr, Alignment, IsVolatile);
}
// InitBlk - Creates a memset helper call/intrinsic.
@ -3694,8 +3696,9 @@ void ReaderBase::initBlk(IRNode *Count, // byte count
IRNode *Value, // Value
IRNode *DestAddr, // dest address
ReaderAlignType Alignment, bool IsVolatile) {
callHelper(CORINFO_HELP_MEMSET, nullptr, DestAddr, Value, Count, nullptr,
Alignment, IsVolatile);
const bool MayThrow = true;
callHelper(CORINFO_HELP_MEMSET, MayThrow, nullptr, DestAddr, Value, Count,
nullptr, Alignment, IsVolatile);
}
void ReaderBase::initObj(CORINFO_RESOLVED_TOKEN *ResolvedToken,
@ -3738,7 +3741,8 @@ IRNode *ReaderBase::box(CORINFO_RESOLVED_TOKEN *ResolvedToken, IRNode *Arg2,
// from the token.
Arg1 = genericTokenToNode(ResolvedToken, true);
RetVal = callHelper(getBoxHelper(Class), Dst, Arg1, Arg2);
const bool MayThrow = true;
RetVal = callHelper(getBoxHelper(Class), MayThrow, Dst, Arg1, Arg2);
return RetVal;
}
@ -3770,12 +3774,14 @@ IRNode *ReaderBase::refAnyVal(IRNode *RefAny,
Dst = makePtrDstGCOperand(true);
// Make the helper call
return callHelper(CORINFO_HELP_GETREFANY, Dst, Arg1, RefAny);
const bool MayThrow = true;
return callHelper(CORINFO_HELP_GETREFANY, MayThrow, Dst, Arg1, RefAny);
}
void ReaderBase::storeElemRefAny(IRNode *Value, IRNode *Index, IRNode *Obj) {
// Make the helper call
callHelper(CORINFO_HELP_ARRADDR_ST, nullptr, Obj, Index, Value);
const bool MayThrow = true;
callHelper(CORINFO_HELP_ARRADDR_ST, MayThrow, nullptr, Obj, Index, Value);
}
// StoreIndir - Creates an instruction to assign the value on
@ -3921,7 +3927,8 @@ IRNode *ReaderBase::unboxAny(CORINFO_RESOLVED_TOKEN *ResolvedToken, IRNode *Arg,
// Break - Default reader processing for CEE_BREAK.
void ReaderBase::breakOpcode() {
// Make the helper call
callHelper(CORINFO_HELP_USER_BREAKPOINT, nullptr);
const bool MayThrow = true;
callHelper(CORINFO_HELP_USER_BREAKPOINT, MayThrow, nullptr);
}
// InsertClassConstructor - Insert a call to the class constructor helper.
@ -3944,30 +3951,38 @@ void ReaderBase::insertClassConstructor() {
methodNeedsToKeepAliveGenericsContext(true);
switch (Kind.runtimeLookupKind) {
case CORINFO_LOOKUP_THISOBJ:
case CORINFO_LOOKUP_THISOBJ: {
// call CORINFO_HELP_INITINSTCLASS(thisobj, embedMethodHandle(M))
Method = embedMethodHandle(Method, &IsIndirect);
// TODO: Aliasing -- always readonly?
MethodNode = handleToIRNode(MethodToken, Method, 0, IsIndirect,
IsIndirect, true, false);
ClassNode = derefAddress(thisObj(), false, false);
callHelper(CORINFO_HELP_INITINSTCLASS, nullptr, ClassNode, MethodNode);
const bool MayThrow = true;
callHelper(CORINFO_HELP_INITINSTCLASS, MayThrow, nullptr, ClassNode,
MethodNode);
return;
case CORINFO_LOOKUP_CLASSPARAM:
}
case CORINFO_LOOKUP_CLASSPARAM: {
// will only be returned when you are compiling code that takes
// a hidden parameter P. You should emit a call
// CORINFO_HELP_INITCLASS(P)
ClassNode = instParam();
callHelper(CORINFO_HELP_INITCLASS, nullptr, ClassNode);
const bool MayThrow = true;
callHelper(CORINFO_HELP_INITCLASS, MayThrow, nullptr, ClassNode);
return;
case CORINFO_LOOKUP_METHODPARAM:
}
case CORINFO_LOOKUP_METHODPARAM: {
// will only be returned when you are compiling code that takes
// a hidden parameter P. You should emit a call
// CORINFO_HELP_INITINSTCLASS(nullptr, P)
MethodNode = instParam();
ClassNode = loadConstantI8(0);
callHelper(CORINFO_HELP_INITINSTCLASS, nullptr, ClassNode, MethodNode);
const bool MayThrow = true;
callHelper(CORINFO_HELP_INITINSTCLASS, MayThrow, nullptr, ClassNode,
MethodNode);
return;
}
default:
ASSERTNR(!"NYI");
}
@ -3987,7 +4002,8 @@ void ReaderBase::insertClassConstructor() {
ClassNode = handleToIRNode(MethodToken, ClassHandle, Class, IsIndirect,
IsIndirect, true, false);
callHelper(HelperId, nullptr, ClassNode);
const bool MayThrow = false;
callHelper(HelperId, MayThrow, nullptr, ClassNode);
} else {
rdrCallGetStaticBase(Class, MethodToken, HelperId, false, false, nullptr);
}
@ -4032,14 +4048,16 @@ IRNode *ReaderBase::rdrGetCritSect() {
// In this case, the hidden param is the class handle.
HandleNode = instParam();
break;
case CORINFO_LOOKUP_METHODPARAM:
case CORINFO_LOOKUP_METHODPARAM: {
// In this case, the hidden param is the method handle.
HandleNode = instParam();
// Call helper CORINFO_HELP_GETCLASSFROMMETHODPARAM to get the
// class handle from the method handle.
HandleNode = callHelper(CORINFO_HELP_GETCLASSFROMMETHODPARAM,
const bool MayThrow = false;
HandleNode = callHelper(CORINFO_HELP_GETCLASSFROMMETHODPARAM, MayThrow,
makePtrNode(), HandleNode);
break;
}
default:
ASSERTNR(!"Unknown LOOKUP_KIND");
break;
@ -4049,8 +4067,9 @@ IRNode *ReaderBase::rdrGetCritSect() {
// CORINFO_CLASS_HANDLE for the exact class.
// Given the class handle, get the pointer to the Monitor.
HandleNode = callHelper(CORINFO_HELP_GETSYNCFROMCLASSHANDLE, makePtrNode(),
HandleNode);
const bool MayThrow = false;
HandleNode = callHelper(CORINFO_HELP_GETSYNCFROMCLASSHANDLE, MayThrow,
makePtrNode(), HandleNode);
}
ASSERTNR(HandleNode);
@ -4101,7 +4120,8 @@ void ReaderBase::rdrCallFieldHelper(
IsIndirect, IsIndirect, true, false);
// Make the helper call
callHelper(HelperId, nullptr, Arg1, Arg2, Arg3, Arg4, Alignment,
const bool MayThrow = true;
callHelper(HelperId, MayThrow, nullptr, Arg1, Arg2, Arg3, Arg4, Alignment,
IsVolatile);
} else {
// OTHER LOAD
@ -4113,8 +4133,9 @@ void ReaderBase::rdrCallFieldHelper(
Arg1 = Obj;
// Make the helper call
callHelper(HelperId, Dst, Arg1, Arg2, nullptr, nullptr, Alignment,
IsVolatile);
const bool MayThrow = true;
callHelper(HelperId, MayThrow, Dst, Arg1, Arg2, nullptr, nullptr,
Alignment, IsVolatile);
}
} else {
// STORE
@ -4147,7 +4168,8 @@ void ReaderBase::rdrCallFieldHelper(
Arg1 = Obj;
// Make the helper call
callHelper(HelperId, nullptr, Arg1, Arg2, Arg3, Arg4, Alignment,
const bool MayThrow = true;
callHelper(HelperId, MayThrow, nullptr, Arg1, Arg2, Arg3, Arg4, Alignment,
IsVolatile);
} else {
// assert that the helper id is expected
@ -4168,8 +4190,9 @@ void ReaderBase::rdrCallFieldHelper(
Arg1 = Obj;
// Make the helper call
callHelper(HelperId, nullptr, Arg1, Arg2, Arg3, nullptr, Alignment,
IsVolatile);
const bool MayThrow = true;
callHelper(HelperId, MayThrow, nullptr, Arg1, Arg2, Arg3, nullptr,
Alignment, IsVolatile);
}
}
}
@ -4202,9 +4225,10 @@ void ReaderBase::rdrCallWriteBarrierHelper(
// writing to a field in a class which happens to be a GC pointer.
//
// HCIMPL2(void, JIT_CheckedWriteBarrier, Object** dest, Object * value)
callHelper(IsUnchecked ? CORINFO_HELP_ASSIGN_REF
: CORINFO_HELP_CHECKED_ASSIGN_REF,
nullptr, Dst, Src, nullptr, nullptr, Alignment, IsVolatile);
const bool MayThrow = true;
callHelper(
IsUnchecked ? CORINFO_HELP_ASSIGN_REF : CORINFO_HELP_CHECKED_ASSIGN_REF,
MayThrow, nullptr, Dst, Src, nullptr, nullptr, Alignment, IsVolatile);
} else {
// This is the case in which we will be copying a value class into
// the field of this struct. The runtime will need to be passed
@ -4242,13 +4266,15 @@ void ReaderBase::rdrCallWriteBarrierHelper(
handleToIRNode(ResolvedToken->token, ClassHandle, Class, IsIndirect,
IsIndirect, true, false);
callHelper(CORINFO_HELP_ASSIGN_STRUCT, nullptr, Dst, Src, ClassHandleNode,
nullptr, Alignment, IsVolatile);
const bool MayThrow = true;
callHelper(CORINFO_HELP_ASSIGN_STRUCT, MayThrow, nullptr, Dst, Src,
ClassHandleNode, nullptr, Alignment, IsVolatile);
} else {
// If the class doesn't have a gc layout then use a memcopy
IRNode *Size = loadConstantI4(getClassSize(Class));
callHelper(CORINFO_HELP_MEMCPY, nullptr, Dst, Src, Size, nullptr,
Alignment, IsVolatile);
const bool MayThrow = true;
callHelper(CORINFO_HELP_MEMCPY, MayThrow, nullptr, Dst, Src, Size,
nullptr, Alignment, IsVolatile);
}
}
}
@ -4285,9 +4311,10 @@ IRNode *ReaderBase::rdrCallGetStaticBase(CORINFO_CLASS_HANDLE Class,
Token, EmbedClassDomainID, (CORINFO_CLASS_HANDLE)((size_t)Class | 1),
IsIndirect2, IsIndirect2, IsIndirect2, false);
return callHelper(HelperId, Dst, ModuleDomainIDNode, ClassDomainIDNode,
nullptr, nullptr, Reader_AlignUnknown, false, NoCtor,
CanMoveUp);
const bool MayThrow = false;
return callHelper(HelperId, MayThrow, Dst, ModuleDomainIDNode,
ClassDomainIDNode, nullptr, nullptr, Reader_AlignUnknown,
false, NoCtor, CanMoveUp);
}
IRNode *
@ -4308,7 +4335,9 @@ ReaderBase::rdrGetStaticFieldAddress(CORINFO_RESOLVED_TOKEN *ResolvedToken,
IRNode *PointerNode = makePtrDstGCOperand(true);
// Now make the call and attach the arguments.
return callHelper(FieldInfo->helper, PointerNode, FieldHandleNode);
const bool MayThrow = false;
return callHelper(FieldInfo->helper, MayThrow, PointerNode,
FieldHandleNode);
}
case CORINFO_FIELD_STATIC_SHARED_STATIC_HELPER:
@ -4331,8 +4360,9 @@ ReaderBase::rdrGetStaticFieldAddress(CORINFO_RESOLVED_TOKEN *ResolvedToken,
IRNode *TempNode = makePtrNode(Reader_PtrGcInterior);
// Now make the call and attach the arguments.
const bool MayThrow = false;
SharedStaticsBaseNode =
callHelper(FieldInfo->helper, TempNode, ClassHandleNode);
callHelper(FieldInfo->helper, MayThrow, TempNode, ClassHandleNode);
} else {
CorInfoHelpFunc HelperId = FieldInfo->helper;
CORINFO_CLASS_HANDLE Class = ResolvedToken->hClass;
@ -4585,7 +4615,8 @@ IRNode *ReaderBase::rdrGetFieldAddress(CORINFO_RESOLVED_TOKEN *ResolvedToken,
Dst = makePtrNode();
}
return callHelper(FieldInfo->helper, Dst, Arg1, Arg2);
const bool MayThrow = true;
return callHelper(FieldInfo->helper, MayThrow, Dst, Arg1, Arg2);
} else {
// Get the offset, add it to the this pointer to calculate the
// actual address of the field.
@ -4812,6 +4843,7 @@ ReaderBase::rdrCall(ReaderCallTargetData *Data, ReaderBaseNS::CallOpcode Opcode,
// For certain intrinsics, we can determine that the call has no
// side effects ...
bool CallCanSideEffect = true;
bool MayThrow = true;
// TODO: readonly work for calls
@ -5304,7 +5336,7 @@ ReaderBase::rdrCall(ReaderCallTargetData *Data, ReaderBaseNS::CallOpcode Opcode,
}
// Ask GenIR to emit call, optionally returns a ReturnNode.
ReturnNode = genCall(Data, Arguments, CallNode);
ReturnNode = genCall(Data, MayThrow, Arguments, CallNode);
if (Data->isNewObj()) {
ReturnNode = rdrMakeNewObjReturnNode(Data, NewObjThisArg, ReturnNode);
@ -5508,7 +5540,8 @@ IRNode *ReaderBase::rdrGetIndirectVirtualCallTarget(
// Get the address of the target function by calling helper.
// Type it as a native int, it will be recast later.
IRNode *Dst = loadConstantI(0);
return callHelper(CORINFO_HELP_VIRTUAL_FUNC_PTR, Dst, ThisPtrCopy,
const bool MayThrow = true;
return callHelper(CORINFO_HELP_VIRTUAL_FUNC_PTR, MayThrow, Dst, ThisPtrCopy,
ClassHandle, MethodHandle);
}
@ -5635,7 +5668,9 @@ void ReaderBase::rdrInsertCalloutForDelegate(CORINFO_CLASS_HANDLE DelegateType,
IsIndirect, IsIndirect, true, false);
// Make the helper call
callHelper(CORINFO_HELP_DELEGATE_SECURITY_CHECK, nullptr, Arg1, Arg2);
const bool MayThrow = true;
callHelper(CORINFO_HELP_DELEGATE_SECURITY_CHECK, MayThrow, nullptr, Arg1,
Arg2);
}
}
@ -6191,7 +6226,8 @@ void ReaderBase::domInfoRecordClassInit(FlowGraphNode *Fg,
// Default routine to insert verification throw.
void ReaderBase::insertThrow(CorInfoHelpFunc ThrowHelper, uint32_t Offset) {
IRNode *IntConstant = loadConstantI4(Offset);
callHelper(ThrowHelper, nullptr, IntConstant);
const bool MayThrow = true;
callHelper(ThrowHelper, MayThrow, nullptr, IntConstant);
}
// Macro used by main reader loop for distinguishing verify-only passes

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

@ -410,10 +410,11 @@ void GenIR::readerPrePass(uint8_t *Buffer, uint32_t NumBytes) {
Value *Condition = LLVMBuilder->CreateIsNotNull(JustMyCodeFlag, "JMC");
IRNode *Zero = loadConstantI4(0);
Type *Void = Type::getVoidTy(*JitContext->LLVMContext);
const bool MayThrow = false;
const bool CallReturns = true;
genConditionalHelperCall(
Condition, CorInfoHelpFunc::CORINFO_HELP_DBG_IS_JUST_MY_CODE, Void,
JustMyCodeFlag, Zero, CallReturns, "JustMyCodeHook");
Condition, CorInfoHelpFunc::CORINFO_HELP_DBG_IS_JUST_MY_CODE,
MayThrow, Void, JustMyCodeFlag, Zero, CallReturns, "JustMyCodeHook");
}
}
@ -510,7 +511,8 @@ void GenIR::insertIRToKeepGenericContextAlive() {
Value *FrameEscape = Intrinsic::getDeclaration(JitContext->CurrentModule,
Intrinsic::frameescape);
Value *Args[] = {ContextLocalAddress};
LLVMBuilder->CreateCall(FrameEscape, Args);
const bool MayThrow = false;
makeCall(FrameEscape, MayThrow, Args);
// Don't move TempInsertionPoint up since what we added was not an alloca
LLVMBuilder->restoreIP(SavedInsertPoint);
@ -545,7 +547,8 @@ void GenIR::insertIRForSecurityObject() {
IsIndirect, IsRelocatable, IsCallTarget);
CorInfoHelpFunc SecurityHelper =
JitContext->JitInfo->getSecurityPrologHelper(MethodHandle);
callHelper(SecurityHelper, nullptr, MethodNode,
const bool MayThrow = true;
callHelper(SecurityHelper, MayThrow, nullptr, MethodNode,
(IRNode *)SecurityObjectAddress);
LLVMBuilder->restoreIP(SavedInsertPoint);
@ -566,7 +569,8 @@ void GenIR::callMonitorHelper(bool IsEnter) {
} else {
HelperId = IsEnter ? CORINFO_HELP_MON_ENTER : CORINFO_HELP_MON_EXIT;
}
callHelperImpl(HelperId, Type::getVoidTy(*JitContext->LLVMContext),
const bool MayThrow = false;
callHelperImpl(HelperId, MayThrow, Type::getVoidTy(*JitContext->LLVMContext),
MethodSyncHandle, (IRNode *)SyncFlag);
}
@ -2499,13 +2503,17 @@ IRNode *GenIR::binaryOp(ReaderBaseNS::BinaryOpcode Opcode, IRNode *Arg1,
llvm_unreachable("Bad floating point type!");
}
Result = callHelperImpl(Helper, ResultType, Arg1, Arg2);
const bool MayThrow = false;
Result = (IRNode *)callHelperImpl(Helper, MayThrow, ResultType, Arg1, Arg2)
.getInstruction();
} else if (IsOverflow) {
// Call the appropriate intrinsic. Its result is a pair of the arithmetic
// result and a bool indicating whether the operation overflows.
Value *Intrinsic = Intrinsic::getDeclaration(
JitContext->CurrentModule, Triple[Opcode].Op.Intrinsic, ResultType);
Value *Pair = LLVMBuilder->CreateCall2(Intrinsic, Arg1, Arg2);
Value *Args[] = {Arg1, Arg2};
const bool MayThrow = false;
Value *Pair = makeCall(Intrinsic, MayThrow, Args).getInstruction();
// Extract the bool and raise an overflow exception if set.
Value *OvfBool = LLVMBuilder->CreateExtractValue(Pair, 1, "Ovf");
@ -3067,6 +3075,13 @@ LoadInst *GenIR::makeLoad(Value *Address, bool IsVolatile,
return LLVMBuilder->CreateLoad(Address, IsVolatile);
}
CallSite GenIR::makeCall(Value *Callee, bool MayThrow, ArrayRef<Value *> Args) {
if (MayThrow) {
// TODO: Generate an invoke with an appropriate unwind label.
}
return LLVMBuilder->CreateCall(Callee, Args);
}
void GenIR::storeStaticField(CORINFO_RESOLVED_TOKEN *FieldToken,
IRNode *ValueToStore, bool IsVolatile) {
// Gather information about the field
@ -3233,8 +3248,10 @@ IRNode *GenIR::loadElemA(CORINFO_RESOLVED_TOKEN *ResolvedToken, IRNode *Index,
if (!IsReadOnly && ((ClassAttribs & CORINFO_FLG_VALUECLASS) == 0)) {
IRNode *HandleNode = genericTokenToNode(ResolvedToken);
PointerType *ElementAddressTy = getManagedPointerType(ElementTy);
return callHelperImpl(CORINFO_HELP_LDELEMA_REF, ElementAddressTy, Array,
Index, HandleNode);
const bool MayThrow = true;
return (IRNode *)callHelperImpl(CORINFO_HELP_LDELEMA_REF, MayThrow,
ElementAddressTy, Array, Index,
HandleNode).getInstruction();
}
return genArrayElemAddress(Array, Index, ElementTy);
@ -3402,21 +3419,23 @@ bool isNonVolatileWriteHelperCall(CorInfoHelpFunc HelperId) {
}
// Generate call to helper
IRNode *GenIR::callHelper(CorInfoHelpFunc HelperID, IRNode *Dst, IRNode *Arg1,
IRNode *Arg2, IRNode *Arg3, IRNode *Arg4,
ReaderAlignType Alignment, bool IsVolatile,
bool NoCtor, bool CanMoveUp) {
IRNode *GenIR::callHelper(CorInfoHelpFunc HelperID, bool MayThrow, IRNode *Dst,
IRNode *Arg1, IRNode *Arg2, IRNode *Arg3,
IRNode *Arg4, ReaderAlignType Alignment,
bool IsVolatile, bool NoCtor, bool CanMoveUp) {
LLVMContext &LLVMContext = *this->JitContext->LLVMContext;
Type *ReturnType =
(Dst == nullptr) ? Type::getVoidTy(LLVMContext) : Dst->getType();
return callHelperImpl(HelperID, ReturnType, Arg1, Arg2, Arg3, Arg4, Alignment,
IsVolatile, NoCtor, CanMoveUp);
return (IRNode *)callHelperImpl(HelperID, MayThrow, ReturnType, Arg1, Arg2,
Arg3, Arg4, Alignment, IsVolatile, NoCtor,
CanMoveUp).getInstruction();
}
IRNode *GenIR::callHelperImpl(CorInfoHelpFunc HelperID, Type *ReturnType,
IRNode *Arg1, IRNode *Arg2, IRNode *Arg3,
IRNode *Arg4, ReaderAlignType Alignment,
bool IsVolatile, bool NoCtor, bool CanMoveUp) {
CallSite GenIR::callHelperImpl(CorInfoHelpFunc HelperID, bool MayThrow,
Type *ReturnType, IRNode *Arg1, IRNode *Arg2,
IRNode *Arg3, IRNode *Arg4,
ReaderAlignType Alignment, bool IsVolatile,
bool NoCtor, bool CanMoveUp) {
ASSERT(HelperID != CORINFO_HELP_UNDEF);
// TODO: We can turn some of these helper calls into intrinsics.
@ -3463,7 +3482,7 @@ IRNode *GenIR::callHelperImpl(CorInfoHelpFunc HelperID, Type *ReturnType,
// This is an intermediate result. Callers must handle
// transitioning to a valid stack type, if appropriate.
IRNode *Call = (IRNode *)LLVMBuilder->CreateCall(Target, Arguments);
CallSite Call = makeCall(Target, MayThrow, Arguments);
if (IsVolatile && isNonVolatileWriteHelperCall(HelperID)) {
// TODO: this is only needed where CLRConfig::INTERNAL_JitLockWrite is set
@ -3500,7 +3519,9 @@ IRNode *GenIR::callRuntimeHandleHelper(CorInfoHelpFunc Helper, IRNode *Arg1,
// Call the helper unconditionally if NullCheckArg is null.
if ((NullCheckArg == nullptr) || isConstantNull(NullCheckArg)) {
return callHelperImpl(Helper, ReturnType, Arg1, Arg2);
const bool MayThrow = true;
return (IRNode *)callHelperImpl(Helper, MayThrow, ReturnType, Arg1, Arg2)
.getInstruction();
}
BasicBlock *SaveBlock = LLVMBuilder->GetInsertBlock();
@ -3509,10 +3530,11 @@ IRNode *GenIR::callRuntimeHandleHelper(CorInfoHelpFunc Helper, IRNode *Arg1,
Value *Compare = LLVMBuilder->CreateIsNull(NullCheckArg, "NullCheck");
// Generate conditional helper call.
bool CallReturns = true;
CallInst *HelperCall =
genConditionalHelperCall(Compare, Helper, ReturnType, Arg1, Arg2,
CallReturns, "RuntimeHandleHelperCall");
const bool MayThrow = true;
const bool CallReturns = true;
CallSite HelperCall =
genConditionalHelperCall(Compare, Helper, MayThrow, ReturnType, Arg1,
Arg2, CallReturns, "RuntimeHandleHelperCall");
// The result is a PHI of NullCheckArg and the generated call.
// The generated code is equivalent to
@ -3523,9 +3545,9 @@ IRNode *GenIR::callRuntimeHandleHelper(CorInfoHelpFunc Helper, IRNode *Arg1,
// return x;
BasicBlock *CurrentBlock = LLVMBuilder->GetInsertBlock();
BasicBlock *CallBlock = HelperCall->getParent();
PHINode *PHI =
mergeConditionalResults(CurrentBlock, NullCheckArg, SaveBlock, HelperCall,
CallBlock, "RuntimeHandle");
PHINode *PHI = mergeConditionalResults(CurrentBlock, NullCheckArg, SaveBlock,
HelperCall.getInstruction(), CallBlock,
"RuntimeHandle");
return (IRNode *)PHI;
}
@ -3546,11 +3568,12 @@ IRNode *GenIR::convertHandle(IRNode *GetTokenNumericNode,
// Get the value that should be assigned to the struct's field, e.g., an
// instance of RuntimeType.
Type *HelperResultType = FieldAddress->getType()->getPointerElementType();
IRNode *HelperResult =
callHelperImpl(HelperID, HelperResultType, GetTokenNumericNode);
const bool MayThrow = true;
CallSite HelperResult =
callHelperImpl(HelperID, MayThrow, HelperResultType, GetTokenNumericNode);
// Assign the field of the result struct.
LLVMBuilder->CreateStore(HelperResult, FieldAddress);
LLVMBuilder->CreateStore(HelperResult.getInstruction(), FieldAddress);
const bool IsVolatile = false;
return (IRNode *)LLVMBuilder->CreateLoad(Result, IsVolatile);
@ -3652,7 +3675,8 @@ IRNode *GenIR::genNewMDArrayCall(ReaderCallTargetData *CallTargetData,
getUnmanagedPointerType(FunctionType));
// Replace the old call instruction with the new one.
*CallNode = (IRNode *)LLVMBuilder->CreateCall(Callee, Arguments);
const bool MayThrow = true;
*CallNode = (IRNode *)makeCall(Callee, MayThrow, Arguments).getInstruction();
return *CallNode;
}
@ -3704,8 +3728,10 @@ IRNode *GenIR::genNewObjThisArg(ReaderCallTargetData *CallTargetData,
// Create the address operand for the newobj helper.
CorInfoHelpFunc HelperId = getNewHelper(CallTargetData->getResolvedToken());
const bool MayThrow = true;
Value *ThisPointer =
callHelperImpl(HelperId, ThisType, CallTargetData->getClassHandleNode());
callHelperImpl(HelperId, MayThrow, ThisType,
CallTargetData->getClassHandleNode()).getInstruction();
return (IRNode *)ThisPointer;
}
@ -3736,7 +3762,7 @@ IRNode *GenIR::genNewObjReturnNode(ReaderCallTargetData *CallTargetData,
return ThisArg;
}
IRNode *GenIR::genCall(ReaderCallTargetData *CallTargetInfo,
IRNode *GenIR::genCall(ReaderCallTargetData *CallTargetInfo, bool MayThrow,
std::vector<IRNode *> Args, IRNode **CallNode) {
IRNode *Call = nullptr, *ReturnNode = nullptr;
IRNode *TargetNode = CallTargetInfo->getCallTargetNode();
@ -3815,7 +3841,7 @@ IRNode *GenIR::genCall(ReaderCallTargetData *CallTargetInfo,
ABICallSignature ABICallSig(Signature, *this, *JitContext->TheABIInfo);
Value *ResultNode = ABICallSig.emitCall(
*this, (Value *)TargetNode, Arguments,
*this, (Value *)TargetNode, MayThrow, Arguments,
(Value *)CallTargetInfo->getIndirectionCellNode(), (Value **)&Call);
// Add VarArgs cookie to outgoing param list
@ -3907,7 +3933,9 @@ Value *GenIR::genConvertOverflowCheck(Value *Source, IntegerType *TargetTy,
}
// Call the helper to convert to int.
Source = callHelperImpl(Helper, HelperResultTy, (IRNode *)Source);
const bool MayThrow = true;
Source = callHelperImpl(Helper, MayThrow, HelperResultTy, (IRNode *)Source)
.getInstruction();
SourceTy = HelperResultTy;
// The result of the helper call already has the requested signedness.
@ -4372,7 +4400,10 @@ IRNode *GenIR::unbox(CORINFO_RESOLVED_TOKEN *ResolvedToken, IRNode *Object,
// Call helper to do the type check and get the address of the unbox payload.
Type *PtrTy = getType(CorInfoType::CORINFO_TYPE_BYREF, ClassHandle);
IRNode *Result = callHelperImpl(HelperId, PtrTy, ClassHandleArgument, Object);
const bool MayThrow = true;
IRNode *Result =
(IRNode *)callHelperImpl(HelperId, MayThrow, PtrTy, ClassHandleArgument,
Object).getInstruction();
// If requested, load the object onto the evaluation stack.
if (AndLoad) {
@ -4417,26 +4448,26 @@ void GenIR::switchOpcode(IRNode *Opr) {
void GenIR::throwOpcode(IRNode *Arg1) {
// Using a call for now; this will need to be invoke
// when we get EH flow properly modeled.
CallInst *ThrowCall =
(CallInst *)callHelper(CORINFO_HELP_THROW, nullptr, Arg1);
Type *Void = Type::getVoidTy(*JitContext->LLVMContext);
const bool MayThrow = true;
CallSite ThrowCall = callHelperImpl(CORINFO_HELP_THROW, MayThrow, Void, Arg1);
// Annotate the helper
ThrowCall->setDoesNotReturn();
ThrowCall.setDoesNotReturn();
}
CallInst *GenIR::genConditionalHelperCall(Value *Condition,
CorInfoHelpFunc HelperId,
Type *ReturnType, IRNode *Arg1,
IRNode *Arg2, bool CallReturns,
const Twine &CallBlockName) {
CallSite GenIR::genConditionalHelperCall(
Value *Condition, CorInfoHelpFunc HelperId, bool MayThrow, Type *ReturnType,
IRNode *Arg1, IRNode *Arg2, bool CallReturns, const Twine &CallBlockName) {
// Create the call block and fill it in.
BasicBlock *CallBlock = createPointBlock(CallBlockName);
IRBuilder<>::InsertPoint SavedInsertPoint = LLVMBuilder->saveIP();
LLVMBuilder->SetInsertPoint(CallBlock);
CallInst *HelperCall =
(CallInst *)callHelperImpl(HelperId, ReturnType, Arg1, Arg2);
CallSite HelperCall =
callHelperImpl(HelperId, MayThrow, ReturnType, Arg1, Arg2);
if (!CallReturns) {
HelperCall->setDoesNotReturn();
HelperCall.setDoesNotReturn();
LLVMBuilder->CreateUnreachable();
}
LLVMBuilder->restoreIP(SavedInsertPoint);
@ -4453,9 +4484,10 @@ void GenIR::genConditionalThrow(Value *Condition, CorInfoHelpFunc HelperId,
const Twine &ThrowBlockName) {
IRNode *Arg1 = nullptr, *Arg2 = nullptr;
Type *ReturnType = Type::getVoidTy(*JitContext->LLVMContext);
bool CallReturns = false;
genConditionalHelperCall(Condition, HelperId, ReturnType, Arg1, Arg2,
CallReturns, ThrowBlockName);
const bool MayThrow = true;
const bool CallReturns = false;
genConditionalHelperCall(Condition, HelperId, MayThrow, ReturnType, Arg1,
Arg2, CallReturns, ThrowBlockName);
}
IRNode *GenIR::genNullCheck(IRNode *Node) {
@ -4943,8 +4975,10 @@ IRNode *GenIR::loadVirtFunc(IRNode *Arg1, CORINFO_RESOLVED_TOKEN *ResolvedToken,
Type *Ty =
Type::getIntNTy(*this->JitContext->LLVMContext, TargetPointerSizeInBits);
IRNode *CodeAddress = callHelperImpl(CORINFO_HELP_VIRTUAL_FUNC_PTR, Ty, Arg1,
TypeToken, MethodToken);
const bool MayThrow = true;
IRNode *CodeAddress =
(IRNode *)callHelperImpl(CORINFO_HELP_VIRTUAL_FUNC_PTR, MayThrow, Ty,
Arg1, TypeToken, MethodToken).getInstruction();
return CodeAddress;
}
@ -5335,8 +5369,9 @@ IRNode *GenIR::newArr(CORINFO_RESOLVED_TOKEN *ResolvedToken, IRNode *Arg1) {
getType(CorInfoType::CORINFO_TYPE_CLASS, ResolvedToken->hClass);
Value *Destination = Constant::getNullValue(ArrayType);
return callHelper(getNewArrHelper(ElementType), (IRNode *)Destination, Token,
NumOfElements);
const bool MayThrow = true;
return callHelper(getNewArrHelper(ElementType), MayThrow,
(IRNode *)Destination, Token, NumOfElements);
}
// CastOp - Generates code for castclass or isinst.
@ -5388,9 +5423,11 @@ IRNode *GenIR::castOp(CORINFO_RESOLVED_TOKEN *ResolvedToken, IRNode *ObjRefNode,
// Generate the helper call or intrinsic
const bool IsVolatile = false;
const bool DoesNotInvokeStaticCtor = Optimize;
return callHelperImpl(HelperId, ResultType, ClassHandleNode, ObjRefNode,
nullptr, nullptr, Reader_AlignUnknown, IsVolatile,
DoesNotInvokeStaticCtor);
const bool MayThrow = true;
return (IRNode *)callHelperImpl(HelperId, MayThrow, ResultType,
ClassHandleNode, ObjRefNode, nullptr, nullptr,
Reader_AlignUnknown, IsVolatile,
DoesNotInvokeStaticCtor).getInstruction();
}
// Override the cast class optimization
@ -5416,7 +5453,8 @@ bool GenIR::abs(IRNode *Argument, IRNode **Result) {
Type *Types[] = {Ty};
Value *FAbs = Intrinsic::getDeclaration(JitContext->CurrentModule,
Intrinsic::fabs, Types);
Value *Abs = LLVMBuilder->CreateCall(FAbs, Argument);
bool MayThrow = false;
Value *Abs = makeCall(FAbs, MayThrow, Argument).getInstruction();
*Result = (IRNode *)Abs;
return true;
}
@ -5438,9 +5476,10 @@ IRNode *GenIR::localAlloc(IRNode *Arg, bool ZeroInit) {
// Zero the allocated region if so requested.
if (ZeroInit) {
Value *ZeroByte = ConstantInt::get(Context, APInt(8, 0, true));
const bool MayThrow = false;
Type *VoidTy = Type::getVoidTy(Context);
callHelperImpl(CORINFO_HELP_MEMSET, VoidTy, (IRNode *)LocAlloc,
Value *ZeroByte = ConstantInt::get(Context, APInt(8, 0, true));
callHelperImpl(CORINFO_HELP_MEMSET, MayThrow, VoidTy, (IRNode *)LocAlloc,
(IRNode *)ZeroByte, Arg);
}