forked from M-Labs/artiq
compiler: generate appropriate landingpad IR
When used together with modified personality function, we got ~20% performance improvement in exception unwinding with zynq.
This commit is contained in:
parent
5e1847e7c1
commit
9f90088fa6
@ -1347,6 +1347,7 @@ class LandingPad(Terminator):
|
|||||||
def __init__(self, cleanup, name=""):
|
def __init__(self, cleanup, name=""):
|
||||||
super().__init__([cleanup], builtins.TException(), name)
|
super().__init__([cleanup], builtins.TException(), name)
|
||||||
self.types = []
|
self.types = []
|
||||||
|
self.has_cleanup = True
|
||||||
|
|
||||||
def copy(self, mapper):
|
def copy(self, mapper):
|
||||||
self_copy = super().copy(mapper)
|
self_copy = super().copy(mapper)
|
||||||
|
@ -718,6 +718,8 @@ class ARTIQIRGenerator(algorithm.Visitor):
|
|||||||
|
|
||||||
cleanup = self.add_block('handler.cleanup')
|
cleanup = self.add_block('handler.cleanup')
|
||||||
landingpad = dispatcher.append(ir.LandingPad(cleanup))
|
landingpad = dispatcher.append(ir.LandingPad(cleanup))
|
||||||
|
if not any(node.finalbody):
|
||||||
|
landingpad.has_cleanup = False
|
||||||
|
|
||||||
handlers = []
|
handlers = []
|
||||||
for handler_node in node.handlers:
|
for handler_node in node.handlers:
|
||||||
|
@ -1722,7 +1722,8 @@ class LLVMIRGenerator:
|
|||||||
def process_LandingPad(self, insn):
|
def process_LandingPad(self, insn):
|
||||||
# Layout on return from landing pad: {%_Unwind_Exception*, %Exception*}
|
# Layout on return from landing pad: {%_Unwind_Exception*, %Exception*}
|
||||||
lllandingpadty = ll.LiteralStructType([llptr, llptr])
|
lllandingpadty = ll.LiteralStructType([llptr, llptr])
|
||||||
lllandingpad = self.llbuilder.landingpad(lllandingpadty, cleanup=True)
|
lllandingpad = self.llbuilder.landingpad(lllandingpadty,
|
||||||
|
cleanup=insn.has_cleanup)
|
||||||
llrawexn = self.llbuilder.extract_value(lllandingpad, 1)
|
llrawexn = self.llbuilder.extract_value(lllandingpad, 1)
|
||||||
llexn = self.llbuilder.bitcast(llrawexn, self.llty_of_type(insn.type))
|
llexn = self.llbuilder.bitcast(llrawexn, self.llty_of_type(insn.type))
|
||||||
llexnnameptr = self.llbuilder.gep(llexn, [self.llindex(0), self.llindex(0)],
|
llexnnameptr = self.llbuilder.gep(llexn, [self.llindex(0), self.llindex(0)],
|
||||||
@ -1731,23 +1732,34 @@ class LLVMIRGenerator:
|
|||||||
|
|
||||||
for target, typ in insn.clauses():
|
for target, typ in insn.clauses():
|
||||||
if typ is None:
|
if typ is None:
|
||||||
exnname = "" # see the comment in ksupport/eh.rs
|
# we use a null pointer here, similar to how cpp does it
|
||||||
|
# https://llvm.org/docs/ExceptionHandling.html#try-catch
|
||||||
|
# > If @ExcType is null, any exception matches, so the
|
||||||
|
# landingpad should always be entered. This is used for C++
|
||||||
|
# catch-all blocks (“catch (...)”).
|
||||||
|
lllandingpad.add_clause(
|
||||||
|
ll.CatchClause(
|
||||||
|
ll.Constant(lli32, 0).inttoptr(llptr)
|
||||||
|
)
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
exnname = "{}:{}".format(typ.id, typ.name)
|
exnname = "{}:{}".format(typ.id, typ.name)
|
||||||
|
|
||||||
llclauseexnname = self.llconst_of_const(
|
llclauseexnname = self.llconst_of_const(
|
||||||
ir.Constant(exnname, builtins.TStr()))
|
ir.Constant(exnname, builtins.TStr()))
|
||||||
llclauseexnnameptr = self.llmodule.globals.get("exn.{}".format(exnname))
|
llclauseexnnameptr = self.llmodule.globals.get("exn.{}".format(exnname))
|
||||||
if llclauseexnnameptr is None:
|
if llclauseexnnameptr is None:
|
||||||
llclauseexnnameptr = ll.GlobalVariable(self.llmodule, llclauseexnname.type,
|
llclauseexnnameptr = ll.GlobalVariable(self.llmodule, llclauseexnname.type,
|
||||||
name="exn.{}".format(exnname))
|
name="exn.{}".format(exnname))
|
||||||
llclauseexnnameptr.global_constant = True
|
llclauseexnnameptr.global_constant = True
|
||||||
llclauseexnnameptr.initializer = llclauseexnname
|
llclauseexnnameptr.initializer = llclauseexnname
|
||||||
llclauseexnnameptr.linkage = "private"
|
llclauseexnnameptr.linkage = "private"
|
||||||
llclauseexnnameptr.unnamed_addr = True
|
llclauseexnnameptr.unnamed_addr = True
|
||||||
lllandingpad.add_clause(ll.CatchClause(llclauseexnnameptr))
|
lllandingpad.add_clause(ll.CatchClause(llclauseexnnameptr))
|
||||||
|
|
||||||
if typ is None:
|
if typ is None:
|
||||||
|
# typ is None means that we match all exceptions, so no need to
|
||||||
|
# compare
|
||||||
self.llbuilder.branch(self.map(target))
|
self.llbuilder.branch(self.map(target))
|
||||||
else:
|
else:
|
||||||
llexnlen = self.llbuilder.extract_value(llexnname, 1)
|
llexnlen = self.llbuilder.extract_value(llexnname, 1)
|
||||||
@ -1764,6 +1776,9 @@ class LLVMIRGenerator:
|
|||||||
self.llbuilder.branch(self.map(target))
|
self.llbuilder.branch(self.map(target))
|
||||||
|
|
||||||
if self.llbuilder.basic_block.terminator is None:
|
if self.llbuilder.basic_block.terminator is None:
|
||||||
self.llbuilder.branch(self.map(insn.cleanup()))
|
if insn.has_cleanup:
|
||||||
|
self.llbuilder.branch(self.map(insn.cleanup()))
|
||||||
|
else:
|
||||||
|
self.llbuilder.resume(lllandingpad)
|
||||||
|
|
||||||
return llexn
|
return llexn
|
||||||
|
Loading…
Reference in New Issue
Block a user