forked from M-Labs/artiq
compiler: Fix crash in escape analysis for assigning string literals
This commit is contained in:
parent
56e14bfac7
commit
ff1eb4858a
|
@ -51,10 +51,6 @@ class Region:
|
||||||
(other.range.begin_pos <= self.range.begin_pos <= other.range.end_pos and \
|
(other.range.begin_pos <= self.range.begin_pos <= other.range.end_pos and \
|
||||||
self.range.end_pos > other.range.end_pos)
|
self.range.end_pos > other.range.end_pos)
|
||||||
|
|
||||||
def contract(self, other):
|
|
||||||
if not self.range:
|
|
||||||
self.range = other.range
|
|
||||||
|
|
||||||
def outlives(lhs, rhs):
|
def outlives(lhs, rhs):
|
||||||
if not isinstance(lhs, Region): # lhs lives nonlexically
|
if not isinstance(lhs, Region): # lhs lives nonlexically
|
||||||
return True
|
return True
|
||||||
|
@ -69,8 +65,11 @@ class Region:
|
||||||
|
|
||||||
class RegionOf(algorithm.Visitor):
|
class RegionOf(algorithm.Visitor):
|
||||||
"""
|
"""
|
||||||
Visit an expression and return the list of regions that must
|
Visit an expression and return the region that must be alive for the
|
||||||
be alive for the expression to execute.
|
expression to execute.
|
||||||
|
|
||||||
|
For expressions involving multiple regions, the shortest-lived one is
|
||||||
|
returned.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, env_stack, youngest_region):
|
def __init__(self, env_stack, youngest_region):
|
||||||
|
@ -301,17 +300,20 @@ class EscapeValidator(algorithm.Visitor):
|
||||||
def visit_assignment(self, target, value):
|
def visit_assignment(self, target, value):
|
||||||
value_region = self._region_of(value)
|
value_region = self._region_of(value)
|
||||||
|
|
||||||
# If this is a variable, we might need to contract the live range.
|
|
||||||
if isinstance(value_region, Region):
|
|
||||||
for name in self._names_of(target):
|
|
||||||
region = self._region_of(name)
|
|
||||||
if isinstance(region, Region):
|
|
||||||
region.contract(value_region)
|
|
||||||
|
|
||||||
# If we assign to an attribute of a quoted value, there will be no names
|
# If we assign to an attribute of a quoted value, there will be no names
|
||||||
# in the assignment lhs.
|
# in the assignment lhs.
|
||||||
target_names = self._names_of(target) or []
|
target_names = self._names_of(target) or []
|
||||||
|
|
||||||
|
# Adopt the value region for any variables declared on the lhs.
|
||||||
|
for name in target_names:
|
||||||
|
region = self._region_of(name)
|
||||||
|
if isinstance(region, Region) and not region.present():
|
||||||
|
# Find the name's environment to overwrite the region.
|
||||||
|
for env in self.env_stack[::-1]:
|
||||||
|
if name.id in env:
|
||||||
|
env[name.id] = value_region
|
||||||
|
break
|
||||||
|
|
||||||
# The assigned value should outlive the assignee
|
# The assigned value should outlive the assignee
|
||||||
target_regions = [self._region_of(name) for name in target_names]
|
target_regions = [self._region_of(name) for name in target_names]
|
||||||
for target_region in target_regions:
|
for target_region in target_regions:
|
||||||
|
|
|
@ -9,3 +9,7 @@ def foo():
|
||||||
@kernel
|
@kernel
|
||||||
def entrypoint():
|
def entrypoint():
|
||||||
foo()
|
foo()
|
||||||
|
|
||||||
|
# Test reassigning strings.
|
||||||
|
a = "a"
|
||||||
|
b = a
|
||||||
|
|
Loading…
Reference in New Issue