Skip to content
This repository has been archived by the owner on Mar 15, 2022. It is now read-only.

Commit

Permalink
Merge pull request #694 from JosephTremoulet/ReadFilter
Browse files Browse the repository at this point in the history
Add support for EH filters
  • Loading branch information
JosephTremoulet committed Jul 10, 2015
2 parents 6334a18 + b0aeb3d commit 065c618
Show file tree
Hide file tree
Showing 6 changed files with 581 additions and 88 deletions.
3 changes: 3 additions & 0 deletions include/Reader/reader.h
Original file line number Diff line number Diff line change
Expand Up @@ -2947,6 +2947,9 @@ class ReaderBase {
// Called between building the flow graph and inserting the IR
virtual void readerMiddlePass(void) = 0;

// Called after reading all MSIL, before removing unreachable blocks
virtual void readerPostVisit() = 0;

// Called when reader has finished processing method.
virtual void readerPostPass(bool IsImportOnly) = 0;

Expand Down
120 changes: 115 additions & 5 deletions include/Reader/readerir.h
Original file line number Diff line number Diff line change
Expand Up @@ -324,9 +324,7 @@ class GenIR : public ReaderBase {
IRNode *conv(ReaderBaseNS::ConvOpcode Opcode, IRNode *Source) override;

void dup(IRNode *Opr, IRNode **Result1, IRNode **Result2) override;
void endFilter(IRNode *Arg1) override {
throw NotYetImplementedException("endFilter");
};
void endFilter(IRNode *Arg1) override;

FlowGraphEdgeList *fgNodeGetSuccessorList(FlowGraphNode *FgNode) override;
FlowGraphEdgeList *fgNodeGetPredecessorList(FlowGraphNode *FgNode) override;
Expand Down Expand Up @@ -523,6 +521,9 @@ class GenIR : public ReaderBase {
// Called between building the flow graph and inserting the IR
void readerMiddlePass(void) override;

// Called after reading all MSIL, before removing unreachable blocks
void readerPostVisit() override;

// Called when reader has finished processing method.
void readerPostPass(bool IsImportOnly) override;

Expand Down Expand Up @@ -591,7 +592,7 @@ class GenIR : public ReaderBase {
llvm::LandingPadInst *createLandingPad(EHRegion *TryRegion,
llvm::LandingPadInst *OuterLandingPad);

/// Generate a single catch clause for a protected region
/// Generate a single catch clause for a protected region.
///
/// \param CatchRegion Handler that needs a clause and dispatch code
/// \param LandingPad \p LandingPadInst under construction
Expand All @@ -602,6 +603,32 @@ class GenIR : public ReaderBase {
void genCatchDispatch(EHRegion *CatchRegion, llvm::LandingPadInst *LandingPad,
llvm::Value *FauxException, llvm::Value *Selector);

/// Generate landingpad code for a single filter.
///
/// \param FilterRegion Filter that needs a clause and dispatch code
/// \param LandingPad \p LandingPadInst under construction
/// \param FauxException \p Value representing the caught exception in the
/// dispatch code
/// \param Selector \p Value representing the exception selector in the
/// dispatch code
void genFilterDispatch(EHRegion *FilterRegion,
llvm::LandingPadInst *LandingPad,
llvm::Value *FauxException, llvm::Value *Selector);

/// Helper for generating catch/filter dispatch.
///
/// \param HandlerRegion Handler that needs a clause and dispatch code
/// \param DoEnter \p Value dictating whether to dispatch to the
/// handler
/// \param EnterBlockName Name for the BasicBlock that will enter the handler
/// \param ExceptionType \p Type of the formal for the exception object
/// \param FauxException \p Value representing the caught exception in the
/// dispatch code
void genHandlerDispatch(EHRegion *HandlerRegion, llvm::Value *DoEnter,
const llvm::Twine &EnterBlockName,
llvm::Type *ExceptionType,
llvm::Value *FauxException);

IRNode *fgNodeFindStartLabel(FlowGraphNode *Block) override;

BranchList *fgGetLabelBranchList(IRNode *LabelNode) override {
Expand Down Expand Up @@ -1453,6 +1480,10 @@ class GenIR : public ReaderBase {
/// the thread pointer.
void insertIRForUnmanagedCallFrame();

/// \brief Apply any function-level attributes needed to indicate an
/// unmanaged call, on root function and any outlined filters.
void setAttributesForUnmanagedCallFrame(llvm::Function *F);

/// \brief Create the @gc.safepoint_poll() method
/// Creates the @gc.safepoint_poll() method and insertes it into the
/// current module. This helper is required by the LLVM GC-Statepoint
Expand Down Expand Up @@ -1585,12 +1616,86 @@ class GenIR : public ReaderBase {
std::vector<std::pair<uint32_t, llvm::Type *>> &OverlapFields,
std::vector<llvm::Type *> &Fields);

/// Access the address of a root function local. If the current region is a
/// filter (which will be outlined), insert appropriate code in the root
/// function to escape the address and in the filter to recover it.
///
/// \param RootFrameAddres Unescaped local alloca in the root function.
/// \returns A \p Value which may be used in the current function (root or
/// filter) to represent the local's address.
llvm::Value *getFrameAddress(llvm::Value *RootFrameAddress);

/// Access the address of the home location of an MSIL-level argument of the
/// root function. Add a home location if necessary. If the current region
/// is a filter (which will be outlined), insert appropriate code in the root
/// function to escape the address and in the filter to recover it.
///
/// \param Ordinal Ordinal number (as would be used in MSIL ldarg etc.)
/// indicating which parameter
/// \returns A \p Value which may be used in the current function (root or
/// filter) to represent the argument's address.
llvm::Value *getArgumentAddress(uint32_t Ordinal);

/// Access an IR-level parameter of the root function. If the current region
/// is a filter (which will be outlined), insert appropriate code in the root
/// function to spill and escape the parameter and in the filter to recover
/// it.
///
/// \param Parameter The \p Argument whose value is required
/// \returns A \p Value which may be used in the current function (root or
/// filter) to represent the parameter's value.
llvm::Value *getReadonlyParameter(llvm::Argument *Parameter);

/// Access an IR-level parameter of the root function. If the current region
/// is a filter (which will be outlined), insert appropriate code in the root
/// function to spill and escape the parameter and in the filter to recover
/// it.
///
/// \param Index The IR-level index of the parameter whose value is required
/// \returns A \p Value which may be used in the current function (root or
/// filter) to represent the parameter's value.
llvm::Value *getReadonlyParameter(uint32_t Index);

/// Get a call to @llvm.framerecover that can be used to reference the given
/// root function alloca in the given filter. Also marks the root address
/// as escaping.
///
/// \param RootAddress The alloca in the root function that the filter
/// needs to reference.
/// \param FilterFunction The outlined filter function that needs to access
/// the address.
/// \returns A \p Value which may be used in the filter function to represent
/// the given address.
llvm::Value *recoverAddress(llvm::Value *RootAddress,
llvm::Function *FilterFunction);

/// Get the outline filter function (if any) associated with the current
/// region.
///
/// \returns The \p Function to which the code at the current point will be
/// outlined.
llvm::Function *getCurrentFilter();

/// Record that the given address needs to escape by call to
/// @llvm.frameescape, and return the index that may be used to recover it by
/// call to @llvm.framerecover. May be called multiple times for the same
/// frame address; will return the same index.
///
/// \param FrameAddress Alloca in the root function
/// \returns Index appropriate to pass to @llvm.framerecover in
/// an outlined filter.
int32_t frameEscape(llvm::Value *FrameAddress);

/// Emit a call to @llvm.frameescape if any allocas have been marked as
/// escaping.
void emitFrameEscapeIfNeeded();

private:
LLILCJitContext *JitContext;
ABIInfo *TheABIInfo;
ReaderMethodSignature MethodSignature;
ABIMethodSignature ABIMethodSig;
llvm::Function *Function;
llvm::Function *RootFunction;
// The LLVMBuilder has a notion of a current insertion point. During the
// first-pass flow-graph construction, each method sets the insertion point
// explicitly before inserting IR (the fg- methods typically take an
Expand Down Expand Up @@ -1628,12 +1733,17 @@ class GenIR : public ReaderBase {
///< first-class
///< aggregates in LLVM IR
///< we are generating.
llvm::DenseMap<llvm::Value *, int32_t> FrameEscapes;
llvm::SmallVector<llvm::Value *, 4> FrameEscapeArgs;
std::map<std::pair<llvm::Value *, llvm::Function *>, llvm::Value *>
FrameRecovers;
FlowGraphNode *FirstMSILBlock;
llvm::BasicBlock *UnreachableContinuationBlock;
llvm::Function *PersonalityFunction; ///< Personality routine reported on
///< LandingPads in this function.
///< Lazily created/cached.
bool KeepGenericContextAlive;
bool HasUnmanagedCallFrame;
bool NeedsSecurityObject;
bool DoneBuildingFlowGraph;
llvm::BasicBlock *EntryBlock;
Expand Down
5 changes: 2 additions & 3 deletions lib/Jit/LLILCJit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -399,8 +399,7 @@ bool LLILCJit::readMethod(LLILCJitContext *JitContext) {
return false;
}

Function *Func = JitContext->CurrentModule->getFunction(FuncName);
bool IsOk = !verifyFunction(*Func, &dbgs());
bool IsOk = !verifyModule(*JitContext->CurrentModule, &dbgs());
assert(IsOk && "verification failed");

if (IsOk) {
Expand All @@ -415,7 +414,7 @@ bool LLILCJit::readMethod(LLILCJitContext *JitContext) {
}

if (DumpLevel == ::DumpLevel::VERBOSE) {
Func->dump();
JitContext->CurrentModule->dump();
}

return IsOk;
Expand Down
2 changes: 1 addition & 1 deletion lib/Reader/abisignature.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,7 @@ CallSite ABICallSignature::emitUnmanagedCall(GenIR &Reader, Value *Target,
// 1) Address of the GC mode field
// 2) Address of the thread trap global
// 3) Address of CORINFO_HELP_STOP_FOR_GC
Module *M = Reader.Function->getParent();
Module *M = Reader.RootFunction->getParent();
Type *CallTypeArgs[] = {Target->getType()};
Function *CallIntrinsic = Intrinsic::getDeclaration(
M, Intrinsic::experimental_gc_statepoint, CallTypeArgs);
Expand Down
7 changes: 6 additions & 1 deletion lib/Reader/reader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3026,7 +3026,8 @@ void ReaderBase::fgBuildPhase1(FlowGraphNode *Block, uint8_t *ILInput,
break;

case ReaderBaseNS::CEE_ENDFILTER:
// Do nothing...
fgNodeSetEndMSILOffset(Block, NextOffset);
Block = makeFlowGraphNode(NextOffset, Block);
break;

case ReaderBaseNS::CEE_ENDFINALLY: {
Expand Down Expand Up @@ -8070,6 +8071,10 @@ void ReaderBase::msilToIR(void) {
}
}

// Give client a chance to do any bookkeeping necessary after reading MSIL
// for all blocks but before removing unreachable ones.
readerPostVisit();

// Remove blocks that weren't marked as visited.
fgRemoveUnusedBlocks(FgHead);

Expand Down
Loading

0 comments on commit 065c618

Please sign in to comment.