forked from M-Labs/artiq
1
0
Fork 0

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:
David Nadlinger 2021-03-21 01:31:26 +00:00 committed by Sebastien Bourdeauducq
parent 9e3b6faceb
commit c1733eef49
2 changed files with 50 additions and 3 deletions

View File

@ -1474,19 +1474,22 @@ class LLVMIRGenerator:
llstackptr = self.llbuilder.call(self.llbuiltin("llvm.stacksave"), []) llstackptr = self.llbuilder.call(self.llbuiltin("llvm.stacksave"), [])
llresultslot = self.llbuilder.alloca(llfun.type.pointee.args[0].pointee) llresultslot = self.llbuilder.alloca(llfun.type.pointee.args[0].pointee)
llcall = self.llbuilder.invoke(llfun, llargs, llnormalblock, llunwindblock, llcall = self.llbuilder.invoke(llfun, [llresultslot] + llargs,
name=insn.name) llnormalblock, llunwindblock, name=insn.name)
self.llbuilder.position_at_start(llnormalblock)
llresult = self.llbuilder.load(llresultslot) llresult = self.llbuilder.load(llresultslot)
self.llbuilder.call(self.llbuiltin("llvm.stackrestore"), [llstackptr]) self.llbuilder.call(self.llbuiltin("llvm.stackrestore"), [llstackptr])
else: else:
llcall = self.llbuilder.invoke(llfun, llargs, llnormalblock, llunwindblock, llcall = self.llbuilder.invoke(llfun, llargs, llnormalblock, llunwindblock,
name=insn.name) name=insn.name)
llresult = llcall
# The !tbaa metadata is not legal to use with the invoke instruction, # The !tbaa metadata is not legal to use with the invoke instruction,
# so unlike process_Call, we do not set it here. # 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): def _quote_listish_to_llglobal(self, value, elt_type, path, kind_name):
llelts = [self._quote(value[i], elt_type, lambda: path() + [str(i)]) llelts = [self._quote(value[i], elt_type, lambda: path() + [str(i)])

View 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()