forked from M-Labs/artiq
compiler: Fix crash with try/finally and stack-return function calls
The previous code could have never worked as-is, as the result slot went unused, and it tried to append the load instruction to the block just terminated with the invoke. GitHub: Fixes #1506, #1531.
This commit is contained in:
parent
1f40f3ce15
commit
be4669d7a5
@ -1474,19 +1474,22 @@ class LLVMIRGenerator:
|
||||
llstackptr = self.llbuilder.call(self.llbuiltin("llvm.stacksave"), [])
|
||||
|
||||
llresultslot = self.llbuilder.alloca(llfun.type.pointee.args[0].pointee)
|
||||
llcall = self.llbuilder.invoke(llfun, llargs, llnormalblock, llunwindblock,
|
||||
name=insn.name)
|
||||
llcall = self.llbuilder.invoke(llfun, [llresultslot] + llargs,
|
||||
llnormalblock, llunwindblock, name=insn.name)
|
||||
|
||||
self.llbuilder.position_at_start(llnormalblock)
|
||||
llresult = self.llbuilder.load(llresultslot)
|
||||
|
||||
self.llbuilder.call(self.llbuiltin("llvm.stackrestore"), [llstackptr])
|
||||
else:
|
||||
llcall = self.llbuilder.invoke(llfun, llargs, llnormalblock, llunwindblock,
|
||||
name=insn.name)
|
||||
llresult = llcall
|
||||
|
||||
# The !tbaa metadata is not legal to use with the invoke instruction,
|
||||
# so unlike process_Call, we do not set it here.
|
||||
|
||||
return llcall
|
||||
return llresult
|
||||
|
||||
def _quote_listish_to_llglobal(self, value, elt_type, path, kind_name):
|
||||
llelts = [self._quote(value[i], elt_type, lambda: path() + [str(i)])
|
||||
|
44
artiq/test/lit/regression/issue_1506.py
Normal file
44
artiq/test/lit/regression/issue_1506.py
Normal file
@ -0,0 +1,44 @@
|
||||
# RUN: %python -m artiq.compiler.testbench.jit %s
|
||||
|
||||
#
|
||||
# Check various sret-ized return types integrate properly with try/finally, which lowers
|
||||
# to `invoke` on the LLVM level (code adapted from GitHub #1506).
|
||||
#
|
||||
|
||||
LIST = [1, 2]
|
||||
|
||||
|
||||
def get_tuple():
|
||||
return (1, 2)
|
||||
|
||||
|
||||
def get_list():
|
||||
return LIST
|
||||
|
||||
|
||||
def get_range():
|
||||
return range(10)
|
||||
|
||||
|
||||
def main():
|
||||
try:
|
||||
a, b = get_tuple()
|
||||
assert a == 1
|
||||
assert b == 2
|
||||
finally:
|
||||
pass
|
||||
|
||||
try:
|
||||
for _ in get_list():
|
||||
pass
|
||||
finally:
|
||||
pass
|
||||
|
||||
try:
|
||||
for _ in get_range():
|
||||
pass
|
||||
finally:
|
||||
pass
|
||||
|
||||
|
||||
main()
|
Loading…
Reference in New Issue
Block a user