Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[NativeAOT-LLVM] Exception handling: dispatch #2145

Merged
8 changes: 4 additions & 4 deletions src/coreclr/jit/compiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -4362,6 +4362,8 @@ class Compiler
bool isExplicitTailCall,
IL_OFFSET ilOffset = BAD_IL_OFFSET);

void impResolveToken(const BYTE* addr, CORINFO_RESOLVED_TOKEN* pResolvedToken, CorInfoTokenKind kind);

//=========================================================================
// PROTECTED
//=========================================================================
Expand All @@ -4382,8 +4384,6 @@ class Compiler
bool impIsPrimitive(CorInfoType type);
bool impILConsumesAddr(const BYTE* codeAddr);

void impResolveToken(const BYTE* addr, CORINFO_RESOLVED_TOKEN* pResolvedToken, CorInfoTokenKind kind);

void impPushOnStack(GenTree* tree, typeInfo ti);
void impPushNullObjRefOnStack();
StackEntry impPopStack();
Expand Down Expand Up @@ -6635,6 +6635,8 @@ class Compiler

AddCodeDsc* fgFindExcptnTarget(SpecialCodeKind kind, unsigned refData);

bool fgIsThrowHlpBlk(BasicBlock* block);

bool fgUseThrowHelperBlocks();

AddCodeDsc* fgGetAdditionalCodeDescriptors()
Expand All @@ -6645,8 +6647,6 @@ class Compiler
private:
bool fgIsCodeAdded();

bool fgIsThrowHlpBlk(BasicBlock* block);

#if !FEATURE_FIXED_OUT_ARGS
unsigned fgThrowHlpBlkStkLevel(BasicBlock* block);
#endif // !FEATURE_FIXED_OUT_ARGS
Expand Down
6 changes: 4 additions & 2 deletions src/coreclr/jit/compiler.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2705,7 +2705,8 @@ inline bool Compiler::fgIsThrowHlpBlk(BasicBlock* block)
(call->AsCall()->gtCallMethHnd == eeFindHelper(CORINFO_HELP_THROWDIVZERO)) ||
(call->AsCall()->gtCallMethHnd == eeFindHelper(CORINFO_HELP_THROW_ARGUMENTEXCEPTION)) ||
(call->AsCall()->gtCallMethHnd == eeFindHelper(CORINFO_HELP_THROW_ARGUMENTOUTOFRANGEEXCEPTION)) ||
(call->AsCall()->gtCallMethHnd == eeFindHelper(CORINFO_HELP_OVERFLOW))))
(call->AsCall()->gtCallMethHnd == eeFindHelper(CORINFO_HELP_OVERFLOW)) ||
(call->AsCall()->gtCallMethHnd == eeFindHelper(CORINFO_HELP_THROWNULLREF))))
{
return false;
}
Expand All @@ -2719,7 +2720,8 @@ inline bool Compiler::fgIsThrowHlpBlk(BasicBlock* block)
if (block == add->acdDstBlk)
{
return add->acdKind == SCK_RNGCHK_FAIL || add->acdKind == SCK_DIV_BY_ZERO || add->acdKind == SCK_OVERFLOW ||
add->acdKind == SCK_ARG_EXCPN || add->acdKind == SCK_ARG_RNG_EXCPN;
add->acdKind == SCK_ARG_EXCPN || add->acdKind == SCK_ARG_RNG_EXCPN ||
add->acdKind == SCK_NULL_REF_EXCPN;
}
}

Expand Down
2 changes: 2 additions & 0 deletions src/coreclr/jit/fgdiagnostic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1660,6 +1660,8 @@ bool Compiler::fgDumpFlowGraph(Phases phase, PhasePosition pos)
case EH_HANDLER_FAULT_WAS_FINALLY:
handlerType = "fault-was-finally";
break;
default:
unreached();
}
sprintf_s(name, sizeof(name), "EH#%u %s", XTnum, handlerType);
rgnGraph.Insert(name, RegionGraph::RegionType::EH, ehDsc->ebdHndBeg, ehDsc->ebdHndLast);
Expand Down
3 changes: 2 additions & 1 deletion src/coreclr/jit/jiteh.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ enum EHHandlerType
EH_HANDLER_FILTER,
EH_HANDLER_FAULT,
EH_HANDLER_FINALLY,
EH_HANDLER_FAULT_WAS_FINALLY
EH_HANDLER_FAULT_WAS_FINALLY,
EH_HANDLER_COUNT
};

// ToCORINFO_EH_CLAUSE_FLAGS: Convert an internal EHHandlerType to a CORINFO_EH_CLAUSE_FLAGS value
Expand Down
18 changes: 12 additions & 6 deletions src/coreclr/jit/llvm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ enum class EEApiId
{
GetMangledMethodName,
GetSymbolMangledName,
GetEHDispatchFunctionName,
GetTypeName,
AddCodeReloc,
IsRuntimeImport,
Expand Down Expand Up @@ -102,7 +103,6 @@ Llvm::Llvm(Compiler* compiler)
_info(compiler->info),
_sigInfo(compiler->info.compMethodInfo->args),
_builder(_llvmContext),
_prologBuilder(_llvmContext),
_blkToLlvmBlksMap(compiler->getAllocator(CMK_Codegen)),
_sdsuMap(compiler->getAllocator(CMK_Codegen)),
_localsMap(compiler->getAllocator(CMK_Codegen)),
Expand Down Expand Up @@ -167,6 +167,7 @@ GCInfo* Llvm::getGCInfo()
{
_gcInfo = new (_compiler->getAllocator(CMK_GC)) GCInfo(_compiler);
}

return _gcInfo;
}

Expand Down Expand Up @@ -369,8 +370,8 @@ const HelperFuncInfo& Llvm::getHelperFuncInfo(CorInfoHelpFunc helperFunc)
// For WASM, currently implemented in the bootstrapper...
{ FUNC(CORINFO_HELP_THROW) CORINFO_TYPE_VOID, { CORINFO_TYPE_PTR } },

// (Not) implemented in "Runtime\EHHelpers.cpp"
{ FUNC(CORINFO_HELP_RETHROW) CORINFO_TYPE_VOID, { } },
// Implemented in "Runtime.Base\src\System\Runtime\ExceptionHandling.wasm.cs".
{ FUNC(CORINFO_HELP_RETHROW) CORINFO_TYPE_VOID, { CORINFO_TYPE_PTR } },

// Implemented in "Runtime\MiscHelpers.cpp".
{ FUNC(CORINFO_HELP_USER_BREAKPOINT) CORINFO_TYPE_VOID, { } },
Expand Down Expand Up @@ -641,11 +642,11 @@ unsigned Llvm::padNextOffset(CorInfoType corInfoType, CORINFO_CLASS_HANDLE struc

[[noreturn]] void Llvm::failFunctionCompilation()
{
for (Function* llvmFunc : m_functions)
for (FunctionInfo& funcInfo : m_functions)
{
if (llvmFunc != nullptr)
if (funcInfo.LlvmFunction != nullptr)
{
llvmFunc->deleteBody();
funcInfo.LlvmFunction->deleteBody();
}
}

Expand All @@ -668,6 +669,11 @@ const char* Llvm::GetMangledSymbolName(void* symbol)
return CallEEApi<EEApiId::GetSymbolMangledName, const char*>(symbol);
}

const char* Llvm::GetEHDispatchFunctionName(CORINFO_EH_CLAUSE_FLAGS handlerType)
{
return CallEEApi<EEApiId::GetEHDispatchFunctionName, const char*>(handlerType);
}

const char* Llvm::GetTypeName(CORINFO_CLASS_HANDLE typeHandle)
{
return CallEEApi<EEApiId::GetTypeName, const char*>(typeHandle);
Expand Down
80 changes: 61 additions & 19 deletions src/coreclr/jit/llvm.h
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,22 @@ struct LlvmBlockRange
{
llvm::BasicBlock* FirstBlock;
llvm::BasicBlock* LastBlock;
INDEBUG(unsigned Count = 1);

LlvmBlockRange(llvm::BasicBlock* llvmBlock) : FirstBlock(llvmBlock), LastBlock(llvmBlock)
{
}
};

typedef JitHashTable<unsigned, JitSmallPrimitiveKeyFuncs<unsigned>, llvm::AllocaInst*> AllocaMap;

struct FunctionInfo
{
Function* LlvmFunction;
union {
llvm::AllocaInst** Allocas; // Dense "lclNum -> Alloca*" mapping used for the main function.
AllocaMap* AllocaMap; // Sparse "lclNum -> Alloca*" mapping used for funclets.
};
};

// TODO: We should create a Static... class to manage the globals and their lifetimes.
Expand All @@ -125,25 +141,29 @@ class Llvm

CORINFO_SIG_INFO _sigInfo; // sigInfo of function being compiled
LIR::Range* _currentRange;
BasicBlock* _currentBlock;
BasicBlock* m_currentBlock;
DebugInfo _currentOffset;
llvm::IRBuilder<> _builder;
llvm::IRBuilder<> _prologBuilder;
JitHashTable<BasicBlock*, JitPtrKeyFuncs<BasicBlock>, LlvmBlockRange> _blkToLlvmBlksMap;
JitHashTable<GenTree*, JitPtrKeyFuncs<GenTree>, Value*> _sdsuMap;
JitHashTable<SSAName, SSAName, Value*> _localsMap;
std::vector<PhiPair> _phiPairs;
std::vector<AllocaInst*> m_allocas;
std::vector<Function*> m_functions;
std::vector<FunctionInfo> m_functions;
std::vector<llvm::BasicBlock*> m_EHDispatchLlvmBlocks;

// Codegen emit context.
unsigned m_currentLlvmFunctionIndex = ROOT_FUNC_IDX;
unsigned m_currentProtectedRegionIndex = EHblkDsc::NO_ENCLOSING_INDEX;
LlvmBlockRange* m_currentLlvmBlocks = nullptr;

// DWARF
llvm::DILocation* _currentOffsetDiLocation;
llvm::DISubprogram* _debugFunction;
DebugMetadata _debugMetadata;
JitHashTable<std::string, JitStdStringKeyFuncs, DebugMetadata> _debugMetadataMap;

unsigned _shadowStackLocalsSize;
unsigned _originalShadowStackLclNum = BAD_VAR_NUM;
unsigned _shadowStackLclNum = BAD_VAR_NUM;
unsigned _retAddressLclNum = BAD_VAR_NUM;
unsigned _llvmArgCount;
Expand All @@ -165,7 +185,7 @@ class Llvm
}
BasicBlock* CurrentBlock() const
{
return _currentBlock;
return m_currentBlock;
}

GCInfo* getGCInfo();
Expand All @@ -188,6 +208,7 @@ class Llvm
//
const char* GetMangledMethodName(CORINFO_METHOD_HANDLE methodHandle);
const char* GetMangledSymbolName(void* symbol);
const char* GetEHDispatchFunctionName(CORINFO_EH_CLAUSE_FLAGS handlerType);
const char* GetTypeName(CORINFO_CLASS_HANDLE typeHandle);
void AddCodeReloc(void* handle);
bool IsRuntimeImport(CORINFO_METHOD_HANDLE methodHandle);
Expand Down Expand Up @@ -237,6 +258,8 @@ class Llvm
void lowerFieldOfDependentlyPromotedStruct(GenTree* node);
void ConvertShadowStackLocalNode(GenTreeLclVarCommon* node);
void lowerCall(GenTreeCall* callNode);
void lowerRethrow(GenTreeCall* callNode);
void lowerCatchArg(GenTree* catchArgNode);
void lowerIndir(GenTreeIndir* indirNode);
void lowerStoreBlk(GenTreeBlk* storeBlkNode);
void lowerStoreDynBlk(GenTreeStoreDynBlk* storeDynBlkNode);
Expand All @@ -251,9 +274,15 @@ class Llvm

GenTree* createStoreNode(var_types nodeType, GenTree* addr, GenTree* data);
GenTree* createShadowStackStoreNode(var_types storeType, GenTree* addr, GenTree* data);
GenTree* insertShadowStackAddr(GenTree* insertBefore, ssize_t offset);
GenTree* insertShadowStackAddr(GenTree* insertBefore, ssize_t offset, unsigned shadowStackLclNum);

bool isShadowFrameLocal(LclVarDsc* varDsc) const;
bool isFuncletParameter(unsigned lclNum) const;

unsigned getCurrentShadowFrameSize() const;
unsigned getShadowFrameSize(unsigned hndIndex) const;
unsigned getOriginalShadowFrameSize() const;
unsigned getCatchArgOffset() const;

// ================================================================================================================
// | Codegen |
Expand All @@ -263,13 +292,14 @@ class Llvm
void Compile();

private:
const int ROOT_FUNC_IDX = 0;
const unsigned ROOT_FUNC_IDX = 0;

bool initializeFunctions();
void generateProlog();
void initializeLocals();
void generateBlock(BasicBlock* block);
void generateEHDispatch();
Value* generateEHDispatchTable(Function* llvmFunc, unsigned innerEHIndex, unsigned outerEHIndex);
void fillPhis();

Value* getGenTreeValue(GenTree* node);
Expand Down Expand Up @@ -304,15 +334,13 @@ class Llvm
void buildBinaryOperation(GenTree* node);
void buildShift(GenTreeOp* node);
void buildReturn(GenTree* node);
void buildCatchArg(GenTree* node);
void buildJTrue(GenTree* node);
void buildSwitch(GenTreeUnOp* switchNode);
void buildNullCheck(GenTreeIndir* nullCheckNode);
void buildBoundsCheck(GenTreeBoundsChk* boundsCheck);
void buildCkFinite(GenTreeUnOp* ckNode);

void buildCallFinally(BasicBlock* block);
void buildCatchReturn(BasicBlock* block);

void storeObjAtAddress(Value* baseAddress, Value* data, StructDesc* structDesc);
unsigned buildMemCpy(Value* baseAddress, unsigned startOffset, unsigned endOffset, Value* srcAddress);
Expand All @@ -322,39 +350,53 @@ class Llvm
void emitNullCheckForIndir(GenTreeIndir* indir, Value* addrValue);
Value* emitCheckedArithmeticOperation(llvm::Intrinsic::ID intrinsicId, Value* op1Value, Value* op2Value);
Value* emitHelperCall(CorInfoHelpFunc helperFunc, ArrayRef<Value*> sigArgs = { });
Value* emitCallOrInvoke(llvm::FunctionCallee callee, ArrayRef<Value*> args);
llvm::CallBase* emitCallOrInvoke(llvm::FunctionCallee callee, ArrayRef<Value*> args);

FunctionType* getFunctionType();
Function* getOrCreateLlvmFunction(const char* symbolName, GenTreeCall* call);
FunctionType* createFunctionTypeForCall(GenTreeCall* call);
FunctionType* createFunctionTypeForHelper(CorInfoHelpFunc helperFunc);

Value* getOrCreateExternalSymbol(const char* symbolName, Type* symbolType = nullptr);
llvm::GlobalVariable* getOrCreateExternalSymbol(const char* symbolName, Type* symbolType = nullptr);
llvm::GlobalVariable* getOrCreateSymbol(CORINFO_GENERIC_HANDLE symbolHandle, Type* symbolType = nullptr);
Value* emitSymbolRef(CORINFO_GENERIC_HANDLE symbolHandle);
CORINFO_GENERIC_HANDLE getSymbolHandleForClassToken(mdToken token);

Instruction* getCast(Value* source, Type* targetType);
Value* castIfNecessary(Value* source, Type* targetType, llvm::IRBuilder<>* builder = nullptr);
Value* gepOrAddr(Value* addr, unsigned offset);
Value* getShadowStack();
Value* getShadowStackForCallee();
Value* getOriginalShadowStack();

DebugMetadata getOrCreateDebugMetadata(const char* documentFileName);
llvm::DILocation* createDebugFunctionAndDiLocation(struct DebugMetadata debugMetadata, unsigned int lineNo);
llvm::DILocation* getArtificialDebugLocation();

void setCurrentEmitContextForBlock(BasicBlock* block);
void setCurrentEmitContext(unsigned funcIdx, unsigned tryIndex, LlvmBlockRange* llvmBlock);
unsigned getCurrentLlvmFunctionIndex() const;
unsigned getCurrentProtectedRegionIndex() const;
LlvmBlockRange* getCurrentLlvmBlocks() const;

Function* getRootLlvmFunction();
Function* getCurrentLlvmFunction();
Function* getLlvmFunctionForIndex(unsigned funcIdx);
unsigned getLlvmFunctionIndexForBlock(BasicBlock* block);
void setCurrentLlvmFunctionForBlock(BasicBlock* block);
FunctionInfo& getLlvmFunctionInfoForIndex(unsigned funcIdx);
unsigned getLlvmFunctionIndexForBlock(BasicBlock* block) const;
unsigned getLlvmFunctionIndexForProtectedRegion(unsigned tryIndex) const;

llvm::BasicBlock* createInlineLlvmBlock();
llvm::BasicBlock* getEHDispatchLlvmBlockForBlock(BasicBlock* block);
llvm::BasicBlock* getCurrentLlvmBlock() const;
LlvmBlockRange* getLlvmBlocksForBlock(BasicBlock* block);
llvm::BasicBlock* getFirstLlvmBlockForBlock(BasicBlock* block);
llvm::BasicBlock* getLastLlvmBlockForBlock(BasicBlock* block);
void setLastLlvmBlockForBlock(BasicBlock* block, llvm::BasicBlock* llvmBlock);

AllocaInst* getLocalAddr(unsigned lclNum);
unsigned int getTotalLocalOffset();
};
llvm::BasicBlock* getOrCreatePrologLlvmBlockForFunction(unsigned funcIdx);

bool isReachable(BasicBlock* block) const;
BasicBlock* getFirstBlockForFunction(unsigned funcIdx) const;

Value* getLocalAddr(unsigned lclNum);
Value* getOrCreateAllocaForLocalInFunclet(unsigned lclNum);
};
#endif /* End of _LLVM_H_ */
Loading